videoconvert: small cleanup
[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->tmpline8 = 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->tmpline8);
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   guint8 *tmpline8;
397   guint16 *tmpline16;
398
399   height = convert->height;
400   width = convert->width;
401
402   in_bits = convert->in_bits;
403   out_bits = convert->out_bits;
404
405   tmpline8 = convert->tmpline8;
406   tmpline16 = convert->tmpline16;
407
408   for (j = 0; j < height; j++) {
409     if (in_bits == 16) {
410       UNPACK_FRAME (src, tmpline16, j, width);
411     } else {
412       UNPACK_FRAME (src, tmpline8, j, width);
413
414       if (out_bits == 16)
415         for (i = 0; i < width * 4; i++)
416           tmpline16[i] = TO_16 (tmpline8[i]);
417     }
418
419     if (out_bits == 16 || in_bits == 16) {
420       if (convert->matrix16)
421         convert->matrix16 (convert, tmpline16);
422       if (convert->dither16)
423         convert->dither16 (convert, tmpline16, j);
424     } else {
425       if (convert->matrix)
426         convert->matrix (convert, tmpline8);
427     }
428
429     if (out_bits == 16) {
430       PACK_FRAME (dest, tmpline16, j, width);
431     } else {
432       if (in_bits == 16)
433         for (i = 0; i < width * 4; i++)
434           tmpline8[i] = tmpline16[i] >> 8;
435
436       PACK_FRAME (dest, tmpline8, j, width);
437     }
438   }
439   if ((pal =
440           gst_video_format_get_palette (GST_VIDEO_FRAME_FORMAT (dest),
441               &palsize))) {
442     memcpy (GST_VIDEO_FRAME_PLANE_DATA (dest, 1), pal, palsize);
443   }
444 }
445
446 #define FRAME_GET_PLANE_STRIDE(frame, plane) \
447   GST_VIDEO_FRAME_PLANE_STRIDE (frame, plane)
448 #define FRAME_GET_PLANE_LINE(frame, plane, line) \
449   (gpointer)(((guint8*)(GST_VIDEO_FRAME_PLANE_DATA (frame, plane))) + \
450       FRAME_GET_PLANE_STRIDE (frame, plane) * (line))
451
452 #define FRAME_GET_COMP_STRIDE(frame, comp) \
453   GST_VIDEO_FRAME_COMP_STRIDE (frame, comp)
454 #define FRAME_GET_COMP_LINE(frame, comp, line) \
455   (gpointer)(((guint8*)(GST_VIDEO_FRAME_COMP_DATA (frame, comp))) + \
456       FRAME_GET_COMP_STRIDE (frame, comp) * (line))
457
458 #define FRAME_GET_STRIDE(frame)      FRAME_GET_PLANE_STRIDE (frame, 0)
459 #define FRAME_GET_LINE(frame,line)   FRAME_GET_PLANE_LINE (frame, 0, line)
460
461 #define FRAME_GET_Y_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_Y, line)
462 #define FRAME_GET_U_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_U, line)
463 #define FRAME_GET_V_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_V, line)
464 #define FRAME_GET_A_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_A, line)
465
466 #define FRAME_GET_Y_STRIDE(frame)    FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_Y)
467 #define FRAME_GET_U_STRIDE(frame)    FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_U)
468 #define FRAME_GET_V_STRIDE(frame)    FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_V)
469 #define FRAME_GET_A_STRIDE(frame)    FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_A)
470
471 /* Fast paths */
472
473 #define GET_LINE_OFFSETS(interlaced,line,l1,l2) \
474     if (interlaced) {                           \
475       l1 = (line & 2 ? line - 1 : line);        \
476       l2 = l1 + 2;                              \
477     } else {                                    \
478       l1 = line;                                \
479       l2 = l1 + 1;                              \
480     }
481
482
483 static void
484 convert_I420_YUY2 (VideoConvert * convert, GstVideoFrame * dest,
485     const GstVideoFrame * src)
486 {
487   int i;
488   gint width = convert->width;
489   gint height = convert->height;
490   gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src);
491   gint l1, l2;
492
493   for (i = 0; i < GST_ROUND_DOWN_2 (height); i += 2) {
494     GET_LINE_OFFSETS (interlaced, i, l1, l2);
495
496     video_convert_orc_convert_I420_YUY2 (FRAME_GET_LINE (dest, l1),
497         FRAME_GET_LINE (dest, l2),
498         FRAME_GET_Y_LINE (src, l1),
499         FRAME_GET_Y_LINE (src, l2),
500         FRAME_GET_U_LINE (src, i >> 1),
501         FRAME_GET_V_LINE (src, i >> 1), (width + 1) / 2);
502   }
503
504   /* now handle last line */
505   if (height & 1) {
506     UNPACK_FRAME (src, convert->tmpline8, height - 1, width);
507     PACK_FRAME (dest, convert->tmpline8, height - 1, width);
508   }
509 }
510
511 static void
512 convert_I420_UYVY (VideoConvert * convert, GstVideoFrame * dest,
513     const GstVideoFrame * src)
514 {
515   int i;
516   gint width = convert->width;
517   gint height = convert->height;
518   gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src);
519   gint l1, l2;
520
521   for (i = 0; i < GST_ROUND_DOWN_2 (height); i += 2) {
522     GET_LINE_OFFSETS (interlaced, i, l1, l2);
523
524     video_convert_orc_convert_I420_UYVY (FRAME_GET_LINE (dest, l1),
525         FRAME_GET_LINE (dest, l2),
526         FRAME_GET_Y_LINE (src, l1),
527         FRAME_GET_Y_LINE (src, l2),
528         FRAME_GET_U_LINE (src, i >> 1),
529         FRAME_GET_V_LINE (src, i >> 1), (width + 1) / 2);
530   }
531
532   /* now handle last line */
533   if (height & 1) {
534     UNPACK_FRAME (src, convert->tmpline8, height - 1, width);
535     PACK_FRAME (dest, convert->tmpline8, height - 1, width);
536   }
537 }
538
539 static void
540 convert_I420_AYUV (VideoConvert * convert, GstVideoFrame * dest,
541     const GstVideoFrame * src)
542 {
543   int i;
544   gint width = convert->width;
545   gint height = convert->height;
546   gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src);
547   gint l1, l2;
548
549   for (i = 0; i < GST_ROUND_DOWN_2 (height); i += 2) {
550     GET_LINE_OFFSETS (interlaced, i, l1, l2);
551
552     video_convert_orc_convert_I420_AYUV (FRAME_GET_LINE (dest, l1),
553         FRAME_GET_LINE (dest, l2),
554         FRAME_GET_Y_LINE (src, l1),
555         FRAME_GET_Y_LINE (src, l2),
556         FRAME_GET_U_LINE (src, i >> 1), FRAME_GET_V_LINE (src, i >> 1), width);
557   }
558
559   /* now handle last line */
560   if (height & 1) {
561     UNPACK_FRAME (src, convert->tmpline8, height - 1, width);
562     PACK_FRAME (dest, convert->tmpline8, height - 1, width);
563   }
564 }
565
566 static void
567 convert_I420_Y42B (VideoConvert * convert, GstVideoFrame * dest,
568     const GstVideoFrame * src)
569 {
570   gint width = convert->width;
571   gint height = convert->height;
572
573   video_convert_orc_memcpy_2d (FRAME_GET_Y_LINE (dest, 0),
574       FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
575       FRAME_GET_Y_STRIDE (src), width, height);
576
577   video_convert_orc_planar_chroma_420_422 (FRAME_GET_U_LINE (dest, 0),
578       2 * FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (dest, 1),
579       2 * FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (src, 0),
580       FRAME_GET_U_STRIDE (src), (width + 1) / 2, height / 2);
581
582   video_convert_orc_planar_chroma_420_422 (FRAME_GET_V_LINE (dest, 0),
583       2 * FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (dest, 1),
584       2 * FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (src, 0),
585       FRAME_GET_V_STRIDE (src), (width + 1) / 2, height / 2);
586 }
587
588 static void
589 convert_I420_Y444 (VideoConvert * convert, GstVideoFrame * dest,
590     const GstVideoFrame * src)
591 {
592   gint width = convert->width;
593   gint height = convert->height;
594
595   video_convert_orc_memcpy_2d (FRAME_GET_Y_LINE (dest, 0),
596       FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
597       FRAME_GET_Y_STRIDE (src), width, height);
598
599   video_convert_orc_planar_chroma_420_444 (FRAME_GET_U_LINE (dest, 0),
600       2 * FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (dest, 1),
601       2 * FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (src, 0),
602       FRAME_GET_U_STRIDE (src), (width + 1) / 2, height / 2);
603
604   video_convert_orc_planar_chroma_420_444 (FRAME_GET_V_LINE (dest, 0),
605       2 * FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (dest, 1),
606       2 * FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (src, 0),
607       FRAME_GET_V_STRIDE (src), (width + 1) / 2, height / 2);
608
609   /* now handle last line */
610   if (height & 1) {
611     UNPACK_FRAME (src, convert->tmpline8, height - 1, width);
612     PACK_FRAME (dest, convert->tmpline8, height - 1, width);
613   }
614 }
615
616 static void
617 convert_YUY2_I420 (VideoConvert * convert, GstVideoFrame * dest,
618     const GstVideoFrame * src)
619 {
620   int i, h;
621   gint width = convert->width;
622   gint height = convert->height;
623   gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src);
624   gint l1, l2;
625
626   h = height;
627   if (width & 1)
628     h--;
629
630   for (i = 0; i < h; i += 2) {
631     GET_LINE_OFFSETS (interlaced, i, l1, l2);
632
633     video_convert_orc_convert_YUY2_I420 (FRAME_GET_Y_LINE (dest, l1),
634         FRAME_GET_Y_LINE (dest, l2),
635         FRAME_GET_U_LINE (dest, i >> 1),
636         FRAME_GET_V_LINE (dest, i >> 1),
637         FRAME_GET_LINE (src, l1), FRAME_GET_LINE (src, l2), (width + 1) / 2);
638   }
639
640   /* now handle last line */
641   if (height & 1) {
642     UNPACK_FRAME (src, convert->tmpline8, height - 1, width);
643     PACK_FRAME (dest, convert->tmpline8, height - 1, width);
644   }
645 }
646
647 static void
648 convert_YUY2_AYUV (VideoConvert * convert, GstVideoFrame * dest,
649     const GstVideoFrame * src)
650 {
651   gint width = convert->width;
652   gint height = convert->height;
653
654   video_convert_orc_convert_YUY2_AYUV (FRAME_GET_LINE (dest, 0),
655       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
656       FRAME_GET_STRIDE (src), (width + 1) / 2,
657       height & 1 ? height - 1 : height);
658
659   /* now handle last line */
660   if (height & 1) {
661     UNPACK_FRAME (src, convert->tmpline8, height - 1, width);
662     PACK_FRAME (dest, convert->tmpline8, height - 1, width);
663   }
664 }
665
666 static void
667 convert_YUY2_Y42B (VideoConvert * convert, GstVideoFrame * dest,
668     const GstVideoFrame * src)
669 {
670   gint width = convert->width;
671   gint height = convert->height;
672
673   video_convert_orc_convert_YUY2_Y42B (FRAME_GET_Y_LINE (dest, 0),
674       FRAME_GET_Y_STRIDE (dest), FRAME_GET_U_LINE (dest, 0),
675       FRAME_GET_U_STRIDE (dest), FRAME_GET_V_LINE (dest, 0),
676       FRAME_GET_V_STRIDE (dest), FRAME_GET_LINE (src, 0),
677       FRAME_GET_STRIDE (src), (width + 1) / 2, height);
678 }
679
680 static void
681 convert_YUY2_Y444 (VideoConvert * convert, GstVideoFrame * dest,
682     const GstVideoFrame * src)
683 {
684   gint width = convert->width;
685   gint height = convert->height;
686
687   video_convert_orc_convert_YUY2_Y444 (FRAME_GET_COMP_LINE (dest, 0, 0),
688       FRAME_GET_COMP_STRIDE (dest, 0), FRAME_GET_COMP_LINE (dest, 1, 0),
689       FRAME_GET_COMP_STRIDE (dest, 1), FRAME_GET_COMP_LINE (dest, 2, 0),
690       FRAME_GET_COMP_STRIDE (dest, 2), FRAME_GET_LINE (src, 0),
691       FRAME_GET_STRIDE (src), (width + 1) / 2, height);
692 }
693
694
695 static void
696 convert_UYVY_I420 (VideoConvert * convert, GstVideoFrame * dest,
697     const GstVideoFrame * src)
698 {
699   int i;
700   gint width = convert->width;
701   gint height = convert->height;
702   gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src);
703   gint l1, l2;
704
705   for (i = 0; i < GST_ROUND_DOWN_2 (height); i += 2) {
706     GET_LINE_OFFSETS (interlaced, i, l1, l2);
707
708     video_convert_orc_convert_UYVY_I420 (FRAME_GET_COMP_LINE (dest, 0, l1),
709         FRAME_GET_COMP_LINE (dest, 0, l2),
710         FRAME_GET_COMP_LINE (dest, 1, i >> 1),
711         FRAME_GET_COMP_LINE (dest, 2, i >> 1),
712         FRAME_GET_LINE (src, l1), FRAME_GET_LINE (src, l2), (width + 1) / 2);
713   }
714
715   /* now handle last line */
716   if (height & 1) {
717     UNPACK_FRAME (src, convert->tmpline8, height - 1, width);
718     PACK_FRAME (dest, convert->tmpline8, height - 1, width);
719   }
720 }
721
722 static void
723 convert_UYVY_AYUV (VideoConvert * convert, GstVideoFrame * dest,
724     const GstVideoFrame * src)
725 {
726   gint width = convert->width;
727   gint height = convert->height;
728
729   video_convert_orc_convert_UYVY_AYUV (FRAME_GET_LINE (dest, 0),
730       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
731       FRAME_GET_STRIDE (src), (width + 1) / 2,
732       height & 1 ? height - 1 : height);
733
734   /* now handle last line */
735   if (height & 1) {
736     UNPACK_FRAME (src, convert->tmpline8, height - 1, width);
737     PACK_FRAME (dest, convert->tmpline8, height - 1, width);
738   }
739 }
740
741 static void
742 convert_UYVY_YUY2 (VideoConvert * convert, GstVideoFrame * dest,
743     const GstVideoFrame * src)
744 {
745   gint width = convert->width;
746   gint height = convert->height;
747
748   video_convert_orc_convert_UYVY_YUY2 (FRAME_GET_LINE (dest, 0),
749       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
750       FRAME_GET_STRIDE (src), (width + 1) / 2, height);
751 }
752
753 static void
754 convert_UYVY_Y42B (VideoConvert * convert, GstVideoFrame * dest,
755     const GstVideoFrame * src)
756 {
757   gint width = convert->width;
758   gint height = convert->height;
759
760   video_convert_orc_convert_UYVY_Y42B (FRAME_GET_Y_LINE (dest, 0),
761       FRAME_GET_Y_STRIDE (dest), FRAME_GET_U_LINE (dest, 0),
762       FRAME_GET_U_STRIDE (dest), FRAME_GET_V_LINE (dest, 0),
763       FRAME_GET_V_STRIDE (dest), FRAME_GET_LINE (src, 0),
764       FRAME_GET_STRIDE (src), (width + 1) / 2, height);
765 }
766
767 static void
768 convert_UYVY_Y444 (VideoConvert * convert, GstVideoFrame * dest,
769     const GstVideoFrame * src)
770 {
771   gint width = convert->width;
772   gint height = convert->height;
773
774   video_convert_orc_convert_UYVY_Y444 (FRAME_GET_Y_LINE (dest, 0),
775       FRAME_GET_Y_STRIDE (dest), FRAME_GET_U_LINE (dest, 0),
776       FRAME_GET_U_STRIDE (dest), FRAME_GET_V_LINE (dest, 0),
777       FRAME_GET_V_STRIDE (dest), FRAME_GET_LINE (src, 0),
778       FRAME_GET_STRIDE (src), (width + 1) / 2, height);
779 }
780
781 static void
782 convert_AYUV_I420 (VideoConvert * convert, GstVideoFrame * dest,
783     const GstVideoFrame * src)
784 {
785   gint width = convert->width;
786   gint height = convert->height;
787
788   video_convert_orc_convert_AYUV_I420 (FRAME_GET_Y_LINE (dest, 0),
789       2 * FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (dest, 1),
790       2 * FRAME_GET_Y_STRIDE (dest), FRAME_GET_U_LINE (dest, 0),
791       FRAME_GET_U_STRIDE (dest), FRAME_GET_V_LINE (dest, 0),
792       FRAME_GET_V_STRIDE (dest), FRAME_GET_LINE (src, 0),
793       2 * FRAME_GET_STRIDE (src), FRAME_GET_LINE (src, 1),
794       2 * FRAME_GET_STRIDE (src), width / 2, height / 2);
795 }
796
797 static void
798 convert_AYUV_YUY2 (VideoConvert * convert, GstVideoFrame * dest,
799     const GstVideoFrame * src)
800 {
801   gint width = convert->width;
802   gint height = convert->height;
803
804   video_convert_orc_convert_AYUV_YUY2 (FRAME_GET_LINE (dest, 0),
805       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
806       FRAME_GET_STRIDE (src), width / 2, height);
807 }
808
809 static void
810 convert_AYUV_UYVY (VideoConvert * convert, GstVideoFrame * dest,
811     const GstVideoFrame * src)
812 {
813   gint width = convert->width;
814   gint height = convert->height;
815
816   video_convert_orc_convert_AYUV_UYVY (FRAME_GET_LINE (dest, 0),
817       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
818       FRAME_GET_STRIDE (src), width / 2, height);
819 }
820
821 static void
822 convert_AYUV_Y42B (VideoConvert * convert, GstVideoFrame * dest,
823     const GstVideoFrame * src)
824 {
825   gint width = convert->width;
826   gint height = convert->height;
827
828   video_convert_orc_convert_AYUV_Y42B (FRAME_GET_Y_LINE (dest, 0),
829       FRAME_GET_Y_STRIDE (dest), FRAME_GET_U_LINE (dest, 0),
830       FRAME_GET_U_STRIDE (dest), FRAME_GET_V_LINE (dest, 0),
831       FRAME_GET_V_STRIDE (dest), FRAME_GET_LINE (src, 0),
832       FRAME_GET_STRIDE (src), (width + 1) / 2,
833       height & 1 ? height - 1 : height);
834
835   /* now handle last line */
836   if (height & 1) {
837     UNPACK_FRAME (src, convert->tmpline8, height - 1, width);
838     PACK_FRAME (dest, convert->tmpline8, height - 1, width);
839   }
840 }
841
842 static void
843 convert_AYUV_Y444 (VideoConvert * convert, GstVideoFrame * dest,
844     const GstVideoFrame * src)
845 {
846   gint width = convert->width;
847   gint height = convert->height;
848
849   video_convert_orc_convert_AYUV_Y444 (FRAME_GET_Y_LINE (dest, 0),
850       FRAME_GET_Y_STRIDE (dest), FRAME_GET_U_LINE (dest, 0),
851       FRAME_GET_U_STRIDE (dest), FRAME_GET_V_LINE (dest, 0),
852       FRAME_GET_V_STRIDE (dest), FRAME_GET_LINE (src, 0),
853       FRAME_GET_STRIDE (src), width, height);
854 }
855
856 static void
857 convert_Y42B_I420 (VideoConvert * convert, GstVideoFrame * dest,
858     const GstVideoFrame * src)
859 {
860   gint width = convert->width;
861   gint height = convert->height;
862
863   video_convert_orc_memcpy_2d (FRAME_GET_Y_LINE (dest, 0),
864       FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
865       FRAME_GET_Y_STRIDE (src), width, height);
866
867   video_convert_orc_planar_chroma_422_420 (FRAME_GET_U_LINE (dest, 0),
868       FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (src, 0),
869       2 * FRAME_GET_U_STRIDE (src), FRAME_GET_U_LINE (src, 1),
870       2 * FRAME_GET_U_STRIDE (src), (width + 1) / 2, height / 2);
871
872   video_convert_orc_planar_chroma_422_420 (FRAME_GET_V_LINE (dest, 0),
873       FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (src, 0),
874       2 * FRAME_GET_V_STRIDE (src), FRAME_GET_V_LINE (src, 1),
875       2 * FRAME_GET_V_STRIDE (src), (width + 1) / 2, height / 2);
876
877   /* now handle last line */
878   if (height & 1) {
879     UNPACK_FRAME (src, convert->tmpline8, height - 1, width);
880     PACK_FRAME (dest, convert->tmpline8, height - 1, width);
881   }
882 }
883
884 static void
885 convert_Y42B_Y444 (VideoConvert * convert, GstVideoFrame * dest,
886     const GstVideoFrame * src)
887 {
888   gint width = convert->width;
889   gint height = convert->height;
890
891   video_convert_orc_memcpy_2d (FRAME_GET_Y_LINE (dest, 0),
892       FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
893       FRAME_GET_Y_STRIDE (src), width, height);
894
895   video_convert_orc_planar_chroma_422_444 (FRAME_GET_U_LINE (dest, 0),
896       FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (src, 0),
897       FRAME_GET_U_STRIDE (src), (width + 1) / 2, height);
898
899   video_convert_orc_planar_chroma_422_444 (FRAME_GET_V_LINE (dest, 0),
900       FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (src, 0),
901       FRAME_GET_V_STRIDE (src), (width + 1) / 2, height);
902 }
903
904 static void
905 convert_Y42B_YUY2 (VideoConvert * convert, GstVideoFrame * dest,
906     const GstVideoFrame * src)
907 {
908   gint width = convert->width;
909   gint height = convert->height;
910
911   video_convert_orc_convert_Y42B_YUY2 (FRAME_GET_LINE (dest, 0),
912       FRAME_GET_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
913       FRAME_GET_Y_STRIDE (src), FRAME_GET_U_LINE (src, 0),
914       FRAME_GET_U_STRIDE (src), FRAME_GET_V_LINE (src, 0),
915       FRAME_GET_V_STRIDE (src), (width + 1) / 2, height);
916 }
917
918 static void
919 convert_Y42B_UYVY (VideoConvert * convert, GstVideoFrame * dest,
920     const GstVideoFrame * src)
921 {
922   gint width = convert->width;
923   gint height = convert->height;
924
925   video_convert_orc_convert_Y42B_UYVY (FRAME_GET_LINE (dest, 0),
926       FRAME_GET_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
927       FRAME_GET_Y_STRIDE (src), FRAME_GET_U_LINE (src, 0),
928       FRAME_GET_U_STRIDE (src), FRAME_GET_V_LINE (src, 0),
929       FRAME_GET_V_STRIDE (src), (width + 1) / 2, height);
930 }
931
932 static void
933 convert_Y42B_AYUV (VideoConvert * convert, GstVideoFrame * dest,
934     const GstVideoFrame * src)
935 {
936   gint width = convert->width;
937   gint height = convert->height;
938
939   video_convert_orc_convert_Y42B_AYUV (FRAME_GET_LINE (dest, 0),
940       FRAME_GET_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
941       FRAME_GET_Y_STRIDE (src), FRAME_GET_U_LINE (src, 0),
942       FRAME_GET_U_STRIDE (src), FRAME_GET_V_LINE (src, 0),
943       FRAME_GET_V_STRIDE (src), (width) / 2, height);
944 }
945
946 static void
947 convert_Y444_I420 (VideoConvert * convert, GstVideoFrame * dest,
948     const GstVideoFrame * src)
949 {
950   gint width = convert->width;
951   gint height = convert->height;
952
953   video_convert_orc_memcpy_2d (FRAME_GET_Y_LINE (dest, 0),
954       FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
955       FRAME_GET_Y_STRIDE (src), width, height);
956
957   video_convert_orc_planar_chroma_444_420 (FRAME_GET_U_LINE (dest, 0),
958       FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (src, 0),
959       2 * FRAME_GET_U_STRIDE (src), FRAME_GET_U_LINE (src, 1),
960       2 * FRAME_GET_U_STRIDE (src), (width + 1) / 2, height / 2);
961
962   video_convert_orc_planar_chroma_444_420 (FRAME_GET_V_LINE (dest, 0),
963       FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (src, 0),
964       2 * FRAME_GET_V_STRIDE (src), FRAME_GET_V_LINE (src, 1),
965       2 * FRAME_GET_V_STRIDE (src), (width + 1) / 2, height / 2);
966
967   /* now handle last line */
968   if (height & 1) {
969     UNPACK_FRAME (src, convert->tmpline8, height - 1, width);
970     PACK_FRAME (dest, convert->tmpline8, height - 1, width);
971   }
972 }
973
974 static void
975 convert_Y444_Y42B (VideoConvert * convert, GstVideoFrame * dest,
976     const GstVideoFrame * src)
977 {
978   gint width = convert->width;
979   gint height = convert->height;
980
981   video_convert_orc_memcpy_2d (FRAME_GET_Y_LINE (dest, 0),
982       FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
983       FRAME_GET_Y_STRIDE (src), width, height);
984
985   video_convert_orc_planar_chroma_444_422 (FRAME_GET_U_LINE (dest, 0),
986       FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (src, 0),
987       FRAME_GET_U_STRIDE (src), (width + 1) / 2, height);
988
989   video_convert_orc_planar_chroma_444_422 (FRAME_GET_V_LINE (dest, 0),
990       FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (src, 0),
991       FRAME_GET_V_STRIDE (src), (width + 1) / 2, height);
992 }
993
994 static void
995 convert_Y444_YUY2 (VideoConvert * convert, GstVideoFrame * dest,
996     const GstVideoFrame * src)
997 {
998   gint width = convert->width;
999   gint height = convert->height;
1000
1001   video_convert_orc_convert_Y444_YUY2 (FRAME_GET_LINE (dest, 0),
1002       FRAME_GET_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
1003       FRAME_GET_Y_STRIDE (src), FRAME_GET_U_LINE (src, 0),
1004       FRAME_GET_U_STRIDE (src), FRAME_GET_V_LINE (src, 0),
1005       FRAME_GET_V_STRIDE (src), (width + 1) / 2, height);
1006 }
1007
1008 static void
1009 convert_Y444_UYVY (VideoConvert * convert, GstVideoFrame * dest,
1010     const GstVideoFrame * src)
1011 {
1012   gint width = convert->width;
1013   gint height = convert->height;
1014
1015   video_convert_orc_convert_Y444_UYVY (FRAME_GET_LINE (dest, 0),
1016       FRAME_GET_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
1017       FRAME_GET_Y_STRIDE (src), FRAME_GET_U_LINE (src, 0),
1018       FRAME_GET_U_STRIDE (src), FRAME_GET_V_LINE (src, 0),
1019       FRAME_GET_V_STRIDE (src), (width + 1) / 2, height);
1020 }
1021
1022 static void
1023 convert_Y444_AYUV (VideoConvert * convert, GstVideoFrame * dest,
1024     const GstVideoFrame * src)
1025 {
1026   gint width = convert->width;
1027   gint height = convert->height;
1028
1029   video_convert_orc_convert_Y444_AYUV (FRAME_GET_LINE (dest, 0),
1030       FRAME_GET_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
1031       FRAME_GET_Y_STRIDE (src), FRAME_GET_U_LINE (src, 0),
1032       FRAME_GET_U_STRIDE (src), FRAME_GET_V_LINE (src, 0),
1033       FRAME_GET_V_STRIDE (src), width, height);
1034 }
1035
1036 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1037 static void
1038 convert_AYUV_ARGB (VideoConvert * convert, GstVideoFrame * dest,
1039     const GstVideoFrame * src)
1040 {
1041   gint width = convert->width;
1042   gint height = convert->height;
1043
1044   video_convert_orc_convert_AYUV_ARGB (FRAME_GET_LINE (dest, 0),
1045       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
1046       FRAME_GET_STRIDE (src), width, height);
1047 }
1048
1049 static void
1050 convert_AYUV_BGRA (VideoConvert * convert, GstVideoFrame * dest,
1051     const GstVideoFrame * src)
1052 {
1053   gint width = convert->width;
1054   gint height = convert->height;
1055
1056   video_convert_orc_convert_AYUV_BGRA (FRAME_GET_LINE (dest, 0),
1057       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
1058       FRAME_GET_STRIDE (src), width, height);
1059 }
1060
1061 static void
1062 convert_AYUV_ABGR (VideoConvert * convert, GstVideoFrame * dest,
1063     const GstVideoFrame * src)
1064 {
1065   gint width = convert->width;
1066   gint height = convert->height;
1067
1068   video_convert_orc_convert_AYUV_ABGR (FRAME_GET_LINE (dest, 0),
1069       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
1070       FRAME_GET_STRIDE (src), width, height);
1071 }
1072
1073 static void
1074 convert_AYUV_RGBA (VideoConvert * convert, GstVideoFrame * dest,
1075     const GstVideoFrame * src)
1076 {
1077   gint width = convert->width;
1078   gint height = convert->height;
1079
1080   video_convert_orc_convert_AYUV_RGBA (FRAME_GET_LINE (dest, 0),
1081       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
1082       FRAME_GET_STRIDE (src), width, height);
1083 }
1084
1085 static void
1086 convert_I420_BGRA (VideoConvert * convert, GstVideoFrame * dest,
1087     const GstVideoFrame * src)
1088 {
1089   int i;
1090   int quality = 0;
1091   gint width = convert->width;
1092   gint height = convert->height;
1093
1094   if (quality > 3) {
1095     for (i = 0; i < height; i++) {
1096       if (i & 1) {
1097         video_convert_orc_convert_I420_BGRA_avg (FRAME_GET_LINE (dest, i),
1098             FRAME_GET_Y_LINE (src, i),
1099             FRAME_GET_U_LINE (src, i >> 1),
1100             FRAME_GET_U_LINE (src, (i >> 1) + 1),
1101             FRAME_GET_V_LINE (src, i >> 1),
1102             FRAME_GET_V_LINE (src, (i >> 1) + 1), width);
1103       } else {
1104         video_convert_orc_convert_I420_BGRA (FRAME_GET_LINE (dest, i),
1105             FRAME_GET_Y_LINE (src, i),
1106             FRAME_GET_U_LINE (src, i >> 1),
1107             FRAME_GET_V_LINE (src, i >> 1), width);
1108       }
1109     }
1110   } else {
1111     for (i = 0; i < height; i++) {
1112       video_convert_orc_convert_I420_BGRA (FRAME_GET_LINE (dest, i),
1113           FRAME_GET_Y_LINE (src, i),
1114           FRAME_GET_U_LINE (src, i >> 1),
1115           FRAME_GET_V_LINE (src, i >> 1), width);
1116     }
1117   }
1118 }
1119 #endif
1120
1121
1122
1123 /* Fast paths */
1124
1125 typedef struct
1126 {
1127   GstVideoFormat in_format;
1128   GstVideoColorMatrix in_matrix;
1129   GstVideoFormat out_format;
1130   GstVideoColorMatrix out_matrix;
1131   gboolean keeps_color_matrix;
1132   gboolean keeps_interlaced;
1133   void (*convert) (VideoConvert * convert, GstVideoFrame * dest,
1134       const GstVideoFrame * src);
1135 } VideoTransform;
1136 static const VideoTransform transforms[] = {
1137   {GST_VIDEO_FORMAT_I420, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_YUY2,
1138       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_I420_YUY2},
1139   {GST_VIDEO_FORMAT_I420, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_UYVY,
1140       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_I420_UYVY},
1141   {GST_VIDEO_FORMAT_I420, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_AYUV,
1142       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_I420_AYUV},
1143   {GST_VIDEO_FORMAT_I420, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y42B,
1144       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, convert_I420_Y42B},
1145   {GST_VIDEO_FORMAT_I420, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y444,
1146       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, convert_I420_Y444},
1147
1148   {GST_VIDEO_FORMAT_YUY2, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_I420,
1149       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_YUY2_I420},
1150   {GST_VIDEO_FORMAT_YUY2, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_UYVY,
1151       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_UYVY_YUY2},   /* alias */
1152   {GST_VIDEO_FORMAT_YUY2, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_AYUV,
1153       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_YUY2_AYUV},
1154   {GST_VIDEO_FORMAT_YUY2, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y42B,
1155       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_YUY2_Y42B},
1156   {GST_VIDEO_FORMAT_YUY2, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y444,
1157       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_YUY2_Y444},
1158
1159   {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_I420,
1160       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_UYVY_I420},
1161   {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_YUY2,
1162       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_UYVY_YUY2},
1163   {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_AYUV,
1164       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_UYVY_AYUV},
1165   {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y42B,
1166       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_UYVY_Y42B},
1167   {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y444,
1168       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_UYVY_Y444},
1169
1170   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_I420,
1171       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, convert_AYUV_I420},
1172   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_YUY2,
1173       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_AYUV_YUY2},
1174   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_UYVY,
1175       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_AYUV_UYVY},
1176   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y42B,
1177       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_AYUV_Y42B},
1178   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y444,
1179       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_AYUV_Y444},
1180
1181   {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_I420,
1182       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, convert_Y42B_I420},
1183   {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_YUY2,
1184       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_Y42B_YUY2},
1185   {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_UYVY,
1186       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_Y42B_UYVY},
1187   {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_AYUV,
1188       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_Y42B_AYUV},
1189   {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y444,
1190       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_Y42B_Y444},
1191
1192   {GST_VIDEO_FORMAT_Y444, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_I420,
1193       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, convert_Y444_I420},
1194   {GST_VIDEO_FORMAT_Y444, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_YUY2,
1195       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_Y444_YUY2},
1196   {GST_VIDEO_FORMAT_Y444, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_UYVY,
1197       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_Y444_UYVY},
1198   {GST_VIDEO_FORMAT_Y444, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_AYUV,
1199       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_Y444_AYUV},
1200   {GST_VIDEO_FORMAT_Y444, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y42B,
1201       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, convert_Y444_Y42B},
1202
1203 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1204   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_BT601, GST_VIDEO_FORMAT_ARGB,
1205       GST_VIDEO_COLOR_MATRIX_RGB, FALSE, TRUE, convert_AYUV_ARGB},
1206   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_BT601, GST_VIDEO_FORMAT_BGRA,
1207       GST_VIDEO_COLOR_MATRIX_RGB, FALSE, TRUE, convert_AYUV_BGRA},
1208   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_BT601, GST_VIDEO_FORMAT_xRGB, GST_VIDEO_COLOR_MATRIX_RGB, FALSE, TRUE, convert_AYUV_ARGB},     /* alias */
1209   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_BT601, GST_VIDEO_FORMAT_BGRx, GST_VIDEO_COLOR_MATRIX_RGB, FALSE, TRUE, convert_AYUV_BGRA},     /* alias */
1210   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_BT601, GST_VIDEO_FORMAT_ABGR,
1211       GST_VIDEO_COLOR_MATRIX_RGB, FALSE, TRUE, convert_AYUV_ABGR},
1212   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_BT601, GST_VIDEO_FORMAT_RGBA,
1213       GST_VIDEO_COLOR_MATRIX_RGB, FALSE, TRUE, convert_AYUV_RGBA},
1214   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_BT601, GST_VIDEO_FORMAT_xBGR, GST_VIDEO_COLOR_MATRIX_RGB, FALSE, TRUE, convert_AYUV_ABGR},     /* alias */
1215   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_BT601, GST_VIDEO_FORMAT_RGBx, GST_VIDEO_COLOR_MATRIX_RGB, FALSE, TRUE, convert_AYUV_RGBA},     /* alias */
1216
1217   {GST_VIDEO_FORMAT_I420, GST_VIDEO_COLOR_MATRIX_BT601, GST_VIDEO_FORMAT_BGRA,
1218       GST_VIDEO_COLOR_MATRIX_RGB, FALSE, FALSE, convert_I420_BGRA},
1219 #endif
1220 };
1221
1222 static gboolean
1223 videoconvert_convert_lookup_fastpath (VideoConvert * convert)
1224 {
1225   int i;
1226   GstVideoFormat in_format, out_format;
1227   GstVideoColorMatrix in_matrix, out_matrix;
1228   gboolean interlaced;
1229
1230   in_format = GST_VIDEO_INFO_FORMAT (&convert->in_info);
1231   out_format = GST_VIDEO_INFO_FORMAT (&convert->out_info);
1232
1233   in_matrix = convert->in_info.colorimetry.matrix;
1234   out_matrix = convert->out_info.colorimetry.matrix;
1235
1236   interlaced = GST_VIDEO_INFO_IS_INTERLACED (&convert->in_info);
1237   interlaced |= GST_VIDEO_INFO_IS_INTERLACED (&convert->out_info);
1238
1239   for (i = 0; i < sizeof (transforms) / sizeof (transforms[0]); i++) {
1240     if (transforms[i].in_format == in_format &&
1241         transforms[i].out_format == out_format &&
1242         (transforms[i].keeps_color_matrix ||
1243             (transforms[i].in_matrix == in_matrix &&
1244                 transforms[i].out_matrix == out_matrix)) &&
1245         (transforms[i].keeps_interlaced || !interlaced)) {
1246       GST_DEBUG ("using fastpath");
1247       convert->convert = transforms[i].convert;
1248       return TRUE;
1249     }
1250   }
1251   return FALSE;
1252 }