• 一、AAC文件头信息
    • 1.1 adts_fixed_header
    • 1.2 adts_variable_header
  • 二、代码实现结合 FFmpeg 保存AAC 文件
    • 2.1 FFmpeg读取 AAC数据包
    • 2.2 保存AAC文件头信息
    • 2.3 实现
    • 2.4 代码地址和测试

  AAC 有两种数据交换格式分别为:ADTS 和 ADIF。 ADIF 因为整个流中只包含一个文件头,不能在任意时码处读取音频压缩包来解析,而ADTS在每一帧的音频压缩数据包中都有一个文件头信息,记录了音频的采样率、通道数等参数,因此ADTS的用途要比 ADIF 广泛。本文先介绍ADTS的文件头参数,而后用 ffmpeg 读取音频包保存成 AAC文件。

一、AAC文件头信息

ADTS的头信息分为:固定头信息(adts_fixed_header)和可变头信息(adts_variable_header)两部分。

1.1 adts_fixed_header

syncword :同步头代表着1个ADTS帧的开始,所有bit置1,即 0xFFF
ID:MPEG标识符,0标识MPEG-4,1标识MPEG-2
Layer: 直接置00
protection_absent:表示是否误码校验。1 no CRC , 0 has CRC
profile:AAC 编码级别, 0: Main Profile, 1:LC(最常用), 2: SSR, 3: reserved.
sampling_frequency_index:采样率标识
Private bit:直接置0,解码时忽略这个参数
channel_configuration: 声道数标识
original_copy: 直接置0,解码时忽略这个参数
home:直接置0,解码时忽略这个参数
采样率和通道数标识表:

1.2 adts_variable_header

copyright_identification_bit: 直接置0,解码时忽略这个参数
copyright_identification_start: 直接置0,解码时忽略这个参数
aac_frame_lenght: 当前音频帧的字节数,编码元数据字节数 + 文件头字节数(0 == protection_absent ? 7: 9)
adts_buffer_fullness: 当设置为0x7FF时表示时可变码率
number_of_raw_data_blocks_in_frames: 当前音频包里面包含的音频编码帧数, 置为 aac_nums - 1, 即只有一帧音频时置0

二、代码实现结合 FFmpeg 保存AAC 文件

2.1 FFmpeg读取 AAC数据包

  先检测素材是否含有 AAC格式的音频流,再读取数据


bool CheckAACInClip(const char* url)
{bool has_aac = false;int  rec = -1;do{rec = avformat_open_input(&g_filefmt_ctx, url, nullptr, nullptr);if (rec < 0){break;}rec = avformat_find_stream_info(g_filefmt_ctx, nullptr);if (rec < 0){break;}av_dump_format(g_filefmt_ctx, 0, url, 0);g_audio_stream_index = av_find_best_stream(g_filefmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, nullptr, 0);if (AVERROR_STREAM_NOT_FOUND == g_audio_stream_index){break;}if (AV_CODEC_ID_AAC != g_filefmt_ctx->streams[g_audio_stream_index]->codecpar->codec_id){break;}has_aac = true;} while (false);return has_aac;
}bool ReadAACPkt(AVPacket* aac_pkt)
{bool get_acc = false;while ( 0 == av_read_frame(g_filefmt_ctx, aac_pkt)){if (g_audio_stream_index == aac_pkt->stream_index){get_acc = true;break;     }av_packet_unref(aac_pkt);}return get_acc;
}

2.2 保存AAC文件头信息

