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