2 * gstvaapiimage.c - VA image abstraction
4 * gstreamer-vaapi (C) 2010 Splitted-Desktop Systems
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 * SECTION:gstvaapiimage
23 * @short_description: VA image abstraction
28 #include "gstvaapiutils.h"
29 #include "gstvaapiimage.h"
30 #include "gstvaapiobject_priv.h"
33 #include "gstvaapidebug.h"
35 G_DEFINE_TYPE(GstVaapiImage, gst_vaapi_image, GST_VAAPI_TYPE_OBJECT);
37 #define GST_VAAPI_IMAGE_GET_PRIVATE(obj) \
38 (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
39 GST_VAAPI_TYPE_IMAGE, \
40 GstVaapiImagePrivate))
42 struct _GstVaapiImagePrivate {
43 VAImage internal_image;
46 GstVaapiImageFormat internal_format;
47 GstVaapiImageFormat format;
50 guint create_image : 1;
51 guint is_constructed : 1;
64 #define SWAP_UINT(a, b) do { \
71 _gst_vaapi_image_map(GstVaapiImage *image);
74 _gst_vaapi_image_unmap(GstVaapiImage *image);
77 _gst_vaapi_image_set_image(GstVaapiImage *image, const VAImage *va_image);
83 #define VAAPI_TYPE_IMAGE vaapi_image_get_type()
86 vaapi_image_copy(gpointer va_image)
88 return g_slice_dup(VAImage, va_image);
92 vaapi_image_free(gpointer va_image)
94 if (G_LIKELY(va_image))
95 g_slice_free(VAImage, va_image);
99 vaapi_image_get_type(void)
101 static GType type = 0;
103 if (G_UNLIKELY(type == 0))
104 type = g_boxed_type_register_static(
113 vaapi_image_is_linear(const VAImage *va_image)
115 guint i, width, height, width2, height2, data_size;
117 for (i = 1; i < va_image->num_planes; i++)
118 if (va_image->offsets[i] < va_image->offsets[i - 1])
121 width = va_image->width;
122 height = va_image->height;
123 width2 = (width + 1) / 2;
124 height2 = (height + 1) / 2;
126 switch (va_image->format.fourcc) {
127 case VA_FOURCC('N','V','1','2'):
128 case VA_FOURCC('Y','V','1','2'):
129 case VA_FOURCC('I','4','2','0'):
130 data_size = width * height + 2 * width2 * height2;
132 case VA_FOURCC('A','R','G','B'):
133 case VA_FOURCC('R','G','B','A'):
134 case VA_FOURCC('A','B','G','R'):
135 case VA_FOURCC('B','G','R','A'):
136 data_size = 4 * width * height;
139 g_error("FIXME: incomplete formats");
142 return va_image->data_size == data_size;
146 gst_vaapi_image_destroy(GstVaapiImage *image)
148 GstVaapiDisplay * const display = GST_VAAPI_OBJECT_GET_DISPLAY(image);
152 _gst_vaapi_image_unmap(image);
154 image_id = GST_VAAPI_OBJECT_ID(image);
155 GST_DEBUG("image %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(image_id));
157 if (image_id != VA_INVALID_ID) {
158 GST_VAAPI_DISPLAY_LOCK(display);
159 status = vaDestroyImage(GST_VAAPI_DISPLAY_VADISPLAY(display), image_id);
160 GST_VAAPI_DISPLAY_UNLOCK(display);
161 if (!vaapi_check_status(status, "vaDestroyImage()"))
162 g_warning("failed to destroy image %" GST_VAAPI_ID_FORMAT "\n",
163 GST_VAAPI_ID_ARGS(image_id));
164 GST_VAAPI_OBJECT_ID(image) = VA_INVALID_ID;
169 _gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format)
171 GstVaapiDisplay * const display = GST_VAAPI_OBJECT_GET_DISPLAY(image);
172 GstVaapiImagePrivate * const priv = image->priv;
173 const VAImageFormat *va_format;
176 if (!gst_vaapi_display_has_image_format(display, format))
179 va_format = gst_vaapi_image_format_get_va_format(format);
183 GST_VAAPI_DISPLAY_LOCK(display);
184 status = vaCreateImage(
185 GST_VAAPI_DISPLAY_VADISPLAY(display),
186 (VAImageFormat *)va_format,
189 &priv->internal_image
191 GST_VAAPI_DISPLAY_UNLOCK(display);
192 if (status != VA_STATUS_SUCCESS ||
193 priv->internal_image.format.fourcc != va_format->fourcc)
196 priv->internal_format = format;
201 gst_vaapi_image_create(GstVaapiImage *image)
203 GstVaapiImagePrivate * const priv = image->priv;
204 GstVaapiImageFormat format = priv->format;
205 const VAImageFormat *va_format;
208 if (!priv->create_image)
209 return (priv->image.image_id != VA_INVALID_ID &&
210 priv->image.buf != VA_INVALID_ID);
212 if (!_gst_vaapi_image_create(image, format)) {
214 case GST_VAAPI_IMAGE_I420:
215 format = GST_VAAPI_IMAGE_YV12;
217 case GST_VAAPI_IMAGE_YV12:
218 format = GST_VAAPI_IMAGE_I420;
224 if (!format || !_gst_vaapi_image_create(image, format))
227 priv->image = priv->internal_image;
228 image_id = priv->image.image_id;
230 if (priv->format != priv->internal_format) {
231 switch (priv->format) {
232 case GST_VAAPI_IMAGE_YV12:
233 case GST_VAAPI_IMAGE_I420:
234 va_format = gst_vaapi_image_format_get_va_format(priv->format);
237 priv->image.format = *va_format;
238 SWAP_UINT(priv->image.offsets[1], priv->image.offsets[2]);
239 SWAP_UINT(priv->image.pitches[1], priv->image.pitches[2]);
245 priv->is_linear = vaapi_image_is_linear(&priv->image);
247 GST_DEBUG("image %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(image_id));
248 GST_VAAPI_OBJECT_ID(image) = image_id;
253 gst_vaapi_image_finalize(GObject *object)
255 gst_vaapi_image_destroy(GST_VAAPI_IMAGE(object));
257 G_OBJECT_CLASS(gst_vaapi_image_parent_class)->finalize(object);
261 gst_vaapi_image_set_property(
268 GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
269 GstVaapiImagePrivate * const priv = image->priv;
273 const VAImage * const va_image = g_value_get_boxed(value);
275 _gst_vaapi_image_set_image(image, va_image);
279 priv->format = g_value_get_uint(value);
282 priv->width = g_value_get_uint(value);
285 priv->height = g_value_get_uint(value);
288 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
294 gst_vaapi_image_get_property(
301 GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
305 g_value_set_boxed(value, &image->priv->image);
308 g_value_set_uint(value, gst_vaapi_image_get_format(image));
311 g_value_set_uint(value, gst_vaapi_image_get_width(image));
314 g_value_set_uint(value, gst_vaapi_image_get_height(image));
317 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
323 gst_vaapi_image_constructed(GObject *object)
325 GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
326 GObjectClass *parent_class;
328 image->priv->is_constructed = gst_vaapi_image_create(image);
330 parent_class = G_OBJECT_CLASS(gst_vaapi_image_parent_class);
331 if (parent_class->constructed)
332 parent_class->constructed(object);
336 gst_vaapi_image_class_init(GstVaapiImageClass *klass)
338 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
340 g_type_class_add_private(klass, sizeof(GstVaapiImagePrivate));
342 object_class->finalize = gst_vaapi_image_finalize;
343 object_class->set_property = gst_vaapi_image_set_property;
344 object_class->get_property = gst_vaapi_image_get_property;
345 object_class->constructed = gst_vaapi_image_constructed;
347 g_object_class_install_property
350 g_param_spec_boxed("image",
352 "The underlying VA image",
354 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
356 g_object_class_install_property
359 g_param_spec_uint("width",
363 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
365 g_object_class_install_property
368 g_param_spec_uint("height",
372 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
375 * GstVaapiImage:format:
377 * The #GstVaapiImageFormat of the image
379 g_object_class_install_property
382 g_param_spec_uint("format",
384 "The underlying image format",
386 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
390 gst_vaapi_image_init(GstVaapiImage *image)
392 GstVaapiImagePrivate *priv = GST_VAAPI_IMAGE_GET_PRIVATE(image);
395 priv->image_data = NULL;
398 priv->internal_format = 0;
400 priv->create_image = TRUE;
401 priv->is_constructed = FALSE;
402 priv->is_linear = FALSE;
404 memset(&priv->internal_image, 0, sizeof(priv->internal_image));
405 priv->internal_image.image_id = VA_INVALID_ID;
406 priv->internal_image.buf = VA_INVALID_ID;
408 memset(&priv->image, 0, sizeof(priv->image));
409 priv->image.image_id = VA_INVALID_ID;
410 priv->image.buf = VA_INVALID_ID;
414 * gst_vaapi_image_new:
415 * @display: a #GstVaapiDisplay
416 * @format: a #GstVaapiImageFormat
417 * @width: the requested image width
418 * @height: the requested image height
420 * Creates a new #GstVaapiImage with the specified format and
423 * Return value: the newly allocated #GstVaapiImage object
427 GstVaapiDisplay *display,
428 GstVaapiImageFormat format,
433 GstVaapiImage *image;
435 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
436 g_return_val_if_fail(width > 0, NULL);
437 g_return_val_if_fail(height > 0, NULL);
439 GST_DEBUG("format %" GST_FOURCC_FORMAT ", size %ux%u",
440 GST_FOURCC_ARGS(format), width, height);
442 image = g_object_new(
443 GST_VAAPI_TYPE_IMAGE,
453 if (!image->priv->is_constructed) {
454 g_object_unref(image);
461 * gst_vaapi_image_new_with_image:
462 * @display: a #GstVaapiDisplay
463 * @va_image: a VA image
465 * Creates a new #GstVaapiImage from a foreign VA image. The image
466 * format and dimensions will be extracted from @va_image. This
467 * function is mainly used by gst_vaapi_surface_derive_image() to bind
468 * a VA image to a #GstVaapiImage object.
470 * Return value: the newly allocated #GstVaapiImage object
473 gst_vaapi_image_new_with_image(GstVaapiDisplay *display, VAImage *va_image)
475 GstVaapiImage *image;
477 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
478 g_return_val_if_fail(va_image, NULL);
479 g_return_val_if_fail(va_image->image_id != VA_INVALID_ID, NULL);
480 g_return_val_if_fail(va_image->buf != VA_INVALID_ID, NULL);
482 GST_DEBUG("VA image 0x%08x, format %" GST_FOURCC_FORMAT ", size %ux%u",
484 GST_FOURCC_ARGS(va_image->format.fourcc),
485 va_image->width, va_image->height);
487 image = g_object_new(
488 GST_VAAPI_TYPE_IMAGE,
496 if (!image->priv->is_constructed) {
497 g_object_unref(image);
504 * gst_vaapi_image_get_image:
505 * @image: a #GstVaapiImage
506 * @va_image: a VA image
508 * Fills @va_image with the VA image used internally.
510 * Return value: %TRUE on success
513 gst_vaapi_image_get_image(GstVaapiImage *image, VAImage *va_image)
515 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
516 g_return_val_if_fail(image->priv->is_constructed, FALSE);
519 *va_image = image->priv->image;
525 * _gst_vaapi_image_set_image:
526 * @image: a #GstVaapiImage
527 * @va_image: a VA image
529 * Initializes #GstVaapiImage with a foreign VA image. This function
530 * will try to "linearize" the VA image. i.e. making sure that the VA
531 * image offsets into the data buffer are in increasing order with the
532 * number of planes available in the image.
534 * This is an internal function used by gst_vaapi_image_new_with_image().
536 * Return value: %TRUE on success
539 _gst_vaapi_image_set_image(GstVaapiImage *image, const VAImage *va_image)
541 GstVaapiImagePrivate * const priv = image->priv;
542 GstVaapiImageFormat format;
543 VAImage alt_va_image;
544 const VAImageFormat *alt_va_format;
549 format = gst_vaapi_image_format(&va_image->format);
553 priv->create_image = FALSE;
554 priv->internal_image = *va_image;
555 priv->internal_format = format;
556 priv->is_linear = vaapi_image_is_linear(va_image);
557 priv->image = *va_image;
558 priv->format = format;
559 priv->width = va_image->width;
560 priv->height = va_image->height;
562 /* Try to linearize image */
563 if (!priv->is_linear) {
565 case GST_VAAPI_IMAGE_I420:
566 format = GST_VAAPI_IMAGE_YV12;
568 case GST_VAAPI_IMAGE_YV12:
569 format = GST_VAAPI_IMAGE_I420;
576 (alt_va_format = gst_vaapi_image_format_get_va_format(format))) {
577 alt_va_image = *va_image;
578 alt_va_image.format = *alt_va_format;
579 SWAP_UINT(alt_va_image.offsets[1], alt_va_image.offsets[2]);
580 SWAP_UINT(alt_va_image.pitches[1], alt_va_image.pitches[2]);
581 if (vaapi_image_is_linear(&alt_va_image)) {
582 priv->image = alt_va_image;
583 priv->format = format;
584 priv->is_linear = TRUE;
585 GST_DEBUG("linearized image to %" GST_FOURCC_FORMAT " format",
586 GST_FOURCC_ARGS(format));
594 * gst_vaapi_image_get_format:
595 * @image: a #GstVaapiImage
597 * Returns the #GstVaapiImageFormat the @image was created with.
599 * Return value: the #GstVaapiImageFormat
602 gst_vaapi_image_get_format(GstVaapiImage *image)
604 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
605 g_return_val_if_fail(image->priv->is_constructed, FALSE);
607 return image->priv->format;
611 * gst_vaapi_image_get_width:
612 * @image: a #GstVaapiImage
614 * Returns the @image width.
616 * Return value: the image width, in pixels
619 gst_vaapi_image_get_width(GstVaapiImage *image)
621 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
622 g_return_val_if_fail(image->priv->is_constructed, FALSE);
624 return image->priv->width;
628 * gst_vaapi_image_get_height:
629 * @image: a #GstVaapiImage
631 * Returns the @image height.
633 * Return value: the image height, in pixels.
636 gst_vaapi_image_get_height(GstVaapiImage *image)
638 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
639 g_return_val_if_fail(image->priv->is_constructed, FALSE);
641 return image->priv->height;
645 * gst_vaapi_image_get_size:
646 * @image: a #GstVaapiImage
647 * @pwidth: return location for the width, or %NULL
648 * @pheight: return location for the height, or %NULL
650 * Retrieves the dimensions of a #GstVaapiImage.
653 gst_vaapi_image_get_size(GstVaapiImage *image, guint *pwidth, guint *pheight)
655 g_return_if_fail(GST_VAAPI_IS_IMAGE(image));
656 g_return_if_fail(image->priv->is_constructed);
659 *pwidth = image->priv->width;
662 *pheight = image->priv->height;
666 * gst_vaapi_image_is_linear:
667 * @image: a #GstVaapiImage
669 * Checks whether the @image has data planes allocated from a single
670 * buffer and offsets into that buffer are in increasing order with
671 * the number of planes.
673 * Return value: %TRUE if image data planes are allocated from a single buffer
676 gst_vaapi_image_is_linear(GstVaapiImage *image)
678 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
679 g_return_val_if_fail(image->priv->is_constructed, FALSE);
681 return image->priv->is_linear;
685 * gst_vaapi_image_is_mapped:
686 * @image: a #GstVaapiImage
688 * Checks whether the @image is currently mapped or not.
690 * Return value: %TRUE if the @image is mapped
692 static inline gboolean
693 _gst_vaapi_image_is_mapped(GstVaapiImage *image)
695 return image->priv->image_data != NULL;
699 gst_vaapi_image_is_mapped(GstVaapiImage *image)
701 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
702 g_return_val_if_fail(image->priv->is_constructed, FALSE);
704 return _gst_vaapi_image_is_mapped(image);
708 * gst_vaapi_image_map:
709 * @image: a #GstVaapiImage
711 * Maps the image data buffer. The actual pixels are returned by the
712 * gst_vaapi_image_get_plane() function.
714 * Return value: %TRUE on success
717 gst_vaapi_image_map(GstVaapiImage *image)
719 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
720 g_return_val_if_fail(image->priv->is_constructed, FALSE);
722 return _gst_vaapi_image_map(image);
726 _gst_vaapi_image_map(GstVaapiImage *image)
728 GstVaapiDisplay *display;
732 if (_gst_vaapi_image_is_mapped(image))
735 display = GST_VAAPI_OBJECT_GET_DISPLAY(image);
739 GST_VAAPI_DISPLAY_LOCK(display);
740 status = vaMapBuffer(
741 GST_VAAPI_DISPLAY_VADISPLAY(display),
742 image->priv->image.buf,
745 GST_VAAPI_DISPLAY_UNLOCK(display);
746 if (!vaapi_check_status(status, "vaMapBuffer()"))
749 image->priv->image_data = image_data;
754 * gst_vaapi_image_unmap:
755 * @image: a #GstVaapiImage
757 * Unmaps the image data buffer. Pointers to pixels returned by
758 * gst_vaapi_image_get_plane() are then no longer valid.
760 * Return value: %TRUE on success
763 gst_vaapi_image_unmap(GstVaapiImage *image)
765 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
766 g_return_val_if_fail(image->priv->is_constructed, FALSE);
768 return _gst_vaapi_image_unmap(image);
772 _gst_vaapi_image_unmap(GstVaapiImage *image)
774 GstVaapiDisplay *display;
777 if (!_gst_vaapi_image_is_mapped(image))
780 display = GST_VAAPI_OBJECT_GET_DISPLAY(image);
784 GST_VAAPI_DISPLAY_LOCK(display);
785 status = vaUnmapBuffer(
786 GST_VAAPI_DISPLAY_VADISPLAY(display),
787 image->priv->image.buf
789 GST_VAAPI_DISPLAY_UNLOCK(display);
790 if (!vaapi_check_status(status, "vaUnmapBuffer()"))
793 image->priv->image_data = NULL;
798 * gst_vaapi_image_get_plane_count:
799 * @image: a #GstVaapiImage
801 * Retrieves the number of planes available in the @image. The @image
802 * must be mapped for this function to work properly.
804 * Return value: the number of planes available in the @image
807 gst_vaapi_image_get_plane_count(GstVaapiImage *image)
809 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
810 g_return_val_if_fail(image->priv->is_constructed, FALSE);
811 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0);
813 return image->priv->image.num_planes;
817 * gst_vaapi_image_get_plane:
818 * @image: a #GstVaapiImage
819 * @plane: the requested plane number
821 * Retrieves the pixels data to the specified @plane. The @image must
822 * be mapped for this function to work properly.
824 * Return value: the pixels data of the specified @plane
827 gst_vaapi_image_get_plane(GstVaapiImage *image, guint plane)
829 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), NULL);
830 g_return_val_if_fail(image->priv->is_constructed, FALSE);
831 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), NULL);
832 g_return_val_if_fail(plane < image->priv->image.num_planes, NULL);
834 return image->priv->image_data + image->priv->image.offsets[plane];
838 * gst_vaapi_image_get_pitch:
839 * @image: a #GstVaapiImage
840 * @plane: the requested plane number
842 * Retrieves the line size (stride) of the specified @plane. The
843 * @image must be mapped for this function to work properly.
845 * Return value: the line size (stride) of the specified plane
848 gst_vaapi_image_get_pitch(GstVaapiImage *image, guint plane)
850 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
851 g_return_val_if_fail(image->priv->is_constructed, FALSE);
852 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0);
853 g_return_val_if_fail(plane < image->priv->image.num_planes, 0);
855 return image->priv->image.pitches[plane];
859 * gst_vaapi_image_get_data_size:
860 * @image: a #GstVaapiImage
862 * Retrieves the underlying image data size. This function could be
863 * used to determine whether the image has a compatible layout with
864 * another image structure.
866 * Return value: the whole image data size of the @image
869 gst_vaapi_image_get_data_size(GstVaapiImage *image)
871 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
872 g_return_val_if_fail(image->priv->is_constructed, FALSE);
874 return image->priv->image.data_size;
878 * gst_vaapi_image_update_from_buffer:
879 * @image: a #GstVaapiImage
880 * @buffer: a #GstBuffer
882 * Transfers pixels data contained in the #GstBuffer into the
883 * @image. Both image structures shall have the same format.
885 * Return value: %TRUE on success
888 gst_vaapi_image_update_from_buffer(GstVaapiImage *image, GstBuffer *buffer)
890 GstVaapiImagePrivate *priv;
891 GstStructure *structure;
893 GstVaapiImageFormat format;
895 guint offsets[3], pitches[3], widths[3], heights[3];
900 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
901 g_return_val_if_fail(image->priv->is_constructed, FALSE);
902 g_return_val_if_fail(GST_IS_BUFFER(buffer), FALSE);
905 data = GST_BUFFER_DATA(buffer);
906 data_size = GST_BUFFER_SIZE(buffer);
907 caps = GST_BUFFER_CAPS(buffer);
912 format = gst_vaapi_image_format_from_caps(caps);
913 if (format != priv->format)
916 structure = gst_caps_get_structure(caps, 0);
917 gst_structure_get_int(structure, "width", &width);
918 gst_structure_get_int(structure, "height", &height);
919 if (width != priv->width || height != priv->height)
922 if (!gst_vaapi_image_map(image))
925 if (priv->is_linear && data_size == priv->image.data_size)
926 memcpy(priv->image_data, data, data_size);
928 /* XXX: copied from gst_video_format_get_row_stride() -- no NV12? */
929 const guint width2 = (width + 1) / 2;
930 const guint height2 = (height + 1) / 2;
933 case GST_VAAPI_IMAGE_NV12:
935 pitches[0] = GST_ROUND_UP_4(width);
938 offsets[1] = offsets[0] + height * pitches[0];
939 pitches[1] = pitches[0];
940 widths [1] = width2 * 2;
941 heights[1] = height2;
942 size2 = offsets[1] + height2 * pitches[1];
944 case GST_VAAPI_IMAGE_YV12:
945 case GST_VAAPI_IMAGE_I420:
947 pitches[0] = GST_ROUND_UP_4(width);
950 offsets[1] = offsets[0] + height * pitches[0];
951 pitches[1] = GST_ROUND_UP_4(GST_ROUND_UP_2(width) / 2);
953 heights[1] = height2;
954 offsets[2] = offsets[1] + height2 * pitches[1];
955 pitches[2] = pitches[1];
957 heights[2] = height2;
958 size2 = offsets[2] + height2 * pitches[2];
960 case GST_VAAPI_IMAGE_ARGB:
961 case GST_VAAPI_IMAGE_RGBA:
962 case GST_VAAPI_IMAGE_ABGR:
963 case GST_VAAPI_IMAGE_BGRA:
965 pitches[0] = width * 4;
966 widths [0] = width * 4;
968 size2 = offsets[0] + height * pitches[0];
971 g_error("could not compute row-stride for %" GST_FOURCC_FORMAT,
972 GST_FOURCC_ARGS(format));
975 if (size2 != data_size)
976 g_error("data_size mismatch %d / %u", size2, data_size);
977 for (i = 0; i < priv->image.num_planes; i++) {
978 guchar *src = data + offsets[i];
979 guchar *dst = priv->image_data + priv->image.offsets[i];
980 for (j = 0; j < heights[i]; j++) {
981 memcpy(dst, src, widths[i]);
983 dst += priv->image.pitches[i];
988 if (!gst_vaapi_image_unmap(image))