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 static int fill_planes (GstVideoInfo * info);
35 * gst_video_info_init:
36 * @info: a #GstVideoInfo
38 * Initialize @info with default values.
41 gst_video_info_init (GstVideoInfo * info)
43 g_return_if_fail (info != NULL);
45 memset (info, 0, sizeof (GstVideoInfo));
47 info->finfo = gst_video_format_get_info (GST_VIDEO_FORMAT_UNKNOWN);
50 /* arrange for sensible defaults, e.g. if turned into caps */
55 GST_VIDEO_INFO_MULTIVIEW_MODE (info) = GST_VIDEO_MULTIVIEW_MODE_NONE;
58 #define MAKE_COLORIMETRY(r,m,t,p) { \
59 GST_VIDEO_COLOR_RANGE ##r, GST_VIDEO_COLOR_MATRIX_ ##m, \
60 GST_VIDEO_TRANSFER_ ##t, GST_VIDEO_COLOR_PRIMARIES_ ##p }
62 #define DEFAULT_YUV_SD 0
63 #define DEFAULT_YUV_HD 1
65 #define DEFAULT_GRAY 3
66 #define DEFAULT_UNKNOWN 4
67 #define DEFAULT_YUV_UHD 5
69 static const GstVideoColorimetry default_color[] = {
70 MAKE_COLORIMETRY (_16_235, BT601, BT709, SMPTE170M),
71 MAKE_COLORIMETRY (_16_235, BT709, BT709, BT709),
72 MAKE_COLORIMETRY (_0_255, RGB, SRGB, BT709),
73 MAKE_COLORIMETRY (_0_255, BT601, UNKNOWN, UNKNOWN),
74 MAKE_COLORIMETRY (_UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN),
75 MAKE_COLORIMETRY (_16_235, BT2020, BT2020_12, BT2020),
79 set_default_colorimetry (GstVideoInfo * info)
81 const GstVideoFormatInfo *finfo = info->finfo;
83 if (GST_VIDEO_FORMAT_INFO_IS_YUV (finfo)) {
84 if (info->height >= 2160) {
85 info->chroma_site = GST_VIDEO_CHROMA_SITE_H_COSITED;
86 info->colorimetry = default_color[DEFAULT_YUV_UHD];
87 } else if (info->height > 576) {
88 info->chroma_site = GST_VIDEO_CHROMA_SITE_H_COSITED;
89 info->colorimetry = default_color[DEFAULT_YUV_HD];
91 info->chroma_site = GST_VIDEO_CHROMA_SITE_NONE;
92 info->colorimetry = default_color[DEFAULT_YUV_SD];
94 } else if (GST_VIDEO_FORMAT_INFO_IS_GRAY (finfo)) {
95 info->colorimetry = default_color[DEFAULT_GRAY];
96 } else if (GST_VIDEO_FORMAT_INFO_IS_RGB (finfo)) {
97 info->colorimetry = default_color[DEFAULT_RGB];
99 info->colorimetry = default_color[DEFAULT_UNKNOWN];
104 validate_colorimetry (GstVideoInfo * info)
106 const GstVideoFormatInfo *finfo = info->finfo;
108 if (!GST_VIDEO_FORMAT_INFO_IS_RGB (finfo) &&
109 info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB)
112 if (GST_VIDEO_FORMAT_INFO_IS_YUV (finfo) &&
113 info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN)
120 * gst_video_info_set_format:
121 * @info: a #GstVideoInfo
122 * @format: the format
126 * Set the default info for a video frame of @format and @width and @height.
128 * Note: This initializes @info first, no values are preserved. This function
129 * does not set the offsets correctly for interlaced vertically
130 * subsampled formats.
133 gst_video_info_set_format (GstVideoInfo * info, GstVideoFormat format,
134 guint width, guint height)
136 g_return_if_fail (info != NULL);
137 g_return_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN);
139 gst_video_info_init (info);
141 info->finfo = gst_video_format_get_info (format);
143 info->height = height;
146 set_default_colorimetry (info);
151 static const gchar *interlace_mode[] = {
159 * gst_video_interlace_mode_to_string:
160 * @mode: a #GstVideoInterlaceMode
162 * Convert @mode to its string representation.
164 * Returns: @mode as a string or NULL if @mode in invalid.
169 gst_video_interlace_mode_to_string (GstVideoInterlaceMode mode)
171 if (((guint) mode) >= G_N_ELEMENTS (interlace_mode))
174 return interlace_mode[mode];
178 * gst_video_interlace_mode_from_string:
181 * Convert @mode to a #GstVideoInterlaceMode
183 * Returns: the #GstVideoInterlaceMode of @mode or
184 * #GST_VIDEO_INTERLACE_MODE_PROGRESSIVE when @mode is not a valid
185 * string representation for a #GstVideoInterlaceMode.
189 GstVideoInterlaceMode
190 gst_video_interlace_mode_from_string (const gchar * mode)
193 for (i = 0; i < G_N_ELEMENTS (interlace_mode); i++) {
194 if (g_str_equal (interlace_mode[i], mode))
197 return GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
201 * gst_video_info_from_caps:
202 * @info: a #GstVideoInfo
205 * Parse @caps and update @info.
207 * Returns: TRUE if @caps could be parsed
210 gst_video_info_from_caps (GstVideoInfo * info, const GstCaps * caps)
212 GstStructure *structure;
214 GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
215 gint width = 0, height = 0;
219 g_return_val_if_fail (info != NULL, FALSE);
220 g_return_val_if_fail (caps != NULL, FALSE);
221 g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
223 GST_DEBUG ("parsing caps %" GST_PTR_FORMAT, caps);
225 structure = gst_caps_get_structure (caps, 0);
227 if (gst_structure_has_name (structure, "video/x-raw")) {
228 if (!(s = gst_structure_get_string (structure, "format")))
231 format = gst_video_format_from_string (s);
232 if (format == GST_VIDEO_FORMAT_UNKNOWN)
235 } else if (g_str_has_prefix (gst_structure_get_name (structure), "video/") ||
236 g_str_has_prefix (gst_structure_get_name (structure), "image/")) {
237 format = GST_VIDEO_FORMAT_ENCODED;
242 /* width and height are mandatory, except for non-raw-formats */
243 if (!gst_structure_get_int (structure, "width", &width) &&
244 format != GST_VIDEO_FORMAT_ENCODED)
246 if (!gst_structure_get_int (structure, "height", &height) &&
247 format != GST_VIDEO_FORMAT_ENCODED)
250 gst_video_info_init (info);
252 info->finfo = gst_video_format_get_info (format);
254 info->height = height;
256 if (gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d)) {
258 /* variable framerate */
259 info->flags |= GST_VIDEO_FLAG_VARIABLE_FPS;
260 /* see if we have a max-framerate */
261 gst_structure_get_fraction (structure, "max-framerate", &fps_n, &fps_d);
266 /* unspecified is variable framerate */
271 if (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
280 if ((s = gst_structure_get_string (structure, "interlace-mode")))
281 info->interlace_mode = gst_video_interlace_mode_from_string (s);
283 info->interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
286 if ((s = gst_structure_get_string (structure, "multiview-mode")))
287 GST_VIDEO_INFO_MULTIVIEW_MODE (info) =
288 gst_video_multiview_mode_from_caps_string (s);
290 GST_VIDEO_INFO_MULTIVIEW_MODE (info) = GST_VIDEO_MULTIVIEW_MODE_NONE;
292 gst_structure_get_flagset (structure, "multiview-flags",
293 &GST_VIDEO_INFO_MULTIVIEW_FLAGS (info), NULL);
295 if (!gst_structure_get_int (structure, "views", &info->views))
298 /* At one point, I tried normalising the half-aspect flag here,
299 * but it behaves weird for GstVideoInfo operations other than
300 * directly converting to/from caps - sometimes causing the
301 * PAR to be doubled/halved too many times */
304 if ((s = gst_structure_get_string (structure, "chroma-site")))
305 info->chroma_site = gst_video_chroma_from_string (s);
307 info->chroma_site = GST_VIDEO_CHROMA_SITE_UNKNOWN;
309 if ((s = gst_structure_get_string (structure, "colorimetry"))) {
310 if (!gst_video_colorimetry_from_string (&info->colorimetry, s)) {
311 GST_WARNING ("unparsable colorimetry, using default");
312 set_default_colorimetry (info);
313 } else if (!validate_colorimetry (info)) {
314 GST_WARNING ("invalid colorimetry, using default");
315 set_default_colorimetry (info);
318 GST_DEBUG ("no colorimetry, using default");
319 set_default_colorimetry (info);
329 GST_ERROR ("wrong name '%s', expected video/ or image/",
330 gst_structure_get_name (structure));
335 GST_ERROR ("no format given");
340 GST_ERROR ("unknown format '%s' given", s);
345 GST_ERROR ("no width property given");
350 GST_ERROR ("no height property given");
356 * gst_video_info_is_equal:
357 * @info: a #GstVideoInfo
358 * @other: a #GstVideoInfo
360 * Compares two #GstVideoInfo and returns whether they are equal or not
362 * Returns: %TRUE if @info and @other are equal, else %FALSE.
365 gst_video_info_is_equal (const GstVideoInfo * info, const GstVideoInfo * other)
369 if (GST_VIDEO_INFO_FORMAT (info) != GST_VIDEO_INFO_FORMAT (other))
371 if (GST_VIDEO_INFO_INTERLACE_MODE (info) !=
372 GST_VIDEO_INFO_INTERLACE_MODE (other))
374 if (GST_VIDEO_INFO_FLAGS (info) != GST_VIDEO_INFO_FLAGS (other))
376 if (GST_VIDEO_INFO_WIDTH (info) != GST_VIDEO_INFO_WIDTH (other))
378 if (GST_VIDEO_INFO_HEIGHT (info) != GST_VIDEO_INFO_HEIGHT (other))
380 if (GST_VIDEO_INFO_SIZE (info) != GST_VIDEO_INFO_SIZE (other))
382 if (GST_VIDEO_INFO_PAR_N (info) != GST_VIDEO_INFO_PAR_N (other))
384 if (GST_VIDEO_INFO_PAR_D (info) != GST_VIDEO_INFO_PAR_D (other))
386 if (GST_VIDEO_INFO_FPS_N (info) != GST_VIDEO_INFO_FPS_N (other))
388 if (GST_VIDEO_INFO_FPS_D (info) != GST_VIDEO_INFO_FPS_D (other))
390 if (!gst_video_colorimetry_is_equal (&GST_VIDEO_INFO_COLORIMETRY (info),
391 &GST_VIDEO_INFO_COLORIMETRY (other)))
393 if (GST_VIDEO_INFO_CHROMA_SITE (info) != GST_VIDEO_INFO_CHROMA_SITE (other))
395 if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) !=
396 GST_VIDEO_INFO_MULTIVIEW_MODE (other))
398 if (GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) !=
399 GST_VIDEO_INFO_MULTIVIEW_FLAGS (other))
401 if (GST_VIDEO_INFO_VIEWS (info) != GST_VIDEO_INFO_VIEWS (other))
404 for (i = 0; i < info->finfo->n_planes; i++) {
405 if (info->stride[i] != other->stride[i])
407 if (info->offset[i] != other->offset[i])
415 * gst_video_info_to_caps:
416 * @info: a #GstVideoInfo
418 * Convert the values of @info into a #GstCaps.
420 * Returns: a new #GstCaps containing the info of @info.
423 gst_video_info_to_caps (GstVideoInfo * info)
430 g_return_val_if_fail (info != NULL, NULL);
431 g_return_val_if_fail (info->finfo != NULL, NULL);
432 g_return_val_if_fail (info->finfo->format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
434 format = gst_video_format_to_string (info->finfo->format);
435 g_return_val_if_fail (format != NULL, NULL);
437 caps = gst_caps_new_simple ("video/x-raw",
438 "format", G_TYPE_STRING, format,
439 "width", G_TYPE_INT, info->width,
440 "height", G_TYPE_INT, info->height, NULL);
445 gst_caps_set_simple (caps, "interlace-mode", G_TYPE_STRING,
446 gst_video_interlace_mode_to_string (info->interlace_mode), NULL);
448 if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) != GST_VIDEO_MULTIVIEW_MODE_NONE) {
449 const gchar *caps_str = NULL;
451 /* If the half-aspect flag is set, applying it into the PAR of the
452 * resulting caps now seems safe, and helps with automatic behaviour
453 * in elements that aren't explicitly multiview aware */
454 if (GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) &
455 GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT) {
456 GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) &=
457 ~GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
458 switch (GST_VIDEO_INFO_MULTIVIEW_MODE (info)) {
459 case GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE:
460 case GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX:
461 case GST_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED:
462 case GST_VIDEO_MULTIVIEW_MODE_CHECKERBOARD:
463 par_n *= 2; /* double the width / half the height */
465 case GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED:
466 case GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM:
467 par_d *= 2; /* half the width / double the height */
475 gst_video_multiview_mode_to_caps_string (GST_VIDEO_INFO_MULTIVIEW_MODE
477 if (caps_str != NULL) {
478 gst_caps_set_simple (caps, "multiview-mode", G_TYPE_STRING,
479 caps_str, "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
480 GST_VIDEO_INFO_MULTIVIEW_FLAGS (info), GST_FLAG_SET_MASK_EXACT, NULL);
484 gst_caps_set_simple (caps, "pixel-aspect-ratio",
485 GST_TYPE_FRACTION, par_n, par_d, NULL);
487 if (info->chroma_site != GST_VIDEO_CHROMA_SITE_UNKNOWN)
488 gst_caps_set_simple (caps, "chroma-site", G_TYPE_STRING,
489 gst_video_chroma_to_string (info->chroma_site), NULL);
491 if ((color = gst_video_colorimetry_to_string (&info->colorimetry))) {
492 gst_caps_set_simple (caps, "colorimetry", G_TYPE_STRING, color, NULL);
497 gst_caps_set_simple (caps, "views", G_TYPE_INT, info->views, NULL);
499 if (info->flags & GST_VIDEO_FLAG_VARIABLE_FPS && info->fps_n != 0) {
500 /* variable fps with a max-framerate */
501 gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, 0, 1,
502 "max-framerate", GST_TYPE_FRACTION, info->fps_n, info->fps_d, NULL);
504 /* no variable fps or no max-framerate */
505 gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION,
506 info->fps_n, info->fps_d, NULL);
513 fill_planes (GstVideoInfo * info)
515 gsize width, height, cr_h;
517 width = (gsize) info->width;
518 height = (gsize) info->height;
520 switch (info->finfo->format) {
521 case GST_VIDEO_FORMAT_YUY2:
522 case GST_VIDEO_FORMAT_YVYU:
523 case GST_VIDEO_FORMAT_UYVY:
524 info->stride[0] = GST_ROUND_UP_4 (width * 2);
526 info->size = info->stride[0] * height;
528 case GST_VIDEO_FORMAT_AYUV:
529 case GST_VIDEO_FORMAT_RGBx:
530 case GST_VIDEO_FORMAT_RGBA:
531 case GST_VIDEO_FORMAT_BGRx:
532 case GST_VIDEO_FORMAT_BGRA:
533 case GST_VIDEO_FORMAT_xRGB:
534 case GST_VIDEO_FORMAT_ARGB:
535 case GST_VIDEO_FORMAT_xBGR:
536 case GST_VIDEO_FORMAT_ABGR:
537 case GST_VIDEO_FORMAT_r210:
538 info->stride[0] = width * 4;
540 info->size = info->stride[0] * height;
542 case GST_VIDEO_FORMAT_RGB16:
543 case GST_VIDEO_FORMAT_BGR16:
544 case GST_VIDEO_FORMAT_RGB15:
545 case GST_VIDEO_FORMAT_BGR15:
546 info->stride[0] = GST_ROUND_UP_4 (width * 2);
548 info->size = info->stride[0] * height;
550 case GST_VIDEO_FORMAT_RGB:
551 case GST_VIDEO_FORMAT_BGR:
552 case GST_VIDEO_FORMAT_v308:
553 info->stride[0] = GST_ROUND_UP_4 (width * 3);
555 info->size = info->stride[0] * height;
557 case GST_VIDEO_FORMAT_v210:
558 info->stride[0] = ((width + 47) / 48) * 128;
560 info->size = info->stride[0] * height;
562 case GST_VIDEO_FORMAT_v216:
563 info->stride[0] = GST_ROUND_UP_8 (width * 4);
565 info->size = info->stride[0] * height;
567 case GST_VIDEO_FORMAT_GRAY8:
568 info->stride[0] = GST_ROUND_UP_4 (width);
570 info->size = info->stride[0] * height;
572 case GST_VIDEO_FORMAT_GRAY16_BE:
573 case GST_VIDEO_FORMAT_GRAY16_LE:
574 info->stride[0] = GST_ROUND_UP_4 (width * 2);
576 info->size = info->stride[0] * height;
578 case GST_VIDEO_FORMAT_UYVP:
579 info->stride[0] = GST_ROUND_UP_4 ((width * 2 * 5 + 3) / 4);
581 info->size = info->stride[0] * height;
583 case GST_VIDEO_FORMAT_RGB8P:
584 info->stride[0] = GST_ROUND_UP_4 (width);
587 info->offset[1] = info->stride[0] * height;
588 info->size = info->offset[1] + (4 * 256);
590 case GST_VIDEO_FORMAT_IYU1:
591 info->stride[0] = GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) +
592 GST_ROUND_UP_4 (width) / 2);
594 info->size = info->stride[0] * height;
596 case GST_VIDEO_FORMAT_ARGB64:
597 case GST_VIDEO_FORMAT_AYUV64:
598 info->stride[0] = width * 8;
600 info->size = info->stride[0] * height;
602 case GST_VIDEO_FORMAT_I420:
603 case GST_VIDEO_FORMAT_YV12: /* same as I420, but plane 1+2 swapped */
604 info->stride[0] = GST_ROUND_UP_4 (width);
605 info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
606 info->stride[2] = info->stride[1];
608 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
609 cr_h = GST_ROUND_UP_2 (height) / 2;
610 if (GST_VIDEO_INFO_IS_INTERLACED (info))
611 cr_h = GST_ROUND_UP_2 (cr_h);
612 info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
613 info->size = info->offset[2] + info->stride[2] * cr_h;
614 GST_DEBUG ("%d %d %d", GST_VIDEO_INFO_IS_INTERLACED (info),
615 (int) info->offset[2], (int) info->size);
617 case GST_VIDEO_FORMAT_Y41B:
618 info->stride[0] = GST_ROUND_UP_4 (width);
619 info->stride[1] = GST_ROUND_UP_16 (width) / 4;
620 info->stride[2] = info->stride[1];
622 info->offset[1] = info->stride[0] * height;
623 info->offset[2] = info->offset[1] + info->stride[1] * height;
624 /* simplification of ROUNDUP4(w)*h + 2*((ROUNDUP16(w)/4)*h */
625 info->size = (info->stride[0] + (GST_ROUND_UP_16 (width) / 2)) * height;
627 case GST_VIDEO_FORMAT_Y42B:
628 info->stride[0] = GST_ROUND_UP_4 (width);
629 info->stride[1] = GST_ROUND_UP_8 (width) / 2;
630 info->stride[2] = info->stride[1];
632 info->offset[1] = info->stride[0] * height;
633 info->offset[2] = info->offset[1] + info->stride[1] * height;
634 /* simplification of ROUNDUP4(w)*h + 2*(ROUNDUP8(w)/2)*h */
635 info->size = (info->stride[0] + GST_ROUND_UP_8 (width)) * height;
637 case GST_VIDEO_FORMAT_Y444:
638 case GST_VIDEO_FORMAT_GBR:
639 info->stride[0] = GST_ROUND_UP_4 (width);
640 info->stride[1] = info->stride[0];
641 info->stride[2] = info->stride[0];
643 info->offset[1] = info->stride[0] * height;
644 info->offset[2] = info->offset[1] * 2;
645 info->size = info->stride[0] * height * 3;
647 case GST_VIDEO_FORMAT_NV12:
648 case GST_VIDEO_FORMAT_NV21:
649 info->stride[0] = GST_ROUND_UP_4 (width);
650 info->stride[1] = info->stride[0];
652 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
653 cr_h = GST_ROUND_UP_2 (height) / 2;
654 if (GST_VIDEO_INFO_IS_INTERLACED (info))
655 cr_h = GST_ROUND_UP_2 (cr_h);
656 info->size = info->offset[1] + info->stride[0] * cr_h;
658 case GST_VIDEO_FORMAT_NV16:
659 case GST_VIDEO_FORMAT_NV61:
660 info->stride[0] = GST_ROUND_UP_4 (width);
661 info->stride[1] = info->stride[0];
663 info->offset[1] = info->stride[0] * height;
664 info->size = info->stride[0] * height * 2;
666 case GST_VIDEO_FORMAT_NV24:
667 info->stride[0] = GST_ROUND_UP_4 (width);
668 info->stride[1] = GST_ROUND_UP_4 (width * 2);
670 info->offset[1] = info->stride[0] * height;
671 info->size = info->stride[0] * height + info->stride[1] * height;
673 case GST_VIDEO_FORMAT_A420:
674 info->stride[0] = GST_ROUND_UP_4 (width);
675 info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
676 info->stride[2] = info->stride[1];
677 info->stride[3] = info->stride[0];
679 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
680 cr_h = GST_ROUND_UP_2 (height) / 2;
681 if (GST_VIDEO_INFO_IS_INTERLACED (info))
682 cr_h = GST_ROUND_UP_2 (cr_h);
683 info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
684 info->offset[3] = info->offset[2] + info->stride[2] * cr_h;
685 info->size = info->offset[3] + info->stride[0] * GST_ROUND_UP_2 (height);
687 case GST_VIDEO_FORMAT_YUV9:
688 case GST_VIDEO_FORMAT_YVU9:
689 info->stride[0] = GST_ROUND_UP_4 (width);
690 info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4);
691 info->stride[2] = info->stride[1];
693 info->offset[1] = info->stride[0] * height;
694 cr_h = GST_ROUND_UP_4 (height) / 4;
695 if (GST_VIDEO_INFO_IS_INTERLACED (info))
696 cr_h = GST_ROUND_UP_2 (cr_h);
697 info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
698 info->size = info->offset[2] + info->stride[2] * cr_h;
700 case GST_VIDEO_FORMAT_I420_10LE:
701 case GST_VIDEO_FORMAT_I420_10BE:
702 info->stride[0] = GST_ROUND_UP_4 (width * 2);
703 info->stride[1] = GST_ROUND_UP_4 (width);
704 info->stride[2] = info->stride[1];
706 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
707 cr_h = GST_ROUND_UP_2 (height) / 2;
708 if (GST_VIDEO_INFO_IS_INTERLACED (info))
709 cr_h = GST_ROUND_UP_2 (cr_h);
710 info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
711 info->size = info->offset[2] + info->stride[2] * cr_h;
713 case GST_VIDEO_FORMAT_I422_10LE:
714 case GST_VIDEO_FORMAT_I422_10BE:
715 info->stride[0] = GST_ROUND_UP_4 (width * 2);
716 info->stride[1] = GST_ROUND_UP_4 (width);
717 info->stride[2] = info->stride[1];
719 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
720 info->offset[2] = info->offset[1] +
721 info->stride[1] * GST_ROUND_UP_2 (height);
722 info->size = info->offset[2] + info->stride[2] * GST_ROUND_UP_2 (height);
724 case GST_VIDEO_FORMAT_Y444_10LE:
725 case GST_VIDEO_FORMAT_Y444_10BE:
726 case GST_VIDEO_FORMAT_GBR_10LE:
727 case GST_VIDEO_FORMAT_GBR_10BE:
728 info->stride[0] = GST_ROUND_UP_4 (width * 2);
729 info->stride[1] = info->stride[0];
730 info->stride[2] = info->stride[0];
732 info->offset[1] = info->stride[0] * height;
733 info->offset[2] = info->offset[1] * 2;
734 info->size = info->stride[0] * height * 3;
736 case GST_VIDEO_FORMAT_NV12_64Z32:
738 GST_VIDEO_TILE_MAKE_STRIDE (GST_ROUND_UP_128 (width) / 64,
739 GST_ROUND_UP_32 (height) / 32);
741 GST_VIDEO_TILE_MAKE_STRIDE (GST_ROUND_UP_128 (width) / 64,
742 GST_ROUND_UP_64 (height) / 64);
744 info->offset[1] = GST_ROUND_UP_128 (width) * GST_ROUND_UP_32 (height);
745 info->size = info->offset[1] +
746 GST_ROUND_UP_128 (width) * GST_ROUND_UP_64 (height) / 2;
748 case GST_VIDEO_FORMAT_A420_10LE:
749 case GST_VIDEO_FORMAT_A420_10BE:
750 info->stride[0] = GST_ROUND_UP_4 (width * 2);
751 info->stride[1] = GST_ROUND_UP_4 (width);
752 info->stride[2] = info->stride[1];
753 info->stride[3] = info->stride[0];
755 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
756 cr_h = GST_ROUND_UP_2 (height) / 2;
757 if (GST_VIDEO_INFO_IS_INTERLACED (info))
758 cr_h = GST_ROUND_UP_2 (cr_h);
759 info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
760 info->offset[3] = info->offset[2] + info->stride[2] * cr_h;
761 info->size = info->offset[3] + info->stride[0] * GST_ROUND_UP_2 (height);
763 case GST_VIDEO_FORMAT_A422_10LE:
764 case GST_VIDEO_FORMAT_A422_10BE:
765 info->stride[0] = GST_ROUND_UP_4 (width * 2);
766 info->stride[1] = GST_ROUND_UP_4 (width);
767 info->stride[2] = info->stride[1];
768 info->stride[3] = info->stride[0];
770 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
771 info->offset[2] = info->offset[1] +
772 info->stride[1] * GST_ROUND_UP_2 (height);
774 info->offset[2] + info->stride[2] * GST_ROUND_UP_2 (height);
775 info->size = info->offset[3] + info->stride[0] * GST_ROUND_UP_2 (height);
777 case GST_VIDEO_FORMAT_A444_10LE:
778 case GST_VIDEO_FORMAT_A444_10BE:
779 info->stride[0] = GST_ROUND_UP_4 (width * 2);
780 info->stride[1] = info->stride[0];
781 info->stride[2] = info->stride[0];
782 info->stride[3] = info->stride[0];
784 info->offset[1] = info->stride[0] * height;
785 info->offset[2] = info->offset[1] * 2;
786 info->offset[3] = info->offset[1] * 3;
787 info->size = info->stride[0] * height * 4;
790 case GST_VIDEO_FORMAT_ENCODED:
792 case GST_VIDEO_FORMAT_UNKNOWN:
793 GST_ERROR ("invalid format");
794 g_warning ("invalid format");
801 * gst_video_info_convert:
802 * @info: a #GstVideoInfo
803 * @src_format: #GstFormat of the @src_value
804 * @src_value: value to convert
805 * @dest_format: #GstFormat of the @dest_value
806 * @dest_value: pointer to destination value
808 * Converts among various #GstFormat types. This function handles
809 * GST_FORMAT_BYTES, GST_FORMAT_TIME, and GST_FORMAT_DEFAULT. For
810 * raw video, GST_FORMAT_DEFAULT corresponds to video frames. This
811 * function can be used to handle pad queries of the type GST_QUERY_CONVERT.
813 * Returns: TRUE if the conversion was successful.
816 gst_video_info_convert (GstVideoInfo * info,
817 GstFormat src_format, gint64 src_value,
818 GstFormat dest_format, gint64 * dest_value)
820 gboolean ret = FALSE;
824 g_return_val_if_fail (info != NULL, 0);
825 g_return_val_if_fail (info->finfo != NULL, 0);
826 g_return_val_if_fail (info->finfo->format != GST_VIDEO_FORMAT_UNKNOWN, 0);
827 g_return_val_if_fail (info->size > 0, 0);
833 GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s to %s",
834 src_value, gst_format_get_name (src_format),
835 gst_format_get_name (dest_format));
837 if (src_format == dest_format) {
838 *dest_value = src_value;
843 if (src_value == -1) {
849 /* bytes to frames */
850 if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_DEFAULT) {
852 *dest_value = gst_util_uint64_scale (src_value, 1, size);
854 GST_ERROR ("blocksize is 0");
861 /* frames to bytes */
862 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_BYTES) {
863 *dest_value = gst_util_uint64_scale (src_value, size, 1);
869 if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_DEFAULT) {
871 *dest_value = gst_util_uint64_scale (src_value,
872 fps_n, GST_SECOND * fps_d);
874 GST_ERROR ("framerate denominator is 0");
882 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
884 *dest_value = gst_util_uint64_scale (src_value,
885 GST_SECOND * fps_d, fps_n);
887 GST_ERROR ("framerate numerator is 0");
895 if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) {
897 *dest_value = gst_util_uint64_scale (src_value,
898 fps_n * size, GST_SECOND * fps_d);
900 GST_ERROR ("framerate denominator is 0");
908 if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_TIME) {
909 if (fps_n != 0 && size != 0) {
910 *dest_value = gst_util_uint64_scale (src_value,
911 GST_SECOND * fps_d, fps_n * size);
913 GST_ERROR ("framerate denominator and/or blocksize is 0");
921 GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, ret, *dest_value);
927 * gst_video_info_align:
928 * @info: a #GstVideoInfo
929 * @align: alignment parameters
931 * Adjust the offset and stride fields in @info so that the padding and
932 * stride alignment in @align is respected.
934 * Extra padding will be added to the right side when stride alignment padding
935 * is required and @align will be updated with the new padding values.
938 gst_video_info_align (GstVideoInfo * info, GstVideoAlignment * align)
940 const GstVideoFormatInfo *vinfo = info->finfo;
942 gint padded_width, padded_height;
946 width = GST_VIDEO_INFO_WIDTH (info);
947 height = GST_VIDEO_INFO_HEIGHT (info);
949 GST_LOG ("padding %u-%ux%u-%u", align->padding_top,
950 align->padding_left, align->padding_right, align->padding_bottom);
952 n_planes = GST_VIDEO_INFO_N_PLANES (info);
954 if (GST_VIDEO_FORMAT_INFO_HAS_PALETTE (vinfo))
957 /* first make sure the left padding does not cause alignment problems later */
959 GST_LOG ("left padding %u", align->padding_left);
961 for (i = 0; i < n_planes; i++) {
964 /* this is the amout of pixels to add as left padding */
965 hedge = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (vinfo, i, align->padding_left);
966 hedge *= GST_VIDEO_FORMAT_INFO_PSTRIDE (vinfo, i);
968 GST_LOG ("plane %d, padding %d, alignment %u", i, hedge,
969 align->stride_align[i]);
970 aligned &= (hedge & align->stride_align[i]) == 0;
975 GST_LOG ("unaligned padding, increasing padding");
976 /* increase padded_width */
977 align->padding_left += align->padding_left & ~(align->padding_left - 1);
980 /* add the padding */
981 padded_width = width + align->padding_left + align->padding_right;
982 padded_height = height + align->padding_top + align->padding_bottom;
985 GST_LOG ("padded dimension %u-%u", padded_width, padded_height);
987 info->width = padded_width;
988 info->height = padded_height;
991 /* check alignment */
993 for (i = 0; i < n_planes; i++) {
994 GST_LOG ("plane %d, stride %d, alignment %u", i, info->stride[i],
995 align->stride_align[i]);
996 aligned &= (info->stride[i] & align->stride_align[i]) == 0;
1001 GST_LOG ("unaligned strides, increasing dimension");
1002 /* increase padded_width */
1003 padded_width += padded_width & ~(padded_width - 1);
1006 align->padding_right = padded_width - width - align->padding_left;
1008 info->width = width;
1009 info->height = height;
1011 for (i = 0; i < n_planes; i++) {
1012 gint vedge, hedge, comp;
1014 /* Find the component for this plane, FIXME, we assume the plane number and
1015 * component number is the same for now, for scaling the dimensions this is
1016 * currently true for all formats but it might not be when adding new
1017 * formats. We might need to add a plane subsamling in the format info to
1018 * make this more generic or maybe use a plane -> component mapping. */
1022 GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (vinfo, comp, align->padding_left);
1024 GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (vinfo, comp, align->padding_top);
1026 GST_DEBUG ("plane %d: comp: %d, hedge %d vedge %d align %d stride %d", i,
1027 comp, hedge, vedge, align->stride_align[i], info->stride[i]);
1029 info->offset[i] += (vedge * info->stride[i]) +
1030 (hedge * GST_VIDEO_FORMAT_INFO_PSTRIDE (vinfo, comp));