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., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
29 #include "video-info.h"
31 static int fill_planes (GstVideoInfo * info);
34 * gst_video_info_init:
35 * @info: a #GstVideoInfo
37 * Initialize @info with default values.
40 gst_video_info_init (GstVideoInfo * info)
42 g_return_if_fail (info != NULL);
44 memset (info, 0, sizeof (GstVideoInfo));
46 info->finfo = gst_video_format_get_info (GST_VIDEO_FORMAT_UNKNOWN);
49 /* arrange for sensible defaults, e.g. if turned into caps */
56 #define MAKE_COLORIMETRY(r,m,t,p) { \
57 GST_VIDEO_COLOR_RANGE ##r, GST_VIDEO_COLOR_MATRIX_ ##m, \
58 GST_VIDEO_TRANSFER_ ##t, GST_VIDEO_COLOR_PRIMARIES_ ##p }
60 #define DEFAULT_YUV_SD 0
61 #define DEFAULT_YUV_HD 1
63 #define DEFAULT_GRAY 3
64 #define DEFAULT_UNKNOWN 4
66 static const GstVideoColorimetry default_color[] = {
67 MAKE_COLORIMETRY (_16_235, BT601, BT709, BT470M),
68 MAKE_COLORIMETRY (_16_235, BT709, BT709, BT709),
69 MAKE_COLORIMETRY (_0_255, RGB, UNKNOWN, UNKNOWN),
70 MAKE_COLORIMETRY (_0_255, BT601, UNKNOWN, UNKNOWN),
71 MAKE_COLORIMETRY (_UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN),
75 * gst_video_info_set_format:
76 * @info: a #GstVideoInfo
81 * Set the default info for a video frame of @format and @width and @height.
84 gst_video_info_set_format (GstVideoInfo * info, GstVideoFormat format,
85 guint width, guint height)
87 const GstVideoFormatInfo *finfo;
89 g_return_if_fail (info != NULL);
90 g_return_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN);
92 finfo = gst_video_format_get_info (format);
97 info->height = height;
99 if (GST_VIDEO_FORMAT_INFO_IS_YUV (finfo)) {
101 info->colorimetry = default_color[DEFAULT_YUV_HD];
103 info->colorimetry = default_color[DEFAULT_YUV_SD];
104 } else if (GST_VIDEO_FORMAT_INFO_IS_GRAY (finfo)) {
105 info->colorimetry = default_color[DEFAULT_GRAY];
106 } else if (GST_VIDEO_FORMAT_INFO_IS_RGB (finfo)) {
107 info->colorimetry = default_color[DEFAULT_RGB];
109 info->colorimetry = default_color[DEFAULT_UNKNOWN];
115 static const gchar *interlace_mode[] = {
123 gst_interlace_mode_to_string (GstVideoInterlaceMode mode)
125 if (((guint) mode) >= G_N_ELEMENTS (interlace_mode))
128 return interlace_mode[mode];
131 static GstVideoInterlaceMode
132 gst_interlace_mode_from_string (const gchar * mode)
135 for (i = 0; i < G_N_ELEMENTS (interlace_mode); i++) {
136 if (g_str_equal (interlace_mode[i], mode))
139 return GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
143 * gst_video_info_from_caps:
144 * @info: a #GstVideoInfo
147 * Parse @caps and update @info.
149 * Returns: TRUE if @caps could be parsed
152 gst_video_info_from_caps (GstVideoInfo * info, const GstCaps * caps)
154 GstStructure *structure;
156 GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
157 gint width = 0, height = 0, views;
161 g_return_val_if_fail (info != NULL, FALSE);
162 g_return_val_if_fail (caps != NULL, FALSE);
163 g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
165 GST_DEBUG ("parsing caps %" GST_PTR_FORMAT, caps);
167 structure = gst_caps_get_structure (caps, 0);
169 if (gst_structure_has_name (structure, "video/x-raw")) {
170 if (!(s = gst_structure_get_string (structure, "format")))
173 format = gst_video_format_from_string (s);
174 if (format == GST_VIDEO_FORMAT_UNKNOWN)
177 } else if (g_str_has_prefix (gst_structure_get_name (structure), "video/") ||
178 g_str_has_prefix (gst_structure_get_name (structure), "image/")) {
179 format = GST_VIDEO_FORMAT_ENCODED;
184 /* width and height are mandatory, except for non-raw-formats */
185 if (!gst_structure_get_int (structure, "width", &width) &&
186 format != GST_VIDEO_FORMAT_ENCODED)
188 if (!gst_structure_get_int (structure, "height", &height) &&
189 format != GST_VIDEO_FORMAT_ENCODED)
192 gst_video_info_set_format (info, format, width, height);
194 if (gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d)) {
196 /* variable framerate */
197 info->flags |= GST_VIDEO_FLAG_VARIABLE_FPS;
198 /* see if we have a max-framerate */
199 gst_structure_get_fraction (structure, "max-framerate", &fps_n, &fps_d);
204 /* unspecified is variable framerate */
209 if ((s = gst_structure_get_string (structure, "interlace-mode")))
210 info->interlace_mode = gst_interlace_mode_from_string (s);
212 info->interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
214 if (gst_structure_get_int (structure, "views", &views))
219 if ((s = gst_structure_get_string (structure, "chroma-site")))
220 info->chroma_site = gst_video_chroma_from_string (s);
222 info->chroma_site = GST_VIDEO_CHROMA_SITE_UNKNOWN;
224 if ((s = gst_structure_get_string (structure, "colorimetry")))
225 gst_video_colorimetry_from_string (&info->colorimetry, s);
227 if (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
240 GST_ERROR ("wrong name '%s', expected video/ or image/",
241 gst_structure_get_name (structure));
246 GST_ERROR ("no format given");
251 GST_ERROR ("unknown format '%s' given", s);
256 GST_ERROR ("no width property given");
261 GST_ERROR ("no height property given");
267 * gst_video_info_is_equal:
268 * @info: a #GstVideoInfo
269 * @other: a #GstVideoInfo
271 * Compares two #GstVideoInfo and returns whether they are equal or not
273 * Returns: %TRUE if @info and @other are equal, else %FALSE.
276 gst_video_info_is_equal (const GstVideoInfo * info, const GstVideoInfo * other)
278 if (GST_VIDEO_INFO_FORMAT (info) != GST_VIDEO_INFO_FORMAT (other))
280 if (GST_VIDEO_INFO_INTERLACE_MODE (info) !=
281 GST_VIDEO_INFO_INTERLACE_MODE (other))
283 if (GST_VIDEO_INFO_FLAGS (info) != GST_VIDEO_INFO_FLAGS (other))
285 if (GST_VIDEO_INFO_WIDTH (info) != GST_VIDEO_INFO_WIDTH (other))
287 if (GST_VIDEO_INFO_HEIGHT (info) != GST_VIDEO_INFO_HEIGHT (other))
289 if (GST_VIDEO_INFO_SIZE (info) != GST_VIDEO_INFO_SIZE (other))
291 if (GST_VIDEO_INFO_PAR_N (info) != GST_VIDEO_INFO_PAR_N (other))
293 if (GST_VIDEO_INFO_PAR_D (info) != GST_VIDEO_INFO_PAR_D (other))
295 if (GST_VIDEO_INFO_FPS_N (info) != GST_VIDEO_INFO_FPS_N (other))
297 if (GST_VIDEO_INFO_FPS_D (info) != GST_VIDEO_INFO_FPS_D (other))
303 * gst_video_info_to_caps:
304 * @info: a #GstVideoInfo
306 * Convert the values of @info into a #GstCaps.
308 * Returns: a new #GstCaps containing the info of @info.
311 gst_video_info_to_caps (GstVideoInfo * info)
317 g_return_val_if_fail (info != NULL, NULL);
318 g_return_val_if_fail (info->finfo != NULL, NULL);
319 g_return_val_if_fail (info->finfo->format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
321 format = gst_video_format_to_string (info->finfo->format);
322 g_return_val_if_fail (format != NULL, NULL);
324 caps = gst_caps_new_simple ("video/x-raw",
325 "format", G_TYPE_STRING, format,
326 "width", G_TYPE_INT, info->width,
327 "height", G_TYPE_INT, info->height,
328 "pixel-aspect-ratio", GST_TYPE_FRACTION, info->par_n, info->par_d, NULL);
330 gst_caps_set_simple (caps, "interlace-mode", G_TYPE_STRING,
331 gst_interlace_mode_to_string (info->interlace_mode), NULL);
333 if (info->chroma_site != GST_VIDEO_CHROMA_SITE_UNKNOWN)
334 gst_caps_set_simple (caps, "chroma-site", G_TYPE_STRING,
335 gst_video_chroma_to_string (info->chroma_site), NULL);
337 if ((color = gst_video_colorimetry_to_string (&info->colorimetry))) {
338 gst_caps_set_simple (caps, "colorimetry", G_TYPE_STRING, color, NULL);
343 gst_caps_set_simple (caps, "views", G_TYPE_INT, info->views, NULL);
345 if (info->flags & GST_VIDEO_FLAG_VARIABLE_FPS && info->fps_n != 0) {
346 /* variable fps with a max-framerate */
347 gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, 0, 1,
348 "max-framerate", GST_TYPE_FRACTION, info->fps_n, info->fps_d, NULL);
350 /* no variable fps or no max-framerate */
351 gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION,
352 info->fps_n, info->fps_d, NULL);
359 fill_planes (GstVideoInfo * info)
364 height = info->height;
366 switch (info->finfo->format) {
367 case GST_VIDEO_FORMAT_YUY2:
368 case GST_VIDEO_FORMAT_YVYU:
369 case GST_VIDEO_FORMAT_UYVY:
370 info->stride[0] = GST_ROUND_UP_4 (width * 2);
372 info->size = info->stride[0] * height;
374 case GST_VIDEO_FORMAT_AYUV:
375 case GST_VIDEO_FORMAT_RGBx:
376 case GST_VIDEO_FORMAT_RGBA:
377 case GST_VIDEO_FORMAT_BGRx:
378 case GST_VIDEO_FORMAT_BGRA:
379 case GST_VIDEO_FORMAT_xRGB:
380 case GST_VIDEO_FORMAT_ARGB:
381 case GST_VIDEO_FORMAT_xBGR:
382 case GST_VIDEO_FORMAT_ABGR:
383 case GST_VIDEO_FORMAT_r210:
384 info->stride[0] = width * 4;
386 info->size = info->stride[0] * height;
388 case GST_VIDEO_FORMAT_RGB16:
389 case GST_VIDEO_FORMAT_BGR16:
390 case GST_VIDEO_FORMAT_RGB15:
391 case GST_VIDEO_FORMAT_BGR15:
392 info->stride[0] = GST_ROUND_UP_4 (width * 2);
394 info->size = info->stride[0] * height;
396 case GST_VIDEO_FORMAT_RGB:
397 case GST_VIDEO_FORMAT_BGR:
398 case GST_VIDEO_FORMAT_v308:
399 info->stride[0] = GST_ROUND_UP_4 (width * 3);
401 info->size = info->stride[0] * height;
403 case GST_VIDEO_FORMAT_v210:
404 info->stride[0] = ((width + 47) / 48) * 128;
406 info->size = info->stride[0] * height;
408 case GST_VIDEO_FORMAT_v216:
409 info->stride[0] = GST_ROUND_UP_8 (width * 4);
411 info->size = info->stride[0] * height;
413 case GST_VIDEO_FORMAT_GRAY8:
414 info->stride[0] = GST_ROUND_UP_4 (width);
416 info->size = info->stride[0] * height;
418 case GST_VIDEO_FORMAT_GRAY16_BE:
419 case GST_VIDEO_FORMAT_GRAY16_LE:
420 info->stride[0] = GST_ROUND_UP_4 (width * 2);
422 info->size = info->stride[0] * height;
424 case GST_VIDEO_FORMAT_UYVP:
425 info->stride[0] = GST_ROUND_UP_4 ((width * 2 * 5 + 3) / 4);
427 info->size = info->stride[0] * height;
429 case GST_VIDEO_FORMAT_RGB8P:
430 info->stride[0] = GST_ROUND_UP_4 (width);
433 info->offset[1] = info->stride[0] * height;
434 info->size = info->offset[1] + (4 * 256);
436 case GST_VIDEO_FORMAT_IYU1:
437 info->stride[0] = GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) +
438 GST_ROUND_UP_4 (width) / 2);
440 info->size = info->stride[0] * height;
442 case GST_VIDEO_FORMAT_ARGB64:
443 case GST_VIDEO_FORMAT_AYUV64:
444 info->stride[0] = width * 8;
446 info->size = info->stride[0] * height;
448 case GST_VIDEO_FORMAT_I420:
449 case GST_VIDEO_FORMAT_YV12: /* same as I420, but plane 1+2 swapped */
450 info->stride[0] = GST_ROUND_UP_4 (width);
451 info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
452 info->stride[2] = info->stride[1];
454 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
455 info->offset[2] = info->offset[1] +
456 info->stride[1] * (GST_ROUND_UP_2 (height) / 2);
457 info->size = info->offset[2] +
458 info->stride[2] * (GST_ROUND_UP_2 (height) / 2);
460 case GST_VIDEO_FORMAT_Y41B:
461 info->stride[0] = GST_ROUND_UP_4 (width);
462 info->stride[1] = GST_ROUND_UP_16 (width) / 4;
463 info->stride[2] = info->stride[1];
465 info->offset[1] = info->stride[0] * height;
466 info->offset[2] = info->offset[1] + info->stride[1] * height;
467 /* simplification of ROUNDUP4(w)*h + 2*((ROUNDUP16(w)/4)*h */
468 info->size = (info->stride[0] + (GST_ROUND_UP_16 (width) / 2)) * height;
470 case GST_VIDEO_FORMAT_Y42B:
471 info->stride[0] = GST_ROUND_UP_4 (width);
472 info->stride[1] = GST_ROUND_UP_8 (width) / 2;
473 info->stride[2] = info->stride[1];
475 info->offset[1] = info->stride[0] * height;
476 info->offset[2] = info->offset[1] + info->stride[1] * height;
477 /* simplification of ROUNDUP4(w)*h + 2*(ROUNDUP8(w)/2)*h */
478 info->size = (info->stride[0] + GST_ROUND_UP_8 (width)) * height;
480 case GST_VIDEO_FORMAT_Y444:
481 info->stride[0] = GST_ROUND_UP_4 (width);
482 info->stride[1] = info->stride[0];
483 info->stride[2] = info->stride[0];
485 info->offset[1] = info->stride[0] * height;
486 info->offset[2] = info->offset[1] * 2;
487 info->size = info->stride[0] * height * 3;
489 case GST_VIDEO_FORMAT_NV12:
490 case GST_VIDEO_FORMAT_NV21:
491 info->stride[0] = GST_ROUND_UP_4 (width);
492 info->stride[1] = info->stride[0];
494 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
495 info->size = info->stride[0] * GST_ROUND_UP_2 (height) * 3 / 2;
497 case GST_VIDEO_FORMAT_A420:
498 info->stride[0] = GST_ROUND_UP_4 (width);
499 info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
500 info->stride[2] = info->stride[1];
501 info->stride[3] = info->stride[0];
503 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
504 info->offset[2] = info->offset[1] +
505 info->stride[1] * (GST_ROUND_UP_2 (height) / 2);
506 info->offset[3] = info->offset[2] +
507 info->stride[2] * (GST_ROUND_UP_2 (height) / 2);
508 info->size = info->offset[3] + info->stride[0];
510 case GST_VIDEO_FORMAT_YUV9:
511 case GST_VIDEO_FORMAT_YVU9:
512 info->stride[0] = GST_ROUND_UP_4 (width);
513 info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4);
514 info->stride[2] = info->stride[1];
516 info->offset[1] = info->stride[0] * height;
517 info->offset[2] = info->offset[1] +
518 info->stride[1] * (GST_ROUND_UP_4 (height) / 4);
519 info->size = info->offset[2] +
520 info->stride[2] * (GST_ROUND_UP_4 (height) / 4);
522 case GST_VIDEO_FORMAT_I420_10LE:
523 case GST_VIDEO_FORMAT_I420_10BE:
524 info->stride[0] = GST_ROUND_UP_4 (width * 2);
525 info->stride[1] = GST_ROUND_UP_4 (width);
526 info->stride[2] = info->stride[1];
528 info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
529 info->offset[2] = info->offset[1] +
530 info->stride[1] * (GST_ROUND_UP_2 (height) / 2);
531 info->size = info->offset[2] +
532 info->stride[2] * (GST_ROUND_UP_2 (height) / 2);
534 case GST_VIDEO_FORMAT_ENCODED:
536 case GST_VIDEO_FORMAT_UNKNOWN:
537 GST_ERROR ("invalid format");
538 g_warning ("invalid format");
545 * gst_video_info_convert:
546 * @info: a #GstVideoInfo
547 * @src_format: #GstFormat of the @src_value
548 * @src_value: value to convert
549 * @dest_format: #GstFormat of the @dest_value
550 * @dest_value: pointer to destination value
552 * Converts among various #GstFormat types. This function handles
553 * GST_FORMAT_BYTES, GST_FORMAT_TIME, and GST_FORMAT_DEFAULT. For
554 * raw video, GST_FORMAT_DEFAULT corresponds to video frames. This
555 * function can be used to handle pad queries of the type GST_QUERY_CONVERT.
557 * Returns: TRUE if the conversion was successful.
560 gst_video_info_convert (GstVideoInfo * info,
561 GstFormat src_format, gint64 src_value,
562 GstFormat dest_format, gint64 * dest_value)
564 gboolean ret = FALSE;
565 int size, fps_n, fps_d;
567 g_return_val_if_fail (info != NULL, 0);
568 g_return_val_if_fail (info->finfo != NULL, 0);
569 g_return_val_if_fail (info->finfo->format != GST_VIDEO_FORMAT_UNKNOWN, 0);
570 g_return_val_if_fail (info->size > 0, 0);
576 GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s to %s",
577 src_value, gst_format_get_name (src_format),
578 gst_format_get_name (dest_format));
580 if (src_format == dest_format) {
581 *dest_value = src_value;
586 if (src_value == -1) {
592 /* bytes to frames */
593 if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_DEFAULT) {
595 *dest_value = gst_util_uint64_scale_int (src_value, 1, size);
597 GST_ERROR ("blocksize is 0");
604 /* frames to bytes */
605 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_BYTES) {
606 *dest_value = gst_util_uint64_scale_int (src_value, size, 1);
612 if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_DEFAULT) {
614 *dest_value = gst_util_uint64_scale (src_value,
615 fps_n, GST_SECOND * fps_d);
617 GST_ERROR ("framerate denominator is 0");
625 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
627 *dest_value = gst_util_uint64_scale (src_value,
628 GST_SECOND * fps_d, fps_n);
630 GST_ERROR ("framerate numerator is 0");
638 if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) {
640 *dest_value = gst_util_uint64_scale (src_value,
641 fps_n * size, GST_SECOND * fps_d);
643 GST_ERROR ("framerate denominator is 0");
651 if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_TIME) {
652 if (fps_n != 0 && size != 0) {
653 *dest_value = gst_util_uint64_scale (src_value,
654 GST_SECOND * fps_d, fps_n * size);
656 GST_ERROR ("framerate denominator and/or blocksize is 0");
664 GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, ret, *dest_value);
670 * gst_video_info_align:
671 * @info: a #GstVideoInfo
672 * @align: alignment parameters
674 * Adjust the offset and stride fields in @info so that the padding and
675 * stride alignment in @align is respected.
677 * Extra padding will be added to the right side when stride alignment padding
678 * is required and @align will be updated with the new padding values.
681 gst_video_info_align (GstVideoInfo * info, GstVideoAlignment * align)
683 const GstVideoFormatInfo *vinfo = info->finfo;
685 gint padded_width, padded_height;
689 width = GST_VIDEO_INFO_WIDTH (info);
690 height = GST_VIDEO_INFO_HEIGHT (info);
692 GST_LOG ("padding %u-%ux%u-%u", align->padding_top,
693 align->padding_left, align->padding_right, align->padding_bottom);
695 /* add the padding */
696 padded_width = width + align->padding_left + align->padding_right;
697 padded_height = height + align->padding_top + align->padding_bottom;
699 n_planes = GST_VIDEO_INFO_N_PLANES (info);
701 GST_LOG ("padded dimension %u-%u", padded_width, padded_height);
703 gst_video_info_set_format (info, GST_VIDEO_INFO_FORMAT (info),
704 padded_width, padded_height);
706 /* check alignment */
708 for (i = 0; i < n_planes; i++) {
709 GST_LOG ("plane %d, stride %d, alignment %u", i, info->stride[i],
710 align->stride_align[i]);
711 aligned &= (info->stride[i] & align->stride_align[i]) == 0;
716 GST_LOG ("unaligned strides, increasing dimension");
717 /* increase padded_width */
718 padded_width += padded_width & ~(padded_width - 1);
721 align->padding_right = padded_width - width - align->padding_left;
724 info->height = height;
726 if (GST_VIDEO_FORMAT_INFO_HAS_PALETTE (vinfo))
729 for (i = 0; i < n_planes; i++) {
730 gint vedge, hedge, comp;
732 /* Find the component for this plane, FIXME, we assume the plane number and
733 * component number is the same for now, for scaling the dimensions this is
734 * currently true for all formats but it might not be when adding new
735 * formats. We might need to add a plane subsamling in the format info to
736 * make this more generic or maybe use a plane -> component mapping. */
740 GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (vinfo, comp, align->padding_left);
742 GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (vinfo, comp, align->padding_top);
744 GST_DEBUG ("plane %d: comp: %d, hedge %d vedge %d align %d stride %d", i,
745 comp, hedge, vedge, align->stride_align[i], info->stride[i]);
747 info->offset[i] += (vedge * info->stride[i]) +
748 (hedge * GST_VIDEO_FORMAT_INFO_PSTRIDE (vinfo, comp));