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:gst-vaapi-image
28 #include "gstvaapiutils.h"
29 #include "gstvaapiimage.h"
30 #include <va/va_backend.h>
33 #include "gstvaapidebug.h"
35 G_DEFINE_TYPE(GstVaapiImage, gst_vaapi_image, G_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 GstVaapiDisplay *display;
44 VAImage internal_image;
47 GstVaapiImageFormat internal_format;
48 GstVaapiImageFormat format;
51 guint create_image : 1;
52 guint is_constructed : 1;
67 #define SWAP_UINT(a, b) do { \
74 _gst_vaapi_image_map(GstVaapiImage *image);
77 _gst_vaapi_image_unmap(GstVaapiImage *image);
80 _gst_vaapi_image_set_image(GstVaapiImage *image, const VAImage *va_image);
86 #define VAAPI_TYPE_IMAGE vaapi_image_get_type()
89 vaapi_image_copy(gpointer va_image)
91 return g_slice_dup(VAImage, va_image);
95 vaapi_image_free(gpointer va_image)
97 if (G_LIKELY(va_image))
98 g_slice_free(VAImage, va_image);
102 vaapi_image_get_type(void)
104 static GType type = 0;
106 if (G_UNLIKELY(type == 0))
107 type = g_boxed_type_register_static(
116 vaapi_image_is_linear(const VAImage *va_image)
118 guint i, width, height, width2, height2, data_size;
120 for (i = 1; i < va_image->num_planes; i++)
121 if (va_image->offsets[i] < va_image->offsets[i - 1])
124 width = va_image->width;
125 height = va_image->height;
126 width2 = (width + 1) / 2;
127 height2 = (height + 1) / 2;
129 switch (va_image->format.fourcc) {
130 case VA_FOURCC('N','V','1','2'):
131 case VA_FOURCC('Y','V','1','2'):
132 case VA_FOURCC('I','4','2','0'):
133 data_size = width * height + 2 * width2 * height2;
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 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(priv->display);
160 status = vaDestroyImage(
161 GST_VAAPI_DISPLAY_VADISPLAY(priv->display),
162 priv->internal_image.image_id
164 GST_VAAPI_DISPLAY_UNLOCK(priv->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;
172 g_object_unref(priv->display);
173 priv->display = NULL;
178 _gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format)
180 GstVaapiImagePrivate * const priv = image->priv;
181 const VAImageFormat *va_format;
184 if (!gst_vaapi_display_has_image_format(priv->display, format))
187 va_format = gst_vaapi_image_format_get_va_format(format);
191 GST_VAAPI_DISPLAY_LOCK(priv->display);
192 status = vaCreateImage(
193 GST_VAAPI_DISPLAY_VADISPLAY(priv->display),
194 (VAImageFormat *)va_format,
197 &priv->internal_image
199 GST_VAAPI_DISPLAY_UNLOCK(priv->display);
200 if (status != VA_STATUS_SUCCESS ||
201 priv->internal_image.format.fourcc != va_format->fourcc)
204 priv->internal_format = format;
209 gst_vaapi_image_create(GstVaapiImage *image)
211 GstVaapiImagePrivate * const priv = image->priv;
212 GstVaapiImageFormat format = priv->format;
213 const VAImageFormat *va_format;
215 if (!priv->create_image)
216 return (priv->image.image_id != VA_INVALID_ID &&
217 priv->image.buf != VA_INVALID_ID);
219 if (!_gst_vaapi_image_create(image, format)) {
221 case GST_VAAPI_IMAGE_I420:
222 format = GST_VAAPI_IMAGE_YV12;
224 case GST_VAAPI_IMAGE_YV12:
225 format = GST_VAAPI_IMAGE_I420;
231 if (!format || !_gst_vaapi_image_create(image, format))
234 priv->image = priv->internal_image;
236 if (priv->format != priv->internal_format) {
237 switch (priv->format) {
238 case GST_VAAPI_IMAGE_YV12:
239 case GST_VAAPI_IMAGE_I420:
240 va_format = gst_vaapi_image_format_get_va_format(priv->format);
243 priv->image.format = *va_format;
244 SWAP_UINT(priv->image.offsets[1], priv->image.offsets[2]);
245 SWAP_UINT(priv->image.pitches[1], priv->image.pitches[2]);
252 GST_DEBUG("image 0x%08x", priv->image.image_id);
253 priv->is_linear = vaapi_image_is_linear(&priv->image);
258 gst_vaapi_image_finalize(GObject *object)
260 gst_vaapi_image_destroy(GST_VAAPI_IMAGE(object));
262 G_OBJECT_CLASS(gst_vaapi_image_parent_class)->finalize(object);
266 gst_vaapi_image_set_property(
273 GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
274 GstVaapiImagePrivate * const priv = image->priv;
278 priv->display = g_object_ref(g_value_get_object(value));
281 const VAImage * const va_image = g_value_get_boxed(value);
283 _gst_vaapi_image_set_image(image, va_image);
287 priv->format = g_value_get_uint(value);
290 priv->width = g_value_get_uint(value);
293 priv->height = g_value_get_uint(value);
296 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
302 gst_vaapi_image_get_property(
309 GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
313 g_value_set_pointer(value, gst_vaapi_image_get_display(image));
316 g_value_set_boxed(value, &image->priv->image);
319 g_value_set_uint(value, gst_vaapi_image_get_id(image));
322 g_value_set_uint(value, gst_vaapi_image_get_format(image));
325 g_value_set_uint(value, gst_vaapi_image_get_width(image));
328 g_value_set_uint(value, gst_vaapi_image_get_height(image));
331 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
337 gst_vaapi_image_constructed(GObject *object)
339 GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
340 GObjectClass *parent_class;
342 image->priv->is_constructed = gst_vaapi_image_create(image);
344 parent_class = G_OBJECT_CLASS(gst_vaapi_image_parent_class);
345 if (parent_class->constructed)
346 parent_class->constructed(object);
350 gst_vaapi_image_class_init(GstVaapiImageClass *klass)
352 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
354 g_type_class_add_private(klass, sizeof(GstVaapiImagePrivate));
356 object_class->finalize = gst_vaapi_image_finalize;
357 object_class->set_property = gst_vaapi_image_set_property;
358 object_class->get_property = gst_vaapi_image_get_property;
359 object_class->constructed = gst_vaapi_image_constructed;
362 * GstVaapiImage:display:
364 * The #GstVaapiDisplay this image is bound to.
366 g_object_class_install_property
369 g_param_spec_object("display",
371 "The GstVaapiDisplay this image is bound to",
372 GST_VAAPI_TYPE_DISPLAY,
373 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
375 g_object_class_install_property
378 g_param_spec_boxed("image",
380 "The underlying VA image",
382 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
387 * The underlying #VAImageID of the image.
389 g_object_class_install_property
392 g_param_spec_uint("id",
394 "The underlying VA image id",
395 0, G_MAXUINT32, VA_INVALID_ID,
398 g_object_class_install_property
401 g_param_spec_uint("width",
405 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
407 g_object_class_install_property
410 g_param_spec_uint("height",
414 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
417 * GstVaapiImage:format:
419 * The #GstVaapiImageFormat of the image
421 g_object_class_install_property
424 g_param_spec_uint("format",
426 "The underlying image format",
428 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
432 gst_vaapi_image_init(GstVaapiImage *image)
434 GstVaapiImagePrivate *priv = GST_VAAPI_IMAGE_GET_PRIVATE(image);
437 priv->display = NULL;
438 priv->image_data = NULL;
441 priv->internal_format = 0;
443 priv->create_image = TRUE;
444 priv->is_constructed = FALSE;
445 priv->is_linear = FALSE;
447 memset(&priv->internal_image, 0, sizeof(priv->internal_image));
448 priv->internal_image.image_id = VA_INVALID_ID;
449 priv->internal_image.buf = VA_INVALID_ID;
451 memset(&priv->image, 0, sizeof(priv->image));
452 priv->image.image_id = VA_INVALID_ID;
453 priv->image.buf = VA_INVALID_ID;
457 * gst_vaapi_image_new:
458 * @display: a #GstVaapiDisplay
459 * @format: a #GstVaapiImageFormat
460 * @width: the requested image width
461 * @height: the requested image height
463 * Creates a new #GstVaapiImage with the specified format and
466 * Return value: the newly allocated #GstVaapiImage object
470 GstVaapiDisplay *display,
471 GstVaapiImageFormat format,
476 GstVaapiImage *image;
478 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
479 g_return_val_if_fail(width > 0, NULL);
480 g_return_val_if_fail(height > 0, NULL);
482 GST_DEBUG("format %" GST_FOURCC_FORMAT ", size %ux%u",
483 GST_FOURCC_ARGS(format), width, height);
485 image = g_object_new(
486 GST_VAAPI_TYPE_IMAGE,
496 if (!image->priv->is_constructed) {
497 g_object_unref(image);
504 * gst_vaapi_image_new_with_image:
505 * @display: a #GstVaapiDisplay
506 * @va_image: a VA image
508 * Creates a new #GstVaapiImage from a foreign VA image. The image
509 * format and dimensions will be extracted from @va_image. This
510 * function is mainly used by gst_vaapi_surface_derive_image() to bind
511 * a VA image to a #GstVaapiImage object.
513 * Return value: the newly allocated #GstVaapiImage object
516 gst_vaapi_image_new_with_image(GstVaapiDisplay *display, VAImage *va_image)
518 GstVaapiImage *image;
520 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
521 g_return_val_if_fail(va_image, NULL);
522 g_return_val_if_fail(va_image->image_id != VA_INVALID_ID, NULL);
523 g_return_val_if_fail(va_image->buf != VA_INVALID_ID, NULL);
525 GST_DEBUG("VA image 0x%08x, format %" GST_FOURCC_FORMAT ", size %ux%u",
527 GST_FOURCC_ARGS(va_image->format.fourcc),
528 va_image->width, va_image->height);
530 image = g_object_new(
531 GST_VAAPI_TYPE_IMAGE,
539 if (!image->priv->is_constructed) {
540 g_object_unref(image);
547 * gst_vaapi_image_get_id:
548 * @image: a #GstVaapiImage
550 * Returns the underlying VAImageID of the @image.
552 * Return value: the underlying VA image id
555 gst_vaapi_image_get_id(GstVaapiImage *image)
557 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), VA_INVALID_ID);
558 g_return_val_if_fail(image->priv->is_constructed, VA_INVALID_ID);
560 return image->priv->image.image_id;
564 * gst_vaapi_image_get_image:
565 * @image: a #GstVaapiImage
566 * @va_image: (output): a VA image
568 * Fills @va_image with the VA image used internally.
570 * Return value: %TRUE on success
573 gst_vaapi_image_get_image(GstVaapiImage *image, VAImage *va_image)
575 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
576 g_return_val_if_fail(image->priv->is_constructed, FALSE);
579 *va_image = image->priv->image;
585 * _gst_vaapi_image_set_image:
586 * @image: a #GstVaapiImage
587 * @va_image: a VA image
589 * Initializes #GstVaapiImage with a foreign VA image. This function
590 * will try to "linearize" the VA image. i.e. making sure that the VA
591 * image offsets into the data buffer are in increasing order with the
592 * number of planes available in the image.
594 * This is an internal function used by gst_vaapi_image_new_with_image().
596 * Return value: %TRUE on success
599 _gst_vaapi_image_set_image(GstVaapiImage *image, const VAImage *va_image)
601 GstVaapiImagePrivate * const priv = image->priv;
602 GstVaapiImageFormat format;
603 VAImage alt_va_image;
604 const VAImageFormat *alt_va_format;
609 format = gst_vaapi_image_format(&va_image->format);
613 priv->create_image = FALSE;
614 priv->internal_image = *va_image;
615 priv->internal_format = format;
616 priv->is_linear = vaapi_image_is_linear(va_image);
617 priv->image = *va_image;
618 priv->format = format;
619 priv->width = va_image->width;
620 priv->height = va_image->height;
622 /* Try to linearize image */
623 if (!priv->is_linear) {
625 case GST_VAAPI_IMAGE_I420:
626 format = GST_VAAPI_IMAGE_YV12;
628 case GST_VAAPI_IMAGE_YV12:
629 format = GST_VAAPI_IMAGE_I420;
636 (alt_va_format = gst_vaapi_image_format_get_va_format(format))) {
637 alt_va_image = *va_image;
638 alt_va_image.format = *alt_va_format;
639 SWAP_UINT(alt_va_image.offsets[1], alt_va_image.offsets[2]);
640 SWAP_UINT(alt_va_image.pitches[1], alt_va_image.pitches[2]);
641 if (vaapi_image_is_linear(&alt_va_image)) {
642 priv->image = alt_va_image;
643 priv->format = format;
644 priv->is_linear = TRUE;
645 GST_DEBUG("linearized image to %" GST_FOURCC_FORMAT " format",
646 GST_FOURCC_ARGS(format));
654 * gst_vaapi_image_get_display:
655 * @image: a #GstVaapiImage
657 * Returns the #GstVaapiDisplay this @image is bound to.
659 * Return value: the parent #GstVaapiDisplay object
662 gst_vaapi_image_get_display(GstVaapiImage *image)
664 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), NULL);
665 g_return_val_if_fail(image->priv->is_constructed, FALSE);
667 return image->priv->display;
671 * gst_vaapi_image_get_format:
672 * @image: a #GstVaapiImage
674 * Returns the #GstVaapiImageFormat the @image was created with.
676 * Return value: the #GstVaapiImageFormat
679 gst_vaapi_image_get_format(GstVaapiImage *image)
681 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
682 g_return_val_if_fail(image->priv->is_constructed, FALSE);
684 return image->priv->format;
688 * gst_vaapi_image_get_width:
689 * @image: a #GstVaapiImage
691 * Returns the @image width.
693 * Return value: the image width, in pixels
696 gst_vaapi_image_get_width(GstVaapiImage *image)
698 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
699 g_return_val_if_fail(image->priv->is_constructed, FALSE);
701 return image->priv->width;
705 * gst_vaapi_image_get_height:
706 * @image: a #GstVaapiImage
708 * Returns the @image height.
710 * Return value: the image height, in pixels.
713 gst_vaapi_image_get_height(GstVaapiImage *image)
715 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
716 g_return_val_if_fail(image->priv->is_constructed, FALSE);
718 return image->priv->height;
722 * gst_vaapi_image_get_size:
723 * @image: a #GstVaapiImage
724 * @pwidth: (out) (allow-none): return location for the width, or %NULL
725 * @pheight: (out) (allow-none): return location for the height, or %NULL
727 * Retrieves the dimensions of a #GstVaapiImage.
730 gst_vaapi_image_get_size(GstVaapiImage *image, guint *pwidth, guint *pheight)
732 g_return_if_fail(GST_VAAPI_IS_IMAGE(image));
733 g_return_if_fail(image->priv->is_constructed);
736 *pwidth = image->priv->width;
739 *pheight = image->priv->height;
743 * gst_vaapi_image_is_linear:
744 * @image: a #GstVaapiImage
746 * Checks whether the @image has data planes allocated from a single
747 * buffer and offsets into that buffer are in increasing order with
748 * the number of planes.
750 * Return value: %TRUE if image data planes are allocated from a single buffer
753 gst_vaapi_image_is_linear(GstVaapiImage *image)
755 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
756 g_return_val_if_fail(image->priv->is_constructed, FALSE);
758 return image->priv->is_linear;
762 * gst_vaapi_image_is_mapped:
763 * @image: a #GstVaapiImage
765 * Checks whether the @image is currently mapped or not.
767 * Return value: %TRUE if the @image is mapped
769 static inline gboolean
770 _gst_vaapi_image_is_mapped(GstVaapiImage *image)
772 return image->priv->image_data != NULL;
776 gst_vaapi_image_is_mapped(GstVaapiImage *image)
778 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
779 g_return_val_if_fail(image->priv->is_constructed, FALSE);
781 return _gst_vaapi_image_is_mapped(image);
785 * gst_vaapi_image_map:
786 * @image: a #GstVaapiImage
788 * Maps the image data buffer. The actual pixels are returned by the
789 * gst_vaapi_image_get_plane() function.
791 * Return value: %TRUE on success
794 gst_vaapi_image_map(GstVaapiImage *image)
796 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
797 g_return_val_if_fail(image->priv->is_constructed, FALSE);
799 return _gst_vaapi_image_map(image);
803 _gst_vaapi_image_map(GstVaapiImage *image)
808 if (_gst_vaapi_image_is_mapped(image))
811 GST_VAAPI_DISPLAY_LOCK(image->priv->display);
812 status = vaMapBuffer(
813 GST_VAAPI_DISPLAY_VADISPLAY(image->priv->display),
814 image->priv->image.buf,
817 GST_VAAPI_DISPLAY_UNLOCK(image->priv->display);
818 if (!vaapi_check_status(status, "vaMapBuffer()"))
821 image->priv->image_data = image_data;
826 * gst_vaapi_image_unmap:
827 * @image: a #GstVaapiImage
829 * Unmaps the image data buffer. Pointers to pixels returned by
830 * gst_vaapi_image_get_plane() are then no longer valid.
832 * Return value: %TRUE on success
835 gst_vaapi_image_unmap(GstVaapiImage *image)
837 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
838 g_return_val_if_fail(image->priv->is_constructed, FALSE);
840 return _gst_vaapi_image_unmap(image);
844 _gst_vaapi_image_unmap(GstVaapiImage *image)
848 if (!_gst_vaapi_image_is_mapped(image))
851 GST_VAAPI_DISPLAY_LOCK(image->priv->display);
852 status = vaUnmapBuffer(
853 GST_VAAPI_DISPLAY_VADISPLAY(image->priv->display),
854 image->priv->image.buf
856 GST_VAAPI_DISPLAY_UNLOCK(image->priv->display);
857 if (!vaapi_check_status(status, "vaUnmapBuffer()"))
860 image->priv->image_data = NULL;
865 * gst_vaapi_image_get_plane_count:
866 * @image: a #GstVaapiImage
868 * Retrieves the number of planes available in the @image. The @image
869 * must be mapped for this function to work properly.
871 * Return value: the number of planes available in the @image
874 gst_vaapi_image_get_plane_count(GstVaapiImage *image)
876 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
877 g_return_val_if_fail(image->priv->is_constructed, FALSE);
878 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0);
880 return image->priv->image.num_planes;
884 * gst_vaapi_image_get_plane:
885 * @image: a #GstVaapiImage
886 * @plane: the requested plane number
888 * Retrieves the pixels data to the specified @plane. The @image must
889 * be mapped for this function to work properly.
891 * Return value: the pixels data of the specified @plane
894 gst_vaapi_image_get_plane(GstVaapiImage *image, guint plane)
896 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), NULL);
897 g_return_val_if_fail(image->priv->is_constructed, FALSE);
898 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), NULL);
899 g_return_val_if_fail(plane < image->priv->image.num_planes, NULL);
901 return image->priv->image_data + image->priv->image.offsets[plane];
905 * gst_vaapi_image_get_pitch:
906 * @image: a #GstVaapiImage
907 * @plane: the requested plane number
909 * Retrieves the line size (stride) of the specified @plane. The
910 * @image must be mapped for this function to work properly.
912 * Return value: the line size (stride) of the specified plane
915 gst_vaapi_image_get_pitch(GstVaapiImage *image, guint plane)
917 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
918 g_return_val_if_fail(image->priv->is_constructed, FALSE);
919 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0);
920 g_return_val_if_fail(plane < image->priv->image.num_planes, 0);
922 return image->priv->image.pitches[plane];
926 * gst_vaapi_image_get_data_size:
927 * @image: a #GstVaapiImage
929 * Retrieves the underlying image data size. This function could be
930 * used to determine whether the image has a compatible layout with
931 * another image structure.
933 * Return value: the whole image data size of the @image
936 gst_vaapi_image_get_data_size(GstVaapiImage *image)
938 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
939 g_return_val_if_fail(image->priv->is_constructed, FALSE);
941 return image->priv->image.data_size;
945 * gst_vaapi_image_update_from_buffer:
946 * @image: a #GstVaapiImage
947 * @buffer: a #GstBuffer
949 * Transfers pixels data contained in the #GstBuffer into the
950 * @image. Both image structures shall have the same format.
952 * Return value: %TRUE on success
955 gst_vaapi_image_update_from_buffer(GstVaapiImage *image, GstBuffer *buffer)
957 GstVaapiImagePrivate *priv;
958 GstStructure *structure;
960 GstVaapiImageFormat format;
962 guint offsets[3], pitches[3], widths[3], heights[3];
967 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
968 g_return_val_if_fail(image->priv->is_constructed, FALSE);
969 g_return_val_if_fail(GST_IS_BUFFER(buffer), FALSE);
972 data = GST_BUFFER_DATA(buffer);
973 data_size = GST_BUFFER_SIZE(buffer);
974 caps = GST_BUFFER_CAPS(buffer);
979 format = gst_vaapi_image_format_from_caps(caps);
980 if (format != priv->format)
983 structure = gst_caps_get_structure(caps, 0);
984 gst_structure_get_int(structure, "width", &width);
985 gst_structure_get_int(structure, "height", &height);
986 if (width != priv->width || height != priv->height)
989 if (!gst_vaapi_image_map(image))
992 if (priv->is_linear && data_size == priv->image.data_size)
993 memcpy(priv->image_data, data, data_size);
995 /* XXX: copied from gst_video_format_get_row_stride() -- no NV12? */
996 const guint width2 = (width + 1) / 2;
997 const guint height2 = (height + 1) / 2;
1000 case GST_VAAPI_IMAGE_NV12:
1002 pitches[0] = GST_ROUND_UP_4(width);
1004 heights[0] = height;
1005 offsets[1] = offsets[0] + height * pitches[0];
1006 pitches[1] = pitches[0];
1007 widths [1] = width2 * 2;
1008 heights[1] = height2;
1009 size2 = offsets[1] + height2 * pitches[1];
1011 case GST_VAAPI_IMAGE_YV12:
1012 case GST_VAAPI_IMAGE_I420:
1014 pitches[0] = GST_ROUND_UP_4(width);
1016 heights[0] = height;
1017 offsets[1] = offsets[0] + height * pitches[0];
1018 pitches[1] = GST_ROUND_UP_4(GST_ROUND_UP_2(width) / 2);
1019 widths [1] = width2;
1020 heights[1] = height2;
1021 offsets[2] = offsets[1] + height2 * pitches[1];
1022 pitches[2] = pitches[1];
1023 widths [2] = width2;
1024 heights[2] = height2;
1025 size2 = offsets[2] + height2 * pitches[2];
1027 case GST_VAAPI_IMAGE_ARGB:
1028 case GST_VAAPI_IMAGE_RGBA:
1029 case GST_VAAPI_IMAGE_ABGR:
1030 case GST_VAAPI_IMAGE_BGRA:
1032 pitches[0] = width * 4;
1033 widths [0] = width * 4;
1034 heights[0] = height;
1035 size2 = offsets[0] + height * pitches[0];
1038 g_error("could not compute row-stride for %" GST_FOURCC_FORMAT,
1039 GST_FOURCC_ARGS(format));
1042 if (size2 != data_size)
1043 g_error("data_size mismatch %d / %u", size2, data_size);
1044 for (i = 0; i < priv->image.num_planes; i++) {
1045 guchar *src = data + offsets[i];
1046 guchar *dst = priv->image_data + priv->image.offsets[i];
1047 for (j = 0; j < heights[i]; j++) {
1048 memcpy(dst, src, widths[i]);
1050 dst += priv->image.pitches[i];
1055 if (!gst_vaapi_image_unmap(image))