FFmpeg 开发记录---H264编码,avi封装,暴风影音,qq影音播放有声无画
使用ffmpeg编码视频文件时,视频编码为H264,音频编码为MP3,封装格式为avi,发现输出的文件用vlc,mkplayer等能正常播放,但是用暴风影音或者QQ影音等无法正常播放,有声音无画面。后来发现,在创建封装格式为avi时候,是需要指定video codec的fourcc的。目前代码中H264编码时指定了codec_tag为H264,但是为什么要指定H264呢?这个codec_tag到底有什么用呢?
--->找codec_tag的用处:
跟到头文件avcodec.h中,看此变量解释:
这里有个词很关键:work around,看来是用来绕过一些编码器的bug。
编码时由使用者设置,如果没有设置就用默认的,我们之前没有设置或者设置的有问题,所以导致没有播出画面,但是好像还没有找到关键性原因,这个codec_tag到底是做什么的?影响了什么?
看源码,在avienc.c中avi_write_packet函数中如果设置了H264的话,会调用ff_check_h264_startcode,
但是ff_check_h264_startcode内部并未做其他操作
参考:https://en.wikipedia.org/wiki/FourCC
但是设置后确实是可以播放了,怀疑跟videostream里的AVCodec参数中的flags有关系。代码中搜索AV_CODEC_FLAG_GLOBAL_HEADER,发现
因为avi 文件 flag是0,所以没有去置pCodecCtxEnc(也就是videostream中的codec)的flags。查看这2个flag分别为
----》avformat.h中
#define AVFMT_GLOBALHEADER 0x0040
Format wants global header.
---->avcodec.h中
#define AV_CODEC_FLAG_GLOBAL_HEADER (1 << 22)
Place global headers in extradata instead of every keyframe.
告知在extradata中以global headers取代每个关键帧。继续搜索AV_CODEC_FLAG_GLOBAL_HEADER,发现x264编码中
如果flag中有AV_CODEC_FLAG_GLOBAL_HEADER标识,则b_repeat_headers为0。
b_repeat_header : 在每个关键帧前面put SPS/PPS。
这么下来,应该就明白了,如果设置了videosteam 的codec中设置了AV_CODEC_FLAG_GLOBAL_HEADER就会导致x264_param_t参数中的b_repeat_header赋值为0,这样每个关键帧前面就不会put SPS/PPS导致解码失败。
注:使用实时视频传输时,需要实时发送sps/pps数据
param.b_repeat_headers = 1; // 重复SPS/PPS放到关键帧前面