f22ff4c12f66acf488188edd97f6016e81a0c078
[framework/multimedia/gst-plugins-base0.10.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 "video.h"
27
28 /**
29  * SECTION:gstvideo
30  * @short_description: Support library for video operations
31  *
32  * <refsect2>
33  * <para>
34  * This library contains some helper functions and includes the
35  * videosink and videofilter base classes.
36  * </para>
37  * </refsect2>
38  */
39
40 static GstVideoFormat gst_video_format_from_rgb32_masks (int red_mask,
41     int green_mask, int blue_mask);
42 static GstVideoFormat gst_video_format_from_rgba32_masks (int red_mask,
43     int green_mask, int blue_mask, int alpha_mask);
44 static GstVideoFormat gst_video_format_from_rgb24_masks (int red_mask,
45     int green_mask, int blue_mask);
46 static GstVideoFormat gst_video_format_from_rgb16_masks (int red_mask,
47     int green_mask, int blue_mask);
48
49
50 /**
51  * gst_video_frame_rate:
52  * @pad: pointer to a #GstPad
53  *
54  * A convenience function to retrieve a GValue holding the framerate
55  * from the caps on a pad.
56  *
57  * The pad needs to have negotiated caps containing a framerate property.
58  *
59  * Returns: NULL if the pad has no configured caps or the configured caps
60  * do not contain a framerate.
61  *
62  */
63 const GValue *
64 gst_video_frame_rate (GstPad * pad)
65 {
66   const GValue *fps;
67   gchar *fps_string;
68
69   const GstCaps *caps = NULL;
70   GstStructure *structure;
71
72   /* get pad caps */
73   caps = GST_PAD_CAPS (pad);
74   if (caps == NULL) {
75     g_warning ("gstvideo: failed to get caps of pad %s:%s",
76         GST_DEBUG_PAD_NAME (pad));
77     return NULL;
78   }
79
80   structure = gst_caps_get_structure (caps, 0);
81   if ((fps = gst_structure_get_value (structure, "framerate")) == NULL) {
82     g_warning ("gstvideo: failed to get framerate property of pad %s:%s",
83         GST_DEBUG_PAD_NAME (pad));
84     return NULL;
85   }
86   if (!GST_VALUE_HOLDS_FRACTION (fps)) {
87     g_warning
88         ("gstvideo: framerate property of pad %s:%s is not of type Fraction",
89         GST_DEBUG_PAD_NAME (pad));
90     return NULL;
91   }
92
93   fps_string = gst_value_serialize (fps);
94   GST_DEBUG ("Framerate request on pad %s:%s: %s",
95       GST_DEBUG_PAD_NAME (pad), fps_string);
96   g_free (fps_string);
97
98   return fps;
99 }
100
101 /**
102  * gst_video_get_size:
103  * @pad: pointer to a #GstPad
104  * @width: pointer to integer to hold pixel width of the video frames (output)
105  * @height: pointer to integer to hold pixel height of the video frames (output)
106  *
107  * Inspect the caps of the provided pad and retrieve the width and height of
108  * the video frames it is configured for.
109  *
110  * The pad needs to have negotiated caps containing width and height properties.
111  *
112  * Returns: TRUE if the width and height could be retrieved.
113  *
114  */
115 gboolean
116 gst_video_get_size (GstPad * pad, gint * width, gint * height)
117 {
118   const GstCaps *caps = NULL;
119   GstStructure *structure;
120   gboolean ret;
121
122   g_return_val_if_fail (pad != NULL, FALSE);
123   g_return_val_if_fail (width != NULL, FALSE);
124   g_return_val_if_fail (height != NULL, FALSE);
125
126   caps = GST_PAD_CAPS (pad);
127
128   if (caps == NULL) {
129     g_warning ("gstvideo: failed to get caps of pad %s:%s",
130         GST_DEBUG_PAD_NAME (pad));
131     return FALSE;
132   }
133
134   structure = gst_caps_get_structure (caps, 0);
135   ret = gst_structure_get_int (structure, "width", width);
136   ret &= gst_structure_get_int (structure, "height", height);
137
138   if (!ret) {
139     g_warning ("gstvideo: failed to get size properties on pad %s:%s",
140         GST_DEBUG_PAD_NAME (pad));
141     return FALSE;
142   }
143
144   GST_DEBUG ("size request on pad %s:%s: %dx%d",
145       GST_DEBUG_PAD_NAME (pad), width ? *width : -1, height ? *height : -1);
146
147   return TRUE;
148 }
149
150 /**
151  * gst_video_calculate_display_ratio:
152  * @dar_n: Numerator of the calculated display_ratio
153  * @dar_d: Denominator of the calculated display_ratio
154  * @video_width: Width of the video frame in pixels
155  * @video_height: Height of the video frame in pixels
156  * @video_par_n: Numerator of the pixel aspect ratio of the input video.
157  * @video_par_d: Denominator of the pixel aspect ratio of the input video.
158  * @display_par_n: Numerator of the pixel aspect ratio of the display device
159  * @display_par_d: Denominator of the pixel aspect ratio of the display device
160  *
161  * Given the Pixel Aspect Ratio and size of an input video frame, and the
162  * pixel aspect ratio of the intended display device, calculates the actual
163  * display ratio the video will be rendered with.
164  *
165  * Returns: A boolean indicating success and a calculated Display Ratio in the
166  * dar_n and dar_d parameters.
167  * The return value is FALSE in the case of integer overflow or other error.
168  *
169  * Since: 0.10.7
170  */
171 gboolean
172 gst_video_calculate_display_ratio (guint * dar_n, guint * dar_d,
173     guint video_width, guint video_height,
174     guint video_par_n, guint video_par_d,
175     guint display_par_n, guint display_par_d)
176 {
177   gint num, den;
178   gint tmp_n, tmp_d;
179
180   g_return_val_if_fail (dar_n != NULL, FALSE);
181   g_return_val_if_fail (dar_d != NULL, FALSE);
182
183   /* Calculate (video_width * video_par_n * display_par_d) /
184    * (video_height * video_par_d * display_par_n) */
185   if (!gst_util_fraction_multiply (video_width, video_height, video_par_n,
186           video_par_d, &tmp_n, &tmp_d))
187     goto error_overflow;
188
189   if (!gst_util_fraction_multiply (tmp_n, tmp_d, display_par_d, display_par_n,
190           &num, &den))
191     goto error_overflow;
192
193   g_return_val_if_fail (num > 0, FALSE);
194   g_return_val_if_fail (den > 0, FALSE);
195
196   *dar_n = num;
197   *dar_d = den;
198
199   return TRUE;
200 error_overflow:
201   return FALSE;
202 }
203
204 /**
205  * gst_video_format_parse_caps_interlaced:
206  * @caps: the fixed #GstCaps to parse
207  * @interlaced: whether @caps represents interlaced video or not, may be NULL (output)
208  *
209  * Extracts whether the caps represents interlaced content or not and places it
210  * in @interlaced.
211  *
212  * Since: 0.10.23
213  *
214  * Returns: TRUE if @caps was parsed correctly.
215  */
216 gboolean
217 gst_video_format_parse_caps_interlaced (GstCaps * caps, gboolean * interlaced)
218 {
219   GstStructure *structure;
220
221   if (!gst_caps_is_fixed (caps))
222     return FALSE;
223
224   structure = gst_caps_get_structure (caps, 0);
225
226   if (interlaced) {
227     if (!gst_structure_get_boolean (structure, "interlaced", interlaced))
228       *interlaced = FALSE;
229   }
230
231   return TRUE;
232 }
233
234 /**
235  * gst_video_parse_caps_color_matrix:
236  * @caps: the fixed #GstCaps to parse
237  *
238  * Extracts the color matrix used by the caps.  Possible values are
239  * "sdtv" for the standard definition color matrix (as specified in
240  * Rec. ITU-R BT.470-6) or "hdtv" for the high definition color
241  * matrix (as specified in Rec. ITU-R BT.709)
242  *
243  * Since: 0.10.29
244  *
245  * Returns: a color matrix string, or NULL if no color matrix could be
246  *     determined.
247  */
248 const char *
249 gst_video_parse_caps_color_matrix (GstCaps * caps)
250 {
251   GstStructure *structure;
252   const char *s;
253
254   if (!gst_caps_is_fixed (caps))
255     return NULL;
256
257   structure = gst_caps_get_structure (caps, 0);
258
259   s = gst_structure_get_string (structure, "color-matrix");
260   if (s)
261     return s;
262
263   if (gst_structure_has_name (structure, "video/x-raw-yuv")) {
264     return "sdtv";
265   }
266
267   return NULL;
268 }
269
270 /**
271  * gst_video_parse_caps_chroma_site:
272  * @caps: the fixed #GstCaps to parse
273  *
274  * Extracts the chroma site used by the caps.  Possible values are
275  * "mpeg2" for MPEG-2 style chroma siting (co-sited horizontally,
276  * halfway-sited vertically), "jpeg" for JPEG and Theora style
277  * chroma siting (halfway-sited both horizontally and vertically).
278  * Other chroma site values are possible, but uncommon.
279  *
280  * When no chroma site is specified in the caps, it should be assumed
281  * to be "mpeg2".
282  *
283  * Since: 0.10.29
284  *
285  * Returns: a chroma site string, or NULL if no chroma site could be
286  *     determined.
287  */
288 const char *
289 gst_video_parse_caps_chroma_site (GstCaps * caps)
290 {
291   GstStructure *structure;
292   const char *s;
293
294   if (!gst_caps_is_fixed (caps))
295     return NULL;
296
297   structure = gst_caps_get_structure (caps, 0);
298
299   s = gst_structure_get_string (structure, "chroma-site");
300   if (s)
301     return s;
302
303   if (gst_structure_has_name (structure, "video/x-raw-yuv")) {
304     return "mpeg2";
305   }
306
307   return NULL;
308 }
309
310 /**
311  * gst_video_format_parse_caps:
312  * @caps: the #GstCaps to parse
313  * @format: the #GstVideoFormat of the video represented by @caps (output)
314  * @width: the width of the video represented by @caps, may be NULL (output)
315  * @height: the height of the video represented by @caps, may be NULL (output)
316  *
317  * Determines the #GstVideoFormat of @caps and places it in the location
318  * pointed to by @format.  Extracts the size of the video and places it
319  * in the location pointed to by @width and @height.  If @caps does not
320  * represent a video format or does not contain height and width, the
321  * function will fail and return FALSE. If @caps does not represent a raw
322  * video format listed in #GstVideoFormat, but still contains video caps,
323  * this function will return TRUE and set @format to #GST_VIDEO_FORMAT_UNKNOWN.
324  *
325  * Since: 0.10.16
326  *
327  * Returns: TRUE if @caps was parsed correctly.
328  */
329 gboolean
330 gst_video_format_parse_caps (const GstCaps * caps, GstVideoFormat * format,
331     int *width, int *height)
332 {
333   GstStructure *structure;
334   gboolean ok = TRUE;
335
336   if (!gst_caps_is_fixed (caps))
337     return FALSE;
338
339   structure = gst_caps_get_structure (caps, 0);
340
341   if (format) {
342     if (gst_structure_has_name (structure, "video/x-raw-yuv")) {
343       guint32 fourcc;
344
345       ok &= gst_structure_get_fourcc (structure, "format", &fourcc);
346
347       *format = gst_video_format_from_fourcc (fourcc);
348       if (*format == GST_VIDEO_FORMAT_UNKNOWN) {
349         ok = FALSE;
350       }
351     } else if (gst_structure_has_name (structure, "video/x-raw-rgb")) {
352       int depth;
353       int bpp;
354       int endianness = 0;
355       int red_mask = 0;
356       int green_mask = 0;
357       int blue_mask = 0;
358       int alpha_mask = 0;
359       gboolean have_alpha;
360
361       ok &= gst_structure_get_int (structure, "depth", &depth);
362       ok &= gst_structure_get_int (structure, "bpp", &bpp);
363
364       if (bpp != 8) {
365         ok &= gst_structure_get_int (structure, "endianness", &endianness);
366         ok &= gst_structure_get_int (structure, "red_mask", &red_mask);
367         ok &= gst_structure_get_int (structure, "green_mask", &green_mask);
368         ok &= gst_structure_get_int (structure, "blue_mask", &blue_mask);
369       }
370       have_alpha = gst_structure_get_int (structure, "alpha_mask", &alpha_mask);
371
372       if (depth == 30 && bpp == 32 && endianness == G_BIG_ENDIAN) {
373         *format = GST_VIDEO_FORMAT_r210;
374       } else if (depth == 24 && bpp == 32 && endianness == G_BIG_ENDIAN) {
375         *format = gst_video_format_from_rgb32_masks (red_mask, green_mask,
376             blue_mask);
377         if (*format == GST_VIDEO_FORMAT_UNKNOWN) {
378           ok = FALSE;
379         }
380       } else if (depth == 32 && bpp == 32 && endianness == G_BIG_ENDIAN &&
381           have_alpha) {
382         *format = gst_video_format_from_rgba32_masks (red_mask, green_mask,
383             blue_mask, alpha_mask);
384         if (*format == GST_VIDEO_FORMAT_UNKNOWN) {
385           ok = FALSE;
386         }
387       } else if (depth == 24 && bpp == 24 && endianness == G_BIG_ENDIAN) {
388         *format = gst_video_format_from_rgb24_masks (red_mask, green_mask,
389             blue_mask);
390         if (*format == GST_VIDEO_FORMAT_UNKNOWN) {
391           ok = FALSE;
392         }
393       } else if ((depth == 15 || depth == 16) && bpp == 16 &&
394           endianness == G_BYTE_ORDER) {
395         *format = gst_video_format_from_rgb16_masks (red_mask, green_mask,
396             blue_mask);
397         if (*format == GST_VIDEO_FORMAT_UNKNOWN) {
398           ok = FALSE;
399         }
400       } else if (depth == 8 && bpp == 8) {
401         *format = GST_VIDEO_FORMAT_RGB8_PALETTED;
402       } else if (depth == 64 && bpp == 64) {
403         *format = gst_video_format_from_rgba32_masks (red_mask, green_mask,
404             blue_mask, alpha_mask);
405         if (*format == GST_VIDEO_FORMAT_ARGB) {
406           *format = GST_VIDEO_FORMAT_ARGB64;
407         } else {
408           *format = GST_VIDEO_FORMAT_UNKNOWN;
409           ok = FALSE;
410         }
411       } else {
412         ok = FALSE;
413       }
414     } else if (gst_structure_has_name (structure, "video/x-raw-gray")) {
415       int depth;
416       int bpp;
417       int endianness;
418
419       ok &= gst_structure_get_int (structure, "depth", &depth);
420       ok &= gst_structure_get_int (structure, "bpp", &bpp);
421
422       if (bpp > 8)
423         ok &= gst_structure_get_int (structure, "endianness", &endianness);
424
425       if (depth == 8 && bpp == 8) {
426         *format = GST_VIDEO_FORMAT_GRAY8;
427       } else if (depth == 16 && bpp == 16 && endianness == G_BIG_ENDIAN) {
428         *format = GST_VIDEO_FORMAT_GRAY16_BE;
429       } else if (depth == 16 && bpp == 16 && endianness == G_LITTLE_ENDIAN) {
430         *format = GST_VIDEO_FORMAT_GRAY16_LE;
431       } else {
432         ok = FALSE;
433       }
434     } else if (g_str_has_prefix (gst_structure_get_name (structure), "video/")) {
435       *format = GST_VIDEO_FORMAT_UNKNOWN;
436     } else {
437       ok = FALSE;
438     }
439   }
440
441   if (width) {
442     ok &= gst_structure_get_int (structure, "width", width);
443   }
444
445   if (height) {
446     ok &= gst_structure_get_int (structure, "height", height);
447   }
448
449   return ok;
450 }
451
452
453 /**
454  * gst_video_parse_caps_framerate:
455  * @caps: pointer to a #GstCaps instance
456  * @fps_n: pointer to integer to hold numerator of frame rate (output)
457  * @fps_d: pointer to integer to hold denominator of frame rate (output)
458  *
459  * Extracts the frame rate from @caps and places the values in the locations
460  * pointed to by @fps_n and @fps_d.  Returns TRUE if the values could be
461  * parsed correctly, FALSE if not.
462  *
463  * This function can be used with #GstCaps that have any media type; it
464  * is not limited to formats handled by #GstVideoFormat.
465  *
466  * Since: 0.10.16
467  *
468  * Returns: TRUE if @caps was parsed correctly.
469  */
470 gboolean
471 gst_video_parse_caps_framerate (GstCaps * caps, int *fps_n, int *fps_d)
472 {
473   GstStructure *structure;
474
475   if (!gst_caps_is_fixed (caps))
476     return FALSE;
477
478   structure = gst_caps_get_structure (caps, 0);
479
480   return gst_structure_get_fraction (structure, "framerate", fps_n, fps_d);
481 }
482
483 /**
484  * gst_video_parse_caps_pixel_aspect_ratio:
485  * @caps: pointer to a #GstCaps instance
486  * @par_n: pointer to numerator of pixel aspect ratio (output)
487  * @par_d: pointer to denominator of pixel aspect ratio (output)
488  *
489  * Extracts the pixel aspect ratio from @caps and places the values in
490  * the locations pointed to by @par_n and @par_d.  Returns TRUE if the
491  * values could be parsed correctly, FALSE if not.
492  *
493  * This function can be used with #GstCaps that have any media type; it
494  * is not limited to formats handled by #GstVideoFormat.
495  *
496  * Since: 0.10.16
497  *
498  * Returns: TRUE if @caps was parsed correctly.
499  */
500 gboolean
501 gst_video_parse_caps_pixel_aspect_ratio (GstCaps * caps, int *par_n, int *par_d)
502 {
503   GstStructure *structure;
504
505   if (!gst_caps_is_fixed (caps))
506     return FALSE;
507
508   structure = gst_caps_get_structure (caps, 0);
509
510   if (!gst_structure_get_fraction (structure, "pixel-aspect-ratio",
511           par_n, par_d)) {
512     *par_n = 1;
513     *par_d = 1;
514   }
515   return TRUE;
516 }
517
518 /**
519  * gst_video_format_new_caps_interlaced:
520  * @format: the #GstVideoFormat describing the raw video format
521  * @width: width of video
522  * @height: height of video
523  * @framerate_n: numerator of frame rate
524  * @framerate_d: denominator of frame rate
525  * @par_n: numerator of pixel aspect ratio
526  * @par_d: denominator of pixel aspect ratio
527  * @interlaced: #TRUE if the format is interlaced
528  *
529  * Creates a new #GstCaps object based on the parameters provided.
530  *
531  * Since: 0.10.23
532  *
533  * Returns: a new #GstCaps object, or NULL if there was an error
534  */
535 GstCaps *
536 gst_video_format_new_caps_interlaced (GstVideoFormat format,
537     int width, int height, int framerate_n, int framerate_d, int par_n,
538     int par_d, gboolean interlaced)
539 {
540   GstCaps *res;
541
542   res =
543       gst_video_format_new_caps (format, width, height, framerate_n,
544       framerate_d, par_n, par_d);
545   if (interlaced && (res != NULL))
546     gst_caps_set_simple (res, "interlaced", G_TYPE_BOOLEAN, TRUE, NULL);
547
548   return res;
549 }
550
551 static GstCaps *
552 gst_video_format_new_caps_raw (GstVideoFormat format)
553 {
554   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
555
556   if (gst_video_format_is_yuv (format)) {
557     return gst_caps_new_simple ("video/x-raw-yuv",
558         "format", GST_TYPE_FOURCC, gst_video_format_to_fourcc (format), NULL);
559   }
560   if (gst_video_format_is_rgb (format)) {
561     GstCaps *caps;
562     int red_mask = 0;
563     int blue_mask = 0;
564     int green_mask = 0;
565     int alpha_mask;
566     int depth;
567     int bpp;
568     gboolean have_alpha;
569     unsigned int mask = 0;
570
571     switch (format) {
572       case GST_VIDEO_FORMAT_RGBx:
573       case GST_VIDEO_FORMAT_BGRx:
574       case GST_VIDEO_FORMAT_xRGB:
575       case GST_VIDEO_FORMAT_xBGR:
576         bpp = 32;
577         depth = 24;
578         have_alpha = FALSE;
579         break;
580       case GST_VIDEO_FORMAT_RGBA:
581       case GST_VIDEO_FORMAT_BGRA:
582       case GST_VIDEO_FORMAT_ARGB:
583       case GST_VIDEO_FORMAT_ABGR:
584         bpp = 32;
585         depth = 32;
586         have_alpha = TRUE;
587         break;
588       case GST_VIDEO_FORMAT_RGB:
589       case GST_VIDEO_FORMAT_BGR:
590         bpp = 24;
591         depth = 24;
592         have_alpha = FALSE;
593         break;
594       case GST_VIDEO_FORMAT_RGB16:
595       case GST_VIDEO_FORMAT_BGR16:
596         bpp = 16;
597         depth = 16;
598         have_alpha = FALSE;
599         break;
600       case GST_VIDEO_FORMAT_RGB15:
601       case GST_VIDEO_FORMAT_BGR15:
602         bpp = 16;
603         depth = 15;
604         have_alpha = FALSE;
605         break;
606       case GST_VIDEO_FORMAT_RGB8_PALETTED:
607         bpp = 8;
608         depth = 8;
609         have_alpha = FALSE;
610         break;
611       case GST_VIDEO_FORMAT_ARGB64:
612         bpp = 64;
613         depth = 64;
614         have_alpha = TRUE;
615         break;
616       case GST_VIDEO_FORMAT_r210:
617         bpp = 32;
618         depth = 30;
619         have_alpha = FALSE;
620         break;
621       default:
622         return NULL;
623     }
624     if (bpp == 32 && depth == 30) {
625       red_mask = 0x3ff00000;
626       green_mask = 0x000ffc00;
627       blue_mask = 0x000003ff;
628       have_alpha = FALSE;
629     } else if (bpp == 32 || bpp == 24 || bpp == 64) {
630       if (bpp == 32) {
631         mask = 0xff000000;
632       } else {
633         mask = 0xff0000;
634       }
635       red_mask =
636           mask >> (8 * gst_video_format_get_component_offset (format, 0, 0, 0));
637       green_mask =
638           mask >> (8 * gst_video_format_get_component_offset (format, 1, 0, 0));
639       blue_mask =
640           mask >> (8 * gst_video_format_get_component_offset (format, 2, 0, 0));
641     } else if (bpp == 16) {
642       switch (format) {
643         case GST_VIDEO_FORMAT_RGB16:
644           red_mask = GST_VIDEO_COMP1_MASK_16_INT;
645           green_mask = GST_VIDEO_COMP2_MASK_16_INT;
646           blue_mask = GST_VIDEO_COMP3_MASK_16_INT;
647           break;
648         case GST_VIDEO_FORMAT_BGR16:
649           red_mask = GST_VIDEO_COMP3_MASK_16_INT;
650           green_mask = GST_VIDEO_COMP2_MASK_16_INT;
651           blue_mask = GST_VIDEO_COMP1_MASK_16_INT;
652           break;
653           break;
654         case GST_VIDEO_FORMAT_RGB15:
655           red_mask = GST_VIDEO_COMP1_MASK_15_INT;
656           green_mask = GST_VIDEO_COMP2_MASK_15_INT;
657           blue_mask = GST_VIDEO_COMP3_MASK_15_INT;
658           break;
659         case GST_VIDEO_FORMAT_BGR15:
660           red_mask = GST_VIDEO_COMP3_MASK_15_INT;
661           green_mask = GST_VIDEO_COMP2_MASK_15_INT;
662           blue_mask = GST_VIDEO_COMP1_MASK_15_INT;
663           break;
664         default:
665           g_assert_not_reached ();
666       }
667     } else if (bpp != 8) {
668       g_assert_not_reached ();
669     }
670
671     caps = gst_caps_new_simple ("video/x-raw-rgb",
672         "bpp", G_TYPE_INT, bpp, "depth", G_TYPE_INT, depth, NULL);
673
674     if (bpp != 8) {
675       gst_caps_set_simple (caps,
676           "endianness", G_TYPE_INT, G_BIG_ENDIAN,
677           "red_mask", G_TYPE_INT, red_mask,
678           "green_mask", G_TYPE_INT, green_mask,
679           "blue_mask", G_TYPE_INT, blue_mask, NULL);
680     }
681
682     if (have_alpha) {
683       alpha_mask =
684           mask >> (8 * gst_video_format_get_component_offset (format, 3, 0, 0));
685       gst_caps_set_simple (caps, "alpha_mask", G_TYPE_INT, alpha_mask, NULL);
686     }
687     return caps;
688   }
689
690   if (gst_video_format_is_gray (format)) {
691     GstCaps *caps;
692     int bpp;
693     int depth;
694     int endianness;
695
696     switch (format) {
697       case GST_VIDEO_FORMAT_GRAY8:
698         bpp = depth = 8;
699         endianness = G_BIG_ENDIAN;
700         break;
701       case GST_VIDEO_FORMAT_GRAY16_BE:
702         bpp = depth = 16;
703         endianness = G_BIG_ENDIAN;
704         break;
705       case GST_VIDEO_FORMAT_GRAY16_LE:
706         bpp = depth = 16;
707         endianness = G_LITTLE_ENDIAN;
708         break;
709       default:
710         return NULL;
711         break;
712     }
713
714     if (bpp <= 8) {
715       caps = gst_caps_new_simple ("video/x-raw-gray",
716           "bpp", G_TYPE_INT, bpp, "depth", G_TYPE_INT, depth, NULL);
717     } else {
718       caps = gst_caps_new_simple ("video/x-raw-gray",
719           "bpp", G_TYPE_INT, bpp,
720           "depth", G_TYPE_INT, depth,
721           "endianness", G_TYPE_INT, endianness, NULL);
722     }
723
724     return caps;
725   }
726
727   return NULL;
728 }
729
730 /**
731  * gst_video_format_new_template_caps:
732  * @format: the #GstVideoFormat describing the raw video format
733  *
734  * Creates a new #GstCaps object based on the parameters provided.
735  * Size, frame rate, and pixel aspect ratio are set to the full
736  * range.
737  *
738  * Since: 0.10.33
739  *
740  * Returns: a new #GstCaps object, or NULL if there was an error
741  */
742 GstCaps *
743 gst_video_format_new_template_caps (GstVideoFormat format)
744 {
745   GstCaps *caps;
746   GstStructure *structure;
747
748   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
749
750   caps = gst_video_format_new_caps_raw (format);
751   if (caps) {
752     GValue value = { 0 };
753     GValue v = { 0 };
754
755     structure = gst_caps_get_structure (caps, 0);
756
757     gst_structure_set (structure,
758         "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
759         "height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
760         "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1,
761         "pixel-aspect-ratio", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
762
763     g_value_init (&value, GST_TYPE_LIST);
764     g_value_init (&v, G_TYPE_BOOLEAN);
765     g_value_set_boolean (&v, TRUE);
766     gst_value_list_append_value (&value, &v);
767     g_value_set_boolean (&v, FALSE);
768     gst_value_list_append_value (&value, &v);
769     g_value_unset (&v);
770
771     gst_structure_take_value (structure, "interlaced", &value);
772   }
773
774   return caps;
775 }
776
777 /**
778  * gst_video_format_new_caps:
779  * @format: the #GstVideoFormat describing the raw video format
780  * @width: width of video
781  * @height: height of video
782  * @framerate_n: numerator of frame rate
783  * @framerate_d: denominator of frame rate
784  * @par_n: numerator of pixel aspect ratio
785  * @par_d: denominator of pixel aspect ratio
786  *
787  * Creates a new #GstCaps object based on the parameters provided.
788  *
789  * Since: 0.10.16
790  *
791  * Returns: a new #GstCaps object, or NULL if there was an error
792  */
793 GstCaps *
794 gst_video_format_new_caps (GstVideoFormat format, int width,
795     int height, int framerate_n, int framerate_d, int par_n, int par_d)
796 {
797   GstCaps *caps;
798   GstStructure *structure;
799
800   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
801   g_return_val_if_fail (width > 0 && height > 0, NULL);
802
803   caps = gst_video_format_new_caps_raw (format);
804   if (caps) {
805     structure = gst_caps_get_structure (caps, 0);
806
807     gst_structure_set (structure,
808         "width", G_TYPE_INT, width,
809         "height", G_TYPE_INT, height,
810         "framerate", GST_TYPE_FRACTION, framerate_n, framerate_d,
811         "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, NULL);
812   }
813
814   return caps;
815 }
816
817
818 /**
819  * gst_video_format_from_fourcc:
820  * @fourcc: a FOURCC value representing raw YUV video
821  *
822  * Converts a FOURCC value into the corresponding #GstVideoFormat.
823  * If the FOURCC cannot be represented by #GstVideoFormat,
824  * #GST_VIDEO_FORMAT_UNKNOWN is returned.
825  *
826  * Since: 0.10.16
827  *
828  * Returns: the #GstVideoFormat describing the FOURCC value
829  */
830 GstVideoFormat
831 gst_video_format_from_fourcc (guint32 fourcc)
832 {
833   switch (fourcc) {
834     case GST_MAKE_FOURCC ('I', '4', '2', '0'):
835       return GST_VIDEO_FORMAT_I420;
836     case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
837       return GST_VIDEO_FORMAT_YV12;
838     case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
839       return GST_VIDEO_FORMAT_YUY2;
840     case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'):
841       return GST_VIDEO_FORMAT_YVYU;
842     case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
843       return GST_VIDEO_FORMAT_UYVY;
844     case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'):
845       return GST_VIDEO_FORMAT_AYUV;
846     case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
847       return GST_VIDEO_FORMAT_Y41B;
848     case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
849       return GST_VIDEO_FORMAT_Y42B;
850     case GST_MAKE_FOURCC ('Y', '4', '4', '4'):
851       return GST_VIDEO_FORMAT_Y444;
852     case GST_MAKE_FOURCC ('v', '2', '1', '0'):
853       return GST_VIDEO_FORMAT_v210;
854     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
855       return GST_VIDEO_FORMAT_v216;
856     case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
857       return GST_VIDEO_FORMAT_NV12;
858     case GST_MAKE_FOURCC ('N', 'V', '2', '1'):
859       return GST_VIDEO_FORMAT_NV21;
860     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
861       return GST_VIDEO_FORMAT_v308;
862     case GST_MAKE_FOURCC ('Y', '8', '0', '0'):
863     case GST_MAKE_FOURCC ('Y', '8', ' ', ' '):
864     case GST_MAKE_FOURCC ('G', 'R', 'E', 'Y'):
865       return GST_VIDEO_FORMAT_Y800;
866     case GST_MAKE_FOURCC ('Y', '1', '6', ' '):
867       return GST_VIDEO_FORMAT_Y16;
868     case GST_MAKE_FOURCC ('U', 'Y', 'V', 'P'):
869       return GST_VIDEO_FORMAT_UYVP;
870     case GST_MAKE_FOURCC ('A', '4', '2', '0'):
871       return GST_VIDEO_FORMAT_A420;
872     case GST_MAKE_FOURCC ('Y', 'U', 'V', '9'):
873       return GST_VIDEO_FORMAT_YUV9;
874     case GST_MAKE_FOURCC ('Y', 'V', 'U', '9'):
875       return GST_VIDEO_FORMAT_YVU9;
876     case GST_MAKE_FOURCC ('I', 'Y', 'U', '1'):
877       return GST_VIDEO_FORMAT_IYU1;
878     case GST_MAKE_FOURCC ('A', 'Y', '6', '4'):
879       return GST_VIDEO_FORMAT_AYUV64;
880     default:
881       return GST_VIDEO_FORMAT_UNKNOWN;
882   }
883 }
884
885 /**
886  * gst_video_format_to_fourcc:
887  * @format: a #GstVideoFormat video format
888  *
889  * Converts a #GstVideoFormat value into the corresponding FOURCC.  Only
890  * a few YUV formats have corresponding FOURCC values.  If @format has
891  * no corresponding FOURCC value, 0 is returned.
892  *
893  * Since: 0.10.16
894  *
895  * Returns: the FOURCC corresponding to @format
896  */
897 guint32
898 gst_video_format_to_fourcc (GstVideoFormat format)
899 {
900   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
901
902   switch (format) {
903     case GST_VIDEO_FORMAT_I420:
904       return GST_MAKE_FOURCC ('I', '4', '2', '0');
905     case GST_VIDEO_FORMAT_YV12:
906       return GST_MAKE_FOURCC ('Y', 'V', '1', '2');
907     case GST_VIDEO_FORMAT_YUY2:
908       return GST_MAKE_FOURCC ('Y', 'U', 'Y', '2');
909     case GST_VIDEO_FORMAT_YVYU:
910       return GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U');
911     case GST_VIDEO_FORMAT_UYVY:
912       return GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y');
913     case GST_VIDEO_FORMAT_AYUV:
914       return GST_MAKE_FOURCC ('A', 'Y', 'U', 'V');
915     case GST_VIDEO_FORMAT_Y41B:
916       return GST_MAKE_FOURCC ('Y', '4', '1', 'B');
917     case GST_VIDEO_FORMAT_Y42B:
918       return GST_MAKE_FOURCC ('Y', '4', '2', 'B');
919     case GST_VIDEO_FORMAT_Y444:
920       return GST_MAKE_FOURCC ('Y', '4', '4', '4');
921     case GST_VIDEO_FORMAT_v210:
922       return GST_MAKE_FOURCC ('v', '2', '1', '0');
923     case GST_VIDEO_FORMAT_v216:
924       return GST_MAKE_FOURCC ('v', '2', '1', '6');
925     case GST_VIDEO_FORMAT_NV12:
926       return GST_MAKE_FOURCC ('N', 'V', '1', '2');
927     case GST_VIDEO_FORMAT_NV21:
928       return GST_MAKE_FOURCC ('N', 'V', '2', '1');
929     case GST_VIDEO_FORMAT_v308:
930       return GST_MAKE_FOURCC ('v', '3', '0', '8');
931     case GST_VIDEO_FORMAT_Y800:
932       return GST_MAKE_FOURCC ('Y', '8', '0', '0');
933     case GST_VIDEO_FORMAT_Y16:
934       return GST_MAKE_FOURCC ('Y', '1', '6', ' ');
935     case GST_VIDEO_FORMAT_UYVP:
936       return GST_MAKE_FOURCC ('U', 'Y', 'V', 'P');
937     case GST_VIDEO_FORMAT_A420:
938       return GST_MAKE_FOURCC ('A', '4', '2', '0');
939     case GST_VIDEO_FORMAT_YUV9:
940       return GST_MAKE_FOURCC ('Y', 'U', 'V', '9');
941     case GST_VIDEO_FORMAT_YVU9:
942       return GST_MAKE_FOURCC ('Y', 'V', 'U', '9');
943     case GST_VIDEO_FORMAT_IYU1:
944       return GST_MAKE_FOURCC ('I', 'Y', 'U', '1');
945     case GST_VIDEO_FORMAT_AYUV64:
946       return GST_MAKE_FOURCC ('A', 'Y', '6', '4');
947     default:
948       return 0;
949   }
950 }
951
952 /*
953  * gst_video_format_from_rgb32_masks:
954  * @red_mask: red bit mask
955  * @green_mask: green bit mask
956  * @blue_mask: blue bit mask
957  *
958  * Converts red, green, blue bit masks into the corresponding
959  * #GstVideoFormat.
960  *
961  * Since: 0.10.16
962  *
963  * Returns: the #GstVideoFormat corresponding to the bit masks
964  */
965 static GstVideoFormat
966 gst_video_format_from_rgb32_masks (int red_mask, int green_mask, int blue_mask)
967 {
968   if (red_mask == 0xff000000 && green_mask == 0x00ff0000 &&
969       blue_mask == 0x0000ff00) {
970     return GST_VIDEO_FORMAT_RGBx;
971   }
972   if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 &&
973       blue_mask == 0xff000000) {
974     return GST_VIDEO_FORMAT_BGRx;
975   }
976   if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 &&
977       blue_mask == 0x000000ff) {
978     return GST_VIDEO_FORMAT_xRGB;
979   }
980   if (red_mask == 0x000000ff && green_mask == 0x0000ff00 &&
981       blue_mask == 0x00ff0000) {
982     return GST_VIDEO_FORMAT_xBGR;
983   }
984
985   return GST_VIDEO_FORMAT_UNKNOWN;
986 }
987
988 static GstVideoFormat
989 gst_video_format_from_rgba32_masks (int red_mask, int green_mask,
990     int blue_mask, int alpha_mask)
991 {
992   if (red_mask == 0xff000000 && green_mask == 0x00ff0000 &&
993       blue_mask == 0x0000ff00 && alpha_mask == 0x000000ff) {
994     return GST_VIDEO_FORMAT_RGBA;
995   }
996   if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 &&
997       blue_mask == 0xff000000 && alpha_mask == 0x000000ff) {
998     return GST_VIDEO_FORMAT_BGRA;
999   }
1000   if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 &&
1001       blue_mask == 0x000000ff && alpha_mask == 0xff000000) {
1002     return GST_VIDEO_FORMAT_ARGB;
1003   }
1004   if (red_mask == 0x000000ff && green_mask == 0x0000ff00 &&
1005       blue_mask == 0x00ff0000 && alpha_mask == 0xff000000) {
1006     return GST_VIDEO_FORMAT_ABGR;
1007   }
1008
1009   return GST_VIDEO_FORMAT_UNKNOWN;
1010 }
1011
1012 static GstVideoFormat
1013 gst_video_format_from_rgb24_masks (int red_mask, int green_mask, int blue_mask)
1014 {
1015   if (red_mask == 0xff0000 && green_mask == 0x00ff00 && blue_mask == 0x0000ff) {
1016     return GST_VIDEO_FORMAT_RGB;
1017   }
1018   if (red_mask == 0x0000ff && green_mask == 0x00ff00 && blue_mask == 0xff0000) {
1019     return GST_VIDEO_FORMAT_BGR;
1020   }
1021
1022   return GST_VIDEO_FORMAT_UNKNOWN;
1023 }
1024
1025 static GstVideoFormat
1026 gst_video_format_from_rgb16_masks (int red_mask, int green_mask, int blue_mask)
1027 {
1028   if (red_mask == GST_VIDEO_COMP1_MASK_16_INT
1029       && green_mask == GST_VIDEO_COMP2_MASK_16_INT
1030       && blue_mask == GST_VIDEO_COMP3_MASK_16_INT) {
1031     return GST_VIDEO_FORMAT_RGB16;
1032   }
1033   if (red_mask == GST_VIDEO_COMP3_MASK_16_INT
1034       && green_mask == GST_VIDEO_COMP2_MASK_16_INT
1035       && blue_mask == GST_VIDEO_COMP1_MASK_16_INT) {
1036     return GST_VIDEO_FORMAT_BGR16;
1037   }
1038   if (red_mask == GST_VIDEO_COMP1_MASK_15_INT
1039       && green_mask == GST_VIDEO_COMP2_MASK_15_INT
1040       && blue_mask == GST_VIDEO_COMP3_MASK_15_INT) {
1041     return GST_VIDEO_FORMAT_RGB15;
1042   }
1043   if (red_mask == GST_VIDEO_COMP3_MASK_15_INT
1044       && green_mask == GST_VIDEO_COMP2_MASK_15_INT
1045       && blue_mask == GST_VIDEO_COMP1_MASK_15_INT) {
1046     return GST_VIDEO_FORMAT_BGR15;
1047   }
1048
1049   return GST_VIDEO_FORMAT_UNKNOWN;
1050 }
1051
1052 /**
1053  * gst_video_format_is_rgb:
1054  * @format: a #GstVideoFormat
1055  *
1056  * Determine whether the video format is an RGB format.
1057  *
1058  * Since: 0.10.16
1059  *
1060  * Returns: TRUE if @format represents RGB video
1061  */
1062 gboolean
1063 gst_video_format_is_rgb (GstVideoFormat format)
1064 {
1065   switch (format) {
1066     case GST_VIDEO_FORMAT_I420:
1067     case GST_VIDEO_FORMAT_YV12:
1068     case GST_VIDEO_FORMAT_YUY2:
1069     case GST_VIDEO_FORMAT_YVYU:
1070     case GST_VIDEO_FORMAT_UYVY:
1071     case GST_VIDEO_FORMAT_AYUV:
1072     case GST_VIDEO_FORMAT_Y41B:
1073     case GST_VIDEO_FORMAT_Y42B:
1074     case GST_VIDEO_FORMAT_Y444:
1075     case GST_VIDEO_FORMAT_v210:
1076     case GST_VIDEO_FORMAT_v216:
1077     case GST_VIDEO_FORMAT_NV12:
1078     case GST_VIDEO_FORMAT_NV21:
1079     case GST_VIDEO_FORMAT_v308:
1080     case GST_VIDEO_FORMAT_UYVP:
1081     case GST_VIDEO_FORMAT_A420:
1082     case GST_VIDEO_FORMAT_YUV9:
1083     case GST_VIDEO_FORMAT_YVU9:
1084     case GST_VIDEO_FORMAT_IYU1:
1085     case GST_VIDEO_FORMAT_AYUV64:
1086       return FALSE;
1087     case GST_VIDEO_FORMAT_RGBx:
1088     case GST_VIDEO_FORMAT_BGRx:
1089     case GST_VIDEO_FORMAT_xRGB:
1090     case GST_VIDEO_FORMAT_xBGR:
1091     case GST_VIDEO_FORMAT_RGBA:
1092     case GST_VIDEO_FORMAT_BGRA:
1093     case GST_VIDEO_FORMAT_ARGB:
1094     case GST_VIDEO_FORMAT_ABGR:
1095     case GST_VIDEO_FORMAT_RGB:
1096     case GST_VIDEO_FORMAT_BGR:
1097     case GST_VIDEO_FORMAT_RGB16:
1098     case GST_VIDEO_FORMAT_BGR16:
1099     case GST_VIDEO_FORMAT_RGB15:
1100     case GST_VIDEO_FORMAT_BGR15:
1101     case GST_VIDEO_FORMAT_RGB8_PALETTED:
1102     case GST_VIDEO_FORMAT_ARGB64:
1103     case GST_VIDEO_FORMAT_r210:
1104       return TRUE;
1105     default:
1106       return FALSE;
1107   }
1108 }
1109
1110 /**
1111  * gst_video_format_is_yuv:
1112  * @format: a #GstVideoFormat
1113  *
1114  * Determine whether the video format is a YUV format.
1115  *
1116  * Since: 0.10.16
1117  *
1118  * Returns: TRUE if @format represents YUV video
1119  */
1120 gboolean
1121 gst_video_format_is_yuv (GstVideoFormat format)
1122 {
1123   switch (format) {
1124     case GST_VIDEO_FORMAT_I420:
1125     case GST_VIDEO_FORMAT_YV12:
1126     case GST_VIDEO_FORMAT_YUY2:
1127     case GST_VIDEO_FORMAT_YVYU:
1128     case GST_VIDEO_FORMAT_UYVY:
1129     case GST_VIDEO_FORMAT_AYUV:
1130     case GST_VIDEO_FORMAT_Y41B:
1131     case GST_VIDEO_FORMAT_Y42B:
1132     case GST_VIDEO_FORMAT_Y444:
1133     case GST_VIDEO_FORMAT_v210:
1134     case GST_VIDEO_FORMAT_v216:
1135     case GST_VIDEO_FORMAT_NV12:
1136     case GST_VIDEO_FORMAT_NV21:
1137     case GST_VIDEO_FORMAT_v308:
1138     case GST_VIDEO_FORMAT_Y800:
1139     case GST_VIDEO_FORMAT_Y16:
1140     case GST_VIDEO_FORMAT_UYVP:
1141     case GST_VIDEO_FORMAT_A420:
1142     case GST_VIDEO_FORMAT_YUV9:
1143     case GST_VIDEO_FORMAT_YVU9:
1144     case GST_VIDEO_FORMAT_IYU1:
1145     case GST_VIDEO_FORMAT_AYUV64:
1146       return TRUE;
1147     case GST_VIDEO_FORMAT_RGBx:
1148     case GST_VIDEO_FORMAT_BGRx:
1149     case GST_VIDEO_FORMAT_xRGB:
1150     case GST_VIDEO_FORMAT_xBGR:
1151     case GST_VIDEO_FORMAT_RGBA:
1152     case GST_VIDEO_FORMAT_BGRA:
1153     case GST_VIDEO_FORMAT_ARGB:
1154     case GST_VIDEO_FORMAT_ABGR:
1155     case GST_VIDEO_FORMAT_RGB:
1156     case GST_VIDEO_FORMAT_BGR:
1157     case GST_VIDEO_FORMAT_RGB16:
1158     case GST_VIDEO_FORMAT_BGR16:
1159     case GST_VIDEO_FORMAT_RGB15:
1160     case GST_VIDEO_FORMAT_BGR15:
1161     case GST_VIDEO_FORMAT_RGB8_PALETTED:
1162     case GST_VIDEO_FORMAT_ARGB64:
1163     case GST_VIDEO_FORMAT_r210:
1164       return FALSE;
1165     default:
1166       return FALSE;
1167   }
1168 }
1169
1170 /**
1171  * gst_video_format_is_gray:
1172  * @format: a #GstVideoFormat
1173  *
1174  * Determine whether the video format is a grayscale format.
1175  *
1176  * Since: 0.10.29
1177  *
1178  * Returns: TRUE if @format represents grayscale video
1179  */
1180 gboolean
1181 gst_video_format_is_gray (GstVideoFormat format)
1182 {
1183   switch (format) {
1184     case GST_VIDEO_FORMAT_GRAY8:
1185     case GST_VIDEO_FORMAT_GRAY16_BE:
1186     case GST_VIDEO_FORMAT_GRAY16_LE:
1187     case GST_VIDEO_FORMAT_Y800:
1188     case GST_VIDEO_FORMAT_Y16:
1189       return TRUE;
1190     default:
1191       return FALSE;
1192   }
1193 }
1194
1195 /**
1196  * gst_video_format_has_alpha:
1197  * @format: a #GstVideoFormat
1198  *
1199  * Returns TRUE or FALSE depending on if the video format provides an
1200  * alpha channel.
1201  *
1202  * Since: 0.10.16
1203  *
1204  * Returns: TRUE if @format has an alpha channel
1205  */
1206 gboolean
1207 gst_video_format_has_alpha (GstVideoFormat format)
1208 {
1209   switch (format) {
1210     case GST_VIDEO_FORMAT_I420:
1211     case GST_VIDEO_FORMAT_YV12:
1212     case GST_VIDEO_FORMAT_YUY2:
1213     case GST_VIDEO_FORMAT_YVYU:
1214     case GST_VIDEO_FORMAT_UYVY:
1215     case GST_VIDEO_FORMAT_Y41B:
1216     case GST_VIDEO_FORMAT_Y42B:
1217     case GST_VIDEO_FORMAT_Y444:
1218     case GST_VIDEO_FORMAT_v210:
1219     case GST_VIDEO_FORMAT_v216:
1220     case GST_VIDEO_FORMAT_NV12:
1221     case GST_VIDEO_FORMAT_NV21:
1222     case GST_VIDEO_FORMAT_v308:
1223     case GST_VIDEO_FORMAT_Y800:
1224     case GST_VIDEO_FORMAT_Y16:
1225     case GST_VIDEO_FORMAT_UYVP:
1226     case GST_VIDEO_FORMAT_YUV9:
1227     case GST_VIDEO_FORMAT_YVU9:
1228     case GST_VIDEO_FORMAT_IYU1:
1229       return FALSE;
1230     case GST_VIDEO_FORMAT_AYUV:
1231     case GST_VIDEO_FORMAT_RGBA:
1232     case GST_VIDEO_FORMAT_BGRA:
1233     case GST_VIDEO_FORMAT_ARGB:
1234     case GST_VIDEO_FORMAT_ABGR:
1235     case GST_VIDEO_FORMAT_A420:
1236     case GST_VIDEO_FORMAT_RGB8_PALETTED:
1237     case GST_VIDEO_FORMAT_ARGB64:
1238     case GST_VIDEO_FORMAT_AYUV64:
1239       return TRUE;
1240     case GST_VIDEO_FORMAT_RGBx:
1241     case GST_VIDEO_FORMAT_BGRx:
1242     case GST_VIDEO_FORMAT_xRGB:
1243     case GST_VIDEO_FORMAT_xBGR:
1244     case GST_VIDEO_FORMAT_RGB:
1245     case GST_VIDEO_FORMAT_BGR:
1246     case GST_VIDEO_FORMAT_RGB16:
1247     case GST_VIDEO_FORMAT_BGR16:
1248     case GST_VIDEO_FORMAT_RGB15:
1249     case GST_VIDEO_FORMAT_BGR15:
1250     case GST_VIDEO_FORMAT_r210:
1251       return FALSE;
1252     default:
1253       return FALSE;
1254   }
1255 }
1256
1257 /**
1258  * gst_video_format_get_component_depth:
1259  * @format: a #GstVideoFormat
1260  * @component: the video component (e.g. 0 for 'R' in RGB)
1261  *
1262  * Returns the number of bits used to encode an individual pixel of
1263  * a given @component.  Typically this is 8, although higher and lower
1264  * values are possible for some formats.
1265  *
1266  * Since: 0.10.33
1267  *
1268  * Returns: depth of component
1269  */
1270 int
1271 gst_video_format_get_component_depth (GstVideoFormat format, int component)
1272 {
1273   if (component == 3 && !gst_video_format_has_alpha (format))
1274     return 0;
1275
1276   switch (format) {
1277     case GST_VIDEO_FORMAT_RGB16:
1278     case GST_VIDEO_FORMAT_BGR16:
1279       if (component == 1)
1280         return 6;
1281       return 5;
1282     case GST_VIDEO_FORMAT_RGB15:
1283     case GST_VIDEO_FORMAT_BGR15:
1284       return 5;
1285     case GST_VIDEO_FORMAT_I420:
1286     case GST_VIDEO_FORMAT_YV12:
1287     case GST_VIDEO_FORMAT_YUY2:
1288     case GST_VIDEO_FORMAT_YVYU:
1289     case GST_VIDEO_FORMAT_UYVY:
1290     case GST_VIDEO_FORMAT_Y41B:
1291     case GST_VIDEO_FORMAT_Y42B:
1292     case GST_VIDEO_FORMAT_Y444:
1293     case GST_VIDEO_FORMAT_NV12:
1294     case GST_VIDEO_FORMAT_NV21:
1295     case GST_VIDEO_FORMAT_v308:
1296     case GST_VIDEO_FORMAT_Y800:
1297     case GST_VIDEO_FORMAT_YUV9:
1298     case GST_VIDEO_FORMAT_YVU9:
1299     case GST_VIDEO_FORMAT_IYU1:
1300     case GST_VIDEO_FORMAT_AYUV:
1301     case GST_VIDEO_FORMAT_RGBA:
1302     case GST_VIDEO_FORMAT_BGRA:
1303     case GST_VIDEO_FORMAT_ARGB:
1304     case GST_VIDEO_FORMAT_ABGR:
1305     case GST_VIDEO_FORMAT_A420:
1306     case GST_VIDEO_FORMAT_RGB8_PALETTED:
1307     case GST_VIDEO_FORMAT_RGBx:
1308     case GST_VIDEO_FORMAT_BGRx:
1309     case GST_VIDEO_FORMAT_xRGB:
1310     case GST_VIDEO_FORMAT_xBGR:
1311     case GST_VIDEO_FORMAT_RGB:
1312     case GST_VIDEO_FORMAT_BGR:
1313     default:
1314       return 8;
1315     case GST_VIDEO_FORMAT_v210:
1316     case GST_VIDEO_FORMAT_UYVP:
1317     case GST_VIDEO_FORMAT_r210:
1318       return 10;
1319     case GST_VIDEO_FORMAT_Y16:
1320     case GST_VIDEO_FORMAT_v216:
1321     case GST_VIDEO_FORMAT_ARGB64:
1322     case GST_VIDEO_FORMAT_AYUV64:
1323       return 16;
1324   }
1325
1326 }
1327
1328 /**
1329  * gst_video_format_get_row_stride:
1330  * @format: a #GstVideoFormat
1331  * @component: the component index
1332  * @width: the width of video
1333  *
1334  * Calculates the row stride (number of bytes from one row of pixels to
1335  * the next) for the video component with an index of @component.  For
1336  * YUV video, Y, U, and V have component indices of 0, 1, and 2,
1337  * respectively.  For RGB video, R, G, and B have component indicies of
1338  * 0, 1, and 2, respectively.  Alpha channels, if present, have a component
1339  * index of 3.  The @width parameter always represents the width of the
1340  * video, not the component.
1341  *
1342  * Since: 0.10.16
1343  *
1344  * Returns: row stride of component @component
1345  */
1346 int
1347 gst_video_format_get_row_stride (GstVideoFormat format, int component,
1348     int width)
1349 {
1350   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1351   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1352   g_return_val_if_fail (width > 0, 0);
1353
1354   switch (format) {
1355     case GST_VIDEO_FORMAT_I420:
1356     case GST_VIDEO_FORMAT_YV12:
1357       if (component == 0) {
1358         return GST_ROUND_UP_4 (width);
1359       } else {
1360         return GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
1361       }
1362     case GST_VIDEO_FORMAT_YUY2:
1363     case GST_VIDEO_FORMAT_YVYU:
1364     case GST_VIDEO_FORMAT_UYVY:
1365       return GST_ROUND_UP_4 (width * 2);
1366     case GST_VIDEO_FORMAT_AYUV:
1367     case GST_VIDEO_FORMAT_RGBx:
1368     case GST_VIDEO_FORMAT_BGRx:
1369     case GST_VIDEO_FORMAT_xRGB:
1370     case GST_VIDEO_FORMAT_xBGR:
1371     case GST_VIDEO_FORMAT_RGBA:
1372     case GST_VIDEO_FORMAT_BGRA:
1373     case GST_VIDEO_FORMAT_ARGB:
1374     case GST_VIDEO_FORMAT_ABGR:
1375     case GST_VIDEO_FORMAT_r210:
1376       return width * 4;
1377     case GST_VIDEO_FORMAT_RGB16:
1378     case GST_VIDEO_FORMAT_BGR16:
1379     case GST_VIDEO_FORMAT_RGB15:
1380     case GST_VIDEO_FORMAT_BGR15:
1381       return GST_ROUND_UP_4 (width * 2);
1382     case GST_VIDEO_FORMAT_RGB:
1383     case GST_VIDEO_FORMAT_BGR:
1384     case GST_VIDEO_FORMAT_v308:
1385       return GST_ROUND_UP_4 (width * 3);
1386     case GST_VIDEO_FORMAT_Y41B:
1387       if (component == 0) {
1388         return GST_ROUND_UP_4 (width);
1389       } else {
1390         return GST_ROUND_UP_16 (width) / 4;
1391       }
1392     case GST_VIDEO_FORMAT_Y42B:
1393       if (component == 0) {
1394         return GST_ROUND_UP_4 (width);
1395       } else {
1396         return GST_ROUND_UP_8 (width) / 2;
1397       }
1398     case GST_VIDEO_FORMAT_Y444:
1399       return GST_ROUND_UP_4 (width);
1400     case GST_VIDEO_FORMAT_v210:
1401       return ((width + 47) / 48) * 128;
1402     case GST_VIDEO_FORMAT_v216:
1403       return GST_ROUND_UP_8 (width * 4);
1404     case GST_VIDEO_FORMAT_NV12:
1405     case GST_VIDEO_FORMAT_NV21:
1406       return GST_ROUND_UP_4 (width);
1407     case GST_VIDEO_FORMAT_GRAY8:
1408     case GST_VIDEO_FORMAT_Y800:
1409       return GST_ROUND_UP_4 (width);
1410     case GST_VIDEO_FORMAT_GRAY16_BE:
1411     case GST_VIDEO_FORMAT_GRAY16_LE:
1412     case GST_VIDEO_FORMAT_Y16:
1413       return GST_ROUND_UP_4 (width * 2);
1414     case GST_VIDEO_FORMAT_UYVP:
1415       return GST_ROUND_UP_4 ((width * 2 * 5 + 3) / 4);
1416     case GST_VIDEO_FORMAT_A420:
1417       if (component == 0 || component == 3) {
1418         return GST_ROUND_UP_4 (width);
1419       } else {
1420         return GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
1421       }
1422     case GST_VIDEO_FORMAT_RGB8_PALETTED:
1423       return GST_ROUND_UP_4 (width);
1424     case GST_VIDEO_FORMAT_YUV9:
1425     case GST_VIDEO_FORMAT_YVU9:
1426       if (component == 0) {
1427         return GST_ROUND_UP_4 (width);
1428       } else {
1429         return GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4);
1430       }
1431     case GST_VIDEO_FORMAT_IYU1:
1432       return GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) +
1433           GST_ROUND_UP_4 (width) / 2);
1434     case GST_VIDEO_FORMAT_ARGB64:
1435     case GST_VIDEO_FORMAT_AYUV64:
1436       return width * 8;
1437     default:
1438       return 0;
1439   }
1440 }
1441
1442 /**
1443  * gst_video_format_get_pixel_stride:
1444  * @format: a #GstVideoFormat
1445  * @component: the component index
1446  *
1447  * Calculates the pixel stride (number of bytes from one pixel to the
1448  * pixel to its immediate left) for the video component with an index
1449  * of @component.  See @gst_video_format_get_row_stride for a description
1450  * of the component index.
1451  *
1452  * Since: 0.10.16
1453  *
1454  * Returns: pixel stride of component @component
1455  */
1456 int
1457 gst_video_format_get_pixel_stride (GstVideoFormat format, int component)
1458 {
1459   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1460   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1461
1462   switch (format) {
1463     case GST_VIDEO_FORMAT_I420:
1464     case GST_VIDEO_FORMAT_YV12:
1465     case GST_VIDEO_FORMAT_Y41B:
1466     case GST_VIDEO_FORMAT_Y42B:
1467     case GST_VIDEO_FORMAT_Y444:
1468     case GST_VIDEO_FORMAT_A420:
1469     case GST_VIDEO_FORMAT_YUV9:
1470     case GST_VIDEO_FORMAT_YVU9:
1471       return 1;
1472     case GST_VIDEO_FORMAT_YUY2:
1473     case GST_VIDEO_FORMAT_YVYU:
1474     case GST_VIDEO_FORMAT_UYVY:
1475       if (component == 0) {
1476         return 2;
1477       } else {
1478         return 4;
1479       }
1480     case GST_VIDEO_FORMAT_IYU1:
1481       /* doesn't make much sense for IYU1 because it's 1 or 3
1482        * for luma depending on position */
1483       return 0;
1484     case GST_VIDEO_FORMAT_AYUV:
1485     case GST_VIDEO_FORMAT_RGBx:
1486     case GST_VIDEO_FORMAT_BGRx:
1487     case GST_VIDEO_FORMAT_xRGB:
1488     case GST_VIDEO_FORMAT_xBGR:
1489     case GST_VIDEO_FORMAT_RGBA:
1490     case GST_VIDEO_FORMAT_BGRA:
1491     case GST_VIDEO_FORMAT_ARGB:
1492     case GST_VIDEO_FORMAT_ABGR:
1493     case GST_VIDEO_FORMAT_r210:
1494       return 4;
1495     case GST_VIDEO_FORMAT_RGB16:
1496     case GST_VIDEO_FORMAT_BGR16:
1497     case GST_VIDEO_FORMAT_RGB15:
1498     case GST_VIDEO_FORMAT_BGR15:
1499       return 2;
1500     case GST_VIDEO_FORMAT_RGB:
1501     case GST_VIDEO_FORMAT_BGR:
1502     case GST_VIDEO_FORMAT_v308:
1503       return 3;
1504     case GST_VIDEO_FORMAT_v210:
1505       /* v210 is packed at the bit level, so pixel stride doesn't make sense */
1506       return 0;
1507     case GST_VIDEO_FORMAT_v216:
1508       if (component == 0) {
1509         return 4;
1510       } else {
1511         return 8;
1512       }
1513     case GST_VIDEO_FORMAT_NV12:
1514     case GST_VIDEO_FORMAT_NV21:
1515       if (component == 0) {
1516         return 1;
1517       } else {
1518         return 2;
1519       }
1520     case GST_VIDEO_FORMAT_GRAY8:
1521     case GST_VIDEO_FORMAT_Y800:
1522       return 1;
1523     case GST_VIDEO_FORMAT_GRAY16_BE:
1524     case GST_VIDEO_FORMAT_GRAY16_LE:
1525     case GST_VIDEO_FORMAT_Y16:
1526       return 2;
1527     case GST_VIDEO_FORMAT_UYVP:
1528       /* UYVP is packed at the bit level, so pixel stride doesn't make sense */
1529       return 0;
1530     case GST_VIDEO_FORMAT_RGB8_PALETTED:
1531       return 1;
1532     case GST_VIDEO_FORMAT_ARGB64:
1533     case GST_VIDEO_FORMAT_AYUV64:
1534       return 8;
1535     default:
1536       return 0;
1537   }
1538 }
1539
1540 /**
1541  * gst_video_format_get_component_width:
1542  * @format: a #GstVideoFormat
1543  * @component: the component index
1544  * @width: the width of video
1545  *
1546  * Calculates the width of the component.  See
1547  * @gst_video_format_get_row_stride for a description
1548  * of the component index.
1549  *
1550  * Since: 0.10.16
1551  *
1552  * Returns: width of component @component
1553  */
1554 int
1555 gst_video_format_get_component_width (GstVideoFormat format,
1556     int component, int width)
1557 {
1558   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1559   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1560   g_return_val_if_fail (width > 0, 0);
1561
1562   switch (format) {
1563     case GST_VIDEO_FORMAT_I420:
1564     case GST_VIDEO_FORMAT_YV12:
1565     case GST_VIDEO_FORMAT_YUY2:
1566     case GST_VIDEO_FORMAT_YVYU:
1567     case GST_VIDEO_FORMAT_UYVY:
1568     case GST_VIDEO_FORMAT_Y42B:
1569     case GST_VIDEO_FORMAT_v210:
1570     case GST_VIDEO_FORMAT_v216:
1571     case GST_VIDEO_FORMAT_NV12:
1572     case GST_VIDEO_FORMAT_NV21:
1573     case GST_VIDEO_FORMAT_UYVP:
1574       if (component == 0) {
1575         return width;
1576       } else {
1577         return GST_ROUND_UP_2 (width) / 2;
1578       }
1579     case GST_VIDEO_FORMAT_Y41B:
1580     case GST_VIDEO_FORMAT_YUV9:
1581     case GST_VIDEO_FORMAT_YVU9:
1582     case GST_VIDEO_FORMAT_IYU1:
1583       if (component == 0) {
1584         return width;
1585       } else {
1586         return GST_ROUND_UP_4 (width) / 4;
1587       }
1588     case GST_VIDEO_FORMAT_AYUV:
1589     case GST_VIDEO_FORMAT_RGBx:
1590     case GST_VIDEO_FORMAT_BGRx:
1591     case GST_VIDEO_FORMAT_xRGB:
1592     case GST_VIDEO_FORMAT_xBGR:
1593     case GST_VIDEO_FORMAT_RGBA:
1594     case GST_VIDEO_FORMAT_BGRA:
1595     case GST_VIDEO_FORMAT_ARGB:
1596     case GST_VIDEO_FORMAT_ABGR:
1597     case GST_VIDEO_FORMAT_RGB:
1598     case GST_VIDEO_FORMAT_BGR:
1599     case GST_VIDEO_FORMAT_RGB16:
1600     case GST_VIDEO_FORMAT_BGR16:
1601     case GST_VIDEO_FORMAT_RGB15:
1602     case GST_VIDEO_FORMAT_BGR15:
1603     case GST_VIDEO_FORMAT_Y444:
1604     case GST_VIDEO_FORMAT_v308:
1605     case GST_VIDEO_FORMAT_GRAY8:
1606     case GST_VIDEO_FORMAT_GRAY16_BE:
1607     case GST_VIDEO_FORMAT_GRAY16_LE:
1608     case GST_VIDEO_FORMAT_Y800:
1609     case GST_VIDEO_FORMAT_Y16:
1610     case GST_VIDEO_FORMAT_RGB8_PALETTED:
1611     case GST_VIDEO_FORMAT_ARGB64:
1612     case GST_VIDEO_FORMAT_AYUV64:
1613     case GST_VIDEO_FORMAT_r210:
1614       return width;
1615     case GST_VIDEO_FORMAT_A420:
1616       if (component == 0 || component == 3) {
1617         return width;
1618       } else {
1619         return GST_ROUND_UP_2 (width) / 2;
1620       }
1621     default:
1622       return 0;
1623   }
1624 }
1625
1626 /**
1627  * gst_video_format_get_component_height:
1628  * @format: a #GstVideoFormat
1629  * @component: the component index
1630  * @height: the height of video
1631  *
1632  * Calculates the height of the component.  See
1633  * @gst_video_format_get_row_stride for a description
1634  * of the component index.
1635  *
1636  * Since: 0.10.16
1637  *
1638  * Returns: height of component @component
1639  */
1640 int
1641 gst_video_format_get_component_height (GstVideoFormat format,
1642     int component, int height)
1643 {
1644   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1645   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1646   g_return_val_if_fail (height > 0, 0);
1647
1648   switch (format) {
1649     case GST_VIDEO_FORMAT_I420:
1650     case GST_VIDEO_FORMAT_YV12:
1651     case GST_VIDEO_FORMAT_NV12:
1652     case GST_VIDEO_FORMAT_NV21:
1653       if (component == 0) {
1654         return height;
1655       } else {
1656         return GST_ROUND_UP_2 (height) / 2;
1657       }
1658     case GST_VIDEO_FORMAT_Y41B:
1659     case GST_VIDEO_FORMAT_Y42B:
1660     case GST_VIDEO_FORMAT_YUY2:
1661     case GST_VIDEO_FORMAT_YVYU:
1662     case GST_VIDEO_FORMAT_UYVY:
1663     case GST_VIDEO_FORMAT_AYUV:
1664     case GST_VIDEO_FORMAT_RGBx:
1665     case GST_VIDEO_FORMAT_BGRx:
1666     case GST_VIDEO_FORMAT_xRGB:
1667     case GST_VIDEO_FORMAT_xBGR:
1668     case GST_VIDEO_FORMAT_RGBA:
1669     case GST_VIDEO_FORMAT_BGRA:
1670     case GST_VIDEO_FORMAT_ARGB:
1671     case GST_VIDEO_FORMAT_ABGR:
1672     case GST_VIDEO_FORMAT_RGB:
1673     case GST_VIDEO_FORMAT_BGR:
1674     case GST_VIDEO_FORMAT_RGB16:
1675     case GST_VIDEO_FORMAT_BGR16:
1676     case GST_VIDEO_FORMAT_RGB15:
1677     case GST_VIDEO_FORMAT_BGR15:
1678     case GST_VIDEO_FORMAT_Y444:
1679     case GST_VIDEO_FORMAT_v210:
1680     case GST_VIDEO_FORMAT_v216:
1681     case GST_VIDEO_FORMAT_v308:
1682     case GST_VIDEO_FORMAT_GRAY8:
1683     case GST_VIDEO_FORMAT_GRAY16_BE:
1684     case GST_VIDEO_FORMAT_GRAY16_LE:
1685     case GST_VIDEO_FORMAT_Y800:
1686     case GST_VIDEO_FORMAT_Y16:
1687     case GST_VIDEO_FORMAT_UYVP:
1688     case GST_VIDEO_FORMAT_RGB8_PALETTED:
1689     case GST_VIDEO_FORMAT_IYU1:
1690     case GST_VIDEO_FORMAT_ARGB64:
1691     case GST_VIDEO_FORMAT_AYUV64:
1692     case GST_VIDEO_FORMAT_r210:
1693       return height;
1694     case GST_VIDEO_FORMAT_A420:
1695       if (component == 0 || component == 3) {
1696         return height;
1697       } else {
1698         return GST_ROUND_UP_2 (height) / 2;
1699       }
1700     case GST_VIDEO_FORMAT_YUV9:
1701     case GST_VIDEO_FORMAT_YVU9:
1702       if (component == 0) {
1703         return height;
1704       } else {
1705         return GST_ROUND_UP_4 (height) / 4;
1706       }
1707     default:
1708       return 0;
1709   }
1710 }
1711
1712 /**
1713  * gst_video_format_get_component_offset:
1714  * @format: a #GstVideoFormat
1715  * @component: the component index
1716  * @width: the width of video
1717  * @height: the height of video
1718  *
1719  * Calculates the offset (in bytes) of the first pixel of the component
1720  * with index @component.  For packed formats, this will typically be a
1721  * small integer (0, 1, 2, 3).  For planar formats, this will be a
1722  * (relatively) large offset to the beginning of the second or third
1723  * component planes.  See @gst_video_format_get_row_stride for a description
1724  * of the component index.
1725  *
1726  * Since: 0.10.16
1727  *
1728  * Returns: offset of component @component
1729  */
1730 int
1731 gst_video_format_get_component_offset (GstVideoFormat format,
1732     int component, int width, int height)
1733 {
1734   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1735   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1736   g_return_val_if_fail ((!gst_video_format_is_yuv (format)) || (width > 0
1737           && height > 0), 0);
1738
1739   switch (format) {
1740     case GST_VIDEO_FORMAT_I420:
1741       if (component == 0)
1742         return 0;
1743       if (component == 1)
1744         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1745       if (component == 2) {
1746         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) +
1747             GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1748             (GST_ROUND_UP_2 (height) / 2);
1749       }
1750       break;
1751     case GST_VIDEO_FORMAT_YV12:        /* same as I420, but components 1+2 swapped */
1752       if (component == 0)
1753         return 0;
1754       if (component == 2)
1755         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1756       if (component == 1) {
1757         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) +
1758             GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1759             (GST_ROUND_UP_2 (height) / 2);
1760       }
1761       break;
1762     case GST_VIDEO_FORMAT_YUY2:
1763       if (component == 0)
1764         return 0;
1765       if (component == 1)
1766         return 1;
1767       if (component == 2)
1768         return 3;
1769       break;
1770     case GST_VIDEO_FORMAT_YVYU:
1771       if (component == 0)
1772         return 0;
1773       if (component == 1)
1774         return 3;
1775       if (component == 2)
1776         return 1;
1777       break;
1778     case GST_VIDEO_FORMAT_UYVY:
1779       if (component == 0)
1780         return 1;
1781       if (component == 1)
1782         return 0;
1783       if (component == 2)
1784         return 2;
1785       break;
1786     case GST_VIDEO_FORMAT_AYUV:
1787       if (component == 0)
1788         return 1;
1789       if (component == 1)
1790         return 2;
1791       if (component == 2)
1792         return 3;
1793       if (component == 3)
1794         return 0;
1795       break;
1796     case GST_VIDEO_FORMAT_RGBx:
1797     case GST_VIDEO_FORMAT_RGBA:
1798       if (component == 0)
1799         return 0;
1800       if (component == 1)
1801         return 1;
1802       if (component == 2)
1803         return 2;
1804       if (component == 3)
1805         return 3;
1806       break;
1807     case GST_VIDEO_FORMAT_BGRx:
1808     case GST_VIDEO_FORMAT_BGRA:
1809       if (component == 0)
1810         return 2;
1811       if (component == 1)
1812         return 1;
1813       if (component == 2)
1814         return 0;
1815       if (component == 3)
1816         return 3;
1817       break;
1818     case GST_VIDEO_FORMAT_xRGB:
1819     case GST_VIDEO_FORMAT_ARGB:
1820       if (component == 0)
1821         return 1;
1822       if (component == 1)
1823         return 2;
1824       if (component == 2)
1825         return 3;
1826       if (component == 3)
1827         return 0;
1828       break;
1829     case GST_VIDEO_FORMAT_xBGR:
1830     case GST_VIDEO_FORMAT_ABGR:
1831       if (component == 0)
1832         return 3;
1833       if (component == 1)
1834         return 2;
1835       if (component == 2)
1836         return 1;
1837       if (component == 3)
1838         return 0;
1839       break;
1840     case GST_VIDEO_FORMAT_RGB:
1841     case GST_VIDEO_FORMAT_v308:
1842       if (component == 0)
1843         return 0;
1844       if (component == 1)
1845         return 1;
1846       if (component == 2)
1847         return 2;
1848       break;
1849     case GST_VIDEO_FORMAT_BGR:
1850       if (component == 0)
1851         return 2;
1852       if (component == 1)
1853         return 1;
1854       if (component == 2)
1855         return 0;
1856       break;
1857     case GST_VIDEO_FORMAT_Y41B:
1858       if (component == 0)
1859         return 0;
1860       if (component == 1)
1861         return GST_ROUND_UP_4 (width) * height;
1862       if (component == 2)
1863         return (GST_ROUND_UP_4 (width) +
1864             (GST_ROUND_UP_16 (width) / 4)) * height;
1865       break;
1866     case GST_VIDEO_FORMAT_Y42B:
1867       if (component == 0)
1868         return 0;
1869       if (component == 1)
1870         return GST_ROUND_UP_4 (width) * height;
1871       if (component == 2)
1872         return (GST_ROUND_UP_4 (width) + (GST_ROUND_UP_8 (width) / 2)) * height;
1873       break;
1874     case GST_VIDEO_FORMAT_Y444:
1875       return GST_ROUND_UP_4 (width) * height * component;
1876     case GST_VIDEO_FORMAT_v210:
1877     case GST_VIDEO_FORMAT_r210:
1878       /* v210 is bit-packed, so this doesn't make sense */
1879       return 0;
1880     case GST_VIDEO_FORMAT_v216:
1881       if (component == 0)
1882         return 0;
1883       if (component == 1)
1884         return 2;
1885       if (component == 2)
1886         return 6;
1887       break;
1888     case GST_VIDEO_FORMAT_NV12:
1889       if (component == 0)
1890         return 0;
1891       if (component == 1)
1892         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1893       if (component == 2)
1894         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) + 1;
1895       break;
1896     case GST_VIDEO_FORMAT_NV21:
1897       if (component == 0)
1898         return 0;
1899       if (component == 1)
1900         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) + 1;
1901       if (component == 2)
1902         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1903       break;
1904     case GST_VIDEO_FORMAT_GRAY8:
1905     case GST_VIDEO_FORMAT_GRAY16_BE:
1906     case GST_VIDEO_FORMAT_GRAY16_LE:
1907     case GST_VIDEO_FORMAT_Y800:
1908     case GST_VIDEO_FORMAT_Y16:
1909       return 0;
1910     case GST_VIDEO_FORMAT_UYVP:
1911       /* UYVP is bit-packed, so this doesn't make sense */
1912       return 0;
1913     case GST_VIDEO_FORMAT_A420:
1914       if (component == 0)
1915         return 0;
1916       if (component == 1)
1917         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1918       if (component == 2) {
1919         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) +
1920             GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1921             (GST_ROUND_UP_2 (height) / 2);
1922       }
1923       if (component == 3) {
1924         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) +
1925             2 * GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1926             (GST_ROUND_UP_2 (height) / 2);
1927       }
1928       break;
1929     case GST_VIDEO_FORMAT_RGB8_PALETTED:
1930       return 0;
1931     case GST_VIDEO_FORMAT_YUV9:
1932       if (component == 0)
1933         return 0;
1934       if (component == 1)
1935         return GST_ROUND_UP_4 (width) * height;
1936       if (component == 2) {
1937         return GST_ROUND_UP_4 (width) * height +
1938             GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4) *
1939             (GST_ROUND_UP_4 (height) / 4);
1940       }
1941       break;
1942     case GST_VIDEO_FORMAT_YVU9:
1943       if (component == 0)
1944         return 0;
1945       if (component == 1) {
1946         return GST_ROUND_UP_4 (width) * height +
1947             GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4) *
1948             (GST_ROUND_UP_4 (height) / 4);
1949       }
1950       if (component == 2)
1951         return GST_ROUND_UP_4 (width) * height;
1952       break;
1953     case GST_VIDEO_FORMAT_IYU1:
1954       if (component == 0)
1955         return 1;
1956       if (component == 1)
1957         return 0;
1958       if (component == 2)
1959         return 4;
1960       break;
1961     case GST_VIDEO_FORMAT_ARGB64:
1962     case GST_VIDEO_FORMAT_AYUV64:
1963       if (component == 0)
1964         return 2;
1965       if (component == 1)
1966         return 4;
1967       if (component == 2)
1968         return 6;
1969       if (component == 3)
1970         return 0;
1971       break;
1972     default:
1973       break;
1974   }
1975   GST_WARNING ("unhandled format %d or component %d", format, component);
1976   return 0;
1977 }
1978
1979 /**
1980  * gst_video_format_get_size:
1981  * @format: a #GstVideoFormat
1982  * @width: the width of video
1983  * @height: the height of video
1984  *
1985  * Calculates the total number of bytes in the raw video format.  This
1986  * number should be used when allocating a buffer for raw video.
1987  *
1988  * Since: 0.10.16
1989  *
1990  * Returns: size (in bytes) of raw video format
1991  */
1992 int
1993 gst_video_format_get_size (GstVideoFormat format, int width, int height)
1994 {
1995   int size;
1996
1997   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1998   g_return_val_if_fail (width > 0 && height > 0, 0);
1999
2000   switch (format) {
2001     case GST_VIDEO_FORMAT_I420:
2002     case GST_VIDEO_FORMAT_YV12:
2003       size = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
2004       size += GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
2005           (GST_ROUND_UP_2 (height) / 2) * 2;
2006       return size;
2007     case GST_VIDEO_FORMAT_IYU1:
2008       return GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) +
2009           GST_ROUND_UP_4 (width) / 2) * height;
2010     case GST_VIDEO_FORMAT_YUY2:
2011     case GST_VIDEO_FORMAT_YVYU:
2012     case GST_VIDEO_FORMAT_UYVY:
2013       return GST_ROUND_UP_4 (width * 2) * height;
2014     case GST_VIDEO_FORMAT_AYUV:
2015     case GST_VIDEO_FORMAT_RGBx:
2016     case GST_VIDEO_FORMAT_BGRx:
2017     case GST_VIDEO_FORMAT_xRGB:
2018     case GST_VIDEO_FORMAT_xBGR:
2019     case GST_VIDEO_FORMAT_RGBA:
2020     case GST_VIDEO_FORMAT_BGRA:
2021     case GST_VIDEO_FORMAT_ARGB:
2022     case GST_VIDEO_FORMAT_ABGR:
2023     case GST_VIDEO_FORMAT_r210:
2024       return width * 4 * height;
2025     case GST_VIDEO_FORMAT_RGB16:
2026     case GST_VIDEO_FORMAT_BGR16:
2027     case GST_VIDEO_FORMAT_RGB15:
2028     case GST_VIDEO_FORMAT_BGR15:
2029       return GST_ROUND_UP_4 (width * 2) * height;
2030     case GST_VIDEO_FORMAT_RGB:
2031     case GST_VIDEO_FORMAT_BGR:
2032     case GST_VIDEO_FORMAT_v308:
2033       return GST_ROUND_UP_4 (width * 3) * height;
2034     case GST_VIDEO_FORMAT_Y41B:
2035       /* simplification of ROUNDUP4(w)*h + 2*((ROUNDUP16(w)/4)*h */
2036       return (GST_ROUND_UP_4 (width) + (GST_ROUND_UP_16 (width) / 2)) * height;
2037     case GST_VIDEO_FORMAT_Y42B:
2038       /* simplification of ROUNDUP4(w)*h + 2*(ROUNDUP8(w)/2)*h */
2039       return (GST_ROUND_UP_4 (width) + GST_ROUND_UP_8 (width)) * height;
2040     case GST_VIDEO_FORMAT_Y444:
2041       return GST_ROUND_UP_4 (width) * height * 3;
2042     case GST_VIDEO_FORMAT_v210:
2043       return ((width + 47) / 48) * 128 * height;
2044     case GST_VIDEO_FORMAT_v216:
2045       return GST_ROUND_UP_8 (width * 4) * height;
2046     case GST_VIDEO_FORMAT_NV12:
2047     case GST_VIDEO_FORMAT_NV21:
2048       return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) * 3 / 2;
2049     case GST_VIDEO_FORMAT_GRAY8:
2050     case GST_VIDEO_FORMAT_Y800:
2051     case GST_VIDEO_FORMAT_RGB8_PALETTED:
2052       return GST_ROUND_UP_4 (width) * height;
2053     case GST_VIDEO_FORMAT_GRAY16_BE:
2054     case GST_VIDEO_FORMAT_GRAY16_LE:
2055     case GST_VIDEO_FORMAT_Y16:
2056       return GST_ROUND_UP_4 (width * 2) * height;
2057     case GST_VIDEO_FORMAT_UYVP:
2058       return GST_ROUND_UP_4 ((width * 2 * 5 + 3) / 4) * height;
2059     case GST_VIDEO_FORMAT_A420:
2060       size = 2 * GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
2061       size += GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
2062           (GST_ROUND_UP_2 (height) / 2) * 2;
2063       return size;
2064     case GST_VIDEO_FORMAT_YUV9:
2065     case GST_VIDEO_FORMAT_YVU9:
2066       size = GST_ROUND_UP_4 (width) * height;
2067       size += GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4) *
2068           (GST_ROUND_UP_4 (height) / 4) * 2;
2069       return size;
2070     case GST_VIDEO_FORMAT_ARGB64:
2071     case GST_VIDEO_FORMAT_AYUV64:
2072       return width * 8 * height;
2073     default:
2074       return 0;
2075   }
2076 }
2077
2078 /**
2079  * gst_video_get_size_from_caps:
2080  * @caps: a pointer to #GstCaps
2081  * @size: a pointer to a gint that will be assigned the size (in bytes) of a video frame with the given caps
2082  *
2083  * Calculates the total number of bytes in the raw video format for the given
2084  * caps.  This number should be used when allocating a buffer for raw video.
2085  *
2086  * Since: 0.10.36
2087  *
2088  * Returns: %TRUE if the size could be calculated from the caps
2089  */
2090 gboolean
2091 gst_video_get_size_from_caps (const GstCaps * caps, gint * size)
2092 {
2093   GstVideoFormat format = 0;
2094   gint width = 0, height = 0;
2095
2096   g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
2097   g_return_val_if_fail (size != NULL, FALSE);
2098
2099   if (gst_video_format_parse_caps (caps, &format, &width, &height) == FALSE) {
2100     GST_WARNING ("Could not parse caps: %" GST_PTR_FORMAT, caps);
2101     return FALSE;
2102   }
2103
2104   *size = gst_video_format_get_size (format, width, height);
2105   return TRUE;
2106 }
2107
2108 /**
2109  * gst_video_format_convert:
2110  * @format: a #GstVideoFormat
2111  * @width: the width of video
2112  * @height: the height of video
2113  * @fps_n: frame rate numerator
2114  * @fps_d: frame rate denominator
2115  * @src_format: #GstFormat of the @src_value
2116  * @src_value: value to convert
2117  * @dest_format: #GstFormat of the @dest_value
2118  * @dest_value: pointer to destination value
2119  *
2120  * Converts among various #GstFormat types.  This function handles
2121  * GST_FORMAT_BYTES, GST_FORMAT_TIME, and GST_FORMAT_DEFAULT.  For
2122  * raw video, GST_FORMAT_DEFAULT corresponds to video frames.  This
2123  * function can be to handle pad queries of the type GST_QUERY_CONVERT.
2124  *
2125  * Since: 0.10.16
2126  *
2127  * Returns: TRUE if the conversion was successful.
2128  */
2129 gboolean
2130 gst_video_format_convert (GstVideoFormat format, int width, int height,
2131     int fps_n, int fps_d,
2132     GstFormat src_format, gint64 src_value,
2133     GstFormat dest_format, gint64 * dest_value)
2134 {
2135   gboolean ret = FALSE;
2136   int size;
2137
2138   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
2139   g_return_val_if_fail (width > 0 && height > 0, 0);
2140
2141   size = gst_video_format_get_size (format, width, height);
2142
2143   GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s to %s",
2144       src_value, gst_format_get_name (src_format),
2145       gst_format_get_name (dest_format));
2146
2147   if (src_format == dest_format) {
2148     *dest_value = src_value;
2149     ret = TRUE;
2150     goto done;
2151   }
2152
2153   if (src_value == -1) {
2154     *dest_value = -1;
2155     ret = TRUE;
2156     goto done;
2157   }
2158
2159   /* bytes to frames */
2160   if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_DEFAULT) {
2161     if (size != 0) {
2162       *dest_value = gst_util_uint64_scale_int (src_value, 1, size);
2163     } else {
2164       GST_ERROR ("blocksize is 0");
2165       *dest_value = 0;
2166     }
2167     ret = TRUE;
2168     goto done;
2169   }
2170
2171   /* frames to bytes */
2172   if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_BYTES) {
2173     *dest_value = gst_util_uint64_scale_int (src_value, size, 1);
2174     ret = TRUE;
2175     goto done;
2176   }
2177
2178   /* time to frames */
2179   if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_DEFAULT) {
2180     if (fps_d != 0) {
2181       *dest_value = gst_util_uint64_scale (src_value,
2182           fps_n, GST_SECOND * fps_d);
2183     } else {
2184       GST_ERROR ("framerate denominator is 0");
2185       *dest_value = 0;
2186     }
2187     ret = TRUE;
2188     goto done;
2189   }
2190
2191   /* frames to time */
2192   if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
2193     if (fps_n != 0) {
2194       *dest_value = gst_util_uint64_scale (src_value,
2195           GST_SECOND * fps_d, fps_n);
2196     } else {
2197       GST_ERROR ("framerate numerator is 0");
2198       *dest_value = 0;
2199     }
2200     ret = TRUE;
2201     goto done;
2202   }
2203
2204   /* time to bytes */
2205   if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) {
2206     if (fps_d != 0) {
2207       *dest_value = gst_util_uint64_scale (src_value,
2208           fps_n * size, GST_SECOND * fps_d);
2209     } else {
2210       GST_ERROR ("framerate denominator is 0");
2211       *dest_value = 0;
2212     }
2213     ret = TRUE;
2214     goto done;
2215   }
2216
2217   /* bytes to time */
2218   if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_TIME) {
2219     if (fps_n != 0 && size != 0) {
2220       *dest_value = gst_util_uint64_scale (src_value,
2221           GST_SECOND * fps_d, fps_n * size);
2222     } else {
2223       GST_ERROR ("framerate denominator and/or blocksize is 0");
2224       *dest_value = 0;
2225     }
2226     ret = TRUE;
2227   }
2228
2229 done:
2230
2231   GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, ret, *dest_value);
2232
2233   return ret;
2234 }
2235
2236 #define GST_VIDEO_EVENT_STILL_STATE_NAME "GstEventStillFrame"
2237
2238 /**
2239  * gst_video_event_new_still_frame:
2240  * @in_still: boolean value for the still-frame state of the event.
2241  *
2242  * Creates a new Still Frame event. If @in_still is %TRUE, then the event
2243  * represents the start of a still frame sequence. If it is %FALSE, then
2244  * the event ends a still frame sequence.
2245  *
2246  * To parse an event created by gst_video_event_new_still_frame() use
2247  * gst_video_event_parse_still_frame().
2248  *
2249  * Returns: The new GstEvent
2250  * Since: 0.10.26
2251  */
2252 GstEvent *
2253 gst_video_event_new_still_frame (gboolean in_still)
2254 {
2255   GstEvent *still_event;
2256   GstStructure *s;
2257
2258   s = gst_structure_new (GST_VIDEO_EVENT_STILL_STATE_NAME,
2259       "still-state", G_TYPE_BOOLEAN, in_still, NULL);
2260   still_event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
2261
2262   return still_event;
2263 }
2264
2265 /**
2266  * gst_video_event_parse_still_frame:
2267  * @event: A #GstEvent to parse
2268  * @in_still: A boolean to receive the still-frame status from the event, or NULL
2269  *
2270  * Parse a #GstEvent, identify if it is a Still Frame event, and
2271  * return the still-frame state from the event if it is.
2272  * If the event represents the start of a still frame, the in_still
2273  * variable will be set to TRUE, otherwise FALSE. It is OK to pass NULL for the
2274  * in_still variable order to just check whether the event is a valid still-frame
2275  * event.
2276  *
2277  * Create a still frame event using gst_video_event_new_still_frame()
2278  *
2279  * Returns: %TRUE if the event is a valid still-frame event. %FALSE if not
2280  * Since: 0.10.26
2281  */
2282 gboolean
2283 gst_video_event_parse_still_frame (GstEvent * event, gboolean * in_still)
2284 {
2285   const GstStructure *s;
2286   gboolean ev_still_state;
2287
2288   g_return_val_if_fail (event != NULL, FALSE);
2289
2290   if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_DOWNSTREAM)
2291     return FALSE;               /* Not a still frame event */
2292
2293   s = gst_event_get_structure (event);
2294   if (s == NULL
2295       || !gst_structure_has_name (s, GST_VIDEO_EVENT_STILL_STATE_NAME))
2296     return FALSE;               /* Not a still frame event */
2297   if (!gst_structure_get_boolean (s, "still-state", &ev_still_state))
2298     return FALSE;               /* Not a still frame event */
2299   if (in_still)
2300     *in_still = ev_still_state;
2301   return TRUE;
2302 }
2303
2304 /**
2305  * gst_video_parse_caps_palette:
2306  * @caps: #GstCaps to parse
2307  *
2308  * Returns the palette data from the caps as a #GstBuffer. For
2309  * #GST_VIDEO_FORMAT_RGB8_PALETTED this is containing 256 #guint32
2310  * values, each containing ARGB colors in native endianness.
2311  *
2312  * Returns: a #GstBuffer containing the palette data. Unref after usage.
2313  * Since: 0.10.32
2314  */
2315 GstBuffer *
2316 gst_video_parse_caps_palette (GstCaps * caps)
2317 {
2318   GstStructure *s;
2319   const GValue *p_v;
2320   GstBuffer *p;
2321
2322   if (!gst_caps_is_fixed (caps))
2323     return NULL;
2324
2325   s = gst_caps_get_structure (caps, 0);
2326
2327   p_v = gst_structure_get_value (s, "palette_data");
2328   if (!p_v || !GST_VALUE_HOLDS_BUFFER (p_v))
2329     return NULL;
2330
2331   p = gst_buffer_ref (gst_value_get_buffer (p_v));
2332
2333   return p;
2334 }
2335
2336 #define GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME "GstForceKeyUnit"
2337
2338 /**
2339  * gst_video_event_new_downstream_force_key_unit:
2340  * @timestamp: the timestamp of the buffer that starts a new key unit
2341  * @stream_time: the stream_time of the buffer that starts a new key unit
2342  * @running_time: the running_time of the buffer that starts a new key unit
2343  * @all_headers: %TRUE to produce headers when starting a new key unit
2344  * @count: integer that can be used to number key units
2345  *
2346  * Creates a new downstream force key unit event. A downstream force key unit
2347  * event can be sent down the pipeline to request downstream elements to produce
2348  * a key unit. A downstream force key unit event must also be sent when handling
2349  * an upstream force key unit event to notify downstream that the latter has been
2350  * handled.
2351  *
2352  * To parse an event created by gst_video_event_new_downstream_force_key_unit() use
2353  * gst_video_event_parse_downstream_force_key_unit().
2354  *
2355  * Returns: The new GstEvent
2356  * Since: 0.10.36
2357  */
2358 GstEvent *
2359 gst_video_event_new_downstream_force_key_unit (GstClockTime timestamp,
2360     GstClockTime stream_time, GstClockTime running_time, gboolean all_headers,
2361     guint count)
2362 {
2363   GstEvent *force_key_unit_event;
2364   GstStructure *s;
2365
2366   s = gst_structure_new (GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME,
2367       "timestamp", G_TYPE_UINT64, timestamp,
2368       "stream-time", G_TYPE_UINT64, stream_time,
2369       "running-time", G_TYPE_UINT64, running_time,
2370       "all-headers", G_TYPE_BOOLEAN, all_headers,
2371       "count", G_TYPE_UINT, count, NULL);
2372   force_key_unit_event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
2373
2374   return force_key_unit_event;
2375 }
2376
2377 /**
2378  * gst_video_event_new_upstream_force_key_unit:
2379  * @running_time: the running_time at which a new key unit should be produced
2380  * @all_headers: %TRUE to produce headers when starting a new key unit
2381  * @count: integer that can be used to number key units
2382  *
2383  * Creates a new upstream force key unit event. An upstream force key unit event
2384  * can be sent to request upstream elements to produce a key unit. 
2385  *
2386  * @running_time can be set to request a new key unit at a specific
2387  * running_time. If set to GST_CLOCK_TIME_NONE, upstream elements will produce a
2388  * new key unit as soon as possible.
2389  *
2390  * To parse an event created by gst_video_event_new_downstream_force_key_unit() use
2391  * gst_video_event_parse_downstream_force_key_unit().
2392  *
2393  * Returns: The new GstEvent
2394  * Since: 0.10.36
2395  */
2396 GstEvent *
2397 gst_video_event_new_upstream_force_key_unit (GstClockTime running_time,
2398     gboolean all_headers, guint count)
2399 {
2400   GstEvent *force_key_unit_event;
2401   GstStructure *s;
2402
2403   s = gst_structure_new (GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME,
2404       "running-time", GST_TYPE_CLOCK_TIME, running_time,
2405       "all-headers", G_TYPE_BOOLEAN, all_headers,
2406       "count", G_TYPE_UINT, count, NULL);
2407   force_key_unit_event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, s);
2408
2409   return force_key_unit_event;
2410 }
2411
2412 /**
2413  * gst_video_event_is_force_key_unit:
2414  * @event: A #GstEvent to check
2415  *
2416  * Checks if an event is a force key unit event. Returns true for both upstream
2417  * and downstream force key unit events.
2418  *
2419  * Returns: %TRUE if the event is a valid force key unit event
2420  * Since: 0.10.36
2421  */
2422 gboolean
2423 gst_video_event_is_force_key_unit (GstEvent * event)
2424 {
2425   const GstStructure *s;
2426
2427   g_return_val_if_fail (event != NULL, FALSE);
2428
2429   if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_DOWNSTREAM &&
2430       GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_UPSTREAM)
2431     return FALSE;               /* Not a force key unit event */
2432
2433   s = gst_event_get_structure (event);
2434   if (s == NULL
2435       || !gst_structure_has_name (s, GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME))
2436     return FALSE;
2437
2438   return TRUE;
2439 }
2440
2441 /**
2442  * gst_video_event_parse_downstream_force_key_unit:
2443  * @event: A #GstEvent to parse
2444  * @timestamp: (out): A pointer to the timestamp in the event
2445  * @stream_time: (out): A pointer to the stream-time in the event
2446  * @running_time: (out): A pointer to the running-time in the event
2447  * @all_headers: (out): A pointer to the all_headers flag in the event
2448  * @count: (out): A pointer to the count field of the event
2449  *
2450  * Get timestamp, stream-time, running-time, all-headers and count in the force
2451  * key unit event. See gst_video_event_new_downstream_force_key_unit() for a
2452  * full description of the downstream force key unit event.
2453  *
2454  * Returns: %TRUE if the event is a valid downstream force key unit event.
2455  * Since: 0.10.36
2456  */
2457 gboolean
2458 gst_video_event_parse_downstream_force_key_unit (GstEvent * event,
2459     GstClockTime * timestamp, GstClockTime * stream_time,
2460     GstClockTime * running_time, gboolean * all_headers, guint * count)
2461 {
2462   const GstStructure *s;
2463   GstClockTime ev_timestamp, ev_stream_time, ev_running_time;
2464   gboolean ev_all_headers;
2465   guint ev_count;
2466
2467   g_return_val_if_fail (event != NULL, FALSE);
2468
2469   if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_DOWNSTREAM)
2470     return FALSE;               /* Not a force key unit event */
2471
2472   s = gst_event_get_structure (event);
2473   if (s == NULL
2474       || !gst_structure_has_name (s, GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME))
2475     return FALSE;
2476
2477   if (!gst_structure_get_clock_time (s, "timestamp", &ev_timestamp))
2478     return FALSE;               /* Not a force key unit event */
2479   if (!gst_structure_get_clock_time (s, "stream-time", &ev_stream_time))
2480     return FALSE;               /* Not a force key unit event */
2481   if (!gst_structure_get_clock_time (s, "running-time", &ev_running_time))
2482     return FALSE;               /* Not a force key unit event */
2483   if (!gst_structure_get_boolean (s, "all-headers", &ev_all_headers))
2484     return FALSE;               /* Not a force key unit event */
2485   if (!gst_structure_get_uint (s, "count", &ev_count))
2486     return FALSE;               /* Not a force key unit event */
2487
2488   if (timestamp)
2489     *timestamp = ev_timestamp;
2490
2491   if (stream_time)
2492     *stream_time = ev_stream_time;
2493
2494   if (running_time)
2495     *running_time = ev_running_time;
2496
2497   if (all_headers)
2498     *all_headers = ev_all_headers;
2499
2500   if (count)
2501     *count = ev_count;
2502
2503   return TRUE;
2504 }
2505
2506 /**
2507  * gst_video_event_parse_upstream_force_key_unit:
2508  * @event: A #GstEvent to parse
2509  * @running_time: (out): A pointer to the running_time in the event
2510  * @all_headers: (out): A pointer to the all_headers flag in the event
2511  * @count: (out): A pointer to the count field in the event
2512  *
2513  * Get running-time, all-headers and count in the force key unit event. See
2514  * gst_video_event_new_upstream_force_key_unit() for a full description of the
2515  * upstream force key unit event.
2516  *
2517  * Create an upstream force key unit event using  gst_video_event_new_upstream_force_key_unit()
2518  *
2519  * Returns: %TRUE if the event is a valid upstream force-key-unit event. %FALSE if not
2520  * Since: 0.10.36
2521  */
2522 gboolean
2523 gst_video_event_parse_upstream_force_key_unit (GstEvent * event,
2524     GstClockTime * running_time, gboolean * all_headers, guint * count)
2525 {
2526   const GstStructure *s;
2527   GstClockTime ev_running_time;
2528   gboolean ev_all_headers;
2529   guint ev_count;
2530
2531   g_return_val_if_fail (event != NULL, FALSE);
2532
2533   if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_UPSTREAM)
2534     return FALSE;               /* Not a force key unit event */
2535
2536   s = gst_event_get_structure (event);
2537   if (s == NULL
2538       || !gst_structure_has_name (s, GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME))
2539     return FALSE;
2540
2541   if (!gst_structure_get_clock_time (s, "running-time", &ev_running_time))
2542     return FALSE;               /* Not a force key unit event */
2543   if (!gst_structure_get_boolean (s, "all-headers", &ev_all_headers))
2544     return FALSE;               /* Not a force key unit event */
2545   if (!gst_structure_get_uint (s, "count", &ev_count))
2546     return FALSE;               /* Not a force key unit event */
2547
2548   if (running_time)
2549     *running_time = ev_running_time;
2550
2551   if (all_headers)
2552     *all_headers = ev_all_headers;
2553
2554   if (count)
2555     *count = ev_count;
2556
2557   return TRUE;
2558 }