Merge branch 'tizen' into tizen_gst_1.19.2
[platform/upstream/gstreamer.git] / gst-libs / gst / video / video-info.c
index 3c38a15..93bede5 100644 (file)
  * Boston, MA 02110-1301, USA.
  */
 
+/**
+ * SECTION:video-info
+ * @title: GstVideoInfo
+ * @short_description: Structures and enumerations to describe raw images
+ */
+
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
 #endif
@@ -106,11 +112,12 @@ gst_video_info_new (void)
   return info;
 }
 
-static int fill_planes (GstVideoInfo * info);
+static gboolean fill_planes (GstVideoInfo * info,
+    gsize plane_size[GST_VIDEO_MAX_PLANES]);
 
 /**
  * gst_video_info_init:
- * @info: a #GstVideoInfo
+ * @info: (out caller-allocates): a #GstVideoInfo
  *
  * Initialize @info with default values.
  */
@@ -130,6 +137,8 @@ gst_video_info_init (GstVideoInfo * info)
   info->par_n = 1;
   info->par_d = 1;
   GST_VIDEO_INFO_MULTIVIEW_MODE (info) = GST_VIDEO_MULTIVIEW_MODE_NONE;
+  GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
+  GST_VIDEO_INFO_FIELD_ORDER (info) = GST_VIDEO_FIELD_ORDER_UNKNOWN;
 }
 
 #define MAKE_COLORIMETRY(r,m,t,p) {  \
@@ -144,7 +153,7 @@ gst_video_info_init (GstVideoInfo * info)
 #define DEFAULT_YUV_UHD 5
 
 static const GstVideoColorimetry default_color[] = {
-  MAKE_COLORIMETRY (_16_235, BT601, BT709, SMPTE170M),
+  MAKE_COLORIMETRY (_16_235, BT601, BT601, SMPTE170M),
   MAKE_COLORIMETRY (_16_235, BT709, BT709, BT709),
   MAKE_COLORIMETRY (_0_255, RGB, SRGB, BT709),
   MAKE_COLORIMETRY (_0_255, BT601, UNKNOWN, UNKNOWN),
@@ -178,17 +187,46 @@ set_default_colorimetry (GstVideoInfo * info)
 }
 
 static gboolean
-validate_colorimetry (const GstVideoInfo * info)
+validate_colorimetry (GstVideoInfo * info)
 {
   const GstVideoFormatInfo *finfo = info->finfo;
 
   if (!GST_VIDEO_FORMAT_INFO_IS_RGB (finfo) &&
-      info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB)
+      info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB) {
+    GST_WARNING
+        ("color matrix RGB is only supported with RGB format, %s is not",
+        finfo->name);
     return FALSE;
+  }
 
   if (GST_VIDEO_FORMAT_INFO_IS_YUV (finfo) &&
-      info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN)
+      info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
+    GST_WARNING ("Need to specify a color matrix when using YUV format (%s)",
+        finfo->name);
     return FALSE;
+  }
+
+  return TRUE;
+}
+
+static gboolean
+gst_video_info_set_format_common (GstVideoInfo * info, GstVideoFormat format,
+    guint width, guint height)
+{
+  g_return_val_if_fail (info != NULL, FALSE);
+  g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, FALSE);
+
+  if (width > G_MAXINT || height > G_MAXINT)
+    return FALSE;
+
+  gst_video_info_init (info);
+
+  info->finfo = gst_video_format_get_info (format);
+  info->width = width;
+  info->height = height;
+  info->views = 1;
+
+  set_default_colorimetry (info);
 
   return TRUE;
 }
@@ -205,31 +243,54 @@ validate_colorimetry (const GstVideoInfo * info)
  * Note: This initializes @info first, no values are preserved. This function
  * does not set the offsets correctly for interlaced vertically
  * subsampled formats.
+ *
+ * Returns: %FALSE if the returned video info is invalid, e.g. because the
+ *   size of a frame can't be represented as a 32 bit integer (Since: 1.12)
  */
-void
+gboolean
 gst_video_info_set_format (GstVideoInfo * info, GstVideoFormat format,
     guint width, guint height)
 {
-  g_return_if_fail (info != NULL);
-  g_return_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN);
-
-  gst_video_info_init (info);
+  if (!gst_video_info_set_format_common (info, format, width, height))
+    return FALSE;
 
-  info->finfo = gst_video_format_get_info (format);
-  info->width = width;
-  info->height = height;
-  info->views = 1;
+  return fill_planes (info, NULL);
+}
 
