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.
29 #include "video-info.h"
30 #include "video-tile.h"
32 #ifndef GST_DISABLE_GST_DEBUG
33 #define GST_CAT_DEFAULT ensure_debug_category()
34 static GstDebugCategory *
35 ensure_debug_category (void)
37 static gsize cat_gonce = 0;
39 if (g_once_init_enter (&cat_gonce)) {
42 cat_done = (gsize) _gst_debug_category_new ("video-info", 0,
43 "video-info structure");
45 g_once_init_leave (&cat_gonce, cat_done);
48 return (GstDebugCategory *) cat_gonce;
51 #define ensure_debug_category() /* NOOP */
52 #endif /* GST_DISABLE_GST_DEBUG */
55 * gst_video_info_copy:
56 * @info: a #GstVideoInfo
58 * Copy a GstVideoInfo structure.
60 * Returns: a new #GstVideoInfo. free with gst_video_info_free.
65 gst_video_info_copy (const GstVideoInfo * info)
67 return g_slice_dup (GstVideoInfo, info);
71 * gst_video_info_free:
72 * @info: a #GstVideoInfo
74 * Free a GstVideoInfo structure previously allocated with gst_video_info_new()
75 * or gst_video_info_copy().
80 gst_video_info_free (GstVideoInfo * info)
82 g_slice_free (GstVideoInfo, info);
85 G_DEFINE_BOXED_TYPE (GstVideoInfo, gst_video_info,
86 (GBoxedCopyFunc) gst_video_info_copy, (GBoxedFreeFunc) gst_video_info_free);
91 * Allocate a new #GstVideoInfo that is also initialized with
92 * gst_video_info_init().
94 * Returns: a new #GstVideoInfo. free with gst_video_info_free().
99 gst_video_info_new (void)
103 info = g_slice_new (GstVideoInfo);
104 gst_video_info_init (info);
109 static gboolean fill_planes (GstVideoInfo * info);
112 * gst_video_info_init:
113 * @info: a #GstVideoInfo
115 * Initialize @info with default values.
118 gst_video_info_init (GstVideoInfo * info)
120 g_return_if_fail (info != NULL);
122 memset (info, 0, sizeof (GstVideoInfo));
124 info->finfo = gst_video_format_get_info (GST_VIDEO_FORMAT_UNKNOWN);
127 /* arrange for sensible defaults, e.g. if turned into caps */
132 GST_VIDEO_INFO_MULTIVIEW_MODE (info) = GST_VIDEO_MULTIVIEW_MODE_NONE;
133 GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
134 GST_VIDEO_INFO_FIELD_ORDER (info) = GST_VIDEO_FIELD_ORDER_UNKNOWN;
137 #define MAKE_COLORIMETRY(r,m,t,p) { \
138 GST_VIDEO_COLOR_RANGE ##r, GST_VIDEO_COLOR_MATRIX_ ##m, \
139 GST_VIDEO_TRANSFER_ ##t, GST_VIDEO_COLOR_PRIMARIES_ ##p }
141 #define DEFAULT_YUV_SD 0
142 #define DEFAULT_YUV_HD 1
143 #define DEFAULT_RGB 2
144 #define DEFAULT_GRAY 3
145 #define DEFAULT_UNKNOWN 4
146 #define DEFAULT_YUV_UHD 5
148 static const GstVideoColorimetry default_color[] = {
149 MAKE_COLORIMETRY (_16_235, BT601, BT709, SMPTE170M),
150 MAKE_COLORIMETRY (_16_235, BT709, BT709, BT709),
151 MAKE_COLORIMETRY (_0_255, RGB, SRGB, BT709),
152 MAKE_COLORIMETRY (_0_255, BT601, UNKNOWN, UNKNOWN),
153 MAKE_COLORIMETRY (_UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN),
154 MAKE_COLORIMETRY (_16_235, BT2020, BT2020_12, BT2020),
158 set_default_colorimetry (GstVideoInfo * info)
160 const GstVideoFormatInfo *finfo = info->finfo;
162 if (GST_VIDEO_FORMAT_INFO_IS_YUV (finfo)) {
163 if (info->height >= 2160) {
164 info->chroma_site = GST_VIDEO_CHROMA_SITE_H_COSITED;
165 info->colorimetry = default_color[DEFAULT_YUV_UHD];
166 } else if (info->height > 576) {
167 info->chroma_site = GST_VIDEO_CHROMA_SITE_H_COSITED;
168 info->colorimetry = default_color[DEFAULT_YUV_HD];
170 info->chroma_site = GST_VIDEO_CHROMA_SITE_NONE;
171 info->colorimetry = default_color[DEFAULT_YUV_SD];
173 } else if (GST_VIDEO_FORMAT_INFO_IS_GRAY (finfo)) {
174 info->colorimetry = default_color[DEFAULT_GRAY];
175 } else if (GST_VIDEO_FORMAT_INFO_IS_RGB (finfo)) {
176 info->colorimetry = default_color[DEFAULT_RGB];
178 info->colorimetry = default_color[DEFAULT_UNKNOWN];
183 validate_colorimetry (GstVideoInfo * info)
185 const GstVideoFormatInfo *finfo = info->finfo;
187 if (!GST_VIDEO_FORMAT_INFO_IS_RGB (finfo) &&
188 info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB)
191 if (GST_VIDEO_FORMAT_INFO_IS_YUV (finfo) &&
192 info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN)
199 gst_video_info_set_format_common (GstVideoInfo * info, GstVideoFormat format,
200 guint width, guint height)
202 g_return_val_if_fail (info != NULL, FALSE);
203 g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, FALSE);
205 if (width > G_MAXINT || height > G_MAXINT)
208 gst_video_info_init (info);
210 info->finfo = gst_video_format_get_info (format);
212 info->height = height;
215 set_default_colorimetry (info);
221 * gst_video_info_set_format:
222 * @info: a #GstVideoInfo
223 * @format: the format
227 * Set the default info for a video frame of @format and @width and @height.
229 * Note: This initializes @info first, no values are preserved. This function
230 * does not set the offsets correctly for interlaced vertically
231 * subsampled formats.
233 * Returns: %FALSE if the returned video info is invalid, e.g. because the
234 * size of a frame can't be represented as a 32 bit integer (Since: 1.12)
237 gst_video_info_set_format (GstVideoInfo * info, GstVideoFormat format,
238 guint width, guint height)
240 if (!gst_video_info_set_format_common (info, format, width, height))
243 return fill_planes (info);
247 * gst_video_info_set_interlaced_format:
248 * @info: a #GstVideoInfo
249 * @format: the format
250 * @mode: a #GstVideoInterlaceMode
254 * Same as #gst_video_info_set_format but also allowing to set the interlaced
257 * Returns: %FALSE if the returned video info is invalid, e.g. because the
258 * size of a frame can't be represented as a 32 bit integer.
263 gst_video_info_set_interlaced_format (GstVideoInfo * info,
264 GstVideoFormat format, GstVideoInterlaceMode mode, guint width,
267 if (!gst_video_info_set_format_common (info, format, width, height))
270 GST_VIDEO_INFO_INTERLACE_MODE (info) = mode;
271 return fill_planes (info);
274 static const gchar *interlace_mode[] = {
283 * gst_video_interlace_mode_to_string:
284 * @mode: a #GstVideoInterlaceMode
286 * Convert @mode to its string representation.
288 * Returns: @mode as a string or NULL if @mode in invalid.
293 gst_video_interlace_mode_to_string (GstVideoInterlaceMode mode)
295 if (((guint) mode) >= G_N_ELEMENTS (interlace_mode))
298 return interlace_mode[mode];
302 * gst_video_interlace_mode_from_string:
305 * Convert @mode to a #GstVideoInterlaceMode
307 * Returns: the #GstVideoInterlaceMode of @mode or
308 * #GST_VIDEO_INTERLACE_MODE_PROGRESSIVE when @mode is not a valid
309 * string representation for a #GstVideoInterlaceMode.
313 GstVideoInterlaceMode
314 gst_video_interlace_mode_from_string (const gchar * mode)
317 for (i = 0; i < G_N_ELEMENTS (interlace_mode); i++) {
318 if (g_str_equal (interlace_mode[i], mode))
321 return GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
324 static const gchar *field_order[] = {
331 * gst_video_field_order_to_string:
332 * @order: a #GstVideoFieldOrder
334 * Convert @order to its string representation.
336 * Returns: @order as a string or NULL if @order in invalid.
341 gst_video_field_order_to_string (GstVideoFieldOrder order)
343 if (((guint) order) >= G_N_ELEMENTS (field_order))
346 return field_order[order];
350 * gst_video_field_order_from_string:
351 * @order: a field order
353 * Convert @order to a #GstVideoFieldOrder
355 * Returns: the #GstVideoFieldOrder of @order or
356 * #GST_VIDEO_FIELD_ORDER_UNKNOWN when @order is not a valid
357 * string representation for a #GstVideoFieldOrder.
362 gst_video_field_order_from_string (const gchar * order)
365 for (i = 0; i < G_N_ELEMENTS (field_order); i++) {
366 if (g_str_equal (field_order[i], order))
369 return GST_VIDEO_FIELD_ORDER_UNKNOWN;
373 * gst_video_info_from_caps:
374 * @info: a #GstVideoInfo
377 * Parse @caps and update @info.
379 * Returns: TRUE if @caps could be parsed
382 gst_video_info_from_caps (GstVideoInfo * info, const GstCaps * caps)
384 GstStructure *structure;
386 GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
387 gint width = 0, height = 0;
390 guint multiview_flags;
392 g_return_val_if_fail (info != NULL, FALSE);
393 g_return_val_if_fail (caps != NULL, FALSE);
394 g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
396 GST_DEBUG ("parsing caps %" GST_PTR_FORMAT, caps);
398 structure = gst_caps_get_structure (caps, 0);
400 if (gst_structure_has_name (structure, "video/x-raw")) {
401 if (!(s = gst_structure_get_string (structure, "format")))
404 format = gst_video_format_from_string (s);
405 if (format == GST_VIDEO_FORMAT_UNKNOWN)
408 } else if (g_str_has_prefix (gst_structure_get_name (structure), "video/") ||
409 g_str_has_prefix (gst_structure_get_name (structure), "image/")) {
410 format = GST_VIDEO_FORMAT_ENCODED;
415 /* width and height are mandatory, except for non-raw-formats */
416 if (!gst_structure_get_int (structure, "width", &width) &&
417 format != GST_VIDEO_FORMAT_ENCODED)
419 if (!gst_structure_get_int (structure, "height", &height) &&
420 format != GST_VIDEO_FORMAT_ENCODED)
423 gst_video_info_init (info);
425 info->finfo = gst_video_format_get_info (format);
427 info->height = height;
429 if (gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d)) {
431 /* variable framerate */
432 info->flags |= GST_VIDEO_FLAG_VARIABLE_FPS;
433 /* see if we have a max-framerate */
434 gst_structure_get_fraction (structure, "max-framerate", &fps_n, &fps_d);
439 /* unspecified is variable framerate */
444 if (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
453 if ((s = gst_structure_get_string (structure, "interlace-mode")))
454 info->interlace_mode = gst_video_interlace_mode_from_string (s);
456 info->interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
458 if (info->interlace_mode == GST_VIDEO_INTERLACE_MODE_INTERLEAVED &&
459 (s = gst_structure_get_string (structure, "field-order"))) {
460 GST_VIDEO_INFO_FIELD_ORDER (info) = gst_video_field_order_from_string (s);
462 GST_VIDEO_INFO_FIELD_ORDER (info) = GST_VIDEO_FIELD_ORDER_UNKNOWN;
466 if ((s = gst_structure_get_string (structure, "multiview-mode")))
467 GST_VIDEO_INFO_MULTIVIEW_MODE (info) =
468 gst_video_multiview_mode_from_caps_string (s);
470 GST_VIDEO_INFO_MULTIVIEW_MODE (info) = GST_VIDEO_MULTIVIEW_MODE_NONE;
472 if (gst_structure_get_flagset (structure, "multiview-flags",
473 &multiview_flags, NULL))
474 GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) = multiview_flags;
476 if (!gst_structure_get_int (structure, "views", &info->views))
479 /* At one point, I tried normalising the half-aspect flag here,
480 * but it behaves weird for GstVideoInfo operations other than
481 * directly converting to/from caps - sometimes causing the
482 * PAR to be doubled/halved too many times */
485 if ((s = gst_structure_get_string (structure, "chroma-site")))
486 info->chroma_site = gst_video_chroma_from_string (s);
488 info->chroma_site = GST_VIDEO_CHROMA_SITE_UNKNOWN;
490 if ((s = gst_structure_get_string (structure, "colorimetry"))) {
491 if (!gst_video_colorimetry_from_string (&info->colorimetry, s)) {
492 GST_WARNING ("unparsable colorimetry, using default");
493 set_default_colorimetry (info);
494 } else if (!validate_colorimetry (info)) {
495 GST_WARNING ("invalid colorimetry, using default");
496 set_default_colorimetry (info);
498 /* force RGB matrix for RGB formats */
499 if (GST_VIDEO_FORMAT_INFO_IS_RGB (info->finfo) &&
500 info->colorimetry.matrix != GST_VIDEO_COLOR_MATRIX_RGB) {
501 GST_WARNING ("invalid matrix %d for RGB format, using RGB",
502 info->colorimetry.matrix);
503 info->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_RGB;
507 GST_DEBUG ("no colorimetry, using default");
508 set_default_colorimetry (info);
511 if (!fill_planes (info))
519 GST_ERROR ("wrong name '%s', expected video/ or image/",
520 gst_structure_get_name (structure));
525 GST_ERROR ("no format given");
530 GST_ERROR ("unknown format '%s' given", s);
535 GST_ERROR ("no width property given");
540 GST_ERROR ("no height property given");
546 * gst_video_info_is_equal:
547 * @info: a #GstVideoInfo
548 * @other: a #GstVideoInfo
550 * Compares two #GstVideoInfo and returns whether they are equal or not
552 * Returns: %TRUE if @info and @other are equal, else %FALSE.
555 gst_video_info_is_equal (const GstVideoInfo * info, const GstVideoInfo * other)
559 if (GST_VIDEO_INFO_FORMAT (info) != GST_VIDEO_INFO_FORMAT (other))
561 if (GST_VIDEO_INFO_INTERLACE_MODE (info) !=
562 GST_VIDEO_INFO_INTERLACE_MODE (other))
564 if (GST_VIDEO_INFO_FLAGS (info) != GST_VIDEO_INFO_FLAGS (other))
566 if (GST_VIDEO_INFO_WIDTH (info) != GST_VIDEO_INFO_WIDTH (other))
568 if (GST_VIDEO_INFO_HEIGHT (info) != GST_VIDEO_INFO_HEIGHT (other))
570 if (GST_VIDEO_INFO_SIZE (info) != GST_VIDEO_INFO_SIZE (other))
572 if (GST_VIDEO_INFO_PAR_N (info) != GST_VIDEO_INFO_PAR_N (other))
574 if (GST_VIDEO_INFO_PAR_D (info) != GST_VIDEO_INFO_PAR_D (other))
576 if (GST_VIDEO_INFO_FPS_N (info) != GST_VIDEO_INFO_FPS_N (other))
578 if (GST_VIDEO_INFO_FPS_D (info) != GST_VIDEO_INFO_FPS_D (other))
580 if (!gst_video_colorimetry_is_equal (&GST_VIDEO_INFO_COLORIMETRY (info),
581 &GST_VIDEO_INFO_COLORIMETRY (other)))
583 if (GST_VIDEO_INFO_CHROMA_SITE (info) != GST_VIDEO_INFO_CHROMA_SITE (other))
585 if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) !=
586 GST_VIDEO_INFO_MULTIVIEW_MODE (other))
588 if (GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) !=
589 GST_VIDEO_INFO_MULTIVIEW_FLAGS (other))
591 if (GST_VIDEO_INFO_VIEWS (info) != GST_VIDEO_INFO_VIEWS (other))
594 for (i = 0; i < info->finfo->n_planes; i++) {
595 if (info->stride[i] != other->stride[i])
597 if (info->offset[i] != other->offset[i])
605 * gst_video_info_to_caps:
606 * @info: a #GstVideoInfo
608 * Convert the values of @info into a #GstCaps.
610 * Returns: a new #GstCaps containing the info of @info.
613 gst_video_info_to_caps (GstVideoInfo * info)
619 GstVideoColorimetry colorimetry;
621 g_return_val_if_fail (info != NULL, NULL);
622 g_return_val_if_fail (info->finfo != NULL, NULL);
623 g_return_val_if_fail (info->finfo->format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
625 format = gst_video_format_to_string (info->finfo->format);
626 g_return_val_if_fail (format != NULL, NULL);
628 caps = gst_caps_new_simple ("video/x-raw",
629 "format", G_TYPE_STRING, format,
630 "width", G_TYPE_INT, info->width,
631 "height", G_TYPE_INT, info->height, NULL);
636 gst_caps_set_simple (caps, "interlace-mode", G_TYPE_STRING,
637 gst_video_interlace_mode_to_string (info->interlace_mode), NULL);
639 if (info->interlace_mode == GST_VIDEO_INTERLACE_MODE_INTERLEAVED &&
640 GST_VIDEO_INFO_FIELD_ORDER (info) != GST_VIDEO_FIELD_ORDER_UNKNOWN) {
641 gst_caps_set_simple (caps, "field-order", G_TYPE_STRING,
642 gst_video_field_order_to_string (GST_VIDEO_INFO_FIELD_ORDER (info)),
646 if (info->interlace_mode == GST_VIDEO_INTERLACE_MODE_ALTERNATE) {
647 /* 'alternate' mode must always be accompanied by interlaced caps feature.
649 GstCapsFeatures *features;
651 features = gst_caps_features_new (GST_CAPS_FEATURE_FORMAT_INTERLACED, NULL);
652 gst_caps_set_features (caps, 0, features);
655 if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) != GST_VIDEO_MULTIVIEW_MODE_NONE) {
656 const gchar *caps_str = NULL;
658 /* If the half-aspect flag is set, applying it into the PAR of the
659 * resulting caps now seems safe, and helps with automatic behaviour
660 * in elements that aren't explicitly multiview aware */
661 if (GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) &
662 GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT) {
663 GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) &=
664 ~GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
665 switch (GST_VIDEO_INFO_MULTIVIEW_MODE (info)) {
666 case GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE:
667 case GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX:
668 case GST_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED:
669 case GST_VIDEO_MULTIVIEW_MODE_CHECKERBOARD:
670 par_n *= 2; /* double the width / half the height */
672 case GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED:
673 case GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM:
674 par_d *= 2; /* half the width / double the height */
682 gst_video_multiview_mode_to_caps_string (GST_VIDEO_INFO_MULTIVIEW_MODE
684 if (caps_str != NULL) {
685 gst_caps_set_simple (caps, "multiview-mode", G_TYPE_STRING,
686 caps_str, "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
687 GST_VIDEO_INFO_MULTIVIEW_FLAGS (info), GST_FLAG_SET_MASK_EXACT, NULL);
691 gst_caps_set_simple (caps, "pixel-aspect-ratio",
692 GST_TYPE_FRACTION, par_n, par_d, NULL);
694 if (info->chroma_site != GST_VIDEO_CHROMA_SITE_UNKNOWN)
695 gst_caps_set_simple (caps, "chroma-site", G_TYPE_STRING,
696 gst_video_chroma_to_string (info->chroma_site), NULL);
698 /* make sure we set the RGB matrix for RGB formats */
699 colorimetry = info->colorimetry;
700 if (GST_VIDEO_FORMAT_INFO_IS_RGB (info->finfo) &&
701 colorimetry.matrix != GST_VIDEO_COLOR_MATRIX_RGB) {
702 GST_WARNING ("invalid matrix %d for RGB format, using RGB",
704 colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_RGB;
706 if ((color = gst_video_colorimetry_to_string (&colorimetry))) {
707 gst_caps_set_simple (caps, "colorimetry", G_TYPE_STRING, color, NULL);
712 gst_caps_set_simple (caps, "views", G_TYPE_INT, info->views, NULL);
714 if (info->flags & GST_VIDEO_FLAG_VARIABLE_FPS && info->fps_n != 0) {
715 /* variable fps with a max-framerate */
716 gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, 0, 1,
717 "max-framerate", GST_TYPE_FRACTION, info->fps_n, info->fps_d, NULL);
719 /* no variable fps or no max-framerate */
720 gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION,
721 info->fps_n, info->fps_d, NULL);
728 fill_planes (GstVideoInfo * info)
730 gsize width, height, cr_h;
733 width = (gsize) info->width;
734 if (GST_VIDEO_INFO_INTERLACE_MODE (info) ==
735 GST_VIDEO_INTERLACE_MODE_ALTERNATE)
736 height = (gsize) info->height / 2;
738 height = (gsize) info->height;
740 /* Sanity check the resulting frame size for overflows */
741 for (i = 0; i < GST_VIDEO_INFO_N_COMPONENTS (info); i++)
742 bpp += GST_VIDEO_INFO_COMP_DEPTH (info, i);
743 bpp = GST_ROUND_UP_8 (bpp) / 8;
744 if (bpp > 0 && GST_ROUND_UP_128 ((guint64) width) * ((guint64) height) >=
746 GST_ERROR ("Frame size %ux%u would overflow", info->width, info->height);
750 switch (info->finfo->format) {
751 case GST_VIDEO_FORMAT_YUY2:
752 case GST_VIDEO_FORMAT_YVYU:
753 case GST_VIDEO_FORMAT_UYVY:
754 case GST_VIDEO_FORMAT_VYUY:
755 info->stride[0] = GST_ROUND_UP_4 (width * 2);
757 info->size = info->stride[0] * height;
759 case GST_VIDEO_FORMAT_AYUV:
760 case GST_VIDEO_FORMAT_RGBx:
761 case GST_VIDEO_FORMAT_RGBA:
762 case GST_VIDEO_FORMAT_BGRx:
763 case GST_VIDEO_FORMAT_BGRA:
764 case GST_VIDEO_FORMAT_xRGB:
765 case GST_VIDEO_FORMAT_ARGB:
766 case GST_VIDEO_FORMAT_xBGR:
767 case GST_VIDEO_FORMAT_ABGR:
768 case GST_VIDEO_FORMAT_r210:
769 info->stride[0] = width * 4;
771 info->size = info->stride[0] * height;
773 case GST_VIDEO_FORMAT_RGB16:
774 case GST_VIDEO_FORMAT_BGR16:
775 case GST_VIDEO_FORMAT_RGB15:
776 case GST_VIDEO_FORMAT_BGR15:
777 info->stride[0] = GST_ROUND_UP_4 (width * 2);
779 info->size = info->stride[0] * height;
781 case GST_VIDEO_FORMAT_RGB:
782 case GST_VIDEO_FORMAT_BGR:
783 case GST_VIDEO_FORMAT_v308:
784 case GST_VIDEO_FORMAT_IYU2:
785 info->stride[0] = GST_ROUND_UP_4 (width * 3);
787 info->size = info->stride[0] * height;
789 case GST_VIDEO_FORMAT_v210:
790 info->stride[0] = ((width + 47) / 48) * 128;
792 info->size = info->stride[0] * height;
794 case GST_VIDEO_FORMAT_v216:
795 info->stride[0] = GST_ROUND_UP_8 (width * 4);
797 info->size = info->stride[0] * height;
799 case GST_VIDEO_FORMAT_GRAY8:
800 info->stride[0] = GST_ROUND_UP_4 (width);
802 info->size = info->stride[0] * height;
804 case GST_VIDEO_FORMAT_GRAY16_BE:
805 case GST_VIDEO_FORMAT_GRAY16_LE:
806 info->stride[0] = GST_ROUND_UP_4 (width * 2);
808 info->size = info->stride[0] * height;
810 case GST_VIDEO_FORMAT_UYVP:
811 info->stride[0] = GST_ROUND_UP_4 ((width * 2 * 5 + 3) / 4);
813 info->size = info->stride[0] * height;
815 case GST_VIDEO_FORMAT_RGB8P:
816 info->stride[0] = GST_ROUND_UP_4 (width);
819 info->offset[1] = info->stride[0] * height;
820 info->size = info->offset[1] + (4 * 256);
822 case GST_VIDEO_FORMAT_IYU1:
823 info->stride[0] = GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) +
824 GST_ROUND_UP_4 (width) / 2);
826 info->size = info->stride[0] * height;
828 case GST_VIDEO_FORMAT_ARGB64:
829 case GST_VIDEO_FORMAT_AYUV64:
830 info->stride[0] = width * 8;
832 info->size = info->stride[0] * height;
834 case GST_VIDEO_FORMAT_I420:
835 case GST_VIDEO_FORMAT_YV12: /* same as I420, but plane 1+2 swapped */
836 info->stride[0] = GST_ROUND_UP_4 (width);
837 info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
838 info->stride[2] = info->stride[1];
840 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
841 cr_h = GST_ROUND_UP_2 (height) / 2;
842 if (GST_VIDEO_INFO_IS_INTERLACED (info))
843 cr_h = GST_ROUND_UP_2 (cr_h);
844 info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
845 info->size = info->offset[2] + info->stride[2] * cr_h;
847 case GST_VIDEO_FORMAT_Y41B:
848 info->stride[0] = GST_ROUND_UP_4 (width);
849 info->stride[1] = GST_ROUND_UP_16 (width) / 4;
850 info->stride[2] = info->stride[1];
852 info->offset[1] = info->stride[0] * height;
853 info->offset[2] = info->offset[1] + info->stride[1] * height;
854 /* simplification of ROUNDUP4(w)*h + 2*((ROUNDUP16(w)/4)*h */
855 info->size = (info->stride[0] + (GST_ROUND_UP_16 (width) / 2)) * height;
857 case GST_VIDEO_FORMAT_Y42B:
858 info->stride[0] = GST_ROUND_UP_4 (width);
859 info->stride[1] = GST_ROUND_UP_8 (width) / 2;
860 info->stride[2] = info->stride[1];
862 info->offset[1] = info->stride[0] * height;
863 info->offset[2] = info->offset[1] + info->stride[1] * height;
864 /* simplification of ROUNDUP4(w)*h + 2*(ROUNDUP8(w)/2)*h */
865 info->size = (info->stride[0] + GST_ROUND_UP_8 (width)) * height;
867 case GST_VIDEO_FORMAT_Y444:
868 case GST_VIDEO_FORMAT_GBR:
869 info->stride[0] = GST_ROUND_UP_4 (width);
870 info->stride[1] = info->stride[0];
871 info->stride[2] = info->stride[0];
873 info->offset[1] = info->stride[0] * height;
874 info->offset[2] = info->offset[1] * 2;
875 info->size = info->stride[0] * height * 3;
877 case GST_VIDEO_FORMAT_GBRA:
878 info->stride[0] = GST_ROUND_UP_4 (width);
879 info->stride[1] = info->stride[0];
880 info->stride[2] = info->stride[0];
881 info->stride[3] = info->stride[0];
883 info->offset[1] = info->stride[0] * height;
884 info->offset[2] = info->offset[1] * 2;
885 info->offset[3] = info->offset[1] * 3;
886 info->size = info->stride[0] * height * 4;
888 case GST_VIDEO_FORMAT_NV12:
889 case GST_VIDEO_FORMAT_NV21:
890 info->stride[0] = GST_ROUND_UP_4 (width);
891 info->stride[1] = info->stride[0];
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->size = info->offset[1] + info->stride[0] * cr_h;
899 case GST_VIDEO_FORMAT_NV16:
900 case GST_VIDEO_FORMAT_NV61:
901 info->stride[0] = GST_ROUND_UP_4 (width);
902 info->stride[1] = info->stride[0];
904 info->offset[1] = info->stride[0] * height;
905 info->size = info->stride[0] * height * 2;
907 case GST_VIDEO_FORMAT_NV24:
908 info->stride[0] = GST_ROUND_UP_4 (width);
909 info->stride[1] = GST_ROUND_UP_4 (width * 2);
911 info->offset[1] = info->stride[0] * height;
912 info->size = info->stride[0] * height + info->stride[1] * height;
914 case GST_VIDEO_FORMAT_A420:
915 info->stride[0] = GST_ROUND_UP_4 (width);
916 info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
917 info->stride[2] = info->stride[1];
918 info->stride[3] = info->stride[0];
920 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
921 cr_h = GST_ROUND_UP_2 (height) / 2;
922 if (GST_VIDEO_INFO_IS_INTERLACED (info))
923 cr_h = GST_ROUND_UP_2 (cr_h);
924 info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
925 info->offset[3] = info->offset[2] + info->stride[2] * cr_h;
926 info->size = info->offset[3] + info->stride[0] * GST_ROUND_UP_2 (height);
928 case GST_VIDEO_FORMAT_YUV9:
929 case GST_VIDEO_FORMAT_YVU9:
930 info->stride[0] = GST_ROUND_UP_4 (width);
931 info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4);
932 info->stride[2] = info->stride[1];
934 info->offset[1] = info->stride[0] * height;
935 cr_h = GST_ROUND_UP_4 (height) / 4;
936 if (GST_VIDEO_INFO_IS_INTERLACED (info))
937 cr_h = GST_ROUND_UP_2 (cr_h);
938 info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
939 info->size = info->offset[2] + info->stride[2] * cr_h;
941 case GST_VIDEO_FORMAT_I420_10LE:
942 case GST_VIDEO_FORMAT_I420_10BE:
943 case GST_VIDEO_FORMAT_I420_12LE:
944 case GST_VIDEO_FORMAT_I420_12BE:
945 info->stride[0] = GST_ROUND_UP_4 (width * 2);
946 info->stride[1] = GST_ROUND_UP_4 (width);
947 info->stride[2] = info->stride[1];
949 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
950 cr_h = GST_ROUND_UP_2 (height) / 2;
951 if (GST_VIDEO_INFO_IS_INTERLACED (info))
952 cr_h = GST_ROUND_UP_2 (cr_h);
953 info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
954 info->size = info->offset[2] + info->stride[2] * cr_h;
956 case GST_VIDEO_FORMAT_I422_10LE:
957 case GST_VIDEO_FORMAT_I422_10BE:
958 case GST_VIDEO_FORMAT_I422_12LE:
959 case GST_VIDEO_FORMAT_I422_12BE:
960 info->stride[0] = GST_ROUND_UP_4 (width * 2);
961 info->stride[1] = GST_ROUND_UP_4 (width);
962 info->stride[2] = info->stride[1];
964 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
965 info->offset[2] = info->offset[1] +
966 info->stride[1] * GST_ROUND_UP_2 (height);
967 info->size = info->offset[2] + info->stride[2] * GST_ROUND_UP_2 (height);
969 case GST_VIDEO_FORMAT_Y444_10LE:
970 case GST_VIDEO_FORMAT_Y444_10BE:
971 case GST_VIDEO_FORMAT_Y444_12LE:
972 case GST_VIDEO_FORMAT_Y444_12BE:
973 case GST_VIDEO_FORMAT_GBR_10LE:
974 case GST_VIDEO_FORMAT_GBR_10BE:
975 case GST_VIDEO_FORMAT_GBR_12LE:
976 case GST_VIDEO_FORMAT_GBR_12BE:
977 info->stride[0] = GST_ROUND_UP_4 (width * 2);
978 info->stride[1] = info->stride[0];
979 info->stride[2] = info->stride[0];
981 info->offset[1] = info->stride[0] * height;
982 info->offset[2] = info->offset[1] * 2;
983 info->size = info->stride[0] * height * 3;
985 case GST_VIDEO_FORMAT_GBRA_10LE:
986 case GST_VIDEO_FORMAT_GBRA_10BE:
987 case GST_VIDEO_FORMAT_GBRA_12LE:
988 case GST_VIDEO_FORMAT_GBRA_12BE:
989 info->stride[0] = GST_ROUND_UP_4 (width * 2);
990 info->stride[1] = info->stride[0];
991 info->stride[2] = info->stride[0];
992 info->stride[3] = info->stride[0];
994 info->offset[1] = info->stride[0] * height;
995 info->offset[2] = info->offset[1] * 2;
996 info->offset[3] = info->offset[1] * 3;
997 info->size = info->stride[0] * height * 4;
999 case GST_VIDEO_FORMAT_NV12_64Z32:
1001 GST_VIDEO_TILE_MAKE_STRIDE (GST_ROUND_UP_128 (width) / 64,
1002 GST_ROUND_UP_32 (height) / 32);
1004 GST_VIDEO_TILE_MAKE_STRIDE (GST_ROUND_UP_128 (width) / 64,
1005 GST_ROUND_UP_64 (height) / 64);
1006 info->offset[0] = 0;
1007 info->offset[1] = GST_ROUND_UP_128 (width) * GST_ROUND_UP_32 (height);
1008 info->size = info->offset[1] +
1009 GST_ROUND_UP_128 (width) * GST_ROUND_UP_64 (height) / 2;
1011 case GST_VIDEO_FORMAT_A420_10LE:
1012 case GST_VIDEO_FORMAT_A420_10BE:
1013 info->stride[0] = GST_ROUND_UP_4 (width * 2);
1014 info->stride[1] = GST_ROUND_UP_4 (width);
1015 info->stride[2] = info->stride[1];
1016 info->stride[3] = info->stride[0];
1017 info->offset[0] = 0;
1018 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
1019 cr_h = GST_ROUND_UP_2 (height) / 2;
1020 if (GST_VIDEO_INFO_IS_INTERLACED (info))
1021 cr_h = GST_ROUND_UP_2 (cr_h);
1022 info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
1023 info->offset[3] = info->offset[2] + info->stride[2] * cr_h;
1024 info->size = info->offset[3] + info->stride[0] * GST_ROUND_UP_2 (height);
1026 case GST_VIDEO_FORMAT_A422_10LE:
1027 case GST_VIDEO_FORMAT_A422_10BE:
1028 info->stride[0] = GST_ROUND_UP_4 (width * 2);
1029 info->stride[1] = GST_ROUND_UP_4 (width);
1030 info->stride[2] = info->stride[1];
1031 info->stride[3] = info->stride[0];
1032 info->offset[0] = 0;
1033 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
1034 info->offset[2] = info->offset[1] +
1035 info->stride[1] * GST_ROUND_UP_2 (height);
1037 info->offset[2] + info->stride[2] * GST_ROUND_UP_2 (height);
1038 info->size = info->offset[3] + info->stride[0] * GST_ROUND_UP_2 (height);
1040 case GST_VIDEO_FORMAT_A444_10LE:
1041 case GST_VIDEO_FORMAT_A444_10BE:
1042 info->stride[0] = GST_ROUND_UP_4 (width * 2);
1043 info->stride[1] = info->stride[0];
1044 info->stride[2] = info->stride[0];
1045 info->stride[3] = info->stride[0];
1046 info->offset[0] = 0;
1047 info->offset[1] = info->stride[0] * height;
1048 info->offset[2] = info->offset[1] * 2;
1049 info->offset[3] = info->offset[1] * 3;
1050 info->size = info->stride[0] * height * 4;
1052 case GST_VIDEO_FORMAT_P010_10LE:
1053 case GST_VIDEO_FORMAT_P010_10BE:
1054 info->stride[0] = GST_ROUND_UP_4 (width * 2);
1055 info->stride[1] = info->stride[0];
1056 info->offset[0] = 0;
1057 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
1058 cr_h = GST_ROUND_UP_2 (height) / 2;
1059 info->size = info->offset[1] + info->stride[0] * cr_h;
1061 case GST_VIDEO_FORMAT_GRAY10_LE32:
1062 info->stride[0] = (width + 2) / 3 * 4;
1063 info->offset[0] = 0;
1064 info->size = info->stride[0] * GST_ROUND_UP_2 (height);
1066 case GST_VIDEO_FORMAT_NV12_10LE32:
1067 info->stride[0] = (width + 2) / 3 * 4;
1068 info->stride[1] = info->stride[0];
1069 info->offset[0] = 0;
1070 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
1071 cr_h = GST_ROUND_UP_2 (height) / 2;
1072 if (GST_VIDEO_INFO_IS_INTERLACED (info))
1073 cr_h = GST_ROUND_UP_2 (cr_h);
1074 info->size = info->offset[1] + info->stride[0] * cr_h;
1076 case GST_VIDEO_FORMAT_NV16_10LE32:
1077 info->stride[0] = (width + 2) / 3 * 4;
1078 info->stride[1] = info->stride[0];
1079 info->offset[0] = 0;
1080 info->offset[1] = info->stride[0] * height;
1081 info->size = info->stride[0] * height * 2;
1083 case GST_VIDEO_FORMAT_NV12_10LE40:
1084 info->stride[0] = ((width * 5 >> 2) + 4) / 5 * 5;
1085 info->stride[1] = info->stride[0];
1086 info->offset[0] = 0;
1087 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
1088 cr_h = GST_ROUND_UP_2 (height) / 2;
1089 if (GST_VIDEO_INFO_IS_INTERLACED (info))
1090 cr_h = GST_ROUND_UP_2 (cr_h);
1091 info->size = info->offset[1] + info->stride[0] * cr_h;
1094 case GST_VIDEO_FORMAT_ENCODED:
1096 case GST_VIDEO_FORMAT_UNKNOWN:
1097 GST_ERROR ("invalid format");
1098 g_warning ("invalid format");
1106 * gst_video_info_convert:
1107 * @info: a #GstVideoInfo
1108 * @src_format: #GstFormat of the @src_value
1109 * @src_value: value to convert
1110 * @dest_format: #GstFormat of the @dest_value
1111 * @dest_value: (out): pointer to destination value
1113 * Converts among various #GstFormat types. This function handles
1114 * GST_FORMAT_BYTES, GST_FORMAT_TIME, and GST_FORMAT_DEFAULT. For
1115 * raw video, GST_FORMAT_DEFAULT corresponds to video frames. This
1116 * function can be used to handle pad queries of the type GST_QUERY_CONVERT.
1118 * Returns: TRUE if the conversion was successful.
1121 gst_video_info_convert (GstVideoInfo * info,
1122 GstFormat src_format, gint64 src_value,
1123 GstFormat dest_format, gint64 * dest_value)
1125 gboolean ret = FALSE;
1129 g_return_val_if_fail (info != NULL, 0);
1130 g_return_val_if_fail (info->finfo != NULL, 0);
1131 g_return_val_if_fail (info->finfo->format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1132 g_return_val_if_fail (info->size > 0, 0);
1135 fps_n = info->fps_n;
1136 fps_d = info->fps_d;
1138 GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s to %s",
1139 src_value, gst_format_get_name (src_format),
1140 gst_format_get_name (dest_format));
1142 if (src_format == dest_format) {
1143 *dest_value = src_value;
1148 if (src_value == -1) {
1154 /* bytes to frames */
1155 if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_DEFAULT) {
1157 *dest_value = gst_util_uint64_scale (src_value, 1, size);
1159 GST_ERROR ("blocksize is 0");
1166 /* frames to bytes */
1167 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_BYTES) {
1168 *dest_value = gst_util_uint64_scale (src_value, size, 1);
1173 /* time to frames */
1174 if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_DEFAULT) {
1176 *dest_value = gst_util_uint64_scale (src_value,
1177 fps_n, GST_SECOND * fps_d);
1179 GST_ERROR ("framerate denominator is 0");
1186 /* frames to time */
1187 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
1189 *dest_value = gst_util_uint64_scale (src_value,
1190 GST_SECOND * fps_d, fps_n);
1192 GST_ERROR ("framerate numerator is 0");
1200 if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) {
1202 *dest_value = gst_util_uint64_scale (src_value,
1203 fps_n * size, GST_SECOND * fps_d);
1205 GST_ERROR ("framerate denominator is 0");
1213 if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_TIME) {
1214 if (fps_n != 0 && size != 0) {
1215 *dest_value = gst_util_uint64_scale (src_value,
1216 GST_SECOND * fps_d, fps_n * size);
1218 GST_ERROR ("framerate denominator and/or blocksize is 0");
1226 GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, ret, *dest_value);
1232 * gst_video_info_align:
1233 * @info: a #GstVideoInfo
1234 * @align: alignment parameters
1236 * Adjust the offset and stride fields in @info so that the padding and
1237 * stride alignment in @align is respected.
1239 * Extra padding will be added to the right side when stride alignment padding
1240 * is required and @align will be updated with the new padding values.
1242 * Returns: %FALSE if alignment could not be applied, e.g. because the
1243 * size of a frame can't be represented as a 32 bit integer (Since: 1.12)
1246 gst_video_info_align (GstVideoInfo * info, GstVideoAlignment * align)
1248 const GstVideoFormatInfo *vinfo = info->finfo;
1250 gint padded_width, padded_height;
1254 width = GST_VIDEO_INFO_WIDTH (info);
1255 height = GST_VIDEO_INFO_HEIGHT (info);
1257 GST_LOG ("padding %u-%ux%u-%u", align->padding_top,
1258 align->padding_left, align->padding_right, align->padding_bottom);
1260 n_planes = GST_VIDEO_INFO_N_PLANES (info);
1262 if (GST_VIDEO_FORMAT_INFO_HAS_PALETTE (vinfo))
1265 /* first make sure the left padding does not cause alignment problems later */
1267 GST_LOG ("left padding %u", align->padding_left);
1269 for (i = 0; i < n_planes; i++) {
1272 /* this is the amout of pixels to add as left padding */
1273 hedge = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (vinfo, i, align->padding_left);
1274 hedge *= GST_VIDEO_FORMAT_INFO_PSTRIDE (vinfo, i);
1276 GST_LOG ("plane %d, padding %d, alignment %u", i, hedge,
1277 align->stride_align[i]);
1278 aligned &= (hedge & align->stride_align[i]) == 0;
1283 GST_LOG ("unaligned padding, increasing padding");
1284 /* increase padded_width */
1285 align->padding_left += align->padding_left & ~(align->padding_left - 1);
1288 /* add the padding */
1289 padded_width = width + align->padding_left + align->padding_right;
1290 padded_height = height + align->padding_top + align->padding_bottom;
1293 GST_LOG ("padded dimension %u-%u", padded_width, padded_height);
1295 info->width = padded_width;
1296 info->height = padded_height;
1298 if (!fill_planes (info))
1301 /* check alignment */
1303 for (i = 0; i < n_planes; i++) {
1304 GST_LOG ("plane %d, stride %d, alignment %u", i, info->stride[i],
1305 align->stride_align[i]);
1306 aligned &= (info->stride[i] & align->stride_align[i]) == 0;
1311 GST_LOG ("unaligned strides, increasing dimension");
1312 /* increase padded_width */
1313 padded_width += padded_width & ~(padded_width - 1);
1316 align->padding_right = padded_width - width - align->padding_left;
1318 info->width = width;
1319 info->height = height;
1321 for (i = 0; i < n_planes; i++) {
1322 gint vedge, hedge, comp;
1324 /* Find the component for this plane, FIXME, we assume the plane number and
1325 * component number is the same for now, for scaling the dimensions this is
1326 * currently true for all formats but it might not be when adding new
1327 * formats. We might need to add a plane subsamling in the format info to
1328 * make this more generic or maybe use a plane -> component mapping. */
1332 GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (vinfo, comp, align->padding_left);
1334 GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (vinfo, comp, align->padding_top);
1336 GST_DEBUG ("plane %d: comp: %d, hedge %d vedge %d align %d stride %d", i,
1337 comp, hedge, vedge, align->stride_align[i], info->stride[i]);
1339 info->offset[i] += (vedge * info->stride[i]) +
1340 (hedge * GST_VIDEO_FORMAT_INFO_PSTRIDE (vinfo, comp));