gstvideo: Fix typos in comments
[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_format_parse_caps:
254  * @caps: the #GstCaps to parse
255  * @format: the #GstVideoFormat of the video represented by @caps (output)
256  * @width: the width of the video represented by @caps, may be NULL (output)
257  * @height: the height of the video represented by @caps, may be NULL (output)
258  *
259  * Determines the #GstVideoFormat of @caps and places it in the location
260  * pointed to by @format.  Extracts the size of the video and places it
261  * in the location pointed to by @width and @height.  If @caps does not
262  * represent one of the raw video formats listed in #GstVideoFormat, the
263  * function will fail and return FALSE.
264  *
265  * Since: 0.10.16
266  *
267  * Returns: TRUE if @caps was parsed correctly.
268  */
269 gboolean
270 gst_video_format_parse_caps (GstCaps * caps, GstVideoFormat * format,
271     int *width, int *height)
272 {
273   GstStructure *structure;
274   gboolean ok = TRUE;
275
276   if (!gst_caps_is_fixed (caps))
277     return FALSE;
278
279   structure = gst_caps_get_structure (caps, 0);
280
281   if (format) {
282     if (gst_structure_has_name (structure, "video/x-raw-yuv")) {
283       guint32 fourcc;
284
285       ok &= gst_structure_get_fourcc (structure, "format", &fourcc);
286
287       *format = gst_video_format_from_fourcc (fourcc);
288       if (*format == GST_VIDEO_FORMAT_UNKNOWN) {
289         ok = FALSE;
290       }
291     } else if (gst_structure_has_name (structure, "video/x-raw-rgb")) {
292       int depth;
293       int bpp;
294       int endianness;
295       int red_mask;
296       int green_mask;
297       int blue_mask;
298       int alpha_mask;
299       gboolean have_alpha;
300
301       ok &= gst_structure_get_int (structure, "depth", &depth);
302       ok &= gst_structure_get_int (structure, "bpp", &bpp);
303       ok &= gst_structure_get_int (structure, "endianness", &endianness);
304       ok &= gst_structure_get_int (structure, "red_mask", &red_mask);
305       ok &= gst_structure_get_int (structure, "green_mask", &green_mask);
306       ok &= gst_structure_get_int (structure, "blue_mask", &blue_mask);
307       have_alpha = gst_structure_get_int (structure, "alpha_mask", &alpha_mask);
308
309       if (depth == 24 && bpp == 32 && endianness == G_BIG_ENDIAN) {
310         *format = gst_video_format_from_rgb32_masks (red_mask, green_mask,
311             blue_mask);
312         if (*format == GST_VIDEO_FORMAT_UNKNOWN) {
313           ok = FALSE;
314         }
315       } else if (depth == 32 && bpp == 32 && endianness == G_BIG_ENDIAN &&
316           have_alpha) {
317         *format = gst_video_format_from_rgba32_masks (red_mask, green_mask,
318             blue_mask, alpha_mask);
319         if (*format == GST_VIDEO_FORMAT_UNKNOWN) {
320           ok = FALSE;
321         }
322       } else if (depth == 24 && bpp == 24 && endianness == G_BIG_ENDIAN) {
323         *format = gst_video_format_from_rgb24_masks (red_mask, green_mask,
324             blue_mask);
325         if (*format == GST_VIDEO_FORMAT_UNKNOWN) {
326           ok = FALSE;
327         }
328       } else {
329         ok = FALSE;
330       }
331     } else {
332       ok = FALSE;
333     }
334   }
335
336   if (width) {
337     ok &= gst_structure_get_int (structure, "width", width);
338   }
339
340   if (height) {
341     ok &= gst_structure_get_int (structure, "height", height);
342   }
343
344   return ok;
345 }
346
347
348 /**
349  * gst_video_parse_caps_framerate:
350  * @caps: pointer to a #GstCaps instance
351  * @fps_n: pointer to integer to hold numerator of frame rate (output)
352  * @fps_d: pointer to integer to hold denominator of frame rate (output)
353  *
354  * Extracts the frame rate from @caps and places the values in the locations
355  * pointed to by @fps_n and @fps_d.  Returns TRUE if the values could be
356  * parsed correctly, FALSE if not.
357  *
358  * This function can be used with #GstCaps that have any media type; it
359  * is not limited to formats handled by #GstVideoFormat.
360  *
361  * Since: 0.10.16
362  *
363  * Returns: TRUE if @caps was parsed correctly.
364  */
365 gboolean
366 gst_video_parse_caps_framerate (GstCaps * caps, int *fps_n, int *fps_d)
367 {
368   GstStructure *structure;
369
370   if (!gst_caps_is_fixed (caps))
371     return FALSE;
372
373   structure = gst_caps_get_structure (caps, 0);
374
375   return gst_structure_get_fraction (structure, "framerate", fps_n, fps_d);
376 }
377
378 /**
379  * gst_video_parse_caps_pixel_aspect_ratio:
380  * @caps: pointer to a #GstCaps instance
381  * @par_n: pointer to numerator of pixel aspect ratio (output)
382  * @par_d: pointer to denominator of pixel aspect ratio (output)
383  *
384  * Extracts the pixel aspect ratio from @caps and places the values in
385  * the locations pointed to by @par_n and @par_d.  Returns TRUE if the
386  * values could be parsed correctly, FALSE if not.
387  *
388  * This function can be used with #GstCaps that have any media type; it
389  * is not limited to formats handled by #GstVideoFormat.
390  *
391  * Since: 0.10.16
392  *
393  * Returns: TRUE if @caps was parsed correctly.
394  */
395 gboolean
396 gst_video_parse_caps_pixel_aspect_ratio (GstCaps * caps, int *par_n, int *par_d)
397 {
398   GstStructure *structure;
399
400   if (!gst_caps_is_fixed (caps))
401     return FALSE;
402
403   structure = gst_caps_get_structure (caps, 0);
404
405   if (!gst_structure_get_fraction (structure, "pixel-aspect-ratio",
406           par_n, par_d)) {
407     *par_n = 1;
408     *par_d = 1;
409   }
410   return TRUE;
411 }
412
413 /**
414  * gst_video_format_new_caps_interlaced:
415  * @format: the #GstVideoFormat describing the raw video format
416  * @width: width of video
417  * @height: height of video
418  * @framerate_n: numerator of frame rate
419  * @framerate_d: denominator of frame rate
420  * @par_n: numerator of pixel aspect ratio
421  * @par_d: denominator of pixel aspect ratio
422  * @interlaced: #TRUE if the format is interlaced
423  *
424  * Creates a new #GstCaps object based on the parameters provided.
425  *
426  * Since: 0.10.23
427  *
428  * Returns: a new #GstCaps object, or NULL if there was an error
429  */
430 GstCaps *
431 gst_video_format_new_caps_interlaced (GstVideoFormat format, int width,
432     int height, int framerate_n, int framerate_d, int par_n, int par_d,
433     gboolean interlaced)
434 {
435   GstCaps *res;
436
437   res =
438       gst_video_format_new_caps (format, width, height, framerate_n,
439       framerate_d, par_n, par_d);
440   if (interlaced && (res != NULL))
441     gst_caps_set_simple (res, "interlaced", G_TYPE_BOOLEAN, TRUE, NULL);
442
443   return res;
444 }
445
446 /**
447  * gst_video_format_new_caps:
448  * @format: the #GstVideoFormat describing the raw video format
449  * @width: width of video
450  * @height: height of video
451  * @framerate_n: numerator of frame rate
452  * @framerate_d: denominator of frame rate
453  * @par_n: numerator of pixel aspect ratio
454  * @par_d: denominator of pixel aspect ratio
455  *
456  * Creates a new #GstCaps object based on the parameters provided.
457  *
458  * Since: 0.10.16
459  *
460  * Returns: a new #GstCaps object, or NULL if there was an error
461  */
462 GstCaps *
463 gst_video_format_new_caps (GstVideoFormat format, int width, int height,
464     int framerate_n, int framerate_d, int par_n, int par_d)
465 {
466   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
467   g_return_val_if_fail (width > 0 && height > 0, NULL);
468
469   if (gst_video_format_is_yuv (format)) {
470     return gst_caps_new_simple ("video/x-raw-yuv",
471         "format", GST_TYPE_FOURCC, gst_video_format_to_fourcc (format),
472         "width", G_TYPE_INT, width,
473         "height", G_TYPE_INT, height,
474         "framerate", GST_TYPE_FRACTION, framerate_n, framerate_d,
475         "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, NULL);
476   }
477   if (gst_video_format_is_rgb (format)) {
478     GstCaps *caps;
479     int red_mask;
480     int blue_mask;
481     int green_mask;
482     int alpha_mask;
483     int depth;
484     int bpp;
485     gboolean have_alpha;
486     unsigned int mask;
487
488     switch (format) {
489       case GST_VIDEO_FORMAT_RGBx:
490       case GST_VIDEO_FORMAT_BGRx:
491       case GST_VIDEO_FORMAT_xRGB:
492       case GST_VIDEO_FORMAT_xBGR:
493         bpp = 32;
494         depth = 24;
495         have_alpha = FALSE;
496         break;
497       case GST_VIDEO_FORMAT_RGBA:
498       case GST_VIDEO_FORMAT_BGRA:
499       case GST_VIDEO_FORMAT_ARGB:
500       case GST_VIDEO_FORMAT_ABGR:
501         bpp = 32;
502         depth = 32;
503         have_alpha = TRUE;
504         break;
505       case GST_VIDEO_FORMAT_RGB:
506       case GST_VIDEO_FORMAT_BGR:
507         bpp = 24;
508         depth = 24;
509         have_alpha = FALSE;
510         break;
511       default:
512         return NULL;
513     }
514     if (bpp == 32) {
515       mask = 0xff000000;
516     } else {
517       mask = 0xff0000;
518     }
519     red_mask =
520         mask >> (8 * gst_video_format_get_component_offset (format, 0, width,
521             height));
522     green_mask =
523         mask >> (8 * gst_video_format_get_component_offset (format, 1, width,
524             height));
525     blue_mask =
526         mask >> (8 * gst_video_format_get_component_offset (format, 2, width,
527             height));
528
529     caps = gst_caps_new_simple ("video/x-raw-rgb",
530         "bpp", G_TYPE_INT, bpp,
531         "depth", G_TYPE_INT, depth,
532         "endianness", G_TYPE_INT, G_BIG_ENDIAN,
533         "red_mask", G_TYPE_INT, red_mask,
534         "green_mask", G_TYPE_INT, green_mask,
535         "blue_mask", G_TYPE_INT, blue_mask,
536         "width", G_TYPE_INT, width,
537         "height", G_TYPE_INT, height,
538         "framerate", GST_TYPE_FRACTION, framerate_n, framerate_d,
539         "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, NULL);
540     if (have_alpha) {
541       alpha_mask =
542           mask >> (8 * gst_video_format_get_component_offset (format, 3, width,
543               height));
544       gst_caps_set_simple (caps, "alpha_mask", G_TYPE_INT, alpha_mask, NULL);
545     }
546     return caps;
547   }
548   return NULL;
549 }
550
551 /**
552  * gst_video_format_from_fourcc:
553  * @fourcc: a FOURCC value representing raw YUV video
554  *
555  * Converts a FOURCC value into the corresponding #GstVideoFormat.
556  * If the FOURCC cannot be represented by #GstVideoFormat,
557  * #GST_VIDEO_FORMAT_UNKNOWN is returned.
558  *
559  * Since: 0.10.16
560  *
561  * Returns: the #GstVideoFormat describing the FOURCC value
562  */
563 GstVideoFormat
564 gst_video_format_from_fourcc (guint32 fourcc)
565 {
566   switch (fourcc) {
567     case GST_MAKE_FOURCC ('I', '4', '2', '0'):
568       return GST_VIDEO_FORMAT_I420;
569     case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
570       return GST_VIDEO_FORMAT_YV12;
571     case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
572       return GST_VIDEO_FORMAT_YUY2;
573     case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'):
574       return GST_VIDEO_FORMAT_YVYU;
575     case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
576       return GST_VIDEO_FORMAT_UYVY;
577     case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'):
578       return GST_VIDEO_FORMAT_AYUV;
579     case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
580       return GST_VIDEO_FORMAT_Y41B;
581     case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
582       return GST_VIDEO_FORMAT_Y42B;
583     case GST_MAKE_FOURCC ('Y', '4', '4', '4'):
584       return GST_VIDEO_FORMAT_Y444;
585     case GST_MAKE_FOURCC ('v', '2', '1', '0'):
586       return GST_VIDEO_FORMAT_v210;
587     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
588       return GST_VIDEO_FORMAT_v216;
589     case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
590       return GST_VIDEO_FORMAT_NV12;
591     case GST_MAKE_FOURCC ('N', 'V', '2', '1'):
592       return GST_VIDEO_FORMAT_NV21;
593     default:
594       return GST_VIDEO_FORMAT_UNKNOWN;
595   }
596 }
597
598 /**
599  * gst_video_format_to_fourcc:
600  * @format: a #GstVideoFormat video format
601  *
602  * Converts a #GstVideoFormat value into the corresponding FOURCC.  Only
603  * a few YUV formats have corresponding FOURCC values.  If @format has
604  * no corresponding FOURCC value, 0 is returned.
605  *
606  * Since: 0.10.16
607  *
608  * Returns: the FOURCC corresponding to @format
609  */
610 guint32
611 gst_video_format_to_fourcc (GstVideoFormat format)
612 {
613   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
614
615   switch (format) {
616     case GST_VIDEO_FORMAT_I420:
617       return GST_MAKE_FOURCC ('I', '4', '2', '0');
618     case GST_VIDEO_FORMAT_YV12:
619       return GST_MAKE_FOURCC ('Y', 'V', '1', '2');
620     case GST_VIDEO_FORMAT_YUY2:
621       return GST_MAKE_FOURCC ('Y', 'U', 'Y', '2');
622     case GST_VIDEO_FORMAT_YVYU:
623       return GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U');
624     case GST_VIDEO_FORMAT_UYVY:
625       return GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y');
626     case GST_VIDEO_FORMAT_AYUV:
627       return GST_MAKE_FOURCC ('A', 'Y', 'U', 'V');
628     case GST_VIDEO_FORMAT_Y41B:
629       return GST_MAKE_FOURCC ('Y', '4', '1', 'B');
630     case GST_VIDEO_FORMAT_Y42B:
631       return GST_MAKE_FOURCC ('Y', '4', '2', 'B');
632     case GST_VIDEO_FORMAT_Y444:
633       return GST_MAKE_FOURCC ('Y', '4', '4', '4');
634     case GST_VIDEO_FORMAT_v210:
635       return GST_MAKE_FOURCC ('v', '2', '1', '0');
636     case GST_VIDEO_FORMAT_v216:
637       return GST_MAKE_FOURCC ('v', '2', '1', '6');
638     case GST_VIDEO_FORMAT_NV12:
639       return GST_MAKE_FOURCC ('N', 'V', '1', '2');
640     case GST_VIDEO_FORMAT_NV21:
641       return GST_MAKE_FOURCC ('N', 'V', '2', '1');
642     default:
643       return 0;
644   }
645 }
646
647 /*
648  * gst_video_format_from_rgb32_masks:
649  * @red_mask: red bit mask
650  * @green_mask: green bit mask
651  * @blue_mask: blue bit mask
652  *
653  * Converts red, green, blue bit masks into the corresponding
654  * #GstVideoFormat.  
655  *
656  * Since: 0.10.16
657  *
658  * Returns: the #GstVideoFormat corresponding to the bit masks
659  */
660 static GstVideoFormat
661 gst_video_format_from_rgb32_masks (int red_mask, int green_mask, int blue_mask)
662 {
663   if (red_mask == 0xff000000 && green_mask == 0x00ff0000 &&
664       blue_mask == 0x0000ff00) {
665     return GST_VIDEO_FORMAT_RGBx;
666   }
667   if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 &&
668       blue_mask == 0xff000000) {
669     return GST_VIDEO_FORMAT_BGRx;
670   }
671   if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 &&
672       blue_mask == 0x000000ff) {
673     return GST_VIDEO_FORMAT_xRGB;
674   }
675   if (red_mask == 0x000000ff && green_mask == 0x0000ff00 &&
676       blue_mask == 0x00ff0000) {
677     return GST_VIDEO_FORMAT_xBGR;
678   }
679
680   return GST_VIDEO_FORMAT_UNKNOWN;
681 }
682
683 static GstVideoFormat
684 gst_video_format_from_rgba32_masks (int red_mask, int green_mask, int blue_mask,
685     int alpha_mask)
686 {
687   if (red_mask == 0xff000000 && green_mask == 0x00ff0000 &&
688       blue_mask == 0x0000ff00 && alpha_mask == 0x000000ff) {
689     return GST_VIDEO_FORMAT_RGBA;
690   }
691   if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 &&
692       blue_mask == 0xff000000 && alpha_mask == 0x000000ff) {
693     return GST_VIDEO_FORMAT_BGRA;
694   }
695   if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 &&
696       blue_mask == 0x000000ff && alpha_mask == 0xff000000) {
697     return GST_VIDEO_FORMAT_ARGB;
698   }
699   if (red_mask == 0x000000ff && green_mask == 0x0000ff00 &&
700       blue_mask == 0x00ff0000 && alpha_mask == 0xff000000) {
701     return GST_VIDEO_FORMAT_ABGR;
702   }
703
704   return GST_VIDEO_FORMAT_UNKNOWN;
705 }
706
707 static GstVideoFormat
708 gst_video_format_from_rgb24_masks (int red_mask, int green_mask, int blue_mask)
709 {
710   if (red_mask == 0xff0000 && green_mask == 0x00ff00 && blue_mask == 0x0000ff) {
711     return GST_VIDEO_FORMAT_RGB;
712   }
713   if (red_mask == 0x0000ff && green_mask == 0x00ff00 && blue_mask == 0xff0000) {
714     return GST_VIDEO_FORMAT_BGR;
715   }
716
717   return GST_VIDEO_FORMAT_UNKNOWN;
718 }
719
720 /**
721  * gst_video_format_is_rgb:
722  * @format: a #GstVideoFormat
723  *
724  * Determine whether the video format is an RGB format.
725  *
726  * Since: 0.10.16
727  *
728  * Returns: TRUE if @format represents RGB video
729  */
730 gboolean
731 gst_video_format_is_rgb (GstVideoFormat format)
732 {
733   switch (format) {
734     case GST_VIDEO_FORMAT_I420:
735     case GST_VIDEO_FORMAT_YV12:
736     case GST_VIDEO_FORMAT_YUY2:
737     case GST_VIDEO_FORMAT_YVYU:
738     case GST_VIDEO_FORMAT_UYVY:
739     case GST_VIDEO_FORMAT_AYUV:
740     case GST_VIDEO_FORMAT_Y41B:
741     case GST_VIDEO_FORMAT_Y42B:
742     case GST_VIDEO_FORMAT_Y444:
743     case GST_VIDEO_FORMAT_v210:
744     case GST_VIDEO_FORMAT_v216:
745     case GST_VIDEO_FORMAT_NV12:
746     case GST_VIDEO_FORMAT_NV21:
747       return FALSE;
748     case GST_VIDEO_FORMAT_RGBx:
749     case GST_VIDEO_FORMAT_BGRx:
750     case GST_VIDEO_FORMAT_xRGB:
751     case GST_VIDEO_FORMAT_xBGR:
752     case GST_VIDEO_FORMAT_RGBA:
753     case GST_VIDEO_FORMAT_BGRA:
754     case GST_VIDEO_FORMAT_ARGB:
755     case GST_VIDEO_FORMAT_ABGR:
756     case GST_VIDEO_FORMAT_RGB:
757     case GST_VIDEO_FORMAT_BGR:
758       return TRUE;
759     default:
760       return FALSE;
761   }
762 }
763
764 /**
765  * gst_video_format_is_yuv:
766  * @format: a #GstVideoFormat
767  *
768  * Determine whether the video format is a YUV format.
769  *
770  * Since: 0.10.16
771  *
772  * Returns: TRUE if @format represents YUV video
773  */
774 gboolean
775 gst_video_format_is_yuv (GstVideoFormat format)
776 {
777   switch (format) {
778     case GST_VIDEO_FORMAT_I420:
779     case GST_VIDEO_FORMAT_YV12:
780     case GST_VIDEO_FORMAT_YUY2:
781     case GST_VIDEO_FORMAT_YVYU:
782     case GST_VIDEO_FORMAT_UYVY:
783     case GST_VIDEO_FORMAT_AYUV:
784     case GST_VIDEO_FORMAT_Y41B:
785     case GST_VIDEO_FORMAT_Y42B:
786     case GST_VIDEO_FORMAT_Y444:
787     case GST_VIDEO_FORMAT_v210:
788     case GST_VIDEO_FORMAT_v216:
789     case GST_VIDEO_FORMAT_NV12:
790     case GST_VIDEO_FORMAT_NV21:
791       return TRUE;
792     case GST_VIDEO_FORMAT_RGBx:
793     case GST_VIDEO_FORMAT_BGRx:
794     case GST_VIDEO_FORMAT_xRGB:
795     case GST_VIDEO_FORMAT_xBGR:
796     case GST_VIDEO_FORMAT_RGBA:
797     case GST_VIDEO_FORMAT_BGRA:
798     case GST_VIDEO_FORMAT_ARGB:
799     case GST_VIDEO_FORMAT_ABGR:
800     case GST_VIDEO_FORMAT_RGB:
801     case GST_VIDEO_FORMAT_BGR:
802       return FALSE;
803     default:
804       return FALSE;
805   }
806 }
807
808 /**
809  * gst_video_format_has_alpha:
810  * @format: a #GstVideoFormat
811  * 
812  * Returns TRUE or FALSE depending on if the video format provides an
813  * alpha channel.
814  *
815  * Since: 0.10.16
816  *
817  * Returns: TRUE if @format has an alpha channel
818  */
819 gboolean
820 gst_video_format_has_alpha (GstVideoFormat format)
821 {
822   switch (format) {
823     case GST_VIDEO_FORMAT_I420:
824     case GST_VIDEO_FORMAT_YV12:
825     case GST_VIDEO_FORMAT_YUY2:
826     case GST_VIDEO_FORMAT_YVYU:
827     case GST_VIDEO_FORMAT_UYVY:
828     case GST_VIDEO_FORMAT_Y41B:
829     case GST_VIDEO_FORMAT_Y42B:
830     case GST_VIDEO_FORMAT_Y444:
831     case GST_VIDEO_FORMAT_v210:
832     case GST_VIDEO_FORMAT_v216:
833     case GST_VIDEO_FORMAT_NV12:
834     case GST_VIDEO_FORMAT_NV21:
835       return FALSE;
836     case GST_VIDEO_FORMAT_AYUV:
837     case GST_VIDEO_FORMAT_RGBA:
838     case GST_VIDEO_FORMAT_BGRA:
839     case GST_VIDEO_FORMAT_ARGB:
840     case GST_VIDEO_FORMAT_ABGR:
841       return TRUE;
842     case GST_VIDEO_FORMAT_RGBx:
843     case GST_VIDEO_FORMAT_BGRx:
844     case GST_VIDEO_FORMAT_xRGB:
845     case GST_VIDEO_FORMAT_xBGR:
846     case GST_VIDEO_FORMAT_RGB:
847     case GST_VIDEO_FORMAT_BGR:
848       return FALSE;
849     default:
850       return FALSE;
851   }
852 }
853
854 /**
855  * gst_video_format_get_row_stride:
856  * @format: a #GstVideoFormat
857  * @component: the component index
858  * @width: the width of video
859  *
860  * Calculates the row stride (number of bytes from one row of pixels to
861  * the next) for the video component with an index of @component.  For
862  * YUV video, Y, U, and V have component indices of 0, 1, and 2,
863  * respectively.  For RGB video, R, G, and B have component indicies of
864  * 0, 1, and 2, respectively.  Alpha channels, if present, have a component
865  * index of 3.  The @width parameter always represents the width of the
866  * video, not the component.
867  *
868  * Since: 0.10.16
869  *
870  * Returns: row stride of component @component
871  */
872 int
873 gst_video_format_get_row_stride (GstVideoFormat format, int component,
874     int width)
875 {
876   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
877   g_return_val_if_fail (component >= 0 && component <= 3, 0);
878   g_return_val_if_fail (width > 0, 0);
879
880   switch (format) {
881     case GST_VIDEO_FORMAT_I420:
882     case GST_VIDEO_FORMAT_YV12:
883       if (component == 0) {
884         return GST_ROUND_UP_4 (width);
885       } else {
886         return GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
887       }
888     case GST_VIDEO_FORMAT_YUY2:
889     case GST_VIDEO_FORMAT_YVYU:
890     case GST_VIDEO_FORMAT_UYVY:
891       return GST_ROUND_UP_4 (width * 2);
892     case GST_VIDEO_FORMAT_AYUV:
893     case GST_VIDEO_FORMAT_RGBx:
894     case GST_VIDEO_FORMAT_BGRx:
895     case GST_VIDEO_FORMAT_xRGB:
896     case GST_VIDEO_FORMAT_xBGR:
897     case GST_VIDEO_FORMAT_RGBA:
898     case GST_VIDEO_FORMAT_BGRA:
899     case GST_VIDEO_FORMAT_ARGB:
900     case GST_VIDEO_FORMAT_ABGR:
901       return width * 4;
902     case GST_VIDEO_FORMAT_RGB:
903     case GST_VIDEO_FORMAT_BGR:
904       return GST_ROUND_UP_4 (width * 3);
905     case GST_VIDEO_FORMAT_Y41B:
906       if (component == 0) {
907         return GST_ROUND_UP_4 (width);
908       } else {
909         return GST_ROUND_UP_16 (width) / 4;
910       }
911     case GST_VIDEO_FORMAT_Y42B:
912       if (component == 0) {
913         return GST_ROUND_UP_4 (width);
914       } else {
915         return GST_ROUND_UP_8 (width) / 2;
916       }
917     case GST_VIDEO_FORMAT_Y444:
918       return GST_ROUND_UP_4 (width);
919     case GST_VIDEO_FORMAT_v210:
920       return ((width + 47) / 48) * 128;
921     case GST_VIDEO_FORMAT_v216:
922       return GST_ROUND_UP_8 (width * 4);
923     case GST_VIDEO_FORMAT_NV12:
924     case GST_VIDEO_FORMAT_NV21:
925       return GST_ROUND_UP_4 (width);
926     default:
927       return 0;
928   }
929 }
930
931 /**
932  * gst_video_format_get_pixel_stride:
933  * @format: a #GstVideoFormat
934  * @component: the component index
935  *
936  * Calculates the pixel stride (number of bytes from one pixel to the
937  * pixel to its immediate left) for the video component with an index
938  * of @component.  See @gst_video_format_get_row_stride for a description
939  * of the component index.
940  *
941  * Since: 0.10.16
942  *
943  * Returns: pixel stride of component @component
944  */
945 int
946 gst_video_format_get_pixel_stride (GstVideoFormat format, int component)
947 {
948   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
949   g_return_val_if_fail (component >= 0 && component <= 3, 0);
950
951   switch (format) {
952     case GST_VIDEO_FORMAT_I420:
953     case GST_VIDEO_FORMAT_YV12:
954     case GST_VIDEO_FORMAT_Y41B:
955     case GST_VIDEO_FORMAT_Y42B:
956     case GST_VIDEO_FORMAT_Y444:
957       return 1;
958     case GST_VIDEO_FORMAT_YUY2:
959     case GST_VIDEO_FORMAT_YVYU:
960     case GST_VIDEO_FORMAT_UYVY:
961       if (component == 0) {
962         return 2;
963       } else {
964         return 4;
965       }
966     case GST_VIDEO_FORMAT_AYUV:
967     case GST_VIDEO_FORMAT_RGBx:
968     case GST_VIDEO_FORMAT_BGRx:
969     case GST_VIDEO_FORMAT_xRGB:
970     case GST_VIDEO_FORMAT_xBGR:
971     case GST_VIDEO_FORMAT_RGBA:
972     case GST_VIDEO_FORMAT_BGRA:
973     case GST_VIDEO_FORMAT_ARGB:
974     case GST_VIDEO_FORMAT_ABGR:
975       return 4;
976     case GST_VIDEO_FORMAT_RGB:
977     case GST_VIDEO_FORMAT_BGR:
978       return 3;
979     case GST_VIDEO_FORMAT_v210:
980       /* v210 is packed at the bit level, so pixel stride doesn't make sense */
981       return 0;
982     case GST_VIDEO_FORMAT_v216:
983       if (component == 0) {
984         return 4;
985       } else {
986         return 8;
987       }
988     case GST_VIDEO_FORMAT_NV12:
989     case GST_VIDEO_FORMAT_NV21:
990       if (component == 0) {
991         return 1;
992       } else {
993         return 2;
994       }
995     default:
996       return 0;
997   }
998 }
999
1000 /**
1001  * gst_video_format_get_component_width:
1002  * @format: a #GstVideoFormat
1003  * @component: the component index
1004  * @width: the width of video
1005  *
1006  * Calculates the width of the component.  See
1007  * @gst_video_format_get_row_stride for a description
1008  * of the component index.
1009  *
1010  * Since: 0.10.16
1011  *
1012  * Returns: width of component @component
1013  */
1014 int
1015 gst_video_format_get_component_width (GstVideoFormat format, int component,
1016     int width)
1017 {
1018   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1019   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1020   g_return_val_if_fail (width > 0, 0);
1021
1022   switch (format) {
1023     case GST_VIDEO_FORMAT_I420:
1024     case GST_VIDEO_FORMAT_YV12:
1025     case GST_VIDEO_FORMAT_YUY2:
1026     case GST_VIDEO_FORMAT_YVYU:
1027     case GST_VIDEO_FORMAT_UYVY:
1028     case GST_VIDEO_FORMAT_Y42B:
1029     case GST_VIDEO_FORMAT_v210:
1030     case GST_VIDEO_FORMAT_v216:
1031       if (component == 0) {
1032         return width;
1033       } else {
1034         return GST_ROUND_UP_2 (width) / 2;
1035       }
1036     case GST_VIDEO_FORMAT_Y41B:
1037       if (component == 0) {
1038         return width;
1039       } else {
1040         return GST_ROUND_UP_4 (width) / 4;
1041       }
1042     case GST_VIDEO_FORMAT_AYUV:
1043     case GST_VIDEO_FORMAT_RGBx:
1044     case GST_VIDEO_FORMAT_BGRx:
1045     case GST_VIDEO_FORMAT_xRGB:
1046     case GST_VIDEO_FORMAT_xBGR:
1047     case GST_VIDEO_FORMAT_RGBA:
1048     case GST_VIDEO_FORMAT_BGRA:
1049     case GST_VIDEO_FORMAT_ARGB:
1050     case GST_VIDEO_FORMAT_ABGR:
1051     case GST_VIDEO_FORMAT_RGB:
1052     case GST_VIDEO_FORMAT_BGR:
1053     case GST_VIDEO_FORMAT_Y444:
1054     case GST_VIDEO_FORMAT_NV12:
1055     case GST_VIDEO_FORMAT_NV21:
1056       return width;
1057     default:
1058       return 0;
1059   }
1060 }
1061
1062 /**
1063  * gst_video_format_get_component_height:
1064  * @format: a #GstVideoFormat
1065  * @component: the component index
1066  * @height: the height of video
1067  *
1068  * Calculates the height of the component.  See
1069  * @gst_video_format_get_row_stride for a description
1070  * of the component index.
1071  *
1072  * Since: 0.10.16
1073  *
1074  * Returns: height of component @component
1075  */
1076 int
1077 gst_video_format_get_component_height (GstVideoFormat format, int component,
1078     int height)
1079 {
1080   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1081   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1082   g_return_val_if_fail (height > 0, 0);
1083
1084   switch (format) {
1085     case GST_VIDEO_FORMAT_I420:
1086     case GST_VIDEO_FORMAT_YV12:
1087     case GST_VIDEO_FORMAT_NV12:
1088     case GST_VIDEO_FORMAT_NV21:
1089       if (component == 0) {
1090         return height;
1091       } else {
1092         return GST_ROUND_UP_2 (height) / 2;
1093       }
1094     case GST_VIDEO_FORMAT_Y41B:
1095     case GST_VIDEO_FORMAT_Y42B:
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_RGBx:
1101     case GST_VIDEO_FORMAT_BGRx:
1102     case GST_VIDEO_FORMAT_xRGB:
1103     case GST_VIDEO_FORMAT_xBGR:
1104     case GST_VIDEO_FORMAT_RGBA:
1105     case GST_VIDEO_FORMAT_BGRA:
1106     case GST_VIDEO_FORMAT_ARGB:
1107     case GST_VIDEO_FORMAT_ABGR:
1108     case GST_VIDEO_FORMAT_RGB:
1109     case GST_VIDEO_FORMAT_BGR:
1110     case GST_VIDEO_FORMAT_Y444:
1111     case GST_VIDEO_FORMAT_v210:
1112     case GST_VIDEO_FORMAT_v216:
1113       return height;
1114     default:
1115       return 0;
1116   }
1117 }
1118
1119 /**
1120  * gst_video_format_get_component_offset:
1121  * @format: a #GstVideoFormat
1122  * @component: the component index
1123  * @width: the width of video
1124  * @height: the height of video
1125  *
1126  * Calculates the offset (in bytes) of the first pixel of the component
1127  * with index @component.  For packed formats, this will typically be a
1128  * small integer (0, 1, 2, 3).  For planar formats, this will be a
1129  * (relatively) large offset to the beginning of the second or third
1130  * component planes.  See @gst_video_format_get_row_stride for a description
1131  * of the component index.
1132  *
1133  * Since: 0.10.16
1134  *
1135  * Returns: offset of component @component
1136  */
1137 int
1138 gst_video_format_get_component_offset (GstVideoFormat format, int component,
1139     int width, int height)
1140 {
1141   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1142   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1143   g_return_val_if_fail (width > 0 && height > 0, 0);
1144
1145   switch (format) {
1146     case GST_VIDEO_FORMAT_I420:
1147       if (component == 0)
1148         return 0;
1149       if (component == 1)
1150         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1151       if (component == 2) {
1152         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) +
1153             GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1154             (GST_ROUND_UP_2 (height) / 2);
1155       }
1156       return 0;
1157     case GST_VIDEO_FORMAT_YV12:        /* same as I420, but components 1+2 swapped */
1158       if (component == 0)
1159         return 0;
1160       if (component == 2)
1161         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1162       if (component == 1) {
1163         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) +
1164             GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1165             (GST_ROUND_UP_2 (height) / 2);
1166       }
1167       return 0;
1168     case GST_VIDEO_FORMAT_YUY2:
1169       if (component == 0)
1170         return 0;
1171       if (component == 1)
1172         return 1;
1173       if (component == 2)
1174         return 3;
1175       return 0;
1176     case GST_VIDEO_FORMAT_YVYU:
1177       if (component == 0)
1178         return 0;
1179       if (component == 1)
1180         return 3;
1181       if (component == 2)
1182         return 1;
1183       return 0;
1184     case GST_VIDEO_FORMAT_UYVY:
1185       if (component == 0)
1186         return 1;
1187       if (component == 1)
1188         return 0;
1189       if (component == 2)
1190         return 2;
1191       return 0;
1192     case GST_VIDEO_FORMAT_AYUV:
1193       if (component == 0)
1194         return 1;
1195       if (component == 1)
1196         return 2;
1197       if (component == 2)
1198         return 3;
1199       if (component == 3)
1200         return 0;
1201       return 0;
1202     case GST_VIDEO_FORMAT_RGBx:
1203     case GST_VIDEO_FORMAT_RGBA:
1204       if (component == 0)
1205         return 0;
1206       if (component == 1)
1207         return 1;
1208       if (component == 2)
1209         return 2;
1210       if (component == 3)
1211         return 3;
1212       return 0;
1213     case GST_VIDEO_FORMAT_BGRx:
1214     case GST_VIDEO_FORMAT_BGRA:
1215       if (component == 0)
1216         return 2;
1217       if (component == 1)
1218         return 1;
1219       if (component == 2)
1220         return 0;
1221       if (component == 3)
1222         return 3;
1223       return 0;
1224     case GST_VIDEO_FORMAT_xRGB:
1225     case GST_VIDEO_FORMAT_ARGB:
1226       if (component == 0)
1227         return 1;
1228       if (component == 1)
1229         return 2;
1230       if (component == 2)
1231         return 3;
1232       if (component == 3)
1233         return 0;
1234       return 0;
1235     case GST_VIDEO_FORMAT_xBGR:
1236     case GST_VIDEO_FORMAT_ABGR:
1237       if (component == 0)
1238         return 3;
1239       if (component == 1)
1240         return 2;
1241       if (component == 2)
1242         return 1;
1243       if (component == 3)
1244         return 0;
1245       return 0;
1246     case GST_VIDEO_FORMAT_RGB:
1247       if (component == 0)
1248         return 0;
1249       if (component == 1)
1250         return 1;
1251       if (component == 2)
1252         return 2;
1253       return 0;
1254     case GST_VIDEO_FORMAT_BGR:
1255       if (component == 0)
1256         return 2;
1257       if (component == 1)
1258         return 1;
1259       if (component == 2)
1260         return 0;
1261       return 0;
1262     case GST_VIDEO_FORMAT_Y41B:
1263       if (component == 0)
1264         return 0;
1265       if (component == 1)
1266         return GST_ROUND_UP_4 (width) * height;
1267       if (component == 2)
1268         return (GST_ROUND_UP_4 (width) +
1269             (GST_ROUND_UP_16 (width) / 4)) * height;
1270       return 0;
1271     case GST_VIDEO_FORMAT_Y42B:
1272       if (component == 0)
1273         return 0;
1274       if (component == 1)
1275         return GST_ROUND_UP_4 (width) * height;
1276       if (component == 2)
1277         return (GST_ROUND_UP_4 (width) + (GST_ROUND_UP_8 (width) / 2)) * height;
1278       return 0;
1279     case GST_VIDEO_FORMAT_Y444:
1280       return GST_ROUND_UP_4 (width) * height * component;
1281     case GST_VIDEO_FORMAT_v210:
1282       /* v210 is bit-packed, so this doesn't make sense */
1283       return 0;
1284     case GST_VIDEO_FORMAT_v216:
1285       if (component == 0)
1286         return 0;
1287       if (component == 1)
1288         return 2;
1289       if (component == 2)
1290         return 6;
1291       return 0;
1292     case GST_VIDEO_FORMAT_NV12:
1293       if (component == 0)
1294         return 0;
1295       if (component == 1)
1296         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1297       if (component == 2)
1298         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) + 1;
1299     case GST_VIDEO_FORMAT_NV21:
1300       if (component == 0)
1301         return 0;
1302       if (component == 1)
1303         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) + 1;
1304       if (component == 2)
1305         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1306     default:
1307       return 0;
1308   }
1309 }
1310
1311 /**
1312  * gst_video_format_get_size:
1313  * @format: a #GstVideoFormat
1314  * @width: the width of video
1315  * @height: the height of video
1316  *
1317  * Calculates the total number of bytes in the raw video format.  This
1318  * number should be used when allocating a buffer for raw video.
1319  *
1320  * Since: 0.10.16
1321  *
1322  * Returns: size (in bytes) of raw video format
1323  */
1324 int
1325 gst_video_format_get_size (GstVideoFormat format, int width, int height)
1326 {
1327   int size;
1328
1329   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1330   g_return_val_if_fail (width > 0 && height > 0, 0);
1331
1332   switch (format) {
1333     case GST_VIDEO_FORMAT_I420:
1334     case GST_VIDEO_FORMAT_YV12:
1335       size = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1336       size += GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1337           (GST_ROUND_UP_2 (height) / 2) * 2;
1338       return size;
1339     case GST_VIDEO_FORMAT_YUY2:
1340     case GST_VIDEO_FORMAT_YVYU:
1341     case GST_VIDEO_FORMAT_UYVY:
1342       return GST_ROUND_UP_4 (width * 2) * height;
1343     case GST_VIDEO_FORMAT_AYUV:
1344     case GST_VIDEO_FORMAT_RGBx:
1345     case GST_VIDEO_FORMAT_BGRx:
1346     case GST_VIDEO_FORMAT_xRGB:
1347     case GST_VIDEO_FORMAT_xBGR:
1348     case GST_VIDEO_FORMAT_RGBA:
1349     case GST_VIDEO_FORMAT_BGRA:
1350     case GST_VIDEO_FORMAT_ARGB:
1351     case GST_VIDEO_FORMAT_ABGR:
1352       return width * 4 * height;
1353     case GST_VIDEO_FORMAT_RGB:
1354     case GST_VIDEO_FORMAT_BGR:
1355       return GST_ROUND_UP_4 (width * 3) * height;
1356     case GST_VIDEO_FORMAT_Y41B:
1357       /* simplification of ROUNDUP4(w)*h + 2*((ROUNDUP16(w)/4)*h */
1358       return (GST_ROUND_UP_4 (width) + (GST_ROUND_UP_16 (width) / 2)) * height;
1359     case GST_VIDEO_FORMAT_Y42B:
1360       /* simplification of ROUNDUP4(w)*h + 2*(ROUNDUP8(w)/2)*h */
1361       return (GST_ROUND_UP_4 (width) + GST_ROUND_UP_8 (width)) * height;
1362     case GST_VIDEO_FORMAT_Y444:
1363       return GST_ROUND_UP_4 (width) * height * 3;
1364     case GST_VIDEO_FORMAT_v210:
1365       return ((width + 47) / 48) * 128 * height;
1366     case GST_VIDEO_FORMAT_v216:
1367       return GST_ROUND_UP_8 (width * 4) * height;
1368     case GST_VIDEO_FORMAT_NV12:
1369     case GST_VIDEO_FORMAT_NV21:
1370       return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) * 3 / 2;
1371     default:
1372       return 0;
1373   }
1374 }
1375
1376 /**
1377  * gst_video_format_convert:
1378  * @format: a #GstVideoFormat
1379  * @width: the width of video
1380  * @height: the height of video
1381  * @fps_n: frame rate numerator
1382  * @fps_d: frame rate denominator
1383  * @src_format: #GstFormat of the @src_value
1384  * @src_value: value to convert
1385  * @dest_format: #GstFormat of the @dest_value
1386  * @dest_value: pointer to destination value
1387  *
1388  * Converts among various #GstFormat types.  This function handles
1389  * GST_FORMAT_BYTES, GST_FORMAT_TIME, and GST_FORMAT_DEFAULT.  For
1390  * raw video, GST_FORMAT_DEFAULT corresponds to video frames.  This
1391  * function can be to handle pad queries of the type GST_QUERY_CONVERT.
1392  *
1393  * Since: 0.10.16
1394  *
1395  * Returns: TRUE if the conversion was successful.
1396  */
1397 gboolean
1398 gst_video_format_convert (GstVideoFormat format, int width, int height,
1399     int fps_n, int fps_d,
1400     GstFormat src_format, gint64 src_value,
1401     GstFormat dest_format, gint64 * dest_value)
1402 {
1403   gboolean ret = FALSE;
1404   int size;
1405
1406   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1407   g_return_val_if_fail (width > 0 && height > 0, 0);
1408
1409   size = gst_video_format_get_size (format, width, height);
1410
1411   GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s to %s",
1412       src_value, gst_format_get_name (src_format),
1413       gst_format_get_name (dest_format));
1414
1415   if (src_format == dest_format) {
1416     *dest_value = src_value;
1417     ret = TRUE;
1418     goto done;
1419   }
1420
1421   if (src_value == -1) {
1422     *dest_value = -1;
1423     ret = TRUE;
1424     goto done;
1425   }
1426
1427   /* bytes to frames */
1428   if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_DEFAULT) {
1429     if (size != 0) {
1430       *dest_value = gst_util_uint64_scale_int (src_value, 1, size);
1431     } else {
1432       GST_ERROR ("blocksize is 0");
1433       *dest_value = 0;
1434     }
1435     ret = TRUE;
1436     goto done;
1437   }
1438
1439   /* frames to bytes */
1440   if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_BYTES) {
1441     *dest_value = gst_util_uint64_scale_int (src_value, size, 1);
1442     ret = TRUE;
1443     goto done;
1444   }
1445
1446   /* time to frames */
1447   if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_DEFAULT) {
1448     if (fps_d != 0) {
1449       *dest_value = gst_util_uint64_scale (src_value,
1450           fps_n, GST_SECOND * fps_d);
1451     } else {
1452       GST_ERROR ("framerate denominator is 0");
1453       *dest_value = 0;
1454     }
1455     ret = TRUE;
1456     goto done;
1457   }
1458
1459   /* frames to time */
1460   if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
1461     if (fps_n != 0) {
1462       *dest_value = gst_util_uint64_scale (src_value,
1463           GST_SECOND * fps_d, fps_n);
1464     } else {
1465       GST_ERROR ("framerate numerator is 0");
1466       *dest_value = 0;
1467     }
1468     ret = TRUE;
1469     goto done;
1470   }
1471
1472   /* time to bytes */
1473   if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) {
1474     if (fps_d != 0) {
1475       *dest_value = gst_util_uint64_scale (src_value,
1476           fps_n * size, GST_SECOND * fps_d);
1477     } else {
1478       GST_ERROR ("framerate denominator is 0");
1479       *dest_value = 0;
1480     }
1481     ret = TRUE;
1482     goto done;
1483   }
1484
1485   /* bytes to time */
1486   if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_TIME) {
1487     if (fps_n != 0 && size != 0) {
1488       *dest_value = gst_util_uint64_scale (src_value,
1489           GST_SECOND * fps_d, fps_n * size);
1490     } else {
1491       GST_ERROR ("framerate denominator and/or blocksize is 0");
1492       *dest_value = 0;
1493     }
1494     ret = TRUE;
1495   }
1496
1497 done:
1498
1499   GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, ret, *dest_value);
1500
1501   return ret;
1502 }
1503
1504 #define GST_VIDEO_EVENT_STILL_STATE_NAME "GstEventStillFrame"
1505
1506 /**
1507  * gst_video_event_new_still_frame:
1508  * @in_still: boolean value for the still-frame state of the event.
1509  *
1510  * Creates a new Still Frame event. If @in_still is %TRUE, then the event
1511  * represents the start of a still frame sequence. If it is %FALSE, then
1512  * the event ends a still frame sequence.
1513  *
1514  * To parse an event created by gst_video_event_new_still_frame() use
1515  * gst_video_event_parse_still_frame().
1516  *
1517  * Returns: The new GstEvent
1518  * Since: 0.10.26
1519  */
1520 GstEvent *
1521 gst_video_event_new_still_frame (gboolean in_still)
1522 {
1523   GstEvent *still_event;
1524   GstStructure *s;
1525
1526   s = gst_structure_new (GST_VIDEO_EVENT_STILL_STATE_NAME,
1527       "still-state", G_TYPE_BOOLEAN, in_still, NULL);
1528   still_event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
1529
1530   return still_event;
1531 }
1532
1533 /**
1534  * gst_video_event_parse_still_frame:
1535  * @event: A #GstEvent to parse
1536  * @in_still: A boolean to receive the still-frame status from the event, or NULL
1537  *
1538  * Parse a #GstEvent, identify if it is a Still Frame event, and
1539  * return the still-frame state from the event if it is.
1540  * If the event represents the start of a still frame, the in_still
1541  * variable will be set to TRUE, otherwise FALSE. It is OK to pass NULL for the
1542  * in_still variable order to just check whether the event is a valid still-frame
1543  * event.
1544  *
1545  * Create a still frame event using gst_video_event_new_still_frame()
1546  *
1547  * Returns: %TRUE if the event is a valid still-frame event. %FALSE if not
1548  * Since: 0.10.26
1549  */
1550 gboolean
1551 gst_video_event_parse_still_frame (GstEvent * event, gboolean * in_still)
1552 {
1553   const GstStructure *s;
1554   gboolean ev_still_state;
1555
1556   g_return_val_if_fail (event != NULL, FALSE);
1557
1558   if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_DOWNSTREAM)
1559     return FALSE;               /* Not a still frame event */
1560
1561   s = gst_event_get_structure (event);
1562   if (s == NULL
1563       || !gst_structure_has_name (s, GST_VIDEO_EVENT_STILL_STATE_NAME))
1564     return FALSE;               /* Not a still frame event */
1565   if (!gst_structure_get_boolean (s, "still-state", &ev_still_state))
1566     return FALSE;               /* Not a still frame event */
1567   if (in_still)
1568     *in_still = ev_still_state;
1569   return TRUE;
1570 }