void adts_header(char *aac_header, int profile, int sample_rate, int channels, int frame_len) { int sampling_frequency_index = 4; //44100
//sync wordaac_header[0] = 0xff; //syncword:0xfff 高8bitsaac_header[1] = 0xf0; //syncword:0xfff 低4bits//IDaac_header[1] |= (0 << 3); //ID : 0 for MPEG-4 ; 1 for MPEG-2//layeraac_header[1] |= (0 << 1); //Layer:0 always:00//protection absentaac_header[1] |= 1; //protection absent:1 前两个字节的最低位为 1// also : aac_header[0] = 0xff; aac_header[1] = 0xf1;//profileaac_header[2] = (profile) << 6; //profile:profile 2bits//sampling_frequency_indexaac_header[2] |= (sampling_frequency_index & 0x0f) << 2; //sampling_frequency_index 4bits 只有4bit要 &0x0f,清空高4位//private_bitaac_header[2] |= (0 << 1); //private_bit: 0 1bits//channelsaac_header[2] |= (channels & 0x04) >> 2; //channel 高1bit: &0000 0100取channels的最高位aac_header[3] |= (channels & 0x03) << 6; //&0000 0011取channels的低2位aac_header[3] |= (0 << 5); //original:0 1bitaac_header[3] |= (0 << 4); //home:0 1bitaac_header[3] |= (0 << 3); //copyright id bit:0 1bitaac_header[3] |= (0 << 2); //copyright id start:0 1bit//frame len 一个ADTS帧的长度包括ADTS头和AAC原始流int adtsLen = frame_len + 7;aac_header[3] |= ((adtsLen & 0x1800) >> 11); //frame length:value 高2bitsaac_header[4] = (uint8_t)((adtsLen & 0x7f8) >> 3); //frame length:value 中间8bitsaac_header[5] = (uint8_t)((adtsLen & 0x7) << 5); //frame length:value 低3bits//buffer fullness 0x1FF 说明是码率可变的码流aac_header[5] |= 0x1f; //buffer fullness:0x1ff 高5bitsaac_header[6] = 0xfc; //111111 00 //buffer fullness:0x1ff 低6bits//buffer fullness = 1FF, number_of_raw_data_blocks_in_frame = 0, 表示说ADTS帧中有一个AAC数据块return;
}
int main(int argc, char argv[]) { char src = NULL; char dst = NULL; int ret = -1; int audio_index = -1; int len = 0; AVPacket pkt; AVFormatContext fmt_ctx = NULL;
av_log_set_level(AV_LOG_INFO);av_register_all();//1、read two params from consoleif (argc < 3) {av_log(NULL, AV_LOG_ERROR, "the count of params should be more than three!\n");return -1;}src = argv[1];dst = argv[2];if (src == NULL || dst == NULL) {av_log(NULL, AV_LOG_ERROR, "src or dst is null!\n");return -1;}ret = avformat_open_input(&fmt_ctx, src, NULL, NULL);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "Can't open file: %s\n", av_err2str(ret));return -1;}av_dump_format(fmt_ctx, 0, "./test.mp4", 0);FILE *dst_fd = fopen(dst, "wb");if (!dst_fd) {av_log(NULL, AV_LOG_ERROR, "Can't open out file !\n");avformat_close_input(&fmt_ctx);return -1;}//2、get frameret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0); //第2个参数是获取流的类型;第3个参数是流的索引号,不知道直接写-1;第4个参数是相关的流的索引号,比如音频对应的视频流的索引号,不知道直接写-1;第5个参数是对应的编解码器,不知道直接写NULLif (ret < 0) {av_log(NULL, AV_LOG_ERROR, "Can't find the best stream!\n");avformat_close_input(&fmt_ctx);fclose(dst_fd);return -1;}audio_index = ret;av_init_packet(&pkt);while (av_read_frame(fmt_ctx, &pkt) >= 0) {if (pkt.stream_index == audio_index) {//3、write audio data to aac filechar adts_header_buf[7] = {0};adts_header(adts_header_buf, 2, 44100, 2, pkt.size);fwrite(adts_header_buf, 1, 7, dst_fd);len = fwrite(pkt.data, 1, pkt.size, dst_fd);if (len != pkt.size) {av_log(NULL, AV_LOG_WARNING, "warning, length of data is not equal size of pkt!\n");}}av_packet_unref(&pkt);}av_packet_unref(&pkt);if (fmt_ctx) {avformat_close_input(&fmt_ctx);}if (dst_fd) {fclose(dst_fd);}return 0;
}
编译: gcc -lavutil -lavformat -lavcodec ``` 注:mp4里的aac数据没有adts,从MP4里抽取的aac数据需要自己添加adts头。
