summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ffmpeg.c24
-rw-r--r--tests/ref/fate/filter-setpts10
2 files changed, 23 insertions, 11 deletions
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