void SaveCurADTSInfo(AVPacket* aac_pkt)
{//syncword 0xFFFg_adts_header[0] |= 0xff;g_adts_header[1] |= 0xf0;//ID g_adts_header[1] |= (0<<3);//layerg_adts_header[1] |= (0<<1);//potection_absentg_adts_header[1] |= 1;//profileint profile = g_filefmt_ctx->streams[g_audio_stream_index]->codecpar->profile;g_adts_header[2] = (profile << 6);//sampple rateint sample_rate = g_filefmt_ctx->streams[g_audio_stream_index]->codecpar->sample_rate;int samplerate_mark = g_samplerate_table.find(sample_rate)->second;g_adts_header[2] |= (samplerate_mark << 2);//private bitg_adts_header[2] |= (0<<1);//channelint channels = g_filefmt_ctx->streams[g_audio_stream_index]->codecpar->channels;g_adts_header[2] |= (channels & 0x04) >> 2;g_adts_header[3] =  (channels & 0x03) << 6;//original_copyg_adts_header[3] |= (0<<5);//homeg_adts_header[3] |= (0<<4);//copyright_identification_bitg_adts_header[3] |= (0<<3);//copyright_identification_startg_adts_header[3] |= (0<<2);//aac_frame_lengthint data_lenth = aac_pkt->size + static_cast<int>( g_adts_header.size() );//int data_lenth = aac_pkt->size + 7;g_adts_header[3] |= ( (data_lenth & 0x1800) >> 11 );g_adts_header[4] =  ( (data_lenth & 0x7F8) >> 3 );g_adts_header[5] =  ( (data_lenth & 0x7) << 5 );//adts_buffer_fullnessg_adts_header[5] |= (0x7C >> 6);g_adts_header[6] |=  (0x3F << 2);//number_of_raw_data_blocks_in_frameg_adts_header[6] |= (0x00);
}

2.3 实现

static unordered_map<int, int> g_samplerate_table = {{96000, 0},{88200, 1},{64000, 2},{48000, 3},{44100, 4},{32000, 5},{24000, 6},{22050, 7},{16000, 8},{12000, 9},{11025, 10},{8000,  11},{7350,  12}
};static AVFormatContext* g_filefmt_ctx = nullptr;
static int g_audio_stream_index = -1;
static vector<char> g_adts_header(7);int main(int argc, char* argv[])
{char* src_file = argv[1];char* dst_aac_file = argv[2];int  rec = -1;ofstream out_aac_file;bool prepare = false; do {if (!CheckAACInClip(src_file)){cout << "there is no aac stream in clip" << endl;break;}out_aac_file.open(dst_aac_file, ios_base::binary | ios_base::out | ios_base::app);if (!out_aac_file.good()){break;}prepare = true;} while (false);AVPacket* aac_pkt =av_packet_alloc();av_packet_unref(aac_pkt);while (prepare && ReadAACPkt(aac_pkt)){SaveCurADTSInfo(aac_pkt);out_aac_file.write(&g_adts_header.front(), g_adts_header.size() );out_aac_file.write(reinterpret_cast<char*>(aac_pkt->data), aac_pkt->size);av_packet_unref(aac_pkt);}out_aac_file.close();av_packet_free(&aac_pkt);avformat_close_input(&g_filefmt_ctx);return 0;
}

2.4 代码地址和测试

 完整代码地址:https://github.com/pengguoqing/samples_code/tree/master/AV/ADTS
 对于生成完的素材直接用 ffplay播放测试效果

  .\ffplay.exe  "test_out.aac"