-  set_default_colorimetry (info);
+/**
+ * gst_video_info_set_interlaced_format:
+ * @info: a #GstVideoInfo
+ * @format: the format
+ * @mode: a #GstVideoInterlaceMode
+ * @width: a width
+ * @height: a height
+ *
+ * Same as #gst_video_info_set_format but also allowing to set the interlaced
+ * mode.
+ *
+ * Returns: %FALSE if the returned video info is invalid, e.g. because the
+ *   size of a frame can't be represented as a 32 bit integer.
+ *
+ * Since: 1.16
+ */
+gboolean
+gst_video_info_set_interlaced_format (GstVideoInfo * info,
+    GstVideoFormat format, GstVideoInterlaceMode mode, guint width,
+    guint height)
+{
+  if (!gst_video_info_set_format_common (info, format, width, height))
+    return FALSE;
 
-  fill_planes (info);
+  GST_VIDEO_INFO_INTERLACE_MODE (info) = mode;
+  return fill_planes (info, NULL);
 }
 
 static const gchar *interlace_mode[] = {
   "progressive",
   "interleaved",
   "mixed",
-  "fields"
+  "fields",
+  "alternate"
 };
 
 /**
@@ -324,7 +385,7 @@ gst_video_field_order_from_string (const gchar * order)
 
 /**
  * gst_video_info_from_caps:
- * @info: a #GstVideoInfo
+ * @info: (out caller-allocates): #GstVideoInfo
  * @caps: a #GstCaps
  *
  * Parse @caps and update @info.
@@ -340,6 +401,7 @@ gst_video_info_from_caps (GstVideoInfo * info, const GstCaps * caps)
   gint width = 0, height = 0;
   gint fps_n, fps_d;
   gint par_n, par_d;
+  guint multiview_flags;
 
   g_return_val_if_fail (info != NULL, FALSE);
   g_return_val_if_fail (caps != NULL, FALSE);
@@ -407,7 +469,18 @@ gst_video_info_from_caps (GstVideoInfo * info, const GstCaps * caps)
   else
     info->interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
 
-  if (info->interlace_mode == GST_VIDEO_INTERLACE_MODE_INTERLEAVED &&
+  /* Interlaced feature is mandatory for raw alternate streams */
+  if (info->interlace_mode == GST_VIDEO_INTERLACE_MODE_ALTERNATE &&
+      format != GST_VIDEO_FORMAT_ENCODED) {
+    GstCapsFeatures *f;
+
+    f = gst_caps_get_features (caps, 0);
+    if (!f
+        || !gst_caps_features_contains (f, GST_CAPS_FEATURE_FORMAT_INTERLACED))
+      goto alternate_no_feature;
+  }
+
+  if (GST_VIDEO_INFO_IS_INTERLACED (info) &&
       (s = gst_structure_get_string (structure, "field-order"))) {
     GST_VIDEO_INFO_FIELD_ORDER (info) = gst_video_field_order_from_string (s);
   } else {
@@ -421,8 +494,9 @@ gst_video_info_from_caps (GstVideoInfo * info, const GstCaps * caps)
     else
       GST_VIDEO_INFO_MULTIVIEW_MODE (info) = GST_VIDEO_MULTIVIEW_MODE_NONE;
 
-    gst_structure_get_flagset (structure, "multiview-flags",
-        &GST_VIDEO_INFO_MULTIVIEW_FLAGS (info), NULL);
+    if (gst_structure_get_flagset (structure, "multiview-flags",
+            &multiview_flags, NULL))
+      GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) = multiview_flags;
 
     if (!gst_structure_get_int (structure, "views", &info->views))
       info->views = 1;
@@ -434,7 +508,7 @@ gst_video_info_from_caps (GstVideoInfo * info, const GstCaps * caps)
   }
 
   if ((s = gst_structure_get_string (structure, "chroma-site")))
-    info->chroma_site = gst_video_chroma_from_string (s);
+    info->chroma_site = gst_video_chroma_site_from_string (s);
   else
     info->chroma_site = GST_VIDEO_CHROMA_SITE_UNKNOWN;
 
@@ -459,7 +533,8 @@ gst_video_info_from_caps (GstVideoInfo * info, const GstCaps * caps)
     set_default_colorimetry (info);
   }
 
-  fill_planes (info);
+  if (!fill_planes (info, NULL))
+    return FALSE;
 
   return TRUE;
 
