video: add Y210 pixel format.
[platform/upstream/gstreamer.git] / gst-libs / gst / video / video-format.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Library       <2002> Ronald Bultje <rbultje@ronald.bitfreak.net>
4  * Copyright (C) 2007 David A. Schleef <ds@schleef.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #  include "config.h"
24 #endif
25
26 #include <string.h>
27 #include <stdio.h>
28
29 #include "video-format.h"
30 #include "video-orc.h"
31
32 #ifndef restrict
33 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
34 /* restrict should be available */
35 #elif defined(__GNUC__) && __GNUC__ >= 4
36 #define restrict __restrict__
37 #elif defined(_MSC_VER) &&  _MSC_VER >= 1500
38 #define restrict __restrict
39 #else
40 #define restrict                /* no op */
41 #endif
42 #endif
43
44 /* Line conversion to AYUV */
45
46 #define GET_PLANE_STRIDE(plane) (stride(plane))
47 #define GET_PLANE_LINE(plane, line) \
48   (gpointer)(((guint8*)(data[plane])) + stride[plane] * (line))
49
50 #define GET_COMP_STRIDE(comp) \
51   GST_VIDEO_FORMAT_INFO_STRIDE (info, stride, comp)
52 #define GET_COMP_DATA(comp) \
53   GST_VIDEO_FORMAT_INFO_DATA (info, data, comp)
54
55 #define GET_COMP_LINE(comp, line) \
56   (gpointer)(((guint8*)GET_COMP_DATA (comp)) + \
57       GET_COMP_STRIDE(comp) * (line))
58
59 #define GET_LINE(line)               GET_PLANE_LINE (0, line)
60
61 #define GET_Y_LINE(line)             GET_COMP_LINE(GST_VIDEO_COMP_Y, line)
62 #define GET_U_LINE(line)             GET_COMP_LINE(GST_VIDEO_COMP_U, line)
63 #define GET_V_LINE(line)             GET_COMP_LINE(GST_VIDEO_COMP_V, line)
64
65 #define GET_R_LINE(line)             GET_COMP_LINE(GST_VIDEO_COMP_R, line)
66 #define GET_G_LINE(line)             GET_COMP_LINE(GST_VIDEO_COMP_G, line)
67 #define GET_B_LINE(line)             GET_COMP_LINE(GST_VIDEO_COMP_B, line)
68
69 #define GET_A_LINE(line)             GET_COMP_LINE(GST_VIDEO_COMP_A, line)
70
71 #define GET_UV_420(line, flags)                 \
72   (flags & GST_VIDEO_PACK_FLAG_INTERLACED ?     \
73    ((line & ~3) >> 1) + (line & 1) :            \
74    line >> 1)
75 #define GET_UV_410(line, flags)                 \
76   (flags & GST_VIDEO_PACK_FLAG_INTERLACED ?     \
77    ((line & ~7) >> 2) + (line & 1) :            \
78    line >> 2)
79
80 #define IS_CHROMA_LINE_420(line, flags)         \
81   (flags & GST_VIDEO_PACK_FLAG_INTERLACED ?     \
82    !(line & 2) : !(line & 1))
83 #define IS_CHROMA_LINE_410(line, flags)         \
84   (flags & GST_VIDEO_PACK_FLAG_INTERLACED ?     \
85    !(line & 6) : !(line & 3))
86
87 #define IS_ALIGNED(x,n) ((((guintptr)(x)&((n)-1))) == 0)
88
89 #define PACK_420 GST_VIDEO_FORMAT_AYUV, unpack_planar_420, 1, pack_planar_420
90 static void
91 unpack_planar_420 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
92     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
93     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
94 {
95   gint uv = GET_UV_420 (y, flags);
96   const guint8 *restrict sy = GET_Y_LINE (y);
97   const guint8 *restrict su = GET_U_LINE (uv);
98   const guint8 *restrict sv = GET_V_LINE (uv);
99   guint8 *restrict d = dest;
100
101   sy += x;
102   su += x >> 1;
103   sv += x >> 1;
104
105   if (x & 1) {
106     d[0] = 0xff;
107     d[1] = *sy++;
108     d[2] = *su++;
109     d[3] = *sv++;
110     width--;
111     d += 4;
112   }
113   video_orc_unpack_I420 (d, sy, su, sv, width);
114 }
115
116 static void
117 pack_planar_420 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
118     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
119     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
120     gint y, gint width)
121 {
122   gint uv = GET_UV_420 (y, flags);
123   guint8 *dy = GET_Y_LINE (y);
124   guint8 *du = GET_U_LINE (uv);
125   guint8 *dv = GET_V_LINE (uv);
126   const guint8 *s = src;
127
128   if (IS_CHROMA_LINE_420 (y, flags)) {
129     if (IS_ALIGNED (s, 8))
130       video_orc_pack_I420 (dy, du, dv, s, width / 2);
131     else {
132       gint i;
133
134       for (i = 0; i < width / 2; i++) {
135         dy[i * 2 + 0] = s[i * 8 + 1];
136         dy[i * 2 + 1] = s[i * 8 + 5];
137         du[i] = s[i * 8 + 2];
138         dv[i] = s[i * 8 + 3];
139       }
140     }
141     if (width & 1) {
142       gint i = width - 1;
143
144       dy[i] = s[i * 4 + 1];
145       du[i >> 1] = s[i * 4 + 2];
146       dv[i >> 1] = s[i * 4 + 3];
147     }
148   } else
149     video_orc_pack_Y (dy, s, width);
150 }
151
152 #define PACK_YUY2 GST_VIDEO_FORMAT_AYUV, unpack_YUY2, 1, pack_YUY2
153 static void
154 unpack_YUY2 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
155     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
156     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
157 {
158   const guint8 *restrict s = GET_LINE (y);
159   guint8 *restrict d = dest;
160
161   s += (x & ~1) << 1;
162   if (x & 1) {
163     d[0] = 0xff;
164     d[1] = s[2];
165     d[2] = s[1];
166     d[3] = s[3];
167     s += 4;
168     d += 4;
169     width--;
170   }
171
172   if (IS_ALIGNED (d, 8))
173     video_orc_unpack_YUY2 (d, s, width / 2);
174   else {
175     gint i;
176
177     for (i = 0; i < width / 2; i++) {
178       d[i * 8 + 0] = 0xff;
179       d[i * 8 + 1] = s[i * 4 + 0];
180       d[i * 8 + 2] = s[i * 4 + 1];
181       d[i * 8 + 3] = s[i * 4 + 3];
182       d[i * 8 + 4] = 0xff;
183       d[i * 8 + 5] = s[i * 4 + 2];
184       d[i * 8 + 6] = s[i * 4 + 1];
185       d[i * 8 + 7] = s[i * 4 + 3];
186     }
187   }
188
189   if (width & 1) {
190     gint i = width - 1;
191
192     d[i * 4 + 0] = 0xff;
193     d[i * 4 + 1] = s[i * 2 + 0];
194     d[i * 4 + 2] = s[i * 2 + 1];
195     d[i * 4 + 3] = s[i * 2 + 3];
196   }
197 }
198
199 static void
200 pack_YUY2 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
201     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
202     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
203     gint y, gint width)
204 {
205   guint8 *restrict d = GET_LINE (y);
206   const guint8 *restrict s = src;
207
208   if (IS_ALIGNED (s, 8))
209     video_orc_pack_YUY2 (d, s, width / 2);
210   else {
211     gint i;
212     for (i = 0; i < width / 2; i++) {
213       d[i * 4 + 0] = s[i * 8 + 1];
214       d[i * 4 + 1] = s[i * 8 + 2];
215       d[i * 4 + 2] = s[i * 8 + 5];
216       d[i * 4 + 3] = s[i * 8 + 3];
217     }
218   }
219
220   if (width & 1) {
221     gint i = width - 1;
222
223     d[i * 2 + 0] = s[i * 4 + 1];
224     d[i * 2 + 1] = s[i * 4 + 2];
225     d[i * 2 + 3] = s[i * 4 + 3];
226   }
227 }
228
229 #define PACK_UYVY GST_VIDEO_FORMAT_AYUV, unpack_UYVY, 1, pack_UYVY
230 static void
231 unpack_UYVY (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
232     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
233     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
234 {
235   const guint8 *s = GET_LINE (y);
236   guint8 *d = dest;
237
238   s += (x & ~1) << 1;
239   if (x & 1) {
240     d[0] = 0xff;
241     d[1] = s[3];
242     d[2] = s[0];
243     d[3] = s[2];
244     s += 4;
245     d += 4;
246     width--;
247   }
248
249   if (IS_ALIGNED (d, 8))
250     video_orc_unpack_UYVY (d, s, width / 2);
251   else {
252     gint i;
253
254     for (i = 0; i < width / 2; i++) {
255       d[i * 8 + 0] = 0xff;
256       d[i * 8 + 1] = s[i * 4 + 1];
257       d[i * 8 + 2] = s[i * 4 + 0];
258       d[i * 8 + 3] = s[i * 4 + 2];
259       d[i * 8 + 4] = 0xff;
260       d[i * 8 + 5] = s[i * 4 + 3];
261       d[i * 8 + 6] = s[i * 4 + 0];
262       d[i * 8 + 7] = s[i * 4 + 2];
263     }
264   }
265
266   if (width & 1) {
267     gint i = width - 1;
268
269     d[i * 4 + 0] = 0xff;
270     d[i * 4 + 1] = s[i * 2 + 1];
271     d[i * 4 + 2] = s[i * 2 + 0];
272     d[i * 4 + 3] = s[i * 2 + 2];
273   }
274 }
275
276 static void
277 pack_UYVY (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
278     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
279     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
280     gint y, gint width)
281 {
282   guint8 *restrict d = GET_LINE (y);
283   const guint8 *restrict s = src;
284
285   if (IS_ALIGNED (s, 8))
286     video_orc_pack_UYVY (d, s, width / 2);
287   else {
288     gint i;
289     for (i = 0; i < width / 2; i++) {
290       d[i * 4 + 0] = s[i * 8 + 2];
291       d[i * 4 + 1] = s[i * 8 + 1];
292       d[i * 4 + 2] = s[i * 8 + 3];
293       d[i * 4 + 3] = s[i * 8 + 5];
294     }
295   }
296   if (width & 1) {
297     gint i = width - 1;
298
299     d[i * 2 + 0] = s[i * 4 + 2];
300     d[i * 2 + 1] = s[i * 4 + 1];
301     d[i * 2 + 2] = s[i * 4 + 3];
302   }
303 }
304
305 #define PACK_VYUY GST_VIDEO_FORMAT_AYUV, unpack_VYUY, 1, pack_VYUY
306 static void
307 unpack_VYUY (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
308     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
309     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
310 {
311   const guint8 *s = GET_LINE (y);
312   guint8 *d = dest;
313
314   s += (x & ~1) << 1;
315   if (x & 1) {
316     d[0] = 0xff;
317     d[1] = s[3];
318     d[2] = s[0];
319     d[3] = s[2];
320     s += 4;
321     d += 4;
322     width--;
323   }
324
325   if (IS_ALIGNED (d, 8))
326     video_orc_unpack_VYUY (d, s, width / 2);
327   else {
328     gint i;
329
330     for (i = 0; i < width / 2; i++) {
331       d[i * 8 + 0] = 0xff;
332       d[i * 8 + 1] = s[i * 4 + 1];
333       d[i * 8 + 2] = s[i * 4 + 0];
334       d[i * 8 + 3] = s[i * 4 + 2];
335       d[i * 8 + 4] = 0xff;
336       d[i * 8 + 5] = s[i * 4 + 3];
337       d[i * 8 + 6] = s[i * 4 + 0];
338       d[i * 8 + 7] = s[i * 4 + 2];
339     }
340   }
341
342   if (width & 1) {
343     gint i = width - 1;
344
345     d[i * 4 + 0] = 0xff;
346     d[i * 4 + 1] = s[i * 2 + 1];
347     d[i * 4 + 2] = s[i * 2 + 0];
348     d[i * 4 + 3] = s[i * 2 + 2];
349   }
350 }
351
352 static void
353 pack_VYUY (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
354     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
355     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
356     gint y, gint width)
357 {
358   guint8 *restrict d = GET_LINE (y);
359   const guint8 *restrict s = src;
360
361   if (IS_ALIGNED (s, 8))
362     video_orc_pack_VYUY (d, s, width / 2);
363   else {
364     gint i;
365     for (i = 0; i < width / 2; i++) {
366       d[i * 4 + 0] = s[i * 8 + 2];
367       d[i * 4 + 1] = s[i * 8 + 1];
368       d[i * 4 + 2] = s[i * 8 + 3];
369       d[i * 4 + 3] = s[i * 8 + 5];
370     }
371   }
372   if (width & 1) {
373     gint i = width - 1;
374
375     d[i * 2 + 0] = s[i * 4 + 2];
376     d[i * 2 + 1] = s[i * 4 + 1];
377     d[i * 2 + 2] = s[i * 4 + 3];
378   }
379 }
380
381 #define PACK_YVYU GST_VIDEO_FORMAT_AYUV, unpack_YVYU, 1, pack_YVYU
382 static void
383 unpack_YVYU (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
384     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
385     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
386 {
387   const guint8 *restrict s = GET_LINE (y);
388   guint8 *restrict d = dest;
389
390   s += (x & ~1) << 1;
391   if (x & 1) {
392     d[0] = 0xff;
393     d[1] = s[2];
394     d[2] = s[3];
395     d[3] = s[1];
396     s += 4;
397     d += 4;
398     width--;
399   }
400
401   if (IS_ALIGNED (d, 8))
402     video_orc_unpack_YVYU (d, s, width / 2);
403   else {
404     gint i;
405
406     for (i = 0; i < width / 2; i++) {
407       d[i * 8 + 0] = 0xff;
408       d[i * 8 + 1] = s[i * 4 + 0];
409       d[i * 8 + 2] = s[i * 4 + 3];
410       d[i * 8 + 3] = s[i * 4 + 1];
411       d[i * 8 + 4] = 0xff;
412       d[i * 8 + 5] = s[i * 4 + 2];
413       d[i * 8 + 6] = s[i * 4 + 3];
414       d[i * 8 + 7] = s[i * 4 + 1];
415     }
416   }
417
418   if (width & 1) {
419     gint i = width - 1;
420
421     d[i * 4 + 0] = 0xff;
422     d[i * 4 + 1] = s[i * 2 + 0];
423     d[i * 4 + 2] = s[i * 2 + 3];
424     d[i * 4 + 3] = s[i * 2 + 1];
425   }
426 }
427
428 static void
429 pack_YVYU (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
430     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
431     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
432     gint y, gint width)
433 {
434   guint8 *restrict d = GET_LINE (y);
435   const guint8 *restrict s = src;
436
437   if (IS_ALIGNED (s, 8))
438     video_orc_pack_YVYU (d, s, width / 2);
439   else {
440     gint i;
441     for (i = 0; i < width / 2; i++) {
442       d[i * 4 + 0] = s[i * 8 + 1];
443       d[i * 4 + 1] = s[i * 8 + 3];
444       d[i * 4 + 2] = s[i * 8 + 5];
445       d[i * 4 + 3] = s[i * 8 + 2];
446     }
447   }
448
449   if (width & 1) {
450     gint i = width - 1;
451
452     d[i * 2 + 0] = s[i * 4 + 1];
453     d[i * 2 + 1] = s[i * 4 + 3];
454     d[i * 2 + 3] = s[i * 4 + 2];
455   }
456 }
457
458 #define PACK_v308 GST_VIDEO_FORMAT_AYUV, unpack_v308, 1, pack_v308
459 static void
460 unpack_v308 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
461     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
462     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
463 {
464   int i;
465   const guint8 *restrict s = GET_LINE (y);
466   guint8 *restrict d = dest;
467
468   s += x * 3;
469
470   for (i = 0; i < width; i++) {
471     d[i * 4 + 0] = 0xff;
472     d[i * 4 + 1] = s[i * 3 + 0];
473     d[i * 4 + 2] = s[i * 3 + 1];
474     d[i * 4 + 3] = s[i * 3 + 2];
475   }
476 }
477
478 static void
479 pack_v308 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
480     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
481     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
482     gint y, gint width)
483 {
484   int i;
485   guint8 *restrict d = GET_LINE (y);
486   const guint8 *restrict s = src;
487
488   for (i = 0; i < width; i++) {
489     d[i * 3 + 0] = s[i * 4 + 1];
490     d[i * 3 + 1] = s[i * 4 + 2];
491     d[i * 3 + 2] = s[i * 4 + 3];
492   }
493 }
494
495 #define PACK_IYU2 GST_VIDEO_FORMAT_AYUV, unpack_IYU2, 1, pack_IYU2
496 static void
497 unpack_IYU2 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
498     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
499     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
500 {
501   int i;
502   const guint8 *restrict s = GET_LINE (y);
503   guint8 *restrict d = dest;
504
505   s += x * 3;
506
507   for (i = 0; i < width; i++) {
508     d[i * 4 + 0] = 0xff;
509     d[i * 4 + 1] = s[i * 3 + 1];
510     d[i * 4 + 2] = s[i * 3 + 0];
511     d[i * 4 + 3] = s[i * 3 + 2];
512   }
513 }
514
515 static void
516 pack_IYU2 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
517     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
518     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
519     gint y, gint width)
520 {
521   int i;
522   guint8 *restrict d = GET_LINE (y);
523   const guint8 *restrict s = src;
524
525   for (i = 0; i < width; i++) {
526     d[i * 3 + 0] = s[i * 4 + 2];
527     d[i * 3 + 1] = s[i * 4 + 1];
528     d[i * 3 + 2] = s[i * 4 + 3];
529   }
530 }
531
532 #define PACK_AYUV GST_VIDEO_FORMAT_AYUV, unpack_copy4, 1, pack_copy4
533 #define PACK_ARGB GST_VIDEO_FORMAT_ARGB, unpack_copy4, 1, pack_copy4
534 static void
535 unpack_copy4 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
536     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
537     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
538 {
539   const guint8 *restrict s = GET_LINE (y);
540
541   s += x * 4;
542
543   memcpy (dest, s, width * 4);
544 }
545
546 static void
547 pack_copy4 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
548     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
549     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
550     gint y, gint width)
551 {
552   guint8 *restrict d = GET_LINE (y);
553
554   memcpy (d, src, width * 4);
555 }
556
557 #define PACK_v210 GST_VIDEO_FORMAT_AYUV64, unpack_v210, 1, pack_v210
558 static void
559 unpack_v210 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
560     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
561     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
562 {
563   int i;
564   const guint8 *restrict s = GET_LINE (y);
565   guint16 *restrict d = dest;
566   guint32 a0, a1, a2, a3;
567   guint16 y0, y1, y2, y3, y4, y5;
568   guint16 u0, u2, u4;
569   guint16 v0, v2, v4;
570
571   /* FIXME */
572   s += x * 2;
573
574   for (i = 0; i < width; i += 6) {
575     a0 = GST_READ_UINT32_LE (s + (i / 6) * 16 + 0);
576     a1 = GST_READ_UINT32_LE (s + (i / 6) * 16 + 4);
577     a2 = GST_READ_UINT32_LE (s + (i / 6) * 16 + 8);
578     a3 = GST_READ_UINT32_LE (s + (i / 6) * 16 + 12);
579
580     u0 = ((a0 >> 0) & 0x3ff) << 6;
581     y0 = ((a0 >> 10) & 0x3ff) << 6;
582     v0 = ((a0 >> 20) & 0x3ff) << 6;
583     y1 = ((a1 >> 0) & 0x3ff) << 6;
584
585     u2 = ((a1 >> 10) & 0x3ff) << 6;
586     y2 = ((a1 >> 20) & 0x3ff) << 6;
587     v2 = ((a2 >> 0) & 0x3ff) << 6;
588     y3 = ((a2 >> 10) & 0x3ff) << 6;
589
590     u4 = ((a2 >> 20) & 0x3ff) << 6;
591     y4 = ((a3 >> 0) & 0x3ff) << 6;
592     v4 = ((a3 >> 10) & 0x3ff) << 6;
593     y5 = ((a3 >> 20) & 0x3ff) << 6;
594
595     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
596       y0 |= (y0 >> 10);
597       y1 |= (y1 >> 10);
598       u0 |= (u0 >> 10);
599       v0 |= (v0 >> 10);
600
601       y2 |= (y2 >> 10);
602       y3 |= (y3 >> 10);
603       u2 |= (u2 >> 10);
604       v2 |= (v2 >> 10);
605
606       y4 |= (y4 >> 10);
607       y5 |= (y5 >> 10);
608       u4 |= (u4 >> 10);
609       v4 |= (v4 >> 10);
610     }
611
612     d[4 * (i + 0) + 0] = 0xffff;
613     d[4 * (i + 0) + 1] = y0;
614     d[4 * (i + 0) + 2] = u0;
615     d[4 * (i + 0) + 3] = v0;
616
617     if (i < width - 1) {
618       d[4 * (i + 1) + 0] = 0xffff;
619       d[4 * (i + 1) + 1] = y1;
620       d[4 * (i + 1) + 2] = u0;
621       d[4 * (i + 1) + 3] = v0;
622     }
623     if (i < width - 2) {
624       d[4 * (i + 2) + 0] = 0xffff;
625       d[4 * (i + 2) + 1] = y2;
626       d[4 * (i + 2) + 2] = u2;
627       d[4 * (i + 2) + 3] = v2;
628     }
629     if (i < width - 3) {
630       d[4 * (i + 3) + 0] = 0xffff;
631       d[4 * (i + 3) + 1] = y3;
632       d[4 * (i + 3) + 2] = u2;
633       d[4 * (i + 3) + 3] = v2;
634     }
635     if (i < width - 4) {
636       d[4 * (i + 4) + 0] = 0xffff;
637       d[4 * (i + 4) + 1] = y4;
638       d[4 * (i + 4) + 2] = u4;
639       d[4 * (i + 4) + 3] = v4;
640     }
641     if (i < width - 5) {
642       d[4 * (i + 5) + 0] = 0xffff;
643       d[4 * (i + 5) + 1] = y5;
644       d[4 * (i + 5) + 2] = u4;
645       d[4 * (i + 5) + 3] = v4;
646     }
647   }
648 }
649
650 static void
651 pack_v210 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
652     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
653     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
654     gint y, gint width)
655 {
656   int i;
657   guint8 *restrict d = GET_LINE (y);
658   const guint16 *restrict s = src;
659   guint32 a0, a1, a2, a3;
660   guint16 y0, y1, y2, y3, y4, y5;
661   guint16 u0, u1, u2;
662   guint16 v0, v1, v2;
663
664   for (i = 0; i < width - 5; i += 6) {
665     y0 = s[4 * (i + 0) + 1] >> 6;
666     y1 = s[4 * (i + 1) + 1] >> 6;
667     y2 = s[4 * (i + 2) + 1] >> 6;
668     y3 = s[4 * (i + 3) + 1] >> 6;
669     y4 = s[4 * (i + 4) + 1] >> 6;
670     y5 = s[4 * (i + 5) + 1] >> 6;
671
672     u0 = s[4 * (i + 0) + 2] >> 6;
673     u1 = s[4 * (i + 2) + 2] >> 6;
674     u2 = s[4 * (i + 4) + 2] >> 6;
675
676     v0 = s[4 * (i + 0) + 3] >> 6;
677     v1 = s[4 * (i + 2) + 3] >> 6;
678     v2 = s[4 * (i + 4) + 3] >> 6;
679
680     a0 = u0 | (y0 << 10) | (v0 << 20);
681     a1 = y1 | (u1 << 10) | (y2 << 20);
682     a2 = v1 | (y3 << 10) | (u2 << 20);
683     a3 = y4 | (v2 << 10) | (y5 << 20);
684
685     GST_WRITE_UINT32_LE (d + (i / 6) * 16 + 0, a0);
686     GST_WRITE_UINT32_LE (d + (i / 6) * 16 + 4, a1);
687     GST_WRITE_UINT32_LE (d + (i / 6) * 16 + 8, a2);
688     GST_WRITE_UINT32_LE (d + (i / 6) * 16 + 12, a3);
689   }
690   if (i < width) {
691     y0 = s[4 * (i + 0) + 1] >> 6;
692     u0 = s[4 * (i + 0) + 2] >> 6;
693     v0 = s[4 * (i + 0) + 3] >> 6;
694     if (i < width - 1)
695       y1 = s[4 * (i + 1) + 1] >> 6;
696     else
697       y1 = y0;
698     if (i < width - 2) {
699       y2 = s[4 * (i + 2) + 1] >> 6;
700       u1 = s[4 * (i + 2) + 2] >> 6;
701       v1 = s[4 * (i + 2) + 3] >> 6;
702     } else {
703       y2 = y1;
704       u1 = u0;
705       v1 = v0;
706     }
707     if (i < width - 3)
708       y3 = s[4 * (i + 3) + 1] >> 6;
709     else
710       y3 = y2;
711     if (i < width - 4) {
712       y4 = s[4 * (i + 4) + 1] >> 6;
713       u2 = s[4 * (i + 4) + 2] >> 6;
714       v2 = s[4 * (i + 4) + 3] >> 6;
715     } else {
716       y4 = y3;
717       u2 = u1;
718       v2 = v1;
719     }
720     y5 = y4;
721
722     a0 = u0 | (y0 << 10) | (v0 << 20);
723     a1 = y1 | (u1 << 10) | (y2 << 20);
724     a2 = v1 | (y3 << 10) | (u2 << 20);
725     a3 = y4 | (v2 << 10) | (y5 << 20);
726
727     GST_WRITE_UINT32_LE (d + (i / 6) * 16 + 0, a0);
728     GST_WRITE_UINT32_LE (d + (i / 6) * 16 + 4, a1);
729     GST_WRITE_UINT32_LE (d + (i / 6) * 16 + 8, a2);
730     GST_WRITE_UINT32_LE (d + (i / 6) * 16 + 12, a3);
731   }
732 }
733
734 #define PACK_v216 GST_VIDEO_FORMAT_AYUV64, unpack_v216, 1, pack_v216
735 static void
736 unpack_v216 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
737     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
738     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
739 {
740   int i;
741   const guint8 *restrict s = GET_LINE (y);
742   guint16 *restrict d = dest;
743
744   s += (x & ~1) << 2;
745   if (x & 1) {
746     d[0] = 0xffff;
747     d[1] = GST_READ_UINT16_LE (s + 6);
748     d[2] = GST_READ_UINT16_LE (s + 0);
749     d[3] = GST_READ_UINT16_LE (s + 4);
750     s += 8;
751     d += 4;
752     width--;
753   }
754
755   for (i = 0; i < width; i++) {
756     d[i * 4 + 0] = 0xffff;
757     d[i * 4 + 1] = GST_READ_UINT16_LE (s + i * 4 + 2);
758     d[i * 4 + 2] = GST_READ_UINT16_LE (s + (i >> 1) * 8 + 0);
759     d[i * 4 + 3] = GST_READ_UINT16_LE (s + (i >> 1) * 8 + 4);
760   }
761 }
762
763 static void
764 pack_v216 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
765     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
766     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
767     gint y, gint width)
768 {
769   int i;
770   guint8 *restrict d = GET_LINE (y);
771   const guint16 *restrict s = src;
772
773   for (i = 0; i < width - 1; i += 2) {
774     GST_WRITE_UINT16_LE (d + i * 4 + 0, s[(i + 0) * 4 + 2]);
775     GST_WRITE_UINT16_LE (d + i * 4 + 2, s[(i + 0) * 4 + 1]);
776     GST_WRITE_UINT16_LE (d + i * 4 + 4, s[(i + 0) * 4 + 3]);
777     GST_WRITE_UINT16_LE (d + i * 4 + 6, s[(i + 1) * 4 + 1]);
778   }
779   if (i == width - 1) {
780     GST_WRITE_UINT16_LE (d + i * 4 + 0, s[i * 4 + 2]);
781     GST_WRITE_UINT16_LE (d + i * 4 + 2, s[i * 4 + 1]);
782     GST_WRITE_UINT16_LE (d + i * 4 + 4, s[i * 4 + 3]);
783     GST_WRITE_UINT16_LE (d + i * 4 + 6, s[i * 4 + 1]);
784   }
785 }
786
787 #define PACK_Y210 GST_VIDEO_FORMAT_AYUV64, unpack_Y210, 1, pack_Y210
788 static void
789 unpack_Y210 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
790     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
791     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
792 {
793   int i;
794   const guint8 *restrict s = GET_LINE (y);
795   guint16 *restrict d = dest;
796   guint Y0, Y1, U, V;
797
798   for (i = 0; i < width / 2; i++) {
799     Y0 = GST_READ_UINT16_LE (s + i * 8 + 0);
800     U = GST_READ_UINT16_LE (s + i * 8 + 2);
801     V = GST_READ_UINT16_LE (s + i * 8 + 6);
802     Y1 = GST_READ_UINT16_LE (s + i * 8 + 4);
803
804     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
805       Y0 |= (Y0 >> 10);
806       U |= (U >> 10);
807       V |= (V >> 10);
808     }
809
810     d[i * 8 + 0] = 0xffff;
811     d[i * 8 + 1] = Y0;
812     d[i * 8 + 2] = U;
813     d[i * 8 + 3] = V;
814
815     d[i * 8 + 4] = 0xffff;
816     d[i * 8 + 5] = Y1;
817     d[i * 8 + 6] = U;
818     d[i * 8 + 7] = V;
819   }
820 }
821
822 static void
823 pack_Y210 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
824     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
825     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
826     gint y, gint width)
827 {
828   int i;
829   guint16 Y0, Y1, U, V;
830   guint8 *restrict d = GET_LINE (y);
831   const guint16 *restrict s = src;
832
833   for (i = 0; i < width; i += 2) {
834     Y0 = s[i * 4 + 1] & 0xffc0;
835     U = s[i * 4 + 2] & 0xffc0;
836     V = s[i * 4 + 3] & 0xffc0;
837     if (i == width - 1)
838       Y1 = s[i * 4 + 1] & 0xffc0;
839     else
840       Y1 = s[(i + 1) * 4 + 1] & 0xffc0;
841
842     GST_WRITE_UINT16_LE (d + i * 4 + 0, Y0);
843     GST_WRITE_UINT16_LE (d + i * 4 + 2, U);
844     GST_WRITE_UINT16_LE (d + i * 4 + 4, Y1);
845     GST_WRITE_UINT16_LE (d + i * 4 + 6, V);
846   }
847 }
848
849 #define PACK_Y41B GST_VIDEO_FORMAT_AYUV, unpack_Y41B, 1, pack_Y41B
850 static void
851 unpack_Y41B (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
852     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
853     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
854 {
855   const guint8 *restrict sy = GET_Y_LINE (y);
856   const guint8 *restrict su = GET_U_LINE (y);
857   const guint8 *restrict sv = GET_V_LINE (y);
858   guint8 *restrict d = dest;
859
860   sy += x;
861   su += x >> 2;
862   sv += x >> 2;
863
864   if (x & 3) {
865     for (; x & 3; x++) {
866       d[0] = 0xff;
867       d[1] = *sy++;
868       d[2] = *su;
869       d[3] = *sv;
870       width--;
871       d += 4;
872     }
873     su++;
874     sy++;
875   }
876
877   if (IS_ALIGNED (d, 8))
878     video_orc_unpack_YUV9 (d, sy, su, sv, width / 2);
879   else {
880     gint i;
881     for (i = 0; i < width / 2; i++) {
882       d[i * 8 + 0] = 0xff;
883       d[i * 8 + 1] = sy[i * 2 + 0];
884       d[i * 8 + 2] = su[i >> 1];
885       d[i * 8 + 3] = sv[i >> 1];
886       d[i * 8 + 4] = 0xff;
887       d[i * 8 + 5] = sy[i * 2 + 1];
888       d[i * 8 + 6] = su[i >> 1];
889       d[i * 8 + 7] = sv[i >> 1];
890     }
891   }
892
893   if (width & 1) {
894     gint i = width - 1;
895
896     d[i * 4 + 0] = 0xff;
897     d[i * 4 + 1] = sy[i];
898     d[i * 4 + 2] = su[i >> 2];
899     d[i * 4 + 3] = sv[i >> 2];
900   }
901 }
902
903 static void
904 pack_Y41B (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
905     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
906     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
907     gint y, gint width)
908 {
909   int i;
910   guint8 *restrict dy = GET_Y_LINE (y);
911   guint8 *restrict du = GET_U_LINE (y);
912   guint8 *restrict dv = GET_V_LINE (y);
913   const guint8 *restrict s = src;
914
915   for (i = 0; i < width - 3; i += 4) {
916     dy[i] = s[i * 4 + 1];
917     dy[i + 1] = s[i * 4 + 5];
918     dy[i + 2] = s[i * 4 + 9];
919     dy[i + 3] = s[i * 4 + 13];
920
921     du[i >> 2] = s[i * 4 + 2];
922     dv[i >> 2] = s[i * 4 + 3];
923   }
924   if (i < width) {
925     dy[i] = s[i * 4 + 1];
926     du[i >> 2] = s[i * 4 + 2];
927     dv[i >> 2] = s[i * 4 + 3];
928     if (i < width - 1)
929       dy[i + 1] = s[i * 4 + 5];
930     if (i < width - 2)
931       dy[i + 2] = s[i * 4 + 9];
932   }
933 }
934
935 #define PACK_Y42B GST_VIDEO_FORMAT_AYUV, unpack_Y42B, 1, pack_Y42B
936 static void
937 unpack_Y42B (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
938     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
939     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
940 {
941   const guint8 *restrict sy = GET_Y_LINE (y);
942   const guint8 *restrict su = GET_U_LINE (y);
943   const guint8 *restrict sv = GET_V_LINE (y);
944   guint8 *restrict d = dest;
945
946   sy += x;
947   su += x >> 1;
948   sv += x >> 1;
949
950   if (x & 1) {
951     d[0] = 0xff;
952     d[1] = *sy++;
953     d[2] = *su++;
954     d[3] = *sv++;
955     width--;
956     d += 4;
957   }
958
959   if (IS_ALIGNED (d, 8))
960     video_orc_unpack_Y42B (d, sy, su, sv, width / 2);
961   else {
962     gint i;
963     for (i = 0; i < width / 2; i++) {
964       d[i * 8 + 0] = 0xff;
965       d[i * 8 + 1] = sy[i * 2 + 0];
966       d[i * 8 + 2] = su[i];
967       d[i * 8 + 3] = sv[i];
968       d[i * 8 + 4] = 0xff;
969       d[i * 8 + 5] = sy[i * 2 + 1];
970       d[i * 8 + 6] = su[i];
971       d[i * 8 + 7] = sv[i];
972     }
973   }
974
975   if (width & 1) {
976     gint i = width - 1;
977
978     d[i * 4 + 0] = 0xff;
979     d[i * 4 + 1] = sy[i];
980     d[i * 4 + 2] = su[i >> 1];
981     d[i * 4 + 3] = sv[i >> 1];
982   }
983 }
984
985 static void
986 pack_Y42B (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
987     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
988     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
989     gint y, gint width)
990 {
991   guint8 *restrict dy = GET_Y_LINE (y);
992   guint8 *restrict du = GET_U_LINE (y);
993   guint8 *restrict dv = GET_V_LINE (y);
994   const guint8 *restrict s = src;
995
996   if (IS_ALIGNED (s, 8))
997     video_orc_pack_Y42B (dy, du, dv, s, width / 2);
998   else {
999     gint i;
1000     for (i = 0; i < width / 2; i++) {
1001       dy[i * 2 + 0] = s[i * 8 + 1];
1002       dy[i * 2 + 1] = s[i * 8 + 5];
1003       du[i] = s[i * 8 + 2];
1004       dv[i] = s[i * 8 + 3];
1005     }
1006   }
1007
1008   if (width & 1) {
1009     gint i = width - 1;
1010
1011     dy[i] = s[i * 4 + 1];
1012     du[i >> 1] = s[i * 4 + 2];
1013     dv[i >> 1] = s[i * 4 + 3];
1014   }
1015 }
1016
1017 #define PACK_Y444 GST_VIDEO_FORMAT_AYUV, unpack_Y444, 1, pack_Y444
1018 static void
1019 unpack_Y444 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1020     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1021     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1022 {
1023   const guint8 *restrict sy = GET_Y_LINE (y);
1024   const guint8 *restrict su = GET_U_LINE (y);
1025   const guint8 *restrict sv = GET_V_LINE (y);
1026
1027   sy += x;
1028   su += x;
1029   sv += x;
1030
1031   video_orc_unpack_Y444 (dest, sy, su, sv, width);
1032 }
1033
1034 static void
1035 pack_Y444 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1036     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1037     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1038     gint y, gint width)
1039 {
1040   guint8 *restrict dy = GET_Y_LINE (y);
1041   guint8 *restrict du = GET_U_LINE (y);
1042   guint8 *restrict dv = GET_V_LINE (y);
1043
1044   video_orc_pack_Y444 (dy, du, dv, src, width);
1045 }
1046
1047 #define PACK_GBR GST_VIDEO_FORMAT_ARGB, unpack_GBR, 1, pack_GBR
1048 static void
1049 unpack_GBR (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1050     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1051     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1052 {
1053   const guint8 *restrict sr = GET_R_LINE (y);
1054   const guint8 *restrict sg = GET_G_LINE (y);
1055   const guint8 *restrict sb = GET_B_LINE (y);
1056
1057   sr += x;
1058   sg += x;
1059   sb += x;
1060
1061   video_orc_unpack_Y444 (dest, sr, sg, sb, width);
1062 }
1063
1064 static void
1065 pack_GBR (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1066     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1067     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1068     gint y, gint width)
1069 {
1070   guint8 *restrict dr = GET_R_LINE (y);
1071   guint8 *restrict dg = GET_G_LINE (y);
1072   guint8 *restrict db = GET_B_LINE (y);
1073
1074   video_orc_pack_Y444 (dr, dg, db, src, width);
1075 }
1076
1077 #define PACK_GBRA GST_VIDEO_FORMAT_ARGB, unpack_GBRA, 1, pack_GBRA
1078 static void
1079 unpack_GBRA (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1080     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1081     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1082 {
1083   int i;
1084   const guint8 *sg = GET_G_LINE (y);
1085   const guint8 *sb = GET_B_LINE (y);
1086   const guint8 *sr = GET_R_LINE (y);
1087   const guint8 *sa = GET_A_LINE (y);
1088   guint8 *d = dest, G, B, R, A;
1089
1090   sg += x;
1091   sb += x;
1092   sr += x;
1093   sa += x;
1094
1095   for (i = 0; i < width; i++) {
1096     G = GST_READ_UINT8 (sg + i);
1097     B = GST_READ_UINT8 (sb + i);
1098     R = GST_READ_UINT8 (sr + i);
1099     A = GST_READ_UINT8 (sa + i);
1100
1101     d[i * 4 + 0] = A;
1102     d[i * 4 + 1] = R;
1103     d[i * 4 + 2] = G;
1104     d[i * 4 + 3] = B;
1105   }
1106 }
1107
1108 static void
1109 pack_GBRA (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1110     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1111     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1112     gint y, gint width)
1113 {
1114   int i;
1115   guint8 *restrict dg = GET_G_LINE (y);
1116   guint8 *restrict db = GET_B_LINE (y);
1117   guint8 *restrict dr = GET_R_LINE (y);
1118   guint8 *restrict da = GET_A_LINE (y);
1119   guint8 G, B, R, A;
1120   const guint8 *restrict s = src;
1121
1122   for (i = 0; i < width; i++) {
1123     G = (s[i * 4 + 2]);
1124     B = (s[i * 4 + 3]);
1125     R = (s[i * 4 + 1]);
1126     A = (s[i * 4 + 0]);
1127
1128     GST_WRITE_UINT8 (dg + i, G);
1129     GST_WRITE_UINT8 (db + i, B);
1130     GST_WRITE_UINT8 (dr + i, R);
1131     GST_WRITE_UINT8 (da + i, A);
1132   }
1133 }
1134
1135 #define PACK_GRAY8 GST_VIDEO_FORMAT_AYUV, unpack_GRAY8, 1, pack_GRAY8
1136 static void
1137 unpack_GRAY8 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1138     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1139     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1140 {
1141   const guint8 *restrict s = GET_LINE (y);
1142
1143   s += x;
1144
1145   video_orc_unpack_GRAY8 (dest, s, width);
1146 }
1147
1148 static void
1149 pack_GRAY8 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1150     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1151     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1152     gint y, gint width)
1153 {
1154   guint8 *restrict d = GET_LINE (y);
1155
1156   video_orc_pack_GRAY8 (d, src, width);
1157 }
1158
1159 #define PACK_GRAY16_BE GST_VIDEO_FORMAT_AYUV64, unpack_GRAY16_BE, 1, pack_GRAY16_BE
1160 static void
1161 unpack_GRAY16_BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1162     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1163     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1164 {
1165   int i;
1166   const guint16 *restrict s = GET_LINE (y);
1167   guint16 *restrict d = dest;
1168
1169   s += x;
1170
1171   for (i = 0; i < width; i++) {
1172     d[i * 4 + 0] = 0xffff;
1173     d[i * 4 + 1] = GST_READ_UINT16_BE (s + i);
1174     d[i * 4 + 2] = 0x8000;
1175     d[i * 4 + 3] = 0x8000;
1176   }
1177 }
1178
1179 static void
1180 pack_GRAY16_BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1181     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1182     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1183     gint y, gint width)
1184 {
1185   int i;
1186   guint16 *restrict d = GET_LINE (y);
1187   const guint16 *restrict s = src;
1188
1189   for (i = 0; i < width; i++) {
1190     GST_WRITE_UINT16_BE (d + i, s[i * 4 + 1]);
1191   }
1192 }
1193
1194 #define PACK_GRAY16_LE GST_VIDEO_FORMAT_AYUV64, unpack_GRAY16_LE, 1, pack_GRAY16_LE
1195 static void
1196 unpack_GRAY16_LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1197     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1198     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1199 {
1200   int i;
1201   const guint16 *restrict s = GET_LINE (y);
1202   guint16 *restrict d = dest;
1203
1204   s += x;
1205
1206   for (i = 0; i < width; i++) {
1207     d[i * 4 + 0] = 0xffff;
1208     d[i * 4 + 1] = GST_READ_UINT16_LE (s + i);
1209     d[i * 4 + 2] = 0x8000;
1210     d[i * 4 + 3] = 0x8000;
1211   }
1212 }
1213
1214 static void
1215 pack_GRAY16_LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1216     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1217     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1218     gint y, gint width)
1219 {
1220   int i;
1221   guint16 *restrict d = GET_LINE (y);
1222   const guint16 *restrict s = src;
1223
1224   for (i = 0; i < width; i++) {
1225     GST_WRITE_UINT16_LE (d + i, s[i * 4 + 1]);
1226   }
1227 }
1228
1229 #define PACK_RGB16 GST_VIDEO_FORMAT_ARGB, unpack_RGB16, 1, pack_RGB16
1230 static void
1231 unpack_RGB16 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1232     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1233     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1234 {
1235   const guint16 *restrict s = GET_LINE (y);
1236
1237   if (flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)
1238     video_orc_unpack_RGB16_trunc (dest, s + x, width);
1239   else
1240     video_orc_unpack_RGB16 (dest, s + x, width);
1241 }
1242
1243 static void
1244 pack_RGB16 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1245     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1246     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1247     gint y, gint width)
1248 {
1249   guint16 *restrict d = GET_LINE (y);
1250
1251 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1252   video_orc_pack_RGB16_le (d, src, width);
1253 #else
1254   video_orc_pack_RGB16_be (d, src, width);
1255 #endif
1256 }
1257
1258 #define PACK_BGR16 GST_VIDEO_FORMAT_ARGB, unpack_BGR16, 1, pack_BGR16
1259 static void
1260 unpack_BGR16 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1261     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1262     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1263 {
1264   const guint16 *restrict s = GET_LINE (y);
1265
1266   if (flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)
1267     video_orc_unpack_BGR16_trunc (dest, s + x, width);
1268   else
1269     video_orc_unpack_BGR16 (dest, s + x, width);
1270 }
1271
1272 static void
1273 pack_BGR16 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1274     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1275     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1276     gint y, gint width)
1277 {
1278   guint16 *restrict d = GET_LINE (y);
1279
1280 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1281   video_orc_pack_BGR16_le (d, src, width);
1282 #else
1283   video_orc_pack_BGR16_be (d, src, width);
1284 #endif
1285 }
1286
1287 #define PACK_RGB15 GST_VIDEO_FORMAT_ARGB, unpack_RGB15, 1, pack_RGB15
1288 static void
1289 unpack_RGB15 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1290     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1291     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1292 {
1293   const guint16 *restrict s = GET_LINE (y);
1294
1295 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1296   if (flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)
1297     video_orc_unpack_RGB15_le_trunc (dest, s + x, width);
1298   else
1299     video_orc_unpack_RGB15_le (dest, s + x, width);
1300 #else
1301   if (flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)
1302     video_orc_unpack_RGB15_be_trunc (dest, s + x, width);
1303   else
1304     video_orc_unpack_RGB15_be (dest, s + x, width);
1305 #endif
1306 }
1307
1308 static void
1309 pack_RGB15 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1310     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1311     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1312     gint y, gint width)
1313 {
1314   guint16 *restrict d = GET_LINE (y);
1315
1316 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1317   video_orc_pack_RGB15_le (d, src, width);
1318 #else
1319   video_orc_pack_RGB15_be (d, src, width);
1320 #endif
1321 }
1322
1323 #define PACK_BGR15 GST_VIDEO_FORMAT_ARGB, unpack_BGR15, 1, pack_BGR15
1324 static void
1325 unpack_BGR15 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1326     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1327     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1328 {
1329   const guint16 *restrict s = GET_LINE (y);
1330
1331 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1332   if (flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)
1333     video_orc_unpack_BGR15_le_trunc (dest, s + x, width);
1334   else
1335     video_orc_unpack_BGR15_le (dest, s + x, width);
1336 #else
1337   if (flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)
1338     video_orc_unpack_BGR15_be_trunc (dest, s + x, width);
1339   else
1340     video_orc_unpack_BGR15_be (dest, s + x, width);
1341 #endif
1342 }
1343
1344 static void
1345 pack_BGR15 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1346     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1347     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1348     gint y, gint width)
1349 {
1350   guint16 *restrict d = GET_LINE (y);
1351
1352 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1353   video_orc_pack_BGR15_le (d, src, width);
1354 #else
1355   video_orc_pack_BGR15_be (d, src, width);
1356 #endif
1357 }
1358
1359 #define PACK_BGRA GST_VIDEO_FORMAT_ARGB, unpack_BGRA, 1, pack_BGRA
1360 static void
1361 unpack_BGRA (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1362     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1363     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1364 {
1365   const guint8 *restrict s = GET_LINE (y);
1366
1367   s += x * 4;
1368
1369   video_orc_unpack_BGRA (dest, s, width);
1370 }
1371
1372 static void
1373 pack_BGRA (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1374     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1375     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1376     gint y, gint width)
1377 {
1378   guint8 *restrict d = GET_LINE (y);
1379
1380   video_orc_pack_BGRA (d, src, width);
1381 }
1382
1383 #define PACK_ABGR GST_VIDEO_FORMAT_ARGB, unpack_ABGR, 1, pack_ABGR
1384 static void
1385 unpack_ABGR (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1386     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1387     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1388 {
1389   const guint8 *restrict s = GET_LINE (y);
1390
1391   s += x * 4;
1392
1393 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1394   video_orc_unpack_ABGR_le (dest, s, width);
1395 #else
1396   video_orc_unpack_ABGR_be (dest, s, width);
1397 #endif
1398 }
1399
1400 static void
1401 pack_ABGR (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1402     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1403     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1404     gint y, gint width)
1405 {
1406   guint8 *restrict d = GET_LINE (y);
1407
1408 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1409   video_orc_pack_ABGR_le (d, src, width);
1410 #else
1411   video_orc_pack_ABGR_be (d, src, width);
1412 #endif
1413 }
1414
1415 #define PACK_RGBA GST_VIDEO_FORMAT_ARGB, unpack_RGBA, 1, pack_RGBA
1416 static void
1417 unpack_RGBA (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1418     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1419     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1420 {
1421   const guint8 *restrict s = GET_LINE (y);
1422
1423   s += x * 4;
1424
1425 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1426   video_orc_unpack_RGBA_le (dest, s, width);
1427 #else
1428   video_orc_unpack_RGBA_be (dest, s, width);
1429 #endif
1430 }
1431
1432 static void
1433 pack_RGBA (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1434     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1435     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1436     gint y, gint width)
1437 {
1438   guint8 *restrict d = GET_LINE (y);
1439
1440 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1441   video_orc_pack_RGBA_le (d, src, width);
1442 #else
1443   video_orc_pack_RGBA_be (d, src, width);
1444 #endif
1445 }
1446
1447 #define PACK_RGB GST_VIDEO_FORMAT_ARGB, unpack_RGB, 1, pack_RGB
1448 static void
1449 unpack_RGB (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1450     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1451     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1452 {
1453   int i;
1454   const guint8 *restrict s = GET_LINE (y);
1455   guint8 *restrict d = dest;
1456
1457   s += x * 3;
1458
1459   for (i = 0; i < width; i++) {
1460     d[i * 4 + 0] = 0xff;
1461     d[i * 4 + 1] = s[i * 3 + 0];
1462     d[i * 4 + 2] = s[i * 3 + 1];
1463     d[i * 4 + 3] = s[i * 3 + 2];
1464   }
1465 }
1466
1467 static void
1468 pack_RGB (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1469     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1470     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1471     gint y, gint width)
1472 {
1473   int i;
1474   guint8 *restrict d = GET_LINE (y);
1475   const guint8 *restrict s = src;
1476
1477   for (i = 0; i < width; i++) {
1478     d[i * 3 + 0] = s[i * 4 + 1];
1479     d[i * 3 + 1] = s[i * 4 + 2];
1480     d[i * 3 + 2] = s[i * 4 + 3];
1481   }
1482 }
1483
1484 #define PACK_BGR GST_VIDEO_FORMAT_ARGB, unpack_BGR, 1, pack_BGR
1485 static void
1486 unpack_BGR (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1487     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1488     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1489 {
1490   int i;
1491   const guint8 *restrict s = GET_LINE (y);
1492   guint8 *restrict d = dest;
1493
1494   s += x * 3;
1495
1496   for (i = 0; i < width; i++) {
1497     d[i * 4 + 0] = 0xff;
1498     d[i * 4 + 1] = s[i * 3 + 2];
1499     d[i * 4 + 2] = s[i * 3 + 1];
1500     d[i * 4 + 3] = s[i * 3 + 0];
1501   }
1502 }
1503
1504 static void
1505 pack_BGR (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1506     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1507     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1508     gint y, gint width)
1509 {
1510   int i;
1511   guint8 *restrict d = GET_LINE (y);
1512   const guint8 *restrict s = src;
1513
1514   for (i = 0; i < width; i++) {
1515     d[i * 3 + 0] = s[i * 4 + 3];
1516     d[i * 3 + 1] = s[i * 4 + 2];
1517     d[i * 3 + 2] = s[i * 4 + 1];
1518   }
1519 }
1520
1521 #define PACK_NV12 GST_VIDEO_FORMAT_AYUV, unpack_NV12, 1, pack_NV12
1522 static void
1523 unpack_NV12 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1524     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1525     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1526 {
1527   gint uv = GET_UV_420 (y, flags);
1528   const guint8 *restrict sy = GET_PLANE_LINE (0, y);
1529   const guint8 *restrict suv = GET_PLANE_LINE (1, uv);
1530   guint8 *restrict d = dest;
1531
1532   sy += x;
1533   suv += (x & ~1);
1534
1535   if (x & 1) {
1536     d[0] = 0xff;
1537     d[1] = *sy++;
1538     d[2] = suv[0];
1539     d[3] = suv[1];
1540     width--;
1541     d += 4;
1542     suv += 2;
1543   }
1544
1545   if (IS_ALIGNED (d, 8))
1546     video_orc_unpack_NV12 (d, sy, suv, width / 2);
1547   else {
1548     gint i;
1549     for (i = 0; i < width / 2; i++) {
1550       d[i * 8 + 0] = 0xff;
1551       d[i * 8 + 1] = sy[i * 2 + 0];
1552       d[i * 8 + 2] = suv[i * 2 + 0];
1553       d[i * 8 + 3] = suv[i * 2 + 1];
1554       d[i * 8 + 4] = 0xff;
1555       d[i * 8 + 5] = sy[i * 2 + 1];
1556       d[i * 8 + 6] = suv[i * 2 + 0];
1557       d[i * 8 + 7] = suv[i * 2 + 1];
1558     }
1559   }
1560
1561   if (width & 1) {
1562     gint i = width - 1;
1563
1564     d[i * 4 + 0] = 0xff;
1565     d[i * 4 + 1] = sy[i];
1566     d[i * 4 + 2] = suv[i + 0];
1567     d[i * 4 + 3] = suv[i + 1];
1568   }
1569 }
1570
1571 static void
1572 pack_NV12 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1573     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1574     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1575     gint y, gint width)
1576 {
1577   gint uv = GET_UV_420 (y, flags);
1578   guint8 *restrict dy = GET_PLANE_LINE (0, y);
1579   guint8 *restrict duv = GET_PLANE_LINE (1, uv);
1580   const guint8 *restrict s = src;
1581
1582   if (IS_CHROMA_LINE_420 (y, flags)) {
1583     if (IS_ALIGNED (s, 8))
1584       video_orc_pack_NV12 (dy, duv, s, width / 2);
1585     else {
1586       gint i;
1587       for (i = 0; i < width / 2; i++) {
1588         dy[i * 2 + 0] = s[i * 8 + 1];
1589         dy[i * 2 + 1] = s[i * 8 + 5];
1590         duv[i * 2 + 0] = s[i * 8 + 2];
1591         duv[i * 2 + 1] = s[i * 8 + 3];
1592       }
1593     }
1594     if (width & 1) {
1595       gint i = width - 1;
1596
1597       dy[i] = s[i * 4 + 1];
1598       duv[i + 0] = s[i * 4 + 2];
1599       duv[i + 1] = s[i * 4 + 3];
1600     }
1601   } else
1602     video_orc_pack_Y (dy, s, width);
1603 }
1604
1605 #define PACK_NV21 GST_VIDEO_FORMAT_AYUV, unpack_NV21, 1, pack_NV21
1606 static void
1607 unpack_NV21 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1608     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1609     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1610 {
1611   gint uv = GET_UV_420 (y, flags);
1612   const guint8 *restrict sy = GET_PLANE_LINE (0, y);
1613   const guint8 *restrict suv = GET_PLANE_LINE (1, uv);
1614   guint8 *restrict d = dest;
1615
1616   sy += x;
1617   suv += (x & ~1);
1618
1619   if (x & 1) {
1620     d[0] = 0xff;
1621     d[1] = *sy++;
1622     d[2] = suv[1];
1623     d[3] = suv[0];
1624     width--;
1625     d += 4;
1626     suv += 2;
1627   }
1628
1629   if (IS_ALIGNED (d, 8))
1630     video_orc_unpack_NV21 (d, sy, suv, width / 2);
1631   else {
1632     gint i;
1633     for (i = 0; i < width / 2; i++) {
1634       d[i * 8 + 0] = 0xff;
1635       d[i * 8 + 1] = sy[i * 2 + 0];
1636       d[i * 8 + 2] = suv[i * 2 + 1];
1637       d[i * 8 + 3] = suv[i * 2 + 0];
1638       d[i * 8 + 4] = 0xff;
1639       d[i * 8 + 5] = sy[i * 2 + 1];
1640       d[i * 8 + 6] = suv[i * 2 + 1];
1641       d[i * 8 + 7] = suv[i * 2 + 0];
1642     }
1643   }
1644
1645   if (width & 1) {
1646     gint i = width - 1;
1647
1648     d[i * 4 + 0] = 0xff;
1649     d[i * 4 + 1] = sy[i];
1650     d[i * 4 + 2] = suv[i + 1];
1651     d[i * 4 + 3] = suv[i + 0];
1652   }
1653 }
1654
1655 static void
1656 pack_NV21 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1657     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1658     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1659     gint y, gint width)
1660 {
1661   gint uv = GET_UV_420 (y, flags);
1662   guint8 *restrict dy = GET_PLANE_LINE (0, y);
1663   guint8 *restrict duv = GET_PLANE_LINE (1, uv);
1664   const guint8 *restrict s = src;
1665
1666   if (IS_CHROMA_LINE_420 (y, flags)) {
1667     if (IS_ALIGNED (s, 8))
1668       video_orc_pack_NV21 (dy, duv, s, width / 2);
1669     else {
1670       gint i;
1671       for (i = 0; i < width / 2; i++) {
1672         dy[i * 2 + 0] = s[i * 8 + 1];
1673         dy[i * 2 + 1] = s[i * 8 + 5];
1674         duv[i * 2 + 0] = s[i * 8 + 3];
1675         duv[i * 2 + 1] = s[i * 8 + 2];
1676       }
1677     }
1678     if (width & 1) {
1679       gint i = width - 1;
1680
1681       dy[i] = s[i * 4 + 1];
1682       duv[i + 0] = s[i * 4 + 3];
1683       duv[i + 1] = s[i * 4 + 2];
1684     }
1685   } else
1686     video_orc_pack_Y (dy, s, width);
1687 }
1688
1689 #define PACK_NV16 GST_VIDEO_FORMAT_AYUV, unpack_NV16, 1, pack_NV16
1690 static void
1691 unpack_NV16 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1692     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1693     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1694 {
1695   const guint8 *restrict sy = GET_PLANE_LINE (0, y);
1696   const guint8 *restrict suv = GET_PLANE_LINE (1, y);
1697   guint8 *restrict d = dest;
1698
1699   sy += x;
1700   suv += (x & ~1);
1701
1702   if (x & 1) {
1703     d[0] = 0xff;
1704     d[1] = *sy++;
1705     d[2] = suv[0];
1706     d[3] = suv[1];
1707     width--;
1708     d += 4;
1709     suv += 2;
1710   }
1711
1712   if (IS_ALIGNED (d, 8))
1713     video_orc_unpack_NV12 (d, sy, suv, width / 2);
1714   else {
1715     gint i;
1716     for (i = 0; i < width / 2; i++) {
1717       d[i * 8 + 0] = 0xff;
1718       d[i * 8 + 1] = sy[i * 2 + 0];
1719       d[i * 8 + 2] = suv[i * 2 + 0];
1720       d[i * 8 + 3] = suv[i * 2 + 1];
1721       d[i * 8 + 4] = 0xff;
1722       d[i * 8 + 5] = sy[i * 2 + 1];
1723       d[i * 8 + 6] = suv[i * 2 + 0];
1724       d[i * 8 + 7] = suv[i * 2 + 1];
1725     }
1726   }
1727
1728   if (width & 1) {
1729     gint i = width - 1;
1730
1731     d[i * 4 + 0] = 0xff;
1732     d[i * 4 + 1] = sy[i];
1733     d[i * 4 + 2] = suv[i + 0];
1734     d[i * 4 + 3] = suv[i + 1];
1735   }
1736 }
1737
1738 static void
1739 pack_NV16 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1740     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1741     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1742     gint y, gint width)
1743 {
1744   guint8 *restrict dy = GET_PLANE_LINE (0, y);
1745   guint8 *restrict duv = GET_PLANE_LINE (1, y);
1746   const guint8 *restrict s = src;
1747
1748   if (IS_ALIGNED (s, 8))
1749     video_orc_pack_NV12 (dy, duv, s, width / 2);
1750   else {
1751     gint i;
1752     for (i = 0; i < width / 2; i++) {
1753       dy[i * 2 + 0] = s[i * 8 + 1];
1754       dy[i * 2 + 1] = s[i * 8 + 5];
1755       duv[i * 2 + 0] = s[i * 8 + 2];
1756       duv[i * 2 + 1] = s[i * 8 + 3];
1757     }
1758   }
1759
1760   if (width & 1) {
1761     gint i = width - 1;
1762
1763     dy[i] = s[i * 4 + 1];
1764     duv[i + 0] = s[i * 4 + 2];
1765     duv[i + 1] = s[i * 4 + 3];
1766   }
1767 }
1768
1769 #define PACK_NV61 GST_VIDEO_FORMAT_AYUV, unpack_NV61, 1, pack_NV61
1770 static void
1771 unpack_NV61 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1772     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1773     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1774 {
1775   const guint8 *restrict sy = GET_PLANE_LINE (0, y);
1776   const guint8 *restrict svu = GET_PLANE_LINE (1, y);
1777   guint8 *restrict d = dest;
1778
1779   sy += x;
1780   svu += (x & ~1);
1781
1782   if (x & 1) {
1783     d[0] = 0xff;
1784     d[1] = *sy++;
1785     d[2] = svu[1];
1786     d[3] = svu[0];
1787     width--;
1788     d += 4;
1789     svu += 2;
1790   }
1791
1792   if (IS_ALIGNED (d, 8)) {
1793     video_orc_unpack_NV21 (d, sy, svu, width / 2);
1794   } else {
1795     gint i;
1796
1797     for (i = 0; i < width / 2; i++) {
1798       d[i * 8 + 0] = 0xff;
1799       d[i * 8 + 1] = sy[i * 2 + 0];
1800       d[i * 8 + 2] = svu[i * 2 + 1];
1801       d[i * 8 + 3] = svu[i * 2 + 0];
1802       d[i * 8 + 4] = 0xff;
1803       d[i * 8 + 5] = sy[i * 2 + 1];
1804       d[i * 8 + 6] = svu[i * 2 + 1];
1805       d[i * 8 + 7] = svu[i * 2 + 0];
1806     }
1807   }
1808
1809   if (width & 1) {
1810     gint i = width - 1;
1811
1812     d[i * 4 + 0] = 0xff;
1813     d[i * 4 + 1] = sy[i];
1814     d[i * 4 + 2] = svu[i + 1];
1815     d[i * 4 + 3] = svu[i + 0];
1816   }
1817 }
1818
1819 static void
1820 pack_NV61 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1821     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1822     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1823     gint y, gint width)
1824 {
1825   const guint8 *restrict s = src;
1826   guint8 *restrict dy = GET_PLANE_LINE (0, y);
1827   guint8 *restrict dvu = GET_PLANE_LINE (1, y);
1828
1829   if (IS_ALIGNED (s, 8)) {
1830     video_orc_pack_NV21 (dy, dvu, s, width / 2);
1831   } else {
1832     gint i;
1833
1834     for (i = 0; i < width / 2; i++) {
1835       dy[i * 2 + 0] = s[i * 8 + 1];
1836       dy[i * 2 + 1] = s[i * 8 + 5];
1837       dvu[i * 2 + 0] = s[i * 8 + 3];
1838       dvu[i * 2 + 1] = s[i * 8 + 2];
1839     }
1840   }
1841
1842   if (width & 1) {
1843     gint i = width - 1;
1844
1845     dy[i] = s[i * 4 + 1];
1846     dvu[i + 0] = s[i * 4 + 2];
1847     dvu[i + 1] = s[i * 4 + 3];
1848   }
1849 }
1850
1851 #define PACK_NV24 GST_VIDEO_FORMAT_AYUV, unpack_NV24, 1, pack_NV24
1852 static void
1853 unpack_NV24 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1854     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1855     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1856 {
1857   const guint8 *restrict sy = GET_PLANE_LINE (0, y);
1858   const guint8 *restrict suv = GET_PLANE_LINE (1, y);
1859
1860   sy += x;
1861   suv += x << 1;
1862
1863   video_orc_unpack_NV24 (dest, sy, suv, width);
1864 }
1865
1866 static void
1867 pack_NV24 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1868     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1869     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1870     gint y, gint width)
1871 {
1872   guint8 *restrict dy = GET_PLANE_LINE (0, y);
1873   guint8 *restrict duv = GET_PLANE_LINE (1, y);
1874
1875   video_orc_pack_NV24 (dy, duv, src, width);
1876 }
1877
1878 #define PACK_UYVP GST_VIDEO_FORMAT_AYUV64, unpack_UYVP, 1, pack_UYVP
1879 static void
1880 unpack_UYVP (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1881     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1882     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1883 {
1884   int i;
1885   const guint8 *restrict s = GET_LINE (y);
1886   guint16 *restrict d = dest;
1887
1888   /* FIXME */
1889   s += x << 1;
1890
1891   for (i = 0; i < width; i += 2) {
1892     guint16 y0, y1;
1893     guint16 u0;
1894     guint16 v0;
1895
1896     u0 = ((s[(i / 2) * 5 + 0] << 2) | (s[(i / 2) * 5 + 1] >> 6)) << 6;
1897     y0 = (((s[(i / 2) * 5 + 1] & 0x3f) << 4) | (s[(i / 2) * 5 + 2] >> 4)) << 6;
1898     v0 = (((s[(i / 2) * 5 + 2] & 0x0f) << 6) | (s[(i / 2) * 5 + 3] >> 2)) << 6;
1899     y1 = (((s[(i / 2) * 5 + 3] & 0x03) << 8) | s[(i / 2) * 5 + 4]) << 6;
1900
1901     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
1902       y0 |= (y0 >> 10);
1903       y1 |= (y1 >> 10);
1904       u0 |= (u0 >> 10);
1905       v0 |= (v0 >> 10);
1906     }
1907
1908     d[i * 4 + 0] = 0xffff;
1909     d[i * 4 + 1] = y0;
1910     d[i * 4 + 2] = u0;
1911     d[i * 4 + 3] = v0;
1912
1913     if (i < width - 1) {
1914       d[i * 4 + 4] = 0xffff;
1915       d[i * 4 + 5] = y1;
1916       d[i * 4 + 6] = u0;
1917       d[i * 4 + 7] = v0;
1918     }
1919   }
1920 }
1921
1922 static void
1923 pack_UYVP (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1924     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1925     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1926     gint y, gint width)
1927 {
1928   int i;
1929   guint8 *restrict d = GET_LINE (y);
1930   const guint16 *restrict s = src;
1931
1932   for (i = 0; i < width; i += 2) {
1933     guint16 y0, y1;
1934     guint16 u0;
1935     guint16 v0;
1936
1937     y0 = s[4 * (i + 0) + 1];
1938     if (i < width - 1)
1939       y1 = s[4 * (i + 1) + 1];
1940     else
1941       y1 = y0;
1942
1943     u0 = s[4 * (i + 0) + 2];
1944     v0 = s[4 * (i + 0) + 3];
1945
1946     d[(i / 2) * 5 + 0] = u0 >> 8;
1947     d[(i / 2) * 5 + 1] = (u0 & 0xc0) | y0 >> 10;
1948     d[(i / 2) * 5 + 2] = ((y0 & 0x3c0) >> 2) | (v0 >> 12);
1949     d[(i / 2) * 5 + 3] = ((v0 & 0xfc0) >> 4) | (y1 >> 14);
1950     d[(i / 2) * 5 + 4] = (y1 >> 6);
1951   }
1952 }
1953
1954 #define PACK_A420 GST_VIDEO_FORMAT_AYUV, unpack_A420, 1, pack_A420
1955 static void
1956 unpack_A420 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1957     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1958     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1959 {
1960   gint uv = GET_UV_420 (y, flags);
1961   const guint8 *restrict sy = GET_Y_LINE (y);
1962   const guint8 *restrict su = GET_U_LINE (uv);
1963   const guint8 *restrict sv = GET_V_LINE (uv);
1964   const guint8 *restrict sa = GET_A_LINE (y);
1965   guint8 *restrict d = dest;
1966
1967   sy += x;
1968   su += x >> 1;
1969   sv += x >> 1;
1970   sa += x;
1971
1972   if (x & 1) {
1973     d[0] = *sa++;
1974     d[1] = *sy++;
1975     d[2] = *su++;
1976     d[3] = *sv++;
1977     width--;
1978     d += 4;
1979   }
1980   video_orc_unpack_A420 (d, sy, su, sv, sa, width);
1981 }
1982
1983 static void
1984 pack_A420 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1985     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1986     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1987     gint y, gint width)
1988 {
1989   gint uv = GET_UV_420 (y, flags);
1990   guint8 *restrict dy = GET_Y_LINE (y);
1991   guint8 *restrict du = GET_U_LINE (uv);
1992   guint8 *restrict dv = GET_V_LINE (uv);
1993   guint8 *restrict da = GET_A_LINE (y);
1994   const guint8 *restrict s = src;
1995
1996   if (IS_CHROMA_LINE_420 (y, flags)) {
1997     if (IS_ALIGNED (s, 8))
1998       video_orc_pack_A420 (dy, du, dv, da, s, width / 2);
1999     else {
2000       gint i;
2001       for (i = 0; i < width / 2; i++) {
2002         da[i * 2 + 0] = s[i * 8 + 0];
2003         dy[i * 2 + 0] = s[i * 8 + 1];
2004         da[i * 2 + 1] = s[i * 8 + 4];
2005         dy[i * 2 + 1] = s[i * 8 + 5];
2006         du[i] = s[i * 8 + 2];
2007         dv[i] = s[i * 8 + 3];
2008       }
2009     }
2010
2011     if (width & 1) {
2012       gint i = width - 1;
2013
2014       da[i] = s[i * 4 + 0];
2015       dy[i] = s[i * 4 + 1];
2016       du[i >> 1] = s[i * 4 + 2];
2017       dv[i >> 1] = s[i * 4 + 3];
2018     }
2019   } else
2020     video_orc_pack_AY (dy, da, s, width);
2021 }
2022
2023 #define PACK_RGB8P GST_VIDEO_FORMAT_ARGB, unpack_RGB8P, 1, pack_RGB8P
2024 static void
2025 unpack_RGB8P (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2026     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
2027     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
2028 {
2029   int i;
2030   const guint8 *restrict s = GET_LINE (y);
2031   const guint32 *restrict p = data[1];
2032   guint8 *restrict d = dest;
2033
2034   s += x;
2035
2036   for (i = 0; i < width; i++) {
2037     guint32 v = p[s[i]];
2038     d[i * 4 + 0] = (v >> 24) & 0xff;
2039     d[i * 4 + 1] = (v >> 16) & 0xff;
2040     d[i * 4 + 2] = (v >> 8) & 0xff;
2041     d[i * 4 + 3] = (v) & 0xff;
2042   }
2043 }
2044
2045 static const guint32 std_palette_RGB8P[] = {
2046   0xff000000, 0xff000033, 0xff000066, 0xff000099, 0xff0000cc, 0xff0000ff,
2047   0xff003300, 0xff003333, 0xff003366, 0xff003399, 0xff0033cc, 0xff0033ff,
2048   0xff006600, 0xff006633, 0xff006666, 0xff006699, 0xff0066cc, 0xff0066ff,
2049   0xff009900, 0xff009933, 0xff009966, 0xff009999, 0xff0099cc, 0xff0099ff,
2050   0xff00cc00, 0xff00cc33, 0xff00cc66, 0xff00cc99, 0xff00cccc, 0xff00ccff,
2051   0xff00ff00, 0xff00ff33, 0xff00ff66, 0xff00ff99, 0xff00ffcc, 0xff00ffff,
2052   0xff330000, 0xff330033, 0xff330066, 0xff330099, 0xff3300cc, 0xff3300ff,
2053   0xff333300, 0xff333333, 0xff333366, 0xff333399, 0xff3333cc, 0xff3333ff,
2054   0xff336600, 0xff336633, 0xff336666, 0xff336699, 0xff3366cc, 0xff3366ff,
2055   0xff339900, 0xff339933, 0xff339966, 0xff339999, 0xff3399cc, 0xff3399ff,
2056   0xff33cc00, 0xff33cc33, 0xff33cc66, 0xff33cc99, 0xff33cccc, 0xff33ccff,
2057   0xff33ff00, 0xff33ff33, 0xff33ff66, 0xff33ff99, 0xff33ffcc, 0xff33ffff,
2058   0xff660000, 0xff660033, 0xff660066, 0xff660099, 0xff6600cc, 0xff6600ff,
2059   0xff663300, 0xff663333, 0xff663366, 0xff663399, 0xff6633cc, 0xff6633ff,
2060   0xff666600, 0xff666633, 0xff666666, 0xff666699, 0xff6666cc, 0xff6666ff,
2061   0xff669900, 0xff669933, 0xff669966, 0xff669999, 0xff6699cc, 0xff6699ff,
2062   0xff66cc00, 0xff66cc33, 0xff66cc66, 0xff66cc99, 0xff66cccc, 0xff66ccff,
2063   0xff66ff00, 0xff66ff33, 0xff66ff66, 0xff66ff99, 0xff66ffcc, 0xff66ffff,
2064   0xff990000, 0xff990033, 0xff990066, 0xff990099, 0xff9900cc, 0xff9900ff,
2065   0xff993300, 0xff993333, 0xff993366, 0xff993399, 0xff9933cc, 0xff9933ff,
2066   0xff996600, 0xff996633, 0xff996666, 0xff996699, 0xff9966cc, 0xff9966ff,
2067   0xff999900, 0xff999933, 0xff999966, 0xff999999, 0xff9999cc, 0xff9999ff,
2068   0xff99cc00, 0xff99cc33, 0xff99cc66, 0xff99cc99, 0xff99cccc, 0xff99ccff,
2069   0xff99ff00, 0xff99ff33, 0xff99ff66, 0xff99ff99, 0xff99ffcc, 0xff99ffff,
2070   0xffcc0000, 0xffcc0033, 0xffcc0066, 0xffcc0099, 0xffcc00cc, 0xffcc00ff,
2071   0xffcc3300, 0xffcc3333, 0xffcc3366, 0xffcc3399, 0xffcc33cc, 0xffcc33ff,
2072   0xffcc6600, 0xffcc6633, 0xffcc6666, 0xffcc6699, 0xffcc66cc, 0xffcc66ff,
2073   0xffcc9900, 0xffcc9933, 0xffcc9966, 0xffcc9999, 0xffcc99cc, 0xffcc99ff,
2074   0xffcccc00, 0xffcccc33, 0xffcccc66, 0xffcccc99, 0xffcccccc, 0xffccccff,
2075   0xffccff00, 0xffccff33, 0xffccff66, 0xffccff99, 0xffccffcc, 0xffccffff,
2076   0xffff0000, 0xffff0033, 0xffff0066, 0xffff0099, 0xffff00cc, 0xffff00ff,
2077   0xffff3300, 0xffff3333, 0xffff3366, 0xffff3399, 0xffff33cc, 0xffff33ff,
2078   0xffff6600, 0xffff6633, 0xffff6666, 0xffff6699, 0xffff66cc, 0xffff66ff,
2079   0xffff9900, 0xffff9933, 0xffff9966, 0xffff9999, 0xffff99cc, 0xffff99ff,
2080   0xffffcc00, 0xffffcc33, 0xffffcc66, 0xffffcc99, 0xffffcccc, 0xffffccff,
2081   0xffffff00, 0xffffff33, 0xffffff66, 0xffffff99, 0xffffffcc, 0xffffffff,
2082   0x00000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
2083   0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
2084   0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
2085   0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
2086   0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
2087   0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
2088   0xff000000, 0xff000000, 0xff000000, 0xff000000
2089 };
2090
2091 static void
2092 pack_RGB8P (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2093     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
2094     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
2095     gint y, gint width)
2096 {
2097   int i;
2098   guint8 *restrict d = GET_LINE (y);
2099   const guint8 *restrict s = src;
2100
2101   /* Use our poor man's palette, taken from ffmpegcolorspace too */
2102   for (i = 0; i < width; i++) {
2103     /* crude approximation for alpha ! */
2104     if (s[i * 4 + 0] < 0x80)
2105       d[i] = 6 * 6 * 6;
2106     else
2107       d[i] =
2108           ((((s[i * 4 + 1]) / 47) % 6) * 6 * 6 + (((s[i * 4 +
2109                           2]) / 47) % 6) * 6 + (((s[i * 4 + 3]) / 47) % 6));
2110   }
2111 }
2112
2113 #define PACK_410 GST_VIDEO_FORMAT_AYUV, unpack_410, 1, pack_410
2114 static void
2115 unpack_410 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2116     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
2117     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
2118 {
2119   gint uv = GET_UV_410 (y, flags);
2120   const guint8 *restrict sy = GET_Y_LINE (y);
2121   const guint8 *restrict su = GET_U_LINE (uv);
2122   const guint8 *restrict sv = GET_V_LINE (uv);
2123   guint8 *restrict d = dest;
2124
2125   sy += x;
2126   su += x >> 2;
2127   sv += x >> 2;
2128
2129   if (x & 3) {
2130     for (; x & 3; x++) {
2131       d[0] = 0xff;
2132       d[1] = *sy++;
2133       d[2] = *su;
2134       d[3] = *sv;
2135       width--;
2136       d += 4;
2137     }
2138     su++;
2139     sy++;
2140   }
2141
2142   if (IS_ALIGNED (d, 8))
2143     video_orc_unpack_YUV9 (d, sy, su, sv, width / 2);
2144   else {
2145     gint i;
2146     for (i = 0; i < width / 2; i++) {
2147       d[i * 8 + 0] = 0xff;
2148       d[i * 8 + 1] = sy[i * 2 + 0];
2149       d[i * 8 + 2] = su[i >> 1];
2150       d[i * 8 + 3] = sv[i >> 1];
2151       d[i * 8 + 4] = 0xff;
2152       d[i * 8 + 5] = sy[i * 2 + 1];
2153       d[i * 8 + 6] = su[i >> 1];
2154       d[i * 8 + 7] = sv[i >> 1];
2155     }
2156   }
2157
2158   if (width & 1) {
2159     gint i = width - 1;
2160
2161     d[i * 4 + 0] = 0xff;
2162     d[i * 4 + 1] = sy[i];
2163     d[i * 4 + 2] = su[i >> 2];
2164     d[i * 4 + 3] = sv[i >> 2];
2165   }
2166 }
2167
2168 static void
2169 pack_410 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2170     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
2171     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
2172     gint y, gint width)
2173 {
2174   int i;
2175   gint uv = GET_UV_410 (y, flags);
2176   guint8 *restrict dy = GET_Y_LINE (y);
2177   guint8 *restrict du = GET_U_LINE (uv);
2178   guint8 *restrict dv = GET_V_LINE (uv);
2179   const guint8 *restrict s = src;
2180
2181   for (i = 0; i < width - 3; i += 4) {
2182     dy[i] = s[i * 4 + 1];
2183     dy[i + 1] = s[i * 4 + 5];
2184     dy[i + 2] = s[i * 4 + 9];
2185     dy[i + 3] = s[i * 4 + 13];
2186     if (IS_CHROMA_LINE_410 (y, flags)) {
2187       du[i >> 2] = s[i * 4 + 2];
2188       dv[i >> 2] = s[i * 4 + 3];
2189     }
2190   }
2191   if (i < width) {
2192     dy[i] = s[i * 4 + 1];
2193     if (IS_CHROMA_LINE_410 (y, flags)) {
2194       du[i >> 2] = s[i * 4 + 2];
2195       dv[i >> 2] = s[i * 4 + 3];
2196     }
2197     if (i < width - 1)
2198       dy[i + 1] = s[i * 4 + 5];
2199     if (i < width - 2)
2200       dy[i + 2] = s[i * 4 + 9];
2201   }
2202 }
2203
2204 #define PACK_IYU1 GST_VIDEO_FORMAT_AYUV, unpack_IYU1, 1, pack_IYU1
2205 static void
2206 unpack_IYU1 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2207     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
2208     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
2209 {
2210   int i;
2211   const guint8 *restrict s = GET_LINE (y);
2212   guint8 *restrict d = dest;
2213   guint8 y0, y1, y2, y3;
2214   guint8 u0;
2215   guint8 v0;
2216
2217   /* FIXME */
2218   s += x * 4;
2219
2220   for (i = 0; i < width - 3; i += 4) {
2221     y0 = s[(i >> 2) * 6 + 1];
2222     y1 = s[(i >> 2) * 6 + 2];
2223     y2 = s[(i >> 2) * 6 + 4];
2224     y3 = s[(i >> 2) * 6 + 5];
2225
2226     u0 = s[(i >> 2) * 6 + 0];
2227     v0 = s[(i >> 2) * 6 + 3];
2228
2229     d[i * 4 + 0] = 0xff;
2230     d[i * 4 + 1] = y0;
2231     d[i * 4 + 2] = u0;
2232     d[i * 4 + 3] = v0;
2233
2234     d[i * 4 + 4] = 0xff;
2235     d[i * 4 + 5] = y1;
2236     d[i * 4 + 6] = u0;
2237     d[i * 4 + 7] = v0;
2238
2239     d[i * 4 + 8] = 0xff;
2240     d[i * 4 + 9] = y2;
2241     d[i * 4 + 10] = u0;
2242     d[i * 4 + 11] = v0;
2243
2244     d[i * 4 + 12] = 0xff;
2245     d[i * 4 + 13] = y3;
2246     d[i * 4 + 14] = u0;
2247     d[i * 4 + 15] = v0;
2248   }
2249   if (i < width) {
2250     u0 = s[(i >> 2) * 6 + 0];
2251     v0 = s[(i >> 2) * 6 + 3];
2252
2253     d[i * 4 + 0] = 0xff;
2254     d[i * 4 + 1] = s[(i >> 2) * 6 + 1];
2255     d[i * 4 + 2] = u0;
2256     d[i * 4 + 3] = v0;
2257
2258     if (i < width - 1) {
2259       d[i * 4 + 4] = 0xff;
2260       d[i * 4 + 5] = s[(i >> 2) * 6 + 2];
2261       d[i * 4 + 6] = u0;
2262       d[i * 4 + 7] = v0;
2263     }
2264     if (i < width - 2) {
2265       d[i * 4 + 8] = 0xff;
2266       d[i * 4 + 9] = s[(i >> 2) * 6 + 4];
2267       d[i * 4 + 10] = u0;
2268       d[i * 4 + 11] = v0;
2269     }
2270   }
2271 }
2272
2273 static void
2274 pack_IYU1 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2275     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
2276     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
2277     gint y, gint width)
2278 {
2279   int i;
2280   guint8 *restrict d = GET_LINE (y);
2281   const guint8 *restrict s = src;
2282
2283   for (i = 0; i < width - 3; i += 4) {
2284     d[(i >> 2) * 6 + 0] = s[i * 4 + 2];
2285     d[(i >> 2) * 6 + 1] = s[i * 4 + 1];
2286     d[(i >> 2) * 6 + 2] = s[i * 4 + 5];
2287     d[(i >> 2) * 6 + 3] = s[i * 4 + 3];
2288     d[(i >> 2) * 6 + 4] = s[i * 4 + 9];
2289     d[(i >> 2) * 6 + 5] = s[i * 4 + 13];
2290   }
2291   if (i < width) {
2292     d[(i >> 2) * 6 + 1] = s[i * 4 + 1];
2293     d[(i >> 2) * 6 + 0] = s[i * 4 + 2];
2294     d[(i >> 2) * 6 + 3] = s[i * 4 + 3];
2295     if (i < width - 1)
2296       d[(i >> 2) * 6 + 2] = s[i * 4 + 5];
2297     if (i < width - 2)
2298       d[(i >> 2) * 6 + 4] = s[i * 4 + 9];
2299   }
2300 }
2301
2302 #define PACK_ARGB64 GST_VIDEO_FORMAT_ARGB64, unpack_copy8, 1, pack_copy8
2303 #define PACK_AYUV64 GST_VIDEO_FORMAT_AYUV64, unpack_copy8, 1, pack_copy8
2304 static void
2305 unpack_copy8 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2306     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
2307     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
2308 {
2309   const guint8 *s = GET_LINE (y);
2310
2311   s += x * 8;
2312
2313   memcpy (dest, s, width * 8);
2314 }
2315
2316 static void
2317 pack_copy8 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2318     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
2319     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
2320     gint y, gint width)
2321 {
2322   guint8 *restrict d = GET_LINE (y);
2323
2324   memcpy (d, src, width * 8);
2325 }
2326
2327 #define PACK_r210 GST_VIDEO_FORMAT_ARGB64, unpack_r210, 1, pack_r210
2328 static void
2329 unpack_r210 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2330     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
2331     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
2332 {
2333   int i;
2334   const guint8 *restrict s = GET_LINE (y);
2335   guint16 *restrict d = dest, R, G, B;
2336
2337   s += x * 4;
2338
2339   for (i = 0; i < width; i++) {
2340     guint32 x = GST_READ_UINT32_BE (s + i * 4);
2341
2342     R = ((x >> 14) & 0xffc0);
2343     G = ((x >> 4) & 0xffc0);
2344     B = ((x << 6) & 0xffc0);
2345
2346     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
2347       R |= (R >> 10);
2348       G |= (G >> 10);
2349       B |= (B >> 10);
2350     }
2351
2352     d[i * 4 + 0] = 0xffff;
2353     d[i * 4 + 1] = R;
2354     d[i * 4 + 2] = G;
2355     d[i * 4 + 3] = B;
2356   }
2357 }
2358
2359 static void
2360 pack_r210 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2361     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
2362     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
2363     gint y, gint width)
2364 {
2365   int i;
2366   guint8 *restrict d = GET_LINE (y);
2367   const guint16 *restrict s = src;
2368
2369   for (i = 0; i < width; i++) {
2370     guint32 x = 0;
2371     x |= (s[i * 4 + 1] & 0xffc0) << 14;
2372     x |= (s[i * 4 + 2] & 0xffc0) << 4;
2373     x |= (s[i * 4 + 3] & 0xffc0) >> 6;
2374     GST_WRITE_UINT32_BE (d + i * 4, x);
2375   }
2376 }
2377
2378 #define PACK_GBR_10LE GST_VIDEO_FORMAT_ARGB64, unpack_GBR_10LE, 1, pack_GBR_10LE
2379 static void
2380 unpack_GBR_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2381     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
2382     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
2383 {
2384   int i;
2385   const guint16 *sg = GET_G_LINE (y);
2386   const guint16 *sb = GET_B_LINE (y);
2387   const guint16 *sr = GET_R_LINE (y);
2388   guint16 *d = dest, G, B, R;
2389
2390   sg += x;
2391   sb += x;
2392   sr += x;
2393
2394   for (i = 0; i < width; i++) {
2395     G = GST_READ_UINT16_LE (sg + i) << 6;
2396     B = GST_READ_UINT16_LE (sb + i) << 6;
2397     R = GST_READ_UINT16_LE (sr + i) << 6;
2398
2399     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
2400       R |= (R >> 10);
2401       G |= (G >> 10);
2402       B |= (B >> 10);
2403     }
2404
2405     d[i * 4 + 0] = 0xffff;
2406     d[i * 4 + 1] = R;
2407     d[i * 4 + 2] = G;
2408     d[i * 4 + 3] = B;
2409   }
2410 }
2411
2412 static void
2413 pack_GBR_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2414     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
2415     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
2416     gint y, gint width)
2417 {
2418   int i;
2419   guint16 *restrict dg = GET_G_LINE (y);
2420   guint16 *restrict db = GET_B_LINE (y);
2421   guint16 *restrict dr = GET_R_LINE (y);
2422   guint16 G, B, R;
2423   const guint16 *restrict s = src;
2424
2425   for (i = 0; i < width; i++) {
2426     G = (s[i * 4 + 2]) >> 6;
2427     B = (s[i * 4 + 3]) >> 6;
2428     R = (s[i * 4 + 1]) >> 6;
2429
2430     GST_WRITE_UINT16_LE (dg + i, G);
2431     GST_WRITE_UINT16_LE (db + i, B);
2432     GST_WRITE_UINT16_LE (dr + i, R);
2433   }
2434 }
2435
2436 #define PACK_GBR_10BE GST_VIDEO_FORMAT_ARGB64, unpack_GBR_10BE, 1, pack_GBR_10BE
2437 static void
2438 unpack_GBR_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2439     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
2440     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
2441 {
2442   int i;
2443   const guint16 *restrict sg = GET_G_LINE (y);
2444   const guint16 *restrict sb = GET_B_LINE (y);
2445   const guint16 *restrict sr = GET_R_LINE (y);
2446   guint16 *restrict d = dest, G, B, R;
2447
2448   sg += x;
2449   sb += x;
2450   sr += x;
2451
2452   for (i = 0; i < width; i++) {
2453     G = GST_READ_UINT16_BE (sg + i) << 6;
2454     B = GST_READ_UINT16_BE (sb + i) << 6;
2455     R = GST_READ_UINT16_BE (sr + i) << 6;
2456
2457     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
2458       R |= (R >> 10);
2459       G |= (G >> 10);
2460       B |= (B >> 10);
2461     }
2462
2463     d[i * 4 + 0] = 0xffff;
2464     d[i * 4 + 1] = R;
2465     d[i * 4 + 2] = G;
2466     d[i * 4 + 3] = B;
2467   }
2468 }
2469
2470 static void
2471 pack_GBR_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2472     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
2473     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
2474     gint y, gint width)
2475 {
2476   int i;
2477   guint16 *restrict dg = GET_G_LINE (y);
2478   guint16 *restrict db = GET_B_LINE (y);
2479   guint16 *restrict dr = GET_R_LINE (y);
2480   guint16 G, B, R;
2481   const guint16 *restrict s = src;
2482
2483   for (i = 0; i < width; i++) {
2484     G = s[i * 4 + 2] >> 6;
2485     B = s[i * 4 + 3] >> 6;
2486     R = s[i * 4 + 1] >> 6;
2487
2488     GST_WRITE_UINT16_BE (dg + i, G);
2489     GST_WRITE_UINT16_BE (db + i, B);
2490     GST_WRITE_UINT16_BE (dr + i, R);
2491   }
2492 }
2493
2494 #define PACK_GBRA_10LE GST_VIDEO_FORMAT_ARGB64, unpack_GBRA_10LE, 1, pack_GBRA_10LE
2495 static void
2496 unpack_GBRA_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2497     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
2498     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
2499 {
2500   int i;
2501   const guint16 *sg = GET_G_LINE (y);
2502   const guint16 *sb = GET_B_LINE (y);
2503   const guint16 *sr = GET_R_LINE (y);
2504   const guint16 *sa = GET_A_LINE (y);
2505   guint16 *d = dest, G, B, R, A;
2506
2507   sg += x;
2508   sb += x;
2509   sr += x;
2510   sa += x;
2511
2512   for (i = 0; i < width; i++) {
2513     G = GST_READ_UINT16_LE (sg + i) << 6;
2514     B = GST_READ_UINT16_LE (sb + i) << 6;
2515     R = GST_READ_UINT16_LE (sr + i) << 6;
2516     A = GST_READ_UINT16_LE (sa + i) << 6;
2517
2518     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
2519       R |= (R >> 10);
2520       G |= (G >> 10);
2521       B |= (B >> 10);
2522       A |= (A >> 10);
2523     }
2524
2525     d[i * 4 + 0] = A;
2526     d[i * 4 + 1] = R;
2527     d[i * 4 + 2] = G;
2528     d[i * 4 + 3] = B;
2529   }
2530 }
2531
2532 static void
2533 pack_GBRA_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2534     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
2535     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
2536     gint y, gint width)
2537 {
2538   int i;
2539   guint16 *restrict dg = GET_G_LINE (y);
2540   guint16 *restrict db = GET_B_LINE (y);
2541   guint16 *restrict dr = GET_R_LINE (y);
2542   guint16 *restrict da = GET_A_LINE (y);
2543   guint16 G, B, R, A;
2544   const guint16 *restrict s = src;
2545
2546   for (i = 0; i < width; i++) {
2547     G = (s[i * 4 + 2]) >> 6;
2548     B = (s[i * 4 + 3]) >> 6;
2549     R = (s[i * 4 + 1]) >> 6;
2550     A = (s[i * 4 + 0]) >> 6;
2551
2552     GST_WRITE_UINT16_LE (dg + i, G);
2553     GST_WRITE_UINT16_LE (db + i, B);
2554     GST_WRITE_UINT16_LE (dr + i, R);
2555     GST_WRITE_UINT16_LE (da + i, A);
2556   }
2557 }
2558
2559 #define PACK_GBRA_10BE GST_VIDEO_FORMAT_ARGB64, unpack_GBRA_10BE, 1, pack_GBRA_10BE
2560 static void
2561 unpack_GBRA_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2562     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
2563     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
2564 {
2565   int i;
2566   const guint16 *restrict sg = GET_G_LINE (y);
2567   const guint16 *restrict sb = GET_B_LINE (y);
2568   const guint16 *restrict sr = GET_R_LINE (y);
2569   const guint16 *restrict sa = GET_A_LINE (y);
2570   guint16 *restrict d = dest, G, B, R, A;
2571
2572   sg += x;
2573   sb += x;
2574   sr += x;
2575   sa += x;
2576
2577   for (i = 0; i < width; i++) {
2578     G = GST_READ_UINT16_BE (sg + i) << 6;
2579     B = GST_READ_UINT16_BE (sb + i) << 6;
2580     R = GST_READ_UINT16_BE (sr + i) << 6;
2581     A = GST_READ_UINT16_BE (sa + i) << 6;
2582
2583     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
2584       R |= (R >> 10);
2585       G |= (G >> 10);
2586       B |= (B >> 10);
2587       A |= (A >> 10);
2588     }
2589
2590     d[i * 4 + 0] = A;
2591     d[i * 4 + 1] = R;
2592     d[i * 4 + 2] = G;
2593     d[i * 4 + 3] = B;
2594   }
2595 }
2596
2597 static void
2598 pack_GBRA_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2599     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
2600     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
2601     gint y, gint width)
2602 {
2603   int i;
2604   guint16 *restrict dg = GET_G_LINE (y);
2605   guint16 *restrict db = GET_B_LINE (y);
2606   guint16 *restrict dr = GET_R_LINE (y);
2607   guint16 *restrict da = GET_A_LINE (y);
2608   guint16 G, B, R, A;
2609   const guint16 *restrict s = src;
2610
2611   for (i = 0; i < width; i++) {
2612     G = s[i * 4 + 2] >> 6;
2613     B = s[i * 4 + 3] >> 6;
2614     R = s[i * 4 + 1] >> 6;
2615     A = s[i * 4 + 0] >> 6;
2616
2617     GST_WRITE_UINT16_BE (dg + i, G);
2618     GST_WRITE_UINT16_BE (db + i, B);
2619     GST_WRITE_UINT16_BE (dr + i, R);
2620     GST_WRITE_UINT16_BE (da + i, A);
2621   }
2622 }
2623
2624 #define PACK_GBR_12LE GST_VIDEO_FORMAT_ARGB64, unpack_GBR_12LE, 1, pack_GBR_12LE
2625 static void
2626 unpack_GBR_12LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2627     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
2628     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
2629 {
2630   int i;
2631   const guint16 *sg = GET_G_LINE (y);
2632   const guint16 *sb = GET_B_LINE (y);
2633   const guint16 *sr = GET_R_LINE (y);
2634   guint16 *d = dest, G, B, R;
2635
2636   sg += x;
2637   sb += x;
2638   sr += x;
2639
2640   for (i = 0; i < width; i++) {
2641     G = GST_READ_UINT16_LE (sg + i) << 4;
2642     B = GST_READ_UINT16_LE (sb + i) << 4;
2643     R = GST_READ_UINT16_LE (sr + i) << 4;
2644
2645     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
2646       R |= (R >> 12);
2647       G |= (G >> 12);
2648       B |= (B >> 12);
2649     }
2650
2651     d[i * 4 + 0] = 0xffff;
2652     d[i * 4 + 1] = R;
2653     d[i * 4 + 2] = G;
2654     d[i * 4 + 3] = B;
2655   }
2656 }
2657
2658 static void
2659 pack_GBR_12LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2660     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
2661     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
2662     gint y, gint width)
2663 {
2664   int i;
2665   guint16 *restrict dg = GET_G_LINE (y);
2666   guint16 *restrict db = GET_B_LINE (y);
2667   guint16 *restrict dr = GET_R_LINE (y);
2668   guint16 G, B, R;
2669   const guint16 *restrict s = src;
2670
2671   for (i = 0; i < width; i++) {
2672     G = (s[i * 4 + 2]) >> 4;
2673     B = (s[i * 4 + 3]) >> 4;
2674     R = (s[i * 4 + 1]) >> 4;
2675
2676     GST_WRITE_UINT16_LE (dg + i, G);
2677     GST_WRITE_UINT16_LE (db + i, B);
2678     GST_WRITE_UINT16_LE (dr + i, R);
2679   }
2680 }
2681
2682 #define PACK_GBR_12BE GST_VIDEO_FORMAT_ARGB64, unpack_GBR_12BE, 1, pack_GBR_12BE
2683 static void
2684 unpack_GBR_12BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2685     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
2686     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
2687 {
2688   int i;
2689   const guint16 *restrict sg = GET_G_LINE (y);
2690   const guint16 *restrict sb = GET_B_LINE (y);
2691   const guint16 *restrict sr = GET_R_LINE (y);
2692   guint16 *restrict d = dest, G, B, R;
2693
2694   sg += x;
2695   sb += x;
2696   sr += x;
2697
2698   for (i = 0; i < width; i++) {
2699     G = GST_READ_UINT16_BE (sg + i) << 4;
2700     B = GST_READ_UINT16_BE (sb + i) << 4;
2701     R = GST_READ_UINT16_BE (sr + i) << 4;
2702
2703     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
2704       R |= (R >> 12);
2705       G |= (G >> 12);
2706       B |= (B >> 12);
2707     }
2708
2709     d[i * 4 + 0] = 0xffff;
2710     d[i * 4 + 1] = R;
2711     d[i * 4 + 2] = G;
2712     d[i * 4 + 3] = B;
2713   }
2714 }
2715
2716 static void
2717 pack_GBR_12BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2718     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
2719     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
2720     gint y, gint width)
2721 {
2722   int i;
2723   guint16 *restrict dg = GET_G_LINE (y);
2724   guint16 *restrict db = GET_B_LINE (y);
2725   guint16 *restrict dr = GET_R_LINE (y);
2726   guint16 G, B, R;
2727   const guint16 *restrict s = src;
2728
2729   for (i = 0; i < width; i++) {
2730     G = s[i * 4 + 2] >> 4;
2731     B = s[i * 4 + 3] >> 4;
2732     R = s[i * 4 + 1] >> 4;
2733
2734     GST_WRITE_UINT16_BE (dg + i, G);
2735     GST_WRITE_UINT16_BE (db + i, B);
2736     GST_WRITE_UINT16_BE (dr + i, R);
2737   }
2738 }
2739
2740 #define PACK_GBRA_12LE GST_VIDEO_FORMAT_ARGB64, unpack_GBRA_12LE, 1, pack_GBRA_12LE
2741 static void
2742 unpack_GBRA_12LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2743     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
2744     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
2745 {
2746   int i;
2747   const guint16 *sg = GET_G_LINE (y);
2748   const guint16 *sb = GET_B_LINE (y);
2749   const guint16 *sr = GET_R_LINE (y);
2750   const guint16 *sa = GET_A_LINE (y);
2751   guint16 *d = dest, G, B, R, A;
2752
2753   sg += x;
2754   sb += x;
2755   sr += x;
2756   sa += x;
2757
2758   for (i = 0; i < width; i++) {
2759     G = GST_READ_UINT16_LE (sg + i) << 4;
2760     B = GST_READ_UINT16_LE (sb + i) << 4;
2761     R = GST_READ_UINT16_LE (sr + i) << 4;
2762     A = GST_READ_UINT16_LE (sa + i) << 4;
2763
2764     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
2765       A |= (A >> 12);
2766       R |= (R >> 12);
2767       G |= (G >> 12);
2768       B |= (B >> 12);
2769     }
2770
2771     d[i * 4 + 0] = A;
2772     d[i * 4 + 1] = R;
2773     d[i * 4 + 2] = G;
2774     d[i * 4 + 3] = B;
2775   }
2776 }
2777
2778 static void
2779 pack_GBRA_12LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2780     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
2781     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
2782     gint y, gint width)
2783 {
2784   int i;
2785   guint16 *restrict dg = GET_G_LINE (y);
2786   guint16 *restrict db = GET_B_LINE (y);
2787   guint16 *restrict dr = GET_R_LINE (y);
2788   guint16 *restrict da = GET_A_LINE (y);
2789   guint16 G, B, R, A;
2790   const guint16 *restrict s = src;
2791
2792   for (i = 0; i < width; i++) {
2793     G = (s[i * 4 + 2]) >> 4;
2794     B = (s[i * 4 + 3]) >> 4;
2795     R = (s[i * 4 + 1]) >> 4;
2796     A = (s[i * 4 + 0]) >> 4;
2797
2798     GST_WRITE_UINT16_LE (dg + i, G);
2799     GST_WRITE_UINT16_LE (db + i, B);
2800     GST_WRITE_UINT16_LE (dr + i, R);
2801     GST_WRITE_UINT16_LE (da + i, A);
2802   }
2803 }
2804
2805 #define PACK_GBRA_12BE GST_VIDEO_FORMAT_ARGB64, unpack_GBRA_12BE, 1, pack_GBRA_12BE
2806 static void
2807 unpack_GBRA_12BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2808     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
2809     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
2810 {
2811   int i;
2812   const guint16 *restrict sg = GET_G_LINE (y);
2813   const guint16 *restrict sb = GET_B_LINE (y);
2814   const guint16 *restrict sr = GET_R_LINE (y);
2815   const guint16 *restrict sa = GET_A_LINE (y);
2816   guint16 *restrict d = dest, G, B, R, A;
2817
2818   sg += x;
2819   sb += x;
2820   sr += x;
2821   sa += x;
2822
2823   for (i = 0; i < width; i++) {
2824     G = GST_READ_UINT16_BE (sg + i) << 4;
2825     B = GST_READ_UINT16_BE (sb + i) << 4;
2826     R = GST_READ_UINT16_BE (sr + i) << 4;
2827     A = GST_READ_UINT16_BE (sa + i) << 4;
2828
2829     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
2830       R |= (R >> 12);
2831       G |= (G >> 12);
2832       B |= (B >> 12);
2833       A |= (A >> 12);
2834     }
2835
2836     d[i * 4 + 0] = A;
2837     d[i * 4 + 1] = R;
2838     d[i * 4 + 2] = G;
2839     d[i * 4 + 3] = B;
2840   }
2841 }
2842
2843 static void
2844 pack_GBRA_12BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2845     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
2846     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
2847     gint y, gint width)
2848 {
2849   int i;
2850   guint16 *restrict dg = GET_G_LINE (y);
2851   guint16 *restrict db = GET_B_LINE (y);
2852   guint16 *restrict dr = GET_R_LINE (y);
2853   guint16 *restrict da = GET_A_LINE (y);
2854   guint16 G, B, R, A;
2855   const guint16 *restrict s = src;
2856
2857   for (i = 0; i < width; i++) {
2858     G = s[i * 4 + 2] >> 4;
2859     B = s[i * 4 + 3] >> 4;
2860     R = s[i * 4 + 1] >> 4;
2861     A = s[i * 4 + 0] >> 4;
2862
2863     GST_WRITE_UINT16_BE (dg + i, G);
2864     GST_WRITE_UINT16_BE (db + i, B);
2865     GST_WRITE_UINT16_BE (dr + i, R);
2866     GST_WRITE_UINT16_BE (da + i, A);
2867   }
2868 }
2869
2870 #define PACK_Y444_10LE GST_VIDEO_FORMAT_AYUV64, unpack_Y444_10LE, 1, pack_Y444_10LE
2871 static void
2872 unpack_Y444_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2873     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
2874     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
2875 {
2876   int i;
2877   guint16 *restrict sy = GET_Y_LINE (y);
2878   guint16 *restrict su = GET_U_LINE (y);
2879   guint16 *restrict sv = GET_V_LINE (y);
2880   guint16 *restrict d = dest, Y, U, V;
2881
2882   sy += x;
2883   su += x;
2884   sv += x;
2885
2886   for (i = 0; i < width; i++) {
2887     Y = GST_READ_UINT16_LE (sy + i) << 6;
2888     U = GST_READ_UINT16_LE (su + i) << 6;
2889     V = GST_READ_UINT16_LE (sv + i) << 6;
2890
2891     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
2892       Y |= (Y >> 10);
2893       U |= (U >> 10);
2894       V |= (V >> 10);
2895     }
2896
2897     d[i * 4 + 0] = 0xffff;
2898     d[i * 4 + 1] = Y;
2899     d[i * 4 + 2] = U;
2900     d[i * 4 + 3] = V;
2901   }
2902 }
2903
2904 static void
2905 pack_Y444_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2906     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
2907     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
2908     gint y, gint width)
2909 {
2910   int i;
2911   guint16 *restrict dy = GET_Y_LINE (y);
2912   guint16 *restrict du = GET_U_LINE (y);
2913   guint16 *restrict dv = GET_V_LINE (y);
2914   guint16 Y, U, V;
2915   const guint16 *restrict s = src;
2916
2917   for (i = 0; i < width; i++) {
2918     Y = (s[i * 4 + 1]) >> 6;
2919     U = (s[i * 4 + 2]) >> 6;
2920     V = (s[i * 4 + 3]) >> 6;
2921
2922     GST_WRITE_UINT16_LE (dy + i, Y);
2923     GST_WRITE_UINT16_LE (du + i, U);
2924     GST_WRITE_UINT16_LE (dv + i, V);
2925   }
2926 }
2927
2928 #define PACK_Y444_10BE GST_VIDEO_FORMAT_AYUV64, unpack_Y444_10BE, 1, pack_Y444_10BE
2929 static void
2930 unpack_Y444_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2931     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
2932     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
2933 {
2934   int i;
2935   const guint16 *restrict sy = GET_Y_LINE (y);
2936   const guint16 *restrict su = GET_U_LINE (y);
2937   const guint16 *restrict sv = GET_V_LINE (y);
2938   guint16 *restrict d = dest, Y, U, V;
2939
2940   sy += x;
2941   su += x;
2942   sv += x;
2943
2944   for (i = 0; i < width; i++) {
2945     Y = GST_READ_UINT16_BE (sy + i) << 6;
2946     U = GST_READ_UINT16_BE (su + i) << 6;
2947     V = GST_READ_UINT16_BE (sv + i) << 6;
2948
2949     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
2950       Y |= (Y >> 10);
2951       U |= (U >> 10);
2952       V |= (V >> 10);
2953     }
2954
2955     d[i * 4 + 0] = 0xffff;
2956     d[i * 4 + 1] = Y;
2957     d[i * 4 + 2] = U;
2958     d[i * 4 + 3] = V;
2959   }
2960 }
2961
2962 static void
2963 pack_Y444_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2964     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
2965     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
2966     gint y, gint width)
2967 {
2968   int i;
2969   guint16 *restrict dy = GET_Y_LINE (y);
2970   guint16 *restrict du = GET_U_LINE (y);
2971   guint16 *restrict dv = GET_V_LINE (y);
2972   guint16 Y, U, V;
2973   const guint16 *restrict s = src;
2974
2975   for (i = 0; i < width; i++) {
2976     Y = s[i * 4 + 1] >> 6;
2977     U = s[i * 4 + 2] >> 6;
2978     V = s[i * 4 + 3] >> 6;
2979
2980     GST_WRITE_UINT16_BE (dy + i, Y);
2981     GST_WRITE_UINT16_BE (du + i, U);
2982     GST_WRITE_UINT16_BE (dv + i, V);
2983   }
2984 }
2985
2986 #define PACK_I420_10LE GST_VIDEO_FORMAT_AYUV64, unpack_I420_10LE, 1, pack_I420_10LE
2987 static void
2988 unpack_I420_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2989     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
2990     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
2991 {
2992   int i;
2993   gint uv = GET_UV_420 (y, flags);
2994   const guint16 *restrict sy = GET_Y_LINE (y);
2995   const guint16 *restrict su = GET_U_LINE (uv);
2996   const guint16 *restrict sv = GET_V_LINE (uv);
2997   guint16 *restrict d = dest, Y, U, V;
2998
2999   sy += x;
3000   su += x >> 1;
3001   sv += x >> 1;
3002
3003   for (i = 0; i < width; i++) {
3004     Y = GST_READ_UINT16_LE (sy + i) << 6;
3005     U = GST_READ_UINT16_LE (su + (i >> 1)) << 6;
3006     V = GST_READ_UINT16_LE (sv + (i >> 1)) << 6;
3007
3008     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
3009       Y |= (Y >> 10);
3010       U |= (U >> 10);
3011       V |= (V >> 10);
3012     }
3013
3014     d[i * 4 + 0] = 0xffff;
3015     d[i * 4 + 1] = Y;
3016     d[i * 4 + 2] = U;
3017     d[i * 4 + 3] = V;
3018
3019     if (x & 1) {
3020       x = 0;
3021       su++;
3022       sv++;
3023     }
3024   }
3025 }
3026
3027 static void
3028 pack_I420_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3029     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
3030     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
3031     gint y, gint width)
3032 {
3033   int i;
3034   gint uv = GET_UV_420 (y, flags);
3035   guint16 *restrict dy = GET_Y_LINE (y);
3036   guint16 *restrict du = GET_U_LINE (uv);
3037   guint16 *restrict dv = GET_V_LINE (uv);
3038   guint16 Y0, Y1, U, V;
3039   const guint16 *restrict s = src;
3040
3041   if (IS_CHROMA_LINE_420 (y, flags)) {
3042     for (i = 0; i < width - 1; i += 2) {
3043       Y0 = s[i * 4 + 1] >> 6;
3044       Y1 = s[i * 4 + 5] >> 6;
3045       U = s[i * 4 + 2] >> 6;
3046       V = s[i * 4 + 3] >> 6;
3047
3048       GST_WRITE_UINT16_LE (dy + i + 0, Y0);
3049       GST_WRITE_UINT16_LE (dy + i + 1, Y1);
3050       GST_WRITE_UINT16_LE (du + (i >> 1), U);
3051       GST_WRITE_UINT16_LE (dv + (i >> 1), V);
3052     }
3053     if (i == width - 1) {
3054       Y0 = s[i * 4 + 1] >> 6;
3055       U = s[i * 4 + 2] >> 6;
3056       V = s[i * 4 + 3] >> 6;
3057
3058       GST_WRITE_UINT16_LE (dy + i, Y0);
3059       GST_WRITE_UINT16_LE (du + (i >> 1), U);
3060       GST_WRITE_UINT16_LE (dv + (i >> 1), V);
3061     }
3062   } else {
3063     for (i = 0; i < width; i++) {
3064       Y0 = s[i * 4 + 1] >> 6;
3065       GST_WRITE_UINT16_LE (dy + i, Y0);
3066     }
3067   }
3068 }
3069
3070 #define PACK_I420_10BE GST_VIDEO_FORMAT_AYUV64, unpack_I420_10BE, 1, pack_I420_10BE
3071 static void
3072 unpack_I420_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3073     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
3074     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
3075 {
3076   int i;
3077   gint uv = GET_UV_420 (y, flags);
3078   const guint16 *restrict sy = GET_Y_LINE (y);
3079   const guint16 *restrict su = GET_U_LINE (uv);
3080   const guint16 *restrict sv = GET_V_LINE (uv);
3081   guint16 *restrict d = dest, Y, U, V;
3082
3083   sy += x;
3084   su += x >> 1;
3085   sv += x >> 1;
3086
3087   for (i = 0; i < width; i++) {
3088     Y = GST_READ_UINT16_BE (sy + i) << 6;
3089     U = GST_READ_UINT16_BE (su + (i >> 1)) << 6;
3090     V = GST_READ_UINT16_BE (sv + (i >> 1)) << 6;
3091
3092     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
3093       Y |= (Y >> 10);
3094       U |= (U >> 10);
3095       V |= (V >> 10);
3096     }
3097
3098     d[i * 4 + 0] = 0xffff;
3099     d[i * 4 + 1] = Y;
3100     d[i * 4 + 2] = U;
3101     d[i * 4 + 3] = V;
3102
3103     if (x & 1) {
3104       x = 0;
3105       su++;
3106       sv++;
3107     }
3108   }
3109 }
3110
3111 static void
3112 pack_I420_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3113     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
3114     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
3115     gint y, gint width)
3116 {
3117   int i;
3118   gint uv = GET_UV_420 (y, flags);
3119   guint16 *restrict dy = GET_Y_LINE (y);
3120   guint16 *restrict du = GET_U_LINE (uv);
3121   guint16 *restrict dv = GET_V_LINE (uv);
3122   guint16 Y0, Y1, U, V;
3123   const guint16 *restrict s = src;
3124
3125   if (IS_CHROMA_LINE_420 (y, flags)) {
3126     for (i = 0; i < width - 1; i += 2) {
3127       Y0 = s[i * 4 + 1] >> 6;
3128       Y1 = s[i * 4 + 5] >> 6;
3129       U = s[i * 4 + 2] >> 6;
3130       V = s[i * 4 + 3] >> 6;
3131
3132       GST_WRITE_UINT16_BE (dy + i + 0, Y0);
3133       GST_WRITE_UINT16_BE (dy + i + 1, Y1);
3134       GST_WRITE_UINT16_BE (du + (i >> 1), U);
3135       GST_WRITE_UINT16_BE (dv + (i >> 1), V);
3136     }
3137     if (i == width - 1) {
3138       Y0 = s[i * 4 + 1] >> 6;
3139       U = s[i * 4 + 2] >> 6;
3140       V = s[i * 4 + 3] >> 6;
3141
3142       GST_WRITE_UINT16_BE (dy + i, Y0);
3143       GST_WRITE_UINT16_BE (du + (i >> 1), U);
3144       GST_WRITE_UINT16_BE (dv + (i >> 1), V);
3145     }
3146   } else {
3147     for (i = 0; i < width; i++) {
3148       Y0 = s[i * 4 + 1] >> 6;
3149       GST_WRITE_UINT16_BE (dy + i, Y0);
3150     }
3151   }
3152 }
3153
3154 #define PACK_I422_10LE GST_VIDEO_FORMAT_AYUV64, unpack_I422_10LE, 1, pack_I422_10LE
3155 static void
3156 unpack_I422_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3157     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
3158     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
3159 {
3160   int i;
3161   const guint16 *restrict sy = GET_Y_LINE (y);
3162   const guint16 *restrict su = GET_U_LINE (y);
3163   const guint16 *restrict sv = GET_V_LINE (y);
3164   guint16 *restrict d = dest, Y, U, V;
3165
3166   sy += x;
3167   su += x >> 1;
3168   sv += x >> 1;
3169
3170   for (i = 0; i < width; i++) {
3171     Y = GST_READ_UINT16_LE (sy + i) << 6;
3172     U = GST_READ_UINT16_LE (su + (i >> 1)) << 6;
3173     V = GST_READ_UINT16_LE (sv + (i >> 1)) << 6;
3174
3175     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
3176       Y |= (Y >> 10);
3177       U |= (U >> 10);
3178       V |= (V >> 10);
3179     }
3180
3181     d[i * 4 + 0] = 0xffff;
3182     d[i * 4 + 1] = Y;
3183     d[i * 4 + 2] = U;
3184     d[i * 4 + 3] = V;
3185
3186     if (x & 1) {
3187       x = 0;
3188       su++;
3189       sv++;
3190     }
3191   }
3192 }
3193
3194 static void
3195 pack_I422_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3196     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
3197     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
3198     gint y, gint width)
3199 {
3200   int i;
3201   guint16 *restrict dy = GET_Y_LINE (y);
3202   guint16 *restrict du = GET_U_LINE (y);
3203   guint16 *restrict dv = GET_V_LINE (y);
3204   guint16 Y0, Y1, U, V;
3205   const guint16 *restrict s = src;
3206
3207   for (i = 0; i < width - 1; i += 2) {
3208     Y0 = s[i * 4 + 1] >> 6;
3209     Y1 = s[i * 4 + 5] >> 6;
3210     U = s[i * 4 + 2] >> 6;
3211     V = s[i * 4 + 3] >> 6;
3212
3213     GST_WRITE_UINT16_LE (dy + i + 0, Y0);
3214     GST_WRITE_UINT16_LE (dy + i + 1, Y1);
3215     GST_WRITE_UINT16_LE (du + (i >> 1), U);
3216     GST_WRITE_UINT16_LE (dv + (i >> 1), V);
3217   }
3218   if (i == width - 1) {
3219     Y0 = s[i * 4 + 1] >> 6;
3220     U = s[i * 4 + 2] >> 6;
3221     V = s[i * 4 + 3] >> 6;
3222
3223     GST_WRITE_UINT16_LE (dy + i, Y0);
3224     GST_WRITE_UINT16_LE (du + (i >> 1), U);
3225     GST_WRITE_UINT16_LE (dv + (i >> 1), V);
3226   }
3227 }
3228
3229 #define PACK_I422_10BE GST_VIDEO_FORMAT_AYUV64, unpack_I422_10BE, 1, pack_I422_10BE
3230 static void
3231 unpack_I422_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3232     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
3233     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
3234 {
3235   int i;
3236   const guint16 *restrict sy = GET_Y_LINE (y);
3237   const guint16 *restrict su = GET_U_LINE (y);
3238   const guint16 *restrict sv = GET_V_LINE (y);
3239   guint16 *restrict d = dest, Y, U, V;
3240
3241   sy += x;
3242   su += x >> 1;
3243   sv += x >> 1;
3244
3245   for (i = 0; i < width; i++) {
3246     Y = GST_READ_UINT16_BE (sy + i) << 6;
3247     U = GST_READ_UINT16_BE (su + (i >> 1)) << 6;
3248     V = GST_READ_UINT16_BE (sv + (i >> 1)) << 6;
3249
3250     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
3251       Y |= (Y >> 10);
3252       U |= (U >> 10);
3253       V |= (V >> 10);
3254     }
3255
3256     d[i * 4 + 0] = 0xffff;
3257     d[i * 4 + 1] = Y;
3258     d[i * 4 + 2] = U;
3259     d[i * 4 + 3] = V;
3260
3261     if (x & 1) {
3262       x = 0;
3263       su++;
3264       sv++;
3265     }
3266   }
3267 }
3268
3269 static void
3270 pack_I422_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3271     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
3272     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
3273     gint y, gint width)
3274 {
3275   int i;
3276   guint16 *restrict dy = GET_Y_LINE (y);
3277   guint16 *restrict du = GET_U_LINE (y);
3278   guint16 *restrict dv = GET_V_LINE (y);
3279   guint16 Y0, Y1, U, V;
3280   const guint16 *restrict s = src;
3281
3282   for (i = 0; i < width - 1; i += 2) {
3283     Y0 = s[i * 4 + 1] >> 6;
3284     Y1 = s[i * 4 + 5] >> 6;
3285     U = s[i * 4 + 2] >> 6;
3286     V = s[i * 4 + 3] >> 6;
3287
3288     GST_WRITE_UINT16_BE (dy + i + 0, Y0);
3289     GST_WRITE_UINT16_BE (dy + i + 1, Y1);
3290     GST_WRITE_UINT16_BE (du + (i >> 1), U);
3291     GST_WRITE_UINT16_BE (dv + (i >> 1), V);
3292   }
3293   if (i == width - 1) {
3294     Y0 = s[i * 4 + 1] >> 6;
3295     U = s[i * 4 + 2] >> 6;
3296     V = s[i * 4 + 3] >> 6;
3297
3298     GST_WRITE_UINT16_BE (dy + i, Y0);
3299     GST_WRITE_UINT16_BE (du + (i >> 1), U);
3300     GST_WRITE_UINT16_BE (dv + (i >> 1), V);
3301   }
3302 }
3303
3304 #define PACK_Y444_12LE GST_VIDEO_FORMAT_AYUV64, unpack_Y444_12LE, 1, pack_Y444_12LE
3305 static void
3306 unpack_Y444_12LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3307     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
3308     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
3309 {
3310   int i;
3311   guint16 *restrict sy = GET_Y_LINE (y);
3312   guint16 *restrict su = GET_U_LINE (y);
3313   guint16 *restrict sv = GET_V_LINE (y);
3314   guint16 *restrict d = dest, Y, U, V;
3315
3316   sy += x;
3317   su += x;
3318   sv += x;
3319
3320   for (i = 0; i < width; i++) {
3321     Y = GST_READ_UINT16_LE (sy + i) << 4;
3322     U = GST_READ_UINT16_LE (su + i) << 4;
3323     V = GST_READ_UINT16_LE (sv + i) << 4;
3324
3325     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
3326       Y |= (Y >> 12);
3327       U |= (U >> 12);
3328       V |= (V >> 12);
3329     }
3330
3331     d[i * 4 + 0] = 0xffff;
3332     d[i * 4 + 1] = Y;
3333     d[i * 4 + 2] = U;
3334     d[i * 4 + 3] = V;
3335   }
3336 }
3337
3338 static void
3339 pack_Y444_12LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3340     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
3341     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
3342     gint y, gint width)
3343 {
3344   int i;
3345   guint16 *restrict dy = GET_Y_LINE (y);
3346   guint16 *restrict du = GET_U_LINE (y);
3347   guint16 *restrict dv = GET_V_LINE (y);
3348   guint16 Y, U, V;
3349   const guint16 *restrict s = src;
3350
3351   for (i = 0; i < width; i++) {
3352     Y = (s[i * 4 + 1]) >> 4;
3353     U = (s[i * 4 + 2]) >> 4;
3354     V = (s[i * 4 + 3]) >> 4;
3355
3356     GST_WRITE_UINT16_LE (dy + i, Y);
3357     GST_WRITE_UINT16_LE (du + i, U);
3358     GST_WRITE_UINT16_LE (dv + i, V);
3359   }
3360 }
3361
3362 #define PACK_Y444_12BE GST_VIDEO_FORMAT_AYUV64, unpack_Y444_12BE, 1, pack_Y444_12BE
3363 static void
3364 unpack_Y444_12BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3365     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
3366     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
3367 {
3368   int i;
3369   const guint16 *restrict sy = GET_Y_LINE (y);
3370   const guint16 *restrict su = GET_U_LINE (y);
3371   const guint16 *restrict sv = GET_V_LINE (y);
3372   guint16 *restrict d = dest, Y, U, V;
3373
3374   sy += x;
3375   su += x;
3376   sv += x;
3377
3378   for (i = 0; i < width; i++) {
3379     Y = GST_READ_UINT16_BE (sy + i) << 4;
3380     U = GST_READ_UINT16_BE (su + i) << 4;
3381     V = GST_READ_UINT16_BE (sv + i) << 4;
3382
3383     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
3384       Y |= (Y >> 12);
3385       U |= (U >> 12);
3386       V |= (V >> 12);
3387     }
3388
3389     d[i * 4 + 0] = 0xffff;
3390     d[i * 4 + 1] = Y;
3391     d[i * 4 + 2] = U;
3392     d[i * 4 + 3] = V;
3393   }
3394 }
3395
3396 static void
3397 pack_Y444_12BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3398     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
3399     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
3400     gint y, gint width)
3401 {
3402   int i;
3403   guint16 *restrict dy = GET_Y_LINE (y);
3404   guint16 *restrict du = GET_U_LINE (y);
3405   guint16 *restrict dv = GET_V_LINE (y);
3406   guint16 Y, U, V;
3407   const guint16 *restrict s = src;
3408
3409   for (i = 0; i < width; i++) {
3410     Y = s[i * 4 + 1] >> 4;
3411     U = s[i * 4 + 2] >> 4;
3412     V = s[i * 4 + 3] >> 4;
3413
3414     GST_WRITE_UINT16_BE (dy + i, Y);
3415     GST_WRITE_UINT16_BE (du + i, U);
3416     GST_WRITE_UINT16_BE (dv + i, V);
3417   }
3418 }
3419
3420 #define PACK_I420_12LE GST_VIDEO_FORMAT_AYUV64, unpack_I420_12LE, 1, pack_I420_12LE
3421 static void
3422 unpack_I420_12LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3423     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
3424     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
3425 {
3426   int i;
3427   gint uv = GET_UV_420 (y, flags);
3428   const guint16 *restrict sy = GET_Y_LINE (y);
3429   const guint16 *restrict su = GET_U_LINE (uv);
3430   const guint16 *restrict sv = GET_V_LINE (uv);
3431   guint16 *restrict d = dest, Y, U, V;
3432
3433   sy += x;
3434   su += x >> 1;
3435   sv += x >> 1;
3436
3437   for (i = 0; i < width; i++) {
3438     Y = GST_READ_UINT16_LE (sy + i) << 4;
3439     U = GST_READ_UINT16_LE (su + (i >> 1)) << 4;
3440     V = GST_READ_UINT16_LE (sv + (i >> 1)) << 4;
3441
3442     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
3443       Y |= (Y >> 12);
3444       U |= (U >> 12);
3445       V |= (V >> 12);
3446     }
3447
3448     d[i * 4 + 0] = 0xffff;
3449     d[i * 4 + 1] = Y;
3450     d[i * 4 + 2] = U;
3451     d[i * 4 + 3] = V;
3452
3453     if (x & 1) {
3454       x = 0;
3455       su++;
3456       sv++;
3457     }
3458   }
3459 }
3460
3461 static void
3462 pack_I420_12LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3463     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
3464     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
3465     gint y, gint width)
3466 {
3467   int i;
3468   gint uv = GET_UV_420 (y, flags);
3469   guint16 *restrict dy = GET_Y_LINE (y);
3470   guint16 *restrict du = GET_U_LINE (uv);
3471   guint16 *restrict dv = GET_V_LINE (uv);
3472   guint16 Y0, Y1, U, V;
3473   const guint16 *restrict s = src;
3474
3475   if (IS_CHROMA_LINE_420 (y, flags)) {
3476     for (i = 0; i < width - 1; i += 2) {
3477       Y0 = s[i * 4 + 1] >> 4;
3478       Y1 = s[i * 4 + 5] >> 4;
3479       U = s[i * 4 + 2] >> 4;
3480       V = s[i * 4 + 3] >> 4;
3481
3482       GST_WRITE_UINT16_LE (dy + i + 0, Y0);
3483       GST_WRITE_UINT16_LE (dy + i + 1, Y1);
3484       GST_WRITE_UINT16_LE (du + (i >> 1), U);
3485       GST_WRITE_UINT16_LE (dv + (i >> 1), V);
3486     }
3487     if (i == width - 1) {
3488       Y0 = s[i * 4 + 1] >> 4;
3489       U = s[i * 4 + 2] >> 4;
3490       V = s[i * 4 + 3] >> 4;
3491
3492       GST_WRITE_UINT16_LE (dy + i, Y0);
3493       GST_WRITE_UINT16_LE (du + (i >> 1), U);
3494       GST_WRITE_UINT16_LE (dv + (i >> 1), V);
3495     }
3496   } else {
3497     for (i = 0; i < width; i++) {
3498       Y0 = s[i * 4 + 1] >> 4;
3499       GST_WRITE_UINT16_LE (dy + i, Y0);
3500     }
3501   }
3502 }
3503
3504 #define PACK_I420_12BE GST_VIDEO_FORMAT_AYUV64, unpack_I420_12BE, 1, pack_I420_12BE
3505 static void
3506 unpack_I420_12BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3507     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
3508     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
3509 {
3510   int i;
3511   gint uv = GET_UV_420 (y, flags);
3512   const guint16 *restrict sy = GET_Y_LINE (y);
3513   const guint16 *restrict su = GET_U_LINE (uv);
3514   const guint16 *restrict sv = GET_V_LINE (uv);
3515   guint16 *restrict d = dest, Y, U, V;
3516
3517   sy += x;
3518   su += x >> 1;
3519   sv += x >> 1;
3520
3521   for (i = 0; i < width; i++) {
3522     Y = GST_READ_UINT16_BE (sy + i) << 4;
3523     U = GST_READ_UINT16_BE (su + (i >> 1)) << 4;
3524     V = GST_READ_UINT16_BE (sv + (i >> 1)) << 4;
3525
3526     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
3527       Y |= (Y >> 12);
3528       U |= (U >> 12);
3529       V |= (V >> 12);
3530     }
3531
3532     d[i * 4 + 0] = 0xffff;
3533     d[i * 4 + 1] = Y;
3534     d[i * 4 + 2] = U;
3535     d[i * 4 + 3] = V;
3536
3537     if (x & 1) {
3538       x = 0;
3539       su++;
3540       sv++;
3541     }
3542   }
3543 }
3544
3545 static void
3546 pack_I420_12BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3547     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
3548     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
3549     gint y, gint width)
3550 {
3551   int i;
3552   gint uv = GET_UV_420 (y, flags);
3553   guint16 *restrict dy = GET_Y_LINE (y);
3554   guint16 *restrict du = GET_U_LINE (uv);
3555   guint16 *restrict dv = GET_V_LINE (uv);
3556   guint16 Y0, Y1, U, V;
3557   const guint16 *restrict s = src;
3558
3559   if (IS_CHROMA_LINE_420 (y, flags)) {
3560     for (i = 0; i < width - 1; i += 2) {
3561       Y0 = s[i * 4 + 1] >> 4;
3562       Y1 = s[i * 4 + 5] >> 4;
3563       U = s[i * 4 + 2] >> 4;
3564       V = s[i * 4 + 3] >> 4;
3565
3566       GST_WRITE_UINT16_BE (dy + i + 0, Y0);
3567       GST_WRITE_UINT16_BE (dy + i + 1, Y1);
3568       GST_WRITE_UINT16_BE (du + (i >> 1), U);
3569       GST_WRITE_UINT16_BE (dv + (i >> 1), V);
3570     }
3571     if (i == width - 1) {
3572       Y0 = s[i * 4 + 1] >> 4;
3573       U = s[i * 4 + 2] >> 4;
3574       V = s[i * 4 + 3] >> 4;
3575
3576       GST_WRITE_UINT16_BE (dy + i, Y0);
3577       GST_WRITE_UINT16_BE (du + (i >> 1), U);
3578       GST_WRITE_UINT16_BE (dv + (i >> 1), V);
3579     }
3580   } else {
3581     for (i = 0; i < width; i++) {
3582       Y0 = s[i * 4 + 1] >> 4;
3583       GST_WRITE_UINT16_BE (dy + i, Y0);
3584     }
3585   }
3586 }
3587
3588 #define PACK_I422_12LE GST_VIDEO_FORMAT_AYUV64, unpack_I422_12LE, 1, pack_I422_12LE
3589 static void
3590 unpack_I422_12LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3591     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
3592     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
3593 {
3594   int i;
3595   const guint16 *restrict sy = GET_Y_LINE (y);
3596   const guint16 *restrict su = GET_U_LINE (y);
3597   const guint16 *restrict sv = GET_V_LINE (y);
3598   guint16 *restrict d = dest, Y, U, V;
3599
3600   sy += x;
3601   su += x >> 1;
3602   sv += x >> 1;
3603
3604   for (i = 0; i < width; i++) {
3605     Y = GST_READ_UINT16_LE (sy + i) << 4;
3606     U = GST_READ_UINT16_LE (su + (i >> 1)) << 4;
3607     V = GST_READ_UINT16_LE (sv + (i >> 1)) << 4;
3608
3609     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
3610       Y |= (Y >> 12);
3611       U |= (U >> 12);
3612       V |= (V >> 12);
3613     }
3614
3615     d[i * 4 + 0] = 0xffff;
3616     d[i * 4 + 1] = Y;
3617     d[i * 4 + 2] = U;
3618     d[i * 4 + 3] = V;
3619
3620     if (x & 1) {
3621       x = 0;
3622       su++;
3623       sv++;
3624     }
3625   }
3626 }
3627
3628 static void
3629 pack_I422_12LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3630     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
3631     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
3632     gint y, gint width)
3633 {
3634   int i;
3635   guint16 *restrict dy = GET_Y_LINE (y);
3636   guint16 *restrict du = GET_U_LINE (y);
3637   guint16 *restrict dv = GET_V_LINE (y);
3638   guint16 Y0, Y1, U, V;
3639   const guint16 *restrict s = src;
3640
3641   for (i = 0; i < width - 1; i += 2) {
3642     Y0 = s[i * 4 + 1] >> 4;
3643     Y1 = s[i * 4 + 5] >> 4;
3644     U = s[i * 4 + 2] >> 4;
3645     V = s[i * 4 + 3] >> 4;
3646
3647     GST_WRITE_UINT16_LE (dy + i + 0, Y0);
3648     GST_WRITE_UINT16_LE (dy + i + 1, Y1);
3649     GST_WRITE_UINT16_LE (du + (i >> 1), U);
3650     GST_WRITE_UINT16_LE (dv + (i >> 1), V);
3651   }
3652   if (i == width - 1) {
3653     Y0 = s[i * 4 + 1] >> 4;
3654     U = s[i * 4 + 2] >> 4;
3655     V = s[i * 4 + 3] >> 4;
3656
3657     GST_WRITE_UINT16_LE (dy + i, Y0);
3658     GST_WRITE_UINT16_LE (du + (i >> 1), U);
3659     GST_WRITE_UINT16_LE (dv + (i >> 1), V);
3660   }
3661 }
3662
3663 #define PACK_I422_12BE GST_VIDEO_FORMAT_AYUV64, unpack_I422_12BE, 1, pack_I422_12BE
3664 static void
3665 unpack_I422_12BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3666     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
3667     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
3668 {
3669   int i;
3670   const guint16 *restrict sy = GET_Y_LINE (y);
3671   const guint16 *restrict su = GET_U_LINE (y);
3672   const guint16 *restrict sv = GET_V_LINE (y);
3673   guint16 *restrict d = dest, Y, U, V;
3674
3675   sy += x;
3676   su += x >> 1;
3677   sv += x >> 1;
3678
3679   for (i = 0; i < width; i++) {
3680     Y = GST_READ_UINT16_BE (sy + i) << 4;
3681     U = GST_READ_UINT16_BE (su + (i >> 1)) << 4;
3682     V = GST_READ_UINT16_BE (sv + (i >> 1)) << 4;
3683
3684     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
3685       Y |= (Y >> 12);
3686       U |= (U >> 12);
3687       V |= (V >> 12);
3688     }
3689
3690     d[i * 4 + 0] = 0xffff;
3691     d[i * 4 + 1] = Y;
3692     d[i * 4 + 2] = U;
3693     d[i * 4 + 3] = V;
3694
3695     if (x & 1) {
3696       x = 0;
3697       su++;
3698       sv++;
3699     }
3700   }
3701 }
3702
3703 static void
3704 pack_I422_12BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3705     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
3706     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
3707     gint y, gint width)
3708 {
3709   int i;
3710   guint16 *restrict dy = GET_Y_LINE (y);
3711   guint16 *restrict du = GET_U_LINE (y);
3712   guint16 *restrict dv = GET_V_LINE (y);
3713   guint16 Y0, Y1, U, V;
3714   const guint16 *restrict s = src;
3715
3716   for (i = 0; i < width - 1; i += 2) {
3717     Y0 = s[i * 4 + 1] >> 4;
3718     Y1 = s[i * 4 + 5] >> 4;
3719     U = s[i * 4 + 2] >> 4;
3720     V = s[i * 4 + 3] >> 4;
3721
3722     GST_WRITE_UINT16_BE (dy + i + 0, Y0);
3723     GST_WRITE_UINT16_BE (dy + i + 1, Y1);
3724     GST_WRITE_UINT16_BE (du + (i >> 1), U);
3725     GST_WRITE_UINT16_BE (dv + (i >> 1), V);
3726   }
3727   if (i == width - 1) {
3728     Y0 = s[i * 4 + 1] >> 4;
3729     U = s[i * 4 + 2] >> 4;
3730     V = s[i * 4 + 3] >> 4;
3731
3732     GST_WRITE_UINT16_BE (dy + i, Y0);
3733     GST_WRITE_UINT16_BE (du + (i >> 1), U);
3734     GST_WRITE_UINT16_BE (dv + (i >> 1), V);
3735   }
3736 }
3737
3738 #define PACK_A444_10LE GST_VIDEO_FORMAT_AYUV64, unpack_A444_10LE, 1, pack_A444_10LE
3739 static void
3740 unpack_A444_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3741     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
3742     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
3743 {
3744   int i;
3745   guint16 *restrict sa = GET_A_LINE (y);
3746   guint16 *restrict sy = GET_Y_LINE (y);
3747   guint16 *restrict su = GET_U_LINE (y);
3748   guint16 *restrict sv = GET_V_LINE (y);
3749   guint16 *restrict d = dest, A, Y, U, V;
3750
3751   sa += x;
3752   sy += x;
3753   su += x;
3754   sv += x;
3755
3756   for (i = 0; i < width; i++) {
3757     A = GST_READ_UINT16_LE (sa + i) << 6;
3758     Y = GST_READ_UINT16_LE (sy + i) << 6;
3759     U = GST_READ_UINT16_LE (su + i) << 6;
3760     V = GST_READ_UINT16_LE (sv + i) << 6;
3761
3762     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
3763       A |= (A >> 10);
3764       Y |= (Y >> 10);
3765       U |= (U >> 10);
3766       V |= (V >> 10);
3767     }
3768
3769     d[i * 4 + 0] = A;
3770     d[i * 4 + 1] = Y;
3771     d[i * 4 + 2] = U;
3772     d[i * 4 + 3] = V;
3773   }
3774 }
3775
3776 static void
3777 pack_A444_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3778     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
3779     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
3780     gint y, gint width)
3781 {
3782   int i;
3783   guint16 *restrict da = GET_A_LINE (y);
3784   guint16 *restrict dy = GET_Y_LINE (y);
3785   guint16 *restrict du = GET_U_LINE (y);
3786   guint16 *restrict dv = GET_V_LINE (y);
3787   guint16 A, Y, U, V;
3788   const guint16 *restrict s = src;
3789
3790   for (i = 0; i < width; i++) {
3791     A = (s[i * 4 + 0]) >> 6;
3792     Y = (s[i * 4 + 1]) >> 6;
3793     U = (s[i * 4 + 2]) >> 6;
3794     V = (s[i * 4 + 3]) >> 6;
3795
3796     GST_WRITE_UINT16_LE (da + i, A);
3797     GST_WRITE_UINT16_LE (dy + i, Y);
3798     GST_WRITE_UINT16_LE (du + i, U);
3799     GST_WRITE_UINT16_LE (dv + i, V);
3800   }
3801 }
3802
3803 #define PACK_A444_10BE GST_VIDEO_FORMAT_AYUV64, unpack_A444_10BE, 1, pack_A444_10BE
3804 static void
3805 unpack_A444_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3806     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
3807     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
3808 {
3809   int i;
3810   const guint16 *restrict sa = GET_A_LINE (y);
3811   const guint16 *restrict sy = GET_Y_LINE (y);
3812   const guint16 *restrict su = GET_U_LINE (y);
3813   const guint16 *restrict sv = GET_V_LINE (y);
3814   guint16 *restrict d = dest, A, Y, U, V;
3815
3816   sa += x;
3817   sy += x;
3818   su += x;
3819   sv += x;
3820
3821   for (i = 0; i < width; i++) {
3822     A = GST_READ_UINT16_BE (sa + i) << 6;
3823     Y = GST_READ_UINT16_BE (sy + i) << 6;
3824     U = GST_READ_UINT16_BE (su + i) << 6;
3825     V = GST_READ_UINT16_BE (sv + i) << 6;
3826
3827     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
3828       A |= (A >> 10);
3829       Y |= (Y >> 10);
3830       U |= (U >> 10);
3831       V |= (V >> 10);
3832     }
3833
3834     d[i * 4 + 0] = A;
3835     d[i * 4 + 1] = Y;
3836     d[i * 4 + 2] = U;
3837     d[i * 4 + 3] = V;
3838   }
3839 }
3840
3841 static void
3842 pack_A444_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3843     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
3844     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
3845     gint y, gint width)
3846 {
3847   int i;
3848   guint16 *restrict da = GET_A_LINE (y);
3849   guint16 *restrict dy = GET_Y_LINE (y);
3850   guint16 *restrict du = GET_U_LINE (y);
3851   guint16 *restrict dv = GET_V_LINE (y);
3852   guint16 A, Y, U, V;
3853   const guint16 *restrict s = src;
3854
3855   for (i = 0; i < width; i++) {
3856     A = s[i * 4 + 0] >> 6;
3857     Y = s[i * 4 + 1] >> 6;
3858     U = s[i * 4 + 2] >> 6;
3859     V = s[i * 4 + 3] >> 6;
3860
3861     GST_WRITE_UINT16_BE (da + i, A);
3862     GST_WRITE_UINT16_BE (dy + i, Y);
3863     GST_WRITE_UINT16_BE (du + i, U);
3864     GST_WRITE_UINT16_BE (dv + i, V);
3865   }
3866 }
3867
3868 #define PACK_A420_10LE GST_VIDEO_FORMAT_AYUV64, unpack_A420_10LE, 1, pack_A420_10LE
3869 static void
3870 unpack_A420_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3871     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
3872     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
3873 {
3874   int i;
3875   gint uv = GET_UV_420 (y, flags);
3876   const guint16 *restrict sa = GET_A_LINE (y);
3877   const guint16 *restrict sy = GET_Y_LINE (y);
3878   const guint16 *restrict su = GET_U_LINE (uv);
3879   const guint16 *restrict sv = GET_V_LINE (uv);
3880   guint16 *restrict d = dest, A, Y, U, V;
3881
3882   sa += x;
3883   sy += x;
3884   su += x >> 1;
3885   sv += x >> 1;
3886
3887   for (i = 0; i < width; i++) {
3888     A = GST_READ_UINT16_LE (sa + i) << 6;
3889     Y = GST_READ_UINT16_LE (sy + i) << 6;
3890     U = GST_READ_UINT16_LE (su + (i >> 1)) << 6;
3891     V = GST_READ_UINT16_LE (sv + (i >> 1)) << 6;
3892
3893     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
3894       A |= (A >> 10);
3895       Y |= (Y >> 10);
3896       U |= (U >> 10);
3897       V |= (V >> 10);
3898     }
3899
3900     d[i * 4 + 0] = A;
3901     d[i * 4 + 1] = Y;
3902     d[i * 4 + 2] = U;
3903     d[i * 4 + 3] = V;
3904
3905     if (x & 1) {
3906       x = 0;
3907       su++;
3908       sv++;
3909     }
3910   }
3911 }
3912
3913 static void
3914 pack_A420_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3915     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
3916     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
3917     gint y, gint width)
3918 {
3919   int i;
3920   gint uv = GET_UV_420 (y, flags);
3921   guint16 *restrict da = GET_A_LINE (y);
3922   guint16 *restrict dy = GET_Y_LINE (y);
3923   guint16 *restrict du = GET_U_LINE (uv);
3924   guint16 *restrict dv = GET_V_LINE (uv);
3925   guint16 A0, Y0, A1, Y1, U, V;
3926   const guint16 *restrict s = src;
3927
3928   if (IS_CHROMA_LINE_420 (y, flags)) {
3929     for (i = 0; i < width - 1; i += 2) {
3930       A0 = s[i * 4 + 0] >> 6;
3931       Y0 = s[i * 4 + 1] >> 6;
3932       A1 = s[i * 4 + 4] >> 6;
3933       Y1 = s[i * 4 + 5] >> 6;
3934       U = s[i * 4 + 2] >> 6;
3935       V = s[i * 4 + 3] >> 6;
3936
3937       GST_WRITE_UINT16_LE (da + i + 0, A0);
3938       GST_WRITE_UINT16_LE (dy + i + 0, Y0);
3939       GST_WRITE_UINT16_LE (da + i + 1, A1);
3940       GST_WRITE_UINT16_LE (dy + i + 1, Y1);
3941       GST_WRITE_UINT16_LE (du + (i >> 1), U);
3942       GST_WRITE_UINT16_LE (dv + (i >> 1), V);
3943     }
3944     if (i == width - 1) {
3945       A0 = s[i * 4 + 0] >> 6;
3946       Y0 = s[i * 4 + 1] >> 6;
3947       U = s[i * 4 + 2] >> 6;
3948       V = s[i * 4 + 3] >> 6;
3949
3950       GST_WRITE_UINT16_LE (da + i, A0);
3951       GST_WRITE_UINT16_LE (dy + i, Y0);
3952       GST_WRITE_UINT16_LE (du + (i >> 1), U);
3953       GST_WRITE_UINT16_LE (dv + (i >> 1), V);
3954     }
3955   } else {
3956     for (i = 0; i < width; i++) {
3957       A0 = s[i * 4 + 0] >> 6;
3958       Y0 = s[i * 4 + 1] >> 6;
3959       GST_WRITE_UINT16_LE (da + i, A0);
3960       GST_WRITE_UINT16_LE (dy + i, Y0);
3961     }
3962   }
3963 }
3964
3965 #define PACK_A420_10BE GST_VIDEO_FORMAT_AYUV64, unpack_A420_10BE, 1, pack_A420_10BE
3966 static void
3967 unpack_A420_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
3968     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
3969     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
3970 {
3971   int i;
3972   gint uv = GET_UV_420 (y, flags);
3973   const guint16 *restrict sa = GET_A_LINE (y);
3974   const guint16 *restrict sy = GET_Y_LINE (y);
3975   const guint16 *restrict su = GET_U_LINE (uv);
3976   const guint16 *restrict sv = GET_V_LINE (uv);
3977   guint16 *restrict d = dest, A, Y, U, V;
3978
3979   sa += x;
3980   sy += x;
3981   su += x >> 1;
3982   sv += x >> 1;
3983
3984   for (i = 0; i < width; i++) {
3985     A = GST_READ_UINT16_BE (sa + i) << 6;
3986     Y = GST_READ_UINT16_BE (sy + i) << 6;
3987     U = GST_READ_UINT16_BE (su + (i >> 1)) << 6;
3988     V = GST_READ_UINT16_BE (sv + (i >> 1)) << 6;
3989
3990     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
3991       A |= (A >> 10);
3992       Y |= (Y >> 10);
3993       U |= (U >> 10);
3994       V |= (V >> 10);
3995     }
3996
3997     d[i * 4 + 0] = A;
3998     d[i * 4 + 1] = Y;
3999     d[i * 4 + 2] = U;
4000     d[i * 4 + 3] = V;
4001
4002     if (x & 1) {
4003       x = 0;
4004       su++;
4005       sv++;
4006     }
4007   }
4008 }
4009
4010 static void
4011 pack_A420_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
4012     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
4013     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
4014     gint y, gint width)
4015 {
4016   int i;
4017   gint uv = GET_UV_420 (y, flags);
4018   guint16 *restrict da = GET_A_LINE (y);
4019   guint16 *restrict dy = GET_Y_LINE (y);
4020   guint16 *restrict du = GET_U_LINE (uv);
4021   guint16 *restrict dv = GET_V_LINE (uv);
4022   guint16 A0, Y0, A1, Y1, U, V;
4023   const guint16 *restrict s = src;
4024
4025   if (IS_CHROMA_LINE_420 (y, flags)) {
4026     for (i = 0; i < width - 1; i += 2) {
4027       A0 = s[i * 4 + 0] >> 6;
4028       Y0 = s[i * 4 + 1] >> 6;
4029       A1 = s[i * 4 + 4] >> 6;
4030       Y1 = s[i * 4 + 5] >> 6;
4031       U = s[i * 4 + 2] >> 6;
4032       V = s[i * 4 + 3] >> 6;
4033
4034       GST_WRITE_UINT16_BE (da + i + 0, A0);
4035       GST_WRITE_UINT16_BE (dy + i + 0, Y0);
4036       GST_WRITE_UINT16_BE (da + i + 1, A1);
4037       GST_WRITE_UINT16_BE (dy + i + 1, Y1);
4038       GST_WRITE_UINT16_BE (du + (i >> 1), U);
4039       GST_WRITE_UINT16_BE (dv + (i >> 1), V);
4040     }
4041     if (i == width - 1) {
4042       A0 = s[i * 4 + 0] >> 6;
4043       Y0 = s[i * 4 + 1] >> 6;
4044       U = s[i * 4 + 2] >> 6;
4045       V = s[i * 4 + 3] >> 6;
4046
4047       GST_WRITE_UINT16_BE (da + i, A0);
4048       GST_WRITE_UINT16_BE (dy + i, Y0);
4049       GST_WRITE_UINT16_BE (du + (i >> 1), U);
4050       GST_WRITE_UINT16_BE (dv + (i >> 1), V);
4051     }
4052   } else {
4053     for (i = 0; i < width; i++) {
4054       A0 = s[i * 4 + 0] >> 6;
4055       Y0 = s[i * 4 + 1] >> 6;
4056       GST_WRITE_UINT16_BE (da + i, A0);
4057       GST_WRITE_UINT16_BE (dy + i, Y0);
4058     }
4059   }
4060 }
4061
4062 #define PACK_A422_10LE GST_VIDEO_FORMAT_AYUV64, unpack_A422_10LE, 1, pack_A422_10LE
4063 static void
4064 unpack_A422_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
4065     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
4066     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
4067 {
4068   int i;
4069   const guint16 *restrict sa = GET_A_LINE (y);
4070   const guint16 *restrict sy = GET_Y_LINE (y);
4071   const guint16 *restrict su = GET_U_LINE (y);
4072   const guint16 *restrict sv = GET_V_LINE (y);
4073   guint16 *restrict d = dest, A, Y, U, V;
4074
4075   sa += x;
4076   sy += x;
4077   su += x >> 1;
4078   sv += x >> 1;
4079
4080   for (i = 0; i < width; i++) {
4081     A = GST_READ_UINT16_LE (sa + i) << 6;
4082     Y = GST_READ_UINT16_LE (sy + i) << 6;
4083     U = GST_READ_UINT16_LE (su + (i >> 1)) << 6;
4084     V = GST_READ_UINT16_LE (sv + (i >> 1)) << 6;
4085
4086     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
4087       A |= (A >> 10);
4088       Y |= (Y >> 10);
4089       U |= (U >> 10);
4090       V |= (V >> 10);
4091     }
4092
4093     d[i * 4 + 0] = A;
4094     d[i * 4 + 1] = Y;
4095     d[i * 4 + 2] = U;
4096     d[i * 4 + 3] = V;
4097
4098     if (x & 1) {
4099       x = 0;
4100       su++;
4101       sv++;
4102     }
4103   }
4104 }
4105
4106 static void
4107 pack_A422_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
4108     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
4109     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
4110     gint y, gint width)
4111 {
4112   int i;
4113   guint16 *restrict da = GET_A_LINE (y);
4114   guint16 *restrict dy = GET_Y_LINE (y);
4115   guint16 *restrict du = GET_U_LINE (y);
4116   guint16 *restrict dv = GET_V_LINE (y);
4117   guint16 A0, Y0, A1, Y1, U, V;
4118   const guint16 *restrict s = src;
4119
4120   for (i = 0; i < width - 1; i += 2) {
4121     A0 = s[i * 4 + 0] >> 6;
4122     Y0 = s[i * 4 + 1] >> 6;
4123     A1 = s[i * 4 + 4] >> 6;
4124     Y1 = s[i * 4 + 5] >> 6;
4125     U = s[i * 4 + 2] >> 6;
4126     V = s[i * 4 + 3] >> 6;
4127
4128     GST_WRITE_UINT16_LE (da + i + 0, A0);
4129     GST_WRITE_UINT16_LE (dy + i + 0, Y0);
4130     GST_WRITE_UINT16_LE (da + i + 1, A1);
4131     GST_WRITE_UINT16_LE (dy + i + 1, Y1);
4132     GST_WRITE_UINT16_LE (du + (i >> 1), U);
4133     GST_WRITE_UINT16_LE (dv + (i >> 1), V);
4134   }
4135   if (i == width - 1) {
4136     A0 = s[i * 4 + 0] >> 6;
4137     Y0 = s[i * 4 + 1] >> 6;
4138     U = s[i * 4 + 2] >> 6;
4139     V = s[i * 4 + 3] >> 6;
4140
4141     GST_WRITE_UINT16_LE (da + i, A0);
4142     GST_WRITE_UINT16_LE (dy + i, Y0);
4143     GST_WRITE_UINT16_LE (du + (i >> 1), U);
4144     GST_WRITE_UINT16_LE (dv + (i >> 1), V);
4145   }
4146 }
4147
4148 #define PACK_A422_10BE GST_VIDEO_FORMAT_AYUV64, unpack_A422_10BE, 1, pack_A422_10BE
4149 static void
4150 unpack_A422_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
4151     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
4152     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
4153 {
4154   int i;
4155   const guint16 *restrict sa = GET_A_LINE (y);
4156   const guint16 *restrict sy = GET_Y_LINE (y);
4157   const guint16 *restrict su = GET_U_LINE (y);
4158   const guint16 *restrict sv = GET_V_LINE (y);
4159   guint16 *restrict d = dest, A, Y, U, V;
4160
4161   sa += x;
4162   sy += x;
4163   su += x >> 1;
4164   sv += x >> 1;
4165
4166   for (i = 0; i < width; i++) {
4167     A = GST_READ_UINT16_BE (sa + i) << 6;
4168     Y = GST_READ_UINT16_BE (sy + i) << 6;
4169     U = GST_READ_UINT16_BE (su + (i >> 1)) << 6;
4170     V = GST_READ_UINT16_BE (sv + (i >> 1)) << 6;
4171
4172     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
4173       A |= (A >> 10);
4174       Y |= (Y >> 10);
4175       U |= (U >> 10);
4176       V |= (V >> 10);
4177     }
4178
4179     d[i * 4 + 0] = A;
4180     d[i * 4 + 1] = Y;
4181     d[i * 4 + 2] = U;
4182     d[i * 4 + 3] = V;
4183
4184     if (x & 1) {
4185       x = 0;
4186       su++;
4187       sv++;
4188     }
4189   }
4190 }
4191
4192 static void
4193 pack_A422_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
4194     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
4195     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
4196     gint y, gint width)
4197 {
4198   int i;
4199   guint16 *restrict da = GET_A_LINE (y);
4200   guint16 *restrict dy = GET_Y_LINE (y);
4201   guint16 *restrict du = GET_U_LINE (y);
4202   guint16 *restrict dv = GET_V_LINE (y);
4203   guint16 A0, Y0, A1, Y1, U, V;
4204   const guint16 *restrict s = src;
4205
4206   for (i = 0; i < width - 1; i += 2) {
4207     A0 = s[i * 4 + 0] >> 6;
4208     Y0 = s[i * 4 + 1] >> 6;
4209     A1 = s[i * 4 + 4] >> 6;
4210     Y1 = s[i * 4 + 5] >> 6;
4211     U = s[i * 4 + 2] >> 6;
4212     V = s[i * 4 + 3] >> 6;
4213
4214     GST_WRITE_UINT16_BE (da + i + 0, A0);
4215     GST_WRITE_UINT16_BE (dy + i + 0, Y0);
4216     GST_WRITE_UINT16_BE (da + i + 1, A1);
4217     GST_WRITE_UINT16_BE (dy + i + 1, Y1);
4218     GST_WRITE_UINT16_BE (du + (i >> 1), U);
4219     GST_WRITE_UINT16_BE (dv + (i >> 1), V);
4220   }
4221   if (i == width - 1) {
4222     A0 = s[i * 4 + 0] >> 6;
4223     Y0 = s[i * 4 + 1] >> 6;
4224     U = s[i * 4 + 2] >> 6;
4225     V = s[i * 4 + 3] >> 6;
4226
4227     GST_WRITE_UINT16_BE (da + i, A0);
4228     GST_WRITE_UINT16_BE (dy + i, Y0);
4229     GST_WRITE_UINT16_BE (du + (i >> 1), U);
4230     GST_WRITE_UINT16_BE (dv + (i >> 1), V);
4231   }
4232 }
4233
4234 static void
4235 get_tile_NV12 (gint tile_width, gint ts, gint tx, gint ty,
4236     const gpointer data[GST_VIDEO_MAX_PLANES],
4237     const gint stride[GST_VIDEO_MAX_PLANES],
4238     gpointer tile_data[GST_VIDEO_MAX_PLANES],
4239     gint tile_stride[GST_VIDEO_MAX_PLANES])
4240 {
4241   gsize offset;
4242
4243   /* index of Y tile */
4244   offset = gst_video_tile_get_index (GST_VIDEO_TILE_MODE_ZFLIPZ_2X2,
4245       tx, ty, GST_VIDEO_TILE_X_TILES (stride[0]),
4246       GST_VIDEO_TILE_Y_TILES (stride[0]));
4247   offset <<= ts;
4248   tile_data[0] = ((guint8 *) data[0]) + offset;
4249
4250   /* index of UV tile */
4251   offset = gst_video_tile_get_index (GST_VIDEO_TILE_MODE_ZFLIPZ_2X2,
4252       tx, ty >> 1, GST_VIDEO_TILE_X_TILES (stride[1]),
4253       GST_VIDEO_TILE_Y_TILES (stride[1]));
4254   offset <<= ts;
4255   /* On odd rows we return the second part of the UV tile */
4256   offset |= (ty & 1) << (ts - 1);
4257   tile_data[1] = ((guint8 *) data[1]) + offset;
4258
4259   tile_stride[0] = tile_stride[1] = tile_width;
4260 }
4261
4262 #define PACK_NV12_64Z32 GST_VIDEO_FORMAT_AYUV, unpack_NV12_64Z32, 1, pack_NV12_64Z32
4263 static void
4264 unpack_NV12_64Z32 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
4265     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
4266     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
4267 {
4268   const GstVideoFormatInfo *unpack_info, *finfo;
4269   guint8 *line = dest;
4270   gint ws, hs, ts, tile_width;
4271   gint ntx, tx, ty;
4272   gint unpack_pstride;
4273
4274   ws = GST_VIDEO_FORMAT_INFO_TILE_WS (info);
4275   hs = GST_VIDEO_FORMAT_INFO_TILE_HS (info);
4276   ts = ws + hs;
4277
4278   tile_width = 1 << ws;
4279
4280   /* we reuse these unpack functions */
4281   finfo = gst_video_format_get_info (GST_VIDEO_FORMAT_NV12);
4282
4283   /* get pstride of unpacked format */
4284   unpack_info = gst_video_format_get_info (info->unpack_format);
4285   unpack_pstride = GST_VIDEO_FORMAT_INFO_PSTRIDE (unpack_info, 0);
4286
4287   /* first x tile to convert */
4288   tx = x >> ws;
4289   /* Last tile to convert */
4290   ntx = ((x + width - 1) >> ws) + 1;
4291   /* The row we are going to convert */
4292   ty = y >> hs;
4293
4294   /* y position in a tile */
4295   y = y & ((1 << hs) - 1);
4296   /* x position in a tile */
4297   x = x & (tile_width - 1);
4298
4299   for (; tx < ntx; tx++) {
4300     gpointer tdata[GST_VIDEO_MAX_PLANES];
4301     gint tstride[GST_VIDEO_MAX_PLANES];
4302     gint unpack_width;
4303
4304     get_tile_NV12 (tile_width, ts, tx, ty, data, stride, tdata, tstride);
4305
4306     /* the number of bytes left to unpack */
4307     unpack_width = MIN (width - x, tile_width - x);
4308
4309     finfo->unpack_func (finfo, flags, line, tdata, tstride, x, y, unpack_width);
4310
4311     x = 0;
4312     width -= unpack_width;
4313     line += unpack_width * unpack_pstride;
4314   }
4315 }
4316
4317 static void
4318 pack_NV12_64Z32 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
4319     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
4320     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
4321     gint y, gint width)
4322 {
4323   const GstVideoFormatInfo *pack_info, *finfo;
4324   guint8 *line = src;
4325   gint ws, hs, ts, tile_width;
4326   gint ntx, tx, ty;
4327   gint pack_pstride;
4328
4329   ws = GST_VIDEO_FORMAT_INFO_TILE_WS (info);
4330   hs = GST_VIDEO_FORMAT_INFO_TILE_HS (info);
4331   ts = ws + hs;
4332
4333   tile_width = 1 << ws;
4334
4335   /* we reuse these pack functions */
4336   finfo = gst_video_format_get_info (GST_VIDEO_FORMAT_NV12);
4337
4338   /* get pstride of packed format */
4339   pack_info = gst_video_format_get_info (info->unpack_format);
4340   pack_pstride = GST_VIDEO_FORMAT_INFO_PSTRIDE (pack_info, 0);
4341
4342   /* Last tile to convert */
4343   ntx = ((width - 1) >> ws) + 1;
4344   /* The row we are going to convert */
4345   ty = y >> hs;
4346
4347   /* y position in a tile */
4348   y = y & ((1 << hs) - 1);
4349
4350   for (tx = 0; tx < ntx; tx++) {
4351     gpointer tdata[GST_VIDEO_MAX_PLANES];
4352     gint tstride[GST_VIDEO_MAX_PLANES];
4353     gint pack_width;
4354
4355     get_tile_NV12 (tile_width, ts, tx, ty, data, stride, tdata, tstride);
4356
4357     /* the number of bytes left to pack */
4358     pack_width = MIN (width, tile_width);
4359
4360     finfo->pack_func (finfo, flags, line, sstride, tdata, tstride,
4361         chroma_site, y, pack_width);
4362
4363     width -= pack_width;
4364     line += pack_width * pack_pstride;
4365   }
4366 }
4367
4368 #define PACK_P010_10BE GST_VIDEO_FORMAT_AYUV64, unpack_P010_10BE, 1, pack_P010_10BE
4369 static void
4370 unpack_P010_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
4371     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
4372     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
4373 {
4374   int i;
4375   gint uv = GET_UV_420 (y, flags);
4376   const guint16 *restrict sy = GET_PLANE_LINE (0, y);
4377   const guint16 *restrict suv = GET_PLANE_LINE (1, uv);
4378   guint16 *restrict d = dest, Y0, Y1, U, V;
4379
4380   sy += x;
4381   suv += (x & ~1);
4382
4383   if (x & 1) {
4384     Y0 = GST_READ_UINT16_BE (sy);
4385     U = GST_READ_UINT16_BE (suv);
4386     V = GST_READ_UINT16_BE (suv + 1);
4387
4388     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
4389       Y0 |= (Y0 >> 10);
4390       U |= (U >> 10);
4391       V |= (V >> 10);
4392     }
4393
4394     d[0] = 0xffff;
4395     d[1] = Y0;
4396     d[2] = U;
4397     d[3] = V;
4398     width--;
4399     d += 4;
4400     sy += 1;
4401     suv += 2;
4402   }
4403
4404   for (i = 0; i < width / 2; i++) {
4405     Y0 = GST_READ_UINT16_BE (sy + 2 * i);
4406     Y1 = GST_READ_UINT16_BE (sy + 2 * i + 1);
4407     U = GST_READ_UINT16_BE (suv + 2 * i);
4408     V = GST_READ_UINT16_BE (suv + 2 * i + 1);
4409
4410     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
4411       Y0 |= (Y0 >> 10);
4412       Y1 |= (Y1 >> 10);
4413       U |= (U >> 10);
4414       V |= (V >> 10);
4415     }
4416
4417     d[i * 8 + 0] = 0xffff;
4418     d[i * 8 + 1] = Y0;
4419     d[i * 8 + 2] = U;
4420     d[i * 8 + 3] = V;
4421     d[i * 8 + 4] = 0xffff;
4422     d[i * 8 + 5] = Y1;
4423     d[i * 8 + 6] = U;
4424     d[i * 8 + 7] = V;
4425   }
4426
4427   if (width & 1) {
4428     gint i = width - 1;
4429
4430     Y0 = GST_READ_UINT16_BE (sy + i);
4431     U = GST_READ_UINT16_BE (suv + i);
4432     V = GST_READ_UINT16_BE (suv + i + 1);
4433
4434     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
4435       Y0 |= (Y0 >> 10);
4436       U |= (U >> 10);
4437       V |= (V >> 10);
4438     }
4439
4440     d[i * 4 + 0] = 0xffff;
4441     d[i * 4 + 1] = Y0;
4442     d[i * 4 + 2] = U;
4443     d[i * 4 + 3] = V;
4444   }
4445 }
4446
4447 static void
4448 pack_P010_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
4449     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
4450     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
4451     gint y, gint width)
4452 {
4453   int i;
4454   gint uv = GET_UV_420 (y, flags);
4455   guint16 *restrict dy = GET_PLANE_LINE (0, y);
4456   guint16 *restrict duv = GET_PLANE_LINE (1, uv);
4457   guint16 Y0, Y1, U, V;
4458   const guint16 *restrict s = src;
4459
4460   if (IS_CHROMA_LINE_420 (y, flags)) {
4461     for (i = 0; i < width / 2; i++) {
4462       Y0 = s[i * 8 + 1] & 0xffc0;
4463       Y1 = s[i * 8 + 5] & 0xffc0;
4464       U = s[i * 8 + 2] & 0xffc0;
4465       V = s[i * 8 + 3] & 0xffc0;
4466
4467       GST_WRITE_UINT16_BE (dy + i * 2 + 0, Y0);
4468       GST_WRITE_UINT16_BE (dy + i * 2 + 1, Y1);
4469       GST_WRITE_UINT16_BE (duv + i * 2 + 0, U);
4470       GST_WRITE_UINT16_BE (duv + i * 2 + 1, V);
4471     }
4472     if (width & 1) {
4473       gint i = width - 1;
4474
4475       Y0 = s[i * 4 + 1] & 0xffc0;
4476       U = s[i * 4 + 2] & 0xffc0;
4477       V = s[i * 4 + 3] & 0xffc0;
4478
4479       GST_WRITE_UINT16_BE (dy + i, Y0);
4480       GST_WRITE_UINT16_BE (duv + i + 0, U);
4481       GST_WRITE_UINT16_BE (duv + i + 1, V);
4482     }
4483   } else {
4484     for (i = 0; i < width; i++) {
4485       Y0 = s[i * 4 + 1] & 0xffc0;
4486       GST_WRITE_UINT16_BE (dy + i, Y0);
4487     }
4488   }
4489 }
4490
4491 #define PACK_P010_10LE GST_VIDEO_FORMAT_AYUV64, unpack_P010_10LE, 1, pack_P010_10LE
4492 static void
4493 unpack_P010_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
4494     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
4495     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
4496 {
4497   int i;
4498   gint uv = GET_UV_420 (y, flags);
4499   const guint16 *restrict sy = GET_PLANE_LINE (0, y);
4500   const guint16 *restrict suv = GET_PLANE_LINE (1, uv);
4501   guint16 *restrict d = dest, Y0, Y1, U, V;
4502
4503   sy += x;
4504   suv += (x & ~1);
4505
4506   if (x & 1) {
4507     Y0 = GST_READ_UINT16_LE (sy);
4508     U = GST_READ_UINT16_LE (suv);
4509     V = GST_READ_UINT16_LE (suv + 1);
4510
4511     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
4512       Y0 |= (Y0 >> 10);
4513       U |= (U >> 10);
4514       V |= (V >> 10);
4515     }
4516
4517     d[0] = 0xffff;
4518     d[1] = Y0;
4519     d[2] = U;
4520     d[3] = V;
4521     width--;
4522     d += 4;
4523     sy += 1;
4524     suv += 2;
4525   }
4526
4527   for (i = 0; i < width / 2; i++) {
4528     Y0 = GST_READ_UINT16_LE (sy + 2 * i);
4529     Y1 = GST_READ_UINT16_LE (sy + 2 * i + 1);
4530     U = GST_READ_UINT16_LE (suv + 2 * i);
4531     V = GST_READ_UINT16_LE (suv + 2 * i + 1);
4532
4533     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
4534       Y0 |= (Y0 >> 10);
4535       Y1 |= (Y1 >> 10);
4536       U |= (U >> 10);
4537       V |= (V >> 10);
4538     }
4539
4540     d[i * 8 + 0] = 0xffff;
4541     d[i * 8 + 1] = Y0;
4542     d[i * 8 + 2] = U;
4543     d[i * 8 + 3] = V;
4544     d[i * 8 + 4] = 0xffff;
4545     d[i * 8 + 5] = Y1;
4546     d[i * 8 + 6] = U;
4547     d[i * 8 + 7] = V;
4548   }
4549
4550   if (width & 1) {
4551     gint i = width - 1;
4552
4553     Y0 = GST_READ_UINT16_LE (sy + i);
4554     U = GST_READ_UINT16_LE (suv + i);
4555     V = GST_READ_UINT16_LE (suv + i + 1);
4556
4557     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
4558       Y0 |= (Y0 >> 10);
4559       U |= (U >> 10);
4560       V |= (V >> 10);
4561     }
4562
4563     d[i * 4 + 0] = 0xffff;
4564     d[i * 4 + 1] = Y0;
4565     d[i * 4 + 2] = U;
4566     d[i * 4 + 3] = V;
4567   }
4568 }
4569
4570 static void
4571 pack_P010_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
4572     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
4573     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
4574     gint y, gint width)
4575 {
4576   int i;
4577   gint uv = GET_UV_420 (y, flags);
4578   guint16 *restrict dy = GET_PLANE_LINE (0, y);
4579   guint16 *restrict duv = GET_PLANE_LINE (1, uv);
4580   guint16 Y0, Y1, U, V;
4581   const guint16 *restrict s = src;
4582
4583   if (IS_CHROMA_LINE_420 (y, flags)) {
4584     for (i = 0; i < width / 2; i++) {
4585       Y0 = s[i * 8 + 1] & 0xffc0;
4586       Y1 = s[i * 8 + 5] & 0xffc0;
4587       U = s[i * 8 + 2] & 0xffc0;
4588       V = s[i * 8 + 3] & 0xffc0;
4589
4590       GST_WRITE_UINT16_LE (dy + i * 2 + 0, Y0);
4591       GST_WRITE_UINT16_LE (dy + i * 2 + 1, Y1);
4592       GST_WRITE_UINT16_LE (duv + i * 2 + 0, U);
4593       GST_WRITE_UINT16_LE (duv + i * 2 + 1, V);
4594     }
4595     if (width & 1) {
4596       gint i = width - 1;
4597
4598       Y0 = s[i * 4 + 1] & 0xffc0;
4599       U = s[i * 4 + 2] & 0xffc0;
4600       V = s[i * 4 + 3] & 0xffc0;
4601
4602       GST_WRITE_UINT16_LE (dy + i, Y0);
4603       GST_WRITE_UINT16_LE (duv + i + 0, U);
4604       GST_WRITE_UINT16_LE (duv + i + 1, V);
4605     }
4606   } else {
4607     for (i = 0; i < width; i++) {
4608       Y0 = s[i * 4 + 1] & 0xffc0;
4609       GST_WRITE_UINT16_LE (dy + i, Y0);
4610     }
4611   }
4612 }
4613
4614 #define PACK_GRAY10_LE32 GST_VIDEO_FORMAT_AYUV64, unpack_GRAY10_LE32, 1, pack_GRAY10_LE32
4615 static void
4616 unpack_GRAY10_LE32 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
4617     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
4618     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
4619 {
4620   gint i;
4621   const guint32 *restrict sy = GET_PLANE_LINE (0, y);
4622   guint16 *restrict d = dest;
4623   gint num_words = (width + 2) / 3;
4624
4625   /* Y data is packed into little endian 32bit words, with the 2 MSB being
4626    * padding. There is only 1 pattern.
4627    * -> padding | Y1 | Y2 | Y3
4628    */
4629
4630   for (i = 0; i < num_words; i++) {
4631     gint num_comps = MIN (3, width - i * 3);
4632     guint pix = i * 3;
4633     gsize doff = pix * 4;
4634     gint c;
4635     guint32 Y;
4636
4637     Y = GST_READ_UINT32_LE (sy + i);
4638
4639     for (c = 0; c < num_comps; c++) {
4640       guint16 Yn;
4641
4642       /* For Y, we simply read 10 bit and shift it out */
4643       Yn = (Y & 0x03ff) << 6;
4644       Y >>= 10;
4645
4646       if (G_UNLIKELY (pix + c < x))
4647         continue;
4648
4649       if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE))
4650         Yn |= Yn >> 10;
4651
4652       d[doff + 0] = 0xffff;
4653       d[doff + 1] = Yn;
4654       d[doff + 2] = 0x8000;
4655       d[doff + 3] = 0x8000;
4656
4657       doff += 4;
4658     }
4659   }
4660 }
4661
4662 static void
4663 pack_GRAY10_LE32 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
4664     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
4665     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
4666     gint y, gint width)
4667 {
4668   gint i;
4669   guint32 *restrict dy = GET_PLANE_LINE (0, y);
4670   const guint16 *restrict s = src;
4671   gint num_words = (width + 2) / 3;
4672
4673   for (i = 0; i < num_words; i++) {
4674     gint num_comps = MIN (3, width - i * 3);
4675     guint pix = i * 3;
4676     gsize soff = pix * 4;
4677     gint c;
4678     guint32 Y = 0;
4679
4680     for (c = 0; c < num_comps; c++) {
4681       Y |= s[soff + 1] >> 6 << (10 * c);
4682       soff += 4;
4683     }
4684
4685     GST_WRITE_UINT32_LE (dy + i, Y);
4686   }
4687 }
4688
4689 #define PACK_NV12_10LE32 GST_VIDEO_FORMAT_AYUV64, unpack_NV12_10LE32, 1, pack_NV12_10LE32
4690 static void
4691 unpack_NV12_10LE32 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
4692     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
4693     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
4694 {
4695   gint i;
4696   gint uv = GET_UV_420 (y, flags);
4697   const guint32 *restrict sy = GET_PLANE_LINE (0, y);
4698   const guint32 *restrict suv = GET_PLANE_LINE (1, uv);
4699   guint16 *restrict d = dest;
4700   gint num_words = (width + 2) / 3;
4701   guint32 UV = 0;
4702   guint16 Un = 0, Vn = 0;
4703
4704   /* Y data is packed into little endian 32bit words, with the 2 MSB being
4705    * padding. There is only 1 pattern.
4706    * -> padding | Y1 | Y2 | Y3
4707    *
4708    * UV is packed the same way, though we end up with 2 patterns:
4709    * -> U | V | U | padding
4710    * -> V | U | V | padding
4711    */
4712
4713   /* FIXME unroll the 6 states ? */
4714
4715   for (i = 0; i < num_words; i++) {
4716     gint num_comps = MIN (3, width - i * 3);
4717     guint pix = i * 3;
4718     gsize doff = pix * 4;
4719     gint c;
4720     guint32 Y;
4721
4722     Y = GST_READ_UINT32_LE (sy + i);
4723
4724     for (c = 0; c < num_comps; c++) {
4725       guint16 Yn;
4726
4727       /* For Y, we simply read 10 bit and shift it out */
4728       Yn = (Y & 0x03ff) << 6;
4729       Y >>= 10;
4730
4731       /* Unpacking UV has been reduced to a cycle of 6 states. The following
4732        * code is a reduce version of:
4733        * 0: - Read first UV word (UVU)
4734        *      Unpack U and V
4735        * 1: - Resued U/V from 1 (sub-sampling)
4736        * 2: - Unpack remaining U value
4737        *    - Read following UV word (VUV)
4738        *    - Unpack V value
4739        * 3: - Reuse U/V from 2 (sub-sampling)
4740        * 4: - Unpack remaining U
4741        *    - Unpack remaining V
4742        * 5: - Reuse UV/V from 4 (sub-sampling)
4743        */
4744       switch ((pix + c) % 6) {
4745         case 0:
4746           UV = GST_READ_UINT32_LE (suv + i);
4747           /* fallthrough */
4748         case 4:
4749           Un = (UV & 0x03ff) << 6;
4750           UV >>= 10;
4751           Vn = (UV & 0x03ff) << 6;
4752           UV >>= 10;
4753           break;
4754         case 2:
4755           Un = (UV & 0x03ff) << 6;
4756           UV = GST_READ_UINT32_LE (suv + i + 1);
4757           Vn = (UV & 0x03ff) << 6;
4758           UV >>= 10;
4759           break;
4760         default:
4761           /* keep value */
4762           break;
4763       }
4764
4765       if (G_UNLIKELY (pix + c < x))
4766         continue;
4767
4768       if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
4769         Yn |= Yn >> 10;
4770         Un |= Un >> 10;
4771         Vn |= Vn >> 10;
4772       }
4773
4774       d[doff + 0] = 0xffff;
4775       d[doff + 1] = Yn;
4776       d[doff + 2] = Un;
4777       d[doff + 3] = Vn;
4778
4779       doff += 4;
4780     }
4781   }
4782 }
4783
4784 static void
4785 pack_NV12_10LE32 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
4786     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
4787     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
4788     gint y, gint width)
4789 {
4790   gint i;
4791   gint uv = GET_UV_420 (y, flags);
4792   guint32 *restrict dy = GET_PLANE_LINE (0, y);
4793   guint32 *restrict duv = GET_PLANE_LINE (1, uv);
4794   const guint16 *restrict s = src;
4795   gint num_words = (width + 2) / 3;
4796   guint32 UV = 0;
4797
4798   /* FIXME unroll the 6 states ? */
4799
4800   for (i = 0; i < num_words; i++) {
4801     gint num_comps = MIN (3, width - i * 3);
4802     guint pix = i * 3;
4803     gsize soff = pix * 4;
4804     gint c;
4805     guint32 Y = 0;
4806
4807     for (c = 0; c < num_comps; c++) {
4808       Y |= s[soff + 1] >> 6 << (10 * c);
4809
4810       if (IS_CHROMA_LINE_420 (y, flags)) {
4811         switch ((pix + c) % 6) {
4812           case 0:
4813             UV = s[soff + 2] >> 6;
4814             UV |= s[soff + 3] >> 6 << 10;
4815             break;
4816           case 2:
4817             UV |= s[soff + 2] >> 6 << 20;
4818             GST_WRITE_UINT32_LE (duv + i, UV);
4819             UV = s[soff + 3] >> 6;
4820             break;
4821           case 4:
4822             UV |= s[soff + 2] >> 6 << 10;
4823             UV |= s[soff + 3] >> 6 << 20;
4824             GST_WRITE_UINT32_LE (duv + i, UV);
4825             break;
4826           default:
4827             /* keep value */
4828             break;
4829         }
4830       }
4831
4832       soff += 4;
4833     }
4834
4835     GST_WRITE_UINT32_LE (dy + i, Y);
4836
4837     if (IS_CHROMA_LINE_420 (y, flags) && num_comps < 3)
4838       GST_WRITE_UINT32_LE (duv + i, UV);
4839
4840   }
4841 }
4842
4843 #define PACK_NV16_10LE32 GST_VIDEO_FORMAT_AYUV64, unpack_NV16_10LE32, 1, pack_NV16_10LE32
4844 static void
4845 unpack_NV16_10LE32 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
4846     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
4847     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
4848 {
4849   gint i;
4850   const guint32 *restrict sy = GET_PLANE_LINE (0, y);
4851   const guint32 *restrict suv = GET_PLANE_LINE (1, y);
4852   guint16 *restrict d = dest;
4853   gint num_words = (width + 2) / 3;
4854   guint32 UV = 0;
4855   guint16 Un = 0, Vn = 0;
4856
4857   /* Y data is packed into little endian 32bit words, with the 2 MSB being
4858    * padding. There is only 1 pattern.
4859    * -> padding | Y1 | Y2 | Y3
4860    *
4861    * UV is packed the same way, though we end up with 2 patterns:
4862    * -> U | V | U | padding
4863    * -> V | U | V | padding
4864    */
4865
4866   /* FIXME unroll the 6 states ? */
4867
4868   for (i = 0; i < num_words; i++) {
4869     gint num_comps = MIN (3, width - i * 3);
4870     guint pix = i * 3;
4871     gsize doff = pix * 4;
4872     gint c;
4873     guint32 Y;
4874
4875     Y = GST_READ_UINT32_LE (sy + i);
4876
4877     for (c = 0; c < num_comps; c++) {
4878       guint16 Yn;
4879
4880       /* For Y, we simply read 10 bit and shift it out */
4881       Yn = (Y & 0x03ff) << 6;
4882       Y >>= 10;
4883
4884       /* Unpacking UV has been reduced to a cycle of 6 states. The following
4885        * code is a reduce version of:
4886        * 0: - Read first UV word (UVU)
4887        *      Unpack U and V
4888        * 1: - Resued U/V from 1 (sub-sampling)
4889        * 2: - Unpack remaining U value
4890        *    - Read following UV word (VUV)
4891        *    - Unpack V value
4892        * 3: - Reuse U/V from 2 (sub-sampling)
4893        * 4: - Unpack remaining U
4894        *    - Unpack remaining V
4895        * 5: - Reuse UV/V from 4 (sub-sampling)
4896        */
4897       switch ((pix + c) % 6) {
4898         case 0:
4899           UV = GST_READ_UINT32_LE (suv + i);
4900           /* fallthrough */
4901         case 4:
4902           Un = (UV & 0x03ff) << 6;
4903           UV >>= 10;
4904           Vn = (UV & 0x03ff) << 6;
4905           UV >>= 10;
4906           break;
4907         case 2:
4908           Un = (UV & 0x03ff) << 6;
4909           UV = GST_READ_UINT32_LE (suv + i + 1);
4910           Vn = (UV & 0x03ff) << 6;
4911           UV >>= 10;
4912           break;
4913         default:
4914           /* keep value */
4915           break;
4916       }
4917
4918       if (G_UNLIKELY (pix + c < x))
4919         continue;
4920
4921       if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
4922         Yn |= Yn >> 10;
4923         Un |= Un >> 10;
4924         Vn |= Vn >> 10;
4925       }
4926
4927       d[doff + 0] = 0xffff;
4928       d[doff + 1] = Yn;
4929       d[doff + 2] = Un;
4930       d[doff + 3] = Vn;
4931
4932       doff += 4;
4933     }
4934   }
4935 }
4936
4937 static void
4938 pack_NV16_10LE32 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
4939     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
4940     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
4941     gint y, gint width)
4942 {
4943   gint i;
4944   guint32 *restrict dy = GET_PLANE_LINE (0, y);
4945   guint32 *restrict duv = GET_PLANE_LINE (1, y);
4946   const guint16 *restrict s = src;
4947   gint num_words = (width + 2) / 3;
4948   guint32 UV = 0;
4949
4950   /* FIXME unroll the 6 states ? */
4951
4952   for (i = 0; i < num_words; i++) {
4953     gint num_comps = MIN (3, width - i * 3);
4954     guint pix = i * 3;
4955     gsize soff = pix * 4;
4956     gint c;
4957     guint32 Y = 0;
4958
4959     for (c = 0; c < num_comps; c++) {
4960       Y |= s[soff + 1] >> 6 << (10 * c);
4961
4962       switch ((pix + c) % 6) {
4963         case 0:
4964           UV = s[soff + 2] >> 6;
4965           UV |= s[soff + 3] >> 6 << 10;
4966           break;
4967         case 2:
4968           UV |= s[soff + 2] >> 6 << 20;
4969           GST_WRITE_UINT32_LE (duv + i, UV);
4970           UV = s[soff + 3] >> 6;
4971           break;
4972         case 4:
4973           UV |= s[soff + 2] >> 6 << 10;
4974           UV |= s[soff + 3] >> 6 << 20;
4975           GST_WRITE_UINT32_LE (duv + i, UV);
4976           break;
4977         default:
4978           /* keep value */
4979           break;
4980       }
4981
4982       soff += 4;
4983     }
4984
4985     GST_WRITE_UINT32_LE (dy + i, Y);
4986
4987     if (num_comps < 3)
4988       GST_WRITE_UINT32_LE (duv + i, UV);
4989   }
4990 }
4991
4992 #define PACK_NV12_10LE40 GST_VIDEO_FORMAT_AYUV64, unpack_NV12_10LE40, 1, pack_NV12_10LE40
4993 static void
4994 unpack_NV12_10LE40 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
4995     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
4996     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
4997 {
4998   gint i;
4999   gint uv = GET_UV_420 (y, flags);
5000   guint16 *restrict d = dest;
5001   const guint8 *restrict sy = GET_PLANE_LINE (0, y);
5002   const guint8 *restrict suv = GET_PLANE_LINE (1, uv);
5003   guint16 Y0 = 0, Y1 = 0, Yn = 0, Un = 0, Vn = 0;
5004   guint32 UV = 0;
5005
5006   for (i = 0; i < width; i++) {
5007     gboolean update_c = FALSE;
5008
5009     switch (i & 3) {
5010       case 0:
5011         Y0 = GST_READ_UINT16_LE (sy);
5012         Yn = Y0 & 0x3ff;
5013         sy += 2;
5014
5015         UV = GST_READ_UINT32_LE (suv);
5016         Un = UV & 0x3ff;
5017         Vn = (UV >> 10) & 0x3ff;
5018         suv += 4;
5019
5020         Yn <<= 6;
5021         Un <<= 6;
5022         Vn <<= 6;
5023         update_c = TRUE;
5024         break;
5025       case 1:
5026         Y1 = GST_READ_UINT16_LE (sy);
5027         Yn = (Y0 >> 10) | ((Y1 & 0xf) << 6);
5028         sy += 2;
5029
5030         Yn <<= 6;
5031         break;
5032       case 2:
5033         Yn = (Y1 >> 4) & 0x3ff;
5034
5035         Un = (UV >> 20) & 0x3ff;
5036         Vn = (UV >> 30);
5037         UV = GST_READ_UINT8 (suv);
5038         Vn |= (UV << 2);
5039         suv++;
5040
5041         Yn <<= 6;
5042         Un <<= 6;
5043         Vn <<= 6;
5044         update_c = TRUE;
5045         break;
5046       case 3:
5047         Y0 = GST_READ_UINT8 (sy);
5048         Yn = (Y1 >> 14) | (Y0 << 2);
5049         sy++;
5050
5051         Yn <<= 6;
5052         break;
5053     }
5054
5055     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
5056       Yn |= Yn >> 10;
5057       if (update_c) {
5058         Un |= Un >> 10;
5059         Vn |= Vn >> 10;
5060       }
5061     }
5062
5063     d[i * 4 + 0] = 0xffff;
5064     d[i * 4 + 1] = Yn;
5065     d[i * 4 + 2] = Un;
5066     d[i * 4 + 3] = Vn;
5067   }
5068 }
5069
5070 static void
5071 pack_NV12_10LE40 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
5072     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
5073     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
5074     gint y, gint width)
5075 {
5076   gint i;
5077   gint uv = GET_UV_420 (y, flags);
5078   guint8 *restrict dy = GET_PLANE_LINE (0, y);
5079   guint8 *restrict duv = GET_PLANE_LINE (1, uv);
5080   guint16 Y0 = 0, Y1 = 0, Y2 = 0, Y3 = 0, U0, V0 = 0, U1 = 0, V1 = 0;
5081   const guint16 *restrict s = src;
5082
5083   for (i = 0; i < width; i++) {
5084     switch (i & 3) {
5085       case 0:
5086         Y0 = s[i * 4 + 1] >> 6;
5087         GST_WRITE_UINT8 (dy, Y0 & 0xff);
5088         dy++;
5089
5090         if (IS_CHROMA_LINE_420 (y, flags)) {
5091           U0 = s[i * 4 + 2] >> 6;
5092           V0 = s[i * 4 + 3] >> 6;
5093
5094           GST_WRITE_UINT8 (duv, U0 & 0xff);
5095           duv++;
5096
5097           GST_WRITE_UINT8 (duv, (U0 >> 8) | ((V0 & 0x3f) << 2));
5098           duv++;
5099         }
5100         break;
5101       case 1:
5102         Y1 = s[i * 4 + 1] >> 6;
5103         GST_WRITE_UINT8 (dy, (Y0 >> 8) | ((Y1 & 0x3f) << 2));
5104         dy++;
5105         break;
5106       case 2:
5107         Y2 = s[i * 4 + 1] >> 6;
5108         GST_WRITE_UINT8 (dy, (Y1 >> 6) | ((Y2 & 0xf) << 4));
5109         dy++;
5110
5111         if (IS_CHROMA_LINE_420 (y, flags)) {
5112           U1 = s[i * 4 + 2] >> 6;
5113           V1 = s[i * 4 + 3] >> 6;
5114
5115           GST_WRITE_UINT8 (duv, (V0 >> 6) | ((U1 & 0xf) << 4));
5116           duv++;
5117
5118           GST_WRITE_UINT8 (duv, (U1 >> 4) | ((V1 & 0x3) << 6));
5119           duv++;
5120
5121           GST_WRITE_UINT8 (duv, V1 >> 2);
5122           duv++;
5123         }
5124         break;
5125       case 3:
5126         Y3 = s[i * 4 + 1] >> 6;
5127         GST_WRITE_UINT8 (dy, (Y2 >> 4) | ((Y3 & 0x3) << 6));
5128         dy++;
5129         GST_WRITE_UINT8 (dy, (Y3 >> 2));
5130         dy++;
5131         break;
5132     }
5133   }
5134
5135   switch (width & 3) {
5136     case 0:
5137       break;
5138     case 1:
5139       GST_WRITE_UINT8 (dy, Y0 >> 8);
5140       if (IS_CHROMA_LINE_420 (y, flags))
5141         GST_WRITE_UINT8 (duv, V0 >> 6);
5142       break;
5143     case 2:
5144       GST_WRITE_UINT8 (dy, Y1 >> 6);
5145       if (IS_CHROMA_LINE_420 (y, flags))
5146         GST_WRITE_UINT8 (duv, V0 >> 6);
5147       break;
5148     case 3:
5149       GST_WRITE_UINT8 (dy, Y2 >> 4);
5150       break;
5151   }
5152 }
5153
5154 typedef struct
5155 {
5156   guint32 fourcc;
5157   GstVideoFormatInfo info;
5158 } VideoFormat;
5159
5160 /* depths: bits, n_components, shift, depth */
5161 #define DPTH0            0, 0, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
5162 #define DPTH8            8, 1, { 0, 0, 0, 0 }, { 8, 0, 0, 0 }
5163 #define DPTH8_32         8, 2, { 0, 0, 0, 0 }, { 8, 32, 0, 0 }
5164 #define DPTH888          8, 3, { 0, 0, 0, 0 }, { 8, 8, 8, 0 }
5165 #define DPTH8888         8, 4, { 0, 0, 0, 0 }, { 8, 8, 8, 8 }
5166 #define DPTH8880         8, 4, { 0, 0, 0, 0 }, { 8, 8, 8, 0 }
5167 #define DPTH10           10, 1, { 0, 0, 0, 0 }, { 10, 0, 0, 0 }
5168 #define DPTH10_10_10     10, 3, { 0, 0, 0, 0 }, { 10, 10, 10, 0 }
5169 #define DPTH10_10_10_10  10, 4, { 0, 0, 0, 0 }, { 10, 10, 10, 10 }
5170 #define DPTH10_10_10_HI  16, 3, { 6, 6, 6, 0 }, { 10, 10, 10, 0 }
5171 #define DPTH12_12_12     12, 3, { 0, 0, 0, 0 }, { 12, 12, 12, 0 }
5172 #define DPTH12_12_12_12  12, 4, { 0, 0, 0, 0 }, { 12, 12, 12, 12 }
5173 #define DPTH16           16, 1, { 0, 0, 0, 0 }, { 16, 0, 0, 0 }
5174 #define DPTH16_16_16     16, 3, { 0, 0, 0, 0 }, { 16, 16, 16, 0 }
5175 #define DPTH16_16_16_16  16, 4, { 0, 0, 0, 0 }, { 16, 16, 16, 16 }
5176 #define DPTH555          16, 3, { 10, 5, 0, 0 }, { 5, 5, 5, 0 }
5177 #define DPTH565          16, 3, { 11, 5, 0, 0 }, { 5, 6, 5, 0 }
5178
5179 /* pixel strides */
5180 #define PSTR0             { 0, 0, 0, 0 }
5181 #define PSTR1             { 1, 0, 0, 0 }
5182 #define PSTR14            { 1, 4, 0, 0 }
5183 #define PSTR111           { 1, 1, 1, 0 }
5184 #define PSTR1111          { 1, 1, 1, 1 }
5185 #define PSTR122           { 1, 2, 2, 0 }
5186 #define PSTR2             { 2, 0, 0, 0 }
5187 #define PSTR222           { 2, 2, 2, 0 }
5188 #define PSTR2222          { 2, 2, 2, 2 }
5189 #define PSTR244           { 2, 4, 4, 0 }
5190 #define PSTR444           { 4, 4, 4, 0 }
5191 #define PSTR4444          { 4, 4, 4, 4 }
5192 #define PSTR333           { 3, 3, 3, 0 }
5193 #define PSTR488           { 4, 8, 8, 0 }
5194 #define PSTR8888          { 8, 8, 8, 8 }
5195
5196 /* planes, in what plane do we find component N */
5197 #define PLANE_NA          0, { 0, 0, 0, 0 }
5198 #define PLANE0            1, { 0, 0, 0, 0 }
5199 #define PLANE01           2, { 0, 1, 0, 0 }
5200 #define PLANE011          2, { 0, 1, 1, 0 }
5201 #define PLANE012          3, { 0, 1, 2, 0 }
5202 #define PLANE0123         4, { 0, 1, 2, 3 }
5203 #define PLANE021          3, { 0, 2, 1, 0 }
5204 #define PLANE201          3, { 2, 0, 1, 0 }
5205 #define PLANE2013         4, { 2, 0, 1, 3 }
5206
5207 /* offsets */
5208 #define OFFS0             { 0, 0, 0, 0 }
5209 #define OFFS013           { 0, 1, 3, 0 }
5210 #define OFFS102           { 1, 0, 2, 0 }
5211 #define OFFS1230          { 1, 2, 3, 0 }
5212 #define OFFS012           { 0, 1, 2, 0 }
5213 #define OFFS210           { 2, 1, 0, 0 }
5214 #define OFFS123           { 1, 2, 3, 0 }
5215 #define OFFS321           { 3, 2, 1, 0 }
5216 #define OFFS0123          { 0, 1, 2, 3 }
5217 #define OFFS2103          { 2, 1, 0, 3 }
5218 #define OFFS3210          { 3, 2, 1, 0 }
5219 #define OFFS031           { 0, 3, 1, 0 }
5220 #define OFFS204           { 2, 0, 4, 0 }
5221 #define OFFS001           { 0, 0, 1, 0 }
5222 #define OFFS010           { 0, 1, 0, 0 }
5223 #define OFFS104           { 1, 0, 4, 0 }
5224 #define OFFS2460          { 2, 4, 6, 0 }
5225
5226 /* subsampling, w_sub, h_sub */
5227 #define SUB410            { 0, 2, 2, 0 }, { 0, 2, 2, 0 }
5228 #define SUB411            { 0, 2, 2, 0 }, { 0, 0, 0, 0 }
5229 #define SUB420            { 0, 1, 1, 0 }, { 0, 1, 1, 0 }
5230 #define SUB422            { 0, 1, 1, 0 }, { 0, 0, 0, 0 }
5231 #define SUB4              { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
5232 #define SUB44             { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
5233 #define SUB444            { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
5234 #define SUB4444           { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
5235 #define SUB4204           { 0, 1, 1, 0 }, { 0, 1, 1, 0 }
5236 #define SUB4224           { 0, 1, 1, 0 }, { 0, 0, 0, 0 }
5237
5238 /* tile_mode, tile_width, tile_height */
5239 #define TILE_64x32(mode) GST_VIDEO_TILE_MODE_ ##mode, 6, 5
5240
5241 #define MAKE_YUV_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub, pack ) \
5242  { fourcc, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_YUV, depth, pstride, plane, offs, sub, pack } }
5243 #define MAKE_YUV_LE_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub, pack ) \
5244  { fourcc, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_YUV | GST_VIDEO_FORMAT_FLAG_LE, depth, pstride, plane, offs, sub, pack } }
5245 #define MAKE_YUVA_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub, pack) \
5246  { fourcc, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_YUV | GST_VIDEO_FORMAT_FLAG_ALPHA, depth, pstride, plane, offs, sub, pack } }
5247 #define MAKE_YUVA_LE_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub, pack ) \
5248  { fourcc, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_YUV | GST_VIDEO_FORMAT_FLAG_ALPHA | GST_VIDEO_FORMAT_FLAG_LE, depth, pstride, plane, offs, sub, pack } }
5249 #define MAKE_YUVA_PACK_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub, pack) \
5250  { fourcc, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_YUV | GST_VIDEO_FORMAT_FLAG_ALPHA | GST_VIDEO_FORMAT_FLAG_UNPACK, depth, pstride, plane, offs, sub, pack } }
5251 #define MAKE_YUVA_LE_PACK_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub, pack) \
5252  { fourcc, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_YUV | GST_VIDEO_FORMAT_FLAG_ALPHA | GST_VIDEO_FORMAT_FLAG_UNPACK | GST_VIDEO_FORMAT_FLAG_LE, depth, pstride, plane, offs, sub, pack } }
5253 #define MAKE_YUV_C_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub, pack) \
5254  { fourcc, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_YUV | GST_VIDEO_FORMAT_FLAG_COMPLEX, depth, pstride, plane, offs, sub, pack } }
5255 #define MAKE_YUV_C_LE_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub, pack) \
5256  { fourcc, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_YUV | GST_VIDEO_FORMAT_FLAG_COMPLEX | GST_VIDEO_FORMAT_FLAG_LE, depth, pstride, plane, offs, sub, pack } }
5257 #define MAKE_YUV_T_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub, pack, tile) \
5258  { fourcc, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_YUV | GST_VIDEO_FORMAT_FLAG_COMPLEX | GST_VIDEO_FORMAT_FLAG_TILED, depth, pstride, plane, offs, sub, pack, tile } }
5259
5260 #define MAKE_RGB_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
5261  { 0x00000000, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_RGB, depth, pstride, plane, offs, sub, pack } }
5262 #define MAKE_RGB_LE_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
5263  { 0x00000000, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_RGB | GST_VIDEO_FORMAT_FLAG_LE, depth, pstride, plane, offs, sub, pack } }
5264 #define MAKE_RGBA_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
5265  { 0x00000000, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_RGB | GST_VIDEO_FORMAT_FLAG_ALPHA, depth, pstride, plane, offs, sub, pack } }
5266 #define MAKE_RGBA_LE_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
5267  { 0x00000000, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_RGB | GST_VIDEO_FORMAT_FLAG_ALPHA | GST_VIDEO_FORMAT_FLAG_LE, depth, pstride, plane, offs, sub, pack } }
5268 #define MAKE_RGBAP_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
5269  { 0x00000000, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_RGB | GST_VIDEO_FORMAT_FLAG_ALPHA | GST_VIDEO_FORMAT_FLAG_PALETTE, depth, pstride, plane, offs, sub, pack } }
5270 #define MAKE_RGBA_PACK_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
5271  { 0x00000000, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_RGB | GST_VIDEO_FORMAT_FLAG_ALPHA | GST_VIDEO_FORMAT_FLAG_UNPACK, depth, pstride, plane, offs, sub, pack } }
5272 #define MAKE_RGBA_LE_PACK_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
5273  { 0x00000000, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_RGB | GST_VIDEO_FORMAT_FLAG_ALPHA | GST_VIDEO_FORMAT_FLAG_UNPACK | GST_VIDEO_FORMAT_FLAG_LE, depth, pstride, plane, offs, sub, pack } }
5274
5275 #define MAKE_GRAY_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
5276  { 0x00000000, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_GRAY, depth, pstride, plane, offs, sub, pack } }
5277 #define MAKE_GRAY_LE_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
5278  { 0x00000000, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_GRAY | GST_VIDEO_FORMAT_FLAG_LE, depth, pstride, plane, offs, sub, pack } }
5279 #define MAKE_GRAY_C_LE_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
5280  { 0x00000000, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_GRAY | GST_VIDEO_FORMAT_FLAG_COMPLEX | GST_VIDEO_FORMAT_FLAG_LE, depth, pstride, plane, offs, sub, pack } }
5281
5282 static const VideoFormat formats[] = {
5283   {0x00000000, {GST_VIDEO_FORMAT_UNKNOWN, "UNKNOWN", "unknown video", 0, DPTH0,
5284           PSTR0, PLANE_NA, OFFS0}},
5285   {0x00000000, {GST_VIDEO_FORMAT_ENCODED, "ENCODED", "encoded video",
5286           GST_VIDEO_FORMAT_FLAG_COMPLEX, DPTH0, PSTR0, PLANE_NA, OFFS0}},
5287
5288   MAKE_YUV_FORMAT (I420, "raw video", GST_MAKE_FOURCC ('I', '4', '2', '0'),
5289       DPTH888, PSTR111, PLANE012, OFFS0, SUB420, PACK_420),
5290   MAKE_YUV_FORMAT (YV12, "raw video", GST_MAKE_FOURCC ('Y', 'V', '1', '2'),
5291       DPTH888, PSTR111, PLANE021, OFFS0, SUB420, PACK_420),
5292   MAKE_YUV_FORMAT (YUY2, "raw video", GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'),
5293       DPTH888, PSTR244, PLANE0, OFFS013, SUB422, PACK_YUY2),
5294   MAKE_YUV_FORMAT (UYVY, "raw video", GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'),
5295       DPTH888, PSTR244, PLANE0, OFFS102, SUB422, PACK_UYVY),
5296   MAKE_YUVA_PACK_FORMAT (AYUV, "raw video", GST_MAKE_FOURCC ('A', 'Y', 'U',
5297           'V'), DPTH8888, PSTR4444, PLANE0, OFFS1230, SUB4444, PACK_AYUV),
5298   MAKE_RGB_FORMAT (RGBx, "raw video", DPTH888, PSTR444, PLANE0, OFFS012,
5299       SUB444, PACK_RGBA),
5300   MAKE_RGB_FORMAT (BGRx, "raw video", DPTH888, PSTR444, PLANE0, OFFS210,
5301       SUB444, PACK_BGRA),
5302   MAKE_RGB_FORMAT (xRGB, "raw video", DPTH888, PSTR444, PLANE0, OFFS123,
5303       SUB444, PACK_ARGB),
5304   MAKE_RGB_FORMAT (xBGR, "raw video", DPTH888, PSTR444, PLANE0, OFFS321,
5305       SUB444, PACK_ABGR),
5306   MAKE_RGBA_FORMAT (RGBA, "raw video", DPTH8888, PSTR4444, PLANE0, OFFS0123,
5307       SUB4444, PACK_RGBA),
5308   MAKE_RGBA_FORMAT (BGRA, "raw video", DPTH8888, PSTR4444, PLANE0, OFFS2103,
5309       SUB4444, PACK_BGRA),
5310   MAKE_RGBA_PACK_FORMAT (ARGB, "raw video", DPTH8888, PSTR4444, PLANE0,
5311       OFFS1230, SUB4444, PACK_ARGB),
5312   MAKE_RGBA_FORMAT (ABGR, "raw video", DPTH8888, PSTR4444, PLANE0, OFFS3210,
5313       SUB4444, PACK_ABGR),
5314   MAKE_RGB_FORMAT (RGB, "raw video", DPTH888, PSTR333, PLANE0, OFFS012, SUB444,
5315       PACK_RGB),
5316   MAKE_RGB_FORMAT (BGR, "raw video", DPTH888, PSTR333, PLANE0, OFFS210, SUB444,
5317       PACK_BGR),
5318
5319   MAKE_YUV_FORMAT (Y41B, "raw video", GST_MAKE_FOURCC ('Y', '4', '1', 'B'),
5320       DPTH888, PSTR111, PLANE012, OFFS0, SUB411, PACK_Y41B),
5321   MAKE_YUV_FORMAT (Y42B, "raw video", GST_MAKE_FOURCC ('Y', '4', '2', 'B'),
5322       DPTH888, PSTR111, PLANE012, OFFS0, SUB422, PACK_Y42B),
5323   MAKE_YUV_FORMAT (YVYU, "raw video", GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'),
5324       DPTH888, PSTR244, PLANE0, OFFS031, SUB422, PACK_YVYU),
5325   MAKE_YUV_FORMAT (Y444, "raw video", GST_MAKE_FOURCC ('Y', '4', '4', '4'),
5326       DPTH888, PSTR111, PLANE012, OFFS0, SUB444, PACK_Y444),
5327   MAKE_YUV_C_FORMAT (v210, "raw video", GST_MAKE_FOURCC ('v', '2', '1', '0'),
5328       DPTH10_10_10, PSTR0, PLANE0, OFFS0, SUB422, PACK_v210),
5329   MAKE_YUV_FORMAT (v216, "raw video", GST_MAKE_FOURCC ('v', '2', '1', '6'),
5330       DPTH16_16_16, PSTR488, PLANE0, OFFS204, SUB422, PACK_v216),
5331   MAKE_YUV_FORMAT (Y210, "raw video", GST_MAKE_FOURCC ('Y', '2', '1', '0'),
5332       DPTH10_10_10, PSTR488, PLANE0, OFFS0, SUB422, PACK_Y210),
5333   MAKE_YUV_FORMAT (NV12, "raw video", GST_MAKE_FOURCC ('N', 'V', '1', '2'),
5334       DPTH888, PSTR122, PLANE011, OFFS001, SUB420, PACK_NV12),
5335   MAKE_YUV_FORMAT (NV21, "raw video", GST_MAKE_FOURCC ('N', 'V', '2', '1'),
5336       DPTH888, PSTR122, PLANE011, OFFS010, SUB420, PACK_NV21),
5337
5338   MAKE_GRAY_FORMAT (GRAY8, "raw video", DPTH8, PSTR1, PLANE0, OFFS0, SUB4,
5339       PACK_GRAY8),
5340   MAKE_GRAY_FORMAT (GRAY16_BE, "raw video", DPTH16, PSTR2, PLANE0, OFFS0, SUB4,
5341       PACK_GRAY16_BE),
5342   MAKE_GRAY_LE_FORMAT (GRAY16_LE, "raw video", DPTH16, PSTR2, PLANE0, OFFS0,
5343       SUB4, PACK_GRAY16_LE),
5344
5345   MAKE_YUV_FORMAT (v308, "raw video", GST_MAKE_FOURCC ('v', '3', '0', '8'),
5346       DPTH888, PSTR333, PLANE0, OFFS012, SUB444, PACK_v308),
5347
5348 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
5349   MAKE_RGB_LE_FORMAT (RGB16, "raw video", DPTH565, PSTR222, PLANE0, OFFS0,
5350       SUB444, PACK_RGB16),
5351   MAKE_RGB_LE_FORMAT (BGR16, "raw video", DPTH565, PSTR222, PLANE0, OFFS0,
5352       SUB444, PACK_BGR16),
5353   MAKE_RGB_LE_FORMAT (RGB15, "raw video", DPTH555, PSTR222, PLANE0, OFFS0,
5354       SUB444, PACK_RGB15),
5355   MAKE_RGB_LE_FORMAT (BGR15, "raw video", DPTH555, PSTR222, PLANE0, OFFS0,
5356       SUB444, PACK_BGR15),
5357 #else
5358   MAKE_RGB_FORMAT (RGB16, "raw video", DPTH565, PSTR222, PLANE0, OFFS0, SUB444,
5359       PACK_RGB16),
5360   MAKE_RGB_FORMAT (BGR16, "raw video", DPTH565, PSTR222, PLANE0, OFFS0, SUB444,
5361       PACK_BGR16),
5362   MAKE_RGB_FORMAT (RGB15, "raw video", DPTH555, PSTR222, PLANE0, OFFS0, SUB444,
5363       PACK_RGB15),
5364   MAKE_RGB_FORMAT (BGR15, "raw video", DPTH555, PSTR222, PLANE0, OFFS0, SUB444,
5365       PACK_BGR15),
5366 #endif
5367
5368   MAKE_YUV_C_FORMAT (UYVP, "raw video", GST_MAKE_FOURCC ('U', 'Y', 'V', 'P'),
5369       DPTH10_10_10, PSTR0, PLANE0, OFFS0, SUB422, PACK_UYVP),
5370   MAKE_YUVA_FORMAT (A420, "raw video", GST_MAKE_FOURCC ('A', '4', '2', '0'),
5371       DPTH8888, PSTR1111, PLANE0123, OFFS0, SUB4204, PACK_A420),
5372   MAKE_RGBAP_FORMAT (RGB8P, "raw video", DPTH8_32, PSTR14, PLANE01,
5373       OFFS0, SUB44, PACK_RGB8P),
5374   MAKE_YUV_FORMAT (YUV9, "raw video", GST_MAKE_FOURCC ('Y', 'U', 'V', '9'),
5375       DPTH888, PSTR111, PLANE012, OFFS0, SUB410, PACK_410),
5376   MAKE_YUV_FORMAT (YVU9, "raw video", GST_MAKE_FOURCC ('Y', 'V', 'U', '9'),
5377       DPTH888, PSTR111, PLANE021, OFFS0, SUB410, PACK_410),
5378   MAKE_YUV_FORMAT (IYU1, "raw video", GST_MAKE_FOURCC ('I', 'Y', 'U', '1'),
5379       DPTH888, PSTR0, PLANE0, OFFS104, SUB411, PACK_IYU1),
5380 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
5381   MAKE_RGBA_LE_PACK_FORMAT (ARGB64, "raw video", DPTH16_16_16_16, PSTR8888,
5382       PLANE0,
5383       OFFS2460, SUB444, PACK_ARGB64),
5384   MAKE_YUVA_LE_PACK_FORMAT (AYUV64, "raw video", 0x00000000, DPTH16_16_16_16,
5385       PSTR8888, PLANE0, OFFS2460, SUB444, PACK_AYUV64),
5386 #else
5387   MAKE_RGBA_PACK_FORMAT (ARGB64, "raw video", DPTH16_16_16_16, PSTR8888, PLANE0,
5388       OFFS2460, SUB444, PACK_ARGB64),
5389   MAKE_YUVA_PACK_FORMAT (AYUV64, "raw video", 0x00000000, DPTH16_16_16_16,
5390       PSTR8888, PLANE0, OFFS2460, SUB444, PACK_AYUV64),
5391 #endif
5392   MAKE_RGB_FORMAT (r210, "raw video", DPTH10_10_10, PSTR444, PLANE0, OFFS0,
5393       SUB444, PACK_r210),
5394   MAKE_YUV_FORMAT (I420_10BE, "raw video", 0x00000000, DPTH10_10_10,
5395       PSTR222, PLANE012, OFFS0, SUB420, PACK_I420_10BE),
5396   MAKE_YUV_LE_FORMAT (I420_10LE, "raw video", 0x00000000, DPTH10_10_10,
5397       PSTR222, PLANE012, OFFS0, SUB420, PACK_I420_10LE),
5398   MAKE_YUV_FORMAT (I422_10BE, "raw video", 0x00000000, DPTH10_10_10,
5399       PSTR222, PLANE012, OFFS0, SUB422, PACK_I422_10BE),
5400   MAKE_YUV_LE_FORMAT (I422_10LE, "raw video", 0x00000000, DPTH10_10_10,
5401       PSTR222, PLANE012, OFFS0, SUB422, PACK_I422_10LE),
5402   MAKE_YUV_FORMAT (Y444_10BE, "raw video", 0x00000000, DPTH10_10_10,
5403       PSTR222, PLANE012, OFFS0, SUB444, PACK_Y444_10BE),
5404   MAKE_YUV_LE_FORMAT (Y444_10LE, "raw video", 0x00000000, DPTH10_10_10,
5405       PSTR222, PLANE012, OFFS0, SUB444, PACK_Y444_10LE),
5406   MAKE_RGB_FORMAT (GBR, "raw video", DPTH888, PSTR111, PLANE201, OFFS0, SUB444,
5407       PACK_GBR),
5408   MAKE_RGB_FORMAT (GBR_10BE, "raw video", DPTH10_10_10, PSTR222, PLANE201,
5409       OFFS0, SUB444, PACK_GBR_10BE),
5410   MAKE_RGB_LE_FORMAT (GBR_10LE, "raw video", DPTH10_10_10, PSTR222, PLANE201,
5411       OFFS0, SUB444, PACK_GBR_10LE),
5412   MAKE_YUV_FORMAT (NV16, "raw video", GST_MAKE_FOURCC ('N', 'V', '1', '6'),
5413       DPTH888, PSTR122, PLANE011, OFFS001, SUB422, PACK_NV16),
5414   MAKE_YUV_FORMAT (NV24, "raw video", GST_MAKE_FOURCC ('N', 'V', '2', '4'),
5415       DPTH888, PSTR122, PLANE011, OFFS001, SUB444, PACK_NV24),
5416   MAKE_YUV_T_FORMAT (NV12_64Z32, "raw video",
5417       GST_MAKE_FOURCC ('T', 'M', '1', '2'), DPTH8880, PSTR122, PLANE011,
5418       OFFS001, SUB420, PACK_NV12_64Z32, TILE_64x32 (ZFLIPZ_2X2)),
5419   MAKE_YUVA_FORMAT (A420_10BE, "raw video", 0x00000000, DPTH10_10_10_10,
5420       PSTR2222, PLANE0123, OFFS0, SUB4204, PACK_A420_10BE),
5421   MAKE_YUVA_LE_FORMAT (A420_10LE, "raw video", 0x00000000, DPTH10_10_10_10,
5422       PSTR2222, PLANE0123, OFFS0, SUB4204, PACK_A420_10LE),
5423   MAKE_YUVA_FORMAT (A422_10BE, "raw video", 0x00000000, DPTH10_10_10_10,
5424       PSTR2222, PLANE0123, OFFS0, SUB4224, PACK_A422_10BE),
5425   MAKE_YUVA_LE_FORMAT (A422_10LE, "raw video", 0x00000000, DPTH10_10_10_10,
5426       PSTR2222, PLANE0123, OFFS0, SUB4224, PACK_A422_10LE),
5427   MAKE_YUVA_FORMAT (A444_10BE, "raw video", 0x00000000, DPTH10_10_10_10,
5428       PSTR2222, PLANE0123, OFFS0, SUB4444, PACK_A444_10BE),
5429   MAKE_YUVA_LE_FORMAT (A444_10LE, "raw video", 0x00000000, DPTH10_10_10_10,
5430       PSTR2222, PLANE0123, OFFS0, SUB4444, PACK_A444_10LE),
5431   MAKE_YUV_FORMAT (NV61, "raw video", GST_MAKE_FOURCC ('N', 'V', '6', '1'),
5432       DPTH888, PSTR122, PLANE011, OFFS010, SUB422, PACK_NV61),
5433   MAKE_YUV_FORMAT (P010_10BE, "raw video", 0x00000000, DPTH10_10_10_HI,
5434       PSTR244, PLANE011, OFFS001, SUB420, PACK_P010_10BE),
5435   MAKE_YUV_LE_FORMAT (P010_10LE, "raw video", 0x00000000, DPTH10_10_10_HI,
5436       PSTR244, PLANE011, OFFS001, SUB420, PACK_P010_10LE),
5437   MAKE_YUV_FORMAT (IYU2, "raw video", GST_MAKE_FOURCC ('I', 'Y', 'U', '2'),
5438       DPTH888, PSTR333, PLANE0, OFFS102, SUB444, PACK_IYU2),
5439   MAKE_YUV_FORMAT (VYUY, "raw video", GST_MAKE_FOURCC ('V', 'Y', 'U', 'Y'),
5440       DPTH888, PSTR244, PLANE0, OFFS102, SUB422, PACK_VYUY),
5441   MAKE_RGBA_FORMAT (GBRA, "raw video", DPTH8888, PSTR1111, PLANE2013,
5442       OFFS0, SUB4444, PACK_GBRA),
5443   MAKE_RGBA_FORMAT (GBRA_10BE, "raw video", DPTH10_10_10_10, PSTR222, PLANE2013,
5444       OFFS0, SUB4444, PACK_GBRA_10BE),
5445   MAKE_RGBA_LE_FORMAT (GBRA_10LE, "raw video", DPTH10_10_10_10, PSTR222,
5446       PLANE2013,
5447       OFFS0, SUB4444, PACK_GBRA_10LE),
5448   MAKE_RGB_FORMAT (GBR_12BE, "raw video", DPTH12_12_12, PSTR222, PLANE201,
5449       OFFS0, SUB444, PACK_GBR_12BE),
5450   MAKE_RGB_LE_FORMAT (GBR_12LE, "raw video", DPTH12_12_12, PSTR222, PLANE201,
5451       OFFS0, SUB444, PACK_GBR_12LE),
5452   MAKE_RGBA_FORMAT (GBRA_12BE, "raw video", DPTH12_12_12_12, PSTR222, PLANE2013,
5453       OFFS0, SUB4444, PACK_GBRA_12BE),
5454   MAKE_RGBA_LE_PACK_FORMAT (GBRA_12LE, "raw video", DPTH12_12_12_12, PSTR222,
5455       PLANE2013, OFFS0, SUB4444, PACK_GBRA_12LE),
5456   MAKE_YUV_FORMAT (I420_12BE, "raw video", 0x00000000, DPTH12_12_12,
5457       PSTR222, PLANE012, OFFS0, SUB420, PACK_I420_12BE),
5458   MAKE_YUV_LE_FORMAT (I420_12LE, "raw video", 0x00000000, DPTH12_12_12,
5459       PSTR222, PLANE012, OFFS0, SUB420, PACK_I420_12LE),
5460   MAKE_YUV_FORMAT (I422_12BE, "raw video", 0x00000000, DPTH12_12_12,
5461       PSTR222, PLANE012, OFFS0, SUB422, PACK_I422_12BE),
5462   MAKE_YUV_LE_FORMAT (I422_12LE, "raw video", 0x00000000, DPTH12_12_12,
5463       PSTR222, PLANE012, OFFS0, SUB422, PACK_I422_12LE),
5464   MAKE_YUV_FORMAT (Y444_12BE, "raw video", 0x00000000, DPTH12_12_12,
5465       PSTR222, PLANE012, OFFS0, SUB444, PACK_Y444_12BE),
5466   MAKE_YUV_LE_FORMAT (Y444_12LE, "raw video", 0x00000000, DPTH12_12_12,
5467       PSTR222, PLANE012, OFFS0, SUB444, PACK_Y444_12LE),
5468   MAKE_GRAY_C_LE_FORMAT (GRAY10_LE32, "raw video", DPTH10, PSTR0, PLANE0, OFFS0,
5469       SUB4, PACK_GRAY10_LE32),
5470   MAKE_YUV_C_LE_FORMAT (NV12_10LE32, "raw video",
5471       GST_MAKE_FOURCC ('X', 'V', '1', '5'), DPTH10_10_10, PSTR0, PLANE011,
5472       OFFS001, SUB420, PACK_NV12_10LE32),
5473   MAKE_YUV_C_LE_FORMAT (NV16_10LE32, "raw video",
5474       GST_MAKE_FOURCC ('X', 'V', '2', '0'), DPTH10_10_10, PSTR0, PLANE011,
5475       OFFS001, SUB422, PACK_NV16_10LE32),
5476   MAKE_YUV_C_LE_FORMAT (NV12_10LE40, "raw video",
5477       GST_MAKE_FOURCC ('R', 'K', '2', '0'), DPTH10_10_10, PSTR0, PLANE011,
5478       OFFS0, SUB420, PACK_NV12_10LE40),
5479 };
5480
5481 static GstVideoFormat
5482 gst_video_format_from_rgb32_masks (int red_mask, int green_mask, int blue_mask)
5483 {
5484   if (red_mask == 0xff000000 && green_mask == 0x00ff0000 &&
5485       blue_mask == 0x0000ff00) {
5486     return GST_VIDEO_FORMAT_RGBx;
5487   }
5488   if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 &&
5489       blue_mask == 0xff000000) {
5490     return GST_VIDEO_FORMAT_BGRx;
5491   }
5492   if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 &&
5493       blue_mask == 0x000000ff) {
5494     return GST_VIDEO_FORMAT_xRGB;
5495   }
5496   if (red_mask == 0x000000ff && green_mask == 0x0000ff00 &&
5497       blue_mask == 0x00ff0000) {
5498     return GST_VIDEO_FORMAT_xBGR;
5499   }
5500
5501   return GST_VIDEO_FORMAT_UNKNOWN;
5502 }
5503
5504 static GstVideoFormat
5505 gst_video_format_from_rgba32_masks (int red_mask, int green_mask,
5506     int blue_mask, int alpha_mask)
5507 {
5508   if (red_mask == 0xff000000 && green_mask == 0x00ff0000 &&
5509       blue_mask == 0x0000ff00 && alpha_mask == 0x000000ff) {
5510     return GST_VIDEO_FORMAT_RGBA;
5511   }
5512   if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 &&
5513       blue_mask == 0xff000000 && alpha_mask == 0x000000ff) {
5514     return GST_VIDEO_FORMAT_BGRA;
5515   }
5516   if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 &&
5517       blue_mask == 0x000000ff && alpha_mask == 0xff000000) {
5518     return GST_VIDEO_FORMAT_ARGB;
5519   }
5520   if (red_mask == 0x000000ff && green_mask == 0x0000ff00 &&
5521       blue_mask == 0x00ff0000 && alpha_mask == 0xff000000) {
5522     return GST_VIDEO_FORMAT_ABGR;
5523   }
5524   return GST_VIDEO_FORMAT_UNKNOWN;
5525 }
5526
5527 static GstVideoFormat
5528 gst_video_format_from_rgb24_masks (int red_mask, int green_mask, int blue_mask)
5529 {
5530   if (red_mask == 0xff0000 && green_mask == 0x00ff00 && blue_mask == 0x0000ff) {
5531     return GST_VIDEO_FORMAT_RGB;
5532   }
5533   if (red_mask == 0x0000ff && green_mask == 0x00ff00 && blue_mask == 0xff0000) {
5534     return GST_VIDEO_FORMAT_BGR;
5535   }
5536
5537   return GST_VIDEO_FORMAT_UNKNOWN;
5538 }
5539
5540 #define GST_VIDEO_COMP1_MASK_16_INT 0xf800
5541 #define GST_VIDEO_COMP2_MASK_16_INT 0x07e0
5542 #define GST_VIDEO_COMP3_MASK_16_INT 0x001f
5543
5544 #define GST_VIDEO_COMP1_MASK_15_INT 0x7c00
5545 #define GST_VIDEO_COMP2_MASK_15_INT 0x03e0
5546 #define GST_VIDEO_COMP3_MASK_15_INT 0x001f
5547
5548 static GstVideoFormat
5549 gst_video_format_from_rgb16_masks (int red_mask, int green_mask, int blue_mask)
5550 {
5551   if (red_mask == GST_VIDEO_COMP1_MASK_16_INT
5552       && green_mask == GST_VIDEO_COMP2_MASK_16_INT
5553       && blue_mask == GST_VIDEO_COMP3_MASK_16_INT) {
5554     return GST_VIDEO_FORMAT_RGB16;
5555   }
5556   if (red_mask == GST_VIDEO_COMP3_MASK_16_INT
5557       && green_mask == GST_VIDEO_COMP2_MASK_16_INT
5558       && blue_mask == GST_VIDEO_COMP1_MASK_16_INT) {
5559     return GST_VIDEO_FORMAT_BGR16;
5560   }
5561   if (red_mask == GST_VIDEO_COMP1_MASK_15_INT
5562       && green_mask == GST_VIDEO_COMP2_MASK_15_INT
5563       && blue_mask == GST_VIDEO_COMP3_MASK_15_INT) {
5564     return GST_VIDEO_FORMAT_RGB15;
5565   }
5566   if (red_mask == GST_VIDEO_COMP3_MASK_15_INT
5567       && green_mask == GST_VIDEO_COMP2_MASK_15_INT
5568       && blue_mask == GST_VIDEO_COMP1_MASK_15_INT) {
5569     return GST_VIDEO_FORMAT_BGR15;
5570   }
5571   return GST_VIDEO_FORMAT_UNKNOWN;
5572 }
5573
5574 /**
5575  * gst_video_format_from_masks:
5576  * @depth: the amount of bits used for a pixel
5577  * @bpp: the amount of bits used to store a pixel. This value is bigger than
5578  *   @depth
5579  * @endianness: the endianness of the masks, #G_LITTLE_ENDIAN or #G_BIG_ENDIAN
5580  * @red_mask: the red mask
5581  * @green_mask: the green mask
5582  * @blue_mask: the blue mask
5583  * @alpha_mask: the alpha mask, or 0 if no alpha mask
5584  *
5585  * Find the #GstVideoFormat for the given parameters.
5586  *
5587  * Returns: a #GstVideoFormat or GST_VIDEO_FORMAT_UNKNOWN when the parameters to
5588  * not specify a known format.
5589  */
5590 GstVideoFormat
5591 gst_video_format_from_masks (gint depth, gint bpp, gint endianness,
5592     guint red_mask, guint green_mask, guint blue_mask, guint alpha_mask)
5593 {
5594   GstVideoFormat format;
5595
5596   /* our caps system handles 24/32bpp RGB as big-endian. */
5597   if ((bpp == 24 || bpp == 32) && endianness == G_LITTLE_ENDIAN) {
5598     red_mask = GUINT32_TO_BE (red_mask);
5599     green_mask = GUINT32_TO_BE (green_mask);
5600     blue_mask = GUINT32_TO_BE (blue_mask);
5601     alpha_mask = GUINT32_TO_BE (alpha_mask);
5602     endianness = G_BIG_ENDIAN;
5603     if (bpp == 24) {
5604       red_mask >>= 8;
5605       green_mask >>= 8;
5606       blue_mask >>= 8;
5607     }
5608   }
5609
5610   if (depth == 30 && bpp == 32) {
5611     format = GST_VIDEO_FORMAT_r210;
5612   } else if (depth == 24 && bpp == 32) {
5613     format = gst_video_format_from_rgb32_masks (red_mask, green_mask,
5614         blue_mask);
5615   } else if (depth == 32 && bpp == 32 && alpha_mask) {
5616     format = gst_video_format_from_rgba32_masks (red_mask, green_mask,
5617         blue_mask, alpha_mask);
5618   } else if (depth == 24 && bpp == 24) {
5619     format = gst_video_format_from_rgb24_masks (red_mask, green_mask,
5620         blue_mask);
5621   } else if ((depth == 15 || depth == 16) && bpp == 16 &&
5622       endianness == G_BYTE_ORDER) {
5623     format = gst_video_format_from_rgb16_masks (red_mask, green_mask,
5624         blue_mask);
5625   } else if (depth == 8 && bpp == 8) {
5626     format = GST_VIDEO_FORMAT_RGB8P;
5627   } else if (depth == 64 && bpp == 64) {
5628     format = gst_video_format_from_rgba32_masks (red_mask, green_mask,
5629         blue_mask, alpha_mask);
5630     if (format == GST_VIDEO_FORMAT_ARGB) {
5631       format = GST_VIDEO_FORMAT_ARGB64;
5632     } else {
5633       format = GST_VIDEO_FORMAT_UNKNOWN;
5634     }
5635   } else {
5636     format = GST_VIDEO_FORMAT_UNKNOWN;
5637   }
5638   return format;
5639 }
5640
5641 /**
5642  * gst_video_format_from_fourcc:
5643  * @fourcc: a FOURCC value representing raw YUV video
5644  *
5645  * Converts a FOURCC value into the corresponding #GstVideoFormat.
5646  * If the FOURCC cannot be represented by #GstVideoFormat,
5647  * #GST_VIDEO_FORMAT_UNKNOWN is returned.
5648  *
5649  * Returns: the #GstVideoFormat describing the FOURCC value
5650  */
5651 GstVideoFormat
5652 gst_video_format_from_fourcc (guint32 fourcc)
5653 {
5654   switch (fourcc) {
5655     case GST_MAKE_FOURCC ('I', '4', '2', '0'):
5656       return GST_VIDEO_FORMAT_I420;
5657     case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
5658       return GST_VIDEO_FORMAT_YV12;
5659     case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
5660       return GST_VIDEO_FORMAT_YUY2;
5661     case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'):
5662       return GST_VIDEO_FORMAT_YVYU;
5663     case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
5664       return GST_VIDEO_FORMAT_UYVY;
5665     case GST_MAKE_FOURCC ('V', 'Y', 'U', 'Y'):
5666       return GST_VIDEO_FORMAT_VYUY;
5667     case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'):
5668       return GST_VIDEO_FORMAT_AYUV;
5669     case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
5670       return GST_VIDEO_FORMAT_Y41B;
5671     case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
5672       return GST_VIDEO_FORMAT_Y42B;
5673     case GST_MAKE_FOURCC ('Y', '4', '4', '4'):
5674       return GST_VIDEO_FORMAT_Y444;
5675     case GST_MAKE_FOURCC ('v', '2', '1', '0'):
5676       return GST_VIDEO_FORMAT_v210;
5677     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
5678       return GST_VIDEO_FORMAT_v216;
5679     case GST_MAKE_FOURCC ('Y', '2', '1', '0'):
5680       return GST_VIDEO_FORMAT_Y210;
5681     case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
5682       return GST_VIDEO_FORMAT_NV12;
5683     case GST_MAKE_FOURCC ('N', 'V', '2', '1'):
5684       return GST_VIDEO_FORMAT_NV21;
5685     case GST_MAKE_FOURCC ('N', 'V', '1', '6'):
5686       return GST_VIDEO_FORMAT_NV16;
5687     case GST_MAKE_FOURCC ('N', 'V', '6', '1'):
5688       return GST_VIDEO_FORMAT_NV61;
5689     case GST_MAKE_FOURCC ('N', 'V', '2', '4'):
5690       return GST_VIDEO_FORMAT_NV24;
5691     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
5692       return GST_VIDEO_FORMAT_v308;
5693     case GST_MAKE_FOURCC ('I', 'Y', 'U', '2'):
5694       return GST_VIDEO_FORMAT_IYU2;
5695     case GST_MAKE_FOURCC ('Y', '8', '0', '0'):
5696     case GST_MAKE_FOURCC ('Y', '8', ' ', ' '):
5697     case GST_MAKE_FOURCC ('G', 'R', 'E', 'Y'):
5698       return GST_VIDEO_FORMAT_GRAY8;
5699     case GST_MAKE_FOURCC ('Y', '1', '6', ' '):
5700       return GST_VIDEO_FORMAT_GRAY16_LE;
5701     case GST_MAKE_FOURCC ('U', 'Y', 'V', 'P'):
5702       return GST_VIDEO_FORMAT_UYVP;
5703     case GST_MAKE_FOURCC ('A', '4', '2', '0'):
5704       return GST_VIDEO_FORMAT_A420;
5705     case GST_MAKE_FOURCC ('Y', 'U', 'V', '9'):
5706       return GST_VIDEO_FORMAT_YUV9;
5707     case GST_MAKE_FOURCC ('Y', 'V', 'U', '9'):
5708       return GST_VIDEO_FORMAT_YVU9;
5709     case GST_MAKE_FOURCC ('I', 'Y', 'U', '1'):
5710       return GST_VIDEO_FORMAT_IYU1;
5711     case GST_MAKE_FOURCC ('A', 'Y', '6', '4'):
5712       return GST_VIDEO_FORMAT_AYUV64;
5713     case GST_MAKE_FOURCC ('X', 'V', '1', '0'):
5714       return GST_VIDEO_FORMAT_GRAY10_LE32;
5715     case GST_MAKE_FOURCC ('X', 'V', '1', '5'):
5716       return GST_VIDEO_FORMAT_NV12_10LE32;
5717     case GST_MAKE_FOURCC ('X', 'V', '2', '0'):
5718       return GST_VIDEO_FORMAT_NV16_10LE32;
5719     case GST_MAKE_FOURCC ('R', 'K', '2', '0'):
5720       return GST_VIDEO_FORMAT_NV12_10LE40;
5721     default:
5722       return GST_VIDEO_FORMAT_UNKNOWN;
5723   }
5724 }
5725
5726 /**
5727  * gst_video_format_from_string:
5728  * @format: a format string
5729  *
5730  * Convert the @format string to its #GstVideoFormat.
5731  *
5732  * Returns: the #GstVideoFormat for @format or GST_VIDEO_FORMAT_UNKNOWN when the
5733  * string is not a known format.
5734  */
5735 GstVideoFormat
5736 gst_video_format_from_string (const gchar * format)
5737 {
5738   guint i;
5739
5740   g_return_val_if_fail (format != NULL, GST_VIDEO_FORMAT_UNKNOWN);
5741
5742   for (i = 0; i < G_N_ELEMENTS (formats); i++) {
5743     if (strcmp (GST_VIDEO_FORMAT_INFO_NAME (&formats[i].info), format) == 0)
5744       return GST_VIDEO_FORMAT_INFO_FORMAT (&formats[i].info);
5745   }
5746   return GST_VIDEO_FORMAT_UNKNOWN;
5747 }
5748
5749
5750 /**
5751  * gst_video_format_to_fourcc:
5752  * @format: a #GstVideoFormat video format
5753  *
5754  * Converts a #GstVideoFormat value into the corresponding FOURCC.  Only
5755  * a few YUV formats have corresponding FOURCC values.  If @format has
5756  * no corresponding FOURCC value, 0 is returned.
5757  *
5758  * Returns: the FOURCC corresponding to @format
5759  */
5760 guint32
5761 gst_video_format_to_fourcc (GstVideoFormat format)
5762 {
5763   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
5764
5765   if ((gint) format >= G_N_ELEMENTS (formats))
5766     return 0;
5767
5768   return formats[format].fourcc;
5769 }
5770
5771 /**
5772  * gst_video_format_to_string:
5773  * @format: a #GstVideoFormat video format
5774  *
5775  * Returns a string containing a descriptive name for
5776  * the #GstVideoFormat if there is one, or NULL otherwise.
5777  *
5778  * Returns: the name corresponding to @format
5779  */
5780 const gchar *
5781 gst_video_format_to_string (GstVideoFormat format)
5782 {
5783   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
5784
5785   if ((gint) format >= G_N_ELEMENTS (formats))
5786     return NULL;
5787
5788   return GST_VIDEO_FORMAT_INFO_NAME (&formats[format].info);
5789 }
5790
5791 /**
5792  * gst_video_format_get_info:
5793  * @format: a #GstVideoFormat
5794  *
5795  * Get the #GstVideoFormatInfo for @format
5796  *
5797  * Returns: The #GstVideoFormatInfo for @format.
5798  */
5799 const GstVideoFormatInfo *
5800 gst_video_format_get_info (GstVideoFormat format)
5801 {
5802   g_return_val_if_fail ((gint) format < G_N_ELEMENTS (formats), NULL);
5803
5804   return &formats[format].info;
5805 }
5806
5807 /**
5808  * gst_video_format_get_palette:
5809  * @format: a #GstVideoFormat
5810  * @size: (out): size of the palette in bytes
5811  *
5812  * Get the default palette of @format. This the palette used in the pack
5813  * function for paletted formats.
5814  *
5815  * Returns: (transfer none): the default palette of @format or %NULL when
5816  * @format does not have a palette.
5817  *
5818  * Since: 1.2
5819  */
5820 gconstpointer
5821 gst_video_format_get_palette (GstVideoFormat format, gsize * size)
5822 {
5823   g_return_val_if_fail ((gint) format < G_N_ELEMENTS (formats), NULL);
5824   g_return_val_if_fail (size != NULL, NULL);
5825
5826   switch (format) {
5827     case GST_VIDEO_FORMAT_RGB8P:
5828       *size = sizeof (std_palette_RGB8P);
5829       return std_palette_RGB8P;
5830     default:
5831       return NULL;
5832   }
5833 }