deinterlace: Add support for AYUV
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Wed, 5 May 2010 14:06:51 +0000 (16:06 +0200)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Wed, 5 May 2010 14:06:51 +0000 (16:06 +0200)
13 files changed:
gst/deinterlace/gstdeinterlace.c
gst/deinterlace/gstdeinterlacemethod.c
gst/deinterlace/gstdeinterlacemethod.h
gst/deinterlace/tvtime/greedy.c
gst/deinterlace/tvtime/greedyh.asm
gst/deinterlace/tvtime/greedyh.c
gst/deinterlace/tvtime/linear.c
gst/deinterlace/tvtime/linearblend.c
gst/deinterlace/tvtime/scalerbob.c
gst/deinterlace/tvtime/vfir.c
gst/deinterlace/tvtime/weave.c
gst/deinterlace/tvtime/weavebff.c
gst/deinterlace/tvtime/weavetff.c

index 8554c9d..8987764 100644 (file)
@@ -155,8 +155,8 @@ gst_deinterlace_modes_get_type (void)
 static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("Y444") ";"
-        GST_VIDEO_CAPS_YUV ("YUY2") ";" GST_VIDEO_CAPS_YUV ("YVYU") ";"
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") ";" GST_VIDEO_CAPS_YUV ("Y444")
+        ";" GST_VIDEO_CAPS_YUV ("YUY2") ";" GST_VIDEO_CAPS_YUV ("YVYU") ";"
         GST_VIDEO_CAPS_YUV ("Y42B") ";" GST_VIDEO_CAPS_YUV ("I420") ";"
         GST_VIDEO_CAPS_YUV ("YV12") ";" GST_VIDEO_CAPS_YUV ("Y41B"))
     );
@@ -164,8 +164,8 @@ static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
 static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("Y444") ";"
-        GST_VIDEO_CAPS_YUV ("YUY2") ";" GST_VIDEO_CAPS_YUV ("YVYU") ";"
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") ";" GST_VIDEO_CAPS_YUV ("Y444")
+        ";" GST_VIDEO_CAPS_YUV ("YUY2") ";" GST_VIDEO_CAPS_YUV ("YVYU") ";"
         GST_VIDEO_CAPS_YUV ("Y42B") ";" GST_VIDEO_CAPS_YUV ("I420") ";"
         GST_VIDEO_CAPS_YUV ("YV12") ";" GST_VIDEO_CAPS_YUV ("Y41B"))
     );
index 6db1cad..e93d5c3 100644 (file)
@@ -68,6 +68,8 @@ gst_deinterlace_method_supported_impl (GstDeinterlaceMethodClass * klass,
       return (klass->deinterlace_frame_y42b != NULL);
     case GST_VIDEO_FORMAT_Y41B:
       return (klass->deinterlace_frame_y41b != NULL);
+    case GST_VIDEO_FORMAT_AYUV:
+      return (klass->deinterlace_frame_ayuv != NULL);
     default:
       return FALSE;
   }
