国内知名企业网站,公司网络安全管理制度和应急工作预案,赣州市城乡建设局官方网站,端端网站开发音视频入门基础#xff1a;AAC专题系列文章#xff1a;
音视频入门基础#xff1a;AAC专题#xff08;1#xff09;——AAC官方文档下载
音视频入门基础#xff1a;AAC专题#xff08;2#xff09;——使用FFmpeg命令生成AAC裸流文件
音视频入门基础#xff1a;AAC…
音视频入门基础AAC专题系列文章
音视频入门基础AAC专题1——AAC官方文档下载
音视频入门基础AAC专题2——使用FFmpeg命令生成AAC裸流文件
音视频入门基础AAC专题3——AAC的ADTS格式简介
音视频入门基础AAC专题4——ADTS格式的AAC裸流实例分析
音视频入门基础AAC专题5——FFmpeg源码中判断某文件是否为AAC裸流文件的实现
音视频入门基础AAC专题6——FFmpeg源码中解码ADTS格式的AAC的Header的实现
音视频入门基础AAC专题7——FFmpeg源码中计算AAC裸流每个packet的size值的实现
音视频入门基础AAC专题8——FFmpeg源码中计算AAC裸流AVStream的time_base的实现
音视频入门基础AAC专题9——FFmpeg源码中计算AAC裸流每个packet的duration和duration_time的实现
音视频入门基础AAC专题10——FFmpeg源码中计算AAC裸流每个packet的pts、dts、pts_time、dts_time的实现
音视频入门基础AAC专题11——AudioSpecificConfig简介
音视频入门基础AAC专题12——FFmpeg源码中解码AudioSpecificConfig的实现 一、引言
在《音视频入门基础AAC专题11——AudioSpecificConfig简介》中对AudioSpecificConfig进行了简介本文讲述FFmpeg源码中是怎样解码AudioSpecificConfig拿到里面的信息。 二、decode_audio_specific_config_gb函数的定义
FFmpeg源码中使用decode_audio_specific_config_gb函数来读取AudioSpecificConfig的信息。该函数定义在FFmpeg源码本文演示用的FFmpeg源码版本为7.0.1的源文件libavcodec/aacdec_template.c中
/*** Decode audio specific configuration; reference: table 1.13.** param ac pointer to AACDecContext, may be null* param avctx pointer to AVCCodecContext, used for logging* param m4ac pointer to MPEG4AudioConfig, used for parsing* param gb buffer holding an audio specific config* param get_bit_alignment relative alignment for byte align operations* param sync_extension look for an appended sync extension** return Returns error status or number of consumed bits. 0 - error*/
static int decode_audio_specific_config_gb(AACDecContext *ac,AVCodecContext *avctx,MPEG4AudioConfig *m4ac,GetBitContext *gb,int get_bit_alignment,int sync_extension)
{int i, ret;GetBitContext gbc *gb;MPEG4AudioConfig m4ac_bak *m4ac;if ((i ff_mpeg4audio_get_config_gb(m4ac, gbc, sync_extension, avctx)) 0) {*m4ac m4ac_bak;return AVERROR_INVALIDDATA;}if (m4ac-sampling_index 12) {av_log(avctx, AV_LOG_ERROR,invalid sampling rate index %d\n,m4ac-sampling_index);*m4ac m4ac_bak;return AVERROR_INVALIDDATA;}if (m4ac-object_type AOT_ER_AAC_LD (m4ac-sampling_index 3 || m4ac-sampling_index 7)) {av_log(avctx, AV_LOG_ERROR,invalid low delay sampling rate index %d\n,m4ac-sampling_index);*m4ac m4ac_bak;return AVERROR_INVALIDDATA;}skip_bits_long(gb, i);switch (m4ac-object_type) {case AOT_AAC_MAIN:case AOT_AAC_LC:case AOT_AAC_SSR:case AOT_AAC_LTP:case AOT_ER_AAC_LC:case AOT_ER_AAC_LD:if ((ret decode_ga_specific_config(ac, avctx, gb, get_bit_alignment,m4ac, m4ac-chan_config)) 0)return ret;break;case AOT_ER_AAC_ELD:if ((ret decode_eld_specific_config(ac, avctx, gb,m4ac, m4ac-chan_config)) 0)return ret;break;default:avpriv_report_missing_feature(avctx,Audio object type %s%d,m4ac-sbr 1 ? SBR : ,m4ac-object_type);return AVERROR(ENOSYS);}ff_dlog(avctx,AOT %d chan config %d sampling index %d (%d) SBR %d PS %d\n,m4ac-object_type, m4ac-chan_config, m4ac-sampling_index,m4ac-sample_rate, m4ac-sbr,m4ac-ps);return get_bits_count(gb);
} 形参ac既是输入型参数也是输出型参数。指向一个AACDecContext类型变量。 形参avctx输入型参数。用来输出日志可忽略。 形参m4ac输出型参数指向一个MPEG4AudioConfig类型变量执行decode_audio_specific_config_gb函数后m4ac指向的变量会得到从AudioSpecificConfig中解码出来的属性。MPEG4AudioConfig结构体声明如下
typedef struct MPEG4AudioConfig {int object_type;int sampling_index;int sample_rate;int chan_config;int sbr; /// -1 implicit, 1 presenceint ext_object_type;int ext_sampling_index;int ext_sample_rate;int ext_chan_config;int channels;int ps; /// -1 implicit, 1 presenceint frame_length_short;
} MPEG4AudioConfig; 形参gb既是输入型参数也是输出型参数为GetBitContext类型用来对“位”进行操作具体可以参考《FFmpeg中位操作相关的源码GetBitContext结构体init_get_bits函数、get_bits1函数和get_bits函数分析》。
执行decode_audio_specific_config_gb函数前gb-buffer为指向某个缓冲区的指针。该缓冲区存放AudioSpecificConfig的二进制数据。 形参get_bit_alignment输入型参数。字节对齐操作的相对对齐。 形参sync_extension输入型参数。寻找附加的同步扩展。 三、decode_audio_specific_config_gb函数的内部实现分析
decode_audio_specific_config_gb函数中首先调用ff_mpeg4audio_get_config_gb函数 if ((i ff_mpeg4audio_get_config_gb(m4ac, gbc, sync_extension, avctx)) 0) {*m4ac m4ac_bak;return AVERROR_INVALIDDATA;} 一ff_mpeg4audio_get_config_gb函数
ff_mpeg4audio_get_config_gb函数定义在libavcodec/mpeg4audio.c中
int ff_mpeg4audio_get_config_gb(MPEG4AudioConfig *c, GetBitContext *gb,int sync_extension, void *logctx)
{int specific_config_bitindex, ret;int start_bit_index get_bits_count(gb);c-object_type get_object_type(gb);c-sample_rate get_sample_rate(gb, c-sampling_index);c-chan_config get_bits(gb, 4);if (c-chan_config FF_ARRAY_ELEMS(ff_mpeg4audio_channels))c-channels ff_mpeg4audio_channels[c-chan_config];else {av_log(logctx, AV_LOG_ERROR, Invalid chan_config %d\n, c-chan_config);return AVERROR_INVALIDDATA;}c-sbr -1;c-ps -1;if (c-object_type AOT_SBR || (c-object_type AOT_PS // check for W6132 Annex YYYY draft MP3onMP4!(show_bits(gb, 3) 0x03 !(show_bits(gb, 9) 0x3F)))) {if (c-object_type AOT_PS)c-ps 1;c-ext_object_type AOT_SBR;c-sbr 1;c-ext_sample_rate get_sample_rate(gb, c-ext_sampling_index);c-object_type get_object_type(gb);if (c-object_type AOT_ER_BSAC)c-ext_chan_config get_bits(gb, 4);} else {c-ext_object_type AOT_NULL;c-ext_sample_rate 0;}specific_config_bitindex get_bits_count(gb);if (c-object_type AOT_ALS) {skip_bits(gb, 5);if (show_bits(gb, 24) ! MKBETAG(\0,A,L,S))skip_bits(gb, 24);specific_config_bitindex get_bits_count(gb);ret parse_config_ALS(gb, c, logctx);if (ret 0)return ret;}if (c-ext_object_type ! AOT_SBR sync_extension) {while (get_bits_left(gb) 15) {if (show_bits(gb, 11) 0x2b7) { // sync extensionget_bits(gb, 11);c-ext_object_type get_object_type(gb);if (c-ext_object_type AOT_SBR (c-sbr get_bits1(gb)) 1) {c-ext_sample_rate get_sample_rate(gb, c-ext_sampling_index);if (c-ext_sample_rate c-sample_rate)c-sbr -1;}if (get_bits_left(gb) 11 get_bits(gb, 11) 0x548)c-ps get_bits1(gb);break;} elseget_bits1(gb); // skip 1 bit}}//PS requires SBRif (!c-sbr)c-ps 0;//Limit implicit PS to the HE-AACv2 Profileif ((c-ps -1 c-object_type ! AOT_AAC_LC) || c-channels ~0x01)c-ps 0;return specific_config_bitindex - start_bit_index;
} 1.获取audioObjectType属性
ff_mpeg4audio_get_config_gb函数中首先通过语句c-object_type get_object_type(gb) 获取AudioSpecificConfig的audioObjectType属性。get_object_type函数定义如下。关于get_bits函数的用法可以参考《FFmpeg中位操作相关的源码GetBitContext结构体init_get_bits函数、get_bits1函数和get_bits函数分析》
static inline int get_object_type(GetBitContext *gb)
{int object_type get_bits(gb, 5);if (object_type AOT_ESCAPE)object_type 32 get_bits(gb, 6);return object_type;
} 2.获取samplingFrequencyIndex属性
获取完audioObjectType属性后ff_mpeg4audio_get_config_gb函数中通过语句c-sample_rate get_sample_rate(gb, c-sampling_index)获取AudioSpecificConfig的samplingFrequencyIndex属性。get_sample_rate定义如下
static inline int get_sample_rate(GetBitContext *gb, int *index)
{*index get_bits(gb, 4);return *index 0x0f ? get_bits(gb, 24) :ff_mpeg4audio_sample_rates[*index];
} 全局数组ff_mpeg4audio_sample_rates定义如下
const int ff_mpeg4audio_sample_rates[16] {96000, 88200, 64000, 48000, 44100, 32000,24000, 22050, 16000, 12000, 11025, 8000, 7350
}; 3.获取channelConfiguration属性
ff_mpeg4audio_get_config_gb函数中通过语句c-chan_config get_bits(gb, 4)获取AudioSpecificConfig的channelConfiguration属性。 ——————————————————分隔符——————————————————
回到decode_audio_specific_config_gb函数所以执行下面代码块后m4ac指向的变量会得到从AudioSpecificConfig中解析出来的audioObjectType、samplingFrequencyIndex、channelConfiguration属性 if ((i ff_mpeg4audio_get_config_gb(m4ac, gbc, sync_extension, avctx)) 0) {*m4ac m4ac_bak;return AVERROR_INVALIDDATA;} 然后decode_audio_specific_config_gb函数通过下面代码块解析AudioSpecificConfig中的GASpecificConfig switch (m4ac-object_type) {case AOT_AAC_MAIN:case AOT_AAC_LC:case AOT_AAC_SSR:case AOT_AAC_LTP:case AOT_ER_AAC_LC:case AOT_ER_AAC_LD:if ((ret decode_ga_specific_config(ac, avctx, gb, get_bit_alignment,m4ac, m4ac-chan_config)) 0)return ret;break; 通过下面代码块解析AudioSpecificConfig中的ELDSpecificConfig(channelConfiguration) case AOT_ER_AAC_ELD:if ((ret decode_eld_specific_config(ac, avctx, gb,m4ac, m4ac-chan_config)) 0)return ret;break;