X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gst-libs%2Fgst%2Fvideo%2Fvideo-info.c;h=93bede5178967be8ae1c233b5f1380eeadc7e904;hb=1b4ae195f72665dc21f133ee656333a025f67bb0;hp=0c4edab0b3ff5b3594e6f4af068f032061caa7c9;hpb=79809633de398d5495dbe2e3fa3c1bc6bd9f780d;p=platform%2Fupstream%2Fgstreamer.git diff --git a/gst-libs/gst/video/video-info.c b/gst-libs/gst/video/video-info.c index 0c4edab..93bede5 100644 --- a/gst-libs/gst/video/video-info.c +++ b/gst-libs/gst/video/video-info.c @@ -19,6 +19,12 @@ * 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), @@ -183,12 +192,41 @@ 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 (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; @@ -586,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: @@ -625,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; @@ -665,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: @@ -687,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; @@ -718,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; @@ -729,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; @@ -753,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]; @@ -792,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]; @@ -800,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: @@ -855,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]; @@ -868,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]; @@ -879,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]; @@ -889,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, @@ -899,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); @@ -944,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; @@ -951,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; } /** @@ -968,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 @@ -978,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) { @@ -1089,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; @@ -1124,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]); @@ -1151,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; @@ -1174,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); }