761e505a1ee9ed9b853029edcc5c5b151feff286
[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 static void colorspace_dither_none (ColorspaceConvert * convert, int j);
36 static void colorspace_dither_verterr (ColorspaceConvert * convert, int j);
37 static void colorspace_dither_halftone (ColorspaceConvert * convert, int j);
38
39
40 ColorspaceConvert *
41 colorspace_convert_new (GstVideoFormat to_format, ColorSpaceColorSpec to_spec,
42     GstVideoFormat from_format, ColorSpaceColorSpec from_spec,
43     int width, int height)
44 {
45   ColorspaceConvert *convert;
46   int i;
47
48   g_return_val_if_fail (!gst_video_format_is_rgb (to_format)
49       || to_spec == COLOR_SPEC_RGB, NULL);
50   g_return_val_if_fail (!gst_video_format_is_yuv (to_format)
51       || to_spec == COLOR_SPEC_YUV_BT709
52       || to_spec == COLOR_SPEC_YUV_BT470_6, NULL);
53   g_return_val_if_fail (gst_video_format_is_rgb (to_format)
54       || gst_video_format_is_yuv (to_format)
55       || (gst_video_format_is_gray (to_format) &&
56           to_spec == COLOR_SPEC_GRAY), NULL);
57
58   g_return_val_if_fail (!gst_video_format_is_rgb (from_format)
59       || from_spec == COLOR_SPEC_RGB, NULL);
60   g_return_val_if_fail (!gst_video_format_is_yuv (from_format)
61       || from_spec == COLOR_SPEC_YUV_BT709
62       || from_spec == COLOR_SPEC_YUV_BT470_6, NULL);
63   g_return_val_if_fail (gst_video_format_is_rgb (from_format)
64       || gst_video_format_is_yuv (from_format)
65       || (gst_video_format_is_gray (from_format) &&
66           from_spec == COLOR_SPEC_GRAY), NULL);
67
68   convert = g_malloc (sizeof (ColorspaceConvert));
69   memset (convert, 0, sizeof (ColorspaceConvert));
70
71   convert->to_format = to_format;
72   convert->to_spec = to_spec;
73   convert->from_format = from_format;
74   convert->from_spec = from_spec;
75   convert->height = height;
76   convert->width = width;
77   convert->convert = colorspace_convert_generic;
78   convert->dither16 = colorspace_dither_none;
79
80   if (gst_video_format_get_component_depth (to_format, 0) > 8 ||
81       gst_video_format_get_component_depth (from_format, 0) > 8) {
82     convert->use_16bit = TRUE;
83   } else {
84     convert->use_16bit = FALSE;
85   }
86
87   for (i = 0; i < 4; i++) {
88     convert->dest_stride[i] = gst_video_format_get_row_stride (to_format, i,
89         width);
90     convert->dest_offset[i] = gst_video_format_get_component_offset (to_format,
91         i, width, height);
92     if (i == 0)
93       convert->dest_offset[i] = 0;
94
95     convert->src_stride[i] = gst_video_format_get_row_stride (from_format, i,
96         width);
97     convert->src_offset[i] = gst_video_format_get_component_offset (from_format,
98         i, width, height);
99     if (i == 0)
100       convert->src_offset[i] = 0;
101
102     GST_DEBUG ("%d: dest %d %d src %d %d", i,
103         convert->dest_stride[i], convert->dest_offset[i],
104         convert->src_stride[i], convert->src_offset[i]);
105   }
106
107   colorspace_convert_lookup_fastpath (convert);
108   colorspace_convert_lookup_getput (convert);
109
110   convert->tmpline = g_malloc (sizeof (guint8) * (width + 8) * 4);
111   convert->tmpline16 = g_malloc (sizeof (guint16) * (width + 8) * 4);
112   convert->errline = g_malloc (sizeof (guint16) * width * 4);
113
114   if (to_format == GST_VIDEO_FORMAT_RGB8_PALETTED) {
115     /* build poor man's palette, taken from ffmpegcolorspace */
116     static const guint8 pal_value[6] = { 0x00, 0x33, 0x66, 0x99, 0xcc, 0xff };
117     guint32 *palette;
118     gint r, g, b;
119
120     convert->palette = palette = g_new (guint32, 256);
121     i = 0;
122     for (r = 0; r < 6; r++) {
123       for (g = 0; g < 6; g++) {
124         for (b = 0; b < 6; b++) {
125           palette[i++] =
126               (0xffU << 24) | (pal_value[r] << 16) | (pal_value[g] << 8) |
127               pal_value[b];
128         }
129       }
130     }
131     palette[i++] = 0;           /* 100% transparent, i == 6*6*6 */
132     while (i < 256)
133       palette[i++] = 0xff000000;
134   }
135
136   return convert;
137 }
138
139 void
140 colorspace_convert_free (ColorspaceConvert * convert)
141 {
142   g_free (convert->palette);
143   g_free (convert->tmpline);
144   g_free (convert->tmpline16);
145   g_free (convert->errline);
146
147   g_free (convert);
148 }
149
150 void
151 colorspace_convert_set_interlaced (ColorspaceConvert * convert,
152     gboolean interlaced)
153 {
154   convert->interlaced = interlaced;
155 }
156
157 void
158 colorspace_convert_set_dither (ColorspaceConvert * convert, int type)
159 {
160   switch (type) {
161     case 0:
162     default:
163       convert->dither16 = colorspace_dither_none;
164       break;
165     case 1:
166       convert->dither16 = colorspace_dither_verterr;
167       break;
168     case 2:
169       convert->dither16 = colorspace_dither_halftone;
170       break;
171   }
172 }
173
174 void
175 colorspace_convert_set_palette (ColorspaceConvert * convert,
176     const guint32 * palette)
177 {
178   if (convert->palette == NULL) {
179     convert->palette = g_malloc (sizeof (guint32) * 256);
180   }
181   memcpy (convert->palette, palette, sizeof (guint32) * 256);
182 }
183
184 const guint32 *
185 colorspace_convert_get_palette (ColorspaceConvert * convert)
186 {
187   return convert->palette;
188 }
189
190 void
191 colorspace_convert_convert (ColorspaceConvert * convert,
192     guint8 * dest, const guint8 * src)
193 {
194   convert->convert (convert, dest, src);
195 }
196
197 /* Line conversion to AYUV */
198
199 #define FRAME_GET_LINE(dir, comp, line) \
200   ((dir) + convert-> dir ## _offset[(comp)] + convert-> dir ## _stride[(comp)] * (line))
201
202 static void
203 getline_I420 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
204     int j)
205 {
206   cogorc_getline_I420 (dest,
207       FRAME_GET_LINE (src, 0, j),
208       FRAME_GET_LINE (src, 1, j >> 1),
209       FRAME_GET_LINE (src, 2, j >> 1), convert->width);
210 }
211
212 static void
213 putline_I420 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
214     int j)
215 {
216   cogorc_putline_I420 (FRAME_GET_LINE (dest, 0, j),
217       FRAME_GET_LINE (dest, 1, j >> 1),
218       FRAME_GET_LINE (dest, 2, j >> 1), src, convert->width / 2);
219 }
220
221 static void
222 getline_YV12 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
223     int j)
224 {
225   cogorc_getline_I420 (dest,
226       FRAME_GET_LINE (src, 0, j),
227       FRAME_GET_LINE (src, 1, j >> 1),
228       FRAME_GET_LINE (src, 2, j >> 1), convert->width);
229 }
230
231 static void
232 putline_YV12 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
233     int j)
234 {
235   cogorc_putline_I420 (FRAME_GET_LINE (dest, 0, j),
236       FRAME_GET_LINE (dest, 1, j >> 1),
237       FRAME_GET_LINE (dest, 2, j >> 1), src, convert->width / 2);
238 }
239
240 static void
241 getline_YUY2 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
242     int j)
243 {
244   cogorc_getline_YUY2 (dest, FRAME_GET_LINE (src, 0, j), convert->width / 2);
245 }
246
247 static void
248 putline_YUY2 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
249     int j)
250 {
251   cogorc_putline_YUY2 (FRAME_GET_LINE (dest, 0, j), src, convert->width / 2);
252 }
253
254 static void
255 getline_UYVY (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
256     int j)
257 {
258   cogorc_getline_UYVY (dest, FRAME_GET_LINE (src, 0, j), convert->width / 2);
259 }
260
261 static void
262 putline_UYVY (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
263     int j)
264 {
265   cogorc_putline_UYVY (FRAME_GET_LINE (dest, 0, j), src, convert->width / 2);
266 }
267
268 static void
269 getline_YVYU (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
270     int j)
271 {
272   cogorc_getline_YVYU (dest, FRAME_GET_LINE (src, 0, j), convert->width / 2);
273 }
274
275 static void
276 putline_YVYU (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
277     int j)
278 {
279   cogorc_putline_YVYU (FRAME_GET_LINE (dest, 0, j), src, convert->width / 2);
280 }
281
282 static void
283 getline_v308 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
284     int j)
285 {
286   int i;
287   const guint8 *srcline = FRAME_GET_LINE (src, 0, j);
288   for (i = 0; i < convert->width; i++) {
289     dest[i * 4 + 0] = 0xff;
290     dest[i * 4 + 1] = srcline[i * 3 + 0];
291     dest[i * 4 + 2] = srcline[i * 3 + 1];
292     dest[i * 4 + 3] = srcline[i * 3 + 2];
293   }
294 }
295
296 static void
297 putline_v308 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
298     int j)
299 {
300   int i;
301   guint8 *destline = FRAME_GET_LINE (dest, 0, j);
302   for (i = 0; i < convert->width; i++) {
303     destline[i * 3 + 0] = src[i * 4 + 1];
304     destline[i * 3 + 1] = src[i * 4 + 2];
305     destline[i * 3 + 2] = src[i * 4 + 3];
306   }
307 }
308
309 static void
310 getline_AYUV (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
311     int j)
312 {
313   memcpy (dest, FRAME_GET_LINE (src, 0, j), convert->width * 4);
314 }
315
316 static void
317 putline_AYUV (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
318     int j)
319 {
320   memcpy (FRAME_GET_LINE (dest, 0, j), src, convert->width * 4);
321 }
322
323 #if 0
324 static void
325 getline_v410 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
326     int j)
327 {
328   int i;
329   const guint8 *srcline = FRAME_GET_LINE (src, 0, j);
330   for (i = 0; i < convert->width; i++) {
331     dest[i * 4 + 0] = GST_READ_UINT16_LE (srcline + i * 8 + 0);
332     dest[i * 4 + 1] = GST_READ_UINT16_LE (srcline + i * 8 + 2);
333     dest[i * 4 + 2] = GST_READ_UINT16_LE (srcline + i * 8 + 4);
334     dest[i * 4 + 3] = GST_READ_UINT16_LE (srcline + i * 8 + 6);
335   }
336 }
337 #endif
338
339 static void
340 getline_v210 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
341     int j)
342 {
343   int i;
344   const guint8 *srcline = FRAME_GET_LINE (src, 0, j);
345
346   for (i = 0; i < convert->width; i += 6) {
347     guint32 a0, a1, a2, a3;
348     guint16 y0, y1, y2, y3, y4, y5;
349     guint16 u0, u2, u4;
350     guint16 v0, v2, v4;
351
352     a0 = GST_READ_UINT32_LE (srcline + (i / 6) * 16 + 0);
353     a1 = GST_READ_UINT32_LE (srcline + (i / 6) * 16 + 4);
354     a2 = GST_READ_UINT32_LE (srcline + (i / 6) * 16 + 8);
355     a3 = GST_READ_UINT32_LE (srcline + (i / 6) * 16 + 12);
356
357     u0 = ((a0 >> 0) & 0x3ff) >> 2;
358     y0 = ((a0 >> 10) & 0x3ff) >> 2;
359     v0 = ((a0 >> 20) & 0x3ff) >> 2;
360     y1 = ((a1 >> 0) & 0x3ff) >> 2;
361
362     u2 = ((a1 >> 10) & 0x3ff) >> 2;
363     y2 = ((a1 >> 20) & 0x3ff) >> 2;
364     v2 = ((a2 >> 0) & 0x3ff) >> 2;
365     y3 = ((a2 >> 10) & 0x3ff) >> 2;
366
367     u4 = ((a2 >> 20) & 0x3ff) >> 2;
368     y4 = ((a3 >> 0) & 0x3ff) >> 2;
369     v4 = ((a3 >> 10) & 0x3ff) >> 2;
370     y5 = ((a3 >> 20) & 0x3ff) >> 2;
371
372     dest[4 * (i + 0) + 0] = 0xff;
373     dest[4 * (i + 0) + 1] = y0;
374     dest[4 * (i + 0) + 2] = u0;
375     dest[4 * (i + 0) + 3] = v0;
376
377     dest[4 * (i + 1) + 0] = 0xff;
378     dest[4 * (i + 1) + 1] = y1;
379     dest[4 * (i + 1) + 2] = u0;
380     dest[4 * (i + 1) + 3] = v0;
381
382     dest[4 * (i + 2) + 0] = 0xff;
383     dest[4 * (i + 2) + 1] = y2;
384     dest[4 * (i + 2) + 2] = u2;
385     dest[4 * (i + 2) + 3] = v2;
386
387     dest[4 * (i + 3) + 0] = 0xff;
388     dest[4 * (i + 3) + 1] = y3;
389     dest[4 * (i + 3) + 2] = u2;
390     dest[4 * (i + 3) + 3] = v2;
391
392     dest[4 * (i + 4) + 0] = 0xff;
393     dest[4 * (i + 4) + 1] = y4;
394     dest[4 * (i + 4) + 2] = u4;
395     dest[4 * (i + 4) + 3] = v4;
396
397     dest[4 * (i + 5) + 0] = 0xff;
398     dest[4 * (i + 5) + 1] = y5;
399     dest[4 * (i + 5) + 2] = u4;
400     dest[4 * (i + 5) + 3] = v4;
401
402   }
403
404 }
405
406 static void
407 putline_v210 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
408     int j)
409 {
410   int i;
411   guint8 *destline = FRAME_GET_LINE (dest, 0, j);
412
413   for (i = 0; i < convert->width + 5; i += 6) {
414     guint32 a0, a1, a2, a3;
415     guint16 y0, y1, y2, y3, y4, y5;
416     guint16 u0, u1, u2;
417     guint16 v0, v1, v2;
418
419     y0 = src[4 * (i + 0) + 1] << 2;
420     y1 = src[4 * (i + 1) + 1] << 2;
421     y2 = src[4 * (i + 2) + 1] << 2;
422     y3 = src[4 * (i + 3) + 1] << 2;
423     y4 = src[4 * (i + 4) + 1] << 2;
424     y5 = src[4 * (i + 5) + 1] << 2;
425
426     u0 = (src[4 * (i + 0) + 2] + src[4 * (i + 1) + 2]) << 1;
427     u1 = (src[4 * (i + 2) + 2] + src[4 * (i + 3) + 2]) << 1;
428     u2 = (src[4 * (i + 4) + 2] + src[4 * (i + 5) + 2]) << 1;
429
430     v0 = (src[4 * (i + 0) + 3] + src[4 * (i + 1) + 3]) << 1;
431     v1 = (src[4 * (i + 2) + 3] + src[4 * (i + 3) + 3]) << 1;
432     v2 = (src[4 * (i + 4) + 3] + src[4 * (i + 5) + 3]) << 1;
433
434     a0 = u0 | (y0 << 10) | (v0 << 20);
435     a1 = y1 | (u1 << 10) | (y2 << 20);
436     a2 = v1 | (y3 << 10) | (u2 << 20);
437     a3 = y4 | (v2 << 10) | (y5 << 20);
438
439     GST_WRITE_UINT32_LE (destline + (i / 6) * 16 + 0, a0);
440     GST_WRITE_UINT32_LE (destline + (i / 6) * 16 + 4, a1);
441     GST_WRITE_UINT32_LE (destline + (i / 6) * 16 + 8, a2);
442     GST_WRITE_UINT32_LE (destline + (i / 6) * 16 + 12, a3);
443   }
444 }
445
446 static void
447 getline16_v210 (ColorspaceConvert * convert, guint16 * dest, const guint8 * src,
448     int j)
449 {
450   int i;
451   const guint8 *srcline = FRAME_GET_LINE (src, 0, j);
452
453   for (i = 0; i < convert->width; i += 6) {
454     guint32 a0, a1, a2, a3;
455     guint16 y0, y1, y2, y3, y4, y5;
456     guint16 u0, u2, u4;
457     guint16 v0, v2, v4;
458
459     a0 = GST_READ_UINT32_LE (srcline + (i / 6) * 16 + 0);
460     a1 = GST_READ_UINT32_LE (srcline + (i / 6) * 16 + 4);
461     a2 = GST_READ_UINT32_LE (srcline + (i / 6) * 16 + 8);
462     a3 = GST_READ_UINT32_LE (srcline + (i / 6) * 16 + 12);
463
464     u0 = ((a0 >> 0) & 0x3ff) << 6;
465     y0 = ((a0 >> 10) & 0x3ff) << 6;
466     v0 = ((a0 >> 20) & 0x3ff) << 6;
467     y1 = ((a1 >> 0) & 0x3ff) << 6;
468
469     u2 = ((a1 >> 10) & 0x3ff) << 6;
470     y2 = ((a1 >> 20) & 0x3ff) << 6;
471     v2 = ((a2 >> 0) & 0x3ff) << 6;
472     y3 = ((a2 >> 10) & 0x3ff) << 6;
473
474     u4 = ((a2 >> 20) & 0x3ff) << 6;
475     y4 = ((a3 >> 0) & 0x3ff) << 6;
476     v4 = ((a3 >> 10) & 0x3ff) << 6;
477     y5 = ((a3 >> 20) & 0x3ff) << 6;
478
479     dest[4 * (i + 0) + 0] = 0xffff;
480     dest[4 * (i + 0) + 1] = y0;
481     dest[4 * (i + 0) + 2] = u0;
482     dest[4 * (i + 0) + 3] = v0;
483
484     dest[4 * (i + 1) + 0] = 0xffff;
485     dest[4 * (i + 1) + 1] = y1;
486     dest[4 * (i + 1) + 2] = u0;
487     dest[4 * (i + 1) + 3] = v0;
488
489     dest[4 * (i + 2) + 0] = 0xffff;
490     dest[4 * (i + 2) + 1] = y2;
491     dest[4 * (i + 2) + 2] = u2;
492     dest[4 * (i + 2) + 3] = v2;
493
494     dest[4 * (i + 3) + 0] = 0xffff;
495     dest[4 * (i + 3) + 1] = y3;
496     dest[4 * (i + 3) + 2] = u2;
497     dest[4 * (i + 3) + 3] = v2;
498
499     dest[4 * (i + 4) + 0] = 0xffff;
500     dest[4 * (i + 4) + 1] = y4;
501     dest[4 * (i + 4) + 2] = u4;
502     dest[4 * (i + 4) + 3] = v4;
503
504     dest[4 * (i + 5) + 0] = 0xffff;
505     dest[4 * (i + 5) + 1] = y5;
506     dest[4 * (i + 5) + 2] = u4;
507     dest[4 * (i + 5) + 3] = v4;
508
509   }
510 }
511
512 static void
513 putline16_v210 (ColorspaceConvert * convert, guint8 * dest, const guint16 * src,
514     int j)
515 {
516   int i;
517   guint8 *destline = FRAME_GET_LINE (dest, 0, j);
518
519   for (i = 0; i < convert->width + 5; i += 6) {
520     guint32 a0, a1, a2, a3;
521     guint16 y0, y1, y2, y3, y4, y5;
522     guint16 u0, u1, u2;
523     guint16 v0, v1, v2;
524
525     y0 = src[4 * (i + 0) + 1] >> 6;
526     y1 = src[4 * (i + 1) + 1] >> 6;
527     y2 = src[4 * (i + 2) + 1] >> 6;
528     y3 = src[4 * (i + 3) + 1] >> 6;
529     y4 = src[4 * (i + 4) + 1] >> 6;
530     y5 = src[4 * (i + 5) + 1] >> 6;
531
532     u0 = (src[4 * (i + 0) + 2] + src[4 * (i + 1) + 2] + 1) >> 7;
533     u1 = (src[4 * (i + 2) + 2] + src[4 * (i + 3) + 2] + 1) >> 7;
534     u2 = (src[4 * (i + 4) + 2] + src[4 * (i + 5) + 2] + 1) >> 7;
535
536     v0 = (src[4 * (i + 0) + 3] + src[4 * (i + 1) + 3] + 1) >> 7;
537     v1 = (src[4 * (i + 2) + 3] + src[4 * (i + 3) + 3] + 1) >> 7;
538     v2 = (src[4 * (i + 4) + 3] + src[4 * (i + 5) + 3] + 1) >> 7;
539
540     a0 = u0 | (y0 << 10) | (v0 << 20);
541     a1 = y1 | (u1 << 10) | (y2 << 20);
542     a2 = v1 | (y3 << 10) | (u2 << 20);
543     a3 = y4 | (v2 << 10) | (y5 << 20);
544
545     GST_WRITE_UINT32_LE (destline + (i / 6) * 16 + 0, a0);
546     GST_WRITE_UINT32_LE (destline + (i / 6) * 16 + 4, a1);
547     GST_WRITE_UINT32_LE (destline + (i / 6) * 16 + 8, a2);
548     GST_WRITE_UINT32_LE (destline + (i / 6) * 16 + 12, a3);
549   }
550 }
551
552 static void
553 getline_v216 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
554     int j)
555 {
556   int i;
557   const guint8 *srcline = FRAME_GET_LINE (src, 0, j);
558   for (i = 0; i < convert->width; i++) {
559     dest[i * 4 + 0] = 0xff;
560     dest[i * 4 + 1] = GST_READ_UINT16_LE (srcline + i * 4 + 2) >> 8;
561     dest[i * 4 + 2] = GST_READ_UINT16_LE (srcline + (i >> 1) * 8 + 0) >> 8;
562     dest[i * 4 + 3] = GST_READ_UINT16_LE (srcline + (i >> 1) * 8 + 4) >> 8;
563   }
564 }
565
566 static void
567 putline_v216 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
568     int j)
569 {
570   int i;
571   guint8 *destline = FRAME_GET_LINE (dest, 0, j);
572   for (i = 0; i < convert->width / 2; i++) {
573     GST_WRITE_UINT16_LE (destline + i * 8 + 0, src[(i * 2 + 0) * 4 + 2] << 8);
574     GST_WRITE_UINT16_LE (destline + i * 8 + 2, src[(i * 2 + 0) * 4 + 1] << 8);
575     GST_WRITE_UINT16_LE (destline + i * 8 + 4, src[(i * 2 + 1) * 4 + 3] << 8);
576     GST_WRITE_UINT16_LE (destline + i * 8 + 8, src[(i * 2 + 0) * 4 + 1] << 8);
577   }
578 }
579
580 static void
581 getline16_v216 (ColorspaceConvert * convert, guint16 * dest, const guint8 * src,
582     int j)
583 {
584   int i;
585   const guint8 *srcline = FRAME_GET_LINE (src, 0, j);
586   for (i = 0; i < convert->width; i++) {
587     dest[i * 4 + 0] = 0xffff;
588     dest[i * 4 + 1] = GST_READ_UINT16_LE (srcline + i * 4 + 2);
589     dest[i * 4 + 2] = GST_READ_UINT16_LE (srcline + (i >> 1) * 8 + 0);
590     dest[i * 4 + 3] = GST_READ_UINT16_LE (srcline + (i >> 1) * 8 + 4);
591   }
592 }
593
594 static void
595 putline16_v216 (ColorspaceConvert * convert, guint8 * dest, const guint16 * src,
596     int j)
597 {
598   int i;
599   guint8 *destline = FRAME_GET_LINE (dest, 0, j);
600   for (i = 0; i < convert->width / 2; i++) {
601     GST_WRITE_UINT16_LE (destline + i * 8 + 0, src[(i * 2 + 0) * 4 + 2]);
602     GST_WRITE_UINT16_LE (destline + i * 8 + 2, src[(i * 2 + 0) * 4 + 1]);
603     GST_WRITE_UINT16_LE (destline + i * 8 + 4, src[(i * 2 + 1) * 4 + 3]);
604     GST_WRITE_UINT16_LE (destline + i * 8 + 8, src[(i * 2 + 0) * 4 + 1]);
605   }
606 }
607
608 static void
609 getline_Y41B (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
610     int j)
611 {
612   cogorc_getline_YUV9 (dest,
613       FRAME_GET_LINE (src, 0, j),
614       FRAME_GET_LINE (src, 1, j), FRAME_GET_LINE (src, 2, j),
615       convert->width / 2);
616 }
617
618 static void
619 putline_Y41B (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
620     int j)
621 {
622   int i;
623   guint8 *destlineY = FRAME_GET_LINE (dest, 0, j);
624   guint8 *destlineU = FRAME_GET_LINE (dest, 1, j);
625   guint8 *destlineV = FRAME_GET_LINE (dest, 2, j);
626
627   for (i = 0; i < convert->width - 3; i += 4) {
628     destlineY[i] = src[i * 4 + 1];
629     destlineY[i + 1] = src[i * 4 + 5];
630     destlineY[i + 2] = src[i * 4 + 9];
631     destlineY[i + 3] = src[i * 4 + 13];
632
633     destlineU[i >> 2] =
634         (src[i * 4 + 2] + src[i * 4 + 6] + src[i * 4 + 10] + src[i * 4 + 14] +
635         2) >> 2;
636     destlineV[i >> 2] =
637         (src[i * 4 + 3] + src[i * 4 + 7] + src[i * 4 + 11] + src[i * 4 + 15] +
638         2) >> 2;
639   }
640
641   if (i == convert->width - 3) {
642     destlineY[i] = src[i * 4 + 1];
643     destlineY[i + 1] = src[i * 4 + 5];
644     destlineY[i + 2] = src[i * 4 + 9];
645
646     destlineU[i >> 2] =
647         (src[i * 4 + 2] + src[i * 4 + 6] + src[i * 4 + 10] + 1) / 3;
648     destlineV[i >> 2] =
649         (src[i * 4 + 3] + src[i * 4 + 7] + src[i * 4 + 11] + 1) / 3;
650   } else if (i == convert->width - 2) {
651     destlineY[i] = src[i * 4 + 1];
652     destlineY[i + 1] = src[i * 4 + 5];
653
654     destlineU[i >> 2] = (src[i * 4 + 2] + src[i * 4 + 6] + 1) >> 1;
655     destlineV[i >> 2] = (src[i * 4 + 3] + src[i * 4 + 7] + 1) >> 1;
656   } else if (i == convert->width - 1) {
657     destlineY[i + 1] = src[i * 4 + 5];
658
659     destlineU[i >> 2] = src[i * 4 + 2];
660     destlineV[i >> 2] = src[i * 4 + 3];
661   }
662 }
663
664 static void
665 getline_Y42B (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
666     int j)
667 {
668   cogorc_getline_Y42B (dest,
669       FRAME_GET_LINE (src, 0, j),
670       FRAME_GET_LINE (src, 1, j),
671       FRAME_GET_LINE (src, 2, j), convert->width / 2);
672 }
673
674 static void
675 putline_Y42B (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
676     int j)
677 {
678   cogorc_putline_Y42B (FRAME_GET_LINE (dest, 0, j),
679       FRAME_GET_LINE (dest, 1, j),
680       FRAME_GET_LINE (dest, 2, j), src, convert->width / 2);
681 }
682
683 static void
684 getline_Y444 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
685     int j)
686 {
687   cogorc_getline_Y444 (dest,
688       FRAME_GET_LINE (src, 0, j),
689       FRAME_GET_LINE (src, 1, j), FRAME_GET_LINE (src, 2, j), convert->width);
690 }
691
692 static void
693 putline_Y444 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
694     int j)
695 {
696   cogorc_putline_Y444 (FRAME_GET_LINE (dest, 0, j),
697       FRAME_GET_LINE (dest, 1, j),
698       FRAME_GET_LINE (dest, 2, j), src, convert->width);
699 }
700
701 static void
702 getline_Y800 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
703     int j)
704 {
705   cogorc_getline_Y800 (dest, FRAME_GET_LINE (src, 0, j), convert->width);
706 }
707
708 static void
709 putline_Y800 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
710     int j)
711 {
712   cogorc_putline_Y800 (FRAME_GET_LINE (dest, 0, j), src, convert->width);
713 }
714
715 static void
716 getline_Y16 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
717     int j)
718 {
719   cogorc_getline_Y16 (dest, FRAME_GET_LINE (src, 0, j), convert->width);
720 }
721
722 static void
723 putline_Y16 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
724     int j)
725 {
726   cogorc_putline_Y16 (FRAME_GET_LINE (dest, 0, j), src, convert->width);
727 }
728
729 static void
730 getline_RGB16 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
731     int j)
732 {
733   int i;
734   const guint16 *srcline = (const guint16 *) FRAME_GET_LINE (src, 0, j);
735   for (i = 0; i < convert->width; i++) {
736     dest[i * 4 + 0] = 0xff;
737     dest[i * 4 + 1] = ((srcline[i] >> 11) & 0x1f) << 3;
738     dest[i * 4 + 2] = ((srcline[i] >> 5) & 0x3f) << 2;
739     dest[i * 4 + 3] = ((srcline[i]) & 0x1f) << 3;
740   }
741 }
742
743 static void
744 putline_RGB16 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
745     int j)
746 {
747   int i;
748   guint16 *destline = (guint16 *) FRAME_GET_LINE (dest, 0, j);
749   for (i = 0; i < convert->width; i++) {
750     destline[i] =
751         ((src[i * 4 + 1] >> 3) << 11) | ((src[i * 4 +
752                 2] >> 2) << 5) | (src[i * 4 + 3] >> 3);
753   }
754 }
755
756 static void
757 getline_BGR16 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
758     int j)
759 {
760   int i;
761   const guint16 *srcline = (const guint16 *) FRAME_GET_LINE (src, 0, j);
762   for (i = 0; i < convert->width; i++) {
763     dest[i * 4 + 0] = 0xff;
764     dest[i * 4 + 3] = ((srcline[i] >> 11) & 0x1f) << 3;
765     dest[i * 4 + 2] = ((srcline[i] >> 5) & 0x3f) << 2;
766     dest[i * 4 + 1] = ((srcline[i]) & 0x1f) << 3;
767   }
768 }
769
770 static void
771 putline_BGR16 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
772     int j)
773 {
774   int i;
775   guint16 *destline = (guint16 *) FRAME_GET_LINE (dest, 0, j);
776   for (i = 0; i < convert->width; i++) {
777     destline[i] =
778         ((src[i * 4 + 3] >> 3) << 11) | ((src[i * 4 +
779                 2] >> 2) << 5) | (src[i * 4 + 1] >> 3);
780   }
781 }
782
783 static void
784 getline_RGB15 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
785     int j)
786 {
787   int i;
788   const guint16 *srcline = (const guint16 *) FRAME_GET_LINE (src, 0, j);
789   for (i = 0; i < convert->width; i++) {
790     dest[i * 4 + 0] = 0xff;
791     dest[i * 4 + 1] = ((srcline[i] >> 10) & 0x1f) << 3;
792     dest[i * 4 + 2] = ((srcline[i] >> 5) & 0x1f) << 3;
793     dest[i * 4 + 3] = ((srcline[i]) & 0x1f) << 3;
794   }
795 }
796
797 static void
798 putline_RGB15 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
799     int j)
800 {
801   int i;
802   guint16 *destline = (guint16 *) FRAME_GET_LINE (dest, 0, j);
803   for (i = 0; i < convert->width; i++) {
804     destline[i] =
805         ((src[i * 4 + 1] >> 3) << 10) | ((src[i * 4 +
806                 2] >> 3) << 5) | (src[i * 4 + 3] >> 3);
807   }
808 }
809
810 static void
811 getline_BGR15 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
812     int j)
813 {
814   int i;
815   const guint16 *srcline = (const guint16 *) FRAME_GET_LINE (src, 0, j);
816   for (i = 0; i < convert->width; i++) {
817     dest[i * 4 + 0] = 0xff;
818     dest[i * 4 + 3] = ((srcline[i] >> 10) & 0x1f) << 3;
819     dest[i * 4 + 2] = ((srcline[i] >> 5) & 0x1f) << 3;
820     dest[i * 4 + 1] = ((srcline[i]) & 0x1f) << 3;
821   }
822 }
823
824 static void
825 putline_BGR15 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
826     int j)
827 {
828   int i;
829   guint16 *destline = (guint16 *) FRAME_GET_LINE (dest, 0, j);
830   for (i = 0; i < convert->width; i++) {
831     destline[i] =
832         ((src[i * 4 + 3] >> 3) << 10) | ((src[i * 4 +
833                 2] >> 3) << 5) | (src[i * 4 + 1] >> 3);
834   }
835 }
836
837 static void
838 getline_BGRA (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
839     int j)
840 {
841   cogorc_getline_BGRA (dest, FRAME_GET_LINE (src, 0, j), convert->width);
842 }
843
844 static void
845 putline_BGRA (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
846     int j)
847 {
848   cogorc_putline_BGRA (FRAME_GET_LINE (dest, 0, j), src, convert->width);
849 }
850
851 static void
852 getline_ABGR (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
853     int j)
854 {
855   cogorc_getline_ABGR (dest, FRAME_GET_LINE (src, 0, j), convert->width);
856 }
857
858 static void
859 putline_ABGR (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
860     int j)
861 {
862   cogorc_putline_ABGR (FRAME_GET_LINE (dest, 0, j), src, convert->width);
863 }
864
865 static void
866 getline_RGBA (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
867     int j)
868 {
869   cogorc_getline_RGBA (dest, FRAME_GET_LINE (src, 0, j), convert->width);
870 }
871
872 static void
873 putline_RGBA (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
874     int j)
875 {
876   cogorc_putline_RGBA (FRAME_GET_LINE (dest, 0, j), src, convert->width);
877 }
878
879 static void
880 getline_RGB (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
881     int j)
882 {
883   int i;
884   const guint8 *srcline = FRAME_GET_LINE (src, 0, j);
885   for (i = 0; i < convert->width; i++) {
886     dest[i * 4 + 0] = 0xff;
887     dest[i * 4 + 1] = srcline[i * 3 + 0];
888     dest[i * 4 + 2] = srcline[i * 3 + 1];
889     dest[i * 4 + 3] = srcline[i * 3 + 2];
890   }
891 }
892
893 static void
894 putline_RGB (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
895     int j)
896 {
897   int i;
898   guint8 *destline = FRAME_GET_LINE (dest, 0, j);
899   for (i = 0; i < convert->width; i++) {
900     destline[i * 3 + 0] = src[i * 4 + 1];
901     destline[i * 3 + 1] = src[i * 4 + 2];
902     destline[i * 3 + 2] = src[i * 4 + 3];
903   }
904 }
905
906 static void
907 getline_BGR (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
908     int j)
909 {
910   int i;
911   const guint8 *srcline = FRAME_GET_LINE (src, 0, j);
912   for (i = 0; i < convert->width; i++) {
913     dest[i * 4 + 0] = 0xff;
914     dest[i * 4 + 1] = srcline[i * 3 + 2];
915     dest[i * 4 + 2] = srcline[i * 3 + 1];
916     dest[i * 4 + 3] = srcline[i * 3 + 0];
917   }
918 }
919
920 static void
921 putline_BGR (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
922     int j)
923 {
924   int i;
925   guint8 *destline = FRAME_GET_LINE (dest, 0, j);
926   for (i = 0; i < convert->width; i++) {
927     destline[i * 3 + 0] = src[i * 4 + 3];
928     destline[i * 3 + 1] = src[i * 4 + 2];
929     destline[i * 3 + 2] = src[i * 4 + 1];
930   }
931 }
932
933 static void
934 getline_NV12 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
935     int j)
936 {
937   cogorc_getline_NV12 (dest,
938       FRAME_GET_LINE (src, 0, j),
939       FRAME_GET_LINE (src, 1, j >> 1), convert->width / 2);
940 }
941
942 static void
943 putline_NV12 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
944     int j)
945 {
946   cogorc_putline_NV12 (FRAME_GET_LINE (dest, 0, j),
947       FRAME_GET_LINE (dest, 1, j >> 1), src, convert->width / 2);
948 }
949
950 static void
951 getline_NV21 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
952     int j)
953 {
954   cogorc_getline_NV21 (dest,
955       FRAME_GET_LINE (src, 0, j),
956       FRAME_GET_LINE (src, 2, j >> 1), convert->width / 2);
957 }
958
959 static void
960 putline_NV21 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
961     int j)
962 {
963   cogorc_putline_NV21 (FRAME_GET_LINE (dest, 0, j),
964       FRAME_GET_LINE (dest, 2, j >> 1), src, convert->width / 2);
965 }
966
967 static void
968 getline_UYVP (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
969     int j)
970 {
971   int i;
972
973   for (i = 0; i < convert->width; i += 2) {
974     guint16 y0, y1;
975     guint16 u0;
976     guint16 v0;
977
978     u0 = (src[(i / 2) * 5 + 0] << 2) | (src[(i / 2) * 5 + 1] >> 6);
979     y0 = ((src[(i / 2) * 5 + 1] & 0x3f) << 4) | (src[(i / 2) * 5 + 2] >> 4);
980     v0 = ((src[(i / 2) * 5 + 2] & 0x0f) << 6) | (src[(i / 2) * 5 + 3] >> 2);
981     y1 = ((src[(i / 2) * 5 + 3] & 0x03) << 8) | src[(i / 2) * 5 + 4];
982
983     dest[i * 4 + 0] = 0xff;
984     dest[i * 4 + 1] = y0 >> 2;
985     dest[i * 4 + 2] = u0 >> 2;
986     dest[i * 4 + 3] = v0 >> 2;
987     dest[i * 4 + 4] = 0xff;
988     dest[i * 4 + 5] = y1 >> 2;
989     dest[i * 4 + 6] = u0 >> 2;
990     dest[i * 4 + 7] = v0 >> 2;
991   }
992 }
993
994 static void
995 putline_UYVP (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
996     int j)
997 {
998   int i;
999
1000   for (i = 0; i < convert->width; i += 2) {
1001     guint16 y0, y1;
1002     guint16 u0;
1003     guint16 v0;
1004
1005     y0 = src[4 * (i + 0) + 1];
1006     y1 = src[4 * (i + 1) + 1];
1007     u0 = (src[4 * (i + 0) + 2] + src[4 * (i + 1) + 2] + 1) >> 1;
1008     v0 = (src[4 * (i + 0) + 3] + src[4 * (i + 1) + 3] + 1) >> 1;
1009
1010     dest[(i / 2) * 5 + 0] = u0;
1011     dest[(i / 2) * 5 + 1] = y0 >> 2;
1012     dest[(i / 2) * 5 + 2] = (y0 << 6) | (v0 >> 4);
1013     dest[(i / 2) * 5 + 3] = (v0 << 4) | (y1 >> 2);
1014     dest[(i / 2) * 5 + 4] = (y1 << 2);
1015   }
1016 }
1017
1018 static void
1019 getline_A420 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
1020     int j)
1021 {
1022   cogorc_getline_A420 (dest,
1023       FRAME_GET_LINE (src, 0, j),
1024       FRAME_GET_LINE (src, 1, j >> 1),
1025       FRAME_GET_LINE (src, 2, j >> 1),
1026       FRAME_GET_LINE (src, 3, j), convert->width);
1027 }
1028
1029 static void
1030 putline_A420 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
1031     int j)
1032 {
1033   cogorc_putline_A420 (FRAME_GET_LINE (dest, 0, j),
1034       FRAME_GET_LINE (dest, 1, j >> 1),
1035       FRAME_GET_LINE (dest, 2, j >> 1),
1036       FRAME_GET_LINE (dest, 3, j), src, convert->width / 2);
1037 }
1038
1039 static void
1040 getline_RGB8P (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
1041     int j)
1042 {
1043   int i;
1044   const guint8 *srcline = FRAME_GET_LINE (src, 0, j);
1045   for (i = 0; i < convert->width; i++) {
1046     guint32 v = convert->palette[srcline[i]];
1047     dest[i * 4 + 0] = (v >> 24) & 0xff;
1048     dest[i * 4 + 1] = (v >> 16) & 0xff;
1049     dest[i * 4 + 2] = (v >> 8) & 0xff;
1050     dest[i * 4 + 3] = (v) & 0xff;
1051   }
1052 }
1053
1054 static void
1055 putline_RGB8P (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
1056     int j)
1057 {
1058   int i;
1059   guint8 *destline = FRAME_GET_LINE (dest, 0, j);
1060   /* Use our poor man's palette, taken from ffmpegcolorspace too */
1061   for (i = 0; i < convert->width; i++) {
1062     /* crude approximation for alpha ! */
1063     if (src[i * 4 + 0] < 0x80)
1064       destline[i] = 6 * 6 * 6;
1065     else
1066       destline[i] =
1067           ((((src[i * 4 + 1]) / 47) % 6) * 6 * 6 + (((src[i * 4 +
1068                           2]) / 47) % 6) * 6 + (((src[i * 4 + 3]) / 47) % 6));
1069   }
1070 }
1071
1072
1073 static void
1074 getline_YUV9 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
1075     int j)
1076 {
1077   cogorc_getline_YUV9 (dest,
1078       FRAME_GET_LINE (src, 0, j),
1079       FRAME_GET_LINE (src, 1, j >> 2),
1080       FRAME_GET_LINE (src, 2, j >> 2), convert->width / 2);
1081 }
1082
1083 static void
1084 putline_YUV9 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
1085     int j)
1086 {
1087   int i;
1088   guint8 *destY = FRAME_GET_LINE (dest, 0, j);
1089   guint8 *destU = FRAME_GET_LINE (dest, 1, j >> 2);
1090   guint8 *destV = FRAME_GET_LINE (dest, 2, j >> 2);
1091
1092   for (i = 0; i < convert->width - 3; i += 4) {
1093     destY[i] = src[i * 4 + 1];
1094     destY[i + 1] = src[i * 4 + 5];
1095     destY[i + 2] = src[i * 4 + 9];
1096     destY[i + 3] = src[i * 4 + 13];
1097     if (j % 4 == 0) {
1098       destU[i >> 2] =
1099           (src[i * 4 + 2] + src[i * 4 + 6] + src[i * 4 + 10] + src[i * 4 +
1100               14]) >> 2;
1101       destV[i >> 2] =
1102           (src[i * 4 + 3] + src[i * 4 + 7] + src[i * 4 + 11] + src[i * 4 +
1103               15]) >> 2;
1104     }
1105   }
1106
1107   if (i == convert->width - 3) {
1108     destY[i] = src[i * 4 + 1];
1109     destY[i + 1] = src[i * 4 + 5];
1110     destY[i + 2] = src[i * 4 + 9];
1111     if (j % 4 == 0) {
1112       destU[i >> 2] = (src[i * 4 + 2] + src[i * 4 + 6] + src[i * 4 + 10]) / 3;
1113       destV[i >> 2] = (src[i * 4 + 3] + src[i * 4 + 7] + src[i * 4 + 11]) / 3;
1114     }
1115   } else if (i == convert->width - 2) {
1116     destY[i] = src[i * 4 + 1];
1117     destY[i + 1] = src[i * 4 + 5];
1118     if (j % 4 == 0) {
1119       destU[i >> 2] = (src[i * 4 + 2] + src[i * 4 + 6]) >> 1;
1120       destV[i >> 2] = (src[i * 4 + 3] + src[i * 4 + 7]) >> 1;
1121     }
1122   } else if (i == convert->width - 1) {
1123     destY[i] = src[i * 4 + 1];
1124     destU[i >> 2] = src[i * 4 + 2];
1125     destV[i >> 2] = src[i * 4 + 3];
1126   }
1127 }
1128
1129 static void
1130 getline_IYU1 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
1131     int j)
1132 {
1133   int i;
1134   const guint8 *srcline = FRAME_GET_LINE (src, 0, j);
1135
1136   for (i = 0; i < convert->width - 3; i += 4) {
1137     dest[i * 4 + 0] = 0xff;
1138     dest[i * 4 + 4] = 0xff;
1139     dest[i * 4 + 8] = 0xff;
1140     dest[i * 4 + 12] = 0xff;
1141     dest[i * 4 + 1] = srcline[(i >> 2) * 6 + 1];
1142     dest[i * 4 + 5] = srcline[(i >> 2) * 6 + 2];
1143     dest[i * 4 + 9] = srcline[(i >> 2) * 6 + 4];
1144     dest[i * 4 + 13] = srcline[(i >> 2) * 6 + 5];
1145     dest[i * 4 + 2] = dest[i * 4 + 6] = dest[i * 4 + 10] = dest[i * 4 + 14] =
1146         srcline[(i >> 2) * 6 + 0];
1147     dest[i * 4 + 3] = dest[i * 4 + 7] = dest[i * 4 + 11] = dest[i * 4 + 15] =
1148         srcline[(i >> 2) * 6 + 3];
1149   }
1150
1151   if (i == convert->width - 3) {
1152     dest[i * 4 + 0] = 0xff;
1153     dest[i * 4 + 4] = 0xff;
1154     dest[i * 4 + 8] = 0xff;
1155     dest[i * 4 + 1] = srcline[(i >> 2) * 6 + 1];
1156     dest[i * 4 + 5] = srcline[(i >> 2) * 6 + 2];
1157     dest[i * 4 + 9] = srcline[(i >> 2) * 6 + 4];
1158     dest[i * 4 + 2] = dest[i * 4 + 6] = dest[i * 4 + 10] =
1159         srcline[(i >> 2) * 6 + 0];
1160     dest[i * 4 + 3] = dest[i * 4 + 7] = dest[i * 4 + 11] =
1161         srcline[(i >> 2) * 6 + 3];
1162   } else if (i == convert->width - 2) {
1163     dest[i * 4 + 0] = 0xff;
1164     dest[i * 4 + 4] = 0xff;
1165     dest[i * 4 + 1] = srcline[(i >> 2) * 6 + 1];
1166     dest[i * 4 + 5] = srcline[(i >> 2) * 6 + 2];
1167     dest[i * 4 + 2] = dest[i * 4 + 6] = srcline[(i >> 2) * 6 + 0];
1168     dest[i * 4 + 3] = dest[i * 4 + 7] = srcline[(i >> 2) * 6 + 3];
1169   } else if (i == convert->width - 1) {
1170     dest[i * 4 + 0] = 0xff;
1171     dest[i * 4 + 1] = srcline[(i >> 2) * 6 + 1];
1172     dest[i * 4 + 2] = srcline[(i >> 2) * 6 + 0];
1173     dest[i * 4 + 3] = srcline[(i >> 2) * 6 + 3];
1174   }
1175 }
1176
1177 static void
1178 putline_IYU1 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
1179     int j)
1180 {
1181   int i;
1182   guint8 *destline = FRAME_GET_LINE (dest, 0, j);
1183
1184   for (i = 0; i < convert->width - 3; i += 4) {
1185     destline[(i >> 2) * 6 + 1] = src[i * 4 + 1];
1186     destline[(i >> 2) * 6 + 2] = src[i * 4 + 5];
1187     destline[(i >> 2) * 6 + 4] = src[i * 4 + 9];
1188     destline[(i >> 2) * 6 + 5] = src[i * 4 + 13];
1189     destline[(i >> 2) * 6 + 0] =
1190         (src[i * 4 + 2] + src[i * 4 + 6] + src[i * 4 + 10] + src[i * 4 +
1191             14]) >> 2;
1192     destline[(i >> 2) * 6 + 3] =
1193         (src[i * 4 + 3] + src[i * 4 + 7] + src[i * 4 + 11] + src[i * 4 +
1194             15]) >> 2;
1195   }
1196
1197   if (i == convert->width - 3) {
1198     destline[(i >> 2) * 6 + 1] = src[i * 4 + 1];
1199     destline[(i >> 2) * 6 + 2] = src[i * 4 + 5];
1200     destline[(i >> 2) * 6 + 4] = src[i * 4 + 9];
1201     destline[(i >> 2) * 6 + 0] =
1202         (src[i * 4 + 2] + src[i * 4 + 6] + src[i * 4 + 10]) / 3;
1203     destline[(i >> 2) * 6 + 3] =
1204         (src[i * 4 + 3] + src[i * 4 + 7] + src[i * 4 + 11]) / 3;
1205   } else if (i == convert->width - 2) {
1206     destline[(i >> 2) * 6 + 1] = src[i * 4 + 1];
1207     destline[(i >> 2) * 6 + 2] = src[i * 4 + 5];
1208     destline[(i >> 2) * 6 + 0] = (src[i * 4 + 2] + src[i * 4 + 6]) >> 1;
1209     destline[(i >> 2) * 6 + 3] = (src[i * 4 + 3] + src[i * 4 + 7]) >> 1;
1210   } else if (i == convert->width - 1) {
1211     destline[(i >> 2) * 6 + 1] = src[i * 4 + 1];
1212     destline[(i >> 2) * 6 + 0] = src[i * 4 + 2];
1213     destline[(i >> 2) * 6 + 3] = src[i * 4 + 3];
1214   }
1215 }
1216
1217 static void
1218 getline_AY64 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
1219     int j)
1220 {
1221   int i;
1222   const guint16 *srcline = (const guint16 *) FRAME_GET_LINE (src, 0, j);
1223   for (i = 0; i < convert->width * 4; i++) {
1224     dest[i] = srcline[i] >> 8;
1225   }
1226 }
1227
1228 static void
1229 putline_AY64 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src,
1230     int j)
1231 {
1232   int i;
1233   guint16 *destline = (guint16 *) FRAME_GET_LINE (dest, 0, j);
1234   for (i = 0; i < convert->width * 4; i++) {
1235     destline[i] = src[i] << 8;
1236   }
1237 }
1238
1239 static void
1240 getline16_AY64 (ColorspaceConvert * convert, guint16 * dest, const guint8 * src,
1241     int j)
1242 {
1243   memcpy (dest, FRAME_GET_LINE (src, 0, j), convert->width * 8);
1244 }
1245
1246 static void
1247 putline16_AY64 (ColorspaceConvert * convert, guint8 * dest, const guint16 * src,
1248     int j)
1249 {
1250   memcpy (FRAME_GET_LINE (dest, 0, j), src, convert->width * 8);
1251 }
1252
1253 static void
1254 getline16_convert (ColorspaceConvert * convert, guint16 * dest,
1255     const guint8 * src, int j)
1256 {
1257   int i;
1258   convert->getline (convert, convert->tmpline, src, j);
1259   for (i = 0; i < convert->width * 4; i++) {
1260     dest[i] = convert->tmpline[i] << 8;
1261   }
1262 }
1263
1264 static void
1265 putline16_convert (ColorspaceConvert * convert, guint8 * dest,
1266     const guint16 * src, int j)
1267 {
1268   int i;
1269   for (i = 0; i < convert->width * 4; i++) {
1270     convert->tmpline[i] = src[i] >> 8;
1271   }
1272   convert->putline (convert, dest, convert->tmpline, j);
1273 }
1274
1275 typedef struct
1276 {
1277   GstVideoFormat format;
1278   void (*getline) (ColorspaceConvert * convert, guint8 * dest,
1279       const guint8 * src, int j);
1280   void (*putline) (ColorspaceConvert * convert, guint8 * dest,
1281       const guint8 * src, int j);
1282   void (*getline16) (ColorspaceConvert * convert, guint16 * dest,
1283       const guint8 * src, int j);
1284   void (*putline16) (ColorspaceConvert * convert, guint8 * dest,
1285       const guint16 * src, int j);
1286 } ColorspaceLine;
1287 static const ColorspaceLine lines[] = {
1288   {GST_VIDEO_FORMAT_I420, getline_I420, putline_I420},
1289   {GST_VIDEO_FORMAT_YV12, getline_YV12, putline_YV12},
1290   {GST_VIDEO_FORMAT_YUY2, getline_YUY2, putline_YUY2},
1291   {GST_VIDEO_FORMAT_UYVY, getline_UYVY, putline_UYVY},
1292   {GST_VIDEO_FORMAT_AYUV, getline_AYUV, putline_AYUV},
1293   {GST_VIDEO_FORMAT_RGBx, getline_RGBA, putline_RGBA},
1294   {GST_VIDEO_FORMAT_BGRx, getline_BGRA, putline_BGRA},
1295   {GST_VIDEO_FORMAT_xRGB, getline_AYUV, putline_AYUV},
1296   {GST_VIDEO_FORMAT_xBGR, getline_ABGR, putline_ABGR},
1297   {GST_VIDEO_FORMAT_RGBA, getline_RGBA, putline_RGBA},
1298   {GST_VIDEO_FORMAT_BGRA, getline_BGRA, putline_BGRA},
1299   {GST_VIDEO_FORMAT_ARGB, getline_AYUV, putline_AYUV},
1300   {GST_VIDEO_FORMAT_ABGR, getline_ABGR, putline_ABGR},
1301   {GST_VIDEO_FORMAT_RGB, getline_RGB, putline_RGB},
1302   {GST_VIDEO_FORMAT_BGR, getline_BGR, putline_BGR},
1303   {GST_VIDEO_FORMAT_Y41B, getline_Y41B, putline_Y41B},
1304   {GST_VIDEO_FORMAT_Y42B, getline_Y42B, putline_Y42B},
1305   {GST_VIDEO_FORMAT_YVYU, getline_YVYU, putline_YVYU},
1306   {GST_VIDEO_FORMAT_Y444, getline_Y444, putline_Y444},
1307   {GST_VIDEO_FORMAT_v210, getline_v210, putline_v210,
1308       getline16_v210, putline16_v210},
1309   {GST_VIDEO_FORMAT_v216, getline_v216, putline_v216,
1310       getline16_v216, putline16_v216},
1311   {GST_VIDEO_FORMAT_NV12, getline_NV12, putline_NV12},
1312   {GST_VIDEO_FORMAT_NV21, getline_NV21, putline_NV21},
1313   //{GST_VIDEO_FORMAT_GRAY8, getline_GRAY8, putline_GRAY8},
1314   //{GST_VIDEO_FORMAT_GRAY16_BE, getline_GRAY16_BE, putline_GRAY16_BE},
1315   //{GST_VIDEO_FORMAT_GRAY16_LE, getline_GRAY16_LE, putline_GRAY16_LE},
1316   {GST_VIDEO_FORMAT_v308, getline_v308, putline_v308},
1317   {GST_VIDEO_FORMAT_Y800, getline_Y800, putline_Y800},
1318   {GST_VIDEO_FORMAT_Y16, getline_Y16, putline_Y16},
1319   {GST_VIDEO_FORMAT_RGB16, getline_RGB16, putline_RGB16},
1320   {GST_VIDEO_FORMAT_BGR16, getline_BGR16, putline_BGR16},
1321   {GST_VIDEO_FORMAT_RGB15, getline_RGB15, putline_RGB15},
1322   {GST_VIDEO_FORMAT_BGR15, getline_BGR15, putline_BGR15},
1323   {GST_VIDEO_FORMAT_UYVP, getline_UYVP, putline_UYVP},
1324   {GST_VIDEO_FORMAT_A420, getline_A420, putline_A420}
1325   , {GST_VIDEO_FORMAT_RGB8_PALETTED, getline_RGB8P, putline_RGB8P},
1326   {GST_VIDEO_FORMAT_YUV9, getline_YUV9, putline_YUV9},
1327   {GST_VIDEO_FORMAT_YVU9, getline_YUV9, putline_YUV9},  /* alias */
1328   {GST_VIDEO_FORMAT_IYU1, getline_IYU1, putline_IYU1},
1329   {GST_VIDEO_FORMAT_ARGB64, getline_AY64, putline_AY64, getline16_AY64,
1330       putline16_AY64},
1331   {GST_VIDEO_FORMAT_AYUV64, getline_AY64, putline_AY64, getline16_AY64,
1332       putline16_AY64}
1333 };
1334
1335 static void
1336 matrix_rgb_to_yuv_bt470_6 (ColorspaceConvert * convert)
1337 {
1338   int i;
1339   int r, g, b;
1340   int y, u, v;
1341   guint8 *tmpline = convert->tmpline;
1342
1343   for (i = 0; i < convert->width; i++) {
1344     r = tmpline[i * 4 + 1];
1345     g = tmpline[i * 4 + 2];
1346     b = tmpline[i * 4 + 3];
1347
1348     y = (66 * r + 129 * g + 25 * b + 4096) >> 8;
1349     u = (-38 * r - 74 * g + 112 * b + 32768) >> 8;
1350     v = (112 * r - 94 * g - 18 * b + 32768) >> 8;
1351
1352     tmpline[i * 4 + 1] = CLAMP (y, 0, 255);
1353     tmpline[i * 4 + 2] = CLAMP (u, 0, 255);
1354     tmpline[i * 4 + 3] = CLAMP (v, 0, 255);
1355   }
1356 }
1357
1358 static void
1359 matrix_rgb_to_yuv_bt709 (ColorspaceConvert * convert)
1360 {
1361   int i;
1362   int r, g, b;
1363   int y, u, v;
1364   guint8 *tmpline = convert->tmpline;
1365
1366   for (i = 0; i < convert->width; i++) {
1367     r = tmpline[i * 4 + 1];
1368     g = tmpline[i * 4 + 2];
1369     b = tmpline[i * 4 + 3];
1370
1371     y = (47 * r + 157 * g + 16 * b + 4096) >> 8;
1372     u = (-26 * r - 87 * g + 112 * b + 32768) >> 8;
1373     v = (112 * r - 102 * g - 10 * b + 32768) >> 8;
1374
1375     tmpline[i * 4 + 1] = CLAMP (y, 0, 255);
1376     tmpline[i * 4 + 2] = CLAMP (u, 0, 255);
1377     tmpline[i * 4 + 3] = CLAMP (v, 0, 255);
1378   }
1379 }
1380
1381 static void
1382 matrix_yuv_bt470_6_to_rgb (ColorspaceConvert * convert)
1383 {
1384   int i;
1385   int r, g, b;
1386   int y, u, v;
1387   guint8 *tmpline = convert->tmpline;
1388
1389   for (i = 0; i < convert->width; i++) {
1390     y = tmpline[i * 4 + 1];
1391     u = tmpline[i * 4 + 2];
1392     v = tmpline[i * 4 + 3];
1393
1394     r = (298 * y + 409 * v - 57068) >> 8;
1395     g = (298 * y - 100 * u - 208 * v + 34707) >> 8;
1396     b = (298 * y + 516 * u - 70870) >> 8;
1397
1398     tmpline[i * 4 + 1] = CLAMP (r, 0, 255);
1399     tmpline[i * 4 + 2] = CLAMP (g, 0, 255);
1400     tmpline[i * 4 + 3] = CLAMP (b, 0, 255);
1401   }
1402 }
1403
1404 static void
1405 matrix_yuv_bt709_to_rgb (ColorspaceConvert * convert)
1406 {
1407   int i;
1408   int r, g, b;
1409   int y, u, v;
1410   guint8 *tmpline = convert->tmpline;
1411
1412   for (i = 0; i < convert->width; i++) {
1413     y = tmpline[i * 4 + 1];
1414     u = tmpline[i * 4 + 2];
1415     v = tmpline[i * 4 + 3];
1416
1417     r = (298 * y + 459 * v - 63514) >> 8;
1418     g = (298 * y - 55 * u - 136 * v + 19681) >> 8;
1419     b = (298 * y + 541 * u - 73988) >> 8;
1420
1421     tmpline[i * 4 + 1] = CLAMP (r, 0, 255);
1422     tmpline[i * 4 + 2] = CLAMP (g, 0, 255);
1423     tmpline[i * 4 + 3] = CLAMP (b, 0, 255);
1424   }
1425 }
1426
1427 static void
1428 matrix_yuv_bt709_to_yuv_bt470_6 (ColorspaceConvert * convert)
1429 {
1430   int i;
1431   int r, g, b;
1432   int y, u, v;
1433   guint8 *tmpline = convert->tmpline;
1434
1435   for (i = 0; i < convert->width; i++) {
1436     y = tmpline[i * 4 + 1];
1437     u = tmpline[i * 4 + 2];
1438     v = tmpline[i * 4 + 3];
1439
1440     r = (256 * y + 25 * u + 49 * v - 9536) >> 8;
1441     g = (253 * u - 28 * v + 3958) >> 8;
1442     b = (-19 * u + 252 * v + 2918) >> 8;
1443
1444     tmpline[i * 4 + 1] = CLAMP (r, 0, 255);
1445     tmpline[i * 4 + 2] = CLAMP (g, 0, 255);
1446     tmpline[i * 4 + 3] = CLAMP (b, 0, 255);
1447   }
1448 }
1449
1450 static void
1451 matrix_yuv_bt470_6_to_yuv_bt709 (ColorspaceConvert * convert)
1452 {
1453   int i;
1454   int r, g, b;
1455   int y, u, v;
1456   guint8 *tmpline = convert->tmpline;
1457
1458   for (i = 0; i < convert->width; i++) {
1459     y = tmpline[i * 4 + 1];
1460     u = tmpline[i * 4 + 2];
1461     v = tmpline[i * 4 + 3];
1462
1463     r = (256 * y - 30 * u - 53 * v + 10600) >> 8;
1464     g = (261 * u + 29 * v - 4367) >> 8;
1465     b = (19 * u + 262 * v - 3289) >> 8;
1466
1467     tmpline[i * 4 + 1] = CLAMP (r, 0, 255);
1468     tmpline[i * 4 + 2] = CLAMP (g, 0, 255);
1469     tmpline[i * 4 + 3] = CLAMP (b, 0, 255);
1470   }
1471 }
1472
1473 static void
1474 matrix_identity (ColorspaceConvert * convert)
1475 {
1476   /* do nothing */
1477 }
1478
1479 static void
1480 matrix16_rgb_to_yuv_bt470_6 (ColorspaceConvert * convert)
1481 {
1482   int i;
1483   int r, g, b;
1484   int y, u, v;
1485   guint16 *tmpline = convert->tmpline16;
1486
1487   for (i = 0; i < convert->width; i++) {
1488     r = tmpline[i * 4 + 1];
1489     g = tmpline[i * 4 + 2];
1490     b = tmpline[i * 4 + 3];
1491
1492     y = (66 * r + 129 * g + 25 * b + 4096 * 256) >> 8;
1493     u = (-38 * r - 74 * g + 112 * b + 32768 * 256) >> 8;
1494     v = (112 * r - 94 * g - 18 * b + 32768 * 256) >> 8;
1495
1496     tmpline[i * 4 + 1] = CLAMP (y, 0, 65535);
1497     tmpline[i * 4 + 2] = CLAMP (u, 0, 65535);
1498     tmpline[i * 4 + 3] = CLAMP (v, 0, 65535);
1499   }
1500 }
1501
1502 static void
1503 matrix16_rgb_to_yuv_bt709 (ColorspaceConvert * convert)
1504 {
1505   int i;
1506   int r, g, b;
1507   int y, u, v;
1508   guint16 *tmpline = convert->tmpline16;
1509
1510   for (i = 0; i < convert->width; i++) {
1511     r = tmpline[i * 4 + 1];
1512     g = tmpline[i * 4 + 2];
1513     b = tmpline[i * 4 + 3];
1514
1515     y = (47 * r + 157 * g + 16 * b + 4096 * 256) >> 8;
1516     u = (-26 * r - 87 * g + 112 * b + 32768 * 256) >> 8;
1517     v = (112 * r - 102 * g - 10 * b + 32768 * 256) >> 8;
1518
1519     tmpline[i * 4 + 1] = CLAMP (y, 0, 65535);
1520     tmpline[i * 4 + 2] = CLAMP (u, 0, 65535);
1521     tmpline[i * 4 + 3] = CLAMP (v, 0, 65535);
1522   }
1523 }
1524
1525 static void
1526 matrix16_yuv_bt470_6_to_rgb (ColorspaceConvert * convert)
1527 {
1528   int i;
1529   int r, g, b;
1530   int y, u, v;
1531   guint16 *tmpline = convert->tmpline16;
1532
1533   for (i = 0; i < convert->width; i++) {
1534     y = tmpline[i * 4 + 1];
1535     u = tmpline[i * 4 + 2];
1536     v = tmpline[i * 4 + 3];
1537
1538     r = (298 * y + 409 * v - 57068 * 256) >> 8;
1539     g = (298 * y - 100 * u - 208 * v + 34707 * 256) >> 8;
1540     b = (298 * y + 516 * u - 70870 * 256) >> 8;
1541
1542     tmpline[i * 4 + 1] = CLAMP (r, 0, 65535);
1543     tmpline[i * 4 + 2] = CLAMP (g, 0, 65535);
1544     tmpline[i * 4 + 3] = CLAMP (b, 0, 65535);
1545   }
1546 }
1547
1548 static void
1549 matrix16_yuv_bt709_to_rgb (ColorspaceConvert * convert)
1550 {
1551   int i;
1552   int r, g, b;
1553   int y, u, v;
1554   guint16 *tmpline = convert->tmpline16;
1555
1556   for (i = 0; i < convert->width; i++) {
1557     y = tmpline[i * 4 + 1];
1558     u = tmpline[i * 4 + 2];
1559     v = tmpline[i * 4 + 3];
1560
1561     r = (298 * y + 459 * v - 63514 * 256) >> 8;
1562     g = (298 * y - 55 * u - 136 * v + 19681 * 256) >> 8;
1563     b = (298 * y + 541 * u - 73988 * 256) >> 8;
1564
1565     tmpline[i * 4 + 1] = CLAMP (r, 0, 65535);
1566     tmpline[i * 4 + 2] = CLAMP (g, 0, 65535);
1567     tmpline[i * 4 + 3] = CLAMP (b, 0, 65535);
1568   }
1569 }
1570
1571 static void
1572 matrix16_yuv_bt709_to_yuv_bt470_6 (ColorspaceConvert * convert)
1573 {
1574   int i;
1575   int r, g, b;
1576   int y, u, v;
1577   guint16 *tmpline = convert->tmpline16;
1578
1579   for (i = 0; i < convert->width; i++) {
1580     y = tmpline[i * 4 + 1];
1581     u = tmpline[i * 4 + 2];
1582     v = tmpline[i * 4 + 3];
1583
1584     r = (256 * y + 25 * u + 49 * v - 9536 * 256) >> 8;
1585     g = (253 * u - 28 * v + 3958 * 256) >> 8;
1586     b = (-19 * u + 252 * v + 2918 * 256) >> 8;
1587
1588     tmpline[i * 4 + 1] = CLAMP (r, 0, 65535);
1589     tmpline[i * 4 + 2] = CLAMP (g, 0, 65535);
1590     tmpline[i * 4 + 3] = CLAMP (b, 0, 65535);
1591   }
1592 }
1593
1594 static void
1595 matrix16_yuv_bt470_6_to_yuv_bt709 (ColorspaceConvert * convert)
1596 {
1597   int i;
1598   int r, g, b;
1599   int y, u, v;
1600   guint16 *tmpline = convert->tmpline16;
1601
1602   for (i = 0; i < convert->width; i++) {
1603     y = tmpline[i * 4 + 1];
1604     u = tmpline[i * 4 + 2];
1605     v = tmpline[i * 4 + 3];
1606
1607     r = (256 * y - 30 * u - 53 * v + 10600 * 256) >> 8;
1608     g = (261 * u + 29 * v - 4367 * 256) >> 8;
1609     b = (19 * u + 262 * v - 3289 * 256) >> 8;
1610
1611     tmpline[i * 4 + 1] = CLAMP (r, 0, 65535);
1612     tmpline[i * 4 + 2] = CLAMP (g, 0, 65535);
1613     tmpline[i * 4 + 3] = CLAMP (b, 0, 65535);
1614   }
1615 }
1616
1617 static void
1618 matrix16_identity (ColorspaceConvert * convert)
1619 {
1620   /* do nothing */
1621 }
1622
1623
1624
1625 static void
1626 colorspace_convert_lookup_getput (ColorspaceConvert * convert)
1627 {
1628   int i;
1629
1630   convert->getline = NULL;
1631   convert->getline16 = NULL;
1632   for (i = 0; i < sizeof (lines) / sizeof (lines[0]); i++) {
1633     if (lines[i].format == convert->from_format) {
1634       convert->getline = lines[i].getline;
1635       convert->getline16 = lines[i].getline16;
1636       break;
1637     }
1638   }
1639   convert->putline = NULL;
1640   convert->putline16 = NULL;
1641   for (i = 0; i < sizeof (lines) / sizeof (lines[0]); i++) {
1642     if (lines[i].format == convert->to_format) {
1643       convert->putline = lines[i].putline;
1644       convert->putline16 = lines[i].putline16;
1645       break;
1646     }
1647   }
1648   GST_DEBUG ("get %p put %p", convert->getline, convert->putline);
1649
1650   if (convert->getline16 == NULL) {
1651     convert->getline16 = getline16_convert;
1652   }
1653   if (convert->putline16 == NULL) {
1654     convert->putline16 = putline16_convert;
1655   }
1656
1657   if (convert->from_spec == convert->to_spec) {
1658     convert->matrix = matrix_identity;
1659     convert->matrix16 = matrix16_identity;
1660   } else if (convert->from_spec == COLOR_SPEC_RGB
1661       && convert->to_spec == COLOR_SPEC_YUV_BT470_6) {
1662     convert->matrix = matrix_rgb_to_yuv_bt470_6;
1663     convert->matrix16 = matrix16_rgb_to_yuv_bt470_6;
1664   } else if (convert->from_spec == COLOR_SPEC_RGB
1665       && convert->to_spec == COLOR_SPEC_YUV_BT709) {
1666     convert->matrix = matrix_rgb_to_yuv_bt709;
1667     convert->matrix16 = matrix16_rgb_to_yuv_bt709;
1668   } else if (convert->from_spec == COLOR_SPEC_YUV_BT470_6
1669       && convert->to_spec == COLOR_SPEC_RGB) {
1670     convert->matrix = matrix_yuv_bt470_6_to_rgb;
1671     convert->matrix16 = matrix16_yuv_bt470_6_to_rgb;
1672   } else if (convert->from_spec == COLOR_SPEC_YUV_BT709
1673       && convert->to_spec == COLOR_SPEC_RGB) {
1674     convert->matrix = matrix_yuv_bt709_to_rgb;
1675     convert->matrix16 = matrix16_yuv_bt709_to_rgb;
1676   } else if (convert->from_spec == COLOR_SPEC_YUV_BT709
1677       && convert->to_spec == COLOR_SPEC_YUV_BT470_6) {
1678     convert->matrix = matrix_yuv_bt709_to_yuv_bt470_6;
1679     convert->matrix16 = matrix16_yuv_bt709_to_yuv_bt470_6;
1680   } else if (convert->from_spec == COLOR_SPEC_YUV_BT470_6
1681       && convert->to_spec == COLOR_SPEC_YUV_BT709) {
1682     convert->matrix = matrix_yuv_bt470_6_to_yuv_bt709;
1683     convert->matrix16 = matrix16_yuv_bt470_6_to_yuv_bt709;
1684   }
1685 }
1686
1687 static void
1688 colorspace_convert_generic (ColorspaceConvert * convert, guint8 * dest,
1689     const guint8 * src)
1690 {
1691   int j;
1692
1693   if (convert->getline == NULL) {
1694     GST_ERROR ("no getline");
1695     return;
1696   }
1697
1698   if (convert->putline == NULL) {
1699     GST_ERROR ("no putline");
1700     return;
1701   }
1702
1703   if (convert->use_16bit) {
1704     for (j = 0; j < convert->height; j++) {
1705       convert->getline16 (convert, convert->tmpline16, src, j);
1706       convert->matrix16 (convert);
1707       convert->dither16 (convert, j);
1708       convert->putline16 (convert, dest, convert->tmpline16, j);
1709     }
1710   } else {
1711     for (j = 0; j < convert->height; j++) {
1712       convert->getline (convert, convert->tmpline, src, j);
1713       convert->matrix (convert);
1714       convert->putline (convert, dest, convert->tmpline, j);
1715     }
1716   }
1717 }
1718
1719 static void
1720 colorspace_dither_none (ColorspaceConvert * convert, int j)
1721 {
1722 }
1723
1724 static void
1725 colorspace_dither_verterr (ColorspaceConvert * convert, int j)
1726 {
1727   int i;
1728   guint16 *tmpline = convert->tmpline16;
1729   guint16 *errline = convert->errline;
1730
1731   for (i = 0; i < 4 * convert->width; i++) {
1732     tmpline[i] += errline[i];
1733     errline[i] = tmpline[i] & 0xff;
1734   }
1735 }
1736
1737 static void
1738 colorspace_dither_halftone (ColorspaceConvert * convert, int j)
1739 {
1740   int i;
1741   guint16 *tmpline = convert->tmpline16;
1742   static guint16 halftone[8][8] = {
1743     {0, 128, 32, 160, 8, 136, 40, 168},
1744     {192, 64, 224, 96, 200, 72, 232, 104},
1745     {48, 176, 16, 144, 56, 184, 24, 152},
1746     {240, 112, 208, 80, 248, 120, 216, 88},
1747     {12, 240, 44, 172, 4, 132, 36, 164},
1748     {204, 76, 236, 108, 196, 68, 228, 100},
1749     {60, 188, 28, 156, 52, 180, 20, 148},
1750     {252, 142, 220, 92, 244, 116, 212, 84}
1751   };
1752
1753   for (i = 0; i < convert->width * 4; i++) {
1754     tmpline[i] += halftone[(i >> 2) & 7][j & 7];
1755   }
1756 }
1757
1758 /* Fast paths */
1759
1760 static void
1761 convert_I420_YUY2 (ColorspaceConvert * convert, guint8 * dest,
1762     const guint8 * src)
1763 {
1764   int i;
1765
1766   for (i = 0; i < convert->height; i += 2) {
1767     cogorc_convert_I420_YUY2 (FRAME_GET_LINE (dest, 0, i),
1768         FRAME_GET_LINE (dest, 0, i + 1),
1769         FRAME_GET_LINE (src, 0, i),
1770         FRAME_GET_LINE (src, 0, i + 1),
1771         FRAME_GET_LINE (src, 1, i >> 1),
1772         FRAME_GET_LINE (src, 2, i >> 1), (convert->width + 1) / 2);
1773   }
1774 }
1775
1776 static void
1777 convert_I420_UYVY (ColorspaceConvert * convert, guint8 * dest,
1778     const guint8 * src)
1779 {
1780   int i;
1781
1782   for (i = 0; i < convert->height; i += 2) {
1783     cogorc_convert_I420_UYVY (FRAME_GET_LINE (dest, 0, i),
1784         FRAME_GET_LINE (dest, 0, i + 1),
1785         FRAME_GET_LINE (src, 0, i),
1786         FRAME_GET_LINE (src, 0, i + 1),
1787         FRAME_GET_LINE (src, 1, i >> 1),
1788         FRAME_GET_LINE (src, 2, i >> 1), (convert->width + 1) / 2);
1789   }
1790 }
1791
1792 static void
1793 convert_I420_AYUV (ColorspaceConvert * convert, guint8 * dest,
1794     const guint8 * src)
1795 {
1796   int i;
1797
1798   for (i = 0; i < convert->height; i += 2) {
1799     cogorc_convert_I420_AYUV (FRAME_GET_LINE (dest, 0, i),
1800         FRAME_GET_LINE (dest, 0, i + 1),
1801         FRAME_GET_LINE (src, 0, i),
1802         FRAME_GET_LINE (src, 0, i + 1),
1803         FRAME_GET_LINE (src, 1, i >> 1),
1804         FRAME_GET_LINE (src, 2, i >> 1), convert->width);
1805   }
1806 }
1807
1808 static void
1809 convert_I420_Y42B (ColorspaceConvert * convert, guint8 * dest,
1810     const guint8 * src)
1811 {
1812   cogorc_memcpy_2d (FRAME_GET_LINE (dest, 0, 0), convert->dest_stride[0],
1813       FRAME_GET_LINE (src, 0, 0), convert->src_stride[0],
1814       convert->width, convert->height);
1815
1816   cogorc_planar_chroma_420_422 (FRAME_GET_LINE (dest, 1, 0),
1817       2 * convert->dest_stride[1], FRAME_GET_LINE (dest, 1, 1),
1818       2 * convert->dest_stride[1], FRAME_GET_LINE (src, 1, 0),
1819       convert->src_stride[1], (convert->width + 1) / 2, convert->height / 2);
1820
1821   cogorc_planar_chroma_420_422 (FRAME_GET_LINE (dest, 2, 0),
1822       2 * convert->dest_stride[2], FRAME_GET_LINE (dest, 2, 1),
1823       2 * convert->dest_stride[2], FRAME_GET_LINE (src, 2, 0),
1824       convert->src_stride[2], (convert->width + 1) / 2, convert->height / 2);
1825 }
1826
1827 static void
1828 convert_I420_Y444 (ColorspaceConvert * convert, guint8 * dest,
1829     const guint8 * src)
1830 {
1831   cogorc_memcpy_2d (FRAME_GET_LINE (dest, 0, 0), convert->dest_stride[0],
1832       FRAME_GET_LINE (src, 0, 0), convert->src_stride[0],
1833       convert->width, convert->height);
1834
1835   cogorc_planar_chroma_420_444 (FRAME_GET_LINE (dest, 1, 0),
1836       2 * convert->dest_stride[1], FRAME_GET_LINE (dest, 1, 1),
1837       2 * convert->dest_stride[1], FRAME_GET_LINE (src, 1, 0),
1838       convert->src_stride[1], (convert->width + 1) / 2,
1839       (convert->height + 1) / 2);
1840
1841   cogorc_planar_chroma_420_444 (FRAME_GET_LINE (dest, 2, 0),
1842       2 * convert->dest_stride[2], FRAME_GET_LINE (dest, 2, 1),
1843       2 * convert->dest_stride[2], FRAME_GET_LINE (src, 2, 0),
1844       convert->src_stride[2], (convert->width + 1) / 2,
1845       (convert->height + 1) / 2);
1846 }
1847
1848 static void
1849 convert_YUY2_I420 (ColorspaceConvert * convert, guint8 * dest,
1850     const guint8 * src)
1851 {
1852   int i;
1853
1854   for (i = 0; i < convert->height; i += 2) {
1855     cogorc_convert_YUY2_I420 (FRAME_GET_LINE (dest, 0, i),
1856         FRAME_GET_LINE (dest, 0, i + 1),
1857         FRAME_GET_LINE (dest, 1, i >> 1),
1858         FRAME_GET_LINE (dest, 2, i >> 1),
1859         FRAME_GET_LINE (src, 0, i),
1860         FRAME_GET_LINE (src, 0, i + 1), (convert->width + 1) / 2);
1861   }
1862 }
1863
1864 static void
1865 convert_YUY2_AYUV (ColorspaceConvert * convert, guint8 * dest,
1866     const guint8 * src)
1867 {
1868   cogorc_convert_YUY2_AYUV (FRAME_GET_LINE (dest, 0, 0),
1869       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
1870       convert->src_stride[0], (convert->width + 1) / 2, convert->height);
1871 }
1872
1873 static void
1874 convert_YUY2_Y42B (ColorspaceConvert * convert, guint8 * dest,
1875     const guint8 * src)
1876 {
1877   cogorc_convert_YUY2_Y42B (FRAME_GET_LINE (dest, 0, 0),
1878       convert->dest_stride[0], FRAME_GET_LINE (dest, 1, 0),
1879       convert->dest_stride[1], FRAME_GET_LINE (dest, 2, 0),
1880       convert->dest_stride[2], FRAME_GET_LINE (src, 0, 0),
1881       convert->src_stride[0], (convert->width + 1) / 2, convert->height);
1882 }
1883
1884 static void
1885 convert_YUY2_Y444 (ColorspaceConvert * convert, guint8 * dest,
1886     const guint8 * src)
1887 {
1888   cogorc_convert_YUY2_Y444 (FRAME_GET_LINE (dest, 0, 0),
1889       convert->dest_stride[0], FRAME_GET_LINE (dest, 1, 0),
1890       convert->dest_stride[1], FRAME_GET_LINE (dest, 2, 0),
1891       convert->dest_stride[2], FRAME_GET_LINE (src, 0, 0),
1892       convert->src_stride[0], (convert->width + 1) / 2, convert->height);
1893 }
1894
1895
1896 static void
1897 convert_UYVY_I420 (ColorspaceConvert * convert, guint8 * dest,
1898     const guint8 * src)
1899 {
1900   int i;
1901
1902   for (i = 0; i < convert->height; i += 2) {
1903     cogorc_convert_UYVY_I420 (FRAME_GET_LINE (dest, 0, i),
1904         FRAME_GET_LINE (dest, 0, i + 1),
1905         FRAME_GET_LINE (dest, 1, i >> 1),
1906         FRAME_GET_LINE (dest, 2, i >> 1),
1907         FRAME_GET_LINE (src, 0, i),
1908         FRAME_GET_LINE (src, 0, i + 1), (convert->width + 1) / 2);
1909   }
1910 }
1911
1912 static void
1913 convert_UYVY_AYUV (ColorspaceConvert * convert, guint8 * dest,
1914     const guint8 * src)
1915 {
1916   cogorc_convert_UYVY_AYUV (FRAME_GET_LINE (dest, 0, 0),
1917       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
1918       convert->src_stride[0], (convert->width + 1) / 2, convert->height);
1919 }
1920
1921 static void
1922 convert_UYVY_YUY2 (ColorspaceConvert * convert, guint8 * dest,
1923     const guint8 * src)
1924 {
1925   cogorc_convert_UYVY_YUY2 (FRAME_GET_LINE (dest, 0, 0),
1926       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
1927       convert->src_stride[0], (convert->width + 1) / 2, convert->height);
1928 }
1929
1930 static void
1931 convert_UYVY_Y42B (ColorspaceConvert * convert, guint8 * dest,
1932     const guint8 * src)
1933 {
1934   cogorc_convert_UYVY_Y42B (FRAME_GET_LINE (dest, 0, 0),
1935       convert->dest_stride[0], FRAME_GET_LINE (dest, 1, 0),
1936       convert->dest_stride[1], FRAME_GET_LINE (dest, 2, 0),
1937       convert->dest_stride[2], FRAME_GET_LINE (src, 0, 0),
1938       convert->src_stride[0], (convert->width + 1) / 2, convert->height);
1939 }
1940
1941 static void
1942 convert_UYVY_Y444 (ColorspaceConvert * convert, guint8 * dest,
1943     const guint8 * src)
1944 {
1945   cogorc_convert_UYVY_Y444 (FRAME_GET_LINE (dest, 0, 0),
1946       convert->dest_stride[0], FRAME_GET_LINE (dest, 1, 0),
1947       convert->dest_stride[1], FRAME_GET_LINE (dest, 2, 0),
1948       convert->dest_stride[2], FRAME_GET_LINE (src, 0, 0),
1949       convert->src_stride[0], (convert->width + 1) / 2, convert->height);
1950 }
1951
1952 static void
1953 convert_AYUV_I420 (ColorspaceConvert * convert, guint8 * dest,
1954     const guint8 * src)
1955 {
1956   cogorc_convert_AYUV_I420 (FRAME_GET_LINE (dest, 0, 0),
1957       2 * convert->dest_stride[0], FRAME_GET_LINE (dest, 0, 1),
1958       2 * convert->dest_stride[0], FRAME_GET_LINE (dest, 1, 0),
1959       convert->dest_stride[1], FRAME_GET_LINE (dest, 2, 0),
1960       convert->dest_stride[2], FRAME_GET_LINE (src, 0, 0),
1961       2 * convert->src_stride[0], FRAME_GET_LINE (src, 0, 1),
1962       2 * convert->src_stride[0], convert->width / 2, convert->height / 2);
1963 }
1964
1965 static void
1966 convert_AYUV_YUY2 (ColorspaceConvert * convert, guint8 * dest,
1967     const guint8 * src)
1968 {
1969   cogorc_convert_AYUV_YUY2 (FRAME_GET_LINE (dest, 0, 0),
1970       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
1971       convert->src_stride[0], convert->width / 2, convert->height);
1972 }
1973
1974 static void
1975 convert_AYUV_UYVY (ColorspaceConvert * convert, guint8 * dest,
1976     const guint8 * src)
1977 {
1978   cogorc_convert_AYUV_UYVY (FRAME_GET_LINE (dest, 0, 0),
1979       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
1980       convert->src_stride[0], convert->width / 2, convert->height);
1981 }
1982
1983 static void
1984 convert_AYUV_Y42B (ColorspaceConvert * convert, guint8 * dest,
1985     const guint8 * src)
1986 {
1987   cogorc_convert_AYUV_Y42B (FRAME_GET_LINE (dest, 0, 0),
1988       convert->dest_stride[0], FRAME_GET_LINE (dest, 1, 0),
1989       convert->dest_stride[1], FRAME_GET_LINE (dest, 2, 0),
1990       convert->dest_stride[2], FRAME_GET_LINE (src, 0, 0),
1991       convert->src_stride[0], (convert->width + 1) / 2, convert->height);
1992 }
1993
1994 static void
1995 convert_AYUV_Y444 (ColorspaceConvert * convert, guint8 * dest,
1996     const guint8 * src)
1997 {
1998   cogorc_convert_AYUV_Y444 (FRAME_GET_LINE (dest, 0, 0),
1999       convert->dest_stride[0], FRAME_GET_LINE (dest, 1, 0),
2000       convert->dest_stride[1], FRAME_GET_LINE (dest, 2, 0),
2001       convert->dest_stride[2], FRAME_GET_LINE (src, 0, 0),
2002       convert->src_stride[0], convert->width, convert->height);
2003 }
2004
2005 static void
2006 convert_Y42B_I420 (ColorspaceConvert * convert, guint8 * dest,
2007     const guint8 * src)
2008 {
2009   cogorc_memcpy_2d (FRAME_GET_LINE (dest, 0, 0), convert->dest_stride[0],
2010       FRAME_GET_LINE (src, 0, 0), convert->src_stride[0],
2011       convert->width, convert->height);
2012
2013   cogorc_planar_chroma_422_420 (FRAME_GET_LINE (dest, 1, 0),
2014       convert->dest_stride[1], FRAME_GET_LINE (src, 1, 0),
2015       2 * convert->src_stride[1], FRAME_GET_LINE (src, 1, 1),
2016       2 * convert->src_stride[1], (convert->width + 1) / 2,
2017       (convert->height + 1) / 2);
2018
2019   cogorc_planar_chroma_422_420 (FRAME_GET_LINE (dest, 2, 0),
2020       convert->dest_stride[2], FRAME_GET_LINE (src, 2, 0),
2021       2 * convert->src_stride[2], FRAME_GET_LINE (src, 2, 1),
2022       2 * convert->src_stride[2], (convert->width + 1) / 2,
2023       (convert->height + 1) / 2);
2024 }
2025
2026 static void
2027 convert_Y42B_Y444 (ColorspaceConvert * convert, guint8 * dest,
2028     const guint8 * src)
2029 {
2030   cogorc_memcpy_2d (FRAME_GET_LINE (dest, 0, 0), convert->dest_stride[0],
2031       FRAME_GET_LINE (src, 0, 0), convert->src_stride[0],
2032       convert->width, convert->height);
2033
2034   cogorc_planar_chroma_422_444 (FRAME_GET_LINE (dest, 1, 0),
2035       convert->dest_stride[1], FRAME_GET_LINE (src, 1, 0),
2036       convert->src_stride[1], (convert->width + 1) / 2, convert->height);
2037
2038   cogorc_planar_chroma_422_444 (FRAME_GET_LINE (dest, 2, 0),
2039       convert->dest_stride[2], FRAME_GET_LINE (src, 2, 0),
2040       convert->src_stride[2], (convert->width + 1) / 2, convert->height);
2041 }
2042
2043 static void
2044 convert_Y42B_YUY2 (ColorspaceConvert * convert, guint8 * dest,
2045     const guint8 * src)
2046 {
2047   cogorc_convert_Y42B_YUY2 (FRAME_GET_LINE (dest, 0, 0),
2048       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
2049       convert->src_stride[0], FRAME_GET_LINE (src, 1, 0),
2050       convert->src_stride[1], FRAME_GET_LINE (src, 2, 0),
2051       convert->src_stride[2], (convert->width + 1) / 2, convert->height);
2052 }
2053
2054 static void
2055 convert_Y42B_UYVY (ColorspaceConvert * convert, guint8 * dest,
2056     const guint8 * src)
2057 {
2058   cogorc_convert_Y42B_UYVY (FRAME_GET_LINE (dest, 0, 0),
2059       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
2060       convert->src_stride[0], FRAME_GET_LINE (src, 1, 0),
2061       convert->src_stride[1], FRAME_GET_LINE (src, 2, 0),
2062       convert->src_stride[2], (convert->width + 1) / 2, convert->height);
2063 }
2064
2065 static void
2066 convert_Y42B_AYUV (ColorspaceConvert * convert, guint8 * dest,
2067     const guint8 * src)
2068 {
2069   cogorc_convert_Y42B_AYUV (FRAME_GET_LINE (dest, 0, 0),
2070       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
2071       convert->src_stride[0], FRAME_GET_LINE (src, 1, 0),
2072       convert->src_stride[1], FRAME_GET_LINE (src, 2, 0),
2073       convert->src_stride[2], (convert->width) / 2, convert->height);
2074 }
2075
2076 static void
2077 convert_Y444_I420 (ColorspaceConvert * convert, guint8 * dest,
2078     const guint8 * src)
2079 {
2080   cogorc_memcpy_2d (FRAME_GET_LINE (dest, 0, 0), convert->dest_stride[0],
2081       FRAME_GET_LINE (src, 0, 0), convert->src_stride[0],
2082       convert->width, convert->height);
2083
2084   cogorc_planar_chroma_444_420 (FRAME_GET_LINE (dest, 1, 0),
2085       convert->dest_stride[1], FRAME_GET_LINE (src, 1, 0),
2086       2 * convert->src_stride[1], FRAME_GET_LINE (src, 1, 1),
2087       2 * convert->src_stride[1], (convert->width + 1) / 2,
2088       (convert->height + 1) / 2);
2089
2090   cogorc_planar_chroma_444_420 (FRAME_GET_LINE (dest, 2, 0),
2091       convert->dest_stride[2], FRAME_GET_LINE (src, 2, 0),
2092       2 * convert->src_stride[2], FRAME_GET_LINE (src, 2, 1),
2093       2 * convert->src_stride[2], (convert->width + 1) / 2,
2094       (convert->height + 1) / 2);
2095 }
2096
2097 static void
2098 convert_Y444_Y42B (ColorspaceConvert * convert, guint8 * dest,
2099     const guint8 * src)
2100 {
2101   cogorc_memcpy_2d (FRAME_GET_LINE (dest, 0, 0), convert->dest_stride[0],
2102       FRAME_GET_LINE (src, 0, 0), convert->src_stride[0],
2103       convert->width, convert->height);
2104
2105   cogorc_planar_chroma_444_422 (FRAME_GET_LINE (dest, 1, 0),
2106       convert->dest_stride[1], FRAME_GET_LINE (src, 1, 0),
2107       convert->src_stride[1], (convert->width + 1) / 2, convert->height);
2108
2109   cogorc_planar_chroma_444_422 (FRAME_GET_LINE (dest, 2, 0),
2110       convert->dest_stride[2], FRAME_GET_LINE (src, 2, 0),
2111       convert->src_stride[2], (convert->width + 1) / 2, convert->height);
2112 }
2113
2114 static void
2115 convert_Y444_YUY2 (ColorspaceConvert * convert, guint8 * dest,
2116     const guint8 * src)
2117 {
2118   cogorc_convert_Y444_YUY2 (FRAME_GET_LINE (dest, 0, 0),
2119       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
2120       convert->src_stride[0], FRAME_GET_LINE (src, 1, 0),
2121       convert->src_stride[1], FRAME_GET_LINE (src, 2, 0),
2122       convert->src_stride[2], (convert->width + 1) / 2, convert->height);
2123 }
2124
2125 static void
2126 convert_Y444_UYVY (ColorspaceConvert * convert, guint8 * dest,
2127     const guint8 * src)
2128 {
2129   cogorc_convert_Y444_UYVY (FRAME_GET_LINE (dest, 0, 0),
2130       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
2131       convert->src_stride[0], FRAME_GET_LINE (src, 1, 0),
2132       convert->src_stride[1], FRAME_GET_LINE (src, 2, 0),
2133       convert->src_stride[2], (convert->width + 1) / 2, convert->height);
2134 }
2135
2136 static void
2137 convert_Y444_AYUV (ColorspaceConvert * convert, guint8 * dest,
2138     const guint8 * src)
2139 {
2140   cogorc_convert_Y444_AYUV (FRAME_GET_LINE (dest, 0, 0),
2141       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
2142       convert->src_stride[0], FRAME_GET_LINE (src, 1, 0),
2143       convert->src_stride[1], FRAME_GET_LINE (src, 2, 0),
2144       convert->src_stride[2], convert->width, convert->height);
2145 }
2146
2147 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
2148 static void
2149 convert_AYUV_ARGB (ColorspaceConvert * convert, guint8 * dest,
2150     const guint8 * src)
2151 {
2152   cogorc_convert_AYUV_ARGB (FRAME_GET_LINE (dest, 0, 0),
2153       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
2154       convert->src_stride[0], convert->width, convert->height);
2155 }
2156
2157 static void
2158 convert_AYUV_BGRA (ColorspaceConvert * convert, guint8 * dest,
2159     const guint8 * src)
2160 {
2161   cogorc_convert_AYUV_BGRA (FRAME_GET_LINE (dest, 0, 0),
2162       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
2163       convert->src_stride[0], convert->width, convert->height);
2164 }
2165
2166 static void
2167 convert_AYUV_ABGR (ColorspaceConvert * convert, guint8 * dest,
2168     const guint8 * src)
2169 {
2170   cogorc_convert_AYUV_ABGR (FRAME_GET_LINE (dest, 0, 0),
2171       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
2172       convert->src_stride[0], convert->width, convert->height);
2173 }
2174
2175 static void
2176 convert_AYUV_RGBA (ColorspaceConvert * convert, guint8 * dest,
2177     const guint8 * src)
2178 {
2179   cogorc_convert_AYUV_RGBA (FRAME_GET_LINE (dest, 0, 0),
2180       convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0),
2181       convert->src_stride[0], convert->width, convert->height);
2182 }
2183
2184 static void
2185 convert_I420_BGRA (ColorspaceConvert * convert, guint8 * dest,
2186     const guint8 * src)
2187 {
2188   int i;
2189   int quality = 0;
2190
2191   if (quality > 3) {
2192     for (i = 0; i < convert->height; i++) {
2193       if (i & 1) {
2194         cogorc_convert_I420_BGRA_avg (FRAME_GET_LINE (dest, 0, i),
2195             FRAME_GET_LINE (src, 0, i),
2196             FRAME_GET_LINE (src, 1, i >> 1),
2197             FRAME_GET_LINE (src, 1, (i >> 1) + 1),
2198             FRAME_GET_LINE (src, 2, i >> 1),
2199             FRAME_GET_LINE (src, 2, (i >> 1) + 1), convert->width);
2200       } else {
2201         cogorc_convert_I420_BGRA (FRAME_GET_LINE (dest, 0, i),
2202             FRAME_GET_LINE (src, 0, i),
2203             FRAME_GET_LINE (src, 1, i >> 1),
2204             FRAME_GET_LINE (src, 2, i >> 1), convert->width);
2205       }
2206     }
2207   } else {
2208     for (i = 0; i < convert->height; i++) {
2209       cogorc_convert_I420_BGRA (FRAME_GET_LINE (dest, 0, i),
2210           FRAME_GET_LINE (src, 0, i),
2211           FRAME_GET_LINE (src, 1, i >> 1),
2212           FRAME_GET_LINE (src, 2, i >> 1), convert->width);
2213     }
2214   }
2215 }
2216 #endif
2217
2218
2219
2220 /* Fast paths */
2221
2222 typedef struct
2223 {
2224   GstVideoFormat from_format;
2225   ColorSpaceColorSpec from_spec;
2226   GstVideoFormat to_format;
2227   ColorSpaceColorSpec to_spec;
2228   gboolean keeps_color_spec;
2229   void (*convert) (ColorspaceConvert * convert, guint8 * dest,
2230       const guint8 * src);
2231 } ColorspaceTransform;
2232 static const ColorspaceTransform transforms[] = {
2233   {GST_VIDEO_FORMAT_I420, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_YUY2,
2234       COLOR_SPEC_NONE, TRUE, convert_I420_YUY2},
2235   {GST_VIDEO_FORMAT_I420, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_UYVY,
2236       COLOR_SPEC_NONE, TRUE, convert_I420_UYVY},
2237   {GST_VIDEO_FORMAT_I420, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_AYUV,
2238       COLOR_SPEC_NONE, TRUE, convert_I420_AYUV},
2239   {GST_VIDEO_FORMAT_I420, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_Y42B,
2240       COLOR_SPEC_NONE, TRUE, convert_I420_Y42B},
2241   {GST_VIDEO_FORMAT_I420, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_Y444,
2242       COLOR_SPEC_NONE, TRUE, convert_I420_Y444},
2243
2244   {GST_VIDEO_FORMAT_YUY2, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_I420,
2245       COLOR_SPEC_NONE, TRUE, convert_YUY2_I420},
2246   {GST_VIDEO_FORMAT_YUY2, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_UYVY, COLOR_SPEC_NONE, TRUE, convert_UYVY_YUY2},    /* alias */
2247   {GST_VIDEO_FORMAT_YUY2, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_AYUV,
2248       COLOR_SPEC_NONE, TRUE, convert_YUY2_AYUV},
2249   {GST_VIDEO_FORMAT_YUY2, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_Y42B,
2250       COLOR_SPEC_NONE, TRUE, convert_YUY2_Y42B},
2251   {GST_VIDEO_FORMAT_YUY2, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_Y444,
2252       COLOR_SPEC_NONE, TRUE, convert_YUY2_Y444},
2253
2254   {GST_VIDEO_FORMAT_UYVY, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_I420,
2255       COLOR_SPEC_NONE, TRUE, convert_UYVY_I420},
2256   {GST_VIDEO_FORMAT_UYVY, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_YUY2,
2257       COLOR_SPEC_NONE, TRUE, convert_UYVY_YUY2},
2258   {GST_VIDEO_FORMAT_UYVY, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_AYUV,
2259       COLOR_SPEC_NONE, TRUE, convert_UYVY_AYUV},
2260   {GST_VIDEO_FORMAT_UYVY, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_Y42B,
2261       COLOR_SPEC_NONE, TRUE, convert_UYVY_Y42B},
2262   {GST_VIDEO_FORMAT_UYVY, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_Y444,
2263       COLOR_SPEC_NONE, TRUE, convert_UYVY_Y444},
2264
2265   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_I420,
2266       COLOR_SPEC_NONE, TRUE, convert_AYUV_I420},
2267   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_YUY2,
2268       COLOR_SPEC_NONE, TRUE, convert_AYUV_YUY2},
2269   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_UYVY,
2270       COLOR_SPEC_NONE, TRUE, convert_AYUV_UYVY},
2271   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_Y42B,
2272       COLOR_SPEC_NONE, TRUE, convert_AYUV_Y42B},
2273   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_Y444,
2274       COLOR_SPEC_NONE, TRUE, convert_AYUV_Y444},
2275
2276   {GST_VIDEO_FORMAT_Y42B, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_I420,
2277       COLOR_SPEC_NONE, TRUE, convert_Y42B_I420},
2278   {GST_VIDEO_FORMAT_Y42B, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_YUY2,
2279       COLOR_SPEC_NONE, TRUE, convert_Y42B_YUY2},
2280   {GST_VIDEO_FORMAT_Y42B, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_UYVY,
2281       COLOR_SPEC_NONE, TRUE, convert_Y42B_UYVY},
2282   {GST_VIDEO_FORMAT_Y42B, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_AYUV,
2283       COLOR_SPEC_NONE, TRUE, convert_Y42B_AYUV},
2284   {GST_VIDEO_FORMAT_Y42B, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_Y444,
2285       COLOR_SPEC_NONE, TRUE, convert_Y42B_Y444},
2286
2287   {GST_VIDEO_FORMAT_Y444, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_I420,
2288       COLOR_SPEC_NONE, TRUE, convert_Y444_I420},
2289   {GST_VIDEO_FORMAT_Y444, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_YUY2,
2290       COLOR_SPEC_NONE, TRUE, convert_Y444_YUY2},
2291   {GST_VIDEO_FORMAT_Y444, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_UYVY,
2292       COLOR_SPEC_NONE, TRUE, convert_Y444_UYVY},
2293   {GST_VIDEO_FORMAT_Y444, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_AYUV,
2294       COLOR_SPEC_NONE, TRUE, convert_Y444_AYUV},
2295   {GST_VIDEO_FORMAT_Y444, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_Y42B,
2296       COLOR_SPEC_NONE, TRUE, convert_Y444_Y42B},
2297
2298 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
2299   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_YUV_BT470_6, GST_VIDEO_FORMAT_ARGB,
2300       COLOR_SPEC_RGB, FALSE, convert_AYUV_ARGB},
2301   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_YUV_BT470_6, GST_VIDEO_FORMAT_BGRA,
2302       COLOR_SPEC_RGB, FALSE, convert_AYUV_BGRA},
2303   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_YUV_BT470_6, GST_VIDEO_FORMAT_xRGB, COLOR_SPEC_RGB, FALSE, convert_AYUV_ARGB},     /* alias */
2304   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_YUV_BT470_6, GST_VIDEO_FORMAT_BGRx, COLOR_SPEC_RGB, FALSE, convert_AYUV_BGRA},     /* alias */
2305   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_YUV_BT470_6, GST_VIDEO_FORMAT_ABGR,
2306       COLOR_SPEC_RGB, FALSE, convert_AYUV_ABGR},
2307   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_YUV_BT470_6, GST_VIDEO_FORMAT_RGBA,
2308       COLOR_SPEC_RGB, FALSE, convert_AYUV_RGBA},
2309   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_YUV_BT470_6, GST_VIDEO_FORMAT_xBGR, COLOR_SPEC_RGB, FALSE, convert_AYUV_ABGR},     /* alias */
2310   {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_YUV_BT470_6, GST_VIDEO_FORMAT_RGBx, COLOR_SPEC_RGB, FALSE, convert_AYUV_RGBA},     /* alias */
2311
2312   {GST_VIDEO_FORMAT_I420, COLOR_SPEC_YUV_BT470_6, GST_VIDEO_FORMAT_BGRA,
2313       COLOR_SPEC_RGB, FALSE, convert_I420_BGRA},
2314 #endif
2315 };
2316
2317 static void
2318 colorspace_convert_lookup_fastpath (ColorspaceConvert * convert)
2319 {
2320   int i;
2321
2322   for (i = 0; i < sizeof (transforms) / sizeof (transforms[0]); i++) {
2323     if (transforms[i].to_format == convert->to_format &&
2324         transforms[i].from_format == convert->from_format &&
2325         (transforms[i].keeps_color_spec ||
2326             (transforms[i].from_spec == convert->from_spec &&
2327                 transforms[i].to_spec == convert->to_spec))) {
2328       convert->convert = transforms[i].convert;
2329       return;
2330     }
2331   }
2332 }