video: fix default colorspace settings
[platform/upstream/gstreamer.git] / gst-libs / gst / video / video.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., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #  include "config.h"
24 #endif
25
26 #include <string.h>
27
28 #include "video.h"
29 #include "gstvideometa.h"
30
31 /**
32  * SECTION:gstvideo
33  * @short_description: Support library for video operations
34  *
35  * <refsect2>
36  * <para>
37  * This library contains some helper functions and includes the
38  * videosink and videofilter base classes.
39  * </para>
40  * </refsect2>
41  */
42
43 GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE);
44
45 static int fill_planes (GstVideoInfo * info);
46
47 #include "videoblendorc.h"
48
49 /* Line conversion to AYUV */
50
51 #define GET_PLANE_STRIDE(plane) (stride(plane))
52 #define GET_PLANE_LINE(plane, line) \
53   (gpointer)(((guint8*)(data[plane])) + stride[plane] * (line))
54
55 #define GET_COMP_STRIDE(comp) \
56   GST_VIDEO_FORMAT_INFO_STRIDE (info, stride, comp)
57 #define GET_COMP_DATA(comp) \
58   GST_VIDEO_FORMAT_INFO_DATA (info, data, comp)
59
60 #define GET_COMP_LINE(comp, line) \
61   (gpointer)(((guint8*)GET_COMP_DATA (comp)) + \
62       GET_COMP_STRIDE(comp) * (line))
63
64 #define GET_STRIDE()                 GET_PLANE_STRIDE (0)
65 #define GET_LINE(line)               GET_PLANE_LINE (0, line)
66
67 #define GET_Y_LINE(line)             GET_COMP_LINE(GST_VIDEO_COMP_Y, line)
68 #define GET_U_LINE(line)             GET_COMP_LINE(GST_VIDEO_COMP_U, line)
69 #define GET_V_LINE(line)             GET_COMP_LINE(GST_VIDEO_COMP_V, line)
70 #define GET_A_LINE(line)             GET_COMP_LINE(GST_VIDEO_COMP_A, line)
71
72 #define GET_Y_STRIDE()               GET_COMP_STRIDE(GST_VIDEO_COMP_Y)
73 #define GET_U_STRIDE()               GET_COMP_STRIDE(GST_VIDEO_COMP_U)
74 #define GET_V_STRIDE()               GET_COMP_STRIDE(GST_VIDEO_COMP_V)
75 #define GET_A_STRIDE()               GET_COMP_STRIDE(GST_VIDEO_COMP_A)
76
77 #define PACK_420 GST_VIDEO_FORMAT_AYUV, unpack_planar_420, pack_planar_420
78 static void
79 unpack_planar_420 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
80     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
81     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
82 {
83   orc_unpack_I420 (dest,
84       GET_Y_LINE (y), GET_U_LINE (y >> 1), GET_V_LINE (y >> 1), width);
85 }
86
87 static void
88 pack_planar_420 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
89     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
90     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
91     gint y, gint width)
92 {
93   orc_pack_I420 (GET_Y_LINE (y),
94       GET_U_LINE (y >> 1), GET_V_LINE (y >> 1), src, width / 2);
95 }
96
97 #define PACK_YUY2 GST_VIDEO_FORMAT_AYUV, unpack_YUY2, pack_YUY2
98 static void
99 unpack_YUY2 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
100     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
101     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
102 {
103   orc_unpack_YUY2 (dest, GET_LINE (y), width / 2);
104 }
105
106 static void
107 pack_YUY2 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
108     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
109     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
110     gint y, gint width)
111 {
112   orc_pack_YUY2 (GET_LINE (y), src, width / 2);
113 }
114
115 #define PACK_UYVY GST_VIDEO_FORMAT_AYUV, unpack_UYVY, pack_UYVY
116 static void
117 unpack_UYVY (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
118     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
119     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
120 {
121   orc_unpack_UYVY (dest, GET_LINE (y), width / 2);
122 }
123
124 static void
125 pack_UYVY (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
126     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
127     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
128     gint y, gint width)
129 {
130   orc_pack_UYVY (GET_LINE (y), src, width / 2);
131 }
132
133 #define PACK_YVYU GST_VIDEO_FORMAT_AYUV, unpack_YVYU, pack_YVYU
134 static void
135 unpack_YVYU (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
136     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
137     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
138 {
139   orc_unpack_YVYU (dest, GET_LINE (y), width / 2);
140 }
141
142 static void
143 pack_YVYU (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
144     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
145     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
146     gint y, gint width)
147 {
148   orc_pack_YVYU (GET_LINE (y), src, width / 2);
149 }
150
151 #define PACK_v308 GST_VIDEO_FORMAT_AYUV, unpack_v308, pack_v308
152 static void
153 unpack_v308 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
154     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
155     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
156 {
157   int i;
158   const guint8 *s = GET_LINE (y);
159   guint8 *d = dest;
160
161   for (i = 0; i < width; i++) {
162     d[i * 4 + 0] = 0xff;
163     d[i * 4 + 1] = s[i * 3 + 0];
164     d[i * 4 + 2] = s[i * 3 + 1];
165     d[i * 4 + 3] = s[i * 3 + 2];
166   }
167 }
168
169 static void
170 pack_v308 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
171     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
172     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
173     gint y, gint width)
174 {
175   int i;
176   guint8 *d = GET_LINE (y);
177   const guint8 *s = src;
178
179   for (i = 0; i < width; i++) {
180     d[i * 3 + 0] = s[i * 4 + 1];
181     d[i * 3 + 1] = s[i * 4 + 2];
182     d[i * 3 + 2] = s[i * 4 + 3];
183   }
184 }
185
186 #define PACK_AYUV GST_VIDEO_FORMAT_AYUV, unpack_copy4, pack_copy4
187 #define PACK_ARGB GST_VIDEO_FORMAT_ARGB, unpack_copy4, pack_copy4
188 static void
189 unpack_copy4 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
190     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
191     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
192 {
193   memcpy (dest, GET_LINE (y), width * 4);
194 }
195
196 static void
197 pack_copy4 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
198     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
199     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
200     gint y, gint width)
201 {
202   memcpy (GET_LINE (y), src, width * 4);
203 }
204
205 #define PACK_v210 GST_VIDEO_FORMAT_AYUV64, unpack_v210, pack_v210
206 static void
207 unpack_v210 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
208     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
209     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
210 {
211   int i;
212   const guint8 *s = GET_LINE (y);
213   guint16 *d = dest;
214
215   for (i = 0; i < width; i += 6) {
216     guint32 a0, a1, a2, a3;
217     guint16 y0, y1, y2, y3, y4, y5;
218     guint16 u0, u2, u4;
219     guint16 v0, v2, v4;
220
221     a0 = GST_READ_UINT32_LE (s + (i / 6) * 16 + 0);
222     a1 = GST_READ_UINT32_LE (s + (i / 6) * 16 + 4);
223     a2 = GST_READ_UINT32_LE (s + (i / 6) * 16 + 8);
224     a3 = GST_READ_UINT32_LE (s + (i / 6) * 16 + 12);
225
226     u0 = ((a0 >> 0) & 0x3ff) << 6;
227     y0 = ((a0 >> 10) & 0x3ff) << 6;
228     v0 = ((a0 >> 20) & 0x3ff) << 6;
229     y1 = ((a1 >> 0) & 0x3ff) << 6;
230
231     u2 = ((a1 >> 10) & 0x3ff) << 6;
232     y2 = ((a1 >> 20) & 0x3ff) << 6;
233     v2 = ((a2 >> 0) & 0x3ff) << 6;
234     y3 = ((a2 >> 10) & 0x3ff) << 6;
235
236     u4 = ((a2 >> 20) & 0x3ff) << 6;
237     y4 = ((a3 >> 0) & 0x3ff) << 6;
238     v4 = ((a3 >> 10) & 0x3ff) << 6;
239     y5 = ((a3 >> 20) & 0x3ff) << 6;
240
241     d[4 * (i + 0) + 0] = 0xffff;
242     d[4 * (i + 0) + 1] = y0;
243     d[4 * (i + 0) + 2] = u0;
244     d[4 * (i + 0) + 3] = v0;
245
246     d[4 * (i + 1) + 0] = 0xffff;
247     d[4 * (i + 1) + 1] = y1;
248     d[4 * (i + 1) + 2] = u0;
249     d[4 * (i + 1) + 3] = v0;
250
251     d[4 * (i + 2) + 0] = 0xffff;
252     d[4 * (i + 2) + 1] = y2;
253     d[4 * (i + 2) + 2] = u2;
254     d[4 * (i + 2) + 3] = v2;
255
256     d[4 * (i + 3) + 0] = 0xffff;
257     d[4 * (i + 3) + 1] = y3;
258     d[4 * (i + 3) + 2] = u2;
259     d[4 * (i + 3) + 3] = v2;
260
261     d[4 * (i + 4) + 0] = 0xffff;
262     d[4 * (i + 4) + 1] = y4;
263     d[4 * (i + 4) + 2] = u4;
264     d[4 * (i + 4) + 3] = v4;
265
266     d[4 * (i + 5) + 0] = 0xffff;
267     d[4 * (i + 5) + 1] = y5;
268     d[4 * (i + 5) + 2] = u4;
269     d[4 * (i + 5) + 3] = v4;
270   }
271 }
272
273 static void
274 pack_v210 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
275     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
276     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
277     gint y, gint width)
278 {
279   int i;
280   guint8 *d = GET_LINE (y);
281   const guint16 *s = src;
282
283   for (i = 0; i < width; i += 6) {
284     guint32 a0, a1, a2, a3;
285     guint16 y0, y1, y2, y3, y4, y5;
286     guint16 u0, u1, u2;
287     guint16 v0, v1, v2;
288
289     y0 = s[4 * (i + 0) + 1] >> 6;
290     y1 = s[4 * (i + 1) + 1] >> 6;
291     y2 = s[4 * (i + 2) + 1] >> 6;
292     y3 = s[4 * (i + 3) + 1] >> 6;
293     y4 = s[4 * (i + 4) + 1] >> 6;
294     y5 = s[4 * (i + 5) + 1] >> 6;
295
296     u0 = (s[4 * (i + 0) + 2] + s[4 * (i + 1) + 2] + 1) >> 7;
297     u1 = (s[4 * (i + 2) + 2] + s[4 * (i + 3) + 2] + 1) >> 7;
298     u2 = (s[4 * (i + 4) + 2] + s[4 * (i + 5) + 2] + 1) >> 7;
299
300     v0 = (s[4 * (i + 0) + 3] + s[4 * (i + 1) + 3] + 1) >> 7;
301     v1 = (s[4 * (i + 2) + 3] + s[4 * (i + 3) + 3] + 1) >> 7;
302     v2 = (s[4 * (i + 4) + 3] + s[4 * (i + 5) + 3] + 1) >> 7;
303
304     a0 = u0 | (y0 << 10) | (v0 << 20);
305     a1 = y1 | (u1 << 10) | (y2 << 20);
306     a2 = v1 | (y3 << 10) | (u2 << 20);
307     a3 = y4 | (v2 << 10) | (y5 << 20);
308
309     GST_WRITE_UINT32_LE (d + (i / 6) * 16 + 0, a0);
310     GST_WRITE_UINT32_LE (d + (i / 6) * 16 + 4, a1);
311     GST_WRITE_UINT32_LE (d + (i / 6) * 16 + 8, a2);
312     GST_WRITE_UINT32_LE (d + (i / 6) * 16 + 12, a3);
313   }
314 }
315
316 #define PACK_v216 GST_VIDEO_FORMAT_AYUV64, unpack_v216, pack_v216
317 static void
318 unpack_v216 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
319     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
320     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
321 {
322   int i;
323   const guint8 *s = GET_LINE (y);
324   guint16 *d = dest;
325
326   for (i = 0; i < width; i++) {
327     d[i * 4 + 0] = 0xffff;
328     d[i * 4 + 1] = GST_READ_UINT16_LE (s + i * 4 + 2);
329     d[i * 4 + 2] = GST_READ_UINT16_LE (s + (i >> 1) * 8 + 0);
330     d[i * 4 + 3] = GST_READ_UINT16_LE (s + (i >> 1) * 8 + 4);
331   }
332 }
333
334 static void
335 pack_v216 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
336     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
337     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
338     gint y, gint width)
339 {
340   int i;
341   guint8 *d = GET_LINE (y);
342   const guint16 *s = src;
343
344   for (i = 0; i < width / 2; i++) {
345     GST_WRITE_UINT16_LE (d + i * 8 + 0, s[(i * 2 + 0) * 4 + 2]);
346     GST_WRITE_UINT16_LE (d + i * 8 + 2, s[(i * 2 + 0) * 4 + 1]);
347     GST_WRITE_UINT16_LE (d + i * 8 + 4, s[(i * 2 + 0) * 4 + 3]);
348     GST_WRITE_UINT16_LE (d + i * 8 + 6, s[(i * 2 + 1) * 4 + 1]);
349   }
350 }
351
352 #define PACK_Y41B GST_VIDEO_FORMAT_AYUV, unpack_Y41B, pack_Y41B
353 static void
354 unpack_Y41B (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
355     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
356     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
357 {
358   orc_unpack_YUV9 (dest,
359       GET_Y_LINE (y), GET_U_LINE (y), GET_V_LINE (y), width / 2);
360 }
361
362 static void
363 pack_Y41B (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
364     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
365     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
366     gint y, gint width)
367 {
368   int i;
369   guint8 *destY = GET_Y_LINE (y);
370   guint8 *destU = GET_U_LINE (y);
371   guint8 *destV = GET_V_LINE (y);
372   const guint8 *s = src;
373
374   for (i = 0; i < width - 3; i += 4) {
375     destY[i] = s[i * 4 + 1];
376     destY[i + 1] = s[i * 4 + 5];
377     destY[i + 2] = s[i * 4 + 9];
378     destY[i + 3] = s[i * 4 + 13];
379
380     destU[i >> 2] =
381         (s[i * 4 + 2] + s[i * 4 + 6] + s[i * 4 + 10] + s[i * 4 + 14] + 2) >> 2;
382     destV[i >> 2] =
383         (s[i * 4 + 3] + s[i * 4 + 7] + s[i * 4 + 11] + s[i * 4 + 15] + 2) >> 2;
384   }
385
386   if (i == width - 3) {
387     destY[i] = s[i * 4 + 1];
388     destY[i + 1] = s[i * 4 + 5];
389     destY[i + 2] = s[i * 4 + 9];
390
391     destU[i >> 2] = (s[i * 4 + 2] + s[i * 4 + 6] + s[i * 4 + 10] + 1) / 3;
392     destV[i >> 2] = (s[i * 4 + 3] + s[i * 4 + 7] + s[i * 4 + 11] + 1) / 3;
393   } else if (i == width - 2) {
394     destY[i] = s[i * 4 + 1];
395     destY[i + 1] = s[i * 4 + 5];
396
397     destU[i >> 2] = (s[i * 4 + 2] + s[i * 4 + 6] + 1) >> 1;
398     destV[i >> 2] = (s[i * 4 + 3] + s[i * 4 + 7] + 1) >> 1;
399   } else if (i == width - 1) {
400     destY[i + 1] = s[i * 4 + 5];
401
402     destU[i >> 2] = s[i * 4 + 2];
403     destV[i >> 2] = s[i * 4 + 3];
404   }
405 }
406
407 #define PACK_Y42B GST_VIDEO_FORMAT_AYUV, unpack_Y42B, pack_Y42B
408 static void
409 unpack_Y42B (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
410     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
411     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
412 {
413   orc_unpack_Y42B (dest,
414       GET_Y_LINE (y), GET_U_LINE (y), GET_V_LINE (y), width / 2);
415 }
416
417 static void
418 pack_Y42B (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
419     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
420     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
421     gint y, gint width)
422 {
423   orc_pack_Y42B (GET_Y_LINE (y),
424       GET_U_LINE (y), GET_V_LINE (y), src, width / 2);
425 }
426
427 #define PACK_Y444 GST_VIDEO_FORMAT_AYUV, unpack_Y444, pack_Y444
428 static void
429 unpack_Y444 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
430     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
431     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
432 {
433   orc_unpack_Y444 (dest, GET_Y_LINE (y), GET_U_LINE (y), GET_V_LINE (y), width);
434 }
435
436 static void
437 pack_Y444 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
438     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
439     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
440     gint y, gint width)
441 {
442   orc_pack_Y444 (GET_Y_LINE (y), GET_U_LINE (y), GET_V_LINE (y), src, width);
443 }
444
445 #define PACK_GRAY8 GST_VIDEO_FORMAT_AYUV, unpack_GRAY8, pack_GRAY8
446 static void
447 unpack_GRAY8 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
448     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
449     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
450 {
451   orc_unpack_GRAY8 (dest, GET_LINE (y), width);
452 }
453
454 static void
455 pack_GRAY8 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
456     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
457     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
458     gint y, gint width)
459 {
460   orc_pack_GRAY8 (GET_LINE (y), src, width);
461 }
462
463 #define PACK_GRAY16_BE GST_VIDEO_FORMAT_AYUV64, unpack_GRAY16_BE, pack_GRAY16_BE
464 static void
465 unpack_GRAY16_BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
466     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
467     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
468 {
469   int i;
470   const guint16 *s = GET_LINE (y);
471   guint16 *d = dest;
472
473   for (i = 0; i < width; i++) {
474     d[i * 4 + 0] = 0xffff;
475     d[i * 4 + 1] = GST_READ_UINT16_BE (s + i);
476     d[i * 4 + 2] = 0x8000;
477     d[i * 4 + 3] = 0x8000;
478   }
479 }
480
481 static void
482 pack_GRAY16_BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
483     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
484     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
485     gint y, gint width)
486 {
487   int i;
488   guint16 *d = GET_LINE (y);
489   const guint16 *s = src;
490
491   for (i = 0; i < width; i++) {
492     GST_WRITE_UINT16_BE (d + i, s[i * 4 + 1]);
493   }
494 }
495
496 #define PACK_GRAY16_LE GST_VIDEO_FORMAT_AYUV64, unpack_GRAY16_LE, pack_GRAY16_LE
497 static void
498 unpack_GRAY16_LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
499     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
500     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
501 {
502   int i;
503   const guint16 *s = GET_LINE (y);
504   guint16 *d = dest;
505
506   for (i = 0; i < width; i++) {
507     d[i * 4 + 0] = 0xffff;
508     d[i * 4 + 1] = GST_READ_UINT16_LE (s + i);
509     d[i * 4 + 2] = 0x8000;
510     d[i * 4 + 3] = 0x8000;
511   }
512 }
513
514 static void
515 pack_GRAY16_LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
516     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
517     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
518     gint y, gint width)
519 {
520   int i;
521   guint16 *d = GET_LINE (y);
522   const guint16 *s = src;
523
524   for (i = 0; i < width; i++) {
525     GST_WRITE_UINT16_LE (d + i, s[i * 4 + 1]);
526   }
527 }
528
529 #define PACK_RGB16 GST_VIDEO_FORMAT_ARGB, unpack_RGB16, pack_RGB16
530 static void
531 unpack_RGB16 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
532     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
533     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
534 {
535   int i;
536   const guint16 *s = GET_LINE (y);
537   guint8 *d = dest;
538
539   for (i = 0; i < width; i++) {
540     d[i * 4 + 0] = 0xff;
541     d[i * 4 + 1] = ((s[i] >> 11) & 0x1f) << 3;
542     d[i * 4 + 2] = ((s[i] >> 5) & 0x3f) << 2;
543     d[i * 4 + 3] = ((s[i]) & 0x1f) << 3;
544   }
545 }
546
547 static void
548 pack_RGB16 (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   guint16 *d = GET_LINE (y);
555   const guint8 *s = src;
556
557   for (i = 0; i < width; i++) {
558     d[i] = ((s[i * 4 + 1] >> 3) << 11) |
559         ((s[i * 4 + 2] >> 2) << 5) | (s[i * 4 + 3] >> 3);
560   }
561 }
562
563 #define PACK_BGR16 GST_VIDEO_FORMAT_ARGB, unpack_BGR16, pack_BGR16
564 static void
565 unpack_BGR16 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
566     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
567     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
568 {
569   int i;
570   const guint16 *s = GET_LINE (y);
571   guint8 *d = dest;
572
573   for (i = 0; i < width; i++) {
574     d[i * 4 + 0] = 0xff;
575     d[i * 4 + 3] = ((s[i] >> 11) & 0x1f) << 3;
576     d[i * 4 + 2] = ((s[i] >> 5) & 0x3f) << 2;
577     d[i * 4 + 1] = ((s[i]) & 0x1f) << 3;
578   }
579 }
580
581 static void
582 pack_BGR16 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
583     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
584     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
585     gint y, gint width)
586 {
587   int i;
588   guint16 *d = GET_LINE (y);
589   const guint8 *s = src;
590
591   for (i = 0; i < width; i++) {
592     d[i] = ((s[i * 4 + 3] >> 3) << 11) |
593         ((s[i * 4 + 2] >> 2) << 5) | (s[i * 4 + 1] >> 3);
594   }
595 }
596
597 #define PACK_RGB15 GST_VIDEO_FORMAT_ARGB, unpack_RGB15, pack_RGB15
598 static void
599 unpack_RGB15 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
600     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
601     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
602 {
603   int i;
604   const guint16 *s = GET_LINE (y);
605   guint8 *d = dest;
606
607   for (i = 0; i < width; i++) {
608     d[i * 4 + 0] = 0xff;
609     d[i * 4 + 1] = ((s[i] >> 10) & 0x1f) << 3;
610     d[i * 4 + 2] = ((s[i] >> 5) & 0x1f) << 3;
611     d[i * 4 + 3] = ((s[i]) & 0x1f) << 3;
612   }
613 }
614
615 static void
616 pack_RGB15 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
617     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
618     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
619     gint y, gint width)
620 {
621   int i;
622   guint16 *d = GET_LINE (y);
623   const guint8 *s = src;
624
625   for (i = 0; i < width; i++) {
626     d[i] = ((s[i * 4 + 1] >> 3) << 10) |
627         ((s[i * 4 + 2] >> 3) << 5) | (s[i * 4 + 3] >> 3);
628   }
629 }
630
631 #define PACK_BGR15 GST_VIDEO_FORMAT_ARGB, unpack_BGR15, pack_BGR15
632 static void
633 unpack_BGR15 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
634     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
635     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
636 {
637   int i;
638   const guint16 *s = GET_LINE (y);
639   guint8 *d = dest;
640
641   for (i = 0; i < width; i++) {
642     d[i * 4 + 0] = 0xff;
643     d[i * 4 + 3] = ((s[i] >> 10) & 0x1f) << 3;
644     d[i * 4 + 2] = ((s[i] >> 5) & 0x1f) << 3;
645     d[i * 4 + 1] = ((s[i]) & 0x1f) << 3;
646   }
647 }
648
649 static void
650 pack_BGR15 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
651     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
652     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
653     gint y, gint width)
654 {
655   int i;
656   guint16 *d = GET_LINE (y);
657   const guint8 *s = src;
658
659   for (i = 0; i < width; i++) {
660     d[i] = ((s[i * 4 + 3] >> 3) << 10) |
661         ((s[i * 4 + 2] >> 3) << 5) | (s[i * 4 + 1] >> 3);
662   }
663 }
664
665 #define PACK_BGRA GST_VIDEO_FORMAT_ARGB, unpack_BGRA, pack_BGRA
666 static void
667 unpack_BGRA (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
668     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
669     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
670 {
671   orc_unpack_BGRA (dest, GET_LINE (y), width);
672 }
673
674 static void
675 pack_BGRA (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
676     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
677     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
678     gint y, gint width)
679 {
680   orc_pack_BGRA (GET_LINE (y), src, width);
681 }
682
683 #define PACK_ABGR GST_VIDEO_FORMAT_ARGB, unpack_ABGR, pack_ABGR
684 static void
685 unpack_ABGR (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
686     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
687     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
688 {
689   orc_unpack_ABGR (dest, GET_LINE (y), width);
690 }
691
692 static void
693 pack_ABGR (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
694     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
695     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
696     gint y, gint width)
697 {
698   orc_pack_ABGR (GET_LINE (y), src, width);
699 }
700
701 #define PACK_RGBA GST_VIDEO_FORMAT_ARGB, unpack_RGBA, pack_RGBA
702 static void
703 unpack_RGBA (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
704     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
705     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
706 {
707   orc_unpack_RGBA (dest, GET_LINE (y), width);
708 }
709
710 static void
711 pack_RGBA (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
712     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
713     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
714     gint y, gint width)
715 {
716   orc_pack_RGBA (GET_LINE (y), src, width);
717 }
718
719 #define PACK_RGB GST_VIDEO_FORMAT_ARGB, unpack_RGB, pack_RGB
720 static void
721 unpack_RGB (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 guint8 *s = GET_LINE (y);
727   guint8 *d = dest;
728
729   for (i = 0; i < width; i++) {
730     d[i * 4 + 0] = 0xff;
731     d[i * 4 + 1] = s[i * 3 + 0];
732     d[i * 4 + 2] = s[i * 3 + 1];
733     d[i * 4 + 3] = s[i * 3 + 2];
734   }
735 }
736
737 static void
738 pack_RGB (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   guint8 *d = GET_LINE (y);
745   const guint8 *s = src;
746
747   for (i = 0; i < width; i++) {
748     d[i * 3 + 0] = s[i * 4 + 1];
749     d[i * 3 + 1] = s[i * 4 + 2];
750     d[i * 3 + 2] = s[i * 4 + 3];
751   }
752 }
753
754 #define PACK_BGR GST_VIDEO_FORMAT_ARGB, unpack_BGR, pack_BGR
755 static void
756 unpack_BGR (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
757     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
758     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
759 {
760   int i;
761   const guint8 *s = GET_LINE (y);
762   guint8 *d = dest;
763
764   for (i = 0; i < width; i++) {
765     d[i * 4 + 0] = 0xff;
766     d[i * 4 + 1] = s[i * 3 + 2];
767     d[i * 4 + 2] = s[i * 3 + 1];
768     d[i * 4 + 3] = s[i * 3 + 0];
769   }
770 }
771
772 static void
773 pack_BGR (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
774     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
775     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
776     gint y, gint width)
777 {
778   int i;
779   guint8 *d = GET_LINE (y);
780   const guint8 *s = src;
781
782   for (i = 0; i < width; i++) {
783     d[i * 3 + 0] = s[i * 4 + 3];
784     d[i * 3 + 1] = s[i * 4 + 2];
785     d[i * 3 + 2] = s[i * 4 + 1];
786   }
787 }
788
789 #define PACK_NV12 GST_VIDEO_FORMAT_AYUV, unpack_NV12, pack_NV12
790 static void
791 unpack_NV12 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
792     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
793     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
794 {
795   orc_unpack_NV12 (dest,
796       GET_PLANE_LINE (0, y), GET_PLANE_LINE (1, y >> 1), width / 2);
797 }
798
799 static void
800 pack_NV12 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
801     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
802     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
803     gint y, gint width)
804 {
805   orc_pack_NV12 (GET_PLANE_LINE (0, y),
806       GET_PLANE_LINE (1, y >> 1), src, width / 2);
807 }
808
809 #define PACK_NV21 GST_VIDEO_FORMAT_AYUV, unpack_NV21, pack_NV21
810 static void
811 unpack_NV21 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
812     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
813     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
814 {
815   orc_unpack_NV21 (dest,
816       GET_PLANE_LINE (0, y), GET_PLANE_LINE (1, y >> 1), width / 2);
817 }
818
819 static void
820 pack_NV21 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
821     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
822     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
823     gint y, gint width)
824 {
825   orc_pack_NV21 (GET_PLANE_LINE (0, y),
826       GET_PLANE_LINE (1, y >> 1), src, width / 2);
827 }
828
829 #define PACK_UYVP GST_VIDEO_FORMAT_AYUV64, unpack_UYVP, pack_UYVP
830 static void
831 unpack_UYVP (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
832     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
833     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
834 {
835   int i;
836   const guint8 *s = GET_LINE (y);
837   guint16 *d = dest;
838
839   for (i = 0; i < width; i += 2) {
840     guint16 y0, y1;
841     guint16 u0;
842     guint16 v0;
843
844     u0 = (s[(i / 2) * 5 + 0] << 2) | (s[(i / 2) * 5 + 1] >> 6);
845     y0 = ((s[(i / 2) * 5 + 1] & 0x3f) << 4) | (s[(i / 2) * 5 + 2] >> 4);
846     v0 = ((s[(i / 2) * 5 + 2] & 0x0f) << 6) | (s[(i / 2) * 5 + 3] >> 2);
847     y1 = ((s[(i / 2) * 5 + 3] & 0x03) << 8) | s[(i / 2) * 5 + 4];
848
849     d[i * 4 + 0] = 0xffff;
850     d[i * 4 + 1] = y0 << 6;
851     d[i * 4 + 2] = u0 << 6;
852     d[i * 4 + 3] = v0 << 6;
853     d[i * 4 + 4] = 0xffff;
854     d[i * 4 + 5] = y1 << 6;
855     d[i * 4 + 6] = u0 << 6;
856     d[i * 4 + 7] = v0 << 6;
857   }
858 }
859
860 static void
861 pack_UYVP (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
862     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
863     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
864     gint y, gint width)
865 {
866   int i;
867   guint8 *d = GET_LINE (y);
868   const guint16 *s = src;
869
870   for (i = 0; i < width; i += 2) {
871     guint16 y0, y1;
872     guint16 u0;
873     guint16 v0;
874
875     y0 = s[4 * (i + 0) + 1];
876     y1 = s[4 * (i + 1) + 1];
877     u0 = (s[4 * (i + 0) + 2] + s[4 * (i + 1) + 2] + 1) >> 1;
878     v0 = (s[4 * (i + 0) + 3] + s[4 * (i + 1) + 3] + 1) >> 1;
879
880     d[(i / 2) * 5 + 0] = u0 >> 8;
881     d[(i / 2) * 5 + 1] = (u0 & 0xc0) | y0 >> 10;
882     d[(i / 2) * 5 + 2] = ((y0 & 0x3c0) >> 2) | (v0 >> 12);
883     d[(i / 2) * 5 + 3] = ((v0 & 0xfc0) >> 4) | (y1 >> 14);
884     d[(i / 2) * 5 + 4] = (y1 >> 6);
885   }
886 }
887
888 #define PACK_A420 GST_VIDEO_FORMAT_AYUV, unpack_A420, pack_A420
889 static void
890 unpack_A420 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
891     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
892     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
893 {
894   orc_unpack_A420 (dest,
895       GET_Y_LINE (y), GET_U_LINE (y >> 1), GET_V_LINE (y >> 1), GET_A_LINE (y),
896       width);
897 }
898
899 static void
900 pack_A420 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
901     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
902     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
903     gint y, gint width)
904 {
905   orc_pack_A420 (GET_Y_LINE (y),
906       GET_U_LINE (y >> 1), GET_V_LINE (y >> 1), GET_A_LINE (y), src, width / 2);
907 }
908
909 #define PACK_RGB8P GST_VIDEO_FORMAT_ARGB, unpack_RGB8P, pack_RGB8P
910 static void
911 unpack_RGB8P (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
912     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
913     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
914 {
915   int i;
916   const guint8 *s = GET_LINE (y);
917   const guint32 *p = data[1];
918   guint8 *d = dest;
919
920   for (i = 0; i < width; i++) {
921     guint32 v = p[s[i]];
922     d[i * 4 + 0] = (v >> 24) & 0xff;
923     d[i * 4 + 1] = (v >> 16) & 0xff;
924     d[i * 4 + 2] = (v >> 8) & 0xff;
925     d[i * 4 + 3] = (v) & 0xff;
926   }
927 }
928
929 static void
930 pack_RGB8P (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
931     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
932     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
933     gint y, gint width)
934 {
935   int i;
936   guint8 *d = GET_LINE (y);
937   const guint8 *s = src;
938
939   /* Use our poor man's palette, taken from ffmpegcolorspace too */
940   for (i = 0; i < width; i++) {
941     /* crude approximation for alpha ! */
942     if (s[i * 4 + 0] < 0x80)
943       d[i] = 6 * 6 * 6;
944     else
945       d[i] =
946           ((((s[i * 4 + 1]) / 47) % 6) * 6 * 6 + (((s[i * 4 +
947                           2]) / 47) % 6) * 6 + (((s[i * 4 + 3]) / 47) % 6));
948   }
949 }
950
951 #define PACK_410 GST_VIDEO_FORMAT_AYUV, unpack_410, pack_410
952 static void
953 unpack_410 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
954     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
955     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
956 {
957   orc_unpack_YUV9 (dest,
958       GET_Y_LINE (y), GET_U_LINE (y >> 2), GET_V_LINE (y >> 2), width / 2);
959 }
960
961 static void
962 pack_410 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
963     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
964     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
965     gint y, gint width)
966 {
967   int i;
968   guint8 *destY = GET_Y_LINE (y);
969   guint8 *destU = GET_U_LINE (y >> 2);
970   guint8 *destV = GET_V_LINE (y >> 2);
971   const guint8 *s = src;
972
973   for (i = 0; i < width - 3; i += 4) {
974     destY[i] = s[i * 4 + 1];
975     destY[i + 1] = s[i * 4 + 5];
976     destY[i + 2] = s[i * 4 + 9];
977     destY[i + 3] = s[i * 4 + 13];
978     if (y % 4 == 0) {
979       destU[i >> 2] =
980           (s[i * 4 + 2] + s[i * 4 + 6] + s[i * 4 + 10] + s[i * 4 + 14]) >> 2;
981       destV[i >> 2] =
982           (s[i * 4 + 3] + s[i * 4 + 7] + s[i * 4 + 11] + s[i * 4 + 15]) >> 2;
983     }
984   }
985
986   if (i == width - 3) {
987     destY[i] = s[i * 4 + 1];
988     destY[i + 1] = s[i * 4 + 5];
989     destY[i + 2] = s[i * 4 + 9];
990     if (y % 4 == 0) {
991       destU[i >> 2] = (s[i * 4 + 2] + s[i * 4 + 6] + s[i * 4 + 10]) / 3;
992       destV[i >> 2] = (s[i * 4 + 3] + s[i * 4 + 7] + s[i * 4 + 11]) / 3;
993     }
994   } else if (i == width - 2) {
995     destY[i] = s[i * 4 + 1];
996     destY[i + 1] = s[i * 4 + 5];
997     if (y % 4 == 0) {
998       destU[i >> 2] = (s[i * 4 + 2] + s[i * 4 + 6]) >> 1;
999       destV[i >> 2] = (s[i * 4 + 3] + s[i * 4 + 7]) >> 1;
1000     }
1001   } else if (i == width - 1) {
1002     destY[i] = s[i * 4 + 1];
1003     destU[i >> 2] = s[i * 4 + 2];
1004     destV[i >> 2] = s[i * 4 + 3];
1005   }
1006 }
1007
1008 #define PACK_IYU1 GST_VIDEO_FORMAT_AYUV, unpack_IYU1, pack_IYU1
1009 static void
1010 unpack_IYU1 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1011     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1012     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1013 {
1014   int i;
1015   const guint8 *s = GET_LINE (y);
1016   guint8 *d = dest;
1017
1018   for (i = 0; i < width - 3; i += 4) {
1019     d[i * 4 + 0] = 0xff;
1020     d[i * 4 + 4] = 0xff;
1021     d[i * 4 + 8] = 0xff;
1022     d[i * 4 + 12] = 0xff;
1023     d[i * 4 + 1] = s[(i >> 2) * 6 + 1];
1024     d[i * 4 + 5] = s[(i >> 2) * 6 + 2];
1025     d[i * 4 + 9] = s[(i >> 2) * 6 + 4];
1026     d[i * 4 + 13] = s[(i >> 2) * 6 + 5];
1027     d[i * 4 + 2] = d[i * 4 + 6] = d[i * 4 + 10] = d[i * 4 + 14] =
1028         s[(i >> 2) * 6 + 0];
1029     d[i * 4 + 3] = d[i * 4 + 7] = d[i * 4 + 11] = d[i * 4 + 15] =
1030         s[(i >> 2) * 6 + 3];
1031   }
1032
1033   if (i == width - 3) {
1034     d[i * 4 + 0] = 0xff;
1035     d[i * 4 + 4] = 0xff;
1036     d[i * 4 + 8] = 0xff;
1037     d[i * 4 + 1] = s[(i >> 2) * 6 + 1];
1038     d[i * 4 + 5] = s[(i >> 2) * 6 + 2];
1039     d[i * 4 + 9] = s[(i >> 2) * 6 + 4];
1040     d[i * 4 + 2] = d[i * 4 + 6] = d[i * 4 + 10] = s[(i >> 2) * 6 + 0];
1041     d[i * 4 + 3] = d[i * 4 + 7] = d[i * 4 + 11] = s[(i >> 2) * 6 + 3];
1042   } else if (i == width - 2) {
1043     d[i * 4 + 0] = 0xff;
1044     d[i * 4 + 4] = 0xff;
1045     d[i * 4 + 1] = s[(i >> 2) * 6 + 1];
1046     d[i * 4 + 5] = s[(i >> 2) * 6 + 2];
1047     d[i * 4 + 2] = d[i * 4 + 6] = s[(i >> 2) * 6 + 0];
1048     d[i * 4 + 3] = d[i * 4 + 7] = s[(i >> 2) * 6 + 3];
1049   } else if (i == width - 1) {
1050     d[i * 4 + 0] = 0xff;
1051     d[i * 4 + 1] = s[(i >> 2) * 6 + 1];
1052     d[i * 4 + 2] = s[(i >> 2) * 6 + 0];
1053     d[i * 4 + 3] = s[(i >> 2) * 6 + 3];
1054   }
1055 }
1056
1057 static void
1058 pack_IYU1 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1059     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1060     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1061     gint y, gint width)
1062 {
1063   int i;
1064   guint8 *d = GET_LINE (y);
1065   const guint8 *s = src;
1066
1067   for (i = 0; i < width - 3; i += 4) {
1068     d[(i >> 2) * 6 + 1] = s[i * 4 + 1];
1069     d[(i >> 2) * 6 + 2] = s[i * 4 + 5];
1070     d[(i >> 2) * 6 + 4] = s[i * 4 + 9];
1071     d[(i >> 2) * 6 + 5] = s[i * 4 + 13];
1072     d[(i >> 2) * 6 + 0] =
1073         (s[i * 4 + 2] + s[i * 4 + 6] + s[i * 4 + 10] + s[i * 4 + 14]) >> 2;
1074     d[(i >> 2) * 6 + 3] =
1075         (s[i * 4 + 3] + s[i * 4 + 7] + s[i * 4 + 11] + s[i * 4 + 15]) >> 2;
1076   }
1077
1078   if (i == width - 3) {
1079     d[(i >> 2) * 6 + 1] = s[i * 4 + 1];
1080     d[(i >> 2) * 6 + 2] = s[i * 4 + 5];
1081     d[(i >> 2) * 6 + 4] = s[i * 4 + 9];
1082     d[(i >> 2) * 6 + 0] = (s[i * 4 + 2] + s[i * 4 + 6] + s[i * 4 + 10]) / 3;
1083     d[(i >> 2) * 6 + 3] = (s[i * 4 + 3] + s[i * 4 + 7] + s[i * 4 + 11]) / 3;
1084   } else if (i == width - 2) {
1085     d[(i >> 2) * 6 + 1] = s[i * 4 + 1];
1086     d[(i >> 2) * 6 + 2] = s[i * 4 + 5];
1087     d[(i >> 2) * 6 + 0] = (s[i * 4 + 2] + s[i * 4 + 6]) >> 1;
1088     d[(i >> 2) * 6 + 3] = (s[i * 4 + 3] + s[i * 4 + 7]) >> 1;
1089   } else if (i == width - 1) {
1090     d[(i >> 2) * 6 + 1] = s[i * 4 + 1];
1091     d[(i >> 2) * 6 + 0] = s[i * 4 + 2];
1092     d[(i >> 2) * 6 + 3] = s[i * 4 + 3];
1093   }
1094 }
1095
1096 #define PACK_ARGB64 GST_VIDEO_FORMAT_ARGB64, unpack_copy8, pack_copy8
1097 #define PACK_AYUV64 GST_VIDEO_FORMAT_AYUV64, unpack_copy8, pack_copy8
1098 static void
1099 unpack_copy8 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1100     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1101     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1102 {
1103   memcpy (dest, GET_LINE (y), width * 8);
1104 }
1105
1106 static void
1107 pack_copy8 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1108     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1109     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1110     gint y, gint width)
1111 {
1112   memcpy (GET_LINE (y), src, width * 8);
1113 }
1114
1115 #define PACK_r210 GST_VIDEO_FORMAT_AYUV64, unpack_r210, pack_r210
1116 static void
1117 unpack_r210 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1118     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1119     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1120 {
1121   int i;
1122   const guint8 *s = GET_LINE (y);
1123   guint16 *d = dest;
1124
1125   for (i = 0; i < width; i++) {
1126     guint32 x;
1127     d[i * 4 + 0] = 0xffff;
1128     x = GST_READ_UINT32_BE (s + i * 4);
1129     d[i * 4 + 1] = ((x >> 14) & 0xffc0) | (x >> 24);
1130     d[i * 4 + 2] = ((x >> 4) & 0xffc0) | ((x >> 14) & 0x3f);
1131     d[i * 4 + 3] = ((x << 6) & 0xffc0) | ((x >> 4) & 0x3f);
1132   }
1133 }
1134
1135 static void
1136 pack_r210 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1137     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1138     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1139     gint y, gint width)
1140 {
1141   int i;
1142   guint8 *d = GET_LINE (y);
1143   const guint16 *s = src;
1144
1145   for (i = 0; i < width; i++) {
1146     guint32 x = 0;
1147     x |= (s[i * 4 + 1] & 0xffc0) << 14;
1148     x |= (s[i * 4 + 2] & 0xffc0) << 4;
1149     x |= (s[i * 4 + 3] & 0xffc0) >> 6;
1150     GST_WRITE_UINT32_BE (d + i * 4, x);
1151   }
1152 }
1153
1154 #define PACK_I420_10LE GST_VIDEO_FORMAT_AYUV64, unpack_I420_10LE, pack_I420_10LE
1155 static void
1156 unpack_I420_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1157     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1158     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1159 {
1160   int i;
1161   guint16 *srcY = GET_Y_LINE (y);
1162   guint16 *srcU = GET_U_LINE (y >> 1);
1163   guint16 *srcV = GET_V_LINE (y >> 1);
1164   guint16 *d = dest;
1165
1166   for (i = 0; i < width; i++) {
1167     d[i * 4 + 0] = 0xffff;
1168     d[i * 4 + 1] = GST_READ_UINT16_LE (srcY + i) << 6;
1169     d[i * 4 + 2] = GST_READ_UINT16_LE (srcU + (i >> 1)) << 6;
1170     d[i * 4 + 3] = GST_READ_UINT16_LE (srcV + (i >> 1)) << 6;
1171   }
1172 }
1173
1174 static void
1175 pack_I420_10LE (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   int i;
1181   guint16 *destY = GET_Y_LINE (y);
1182   guint16 *destU = GET_U_LINE (y >> 1);
1183   guint16 *destV = GET_V_LINE (y >> 1);
1184   guint16 Y0, Y1, U, V;
1185   const guint16 *s = src;
1186
1187   for (i = 0; i < width - 1; i += 2) {
1188     Y0 = (s[i * 4 + 1]) >> 6;
1189     Y1 = (s[i * 4 + 5]) >> 6;
1190     U = ((s[i * 4 + 2] + s[i * 4 + 6] + 1) >> 1) >> 6;
1191     V = ((s[i * 4 + 3] + s[i * 4 + 7] + 1) >> 1) >> 6;
1192
1193     GST_WRITE_UINT16_LE (destY + i + 0, Y0);
1194     GST_WRITE_UINT16_LE (destY + i + 1, Y1);
1195     GST_WRITE_UINT16_LE (destU + (i >> 1), U);
1196     GST_WRITE_UINT16_LE (destV + (i >> 1), V);
1197   }
1198   if (i == width - 1) {
1199     Y0 = s[i * 4 + 1] >> 6;
1200     U = s[i * 4 + 2] >> 6;
1201     V = s[i * 4 + 3] >> 6;
1202
1203     GST_WRITE_UINT16_LE (destY + i, Y0);
1204     GST_WRITE_UINT16_LE (destU + (i >> 1), U);
1205     GST_WRITE_UINT16_LE (destV + (i >> 1), V);
1206   }
1207 }
1208
1209 #define PACK_I420_10BE GST_VIDEO_FORMAT_AYUV64, unpack_I420_10BE, pack_I420_10BE
1210 static void
1211 unpack_I420_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1212     gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
1213     const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
1214 {
1215   int i;
1216   guint16 *srcY = GET_Y_LINE (y);
1217   guint16 *srcU = GET_U_LINE (y >> 1);
1218   guint16 *srcV = GET_V_LINE (y >> 1);
1219   guint16 *d = dest;
1220
1221   for (i = 0; i < width; i++) {
1222     d[i * 4 + 0] = 0xffff;
1223     d[i * 4 + 1] = GST_READ_UINT16_BE (srcY + i) << 6;
1224     d[i * 4 + 2] = GST_READ_UINT16_BE (srcU + (i >> 1)) << 6;
1225     d[i * 4 + 3] = GST_READ_UINT16_BE (srcV + (i >> 1)) << 6;
1226   }
1227 }
1228
1229 static void
1230 pack_I420_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
1231     const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
1232     const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
1233     gint y, gint width)
1234 {
1235   int i;
1236   guint16 *destY = GET_Y_LINE (y);
1237   guint16 *destU = GET_U_LINE (y >> 1);
1238   guint16 *destV = GET_V_LINE (y >> 1);
1239   guint16 Y0, Y1, U, V;
1240   const guint16 *s = src;
1241
1242   for (i = 0; i < width - 1; i += 2) {
1243     Y0 = s[i * 4 + 1] >> 6;
1244     Y1 = s[i * 4 + 5] >> 6;
1245     U = ((s[i * 4 + 2] + s[i * 4 + 6] + 1) >> 1) >> 6;
1246     V = ((s[i * 4 + 3] + s[i * 4 + 7] + 1) >> 1) >> 6;
1247
1248     GST_WRITE_UINT16_BE (destY + i + 0, Y0);
1249     GST_WRITE_UINT16_BE (destY + i + 1, Y1);
1250     GST_WRITE_UINT16_BE (destU + (i >> 1), U);
1251     GST_WRITE_UINT16_BE (destV + (i >> 1), V);
1252   }
1253   if (i == width - 1) {
1254     Y0 = s[i * 4 + 1] >> 6;
1255     U = s[i * 4 + 2] >> 6;
1256     V = s[i * 4 + 3] >> 6;
1257
1258     GST_WRITE_UINT16_BE (destY + i, Y0);
1259     GST_WRITE_UINT16_BE (destU + (i >> 1), U);
1260     GST_WRITE_UINT16_BE (destV + (i >> 1), V);
1261   }
1262 }
1263
1264 typedef struct
1265 {
1266   guint32 fourcc;
1267   GstVideoFormatInfo info;
1268 } VideoFormat;
1269
1270 /* depths: bits, n_components, shift, depth */
1271 #define DPTH0            0, 0, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
1272 #define DPTH8            8, 1, { 0, 0, 0, 0 }, { 8, 0, 0, 0 }
1273 #define DPTH8_32         8, 2, { 0, 0, 0, 0 }, { 8, 32, 0, 0 }
1274 #define DPTH888          8, 3, { 0, 0, 0, 0 }, { 8, 8, 8, 0 }
1275 #define DPTH8888         8, 4, { 0, 0, 0, 0 }, { 8, 8, 8, 8 }
1276 #define DPTH10_10_10     10, 3, { 0, 0, 0, 0 }, { 10, 10, 10, 0 }
1277 #define DPTH16           16, 1, { 0, 0, 0, 0 }, { 16, 0, 0, 0 }
1278 #define DPTH16_16_16     16, 3, { 0, 0, 0, 0 }, { 16, 16, 16, 0 }
1279 #define DPTH16_16_16_16  16, 4, { 0, 0, 0, 0 }, { 16, 16, 16, 16 }
1280 #define DPTH555          16, 3, { 10, 5, 0, 0 }, { 5, 5, 5, 0 }
1281 #define DPTH565          16, 3, { 11, 5, 0, 0 }, { 5, 6, 5, 0 }
1282
1283 /* pixel strides */
1284 #define PSTR0             { 0, 0, 0, 0 }
1285 #define PSTR1             { 1, 0, 0, 0 }
1286 #define PSTR14            { 1, 4, 0, 0 }
1287 #define PSTR111           { 1, 1, 1, 0 }
1288 #define PSTR1111          { 1, 1, 1, 1 }
1289 #define PSTR122           { 1, 2, 2, 0 }
1290 #define PSTR2             { 2, 0, 0, 0 }
1291 #define PSTR222           { 2, 2, 2, 0 }
1292 #define PSTR244           { 2, 4, 4, 0 }
1293 #define PSTR444           { 4, 4, 4, 0 }
1294 #define PSTR4444          { 4, 4, 4, 4 }
1295 #define PSTR333           { 3, 3, 3, 0 }
1296 #define PSTR488           { 4, 8, 8, 0 }
1297 #define PSTR8888          { 8, 8, 8, 8 }
1298
1299 /* planes */
1300 #define PLANE_NA          0, { 0, 0, 0, 0 }
1301 #define PLANE0            1, { 0, 0, 0, 0 }
1302 #define PLANE01           2, { 0, 1, 0, 0 }
1303 #define PLANE011          2, { 0, 1, 1, 0 }
1304 #define PLANE012          3, { 0, 1, 2, 0 }
1305 #define PLANE0123         4, { 0, 1, 2, 3 }
1306 #define PLANE021          3, { 0, 2, 1, 0 }
1307
1308 /* offsets */
1309 #define OFFS0             { 0, 0, 0, 0 }
1310 #define OFFS013           { 0, 1, 3, 0 }
1311 #define OFFS102           { 1, 0, 2, 0 }
1312 #define OFFS1230          { 1, 2, 3, 0 }
1313 #define OFFS012           { 0, 1, 2, 0 }
1314 #define OFFS210           { 2, 1, 0, 0 }
1315 #define OFFS123           { 1, 2, 3, 0 }
1316 #define OFFS321           { 3, 2, 1, 0 }
1317 #define OFFS0123          { 0, 1, 2, 3 }
1318 #define OFFS2103          { 2, 1, 0, 3 }
1319 #define OFFS3210          { 3, 2, 1, 0 }
1320 #define OFFS031           { 0, 3, 1, 0 }
1321 #define OFFS204           { 2, 0, 4, 0 }
1322 #define OFFS001           { 0, 0, 1, 0 }
1323 #define OFFS010           { 0, 1, 0, 0 }
1324 #define OFFS104           { 1, 0, 4, 0 }
1325 #define OFFS2460          { 2, 4, 6, 0 }
1326
1327 /* subsampling */
1328 #define SUB410            { 0, 2, 2, 0 }, { 0, 2, 2, 0 }
1329 #define SUB411            { 0, 2, 2, 0 }, { 0, 0, 0, 0 }
1330 #define SUB420            { 0, 1, 1, 0 }, { 0, 1, 1, 0 }
1331 #define SUB422            { 0, 1, 1, 0 }, { 0, 0, 0, 0 }
1332 #define SUB4              { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
1333 #define SUB44             { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
1334 #define SUB444            { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
1335 #define SUB4444           { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
1336 #define SUB4204           { 0, 1, 1, 0 }, { 0, 1, 1, 0 }
1337
1338 #define MAKE_YUV_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub, pack ) \
1339  { fourcc, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_YUV, depth, pstride, plane, offs, sub, pack } }
1340 #define MAKE_YUV_LE_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub, pack ) \
1341  { 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 } }
1342 #define MAKE_YUVA_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub, pack) \
1343  { 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 } }
1344 #define MAKE_YUV_C_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub, pack) \
1345  { 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 } }
1346
1347 #define MAKE_RGB_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
1348  { 0x00000000, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_RGB, depth, pstride, plane, offs, sub, pack } }
1349 #define MAKE_RGB_LE_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
1350  { 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 } }
1351 #define MAKE_RGBA_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
1352  { 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 } }
1353 #define MAKE_RGBAP_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
1354  { 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 } }
1355
1356 #define MAKE_GRAY_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
1357  { 0x00000000, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_GRAY, depth, pstride, plane, offs, sub, pack } }
1358 #define MAKE_GRAY_LE_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \
1359  { 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 } }
1360
1361 static VideoFormat formats[] = {
1362   {0x00000000, {GST_VIDEO_FORMAT_UNKNOWN, "UNKNOWN", "unknown video", 0, DPTH0,
1363               PSTR0, PLANE_NA,
1364           OFFS0}},
1365   {0x00000000, {GST_VIDEO_FORMAT_ENCODED, "ENCODED", "encoded video",
1366           GST_VIDEO_FORMAT_FLAG_COMPLEX, DPTH0, PSTR0, PLANE_NA, OFFS0}},
1367
1368   MAKE_YUV_FORMAT (I420, "raw video", GST_MAKE_FOURCC ('I', '4', '2', '0'),
1369       DPTH888, PSTR111,
1370       PLANE012, OFFS0, SUB420, PACK_420),
1371   MAKE_YUV_FORMAT (YV12, "raw video", GST_MAKE_FOURCC ('Y', 'V', '1', '2'),
1372       DPTH888, PSTR111,
1373       PLANE021, OFFS0, SUB420, PACK_420),
1374   MAKE_YUV_FORMAT (YUY2, "raw video", GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'),
1375       DPTH888, PSTR244,
1376       PLANE0, OFFS013, SUB422, PACK_YUY2),
1377   MAKE_YUV_FORMAT (UYVY, "raw video", GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'),
1378       DPTH888, PSTR244,
1379       PLANE0, OFFS102, SUB422, PACK_UYVY),
1380   MAKE_YUVA_FORMAT (AYUV, "raw video", GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'),
1381       DPTH8888,
1382       PSTR4444, PLANE0, OFFS1230, SUB4444, PACK_AYUV),
1383   MAKE_RGB_FORMAT (RGBx, "raw video", DPTH888, PSTR444, PLANE0, OFFS012,
1384       SUB444, PACK_RGBA),
1385   MAKE_RGB_FORMAT (BGRx, "raw video", DPTH888, PSTR444, PLANE0, OFFS210,
1386       SUB444, PACK_BGRA),
1387   MAKE_RGB_FORMAT (xRGB, "raw video", DPTH888, PSTR444, PLANE0, OFFS123,
1388       SUB444, PACK_ARGB),
1389   MAKE_RGB_FORMAT (xBGR, "raw video", DPTH888, PSTR444, PLANE0, OFFS321,
1390       SUB444, PACK_ABGR),
1391   MAKE_RGBA_FORMAT (RGBA, "raw video", DPTH8888, PSTR4444, PLANE0, OFFS0123,
1392       SUB4444, PACK_RGBA),
1393   MAKE_RGBA_FORMAT (BGRA, "raw video", DPTH8888, PSTR4444, PLANE0, OFFS2103,
1394       SUB4444, PACK_BGRA),
1395   MAKE_RGBA_FORMAT (ARGB, "raw video", DPTH8888, PSTR4444, PLANE0, OFFS1230,
1396       SUB4444, PACK_ARGB),
1397   MAKE_RGBA_FORMAT (ABGR, "raw video", DPTH8888, PSTR4444, PLANE0, OFFS3210,
1398       SUB4444, PACK_ABGR),
1399   MAKE_RGB_FORMAT (RGB, "raw video", DPTH888, PSTR333, PLANE0, OFFS012, SUB444,
1400       PACK_RGB),
1401   MAKE_RGB_FORMAT (BGR, "raw video", DPTH888, PSTR333, PLANE0, OFFS210, SUB444,
1402       PACK_BGR),
1403
1404   MAKE_YUV_FORMAT (Y41B, "raw video", GST_MAKE_FOURCC ('Y', '4', '1', 'B'),
1405       DPTH888, PSTR111,
1406       PLANE012, OFFS0, SUB411, PACK_Y41B),
1407   MAKE_YUV_FORMAT (Y42B, "raw video", GST_MAKE_FOURCC ('Y', '4', '2', 'B'),
1408       DPTH888, PSTR111,
1409       PLANE012, OFFS0, SUB422, PACK_Y42B),
1410   MAKE_YUV_FORMAT (YVYU, "raw video", GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'),
1411       DPTH888, PSTR244,
1412       PLANE0, OFFS031, SUB422, PACK_YVYU),
1413   MAKE_YUV_FORMAT (Y444, "raw video", GST_MAKE_FOURCC ('Y', '4', '4', '4'),
1414       DPTH888, PSTR111,
1415       PLANE012, OFFS0, SUB444, PACK_Y444),
1416   MAKE_YUV_C_FORMAT (v210, "raw video", GST_MAKE_FOURCC ('v', '2', '1', '0'),
1417       DPTH10_10_10,
1418       PSTR0, PLANE0, OFFS0, SUB422, PACK_v210),
1419   MAKE_YUV_FORMAT (v216, "raw video", GST_MAKE_FOURCC ('v', '2', '1', '6'),
1420       DPTH16_16_16,
1421       PSTR488, PLANE0, OFFS204, SUB422, PACK_v216),
1422   MAKE_YUV_FORMAT (NV12, "raw video", GST_MAKE_FOURCC ('N', 'V', '1', '2'),
1423       DPTH888, PSTR122,
1424       PLANE011, OFFS001, SUB420, PACK_NV12),
1425   MAKE_YUV_FORMAT (NV21, "raw video", GST_MAKE_FOURCC ('N', 'V', '2', '1'),
1426       DPTH888, PSTR122,
1427       PLANE011, OFFS010, SUB420, PACK_NV21),
1428
1429   MAKE_GRAY_FORMAT (GRAY8, "raw video", DPTH8, PSTR1, PLANE0, OFFS0, SUB4,
1430       PACK_GRAY8),
1431   MAKE_GRAY_FORMAT (GRAY16_BE, "raw video", DPTH16, PSTR2, PLANE0, OFFS0, SUB4,
1432       PACK_GRAY16_BE),
1433   MAKE_GRAY_LE_FORMAT (GRAY16_LE, "raw video", DPTH16, PSTR2, PLANE0, OFFS0,
1434       SUB4, PACK_GRAY16_LE),
1435
1436   MAKE_YUV_FORMAT (v308, "raw video", GST_MAKE_FOURCC ('v', '3', '0', '8'),
1437       DPTH888, PSTR333,
1438       PLANE0, OFFS012, SUB444, PACK_v308),
1439
1440 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1441   MAKE_RGB_LE_FORMAT (RGB16, "raw video", DPTH565, PSTR222, PLANE0, OFFS0,
1442       SUB444, PACK_RGB16),
1443   MAKE_RGB_LE_FORMAT (BGR16, "raw video", DPTH565, PSTR222, PLANE0, OFFS0,
1444       SUB444, PACK_BGR16),
1445   MAKE_RGB_LE_FORMAT (RGB15, "raw video", DPTH555, PSTR222, PLANE0, OFFS0,
1446       SUB444, PACK_RGB15),
1447   MAKE_RGB_LE_FORMAT (BGR15, "raw video", DPTH555, PSTR222, PLANE0, OFFS0,
1448       SUB444, PACK_BGR15),
1449 #else
1450   MAKE_RGB_FORMAT (RGB16, "raw video", DPTH565, PSTR222, PLANE0, OFFS0, SUB444,
1451       PACK_RGB16),
1452   MAKE_RGB_FORMAT (BGR16, "raw video", DPTH565, PSTR222, PLANE0, OFFS0, SUB444,
1453       PACK_BGR16),
1454   MAKE_RGB_FORMAT (RGB15, "raw video", DPTH555, PSTR222, PLANE0, OFFS0, SUB444,
1455       PACK_RGB15),
1456   MAKE_RGB_FORMAT (BGR15, "raw video", DPTH555, PSTR222, PLANE0, OFFS0, SUB444,
1457       PACK_BGR15),
1458 #endif
1459
1460   MAKE_YUV_C_FORMAT (UYVP, "raw video", GST_MAKE_FOURCC ('U', 'Y', 'V', 'P'),
1461       DPTH10_10_10,
1462       PSTR0, PLANE0, OFFS0, SUB422, PACK_UYVP),
1463   MAKE_YUVA_FORMAT (A420, "raw video", GST_MAKE_FOURCC ('A', '4', '2', '0'),
1464       DPTH8888,
1465       PSTR1111, PLANE0123, OFFS0, SUB4204, PACK_A420),
1466   MAKE_RGBAP_FORMAT (RGB8P, "raw video", DPTH8_32, PSTR14, PLANE01,
1467       OFFS0, SUB44, PACK_RGB8P),
1468   MAKE_YUV_FORMAT (YUV9, "raw video", GST_MAKE_FOURCC ('Y', 'U', 'V', '9'),
1469       DPTH888, PSTR111,
1470       PLANE012, OFFS0, SUB410, PACK_410),
1471   MAKE_YUV_FORMAT (YVU9, "raw video", GST_MAKE_FOURCC ('Y', 'V', 'U', '9'),
1472       DPTH888, PSTR111,
1473       PLANE021, OFFS0, SUB410, PACK_410),
1474   MAKE_YUV_FORMAT (IYU1, "raw video", GST_MAKE_FOURCC ('I', 'Y', 'U', '1'),
1475       DPTH888, PSTR0,
1476       PLANE0, OFFS104, SUB411, PACK_IYU1),
1477   MAKE_RGBA_FORMAT (ARGB64, "raw video", DPTH16_16_16_16, PSTR8888, PLANE0,
1478       OFFS2460,
1479       SUB444, PACK_ARGB64),
1480   MAKE_YUVA_FORMAT (AYUV64, "raw video", 0x00000000, DPTH16_16_16_16, PSTR8888,
1481       PLANE0,
1482       OFFS2460, SUB444, PACK_AYUV64),
1483   MAKE_YUV_FORMAT (r210, "raw video", GST_MAKE_FOURCC ('r', '2', '1', '0'),
1484       DPTH10_10_10,
1485       PSTR444, PLANE0, OFFS0, SUB444, PACK_r210),
1486   MAKE_YUV_FORMAT (I420_10BE, "raw video", 0x00000000, DPTH10_10_10,
1487       PSTR222, PLANE012, OFFS0, SUB420, PACK_I420_10BE),
1488   MAKE_YUV_LE_FORMAT (I420_10LE, "raw video", 0x00000000, DPTH10_10_10,
1489       PSTR222, PLANE012, OFFS0, SUB420, PACK_I420_10LE),
1490 };
1491
1492 /**
1493  * gst_video_calculate_display_ratio:
1494  * @dar_n: Numerator of the calculated display_ratio
1495  * @dar_d: Denominator of the calculated display_ratio
1496  * @video_width: Width of the video frame in pixels
1497  * @video_height: Height of the video frame in pixels
1498  * @video_par_n: Numerator of the pixel aspect ratio of the input video.
1499  * @video_par_d: Denominator of the pixel aspect ratio of the input video.
1500  * @display_par_n: Numerator of the pixel aspect ratio of the display device
1501  * @display_par_d: Denominator of the pixel aspect ratio of the display device
1502  *
1503  * Given the Pixel Aspect Ratio and size of an input video frame, and the
1504  * pixel aspect ratio of the intended display device, calculates the actual
1505  * display ratio the video will be rendered with.
1506  *
1507  * Returns: A boolean indicating success and a calculated Display Ratio in the
1508  * dar_n and dar_d parameters.
1509  * The return value is FALSE in the case of integer overflow or other error.
1510  *
1511  * Since: 0.10.7
1512  */
1513 gboolean
1514 gst_video_calculate_display_ratio (guint * dar_n, guint * dar_d,
1515     guint video_width, guint video_height,
1516     guint video_par_n, guint video_par_d,
1517     guint display_par_n, guint display_par_d)
1518 {
1519   gint num, den;
1520   gint tmp_n, tmp_d;
1521
1522   g_return_val_if_fail (dar_n != NULL, FALSE);
1523   g_return_val_if_fail (dar_d != NULL, FALSE);
1524
1525   /* Calculate (video_width * video_par_n * display_par_d) /
1526    * (video_height * video_par_d * display_par_n) */
1527   if (!gst_util_fraction_multiply (video_width, video_height, video_par_n,
1528           video_par_d, &tmp_n, &tmp_d))
1529     goto error_overflow;
1530
1531   if (!gst_util_fraction_multiply (tmp_n, tmp_d, display_par_d, display_par_n,
1532           &num, &den))
1533     goto error_overflow;
1534
1535   g_return_val_if_fail (num > 0, FALSE);
1536   g_return_val_if_fail (den > 0, FALSE);
1537
1538   *dar_n = num;
1539   *dar_d = den;
1540
1541   return TRUE;
1542
1543   /* ERRORS */
1544 error_overflow:
1545   {
1546     GST_WARNING ("overflow in multiply");
1547     return FALSE;
1548   }
1549 }
1550
1551 static GstVideoFormat
1552 gst_video_format_from_rgb32_masks (int red_mask, int green_mask, int blue_mask)
1553 {
1554   if (red_mask == 0xff000000 && green_mask == 0x00ff0000 &&
1555       blue_mask == 0x0000ff00) {
1556     return GST_VIDEO_FORMAT_RGBx;
1557   }
1558   if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 &&
1559       blue_mask == 0xff000000) {
1560     return GST_VIDEO_FORMAT_BGRx;
1561   }
1562   if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 &&
1563       blue_mask == 0x000000ff) {
1564     return GST_VIDEO_FORMAT_xRGB;
1565   }
1566   if (red_mask == 0x000000ff && green_mask == 0x0000ff00 &&
1567       blue_mask == 0x00ff0000) {
1568     return GST_VIDEO_FORMAT_xBGR;
1569   }
1570
1571   return GST_VIDEO_FORMAT_UNKNOWN;
1572 }
1573
1574 static GstVideoFormat
1575 gst_video_format_from_rgba32_masks (int red_mask, int green_mask,
1576     int blue_mask, int alpha_mask)
1577 {
1578   if (red_mask == 0xff000000 && green_mask == 0x00ff0000 &&
1579       blue_mask == 0x0000ff00 && alpha_mask == 0x000000ff) {
1580     return GST_VIDEO_FORMAT_RGBA;
1581   }
1582   if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 &&
1583       blue_mask == 0xff000000 && alpha_mask == 0x000000ff) {
1584     return GST_VIDEO_FORMAT_BGRA;
1585   }
1586   if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 &&
1587       blue_mask == 0x000000ff && alpha_mask == 0xff000000) {
1588     return GST_VIDEO_FORMAT_ARGB;
1589   }
1590   if (red_mask == 0x000000ff && green_mask == 0x0000ff00 &&
1591       blue_mask == 0x00ff0000 && alpha_mask == 0xff000000) {
1592     return GST_VIDEO_FORMAT_ABGR;
1593   }
1594   return GST_VIDEO_FORMAT_UNKNOWN;
1595 }
1596
1597 static GstVideoFormat
1598 gst_video_format_from_rgb24_masks (int red_mask, int green_mask, int blue_mask)
1599 {
1600   if (red_mask == 0xff0000 && green_mask == 0x00ff00 && blue_mask == 0x0000ff) {
1601     return GST_VIDEO_FORMAT_RGB;
1602   }
1603   if (red_mask == 0x0000ff && green_mask == 0x00ff00 && blue_mask == 0xff0000) {
1604     return GST_VIDEO_FORMAT_BGR;
1605   }
1606
1607   return GST_VIDEO_FORMAT_UNKNOWN;
1608 }
1609
1610 #define GST_VIDEO_COMP1_MASK_16_INT 0xf800
1611 #define GST_VIDEO_COMP2_MASK_16_INT 0x07e0
1612 #define GST_VIDEO_COMP3_MASK_16_INT 0x001f
1613
1614 #define GST_VIDEO_COMP1_MASK_15_INT 0x7c00
1615 #define GST_VIDEO_COMP2_MASK_15_INT 0x03e0
1616 #define GST_VIDEO_COMP3_MASK_15_INT 0x001f
1617
1618 static GstVideoFormat
1619 gst_video_format_from_rgb16_masks (int red_mask, int green_mask, int blue_mask)
1620 {
1621   if (red_mask == GST_VIDEO_COMP1_MASK_16_INT
1622       && green_mask == GST_VIDEO_COMP2_MASK_16_INT
1623       && blue_mask == GST_VIDEO_COMP3_MASK_16_INT) {
1624     return GST_VIDEO_FORMAT_RGB16;
1625   }
1626   if (red_mask == GST_VIDEO_COMP3_MASK_16_INT
1627       && green_mask == GST_VIDEO_COMP2_MASK_16_INT
1628       && blue_mask == GST_VIDEO_COMP1_MASK_16_INT) {
1629     return GST_VIDEO_FORMAT_BGR16;
1630   }
1631   if (red_mask == GST_VIDEO_COMP1_MASK_15_INT
1632       && green_mask == GST_VIDEO_COMP2_MASK_15_INT
1633       && blue_mask == GST_VIDEO_COMP3_MASK_15_INT) {
1634     return GST_VIDEO_FORMAT_RGB15;
1635   }
1636   if (red_mask == GST_VIDEO_COMP3_MASK_15_INT
1637       && green_mask == GST_VIDEO_COMP2_MASK_15_INT
1638       && blue_mask == GST_VIDEO_COMP1_MASK_15_INT) {
1639     return GST_VIDEO_FORMAT_BGR15;
1640   }
1641   return GST_VIDEO_FORMAT_UNKNOWN;
1642 }
1643
1644 /**
1645  * gst_video_format_from_masks:
1646  * @depth: the amount of bits used for a pixel
1647  * @bpp: the amount of bits used to store a pixel. This value is bigger than
1648  *   @depth
1649  * @endianness: the endianness of the masks
1650  * @red_mask: the red mask
1651  * @green_mask: the green mask
1652  * @blue_mask: the blue mask
1653  * @alpha_mask: the optional alpha mask
1654  *
1655  * Find the #GstVideoFormat for the given parameters.
1656  *
1657  * Returns: a #GstVideoFormat or GST_VIDEO_FORMAT_UNKNOWN when the parameters to
1658  * not specify a known format.
1659  */
1660 GstVideoFormat
1661 gst_video_format_from_masks (gint depth, gint bpp, gint endianness,
1662     gint red_mask, gint green_mask, gint blue_mask, gint alpha_mask)
1663 {
1664   GstVideoFormat format;
1665
1666   /* our caps system handles 24/32bpp RGB as big-endian. */
1667   if ((bpp == 24 || bpp == 32) && endianness == G_LITTLE_ENDIAN) {
1668     red_mask = GUINT32_TO_BE (red_mask);
1669     green_mask = GUINT32_TO_BE (green_mask);
1670     blue_mask = GUINT32_TO_BE (blue_mask);
1671     endianness = G_BIG_ENDIAN;
1672     if (bpp == 24) {
1673       red_mask >>= 8;
1674       green_mask >>= 8;
1675       blue_mask >>= 8;
1676     }
1677   }
1678
1679   if (depth == 30 && bpp == 32) {
1680     format = GST_VIDEO_FORMAT_r210;
1681   } else if (depth == 24 && bpp == 32) {
1682     format = gst_video_format_from_rgb32_masks (red_mask, green_mask,
1683         blue_mask);
1684   } else if (depth == 32 && bpp == 32 && alpha_mask) {
1685     format = gst_video_format_from_rgba32_masks (red_mask, green_mask,
1686         blue_mask, alpha_mask);
1687   } else if (depth == 24 && bpp == 24) {
1688     format = gst_video_format_from_rgb24_masks (red_mask, green_mask,
1689         blue_mask);
1690   } else if ((depth == 15 || depth == 16) && bpp == 16 &&
1691       endianness == G_BYTE_ORDER) {
1692     format = gst_video_format_from_rgb16_masks (red_mask, green_mask,
1693         blue_mask);
1694   } else if (depth == 8 && bpp == 8) {
1695     format = GST_VIDEO_FORMAT_RGB8P;
1696   } else if (depth == 64 && bpp == 64) {
1697     format = gst_video_format_from_rgba32_masks (red_mask, green_mask,
1698         blue_mask, alpha_mask);
1699     if (format == GST_VIDEO_FORMAT_ARGB) {
1700       format = GST_VIDEO_FORMAT_ARGB64;
1701     } else {
1702       format = GST_VIDEO_FORMAT_UNKNOWN;
1703     }
1704   } else {
1705     format = GST_VIDEO_FORMAT_UNKNOWN;
1706   }
1707   return format;
1708 }
1709
1710 /**
1711  * gst_video_format_from_fourcc:
1712  * @fourcc: a FOURCC value representing raw YUV video
1713  *
1714  * Converts a FOURCC value into the corresponding #GstVideoFormat.
1715  * If the FOURCC cannot be represented by #GstVideoFormat,
1716  * #GST_VIDEO_FORMAT_UNKNOWN is returned.
1717  *
1718  * Since: 0.10.16
1719  *
1720  * Returns: the #GstVideoFormat describing the FOURCC value
1721  */
1722 GstVideoFormat
1723 gst_video_format_from_fourcc (guint32 fourcc)
1724 {
1725   switch (fourcc) {
1726     case GST_MAKE_FOURCC ('I', '4', '2', '0'):
1727       return GST_VIDEO_FORMAT_I420;
1728     case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
1729       return GST_VIDEO_FORMAT_YV12;
1730     case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
1731       return GST_VIDEO_FORMAT_YUY2;
1732     case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'):
1733       return GST_VIDEO_FORMAT_YVYU;
1734     case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
1735       return GST_VIDEO_FORMAT_UYVY;
1736     case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'):
1737       return GST_VIDEO_FORMAT_AYUV;
1738     case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
1739       return GST_VIDEO_FORMAT_Y41B;
1740     case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
1741       return GST_VIDEO_FORMAT_Y42B;
1742     case GST_MAKE_FOURCC ('Y', '4', '4', '4'):
1743       return GST_VIDEO_FORMAT_Y444;
1744     case GST_MAKE_FOURCC ('v', '2', '1', '0'):
1745       return GST_VIDEO_FORMAT_v210;
1746     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
1747       return GST_VIDEO_FORMAT_v216;
1748     case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
1749       return GST_VIDEO_FORMAT_NV12;
1750     case GST_MAKE_FOURCC ('N', 'V', '2', '1'):
1751       return GST_VIDEO_FORMAT_NV21;
1752     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
1753       return GST_VIDEO_FORMAT_v308;
1754     case GST_MAKE_FOURCC ('Y', '8', '0', '0'):
1755     case GST_MAKE_FOURCC ('Y', '8', ' ', ' '):
1756     case GST_MAKE_FOURCC ('G', 'R', 'E', 'Y'):
1757       return GST_VIDEO_FORMAT_GRAY8;
1758     case GST_MAKE_FOURCC ('Y', '1', '6', ' '):
1759       return GST_VIDEO_FORMAT_GRAY16_LE;
1760     case GST_MAKE_FOURCC ('U', 'Y', 'V', 'P'):
1761       return GST_VIDEO_FORMAT_UYVP;
1762     case GST_MAKE_FOURCC ('A', '4', '2', '0'):
1763       return GST_VIDEO_FORMAT_A420;
1764     case GST_MAKE_FOURCC ('Y', 'U', 'V', '9'):
1765       return GST_VIDEO_FORMAT_YUV9;
1766     case GST_MAKE_FOURCC ('Y', 'V', 'U', '9'):
1767       return GST_VIDEO_FORMAT_YVU9;
1768     case GST_MAKE_FOURCC ('I', 'Y', 'U', '1'):
1769       return GST_VIDEO_FORMAT_IYU1;
1770     case GST_MAKE_FOURCC ('A', 'Y', '6', '4'):
1771       return GST_VIDEO_FORMAT_AYUV64;
1772     default:
1773       return GST_VIDEO_FORMAT_UNKNOWN;
1774   }
1775 }
1776
1777 /**
1778  * gst_video_format_from_string:
1779  * @format: a format string
1780  *
1781  * Convert the @format string to its #GstVideoFormat.
1782  *
1783  * Returns: the #GstVideoFormat for @format or GST_VIDEO_FORMAT_UNKNOWN when the
1784  * string is not a known format.
1785  */
1786 GstVideoFormat
1787 gst_video_format_from_string (const gchar * format)
1788 {
1789   guint i;
1790
1791   g_return_val_if_fail (format != NULL, GST_VIDEO_FORMAT_UNKNOWN);
1792
1793   for (i = 0; i < G_N_ELEMENTS (formats); i++) {
1794     if (strcmp (GST_VIDEO_FORMAT_INFO_NAME (&formats[i].info), format) == 0)
1795       return GST_VIDEO_FORMAT_INFO_FORMAT (&formats[i].info);
1796   }
1797   return GST_VIDEO_FORMAT_UNKNOWN;
1798 }
1799
1800
1801 /**
1802  * gst_video_format_to_fourcc:
1803  * @format: a #GstVideoFormat video format
1804  *
1805  * Converts a #GstVideoFormat value into the corresponding FOURCC.  Only
1806  * a few YUV formats have corresponding FOURCC values.  If @format has
1807  * no corresponding FOURCC value, 0 is returned.
1808  *
1809  * Since: 0.10.16
1810  *
1811  * Returns: the FOURCC corresponding to @format
1812  */
1813 guint32
1814 gst_video_format_to_fourcc (GstVideoFormat format)
1815 {
1816   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1817
1818   if (format >= G_N_ELEMENTS (formats))
1819     return 0;
1820
1821   return formats[format].fourcc;
1822 }
1823
1824 const gchar *
1825 gst_video_format_to_string (GstVideoFormat format)
1826 {
1827   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
1828
1829   if (format >= G_N_ELEMENTS (formats))
1830     return NULL;
1831
1832   return GST_VIDEO_FORMAT_INFO_NAME (&formats[format].info);
1833 }
1834
1835 /**
1836  * gst_video_format_get_info:
1837  * @format: a #GstVideoFormat
1838  *
1839  * Get the #GstVideoFormatInfo for @format
1840  *
1841  * Returns: The #GstVideoFormatInfo for @format.
1842  */
1843 const GstVideoFormatInfo *
1844 gst_video_format_get_info (GstVideoFormat format)
1845 {
1846   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
1847   g_return_val_if_fail (format < G_N_ELEMENTS (formats), NULL);
1848
1849   return &formats[format].info;
1850 }
1851
1852 typedef struct
1853 {
1854   const gchar *name;
1855   GstVideoColorimetry color;
1856 } ColorimetryInfo;
1857
1858 #define MAKE_COLORIMETRY(n,r,m,t,p) { GST_VIDEO_COLORIMETRY_ ##n, \
1859   { GST_VIDEO_COLOR_RANGE ##r, GST_VIDEO_COLOR_MATRIX_ ##m, \
1860   GST_VIDEO_TRANSFER_ ##t, GST_VIDEO_COLOR_PRIMARIES_ ##p } }
1861
1862 #define GST_VIDEO_COLORIMETRY_NONAME  ""
1863
1864 #define DEFAULT_YUV_SD 0
1865 #define DEFAULT_YUV_HD 1
1866 #define DEFAULT_RGB    3
1867 #define DEFAULT_GRAY   4
1868
1869 static const ColorimetryInfo colorimetry[] = {
1870   MAKE_COLORIMETRY (BT601, _16_235, BT601, BT709, BT470M),
1871   MAKE_COLORIMETRY (BT709, _16_235, BT709, BT709, BT709),
1872   MAKE_COLORIMETRY (SMPTE240M, _16_235, SMPTE240M, SMPTE240M, SMPTE240M),
1873   MAKE_COLORIMETRY (NONAME, _0_255, RGB, UNKNOWN, UNKNOWN),
1874   MAKE_COLORIMETRY (NONAME, _0_255, BT601, UNKNOWN, UNKNOWN),
1875 };
1876
1877 /**
1878  * gst_video_info_init:
1879  * @info: a #GstVideoInfo
1880  *
1881  * Initialize @info with default values.
1882  */
1883 void
1884 gst_video_info_init (GstVideoInfo * info)
1885 {
1886   g_return_if_fail (info != NULL);
1887
1888   memset (info, 0, sizeof (GstVideoInfo));
1889
1890   info->finfo = &formats[GST_VIDEO_FORMAT_UNKNOWN].info;
1891
1892   info->views = 1;
1893   /* arrange for sensible defaults, e.g. if turned into caps */
1894   info->fps_n = 0;
1895   info->fps_d = 1;
1896   info->par_n = 1;
1897   info->par_d = 1;
1898 }
1899
1900 /**
1901  * gst_video_info_set_format:
1902  * @info: a #GstVideoInfo
1903  * @format: the format
1904  * @width: a width
1905  * @height: a height
1906  *
1907  * Set the default info for a video frame of @format and @width and @height.
1908  */
1909 void
1910 gst_video_info_set_format (GstVideoInfo * info, GstVideoFormat format,
1911     guint width, guint height)
1912 {
1913   const GstVideoFormatInfo *finfo;
1914
1915   g_return_if_fail (info != NULL);
1916   g_return_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN);
1917
1918   finfo = &formats[format].info;
1919
1920   info->flags = 0;
1921   info->finfo = finfo;
1922   info->width = width;
1923   info->height = height;
1924
1925   if (GST_VIDEO_FORMAT_INFO_IS_YUV (finfo)) {
1926     if (height > 576)
1927       info->colorimetry = colorimetry[DEFAULT_YUV_HD].color;
1928     else
1929       info->colorimetry = colorimetry[DEFAULT_YUV_SD].color;
1930   } else if (GST_VIDEO_FORMAT_INFO_IS_GRAY (finfo)) {
1931     info->colorimetry = colorimetry[DEFAULT_GRAY].color;
1932   } else {
1933     info->colorimetry = colorimetry[DEFAULT_RGB].color;
1934   }
1935
1936   fill_planes (info);
1937 }
1938
1939 static const gchar *interlace_mode[] = {
1940   "progressive",
1941   "interleaved",
1942   "mixed",
1943   "fields"
1944 };
1945
1946 static const gchar *
1947 gst_interlace_mode_to_string (GstVideoInterlaceMode mode)
1948 {
1949   if (((guint) mode) >= G_N_ELEMENTS (interlace_mode))
1950     return NULL;
1951
1952   return interlace_mode[mode];
1953 }
1954
1955 static GstVideoInterlaceMode
1956 gst_interlace_mode_from_string (const gchar * mode)
1957 {
1958   gint i;
1959   for (i = 0; i < G_N_ELEMENTS (interlace_mode); i++) {
1960     if (g_str_equal (interlace_mode[i], mode))
1961       return i;
1962   }
1963   return GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
1964 }
1965
1966 typedef struct
1967 {
1968   const gchar *name;
1969   GstVideoChromaSite site;
1970 } ChromaSiteInfo;
1971
1972 static const ChromaSiteInfo chromasite[] = {
1973   {"jpeg", GST_VIDEO_CHROMA_SITE_JPEG},
1974   {"mpeg2", GST_VIDEO_CHROMA_SITE_MPEG2},
1975   {"dv", GST_VIDEO_CHROMA_SITE_DV}
1976 };
1977
1978 static GstVideoChromaSite
1979 gst_video_chroma_from_string (const gchar * s)
1980 {
1981   gint i;
1982   for (i = 0; i < G_N_ELEMENTS (chromasite); i++) {
1983     if (g_str_equal (chromasite[i].name, s))
1984       return chromasite[i].site;
1985   }
1986   return GST_VIDEO_CHROMA_SITE_UNKNOWN;
1987 }
1988
1989 static const gchar *
1990 gst_video_chroma_to_string (GstVideoChromaSite site)
1991 {
1992   gint i;
1993   for (i = 0; i < G_N_ELEMENTS (chromasite); i++) {
1994     if (chromasite[i].site == site)
1995       return chromasite[i].name;
1996   }
1997   return NULL;
1998 }
1999
2000 static const ColorimetryInfo *
2001 gst_video_get_colorimetry (const gchar * s)
2002 {
2003   gint i;
2004
2005   for (i = 0; i < G_N_ELEMENTS (colorimetry); i++) {
2006     if (g_str_equal (colorimetry[i].name, s))
2007       return &colorimetry[i];
2008   }
2009   return NULL;
2010 }
2011
2012 #define IS_EQUAL(ci,i) (((ci)->color.range == (i)->range) && \
2013                         ((ci)->color.matrix == (i)->matrix) && \
2014                         ((ci)->color.transfer == (i)->transfer) && \
2015                         ((ci)->color.primaries == (i)->primaries))
2016
2017
2018 /**
2019  * gst_video_colorimetry_from_string
2020  * @cinfo: a #GstVideoColorimetry
2021  * @color: a colorimetry string
2022  *
2023  * Parse the colorimetry string and update @cinfo with the parsed
2024  * values.
2025  *
2026  * Returns: #TRUE if @color points to valid colorimetry info.
2027  */
2028 gboolean
2029 gst_video_colorimetry_from_string (GstVideoColorimetry * cinfo,
2030     const gchar * color)
2031 {
2032   const ColorimetryInfo *ci;
2033
2034   if ((ci = gst_video_get_colorimetry (color))) {
2035     *cinfo = ci->color;
2036   } else {
2037     /* FIXME, split and parse */
2038     cinfo->range = GST_VIDEO_COLOR_RANGE_16_235;
2039     cinfo->matrix = GST_VIDEO_COLOR_MATRIX_BT601;
2040     cinfo->transfer = GST_VIDEO_TRANSFER_BT709;
2041     cinfo->primaries = GST_VIDEO_COLOR_PRIMARIES_BT709;
2042   }
2043   return TRUE;
2044 }
2045
2046 static void
2047 gst_video_caps_set_colorimetry (GstCaps * caps, GstVideoColorimetry * cinfo)
2048 {
2049   gint i;
2050
2051   for (i = 0; i < G_N_ELEMENTS (colorimetry); i++) {
2052     if (IS_EQUAL (&colorimetry[i], cinfo)) {
2053       gst_caps_set_simple (caps, "colorimetry", G_TYPE_STRING,
2054           colorimetry[i].name, NULL);
2055       return;
2056     }
2057   }
2058   /* FIXME, construct colorimetry */
2059 }
2060
2061 /**
2062  * gst_video_colorimetry_matches:
2063  * @info: a #GstVideoInfo
2064  * @color: a colorimetry string
2065  *
2066  * Check if the colorimetry information in @info matches that of the
2067  * string @color.
2068  *
2069  * Returns: #TRUE if @color conveys the same colorimetry info as the color
2070  * information in @info.
2071  */
2072 gboolean
2073 gst_video_colorimetry_matches (GstVideoColorimetry * cinfo, const gchar * color)
2074 {
2075   const ColorimetryInfo *ci;
2076
2077   if ((ci = gst_video_get_colorimetry (color)))
2078     return IS_EQUAL (ci, cinfo);
2079
2080   return FALSE;
2081 }
2082
2083 /**
2084  * gst_video_info_from_caps:
2085  * @info: a #GstVideoInfo
2086  * @caps: a #GstCaps
2087  *
2088  * Parse @caps and update @info.
2089  *
2090  * Returns: TRUE if @caps could be parsed
2091  */
2092 gboolean
2093 gst_video_info_from_caps (GstVideoInfo * info, const GstCaps * caps)
2094 {
2095   GstStructure *structure;
2096   const gchar *s;
2097   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
2098   gint width = 0, height = 0, views;
2099   gint fps_n, fps_d;
2100   gint par_n, par_d;
2101
2102   g_return_val_if_fail (info != NULL, FALSE);
2103   g_return_val_if_fail (caps != NULL, FALSE);
2104   g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
2105
2106   GST_DEBUG ("parsing caps %" GST_PTR_FORMAT, caps);
2107
2108   structure = gst_caps_get_structure (caps, 0);
2109
2110   if (gst_structure_has_name (structure, "video/x-raw")) {
2111     if (!(s = gst_structure_get_string (structure, "format")))
2112       goto no_format;
2113
2114     format = gst_video_format_from_string (s);
2115     if (format == GST_VIDEO_FORMAT_UNKNOWN)
2116       goto unknown_format;
2117
2118   } else if (g_str_has_prefix (gst_structure_get_name (structure), "video/") ||
2119       g_str_has_prefix (gst_structure_get_name (structure), "image/")) {
2120     format = GST_VIDEO_FORMAT_ENCODED;
2121   } else {
2122     goto wrong_name;
2123   }
2124
2125   /* width and height are mandatory, except for non-raw-formats */
2126   if (!gst_structure_get_int (structure, "width", &width) &&
2127       format != GST_VIDEO_FORMAT_ENCODED)
2128     goto no_width;
2129   if (!gst_structure_get_int (structure, "height", &height) &&
2130       format != GST_VIDEO_FORMAT_ENCODED)
2131     goto no_height;
2132
2133   gst_video_info_set_format (info, format, width, height);
2134
2135   if (gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d)) {
2136     if (fps_n == 0) {
2137       /* variable framerate */
2138       info->flags |= GST_VIDEO_FLAG_VARIABLE_FPS;
2139       /* see if we have a max-framerate */
2140       gst_structure_get_fraction (structure, "max-framerate", &fps_n, &fps_d);
2141     }
2142     info->fps_n = fps_n;
2143     info->fps_d = fps_d;
2144   } else {
2145     /* unspecified is variable framerate */
2146     info->fps_n = 0;
2147     info->fps_d = 1;
2148   }
2149
2150   if ((s = gst_structure_get_string (structure, "interlace-mode")))
2151     info->interlace_mode = gst_interlace_mode_from_string (s);
2152   else
2153     info->interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
2154
2155   if (gst_structure_get_int (structure, "views", &views))
2156     info->views = views;
2157   else
2158     info->views = 1;
2159
2160   if ((s = gst_structure_get_string (structure, "chroma-site")))
2161     info->chroma_site = gst_video_chroma_from_string (s);
2162   else
2163     info->chroma_site = GST_VIDEO_CHROMA_SITE_UNKNOWN;
2164
2165   if ((s = gst_structure_get_string (structure, "colorimetry")))
2166     gst_video_colorimetry_from_string (&info->colorimetry, s);
2167
2168   if (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
2169           &par_n, &par_d)) {
2170     info->par_n = par_n;
2171     info->par_d = par_d;
2172   } else {
2173     info->par_n = 1;
2174     info->par_d = 1;
2175   }
2176   return TRUE;
2177
2178   /* ERROR */
2179 wrong_name:
2180   {
2181     GST_ERROR ("wrong name '%s', expected video/ or image/",
2182         gst_structure_get_name (structure));
2183     return FALSE;
2184   }
2185 no_format:
2186   {
2187     GST_ERROR ("no format given");
2188     return FALSE;
2189   }
2190 unknown_format:
2191   {
2192     GST_ERROR ("unknown format '%s' given", s);
2193     return FALSE;
2194   }
2195 no_width:
2196   {
2197     GST_ERROR ("no width property given");
2198     return FALSE;
2199   }
2200 no_height:
2201   {
2202     GST_ERROR ("no height property given");
2203     return FALSE;
2204   }
2205 }
2206
2207 /**
2208  * gst_video_info_is_equal:
2209  * @info: a #GstVideoInfo
2210  * @other: a #GstVideoInfo
2211  *
2212  * Compares two #GstVideoInfo and returns whether they are equal or not
2213  *
2214  * Returns: %TRUE if @info and @other are equal, else %FALSE.
2215  */
2216 gboolean
2217 gst_video_info_is_equal (const GstVideoInfo * info, const GstVideoInfo * other)
2218 {
2219   if (GST_VIDEO_INFO_FORMAT (info) != GST_VIDEO_INFO_FORMAT (other))
2220     return FALSE;
2221   if (GST_VIDEO_INFO_INTERLACE_MODE (info) !=
2222       GST_VIDEO_INFO_INTERLACE_MODE (other))
2223     return FALSE;
2224   if (GST_VIDEO_INFO_FLAGS (info) != GST_VIDEO_INFO_FLAGS (other))
2225     return FALSE;
2226   if (GST_VIDEO_INFO_WIDTH (info) != GST_VIDEO_INFO_WIDTH (other))
2227     return FALSE;
2228   if (GST_VIDEO_INFO_HEIGHT (info) != GST_VIDEO_INFO_HEIGHT (other))
2229     return FALSE;
2230   if (GST_VIDEO_INFO_SIZE (info) != GST_VIDEO_INFO_SIZE (other))
2231     return FALSE;
2232   if (GST_VIDEO_INFO_PAR_N (info) != GST_VIDEO_INFO_PAR_N (other))
2233     return FALSE;
2234   if (GST_VIDEO_INFO_PAR_D (info) != GST_VIDEO_INFO_PAR_D (other))
2235     return FALSE;
2236   if (GST_VIDEO_INFO_FPS_N (info) != GST_VIDEO_INFO_FPS_N (other))
2237     return FALSE;
2238   if (GST_VIDEO_INFO_FPS_D (info) != GST_VIDEO_INFO_FPS_D (other))
2239     return FALSE;
2240   return TRUE;
2241 }
2242
2243 /**
2244  * gst_video_info_to_caps:
2245  * @info: a #GstVideoInfo
2246  *
2247  * Convert the values of @info into a #GstCaps.
2248  *
2249  * Returns: a new #GstCaps containing the info of @info.
2250  */
2251 GstCaps *
2252 gst_video_info_to_caps (GstVideoInfo * info)
2253 {
2254   GstCaps *caps;
2255   const gchar *format;
2256
2257   g_return_val_if_fail (info != NULL, NULL);
2258   g_return_val_if_fail (info->finfo != NULL, NULL);
2259   g_return_val_if_fail (info->finfo->format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
2260
2261   format = gst_video_format_to_string (info->finfo->format);
2262   g_return_val_if_fail (format != NULL, NULL);
2263
2264   caps = gst_caps_new_simple ("video/x-raw",
2265       "format", G_TYPE_STRING, format,
2266       "width", G_TYPE_INT, info->width,
2267       "height", G_TYPE_INT, info->height,
2268       "pixel-aspect-ratio", GST_TYPE_FRACTION, info->par_n, info->par_d, NULL);
2269
2270   gst_caps_set_simple (caps, "interlace-mode", G_TYPE_STRING,
2271       gst_interlace_mode_to_string (info->interlace_mode), NULL);
2272
2273   if (info->chroma_site != GST_VIDEO_CHROMA_SITE_UNKNOWN)
2274     gst_caps_set_simple (caps, "chroma-site", G_TYPE_STRING,
2275         gst_video_chroma_to_string (info->chroma_site), NULL);
2276
2277   gst_video_caps_set_colorimetry (caps, &info->colorimetry);
2278
2279   if (info->views > 1)
2280     gst_caps_set_simple (caps, "views", G_TYPE_INT, info->views, NULL);
2281
2282   if (info->flags & GST_VIDEO_FLAG_VARIABLE_FPS && info->fps_n != 0) {
2283     /* variable fps with a max-framerate */
2284     gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, 0, 1,
2285         "max-framerate", GST_TYPE_FRACTION, info->fps_n, info->fps_d, NULL);
2286   } else {
2287     /* no variable fps or no max-framerate */
2288     gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION,
2289         info->fps_n, info->fps_d, NULL);
2290   }
2291
2292   return caps;
2293 }
2294
2295 /**
2296  * gst_video_frame_map_id:
2297  * @frame: pointer to #GstVideoFrame
2298  * @info: a #GstVideoInfo
2299  * @buffer: the buffer to map
2300  * @id: the frame id to map
2301  * @flags: #GstMapFlags
2302  *
2303  * Use @info and @buffer to fill in the values of @frame with the video frame
2304  * information of frame @id.
2305  *
2306  * When @id is -1, the default frame is mapped. When @id != -1, this function
2307  * will return %FALSE when there is no GstVideoMeta with that id.
2308  *
2309  * All video planes of @buffer will be mapped and the pointers will be set in
2310  * @frame->data.
2311  *
2312  * Returns: %TRUE on success.
2313  */
2314 gboolean
2315 gst_video_frame_map_id (GstVideoFrame * frame, GstVideoInfo * info,
2316     GstBuffer * buffer, gint id, GstMapFlags flags)
2317 {
2318   GstVideoMeta *meta;
2319   gint i;
2320
2321   g_return_val_if_fail (frame != NULL, FALSE);
2322   g_return_val_if_fail (info != NULL, FALSE);
2323   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
2324
2325   if (id == -1)
2326     meta = gst_buffer_get_video_meta (buffer);
2327   else
2328     meta = gst_buffer_get_video_meta_id (buffer, id);
2329
2330   /* copy the info */
2331   frame->info = *info;
2332
2333   if (meta) {
2334     frame->info.finfo = &formats[meta->format].info;
2335     frame->info.width = meta->width;
2336     frame->info.height = meta->height;
2337     frame->id = meta->id;
2338     frame->flags = meta->flags;
2339
2340     for (i = 0; i < info->finfo->n_planes; i++)
2341       gst_video_meta_map (meta, i, &frame->map[i], &frame->data[i],
2342           &frame->info.stride[i], flags);
2343   } else {
2344     /* no metadata, we really need to have the metadata when the id is
2345      * specified. */
2346     if (id != -1)
2347       goto no_metadata;
2348
2349     frame->id = id;
2350     frame->flags = 0;
2351
2352     if (GST_VIDEO_INFO_IS_INTERLACED (info)) {
2353       if (GST_BUFFER_FLAG_IS_SET (buffer, GST_VIDEO_BUFFER_FLAG_TFF))
2354         frame->flags |= GST_VIDEO_FRAME_FLAG_TFF;
2355       if (GST_BUFFER_FLAG_IS_SET (buffer, GST_VIDEO_BUFFER_FLAG_RFF))
2356         frame->flags |= GST_VIDEO_FRAME_FLAG_RFF;
2357       if (GST_BUFFER_FLAG_IS_SET (buffer, GST_VIDEO_BUFFER_FLAG_ONEFIELD))
2358         frame->flags |= GST_VIDEO_FRAME_FLAG_ONEFIELD;
2359     }
2360
2361     gst_buffer_map (buffer, &frame->map[0], flags);
2362
2363     /* do some sanity checks */
2364     if (frame->map[0].size < info->size)
2365       goto invalid_size;
2366
2367     /* set up pointers */
2368     for (i = 0; i < info->finfo->n_planes; i++) {
2369       frame->data[i] = frame->map[0].data + info->offset[i];
2370     }
2371   }
2372   frame->buffer = gst_buffer_ref (buffer);
2373   frame->meta = meta;
2374
2375   return TRUE;
2376
2377   /* ERRORS */
2378 no_metadata:
2379   {
2380     GST_ERROR ("no GstVideoMeta for id %d", id);
2381     return FALSE;
2382   }
2383 invalid_size:
2384   {
2385     GST_ERROR ("invalid buffer size %" G_GSIZE_FORMAT " < %" G_GSIZE_FORMAT,
2386         frame->map[0].size, info->size);
2387     gst_buffer_unmap (buffer, &frame->map[0]);
2388     return FALSE;
2389   }
2390 }
2391
2392 /**
2393  * gst_video_frame_map:
2394  * @frame: pointer to #GstVideoFrame
2395  * @info: a #GstVideoInfo
2396  * @buffer: the buffer to map
2397  * @flags: #GstMapFlags
2398  *
2399  * Use @info and @buffer to fill in the values of @frame.
2400  *
2401  * All video planes of @buffer will be mapped and the pointers will be set in
2402  * @frame->data.
2403  *
2404  * Returns: %TRUE on success.
2405  */
2406 gboolean
2407 gst_video_frame_map (GstVideoFrame * frame, GstVideoInfo * info,
2408     GstBuffer * buffer, GstMapFlags flags)
2409 {
2410   return gst_video_frame_map_id (frame, info, buffer, -1, flags);
2411 }
2412
2413 /**
2414  * gst_video_frame_unmap:
2415  * @frame: a #GstVideoFrame
2416  *
2417  * Unmap the memory previously mapped with gst_video_frame_map.
2418  */
2419 void
2420 gst_video_frame_unmap (GstVideoFrame * frame)
2421 {
2422   GstBuffer *buffer;
2423   GstVideoMeta *meta;
2424   gint i;
2425
2426   g_return_if_fail (frame != NULL);
2427
2428   buffer = frame->buffer;
2429   meta = frame->meta;
2430
2431   if (meta) {
2432     for (i = 0; i < frame->info.finfo->n_planes; i++) {
2433       gst_video_meta_unmap (meta, i, &frame->map[i]);
2434     }
2435   } else {
2436     gst_buffer_unmap (buffer, &frame->map[0]);
2437   }
2438   gst_buffer_unref (buffer);
2439 }
2440
2441 /**
2442  * gst_video_frame_copy:
2443  * @dest: a #GstVideoFrame
2444  * @src: a #GstVideoFrame
2445  * @plane: a plane
2446  *
2447  * Copy the plane with index @plane from @src to @dest.
2448  *
2449  * Returns: TRUE if the contents could be copied.
2450  */
2451 gboolean
2452 gst_video_frame_copy_plane (GstVideoFrame * dest, const GstVideoFrame * src,
2453     guint plane)
2454 {
2455   const GstVideoInfo *sinfo;
2456   GstVideoInfo *dinfo;
2457   guint w, h, j;
2458   guint8 *sp, *dp;
2459   gint ss, ds;
2460
2461   g_return_val_if_fail (dest != NULL, FALSE);
2462   g_return_val_if_fail (src != NULL, FALSE);
2463
2464   sinfo = &src->info;
2465   dinfo = &dest->info;
2466
2467   g_return_val_if_fail (dinfo->finfo->format == sinfo->finfo->format, FALSE);
2468   g_return_val_if_fail (dinfo->width == sinfo->width
2469       && dinfo->height == sinfo->height, FALSE);
2470   g_return_val_if_fail (dinfo->finfo->n_planes > plane, FALSE);
2471
2472   sp = src->data[plane];
2473   dp = dest->data[plane];
2474
2475   ss = sinfo->stride[plane];
2476   ds = dinfo->stride[plane];
2477
2478   w = MIN (ABS (ss), ABS (ds));
2479   h = GST_VIDEO_FRAME_COMP_HEIGHT (dest, plane);
2480
2481   GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy plane %d, w:%d h:%d ", plane, w, h);
2482
2483   for (j = 0; j < h; j++) {
2484     memcpy (dp, sp, w);
2485     dp += ds;
2486     sp += ss;
2487   }
2488   return TRUE;
2489 }
2490
2491 /**
2492  * gst_video_frame_copy:
2493  * @dest: a #GstVideoFrame
2494  * @src: a #GstVideoFrame
2495  *
2496  * Copy the contents from @src to @dest.
2497  *
2498  * Returns: TRUE if the contents could be copied.
2499  */
2500 gboolean
2501 gst_video_frame_copy (GstVideoFrame * dest, const GstVideoFrame * src)
2502 {
2503   guint i, n_planes;
2504   const GstVideoInfo *sinfo;
2505   GstVideoInfo *dinfo;
2506
2507   g_return_val_if_fail (dest != NULL, FALSE);
2508   g_return_val_if_fail (src != NULL, FALSE);
2509
2510   sinfo = &src->info;
2511   dinfo = &dest->info;
2512
2513   g_return_val_if_fail (dinfo->finfo->format == sinfo->finfo->format, FALSE);
2514   g_return_val_if_fail (dinfo->width == sinfo->width
2515       && dinfo->height == sinfo->height, FALSE);
2516
2517   n_planes = dinfo->finfo->n_planes;
2518   if (GST_VIDEO_FORMAT_INFO_HAS_PALETTE (sinfo->finfo)) {
2519     memcpy (dest->data[1], src->data[1], 256 * 4);
2520     n_planes = 1;
2521   }
2522
2523   for (i = 0; i < n_planes; i++)
2524     gst_video_frame_copy_plane (dest, src, i);
2525
2526   return TRUE;
2527 }
2528
2529 static int
2530 fill_planes (GstVideoInfo * info)
2531 {
2532   gint width, height;
2533
2534   width = info->width;
2535   height = info->height;
2536
2537   switch (info->finfo->format) {
2538     case GST_VIDEO_FORMAT_YUY2:
2539     case GST_VIDEO_FORMAT_YVYU:
2540     case GST_VIDEO_FORMAT_UYVY:
2541       info->stride[0] = GST_ROUND_UP_4 (width * 2);
2542       info->offset[0] = 0;
2543       info->size = info->stride[0] * height;
2544       break;
2545     case GST_VIDEO_FORMAT_AYUV:
2546     case GST_VIDEO_FORMAT_RGBx:
2547     case GST_VIDEO_FORMAT_RGBA:
2548     case GST_VIDEO_FORMAT_BGRx:
2549     case GST_VIDEO_FORMAT_BGRA:
2550     case GST_VIDEO_FORMAT_xRGB:
2551     case GST_VIDEO_FORMAT_ARGB:
2552     case GST_VIDEO_FORMAT_xBGR:
2553     case GST_VIDEO_FORMAT_ABGR:
2554     case GST_VIDEO_FORMAT_r210:
2555       info->stride[0] = width * 4;
2556       info->offset[0] = 0;
2557       info->size = info->stride[0] * height;
2558       break;
2559     case GST_VIDEO_FORMAT_RGB16:
2560     case GST_VIDEO_FORMAT_BGR16:
2561     case GST_VIDEO_FORMAT_RGB15:
2562     case GST_VIDEO_FORMAT_BGR15:
2563       info->stride[0] = GST_ROUND_UP_4 (width * 2);
2564       info->offset[0] = 0;
2565       info->size = info->stride[0] * height;
2566       break;
2567     case GST_VIDEO_FORMAT_RGB:
2568     case GST_VIDEO_FORMAT_BGR:
2569     case GST_VIDEO_FORMAT_v308:
2570       info->stride[0] = GST_ROUND_UP_4 (width * 3);
2571       info->offset[0] = 0;
2572       info->size = info->stride[0] * height;
2573       break;
2574     case GST_VIDEO_FORMAT_v210:
2575       info->stride[0] = ((width + 47) / 48) * 128;
2576       info->offset[0] = 0;
2577       info->size = info->stride[0] * height;
2578       break;
2579     case GST_VIDEO_FORMAT_v216:
2580       info->stride[0] = GST_ROUND_UP_8 (width * 4);
2581       info->offset[0] = 0;
2582       info->size = info->stride[0] * height;
2583       break;
2584     case GST_VIDEO_FORMAT_GRAY8:
2585       info->stride[0] = GST_ROUND_UP_4 (width);
2586       info->offset[0] = 0;
2587       info->size = info->stride[0] * height;
2588       break;
2589     case GST_VIDEO_FORMAT_GRAY16_BE:
2590     case GST_VIDEO_FORMAT_GRAY16_LE:
2591       info->stride[0] = GST_ROUND_UP_4 (width * 2);
2592       info->offset[0] = 0;
2593       info->size = info->stride[0] * height;
2594       break;
2595     case GST_VIDEO_FORMAT_UYVP:
2596       info->stride[0] = GST_ROUND_UP_4 ((width * 2 * 5 + 3) / 4);
2597       info->offset[0] = 0;
2598       info->size = info->stride[0] * height;
2599       break;
2600     case GST_VIDEO_FORMAT_RGB8P:
2601       info->stride[0] = GST_ROUND_UP_4 (width);
2602       info->stride[1] = 4;
2603       info->offset[0] = 0;
2604       info->offset[1] = info->stride[0] * height;
2605       info->size = info->offset[1] + (4 * 256);
2606       break;
2607     case GST_VIDEO_FORMAT_IYU1:
2608       info->stride[0] = GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) +
2609           GST_ROUND_UP_4 (width) / 2);
2610       info->offset[0] = 0;
2611       info->size = info->stride[0] * height;
2612       break;
2613     case GST_VIDEO_FORMAT_ARGB64:
2614     case GST_VIDEO_FORMAT_AYUV64:
2615       info->stride[0] = width * 8;
2616       info->offset[0] = 0;
2617       info->size = info->stride[0] * height;
2618       break;
2619     case GST_VIDEO_FORMAT_I420:
2620     case GST_VIDEO_FORMAT_YV12:        /* same as I420, but plane 1+2 swapped */
2621       info->stride[0] = GST_ROUND_UP_4 (width);
2622       info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
2623       info->stride[2] = info->stride[1];
2624       info->offset[0] = 0;
2625       info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
2626       info->offset[2] = info->offset[1] +
2627           info->stride[1] * (GST_ROUND_UP_2 (height) / 2);
2628       info->size = info->offset[2] +
2629           info->stride[2] * (GST_ROUND_UP_2 (height) / 2);
2630       break;
2631     case GST_VIDEO_FORMAT_Y41B:
2632       info->stride[0] = GST_ROUND_UP_4 (width);
2633       info->stride[1] = GST_ROUND_UP_16 (width) / 4;
2634       info->stride[2] = info->stride[1];
2635       info->offset[0] = 0;
2636       info->offset[1] = info->stride[0] * height;
2637       info->offset[2] = info->offset[1] + info->stride[1] * height;
2638       /* simplification of ROUNDUP4(w)*h + 2*((ROUNDUP16(w)/4)*h */
2639       info->size = (info->stride[0] + (GST_ROUND_UP_16 (width) / 2)) * height;
2640       break;
2641     case GST_VIDEO_FORMAT_Y42B:
2642       info->stride[0] = GST_ROUND_UP_4 (width);
2643       info->stride[1] = GST_ROUND_UP_8 (width) / 2;
2644       info->stride[2] = info->stride[1];
2645       info->offset[0] = 0;
2646       info->offset[1] = info->stride[0] * height;
2647       info->offset[2] = info->offset[1] + info->stride[1] * height;
2648       /* simplification of ROUNDUP4(w)*h + 2*(ROUNDUP8(w)/2)*h */
2649       info->size = (info->stride[0] + GST_ROUND_UP_8 (width)) * height;
2650       break;
2651     case GST_VIDEO_FORMAT_Y444:
2652       info->stride[0] = GST_ROUND_UP_4 (width);
2653       info->stride[1] = info->stride[0];
2654       info->stride[2] = info->stride[0];
2655       info->offset[0] = 0;
2656       info->offset[1] = info->stride[0] * height;
2657       info->offset[2] = info->offset[1] * 2;
2658       info->size = info->stride[0] * height * 3;
2659       break;
2660     case GST_VIDEO_FORMAT_NV12:
2661     case GST_VIDEO_FORMAT_NV21:
2662       info->stride[0] = GST_ROUND_UP_4 (width);
2663       info->stride[1] = info->stride[0];
2664       info->offset[0] = 0;
2665       info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
2666       info->size = info->stride[0] * GST_ROUND_UP_2 (height) * 3 / 2;
2667       break;
2668     case GST_VIDEO_FORMAT_A420:
2669       info->stride[0] = GST_ROUND_UP_4 (width);
2670       info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
2671       info->stride[2] = info->stride[1];
2672       info->stride[3] = info->stride[0];
2673       info->offset[0] = 0;
2674       info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
2675       info->offset[2] = info->offset[1] +
2676           info->stride[1] * (GST_ROUND_UP_2 (height) / 2);
2677       info->offset[3] = info->offset[2] +
2678           info->stride[2] * (GST_ROUND_UP_2 (height) / 2);
2679       info->size = info->offset[3] + info->stride[0];
2680       break;
2681     case GST_VIDEO_FORMAT_YUV9:
2682     case GST_VIDEO_FORMAT_YVU9:
2683       info->stride[0] = GST_ROUND_UP_4 (width);
2684       info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4);
2685       info->stride[2] = info->stride[1];
2686       info->offset[0] = 0;
2687       info->offset[1] = info->stride[0] * height;
2688       info->offset[2] = info->offset[1] +
2689           info->stride[1] * (GST_ROUND_UP_4 (height) / 4);
2690       info->size = info->offset[2] +
2691           info->stride[2] * (GST_ROUND_UP_4 (height) / 4);
2692       break;
2693     case GST_VIDEO_FORMAT_I420_10LE:
2694     case GST_VIDEO_FORMAT_I420_10BE:
2695       info->stride[0] = GST_ROUND_UP_4 (width * 2);
2696       info->stride[1] = GST_ROUND_UP_4 (width);
2697       info->stride[2] = info->stride[1];
2698       info->offset[0] = 0;
2699       info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
2700       info->offset[2] = info->offset[1] +
2701           info->stride[1] * (GST_ROUND_UP_2 (height) / 2);
2702       info->size = info->offset[2] +
2703           info->stride[2] * (GST_ROUND_UP_2 (height) / 2);
2704       break;
2705     case GST_VIDEO_FORMAT_ENCODED:
2706       break;
2707     case GST_VIDEO_FORMAT_UNKNOWN:
2708       GST_ERROR ("invalid format");
2709       g_warning ("invalid format");
2710       break;
2711   }
2712   return 0;
2713 }
2714
2715 /**
2716  * gst_video_format_convert:
2717  * @info: a #GstVideoInfo
2718  * @src_format: #GstFormat of the @src_value
2719  * @src_value: value to convert
2720  * @dest_format: #GstFormat of the @dest_value
2721  * @dest_value: pointer to destination value
2722  *
2723  * Converts among various #GstFormat types.  This function handles
2724  * GST_FORMAT_BYTES, GST_FORMAT_TIME, and GST_FORMAT_DEFAULT.  For
2725  * raw video, GST_FORMAT_DEFAULT corresponds to video frames.  This
2726  * function can be used to handle pad queries of the type GST_QUERY_CONVERT.
2727  *
2728  * Since: 0.10.16
2729  *
2730  * Returns: TRUE if the conversion was successful.
2731  */
2732 gboolean
2733 gst_video_info_convert (GstVideoInfo * info,
2734     GstFormat src_format, gint64 src_value,
2735     GstFormat dest_format, gint64 * dest_value)
2736 {
2737   gboolean ret = FALSE;
2738   int size, fps_n, fps_d;
2739
2740   g_return_val_if_fail (info != NULL, 0);
2741   g_return_val_if_fail (info->finfo != NULL, 0);
2742   g_return_val_if_fail (info->finfo->format != GST_VIDEO_FORMAT_UNKNOWN, 0);
2743   g_return_val_if_fail (info->size > 0, 0);
2744
2745   size = info->size;
2746   fps_n = info->fps_n;
2747   fps_d = info->fps_d;
2748
2749   GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s to %s",
2750       src_value, gst_format_get_name (src_format),
2751       gst_format_get_name (dest_format));
2752
2753   if (src_format == dest_format) {
2754     *dest_value = src_value;
2755     ret = TRUE;
2756     goto done;
2757   }
2758
2759   if (src_value == -1) {
2760     *dest_value = -1;
2761     ret = TRUE;
2762     goto done;
2763   }
2764
2765   /* bytes to frames */
2766   if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_DEFAULT) {
2767     if (size != 0) {
2768       *dest_value = gst_util_uint64_scale_int (src_value, 1, size);
2769     } else {
2770       GST_ERROR ("blocksize is 0");
2771       *dest_value = 0;
2772     }
2773     ret = TRUE;
2774     goto done;
2775   }
2776
2777   /* frames to bytes */
2778   if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_BYTES) {
2779     *dest_value = gst_util_uint64_scale_int (src_value, size, 1);
2780     ret = TRUE;
2781     goto done;
2782   }
2783
2784   /* time to frames */
2785   if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_DEFAULT) {
2786     if (fps_d != 0) {
2787       *dest_value = gst_util_uint64_scale (src_value,
2788           fps_n, GST_SECOND * fps_d);
2789     } else {
2790       GST_ERROR ("framerate denominator is 0");
2791       *dest_value = 0;
2792     }
2793     ret = TRUE;
2794     goto done;
2795   }
2796
2797   /* frames to time */
2798   if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
2799     if (fps_n != 0) {
2800       *dest_value = gst_util_uint64_scale (src_value,
2801           GST_SECOND * fps_d, fps_n);
2802     } else {
2803       GST_ERROR ("framerate numerator is 0");
2804       *dest_value = 0;
2805     }
2806     ret = TRUE;
2807     goto done;
2808   }
2809
2810   /* time to bytes */
2811   if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) {
2812     if (fps_d != 0) {
2813       *dest_value = gst_util_uint64_scale (src_value,
2814           fps_n * size, GST_SECOND * fps_d);
2815     } else {
2816       GST_ERROR ("framerate denominator is 0");
2817       *dest_value = 0;
2818     }
2819     ret = TRUE;
2820     goto done;
2821   }
2822
2823   /* bytes to time */
2824   if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_TIME) {
2825     if (fps_n != 0 && size != 0) {
2826       *dest_value = gst_util_uint64_scale (src_value,
2827           GST_SECOND * fps_d, fps_n * size);
2828     } else {
2829       GST_ERROR ("framerate denominator and/or blocksize is 0");
2830       *dest_value = 0;
2831     }
2832     ret = TRUE;
2833   }
2834
2835 done:
2836
2837   GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, ret, *dest_value);
2838
2839   return ret;
2840 }
2841
2842 #define GST_VIDEO_EVENT_STILL_STATE_NAME "GstEventStillFrame"
2843
2844 /**
2845  * gst_video_event_new_still_frame:
2846  * @in_still: boolean value for the still-frame state of the event.
2847  *
2848  * Creates a new Still Frame event. If @in_still is %TRUE, then the event
2849  * represents the start of a still frame sequence. If it is %FALSE, then
2850  * the event ends a still frame sequence.
2851  *
2852  * To parse an event created by gst_video_event_new_still_frame() use
2853  * gst_video_event_parse_still_frame().
2854  *
2855  * Returns: The new GstEvent
2856  * Since: 0.10.26
2857  */
2858 GstEvent *
2859 gst_video_event_new_still_frame (gboolean in_still)
2860 {
2861   GstEvent *still_event;
2862   GstStructure *s;
2863
2864   s = gst_structure_new (GST_VIDEO_EVENT_STILL_STATE_NAME,
2865       "still-state", G_TYPE_BOOLEAN, in_still, NULL);
2866   still_event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
2867
2868   return still_event;
2869 }
2870
2871 /**
2872  * gst_video_event_parse_still_frame:
2873  * @event: A #GstEvent to parse
2874  * @in_still: A boolean to receive the still-frame status from the event, or NULL
2875  *
2876  * Parse a #GstEvent, identify if it is a Still Frame event, and
2877  * return the still-frame state from the event if it is.
2878  * If the event represents the start of a still frame, the in_still
2879  * variable will be set to TRUE, otherwise FALSE. It is OK to pass NULL for the
2880  * in_still variable order to just check whether the event is a valid still-frame
2881  * event.
2882  *
2883  * Create a still frame event using gst_video_event_new_still_frame()
2884  *
2885  * Returns: %TRUE if the event is a valid still-frame event. %FALSE if not
2886  * Since: 0.10.26
2887  */
2888 gboolean
2889 gst_video_event_parse_still_frame (GstEvent * event, gboolean * in_still)
2890 {
2891   const GstStructure *s;
2892   gboolean ev_still_state;
2893
2894   g_return_val_if_fail (event != NULL, FALSE);
2895
2896   if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_DOWNSTREAM)
2897     return FALSE;               /* Not a still frame event */
2898
2899   s = gst_event_get_structure (event);
2900   if (s == NULL
2901       || !gst_structure_has_name (s, GST_VIDEO_EVENT_STILL_STATE_NAME))
2902     return FALSE;               /* Not a still frame event */
2903   if (!gst_structure_get_boolean (s, "still-state", &ev_still_state))
2904     return FALSE;               /* Not a still frame event */
2905   if (in_still)
2906     *in_still = ev_still_state;
2907   return TRUE;
2908 }
2909
2910 #define GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME "GstForceKeyUnit"
2911
2912 /**
2913  * gst_video_event_new_downstream_force_key_unit:
2914  * @timestamp: the timestamp of the buffer that starts a new key unit
2915  * @stream_time: the stream_time of the buffer that starts a new key unit
2916  * @running_time: the running_time of the buffer that starts a new key unit
2917  * @all_headers: %TRUE to produce headers when starting a new key unit
2918  * @count: integer that can be used to number key units
2919  *
2920  * Creates a new downstream force key unit event. A downstream force key unit
2921  * event can be sent down the pipeline to request downstream elements to produce
2922  * a key unit. A downstream force key unit event must also be sent when handling
2923  * an upstream force key unit event to notify downstream that the latter has been
2924  * handled.
2925  *
2926  * To parse an event created by gst_video_event_new_downstream_force_key_unit() use
2927  * gst_video_event_parse_downstream_force_key_unit().
2928  *
2929  * Returns: The new GstEvent
2930  * Since: 0.10.36
2931  */
2932 GstEvent *
2933 gst_video_event_new_downstream_force_key_unit (GstClockTime timestamp,
2934     GstClockTime stream_time, GstClockTime running_time, gboolean all_headers,
2935     guint count)
2936 {
2937   GstEvent *force_key_unit_event;
2938   GstStructure *s;
2939
2940   s = gst_structure_new (GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME,
2941       "timestamp", G_TYPE_UINT64, timestamp,
2942       "stream-time", G_TYPE_UINT64, stream_time,
2943       "running-time", G_TYPE_UINT64, running_time,
2944       "all-headers", G_TYPE_BOOLEAN, all_headers,
2945       "count", G_TYPE_UINT, count, NULL);
2946   force_key_unit_event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
2947
2948   return force_key_unit_event;
2949 }
2950
2951 /**
2952  * gst_video_event_new_upstream_force_key_unit:
2953  * @running_time: the running_time at which a new key unit should be produced
2954  * @all_headers: %TRUE to produce headers when starting a new key unit
2955  * @count: integer that can be used to number key units
2956  *
2957  * Creates a new upstream force key unit event. An upstream force key unit event
2958  * can be sent to request upstream elements to produce a key unit. 
2959  *
2960  * @running_time can be set to request a new key unit at a specific
2961  * running_time. If set to GST_CLOCK_TIME_NONE, upstream elements will produce a
2962  * new key unit as soon as possible.
2963  *
2964  * To parse an event created by gst_video_event_new_downstream_force_key_unit() use
2965  * gst_video_event_parse_downstream_force_key_unit().
2966  *
2967  * Returns: The new GstEvent
2968  * Since: 0.10.36
2969  */
2970 GstEvent *
2971 gst_video_event_new_upstream_force_key_unit (GstClockTime running_time,
2972     gboolean all_headers, guint count)
2973 {
2974   GstEvent *force_key_unit_event;
2975   GstStructure *s;
2976
2977   s = gst_structure_new (GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME,
2978       "running-time", GST_TYPE_CLOCK_TIME, running_time,
2979       "all-headers", G_TYPE_BOOLEAN, all_headers,
2980       "count", G_TYPE_UINT, count, NULL);
2981   force_key_unit_event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, s);
2982
2983   return force_key_unit_event;
2984 }
2985
2986 /**
2987  * gst_video_event_is_force_key_unit:
2988  * @event: A #GstEvent to check
2989  *
2990  * Checks if an event is a force key unit event. Returns true for both upstream
2991  * and downstream force key unit events.
2992  *
2993  * Returns: %TRUE if the event is a valid force key unit event
2994  * Since: 0.10.36
2995  */
2996 gboolean
2997 gst_video_event_is_force_key_unit (GstEvent * event)
2998 {
2999   const GstStructure *s;
3000
3001   g_return_val_if_fail (event != NULL, FALSE);
3002
3003   if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_DOWNSTREAM &&
3004       GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_UPSTREAM)
3005     return FALSE;               /* Not a force key unit event */
3006
3007   s = gst_event_get_structure (event);
3008   if (s == NULL
3009       || !gst_structure_has_name (s, GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME))
3010     return FALSE;
3011
3012   return TRUE;
3013 }
3014
3015 /**
3016  * gst_video_event_parse_downstream_force_key_unit:
3017  * @event: A #GstEvent to parse
3018  * @timestamp: (out): A pointer to the timestamp in the event
3019  * @stream_time: (out): A pointer to the stream-time in the event
3020  * @running_time: (out): A pointer to the running-time in the event
3021  * @all_headers: (out): A pointer to the all_headers flag in the event
3022  * @count: (out): A pointer to the count field of the event
3023  *
3024  * Get timestamp, stream-time, running-time, all-headers and count in the force
3025  * key unit event. See gst_video_event_new_downstream_force_key_unit() for a
3026  * full description of the downstream force key unit event.
3027  *
3028  * Returns: %TRUE if the event is a valid downstream force key unit event.
3029  * Since: 0.10.36
3030  */
3031 gboolean
3032 gst_video_event_parse_downstream_force_key_unit (GstEvent * event,
3033     GstClockTime * timestamp, GstClockTime * stream_time,
3034     GstClockTime * running_time, gboolean * all_headers, guint * count)
3035 {
3036   const GstStructure *s;
3037   GstClockTime ev_timestamp, ev_stream_time, ev_running_time;
3038   gboolean ev_all_headers;
3039   guint ev_count;
3040
3041   g_return_val_if_fail (event != NULL, FALSE);
3042
3043   if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_DOWNSTREAM)
3044     return FALSE;               /* Not a force key unit event */
3045
3046   s = gst_event_get_structure (event);
3047   if (s == NULL
3048       || !gst_structure_has_name (s, GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME))
3049     return FALSE;
3050
3051   if (!gst_structure_get_clock_time (s, "timestamp", &ev_timestamp))
3052     ev_timestamp = GST_CLOCK_TIME_NONE;
3053   if (!gst_structure_get_clock_time (s, "stream-time", &ev_stream_time))
3054     ev_stream_time = GST_CLOCK_TIME_NONE;
3055   if (!gst_structure_get_clock_time (s, "running-time", &ev_running_time))
3056     ev_running_time = GST_CLOCK_TIME_NONE;
3057   if (!gst_structure_get_boolean (s, "all-headers", &ev_all_headers))
3058     ev_all_headers = FALSE;
3059   if (!gst_structure_get_uint (s, "count", &ev_count))
3060     ev_count = 0;
3061
3062   if (timestamp)
3063     *timestamp = ev_timestamp;
3064
3065   if (stream_time)
3066     *stream_time = ev_stream_time;
3067
3068   if (running_time)
3069     *running_time = ev_running_time;
3070
3071   if (all_headers)
3072     *all_headers = ev_all_headers;
3073
3074   if (count)
3075     *count = ev_count;
3076
3077   return TRUE;
3078 }
3079
3080 /**
3081  * gst_video_event_parse_upstream_force_key_unit:
3082  * @event: A #GstEvent to parse
3083  * @running_time: (out): A pointer to the running_time in the event
3084  * @all_headers: (out): A pointer to the all_headers flag in the event
3085  * @count: (out): A pointer to the count field in the event
3086  *
3087  * Get running-time, all-headers and count in the force key unit event. See
3088  * gst_video_event_new_upstream_force_key_unit() for a full description of the
3089  * upstream force key unit event.
3090  *
3091  * Create an upstream force key unit event using  gst_video_event_new_upstream_force_key_unit()
3092  *
3093  * Returns: %TRUE if the event is a valid upstream force-key-unit event. %FALSE if not
3094  * Since: 0.10.36
3095  */
3096 gboolean
3097 gst_video_event_parse_upstream_force_key_unit (GstEvent * event,
3098     GstClockTime * running_time, gboolean * all_headers, guint * count)
3099 {
3100   const GstStructure *s;
3101   GstClockTime ev_running_time;
3102   gboolean ev_all_headers;
3103   guint ev_count;
3104
3105   g_return_val_if_fail (event != NULL, FALSE);
3106
3107   if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_UPSTREAM)
3108     return FALSE;               /* Not a force key unit event */
3109
3110   s = gst_event_get_structure (event);
3111   if (s == NULL
3112       || !gst_structure_has_name (s, GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME))
3113     return FALSE;
3114
3115   if (!gst_structure_get_clock_time (s, "running-time", &ev_running_time))
3116     ev_running_time = GST_CLOCK_TIME_NONE;
3117   if (!gst_structure_get_boolean (s, "all-headers", &ev_all_headers))
3118     ev_all_headers = FALSE;
3119   if (!gst_structure_get_uint (s, "count", &ev_count))
3120     ev_count = 0;
3121
3122   if (running_time)
3123     *running_time = ev_running_time;
3124
3125   if (all_headers)
3126     *all_headers = ev_all_headers;
3127
3128   if (count)
3129     *count = ev_count;
3130
3131   return TRUE;
3132 }