2 * gstvaapiimage.c - VA image abstraction
4 * gstreamer-vaapi (C) 2010-2011 Splitted-Desktop Systems
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 2.1
9 * of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
23 * SECTION:gstvaapiimage
24 * @short_description: VA image abstraction
29 #include "gstvaapicompat.h"
30 #include "gstvaapiutils.h"
31 #include "gstvaapiimage.h"
32 #include "gstvaapi_priv.h"
35 #include "gstvaapidebug.h"
37 G_DEFINE_TYPE(GstVaapiImage, gst_vaapi_image, GST_VAAPI_TYPE_OBJECT);
39 #define GST_VAAPI_IMAGE_GET_PRIVATE(obj) \
40 (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
41 GST_VAAPI_TYPE_IMAGE, \
42 GstVaapiImagePrivate))
44 struct _GstVaapiImagePrivate {
45 VAImage internal_image;
48 GstVaapiImageFormat internal_format;
49 GstVaapiImageFormat format;
52 guint create_image : 1;
53 guint is_constructed : 1;
66 #define SWAP_UINT(a, b) do { \
73 _gst_vaapi_image_map(GstVaapiImage *image, GstVaapiImageRaw *raw_image);
76 _gst_vaapi_image_unmap(GstVaapiImage *image);
79 _gst_vaapi_image_set_image(GstVaapiImage *image, const VAImage *va_image);
85 #define VAAPI_TYPE_IMAGE vaapi_image_get_type()
88 vaapi_image_copy(gpointer va_image)
90 return g_slice_dup(VAImage, va_image);
94 vaapi_image_free(gpointer va_image)
96 if (G_LIKELY(va_image))
97 g_slice_free(VAImage, va_image);
101 vaapi_image_get_type(void)
103 static GType type = 0;
105 if (G_UNLIKELY(type == 0))
106 type = g_boxed_type_register_static(
115 vaapi_image_is_linear(const VAImage *va_image)
117 guint i, width, height, width2, height2, data_size;
119 for (i = 1; i < va_image->num_planes; i++)
120 if (va_image->offsets[i] < va_image->offsets[i - 1])
123 width = va_image->width;
124 height = va_image->height;
125 width2 = (width + 1) / 2;
126 height2 = (height + 1) / 2;
128 switch (va_image->format.fourcc) {
129 case VA_FOURCC('N','V','1','2'):
130 case VA_FOURCC('Y','V','1','2'):
131 case VA_FOURCC('I','4','2','0'):
132 data_size = width * height + 2 * width2 * height2;
134 case VA_FOURCC('A','Y','U','V'):
135 case VA_FOURCC('A','R','G','B'):
136 case VA_FOURCC('R','G','B','A'):
137 case VA_FOURCC('A','B','G','R'):
138 case VA_FOURCC('B','G','R','A'):
139 data_size = 4 * width * height;
142 g_error("FIXME: incomplete formats");
145 return va_image->data_size == data_size;
149 gst_vaapi_image_destroy(GstVaapiImage *image)
151 GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(image);
155 _gst_vaapi_image_unmap(image);
157 image_id = GST_VAAPI_OBJECT_ID(image);
158 GST_DEBUG("image %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(image_id));
160 if (image_id != VA_INVALID_ID) {
161 GST_VAAPI_DISPLAY_LOCK(display);
162 status = vaDestroyImage(GST_VAAPI_DISPLAY_VADISPLAY(display), image_id);
163 GST_VAAPI_DISPLAY_UNLOCK(display);
164 if (!vaapi_check_status(status, "vaDestroyImage()"))
165 g_warning("failed to destroy image %" GST_VAAPI_ID_FORMAT,
166 GST_VAAPI_ID_ARGS(image_id));
167 GST_VAAPI_OBJECT_ID(image) = VA_INVALID_ID;
172 _gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format)
174 GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(image);
175 GstVaapiImagePrivate * const priv = image->priv;
176 const VAImageFormat *va_format;
179 if (!gst_vaapi_display_has_image_format(display, format))
182 va_format = gst_vaapi_image_format_get_va_format(format);
186 GST_VAAPI_DISPLAY_LOCK(display);
187 status = vaCreateImage(
188 GST_VAAPI_DISPLAY_VADISPLAY(display),
189 (VAImageFormat *)va_format,
192 &priv->internal_image
194 GST_VAAPI_DISPLAY_UNLOCK(display);
195 if (status != VA_STATUS_SUCCESS ||
196 priv->internal_image.format.fourcc != va_format->fourcc)
199 priv->internal_format = format;
204 gst_vaapi_image_create(GstVaapiImage *image)
206 GstVaapiImagePrivate * const priv = image->priv;
207 GstVaapiImageFormat format = priv->format;
208 const VAImageFormat *va_format;
211 if (!priv->create_image)
212 return (priv->image.image_id != VA_INVALID_ID &&
213 priv->image.buf != VA_INVALID_ID);
215 if (!_gst_vaapi_image_create(image, format)) {
217 case GST_VAAPI_IMAGE_I420:
218 format = GST_VAAPI_IMAGE_YV12;
220 case GST_VAAPI_IMAGE_YV12:
221 format = GST_VAAPI_IMAGE_I420;
227 if (!format || !_gst_vaapi_image_create(image, format))
230 priv->image = priv->internal_image;
231 image_id = priv->image.image_id;
233 if (priv->format != priv->internal_format) {
234 switch (priv->format) {
235 case GST_VAAPI_IMAGE_YV12:
236 case GST_VAAPI_IMAGE_I420:
237 va_format = gst_vaapi_image_format_get_va_format(priv->format);
240 priv->image.format = *va_format;
241 SWAP_UINT(priv->image.offsets[1], priv->image.offsets[2]);
242 SWAP_UINT(priv->image.pitches[1], priv->image.pitches[2]);
248 priv->is_linear = vaapi_image_is_linear(&priv->image);
250 GST_DEBUG("image %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(image_id));
251 GST_VAAPI_OBJECT_ID(image) = image_id;
256 gst_vaapi_image_finalize(GObject *object)
258 gst_vaapi_image_destroy(GST_VAAPI_IMAGE(object));
260 G_OBJECT_CLASS(gst_vaapi_image_parent_class)->finalize(object);
264 gst_vaapi_image_set_property(
271 GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
272 GstVaapiImagePrivate * const priv = image->priv;
276 const VAImage * const va_image = g_value_get_boxed(value);
278 _gst_vaapi_image_set_image(image, va_image);
282 if (priv->create_image)
283 priv->format = g_value_get_uint(value);
286 if (priv->create_image)
287 priv->width = g_value_get_uint(value);
290 if (priv->create_image)
291 priv->height = g_value_get_uint(value);
294 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
300 gst_vaapi_image_get_property(
307 GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
311 g_value_set_boxed(value, &image->priv->image);
314 g_value_set_uint(value, gst_vaapi_image_get_format(image));
317 g_value_set_uint(value, gst_vaapi_image_get_width(image));
320 g_value_set_uint(value, gst_vaapi_image_get_height(image));
323 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
329 gst_vaapi_image_constructed(GObject *object)
331 GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
332 GObjectClass *parent_class;
334 image->priv->is_constructed = gst_vaapi_image_create(image);
336 parent_class = G_OBJECT_CLASS(gst_vaapi_image_parent_class);
337 if (parent_class->constructed)
338 parent_class->constructed(object);
342 gst_vaapi_image_class_init(GstVaapiImageClass *klass)
344 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
346 g_type_class_add_private(klass, sizeof(GstVaapiImagePrivate));
348 object_class->finalize = gst_vaapi_image_finalize;
349 object_class->set_property = gst_vaapi_image_set_property;
350 object_class->get_property = gst_vaapi_image_get_property;
351 object_class->constructed = gst_vaapi_image_constructed;
353 g_object_class_install_property
356 g_param_spec_boxed("image",
358 "The underlying VA image",
360 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
362 g_object_class_install_property
365 g_param_spec_uint("width",
369 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
371 g_object_class_install_property
374 g_param_spec_uint("height",
378 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
381 * GstVaapiImage:format:
383 * The #GstVaapiImageFormat of the image
385 g_object_class_install_property
388 g_param_spec_uint("format",
390 "The underlying image format",
392 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
396 gst_vaapi_image_init(GstVaapiImage *image)
398 GstVaapiImagePrivate *priv = GST_VAAPI_IMAGE_GET_PRIVATE(image);
401 priv->image_data = NULL;
404 priv->internal_format = 0;
406 priv->create_image = TRUE;
407 priv->is_constructed = FALSE;
408 priv->is_linear = FALSE;
410 memset(&priv->internal_image, 0, sizeof(priv->internal_image));
411 priv->internal_image.image_id = VA_INVALID_ID;
412 priv->internal_image.buf = VA_INVALID_ID;
414 memset(&priv->image, 0, sizeof(priv->image));
415 priv->image.image_id = VA_INVALID_ID;
416 priv->image.buf = VA_INVALID_ID;
420 * gst_vaapi_image_new:
421 * @display: a #GstVaapiDisplay
422 * @format: a #GstVaapiImageFormat
423 * @width: the requested image width
424 * @height: the requested image height
426 * Creates a new #GstVaapiImage with the specified format and
429 * Return value: the newly allocated #GstVaapiImage object
433 GstVaapiDisplay *display,
434 GstVaapiImageFormat format,
439 GstVaapiImage *image;
441 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
442 g_return_val_if_fail(width > 0, NULL);
443 g_return_val_if_fail(height > 0, NULL);
445 GST_DEBUG("format %" GST_FOURCC_FORMAT ", size %ux%u",
446 GST_FOURCC_ARGS(format), width, height);
448 image = g_object_new(
449 GST_VAAPI_TYPE_IMAGE,
451 "id", GST_VAAPI_ID(VA_INVALID_ID),
460 if (!image->priv->is_constructed) {
461 g_object_unref(image);
468 * gst_vaapi_image_new_with_image:
469 * @display: a #GstVaapiDisplay
470 * @va_image: a VA image
472 * Creates a new #GstVaapiImage from a foreign VA image. The image
473 * format and dimensions will be extracted from @va_image. This
474 * function is mainly used by gst_vaapi_surface_derive_image() to bind
475 * a VA image to a #GstVaapiImage object.
477 * Return value: the newly allocated #GstVaapiImage object
480 gst_vaapi_image_new_with_image(GstVaapiDisplay *display, VAImage *va_image)
482 GstVaapiImage *image;
484 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
485 g_return_val_if_fail(va_image, NULL);
486 g_return_val_if_fail(va_image->image_id != VA_INVALID_ID, NULL);
487 g_return_val_if_fail(va_image->buf != VA_INVALID_ID, NULL);
489 GST_DEBUG("VA image 0x%08x, format %" GST_FOURCC_FORMAT ", size %ux%u",
491 GST_FOURCC_ARGS(va_image->format.fourcc),
492 va_image->width, va_image->height);
494 image = g_object_new(
495 GST_VAAPI_TYPE_IMAGE,
497 "id", GST_VAAPI_ID(va_image->image_id),
504 if (!image->priv->is_constructed) {
505 g_object_unref(image);
512 * gst_vaapi_image_get_id:
513 * @image: a #GstVaapiImage
515 * Returns the underlying VAImageID of the @image.
517 * Return value: the underlying VA image id
520 gst_vaapi_image_get_id(GstVaapiImage *image)
522 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), VA_INVALID_ID);
523 g_return_val_if_fail(image->priv->is_constructed, VA_INVALID_ID);
525 return GST_VAAPI_OBJECT_ID(image);
529 * gst_vaapi_image_get_image:
530 * @image: a #GstVaapiImage
531 * @va_image: a VA image
533 * Fills @va_image with the VA image used internally.
535 * Return value: %TRUE on success
538 gst_vaapi_image_get_image(GstVaapiImage *image, VAImage *va_image)
540 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
541 g_return_val_if_fail(image->priv->is_constructed, FALSE);
544 *va_image = image->priv->image;
550 * _gst_vaapi_image_set_image:
551 * @image: a #GstVaapiImage
552 * @va_image: a VA image
554 * Initializes #GstVaapiImage with a foreign VA image. This function
555 * will try to "linearize" the VA image. i.e. making sure that the VA
556 * image offsets into the data buffer are in increasing order with the
557 * number of planes available in the image.
559 * This is an internal function used by gst_vaapi_image_new_with_image().
561 * Return value: %TRUE on success
564 _gst_vaapi_image_set_image(GstVaapiImage *image, const VAImage *va_image)
566 GstVaapiImagePrivate * const priv = image->priv;
567 GstVaapiImageFormat format;
568 VAImage alt_va_image;
569 const VAImageFormat *alt_va_format;
574 format = gst_vaapi_image_format(&va_image->format);
578 priv->create_image = FALSE;
579 priv->internal_image = *va_image;
580 priv->internal_format = format;
581 priv->is_linear = vaapi_image_is_linear(va_image);
582 priv->image = *va_image;
583 priv->format = format;
584 priv->width = va_image->width;
585 priv->height = va_image->height;
587 /* Try to linearize image */
588 if (!priv->is_linear) {
590 case GST_VAAPI_IMAGE_I420:
591 format = GST_VAAPI_IMAGE_YV12;
593 case GST_VAAPI_IMAGE_YV12:
594 format = GST_VAAPI_IMAGE_I420;
601 (alt_va_format = gst_vaapi_image_format_get_va_format(format))) {
602 alt_va_image = *va_image;
603 alt_va_image.format = *alt_va_format;
604 SWAP_UINT(alt_va_image.offsets[1], alt_va_image.offsets[2]);
605 SWAP_UINT(alt_va_image.pitches[1], alt_va_image.pitches[2]);
606 if (vaapi_image_is_linear(&alt_va_image)) {
607 priv->image = alt_va_image;
608 priv->format = format;
609 priv->is_linear = TRUE;
610 GST_DEBUG("linearized image to %" GST_FOURCC_FORMAT " format",
611 GST_FOURCC_ARGS(format));
619 * gst_vaapi_image_get_format:
620 * @image: a #GstVaapiImage
622 * Returns the #GstVaapiImageFormat the @image was created with.
624 * Return value: the #GstVaapiImageFormat
627 gst_vaapi_image_get_format(GstVaapiImage *image)
629 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
630 g_return_val_if_fail(image->priv->is_constructed, 0);
632 return image->priv->format;
636 * gst_vaapi_image_get_width:
637 * @image: a #GstVaapiImage
639 * Returns the @image width.
641 * Return value: the image width, in pixels
644 gst_vaapi_image_get_width(GstVaapiImage *image)
646 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
647 g_return_val_if_fail(image->priv->is_constructed, 0);
649 return image->priv->width;
653 * gst_vaapi_image_get_height:
654 * @image: a #GstVaapiImage
656 * Returns the @image height.
658 * Return value: the image height, in pixels.
661 gst_vaapi_image_get_height(GstVaapiImage *image)
663 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
664 g_return_val_if_fail(image->priv->is_constructed, 0);
666 return image->priv->height;
670 * gst_vaapi_image_get_size:
671 * @image: a #GstVaapiImage
672 * @pwidth: return location for the width, or %NULL
673 * @pheight: return location for the height, or %NULL
675 * Retrieves the dimensions of a #GstVaapiImage.
678 gst_vaapi_image_get_size(GstVaapiImage *image, guint *pwidth, guint *pheight)
680 g_return_if_fail(GST_VAAPI_IS_IMAGE(image));
681 g_return_if_fail(image->priv->is_constructed);
684 *pwidth = image->priv->width;
687 *pheight = image->priv->height;
691 * gst_vaapi_image_is_linear:
692 * @image: a #GstVaapiImage
694 * Checks whether the @image has data planes allocated from a single
695 * buffer and offsets into that buffer are in increasing order with
696 * the number of planes.
698 * Return value: %TRUE if image data planes are allocated from a single buffer
701 gst_vaapi_image_is_linear(GstVaapiImage *image)
703 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
704 g_return_val_if_fail(image->priv->is_constructed, FALSE);
706 return image->priv->is_linear;
710 * gst_vaapi_image_is_mapped:
711 * @image: a #GstVaapiImage
713 * Checks whether the @image is currently mapped or not.
715 * Return value: %TRUE if the @image is mapped
717 static inline gboolean
718 _gst_vaapi_image_is_mapped(GstVaapiImage *image)
720 return image->priv->image_data != NULL;
724 gst_vaapi_image_is_mapped(GstVaapiImage *image)
726 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
727 g_return_val_if_fail(image->priv->is_constructed, FALSE);
729 return _gst_vaapi_image_is_mapped(image);
733 * gst_vaapi_image_map:
734 * @image: a #GstVaapiImage
736 * Maps the image data buffer. The actual pixels are returned by the
737 * gst_vaapi_image_get_plane() function.
739 * Return value: %TRUE on success
742 gst_vaapi_image_map(GstVaapiImage *image)
744 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
745 g_return_val_if_fail(image->priv->is_constructed, FALSE);
747 return _gst_vaapi_image_map(image, NULL);
751 _gst_vaapi_image_map(GstVaapiImage *image, GstVaapiImageRaw *raw_image)
753 GstVaapiImagePrivate * const priv = image->priv;
754 GstVaapiDisplay *display;
759 if (_gst_vaapi_image_is_mapped(image))
762 display = GST_VAAPI_OBJECT_DISPLAY(image);
766 GST_VAAPI_DISPLAY_LOCK(display);
767 status = vaMapBuffer(
768 GST_VAAPI_DISPLAY_VADISPLAY(display),
769 image->priv->image.buf,
772 GST_VAAPI_DISPLAY_UNLOCK(display);
773 if (!vaapi_check_status(status, "vaMapBuffer()"))
776 image->priv->image_data = image_data;
779 const VAImage * const va_image = &priv->image;
780 raw_image->format = priv->format;
781 raw_image->width = va_image->width;
782 raw_image->height = va_image->height;
783 raw_image->num_planes = va_image->num_planes;
784 for (i = 0; i < raw_image->num_planes; i++) {
785 raw_image->pixels[i] = image_data + va_image->offsets[i];
786 raw_image->stride[i] = va_image->pitches[i];
793 * gst_vaapi_image_unmap:
794 * @image: a #GstVaapiImage
796 * Unmaps the image data buffer. Pointers to pixels returned by
797 * gst_vaapi_image_get_plane() are then no longer valid.
799 * Return value: %TRUE on success
802 gst_vaapi_image_unmap(GstVaapiImage *image)
804 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
805 g_return_val_if_fail(image->priv->is_constructed, FALSE);
807 return _gst_vaapi_image_unmap(image);
811 _gst_vaapi_image_unmap(GstVaapiImage *image)
813 GstVaapiDisplay *display;
816 if (!_gst_vaapi_image_is_mapped(image))
819 display = GST_VAAPI_OBJECT_DISPLAY(image);
823 GST_VAAPI_DISPLAY_LOCK(display);
824 status = vaUnmapBuffer(
825 GST_VAAPI_DISPLAY_VADISPLAY(display),
826 image->priv->image.buf
828 GST_VAAPI_DISPLAY_UNLOCK(display);
829 if (!vaapi_check_status(status, "vaUnmapBuffer()"))
832 image->priv->image_data = NULL;
837 * gst_vaapi_image_get_plane_count:
838 * @image: a #GstVaapiImage
840 * Retrieves the number of planes available in the @image. The @image
841 * must be mapped for this function to work properly.
843 * Return value: the number of planes available in the @image
846 gst_vaapi_image_get_plane_count(GstVaapiImage *image)
848 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
849 g_return_val_if_fail(image->priv->is_constructed, FALSE);
850 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0);
852 return image->priv->image.num_planes;
856 * gst_vaapi_image_get_plane:
857 * @image: a #GstVaapiImage
858 * @plane: the requested plane number
860 * Retrieves the pixels data to the specified @plane. The @image must
861 * be mapped for this function to work properly.
863 * Return value: the pixels data of the specified @plane
866 gst_vaapi_image_get_plane(GstVaapiImage *image, guint plane)
868 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), NULL);
869 g_return_val_if_fail(image->priv->is_constructed, FALSE);
870 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), NULL);
871 g_return_val_if_fail(plane < image->priv->image.num_planes, NULL);
873 return image->priv->image_data + image->priv->image.offsets[plane];
877 * gst_vaapi_image_get_pitch:
878 * @image: a #GstVaapiImage
879 * @plane: the requested plane number
881 * Retrieves the line size (stride) of the specified @plane. The
882 * @image must be mapped for this function to work properly.
884 * Return value: the line size (stride) of the specified plane
887 gst_vaapi_image_get_pitch(GstVaapiImage *image, guint plane)
889 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
890 g_return_val_if_fail(image->priv->is_constructed, FALSE);
891 g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0);
892 g_return_val_if_fail(plane < image->priv->image.num_planes, 0);
894 return image->priv->image.pitches[plane];
898 * gst_vaapi_image_get_data_size:
899 * @image: a #GstVaapiImage
901 * Retrieves the underlying image data size. This function could be
902 * used to determine whether the image has a compatible layout with
903 * another image structure.
905 * Return value: the whole image data size of the @image
908 gst_vaapi_image_get_data_size(GstVaapiImage *image)
910 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
911 g_return_val_if_fail(image->priv->is_constructed, FALSE);
913 return image->priv->image.data_size;
916 /* Copy N lines of an image */
929 for (i = 0; i < height; i++) {
930 memcpy(dst, src, len);
936 /* Copy NV12 images */
939 GstVaapiImageRaw *dst_image,
940 GstVaapiImageRaw *src_image,
941 const GstVaapiRectangle *rect
945 guint dst_stride, src_stride;
948 dst_stride = dst_image->stride[0];
949 dst = dst_image->pixels[0] + rect->y * dst_stride + rect->x;
950 src_stride = src_image->stride[0];
951 src = src_image->pixels[0] + rect->y * src_stride + rect->x;
952 memcpy_pic(dst, dst_stride, src, src_stride, rect->width, rect->height);
955 dst_stride = dst_image->stride[1];
956 dst = dst_image->pixels[1] + (rect->y / 2) * dst_stride + (rect->x & -2);
957 src_stride = src_image->stride[1];
958 src = src_image->pixels[1] + (rect->y / 2) * src_stride + (rect->x & -2);
959 memcpy_pic(dst, dst_stride, src, src_stride, rect->width, rect->height / 2);
962 /* Copy YV12 images */
965 GstVaapiImageRaw *dst_image,
966 GstVaapiImageRaw *src_image,
967 const GstVaapiRectangle *rect
971 guint dst_stride, src_stride;
975 dst_stride = dst_image->stride[0];
976 dst = dst_image->pixels[0] + rect->y * dst_stride + rect->x;
977 src_stride = src_image->stride[0];
978 src = src_image->pixels[0] + rect->y * src_stride + rect->x;
979 memcpy_pic(dst, dst_stride, src, src_stride, rect->width, rect->height);
985 h = rect->height / 2;
986 for (i = 1; i < dst_image->num_planes; i++) {
987 dst_stride = dst_image->stride[i];
988 dst = dst_image->pixels[i] + y * dst_stride + x;
989 src_stride = src_image->stride[i];
990 src = src_image->pixels[i] + y * src_stride + x;
991 memcpy_pic(dst, dst_stride, src, src_stride, w, h);
995 /* Copy RGBA images */
998 GstVaapiImageRaw *dst_image,
999 GstVaapiImageRaw *src_image,
1000 const GstVaapiRectangle *rect
1004 guint dst_stride, src_stride;
1006 dst_stride = dst_image->stride[0];
1007 dst = dst_image->pixels[0] + rect->y * dst_stride + rect->x;
1008 src_stride = src_image->stride[0];
1009 src = src_image->pixels[0] + rect->y * src_stride + rect->x;
1010 memcpy_pic(dst, dst_stride, src, src_stride, 4 * rect->width, rect->height);
1015 GstVaapiImageRaw *dst_image,
1016 GstVaapiImageRaw *src_image,
1017 const GstVaapiRectangle *rect
1020 GstVaapiRectangle default_rect;
1022 if (dst_image->format != src_image->format ||
1023 dst_image->width != src_image->width ||
1024 dst_image->height != src_image->height)
1028 if (rect->x >= src_image->width ||
1029 rect->x + src_image->width > src_image->width ||
1030 rect->y >= src_image->height ||
1031 rect->y + src_image->height > src_image->height)
1037 default_rect.width = src_image->width;
1038 default_rect.height = src_image->height;
1039 rect = &default_rect;
1042 switch (dst_image->format) {
1043 case GST_VAAPI_IMAGE_NV12:
1044 copy_image_NV12(dst_image, src_image, rect);
1046 case GST_VAAPI_IMAGE_YV12:
1047 case GST_VAAPI_IMAGE_I420:
1048 copy_image_YV12(dst_image, src_image, rect);
1050 case GST_VAAPI_IMAGE_ARGB:
1051 case GST_VAAPI_IMAGE_RGBA:
1052 case GST_VAAPI_IMAGE_ABGR:
1053 case GST_VAAPI_IMAGE_BGRA:
1054 copy_image_RGBA(dst_image, src_image, rect);
1057 GST_ERROR("unsupported image format for copy");
1064 * gst_vaapi_image_update_from_buffer:
1065 * @image: a #GstVaapiImage
1066 * @buffer: a #GstBuffer
1067 * @rect: a #GstVaapiRectangle expressing a region, or %NULL for the
1070 * Transfers pixels data contained in the #GstBuffer into the
1071 * @image. Both image structures shall have the same format.
1073 * Return value: %TRUE on success
1076 gst_vaapi_image_update_from_buffer(
1077 GstVaapiImage *image,
1079 GstVaapiRectangle *rect
1082 GstVaapiImagePrivate *priv;
1083 GstStructure *structure;
1085 GstVaapiImageFormat format;
1086 GstVaapiImageRaw dst_image, src_image;
1087 guint width2, height2, size2;
1093 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
1094 g_return_val_if_fail(image->priv->is_constructed, FALSE);
1095 g_return_val_if_fail(GST_IS_BUFFER(buffer), FALSE);
1098 data = GST_BUFFER_DATA(buffer);
1099 data_size = GST_BUFFER_SIZE(buffer);
1100 caps = GST_BUFFER_CAPS(buffer);
1105 format = gst_vaapi_image_format_from_caps(caps);
1106 if (format != priv->format)
1109 structure = gst_caps_get_structure(caps, 0);
1110 gst_structure_get_int(structure, "width", &width);
1111 gst_structure_get_int(structure, "height", &height);
1112 if (width != priv->width || height != priv->height)
1115 if (!_gst_vaapi_image_map(image, &dst_image))
1118 /* XXX: copied from gst_video_format_get_row_stride() -- no NV12? */
1119 src_image.format = priv->format;
1120 src_image.width = width;
1121 src_image.height = height;
1122 width2 = (width + 1) / 2;
1123 height2 = (height + 1) / 2;
1126 case GST_VAAPI_IMAGE_NV12:
1127 src_image.num_planes = 2;
1128 src_image.pixels[0] = data;
1129 src_image.stride[0] = GST_ROUND_UP_4(width);
1130 size2 += height * src_image.stride[0];
1131 src_image.pixels[1] = data + size2;
1132 src_image.stride[1] = src_image.stride[0];
1133 size2 += height2 * src_image.stride[1];
1135 case GST_VAAPI_IMAGE_YV12:
1136 case GST_VAAPI_IMAGE_I420:
1137 src_image.num_planes = 3;
1138 src_image.pixels[0] = data;
1139 src_image.stride[0] = GST_ROUND_UP_4(width);
1140 size2 += height * src_image.stride[0];
1141 src_image.pixels[1] = data + size2;
1142 src_image.stride[1] = GST_ROUND_UP_4(width2);
1143 size2 += height2 * src_image.stride[1];
1144 src_image.pixels[2] = data + size2;
1145 src_image.stride[2] = src_image.stride[1];
1146 size2 += height2 * src_image.stride[2];
1148 case GST_VAAPI_IMAGE_ARGB:
1149 case GST_VAAPI_IMAGE_RGBA:
1150 case GST_VAAPI_IMAGE_ABGR:
1151 case GST_VAAPI_IMAGE_BGRA:
1152 src_image.num_planes = 1;
1153 src_image.pixels[0] = data;
1154 src_image.stride[0] = width * 4;
1155 size2 += height * src_image.stride[0];
1158 g_error("could not compute row-stride for %" GST_FOURCC_FORMAT,
1159 GST_FOURCC_ARGS(format));
1163 if (size2 != data_size) {
1164 g_error("data_size mismatch %d / %u", size2, data_size);
1165 if (size2 > data_size) {
1166 _gst_vaapi_image_unmap(image);
1171 success = copy_image(&dst_image, &src_image, rect);
1173 if (!_gst_vaapi_image_unmap(image))
1180 * gst_vaapi_image_update_from_raw:
1181 * @image: a #GstVaapiImage
1182 * @src_image: a #GstVaapiImageRaw
1183 * @buffer: a #GstBuffer
1184 * @rect: a #GstVaapiRectangle expressing a region, or %NULL for the
1187 * Transfers pixels data contained in the #GstVaapiImageRaw into the
1188 * @image. Both image structures shall have the same format.
1190 * Return value: %TRUE on success
1193 gst_vaapi_image_update_from_raw(
1194 GstVaapiImage *image,
1195 GstVaapiImageRaw *src_image,
1196 GstVaapiRectangle *rect
1199 GstVaapiImageRaw dst_image;
1202 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
1203 g_return_val_if_fail(image->priv->is_constructed, FALSE);
1205 if (!_gst_vaapi_image_map(image, &dst_image))
1208 success = copy_image(&dst_image, src_image, rect);
1210 if (!_gst_vaapi_image_unmap(image))