@@ -490,6 +565,12 @@ no_height:
     GST_ERROR ("no height property given");
     return FALSE;
   }
+alternate_no_feature:
+  {
+    GST_ERROR
+        ("caps has 'interlace-mode=alternate' but doesn't have the Interlaced feature");
+    return FALSE;
+  }
 }
 
 /**
@@ -560,7 +641,7 @@ gst_video_info_is_equal (const GstVideoInfo * info, const GstVideoInfo * other)
  * Returns: a new #GstCaps containing the info of @info.
  */
 GstCaps *
-gst_video_info_to_caps (GstVideoInfo * info)
+gst_video_info_to_caps (const GstVideoInfo * info)
 {
   GstCaps *caps;
   const gchar *format;
@@ -571,7 +652,6 @@ gst_video_info_to_caps (GstVideoInfo * info)
   g_return_val_if_fail (info != NULL, NULL);
   g_return_val_if_fail (info->finfo != NULL, NULL);
   g_return_val_if_fail (info->finfo->format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
-  g_return_val_if_fail (info->finfo->format != GST_VIDEO_FORMAT_ENCODED, NULL);
 
   format = gst_video_format_to_string (info->finfo->format);
   g_return_val_if_fail (format != NULL, NULL);
@@ -587,23 +667,33 @@ gst_video_info_to_caps (GstVideoInfo * info)
   gst_caps_set_simple (caps, "interlace-mode", G_TYPE_STRING,
       gst_video_interlace_mode_to_string (info->interlace_mode), NULL);
 
-  if (info->interlace_mode == GST_VIDEO_INTERLACE_MODE_INTERLEAVED &&
+  if ((info->interlace_mode == GST_VIDEO_INTERLACE_MODE_INTERLEAVED ||
+          info->interlace_mode == GST_VIDEO_INTERLACE_MODE_ALTERNATE) &&
       GST_VIDEO_INFO_FIELD_ORDER (info) != GST_VIDEO_FIELD_ORDER_UNKNOWN) {
     gst_caps_set_simple (caps, "field-order", G_TYPE_STRING,
         gst_video_field_order_to_string (GST_VIDEO_INFO_FIELD_ORDER (info)),
         NULL);
   }
 
+  if (info->interlace_mode == GST_VIDEO_INTERLACE_MODE_ALTERNATE) {
+    /* 'alternate' mode must always be accompanied by interlaced caps feature.
+     */
+    GstCapsFeatures *features;
+
+    features = gst_caps_features_new (GST_CAPS_FEATURE_FORMAT_INTERLACED, NULL);
+    gst_caps_set_features (caps, 0, features);
+  }
+
   if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) != GST_VIDEO_MULTIVIEW_MODE_NONE) {
     const gchar *caps_str = NULL;
+    GstVideoMultiviewFlags multiview_flags =
+        GST_VIDEO_INFO_MULTIVIEW_FLAGS (info);
 
     /* If the half-aspect flag is set, applying it into the PAR of the
      * resulting caps now seems safe, and helps with automatic behaviour
      * in elements that aren't explicitly multiview aware */
-    if (GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) &
-        GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT) {
-      GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) &=
-          ~GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
+    if (multiview_flags & GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT) {
+      multiview_flags &= ~GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
       switch (GST_VIDEO_INFO_MULTIVIEW_MODE (info)) {
         case GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE:
         case GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX:
@@ -626,16 +716,25 @@ gst_video_info_to_caps (GstVideoInfo * info)
     if (caps_str != NULL) {
       gst_caps_set_simple (caps, "multiview-mode", G_TYPE_STRING,
           caps_str, "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
-          GST_VIDEO_INFO_MULTIVIEW_FLAGS (info), GST_FLAG_SET_MASK_EXACT, NULL);
+          multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
     }
   }
 
   gst_caps_set_simple (caps, "pixel-aspect-ratio",
       GST_TYPE_FRACTION, par_n, par_d, NULL);
 
-  if (info->chroma_site != GST_VIDEO_CHROMA_SITE_UNKNOWN)
-    gst_caps_set_simple (caps, "chroma-site", G_TYPE_STRING,
-        gst_video_chroma_to_string (info->chroma_site), NULL);
+  if (info->chroma_site != GST_VIDEO_CHROMA_SITE_UNKNOWN) {
+    gchar *chroma_site = gst_video_chroma_site_to_string (info->chroma_site);
+
+    if (!chroma_site) {
+      GST_WARNING ("Couldn't convert chroma-site 0x%x to string",
+          info->chroma_site);
+    } else {
+      gst_caps_set_simple (caps,
+          "chroma-site", G_TYPE_STRING, chroma_site, NULL);
+      g_free (chroma_site);
+    }
+  }
 
   /* make sure we set the RGB matrix for RGB formats */
   colorimetry = info->colorimetry;
@@ -645,7 +744,7 @@ gst_video_info_to_caps (GstVideoInfo * info)
         colorimetry.matrix);
     colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_RGB;
   }
