问题
用ffmpeg库写了一个编码器,发现编码出来MP4文件中的视频部分无法被QuickTime、VLC等播放器识别和播放,但实际上视频的码流信息是存在的。
解决
经过分析,发现有个flag没有配置给encode context——AV_CODEC_FLAG_GLOBAL_HEADER
if (output_fmt_ctx_->oformat->flags & AVFMT_GLOBALHEADER)
enc_ctxs_[idx]->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
ret = avcodec_open2(enc_ctxs_[idx], codecs_[idx], NULL);
if (ret < 0) {
fprintf(stderr, "Cannot open video encoder for stream #%u\n");
}
关于AV_CODEC_FLAG_GLOBAL_HEADER
1. 将全局头部信息放在context的extradata指针中,而不是每一个关键帧中。通过AVCodecContext在解码过程中,从extradata中读取SPS/PPS,然后将信息填充到每一帧之前正确解码;
2. 如果AVCodecContext中设置了AV_CODEC_FLAG_GLOBAL_HEADER标志,对于生成的视频文件(如mp4),在windows操作系统下,并以图标的方式查看该视频文件时,视频文件的图标将是视频文件的第一帧,从而起到预览的作用该变量主要出现在该函数的以下两个地方
if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)
x4->params.b_repeat_headers = 0;
注意
AV_CODEC_FLAG_GLOBAL_HEADER的配置会影响到params.b_repeat_headers,而b_repeat_headers的意思是将SPS/PPS添加到每一个关键帧之前,0代表不添加。
如果设置了videosteam 的codec中设置了AV_CODEC_FLAG_GLOBAL_HEADER就会导致x264_param_t参数中的b_repeat_header赋值为0,这样每个关键帧前面就不会添加SPS/PPS,如果在探测码流的时候,无法获取正确的SPS/PPS,就会导致解码失败。
所以,究竟要不要配置AV_CODEC_FLAG_GLOBAL_HEADER需要根据用户的需求来决定。
参考: