Merge remote-tracking branch 'origin/master' into 0.11
[platform/upstream/gstreamer.git] / ext / libswscale / gstffmpegscale.c
index 202fda8..6d75d9a 100644 (file)
@@ -47,16 +47,11 @@ typedef struct _GstFFMpegScale
   GstPad *sinkpad, *srcpad;
 
   /* state */
-  gint in_width, in_height;
-  gint out_width, out_height;
+  GstVideoInfo in_info, out_info;
 
   enum PixelFormat in_pixfmt, out_pixfmt;
   struct SwsContext *ctx;
 
-  /* cached auxiliary data */
-  gint in_stride[3], in_offset[3];
-  gint out_stride[3], out_offset[3];
-
   /* property */
   gint method;
 } GstFFMpegScale;
@@ -85,16 +80,10 @@ GST_DEBUG_CATEGORY (ffmpegscale_debug);
 /* libswscale supported formats depend on endianness */
 #if G_BYTE_ORDER == G_BIG_ENDIAN
 #define VIDEO_CAPS \
-        GST_VIDEO_CAPS_RGB "; " GST_VIDEO_CAPS_BGR "; " \
-        GST_VIDEO_CAPS_xRGB "; " GST_VIDEO_CAPS_xBGR "; " \
-        GST_VIDEO_CAPS_ARGB "; " GST_VIDEO_CAPS_ABGR "; " \
-        GST_VIDEO_CAPS_YUV ("{ I420, YUY2, UYVY, Y41B, Y42B }")
+        GST_VIDEO_CAPS_MAKE ("{ RGB, BGR, xRGB, xBGR, ARGB, ABGR, I420, YUY2, UYVY, Y41B, Y42B }")
 #else
 #define VIDEO_CAPS \
-        GST_VIDEO_CAPS_RGB "; " GST_VIDEO_CAPS_BGR "; " \
-        GST_VIDEO_CAPS_RGBx "; " GST_VIDEO_CAPS_BGRx "; " \
-        GST_VIDEO_CAPS_RGBA "; " GST_VIDEO_CAPS_BGRA "; " \
-        GST_VIDEO_CAPS_YUV ("{ I420, YUY2, UYVY, Y41B, Y42B }")
+        GST_VIDEO_CAPS_MAKE ("{ RGB, BGR, RGBx, BGRx, RGBA, BGRA, I420, YUY2, UYVY, Y41B, Y42B }")
 #endif
 
 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
@@ -161,8 +150,8 @@ enum
       /* FILL ME */
 };
 
-GST_BOILERPLATE (GstFFMpegScale, gst_ffmpegscale, GstBaseTransform,
-    GST_TYPE_BASE_TRANSFORM);
+#define gst_ffmpegscale_parent_class parent_class
+G_DEFINE_TYPE (GstFFMpegScale, gst_ffmpegscale, GST_TYPE_BASE_TRANSFORM);
 
 static void gst_ffmpegscale_finalize (GObject * object);
 static void gst_ffmpegscale_set_property (GObject * object, guint prop_id,
@@ -172,11 +161,11 @@ static void gst_ffmpegscale_get_property (GObject * object, guint prop_id,
 
 static gboolean gst_ffmpegscale_stop (GstBaseTransform * trans);
 static GstCaps *gst_ffmpegscale_transform_caps (GstBaseTransform * trans,
-    GstPadDirection direction, GstCaps * caps);
+    GstPadDirection direction, GstCaps * caps, GstCaps * filter);
 static void gst_ffmpegscale_fixate_caps (GstBaseTransform * trans,
     GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
 static gboolean gst_ffmpegscale_get_unit_size (GstBaseTransform * trans,
-    GstCaps * caps, guint * size);
+    GstCaps * caps, gsize * size);
 static gboolean gst_ffmpegscale_set_caps (GstBaseTransform * trans,
     GstCaps * incaps, GstCaps * outcaps);
 static GstFlowReturn gst_ffmpegscale_transform (GstBaseTransform * trans,
@@ -186,24 +175,10 @@ static gboolean gst_ffmpegscale_handle_src_event (GstPad * pad,
     GstEvent * event);
 
 static void
-gst_ffmpegscale_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&src_factory));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&sink_factory));
-  gst_element_class_set_details_simple (element_class, "FFMPEG Scale element",
-      "Filter/Converter/Video",
-      "Converts video from one resolution to another",
-      "Luca Ognibene <luogni@tin.it>, Mark Nauwelaerts <mnauw@users.sf.net>");
-}
-
-static void
 gst_ffmpegscale_class_init (GstFFMpegScaleClass * klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
   GstBaseTransformClass *trans_class = GST_BASE_TRANSFORM_CLASS (klass);
 
   gobject_class->finalize = gst_ffmpegscale_finalize;
@@ -215,6 +190,16 @@ gst_ffmpegscale_class_init (GstFFMpegScaleClass * klass)
           GST_TYPE_FFMPEGSCALE_METHOD, DEFAULT_PROP_METHOD,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&src_factory));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&sink_factory));
