diff --git a/ffmpeg.c b/ffmpeg.c index 18d2768221..909dd68600 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -883,14 +883,15 @@ static void do_subtitle_out(AVFormatContext *s, static void do_video_out(AVFormatContext *s, OutputStream *ost, - AVFrame *next_picture) + AVFrame *next_picture, + double sync_ipts) { int ret, format_video_sync; AVPacket pkt; AVCodecContext *enc = ost->enc_ctx; AVCodecContext *mux_enc = ost->st->codec; int nb_frames, nb0_frames, i; - double sync_ipts, delta, delta0; + double delta, delta0; double duration = 0; int frame_size = 0; InputStream *ist = NULL; @@ -909,7 +910,6 @@ static void do_video_out(AVFormatContext *s, duration = lrintf(av_frame_get_pkt_duration(next_picture) * av_q2d(ist->st->time_base) / av_q2d(enc->time_base)); } - sync_ipts = next_picture->pts; delta0 = sync_ipts - ost->sync_opts; delta = delta0 + duration; @@ -1233,6 +1233,7 @@ static int reap_filters(void) filtered_frame = ost->filtered_frame; while (1) { + double float_pts = AV_NOPTS_VALUE; // this is identical to filtered_frame.pts but with higher precission ret = av_buffersink_get_frame_flags(filter, filtered_frame, AV_BUFFERSINK_FLAG_NO_REQUEST); if (ret < 0) { @@ -1246,9 +1247,19 @@ static int reap_filters(void) av_frame_unref(filtered_frame); continue; } - if (filtered_frame->pts != AV_NOPTS_VALUE) { int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; + AVRational tb = enc->time_base; + int extra_bits = av_clip(29 - av_log2(tb.den), 0, 16); + + tb.den <<= extra_bits; + float_pts = + av_rescale_q(filtered_frame->pts, filter->inputs[0]->time_base, tb) - + av_rescale_q(start_time, AV_TIME_BASE_Q, tb); + float_pts /= 1 << extra_bits; + // avoid exact midoints to reduce the chance of rounding differences, this can be removed in case the fps code is changed to work with integers + float_pts += FFSIGN(float_pts) * 1.0 / (1<<17); + filtered_frame->pts = av_rescale_q(filtered_frame->pts, filter->inputs[0]->time_base, enc->time_base) - av_rescale_q(start_time, AV_TIME_BASE_Q, enc->time_base); @@ -1262,12 +1273,13 @@ static int reap_filters(void) enc->sample_aspect_ratio = filtered_frame->sample_aspect_ratio; if (debug_ts) { - av_log(NULL, AV_LOG_INFO, "filter -> pts:%s pts_time:%s time_base:%d/%d\n", + av_log(NULL, AV_LOG_INFO, "filter -> pts:%s pts_time:%s exact:%f time_base:%d/%d\n", av_ts2str(filtered_frame->pts), av_ts2timestr(filtered_frame->pts, &enc->time_base), + float_pts, enc->time_base.num, enc->time_base.den); } - do_video_out(of->ctx, ost, filtered_frame); + do_video_out(of->ctx, ost, filtered_frame, float_pts); break; case AVMEDIA_TYPE_AUDIO: if (!(enc->codec->capabilities & CODEC_CAP_PARAM_CHANGE) && diff --git a/tests/ref/fate/filter-setpts b/tests/ref/fate/filter-setpts index c1ce1d3d1e..5b1d73446f 100644 --- a/tests/ref/fate/filter-setpts +++ b/tests/ref/fate/filter-setpts @@ -7,27 +7,27 @@ 0, 5, 5, 1, 152064, 0xedb5a8e6 0, 6, 6, 1, 152064, 0x5ab58bac 0, 7, 7, 1, 152064, 0x1f1b8026 -0, 8, 8, 1, 152064, 0x02344760 +0, 8, 8, 1, 152064, 0x91373915 0, 9, 9, 1, 152064, 0x30f5fcd5 0, 10, 10, 1, 152064, 0xc711ad61 0, 11, 11, 1, 152064, 0x52a48ddd 0, 12, 12, 1, 152064, 0xa91c0f05 -0, 13, 13, 1, 152064, 0xb15d38c8 +0, 13, 13, 1, 152064, 0x8e364e18 0, 14, 14, 1, 152064, 0xf25f6acc 0, 15, 15, 1, 152064, 0xf34ddbff 0, 16, 16, 1, 152064, 0x9dc72412 0, 17, 17, 1, 152064, 0x445d1d59 -0, 18, 18, 1, 152064, 0xce09f9d6 +0, 18, 18, 1, 152064, 0x2f2768ef 0, 19, 19, 1, 152064, 0x95579936 0, 20, 20, 1, 152064, 0x43d796b5 0, 21, 21, 1, 152064, 0x76d2a455 0, 22, 22, 1, 152064, 0x6dc3650e -0, 23, 23, 1, 152064, 0xe295c51e +0, 23, 23, 1, 152064, 0x0f9d6aca 0, 24, 24, 1, 152064, 0xd766fc8d 0, 25, 25, 1, 152064, 0xe22f7a30 0, 26, 26, 1, 152064, 0xfa8d94fb 0, 27, 27, 1, 152064, 0x4c9737ab -0, 28, 28, 1, 152064, 0x0b07594c +0, 28, 28, 1, 152064, 0xa50d01f8 0, 29, 29, 1, 152064, 0x88734edd 0, 30, 30, 1, 152064, 0xd2735925 0, 31, 31, 1, 152064, 0x20cebfa9