-  if ((color = gst_video_colorimetry_to_string_full (&colorimetry, FALSE))) {
+  if ((color = gst_video_colorimetry_to_string (&colorimetry))) {
     gst_caps_set_simple (caps, "colorimetry", G_TYPE_STRING, color, NULL);
     g_free (color);
   }
@@ -666,13 +765,24 @@ gst_video_info_to_caps (GstVideoInfo * info)
   return caps;
 }
 
-static int
-fill_planes (GstVideoInfo * info)
+static gboolean
+fill_planes (GstVideoInfo * info, gsize plane_size[GST_VIDEO_MAX_PLANES])
 {
   gsize width, height, cr_h;
+  gint bpp = 0, i;
 
   width = (gsize) info->width;
-  height = (gsize) info->height;
+  height = (gsize) GST_VIDEO_INFO_FIELD_HEIGHT (info);
+
+  /* Sanity check the resulting frame size for overflows */
+  for (i = 0; i < GST_VIDEO_INFO_N_COMPONENTS (info); i++)
+    bpp += GST_VIDEO_INFO_COMP_DEPTH (info, i);
+  bpp = GST_ROUND_UP_8 (bpp) / 8;
+  if (bpp > 0 && GST_ROUND_UP_128 ((guint64) width) * ((guint64) height) >=
+      G_MAXUINT / bpp) {
+    GST_ERROR ("Frame size %ux%u would overflow", info->width, info->height);
+    return FALSE;
+  }
 
   switch (info->finfo->format) {
     case GST_VIDEO_FORMAT_YUY2:
@@ -688,11 +798,16 @@ fill_planes (GstVideoInfo * info)
     case GST_VIDEO_FORMAT_RGBA:
     case GST_VIDEO_FORMAT_BGRx:
     case GST_VIDEO_FORMAT_BGRA:
+    case GST_VIDEO_FORMAT_SR32:
     case GST_VIDEO_FORMAT_xRGB:
     case GST_VIDEO_FORMAT_ARGB:
     case GST_VIDEO_FORMAT_xBGR:
     case GST_VIDEO_FORMAT_ABGR:
     case GST_VIDEO_FORMAT_r210:
+    case GST_VIDEO_FORMAT_Y410:
+    case GST_VIDEO_FORMAT_VUYA:
+    case GST_VIDEO_FORMAT_BGR10A2_LE:
+    case GST_VIDEO_FORMAT_RGB10A2_LE:
       info->stride[0] = width * 4;
       info->offset[0] = 0;
       info->size = info->stride[0] * height;
@@ -719,6 +834,9 @@ fill_planes (GstVideoInfo * info)
       info->size = info->stride[0] * height;
       break;
     case GST_VIDEO_FORMAT_v216:
+    case GST_VIDEO_FORMAT_Y210:
+    case GST_VIDEO_FORMAT_Y212_BE:
+    case GST_VIDEO_FORMAT_Y212_LE:
       info->stride[0] = GST_ROUND_UP_8 (width * 4);
       info->offset[0] = 0;
       info->size = info->stride[0] * height;
@@ -730,6 +848,7 @@ fill_planes (GstVideoInfo * info)
       break;
     case GST_VIDEO_FORMAT_GRAY16_BE:
     case GST_VIDEO_FORMAT_GRAY16_LE:
+    case GST_VIDEO_FORMAT_INVZ:
       info->stride[0] = GST_ROUND_UP_4 (width * 2);
       info->offset[0] = 0;
       info->size = info->stride[0] * height;
@@ -754,12 +873,19 @@ fill_planes (GstVideoInfo * info)
       break;
     case GST_VIDEO_FORMAT_ARGB64:
     case GST_VIDEO_FORMAT_AYUV64:
+    case GST_VIDEO_FORMAT_Y412_BE:
+    case GST_VIDEO_FORMAT_Y412_LE:
       info->stride[0] = width * 8;
       info->offset[0] = 0;
       info->size = info->stride[0] * height;
       break;
     case GST_VIDEO_FORMAT_I420:
+    case GST_VIDEO_FORMAT_S420:
     case GST_VIDEO_FORMAT_YV12:        /* same as I420, but plane 1+2 swapped */
+#ifdef TIZEN_PROFILE_TV
+    case GST_VIDEO_FORMAT_STV0:
+    case GST_VIDEO_FORMAT_STV1:
+#endif
       info->stride[0] = GST_ROUND_UP_4 (width);
       info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
       info->stride[2] = info->stride[1];
@@ -793,6 +919,8 @@ fill_planes (GstVideoInfo * info)
       break;
     case GST_VIDEO_FORMAT_Y444:
     case GST_VIDEO_FORMAT_GBR:
+    case GST_VIDEO_FORMAT_RGBP:
+    case GST_VIDEO_FORMAT_BGRP:
       info->stride[0] = GST_ROUND_UP_4 (width);
       info->stride[1] = info->stride[0];
       info->stride[2] = info->stride[0];
@@ -801,16 +929,46 @@ fill_planes (GstVideoInfo * info)
       info->offset[2] = info->offset[1] * 2;
       info->size = info->stride[0] * height * 3;
       break;
+    case GST_VIDEO_FORMAT_GBRA:
+      info->stride[0] = GST_ROUND_UP_4 (width);
+      info->stride[1] = info->stride[0];
+      info->stride[2] = info->stride[0];
+      info->stride[3] = info->stride[0];
+      info->offset[0] = 0;
+      info->offset[1] = info->stride[0] * height;
+      info->offset[2] = info->offset[1] * 2;
+      info->offset[3] = info->offset[1] * 3;
+      info->size = info->stride[0] * height * 4;
+      break;
     case GST_VIDEO_FORMAT_NV12:
+#ifdef TIZEN_FEATURE_VIDEO_MODIFICATION
+    case GST_VIDEO_FORMAT_SN12:
+    case GST_VIDEO_FORMAT_ST12:
+    case GST_VIDEO_FORMAT_SN21:
+#endif
     case GST_VIDEO_FORMAT_NV21:
       info->stride[0] = GST_ROUND_UP_4 (width);
       info->stride[1] = info->stride[0];
       info->offset[0] = 0;
       info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
+#ifdef TIZEN_FEATURE_VIDEO_MODIFICATION
+      info->size = info->stride[0] * GST_ROUND_UP_2 (height) * 3 / 2;
+#else
       cr_h = GST_ROUND_UP_2 (height) / 2;
       if (GST_VIDEO_INFO_IS_INTERLACED (info))
         cr_h = GST_ROUND_UP_2 (cr_h);
       info->size = info->offset[1] + info->stride[0] * cr_h;
+#endif
+      break;
+    case GST_VIDEO_FORMAT_AV12:
+      info->stride[0] = GST_ROUND_UP_4 (width);
+      info->stride[1] = info->stride[0];
+      info->stride[2] = info->stride[0];
+      info->offset[0] = 0;
+      info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
+      info->offset[2] =
+          info->offset[1] + (info->stride[1] * GST_ROUND_UP_2 (height) / 2);
+      info->size = info->offset[2] + info->stride[2] * GST_ROUND_UP_2 (height);
       break;
     case GST_VIDEO_FORMAT_NV16:
     case GST_VIDEO_FORMAT_NV61:
@@ -856,6 +1014,8 @@ fill_planes (GstVideoInfo * info)
       break;
     case GST_VIDEO_FORMAT_I420_10LE:
     case GST_VIDEO_FORMAT_I420_10BE:
+    case GST_VIDEO_FORMAT_I420_12LE:
+    case GST_VIDEO_FORMAT_I420_12BE:
       info->stride[0] = GST_ROUND_UP_4 (width * 2);
       info->stride[1] = GST_ROUND_UP_4 (width);
       info->stride[2] = info->stride[1];
@@ -869,6 +1029,8 @@ fill_planes (GstVideoInfo * info)
       break;
     case GST_VIDEO_FORMAT_I422_10LE:
     case GST_VIDEO_FORMAT_I422_10BE:
+    case GST_VIDEO_FORMAT_I422_12LE:
+    case GST_VIDEO_FORMAT_I422_12BE:
       info->stride[0] = GST_ROUND_UP_4 (width * 2);
       info->stride[1] = GST_ROUND_UP_4 (width);
       info->stride[2] = info->stride[1];
@@ -880,8 +1042,14 @@ fill_planes (GstVideoInfo * info)
       break;
     case GST_VIDEO_FORMAT_Y444_10LE:
     case GST_VIDEO_FORMAT_Y444_10BE:
+    case GST_VIDEO_FORMAT_Y444_12LE:
+    case GST_VIDEO_FORMAT_Y444_12BE:
     case GST_VIDEO_FORMAT_GBR_10LE:
     case GST_VIDEO_FORMAT_GBR_10BE:
+    case GST_VIDEO_FORMAT_GBR_12LE:
+    case GST_VIDEO_FORMAT_GBR_12BE:
+    case GST_VIDEO_FORMAT_Y444_16LE:
+    case GST_VIDEO_FORMAT_Y444_16BE:
       info->stride[0] = GST_ROUND_UP_4 (width * 2);
       info->stride[1] = info->stride[0];
       info->stride[2] = info->stride[0];
@@ -890,6 +1058,20 @@ fill_planes (GstVideoInfo * info)
       info->offset[2] = info->offset[1] * 2;
       info->size = info->stride[0] * height * 3;
       break;
+    case GST_VIDEO_FORMAT_GBRA_10LE:
+    case GST_VIDEO_FORMAT_GBRA_10BE:
+    case GST_VIDEO_FORMAT_GBRA_12LE:
+    case GST_VIDEO_FORMAT_GBRA_12BE:
+      info->stride[0] = GST_ROUND_UP_4 (width * 2);
+      info->stride[1] = info->stride[0];
+      info->stride[2] = info->stride[0];
+      info->stride[3] = info->stride[0];
+      info->offset[0] = 0;
+      info->offset[1] = info->stride[0] * height;
+      info->offset[2] = info->offset[1] * 2;
+      info->offset[3] = info->offset[1] * 3;
+      info->size = info->stride[0] * height * 4;
+      break;
     case GST_VIDEO_FORMAT_NV12_64Z32:
       info->stride[0] =
           GST_VIDEO_TILE_MAKE_STRIDE (GST_ROUND_UP_128 (width) / 64,
@@ -900,8 +1082,27 @@ fill_planes (GstVideoInfo * info)
       info->offset[0] = 0;
       info->offset[1] = GST_ROUND_UP_128 (width) * GST_ROUND_UP_32 (height);
       info->size = info->offset[1] +
-          GST_ROUND_UP_128 (width) * GST_ROUND_UP_64 (height) / 2;
+          GST_ROUND_UP_128 (width) * (GST_ROUND_UP_64 (height) / 2);
       break;
+    case GST_VIDEO_FORMAT_NV12_4L4:
+    case GST_VIDEO_FORMAT_NV12_32L32:
+    {
+      gint ws = GST_VIDEO_FORMAT_INFO_TILE_WS (info->finfo);
+      gint hs = GST_VIDEO_FORMAT_INFO_TILE_HS (info->finfo);
+      info->stride[0] =
+          GST_VIDEO_TILE_MAKE_STRIDE (GST_ROUND_UP_N (width, 1 << ws) >> ws,
+          GST_ROUND_UP_N (height, 1 << hs) >> hs);
+      info->stride[1] =
+          GST_VIDEO_TILE_MAKE_STRIDE (GST_ROUND_UP_N (width, 1 << ws) >> ws,
+          GST_ROUND_UP_N (height, 1 << (hs + 1)) >> (hs + 1));
+      info->offset[0] = 0;
+      info->offset[1] =
+          GST_ROUND_UP_N (width, 1 << ws) * GST_ROUND_UP_N (height, 1 << hs);
+      info->size = info->offset[1] +
+          GST_ROUND_UP_N (width, 1 << ws) *
+          (GST_ROUND_UP_N (height, 1 << (hs + 1)) / 2);
+      break;
+    }
     case GST_VIDEO_FORMAT_A420_10LE:
     case GST_VIDEO_FORMAT_A420_10BE:
       info->stride[0] = GST_ROUND_UP_4 (width * 2);
@@ -945,6 +1146,10 @@ fill_planes (GstVideoInfo * info)
       break;
     case GST_VIDEO_FORMAT_P010_10LE:
     case GST_VIDEO_FORMAT_P010_10BE:
+    case GST_VIDEO_FORMAT_P016_LE:
+    case GST_VIDEO_FORMAT_P016_BE:
+    case GST_VIDEO_FORMAT_P012_LE:
+    case GST_VIDEO_FORMAT_P012_BE:
       info->stride[0] = GST_ROUND_UP_4 (width * 2);
       info->stride[1] = info->stride[0];
       info->offset[0] = 0;
@@ -952,15 +1157,70 @@ fill_planes (GstVideoInfo * info)
       cr_h = GST_ROUND_UP_2 (height) / 2;
       info->size = info->offset[1] + info->stride[0] * cr_h;
       break;
+    case GST_VIDEO_FORMAT_GRAY10_LE32:
+      info->stride[0] = (width + 2) / 3 * 4;
+      info->offset[0] = 0;
+      info->size = info->stride[0] * GST_ROUND_UP_2 (height);
+      break;
+    case GST_VIDEO_FORMAT_NV12_10LE32:
+      info->stride[0] = (width + 2) / 3 * 4;
+      info->stride[1] = info->stride[0];
+      info->offset[0] = 0;
+      info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
+      cr_h = GST_ROUND_UP_2 (height) / 2;
+      if (GST_VIDEO_INFO_IS_INTERLACED (info))
+        cr_h = GST_ROUND_UP_2 (cr_h);
+      info->size = info->offset[1] + info->stride[0] * cr_h;
+      break;
+    case GST_VIDEO_FORMAT_NV16_10LE32:
+      info->stride[0] = (width + 2) / 3 * 4;
+      info->stride[1] = info->stride[0];
+      info->offset[0] = 0;
+      info->offset[1] = info->stride[0] * height;
+      info->size = info->stride[0] * height * 2;
+      break;
+    case GST_VIDEO_FORMAT_NV12_10LE40:
+      info->stride[0] = ((width * 5 >> 2) + 4) / 5 * 5;
+      info->stride[1] = info->stride[0];
+      info->offset[0] = 0;
+      info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
+      cr_h = GST_ROUND_UP_2 (height) / 2;
+      if (GST_VIDEO_INFO_IS_INTERLACED (info))
+        cr_h = GST_ROUND_UP_2 (cr_h);
+      info->size = info->offset[1] + info->stride[0] * cr_h;
+      break;
 
     case GST_VIDEO_FORMAT_ENCODED:
       break;
     case GST_VIDEO_FORMAT_UNKNOWN:
+#ifdef TIZEN_FEATURE_VIDEO_MODIFICATION
+    default:
+#endif
       GST_ERROR ("invalid format");
       g_warning ("invalid format");
+      return FALSE;
       break;
   }
-  return 0;
+
+  if (plane_size) {
+    for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
+      if (i < GST_VIDEO_INFO_N_PLANES (info)) {
+        gint comp[GST_VIDEO_MAX_COMPONENTS];
+        guint plane_height;
+
+        /* Convert plane index to component index */
+        gst_video_format_info_component (info->finfo, i, comp);
+        plane_height =
+            GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (info->finfo, comp[0],
+            GST_VIDEO_INFO_FIELD_HEIGHT (info));
+        plane_size[i] = plane_height * GST_VIDEO_INFO_PLANE_STRIDE (info, i);
+      } else {
+        plane_size[i] = 0;
+      }
+    }
+  }
+
+  return TRUE;
 }
 
 /**
@@ -969,7 +1229,7 @@ fill_planes (GstVideoInfo * info)
  * @src_format: #GstFormat of the @src_value
  * @src_value: value to convert
  * @dest_format: #GstFormat of the @dest_value
- * @dest_value: pointer to destination value
+ * @dest_value: (out): pointer to destination value
  *
  * Converts among various #GstFormat types.  This function handles
  * GST_FORMAT_BYTES, GST_FORMAT_TIME, and GST_FORMAT_DEFAULT.  For
@@ -979,7 +1239,7 @@ fill_planes (GstVideoInfo * info)
  * Returns: TRUE if the conversion was successful.
  */
 gboolean
