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