[MOVED FROM BAD 17/56] gst/deinterlace2/tvtime/greedy.c: Don't use scanlines function...
authorSebastian Dröge <slomo@circular-chaos.org>
Sat, 28 Jun 2008 18:10:52 +0000 (18:10 +0000)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Wed, 13 May 2009 08:33:58 +0000 (10:33 +0200)
Original commit message from CVS:
* gst/deinterlace2/tvtime/greedy.c:
(deinterlace_greedy_packed422_scanline_c),
(deinterlace_greedy_packed422_scanline_mmx),
(deinterlace_greedy_packed422_scanline_mmxext),
(deinterlace_frame_di_greedy):
Don't use scanlines function from gstdeinterlace2 as it's
not appropiate for this method. Instead implement deinterlace_frame
function by taking the one from greedyh.
* gst/deinterlace2/tvtime/greedyh.c: (greedyDScaler_C):
Small fix for the C implementation.
* gst/deinterlace2/tvtime/vfir.c: (deinterlace_frame_vfir):
Don't use the scanlines function from gstdeinterlace2 as it's only
used for this method and will be removed. Instead implement
deinterlace_frame function and make it a bit more efficient.
* gst/deinterlace2/gstdeinterlace2.c:
(gst_deinterlace2_class_init), (gst_deinterlace2_set_method),
(gst_deinterlace2_push_history), (gst_deinterlace2_chain),
(gst_deinterlace2_setcaps), (gst_deinterlace2_sink_event),
(gst_deinterlace2_change_state), (gst_deinterlace2_src_event),
(gst_deinterlace2_src_query):
Fix coding style and remove scanlines function as it's unused now.

gst/deinterlace2/gstdeinterlace2.c
gst/deinterlace2/tvtime/greedy.c
gst/deinterlace2/tvtime/greedyh.c
gst/deinterlace2/tvtime/vfir.c

index 04ba4f0..64557d4 100644 (file)
@@ -125,29 +125,21 @@ static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
     );
 
 static void gst_deinterlace2_finalize (GObject * object);
-
 static void gst_deinterlace2_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
 static void gst_deinterlace2_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
 static gboolean gst_deinterlace2_setcaps (GstPad * pad, GstCaps * caps);
-
 static gboolean gst_deinterlace2_sink_event (GstPad * pad, GstEvent * event);
-
 static GstFlowReturn gst_deinterlace2_chain (GstPad * pad, GstBuffer * buffer);
-
 static GstStateChangeReturn gst_deinterlace2_change_state (GstElement * element,
     GstStateChange transition);
 
 static gboolean gst_deinterlace2_src_event (GstPad * pad, GstEvent * event);
-
 static gboolean gst_deinterlace2_src_query (GstPad * pad, GstQuery * query);
-
 static const GstQueryType *gst_deinterlace2_src_query_types (GstPad * pad);
 
-static void gst_deinterlace2_deinterlace_scanlines (GstDeinterlace2 * object);
-
 static void gst_deinterlace2_reset (GstDeinterlace2 * object);
 
 GST_BOILERPLATE (GstDeinterlace2, gst_deinterlace2, GstElement,
@@ -198,7 +190,6 @@ gst_deinterlace2_class_init (GstDeinterlace2Class * klass)
           GST_DEINTERLACE2_ALL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
       );
 
