audiotestsrc: fix rounding errors that might cause segments to be one sample too...
[platform/upstream/gstreamer.git] / gst / videoconvert / videoconvert.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., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "videoconvert.h"
26
27 #include <glib.h>
28 #include <string.h>
29 #include <math.h>
30
31 #include "gstvideoconvertorc.h"
32
33
34 static void videoconvert_convert_generic (VideoConvert * convert,
35     GstVideoFrame * dest, const GstVideoFrame * src);
36 static void videoconvert_convert_matrix (VideoConvert * convert,
37     guint8 * pixels);
38 static void videoconvert_convert_matrix16 (VideoConvert * convert,
39     guint16 * pixels);
40 static gboolean videoconvert_convert_lookup_fastpath (VideoConvert * convert);
41 static gboolean videoconvert_convert_compute_matrix (VideoConvert * convert);
42 static void videoconvert_dither_verterr (VideoConvert * convert,
43     guint16 * pixels, int j);
44 static void videoconvert_dither_halftone (VideoConvert * convert,
45     guint16 * pixels, int j);
46
47
48 VideoConvert *
49 videoconvert_convert_new (GstVideoInfo * in_info, GstVideoInfo * out_info)
50 {
51   VideoConvert *convert;
52   int width;
53
54   convert = g_malloc0 (sizeof (VideoConvert));
55
56   convert->in_info = *in_info;
57   convert->out_info = *out_info;
58   convert->dither16 = NULL;
59
60   if (!videoconvert_convert_lookup_fastpath (convert)) {
61     convert->convert = videoconvert_convert_generic;
62     if (!videoconvert_convert_compute_matrix (convert))
63       goto no_convert;
64   }
65
66   convert->width = GST_VIDEO_INFO_WIDTH (in_info);
67   convert->height = GST_VIDEO_INFO_HEIGHT (in_info);
68
69   width = convert->width;
70
71   convert->tmpline = g_malloc (sizeof (guint8) * (width + 8) * 4);
72   convert->tmpline16 = g_malloc (sizeof (guint16) * (width + 8) * 4);
73   convert->errline = g_malloc0 (sizeof (guint16) * width * 4);
74
75   return convert;
76
77   /* ERRORS */
78 no_convert:
79   {
80     videoconvert_convert_free (convert);
81     return NULL;
82   }
83 }
84
85 void
86 videoconvert_convert_free (VideoConvert * convert)
87 {
88   g_free (convert->tmpline);
89   g_free (convert->tmpline16);
90   g_free (convert->errline);
91
92   g_free (convert);
93 }
94
95 void
96 videoconvert_convert_set_dither (VideoConvert * convert, int type)
97 {
98   switch (type) {
99     case 0:
100     default:
101       convert->dither16 = NULL;
102       break;
103     case 1:
104       convert->dither16 = videoconvert_dither_verterr;
105       break;
106     case 2:
107       convert->dither16 = videoconvert_dither_halftone;
108       break;
109   }
110 }
111
112 void
113 videoconvert_convert_convert (VideoConvert * convert,
114     GstVideoFrame * dest, const GstVideoFrame * src)
115 {
116   convert->convert (convert, dest, src);
117 }
118
119 #define SCALE    (8)
120 #define SCALE_F  ((float) (1 << SCALE))
121
122 static void
123 videoconvert_convert_matrix (VideoConvert * convert, guint8 * pixels)
124 {
125   int i;
126   int r, g, b;
127   int y, u, v;
128
129   for (i = 0; i < convert->width; i++) {
130     r = pixels[i * 4 + 1];
131     g = pixels[i * 4 + 2];
132     b = pixels[i * 4 + 3];
133
134     y = (convert->cmatrix[0][0] * r + convert->cmatrix[0][1] * g +
135         convert->cmatrix[0][2] * b + convert->cmatrix[0][3]) >> SCALE;
136     u = (convert->cmatrix[1][0] * r + convert->cmatrix[1][1] * g +
137         convert->cmatrix[1][2] * b + convert->cmatrix[1][3]) >> SCALE;
138     v = (convert->cmatrix[2][0] * r + convert->cmatrix[2][1] * g +
139         convert->cmatrix[2][2] * b + convert->cmatrix[2][3]) >> SCALE;
140
141     pixels[i * 4 + 1] = CLAMP (y, 0, 255);
142     pixels[i * 4 + 2] = CLAMP (u, 0, 255);
143     pixels[i * 4 + 3] = CLAMP (v, 0, 255);
144   }
145 }
146
147 static void
148 videoconvert_convert_matrix16 (VideoConvert * convert, guint16 * pixels)
149 {
150   int i;
151   int r, g, b;
152   int y, u, v;
153
154   for (i = 0; i < convert->width; i++) {
155     r = pixels[i * 4 + 1];
156     g = pixels[i * 4 + 2];
157     b = pixels[i * 4 + 3];
158
159     y = (convert->cmatrix[0][0] * r + convert->cmatrix[0][1] * g +
160         convert->cmatrix[0][2] * b + convert->cmatrix[0][3]) >> SCALE;
161     u = (convert->cmatrix[1][0] * r + convert->cmatrix[1][1] * g +
162         convert->cmatrix[1][2] * b + convert->cmatrix[1][3]) >> SCALE;
163     v = (convert->cmatrix[2][0] * r + convert->cmatrix[2][1] * g +
164         convert->cmatrix[2][2] * b + convert->cmatrix[2][3]) >> SCALE;
165
166     pixels[i * 4 + 1] = CLAMP (y, 0, 65535);
167     pixels[i * 4 + 2] = CLAMP (u, 0, 65535);
168     pixels[i * 4 + 3] = CLAMP (v, 0, 65535);
169   }
170 }
171
172 static gboolean
173 get_Kr_Kb (GstVideoColorMatrix matrix, gdouble * Kr, gdouble * Kb)
174 {
175   gboolean res = TRUE;
176
177   switch (matrix) {
178       /* RGB */
179     default:
180     case GST_VIDEO_COLOR_MATRIX_RGB:
181       res = FALSE;
182       break;
183       /* YUV */
184     case GST_VIDEO_COLOR_MATRIX_FCC:
185       *Kr = 0.30;
186       *Kb = 0.11;
187       break;
188     case GST_VIDEO_COLOR_MATRIX_BT709:
189       *Kr = 0.2126;
190       *Kb = 0.0722;
191       break;
192     case GST_VIDEO_COLOR_MATRIX_BT601:
193       *Kr = 0.2990;
194       *Kb = 0.1140;
195       break;
196     case GST_VIDEO_COLOR_MATRIX_SMPTE240M:
197       *Kr = 0.212;
198       *Kb = 0.087;
199       break;
200   }
201   GST_DEBUG ("matrix: %d, Kr %f, Kb %f", matrix, *Kr, *Kb);
202   return res;
203 }
204
205 static gboolean
206 videoconvert_convert_compute_matrix (VideoConvert * convert)
207 {
208   GstVideoInfo *in_info, *out_info;
209   ColorMatrix dst;
210   gint i, j;
211   const GstVideoFormatInfo *sfinfo, *dfinfo;
212   const GstVideoFormatInfo *suinfo, *duinfo;
213   gint offset[4], scale[4];
214   gdouble Kr = 0, Kb = 0;
215
216   in_info = &convert->in_info;
217   out_info = &convert->out_info;
218
219   sfinfo = in_info->finfo;
220   dfinfo = out_info->finfo;
221
222   if (sfinfo->unpack_func == NULL)
223     goto no_unpack_func;
224
225   if (dfinfo->pack_func == NULL)
226     goto no_pack_func;
227
228   suinfo = gst_video_format_get_info (sfinfo->unpack_format);
229   duinfo = gst_video_format_get_info (dfinfo->unpack_format);
230
231   convert->in_bits = GST_VIDEO_FORMAT_INFO_DEPTH (suinfo, 0);
232   convert->out_bits = GST_VIDEO_FORMAT_INFO_DEPTH (duinfo, 0);
233
234   GST_DEBUG ("in bits %d, out bits %d", convert->in_bits, convert->out_bits);
235
236   if (in_info->colorimetry.range == out_info->colorimetry.range &&
237       in_info->colorimetry.matrix == out_info->colorimetry.matrix) {
238     GST_DEBUG ("using identity color transform");
239     convert->matrix = NULL;
240     convert->matrix16 = NULL;
241     return TRUE;
242   }
243
244   /* calculate intermediate format for the matrix. When unpacking, we expand
245    * input to 16 when one of the inputs is 16 bits */
246   if (convert->in_bits == 16 || convert->out_bits == 16) {
247     if (GST_VIDEO_FORMAT_INFO_IS_RGB (suinfo))
248       suinfo = gst_video_format_get_info (GST_VIDEO_FORMAT_ARGB64);
249     else
250       suinfo = gst_video_format_get_info (GST_VIDEO_FORMAT_AYUV64);
251
252     if (GST_VIDEO_FORMAT_INFO_IS_RGB (duinfo))
253       duinfo = gst_video_format_get_info (GST_VIDEO_FORMAT_ARGB64);
254     else
255       duinfo = gst_video_format_get_info (GST_VIDEO_FORMAT_AYUV64);
256   }
257
258   color_matrix_set_identity (&dst);
259
260   /* 1, bring color components to [0..1.0] range */
261   gst_video_color_range_offsets (in_info->colorimetry.range, suinfo, offset,
262       scale);
263   color_matrix_offset_components (&dst, -offset[0], -offset[1], -offset[2]);
264
265   color_matrix_scale_components (&dst, 1 / ((float) scale[0]),
266       1 / ((float) scale[1]), 1 / ((float) scale[2]));
267
268   /* 2. bring components to R'G'B' space */
269   if (get_Kr_Kb (in_info->colorimetry.matrix, &Kr, &Kb))
270     color_matrix_YCbCr_to_RGB (&dst, Kr, Kb);
271
272   /* 3. inverse transfer function. R'G'B' to linear RGB */
273
274   /* 4. from RGB to XYZ using the primaries */
275
276   /* 5. from XYZ to RGB using the primaries */
277
278   /* 6. transfer function. linear RGB to R'G'B' */
279
280   /* 7. bring components to YCbCr space */
281   if (get_Kr_Kb (out_info->colorimetry.matrix, &Kr, &Kb))
282     color_matrix_RGB_to_YCbCr (&dst, Kr, Kb);
283
284   /* 8, bring color components to nominal range */
285   gst_video_color_range_offsets (out_info->colorimetry.range, duinfo, offset,
286       scale);
287   color_matrix_scale_components (&dst, (float) scale[0], (float) scale[1],
288       (float) scale[2]);
289
290   color_matrix_offset_components (&dst, offset[0], offset[1], offset[2]);
291
292   /* because we're doing fixed point matrix coefficients */
293   color_matrix_scale_components (&dst, SCALE_F, SCALE_F, SCALE_F);
294
295   for (i = 0; i < 4; i++)
296     for (j = 0; j < 4; j++)
297       convert->cmatrix[i][j] = rint (dst.m[i][j]);
298
299   GST_DEBUG ("[%6d %6d %6d %6d]", convert->cmatrix[0][0],
300       convert->cmatrix[0][1], convert->cmatrix[0][2], convert->cmatrix[0][3]);
301   GST_DEBUG ("[%6d %6d %6d %6d]", convert->cmatrix[1][0],
302       convert->cmatrix[1][1], convert->cmatrix[1][2], convert->cmatrix[1][3]);
303   GST_DEBUG ("[%6d %6d %6d %6d]", convert->cmatrix[2][0],
304       convert->cmatrix[2][1], convert->cmatrix[2][2], convert->cmatrix[2][3]);
305   GST_DEBUG ("[%6d %6d %6d %6d]", convert->cmatrix[3][0],
306       convert->cmatrix[3][1], convert->cmatrix[3][2], convert->cmatrix[3][3]);
307
308   convert->matrix = videoconvert_convert_matrix;
309   convert->matrix16 = videoconvert_convert_matrix16;
310
311   return TRUE;
312
313   /* ERRORS */
314 no_unpack_func:
315   {
316     GST_ERROR ("no unpack_func for format %s",
317         gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (in_info)));
318     return FALSE;
319   }
320 no_pack_func:
321   {
322     GST_ERROR ("no pack_func for format %s",
323         gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (out_info)));
324     return FALSE;
325   }
326 }
327
328 static void
329 videoconvert_dither_verterr (VideoConvert * convert, guint16 * pixels, int j)
330 {
331   int i;
332   guint16 *tmpline = convert->tmpline16;
333   guint16 *errline = convert->errline;
334   unsigned int mask = 0xff;
335
336   for (i = 0; i < 4 * convert->width; i++) {
337     int x = tmpline[i] + errline[i];
338     if (x > 65535)
339       x = 65535;
340     tmpline[i] = x;
341     errline[i] = x & mask;
342   }
343 }
344
345 static void
346 videoconvert_dither_halftone (VideoConvert * convert, guint16 * pixels, int j)
347 {
348   int i;
349   guint16 *tmpline = convert->tmpline16;
350   static guint16 halftone[8][8] = {
351     {0, 128, 32, 160, 8, 136, 40, 168},
352     {192, 64, 224, 96, 200, 72, 232, 104},
353     {48, 176, 16, 144, 56, 184, 24, 152},
354     {240, 112, 208, 80, 248, 120, 216, 88},
355     {12, 240, 44, 172, 4, 132, 36, 164},
356     {204, 76, 236, 108, 196, 68, 228, 100},
357     {60, 188, 28, 156, 52, 180, 20, 148},
358     {252, 142, 220, 92, 244, 116, 212, 84}
359   };
360
361   for (i = 0; i < convert->width * 4; i++) {
362     int x;
363     x = tmpline[i] + halftone[(i >> 2) & 7][j & 7];
364     if (x > 65535)
365       x = 65535;
366     tmpline[i] = x;
367   }
368 }
369
370 #define TO_16(x) (((x)<<8) | (x))
371
372 #define UNPACK_FRAME(frame,dest,line,width)          \
373   frame->info.finfo->unpack_func (frame->info.finfo, \
374       (GST_VIDEO_FRAME_IS_INTERLACED (frame) ?       \
375         GST_VIDEO_PACK_FLAG_INTERLACED :             \
376         GST_VIDEO_PACK_FLAG_NONE),                   \
377       dest, frame->data, frame->info.stride, 0,      \
378       line, width)
379 #define PACK_FRAME(frame,dest,line,width)            \
380   frame->info.finfo->pack_func (frame->info.finfo,   \
381       (GST_VIDEO_FRAME_IS_INTERLACED (frame) ?       \
382         GST_VIDEO_PACK_FLAG_INTERLACED :             \
383         GST_VIDEO_PACK_FLAG_NONE),                   \
384       dest, 0, frame->data, frame->info.stride,      \
385       frame->info.chroma_site, line, width);
386
387 static void
388 videoconvert_convert_generic (VideoConvert * convert, GstVideoFrame * dest,
389     const GstVideoFrame * src)
390 {
391   int i, j;
392   gint width, height;
393   guint in_bits, out_bits;
394   gconstpointer pal;
395   gsize palsize;
396
397   height = convert->height;
398   width = convert->width;
399
400   in_bits = convert->in_bits;
401   out_bits = convert->out_bits;
402
403   for (j = 0; j < height; j++) {
404     if (in_bits == 16) {
405       UNPACK_FRAME (src, convert->tmpline16, j, width);
406     } else {
407       UNPACK_FRAME (src, convert->tmpline, j, width);
408
409       if (out_bits == 16)
410         for (i = 0; i < width * 4; i++)
411           convert->tmpline16[i] = TO_16 (convert->tmpline[i]);
412     }
413
414     if (out_bits == 16 || in_bits == 16) {
415       if (convert->matrix16)
416         convert->matrix16 (convert, convert->tmpline16);
417       if (convert->dither16)
418         convert->dither16 (convert, convert->tmpline16, j);
419     } else {
420       if (convert->matrix)
421         convert->matrix (convert, convert->tmpline);
422     }
423
424     if (out_bits == 16) {
425       PACK_FRAME (dest, convert->tmpline16, j, width);
426     } else {
427       if (in_bits == 16)
428         for (i = 0; i < width * 4; i++)
429           convert->tmpline[i] = convert->tmpline16[i] >> 8;
430
431       PACK_FRAME (dest, convert->tmpline, j, width);
432     }
433   }
434   if ((pal =
435           gst_video_format_get_palette (GST_VIDEO_FRAME_FORMAT (dest),
436               &palsize))) {
437     memcpy (GST_VIDEO_FRAME_PLANE_DATA (dest, 1), pal, palsize);
438   }
439 }
440
441 #define FRAME_GET_PLANE_STRIDE(frame, plane) \
442   GST_VIDEO_FRAME_PLANE_STRIDE (frame, plane)
443 #define FRAME_GET_PLANE_LINE(frame, plane, line) \
444   (gpointer)(((guint8*)(GST_VIDEO_FRAME_PLANE_DATA (frame, plane))) + \
445       FRAME_GET_PLANE_STRIDE (frame, plane) * (line))
446
447 #define FRAME_GET_COMP_STRIDE(frame, comp) \
448   GST_VIDEO_FRAME_COMP_STRIDE (frame, comp)
449 #define FRAME_GET_COMP_LINE(frame, comp, line) \
450   (gpointer)(((guint8*)(GST_VIDEO_FRAME_COMP_DATA (frame, comp))) + \
451       FRAME_GET_COMP_STRIDE (frame, comp) * (line))
452
453 #define FRAME_GET_STRIDE(frame)      FRAME_GET_PLANE_STRIDE (frame, 0)
454 #define FRAME_GET_LINE(frame,line)   FRAME_GET_PLANE_LINE (frame, 0, line)
455
456 #define FRAME_GET_Y_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_Y, line)
457 #define FRAME_GET_U_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_U, line)
458 #define FRAME_GET_V_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_V, line)
459 #define FRAME_GET_A_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_A, line)
460
461 #define FRAME_GET_Y_STRIDE(frame)    FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_Y)
462 #define FRAME_GET_U_STRIDE(frame)    FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_U)
463 #define FRAME_GET_V_STRIDE(frame)    FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_V)
464 #define FRAME_GET_A_STRIDE(frame)    FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_A)
465
466 /* Fast paths */
467
468 #define GET_LINE_OFFSETS(interlaced,line,l1,l2) \
469     if (interlaced) {                           \
470       l1 = (line & 2 ? line - 1 : line);        \
471       l2 = l1 + 2;                              \
472     } else {                                    \
473       l1 = line;                                \
474       l2 = l1 + 1;                              \
475     }
476
477
478 static void
479 convert_I420_YUY2 (VideoConvert * convert, GstVideoFrame * dest,
480     const GstVideoFrame * src)
481 {
482   int i;
483   gint width = convert->width;
484   gint height = convert->height;
485   gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src);
486   gint l1, l2;
487
488   for (i = 0; i < GST_ROUND_DOWN_2 (height); i += 2) {
489     GET_LINE_OFFSETS (interlaced, i, l1, l2);
490
491     video_convert_orc_convert_I420_YUY2 (FRAME_GET_LINE (dest, l1),
492         FRAME_GET_LINE (dest, l2),
493         FRAME_GET_Y_LINE (src, l1),
494         FRAME_GET_Y_LINE (src, l2),
495         FRAME_GET_U_LINE (src, i >> 1),
496         FRAME_GET_V_LINE (src, i >> 1), (width + 1) / 2);
497   }
498
499   /* now handle last line */
500   if (height & 1) {
501     UNPACK_FRAME (src, convert->tmpline, height - 1, width);
502     PACK_FRAME (dest, convert->tmpline, height - 1, width);
503   }
504 }
505
506 static void
507 convert_I420_UYVY (VideoConvert * convert, GstVideoFrame * dest,
508     const GstVideoFrame * src)
509 {
510   int i;
511   gint width = convert->width;
512   gint height = convert->height;
513   gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src);
514   gint l1, l2;
515
516   for (i = 0; i < GST_ROUND_DOWN_2 (height); i += 2) {
517     GET_LINE_OFFSETS (interlaced, i, l1, l2);
518
519     video_convert_orc_convert_I420_UYVY (FRAME_GET_LINE (dest, l1),
520         FRAME_GET_LINE (dest, l2),
521         FRAME_GET_Y_LINE (src, l1),
522         FRAME_GET_Y_LINE (src, l2),
523         FRAME_GET_U_LINE (src, i >> 1),
524         FRAME_GET_V_LINE (src, i >> 1), (width + 1) / 2);
525   }
526
527   /* now handle last line */
528   if (height & 1) {
529     UNPACK_FRAME (src, convert->tmpline, height - 1, width);
530     PACK_FRAME (dest, convert->tmpline, height - 1, width);
531   }
532 }
533
534 static void
535 convert_I420_AYUV (VideoConvert * convert, GstVideoFrame * dest,
536     const GstVideoFrame * src)
537 {
538   int i;
539   gint width = convert->width;
540   gint height = convert->height;
541   gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src);
542   gint l1, l2;
543
544   for (i = 0; i < GST_ROUND_DOWN_2 (height); i += 2) {
545     GET_LINE_OFFSETS (interlaced, i, l1, l2);
546
547     video_convert_orc_convert_I420_AYUV (FRAME_GET_LINE (dest, l1),
548         FRAME_GET_LINE (dest, l2),
549         FRAME_GET_Y_LINE (src, l1),
550         FRAME_GET_Y_LINE (src, l2),
551         FRAME_GET_U_LINE (src, i >> 1), FRAME_GET_V_LINE (src, i >> 1), width);
552   }
553
554   /* now handle last line */
555   if (height & 1) {
556     UNPACK_FRAME (src, convert->tmpline, height - 1, width);
557     PACK_FRAME (dest, convert->tmpline, height - 1, width);
558   }
559 }
560
561 static void
562 convert_I420_Y42B (VideoConvert * convert, GstVideoFrame * dest,
563     const GstVideoFrame * src)
564 {
565   gint width = convert->width;
566   gint height = convert->height;
567
568   video_convert_orc_memcpy_2d (FRAME_GET_Y_LINE (dest, 0),
569       FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
570       FRAME_GET_Y_STRIDE (src), width, height);
571
572   video_convert_orc_planar_chroma_420_422 (FRAME_GET_U_LINE (dest, 0),
573       2 * FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (dest, 1),
574       2 * FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (src, 0),
575       FRAME_GET_U_STRIDE (src), (width + 1) / 2, height / 2);
576
577   video_convert_orc_planar_chroma_420_422 (FRAME_GET_V_LINE (dest, 0),
578       2 * FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (dest, 1),
579       2 * FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (src, 0),
580       FRAME_GET_V_STRIDE (src), (width + 1) / 2, height / 2);
581 }
582
583 static void
584 convert_I420_Y444 (VideoConvert * convert, GstVideoFrame * dest,
585     const GstVideoFrame * src)
586 {
587   gint width = convert->width;
588   gint height = convert->height;
589
590   video_convert_orc_memcpy_2d (FRAME_GET_Y_LINE (dest, 0),
591       FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
592       FRAME_GET_Y_STRIDE (src), width, height);
593
594   video_convert_orc_planar_chroma_420_444 (FRAME_GET_U_LINE (dest, 0),
595       2 * FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (dest, 1),
596       2 * FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (src, 0),
597       FRAME_GET_U_STRIDE (src), (width + 1) / 2, height / 2);
598
599   video_convert_orc_planar_chroma_420_444 (FRAME_GET_V_LINE (dest, 0),
600       2 * FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (dest, 1),
601       2 * FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (src, 0),
602       FRAME_GET_V_STRIDE (src), (width + 1) / 2, height / 2);
603
604   /* now handle last line */
605   if (height & 1) {
606     UNPACK_FRAME (src, convert->tmpline, height - 1, width);
607     PACK_FRAME (dest, convert->tmpline, height - 1, width);
608   }
609 }
610
611 static void
612 convert_YUY2_I420 (VideoConvert * convert, GstVideoFrame * dest,
613     const GstVideoFrame * src)
614 {
615   int i, h;
616   gint width = convert->width;
617   gint height = convert->height;
618   gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src);
619   gint l1, l2;
620
621   h = height;
622   if (width & 1)
623     h--;
624
625   for (i = 0; i < h; i += 2) {
626     GET_LINE_OFFSETS (interlaced, i, l1, l2);
627
628     video_convert_orc_convert_YUY2_I420 (FRAME_GET_Y_LINE (dest, l1),
629         FRAME_GET_Y_LINE (dest, l2),
630         FRAME_GET_U_LINE (dest, i >> 1),
631         FRAME_GET_V_LINE (dest, i >> 1),
632         FRAME_GET_LINE (src, l1), FRAME_GET_LINE (src, l2), (width + 1) / 2);
633   }
634
635   /* now handle last line */
636   if (height & 1) {
637     UNPACK_FRAME (src, convert->tmpline, height - 1, width);
638     PACK_FRAME (dest, convert->tmpline, height - 1, width);
639   }
640 }
641
642 static void
643 convert_YUY2_AYUV (VideoConvert * convert, GstVideoFrame * dest,
644     const GstVideoFrame * src)
645 {
646   gint width = convert->width;
647   gint height = convert->height;
648
649   video_convert_orc_convert_YUY2_AYUV (FRAME_GET_LINE (dest, 0),
650       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
651       FRAME_GET_STRIDE (src), (width + 1) / 2,
652       height & 1 ? height - 1 : height);
653
654   /* now handle last line */
655   if (height & 1) {
656     UNPACK_FRAME (src, convert->tmpline, height - 1, width);
657     PACK_FRAME (dest, convert->tmpline, height - 1, width);
658   }
659 }
660
661 static void
662 convert_YUY2_Y42B (VideoConvert * convert, GstVideoFrame * dest,
663     const GstVideoFrame * src)
664 {
665   gint width = convert->width;
666   gint height = convert->height;
667
668   video_convert_orc_convert_YUY2_Y42B (FRAME_GET_Y_LINE (dest, 0),
669       FRAME_GET_Y_STRIDE (dest), FRAME_GET_U_LINE (dest, 0),
670       FRAME_GET_U_STRIDE (dest), FRAME_GET_V_LINE (dest, 0),
671       FRAME_GET_V_STRIDE (dest), FRAME_GET_LINE (src, 0),
672       FRAME_GET_STRIDE (src), (width + 1) / 2, height);
673 }
674
675 static void
676 convert_YUY2_Y444 (VideoConvert * convert, GstVideoFrame * dest,
677     const GstVideoFrame * src)
678 {
679   gint width = convert->width;
680   gint height = convert->height;
681
682   video_convert_orc_convert_YUY2_Y444 (FRAME_GET_COMP_LINE (dest, 0, 0),
683       FRAME_GET_COMP_STRIDE (dest, 0), FRAME_GET_COMP_LINE (dest, 1, 0),
684       FRAME_GET_COMP_STRIDE (dest, 1), FRAME_GET_COMP_LINE (dest, 2, 0),
685       FRAME_GET_COMP_STRIDE (dest, 2), FRAME_GET_LINE (src, 0),
686       FRAME_GET_STRIDE (src), (width + 1) / 2, height);
687 }
688
689
690 static void
691 convert_UYVY_I420 (VideoConvert * convert, GstVideoFrame * dest,
692     const GstVideoFrame * src)
693 {
694   int i;
695   gint width = convert->width;
696   gint height = convert->height;
697   gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src);
698   gint l1, l2;
699
700   for (i = 0; i < GST_ROUND_DOWN_2 (height); i += 2) {
701     GET_LINE_OFFSETS (interlaced, i, l1, l2);
702
703     video_convert_orc_convert_UYVY_I420 (FRAME_GET_COMP_LINE (dest, 0, l1),
704         FRAME_GET_COMP_LINE (dest, 0, l2),
705         FRAME_GET_COMP_LINE (dest, 1, i >> 1),
706         FRAME_GET_COMP_LINE (dest, 2, i >> 1),
707         FRAME_GET_LINE (src, l1), FRAME_GET_LINE (src, l2), (width + 1) / 2);
708   }
709
710   /* now handle last line */
711   if (height & 1) {
712     UNPACK_FRAME (src, convert->tmpline, height - 1, width);
713     PACK_FRAME (dest, convert->tmpline, height - 1, width);
714   }
715 }
716
717 static void
718 convert_UYVY_AYUV (VideoConvert * convert, GstVideoFrame * dest,
719     const GstVideoFrame * src)
720 {
721   gint width = convert->width;
722   gint height = convert->height;
723
724   video_convert_orc_convert_UYVY_AYUV (FRAME_GET_LINE (dest, 0),
725       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
726       FRAME_GET_STRIDE (src), (width + 1) / 2,
727       height & 1 ? height - 1 : height);
728
729   /* now handle last line */
730   if (height & 1) {
731     UNPACK_FRAME (src, convert->tmpline, height - 1, width);
732     PACK_FRAME (dest, convert->tmpline, height - 1, width);
733   }
734 }
735
736 static void
737 convert_UYVY_YUY2 (VideoConvert * convert, GstVideoFrame * dest,
738     const GstVideoFrame * src)
739 {
740   gint width = convert->width;
741   gint height = convert->height;
742
743   video_convert_orc_convert_UYVY_YUY2 (FRAME_GET_LINE (dest, 0),
744       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
745       FRAME_GET_STRIDE (src), (width + 1) / 2, height);
746 }
747
748 static void
749 convert_UYVY_Y42B (VideoConvert * convert, GstVideoFrame * dest,
750     const GstVideoFrame * src)
751 {
752   gint width = convert->width;
753   gint height = convert->height;
754
755   video_convert_orc_convert_UYVY_Y42B (FRAME_GET_Y_LINE (dest, 0),
756       FRAME_GET_Y_STRIDE (dest), FRAME_GET_U_LINE (dest, 0),
757       FRAME_GET_U_STRIDE (dest), FRAME_GET_V_LINE (dest, 0),
758       FRAME_GET_V_STRIDE (dest), FRAME_GET_LINE (src, 0),
759       FRAME_GET_STRIDE (src), (width + 1) / 2, height);
760 }
761
762 static void
763 convert_UYVY_Y444 (VideoConvert * convert, GstVideoFrame * dest,
764     const GstVideoFrame * src)
765 {
766   gint width = convert->width;
767   gint height = convert->height;
768
769   video_convert_orc_convert_UYVY_Y444 (FRAME_GET_Y_LINE (dest, 0),
770       FRAME_GET_Y_STRIDE (dest), FRAME_GET_U_LINE (dest, 0),
771       FRAME_GET_U_STRIDE (dest), FRAME_GET_V_LINE (dest, 0),
772       FRAME_GET_V_STRIDE (dest), FRAME_GET_LINE (src, 0),
773       FRAME_GET_STRIDE (src), (width + 1) / 2, height);
774 }
775
776 static void
777 convert_AYUV_I420 (VideoConvert * convert, GstVideoFrame * dest,
778     const GstVideoFrame * src)
779 {
780   gint width = convert->width;
781   gint height = convert->height;
782
783   video_convert_orc_convert_AYUV_I420 (FRAME_GET_Y_LINE (dest, 0),
784       2 * FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (dest, 1),
785       2 * FRAME_GET_Y_STRIDE (dest), FRAME_GET_U_LINE (dest, 0),
786       FRAME_GET_U_STRIDE (dest), FRAME_GET_V_LINE (dest, 0),
787       FRAME_GET_V_STRIDE (dest), FRAME_GET_LINE (src, 0),
788       2 * FRAME_GET_STRIDE (src), FRAME_GET_LINE (src, 1),
789       2 * FRAME_GET_STRIDE (src), width / 2, height / 2);
790 }
791
792 static void
793 convert_AYUV_YUY2 (VideoConvert * convert, GstVideoFrame * dest,
794     const GstVideoFrame * src)
795 {
796   gint width = convert->width;
797   gint height = convert->height;
798
799   video_convert_orc_convert_AYUV_YUY2 (FRAME_GET_LINE (dest, 0),
800       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
801       FRAME_GET_STRIDE (src), width / 2, height);
802 }
803
804 static void
805 convert_AYUV_UYVY (VideoConvert * convert, GstVideoFrame * dest,
806     const GstVideoFrame * src)
807 {
808   gint width = convert->width;
809   gint height = convert->height;
810
811   video_convert_orc_convert_AYUV_UYVY (FRAME_GET_LINE (dest, 0),
812       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
813       FRAME_GET_STRIDE (src), width / 2, height);
814 }
815
816 static void
817 convert_AYUV_Y42B (VideoConvert * convert, GstVideoFrame * dest,
818     const GstVideoFrame * src)
819 {
820   gint width = convert->width;
821   gint height = convert->height;
822
823   video_convert_orc_convert_AYUV_Y42B (FRAME_GET_Y_LINE (dest, 0),
824       FRAME_GET_Y_STRIDE (dest), FRAME_GET_U_LINE (dest, 0),
825       FRAME_GET_U_STRIDE (dest), FRAME_GET_V_LINE (dest, 0),
826       FRAME_GET_V_STRIDE (dest), FRAME_GET_LINE (src, 0),
827       FRAME_GET_STRIDE (src), (width + 1) / 2,
828       height & 1 ? height - 1 : height);
829
830   /* now handle last line */
831   if (height & 1) {
832     UNPACK_FRAME (src, convert->tmpline, height - 1, width);
833     PACK_FRAME (dest, convert->tmpline, height - 1, width);
834   }
835 }
836
837 static void
838 convert_AYUV_Y444 (VideoConvert * convert, GstVideoFrame * dest,
839     const GstVideoFrame * src)
840 {
841   gint width = convert->width;
842   gint height = convert->height;
843
844   video_convert_orc_convert_AYUV_Y444 (FRAME_GET_Y_LINE (dest, 0),
845       FRAME_GET_Y_STRIDE (dest), FRAME_GET_U_LINE (dest, 0),
846       FRAME_GET_U_STRIDE (dest), FRAME_GET_V_LINE (dest, 0),
847       FRAME_GET_V_STRIDE (dest), FRAME_GET_LINE (src, 0),
848       FRAME_GET_STRIDE (src), width, height);
849 }
850
851 static void
852 convert_Y42B_I420 (VideoConvert * convert, GstVideoFrame * dest,
853     const GstVideoFrame * src)
854 {
855   gint width = convert->width;
856   gint height = convert->height;
857
858   video_convert_orc_memcpy_2d (FRAME_GET_Y_LINE (dest, 0),
859       FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
860       FRAME_GET_Y_STRIDE (src), width, height);
861
862   video_convert_orc_planar_chroma_422_420 (FRAME_GET_U_LINE (dest, 0),
863       FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (src, 0),
864       2 * FRAME_GET_U_STRIDE (src), FRAME_GET_U_LINE (src, 1),
865       2 * FRAME_GET_U_STRIDE (src), (width + 1) / 2, height / 2);
866
867   video_convert_orc_planar_chroma_422_420 (FRAME_GET_V_LINE (dest, 0),
868       FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (src, 0),
869       2 * FRAME_GET_V_STRIDE (src), FRAME_GET_V_LINE (src, 1),
870       2 * FRAME_GET_V_STRIDE (src), (width + 1) / 2, height / 2);
871
872   /* now handle last line */
873   if (height & 1) {
874     UNPACK_FRAME (src, convert->tmpline, height - 1, width);
875     PACK_FRAME (dest, convert->tmpline, height - 1, width);
876   }
877 }
878
879 static void
880 convert_Y42B_Y444 (VideoConvert * convert, GstVideoFrame * dest,
881     const GstVideoFrame * src)
882 {
883   gint width = convert->width;
884   gint height = convert->height;
885
886   video_convert_orc_memcpy_2d (FRAME_GET_Y_LINE (dest, 0),
887       FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
888       FRAME_GET_Y_STRIDE (src), width, height);
889
890   video_convert_orc_planar_chroma_422_444 (FRAME_GET_U_LINE (dest, 0),
891       FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (src, 0),
892       FRAME_GET_U_STRIDE (src), (width + 1) / 2, height);
893
894   video_convert_orc_planar_chroma_422_444 (FRAME_GET_V_LINE (dest, 0),
895       FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (src, 0),
896       FRAME_GET_V_STRIDE (src), (width + 1) / 2, height);
897 }
898
899 static void
900 convert_Y42B_YUY2 (VideoConvert * convert, GstVideoFrame * dest,
901     const GstVideoFrame * src)
902 {
903   gint width = convert->width;
904   gint height = convert->height;
905
906   video_convert_orc_convert_Y42B_YUY2 (FRAME_GET_LINE (dest, 0),
907       FRAME_GET_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
908       FRAME_GET_Y_STRIDE (src), FRAME_GET_U_LINE (src, 0),
909       FRAME_GET_U_STRIDE (src), FRAME_GET_V_LINE (src, 0),
910       FRAME_GET_V_STRIDE (src), (width + 1) / 2, height);
911 }
912
913 static void
914 convert_Y42B_UYVY (VideoConvert * convert, GstVideoFrame * dest,
915     const GstVideoFrame * src)
916 {
917   gint width = convert->width;
918   gint height = convert->height;
919
920   video_convert_orc_convert_Y42B_UYVY (FRAME_GET_LINE (dest, 0),
921       FRAME_GET_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
922       FRAME_GET_Y_STRIDE (src), FRAME_GET_U_LINE (src, 0),
923       FRAME_GET_U_STRIDE (src), FRAME_GET_V_LINE (src, 0),
924       FRAME_GET_V_STRIDE (src), (width + 1) / 2, height);
925 }
926
927 static void
928 convert_Y42B_AYUV (VideoConvert * convert, GstVideoFrame * dest,
929     const GstVideoFrame * src)
930 {
931   gint width = convert->width;
932   gint height = convert->height;
933
934   video_convert_orc_convert_Y42B_AYUV (FRAME_GET_LINE (dest, 0),
935       FRAME_GET_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
936       FRAME_GET_Y_STRIDE (src), FRAME_GET_U_LINE (src, 0),
937       FRAME_GET_U_STRIDE (src), FRAME_GET_V_LINE (src, 0),
938       FRAME_GET_V_STRIDE (src), (width) / 2, height);
939 }
940
941 static void
942 convert_Y444_I420 (VideoConvert * convert, GstVideoFrame * dest,
943     const GstVideoFrame * src)
944 {
945   gint width = convert->width;
946   gint height = convert->height;
947
948   video_convert_orc_memcpy_2d (FRAME_GET_Y_LINE (dest, 0),
949       FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
950       FRAME_GET_Y_STRIDE (src), width, height);
951
952   video_convert_orc_planar_chroma_444_420 (FRAME_GET_U_LINE (dest, 0),
953       FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (src, 0),
954       2 * FRAME_GET_U_STRIDE (src), FRAME_GET_U_LINE (src, 1),
955       2 * FRAME_GET_U_STRIDE (src), (width + 1) / 2, height / 2);
956
957   video_convert_orc_planar_chroma_444_420 (FRAME_GET_V_LINE (dest, 0),
958       FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (src, 0),
959       2 * FRAME_GET_V_STRIDE (src), FRAME_GET_V_LINE (src, 1),
960       2 * FRAME_GET_V_STRIDE (src), (width + 1) / 2, height / 2);
961
962   /* now handle last line */
963   if (height & 1) {
964     UNPACK_FRAME (src, convert->tmpline, height - 1, width);
965     PACK_FRAME (dest, convert->tmpline, height - 1, width);
966   }
967 }
968
969 static void
970 convert_Y444_Y42B (VideoConvert * convert, GstVideoFrame * dest,
971     const GstVideoFrame * src)
972 {
973   gint width = convert->width;
974   gint height = convert->height;
975
976   video_convert_orc_memcpy_2d (FRAME_GET_Y_LINE (dest, 0),
977       FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
978       FRAME_GET_Y_STRIDE (src), width, height);
979
980   video_convert_orc_planar_chroma_444_422 (FRAME_GET_U_LINE (dest, 0),
981       FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (src, 0),
982       FRAME_GET_U_STRIDE (src), (width + 1) / 2, height);
983
984   video_convert_orc_planar_chroma_444_422 (FRAME_GET_V_LINE (dest, 0),
985       FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (src, 0),
986       FRAME_GET_V_STRIDE (src), (width + 1) / 2, height);
987 }
988
989 static void
990 convert_Y444_YUY2 (VideoConvert * convert, GstVideoFrame * dest,
991     const GstVideoFrame * src)
992 {
993   gint width = convert->width;
994   gint height = convert->height;
995
996   video_convert_orc_convert_Y444_YUY2 (FRAME_GET_LINE (dest, 0),
997       FRAME_GET_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
998       FRAME_GET_Y_STRIDE (src), FRAME_GET_U_LINE (src, 0),
999       FRAME_GET_U_STRIDE (src), FRAME_GET_V_LINE (src, 0),
1000       FRAME_GET_V_STRIDE (src), (width + 1) / 2, height);
1001 }
1002
1003 static void
1004 convert_Y444_UYVY (VideoConvert * convert, GstVideoFrame * dest,
1005     const GstVideoFrame * src)
1006 {
1007   gint width = convert->width;
1008   gint height = convert->height;
1009
1010   video_convert_orc_convert_Y444_UYVY (FRAME_GET_LINE (dest, 0),
1011       FRAME_GET_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
1012       FRAME_GET_Y_STRIDE (src), FRAME_GET_U_LINE (src, 0),
1013       FRAME_GET_U_STRIDE (src), FRAME_GET_V_LINE (src, 0),
1014       FRAME_GET_V_STRIDE (src), (width + 1) / 2, height);
1015 }
1016
1017 static void
1018 convert_Y444_AYUV (VideoConvert * convert, GstVideoFrame * dest,
1019     const GstVideoFrame * src)
1020 {
1021   gint width = convert->width;
1022   gint height = convert->height;
1023
1024   video_convert_orc_convert_Y444_AYUV (FRAME_GET_LINE (dest, 0),
1025       FRAME_GET_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
1026       FRAME_GET_Y_STRIDE (src), FRAME_GET_U_LINE (src, 0),
1027       FRAME_GET_U_STRIDE (src), FRAME_GET_V_LINE (src, 0),
1028       FRAME_GET_V_STRIDE (src), width, height);
1029 }
1030
1031 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1032 static void
1033 convert_AYUV_ARGB (VideoConvert * convert, GstVideoFrame * dest,
1034     const GstVideoFrame * src)
1035 {
1036   gint width = convert->width;
1037   gint height = convert->height;
1038
1039   video_convert_orc_convert_AYUV_ARGB (FRAME_GET_LINE (dest, 0),
1040       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
1041       FRAME_GET_STRIDE (src), width, height);
1042 }
1043
1044 static void
1045 convert_AYUV_BGRA (VideoConvert * convert, GstVideoFrame * dest,
1046     const GstVideoFrame * src)
1047 {
1048   gint width = convert->width;
1049   gint height = convert->height;
1050
1051   video_convert_orc_convert_AYUV_BGRA (FRAME_GET_LINE (dest, 0),
1052       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
1053       FRAME_GET_STRIDE (src), width, height);
1054 }
1055
1056 static void
1057 convert_AYUV_ABGR (VideoConvert * convert, GstVideoFrame * dest,
1058     const GstVideoFrame * src)
1059 {
1060   gint width = convert->width;
1061   gint height = convert->height;
1062
1063   video_convert_orc_convert_AYUV_ABGR (FRAME_GET_LINE (dest, 0),
1064       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
1065       FRAME_GET_STRIDE (src), width, height);
1066 }
1067
1068 static void
1069 convert_AYUV_RGBA (VideoConvert * convert, GstVideoFrame * dest,
1070     const GstVideoFrame * src)
1071 {
1072   gint width = convert->width;
1073   gint height = convert->height;
1074
1075   video_convert_orc_convert_AYUV_RGBA (FRAME_GET_LINE (dest, 0),
1076       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
1077       FRAME_GET_STRIDE (src), width, height);
1078 }
1079
1080 static void
1081 convert_I420_BGRA (VideoConvert * convert, GstVideoFrame * dest,
1082     const GstVideoFrame * src)
1083 {
1084   int i;
1085   int quality = 0;
1086   gint width = convert->width;
1087   gint height = convert->height;
1088
1089   if (quality > 3) {
1090     for (i = 0; i < height; i++) {
1091       if (i & 1) {
1092         video_convert_orc_convert_I420_BGRA_avg (FRAME_GET_LINE (dest, i),
1093             FRAME_GET_Y_LINE (src, i),
1094             FRAME_GET_U_LINE (src, i >> 1),
1095             FRAME_GET_U_LINE (src, (i >> 1) + 1),
1096             FRAME_GET_V_LINE (src, i >> 1),
1097             FRAME_GET_V_LINE (src, (i >> 1) + 1), width);
1098       } else {
1099         video_convert_orc_convert_I420_BGRA (FRAME_GET_LINE (dest, i),
1100             FRAME_GET_Y_LINE (src, i),
1101             FRAME_GET_U_LINE (src, i >> 1),
1102             FRAME_GET_V_LINE (src, i >> 1), width);
1103       }
1104     }
1105   } else {
1106     for (i = 0; i < height; i++) {
1107       video_convert_orc_convert_I420_BGRA (FRAME_GET_LINE (dest, i),
1108           FRAME_GET_Y_LINE (src, i),
1109           FRAME_GET_U_LINE (src, i >> 1),
1110           FRAME_GET_V_LINE (src, i >> 1), width);
1111     }
1112   }
1113 }
1114 #endif
1115
1116
1117
1118 /* Fast paths */
1119
1120 typedef struct
1121 {
1122   GstVideoFormat in_format;
1123   GstVideoColorMatrix in_matrix;
1124   GstVideoFormat out_format;
1125   GstVideoColorMatrix out_matrix;
1126   gboolean keeps_color_matrix;
1127   gboolean keeps_interlaced;
1128   void (*convert) (VideoConvert * convert, GstVideoFrame * dest,
1129       const GstVideoFrame * src);
1130 } VideoTransform;
1131 static const VideoTransform transforms[] = {
1132   {GST_VIDEO_FORMAT_I420, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_YUY2,
1133       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_I420_YUY2},
1134   {GST_VIDEO_FORMAT_I420, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_UYVY,
1135       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_I420_UYVY},
1136   {GST_VIDEO_FORMAT_I420, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_AYUV,
1137       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_I420_AYUV},
1138   {GST_VIDEO_FORMAT_I420, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y42B,
1139       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, convert_I420_Y42B},
1140   {GST_VIDEO_FORMAT_I420, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y444,
1141       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, convert_I420_Y444},
1142
1143   {GST_VIDEO_FORMAT_YUY2, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_I420,
1144       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_YUY2_I420},
1145   {GST_VIDEO_FORMAT_YUY2, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_UYVY,
1146       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_UYVY_YUY2},   /* alias */
1147   {GST_VIDEO_FORMAT_YUY2, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_AYUV,
1148       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_YUY2_AYUV},
1149   {GST_VIDEO_FORMAT_YUY2, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y42B,
1150       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_YUY2_Y42B},
1151   {GST_VIDEO_FORMAT_YUY2, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y444,
1152       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_YUY2_Y444},
1153
1154   {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_I420,
1155       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_UYVY_I420},
1156   {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_YUY2,
1157       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_UYVY_YUY2},
1158   {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_AYUV,
1159       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_UYVY_AYUV},
1160   {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y42B,
1161       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_UYVY_Y42B},
1162   {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y444,
1163       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_UYVY_Y444},
1164
1165   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_I420,
1166       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, convert_AYUV_I420},
1167   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_YUY2,
1168       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_AYUV_YUY2},
1169   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_UYVY,
1170       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_AYUV_UYVY},
1171   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y42B,
1172       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_AYUV_Y42B},
1173   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y444,
1174       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_AYUV_Y444},
1175
1176   {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_I420,
1177       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, convert_Y42B_I420},
1178   {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_YUY2,
1179       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_Y42B_YUY2},
1180   {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_UYVY,
1181       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_Y42B_UYVY},
1182   {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_AYUV,
1183       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_Y42B_AYUV},
1184   {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y444,
1185       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_Y42B_Y444},
1186
1187   {GST_VIDEO_FORMAT_Y444, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_I420,
1188       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, convert_Y444_I420},
1189   {GST_VIDEO_FORMAT_Y444, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_YUY2,
1190       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_Y444_YUY2},
1191   {GST_VIDEO_FORMAT_Y444, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_UYVY,
1192       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_Y444_UYVY},
1193   {GST_VIDEO_FORMAT_Y444, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_AYUV,
1194       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_Y444_AYUV},
1195   {GST_VIDEO_FORMAT_Y444, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y42B,
1196       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_Y444_Y42B},
1197
1198 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1199   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_BT601, GST_VIDEO_FORMAT_ARGB,
1200       GST_VIDEO_COLOR_MATRIX_RGB, FALSE, TRUE, convert_AYUV_ARGB},
1201   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_BT601, GST_VIDEO_FORMAT_BGRA,
1202       GST_VIDEO_COLOR_MATRIX_RGB, FALSE, TRUE, convert_AYUV_BGRA},
1203   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_BT601, GST_VIDEO_FORMAT_xRGB, GST_VIDEO_COLOR_MATRIX_RGB, FALSE, TRUE, convert_AYUV_ARGB},     /* alias */
1204   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_BT601, GST_VIDEO_FORMAT_BGRx, GST_VIDEO_COLOR_MATRIX_RGB, FALSE, TRUE, convert_AYUV_BGRA},     /* alias */
1205   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_BT601, GST_VIDEO_FORMAT_ABGR,
1206       GST_VIDEO_COLOR_MATRIX_RGB, FALSE, TRUE, convert_AYUV_ABGR},
1207   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_BT601, GST_VIDEO_FORMAT_RGBA,
1208       GST_VIDEO_COLOR_MATRIX_RGB, FALSE, TRUE, convert_AYUV_RGBA},
1209   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_BT601, GST_VIDEO_FORMAT_xBGR, GST_VIDEO_COLOR_MATRIX_RGB, FALSE, TRUE, convert_AYUV_ABGR},     /* alias */
1210   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_BT601, GST_VIDEO_FORMAT_RGBx, GST_VIDEO_COLOR_MATRIX_RGB, FALSE, TRUE, convert_AYUV_RGBA},     /* alias */
1211
1212   {GST_VIDEO_FORMAT_I420, GST_VIDEO_COLOR_MATRIX_BT601, GST_VIDEO_FORMAT_BGRA,
1213       GST_VIDEO_COLOR_MATRIX_RGB, FALSE, FALSE, convert_I420_BGRA},
1214 #endif
1215 };
1216
1217 static gboolean
1218 videoconvert_convert_lookup_fastpath (VideoConvert * convert)
1219 {
1220   int i;
1221   GstVideoFormat in_format, out_format;
1222   GstVideoColorMatrix in_matrix, out_matrix;
1223   gboolean interlaced;
1224
1225   in_format = GST_VIDEO_INFO_FORMAT (&convert->in_info);
1226   out_format = GST_VIDEO_INFO_FORMAT (&convert->out_info);
1227
1228   in_matrix = convert->in_info.colorimetry.matrix;
1229   out_matrix = convert->out_info.colorimetry.matrix;
1230
1231   interlaced = GST_VIDEO_INFO_IS_INTERLACED (&convert->in_info);
1232   interlaced |= GST_VIDEO_INFO_IS_INTERLACED (&convert->out_info);
1233
1234   for (i = 0; i < sizeof (transforms) / sizeof (transforms[0]); i++) {
1235     if (transforms[i].in_format == in_format &&
1236         transforms[i].out_format == out_format &&
1237         (transforms[i].keeps_color_matrix ||
1238             (transforms[i].in_matrix == in_matrix &&
1239                 transforms[i].out_matrix == out_matrix)) &&
1240         (transforms[i].keeps_interlaced || !interlaced)) {
1241       GST_DEBUG ("using fastpath");
1242       convert->convert = transforms[i].convert;
1243       return TRUE;
1244     }
1245   }
1246   return FALSE;
1247 }