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