• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) 2020 Igalia, S.L.
3  *     Author: Víctor Jáquez <vjaquez@igalia.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include "gstvavideoformat.h"
26 
27 GST_DEBUG_CATEGORY_STATIC (gstva_debug);
28 
29 #define VA_NSB_FIRST 0          /* No Significant Bit  */
30 
31 /* *INDENT-OFF* */
32 static struct FormatMap
33 {
34   GstVideoFormat format;
35   guint va_rtformat;
36   VAImageFormat va_format;
37 } format_map[] = {
38 #define F(format, fourcc, rtformat, order, bpp, depth, r, g, b, a) {      \
39     G_PASTE (GST_VIDEO_FORMAT_, format),                                \
40     G_PASTE (VA_RT_FORMAT_, rtformat),                             \
41     { VA_FOURCC fourcc, G_PASTE (G_PASTE (VA_, order), _FIRST),    \
42       bpp, depth, r, g, b, a } }
43 #define G(format, fourcc, rtformat, order, bpp) \
44     F (format, fourcc, rtformat, order, bpp, 0, 0, 0 ,0, 0)
45   G (NV12, ('N', 'V', '1', '2'), YUV420, NSB, 12),
46   G (NV21, ('N', 'V', '2', '1'), YUV420, NSB, 21),
47   G (VUYA, ('A', 'Y', 'U', 'V'), YUV444, LSB, 32),
48   F (RGBA, ('R', 'G', 'B', 'A'), RGB32, LSB, 32, 32, 0x000000ff,
49       0x0000ff00, 0x00ff0000, 0xff000000),
50   F (RGBx, ('R', 'G', 'B', 'X'), RGB32, LSB, 32, 24, 0x000000ff,
51       0x0000ff00, 0x00ff0000, 0x00000000),
52   F (BGRA, ('B', 'G', 'R', 'A'), RGB32, LSB, 32, 32, 0x00ff0000,
53       0x0000ff00, 0x000000ff, 0xff000000),
54   F (ARGB, ('A', 'R', 'G', 'B'), RGB32, LSB, 32, 32, 0x0000ff00,
55       0x00ff0000, 0xff000000, 0x000000ff),
56   F (xRGB, ('X', 'R', 'G', 'B'), RGB32, LSB, 32, 24, 0x0000ff00,
57       0x00ff0000, 0xff000000, 0x00000000),
58   F (ABGR, ('A', 'B', 'G', 'R'), RGB32, LSB, 32, 32, 0xff000000,
59       0x00ff0000, 0x0000ff00, 0x000000ff),
60   F (xBGR, ('X', 'B', 'G', 'R'), RGB32, LSB, 32, 24, 0xff000000,
61       0x00ff0000, 0x0000ff00, 0x00000000),
62   F (BGRx, ('B', 'G', 'R', 'X'), RGB32, LSB, 32, 24, 0x00ff0000,
63       0x0000ff00, 0x000000ff, 0x00000000),
64   G (UYVY, ('U', 'Y', 'V', 'Y'), YUV422, NSB, 16),
65   G (YUY2, ('Y', 'U', 'Y', '2'), YUV422, NSB, 16),
66   G (AYUV, ('A', 'Y', 'U', 'V'), YUV444, LSB, 32),
67   /* F (????, NV11), */
68   G (YV12, ('Y', 'V', '1', '2'), YUV420, NSB, 12),
69   /* F (????, P208), */
70   G (I420, ('I', '4', '2', '0'), YUV420, NSB, 12),
71   /* F (????, YV24), */
72   /* F (????, YV32), */
73   /* F (????, Y800), */
74   /* F (????, IMC3), */
75   /* F (????, 411P), */
76   /* F (????, 411R), */
77   /* F (????, 422H), */
78   /* F (????, 422V), */
79   /* F (????, 444P), */
80   /* F (????, RGBP), */
81   /* F (????, BGRP), */
82   /* F (????, RGB565), */
83   /* F (????, BGR565), */
84   G (Y210, ('Y', '2', '1', '0'), YUV422_10, NSB, 32),
85   /* F (????, Y216), */
86   G (Y410, ('Y', '4', '1', '0'), YUV444_10, NSB, 32),
87   G (Y212_LE, ('Y', '2', '1', '2'), YUV422_12, NSB, 32),
88   G (Y412_LE, ('Y', '4', '1', '2'), YUV444_12, NSB, 32),
89   /* F (????, Y416), */
90   /* F (????, YV16), */
91   G (P010_10LE, ('P', '0', '1', '0'), YUV420_10, NSB, 24),
92   G (P012_LE, ('P', '0', '1', '2'), YUV420_12, NSB, 24),
93   /* F (P016_LE, P016, ????), */
94   /* F (????, I010), */
95   /* F (????, IYUV), */
96   /* F (????, A2R10G10B10), */
97   /* F (????, A2B10G10R10), */
98   /* F (????, X2R10G10B10), */
99   /* F (????, X2B10G10R10), */
100   G (GRAY8, ('Y', '8', '0', '0'), YUV400, NSB, 8),
101   G (Y444, ('4', '4', '4', 'P'), YUV444, NSB, 24),
102   /* F (????, Y16), */
103   /* G (VYUY, VYUY, YUV422), */
104   /* G (YVYU, YVYU, YUV422), */
105   /* F (ARGB64, ARGB64, ????), */
106   /* F (????, ABGR64), */
107   F (RGB16, ('R', 'G', '1', '6'), RGB16, NSB, 16, 16, 0x0000f800,
108      0x000007e0, 0x0000001f, 0x00000000),
109   F (RGB, ('R', 'G', '2', '4'), RGB32, NSB, 32, 24, 0x00ff0000,
110      0x0000ff00, 0x000000ff, 0x00000000),
111   F (BGR10A2_LE, ('A', 'R', '3', '0'), RGB32, LSB, 32, 30, 0x3ff00000,
112      0x000ffc00, 0x000003ff, 0x30000000),
113 #undef F
114 #undef G
115 };
116 
117 static const struct RBG32FormatMap
118 {
119   GstVideoFormat format;
120   VAImageFormat va_format[2];
121 } rgb32_format_map[] = {
122 #define  F(fourcc, order, bpp, depth, r, g, b, a)                       \
123   {  VA_FOURCC fourcc, G_PASTE (G_PASTE (VA_, order), _FIRST), bpp, depth, r, g, b, a }
124 #define  A(fourcc, order, r, g, b, a) F (fourcc, order, 32, 32, r, g, b, a)
125 #define  X(fourcc, order, r, g, b) F (fourcc, order, 32, 24, r, g, b, 0x0)
126   { GST_VIDEO_FORMAT_ARGB, {
127       A (('B', 'G', 'R', 'A'), LSB, 0x0000ff00, 0x00ff0000, 0xff000000, 0x000000ff),
128       A (('A', 'R', 'G', 'B'), MSB, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000),
129     } },
130   { GST_VIDEO_FORMAT_RGBA, {
131       A (('A', 'B', 'G', 'R'), LSB, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000),
132       A (('R', 'G', 'B', 'A'), MSB, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff),
133     } },
134   { GST_VIDEO_FORMAT_ABGR, {
135       A (('R', 'G', 'B', 'A'), LSB, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff),
136       A (('A', 'B', 'G', 'R'), MSB, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000),
137     } },
138   { GST_VIDEO_FORMAT_BGRA, {
139       A (('A', 'R', 'G', 'B'), LSB, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000),
140       A (('B', 'G', 'R', 'A'), MSB, 0x0000ff00, 0x00ff0000, 0xff000000, 0x000000ff),
141     } },
142   { GST_VIDEO_FORMAT_xRGB, {
143       X (('B', 'G', 'R', 'X'), LSB, 0x0000ff00, 0x00ff0000, 0xff000000),
144       X (('X', 'R', 'G', 'B'), MSB, 0x00ff0000, 0x0000ff00, 0x000000ff),
145     } },
146   { GST_VIDEO_FORMAT_RGBx, {
147       X (('X', 'B', 'G', 'R'), LSB, 0x000000ff, 0x0000ff00, 0x00ff0000),
148       X (('R', 'G', 'B', 'X'), MSB, 0xff000000, 0x00ff0000, 0x0000ff00),
149     } },
150   { GST_VIDEO_FORMAT_xBGR, {
151       X (('R', 'G', 'B', 'X'), LSB, 0xff000000, 0x00ff0000, 0x0000ff00),
152       X (('X', 'B', 'G', 'R'), MSB, 0x000000ff, 0x0000ff00, 0x00ff0000),
153     } },
154   { GST_VIDEO_FORMAT_BGRx, {
155       X (('X', 'R', 'G', 'B'), LSB, 0x00ff0000, 0x0000ff00, 0x000000ff),
156       X (('B', 'G', 'R', 'X'), MSB, 0x0000ff00, 0x00ff0000, 0xff000000),
157     } },
158 #undef X
159 #undef A
160 #undef F
161 };
162 /* *INDENT-ON* */
163 
164 static const struct FormatMap *
get_format_map_from_va_fourcc(guint va_fourcc)165 get_format_map_from_va_fourcc (guint va_fourcc)
166 {
167   int i;
168 
169   for (i = 0; i < G_N_ELEMENTS (format_map); i++) {
170     if (format_map[i].va_format.fourcc == va_fourcc)
171       return &format_map[i];
172   }
173 
174   return NULL;
175 }
176 
177 static struct FormatMap *
get_format_map_from_video_format(GstVideoFormat format)178 get_format_map_from_video_format (GstVideoFormat format)
179 {
180   int i;
181 
182   for (i = 0; i < G_N_ELEMENTS (format_map); i++) {
183     if (format_map[i].format == format)
184       return &format_map[i];
185   }
186 
187   return NULL;
188 }
189 
190 static inline gboolean
va_format_is_rgb(const VAImageFormat * va_format)191 va_format_is_rgb (const VAImageFormat * va_format)
192 {
193   return va_format->depth != 0;
194 }
195 
196 static inline gboolean
va_format_is_same_rgb(const VAImageFormat * fmt1,const VAImageFormat * fmt2)197 va_format_is_same_rgb (const VAImageFormat * fmt1, const VAImageFormat * fmt2)
198 {
199   return (fmt1->red_mask == fmt2->red_mask
200       && fmt1->green_mask == fmt2->green_mask
201       && fmt1->blue_mask == fmt2->blue_mask
202       && fmt1->alpha_mask == fmt2->alpha_mask);
203 }
204 
205 static inline gboolean
va_format_is_same(const VAImageFormat * fmt1,const VAImageFormat * fmt2)206 va_format_is_same (const VAImageFormat * fmt1, const VAImageFormat * fmt2)
207 {
208   if (fmt1->fourcc != fmt2->fourcc)
209     return FALSE;
210   if (fmt1->byte_order != VA_NSB_FIRST
211       && fmt2->byte_order != VA_NSB_FIRST
212       && fmt1->byte_order != fmt2->byte_order)
213     return FALSE;
214   return va_format_is_rgb (fmt1) ? va_format_is_same_rgb (fmt1, fmt2) : TRUE;
215 }
216 
217 static const struct FormatMap *
get_format_map_from_va_image_format(const VAImageFormat * va_format)218 get_format_map_from_va_image_format (const VAImageFormat * va_format)
219 {
220   int i;
221 
222   for (i = 0; i < G_N_ELEMENTS (format_map); i++) {
223     if (va_format_is_same (&format_map[i].va_format, va_format))
224       return &format_map[i];
225   }
226 
227   return NULL;
228 }
229 
230 GstVideoFormat
gst_va_video_format_from_va_fourcc(guint va_fourcc)231 gst_va_video_format_from_va_fourcc (guint va_fourcc)
232 {
233   const struct FormatMap *map = get_format_map_from_va_fourcc (va_fourcc);
234 
235   return map ? map->format : GST_VIDEO_FORMAT_UNKNOWN;
236 }
237 
238 guint
gst_va_fourcc_from_video_format(GstVideoFormat format)239 gst_va_fourcc_from_video_format (GstVideoFormat format)
240 {
241   const struct FormatMap *map = get_format_map_from_video_format (format);
242 
243   return map ? map->va_format.fourcc : 0;
244 }
245 
246 guint
gst_va_chroma_from_video_format(GstVideoFormat format)247 gst_va_chroma_from_video_format (GstVideoFormat format)
248 {
249   const struct FormatMap *map = get_format_map_from_video_format (format);
250 
251   return map ? map->va_rtformat : 0;
252 }
253 
254 const VAImageFormat *
gst_va_image_format_from_video_format(GstVideoFormat format)255 gst_va_image_format_from_video_format (GstVideoFormat format)
256 {
257   const struct FormatMap *map = get_format_map_from_video_format (format);
258 
259   return map ? &map->va_format : NULL;
260 }
261 
262 GstVideoFormat
gst_va_video_format_from_va_image_format(const VAImageFormat * va_format)263 gst_va_video_format_from_va_image_format (const VAImageFormat * va_format)
264 {
265   const struct FormatMap *map = get_format_map_from_va_image_format (va_format);
266 
267   return map ? map->format : GST_VIDEO_FORMAT_UNKNOWN;
268 }
269 
270 GstVideoFormat
gst_va_video_surface_format_from_image_format(GstVideoFormat image_format,GArray * surface_formats)271 gst_va_video_surface_format_from_image_format (GstVideoFormat image_format,
272     GArray * surface_formats)
273 {
274   GstVideoFormat surface_format;
275   guint i, image_chroma;
276 
277   if (image_format == GST_VIDEO_FORMAT_UNKNOWN)
278     return GST_VIDEO_FORMAT_UNKNOWN;
279 
280   if (!surface_formats || surface_formats->len == 0)
281     return GST_VIDEO_FORMAT_UNKNOWN;
282 
283   image_chroma = gst_va_chroma_from_video_format (image_format);
284   if (image_chroma == 0)
285     return GST_VIDEO_FORMAT_UNKNOWN;
286 
287   for (i = 0; i < surface_formats->len; i++) {
288     surface_format = g_array_index (surface_formats, GstVideoFormat, i);
289 
290     if (surface_format == image_format)
291       return surface_format;
292   }
293 
294   return GST_VIDEO_FORMAT_UNKNOWN;
295 }
296 
297 static GstVideoFormat
find_gst_video_format_in_rgb32_map(VAImageFormat * image_format)298 find_gst_video_format_in_rgb32_map (VAImageFormat * image_format)
299 {
300   guint i, j;
301 
302   for (i = 0; i < G_N_ELEMENTS (rgb32_format_map); i++) {
303     for (j = 0; j < G_N_ELEMENTS (rgb32_format_map[i].va_format); j++) {
304       if (va_format_is_same (&rgb32_format_map[i].va_format[j], image_format))
305         return rgb32_format_map[i].format;
306     }
307   }
308 
309   return GST_VIDEO_FORMAT_UNKNOWN;
310 }
311 
312 struct ImageFormatArray
313 {
314   VAImageFormat *image_formats;
315   gint len;
316 };
317 
318 static gpointer
fix_map(gpointer data)319 fix_map (gpointer data)
320 {
321   struct ImageFormatArray *args = data;
322   GstVideoFormat format;
323   VAImageFormat *image_format;
324   struct FormatMap *map;
325   guint i;
326 
327   GST_DEBUG_CATEGORY_GET (gstva_debug, "va");
328 
329   for (i = 0; i < args->len; i++) {
330     image_format = &args->image_formats[i];
331     if (!va_format_is_rgb (image_format))
332       continue;
333     format = find_gst_video_format_in_rgb32_map (image_format);
334     if (format == GST_VIDEO_FORMAT_UNKNOWN)
335       continue;
336     map = get_format_map_from_video_format (format);
337     if (!map)
338       continue;
339     if (va_format_is_same (&map->va_format, image_format))
340       continue;
341 
342     map->va_format = *image_format;
343 
344     GST_CAT_INFO (gstva_debug, "GST_VIDEO_FORMAT_%s => { fourcc %"
345         GST_FOURCC_FORMAT ", %s, bpp %d, depth %d, R %#010x, G %#010x, "
346         "B %#010x, A %#010x }", gst_video_format_to_string (map->format),
347         GST_FOURCC_ARGS (map->va_format.fourcc),
348         (map->va_format.byte_order == 1) ? "LSB" : "MSB",
349         map->va_format.bits_per_pixel, map->va_format.depth,
350         map->va_format.red_mask, map->va_format.green_mask,
351         map->va_format.blue_mask, map->va_format.alpha_mask);
352   }
353 
354   return NULL;
355 }
356 
357 /* XXX: RGB32 LSB VAImageFormats don't map statically with GStreamer
358  * color formats. Each driver does what they want.
359  *
360  * For MSB, there is no ambiguity: same order in define, memory and
361  * CPU. For example,
362  *
363  *  RGBA is RGBA in memory and RGBA with channel mask R:0xFF0000
364  *  G:0x00FF0000 B:0x0000FF00 A:0x000000FF in CPU.
365  *
366  * For LSB, CPU's perspective and memory's perspective are
367  * different. For example,
368  *
369  *  From CPU's perspective, it's RGBA order in memory, but when it is
370  *  stored in memory, because CPU's little endianness, it will be
371  *  re-ordered, with mask R:0x000000FF G:0x0000FF00 B:0x00FF0000
372  *  A:0xFF000000.
373  *
374  *  In other words, from memory's perspective, RGBA LSB is equal as
375  *  ABGR MSB.
376  *
377  * These definitions are mixed used all over the media system and we
378  * need to correct the mapping form VA video format to GStreamer
379  * video format in both manners.
380  *
381  * https://gitlab.freedesktop.org/gstreamer/gstreamer-vaapi/-/merge_requests/123
382  */
383 void
gst_va_video_format_fix_map(VAImageFormat * image_formats,gint num)384 gst_va_video_format_fix_map (VAImageFormat * image_formats, gint num)
385 {
386   static GOnce once = G_ONCE_INIT;
387   struct ImageFormatArray args = { image_formats, num };
388 
389   g_once (&once, fix_map, &args);
390 }
391