+
+  gst_element_class_set_details_simple (gstelement_class,
+      "FFMPEG Scale element", "Filter/Converter/Video",
+      "Converts video from one resolution to another",
+      "Luca Ognibene <luogni@tin.it>, Mark Nauwelaerts <mnauw@users.sf.net>");
+
   trans_class->stop = GST_DEBUG_FUNCPTR (gst_ffmpegscale_stop);
   trans_class->transform_caps =
       GST_DEBUG_FUNCPTR (gst_ffmpegscale_transform_caps);
@@ -228,7 +213,7 @@ gst_ffmpegscale_class_init (GstFFMpegScaleClass * klass)
 }
 
 static void
-gst_ffmpegscale_init (GstFFMpegScale * scale, GstFFMpegScaleClass * klass)
+gst_ffmpegscale_init (GstFFMpegScale * scale)
 {
   GstBaseTransform *trans = GST_BASE_TRANSFORM (scale);
 
@@ -311,7 +296,7 @@ gst_ffmpegscale_caps_remove_format_info (GstCaps * caps)
 
 static GstCaps *
 gst_ffmpegscale_transform_caps (GstBaseTransform * trans,
-    GstPadDirection direction, GstCaps * caps)
+    GstPadDirection direction, GstCaps * caps, GstCaps * filter)
 {
   GstCaps *ret;
   GstStructure *structure;
@@ -472,18 +457,18 @@ gst_ffmpegscale_fixate_caps (GstBaseTransform * trans,
 
 static gboolean
 gst_ffmpegscale_get_unit_size (GstBaseTransform * trans, GstCaps * caps,
-    guint * size)
+    gsize * size)
 {
-  gint width, height;
-  GstVideoFormat format;
+  GstVideoInfo info;
 
-  if (!gst_video_format_parse_caps (caps, &format, &width, &height))
+  if (!gst_video_info_from_caps (&info, caps))
     return FALSE;
 
-  *size = gst_video_format_get_size (format, width, height);
+  *size = info.size;
 
   GST_DEBUG_OBJECT (trans, "unit size = %d for format %d w %d height %d",
-      *size, format, width, height);
+      *size, GST_VIDEO_INFO_FORMAT (&info), GST_VIDEO_INFO_WIDTH (&info),
+      GST_VIDEO_INFO_HEIGHT (&info));
 
   return TRUE;
 }
