2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 * Library <2002> Ronald Bultje <rbultje@ronald.bitfreak.net>
4 * Copyright (C) 2007 David A. Schleef <ds@schleef.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
24 * @title: GstVideoInfo
25 * @short_description: Structures and enumerations to describe raw images
35 #include "video-info.h"
36 #include "video-tile.h"
38 #ifndef GST_DISABLE_GST_DEBUG
39 #define GST_CAT_DEFAULT ensure_debug_category()
40 static GstDebugCategory *
41 ensure_debug_category (void)
43 static gsize cat_gonce = 0;
45 if (g_once_init_enter (&cat_gonce)) {
48 cat_done = (gsize) _gst_debug_category_new ("video-info", 0,
49 "video-info structure");
51 g_once_init_leave (&cat_gonce, cat_done);
54 return (GstDebugCategory *) cat_gonce;
57 #define ensure_debug_category() /* NOOP */
58 #endif /* GST_DISABLE_GST_DEBUG */
61 * gst_video_info_copy:
62 * @info: a #GstVideoInfo
64 * Copy a GstVideoInfo structure.
66 * Returns: a new #GstVideoInfo. free with gst_video_info_free.
71 gst_video_info_copy (const GstVideoInfo * info)
73 return g_slice_dup (GstVideoInfo, info);
77 * gst_video_info_free:
78 * @info: a #GstVideoInfo
80 * Free a GstVideoInfo structure previously allocated with gst_video_info_new()
81 * or gst_video_info_copy().
86 gst_video_info_free (GstVideoInfo * info)
88 g_slice_free (GstVideoInfo, info);
91 G_DEFINE_BOXED_TYPE (GstVideoInfo, gst_video_info,
92 (GBoxedCopyFunc) gst_video_info_copy, (GBoxedFreeFunc) gst_video_info_free);
97 * Allocate a new #GstVideoInfo that is also initialized with
98 * gst_video_info_init().
100 * Returns: a new #GstVideoInfo. free with gst_video_info_free().
105 gst_video_info_new (void)
109 info = g_slice_new (GstVideoInfo);
110 gst_video_info_init (info);
115 static gboolean fill_planes (GstVideoInfo * info,
116 gsize plane_size[GST_VIDEO_MAX_PLANES]);
119 * gst_video_info_init:
120 * @info: (out caller-allocates): a #GstVideoInfo
122 * Initialize @info with default values.
125 gst_video_info_init (GstVideoInfo * info)
127 g_return_if_fail (info != NULL);
129 memset (info, 0, sizeof (GstVideoInfo));
131 info->finfo = gst_video_format_get_info (GST_VIDEO_FORMAT_UNKNOWN);
134 /* arrange for sensible defaults, e.g. if turned into caps */
139 GST_VIDEO_INFO_MULTIVIEW_MODE (info) = GST_VIDEO_MULTIVIEW_MODE_NONE;
140 GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
141 GST_VIDEO_INFO_FIELD_ORDER (info) = GST_VIDEO_FIELD_ORDER_UNKNOWN;
144 #define MAKE_COLORIMETRY(r,m,t,p) { \
145 GST_VIDEO_COLOR_RANGE ##r, GST_VIDEO_COLOR_MATRIX_ ##m, \
146 GST_VIDEO_TRANSFER_ ##t, GST_VIDEO_COLOR_PRIMARIES_ ##p }
148 #define DEFAULT_YUV_SD 0
149 #define DEFAULT_YUV_HD 1
150 #define DEFAULT_RGB 2
151 #define DEFAULT_GRAY 3
152 #define DEFAULT_UNKNOWN 4
153 #define DEFAULT_YUV_UHD 5
155 static const GstVideoColorimetry default_color[] = {
156 MAKE_COLORIMETRY (_16_235, BT601, BT601, SMPTE170M),
157 MAKE_COLORIMETRY (_16_235, BT709, BT709, BT709),
158 MAKE_COLORIMETRY (_0_255, RGB, SRGB, BT709),
159 MAKE_COLORIMETRY (_0_255, BT601, UNKNOWN, UNKNOWN),
160 MAKE_COLORIMETRY (_UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN),
161 MAKE_COLORIMETRY (_16_235, BT2020, BT2020_12, BT2020),
165 set_default_colorimetry (GstVideoInfo * info)
167 const GstVideoFormatInfo *finfo = info->finfo;
169 if (GST_VIDEO_FORMAT_INFO_IS_YUV (finfo)) {
170 if (info->height >= 2160) {
171 info->chroma_site = GST_VIDEO_CHROMA_SITE_H_COSITED;
172 info->colorimetry = default_color[DEFAULT_YUV_UHD];
173 } else if (info->height > 576) {
174 info->chroma_site = GST_VIDEO_CHROMA_SITE_H_COSITED;
175 info->colorimetry = default_color[DEFAULT_YUV_HD];
177 info->chroma_site = GST_VIDEO_CHROMA_SITE_NONE;
178 info->colorimetry = default_color[DEFAULT_YUV_SD];
180 } else if (GST_VIDEO_FORMAT_INFO_IS_GRAY (finfo)) {
181 info->colorimetry = default_color[DEFAULT_GRAY];
182 } else if (GST_VIDEO_FORMAT_INFO_IS_RGB (finfo)) {
183 info->colorimetry = default_color[DEFAULT_RGB];
185 info->colorimetry = default_color[DEFAULT_UNKNOWN];
190 validate_colorimetry (GstVideoInfo * info)
192 const GstVideoFormatInfo *finfo = info->finfo;
194 if (!GST_VIDEO_FORMAT_INFO_IS_RGB (finfo) &&
195 info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB) {
197 ("color matrix RGB is only supported with RGB format, %s is not",
202 if (GST_VIDEO_FORMAT_INFO_IS_YUV (finfo) &&
203 info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
204 GST_WARNING ("Need to specify a color matrix when using YUV format (%s)",
213 gst_video_info_set_format_common (GstVideoInfo * info, GstVideoFormat format,
214 guint width, guint height)
216 g_return_val_if_fail (info != NULL, FALSE);
217 g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, FALSE);
219 if (width > G_MAXINT || height > G_MAXINT)
222 gst_video_info_init (info);
224 info->finfo = gst_video_format_get_info (format);
226 info->height = height;
229 set_default_colorimetry (info);
235 * gst_video_info_set_format:
236 * @info: a #GstVideoInfo
237 * @format: the format
241 * Set the default info for a video frame of @format and @width and @height.
243 * Note: This initializes @info first, no values are preserved. This function
244 * does not set the offsets correctly for interlaced vertically
245 * subsampled formats.
247 * Returns: %FALSE if the returned video info is invalid, e.g. because the
248 * size of a frame can't be represented as a 32 bit integer (Since: 1.12)
251 gst_video_info_set_format (GstVideoInfo * info, GstVideoFormat format,
252 guint width, guint height)
254 if (!gst_video_info_set_format_common (info, format, width, height))
257 return fill_planes (info, NULL);
261 * gst_video_info_set_interlaced_format:
262 * @info: a #GstVideoInfo
263 * @format: the format
264 * @mode: a #GstVideoInterlaceMode
268 * Same as #gst_video_info_set_format but also allowing to set the interlaced
271 * Returns: %FALSE if the returned video info is invalid, e.g. because the
272 * size of a frame can't be represented as a 32 bit integer.
277 gst_video_info_set_interlaced_format (GstVideoInfo * info,
278 GstVideoFormat format, GstVideoInterlaceMode mode, guint width,
281 if (!gst_video_info_set_format_common (info, format, width, height))
284 GST_VIDEO_INFO_INTERLACE_MODE (info) = mode;
285 return fill_planes (info, NULL);
288 static const gchar *interlace_mode[] = {
297 * gst_video_interlace_mode_to_string:
298 * @mode: a #GstVideoInterlaceMode
300 * Convert @mode to its string representation.
302 * Returns: @mode as a string or NULL if @mode in invalid.
307 gst_video_interlace_mode_to_string (GstVideoInterlaceMode mode)
309 if (((guint) mode) >= G_N_ELEMENTS (interlace_mode))
312 return interlace_mode[mode];
316 * gst_video_interlace_mode_from_string:
319 * Convert @mode to a #GstVideoInterlaceMode
321 * Returns: the #GstVideoInterlaceMode of @mode or
322 * #GST_VIDEO_INTERLACE_MODE_PROGRESSIVE when @mode is not a valid
323 * string representation for a #GstVideoInterlaceMode.
327 GstVideoInterlaceMode
328 gst_video_interlace_mode_from_string (const gchar * mode)
331 for (i = 0; i < G_N_ELEMENTS (interlace_mode); i++) {
332 if (g_str_equal (interlace_mode[i], mode))
335 return GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
338 static const gchar *field_order[] = {
345 * gst_video_field_order_to_string:
346 * @order: a #GstVideoFieldOrder
348 * Convert @order to its string representation.
350 * Returns: @order as a string or NULL if @order in invalid.
355 gst_video_field_order_to_string (GstVideoFieldOrder order)
357 if (((guint) order) >= G_N_ELEMENTS (field_order))
360 return field_order[order];
364 * gst_video_field_order_from_string:
365 * @order: a field order
367 * Convert @order to a #GstVideoFieldOrder
369 * Returns: the #GstVideoFieldOrder of @order or
370 * #GST_VIDEO_FIELD_ORDER_UNKNOWN when @order is not a valid
371 * string representation for a #GstVideoFieldOrder.
376 gst_video_field_order_from_string (const gchar * order)
379 for (i = 0; i < G_N_ELEMENTS (field_order); i++) {
380 if (g_str_equal (field_order[i], order))
383 return GST_VIDEO_FIELD_ORDER_UNKNOWN;
387 * gst_video_info_from_caps:
388 * @info: (out caller-allocates): #GstVideoInfo
391 * Parse @caps and update @info.
393 * Returns: TRUE if @caps could be parsed
396 gst_video_info_from_caps (GstVideoInfo * info, const GstCaps * caps)
398 GstStructure *structure;
400 GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
401 gint width = 0, height = 0;
404 guint multiview_flags;
406 g_return_val_if_fail (info != NULL, FALSE);
407 g_return_val_if_fail (caps != NULL, FALSE);
408 g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
410 GST_DEBUG ("parsing caps %" GST_PTR_FORMAT, caps);
412 structure = gst_caps_get_structure (caps, 0);
414 if (gst_structure_has_name (structure, "video/x-raw")) {
415 if (!(s = gst_structure_get_string (structure, "format")))
418 format = gst_video_format_from_string (s);
419 if (format == GST_VIDEO_FORMAT_UNKNOWN)
422 } else if (g_str_has_prefix (gst_structure_get_name (structure), "video/") ||
423 g_str_has_prefix (gst_structure_get_name (structure), "image/")) {
424 format = GST_VIDEO_FORMAT_ENCODED;
429 /* width and height are mandatory, except for non-raw-formats */
430 if (!gst_structure_get_int (structure, "width", &width) &&
431 format != GST_VIDEO_FORMAT_ENCODED)
433 if (!gst_structure_get_int (structure, "height", &height) &&
434 format != GST_VIDEO_FORMAT_ENCODED)
437 gst_video_info_init (info);
439 info->finfo = gst_video_format_get_info (format);
441 info->height = height;
443 if (gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d)) {
445 /* variable framerate */
446 info->flags |= GST_VIDEO_FLAG_VARIABLE_FPS;
447 /* see if we have a max-framerate */
448 gst_structure_get_fraction (structure, "max-framerate", &fps_n, &fps_d);
453 /* unspecified is variable framerate */
458 if (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
467 if ((s = gst_structure_get_string (structure, "interlace-mode")))
468 info->interlace_mode = gst_video_interlace_mode_from_string (s);
470 info->interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
472 /* Interlaced feature is mandatory for raw alternate streams */
473 if (info->interlace_mode == GST_VIDEO_INTERLACE_MODE_ALTERNATE &&
474 format != GST_VIDEO_FORMAT_ENCODED) {
477 f = gst_caps_get_features (caps, 0);
479 || !gst_caps_features_contains (f, GST_CAPS_FEATURE_FORMAT_INTERLACED))
480 goto alternate_no_feature;
483 if (GST_VIDEO_INFO_IS_INTERLACED (info) &&
484 (s = gst_structure_get_string (structure, "field-order"))) {
485 GST_VIDEO_INFO_FIELD_ORDER (info) = gst_video_field_order_from_string (s);
487 GST_VIDEO_INFO_FIELD_ORDER (info) = GST_VIDEO_FIELD_ORDER_UNKNOWN;
491 if ((s = gst_structure_get_string (structure, "multiview-mode")))
492 GST_VIDEO_INFO_MULTIVIEW_MODE (info) =
493 gst_video_multiview_mode_from_caps_string (s);
495 GST_VIDEO_INFO_MULTIVIEW_MODE (info) = GST_VIDEO_MULTIVIEW_MODE_NONE;
497 if (gst_structure_get_flagset (structure, "multiview-flags",
498 &multiview_flags, NULL))
499 GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) = multiview_flags;
501 if (!gst_structure_get_int (structure, "views", &info->views))
504 /* At one point, I tried normalising the half-aspect flag here,
505 * but it behaves weird for GstVideoInfo operations other than
506 * directly converting to/from caps - sometimes causing the
507 * PAR to be doubled/halved too many times */
510 if ((s = gst_structure_get_string (structure, "chroma-site")))
511 info->chroma_site = gst_video_chroma_site_from_string (s);
513 info->chroma_site = GST_VIDEO_CHROMA_SITE_UNKNOWN;
515 if ((s = gst_structure_get_string (structure, "colorimetry"))) {
516 if (!gst_video_colorimetry_from_string (&info->colorimetry, s)) {
517 GST_WARNING ("unparsable colorimetry, using default");
518 set_default_colorimetry (info);
519 } else if (!validate_colorimetry (info)) {
520 GST_WARNING ("invalid colorimetry, using default");
521 set_default_colorimetry (info);
523 /* force RGB matrix for RGB formats */
524 if (GST_VIDEO_FORMAT_INFO_IS_RGB (info->finfo) &&
525 info->colorimetry.matrix != GST_VIDEO_COLOR_MATRIX_RGB) {
526 GST_WARNING ("invalid matrix %d for RGB format, using RGB",
527 info->colorimetry.matrix);
528 info->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_RGB;
532 GST_DEBUG ("no colorimetry, using default");
533 set_default_colorimetry (info);
536 if (!fill_planes (info, NULL))
544 GST_ERROR ("wrong name '%s', expected video/ or image/",
545 gst_structure_get_name (structure));
550 GST_ERROR ("no format given");
555 GST_ERROR ("unknown format '%s' given", s);
560 GST_ERROR ("no width property given");
565 GST_ERROR ("no height property given");
568 alternate_no_feature:
571 ("caps has 'interlace-mode=alternate' but doesn't have the Interlaced feature");
577 * gst_video_info_is_equal:
578 * @info: a #GstVideoInfo
579 * @other: a #GstVideoInfo
581 * Compares two #GstVideoInfo and returns whether they are equal or not
583 * Returns: %TRUE if @info and @other are equal, else %FALSE.
586 gst_video_info_is_equal (const GstVideoInfo * info, const GstVideoInfo * other)
590 if (GST_VIDEO_INFO_FORMAT (info) != GST_VIDEO_INFO_FORMAT (other))
592 if (GST_VIDEO_INFO_INTERLACE_MODE (info) !=
593 GST_VIDEO_INFO_INTERLACE_MODE (other))
595 if (GST_VIDEO_INFO_FLAGS (info) != GST_VIDEO_INFO_FLAGS (other))
597 if (GST_VIDEO_INFO_WIDTH (info) != GST_VIDEO_INFO_WIDTH (other))
599 if (GST_VIDEO_INFO_HEIGHT (info) != GST_VIDEO_INFO_HEIGHT (other))
601 if (GST_VIDEO_INFO_SIZE (info) != GST_VIDEO_INFO_SIZE (other))
603 if (GST_VIDEO_INFO_PAR_N (info) != GST_VIDEO_INFO_PAR_N (other))
605 if (GST_VIDEO_INFO_PAR_D (info) != GST_VIDEO_INFO_PAR_D (other))
607 if (GST_VIDEO_INFO_FPS_N (info) != GST_VIDEO_INFO_FPS_N (other))
609 if (GST_VIDEO_INFO_FPS_D (info) != GST_VIDEO_INFO_FPS_D (other))
611 if (!gst_video_colorimetry_is_equal (&GST_VIDEO_INFO_COLORIMETRY (info),
612 &GST_VIDEO_INFO_COLORIMETRY (other)))
614 if (GST_VIDEO_INFO_CHROMA_SITE (info) != GST_VIDEO_INFO_CHROMA_SITE (other))
616 if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) !=
617 GST_VIDEO_INFO_MULTIVIEW_MODE (other))
619 if (GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) !=
620 GST_VIDEO_INFO_MULTIVIEW_FLAGS (other))
622 if (GST_VIDEO_INFO_VIEWS (info) != GST_VIDEO_INFO_VIEWS (other))
625 for (i = 0; i < info->finfo->n_planes; i++) {
626 if (info->stride[i] != other->stride[i])
628 if (info->offset[i] != other->offset[i])
636 * gst_video_info_to_caps:
637 * @info: a #GstVideoInfo
639 * Convert the values of @info into a #GstCaps.
641 * Returns: a new #GstCaps containing the info of @info.
644 gst_video_info_to_caps (const GstVideoInfo * info)
650 GstVideoColorimetry colorimetry;
652 g_return_val_if_fail (info != NULL, NULL);
653 g_return_val_if_fail (info->finfo != NULL, NULL);
654 g_return_val_if_fail (info->finfo->format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
656 format = gst_video_format_to_string (info->finfo->format);
657 g_return_val_if_fail (format != NULL, NULL);
659 caps = gst_caps_new_simple ("video/x-raw",
660 "format", G_TYPE_STRING, format,
661 "width", G_TYPE_INT, info->width,
662 "height", G_TYPE_INT, info->height, NULL);
667 gst_caps_set_simple (caps, "interlace-mode", G_TYPE_STRING,
668 gst_video_interlace_mode_to_string (info->interlace_mode), NULL);
670 if ((info->interlace_mode == GST_VIDEO_INTERLACE_MODE_INTERLEAVED ||
671 info->interlace_mode == GST_VIDEO_INTERLACE_MODE_ALTERNATE) &&
672 GST_VIDEO_INFO_FIELD_ORDER (info) != GST_VIDEO_FIELD_ORDER_UNKNOWN) {
673 gst_caps_set_simple (caps, "field-order", G_TYPE_STRING,
674 gst_video_field_order_to_string (GST_VIDEO_INFO_FIELD_ORDER (info)),
678 if (info->interlace_mode == GST_VIDEO_INTERLACE_MODE_ALTERNATE) {
679 /* 'alternate' mode must always be accompanied by interlaced caps feature.
681 GstCapsFeatures *features;
683 features = gst_caps_features_new (GST_CAPS_FEATURE_FORMAT_INTERLACED, NULL);
684 gst_caps_set_features (caps, 0, features);
687 if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) != GST_VIDEO_MULTIVIEW_MODE_NONE) {
688 const gchar *caps_str = NULL;
689 GstVideoMultiviewFlags multiview_flags =
690 GST_VIDEO_INFO_MULTIVIEW_FLAGS (info);
692 /* If the half-aspect flag is set, applying it into the PAR of the
693 * resulting caps now seems safe, and helps with automatic behaviour
694 * in elements that aren't explicitly multiview aware */
695 if (multiview_flags & GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT) {
696 multiview_flags &= ~GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
697 switch (GST_VIDEO_INFO_MULTIVIEW_MODE (info)) {
698 case GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE:
699 case GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX:
700 case GST_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED:
701 case GST_VIDEO_MULTIVIEW_MODE_CHECKERBOARD:
702 par_n *= 2; /* double the width / half the height */
704 case GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED:
705 case GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM:
706 par_d *= 2; /* half the width / double the height */
714 gst_video_multiview_mode_to_caps_string (GST_VIDEO_INFO_MULTIVIEW_MODE
716 if (caps_str != NULL) {
717 gst_caps_set_simple (caps, "multiview-mode", G_TYPE_STRING,
718 caps_str, "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
719 multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
723 gst_caps_set_simple (caps, "pixel-aspect-ratio",
724 GST_TYPE_FRACTION, par_n, par_d, NULL);
726 if (info->chroma_site != GST_VIDEO_CHROMA_SITE_UNKNOWN) {
727 gchar *chroma_site = gst_video_chroma_site_to_string (info->chroma_site);
730 GST_WARNING ("Couldn't convert chroma-site 0x%x to string",
733 gst_caps_set_simple (caps,
734 "chroma-site", G_TYPE_STRING, chroma_site, NULL);
735 g_free (chroma_site);
739 /* make sure we set the RGB matrix for RGB formats */
740 colorimetry = info->colorimetry;
741 if (GST_VIDEO_FORMAT_INFO_IS_RGB (info->finfo) &&
742 colorimetry.matrix != GST_VIDEO_COLOR_MATRIX_RGB) {
743 GST_WARNING ("invalid matrix %d for RGB format, using RGB",
745 colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_RGB;
747 if ((color = gst_video_colorimetry_to_string (&colorimetry))) {
748 gst_caps_set_simple (caps, "colorimetry", G_TYPE_STRING, color, NULL);
753 gst_caps_set_simple (caps, "views", G_TYPE_INT, info->views, NULL);
755 if (info->flags & GST_VIDEO_FLAG_VARIABLE_FPS && info->fps_n != 0) {
756 /* variable fps with a max-framerate */
757 gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, 0, 1,
758 "max-framerate", GST_TYPE_FRACTION, info->fps_n, info->fps_d, NULL);
760 /* no variable fps or no max-framerate */
761 gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION,
762 info->fps_n, info->fps_d, NULL);
769 fill_planes (GstVideoInfo * info, gsize plane_size[GST_VIDEO_MAX_PLANES])
771 gsize width, height, cr_h;
774 width = (gsize) info->width;
775 height = (gsize) GST_VIDEO_INFO_FIELD_HEIGHT (info);
777 /* Sanity check the resulting frame size for overflows */
778 for (i = 0; i < GST_VIDEO_INFO_N_COMPONENTS (info); i++)
779 bpp += GST_VIDEO_INFO_COMP_DEPTH (info, i);
780 bpp = GST_ROUND_UP_8 (bpp) / 8;
781 if (bpp > 0 && GST_ROUND_UP_128 ((guint64) width) * ((guint64) height) >=
783 GST_ERROR ("Frame size %ux%u would overflow", info->width, info->height);
787 switch (info->finfo->format) {
788 case GST_VIDEO_FORMAT_YUY2:
789 case GST_VIDEO_FORMAT_YVYU:
790 case GST_VIDEO_FORMAT_UYVY:
791 case GST_VIDEO_FORMAT_VYUY:
792 info->stride[0] = GST_ROUND_UP_4 (width * 2);
794 info->size = info->stride[0] * height;
796 case GST_VIDEO_FORMAT_AYUV:
797 case GST_VIDEO_FORMAT_RGBx:
798 case GST_VIDEO_FORMAT_RGBA:
799 case GST_VIDEO_FORMAT_BGRx:
800 case GST_VIDEO_FORMAT_BGRA:
801 case GST_VIDEO_FORMAT_SR32:
802 case GST_VIDEO_FORMAT_xRGB:
803 case GST_VIDEO_FORMAT_ARGB:
804 case GST_VIDEO_FORMAT_xBGR:
805 case GST_VIDEO_FORMAT_ABGR:
806 case GST_VIDEO_FORMAT_r210:
807 case GST_VIDEO_FORMAT_Y410:
808 case GST_VIDEO_FORMAT_VUYA:
809 case GST_VIDEO_FORMAT_BGR10A2_LE:
810 case GST_VIDEO_FORMAT_RGB10A2_LE:
811 info->stride[0] = width * 4;
813 info->size = info->stride[0] * height;
815 case GST_VIDEO_FORMAT_RGB16:
816 case GST_VIDEO_FORMAT_BGR16:
817 case GST_VIDEO_FORMAT_RGB15:
818 case GST_VIDEO_FORMAT_BGR15:
819 info->stride[0] = GST_ROUND_UP_4 (width * 2);
821 info->size = info->stride[0] * height;
823 case GST_VIDEO_FORMAT_RGB:
824 case GST_VIDEO_FORMAT_BGR:
825 case GST_VIDEO_FORMAT_v308:
826 case GST_VIDEO_FORMAT_IYU2:
827 info->stride[0] = GST_ROUND_UP_4 (width * 3);
829 info->size = info->stride[0] * height;
831 case GST_VIDEO_FORMAT_v210:
832 info->stride[0] = ((width + 47) / 48) * 128;
834 info->size = info->stride[0] * height;
836 case GST_VIDEO_FORMAT_v216:
837 case GST_VIDEO_FORMAT_Y210:
838 case GST_VIDEO_FORMAT_Y212_BE:
839 case GST_VIDEO_FORMAT_Y212_LE:
840 info->stride[0] = GST_ROUND_UP_8 (width * 4);
842 info->size = info->stride[0] * height;
844 case GST_VIDEO_FORMAT_GRAY8:
845 info->stride[0] = GST_ROUND_UP_4 (width);
847 info->size = info->stride[0] * height;
849 case GST_VIDEO_FORMAT_GRAY16_BE:
850 case GST_VIDEO_FORMAT_GRAY16_LE:
851 case GST_VIDEO_FORMAT_INVZ:
852 info->stride[0] = GST_ROUND_UP_4 (width * 2);
854 info->size = info->stride[0] * height;
856 case GST_VIDEO_FORMAT_UYVP:
857 info->stride[0] = GST_ROUND_UP_4 ((width * 2 * 5 + 3) / 4);
859 info->size = info->stride[0] * height;
861 case GST_VIDEO_FORMAT_RGB8P:
862 info->stride[0] = GST_ROUND_UP_4 (width);
865 info->offset[1] = info->stride[0] * height;
866 info->size = info->offset[1] + (4 * 256);
868 case GST_VIDEO_FORMAT_IYU1:
869 info->stride[0] = GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) +
870 GST_ROUND_UP_4 (width) / 2);
872 info->size = info->stride[0] * height;
874 case GST_VIDEO_FORMAT_ARGB64:
875 case GST_VIDEO_FORMAT_AYUV64:
876 case GST_VIDEO_FORMAT_Y412_BE:
877 case GST_VIDEO_FORMAT_Y412_LE:
878 info->stride[0] = width * 8;
880 info->size = info->stride[0] * height;
882 case GST_VIDEO_FORMAT_I420:
883 case GST_VIDEO_FORMAT_S420:
884 case GST_VIDEO_FORMAT_YV12: /* same as I420, but plane 1+2 swapped */
885 #ifdef TIZEN_PROFILE_TV
886 case GST_VIDEO_FORMAT_STV0:
887 case GST_VIDEO_FORMAT_STV1:
889 info->stride[0] = GST_ROUND_UP_4 (width);
890 info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
891 info->stride[2] = info->stride[1];
893 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
894 cr_h = GST_ROUND_UP_2 (height) / 2;
895 if (GST_VIDEO_INFO_IS_INTERLACED (info))
896 cr_h = GST_ROUND_UP_2 (cr_h);
897 info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
898 info->size = info->offset[2] + info->stride[2] * cr_h;
900 case GST_VIDEO_FORMAT_Y41B:
901 info->stride[0] = GST_ROUND_UP_4 (width);
902 info->stride[1] = GST_ROUND_UP_16 (width) / 4;
903 info->stride[2] = info->stride[1];
905 info->offset[1] = info->stride[0] * height;
906 info->offset[2] = info->offset[1] + info->stride[1] * height;
907 /* simplification of ROUNDUP4(w)*h + 2*((ROUNDUP16(w)/4)*h */
908 info->size = (info->stride[0] + (GST_ROUND_UP_16 (width) / 2)) * height;
910 case GST_VIDEO_FORMAT_Y42B:
911 info->stride[0] = GST_ROUND_UP_4 (width);
912 info->stride[1] = GST_ROUND_UP_8 (width) / 2;
913 info->stride[2] = info->stride[1];
915 info->offset[1] = info->stride[0] * height;
916 info->offset[2] = info->offset[1] + info->stride[1] * height;
917 /* simplification of ROUNDUP4(w)*h + 2*(ROUNDUP8(w)/2)*h */
918 info->size = (info->stride[0] + GST_ROUND_UP_8 (width)) * height;
920 case GST_VIDEO_FORMAT_Y444:
921 case GST_VIDEO_FORMAT_GBR:
922 case GST_VIDEO_FORMAT_RGBP:
923 case GST_VIDEO_FORMAT_BGRP:
924 info->stride[0] = GST_ROUND_UP_4 (width);
925 info->stride[1] = info->stride[0];
926 info->stride[2] = info->stride[0];
928 info->offset[1] = info->stride[0] * height;
929 info->offset[2] = info->offset[1] * 2;
930 info->size = info->stride[0] * height * 3;
932 case GST_VIDEO_FORMAT_GBRA:
933 info->stride[0] = GST_ROUND_UP_4 (width);
934 info->stride[1] = info->stride[0];
935 info->stride[2] = info->stride[0];
936 info->stride[3] = info->stride[0];
938 info->offset[1] = info->stride[0] * height;
939 info->offset[2] = info->offset[1] * 2;
940 info->offset[3] = info->offset[1] * 3;
941 info->size = info->stride[0] * height * 4;
943 case GST_VIDEO_FORMAT_NV12:
944 #ifdef TIZEN_FEATURE_VIDEO_MODIFICATION
945 case GST_VIDEO_FORMAT_SN12:
946 case GST_VIDEO_FORMAT_ST12:
947 case GST_VIDEO_FORMAT_SN21:
949 case GST_VIDEO_FORMAT_NV21:
950 info->stride[0] = GST_ROUND_UP_4 (width);
951 info->stride[1] = info->stride[0];
953 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
954 #ifdef TIZEN_FEATURE_VIDEO_MODIFICATION
955 info->size = info->stride[0] * GST_ROUND_UP_2 (height) * 3 / 2;
957 cr_h = GST_ROUND_UP_2 (height) / 2;
958 if (GST_VIDEO_INFO_IS_INTERLACED (info))
959 cr_h = GST_ROUND_UP_2 (cr_h);
960 info->size = info->offset[1] + info->stride[0] * cr_h;
963 case GST_VIDEO_FORMAT_AV12:
964 info->stride[0] = GST_ROUND_UP_4 (width);
965 info->stride[1] = info->stride[0];
966 info->stride[2] = info->stride[0];
968 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
970 info->offset[1] + (info->stride[1] * GST_ROUND_UP_2 (height) / 2);
971 info->size = info->offset[2] + info->stride[2] * GST_ROUND_UP_2 (height);
973 case GST_VIDEO_FORMAT_NV16:
974 case GST_VIDEO_FORMAT_NV61:
975 info->stride[0] = GST_ROUND_UP_4 (width);
976 info->stride[1] = info->stride[0];
978 info->offset[1] = info->stride[0] * height;
979 info->size = info->stride[0] * height * 2;
981 case GST_VIDEO_FORMAT_NV24:
982 info->stride[0] = GST_ROUND_UP_4 (width);
983 info->stride[1] = GST_ROUND_UP_4 (width * 2);
985 info->offset[1] = info->stride[0] * height;
986 info->size = info->stride[0] * height + info->stride[1] * height;
988 case GST_VIDEO_FORMAT_A420:
989 info->stride[0] = GST_ROUND_UP_4 (width);
990 info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
991 info->stride[2] = info->stride[1];
992 info->stride[3] = info->stride[0];
994 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
995 cr_h = GST_ROUND_UP_2 (height) / 2;
996 if (GST_VIDEO_INFO_IS_INTERLACED (info))
997 cr_h = GST_ROUND_UP_2 (cr_h);
998 info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
999 info->offset[3] = info->offset[2] + info->stride[2] * cr_h;
1000 info->size = info->offset[3] + info->stride[0] * GST_ROUND_UP_2 (height);
1002 case GST_VIDEO_FORMAT_YUV9:
1003 case GST_VIDEO_FORMAT_YVU9:
1004 info->stride[0] = GST_ROUND_UP_4 (width);
1005 info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4);
1006 info->stride[2] = info->stride[1];
1007 info->offset[0] = 0;
1008 info->offset[1] = info->stride[0] * height;
1009 cr_h = GST_ROUND_UP_4 (height) / 4;
1010 if (GST_VIDEO_INFO_IS_INTERLACED (info))
1011 cr_h = GST_ROUND_UP_2 (cr_h);
1012 info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
1013 info->size = info->offset[2] + info->stride[2] * cr_h;
1015 case GST_VIDEO_FORMAT_I420_10LE:
1016 case GST_VIDEO_FORMAT_I420_10BE:
1017 case GST_VIDEO_FORMAT_I420_12LE:
1018 case GST_VIDEO_FORMAT_I420_12BE:
1019 info->stride[0] = GST_ROUND_UP_4 (width * 2);
1020 info->stride[1] = GST_ROUND_UP_4 (width);
1021 info->stride[2] = info->stride[1];
1022 info->offset[0] = 0;
1023 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
1024 cr_h = GST_ROUND_UP_2 (height) / 2;
1025 if (GST_VIDEO_INFO_IS_INTERLACED (info))
1026 cr_h = GST_ROUND_UP_2 (cr_h);
1027 info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
1028 info->size = info->offset[2] + info->stride[2] * cr_h;
1030 case GST_VIDEO_FORMAT_I422_10LE:
1031 case GST_VIDEO_FORMAT_I422_10BE:
1032 case GST_VIDEO_FORMAT_I422_12LE:
1033 case GST_VIDEO_FORMAT_I422_12BE:
1034 info->stride[0] = GST_ROUND_UP_4 (width * 2);
1035 info->stride[1] = GST_ROUND_UP_4 (width);
1036 info->stride[2] = info->stride[1];
1037 info->offset[0] = 0;
1038 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
1039 info->offset[2] = info->offset[1] +
1040 info->stride[1] * GST_ROUND_UP_2 (height);
1041 info->size = info->offset[2] + info->stride[2] * GST_ROUND_UP_2 (height);
1043 case GST_VIDEO_FORMAT_Y444_10LE:
1044 case GST_VIDEO_FORMAT_Y444_10BE:
1045 case GST_VIDEO_FORMAT_Y444_12LE:
1046 case GST_VIDEO_FORMAT_Y444_12BE:
1047 case GST_VIDEO_FORMAT_GBR_10LE:
1048 case GST_VIDEO_FORMAT_GBR_10BE:
1049 case GST_VIDEO_FORMAT_GBR_12LE:
1050 case GST_VIDEO_FORMAT_GBR_12BE:
1051 case GST_VIDEO_FORMAT_Y444_16LE:
1052 case GST_VIDEO_FORMAT_Y444_16BE:
1053 info->stride[0] = GST_ROUND_UP_4 (width * 2);
1054 info->stride[1] = info->stride[0];
1055 info->stride[2] = info->stride[0];
1056 info->offset[0] = 0;
1057 info->offset[1] = info->stride[0] * height;
1058 info->offset[2] = info->offset[1] * 2;
1059 info->size = info->stride[0] * height * 3;
1061 case GST_VIDEO_FORMAT_GBRA_10LE:
1062 case GST_VIDEO_FORMAT_GBRA_10BE:
1063 case GST_VIDEO_FORMAT_GBRA_12LE:
1064 case GST_VIDEO_FORMAT_GBRA_12BE:
1065 info->stride[0] = GST_ROUND_UP_4 (width * 2);
1066 info->stride[1] = info->stride[0];
1067 info->stride[2] = info->stride[0];
1068 info->stride[3] = info->stride[0];
1069 info->offset[0] = 0;
1070 info->offset[1] = info->stride[0] * height;
1071 info->offset[2] = info->offset[1] * 2;
1072 info->offset[3] = info->offset[1] * 3;
1073 info->size = info->stride[0] * height * 4;
1075 case GST_VIDEO_FORMAT_NV12_64Z32:
1077 GST_VIDEO_TILE_MAKE_STRIDE (GST_ROUND_UP_128 (width) / 64,
1078 GST_ROUND_UP_32 (height) / 32);
1080 GST_VIDEO_TILE_MAKE_STRIDE (GST_ROUND_UP_128 (width) / 64,
1081 GST_ROUND_UP_64 (height) / 64);
1082 info->offset[0] = 0;
1083 info->offset[1] = GST_ROUND_UP_128 (width) * GST_ROUND_UP_32 (height);
1084 info->size = info->offset[1] +
1085 GST_ROUND_UP_128 (width) * (GST_ROUND_UP_64 (height) / 2);
1087 case GST_VIDEO_FORMAT_NV12_4L4:
1088 case GST_VIDEO_FORMAT_NV12_32L32:
1090 gint ws = GST_VIDEO_FORMAT_INFO_TILE_WS (info->finfo);
1091 gint hs = GST_VIDEO_FORMAT_INFO_TILE_HS (info->finfo);
1093 GST_VIDEO_TILE_MAKE_STRIDE (GST_ROUND_UP_N (width, 1 << ws) >> ws,
1094 GST_ROUND_UP_N (height, 1 << hs) >> hs);
1096 GST_VIDEO_TILE_MAKE_STRIDE (GST_ROUND_UP_N (width, 1 << ws) >> ws,
1097 GST_ROUND_UP_N (height, 1 << (hs + 1)) >> (hs + 1));
1098 info->offset[0] = 0;
1100 GST_ROUND_UP_N (width, 1 << ws) * GST_ROUND_UP_N (height, 1 << hs);
1101 info->size = info->offset[1] +
1102 GST_ROUND_UP_N (width, 1 << ws) *
1103 (GST_ROUND_UP_N (height, 1 << (hs + 1)) / 2);
1106 case GST_VIDEO_FORMAT_A420_10LE:
1107 case GST_VIDEO_FORMAT_A420_10BE:
1108 info->stride[0] = GST_ROUND_UP_4 (width * 2);
1109 info->stride[1] = GST_ROUND_UP_4 (width);
1110 info->stride[2] = info->stride[1];
1111 info->stride[3] = info->stride[0];
1112 info->offset[0] = 0;
1113 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
1114 cr_h = GST_ROUND_UP_2 (height) / 2;
1115 if (GST_VIDEO_INFO_IS_INTERLACED (info))
1116 cr_h = GST_ROUND_UP_2 (cr_h);
1117 info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
1118 info->offset[3] = info->offset[2] + info->stride[2] * cr_h;
1119 info->size = info->offset[3] + info->stride[0] * GST_ROUND_UP_2 (height);
1121 case GST_VIDEO_FORMAT_A422_10LE:
1122 case GST_VIDEO_FORMAT_A422_10BE:
1123 info->stride[0] = GST_ROUND_UP_4 (width * 2);
1124 info->stride[1] = GST_ROUND_UP_4 (width);
1125 info->stride[2] = info->stride[1];
1126 info->stride[3] = info->stride[0];
1127 info->offset[0] = 0;
1128 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
1129 info->offset[2] = info->offset[1] +
1130 info->stride[1] * GST_ROUND_UP_2 (height);
1132 info->offset[2] + info->stride[2] * GST_ROUND_UP_2 (height);
1133 info->size = info->offset[3] + info->stride[0] * GST_ROUND_UP_2 (height);
1135 case GST_VIDEO_FORMAT_A444_10LE:
1136 case GST_VIDEO_FORMAT_A444_10BE:
1137 info->stride[0] = GST_ROUND_UP_4 (width * 2);
1138 info->stride[1] = info->stride[0];
1139 info->stride[2] = info->stride[0];
1140 info->stride[3] = info->stride[0];
1141 info->offset[0] = 0;
1142 info->offset[1] = info->stride[0] * height;
1143 info->offset[2] = info->offset[1] * 2;
1144 info->offset[3] = info->offset[1] * 3;
1145 info->size = info->stride[0] * height * 4;
1147 case GST_VIDEO_FORMAT_P010_10LE:
1148 case GST_VIDEO_FORMAT_P010_10BE:
1149 case GST_VIDEO_FORMAT_P016_LE:
1150 case GST_VIDEO_FORMAT_P016_BE:
1151 case GST_VIDEO_FORMAT_P012_LE:
1152 case GST_VIDEO_FORMAT_P012_BE:
1153 info->stride[0] = GST_ROUND_UP_4 (width * 2);
1154 info->stride[1] = info->stride[0];
1155 info->offset[0] = 0;
1156 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
1157 cr_h = GST_ROUND_UP_2 (height) / 2;
1158 info->size = info->offset[1] + info->stride[0] * cr_h;
1160 case GST_VIDEO_FORMAT_GRAY10_LE32:
1161 info->stride[0] = (width + 2) / 3 * 4;
1162 info->offset[0] = 0;
1163 info->size = info->stride[0] * GST_ROUND_UP_2 (height);
1165 case GST_VIDEO_FORMAT_NV12_10LE32:
1166 info->stride[0] = (width + 2) / 3 * 4;
1167 info->stride[1] = info->stride[0];
1168 info->offset[0] = 0;
1169 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
1170 cr_h = GST_ROUND_UP_2 (height) / 2;
1171 if (GST_VIDEO_INFO_IS_INTERLACED (info))
1172 cr_h = GST_ROUND_UP_2 (cr_h);
1173 info->size = info->offset[1] + info->stride[0] * cr_h;
1175 case GST_VIDEO_FORMAT_NV16_10LE32:
1176 info->stride[0] = (width + 2) / 3 * 4;
1177 info->stride[1] = info->stride[0];
1178 info->offset[0] = 0;
1179 info->offset[1] = info->stride[0] * height;
1180 info->size = info->stride[0] * height * 2;
1182 case GST_VIDEO_FORMAT_NV12_10LE40:
1183 info->stride[0] = ((width * 5 >> 2) + 4) / 5 * 5;
1184 info->stride[1] = info->stride[0];
1185 info->offset[0] = 0;
1186 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
1187 cr_h = GST_ROUND_UP_2 (height) / 2;
1188 if (GST_VIDEO_INFO_IS_INTERLACED (info))
1189 cr_h = GST_ROUND_UP_2 (cr_h);
1190 info->size = info->offset[1] + info->stride[0] * cr_h;
1193 case GST_VIDEO_FORMAT_ENCODED:
1195 case GST_VIDEO_FORMAT_UNKNOWN:
1196 #ifdef TIZEN_FEATURE_VIDEO_MODIFICATION
1199 GST_ERROR ("invalid format");
1200 g_warning ("invalid format");
1206 for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
1207 if (i < GST_VIDEO_INFO_N_PLANES (info)) {
1208 gint comp[GST_VIDEO_MAX_COMPONENTS];
1211 /* Convert plane index to component index */
1212 gst_video_format_info_component (info->finfo, i, comp);
1214 GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (info->finfo, comp[0],
1215 GST_VIDEO_INFO_FIELD_HEIGHT (info));
1216 plane_size[i] = plane_height * GST_VIDEO_INFO_PLANE_STRIDE (info, i);
1227 * gst_video_info_convert:
1228 * @info: a #GstVideoInfo
1229 * @src_format: #GstFormat of the @src_value
1230 * @src_value: value to convert
1231 * @dest_format: #GstFormat of the @dest_value
1232 * @dest_value: (out): pointer to destination value
1234 * Converts among various #GstFormat types. This function handles
1235 * GST_FORMAT_BYTES, GST_FORMAT_TIME, and GST_FORMAT_DEFAULT. For
1236 * raw video, GST_FORMAT_DEFAULT corresponds to video frames. This
1237 * function can be used to handle pad queries of the type GST_QUERY_CONVERT.
1239 * Returns: TRUE if the conversion was successful.
1242 gst_video_info_convert (const GstVideoInfo * info,
1243 GstFormat src_format, gint64 src_value,
1244 GstFormat dest_format, gint64 * dest_value)
1246 gboolean ret = FALSE;
1250 g_return_val_if_fail (info != NULL, 0);
1251 g_return_val_if_fail (info->finfo != NULL, 0);
1252 g_return_val_if_fail (info->finfo->format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1253 g_return_val_if_fail (info->size > 0, 0);
1256 fps_n = info->fps_n;
1257 fps_d = info->fps_d;
1259 GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s to %s",
1260 src_value, gst_format_get_name (src_format),
1261 gst_format_get_name (dest_format));
1263 if (src_format == dest_format) {
1264 *dest_value = src_value;
1269 if (src_value == -1) {
1275 /* bytes to frames */
1276 if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_DEFAULT) {
1278 *dest_value = gst_util_uint64_scale (src_value, 1, size);
1280 GST_ERROR ("blocksize is 0");
1287 /* frames to bytes */
1288 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_BYTES) {
1289 *dest_value = gst_util_uint64_scale (src_value, size, 1);
1294 /* time to frames */
1295 if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_DEFAULT) {
1297 *dest_value = gst_util_uint64_scale (src_value,
1298 fps_n, GST_SECOND * fps_d);
1300 GST_ERROR ("framerate denominator is 0");
1307 /* frames to time */
1308 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
1310 *dest_value = gst_util_uint64_scale (src_value,
1311 GST_SECOND * fps_d, fps_n);
1313 GST_ERROR ("framerate numerator is 0");
1321 if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) {
1323 *dest_value = gst_util_uint64_scale (src_value,
1324 fps_n * size, GST_SECOND * fps_d);
1326 GST_ERROR ("framerate denominator is 0");
1334 if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_TIME) {
1335 if (fps_n != 0 && size != 0) {
1336 *dest_value = gst_util_uint64_scale (src_value,
1337 GST_SECOND * fps_d, fps_n * size);
1339 GST_ERROR ("framerate denominator and/or blocksize is 0");
1347 GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, ret, *dest_value);
1353 * gst_video_info_align_full:
1354 * @info: a #GstVideoInfo
1355 * @align: alignment parameters
1356 * @plane_size: (out) (allow-none): array used to store the plane sizes
1358 * Extra padding will be added to the right side when stride alignment padding
1359 * is required and @align will be updated with the new padding values.
1361 * This variant of gst_video_info_align() provides the updated size, in bytes,
1362 * of each video plane after the alignment, including all horizontal and vertical
1365 * In case of GST_VIDEO_INTERLACE_MODE_ALTERNATE info, the returned sizes are the
1366 * ones used to hold a single field, not the full frame.
1368 * Returns: %FALSE if alignment could not be applied, e.g. because the
1369 * size of a frame can't be represented as a 32 bit integer
1374 gst_video_info_align_full (GstVideoInfo * info, GstVideoAlignment * align,
1375 gsize plane_size[GST_VIDEO_MAX_PLANES])
1377 const GstVideoFormatInfo *vinfo = info->finfo;
1379 gint padded_width, padded_height;
1383 width = GST_VIDEO_INFO_WIDTH (info);
1384 height = GST_VIDEO_INFO_HEIGHT (info);
1386 GST_LOG ("padding %u-%ux%u-%u", align->padding_top,
1387 align->padding_left, align->padding_right, align->padding_bottom);
1389 n_planes = GST_VIDEO_INFO_N_PLANES (info);
1391 if (GST_VIDEO_FORMAT_INFO_HAS_PALETTE (vinfo))
1394 /* first make sure the left padding does not cause alignment problems later */
1396 GST_LOG ("left padding %u", align->padding_left);
1398 for (i = 0; i < n_planes; i++) {
1399 gint comp[GST_VIDEO_MAX_COMPONENTS];
1402 /* this is the amount of pixels to add as left padding */
1403 gst_video_format_info_component (vinfo, i, comp);
1404 hedge = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (vinfo, comp[0],
1405 align->padding_left);
1406 hedge *= GST_VIDEO_FORMAT_INFO_PSTRIDE (vinfo, comp[0]);
1408 GST_LOG ("plane %d, padding %d, alignment %u", i, hedge,
1409 align->stride_align[i]);
1410 aligned &= (hedge & align->stride_align[i]) == 0;
1415 GST_LOG ("unaligned padding, increasing padding");
1416 /* increase padded_width */
1417 align->padding_left += align->padding_left & ~(align->padding_left - 1);
1420 /* add the padding */
1421 padded_width = width + align->padding_left + align->padding_right;
1422 padded_height = height + align->padding_top + align->padding_bottom;
1425 GST_LOG ("padded dimension %u-%u", padded_width, padded_height);
1427 info->width = padded_width;
1428 info->height = padded_height;
1430 if (!fill_planes (info, plane_size))
1433 /* check alignment */
1435 for (i = 0; i < n_planes; i++) {
1436 GST_LOG ("plane %d, stride %d, alignment %u", i, info->stride[i],
1437 align->stride_align[i]);
1438 aligned &= (info->stride[i] & align->stride_align[i]) == 0;
1443 GST_LOG ("unaligned strides, increasing dimension");
1444 /* increase padded_width */
1445 padded_width += padded_width & ~(padded_width - 1);
1448 align->padding_right = padded_width - width - align->padding_left;
1450 info->width = width;
1451 info->height = height;
1453 for (i = 0; i < n_planes; i++) {
1454 gint comp[GST_VIDEO_MAX_COMPONENTS];
1457 gst_video_format_info_component (info->finfo, i, comp);
1459 GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (vinfo, comp[0], align->padding_left);
1461 GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (vinfo, comp[0], align->padding_top);
1463 GST_DEBUG ("plane %d: comp: %d, hedge %d vedge %d align %d stride %d", i,
1464 comp[0], hedge, vedge, align->stride_align[i], info->stride[i]);
1466 info->offset[i] += (vedge * info->stride[i]) +
1467 (hedge * GST_VIDEO_FORMAT_INFO_PSTRIDE (vinfo, comp[0]));
1474 * gst_video_info_align:
1475 * @info: a #GstVideoInfo
1476 * @align: alignment parameters
1478 * Adjust the offset and stride fields in @info so that the padding and
1479 * stride alignment in @align is respected.
1481 * Extra padding will be added to the right side when stride alignment padding
1482 * is required and @align will be updated with the new padding values.
1484 * Returns: %FALSE if alignment could not be applied, e.g. because the
1485 * size of a frame can't be represented as a 32 bit integer (Since: 1.12)
1488 gst_video_info_align (GstVideoInfo * info, GstVideoAlignment * align)
1490 return gst_video_info_align_full (info, align, NULL);