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 <va/va_backend.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;
65 #define SWAP_UINT(a, b) do { \
72 _gst_vaapi_image_map(GstVaapiImage *image);
75 _gst_vaapi_image_unmap(GstVaapiImage *image);
78 _gst_vaapi_image_set_image(GstVaapiImage *image, const VAImage *va_image);
84 #define VAAPI_TYPE_IMAGE vaapi_image_get_type()
87 vaapi_image_copy(gpointer va_image)
89 return g_slice_dup(VAImage, va_image);
93 vaapi_image_free(gpointer va_image)
95 if (G_LIKELY(va_image))
96 g_slice_free(VAImage, va_image);
100 vaapi_image_get_type(void)
102 static GType type = 0;
104 if (G_UNLIKELY(type == 0))
105 type = g_boxed_type_register_static(
114 vaapi_image_is_linear(const VAImage *va_image)
116 guint i, width, height, width2, height2, data_size;
118 for (i = 1; i < va_image->num_planes; i++)
119 if (va_image->offsets[i] < va_image->offsets[i - 1])
122 width = va_image->width;
123 height = va_image->height;
124 width2 = (width + 1) / 2;
125 height2 = (height + 1) / 2;
127 switch (va_image->format.fourcc) {
128 case VA_FOURCC('N','V','1','2'):
129 case VA_FOURCC('Y','V','1','2'):
130 case VA_FOURCC('I','4','2','0'):
131 data_size = width * height + 2 * width2 * height2;
133 case VA_FOURCC('A','R','G','B'):
134 case VA_FOURCC('R','G','B','A'):
135 case VA_FOURCC('A','B','G','R'):
136 case VA_FOURCC('B','G','R','A'):
137 data_size = 4 * width * height;
140 g_error("FIXME: incomplete formats");
143 return va_image->data_size == data_size;
147 gst_vaapi_image_destroy(GstVaapiImage *image)
149 GstVaapiDisplay * const display = GST_VAAPI_OBJECT_GET_DISPLAY(image);
150 GstVaapiImagePrivate * const priv = image->priv;
153 _gst_vaapi_image_unmap(image);
155 GST_DEBUG("image 0x%08x", priv->internal_image.image_id);
157 if (priv->internal_image.image_id != VA_INVALID_ID) {
158 GST_VAAPI_DISPLAY_LOCK(display);
159 status = vaDestroyImage(
160 GST_VAAPI_DISPLAY_VADISPLAY(display),
161 priv->internal_image.image_id
163 GST_VAAPI_DISPLAY_UNLOCK(display);
164 if (!vaapi_check_status(status, "vaDestroyImage()"))
165 g_warning("failed to destroy image 0x%08x\n",
166 priv->internal_image.image_id);
167 priv->internal_image.image_id = VA_INVALID_ID;
172 _gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format)
174 GstVaapiDisplay * const display = GST_VAAPI_OBJECT_GET_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;
210 if (!priv->create_image)
211 return (priv->image.image_id != VA_INVALID_ID &&
212 priv->image.buf != VA_INVALID_ID);
214 if (!_gst_vaapi_image_create(image, format)) {
216 case GST_VAAPI_IMAGE_I420:
217 format = GST_VAAPI_IMAGE_YV12;
219 case GST_VAAPI_IMAGE_YV12:
220 format = GST_VAAPI_IMAGE_I420;
226 if (!format || !_gst_vaapi_image_create(image, format))
229 priv->image = priv->internal_image;
231 if (priv->format != priv->internal_format) {
232 switch (priv->format) {
233 case GST_VAAPI_IMAGE_YV12:
234 case GST_VAAPI_IMAGE_I420:
235 va_format = gst_vaapi_image_format_get_va_format(priv->format);
238 priv->image.format = *va_format;
239 SWAP_UINT(priv->image.offsets[1], priv->image.offsets[2]);
240 SWAP_UINT(priv->image.pitches[1], priv->image.pitches[2]);
247 GST_DEBUG("image 0x%08x", priv->image.image_id);
248 priv->is_linear = vaapi_image_is_linear(&priv->image);
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_id(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));
362 * The underlying #VAImageID of the image.
364 g_object_class_install_property
367 g_param_spec_uint("id",
369 "The underlying VA image id",
370 0, G_MAXUINT32, VA_INVALID_ID,
373 g_object_class_install_property
376 g_param_spec_uint("width",
380 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
382 g_object_class_install_property
385 g_param_spec_uint("height",
389 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
392 * GstVaapiImage:format:
394 * The #GstVaapiImageFormat of the image
396 g_object_class_install_property
399 g_param_spec_uint("format",
401 "The underlying image format",
403 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
407 gst_vaapi_image_init(GstVaapiImage *image)
409 GstVaapiImagePrivate *priv = GST_VAAPI_IMAGE_GET_PRIVATE(image);
412 priv->image_data = NULL;
415 priv->internal_format = 0;
417 priv->create_image = TRUE;
418 priv->is_constructed = FALSE;
419 priv->is_linear = FALSE;
421 memset(&priv->internal_image, 0, sizeof(priv->internal_image));
422 priv->internal_image.image_id = VA_INVALID_ID;
423 priv->internal_image.buf = VA_INVALID_ID;
425 memset(&priv->image, 0, sizeof(priv->image));
426 priv->image.image_id = VA_INVALID_ID;
427 priv->image.buf = VA_INVALID_ID;
431 * gst_vaapi_image_new:
432 * @display: a #GstVaapiDisplay
433 * @format: a #GstVaapiImageFormat
434 * @width: the requested image width
435 * @height: the requested image height
437 * Creates a new #GstVaapiImage with the specified format and
440 * Return value: the newly allocated #GstVaapiImage object
444 GstVaapiDisplay *display,
445 GstVaapiImageFormat format,
450 GstVaapiImage *image;
452 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
453 g_return_val_if_fail(width > 0, NULL);
454 g_return_val_if_fail(height > 0, NULL);
456 GST_DEBUG("format %" GST_FOURCC_FORMAT ", size %ux%u",
457 GST_FOURCC_ARGS(format), width, height);
459 image = g_object_new(
460 GST_VAAPI_TYPE_IMAGE,
470 if (!image->priv->is_constructed) {
471 g_object_unref(image);
478 * gst_vaapi_image_new_with_image:
479 * @display: a #GstVaapiDisplay
480 * @va_image: a VA image
482 * Creates a new #GstVaapiImage from a foreign VA image. The image
483 * format and dimensions will be extracted from @va_image. This
484 * function is mainly used by gst_vaapi_surface_derive_image() to bind
485 * a VA image to a #GstVaapiImage object.
487 * Return value: the newly allocated #GstVaapiImage object
490 gst_vaapi_image_new_with_image(GstVaapiDisplay *display, VAImage *va_image)
492 GstVaapiImage *image;
494 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
495 g_return_val_if_fail(va_image, NULL);
496 g_return_val_if_fail(va_image->image_id != VA_INVALID_ID, NULL);
497 g_return_val_if_fail(va_image->buf != VA_INVALID_ID, NULL);
499 GST_DEBUG("VA image 0x%08x, format %" GST_FOURCC_FORMAT ", size %ux%u",
501 GST_FOURCC_ARGS(va_image->format.fourcc),
502 va_image->width, va_image->height);
504 image = g_object_new(
505 GST_VAAPI_TYPE_IMAGE,
513 if (!image->priv->is_constructed) {
514 g_object_unref(image);
521 * gst_vaapi_image_get_id:
522 * @image: a #GstVaapiImage
524 * Returns the underlying VAImageID of the @image.
526 * Return value: the underlying VA image id
529 gst_vaapi_image_get_id(GstVaapiImage *image)
531 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), VA_INVALID_ID);
532 g_return_val_if_fail(image->priv->is_constructed, VA_INVALID_ID);
534 return image->priv->image.image_id;
538 * gst_vaapi_image_get_image:
539 * @image: a #GstVaapiImage
540 * @va_image: a VA image
542 * Fills @va_image with the VA image used internally.
544 * Return value: %TRUE on success
547 gst_vaapi_image_get_image(GstVaapiImage *image, VAImage *va_image)
549 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
550 g_return_val_if_fail(image->priv->is_constructed, FALSE);
553 *va_image = image->priv->image;
559 * _gst_vaapi_image_set_image:
560 * @image: a #GstVaapiImage
561 * @va_image: a VA image
563 * Initializes #GstVaapiImage with a foreign VA image. This function
564 * will try to "linearize" the VA image. i.e. making sure that the VA
565 * image offsets into the data buffer are in increasing order with the
566 * number of planes available in the image.
568 * This is an internal function used by gst_vaapi_image_new_with_image().
570 * Return value: %TRUE on success
573 _gst_vaapi_image_set_image(GstVaapiImage *image, const VAImage *va_image)
575 GstVaapiImagePrivate * const priv = image->priv;
576 GstVaapiImageFormat format;
577 VAImage alt_va_image;
578 const VAImageFormat *alt_va_format;
583 format = gst_vaapi_image_format(&va_image->format);
587 priv->create_image = FALSE;
588 priv->internal_image = *va_image;
589 priv->internal_format = format;
590 priv->is_linear = vaapi_image_is_linear(va_image);
591 priv->image = *va_image;
592 priv->format = format;
593 priv->width = va_image->width;
594 priv->height = va_image->height;
596 /* Try to linearize image */
597 if (!priv->is_linear) {
599 case GST_VAAPI_IMAGE_I420:
600 format = GST_VAAPI_IMAGE_YV12;
602 case GST_VAAPI_IMAGE_YV12:
603 format = GST_VAAPI_IMAGE_I420;
610 (alt_va_format = gst_vaapi_image_format_get_va_format(format))) {
611 alt_va_image = *va_image;
612 alt_va_image.format = *alt_va_format;
613 SWAP_UINT(alt_va_image.offsets[1], alt_va_image.offsets[2]);
614 SWAP_UINT(alt_va_image.pitches[1], alt_va_image.pitches[2]);
615 if (vaapi_image_is_linear(&alt_va_image)) {
616 priv->image = alt_va_image;
617 priv->format = format;
618 priv->is_linear = TRUE;
619 GST_DEBUG("linearized image to %" GST_FOURCC_FORMAT " format",
620 GST_FOURCC_ARGS(format));
628 * gst_vaapi_image_get_format:
629 * @image: a #GstVaapiImage
631 * Returns the #GstVaapiImageFormat the @image was created with.
633 * Return value: the #GstVaapiImageFormat
636 gst_vaapi_image_get_format(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->format;
645 * gst_vaapi_image_get_width:
646 * @image: a #GstVaapiImage
648 * Returns the @image width.
650 * Return value: the image width, in pixels
653 gst_vaapi_image_get_width(GstVaapiImage *image)
655 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
656 g_return_val_if_fail(image->priv->is_constructed, FALSE);
658 return image->priv->width;
662 * gst_vaapi_image_get_height:
663 * @image: a #GstVaapiImage
665 * Returns the @image height.
667 * Return value: the image height, in pixels.
670 gst_vaapi_image_get_height(GstVaapiImage *image)
672 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
673 g_return_val_if_fail(image->priv->is_constructed, FALSE);
675 return image->priv->height;
679 * gst_vaapi_image_get_size:
680 * @image: a #GstVaapiImage
681 * @pwidth: return location for the width, or %NULL
682 * @pheight: return location for the height, or %NULL
684 * Retrieves the dimensions of a #GstVaapiImage.
687 gst_vaapi_image_get_size(GstVaapiImage *image, guint *pwidth, guint *pheight)
689 g_return_if_fail(GST_VAAPI_IS_IMAGE(image));
690 g_return_if_fail(image->priv->is_constructed);
693 *pwidth = image->priv->width;
696 *pheight = image->priv->height;
700 * gst_vaapi_image_is_linear:
701 * @image: a #GstVaapiImage
703 * Checks whether the @image has data planes allocated from a single
704 * buffer and offsets into that buffer are in increasing order with
705 * the number of planes.
707 * Return value: %TRUE if image data planes are allocated from a single buffer
710 gst_vaapi_image_is_linear(GstVaapiImage *image)
712 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
713 g_return_val_if_fail(image->priv->is_constructed, FALSE);
715 return image->priv->is_linear;
719 * gst_vaapi_image_is_mapped:
720 * @image: a #GstVaapiImage
722 * Checks whether the @image is currently mapped or not.
724 * Return value: %TRUE if the @image is mapped
726 static inline gboolean
727 _gst_vaapi_image_is_mapped(GstVaapiImage *image)
729 return image->priv->image_data != NULL;
733 gst_vaapi_image_is_mapped(GstVaapiImage *image)
735 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
736 g_return_val_if_fail(image->priv->is_constructed, FALSE);
738 return _gst_vaapi_image_is_mapped(image);
742 * gst_vaapi_image_map:
743 * @image: a #GstVaapiImage
745 * Maps the image data buffer. The actual pixels are returned by the
746 * gst_vaapi_image_get_plane() function.
748 * Return value: %TRUE on success
751 gst_vaapi_image_map(GstVaapiImage *image)
753 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
754 g_return_val_if_fail(image->priv->is_constructed, FALSE);
756 return _gst_vaapi_image_map(image);
760 _gst_vaapi_image_map(GstVaapiImage *image)
762 GstVaapiDisplay *display;
766 if (_gst_vaapi_image_is_mapped(image))
769 display = GST_VAAPI_OBJECT_GET_DISPLAY(image);
773 GST_VAAPI_DISPLAY_LOCK(display);
774 status = vaMapBuffer(
775 GST_VAAPI_DISPLAY_VADISPLAY(display),
776 image->priv->image.buf,
779 GST_VAAPI_DISPLAY_UNLOCK(display);
780 if (!vaapi_check_status(status, "vaMapBuffer()"))
783 image->priv->image_data = image_data;
788 * gst_vaapi_image_unmap:
789 * @image: a #GstVaapiImage
791 * Unmaps the image data buffer. Pointers to pixels returned by
792 * gst_vaapi_image_get_plane() are then no longer valid.
794 * Return value: %TRUE on success
797 gst_vaapi_image_unmap(GstVaapiImage *image)
799 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
800 g_return_val_if_fail(image->priv->is_constructed, FALSE);
802 return _gst_vaapi_image_unmap(image);
806 _gst_vaapi_image_unmap(GstVaapiImage *image)
808 GstVaapiDisplay *display;
811 if (!_gst_vaapi_image_is_mapped(image))
814 display = GST_VAAPI_OBJECT_GET_DISPLAY(image);
818 GST_VAAPI_DISPLAY_LOCK(display);
819 status = vaUnmapBuffer(
820 GST_VAAPI_DISPLAY_VADISPLAY(display),
821 image->priv->image.buf
823 GST_VAAPI_DISPLAY_UNLOCK(display);
824 if (!vaapi_check_status(status, "vaUnmapBuffer()"))
827 image->priv->image_data = NULL;
832 * gst_vaapi_image_get_plane_count:
833 * @image: a #GstVaapiImage
835 * Retrieves the number of planes available in the @image. The @image
836 * must be mapped for this function to work properly.
838 * Return value: the number of planes available in the @image
841 gst_vaapi_image_get_plane_count(GstVaapiImage *image)
843 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
844 g_return_val_if_fail(image->priv->is_constructed, FALSE);
845 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0);
847 return image->priv->image.num_planes;
851 * gst_vaapi_image_get_plane:
852 * @image: a #GstVaapiImage
853 * @plane: the requested plane number
855 * Retrieves the pixels data to the specified @plane. The @image must
856 * be mapped for this function to work properly.
858 * Return value: the pixels data of the specified @plane
861 gst_vaapi_image_get_plane(GstVaapiImage *image, guint plane)
863 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), NULL);
864 g_return_val_if_fail(image->priv->is_constructed, FALSE);
865 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), NULL);
866 g_return_val_if_fail(plane < image->priv->image.num_planes, NULL);
868 return image->priv->image_data + image->priv->image.offsets[plane];
872 * gst_vaapi_image_get_pitch:
873 * @image: a #GstVaapiImage
874 * @plane: the requested plane number
876 * Retrieves the line size (stride) of the specified @plane. The
877 * @image must be mapped for this function to work properly.
879 * Return value: the line size (stride) of the specified plane
882 gst_vaapi_image_get_pitch(GstVaapiImage *image, guint plane)
884 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
885 g_return_val_if_fail(image->priv->is_constructed, FALSE);
886 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0);
887 g_return_val_if_fail(plane < image->priv->image.num_planes, 0);
889 return image->priv->image.pitches[plane];
893 * gst_vaapi_image_get_data_size:
894 * @image: a #GstVaapiImage
896 * Retrieves the underlying image data size. This function could be
897 * used to determine whether the image has a compatible layout with
898 * another image structure.
900 * Return value: the whole image data size of the @image
903 gst_vaapi_image_get_data_size(GstVaapiImage *image)
905 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
906 g_return_val_if_fail(image->priv->is_constructed, FALSE);
908 return image->priv->image.data_size;
912 * gst_vaapi_image_update_from_buffer:
913 * @image: a #GstVaapiImage
914 * @buffer: a #GstBuffer
916 * Transfers pixels data contained in the #GstBuffer into the
917 * @image. Both image structures shall have the same format.
919 * Return value: %TRUE on success
922 gst_vaapi_image_update_from_buffer(GstVaapiImage *image, GstBuffer *buffer)
924 GstVaapiImagePrivate *priv;
925 GstStructure *structure;
927 GstVaapiImageFormat format;
929 guint offsets[3], pitches[3], widths[3], heights[3];
934 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
935 g_return_val_if_fail(image->priv->is_constructed, FALSE);
936 g_return_val_if_fail(GST_IS_BUFFER(buffer), FALSE);
939 data = GST_BUFFER_DATA(buffer);
940 data_size = GST_BUFFER_SIZE(buffer);
941 caps = GST_BUFFER_CAPS(buffer);
946 format = gst_vaapi_image_format_from_caps(caps);
947 if (format != priv->format)
950 structure = gst_caps_get_structure(caps, 0);
951 gst_structure_get_int(structure, "width", &width);
952 gst_structure_get_int(structure, "height", &height);
953 if (width != priv->width || height != priv->height)
956 if (!gst_vaapi_image_map(image))
959 if (priv->is_linear && data_size == priv->image.data_size)
960 memcpy(priv->image_data, data, data_size);
962 /* XXX: copied from gst_video_format_get_row_stride() -- no NV12? */
963 const guint width2 = (width + 1) / 2;
964 const guint height2 = (height + 1) / 2;
967 case GST_VAAPI_IMAGE_NV12:
969 pitches[0] = GST_ROUND_UP_4(width);
972 offsets[1] = offsets[0] + height * pitches[0];
973 pitches[1] = pitches[0];
974 widths [1] = width2 * 2;
975 heights[1] = height2;
976 size2 = offsets[1] + height2 * pitches[1];
978 case GST_VAAPI_IMAGE_YV12:
979 case GST_VAAPI_IMAGE_I420:
981 pitches[0] = GST_ROUND_UP_4(width);
984 offsets[1] = offsets[0] + height * pitches[0];
985 pitches[1] = GST_ROUND_UP_4(GST_ROUND_UP_2(width) / 2);
987 heights[1] = height2;
988 offsets[2] = offsets[1] + height2 * pitches[1];
989 pitches[2] = pitches[1];
991 heights[2] = height2;
992 size2 = offsets[2] + height2 * pitches[2];
994 case GST_VAAPI_IMAGE_ARGB:
995 case GST_VAAPI_IMAGE_RGBA:
996 case GST_VAAPI_IMAGE_ABGR:
997 case GST_VAAPI_IMAGE_BGRA:
999 pitches[0] = width * 4;
1000 widths [0] = width * 4;
1001 heights[0] = height;
1002 size2 = offsets[0] + height * pitches[0];
1005 g_error("could not compute row-stride for %" GST_FOURCC_FORMAT,
1006 GST_FOURCC_ARGS(format));
1009 if (size2 != data_size)
1010 g_error("data_size mismatch %d / %u", size2, data_size);
1011 for (i = 0; i < priv->image.num_planes; i++) {
1012 guchar *src = data + offsets[i];
1013 guchar *dst = priv->image_data + priv->image.offsets[i];
1014 for (j = 0; j < heights[i]; j++) {
1015 memcpy(dst, src, widths[i]);
1017 dst += priv->image.pitches[i];
1022 if (!gst_vaapi_image_unmap(image))