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