video: Fix parsing of 8-bit grayscale caps
[platform/upstream/gstreamer.git] / gst-libs / gst / video / video.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Library       <2002> Ronald Bultje <rbultje@ronald.bitfreak.net>
4  * Copyright (C) 2007 David A. Schleef <ds@schleef.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #  include "config.h"
24 #endif
25
26 #include "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
47
48 /**
49  * gst_video_frame_rate:
50  * @pad: pointer to a #GstPad
51  *
52  * A convenience function to retrieve a GValue holding the framerate
53  * from the caps on a pad.
54  * 
55  * The pad needs to have negotiated caps containing a framerate property.
56  *
57  * Returns: NULL if the pad has no configured caps or the configured caps
58  * do not contain a framerate.
59  *
60  */
61 const GValue *
62 gst_video_frame_rate (GstPad * pad)
63 {
64   const GValue *fps;
65   gchar *fps_string;
66
67   const GstCaps *caps = NULL;
68   GstStructure *structure;
69
70   /* get pad caps */
71   caps = GST_PAD_CAPS (pad);
72   if (caps == NULL) {
73     g_warning ("gstvideo: failed to get caps of pad %s:%s",
74         GST_DEBUG_PAD_NAME (pad));
75     return NULL;
76   }
77
78   structure = gst_caps_get_structure (caps, 0);
79   if ((fps = gst_structure_get_value (structure, "framerate")) == NULL) {
80     g_warning ("gstvideo: failed to get framerate property of pad %s:%s",
81         GST_DEBUG_PAD_NAME (pad));
82     return NULL;
83   }
84   if (!GST_VALUE_HOLDS_FRACTION (fps)) {
85     g_warning
86         ("gstvideo: framerate property of pad %s:%s is not of type Fraction",
87         GST_DEBUG_PAD_NAME (pad));
88     return NULL;
89   }
90
91   fps_string = gst_value_serialize (fps);
92   GST_DEBUG ("Framerate request on pad %s:%s: %s",
93       GST_DEBUG_PAD_NAME (pad), fps_string);
94   g_free (fps_string);
95
96   return fps;
97 }
98
99 /**
100  * gst_video_get_size:
101  * @pad: pointer to a #GstPad
102  * @width: pointer to integer to hold pixel width of the video frames (output)
103  * @height: pointer to integer to hold pixel height of the video frames (output)
104  *
105  * Inspect the caps of the provided pad and retrieve the width and height of
106  * the video frames it is configured for.
107  * 
108  * The pad needs to have negotiated caps containing width and height properties.
109  *
110  * Returns: TRUE if the width and height could be retrieved.
111  *
112  */
113 gboolean
114 gst_video_get_size (GstPad * pad, gint * width, gint * height)
115 {
116   const GstCaps *caps = NULL;
117   GstStructure *structure;
118   gboolean ret;
119
120   g_return_val_if_fail (pad != NULL, FALSE);
121   g_return_val_if_fail (width != NULL, FALSE);
122   g_return_val_if_fail (height != NULL, FALSE);
123
124   caps = GST_PAD_CAPS (pad);
125
126   if (caps == NULL) {
127     g_warning ("gstvideo: failed to get caps of pad %s:%s",
128         GST_DEBUG_PAD_NAME (pad));
129     return FALSE;
130   }
131
132   structure = gst_caps_get_structure (caps, 0);
133   ret = gst_structure_get_int (structure, "width", width);
134   ret &= gst_structure_get_int (structure, "height", height);
135
136   if (!ret) {
137     g_warning ("gstvideo: failed to get size properties on pad %s:%s",
138         GST_DEBUG_PAD_NAME (pad));
139     return FALSE;
140   }
141
142   GST_DEBUG ("size request on pad %s:%s: %dx%d",
143       GST_DEBUG_PAD_NAME (pad), width ? *width : -1, height ? *height : -1);
144
145   return TRUE;
146 }
147
148 /**
149  * gst_video_calculate_display_ratio:
150  * @dar_n: Numerator of the calculated display_ratio
151  * @dar_d: Denominator of the calculated display_ratio
152  * @video_width: Width of the video frame in pixels
153  * @video_height: Height of the video frame in pixels
154  * @video_par_n: Numerator of the pixel aspect ratio of the input video.
155  * @video_par_d: Denominator of the pixel aspect ratio of the input video.
156  * @display_par_n: Numerator of the pixel aspect ratio of the display device
157  * @display_par_d: Denominator of the pixel aspect ratio of the display device
158  *
159  * Given the Pixel Aspect Ratio and size of an input video frame, and the 
160  * pixel aspect ratio of the intended display device, calculates the actual 
161  * display ratio the video will be rendered with.
162  *
163  * Returns: A boolean indicating success and a calculated Display Ratio in the 
164  * dar_n and dar_d parameters. 
165  * The return value is FALSE in the case of integer overflow or other error. 
166  *
167  * Since: 0.10.7
168  */
169 gboolean
170 gst_video_calculate_display_ratio (guint * dar_n, guint * dar_d,
171     guint video_width, guint video_height,
172     guint video_par_n, guint video_par_d,
173     guint display_par_n, guint display_par_d)
174 {
175   gint num, den;
176
177   GValue display_ratio = { 0, };
178   GValue tmp = { 0, };
179   GValue tmp2 = { 0, };
180
181   g_return_val_if_fail (dar_n != NULL, FALSE);
182   g_return_val_if_fail (dar_d != NULL, FALSE);
183
184   g_value_init (&display_ratio, GST_TYPE_FRACTION);
185   g_value_init (&tmp, GST_TYPE_FRACTION);
186   g_value_init (&tmp2, GST_TYPE_FRACTION);
187
188   /* Calculate (video_width * video_par_n * display_par_d) /
189    * (video_height * video_par_d * display_par_n) */
190   gst_value_set_fraction (&display_ratio, video_width, video_height);
191   gst_value_set_fraction (&tmp, video_par_n, video_par_d);
192
193   if (!gst_value_fraction_multiply (&tmp2, &display_ratio, &tmp))
194     goto error_overflow;
195
196   gst_value_set_fraction (&tmp, display_par_d, display_par_n);
197
198   if (!gst_value_fraction_multiply (&display_ratio, &tmp2, &tmp))
199     goto error_overflow;
200
201   num = gst_value_get_fraction_numerator (&display_ratio);
202   den = gst_value_get_fraction_denominator (&display_ratio);
203
204   g_value_unset (&display_ratio);
205   g_value_unset (&tmp);
206   g_value_unset (&tmp2);
207
208   g_return_val_if_fail (num > 0, FALSE);
209   g_return_val_if_fail (den > 0, FALSE);
210
211   *dar_n = num;
212   *dar_d = den;
213
214   return TRUE;
215 error_overflow:
216   g_value_unset (&display_ratio);
217   g_value_unset (&tmp);
218   g_value_unset (&tmp2);
219   return FALSE;
220 }
221
222 /**
223  * gst_video_format_parse_caps_interlaced:
224  * @caps: the fixed #GstCaps to parse
225  * @interlaced: whether @caps represents interlaced video or not, may be NULL (output)
226  *
227  * Extracts whether the caps represents interlaced content or not and places it
228  * in @interlaced.
229  *
230  * Since: 0.10.23
231  *
232  * Returns: TRUE if @caps was parsed correctly.
233  */
234 gboolean
235 gst_video_format_parse_caps_interlaced (GstCaps * caps, gboolean * interlaced)
236 {
237   GstStructure *structure;
238
239   if (!gst_caps_is_fixed (caps))
240     return FALSE;
241
242   structure = gst_caps_get_structure (caps, 0);
243
244   if (interlaced) {
245     if (!gst_structure_get_boolean (structure, "interlaced", interlaced))
246       *interlaced = FALSE;
247   }
248
249   return TRUE;
250 }
251
252 /**
253  * gst_video_parse_caps_color_matrix:
254  * @caps: the fixed #GstCaps to parse
255  *
256  * Extracts the color matrix used by the caps.  Possible values are
257  * "sdtv" for the standard definition color matrix (as specified in
258  * Rec. ITU-R BT.470-6) or "hdtv" for the high definition color
259  * matrix (as specified in Rec. ITU-R BT.709)
260  *
261  * Since: 0.10.29
262  *
263  * Returns: a color matrix string, or NULL if no color matrix could be
264  *     determined.
265  */
266 const char *
267 gst_video_parse_caps_color_matrix (GstCaps * caps)
268 {
269   GstStructure *structure;
270   const char *s;
271
272   if (!gst_caps_is_fixed (caps))
273     return NULL;
274
275   structure = gst_caps_get_structure (caps, 0);
276
277   s = gst_structure_get_string (structure, "color-matrix");
278   if (s)
279     return s;
280
281   if (gst_structure_has_name (structure, "video/x-raw-yuv")) {
282     return "sdtv";
283   }
284
285   return NULL;
286 }
287
288 /**
289  * gst_video_parse_caps_chroma_site:
290  * @caps: the fixed #GstCaps to parse
291  *
292  * Extracts the chroma site used by the caps.  Possible values are
293  * "mpeg2" for MPEG-2 style chroma siting (co-sited horizontally,
294  * halfway-sited vertically), "jpeg" for JPEG and Theora style
295  * chroma siting (halfway-sited both horizontally and vertically).
296  * Other chroma site values are possible, but uncommon.
297  * 
298  * When no chroma site is specified in the caps, it should be assumed
299  * to be "mpeg2".
300  *
301  * Since: 0.10.29
302  *
303  * Returns: a chroma site string, or NULL if no chroma site could be
304  *     determined.
305  */
306 const char *
307 gst_video_parse_caps_chroma_site (GstCaps * caps)
308 {
309   GstStructure *structure;
310   const char *s;
311
312   if (!gst_caps_is_fixed (caps))
313     return NULL;
314
315   structure = gst_caps_get_structure (caps, 0);
316
317   s = gst_structure_get_string (structure, "chroma-site");
318   if (s)
319     return s;
320
321   if (gst_structure_has_name (structure, "video/x-raw-yuv")) {
322     return "mpeg2";
323   }
324
325   return NULL;
326 }
327
328 /**
329  * gst_video_format_parse_caps:
330  * @caps: the #GstCaps to parse
331  * @format: the #GstVideoFormat of the video represented by @caps (output)
332  * @width: the width of the video represented by @caps, may be NULL (output)
333  * @height: the height of the video represented by @caps, may be NULL (output)
334  *
335  * Determines the #GstVideoFormat of @caps and places it in the location
336  * pointed to by @format.  Extracts the size of the video and places it
337  * in the location pointed to by @width and @height.  If @caps does not
338  * represent one of the raw video formats listed in #GstVideoFormat, the
339  * function will fail and return FALSE.
340  *
341  * Since: 0.10.16
342  *
343  * Returns: TRUE if @caps was parsed correctly.
344  */
345 gboolean
346 gst_video_format_parse_caps (GstCaps * caps, GstVideoFormat * format,
347     int *width, int *height)
348 {
349   GstStructure *structure;
350   gboolean ok = TRUE;
351
352   if (!gst_caps_is_fixed (caps))
353     return FALSE;
354
355   structure = gst_caps_get_structure (caps, 0);
356
357   if (format) {
358     if (gst_structure_has_name (structure, "video/x-raw-yuv")) {
359       guint32 fourcc;
360
361       ok &= gst_structure_get_fourcc (structure, "format", &fourcc);
362
363       *format = gst_video_format_from_fourcc (fourcc);
364       if (*format == GST_VIDEO_FORMAT_UNKNOWN) {
365         ok = FALSE;
366       }
367     } else if (gst_structure_has_name (structure, "video/x-raw-rgb")) {
368       int depth;
369       int bpp;
370       int endianness;
371       int red_mask;
372       int green_mask;
373       int blue_mask;
374       int alpha_mask;
375       gboolean have_alpha;
376
377       ok &= gst_structure_get_int (structure, "depth", &depth);
378       ok &= gst_structure_get_int (structure, "bpp", &bpp);
379       ok &= gst_structure_get_int (structure, "endianness", &endianness);
380       ok &= gst_structure_get_int (structure, "red_mask", &red_mask);
381       ok &= gst_structure_get_int (structure, "green_mask", &green_mask);
382       ok &= gst_structure_get_int (structure, "blue_mask", &blue_mask);
383       have_alpha = gst_structure_get_int (structure, "alpha_mask", &alpha_mask);
384
385       if (depth == 24 && bpp == 32 && endianness == G_BIG_ENDIAN) {
386         *format = gst_video_format_from_rgb32_masks (red_mask, green_mask,
387             blue_mask);
388         if (*format == GST_VIDEO_FORMAT_UNKNOWN) {
389           ok = FALSE;
390         }
391       } else if (depth == 32 && bpp == 32 && endianness == G_BIG_ENDIAN &&
392           have_alpha) {
393         *format = gst_video_format_from_rgba32_masks (red_mask, green_mask,
394             blue_mask, alpha_mask);
395         if (*format == GST_VIDEO_FORMAT_UNKNOWN) {
396           ok = FALSE;
397         }
398       } else if (depth == 24 && bpp == 24 && endianness == G_BIG_ENDIAN) {
399         *format = gst_video_format_from_rgb24_masks (red_mask, green_mask,
400             blue_mask);
401         if (*format == GST_VIDEO_FORMAT_UNKNOWN) {
402           ok = FALSE;
403         }
404       } else {
405         ok = FALSE;
406       }
407     } else if (gst_structure_has_name (structure, "video/x-raw-gray")) {
408       int depth;
409       int bpp;
410       int endianness;
411
412       ok &= gst_structure_get_int (structure, "depth", &depth);
413       ok &= gst_structure_get_int (structure, "bpp", &bpp);
414
415       if (bpp > 8)
416         ok &= gst_structure_get_int (structure, "endianness", &endianness);
417
418       if (depth == 8 && bpp == 8) {
419         *format = GST_VIDEO_FORMAT_GRAY8;
420       } else if (depth == 16 && bpp == 16 && endianness == G_BIG_ENDIAN) {
421         *format = GST_VIDEO_FORMAT_GRAY16_BE;
422       } else if (depth == 16 && bpp == 16 && endianness == G_LITTLE_ENDIAN) {
423         *format = GST_VIDEO_FORMAT_GRAY16_LE;
424       } else {
425         ok = FALSE;
426       }
427     } else {
428       ok = FALSE;
429     }
430   }
431
432   if (width) {
433     ok &= gst_structure_get_int (structure, "width", width);
434   }
435
436   if (height) {
437     ok &= gst_structure_get_int (structure, "height", height);
438   }
439
440   return ok;
441 }
442
443
444 /**
445  * gst_video_parse_caps_framerate:
446  * @caps: pointer to a #GstCaps instance
447  * @fps_n: pointer to integer to hold numerator of frame rate (output)
448  * @fps_d: pointer to integer to hold denominator of frame rate (output)
449  *
450  * Extracts the frame rate from @caps and places the values in the locations
451  * pointed to by @fps_n and @fps_d.  Returns TRUE if the values could be
452  * parsed correctly, FALSE if not.
453  *
454  * This function can be used with #GstCaps that have any media type; it
455  * is not limited to formats handled by #GstVideoFormat.
456  *
457  * Since: 0.10.16
458  *
459  * Returns: TRUE if @caps was parsed correctly.
460  */
461 gboolean
462 gst_video_parse_caps_framerate (GstCaps * caps, int *fps_n, int *fps_d)
463 {
464   GstStructure *structure;
465
466   if (!gst_caps_is_fixed (caps))
467     return FALSE;
468
469   structure = gst_caps_get_structure (caps, 0);
470
471   return gst_structure_get_fraction (structure, "framerate", fps_n, fps_d);
472 }
473
474 /**
475  * gst_video_parse_caps_pixel_aspect_ratio:
476  * @caps: pointer to a #GstCaps instance
477  * @par_n: pointer to numerator of pixel aspect ratio (output)
478  * @par_d: pointer to denominator of pixel aspect ratio (output)
479  *
480  * Extracts the pixel aspect ratio from @caps and places the values in
481  * the locations pointed to by @par_n and @par_d.  Returns TRUE if the
482  * values could be parsed correctly, FALSE if not.
483  *
484  * This function can be used with #GstCaps that have any media type; it
485  * is not limited to formats handled by #GstVideoFormat.
486  *
487  * Since: 0.10.16
488  *
489  * Returns: TRUE if @caps was parsed correctly.
490  */
491 gboolean
492 gst_video_parse_caps_pixel_aspect_ratio (GstCaps * caps, int *par_n, int *par_d)
493 {
494   GstStructure *structure;
495
496   if (!gst_caps_is_fixed (caps))
497     return FALSE;
498
499   structure = gst_caps_get_structure (caps, 0);
500
501   if (!gst_structure_get_fraction (structure, "pixel-aspect-ratio",
502           par_n, par_d)) {
503     *par_n = 1;
504     *par_d = 1;
505   }
506   return TRUE;
507 }
508
509 /**
510  * gst_video_format_new_caps_interlaced:
511  * @format: the #GstVideoFormat describing the raw video format
512  * @width: width of video
513  * @height: height of video
514  * @framerate_n: numerator of frame rate
515  * @framerate_d: denominator of frame rate
516  * @par_n: numerator of pixel aspect ratio
517  * @par_d: denominator of pixel aspect ratio
518  * @interlaced: #TRUE if the format is interlaced
519  *
520  * Creates a new #GstCaps object based on the parameters provided.
521  *
522  * Since: 0.10.23
523  *
524  * Returns: a new #GstCaps object, or NULL if there was an error
525  */
526 GstCaps *
527 gst_video_format_new_caps_interlaced (GstVideoFormat format, int width,
528     int height, int framerate_n, int framerate_d, int par_n, int par_d,
529     gboolean interlaced)
530 {
531   GstCaps *res;
532
533   res =
534       gst_video_format_new_caps (format, width, height, framerate_n,
535       framerate_d, par_n, par_d);
536   if (interlaced && (res != NULL))
537     gst_caps_set_simple (res, "interlaced", G_TYPE_BOOLEAN, TRUE, NULL);
538
539   return res;
540 }
541
542 /**
543  * gst_video_format_new_caps:
544  * @format: the #GstVideoFormat describing the raw video format
545  * @width: width of video
546  * @height: height of video
547  * @framerate_n: numerator of frame rate
548  * @framerate_d: denominator of frame rate
549  * @par_n: numerator of pixel aspect ratio
550  * @par_d: denominator of pixel aspect ratio
551  *
552  * Creates a new #GstCaps object based on the parameters provided.
553  *
554  * Since: 0.10.16
555  *
556  * Returns: a new #GstCaps object, or NULL if there was an error
557  */
558 GstCaps *
559 gst_video_format_new_caps (GstVideoFormat format, int width, int height,
560     int framerate_n, int framerate_d, int par_n, int par_d)
561 {
562   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
563   g_return_val_if_fail (width > 0 && height > 0, NULL);
564
565   if (gst_video_format_is_yuv (format)) {
566     return gst_caps_new_simple ("video/x-raw-yuv",
567         "format", GST_TYPE_FOURCC, gst_video_format_to_fourcc (format),
568         "width", G_TYPE_INT, width,
569         "height", G_TYPE_INT, height,
570         "framerate", GST_TYPE_FRACTION, framerate_n, framerate_d,
571         "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, NULL);
572   }
573   if (gst_video_format_is_rgb (format)) {
574     GstCaps *caps;
575     int red_mask;
576     int blue_mask;
577     int green_mask;
578     int alpha_mask;
579     int depth;
580     int bpp;
581     gboolean have_alpha;
582     unsigned int mask;
583
584     switch (format) {
585       case GST_VIDEO_FORMAT_RGBx:
586       case GST_VIDEO_FORMAT_BGRx:
587       case GST_VIDEO_FORMAT_xRGB:
588       case GST_VIDEO_FORMAT_xBGR:
589         bpp = 32;
590         depth = 24;
591         have_alpha = FALSE;
592         break;
593       case GST_VIDEO_FORMAT_RGBA:
594       case GST_VIDEO_FORMAT_BGRA:
595       case GST_VIDEO_FORMAT_ARGB:
596       case GST_VIDEO_FORMAT_ABGR:
597         bpp = 32;
598         depth = 32;
599         have_alpha = TRUE;
600         break;
601       case GST_VIDEO_FORMAT_RGB:
602       case GST_VIDEO_FORMAT_BGR:
603         bpp = 24;
604         depth = 24;
605         have_alpha = FALSE;
606         break;
607       default:
608         return NULL;
609     }
610     if (bpp == 32) {
611       mask = 0xff000000;
612     } else {
613       mask = 0xff0000;
614     }
615     red_mask =
616         mask >> (8 * gst_video_format_get_component_offset (format, 0, width,
617             height));
618     green_mask =
619         mask >> (8 * gst_video_format_get_component_offset (format, 1, width,
620             height));
621     blue_mask =
622         mask >> (8 * gst_video_format_get_component_offset (format, 2, width,
623             height));
624
625     caps = gst_caps_new_simple ("video/x-raw-rgb",
626         "bpp", G_TYPE_INT, bpp,
627         "depth", G_TYPE_INT, depth,
628         "endianness", G_TYPE_INT, G_BIG_ENDIAN,
629         "red_mask", G_TYPE_INT, red_mask,
630         "green_mask", G_TYPE_INT, green_mask,
631         "blue_mask", G_TYPE_INT, blue_mask,
632         "width", G_TYPE_INT, width,
633         "height", G_TYPE_INT, height,
634         "framerate", GST_TYPE_FRACTION, framerate_n, framerate_d,
635         "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, NULL);
636     if (have_alpha) {
637       alpha_mask =
638           mask >> (8 * gst_video_format_get_component_offset (format, 3, width,
639               height));
640       gst_caps_set_simple (caps, "alpha_mask", G_TYPE_INT, alpha_mask, NULL);
641     }
642     return caps;
643   }
644
645   if (gst_video_format_is_gray (format)) {
646     GstCaps *caps;
647     int bpp;
648     int depth;
649     int endianness;
650
651     switch (format) {
652       case GST_VIDEO_FORMAT_GRAY8:
653         bpp = depth = 8;
654         endianness = G_BIG_ENDIAN;
655         break;
656       case GST_VIDEO_FORMAT_GRAY16_BE:
657         bpp = depth = 16;
658         endianness = G_BIG_ENDIAN;
659         break;
660       case GST_VIDEO_FORMAT_GRAY16_LE:
661         bpp = depth = 16;
662         endianness = G_LITTLE_ENDIAN;
663         break;
664       default:
665         return NULL;
666         break;
667     }
668
669     if (bpp > 8) {
670       caps = gst_caps_new_simple ("video/x-raw-gray",
671           "bpp", G_TYPE_INT, bpp,
672           "depth", G_TYPE_INT, depth,
673           "width", G_TYPE_INT, width,
674           "height", G_TYPE_INT, height,
675           "framerate", GST_TYPE_FRACTION, framerate_n, framerate_d,
676           "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, NULL);
677     } else {
678       caps = gst_caps_new_simple ("video/x-raw-gray",
679           "bpp", G_TYPE_INT, bpp,
680           "depth", G_TYPE_INT, depth,
681           "endianness", G_TYPE_INT, G_BIG_ENDIAN,
682           "width", G_TYPE_INT, width,
683           "height", G_TYPE_INT, height,
684           "framerate", GST_TYPE_FRACTION, framerate_n, framerate_d,
685           "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, NULL);
686     }
687
688     return caps;
689   }
690
691   return NULL;
692 }
693
694 /**
695  * gst_video_format_from_fourcc:
696  * @fourcc: a FOURCC value representing raw YUV video
697  *
698  * Converts a FOURCC value into the corresponding #GstVideoFormat.
699  * If the FOURCC cannot be represented by #GstVideoFormat,
700  * #GST_VIDEO_FORMAT_UNKNOWN is returned.
701  *
702  * Since: 0.10.16
703  *
704  * Returns: the #GstVideoFormat describing the FOURCC value
705  */
706 GstVideoFormat
707 gst_video_format_from_fourcc (guint32 fourcc)
708 {
709   switch (fourcc) {
710     case GST_MAKE_FOURCC ('I', '4', '2', '0'):
711       return GST_VIDEO_FORMAT_I420;
712     case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
713       return GST_VIDEO_FORMAT_YV12;
714     case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
715       return GST_VIDEO_FORMAT_YUY2;
716     case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'):
717       return GST_VIDEO_FORMAT_YVYU;
718     case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
719       return GST_VIDEO_FORMAT_UYVY;
720     case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'):
721       return GST_VIDEO_FORMAT_AYUV;
722     case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
723       return GST_VIDEO_FORMAT_Y41B;
724     case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
725       return GST_VIDEO_FORMAT_Y42B;
726     case GST_MAKE_FOURCC ('Y', '4', '4', '4'):
727       return GST_VIDEO_FORMAT_Y444;
728     case GST_MAKE_FOURCC ('v', '2', '1', '0'):
729       return GST_VIDEO_FORMAT_v210;
730     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
731       return GST_VIDEO_FORMAT_v216;
732     case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
733       return GST_VIDEO_FORMAT_NV12;
734     case GST_MAKE_FOURCC ('N', 'V', '2', '1'):
735       return GST_VIDEO_FORMAT_NV21;
736     default:
737       return GST_VIDEO_FORMAT_UNKNOWN;
738   }
739 }
740
741 /**
742  * gst_video_format_to_fourcc:
743  * @format: a #GstVideoFormat video format
744  *
745  * Converts a #GstVideoFormat value into the corresponding FOURCC.  Only
746  * a few YUV formats have corresponding FOURCC values.  If @format has
747  * no corresponding FOURCC value, 0 is returned.
748  *
749  * Since: 0.10.16
750  *
751  * Returns: the FOURCC corresponding to @format
752  */
753 guint32
754 gst_video_format_to_fourcc (GstVideoFormat format)
755 {
756   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
757
758   switch (format) {
759     case GST_VIDEO_FORMAT_I420:
760       return GST_MAKE_FOURCC ('I', '4', '2', '0');
761     case GST_VIDEO_FORMAT_YV12:
762       return GST_MAKE_FOURCC ('Y', 'V', '1', '2');
763     case GST_VIDEO_FORMAT_YUY2:
764       return GST_MAKE_FOURCC ('Y', 'U', 'Y', '2');
765     case GST_VIDEO_FORMAT_YVYU:
766       return GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U');
767     case GST_VIDEO_FORMAT_UYVY:
768       return GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y');
769     case GST_VIDEO_FORMAT_AYUV:
770       return GST_MAKE_FOURCC ('A', 'Y', 'U', 'V');
771     case GST_VIDEO_FORMAT_Y41B:
772       return GST_MAKE_FOURCC ('Y', '4', '1', 'B');
773     case GST_VIDEO_FORMAT_Y42B:
774       return GST_MAKE_FOURCC ('Y', '4', '2', 'B');
775     case GST_VIDEO_FORMAT_Y444:
776       return GST_MAKE_FOURCC ('Y', '4', '4', '4');
777     case GST_VIDEO_FORMAT_v210:
778       return GST_MAKE_FOURCC ('v', '2', '1', '0');
779     case GST_VIDEO_FORMAT_v216:
780       return GST_MAKE_FOURCC ('v', '2', '1', '6');
781     case GST_VIDEO_FORMAT_NV12:
782       return GST_MAKE_FOURCC ('N', 'V', '1', '2');
783     case GST_VIDEO_FORMAT_NV21:
784       return GST_MAKE_FOURCC ('N', 'V', '2', '1');
785     default:
786       return 0;
787   }
788 }
789
790 /*
791  * gst_video_format_from_rgb32_masks:
792  * @red_mask: red bit mask
793  * @green_mask: green bit mask
794  * @blue_mask: blue bit mask
795  *
796  * Converts red, green, blue bit masks into the corresponding
797  * #GstVideoFormat.  
798  *
799  * Since: 0.10.16
800  *
801  * Returns: the #GstVideoFormat corresponding to the bit masks
802  */
803 static GstVideoFormat
804 gst_video_format_from_rgb32_masks (int red_mask, int green_mask, int blue_mask)
805 {
806   if (red_mask == 0xff000000 && green_mask == 0x00ff0000 &&
807       blue_mask == 0x0000ff00) {
808     return GST_VIDEO_FORMAT_RGBx;
809   }
810   if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 &&
811       blue_mask == 0xff000000) {
812     return GST_VIDEO_FORMAT_BGRx;
813   }
814   if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 &&
815       blue_mask == 0x000000ff) {
816     return GST_VIDEO_FORMAT_xRGB;
817   }
818   if (red_mask == 0x000000ff && green_mask == 0x0000ff00 &&
819       blue_mask == 0x00ff0000) {
820     return GST_VIDEO_FORMAT_xBGR;
821   }
822
823   return GST_VIDEO_FORMAT_UNKNOWN;
824 }
825
826 static GstVideoFormat
827 gst_video_format_from_rgba32_masks (int red_mask, int green_mask, int blue_mask,
828     int alpha_mask)
829 {
830   if (red_mask == 0xff000000 && green_mask == 0x00ff0000 &&
831       blue_mask == 0x0000ff00 && alpha_mask == 0x000000ff) {
832     return GST_VIDEO_FORMAT_RGBA;
833   }
834   if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 &&
835       blue_mask == 0xff000000 && alpha_mask == 0x000000ff) {
836     return GST_VIDEO_FORMAT_BGRA;
837   }
838   if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 &&
839       blue_mask == 0x000000ff && alpha_mask == 0xff000000) {
840     return GST_VIDEO_FORMAT_ARGB;
841   }
842   if (red_mask == 0x000000ff && green_mask == 0x0000ff00 &&
843       blue_mask == 0x00ff0000 && alpha_mask == 0xff000000) {
844     return GST_VIDEO_FORMAT_ABGR;
845   }
846
847   return GST_VIDEO_FORMAT_UNKNOWN;
848 }
849
850 static GstVideoFormat
851 gst_video_format_from_rgb24_masks (int red_mask, int green_mask, int blue_mask)
852 {
853   if (red_mask == 0xff0000 && green_mask == 0x00ff00 && blue_mask == 0x0000ff) {
854     return GST_VIDEO_FORMAT_RGB;
855   }
856   if (red_mask == 0x0000ff && green_mask == 0x00ff00 && blue_mask == 0xff0000) {
857     return GST_VIDEO_FORMAT_BGR;
858   }
859
860   return GST_VIDEO_FORMAT_UNKNOWN;
861 }
862
863 /**
864  * gst_video_format_is_rgb:
865  * @format: a #GstVideoFormat
866  *
867  * Determine whether the video format is an RGB format.
868  *
869  * Since: 0.10.16
870  *
871  * Returns: TRUE if @format represents RGB video
872  */
873 gboolean
874 gst_video_format_is_rgb (GstVideoFormat format)
875 {
876   switch (format) {
877     case GST_VIDEO_FORMAT_I420:
878     case GST_VIDEO_FORMAT_YV12:
879     case GST_VIDEO_FORMAT_YUY2:
880     case GST_VIDEO_FORMAT_YVYU:
881     case GST_VIDEO_FORMAT_UYVY:
882     case GST_VIDEO_FORMAT_AYUV:
883     case GST_VIDEO_FORMAT_Y41B:
884     case GST_VIDEO_FORMAT_Y42B:
885     case GST_VIDEO_FORMAT_Y444:
886     case GST_VIDEO_FORMAT_v210:
887     case GST_VIDEO_FORMAT_v216:
888     case GST_VIDEO_FORMAT_NV12:
889     case GST_VIDEO_FORMAT_NV21:
890       return FALSE;
891     case GST_VIDEO_FORMAT_RGBx:
892     case GST_VIDEO_FORMAT_BGRx:
893     case GST_VIDEO_FORMAT_xRGB:
894     case GST_VIDEO_FORMAT_xBGR:
895     case GST_VIDEO_FORMAT_RGBA:
896     case GST_VIDEO_FORMAT_BGRA:
897     case GST_VIDEO_FORMAT_ARGB:
898     case GST_VIDEO_FORMAT_ABGR:
899     case GST_VIDEO_FORMAT_RGB:
900     case GST_VIDEO_FORMAT_BGR:
901       return TRUE;
902     default:
903       return FALSE;
904   }
905 }
906
907 /**
908  * gst_video_format_is_yuv:
909  * @format: a #GstVideoFormat
910  *
911  * Determine whether the video format is a YUV format.
912  *
913  * Since: 0.10.16
914  *
915  * Returns: TRUE if @format represents YUV video
916  */
917 gboolean
918 gst_video_format_is_yuv (GstVideoFormat format)
919 {
920   switch (format) {
921     case GST_VIDEO_FORMAT_I420:
922     case GST_VIDEO_FORMAT_YV12:
923     case GST_VIDEO_FORMAT_YUY2:
924     case GST_VIDEO_FORMAT_YVYU:
925     case GST_VIDEO_FORMAT_UYVY:
926     case GST_VIDEO_FORMAT_AYUV:
927     case GST_VIDEO_FORMAT_Y41B:
928     case GST_VIDEO_FORMAT_Y42B:
929     case GST_VIDEO_FORMAT_Y444:
930     case GST_VIDEO_FORMAT_v210:
931     case GST_VIDEO_FORMAT_v216:
932     case GST_VIDEO_FORMAT_NV12:
933     case GST_VIDEO_FORMAT_NV21:
934       return TRUE;
935     case GST_VIDEO_FORMAT_RGBx:
936     case GST_VIDEO_FORMAT_BGRx:
937     case GST_VIDEO_FORMAT_xRGB:
938     case GST_VIDEO_FORMAT_xBGR:
939     case GST_VIDEO_FORMAT_RGBA:
940     case GST_VIDEO_FORMAT_BGRA:
941     case GST_VIDEO_FORMAT_ARGB:
942     case GST_VIDEO_FORMAT_ABGR:
943     case GST_VIDEO_FORMAT_RGB:
944     case GST_VIDEO_FORMAT_BGR:
945       return FALSE;
946     default:
947       return FALSE;
948   }
949 }
950
951 /**
952  * gst_video_format_is_gray:
953  * @format: a #GstVideoFormat
954  *
955  * Determine whether the video format is a grayscale format.
956  *
957  * Since: 0.10.29
958  *
959  * Returns: TRUE if @format represents grayscale video
960  */
961 gboolean
962 gst_video_format_is_gray (GstVideoFormat format)
963 {
964   switch (format) {
965     case GST_VIDEO_FORMAT_GRAY8:
966     case GST_VIDEO_FORMAT_GRAY16_BE:
967     case GST_VIDEO_FORMAT_GRAY16_LE:
968       return TRUE;
969     default:
970       return FALSE;
971   }
972 }
973
974 /**
975  * gst_video_format_has_alpha:
976  * @format: a #GstVideoFormat
977  * 
978  * Returns TRUE or FALSE depending on if the video format provides an
979  * alpha channel.
980  *
981  * Since: 0.10.16
982  *
983  * Returns: TRUE if @format has an alpha channel
984  */
985 gboolean
986 gst_video_format_has_alpha (GstVideoFormat format)
987 {
988   switch (format) {
989     case GST_VIDEO_FORMAT_I420:
990     case GST_VIDEO_FORMAT_YV12:
991     case GST_VIDEO_FORMAT_YUY2:
992     case GST_VIDEO_FORMAT_YVYU:
993     case GST_VIDEO_FORMAT_UYVY:
994     case GST_VIDEO_FORMAT_Y41B:
995     case GST_VIDEO_FORMAT_Y42B:
996     case GST_VIDEO_FORMAT_Y444:
997     case GST_VIDEO_FORMAT_v210:
998     case GST_VIDEO_FORMAT_v216:
999     case GST_VIDEO_FORMAT_NV12:
1000     case GST_VIDEO_FORMAT_NV21:
1001       return FALSE;
1002     case GST_VIDEO_FORMAT_AYUV:
1003     case GST_VIDEO_FORMAT_RGBA:
1004     case GST_VIDEO_FORMAT_BGRA:
1005     case GST_VIDEO_FORMAT_ARGB:
1006     case GST_VIDEO_FORMAT_ABGR:
1007       return TRUE;
1008     case GST_VIDEO_FORMAT_RGBx:
1009     case GST_VIDEO_FORMAT_BGRx:
1010     case GST_VIDEO_FORMAT_xRGB:
1011     case GST_VIDEO_FORMAT_xBGR:
1012     case GST_VIDEO_FORMAT_RGB:
1013     case GST_VIDEO_FORMAT_BGR:
1014       return FALSE;
1015     default:
1016       return FALSE;
1017   }
1018 }
1019
1020 /**
1021  * gst_video_format_get_row_stride:
1022  * @format: a #GstVideoFormat
1023  * @component: the component index
1024  * @width: the width of video
1025  *
1026  * Calculates the row stride (number of bytes from one row of pixels to
1027  * the next) for the video component with an index of @component.  For
1028  * YUV video, Y, U, and V have component indices of 0, 1, and 2,
1029  * respectively.  For RGB video, R, G, and B have component indicies of
1030  * 0, 1, and 2, respectively.  Alpha channels, if present, have a component
1031  * index of 3.  The @width parameter always represents the width of the
1032  * video, not the component.
1033  *
1034  * Since: 0.10.16
1035  *
1036  * Returns: row stride of component @component
1037  */
1038 int
1039 gst_video_format_get_row_stride (GstVideoFormat format, int component,
1040     int width)
1041 {
1042   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1043   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1044   g_return_val_if_fail (width > 0, 0);
1045
1046   switch (format) {
1047     case GST_VIDEO_FORMAT_I420:
1048     case GST_VIDEO_FORMAT_YV12:
1049       if (component == 0) {
1050         return GST_ROUND_UP_4 (width);
1051       } else {
1052         return GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
1053       }
1054     case GST_VIDEO_FORMAT_YUY2:
1055     case GST_VIDEO_FORMAT_YVYU:
1056     case GST_VIDEO_FORMAT_UYVY:
1057       return GST_ROUND_UP_4 (width * 2);
1058     case GST_VIDEO_FORMAT_AYUV:
1059     case GST_VIDEO_FORMAT_RGBx:
1060     case GST_VIDEO_FORMAT_BGRx:
1061     case GST_VIDEO_FORMAT_xRGB:
1062     case GST_VIDEO_FORMAT_xBGR:
1063     case GST_VIDEO_FORMAT_RGBA:
1064     case GST_VIDEO_FORMAT_BGRA:
1065     case GST_VIDEO_FORMAT_ARGB:
1066     case GST_VIDEO_FORMAT_ABGR:
1067       return width * 4;
1068     case GST_VIDEO_FORMAT_RGB:
1069     case GST_VIDEO_FORMAT_BGR:
1070       return GST_ROUND_UP_4 (width * 3);
1071     case GST_VIDEO_FORMAT_Y41B:
1072       if (component == 0) {
1073         return GST_ROUND_UP_4 (width);
1074       } else {
1075         return GST_ROUND_UP_16 (width) / 4;
1076       }
1077     case GST_VIDEO_FORMAT_Y42B:
1078       if (component == 0) {
1079         return GST_ROUND_UP_4 (width);
1080       } else {
1081         return GST_ROUND_UP_8 (width) / 2;
1082       }
1083     case GST_VIDEO_FORMAT_Y444:
1084       return GST_ROUND_UP_4 (width);
1085     case GST_VIDEO_FORMAT_v210:
1086       return ((width + 47) / 48) * 128;
1087     case GST_VIDEO_FORMAT_v216:
1088       return GST_ROUND_UP_8 (width * 4);
1089     case GST_VIDEO_FORMAT_NV12:
1090     case GST_VIDEO_FORMAT_NV21:
1091       return GST_ROUND_UP_4 (width);
1092     case GST_VIDEO_FORMAT_GRAY8:
1093       return GST_ROUND_UP_4 (width);
1094     case GST_VIDEO_FORMAT_GRAY16_BE:
1095     case GST_VIDEO_FORMAT_GRAY16_LE:
1096       return GST_ROUND_UP_4 (width * 2);
1097     default:
1098       return 0;
1099   }
1100 }
1101
1102 /**
1103  * gst_video_format_get_pixel_stride:
1104  * @format: a #GstVideoFormat
1105  * @component: the component index
1106  *
1107  * Calculates the pixel stride (number of bytes from one pixel to the
1108  * pixel to its immediate left) for the video component with an index
1109  * of @component.  See @gst_video_format_get_row_stride for a description
1110  * of the component index.
1111  *
1112  * Since: 0.10.16
1113  *
1114  * Returns: pixel stride of component @component
1115  */
1116 int
1117 gst_video_format_get_pixel_stride (GstVideoFormat format, int component)
1118 {
1119   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1120   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1121
1122   switch (format) {
1123     case GST_VIDEO_FORMAT_I420:
1124     case GST_VIDEO_FORMAT_YV12:
1125     case GST_VIDEO_FORMAT_Y41B:
1126     case GST_VIDEO_FORMAT_Y42B:
1127     case GST_VIDEO_FORMAT_Y444:
1128       return 1;
1129     case GST_VIDEO_FORMAT_YUY2:
1130     case GST_VIDEO_FORMAT_YVYU:
1131     case GST_VIDEO_FORMAT_UYVY:
1132       if (component == 0) {
1133         return 2;
1134       } else {
1135         return 4;
1136       }
1137     case GST_VIDEO_FORMAT_AYUV:
1138     case GST_VIDEO_FORMAT_RGBx:
1139     case GST_VIDEO_FORMAT_BGRx:
1140     case GST_VIDEO_FORMAT_xRGB:
1141     case GST_VIDEO_FORMAT_xBGR:
1142     case GST_VIDEO_FORMAT_RGBA:
1143     case GST_VIDEO_FORMAT_BGRA:
1144     case GST_VIDEO_FORMAT_ARGB:
1145     case GST_VIDEO_FORMAT_ABGR:
1146       return 4;
1147     case GST_VIDEO_FORMAT_RGB:
1148     case GST_VIDEO_FORMAT_BGR:
1149       return 3;
1150     case GST_VIDEO_FORMAT_v210:
1151       /* v210 is packed at the bit level, so pixel stride doesn't make sense */
1152       return 0;
1153     case GST_VIDEO_FORMAT_v216:
1154       if (component == 0) {
1155         return 4;
1156       } else {
1157         return 8;
1158       }
1159     case GST_VIDEO_FORMAT_NV12:
1160     case GST_VIDEO_FORMAT_NV21:
1161       if (component == 0) {
1162         return 1;
1163       } else {
1164         return 2;
1165       }
1166     case GST_VIDEO_FORMAT_GRAY8:
1167       return 1;
1168     case GST_VIDEO_FORMAT_GRAY16_BE:
1169     case GST_VIDEO_FORMAT_GRAY16_LE:
1170       return 2;
1171     default:
1172       return 0;
1173   }
1174 }
1175
1176 /**
1177  * gst_video_format_get_component_width:
1178  * @format: a #GstVideoFormat
1179  * @component: the component index
1180  * @width: the width of video
1181  *
1182  * Calculates the width of the component.  See
1183  * @gst_video_format_get_row_stride for a description
1184  * of the component index.
1185  *
1186  * Since: 0.10.16
1187  *
1188  * Returns: width of component @component
1189  */
1190 int
1191 gst_video_format_get_component_width (GstVideoFormat format, int component,
1192     int width)
1193 {
1194   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1195   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1196   g_return_val_if_fail (width > 0, 0);
1197
1198   switch (format) {
1199     case GST_VIDEO_FORMAT_I420:
1200     case GST_VIDEO_FORMAT_YV12:
1201     case GST_VIDEO_FORMAT_YUY2:
1202     case GST_VIDEO_FORMAT_YVYU:
1203     case GST_VIDEO_FORMAT_UYVY:
1204     case GST_VIDEO_FORMAT_Y42B:
1205     case GST_VIDEO_FORMAT_v210:
1206     case GST_VIDEO_FORMAT_v216:
1207       if (component == 0) {
1208         return width;
1209       } else {
1210         return GST_ROUND_UP_2 (width) / 2;
1211       }
1212     case GST_VIDEO_FORMAT_Y41B:
1213       if (component == 0) {
1214         return width;
1215       } else {
1216         return GST_ROUND_UP_4 (width) / 4;
1217       }
1218     case GST_VIDEO_FORMAT_AYUV:
1219     case GST_VIDEO_FORMAT_RGBx:
1220     case GST_VIDEO_FORMAT_BGRx:
1221     case GST_VIDEO_FORMAT_xRGB:
1222     case GST_VIDEO_FORMAT_xBGR:
1223     case GST_VIDEO_FORMAT_RGBA:
1224     case GST_VIDEO_FORMAT_BGRA:
1225     case GST_VIDEO_FORMAT_ARGB:
1226     case GST_VIDEO_FORMAT_ABGR:
1227     case GST_VIDEO_FORMAT_RGB:
1228     case GST_VIDEO_FORMAT_BGR:
1229     case GST_VIDEO_FORMAT_Y444:
1230     case GST_VIDEO_FORMAT_NV12:
1231     case GST_VIDEO_FORMAT_NV21:
1232     case GST_VIDEO_FORMAT_GRAY8:
1233     case GST_VIDEO_FORMAT_GRAY16_BE:
1234     case GST_VIDEO_FORMAT_GRAY16_LE:
1235       return width;
1236     default:
1237       return 0;
1238   }
1239 }
1240
1241 /**
1242  * gst_video_format_get_component_height:
1243  * @format: a #GstVideoFormat
1244  * @component: the component index
1245  * @height: the height of video
1246  *
1247  * Calculates the height of the component.  See
1248  * @gst_video_format_get_row_stride for a description
1249  * of the component index.
1250  *
1251  * Since: 0.10.16
1252  *
1253  * Returns: height of component @component
1254  */
1255 int
1256 gst_video_format_get_component_height (GstVideoFormat format, int component,
1257     int height)
1258 {
1259   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1260   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1261   g_return_val_if_fail (height > 0, 0);
1262
1263   switch (format) {
1264     case GST_VIDEO_FORMAT_I420:
1265     case GST_VIDEO_FORMAT_YV12:
1266     case GST_VIDEO_FORMAT_NV12:
1267     case GST_VIDEO_FORMAT_NV21:
1268       if (component == 0) {
1269         return height;
1270       } else {
1271         return GST_ROUND_UP_2 (height) / 2;
1272       }
1273     case GST_VIDEO_FORMAT_Y41B:
1274     case GST_VIDEO_FORMAT_Y42B:
1275     case GST_VIDEO_FORMAT_YUY2:
1276     case GST_VIDEO_FORMAT_YVYU:
1277     case GST_VIDEO_FORMAT_UYVY:
1278     case GST_VIDEO_FORMAT_AYUV:
1279     case GST_VIDEO_FORMAT_RGBx:
1280     case GST_VIDEO_FORMAT_BGRx:
1281     case GST_VIDEO_FORMAT_xRGB:
1282     case GST_VIDEO_FORMAT_xBGR:
1283     case GST_VIDEO_FORMAT_RGBA:
1284     case GST_VIDEO_FORMAT_BGRA:
1285     case GST_VIDEO_FORMAT_ARGB:
1286     case GST_VIDEO_FORMAT_ABGR:
1287     case GST_VIDEO_FORMAT_RGB:
1288     case GST_VIDEO_FORMAT_BGR:
1289     case GST_VIDEO_FORMAT_Y444:
1290     case GST_VIDEO_FORMAT_v210:
1291     case GST_VIDEO_FORMAT_v216:
1292     case GST_VIDEO_FORMAT_GRAY8:
1293     case GST_VIDEO_FORMAT_GRAY16_BE:
1294     case GST_VIDEO_FORMAT_GRAY16_LE:
1295       return height;
1296     default:
1297       return 0;
1298   }
1299 }
1300
1301 /**
1302  * gst_video_format_get_component_offset:
1303  * @format: a #GstVideoFormat
1304  * @component: the component index
1305  * @width: the width of video
1306  * @height: the height of video
1307  *
1308  * Calculates the offset (in bytes) of the first pixel of the component
1309  * with index @component.  For packed formats, this will typically be a
1310  * small integer (0, 1, 2, 3).  For planar formats, this will be a
1311  * (relatively) large offset to the beginning of the second or third
1312  * component planes.  See @gst_video_format_get_row_stride for a description
1313  * of the component index.
1314  *
1315  * Since: 0.10.16
1316  *
1317  * Returns: offset of component @component
1318  */
1319 int
1320 gst_video_format_get_component_offset (GstVideoFormat format, int component,
1321     int width, int height)
1322 {
1323   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1324   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1325   g_return_val_if_fail (width > 0 && height > 0, 0);
1326
1327   switch (format) {
1328     case GST_VIDEO_FORMAT_I420:
1329       if (component == 0)
1330         return 0;
1331       if (component == 1)
1332         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1333       if (component == 2) {
1334         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) +
1335             GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1336             (GST_ROUND_UP_2 (height) / 2);
1337       }
1338       return 0;
1339     case GST_VIDEO_FORMAT_YV12:        /* same as I420, but components 1+2 swapped */
1340       if (component == 0)
1341         return 0;
1342       if (component == 2)
1343         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1344       if (component == 1) {
1345         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) +
1346             GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1347             (GST_ROUND_UP_2 (height) / 2);
1348       }
1349       return 0;
1350     case GST_VIDEO_FORMAT_YUY2:
1351       if (component == 0)
1352         return 0;
1353       if (component == 1)
1354         return 1;
1355       if (component == 2)
1356         return 3;
1357       return 0;
1358     case GST_VIDEO_FORMAT_YVYU:
1359       if (component == 0)
1360         return 0;
1361       if (component == 1)
1362         return 3;
1363       if (component == 2)
1364         return 1;
1365       return 0;
1366     case GST_VIDEO_FORMAT_UYVY:
1367       if (component == 0)
1368         return 1;
1369       if (component == 1)
1370         return 0;
1371       if (component == 2)
1372         return 2;
1373       return 0;
1374     case GST_VIDEO_FORMAT_AYUV:
1375       if (component == 0)
1376         return 1;
1377       if (component == 1)
1378         return 2;
1379       if (component == 2)
1380         return 3;
1381       if (component == 3)
1382         return 0;
1383       return 0;
1384     case GST_VIDEO_FORMAT_RGBx:
1385     case GST_VIDEO_FORMAT_RGBA:
1386       if (component == 0)
1387         return 0;
1388       if (component == 1)
1389         return 1;
1390       if (component == 2)
1391         return 2;
1392       if (component == 3)
1393         return 3;
1394       return 0;
1395     case GST_VIDEO_FORMAT_BGRx:
1396     case GST_VIDEO_FORMAT_BGRA:
1397       if (component == 0)
1398         return 2;
1399       if (component == 1)
1400         return 1;
1401       if (component == 2)
1402         return 0;
1403       if (component == 3)
1404         return 3;
1405       return 0;
1406     case GST_VIDEO_FORMAT_xRGB:
1407     case GST_VIDEO_FORMAT_ARGB:
1408       if (component == 0)
1409         return 1;
1410       if (component == 1)
1411         return 2;
1412       if (component == 2)
1413         return 3;
1414       if (component == 3)
1415         return 0;
1416       return 0;
1417     case GST_VIDEO_FORMAT_xBGR:
1418     case GST_VIDEO_FORMAT_ABGR:
1419       if (component == 0)
1420         return 3;
1421       if (component == 1)
1422         return 2;
1423       if (component == 2)
1424         return 1;
1425       if (component == 3)
1426         return 0;
1427       return 0;
1428     case GST_VIDEO_FORMAT_RGB:
1429       if (component == 0)
1430         return 0;
1431       if (component == 1)
1432         return 1;
1433       if (component == 2)
1434         return 2;
1435       return 0;
1436     case GST_VIDEO_FORMAT_BGR:
1437       if (component == 0)
1438         return 2;
1439       if (component == 1)
1440         return 1;
1441       if (component == 2)
1442         return 0;
1443       return 0;
1444     case GST_VIDEO_FORMAT_Y41B:
1445       if (component == 0)
1446         return 0;
1447       if (component == 1)
1448         return GST_ROUND_UP_4 (width) * height;
1449       if (component == 2)
1450         return (GST_ROUND_UP_4 (width) +
1451             (GST_ROUND_UP_16 (width) / 4)) * height;
1452       return 0;
1453     case GST_VIDEO_FORMAT_Y42B:
1454       if (component == 0)
1455         return 0;
1456       if (component == 1)
1457         return GST_ROUND_UP_4 (width) * height;
1458       if (component == 2)
1459         return (GST_ROUND_UP_4 (width) + (GST_ROUND_UP_8 (width) / 2)) * height;
1460       return 0;
1461     case GST_VIDEO_FORMAT_Y444:
1462       return GST_ROUND_UP_4 (width) * height * component;
1463     case GST_VIDEO_FORMAT_v210:
1464       /* v210 is bit-packed, so this doesn't make sense */
1465       return 0;
1466     case GST_VIDEO_FORMAT_v216:
1467       if (component == 0)
1468         return 0;
1469       if (component == 1)
1470         return 2;
1471       if (component == 2)
1472         return 6;
1473       return 0;
1474     case GST_VIDEO_FORMAT_NV12:
1475       if (component == 0)
1476         return 0;
1477       if (component == 1)
1478         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1479       if (component == 2)
1480         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) + 1;
1481     case GST_VIDEO_FORMAT_NV21:
1482       if (component == 0)
1483         return 0;
1484       if (component == 1)
1485         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) + 1;
1486       if (component == 2)
1487         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1488     case GST_VIDEO_FORMAT_GRAY8:
1489     case GST_VIDEO_FORMAT_GRAY16_BE:
1490     case GST_VIDEO_FORMAT_GRAY16_LE:
1491       return 0;
1492     default:
1493       return 0;
1494   }
1495 }
1496
1497 /**
1498  * gst_video_format_get_size:
1499  * @format: a #GstVideoFormat
1500  * @width: the width of video
1501  * @height: the height of video
1502  *
1503  * Calculates the total number of bytes in the raw video format.  This
1504  * number should be used when allocating a buffer for raw video.
1505  *
1506  * Since: 0.10.16
1507  *
1508  * Returns: size (in bytes) of raw video format
1509  */
1510 int
1511 gst_video_format_get_size (GstVideoFormat format, int width, int height)
1512 {
1513   int size;
1514
1515   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1516   g_return_val_if_fail (width > 0 && height > 0, 0);
1517
1518   switch (format) {
1519     case GST_VIDEO_FORMAT_I420:
1520     case GST_VIDEO_FORMAT_YV12:
1521       size = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1522       size += GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1523           (GST_ROUND_UP_2 (height) / 2) * 2;
1524       return size;
1525     case GST_VIDEO_FORMAT_YUY2:
1526     case GST_VIDEO_FORMAT_YVYU:
1527     case GST_VIDEO_FORMAT_UYVY:
1528       return GST_ROUND_UP_4 (width * 2) * height;
1529     case GST_VIDEO_FORMAT_AYUV:
1530     case GST_VIDEO_FORMAT_RGBx:
1531     case GST_VIDEO_FORMAT_BGRx:
1532     case GST_VIDEO_FORMAT_xRGB:
1533     case GST_VIDEO_FORMAT_xBGR:
1534     case GST_VIDEO_FORMAT_RGBA:
1535     case GST_VIDEO_FORMAT_BGRA:
1536     case GST_VIDEO_FORMAT_ARGB:
1537     case GST_VIDEO_FORMAT_ABGR:
1538       return width * 4 * height;
1539     case GST_VIDEO_FORMAT_RGB:
1540     case GST_VIDEO_FORMAT_BGR:
1541       return GST_ROUND_UP_4 (width * 3) * height;
1542     case GST_VIDEO_FORMAT_Y41B:
1543       /* simplification of ROUNDUP4(w)*h + 2*((ROUNDUP16(w)/4)*h */
1544       return (GST_ROUND_UP_4 (width) + (GST_ROUND_UP_16 (width) / 2)) * height;
1545     case GST_VIDEO_FORMAT_Y42B:
1546       /* simplification of ROUNDUP4(w)*h + 2*(ROUNDUP8(w)/2)*h */
1547       return (GST_ROUND_UP_4 (width) + GST_ROUND_UP_8 (width)) * height;
1548     case GST_VIDEO_FORMAT_Y444:
1549       return GST_ROUND_UP_4 (width) * height * 3;
1550     case GST_VIDEO_FORMAT_v210:
1551       return ((width + 47) / 48) * 128 * height;
1552     case GST_VIDEO_FORMAT_v216:
1553       return GST_ROUND_UP_8 (width * 4) * height;
1554     case GST_VIDEO_FORMAT_NV12:
1555     case GST_VIDEO_FORMAT_NV21:
1556       return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) * 3 / 2;
1557     case GST_VIDEO_FORMAT_GRAY8:
1558       return GST_ROUND_UP_4 (width) * height;
1559     case GST_VIDEO_FORMAT_GRAY16_BE:
1560     case GST_VIDEO_FORMAT_GRAY16_LE:
1561       return GST_ROUND_UP_4 (width * 2) * height;
1562     default:
1563       return 0;
1564   }
1565 }
1566
1567 /**
1568  * gst_video_format_convert:
1569  * @format: a #GstVideoFormat
1570  * @width: the width of video
1571  * @height: the height of video
1572  * @fps_n: frame rate numerator
1573  * @fps_d: frame rate denominator
1574  * @src_format: #GstFormat of the @src_value
1575  * @src_value: value to convert
1576  * @dest_format: #GstFormat of the @dest_value
1577  * @dest_value: pointer to destination value
1578  *
1579  * Converts among various #GstFormat types.  This function handles
1580  * GST_FORMAT_BYTES, GST_FORMAT_TIME, and GST_FORMAT_DEFAULT.  For
1581  * raw video, GST_FORMAT_DEFAULT corresponds to video frames.  This
1582  * function can be to handle pad queries of the type GST_QUERY_CONVERT.
1583  *
1584  * Since: 0.10.16
1585  *
1586  * Returns: TRUE if the conversion was successful.
1587  */
1588 gboolean
1589 gst_video_format_convert (GstVideoFormat format, int width, int height,
1590     int fps_n, int fps_d,
1591     GstFormat src_format, gint64 src_value,
1592     GstFormat dest_format, gint64 * dest_value)
1593 {
1594   gboolean ret = FALSE;
1595   int size;
1596
1597   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1598   g_return_val_if_fail (width > 0 && height > 0, 0);
1599
1600   size = gst_video_format_get_size (format, width, height);
1601
1602   GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s to %s",
1603       src_value, gst_format_get_name (src_format),
1604       gst_format_get_name (dest_format));
1605
1606   if (src_format == dest_format) {
1607     *dest_value = src_value;
1608     ret = TRUE;
1609     goto done;
1610   }
1611
1612   if (src_value == -1) {
1613     *dest_value = -1;
1614     ret = TRUE;
1615     goto done;
1616   }
1617
1618   /* bytes to frames */
1619   if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_DEFAULT) {
1620     if (size != 0) {
1621       *dest_value = gst_util_uint64_scale_int (src_value, 1, size);
1622     } else {
1623       GST_ERROR ("blocksize is 0");
1624       *dest_value = 0;
1625     }
1626     ret = TRUE;
1627     goto done;
1628   }
1629
1630   /* frames to bytes */
1631   if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_BYTES) {
1632     *dest_value = gst_util_uint64_scale_int (src_value, size, 1);
1633     ret = TRUE;
1634     goto done;
1635   }
1636
1637   /* time to frames */
1638   if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_DEFAULT) {
1639     if (fps_d != 0) {
1640       *dest_value = gst_util_uint64_scale (src_value,
1641           fps_n, GST_SECOND * fps_d);
1642     } else {
1643       GST_ERROR ("framerate denominator is 0");
1644       *dest_value = 0;
1645     }
1646     ret = TRUE;
1647     goto done;
1648   }
1649
1650   /* frames to time */
1651   if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
1652     if (fps_n != 0) {
1653       *dest_value = gst_util_uint64_scale (src_value,
1654           GST_SECOND * fps_d, fps_n);
1655     } else {
1656       GST_ERROR ("framerate numerator is 0");
1657       *dest_value = 0;
1658     }
1659     ret = TRUE;
1660     goto done;
1661   }
1662
1663   /* time to bytes */
1664   if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) {
1665     if (fps_d != 0) {
1666       *dest_value = gst_util_uint64_scale (src_value,
1667           fps_n * size, GST_SECOND * fps_d);
1668     } else {
1669       GST_ERROR ("framerate denominator is 0");
1670       *dest_value = 0;
1671     }
1672     ret = TRUE;
1673     goto done;
1674   }
1675
1676   /* bytes to time */
1677   if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_TIME) {
1678     if (fps_n != 0 && size != 0) {
1679       *dest_value = gst_util_uint64_scale (src_value,
1680           GST_SECOND * fps_d, fps_n * size);
1681     } else {
1682       GST_ERROR ("framerate denominator and/or blocksize is 0");
1683       *dest_value = 0;
1684     }
1685     ret = TRUE;
1686   }
1687
1688 done:
1689
1690   GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, ret, *dest_value);
1691
1692   return ret;
1693 }
1694
1695 #define GST_VIDEO_EVENT_STILL_STATE_NAME "GstEventStillFrame"
1696
1697 /**
1698  * gst_video_event_new_still_frame:
1699  * @in_still: boolean value for the still-frame state of the event.
1700  *
1701  * Creates a new Still Frame event. If @in_still is %TRUE, then the event
1702  * represents the start of a still frame sequence. If it is %FALSE, then
1703  * the event ends a still frame sequence.
1704  *
1705  * To parse an event created by gst_video_event_new_still_frame() use
1706  * gst_video_event_parse_still_frame().
1707  *
1708  * Returns: The new GstEvent
1709  * Since: 0.10.26
1710  */
1711 GstEvent *
1712 gst_video_event_new_still_frame (gboolean in_still)
1713 {
1714   GstEvent *still_event;
1715   GstStructure *s;
1716
1717   s = gst_structure_new (GST_VIDEO_EVENT_STILL_STATE_NAME,
1718       "still-state", G_TYPE_BOOLEAN, in_still, NULL);
1719   still_event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
1720
1721   return still_event;
1722 }
1723
1724 /**
1725  * gst_video_event_parse_still_frame:
1726  * @event: A #GstEvent to parse
1727  * @in_still: A boolean to receive the still-frame status from the event, or NULL
1728  *
1729  * Parse a #GstEvent, identify if it is a Still Frame event, and
1730  * return the still-frame state from the event if it is.
1731  * If the event represents the start of a still frame, the in_still
1732  * variable will be set to TRUE, otherwise FALSE. It is OK to pass NULL for the
1733  * in_still variable order to just check whether the event is a valid still-frame
1734  * event.
1735  *
1736  * Create a still frame event using gst_video_event_new_still_frame()
1737  *
1738  * Returns: %TRUE if the event is a valid still-frame event. %FALSE if not
1739  * Since: 0.10.26
1740  */
1741 gboolean
1742 gst_video_event_parse_still_frame (GstEvent * event, gboolean * in_still)
1743 {
1744   const GstStructure *s;
1745   gboolean ev_still_state;
1746
1747   g_return_val_if_fail (event != NULL, FALSE);
1748
1749   if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_DOWNSTREAM)
1750     return FALSE;               /* Not a still frame event */
1751
1752   s = gst_event_get_structure (event);
1753   if (s == NULL
1754       || !gst_structure_has_name (s, GST_VIDEO_EVENT_STILL_STATE_NAME))
1755     return FALSE;               /* Not a still frame event */
1756   if (!gst_structure_get_boolean (s, "still-state", &ev_still_state))
1757     return FALSE;               /* Not a still frame event */
1758   if (in_still)
1759     *in_still = ev_still_state;
1760   return TRUE;
1761 }