From dba90631bc853ef710f15ffb03c8c2d94afbcaaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 12 Sep 2016 20:08:36 +0200 Subject: [PATCH] deinterlace: Fix field ordering for reverse playback And actually calculate the field duration instead of a frame duration so that we can properly timestamp output frames in fields=all mode. This is probably still broken for reverse playback in telecine mode. --- gst/deinterlace/gstdeinterlace.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/gst/deinterlace/gstdeinterlace.c b/gst/deinterlace/gstdeinterlace.c index 3a1833edde..503b75e566 100644 --- a/gst/deinterlace/gstdeinterlace.c +++ b/gst/deinterlace/gstdeinterlace.c @@ -1081,7 +1081,7 @@ gst_deinterlace_push_history (GstDeinterlace * self, GstBuffer * buffer) GstVideoFrame *frame = NULL; GstVideoFrame *field1, *field2 = NULL; guint fields_to_push; - gint field1_flags, field2_flags; + guint field1_flags, field2_flags; GstVideoInterlaceMode interlacing_mode; guint8 buf_state; @@ -1151,6 +1151,13 @@ gst_deinterlace_push_history (GstDeinterlace * self, GstBuffer * buffer) field2_flags = PICTURE_INTERLACED_TOP; } + /* Swap for reverse playback */ + if (self->segment.rate < 0) { + field1_flags = field1_flags ^ field2_flags; + field2_flags = field1_flags ^ field2_flags; + field1_flags = field1_flags ^ field2_flags; + } + if (!onefield) { GST_DEBUG_OBJECT (self, "Two fields"); self->field_history[1].frame = field1; @@ -1283,6 +1290,7 @@ gst_deinterlace_fix_timestamps (GstDeinterlace * self, GstVideoFrame *field3, *field4; GstVideoInterlaceMode interlacing_mode; + /* FIXME: This is broken for rate < 0 */ if (self->pattern_lock && self->pattern > -1) { /* accurate pattern-locked timestamp adjustment */ if (!self->pattern_count) @@ -1742,11 +1750,16 @@ restart: if (!IS_TELECINE (interlacing_mode)) { timestamp = GST_BUFFER_TIMESTAMP (buf); - GST_BUFFER_TIMESTAMP (outbuf) = timestamp; - if (self->fields == GST_DEINTERLACE_ALL) + if (self->fields == GST_DEINTERLACE_ALL) { + if (self->segment.rate < 0) + GST_BUFFER_TIMESTAMP (outbuf) = timestamp + self->field_duration; + else + GST_BUFFER_TIMESTAMP (outbuf) = timestamp; GST_BUFFER_DURATION (outbuf) = self->field_duration; - else + } else { + GST_BUFFER_TIMESTAMP (outbuf) = timestamp; GST_BUFFER_DURATION (outbuf) = 2 * self->field_duration; + } GST_DEBUG_OBJECT (self, "[ADJUST] ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", end %" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)), @@ -1884,7 +1897,10 @@ restart: timestamp = GST_BUFFER_TIMESTAMP (buf); if (self->fields == GST_DEINTERLACE_ALL) { - GST_BUFFER_TIMESTAMP (outbuf) = timestamp + self->field_duration; + if (self->segment.rate < 0) + GST_BUFFER_TIMESTAMP (outbuf) = timestamp; + else + GST_BUFFER_TIMESTAMP (outbuf) = timestamp + self->field_duration; GST_BUFFER_DURATION (outbuf) = self->field_duration; } else { GST_BUFFER_TIMESTAMP (outbuf) = timestamp; @@ -2747,7 +2763,7 @@ gst_deinterlace_setcaps (GstDeinterlace * self, GstPad * pad, GstCaps * caps) } if (fps_n != 0) { - self->field_duration = gst_util_uint64_scale (GST_SECOND, fps_d, fps_n); + self->field_duration = gst_util_uint64_scale (GST_SECOND, fps_d, 2 * fps_n); } else { self->field_duration = 0; }