2 * gstvaapiimage.c - VA image abstraction
4 * Copyright (C) 2010-2011 Splitted-Desktop Systems
5 * Copyright (C) 2011 Intel Corporation
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either version 2.1
10 * of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301 USA
24 * SECTION:gstvaapiimage
25 * @short_description: VA image abstraction
30 #include "gstvaapicompat.h"
31 #include "gstvaapiutils.h"
32 #include "gstvaapiimage.h"
33 #include "gstvaapi_priv.h"
36 #include "gstvaapidebug.h"
38 G_DEFINE_TYPE(GstVaapiImage, gst_vaapi_image, GST_VAAPI_TYPE_OBJECT);
40 #define GST_VAAPI_IMAGE_GET_PRIVATE(obj) \
41 (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
42 GST_VAAPI_TYPE_IMAGE, \
43 GstVaapiImagePrivate))
45 struct _GstVaapiImagePrivate {
46 VAImage internal_image;
49 GstVaapiImageFormat internal_format;
50 GstVaapiImageFormat format;
53 guint create_image : 1;
54 guint is_constructed : 1;
67 #define SWAP_UINT(a, b) do { \
74 _gst_vaapi_image_map(GstVaapiImage *image, GstVaapiImageRaw *raw_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','Y','U','V'):
136 case VA_FOURCC('A','R','G','B'):
137 case VA_FOURCC('R','G','B','A'):
138 case VA_FOURCC('A','B','G','R'):
139 case VA_FOURCC('B','G','R','A'):
140 data_size = 4 * width * height;
143 g_error("FIXME: incomplete formats");
146 return va_image->data_size == data_size;
150 gst_vaapi_image_destroy(GstVaapiImage *image)
152 GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(image);
156 _gst_vaapi_image_unmap(image);
158 image_id = GST_VAAPI_OBJECT_ID(image);
159 GST_DEBUG("image %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(image_id));
161 if (image_id != VA_INVALID_ID) {
162 GST_VAAPI_DISPLAY_LOCK(display);
163 status = vaDestroyImage(GST_VAAPI_DISPLAY_VADISPLAY(display), image_id);
164 GST_VAAPI_DISPLAY_UNLOCK(display);
165 if (!vaapi_check_status(status, "vaDestroyImage()"))
166 g_warning("failed to destroy image %" GST_VAAPI_ID_FORMAT,
167 GST_VAAPI_ID_ARGS(image_id));
168 GST_VAAPI_OBJECT_ID(image) = VA_INVALID_ID;
173 _gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format)
175 GstVaapiDisplay * const display = GST_VAAPI_OBJECT_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;
212 if (!priv->create_image)
213 return (priv->image.image_id != VA_INVALID_ID &&
214 priv->image.buf != VA_INVALID_ID);
216 if (!_gst_vaapi_image_create(image, format)) {
218 case GST_VAAPI_IMAGE_I420:
219 format = GST_VAAPI_IMAGE_YV12;
221 case GST_VAAPI_IMAGE_YV12:
222 format = GST_VAAPI_IMAGE_I420;
228 if (!format || !_gst_vaapi_image_create(image, format))
231 priv->image = priv->internal_image;
232 image_id = priv->image.image_id;
234 if (priv->format != priv->internal_format) {
235 switch (priv->format) {
236 case GST_VAAPI_IMAGE_YV12:
237 case GST_VAAPI_IMAGE_I420:
238 va_format = gst_vaapi_image_format_get_va_format(priv->format);
241 priv->image.format = *va_format;
242 SWAP_UINT(priv->image.offsets[1], priv->image.offsets[2]);
243 SWAP_UINT(priv->image.pitches[1], priv->image.pitches[2]);
249 priv->is_linear = vaapi_image_is_linear(&priv->image);
251 GST_DEBUG("image %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(image_id));
252 GST_VAAPI_OBJECT_ID(image) = image_id;
257 gst_vaapi_image_finalize(GObject *object)
259 gst_vaapi_image_destroy(GST_VAAPI_IMAGE(object));
261 G_OBJECT_CLASS(gst_vaapi_image_parent_class)->finalize(object);
265 gst_vaapi_image_set_property(
272 GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
273 GstVaapiImagePrivate * const priv = image->priv;
277 const VAImage * const va_image = g_value_get_boxed(value);
279 _gst_vaapi_image_set_image(image, va_image);
283 if (priv->create_image)
284 priv->format = g_value_get_uint(value);
287 if (priv->create_image)
288 priv->width = g_value_get_uint(value);
291 if (priv->create_image)
292 priv->height = g_value_get_uint(value);
295 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
301 gst_vaapi_image_get_property(
308 GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
312 g_value_set_boxed(value, &image->priv->image);
315 g_value_set_uint(value, gst_vaapi_image_get_format(image));
318 g_value_set_uint(value, gst_vaapi_image_get_width(image));
321 g_value_set_uint(value, gst_vaapi_image_get_height(image));
324 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
330 gst_vaapi_image_constructed(GObject *object)
332 GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
333 GObjectClass *parent_class;
335 image->priv->is_constructed = gst_vaapi_image_create(image);
337 parent_class = G_OBJECT_CLASS(gst_vaapi_image_parent_class);
338 if (parent_class->constructed)
339 parent_class->constructed(object);
343 gst_vaapi_image_class_init(GstVaapiImageClass *klass)
345 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
347 g_type_class_add_private(klass, sizeof(GstVaapiImagePrivate));
349 object_class->finalize = gst_vaapi_image_finalize;
350 object_class->set_property = gst_vaapi_image_set_property;
351 object_class->get_property = gst_vaapi_image_get_property;
352 object_class->constructed = gst_vaapi_image_constructed;
354 g_object_class_install_property
357 g_param_spec_boxed("image",
359 "The underlying VA image",
361 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
363 g_object_class_install_property
366 g_param_spec_uint("width",
370 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
372 g_object_class_install_property
375 g_param_spec_uint("height",
379 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
382 * GstVaapiImage:format:
384 * The #GstVaapiImageFormat of the image
386 g_object_class_install_property
389 g_param_spec_uint("format",
391 "The underlying image format",
393 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
397 gst_vaapi_image_init(GstVaapiImage *image)
399 GstVaapiImagePrivate *priv = GST_VAAPI_IMAGE_GET_PRIVATE(image);
402 priv->image_data = NULL;
405 priv->internal_format = 0;
407 priv->create_image = TRUE;
408 priv->is_constructed = FALSE;
409 priv->is_linear = FALSE;
411 memset(&priv->internal_image, 0, sizeof(priv->internal_image));
412 priv->internal_image.image_id = VA_INVALID_ID;
413 priv->internal_image.buf = VA_INVALID_ID;
415 memset(&priv->image, 0, sizeof(priv->image));
416 priv->image.image_id = VA_INVALID_ID;
417 priv->image.buf = VA_INVALID_ID;
421 * gst_vaapi_image_new:
422 * @display: a #GstVaapiDisplay
423 * @format: a #GstVaapiImageFormat
424 * @width: the requested image width
425 * @height: the requested image height
427 * Creates a new #GstVaapiImage with the specified format and
430 * Return value: the newly allocated #GstVaapiImage object
434 GstVaapiDisplay *display,
435 GstVaapiImageFormat format,
440 GstVaapiImage *image;
442 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
443 g_return_val_if_fail(width > 0, NULL);
444 g_return_val_if_fail(height > 0, NULL);
446 GST_DEBUG("format %" GST_FOURCC_FORMAT ", size %ux%u",
447 GST_FOURCC_ARGS(format), width, height);
449 image = g_object_new(
450 GST_VAAPI_TYPE_IMAGE,
452 "id", GST_VAAPI_ID(VA_INVALID_ID),
461 if (!image->priv->is_constructed) {
462 g_object_unref(image);
469 * gst_vaapi_image_new_with_image:
470 * @display: a #GstVaapiDisplay
471 * @va_image: a VA image
473 * Creates a new #GstVaapiImage from a foreign VA image. The image
474 * format and dimensions will be extracted from @va_image. This
475 * function is mainly used by gst_vaapi_surface_derive_image() to bind
476 * a VA image to a #GstVaapiImage object.
478 * Return value: the newly allocated #GstVaapiImage object
481 gst_vaapi_image_new_with_image(GstVaapiDisplay *display, VAImage *va_image)
483 GstVaapiImage *image;
485 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
486 g_return_val_if_fail(va_image, NULL);
487 g_return_val_if_fail(va_image->image_id != VA_INVALID_ID, NULL);
488 g_return_val_if_fail(va_image->buf != VA_INVALID_ID, NULL);
490 GST_DEBUG("VA image 0x%08x, format %" GST_FOURCC_FORMAT ", size %ux%u",
492 GST_FOURCC_ARGS(va_image->format.fourcc),
493 va_image->width, va_image->height);
495 image = g_object_new(
496 GST_VAAPI_TYPE_IMAGE,
498 "id", GST_VAAPI_ID(va_image->image_id),
505 if (!image->priv->is_constructed) {
506 g_object_unref(image);
513 * gst_vaapi_image_get_id:
514 * @image: a #GstVaapiImage
516 * Returns the underlying VAImageID of the @image.
518 * Return value: the underlying VA image id
521 gst_vaapi_image_get_id(GstVaapiImage *image)
523 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), VA_INVALID_ID);
524 g_return_val_if_fail(image->priv->is_constructed, VA_INVALID_ID);
526 return GST_VAAPI_OBJECT_ID(image);
530 * gst_vaapi_image_get_image:
531 * @image: a #GstVaapiImage
532 * @va_image: a VA image
534 * Fills @va_image with the VA image used internally.
536 * Return value: %TRUE on success
539 gst_vaapi_image_get_image(GstVaapiImage *image, VAImage *va_image)
541 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
542 g_return_val_if_fail(image->priv->is_constructed, FALSE);
545 *va_image = image->priv->image;
551 * _gst_vaapi_image_set_image:
552 * @image: a #GstVaapiImage
553 * @va_image: a VA image
555 * Initializes #GstVaapiImage with a foreign VA image. This function
556 * will try to "linearize" the VA image. i.e. making sure that the VA
557 * image offsets into the data buffer are in increasing order with the
558 * number of planes available in the image.
560 * This is an internal function used by gst_vaapi_image_new_with_image().
562 * Return value: %TRUE on success
565 _gst_vaapi_image_set_image(GstVaapiImage *image, const VAImage *va_image)
567 GstVaapiImagePrivate * const priv = image->priv;
568 GstVaapiImageFormat format;
569 VAImage alt_va_image;
570 const VAImageFormat *alt_va_format;
575 format = gst_vaapi_image_format(&va_image->format);
579 priv->create_image = FALSE;
580 priv->internal_image = *va_image;
581 priv->internal_format = format;
582 priv->is_linear = vaapi_image_is_linear(va_image);
583 priv->image = *va_image;
584 priv->format = format;
585 priv->width = va_image->width;
586 priv->height = va_image->height;
588 /* Try to linearize image */
589 if (!priv->is_linear) {
591 case GST_VAAPI_IMAGE_I420:
592 format = GST_VAAPI_IMAGE_YV12;
594 case GST_VAAPI_IMAGE_YV12:
595 format = GST_VAAPI_IMAGE_I420;
602 (alt_va_format = gst_vaapi_image_format_get_va_format(format))) {
603 alt_va_image = *va_image;
604 alt_va_image.format = *alt_va_format;
605 SWAP_UINT(alt_va_image.offsets[1], alt_va_image.offsets[2]);
606 SWAP_UINT(alt_va_image.pitches[1], alt_va_image.pitches[2]);
607 if (vaapi_image_is_linear(&alt_va_image)) {
608 priv->image = alt_va_image;
609 priv->format = format;
610 priv->is_linear = TRUE;
611 GST_DEBUG("linearized image to %" GST_FOURCC_FORMAT " format",
612 GST_FOURCC_ARGS(format));
620 * gst_vaapi_image_get_format:
621 * @image: a #GstVaapiImage
623 * Returns the #GstVaapiImageFormat the @image was created with.
625 * Return value: the #GstVaapiImageFormat
628 gst_vaapi_image_get_format(GstVaapiImage *image)
630 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
631 g_return_val_if_fail(image->priv->is_constructed, 0);
633 return image->priv->format;
637 * gst_vaapi_image_get_width:
638 * @image: a #GstVaapiImage
640 * Returns the @image width.
642 * Return value: the image width, in pixels
645 gst_vaapi_image_get_width(GstVaapiImage *image)
647 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
648 g_return_val_if_fail(image->priv->is_constructed, 0);
650 return image->priv->width;
654 * gst_vaapi_image_get_height:
655 * @image: a #GstVaapiImage
657 * Returns the @image height.
659 * Return value: the image height, in pixels.
662 gst_vaapi_image_get_height(GstVaapiImage *image)
664 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
665 g_return_val_if_fail(image->priv->is_constructed, 0);
667 return image->priv->height;
671 * gst_vaapi_image_get_size:
672 * @image: a #GstVaapiImage
673 * @pwidth: return location for the width, or %NULL
674 * @pheight: return location for the height, or %NULL
676 * Retrieves the dimensions of a #GstVaapiImage.
679 gst_vaapi_image_get_size(GstVaapiImage *image, guint *pwidth, guint *pheight)
681 g_return_if_fail(GST_VAAPI_IS_IMAGE(image));
682 g_return_if_fail(image->priv->is_constructed);
685 *pwidth = image->priv->width;
688 *pheight = image->priv->height;
692 * gst_vaapi_image_is_linear:
693 * @image: a #GstVaapiImage
695 * Checks whether the @image has data planes allocated from a single
696 * buffer and offsets into that buffer are in increasing order with
697 * the number of planes.
699 * Return value: %TRUE if image data planes are allocated from a single buffer
702 gst_vaapi_image_is_linear(GstVaapiImage *image)
704 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
705 g_return_val_if_fail(image->priv->is_constructed, FALSE);
707 return image->priv->is_linear;
711 * gst_vaapi_image_is_mapped:
712 * @image: a #GstVaapiImage
714 * Checks whether the @image is currently mapped or not.
716 * Return value: %TRUE if the @image is mapped
718 static inline gboolean
719 _gst_vaapi_image_is_mapped(GstVaapiImage *image)
721 return image->priv->image_data != NULL;
725 gst_vaapi_image_is_mapped(GstVaapiImage *image)
727 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
728 g_return_val_if_fail(image->priv->is_constructed, FALSE);
730 return _gst_vaapi_image_is_mapped(image);
734 * gst_vaapi_image_map:
735 * @image: a #GstVaapiImage
737 * Maps the image data buffer. The actual pixels are returned by the
738 * gst_vaapi_image_get_plane() function.
740 * Return value: %TRUE on success
743 gst_vaapi_image_map(GstVaapiImage *image)
745 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
746 g_return_val_if_fail(image->priv->is_constructed, FALSE);
748 return _gst_vaapi_image_map(image, NULL);
752 _gst_vaapi_image_map(GstVaapiImage *image, GstVaapiImageRaw *raw_image)
754 GstVaapiImagePrivate * const priv = image->priv;
755 GstVaapiDisplay *display;
760 if (_gst_vaapi_image_is_mapped(image))
763 display = GST_VAAPI_OBJECT_DISPLAY(image);
767 GST_VAAPI_DISPLAY_LOCK(display);
768 status = vaMapBuffer(
769 GST_VAAPI_DISPLAY_VADISPLAY(display),
770 image->priv->image.buf,
773 GST_VAAPI_DISPLAY_UNLOCK(display);
774 if (!vaapi_check_status(status, "vaMapBuffer()"))
777 image->priv->image_data = image_data;
780 const VAImage * const va_image = &priv->image;
781 raw_image->format = priv->format;
782 raw_image->width = va_image->width;
783 raw_image->height = va_image->height;
784 raw_image->num_planes = va_image->num_planes;
785 for (i = 0; i < raw_image->num_planes; i++) {
786 raw_image->pixels[i] = image_data + va_image->offsets[i];
787 raw_image->stride[i] = va_image->pitches[i];
794 * gst_vaapi_image_unmap:
795 * @image: a #GstVaapiImage
797 * Unmaps the image data buffer. Pointers to pixels returned by
798 * gst_vaapi_image_get_plane() are then no longer valid.
800 * Return value: %TRUE on success
803 gst_vaapi_image_unmap(GstVaapiImage *image)
805 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
806 g_return_val_if_fail(image->priv->is_constructed, FALSE);
808 return _gst_vaapi_image_unmap(image);
812 _gst_vaapi_image_unmap(GstVaapiImage *image)
814 GstVaapiDisplay *display;
817 if (!_gst_vaapi_image_is_mapped(image))
820 display = GST_VAAPI_OBJECT_DISPLAY(image);
824 GST_VAAPI_DISPLAY_LOCK(display);
825 status = vaUnmapBuffer(
826 GST_VAAPI_DISPLAY_VADISPLAY(display),
827 image->priv->image.buf
829 GST_VAAPI_DISPLAY_UNLOCK(display);
830 if (!vaapi_check_status(status, "vaUnmapBuffer()"))
833 image->priv->image_data = NULL;
838 * gst_vaapi_image_get_plane_count:
839 * @image: a #GstVaapiImage
841 * Retrieves the number of planes available in the @image. The @image
842 * must be mapped for this function to work properly.
844 * Return value: the number of planes available in the @image
847 gst_vaapi_image_get_plane_count(GstVaapiImage *image)
849 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
850 g_return_val_if_fail(image->priv->is_constructed, FALSE);
851 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0);
853 return image->priv->image.num_planes;
857 * gst_vaapi_image_get_plane:
858 * @image: a #GstVaapiImage
859 * @plane: the requested plane number
861 * Retrieves the pixels data to the specified @plane. The @image must
862 * be mapped for this function to work properly.
864 * Return value: the pixels data of the specified @plane
867 gst_vaapi_image_get_plane(GstVaapiImage *image, guint plane)
869 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), NULL);
870 g_return_val_if_fail(image->priv->is_constructed, FALSE);
871 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), NULL);
872 g_return_val_if_fail(plane < image->priv->image.num_planes, NULL);
874 return image->priv->image_data + image->priv->image.offsets[plane];
878 * gst_vaapi_image_get_pitch:
879 * @image: a #GstVaapiImage
880 * @plane: the requested plane number
882 * Retrieves the line size (stride) of the specified @plane. The
883 * @image must be mapped for this function to work properly.
885 * Return value: the line size (stride) of the specified plane
888 gst_vaapi_image_get_pitch(GstVaapiImage *image, guint plane)
890 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
891 g_return_val_if_fail(image->priv->is_constructed, FALSE);
892 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0);
893 g_return_val_if_fail(plane < image->priv->image.num_planes, 0);
895 return image->priv->image.pitches[plane];
899 * gst_vaapi_image_get_data_size:
900 * @image: a #GstVaapiImage
902 * Retrieves the underlying image data size. This function could be
903 * used to determine whether the image has a compatible layout with
904 * another image structure.
906 * Return value: the whole image data size of the @image
909 gst_vaapi_image_get_data_size(GstVaapiImage *image)
911 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
912 g_return_val_if_fail(image->priv->is_constructed, FALSE);
914 return image->priv->image.data_size;
918 init_image_from_buffer(GstVaapiImageRaw *raw_image, GstBuffer *buffer)
920 GstStructure *structure;
922 GstVaapiImageFormat format;
923 guint width2, height2, size2;
928 data = GST_BUFFER_DATA(buffer);
929 data_size = GST_BUFFER_SIZE(buffer);
930 caps = GST_BUFFER_CAPS(buffer);
935 format = gst_vaapi_image_format_from_caps(caps);
937 structure = gst_caps_get_structure(caps, 0);
938 gst_structure_get_int(structure, "width", &width);
939 gst_structure_get_int(structure, "height", &height);
941 /* XXX: copied from gst_video_format_get_row_stride() -- no NV12? */
942 raw_image->format = format;
943 raw_image->width = width;
944 raw_image->height = height;
945 width2 = (width + 1) / 2;
946 height2 = (height + 1) / 2;
949 case GST_VAAPI_IMAGE_NV12:
950 raw_image->num_planes = 2;
951 raw_image->pixels[0] = data;
952 raw_image->stride[0] = GST_ROUND_UP_4(width);
953 size2 += height * raw_image->stride[0];
954 raw_image->pixels[1] = data + size2;
955 raw_image->stride[1] = raw_image->stride[0];
956 size2 += height2 * raw_image->stride[1];
958 case GST_VAAPI_IMAGE_YV12:
959 case GST_VAAPI_IMAGE_I420:
960 raw_image->num_planes = 3;
961 raw_image->pixels[0] = data;
962 raw_image->stride[0] = GST_ROUND_UP_4(width);
963 size2 += height * raw_image->stride[0];
964 raw_image->pixels[1] = data + size2;
965 raw_image->stride[1] = GST_ROUND_UP_4(width2);
966 size2 += height2 * raw_image->stride[1];
967 raw_image->pixels[2] = data + size2;
968 raw_image->stride[2] = raw_image->stride[1];
969 size2 += height2 * raw_image->stride[2];
971 case GST_VAAPI_IMAGE_ARGB:
972 case GST_VAAPI_IMAGE_RGBA:
973 case GST_VAAPI_IMAGE_ABGR:
974 case GST_VAAPI_IMAGE_BGRA:
975 raw_image->num_planes = 1;
976 raw_image->pixels[0] = data;
977 raw_image->stride[0] = width * 4;
978 size2 += height * raw_image->stride[0];
981 g_error("could not compute row-stride for %" GST_FOURCC_FORMAT,
982 GST_FOURCC_ARGS(format));
986 if (size2 != data_size) {
987 g_error("data_size mismatch %d / %u", size2, data_size);
988 if (size2 > data_size)
994 /* Copy N lines of an image */
1007 for (i = 0; i < height; i++) {
1008 memcpy(dst, src, len);
1014 /* Copy NV12 images */
1017 GstVaapiImageRaw *dst_image,
1018 GstVaapiImageRaw *src_image,
1019 const GstVaapiRectangle *rect
1023 guint dst_stride, src_stride;
1026 dst_stride = dst_image->stride[0];
1027 dst = dst_image->pixels[0] + rect->y * dst_stride + rect->x;
1028 src_stride = src_image->stride[0];
1029 src = src_image->pixels[0] + rect->y * src_stride + rect->x;
1030 memcpy_pic(dst, dst_stride, src, src_stride, rect->width, rect->height);
1033 dst_stride = dst_image->stride[1];
1034 dst = dst_image->pixels[1] + (rect->y / 2) * dst_stride + (rect->x & -2);
1035 src_stride = src_image->stride[1];
1036 src = src_image->pixels[1] + (rect->y / 2) * src_stride + (rect->x & -2);
1037 memcpy_pic(dst, dst_stride, src, src_stride, rect->width, rect->height / 2);
1040 /* Copy YV12 images */
1043 GstVaapiImageRaw *dst_image,
1044 GstVaapiImageRaw *src_image,
1045 const GstVaapiRectangle *rect
1049 guint dst_stride, src_stride;
1050 guint i, x, y, w, h;
1053 dst_stride = dst_image->stride[0];
1054 dst = dst_image->pixels[0] + rect->y * dst_stride + rect->x;
1055 src_stride = src_image->stride[0];
1056 src = src_image->pixels[0] + rect->y * src_stride + rect->x;
1057 memcpy_pic(dst, dst_stride, src, src_stride, rect->width, rect->height);
1062 w = rect->width / 2;
1063 h = rect->height / 2;
1064 for (i = 1; i < dst_image->num_planes; i++) {
1065 dst_stride = dst_image->stride[i];
1066 dst = dst_image->pixels[i] + y * dst_stride + x;
1067 src_stride = src_image->stride[i];
1068 src = src_image->pixels[i] + y * src_stride + x;
1069 memcpy_pic(dst, dst_stride, src, src_stride, w, h);
1073 /* Copy RGBA images */
1076 GstVaapiImageRaw *dst_image,
1077 GstVaapiImageRaw *src_image,
1078 const GstVaapiRectangle *rect
1082 guint dst_stride, src_stride;
1084 dst_stride = dst_image->stride[0];
1085 dst = dst_image->pixels[0] + rect->y * dst_stride + rect->x;
1086 src_stride = src_image->stride[0];
1087 src = src_image->pixels[0] + rect->y * src_stride + rect->x;
1088 memcpy_pic(dst, dst_stride, src, src_stride, 4 * rect->width, rect->height);
1093 GstVaapiImageRaw *dst_image,
1094 GstVaapiImageRaw *src_image,
1095 const GstVaapiRectangle *rect
1098 GstVaapiRectangle default_rect;
1100 if (dst_image->format != src_image->format ||
1101 dst_image->width != src_image->width ||
1102 dst_image->height != src_image->height)
1106 if (rect->x >= src_image->width ||
1107 rect->x + src_image->width > src_image->width ||
1108 rect->y >= src_image->height ||
1109 rect->y + src_image->height > src_image->height)
1115 default_rect.width = src_image->width;
1116 default_rect.height = src_image->height;
1117 rect = &default_rect;
1120 switch (dst_image->format) {
1121 case GST_VAAPI_IMAGE_NV12:
1122 copy_image_NV12(dst_image, src_image, rect);
1124 case GST_VAAPI_IMAGE_YV12:
1125 case GST_VAAPI_IMAGE_I420:
1126 copy_image_YV12(dst_image, src_image, rect);
1128 case GST_VAAPI_IMAGE_ARGB:
1129 case GST_VAAPI_IMAGE_RGBA:
1130 case GST_VAAPI_IMAGE_ABGR:
1131 case GST_VAAPI_IMAGE_BGRA:
1132 copy_image_RGBA(dst_image, src_image, rect);
1135 GST_ERROR("unsupported image format for copy");
1142 * gst_vaapi_image_get_buffer:
1143 * @image: a #GstVaapiImage
1144 * @buffer: a #GstBuffer
1145 * @rect: a #GstVaapiRectangle expressing a region, or %NULL for the
1148 * Transfers pixels data contained in the @image into the #GstBuffer.
1149 * Both image structures shall have the same format.
1151 * Return value: %TRUE on success
1154 gst_vaapi_image_get_buffer(
1155 GstVaapiImage *image,
1157 GstVaapiRectangle *rect
1160 GstVaapiImagePrivate *priv;
1161 GstVaapiImageRaw dst_image, src_image;
1164 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
1165 g_return_val_if_fail(image->priv->is_constructed, FALSE);
1166 g_return_val_if_fail(GST_IS_BUFFER(buffer), FALSE);
1170 if (!init_image_from_buffer(&dst_image, buffer))
1172 if (dst_image.format != priv->format)
1174 if (dst_image.width != priv->width || dst_image.height != priv->height)
1177 if (!_gst_vaapi_image_map(image, &src_image))
1180 success = copy_image(&dst_image, &src_image, rect);
1182 if (!_gst_vaapi_image_unmap(image))
1189 * gst_vaapi_image_get_raw:
1190 * @image: a #GstVaapiImage
1191 * @dst_image: a #GstVaapiImageRaw
1192 * @buffer: a #GstBuffer
1193 * @rect: a #GstVaapiRectangle expressing a region, or %NULL for the
1196 * Transfers pixels data contained in the @image into the #GstVaapiImageRaw.
1197 * Both image structures shall have the same format.
1199 * Return value: %TRUE on success
1202 gst_vaapi_image_get_raw(
1203 GstVaapiImage *image,
1204 GstVaapiImageRaw *dst_image,
1205 GstVaapiRectangle *rect
1208 GstVaapiImageRaw src_image;
1211 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
1212 g_return_val_if_fail(image->priv->is_constructed, FALSE);
1214 if (!_gst_vaapi_image_map(image, &src_image))
1217 success = copy_image(dst_image, &src_image, rect);
1219 if (!_gst_vaapi_image_unmap(image))
1226 * gst_vaapi_image_update_from_buffer:
1227 * @image: a #GstVaapiImage
1228 * @buffer: a #GstBuffer
1229 * @rect: a #GstVaapiRectangle expressing a region, or %NULL for the
1232 * Transfers pixels data contained in the #GstBuffer into the
1233 * @image. Both image structures shall have the same format.
1235 * Return value: %TRUE on success
1238 gst_vaapi_image_update_from_buffer(
1239 GstVaapiImage *image,
1241 GstVaapiRectangle *rect
1244 GstVaapiImagePrivate *priv;
1245 GstVaapiImageRaw dst_image, src_image;
1248 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
1249 g_return_val_if_fail(image->priv->is_constructed, FALSE);
1250 g_return_val_if_fail(GST_IS_BUFFER(buffer), FALSE);
1254 if (!init_image_from_buffer(&src_image, buffer))
1256 if (src_image.format != priv->format)
1258 if (src_image.width != priv->width || src_image.height != priv->height)
1261 if (!_gst_vaapi_image_map(image, &dst_image))
1264 success = copy_image(&dst_image, &src_image, rect);
1266 if (!_gst_vaapi_image_unmap(image))
1273 * gst_vaapi_image_update_from_raw:
1274 * @image: a #GstVaapiImage
1275 * @src_image: a #GstVaapiImageRaw
1276 * @buffer: a #GstBuffer
1277 * @rect: a #GstVaapiRectangle expressing a region, or %NULL for the
1280 * Transfers pixels data contained in the #GstVaapiImageRaw into the
1281 * @image. Both image structures shall have the same format.
1283 * Return value: %TRUE on success
1286 gst_vaapi_image_update_from_raw(
1287 GstVaapiImage *image,
1288 GstVaapiImageRaw *src_image,
1289 GstVaapiRectangle *rect
1292 GstVaapiImageRaw dst_image;
1295 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
1296 g_return_val_if_fail(image->priv->is_constructed, FALSE);
1298 if (!_gst_vaapi_image_map(image, &dst_image))
1301 success = copy_image(&dst_image, src_image, rect);
1303 if (!_gst_vaapi_image_unmap(image))