ffmpeg: Maintain higher precision pts between video filter and fps code
authorMichael Niedermayer <michaelni@gmx.at>
Fri, 16 Jan 2015 16:03:35 +0000 (17:03 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Fri, 16 Jan 2015 18:53:17 +0000 (19:53 +0100)
This is a bit ugly as it attempts to keep most of the computation
in integers before the double based fps code. The use of integers
is to reduce the chances of rounding differences between platforms

Previously the timestamp was rounded to the encoder timebase
before being converted back to double precision which could cause loss
of precision

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
ffmpeg.c
tests/ref/fate/filter-setpts

index 18d27682219fbed53629e800c284e18b50c32341..909dd68600fbecb0074ea8bbc09674194455d6ce 100644 (file)
--- 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) &&
index c1ce1d3d1e0306db6ee4458337d98799dc790513..5b1d73446f8fb5bc05cb70f83c4150bca999a132 100644 (file)
@@ -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