summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian@centricular.com>2016-09-12 20:08:36 +0200
committerSebastian Dröge <sebastian@centricular.com>2016-09-30 13:44:57 +0300
commitaea184359307d62e44597f93ba4af0ce29abde26 (patch)
tree79e81bc951e954d40e54a08a590aad3e8c212c69
parent59085d948aab662a9bfef9ba0c7d646799a84f7e (diff)
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.
-rw-r--r--gst/deinterlace/gstdeinterlace.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/gst/deinterlace/gstdeinterlace.c b/gst/deinterlace/gstdeinterlace.c
index 6e0589352..c2a31a8c2 100644
--- a/gst/deinterlace/gstdeinterlace.c
+++ b/gst/deinterlace/gstdeinterlace.c
@@ -1074,7 +1074,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;
@@ -1144,6 +1144,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;
@@ -1276,6 +1283,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)
@@ -1731,11 +1739,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)),
@@ -1869,7 +1882,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;
@@ -2683,7 +2699,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;
}