AAC音频格式解析(ADTS)相关推荐

  1. 【Android RTMP】音频数据采集编码 ( AAC 音频格式解析 | FLV 音频数据标签解析 | AAC 音频数据标签头 | 音频解码配置信息 )

    文章目录 安卓直播推流专栏博客总结 一. AAC 音频格式解析 二. FLV 音频数据标签解析 1. 分析 FLV 格式中的 AAC 音频格式数据 2. AAC 音频特殊配置 3. AAC 音频数据标 ...

  2. AAC音频格式详解和实战解析

    AAC音频格式详解和实战解析 一.基本概念 AAC:即MPEG-2 Advanced Audio Coding,分为流格式和文件格式.文件格式主要用于文件存储和文件播放,流格式主要用于流媒体在线播放. ...

  3. AAC音频格式分析与解码

    原文地址为: AAC音频格式分析与解码 一直在做一个语音项目,到了测试阶段,近来不是很忙,想把之前做的内容整理一下. 关于AAC音频格式基本情况,可参考维基百科http://en.wikipedia. ...

  4. aac音频格式怎么转化为mp3

    aac音频格式怎么转化为mp3?aac格式是我们手机录音保存后的音频格式,在电脑端的平台可能不是很好兼容.当我们需要进一步处理aac音频格式文件时,都会将其转化为mp3 来进行. aac音频格式怎么转 ...

  5. 多媒体音频格式解析WMA WAV OGG AAC APE FLAC

    无论是MP3还是MP4,甚至手机和多媒体DC,产品所支持的各种格式往往让人眼花缭乱.特别是对于刚上手的新手玩家来说,各种格式都有哪些特性,在实际 使用当中有多少格式实用或者必须,其实有很多方面需要我们 ...

  6. MP3、AAC、WMA、Ogg、MPC、WAV、FLAC、APE、WV、CD、MIDI、RealVideo等音频格式解析及对比

    音频格式详解 无论是随身听还是手机或者是多媒体DC,产品支持的音频格式多样,然而它们都有各自的特性.我们在应用中选择的时候必须考虑到各种格式的适用场合,这要求我们对很多方面有个系统的了解. 有损压缩格 ...

  7. MIDI音频格式解析

    由于网上关于MIDI音频格式的实例解析较少, 而本人这段时间刚好有做相关的应用, 所以,特别分享MIDI的解析实例, 希望对大家有所帮助. 0x4D , 0x54 , 0x68 , 0x64 , // ...

  8. mp3与aac音频格式的比较

    1.        常见的使用比较好的音频格式:mp3 aac 2.        利用ffmpeg转换的命令: D:\srcVideo\testAudio>ffmpeg -i song.mp3 ...

  9. Wave音频格式解析

    PCM脉码调制数字音频格式是70年代末发展起来的,记录媒体之一的CD,80年代初由飞利浦和索尼公司共同推出.PCM的音频格式也被DVD-A所采用,它支持立体声和5.1环绕声,1999年由DVD讨论会发 ...

最新文章

  1. machine learning(15) --Regularization:Regularized logistic regression
  2. ruby elixir_如何使用Elixir和Phoenix快速入门构建CRUD REST API
  3. 60-179-024-使用-TypeInfo-Flink类型系统TypeIinformation
  4. 庆贺使用VS2017编译OpenJDK12成功!
  5. SQL5.5安装教程
  6. 如何开始使用 Java 机器学习
  7. Can‘t update dev_zgd has no tracked branch
  8. 利用pm2 启动node项目
  9. 百度收录提交软件-百度批量收录提交入口工具免费
  10. 去掉电脑桌面图标中的箭头图标
  11. golang:%v,%+v,%#v区别
  12. 大端模式和小端模式的判别!
  13. C语言数组知识点总结
  14. Qt5.10.1下载安装和VS2013配置
  15. python——class.__dict__
  16. 毕业论文答辩の七个原则(博士)
  17. IP组播协议——IGMP协议之IGMPv1
  18. 画图工具,告别visio
  19. seo实战密码好不好
  20. 毕业生登记表中专计算机应用技术学院,中等专业学校毕业生登记表范文

热门文章

  1. 从web端循环录入数据库的方法
  2. 小知识!谷歌自动翻译的坑
  3. SIGIR‘22 推荐系统论文之图网络篇
  4. a+1、a+1、*(a+1)、*(a+1)、*(*(a+1))的区别
  5. FL水果编曲20.8中文版下载 flstudio语言修改中文教程
  6. 2020高压电工考试及高压电工模拟考试
  7. 20大经典电路——桥式整流电路
  8. 台灯灯泡用白炽灯还是LED灯好?推荐视力康复师力荐的LED灯
  9. 【GIS】OpenStreetMap城市边界shp提取
  10. 多一份胜利,多一份胆量