1 /*****************************************************************************
2  * fourcc.c: fourcc helpers functions
3  *****************************************************************************
4  * Copyright © 2009-2011 Laurent Aimar
5  *
6  * Authors: Laurent Aimar <fenrir@videolan.org>
7  *          Jean-Baptiste Kempf <jb@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This program 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
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23 
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30 
31 #include <vlc_common.h>
32 #include <vlc_fourcc.h>
33 #include <vlc_es.h>
34 #include <assert.h>
35 
36 #include "fourcc_tables.h"
37 
fourcc_cmp(const void * key,const void * ent)38 static int fourcc_cmp(const void *key, const void *ent)
39 {
40     return memcmp(key, ent, 4);
41 }
42 
Lookup(vlc_fourcc_t fourcc,const char ** restrict dsc,const struct fourcc_mapping * mapv,size_t mapc,const struct fourcc_desc * dscv,size_t dscc)43 static vlc_fourcc_t Lookup(vlc_fourcc_t fourcc, const char **restrict dsc,
44                            const struct fourcc_mapping *mapv, size_t mapc,
45                            const struct fourcc_desc *dscv, size_t dscc)
46 {
47     const struct fourcc_mapping *mapping;
48     const struct fourcc_desc *desc;
49 
50     mapping = bsearch(&fourcc, mapv, mapc, sizeof (*mapv), fourcc_cmp);
51     if (mapping != NULL)
52     {
53         if (dsc != NULL)
54         {
55             desc = bsearch(&fourcc, dscv, dscc, sizeof (*dscv), fourcc_cmp);
56             if (desc != NULL)
57             {
58                 *dsc = desc->desc;
59                 return mapping->fourcc;
60             }
61         }
62         fourcc = mapping->fourcc;
63     }
64 
65     desc = bsearch(&fourcc, dscv, dscc, sizeof (*dscv), fourcc_cmp);
66     if (desc == NULL)
67         return 0; /* Unknown FourCC */
68     if (dsc != NULL)
69         *dsc = desc->desc;
70     return fourcc; /* Known FourCC (has a description) */
71 }
72 
LookupVideo(vlc_fourcc_t fourcc,const char ** restrict dsc)73 static vlc_fourcc_t LookupVideo(vlc_fourcc_t fourcc, const char **restrict dsc)
74 {
75     return Lookup(fourcc, dsc, mapping_video,
76                   sizeof (mapping_video) / sizeof (mapping_video[0]),
77                   desc_video, sizeof (desc_video) / sizeof (desc_video[0]));
78 }
79 
LookupAudio(vlc_fourcc_t fourcc,const char ** restrict dsc)80 static vlc_fourcc_t LookupAudio(vlc_fourcc_t fourcc, const char **restrict dsc)
81 {
82     return Lookup(fourcc, dsc, mapping_audio,
83                   sizeof (mapping_audio) / sizeof (mapping_audio[0]),
84                   desc_audio, sizeof (desc_audio) / sizeof (desc_audio[0]));
85 }
86 
LookupSpu(vlc_fourcc_t fourcc,const char ** restrict dsc)87 static vlc_fourcc_t LookupSpu(vlc_fourcc_t fourcc, const char **restrict dsc)
88 {
89     return Lookup(fourcc, dsc, mapping_spu,
90                   sizeof (mapping_spu) / sizeof (mapping_spu[0]),
91                   desc_spu, sizeof (desc_spu) / sizeof (desc_spu[0]));
92 }
93 
LookupCat(vlc_fourcc_t fourcc,const char ** restrict dsc,int cat)94 static vlc_fourcc_t LookupCat(vlc_fourcc_t fourcc, const char **restrict dsc,
95                               int cat)
96 {
97     switch (cat)
98     {
99         case VIDEO_ES:
100             return LookupVideo(fourcc, dsc);
101         case AUDIO_ES:
102             return LookupAudio(fourcc, dsc);
103         case SPU_ES:
104             return LookupSpu(fourcc, dsc);
105     }
106 
107     vlc_fourcc_t ret = LookupVideo(fourcc, dsc);
108     if (!ret)
109         ret = LookupAudio(fourcc, dsc);
110     if (!ret)
111         ret = LookupSpu(fourcc, dsc);
112     return ret;
113 }
114 
vlc_fourcc_GetCodec(int cat,vlc_fourcc_t fourcc)115 vlc_fourcc_t vlc_fourcc_GetCodec(int cat, vlc_fourcc_t fourcc)
116 {
117     vlc_fourcc_t codec = LookupCat(fourcc, NULL, cat);
118     return codec ? codec : fourcc;
119 }
120 
vlc_fourcc_GetCodecFromString(int i_cat,const char * psz_fourcc)121 vlc_fourcc_t vlc_fourcc_GetCodecFromString( int i_cat, const char *psz_fourcc )
122 {
123     if( !psz_fourcc || strlen(psz_fourcc) != 4 )
124         return 0;
125     return vlc_fourcc_GetCodec( i_cat,
126                                 VLC_FOURCC( psz_fourcc[0], psz_fourcc[1],
127                                             psz_fourcc[2], psz_fourcc[3] ) );
128 }
129 
vlc_fourcc_GetCodecAudio(vlc_fourcc_t i_fourcc,int i_bits)130 vlc_fourcc_t vlc_fourcc_GetCodecAudio( vlc_fourcc_t i_fourcc, int i_bits )
131 {
132     const int i_bytes = ( i_bits + 7 ) / 8;
133 
134     if( i_fourcc == VLC_FOURCC( 'a', 'f', 'l', 't' ) )
135     {
136         switch( i_bytes )
137         {
138         case 4:
139             return VLC_CODEC_FL32;
140         case 8:
141             return VLC_CODEC_FL64;
142         default:
143             return 0;
144         }
145     }
146     else if( i_fourcc == VLC_FOURCC( 'a', 'r', 'a', 'w' ) )
147     {
148         switch( i_bytes )
149         {
150         case 1:
151             return VLC_CODEC_U8;
152         case 2:
153             return VLC_CODEC_S16L;
154         case 3:
155             return VLC_CODEC_S24L;
156         case 4:
157             return VLC_CODEC_S32L;
158         default:
159             return 0;
160         }
161     }
162     else if( i_fourcc == VLC_FOURCC( 't', 'w', 'o', 's' ) )
163     {
164         switch( i_bytes )
165         {
166         case 1:
167             return VLC_CODEC_S8;
168         case 2:
169             return VLC_CODEC_S16B;
170         case 3:
171             return VLC_CODEC_S24B;
172         case 4:
173             return VLC_CODEC_S32B;
174         default:
175             return 0;
176         }
177     }
178     else if( i_fourcc == VLC_FOURCC( 's', 'o', 'w', 't' ) )
179     {
180         switch( i_bytes )
181         {
182         case 1:
183             return VLC_CODEC_S8;
184         case 2:
185             return VLC_CODEC_S16L;
186         case 3:
187             return VLC_CODEC_S24L;
188         case 4:
189             return VLC_CODEC_S32L;
190         default:
191             return 0;
192         }
193     }
194     else
195     {
196         return vlc_fourcc_GetCodec( AUDIO_ES, i_fourcc );
197     }
198 }
199 
vlc_fourcc_GetDescription(int cat,vlc_fourcc_t fourcc)200 const char *vlc_fourcc_GetDescription(int cat, vlc_fourcc_t fourcc)
201 {
202     const char *ret;
203 
204     return LookupCat(fourcc, &ret, cat) ? ret : "";
205 }
206 
207 
208 /* */
209 #define VLC_CODEC_YUV_PLANAR_410 \
210     VLC_CODEC_I410, VLC_CODEC_YV9
211 
212 #define VLC_CODEC_YUV_PLANAR_420 \
213     VLC_CODEC_I420, VLC_CODEC_YV12, VLC_CODEC_J420
214 
215 #define VLC_CODEC_YUV_SEMIPLANAR_420 \
216     VLC_CODEC_NV12, VLC_CODEC_NV21
217 
218 #define VLC_CODEC_YUV_PLANAR_420_16 \
219     VLC_CODEC_I420_16L, VLC_CODEC_I420_16B, VLC_CODEC_I420_12L, VLC_CODEC_I420_12B, VLC_CODEC_I420_10L, VLC_CODEC_I420_10B, VLC_CODEC_I420_9L, VLC_CODEC_I420_9B
220 
221 #define VLC_CODEC_YUV_SEMIPLANAR_420_16 \
222     VLC_CODEC_P010
223 
224 #define VLC_CODEC_YUV_PLANAR_422 \
225     VLC_CODEC_I422, VLC_CODEC_J422
226 
227 #define VLC_CODEC_YUV_SEMIPLANAR_422 \
228     VLC_CODEC_NV16, VLC_CODEC_NV61
229 
230 #define VLC_CODEC_YUV_PLANAR_422_16 \
231     VLC_CODEC_I422_12L, VLC_CODEC_I422_12B, VLC_CODEC_I422_10L, VLC_CODEC_I422_10B, VLC_CODEC_I422_9L, VLC_CODEC_I422_9B
232 
233 #define VLC_CODEC_YUV_PLANAR_440 \
234     VLC_CODEC_I440, VLC_CODEC_J440
235 
236 #define VLC_CODEC_YUV_PLANAR_444 \
237     VLC_CODEC_I444, VLC_CODEC_J444
238 
239 #define VLC_CODEC_YUV_PLANAR_444_ALPHA \
240     VLC_CODEC_YUVA, VLC_CODEC_YUVA_444_10L, VLC_CODEC_YUVA_444_10B
241 
242 #define VLC_CODEC_YUV_SEMIPLANAR_444 \
243     VLC_CODEC_NV24, VLC_CODEC_NV42
244 
245 #define VLC_CODEC_YUV_PLANAR_444_16 \
246     VLC_CODEC_I444_10L, VLC_CODEC_I444_10B, VLC_CODEC_I444_9L, VLC_CODEC_I444_9B, \
247     VLC_CODEC_I444_16L, VLC_CODEC_I444_16B, VLC_CODEC_I444_12L, VLC_CODEC_I444_12B
248 
249 #define VLC_CODEC_YUV_PACKED \
250     VLC_CODEC_YUYV, VLC_CODEC_YVYU, \
251     VLC_CODEC_UYVY, VLC_CODEC_VYUY
252 
253 #define VLC_CODEC_FALLBACK_420 \
254     VLC_CODEC_YUV_PLANAR_422, VLC_CODEC_YUV_PACKED, \
255     VLC_CODEC_YUV_PLANAR_444, VLC_CODEC_YUV_PLANAR_440, \
256     VLC_CODEC_I411, VLC_CODEC_YUV_PLANAR_410, VLC_CODEC_Y211
257 
258 static const vlc_fourcc_t p_I420_fallback[] = {
259     VLC_CODEC_I420, VLC_CODEC_YV12, VLC_CODEC_J420, VLC_CODEC_FALLBACK_420, 0
260 };
261 static const vlc_fourcc_t p_J420_fallback[] = {
262     VLC_CODEC_J420, VLC_CODEC_I420, VLC_CODEC_YV12, VLC_CODEC_FALLBACK_420, 0
263 };
264 static const vlc_fourcc_t p_YV12_fallback[] = {
265     VLC_CODEC_YV12, VLC_CODEC_I420, VLC_CODEC_J420, VLC_CODEC_FALLBACK_420, 0
266 };
267 static const vlc_fourcc_t p_NV12_fallback[] = {
268     VLC_CODEC_NV12, VLC_CODEC_I420, VLC_CODEC_J420, VLC_CODEC_FALLBACK_420, 0
269 };
270 
271 #define VLC_CODEC_FALLBACK_420_16 \
272     VLC_CODEC_I420, VLC_CODEC_YV12, VLC_CODEC_J420, VLC_CODEC_FALLBACK_420
273 
274 static const vlc_fourcc_t p_I420_9L_fallback[] = {
275     VLC_CODEC_I420_9L, VLC_CODEC_I420_9B, VLC_CODEC_FALLBACK_420_16, 0
276 };
277 static const vlc_fourcc_t p_I420_9B_fallback[] = {
278     VLC_CODEC_I420_9B, VLC_CODEC_I420_9L, VLC_CODEC_FALLBACK_420_16, 0
279 };
280 static const vlc_fourcc_t p_I420_10L_fallback[] = {
281     VLC_CODEC_I420_10L, VLC_CODEC_I420_10B, VLC_CODEC_FALLBACK_420_16, 0
282 };
283 static const vlc_fourcc_t p_I420_10B_fallback[] = {
284     VLC_CODEC_I420_10B, VLC_CODEC_I420_10L, VLC_CODEC_FALLBACK_420_16, 0
285 };
286 static const vlc_fourcc_t p_I420_12L_fallback[] = {
287     VLC_CODEC_I420_12L, VLC_CODEC_I420_12B, VLC_CODEC_FALLBACK_420_16, 0
288 };
289 static const vlc_fourcc_t p_I420_12B_fallback[] = {
290     VLC_CODEC_I420_12B, VLC_CODEC_I420_12L, VLC_CODEC_FALLBACK_420_16, 0
291 };
292 static const vlc_fourcc_t p_I420_16L_fallback[] = {
293     VLC_CODEC_I420_16L, VLC_CODEC_I420_16B, VLC_CODEC_FALLBACK_420_16, 0
294 };
295 static const vlc_fourcc_t p_I420_16B_fallback[] = {
296     VLC_CODEC_I420_16B, VLC_CODEC_I420_16L, VLC_CODEC_FALLBACK_420_16, 0
297 };
298 static const vlc_fourcc_t p_P010_fallback[] = {
299     VLC_CODEC_P010, VLC_CODEC_FALLBACK_420_16, 0
300 };
301 
302 
303 #define VLC_CODEC_FALLBACK_422 \
304     VLC_CODEC_YUV_PACKED, VLC_CODEC_YUV_PLANAR_420, \
305     VLC_CODEC_YUV_PLANAR_444, VLC_CODEC_YUV_PLANAR_440, \
306     VLC_CODEC_I411, VLC_CODEC_YUV_PLANAR_410, VLC_CODEC_Y211
307 
308 static const vlc_fourcc_t p_I422_fallback[] = {
309     VLC_CODEC_I422, VLC_CODEC_J422, VLC_CODEC_FALLBACK_422, 0
310 };
311 static const vlc_fourcc_t p_J422_fallback[] = {
312     VLC_CODEC_J422, VLC_CODEC_I422, VLC_CODEC_FALLBACK_422, 0
313 };
314 
315 #define VLC_CODEC_FALLBACK_422_16 \
316     VLC_CODEC_I422, VLC_CODEC_J422, VLC_CODEC_FALLBACK_422
317 
318 static const vlc_fourcc_t p_I422_9L_fallback[] = {
319     VLC_CODEC_I422_9L, VLC_CODEC_I422_9B, VLC_CODEC_FALLBACK_422_16, 0
320 };
321 static const vlc_fourcc_t p_I422_9B_fallback[] = {
322     VLC_CODEC_I422_9B, VLC_CODEC_I422_9L, VLC_CODEC_FALLBACK_422_16, 0
323 };
324 static const vlc_fourcc_t p_I422_10L_fallback[] = {
325     VLC_CODEC_I422_10L, VLC_CODEC_I422_10B, VLC_CODEC_FALLBACK_422_16, 0
326 };
327 static const vlc_fourcc_t p_I422_10B_fallback[] = {
328     VLC_CODEC_I422_10B, VLC_CODEC_I422_10L, VLC_CODEC_FALLBACK_422_16, 0
329 };
330 static const vlc_fourcc_t p_I422_12L_fallback[] = {
331     VLC_CODEC_I422_12L, VLC_CODEC_I422_12B, VLC_CODEC_FALLBACK_422_16, 0
332 };
333 static const vlc_fourcc_t p_I422_12B_fallback[] = {
334     VLC_CODEC_I422_12B, VLC_CODEC_I422_12L, VLC_CODEC_FALLBACK_422_16, 0
335 };
336 
337 #define VLC_CODEC_FALLBACK_444 \
338     VLC_CODEC_YUV_PLANAR_422, VLC_CODEC_YUV_PACKED, \
339     VLC_CODEC_YUV_PLANAR_420, VLC_CODEC_YUV_PLANAR_440, \
340     VLC_CODEC_I411, VLC_CODEC_YUV_PLANAR_410, VLC_CODEC_Y211
341 
342 static const vlc_fourcc_t p_I444_fallback[] = {
343     VLC_CODEC_I444, VLC_CODEC_J444, VLC_CODEC_FALLBACK_444, 0
344 };
345 static const vlc_fourcc_t p_J444_fallback[] = {
346     VLC_CODEC_J444, VLC_CODEC_I444, VLC_CODEC_FALLBACK_444, 0
347 };
348 
349 #define VLC_CODEC_FALLBACK_444_16 \
350     VLC_CODEC_I444, VLC_CODEC_J444, VLC_CODEC_FALLBACK_444
351 
352 static const vlc_fourcc_t p_I444_9L_fallback[] = {
353     VLC_CODEC_I444_9L, VLC_CODEC_I444_9B, VLC_CODEC_FALLBACK_444_16, 0
354 };
355 static const vlc_fourcc_t p_I444_9B_fallback[] = {
356     VLC_CODEC_I444_9B, VLC_CODEC_I444_9L, VLC_CODEC_FALLBACK_444_16, 0
357 };
358 static const vlc_fourcc_t p_I444_10L_fallback[] = {
359     VLC_CODEC_I444_10L, VLC_CODEC_I444_10B, VLC_CODEC_FALLBACK_444_16, 0
360 };
361 static const vlc_fourcc_t p_I444_10B_fallback[] = {
362     VLC_CODEC_I444_10B, VLC_CODEC_I444_10L, VLC_CODEC_FALLBACK_444_16, 0
363 };
364 static const vlc_fourcc_t p_I444_12L_fallback[] = {
365     VLC_CODEC_I444_12L, VLC_CODEC_I444_12B, VLC_CODEC_FALLBACK_444_16, 0
366 };
367 static const vlc_fourcc_t p_I444_12B_fallback[] = {
368     VLC_CODEC_I444_12B, VLC_CODEC_I444_12L, VLC_CODEC_FALLBACK_444_16, 0
369 };
370 static const vlc_fourcc_t p_I444_16L_fallback[] = {
371     VLC_CODEC_I444_16L, VLC_CODEC_I444_16B, VLC_CODEC_FALLBACK_444_16, 0
372 };
373 static const vlc_fourcc_t p_I444_16B_fallback[] = {
374     VLC_CODEC_I444_16B, VLC_CODEC_I444_16L, VLC_CODEC_FALLBACK_444_16, 0
375 };
376 
377 
378 /* Fallbacks for cvpx */
379 static const vlc_fourcc_t p_CVPX_VIDEO_NV12_fallback[] = {
380     VLC_CODEC_CVPX_NV12, VLC_CODEC_NV12, VLC_CODEC_I420, 0,
381 };
382 static const vlc_fourcc_t p_CVPX_VIDEO_UYVY_fallback[] = {
383     VLC_CODEC_CVPX_UYVY, VLC_CODEC_UYVY, 0,
384 };
385 static const vlc_fourcc_t p_CVPX_VIDEO_I420_fallback[] = {
386     VLC_CODEC_CVPX_I420, VLC_CODEC_I420, 0,
387 };
388 static const vlc_fourcc_t p_CVPX_VIDEO_BGRA_fallback[] = {
389     VLC_CODEC_CVPX_BGRA, VLC_CODEC_BGRA, 0,
390 };
391 static const vlc_fourcc_t p_CVPX_VIDEO_P010_fallback[] = {
392     VLC_CODEC_CVPX_P010, VLC_CODEC_P010, VLC_CODEC_I420_10L, 0
393 };
394 
395 static const vlc_fourcc_t p_VAAPI_420_fallback[] = {
396     VLC_CODEC_VAAPI_420, VLC_CODEC_I420, 0,
397 };
398 
399 static const vlc_fourcc_t p_VAAPI_420_10BPP_fallback[] = {
400     VLC_CODEC_VAAPI_420_10BPP, VLC_CODEC_P010, VLC_CODEC_I420_10L, 0,
401 };
402 
403 static const vlc_fourcc_t p_D3D9_OPAQUE_fallback[] = {
404     VLC_CODEC_D3D9_OPAQUE, VLC_CODEC_I420, 0,
405 };
406 
407 static const vlc_fourcc_t p_D3D9_OPAQUE_10B_fallback[] = {
408     VLC_CODEC_D3D9_OPAQUE_10B, VLC_CODEC_P010, VLC_CODEC_I420_10L, 0,
409 };
410 
411 static const vlc_fourcc_t p_D3D11_OPAQUE_fallback[] = {
412     VLC_CODEC_D3D11_OPAQUE, VLC_CODEC_NV12, 0,
413 };
414 
415 static const vlc_fourcc_t p_D3D11_OPAQUE_10B_fallback[] = {
416     VLC_CODEC_D3D11_OPAQUE_10B, VLC_CODEC_P010, VLC_CODEC_I420_10L, 0,
417 };
418 
419 static const vlc_fourcc_t p_I440_fallback[] = {
420     VLC_CODEC_I440,
421     VLC_CODEC_YUV_PLANAR_420,
422     VLC_CODEC_YUV_PLANAR_422,
423     VLC_CODEC_YUV_PLANAR_444,
424     VLC_CODEC_YUV_PACKED,
425     VLC_CODEC_I411, VLC_CODEC_YUV_PLANAR_410, VLC_CODEC_Y211, 0
426 };
427 
428 #define VLC_CODEC_FALLBACK_PACKED \
429     VLC_CODEC_YUV_PLANAR_422, VLC_CODEC_YUV_PLANAR_420, \
430     VLC_CODEC_YUV_PLANAR_444, VLC_CODEC_YUV_PLANAR_440, \
431     VLC_CODEC_I411, VLC_CODEC_YUV_PLANAR_410, VLC_CODEC_Y211
432 
433 static const vlc_fourcc_t p_YUYV_fallback[] = {
434     VLC_CODEC_YUYV,
435     VLC_CODEC_YVYU,
436     VLC_CODEC_UYVY,
437     VLC_CODEC_VYUY,
438     VLC_CODEC_FALLBACK_PACKED, 0
439 };
440 static const vlc_fourcc_t p_YVYU_fallback[] = {
441     VLC_CODEC_YVYU,
442     VLC_CODEC_YUYV,
443     VLC_CODEC_UYVY,
444     VLC_CODEC_VYUY,
445     VLC_CODEC_FALLBACK_PACKED, 0
446 };
447 static const vlc_fourcc_t p_UYVY_fallback[] = {
448     VLC_CODEC_UYVY,
449     VLC_CODEC_VYUY,
450     VLC_CODEC_YUYV,
451     VLC_CODEC_YVYU,
452     VLC_CODEC_FALLBACK_PACKED, 0
453 };
454 static const vlc_fourcc_t p_VYUY_fallback[] = {
455     VLC_CODEC_VYUY,
456     VLC_CODEC_UYVY,
457     VLC_CODEC_YUYV,
458     VLC_CODEC_YVYU,
459     VLC_CODEC_FALLBACK_PACKED, 0
460 };
461 
462 static const vlc_fourcc_t *pp_YUV_fallback[] = {
463     p_YV12_fallback,
464     p_I420_fallback,
465     p_I420_9L_fallback,
466     p_I420_9B_fallback,
467     p_I420_10L_fallback,
468     p_I420_10B_fallback,
469     p_I420_12L_fallback,
470     p_I420_12B_fallback,
471     p_I420_16L_fallback,
472     p_I420_16B_fallback,
473     p_J420_fallback,
474     p_I422_fallback,
475     p_I422_9L_fallback,
476     p_I422_9B_fallback,
477     p_I422_10L_fallback,
478     p_I422_10B_fallback,
479     p_I422_12L_fallback,
480     p_I422_12B_fallback,
481     p_J422_fallback,
482     p_I444_fallback,
483     p_J444_fallback,
484     p_I444_9L_fallback,
485     p_I444_9B_fallback,
486     p_I444_10L_fallback,
487     p_I444_10B_fallback,
488     p_I444_12L_fallback,
489     p_I444_12B_fallback,
490     p_I444_16L_fallback,
491     p_I444_16B_fallback,
492     p_I440_fallback,
493     p_YUYV_fallback,
494     p_YVYU_fallback,
495     p_UYVY_fallback,
496     p_VYUY_fallback,
497     p_NV12_fallback,
498     p_P010_fallback,
499     p_CVPX_VIDEO_NV12_fallback,
500     p_CVPX_VIDEO_UYVY_fallback,
501     p_CVPX_VIDEO_I420_fallback,
502     p_CVPX_VIDEO_P010_fallback,
503     p_VAAPI_420_fallback,
504     p_VAAPI_420_10BPP_fallback,
505     p_D3D9_OPAQUE_fallback,
506     p_D3D9_OPAQUE_10B_fallback,
507     p_D3D11_OPAQUE_fallback,
508     p_D3D11_OPAQUE_10B_fallback,
509     NULL,
510 };
511 
512 static const vlc_fourcc_t p_list_YUV[] = {
513     VLC_CODEC_YUV_PLANAR_420,
514     VLC_CODEC_YUV_SEMIPLANAR_420,
515     VLC_CODEC_YUV_PLANAR_422,
516     VLC_CODEC_YUV_SEMIPLANAR_422,
517     VLC_CODEC_YUV_PLANAR_440,
518     VLC_CODEC_YUV_PLANAR_444,
519     VLC_CODEC_YUV_PLANAR_444_ALPHA,
520     VLC_CODEC_YUV_SEMIPLANAR_444,
521     VLC_CODEC_YUV_PACKED,
522     VLC_CODEC_I411, VLC_CODEC_YUV_PLANAR_410, VLC_CODEC_Y211,
523     VLC_CODEC_YUV_PLANAR_420_16,
524     VLC_CODEC_YUV_SEMIPLANAR_420_16,
525     VLC_CODEC_YUV_PLANAR_422_16,
526     VLC_CODEC_YUV_PLANAR_444_16,
527     VLC_CODEC_VDPAU_VIDEO_420,
528     VLC_CODEC_VDPAU_VIDEO_422,
529     VLC_CODEC_VDPAU_VIDEO_444,
530     VLC_CODEC_CVPX_NV12,
531     VLC_CODEC_CVPX_UYVY,
532     VLC_CODEC_CVPX_I420,
533     VLC_CODEC_CVPX_P010,
534     VLC_CODEC_VAAPI_420,
535     VLC_CODEC_VAAPI_420_10BPP,
536     VLC_CODEC_D3D9_OPAQUE,
537     VLC_CODEC_D3D9_OPAQUE_10B,
538     VLC_CODEC_D3D11_OPAQUE,
539     VLC_CODEC_D3D11_OPAQUE_10B,
540     0,
541 };
542 
543 /* */
544 static const vlc_fourcc_t p_RGB32_fallback[] = {
545     VLC_CODEC_RGB32,
546     VLC_CODEC_RGB24,
547     VLC_CODEC_RGB16,
548     VLC_CODEC_RGB15,
549     VLC_CODEC_RGB8,
550     0,
551 };
552 static const vlc_fourcc_t p_RGB24_fallback[] = {
553     VLC_CODEC_RGB24,
554     VLC_CODEC_RGB32,
555     VLC_CODEC_RGB16,
556     VLC_CODEC_RGB15,
557     VLC_CODEC_RGB8,
558     0,
559 };
560 static const vlc_fourcc_t p_RGB16_fallback[] = {
561     VLC_CODEC_RGB16,
562     VLC_CODEC_RGB24,
563     VLC_CODEC_RGB32,
564     VLC_CODEC_RGB15,
565     VLC_CODEC_RGB8,
566     0,
567 };
568 static const vlc_fourcc_t p_RGB15_fallback[] = {
569     VLC_CODEC_RGB15,
570     VLC_CODEC_RGB16,
571     VLC_CODEC_RGB24,
572     VLC_CODEC_RGB32,
573     VLC_CODEC_RGB8,
574     0,
575 };
576 static const vlc_fourcc_t p_RGB8_fallback[] = {
577     VLC_CODEC_RGB8,
578     VLC_CODEC_RGB15,
579     VLC_CODEC_RGB16,
580     VLC_CODEC_RGB24,
581     VLC_CODEC_RGB32,
582     0,
583 };
584 static const vlc_fourcc_t *pp_RGB_fallback[] = {
585     p_RGB32_fallback,
586     p_RGB24_fallback,
587     p_RGB16_fallback,
588     p_RGB15_fallback,
589     p_RGB8_fallback,
590     p_CVPX_VIDEO_BGRA_fallback,
591 
592     NULL,
593 };
594 
595 
596 /* */
GetFallback(vlc_fourcc_t i_fourcc,const vlc_fourcc_t * pp_fallback[],const vlc_fourcc_t p_list[])597 static const vlc_fourcc_t *GetFallback( vlc_fourcc_t i_fourcc,
598                                         const vlc_fourcc_t *pp_fallback[],
599                                         const vlc_fourcc_t p_list[] )
600 {
601     for( unsigned i = 0; pp_fallback[i]; i++ )
602     {
603         if( pp_fallback[i][0] == i_fourcc )
604             return pp_fallback[i];
605     }
606     return p_list;
607 }
608 
vlc_fourcc_GetYUVFallback(vlc_fourcc_t i_fourcc)609 const vlc_fourcc_t *vlc_fourcc_GetYUVFallback( vlc_fourcc_t i_fourcc )
610 {
611     return GetFallback( i_fourcc, pp_YUV_fallback, p_list_YUV );
612 }
vlc_fourcc_GetRGBFallback(vlc_fourcc_t i_fourcc)613 const vlc_fourcc_t *vlc_fourcc_GetRGBFallback( vlc_fourcc_t i_fourcc )
614 {
615     return GetFallback( i_fourcc, pp_RGB_fallback, p_RGB32_fallback );
616 }
617 
vlc_fourcc_AreUVPlanesSwapped(vlc_fourcc_t a,vlc_fourcc_t b)618 bool vlc_fourcc_AreUVPlanesSwapped( vlc_fourcc_t a, vlc_fourcc_t b )
619 {
620     static const vlc_fourcc_t pp_swapped[][4] = {
621         { VLC_CODEC_YV12, VLC_CODEC_I420, VLC_CODEC_J420, 0 },
622         { VLC_CODEC_YV9,  VLC_CODEC_I410, 0 },
623         { 0 }
624     };
625 
626     for( int i = 0; pp_swapped[i][0]; i++ )
627     {
628         if( pp_swapped[i][0] == b )
629         {
630             vlc_fourcc_t t = a;
631             a = b;
632             b = t;
633         }
634         if( pp_swapped[i][0] != a )
635             continue;
636         for( int j = 1; pp_swapped[i][j]; j++ )
637         {
638             if( pp_swapped[i][j] == b )
639                 return true;
640         }
641     }
642     return false;
643 }
644 
vlc_fourcc_IsYUV(vlc_fourcc_t fcc)645 bool vlc_fourcc_IsYUV(vlc_fourcc_t fcc)
646 {
647     for( unsigned i = 0; p_list_YUV[i]; i++ )
648     {
649         if( p_list_YUV[i] == fcc )
650             return true;
651     }
652     return false;
653 }
654 
655 #define PLANAR(n, w_den, h_den, size, bits) \
656     { .plane_count = n, \
657       .p = { {.w = {1,    1}, .h = {1,    1}}, \
658              {.w = {1,w_den}, .h = {1,h_den}}, \
659              {.w = {1,w_den}, .h = {1,h_den}}, \
660              {.w = {1,    1}, .h = {1,    1}} }, \
661       .pixel_size = size, \
662       .pixel_bits = bits }
663 
664 #define PLANAR_8(n, w_den, h_den)        PLANAR(n, w_den, h_den, 1, 8)
665 #define PLANAR_16(n, w_den, h_den, bits) PLANAR(n, w_den, h_den, 2, bits)
666 
667 #define SEMIPLANAR(w_den, h_den, size, bits) \
668     { .plane_count = 2, \
669       .p = { {.w = {1,    1}, .h = {1,    1}}, \
670              {.w = {2,w_den}, .h = {1,h_den}} }, \
671       .pixel_size = size, \
672       .pixel_bits = bits }
673 
674 #define PACKED_FMT(size, bits) \
675     { .plane_count = 1, \
676       .p = { {.w = {1,1}, .h = {1,1}} }, \
677       .pixel_size = size, \
678       .pixel_bits = bits }
679 
680 /* Zero planes for hardware picture handles. Cannot be manipulated directly. */
681 #define FAKE_FMT() \
682     { .plane_count = 0, \
683       .p = { {.w = {1,1}, .h = {1,1}} }, \
684       .pixel_size = 0, \
685       .pixel_bits = 0 }
686 
687 static const struct
688 {
689     vlc_fourcc_t             p_fourcc[4];
690     vlc_chroma_description_t description;
691 } p_list_chroma_description[] = {
692     { { VLC_CODEC_I411 },                      PLANAR_8(3, 4, 1) },
693     { { VLC_CODEC_YUV_PLANAR_410 },            PLANAR_8(3, 4, 4) },
694     { { VLC_CODEC_YUV_PLANAR_420 },            PLANAR_8(3, 2, 2) },
695     { { VLC_CODEC_NV12, VLC_CODEC_NV21 },      SEMIPLANAR(2, 2, 1, 8) },
696     { { VLC_CODEC_YUV_PLANAR_422 },            PLANAR_8(3, 2, 1) },
697     { { VLC_CODEC_NV16, VLC_CODEC_NV61 },      PLANAR_8(2, 1, 1) },
698     { { VLC_CODEC_YUV_PLANAR_440 },            PLANAR_8(3, 1, 2) },
699     { { VLC_CODEC_YUV_PLANAR_444 },            PLANAR_8(3, 1, 1) },
700     { { VLC_CODEC_YUVA },                      PLANAR_8(4, 1, 1) },
701     { { VLC_CODEC_YUV420A },                   PLANAR_8(4, 2, 2) },
702     { { VLC_CODEC_YUV422A },                   PLANAR_8(4, 2, 1) },
703 
704     { { VLC_CODEC_GBR_PLANAR },                PLANAR_8(3, 1, 1) },
705     { { VLC_CODEC_GBR_PLANAR_9L,
706         VLC_CODEC_GBR_PLANAR_9B },             PLANAR_16(3, 1, 1, 9) },
707     { { VLC_CODEC_GBR_PLANAR_10L,
708         VLC_CODEC_GBR_PLANAR_10B },            PLANAR_16(3, 1, 1, 10) },
709     { { VLC_CODEC_GBR_PLANAR_16L,
710         VLC_CODEC_GBR_PLANAR_16B },            PLANAR_16(3, 1, 1, 16) },
711 
712     { { VLC_CODEC_I420_16L,
713         VLC_CODEC_I420_16B },                  PLANAR_16(3, 2, 2, 16) },
714     { { VLC_CODEC_I420_12L,
715         VLC_CODEC_I420_12B },                  PLANAR_16(3, 2, 2, 12) },
716     { { VLC_CODEC_I420_10L,
717         VLC_CODEC_I420_10B },                  PLANAR_16(3, 2, 2, 10) },
718     { { VLC_CODEC_I420_9L,
719         VLC_CODEC_I420_9B },                   PLANAR_16(3, 2, 2,  9) },
720     { { VLC_CODEC_I422_12L,
721         VLC_CODEC_I422_12B },                  PLANAR_16(3, 2, 1, 12) },
722     { { VLC_CODEC_I422_10L,
723         VLC_CODEC_I422_10B },                  PLANAR_16(3, 2, 1, 10) },
724     { { VLC_CODEC_I422_9L,
725         VLC_CODEC_I422_9B },                   PLANAR_16(3, 2, 1,  9) },
726     { { VLC_CODEC_I444_12L,
727         VLC_CODEC_I444_12B },                  PLANAR_16(3, 1, 1, 12) },
728     { { VLC_CODEC_I444_10L,
729         VLC_CODEC_I444_10B },                  PLANAR_16(3, 1, 1, 10) },
730     { { VLC_CODEC_I444_9L,
731         VLC_CODEC_I444_9B },                   PLANAR_16(3, 1, 1,  9) },
732     { { VLC_CODEC_I444_16L,
733         VLC_CODEC_I444_16B },                  PLANAR_16(3, 1, 1, 16) },
734     { { VLC_CODEC_YUVA_444_10L,
735         VLC_CODEC_YUVA_444_10B },              PLANAR_16(4, 1, 1, 10) },
736     { { VLC_CODEC_P010 },                      SEMIPLANAR(2, 2, 2, 10) },
737 
738     { { VLC_CODEC_YUV_PACKED },                PACKED_FMT(2, 16) },
739     { { VLC_CODEC_RGB8, VLC_CODEC_GREY,
740         VLC_CODEC_YUVP, VLC_CODEC_RGBP },      PACKED_FMT(1, 8) },
741 
742     { { VLC_CODEC_RGB15, 0 },                  PACKED_FMT(2, 15) },
743     { { VLC_CODEC_RGB12, 0 },                  PACKED_FMT(2, 12) },
744     { { VLC_CODEC_RGB16, 0 },                  PACKED_FMT(2, 16) },
745     { { VLC_CODEC_RGB24, 0 },                  PACKED_FMT(3, 24) },
746     { { VLC_CODEC_RGB32, 0 },                  PACKED_FMT(4, 24) },
747     { { VLC_CODEC_RGBA, VLC_CODEC_ARGB,
748         VLC_CODEC_BGRA, VLC_CODEC_RGBA10 },    PACKED_FMT(4, 32) },
749     { { VLC_CODEC_RGBA64, 0 },                 PACKED_FMT(8, 64) },
750     { { VLC_CODEC_VUYA, 0 },                   PACKED_FMT(4, 32) },
751 
752     { { VLC_CODEC_Y211, 0 },                   { 1, { {{1,4}, {1,1}} }, 4, 32 } },
753     { { VLC_CODEC_XYZ12,  0 },                 PACKED_FMT(6, 48) },
754 
755     { { VLC_CODEC_VDPAU_VIDEO_420, VLC_CODEC_VDPAU_VIDEO_422,
756         VLC_CODEC_VDPAU_VIDEO_444, VLC_CODEC_VDPAU_OUTPUT },
757                                                FAKE_FMT() },
758     { { VLC_CODEC_ANDROID_OPAQUE, VLC_CODEC_MMAL_OPAQUE,
759         VLC_CODEC_D3D9_OPAQUE,    VLC_CODEC_D3D11_OPAQUE },
760                                                FAKE_FMT() },
761     { { VLC_CODEC_D3D11_OPAQUE_10B, VLC_CODEC_D3D9_OPAQUE_10B },
762                                                FAKE_FMT() },
763 
764     { { VLC_CODEC_CVPX_NV12, VLC_CODEC_CVPX_UYVY,
765         VLC_CODEC_CVPX_I420, VLC_CODEC_CVPX_BGRA },
766                                                FAKE_FMT() },
767 
768     { { VLC_CODEC_CVPX_P010, 0 },              FAKE_FMT() },
769 
770     { { VLC_CODEC_VAAPI_420, VLC_CODEC_VAAPI_420_10BPP },
771                                                FAKE_FMT() },
772 
773     { { 0 },                                   FAKE_FMT() }
774 };
775 
776 #undef PACKED_FMT
777 #undef PLANAR_16
778 #undef PLANAR_8
779 #undef PLANAR
780 
vlc_fourcc_GetChromaDescription(vlc_fourcc_t i_fourcc)781 const vlc_chroma_description_t *vlc_fourcc_GetChromaDescription( vlc_fourcc_t i_fourcc )
782 {
783     for( unsigned i = 0; p_list_chroma_description[i].p_fourcc[0]; i++ )
784     {
785         const vlc_fourcc_t *p_fourcc = p_list_chroma_description[i].p_fourcc;
786         for( unsigned j = 0; j < 4 && p_fourcc[j] != 0; j++ )
787         {
788             if( p_fourcc[j] == i_fourcc )
789                 return &p_list_chroma_description[i].description;
790         }
791     }
792     return NULL;
793 }
794