tizen 2.3.1 release
[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 #ifdef GST_EXT_XV_ENHANCEMENT
881     case GST_MAKE_FOURCC ('S', 'T', '1', '2'):
882       return GST_VIDEO_FORMAT_ST12;
883     case GST_MAKE_FOURCC ('S', 'N', '1', '2'):
884       return GST_VIDEO_FORMAT_SN12;
885     case GST_MAKE_FOURCC ('S', 'U', 'Y', 'V'):
886       return GST_VIDEO_FORMAT_SUYV;
887     case GST_MAKE_FOURCC ('S', 'U', 'Y', '2'):
888       return GST_VIDEO_FORMAT_SUY2;
889     case GST_MAKE_FOURCC ('S', '4', '2', '0'):
890       return GST_VIDEO_FORMAT_S420;
891     case GST_MAKE_FOURCC ('S', 'Y', 'V', 'Y'):
892       return GST_VIDEO_FORMAT_SYVY;
893 #endif
894     default:
895       return GST_VIDEO_FORMAT_UNKNOWN;
896   }
897 }
898
899 /**
900  * gst_video_format_to_fourcc:
901  * @format: a #GstVideoFormat video format
902  *
903  * Converts a #GstVideoFormat value into the corresponding FOURCC.  Only
904  * a few YUV formats have corresponding FOURCC values.  If @format has
905  * no corresponding FOURCC value, 0 is returned.
906  *
907  * Since: 0.10.16
908  *
909  * Returns: the FOURCC corresponding to @format
910  */
911 guint32
912 gst_video_format_to_fourcc (GstVideoFormat format)
913 {
914   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
915
916   switch (format) {
917     case GST_VIDEO_FORMAT_I420:
918       return GST_MAKE_FOURCC ('I', '4', '2', '0');
919     case GST_VIDEO_FORMAT_YV12:
920       return GST_MAKE_FOURCC ('Y', 'V', '1', '2');
921     case GST_VIDEO_FORMAT_YUY2:
922       return GST_MAKE_FOURCC ('Y', 'U', 'Y', '2');
923     case GST_VIDEO_FORMAT_YVYU:
924       return GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U');
925     case GST_VIDEO_FORMAT_UYVY:
926       return GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y');
927     case GST_VIDEO_FORMAT_AYUV:
928       return GST_MAKE_FOURCC ('A', 'Y', 'U', 'V');
929     case GST_VIDEO_FORMAT_Y41B:
930       return GST_MAKE_FOURCC ('Y', '4', '1', 'B');
931     case GST_VIDEO_FORMAT_Y42B:
932       return GST_MAKE_FOURCC ('Y', '4', '2', 'B');
933     case GST_VIDEO_FORMAT_Y444:
934       return GST_MAKE_FOURCC ('Y', '4', '4', '4');
935     case GST_VIDEO_FORMAT_v210:
936       return GST_MAKE_FOURCC ('v', '2', '1', '0');
937     case GST_VIDEO_FORMAT_v216:
938       return GST_MAKE_FOURCC ('v', '2', '1', '6');
939     case GST_VIDEO_FORMAT_NV12:
940       return GST_MAKE_FOURCC ('N', 'V', '1', '2');
941     case GST_VIDEO_FORMAT_NV21:
942       return GST_MAKE_FOURCC ('N', 'V', '2', '1');
943     case GST_VIDEO_FORMAT_v308:
944       return GST_MAKE_FOURCC ('v', '3', '0', '8');
945     case GST_VIDEO_FORMAT_Y800:
946       return GST_MAKE_FOURCC ('Y', '8', '0', '0');
947     case GST_VIDEO_FORMAT_Y16:
948       return GST_MAKE_FOURCC ('Y', '1', '6', ' ');
949     case GST_VIDEO_FORMAT_UYVP:
950       return GST_MAKE_FOURCC ('U', 'Y', 'V', 'P');
951     case GST_VIDEO_FORMAT_A420:
952       return GST_MAKE_FOURCC ('A', '4', '2', '0');
953     case GST_VIDEO_FORMAT_YUV9:
954       return GST_MAKE_FOURCC ('Y', 'U', 'V', '9');
955     case GST_VIDEO_FORMAT_YVU9:
956       return GST_MAKE_FOURCC ('Y', 'V', 'U', '9');
957     case GST_VIDEO_FORMAT_IYU1:
958       return GST_MAKE_FOURCC ('I', 'Y', 'U', '1');
959     case GST_VIDEO_FORMAT_AYUV64:
960       return GST_MAKE_FOURCC ('A', 'Y', '6', '4');
961 #ifdef GST_EXT_XV_ENHANCEMENT
962     case GST_VIDEO_FORMAT_ST12:
963       return GST_MAKE_FOURCC ('S', 'T', '1', '2');
964     case GST_VIDEO_FORMAT_SN12:
965       return GST_MAKE_FOURCC ('S', 'N', '1', '2');
966     case GST_VIDEO_FORMAT_SUYV:
967       return GST_MAKE_FOURCC ('S', 'U', 'Y', 'V');
968     case GST_VIDEO_FORMAT_SUY2:
969       return GST_MAKE_FOURCC ('S', 'U', 'Y', '2');
970     case GST_VIDEO_FORMAT_S420:
971       return GST_MAKE_FOURCC ('S', '4', '2', '0');
972     case GST_VIDEO_FORMAT_SYVY:
973       return GST_MAKE_FOURCC ('S', 'Y', 'V', 'Y');
974 #endif
975     default:
976       return 0;
977   }
978 }
979
980 /*
981  * gst_video_format_from_rgb32_masks:
982  * @red_mask: red bit mask
983  * @green_mask: green bit mask
984  * @blue_mask: blue bit mask
985  *
986  * Converts red, green, blue bit masks into the corresponding
987  * #GstVideoFormat.
988  *
989  * Since: 0.10.16
990  *
991  * Returns: the #GstVideoFormat corresponding to the bit masks
992  */
993 static GstVideoFormat
994 gst_video_format_from_rgb32_masks (int red_mask, int green_mask, int blue_mask)
995 {
996   if (red_mask == 0xff000000 && green_mask == 0x00ff0000 &&
997       blue_mask == 0x0000ff00) {
998     return GST_VIDEO_FORMAT_RGBx;
999   }
1000   if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 &&
1001       blue_mask == 0xff000000) {
1002     return GST_VIDEO_FORMAT_BGRx;
1003   }
1004   if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 &&
1005       blue_mask == 0x000000ff) {
1006     return GST_VIDEO_FORMAT_xRGB;
1007   }
1008   if (red_mask == 0x000000ff && green_mask == 0x0000ff00 &&
1009       blue_mask == 0x00ff0000) {
1010     return GST_VIDEO_FORMAT_xBGR;
1011   }
1012
1013   return GST_VIDEO_FORMAT_UNKNOWN;
1014 }
1015
1016 static GstVideoFormat
1017 gst_video_format_from_rgba32_masks (int red_mask, int green_mask,
1018     int blue_mask, int alpha_mask)
1019 {
1020   if (red_mask == 0xff000000 && green_mask == 0x00ff0000 &&
1021       blue_mask == 0x0000ff00 && alpha_mask == 0x000000ff) {
1022     return GST_VIDEO_FORMAT_RGBA;
1023   }
1024   if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 &&
1025       blue_mask == 0xff000000 && alpha_mask == 0x000000ff) {
1026     return GST_VIDEO_FORMAT_BGRA;
1027   }
1028   if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 &&
1029       blue_mask == 0x000000ff && alpha_mask == 0xff000000) {
1030     return GST_VIDEO_FORMAT_ARGB;
1031   }
1032   if (red_mask == 0x000000ff && green_mask == 0x0000ff00 &&
1033       blue_mask == 0x00ff0000 && alpha_mask == 0xff000000) {
1034     return GST_VIDEO_FORMAT_ABGR;
1035   }
1036
1037   return GST_VIDEO_FORMAT_UNKNOWN;
1038 }
1039
1040 static GstVideoFormat
1041 gst_video_format_from_rgb24_masks (int red_mask, int green_mask, int blue_mask)
1042 {
1043   if (red_mask == 0xff0000 && green_mask == 0x00ff00 && blue_mask == 0x0000ff) {
1044     return GST_VIDEO_FORMAT_RGB;
1045   }
1046   if (red_mask == 0x0000ff && green_mask == 0x00ff00 && blue_mask == 0xff0000) {
1047     return GST_VIDEO_FORMAT_BGR;
1048   }
1049
1050   return GST_VIDEO_FORMAT_UNKNOWN;
1051 }
1052
1053 static GstVideoFormat
1054 gst_video_format_from_rgb16_masks (int red_mask, int green_mask, int blue_mask)
1055 {
1056   if (red_mask == GST_VIDEO_COMP1_MASK_16_INT
1057       && green_mask == GST_VIDEO_COMP2_MASK_16_INT
1058       && blue_mask == GST_VIDEO_COMP3_MASK_16_INT) {
1059     return GST_VIDEO_FORMAT_RGB16;
1060   }
1061   if (red_mask == GST_VIDEO_COMP3_MASK_16_INT
1062       && green_mask == GST_VIDEO_COMP2_MASK_16_INT
1063       && blue_mask == GST_VIDEO_COMP1_MASK_16_INT) {
1064     return GST_VIDEO_FORMAT_BGR16;
1065   }
1066   if (red_mask == GST_VIDEO_COMP1_MASK_15_INT
1067       && green_mask == GST_VIDEO_COMP2_MASK_15_INT
1068       && blue_mask == GST_VIDEO_COMP3_MASK_15_INT) {
1069     return GST_VIDEO_FORMAT_RGB15;
1070   }
1071   if (red_mask == GST_VIDEO_COMP3_MASK_15_INT
1072       && green_mask == GST_VIDEO_COMP2_MASK_15_INT
1073       && blue_mask == GST_VIDEO_COMP1_MASK_15_INT) {
1074     return GST_VIDEO_FORMAT_BGR15;
1075   }
1076
1077   return GST_VIDEO_FORMAT_UNKNOWN;
1078 }
1079
1080 /**
1081  * gst_video_format_is_rgb:
1082  * @format: a #GstVideoFormat
1083  *
1084  * Determine whether the video format is an RGB format.
1085  *
1086  * Since: 0.10.16
1087  *
1088  * Returns: TRUE if @format represents RGB video
1089  */
1090 gboolean
1091 gst_video_format_is_rgb (GstVideoFormat format)
1092 {
1093   switch (format) {
1094     case GST_VIDEO_FORMAT_I420:
1095     case GST_VIDEO_FORMAT_YV12:
1096     case GST_VIDEO_FORMAT_YUY2:
1097     case GST_VIDEO_FORMAT_YVYU:
1098     case GST_VIDEO_FORMAT_UYVY:
1099     case GST_VIDEO_FORMAT_AYUV:
1100     case GST_VIDEO_FORMAT_Y41B:
1101     case GST_VIDEO_FORMAT_Y42B:
1102     case GST_VIDEO_FORMAT_Y444:
1103     case GST_VIDEO_FORMAT_v210:
1104     case GST_VIDEO_FORMAT_v216:
1105     case GST_VIDEO_FORMAT_NV12:
1106     case GST_VIDEO_FORMAT_NV21:
1107     case GST_VIDEO_FORMAT_v308:
1108     case GST_VIDEO_FORMAT_UYVP:
1109     case GST_VIDEO_FORMAT_A420:
1110     case GST_VIDEO_FORMAT_YUV9:
1111     case GST_VIDEO_FORMAT_YVU9:
1112     case GST_VIDEO_FORMAT_IYU1:
1113     case GST_VIDEO_FORMAT_AYUV64:
1114       return FALSE;
1115     case GST_VIDEO_FORMAT_RGBx:
1116     case GST_VIDEO_FORMAT_BGRx:
1117     case GST_VIDEO_FORMAT_xRGB:
1118     case GST_VIDEO_FORMAT_xBGR:
1119     case GST_VIDEO_FORMAT_RGBA:
1120     case GST_VIDEO_FORMAT_BGRA:
1121     case GST_VIDEO_FORMAT_ARGB:
1122     case GST_VIDEO_FORMAT_ABGR:
1123     case GST_VIDEO_FORMAT_RGB:
1124     case GST_VIDEO_FORMAT_BGR:
1125     case GST_VIDEO_FORMAT_RGB16:
1126     case GST_VIDEO_FORMAT_BGR16:
1127     case GST_VIDEO_FORMAT_RGB15:
1128     case GST_VIDEO_FORMAT_BGR15:
1129     case GST_VIDEO_FORMAT_RGB8_PALETTED:
1130     case GST_VIDEO_FORMAT_ARGB64:
1131     case GST_VIDEO_FORMAT_r210:
1132       return TRUE;
1133     default:
1134       return FALSE;
1135   }
1136 }
1137
1138 /**
1139  * gst_video_format_is_yuv:
1140  * @format: a #GstVideoFormat
1141  *
1142  * Determine whether the video format is a YUV format.
1143  *
1144  * Since: 0.10.16
1145  *
1146  * Returns: TRUE if @format represents YUV video
1147  */
1148 gboolean
1149 gst_video_format_is_yuv (GstVideoFormat format)
1150 {
1151   switch (format) {
1152     case GST_VIDEO_FORMAT_I420:
1153     case GST_VIDEO_FORMAT_YV12:
1154     case GST_VIDEO_FORMAT_YUY2:
1155     case GST_VIDEO_FORMAT_YVYU:
1156     case GST_VIDEO_FORMAT_UYVY:
1157     case GST_VIDEO_FORMAT_AYUV:
1158     case GST_VIDEO_FORMAT_Y41B:
1159     case GST_VIDEO_FORMAT_Y42B:
1160     case GST_VIDEO_FORMAT_Y444:
1161     case GST_VIDEO_FORMAT_v210:
1162     case GST_VIDEO_FORMAT_v216:
1163     case GST_VIDEO_FORMAT_NV12:
1164     case GST_VIDEO_FORMAT_NV21:
1165     case GST_VIDEO_FORMAT_v308:
1166     case GST_VIDEO_FORMAT_Y800:
1167     case GST_VIDEO_FORMAT_Y16:
1168     case GST_VIDEO_FORMAT_UYVP:
1169     case GST_VIDEO_FORMAT_A420:
1170     case GST_VIDEO_FORMAT_YUV9:
1171     case GST_VIDEO_FORMAT_YVU9:
1172     case GST_VIDEO_FORMAT_IYU1:
1173     case GST_VIDEO_FORMAT_AYUV64:
1174       return TRUE;
1175     case GST_VIDEO_FORMAT_RGBx:
1176     case GST_VIDEO_FORMAT_BGRx:
1177     case GST_VIDEO_FORMAT_xRGB:
1178     case GST_VIDEO_FORMAT_xBGR:
1179     case GST_VIDEO_FORMAT_RGBA:
1180     case GST_VIDEO_FORMAT_BGRA:
1181     case GST_VIDEO_FORMAT_ARGB:
1182     case GST_VIDEO_FORMAT_ABGR:
1183     case GST_VIDEO_FORMAT_RGB:
1184     case GST_VIDEO_FORMAT_BGR:
1185     case GST_VIDEO_FORMAT_RGB16:
1186     case GST_VIDEO_FORMAT_BGR16:
1187     case GST_VIDEO_FORMAT_RGB15:
1188     case GST_VIDEO_FORMAT_BGR15:
1189     case GST_VIDEO_FORMAT_RGB8_PALETTED:
1190     case GST_VIDEO_FORMAT_ARGB64:
1191     case GST_VIDEO_FORMAT_r210:
1192       return FALSE;
1193     default:
1194       return FALSE;
1195   }
1196 }
1197
1198 /**
1199  * gst_video_format_is_gray:
1200  * @format: a #GstVideoFormat
1201  *
1202  * Determine whether the video format is a grayscale format.
1203  *
1204  * Since: 0.10.29
1205  *
1206  * Returns: TRUE if @format represents grayscale video
1207  */
1208 gboolean
1209 gst_video_format_is_gray (GstVideoFormat format)
1210 {
1211   switch (format) {
1212     case GST_VIDEO_FORMAT_GRAY8:
1213     case GST_VIDEO_FORMAT_GRAY16_BE:
1214     case GST_VIDEO_FORMAT_GRAY16_LE:
1215     case GST_VIDEO_FORMAT_Y800:
1216     case GST_VIDEO_FORMAT_Y16:
1217       return TRUE;
1218     default:
1219       return FALSE;
1220   }
1221 }
1222
1223 /**
1224  * gst_video_format_has_alpha:
1225  * @format: a #GstVideoFormat
1226  *
1227  * Returns TRUE or FALSE depending on if the video format provides an
1228  * alpha channel.
1229  *
1230  * Since: 0.10.16
1231  *
1232  * Returns: TRUE if @format has an alpha channel
1233  */
1234 gboolean
1235 gst_video_format_has_alpha (GstVideoFormat format)
1236 {
1237   switch (format) {
1238     case GST_VIDEO_FORMAT_I420:
1239     case GST_VIDEO_FORMAT_YV12:
1240     case GST_VIDEO_FORMAT_YUY2:
1241     case GST_VIDEO_FORMAT_YVYU:
1242     case GST_VIDEO_FORMAT_UYVY:
1243     case GST_VIDEO_FORMAT_Y41B:
1244     case GST_VIDEO_FORMAT_Y42B:
1245     case GST_VIDEO_FORMAT_Y444:
1246     case GST_VIDEO_FORMAT_v210:
1247     case GST_VIDEO_FORMAT_v216:
1248     case GST_VIDEO_FORMAT_NV12:
1249     case GST_VIDEO_FORMAT_NV21:
1250     case GST_VIDEO_FORMAT_v308:
1251     case GST_VIDEO_FORMAT_Y800:
1252     case GST_VIDEO_FORMAT_Y16:
1253     case GST_VIDEO_FORMAT_UYVP:
1254     case GST_VIDEO_FORMAT_YUV9:
1255     case GST_VIDEO_FORMAT_YVU9:
1256     case GST_VIDEO_FORMAT_IYU1:
1257       return FALSE;
1258     case GST_VIDEO_FORMAT_AYUV:
1259     case GST_VIDEO_FORMAT_RGBA:
1260     case GST_VIDEO_FORMAT_BGRA:
1261     case GST_VIDEO_FORMAT_ARGB:
1262     case GST_VIDEO_FORMAT_ABGR:
1263     case GST_VIDEO_FORMAT_A420:
1264     case GST_VIDEO_FORMAT_RGB8_PALETTED:
1265     case GST_VIDEO_FORMAT_ARGB64:
1266     case GST_VIDEO_FORMAT_AYUV64:
1267       return TRUE;
1268     case GST_VIDEO_FORMAT_RGBx:
1269     case GST_VIDEO_FORMAT_BGRx:
1270     case GST_VIDEO_FORMAT_xRGB:
1271     case GST_VIDEO_FORMAT_xBGR:
1272     case GST_VIDEO_FORMAT_RGB:
1273     case GST_VIDEO_FORMAT_BGR:
1274     case GST_VIDEO_FORMAT_RGB16:
1275     case GST_VIDEO_FORMAT_BGR16:
1276     case GST_VIDEO_FORMAT_RGB15:
1277     case GST_VIDEO_FORMAT_BGR15:
1278     case GST_VIDEO_FORMAT_r210:
1279       return FALSE;
1280     default:
1281       return FALSE;
1282   }
1283 }
1284
1285 /**
1286  * gst_video_format_get_component_depth:
1287  * @format: a #GstVideoFormat
1288  * @component: the video component (e.g. 0 for 'R' in RGB)
1289  *
1290  * Returns the number of bits used to encode an individual pixel of
1291  * a given @component.  Typically this is 8, although higher and lower
1292  * values are possible for some formats.
1293  *
1294  * Since: 0.10.33
1295  *
1296  * Returns: depth of component
1297  */
1298 int
1299 gst_video_format_get_component_depth (GstVideoFormat format, int component)
1300 {
1301   if (component == 3 && !gst_video_format_has_alpha (format))
1302     return 0;
1303
1304   switch (format) {
1305     case GST_VIDEO_FORMAT_RGB16:
1306     case GST_VIDEO_FORMAT_BGR16:
1307       if (component == 1)
1308         return 6;
1309       return 5;
1310     case GST_VIDEO_FORMAT_RGB15:
1311     case GST_VIDEO_FORMAT_BGR15:
1312       return 5;
1313     case GST_VIDEO_FORMAT_I420:
1314     case GST_VIDEO_FORMAT_YV12:
1315     case GST_VIDEO_FORMAT_YUY2:
1316     case GST_VIDEO_FORMAT_YVYU:
1317     case GST_VIDEO_FORMAT_UYVY:
1318     case GST_VIDEO_FORMAT_Y41B:
1319     case GST_VIDEO_FORMAT_Y42B:
1320     case GST_VIDEO_FORMAT_Y444:
1321     case GST_VIDEO_FORMAT_NV12:
1322     case GST_VIDEO_FORMAT_NV21:
1323     case GST_VIDEO_FORMAT_v308:
1324     case GST_VIDEO_FORMAT_Y800:
1325     case GST_VIDEO_FORMAT_YUV9:
1326     case GST_VIDEO_FORMAT_YVU9:
1327     case GST_VIDEO_FORMAT_IYU1:
1328     case GST_VIDEO_FORMAT_AYUV:
1329     case GST_VIDEO_FORMAT_RGBA:
1330     case GST_VIDEO_FORMAT_BGRA:
1331     case GST_VIDEO_FORMAT_ARGB:
1332     case GST_VIDEO_FORMAT_ABGR:
1333     case GST_VIDEO_FORMAT_A420:
1334     case GST_VIDEO_FORMAT_RGB8_PALETTED:
1335     case GST_VIDEO_FORMAT_RGBx:
1336     case GST_VIDEO_FORMAT_BGRx:
1337     case GST_VIDEO_FORMAT_xRGB:
1338     case GST_VIDEO_FORMAT_xBGR:
1339     case GST_VIDEO_FORMAT_RGB:
1340     case GST_VIDEO_FORMAT_BGR:
1341     default:
1342       return 8;
1343     case GST_VIDEO_FORMAT_v210:
1344     case GST_VIDEO_FORMAT_UYVP:
1345     case GST_VIDEO_FORMAT_r210:
1346       return 10;
1347     case GST_VIDEO_FORMAT_Y16:
1348     case GST_VIDEO_FORMAT_v216:
1349     case GST_VIDEO_FORMAT_ARGB64:
1350     case GST_VIDEO_FORMAT_AYUV64:
1351       return 16;
1352   }
1353
1354 }
1355
1356 /**
1357  * gst_video_format_get_row_stride:
1358  * @format: a #GstVideoFormat
1359  * @component: the component index
1360  * @width: the width of video
1361  *
1362  * Calculates the row stride (number of bytes from one row of pixels to
1363  * the next) for the video component with an index of @component.  For
1364  * YUV video, Y, U, and V have component indices of 0, 1, and 2,
1365  * respectively.  For RGB video, R, G, and B have component indicies of
1366  * 0, 1, and 2, respectively.  Alpha channels, if present, have a component
1367  * index of 3.  The @width parameter always represents the width of the
1368  * video, not the component.
1369  *
1370  * Since: 0.10.16
1371  *
1372  * Returns: row stride of component @component
1373  */
1374 int
1375 gst_video_format_get_row_stride (GstVideoFormat format, int component,
1376     int width)
1377 {
1378   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1379   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1380   g_return_val_if_fail (width > 0, 0);
1381
1382   switch (format) {
1383     case GST_VIDEO_FORMAT_I420:
1384     case GST_VIDEO_FORMAT_YV12:
1385       if (component == 0) {
1386         return GST_ROUND_UP_4 (width);
1387       } else {
1388         return GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
1389       }
1390     case GST_VIDEO_FORMAT_YUY2:
1391     case GST_VIDEO_FORMAT_YVYU:
1392     case GST_VIDEO_FORMAT_UYVY:
1393       return GST_ROUND_UP_4 (width * 2);
1394     case GST_VIDEO_FORMAT_AYUV:
1395     case GST_VIDEO_FORMAT_RGBx:
1396     case GST_VIDEO_FORMAT_BGRx:
1397     case GST_VIDEO_FORMAT_xRGB:
1398     case GST_VIDEO_FORMAT_xBGR:
1399     case GST_VIDEO_FORMAT_RGBA:
1400     case GST_VIDEO_FORMAT_BGRA:
1401     case GST_VIDEO_FORMAT_ARGB:
1402     case GST_VIDEO_FORMAT_ABGR:
1403     case GST_VIDEO_FORMAT_r210:
1404       return width * 4;
1405     case GST_VIDEO_FORMAT_RGB16:
1406     case GST_VIDEO_FORMAT_BGR16:
1407     case GST_VIDEO_FORMAT_RGB15:
1408     case GST_VIDEO_FORMAT_BGR15:
1409       return GST_ROUND_UP_4 (width * 2);
1410     case GST_VIDEO_FORMAT_RGB:
1411     case GST_VIDEO_FORMAT_BGR:
1412     case GST_VIDEO_FORMAT_v308:
1413       return GST_ROUND_UP_4 (width * 3);
1414     case GST_VIDEO_FORMAT_Y41B:
1415       if (component == 0) {
1416         return GST_ROUND_UP_4 (width);
1417       } else {
1418         return GST_ROUND_UP_16 (width) / 4;
1419       }
1420     case GST_VIDEO_FORMAT_Y42B:
1421       if (component == 0) {
1422         return GST_ROUND_UP_4 (width);
1423       } else {
1424         return GST_ROUND_UP_8 (width) / 2;
1425       }
1426     case GST_VIDEO_FORMAT_Y444:
1427       return GST_ROUND_UP_4 (width);
1428     case GST_VIDEO_FORMAT_v210:
1429       return ((width + 47) / 48) * 128;
1430     case GST_VIDEO_FORMAT_v216:
1431       return GST_ROUND_UP_8 (width * 4);
1432     case GST_VIDEO_FORMAT_NV12:
1433     case GST_VIDEO_FORMAT_NV21:
1434       return GST_ROUND_UP_4 (width);
1435     case GST_VIDEO_FORMAT_GRAY8:
1436     case GST_VIDEO_FORMAT_Y800:
1437       return GST_ROUND_UP_4 (width);
1438     case GST_VIDEO_FORMAT_GRAY16_BE:
1439     case GST_VIDEO_FORMAT_GRAY16_LE:
1440     case GST_VIDEO_FORMAT_Y16:
1441       return GST_ROUND_UP_4 (width * 2);
1442     case GST_VIDEO_FORMAT_UYVP:
1443       return GST_ROUND_UP_4 ((width * 2 * 5 + 3) / 4);
1444     case GST_VIDEO_FORMAT_A420:
1445       if (component == 0 || component == 3) {
1446         return GST_ROUND_UP_4 (width);
1447       } else {
1448         return GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
1449       }
1450     case GST_VIDEO_FORMAT_RGB8_PALETTED:
1451       return GST_ROUND_UP_4 (width);
1452     case GST_VIDEO_FORMAT_YUV9:
1453     case GST_VIDEO_FORMAT_YVU9:
1454       if (component == 0) {
1455         return GST_ROUND_UP_4 (width);
1456       } else {
1457         return GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4);
1458       }
1459     case GST_VIDEO_FORMAT_IYU1:
1460       return GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) +
1461           GST_ROUND_UP_4 (width) / 2);
1462     case GST_VIDEO_FORMAT_ARGB64:
1463     case GST_VIDEO_FORMAT_AYUV64:
1464       return width * 8;
1465     default:
1466       return 0;
1467   }
1468 }
1469
1470 /**
1471  * gst_video_format_get_pixel_stride:
1472  * @format: a #GstVideoFormat
1473  * @component: the component index
1474  *
1475  * Calculates the pixel stride (number of bytes from one pixel to the
1476  * pixel to its immediate left) for the video component with an index
1477  * of @component.  See @gst_video_format_get_row_stride for a description
1478  * of the component index.
1479  *
1480  * Since: 0.10.16
1481  *
1482  * Returns: pixel stride of component @component
1483  */
1484 int
1485 gst_video_format_get_pixel_stride (GstVideoFormat format, int component)
1486 {
1487   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1488   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1489
1490   switch (format) {
1491     case GST_VIDEO_FORMAT_I420:
1492     case GST_VIDEO_FORMAT_YV12:
1493     case GST_VIDEO_FORMAT_Y41B:
1494     case GST_VIDEO_FORMAT_Y42B:
1495     case GST_VIDEO_FORMAT_Y444:
1496     case GST_VIDEO_FORMAT_A420:
1497     case GST_VIDEO_FORMAT_YUV9:
1498     case GST_VIDEO_FORMAT_YVU9:
1499       return 1;
1500     case GST_VIDEO_FORMAT_YUY2:
1501     case GST_VIDEO_FORMAT_YVYU:
1502     case GST_VIDEO_FORMAT_UYVY:
1503       if (component == 0) {
1504         return 2;
1505       } else {
1506         return 4;
1507       }
1508     case GST_VIDEO_FORMAT_IYU1:
1509       /* doesn't make much sense for IYU1 because it's 1 or 3
1510        * for luma depending on position */
1511       return 0;
1512     case GST_VIDEO_FORMAT_AYUV:
1513     case GST_VIDEO_FORMAT_RGBx:
1514     case GST_VIDEO_FORMAT_BGRx:
1515     case GST_VIDEO_FORMAT_xRGB:
1516     case GST_VIDEO_FORMAT_xBGR:
1517     case GST_VIDEO_FORMAT_RGBA:
1518     case GST_VIDEO_FORMAT_BGRA:
1519     case GST_VIDEO_FORMAT_ARGB:
1520     case GST_VIDEO_FORMAT_ABGR:
1521     case GST_VIDEO_FORMAT_r210:
1522       return 4;
1523     case GST_VIDEO_FORMAT_RGB16:
1524     case GST_VIDEO_FORMAT_BGR16:
1525     case GST_VIDEO_FORMAT_RGB15:
1526     case GST_VIDEO_FORMAT_BGR15:
1527       return 2;
1528     case GST_VIDEO_FORMAT_RGB:
1529     case GST_VIDEO_FORMAT_BGR:
1530     case GST_VIDEO_FORMAT_v308:
1531       return 3;
1532     case GST_VIDEO_FORMAT_v210:
1533       /* v210 is packed at the bit level, so pixel stride doesn't make sense */
1534       return 0;
1535     case GST_VIDEO_FORMAT_v216:
1536       if (component == 0) {
1537         return 4;
1538       } else {
1539         return 8;
1540       }
1541     case GST_VIDEO_FORMAT_NV12:
1542     case GST_VIDEO_FORMAT_NV21:
1543       if (component == 0) {
1544         return 1;
1545       } else {
1546         return 2;
1547       }
1548     case GST_VIDEO_FORMAT_GRAY8:
1549     case GST_VIDEO_FORMAT_Y800:
1550       return 1;
1551     case GST_VIDEO_FORMAT_GRAY16_BE:
1552     case GST_VIDEO_FORMAT_GRAY16_LE:
1553     case GST_VIDEO_FORMAT_Y16:
1554       return 2;
1555     case GST_VIDEO_FORMAT_UYVP:
1556       /* UYVP is packed at the bit level, so pixel stride doesn't make sense */
1557       return 0;
1558     case GST_VIDEO_FORMAT_RGB8_PALETTED:
1559       return 1;
1560     case GST_VIDEO_FORMAT_ARGB64:
1561     case GST_VIDEO_FORMAT_AYUV64:
1562       return 8;
1563     default:
1564       return 0;
1565   }
1566 }
1567
1568 /**
1569  * gst_video_format_get_component_width:
1570  * @format: a #GstVideoFormat
1571  * @component: the component index
1572  * @width: the width of video
1573  *
1574  * Calculates the width of the component.  See
1575  * @gst_video_format_get_row_stride for a description
1576  * of the component index.
1577  *
1578  * Since: 0.10.16
1579  *
1580  * Returns: width of component @component
1581  */
1582 int
1583 gst_video_format_get_component_width (GstVideoFormat format,
1584     int component, int width)
1585 {
1586   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1587   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1588   g_return_val_if_fail (width > 0, 0);
1589
1590   switch (format) {
1591     case GST_VIDEO_FORMAT_I420:
1592     case GST_VIDEO_FORMAT_YV12:
1593     case GST_VIDEO_FORMAT_YUY2:
1594     case GST_VIDEO_FORMAT_YVYU:
1595     case GST_VIDEO_FORMAT_UYVY:
1596     case GST_VIDEO_FORMAT_Y42B:
1597     case GST_VIDEO_FORMAT_v210:
1598     case GST_VIDEO_FORMAT_v216:
1599     case GST_VIDEO_FORMAT_NV12:
1600     case GST_VIDEO_FORMAT_NV21:
1601     case GST_VIDEO_FORMAT_UYVP:
1602       if (component == 0) {
1603         return width;
1604       } else {
1605         return GST_ROUND_UP_2 (width) / 2;
1606       }
1607     case GST_VIDEO_FORMAT_Y41B:
1608     case GST_VIDEO_FORMAT_YUV9:
1609     case GST_VIDEO_FORMAT_YVU9:
1610     case GST_VIDEO_FORMAT_IYU1:
1611       if (component == 0) {
1612         return width;
1613       } else {
1614         return GST_ROUND_UP_4 (width) / 4;
1615       }
1616     case GST_VIDEO_FORMAT_AYUV:
1617     case GST_VIDEO_FORMAT_RGBx:
1618     case GST_VIDEO_FORMAT_BGRx:
1619     case GST_VIDEO_FORMAT_xRGB:
1620     case GST_VIDEO_FORMAT_xBGR:
1621     case GST_VIDEO_FORMAT_RGBA:
1622     case GST_VIDEO_FORMAT_BGRA:
1623     case GST_VIDEO_FORMAT_ARGB:
1624     case GST_VIDEO_FORMAT_ABGR:
1625     case GST_VIDEO_FORMAT_RGB:
1626     case GST_VIDEO_FORMAT_BGR:
1627     case GST_VIDEO_FORMAT_RGB16:
1628     case GST_VIDEO_FORMAT_BGR16:
1629     case GST_VIDEO_FORMAT_RGB15:
1630     case GST_VIDEO_FORMAT_BGR15:
1631     case GST_VIDEO_FORMAT_Y444:
1632     case GST_VIDEO_FORMAT_v308:
1633     case GST_VIDEO_FORMAT_GRAY8:
1634     case GST_VIDEO_FORMAT_GRAY16_BE:
1635     case GST_VIDEO_FORMAT_GRAY16_LE:
1636     case GST_VIDEO_FORMAT_Y800:
1637     case GST_VIDEO_FORMAT_Y16:
1638     case GST_VIDEO_FORMAT_RGB8_PALETTED:
1639     case GST_VIDEO_FORMAT_ARGB64:
1640     case GST_VIDEO_FORMAT_AYUV64:
1641     case GST_VIDEO_FORMAT_r210:
1642       return width;
1643     case GST_VIDEO_FORMAT_A420:
1644       if (component == 0 || component == 3) {
1645         return width;
1646       } else {
1647         return GST_ROUND_UP_2 (width) / 2;
1648       }
1649     default:
1650       return 0;
1651   }
1652 }
1653
1654 /**
1655  * gst_video_format_get_component_height:
1656  * @format: a #GstVideoFormat
1657  * @component: the component index
1658  * @height: the height of video
1659  *
1660  * Calculates the height of the component.  See
1661  * @gst_video_format_get_row_stride for a description
1662  * of the component index.
1663  *
1664  * Since: 0.10.16
1665  *
1666  * Returns: height of component @component
1667  */
1668 int
1669 gst_video_format_get_component_height (GstVideoFormat format,
1670     int component, int height)
1671 {
1672   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1673   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1674   g_return_val_if_fail (height > 0, 0);
1675
1676   switch (format) {
1677     case GST_VIDEO_FORMAT_I420:
1678     case GST_VIDEO_FORMAT_YV12:
1679     case GST_VIDEO_FORMAT_NV12:
1680     case GST_VIDEO_FORMAT_NV21:
1681       if (component == 0) {
1682         return height;
1683       } else {
1684         return GST_ROUND_UP_2 (height) / 2;
1685       }
1686     case GST_VIDEO_FORMAT_Y41B:
1687     case GST_VIDEO_FORMAT_Y42B:
1688     case GST_VIDEO_FORMAT_YUY2:
1689     case GST_VIDEO_FORMAT_YVYU:
1690     case GST_VIDEO_FORMAT_UYVY:
1691     case GST_VIDEO_FORMAT_AYUV:
1692     case GST_VIDEO_FORMAT_RGBx:
1693     case GST_VIDEO_FORMAT_BGRx:
1694     case GST_VIDEO_FORMAT_xRGB:
1695     case GST_VIDEO_FORMAT_xBGR:
1696     case GST_VIDEO_FORMAT_RGBA:
1697     case GST_VIDEO_FORMAT_BGRA:
1698     case GST_VIDEO_FORMAT_ARGB:
1699     case GST_VIDEO_FORMAT_ABGR:
1700     case GST_VIDEO_FORMAT_RGB:
1701     case GST_VIDEO_FORMAT_BGR:
1702     case GST_VIDEO_FORMAT_RGB16:
1703     case GST_VIDEO_FORMAT_BGR16:
1704     case GST_VIDEO_FORMAT_RGB15:
1705     case GST_VIDEO_FORMAT_BGR15:
1706     case GST_VIDEO_FORMAT_Y444:
1707     case GST_VIDEO_FORMAT_v210:
1708     case GST_VIDEO_FORMAT_v216:
1709     case GST_VIDEO_FORMAT_v308:
1710     case GST_VIDEO_FORMAT_GRAY8:
1711     case GST_VIDEO_FORMAT_GRAY16_BE:
1712     case GST_VIDEO_FORMAT_GRAY16_LE:
1713     case GST_VIDEO_FORMAT_Y800:
1714     case GST_VIDEO_FORMAT_Y16:
1715     case GST_VIDEO_FORMAT_UYVP:
1716     case GST_VIDEO_FORMAT_RGB8_PALETTED:
1717     case GST_VIDEO_FORMAT_IYU1:
1718     case GST_VIDEO_FORMAT_ARGB64:
1719     case GST_VIDEO_FORMAT_AYUV64:
1720     case GST_VIDEO_FORMAT_r210:
1721       return height;
1722     case GST_VIDEO_FORMAT_A420:
1723       if (component == 0 || component == 3) {
1724         return height;
1725       } else {
1726         return GST_ROUND_UP_2 (height) / 2;
1727       }
1728     case GST_VIDEO_FORMAT_YUV9:
1729     case GST_VIDEO_FORMAT_YVU9:
1730       if (component == 0) {
1731         return height;
1732       } else {
1733         return GST_ROUND_UP_4 (height) / 4;
1734       }
1735     default:
1736       return 0;
1737   }
1738 }
1739
1740 /**
1741  * gst_video_format_get_component_offset:
1742  * @format: a #GstVideoFormat
1743  * @component: the component index
1744  * @width: the width of video
1745  * @height: the height of video
1746  *
1747  * Calculates the offset (in bytes) of the first pixel of the component
1748  * with index @component.  For packed formats, this will typically be a
1749  * small integer (0, 1, 2, 3).  For planar formats, this will be a
1750  * (relatively) large offset to the beginning of the second or third
1751  * component planes.  See @gst_video_format_get_row_stride for a description
1752  * of the component index.
1753  *
1754  * Since: 0.10.16
1755  *
1756  * Returns: offset of component @component
1757  */
1758 int
1759 gst_video_format_get_component_offset (GstVideoFormat format,
1760     int component, int width, int height)
1761 {
1762   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1763   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1764   g_return_val_if_fail ((!gst_video_format_is_yuv (format)) || (width > 0
1765           && height > 0), 0);
1766
1767   switch (format) {
1768     case GST_VIDEO_FORMAT_I420:
1769       if (component == 0)
1770         return 0;
1771       if (component == 1)
1772         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1773       if (component == 2) {
1774         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) +
1775             GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1776             (GST_ROUND_UP_2 (height) / 2);
1777       }
1778       break;
1779     case GST_VIDEO_FORMAT_YV12:        /* same as I420, but components 1+2 swapped */
1780       if (component == 0)
1781         return 0;
1782       if (component == 2)
1783         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1784       if (component == 1) {
1785         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) +
1786             GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1787             (GST_ROUND_UP_2 (height) / 2);
1788       }
1789       break;
1790     case GST_VIDEO_FORMAT_YUY2:
1791       if (component == 0)
1792         return 0;
1793       if (component == 1)
1794         return 1;
1795       if (component == 2)
1796         return 3;
1797       break;
1798     case GST_VIDEO_FORMAT_YVYU:
1799       if (component == 0)
1800         return 0;
1801       if (component == 1)
1802         return 3;
1803       if (component == 2)
1804         return 1;
1805       break;
1806     case GST_VIDEO_FORMAT_UYVY:
1807       if (component == 0)
1808         return 1;
1809       if (component == 1)
1810         return 0;
1811       if (component == 2)
1812         return 2;
1813       break;
1814     case GST_VIDEO_FORMAT_AYUV:
1815       if (component == 0)
1816         return 1;
1817       if (component == 1)
1818         return 2;
1819       if (component == 2)
1820         return 3;
1821       if (component == 3)
1822         return 0;
1823       break;
1824     case GST_VIDEO_FORMAT_RGBx:
1825     case GST_VIDEO_FORMAT_RGBA:
1826       if (component == 0)
1827         return 0;
1828       if (component == 1)
1829         return 1;
1830       if (component == 2)
1831         return 2;
1832       if (component == 3)
1833         return 3;
1834       break;
1835     case GST_VIDEO_FORMAT_BGRx:
1836     case GST_VIDEO_FORMAT_BGRA:
1837       if (component == 0)
1838         return 2;
1839       if (component == 1)
1840         return 1;
1841       if (component == 2)
1842         return 0;
1843       if (component == 3)
1844         return 3;
1845       break;
1846     case GST_VIDEO_FORMAT_xRGB:
1847     case GST_VIDEO_FORMAT_ARGB:
1848       if (component == 0)
1849         return 1;
1850       if (component == 1)
1851         return 2;
1852       if (component == 2)
1853         return 3;
1854       if (component == 3)
1855         return 0;
1856       break;
1857     case GST_VIDEO_FORMAT_xBGR:
1858     case GST_VIDEO_FORMAT_ABGR:
1859       if (component == 0)
1860         return 3;
1861       if (component == 1)
1862         return 2;
1863       if (component == 2)
1864         return 1;
1865       if (component == 3)
1866         return 0;
1867       break;
1868     case GST_VIDEO_FORMAT_RGB:
1869     case GST_VIDEO_FORMAT_v308:
1870       if (component == 0)
1871         return 0;
1872       if (component == 1)
1873         return 1;
1874       if (component == 2)
1875         return 2;
1876       break;
1877     case GST_VIDEO_FORMAT_BGR:
1878       if (component == 0)
1879         return 2;
1880       if (component == 1)
1881         return 1;
1882       if (component == 2)
1883         return 0;
1884       break;
1885     case GST_VIDEO_FORMAT_Y41B:
1886       if (component == 0)
1887         return 0;
1888       if (component == 1)
1889         return GST_ROUND_UP_4 (width) * height;
1890       if (component == 2)
1891         return (GST_ROUND_UP_4 (width) +
1892             (GST_ROUND_UP_16 (width) / 4)) * height;
1893       break;
1894     case GST_VIDEO_FORMAT_Y42B:
1895       if (component == 0)
1896         return 0;
1897       if (component == 1)
1898         return GST_ROUND_UP_4 (width) * height;
1899       if (component == 2)
1900         return (GST_ROUND_UP_4 (width) + (GST_ROUND_UP_8 (width) / 2)) * height;
1901       break;
1902     case GST_VIDEO_FORMAT_Y444:
1903       return GST_ROUND_UP_4 (width) * height * component;
1904     case GST_VIDEO_FORMAT_v210:
1905     case GST_VIDEO_FORMAT_r210:
1906       /* v210 is bit-packed, so this doesn't make sense */
1907       return 0;
1908     case GST_VIDEO_FORMAT_v216:
1909       if (component == 0)
1910         return 0;
1911       if (component == 1)
1912         return 2;
1913       if (component == 2)
1914         return 6;
1915       break;
1916     case GST_VIDEO_FORMAT_NV12:
1917       if (component == 0)
1918         return 0;
1919       if (component == 1)
1920         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1921       if (component == 2)
1922         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) + 1;
1923       break;
1924     case GST_VIDEO_FORMAT_NV21:
1925       if (component == 0)
1926         return 0;
1927       if (component == 1)
1928         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) + 1;
1929       if (component == 2)
1930         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1931       break;
1932     case GST_VIDEO_FORMAT_GRAY8:
1933     case GST_VIDEO_FORMAT_GRAY16_BE:
1934     case GST_VIDEO_FORMAT_GRAY16_LE:
1935     case GST_VIDEO_FORMAT_Y800:
1936     case GST_VIDEO_FORMAT_Y16:
1937       return 0;
1938     case GST_VIDEO_FORMAT_UYVP:
1939       /* UYVP is bit-packed, so this doesn't make sense */
1940       return 0;
1941     case GST_VIDEO_FORMAT_A420:
1942       if (component == 0)
1943         return 0;
1944       if (component == 1)
1945         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1946       if (component == 2) {
1947         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) +
1948             GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1949             (GST_ROUND_UP_2 (height) / 2);
1950       }
1951       if (component == 3) {
1952         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) +
1953             2 * GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1954             (GST_ROUND_UP_2 (height) / 2);
1955       }
1956       break;
1957     case GST_VIDEO_FORMAT_RGB8_PALETTED:
1958       return 0;
1959     case GST_VIDEO_FORMAT_YUV9:
1960       if (component == 0)
1961         return 0;
1962       if (component == 1)
1963         return GST_ROUND_UP_4 (width) * height;
1964       if (component == 2) {
1965         return GST_ROUND_UP_4 (width) * height +
1966             GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4) *
1967             (GST_ROUND_UP_4 (height) / 4);
1968       }
1969       break;
1970     case GST_VIDEO_FORMAT_YVU9:
1971       if (component == 0)
1972         return 0;
1973       if (component == 1) {
1974         return GST_ROUND_UP_4 (width) * height +
1975             GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4) *
1976             (GST_ROUND_UP_4 (height) / 4);
1977       }
1978       if (component == 2)
1979         return GST_ROUND_UP_4 (width) * height;
1980       break;
1981     case GST_VIDEO_FORMAT_IYU1:
1982       if (component == 0)
1983         return 1;
1984       if (component == 1)
1985         return 0;
1986       if (component == 2)
1987         return 4;
1988       break;
1989     case GST_VIDEO_FORMAT_ARGB64:
1990     case GST_VIDEO_FORMAT_AYUV64:
1991       if (component == 0)
1992         return 2;
1993       if (component == 1)
1994         return 4;
1995       if (component == 2)
1996         return 6;
1997       if (component == 3)
1998         return 0;
1999       break;
2000     default:
2001       break;
2002   }
2003   GST_WARNING ("unhandled format %d or component %d", format, component);
2004   return 0;
2005 }
2006
2007 /**
2008  * gst_video_format_get_size:
2009  * @format: a #GstVideoFormat
2010  * @width: the width of video
2011  * @height: the height of video
2012  *
2013  * Calculates the total number of bytes in the raw video format.  This
2014  * number should be used when allocating a buffer for raw video.
2015  *
2016  * Since: 0.10.16
2017  *
2018  * Returns: size (in bytes) of raw video format
2019  */
2020 int
2021 gst_video_format_get_size (GstVideoFormat format, int width, int height)
2022 {
2023   int size;
2024
2025   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
2026   g_return_val_if_fail (width > 0 && height > 0, 0);
2027
2028   switch (format) {
2029     case GST_VIDEO_FORMAT_I420:
2030     case GST_VIDEO_FORMAT_YV12:
2031       size = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
2032       size += GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
2033           (GST_ROUND_UP_2 (height) / 2) * 2;
2034       return size;
2035     case GST_VIDEO_FORMAT_IYU1:
2036       return GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) +
2037           GST_ROUND_UP_4 (width) / 2) * height;
2038     case GST_VIDEO_FORMAT_YUY2:
2039     case GST_VIDEO_FORMAT_YVYU:
2040     case GST_VIDEO_FORMAT_UYVY:
2041       return GST_ROUND_UP_4 (width * 2) * height;
2042     case GST_VIDEO_FORMAT_AYUV:
2043     case GST_VIDEO_FORMAT_RGBx:
2044     case GST_VIDEO_FORMAT_BGRx:
2045     case GST_VIDEO_FORMAT_xRGB:
2046     case GST_VIDEO_FORMAT_xBGR:
2047     case GST_VIDEO_FORMAT_RGBA:
2048     case GST_VIDEO_FORMAT_BGRA:
2049     case GST_VIDEO_FORMAT_ARGB:
2050     case GST_VIDEO_FORMAT_ABGR:
2051     case GST_VIDEO_FORMAT_r210:
2052       return width * 4 * height;
2053     case GST_VIDEO_FORMAT_RGB16:
2054     case GST_VIDEO_FORMAT_BGR16:
2055     case GST_VIDEO_FORMAT_RGB15:
2056     case GST_VIDEO_FORMAT_BGR15:
2057       return GST_ROUND_UP_4 (width * 2) * height;
2058     case GST_VIDEO_FORMAT_RGB:
2059     case GST_VIDEO_FORMAT_BGR:
2060     case GST_VIDEO_FORMAT_v308:
2061       return GST_ROUND_UP_4 (width * 3) * height;
2062     case GST_VIDEO_FORMAT_Y41B:
2063       /* simplification of ROUNDUP4(w)*h + 2*((ROUNDUP16(w)/4)*h */
2064       return (GST_ROUND_UP_4 (width) + (GST_ROUND_UP_16 (width) / 2)) * height;
2065     case GST_VIDEO_FORMAT_Y42B:
2066       /* simplification of ROUNDUP4(w)*h + 2*(ROUNDUP8(w)/2)*h */
2067       return (GST_ROUND_UP_4 (width) + GST_ROUND_UP_8 (width)) * height;
2068     case GST_VIDEO_FORMAT_Y444:
2069       return GST_ROUND_UP_4 (width) * height * 3;
2070     case GST_VIDEO_FORMAT_v210:
2071       return ((width + 47) / 48) * 128 * height;
2072     case GST_VIDEO_FORMAT_v216:
2073       return GST_ROUND_UP_8 (width * 4) * height;
2074     case GST_VIDEO_FORMAT_NV12:
2075     case GST_VIDEO_FORMAT_NV21:
2076       return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) * 3 / 2;
2077     case GST_VIDEO_FORMAT_GRAY8:
2078     case GST_VIDEO_FORMAT_Y800:
2079     case GST_VIDEO_FORMAT_RGB8_PALETTED:
2080       return GST_ROUND_UP_4 (width) * height;
2081     case GST_VIDEO_FORMAT_GRAY16_BE:
2082     case GST_VIDEO_FORMAT_GRAY16_LE:
2083     case GST_VIDEO_FORMAT_Y16:
2084       return GST_ROUND_UP_4 (width * 2) * height;
2085     case GST_VIDEO_FORMAT_UYVP:
2086       return GST_ROUND_UP_4 ((width * 2 * 5 + 3) / 4) * height;
2087     case GST_VIDEO_FORMAT_A420:
2088       size = 2 * GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
2089       size += GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
2090           (GST_ROUND_UP_2 (height) / 2) * 2;
2091       return size;
2092     case GST_VIDEO_FORMAT_YUV9:
2093     case GST_VIDEO_FORMAT_YVU9:
2094       size = GST_ROUND_UP_4 (width) * height;
2095       size += GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4) *
2096           (GST_ROUND_UP_4 (height) / 4) * 2;
2097       return size;
2098     case GST_VIDEO_FORMAT_ARGB64:
2099     case GST_VIDEO_FORMAT_AYUV64:
2100       return width * 8 * height;
2101     default:
2102       return 0;
2103   }
2104 }
2105
2106 /**
2107  * gst_video_get_size_from_caps:
2108  * @caps: a pointer to #GstCaps
2109  * @size: a pointer to a gint that will be assigned the size (in bytes) of a video frame with the given caps
2110  *
2111  * Calculates the total number of bytes in the raw video format for the given
2112  * caps.  This number should be used when allocating a buffer for raw video.
2113  *
2114  * Since: 0.10.36
2115  *
2116  * Returns: %TRUE if the size could be calculated from the caps
2117  */
2118 gboolean
2119 gst_video_get_size_from_caps (const GstCaps * caps, gint * size)
2120 {
2121   GstVideoFormat format = 0;
2122   gint width = 0, height = 0;
2123
2124   g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
2125   g_return_val_if_fail (size != NULL, FALSE);
2126
2127   if (gst_video_format_parse_caps (caps, &format, &width, &height) == FALSE) {
2128     GST_WARNING ("Could not parse caps: %" GST_PTR_FORMAT, caps);
2129     return FALSE;
2130   }
2131
2132   *size = gst_video_format_get_size (format, width, height);
2133   return TRUE;
2134 }
2135
2136 /**
2137  * gst_video_format_convert:
2138  * @format: a #GstVideoFormat
2139  * @width: the width of video
2140  * @height: the height of video
2141  * @fps_n: frame rate numerator
2142  * @fps_d: frame rate denominator
2143  * @src_format: #GstFormat of the @src_value
2144  * @src_value: value to convert
2145  * @dest_format: #GstFormat of the @dest_value
2146  * @dest_value: pointer to destination value
2147  *
2148  * Converts among various #GstFormat types.  This function handles
2149  * GST_FORMAT_BYTES, GST_FORMAT_TIME, and GST_FORMAT_DEFAULT.  For
2150  * raw video, GST_FORMAT_DEFAULT corresponds to video frames.  This
2151  * function can be to handle pad queries of the type GST_QUERY_CONVERT.
2152  *
2153  * Since: 0.10.16
2154  *
2155  * Returns: TRUE if the conversion was successful.
2156  */
2157 gboolean
2158 gst_video_format_convert (GstVideoFormat format, int width, int height,
2159     int fps_n, int fps_d,
2160     GstFormat src_format, gint64 src_value,
2161     GstFormat dest_format, gint64 * dest_value)
2162 {
2163   gboolean ret = FALSE;
2164   int size;
2165
2166   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
2167   g_return_val_if_fail (width > 0 && height > 0, 0);
2168
2169   size = gst_video_format_get_size (format, width, height);
2170
2171   GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s to %s",
2172       src_value, gst_format_get_name (src_format),
2173       gst_format_get_name (dest_format));
2174
2175   if (src_format == dest_format) {
2176     *dest_value = src_value;
2177     ret = TRUE;
2178     goto done;
2179   }
2180
2181   if (src_value == -1) {
2182     *dest_value = -1;
2183     ret = TRUE;
2184     goto done;
2185   }
2186
2187   /* bytes to frames */
2188   if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_DEFAULT) {
2189     if (size != 0) {
2190       *dest_value = gst_util_uint64_scale_int (src_value, 1, size);
2191     } else {
2192       GST_ERROR ("blocksize is 0");
2193       *dest_value = 0;
2194     }
2195     ret = TRUE;
2196     goto done;
2197   }
2198
2199   /* frames to bytes */
2200   if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_BYTES) {
2201     *dest_value = gst_util_uint64_scale_int (src_value, size, 1);
2202     ret = TRUE;
2203     goto done;
2204   }
2205
2206   /* time to frames */
2207   if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_DEFAULT) {
2208     if (fps_d != 0) {
2209       *dest_value = gst_util_uint64_scale (src_value,
2210           fps_n, GST_SECOND * fps_d);
2211     } else {
2212       GST_ERROR ("framerate denominator is 0");
2213       *dest_value = 0;
2214     }
2215     ret = TRUE;
2216     goto done;
2217   }
2218
2219   /* frames to time */
2220   if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
2221     if (fps_n != 0) {
2222       *dest_value = gst_util_uint64_scale (src_value,
2223           GST_SECOND * fps_d, fps_n);
2224     } else {
2225       GST_ERROR ("framerate numerator is 0");
2226       *dest_value = 0;
2227     }
2228     ret = TRUE;
2229     goto done;
2230   }
2231
2232   /* time to bytes */
2233   if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) {
2234     if (fps_d != 0) {
2235       *dest_value = gst_util_uint64_scale (src_value,
2236           fps_n * size, GST_SECOND * fps_d);
2237     } else {
2238       GST_ERROR ("framerate denominator is 0");
2239       *dest_value = 0;
2240     }
2241     ret = TRUE;
2242     goto done;
2243   }
2244
2245   /* bytes to time */
2246   if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_TIME) {
2247     if (fps_n != 0 && size != 0) {
2248       *dest_value = gst_util_uint64_scale (src_value,
2249           GST_SECOND * fps_d, fps_n * size);
2250     } else {
2251       GST_ERROR ("framerate denominator and/or blocksize is 0");
2252       *dest_value = 0;
2253     }
2254     ret = TRUE;
2255   }
2256
2257 done:
2258
2259   GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, ret, *dest_value);
2260
2261   return ret;
2262 }
2263
2264 #define GST_VIDEO_EVENT_STILL_STATE_NAME "GstEventStillFrame"
2265
2266 /**
2267  * gst_video_event_new_still_frame:
2268  * @in_still: boolean value for the still-frame state of the event.
2269  *
2270  * Creates a new Still Frame event. If @in_still is %TRUE, then the event
2271  * represents the start of a still frame sequence. If it is %FALSE, then
2272  * the event ends a still frame sequence.
2273  *
2274  * To parse an event created by gst_video_event_new_still_frame() use
2275  * gst_video_event_parse_still_frame().
2276  *
2277  * Returns: The new GstEvent
2278  * Since: 0.10.26
2279  */
2280 GstEvent *
2281 gst_video_event_new_still_frame (gboolean in_still)
2282 {
2283   GstEvent *still_event;
2284   GstStructure *s;
2285
2286   s = gst_structure_new (GST_VIDEO_EVENT_STILL_STATE_NAME,
2287       "still-state", G_TYPE_BOOLEAN, in_still, NULL);
2288   still_event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
2289
2290   return still_event;
2291 }
2292
2293 /**
2294  * gst_video_event_parse_still_frame:
2295  * @event: A #GstEvent to parse
2296  * @in_still: A boolean to receive the still-frame status from the event, or NULL
2297  *
2298  * Parse a #GstEvent, identify if it is a Still Frame event, and
2299  * return the still-frame state from the event if it is.
2300  * If the event represents the start of a still frame, the in_still
2301  * variable will be set to TRUE, otherwise FALSE. It is OK to pass NULL for the
2302  * in_still variable order to just check whether the event is a valid still-frame
2303  * event.
2304  *
2305  * Create a still frame event using gst_video_event_new_still_frame()
2306  *
2307  * Returns: %TRUE if the event is a valid still-frame event. %FALSE if not
2308  * Since: 0.10.26
2309  */
2310 gboolean
2311 gst_video_event_parse_still_frame (GstEvent * event, gboolean * in_still)
2312 {
2313   const GstStructure *s;
2314   gboolean ev_still_state;
2315
2316   g_return_val_if_fail (event != NULL, FALSE);
2317
2318   if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_DOWNSTREAM)
2319     return FALSE;               /* Not a still frame event */
2320
2321   s = gst_event_get_structure (event);
2322   if (s == NULL
2323       || !gst_structure_has_name (s, GST_VIDEO_EVENT_STILL_STATE_NAME))
2324     return FALSE;               /* Not a still frame event */
2325   if (!gst_structure_get_boolean (s, "still-state", &ev_still_state))
2326     return FALSE;               /* Not a still frame event */
2327   if (in_still)
2328     *in_still = ev_still_state;
2329   return TRUE;
2330 }
2331
2332 /**
2333  * gst_video_parse_caps_palette:
2334  * @caps: #GstCaps to parse
2335  *
2336  * Returns the palette data from the caps as a #GstBuffer. For
2337  * #GST_VIDEO_FORMAT_RGB8_PALETTED this is containing 256 #guint32
2338  * values, each containing ARGB colors in native endianness.
2339  *
2340  * Returns: a #GstBuffer containing the palette data. Unref after usage.
2341  * Since: 0.10.32
2342  */
2343 GstBuffer *
2344 gst_video_parse_caps_palette (GstCaps * caps)
2345 {
2346   GstStructure *s;
2347   const GValue *p_v;
2348   GstBuffer *p;
2349
2350   if (!gst_caps_is_fixed (caps))
2351     return NULL;
2352
2353   s = gst_caps_get_structure (caps, 0);
2354
2355   p_v = gst_structure_get_value (s, "palette_data");
2356   if (!p_v || !GST_VALUE_HOLDS_BUFFER (p_v))
2357     return NULL;
2358
2359   p = gst_buffer_ref (gst_value_get_buffer (p_v));
2360
2361   return p;
2362 }
2363
2364 #define GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME "GstForceKeyUnit"
2365
2366 /**
2367  * gst_video_event_new_downstream_force_key_unit:
2368  * @timestamp: the timestamp of the buffer that starts a new key unit
2369  * @stream_time: the stream_time of the buffer that starts a new key unit
2370  * @running_time: the running_time of the buffer that starts a new key unit
2371  * @all_headers: %TRUE to produce headers when starting a new key unit
2372  * @count: integer that can be used to number key units
2373  *
2374  * Creates a new downstream force key unit event. A downstream force key unit
2375  * event can be sent down the pipeline to request downstream elements to produce
2376  * a key unit. A downstream force key unit event must also be sent when handling
2377  * an upstream force key unit event to notify downstream that the latter has been
2378  * handled.
2379  *
2380  * To parse an event created by gst_video_event_new_downstream_force_key_unit() use
2381  * gst_video_event_parse_downstream_force_key_unit().
2382  *
2383  * Returns: The new GstEvent
2384  * Since: 0.10.36
2385  */
2386 GstEvent *
2387 gst_video_event_new_downstream_force_key_unit (GstClockTime timestamp,
2388     GstClockTime stream_time, GstClockTime running_time, gboolean all_headers,
2389     guint count)
2390 {
2391   GstEvent *force_key_unit_event;
2392   GstStructure *s;
2393
2394   s = gst_structure_new (GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME,
2395       "timestamp", G_TYPE_UINT64, timestamp,
2396       "stream-time", G_TYPE_UINT64, stream_time,
2397       "running-time", G_TYPE_UINT64, running_time,
2398       "all-headers", G_TYPE_BOOLEAN, all_headers,
2399       "count", G_TYPE_UINT, count, NULL);
2400   force_key_unit_event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
2401
2402   return force_key_unit_event;
2403 }
2404
2405 /**
2406  * gst_video_event_new_upstream_force_key_unit:
2407  * @running_time: the running_time at which a new key unit should be produced
2408  * @all_headers: %TRUE to produce headers when starting a new key unit
2409  * @count: integer that can be used to number key units
2410  *
2411  * Creates a new upstream force key unit event. An upstream force key unit event
2412  * can be sent to request upstream elements to produce a key unit. 
2413  *
2414  * @running_time can be set to request a new key unit at a specific
2415  * running_time. If set to GST_CLOCK_TIME_NONE, upstream elements will produce a
2416  * new key unit as soon as possible.
2417  *
2418  * To parse an event created by gst_video_event_new_downstream_force_key_unit() use
2419  * gst_video_event_parse_downstream_force_key_unit().
2420  *
2421  * Returns: The new GstEvent
2422  * Since: 0.10.36
2423  */
2424 GstEvent *
2425 gst_video_event_new_upstream_force_key_unit (GstClockTime running_time,
2426     gboolean all_headers, guint count)
2427 {
2428   GstEvent *force_key_unit_event;
2429   GstStructure *s;
2430
2431   s = gst_structure_new (GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME,
2432       "running-time", GST_TYPE_CLOCK_TIME, running_time,
2433       "all-headers", G_TYPE_BOOLEAN, all_headers,
2434       "count", G_TYPE_UINT, count, NULL);
2435   force_key_unit_event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, s);
2436
2437   return force_key_unit_event;
2438 }
2439
2440 /**
2441  * gst_video_event_is_force_key_unit:
2442  * @event: A #GstEvent to check
2443  *
2444  * Checks if an event is a force key unit event. Returns true for both upstream
2445  * and downstream force key unit events.
2446  *
2447  * Returns: %TRUE if the event is a valid force key unit event
2448  * Since: 0.10.36
2449  */
2450 gboolean
2451 gst_video_event_is_force_key_unit (GstEvent * event)
2452 {
2453   const GstStructure *s;
2454
2455   g_return_val_if_fail (event != NULL, FALSE);
2456
2457   if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_DOWNSTREAM &&
2458       GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_UPSTREAM)
2459     return FALSE;               /* Not a force key unit event */
2460
2461   s = gst_event_get_structure (event);
2462   if (s == NULL
2463       || !gst_structure_has_name (s, GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME))
2464     return FALSE;
2465
2466   return TRUE;
2467 }
2468
2469 /**
2470  * gst_video_event_parse_downstream_force_key_unit:
2471  * @event: A #GstEvent to parse
2472  * @timestamp: (out): A pointer to the timestamp in the event
2473  * @stream_time: (out): A pointer to the stream-time in the event
2474  * @running_time: (out): A pointer to the running-time in the event
2475  * @all_headers: (out): A pointer to the all_headers flag in the event
2476  * @count: (out): A pointer to the count field of the event
2477  *
2478  * Get timestamp, stream-time, running-time, all-headers and count in the force
2479  * key unit event. See gst_video_event_new_downstream_force_key_unit() for a
2480  * full description of the downstream force key unit event.
2481  *
2482  * Returns: %TRUE if the event is a valid downstream force key unit event.
2483  * Since: 0.10.36
2484  */
2485 gboolean
2486 gst_video_event_parse_downstream_force_key_unit (GstEvent * event,
2487     GstClockTime * timestamp, GstClockTime * stream_time,
2488     GstClockTime * running_time, gboolean * all_headers, guint * count)
2489 {
2490   const GstStructure *s;
2491   GstClockTime ev_timestamp, ev_stream_time, ev_running_time;
2492   gboolean ev_all_headers;
2493   guint ev_count;
2494
2495   g_return_val_if_fail (event != NULL, FALSE);
2496
2497   if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_DOWNSTREAM)
2498     return FALSE;               /* Not a force key unit event */
2499
2500   s = gst_event_get_structure (event);
2501   if (s == NULL
2502       || !gst_structure_has_name (s, GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME))
2503     return FALSE;
2504
2505   if (!gst_structure_get_clock_time (s, "timestamp", &ev_timestamp))
2506     return FALSE;               /* Not a force key unit event */
2507   if (!gst_structure_get_clock_time (s, "stream-time", &ev_stream_time))
2508     return FALSE;               /* Not a force key unit event */
2509   if (!gst_structure_get_clock_time (s, "running-time", &ev_running_time))
2510     return FALSE;               /* Not a force key unit event */
2511   if (!gst_structure_get_boolean (s, "all-headers", &ev_all_headers))
2512     return FALSE;               /* Not a force key unit event */
2513   if (!gst_structure_get_uint (s, "count", &ev_count))
2514     return FALSE;               /* Not a force key unit event */
2515
2516   if (timestamp)
2517     *timestamp = ev_timestamp;
2518
2519   if (stream_time)
2520     *stream_time = ev_stream_time;
2521
2522   if (running_time)
2523     *running_time = ev_running_time;
2524
2525   if (all_headers)
2526     *all_headers = ev_all_headers;
2527
2528   if (count)
2529     *count = ev_count;
2530
2531   return TRUE;
2532 }
2533
2534 /**
2535  * gst_video_event_parse_upstream_force_key_unit:
2536  * @event: A #GstEvent to parse
2537  * @running_time: (out): A pointer to the running_time in the event
2538  * @all_headers: (out): A pointer to the all_headers flag in the event
2539  * @count: (out): A pointer to the count field in the event
2540  *
2541  * Get running-time, all-headers and count in the force key unit event. See
2542  * gst_video_event_new_upstream_force_key_unit() for a full description of the
2543  * upstream force key unit event.
2544  *
2545  * Create an upstream force key unit event using  gst_video_event_new_upstream_force_key_unit()
2546  *
2547  * Returns: %TRUE if the event is a valid upstream force-key-unit event. %FALSE if not
2548  * Since: 0.10.36
2549  */
2550 gboolean
2551 gst_video_event_parse_upstream_force_key_unit (GstEvent * event,
2552     GstClockTime * running_time, gboolean * all_headers, guint * count)
2553 {
2554   const GstStructure *s;
2555   GstClockTime ev_running_time;
2556   gboolean ev_all_headers;
2557   guint ev_count;
2558
2559   g_return_val_if_fail (event != NULL, FALSE);
2560
2561   if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_UPSTREAM)
2562     return FALSE;               /* Not a force key unit event */
2563
2564   s = gst_event_get_structure (event);
2565   if (s == NULL
2566       || !gst_structure_has_name (s, GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME))
2567     return FALSE;
2568
2569   if (!gst_structure_get_clock_time (s, "running-time", &ev_running_time))
2570     return FALSE;               /* Not a force key unit event */
2571   if (!gst_structure_get_boolean (s, "all-headers", &ev_all_headers))
2572     return FALSE;               /* Not a force key unit event */
2573   if (!gst_structure_get_uint (s, "count", &ev_count))
2574     return FALSE;               /* Not a force key unit event */
2575
2576   if (running_time)
2577     *running_time = ev_running_time;
2578
2579   if (all_headers)
2580     *all_headers = ev_all_headers;
2581
2582   if (count)
2583     *count = ev_count;
2584
2585   return TRUE;
2586 }