Tizen 2.0 Release
[framework/multimedia/gstreamer-vaapi.git] / gst-libs / gst / vaapi / gstvaapisurface_userptr.c
1 /*
2  *  gstvaapisurface_userptr.c - VA surface abstraction for userptr
3  *
4  *  Copyright (C) 2011 Intel Corporation
5  *
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.
10  *
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.
15  *
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
20  */
21
22 /**
23  * SECTION:gstvaapisurface_userptr
24  * @short_description: VA surface abstraction for userptr
25  */
26 #include "sysdeps.h"
27 #include "gstvaapisurface_userptr.h"
28 #include "gstvaapiutils.h"
29 #include "gstvaapiobject_priv.h"
30 #include "gstvaapidisplay_priv.h"
31
32 #include <va/va.h>
33 #include <va/va_tpi.h>
34
35 #define DEBUG 1
36 #include "gstvaapidebug.h"
37
38 G_DEFINE_TYPE(GstVaapiSurfaceUserPtr, gst_vaapi_surface_userptr, GST_VAAPI_TYPE_SURFACE);
39
40 #define GST_VAAPI_SURFACE_USERPTR_GET_PRIVATE(obj)                 \
41     (G_TYPE_INSTANCE_GET_PRIVATE((obj),                            \
42                                  GST_VAAPI_TYPE_SURFACE_USERPTR,   \
43                                  GstVaapiSurfaceUserPtrPrivate))
44
45 struct _GstVaapiSurfaceUserPtrPrivate {
46     GstVaapiImageFormat format;
47 };
48
49 enum {
50     PROP_0,
51
52     PROP_FORMAT
53 };
54
55 typedef struct _GstVaapiSurfaceUserPtrInfo {
56     guint fourcc;
57     guint datasize;
58     guint y_stride;
59     guint u_stride;
60     guint v_stride;
61     guint y_offset;
62     guint u_offset;
63     guint v_offset;
64 } GstVaapiSurfaceUserPtrInfo;
65
66 static gboolean
67 _get_surface_userptr_info(
68     GstVaapiImageFormat format,
69     guint width,
70     guint height,
71     GstVaapiSurfaceUserPtrInfo *info
72 )
73 {
74     const VAImageFormat *va_format;
75     guint stride1, stride2;
76     guint height2;
77
78     g_return_val_if_fail(info, FALSE);
79
80     va_format = gst_vaapi_image_format_get_va_format(format);
81     if (!va_format)
82         return FALSE;
83     info->fourcc = va_format->fourcc;
84
85     stride1 = GST_ROUND_UP_4(width);
86     stride2 = GST_ROUND_UP_4((width + 1) / 2);
87     height2 = (height + 1) / 2;
88
89     info->datasize = (stride1 * height) + (stride2 * height2)*2;
90     info->y_stride = stride1;
91     info->y_offset = 0;
92
93     switch (format) {
94     case GST_VAAPI_IMAGE_NV12:
95         info->u_stride = stride1;
96         info->v_stride = stride1;
97         info->u_offset = stride1 * height;
98         info->v_offset = stride1 * height;
99         break;
100
101     case GST_VAAPI_IMAGE_YV12:
102         info->u_stride = stride2;
103         info->v_stride = stride2;
104         info->u_offset = stride1 * height + stride2 * height2;
105         info->v_offset = stride1 * height;
106         break;
107
108     case GST_VAAPI_IMAGE_I420:
109         info->u_stride = stride2;
110         info->v_stride = stride2;
111         info->u_offset = stride1 * height;
112         info->v_offset = stride1 * height + stride2 * height2;
113         break;
114
115     default:
116         return FALSE;
117     }
118     return TRUE;
119 }
120
121 static gboolean
122 gst_vaapi_surface_userptr_create(GstVaapiSurface *base)
123 {
124     GstVaapiSurfaceUserPtr * const surface = GST_VAAPI_SURFACE_USERPTR(base);
125     GstVaapiSurfaceUserPtrPrivate * const priv = surface->priv;
126     GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(surface);
127     GstVaapiSurfaceUserPtrInfo info;
128     VASurfaceID surface_id;
129     VAStatus status;
130     guint surface_format;
131     GstVaapiChromaType chroma_type;
132     guint width, height;
133
134     chroma_type = gst_vaapi_surface_get_chroma_type(base);
135     gst_vaapi_surface_get_size(base, &width, &height);
136
137     if (!_get_surface_userptr_info(priv->format, width, height, &info)) {
138         GST_ERROR("surface userptr format error.");
139         return FALSE;
140     }
141
142     switch (chroma_type) {
143     case GST_VAAPI_CHROMA_TYPE_YUV420:
144         surface_format = VA_RT_FORMAT_YUV420;
145         break;
146     case GST_VAAPI_CHROMA_TYPE_YUV422:
147         surface_format = VA_RT_FORMAT_YUV422;
148         break;
149     case GST_VAAPI_CHROMA_TYPE_YUV444:
150         surface_format = VA_RT_FORMAT_YUV444;
151         break;
152     default:
153         GST_DEBUG("unsupported chroma-type %u\n", chroma_type);
154         return FALSE;
155     }
156
157     GST_VAAPI_DISPLAY_LOCK(display);
158     status = vaCreateSurfacesForUserPtr(
159         GST_VAAPI_DISPLAY_VADISPLAY(display),
160         width,
161         height,
162         surface_format,
163         1, &surface_id,
164         info.datasize,
165         info.fourcc,
166         info.y_stride,
167         info.u_stride,
168         info.v_stride,
169         info.y_offset,
170         info.u_offset,
171         info.v_offset);
172     GST_VAAPI_DISPLAY_UNLOCK(display);
173     if (!vaapi_check_status(status, "vaCreateSurfaces()"))
174         return FALSE;
175
176     GST_DEBUG("surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(surface_id));
177     GST_VAAPI_OBJECT_ID(surface) = surface_id;
178     return TRUE;
179 }
180
181 static void
182 gst_vaapi_surface_userptr_finalize(GObject *object)
183 {
184
185     G_OBJECT_CLASS(gst_vaapi_surface_userptr_parent_class)->finalize(object);
186 }
187
188 static void
189 gst_vaapi_surface_userptr_set_property(
190     GObject      *object,
191     guint         prop_id,
192     const GValue *value,
193     GParamSpec   *pspec
194 )
195 {
196     GstVaapiSurfaceUserPtr        * const surface = GST_VAAPI_SURFACE_USERPTR(object);
197     GstVaapiSurfaceUserPtrPrivate * const priv    = surface->priv;
198
199     switch (prop_id) {
200     case PROP_FORMAT:
201         priv->format = g_value_get_uint(value);
202         break;
203     default:
204         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
205         break;
206     }
207 }
208
209 static void
210 gst_vaapi_surface_userptr_get_property(
211     GObject    *object,
212     guint       prop_id,
213     GValue     *value,
214     GParamSpec *pspec
215 )
216 {
217     GstVaapiSurfaceUserPtr * const surface = GST_VAAPI_SURFACE_USERPTR(object);
218
219     switch (prop_id) {
220     case PROP_FORMAT:
221         g_value_set_uint(value, gst_vaapi_surface_userptr_get_format(surface));
222         break;
223     default:
224         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
225         break;
226     }
227 }
228
229 static void
230 gst_vaapi_surface_userptr_class_init(GstVaapiSurfaceUserPtrClass *klass)
231 {
232     GObjectClass * const object_class = G_OBJECT_CLASS(klass);
233     GstVaapiSurfaceClass * const surface_class = GST_VAAPI_SURFACE_CLASS(klass);
234
235     g_type_class_add_private(klass, sizeof(GstVaapiSurfaceUserPtrPrivate));
236
237     object_class->finalize     = gst_vaapi_surface_userptr_finalize;
238     object_class->set_property = gst_vaapi_surface_userptr_set_property;
239     object_class->get_property = gst_vaapi_surface_userptr_get_property;
240
241     surface_class->create = gst_vaapi_surface_userptr_create;
242
243     g_object_class_install_property
244         (object_class,
245          PROP_FORMAT,
246          g_param_spec_uint("format",
247                            "format",
248                            "The buffer format of surface userptr",
249                            0, G_MAXUINT32, 0,
250                            G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
251 }
252
253 static void
254 gst_vaapi_surface_userptr_init(GstVaapiSurfaceUserPtr *surface)
255 {
256     GstVaapiSurfaceUserPtrPrivate *priv = GST_VAAPI_SURFACE_USERPTR_GET_PRIVATE(surface);
257
258     surface->priv        = priv;
259     priv->format         = 0;
260 }
261
262 /**
263  * gst_vaapi_surface_new:
264  * @display: a #GstVaapiDisplay
265  * @chroma_type: the surface chroma format
266  * @format: the fourcc format of the buffer
267  * @width: the requested surface width
268  * @height: the requested surface height
269  *
270  * Creates a new #GstVaapiSurface with the specified chroma format and
271  * dimensions.
272  *
273  * Return value: the newly allocated #GstVaapiSurface object
274  */
275 GstVaapiSurfaceUserPtr *
276 gst_vaapi_surface_userptr_new(
277     GstVaapiDisplay    *display,
278     GstVaapiChromaType  chroma_type,
279     GstVaapiImageFormat format,
280     guint               width,
281     guint               height
282 )
283 {
284     GST_DEBUG("size %ux%u, chroma type 0x%x", width, height, chroma_type);
285
286     return g_object_new(GST_VAAPI_TYPE_SURFACE_USERPTR,
287                         "display",      display,
288                         "id",           GST_VAAPI_ID(VA_INVALID_ID),
289                         "width",        width,
290                         "height",       height,
291                         "chroma-type",  chroma_type,
292                         "format",       format,
293                         NULL);
294 }
295
296
297 GstVaapiImageFormat
298 gst_vaapi_surface_userptr_get_format(GstVaapiSurfaceUserPtr *surface)
299 {
300     g_return_val_if_fail(GST_VAAPI_IS_SURFACE_USERPTR(surface), 0);
301
302     return surface->priv->format;
303 }