v4l2src: Simplify format handling
[platform/upstream/gst-plugins-good.git] / ext / cairo / gstcairooverlay.c
index 7bddb30..9aa4c53 100644 (file)
@@ -13,8 +13,8 @@
  *
  * You should have received a copy of the GNU Library General Public
  * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
  */
 
 /**
 #endif
 
 #include "gstcairooverlay.h"
-#include "gstcairo-marshal.h"
 
 #include <gst/video/video.h>
 
 #include <cairo.h>
 
+/* RGB16 is native-endianness in GStreamer */
 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
-#define ARGB_CAPS GST_VIDEO_CAPS_BGRx " ; " GST_VIDEO_CAPS_BGRA " ; "
+#define TEMPLATE_CAPS GST_VIDEO_CAPS_MAKE("{ BGRx, BGRA, RGB16 }")
 #else
-#define ARGB_CAPS GST_VIDEO_CAPS_xRGB " ; " GST_VIDEO_CAPS_ARGB " ; "
-
+#define TEMPLATE_CAPS GST_VIDEO_CAPS_MAKE("{ xRGB, ARGB, RGB16 }")
 #endif
 
 static GstStaticPadTemplate gst_cairo_overlay_src_template =
 GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS (ARGB_CAPS)
+    GST_STATIC_CAPS (TEMPLATE_CAPS)
     );
 
 static GstStaticPadTemplate gst_cairo_overlay_sink_template =
 GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS (ARGB_CAPS)
+    GST_STATIC_CAPS (TEMPLATE_CAPS)
     );
 
-
-GST_BOILERPLATE (GstCairoOverlay, gst_cairo_overlay, GstVideoFilter,
-    GST_TYPE_VIDEO_FILTER);
+G_DEFINE_TYPE (GstCairoOverlay, gst_cairo_overlay, GST_TYPE_VIDEO_FILTER);
 
 enum
 {
@@ -128,40 +125,55 @@ enum
   SIGNAL_CAPS_CHANGED,
   N_SIGNALS
 };
+
 static guint gst_cairo_overlay_signals[N_SIGNALS];
 
 static gboolean
-gst_cairo_overlay_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
-    GstCaps * outcaps)
+gst_cairo_overlay_set_info (GstVideoFilter * vfilter, GstCaps * in_caps,
+    GstVideoInfo * in_info, GstCaps * out_caps, GstVideoInfo * out_info)
 {
-  GstCairoOverlay *overlay = GST_CAIRO_OVERLAY (btrans);
-  GstStructure *s = gst_caps_get_structure (incaps, 0);
-
-  if (!gst_structure_get_int (s, "bpp", &(overlay->bpp))) {
-    return FALSE;
-  }
+  GstCairoOverlay *overlay = GST_CAIRO_OVERLAY (vfilter);
 
   g_signal_emit (overlay, gst_cairo_overlay_signals[SIGNAL_CAPS_CHANGED], 0,
-      incaps, NULL);
+      in_caps, NULL);
 
-  return G_LIKELY (gst_video_format_parse_caps (incaps,
-          &overlay->caps_format, &overlay->caps_width, &overlay->caps_height));
+  return TRUE;
 }
 
 static GstFlowReturn
-gst_cairo_overlay_transform_ip (GstBaseTransform * btrans, GstBuffer * buf)
+gst_cairo_overlay_transform_frame_ip (GstVideoFilter * vfilter,
+    GstVideoFrame * frame)
 {
-
-  GstCairoOverlay *overlay = GST_CAIRO_OVERLAY (btrans);
+  GstCairoOverlay *overlay = GST_CAIRO_OVERLAY (vfilter);
   cairo_surface_t *surface;
   cairo_t *cr;
   cairo_format_t format;
 
-  format = (overlay->bpp == 32) ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24;
+  switch (GST_VIDEO_FRAME_FORMAT (frame)) {
+    case GST_VIDEO_FORMAT_ARGB:
+    case GST_VIDEO_FORMAT_BGRA:
+      format = CAIRO_FORMAT_ARGB32;
+      break;
+    case GST_VIDEO_FORMAT_xRGB:
+    case GST_VIDEO_FORMAT_BGRx:
+      format = CAIRO_FORMAT_RGB24;
+      break;
+    case GST_VIDEO_FORMAT_RGB16:
+      format = CAIRO_FORMAT_RGB16_565;
+      break;
+    default:
+    {
+      GST_WARNING ("No matching cairo format for %s",
+          gst_video_format_to_string (GST_VIDEO_FRAME_FORMAT (frame)));
+      return GST_FLOW_ERROR;
+    }
+  }
 
   surface =
-      cairo_image_surface_create_for_data (GST_BUFFER_DATA (buf), format,
-      overlay->caps_width, overlay->caps_height, overlay->caps_width * 4);
+      cairo_image_surface_create_for_data (GST_VIDEO_FRAME_PLANE_DATA (frame,
+          0), format, GST_VIDEO_FRAME_WIDTH (frame),
+      GST_VIDEO_FRAME_HEIGHT (frame), GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0));
+
   if (G_UNLIKELY (!surface))
     return GST_FLOW_ERROR;
 