-
   g_object_class_install_property (gobject_class, ARG_FIELDS,
       g_param_spec_enum ("tff",
           "tff",
@@ -314,14 +305,9 @@ gst_deinterlace2_set_method (GstDeinterlace2 * object,
       GST_WARNING ("Invalid Deinterlacer Method");
   }
 
-
-  if (object->method->deinterlace_frame == NULL)
-    object->method->deinterlace_frame = gst_deinterlace2_deinterlace_scanlines;
-
   /* TODO: if current method requires less fields in the history,
      pop the diff from field_history.
    */
-
 }
 
 static void
@@ -422,9 +408,7 @@ static void
 gst_deinterlace2_push_history (GstDeinterlace2 * object, GstBuffer * buffer)
 {
   int i = 1;
-
   GstClockTime timestamp;
-
   GstClockTime field_diff;
 
   g_assert (object->history_count < MAX_FIELD_HISTORY - 2);
@@ -470,122 +454,11 @@ gst_deinterlace2_push_history (GstDeinterlace2 * object, GstBuffer * buffer)
   GST_DEBUG ("push, size(history): %d", object->history_count);
 }
 
-/* some methods support only deinterlace_/copy_scanline functions.
-   This funtion calls them in the right manner. */
-static void
-gst_deinterlace2_deinterlace_scanlines (GstDeinterlace2 * object)
-{
-
-  gint line = 1;
-
-  gint cur_field_idx = object->history_count - object->method->fields_required;
-
-  GST_INFO ("cur_field_idx: %d", cur_field_idx);
-
-  guint8 *out_data = GST_BUFFER_DATA (object->out_buf);
-
-  guint8 *cur_field =
-      GST_BUFFER_DATA (object->field_history[cur_field_idx].buf);
-  guint8 *last_field = NULL;
-
-  guint8 *second_last_field = NULL;
-
-  /* method can just handle up to 3 history fields, 
-     bcs until now there isn't a plugin (with interp./copy scanline methods)
-     that uses more */
-  g_assert (object->method->fields_required <= 3);
-
-  if (object->method->fields_required >= 2) {
-    last_field = GST_BUFFER_DATA (object->field_history[cur_field_idx + 1].buf);
-  }
-  if (object->method->fields_required >= 3) {
-    second_last_field =
-        GST_BUFFER_DATA (object->field_history[cur_field_idx + 2].buf);
-  }
-
-  if (object->field_history[cur_field_idx].flags == PICTURE_INTERLACED_BOTTOM) {
-    /* double the first scanline of the bottom field */
-    blit_packed422_scanline (out_data, cur_field, object->frame_width);
-    out_data += object->output_stride;
-  }
-
-  blit_packed422_scanline (out_data, cur_field, object->frame_width);
-  out_data += object->output_stride;
-  line++;
-
-  for (; line <= object->field_height;) {
-    deinterlace_scanline_data_t data;
-
-    /* interp. scanline */
-    data.t0 = cur_field;
-    data.b0 = cur_field + object->field_stride;
-
-    if (last_field != NULL) {
-      data.tt1 = last_field;
-      data.m1 = last_field + object->field_stride;
-      data.bb1 = last_field + (object->field_stride * 2);
-
-      last_field += object->field_stride;
-    }
-
-    if (second_last_field != NULL) {
-      data.t2 = second_last_field;
-      data.b2 = second_last_field + object->field_stride;
-    }
-
-    /* set valid data for corner cases */
-    if (line == 2) {
-      data.tt1 = data.bb1;
-    } else if (line == object->field_height) {
-      data.bb1 = data.tt1;
-    }
-
-    object->method->interpolate_scanline (object, &data, out_data);
-    out_data += object->output_stride;
-
-    /* copy a scanline */
-    data.tt0 = cur_field;
-    data.m0 = cur_field + (object->field_stride);
-    data.bb0 = cur_field + (object->field_stride * 2);
-    cur_field += object->field_stride;
-
-    if (last_field != NULL) {
-      data.t1 = last_field;
-      data.b1 = last_field + object->field_stride;
-    }
-
-    if (second_last_field != NULL) {
-      data.tt2 = second_last_field;
-      data.m2 = second_last_field + (object->field_stride);
-      data.bb2 = second_last_field + (object->field_stride * 2);
-      second_last_field += object->field_stride;
-    }
-
-    /* set valid data for corner cases */
-    if (line == object->field_height) {
-      data.bb0 = data.tt0;
-      data.bb2 = data.tt2;
-      data.b1 = data.t1;
-    }
-
-    object->method->copy_scanline (object, &data, out_data);
-    out_data += object->output_stride;
-    line++;
-  }
-
-  if (object->field_history[cur_field_idx].flags == PICTURE_INTERLACED_TOP) {
-    /* double the last scanline of the top field */
-    blit_packed422_scanline (out_data, cur_field, object->frame_width);
-  }
-}
-
 static GstFlowReturn
 gst_deinterlace2_chain (GstPad * pad, GstBuffer * buf)
 {
   GstDeinterlace2 *object = NULL;
-
   GstClockTime timestamp;
-
   GstFlowReturn ret = GST_FLOW_OK;
 
   object = GST_DEINTERLACE2 (GST_PAD_PARENT (pad));
@@ -750,8 +623,7 @@ gst_deinterlace2_setcaps (GstPad * pad, GstCaps * caps)
     othercaps = gst_caps_ref (caps);
   }
 
-  if (                          /*!gst_pad_accept_caps (otherpad, othercaps)
-                                   || */ !gst_pad_set_caps (otherpad, othercaps))
+  if (!gst_pad_set_caps (otherpad, othercaps))
     goto caps_not_accepted;
   gst_caps_unref (othercaps);
 
@@ -797,7 +669,6 @@ static gboolean
 gst_deinterlace2_sink_event (GstPad * pad, GstEvent * event)
 {
   gboolean res = TRUE;
-
   GstDeinterlace2 *object = GST_DEINTERLACE2 (gst_pad_get_parent (pad));
 
   GST_LOG_OBJECT (pad, "received %s event", GST_EVENT_TYPE_NAME (event));
@@ -822,7 +693,6 @@ static GstStateChangeReturn
 gst_deinterlace2_change_state (GstElement * element, GstStateChange transition)
 {
   GstStateChangeReturn ret;
-
   GstDeinterlace2 *object = GST_DEINTERLACE2 (element);
 
   switch (transition) {
@@ -858,7 +728,6 @@ static gboolean
 gst_deinterlace2_src_event (GstPad * pad, GstEvent * event)
 {
   GstDeinterlace2 *object = GST_DEINTERLACE2 (gst_pad_get_parent (pad));
-
   gboolean res;
 
   GST_DEBUG_OBJECT (pad, "received %s event", GST_EVENT_TYPE_NAME (event));
@@ -878,7 +747,6 @@ static gboolean
 gst_deinterlace2_src_query (GstPad * pad, GstQuery * query)
 {
   GstDeinterlace2 *object = GST_DEINTERLACE2 (gst_pad_get_parent (pad));
-
   gboolean res = FALSE;
 
   GST_LOG_OBJECT (object, "%s query", GST_QUERY_TYPE_NAME (query));
@@ -887,9 +755,7 @@ gst_deinterlace2_src_query (GstPad * pad, GstQuery * query)
     case GST_QUERY_LATENCY:
     {
       GstClockTime min, max;
-
       gboolean live;
-
       GstPad *peer;
 
       if ((peer = gst_pad_get_peer (object->sinkpad))) {
index 16b9831..2448d1d 100644 (file)
 // I'd intended this to be part of a larger more elaborate method added to 
 // Blended Clip but this give too good results for the CPU to ignore here.
 
-static void
-copy_scanline (GstDeinterlace2 * object,
-    deinterlace_scanline_data_t * data, uint8_t * output)
-{
-  blit_packed422_scanline (output, data->m1, object->frame_width);
-}
-
 static const int GreedyMaxComb = 15;
 
 static inline void
-deinterlace_greedy_packed422_scanline_c (GstDeinterlace2 * object,
-    uint8_t * m0, uint8_t * t1, uint8_t * b1, uint8_t * m2, uint8_t * output,
-    int width)
+deinterlace_greedy_packed422_scanline_c (uint8_t * m0, uint8_t * t1,
+    uint8_t * b1, uint8_t * m2, uint8_t * output, int width)
 {
   int avg, l2_diff, lp2_diff, max, min, best;
 
@@ -112,9 +104,8 @@ deinterlace_greedy_packed422_scanline_c (GstDeinterlace2 * object,
 #ifdef HAVE_CPU_I386
 #include "mmx.h"
 static void
-deinterlace_greedy_packed422_scanline_mmx (GstDeinterlace2 * object,
-    uint8_t * m0, uint8_t * t1, uint8_t * b1, uint8_t * m2, uint8_t * output,
-    int width)
+deinterlace_greedy_packed422_scanline_mmx (uint8_t * m0, uint8_t * t1,
+    uint8_t * b1, uint8_t * m2, uint8_t * output, int width)
 {
   mmx_t MaxComb;
 
@@ -222,16 +213,14 @@ deinterlace_greedy_packed422_scanline_mmx (GstDeinterlace2 * object,
   }
   emms ();
   if (width > 0)
-    deinterlace_greedy_packed422_scanline_c (object, m0, t1, b1, m2, output,
-        width);
+    deinterlace_greedy_packed422_scanline_c (m0, t1, b1, m2, output, width);
 }
 
 #include "sse.h"
 
 static void
-deinterlace_greedy_packed422_scanline_mmxext (GstDeinterlace2 * object,
-    uint8_t * m0, uint8_t * t1, uint8_t * b1, uint8_t * m2, uint8_t * output,
-    int width)
+deinterlace_greedy_packed422_scanline_mmxext (uint8_t * m0, uint8_t * t1,
+    uint8_t * b1, uint8_t * m2, uint8_t * output, int width)
 {
   mmx_t MaxComb;
 
@@ -316,47 +305,104 @@ deinterlace_greedy_packed422_scanline_mmxext (GstDeinterlace2 * object,
   emms ();
 
   if (width > 0)
-    deinterlace_greedy_packed422_scanline_c (object, m0, t1, b1, m2, output,
-        width);
+    deinterlace_greedy_packed422_scanline_c (m0, t1, b1, m2, output, width);
 }
 
 #endif
 
 static void
-deinterlace_greedy_packed422_scanline (GstDeinterlace2 * object,
-    deinterlace_scanline_data_t * data, uint8_t * output)
+deinterlace_frame_di_greedy (GstDeinterlace2 * object)
 {
+  void (*func) (uint8_t * L2, uint8_t * L1, uint8_t * L3, uint8_t * L2P,
+      uint8_t * Dest, int size);
+
+  int InfoIsOdd = 0;
+  int Line;
+  unsigned int Pitch = object->field_stride;
+  unsigned char *L1;            // ptr to Line1, of 3
+  unsigned char *L2;            // ptr to Line2, the weave line
+  unsigned char *L3;            // ptr to Line3
+
+  unsigned char *L2P;           // ptr to prev Line2
+  unsigned char *Dest = GST_BUFFER_DATA (object->out_buf);
+
 #ifdef HAVE_CPU_I386
   if (object->cpu_feature_flags & OIL_IMPL_FLAG_MMXEXT) {
-    deinterlace_greedy_packed422_scanline_mmxext (object, data->m0, data->t1,
-        data->b1, data->m2, output, 2 * object->frame_width);
+    func = deinterlace_greedy_packed422_scanline_mmxext;
   } else if (object->cpu_feature_flags & OIL_IMPL_FLAG_MMX) {
-    deinterlace_greedy_packed422_scanline_mmx (object, data->m0, data->t1,
-        data->b1, data->m2, output, 2 * object->frame_width);
+    func = deinterlace_greedy_packed422_scanline_mmx;
   } else {
-    deinterlace_greedy_packed422_scanline_c (object, data->m0, data->t1,
-        data->b1, data->m2, output, 2 * object->frame_width);
+    func = deinterlace_greedy_packed422_scanline_c;
   }
 #else
-  deinterlace_greedy_packed422_scanline_c (object, data->m0, data->t1, data->b1,
-      data->m2, output, 2 * object->frame_width);
+  func = deinterlace_greedy_packed422_scanline_c;
 #endif
-}
 
+  // 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 (object->field_history[object->history_count - 1].flags ==
+      PICTURE_INTERLACED_BOTTOM) {
+    InfoIsOdd = 1;
+
+    L1 = GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf);
+    L2 = GST_BUFFER_DATA (object->field_history[object->history_count - 1].buf);
+    L3 = L1 + Pitch;
+    L2P =
+        GST_BUFFER_DATA (object->field_history[object->history_count - 3].buf);
+
+    // copy first even line
+    object->pMemcpy (Dest, L1, object->line_length);
+    Dest += object->output_stride;
+  } else {
+    InfoIsOdd = 0;
+    L1 = GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf);
+    L2 = GST_BUFFER_DATA (object->field_history[object->history_count -
+            1].buf) + Pitch;
+    L3 = L1 + Pitch;
+    L2P =
+        GST_BUFFER_DATA (object->field_history[object->history_count - 3].buf) +
+        Pitch;
+
+    // copy first even line
+    object->pMemcpy (Dest, GST_BUFFER_DATA (object->field_history[0].buf),
+        object->line_length);
+    Dest += object->output_stride;
+    // then first odd line
+    object->pMemcpy (Dest, L1, object->line_length);
+    Dest += object->output_stride;
+  }
+
+  for (Line = 0; Line < (object->field_height - 1); ++Line) {
+    func (L2, L1, L3, L2P, Dest, object->line_length);
+    Dest += object->output_stride;
+    object->pMemcpy (Dest, L3, object->line_length);
+    Dest += object->output_stride;
+
+    L1 += Pitch;
+    L2 += Pitch;
+    L3 += Pitch;
+    L2P += Pitch;
+  }
+
+  if (InfoIsOdd) {
+    object->pMemcpy (Dest, L2, object->line_length);
+  }
+}
 
 static deinterlace_method_t greedyl_method = {
   0,                            //DEINTERLACE_PLUGIN_API_VERSION,
   "Motion Adaptive: Simple Detection",
   "AdaptiveSimple",
-  3,
+  4,
   0,
   0,
   0,
   0,
   1,
-  copy_scanline,
-  deinterlace_greedy_packed422_scanline,
   0,
+  0,
+  deinterlace_frame_di_greedy,
   {"Uses heuristics to detect motion in the input",
         "frames and reconstruct image detail where",
         "possible.  Use this for high quality output",
index f9d33e7..5cda7d5 100644 (file)
@@ -85,6 +85,11 @@ greedyDScaler_C (uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P,
     avg_l = (l1_l + l3_l) / 2;
     avg_c = (l1_c + l3_c) / 2;
 
+    if (Pos == 0) {
+      avg_l__1 = avg_l;
+      avg_c__1 = avg_c;
+    }
+
     /* Average of next L1 and next L3 */
     avg_l_1 = (l1_1_l + l3_1_l) / 2;
     avg_c_1 = (l1_1_c + l3_1_c) / 2;
index 4b7a0c0..53d233e 100644 (file)
@@ -127,45 +127,73 @@ deinterlace_line_mmx (uint8_t * dst, uint8_t * lum_m4,
 }
 #endif
 
-/*
- * The commented-out method below that uses the bottom_field member is more
- * like the filter as specified in the MPEG2 spec, but it doesn't seem to
- * have the desired effect.
- */
-
 static void
-deinterlace_scanline_vfir (GstDeinterlace2 * object,
-    deinterlace_scanline_data_t * data, uint8_t * output)
+deinterlace_frame_vfir (GstDeinterlace2 * object)
 {
+  void (*func) (uint8_t * dst, uint8_t * lum_m4,
+      uint8_t * lum_m3, uint8_t * lum_m2,
+      uint8_t * lum_m1, uint8_t * lum, int size);
+  gint line = 0;
+  uint8_t *cur_field, *last_field;
+  uint8_t *t0, *b0, *tt1, *m1, *bb1, *out_data;
+
 #ifdef HAVE_CPU_I386
   if (object->cpu_feature_flags & OIL_IMPL_FLAG_MMX) {
-    deinterlace_line_mmx (output, data->tt1, data->t0, data->m1, data->b0,
-        data->bb1, object->frame_width * 2);
+    func = deinterlace_line_mmx;
   } else {
-    deinterlace_line_c (output, data->tt1, data->t0, data->m1, data->b0,
-        data->bb1, object->frame_width * 2);
+    func = deinterlace_line_c;
   }
 #else
-  deinterlace_line_c (output, data->tt1, data->t0, data->m1, data->b0,
-      data->bb1, object->frame_width * 2);
+  func = deinterlace_line_c;
 #endif
-  // blit_packed422_scanline( output, data->m1, width );
-}
 
-static void
-copy_scanline (GstDeinterlace2 * object,
-    deinterlace_scanline_data_t * data, uint8_t * output)
-{
-  blit_packed422_scanline (output, data->m0, object->frame_width);
-  /*
-     if( data->bottom_field ) {
-     deinterlace_line( output, data->tt2, data->t1, data->m2, data->b1, data->bb2, width*2 );
-     } else {
-     deinterlace_line( output, data->tt0, data->t1, data->m0, data->b1, data->bb0, width*2 );
-     }
-   */
-}
+  cur_field =
+      GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf);
+  last_field =
+      GST_BUFFER_DATA (object->field_history[object->history_count - 1].buf);
+
+  out_data = GST_BUFFER_DATA (object->out_buf);
+
+  if (object->field_history[object->history_count - 2].flags ==
+      PICTURE_INTERLACED_BOTTOM) {
+    blit_packed422_scanline (out_data, cur_field, object->frame_width);
+    out_data += object->output_stride;
+  }
 
+  blit_packed422_scanline (out_data, cur_field, object->frame_width);
+  out_data += object->output_stride;
+  line++;
+
+  for (; line < object->field_height; line++) {
+    t0 = cur_field;
+    b0 = cur_field + object->field_stride;
+
+    tt1 = last_field;
+    m1 = last_field + object->field_stride;
+    bb1 = last_field + (object->field_stride * 2);
+
+    /* set valid data for corner cases */
+    if (line == 1) {
+      tt1 = bb1;
+    } else if (line == object->field_height - 1) {
+      bb1 = tt1;
+    }
+
+    func (out_data, tt1, t0, m1, b0, bb1, object->line_length);
+    out_data += object->output_stride;
+    cur_field += object->field_stride;
+    last_field += object->field_stride;
+
+    blit_packed422_scanline (out_data, cur_field, object->frame_width);
+    out_data += object->output_stride;
+  }
+
+  if (object->field_history[object->history_count - 2].flags ==
+      PICTURE_INTERLACED_TOP) {
+    /* double the last scanline of the top field */
+    blit_packed422_scanline (out_data, cur_field, object->frame_width);
+  }
+}
 
 static deinterlace_method_t vfirmethod = {
   0,                            //DEINTERLACE_PLUGIN_API_VERSION,
@@ -177,9 +205,9 @@ static deinterlace_method_t vfirmethod = {
   0,
   0,
   1,
-  deinterlace_scanline_vfir,
-  copy_scanline,
   0,
+  0,
+  deinterlace_frame_vfir,
   {"Avoids flicker by blurring consecutive frames",
         "of input.  Use this if you want to run your",
         "monitor at an arbitrary refresh rate and not",