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;
917 init_image_from_buffer(GstVaapiImageRaw *raw_image, GstBuffer *buffer)
919 GstStructure *structure;
921 GstVaapiImageFormat format;
922 guint width2, height2, size2;
927 data = GST_BUFFER_DATA(buffer);
928 data_size = GST_BUFFER_SIZE(buffer);
929 caps = GST_BUFFER_CAPS(buffer);
934 format = gst_vaapi_image_format_from_caps(caps);
936 structure = gst_caps_get_structure(caps, 0);
937 gst_structure_get_int(structure, "width", &width);
938 gst_structure_get_int(structure, "height", &height);
940 /* XXX: copied from gst_video_format_get_row_stride() -- no NV12? */
941 raw_image->format = format;
942 raw_image->width = width;
943 raw_image->height = height;
944 width2 = (width + 1) / 2;
945 height2 = (height + 1) / 2;
948 case GST_VAAPI_IMAGE_NV12:
949 raw_image->num_planes = 2;
950 raw_image->pixels[0] = data;
951 raw_image->stride[0] = GST_ROUND_UP_4(width);
952 size2 += height * raw_image->stride[0];
953 raw_image->pixels[1] = data + size2;
954 raw_image->stride[1] = raw_image->stride[0];
955 size2 += height2 * raw_image->stride[1];
957 case GST_VAAPI_IMAGE_YV12:
958 case GST_VAAPI_IMAGE_I420:
959 raw_image->num_planes = 3;
960 raw_image->pixels[0] = data;
961 raw_image->stride[0] = GST_ROUND_UP_4(width);
962 size2 += height * raw_image->stride[0];
963 raw_image->pixels[1] = data + size2;
964 raw_image->stride[1] = GST_ROUND_UP_4(width2);
965 size2 += height2 * raw_image->stride[1];
966 raw_image->pixels[2] = data + size2;
967 raw_image->stride[2] = raw_image->stride[1];
968 size2 += height2 * raw_image->stride[2];
970 case GST_VAAPI_IMAGE_ARGB:
971 case GST_VAAPI_IMAGE_RGBA:
972 case GST_VAAPI_IMAGE_ABGR:
973 case GST_VAAPI_IMAGE_BGRA:
974 raw_image->num_planes = 1;
975 raw_image->pixels[0] = data;
976 raw_image->stride[0] = width * 4;
977 size2 += height * raw_image->stride[0];
980 g_error("could not compute row-stride for %" GST_FOURCC_FORMAT,
981 GST_FOURCC_ARGS(format));
985 if (size2 != data_size) {
986 g_error("data_size mismatch %d / %u", size2, data_size);
987 if (size2 > data_size)
993 /* Copy N lines of an image */
1006 for (i = 0; i < height; i++) {
1007 memcpy(dst, src, len);
1013 /* Copy NV12 images */
1016 GstVaapiImageRaw *dst_image,
1017 GstVaapiImageRaw *src_image,
1018 const GstVaapiRectangle *rect
1022 guint dst_stride, src_stride;
1025 dst_stride = dst_image->stride[0];
1026 dst = dst_image->pixels[0] + rect->y * dst_stride + rect->x;
1027 src_stride = src_image->stride[0];
1028 src = src_image->pixels[0] + rect->y * src_stride + rect->x;
1029 memcpy_pic(dst, dst_stride, src, src_stride, rect->width, rect->height);
1032 dst_stride = dst_image->stride[1];
1033 dst = dst_image->pixels[1] + (rect->y / 2) * dst_stride + (rect->x & -2);
1034 src_stride = src_image->stride[1];
1035 src = src_image->pixels[1] + (rect->y / 2) * src_stride + (rect->x & -2);
1036 memcpy_pic(dst, dst_stride, src, src_stride, rect->width, rect->height / 2);
1039 /* Copy YV12 images */
1042 GstVaapiImageRaw *dst_image,
1043 GstVaapiImageRaw *src_image,
1044 const GstVaapiRectangle *rect
1048 guint dst_stride, src_stride;
1049 guint i, x, y, w, h;
1052 dst_stride = dst_image->stride[0];
1053 dst = dst_image->pixels[0] + rect->y * dst_stride + rect->x;
1054 src_stride = src_image->stride[0];
1055 src = src_image->pixels[0] + rect->y * src_stride + rect->x;
1056 memcpy_pic(dst, dst_stride, src, src_stride, rect->width, rect->height);
1061 w = rect->width / 2;
1062 h = rect->height / 2;
1063 for (i = 1; i < dst_image->num_planes; i++) {
1064 dst_stride = dst_image->stride[i];
1065 dst = dst_image->pixels[i] + y * dst_stride + x;
1066 src_stride = src_image->stride[i];
1067 src = src_image->pixels[i] + y * src_stride + x;
1068 memcpy_pic(dst, dst_stride, src, src_stride, w, h);
1072 /* Copy RGBA images */
1075 GstVaapiImageRaw *dst_image,
1076 GstVaapiImageRaw *src_image,
1077 const GstVaapiRectangle *rect
1081 guint dst_stride, src_stride;
1083 dst_stride = dst_image->stride[0];
1084 dst = dst_image->pixels[0] + rect->y * dst_stride + rect->x;
1085 src_stride = src_image->stride[0];
1086 src = src_image->pixels[0] + rect->y * src_stride + rect->x;
1087 memcpy_pic(dst, dst_stride, src, src_stride, 4 * rect->width, rect->height);
1092 GstVaapiImageRaw *dst_image,
1093 GstVaapiImageRaw *src_image,
1094 const GstVaapiRectangle *rect
1097 GstVaapiRectangle default_rect;
1099 if (dst_image->format != src_image->format ||
1100 dst_image->width != src_image->width ||
1101 dst_image->height != src_image->height)
1105 if (rect->x >= src_image->width ||
1106 rect->x + src_image->width > src_image->width ||
1107 rect->y >= src_image->height ||
1108 rect->y + src_image->height > src_image->height)
1114 default_rect.width = src_image->width;
1115 default_rect.height = src_image->height;
1116 rect = &default_rect;
1119 switch (dst_image->format) {
1120 case GST_VAAPI_IMAGE_NV12:
1121 copy_image_NV12(dst_image, src_image, rect);
1123 case GST_VAAPI_IMAGE_YV12:
1124 case GST_VAAPI_IMAGE_I420:
1125 copy_image_YV12(dst_image, src_image, rect);
1127 case GST_VAAPI_IMAGE_ARGB:
1128 case GST_VAAPI_IMAGE_RGBA:
1129 case GST_VAAPI_IMAGE_ABGR:
1130 case GST_VAAPI_IMAGE_BGRA:
1131 copy_image_RGBA(dst_image, src_image, rect);
1134 GST_ERROR("unsupported image format for copy");
1141 * gst_vaapi_image_get_buffer:
1142 * @image: a #GstVaapiImage
1143 * @buffer: a #GstBuffer
1144 * @rect: a #GstVaapiRectangle expressing a region, or %NULL for the
1147 * Transfers pixels data contained in the @image into the #GstBuffer.
1148 * Both image structures shall have the same format.
1150 * Return value: %TRUE on success
1153 gst_vaapi_image_get_buffer(
1154 GstVaapiImage *image,
1156 GstVaapiRectangle *rect
1159 GstVaapiImagePrivate *priv;
1160 GstVaapiImageRaw dst_image, src_image;
1163 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
1164 g_return_val_if_fail(image->priv->is_constructed, FALSE);
1165 g_return_val_if_fail(GST_IS_BUFFER(buffer), FALSE);
1169 if (!init_image_from_buffer(&dst_image, buffer))
1171 if (dst_image.format != priv->format)
1173 if (dst_image.width != priv->width || dst_image.height != priv->height)
1176 if (!_gst_vaapi_image_map(image, &src_image))
1179 success = copy_image(&dst_image, &src_image, rect);
1181 if (!_gst_vaapi_image_unmap(image))
1188 * gst_vaapi_image_get_raw:
1189 * @image: a #GstVaapiImage
1190 * @dst_image: a #GstVaapiImageRaw
1191 * @buffer: a #GstBuffer
1192 * @rect: a #GstVaapiRectangle expressing a region, or %NULL for the
1195 * Transfers pixels data contained in the @image into the #GstVaapiImageRaw.
1196 * Both image structures shall have the same format.
1198 * Return value: %TRUE on success
1201 gst_vaapi_image_get_raw(
1202 GstVaapiImage *image,
1203 GstVaapiImageRaw *dst_image,
1204 GstVaapiRectangle *rect
1207 GstVaapiImageRaw src_image;
1210 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
1211 g_return_val_if_fail(image->priv->is_constructed, FALSE);
1213 if (!_gst_vaapi_image_map(image, &src_image))
1216 success = copy_image(dst_image, &src_image, rect);
1218 if (!_gst_vaapi_image_unmap(image))
1225 * gst_vaapi_image_update_from_buffer:
1226 * @image: a #GstVaapiImage
1227 * @buffer: a #GstBuffer
1228 * @rect: a #GstVaapiRectangle expressing a region, or %NULL for the
1231 * Transfers pixels data contained in the #GstBuffer into the
1232 * @image. Both image structures shall have the same format.
1234 * Return value: %TRUE on success
1237 gst_vaapi_image_update_from_buffer(
1238 GstVaapiImage *image,
1240 GstVaapiRectangle *rect
1243 GstVaapiImagePrivate *priv;
1244 GstVaapiImageRaw dst_image, src_image;
1247 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
1248 g_return_val_if_fail(image->priv->is_constructed, FALSE);
1249 g_return_val_if_fail(GST_IS_BUFFER(buffer), FALSE);
1253 if (!init_image_from_buffer(&src_image, buffer))
1255 if (src_image.format != priv->format)
1257 if (src_image.width != priv->width || src_image.height != priv->height)
1260 if (!_gst_vaapi_image_map(image, &dst_image))
1263 success = copy_image(&dst_image, &src_image, rect);
1265 if (!_gst_vaapi_image_unmap(image))
1272 * gst_vaapi_image_update_from_raw:
1273 * @image: a #GstVaapiImage
1274 * @src_image: a #GstVaapiImageRaw
1275 * @buffer: a #GstBuffer
1276 * @rect: a #GstVaapiRectangle expressing a region, or %NULL for the
1279 * Transfers pixels data contained in the #GstVaapiImageRaw into the
1280 * @image. Both image structures shall have the same format.
1282 * Return value: %TRUE on success
1285 gst_vaapi_image_update_from_raw(
1286 GstVaapiImage *image,
1287 GstVaapiImageRaw *src_image,
1288 GstVaapiRectangle *rect
1291 GstVaapiImageRaw dst_image;
1294 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
1295 g_return_val_if_fail(image->priv->is_constructed, FALSE);
1297 if (!_gst_vaapi_image_map(image, &dst_image))
1300 success = copy_image(&dst_image, src_image, rect);
1302 if (!_gst_vaapi_image_unmap(image))