FFmpeg 开发记录---H264编码,avi封装,暴风影音,qq影音播放有声无画

使用ffmpeg编码视频文件时,视频编码为H264,音频编码为MP3,封装格式为avi,发现输出的文件用vlcmkplayer等能正常播放,但是用暴风影音或者QQ影音等无法正常播放,有声音无画面。后来发现,在创建封装格式为avi时候,是需要指定video codecfourcc的。目前代码中H264编码时指定了codec_tagH264,但是为什么要指定H264呢?这个codec_tag到底有什么用呢?

--->codec_tag的用处:

跟到头文件avcodec.h中,看此变量解释:

FFmpeg 开发记录---H264编码,avi封装,暴风影音,qq影音播放有声无画_第1张图片


这里有个词很关键:work around,看来是用来绕过一些编码器的bug

编码时由使用者设置,如果没有设置就用默认的,我们之前没有设置或者设置的有问题,所以导致没有播出画面,但是好像还没有找到关键性原因,这个codec_tag到底是做什么的?影响了什么?

看源码,在avienc.cavi_write_packet函数中如果设置了H264的话,会调用ff_check_h264_startcode

FFmpeg 开发记录---H264编码,avi封装,暴风影音,qq影音播放有声无画_第2张图片

但是ff_check_h264_startcode内部并未做其他操作

FFmpeg 开发记录---H264编码,avi封装,暴风影音,qq影音播放有声无画_第3张图片


参考:https://en.wikipedia.org/wiki/FourCC

 

但是设置后确实是可以播放了,怀疑跟videostream里的AVCodec参数中的flags有关系。代码中搜索AV_CODEC_FLAG_GLOBAL_HEADER发现

 FFmpeg 开发记录---H264编码,avi封装,暴风影音,qq影音播放有声无画_第4张图片

因为avi 文件 flag0,所以没有去置pCodecCtxEnc(也就是videostream中的codec)的flags。查看这2flag分别为

----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编码中

 FFmpeg 开发记录---H264编码,avi封装,暴风影音,qq影音播放有声无画_第5张图片

如果flag中有AV_CODEC_FLAG_GLOBAL_HEADER标识,则b_repeat_headers0

 FFmpeg 开发记录---H264编码,avi封装,暴风影音,qq影音播放有声无画_第6张图片

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放到关键帧前面

你可能感兴趣的:(C++,FFMPEG)