Merge branch 'master' into 0.11
[platform/upstream/gstreamer.git] / gst / smpte / gstsmpte.c
index 8f1fcc5..afd30a2 100644 (file)
@@ -87,6 +87,7 @@ enum
 #define DEFAULT_PROP_DEPTH     16
 #define DEFAULT_PROP_FPS       0.
 #define DEFAULT_PROP_DURATION  GST_SECOND
+#define DEFAULT_PROP_INVERT   FALSE
 
 enum
 {
@@ -96,6 +97,7 @@ enum
   PROP_DEPTH,
   PROP_FPS,
   PROP_DURATION,
+  PROP_INVERT,
   PROP_LAST,
 };
 
@@ -150,7 +152,7 @@ static void gst_smpte_base_init (GstSMPTEClass * klass);
 static void gst_smpte_init (GstSMPTE * smpte);
 static void gst_smpte_finalize (GstSMPTE * smpte);
 
-static GstFlowReturn gst_smpte_collected (GstCollectPads * pads,
+static GstFlowReturn gst_smpte_collected (GstCollectPads2 * pads,
     GstSMPTE * smpte);
 
 static void gst_smpte_set_property (GObject * object, guint prop_id,
@@ -226,22 +228,27 @@ gst_smpte_class_init (GstSMPTEClass * klass)
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TYPE,
       g_param_spec_enum ("type", "Type", "The type of transition to use",
           GST_TYPE_SMPTE_TRANSITION_TYPE, DEFAULT_PROP_TYPE,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FPS,
       g_param_spec_float ("fps", "FPS",
           "Frames per second if no input files are given (deprecated)", 0.,
-          G_MAXFLOAT, DEFAULT_PROP_FPS, G_PARAM_READWRITE));
+          G_MAXFLOAT, DEFAULT_PROP_FPS,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BORDER,
       g_param_spec_int ("border", "Border",
           "The border width of the transition", 0, G_MAXINT,
-          DEFAULT_PROP_BORDER, G_PARAM_READWRITE));
+          DEFAULT_PROP_BORDER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DEPTH,
       g_param_spec_int ("depth", "Depth", "Depth of the mask in bits", 1, 24,
-          DEFAULT_PROP_DEPTH, G_PARAM_READWRITE));
+          DEFAULT_PROP_DEPTH, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DURATION,
       g_param_spec_uint64 ("duration", "Duration",
           "Duration of the transition effect in nanoseconds", 0, G_MAXUINT64,
-          DEFAULT_PROP_DURATION, G_PARAM_READWRITE));
+          DEFAULT_PROP_DURATION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_INVERT,
+      g_param_spec_boolean ("invert", "Invert",
+          "Invert transition mask", DEFAULT_PROP_INVERT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_smpte_change_state);
 }
@@ -266,25 +273,27 @@ fill_i420 (guint8 * data, gint width, gint height, gint color)
 }
 
 static gboolean
-gst_smpte_update_mask (GstSMPTE * smpte, gint type, gint depth, gint width,
-    gint height)
+gst_smpte_update_mask (GstSMPTE * smpte, gint type, gboolean invert,
+    gint depth, gint width, gint height)
 {
   GstMask *newmask;
 
   if (smpte->mask) {
     if (smpte->type == type &&
+        smpte->invert == invert &&
         smpte->depth == depth &&
         smpte->width == width && smpte->height == height)
       return TRUE;
   }
 
-  newmask = gst_mask_factory_new (type, depth, width, height);
+  newmask = gst_mask_factory_new (type, invert, depth, width, height);
   if (newmask) {
     if (smpte->mask) {
       gst_mask_destroy (smpte->mask);
     }
     smpte->mask = newmask;
     smpte->type = type;
+    smpte->invert = invert;
     smpte->depth = depth;
     smpte->width = width;
     smpte->height = height;
@@ -321,8 +330,9 @@ gst_smpte_setcaps (GstPad * pad, GstCaps * caps)
 
   GST_DEBUG_OBJECT (smpte, "duration: %d frames", smpte->end_position);
 
-  ret = gst_smpte_update_mask (smpte, smpte->type, smpte->depth, smpte->width,
-      smpte->height);
+  ret =
+      gst_smpte_update_mask (smpte, smpte->type, smpte->invert, smpte->depth,
+      smpte->width, smpte->height);
 
   return ret;
 }
@@ -350,21 +360,22 @@ gst_smpte_init (GstSMPTE * smpte)
       gst_pad_new_from_static_template (&gst_smpte_src_template, "src");
   gst_element_add_pad (GST_ELEMENT (smpte), smpte->srcpad);
 
-  smpte->collect = gst_collect_pads_new ();
-  gst_collect_pads_set_function (smpte->collect,
-      (GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_smpte_collected), smpte);
-  gst_collect_pads_start (smpte->collect);
+  smpte->collect = gst_collect_pads2_new ();
+  gst_collect_pads2_set_function (smpte->collect,
+      (GstCollectPads2Function) GST_DEBUG_FUNCPTR (gst_smpte_collected), smpte);
+  gst_collect_pads2_start (smpte->collect);
 
-  gst_collect_pads_add_pad (smpte->collect, smpte->sinkpad1,
-      sizeof (GstCollectData));
-  gst_collect_pads_add_pad (smpte->collect, smpte->sinkpad2,
-      sizeof (GstCollectData));
+  gst_collect_pads2_add_pad (smpte->collect, smpte->sinkpad1,
+      sizeof (GstCollectData2));
+  gst_collect_pads2_add_pad (smpte->collect, smpte->sinkpad2,
+      sizeof (GstCollectData2));
 
   smpte->fps = DEFAULT_PROP_FPS;
   smpte->type = DEFAULT_PROP_TYPE;
   smpte->border = DEFAULT_PROP_BORDER;
   smpte->depth = DEFAULT_PROP_DEPTH;
   smpte->duration = DEFAULT_PROP_DURATION;
+  smpte->invert = DEFAULT_PROP_INVERT;
   smpte->fps_num = 0;
   smpte->fps_denom = 1;
 }
