解密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,在我的项目里面是自己写的扩展数据解析。
typedef?struct { ??????int?write_adts; ??????int?objecttype; ??????int?sample_rate_index; ??????int?channel_conf; }ADTSContext;
??????? int?aac_decode_extradata(ADTSContext?*adts,?unsigned?char?*pbuf,?int?bufsize)??
int?aac_decode_extradata(ADTSContext?*adts,?unsigned?char?*pbuf,?int?bufsize) { ??????int?aot,?samfreindex; ??????int?i,?channelconfig; ??????unsigned?char?*p?=?pbuf; ? ??????if?(!adts?||?!pbuf?||?bufsize<2) ??????{ ????????????return?-1; ??????} ??????aot?=?(p[0]>>3)&0x1f; ??????if?(aot?==?31) ??????{ ????????????aotext?=?(p[0]<<3?|?(p[1]>>5))?&?0x3f; ????????????aot?=?32?+?aotext; ????????????samfreindex?=?(p[1]>>1)?&?0x0f; ??????????? ????????????if?(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; ????????????if?(samfreindex?==?0x0f) ????????????{ ??????????????????channelconfig?=?(p[4]>>3)?&?0x0f; ????????????} ????????????else ????????????{ ??????????????????channelconfig?=?(p[1]>>3)?&?0x0f; ????????????} ??????} ? #ifdef?AOT_PROFILE_CTRL ??????if?(aot?<?2)?aot?=?2; #endif ??????adts->objecttype?=?aot-1; ??????adts->sample_rate_index?=?samfreindex; ??????adts->channel_conf?=?channelconfig; ??????adts->write_adts?=?1; ? ??????return?0; } ?????????? 上面的pbuf就是extradata。 ??? 接下来,再用ADTSContext数据编码为ADTS头信息插入每一个AAC帧前面: ?????? ?int?aac_set_adts_head(ADTSContext?*acfg,0);">char?*buf,0);">int?size)??
int?aac_set_adts_head(ADTSContext?*acfg,?unsigned?char?*buf,?int?size) {??????? ??????unsigned?char?byte; ? ??????if?(size?<?ADTS_HEADER_SIZE) ??????{ ????????????return?-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; ? ??????return?0; } ? 这个头部是固定的7字节长度,所以可提前空出这7个字节供ADTS占用。 ? 通过以上对H264和AAC的扩展数据处理,播放各种“黄金搭档”的多媒体文件、流媒体、视频点播等都应该没有问题了。 ? ? 想第一时间获得更多原创文章,请关注个人微信公众平台:程序员互动联盟(coder_online),扫一扫下方二维码或者搜索微信号coder_online即可关注,里面有大量Android,Chromium,Linux等相关文章等着您,我们还可以在线交流。
??????? 如需转载本文,请注明出处:谢谢合作! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |