2 * gstvaapiimage.c - VA image abstraction
4 * gstreamer-vaapi (C) 2010-2011 Splitted-Desktop Systems
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 2.1
9 * 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 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
23 * SECTION:gstvaapiimage
24 * @short_description: VA image abstraction
29 #include "gstvaapicompat.h"
30 #include "gstvaapiutils.h"
31 #include "gstvaapiimage.h"
32 #include "gstvaapi_priv.h"
35 #include "gstvaapidebug.h"
37 G_DEFINE_TYPE(GstVaapiImage, gst_vaapi_image, GST_VAAPI_TYPE_OBJECT);
39 #define GST_VAAPI_IMAGE_GET_PRIVATE(obj) \
40 (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
41 GST_VAAPI_TYPE_IMAGE, \
42 GstVaapiImagePrivate))
44 struct _GstVaapiImagePrivate {
45 VAImage internal_image;
48 GstVaapiImageFormat internal_format;
49 GstVaapiImageFormat format;
52 guint create_image : 1;
53 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','Y','U','V'):
135 case VA_FOURCC('A','R','G','B'):
136 case VA_FOURCC('R','G','B','A'):
137 case VA_FOURCC('A','B','G','R'):
138 case VA_FOURCC('B','G','R','A'):
139 data_size = 4 * width * height;
142 g_error("FIXME: incomplete formats");
145 return va_image->data_size == data_size;
149 gst_vaapi_image_destroy(GstVaapiImage *image)
151 GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(image);
155 _gst_vaapi_image_unmap(image);
157 image_id = GST_VAAPI_OBJECT_ID(image);
158 GST_DEBUG("image %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(image_id));
160 if (image_id != VA_INVALID_ID) {
161 GST_VAAPI_DISPLAY_LOCK(display);
162 status = vaDestroyImage(GST_VAAPI_DISPLAY_VADISPLAY(display), image_id);
163 GST_VAAPI_DISPLAY_UNLOCK(display);
164 if (!vaapi_check_status(status, "vaDestroyImage()"))
165 g_warning("failed to destroy image %" GST_VAAPI_ID_FORMAT,
166 GST_VAAPI_ID_ARGS(image_id));
167 GST_VAAPI_OBJECT_ID(image) = VA_INVALID_ID;
172 _gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format)
174 GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(image);
175 GstVaapiImagePrivate * const priv = image->priv;
176 const VAImageFormat *va_format;
179 if (!gst_vaapi_display_has_image_format(display, format))
182 va_format = gst_vaapi_image_format_get_va_format(format);
186 GST_VAAPI_DISPLAY_LOCK(display);
187 status = vaCreateImage(
188 GST_VAAPI_DISPLAY_VADISPLAY(display),
189 (VAImageFormat *)va_format,
192 &priv->internal_image
194 GST_VAAPI_DISPLAY_UNLOCK(display);
195 if (status != VA_STATUS_SUCCESS ||
196 priv->internal_image.format.fourcc != va_format->fourcc)
199 priv->internal_format = format;
204 gst_vaapi_image_create(GstVaapiImage *image)
206 GstVaapiImagePrivate * const priv = image->priv;
207 GstVaapiImageFormat format = priv->format;
208 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;
231 image_id = priv->image.image_id;
233 if (priv->format != priv->internal_format) {
234 switch (priv->format) {
235 case GST_VAAPI_IMAGE_YV12:
236 case GST_VAAPI_IMAGE_I420:
237 va_format = gst_vaapi_image_format_get_va_format(priv->format);
240 priv->image.format = *va_format;
241 SWAP_UINT(priv->image.offsets[1], priv->image.offsets[2]);
242 SWAP_UINT(priv->image.pitches[1], priv->image.pitches[2]);
248 priv->is_linear = vaapi_image_is_linear(&priv->image);
250 GST_DEBUG("image %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(image_id));
251 GST_VAAPI_OBJECT_ID(image) = image_id;
256 gst_vaapi_image_finalize(GObject *object)
258 gst_vaapi_image_destroy(GST_VAAPI_IMAGE(object));
260 G_OBJECT_CLASS(gst_vaapi_image_parent_class)->finalize(object);
264 gst_vaapi_image_set_property(
271 GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
272 GstVaapiImagePrivate * const priv = image->priv;
276 const VAImage * const va_image = g_value_get_boxed(value);
278 _gst_vaapi_image_set_image(image, va_image);
282 priv->format = g_value_get_uint(value);
285 priv->width = g_value_get_uint(value);
288 priv->height = g_value_get_uint(value);
291 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
297 gst_vaapi_image_get_property(
304 GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
308 g_value_set_boxed(value, &image->priv->image);
311 g_value_set_uint(value, gst_vaapi_image_get_format(image));
314 g_value_set_uint(value, gst_vaapi_image_get_width(image));
317 g_value_set_uint(value, gst_vaapi_image_get_height(image));
320 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
326 gst_vaapi_image_constructed(GObject *object)
328 GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
329 GObjectClass *parent_class;
331 image->priv->is_constructed = gst_vaapi_image_create(image);
333 parent_class = G_OBJECT_CLASS(gst_vaapi_image_parent_class);
334 if (parent_class->constructed)
335 parent_class->constructed(object);
339 gst_vaapi_image_class_init(GstVaapiImageClass *klass)
341 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
343 g_type_class_add_private(klass, sizeof(GstVaapiImagePrivate));
345 object_class->finalize = gst_vaapi_image_finalize;
346 object_class->set_property = gst_vaapi_image_set_property;
347 object_class->get_property = gst_vaapi_image_get_property;
348 object_class->constructed = gst_vaapi_image_constructed;
350 g_object_class_install_property
353 g_param_spec_boxed("image",
355 "The underlying VA image",
357 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
359 g_object_class_install_property
362 g_param_spec_uint("width",
366 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
368 g_object_class_install_property
371 g_param_spec_uint("height",
375 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
378 * GstVaapiImage:format:
380 * The #GstVaapiImageFormat of the image
382 g_object_class_install_property
385 g_param_spec_uint("format",
387 "The underlying image format",
389 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
393 gst_vaapi_image_init(GstVaapiImage *image)
395 GstVaapiImagePrivate *priv = GST_VAAPI_IMAGE_GET_PRIVATE(image);
398 priv->image_data = NULL;
401 priv->internal_format = 0;
403 priv->create_image = TRUE;
404 priv->is_constructed = FALSE;
405 priv->is_linear = FALSE;
407 memset(&priv->internal_image, 0, sizeof(priv->internal_image));
408 priv->internal_image.image_id = VA_INVALID_ID;
409 priv->internal_image.buf = VA_INVALID_ID;
411 memset(&priv->image, 0, sizeof(priv->image));
412 priv->image.image_id = VA_INVALID_ID;
413 priv->image.buf = VA_INVALID_ID;
417 * gst_vaapi_image_new:
418 * @display: a #GstVaapiDisplay
419 * @format: a #GstVaapiImageFormat
420 * @width: the requested image width
421 * @height: the requested image height
423 * Creates a new #GstVaapiImage with the specified format and
426 * Return value: the newly allocated #GstVaapiImage object
430 GstVaapiDisplay *display,
431 GstVaapiImageFormat format,
436 GstVaapiImage *image;
438 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
439 g_return_val_if_fail(width > 0, NULL);
440 g_return_val_if_fail(height > 0, NULL);
442 GST_DEBUG("format %" GST_FOURCC_FORMAT ", size %ux%u",
443 GST_FOURCC_ARGS(format), width, height);
445 image = g_object_new(
446 GST_VAAPI_TYPE_IMAGE,
448 "id", GST_VAAPI_ID(VA_INVALID_ID),
457 if (!image->priv->is_constructed) {
458 g_object_unref(image);
465 * gst_vaapi_image_new_with_image:
466 * @display: a #GstVaapiDisplay
467 * @va_image: a VA image
469 * Creates a new #GstVaapiImage from a foreign VA image. The image
470 * format and dimensions will be extracted from @va_image. This
471 * function is mainly used by gst_vaapi_surface_derive_image() to bind
472 * a VA image to a #GstVaapiImage object.
474 * Return value: the newly allocated #GstVaapiImage object
477 gst_vaapi_image_new_with_image(GstVaapiDisplay *display, VAImage *va_image)
479 GstVaapiImage *image;
481 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
482 g_return_val_if_fail(va_image, NULL);
483 g_return_val_if_fail(va_image->image_id != VA_INVALID_ID, NULL);
484 g_return_val_if_fail(va_image->buf != VA_INVALID_ID, NULL);
486 GST_DEBUG("VA image 0x%08x, format %" GST_FOURCC_FORMAT ", size %ux%u",
488 GST_FOURCC_ARGS(va_image->format.fourcc),
489 va_image->width, va_image->height);
491 image = g_object_new(
492 GST_VAAPI_TYPE_IMAGE,
494 "id", GST_VAAPI_ID(va_image->image_id),
501 if (!image->priv->is_constructed) {
502 g_object_unref(image);
509 * gst_vaapi_image_get_id:
510 * @image: a #GstVaapiImage
512 * Returns the underlying VAImageID of the @image.
514 * Return value: the underlying VA image id
517 gst_vaapi_image_get_id(GstVaapiImage *image)
519 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), VA_INVALID_ID);
520 g_return_val_if_fail(image->priv->is_constructed, VA_INVALID_ID);
522 return GST_VAAPI_OBJECT_ID(image);
526 * gst_vaapi_image_get_image:
527 * @image: a #GstVaapiImage
528 * @va_image: a VA image
530 * Fills @va_image with the VA image used internally.
532 * Return value: %TRUE on success
535 gst_vaapi_image_get_image(GstVaapiImage *image, VAImage *va_image)
537 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
538 g_return_val_if_fail(image->priv->is_constructed, FALSE);
541 *va_image = image->priv->image;
547 * _gst_vaapi_image_set_image:
548 * @image: a #GstVaapiImage
549 * @va_image: a VA image
551 * Initializes #GstVaapiImage with a foreign VA image. This function
552 * will try to "linearize" the VA image. i.e. making sure that the VA
553 * image offsets into the data buffer are in increasing order with the
554 * number of planes available in the image.
556 * This is an internal function used by gst_vaapi_image_new_with_image().
558 * Return value: %TRUE on success
561 _gst_vaapi_image_set_image(GstVaapiImage *image, const VAImage *va_image)
563 GstVaapiImagePrivate * const priv = image->priv;
564 GstVaapiImageFormat format;
565 VAImage alt_va_image;
566 const VAImageFormat *alt_va_format;
571 format = gst_vaapi_image_format(&va_image->format);
575 priv->create_image = FALSE;
576 priv->internal_image = *va_image;
577 priv->internal_format = format;
578 priv->is_linear = vaapi_image_is_linear(va_image);
579 priv->image = *va_image;
580 priv->format = format;
581 priv->width = va_image->width;
582 priv->height = va_image->height;
584 /* Try to linearize image */
585 if (!priv->is_linear) {
587 case GST_VAAPI_IMAGE_I420:
588 format = GST_VAAPI_IMAGE_YV12;
590 case GST_VAAPI_IMAGE_YV12:
591 format = GST_VAAPI_IMAGE_I420;
598 (alt_va_format = gst_vaapi_image_format_get_va_format(format))) {
599 alt_va_image = *va_image;
600 alt_va_image.format = *alt_va_format;
601 SWAP_UINT(alt_va_image.offsets[1], alt_va_image.offsets[2]);
602 SWAP_UINT(alt_va_image.pitches[1], alt_va_image.pitches[2]);
603 if (vaapi_image_is_linear(&alt_va_image)) {
604 priv->image = alt_va_image;
605 priv->format = format;
606 priv->is_linear = TRUE;
607 GST_DEBUG("linearized image to %" GST_FOURCC_FORMAT " format",
608 GST_FOURCC_ARGS(format));
616 * gst_vaapi_image_get_format:
617 * @image: a #GstVaapiImage
619 * Returns the #GstVaapiImageFormat the @image was created with.
621 * Return value: the #GstVaapiImageFormat
624 gst_vaapi_image_get_format(GstVaapiImage *image)
626 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
627 g_return_val_if_fail(image->priv->is_constructed, 0);
629 return image->priv->format;
633 * gst_vaapi_image_get_width:
634 * @image: a #GstVaapiImage
636 * Returns the @image width.
638 * Return value: the image width, in pixels
641 gst_vaapi_image_get_width(GstVaapiImage *image)
643 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
644 g_return_val_if_fail(image->priv->is_constructed, 0);
646 return image->priv->width;
650 * gst_vaapi_image_get_height:
651 * @image: a #GstVaapiImage
653 * Returns the @image height.
655 * Return value: the image height, in pixels.
658 gst_vaapi_image_get_height(GstVaapiImage *image)
660 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
661 g_return_val_if_fail(image->priv->is_constructed, 0);
663 return image->priv->height;
667 * gst_vaapi_image_get_size:
668 * @image: a #GstVaapiImage
669 * @pwidth: return location for the width, or %NULL
670 * @pheight: return location for the height, or %NULL
672 * Retrieves the dimensions of a #GstVaapiImage.
675 gst_vaapi_image_get_size(GstVaapiImage *image, guint *pwidth, guint *pheight)
677 g_return_if_fail(GST_VAAPI_IS_IMAGE(image));
678 g_return_if_fail(image->priv->is_constructed);
681 *pwidth = image->priv->width;
684 *pheight = image->priv->height;
688 * gst_vaapi_image_is_linear:
689 * @image: a #GstVaapiImage
691 * Checks whether the @image has data planes allocated from a single
692 * buffer and offsets into that buffer are in increasing order with
693 * the number of planes.
695 * Return value: %TRUE if image data planes are allocated from a single buffer
698 gst_vaapi_image_is_linear(GstVaapiImage *image)
700 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
701 g_return_val_if_fail(image->priv->is_constructed, FALSE);
703 return image->priv->is_linear;
707 * gst_vaapi_image_is_mapped:
708 * @image: a #GstVaapiImage
710 * Checks whether the @image is currently mapped or not.
712 * Return value: %TRUE if the @image is mapped
714 static inline gboolean
715 _gst_vaapi_image_is_mapped(GstVaapiImage *image)
717 return image->priv->image_data != NULL;
721 gst_vaapi_image_is_mapped(GstVaapiImage *image)
723 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
724 g_return_val_if_fail(image->priv->is_constructed, FALSE);
726 return _gst_vaapi_image_is_mapped(image);
730 * gst_vaapi_image_map:
731 * @image: a #GstVaapiImage
733 * Maps the image data buffer. The actual pixels are returned by the
734 * gst_vaapi_image_get_plane() function.
736 * Return value: %TRUE on success
739 gst_vaapi_image_map(GstVaapiImage *image)
741 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
742 g_return_val_if_fail(image->priv->is_constructed, FALSE);
744 return _gst_vaapi_image_map(image);
748 _gst_vaapi_image_map(GstVaapiImage *image)
750 GstVaapiDisplay *display;
754 if (_gst_vaapi_image_is_mapped(image))
757 display = GST_VAAPI_OBJECT_DISPLAY(image);
761 GST_VAAPI_DISPLAY_LOCK(display);
762 status = vaMapBuffer(
763 GST_VAAPI_DISPLAY_VADISPLAY(display),
764 image->priv->image.buf,
767 GST_VAAPI_DISPLAY_UNLOCK(display);
768 if (!vaapi_check_status(status, "vaMapBuffer()"))
771 image->priv->image_data = image_data;
776 * gst_vaapi_image_unmap:
777 * @image: a #GstVaapiImage
779 * Unmaps the image data buffer. Pointers to pixels returned by
780 * gst_vaapi_image_get_plane() are then no longer valid.
782 * Return value: %TRUE on success
785 gst_vaapi_image_unmap(GstVaapiImage *image)
787 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
788 g_return_val_if_fail(image->priv->is_constructed, FALSE);
790 return _gst_vaapi_image_unmap(image);
794 _gst_vaapi_image_unmap(GstVaapiImage *image)
796 GstVaapiDisplay *display;
799 if (!_gst_vaapi_image_is_mapped(image))
802 display = GST_VAAPI_OBJECT_DISPLAY(image);
806 GST_VAAPI_DISPLAY_LOCK(display);
807 status = vaUnmapBuffer(
808 GST_VAAPI_DISPLAY_VADISPLAY(display),
809 image->priv->image.buf
811 GST_VAAPI_DISPLAY_UNLOCK(display);
812 if (!vaapi_check_status(status, "vaUnmapBuffer()"))
815 image->priv->image_data = NULL;
820 * gst_vaapi_image_get_plane_count:
821 * @image: a #GstVaapiImage
823 * Retrieves the number of planes available in the @image. The @image
824 * must be mapped for this function to work properly.
826 * Return value: the number of planes available in the @image
829 gst_vaapi_image_get_plane_count(GstVaapiImage *image)
831 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
832 g_return_val_if_fail(image->priv->is_constructed, FALSE);
833 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0);
835 return image->priv->image.num_planes;
839 * gst_vaapi_image_get_plane:
840 * @image: a #GstVaapiImage
841 * @plane: the requested plane number
843 * Retrieves the pixels data to the specified @plane. The @image must
844 * be mapped for this function to work properly.
846 * Return value: the pixels data of the specified @plane
849 gst_vaapi_image_get_plane(GstVaapiImage *image, guint plane)
851 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), NULL);
852 g_return_val_if_fail(image->priv->is_constructed, FALSE);
853 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), NULL);
854 g_return_val_if_fail(plane < image->priv->image.num_planes, NULL);
856 return image->priv->image_data + image->priv->image.offsets[plane];
860 * gst_vaapi_image_get_pitch:
861 * @image: a #GstVaapiImage
862 * @plane: the requested plane number
864 * Retrieves the line size (stride) of the specified @plane. The
865 * @image must be mapped for this function to work properly.
867 * Return value: the line size (stride) of the specified plane
870 gst_vaapi_image_get_pitch(GstVaapiImage *image, guint plane)
872 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
873 g_return_val_if_fail(image->priv->is_constructed, FALSE);
874 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0);
875 g_return_val_if_fail(plane < image->priv->image.num_planes, 0);
877 return image->priv->image.pitches[plane];
881 * gst_vaapi_image_get_data_size:
882 * @image: a #GstVaapiImage
884 * Retrieves the underlying image data size. This function could be
885 * used to determine whether the image has a compatible layout with
886 * another image structure.
888 * Return value: the whole image data size of the @image
891 gst_vaapi_image_get_data_size(GstVaapiImage *image)
893 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
894 g_return_val_if_fail(image->priv->is_constructed, FALSE);
896 return image->priv->image.data_size;
900 * gst_vaapi_image_update_from_buffer:
901 * @image: a #GstVaapiImage
902 * @buffer: a #GstBuffer
904 * Transfers pixels data contained in the #GstBuffer into the
905 * @image. Both image structures shall have the same format.
907 * Return value: %TRUE on success
910 gst_vaapi_image_update_from_buffer(GstVaapiImage *image, GstBuffer *buffer)
912 GstVaapiImagePrivate *priv;
913 GstStructure *structure;
915 GstVaapiImageFormat format;
917 guint offsets[3], pitches[3], widths[3], heights[3];
922 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
923 g_return_val_if_fail(image->priv->is_constructed, FALSE);
924 g_return_val_if_fail(GST_IS_BUFFER(buffer), FALSE);
927 data = GST_BUFFER_DATA(buffer);
928 data_size = GST_BUFFER_SIZE(buffer);
929 caps = GST_BUFFER_CAPS(buffer);
934 format = gst_vaapi_image_format_from_caps(caps);
935 if (format != priv->format)
938 structure = gst_caps_get_structure(caps, 0);
939 gst_structure_get_int(structure, "width", &width);
940 gst_structure_get_int(structure, "height", &height);
941 if (width != priv->width || height != priv->height)
944 if (!gst_vaapi_image_map(image))
947 if (priv->is_linear && data_size == priv->image.data_size)
948 memcpy(priv->image_data, data, data_size);
950 /* XXX: copied from gst_video_format_get_row_stride() -- no NV12? */
951 const guint width2 = (width + 1) / 2;
952 const guint height2 = (height + 1) / 2;
955 case GST_VAAPI_IMAGE_NV12:
957 pitches[0] = GST_ROUND_UP_4(width);
960 offsets[1] = offsets[0] + height * pitches[0];
961 pitches[1] = pitches[0];
962 widths [1] = width2 * 2;
963 heights[1] = height2;
964 size2 = offsets[1] + height2 * pitches[1];
966 case GST_VAAPI_IMAGE_YV12:
967 case GST_VAAPI_IMAGE_I420:
969 pitches[0] = GST_ROUND_UP_4(width);
972 offsets[1] = offsets[0] + height * pitches[0];
973 pitches[1] = GST_ROUND_UP_4(GST_ROUND_UP_2(width) / 2);
975 heights[1] = height2;
976 offsets[2] = offsets[1] + height2 * pitches[1];
977 pitches[2] = pitches[1];
979 heights[2] = height2;
980 size2 = offsets[2] + height2 * pitches[2];
982 case GST_VAAPI_IMAGE_ARGB:
983 case GST_VAAPI_IMAGE_RGBA:
984 case GST_VAAPI_IMAGE_ABGR:
985 case GST_VAAPI_IMAGE_BGRA:
987 pitches[0] = width * 4;
988 widths [0] = width * 4;
990 size2 = offsets[0] + height * pitches[0];
993 g_error("could not compute row-stride for %" GST_FOURCC_FORMAT,
994 GST_FOURCC_ARGS(format));
997 if (size2 != data_size)
998 g_error("data_size mismatch %d / %u", size2, data_size);
999 for (i = 0; i < priv->image.num_planes; i++) {
1000 guchar *src = data + offsets[i];
1001 guchar *dst = priv->image_data + priv->image.offsets[i];
1002 for (j = 0; j < heights[i]; j++) {
1003 memcpy(dst, src, widths[i]);
1005 dst += priv->image.pitches[i];
1010 if (!gst_vaapi_image_unmap(image))