videoaggregator: Create a new GstVideoAggregator baseclass
[platform/upstream/gstreamer.git] / gst-libs / gst / video / 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 "bad-video-orc.h"
32
33
34 static void videoconvert_convert_generic (VideoConvert * convert,
35     GstVideoFrame * dest, const GstVideoFrame * src);
36 static void videoconvert_convert_matrix8 (VideoConvert * convert,
37     gpointer pixels);
38 static void videoconvert_convert_matrix16 (VideoConvert * convert,
39     gpointer pixels);
40 static gboolean videoconvert_convert_lookup_fastpath (VideoConvert * convert);
41 static gboolean videoconvert_convert_compute_matrix (VideoConvert * convert);
42 static gboolean videoconvert_convert_compute_resample (VideoConvert * convert);
43 static void videoconvert_dither_verterr (VideoConvert * convert,
44     guint16 * pixels, int j);
45 static void videoconvert_dither_halftone (VideoConvert * convert,
46     guint16 * pixels, int j);
47
48
49 VideoConvert *
50 videoconvert_convert_new (GstVideoInfo * in_info, GstVideoInfo * out_info)
51 {
52   VideoConvert *convert;
53   gint width;
54
55   convert = g_malloc0 (sizeof (VideoConvert));
56
57   convert->in_info = *in_info;
58   convert->out_info = *out_info;
59   convert->dither16 = NULL;
60
61   convert->width = GST_VIDEO_INFO_WIDTH (in_info);
62   convert->height = GST_VIDEO_INFO_HEIGHT (in_info);
63
64   if (!videoconvert_convert_lookup_fastpath (convert)) {
65     convert->convert = videoconvert_convert_generic;
66     if (!videoconvert_convert_compute_matrix (convert))
67       goto no_convert;
68
69     if (!videoconvert_convert_compute_resample (convert))
70       goto no_convert;
71   }
72
73   width = convert->width;
74
75   convert->lines = out_info->finfo->pack_lines;
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   gint i;
92
93   if (convert->upsample)
94     gst_video_chroma_resample_free (convert->upsample);
95   if (convert->downsample)
96     gst_video_chroma_resample_free (convert->downsample);
97
98   for (i = 0; i < convert->n_tmplines; i++)
99     g_free (convert->tmplines[i]);
100   g_free (convert->tmplines);
101   g_free (convert->errline);
102
103   g_free (convert);
104 }
105
106 void
107 videoconvert_convert_set_dither (VideoConvert * convert, int type)
108 {
109   switch (type) {
110     case 0:
111     default:
112       convert->dither16 = NULL;
113       break;
114     case 1:
115       convert->dither16 = videoconvert_dither_verterr;
116       break;
117     case 2:
118       convert->dither16 = videoconvert_dither_halftone;
119       break;
120   }
121 }
122
123 void
124 videoconvert_convert_convert (VideoConvert * convert,
125     GstVideoFrame * dest, const GstVideoFrame * src)
126 {
127   convert->convert (convert, dest, src);
128 }
129
130 #define SCALE    (8)
131 #define SCALE_F  ((float) (1 << SCALE))
132
133 static void
134 videoconvert_convert_matrix8 (VideoConvert * convert, gpointer pixels)
135 {
136   int i;
137   int r, g, b;
138   int y, u, v;
139   guint8 *p = pixels;
140
141   for (i = 0; i < convert->width; i++) {
142     r = p[i * 4 + 1];
143     g = p[i * 4 + 2];
144     b = p[i * 4 + 3];
145
146     y = (convert->cmatrix[0][0] * r + convert->cmatrix[0][1] * g +
147         convert->cmatrix[0][2] * b + convert->cmatrix[0][3]) >> SCALE;
148     u = (convert->cmatrix[1][0] * r + convert->cmatrix[1][1] * g +
149         convert->cmatrix[1][2] * b + convert->cmatrix[1][3]) >> SCALE;
150     v = (convert->cmatrix[2][0] * r + convert->cmatrix[2][1] * g +
151         convert->cmatrix[2][2] * b + convert->cmatrix[2][3]) >> SCALE;
152
153     p[i * 4 + 1] = CLAMP (y, 0, 255);
154     p[i * 4 + 2] = CLAMP (u, 0, 255);
155     p[i * 4 + 3] = CLAMP (v, 0, 255);
156   }
157 }
158
159 static void
160 videoconvert_convert_matrix16 (VideoConvert * convert, gpointer pixels)
161 {
162   int i;
163   int r, g, b;
164   int y, u, v;
165   guint16 *p = pixels;
166
167   for (i = 0; i < convert->width; i++) {
168     r = p[i * 4 + 1];
169     g = p[i * 4 + 2];
170     b = p[i * 4 + 3];
171
172     y = (convert->cmatrix[0][0] * r + convert->cmatrix[0][1] * g +
173         convert->cmatrix[0][2] * b + convert->cmatrix[0][3]) >> SCALE;
174     u = (convert->cmatrix[1][0] * r + convert->cmatrix[1][1] * g +
175         convert->cmatrix[1][2] * b + convert->cmatrix[1][3]) >> SCALE;
176     v = (convert->cmatrix[2][0] * r + convert->cmatrix[2][1] * g +
177         convert->cmatrix[2][2] * b + convert->cmatrix[2][3]) >> SCALE;
178
179     p[i * 4 + 1] = CLAMP (y, 0, 65535);
180     p[i * 4 + 2] = CLAMP (u, 0, 65535);
181     p[i * 4 + 3] = CLAMP (v, 0, 65535);
182   }
183 }
184
185 static gboolean
186 get_Kr_Kb (GstVideoColorMatrix matrix, gdouble * Kr, gdouble * Kb)
187 {
188   gboolean res = TRUE;
189
190   switch (matrix) {
191       /* RGB */
192     default:
193     case GST_VIDEO_COLOR_MATRIX_RGB:
194       res = FALSE;
195       break;
196       /* YUV */
197     case GST_VIDEO_COLOR_MATRIX_FCC:
198       *Kr = 0.30;
199       *Kb = 0.11;
200       break;
201     case GST_VIDEO_COLOR_MATRIX_BT709:
202       *Kr = 0.2126;
203       *Kb = 0.0722;
204       break;
205     case GST_VIDEO_COLOR_MATRIX_BT601:
206       *Kr = 0.2990;
207       *Kb = 0.1140;
208       break;
209     case GST_VIDEO_COLOR_MATRIX_SMPTE240M:
210       *Kr = 0.212;
211       *Kb = 0.087;
212       break;
213   }
214   GST_DEBUG ("matrix: %d, Kr %f, Kb %f", matrix, *Kr, *Kb);
215   return res;
216 }
217
218 static gboolean
219 videoconvert_convert_compute_matrix (VideoConvert * convert)
220 {
221   GstVideoInfo *in_info, *out_info;
222   ColorMatrix dst;
223   gint i, j;
224   const GstVideoFormatInfo *sfinfo, *dfinfo;
225   const GstVideoFormatInfo *suinfo, *duinfo;
226   gint offset[4], scale[4];
227   gdouble Kr = 0, Kb = 0;
228
229   in_info = &convert->in_info;
230   out_info = &convert->out_info;
231
232   sfinfo = in_info->finfo;
233   dfinfo = out_info->finfo;
234
235   if (sfinfo->unpack_func == NULL)
236     goto no_unpack_func;
237
238   if (dfinfo->pack_func == NULL)
239     goto no_pack_func;
240
241   suinfo = gst_video_format_get_info (sfinfo->unpack_format);
242   duinfo = gst_video_format_get_info (dfinfo->unpack_format);
243
244   convert->in_bits = GST_VIDEO_FORMAT_INFO_DEPTH (suinfo, 0);
245   convert->out_bits = GST_VIDEO_FORMAT_INFO_DEPTH (duinfo, 0);
246
247   GST_DEBUG ("in bits %d, out bits %d", convert->in_bits, convert->out_bits);
248
249   if (in_info->colorimetry.range == out_info->colorimetry.range &&
250       in_info->colorimetry.matrix == out_info->colorimetry.matrix) {
251     GST_DEBUG ("using identity color transform");
252     convert->matrix = NULL;
253     return TRUE;
254   }
255
256   /* calculate intermediate format for the matrix. When unpacking, we expand
257    * input to 16 when one of the inputs is 16 bits */
258   if (convert->in_bits == 16 || convert->out_bits == 16) {
259     convert->matrix = videoconvert_convert_matrix16;
260
261     if (GST_VIDEO_FORMAT_INFO_IS_RGB (suinfo))
262       suinfo = gst_video_format_get_info (GST_VIDEO_FORMAT_ARGB64);
263     else
264       suinfo = gst_video_format_get_info (GST_VIDEO_FORMAT_AYUV64);
265
266     if (GST_VIDEO_FORMAT_INFO_IS_RGB (duinfo))
267       duinfo = gst_video_format_get_info (GST_VIDEO_FORMAT_ARGB64);
268     else
269       duinfo = gst_video_format_get_info (GST_VIDEO_FORMAT_AYUV64);
270   } else {
271     convert->matrix = videoconvert_convert_matrix8;
272   }
273
274   color_matrix_set_identity (&dst);
275
276   /* 1, bring color components to [0..1.0] range */
277   gst_video_color_range_offsets (in_info->colorimetry.range, suinfo, offset,
278       scale);
279
280   color_matrix_offset_components (&dst, -offset[0], -offset[1], -offset[2]);
281
282   color_matrix_scale_components (&dst, 1 / ((float) scale[0]),
283       1 / ((float) scale[1]), 1 / ((float) scale[2]));
284
285   /* 2. bring components to R'G'B' space */
286   if (get_Kr_Kb (in_info->colorimetry.matrix, &Kr, &Kb))
287     color_matrix_YCbCr_to_RGB (&dst, Kr, Kb);
288
289   /* 3. inverse transfer function. R'G'B' to linear RGB */
290
291   /* 4. from RGB to XYZ using the primaries */
292
293   /* 5. from XYZ to RGB using the primaries */
294
295   /* 6. transfer function. linear RGB to R'G'B' */
296
297   /* 7. bring components to YCbCr space */
298   if (get_Kr_Kb (out_info->colorimetry.matrix, &Kr, &Kb))
299     color_matrix_RGB_to_YCbCr (&dst, Kr, Kb);
300
301   /* 8, bring color components to nominal range */
302   gst_video_color_range_offsets (out_info->colorimetry.range, duinfo, offset,
303       scale);
304
305   color_matrix_scale_components (&dst, (float) scale[0], (float) scale[1],
306       (float) scale[2]);
307
308   color_matrix_offset_components (&dst, offset[0], offset[1], offset[2]);
309
310   /* because we're doing fixed point matrix coefficients */
311   color_matrix_scale_components (&dst, SCALE_F, SCALE_F, SCALE_F);
312
313   for (i = 0; i < 4; i++)
314     for (j = 0; j < 4; j++)
315       convert->cmatrix[i][j] = rint (dst.m[i][j]);
316
317   GST_DEBUG ("[%6d %6d %6d %6d]", convert->cmatrix[0][0],
318       convert->cmatrix[0][1], convert->cmatrix[0][2], convert->cmatrix[0][3]);
319   GST_DEBUG ("[%6d %6d %6d %6d]", convert->cmatrix[1][0],
320       convert->cmatrix[1][1], convert->cmatrix[1][2], convert->cmatrix[1][3]);
321   GST_DEBUG ("[%6d %6d %6d %6d]", convert->cmatrix[2][0],
322       convert->cmatrix[2][1], convert->cmatrix[2][2], convert->cmatrix[2][3]);
323   GST_DEBUG ("[%6d %6d %6d %6d]", convert->cmatrix[3][0],
324       convert->cmatrix[3][1], convert->cmatrix[3][2], convert->cmatrix[3][3]);
325
326   return TRUE;
327
328   /* ERRORS */
329 no_unpack_func:
330   {
331     GST_ERROR ("no unpack_func for format %s",
332         gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (in_info)));
333     return FALSE;
334   }
335 no_pack_func:
336   {
337     GST_ERROR ("no pack_func for format %s",
338         gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (out_info)));
339     return FALSE;
340   }
341 }
342
343 static void
344 videoconvert_dither_verterr (VideoConvert * convert, guint16 * pixels, int j)
345 {
346   int i;
347   guint16 *errline = convert->errline;
348   unsigned int mask = 0xff;
349
350   for (i = 0; i < 4 * convert->width; i++) {
351     int x = pixels[i] + errline[i];
352     if (x > 65535)
353       x = 65535;
354     pixels[i] = x;
355     errline[i] = x & mask;
356   }
357 }
358
359 static void
360 videoconvert_dither_halftone (VideoConvert * convert, guint16 * pixels, int j)
361 {
362   int i;
363   static guint16 halftone[8][8] = {
364     {0, 128, 32, 160, 8, 136, 40, 168},
365     {192, 64, 224, 96, 200, 72, 232, 104},
366     {48, 176, 16, 144, 56, 184, 24, 152},
367     {240, 112, 208, 80, 248, 120, 216, 88},
368     {12, 240, 44, 172, 4, 132, 36, 164},
369     {204, 76, 236, 108, 196, 68, 228, 100},
370     {60, 188, 28, 156, 52, 180, 20, 148},
371     {252, 142, 220, 92, 244, 116, 212, 84}
372   };
373
374   for (i = 0; i < convert->width * 4; i++) {
375     int x;
376     x = pixels[i] + halftone[(i >> 2) & 7][j & 7];
377     if (x > 65535)
378       x = 65535;
379     pixels[i] = x;
380   }
381 }
382
383 static void
384 alloc_tmplines (VideoConvert * convert, guint lines, gint width)
385 {
386   gint i;
387
388   convert->n_tmplines = lines;
389   convert->tmplines = g_malloc (lines * sizeof (gpointer));
390   for (i = 0; i < lines; i++)
391     convert->tmplines[i] = g_malloc (sizeof (guint16) * (width + 8) * 4);
392 }
393
394 static gboolean
395 videoconvert_convert_compute_resample (VideoConvert * convert)
396 {
397   GstVideoInfo *in_info, *out_info;
398   const GstVideoFormatInfo *sfinfo, *dfinfo;
399   gint width;
400
401   in_info = &convert->in_info;
402   out_info = &convert->out_info;
403
404   sfinfo = in_info->finfo;
405   dfinfo = out_info->finfo;
406
407   width = convert->width;
408
409   if (sfinfo->w_sub[2] != dfinfo->w_sub[2] ||
410       sfinfo->h_sub[2] != dfinfo->h_sub[2] ||
411       in_info->chroma_site != out_info->chroma_site) {
412     convert->upsample = gst_video_chroma_resample_new (0,
413         in_info->chroma_site, 0, sfinfo->unpack_format, sfinfo->w_sub[2],
414         sfinfo->h_sub[2]);
415
416
417     convert->downsample = gst_video_chroma_resample_new (0,
418         out_info->chroma_site, 0, dfinfo->unpack_format, -dfinfo->w_sub[2],
419         -dfinfo->h_sub[2]);
420
421   } else {
422     convert->upsample = NULL;
423     convert->downsample = NULL;
424   }
425
426   if (convert->upsample) {
427     gst_video_chroma_resample_get_info (convert->upsample,
428         &convert->up_n_lines, &convert->up_offset);
429   } else {
430     convert->up_n_lines = 1;
431     convert->up_offset = 0;
432   }
433   if (convert->downsample) {
434     gst_video_chroma_resample_get_info (convert->downsample,
435         &convert->down_n_lines, &convert->down_offset);
436   } else {
437     convert->down_n_lines = 1;
438     convert->down_offset = 0;
439   }
440   GST_DEBUG ("upsample: %p, site: %d, offset %d, n_lines %d", convert->upsample,
441       in_info->chroma_site, convert->up_offset, convert->up_n_lines);
442   GST_DEBUG ("downsample: %p, site: %d, offset %d, n_lines %d",
443       convert->downsample, out_info->chroma_site, convert->down_offset,
444       convert->down_n_lines);
445
446   alloc_tmplines (convert, convert->down_n_lines + convert->up_n_lines, width);
447
448   return TRUE;
449 }
450
451 #define TO_16(x) (((x)<<8) | (x))
452
453 static void
454 convert_to16 (gpointer line, gint width)
455 {
456   guint8 *line8 = line;
457   guint16 *line16 = line;
458   gint i;
459
460   for (i = (width - 1) * 4; i >= 0; i--)
461     line16[i] = TO_16 (line8[i]);
462 }
463
464 static void
465 convert_to8 (gpointer line, gint width)
466 {
467   guint8 *line8 = line;
468   guint16 *line16 = line;
469   gint i;
470
471   for (i = 0; i < width * 4; i++)
472     line8[i] = line16[i] >> 8;
473 }
474
475 #define UNPACK_FRAME(frame,dest,line,width)          \
476   frame->info.finfo->unpack_func (frame->info.finfo, \
477       (GST_VIDEO_FRAME_IS_INTERLACED (frame) ?       \
478         GST_VIDEO_PACK_FLAG_INTERLACED :             \
479         GST_VIDEO_PACK_FLAG_NONE),                   \
480       dest, frame->data, frame->info.stride, 0,      \
481       line, width)
482 #define PACK_FRAME(frame,dest,line,width)            \
483   frame->info.finfo->pack_func (frame->info.finfo,   \
484       (GST_VIDEO_FRAME_IS_INTERLACED (frame) ?       \
485         GST_VIDEO_PACK_FLAG_INTERLACED :             \
486         GST_VIDEO_PACK_FLAG_NONE),                   \
487       dest, 0, frame->data, frame->info.stride,      \
488       frame->info.chroma_site, line, width);
489
490 static void
491 videoconvert_convert_generic (VideoConvert * convert, GstVideoFrame * dest,
492     const GstVideoFrame * src)
493 {
494   int j, k;
495   gint width, height, lines, max_lines;
496   guint in_bits, out_bits;
497   gconstpointer pal;
498   gsize palsize;
499   guint up_n_lines, down_n_lines;
500   gint up_offset, down_offset;
501   gint in_lines, out_lines;
502   gint up_line, down_line;
503   gint start_offset, stop_offset;
504   gpointer in_tmplines[8];
505   gpointer out_tmplines[8];
506
507   height = convert->height;
508   width = convert->width;
509
510   in_bits = convert->in_bits;
511   out_bits = convert->out_bits;
512
513   lines = convert->lines;
514   up_n_lines = convert->up_n_lines;
515   up_offset = convert->up_offset;
516   down_n_lines = convert->down_n_lines;
517   down_offset = convert->down_offset;
518   max_lines = convert->n_tmplines;
519
520   in_lines = 0;
521   out_lines = 0;
522
523   GST_DEBUG ("up_offset %d, up_n_lines %u", up_offset, up_n_lines);
524
525   start_offset = MIN (up_offset, down_offset);
526   stop_offset = height + start_offset + MAX (up_n_lines, down_n_lines);
527
528   for (; start_offset < stop_offset; start_offset++) {
529     guint idx, start;
530
531     idx = CLAMP (start_offset, 0, height);
532     in_tmplines[in_lines] = convert->tmplines[idx % max_lines];
533     out_tmplines[out_lines] = in_tmplines[in_lines];
534     GST_DEBUG ("start_offset %d/%d, %d, idx %u, in %d, out %d", start_offset,
535         stop_offset, up_offset, idx, in_lines, out_lines);
536
537     up_line = up_offset + in_lines;
538
539     /* extract the next line */
540     if (up_line >= 0 && up_line < height) {
541       GST_DEBUG ("unpack line %d into %d", up_line, in_lines);
542       UNPACK_FRAME (src, in_tmplines[in_lines], up_line, width);
543     }
544
545     if (start_offset >= up_offset)
546       in_lines++;
547
548     if (start_offset >= down_offset)
549       out_lines++;
550
551     if (in_lines < up_n_lines)
552       continue;
553
554     in_lines = 0;
555
556     /* we have enough lines to upsample */
557     if (convert->upsample) {
558       GST_DEBUG ("doing upsample");
559       gst_video_chroma_resample (convert->upsample, in_tmplines, width);
560     }
561
562     /* convert upsampled lines */
563     for (k = 0; k < up_n_lines; k++) {
564       down_line = up_offset + k;
565
566       /* only takes lines with valid output */
567       if (down_line < 0 || down_line >= height)
568         continue;
569
570       GST_DEBUG ("handle line %d, %d/%d, down_line %d", k, out_lines,
571           down_n_lines, down_line);
572
573       if (out_bits == 16 || in_bits == 16) {
574         /* FIXME, we can scale in the conversion matrix */
575         if (in_bits == 8)
576           convert_to16 (in_tmplines[k], width);
577
578         if (convert->matrix)
579           convert->matrix (convert, in_tmplines[k]);
580         if (convert->dither16)
581           convert->dither16 (convert, in_tmplines[k], down_line);
582
583         if (out_bits == 8)
584           convert_to8 (in_tmplines[k], width);
585       } else {
586         if (convert->matrix)
587           convert->matrix (convert, in_tmplines[k]);
588       }
589     }
590
591     start = 0;
592     while (out_lines >= down_n_lines) {
593       if (convert->downsample) {
594         GST_DEBUG ("doing downsample %u", start);
595         gst_video_chroma_resample (convert->downsample,
596             &out_tmplines[start], width);
597       }
598
599       for (j = 0; j < down_n_lines; j += lines) {
600         idx = down_offset + j;
601
602         if (idx < height) {
603           GST_DEBUG ("packing line %d %d %d", j + start, down_offset, idx);
604           /* FIXME, not correct if lines > 1 */
605           PACK_FRAME (dest, out_tmplines[j + start], idx, width);
606         }
607       }
608       down_offset += down_n_lines;
609       start += down_n_lines;
610       out_lines -= down_n_lines;
611     }
612     /* we didn't process these lines, move them up for the next round */
613     for (j = 0; j < out_lines; j++) {
614       GST_DEBUG ("move line %d->%d", j + start, j);
615       out_tmplines[j] = out_tmplines[j + start];
616     }
617
618     up_offset += up_n_lines;
619   }
620   if ((pal =
621           gst_video_format_get_palette (GST_VIDEO_FRAME_FORMAT (dest),
622               &palsize))) {
623     memcpy (GST_VIDEO_FRAME_PLANE_DATA (dest, 1), pal, palsize);
624   }
625 }
626
627 #define FRAME_GET_PLANE_STRIDE(frame, plane) \
628   GST_VIDEO_FRAME_PLANE_STRIDE (frame, plane)
629 #define FRAME_GET_PLANE_LINE(frame, plane, line) \
630   (gpointer)(((guint8*)(GST_VIDEO_FRAME_PLANE_DATA (frame, plane))) + \
631       FRAME_GET_PLANE_STRIDE (frame, plane) * (line))
632
633 #define FRAME_GET_COMP_STRIDE(frame, comp) \
634   GST_VIDEO_FRAME_COMP_STRIDE (frame, comp)
635 #define FRAME_GET_COMP_LINE(frame, comp, line) \
636   (gpointer)(((guint8*)(GST_VIDEO_FRAME_COMP_DATA (frame, comp))) + \
637       FRAME_GET_COMP_STRIDE (frame, comp) * (line))
638
639 #define FRAME_GET_STRIDE(frame)      FRAME_GET_PLANE_STRIDE (frame, 0)
640 #define FRAME_GET_LINE(frame,line)   FRAME_GET_PLANE_LINE (frame, 0, line)
641
642 #define FRAME_GET_Y_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_Y, line)
643 #define FRAME_GET_U_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_U, line)
644 #define FRAME_GET_V_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_V, line)
645 #define FRAME_GET_A_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_A, line)
646
647 #define FRAME_GET_Y_STRIDE(frame)    FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_Y)
648 #define FRAME_GET_U_STRIDE(frame)    FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_U)
649 #define FRAME_GET_V_STRIDE(frame)    FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_V)
650 #define FRAME_GET_A_STRIDE(frame)    FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_A)
651
652 /* Fast paths */
653
654 #define GET_LINE_OFFSETS(interlaced,line,l1,l2) \
655     if (interlaced) {                           \
656       l1 = (line & 2 ? line - 1 : line);        \
657       l2 = l1 + 2;                              \
658     } else {                                    \
659       l1 = line;                                \
660       l2 = l1 + 1;                              \
661     }
662
663
664 static void
665 convert_I420_YUY2 (VideoConvert * convert, GstVideoFrame * dest,
666     const GstVideoFrame * src)
667 {
668   int i;
669   gint width = convert->width;
670   gint height = convert->height;
671   gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src);
672   gint l1, l2;
673
674   for (i = 0; i < GST_ROUND_DOWN_2 (height); i += 2) {
675     GET_LINE_OFFSETS (interlaced, i, l1, l2);
676
677     video_convert_orc_convert_I420_YUY2 (FRAME_GET_LINE (dest, l1),
678         FRAME_GET_LINE (dest, l2),
679         FRAME_GET_Y_LINE (src, l1),
680         FRAME_GET_Y_LINE (src, l2),
681         FRAME_GET_U_LINE (src, i >> 1),
682         FRAME_GET_V_LINE (src, i >> 1), (width + 1) / 2);
683   }
684
685   /* now handle last line */
686   if (height & 1) {
687     UNPACK_FRAME (src, convert->tmplines[0], height - 1, width);
688     PACK_FRAME (dest, convert->tmplines[0], height - 1, width);
689   }
690 }
691
692 static void
693 convert_I420_UYVY (VideoConvert * convert, GstVideoFrame * dest,
694     const GstVideoFrame * src)
695 {
696   int i;
697   gint width = convert->width;
698   gint height = convert->height;
699   gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src);
700   gint l1, l2;
701
702   for (i = 0; i < GST_ROUND_DOWN_2 (height); i += 2) {
703     GET_LINE_OFFSETS (interlaced, i, l1, l2);
704
705     video_convert_orc_convert_I420_UYVY (FRAME_GET_LINE (dest, l1),
706         FRAME_GET_LINE (dest, l2),
707         FRAME_GET_Y_LINE (src, l1),
708         FRAME_GET_Y_LINE (src, l2),
709         FRAME_GET_U_LINE (src, i >> 1),
710         FRAME_GET_V_LINE (src, i >> 1), (width + 1) / 2);
711   }
712
713   /* now handle last line */
714   if (height & 1) {
715     UNPACK_FRAME (src, convert->tmplines[0], height - 1, width);
716     PACK_FRAME (dest, convert->tmplines[0], height - 1, width);
717   }
718 }
719
720 static void
721 convert_I420_AYUV (VideoConvert * convert, GstVideoFrame * dest,
722     const GstVideoFrame * src)
723 {
724   int i;
725   gint width = convert->width;
726   gint height = convert->height;
727   gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src);
728   gint l1, l2;
729
730   for (i = 0; i < GST_ROUND_DOWN_2 (height); i += 2) {
731     GET_LINE_OFFSETS (interlaced, i, l1, l2);
732
733     video_convert_orc_convert_I420_AYUV (FRAME_GET_LINE (dest, l1),
734         FRAME_GET_LINE (dest, l2),
735         FRAME_GET_Y_LINE (src, l1),
736         FRAME_GET_Y_LINE (src, l2),
737         FRAME_GET_U_LINE (src, i >> 1), FRAME_GET_V_LINE (src, i >> 1), width);
738   }
739
740   /* now handle last line */
741   if (height & 1) {
742     UNPACK_FRAME (src, convert->tmplines[0], height - 1, width);
743     PACK_FRAME (dest, convert->tmplines[0], height - 1, width);
744   }
745 }
746
747 static void
748 convert_I420_Y42B (VideoConvert * convert, GstVideoFrame * dest,
749     const GstVideoFrame * src)
750 {
751   gint width = convert->width;
752   gint height = convert->height;
753
754   video_convert_orc_memcpy_2d (FRAME_GET_Y_LINE (dest, 0),
755       FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
756       FRAME_GET_Y_STRIDE (src), width, height);
757
758   video_convert_orc_planar_chroma_420_422 (FRAME_GET_U_LINE (dest, 0),
759       2 * FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (dest, 1),
760       2 * FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (src, 0),
761       FRAME_GET_U_STRIDE (src), (width + 1) / 2, height / 2);
762
763   video_convert_orc_planar_chroma_420_422 (FRAME_GET_V_LINE (dest, 0),
764       2 * FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (dest, 1),
765       2 * FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (src, 0),
766       FRAME_GET_V_STRIDE (src), (width + 1) / 2, height / 2);
767 }
768
769 static void
770 convert_I420_Y444 (VideoConvert * convert, GstVideoFrame * dest,
771     const GstVideoFrame * src)
772 {
773   gint width = convert->width;
774   gint height = convert->height;
775
776   video_convert_orc_memcpy_2d (FRAME_GET_Y_LINE (dest, 0),
777       FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
778       FRAME_GET_Y_STRIDE (src), width, height);
779
780   video_convert_orc_planar_chroma_420_444 (FRAME_GET_U_LINE (dest, 0),
781       2 * FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (dest, 1),
782       2 * FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (src, 0),
783       FRAME_GET_U_STRIDE (src), (width + 1) / 2, height / 2);
784
785   video_convert_orc_planar_chroma_420_444 (FRAME_GET_V_LINE (dest, 0),
786       2 * FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (dest, 1),
787       2 * FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (src, 0),
788       FRAME_GET_V_STRIDE (src), (width + 1) / 2, height / 2);
789
790   /* now handle last line */
791   if (height & 1) {
792     UNPACK_FRAME (src, convert->tmplines[0], height - 1, width);
793     PACK_FRAME (dest, convert->tmplines[0], height - 1, width);
794   }
795 }
796
797 static void
798 convert_YUY2_I420 (VideoConvert * convert, GstVideoFrame * dest,
799     const GstVideoFrame * src)
800 {
801   int i;
802   gint width = convert->width;
803   gint height = convert->height;
804   gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src);
805   gint l1, l2;
806
807   for (i = 0; i < GST_ROUND_DOWN_2 (height); i += 2) {
808     GET_LINE_OFFSETS (interlaced, i, l1, l2);
809
810     video_convert_orc_convert_YUY2_I420 (FRAME_GET_Y_LINE (dest, l1),
811         FRAME_GET_Y_LINE (dest, l2),
812         FRAME_GET_U_LINE (dest, i >> 1),
813         FRAME_GET_V_LINE (dest, i >> 1),
814         FRAME_GET_LINE (src, l1), FRAME_GET_LINE (src, l2), (width + 1) / 2);
815   }
816
817   /* now handle last line */
818   if (height & 1) {
819     UNPACK_FRAME (src, convert->tmplines[0], height - 1, width);
820     PACK_FRAME (dest, convert->tmplines[0], height - 1, width);
821   }
822 }
823
824 static void
825 convert_YUY2_AYUV (VideoConvert * convert, GstVideoFrame * dest,
826     const GstVideoFrame * src)
827 {
828   gint width = convert->width;
829   gint height = convert->height;
830
831   video_convert_orc_convert_YUY2_AYUV (FRAME_GET_LINE (dest, 0),
832       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
833       FRAME_GET_STRIDE (src), (width + 1) / 2, height);
834 }
835
836 static void
837 convert_YUY2_Y42B (VideoConvert * convert, GstVideoFrame * dest,
838     const GstVideoFrame * src)
839 {
840   gint width = convert->width;
841   gint height = convert->height;
842
843   video_convert_orc_convert_YUY2_Y42B (FRAME_GET_Y_LINE (dest, 0),
844       FRAME_GET_Y_STRIDE (dest), FRAME_GET_U_LINE (dest, 0),
845       FRAME_GET_U_STRIDE (dest), FRAME_GET_V_LINE (dest, 0),
846       FRAME_GET_V_STRIDE (dest), FRAME_GET_LINE (src, 0),
847       FRAME_GET_STRIDE (src), (width + 1) / 2, height);
848 }
849
850 static void
851 convert_YUY2_Y444 (VideoConvert * convert, GstVideoFrame * dest,
852     const GstVideoFrame * src)
853 {
854   gint width = convert->width;
855   gint height = convert->height;
856
857   video_convert_orc_convert_YUY2_Y444 (FRAME_GET_COMP_LINE (dest, 0, 0),
858       FRAME_GET_COMP_STRIDE (dest, 0), FRAME_GET_COMP_LINE (dest, 1, 0),
859       FRAME_GET_COMP_STRIDE (dest, 1), FRAME_GET_COMP_LINE (dest, 2, 0),
860       FRAME_GET_COMP_STRIDE (dest, 2), FRAME_GET_LINE (src, 0),
861       FRAME_GET_STRIDE (src), (width + 1) / 2, height);
862 }
863
864
865 static void
866 convert_UYVY_I420 (VideoConvert * convert, GstVideoFrame * dest,
867     const GstVideoFrame * src)
868 {
869   int i;
870   gint width = convert->width;
871   gint height = convert->height;
872   gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src);
873   gint l1, l2;
874
875   for (i = 0; i < GST_ROUND_DOWN_2 (height); i += 2) {
876     GET_LINE_OFFSETS (interlaced, i, l1, l2);
877
878     video_convert_orc_convert_UYVY_I420 (FRAME_GET_COMP_LINE (dest, 0, l1),
879         FRAME_GET_COMP_LINE (dest, 0, l2),
880         FRAME_GET_COMP_LINE (dest, 1, i >> 1),
881         FRAME_GET_COMP_LINE (dest, 2, i >> 1),
882         FRAME_GET_LINE (src, l1), FRAME_GET_LINE (src, l2), (width + 1) / 2);
883   }
884
885   /* now handle last line */
886   if (height & 1) {
887     UNPACK_FRAME (src, convert->tmplines[0], height - 1, width);
888     PACK_FRAME (dest, convert->tmplines[0], height - 1, width);
889   }
890 }
891
892 static void
893 convert_UYVY_AYUV (VideoConvert * convert, GstVideoFrame * dest,
894     const GstVideoFrame * src)
895 {
896   gint width = convert->width;
897   gint height = convert->height;
898
899   video_convert_orc_convert_UYVY_AYUV (FRAME_GET_LINE (dest, 0),
900       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
901       FRAME_GET_STRIDE (src), (width + 1) / 2, height);
902 }
903
904 static void
905 convert_UYVY_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_UYVY_YUY2 (FRAME_GET_LINE (dest, 0),
912       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
913       FRAME_GET_STRIDE (src), (width + 1) / 2, height);
914 }
915
916 static void
917 convert_UYVY_Y42B (VideoConvert * convert, GstVideoFrame * dest,
918     const GstVideoFrame * src)
919 {
920   gint width = convert->width;
921   gint height = convert->height;
922
923   video_convert_orc_convert_UYVY_Y42B (FRAME_GET_Y_LINE (dest, 0),
924       FRAME_GET_Y_STRIDE (dest), FRAME_GET_U_LINE (dest, 0),
925       FRAME_GET_U_STRIDE (dest), FRAME_GET_V_LINE (dest, 0),
926       FRAME_GET_V_STRIDE (dest), FRAME_GET_LINE (src, 0),
927       FRAME_GET_STRIDE (src), (width + 1) / 2, height);
928 }
929
930 static void
931 convert_UYVY_Y444 (VideoConvert * convert, GstVideoFrame * dest,
932     const GstVideoFrame * src)
933 {
934   gint width = convert->width;
935   gint height = convert->height;
936
937   video_convert_orc_convert_UYVY_Y444 (FRAME_GET_Y_LINE (dest, 0),
938       FRAME_GET_Y_STRIDE (dest), FRAME_GET_U_LINE (dest, 0),
939       FRAME_GET_U_STRIDE (dest), FRAME_GET_V_LINE (dest, 0),
940       FRAME_GET_V_STRIDE (dest), FRAME_GET_LINE (src, 0),
941       FRAME_GET_STRIDE (src), (width + 1) / 2, height);
942 }
943
944 static void
945 convert_AYUV_I420 (VideoConvert * convert, GstVideoFrame * dest,
946     const GstVideoFrame * src)
947 {
948   gint width = convert->width;
949   gint height = convert->height;
950
951   /* only for even width/height */
952   video_convert_orc_convert_AYUV_I420 (FRAME_GET_Y_LINE (dest, 0),
953       2 * FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (dest, 1),
954       2 * FRAME_GET_Y_STRIDE (dest), FRAME_GET_U_LINE (dest, 0),
955       FRAME_GET_U_STRIDE (dest), FRAME_GET_V_LINE (dest, 0),
956       FRAME_GET_V_STRIDE (dest), FRAME_GET_LINE (src, 0),
957       2 * FRAME_GET_STRIDE (src), FRAME_GET_LINE (src, 1),
958       2 * FRAME_GET_STRIDE (src), width / 2, height / 2);
959 }
960
961 static void
962 convert_AYUV_YUY2 (VideoConvert * convert, GstVideoFrame * dest,
963     const GstVideoFrame * src)
964 {
965   gint width = convert->width;
966   gint height = convert->height;
967
968   /* only for even width */
969   video_convert_orc_convert_AYUV_YUY2 (FRAME_GET_LINE (dest, 0),
970       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
971       FRAME_GET_STRIDE (src), width / 2, height);
972 }
973
974 static void
975 convert_AYUV_UYVY (VideoConvert * convert, GstVideoFrame * dest,
976     const GstVideoFrame * src)
977 {
978   gint width = convert->width;
979   gint height = convert->height;
980
981   /* only for even width */
982   video_convert_orc_convert_AYUV_UYVY (FRAME_GET_LINE (dest, 0),
983       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
984       FRAME_GET_STRIDE (src), width / 2, height);
985 }
986
987 static void
988 convert_AYUV_Y42B (VideoConvert * convert, GstVideoFrame * dest,
989     const GstVideoFrame * src)
990 {
991   gint width = convert->width;
992   gint height = convert->height;
993
994   /* only works for even width */
995   video_convert_orc_convert_AYUV_Y42B (FRAME_GET_Y_LINE (dest, 0),
996       FRAME_GET_Y_STRIDE (dest), FRAME_GET_U_LINE (dest, 0),
997       FRAME_GET_U_STRIDE (dest), FRAME_GET_V_LINE (dest, 0),
998       FRAME_GET_V_STRIDE (dest), FRAME_GET_LINE (src, 0),
999       FRAME_GET_STRIDE (src), width / 2, height);
1000 }
1001
1002 static void
1003 convert_AYUV_Y444 (VideoConvert * convert, GstVideoFrame * dest,
1004     const GstVideoFrame * src)
1005 {
1006   gint width = convert->width;
1007   gint height = convert->height;
1008
1009   video_convert_orc_convert_AYUV_Y444 (FRAME_GET_Y_LINE (dest, 0),
1010       FRAME_GET_Y_STRIDE (dest), FRAME_GET_U_LINE (dest, 0),
1011       FRAME_GET_U_STRIDE (dest), FRAME_GET_V_LINE (dest, 0),
1012       FRAME_GET_V_STRIDE (dest), FRAME_GET_LINE (src, 0),
1013       FRAME_GET_STRIDE (src), width, height);
1014 }
1015
1016 static void
1017 convert_Y42B_I420 (VideoConvert * convert, GstVideoFrame * dest,
1018     const GstVideoFrame * src)
1019 {
1020   gint width = convert->width;
1021   gint height = convert->height;
1022
1023   video_convert_orc_memcpy_2d (FRAME_GET_Y_LINE (dest, 0),
1024       FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
1025       FRAME_GET_Y_STRIDE (src), width, height);
1026
1027   video_convert_orc_planar_chroma_422_420 (FRAME_GET_U_LINE (dest, 0),
1028       FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (src, 0),
1029       2 * FRAME_GET_U_STRIDE (src), FRAME_GET_U_LINE (src, 1),
1030       2 * FRAME_GET_U_STRIDE (src), (width + 1) / 2, height / 2);
1031
1032   video_convert_orc_planar_chroma_422_420 (FRAME_GET_V_LINE (dest, 0),
1033       FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (src, 0),
1034       2 * FRAME_GET_V_STRIDE (src), FRAME_GET_V_LINE (src, 1),
1035       2 * FRAME_GET_V_STRIDE (src), (width + 1) / 2, height / 2);
1036
1037   /* now handle last line */
1038   if (height & 1) {
1039     UNPACK_FRAME (src, convert->tmplines[0], height - 1, width);
1040     PACK_FRAME (dest, convert->tmplines[0], height - 1, width);
1041   }
1042 }
1043
1044 static void
1045 convert_Y42B_Y444 (VideoConvert * convert, GstVideoFrame * dest,
1046     const GstVideoFrame * src)
1047 {
1048   gint width = convert->width;
1049   gint height = convert->height;
1050
1051   video_convert_orc_memcpy_2d (FRAME_GET_Y_LINE (dest, 0),
1052       FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
1053       FRAME_GET_Y_STRIDE (src), width, height);
1054
1055   video_convert_orc_planar_chroma_422_444 (FRAME_GET_U_LINE (dest, 0),
1056       FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (src, 0),
1057       FRAME_GET_U_STRIDE (src), (width + 1) / 2, height);
1058
1059   video_convert_orc_planar_chroma_422_444 (FRAME_GET_V_LINE (dest, 0),
1060       FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (src, 0),
1061       FRAME_GET_V_STRIDE (src), (width + 1) / 2, height);
1062 }
1063
1064 static void
1065 convert_Y42B_YUY2 (VideoConvert * convert, GstVideoFrame * dest,
1066     const GstVideoFrame * src)
1067 {
1068   gint width = convert->width;
1069   gint height = convert->height;
1070
1071   video_convert_orc_convert_Y42B_YUY2 (FRAME_GET_LINE (dest, 0),
1072       FRAME_GET_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
1073       FRAME_GET_Y_STRIDE (src), FRAME_GET_U_LINE (src, 0),
1074       FRAME_GET_U_STRIDE (src), FRAME_GET_V_LINE (src, 0),
1075       FRAME_GET_V_STRIDE (src), (width + 1) / 2, height);
1076 }
1077
1078 static void
1079 convert_Y42B_UYVY (VideoConvert * convert, GstVideoFrame * dest,
1080     const GstVideoFrame * src)
1081 {
1082   gint width = convert->width;
1083   gint height = convert->height;
1084
1085   video_convert_orc_convert_Y42B_UYVY (FRAME_GET_LINE (dest, 0),
1086       FRAME_GET_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
1087       FRAME_GET_Y_STRIDE (src), FRAME_GET_U_LINE (src, 0),
1088       FRAME_GET_U_STRIDE (src), FRAME_GET_V_LINE (src, 0),
1089       FRAME_GET_V_STRIDE (src), (width + 1) / 2, height);
1090 }
1091
1092 static void
1093 convert_Y42B_AYUV (VideoConvert * convert, GstVideoFrame * dest,
1094     const GstVideoFrame * src)
1095 {
1096   gint width = convert->width;
1097   gint height = convert->height;
1098
1099   /* only for even width */
1100   video_convert_orc_convert_Y42B_AYUV (FRAME_GET_LINE (dest, 0),
1101       FRAME_GET_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
1102       FRAME_GET_Y_STRIDE (src), FRAME_GET_U_LINE (src, 0),
1103       FRAME_GET_U_STRIDE (src), FRAME_GET_V_LINE (src, 0),
1104       FRAME_GET_V_STRIDE (src), width / 2, height);
1105 }
1106
1107 static void
1108 convert_Y444_I420 (VideoConvert * convert, GstVideoFrame * dest,
1109     const GstVideoFrame * src)
1110 {
1111   gint width = convert->width;
1112   gint height = convert->height;
1113
1114   video_convert_orc_memcpy_2d (FRAME_GET_Y_LINE (dest, 0),
1115       FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
1116       FRAME_GET_Y_STRIDE (src), width, height);
1117
1118   video_convert_orc_planar_chroma_444_420 (FRAME_GET_U_LINE (dest, 0),
1119       FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (src, 0),
1120       2 * FRAME_GET_U_STRIDE (src), FRAME_GET_U_LINE (src, 1),
1121       2 * FRAME_GET_U_STRIDE (src), width / 2, height / 2);
1122
1123   video_convert_orc_planar_chroma_444_420 (FRAME_GET_V_LINE (dest, 0),
1124       FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (src, 0),
1125       2 * FRAME_GET_V_STRIDE (src), FRAME_GET_V_LINE (src, 1),
1126       2 * FRAME_GET_V_STRIDE (src), width / 2, height / 2);
1127
1128   /* now handle last line */
1129   if (height & 1) {
1130     UNPACK_FRAME (src, convert->tmplines[0], height - 1, width);
1131     PACK_FRAME (dest, convert->tmplines[0], height - 1, width);
1132   }
1133 }
1134
1135 static void
1136 convert_Y444_Y42B (VideoConvert * convert, GstVideoFrame * dest,
1137     const GstVideoFrame * src)
1138 {
1139   gint width = convert->width;
1140   gint height = convert->height;
1141
1142   video_convert_orc_memcpy_2d (FRAME_GET_Y_LINE (dest, 0),
1143       FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
1144       FRAME_GET_Y_STRIDE (src), width, height);
1145
1146   video_convert_orc_planar_chroma_444_422 (FRAME_GET_U_LINE (dest, 0),
1147       FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (src, 0),
1148       FRAME_GET_U_STRIDE (src), width / 2, height);
1149
1150   video_convert_orc_planar_chroma_444_422 (FRAME_GET_V_LINE (dest, 0),
1151       FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (src, 0),
1152       FRAME_GET_V_STRIDE (src), width / 2, height);
1153 }
1154
1155 static void
1156 convert_Y444_YUY2 (VideoConvert * convert, GstVideoFrame * dest,
1157     const GstVideoFrame * src)
1158 {
1159   gint width = convert->width;
1160   gint height = convert->height;
1161
1162   video_convert_orc_convert_Y444_YUY2 (FRAME_GET_LINE (dest, 0),
1163       FRAME_GET_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
1164       FRAME_GET_Y_STRIDE (src), FRAME_GET_U_LINE (src, 0),
1165       FRAME_GET_U_STRIDE (src), FRAME_GET_V_LINE (src, 0),
1166       FRAME_GET_V_STRIDE (src), width / 2, height);
1167 }
1168
1169 static void
1170 convert_Y444_UYVY (VideoConvert * convert, GstVideoFrame * dest,
1171     const GstVideoFrame * src)
1172 {
1173   gint width = convert->width;
1174   gint height = convert->height;
1175
1176   video_convert_orc_convert_Y444_UYVY (FRAME_GET_LINE (dest, 0),
1177       FRAME_GET_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
1178       FRAME_GET_Y_STRIDE (src), FRAME_GET_U_LINE (src, 0),
1179       FRAME_GET_U_STRIDE (src), FRAME_GET_V_LINE (src, 0),
1180       FRAME_GET_V_STRIDE (src), width / 2, height);
1181 }
1182
1183 static void
1184 convert_Y444_AYUV (VideoConvert * convert, GstVideoFrame * dest,
1185     const GstVideoFrame * src)
1186 {
1187   gint width = convert->width;
1188   gint height = convert->height;
1189
1190   video_convert_orc_convert_Y444_AYUV (FRAME_GET_LINE (dest, 0),
1191       FRAME_GET_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
1192       FRAME_GET_Y_STRIDE (src), FRAME_GET_U_LINE (src, 0),
1193       FRAME_GET_U_STRIDE (src), FRAME_GET_V_LINE (src, 0),
1194       FRAME_GET_V_STRIDE (src), width, height);
1195 }
1196
1197 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1198 static void
1199 convert_AYUV_ARGB (VideoConvert * convert, GstVideoFrame * dest,
1200     const GstVideoFrame * src)
1201 {
1202   gint width = convert->width;
1203   gint height = convert->height;
1204
1205   video_convert_orc_convert_AYUV_ARGB (FRAME_GET_LINE (dest, 0),
1206       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
1207       FRAME_GET_STRIDE (src), convert->cmatrix[0][0], convert->cmatrix[0][2],
1208       convert->cmatrix[2][1], convert->cmatrix[1][1], convert->cmatrix[1][2],
1209       width, height);
1210 }
1211
1212 static void
1213 convert_AYUV_BGRA (VideoConvert * convert, GstVideoFrame * dest,
1214     const GstVideoFrame * src)
1215 {
1216   gint width = convert->width;
1217   gint height = convert->height;
1218
1219   video_convert_orc_convert_AYUV_BGRA (FRAME_GET_LINE (dest, 0),
1220       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
1221       FRAME_GET_STRIDE (src), convert->cmatrix[0][0], convert->cmatrix[0][2],
1222       convert->cmatrix[2][1], convert->cmatrix[1][1], convert->cmatrix[1][2],
1223       width, height);
1224 }
1225
1226 static void
1227 convert_AYUV_ABGR (VideoConvert * convert, GstVideoFrame * dest,
1228     const GstVideoFrame * src)
1229 {
1230   gint width = convert->width;
1231   gint height = convert->height;
1232
1233   video_convert_orc_convert_AYUV_ABGR (FRAME_GET_LINE (dest, 0),
1234       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
1235       FRAME_GET_STRIDE (src), convert->cmatrix[0][0], convert->cmatrix[0][2],
1236       convert->cmatrix[2][1], convert->cmatrix[1][1], convert->cmatrix[1][2],
1237       width, height);
1238 }
1239
1240 static void
1241 convert_AYUV_RGBA (VideoConvert * convert, GstVideoFrame * dest,
1242     const GstVideoFrame * src)
1243 {
1244   gint width = convert->width;
1245   gint height = convert->height;
1246
1247   video_convert_orc_convert_AYUV_RGBA (FRAME_GET_LINE (dest, 0),
1248       FRAME_GET_STRIDE (dest), FRAME_GET_LINE (src, 0),
1249       FRAME_GET_STRIDE (src), convert->cmatrix[0][0], convert->cmatrix[0][2],
1250       convert->cmatrix[2][1], convert->cmatrix[1][1], convert->cmatrix[1][2],
1251       width, height);
1252 }
1253
1254 static void
1255 convert_I420_BGRA (VideoConvert * convert, GstVideoFrame * dest,
1256     const GstVideoFrame * src)
1257 {
1258   int i;
1259   gint width = convert->width;
1260   gint height = convert->height;
1261
1262   for (i = 0; i < height; i++) {
1263     video_convert_orc_convert_I420_BGRA (FRAME_GET_LINE (dest, i),
1264         FRAME_GET_Y_LINE (src, i),
1265         FRAME_GET_U_LINE (src, i >> 1), FRAME_GET_V_LINE (src, i >> 1),
1266         convert->cmatrix[0][0], convert->cmatrix[0][2],
1267         convert->cmatrix[2][1], convert->cmatrix[1][1], convert->cmatrix[1][2],
1268         width);
1269   }
1270 }
1271 #endif
1272
1273
1274
1275 /* Fast paths */
1276
1277 typedef struct
1278 {
1279   GstVideoFormat in_format;
1280   GstVideoColorMatrix in_matrix;
1281   GstVideoFormat out_format;
1282   GstVideoColorMatrix out_matrix;
1283   gboolean keeps_color_matrix;
1284   gboolean keeps_interlaced;
1285   gboolean needs_color_matrix;
1286   gint width_align, height_align;
1287   void (*convert) (VideoConvert * convert, GstVideoFrame * dest,
1288       const GstVideoFrame * src);
1289 } VideoTransform;
1290
1291 static const VideoTransform transforms[] = {
1292   {GST_VIDEO_FORMAT_I420, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_YUY2,
1293         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 0, 0,
1294       convert_I420_YUY2},
1295   {GST_VIDEO_FORMAT_I420, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_UYVY,
1296         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 0, 0,
1297       convert_I420_UYVY},
1298   {GST_VIDEO_FORMAT_I420, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_AYUV,
1299         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 0, 0,
1300       convert_I420_AYUV},
1301   {GST_VIDEO_FORMAT_I420, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y42B,
1302         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, FALSE, 0, 0,
1303       convert_I420_Y42B},
1304   {GST_VIDEO_FORMAT_I420, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y444,
1305         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, FALSE, 0, 0,
1306       convert_I420_Y444},
1307
1308   {GST_VIDEO_FORMAT_YV12, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_YUY2,
1309         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 0, 0,
1310       convert_I420_YUY2},
1311   {GST_VIDEO_FORMAT_YV12, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_UYVY,
1312         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 0, 0,
1313       convert_I420_UYVY},
1314   {GST_VIDEO_FORMAT_YV12, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_AYUV,
1315         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 0, 0,
1316       convert_I420_AYUV},
1317   {GST_VIDEO_FORMAT_YV12, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y42B,
1318         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, FALSE, 0, 0,
1319       convert_I420_Y42B},
1320   {GST_VIDEO_FORMAT_YV12, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y444,
1321         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, FALSE, 0, 0,
1322       convert_I420_Y444},
1323
1324   {GST_VIDEO_FORMAT_YUY2, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_I420,
1325         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 0, 0,
1326       convert_YUY2_I420},
1327   {GST_VIDEO_FORMAT_YUY2, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_YV12,
1328         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 0, 0,
1329       convert_YUY2_I420},
1330   {GST_VIDEO_FORMAT_YUY2, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_UYVY,
1331       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 0, 0, convert_UYVY_YUY2},      /* alias */
1332   {GST_VIDEO_FORMAT_YUY2, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_AYUV,
1333         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 0, 0,
1334       convert_YUY2_AYUV},
1335   {GST_VIDEO_FORMAT_YUY2, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y42B,
1336         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 0, 0,
1337       convert_YUY2_Y42B},
1338   {GST_VIDEO_FORMAT_YUY2, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y444,
1339         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 0, 0,
1340       convert_YUY2_Y444},
1341
1342   {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_I420,
1343         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 0, 0,
1344       convert_UYVY_I420},
1345   {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_YV12,
1346         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 0, 0,
1347       convert_UYVY_I420},
1348   {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_YUY2,
1349         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 0, 0,
1350       convert_UYVY_YUY2},
1351   {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_AYUV,
1352         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 0, 0,
1353       convert_UYVY_AYUV},
1354   {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y42B,
1355         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 0, 0,
1356       convert_UYVY_Y42B},
1357   {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y444,
1358         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 0, 0,
1359       convert_UYVY_Y444},
1360
1361   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_I420,
1362         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, FALSE, 1, 1,
1363       convert_AYUV_I420},
1364   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_YV12,
1365         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, FALSE, 1, 1,
1366       convert_AYUV_I420},
1367   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_YUY2,
1368         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 1, 0,
1369       convert_AYUV_YUY2},
1370   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_UYVY,
1371         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 1, 0,
1372       convert_AYUV_UYVY},
1373   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y42B,
1374         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 1, 0,
1375       convert_AYUV_Y42B},
1376   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y444,
1377         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 0, 0,
1378       convert_AYUV_Y444},
1379
1380   {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_I420,
1381         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, FALSE, 0, 0,
1382       convert_Y42B_I420},
1383   {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_YV12,
1384         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, FALSE, 0, 0,
1385       convert_Y42B_I420},
1386   {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_YUY2,
1387         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 0, 0,
1388       convert_Y42B_YUY2},
1389   {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_UYVY,
1390         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 0, 0,
1391       convert_Y42B_UYVY},
1392   {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_AYUV,
1393         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 1, 0,
1394       convert_Y42B_AYUV},
1395   {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y444,
1396         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 0, 0,
1397       convert_Y42B_Y444},
1398
1399   {GST_VIDEO_FORMAT_Y444, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_I420,
1400         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, FALSE, 1, 0,
1401       convert_Y444_I420},
1402   {GST_VIDEO_FORMAT_Y444, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_YV12,
1403         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, FALSE, 1, 0,
1404       convert_Y444_I420},
1405   {GST_VIDEO_FORMAT_Y444, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_YUY2,
1406         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 1, 0,
1407       convert_Y444_YUY2},
1408   {GST_VIDEO_FORMAT_Y444, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_UYVY,
1409         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 1, 0,
1410       convert_Y444_UYVY},
1411   {GST_VIDEO_FORMAT_Y444, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_AYUV,
1412         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 0, 0,
1413       convert_Y444_AYUV},
1414   {GST_VIDEO_FORMAT_Y444, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_Y42B,
1415         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, FALSE, 1, 0,
1416       convert_Y444_Y42B},
1417
1418 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1419   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_ARGB,
1420         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, TRUE, 0, 0,
1421       convert_AYUV_ARGB},
1422   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_BGRA,
1423         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, TRUE, 0, 0,
1424       convert_AYUV_BGRA},
1425   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_xRGB,
1426       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, TRUE, 0, 0, convert_AYUV_ARGB},       /* alias */
1427   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_BGRx,
1428       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, TRUE, 0, 0, convert_AYUV_BGRA},       /* alias */
1429   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_ABGR,
1430         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, TRUE, 0, 0,
1431       convert_AYUV_ABGR},
1432   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_RGBA,
1433         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, TRUE, 0, 0,
1434       convert_AYUV_RGBA},
1435   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_xBGR,
1436       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, TRUE, 0, 0, convert_AYUV_ABGR},       /* alias */
1437   {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_RGBx,
1438       GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, TRUE, TRUE, 0, 0, convert_AYUV_RGBA},       /* alias */
1439
1440   {GST_VIDEO_FORMAT_I420, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_BGRA,
1441         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, TRUE, 0, 0,
1442       convert_I420_BGRA},
1443   {GST_VIDEO_FORMAT_I420, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_BGRx,
1444         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, TRUE, 0, 0,
1445       convert_I420_BGRA},
1446   {GST_VIDEO_FORMAT_YV12, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_BGRA,
1447         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, TRUE, 0, 0,
1448       convert_I420_BGRA},
1449   {GST_VIDEO_FORMAT_YV12, GST_VIDEO_COLOR_MATRIX_UNKNOWN, GST_VIDEO_FORMAT_BGRx,
1450         GST_VIDEO_COLOR_MATRIX_UNKNOWN, TRUE, FALSE, TRUE, 0, 0,
1451       convert_I420_BGRA},
1452 #endif
1453 };
1454
1455 static gboolean
1456 videoconvert_convert_lookup_fastpath (VideoConvert * convert)
1457 {
1458   int i;
1459   GstVideoFormat in_format, out_format;
1460   GstVideoColorMatrix in_matrix, out_matrix;
1461   gboolean interlaced;
1462   gint width, height;
1463
1464   in_format = GST_VIDEO_INFO_FORMAT (&convert->in_info);
1465   out_format = GST_VIDEO_INFO_FORMAT (&convert->out_info);
1466
1467   width = GST_VIDEO_INFO_WIDTH (&convert->in_info);
1468   height = GST_VIDEO_INFO_HEIGHT (&convert->in_info);
1469
1470   in_matrix = convert->in_info.colorimetry.matrix;
1471   out_matrix = convert->out_info.colorimetry.matrix;
1472
1473   interlaced = GST_VIDEO_INFO_IS_INTERLACED (&convert->in_info);
1474   interlaced |= GST_VIDEO_INFO_IS_INTERLACED (&convert->out_info);
1475
1476   for (i = 0; i < sizeof (transforms) / sizeof (transforms[0]); i++) {
1477     if (transforms[i].in_format == in_format &&
1478         transforms[i].out_format == out_format &&
1479         (transforms[i].keeps_color_matrix ||
1480             (transforms[i].in_matrix == in_matrix &&
1481                 transforms[i].out_matrix == out_matrix)) &&
1482         (transforms[i].keeps_interlaced || !interlaced) &&
1483         (transforms[i].width_align & width) == 0 &&
1484         (transforms[i].height_align & height) == 0) {
1485       GST_DEBUG ("using fastpath");
1486       if (transforms[i].needs_color_matrix)
1487         if (!videoconvert_convert_compute_matrix (convert))
1488           goto no_convert;
1489       convert->convert = transforms[i].convert;
1490       alloc_tmplines (convert, 1, GST_VIDEO_INFO_WIDTH (&convert->in_info));
1491       return TRUE;
1492     }
1493   }
1494   GST_DEBUG ("no fastpath found");
1495   return FALSE;
1496
1497 no_convert:
1498   {
1499     GST_DEBUG ("can't create matrix");
1500     return FALSE;
1501   }
1502 }