ffmpeg SDK编码MP4 AAC的一处小坑

在最新版的ffmpeg SDK中,如果我们按照一般的编码音频的步骤编码AAC并封入MP4,我们往往会写入一个很奇怪的音频Stream。它的MediaInfo会长这样:
image
如图所示,解码器不能理解这个流,会认为它就是一个ER Parametric而不能理解它是AAC。ffprobe查看stream其配置也会很奇怪:

[STREAM]
index=1
codec_name=aac
codec_long_name=AAC (Advanced Audio Coding)
profile=-1
codec_type=audio
codec_tag_string=mp4a
codec_tag=0x6134706d
sample_fmt=fltp
sample_rate=48000
channels=2
channel_layout=stereo
bits_per_sample=0
initial_padding=0
id=0x2
r_frame_rate=0/0
avg_frame_rate=0/0
time_base=1/48000
start_pts=0
start_time=0.000000
duration_ts=728064
duration=15.168000
bit_rate=126300
max_bit_rate=N/A
bits_per_raw_sample=N/A
nb_frames=712
nb_read_frames=N/A
nb_read_packets=N/A
DISPOSITION:default=1
DISPOSITION:dub=0
DISPOSITION:original=0
DISPOSITION:comment=0
DISPOSITION:lyrics=0
DISPOSITION:karaoke=0
DISPOSITION:forced=0
DISPOSITION:hearing_impaired=0
DISPOSITION:visual_impaired=0
DISPOSITION:clean_effects=0
DISPOSITION:attached_pic=0
DISPOSITION:timed_thumbnails=0
DISPOSITION:captions=0
DISPOSITION:descriptions=0
DISPOSITION:metadata=0
DISPOSITION:dependent=0
DISPOSITION:still_image=0
TAG:language=und
TAG:handler_name=SoundHandler
TAG:vendor_id=[0][0][0][0]
[/STREAM]

ffprobe理解这个AAC流的profile是-1。很明显存在问题。

解决的方法是,要在使用avcodec_open2打开音频编码器之后,再执行avcodec_parameters_from_context拷贝参数。如果在打开编码器之前拷贝参数或者没有拷贝参数,打开编码器的过程所修改的一些参数就不会更新到流信息中,AAC信息也就无法被解析。

也就是说,我们需要:

// 先执行
avError = avcodec_open2(oAudioEncoderCxt, oAudioEncoder, 0);
// 再执行
avError = avcodec_parameters_from_context(oAudioStream->codecpar, oAudioEncoderCxt);

这样,编码器的一些参数就会在打开编码器后被更新到流信息里,即可正确编码可以被识别的AAC。

同时,如果有必要,建议为编码器上下文添加AV_CODEC_FLAG_GLOBAL_HEADER这个flag。也就是在初始化编码器上下文时配置:

oAudioEncoderCxt -> flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
posted @ 2024-03-20 20:23  IZWB-003  阅读(22)  评论(0编辑  收藏  举报