【问题标题】:FFMPEG avformat_write_header changing my stream time_baseFFMPEG avformat_write_header 改变我的流 time_base
【发布时间】:2015-07-03 05:17:42
【问题描述】:

我正在使用带有 libavcodec 55.39.101 的 ffmpeg 2.1.3 混合视频(强制使用该版本,因为它是 google-chrome PNACL 端口项目中可用的版本)。我所有的框架似乎都有不好的时间。在播放视频时,它们会尝试在视频开始时立即渲染。

我将流时基设置为 1/25,但在调用 avformat_write_header 后,它的值为 -18082736/1。 在每一帧中,当我打印流 time_base 时,它​​会显示 1/12800,而编解码器的 time_base 总是可以的(1/25)。

av_format_write_header 前后的控制台日志:

before avformat_write_header stream time_base: 1/25
after avformat_write_header ret 0 stream time_base: -18082736/1

代码(为保持帖子简短而缩写,原始版本中的所有调用都有错误检查):

AVCodecContext *codecContext;
AVCodec * codec = avcodec_find_encoder(codec_id);  
myOutputStream->stream = avformat_new_stream(outputFormatContext, *codec);
myOutputStream->stream->id = outputFormatContext->nb_streams-1;
codecContext = myOutputStream->stream->codec;
codecContext->codec_id = codec_id;
codecContext->bit_rate = 400000;
codecContext->width    = width;
codecContext->height   = height;
myOutputStream->stream->time_base = (AVRational){ 1, 25 };
codecContext->time_base       = myOutputStream->stream->time_base;
codecContext->gop_size      = 12; 
codecContext->pix_fmt       = AV_PIX_FMT_YUV420P;
AVDictionary *opt = NULL;
av_dict_copy(&opt, opt_arg, 0);
ret = avcodec_open2(codecContext, codec, &opt);
av_dict_free(&opt);
myOutputStream->frame = alloc_picture(codecContext->pix_fmt, codecContext->width, codecContext->height);
  myOutputStream->tmp_frame = alloc_picture(AV_PIX_FMT_YUV420P, codecContext->width, codecContext->height);

//before: printing g_outputContext->stream time_base here
ret = avformat_write_header(g_outputContext, &opt);
//after: printing g_outputContext->stream time_base here

如果我在最终视频上运行 ffmpeg -i,我得到了这个(为什么持续时间为零?):

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'test4.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2mp41
    encoder         : Lavf55.19.104
  Duration: 00:00:00.05, start: 0.000000, bitrate: 99549 kb/s
    Stream #0:0(und): Video: mpeg4 (Simple Profile) (mp4v / 0x7634706D), yuv420p, 800x600 [SAR 1:1 DAR 4:3], 463106 kb/s, 12800 fps, 12800 tbr, 12800 tbn, 25 tbc (default)
    Metadata:
      handler_name    : VideoHandler

【问题讨论】:

  • 您找到解决这个问题的合适方法了吗?
  • 为什么@RafaelLucio 的答案没有被标记为正确?

标签: video ffmpeg


【解决方案1】:

您需要在编码之后和写入文件之前操作数据包的 pts... ffmpeg 更改流的 time_base 并不罕见。在https://www.ffmpeg.org/doxygen/trunk/ffmpeg_8c-source.html查看ffmpeg.c源代码的第869行

【讨论】:

  • 我花了将近 1 天的时间来找出我的 pts 被更改的原因。谢谢!
  • 你能详细说明一下“操纵数据包的pts”是什么意思吗?是否会使生成的视频具有开始时设置 time_base 时定义的 FPS?
【解决方案2】:

要向@RafaelLucio answeravformat_write_header 添加更多详细信息,请按设计修改流时基,并且必须在将帧 pts 发送到编解码器上下文之前正确计算帧 pts,将所需值重新调整为实际流时基。一个简单的解决方案是在 frame append 函数之外保留一个 pts 计数器,并在函数体中计算下一个 pts。

int64_t pts = 0;
AVCodecContext *codecCtx;
AVStream *stream;

void appendFrame(AVFrame *frame)
{
    [...]
    frame->pts = pts;
    // Compute next pts
    pts += av_rescale_q(1, codecCtx->time_base, stream->time_base);
    [...]
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-02
    • 2018-03-12
    • 2021-01-24
    • 1970-01-01
    • 2020-10-03
    • 2018-01-09
    • 2022-06-27
    • 2016-06-10
    相关资源
    最近更新 更多