<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-833878f763.css">
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-833878f763.css">
<div class="htmledit_views" id="content_views">
<h2 style="margin-left:0px;"><a name="t0"></a><a name="t0"></a> </h2>
遵循:BY-SA
作者:谭东
时间:2016年10月28日
环境:Windows 7
ADTS是Audio Data Transport Stream的简称。
是AAC音频文件常见的传输格式。
有的时候当你编码AAC裸流的时候,会遇到写出来的AAC文件并不能在PC和手机上播放,很大的可能就是AAC文件的每一帧里缺少了ADTS头信息文件的包装拼接。只需要加入头文件ADTS即可。一个AAC原始数据块长度是可变的,对原始帧加上ADTS头进行ADTS的封装,就形成了ADTS帧。
下面分析下ADTS头文件结构和信息:
AAC音频文件的每一帧由ADTS Header和AAC Audio Data组成。
大家可以用AAC Audio ES Viewer工具来查看AAC的ADTS Header。
每一帧的ADTS的头文件都包含了音频的采样率,声道,帧长度等信息,这样解码器才能解析读取。
一般情况下ADTS的头信息都是7个字节,分为2部分:
adts_fixed_header();
adts_variable_header();
先来看:adts_fixed_header();
- syncword :总是0xFFF, 代表一个ADTS帧的开始, 用于同步.
解码器可通过0xFFF确定每个ADTS的开始位置.
因为它的存在,解码可以在这个流中任何位置开始, 即可以在任意帧解码。 - ID:MPEG Version: 0 for MPEG-4,1 for MPEG-2
- Layer:always: '00'
- protection_absent:Warning, set to 1 if there is no CRC and 0 if there is CRC
- profile:表示使用哪个级别的AAC,如01 Low Complexity(LC) -- AAC LC
profile的值等于 Audio Object Type的值减1.
profile = MPEG-4 Audio Object Type - 1 - sampling_frequency_index:采样率的下标
- channel_configuration:声道数,比如2表示立体声双声道
接下来看下adts_variable_header();
- aac_frame_length:一个ADTS帧的长度包括ADTS头和AAC原始流。frame length, this value must include 7 or 9 bytes of header length:
aac_frame_length = (protection_absent == 1 ? 7 : 9) + size(AACFrame)
protection_absent=0时, header length=9bytes
protection_absent=1时, header length=7bytes - adts_buffer_fullness:0x7FF 说明是码率可变的码流。
- number_of_raw_data_blocks_in_frame:表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧。
所以说number_of_raw_data_blocks_in_frame == 0 表示说ADTS帧中有一个AAC数据块。
(一个AAC原始帧包含一段时间内1024个采样及相关数据)
两个头文件就讲到这里。
这里给出JAVA和Android里的给AAC添加ADTS头文件的部分方法代码,针对ByteBuffer。
-
/**
-
* 添加ADTS头
-
*
-
* @param packet
-
* @param packetLen
-
*/
-
private void addADTStoPacket(byte[] packet, int packetLen) {
-
int profile =
2;
// AAC LC
-
int freqIdx =
4;
// 44.1KHz
-
int chanCfg =
2;
// CPE
-
-
// fill in ADTS data
-
packet[
0] = (
byte)
0xFF;
-
packet[
1] = (
byte)
0xF9;
-
packet[
2] = (
byte) (((profile -
1) <<
6) + (freqIdx <<
2) + (chanCfg >>
2));
-
packet[
3] = (
byte) (((chanCfg &
3) <<
6) + (packetLen >>
11));
-
packet[
4] = (
byte) ((packetLen &
0x7FF) >>
3);
-
packet[
5] = (
byte) (((packetLen &
7) <<
5) +
0x1F);
-
packet[
6] = (
byte)
0xFC;
-
}
这里是调用:(可根据自己需求,这里的AudioBufFrame是我们自己项目里的类,其实就是个ByteBuffer封装的类)
-
AudioBufFrame audioBufFrame = (AudioBufFrame) o;
-
int outBufferSize = audioBufFrame.buf.limit() +
7;
-
byte[] aacBytes =
new
byte[outBufferSize];
-
try {
-
if (!write) {
-
fout =
new FileOutputStream(MyConfiguration.VIDEO_PATH +
"/audio.aac");
-
write =
true;
-
}
-
addADTStoPacket(aacBytes, outBufferSize);
-
audioBufFrame.buf.get(aacBytes,
7, audioBufFrame.buf.limit());
-
fout.write(aacBytes);
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
下面是FFMPEG参考的C的添加ADTS头文件代码,供大家参考。
-
int ff_adts_write_frame_header(ADTSContext *ctx,
-
uint8_t *buf, int size, int pce_size)
-
{
-
PutBitContext pb;
-
-
init_put_bits(&pb, buf, ADTS_HEADER_SIZE);
-
-
/* adts_fixed_header */
-
put_bits(&pb,
12,
0xfff);
/* syncword */
-
put_bits(&pb,
1,
0);
/* ID */
-
put_bits(&pb,
2,
0);
/* layer */
-
put_bits(&pb,
1,
1);
/* protection_absent */
-
put_bits(&pb,
2, ctx->objecttype);
/* profile_objecttype */
-
put_bits(&pb,
4, ctx->sample_rate_index);
-
put_bits(&pb,
1,
0);
/* private_bit */
-
put_bits(&pb,
3, ctx->channel_conf);
/* channel_configuration */
-
put_bits(&pb,
1,
0);
/* original_copy */
-
put_bits(&pb,
1,
0);
/* home */
-
-
/* adts_variable_header */
-
put_bits(&pb,
1,
0);
/* copyright_identification_bit */
-
put_bits(&pb,
1,
0);
/* copyright_identification_start */
-
put_bits(&pb,
13, ADTS_HEADER_SIZE + size + pce_size);
/* aac_frame_length */
-
put_bits(&pb,
11,
0x7ff);
/* adts_buffer_fullness */
-
put_bits(&pb,
2,
0);
/* number_of_raw_data_blocks_in_frame */
-
-
flush_put_bits(&pb);
-
-
return
0;
-
}
遵循:BY-NC-SA
<li class="tool-item tool-active is-like "><a href="javascript:;"><svg class="icon" aria-hidden="true">
<use xlink:href="#csdnc-thumbsup"></use>
</svg><span class="name">点赞</span>
<span class="count">8</span>
</a></li>
<li class="tool-item tool-active is-collection "><a href="javascript:;" data-report-click="{"mod":"popu_824"}"><svg class="icon" aria-hidden="true">
<use xlink:href="#icon-csdnc-Collection-G"></use>
</svg><span class="name">收藏</span></a></li>
<li class="tool-item tool-active is-share"><a href="javascript:;"><svg class="icon" aria-hidden="true">
<use xlink:href="#icon-csdnc-fenxiang"></use>
</svg>分享</a></li>
<!--打赏开始-->
<!--打赏结束-->
<li class="tool-item tool-more">
<a>
<svg t="1575545411852" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5717" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M179.176 499.222m-113.245 0a113.245 113.245 0 1 0 226.49 0 113.245 113.245 0 1 0-226.49 0Z" p-id="5718"></path><path d="M509.684 499.222m-113.245 0a113.245 113.245 0 1 0 226.49 0 113.245 113.245 0 1 0-226.49 0Z" p-id="5719"></path><path d="M846.175 499.222m-113.245 0a113.245 113.245 0 1 0 226.49 0 113.245 113.245 0 1 0-226.49 0Z" p-id="5720"></path></svg>
</a>
<ul class="more-box">
<li class="item"><a class="article-report">文章举报</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div class="person-messagebox">
<div class="left-message"><a href="https://blog.csdn.net/jay100500">
<img src="https://profile.csdnimg.cn/D/5/2/3_jay100500" class="avatar_pic" username="jay100500">
<img src="https://g.csdnimg.cn/static/user-reg-year/2x/9.png" class="user-years">
</a></div>
<div class="middle-message">
<div class="title"><span class="tit"><a href="https://blog.csdn.net/jay100500" data-report-click="{"mod":"popu_379"}" target="_blank">范特西_jay</a></span>
<span class="flag expert">
<a href="https://blog.csdn.net/home/help.html#classicfication" target="_blank">
<svg class="icon" aria-hidden="true">
<use xlink:href="#csdnc-blogexpert"></use>
</svg>
博客专家
</a>
</span>
</div>
<div class="text"><span>发布了111 篇原创文章</span> · <span>获赞 146</span> · <span>访问量 37万+</span></div>
</div>
<div class="right-message">
<a href="https://im.csdn.net/im/main.html?userName=jay100500" target="_blank" class="btn btn-sm btn-red-hollow bt-button personal-letter">私信
</a>
<a class="btn btn-sm bt-button personal-watch" data-report-click="{"mod":"popu_379"}">关注</a>
</div>
</div>