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 int 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;
135 #define MAKE_COLORIMETRY(r,m,t,p) { \
136 GST_VIDEO_COLOR_RANGE ##r, GST_VIDEO_COLOR_MATRIX_ ##m, \
137 GST_VIDEO_TRANSFER_ ##t, GST_VIDEO_COLOR_PRIMARIES_ ##p }
139 #define DEFAULT_YUV_SD 0
140 #define DEFAULT_YUV_HD 1
141 #define DEFAULT_RGB 2
142 #define DEFAULT_GRAY 3
143 #define DEFAULT_UNKNOWN 4
144 #define DEFAULT_YUV_UHD 5
146 static const GstVideoColorimetry default_color[] = {
147 MAKE_COLORIMETRY (_16_235, BT601, BT709, SMPTE170M),
148 MAKE_COLORIMETRY (_16_235, BT709, BT709, BT709),
149 MAKE_COLORIMETRY (_0_255, RGB, SRGB, BT709),
150 MAKE_COLORIMETRY (_0_255, BT601, UNKNOWN, UNKNOWN),
151 MAKE_COLORIMETRY (_UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN),
152 MAKE_COLORIMETRY (_16_235, BT2020, BT2020_12, BT2020),
156 set_default_colorimetry (GstVideoInfo * info)
158 const GstVideoFormatInfo *finfo = info->finfo;
160 if (GST_VIDEO_FORMAT_INFO_IS_YUV (finfo)) {
161 if (info->height >= 2160) {
162 info->chroma_site = GST_VIDEO_CHROMA_SITE_H_COSITED;
163 info->colorimetry = default_color[DEFAULT_YUV_UHD];
164 } else if (info->height > 576) {
165 info->chroma_site = GST_VIDEO_CHROMA_SITE_H_COSITED;
166 info->colorimetry = default_color[DEFAULT_YUV_HD];
168 info->chroma_site = GST_VIDEO_CHROMA_SITE_NONE;
169 info->colorimetry = default_color[DEFAULT_YUV_SD];
171 } else if (GST_VIDEO_FORMAT_INFO_IS_GRAY (finfo)) {
172 info->colorimetry = default_color[DEFAULT_GRAY];
173 } else if (GST_VIDEO_FORMAT_INFO_IS_RGB (finfo)) {
174 info->colorimetry = default_color[DEFAULT_RGB];
176 info->colorimetry = default_color[DEFAULT_UNKNOWN];
181 validate_colorimetry (GstVideoInfo * info)
183 const GstVideoFormatInfo *finfo = info->finfo;
185 if (!GST_VIDEO_FORMAT_INFO_IS_RGB (finfo) &&
186 info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB)
189 if (GST_VIDEO_FORMAT_INFO_IS_YUV (finfo) &&
190 info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN)
197 * gst_video_info_set_format:
198 * @info: a #GstVideoInfo
199 * @format: the format
203 * Set the default info for a video frame of @format and @width and @height.
205 * Note: This initializes @info first, no values are preserved. This function
206 * does not set the offsets correctly for interlaced vertically
207 * subsampled formats.
210 gst_video_info_set_format (GstVideoInfo * info, GstVideoFormat format,
211 guint width, guint height)
213 g_return_if_fail (info != NULL);
214 g_return_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN);
216 gst_video_info_init (info);
218 info->finfo = gst_video_format_get_info (format);
220 info->height = height;
223 set_default_colorimetry (info);
228 static const gchar *interlace_mode[] = {
236 * gst_video_interlace_mode_to_string:
237 * @mode: a #GstVideoInterlaceMode
239 * Convert @mode to its string representation.
241 * Returns: @mode as a string or NULL if @mode in invalid.
246 gst_video_interlace_mode_to_string (GstVideoInterlaceMode mode)
248 if (((guint) mode) >= G_N_ELEMENTS (interlace_mode))
251 return interlace_mode[mode];
255 * gst_video_interlace_mode_from_string:
258 * Convert @mode to a #GstVideoInterlaceMode
260 * Returns: the #GstVideoInterlaceMode of @mode or
261 * #GST_VIDEO_INTERLACE_MODE_PROGRESSIVE when @mode is not a valid
262 * string representation for a #GstVideoInterlaceMode.
266 GstVideoInterlaceMode
267 gst_video_interlace_mode_from_string (const gchar * mode)
270 for (i = 0; i < G_N_ELEMENTS (interlace_mode); i++) {
271 if (g_str_equal (interlace_mode[i], mode))
274 return GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
278 * gst_video_info_from_caps:
279 * @info: a #GstVideoInfo
282 * Parse @caps and update @info.
284 * Returns: TRUE if @caps could be parsed
287 gst_video_info_from_caps (GstVideoInfo * info, const GstCaps * caps)
289 GstStructure *structure;
291 GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
292 gint width = 0, height = 0;
296 g_return_val_if_fail (info != NULL, FALSE);
297 g_return_val_if_fail (caps != NULL, FALSE);
298 g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
300 GST_DEBUG ("parsing caps %" GST_PTR_FORMAT, caps);
302 structure = gst_caps_get_structure (caps, 0);
304 if (gst_structure_has_name (structure, "video/x-raw")) {
305 if (!(s = gst_structure_get_string (structure, "format")))
308 format = gst_video_format_from_string (s);
309 if (format == GST_VIDEO_FORMAT_UNKNOWN)
312 } else if (g_str_has_prefix (gst_structure_get_name (structure), "video/") ||
313 g_str_has_prefix (gst_structure_get_name (structure), "image/")) {
314 format = GST_VIDEO_FORMAT_ENCODED;
319 /* width and height are mandatory, except for non-raw-formats */
320 if (!gst_structure_get_int (structure, "width", &width) &&
321 format != GST_VIDEO_FORMAT_ENCODED)
323 if (!gst_structure_get_int (structure, "height", &height) &&
324 format != GST_VIDEO_FORMAT_ENCODED)
327 gst_video_info_init (info);
329 info->finfo = gst_video_format_get_info (format);
331 info->height = height;
333 if (gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d)) {
335 /* variable framerate */
336 info->flags |= GST_VIDEO_FLAG_VARIABLE_FPS;
337 /* see if we have a max-framerate */
338 gst_structure_get_fraction (structure, "max-framerate", &fps_n, &fps_d);
343 /* unspecified is variable framerate */
348 if (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
357 if ((s = gst_structure_get_string (structure, "interlace-mode")))
358 info->interlace_mode = gst_video_interlace_mode_from_string (s);
360 info->interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
363 if ((s = gst_structure_get_string (structure, "multiview-mode")))
364 GST_VIDEO_INFO_MULTIVIEW_MODE (info) =
365 gst_video_multiview_mode_from_caps_string (s);
367 GST_VIDEO_INFO_MULTIVIEW_MODE (info) = GST_VIDEO_MULTIVIEW_MODE_NONE;
369 gst_structure_get_flagset (structure, "multiview-flags",
370 &GST_VIDEO_INFO_MULTIVIEW_FLAGS (info), NULL);
372 if (!gst_structure_get_int (structure, "views", &info->views))
375 /* At one point, I tried normalising the half-aspect flag here,
376 * but it behaves weird for GstVideoInfo operations other than
377 * directly converting to/from caps - sometimes causing the
378 * PAR to be doubled/halved too many times */
381 if ((s = gst_structure_get_string (structure, "chroma-site")))
382 info->chroma_site = gst_video_chroma_from_string (s);
384 info->chroma_site = GST_VIDEO_CHROMA_SITE_UNKNOWN;
386 if ((s = gst_structure_get_string (structure, "colorimetry"))) {
387 if (!gst_video_colorimetry_from_string (&info->colorimetry, s)) {
388 GST_WARNING ("unparsable colorimetry, using default");
389 set_default_colorimetry (info);
390 } else if (!validate_colorimetry (info)) {
391 GST_WARNING ("invalid colorimetry, using default");
392 set_default_colorimetry (info);
395 GST_DEBUG ("no colorimetry, using default");
396 set_default_colorimetry (info);
406 GST_ERROR ("wrong name '%s', expected video/ or image/",
407 gst_structure_get_name (structure));
412 GST_ERROR ("no format given");
417 GST_ERROR ("unknown format '%s' given", s);
422 GST_ERROR ("no width property given");
427 GST_ERROR ("no height property given");
433 * gst_video_info_is_equal:
434 * @info: a #GstVideoInfo
435 * @other: a #GstVideoInfo
437 * Compares two #GstVideoInfo and returns whether they are equal or not
439 * Returns: %TRUE if @info and @other are equal, else %FALSE.
442 gst_video_info_is_equal (const GstVideoInfo * info, const GstVideoInfo * other)
446 if (GST_VIDEO_INFO_FORMAT (info) != GST_VIDEO_INFO_FORMAT (other))
448 if (GST_VIDEO_INFO_INTERLACE_MODE (info) !=
449 GST_VIDEO_INFO_INTERLACE_MODE (other))
451 if (GST_VIDEO_INFO_FLAGS (info) != GST_VIDEO_INFO_FLAGS (other))
453 if (GST_VIDEO_INFO_WIDTH (info) != GST_VIDEO_INFO_WIDTH (other))
455 if (GST_VIDEO_INFO_HEIGHT (info) != GST_VIDEO_INFO_HEIGHT (other))
457 if (GST_VIDEO_INFO_SIZE (info) != GST_VIDEO_INFO_SIZE (other))
459 if (GST_VIDEO_INFO_PAR_N (info) != GST_VIDEO_INFO_PAR_N (other))
461 if (GST_VIDEO_INFO_PAR_D (info) != GST_VIDEO_INFO_PAR_D (other))
463 if (GST_VIDEO_INFO_FPS_N (info) != GST_VIDEO_INFO_FPS_N (other))
465 if (GST_VIDEO_INFO_FPS_D (info) != GST_VIDEO_INFO_FPS_D (other))
467 if (!gst_video_colorimetry_is_equal (&GST_VIDEO_INFO_COLORIMETRY (info),
468 &GST_VIDEO_INFO_COLORIMETRY (other)))
470 if (GST_VIDEO_INFO_CHROMA_SITE (info) != GST_VIDEO_INFO_CHROMA_SITE (other))
472 if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) !=
473 GST_VIDEO_INFO_MULTIVIEW_MODE (other))
475 if (GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) !=
476 GST_VIDEO_INFO_MULTIVIEW_FLAGS (other))
478 if (GST_VIDEO_INFO_VIEWS (info) != GST_VIDEO_INFO_VIEWS (other))
481 for (i = 0; i < info->finfo->n_planes; i++) {
482 if (info->stride[i] != other->stride[i])
484 if (info->offset[i] != other->offset[i])
492 * gst_video_info_to_caps:
493 * @info: a #GstVideoInfo
495 * Convert the values of @info into a #GstCaps.
497 * Returns: a new #GstCaps containing the info of @info.
500 gst_video_info_to_caps (GstVideoInfo * info)
507 g_return_val_if_fail (info != NULL, NULL);
508 g_return_val_if_fail (info->finfo != NULL, NULL);
509 g_return_val_if_fail (info->finfo->format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
511 format = gst_video_format_to_string (info->finfo->format);
512 g_return_val_if_fail (format != NULL, NULL);
514 caps = gst_caps_new_simple ("video/x-raw",
515 "format", G_TYPE_STRING, format,
516 "width", G_TYPE_INT, info->width,
517 "height", G_TYPE_INT, info->height, NULL);
522 gst_caps_set_simple (caps, "interlace-mode", G_TYPE_STRING,
523 gst_video_interlace_mode_to_string (info->interlace_mode), NULL);
525 if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) != GST_VIDEO_MULTIVIEW_MODE_NONE) {
526 const gchar *caps_str = NULL;
528 /* If the half-aspect flag is set, applying it into the PAR of the
529 * resulting caps now seems safe, and helps with automatic behaviour
530 * in elements that aren't explicitly multiview aware */
531 if (GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) &
532 GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT) {
533 GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) &=
534 ~GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
535 switch (GST_VIDEO_INFO_MULTIVIEW_MODE (info)) {
536 case GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE:
537 case GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX:
538 case GST_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED:
539 case GST_VIDEO_MULTIVIEW_MODE_CHECKERBOARD:
540 par_n *= 2; /* double the width / half the height */
542 case GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED:
543 case GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM:
544 par_d *= 2; /* half the width / double the height */
552 gst_video_multiview_mode_to_caps_string (GST_VIDEO_INFO_MULTIVIEW_MODE
554 if (caps_str != NULL) {
555 gst_caps_set_simple (caps, "multiview-mode", G_TYPE_STRING,
556 caps_str, "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
557 GST_VIDEO_INFO_MULTIVIEW_FLAGS (info), GST_FLAG_SET_MASK_EXACT, NULL);
561 gst_caps_set_simple (caps, "pixel-aspect-ratio",
562 GST_TYPE_FRACTION, par_n, par_d, NULL);
564 if (info->chroma_site != GST_VIDEO_CHROMA_SITE_UNKNOWN)
565 gst_caps_set_simple (caps, "chroma-site", G_TYPE_STRING,
566 gst_video_chroma_to_string (info->chroma_site), NULL);
568 if ((color = gst_video_colorimetry_to_string (&info->colorimetry))) {
569 gst_caps_set_simple (caps, "colorimetry", G_TYPE_STRING, color, NULL);
574 gst_caps_set_simple (caps, "views", G_TYPE_INT, info->views, NULL);
576 if (info->flags & GST_VIDEO_FLAG_VARIABLE_FPS && info->fps_n != 0) {
577 /* variable fps with a max-framerate */
578 gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, 0, 1,
579 "max-framerate", GST_TYPE_FRACTION, info->fps_n, info->fps_d, NULL);
581 /* no variable fps or no max-framerate */
582 gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION,
583 info->fps_n, info->fps_d, NULL);
590 fill_planes (GstVideoInfo * info)
592 gsize width, height, cr_h;
594 width = (gsize) info->width;
595 height = (gsize) info->height;
597 switch (info->finfo->format) {
598 case GST_VIDEO_FORMAT_YUY2:
599 case GST_VIDEO_FORMAT_YVYU:
600 case GST_VIDEO_FORMAT_UYVY:
601 info->stride[0] = GST_ROUND_UP_4 (width * 2);
603 info->size = info->stride[0] * height;
605 case GST_VIDEO_FORMAT_AYUV:
606 case GST_VIDEO_FORMAT_RGBx:
607 case GST_VIDEO_FORMAT_RGBA:
608 case GST_VIDEO_FORMAT_BGRx:
609 case GST_VIDEO_FORMAT_BGRA:
610 case GST_VIDEO_FORMAT_SR32:
611 case GST_VIDEO_FORMAT_xRGB:
612 case GST_VIDEO_FORMAT_ARGB:
613 case GST_VIDEO_FORMAT_xBGR:
614 case GST_VIDEO_FORMAT_ABGR:
615 case GST_VIDEO_FORMAT_r210:
616 info->stride[0] = width * 4;
618 info->size = info->stride[0] * height;
620 case GST_VIDEO_FORMAT_RGB16:
621 case GST_VIDEO_FORMAT_BGR16:
622 case GST_VIDEO_FORMAT_RGB15:
623 case GST_VIDEO_FORMAT_BGR15:
624 info->stride[0] = GST_ROUND_UP_4 (width * 2);
626 info->size = info->stride[0] * height;
628 case GST_VIDEO_FORMAT_RGB:
629 case GST_VIDEO_FORMAT_BGR:
630 case GST_VIDEO_FORMAT_v308:
631 info->stride[0] = GST_ROUND_UP_4 (width * 3);
633 info->size = info->stride[0] * height;
635 case GST_VIDEO_FORMAT_v210:
636 info->stride[0] = ((width + 47) / 48) * 128;
638 info->size = info->stride[0] * height;
640 case GST_VIDEO_FORMAT_v216:
641 info->stride[0] = GST_ROUND_UP_8 (width * 4);
643 info->size = info->stride[0] * height;
645 case GST_VIDEO_FORMAT_GRAY8:
646 info->stride[0] = GST_ROUND_UP_4 (width);
648 info->size = info->stride[0] * height;
650 case GST_VIDEO_FORMAT_GRAY16_BE:
651 case GST_VIDEO_FORMAT_GRAY16_LE:
652 info->stride[0] = GST_ROUND_UP_4 (width * 2);
654 info->size = info->stride[0] * height;
656 case GST_VIDEO_FORMAT_UYVP:
657 info->stride[0] = GST_ROUND_UP_4 ((width * 2 * 5 + 3) / 4);
659 info->size = info->stride[0] * height;
661 case GST_VIDEO_FORMAT_RGB8P:
662 info->stride[0] = GST_ROUND_UP_4 (width);
665 info->offset[1] = info->stride[0] * height;
666 info->size = info->offset[1] + (4 * 256);
668 case GST_VIDEO_FORMAT_IYU1:
669 info->stride[0] = GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) +
670 GST_ROUND_UP_4 (width) / 2);
672 info->size = info->stride[0] * height;
674 case GST_VIDEO_FORMAT_ARGB64:
675 case GST_VIDEO_FORMAT_AYUV64:
676 info->stride[0] = width * 8;
678 info->size = info->stride[0] * height;
680 case GST_VIDEO_FORMAT_I420:
681 case GST_VIDEO_FORMAT_S420:
682 case GST_VIDEO_FORMAT_YV12: /* same as I420, but plane 1+2 swapped */
683 #ifdef TIZEN_PROFILE_TV
684 case GST_VIDEO_FORMAT_STV0:
685 case GST_VIDEO_FORMAT_STV1:
687 info->stride[0] = GST_ROUND_UP_4 (width);
688 info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
689 info->stride[2] = info->stride[1];
691 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
692 cr_h = GST_ROUND_UP_2 (height) / 2;
693 if (GST_VIDEO_INFO_IS_INTERLACED (info))
694 cr_h = GST_ROUND_UP_2 (cr_h);
695 info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
696 info->size = info->offset[2] + info->stride[2] * cr_h;
698 case GST_VIDEO_FORMAT_Y41B:
699 info->stride[0] = GST_ROUND_UP_4 (width);
700 info->stride[1] = GST_ROUND_UP_16 (width) / 4;
701 info->stride[2] = info->stride[1];
703 info->offset[1] = info->stride[0] * height;
704 info->offset[2] = info->offset[1] + info->stride[1] * height;
705 /* simplification of ROUNDUP4(w)*h + 2*((ROUNDUP16(w)/4)*h */
706 info->size = (info->stride[0] + (GST_ROUND_UP_16 (width) / 2)) * height;
708 case GST_VIDEO_FORMAT_Y42B:
709 info->stride[0] = GST_ROUND_UP_4 (width);
710 info->stride[1] = GST_ROUND_UP_8 (width) / 2;
711 info->stride[2] = info->stride[1];
713 info->offset[1] = info->stride[0] * height;
714 info->offset[2] = info->offset[1] + info->stride[1] * height;
715 /* simplification of ROUNDUP4(w)*h + 2*(ROUNDUP8(w)/2)*h */
716 info->size = (info->stride[0] + GST_ROUND_UP_8 (width)) * height;
718 case GST_VIDEO_FORMAT_Y444:
719 case GST_VIDEO_FORMAT_GBR:
720 info->stride[0] = GST_ROUND_UP_4 (width);
721 info->stride[1] = info->stride[0];
722 info->stride[2] = info->stride[0];
724 info->offset[1] = info->stride[0] * height;
725 info->offset[2] = info->offset[1] * 2;
726 info->size = info->stride[0] * height * 3;
728 case GST_VIDEO_FORMAT_NV12:
729 #ifdef TIZEN_FEATURE_VIDEO_MODIFICATION
730 case GST_VIDEO_FORMAT_SN12:
731 case GST_VIDEO_FORMAT_ST12:
732 case GST_VIDEO_FORMAT_SN21:
734 case GST_VIDEO_FORMAT_NV21:
735 info->stride[0] = GST_ROUND_UP_4 (width);
736 info->stride[1] = info->stride[0];
738 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
739 #ifdef TIZEN_FEATURE_VIDEO_MODIFICATION
740 info->size = info->stride[0] * GST_ROUND_UP_2 (height) * 3 / 2;
742 cr_h = GST_ROUND_UP_2 (height) / 2;
743 if (GST_VIDEO_INFO_IS_INTERLACED (info))
744 cr_h = GST_ROUND_UP_2 (cr_h);
745 info->size = info->offset[1] + info->stride[0] * cr_h;
748 case GST_VIDEO_FORMAT_NV16:
749 case GST_VIDEO_FORMAT_NV61:
750 info->stride[0] = GST_ROUND_UP_4 (width);
751 info->stride[1] = info->stride[0];
753 info->offset[1] = info->stride[0] * height;
754 info->size = info->stride[0] * height * 2;
756 case GST_VIDEO_FORMAT_NV24:
757 info->stride[0] = GST_ROUND_UP_4 (width);
758 info->stride[1] = GST_ROUND_UP_4 (width * 2);
760 info->offset[1] = info->stride[0] * height;
761 info->size = info->stride[0] * height + info->stride[1] * height;
763 case GST_VIDEO_FORMAT_A420:
764 info->stride[0] = GST_ROUND_UP_4 (width);
765 info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
766 info->stride[2] = info->stride[1];
767 info->stride[3] = info->stride[0];
769 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
770 cr_h = GST_ROUND_UP_2 (height) / 2;
771 if (GST_VIDEO_INFO_IS_INTERLACED (info))
772 cr_h = GST_ROUND_UP_2 (cr_h);
773 info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
774 info->offset[3] = info->offset[2] + info->stride[2] * cr_h;
775 info->size = info->offset[3] + info->stride[0] * GST_ROUND_UP_2 (height);
777 case GST_VIDEO_FORMAT_YUV9:
778 case GST_VIDEO_FORMAT_YVU9:
779 info->stride[0] = GST_ROUND_UP_4 (width);
780 info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4);
781 info->stride[2] = info->stride[1];
783 info->offset[1] = info->stride[0] * height;
784 cr_h = GST_ROUND_UP_4 (height) / 4;
785 if (GST_VIDEO_INFO_IS_INTERLACED (info))
786 cr_h = GST_ROUND_UP_2 (cr_h);
787 info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
788 info->size = info->offset[2] + info->stride[2] * cr_h;
790 case GST_VIDEO_FORMAT_I420_10LE:
791 case GST_VIDEO_FORMAT_I420_10BE:
792 info->stride[0] = GST_ROUND_UP_4 (width * 2);
793 info->stride[1] = GST_ROUND_UP_4 (width);
794 info->stride[2] = info->stride[1];
796 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
797 cr_h = GST_ROUND_UP_2 (height) / 2;
798 if (GST_VIDEO_INFO_IS_INTERLACED (info))
799 cr_h = GST_ROUND_UP_2 (cr_h);
800 info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
801 info->size = info->offset[2] + info->stride[2] * cr_h;
803 case GST_VIDEO_FORMAT_I422_10LE:
804 case GST_VIDEO_FORMAT_I422_10BE:
805 info->stride[0] = GST_ROUND_UP_4 (width * 2);
806 info->stride[1] = GST_ROUND_UP_4 (width);
807 info->stride[2] = info->stride[1];
809 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
810 info->offset[2] = info->offset[1] +
811 info->stride[1] * GST_ROUND_UP_2 (height);
812 info->size = info->offset[2] + info->stride[2] * GST_ROUND_UP_2 (height);
814 case GST_VIDEO_FORMAT_Y444_10LE:
815 case GST_VIDEO_FORMAT_Y444_10BE:
816 case GST_VIDEO_FORMAT_GBR_10LE:
817 case GST_VIDEO_FORMAT_GBR_10BE:
818 info->stride[0] = GST_ROUND_UP_4 (width * 2);
819 info->stride[1] = info->stride[0];
820 info->stride[2] = info->stride[0];
822 info->offset[1] = info->stride[0] * height;
823 info->offset[2] = info->offset[1] * 2;
824 info->size = info->stride[0] * height * 3;
826 case GST_VIDEO_FORMAT_NV12_64Z32:
828 GST_VIDEO_TILE_MAKE_STRIDE (GST_ROUND_UP_128 (width) / 64,
829 GST_ROUND_UP_32 (height) / 32);
831 GST_VIDEO_TILE_MAKE_STRIDE (GST_ROUND_UP_128 (width) / 64,
832 GST_ROUND_UP_64 (height) / 64);
834 info->offset[1] = GST_ROUND_UP_128 (width) * GST_ROUND_UP_32 (height);
835 info->size = info->offset[1] +
836 GST_ROUND_UP_128 (width) * GST_ROUND_UP_64 (height) / 2;
838 case GST_VIDEO_FORMAT_A420_10LE:
839 case GST_VIDEO_FORMAT_A420_10BE:
840 info->stride[0] = GST_ROUND_UP_4 (width * 2);
841 info->stride[1] = GST_ROUND_UP_4 (width);
842 info->stride[2] = info->stride[1];
843 info->stride[3] = info->stride[0];
845 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
846 cr_h = GST_ROUND_UP_2 (height) / 2;
847 if (GST_VIDEO_INFO_IS_INTERLACED (info))
848 cr_h = GST_ROUND_UP_2 (cr_h);
849 info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
850 info->offset[3] = info->offset[2] + info->stride[2] * cr_h;
851 info->size = info->offset[3] + info->stride[0] * GST_ROUND_UP_2 (height);
853 case GST_VIDEO_FORMAT_A422_10LE:
854 case GST_VIDEO_FORMAT_A422_10BE:
855 info->stride[0] = GST_ROUND_UP_4 (width * 2);
856 info->stride[1] = GST_ROUND_UP_4 (width);
857 info->stride[2] = info->stride[1];
858 info->stride[3] = info->stride[0];
860 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
861 info->offset[2] = info->offset[1] +
862 info->stride[1] * GST_ROUND_UP_2 (height);
864 info->offset[2] + info->stride[2] * GST_ROUND_UP_2 (height);
865 info->size = info->offset[3] + info->stride[0] * GST_ROUND_UP_2 (height);
867 case GST_VIDEO_FORMAT_A444_10LE:
868 case GST_VIDEO_FORMAT_A444_10BE:
869 info->stride[0] = GST_ROUND_UP_4 (width * 2);
870 info->stride[1] = info->stride[0];
871 info->stride[2] = info->stride[0];
872 info->stride[3] = info->stride[0];
874 info->offset[1] = info->stride[0] * height;
875 info->offset[2] = info->offset[1] * 2;
876 info->offset[3] = info->offset[1] * 3;
877 info->size = info->stride[0] * height * 4;
880 case GST_VIDEO_FORMAT_ENCODED:
882 case GST_VIDEO_FORMAT_UNKNOWN:
883 GST_ERROR ("invalid format");
884 g_warning ("invalid format");
891 * gst_video_info_convert:
892 * @info: a #GstVideoInfo
893 * @src_format: #GstFormat of the @src_value
894 * @src_value: value to convert
895 * @dest_format: #GstFormat of the @dest_value
896 * @dest_value: pointer to destination value
898 * Converts among various #GstFormat types. This function handles
899 * GST_FORMAT_BYTES, GST_FORMAT_TIME, and GST_FORMAT_DEFAULT. For
900 * raw video, GST_FORMAT_DEFAULT corresponds to video frames. This
901 * function can be used to handle pad queries of the type GST_QUERY_CONVERT.
903 * Returns: TRUE if the conversion was successful.
906 gst_video_info_convert (GstVideoInfo * info,
907 GstFormat src_format, gint64 src_value,
908 GstFormat dest_format, gint64 * dest_value)
910 gboolean ret = FALSE;
914 g_return_val_if_fail (info != NULL, 0);
915 g_return_val_if_fail (info->finfo != NULL, 0);
916 g_return_val_if_fail (info->finfo->format != GST_VIDEO_FORMAT_UNKNOWN, 0);
917 g_return_val_if_fail (info->size > 0, 0);
923 GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s to %s",
924 src_value, gst_format_get_name (src_format),
925 gst_format_get_name (dest_format));
927 if (src_format == dest_format) {
928 *dest_value = src_value;
933 if (src_value == -1) {
939 /* bytes to frames */
940 if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_DEFAULT) {
942 *dest_value = gst_util_uint64_scale (src_value, 1, size);
944 GST_ERROR ("blocksize is 0");
951 /* frames to bytes */
952 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_BYTES) {
953 *dest_value = gst_util_uint64_scale (src_value, size, 1);
959 if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_DEFAULT) {
961 *dest_value = gst_util_uint64_scale (src_value,
962 fps_n, GST_SECOND * fps_d);
964 GST_ERROR ("framerate denominator is 0");
972 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
974 *dest_value = gst_util_uint64_scale (src_value,
975 GST_SECOND * fps_d, fps_n);
977 GST_ERROR ("framerate numerator is 0");
985 if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) {
987 *dest_value = gst_util_uint64_scale (src_value,
988 fps_n * size, GST_SECOND * fps_d);
990 GST_ERROR ("framerate denominator is 0");
998 if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_TIME) {
999 if (fps_n != 0 && size != 0) {
1000 *dest_value = gst_util_uint64_scale (src_value,
1001 GST_SECOND * fps_d, fps_n * size);
1003 GST_ERROR ("framerate denominator and/or blocksize is 0");
1011 GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, ret, *dest_value);
1017 * gst_video_info_align:
1018 * @info: a #GstVideoInfo
1019 * @align: alignment parameters
1021 * Adjust the offset and stride fields in @info so that the padding and
1022 * stride alignment in @align is respected.
1024 * Extra padding will be added to the right side when stride alignment padding
1025 * is required and @align will be updated with the new padding values.
1028 gst_video_info_align (GstVideoInfo * info, GstVideoAlignment * align)
1030 const GstVideoFormatInfo *vinfo = info->finfo;
1032 gint padded_width, padded_height;
1036 width = GST_VIDEO_INFO_WIDTH (info);
1037 height = GST_VIDEO_INFO_HEIGHT (info);
1039 GST_LOG ("padding %u-%ux%u-%u", align->padding_top,
1040 align->padding_left, align->padding_right, align->padding_bottom);
1042 n_planes = GST_VIDEO_INFO_N_PLANES (info);
1044 if (GST_VIDEO_FORMAT_INFO_HAS_PALETTE (vinfo))
1047 /* first make sure the left padding does not cause alignment problems later */
1049 GST_LOG ("left padding %u", align->padding_left);
1051 for (i = 0; i < n_planes; i++) {
1054 /* this is the amout of pixels to add as left padding */
1055 hedge = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (vinfo, i, align->padding_left);
1056 hedge *= GST_VIDEO_FORMAT_INFO_PSTRIDE (vinfo, i);
1058 GST_LOG ("plane %d, padding %d, alignment %u", i, hedge,
1059 align->stride_align[i]);
1060 aligned &= (hedge & align->stride_align[i]) == 0;
1065 GST_LOG ("unaligned padding, increasing padding");
1066 /* increase padded_width */
1067 align->padding_left += align->padding_left & ~(align->padding_left - 1);
1070 /* add the padding */
1071 padded_width = width + align->padding_left + align->padding_right;
1072 padded_height = height + align->padding_top + align->padding_bottom;
1075 GST_LOG ("padded dimension %u-%u", padded_width, padded_height);
1077 info->width = padded_width;
1078 info->height = padded_height;
1081 /* check alignment */
1083 for (i = 0; i < n_planes; i++) {
1084 GST_LOG ("plane %d, stride %d, alignment %u", i, info->stride[i],
1085 align->stride_align[i]);
1086 aligned &= (info->stride[i] & align->stride_align[i]) == 0;
1091 GST_LOG ("unaligned strides, increasing dimension");
1092 /* increase padded_width */
1093 padded_width += padded_width & ~(padded_width - 1);
1096 align->padding_right = padded_width - width - align->padding_left;
1098 info->width = width;
1099 info->height = height;
1101 for (i = 0; i < n_planes; i++) {
1102 gint vedge, hedge, comp;
1104 /* Find the component for this plane, FIXME, we assume the plane number and
1105 * component number is the same for now, for scaling the dimensions this is
1106 * currently true for all formats but it might not be when adding new
1107 * formats. We might need to add a plane subsamling in the format info to
1108 * make this more generic or maybe use a plane -> component mapping. */
1112 GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (vinfo, comp, align->padding_left);
1114 GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (vinfo, comp, align->padding_top);
1116 GST_DEBUG ("plane %d: comp: %d, hedge %d vedge %d align %d stride %d", i,
1117 comp, hedge, vedge, align->stride_align[i], info->stride[i]);
1119 info->offset[i] += (vedge * info->stride[i]) +
1120 (hedge * GST_VIDEO_FORMAT_INFO_PSTRIDE (vinfo, comp));