libs/video: Fix gst_video_format_new_caps* functions.
[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 ('U', 'Y', 'V', 'Y'):
574       return GST_VIDEO_FORMAT_UYVY;
575     case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'):
576       return GST_VIDEO_FORMAT_AYUV;
577     case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
578       return GST_VIDEO_FORMAT_Y41B;
579     case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
580       return GST_VIDEO_FORMAT_Y42B;
581     default:
582       return GST_VIDEO_FORMAT_UNKNOWN;
583   }
584 }
585
586 /**
587  * gst_video_format_to_fourcc:
588  * @format: a #GstVideoFormat video format
589  *
590  * Converts a #GstVideoFormat value into the corresponding FOURCC.  Only
591  * a few YUV formats have corresponding FOURCC values.  If @format has
592  * no corresponding FOURCC value, 0 is returned.
593  *
594  * Since: 0.10.16
595  *
596  * Returns: the FOURCC corresponding to @format
597  */
598 guint32
599 gst_video_format_to_fourcc (GstVideoFormat format)
600 {
601   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
602
603   switch (format) {
604     case GST_VIDEO_FORMAT_I420:
605       return GST_MAKE_FOURCC ('I', '4', '2', '0');
606     case GST_VIDEO_FORMAT_YV12:
607       return GST_MAKE_FOURCC ('Y', 'V', '1', '2');
608     case GST_VIDEO_FORMAT_YUY2:
609       return GST_MAKE_FOURCC ('Y', 'U', 'Y', '2');
610     case GST_VIDEO_FORMAT_UYVY:
611       return GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y');
612     case GST_VIDEO_FORMAT_AYUV:
613       return GST_MAKE_FOURCC ('A', 'Y', 'U', 'V');
614     case GST_VIDEO_FORMAT_Y41B:
615       return GST_MAKE_FOURCC ('Y', '4', '1', 'B');
616     case GST_VIDEO_FORMAT_Y42B:
617       return GST_MAKE_FOURCC ('Y', '4', '2', 'B');
618     default:
619       return 0;
620   }
621 }
622
623 /*
624  * gst_video_format_from_rgb32_masks:
625  * @red_mask: red bit mask
626  * @green_mask: green bit mask
627  * @blue_mask: blue bit mask
628  *
629  * Converts red, green, blue bit masks into the corresponding
630  * #GstVideoFormat.  
631  *
632  * Since: 0.10.16
633  *
634  * Returns: the #GstVideoFormat corresponding to the bit masks
635  */
636 static GstVideoFormat
637 gst_video_format_from_rgb32_masks (int red_mask, int green_mask, int blue_mask)
638 {
639   if (red_mask == 0xff000000 && green_mask == 0x00ff0000 &&
640       blue_mask == 0x0000ff00) {
641     return GST_VIDEO_FORMAT_RGBx;
642   }
643   if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 &&
644       blue_mask == 0xff000000) {
645     return GST_VIDEO_FORMAT_BGRx;
646   }
647   if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 &&
648       blue_mask == 0x000000ff) {
649     return GST_VIDEO_FORMAT_xRGB;
650   }
651   if (red_mask == 0x000000ff && green_mask == 0x0000ff00 &&
652       blue_mask == 0x00ff0000) {
653     return GST_VIDEO_FORMAT_xBGR;
654   }
655
656   return GST_VIDEO_FORMAT_UNKNOWN;
657 }
658
659 static GstVideoFormat
660 gst_video_format_from_rgba32_masks (int red_mask, int green_mask, int blue_mask,
661     int alpha_mask)
662 {
663   if (red_mask == 0xff000000 && green_mask == 0x00ff0000 &&
664       blue_mask == 0x0000ff00 && alpha_mask == 0x000000ff) {
665     return GST_VIDEO_FORMAT_RGBA;
666   }
667   if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 &&
668       blue_mask == 0xff000000 && alpha_mask == 0x000000ff) {
669     return GST_VIDEO_FORMAT_BGRA;
670   }
671   if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 &&
672       blue_mask == 0x000000ff && alpha_mask == 0xff000000) {
673     return GST_VIDEO_FORMAT_ARGB;
674   }
675   if (red_mask == 0x000000ff && green_mask == 0x0000ff00 &&
676       blue_mask == 0x00ff0000 && alpha_mask == 0xff000000) {
677     return GST_VIDEO_FORMAT_ABGR;
678   }
679
680   return GST_VIDEO_FORMAT_UNKNOWN;
681 }
682
683 static GstVideoFormat
684 gst_video_format_from_rgb24_masks (int red_mask, int green_mask, int blue_mask)
685 {
686   if (red_mask == 0xff0000 && green_mask == 0x00ff00 && blue_mask == 0x0000ff) {
687     return GST_VIDEO_FORMAT_RGB;
688   }
689   if (red_mask == 0x0000ff && green_mask == 0x00ff00 && blue_mask == 0xff0000) {
690     return GST_VIDEO_FORMAT_BGR;
691   }
692
693   return GST_VIDEO_FORMAT_UNKNOWN;
694 }
695
696 /**
697  * gst_video_format_is_rgb:
698  * @format: a #GstVideoFormat
699  *
700  * Determine whether the video format is an RGB format.
701  *
702  * Since: 0.10.16
703  *
704  * Returns: TRUE if @format represents RGB video
705  */
706 gboolean
707 gst_video_format_is_rgb (GstVideoFormat format)
708 {
709   switch (format) {
710     case GST_VIDEO_FORMAT_I420:
711     case GST_VIDEO_FORMAT_YV12:
712     case GST_VIDEO_FORMAT_YUY2:
713     case GST_VIDEO_FORMAT_UYVY:
714     case GST_VIDEO_FORMAT_AYUV:
715     case GST_VIDEO_FORMAT_Y41B:
716     case GST_VIDEO_FORMAT_Y42B:
717       return FALSE;
718     case GST_VIDEO_FORMAT_RGBx:
719     case GST_VIDEO_FORMAT_BGRx:
720     case GST_VIDEO_FORMAT_xRGB:
721     case GST_VIDEO_FORMAT_xBGR:
722     case GST_VIDEO_FORMAT_RGBA:
723     case GST_VIDEO_FORMAT_BGRA:
724     case GST_VIDEO_FORMAT_ARGB:
725     case GST_VIDEO_FORMAT_ABGR:
726     case GST_VIDEO_FORMAT_RGB:
727     case GST_VIDEO_FORMAT_BGR:
728       return TRUE;
729     default:
730       return FALSE;
731   }
732 }
733
734 /**
735  * gst_video_format_is_yuv:
736  * @format: a #GstVideoFormat
737  *
738  * Determine whether the video format is a YUV format.
739  *
740  * Since: 0.10.16
741  *
742  * Returns: TRUE if @format represents YUV video
743  */
744 gboolean
745 gst_video_format_is_yuv (GstVideoFormat format)
746 {
747   switch (format) {
748     case GST_VIDEO_FORMAT_I420:
749     case GST_VIDEO_FORMAT_YV12:
750     case GST_VIDEO_FORMAT_YUY2:
751     case GST_VIDEO_FORMAT_UYVY:
752     case GST_VIDEO_FORMAT_AYUV:
753     case GST_VIDEO_FORMAT_Y41B:
754     case GST_VIDEO_FORMAT_Y42B:
755       return TRUE;
756     case GST_VIDEO_FORMAT_RGBx:
757     case GST_VIDEO_FORMAT_BGRx:
758     case GST_VIDEO_FORMAT_xRGB:
759     case GST_VIDEO_FORMAT_xBGR:
760     case GST_VIDEO_FORMAT_RGBA:
761     case GST_VIDEO_FORMAT_BGRA:
762     case GST_VIDEO_FORMAT_ARGB:
763     case GST_VIDEO_FORMAT_ABGR:
764     case GST_VIDEO_FORMAT_RGB:
765     case GST_VIDEO_FORMAT_BGR:
766       return FALSE;
767     default:
768       return FALSE;
769   }
770 }
771
772 /**
773  * gst_video_format_has_alpha:
774  * @format: a #GstVideoFormat
775  * 
776  * Returns TRUE or FALSE depending on if the video format provides an
777  * alpha channel.
778  *
779  * Since: 0.10.16
780  *
781  * Returns: TRUE if @format has an alpha channel
782  */
783 gboolean
784 gst_video_format_has_alpha (GstVideoFormat format)
785 {
786   switch (format) {
787     case GST_VIDEO_FORMAT_I420:
788     case GST_VIDEO_FORMAT_YV12:
789     case GST_VIDEO_FORMAT_YUY2:
790     case GST_VIDEO_FORMAT_UYVY:
791     case GST_VIDEO_FORMAT_Y41B:
792     case GST_VIDEO_FORMAT_Y42B:
793       return FALSE;
794     case GST_VIDEO_FORMAT_AYUV:
795     case GST_VIDEO_FORMAT_RGBA:
796     case GST_VIDEO_FORMAT_BGRA:
797     case GST_VIDEO_FORMAT_ARGB:
798     case GST_VIDEO_FORMAT_ABGR:
799       return TRUE;
800     case GST_VIDEO_FORMAT_RGBx:
801     case GST_VIDEO_FORMAT_BGRx:
802     case GST_VIDEO_FORMAT_xRGB:
803     case GST_VIDEO_FORMAT_xBGR:
804     case GST_VIDEO_FORMAT_RGB:
805     case GST_VIDEO_FORMAT_BGR:
806       return FALSE;
807     default:
808       return FALSE;
809   }
810 }
811
812 /**
813  * gst_video_format_get_row_stride:
814  * @format: a #GstVideoFormat
815  * @component: the component index
816  * @width: the width of video
817  *
818  * Calculates the row stride (number of bytes from one row of pixels to
819  * the next) for the video component with an index of @component.  For
820  * YUV video, Y, U, and V have component indices of 0, 1, and 2,
821  * respectively.  For RGB video, R, G, and B have component indicies of
822  * 0, 1, and 2, respectively.  Alpha channels, if present, have a component
823  * index of 3.  The @width parameter always represents the width of the
824  * video, not the component.
825  *
826  * Since: 0.10.16
827  *
828  * Returns: row stride of component @component
829  */
830 int
831 gst_video_format_get_row_stride (GstVideoFormat format, int component,
832     int width)
833 {
834   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
835   g_return_val_if_fail (component >= 0 && component <= 3, 0);
836   g_return_val_if_fail (width > 0, 0);
837
838   switch (format) {
839     case GST_VIDEO_FORMAT_I420:
840     case GST_VIDEO_FORMAT_YV12:
841       if (component == 0) {
842         return GST_ROUND_UP_4 (width);
843       } else {
844         return GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
845       }
846     case GST_VIDEO_FORMAT_YUY2:
847     case GST_VIDEO_FORMAT_UYVY:
848       return GST_ROUND_UP_4 (width * 2);
849     case GST_VIDEO_FORMAT_AYUV:
850     case GST_VIDEO_FORMAT_RGBx:
851     case GST_VIDEO_FORMAT_BGRx:
852     case GST_VIDEO_FORMAT_xRGB:
853     case GST_VIDEO_FORMAT_xBGR:
854     case GST_VIDEO_FORMAT_RGBA:
855     case GST_VIDEO_FORMAT_BGRA:
856     case GST_VIDEO_FORMAT_ARGB:
857     case GST_VIDEO_FORMAT_ABGR:
858       return width * 4;
859     case GST_VIDEO_FORMAT_RGB:
860     case GST_VIDEO_FORMAT_BGR:
861       return GST_ROUND_UP_4 (width * 3);
862     case GST_VIDEO_FORMAT_Y41B:
863       if (component == 0) {
864         return GST_ROUND_UP_4 (width);
865       } else {
866         return GST_ROUND_UP_8 (width) / 4;
867       }
868     case GST_VIDEO_FORMAT_Y42B:
869       if (component == 0) {
870         return GST_ROUND_UP_4 (width);
871       } else {
872         return GST_ROUND_UP_8 (width) / 2;
873       }
874     default:
875       return 0;
876   }
877 }
878
879 /**
880  * gst_video_format_get_pixel_stride:
881  * @format: a #GstVideoFormat
882  * @component: the component index
883  *
884  * Calculates the pixel stride (number of bytes from one pixel to the
885  * pixel to its immediate left) for the video component with an index
886  * of @component.  See @gst_video_format_get_row_stride for a description
887  * of the component index.
888  *
889  * Since: 0.10.16
890  *
891  * Returns: pixel stride of component @component
892  */
893 int
894 gst_video_format_get_pixel_stride (GstVideoFormat format, int component)
895 {
896   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
897   g_return_val_if_fail (component >= 0 && component <= 3, 0);
898
899   switch (format) {
900     case GST_VIDEO_FORMAT_I420:
901     case GST_VIDEO_FORMAT_YV12:
902     case GST_VIDEO_FORMAT_Y41B:
903     case GST_VIDEO_FORMAT_Y42B:
904       return 1;
905     case GST_VIDEO_FORMAT_YUY2:
906     case GST_VIDEO_FORMAT_UYVY:
907       if (component == 0) {
908         return 2;
909       } else {
910         return 4;
911       }
912     case GST_VIDEO_FORMAT_AYUV:
913     case GST_VIDEO_FORMAT_RGBx:
914     case GST_VIDEO_FORMAT_BGRx:
915     case GST_VIDEO_FORMAT_xRGB:
916     case GST_VIDEO_FORMAT_xBGR:
917     case GST_VIDEO_FORMAT_RGBA:
918     case GST_VIDEO_FORMAT_BGRA:
919     case GST_VIDEO_FORMAT_ARGB:
920     case GST_VIDEO_FORMAT_ABGR:
921       return 4;
922     case GST_VIDEO_FORMAT_RGB:
923     case GST_VIDEO_FORMAT_BGR:
924       return 3;
925     default:
926       return 0;
927   }
928 }
929
930 /**
931  * gst_video_format_get_component_width:
932  * @format: a #GstVideoFormat
933  * @component: the component index
934  * @width: the width of video
935  *
936  * Calculates the width of the component.  See
937  * @gst_video_format_get_row_stride for a description
938  * of the component index.
939  *
940  * Since: 0.10.16
941  *
942  * Returns: width of component @component
943  */
944 int
945 gst_video_format_get_component_width (GstVideoFormat format, int component,
946     int width)
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   g_return_val_if_fail (width > 0, 0);
951
952   switch (format) {
953     case GST_VIDEO_FORMAT_I420:
954     case GST_VIDEO_FORMAT_YV12:
955     case GST_VIDEO_FORMAT_YUY2:
956     case GST_VIDEO_FORMAT_UYVY:
957       if (component == 0) {
958         return width;
959       } else {
960         return GST_ROUND_UP_2 (width) / 2;
961       }
962     case GST_VIDEO_FORMAT_Y41B:        /* CHECKME: component_width for Y41B */
963       if (component == 0) {
964         return width;
965       } else {
966         return GST_ROUND_UP_8 (width) / 4;
967       }
968     case GST_VIDEO_FORMAT_Y42B:        /* CHECKME: component_width for Y42B */
969       if (component == 0) {
970         return width;
971       } else {
972         return GST_ROUND_UP_8 (width) / 2;
973       }
974     case GST_VIDEO_FORMAT_AYUV:
975     case GST_VIDEO_FORMAT_RGBx:
976     case GST_VIDEO_FORMAT_BGRx:
977     case GST_VIDEO_FORMAT_xRGB:
978     case GST_VIDEO_FORMAT_xBGR:
979     case GST_VIDEO_FORMAT_RGBA:
980     case GST_VIDEO_FORMAT_BGRA:
981     case GST_VIDEO_FORMAT_ARGB:
982     case GST_VIDEO_FORMAT_ABGR:
983     case GST_VIDEO_FORMAT_RGB:
984     case GST_VIDEO_FORMAT_BGR:
985       return width;
986     default:
987       return 0;
988   }
989 }
990
991 /**
992  * gst_video_format_get_component_height:
993  * @format: a #GstVideoFormat
994  * @component: the component index
995  * @height: the height of video
996  *
997  * Calculates the height of the component.  See
998  * @gst_video_format_get_row_stride for a description
999  * of the component index.
1000  *
1001  * Since: 0.10.16
1002  *
1003  * Returns: height of component @component
1004  */
1005 int
1006 gst_video_format_get_component_height (GstVideoFormat format, int component,
1007     int height)
1008 {
1009   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1010   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1011   g_return_val_if_fail (height > 0, 0);
1012
1013   switch (format) {
1014     case GST_VIDEO_FORMAT_I420:
1015     case GST_VIDEO_FORMAT_YV12:
1016       if (component == 0) {
1017         return height;
1018       } else {
1019         return GST_ROUND_UP_2 (height) / 2;
1020       }
1021     case GST_VIDEO_FORMAT_Y41B:
1022     case GST_VIDEO_FORMAT_Y42B:
1023     case GST_VIDEO_FORMAT_YUY2:
1024     case GST_VIDEO_FORMAT_UYVY:
1025     case GST_VIDEO_FORMAT_AYUV:
1026     case GST_VIDEO_FORMAT_RGBx:
1027     case GST_VIDEO_FORMAT_BGRx:
1028     case GST_VIDEO_FORMAT_xRGB:
1029     case GST_VIDEO_FORMAT_xBGR:
1030     case GST_VIDEO_FORMAT_RGBA:
1031     case GST_VIDEO_FORMAT_BGRA:
1032     case GST_VIDEO_FORMAT_ARGB:
1033     case GST_VIDEO_FORMAT_ABGR:
1034     case GST_VIDEO_FORMAT_RGB:
1035     case GST_VIDEO_FORMAT_BGR:
1036       return height;
1037     default:
1038       return 0;
1039   }
1040 }
1041
1042 /**
1043  * gst_video_format_get_component_offset:
1044  * @format: a #GstVideoFormat
1045  * @component: the component index
1046  * @width: the width of video
1047  * @height: the height of video
1048  *
1049  * Calculates the offset (in bytes) of the first pixel of the component
1050  * with index @component.  For packed formats, this will typically be a
1051  * small integer (0, 1, 2, 3).  For planar formats, this will be a
1052  * (relatively) large offset to the beginning of the second or third
1053  * component planes.  See @gst_video_format_get_row_stride for a description
1054  * of the component index.
1055  *
1056  * Since: 0.10.16
1057  *
1058  * Returns: offset of component @component
1059  */
1060 int
1061 gst_video_format_get_component_offset (GstVideoFormat format, int component,
1062     int width, int height)
1063 {
1064   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1065   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1066   g_return_val_if_fail (width > 0 && height > 0, 0);
1067
1068   switch (format) {
1069     case GST_VIDEO_FORMAT_I420:
1070       if (component == 0)
1071         return 0;
1072       if (component == 1)
1073         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1074       if (component == 2) {
1075         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) +
1076             GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1077             (GST_ROUND_UP_2 (height) / 2);
1078       }
1079       return 0;
1080     case GST_VIDEO_FORMAT_YV12:        /* same as I420, but components 1+2 swapped */
1081       if (component == 0)
1082         return 0;
1083       if (component == 2)
1084         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1085       if (component == 1) {
1086         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) +
1087             GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1088             (GST_ROUND_UP_2 (height) / 2);
1089       }
1090       return 0;
1091     case GST_VIDEO_FORMAT_YUY2:
1092       if (component == 0)
1093         return 0;
1094       if (component == 1)
1095         return 1;
1096       if (component == 2)
1097         return 3;
1098       return 0;
1099     case GST_VIDEO_FORMAT_UYVY:
1100       if (component == 0)
1101         return 1;
1102       if (component == 1)
1103         return 0;
1104       if (component == 2)
1105         return 2;
1106       return 0;
1107     case GST_VIDEO_FORMAT_AYUV:
1108       if (component == 0)
1109         return 1;
1110       if (component == 1)
1111         return 2;
1112       if (component == 2)
1113         return 3;
1114       if (component == 3)
1115         return 0;
1116       return 0;
1117     case GST_VIDEO_FORMAT_RGBx:
1118     case GST_VIDEO_FORMAT_RGBA:
1119       if (component == 0)
1120         return 0;
1121       if (component == 1)
1122         return 1;
1123       if (component == 2)
1124         return 2;
1125       if (component == 3)
1126         return 3;
1127       return 0;
1128     case GST_VIDEO_FORMAT_BGRx:
1129     case GST_VIDEO_FORMAT_BGRA:
1130       if (component == 0)
1131         return 2;
1132       if (component == 1)
1133         return 1;
1134       if (component == 2)
1135         return 0;
1136       if (component == 3)
1137         return 3;
1138       return 0;
1139     case GST_VIDEO_FORMAT_xRGB:
1140     case GST_VIDEO_FORMAT_ARGB:
1141       if (component == 0)
1142         return 1;
1143       if (component == 1)
1144         return 2;
1145       if (component == 2)
1146         return 3;
1147       if (component == 3)
1148         return 0;
1149       return 0;
1150     case GST_VIDEO_FORMAT_xBGR:
1151     case GST_VIDEO_FORMAT_ABGR:
1152       if (component == 0)
1153         return 3;
1154       if (component == 1)
1155         return 2;
1156       if (component == 2)
1157         return 1;
1158       if (component == 3)
1159         return 0;
1160       return 0;
1161     case GST_VIDEO_FORMAT_RGB:
1162       if (component == 0)
1163         return 0;
1164       if (component == 1)
1165         return 1;
1166       if (component == 2)
1167         return 2;
1168       return 0;
1169     case GST_VIDEO_FORMAT_BGR:
1170       if (component == 0)
1171         return 2;
1172       if (component == 1)
1173         return 1;
1174       if (component == 2)
1175         return 0;
1176       return 0;
1177     case GST_VIDEO_FORMAT_Y41B:
1178       if (component == 0)
1179         return 0;
1180       if (component == 1)
1181         return GST_ROUND_UP_4 (width) * height;
1182       if (component == 2)
1183         return (GST_ROUND_UP_4 (width) + (GST_ROUND_UP_8 (width) / 4)) * height;
1184       return 0;
1185     case GST_VIDEO_FORMAT_Y42B:
1186       if (component == 0)
1187         return 0;
1188       if (component == 1)
1189         return GST_ROUND_UP_4 (width) * height;
1190       if (component == 2)
1191         return (GST_ROUND_UP_4 (width) + (GST_ROUND_UP_8 (width) / 2)) * height;
1192       return 0;
1193     default:
1194       return 0;
1195   }
1196 }
1197
1198 /**
1199  * gst_video_format_get_size:
1200  * @format: a #GstVideoFormat
1201  * @width: the width of video
1202  * @height: the height of video
1203  *
1204  * Calculates the total number of bytes in the raw video format.  This
1205  * number should be used when allocating a buffer for raw video.
1206  *
1207  * Since: 0.10.16
1208  *
1209  * Returns: size (in bytes) of raw video format
1210  */
1211 int
1212 gst_video_format_get_size (GstVideoFormat format, int width, int height)
1213 {
1214   int size;
1215
1216   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1217   g_return_val_if_fail (width > 0 && height > 0, 0);
1218
1219   switch (format) {
1220     case GST_VIDEO_FORMAT_I420:
1221     case GST_VIDEO_FORMAT_YV12:
1222       size = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1223       size += GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1224           (GST_ROUND_UP_2 (height) / 2) * 2;
1225       return size;
1226     case GST_VIDEO_FORMAT_YUY2:
1227     case GST_VIDEO_FORMAT_UYVY:
1228       return GST_ROUND_UP_4 (width * 2) * height;
1229     case GST_VIDEO_FORMAT_AYUV:
1230     case GST_VIDEO_FORMAT_RGBx:
1231     case GST_VIDEO_FORMAT_BGRx:
1232     case GST_VIDEO_FORMAT_xRGB:
1233     case GST_VIDEO_FORMAT_xBGR:
1234     case GST_VIDEO_FORMAT_RGBA:
1235     case GST_VIDEO_FORMAT_BGRA:
1236     case GST_VIDEO_FORMAT_ARGB:
1237     case GST_VIDEO_FORMAT_ABGR:
1238       return width * 4 * height;
1239     case GST_VIDEO_FORMAT_RGB:
1240     case GST_VIDEO_FORMAT_BGR:
1241       return GST_ROUND_UP_4 (width * 3) * height;
1242     case GST_VIDEO_FORMAT_Y41B:
1243       /* simplification of ROUNDUP4(w)*h + 2*((ROUNDUP8(w)/4)*h */
1244       return (GST_ROUND_UP_4 (width) + (GST_ROUND_UP_8 (width) / 2)) * height;
1245     case GST_VIDEO_FORMAT_Y42B:
1246       /* simplification of ROUNDUP4(w)*h + 2*(ROUNDUP8(w)/2)*h: */
1247       return (GST_ROUND_UP_4 (width) + GST_ROUND_UP_8 (width)) * height;
1248     default:
1249       return 0;
1250   }
1251 }
1252
1253 /**
1254  * gst_video_format_convert:
1255  * @format: a #GstVideoFormat
1256  * @width: the width of video
1257  * @height: the height of video
1258  * @fps_n: frame rate numerator
1259  * @fps_d: frame rate denominator
1260  * @src_format: #GstFormat of the @src_value
1261  * @src_value: value to convert
1262  * @dest_format: #GstFormat of the @dest_value
1263  * @dest_value: pointer to destination value
1264  *
1265  * Converts among various #GstFormat types.  This function handles
1266  * GST_FORMAT_BYTES, GST_FORMAT_TIME, and GST_FORMAT_DEFAULT.  For
1267  * raw video, GST_FORMAT_DEFAULT corresponds to video frames.  This
1268  * function can be to handle pad queries of the type GST_QUERY_CONVERT.
1269  *
1270  * Since: 0.10.16
1271  *
1272  * Returns: TRUE if the conversion was successful.
1273  */
1274 gboolean
1275 gst_video_format_convert (GstVideoFormat format, int width, int height,
1276     int fps_n, int fps_d,
1277     GstFormat src_format, gint64 src_value,
1278     GstFormat dest_format, gint64 * dest_value)
1279 {
1280   gboolean ret = FALSE;
1281   int size;
1282
1283   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1284   g_return_val_if_fail (width > 0 && height > 0, 0);
1285
1286   size = gst_video_format_get_size (format, width, height);
1287
1288   GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s to %s",
1289       src_value, gst_format_get_name (src_format),
1290       gst_format_get_name (dest_format));
1291
1292   if (src_format == dest_format) {
1293     *dest_value = src_value;
1294     ret = TRUE;
1295     goto done;
1296   }
1297
1298   if (src_value == -1) {
1299     *dest_value = -1;
1300     ret = TRUE;
1301     goto done;
1302   }
1303
1304   /* bytes to frames */
1305   if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_DEFAULT) {
1306     if (size != 0) {
1307       *dest_value = gst_util_uint64_scale_int (src_value, 1, size);
1308     } else {
1309       GST_ERROR ("blocksize is 0");
1310       *dest_value = 0;
1311     }
1312     ret = TRUE;
1313     goto done;
1314   }
1315
1316   /* frames to bytes */
1317   if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_BYTES) {
1318     *dest_value = gst_util_uint64_scale_int (src_value, size, 1);
1319     ret = TRUE;
1320     goto done;
1321   }
1322
1323   /* time to frames */
1324   if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_DEFAULT) {
1325     if (fps_d != 0) {
1326       *dest_value = gst_util_uint64_scale (src_value,
1327           fps_n, GST_SECOND * fps_d);
1328     } else {
1329       GST_ERROR ("framerate denominator is 0");
1330       *dest_value = 0;
1331     }
1332     ret = TRUE;
1333     goto done;
1334   }
1335
1336   /* frames to time */
1337   if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
1338     if (fps_n != 0) {
1339       *dest_value = gst_util_uint64_scale (src_value,
1340           GST_SECOND * fps_d, fps_n);
1341     } else {
1342       GST_ERROR ("framerate numerator is 0");
1343       *dest_value = 0;
1344     }
1345     ret = TRUE;
1346     goto done;
1347   }
1348
1349   /* time to bytes */
1350   if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) {
1351     if (fps_d != 0) {
1352       *dest_value = gst_util_uint64_scale (src_value,
1353           fps_n * size, GST_SECOND * fps_d);
1354     } else {
1355       GST_ERROR ("framerate denominator is 0");
1356       *dest_value = 0;
1357     }
1358     ret = TRUE;
1359     goto done;
1360   }
1361
1362   /* bytes to time */
1363   if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_TIME) {
1364     if (fps_n != 0 && size != 0) {
1365       *dest_value = gst_util_uint64_scale (src_value,
1366           GST_SECOND * fps_d, fps_n * size);
1367     } else {
1368       GST_ERROR ("framerate denominator and/or blocksize is 0");
1369       *dest_value = 0;
1370     }
1371     ret = TRUE;
1372   }
1373
1374 done:
1375
1376   GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, ret, *dest_value);
1377
1378   return ret;
1379 }