@@ -172,45 +184,33 @@ gst_cairo_overlay_transform_ip (GstBaseTransform * btrans, GstBuffer * buf)
   }
 
   g_signal_emit (overlay, gst_cairo_overlay_signals[SIGNAL_DRAW], 0,
-      cr, GST_BUFFER_TIMESTAMP (buf), GST_BUFFER_DURATION (buf), NULL);
+      cr, GST_BUFFER_PTS (frame->buffer), GST_BUFFER_DURATION (frame->buffer),
+      NULL);
 
   cairo_destroy (cr);
   cairo_surface_destroy (surface);
-  return GST_FLOW_OK;
-}
-
-static void
-gst_cairo_overlay_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details_simple (element_class, "Cairo overlay",
-      "Filter/Editor/Video",
-      "Render overlay on a video stream using Cairo",
-      "Jon Nordby <jononor@gmail.com>");
 
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&gst_cairo_overlay_sink_template));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&gst_cairo_overlay_src_template));
+  return GST_FLOW_OK;
 }
 
 static void
 gst_cairo_overlay_class_init (GstCairoOverlayClass * klass)
 {
-  GstBaseTransformClass *trans_class;
+  GstVideoFilterClass *vfilter_class;
+  GstElementClass *element_class;
 
-  trans_class = (GstBaseTransformClass *) klass;
+  vfilter_class = (GstVideoFilterClass *) klass;
+  element_class = (GstElementClass *) klass;
 
-  trans_class->set_caps = gst_cairo_overlay_set_caps;
-  trans_class->transform_ip = gst_cairo_overlay_transform_ip;
+  vfilter_class->set_info = gst_cairo_overlay_set_info;
+  vfilter_class->transform_frame_ip = gst_cairo_overlay_transform_frame_ip;
 
   /**
    * GstCairoOverlay::draw:
    * @overlay: Overlay element emitting the signal.
    * @cr: Cairo context to draw to.
-   * @timestamp: Timestamp (see GstClockTime) of the current buffer.
-   * @duration: Duration (see GstClockTime) of the current buffer.
+   * @timestamp: Timestamp (see #GstClockTime) of the current buffer.
+   * @duration: Duration (see #GstClockTime) of the current buffer.
    * 
    * This signal is emitted when the overlay should be drawn.
    */
@@ -221,13 +221,13 @@ gst_cairo_overlay_class_init (GstCairoOverlayClass * klass)
       0,
       NULL,
       NULL,
-      gst_cairo_marshal_VOID__BOXED_UINT64_UINT64,
+      g_cclosure_marshal_generic,
       G_TYPE_NONE, 3, CAIRO_GOBJECT_TYPE_CONTEXT, G_TYPE_UINT64, G_TYPE_UINT64);
 
   /**
    * GstCairoOverlay::caps-changed:
    * @overlay: Overlay element emitting the signal.
-   * @caps: The caps of the element.
+   * @caps: The #GstCaps of the element.
    * 
    * This signal is emitted when the caps of the element has changed.
    */
@@ -235,11 +235,21 @@ gst_cairo_overlay_class_init (GstCairoOverlayClass * klass)
       g_signal_new ("caps-changed",
       G_TYPE_FROM_CLASS (klass),
       0,
-      0,
-      NULL, NULL, gst_cairo_marshal_VOID__BOXED, G_TYPE_NONE, 1, GST_TYPE_CAPS);
+      0, NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_CAPS);
+
+  gst_element_class_set_static_metadata (element_class, "Cairo overlay",
+      "Filter/Editor/Video",
+      "Render overlay on a video stream using Cairo",
+      "Jon Nordby <jononor@gmail.com>");
+
+  gst_element_class_add_static_pad_template (element_class,
+      &gst_cairo_overlay_sink_template);
+  gst_element_class_add_static_pad_template (element_class,
+      &gst_cairo_overlay_src_template);
 }
 
 static void
-gst_cairo_overlay_init (GstCairoOverlay * overlay, GstCairoOverlayClass * klass)
+gst_cairo_overlay_init (GstCairoOverlay * overlay)
 {
+  /* nothing to do */
 }