video-format: fix range extension of UYVP
[platform/upstream/gst-plugins-base.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 /* Line conversion to AYUV */
33
34 #define GET_PLANE_STRIDE(plane) (stride(plane))
35 #define GET_PLANE_LINE(plane, line) \
36   (gpointer)(((guint8*)(data[plane])) + stride[plane] * (line))
37
38 #define GET_COMP_STRIDE(comp) \
39   GST_VIDEO_FORMAT_INFO_STRIDE (info, stride, comp)
40 #define GET_COMP_DATA(comp) \
41   GST_VIDEO_FORMAT_INFO_DATA (info, data, comp)
42
43 #define GET_COMP_LINE(comp, line) \
44   (gpointer)(((guint8*)GET_COMP_DATA (comp)) + \
45       GET_COMP_STRIDE(comp) * (line))
46
47 #define GET_LINE(line)               GET_PLANE_LINE (0, line)
48
49 #define GET_Y_LINE(line)             GET_COMP_LINE(GST_VIDEO_COMP_Y, line)
50 #define GET_U_LINE(line)             GET_COMP_LINE(GST_VIDEO_COMP_U, line)
51 #define GET_V_LINE(line)             GET_COMP_LINE(GST_VIDEO_COMP_V, line)
52
53 #define GET_R_LINE(line)             GET_COMP_LINE(GST_VIDEO_COMP_R, line)
54 #define GET_G_LINE(line)             GET_COMP_LINE(GST_VIDEO_COMP_G, line)
55 #define GET_B_LINE(line)             GET_COMP_LINE(GST_VIDEO_COMP_B, line)
56
57 #define GET_A_LINE(line)             GET_COMP_LINE(GST_VIDEO_COMP_A, line)
58
59 #define GET_UV_420(line, flags)                 \
60   (flags & GST_VIDEO_PACK_FLAG_INTERLACED ?     \
61    ((line & ~3) >> 1) + (line & 1) :            \
62    line >> 1)
63 #define GET_UV_410(line, flags)                 \
64   (flags & GST_VIDEO_PACK_FLAG_INTERLACED ?     \
65    ((line & ~7) >> 2) + (line & 1) :            \
66    line >> 2)
67
68 #define IS_ALIGNED(x,n) ((((guintptr)(x)&((n)-1))) == 0)
69
70 #define PACK_420 GST_VIDEO_FORMAT_AYUV, unpack_planar_420, 1, pack_planar_420
71 static void
72 unpack_planar_420 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
73     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
74     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
75 {
76   gint uv = GET_UV_420 (y, flags);
77   guint8 *y_line = GET_Y_LINE (y);
78   guint8 *u_line = GET_U_LINE (uv);
79   guint8 *v_line = GET_V_LINE (uv);
80   guint8 *ayuv = dest;
81
82   video_orc_unpack_I420 (dest, y_line, u_line, v_line, width);
83
84   if (width & 1) {
85     gint i = width - 1;
86
87     ayuv[i * 4 + 2] = u_line[i >> 1];
88     ayuv[i * 4 + 3] = v_line[i >> 1];
89   }
90 }
91
92 static void
93 pack_planar_420 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
94     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
95     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
96     gint y, gint width)
97 {
98   gint uv = GET_UV_420 (y, flags);
99   guint8 *y_line = GET_Y_LINE (y);
100   guint8 *u_line = GET_U_LINE (uv);
101   guint8 *v_line = GET_V_LINE (uv);
102   const guint8 *ayuv = src;
103
104   g_return_if_fail (IS_ALIGNED (src, 8));
105
106   video_orc_pack_I420 (y_line, u_line, v_line, src, width / 2);
107
108   if (width & 1) {
109     gint i = width - 1;
110
111     y_line[i] = ayuv[i * 4 + 1];
112     u_line[i >> 1] = ayuv[i * 4 + 2];
113     v_line[i >> 1] = ayuv[i * 4 + 3];
114   }
115 }
116
117 #define PACK_YUY2 GST_VIDEO_FORMAT_AYUV, unpack_YUY2, 1, pack_YUY2
118 static void
119 unpack_YUY2 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
120     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
121     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
122 {
123   guint8 *line = GET_LINE (y);
124   guint8 *d = dest;
125
126   g_return_if_fail (IS_ALIGNED (dest, 8));
127
128   video_orc_unpack_YUY2 (dest, line, width / 2);
129
130   if (width & 1) {
131     gint i = width - 1;
132
133     d[i * 4 + 0] = 0xff;
134     d[i * 4 + 1] = line[i * 2 + 0];
135     d[i * 4 + 2] = line[i * 2 + 1];
136     d[i * 4 + 3] = line[i * 2 + 3];
137   }
138 }
139
140 static void
141 pack_YUY2 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
142     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
143     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
144     gint y, gint width)
145 {
146   guint8 *line = GET_LINE (y);
147   const guint8 *ayuv = src;
148
149   g_return_if_fail (IS_ALIGNED (src, 8));
150
151   video_orc_pack_YUY2 (line, src, width / 2);
152
153   if (width & 1) {
154     gint i = width - 1;
155
156     line[i * 2 + 0] = ayuv[i * 4 + 1];
157     line[i * 2 + 1] = ayuv[i * 4 + 2];
158     line[i * 2 + 3] = ayuv[i * 4 + 3];
159   }
160 }
161
162 #define PACK_UYVY GST_VIDEO_FORMAT_AYUV, unpack_UYVY, 1, pack_UYVY
163 static void
164 unpack_UYVY (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
165     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
166     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
167 {
168   guint8 *line = GET_LINE (y);
169   guint8 *d = dest;
170
171   g_return_if_fail (IS_ALIGNED (dest, 8));
172
173   video_orc_unpack_UYVY (dest, line, width / 2);
174
175   if (width & 1) {
176     gint i = width - 1;
177
178     d[i * 4 + 0] = 0xff;
179     d[i * 4 + 1] = line[i * 2 + 1];
180     d[i * 4 + 2] = line[i * 2 + 0];
181     d[i * 4 + 3] = line[i * 2 + 2];
182   }
183 }
184
185 static void
186 pack_UYVY (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
187     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
188     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
189     gint y, gint width)
190 {
191   guint8 *line = GET_LINE (y);
192   const guint8 *ayuv = src;
193
194   g_return_if_fail (IS_ALIGNED (src, 8));
195
196   video_orc_pack_UYVY (line, src, width / 2);
197
198   if (width & 1) {
199     gint i = width - 1;
200
201     line[i * 2 + 0] = ayuv[i * 4 + 2];
202     line[i * 2 + 1] = ayuv[i * 4 + 1];
203     line[i * 2 + 2] = ayuv[i * 4 + 3];
204   }
205 }
206
207 #define PACK_YVYU GST_VIDEO_FORMAT_AYUV, unpack_YVYU, 1, pack_YVYU
208 static void
209 unpack_YVYU (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
210     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
211     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
212 {
213   guint8 *line = GET_LINE (y);
214   guint8 *d = dest;
215
216   g_return_if_fail (IS_ALIGNED (dest, 8));
217
218   video_orc_unpack_YVYU (dest, line, width / 2);
219
220   if (width & 1) {
221     gint i = width - 1;
222
223     d[i * 4 + 0] = 0xff;
224     d[i * 4 + 1] = line[i * 2 + 0];
225     d[i * 4 + 2] = line[i * 2 + 3];
226     d[i * 4 + 3] = line[i * 2 + 1];
227   }
228 }
229
230 static void
231 pack_YVYU (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
232     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
233     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
234     gint y, gint width)
235 {
236   guint8 *line = GET_LINE (y);
237   const guint8 *ayuv = src;
238
239   g_return_if_fail (IS_ALIGNED (src, 8));
240
241   video_orc_pack_YVYU (line, src, width / 2);
242
243   if (width & 1) {
244     gint i = width - 1;
245
246     line[i * 2 + 0] = ayuv[i * 4 + 1];
247     line[i * 2 + 1] = ayuv[i * 4 + 3];
248     line[i * 2 + 3] = ayuv[i * 4 + 2];
249   }
250 }
251
252 #define PACK_v308 GST_VIDEO_FORMAT_AYUV, unpack_v308, 1, pack_v308
253 static void
254 unpack_v308 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
255     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
256     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
257 {
258   int i;
259   const guint8 *s = GET_LINE (y);
260   guint8 *d = dest;
261
262   for (i = 0; i < width; i++) {
263     d[i * 4 + 0] = 0xff;
264     d[i * 4 + 1] = s[i * 3 + 0];
265     d[i * 4 + 2] = s[i * 3 + 1];
266     d[i * 4 + 3] = s[i * 3 + 2];
267   }
268 }
269
270 static void
271 pack_v308 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
272     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
273     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
274     gint y, gint width)
275 {
276   int i;
277   guint8 *d = GET_LINE (y);
278   const guint8 *s = src;
279
280   for (i = 0; i < width; i++) {
281     d[i * 3 + 0] = s[i * 4 + 1];
282     d[i * 3 + 1] = s[i * 4 + 2];
283     d[i * 3 + 2] = s[i * 4 + 3];
284   }
285 }
286
287 #define PACK_AYUV GST_VIDEO_FORMAT_AYUV, unpack_copy4, 1, pack_copy4
288 #define PACK_ARGB GST_VIDEO_FORMAT_ARGB, unpack_copy4, 1, pack_copy4
289 static void
290 unpack_copy4 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
291     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
292     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
293 {
294   memcpy (dest, GET_LINE (y), width * 4);
295 }
296
297 static void
298 pack_copy4 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
299     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
300     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
301     gint y, gint width)
302 {
303   memcpy (GET_LINE (y), src, width * 4);
304 }
305
306 #define PACK_v210 GST_VIDEO_FORMAT_AYUV64, unpack_v210, 1, pack_v210
307 static void
308 unpack_v210 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
309     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
310     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
311 {
312   int i;
313   const guint8 *s = GET_LINE (y);
314   guint16 *d = dest;
315   guint32 a0, a1, a2, a3;
316   guint16 y0, y1, y2, y3, y4, y5;
317   guint16 u0, u2, u4;
318   guint16 v0, v2, v4;
319
320   for (i = 0; i < width; i += 6) {
321     a0 = GST_READ_UINT32_LE (s + (i / 6) * 16 + 0);
322     a1 = GST_READ_UINT32_LE (s + (i / 6) * 16 + 4);
323     a2 = GST_READ_UINT32_LE (s + (i / 6) * 16 + 8);
324     a3 = GST_READ_UINT32_LE (s + (i / 6) * 16 + 12);
325
326     u0 = ((a0 >> 0) & 0x3ff) << 6;
327     y0 = ((a0 >> 10) & 0x3ff) << 6;
328     v0 = ((a0 >> 20) & 0x3ff) << 6;
329     y1 = ((a1 >> 0) & 0x3ff) << 6;
330
331     u2 = ((a1 >> 10) & 0x3ff) << 6;
332     y2 = ((a1 >> 20) & 0x3ff) << 6;
333     v2 = ((a2 >> 0) & 0x3ff) << 6;
334     y3 = ((a2 >> 10) & 0x3ff) << 6;
335
336     u4 = ((a2 >> 20) & 0x3ff) << 6;
337     y4 = ((a3 >> 0) & 0x3ff) << 6;
338     v4 = ((a3 >> 10) & 0x3ff) << 6;
339     y5 = ((a3 >> 20) & 0x3ff) << 6;
340
341     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
342       y0 |= (y0 >> 10);
343       y1 |= (y1 >> 10);
344       u0 |= (u0 >> 10);
345       v0 |= (v0 >> 10);
346
347       y2 |= (y2 >> 10);
348       y3 |= (y3 >> 10);
349       u2 |= (u2 >> 10);
350       v2 |= (v2 >> 10);
351
352       y4 |= (y4 >> 10);
353       y5 |= (y5 >> 10);
354       u4 |= (u4 >> 10);
355       v4 |= (v4 >> 10);
356     }
357
358     d[4 * (i + 0) + 0] = 0xffff;
359     d[4 * (i + 0) + 1] = y0;
360     d[4 * (i + 0) + 2] = u0;
361     d[4 * (i + 0) + 3] = v0;
362
363     if (i < width - 1) {
364       d[4 * (i + 1) + 0] = 0xffff;
365       d[4 * (i + 1) + 1] = y1;
366       d[4 * (i + 1) + 2] = u0;
367       d[4 * (i + 1) + 3] = v0;
368     }
369     if (i < width - 2) {
370       d[4 * (i + 2) + 0] = 0xffff;
371       d[4 * (i + 2) + 1] = y2;
372       d[4 * (i + 2) + 2] = u2;
373       d[4 * (i + 2) + 3] = v2;
374     }
375     if (i < width - 3) {
376       d[4 * (i + 3) + 0] = 0xffff;
377       d[4 * (i + 3) + 1] = y3;
378       d[4 * (i + 3) + 2] = u2;
379       d[4 * (i + 3) + 3] = v2;
380     }
381     if (i < width - 4) {
382       d[4 * (i + 4) + 0] = 0xffff;
383       d[4 * (i + 4) + 1] = y4;
384       d[4 * (i + 4) + 2] = u4;
385       d[4 * (i + 4) + 3] = v4;
386     }
387     if (i < width - 5) {
388       d[4 * (i + 5) + 0] = 0xffff;
389       d[4 * (i + 5) + 1] = y5;
390       d[4 * (i + 5) + 2] = u4;
391       d[4 * (i + 5) + 3] = v4;
392     }
393   }
394 }
395
396 static void
397 pack_v210 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
398     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
399     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
400     gint y, gint width)
401 {
402   int i;
403   guint8 *d = GET_LINE (y);
404   const guint16 *s = src;
405   guint32 a0, a1, a2, a3;
406   guint16 y0, y1, y2, y3, y4, y5;
407   guint16 u0, u1, u2;
408   guint16 v0, v1, v2;
409
410   for (i = 0; i < width - 5; i += 6) {
411     y0 = s[4 * (i + 0) + 1] >> 6;
412     y1 = s[4 * (i + 1) + 1] >> 6;
413     y2 = s[4 * (i + 2) + 1] >> 6;
414     y3 = s[4 * (i + 3) + 1] >> 6;
415     y4 = s[4 * (i + 4) + 1] >> 6;
416     y5 = s[4 * (i + 5) + 1] >> 6;
417
418     u0 = s[4 * (i + 0) + 2] >> 6;
419     u1 = s[4 * (i + 2) + 2] >> 6;
420     u2 = s[4 * (i + 4) + 2] >> 6;
421
422     v0 = s[4 * (i + 0) + 3] >> 6;
423     v1 = s[4 * (i + 2) + 3] >> 6;
424     v2 = s[4 * (i + 4) + 3] >> 6;
425
426     a0 = u0 | (y0 << 10) | (v0 << 20);
427     a1 = y1 | (u1 << 10) | (y2 << 20);
428     a2 = v1 | (y3 << 10) | (u2 << 20);
429     a3 = y4 | (v2 << 10) | (y5 << 20);
430
431     GST_WRITE_UINT32_LE (d + (i / 6) * 16 + 0, a0);
432     GST_WRITE_UINT32_LE (d + (i / 6) * 16 + 4, a1);
433     GST_WRITE_UINT32_LE (d + (i / 6) * 16 + 8, a2);
434     GST_WRITE_UINT32_LE (d + (i / 6) * 16 + 12, a3);
435   }
436   if (i < width) {
437     y0 = s[4 * (i + 0) + 1] >> 6;
438     u0 = s[4 * (i + 0) + 2] >> 6;
439     v0 = s[4 * (i + 0) + 3] >> 6;
440     if (i < width - 1)
441       y1 = s[4 * (i + 1) + 1] >> 6;
442     else
443       y1 = y0;
444     if (i < width - 2) {
445       y2 = s[4 * (i + 2) + 1] >> 6;
446       u1 = s[4 * (i + 2) + 2] >> 6;
447       v1 = s[4 * (i + 2) + 3] >> 6;
448     } else {
449       y2 = y1;
450       u1 = u0;
451       v1 = v0;
452     }
453     if (i < width - 3)
454       y3 = s[4 * (i + 3) + 1] >> 6;
455     else
456       y3 = y2;
457     if (i < width - 4) {
458       y4 = s[4 * (i + 4) + 1] >> 6;
459       u2 = s[4 * (i + 4) + 2] >> 6;
460       v2 = s[4 * (i + 4) + 3] >> 6;
461     } else {
462       y4 = y3;
463       u2 = u1;
464       v2 = v1;
465     }
466     y5 = y4;
467
468     a0 = u0 | (y0 << 10) | (v0 << 20);
469     a1 = y1 | (u1 << 10) | (y2 << 20);
470     a2 = v1 | (y3 << 10) | (u2 << 20);
471     a3 = y4 | (v2 << 10) | (y5 << 20);
472
473     GST_WRITE_UINT32_LE (d + (i / 6) * 16 + 0, a0);
474     GST_WRITE_UINT32_LE (d + (i / 6) * 16 + 4, a1);
475     GST_WRITE_UINT32_LE (d + (i / 6) * 16 + 8, a2);
476     GST_WRITE_UINT32_LE (d + (i / 6) * 16 + 12, a3);
477   }
478 }
479
480 #define PACK_v216 GST_VIDEO_FORMAT_AYUV64, unpack_v216, 1, pack_v216
481 static void
482 unpack_v216 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
483     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
484     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
485 {
486   int i;
487   const guint8 *s = GET_LINE (y);
488   guint16 *d = dest;
489
490   for (i = 0; i < width; i++) {
491     d[i * 4 + 0] = 0xffff;
492     d[i * 4 + 1] = GST_READ_UINT16_LE (s + i * 4 + 2);
493     d[i * 4 + 2] = GST_READ_UINT16_LE (s + (i >> 1) * 8 + 0);
494     d[i * 4 + 3] = GST_READ_UINT16_LE (s + (i >> 1) * 8 + 4);
495   }
496 }
497
498 static void
499 pack_v216 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
500     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
501     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
502     gint y, gint width)
503 {
504   int i;
505   guint8 *d = GET_LINE (y);
506   const guint16 *s = src;
507
508   for (i = 0; i < width - 1; i += 2) {
509     GST_WRITE_UINT16_LE (d + i * 4 + 0, s[(i + 0) * 4 + 2]);
510     GST_WRITE_UINT16_LE (d + i * 4 + 2, s[(i + 0) * 4 + 1]);
511     GST_WRITE_UINT16_LE (d + i * 4 + 4, s[(i + 0) * 4 + 3]);
512     GST_WRITE_UINT16_LE (d + i * 4 + 6, s[(i + 1) * 4 + 1]);
513   }
514   if (i == width - 1) {
515     GST_WRITE_UINT16_LE (d + i * 4 + 0, s[i * 4 + 2]);
516     GST_WRITE_UINT16_LE (d + i * 4 + 2, s[i * 4 + 1]);
517     GST_WRITE_UINT16_LE (d + i * 4 + 4, s[i * 4 + 3]);
518     GST_WRITE_UINT16_LE (d + i * 4 + 6, s[i * 4 + 1]);
519   }
520 }
521
522 #define PACK_Y41B GST_VIDEO_FORMAT_AYUV, unpack_Y41B, 1, pack_Y41B
523 static void
524 unpack_Y41B (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
525     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
526     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
527 {
528   guint8 *y_line = GET_Y_LINE (y);
529   guint8 *u_line = GET_U_LINE (y);
530   guint8 *v_line = GET_V_LINE (y);
531   guint8 *d = dest;
532
533   g_return_if_fail (IS_ALIGNED (dest, 8));
534
535   video_orc_unpack_YUV9 (dest, y_line, u_line, v_line, width / 2);
536
537   if (width & 1) {
538     gint i = width - 1;
539
540     d[i * 4 + 0] = 0xff;
541     d[i * 4 + 1] = y_line[i];
542     d[i * 4 + 2] = u_line[i >> 2];
543     d[i * 4 + 3] = v_line[i >> 2];
544   }
545 }
546
547 static void
548 pack_Y41B (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
549     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
550     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
551     gint y, gint width)
552 {
553   int i;
554   guint8 *destY = GET_Y_LINE (y);
555   guint8 *destU = GET_U_LINE (y);
556   guint8 *destV = GET_V_LINE (y);
557   const guint8 *s = src;
558
559   for (i = 0; i < width - 3; i += 4) {
560     destY[i] = s[i * 4 + 1];
561     destY[i + 1] = s[i * 4 + 5];
562     destY[i + 2] = s[i * 4 + 9];
563     destY[i + 3] = s[i * 4 + 13];
564
565     destU[i >> 2] = s[i * 4 + 2];
566     destV[i >> 2] = s[i * 4 + 3];
567   }
568   if (i < width) {
569     destY[i] = s[i * 4 + 1];
570     destU[i >> 2] = s[i * 4 + 2];
571     destV[i >> 2] = s[i * 4 + 3];
572     if (i < width - 1)
573       destY[i + 1] = s[i * 4 + 5];
574     if (i < width - 2)
575       destY[i + 2] = s[i * 4 + 9];
576   }
577 }
578
579 #define PACK_Y42B GST_VIDEO_FORMAT_AYUV, unpack_Y42B, 1, pack_Y42B
580 static void
581 unpack_Y42B (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
582     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
583     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
584 {
585   guint8 *y_line = GET_Y_LINE (y);
586   guint8 *u_line = GET_U_LINE (y);
587   guint8 *v_line = GET_V_LINE (y);
588   guint8 *d = dest;
589
590   g_return_if_fail (IS_ALIGNED (dest, 8));
591
592   video_orc_unpack_Y42B (dest, y_line, u_line, v_line, width / 2);
593
594   if (width & 1) {
595     gint i = width - 1;
596
597     d[i * 4 + 0] = 0xff;
598     d[i * 4 + 1] = y_line[i];
599     d[i * 4 + 2] = u_line[i >> 1];
600     d[i * 4 + 3] = v_line[i >> 1];
601   }
602 }
603
604 static void
605 pack_Y42B (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
606     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
607     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
608     gint y, gint width)
609 {
610   guint8 *y_line = GET_Y_LINE (y);
611   guint8 *u_line = GET_U_LINE (y);
612   guint8 *v_line = GET_V_LINE (y);
613   const guint8 *ayuv = src;
614
615   g_return_if_fail (IS_ALIGNED (src, 8));
616
617   video_orc_pack_Y42B (y_line, u_line, v_line, src, width / 2);
618
619   if (width & 1) {
620     gint i = width - 1;
621
622     y_line[i] = ayuv[i * 4 + 1];
623     u_line[i >> 1] = ayuv[i * 4 + 2];
624     v_line[i >> 1] = ayuv[i * 4 + 3];
625   }
626 }
627
628 #define PACK_Y444 GST_VIDEO_FORMAT_AYUV, unpack_Y444, 1, pack_Y444
629 static void
630 unpack_Y444 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
631     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
632     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
633 {
634   video_orc_unpack_Y444 (dest, GET_Y_LINE (y), GET_U_LINE (y),
635       GET_V_LINE (y), width);
636 }
637
638 static void
639 pack_Y444 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
640     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
641     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
642     gint y, gint width)
643 {
644   video_orc_pack_Y444 (GET_Y_LINE (y), GET_U_LINE (y), GET_V_LINE (y), src,
645       width);
646 }
647
648 #define PACK_GBR GST_VIDEO_FORMAT_ARGB, unpack_GBR, 1, pack_GBR
649 static void
650 unpack_GBR (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
651     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
652     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
653 {
654   video_orc_unpack_Y444 (dest, GET_R_LINE (y), GET_G_LINE (y),
655       GET_B_LINE (y), width);
656 }
657
658 static void
659 pack_GBR (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
660     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
661     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
662     gint y, gint width)
663 {
664   video_orc_pack_Y444 (GET_R_LINE (y), GET_G_LINE (y), GET_B_LINE (y), src,
665       width);
666 }
667
668 #define PACK_GRAY8 GST_VIDEO_FORMAT_AYUV, unpack_GRAY8, 1, pack_GRAY8
669 static void
670 unpack_GRAY8 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
671     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
672     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
673 {
674   video_orc_unpack_GRAY8 (dest, GET_LINE (y), width);
675 }
676
677 static void
678 pack_GRAY8 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
679     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
680     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
681     gint y, gint width)
682 {
683   video_orc_pack_GRAY8 (GET_LINE (y), src, width);
684 }
685
686 #define PACK_GRAY16_BE GST_VIDEO_FORMAT_AYUV64, unpack_GRAY16_BE, 1, pack_GRAY16_BE
687 static void
688 unpack_GRAY16_BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
689     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
690     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
691 {
692   int i;
693   const guint16 *s = GET_LINE (y);
694   guint16 *d = dest;
695
696   for (i = 0; i < width; i++) {
697     d[i * 4 + 0] = 0xffff;
698     d[i * 4 + 1] = GST_READ_UINT16_BE (s + i);
699     d[i * 4 + 2] = 0x8000;
700     d[i * 4 + 3] = 0x8000;
701   }
702 }
703
704 static void
705 pack_GRAY16_BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
706     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
707     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
708     gint y, gint width)
709 {
710   int i;
711   guint16 *d = GET_LINE (y);
712   const guint16 *s = src;
713
714   for (i = 0; i < width; i++) {
715     GST_WRITE_UINT16_BE (d + i, s[i * 4 + 1]);
716   }
717 }
718
719 #define PACK_GRAY16_LE GST_VIDEO_FORMAT_AYUV64, unpack_GRAY16_LE, 1, pack_GRAY16_LE
720 static void
721 unpack_GRAY16_LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
722     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
723     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
724 {
725   int i;
726   const guint16 *s = GET_LINE (y);
727   guint16 *d = dest;
728
729   for (i = 0; i < width; i++) {
730     d[i * 4 + 0] = 0xffff;
731     d[i * 4 + 1] = GST_READ_UINT16_LE (s + i);
732     d[i * 4 + 2] = 0x8000;
733     d[i * 4 + 3] = 0x8000;
734   }
735 }
736
737 static void
738 pack_GRAY16_LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
739     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
740     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
741     gint y, gint width)
742 {
743   int i;
744   guint16 *d = GET_LINE (y);
745   const guint16 *s = src;
746
747   for (i = 0; i < width; i++) {
748     GST_WRITE_UINT16_LE (d + i, s[i * 4 + 1]);
749   }
750 }
751
752 #define PACK_RGB16 GST_VIDEO_FORMAT_ARGB, unpack_RGB16, 1, pack_RGB16
753 static void
754 unpack_RGB16 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
755     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
756     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
757 {
758   int i;
759   const guint16 *s = GET_LINE (y);
760   guint8 *d = dest, r, g, b;
761
762   for (i = 0; i < width; i++) {
763     r = ((s[i] >> 11) & 0x1f) << 3;
764     g = ((s[i] >> 5) & 0x3f) << 2;
765     b = ((s[i]) & 0x1f) << 3;
766
767     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
768       r |= (r >> 5);
769       g |= (g >> 6);
770       b |= (b >> 5);
771     }
772
773     d[i * 4 + 0] = 0xff;
774     d[i * 4 + 1] = r;
775     d[i * 4 + 2] = g;
776     d[i * 4 + 3] = b;
777   }
778 }
779
780 static void
781 pack_RGB16 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
782     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
783     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
784     gint y, gint width)
785 {
786   int i;
787   guint16 *d = GET_LINE (y);
788   const guint8 *s = src;
789
790   for (i = 0; i < width; i++) {
791     d[i] = ((s[i * 4 + 1] >> 3) << 11) |
792         ((s[i * 4 + 2] >> 2) << 5) | (s[i * 4 + 3] >> 3);
793   }
794 }
795
796 #define PACK_BGR16 GST_VIDEO_FORMAT_ARGB, unpack_BGR16, 1, pack_BGR16
797 static void
798 unpack_BGR16 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
799     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
800     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
801 {
802   int i;
803   const guint16 *s = GET_LINE (y);
804   guint8 *d = dest, r, g, b;
805
806   for (i = 0; i < width; i++) {
807     b = ((s[i] >> 11) & 0x1f) << 3;
808     g = ((s[i] >> 5) & 0x3f) << 2;
809     r = ((s[i]) & 0x1f) << 3;
810
811     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
812       r |= (r >> 5);
813       g |= (g >> 6);
814       b |= (b >> 5);
815     }
816
817     d[i * 4 + 0] = 0xff;
818     d[i * 4 + 1] = r;
819     d[i * 4 + 2] = g;
820     d[i * 4 + 3] = b;
821   }
822 }
823
824 static void
825 pack_BGR16 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
826     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
827     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
828     gint y, gint width)
829 {
830   int i;
831   guint16 *d = GET_LINE (y);
832   const guint8 *s = src;
833
834   for (i = 0; i < width; i++) {
835     d[i] = ((s[i * 4 + 3] >> 3) << 11) |
836         ((s[i * 4 + 2] >> 2) << 5) | (s[i * 4 + 1] >> 3);
837   }
838 }
839
840 #define PACK_RGB15 GST_VIDEO_FORMAT_ARGB, unpack_RGB15, 1, pack_RGB15
841 static void
842 unpack_RGB15 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
843     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
844     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
845 {
846   int i;
847   const guint16 *s = GET_LINE (y);
848   guint8 *d = dest, r, g, b;
849
850   for (i = 0; i < width; i++) {
851     r = ((s[i] >> 10) & 0x1f) << 3;
852     g = ((s[i] >> 5) & 0x1f) << 3;
853     b = ((s[i]) & 0x1f) << 3;
854
855     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
856       r |= (r >> 5);
857       g |= (g >> 5);
858       b |= (b >> 5);
859     }
860
861     d[i * 4 + 0] = 0xff;
862     d[i * 4 + 1] = r;
863     d[i * 4 + 2] = g;
864     d[i * 4 + 3] = b;
865   }
866 }
867
868 static void
869 pack_RGB15 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
870     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
871     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
872     gint y, gint width)
873 {
874   int i;
875   guint16 *d = GET_LINE (y);
876   const guint8 *s = src;
877
878   for (i = 0; i < width; i++) {
879     d[i] = ((s[i * 4 + 1] >> 3) << 10) |
880         ((s[i * 4 + 2] >> 3) << 5) | (s[i * 4 + 3] >> 3);
881   }
882 }
883
884 #define PACK_BGR15 GST_VIDEO_FORMAT_ARGB, unpack_BGR15, 1, pack_BGR15
885 static void
886 unpack_BGR15 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
887     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
888     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
889 {
890   int i;
891   const guint16 *s = GET_LINE (y);
892   guint8 *d = dest, r, g, b;
893
894   for (i = 0; i < width; i++) {
895     b = ((s[i] >> 10) & 0x1f) << 3;
896     g = ((s[i] >> 5) & 0x1f) << 3;
897     r = ((s[i]) & 0x1f) << 3;
898
899     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
900       r |= (r >> 5);
901       g |= (g >> 5);
902       b |= (b >> 5);
903     }
904
905     d[i * 4 + 0] = 0xff;
906     d[i * 4 + 1] = r;
907     d[i * 4 + 2] = g;
908     d[i * 4 + 3] = b;
909   }
910 }
911
912 static void
913 pack_BGR15 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
914     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
915     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
916     gint y, gint width)
917 {
918   int i;
919   guint16 *d = GET_LINE (y);
920   const guint8 *s = src;
921
922   for (i = 0; i < width; i++) {
923     d[i] = ((s[i * 4 + 3] >> 3) << 10) |
924         ((s[i * 4 + 2] >> 3) << 5) | (s[i * 4 + 1] >> 3);
925   }
926 }
927
928 #define PACK_BGRA GST_VIDEO_FORMAT_ARGB, unpack_BGRA, 1, pack_BGRA
929 static void
930 unpack_BGRA (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
931     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
932     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
933 {
934   video_orc_unpack_BGRA (dest, GET_LINE (y), width);
935 }
936
937 static void
938 pack_BGRA (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
939     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
940     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
941     gint y, gint width)
942 {
943   video_orc_pack_BGRA (GET_LINE (y), src, width);
944 }
945
946 #define PACK_ABGR GST_VIDEO_FORMAT_ARGB, unpack_ABGR, 1, pack_ABGR
947 static void
948 unpack_ABGR (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
949     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
950     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
951 {
952   video_orc_unpack_ABGR (dest, GET_LINE (y), width);
953 }
954
955 static void
956 pack_ABGR (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
957     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
958     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
959     gint y, gint width)
960 {
961   video_orc_pack_ABGR (GET_LINE (y), src, width);
962 }
963
964 #define PACK_RGBA GST_VIDEO_FORMAT_ARGB, unpack_RGBA, 1, pack_RGBA
965 static void
966 unpack_RGBA (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
967     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
968     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
969 {
970   video_orc_unpack_RGBA (dest, GET_LINE (y), width);
971 }
972
973 static void
974 pack_RGBA (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
975     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
976     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
977     gint y, gint width)
978 {
979   video_orc_pack_RGBA (GET_LINE (y), src, width);
980 }
981
982 #define PACK_RGB GST_VIDEO_FORMAT_ARGB, unpack_RGB, 1, pack_RGB
983 static void
984 unpack_RGB (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
985     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
986     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
987 {
988   int i;
989   const guint8 *s = GET_LINE (y);
990   guint8 *d = dest;
991
992   for (i = 0; i < width; i++) {
993     d[i * 4 + 0] = 0xff;
994     d[i * 4 + 1] = s[i * 3 + 0];
995     d[i * 4 + 2] = s[i * 3 + 1];
996     d[i * 4 + 3] = s[i * 3 + 2];
997   }
998 }
999
1000 static void
1001 pack_RGB (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1002     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1003     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1004     gint y, gint width)
1005 {
1006   int i;
1007   guint8 *d = GET_LINE (y);
1008   const guint8 *s = src;
1009
1010   for (i = 0; i < width; i++) {
1011     d[i * 3 + 0] = s[i * 4 + 1];
1012     d[i * 3 + 1] = s[i * 4 + 2];
1013     d[i * 3 + 2] = s[i * 4 + 3];
1014   }
1015 }
1016
1017 #define PACK_BGR GST_VIDEO_FORMAT_ARGB, unpack_BGR, 1, pack_BGR
1018 static void
1019 unpack_BGR (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1020     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1021     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1022 {
1023   int i;
1024   const guint8 *s = GET_LINE (y);
1025   guint8 *d = dest;
1026
1027   for (i = 0; i < width; i++) {
1028     d[i * 4 + 0] = 0xff;
1029     d[i * 4 + 1] = s[i * 3 + 2];
1030     d[i * 4 + 2] = s[i * 3 + 1];
1031     d[i * 4 + 3] = s[i * 3 + 0];
1032   }
1033 }
1034
1035 static void
1036 pack_BGR (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1037     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1038     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1039     gint y, gint width)
1040 {
1041   int i;
1042   guint8 *d = GET_LINE (y);
1043   const guint8 *s = src;
1044
1045   for (i = 0; i < width; i++) {
1046     d[i * 3 + 0] = s[i * 4 + 3];
1047     d[i * 3 + 1] = s[i * 4 + 2];
1048     d[i * 3 + 2] = s[i * 4 + 1];
1049   }
1050 }
1051
1052 #define PACK_NV12 GST_VIDEO_FORMAT_AYUV, unpack_NV12, 1, pack_NV12
1053 static void
1054 unpack_NV12 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1055     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1056     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1057 {
1058   gint uv = GET_UV_420 (y, flags);
1059   guint8 *y_line = GET_PLANE_LINE (0, y);
1060   guint8 *uv_line = GET_PLANE_LINE (1, uv);
1061   guint8 *d = dest;
1062
1063   g_return_if_fail (IS_ALIGNED (dest, 8));
1064
1065   video_orc_unpack_NV12 (dest, y_line, uv_line, width / 2);
1066
1067   if (width & 1) {
1068     gint i = width - 1;
1069
1070     d[i * 4 + 0] = 0xff;
1071     d[i * 4 + 1] = y_line[i];
1072     d[i * 4 + 2] = uv_line[i + 0];
1073     d[i * 4 + 3] = uv_line[i + 1];
1074   }
1075 }
1076
1077 static void
1078 pack_NV12 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1079     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1080     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1081     gint y, gint width)
1082 {
1083   gint uv = GET_UV_420 (y, flags);
1084   guint8 *y_line = GET_PLANE_LINE (0, y);
1085   guint8 *uv_line = GET_PLANE_LINE (1, uv);
1086   const guint8 *ayuv = src;
1087
1088   g_return_if_fail (IS_ALIGNED (src, 8));
1089
1090   video_orc_pack_NV12 (y_line, uv_line, src, width / 2);
1091
1092   if (width & 1) {
1093     gint i = width - 1;
1094
1095     y_line[i] = ayuv[i * 4 + 1];
1096     uv_line[i + 0] = ayuv[i * 4 + 2];
1097     uv_line[i + 1] = ayuv[i * 4 + 3];
1098   }
1099 }
1100
1101 #define PACK_NV21 GST_VIDEO_FORMAT_AYUV, unpack_NV21, 1, pack_NV21
1102 static void
1103 unpack_NV21 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1104     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1105     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1106 {
1107   gint uv = GET_UV_420 (y, flags);
1108   guint8 *y_line = GET_PLANE_LINE (0, y);
1109   guint8 *uv_line = GET_PLANE_LINE (1, uv);
1110   guint8 *d = dest;
1111
1112   g_return_if_fail (IS_ALIGNED (dest, 8));
1113
1114   video_orc_unpack_NV21 (dest, y_line, uv_line, width / 2);
1115
1116   if (width & 1) {
1117     gint i = width - 1;
1118
1119     d[i * 4 + 0] = 0xff;
1120     d[i * 4 + 1] = y_line[i];
1121     d[i * 4 + 2] = uv_line[i + 1];
1122     d[i * 4 + 3] = uv_line[i + 0];
1123   }
1124 }
1125
1126 static void
1127 pack_NV21 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1128     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1129     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1130     gint y, gint width)
1131 {
1132   gint uv = GET_UV_420 (y, flags);
1133   guint8 *y_line = GET_PLANE_LINE (0, y);
1134   guint8 *uv_line = GET_PLANE_LINE (1, uv);
1135   const guint8 *ayuv = src;
1136
1137   g_return_if_fail (IS_ALIGNED (src, 8));
1138
1139   video_orc_pack_NV21 (y_line, uv_line, src, width / 2);
1140
1141   if (width & 1) {
1142     gint i = width - 1;
1143
1144     y_line[i] = ayuv[i * 4 + 1];
1145     uv_line[i + 0] = ayuv[i * 4 + 3];
1146     uv_line[i + 1] = ayuv[i * 4 + 2];
1147   }
1148 }
1149
1150 #define PACK_NV16 GST_VIDEO_FORMAT_AYUV, unpack_NV16, 1, pack_NV16
1151 static void
1152 unpack_NV16 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1153     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1154     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1155 {
1156   guint8 *y_line = GET_PLANE_LINE (0, y);
1157   guint8 *uv_line = GET_PLANE_LINE (1, y);
1158   guint8 *d = dest;
1159
1160   g_return_if_fail (IS_ALIGNED (dest, 8));
1161
1162   video_orc_unpack_NV12 (dest, y_line, uv_line, width / 2);
1163
1164   if (width & 1) {
1165     gint i = width - 1;
1166
1167     d[i * 4 + 0] = 0xff;
1168     d[i * 4 + 1] = y_line[i];
1169     d[i * 4 + 2] = uv_line[i + 0];
1170     d[i * 4 + 3] = uv_line[i + 1];
1171   }
1172 }
1173
1174 static void
1175 pack_NV16 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1176     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1177     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1178     gint y, gint width)
1179 {
1180   guint8 *y_line = GET_PLANE_LINE (0, y);
1181   guint8 *uv_line = GET_PLANE_LINE (1, y);
1182   const guint8 *ayuv = src;
1183
1184   g_return_if_fail (IS_ALIGNED (src, 8));
1185
1186   video_orc_pack_NV12 (y_line, uv_line, src, width / 2);
1187
1188   if (width & 1) {
1189     gint i = width - 1;
1190
1191     y_line[i] = ayuv[i * 4 + 1];
1192     uv_line[i + 0] = ayuv[i * 4 + 2];
1193     uv_line[i + 1] = ayuv[i * 4 + 3];
1194   }
1195 }
1196
1197 #define PACK_NV24 GST_VIDEO_FORMAT_AYUV, unpack_NV24, 1, pack_NV24
1198 static void
1199 unpack_NV24 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1200     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1201     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1202 {
1203   video_orc_unpack_NV24 (dest,
1204       GET_PLANE_LINE (0, y), GET_PLANE_LINE (1, y), width);
1205 }
1206
1207 static void
1208 pack_NV24 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1209     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1210     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1211     gint y, gint width)
1212 {
1213   video_orc_pack_NV24 (GET_PLANE_LINE (0, y),
1214       GET_PLANE_LINE (1, y), src, width);
1215 }
1216
1217 #define PACK_UYVP GST_VIDEO_FORMAT_AYUV64, unpack_UYVP, 1, pack_UYVP
1218 static void
1219 unpack_UYVP (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1220     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1221     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1222 {
1223   int i;
1224   const guint8 *s = GET_LINE (y);
1225   guint16 *d = dest;
1226
1227   for (i = 0; i < width; i += 2) {
1228     guint16 y0, y1;
1229     guint16 u0;
1230     guint16 v0;
1231
1232     u0 = ((s[(i / 2) * 5 + 0] << 2) | (s[(i / 2) * 5 + 1] >> 6)) << 6;
1233     y0 = (((s[(i / 2) * 5 + 1] & 0x3f) << 4) | (s[(i / 2) * 5 + 2] >> 4)) << 6;
1234     v0 = (((s[(i / 2) * 5 + 2] & 0x0f) << 6) | (s[(i / 2) * 5 + 3] >> 2)) << 6;
1235     y1 = (((s[(i / 2) * 5 + 3] & 0x03) << 8) | s[(i / 2) * 5 + 4]) << 6;
1236
1237     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
1238       y0 |= (y0 >> 10);
1239       y1 |= (y1 >> 10);
1240       u0 |= (u0 >> 10);
1241       v0 |= (v0 >> 10);
1242     }
1243
1244     d[i * 4 + 0] = 0xffff;
1245     d[i * 4 + 1] = y0;
1246     d[i * 4 + 2] = u0;
1247     d[i * 4 + 3] = v0;
1248
1249     if (i < width - 1) {
1250       d[i * 4 + 4] = 0xffff;
1251       d[i * 4 + 5] = y1;
1252       d[i * 4 + 6] = u0;
1253       d[i * 4 + 7] = v0;
1254     }
1255   }
1256 }
1257
1258 static void
1259 pack_UYVP (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1260     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1261     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1262     gint y, gint width)
1263 {
1264   int i;
1265   guint8 *d = GET_LINE (y);
1266   const guint16 *s = src;
1267
1268   for (i = 0; i < width; i += 2) {
1269     guint16 y0, y1;
1270     guint16 u0;
1271     guint16 v0;
1272
1273     y0 = s[4 * (i + 0) + 1];
1274     if (i < width - 1)
1275       y1 = s[4 * (i + 1) + 1];
1276     else
1277       y1 = y0;
1278
1279     u0 = s[4 * (i + 0) + 2];
1280     v0 = s[4 * (i + 0) + 3];
1281
1282     d[(i / 2) * 5 + 0] = u0 >> 8;
1283     d[(i / 2) * 5 + 1] = (u0 & 0xc0) | y0 >> 10;
1284     d[(i / 2) * 5 + 2] = ((y0 & 0x3c0) >> 2) | (v0 >> 12);
1285     d[(i / 2) * 5 + 3] = ((v0 & 0xfc0) >> 4) | (y1 >> 14);
1286     d[(i / 2) * 5 + 4] = (y1 >> 6);
1287   }
1288 }
1289
1290 #define PACK_A420 GST_VIDEO_FORMAT_AYUV, unpack_A420, 1, pack_A420
1291 static void
1292 unpack_A420 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1293     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1294     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1295 {
1296   gint uv = GET_UV_420 (y, flags);
1297
1298   video_orc_unpack_A420 (dest, GET_Y_LINE (y), GET_U_LINE (uv),
1299       GET_V_LINE (uv), GET_A_LINE (y), width);
1300 }
1301
1302 static void
1303 pack_A420 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1304     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1305     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1306     gint y, gint width)
1307 {
1308   gint uv = GET_UV_420 (y, flags);
1309   guint8 *y_line = GET_Y_LINE (y);
1310   guint8 *u_line = GET_U_LINE (uv);
1311   guint8 *v_line = GET_V_LINE (uv);
1312   guint8 *a_line = GET_A_LINE (y);
1313   const guint8 *ayuv = src;
1314
1315   g_return_if_fail (IS_ALIGNED (src, 8));
1316
1317   video_orc_pack_A420 (y_line, u_line, v_line, a_line, src, width / 2);
1318
1319   if (width & 1) {
1320     gint i = width - 1;
1321
1322     a_line[i] = ayuv[i * 4 + 0];
1323     y_line[i] = ayuv[i * 4 + 1];
1324     u_line[i >> 1] = ayuv[i * 4 + 2];
1325     v_line[i >> 1] = ayuv[i * 4 + 3];
1326   }
1327 }
1328
1329 #define PACK_RGB8P GST_VIDEO_FORMAT_ARGB, unpack_RGB8P, 1, pack_RGB8P
1330 static void
1331 unpack_RGB8P (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1332     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1333     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1334 {
1335   int i;
1336   const guint8 *s = GET_LINE (y);
1337   const guint32 *p = data[1];
1338   guint8 *d = dest;
1339
1340   for (i = 0; i < width; i++) {
1341     guint32 v = p[s[i]];
1342     d[i * 4 + 0] = (v >> 24) & 0xff;
1343     d[i * 4 + 1] = (v >> 16) & 0xff;
1344     d[i * 4 + 2] = (v >> 8) & 0xff;
1345     d[i * 4 + 3] = (v) & 0xff;
1346   }
1347 }
1348
1349 static const guint32 std_palette_RGB8P[] = {
1350   0xff000000, 0xff000033, 0xff000066, 0xff000099, 0xff0000cc, 0xff0000ff,
1351   0xff003300, 0xff003333, 0xff003366, 0xff003399, 0xff0033cc, 0xff0033ff,
1352   0xff006600, 0xff006633, 0xff006666, 0xff006699, 0xff0066cc, 0xff0066ff,
1353   0xff009900, 0xff009933, 0xff009966, 0xff009999, 0xff0099cc, 0xff0099ff,
1354   0xff00cc00, 0xff00cc33, 0xff00cc66, 0xff00cc99, 0xff00cccc, 0xff00ccff,
1355   0xff00ff00, 0xff00ff33, 0xff00ff66, 0xff00ff99, 0xff00ffcc, 0xff00ffff,
1356   0xff330000, 0xff330033, 0xff330066, 0xff330099, 0xff3300cc, 0xff3300ff,
1357   0xff333300, 0xff333333, 0xff333366, 0xff333399, 0xff3333cc, 0xff3333ff,
1358   0xff336600, 0xff336633, 0xff336666, 0xff336699, 0xff3366cc, 0xff3366ff,
1359   0xff339900, 0xff339933, 0xff339966, 0xff339999, 0xff3399cc, 0xff3399ff,
1360   0xff33cc00, 0xff33cc33, 0xff33cc66, 0xff33cc99, 0xff33cccc, 0xff33ccff,
1361   0xff33ff00, 0xff33ff33, 0xff33ff66, 0xff33ff99, 0xff33ffcc, 0xff33ffff,
1362   0xff660000, 0xff660033, 0xff660066, 0xff660099, 0xff6600cc, 0xff6600ff,
1363   0xff663300, 0xff663333, 0xff663366, 0xff663399, 0xff6633cc, 0xff6633ff,
1364   0xff666600, 0xff666633, 0xff666666, 0xff666699, 0xff6666cc, 0xff6666ff,
1365   0xff669900, 0xff669933, 0xff669966, 0xff669999, 0xff6699cc, 0xff6699ff,
1366   0xff66cc00, 0xff66cc33, 0xff66cc66, 0xff66cc99, 0xff66cccc, 0xff66ccff,
1367   0xff66ff00, 0xff66ff33, 0xff66ff66, 0xff66ff99, 0xff66ffcc, 0xff66ffff,
1368   0xff990000, 0xff990033, 0xff990066, 0xff990099, 0xff9900cc, 0xff9900ff,
1369   0xff993300, 0xff993333, 0xff993366, 0xff993399, 0xff9933cc, 0xff9933ff,
1370   0xff996600, 0xff996633, 0xff996666, 0xff996699, 0xff9966cc, 0xff9966ff,
1371   0xff999900, 0xff999933, 0xff999966, 0xff999999, 0xff9999cc, 0xff9999ff,
1372   0xff99cc00, 0xff99cc33, 0xff99cc66, 0xff99cc99, 0xff99cccc, 0xff99ccff,
1373   0xff99ff00, 0xff99ff33, 0xff99ff66, 0xff99ff99, 0xff99ffcc, 0xff99ffff,
1374   0xffcc0000, 0xffcc0033, 0xffcc0066, 0xffcc0099, 0xffcc00cc, 0xffcc00ff,
1375   0xffcc3300, 0xffcc3333, 0xffcc3366, 0xffcc3399, 0xffcc33cc, 0xffcc33ff,
1376   0xffcc6600, 0xffcc6633, 0xffcc6666, 0xffcc6699, 0xffcc66cc, 0xffcc66ff,
1377   0xffcc9900, 0xffcc9933, 0xffcc9966, 0xffcc9999, 0xffcc99cc, 0xffcc99ff,
1378   0xffcccc00, 0xffcccc33, 0xffcccc66, 0xffcccc99, 0xffcccccc, 0xffccccff,
1379   0xffccff00, 0xffccff33, 0xffccff66, 0xffccff99, 0xffccffcc, 0xffccffff,
1380   0xffff0000, 0xffff0033, 0xffff0066, 0xffff0099, 0xffff00cc, 0xffff00ff,
1381   0xffff3300, 0xffff3333, 0xffff3366, 0xffff3399, 0xffff33cc, 0xffff33ff,
1382   0xffff6600, 0xffff6633, 0xffff6666, 0xffff6699, 0xffff66cc, 0xffff66ff,
1383   0xffff9900, 0xffff9933, 0xffff9966, 0xffff9999, 0xffff99cc, 0xffff99ff,
1384   0xffffcc00, 0xffffcc33, 0xffffcc66, 0xffffcc99, 0xffffcccc, 0xffffccff,
1385   0xffffff00, 0xffffff33, 0xffffff66, 0xffffff99, 0xffffffcc, 0xffffffff,
1386   0x00000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
1387   0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
1388   0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
1389   0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
1390   0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
1391   0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
1392   0xff000000, 0xff000000, 0xff000000, 0xff000000
1393 };
1394
1395 static void
1396 pack_RGB8P (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1397     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1398     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1399     gint y, gint width)
1400 {
1401   int i;
1402   guint8 *d = GET_LINE (y);
1403   const guint8 *s = src;
1404
1405   /* Use our poor man's palette, taken from ffmpegcolorspace too */
1406   for (i = 0; i < width; i++) {
1407     /* crude approximation for alpha ! */
1408     if (s[i * 4 + 0] < 0x80)
1409       d[i] = 6 * 6 * 6;
1410     else
1411       d[i] =
1412           ((((s[i * 4 + 1]) / 47) % 6) * 6 * 6 + (((s[i * 4 +
1413                           2]) / 47) % 6) * 6 + (((s[i * 4 + 3]) / 47) % 6));
1414   }
1415 }
1416
1417 #define PACK_410 GST_VIDEO_FORMAT_AYUV, unpack_410, 1, pack_410
1418 static void
1419 unpack_410 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1420     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1421     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1422 {
1423   gint uv = GET_UV_410 (y, flags);
1424   guint8 *y_line = GET_Y_LINE (y);
1425   guint8 *u_line = GET_U_LINE (uv);
1426   guint8 *v_line = GET_V_LINE (uv);
1427   guint8 *d = dest;
1428
1429   g_return_if_fail (IS_ALIGNED (dest, 8));
1430
1431   video_orc_unpack_YUV9 (dest, y_line, u_line, v_line, width / 2);
1432
1433   if (width & 1) {
1434     gint i = width - 1;
1435
1436     d[i * 4 + 0] = 0xff;
1437     d[i * 4 + 1] = y_line[i];
1438     d[i * 4 + 2] = u_line[i >> 2];
1439     d[i * 4 + 3] = v_line[i >> 2];
1440   }
1441 }
1442
1443 static void
1444 pack_410 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1445     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1446     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1447     gint y, gint width)
1448 {
1449   int i;
1450   gint uv = GET_UV_410 (y, flags);
1451   guint8 *destY = GET_Y_LINE (y);
1452   guint8 *destU = GET_U_LINE (uv);
1453   guint8 *destV = GET_V_LINE (uv);
1454   const guint8 *s = src;
1455
1456   for (i = 0; i < width - 3; i += 4) {
1457     destY[i] = s[i * 4 + 1];
1458     destY[i + 1] = s[i * 4 + 5];
1459     destY[i + 2] = s[i * 4 + 9];
1460     destY[i + 3] = s[i * 4 + 13];
1461     if (y % 4 == 0) {
1462       destU[i >> 2] = s[i * 4 + 2];
1463       destV[i >> 2] = s[i * 4 + 3];
1464     }
1465   }
1466   if (i < width) {
1467     destY[i] = s[i * 4 + 1];
1468     if (y % 4 == 0) {
1469       destU[i >> 2] = s[i * 4 + 2];
1470       destV[i >> 2] = s[i * 4 + 3];
1471     }
1472     if (i < width - 1)
1473       destY[i + 1] = s[i * 4 + 5];
1474     if (i < width - 2)
1475       destY[i + 2] = s[i * 4 + 9];
1476   }
1477 }
1478
1479 #define PACK_IYU1 GST_VIDEO_FORMAT_AYUV, unpack_IYU1, 1, pack_IYU1
1480 static void
1481 unpack_IYU1 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1482     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1483     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1484 {
1485   int i;
1486   const guint8 *s = GET_LINE (y);
1487   guint8 *d = dest;
1488   guint8 y0, y1, y2, y3;
1489   guint8 u0;
1490   guint8 v0;
1491
1492   for (i = 0; i < width - 3; i += 4) {
1493     y0 = s[(i >> 2) * 6 + 1];
1494     y1 = s[(i >> 2) * 6 + 2];
1495     y2 = s[(i >> 2) * 6 + 4];
1496     y3 = s[(i >> 2) * 6 + 5];
1497
1498     u0 = s[(i >> 2) * 6 + 0];
1499     v0 = s[(i >> 2) * 6 + 3];
1500
1501     d[i * 4 + 0] = 0xff;
1502     d[i * 4 + 1] = y0;
1503     d[i * 4 + 2] = u0;
1504     d[i * 4 + 3] = v0;
1505
1506     d[i * 4 + 4] = 0xff;
1507     d[i * 4 + 5] = y1;
1508     d[i * 4 + 6] = u0;
1509     d[i * 4 + 7] = v0;
1510
1511     d[i * 4 + 8] = 0xff;
1512     d[i * 4 + 9] = y2;
1513     d[i * 4 + 10] = u0;
1514     d[i * 4 + 11] = v0;
1515
1516     d[i * 4 + 12] = 0xff;
1517     d[i * 4 + 13] = y3;
1518     d[i * 4 + 14] = u0;
1519     d[i * 4 + 15] = v0;
1520   }
1521   if (i < width) {
1522     u0 = s[(i >> 2) * 6 + 0];
1523     v0 = s[(i >> 2) * 6 + 3];
1524
1525     d[i * 4 + 0] = 0xff;
1526     d[i * 4 + 1] = s[(i >> 2) * 6 + 1];
1527     d[i * 4 + 2] = u0;
1528     d[i * 4 + 3] = v0;
1529
1530     if (i < width - 1) {
1531       d[i * 4 + 4] = 0xff;
1532       d[i * 4 + 5] = s[(i >> 2) * 6 + 2];
1533       d[i * 4 + 6] = u0;
1534       d[i * 4 + 7] = v0;
1535     }
1536     if (i < width - 2) {
1537       d[i * 4 + 8] = 0xff;
1538       d[i * 4 + 9] = s[(i >> 2) * 6 + 4];
1539       d[i * 4 + 10] = u0;
1540       d[i * 4 + 11] = v0;
1541     }
1542   }
1543 }
1544
1545 static void
1546 pack_IYU1 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1547     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1548     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1549     gint y, gint width)
1550 {
1551   int i;
1552   guint8 *d = GET_LINE (y);
1553   const guint8 *s = src;
1554
1555   for (i = 0; i < width - 3; i += 4) {
1556     d[(i >> 2) * 6 + 0] = s[i * 4 + 2];
1557     d[(i >> 2) * 6 + 1] = s[i * 4 + 1];
1558     d[(i >> 2) * 6 + 2] = s[i * 4 + 5];
1559     d[(i >> 2) * 6 + 3] = s[i * 4 + 3];
1560     d[(i >> 2) * 6 + 4] = s[i * 4 + 9];
1561     d[(i >> 2) * 6 + 5] = s[i * 4 + 13];
1562   }
1563   if (i < width) {
1564     d[(i >> 2) * 6 + 1] = s[i * 4 + 1];
1565     d[(i >> 2) * 6 + 0] = s[i * 4 + 2];
1566     d[(i >> 2) * 6 + 3] = s[i * 4 + 3];
1567     if (i < width - 1)
1568       d[(i >> 2) * 6 + 2] = s[i * 4 + 5];
1569     if (i < width - 2)
1570       d[(i >> 2) * 6 + 4] = s[i * 4 + 9];
1571   }
1572 }
1573
1574 #define PACK_ARGB64 GST_VIDEO_FORMAT_ARGB64, unpack_copy8, 1, pack_copy8
1575 #define PACK_AYUV64 GST_VIDEO_FORMAT_AYUV64, unpack_copy8, 1, pack_copy8
1576 static void
1577 unpack_copy8 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1578     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1579     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1580 {
1581   memcpy (dest, GET_LINE (y), width * 8);
1582 }
1583
1584 static void
1585 pack_copy8 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1586     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1587     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1588     gint y, gint width)
1589 {
1590   memcpy (GET_LINE (y), src, width * 8);
1591 }
1592
1593 #define PACK_r210 GST_VIDEO_FORMAT_ARGB64, unpack_r210, 1, pack_r210
1594 static void
1595 unpack_r210 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1596     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1597     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1598 {
1599   int i;
1600   const guint8 *s = GET_LINE (y);
1601   guint16 *d = dest, R, G, B;
1602
1603   for (i = 0; i < width; i++) {
1604     guint32 x = GST_READ_UINT32_BE (s + i * 4);
1605
1606     R = ((x >> 14) & 0xffc0);
1607     G = ((x >> 4) & 0xffc0);
1608     B = ((x << 6) & 0xffc0);
1609
1610     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
1611       R |= (R >> 10);
1612       G |= (G >> 10);
1613       B |= (B >> 10);
1614     }
1615
1616     d[i * 4 + 0] = 0xffff;
1617     d[i * 4 + 1] = R;
1618     d[i * 4 + 2] = G;
1619     d[i * 4 + 3] = B;
1620   }
1621 }
1622
1623 static void
1624 pack_r210 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1625     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1626     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1627     gint y, gint width)
1628 {
1629   int i;
1630   guint8 *d = GET_LINE (y);
1631   const guint16 *s = src;
1632
1633   for (i = 0; i < width; i++) {
1634     guint32 x = 0;
1635     x |= (s[i * 4 + 1] & 0xffc0) << 14;
1636     x |= (s[i * 4 + 2] & 0xffc0) << 4;
1637     x |= (s[i * 4 + 3] & 0xffc0) >> 6;
1638     GST_WRITE_UINT32_BE (d + i * 4, x);
1639   }
1640 }
1641
1642 #define PACK_GBR_10LE GST_VIDEO_FORMAT_ARGB64, unpack_GBR_10LE, 1, pack_GBR_10LE
1643 static void
1644 unpack_GBR_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1645     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1646     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1647 {
1648   int i;
1649   guint16 *srcG = GET_G_LINE (y);
1650   guint16 *srcB = GET_B_LINE (y);
1651   guint16 *srcR = GET_R_LINE (y);
1652   guint16 *d = dest, G, B, R;
1653
1654   for (i = 0; i < width; i++) {
1655     G = GST_READ_UINT16_LE (srcG + i) << 6;
1656     B = GST_READ_UINT16_LE (srcB + i) << 6;
1657     R = GST_READ_UINT16_LE (srcR + i) << 6;
1658
1659     d[i * 4 + 0] = 0xffff;
1660     d[i * 4 + 1] = R;
1661     d[i * 4 + 2] = G;
1662     d[i * 4 + 3] = B;
1663   }
1664 }
1665
1666 static void
1667 pack_GBR_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1668     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1669     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1670     gint y, gint width)
1671 {
1672   int i;
1673   guint16 *destG = GET_G_LINE (y);
1674   guint16 *destB = GET_B_LINE (y);
1675   guint16 *destR = GET_R_LINE (y);
1676   guint16 G, B, R;
1677   const guint16 *s = src;
1678
1679   for (i = 0; i < width; i++) {
1680     G = (s[i * 4 + 2]) >> 6;
1681     B = (s[i * 4 + 3]) >> 6;
1682     R = (s[i * 4 + 1]) >> 6;
1683
1684     GST_WRITE_UINT16_LE (destG + i, G);
1685     GST_WRITE_UINT16_LE (destB + i, B);
1686     GST_WRITE_UINT16_LE (destR + i, R);
1687   }
1688 }
1689
1690 #define PACK_GBR_10BE GST_VIDEO_FORMAT_ARGB64, unpack_GBR_10BE, 1, pack_GBR_10BE
1691 static void
1692 unpack_GBR_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1693     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1694     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1695 {
1696   int i;
1697   guint16 *srcG = GET_G_LINE (y);
1698   guint16 *srcB = GET_B_LINE (y);
1699   guint16 *srcR = GET_R_LINE (y);
1700   guint16 *d = dest, G, B, R;
1701
1702   for (i = 0; i < width; i++) {
1703     G = GST_READ_UINT16_BE (srcG + i) << 6;
1704     B = GST_READ_UINT16_BE (srcB + i) << 6;
1705     R = GST_READ_UINT16_BE (srcR + i) << 6;
1706
1707     d[i * 4 + 0] = 0xffff;
1708     d[i * 4 + 1] = R;
1709     d[i * 4 + 2] = G;
1710     d[i * 4 + 3] = B;
1711   }
1712 }
1713
1714 static void
1715 pack_GBR_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1716     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1717     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1718     gint y, gint width)
1719 {
1720   int i;
1721   guint16 *destG = GET_G_LINE (y);
1722   guint16 *destB = GET_B_LINE (y);
1723   guint16 *destR = GET_R_LINE (y);
1724   guint16 G, B, R;
1725   const guint16 *s = src;
1726
1727   for (i = 0; i < width; i++) {
1728     G = s[i * 4 + 2] >> 6;
1729     B = s[i * 4 + 3] >> 6;
1730     R = s[i * 4 + 1] >> 6;
1731
1732     GST_WRITE_UINT16_BE (destG + i, G);
1733     GST_WRITE_UINT16_BE (destB + i, B);
1734     GST_WRITE_UINT16_BE (destR + i, R);
1735   }
1736 }
1737
1738 #define PACK_Y444_10LE GST_VIDEO_FORMAT_AYUV64, unpack_Y444_10LE, 1, pack_Y444_10LE
1739 static void
1740 unpack_Y444_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1741     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1742     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1743 {
1744   int i;
1745   guint16 *srcY = GET_Y_LINE (y);
1746   guint16 *srcU = GET_U_LINE (y);
1747   guint16 *srcV = GET_V_LINE (y);
1748   guint16 *d = dest, Y, U, V;
1749
1750   for (i = 0; i < width; i++) {
1751     Y = GST_READ_UINT16_LE (srcY + i) << 6;
1752     U = GST_READ_UINT16_LE (srcU + i) << 6;
1753     V = GST_READ_UINT16_LE (srcV + i) << 6;
1754
1755     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
1756       Y |= (Y >> 10);
1757       U |= (U >> 10);
1758       V |= (V >> 10);
1759     }
1760
1761     d[i * 4 + 0] = 0xffff;
1762     d[i * 4 + 1] = Y;
1763     d[i * 4 + 2] = U;
1764     d[i * 4 + 3] = V;
1765   }
1766 }
1767
1768 static void
1769 pack_Y444_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1770     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1771     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1772     gint y, gint width)
1773 {
1774   int i;
1775   guint16 *destY = GET_Y_LINE (y);
1776   guint16 *destU = GET_U_LINE (y);
1777   guint16 *destV = GET_V_LINE (y);
1778   guint16 Y, U, V;
1779   const guint16 *s = src;
1780
1781   for (i = 0; i < width; i++) {
1782     Y = (s[i * 4 + 1]) >> 6;
1783     U = (s[i * 4 + 2]) >> 6;
1784     V = (s[i * 4 + 3]) >> 6;
1785
1786     GST_WRITE_UINT16_LE (destY + i, Y);
1787     GST_WRITE_UINT16_LE (destU + i, U);
1788     GST_WRITE_UINT16_LE (destV + i, V);
1789   }
1790 }
1791
1792 #define PACK_Y444_10BE GST_VIDEO_FORMAT_AYUV64, unpack_Y444_10BE, 1, pack_Y444_10BE
1793 static void
1794 unpack_Y444_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1795     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1796     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1797 {
1798   int i;
1799   guint16 *srcY = GET_Y_LINE (y);
1800   guint16 *srcU = GET_U_LINE (y);
1801   guint16 *srcV = GET_V_LINE (y);
1802   guint16 *d = dest, Y, U, V;
1803
1804   for (i = 0; i < width; i++) {
1805     Y = GST_READ_UINT16_BE (srcY + i) << 6;
1806     U = GST_READ_UINT16_BE (srcU + i) << 6;
1807     V = GST_READ_UINT16_BE (srcV + i) << 6;
1808
1809     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
1810       Y |= (Y >> 10);
1811       U |= (U >> 10);
1812       V |= (V >> 10);
1813     }
1814
1815     d[i * 4 + 0] = 0xffff;
1816     d[i * 4 + 1] = Y;
1817     d[i * 4 + 2] = U;
1818     d[i * 4 + 3] = V;
1819   }
1820 }
1821
1822 static void
1823 pack_Y444_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1824     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1825     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1826     gint y, gint width)
1827 {
1828   int i;
1829   guint16 *destY = GET_Y_LINE (y);
1830   guint16 *destU = GET_U_LINE (y);
1831   guint16 *destV = GET_V_LINE (y);
1832   guint16 Y, U, V;
1833   const guint16 *s = src;
1834
1835   for (i = 0; i < width; i++) {
1836     Y = s[i * 4 + 1] >> 6;
1837     U = s[i * 4 + 2] >> 6;
1838     V = s[i * 4 + 3] >> 6;
1839
1840     GST_WRITE_UINT16_BE (destY + i, Y);
1841     GST_WRITE_UINT16_BE (destU + i, U);
1842     GST_WRITE_UINT16_BE (destV + i, V);
1843   }
1844 }
1845
1846 #define PACK_I420_10LE GST_VIDEO_FORMAT_AYUV64, unpack_I420_10LE, 1, pack_I420_10LE
1847 static void
1848 unpack_I420_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1849     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1850     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1851 {
1852   int i;
1853   gint uv = GET_UV_420 (y, flags);
1854   guint16 *srcY = GET_Y_LINE (y);
1855   guint16 *srcU = GET_U_LINE (uv);
1856   guint16 *srcV = GET_V_LINE (uv);
1857   guint16 *d = dest, Y, U, V;
1858
1859   for (i = 0; i < width; i++) {
1860     Y = GST_READ_UINT16_LE (srcY + i) << 6;
1861     U = GST_READ_UINT16_LE (srcU + (i >> 1)) << 6;
1862     V = GST_READ_UINT16_LE (srcV + (i >> 1)) << 6;
1863
1864     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
1865       Y |= (Y >> 10);
1866       U |= (U >> 10);
1867       V |= (V >> 10);
1868     }
1869
1870     d[i * 4 + 0] = 0xffff;
1871     d[i * 4 + 1] = Y;
1872     d[i * 4 + 2] = U;
1873     d[i * 4 + 3] = V;
1874   }
1875 }
1876
1877 static void
1878 pack_I420_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1879     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1880     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1881     gint y, gint width)
1882 {
1883   int i;
1884   gint uv = GET_UV_420 (y, flags);
1885   guint16 *destY = GET_Y_LINE (y);
1886   guint16 *destU = GET_U_LINE (uv);
1887   guint16 *destV = GET_V_LINE (uv);
1888   guint16 Y0, Y1, U, V;
1889   const guint16 *s = src;
1890
1891   for (i = 0; i < width - 1; i += 2) {
1892     Y0 = s[i * 4 + 1] >> 6;
1893     Y1 = s[i * 4 + 5] >> 6;
1894     U = s[i * 4 + 2] >> 6;
1895     V = s[i * 4 + 3] >> 6;
1896
1897     GST_WRITE_UINT16_LE (destY + i + 0, Y0);
1898     GST_WRITE_UINT16_LE (destY + i + 1, Y1);
1899     GST_WRITE_UINT16_LE (destU + (i >> 1), U);
1900     GST_WRITE_UINT16_LE (destV + (i >> 1), V);
1901   }
1902   if (i == width - 1) {
1903     Y0 = s[i * 4 + 1] >> 6;
1904     U = s[i * 4 + 2] >> 6;
1905     V = s[i * 4 + 3] >> 6;
1906
1907     GST_WRITE_UINT16_LE (destY + i, Y0);
1908     GST_WRITE_UINT16_LE (destU + (i >> 1), U);
1909     GST_WRITE_UINT16_LE (destV + (i >> 1), V);
1910   }
1911 }
1912
1913 #define PACK_I420_10BE GST_VIDEO_FORMAT_AYUV64, unpack_I420_10BE, 1, pack_I420_10BE
1914 static void
1915 unpack_I420_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1916     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1917     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1918 {
1919   int i;
1920   gint uv = GET_UV_420 (y, flags);
1921   guint16 *srcY = GET_Y_LINE (y);
1922   guint16 *srcU = GET_U_LINE (uv);
1923   guint16 *srcV = GET_V_LINE (uv);
1924   guint16 *d = dest, Y, U, V;
1925
1926   for (i = 0; i < width; i++) {
1927     Y = GST_READ_UINT16_BE (srcY + i) << 6;
1928     U = GST_READ_UINT16_BE (srcU + (i >> 1)) << 6;
1929     V = GST_READ_UINT16_BE (srcV + (i >> 1)) << 6;
1930
1931     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
1932       Y |= (Y >> 10);
1933       U |= (U >> 10);
1934       V |= (V >> 10);
1935     }
1936
1937     d[i * 4 + 0] = 0xffff;
1938     d[i * 4 + 1] = Y;
1939     d[i * 4 + 2] = U;
1940     d[i * 4 + 3] = V;
1941   }
1942 }
1943
1944 static void
1945 pack_I420_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1946     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1947     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1948     gint y, gint width)
1949 {
1950   int i;
1951   gint uv = GET_UV_420 (y, flags);
1952   guint16 *destY = GET_Y_LINE (y);
1953   guint16 *destU = GET_U_LINE (uv);
1954   guint16 *destV = GET_V_LINE (uv);
1955   guint16 Y0, Y1, U, V;
1956   const guint16 *s = src;
1957
1958   for (i = 0; i < width - 1; i += 2) {
1959     Y0 = s[i * 4 + 1] >> 6;
1960     Y1 = s[i * 4 + 5] >> 6;
1961     U = s[i * 4 + 2] >> 6;
1962     V = s[i * 4 + 3] >> 6;
1963
1964     GST_WRITE_UINT16_BE (destY + i + 0, Y0);
1965     GST_WRITE_UINT16_BE (destY + i + 1, Y1);
1966     GST_WRITE_UINT16_BE (destU + (i >> 1), U);
1967     GST_WRITE_UINT16_BE (destV + (i >> 1), V);
1968   }
1969   if (i == width - 1) {
1970     Y0 = s[i * 4 + 1] >> 6;
1971     U = s[i * 4 + 2] >> 6;
1972     V = s[i * 4 + 3] >> 6;
1973
1974     GST_WRITE_UINT16_BE (destY + i, Y0);
1975     GST_WRITE_UINT16_BE (destU + (i >> 1), U);
1976     GST_WRITE_UINT16_BE (destV + (i >> 1), V);
1977   }
1978 }
1979
1980 #define PACK_I422_10LE GST_VIDEO_FORMAT_AYUV64, unpack_I422_10LE, 1, pack_I422_10LE
1981 static void
1982 unpack_I422_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1983     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1984     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1985 {
1986   int i;
1987   guint16 *srcY = GET_Y_LINE (y);
1988   guint16 *srcU = GET_U_LINE (y);
1989   guint16 *srcV = GET_V_LINE (y);
1990   guint16 *d = dest, Y, U, V;
1991
1992   for (i = 0; i < width; i++) {
1993     Y = GST_READ_UINT16_LE (srcY + i) << 6;
1994     U = GST_READ_UINT16_LE (srcU + (i >> 1)) << 6;
1995     V = GST_READ_UINT16_LE (srcV + (i >> 1)) << 6;
1996
1997     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
1998       Y |= (Y >> 10);
1999       U |= (U >> 10);
2000       V |= (V >> 10);
2001     }
2002
2003     d[i * 4 + 0] = 0xffff;
2004     d[i * 4 + 1] = Y;
2005     d[i * 4 + 2] = U;
2006     d[i * 4 + 3] = V;
2007   }
2008 }
2009
2010 static void
2011 pack_I422_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2012     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
2013     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
2014     gint y, gint width)
2015 {
2016   int i;
2017   guint16 *destY = GET_Y_LINE (y);
2018   guint16 *destU = GET_U_LINE (y);
2019   guint16 *destV = GET_V_LINE (y);
2020   guint16 Y0, Y1, U, V;
2021   const guint16 *s = src;
2022
2023   for (i = 0; i < width - 1; i += 2) {
2024     Y0 = s[i * 4 + 1] >> 6;
2025     Y1 = s[i * 4 + 5] >> 6;
2026     U = s[i * 4 + 2] >> 6;
2027     V = s[i * 4 + 3] >> 6;
2028
2029     GST_WRITE_UINT16_LE (destY + i + 0, Y0);
2030     GST_WRITE_UINT16_LE (destY + i + 1, Y1);
2031     GST_WRITE_UINT16_LE (destU + (i >> 1), U);
2032     GST_WRITE_UINT16_LE (destV + (i >> 1), V);
2033   }
2034   if (i == width - 1) {
2035     Y0 = s[i * 4 + 1] >> 6;
2036     U = s[i * 4 + 2] >> 6;
2037     V = s[i * 4 + 3] >> 6;
2038
2039     GST_WRITE_UINT16_LE (destY + i, Y0);
2040     GST_WRITE_UINT16_LE (destU + (i >> 1), U);
2041     GST_WRITE_UINT16_LE (destV + (i >> 1), V);
2042   }
2043 }
2044
2045 #define PACK_I422_10BE GST_VIDEO_FORMAT_AYUV64, unpack_I422_10BE, 1, pack_I422_10BE
2046 static void
2047 unpack_I422_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2048     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
2049     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
2050 {
2051   int i;
2052   guint16 *srcY = GET_Y_LINE (y);
2053   guint16 *srcU = GET_U_LINE (y);
2054   guint16 *srcV = GET_V_LINE (y);
2055   guint16 *d = dest, Y, U, V;
2056
2057   for (i = 0; i < width; i++) {
2058     Y = GST_READ_UINT16_BE (srcY + i) << 6;
2059     U = GST_READ_UINT16_BE (srcU + (i >> 1)) << 6;
2060     V = GST_READ_UINT16_BE (srcV + (i >> 1)) << 6;
2061
2062     if (!(flags & GST_VIDEO_PACK_FLAG_TRUNCATE_RANGE)) {
2063       Y |= (Y >> 10);
2064       U |= (U >> 10);
2065       V |= (V >> 10);
2066     }
2067
2068     d[i * 4 + 0] = 0xffff;
2069     d[i * 4 + 1] = Y;
2070     d[i * 4 + 2] = U;
2071     d[i * 4 + 3] = V;
2072   }
2073 }
2074
2075 static void
2076 pack_I422_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2077     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
2078     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
2079     gint y, gint width)
2080 {
2081   int i;
2082   guint16 *destY = GET_Y_LINE (y);
2083   guint16 *destU = GET_U_LINE (y);
2084   guint16 *destV = GET_V_LINE (y);
2085   guint16 Y0, Y1, U, V;
2086   const guint16 *s = src;
2087
2088   for (i = 0; i < width - 1; i += 2) {
2089     Y0 = s[i * 4 + 1] >> 6;
2090     Y1 = s[i * 4 + 5] >> 6;
2091     U = s[i * 4 + 2] >> 6;
2092     V = s[i * 4 + 3] >> 6;
2093
2094     GST_WRITE_UINT16_BE (destY + i + 0, Y0);
2095     GST_WRITE_UINT16_BE (destY + i + 1, Y1);
2096     GST_WRITE_UINT16_BE (destU + (i >> 1), U);
2097     GST_WRITE_UINT16_BE (destV + (i >> 1), V);
2098   }
2099   if (i == width - 1) {
2100     Y0 = s[i * 4 + 1] >> 6;
2101     U = s[i * 4 + 2] >> 6;
2102     V = s[i * 4 + 3] >> 6;
2103
2104     GST_WRITE_UINT16_BE (destY + i, Y0);
2105     GST_WRITE_UINT16_BE (destU + (i >> 1), U);
2106     GST_WRITE_UINT16_BE (destV + (i >> 1), V);
2107   }
2108 }
2109
2110 static void
2111 get_tile_NV12 (gint tile_width, gint ts, gint tx, gint ty,
2112     const gpointer data[GST_VIDEO_MAX_PLANES],
2113     const gint stride[GST_VIDEO_MAX_PLANES],
2114     gpointer tile_data[GST_VIDEO_MAX_PLANES],
2115     gint tile_stride[GST_VIDEO_MAX_PLANES])
2116 {
2117   gsize offset;
2118
2119   /* index of Y tile */
2120   offset = gst_video_tile_get_index (GST_VIDEO_TILE_MODE_ZFLIPZ_2X2,
2121       tx, ty, GST_VIDEO_TILE_X_TILES (stride[0]),
2122       GST_VIDEO_TILE_Y_TILES (stride[0]));
2123   offset <<= ts;
2124   tile_data[0] = ((guint8 *) data[0]) + offset;
2125
2126   /* index of UV tile */
2127   offset = gst_video_tile_get_index (GST_VIDEO_TILE_MODE_ZFLIPZ_2X2,
2128       tx, ty >> 1, GST_VIDEO_TILE_X_TILES (stride[1]),
2129       GST_VIDEO_TILE_Y_TILES (stride[1]));
2130   offset <<= ts;
2131   /* On odd rows we return the second part of the UV tile */
2132   offset |= (ty & 1) << (ts - 1);
2133   tile_data[1] = ((guint8 *) data[1]) + offset;
2134
2135   tile_stride[0] = tile_stride[1] = tile_width;
2136 }
2137
2138 #define PACK_NV12_64Z32 GST_VIDEO_FORMAT_AYUV, unpack_NV12_64Z32, 1, pack_NV12_64Z32
2139 static void
2140 unpack_NV12_64Z32 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2141     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
2142     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
2143 {
2144   const GstVideoFormatInfo *unpack_info, *finfo;
2145   guint8 *line = dest;
2146   gint ws, hs, ts, tile_width;
2147   gint ntx, tx, ty;
2148   gint unpack_pstride;
2149
2150   ws = GST_VIDEO_FORMAT_INFO_TILE_WS (info);
2151   hs = GST_VIDEO_FORMAT_INFO_TILE_HS (info);
2152   ts = ws + hs;
2153
2154   tile_width = 1 << ws;
2155
2156   /* we reuse these unpack functions */
2157   finfo = gst_video_format_get_info (GST_VIDEO_FORMAT_NV12);
2158
2159   /* get pstride of unpacked format */
2160   unpack_info = gst_video_format_get_info (info->unpack_format);
2161   unpack_pstride = GST_VIDEO_FORMAT_INFO_PSTRIDE (unpack_info, 0);
2162
2163   /* first x tile to convert */
2164   tx = x >> ws;
2165   /* Last tile to convert */
2166   ntx = ((x + width - 1) >> ws) + 1;
2167   /* The row we are going to convert */
2168   ty = y >> hs;
2169
2170   /* y position in a tile */
2171   y = y & ((1 << hs) - 1);
2172   /* x position in a tile */
2173   x = x & (tile_width - 1);
2174
2175   for (; tx < ntx; tx++) {
2176     gpointer tdata[GST_VIDEO_MAX_PLANES];
2177     gint tstride[GST_VIDEO_MAX_PLANES];
2178     gint unpack_width;
2179
2180     get_tile_NV12 (tile_width, ts, tx, ty, data, stride, tdata, tstride);
2181
2182     /* the number of bytes left to unpack */
2183     unpack_width = MIN (width - x, tile_width - x);
2184
2185     finfo->unpack_func (finfo, flags, line, tdata, tstride, x, y, unpack_width);
2186
2187     x = 0;
2188     width -= unpack_width;
2189     line += unpack_width * unpack_pstride;
2190   }
2191 }
2192
2193 static void
2194 pack_NV12_64Z32 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
2195     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
2196     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
2197     gint y, gint width)
2198 {
2199   const GstVideoFormatInfo *pack_info, *finfo;
2200   guint8 *line = src;
2201   gint ws, hs, ts, tile_width;
2202   gint ntx, tx, ty;
2203   gint pack_pstride;
2204
2205   ws = GST_VIDEO_FORMAT_INFO_TILE_WS (info);
2206   hs = GST_VIDEO_FORMAT_INFO_TILE_HS (info);
2207   ts = ws + hs;
2208
2209   tile_width = 1 << ws;
2210
2211   /* we reuse these pack functions */
2212   finfo = gst_video_format_get_info (GST_VIDEO_FORMAT_NV12);
2213
2214   /* get pstride of packed format */
2215   pack_info = gst_video_format_get_info (info->unpack_format);
2216   pack_pstride = GST_VIDEO_FORMAT_INFO_PSTRIDE (pack_info, 0);
2217
2218   /* Last tile to convert */
2219   ntx = ((width - 1) >> ws) + 1;
2220   /* The row we are going to convert */
2221   ty = y >> hs;
2222
2223   /* y position in a tile */
2224   y = y & ((1 << hs) - 1);
2225
2226   for (tx = 0; tx < ntx; tx++) {
2227     gpointer tdata[GST_VIDEO_MAX_PLANES];
2228     gint tstride[GST_VIDEO_MAX_PLANES];
2229     gint pack_width;
2230
2231     get_tile_NV12 (tile_width, ts, tx, ty, data, stride, tdata, tstride);
2232
2233     /* the number of bytes left to pack */
2234     pack_width = MIN (width, tile_width);
2235
2236     finfo->pack_func (finfo, flags, line, sstride, tdata, tstride,
2237         chroma_site, y, pack_width);
2238
2239     width -= pack_width;
2240     line += pack_width * pack_pstride;
2241   }
2242 }
2243
2244 typedef struct
2245 {
2246   guint32 fourcc;
2247   GstVideoFormatInfo info;
2248 } VideoFormat;
2249
2250 /* depths: bits, n_components, shift, depth */
2251 #define DPTH0            0, 0, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
2252 #define DPTH8            8, 1, { 0, 0, 0, 0 }, { 8, 0, 0, 0 }
2253 #define DPTH8_32         8, 2, { 0, 0, 0, 0 }, { 8, 32, 0, 0 }
2254 #define DPTH888          8, 3, { 0, 0, 0, 0 }, { 8, 8, 8, 0 }
2255 #define DPTH8888         8, 4, { 0, 0, 0, 0 }, { 8, 8, 8, 8 }
2256 #define DPTH8880         8, 4, { 0, 0, 0, 0 }, { 8, 8, 8, 0 }
2257 #define DPTH10_10_10     10, 3, { 0, 0, 0, 0 }, { 10, 10, 10, 0 }
2258 #define DPTH16           16, 1, { 0, 0, 0, 0 }, { 16, 0, 0, 0 }
2259 #define DPTH16_16_16     16, 3, { 0, 0, 0, 0 }, { 16, 16, 16, 0 }
2260 #define DPTH16_16_16_16  16, 4, { 0, 0, 0, 0 }, { 16, 16, 16, 16 }
2261 #define DPTH555          16, 3, { 10, 5, 0, 0 }, { 5, 5, 5, 0 }
2262 #define DPTH565          16, 3, { 11, 5, 0, 0 }, { 5, 6, 5, 0 }
2263
2264 /* pixel strides */
2265 #define PSTR0             { 0, 0, 0, 0 }
2266 #define PSTR1             { 1, 0, 0, 0 }
2267 #define PSTR14            { 1, 4, 0, 0 }
2268 #define PSTR111           { 1, 1, 1, 0 }
2269 #define PSTR1111          { 1, 1, 1, 1 }
2270 #define PSTR122           { 1, 2, 2, 0 }
2271 #define PSTR2             { 2, 0, 0, 0 }
2272 #define PSTR222           { 2, 2, 2, 0 }
2273 #define PSTR244           { 2, 4, 4, 0 }
2274 #define PSTR444           { 4, 4, 4, 0 }
2275 #define PSTR4444          { 4, 4, 4, 4 }
2276 #define PSTR333           { 3, 3, 3, 0 }
2277 #define PSTR488           { 4, 8, 8, 0 }
2278 #define PSTR8888          { 8, 8, 8, 8 }
2279
2280 /* planes, in what plane do we find component N */
2281 #define PLANE_NA          0, { 0, 0, 0, 0 }
2282 #define PLANE0            1, { 0, 0, 0, 0 }
2283 #define PLANE01           2, { 0, 1, 0, 0 }
2284 #define PLANE011          2, { 0, 1, 1, 0 }
2285 #define PLANE012          3, { 0, 1, 2, 0 }
2286 #define PLANE0123         4, { 0, 1, 2, 3 }
2287 #define PLANE021          3, { 0, 2, 1, 0 }
2288 #define PLANE201          3, { 2, 0, 1, 0 }
2289
2290 /* offsets */
2291 #define OFFS0             { 0, 0, 0, 0 }
2292 #define OFFS013           { 0, 1, 3, 0 }
2293 #define OFFS102           { 1, 0, 2, 0 }
2294 #define OFFS1230          { 1, 2, 3, 0 }
2295 #define OFFS012           { 0, 1, 2, 0 }
2296 #define OFFS210           { 2, 1, 0, 0 }
2297 #define OFFS123           { 1, 2, 3, 0 }
2298 #define OFFS321           { 3, 2, 1, 0 }
2299 #define OFFS0123          { 0, 1, 2, 3 }
2300 #define OFFS2103          { 2, 1, 0, 3 }
2301 #define OFFS3210          { 3, 2, 1, 0 }
2302 #define OFFS031           { 0, 3, 1, 0 }
2303 #define OFFS204           { 2, 0, 4, 0 }
2304 #define OFFS001           { 0, 0, 1, 0 }
2305 #define OFFS010           { 0, 1, 0, 0 }
2306 #define OFFS104           { 1, 0, 4, 0 }
2307 #define OFFS2460          { 2, 4, 6, 0 }
2308
2309 /* subsampling, w_sub, h_sub */
2310 #define SUB410            { 0, 2, 2, 0 }, { 0, 2, 2, 0 }
2311 #define SUB411            { 0, 2, 2, 0 }, { 0, 0, 0, 0 }
2312 #define SUB420            { 0, 1, 1, 0 }, { 0, 1, 1, 0 }
2313 #define SUB422            { 0, 1, 1, 0 }, { 0, 0, 0, 0 }
2314 #define SUB4              { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
2315 #define SUB44             { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
2316 #define SUB444            { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
2317 #define SUB4444           { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
2318 #define SUB4204           { 0, 1, 1, 0 }, { 0, 1, 1, 0 }
2319
2320 /* tile_mode, tile_width, tile_height */
2321 #define TILE_64x32(mode) GST_VIDEO_TILE_MODE_ ##mode, 6, 5
2322
2323 #define MAKE_YUV_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub, pack ) \
2324  { fourcc, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_YUV, depth, pstride, plane, offs, sub, pack } }
2325 #define MAKE_YUV_LE_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub, pack ) \
2326  { 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 } }
2327 #define MAKE_YUVA_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub, pack) \
2328  { 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 } }
2329 #define MAKE_YUVA_PACK_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub, pack) \
2330  { 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 } }
2331 #define MAKE_YUVA_LE_PACK_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub, pack) \
2332  { 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 } }
2333 #define MAKE_YUV_C_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub, pack) \
2334  { 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 } }
2335 #define MAKE_YUV_T_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub, pack, tile) \
2336  { 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 } }
2337
2338 #define MAKE_RGB_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
2339  { 0x00000000, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_RGB, depth, pstride, plane, offs, sub, pack } }
2340 #define MAKE_RGB_LE_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
2341  { 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 } }
2342 #define MAKE_RGBA_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
2343  { 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 } }
2344 #define MAKE_RGBAP_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
2345  { 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 } }
2346 #define MAKE_RGBA_PACK_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
2347  { 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 } }
2348 #define MAKE_RGBA_LE_PACK_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
2349  { 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 } }
2350
2351 #define MAKE_GRAY_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
2352  { 0x00000000, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_GRAY, depth, pstride, plane, offs, sub, pack } }
2353 #define MAKE_GRAY_LE_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
2354  { 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 } }
2355
2356 static VideoFormat formats[] = {
2357   {0x00000000, {GST_VIDEO_FORMAT_UNKNOWN, "UNKNOWN", "unknown video", 0, DPTH0,
2358           PSTR0, PLANE_NA, OFFS0}},
2359   {0x00000000, {GST_VIDEO_FORMAT_ENCODED, "ENCODED", "encoded video",
2360           GST_VIDEO_FORMAT_FLAG_COMPLEX, DPTH0, PSTR0, PLANE_NA, OFFS0}},
2361
2362   MAKE_YUV_FORMAT (I420, "raw video", GST_MAKE_FOURCC ('I', '4', '2', '0'),
2363       DPTH888, PSTR111, PLANE012, OFFS0, SUB420, PACK_420),
2364   MAKE_YUV_FORMAT (YV12, "raw video", GST_MAKE_FOURCC ('Y', 'V', '1', '2'),
2365       DPTH888, PSTR111, PLANE021, OFFS0, SUB420, PACK_420),
2366   MAKE_YUV_FORMAT (YUY2, "raw video", GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'),
2367       DPTH888, PSTR244, PLANE0, OFFS013, SUB422, PACK_YUY2),
2368   MAKE_YUV_FORMAT (UYVY, "raw video", GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'),
2369       DPTH888, PSTR244, PLANE0, OFFS102, SUB422, PACK_UYVY),
2370   MAKE_YUVA_PACK_FORMAT (AYUV, "raw video", GST_MAKE_FOURCC ('A', 'Y', 'U',
2371           'V'), DPTH8888, PSTR4444, PLANE0, OFFS1230, SUB4444, PACK_AYUV),
2372   MAKE_RGB_FORMAT (RGBx, "raw video", DPTH888, PSTR444, PLANE0, OFFS012,
2373       SUB444, PACK_RGBA),
2374   MAKE_RGB_FORMAT (BGRx, "raw video", DPTH888, PSTR444, PLANE0, OFFS210,
2375       SUB444, PACK_BGRA),
2376   MAKE_RGB_FORMAT (xRGB, "raw video", DPTH888, PSTR444, PLANE0, OFFS123,
2377       SUB444, PACK_ARGB),
2378   MAKE_RGB_FORMAT (xBGR, "raw video", DPTH888, PSTR444, PLANE0, OFFS321,
2379       SUB444, PACK_ABGR),
2380   MAKE_RGBA_FORMAT (RGBA, "raw video", DPTH8888, PSTR4444, PLANE0, OFFS0123,
2381       SUB4444, PACK_RGBA),
2382   MAKE_RGBA_FORMAT (BGRA, "raw video", DPTH8888, PSTR4444, PLANE0, OFFS2103,
2383       SUB4444, PACK_BGRA),
2384   MAKE_RGBA_PACK_FORMAT (ARGB, "raw video", DPTH8888, PSTR4444, PLANE0,
2385       OFFS1230, SUB4444, PACK_ARGB),
2386   MAKE_RGBA_FORMAT (ABGR, "raw video", DPTH8888, PSTR4444, PLANE0, OFFS3210,
2387       SUB4444, PACK_ABGR),
2388   MAKE_RGB_FORMAT (RGB, "raw video", DPTH888, PSTR333, PLANE0, OFFS012, SUB444,
2389       PACK_RGB),
2390   MAKE_RGB_FORMAT (BGR, "raw video", DPTH888, PSTR333, PLANE0, OFFS210, SUB444,
2391       PACK_BGR),
2392
2393   MAKE_YUV_FORMAT (Y41B, "raw video", GST_MAKE_FOURCC ('Y', '4', '1', 'B'),
2394       DPTH888, PSTR111, PLANE012, OFFS0, SUB411, PACK_Y41B),
2395   MAKE_YUV_FORMAT (Y42B, "raw video", GST_MAKE_FOURCC ('Y', '4', '2', 'B'),
2396       DPTH888, PSTR111, PLANE012, OFFS0, SUB422, PACK_Y42B),
2397   MAKE_YUV_FORMAT (YVYU, "raw video", GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'),
2398       DPTH888, PSTR244, PLANE0, OFFS031, SUB422, PACK_YVYU),
2399   MAKE_YUV_FORMAT (Y444, "raw video", GST_MAKE_FOURCC ('Y', '4', '4', '4'),
2400       DPTH888, PSTR111, PLANE012, OFFS0, SUB444, PACK_Y444),
2401   MAKE_YUV_C_FORMAT (v210, "raw video", GST_MAKE_FOURCC ('v', '2', '1', '0'),
2402       DPTH10_10_10, PSTR0, PLANE0, OFFS0, SUB422, PACK_v210),
2403   MAKE_YUV_FORMAT (v216, "raw video", GST_MAKE_FOURCC ('v', '2', '1', '6'),
2404       DPTH16_16_16, PSTR488, PLANE0, OFFS204, SUB422, PACK_v216),
2405   MAKE_YUV_FORMAT (NV12, "raw video", GST_MAKE_FOURCC ('N', 'V', '1', '2'),
2406       DPTH888, PSTR122, PLANE011, OFFS001, SUB420, PACK_NV12),
2407   MAKE_YUV_FORMAT (NV21, "raw video", GST_MAKE_FOURCC ('N', 'V', '2', '1'),
2408       DPTH888, PSTR122, PLANE011, OFFS010, SUB420, PACK_NV21),
2409
2410   MAKE_GRAY_FORMAT (GRAY8, "raw video", DPTH8, PSTR1, PLANE0, OFFS0, SUB4,
2411       PACK_GRAY8),
2412   MAKE_GRAY_FORMAT (GRAY16_BE, "raw video", DPTH16, PSTR2, PLANE0, OFFS0, SUB4,
2413       PACK_GRAY16_BE),
2414   MAKE_GRAY_LE_FORMAT (GRAY16_LE, "raw video", DPTH16, PSTR2, PLANE0, OFFS0,
2415       SUB4, PACK_GRAY16_LE),
2416
2417   MAKE_YUV_FORMAT (v308, "raw video", GST_MAKE_FOURCC ('v', '3', '0', '8'),
2418       DPTH888, PSTR333, PLANE0, OFFS012, SUB444, PACK_v308),
2419
2420 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
2421   MAKE_RGB_LE_FORMAT (RGB16, "raw video", DPTH565, PSTR222, PLANE0, OFFS0,
2422       SUB444, PACK_RGB16),
2423   MAKE_RGB_LE_FORMAT (BGR16, "raw video", DPTH565, PSTR222, PLANE0, OFFS0,
2424       SUB444, PACK_BGR16),
2425   MAKE_RGB_LE_FORMAT (RGB15, "raw video", DPTH555, PSTR222, PLANE0, OFFS0,
2426       SUB444, PACK_RGB15),
2427   MAKE_RGB_LE_FORMAT (BGR15, "raw video", DPTH555, PSTR222, PLANE0, OFFS0,
2428       SUB444, PACK_BGR15),
2429 #else
2430   MAKE_RGB_FORMAT (RGB16, "raw video", DPTH565, PSTR222, PLANE0, OFFS0, SUB444,
2431       PACK_RGB16),
2432   MAKE_RGB_FORMAT (BGR16, "raw video", DPTH565, PSTR222, PLANE0, OFFS0, SUB444,
2433       PACK_BGR16),
2434   MAKE_RGB_FORMAT (RGB15, "raw video", DPTH555, PSTR222, PLANE0, OFFS0, SUB444,
2435       PACK_RGB15),
2436   MAKE_RGB_FORMAT (BGR15, "raw video", DPTH555, PSTR222, PLANE0, OFFS0, SUB444,
2437       PACK_BGR15),
2438 #endif
2439
2440   MAKE_YUV_C_FORMAT (UYVP, "raw video", GST_MAKE_FOURCC ('U', 'Y', 'V', 'P'),
2441       DPTH10_10_10, PSTR0, PLANE0, OFFS0, SUB422, PACK_UYVP),
2442   MAKE_YUVA_FORMAT (A420, "raw video", GST_MAKE_FOURCC ('A', '4', '2', '0'),
2443       DPTH8888, PSTR1111, PLANE0123, OFFS0, SUB4204, PACK_A420),
2444   MAKE_RGBAP_FORMAT (RGB8P, "raw video", DPTH8_32, PSTR14, PLANE01,
2445       OFFS0, SUB44, PACK_RGB8P),
2446   MAKE_YUV_FORMAT (YUV9, "raw video", GST_MAKE_FOURCC ('Y', 'U', 'V', '9'),
2447       DPTH888, PSTR111, PLANE012, OFFS0, SUB410, PACK_410),
2448   MAKE_YUV_FORMAT (YVU9, "raw video", GST_MAKE_FOURCC ('Y', 'V', 'U', '9'),
2449       DPTH888, PSTR111, PLANE021, OFFS0, SUB410, PACK_410),
2450   MAKE_YUV_FORMAT (IYU1, "raw video", GST_MAKE_FOURCC ('I', 'Y', 'U', '1'),
2451       DPTH888, PSTR0, PLANE0, OFFS104, SUB411, PACK_IYU1),
2452 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
2453   MAKE_RGBA_LE_PACK_FORMAT (ARGB64, "raw video", DPTH16_16_16_16, PSTR8888,
2454       PLANE0,
2455       OFFS2460, SUB444, PACK_ARGB64),
2456   MAKE_YUVA_LE_PACK_FORMAT (AYUV64, "raw video", 0x00000000, DPTH16_16_16_16,
2457       PSTR8888, PLANE0, OFFS2460, SUB444, PACK_AYUV64),
2458 #else
2459   MAKE_RGBA_PACK_FORMAT (ARGB64, "raw video", DPTH16_16_16_16, PSTR8888, PLANE0,
2460       OFFS2460, SUB444, PACK_ARGB64),
2461   MAKE_YUVA_PACK_FORMAT (AYUV64, "raw video", 0x00000000, DPTH16_16_16_16,
2462       PSTR8888, PLANE0, OFFS2460, SUB444, PACK_AYUV64),
2463 #endif
2464   MAKE_RGB_FORMAT (r210, "raw video", DPTH10_10_10, PSTR444, PLANE0, OFFS0,
2465       SUB444, PACK_r210),
2466   MAKE_YUV_FORMAT (I420_10BE, "raw video", 0x00000000, DPTH10_10_10,
2467       PSTR222, PLANE012, OFFS0, SUB420, PACK_I420_10BE),
2468   MAKE_YUV_LE_FORMAT (I420_10LE, "raw video", 0x00000000, DPTH10_10_10,
2469       PSTR222, PLANE012, OFFS0, SUB420, PACK_I420_10LE),
2470   MAKE_YUV_FORMAT (I422_10BE, "raw video", 0x00000000, DPTH10_10_10,
2471       PSTR222, PLANE012, OFFS0, SUB422, PACK_I422_10BE),
2472   MAKE_YUV_LE_FORMAT (I422_10LE, "raw video", 0x00000000, DPTH10_10_10,
2473       PSTR222, PLANE012, OFFS0, SUB422, PACK_I422_10LE),
2474   MAKE_YUV_FORMAT (Y444_10BE, "raw video", 0x00000000, DPTH10_10_10,
2475       PSTR222, PLANE012, OFFS0, SUB444, PACK_Y444_10BE),
2476   MAKE_YUV_LE_FORMAT (Y444_10LE, "raw video", 0x00000000, DPTH10_10_10,
2477       PSTR222, PLANE012, OFFS0, SUB444, PACK_Y444_10LE),
2478   MAKE_RGB_FORMAT (GBR, "raw video", DPTH888, PSTR111, PLANE201, OFFS0, SUB444,
2479       PACK_GBR),
2480   MAKE_RGB_FORMAT (GBR_10BE, "raw video", DPTH10_10_10, PSTR222, PLANE201,
2481       OFFS0, SUB444,
2482       PACK_GBR_10BE),
2483   MAKE_RGB_LE_FORMAT (GBR_10LE, "raw video", DPTH10_10_10, PSTR222, PLANE201,
2484       OFFS0, SUB444,
2485       PACK_GBR_10LE),
2486   MAKE_YUV_FORMAT (NV16, "raw video", GST_MAKE_FOURCC ('N', 'V', '1', '6'),
2487       DPTH888, PSTR111, PLANE011, OFFS001, SUB422, PACK_NV16),
2488   MAKE_YUV_FORMAT (NV24, "raw video", GST_MAKE_FOURCC ('N', 'V', '2', '4'),
2489       DPTH888, PSTR111, PLANE011, OFFS001, SUB444, PACK_NV24),
2490   MAKE_YUV_T_FORMAT (NV12_64Z32, "raw video",
2491       GST_MAKE_FOURCC ('T', 'M', '1', '2'), DPTH8880, PSTR122, PLANE011,
2492       OFFS001, SUB420, PACK_NV12_64Z32, TILE_64x32 (ZFLIPZ_2X2)),
2493 };
2494
2495 static GstVideoFormat
2496 gst_video_format_from_rgb32_masks (int red_mask, int green_mask, int blue_mask)
2497 {
2498   if (red_mask == 0xff000000 && green_mask == 0x00ff0000 &&
2499       blue_mask == 0x0000ff00) {
2500     return GST_VIDEO_FORMAT_RGBx;
2501   }
2502   if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 &&
2503       blue_mask == 0xff000000) {
2504     return GST_VIDEO_FORMAT_BGRx;
2505   }
2506   if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 &&
2507       blue_mask == 0x000000ff) {
2508     return GST_VIDEO_FORMAT_xRGB;
2509   }
2510   if (red_mask == 0x000000ff && green_mask == 0x0000ff00 &&
2511       blue_mask == 0x00ff0000) {
2512     return GST_VIDEO_FORMAT_xBGR;
2513   }
2514
2515   return GST_VIDEO_FORMAT_UNKNOWN;
2516 }
2517
2518 static GstVideoFormat
2519 gst_video_format_from_rgba32_masks (int red_mask, int green_mask,
2520     int blue_mask, int alpha_mask)
2521 {
2522   if (red_mask == 0xff000000 && green_mask == 0x00ff0000 &&
2523       blue_mask == 0x0000ff00 && alpha_mask == 0x000000ff) {
2524     return GST_VIDEO_FORMAT_RGBA;
2525   }
2526   if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 &&
2527       blue_mask == 0xff000000 && alpha_mask == 0x000000ff) {
2528     return GST_VIDEO_FORMAT_BGRA;
2529   }
2530   if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 &&
2531       blue_mask == 0x000000ff && alpha_mask == 0xff000000) {
2532     return GST_VIDEO_FORMAT_ARGB;
2533   }
2534   if (red_mask == 0x000000ff && green_mask == 0x0000ff00 &&
2535       blue_mask == 0x00ff0000 && alpha_mask == 0xff000000) {
2536     return GST_VIDEO_FORMAT_ABGR;
2537   }
2538   return GST_VIDEO_FORMAT_UNKNOWN;
2539 }
2540
2541 static GstVideoFormat
2542 gst_video_format_from_rgb24_masks (int red_mask, int green_mask, int blue_mask)
2543 {
2544   if (red_mask == 0xff0000 && green_mask == 0x00ff00 && blue_mask == 0x0000ff) {
2545     return GST_VIDEO_FORMAT_RGB;
2546   }
2547   if (red_mask == 0x0000ff && green_mask == 0x00ff00 && blue_mask == 0xff0000) {
2548     return GST_VIDEO_FORMAT_BGR;
2549   }
2550
2551   return GST_VIDEO_FORMAT_UNKNOWN;
2552 }
2553
2554 #define GST_VIDEO_COMP1_MASK_16_INT 0xf800
2555 #define GST_VIDEO_COMP2_MASK_16_INT 0x07e0
2556 #define GST_VIDEO_COMP3_MASK_16_INT 0x001f
2557
2558 #define GST_VIDEO_COMP1_MASK_15_INT 0x7c00
2559 #define GST_VIDEO_COMP2_MASK_15_INT 0x03e0
2560 #define GST_VIDEO_COMP3_MASK_15_INT 0x001f
2561
2562 static GstVideoFormat
2563 gst_video_format_from_rgb16_masks (int red_mask, int green_mask, int blue_mask)
2564 {
2565   if (red_mask == GST_VIDEO_COMP1_MASK_16_INT
2566       && green_mask == GST_VIDEO_COMP2_MASK_16_INT
2567       && blue_mask == GST_VIDEO_COMP3_MASK_16_INT) {
2568     return GST_VIDEO_FORMAT_RGB16;
2569   }
2570   if (red_mask == GST_VIDEO_COMP3_MASK_16_INT
2571       && green_mask == GST_VIDEO_COMP2_MASK_16_INT
2572       && blue_mask == GST_VIDEO_COMP1_MASK_16_INT) {
2573     return GST_VIDEO_FORMAT_BGR16;
2574   }
2575   if (red_mask == GST_VIDEO_COMP1_MASK_15_INT
2576       && green_mask == GST_VIDEO_COMP2_MASK_15_INT
2577       && blue_mask == GST_VIDEO_COMP3_MASK_15_INT) {
2578     return GST_VIDEO_FORMAT_RGB15;
2579   }
2580   if (red_mask == GST_VIDEO_COMP3_MASK_15_INT
2581       && green_mask == GST_VIDEO_COMP2_MASK_15_INT
2582       && blue_mask == GST_VIDEO_COMP1_MASK_15_INT) {
2583     return GST_VIDEO_FORMAT_BGR15;
2584   }
2585   return GST_VIDEO_FORMAT_UNKNOWN;
2586 }
2587
2588 /**
2589  * gst_video_format_from_masks:
2590  * @depth: the amount of bits used for a pixel
2591  * @bpp: the amount of bits used to store a pixel. This value is bigger than
2592  *   @depth
2593  * @endianness: the endianness of the masks, #G_LITTLE_ENDIAN or #G_BIG_ENDIAN
2594  * @red_mask: the red mask
2595  * @green_mask: the green mask
2596  * @blue_mask: the blue mask
2597  * @alpha_mask: the alpha mask, or 0 if no alpha mask
2598  *
2599  * Find the #GstVideoFormat for the given parameters.
2600  *
2601  * Returns: a #GstVideoFormat or GST_VIDEO_FORMAT_UNKNOWN when the parameters to
2602  * not specify a known format.
2603  */
2604 GstVideoFormat
2605 gst_video_format_from_masks (gint depth, gint bpp, gint endianness,
2606     guint red_mask, guint green_mask, guint blue_mask, guint alpha_mask)
2607 {
2608   GstVideoFormat format;
2609
2610   /* our caps system handles 24/32bpp RGB as big-endian. */
2611   if ((bpp == 24 || bpp == 32) && endianness == G_LITTLE_ENDIAN) {
2612     red_mask = GUINT32_TO_BE (red_mask);
2613     green_mask = GUINT32_TO_BE (green_mask);
2614     blue_mask = GUINT32_TO_BE (blue_mask);
2615     alpha_mask = GUINT32_TO_BE (alpha_mask);
2616     endianness = G_BIG_ENDIAN;
2617     if (bpp == 24) {
2618       red_mask >>= 8;
2619       green_mask >>= 8;
2620       blue_mask >>= 8;
2621     }
2622   }
2623
2624   if (depth == 30 && bpp == 32) {
2625     format = GST_VIDEO_FORMAT_r210;
2626   } else if (depth == 24 && bpp == 32) {
2627     format = gst_video_format_from_rgb32_masks (red_mask, green_mask,
2628         blue_mask);
2629   } else if (depth == 32 && bpp == 32 && alpha_mask) {
2630     format = gst_video_format_from_rgba32_masks (red_mask, green_mask,
2631         blue_mask, alpha_mask);
2632   } else if (depth == 24 && bpp == 24) {
2633     format = gst_video_format_from_rgb24_masks (red_mask, green_mask,
2634         blue_mask);
2635   } else if ((depth == 15 || depth == 16) && bpp == 16 &&
2636       endianness == G_BYTE_ORDER) {
2637     format = gst_video_format_from_rgb16_masks (red_mask, green_mask,
2638         blue_mask);
2639   } else if (depth == 8 && bpp == 8) {
2640     format = GST_VIDEO_FORMAT_RGB8P;
2641   } else if (depth == 64 && bpp == 64) {
2642     format = gst_video_format_from_rgba32_masks (red_mask, green_mask,
2643         blue_mask, alpha_mask);
2644     if (format == GST_VIDEO_FORMAT_ARGB) {
2645       format = GST_VIDEO_FORMAT_ARGB64;
2646     } else {
2647       format = GST_VIDEO_FORMAT_UNKNOWN;
2648     }
2649   } else {
2650     format = GST_VIDEO_FORMAT_UNKNOWN;
2651   }
2652   return format;
2653 }
2654
2655 /**
2656  * gst_video_format_from_fourcc:
2657  * @fourcc: a FOURCC value representing raw YUV video
2658  *
2659  * Converts a FOURCC value into the corresponding #GstVideoFormat.
2660  * If the FOURCC cannot be represented by #GstVideoFormat,
2661  * #GST_VIDEO_FORMAT_UNKNOWN is returned.
2662  *
2663  * Returns: the #GstVideoFormat describing the FOURCC value
2664  */
2665 GstVideoFormat
2666 gst_video_format_from_fourcc (guint32 fourcc)
2667 {
2668   switch (fourcc) {
2669     case GST_MAKE_FOURCC ('I', '4', '2', '0'):
2670       return GST_VIDEO_FORMAT_I420;
2671     case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
2672       return GST_VIDEO_FORMAT_YV12;
2673     case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
2674       return GST_VIDEO_FORMAT_YUY2;
2675     case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'):
2676       return GST_VIDEO_FORMAT_YVYU;
2677     case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
2678       return GST_VIDEO_FORMAT_UYVY;
2679     case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'):
2680       return GST_VIDEO_FORMAT_AYUV;
2681     case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
2682       return GST_VIDEO_FORMAT_Y41B;
2683     case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
2684       return GST_VIDEO_FORMAT_Y42B;
2685     case GST_MAKE_FOURCC ('Y', '4', '4', '4'):
2686       return GST_VIDEO_FORMAT_Y444;
2687     case GST_MAKE_FOURCC ('v', '2', '1', '0'):
2688       return GST_VIDEO_FORMAT_v210;
2689     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
2690       return GST_VIDEO_FORMAT_v216;
2691     case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
2692       return GST_VIDEO_FORMAT_NV12;
2693     case GST_MAKE_FOURCC ('N', 'V', '2', '1'):
2694       return GST_VIDEO_FORMAT_NV21;
2695     case GST_MAKE_FOURCC ('N', 'V', '1', '6'):
2696       return GST_VIDEO_FORMAT_NV16;
2697     case GST_MAKE_FOURCC ('N', 'V', '2', '4'):
2698       return GST_VIDEO_FORMAT_NV24;
2699     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
2700       return GST_VIDEO_FORMAT_v308;
2701     case GST_MAKE_FOURCC ('Y', '8', '0', '0'):
2702     case GST_MAKE_FOURCC ('Y', '8', ' ', ' '):
2703     case GST_MAKE_FOURCC ('G', 'R', 'E', 'Y'):
2704       return GST_VIDEO_FORMAT_GRAY8;
2705     case GST_MAKE_FOURCC ('Y', '1', '6', ' '):
2706       return GST_VIDEO_FORMAT_GRAY16_LE;
2707     case GST_MAKE_FOURCC ('U', 'Y', 'V', 'P'):
2708       return GST_VIDEO_FORMAT_UYVP;
2709     case GST_MAKE_FOURCC ('A', '4', '2', '0'):
2710       return GST_VIDEO_FORMAT_A420;
2711     case GST_MAKE_FOURCC ('Y', 'U', 'V', '9'):
2712       return GST_VIDEO_FORMAT_YUV9;
2713     case GST_MAKE_FOURCC ('Y', 'V', 'U', '9'):
2714       return GST_VIDEO_FORMAT_YVU9;
2715     case GST_MAKE_FOURCC ('I', 'Y', 'U', '1'):
2716       return GST_VIDEO_FORMAT_IYU1;
2717     case GST_MAKE_FOURCC ('A', 'Y', '6', '4'):
2718       return GST_VIDEO_FORMAT_AYUV64;
2719     default:
2720       return GST_VIDEO_FORMAT_UNKNOWN;
2721   }
2722 }
2723
2724 /**
2725  * gst_video_format_from_string:
2726  * @format: a format string
2727  *
2728  * Convert the @format string to its #GstVideoFormat.
2729  *
2730  * Returns: the #GstVideoFormat for @format or GST_VIDEO_FORMAT_UNKNOWN when the
2731  * string is not a known format.
2732  */
2733 GstVideoFormat
2734 gst_video_format_from_string (const gchar * format)
2735 {
2736   guint i;
2737
2738   g_return_val_if_fail (format != NULL, GST_VIDEO_FORMAT_UNKNOWN);
2739
2740   for (i = 0; i < G_N_ELEMENTS (formats); i++) {
2741     if (strcmp (GST_VIDEO_FORMAT_INFO_NAME (&formats[i].info), format) == 0)
2742       return GST_VIDEO_FORMAT_INFO_FORMAT (&formats[i].info);
2743   }
2744   return GST_VIDEO_FORMAT_UNKNOWN;
2745 }
2746
2747
2748 /**
2749  * gst_video_format_to_fourcc:
2750  * @format: a #GstVideoFormat video format
2751  *
2752  * Converts a #GstVideoFormat value into the corresponding FOURCC.  Only
2753  * a few YUV formats have corresponding FOURCC values.  If @format has
2754  * no corresponding FOURCC value, 0 is returned.
2755  *
2756  * Returns: the FOURCC corresponding to @format
2757  */
2758 guint32
2759 gst_video_format_to_fourcc (GstVideoFormat format)
2760 {
2761   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
2762
2763   if (format >= G_N_ELEMENTS (formats))
2764     return 0;
2765
2766   return formats[format].fourcc;
2767 }
2768
2769 /**
2770  * gst_video_format_to_string:
2771  * @format: a #GstVideoFormat video format
2772  *
2773  * Returns a string containing a descriptive name for
2774  * the #GstVideoFormat if there is one, or NULL otherwise.
2775  *
2776  * Returns: the name corresponding to @format
2777  */
2778 const gchar *
2779 gst_video_format_to_string (GstVideoFormat format)
2780 {
2781   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
2782
2783   if (format >= G_N_ELEMENTS (formats))
2784     return NULL;
2785
2786   return GST_VIDEO_FORMAT_INFO_NAME (&formats[format].info);
2787 }
2788
2789 /**
2790  * gst_video_format_get_info:
2791  * @format: a #GstVideoFormat
2792  *
2793  * Get the #GstVideoFormatInfo for @format
2794  *
2795  * Returns: The #GstVideoFormatInfo for @format.
2796  */
2797 const GstVideoFormatInfo *
2798 gst_video_format_get_info (GstVideoFormat format)
2799 {
2800   g_return_val_if_fail (format < G_N_ELEMENTS (formats), NULL);
2801
2802   return &formats[format].info;
2803 }
2804
2805 /**
2806  * gst_video_format_get_palette:
2807  * @format: a #GstVideoFormat
2808  * @size: (out): size of the palette in bytes
2809  *
2810  * Get the default palette of @format. This the palette used in the pack
2811  * function for paletted formats.
2812  *
2813  * Returns: (transfer none): the default palette of @format or %NULL when
2814  * @format does not have a palette.
2815  *
2816  * Since: 1.2
2817  */
2818 gconstpointer
2819 gst_video_format_get_palette (GstVideoFormat format, gsize * size)
2820 {
2821   g_return_val_if_fail (format < G_N_ELEMENTS (formats), NULL);
2822   g_return_val_if_fail (size != NULL, NULL);
2823
2824   switch (format) {
2825     case GST_VIDEO_FORMAT_RGB8P:
2826       *size = sizeof (std_palette_RGB8P);
2827       return std_palette_RGB8P;
2828     default:
2829       return NULL;
2830   }
2831 }