Tizen 2.0 Release
[framework/multimedia/gstreamer-vaapi.git] / gst-libs / gst / vaapi / gstvaapiimageformat.c
1 /*
2  *  gstvaapiimageformat.c - VA image format abstraction
3  *
4  *  Copyright (C) 2010-2011 Splitted-Desktop Systems
5  *  Copyright (C) 2011 Intel Corporation
6  *
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.
11  *
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.
16  *
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
21  */
22
23 /**
24  * SECTION:gstvaapiimageformat
25  * @short_description: VA image format abstraction
26  */
27
28 #include "sysdeps.h"
29 #include <gst/video/video.h>
30 #include "gstvaapicompat.h"
31 #include "gstvaapiimageformat.h"
32
33 typedef enum _GstVaapiImageFormatType           GstVaapiImageFormatType;
34 typedef struct _GstVaapiImageFormatMap          GstVaapiImageFormatMap;
35
36 enum _GstVaapiImageFormatType {
37     GST_VAAPI_IMAGE_FORMAT_TYPE_YCBCR = 1,      /* YUV */
38     GST_VAAPI_IMAGE_FORMAT_TYPE_RGB,            /* RGB */
39     GST_VAAPI_IMAGE_FORMAT_TYPE_INDEXED         /* paletted */
40 };
41
42 struct _GstVaapiImageFormatMap {
43     GstVaapiImageFormatType     type;
44     GstVaapiImageFormat         format;
45     const char                 *caps_str;
46     VAImageFormat               va_format;
47 };
48
49 #define DEF(TYPE, FORMAT, CAPS_STR)                                     \
50     GST_VAAPI_IMAGE_FORMAT_TYPE_##TYPE,                                 \
51     GST_VAAPI_IMAGE_##FORMAT,                                           \
52     CAPS_STR
53 #define DEF_YUV(FORMAT, FOURCC, ENDIAN, BPP)                            \
54     { DEF(YCBCR, FORMAT, GST_VIDEO_CAPS_YUV(#FORMAT)),                  \
55         { VA_FOURCC FOURCC, VA_##ENDIAN##_FIRST, BPP, }, }
56 #define DEF_RGB(FORMAT, FOURCC, ENDIAN, BPP, DEPTH, R,G,B,A)            \
57     { DEF(RGB, FORMAT, GST_VIDEO_CAPS_##FORMAT),                        \
58         { VA_FOURCC FOURCC, VA_##ENDIAN##_FIRST, BPP, DEPTH, R,G,B,A }, }
59
60 /* Image formats, listed in HW order preference */
61 static const GstVaapiImageFormatMap gst_vaapi_image_formats[] = {
62     DEF_YUV(NV12, ('N','V','1','2'), LSB, 12),
63     DEF_YUV(YV12, ('Y','V','1','2'), LSB, 12),
64     DEF_YUV(I420, ('I','4','2','0'), LSB, 12),
65     DEF_YUV(AYUV, ('A','Y','U','V'), LSB, 32),
66 #if G_BYTE_ORDER == G_BIG_ENDIAN
67     DEF_RGB(ARGB, ('A','R','G','B'), MSB, 32,
68             32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000),
69     DEF_RGB(ABGR, ('A','B','G','R'), MSB, 32,
70             32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000),
71 #elif G_BYTE_ORDER == G_LITTLE_ENDIAN
72     DEF_RGB(BGRA, ('B','G','R','A'), LSB, 32,
73             32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000),
74     DEF_RGB(RGBA, ('R','G','B','A'), LSB, 32,
75             32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000),
76 #endif
77     { 0, }
78 };
79
80 #undef DEF_RGB
81 #undef DEF_YUV
82 #undef DEF
83
84 static inline gboolean
85 match_va_format_rgb(const VAImageFormat *fmt1, const VAImageFormat *fmt2)
86 {
87     return (fmt1->byte_order == fmt2->byte_order &&
88             fmt1->red_mask   == fmt2->red_mask   &&
89             fmt1->green_mask == fmt2->green_mask &&
90             fmt1->blue_mask  == fmt2->blue_mask  &&
91             fmt1->alpha_mask == fmt2->alpha_mask);
92 }
93
94 static const GstVaapiImageFormatMap *
95 get_map(GstVaapiImageFormat format)
96 {
97     const GstVaapiImageFormatMap *m;
98
99     for (m = gst_vaapi_image_formats; m->format; m++)
100         if (m->format == format)
101             return m;
102     return NULL;
103 }
104
105 /**
106  * gst_vaapi_image_format_is_rgb:
107  * @format: a #GstVaapiImageFormat
108  *
109  * Checks whether the format is an RGB format.
110  *
111  * Return value: %TRUE if @format is RGB format
112  */
113 gboolean
114 gst_vaapi_image_format_is_rgb(GstVaapiImageFormat format)
115 {
116     const GstVaapiImageFormatMap * const m = get_map(format);
117
118     return m ? (m->type == GST_VAAPI_IMAGE_FORMAT_TYPE_RGB) : FALSE;
119 }
120
121 /**
122  * gst_vaapi_image_format_is_yuv:
123  * @format: a #GstVaapiImageFormat
124  *
125  * Checks whether the format is an YUV format.
126  *
127  * Return value: %TRUE if @format is YUV format
128  */
129 gboolean
130 gst_vaapi_image_format_is_yuv(GstVaapiImageFormat format)
131 {
132     const GstVaapiImageFormatMap * const m = get_map(format);
133
134     return m ? (m->type == GST_VAAPI_IMAGE_FORMAT_TYPE_YCBCR) : FALSE;
135 }
136
137 /**
138  * gst_vaapi_image_format:
139  * @va_format: a #VAImageFormat
140  *
141  * Converts a VA image format into the corresponding #GstVaapiImageFormat.
142  * If the image format cannot be represented by #GstVaapiImageFormat,
143  * then zero is returned.
144  *
145  * Return value: the #GstVaapiImageFormat describing the @va_format
146  */
147 GstVaapiImageFormat
148 gst_vaapi_image_format(const VAImageFormat *va_format)
149 {
150     const GstVaapiImageFormatMap *m;
151
152     for (m = gst_vaapi_image_formats; m->format; m++)
153         if (m->va_format.fourcc == va_format->fourcc &&
154             (m->type == GST_VAAPI_IMAGE_FORMAT_TYPE_RGB ?
155              match_va_format_rgb(&m->va_format, va_format) :
156              TRUE))
157             return m->format;
158
159     return 0;
160 }
161
162 /**
163  * gst_vaapi_image_format_from_caps:
164  * @caps: a #GstCaps
165  *
166  * Converts @caps into the corresponding #GstVaapiImageFormat. If the
167  * image format cannot be represented by #GstVaapiImageFormat, then
168  * zero is returned.
169  *
170  * Return value: the #GstVaapiImageFormat describing the @caps
171  */
172 GstVaapiImageFormat
173 gst_vaapi_image_format_from_caps(GstCaps *caps)
174 {
175     const GstVaapiImageFormatMap *m;
176     GstStructure *structure;
177     VAImageFormat *va_format, va_formats[2];
178     gint endian, rmask, gmask, bmask, amask = 0;
179     guint32 fourcc;
180
181     if (!caps)
182         return 0;
183
184     structure = gst_caps_get_structure(caps, 0);
185     if (!structure)
186         return 0;
187
188     /* Check for YUV format */
189     if (gst_structure_get_fourcc(structure, "format", &fourcc))
190         return gst_vaapi_image_format_from_fourcc(fourcc);
191
192     /* Check for RGB format */
193     gst_structure_get_int(structure, "endianness", &endian);
194     gst_structure_get_int(structure, "red_mask",   &rmask);
195     gst_structure_get_int(structure, "green_mask", &gmask);
196     gst_structure_get_int(structure, "blue_mask",  &bmask);
197     gst_structure_get_int(structure, "alpha_mask", &amask);
198
199     va_format = &va_formats[0];
200     va_format->byte_order = endian == G_BIG_ENDIAN ? VA_MSB_FIRST : VA_LSB_FIRST;
201     va_format->red_mask   = rmask;
202     va_format->green_mask = gmask;
203     va_format->blue_mask  = bmask;
204     va_format->alpha_mask = amask;
205
206     va_format = &va_formats[1];
207     va_format->byte_order = endian == G_BIG_ENDIAN ? VA_LSB_FIRST : VA_MSB_FIRST;
208     va_format->red_mask   = GUINT32_SWAP_LE_BE(rmask);
209     va_format->green_mask = GUINT32_SWAP_LE_BE(gmask);
210     va_format->blue_mask  = GUINT32_SWAP_LE_BE(bmask);
211     va_format->alpha_mask = GUINT32_SWAP_LE_BE(amask);
212
213     for (m = gst_vaapi_image_formats; m->format; m++)
214         if (match_va_format_rgb(&m->va_format, &va_formats[0]) ||
215             match_va_format_rgb(&m->va_format, &va_formats[1]))
216             return m->format;
217
218     return 0;
219 }
220
221 /**
222  * gst_vaapi_image_format_from_fourcc:
223  * @fourcc: a FOURCC value
224  *
225  * Converts a FOURCC value into the corresponding #GstVaapiImageFormat.
226  * If the image format cannot be represented by #GstVaapiImageFormat,
227  * then zero is returned.
228  *
229  * Return value: the #GstVaapiImageFormat describing the FOURCC value
230  */
231 GstVaapiImageFormat
232 gst_vaapi_image_format_from_fourcc(guint32 fourcc)
233 {
234     return (GstVaapiImageFormat)fourcc;
235 }
236
237 /**
238  * gst_vaapi_image_format_from_video:
239  * @format: a #GstVideoFormat
240  *
241  * Converts a #GstVideoFormat into the corresponding
242  * #GstVaapiImageFormat.  If the image format cannot be represented by
243  * #GstVaapiImageFormat, then zero is returned.
244  *
245  * Return value: the #GstVaapiImageFormat describing the video format
246  */
247 GstVaapiImageFormat
248 gst_vaapi_image_format_from_video(GstVideoFormat format)
249 {
250     GstVaapiImageFormat va_format;
251
252     switch (format) {
253     case GST_VIDEO_FORMAT_NV12: va_format = GST_VAAPI_IMAGE_NV12;   break;
254     case GST_VIDEO_FORMAT_YV12: va_format = GST_VAAPI_IMAGE_YV12;   break;
255     case GST_VIDEO_FORMAT_I420: va_format = GST_VAAPI_IMAGE_I420;   break;
256     case GST_VIDEO_FORMAT_AYUV: va_format = GST_VAAPI_IMAGE_AYUV;   break;
257     case GST_VIDEO_FORMAT_ARGB: va_format = GST_VAAPI_IMAGE_ARGB;   break;
258     case GST_VIDEO_FORMAT_RGBA: va_format = GST_VAAPI_IMAGE_RGBA;   break;
259     case GST_VIDEO_FORMAT_ABGR: va_format = GST_VAAPI_IMAGE_ABGR;   break;
260     case GST_VIDEO_FORMAT_BGRA: va_format = GST_VAAPI_IMAGE_BGRA;   break;
261     default:                    va_format = (GstVaapiImageFormat)0; break;
262     }
263     return va_format;
264 }
265
266 /**
267  * gst_vaapi_image_format_get_va_format:
268  * @format: a #GstVaapiImageFormat
269  *
270  * Converts a #GstVaapiImageFormat into the corresponding VA image
271  * format. If no matching VA image format was found, %NULL is returned
272  * and this error must be reported to be fixed.
273  *
274  * Return value: the VA image format, or %NULL if none was found
275  */
276 const VAImageFormat *
277 gst_vaapi_image_format_get_va_format(GstVaapiImageFormat format)
278 {
279     const GstVaapiImageFormatMap * const m = get_map(format);
280
281     return m ? &m->va_format : NULL;
282 }
283
284 /**
285  * gst_vaapi_image_format_get_caps:
286  * @format: a #GstVaapiImageFormat
287  *
288  * Converts a #GstVaapiImageFormat into the corresponding #GstCaps. If
289  * no matching caps were found, %NULL is returned.
290  *
291  * Return value: the newly allocated #GstCaps, or %NULL if none was found
292  */
293 GstCaps *
294 gst_vaapi_image_format_get_caps(GstVaapiImageFormat format)
295 {
296     const GstVaapiImageFormatMap * const m = get_map(format);
297
298     return m ? gst_caps_from_string(m->caps_str) : NULL;
299 }
300
301 /**
302  * gst_vaapi_image_format_get_score:
303  * @format: a #GstVaapiImageFormat
304  *
305  * Determines how "native" is this @format. The lower is the returned
306  * score, the best format this is for the underlying hardware.
307  *
308  * Return value: the @format score, or %G_MAXUINT if none was found
309  */
310 guint
311 gst_vaapi_image_format_get_score(GstVaapiImageFormat format)
312 {
313     const GstVaapiImageFormatMap * const m = get_map(format);
314
315     return m ? (m - &gst_vaapi_image_formats[0]) : G_MAXUINT;
316 }