Libav转码为H264:帧被丢弃

时间:2014-06-20 18:55:20

标签: ffmpeg h.264 libavcodec libav libavformat

对不起,如果我的问题没有得到很好的表述,我现在才开始使用FFmpeg和Libav。我对媒体格式也不太了解,过去一个月我几乎了解了这个话题。我已经做了尽可能多的研究,而且已经走得很远了,但我现在才刚刚到达我几乎不确定我的问题实际上是什么的地步!这些更像是观察,但希望有些专家可以帮助我。

我尝试使用FFmpeg的库将Gif转码为MP4,但在使用H264 Codec时我遇到了一个奇怪的问题。在我的代码转换循环中,我保留了我写出的帧数(通过验证av_write_frame的返回值)。在特定的样本中,我总共计算出166帧。如果我使用FFprobe检查FFmpeg的转换文件(我希望使用我的程序模拟的功能,从Gif到MP4的转换),FFmpeg的输出文件似乎也有166帧,但是当我用FFprobe检查输出时,我似乎只有144帧。我觉得有点有趣的是,如果我只是将我的编解码器从H264改为MPEG4,我的输出似乎有166帧,匹配FFmpeg的输出和我的计数器。我得到了与不同Gif文件非常相似的结果,其中我写的帧计数器与FFmpeg的输出帧数相匹配,但我的输出似乎丢失了一些帧。

编码器设置:

ostream_codec_context->codec_id = CODEC_IN_USE;  //CODEC_ID_H264 or CODEC_ID_MPEG4
ostream_codec_context->pix_fmt = AV_PIX_FMT_YUV420P;
ostream_codec_context->codec_type = AVMEDIA_TYPE_VIDEO;
ostream_codec_context->flags = CODEC_FLAG_GLOBAL_HEADER;
ostream_codec_context->profile = FF_PROFILE_MPEG4_SIMPLE;

ostream_codec_context->gop_size = istream_codec_context->gop_size;
ostream_codec_context->time_base = istream_codec_context->time_base;

ostream_codec_context->width  = (istream_codec_context->width  / 2) * 2;
ostream_codec_context->height = (istream_codec_context->height / 2) * 2;    

转码循环:

我省略了一些错误检查代码和调试语句

avformat_write_header(oformat_context, NULL);
while (av_read_frame(iformat_context, &packet) == 0 ) 
{
   if (packet.stream_index == istream_index) 
   {   
      avcodec_decode_video2(istream_codec_context, ipicture, &full_frame, &packet);
      if (full_frame) 
      {
         sws_scale(image_conversion_context, 
                   (uint8_t const * const *) ipicture->data,
                   ipicture->linesize, 0, istream_codec_context->height,
                   opicture->data, opicture->linesize);

         opicture->pts = av_rescale_q(packet.pts, istream_codec_context->time_base,
                                      ostream->time_base);

         ret = avcodec_encode_video2(ostream_codec_context, &packet, 
                                     opicture, &got_packet);
         if (!ret)
         {
            ret = av_write_frame(oformat_context, &packet);
            if (ret < 0)
               num_frames_written++;
         }
      }
   }
   av_free_packet(&packet);
   av_init_packet(&packet);
}

我的输出比特率也有问题。我可以尝试使用其余的编码器设置来设置它,但FFprobe显示的比特率与我给编解码器上下文相同。我尝试将比特率设置为常数,只是为了看看它如何影响我的输出,虽然我的输出的比特率与我给它的相同,我发现我的输入肯定似乎影响输出的实际比特率。我发现了一篇似乎正在处理我的问题的帖子,但是那里列出的解决方案似乎没有解决我的问题。

http://ffmpeg.org/pipermail/libav-user/2012-July/002492.html

值得一提的另一件事是,我的各个时间基础似乎与FFmpeg的输出相匹配。值得注意的是,我输出的TBC似乎是输出编解码器上下文的时基的两倍。我不太确定这是否是Gif文件格式的问题,我的输出编解码器上下文似乎总是设置为1/100。

比特率计算和设置

int calculated_br = istream_codec_context->time_base.den *     
                    avpicture_get_size(AV_PIX_FMT_YUV420P, ostream_codec_context->width, 
                                       ostream_codec_context->height);    

ostream_codec_context->bit_rate = calculated_br;
ostream_codec_context->rc_min_rate = calculated_br;
ostream_codec_context->rc_max_rate = calculated_br;
ostream_codec_context->rc_buffer_size = calculated_br;

即使我的输出的pts / dts值与FFmpeg输出的值相匹配,我还是预感到所有这些问题都与我没有正确设置PTS / DTS有关。

我很感激一些帮助, 谢谢!

1 个答案:

答案 0 :(得分:0)

使用libx264进行输出,您可能需要按照我在this answer中的描述手动重新缩放时间戳。这可以解释你的比特率问题。