deinterlace: change field handling through methods
authorDavid Schleef <ds@schleef.org>
Mon, 11 Jul 2011 04:40:20 +0000 (21:40 -0700)
committerDavid Schleef <ds@schleef.org>
Sun, 21 Aug 2011 22:15:14 +0000 (15:15 -0700)
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.

13 files changed:
gst/deinterlace/gstdeinterlace.c
gst/deinterlace/gstdeinterlace.h
gst/deinterlace/gstdeinterlacemethod.c
gst/deinterlace/gstdeinterlacemethod.h
gst/deinterlace/tvtime/greedy.c
gst/deinterlace/tvtime/greedyh.c
gst/deinterlace/tvtime/linearblend.c
gst/deinterlace/tvtime/scalerbob.c
gst/deinterlace/tvtime/tomsmocomp/TomsMoCompAll.inc
gst/deinterlace/tvtime/vfir.c
gst/deinterlace/tvtime/weave.c
gst/deinterlace/tvtime/weavebff.c
gst/deinterlace/tvtime/weavetff.c

index c4d6cf9..4e1b488 100644 (file)
@@ -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) {
index ac97a55..a5a69a3 100644 (file)
@@ -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
index fe5996b..9927868 100644 (file)
@@ -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);
   }
 }
index 11e2c35..a50ecbd 100644 (file)
@@ -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.
index dcb495b..5775132 100644 (file)
@@ -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;
index d1e4fd6..93da8cd 100644 (file)
@@ -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,
index a343d0f..189e1aa 100644 (file)
@@ -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;
index bac4c62..adc285a 100644 (file)
@@ -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;
index 23903b3..f8ffe1e 100644 (file)
@@ -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];
index c589dd7..6442a82 100644 (file)
@@ -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) {
index 8d49979..1501b1a 100644 (file)
@@ -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;
index b96da1f..b11395c 100644 (file)
@@ -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;
index b645b0b..3c60613 100644 (file)
@@ -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;