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