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