decoder: h264: fix marking of non-reference picture into DPB.
[platform/upstream/gstreamer-vaapi.git] / gst-libs / gst / vaapi / video-format.c
1 /*
2  *  video-format.h - Video format helpers for VA-API
3  *
4  *  Copyright (C) 2010-2011 Splitted-Desktop Systems
5  *    Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
6  *  Copyright (C) 2011-2013 Intel Corporation
7  *    Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
8  *
9  *  This library is free software; you can redistribute it and/or
10  *  modify it under the terms of the GNU Lesser General Public License
11  *  as published by the Free Software Foundation; either version 2.1
12  *  of the License, or (at your option) any later version.
13  *
14  *  This library is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  *  Lesser General Public License for more details.
18  *
19  *  You should have received a copy of the GNU Lesser General Public
20  *  License along with this library; if not, write to the Free
21  *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  *  Boston, MA 02110-1301 USA
23  */
24
25 /**
26  * SECTION:videoformat
27  * @short_description: Video format helpers for VA-API
28  */
29
30 #include "sysdeps.h"
31 #include "gstvaapicompat.h"
32 #include "gstvaapisurface.h"
33 #include "video-format.h"
34
35 typedef struct
36 {
37   GstVideoFormat format;
38   GstVaapiChromaType chroma_type;
39   VAImageFormat va_format;
40 } GstVideoFormatMap;
41
42 #define DEF_YUV(FORMAT, FOURCC, ENDIAN, BPP, SUB)                       \
43   { G_PASTE(GST_VIDEO_FORMAT_,FORMAT),                                  \
44     G_PASTE(GST_VAAPI_CHROMA_TYPE_YUV,SUB),                             \
45     { VA_FOURCC FOURCC, VA_##ENDIAN##_FIRST, BPP, }, }
46
47 #define DEF_RGB(FORMAT, FOURCC, ENDIAN, BPP, DEPTH, R,G,B,A)            \
48   { G_PASTE(GST_VIDEO_FORMAT_,FORMAT),                                  \
49     G_PASTE(GST_VAAPI_CHROMA_TYPE_RGB,BPP),                             \
50     { VA_FOURCC FOURCC, VA_##ENDIAN##_FIRST, BPP, DEPTH, R,G,B,A }, }
51
52 /* Image formats, listed in HW order preference */
53 static const GstVideoFormatMap gst_vaapi_video_formats[] = {
54   DEF_YUV (NV12, ('N', 'V', '1', '2'), LSB, 12, 420),
55   DEF_YUV (YV12, ('Y', 'V', '1', '2'), LSB, 12, 420),
56   DEF_YUV (I420, ('I', '4', '2', '0'), LSB, 12, 420),
57   DEF_YUV (YUY2, ('Y', 'U', 'Y', '2'), LSB, 16, 422),
58   DEF_YUV (UYVY, ('U', 'Y', 'V', 'Y'), LSB, 16, 422),
59   DEF_YUV (AYUV, ('A', 'Y', 'U', 'V'), LSB, 32, 444),
60 #if G_BYTE_ORDER == G_BIG_ENDIAN
61   DEF_RGB (ARGB, ('A', 'R', 'G', 'B'), MSB, 32,
62       32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000),
63   DEF_RGB (ABGR, ('A', 'B', 'G', 'R'), MSB, 32,
64       32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000),
65   DEF_RGB (xRGB, ('X', 'R', 'G', 'B'), MSB, 32,
66       24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000),
67   DEF_RGB (xBGR, ('X', 'B', 'G', 'R'), MSB, 32,
68       24, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000),
69 #elif G_BYTE_ORDER == G_LITTLE_ENDIAN
70   DEF_RGB (BGRA, ('B', 'G', 'R', 'A'), LSB, 32,
71       32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000),
72   DEF_RGB (RGBA, ('R', 'G', 'B', 'A'), LSB, 32,
73       32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000),
74   DEF_RGB (BGRx, ('B', 'G', 'R', 'X'), LSB, 32,
75       24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000),
76   DEF_RGB (RGBx, ('R', 'G', 'B', 'X'), LSB, 32,
77       24, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000),
78 #endif
79   DEF_YUV (GRAY8, ('Y', '8', '0', '0'), LSB, 8, 400),
80   {0,}
81 };
82
83 #undef DEF_RGB
84 #undef DEF_YUV
85
86 static inline gboolean
87 va_format_is_rgb (const VAImageFormat * va_format)
88 {
89   return va_format->depth != 0;
90 }
91
92 static inline gboolean
93 va_format_is_yuv (const VAImageFormat * va_format)
94 {
95   return va_format->depth == 0;
96 }
97
98 static inline gboolean
99 va_format_is_same_rgb (const VAImageFormat * fmt1, const VAImageFormat * fmt2)
100 {
101   return (fmt1->byte_order == fmt2->byte_order &&
102       fmt1->red_mask == fmt2->red_mask &&
103       fmt1->green_mask == fmt2->green_mask &&
104       fmt1->blue_mask == fmt2->blue_mask &&
105       fmt1->alpha_mask == fmt2->alpha_mask);
106 }
107
108 static inline gboolean
109 va_format_is_same (const VAImageFormat * fmt1, const VAImageFormat * fmt2)
110 {
111   if (fmt1->fourcc != fmt2->fourcc)
112     return FALSE;
113   return va_format_is_rgb (fmt1) ? va_format_is_same_rgb (fmt1, fmt2) : TRUE;
114 }
115
116 static const GstVideoFormatMap *
117 get_map (GstVideoFormat format)
118 {
119   const GstVideoFormatMap *m;
120
121   for (m = gst_vaapi_video_formats; m->format; m++) {
122     if (m->format == format)
123       return m;
124   }
125   return NULL;
126 }
127
128 /**
129  * gst_vaapi_video_format_from_string:
130  * @str: a string representation of #GstVideoFormat
131  *
132  * Returns the #GstVideoFormat represented as the string @str.
133  *
134  * Return value: #GstVideoFormat for the string representation of
135  *   video format in @str.
136  */
137 GstVideoFormat
138 gst_vaapi_video_format_from_string (const gchar * str)
139 {
140 #if GST_CHECK_VERSION(1,0,0)
141   return gst_video_format_from_string (str);
142 #else
143   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
144
145   do {
146     /* Validate input string */
147     if (!str)
148       break;
149
150     /* Fast path: assume this represents a common fourcc value */
151     const guint32 fourcc = GST_MAKE_FOURCC (str[0], str[1], str[2], str[3]);
152     format = gst_video_format_from_fourcc (fourcc);
153     if (format != GST_VIDEO_FORMAT_UNKNOWN)
154       break;
155
156     /* Slow path: check through all registered enum values */
157     GEnumClass *const enum_class = g_type_class_ref (GST_TYPE_VIDEO_FORMAT);
158     if (!enum_class)
159       break;
160
161     gchar *const video_format_str =
162         g_strdup_printf ("GST_VIDEO_FORMAT_%s", str);
163     if (video_format_str) {
164       const GEnumValue *const enum_value =
165           g_enum_get_value_by_name (enum_class, video_format_str);
166
167       if (enum_value)
168         format = enum_value->value;
169       g_free (video_format_str);
170     }
171     g_type_class_unref (enum_class);
172   } while (0);
173   return format;
174 #endif
175 }
176
177 /**
178  * gst_vaapi_video_format_to_string:
179  * @format: a #GstVideoFormat
180  *
181  * Returns the string representation of the @format argument.
182  *
183  * Return value: string representation of @format, or %NULL if unknown
184  *   or unsupported.
185  */
186 const gchar *
187 gst_vaapi_video_format_to_string (GstVideoFormat format)
188 {
189   return gst_video_format_to_string (format);
190 }
191
192 /**
193  * gst_vaapi_video_format_is_rgb:
194  * @format: a #GstVideoFormat
195  *
196  * Checks whether the format is an RGB format.
197  *
198  * Return value: %TRUE if @format is RGB format
199  */
200 gboolean
201 gst_vaapi_video_format_is_rgb (GstVideoFormat format)
202 {
203   const GstVideoFormatMap *const m = get_map (format);
204
205   return m && va_format_is_rgb (&m->va_format);
206 }
207
208 /**
209  * gst_vaapi_video_format_is_yuv:
210  * @format: a #GstVideoFormat
211  *
212  * Checks whether the format is an YUV format.
213  *
214  * Return value: %TRUE if @format is YUV format
215  */
216 gboolean
217 gst_vaapi_video_format_is_yuv (GstVideoFormat format)
218 {
219   const GstVideoFormatMap *const m = get_map (format);
220
221   return m && va_format_is_yuv (&m->va_format);
222 }
223
224 /**
225  * gst_vaapi_video_format_from_va_fourcc:
226  * @fourcc: a FOURCC value
227  *
228  * Converts a VA fourcc into the corresponding #GstVideoFormat. If no
229  * matching fourcc was found, then zero is returned.
230  *
231  * Return value: the #GstVideoFormat corresponding to the VA @fourcc
232  */
233 GstVideoFormat
234 gst_vaapi_video_format_from_va_fourcc (guint32 fourcc)
235 {
236   const GstVideoFormatMap *m;
237
238   /* Note: VA fourcc values are now standardized and shall represent
239      a unique format. The associated VAImageFormat is just a hint to
240      determine RGBA component ordering */
241   for (m = gst_vaapi_video_formats; m->format; m++) {
242     if (m->va_format.fourcc == fourcc)
243       return m->format;
244   }
245   return GST_VIDEO_FORMAT_UNKNOWN;
246 }
247
248 /**
249  * gst_vaapi_video_format_from_va_format:
250  * @va_format: a #VAImageFormat
251  *
252  * Converts a VA image format into the corresponding #GstVideoFormat.
253  * If the image format cannot be represented by #GstVideoFormat,
254  * then zero is returned.
255  *
256  * Return value: the #GstVideoFormat describing the @va_format
257  */
258 GstVideoFormat
259 gst_vaapi_video_format_from_va_format (const VAImageFormat * va_format)
260 {
261   const GstVideoFormatMap *m;
262
263   for (m = gst_vaapi_video_formats; m->format; m++) {
264     if (va_format_is_same (&m->va_format, va_format))
265       return m->format;
266   }
267   return GST_VIDEO_FORMAT_UNKNOWN;
268 }
269
270 /**
271  * gst_vaapi_video_format_to_va_format:
272  * @format: a #GstVideoFormat
273  *
274  * Converts a #GstVideoFormat into the corresponding VA image
275  * format. If no matching VA image format was found, %NULL is returned
276  * and this error must be reported to be fixed.
277  *
278  * Return value: the VA image format, or %NULL if none was found
279  */
280 const VAImageFormat *
281 gst_vaapi_video_format_to_va_format (GstVideoFormat format)
282 {
283   const GstVideoFormatMap *const m = get_map (format);
284
285   return m ? &m->va_format : NULL;
286 }
287
288 /**
289  * gst_vaapi_video_format_get_chroma_type:
290  * @format: a #GstVideoFormat
291  *
292  * Converts a #GstVideoFormat into the corresponding #GstVaapiChromaType
293  * format.
294  *
295  * Return value: the #GstVaapiChromaType format, or zero if no match
296  *   was found.
297  */
298 guint
299 gst_vaapi_video_format_get_chroma_type (GstVideoFormat format)
300 {
301   const GstVideoFormatMap *const m = get_map (format);
302
303   return m ? m->chroma_type : 0;
304 }
305
306 /**
307  * gst_vaapi_video_format_get_score:
308  * @format: a #GstVideoFormat
309  *
310  * Determines how "native" is this @format. The lower is the returned
311  * score, the best format this is for the underlying hardware.
312  *
313  * Return value: the @format score, or %G_MAXUINT if none was found
314  */
315 guint
316 gst_vaapi_video_format_get_score (GstVideoFormat format)
317 {
318   const GstVideoFormatMap *const m = get_map (format);
319
320   return m ? (m - &gst_vaapi_video_formats[0]) : G_MAXUINT;
321 }