@@ -129,6 +131,9 @@ gst_deinterlace_method_setup_impl (GstDeinterlaceMethod * self,
     case GST_VIDEO_FORMAT_Y41B:
       self->deinterlace_frame = klass->deinterlace_frame_y41b;
       break;
+    case GST_VIDEO_FORMAT_AYUV:
+      self->deinterlace_frame = klass->deinterlace_frame_ayuv;
+      break;
     default:
       self->deinterlace_frame = NULL;
       break;
@@ -195,6 +200,9 @@ gst_deinterlace_simple_method_supported (GstDeinterlaceMethodClass * mklass,
     case GST_VIDEO_FORMAT_YVYU:
       return (klass->interpolate_scanline_yvyu != NULL
           && klass->copy_scanline_yvyu != NULL);
+    case GST_VIDEO_FORMAT_AYUV:
+      return (klass->interpolate_scanline_ayuv != NULL
+          && klass->copy_scanline_ayuv != NULL);
     case GST_VIDEO_FORMAT_I420:
     case GST_VIDEO_FORMAT_YV12:
     case GST_VIDEO_FORMAT_Y444:
@@ -613,6 +621,10 @@ gst_deinterlace_simple_method_setup (GstDeinterlaceMethod * method,
       self->interpolate_scanline_packed = klass->interpolate_scanline_yvyu;
       self->copy_scanline_packed = klass->copy_scanline_yvyu;
       break;
+    case GST_VIDEO_FORMAT_AYUV:
+      self->interpolate_scanline_packed = klass->interpolate_scanline_ayuv;
+      self->copy_scanline_packed = klass->copy_scanline_ayuv;
+      break;
     case GST_VIDEO_FORMAT_I420:
     case GST_VIDEO_FORMAT_YV12:
     case GST_VIDEO_FORMAT_Y444:
@@ -639,6 +651,8 @@ gst_deinterlace_simple_method_class_init (GstDeinterlaceSimpleMethodClass
 {
   GstDeinterlaceMethodClass *dm_class = (GstDeinterlaceMethodClass *) klass;
 
+  dm_class->deinterlace_frame_ayuv =
+      gst_deinterlace_simple_method_deinterlace_frame_packed;
   dm_class->deinterlace_frame_yuy2 =
       gst_deinterlace_simple_method_deinterlace_frame_packed;
   dm_class->deinterlace_frame_yvyu =
index 4ae85c1..57446a1 100644 (file)
@@ -97,6 +97,7 @@ struct _GstDeinterlaceMethodClass {
   GstDeinterlaceMethodDeinterlaceFunction deinterlace_frame_y444;
   GstDeinterlaceMethodDeinterlaceFunction deinterlace_frame_y42b;
   GstDeinterlaceMethodDeinterlaceFunction deinterlace_frame_y41b;
+  GstDeinterlaceMethodDeinterlaceFunction deinterlace_frame_ayuv;
 
   const gchar *name;
   const gchar *nick;
@@ -178,6 +179,8 @@ struct _GstDeinterlaceSimpleMethodClass {
   GstDeinterlaceSimpleMethodFunction copy_scanline_yuy2;
   GstDeinterlaceSimpleMethodFunction interpolate_scanline_yvyu;
   GstDeinterlaceSimpleMethodFunction copy_scanline_yvyu;
+  GstDeinterlaceSimpleMethodFunction interpolate_scanline_ayuv;
+  GstDeinterlaceSimpleMethodFunction copy_scanline_ayuv;
 
   /* Planar formats */
   GstDeinterlaceSimpleMethodFunction copy_scanline_planar_y;
index 36deb8f..8527fa3 100644 (file)
@@ -573,6 +573,7 @@ gst_deinterlace_method_greedy_l_class_init (GstDeinterlaceMethodGreedyLClass *
   dim_class->deinterlace_frame_i420 = deinterlace_frame_di_greedy_planar;
   dim_class->deinterlace_frame_yv12 = deinterlace_frame_di_greedy_planar;
   dim_class->deinterlace_frame_y41b = deinterlace_frame_di_greedy_planar;
+  dim_class->deinterlace_frame_ayuv = deinterlace_frame_di_greedy_planar;
 
 #ifdef BUILD_X86_ASM
   if (cpu_flags & OIL_IMPL_FLAG_MMXEXT) {
index 428148c..3e6b414 100644 (file)
@@ -67,7 +67,7 @@ FUNCT_NAME_YUY2 (GstDeinterlaceMethodGreedyH *self, const guint8 * L1, const gui
   i = 0xffffffff - 256;
   QW256B = i << 48 | i << 32 | i << 16 | i;     // save a couple instr on PMINSW instruct.
 
-  LoopCtr = width / 4 - 1;       // there are LineLength / 4 qwords per line but do 1 less, adj at end of loop
+  LoopCtr = width / 8 - 1;       // there are LineLength / 4 qwords per line but do 1 less, adj at end of loop
 
   // For ease of reading, the comments below assume that we're operating on an odd
   // field (i.e., that InfoIsOdd is true).  Assume the obvious for even lines..
index 3221e5d..8448537 100644 (file)
@@ -61,11 +61,123 @@ typedef struct
 {
   GstDeinterlaceMethodClass parent_class;
   ScanlineFunction scanline_yuy2;       /* This is for YVYU too */
+  ScanlineFunction scanline_ayuv;
   ScanlineFunction scanline_planar_y;
   ScanlineFunction scanline_planar_uv;
 } GstDeinterlaceMethodGreedyHClass;
 
 static void
+greedyh_scanline_C_ayuv (GstDeinterlaceMethodGreedyH * self, const guint8 * L1,
+    const guint8 * L2, const guint8 * L3, const guint8 * L2P, guint8 * Dest,
+    gint width)
+{
+  gint Pos, Comp;
+  guint8 l1, l1_1, l3, l3_1;
+  guint8 avg, avg_1;
+  guint8 avg__1[4] = { 0, };
+  guint8 avg_s;
+  guint8 avg_sc;
+  guint8 best;
+  guint16 mov;
+  guint8 out;
+  guint8 l2, lp2;
+  guint8 l2_diff, lp2_diff;
+  guint8 min, max;
+  guint max_comb = self->max_comb;
+  guint motion_sense = self->motion_sense;
+  guint motion_threshold = self->motion_threshold;
+
+  width /= 4;
+  for (Pos = 0; Pos < width; Pos++) {
+    for (Comp = 0; Comp < 4; Comp++) {
+      l1 = L1[0];
+      l3 = L3[0];
+
+      if (Pos == width - 1) {
+        l1_1 = l1;
+        l3_1 = l3;
+      } else {
+        l1_1 = L1[4];
+        l3_1 = L3[4];
+      }
+
+      /* Average of L1 and L3 */
+      avg = (l1 + l3) / 2;
+
+      if (Pos == 0) {
+        avg__1[Comp] = avg;
+      }
+
+      /* Average of next L1 and next L3 */
+      avg_1 = (l1_1 + l3_1) / 2;
+
+      /* Calculate average of one pixel forward and previous */
+      avg_s = (avg__1[Comp] + avg_1) / 2;
+
+      /* Calculate average of center and surrounding pixels */
+      avg_sc = (avg + avg_s) / 2;
+
+      /* move forward */
+      avg__1[Comp] = avg;
+
+      /* Get best L2/L2P, i.e. least diff from above average */
+      l2 = L2[0];
+      lp2 = L2P[0];
+
+      l2_diff = ABS (l2 - avg_sc);
+
+      lp2_diff = ABS (lp2 - avg_sc);
+
+      if (l2_diff > lp2_diff)
+        best = lp2;
+      else
+        best = l2;
+
+      /* Clip this best L2/L2P by L1/L3 and allow to differ by GreedyMaxComb */
+      max = MAX (l1, l3);
+      min = MIN (l1, l3);
+
+      if (max < 256 - max_comb)
+        max += max_comb;
+      else
+        max = 255;
+
+      if (min > max_comb)
+        min -= max_comb;
+      else
+        min = 0;
+
+      out = CLAMP (best, min, max);
+
+      if (Comp < 2) {
+        /* Do motion compensation for luma, i.e. how much
+         * the weave pixel differs */
+        mov = ABS (l2 - lp2);
+        if (mov > motion_threshold)
+          mov -= motion_threshold;
+        else
+          mov = 0;
+
+        mov = mov * motion_sense;
+        if (mov > 256)
+          mov = 256;
+
+        /* Weighted sum on clipped weave pixel and average */
+        out = (out * (256 - mov) + avg_sc * mov) / 256;
+      }
+
+      Dest[0] = out;
+
+      Dest += 1;
+      L1 += 1;
+      L2 += 1;
+      L3 += 1;
+      L2P += 1;
+    }
+  }
+}
+
+static void
 greedyh_scanline_C_yuy2 (GstDeinterlaceMethodGreedyH * self, const guint8 * L1,
     const guint8 * L2, const guint8 * L3, const guint8 * L2P, guint8 * Dest,
     gint width)
@@ -87,6 +199,7 @@ greedyh_scanline_C_yuy2 (GstDeinterlaceMethodGreedyH * self, const guint8 * L1,
   guint motion_sense = self->motion_sense;
   guint motion_threshold = self->motion_threshold;
 
+  width /= 2;
   for (Pos = 0; Pos < width; Pos++) {
     l1_l = L1[0];
     l1_c = L1[1];
@@ -473,6 +586,9 @@ deinterlace_frame_di_greedyh_packed (GstDeinterlaceMethod * method,
     case GST_VIDEO_FORMAT_YVYU:
       scanline = klass->scanline_yuy2;
       break;
+    case GST_VIDEO_FORMAT_AYUV:
+      scanline = klass->scanline_ayuv;
+      break;
     default:
       g_assert_not_reached ();
       break;
@@ -728,6 +844,7 @@ gst_deinterlace_method_greedy_h_class_init (GstDeinterlaceMethodGreedyHClass *
 
   dim_class->deinterlace_frame_yuy2 = deinterlace_frame_di_greedyh_packed;
   dim_class->deinterlace_frame_yvyu = deinterlace_frame_di_greedyh_packed;
+  dim_class->deinterlace_frame_ayuv = deinterlace_frame_di_greedyh_packed;
   dim_class->deinterlace_frame_y444 = deinterlace_frame_di_greedyh_planar;
   dim_class->deinterlace_frame_i420 = deinterlace_frame_di_greedyh_planar;
   dim_class->deinterlace_frame_yv12 = deinterlace_frame_di_greedyh_planar;
@@ -748,6 +865,7 @@ gst_deinterlace_method_greedy_h_class_init (GstDeinterlaceMethodGreedyHClass *
   klass->scanline_yuy2 = greedyh_scanline_C_yuy2;
 #endif
   /* TODO: MMX implementation of these two */
+  klass->scanline_ayuv = greedyh_scanline_C_ayuv;
   klass->scanline_planar_y = greedyh_scanline_C_planar_y;
   klass->scanline_planar_uv = greedyh_scanline_C_planar_uv;
 }
index 1a18850..5b4a09b 100644 (file)
@@ -292,6 +292,7 @@ gst_deinterlace_method_linear_class_init (GstDeinterlaceMethodLinearClass *
 
   dism_class->interpolate_scanline_yuy2 = deinterlace_scanline_linear_packed_c;
   dism_class->interpolate_scanline_yvyu = deinterlace_scanline_linear_packed_c;
+  dism_class->interpolate_scanline_ayuv = deinterlace_scanline_linear_packed_c;
   dism_class->interpolate_scanline_planar_y =
       deinterlace_scanline_linear_planar_y_c;
   dism_class->interpolate_scanline_planar_u =
@@ -301,6 +302,8 @@ gst_deinterlace_method_linear_class_init (GstDeinterlaceMethodLinearClass *
 
 #ifdef BUILD_X86_ASM
   if (cpu_flags & OIL_IMPL_FLAG_MMXEXT) {
+    dism_class->interpolate_scanline_ayuv =
+        deinterlace_scanline_linear_packed_mmxext;
     dism_class->interpolate_scanline_yuy2 =
         deinterlace_scanline_linear_packed_mmxext;
     dism_class->interpolate_scanline_yvyu =
@@ -312,6 +315,8 @@ gst_deinterlace_method_linear_class_init (GstDeinterlaceMethodLinearClass *
     dism_class->interpolate_scanline_planar_v =
         deinterlace_scanline_linear_planar_v_mmxext;
   } else if (cpu_flags & OIL_IMPL_FLAG_MMX) {
+    dism_class->interpolate_scanline_ayuv =
+        deinterlace_scanline_linear_packed_mmx;
     dism_class->interpolate_scanline_yuy2 =
         deinterlace_scanline_linear_packed_mmx;
     dism_class->interpolate_scanline_yvyu =
index 8c9b10e..2d7478c 100644 (file)
@@ -326,6 +326,8 @@ static void
       deinterlace_scanline_linear_blend_packed_c;
   dism_class->interpolate_scanline_yvyu =
       deinterlace_scanline_linear_blend_packed_c;
+  dism_class->interpolate_scanline_ayuv =
+      deinterlace_scanline_linear_blend_packed_c;
   dism_class->interpolate_scanline_planar_y =
       deinterlace_scanline_linear_blend_planar_y_c;
   dism_class->interpolate_scanline_planar_u =
@@ -334,6 +336,7 @@ static void
       deinterlace_scanline_linear_blend_planar_v_c;
   dism_class->copy_scanline_yuy2 = deinterlace_scanline_linear_blend2_packed_c;
   dism_class->copy_scanline_yvyu = deinterlace_scanline_linear_blend2_packed_c;
+  dism_class->copy_scanline_ayuv = deinterlace_scanline_linear_blend2_packed_c;
   dism_class->copy_scanline_planar_y =
       deinterlace_scanline_linear_blend2_planar_y_c;
   dism_class->copy_scanline_planar_u =
@@ -347,6 +350,8 @@ static void
         deinterlace_scanline_linear_blend_packed_mmx;
     dism_class->interpolate_scanline_yvyu =
         deinterlace_scanline_linear_blend_packed_mmx;
+    dism_class->interpolate_scanline_ayuv =
+        deinterlace_scanline_linear_blend_packed_mmx;
     dism_class->interpolate_scanline_planar_y =
         deinterlace_scanline_linear_blend_planar_y_mmx;
     dism_class->interpolate_scanline_planar_u =
@@ -354,6 +359,8 @@ static void
     dism_class->interpolate_scanline_planar_v =
         deinterlace_scanline_linear_blend_planar_v_mmx;
 
+    dism_class->copy_scanline_ayuv =
+        deinterlace_scanline_linear_blend2_packed_mmx;
     dism_class->copy_scanline_yuy2 =
         deinterlace_scanline_linear_blend2_packed_mmx;
     dism_class->copy_scanline_yvyu =
index 94bfa92..c64f524 100644 (file)
@@ -82,6 +82,8 @@ gst_deinterlace_method_scaler_bob_class_init (GstDeinterlaceMethodScalerBobClass
   dim_class->nick = "scalerbob";
   dim_class->latency = 0;
 
+  dism_class->interpolate_scanline_ayuv =
+      deinterlace_scanline_scaler_bob_packed;
   dism_class->interpolate_scanline_yuy2 =
       deinterlace_scanline_scaler_bob_packed;
   dism_class->interpolate_scanline_yvyu =
index 7a4824c..71151d0 100644 (file)
@@ -265,6 +265,7 @@ gst_deinterlace_method_vfir_class_init (GstDeinterlaceMethodVFIRClass * klass)
 
 #ifdef BUILD_X86_ASM
   if (cpu_flags & OIL_IMPL_FLAG_MMX) {
+    dism_class->interpolate_scanline_ayuv = deinterlace_line_packed_mmx;
     dism_class->interpolate_scanline_yuy2 = deinterlace_line_packed_mmx;
     dism_class->interpolate_scanline_yvyu = deinterlace_line_packed_mmx;
     dism_class->interpolate_scanline_planar_y = deinterlace_line_planar_y_mmx;
@@ -278,6 +279,7 @@ gst_deinterlace_method_vfir_class_init (GstDeinterlaceMethodVFIRClass * klass)
     dism_class->interpolate_scanline_planar_v = deinterlace_line_planar_v_c;
   }
 #else
+  dism_class->interpolate_scanline_ayuv = deinterlace_line_packed_c;
   dism_class->interpolate_scanline_yuy2 = deinterlace_line_packed_c;
   dism_class->interpolate_scanline_yvyu = deinterlace_line_packed_c;
   dism_class->interpolate_scanline_planar_y = deinterlace_line_planar_y_c;
index 46893db..65f7065 100644 (file)
@@ -115,6 +115,7 @@ gst_deinterlace_method_weave_class_init (GstDeinterlaceMethodWeaveClass * klass)
   dim_class->nick = "weave";
   dim_class->latency = 0;
 
+  dism_class->interpolate_scanline_ayuv = deinterlace_scanline_weave_packed;
   dism_class->interpolate_scanline_yuy2 = deinterlace_scanline_weave_packed;
   dism_class->interpolate_scanline_yvyu = deinterlace_scanline_weave_packed;
   dism_class->interpolate_scanline_planar_y =
@@ -123,6 +124,7 @@ gst_deinterlace_method_weave_class_init (GstDeinterlaceMethodWeaveClass * klass)
       deinterlace_scanline_weave_planar_u;
   dism_class->interpolate_scanline_planar_v =
       deinterlace_scanline_weave_planar_v;
+  dism_class->copy_scanline_ayuv = copy_scanline_packed;
   dism_class->copy_scanline_yuy2 = copy_scanline_packed;
   dism_class->copy_scanline_yvyu = copy_scanline_packed;
   dism_class->copy_scanline_planar_y = copy_scanline_planar_y;
index cba13d3..4e9bb6a 100644 (file)
@@ -136,6 +136,7 @@ gst_deinterlace_method_weave_bff_class_init (GstDeinterlaceMethodWeaveBFFClass *
   dim_class->nick = "weavebff";
   dim_class->latency = 0;
 
+  dism_class->interpolate_scanline_ayuv = deinterlace_scanline_weave_packed;
   dism_class->interpolate_scanline_yuy2 = deinterlace_scanline_weave_packed;
   dism_class->interpolate_scanline_yvyu = deinterlace_scanline_weave_packed;
   dism_class->interpolate_scanline_planar_y =
@@ -144,6 +145,7 @@ gst_deinterlace_method_weave_bff_class_init (GstDeinterlaceMethodWeaveBFFClass *
       deinterlace_scanline_weave_planar_u;
   dism_class->interpolate_scanline_planar_v =
       deinterlace_scanline_weave_planar_v;
+  dism_class->copy_scanline_ayuv = copy_scanline_packed;
   dism_class->copy_scanline_yuy2 = copy_scanline_packed;
   dism_class->copy_scanline_yvyu = copy_scanline_packed;
   dism_class->copy_scanline_planar_y = copy_scanline_planar_y;
index 522d195..50a81c3 100644 (file)
@@ -137,6 +137,7 @@ gst_deinterlace_method_weave_tff_class_init (GstDeinterlaceMethodWeaveTFFClass *
   dim_class->nick = "weavetff";
   dim_class->latency = 0;
 
+  dism_class->interpolate_scanline_ayuv = deinterlace_scanline_weave_packed;
   dism_class->interpolate_scanline_yuy2 = deinterlace_scanline_weave_packed;
   dism_class->interpolate_scanline_yvyu = deinterlace_scanline_weave_packed;
   dism_class->interpolate_scanline_planar_y =
@@ -145,6 +146,7 @@ gst_deinterlace_method_weave_tff_class_init (GstDeinterlaceMethodWeaveTFFClass *
       deinterlace_scanline_weave_planar_u;
   dism_class->interpolate_scanline_planar_v =
       deinterlace_scanline_weave_planar_v;
+  dism_class->copy_scanline_ayuv = copy_scanline_packed;
   dism_class->copy_scanline_yuy2 = copy_scanline_packed;
   dism_class->copy_scanline_yvyu = copy_scanline_packed;
   dism_class->copy_scanline_planar_y = copy_scanline_planar_y;