解密H264、AAC硬件解码的关键扩展数据处理
? ? 通过上一篇文章,我们用ffmpeg分离出一个多媒体容器中的音视频数据,但是很可能这些数据是不能被正确解码的。为什么呢?因为在解码这些数据之前,需要对解码器做一些配置,典型的就是目前流行的高清编码“黄金搭档”组合H264 + AAC的搭配。本文将讲述H264和AAC的关键解码配置参数的解析,如果没有这些配置信息,数据帧往往不完整,导致了解码器不能解码。
????????? AVCodecContext定义如下:
????如果视频流是H264,这个extradate里面就包含了H264的配置信息,这个扩展数据有如下定义:
??? 详细解释可以参考“ISO-14496-15 AVC file format”文档。里面最重要的就是NAL长度和SPS,PPS数据和对应的长度信息。对该数据的解析在ffmpeg里面有现成的函数:ff_h264_decode_extradata,在我的项目里面是自己写的扩展数据解析。
|
aac_decode_extradata(ADTSContext?*adts,?unsigned?
char ?
*pbuf,?
bufsize)
aot,?aotext,?samfreindex;
i,?channelconfig;
??????
unsigned?
*p?=?pbuf;
? ?
??????
if ?
(!adts?||?!pbuf?||?bufsize<2)
{
????????????
return ?
-1;
}
aot?=?(p[0]>>3)&0x1f;
(aot?==?31)
{
????????????
aotext?=?(p[0]<<3?|?(p[1]>>5))?&?0x3f;
aot?=?32?+?aotext;
samfreindex?=?(p[1]>>1)?&?0x0f;
??????????? ?
(samfreindex?==?0x0f)
{
??????????????????
channelconfig?=?((p[4]<<3)?|?(p[5]>>5))?&?0x0f;
}
else
{
channelconfig?=?((p[1]<<3)|(p[2]>>5))?&?0x0f;
}
}
else
{
samfreindex?=?((p[0]<<1)|p[1]>>7)?&?0x0f;
(samfreindex?==?0x0f)
{
channelconfig?=?(p[4]>>3)?&?0x0f;
}
else
{
channelconfig?=?(p[1]>>3)?&?0x0f;
}
}
? ?
#ifdef?AOT_PROFILE_CTRL
(aot?<?2)?aot?=?2;
#endif
adts->objecttype?=?aot-1;
adts->sample_rate_index?=?samfreindex;
adts->channel_conf?=?channelconfig;
adts->write_adts?=?1;
? ?
0;
}
|
???????????上面的pbuf就是extradata。
????接下来,再用ADTSContext数据编码为ADTS头信息插入每一个AAC帧前面:
-
aac_set_adts_head(ADTSContext?*acfg,monospace!important; border:0px!important; bottom:auto!important; float:none!important; height:auto!important; left:auto!important; line-height:1.1em!important; outline:0px!important; overflow:visible!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-size:1em!important; min-height:inherit!important; background:none!important">*buf,monospace!important; border:0px!important; bottom:auto!important; float:none!important; height:auto!important; left:auto!important; line-height:1.1em!important; outline:0px!important; overflow:visible!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-size:1em!important; min-height:inherit!important; background:none!important">size) {???????
byte;
?
?(size?<?ADTS_HEADER_SIZE)
{
-1;
}
?????
?buf[0]?=?0xff;
buf[1]?=?0xf1;
byte?=?0;
byte?|=?(acfg->objecttype?&?0x03)?<<?6;
byte?|=?(acfg->sample_rate_index?&?0x0f)?<<?2;
byte?|=?(acfg->channel_conf?&?0x07)?>>?2;
buf[2]?=?byte;
byte?=?0;
byte?|=?(acfg->channel_conf?&?0x07)?<<?6;
byte?|=?(ADTS_HEADER_SIZE?+?size)?>>?11;
buf[3]?=?byte;
byte?=?0;
byte?|=?(ADTS_HEADER_SIZE?+?size)?>>?3;
buf[4]?=?byte;
byte?=?0;
byte?|=?((ADTS_HEADER_SIZE?+?size)?&?0x7)?<<?5;
byte?|=?(0x7ff?>>?6)?&?0x1f;
buf[5]?=?byte;
byte?=?0;
byte?|=?(0x7ff?&?0x3f)?<<?2;
buf[6]?=?byte;
?
?0;
? 这个头部是固定的7字节长度,所以可提前空出这7个字节供ADTS占用。
? 通过以上对H264和AAC的扩展数据处理,播放各种“黄金搭档”的多媒体文件、流媒体、视频点播等都应该没有问题了。
?
? 想第一时间获得更多原创文章,请关注个人微信公众平台:程序员互动联盟(coder_online),扫一扫下方二维码或者搜索微信号coder_online即可关注,里面有大量Android,Chromium,Linux等相关文章等着您,我们还可以在线交流。
??????? 如需转载本文,请注明出处:谢谢合作!
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!