我正在使用ffmpeg 2.1.3与libavcodec 55.39.101复制视频(强制使用该版本因为是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
答案 0 :(得分:4)
您需要在编码之后和写入文件之前操纵数据包的pts ...通过ffmpeg更改流的time_base并不罕见。检查https://www.ffmpeg.org/doxygen/trunk/ffmpeg_8c-source.html
处ffmpeg.c源代码的第869行答案 1 :(得分:0)
要向@RafaelLucio answer添加更多详细信息,avformat_write_header
通过设计修改流时基,并且在将帧pt发送到编解码器上下文之前必须正确计算帧pt,将所需值重新缩放为实际值。流时基。一种简单的解决方案是将pts计数器保留在框架附加函数的外部,然后在函数主体中计算下一个pts。
int64_t pts = 0;
AVCodecContext *codecCtx;
AVStream *stream;
void appendFrame(const AVFrame *frame)
{
[...]
frame->pts = pts;
// Compute next pts
pts += av_rescale_q(1, codecCtx->time_base, stream->time_base);
[...]
}