-gst_video_info_convert (GstVideoInfo * info,
+gst_video_info_convert (const GstVideoInfo * info,
     GstFormat src_format, gint64 src_value,
     GstFormat dest_format, gint64 * dest_value)
 {
@@ -1090,18 +1350,29 @@ done:
 }
 
 /**
- * gst_video_info_align:
+ * gst_video_info_align_full:
  * @info: a #GstVideoInfo
  * @align: alignment parameters
- *
- * Adjust the offset and stride fields in @info so that the padding and
- * stride alignment in @align is respected.
+ * @plane_size: (out) (allow-none): array used to store the plane sizes
  *
  * Extra padding will be added to the right side when stride alignment padding
  * is required and @align will be updated with the new padding values.
+ *
+ * This variant of gst_video_info_align() provides the updated size, in bytes,
+ * of each video plane after the alignment, including all horizontal and vertical
+ * paddings.
+ *
+ * In case of GST_VIDEO_INTERLACE_MODE_ALTERNATE info, the returned sizes are the
+ * ones used to hold a single field, not the full frame.
+ *
+ * Returns: %FALSE if alignment could not be applied, e.g. because the
+ *   size of a frame can't be represented as a 32 bit integer
+ *
+ * Since: 1.18
  */
-void
-gst_video_info_align (GstVideoInfo * info, GstVideoAlignment * align)
+gboolean
+gst_video_info_align_full (GstVideoInfo * info, GstVideoAlignment * align,
+    gsize plane_size[GST_VIDEO_MAX_PLANES])
 {
   const GstVideoFormatInfo *vinfo = info->finfo;
   gint width, height;
@@ -1125,11 +1396,14 @@ gst_video_info_align (GstVideoInfo * info, GstVideoAlignment * align)
     GST_LOG ("left padding %u", align->padding_left);
     aligned = TRUE;
     for (i = 0; i < n_planes; i++) {
+      gint comp[GST_VIDEO_MAX_COMPONENTS];
       gint hedge;
 
-      /* this is the amout of pixels to add as left padding */
-      hedge = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (vinfo, i, align->padding_left);
-      hedge *= GST_VIDEO_FORMAT_INFO_PSTRIDE (vinfo, i);
+      /* this is the amount of pixels to add as left padding */
+      gst_video_format_info_component (vinfo, i, comp);
+      hedge = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (vinfo, comp[0],
+          align->padding_left);
+      hedge *= GST_VIDEO_FORMAT_INFO_PSTRIDE (vinfo, comp[0]);
 
       GST_LOG ("plane %d, padding %d, alignment %u", i, hedge,
           align->stride_align[i]);
@@ -1152,7 +1426,9 @@ gst_video_info_align (GstVideoInfo * info, GstVideoAlignment * align)
 
     info->width = padded_width;
     info->height = padded_height;
-    fill_planes (info);
+
+    if (!fill_planes (info, plane_size))
+      return FALSE;
 
     /* check alignment */
     aligned = TRUE;
@@ -1175,24 +1451,41 @@ gst_video_info_align (GstVideoInfo * info, GstVideoAlignment * align)
   info->height = height;
 
   for (i = 0; i < n_planes; i++) {
-    gint vedge, hedge, comp;
-
-    /* Find the component for this plane, FIXME, we assume the plane number and
-     * component number is the same for now, for scaling the dimensions this is
-     * currently true for all formats but it might not be when adding new
-     * formats. We might need to add a plane subsamling in the format info to
-     * make this more generic or maybe use a plane -> component mapping. */
-    comp = i;
+    gint comp[GST_VIDEO_MAX_COMPONENTS];
+    gint vedge, hedge;
 
+    gst_video_format_info_component (info->finfo, i, comp);
     hedge =
-        GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (vinfo, comp, align->padding_left);
+        GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (vinfo, comp[0], align->padding_left);
     vedge =
-        GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (vinfo, comp, align->padding_top);
+        GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (vinfo, comp[0], align->padding_top);
 
     GST_DEBUG ("plane %d: comp: %d, hedge %d vedge %d align %d stride %d", i,
-        comp, hedge, vedge, align->stride_align[i], info->stride[i]);
+        comp[0], hedge, vedge, align->stride_align[i], info->stride[i]);
 
     info->offset[i] += (vedge * info->stride[i]) +
-        (hedge * GST_VIDEO_FORMAT_INFO_PSTRIDE (vinfo, comp));
+        (hedge * GST_VIDEO_FORMAT_INFO_PSTRIDE (vinfo, comp[0]));
   }
+
+  return TRUE;
+}
+
+/**
+ * gst_video_info_align:
+ * @info: a #GstVideoInfo
+ * @align: alignment parameters
+ *
+ * Adjust the offset and stride fields in @info so that the padding and
+ * stride alignment in @align is respected.
+ *
+ * Extra padding will be added to the right side when stride alignment padding
+ * is required and @align will be updated with the new padding values.
+ *
+ * Returns: %FALSE if alignment could not be applied, e.g. because the
+ *   size of a frame can't be represented as a 32 bit integer (Since: 1.12)
+ */
+gboolean
+gst_video_info_align (GstVideoInfo * info, GstVideoAlignment * align)
+{
+  return gst_video_info_align_full (info, align, NULL);
 }