@@ -397,8 +408,7 @@ gst_smpte_blend_i420 (guint8 * in1, guint8 * in2, guint8 * out, GstMask * mask,
   gint i, j;
   gint min, max;
   guint8 *in1u, *in1v, *in2u, *in2v, *outu, *outv;
-  gint lumsize = width * height;
-  gint chromsize = lumsize >> 2;
+  gint uoffset, voffset, ystr, ustr, vstr;
 
   if (border == 0)
     border++;
@@ -406,12 +416,19 @@ gst_smpte_blend_i420 (guint8 * in1, guint8 * in2, guint8 * out, GstMask * mask,
   min = pos - border;
   max = pos;
 
-  in1u = in1 + lumsize;
-  in1v = in1u + chromsize;
-  in2u = in2 + lumsize;
-  in2v = in2u + chromsize;
-  outu = out + lumsize;
-  outv = outu + chromsize;
+  uoffset = I420_U_OFFSET (width, height);
+  voffset = I420_V_OFFSET (width, height);
+
+  ystr = I420_Y_ROWSTRIDE (width);
+  ustr = I420_U_ROWSTRIDE (width);
+  vstr = I420_V_ROWSTRIDE (width);
+
+  in1u = in1 + uoffset;
+  in1v = in1 + voffset;
+  in2u = in2 + uoffset;
+  in2v = in2 + voffset;
+  outu = out + uoffset;
+  outv = out + voffset;
 
   maskp = mask->data;
 
@@ -420,17 +437,30 @@ gst_smpte_blend_i420 (guint8 * in1, guint8 * in2, guint8 * out, GstMask * mask,
       value = *maskp++;
       value = ((CLAMP (value, min, max) - min) << 8) / border;
 
-      *out++ = ((*in1++ * value) + (*in2++ * (256 - value))) >> 8;
+      out[j] = ((in1[j] * value) + (in2[j] * (256 - value))) >> 8;
       if (!(i & 1) && !(j & 1)) {
-        *outu++ = ((*in1u++ * value) + (*in2u++ * (256 - value))) >> 8;
-        *outv++ = ((*in1v++ * value) + (*in2v++ * (256 - value))) >> 8;
+        outu[j / 2] =
+            ((in1u[j / 2] * value) + (in2u[j / 2] * (256 - value))) >> 8;
+        outv[j / 2] =
+            ((in1v[j / 2] * value) + (in2v[j / 2] * (256 - value))) >> 8;
       }
     }
+    out += ystr;
+    in1 += ystr;
+    in2 += ystr;
+    if (!(i & 1)) {
+      outu += ustr;
+      in1u += ustr;
+      in2u += ustr;
+      outv += vstr;
+      in1v += vstr;
+      in2v += vstr;
+    }
   }
 }
 
 static GstFlowReturn
-gst_smpte_collected (GstCollectPads * pads, GstSMPTE * smpte)
+gst_smpte_collected (GstCollectPads2 * pads, GstSMPTE * smpte)
 {
   GstBuffer *outbuf;
   GstClockTime ts;
@@ -447,14 +477,14 @@ gst_smpte_collected (GstCollectPads * pads, GstSMPTE * smpte)
       smpte->fps_denom, smpte->fps_num);
 
   for (collected = pads->data; collected; collected = g_slist_next (collected)) {
-    GstCollectData *data;
+    GstCollectData2 *data;
 
-    data = (GstCollectData *) collected->data;
+    data = (GstCollectData2 *) collected->data;
 
     if (data->pad == smpte->sinkpad1)
-      in1 = gst_collect_pads_pop (pads, data);
+      in1 = gst_collect_pads2_pop (pads, data);
     else if (data->pad == smpte->sinkpad2)
-      in2 = gst_collect_pads_pop (pads, data);
+      in2 = gst_collect_pads2_pop (pads, data);
   }
 
   if (in1 == NULL) {
@@ -558,6 +588,9 @@ gst_smpte_set_property (GObject * object, guint prop_id,
     case PROP_DURATION:
       smpte->duration = g_value_get_uint64 (value);
       break;
+    case PROP_INVERT:
+      smpte->invert = g_value_get_boolean (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -588,6 +621,9 @@ gst_smpte_get_property (GObject * object, guint prop_id,
     case PROP_DURATION:
       g_value_set_uint64 (value, smpte->duration);
       break;
+    case PROP_INVERT:
+      g_value_set_boolean (value, smpte->invert);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -606,11 +642,11 @@ gst_smpte_change_state (GstElement * element, GstStateChange transition)
     case GST_STATE_CHANGE_READY_TO_PAUSED:
       gst_smpte_reset (smpte);
       GST_LOG_OBJECT (smpte, "starting collectpads");
-      gst_collect_pads_start (smpte->collect);
+      gst_collect_pads2_start (smpte->collect);
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
       GST_LOG_OBJECT (smpte, "stopping collectpads");
-      gst_collect_pads_stop (smpte->collect);
+      gst_collect_pads2_stop (smpte->collect);
       break;
     default:
       break;