From: David Schleef Date: Mon, 11 Jul 2011 04:40:20 +0000 (-0700) Subject: deinterlace: change field handling through methods X-Git-Tag: 1.19.3~509^2~7136^2~404 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0446787e65dabb261fb851e2be86b56918186a51;p=platform%2Fupstream%2Fgstreamer.git deinterlace: change field handling through methods This likely breaks stuff. The good: all of the methods now create field images aligned with input frames, without timestamp mangling. The bad: this touches a lot of code, much of which is hairy and in need of cleanup. However, at this point we can reasonably create a PSNR-based test. --- diff --git a/gst/deinterlace/gstdeinterlace.c b/gst/deinterlace/gstdeinterlace.c index c4d6cf9..4e1b488 100644 --- a/gst/deinterlace/gstdeinterlace.c +++ b/gst/deinterlace/gstdeinterlace.c @@ -765,6 +765,7 @@ gst_deinterlace_reset_history (GstDeinterlace * self, gboolean drop_all) self->state_count = 0; self->pattern_lock = FALSE; self->pattern_refresh = TRUE; + self->cur_field_idx = -1; if (!self->still_frame_mode && self->last_buffer) { gst_buffer_unref (self->last_buffer); @@ -1183,9 +1184,10 @@ gst_deinterlace_push_history (GstDeinterlace * self, GstBuffer * buffer) } self->history_count += fields_to_push; + self->cur_field_idx += fields_to_push; - GST_DEBUG_OBJECT (self, "Pushed buffer -- current history size %d", - self->history_count); + GST_DEBUG_OBJECT (self, "Pushed buffer -- current history size %d, index %d", + self->history_count, self->cur_field_idx); if (self->last_buffer) gst_buffer_unref (self->last_buffer); @@ -1456,7 +1458,6 @@ gst_deinterlace_output_frame (GstDeinterlace * self, gboolean flushing) GstClockTime timestamp; GstFlowReturn ret; gint fields_required; - gint cur_field_idx; GstBuffer *buf, *outbuf; GstDeinterlaceField *field1, *field2; GstDeinterlaceInterlacingMethod interlacing_method; @@ -1471,7 +1472,6 @@ gst_deinterlace_output_frame (GstDeinterlace * self, gboolean flushing) restart: ret = GST_FLOW_OK; fields_required = 0; - cur_field_idx = 0; hl_no_lock = FALSE; same_buffer = FALSE; flush_one = FALSE; @@ -1530,6 +1530,7 @@ restart: if (flush_one && self->drop_orphans) { GST_DEBUG_OBJECT (self, "Dropping orphan first field"); + self->cur_field_idx--; gst_buffer_unref (gst_deinterlace_pop_history (self)); goto restart; } @@ -1558,7 +1559,7 @@ restart: fields_required = 2; if (!flushing && self->history_count < fields_required) { GST_DEBUG_OBJECT (self, "Need more fields (have %d, need %d)", - self->history_count, fields_required); + self->history_count, self->cur_field_idx + fields_required); goto need_more; } @@ -1573,9 +1574,11 @@ restart: GST_DEBUG_OBJECT (self, "Frame type: Telecine Progressive; pushing buffer as a frame"); /* pop and push */ + self->cur_field_idx--; field1_buf = gst_deinterlace_pop_history (self); /* field2 is the same buffer as field1, but we need to remove it from * the history anyway */ + self->cur_field_idx--; gst_buffer_unref (gst_deinterlace_pop_history (self)); /* set the caps from the src pad on the buffer as they should be correct */ gst_buffer_set_caps (field1_buf, GST_PAD_CAPS (self->srcpad)); @@ -1617,9 +1620,9 @@ restart: } /* Not enough fields in the history */ - if (self->history_count < fields_required) { + if (!flushing && self->history_count < fields_required) { GST_DEBUG_OBJECT (self, "Need more fields (have %d, need %d)", - self->history_count, fields_required); + self->history_count, self->cur_field_idx + fields_required); goto need_more; } @@ -1633,9 +1636,9 @@ restart: fields_required = 2; /* Not enough fields in the history */ - if (self->history_count < fields_required) { + if (!flushing && self->history_count < fields_required) { GST_DEBUG_OBJECT (self, "Need more fields (have %d, need %d)", - self->history_count, fields_required); + self->history_count, self->cur_field_idx + fields_required); goto need_more; } @@ -1649,9 +1652,11 @@ restart: GST_DEBUG_OBJECT (self, "Frame type: Progressive; pushing buffer as a frame"); /* pop and push */ + self->cur_field_idx--; field1_buf = gst_deinterlace_pop_history (self); /* field2 is the same buffer as field1, but we need to remove it from the * history anyway */ + self->cur_field_idx--; gst_buffer_unref (gst_deinterlace_pop_history (self)); GST_DEBUG_OBJECT (self, "[OUT] ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", end %" @@ -1662,6 +1667,10 @@ restart: return gst_pad_push (self->srcpad, field1_buf); } + if (!flushing && self->cur_field_idx < 1) { + goto need_more; + } + if (self->fields == GST_DEINTERLACE_ALL || interlacing_method == GST_DEINTERLACE_TELECINE) GST_DEBUG_OBJECT (self, "All fields"); @@ -1670,9 +1679,7 @@ restart: else if (self->fields == GST_DEINTERLACE_BF) GST_DEBUG_OBJECT (self, "Bottom fields"); - cur_field_idx = self->history_count - fields_required; - - if ((self->field_history[cur_field_idx].flags == PICTURE_INTERLACED_TOP + if ((self->field_history[self->cur_field_idx].flags == PICTURE_INTERLACED_TOP && (self->fields == GST_DEINTERLACE_TF || interlacing_method == GST_DEINTERLACE_TELECINE)) || self->fields == GST_DEINTERLACE_ALL) { @@ -1723,16 +1730,37 @@ restart: /* Check if we need to drop the frame because of QoS */ if (!gst_deinterlace_do_qos (self, GST_BUFFER_TIMESTAMP (buf))) { + self->cur_field_idx--; gst_buffer_unref (gst_deinterlace_pop_history (self)); gst_buffer_unref (outbuf); outbuf = NULL; ret = GST_FLOW_OK; } else { + if (self->cur_field_idx < 0 && flushing) { + if (self->history_count == 1) { + gst_buffer_unref (gst_deinterlace_pop_history (self)); + goto need_more; + } + self->cur_field_idx++; + } + if (self->cur_field_idx < 0) { + goto need_more; + } + if (!flushing && self->cur_field_idx < 1) { + goto need_more; + } + /* do magic calculus */ gst_deinterlace_method_deinterlace_frame (self->method, - self->field_history, self->history_count, outbuf); + self->field_history, self->history_count, outbuf, + self->cur_field_idx); - gst_buffer_unref (gst_deinterlace_pop_history (self)); + self->cur_field_idx--; + if (self->cur_field_idx + 1 + + gst_deinterlace_method_get_latency (self->method) + < self->history_count || flushing) { + gst_buffer_unref (gst_deinterlace_pop_history (self)); + } if (gst_deinterlace_clip_buffer (self, outbuf)) { GST_DEBUG_OBJECT (self, @@ -1755,6 +1783,7 @@ restart: /* pop off the second field */ GST_DEBUG_OBJECT (self, "Removing unused field (count: %d)", self->history_count); + self->cur_field_idx--; gst_buffer_unref (gst_deinterlace_pop_history (self)); interlacing_method = GST_DEINTERLACE_INTERLACED; return ret; @@ -1767,10 +1796,11 @@ restart: } } /* no calculation done: remove excess field */ - else if (self->field_history[cur_field_idx].flags == + else if (self->field_history[self->cur_field_idx].flags == PICTURE_INTERLACED_TOP && (self->fields == GST_DEINTERLACE_BF && interlacing_method != GST_DEINTERLACE_TELECINE)) { GST_DEBUG_OBJECT (self, "Removing unused top field"); + self->cur_field_idx--; gst_buffer_unref (gst_deinterlace_pop_history (self)); if (flush_one && !self->drop_orphans) { @@ -1779,13 +1809,19 @@ restart: } } - cur_field_idx = self->history_count - fields_required; if (self->history_count < fields_required) return ret; + if (self->cur_field_idx < 0) + return ret; + + if (!flushing && self->cur_field_idx < 1) { + return ret; + } + /* deinterlace bottom_field */ - if ((self->field_history[cur_field_idx].flags == PICTURE_INTERLACED_BOTTOM - && (self->fields == GST_DEINTERLACE_BF + if ((self->field_history[self->cur_field_idx].flags == + PICTURE_INTERLACED_BOTTOM && (self->fields == GST_DEINTERLACE_BF || interlacing_method == GST_DEINTERLACE_TELECINE)) || self->fields == GST_DEINTERLACE_ALL) { GST_DEBUG_OBJECT (self, "deinterlacing bottom field"); @@ -1834,6 +1870,7 @@ restart: /* Check if we need to drop the frame because of QoS */ if (!gst_deinterlace_do_qos (self, GST_BUFFER_TIMESTAMP (buf))) { + self->cur_field_idx--; gst_buffer_unref (gst_deinterlace_pop_history (self)); gst_buffer_unref (outbuf); outbuf = NULL; @@ -1841,9 +1878,15 @@ restart: } else { /* do magic calculus */ gst_deinterlace_method_deinterlace_frame (self->method, - self->field_history, self->history_count, outbuf); + self->field_history, self->history_count, outbuf, + self->cur_field_idx); - gst_buffer_unref (gst_deinterlace_pop_history (self)); + self->cur_field_idx--; + if (self->cur_field_idx + 1 + + gst_deinterlace_method_get_latency (self->method) + < self->history_count) { + gst_buffer_unref (gst_deinterlace_pop_history (self)); + } if (gst_deinterlace_clip_buffer (self, outbuf)) { GST_DEBUG_OBJECT (self, @@ -1866,6 +1909,7 @@ restart: /* pop off the second field */ GST_DEBUG_OBJECT (self, "Removing unused field (count: %d)", self->history_count); + self->cur_field_idx--; gst_buffer_unref (gst_deinterlace_pop_history (self)); interlacing_method = GST_DEINTERLACE_INTERLACED; return ret; @@ -1878,10 +1922,11 @@ restart: } } /* no calculation done: remove excess field */ - else if (self->field_history[cur_field_idx].flags == + else if (self->field_history[self->cur_field_idx].flags == PICTURE_INTERLACED_BOTTOM && (self->fields == GST_DEINTERLACE_TF && interlacing_method != GST_DEINTERLACE_TELECINE)) { GST_DEBUG_OBJECT (self, "Removing unused bottom field"); + self->cur_field_idx--; gst_buffer_unref (gst_deinterlace_pop_history (self)); if (flush_one && !self->drop_orphans) { diff --git a/gst/deinterlace/gstdeinterlace.h b/gst/deinterlace/gstdeinterlace.h index ac97a55..a5a69a3 100644 --- a/gst/deinterlace/gstdeinterlace.h +++ b/gst/deinterlace/gstdeinterlace.h @@ -146,6 +146,7 @@ struct _GstDeinterlace */ GstDeinterlaceField field_history[GST_DEINTERLACE_MAX_FIELD_HISTORY]; guint history_count; + int cur_field_idx; /* Set to TRUE if we're in still frame mode, i.e. just forward all buffers diff --git a/gst/deinterlace/gstdeinterlacemethod.c b/gst/deinterlace/gstdeinterlacemethod.c index fe5996b..9927868 100644 --- a/gst/deinterlace/gstdeinterlacemethod.c +++ b/gst/deinterlace/gstdeinterlacemethod.c @@ -206,10 +206,10 @@ gst_deinterlace_method_init (GstDeinterlaceMethod * self) void gst_deinterlace_method_deinterlace_frame (GstDeinterlaceMethod * self, const GstDeinterlaceField * history, guint history_count, - GstBuffer * outbuf) + GstBuffer * outbuf, int cur_field_idx) { g_assert (self->deinterlace_frame != NULL); - self->deinterlace_frame (self, history, history_count, outbuf); + self->deinterlace_frame (self, history, history_count, outbuf, cur_field_idx); } gint @@ -318,14 +318,13 @@ gst_deinterlace_simple_method_copy_scanline_packed (GstDeinterlaceSimpleMethod * static void gst_deinterlace_simple_method_deinterlace_frame_packed (GstDeinterlaceMethod * method, const GstDeinterlaceField * history, guint history_count, - GstBuffer * outbuf) + GstBuffer * outbuf, gint cur_field_idx) { GstDeinterlaceSimpleMethod *self = GST_DEINTERLACE_SIMPLE_METHOD (method); GstDeinterlaceMethodClass *dm_class = GST_DEINTERLACE_METHOD_GET_CLASS (self); GstDeinterlaceScanlineData scanlines; guint8 *dest; - const guint8 *field0, *field1, *field2, *field3; - gint cur_field_idx = history_count - dm_class->fields_required; + const guint8 *field0, *field1, *field2, *fieldp; guint cur_field_flags = history[cur_field_idx].flags; gint i; gint frame_height = self->parent.frame_height; @@ -334,29 +333,29 @@ gst_deinterlace_simple_method_deinterlace_frame_packed (GstDeinterlaceMethod * g_assert (self->interpolate_scanline_packed != NULL); g_assert (self->copy_scanline_packed != NULL); + if (cur_field_idx > 0) { + fieldp = GST_BUFFER_DATA (history[cur_field_idx - 1].buf); + } else { + fieldp = NULL; + } + dest = GST_BUFFER_DATA (outbuf); field0 = GST_BUFFER_DATA (history[cur_field_idx].buf); g_assert (dm_class->fields_required <= 4); - if (dm_class->fields_required >= 2) { + if (cur_field_idx + 1 < history_count) { field1 = GST_BUFFER_DATA (history[cur_field_idx + 1].buf); } else { field1 = NULL; } - if (dm_class->fields_required >= 3) { + if (cur_field_idx + 2 < history_count) { field2 = GST_BUFFER_DATA (history[cur_field_idx + 2].buf); } else { field2 = NULL; } - if (dm_class->fields_required >= 4) { - field3 = GST_BUFFER_DATA (history[cur_field_idx + 3].buf); - } else { - field3 = NULL; - } - #define CLAMP_LOW(i) (((i)<0) ? (i+2) : (i)) #define CLAMP_HI(i) (((i)>=(frame_height)) ? (i-2) : (i)) #define LINE(x,i) ((x) + CLAMP_HI(CLAMP_LOW(i)) * (stride)) @@ -368,6 +367,9 @@ gst_deinterlace_simple_method_deinterlace_frame_packed (GstDeinterlaceMethod * if (!((i & 1) ^ scanlines.bottom_field)) { /* copying */ + scanlines.tp = LINE2 (fieldp, i - 1); + scanlines.bp = LINE2 (fieldp, i + 1); + scanlines.tt0 = LINE2 (field0, (i - 2 >= 0) ? i - 2 : i); scanlines.m0 = LINE2 (field0, i); scanlines.bb0 = LINE2 (field0, (i + 2 < frame_height ? i + 2 : i)); @@ -379,12 +381,13 @@ gst_deinterlace_simple_method_deinterlace_frame_packed (GstDeinterlaceMethod * scanlines.m2 = LINE2 (field2, i); scanlines.bb2 = LINE2 (field2, (i + 2 < frame_height ? i + 2 : i)); - scanlines.t3 = LINE2 (field3, i - 1); - scanlines.b3 = LINE2 (field3, i + 1); - self->copy_scanline_packed (self, LINE (dest, i), &scanlines); } else { /* interpolating */ + scanlines.ttp = LINE2 (fieldp, (i - 2 >= 0) ? i - 2 : i); + scanlines.mp = LINE2 (fieldp, i); + scanlines.bbp = LINE2 (fieldp, (i + 2 < frame_height ? i + 2 : i)); + scanlines.t0 = LINE2 (field0, i - 1); scanlines.b0 = LINE2 (field0, i + 1); @@ -395,10 +398,6 @@ gst_deinterlace_simple_method_deinterlace_frame_packed (GstDeinterlaceMethod * scanlines.t2 = LINE2 (field2, i - 1); scanlines.b2 = LINE2 (field2, i + 1); - scanlines.tt3 = LINE2 (field3, (i - 2 >= 0) ? i - 2 : i); - scanlines.m3 = LINE2 (field3, i); - scanlines.bb3 = LINE2 (field3, (i + 2 < frame_height ? i + 2 : i)); - self->interpolate_scanline_packed (self, LINE (dest, i), &scanlines); } } @@ -452,7 +451,7 @@ gst_deinterlace_simple_method_copy_scanline_planar_v (GstDeinterlaceSimpleMethod static void gst_deinterlace_simple_method_deinterlace_frame_planar_plane (GstDeinterlaceSimpleMethod * self, guint8 * dest, const guint8 * field0, - const guint8 * field1, const guint8 * field2, const guint8 * field3, + const guint8 * field1, const guint8 * field2, const guint8 * fieldp, guint cur_field_flags, gint plane, GstDeinterlaceSimpleMethodFunction copy_scanline, GstDeinterlaceSimpleMethodFunction interpolate_scanline) @@ -471,6 +470,9 @@ static void if (!((i & 1) ^ scanlines.bottom_field)) { /* copying */ + scanlines.tp = LINE2 (fieldp, i - 1); + scanlines.bp = LINE2 (fieldp, i + 1); + scanlines.tt0 = LINE2 (field0, (i - 2 >= 0) ? i - 2 : i); scanlines.m0 = LINE2 (field0, i); scanlines.bb0 = LINE2 (field0, (i + 2 < frame_height ? i + 2 : i)); @@ -482,12 +484,13 @@ static void scanlines.m2 = LINE2 (field2, i); scanlines.bb2 = LINE2 (field2, (i + 2 < frame_height ? i + 2 : i)); - scanlines.t3 = LINE2 (field3, i - 1); - scanlines.b3 = LINE2 (field3, i + 1); - copy_scanline (self, LINE (dest, i), &scanlines); } else { /* interpolating */ + scanlines.ttp = LINE2 (fieldp, (i - 2 >= 0) ? i - 2 : i); + scanlines.mp = LINE2 (fieldp, i); + scanlines.bbp = LINE2 (fieldp, (i + 2 < frame_height ? i + 2 : i)); + scanlines.t0 = LINE2 (field0, i - 1); scanlines.b0 = LINE2 (field0, i + 1); @@ -498,10 +501,6 @@ static void scanlines.t2 = LINE2 (field2, i - 1); scanlines.b2 = LINE2 (field2, i + 1); - scanlines.tt3 = LINE2 (field3, (i - 2 >= 0) ? i - 2 : i); - scanlines.m3 = LINE2 (field3, i); - scanlines.bb3 = LINE2 (field3, (i + 2 < frame_height ? i + 2 : i)); - interpolate_scanline (self, LINE (dest, i), &scanlines); } } @@ -510,13 +509,12 @@ static void static void gst_deinterlace_simple_method_deinterlace_frame_planar (GstDeinterlaceMethod * method, const GstDeinterlaceField * history, guint history_count, - GstBuffer * outbuf) + GstBuffer * outbuf, gint cur_field_idx) { GstDeinterlaceSimpleMethod *self = GST_DEINTERLACE_SIMPLE_METHOD (method); GstDeinterlaceMethodClass *dm_class = GST_DEINTERLACE_METHOD_GET_CLASS (self); guint8 *out; - const guint8 *field0, *field1, *field2, *field3; - gint cur_field_idx = history_count - dm_class->fields_required; + const guint8 *field0, *field1, *field2, *fieldp; guint cur_field_flags = history[cur_field_idx].flags; gint i, offset; GstDeinterlaceSimpleMethodFunction copy_scanline; @@ -536,27 +534,27 @@ gst_deinterlace_simple_method_deinterlace_frame_planar (GstDeinterlaceMethod * out = GST_BUFFER_DATA (outbuf) + offset; + fieldp = NULL; + if (cur_field_idx > 0) { + fieldp = GST_BUFFER_DATA (history[cur_field_idx - 1].buf) + offset; + } + field0 = GST_BUFFER_DATA (history[cur_field_idx].buf) + offset; g_assert (dm_class->fields_required <= 4); field1 = NULL; - if (dm_class->fields_required >= 2) { + if (cur_field_idx + 1 < history_count) { field1 = GST_BUFFER_DATA (history[cur_field_idx + 1].buf) + offset; } field2 = NULL; - if (dm_class->fields_required >= 3) { + if (cur_field_idx + 2 < history_count) { field2 = GST_BUFFER_DATA (history[cur_field_idx + 2].buf) + offset; } - field3 = NULL; - if (dm_class->fields_required >= 4) { - field3 = GST_BUFFER_DATA (history[cur_field_idx + 3].buf) + offset; - } - gst_deinterlace_simple_method_deinterlace_frame_planar_plane (self, out, - field0, field1, field2, field3, cur_field_flags, i, copy_scanline, + field0, field1, field2, fieldp, cur_field_flags, i, copy_scanline, interpolate_scanline); } } @@ -564,13 +562,12 @@ gst_deinterlace_simple_method_deinterlace_frame_planar (GstDeinterlaceMethod * static void gst_deinterlace_simple_method_deinterlace_frame_nv12 (GstDeinterlaceMethod * method, const GstDeinterlaceField * history, guint history_count, - GstBuffer * outbuf) + GstBuffer * outbuf, gint cur_field_idx) { GstDeinterlaceSimpleMethod *self = GST_DEINTERLACE_SIMPLE_METHOD (method); GstDeinterlaceMethodClass *dm_class = GST_DEINTERLACE_METHOD_GET_CLASS (self); guint8 *out; - const guint8 *field0, *field1, *field2, *field3; - gint cur_field_idx = history_count - dm_class->fields_required; + const guint8 *field0, *field1, *field2, *fieldp; guint cur_field_flags = history[cur_field_idx].flags; gint i, offset; @@ -582,27 +579,27 @@ gst_deinterlace_simple_method_deinterlace_frame_nv12 (GstDeinterlaceMethod * out = GST_BUFFER_DATA (outbuf) + offset; + fieldp = NULL; + if (cur_field_idx > 0) { + fieldp = GST_BUFFER_DATA (history[cur_field_idx - 1].buf) + offset; + } + field0 = GST_BUFFER_DATA (history[cur_field_idx].buf) + offset; g_assert (dm_class->fields_required <= 4); field1 = NULL; - if (dm_class->fields_required >= 2) { + if (cur_field_idx + 1 < history_count) { field1 = GST_BUFFER_DATA (history[cur_field_idx + 1].buf) + offset; } field2 = NULL; - if (dm_class->fields_required >= 3) { + if (cur_field_idx + 2 < history_count) { field2 = GST_BUFFER_DATA (history[cur_field_idx + 2].buf) + offset; } - field3 = NULL; - if (dm_class->fields_required >= 4) { - field3 = GST_BUFFER_DATA (history[cur_field_idx + 3].buf) + offset; - } - gst_deinterlace_simple_method_deinterlace_frame_planar_plane (self, out, - field0, field1, field2, field3, cur_field_flags, i, + field0, field1, field2, fieldp, cur_field_flags, i, self->copy_scanline_packed, self->interpolate_scanline_packed); } } diff --git a/gst/deinterlace/gstdeinterlacemethod.h b/gst/deinterlace/gstdeinterlacemethod.h index 11e2c35..a50ecbd 100644 --- a/gst/deinterlace/gstdeinterlacemethod.h +++ b/gst/deinterlace/gstdeinterlacemethod.h @@ -61,7 +61,9 @@ typedef struct * This structure defines the deinterlacer plugin. */ -typedef void (*GstDeinterlaceMethodDeinterlaceFunction) (GstDeinterlaceMethod *self, const GstDeinterlaceField *history, guint history_count, GstBuffer *outbuf); +typedef void (*GstDeinterlaceMethodDeinterlaceFunction) ( + GstDeinterlaceMethod *self, const GstDeinterlaceField *history, + guint history_count, GstBuffer *outbuf, int cur_field_idx); struct _GstDeinterlaceMethod { GstObject parent; @@ -112,7 +114,8 @@ GType gst_deinterlace_method_get_type (void); gboolean gst_deinterlace_method_supported (GType type, GstVideoFormat format, gint width, gint height); void gst_deinterlace_method_setup (GstDeinterlaceMethod * self, GstVideoFormat format, gint width, gint height); -void gst_deinterlace_method_deinterlace_frame (GstDeinterlaceMethod * self, const GstDeinterlaceField * history, guint history_count, GstBuffer * outbuf); +void gst_deinterlace_method_deinterlace_frame (GstDeinterlaceMethod * self, const GstDeinterlaceField * history, guint history_count, GstBuffer * outbuf, + int cur_field_idx); gint gst_deinterlace_method_get_fields_required (GstDeinterlaceMethod * self); gint gst_deinterlace_method_get_latency (GstDeinterlaceMethod * self); @@ -133,32 +136,32 @@ typedef struct _GstDeinterlaceScanlineData GstDeinterlaceScanlineData; */ struct _GstDeinterlaceScanlineData { + const guint8 *ttp, *tp, *mp, *bp, *bbp; const guint8 *tt0, *t0, *m0, *b0, *bb0; const guint8 *tt1, *t1, *m1, *b1, *bb1; const guint8 *tt2, *t2, *m2, *b2, *bb2; - const guint8 *tt3, *t3, *m3, *b3, *bb3; gboolean bottom_field; }; /* * For interpolate_scanline the input is: * - * | t-3 t-2 t-1 t - * | Field 3 | Field 2 | Field 1 | Field 0 | - * | TT3 | | TT1 | | + * | t-3 t-2 t-1 t t+1 + * | Field 3 | Field 2 | Field 1 | Field 0 | Field -1 + * | TT3 | | TT1 | | TTp * | | T2 | | T0 | - * | M3 | | M1 | | + * | M3 | | M1 | | Mp * | | B2 | | B0 | - * | BB3 | | BB1 | | + * | BB3 | | BB1 | | BBp * * For copy_scanline the input is: * - * | t-3 t-2 t-1 t - * | Field 3 | Field 2 | Field 1 | Field 0 | + * | t-3 t-2 t-1 t t+1 + * | Field 3 | Field 2 | Field 1 | Field 0 | Field -1 * | | TT2 | | TT0 | - * | T3 | | T1 | | + * | T3 | | T1 | | Tp * | | M2 | | M0 | - * | B3 | | B1 | | + * | B3 | | B1 | | Bp * | | BB2 | | BB0 | * * All other values are NULL. diff --git a/gst/deinterlace/tvtime/greedy.c b/gst/deinterlace/tvtime/greedy.c index dcb495b..5775132 100644 --- a/gst/deinterlace/tvtime/greedy.c +++ b/gst/deinterlace/tvtime/greedy.c @@ -72,54 +72,69 @@ static inline void deinterlace_greedy_interpolate_scanline_orc (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - /* FIXME - is this safe or just a hack? */ guint max_comb = GST_DEINTERLACE_METHOD_GREEDY_L (self)->max_comb; - deinterlace_line_greedy (out, scanlines->m3, scanlines->t2, scanlines->b2, - scanlines->m1, max_comb, self->parent.row_stride[0]); + if (scanlines->m1 == NULL || scanlines->mp == NULL) { + deinterlace_line_linear (out, scanlines->t0, scanlines->b0, + self->parent.row_stride[0]); + } else { + deinterlace_line_greedy (out, scanlines->m1, scanlines->t0, scanlines->b0, + scanlines->mp ? scanlines->mp : scanlines->m1, + max_comb, self->parent.row_stride[0]); + } } static inline void deinterlace_greedy_interpolate_scanline_orc_planar_u (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - /* FIXME - is this safe or just a hack? */ guint max_comb = GST_DEINTERLACE_METHOD_GREEDY_L (self)->max_comb; - deinterlace_line_greedy (out, scanlines->m3, scanlines->t2, scanlines->b2, - scanlines->m1, max_comb, self->parent.row_stride[1]); + if (scanlines->m1 == NULL || scanlines->mp == NULL) { + deinterlace_line_linear (out, scanlines->t0, scanlines->b0, + self->parent.row_stride[1]); + } else { + deinterlace_line_greedy (out, scanlines->m1, scanlines->t0, scanlines->b0, + scanlines->mp ? scanlines->mp : scanlines->m1, + max_comb, self->parent.row_stride[1]); + } } static inline void deinterlace_greedy_interpolate_scanline_orc_planar_v (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - /* FIXME - is this safe or just a hack? */ guint max_comb = GST_DEINTERLACE_METHOD_GREEDY_L (self)->max_comb; - deinterlace_line_greedy (out, scanlines->m3, scanlines->t2, scanlines->b2, - scanlines->m1, max_comb, self->parent.row_stride[2]); + if (scanlines->m1 == NULL || scanlines->mp == NULL) { + deinterlace_line_linear (out, scanlines->t0, scanlines->b0, + self->parent.row_stride[2]); + } else { + deinterlace_line_greedy (out, scanlines->m1, scanlines->t0, scanlines->b0, + scanlines->mp ? scanlines->mp : scanlines->m1, + max_comb, self->parent.row_stride[2]); + } } static void deinterlace_greedy_copy_scanline (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - memcpy (out, scanlines->m2, self->parent.row_stride[0]); + memcpy (out, scanlines->m0, self->parent.row_stride[0]); } static void deinterlace_greedy_copy_scanline_planar_u (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - memcpy (out, scanlines->m2, self->parent.row_stride[1]); + memcpy (out, scanlines->m0, self->parent.row_stride[1]); } static void deinterlace_greedy_copy_scanline_planar_v (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - memcpy (out, scanlines->m2, self->parent.row_stride[2]); + memcpy (out, scanlines->m0, self->parent.row_stride[2]); } G_DEFINE_TYPE (GstDeinterlaceMethodGreedyL, gst_deinterlace_method_greedy_l, @@ -179,7 +194,7 @@ gst_deinterlace_method_greedy_l_class_init (GstDeinterlaceMethodGreedyLClass * "Max Comb", 0, 255, 15, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) ); - dim_class->fields_required = 4; + dim_class->fields_required = 2; dim_class->name = "Motion Adaptive: Simple Detection"; dim_class->nick = "greedyl"; dim_class->latency = 1; diff --git a/gst/deinterlace/tvtime/greedyh.c b/gst/deinterlace/tvtime/greedyh.c index d1e4fd6..93da8cd 100644 --- a/gst/deinterlace/tvtime/greedyh.c +++ b/gst/deinterlace/tvtime/greedyh.c @@ -719,7 +719,7 @@ greedyh_scanline_C_planar_uv (GstDeinterlaceMethodGreedyH * self, static void deinterlace_frame_di_greedyh_packed (GstDeinterlaceMethod * method, const GstDeinterlaceField * history, guint history_count, - GstBuffer * outbuf) + GstBuffer * outbuf, int cur_field_idx) { GstDeinterlaceMethodGreedyH *self = GST_DEINTERLACE_METHOD_GREEDY_H (method); GstDeinterlaceMethodGreedyHClass *klass = @@ -736,6 +736,23 @@ deinterlace_frame_di_greedyh_packed (GstDeinterlaceMethod * method, guint8 *Dest = GST_BUFFER_DATA (outbuf); ScanlineFunction scanline; + if (cur_field_idx + 2 > history_count || cur_field_idx < 1) { + GstDeinterlaceMethod *backup_method; + + backup_method = g_object_new (gst_deinterlace_method_linear_get_type (), + NULL); + + gst_deinterlace_method_setup (backup_method, method->format, + method->frame_width, method->frame_height); + gst_deinterlace_method_deinterlace_frame (backup_method, + history, history_count, outbuf, cur_field_idx); + + g_object_unref (backup_method); + return; + } + + cur_field_idx += 2; + switch (method->format) { case GST_VIDEO_FORMAT_YUY2: case GST_VIDEO_FORMAT_YVYU: @@ -755,20 +772,20 @@ deinterlace_frame_di_greedyh_packed (GstDeinterlaceMethod * method, // copy first even line no matter what, and the first odd line if we're // processing an EVEN field. (note diff from other deint rtns.) - if (history[history_count - 1].flags == PICTURE_INTERLACED_BOTTOM) { + if (history[cur_field_idx - 1].flags == PICTURE_INTERLACED_BOTTOM) { InfoIsOdd = 1; - L1 = GST_BUFFER_DATA (history[history_count - 2].buf); - if (history[history_count - 2].flags & PICTURE_INTERLACED_BOTTOM) + L1 = GST_BUFFER_DATA (history[cur_field_idx - 2].buf); + if (history[cur_field_idx - 2].flags & PICTURE_INTERLACED_BOTTOM) L1 += RowStride; - L2 = GST_BUFFER_DATA (history[history_count - 1].buf); - if (history[history_count - 1].flags & PICTURE_INTERLACED_BOTTOM) + L2 = GST_BUFFER_DATA (history[cur_field_idx - 1].buf); + if (history[cur_field_idx - 1].flags & PICTURE_INTERLACED_BOTTOM) L2 += RowStride; L3 = L1 + Pitch; - L2P = GST_BUFFER_DATA (history[history_count - 3].buf); - if (history[history_count - 3].flags & PICTURE_INTERLACED_BOTTOM) + L2P = GST_BUFFER_DATA (history[cur_field_idx - 3].buf); + if (history[cur_field_idx - 3].flags & PICTURE_INTERLACED_BOTTOM) L2P += RowStride; // copy first even line @@ -776,17 +793,17 @@ deinterlace_frame_di_greedyh_packed (GstDeinterlaceMethod * method, Dest += RowStride; } else { InfoIsOdd = 0; - L1 = GST_BUFFER_DATA (history[history_count - 2].buf); - if (history[history_count - 2].flags & PICTURE_INTERLACED_BOTTOM) + L1 = GST_BUFFER_DATA (history[cur_field_idx - 2].buf); + if (history[cur_field_idx - 2].flags & PICTURE_INTERLACED_BOTTOM) L1 += RowStride; - L2 = GST_BUFFER_DATA (history[history_count - 1].buf) + Pitch; - if (history[history_count - 1].flags & PICTURE_INTERLACED_BOTTOM) + L2 = GST_BUFFER_DATA (history[cur_field_idx - 1].buf) + Pitch; + if (history[cur_field_idx - 1].flags & PICTURE_INTERLACED_BOTTOM) L2 += RowStride; L3 = L1 + Pitch; - L2P = GST_BUFFER_DATA (history[history_count - 3].buf) + Pitch; - if (history[history_count - 3].flags & PICTURE_INTERLACED_BOTTOM) + L2P = GST_BUFFER_DATA (history[cur_field_idx - 3].buf) + Pitch; + if (history[cur_field_idx - 3].flags & PICTURE_INTERLACED_BOTTOM) L2P += RowStride; // copy first even line @@ -858,7 +875,7 @@ deinterlace_frame_di_greedyh_planar_plane (GstDeinterlaceMethodGreedyH * self, static void deinterlace_frame_di_greedyh_planar (GstDeinterlaceMethod * method, const GstDeinterlaceField * history, guint history_count, - GstBuffer * outbuf) + GstBuffer * outbuf, int cur_field_idx) { GstDeinterlaceMethodGreedyH *self = GST_DEINTERLACE_METHOD_GREEDY_H (method); GstDeinterlaceMethodGreedyHClass *klass = @@ -876,10 +893,27 @@ deinterlace_frame_di_greedyh_planar (GstDeinterlaceMethod * method, gint Offset; ScanlineFunction scanline; + if (cur_field_idx + 2 > history_count || cur_field_idx < 1) { + GstDeinterlaceMethod *backup_method; + + backup_method = g_object_new (gst_deinterlace_method_linear_get_type (), + NULL); + + gst_deinterlace_method_setup (backup_method, method->format, + method->frame_width, method->frame_height); + gst_deinterlace_method_deinterlace_frame (backup_method, + history, history_count, outbuf, cur_field_idx); + + g_object_unref (backup_method); + return; + } + + cur_field_idx += 2; + for (i = 0; i < 3; i++) { Offset = method->offset[i]; - InfoIsOdd = (history[history_count - 1].flags == PICTURE_INTERLACED_BOTTOM); + InfoIsOdd = (history[cur_field_idx - 1].flags == PICTURE_INTERLACED_BOTTOM); RowStride = method->row_stride[i]; FieldHeight = method->height[i] / 2; Pitch = method->row_stride[i] * 2; @@ -891,17 +925,17 @@ deinterlace_frame_di_greedyh_planar (GstDeinterlaceMethod * method, Dest = GST_BUFFER_DATA (outbuf) + Offset; - L1 = GST_BUFFER_DATA (history[history_count - 2].buf) + Offset; - if (history[history_count - 2].flags & PICTURE_INTERLACED_BOTTOM) + L1 = GST_BUFFER_DATA (history[cur_field_idx - 2].buf) + Offset; + if (history[cur_field_idx - 2].flags & PICTURE_INTERLACED_BOTTOM) L1 += RowStride; - L2 = GST_BUFFER_DATA (history[history_count - 1].buf) + Offset; - if (history[history_count - 1].flags & PICTURE_INTERLACED_BOTTOM) + L2 = GST_BUFFER_DATA (history[cur_field_idx - 1].buf) + Offset; + if (history[cur_field_idx - 1].flags & PICTURE_INTERLACED_BOTTOM) L2 += RowStride; L3 = L1 + Pitch; - L2P = GST_BUFFER_DATA (history[history_count - 3].buf) + Offset; - if (history[history_count - 3].flags & PICTURE_INTERLACED_BOTTOM) + L2P = GST_BUFFER_DATA (history[cur_field_idx - 3].buf) + Offset; + if (history[cur_field_idx - 3].flags & PICTURE_INTERLACED_BOTTOM) L2P += RowStride; deinterlace_frame_di_greedyh_planar_plane (self, L1, L2, L3, L2P, Dest, diff --git a/gst/deinterlace/tvtime/linearblend.c b/gst/deinterlace/tvtime/linearblend.c index a343d0f..189e1aa 100644 --- a/gst/deinterlace/tvtime/linearblend.c +++ b/gst/deinterlace/tvtime/linearblend.c @@ -56,7 +56,11 @@ deinterlace_scanline_linear_blend_c (GstDeinterlaceSimpleMethod * self, guint8 * out, const guint8 * t0, const guint8 * b0, const guint8 * m1, gint size) { - deinterlace_line_linear_blend (out, t0, b0, m1, size); + if (m1 == NULL) { + deinterlace_line_linear (out, t0, b0, size); + } else { + deinterlace_line_linear_blend (out, t0, b0, m1, size); + } } static void @@ -96,7 +100,11 @@ deinterlace_scanline_linear_blend2_c (GstDeinterlaceSimpleMethod * self, guint8 * out, const guint8 * m0, const guint8 * t1, const guint8 * b1, gint size) { - deinterlace_line_linear_blend (out, t1, b1, m0, size); + if (t1 == NULL) { + memcpy (out, m0, size); + } else { + deinterlace_line_linear_blend (out, t1, b1, m0, size); + } } static void @@ -145,7 +153,7 @@ static void dim_class->fields_required = 2; dim_class->name = "Blur: Temporal"; dim_class->nick = "linearblend"; - dim_class->latency = 0; + dim_class->latency = 1; dism_class->interpolate_scanline_yuy2 = deinterlace_scanline_linear_blend_packed_c; diff --git a/gst/deinterlace/tvtime/scalerbob.c b/gst/deinterlace/tvtime/scalerbob.c index bac4c62..adc285a 100644 --- a/gst/deinterlace/tvtime/scalerbob.c +++ b/gst/deinterlace/tvtime/scalerbob.c @@ -77,10 +77,10 @@ gst_deinterlace_method_scaler_bob_class_init (GstDeinterlaceMethodScalerBobClass GstDeinterlaceSimpleMethodClass *dism_class = (GstDeinterlaceSimpleMethodClass *) klass; - dim_class->fields_required = 1; + dim_class->fields_required = 2; dim_class->name = "Double lines"; dim_class->nick = "scalerbob"; - dim_class->latency = 0; + dim_class->latency = 1; dism_class->interpolate_scanline_ayuv = deinterlace_scanline_scaler_bob_packed; diff --git a/gst/deinterlace/tvtime/tomsmocomp/TomsMoCompAll.inc b/gst/deinterlace/tvtime/tomsmocomp/TomsMoCompAll.inc index 23903b3..f8ffe1e 100644 --- a/gst/deinterlace/tvtime/tomsmocomp/TomsMoCompAll.inc +++ b/gst/deinterlace/tvtime/tomsmocomp/TomsMoCompAll.inc @@ -61,7 +61,9 @@ #define SEFUNC(x) Search_Effort_C_##x(src_pitch, dst_pitch, rowsize, pWeaveSrc, pWeaveSrcP, pWeaveDest, IsOdd, pCopySrc, pCopySrcP, FldHeight) #endif -static void FUNCT_NAME(GstDeinterlaceMethod *d_method, const GstDeinterlaceField* history, guint history_count, GstBuffer *outbuf) +static void FUNCT_NAME(GstDeinterlaceMethod *d_method, + const GstDeinterlaceField* history, guint history_count, + GstBuffer *outbuf, int cur_field_idx) { GstDeinterlaceMethodTomsMoComp *self = GST_DEINTERLACE_METHOD_TOMSMOCOMP (d_method); glong SearchEffort = self->search_effort; @@ -78,6 +80,21 @@ static void FUNCT_NAME(GstDeinterlaceMethod *d_method, const GstDeinterlaceField gint rowsize; gint FldHeight; + if (cur_field_idx + 2 > history_count || cur_field_idx < 1) { + GstDeinterlaceMethod *backup_method; + + backup_method = g_object_new (gst_deinterlace_method_linear_get_type(), + NULL); + + gst_deinterlace_method_setup (backup_method, d_method->format, + d_method->frame_width, d_method->frame_height); + gst_deinterlace_method_deinterlace_frame (backup_method, + history, history_count, outbuf, cur_field_idx); + + g_object_unref (backup_method); + return; + } + /* double stride do address just every odd/even scanline */ src_pitch = self->parent.row_stride[0]*2; dst_pitch = self->parent.row_stride[0]; diff --git a/gst/deinterlace/tvtime/vfir.c b/gst/deinterlace/tvtime/vfir.c index c589dd7..6442a82 100644 --- a/gst/deinterlace/tvtime/vfir.c +++ b/gst/deinterlace/tvtime/vfir.c @@ -68,7 +68,11 @@ static inline void deinterlace_c (guint8 * dst, const guint8 * lum_m4, const guint8 * lum_m3, const guint8 * lum_m2, const guint8 * lum_m1, const guint8 * lum, gint size) { - deinterlace_line_vfir (dst, lum_m4, lum_m3, lum_m2, lum_m1, lum, size); + if (lum_m2 == NULL) { + deinterlace_line_linear (dst, lum_m1, lum_m3, size); + } else { + deinterlace_line_vfir (dst, lum_m4, lum_m3, lum_m2, lum_m1, lum, size); + } } static void @@ -127,6 +131,8 @@ deinterlace_line_planar_v_c (GstDeinterlaceSimpleMethod * self, guint8 * dst, deinterlace_c (dst, lum_m4, lum_m3, lum_m2, lum_m1, lum, size); } +#undef BUILD_X86_ASM + #ifdef BUILD_X86_ASM #include "mmx.h" static void @@ -251,7 +257,7 @@ gst_deinterlace_method_vfir_class_init (GstDeinterlaceMethodVFIRClass * klass) dim_class->fields_required = 2; dim_class->name = "Blur Vertical"; dim_class->nick = "vfir"; - dim_class->latency = 0; + dim_class->latency = 1; #ifdef BUILD_X86_ASM if (cpu_flags & ORC_TARGET_MMX_MMX) { diff --git a/gst/deinterlace/tvtime/weave.c b/gst/deinterlace/tvtime/weave.c index 8d49979..1501b1a 100644 --- a/gst/deinterlace/tvtime/weave.c +++ b/gst/deinterlace/tvtime/weave.c @@ -48,28 +48,44 @@ static void deinterlace_scanline_weave_packed (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - memcpy (out, scanlines->m1, self->parent.row_stride[0]); + if (scanlines->m1 == NULL) { + memcpy (out, scanlines->t0, self->parent.row_stride[0]); + } else { + memcpy (out, scanlines->m1, self->parent.row_stride[0]); + } } static void deinterlace_scanline_weave_planar_y (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - memcpy (out, scanlines->m1, self->parent.row_stride[0]); + if (scanlines->m1 == NULL) { + memcpy (out, scanlines->t0, self->parent.row_stride[0]); + } else { + memcpy (out, scanlines->m1, self->parent.row_stride[0]); + } } static void deinterlace_scanline_weave_planar_u (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - memcpy (out, scanlines->m1, self->parent.row_stride[1]); + if (scanlines->m1 == NULL) { + memcpy (out, scanlines->t0, self->parent.row_stride[1]); + } else { + memcpy (out, scanlines->m1, self->parent.row_stride[1]); + } } static void deinterlace_scanline_weave_planar_v (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - memcpy (out, scanlines->m1, self->parent.row_stride[2]); + if (scanlines->m1 == NULL) { + memcpy (out, scanlines->t0, self->parent.row_stride[2]); + } else { + memcpy (out, scanlines->m1, self->parent.row_stride[2]); + } } static void @@ -113,7 +129,7 @@ gst_deinterlace_method_weave_class_init (GstDeinterlaceMethodWeaveClass * klass) dim_class->fields_required = 2; dim_class->name = "Weave"; dim_class->nick = "weave"; - dim_class->latency = 0; + dim_class->latency = 1; dism_class->interpolate_scanline_ayuv = deinterlace_scanline_weave_packed; dism_class->interpolate_scanline_yuy2 = deinterlace_scanline_weave_packed; diff --git a/gst/deinterlace/tvtime/weavebff.c b/gst/deinterlace/tvtime/weavebff.c index b96da1f..b11395c 100644 --- a/gst/deinterlace/tvtime/weavebff.c +++ b/gst/deinterlace/tvtime/weavebff.c @@ -48,76 +48,72 @@ static void deinterlace_scanline_weave_packed (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - memcpy (out, scanlines->m1, self->parent.row_stride[0]); + if (scanlines->m1 == NULL) { + memcpy (out, scanlines->b0, self->parent.row_stride[0]); + } else { + memcpy (out, scanlines->m1, self->parent.row_stride[0]); + } } static void deinterlace_scanline_weave_planar_y (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - memcpy (out, scanlines->m1, self->parent.row_stride[0]); + if (scanlines->m1 == NULL) { + memcpy (out, scanlines->b0, self->parent.row_stride[0]); + } else { + memcpy (out, scanlines->m1, self->parent.row_stride[0]); + } } static void deinterlace_scanline_weave_planar_u (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - memcpy (out, scanlines->m1, self->parent.row_stride[1]); + if (scanlines->m1 == NULL) { + memcpy (out, scanlines->b0, self->parent.row_stride[1]); + } else { + memcpy (out, scanlines->m1, self->parent.row_stride[1]); + } } static void deinterlace_scanline_weave_planar_v (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - memcpy (out, scanlines->m1, self->parent.row_stride[2]); + if (scanlines->m1 == NULL) { + memcpy (out, scanlines->b0, self->parent.row_stride[2]); + } else { + memcpy (out, scanlines->m1, self->parent.row_stride[2]); + } } static void copy_scanline_packed (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - /* FIXME: original code used m2 and m0 but this looks really bad */ - if (scanlines->bottom_field) { - memcpy (out, scanlines->bb2, self->parent.row_stride[0]); - } else { - memcpy (out, scanlines->bb0, self->parent.row_stride[0]); - } + memcpy (out, scanlines->m0, self->parent.row_stride[0]); } static void copy_scanline_planar_y (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - /* FIXME: original code used m2 and m0 but this looks really bad */ - if (scanlines->bottom_field) { - memcpy (out, scanlines->bb2, self->parent.row_stride[0]); - } else { - memcpy (out, scanlines->bb0, self->parent.row_stride[0]); - } + memcpy (out, scanlines->m0, self->parent.row_stride[0]); } static void copy_scanline_planar_u (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - /* FIXME: original code used m2 and m0 but this looks really bad */ - if (scanlines->bottom_field) { - memcpy (out, scanlines->bb2, self->parent.row_stride[1]); - } else { - memcpy (out, scanlines->bb0, self->parent.row_stride[1]); - } + memcpy (out, scanlines->m0, self->parent.row_stride[1]); } static void copy_scanline_planar_v (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - /* FIXME: original code used m2 and m0 but this looks really bad */ - if (scanlines->bottom_field) { - memcpy (out, scanlines->bb2, self->parent.row_stride[2]); - } else { - memcpy (out, scanlines->bb0, self->parent.row_stride[2]); - } + memcpy (out, scanlines->m0, self->parent.row_stride[2]); } G_DEFINE_TYPE (GstDeinterlaceMethodWeaveBFF, gst_deinterlace_method_weave_bff, @@ -131,10 +127,10 @@ gst_deinterlace_method_weave_bff_class_init (GstDeinterlaceMethodWeaveBFFClass * GstDeinterlaceSimpleMethodClass *dism_class = (GstDeinterlaceSimpleMethodClass *) klass; - dim_class->fields_required = 3; + dim_class->fields_required = 2; dim_class->name = "Progressive: Bottom Field First"; dim_class->nick = "weavebff"; - dim_class->latency = 0; + dim_class->latency = 1; dism_class->interpolate_scanline_ayuv = deinterlace_scanline_weave_packed; dism_class->interpolate_scanline_yuy2 = deinterlace_scanline_weave_packed; diff --git a/gst/deinterlace/tvtime/weavetff.c b/gst/deinterlace/tvtime/weavetff.c index b645b0b..3c60613 100644 --- a/gst/deinterlace/tvtime/weavetff.c +++ b/gst/deinterlace/tvtime/weavetff.c @@ -49,76 +49,72 @@ static void deinterlace_scanline_weave_packed (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - memcpy (out, scanlines->m1, self->parent.row_stride[0]); + if (scanlines->m1 == NULL) { + memcpy (out, scanlines->t0, self->parent.row_stride[0]); + } else { + memcpy (out, scanlines->m1, self->parent.row_stride[0]); + } } static void deinterlace_scanline_weave_planar_y (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - memcpy (out, scanlines->m1, self->parent.row_stride[0]); + if (scanlines->m1 == NULL) { + memcpy (out, scanlines->t0, self->parent.row_stride[0]); + } else { + memcpy (out, scanlines->m1, self->parent.row_stride[0]); + } } static void deinterlace_scanline_weave_planar_u (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - memcpy (out, scanlines->m1, self->parent.row_stride[1]); + if (scanlines->m1 == NULL) { + memcpy (out, scanlines->t0, self->parent.row_stride[1]); + } else { + memcpy (out, scanlines->m1, self->parent.row_stride[1]); + } } static void deinterlace_scanline_weave_planar_v (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - memcpy (out, scanlines->m1, self->parent.row_stride[2]); + if (scanlines->m1 == NULL) { + memcpy (out, scanlines->t0, self->parent.row_stride[2]); + } else { + memcpy (out, scanlines->m1, self->parent.row_stride[2]); + } } static void copy_scanline_packed (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - /* FIXME: original code used m2 and m0 but this looks really bad */ - if (scanlines->bottom_field) { - memcpy (out, scanlines->bb0, self->parent.row_stride[0]); - } else { - memcpy (out, scanlines->bb2, self->parent.row_stride[0]); - } + memcpy (out, scanlines->m0, self->parent.row_stride[0]); } static void copy_scanline_planar_y (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - /* FIXME: original code used m2 and m0 but this looks really bad */ - if (scanlines->bottom_field) { - memcpy (out, scanlines->bb0, self->parent.row_stride[0]); - } else { - memcpy (out, scanlines->bb2, self->parent.row_stride[0]); - } + memcpy (out, scanlines->m0, self->parent.row_stride[0]); } static void copy_scanline_planar_u (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - /* FIXME: original code used m2 and m0 but this looks really bad */ - if (scanlines->bottom_field) { - memcpy (out, scanlines->bb0, self->parent.row_stride[1]); - } else { - memcpy (out, scanlines->bb2, self->parent.row_stride[1]); - } + memcpy (out, scanlines->m0, self->parent.row_stride[1]); } static void copy_scanline_planar_v (GstDeinterlaceSimpleMethod * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) { - /* FIXME: original code used m2 and m0 but this looks really bad */ - if (scanlines->bottom_field) { - memcpy (out, scanlines->bb0, self->parent.row_stride[2]); - } else { - memcpy (out, scanlines->bb2, self->parent.row_stride[2]); - } + memcpy (out, scanlines->m0, self->parent.row_stride[2]); } G_DEFINE_TYPE (GstDeinterlaceMethodWeaveTFF, gst_deinterlace_method_weave_tff, @@ -132,10 +128,10 @@ gst_deinterlace_method_weave_tff_class_init (GstDeinterlaceMethodWeaveTFFClass * GstDeinterlaceSimpleMethodClass *dism_class = (GstDeinterlaceSimpleMethodClass *) klass; - dim_class->fields_required = 3; + dim_class->fields_required = 2; dim_class->name = "Progressive: Top Field First"; dim_class->nick = "weavetff"; - dim_class->latency = 0; + dim_class->latency = 1; dism_class->interpolate_scanline_ayuv = deinterlace_scanline_weave_packed; dism_class->interpolate_scanline_yuy2 = deinterlace_scanline_weave_packed;