@@ -493,101 +478,70 @@ gst_ffmpegscale_get_unit_size (GstBaseTransform * trans, GstCaps * caps,
 static enum PixelFormat
 gst_ffmpeg_caps_to_pixfmt (const GstCaps * caps)
 {
-  GstStructure *structure;
-  enum PixelFormat pix_fmt = PIX_FMT_NONE;
+  GstVideoInfo info;
+  enum PixelFormat pix_fmt;
 
   GST_DEBUG ("converting caps %" GST_PTR_FORMAT, caps);
-  g_return_val_if_fail (gst_caps_get_size (caps) == 1, PIX_FMT_NONE);
-  structure = gst_caps_get_structure (caps, 0);
 
-  if (strcmp (gst_structure_get_name (structure), "video/x-raw-yuv") == 0) {
-    guint32 fourcc;
-
-    if (gst_structure_get_fourcc (structure, "format", &fourcc)) {
-      switch (fourcc) {
-        case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
-          pix_fmt = PIX_FMT_YUYV422;
-          break;
-        case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
-          pix_fmt = PIX_FMT_UYVY422;
-          break;
-        case GST_MAKE_FOURCC ('I', '4', '2', '0'):
-          pix_fmt = PIX_FMT_YUV420P;
-          break;
-        case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
-          pix_fmt = PIX_FMT_YUV411P;
-          break;
-        case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
-          pix_fmt = PIX_FMT_YUV422P;
-          break;
-        case GST_MAKE_FOURCC ('Y', 'U', 'V', '9'):
-          pix_fmt = PIX_FMT_YUV410P;
-          break;
-      }
-    }
-  } else if (strcmp (gst_structure_get_name (structure),
-          "video/x-raw-rgb") == 0) {
-    gint bpp = 0, rmask = 0, endianness = 0;
-
-    if (gst_structure_get_int (structure, "bpp", &bpp) &&
-        gst_structure_get_int (structure, "endianness", &endianness) &&
-        endianness == G_BIG_ENDIAN) {
-      if (gst_structure_get_int (structure, "red_mask", &rmask)) {
-        switch (bpp) {
-          case 32:
-            if (rmask == 0x00ff0000)
-              pix_fmt = PIX_FMT_ARGB;
-            else if (rmask == 0xff000000)
-              pix_fmt = PIX_FMT_RGBA;
-            else if (rmask == 0xff00)
-              pix_fmt = PIX_FMT_BGRA;
-            else if (rmask == 0xff)
-              pix_fmt = PIX_FMT_ABGR;
-            break;
-          case 24:
-            if (rmask == 0x0000FF)
-              pix_fmt = PIX_FMT_BGR24;
-            else
-              pix_fmt = PIX_FMT_RGB24;
-            break;
-          case 16:
-            if (endianness == G_BYTE_ORDER)
-              pix_fmt = PIX_FMT_RGB565;
-            break;
-          case 15:
-            if (endianness == G_BYTE_ORDER)
-              pix_fmt = PIX_FMT_RGB555;
-            break;
-          default:
-            /* nothing */
-            break;
-        }
-      } else {
-        if (bpp == 8) {
-          pix_fmt = PIX_FMT_PAL8;
-        }
-      }
-    }
-  }
+  if (gst_video_info_from_caps (&info, caps))
+    goto invalid_caps;
 
+  switch (GST_VIDEO_INFO_FORMAT (&info)) {
+    case GST_VIDEO_FORMAT_YUY2:
+      pix_fmt = PIX_FMT_YUYV422;
+      break;
+    case GST_VIDEO_FORMAT_UYVY:
+      pix_fmt = PIX_FMT_UYVY422;
+      break;
+    case GST_VIDEO_FORMAT_I420:
+      pix_fmt = PIX_FMT_YUV420P;
+      break;
+    case GST_VIDEO_FORMAT_Y41B:
+      pix_fmt = PIX_FMT_YUV411P;
+      break;
+    case GST_VIDEO_FORMAT_Y42B:
+      pix_fmt = PIX_FMT_YUV422P;
+      break;
+    case GST_VIDEO_FORMAT_YUV9:
+      pix_fmt = PIX_FMT_YUV410P;
+      break;
+    case GST_VIDEO_FORMAT_ARGB:
+      pix_fmt = PIX_FMT_ARGB;
+      break;
+    case GST_VIDEO_FORMAT_RGBA:
+      pix_fmt = PIX_FMT_RGBA;
+      break;
+    case GST_VIDEO_FORMAT_BGRA:
+      pix_fmt = PIX_FMT_BGRA;
+      break;
+    case GST_VIDEO_FORMAT_ABGR:
+      pix_fmt = PIX_FMT_ABGR;
+      break;
+    case GST_VIDEO_FORMAT_BGR:
+      pix_fmt = PIX_FMT_BGR24;
+      break;
+    case GST_VIDEO_FORMAT_RGB:
+      pix_fmt = PIX_FMT_RGB24;
+      break;
+    case GST_VIDEO_FORMAT_RGB16:
+      pix_fmt = PIX_FMT_RGB565;
+      break;
+    case GST_VIDEO_FORMAT_RGB15:
+      pix_fmt = PIX_FMT_RGB555;
+      break;
+    case GST_VIDEO_FORMAT_RGB8_PALETTED:
+      pix_fmt = PIX_FMT_PAL8;
+      break;
+    default:
+      pix_fmt = PIX_FMT_NONE;
+      break;
+  }
   return pix_fmt;
-}
 
-static void
-gst_ffmpegscale_fill_info (GstFFMpegScale * scale, GstVideoFormat format,
-    guint width, guint height, gint stride[], gint offset[])
-{
-  gint i;
-
-  for (i = 0; i < 3; i++) {
-    stride[i] = gst_video_format_get_row_stride (format, i, width);
-    offset[i] = gst_video_format_get_component_offset (format, i, width,
-        height);
-    /* stay close to the ffmpeg offset way */
-    if (offset[i] < 3)
-      offset[i] = 0;
-    GST_DEBUG_OBJECT (scale, "format %d, component %d; stride %d, offset %d",
-        format, i, stride[i], offset[i]);
+  /* ERROR */
+invalid_caps:
+  {
+    return PIX_FMT_NONE;
   }
 }
 
@@ -598,7 +552,6 @@ gst_ffmpegscale_set_caps (GstBaseTransform * trans, GstCaps * incaps,
   GstFFMpegScale *scale = GST_FFMPEGSCALE (trans);
   guint mmx_flags, altivec_flags;
   gint swsflags;
-  GstVideoFormat in_format, out_format;
   gboolean ok;
 
   g_return_val_if_fail (scale->method <
@@ -609,27 +562,25 @@ gst_ffmpegscale_set_caps (GstBaseTransform * trans, GstCaps * incaps,
     scale->ctx = NULL;
   }
 
-  ok = gst_video_format_parse_caps (incaps, &in_format, &scale->in_width,
-      &scale->in_height);
-  ok &= gst_video_format_parse_caps (outcaps, &out_format, &scale->out_width,
-      &scale->out_height);
+  ok = gst_video_info_from_caps (&scale->in_info, incaps);
+  ok &= gst_video_info_from_caps (&scale->out_info, outcaps);
+
   scale->in_pixfmt = gst_ffmpeg_caps_to_pixfmt (incaps);
   scale->out_pixfmt = gst_ffmpeg_caps_to_pixfmt (outcaps);
 
   if (!ok || scale->in_pixfmt == PIX_FMT_NONE ||
       scale->out_pixfmt == PIX_FMT_NONE ||
-      in_format == GST_VIDEO_FORMAT_UNKNOWN ||
-      out_format == GST_VIDEO_FORMAT_UNKNOWN)
+      GST_VIDEO_INFO_FORMAT (&scale->in_info) == GST_VIDEO_FORMAT_UNKNOWN ||
+      GST_VIDEO_INFO_FORMAT (&scale->out_info) == GST_VIDEO_FORMAT_UNKNOWN)
     goto refuse_caps;
 
-  GST_DEBUG_OBJECT (scale, "format %d => %d, from=%dx%d -> to=%dx%d", in_format,
-      out_format, scale->in_width, scale->in_height, scale->out_width,
-      scale->out_height);
-
-  gst_ffmpegscale_fill_info (scale, in_format, scale->in_width,
-      scale->in_height, scale->in_stride, scale->in_offset);
-  gst_ffmpegscale_fill_info (scale, out_format, scale->out_width,
-      scale->out_height, scale->out_stride, scale->out_offset);
+  GST_DEBUG_OBJECT (scale, "format %d => %d, from=%dx%d -> to=%dx%d",
+      GST_VIDEO_INFO_FORMAT (&scale->in_info),
+      GST_VIDEO_INFO_FORMAT (&scale->out_info),
+      GST_VIDEO_INFO_WIDTH (&scale->in_info),
+      GST_VIDEO_INFO_HEIGHT (&scale->in_info),
+      GST_VIDEO_INFO_WIDTH (&scale->out_info),
+      GST_VIDEO_INFO_HEIGHT (&scale->out_info));
 
 #ifdef HAVE_ORC
   mmx_flags = orc_target_get_default_flags (orc_target_get_by_name ("mmx"));
@@ -645,10 +596,10 @@ gst_ffmpegscale_set_caps (GstBaseTransform * trans, GstCaps * incaps,
   swsflags = 0;
 #endif
 
-
-  scale->ctx = sws_getContext (scale->in_width, scale->in_height,
-      scale->in_pixfmt, scale->out_width, scale->out_height, scale->out_pixfmt,
-      swsflags | gst_ffmpegscale_method_flags[scale->method], NULL, NULL, NULL);
+  scale->ctx = sws_getContext (scale->in_info.width, scale->in_info.height,
+      scale->in_pixfmt, scale->out_info.width, scale->out_info.height,
+      scale->out_pixfmt, swsflags | gst_ffmpegscale_method_flags[scale->method],
+      NULL, NULL, NULL);
   if (!scale->ctx)
     goto setup_failed;
 
@@ -672,22 +623,29 @@ gst_ffmpegscale_transform (GstBaseTransform * trans, GstBuffer * inbuf,
     GstBuffer * outbuf)
 {
   GstFFMpegScale *scale = GST_FFMPEGSCALE (trans);
-  guint8 *in_data[3] = { NULL, NULL, NULL };
-  guint8 *out_data[3] = { NULL, NULL, NULL };
-  gint i;
-
-  for (i = 0; i < 3; i++) {
-    /* again; stay close to the ffmpeg offset way */
-    if (!i || scale->in_offset[i])
-      in_data[i] = GST_BUFFER_DATA (inbuf) + scale->in_offset[i];
-    if (!i || scale->out_offset[i])
-      out_data[i] = GST_BUFFER_DATA (outbuf) + scale->out_offset[i];
-  }
+  GstVideoFrame in_frame, out_frame;
 
-  sws_scale (scale->ctx, (const guint8 **) in_data, scale->in_stride, 0,
-      scale->in_height, out_data, scale->out_stride);
+  if (!gst_video_frame_map (&in_frame, &scale->in_info, inbuf, GST_MAP_READ))
+    goto invalid_buffer;
+
+  if (!gst_video_frame_map (&out_frame, &scale->out_info, outbuf,
+          GST_MAP_WRITE))
+    goto invalid_buffer;
+
+  sws_scale (scale->ctx, (const guint8 **) in_frame.data, in_frame.info.stride,
+      0, scale->in_info.height, (guint8 **) out_frame.data,
+      out_frame.info.stride);
+
+  gst_video_frame_unmap (&in_frame);
+  gst_video_frame_unmap (&out_frame);
 
   return GST_FLOW_OK;
+
+  /* ERRORS */
+invalid_buffer:
+  {
+    return GST_FLOW_OK;
+  }
 }
 
 static gboolean
@@ -709,12 +667,12 @@ gst_ffmpegscale_handle_src_event (GstPad * pad, GstEvent * event)
       if (gst_structure_get_double (structure, "pointer_x", &pointer)) {
         gst_structure_set (structure,
             "pointer_x", G_TYPE_DOUBLE,
-            pointer * scale->in_width / scale->out_width, NULL);
+            pointer * scale->in_info.width / scale->out_info.width, NULL);
       }
       if (gst_structure_get_double (structure, "pointer_y", &pointer)) {
         gst_structure_set (structure,
             "pointer_y", G_TYPE_DOUBLE,
-            pointer * scale->in_height / scale->out_height, NULL);
+            pointer * scale->in_info.height / scale->out_info.height, NULL);
       }
       break;
     default: