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"
31 #include <va/va_backend.h>
34 #include "gstvaapidebug.h"
36 G_DEFINE_TYPE(GstVaapiImage, gst_vaapi_image, GST_VAAPI_TYPE_OBJECT);
38 #define GST_VAAPI_IMAGE_GET_PRIVATE(obj) \
39 (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
40 GST_VAAPI_TYPE_IMAGE, \
41 GstVaapiImagePrivate))
43 struct _GstVaapiImagePrivate {
44 VAImage internal_image;
47 GstVaapiImageFormat internal_format;
48 GstVaapiImageFormat format;
51 guint create_image : 1;
52 guint is_constructed : 1;
66 #define SWAP_UINT(a, b) do { \
73 _gst_vaapi_image_map(GstVaapiImage *image);
76 _gst_vaapi_image_unmap(GstVaapiImage *image);
79 _gst_vaapi_image_set_image(GstVaapiImage *image, const VAImage *va_image);
85 #define VAAPI_TYPE_IMAGE vaapi_image_get_type()
88 vaapi_image_copy(gpointer va_image)
90 return g_slice_dup(VAImage, va_image);
94 vaapi_image_free(gpointer va_image)
96 if (G_LIKELY(va_image))
97 g_slice_free(VAImage, va_image);
101 vaapi_image_get_type(void)
103 static GType type = 0;
105 if (G_UNLIKELY(type == 0))
106 type = g_boxed_type_register_static(
115 vaapi_image_is_linear(const VAImage *va_image)
117 guint i, width, height, width2, height2, data_size;
119 for (i = 1; i < va_image->num_planes; i++)
120 if (va_image->offsets[i] < va_image->offsets[i - 1])
123 width = va_image->width;
124 height = va_image->height;
125 width2 = (width + 1) / 2;
126 height2 = (height + 1) / 2;
128 switch (va_image->format.fourcc) {
129 case VA_FOURCC('N','V','1','2'):
130 case VA_FOURCC('Y','V','1','2'):
131 case VA_FOURCC('I','4','2','0'):
132 data_size = width * height + 2 * width2 * height2;
134 case VA_FOURCC('A','R','G','B'):
135 case VA_FOURCC('R','G','B','A'):
136 case VA_FOURCC('A','B','G','R'):
137 case VA_FOURCC('B','G','R','A'):
138 data_size = 4 * width * height;
141 g_error("FIXME: incomplete formats");
144 return va_image->data_size == data_size;
148 gst_vaapi_image_destroy(GstVaapiImage *image)
150 GstVaapiDisplay * const display = GST_VAAPI_OBJECT_GET_DISPLAY(image);
151 GstVaapiImagePrivate * const priv = image->priv;
154 _gst_vaapi_image_unmap(image);
156 GST_DEBUG("image 0x%08x", priv->internal_image.image_id);
158 if (priv->internal_image.image_id != VA_INVALID_ID) {
159 GST_VAAPI_DISPLAY_LOCK(display);
160 status = vaDestroyImage(
161 GST_VAAPI_DISPLAY_VADISPLAY(display),
162 priv->internal_image.image_id
164 GST_VAAPI_DISPLAY_UNLOCK(display);
165 if (!vaapi_check_status(status, "vaDestroyImage()"))
166 g_warning("failed to destroy image 0x%08x\n",
167 priv->internal_image.image_id);
168 priv->internal_image.image_id = VA_INVALID_ID;
173 _gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format)
175 GstVaapiDisplay * const display = GST_VAAPI_OBJECT_GET_DISPLAY(image);
176 GstVaapiImagePrivate * const priv = image->priv;
177 const VAImageFormat *va_format;
180 if (!gst_vaapi_display_has_image_format(display, format))
183 va_format = gst_vaapi_image_format_get_va_format(format);
187 GST_VAAPI_DISPLAY_LOCK(display);
188 status = vaCreateImage(
189 GST_VAAPI_DISPLAY_VADISPLAY(display),
190 (VAImageFormat *)va_format,
193 &priv->internal_image
195 GST_VAAPI_DISPLAY_UNLOCK(display);
196 if (status != VA_STATUS_SUCCESS ||
197 priv->internal_image.format.fourcc != va_format->fourcc)
200 priv->internal_format = format;
205 gst_vaapi_image_create(GstVaapiImage *image)
207 GstVaapiImagePrivate * const priv = image->priv;
208 GstVaapiImageFormat format = priv->format;
209 const VAImageFormat *va_format;
211 if (!priv->create_image)
212 return (priv->image.image_id != VA_INVALID_ID &&
213 priv->image.buf != VA_INVALID_ID);
215 if (!_gst_vaapi_image_create(image, format)) {
217 case GST_VAAPI_IMAGE_I420:
218 format = GST_VAAPI_IMAGE_YV12;
220 case GST_VAAPI_IMAGE_YV12:
221 format = GST_VAAPI_IMAGE_I420;
227 if (!format || !_gst_vaapi_image_create(image, format))
230 priv->image = priv->internal_image;
232 if (priv->format != priv->internal_format) {
233 switch (priv->format) {
234 case GST_VAAPI_IMAGE_YV12:
235 case GST_VAAPI_IMAGE_I420:
236 va_format = gst_vaapi_image_format_get_va_format(priv->format);
239 priv->image.format = *va_format;
240 SWAP_UINT(priv->image.offsets[1], priv->image.offsets[2]);
241 SWAP_UINT(priv->image.pitches[1], priv->image.pitches[2]);
248 GST_DEBUG("image 0x%08x", priv->image.image_id);
249 priv->is_linear = vaapi_image_is_linear(&priv->image);
254 gst_vaapi_image_finalize(GObject *object)
256 gst_vaapi_image_destroy(GST_VAAPI_IMAGE(object));
258 G_OBJECT_CLASS(gst_vaapi_image_parent_class)->finalize(object);
262 gst_vaapi_image_set_property(
269 GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
270 GstVaapiImagePrivate * const priv = image->priv;
274 const VAImage * const va_image = g_value_get_boxed(value);
276 _gst_vaapi_image_set_image(image, va_image);
280 priv->format = g_value_get_uint(value);
283 priv->width = g_value_get_uint(value);
286 priv->height = g_value_get_uint(value);
289 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
295 gst_vaapi_image_get_property(
302 GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
306 g_value_set_boxed(value, &image->priv->image);
309 g_value_set_uint(value, gst_vaapi_image_get_id(image));
312 g_value_set_uint(value, gst_vaapi_image_get_format(image));
315 g_value_set_uint(value, gst_vaapi_image_get_width(image));
318 g_value_set_uint(value, gst_vaapi_image_get_height(image));
321 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
327 gst_vaapi_image_constructed(GObject *object)
329 GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
330 GObjectClass *parent_class;
332 image->priv->is_constructed = gst_vaapi_image_create(image);
334 parent_class = G_OBJECT_CLASS(gst_vaapi_image_parent_class);
335 if (parent_class->constructed)
336 parent_class->constructed(object);
340 gst_vaapi_image_class_init(GstVaapiImageClass *klass)
342 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
344 g_type_class_add_private(klass, sizeof(GstVaapiImagePrivate));
346 object_class->finalize = gst_vaapi_image_finalize;
347 object_class->set_property = gst_vaapi_image_set_property;
348 object_class->get_property = gst_vaapi_image_get_property;
349 object_class->constructed = gst_vaapi_image_constructed;
351 g_object_class_install_property
354 g_param_spec_boxed("image",
356 "The underlying VA image",
358 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
363 * The underlying #VAImageID of the image.
365 g_object_class_install_property
368 g_param_spec_uint("id",
370 "The underlying VA image id",
371 0, G_MAXUINT32, VA_INVALID_ID,
374 g_object_class_install_property
377 g_param_spec_uint("width",
381 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
383 g_object_class_install_property
386 g_param_spec_uint("height",
390 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
393 * GstVaapiImage:format:
395 * The #GstVaapiImageFormat of the image
397 g_object_class_install_property
400 g_param_spec_uint("format",
402 "The underlying image format",
404 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
408 gst_vaapi_image_init(GstVaapiImage *image)
410 GstVaapiImagePrivate *priv = GST_VAAPI_IMAGE_GET_PRIVATE(image);
413 priv->image_data = NULL;
416 priv->internal_format = 0;
418 priv->create_image = TRUE;
419 priv->is_constructed = FALSE;
420 priv->is_linear = FALSE;
422 memset(&priv->internal_image, 0, sizeof(priv->internal_image));
423 priv->internal_image.image_id = VA_INVALID_ID;
424 priv->internal_image.buf = VA_INVALID_ID;
426 memset(&priv->image, 0, sizeof(priv->image));
427 priv->image.image_id = VA_INVALID_ID;
428 priv->image.buf = VA_INVALID_ID;
432 * gst_vaapi_image_new:
433 * @display: a #GstVaapiDisplay
434 * @format: a #GstVaapiImageFormat
435 * @width: the requested image width
436 * @height: the requested image height
438 * Creates a new #GstVaapiImage with the specified format and
441 * Return value: the newly allocated #GstVaapiImage object
445 GstVaapiDisplay *display,
446 GstVaapiImageFormat format,
451 GstVaapiImage *image;
453 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
454 g_return_val_if_fail(width > 0, NULL);
455 g_return_val_if_fail(height > 0, NULL);
457 GST_DEBUG("format %" GST_FOURCC_FORMAT ", size %ux%u",
458 GST_FOURCC_ARGS(format), width, height);
460 image = g_object_new(
461 GST_VAAPI_TYPE_IMAGE,
471 if (!image->priv->is_constructed) {
472 g_object_unref(image);
479 * gst_vaapi_image_new_with_image:
480 * @display: a #GstVaapiDisplay
481 * @va_image: a VA image
483 * Creates a new #GstVaapiImage from a foreign VA image. The image
484 * format and dimensions will be extracted from @va_image. This
485 * function is mainly used by gst_vaapi_surface_derive_image() to bind
486 * a VA image to a #GstVaapiImage object.
488 * Return value: the newly allocated #GstVaapiImage object
491 gst_vaapi_image_new_with_image(GstVaapiDisplay *display, VAImage *va_image)
493 GstVaapiImage *image;
495 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
496 g_return_val_if_fail(va_image, NULL);
497 g_return_val_if_fail(va_image->image_id != VA_INVALID_ID, NULL);
498 g_return_val_if_fail(va_image->buf != VA_INVALID_ID, NULL);
500 GST_DEBUG("VA image 0x%08x, format %" GST_FOURCC_FORMAT ", size %ux%u",
502 GST_FOURCC_ARGS(va_image->format.fourcc),
503 va_image->width, va_image->height);
505 image = g_object_new(
506 GST_VAAPI_TYPE_IMAGE,
514 if (!image->priv->is_constructed) {
515 g_object_unref(image);
522 * gst_vaapi_image_get_id:
523 * @image: a #GstVaapiImage
525 * Returns the underlying VAImageID of the @image.
527 * Return value: the underlying VA image id
530 gst_vaapi_image_get_id(GstVaapiImage *image)
532 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), VA_INVALID_ID);
533 g_return_val_if_fail(image->priv->is_constructed, VA_INVALID_ID);
535 return image->priv->image.image_id;
539 * gst_vaapi_image_get_image:
540 * @image: a #GstVaapiImage
541 * @va_image: a VA image
543 * Fills @va_image with the VA image used internally.
545 * Return value: %TRUE on success
548 gst_vaapi_image_get_image(GstVaapiImage *image, VAImage *va_image)
550 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
551 g_return_val_if_fail(image->priv->is_constructed, FALSE);
554 *va_image = image->priv->image;
560 * _gst_vaapi_image_set_image:
561 * @image: a #GstVaapiImage
562 * @va_image: a VA image
564 * Initializes #GstVaapiImage with a foreign VA image. This function
565 * will try to "linearize" the VA image. i.e. making sure that the VA
566 * image offsets into the data buffer are in increasing order with the
567 * number of planes available in the image.
569 * This is an internal function used by gst_vaapi_image_new_with_image().
571 * Return value: %TRUE on success
574 _gst_vaapi_image_set_image(GstVaapiImage *image, const VAImage *va_image)
576 GstVaapiImagePrivate * const priv = image->priv;
577 GstVaapiImageFormat format;
578 VAImage alt_va_image;
579 const VAImageFormat *alt_va_format;
584 format = gst_vaapi_image_format(&va_image->format);
588 priv->create_image = FALSE;
589 priv->internal_image = *va_image;
590 priv->internal_format = format;
591 priv->is_linear = vaapi_image_is_linear(va_image);
592 priv->image = *va_image;
593 priv->format = format;
594 priv->width = va_image->width;
595 priv->height = va_image->height;
597 /* Try to linearize image */
598 if (!priv->is_linear) {
600 case GST_VAAPI_IMAGE_I420:
601 format = GST_VAAPI_IMAGE_YV12;
603 case GST_VAAPI_IMAGE_YV12:
604 format = GST_VAAPI_IMAGE_I420;
611 (alt_va_format = gst_vaapi_image_format_get_va_format(format))) {
612 alt_va_image = *va_image;
613 alt_va_image.format = *alt_va_format;
614 SWAP_UINT(alt_va_image.offsets[1], alt_va_image.offsets[2]);
615 SWAP_UINT(alt_va_image.pitches[1], alt_va_image.pitches[2]);
616 if (vaapi_image_is_linear(&alt_va_image)) {
617 priv->image = alt_va_image;
618 priv->format = format;
619 priv->is_linear = TRUE;
620 GST_DEBUG("linearized image to %" GST_FOURCC_FORMAT " format",
621 GST_FOURCC_ARGS(format));
629 * gst_vaapi_image_get_format:
630 * @image: a #GstVaapiImage
632 * Returns the #GstVaapiImageFormat the @image was created with.
634 * Return value: the #GstVaapiImageFormat
637 gst_vaapi_image_get_format(GstVaapiImage *image)
639 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
640 g_return_val_if_fail(image->priv->is_constructed, FALSE);
642 return image->priv->format;
646 * gst_vaapi_image_get_width:
647 * @image: a #GstVaapiImage
649 * Returns the @image width.
651 * Return value: the image width, in pixels
654 gst_vaapi_image_get_width(GstVaapiImage *image)
656 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
657 g_return_val_if_fail(image->priv->is_constructed, FALSE);
659 return image->priv->width;
663 * gst_vaapi_image_get_height:
664 * @image: a #GstVaapiImage
666 * Returns the @image height.
668 * Return value: the image height, in pixels.
671 gst_vaapi_image_get_height(GstVaapiImage *image)
673 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
674 g_return_val_if_fail(image->priv->is_constructed, FALSE);
676 return image->priv->height;
680 * gst_vaapi_image_get_size:
681 * @image: a #GstVaapiImage
682 * @pwidth: return location for the width, or %NULL
683 * @pheight: return location for the height, or %NULL
685 * Retrieves the dimensions of a #GstVaapiImage.
688 gst_vaapi_image_get_size(GstVaapiImage *image, guint *pwidth, guint *pheight)
690 g_return_if_fail(GST_VAAPI_IS_IMAGE(image));
691 g_return_if_fail(image->priv->is_constructed);
694 *pwidth = image->priv->width;
697 *pheight = image->priv->height;
701 * gst_vaapi_image_is_linear:
702 * @image: a #GstVaapiImage
704 * Checks whether the @image has data planes allocated from a single
705 * buffer and offsets into that buffer are in increasing order with
706 * the number of planes.
708 * Return value: %TRUE if image data planes are allocated from a single buffer
711 gst_vaapi_image_is_linear(GstVaapiImage *image)
713 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
714 g_return_val_if_fail(image->priv->is_constructed, FALSE);
716 return image->priv->is_linear;
720 * gst_vaapi_image_is_mapped:
721 * @image: a #GstVaapiImage
723 * Checks whether the @image is currently mapped or not.
725 * Return value: %TRUE if the @image is mapped
727 static inline gboolean
728 _gst_vaapi_image_is_mapped(GstVaapiImage *image)
730 return image->priv->image_data != NULL;
734 gst_vaapi_image_is_mapped(GstVaapiImage *image)
736 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
737 g_return_val_if_fail(image->priv->is_constructed, FALSE);
739 return _gst_vaapi_image_is_mapped(image);
743 * gst_vaapi_image_map:
744 * @image: a #GstVaapiImage
746 * Maps the image data buffer. The actual pixels are returned by the
747 * gst_vaapi_image_get_plane() function.
749 * Return value: %TRUE on success
752 gst_vaapi_image_map(GstVaapiImage *image)
754 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
755 g_return_val_if_fail(image->priv->is_constructed, FALSE);
757 return _gst_vaapi_image_map(image);
761 _gst_vaapi_image_map(GstVaapiImage *image)
763 GstVaapiDisplay *display;
767 if (_gst_vaapi_image_is_mapped(image))
770 display = GST_VAAPI_OBJECT_GET_DISPLAY(image);
774 GST_VAAPI_DISPLAY_LOCK(display);
775 status = vaMapBuffer(
776 GST_VAAPI_DISPLAY_VADISPLAY(display),
777 image->priv->image.buf,
780 GST_VAAPI_DISPLAY_UNLOCK(display);
781 if (!vaapi_check_status(status, "vaMapBuffer()"))
784 image->priv->image_data = image_data;
789 * gst_vaapi_image_unmap:
790 * @image: a #GstVaapiImage
792 * Unmaps the image data buffer. Pointers to pixels returned by
793 * gst_vaapi_image_get_plane() are then no longer valid.
795 * Return value: %TRUE on success
798 gst_vaapi_image_unmap(GstVaapiImage *image)
800 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
801 g_return_val_if_fail(image->priv->is_constructed, FALSE);
803 return _gst_vaapi_image_unmap(image);
807 _gst_vaapi_image_unmap(GstVaapiImage *image)
809 GstVaapiDisplay *display;
812 if (!_gst_vaapi_image_is_mapped(image))
815 display = GST_VAAPI_OBJECT_GET_DISPLAY(image);
819 GST_VAAPI_DISPLAY_LOCK(display);
820 status = vaUnmapBuffer(
821 GST_VAAPI_DISPLAY_VADISPLAY(display),
822 image->priv->image.buf
824 GST_VAAPI_DISPLAY_UNLOCK(display);
825 if (!vaapi_check_status(status, "vaUnmapBuffer()"))
828 image->priv->image_data = NULL;
833 * gst_vaapi_image_get_plane_count:
834 * @image: a #GstVaapiImage
836 * Retrieves the number of planes available in the @image. The @image
837 * must be mapped for this function to work properly.
839 * Return value: the number of planes available in the @image
842 gst_vaapi_image_get_plane_count(GstVaapiImage *image)
844 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
845 g_return_val_if_fail(image->priv->is_constructed, FALSE);
846 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0);
848 return image->priv->image.num_planes;
852 * gst_vaapi_image_get_plane:
853 * @image: a #GstVaapiImage
854 * @plane: the requested plane number
856 * Retrieves the pixels data to the specified @plane. The @image must
857 * be mapped for this function to work properly.
859 * Return value: the pixels data of the specified @plane
862 gst_vaapi_image_get_plane(GstVaapiImage *image, guint plane)
864 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), NULL);
865 g_return_val_if_fail(image->priv->is_constructed, FALSE);
866 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), NULL);
867 g_return_val_if_fail(plane < image->priv->image.num_planes, NULL);
869 return image->priv->image_data + image->priv->image.offsets[plane];
873 * gst_vaapi_image_get_pitch:
874 * @image: a #GstVaapiImage
875 * @plane: the requested plane number
877 * Retrieves the line size (stride) of the specified @plane. The
878 * @image must be mapped for this function to work properly.
880 * Return value: the line size (stride) of the specified plane
883 gst_vaapi_image_get_pitch(GstVaapiImage *image, guint plane)
885 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
886 g_return_val_if_fail(image->priv->is_constructed, FALSE);
887 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0);
888 g_return_val_if_fail(plane < image->priv->image.num_planes, 0);
890 return image->priv->image.pitches[plane];
894 * gst_vaapi_image_get_data_size:
895 * @image: a #GstVaapiImage
897 * Retrieves the underlying image data size. This function could be
898 * used to determine whether the image has a compatible layout with
899 * another image structure.
901 * Return value: the whole image data size of the @image
904 gst_vaapi_image_get_data_size(GstVaapiImage *image)
906 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
907 g_return_val_if_fail(image->priv->is_constructed, FALSE);
909 return image->priv->image.data_size;
913 * gst_vaapi_image_update_from_buffer:
914 * @image: a #GstVaapiImage
915 * @buffer: a #GstBuffer
917 * Transfers pixels data contained in the #GstBuffer into the
918 * @image. Both image structures shall have the same format.
920 * Return value: %TRUE on success
923 gst_vaapi_image_update_from_buffer(GstVaapiImage *image, GstBuffer *buffer)
925 GstVaapiImagePrivate *priv;
926 GstStructure *structure;
928 GstVaapiImageFormat format;
930 guint offsets[3], pitches[3], widths[3], heights[3];
935 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
936 g_return_val_if_fail(image->priv->is_constructed, FALSE);
937 g_return_val_if_fail(GST_IS_BUFFER(buffer), FALSE);
940 data = GST_BUFFER_DATA(buffer);
941 data_size = GST_BUFFER_SIZE(buffer);
942 caps = GST_BUFFER_CAPS(buffer);
947 format = gst_vaapi_image_format_from_caps(caps);
948 if (format != priv->format)
951 structure = gst_caps_get_structure(caps, 0);
952 gst_structure_get_int(structure, "width", &width);
953 gst_structure_get_int(structure, "height", &height);
954 if (width != priv->width || height != priv->height)
957 if (!gst_vaapi_image_map(image))
960 if (priv->is_linear && data_size == priv->image.data_size)
961 memcpy(priv->image_data, data, data_size);
963 /* XXX: copied from gst_video_format_get_row_stride() -- no NV12? */
964 const guint width2 = (width + 1) / 2;
965 const guint height2 = (height + 1) / 2;
968 case GST_VAAPI_IMAGE_NV12:
970 pitches[0] = GST_ROUND_UP_4(width);
973 offsets[1] = offsets[0] + height * pitches[0];
974 pitches[1] = pitches[0];
975 widths [1] = width2 * 2;
976 heights[1] = height2;
977 size2 = offsets[1] + height2 * pitches[1];
979 case GST_VAAPI_IMAGE_YV12:
980 case GST_VAAPI_IMAGE_I420:
982 pitches[0] = GST_ROUND_UP_4(width);
985 offsets[1] = offsets[0] + height * pitches[0];
986 pitches[1] = GST_ROUND_UP_4(GST_ROUND_UP_2(width) / 2);
988 heights[1] = height2;
989 offsets[2] = offsets[1] + height2 * pitches[1];
990 pitches[2] = pitches[1];
992 heights[2] = height2;
993 size2 = offsets[2] + height2 * pitches[2];
995 case GST_VAAPI_IMAGE_ARGB:
996 case GST_VAAPI_IMAGE_RGBA:
997 case GST_VAAPI_IMAGE_ABGR:
998 case GST_VAAPI_IMAGE_BGRA:
1000 pitches[0] = width * 4;
1001 widths [0] = width * 4;
1002 heights[0] = height;
1003 size2 = offsets[0] + height * pitches[0];
1006 g_error("could not compute row-stride for %" GST_FOURCC_FORMAT,
1007 GST_FOURCC_ARGS(format));
1010 if (size2 != data_size)
1011 g_error("data_size mismatch %d / %u", size2, data_size);
1012 for (i = 0; i < priv->image.num_planes; i++) {
1013 guchar *src = data + offsets[i];
1014 guchar *dst = priv->image_data + priv->image.offsets[i];
1015 for (j = 0; j < heights[i]; j++) {
1016 memcpy(dst, src, widths[i]);
1018 dst += priv->image.pitches[i];
1023 if (!gst_vaapi_image_unmap(image))