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','Y','U','V'):
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);
153 _gst_vaapi_image_unmap(image);
155 image_id = GST_VAAPI_OBJECT_ID(image);
156 GST_DEBUG("image %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(image_id));
158 if (image_id != VA_INVALID_ID) {
159 GST_VAAPI_DISPLAY_LOCK(display);
160 status = vaDestroyImage(GST_VAAPI_DISPLAY_VADISPLAY(display), image_id);
161 GST_VAAPI_DISPLAY_UNLOCK(display);
162 if (!vaapi_check_status(status, "vaDestroyImage()"))
163 g_warning("failed to destroy image %" GST_VAAPI_ID_FORMAT,
164 GST_VAAPI_ID_ARGS(image_id));
165 GST_VAAPI_OBJECT_ID(image) = VA_INVALID_ID;
170 _gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format)
172 GstVaapiDisplay * const display = GST_VAAPI_OBJECT_GET_DISPLAY(image);
173 GstVaapiImagePrivate * const priv = image->priv;
174 const VAImageFormat *va_format;
177 if (!gst_vaapi_display_has_image_format(display, format))
180 va_format = gst_vaapi_image_format_get_va_format(format);
184 GST_VAAPI_DISPLAY_LOCK(display);
185 status = vaCreateImage(
186 GST_VAAPI_DISPLAY_VADISPLAY(display),
187 (VAImageFormat *)va_format,
190 &priv->internal_image
192 GST_VAAPI_DISPLAY_UNLOCK(display);
193 if (status != VA_STATUS_SUCCESS ||
194 priv->internal_image.format.fourcc != va_format->fourcc)
197 priv->internal_format = format;
202 gst_vaapi_image_create(GstVaapiImage *image)
204 GstVaapiImagePrivate * const priv = image->priv;
205 GstVaapiImageFormat format = priv->format;
206 const VAImageFormat *va_format;
209 if (!priv->create_image)
210 return (priv->image.image_id != VA_INVALID_ID &&
211 priv->image.buf != VA_INVALID_ID);
213 if (!_gst_vaapi_image_create(image, format)) {
215 case GST_VAAPI_IMAGE_I420:
216 format = GST_VAAPI_IMAGE_YV12;
218 case GST_VAAPI_IMAGE_YV12:
219 format = GST_VAAPI_IMAGE_I420;
225 if (!format || !_gst_vaapi_image_create(image, format))
228 priv->image = priv->internal_image;
229 image_id = priv->image.image_id;
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]);
246 priv->is_linear = vaapi_image_is_linear(&priv->image);
248 GST_DEBUG("image %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(image_id));
249 GST_VAAPI_OBJECT_ID(image) = image_id;
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_format(image));
312 g_value_set_uint(value, gst_vaapi_image_get_width(image));
315 g_value_set_uint(value, gst_vaapi_image_get_height(image));
318 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
324 gst_vaapi_image_constructed(GObject *object)
326 GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
327 GObjectClass *parent_class;
329 image->priv->is_constructed = gst_vaapi_image_create(image);
331 parent_class = G_OBJECT_CLASS(gst_vaapi_image_parent_class);
332 if (parent_class->constructed)
333 parent_class->constructed(object);
337 gst_vaapi_image_class_init(GstVaapiImageClass *klass)
339 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
341 g_type_class_add_private(klass, sizeof(GstVaapiImagePrivate));
343 object_class->finalize = gst_vaapi_image_finalize;
344 object_class->set_property = gst_vaapi_image_set_property;
345 object_class->get_property = gst_vaapi_image_get_property;
346 object_class->constructed = gst_vaapi_image_constructed;
348 g_object_class_install_property
351 g_param_spec_boxed("image",
353 "The underlying VA image",
355 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
357 g_object_class_install_property
360 g_param_spec_uint("width",
364 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
366 g_object_class_install_property
369 g_param_spec_uint("height",
373 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
376 * GstVaapiImage:format:
378 * The #GstVaapiImageFormat of the image
380 g_object_class_install_property
383 g_param_spec_uint("format",
385 "The underlying image format",
387 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
391 gst_vaapi_image_init(GstVaapiImage *image)
393 GstVaapiImagePrivate *priv = GST_VAAPI_IMAGE_GET_PRIVATE(image);
396 priv->image_data = NULL;
399 priv->internal_format = 0;
401 priv->create_image = TRUE;
402 priv->is_constructed = FALSE;
403 priv->is_linear = FALSE;
405 memset(&priv->internal_image, 0, sizeof(priv->internal_image));
406 priv->internal_image.image_id = VA_INVALID_ID;
407 priv->internal_image.buf = VA_INVALID_ID;
409 memset(&priv->image, 0, sizeof(priv->image));
410 priv->image.image_id = VA_INVALID_ID;
411 priv->image.buf = VA_INVALID_ID;
415 * gst_vaapi_image_new:
416 * @display: a #GstVaapiDisplay
417 * @format: a #GstVaapiImageFormat
418 * @width: the requested image width
419 * @height: the requested image height
421 * Creates a new #GstVaapiImage with the specified format and
424 * Return value: the newly allocated #GstVaapiImage object
428 GstVaapiDisplay *display,
429 GstVaapiImageFormat format,
434 GstVaapiImage *image;
436 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
437 g_return_val_if_fail(width > 0, NULL);
438 g_return_val_if_fail(height > 0, NULL);
440 GST_DEBUG("format %" GST_FOURCC_FORMAT ", size %ux%u",
441 GST_FOURCC_ARGS(format), width, height);
443 image = g_object_new(
444 GST_VAAPI_TYPE_IMAGE,
454 if (!image->priv->is_constructed) {
455 g_object_unref(image);
462 * gst_vaapi_image_new_with_image:
463 * @display: a #GstVaapiDisplay
464 * @va_image: a VA image
466 * Creates a new #GstVaapiImage from a foreign VA image. The image
467 * format and dimensions will be extracted from @va_image. This
468 * function is mainly used by gst_vaapi_surface_derive_image() to bind
469 * a VA image to a #GstVaapiImage object.
471 * Return value: the newly allocated #GstVaapiImage object
474 gst_vaapi_image_new_with_image(GstVaapiDisplay *display, VAImage *va_image)
476 GstVaapiImage *image;
478 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
479 g_return_val_if_fail(va_image, NULL);
480 g_return_val_if_fail(va_image->image_id != VA_INVALID_ID, NULL);
481 g_return_val_if_fail(va_image->buf != VA_INVALID_ID, NULL);
483 GST_DEBUG("VA image 0x%08x, format %" GST_FOURCC_FORMAT ", size %ux%u",
485 GST_FOURCC_ARGS(va_image->format.fourcc),
486 va_image->width, va_image->height);
488 image = g_object_new(
489 GST_VAAPI_TYPE_IMAGE,
497 if (!image->priv->is_constructed) {
498 g_object_unref(image);
505 * gst_vaapi_image_get_image:
506 * @image: a #GstVaapiImage
507 * @va_image: a VA image
509 * Fills @va_image with the VA image used internally.
511 * Return value: %TRUE on success
514 gst_vaapi_image_get_image(GstVaapiImage *image, VAImage *va_image)
516 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
517 g_return_val_if_fail(image->priv->is_constructed, FALSE);
520 *va_image = image->priv->image;
526 * _gst_vaapi_image_set_image:
527 * @image: a #GstVaapiImage
528 * @va_image: a VA image
530 * Initializes #GstVaapiImage with a foreign VA image. This function
531 * will try to "linearize" the VA image. i.e. making sure that the VA
532 * image offsets into the data buffer are in increasing order with the
533 * number of planes available in the image.
535 * This is an internal function used by gst_vaapi_image_new_with_image().
537 * Return value: %TRUE on success
540 _gst_vaapi_image_set_image(GstVaapiImage *image, const VAImage *va_image)
542 GstVaapiImagePrivate * const priv = image->priv;
543 GstVaapiImageFormat format;
544 VAImage alt_va_image;
545 const VAImageFormat *alt_va_format;
550 format = gst_vaapi_image_format(&va_image->format);
554 priv->create_image = FALSE;
555 priv->internal_image = *va_image;
556 priv->internal_format = format;
557 priv->is_linear = vaapi_image_is_linear(va_image);
558 priv->image = *va_image;
559 priv->format = format;
560 priv->width = va_image->width;
561 priv->height = va_image->height;
563 /* Try to linearize image */
564 if (!priv->is_linear) {
566 case GST_VAAPI_IMAGE_I420:
567 format = GST_VAAPI_IMAGE_YV12;
569 case GST_VAAPI_IMAGE_YV12:
570 format = GST_VAAPI_IMAGE_I420;
577 (alt_va_format = gst_vaapi_image_format_get_va_format(format))) {
578 alt_va_image = *va_image;
579 alt_va_image.format = *alt_va_format;
580 SWAP_UINT(alt_va_image.offsets[1], alt_va_image.offsets[2]);
581 SWAP_UINT(alt_va_image.pitches[1], alt_va_image.pitches[2]);
582 if (vaapi_image_is_linear(&alt_va_image)) {
583 priv->image = alt_va_image;
584 priv->format = format;
585 priv->is_linear = TRUE;
586 GST_DEBUG("linearized image to %" GST_FOURCC_FORMAT " format",
587 GST_FOURCC_ARGS(format));
595 * gst_vaapi_image_get_format:
596 * @image: a #GstVaapiImage
598 * Returns the #GstVaapiImageFormat the @image was created with.
600 * Return value: the #GstVaapiImageFormat
603 gst_vaapi_image_get_format(GstVaapiImage *image)
605 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
606 g_return_val_if_fail(image->priv->is_constructed, FALSE);
608 return image->priv->format;
612 * gst_vaapi_image_get_width:
613 * @image: a #GstVaapiImage
615 * Returns the @image width.
617 * Return value: the image width, in pixels
620 gst_vaapi_image_get_width(GstVaapiImage *image)
622 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
623 g_return_val_if_fail(image->priv->is_constructed, FALSE);
625 return image->priv->width;
629 * gst_vaapi_image_get_height:
630 * @image: a #GstVaapiImage
632 * Returns the @image height.
634 * Return value: the image height, in pixels.
637 gst_vaapi_image_get_height(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->height;
646 * gst_vaapi_image_get_size:
647 * @image: a #GstVaapiImage
648 * @pwidth: return location for the width, or %NULL
649 * @pheight: return location for the height, or %NULL
651 * Retrieves the dimensions of a #GstVaapiImage.
654 gst_vaapi_image_get_size(GstVaapiImage *image, guint *pwidth, guint *pheight)
656 g_return_if_fail(GST_VAAPI_IS_IMAGE(image));
657 g_return_if_fail(image->priv->is_constructed);
660 *pwidth = image->priv->width;
663 *pheight = image->priv->height;
667 * gst_vaapi_image_is_linear:
668 * @image: a #GstVaapiImage
670 * Checks whether the @image has data planes allocated from a single
671 * buffer and offsets into that buffer are in increasing order with
672 * the number of planes.
674 * Return value: %TRUE if image data planes are allocated from a single buffer
677 gst_vaapi_image_is_linear(GstVaapiImage *image)
679 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
680 g_return_val_if_fail(image->priv->is_constructed, FALSE);
682 return image->priv->is_linear;
686 * gst_vaapi_image_is_mapped:
687 * @image: a #GstVaapiImage
689 * Checks whether the @image is currently mapped or not.
691 * Return value: %TRUE if the @image is mapped
693 static inline gboolean
694 _gst_vaapi_image_is_mapped(GstVaapiImage *image)
696 return image->priv->image_data != NULL;
700 gst_vaapi_image_is_mapped(GstVaapiImage *image)
702 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
703 g_return_val_if_fail(image->priv->is_constructed, FALSE);
705 return _gst_vaapi_image_is_mapped(image);
709 * gst_vaapi_image_map:
710 * @image: a #GstVaapiImage
712 * Maps the image data buffer. The actual pixels are returned by the
713 * gst_vaapi_image_get_plane() function.
715 * Return value: %TRUE on success
718 gst_vaapi_image_map(GstVaapiImage *image)
720 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
721 g_return_val_if_fail(image->priv->is_constructed, FALSE);
723 return _gst_vaapi_image_map(image);
727 _gst_vaapi_image_map(GstVaapiImage *image)
729 GstVaapiDisplay *display;
733 if (_gst_vaapi_image_is_mapped(image))
736 display = GST_VAAPI_OBJECT_GET_DISPLAY(image);
740 GST_VAAPI_DISPLAY_LOCK(display);
741 status = vaMapBuffer(
742 GST_VAAPI_DISPLAY_VADISPLAY(display),
743 image->priv->image.buf,
746 GST_VAAPI_DISPLAY_UNLOCK(display);
747 if (!vaapi_check_status(status, "vaMapBuffer()"))
750 image->priv->image_data = image_data;
755 * gst_vaapi_image_unmap:
756 * @image: a #GstVaapiImage
758 * Unmaps the image data buffer. Pointers to pixels returned by
759 * gst_vaapi_image_get_plane() are then no longer valid.
761 * Return value: %TRUE on success
764 gst_vaapi_image_unmap(GstVaapiImage *image)
766 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
767 g_return_val_if_fail(image->priv->is_constructed, FALSE);
769 return _gst_vaapi_image_unmap(image);
773 _gst_vaapi_image_unmap(GstVaapiImage *image)
775 GstVaapiDisplay *display;
778 if (!_gst_vaapi_image_is_mapped(image))
781 display = GST_VAAPI_OBJECT_GET_DISPLAY(image);
785 GST_VAAPI_DISPLAY_LOCK(display);
786 status = vaUnmapBuffer(
787 GST_VAAPI_DISPLAY_VADISPLAY(display),
788 image->priv->image.buf
790 GST_VAAPI_DISPLAY_UNLOCK(display);
791 if (!vaapi_check_status(status, "vaUnmapBuffer()"))
794 image->priv->image_data = NULL;
799 * gst_vaapi_image_get_plane_count:
800 * @image: a #GstVaapiImage
802 * Retrieves the number of planes available in the @image. The @image
803 * must be mapped for this function to work properly.
805 * Return value: the number of planes available in the @image
808 gst_vaapi_image_get_plane_count(GstVaapiImage *image)
810 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
811 g_return_val_if_fail(image->priv->is_constructed, FALSE);
812 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0);
814 return image->priv->image.num_planes;
818 * gst_vaapi_image_get_plane:
819 * @image: a #GstVaapiImage
820 * @plane: the requested plane number
822 * Retrieves the pixels data to the specified @plane. The @image must
823 * be mapped for this function to work properly.
825 * Return value: the pixels data of the specified @plane
828 gst_vaapi_image_get_plane(GstVaapiImage *image, guint plane)
830 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), NULL);
831 g_return_val_if_fail(image->priv->is_constructed, FALSE);
832 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), NULL);
833 g_return_val_if_fail(plane < image->priv->image.num_planes, NULL);
835 return image->priv->image_data + image->priv->image.offsets[plane];
839 * gst_vaapi_image_get_pitch:
840 * @image: a #GstVaapiImage
841 * @plane: the requested plane number
843 * Retrieves the line size (stride) of the specified @plane. The
844 * @image must be mapped for this function to work properly.
846 * Return value: the line size (stride) of the specified plane
849 gst_vaapi_image_get_pitch(GstVaapiImage *image, guint plane)
851 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
852 g_return_val_if_fail(image->priv->is_constructed, FALSE);
853 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0);
854 g_return_val_if_fail(plane < image->priv->image.num_planes, 0);
856 return image->priv->image.pitches[plane];
860 * gst_vaapi_image_get_data_size:
861 * @image: a #GstVaapiImage
863 * Retrieves the underlying image data size. This function could be
864 * used to determine whether the image has a compatible layout with
865 * another image structure.
867 * Return value: the whole image data size of the @image
870 gst_vaapi_image_get_data_size(GstVaapiImage *image)
872 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
873 g_return_val_if_fail(image->priv->is_constructed, FALSE);
875 return image->priv->image.data_size;
879 * gst_vaapi_image_update_from_buffer:
880 * @image: a #GstVaapiImage
881 * @buffer: a #GstBuffer
883 * Transfers pixels data contained in the #GstBuffer into the
884 * @image. Both image structures shall have the same format.
886 * Return value: %TRUE on success
889 gst_vaapi_image_update_from_buffer(GstVaapiImage *image, GstBuffer *buffer)
891 GstVaapiImagePrivate *priv;
892 GstStructure *structure;
894 GstVaapiImageFormat format;
896 guint offsets[3], pitches[3], widths[3], heights[3];
901 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
902 g_return_val_if_fail(image->priv->is_constructed, FALSE);
903 g_return_val_if_fail(GST_IS_BUFFER(buffer), FALSE);
906 data = GST_BUFFER_DATA(buffer);
907 data_size = GST_BUFFER_SIZE(buffer);
908 caps = GST_BUFFER_CAPS(buffer);
913 format = gst_vaapi_image_format_from_caps(caps);
914 if (format != priv->format)
917 structure = gst_caps_get_structure(caps, 0);
918 gst_structure_get_int(structure, "width", &width);
919 gst_structure_get_int(structure, "height", &height);
920 if (width != priv->width || height != priv->height)
923 if (!gst_vaapi_image_map(image))
926 if (priv->is_linear && data_size == priv->image.data_size)
927 memcpy(priv->image_data, data, data_size);
929 /* XXX: copied from gst_video_format_get_row_stride() -- no NV12? */
930 const guint width2 = (width + 1) / 2;
931 const guint height2 = (height + 1) / 2;
934 case GST_VAAPI_IMAGE_NV12:
936 pitches[0] = GST_ROUND_UP_4(width);
939 offsets[1] = offsets[0] + height * pitches[0];
940 pitches[1] = pitches[0];
941 widths [1] = width2 * 2;
942 heights[1] = height2;
943 size2 = offsets[1] + height2 * pitches[1];
945 case GST_VAAPI_IMAGE_YV12:
946 case GST_VAAPI_IMAGE_I420:
948 pitches[0] = GST_ROUND_UP_4(width);
951 offsets[1] = offsets[0] + height * pitches[0];
952 pitches[1] = GST_ROUND_UP_4(GST_ROUND_UP_2(width) / 2);
954 heights[1] = height2;
955 offsets[2] = offsets[1] + height2 * pitches[1];
956 pitches[2] = pitches[1];
958 heights[2] = height2;
959 size2 = offsets[2] + height2 * pitches[2];
961 case GST_VAAPI_IMAGE_ARGB:
962 case GST_VAAPI_IMAGE_RGBA:
963 case GST_VAAPI_IMAGE_ABGR:
964 case GST_VAAPI_IMAGE_BGRA:
966 pitches[0] = width * 4;
967 widths [0] = width * 4;
969 size2 = offsets[0] + height * pitches[0];
972 g_error("could not compute row-stride for %" GST_FOURCC_FORMAT,
973 GST_FOURCC_ARGS(format));
976 if (size2 != data_size)
977 g_error("data_size mismatch %d / %u", size2, data_size);
978 for (i = 0; i < priv->image.num_planes; i++) {
979 guchar *src = data + offsets[i];
980 guchar *dst = priv->image_data + priv->image.offsets[i];
981 for (j = 0; j < heights[i]; j++) {
982 memcpy(dst, src, widths[i]);
984 dst += priv->image.pitches[i];
989 if (!gst_vaapi_image_unmap(image))