summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2015-01-16 17:03:35 +0100
committerMichael Niedermayer <michaelni@gmx.at>2015-01-16 19:53:17 +0100
commit7b32856011d1859a974b884f76bd17b7a7fdab76 (patch)
tree13ead5e61c3d1efa8edac3f18ef3f1a92301da40
parent261e8ccbd1e38c0af719b97ed3fb1720bb733e09 (diff)
ffmpeg: Maintain higher precision pts between video filter and fps code
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>
-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