fabcafb91c4f6d84021d919b324fc87d940a7c9f
[platform/upstream/gstreamer.git] / gst / colorspace / colorspace.c
1 /* GStreamer
2  * Copyright (C) 2010 David Schleef <ds@schleef.org>
3  * Copyright (C) 2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
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., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "colorspace.h"
26 #include <glib.h>
27 #include <string.h>
28 #include "gstcolorspaceorc.h"
29
30
31 static void colorspace_convert_generic (ColorspaceConvert * convert,
32     guint8 * dest, const guint8 * src);
33 static void colorspace_convert_lookup_fastpath (ColorspaceConvert * convert);
34 static void colorspace_convert_lookup_getput (ColorspaceConvert * convert);
35
36
37 ColorspaceConvert *
38 colorspace_convert_new (GstVideoFormat to_format, ColorSpaceColorSpec to_spec,
39     GstVideoFormat from_format, ColorSpaceColorSpec from_spec,
40     int width, int height)
41 {
42   ColorspaceConvert *convert;
43   int i;
44
45   g_return_val_if_fail (!gst_video_format_is_rgb (to_format)
46       || to_spec == COLOR_SPEC_RGB, NULL);
47   g_return_val_if_fail (!gst_video_format_is_yuv (to_format)
48       || to_spec == COLOR_SPEC_YUV_BT709
49       || to_spec == COLOR_SPEC_YUV_BT470_6, NULL);
50   g_return_val_if_fail (gst_video_format_is_rgb (to_format)
51       || gst_video_format_is_yuv (to_format)
52       || (gst_video_format_is_gray (to_format) &&
53           to_spec == COLOR_SPEC_GRAY), NULL);
54
55   g_return_val_if_fail (!gst_video_format_is_rgb (from_format)
56       || from_spec == COLOR_SPEC_RGB, NULL);
57   g_return_val_if_fail (!gst_video_format_is_yuv (from_format)
58       || from_spec == COLOR_SPEC_YUV_BT709
59       || from_spec == COLOR_SPEC_YUV_BT470_6, NULL);
60   g_return_val_if_fail (gst_video_format_is_rgb (from_format)
61       || gst_video_format_is_yuv (from_format)
62       || (gst_video_format_is_gray (from_format) &&
63           from_spec == COLOR_SPEC_GRAY), NULL);
64
65   convert = g_malloc (sizeof (ColorspaceConvert));
66   memset (convert, 0, sizeof (ColorspaceConvert));
67
68   convert->to_format = to_format;
69   convert->to_spec = to_spec;
70   convert->from_format = from_format;
71   convert->from_spec = from_spec;
72   convert->height = height;
73   convert->width = width;
74   convert->convert = colorspace_convert_generic;
75
76   for (i = 0; i < 4; i++) {
77     convert->dest_stride[i] = gst_video_format_get_row_stride (to_format, i,
78         width);
79     convert->dest_offset[i] = gst_video_format_get_component_offset (to_format,
80         i, width, height);
81     if (i == 0)
82       convert->dest_offset[i] = 0;
83
84     convert->src_stride[i] = gst_video_format_get_row_stride (from_format, i,
85         width);
86     convert->src_offset[i] = gst_video_format_get_component_offset (from_format,
87         i, width, height);
88     if (i == 0)
89       convert->src_offset[i] = 0;
90
91     GST_DEBUG ("%d: dest %d %d src %d %d", i,
92         convert->dest_stride[i], convert->dest_offset[i],
93         convert->src_stride[i], convert->src_offset[i]);
94   }
95
96   colorspace_convert_lookup_fastpath (convert);
97   colorspace_convert_lookup_getput (convert);
98
99   convert->tmpline = g_malloc (sizeof (guint32) * width * 2);
100
101   return convert;
102 }
103
104 void
105 colorspace_convert_free (ColorspaceConvert * convert)
106 {
107   if (convert->palette)
108     g_free (convert->palette);
109   if (convert->tmpline)
110     g_free (convert->tmpline);
111
112   g_free (convert);
113 }
114
115 void
116 colorspace_convert_set_interlaced (ColorspaceConvert * convert,
117     gboolean interlaced)
118 {
119   convert->interlaced = interlaced;
120 }
121
122 void
123 colorspace_convert_set_palette (ColorspaceConvert * convert, guint32 * palette)
124 {
125   if (convert->palette == NULL) {
126     convert->palette = g_malloc (sizeof (guint32) * 256);
127   }
128   memcpy (convert->palette, palette, sizeof (guint32) * 256);
129 }
130
131 void
132 colorspace_convert_convert (ColorspaceConvert * convert,
133     guint8 * dest, const guint8 * src)
134 {
135   convert->convert (convert, dest, src);
136 }
137
138 /* Line conversion to AYUV */
139
140 #define FRAME_GET_LINE(dir, comp, line) \
141   ((dir) + convert-> dir ## _offset[(comp)] + convert-> dir ## _stride[(comp)] * (line))
142
143 static void
144 getline_I420 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
145     int j)
146 {
147   cogorc_getline_I420 (dest,
148       FRAME_GET_LINE (src, 0, j),
149       FRAME_GET_LINE (src, 1, j >> 1),
150       FRAME_GET_LINE (src, 2, j >> 1), convert->width);
151 }
152
153 static void
154 putline_I420 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
155     int j)
156 {
157   cogorc_putline_I420 (FRAME_GET_LINE (dest, 0, j),
158       FRAME_GET_LINE (dest, 1, j >> 1),
159       FRAME_GET_LINE (dest, 2, j >> 1), src, convert->width / 2);
160 }
161
162 static void
163 getline_YV12 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
164     int j)
165 {
166   cogorc_getline_I420 (dest,
167       FRAME_GET_LINE (src, 0, j),
168       FRAME_GET_LINE (src, 1, j >> 1),
169       FRAME_GET_LINE (src, 2, j >> 1), convert->width);
170 }
171
172 static void
173 putline_YV12 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
174     int j)
175 {
176   cogorc_putline_I420 (FRAME_GET_LINE (dest, 0, j),
177       FRAME_GET_LINE (dest, 1, j >> 1),
178       FRAME_GET_LINE (dest, 2, j >> 1), src, convert->width / 2);
179 }
180
181 static void
182 getline_YUY2 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
183     int j)
184 {
185   cogorc_getline_YUY2 (dest, FRAME_GET_LINE (src, 0, j), convert->width / 2);
186 }
187
188 static void
189 putline_YUY2 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
190     int j)
191 {
192   cogorc_putline_YUY2 (FRAME_GET_LINE (dest, 0, j), src, convert->width / 2);
193 }
194
195 static void
196 getline_UYVY (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
197     int j)
198 {
199   cogorc_getline_UYVY (dest, FRAME_GET_LINE (src, 0, j), convert->width / 2);
200 }
201
202 static void
203 putline_UYVY (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
204     int j)
205 {
206   cogorc_putline_UYVY (FRAME_GET_LINE (dest, 0, j), src, convert->width / 2);
207 }
208
209 static void
210 getline_YVYU (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
211     int j)
212 {
213   cogorc_getline_YVYU (dest, FRAME_GET_LINE (src, 0, j), convert->width / 2);
214 }
215
216 static void
217 putline_YVYU (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
218     int j)
219 {
220   cogorc_putline_YVYU (FRAME_GET_LINE (dest, 0, j), src, convert->width / 2);
221 }
222
223 static void
224 getline_v308 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
225     int j)
226 {
227   int i;
228   const guint8 *srcline = FRAME_GET_LINE (src, 0, j);
229   for (i = 0; i < convert->width; i++) {
230     dest[i * 4 + 0] = 0xff;
231     dest[i * 4 + 1] = srcline[i * 3 + 0];
232     dest[i * 4 + 2] = srcline[i * 3 + 1];
233     dest[i * 4 + 3] = srcline[i * 3 + 2];
234   }
235 }
236
237 static void
238 putline_v308 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
239     int j)
240 {
241   int i;
242   guint8 *destline = FRAME_GET_LINE (dest, 0, j);
243   for (i = 0; i < convert->width; i++) {
244     destline[i * 3 + 0] = src[i * 4 + 1];
245     destline[i * 3 + 1] = src[i * 4 + 2];
246     destline[i * 3 + 2] = src[i * 4 + 3];
247   }
248 }
249
250 static void
251 getline_AYUV (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
252     int j)
253 {
254   memcpy (dest, FRAME_GET_LINE (src, 0, j), convert->width * 4);
255 }
256
257 static void
258 putline_AYUV (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
259     int j)
260 {
261   memcpy (FRAME_GET_LINE (dest, 0, j), src, convert->width * 4);
262 }
263
264 #if 0
265 static void
266 getline_v410 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
267     int j)
268 {
269   int i;
270   const guint8 *srcline = FRAME_GET_LINE (src, 0, j);
271   for (i = 0; i < convert->width; i++) {
272     dest[i * 4 + 0] = GST_READ_UINT16_LE (srcline + i * 8 + 0);
273     dest[i * 4 + 1] = GST_READ_UINT16_LE (srcline + i * 8 + 2);
274     dest[i * 4 + 2] = GST_READ_UINT16_LE (srcline + i * 8 + 4);
275     dest[i * 4 + 3] = GST_READ_UINT16_LE (srcline + i * 8 + 6);
276   }
277 }
278 #endif
279
280 static void
281 getline_v210 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
282     int j)
283 {
284   int i;
285   const guint8 *srcline = FRAME_GET_LINE (src, 0, j);
286
287   for (i = 0; i < convert->width; i += 6) {
288     guint32 a0, a1, a2, a3;
289     guint16 y0, y1, y2, y3, y4, y5;
290     guint16 u0, u2, u4;
291     guint16 v0, v2, v4;
292
293     a0 = GST_READ_UINT32_LE (srcline + (i / 6) * 16 + 0);
294     a1 = GST_READ_UINT32_LE (srcline + (i / 6) * 16 + 4);
295     a2 = GST_READ_UINT32_LE (srcline + (i / 6) * 16 + 8);
296     a3 = GST_READ_UINT32_LE (srcline + (i / 6) * 16 + 12);
297
298     u0 = ((a0 >> 0) & 0x3ff) >> 2;
299     y0 = ((a0 >> 10) & 0x3ff) >> 2;
300     v0 = ((a0 >> 20) & 0x3ff) >> 2;
301     y1 = ((a1 >> 0) & 0x3ff) >> 2;
302
303     u2 = ((a1 >> 10) & 0x3ff) >> 2;
304     y2 = ((a1 >> 20) & 0x3ff) >> 2;
305     v2 = ((a2 >> 0) & 0x3ff) >> 2;
306     y3 = ((a2 >> 10) & 0x3ff) >> 2;
307
308     u4 = ((a2 >> 20) & 0x3ff) >> 2;
309     y4 = ((a3 >> 0) & 0x3ff) >> 2;
310     v4 = ((a3 >> 10) & 0x3ff) >> 2;
311     y5 = ((a3 >> 20) & 0x3ff) >> 2;
312
313     dest[4 * (i + 0) + 0] = 0xff;
314     dest[4 * (i + 0) + 1] = y0;
315     dest[4 * (i + 0) + 2] = u0;
316     dest[4 * (i + 0) + 3] = v0;
317
318     dest[4 * (i + 1) + 0] = 0xff;
319     dest[4 * (i + 1) + 1] = y1;
320     dest[4 * (i + 1) + 2] = u0;
321     dest[4 * (i + 1) + 3] = v0;
322
323     dest[4 * (i + 2) + 0] = 0xff;
324     dest[4 * (i + 2) + 1] = y2;
325     dest[4 * (i + 2) + 2] = u2;
326     dest[4 * (i + 2) + 3] = v2;
327
328     dest[4 * (i + 3) + 0] = 0xff;
329     dest[4 * (i + 3) + 1] = y3;
330     dest[4 * (i + 3) + 2] = u2;
331     dest[4 * (i + 3) + 3] = v2;
332
333     dest[4 * (i + 4) + 0] = 0xff;
334     dest[4 * (i + 4) + 1] = y4;
335     dest[4 * (i + 4) + 2] = u4;
336     dest[4 * (i + 4) + 3] = v4;
337
338     dest[4 * (i + 5) + 0] = 0xff;
339     dest[4 * (i + 5) + 1] = y5;
340     dest[4 * (i + 5) + 2] = u4;
341     dest[4 * (i + 5) + 3] = v4;
342
343   }
344
345 }
346
347 static void
348 putline_v210 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
349     int j)
350 {
351   int i;
352   guint8 *destline = FRAME_GET_LINE (dest, 0, j);
353
354   for (i = 0; i < convert->width + 5; i += 6) {
355     guint32 a0, a1, a2, a3;
356     guint16 y0, y1, y2, y3, y4, y5;
357     guint16 u0, u1, u2;
358     guint16 v0, v1, v2;
359
360     y0 = src[4 * (i + 0) + 1];
361     y1 = src[4 * (i + 1) + 1];
362     y2 = src[4 * (i + 2) + 1];
363     y3 = src[4 * (i + 3) + 1];
364     y4 = src[4 * (i + 4) + 1];
365     y5 = src[4 * (i + 5) + 1];
366
367     u0 = (src[4 * (i + 0) + 2] + src[4 * (i + 1) + 2] + 1) >> 1;
368     u1 = (src[4 * (i + 2) + 2] + src[4 * (i + 3) + 2] + 1) >> 1;
369     u2 = (src[4 * (i + 4) + 2] + src[4 * (i + 5) + 2] + 1) >> 1;
370
371     v0 = (src[4 * (i + 0) + 3] + src[4 * (i + 1) + 3] + 1) >> 1;
372     v1 = (src[4 * (i + 2) + 3] + src[4 * (i + 3) + 3] + 1) >> 1;
373     v2 = (src[4 * (i + 4) + 3] + src[4 * (i + 5) + 3] + 1) >> 1;
374
375     a0 = (u0 << 2) | ((y0 << 2) << 10) | ((v0 << 2) << 20);
376     a1 = (y1 << 2) | ((u1 << 2) << 10) | ((y2 << 2) << 20);
377     a2 = (v1 << 2) | ((y3 << 2) << 10) | ((u2 << 2) << 20);
378     a3 = (y4 << 2) | ((v2 << 2) << 10) | ((y5 << 2) << 20);
379
380     GST_WRITE_UINT32_LE (destline + (i / 6) * 16 + 0, a0);
381     GST_WRITE_UINT32_LE (destline + (i / 6) * 16 + 4, a1);
382     GST_WRITE_UINT32_LE (destline + (i / 6) * 16 + 8, a2);
383     GST_WRITE_UINT32_LE (destline + (i / 6) * 16 + 12, a3);
384   }
385 }
386
387 static void
388 getline_v216 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
389     int j)
390 {
391   int i;
392   const guint8 *srcline = FRAME_GET_LINE (src, 0, j);
393   for (i = 0; i < convert->width; i++) {
394     dest[i * 4 + 0] = 0xff;
395     dest[i * 4 + 1] = GST_READ_UINT16_LE (srcline + i * 4 + 2);
396     dest[i * 4 + 2] = GST_READ_UINT16_LE (srcline + (i >> 1) * 8 + 0);
397     dest[i * 4 + 3] = GST_READ_UINT16_LE (srcline + (i >> 1) * 8 + 4);
398   }
399 }
400
401 static void
402 putline_v216 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
403     int j)
404 {
405   int i;
406   guint8 *destline = FRAME_GET_LINE (dest, 0, j);
407   for (i = 0; i < convert->width / 2; i++) {
408     GST_WRITE_UINT16_LE (destline + i * 8 + 0, src[(i * 2 + 0) * 4 + 2] << 8);
409     GST_WRITE_UINT16_LE (destline + i * 8 + 2, src[(i * 2 + 0) * 4 + 1] << 8);
410     GST_WRITE_UINT16_LE (destline + i * 8 + 4, src[(i * 2 + 1) * 4 + 3] << 8);
411     GST_WRITE_UINT16_LE (destline + i * 8 + 8, src[(i * 2 + 0) * 4 + 1] << 8);
412   }
413 }
414
415 static void
416 getline_Y41B (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
417     int j)
418 {
419   int i;
420   const guint8 *srclineY = FRAME_GET_LINE (src, 0, j);
421   const guint8 *srclineU = FRAME_GET_LINE (src, 1, j);
422   const guint8 *srclineV = FRAME_GET_LINE (src, 2, j);
423
424   for (i = 0; i < convert->width; i++) {
425     dest[i * 4 + 0] = 0xff;
426     dest[i * 4 + 1] = srclineY[i];
427     dest[i * 4 + 2] = srclineU[i >> 2];
428     dest[i * 4 + 3] = srclineV[i >> 2];
429   }
430 }
431
432 static void
433 putline_Y41B (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
434     int j)
435 {
436   int i;
437   guint8 *destlineY = FRAME_GET_LINE (dest, 0, j);
438   guint8 *destlineU = FRAME_GET_LINE (dest, 1, j);
439   guint8 *destlineV = FRAME_GET_LINE (dest, 2, j);
440
441   for (i = 0; i < convert->width - 3; i += 4) {
442     destlineY[i] = src[i * 4 + 1];
443     destlineY[i + 1] = src[i * 4 + 5];
444     destlineY[i + 2] = src[i * 4 + 9];
445     destlineY[i + 3] = src[i * 4 + 13];
446
447     destlineU[i >> 2] =
448         (src[i * 4 + 2] + src[i * 4 + 6] + src[i * 4 + 10] + src[i * 4 + 14] +
449         2) >> 2;
450     destlineV[i >> 2] =
451         (src[i * 4 + 3] + src[i * 4 + 7] + src[i * 4 + 11] + src[i * 4 + 15] +
452         2) >> 2;
453   }
454
455   if (i == convert->width - 3) {
456     destlineY[i] = src[i * 4 + 1];
457     destlineY[i + 1] = src[i * 4 + 5];
458     destlineY[i + 2] = src[i * 4 + 9];
459
460     destlineU[i >> 2] =
461         (src[i * 4 + 2] + src[i * 4 + 6] + src[i * 4 + 10] + 1) / 3;
462     destlineV[i >> 2] =
463         (src[i * 4 + 3] + src[i * 4 + 7] + src[i * 4 + 11] + 1) / 3;
464   } else if (i == convert->width - 2) {
465     destlineY[i] = src[i * 4 + 1];
466     destlineY[i + 1] = src[i * 4 + 5];
467
468     destlineU[i >> 2] = (src[i * 4 + 2] + src[i * 4 + 6] + 1) >> 1;
469     destlineV[i >> 2] = (src[i * 4 + 3] + src[i * 4 + 7] + 1) >> 1;
470   } else if (i == convert->width - 1) {
471     destlineY[i + 1] = src[i * 4 + 5];
472
473     destlineU[i >> 2] = src[i * 4 + 2];
474     destlineV[i >> 2] = src[i * 4 + 3];
475   }
476 }
477
478 static void
479 getline_Y42B (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
480     int j)
481 {
482   cogorc_getline_Y42B (dest,
483       FRAME_GET_LINE (src, 0, j),
484       FRAME_GET_LINE (src, 1, j),
485       FRAME_GET_LINE (src, 2, j), convert->width / 2);
486 }
487
488 static void
489 putline_Y42B (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
490     int j)
491 {
492   cogorc_putline_Y42B (FRAME_GET_LINE (dest, 0, j),
493       FRAME_GET_LINE (dest, 1, j),
494       FRAME_GET_LINE (dest, 2, j), src, convert->width / 2);
495 }
496
497 static void
498 getline_Y444 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
499     int j)
500 {
501   cogorc_getline_Y444 (dest,
502       FRAME_GET_LINE (src, 0, j),
503       FRAME_GET_LINE (src, 1, j), FRAME_GET_LINE (src, 2, j), convert->width);
504 }
505
506 static void
507 putline_Y444 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
508     int j)
509 {
510   cogorc_putline_Y444 (FRAME_GET_LINE (dest, 0, j),
511       FRAME_GET_LINE (dest, 1, j),
512       FRAME_GET_LINE (dest, 2, j), src, convert->width);
513 }
514
515 static void
516 getline_Y800 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
517     int j)
518 {
519   cogorc_getline_Y800 (dest, FRAME_GET_LINE (src, 0, j), convert->width);
520 }
521
522 static void
523 putline_Y800 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
524     int j)
525 {
526   cogorc_putline_Y800 (FRAME_GET_LINE (dest, 0, j), src, convert->width);
527 }
528
529 static void
530 getline_BGRA (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
531     int j)
532 {
533   cogorc_getline_BGRA (dest, FRAME_GET_LINE (src, 0, j), convert->width);
534 }
535
536 static void
537 putline_BGRA (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
538     int j)
539 {
540   cogorc_putline_BGRA (FRAME_GET_LINE (dest, 0, j), src, convert->width);
541 }
542
543 static void
544 getline_ABGR (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
545     int j)
546 {
547   cogorc_getline_ABGR (dest, FRAME_GET_LINE (src, 0, j), convert->width);
548 }
549
550 static void
551 putline_ABGR (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
552     int j)
553 {
554   cogorc_putline_ABGR (FRAME_GET_LINE (dest, 0, j), src, convert->width);
555 }
556
557 static void
558 getline_RGBA (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
559     int j)
560 {
561   cogorc_getline_RGBA (dest, FRAME_GET_LINE (src, 0, j), convert->width);
562 }
563
564 static void
565 putline_RGBA (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
566     int j)
567 {
568   cogorc_putline_RGBA (FRAME_GET_LINE (dest, 0, j), src, convert->width);
569 }
570
571 static void
572 getline_RGB (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
573     int j)
574 {
575   int i;
576   const guint8 *srcline = FRAME_GET_LINE (src, 0, j);
577   for (i = 0; i < convert->width; i++) {
578     dest[i * 4 + 0] = 0xff;
579     dest[i * 4 + 1] = srcline[i * 3 + 0];
580     dest[i * 4 + 2] = srcline[i * 3 + 1];
581     dest[i * 4 + 3] = srcline[i * 3 + 2];
582   }
583 }
584
585 static void
586 putline_RGB (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
587     int j)
588 {
589   int i;
590   guint8 *destline = FRAME_GET_LINE (dest, 0, j);
591   for (i = 0; i < convert->width; i++) {
592     destline[i * 3 + 0] = src[i * 4 + 1];
593     destline[i * 3 + 1] = src[i * 4 + 2];
594     destline[i * 3 + 2] = src[i * 4 + 3];
595   }
596 }
597
598 static void
599 getline_BGR (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
600     int j)
601 {
602   int i;
603   const guint8 *srcline = FRAME_GET_LINE (src, 0, j);
604   for (i = 0; i < convert->width; i++) {
605     dest[i * 4 + 0] = 0xff;
606     dest[i * 4 + 1] = srcline[i * 3 + 2];
607     dest[i * 4 + 2] = srcline[i * 3 + 1];
608     dest[i * 4 + 3] = srcline[i * 3 + 0];
609   }
610 }
611
612 static void
613 putline_BGR (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
614     int j)
615 {
616   int i;
617   guint8 *destline = FRAME_GET_LINE (dest, 0, j);
618   for (i = 0; i < convert->width; i++) {
619     destline[i * 3 + 0] = src[i * 4 + 3];
620     destline[i * 3 + 1] = src[i * 4 + 2];
621     destline[i * 3 + 2] = src[i * 4 + 1];
622   }
623 }
624
625 static void
626 getline_NV12 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
627     int j)
628 {
629   cogorc_getline_NV12 (dest,
630       FRAME_GET_LINE (src, 0, j),
631       FRAME_GET_LINE (src, 1, j >> 1), convert->width / 2);
632 }
633
634 static void
635 putline_NV12 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
636     int j)
637 {
638   cogorc_putline_NV12 (FRAME_GET_LINE (dest, 0, j),
639       FRAME_GET_LINE (dest, 1, j >> 1), src, convert->width / 2);
640 }
641
642 static void
643 getline_NV21 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
644     int j)
645 {
646   cogorc_getline_NV21 (dest,
647       FRAME_GET_LINE (src, 0, j),
648       FRAME_GET_LINE (src, 2, j >> 1), convert->width / 2);
649 }
650
651 static void
652 putline_NV21 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
653     int j)
654 {
655   cogorc_putline_NV21 (FRAME_GET_LINE (dest, 0, j),
656       FRAME_GET_LINE (dest, 2, j >> 1), src, convert->width / 2);
657 }
658
659 static void
660 getline_UYVP (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
661     int j)
662 {
663   int i;
664
665   for (i = 0; i < convert->width; i += 2) {
666     guint16 y0, y1;
667     guint16 u0;
668     guint16 v0;
669
670     u0 = (src[(i / 2) * 5 + 0] << 2) | (src[(i / 2) * 5 + 1] >> 6);
671     y0 = ((src[(i / 2) * 5 + 1] & 0x3f) << 4) | (src[(i / 2) * 5 + 2] >> 4);
672     v0 = ((src[(i / 2) * 5 + 2] & 0x0f) << 6) | (src[(i / 2) * 5 + 3] >> 2);
673     y1 = ((src[(i / 2) * 5 + 3] & 0x03) << 8) | src[(i / 2) * 5 + 4];
674
675     dest[i * 4 + 0] = 0xff;
676     dest[i * 4 + 1] = y0 >> 2;
677     dest[i * 4 + 2] = u0 >> 2;
678     dest[i * 4 + 3] = v0 >> 2;
679     dest[i * 4 + 4] = 0xff;
680     dest[i * 4 + 5] = y1 >> 2;
681     dest[i * 4 + 6] = u0 >> 2;
682     dest[i * 4 + 7] = v0 >> 2;
683   }
684 }
685
686 static void
687 putline_UYVP (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
688     int j)
689 {
690   int i;
691
692   for (i = 0; i < convert->width; i += 2) {
693     guint16 y0, y1;
694     guint16 u0;
695     guint16 v0;
696
697     y0 = src[4 * (i + 0) + 1];
698     y1 = src[4 * (i + 1) + 1];
699     u0 = (src[4 * (i + 0) + 2] + src[4 * (i + 1) + 2] + 1) >> 1;
700     v0 = (src[4 * (i + 0) + 3] + src[4 * (i + 1) + 3] + 1) >> 1;
701
702     dest[(i / 2) * 5 + 0] = u0;
703     dest[(i / 2) * 5 + 1] = y0 >> 2;
704     dest[(i / 2) * 5 + 2] = (y0 << 6) | (v0 >> 4);
705     dest[(i / 2) * 5 + 3] = (v0 << 4) | (y1 >> 2);
706     dest[(i / 2) * 5 + 4] = (y1 << 2);
707   }
708 }
709
710 static void
711 getline_A420 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
712     int j)
713 {
714   cogorc_getline_A420 (dest,
715       FRAME_GET_LINE (src, 0, j),
716       FRAME_GET_LINE (src, 1, j >> 1),
717       FRAME_GET_LINE (src, 2, j >> 1),
718       FRAME_GET_LINE (src, 3, j), convert->width);
719 }
720
721 static void
722 putline_A420 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
723     int j)
724 {
725   cogorc_putline_A420 (FRAME_GET_LINE (dest, 0, j),
726       FRAME_GET_LINE (dest, 1, j >> 1),
727       FRAME_GET_LINE (dest, 2, j >> 1),
728       FRAME_GET_LINE (dest, 3, j), src, convert->width / 2);
729 }
730
731 typedef struct
732 {
733   GstVideoFormat format;
734   void (*getline) (ColorspaceConvert * convert, guint8 * dest,
735       const guint8 * src, int j);
736   void (*putline) (ColorspaceConvert * convert, guint8 * dest,
737       const guint8 * src, int j);
738 } ColorspaceLine;
739 static const ColorspaceLine lines[] = {
740   {GST_VIDEO_FORMAT_I420, getline_I420, putline_I420},
741   {GST_VIDEO_FORMAT_YV12, getline_YV12, putline_YV12},
742   {GST_VIDEO_FORMAT_YUY2, getline_YUY2, putline_YUY2},
743   {GST_VIDEO_FORMAT_UYVY, getline_UYVY, putline_UYVY},
744   {GST_VIDEO_FORMAT_AYUV, getline_AYUV, putline_AYUV},
745   {GST_VIDEO_FORMAT_RGBx, getline_RGBA, putline_RGBA},
746   {GST_VIDEO_FORMAT_BGRx, getline_BGRA, putline_BGRA},
747   {GST_VIDEO_FORMAT_xRGB, getline_AYUV, putline_AYUV},
748   {GST_VIDEO_FORMAT_xBGR, getline_ABGR, putline_ABGR},
749   {GST_VIDEO_FORMAT_RGBA, getline_RGBA, putline_RGBA},
750   {GST_VIDEO_FORMAT_BGRA, getline_BGRA, putline_BGRA},
751   {GST_VIDEO_FORMAT_ARGB, getline_AYUV, putline_AYUV},
752   {GST_VIDEO_FORMAT_ABGR, getline_ABGR, putline_ABGR},
753   {GST_VIDEO_FORMAT_RGB, getline_RGB, putline_RGB},
754   {GST_VIDEO_FORMAT_BGR, getline_BGR, putline_BGR},
755   {GST_VIDEO_FORMAT_Y41B, getline_Y41B, putline_Y41B},
756   {GST_VIDEO_FORMAT_Y42B, getline_Y42B, putline_Y42B},
757   {GST_VIDEO_FORMAT_YVYU, getline_YVYU, putline_YVYU},
758   {GST_VIDEO_FORMAT_Y444, getline_Y444, putline_Y444},
759   {GST_VIDEO_FORMAT_v210, getline_v210, putline_v210},
760   {GST_VIDEO_FORMAT_v216, getline_v216, putline_v216},
761   {GST_VIDEO_FORMAT_NV12, getline_NV12, putline_NV12},
762   {GST_VIDEO_FORMAT_NV21, getline_NV21, putline_NV21},
763   //{GST_VIDEO_FORMAT_GRAY8, getline_GRAY8, putline_GRAY8},
764   //{GST_VIDEO_FORMAT_GRAY16_BE, getline_GRAY16_BE, putline_GRAY16_BE},
765   //{GST_VIDEO_FORMAT_GRAY16_LE, getline_GRAY16_LE, putline_GRAY16_LE},
766   {GST_VIDEO_FORMAT_v308, getline_v308, putline_v308},
767   {GST_VIDEO_FORMAT_Y800, getline_Y800, putline_Y800},
768   //{GST_VIDEO_FORMAT_Y16, getline_Y16, putline_Y16},
769   //{GST_VIDEO_FORMAT_RGB16, getline_RGB16, putline_RGB16},
770   //{GST_VIDEO_FORMAT_BGR16, getline_BGR16, putline_BGR16},
771   //{GST_VIDEO_FORMAT_RGB15, getline_RGB15, putline_RGB15},
772   //{GST_VIDEO_FORMAT_BGR15, getline_BGR15, putline_BGR15},
773   {GST_VIDEO_FORMAT_UYVP, getline_UYVP, putline_UYVP},
774   {GST_VIDEO_FORMAT_A420, getline_A420, putline_A420}
775 };
776
777 static void
778 matrix_rgb_to_yuv_bt470_6 (ColorspaceConvert * convert)
779 {
780   int i;
781   int r, g, b;
782   int y, u, v;
783   guint8 *tmpline = convert->tmpline;
784
785   for (i = 0; i < convert->width; i++) {
786     r = tmpline[i * 4 + 1];
787     g = tmpline[i * 4 + 2];
788     b = tmpline[i * 4 + 3];
789
790     y = (66 * r + 129 * g + 25 * b + 4096) >> 8;
791     u = (-38 * r - 74 * g + 112 * b + 32768) >> 8;
792     v = (112 * r - 94 * g - 18 * b + 32768) >> 8;
793
794     tmpline[i * 4 + 1] = CLAMP (y, 0, 255);
795     tmpline[i * 4 + 2] = CLAMP (u, 0, 255);
796     tmpline[i * 4 + 3] = CLAMP (v, 0, 255);
797   }
798 }
799
800 static void
801 matrix_rgb_to_yuv_bt709 (ColorspaceConvert * convert)
802 {
803   int i;
804   int r, g, b;
805   int y, u, v;
806   guint8 *tmpline = convert->tmpline;
807
808   for (i = 0; i < convert->width; i++) {
809     r = tmpline[i * 4 + 1];
810     g = tmpline[i * 4 + 2];
811     b = tmpline[i * 4 + 3];
812
813     y = (47 * r + 157 * g + 16 * b + 4096) >> 8;
814     u = (-26 * r - 87 * g + 112 * b + 32768) >> 8;
815     v = (112 * r - 102 * g - 10 * b + 32768) >> 8;
816
817     tmpline[i * 4 + 1] = CLAMP (y, 0, 255);
818     tmpline[i * 4 + 2] = CLAMP (u, 0, 255);
819     tmpline[i * 4 + 3] = CLAMP (v, 0, 255);
820   }
821 }
822
823 static void
824 matrix_yuv_bt470_6_to_rgb (ColorspaceConvert * convert)
825 {
826   int i;
827   int r, g, b;
828   int y, u, v;
829   guint8 *tmpline = convert->tmpline;
830
831   for (i = 0; i < convert->width; i++) {
832     y = tmpline[i * 4 + 1];
833     u = tmpline[i * 4 + 2];
834     v = tmpline[i * 4 + 3];
835
836     r = (298 * y + 409 * v - 57068) >> 8;
837     g = (298 * y - 100 * u - 208 * v + 34707) >> 8;
838     b = (298 * y + 516 * u - 70870) >> 8;
839
840     tmpline[i * 4 + 1] = CLAMP (r, 0, 255);
841     tmpline[i * 4 + 2] = CLAMP (g, 0, 255);
842     tmpline[i * 4 + 3] = CLAMP (b, 0, 255);
843   }
844 }
845
846 static void
847 matrix_yuv_bt709_to_rgb (ColorspaceConvert * convert)
848 {
849   int i;
850   int r, g, b;
851   int y, u, v;
852   guint8 *tmpline = convert->tmpline;
853
854   for (i = 0; i < convert->width; i++) {
855     y = tmpline[i * 4 + 1];
856     u = tmpline[i * 4 + 2];
857     v = tmpline[i * 4 + 3];
858
859     r = (298 * y + 459 * v - 63514) >> 8;
860     g = (298 * y - 55 * u - 136 * v + 19681) >> 8;
861     b = (298 * y + 541 * u - 73988) >> 8;
862
863     tmpline[i * 4 + 1] = CLAMP (r, 0, 255);
864     tmpline[i * 4 + 2] = CLAMP (g, 0, 255);
865     tmpline[i * 4 + 3] = CLAMP (b, 0, 255);
866   }
867 }
868
869 static void
870 matrix_yuv_bt709_to_yuv_bt470_6 (ColorspaceConvert * convert)
871 {
872   int i;
873   int r, g, b;
874   int y, u, v;
875   guint8 *tmpline = convert->tmpline;
876
877   for (i = 0; i < convert->width; i++) {
878     y = tmpline[i * 4 + 1];
879     u = tmpline[i * 4 + 2];
880     v = tmpline[i * 4 + 3];
881
882     r = (256 * y + 25 * u + 49 * v - 9536) >> 8;
883     g = (253 * u - 28 * v + 3958) >> 8;
884     b = (-19 * u + 252 * v + 2918) >> 8;
885
886     tmpline[i * 4 + 1] = CLAMP (r, 0, 255);
887     tmpline[i * 4 + 2] = CLAMP (g, 0, 255);
888     tmpline[i * 4 + 3] = CLAMP (b, 0, 255);
889   }
890 }
891
892 static void
893 matrix_yuv_bt470_6_to_yuv_bt709 (ColorspaceConvert * convert)
894 {
895   int i;
896   int r, g, b;
897   int y, u, v;
898   guint8 *tmpline = convert->tmpline;
899
900   for (i = 0; i < convert->width; i++) {
901     y = tmpline[i * 4 + 1];
902     u = tmpline[i * 4 + 2];
903     v = tmpline[i * 4 + 3];
904
905     r = (256 * y - 30 * u - 53 * v + 10600) >> 8;
906     g = (261 * u + 29 * v - 4367) >> 8;
907     b = (19 * u + 262 * v - 3289) >> 8;
908
909     tmpline[i * 4 + 1] = CLAMP (r, 0, 255);
910     tmpline[i * 4 + 2] = CLAMP (g, 0, 255);
911     tmpline[i * 4 + 3] = CLAMP (b, 0, 255);
912   }
913 }
914
915 static void
916 matrix_identity (ColorspaceConvert * convert)
917 {
918   /* do nothing */
919 }
920
921
922 static void
923 colorspace_convert_lookup_getput (ColorspaceConvert * convert)
924 {
925   int i;
926
927   convert->getline = NULL;
928   for (i = 0; i < sizeof (lines) / sizeof (lines[0]); i++) {
929     if (lines[i].format == convert->from_format) {
930       convert->getline = lines[i].getline;
931       break;
932     }
933   }
934   convert->putline = NULL;
935   for (i = 0; i < sizeof (lines) / sizeof (lines[0]); i++) {
936     if (lines[i].format == convert->to_format) {
937       convert->putline = lines[i].putline;
938       break;
939     }
940   }
941   GST_DEBUG ("get %p put %p", convert->getline, convert->putline);
942
943   if (convert->from_spec == convert->to_spec)
944     convert->matrix = matrix_identity;
945   else if (convert->from_spec == COLOR_SPEC_RGB
946       && convert->to_spec == COLOR_SPEC_YUV_BT470_6)
947     convert->matrix = matrix_rgb_to_yuv_bt470_6;
948   else if (convert->from_spec == COLOR_SPEC_RGB
949       && convert->to_spec == COLOR_SPEC_YUV_BT709)
950     convert->matrix = matrix_rgb_to_yuv_bt709;
951   else if (convert->from_spec == COLOR_SPEC_YUV_BT470_6
952       && convert->to_spec == COLOR_SPEC_RGB)
953     convert->matrix = matrix_yuv_bt470_6_to_rgb;
954   else if (convert->from_spec == COLOR_SPEC_YUV_BT709
955       && convert->to_spec == COLOR_SPEC_RGB)
956     convert->matrix = matrix_yuv_bt709_to_rgb;
957   else if (convert->from_spec == COLOR_SPEC_YUV_BT709
958       && convert->to_spec == COLOR_SPEC_YUV_BT470_6)
959     convert->matrix = matrix_yuv_bt709_to_yuv_bt470_6;
960   else if (convert->from_spec == COLOR_SPEC_YUV_BT470_6
961       && convert->to_spec == COLOR_SPEC_YUV_BT709)
962     convert->matrix = matrix_yuv_bt470_6_to_yuv_bt709;
963 }
964
965 static void
966 colorspace_convert_generic (ColorspaceConvert * convert, guint8 * dest,
967     const guint8 * src)
968 {
969   int j;
970
971   if (convert->getline == NULL) {
972     GST_ERROR ("no getline");
973     return;
974   }
975
976   if (convert->putline == NULL) {
977     GST_ERROR ("no putline");
978     return;
979   }
980
981   for (j = 0; j < convert->height; j++) {
982     convert->getline (convert, convert->tmpline, src, j);
983     convert->matrix (convert);
984     convert->putline (convert, dest, convert->tmpline, j);
985   }
986 }
987
988
989 /* Fast paths */
990
991 static void
992 convert_I420_YUY2 (ColorspaceConvert * convert, guint8 * dest,
993     const guint8 * src)
994 {
995   int i;
996
997   for (i = 0; i < convert->height; i += 2) {
998     cogorc_convert_I420_YUY2 (FRAME_GET_LINE (dest, 0, i),
999         FRAME_GET_LINE (dest, 0, i + 1),
1000         FRAME_GET_LINE (src, 0, i),
1001         FRAME_GET_LINE (src, 0, i + 1),
1002         FRAME_GET_LINE (src, 1, i >> 1),
1003         FRAME_GET_LINE (src, 2, i >> 1), (convert->width + 1) / 2);
1004   }
1005 }
1006
1007 static void
1008 convert_I420_UYVY (ColorspaceConvert * convert, guint8 * dest,
1009     const guint8 * src)
1010 {
1011   int i;
1012
1013   for (i = 0; i < convert->height; i += 2) {
1014     cogorc_convert_I420_UYVY (FRAME_GET_LINE (dest, 0, i),
1015         FRAME_GET_LINE (dest, 0, i + 1),
1016         FRAME_GET_LINE (src, 0, i),
1017         FRAME_GET_LINE (src, 0, i + 1),
1018         FRAME_GET_LINE (src, 1, i >> 1),
1019         FRAME_GET_LINE (src, 2, i >> 1), (convert->width + 1) / 2);
1020   }
1021 }
1022
1023 static void
1024 convert_I420_AYUV (ColorspaceConvert * convert, guint8 * dest,
1025     const guint8 * src)
1026 {
1027   int i;
1028
1029   for (i = 0; i < convert->height; i += 2) {
1030     cogorc_convert_I420_AYUV (FRAME_GET_LINE (dest, 0, i),
1031         FRAME_GET_LINE (dest, 0, i + 1),
1032         FRAME_GET_LINE (src, 0, i),
1033         FRAME_GET_LINE (src, 0, i + 1),
1034         FRAME_GET_LINE (src, 1, i >> 1),
1035         FRAME_GET_LINE (src, 2, i >> 1), convert->width);
1036   }
1037 }
1038
1039 static void
1040 convert_I420_Y42B (ColorspaceConvert * convert, guint8 * dest,
1041     const guint8 * src)
1042 {
1043   cogorc_memcpy_2d (FRAME_GET_LINE (dest, 0, 0), convert->dest_stride[0],
1044       FRAME_GET_LINE (src, 0, 0), convert->src_stride[0],
1045       convert->width, convert->height);
1046
1047   cogorc_planar_chroma_420_422 (FRAME_GET_LINE (dest, 1, 0),
1048       2 * convert->dest_stride[1], FRAME_GET_LINE (dest, 1, 1),
1049       2 * convert->dest_stride[1], FRAME_GET_LINE (src, 1, 0),
1050       convert->src_stride[1], (convert->width + 1) / 2, convert->height / 2);
1051
1052   cogorc_planar_chroma_420_422 (FRAME_GET_LINE (dest, 2, 0),
1053       2 * convert->dest_stride[2], FRAME_GET_LINE (dest, 2, 1),
1054       2 * convert->dest_stride[2], FRAME_GET_LINE (src, 2, 0),
1055       convert->src_stride[2], (convert->width + 1) / 2, convert->height / 2);
1056 }
1057
1058 static void
1059 convert_I420_Y444 (ColorspaceConvert * convert, guint8 * dest,
1060     const guint8 * src)
1061 {
1062   cogorc_memcpy_2d (FRAME_GET_LINE (dest, 0, 0), convert->dest_stride[0],
1063       FRAME_GET_LINE (src, 0, 0), convert->src_stride[0],
1064       convert->width, convert->height);
1065
1066   cogorc_planar_chroma_420_444 (FRAME_GET_LINE (dest, 1, 0),
1067       2 * convert->dest_stride[1], FRAME_GET_LINE (dest, 1, 1),
1068       2 * convert->dest_stride[1], FRAME_GET_LINE (src, 1, 0),
1069       convert->src_stride[1], (convert->width + 1) / 2,
1070       (convert->height + 1) / 2);
1071
1072   cogorc_planar_chroma_420_444 (FRAME_GET_LINE (dest, 2, 0),
1073       2 * convert->dest_stride[2], FRAME_GET_LINE (dest, 2, 1),
1074       2 * convert->dest_stride[2], FRAME_GET_LINE (src, 2, 0),
1075       convert->src_stride[2], (convert->width + 1) / 2,
1076       (convert->height + 1) / 2);
1077 }
1078
1079 static void
1080 convert_YUY2_I420 (ColorspaceConvert * convert, guint8 * dest,
1081     const guint8 * src)
1082 {
1083   int i;
1084
1085   for (i = 0; i < convert->height; i += 2) {
1086     cogorc_convert_YUY2_I420 (FRAME_GET_LINE (dest, 0, i),
1087         FRAME_GET_LINE (dest, 0, i + 1),
1088         FRAME_GET_LINE (dest, 1, i >> 1),
1089         FRAME_GET_LINE (dest, 2, i >> 1),
1090         FRAME_GET_LINE (src, 0, i),
1091         FRAME_GET_LINE (src, 0, i + 1), (convert->width + 1) / 2);
1092   }
1093 }
1094
1095 static void
1096 convert_YUY2_AYUV (ColorspaceConvert * convert, guint8 * dest,
1097     const guint8 * src)
1098 {
1099   cogorc_convert_YUY2_AYUV (FRAME_GET_LINE (dest, 0, 0),
1100       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
1101       convert->src_stride[0], (convert->width + 1) / 2, convert->height);
1102 }
1103
1104 static void
1105 convert_YUY2_Y42B (ColorspaceConvert * convert, guint8 * dest,
1106     const guint8 * src)
1107 {
1108   cogorc_convert_YUY2_Y42B (FRAME_GET_LINE (dest, 0, 0),
1109       convert->dest_stride[0], FRAME_GET_LINE (dest, 1, 0),
1110       convert->dest_stride[1], FRAME_GET_LINE (dest, 2, 0),
1111       convert->dest_stride[2], FRAME_GET_LINE (src, 0, 0),
1112       convert->src_stride[0], (convert->width + 1) / 2, convert->height);
1113 }
1114
1115 static void
1116 convert_YUY2_Y444 (ColorspaceConvert * convert, guint8 * dest,
1117     const guint8 * src)
1118 {
1119   cogorc_convert_YUY2_Y444 (FRAME_GET_LINE (dest, 0, 0),
1120       convert->dest_stride[0], FRAME_GET_LINE (dest, 1, 0),
1121       convert->dest_stride[1], FRAME_GET_LINE (dest, 2, 0),
1122       convert->dest_stride[2], FRAME_GET_LINE (src, 0, 0),
1123       convert->src_stride[0], (convert->width + 1) / 2, convert->height);
1124 }
1125
1126
1127 static void
1128 convert_UYVY_I420 (ColorspaceConvert * convert, guint8 * dest,
1129     const guint8 * src)
1130 {
1131   int i;
1132
1133   for (i = 0; i < convert->height; i += 2) {
1134     cogorc_convert_UYVY_I420 (FRAME_GET_LINE (dest, 0, i),
1135         FRAME_GET_LINE (dest, 0, i + 1),
1136         FRAME_GET_LINE (dest, 1, i >> 1),
1137         FRAME_GET_LINE (dest, 2, i >> 1),
1138         FRAME_GET_LINE (src, 0, i),
1139         FRAME_GET_LINE (src, 0, i + 1), (convert->width + 1) / 2);
1140   }
1141 }
1142
1143 static void
1144 convert_UYVY_AYUV (ColorspaceConvert * convert, guint8 * dest,
1145     const guint8 * src)
1146 {
1147   cogorc_convert_UYVY_AYUV (FRAME_GET_LINE (dest, 0, 0),
1148       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
1149       convert->src_stride[0], (convert->width + 1) / 2, convert->height);
1150 }
1151
1152 static void
1153 convert_UYVY_YUY2 (ColorspaceConvert * convert, guint8 * dest,
1154     const guint8 * src)
1155 {
1156   cogorc_convert_UYVY_YUY2 (FRAME_GET_LINE (dest, 0, 0),
1157       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
1158       convert->src_stride[0], (convert->width + 1) / 2, convert->height);
1159 }
1160
1161 static void
1162 convert_UYVY_Y42B (ColorspaceConvert * convert, guint8 * dest,
1163     const guint8 * src)
1164 {
1165   cogorc_convert_UYVY_Y42B (FRAME_GET_LINE (dest, 0, 0),
1166       convert->dest_stride[0], FRAME_GET_LINE (dest, 1, 0),
1167       convert->dest_stride[1], FRAME_GET_LINE (dest, 2, 0),
1168       convert->dest_stride[2], FRAME_GET_LINE (src, 0, 0),
1169       convert->src_stride[0], (convert->width + 1) / 2, convert->height);
1170 }
1171
1172 static void
1173 convert_UYVY_Y444 (ColorspaceConvert * convert, guint8 * dest,
1174     const guint8 * src)
1175 {
1176   cogorc_convert_UYVY_Y444 (FRAME_GET_LINE (dest, 0, 0),
1177       convert->dest_stride[0], FRAME_GET_LINE (dest, 1, 0),
1178       convert->dest_stride[1], FRAME_GET_LINE (dest, 2, 0),
1179       convert->dest_stride[2], FRAME_GET_LINE (src, 0, 0),
1180       convert->src_stride[0], (convert->width + 1) / 2, convert->height);
1181 }
1182
1183 static void
1184 convert_AYUV_I420 (ColorspaceConvert * convert, guint8 * dest,
1185     const guint8 * src)
1186 {
1187   cogorc_convert_AYUV_I420 (FRAME_GET_LINE (dest, 0, 0),
1188       2 * convert->dest_stride[0], FRAME_GET_LINE (dest, 0, 1),
1189       2 * convert->dest_stride[0], FRAME_GET_LINE (dest, 1, 0),
1190       convert->dest_stride[1], FRAME_GET_LINE (dest, 2, 0),
1191       convert->dest_stride[2], FRAME_GET_LINE (src, 0, 0),
1192       2 * convert->src_stride[0], FRAME_GET_LINE (src, 0, 1),
1193       2 * convert->src_stride[0], convert->width / 2, convert->height / 2);
1194 }
1195
1196 static void
1197 convert_AYUV_YUY2 (ColorspaceConvert * convert, guint8 * dest,
1198     const guint8 * src)
1199 {
1200   cogorc_convert_AYUV_YUY2 (FRAME_GET_LINE (dest, 0, 0),
1201       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
1202       convert->src_stride[0], convert->width / 2, convert->height);
1203 }
1204
1205 static void
1206 convert_AYUV_UYVY (ColorspaceConvert * convert, guint8 * dest,
1207     const guint8 * src)
1208 {
1209   cogorc_convert_AYUV_UYVY (FRAME_GET_LINE (dest, 0, 0),
1210       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
1211       convert->src_stride[0], convert->width / 2, convert->height);
1212 }
1213
1214 static void
1215 convert_AYUV_Y42B (ColorspaceConvert * convert, guint8 * dest,
1216     const guint8 * src)
1217 {
1218   cogorc_convert_AYUV_Y42B (FRAME_GET_LINE (dest, 0, 0),
1219       convert->dest_stride[0], FRAME_GET_LINE (dest, 1, 0),
1220       convert->dest_stride[1], FRAME_GET_LINE (dest, 2, 0),
1221       convert->dest_stride[2], FRAME_GET_LINE (src, 0, 0),
1222       convert->src_stride[0], (convert->width + 1) / 2, convert->height);
1223 }
1224
1225 static void
1226 convert_AYUV_Y444 (ColorspaceConvert * convert, guint8 * dest,
1227     const guint8 * src)
1228 {
1229   cogorc_convert_AYUV_Y444 (FRAME_GET_LINE (dest, 0, 0),
1230       convert->dest_stride[0], FRAME_GET_LINE (dest, 1, 0),
1231       convert->dest_stride[1], FRAME_GET_LINE (dest, 2, 0),
1232       convert->dest_stride[2], FRAME_GET_LINE (src, 0, 0),
1233       convert->src_stride[0], convert->width, convert->height);
1234 }
1235
1236 static void
1237 convert_Y42B_I420 (ColorspaceConvert * convert, guint8 * dest,
1238     const guint8 * src)
1239 {
1240   cogorc_memcpy_2d (FRAME_GET_LINE (dest, 0, 0), convert->dest_stride[0],
1241       FRAME_GET_LINE (src, 0, 0), convert->src_stride[0],
1242       convert->width, convert->height);
1243
1244   cogorc_planar_chroma_422_420 (FRAME_GET_LINE (dest, 1, 0),
1245       convert->dest_stride[1], FRAME_GET_LINE (src, 1, 0),
1246       2 * convert->src_stride[1], FRAME_GET_LINE (src, 1, 1),
1247       2 * convert->src_stride[1], (convert->width + 1) / 2,
1248       (convert->height + 1) / 2);
1249
1250   cogorc_planar_chroma_422_420 (FRAME_GET_LINE (dest, 2, 0),
1251       convert->dest_stride[2], FRAME_GET_LINE (src, 2, 0),
1252       2 * convert->src_stride[2], FRAME_GET_LINE (src, 2, 1),
1253       2 * convert->src_stride[2], (convert->width + 1) / 2,
1254       (convert->height + 1) / 2);
1255 }
1256
1257 static void
1258 convert_Y42B_Y444 (ColorspaceConvert * convert, guint8 * dest,
1259     const guint8 * src)
1260 {
1261   cogorc_memcpy_2d (FRAME_GET_LINE (dest, 0, 0), convert->dest_stride[0],
1262       FRAME_GET_LINE (src, 0, 0), convert->src_stride[0],
1263       convert->width, convert->height);
1264
1265   cogorc_planar_chroma_422_444 (FRAME_GET_LINE (dest, 1, 0),
1266       convert->dest_stride[1], FRAME_GET_LINE (src, 1, 0),
1267       convert->src_stride[1], (convert->width + 1) / 2, convert->height);
1268
1269   cogorc_planar_chroma_422_444 (FRAME_GET_LINE (dest, 2, 0),
1270       convert->dest_stride[2], FRAME_GET_LINE (src, 2, 0),
1271       convert->src_stride[2], (convert->width + 1) / 2, convert->height);
1272 }
1273
1274 static void
1275 convert_Y42B_YUY2 (ColorspaceConvert * convert, guint8 * dest,
1276     const guint8 * src)
1277 {
1278   cogorc_convert_Y42B_YUY2 (FRAME_GET_LINE (dest, 0, 0),
1279       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
1280       convert->src_stride[0], FRAME_GET_LINE (src, 1, 0),
1281       convert->src_stride[1], FRAME_GET_LINE (src, 2, 0),
1282       convert->src_stride[2], (convert->width + 1) / 2, convert->height);
1283 }
1284
1285 static void
1286 convert_Y42B_UYVY (ColorspaceConvert * convert, guint8 * dest,
1287     const guint8 * src)
1288 {
1289   cogorc_convert_Y42B_UYVY (FRAME_GET_LINE (dest, 0, 0),
1290       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
1291       convert->src_stride[0], FRAME_GET_LINE (src, 1, 0),
1292       convert->src_stride[1], FRAME_GET_LINE (src, 2, 0),
1293       convert->src_stride[2], (convert->width + 1) / 2, convert->height);
1294 }
1295
1296 static void
1297 convert_Y42B_AYUV (ColorspaceConvert * convert, guint8 * dest,
1298     const guint8 * src)
1299 {
1300   cogorc_convert_Y42B_AYUV (FRAME_GET_LINE (dest, 0, 0),
1301       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
1302       convert->src_stride[0], FRAME_GET_LINE (src, 1, 0),
1303       convert->src_stride[1], FRAME_GET_LINE (src, 2, 0),
1304       convert->src_stride[2], (convert->width) / 2, convert->height);
1305 }
1306
1307 static void
1308 convert_Y444_I420 (ColorspaceConvert * convert, guint8 * dest,
1309     const guint8 * src)
1310 {
1311   cogorc_memcpy_2d (FRAME_GET_LINE (dest, 0, 0), convert->dest_stride[0],
1312       FRAME_GET_LINE (src, 0, 0), convert->src_stride[0],
1313       convert->width, convert->height);
1314
1315   cogorc_planar_chroma_444_420 (FRAME_GET_LINE (dest, 1, 0),
1316       convert->dest_stride[1], FRAME_GET_LINE (src, 1, 0),
1317       2 * convert->src_stride[1], FRAME_GET_LINE (src, 1, 1),
1318       2 * convert->src_stride[1], (convert->width + 1) / 2,
1319       (convert->height + 1) / 2);
1320
1321   cogorc_planar_chroma_444_420 (FRAME_GET_LINE (dest, 2, 0),
1322       convert->dest_stride[2], FRAME_GET_LINE (src, 2, 0),
1323       2 * convert->src_stride[2], FRAME_GET_LINE (src, 2, 1),
1324       2 * convert->src_stride[2], (convert->width + 1) / 2,
1325       (convert->height + 1) / 2);
1326 }
1327
1328 static void
1329 convert_Y444_Y42B (ColorspaceConvert * convert, guint8 * dest,
1330     const guint8 * src)
1331 {
1332   cogorc_memcpy_2d (FRAME_GET_LINE (dest, 0, 0), convert->dest_stride[0],
1333       FRAME_GET_LINE (src, 0, 0), convert->src_stride[0],
1334       convert->width, convert->height);
1335
1336   cogorc_planar_chroma_444_422 (FRAME_GET_LINE (dest, 1, 0),
1337       convert->dest_stride[1], FRAME_GET_LINE (src, 1, 0),
1338       convert->src_stride[1], (convert->width + 1) / 2, convert->height);
1339
1340   cogorc_planar_chroma_444_422 (FRAME_GET_LINE (dest, 2, 0),
1341       convert->dest_stride[2], FRAME_GET_LINE (src, 2, 0),
1342       convert->src_stride[2], (convert->width + 1) / 2, convert->height);
1343 }
1344
1345 static void
1346 convert_Y444_YUY2 (ColorspaceConvert * convert, guint8 * dest,
1347     const guint8 * src)
1348 {
1349   cogorc_convert_Y444_YUY2 (FRAME_GET_LINE (dest, 0, 0),
1350       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
1351       convert->src_stride[0], FRAME_GET_LINE (src, 1, 0),
1352       convert->src_stride[1], FRAME_GET_LINE (src, 2, 0),
1353       convert->src_stride[2], (convert->width + 1) / 2, convert->height);
1354 }
1355
1356 static void
1357 convert_Y444_UYVY (ColorspaceConvert * convert, guint8 * dest,
1358     const guint8 * src)
1359 {
1360   cogorc_convert_Y444_UYVY (FRAME_GET_LINE (dest, 0, 0),
1361       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
1362       convert->src_stride[0], FRAME_GET_LINE (src, 1, 0),
1363       convert->src_stride[1], FRAME_GET_LINE (src, 2, 0),
1364       convert->src_stride[2], (convert->width + 1) / 2, convert->height);
1365 }
1366
1367 static void
1368 convert_Y444_AYUV (ColorspaceConvert * convert, guint8 * dest,
1369     const guint8 * src)
1370 {
1371   cogorc_convert_Y444_AYUV (FRAME_GET_LINE (dest, 0, 0),
1372       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
1373       convert->src_stride[0], FRAME_GET_LINE (src, 1, 0),
1374       convert->src_stride[1], FRAME_GET_LINE (src, 2, 0),
1375       convert->src_stride[2], convert->width, convert->height);
1376 }
1377
1378 static void
1379 convert_AYUV_ARGB (ColorspaceConvert * convert, guint8 * dest,
1380     const guint8 * src)
1381 {
1382   cogorc_convert_AYUV_ARGB (FRAME_GET_LINE (dest, 0, 0),
1383       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
1384       convert->src_stride[0], convert->width, convert->height);
1385 }
1386
1387 static void
1388 convert_AYUV_BGRA (ColorspaceConvert * convert, guint8 * dest,
1389     const guint8 * src)
1390 {
1391   cogorc_convert_AYUV_BGRA (FRAME_GET_LINE (dest, 0, 0),
1392       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
1393       convert->src_stride[0], convert->width, convert->height);
1394 }
1395
1396 static void
1397 convert_AYUV_ABGR (ColorspaceConvert * convert, guint8 * dest,
1398     const guint8 * src)
1399 {
1400   cogorc_convert_AYUV_ABGR (FRAME_GET_LINE (dest, 0, 0),
1401       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
1402       convert->src_stride[0], convert->width, convert->height);
1403 }
1404
1405 static void
1406 convert_AYUV_RGBA (ColorspaceConvert * convert, guint8 * dest,
1407     const guint8 * src)
1408 {
1409   cogorc_convert_AYUV_RGBA (FRAME_GET_LINE (dest, 0, 0),
1410       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
1411       convert->src_stride[0], convert->width, convert->height);
1412 }
1413
1414 static void
1415 convert_I420_BGRA (ColorspaceConvert * convert, guint8 * dest,
1416     const guint8 * src)
1417 {
1418   int i;
1419   int quality = 0;
1420
1421   if (quality > 3) {
1422     for (i = 0; i < convert->height; i++) {
1423       if (i & 1) {
1424         cogorc_convert_I420_BGRA_avg (FRAME_GET_LINE (dest, 0, i),
1425             FRAME_GET_LINE (src, 0, i),
1426             FRAME_GET_LINE (src, 1, i >> 1),
1427             FRAME_GET_LINE (src, 1, (i >> 1) + 1),
1428             FRAME_GET_LINE (src, 2, i >> 1),
1429             FRAME_GET_LINE (src, 2, (i >> 1) + 1), convert->width);
1430       } else {
1431         cogorc_convert_I420_BGRA (FRAME_GET_LINE (dest, 0, i),
1432             FRAME_GET_LINE (src, 0, i),
1433             FRAME_GET_LINE (src, 1, i >> 1),
1434             FRAME_GET_LINE (src, 2, i >> 1), convert->width);
1435       }
1436     }
1437   } else {
1438     for (i = 0; i < convert->height; i++) {
1439       cogorc_convert_I420_BGRA (FRAME_GET_LINE (dest, 0, i),
1440           FRAME_GET_LINE (src, 0, i),
1441           FRAME_GET_LINE (src, 1, i >> 1),
1442           FRAME_GET_LINE (src, 2, i >> 1), convert->width);
1443     }
1444   }
1445 }
1446
1447
1448
1449 /* Fast paths */
1450
1451 typedef struct
1452 {
1453   GstVideoFormat from_format;
1454   ColorSpaceColorSpec from_spec;
1455   GstVideoFormat to_format;
1456   ColorSpaceColorSpec to_spec;
1457   gboolean keeps_color_spec;
1458   void (*convert) (ColorspaceConvert * convert, guint8 * dest,
1459       const guint8 * src);
1460 } ColorspaceTransform;
1461 static const ColorspaceTransform transforms[] = {
1462   {GST_VIDEO_FORMAT_I420, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_YUY2,
1463       COLOR_SPEC_NONE, TRUE, convert_I420_YUY2},
1464   {GST_VIDEO_FORMAT_I420, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_UYVY,
1465       COLOR_SPEC_NONE, TRUE, convert_I420_UYVY},
1466   {GST_VIDEO_FORMAT_I420, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_AYUV,
1467       COLOR_SPEC_NONE, TRUE, convert_I420_AYUV},
1468   {GST_VIDEO_FORMAT_I420, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_Y42B,
1469       COLOR_SPEC_NONE, TRUE, convert_I420_Y42B},
1470   {GST_VIDEO_FORMAT_I420, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_Y444,
1471       COLOR_SPEC_NONE, TRUE, convert_I420_Y444},
1472
1473   {GST_VIDEO_FORMAT_YUY2, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_I420,
1474       COLOR_SPEC_NONE, TRUE, convert_YUY2_I420},
1475   {GST_VIDEO_FORMAT_YUY2, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_UYVY, COLOR_SPEC_NONE, TRUE, convert_UYVY_YUY2},    /* alias */
1476   {GST_VIDEO_FORMAT_YUY2, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_AYUV,
1477       COLOR_SPEC_NONE, TRUE, convert_YUY2_AYUV},
1478   {GST_VIDEO_FORMAT_YUY2, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_Y42B,
1479       COLOR_SPEC_NONE, TRUE, convert_YUY2_Y42B},
1480   {GST_VIDEO_FORMAT_YUY2, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_Y444,
1481       COLOR_SPEC_NONE, TRUE, convert_YUY2_Y444},
1482
1483   {GST_VIDEO_FORMAT_UYVY, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_I420,
1484       COLOR_SPEC_NONE, TRUE, convert_UYVY_I420},
1485   {GST_VIDEO_FORMAT_UYVY, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_YUY2,
1486       COLOR_SPEC_NONE, TRUE, convert_UYVY_YUY2},
1487   {GST_VIDEO_FORMAT_UYVY, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_AYUV,
1488       COLOR_SPEC_NONE, TRUE, convert_UYVY_AYUV},
1489   {GST_VIDEO_FORMAT_UYVY, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_Y42B,
1490       COLOR_SPEC_NONE, TRUE, convert_UYVY_Y42B},
1491   {GST_VIDEO_FORMAT_UYVY, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_Y444,
1492       COLOR_SPEC_NONE, TRUE, convert_UYVY_Y444},
1493
1494   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_I420,
1495       COLOR_SPEC_NONE, TRUE, convert_AYUV_I420},
1496   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_YUY2,
1497       COLOR_SPEC_NONE, TRUE, convert_AYUV_YUY2},
1498   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_UYVY,
1499       COLOR_SPEC_NONE, TRUE, convert_AYUV_UYVY},
1500   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_Y42B,
1501       COLOR_SPEC_NONE, TRUE, convert_AYUV_Y42B},
1502   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_Y444,
1503       COLOR_SPEC_NONE, TRUE, convert_AYUV_Y444},
1504
1505   {GST_VIDEO_FORMAT_Y42B, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_I420,
1506       COLOR_SPEC_NONE, TRUE, convert_Y42B_I420},
1507   {GST_VIDEO_FORMAT_Y42B, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_YUY2,
1508       COLOR_SPEC_NONE, TRUE, convert_Y42B_YUY2},
1509   {GST_VIDEO_FORMAT_Y42B, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_UYVY,
1510       COLOR_SPEC_NONE, TRUE, convert_Y42B_UYVY},
1511   {GST_VIDEO_FORMAT_Y42B, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_AYUV,
1512       COLOR_SPEC_NONE, TRUE, convert_Y42B_AYUV},
1513   {GST_VIDEO_FORMAT_Y42B, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_Y444,
1514       COLOR_SPEC_NONE, TRUE, convert_Y42B_Y444},
1515
1516   {GST_VIDEO_FORMAT_Y444, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_I420,
1517       COLOR_SPEC_NONE, TRUE, convert_Y444_I420},
1518   {GST_VIDEO_FORMAT_Y444, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_YUY2,
1519       COLOR_SPEC_NONE, TRUE, convert_Y444_YUY2},
1520   {GST_VIDEO_FORMAT_Y444, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_UYVY,
1521       COLOR_SPEC_NONE, TRUE, convert_Y444_UYVY},
1522   {GST_VIDEO_FORMAT_Y444, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_AYUV,
1523       COLOR_SPEC_NONE, TRUE, convert_Y444_AYUV},
1524   {GST_VIDEO_FORMAT_Y444, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_Y42B,
1525       COLOR_SPEC_NONE, TRUE, convert_Y444_Y42B},
1526
1527   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_YUV_BT470_6, GST_VIDEO_FORMAT_ARGB,
1528       COLOR_SPEC_RGB, FALSE, convert_AYUV_ARGB},
1529   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_YUV_BT470_6, GST_VIDEO_FORMAT_BGRA,
1530       COLOR_SPEC_RGB, FALSE, convert_AYUV_BGRA},
1531   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_YUV_BT470_6, GST_VIDEO_FORMAT_xRGB, COLOR_SPEC_RGB, FALSE, convert_AYUV_ARGB},     /* alias */
1532   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_YUV_BT470_6, GST_VIDEO_FORMAT_BGRx, COLOR_SPEC_RGB, FALSE, convert_AYUV_BGRA},     /* alias */
1533   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_YUV_BT470_6, GST_VIDEO_FORMAT_ABGR,
1534       COLOR_SPEC_RGB, FALSE, convert_AYUV_ABGR},
1535   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_YUV_BT470_6, GST_VIDEO_FORMAT_RGBA,
1536       COLOR_SPEC_RGB, FALSE, convert_AYUV_RGBA},
1537   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_YUV_BT470_6, GST_VIDEO_FORMAT_xBGR, COLOR_SPEC_RGB, FALSE, convert_AYUV_ABGR},     /* alias */
1538   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_YUV_BT470_6, GST_VIDEO_FORMAT_RGBx, COLOR_SPEC_RGB, FALSE, convert_AYUV_RGBA},     /* alias */
1539
1540   {GST_VIDEO_FORMAT_I420, COLOR_SPEC_YUV_BT470_6, GST_VIDEO_FORMAT_BGRA,
1541       COLOR_SPEC_RGB, FALSE, convert_I420_BGRA},
1542 };
1543
1544 static void
1545 colorspace_convert_lookup_fastpath (ColorspaceConvert * convert)
1546 {
1547   int i;
1548
1549   for (i = 0; i < sizeof (transforms) / sizeof (transforms[0]); i++) {
1550     if (transforms[i].to_format == convert->to_format &&
1551         transforms[i].from_format == convert->from_format &&
1552         (transforms[i].keeps_color_spec ||
1553             (transforms[i].from_spec == convert->from_spec &&
1554                 transforms[i].to_spec == convert->to_spec))) {
1555       convert->convert = transforms[i].convert;
1556       return;
1557     }
1558   }
1559 }