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 */
57 #define MAKE_COLORIMETRY(r,m,t,p) { \
58 GST_VIDEO_COLOR_RANGE ##r, GST_VIDEO_COLOR_MATRIX_ ##m, \
59 GST_VIDEO_TRANSFER_ ##t, GST_VIDEO_COLOR_PRIMARIES_ ##p }
61 #define DEFAULT_YUV_SD 0
62 #define DEFAULT_YUV_HD 1
64 #define DEFAULT_GRAY 3
65 #define DEFAULT_UNKNOWN 4
67 static const GstVideoColorimetry default_color[] = {
68 MAKE_COLORIMETRY (_16_235, BT601, BT709, BT470M),
69 MAKE_COLORIMETRY (_16_235, BT709, BT709, BT709),
70 MAKE_COLORIMETRY (_0_255, RGB, UNKNOWN, UNKNOWN),
71 MAKE_COLORIMETRY (_0_255, BT601, UNKNOWN, UNKNOWN),
72 MAKE_COLORIMETRY (_UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN),
76 * gst_video_info_set_format:
77 * @info: a #GstVideoInfo
82 * Set the default info for a video frame of @format and @width and @height.
84 * Note: This initializes @info first, no values are preserved.
87 gst_video_info_set_format (GstVideoInfo * info, GstVideoFormat format,
88 guint width, guint height)
90 const GstVideoFormatInfo *finfo;
92 g_return_if_fail (info != NULL);
93 g_return_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN);
95 gst_video_info_init (info);
97 finfo = gst_video_format_get_info (format);
102 info->height = height;
104 if (GST_VIDEO_FORMAT_INFO_IS_YUV (finfo)) {
106 info->chroma_site = GST_VIDEO_CHROMA_SITE_H_COSITED;
107 info->colorimetry = default_color[DEFAULT_YUV_HD];
109 info->chroma_site = GST_VIDEO_CHROMA_SITE_NONE;
110 info->colorimetry = default_color[DEFAULT_YUV_SD];
112 } else if (GST_VIDEO_FORMAT_INFO_IS_GRAY (finfo)) {
113 info->colorimetry = default_color[DEFAULT_GRAY];
114 } else if (GST_VIDEO_FORMAT_INFO_IS_RGB (finfo)) {
115 info->colorimetry = default_color[DEFAULT_RGB];
117 info->colorimetry = default_color[DEFAULT_UNKNOWN];
123 static const gchar *interlace_mode[] = {
131 gst_interlace_mode_to_string (GstVideoInterlaceMode mode)
133 if (((guint) mode) >= G_N_ELEMENTS (interlace_mode))
136 return interlace_mode[mode];
139 static GstVideoInterlaceMode
140 gst_interlace_mode_from_string (const gchar * mode)
143 for (i = 0; i < G_N_ELEMENTS (interlace_mode); i++) {
144 if (g_str_equal (interlace_mode[i], mode))
147 return GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
151 * gst_video_info_from_caps:
152 * @info: a #GstVideoInfo
155 * Parse @caps and update @info.
157 * Returns: TRUE if @caps could be parsed
160 gst_video_info_from_caps (GstVideoInfo * info, const GstCaps * caps)
162 GstStructure *structure;
164 GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
165 gint width = 0, height = 0, views;
169 g_return_val_if_fail (info != NULL, FALSE);
170 g_return_val_if_fail (caps != NULL, FALSE);
171 g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
173 GST_DEBUG ("parsing caps %" GST_PTR_FORMAT, caps);
175 structure = gst_caps_get_structure (caps, 0);
177 if (gst_structure_has_name (structure, "video/x-raw")) {
178 if (!(s = gst_structure_get_string (structure, "format")))
181 format = gst_video_format_from_string (s);
182 if (format == GST_VIDEO_FORMAT_UNKNOWN)
185 } else if (g_str_has_prefix (gst_structure_get_name (structure), "video/") ||
186 g_str_has_prefix (gst_structure_get_name (structure), "image/")) {
187 format = GST_VIDEO_FORMAT_ENCODED;
192 /* width and height are mandatory, except for non-raw-formats */
193 if (!gst_structure_get_int (structure, "width", &width) &&
194 format != GST_VIDEO_FORMAT_ENCODED)
196 if (!gst_structure_get_int (structure, "height", &height) &&
197 format != GST_VIDEO_FORMAT_ENCODED)
200 gst_video_info_set_format (info, format, width, height);
202 if (gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d)) {
204 /* variable framerate */
205 info->flags |= GST_VIDEO_FLAG_VARIABLE_FPS;
206 /* see if we have a max-framerate */
207 gst_structure_get_fraction (structure, "max-framerate", &fps_n, &fps_d);
212 /* unspecified is variable framerate */
217 if ((s = gst_structure_get_string (structure, "interlace-mode")))
218 info->interlace_mode = gst_interlace_mode_from_string (s);
220 info->interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
222 if (gst_structure_get_int (structure, "views", &views))
227 if ((s = gst_structure_get_string (structure, "chroma-site")))
228 info->chroma_site = gst_video_chroma_from_string (s);
230 info->chroma_site = GST_VIDEO_CHROMA_SITE_UNKNOWN;
232 if ((s = gst_structure_get_string (structure, "colorimetry")))
233 gst_video_colorimetry_from_string (&info->colorimetry, s);
235 if (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
248 GST_ERROR ("wrong name '%s', expected video/ or image/",
249 gst_structure_get_name (structure));
254 GST_ERROR ("no format given");
259 GST_ERROR ("unknown format '%s' given", s);
264 GST_ERROR ("no width property given");
269 GST_ERROR ("no height property given");
275 * gst_video_info_is_equal:
276 * @info: a #GstVideoInfo
277 * @other: a #GstVideoInfo
279 * Compares two #GstVideoInfo and returns whether they are equal or not
281 * Returns: %TRUE if @info and @other are equal, else %FALSE.
284 gst_video_info_is_equal (const GstVideoInfo * info, const GstVideoInfo * other)
288 if (GST_VIDEO_INFO_FORMAT (info) != GST_VIDEO_INFO_FORMAT (other))
290 if (GST_VIDEO_INFO_INTERLACE_MODE (info) !=
291 GST_VIDEO_INFO_INTERLACE_MODE (other))
293 if (GST_VIDEO_INFO_FLAGS (info) != GST_VIDEO_INFO_FLAGS (other))
295 if (GST_VIDEO_INFO_WIDTH (info) != GST_VIDEO_INFO_WIDTH (other))
297 if (GST_VIDEO_INFO_HEIGHT (info) != GST_VIDEO_INFO_HEIGHT (other))
299 if (GST_VIDEO_INFO_SIZE (info) != GST_VIDEO_INFO_SIZE (other))
301 if (GST_VIDEO_INFO_PAR_N (info) != GST_VIDEO_INFO_PAR_N (other))
303 if (GST_VIDEO_INFO_PAR_D (info) != GST_VIDEO_INFO_PAR_D (other))
305 if (GST_VIDEO_INFO_FPS_N (info) != GST_VIDEO_INFO_FPS_N (other))
307 if (GST_VIDEO_INFO_FPS_D (info) != GST_VIDEO_INFO_FPS_D (other))
310 for (i = 0; i < info->finfo->n_planes; i++) {
311 if (info->stride[i] != other->stride[i])
313 if (info->offset[i] != other->offset[i])
321 * gst_video_info_to_caps:
322 * @info: a #GstVideoInfo
324 * Convert the values of @info into a #GstCaps.
326 * Returns: a new #GstCaps containing the info of @info.
329 gst_video_info_to_caps (GstVideoInfo * info)
335 g_return_val_if_fail (info != NULL, NULL);
336 g_return_val_if_fail (info->finfo != NULL, NULL);
337 g_return_val_if_fail (info->finfo->format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
339 format = gst_video_format_to_string (info->finfo->format);
340 g_return_val_if_fail (format != NULL, NULL);
342 caps = gst_caps_new_simple ("video/x-raw",
343 "format", G_TYPE_STRING, format,
344 "width", G_TYPE_INT, info->width,
345 "height", G_TYPE_INT, info->height,
346 "pixel-aspect-ratio", GST_TYPE_FRACTION, info->par_n, info->par_d, NULL);
348 gst_caps_set_simple (caps, "interlace-mode", G_TYPE_STRING,
349 gst_interlace_mode_to_string (info->interlace_mode), NULL);
351 if (info->chroma_site != GST_VIDEO_CHROMA_SITE_UNKNOWN)
352 gst_caps_set_simple (caps, "chroma-site", G_TYPE_STRING,
353 gst_video_chroma_to_string (info->chroma_site), NULL);
355 if ((color = gst_video_colorimetry_to_string (&info->colorimetry))) {
356 gst_caps_set_simple (caps, "colorimetry", G_TYPE_STRING, color, NULL);
361 gst_caps_set_simple (caps, "views", G_TYPE_INT, info->views, NULL);
363 if (info->flags & GST_VIDEO_FLAG_VARIABLE_FPS && info->fps_n != 0) {
364 /* variable fps with a max-framerate */
365 gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, 0, 1,
366 "max-framerate", GST_TYPE_FRACTION, info->fps_n, info->fps_d, NULL);
368 /* no variable fps or no max-framerate */
369 gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION,
370 info->fps_n, info->fps_d, NULL);
377 fill_planes (GstVideoInfo * info)
381 width = (gsize) info->width;
382 height = (gsize) info->height;
384 switch (info->finfo->format) {
385 case GST_VIDEO_FORMAT_YUY2:
386 case GST_VIDEO_FORMAT_YVYU:
387 case GST_VIDEO_FORMAT_UYVY:
388 info->stride[0] = GST_ROUND_UP_4 (width * 2);
390 info->size = info->stride[0] * height;
392 case GST_VIDEO_FORMAT_AYUV:
393 case GST_VIDEO_FORMAT_RGBx:
394 case GST_VIDEO_FORMAT_RGBA:
395 case GST_VIDEO_FORMAT_BGRx:
396 case GST_VIDEO_FORMAT_BGRA:
397 case GST_VIDEO_FORMAT_xRGB:
398 case GST_VIDEO_FORMAT_ARGB:
399 case GST_VIDEO_FORMAT_xBGR:
400 case GST_VIDEO_FORMAT_ABGR:
401 case GST_VIDEO_FORMAT_r210:
402 info->stride[0] = width * 4;
404 info->size = info->stride[0] * height;
406 case GST_VIDEO_FORMAT_RGB16:
407 case GST_VIDEO_FORMAT_BGR16:
408 case GST_VIDEO_FORMAT_RGB15:
409 case GST_VIDEO_FORMAT_BGR15:
410 info->stride[0] = GST_ROUND_UP_4 (width * 2);
412 info->size = info->stride[0] * height;
414 case GST_VIDEO_FORMAT_RGB:
415 case GST_VIDEO_FORMAT_BGR:
416 case GST_VIDEO_FORMAT_v308:
417 info->stride[0] = GST_ROUND_UP_4 (width * 3);
419 info->size = info->stride[0] * height;
421 case GST_VIDEO_FORMAT_v210:
422 info->stride[0] = ((width + 47) / 48) * 128;
424 info->size = info->stride[0] * height;
426 case GST_VIDEO_FORMAT_v216:
427 info->stride[0] = GST_ROUND_UP_8 (width * 4);
429 info->size = info->stride[0] * height;
431 case GST_VIDEO_FORMAT_GRAY8:
432 info->stride[0] = GST_ROUND_UP_4 (width);
434 info->size = info->stride[0] * height;
436 case GST_VIDEO_FORMAT_GRAY16_BE:
437 case GST_VIDEO_FORMAT_GRAY16_LE:
438 info->stride[0] = GST_ROUND_UP_4 (width * 2);
440 info->size = info->stride[0] * height;
442 case GST_VIDEO_FORMAT_UYVP:
443 info->stride[0] = GST_ROUND_UP_4 ((width * 2 * 5 + 3) / 4);
445 info->size = info->stride[0] * height;
447 case GST_VIDEO_FORMAT_RGB8P:
448 info->stride[0] = GST_ROUND_UP_4 (width);
451 info->offset[1] = info->stride[0] * height;
452 info->size = info->offset[1] + (4 * 256);
454 case GST_VIDEO_FORMAT_IYU1:
455 info->stride[0] = GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) +
456 GST_ROUND_UP_4 (width) / 2);
458 info->size = info->stride[0] * height;
460 case GST_VIDEO_FORMAT_ARGB64:
461 case GST_VIDEO_FORMAT_AYUV64:
462 info->stride[0] = width * 8;
464 info->size = info->stride[0] * height;
466 case GST_VIDEO_FORMAT_I420:
467 case GST_VIDEO_FORMAT_YV12: /* same as I420, but plane 1+2 swapped */
468 info->stride[0] = GST_ROUND_UP_4 (width);
469 info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
470 info->stride[2] = info->stride[1];
472 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
473 info->offset[2] = info->offset[1] +
474 info->stride[1] * (GST_ROUND_UP_2 (height) / 2);
475 info->size = info->offset[2] +
476 info->stride[2] * (GST_ROUND_UP_2 (height) / 2);
478 case GST_VIDEO_FORMAT_Y41B:
479 info->stride[0] = GST_ROUND_UP_4 (width);
480 info->stride[1] = GST_ROUND_UP_16 (width) / 4;
481 info->stride[2] = info->stride[1];
483 info->offset[1] = info->stride[0] * height;
484 info->offset[2] = info->offset[1] + info->stride[1] * height;
485 /* simplification of ROUNDUP4(w)*h + 2*((ROUNDUP16(w)/4)*h */
486 info->size = (info->stride[0] + (GST_ROUND_UP_16 (width) / 2)) * height;
488 case GST_VIDEO_FORMAT_Y42B:
489 info->stride[0] = GST_ROUND_UP_4 (width);
490 info->stride[1] = GST_ROUND_UP_8 (width) / 2;
491 info->stride[2] = info->stride[1];
493 info->offset[1] = info->stride[0] * height;
494 info->offset[2] = info->offset[1] + info->stride[1] * height;
495 /* simplification of ROUNDUP4(w)*h + 2*(ROUNDUP8(w)/2)*h */
496 info->size = (info->stride[0] + GST_ROUND_UP_8 (width)) * height;
498 case GST_VIDEO_FORMAT_Y444:
499 case GST_VIDEO_FORMAT_GBR:
500 info->stride[0] = GST_ROUND_UP_4 (width);
501 info->stride[1] = info->stride[0];
502 info->stride[2] = info->stride[0];
504 info->offset[1] = info->stride[0] * height;
505 info->offset[2] = info->offset[1] * 2;
506 info->size = info->stride[0] * height * 3;
508 case GST_VIDEO_FORMAT_NV12:
509 case GST_VIDEO_FORMAT_NV21:
510 info->stride[0] = GST_ROUND_UP_4 (width);
511 info->stride[1] = info->stride[0];
513 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
514 info->size = info->stride[0] * GST_ROUND_UP_2 (height) * 3 / 2;
516 case GST_VIDEO_FORMAT_NV16:
517 info->stride[0] = GST_ROUND_UP_4 (width);
518 info->stride[1] = info->stride[0];
520 info->offset[1] = info->stride[0] * height;
521 info->size = info->stride[0] * height * 2;
523 case GST_VIDEO_FORMAT_NV24:
524 info->stride[0] = GST_ROUND_UP_4 (width);
525 info->stride[1] = GST_ROUND_UP_4 (width * 2);
527 info->offset[1] = info->stride[0] * height;
528 info->size = info->stride[0] * height + info->stride[1] * height;
530 case GST_VIDEO_FORMAT_A420:
531 info->stride[0] = GST_ROUND_UP_4 (width);
532 info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
533 info->stride[2] = info->stride[1];
534 info->stride[3] = info->stride[0];
536 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
537 info->offset[2] = info->offset[1] +
538 info->stride[1] * (GST_ROUND_UP_2 (height) / 2);
539 info->offset[3] = info->offset[2] +
540 info->stride[2] * (GST_ROUND_UP_2 (height) / 2);
541 info->size = info->offset[3] + info->stride[0] * GST_ROUND_UP_2 (height);
543 case GST_VIDEO_FORMAT_YUV9:
544 case GST_VIDEO_FORMAT_YVU9:
545 info->stride[0] = GST_ROUND_UP_4 (width);
546 info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4);
547 info->stride[2] = info->stride[1];
549 info->offset[1] = info->stride[0] * height;
550 info->offset[2] = info->offset[1] +
551 info->stride[1] * (GST_ROUND_UP_4 (height) / 4);
552 info->size = info->offset[2] +
553 info->stride[2] * (GST_ROUND_UP_4 (height) / 4);
555 case GST_VIDEO_FORMAT_I420_10LE:
556 case GST_VIDEO_FORMAT_I420_10BE:
557 info->stride[0] = GST_ROUND_UP_4 (width * 2);
558 info->stride[1] = GST_ROUND_UP_4 (width);
559 info->stride[2] = info->stride[1];
561 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
562 info->offset[2] = info->offset[1] +
563 info->stride[1] * (GST_ROUND_UP_2 (height) / 2);
564 info->size = info->offset[2] +
565 info->stride[2] * (GST_ROUND_UP_2 (height) / 2);
567 case GST_VIDEO_FORMAT_I422_10LE:
568 case GST_VIDEO_FORMAT_I422_10BE:
569 info->stride[0] = GST_ROUND_UP_4 (width * 2);
570 info->stride[1] = GST_ROUND_UP_4 (width);
571 info->stride[2] = info->stride[1];
573 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
574 info->offset[2] = info->offset[1] +
575 info->stride[1] * GST_ROUND_UP_2 (height);
576 info->size = info->offset[2] + info->stride[2] * GST_ROUND_UP_2 (height);
578 case GST_VIDEO_FORMAT_Y444_10LE:
579 case GST_VIDEO_FORMAT_Y444_10BE:
580 case GST_VIDEO_FORMAT_GBR_10LE:
581 case GST_VIDEO_FORMAT_GBR_10BE:
582 info->stride[0] = GST_ROUND_UP_4 (width * 2);
583 info->stride[1] = info->stride[0];
584 info->stride[2] = info->stride[0];
586 info->offset[1] = info->stride[0] * height;
587 info->offset[2] = info->offset[1] * 2;
588 info->size = info->stride[0] * height * 3;
590 case GST_VIDEO_FORMAT_NV12_64Z32:
592 GST_VIDEO_TILE_MAKE_STRIDE (GST_ROUND_UP_128 (width) / 64,
593 GST_ROUND_UP_32 (height) / 32);
595 GST_VIDEO_TILE_MAKE_STRIDE (GST_ROUND_UP_128 (width) / 64,
596 GST_ROUND_UP_64 (height) / 64);
598 info->offset[1] = GST_ROUND_UP_128 (width) * GST_ROUND_UP_32 (height);
599 info->size = info->offset[1] +
600 GST_ROUND_UP_128 (width) * GST_ROUND_UP_64 (height) / 2;
602 case GST_VIDEO_FORMAT_ENCODED:
604 case GST_VIDEO_FORMAT_UNKNOWN:
605 GST_ERROR ("invalid format");
606 g_warning ("invalid format");
613 * gst_video_info_convert:
614 * @info: a #GstVideoInfo
615 * @src_format: #GstFormat of the @src_value
616 * @src_value: value to convert
617 * @dest_format: #GstFormat of the @dest_value
618 * @dest_value: pointer to destination value
620 * Converts among various #GstFormat types. This function handles
621 * GST_FORMAT_BYTES, GST_FORMAT_TIME, and GST_FORMAT_DEFAULT. For
622 * raw video, GST_FORMAT_DEFAULT corresponds to video frames. This
623 * function can be used to handle pad queries of the type GST_QUERY_CONVERT.
625 * Returns: TRUE if the conversion was successful.
628 gst_video_info_convert (GstVideoInfo * info,
629 GstFormat src_format, gint64 src_value,
630 GstFormat dest_format, gint64 * dest_value)
632 gboolean ret = FALSE;
636 g_return_val_if_fail (info != NULL, 0);
637 g_return_val_if_fail (info->finfo != NULL, 0);
638 g_return_val_if_fail (info->finfo->format != GST_VIDEO_FORMAT_UNKNOWN, 0);
639 g_return_val_if_fail (info->size > 0, 0);
645 GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s to %s",
646 src_value, gst_format_get_name (src_format),
647 gst_format_get_name (dest_format));
649 if (src_format == dest_format) {
650 *dest_value = src_value;
655 if (src_value == -1) {
661 /* bytes to frames */
662 if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_DEFAULT) {
664 *dest_value = gst_util_uint64_scale (src_value, 1, size);
666 GST_ERROR ("blocksize is 0");
673 /* frames to bytes */
674 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_BYTES) {
675 *dest_value = gst_util_uint64_scale (src_value, size, 1);
681 if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_DEFAULT) {
683 *dest_value = gst_util_uint64_scale (src_value,
684 fps_n, GST_SECOND * fps_d);
686 GST_ERROR ("framerate denominator is 0");
694 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
696 *dest_value = gst_util_uint64_scale (src_value,
697 GST_SECOND * fps_d, fps_n);
699 GST_ERROR ("framerate numerator is 0");
707 if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) {
709 *dest_value = gst_util_uint64_scale (src_value,
710 fps_n * size, GST_SECOND * fps_d);
712 GST_ERROR ("framerate denominator is 0");
720 if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_TIME) {
721 if (fps_n != 0 && size != 0) {
722 *dest_value = gst_util_uint64_scale (src_value,
723 GST_SECOND * fps_d, fps_n * size);
725 GST_ERROR ("framerate denominator and/or blocksize is 0");
733 GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, ret, *dest_value);
739 * gst_video_info_align:
740 * @info: a #GstVideoInfo
741 * @align: alignment parameters
743 * Adjust the offset and stride fields in @info so that the padding and
744 * stride alignment in @align is respected.
746 * Extra padding will be added to the right side when stride alignment padding
747 * is required and @align will be updated with the new padding values.
750 gst_video_info_align (GstVideoInfo * info, GstVideoAlignment * align)
752 const GstVideoFormatInfo *vinfo = info->finfo;
754 gint padded_width, padded_height;
758 width = GST_VIDEO_INFO_WIDTH (info);
759 height = GST_VIDEO_INFO_HEIGHT (info);
761 GST_LOG ("padding %u-%ux%u-%u", align->padding_top,
762 align->padding_left, align->padding_right, align->padding_bottom);
764 n_planes = GST_VIDEO_INFO_N_PLANES (info);
766 if (GST_VIDEO_FORMAT_INFO_HAS_PALETTE (vinfo))
769 /* first make sure the left padding does not cause alignment problems later */
771 GST_LOG ("left padding %u", align->padding_left);
773 for (i = 0; i < n_planes; i++) {
776 /* this is the amout of pixels to add as left padding */
777 hedge = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (vinfo, i, align->padding_left);
778 hedge *= GST_VIDEO_FORMAT_INFO_PSTRIDE (vinfo, i);
780 GST_LOG ("plane %d, padding %d, alignment %u", i, hedge,
781 align->stride_align[i]);
782 aligned &= (hedge & align->stride_align[i]) == 0;
787 GST_LOG ("unaligned padding, increasing padding");
788 /* increase padded_width */
789 align->padding_left += align->padding_left & ~(align->padding_left - 1);
792 /* add the padding */
793 padded_width = width + align->padding_left + align->padding_right;
794 padded_height = height + align->padding_top + align->padding_bottom;
797 GST_LOG ("padded dimension %u-%u", padded_width, padded_height);
799 info->width = padded_width;
800 info->height = padded_height;
803 /* check alignment */
805 for (i = 0; i < n_planes; i++) {
806 GST_LOG ("plane %d, stride %d, alignment %u", i, info->stride[i],
807 align->stride_align[i]);
808 aligned &= (info->stride[i] & align->stride_align[i]) == 0;
813 GST_LOG ("unaligned strides, increasing dimension");
814 /* increase padded_width */
815 padded_width += padded_width & ~(padded_width - 1);
818 align->padding_right = padded_width - width - align->padding_left;
821 info->height = height;
823 for (i = 0; i < n_planes; i++) {
824 gint vedge, hedge, comp;
826 /* Find the component for this plane, FIXME, we assume the plane number and
827 * component number is the same for now, for scaling the dimensions this is
828 * currently true for all formats but it might not be when adding new
829 * formats. We might need to add a plane subsamling in the format info to
830 * make this more generic or maybe use a plane -> component mapping. */
834 GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (vinfo, comp, align->padding_left);
836 GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (vinfo, comp, align->padding_top);
838 GST_DEBUG ("plane %d: comp: %d, hedge %d vedge %d align %d stride %d", i,
839 comp, hedge, vedge, align->stride_align[i], info->stride[i]);
841 info->offset[i] += (vedge * info->stride[i]) +
842 (hedge * GST_VIDEO_FORMAT_INFO_PSTRIDE (vinfo, comp));