gst-libs/gst/video/video.c: Video format can also be conveniently determined from...
[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:
224  * @caps: the #GstCaps to parse
225  * @format: the #GstVideoFormat of the video represented by @caps (output)
226  * @width: the width of the video represented by @caps, may be NULL (output)
227  * @height: the height of the video represented by @caps, may be NULL (output)
228  *
229  * Determines the #GstVideoFormat of @caps and places it in the location
230  * pointed to by @format.  Extracts the size of the video and places it
231  * in the location pointed to by @width and @height.  If @caps does not
232  * represent one of the raw video formats listed in #GstVideoFormat, the
233  * function will fail and return FALSE.
234  *
235  * Since: 0.10.16
236  *
237  * Returns: TRUE if @caps was parsed correctly.
238  */
239 gboolean
240 gst_video_format_parse_caps (GstCaps * caps, GstVideoFormat * format,
241     int *width, int *height)
242 {
243   GstStructure *structure;
244   gboolean ok = TRUE;
245
246   /* caps must hold exactly 1 structure to be unambiguous,
247    * but need not be fixed to determine format */
248   if (gst_caps_get_size (caps) != 1)
249     return FALSE;
250
251   structure = gst_caps_get_structure (caps, 0);
252
253   if (format) {
254     if (gst_structure_has_name (structure, "video/x-raw-yuv")) {
255       guint32 fourcc;
256
257       ok &= gst_structure_get_fourcc (structure, "format", &fourcc);
258
259       *format = gst_video_format_from_fourcc (fourcc);
260       if (*format == GST_VIDEO_FORMAT_UNKNOWN) {
261         ok = FALSE;
262       }
263     } else if (gst_structure_has_name (structure, "video/x-raw-rgb")) {
264       int depth;
265       int bpp;
266       int endianness;
267       int red_mask;
268       int green_mask;
269       int blue_mask;
270       int alpha_mask;
271       gboolean have_alpha;
272
273       ok &= gst_structure_get_int (structure, "depth", &depth);
274       ok &= gst_structure_get_int (structure, "bpp", &bpp);
275       ok &= gst_structure_get_int (structure, "endianness", &endianness);
276       ok &= gst_structure_get_int (structure, "red_mask", &red_mask);
277       ok &= gst_structure_get_int (structure, "green_mask", &green_mask);
278       ok &= gst_structure_get_int (structure, "blue_mask", &blue_mask);
279       have_alpha = gst_structure_get_int (structure, "alpha_mask", &alpha_mask);
280
281       if (depth == 24 && bpp == 32 && endianness == G_BIG_ENDIAN) {
282         *format = gst_video_format_from_rgb32_masks (red_mask, green_mask,
283             blue_mask);
284         if (*format == GST_VIDEO_FORMAT_UNKNOWN) {
285           ok = FALSE;
286         }
287       } else if (depth == 32 && bpp == 32 && endianness == G_BIG_ENDIAN &&
288           have_alpha) {
289         *format = gst_video_format_from_rgba32_masks (red_mask, green_mask,
290             blue_mask, alpha_mask);
291         if (*format == GST_VIDEO_FORMAT_UNKNOWN) {
292           ok = FALSE;
293         }
294       } else if (depth == 24 && bpp == 24 && endianness == G_BIG_ENDIAN) {
295         *format = gst_video_format_from_rgb24_masks (red_mask, green_mask,
296             blue_mask);
297         if (*format == GST_VIDEO_FORMAT_UNKNOWN) {
298           ok = FALSE;
299         }
300       } else {
301         ok = FALSE;
302       }
303     } else {
304       ok = FALSE;
305     }
306   }
307
308   if (width) {
309     ok &= gst_structure_get_int (structure, "width", width);
310   }
311
312   if (height) {
313     ok &= gst_structure_get_int (structure, "height", height);
314   }
315
316   return ok;
317 }
318
319 /**
320  * gst_video_parse_caps_framerate:
321  * @caps: pointer to a #GstCaps instance
322  * @fps_n: pointer to integer to hold numerator of frame rate (output)
323  * @fps_d: pointer to integer to hold denominator of frame rate (output)
324  *
325  * Extracts the frame rate from @caps and places the values in the locations
326  * pointed to by @fps_n and @fps_d.  Returns TRUE if the values could be
327  * parsed correctly, FALSE if not.
328  *
329  * This function can be used with #GstCaps that have any media type; it
330  * is not limited to formats handled by #GstVideoFormat.
331  *
332  * Since: 0.10.16
333  *
334  * Returns: TRUE if @caps was parsed correctly.
335  */
336 gboolean
337 gst_video_parse_caps_framerate (GstCaps * caps, int *fps_n, int *fps_d)
338 {
339   GstStructure *structure;
340
341   if (!gst_caps_is_fixed (caps))
342     return FALSE;
343
344   structure = gst_caps_get_structure (caps, 0);
345
346   return gst_structure_get_fraction (structure, "framerate", fps_n, fps_d);
347 }
348
349 /**
350  * gst_video_parse_caps_pixel_aspect_ratio:
351  * @caps: pointer to a #GstCaps instance
352  * @par_n: pointer to numerator of pixel aspect ratio (output)
353  * @par_d: pointer to denominator of pixel aspect ratio (output)
354  *
355  * Extracts the pixel aspect ratio from @caps and places the values in
356  * the locations pointed to by @par_n and @par_d.  Returns TRUE if the
357  * values could be parsed correctly, FALSE if not.
358  *
359  * This function can be used with #GstCaps that have any media type; it
360  * is not limited to formats handled by #GstVideoFormat.
361  *
362  * Since: 0.10.16
363  *
364  * Returns: TRUE if @caps was parsed correctly.
365  */
366 gboolean
367 gst_video_parse_caps_pixel_aspect_ratio (GstCaps * caps, int *par_n, int *par_d)
368 {
369   GstStructure *structure;
370
371   if (!gst_caps_is_fixed (caps))
372     return FALSE;
373
374   structure = gst_caps_get_structure (caps, 0);
375
376   if (!gst_structure_get_fraction (structure, "pixel-aspect-ratio",
377           par_n, par_d)) {
378     *par_n = 1;
379     *par_d = 1;
380   }
381   return TRUE;
382 }
383
384 /**
385  * gst_video_format_new_caps:
386  * @format: the #GstVideoFormat describing the raw video format
387  * @width: width of video
388  * @height: height of video
389  * @framerate_n: numerator of frame rate
390  * @framerate_d: denominator of frame rate
391  * @par_n: numerator of pixel aspect ratio
392  * @par_d: denominator of pixel aspect ratio
393  *
394  * Creates a new #GstCaps object based on the parameters provided.
395  *
396  * Since: 0.10.16
397  *
398  * Returns: a new #GstCaps object, or NULL if there was an error
399  */
400 GstCaps *
401 gst_video_format_new_caps (GstVideoFormat format, int width, int height,
402     int framerate_n, int framerate_d, int par_n, int par_d)
403 {
404   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
405   g_return_val_if_fail (width > 0 && height > 0, NULL);
406
407   if (gst_video_format_is_yuv (format)) {
408     return gst_caps_new_simple ("video/x-raw-yuv",
409         "format", GST_TYPE_FOURCC, gst_video_format_to_fourcc (format),
410         "width", G_TYPE_INT, width,
411         "height", G_TYPE_INT, height,
412         "framerate", GST_TYPE_FRACTION, framerate_n, framerate_d,
413         "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, NULL);
414   }
415   if (gst_video_format_is_rgb (format)) {
416     GstCaps *caps;
417     int red_mask;
418     int blue_mask;
419     int green_mask;
420     int alpha_mask;
421     int depth;
422     int bpp;
423     gboolean have_alpha;
424     unsigned int mask;
425
426     switch (format) {
427       case GST_VIDEO_FORMAT_RGBx:
428       case GST_VIDEO_FORMAT_BGRx:
429       case GST_VIDEO_FORMAT_xRGB:
430       case GST_VIDEO_FORMAT_xBGR:
431         bpp = 32;
432         depth = 24;
433         have_alpha = FALSE;
434         break;
435       case GST_VIDEO_FORMAT_RGBA:
436       case GST_VIDEO_FORMAT_BGRA:
437       case GST_VIDEO_FORMAT_ARGB:
438       case GST_VIDEO_FORMAT_ABGR:
439         bpp = 32;
440         depth = 32;
441         have_alpha = TRUE;
442         break;
443       case GST_VIDEO_FORMAT_RGB:
444       case GST_VIDEO_FORMAT_BGR:
445         bpp = 24;
446         depth = 24;
447         have_alpha = FALSE;
448         break;
449       default:
450         return NULL;
451     }
452     if (bpp == 32) {
453       mask = 0xff000000;
454     } else {
455       mask = 0xff0000;
456     }
457     red_mask =
458         mask >> (8 * gst_video_format_get_component_offset (format, 0, width,
459             height));
460     green_mask =
461         mask >> (8 * gst_video_format_get_component_offset (format, 1, width,
462             height));
463     blue_mask =
464         mask >> (8 * gst_video_format_get_component_offset (format, 2, width,
465             height));
466
467     caps = gst_caps_new_simple ("video/x-raw-rgb",
468         "bpp", G_TYPE_INT, bpp,
469         "depth", G_TYPE_INT, depth,
470         "endianness", G_TYPE_INT, G_BIG_ENDIAN,
471         "red_mask", G_TYPE_INT, red_mask,
472         "green_mask", G_TYPE_INT, green_mask,
473         "blue_mask", G_TYPE_INT, blue_mask,
474         "width", G_TYPE_INT, width,
475         "height", G_TYPE_INT, height,
476         "framerate", GST_TYPE_FRACTION, framerate_n, framerate_d,
477         "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, NULL);
478     if (have_alpha) {
479       alpha_mask =
480           mask >> (8 * gst_video_format_get_component_offset (format, 3, width,
481               height));
482       gst_caps_set_simple (caps, "alpha_mask", G_TYPE_INT, alpha_mask, NULL);
483     }
484     return caps;
485   }
486   return NULL;
487 }
488
489 /**
490  * gst_video_format_from_fourcc:
491  * @fourcc: a FOURCC value representing raw YUV video
492  *
493  * Converts a FOURCC value into the corresponding #GstVideoFormat.
494  * If the FOURCC cannot be represented by #GstVideoFormat,
495  * #GST_VIDEO_FORMAT_UNKNOWN is returned.
496  *
497  * Since: 0.10.16
498  *
499  * Returns: the #GstVideoFormat describing the FOURCC value
500  */
501 GstVideoFormat
502 gst_video_format_from_fourcc (guint32 fourcc)
503 {
504   switch (fourcc) {
505     case GST_MAKE_FOURCC ('I', '4', '2', '0'):
506       return GST_VIDEO_FORMAT_I420;
507     case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
508       return GST_VIDEO_FORMAT_YV12;
509     case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
510       return GST_VIDEO_FORMAT_YUY2;
511     case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
512       return GST_VIDEO_FORMAT_UYVY;
513     case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'):
514       return GST_VIDEO_FORMAT_AYUV;
515     case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
516       return GST_VIDEO_FORMAT_Y41B;
517     case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
518       return GST_VIDEO_FORMAT_Y42B;
519     default:
520       return GST_VIDEO_FORMAT_UNKNOWN;
521   }
522 }
523
524 /**
525  * gst_video_format_to_fourcc:
526  * @format: a #GstVideoFormat video format
527  *
528  * Converts a #GstVideoFormat value into the corresponding FOURCC.  Only
529  * a few YUV formats have corresponding FOURCC values.  If @format has
530  * no corresponding FOURCC value, 0 is returned.
531  *
532  * Since: 0.10.16
533  *
534  * Returns: the FOURCC corresponding to @format
535  */
536 guint32
537 gst_video_format_to_fourcc (GstVideoFormat format)
538 {
539   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
540
541   switch (format) {
542     case GST_VIDEO_FORMAT_I420:
543       return GST_MAKE_FOURCC ('I', '4', '2', '0');
544     case GST_VIDEO_FORMAT_YV12:
545       return GST_MAKE_FOURCC ('Y', 'V', '1', '2');
546     case GST_VIDEO_FORMAT_YUY2:
547       return GST_MAKE_FOURCC ('Y', 'U', 'Y', '2');
548     case GST_VIDEO_FORMAT_UYVY:
549       return GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y');
550     case GST_VIDEO_FORMAT_AYUV:
551       return GST_MAKE_FOURCC ('A', 'Y', 'U', 'V');
552     case GST_VIDEO_FORMAT_Y41B:
553       return GST_MAKE_FOURCC ('Y', '4', '1', 'B');
554     case GST_VIDEO_FORMAT_Y42B:
555       return GST_MAKE_FOURCC ('Y', '4', '2', 'B');
556     default:
557       return 0;
558   }
559 }
560
561 /*
562  * gst_video_format_from_rgb32_masks:
563  * @red_mask: red bit mask
564  * @green_mask: green bit mask
565  * @blue_mask: blue bit mask
566  *
567  * Converts red, green, blue bit masks into the corresponding
568  * #GstVideoFormat.  
569  *
570  * Since: 0.10.16
571  *
572  * Returns: the #GstVideoFormat corresponding to the bit masks
573  */
574 static GstVideoFormat
575 gst_video_format_from_rgb32_masks (int red_mask, int green_mask, int blue_mask)
576 {
577   if (red_mask == 0xff000000 && green_mask == 0x00ff0000 &&
578       blue_mask == 0x0000ff00) {
579     return GST_VIDEO_FORMAT_RGBx;
580   }
581   if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 &&
582       blue_mask == 0xff000000) {
583     return GST_VIDEO_FORMAT_BGRx;
584   }
585   if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 &&
586       blue_mask == 0x000000ff) {
587     return GST_VIDEO_FORMAT_xRGB;
588   }
589   if (red_mask == 0x000000ff && green_mask == 0x0000ff00 &&
590       blue_mask == 0x00ff0000) {
591     return GST_VIDEO_FORMAT_xBGR;
592   }
593
594   return GST_VIDEO_FORMAT_UNKNOWN;
595 }
596
597 static GstVideoFormat
598 gst_video_format_from_rgba32_masks (int red_mask, int green_mask, int blue_mask,
599     int alpha_mask)
600 {
601   if (red_mask == 0xff000000 && green_mask == 0x00ff0000 &&
602       blue_mask == 0x0000ff00 && alpha_mask == 0x000000ff) {
603     return GST_VIDEO_FORMAT_RGBA;
604   }
605   if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 &&
606       blue_mask == 0xff000000 && alpha_mask == 0x000000ff) {
607     return GST_VIDEO_FORMAT_BGRA;
608   }
609   if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 &&
610       blue_mask == 0x000000ff && alpha_mask == 0xff000000) {
611     return GST_VIDEO_FORMAT_ARGB;
612   }
613   if (red_mask == 0x000000ff && green_mask == 0x0000ff00 &&
614       blue_mask == 0x00ff0000 && alpha_mask == 0xff000000) {
615     return GST_VIDEO_FORMAT_ABGR;
616   }
617
618   return GST_VIDEO_FORMAT_UNKNOWN;
619 }
620
621 static GstVideoFormat
622 gst_video_format_from_rgb24_masks (int red_mask, int green_mask, int blue_mask)
623 {
624   if (red_mask == 0xff0000 && green_mask == 0x00ff00 && blue_mask == 0x0000ff) {
625     return GST_VIDEO_FORMAT_RGB;
626   }
627   if (red_mask == 0x0000ff && green_mask == 0x00ff00 && blue_mask == 0xff0000) {
628     return GST_VIDEO_FORMAT_BGR;
629   }
630
631   return GST_VIDEO_FORMAT_UNKNOWN;
632 }
633
634 /**
635  * gst_video_format_is_rgb:
636  * @format: a #GstVideoFormat
637  *
638  * Determine whether the video format is an RGB format.
639  *
640  * Since: 0.10.16
641  *
642  * Returns: TRUE if @format represents RGB video
643  */
644 gboolean
645 gst_video_format_is_rgb (GstVideoFormat format)
646 {
647   switch (format) {
648     case GST_VIDEO_FORMAT_I420:
649     case GST_VIDEO_FORMAT_YV12:
650     case GST_VIDEO_FORMAT_YUY2:
651     case GST_VIDEO_FORMAT_UYVY:
652     case GST_VIDEO_FORMAT_AYUV:
653     case GST_VIDEO_FORMAT_Y41B:
654     case GST_VIDEO_FORMAT_Y42B:
655       return FALSE;
656     case GST_VIDEO_FORMAT_RGBx:
657     case GST_VIDEO_FORMAT_BGRx:
658     case GST_VIDEO_FORMAT_xRGB:
659     case GST_VIDEO_FORMAT_xBGR:
660     case GST_VIDEO_FORMAT_RGBA:
661     case GST_VIDEO_FORMAT_BGRA:
662     case GST_VIDEO_FORMAT_ARGB:
663     case GST_VIDEO_FORMAT_ABGR:
664     case GST_VIDEO_FORMAT_RGB:
665     case GST_VIDEO_FORMAT_BGR:
666       return TRUE;
667     default:
668       return FALSE;
669   }
670 }
671
672 /**
673  * gst_video_format_is_yuv:
674  * @format: a #GstVideoFormat
675  *
676  * Determine whether the video format is a YUV format.
677  *
678  * Since: 0.10.16
679  *
680  * Returns: TRUE if @format represents YUV video
681  */
682 gboolean
683 gst_video_format_is_yuv (GstVideoFormat format)
684 {
685   switch (format) {
686     case GST_VIDEO_FORMAT_I420:
687     case GST_VIDEO_FORMAT_YV12:
688     case GST_VIDEO_FORMAT_YUY2:
689     case GST_VIDEO_FORMAT_UYVY:
690     case GST_VIDEO_FORMAT_AYUV:
691     case GST_VIDEO_FORMAT_Y41B:
692     case GST_VIDEO_FORMAT_Y42B:
693       return TRUE;
694     case GST_VIDEO_FORMAT_RGBx:
695     case GST_VIDEO_FORMAT_BGRx:
696     case GST_VIDEO_FORMAT_xRGB:
697     case GST_VIDEO_FORMAT_xBGR:
698     case GST_VIDEO_FORMAT_RGBA:
699     case GST_VIDEO_FORMAT_BGRA:
700     case GST_VIDEO_FORMAT_ARGB:
701     case GST_VIDEO_FORMAT_ABGR:
702     case GST_VIDEO_FORMAT_RGB:
703     case GST_VIDEO_FORMAT_BGR:
704       return FALSE;
705     default:
706       return FALSE;
707   }
708 }
709
710 /**
711  * gst_video_format_has_alpha:
712  * @format: a #GstVideoFormat
713  * 
714  * Returns TRUE or FALSE depending on if the video format provides an
715  * alpha channel.
716  *
717  * Since: 0.10.16
718  *
719  * Returns: TRUE if @format has an alpha channel
720  */
721 gboolean
722 gst_video_format_has_alpha (GstVideoFormat format)
723 {
724   switch (format) {
725     case GST_VIDEO_FORMAT_I420:
726     case GST_VIDEO_FORMAT_YV12:
727     case GST_VIDEO_FORMAT_YUY2:
728     case GST_VIDEO_FORMAT_UYVY:
729     case GST_VIDEO_FORMAT_Y41B:
730     case GST_VIDEO_FORMAT_Y42B:
731       return FALSE;
732     case GST_VIDEO_FORMAT_AYUV:
733     case GST_VIDEO_FORMAT_RGBA:
734     case GST_VIDEO_FORMAT_BGRA:
735     case GST_VIDEO_FORMAT_ARGB:
736     case GST_VIDEO_FORMAT_ABGR:
737       return TRUE;
738     case GST_VIDEO_FORMAT_RGBx:
739     case GST_VIDEO_FORMAT_BGRx:
740     case GST_VIDEO_FORMAT_xRGB:
741     case GST_VIDEO_FORMAT_xBGR:
742     case GST_VIDEO_FORMAT_RGB:
743     case GST_VIDEO_FORMAT_BGR:
744       return FALSE;
745     default:
746       return FALSE;
747   }
748 }
749
750 /**
751  * gst_video_format_get_row_stride:
752  * @format: a #GstVideoFormat
753  * @component: the component index
754  * @width: the width of video
755  *
756  * Calculates the row stride (number of bytes from one row of pixels to
757  * the next) for the video component with an index of @component.  For
758  * YUV video, Y, U, and V have component indices of 0, 1, and 2,
759  * respectively.  For RGB video, R, G, and B have component indicies of
760  * 0, 1, and 2, respectively.  Alpha channels, if present, have a component
761  * index of 3.  The @width parameter always represents the width of the
762  * video, not the component.
763  *
764  * Since: 0.10.16
765  *
766  * Returns: row stride of component @component
767  */
768 int
769 gst_video_format_get_row_stride (GstVideoFormat format, int component,
770     int width)
771 {
772   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
773   g_return_val_if_fail (component >= 0 && component <= 3, 0);
774   g_return_val_if_fail (width > 0, 0);
775
776   switch (format) {
777     case GST_VIDEO_FORMAT_I420:
778     case GST_VIDEO_FORMAT_YV12:
779       if (component == 0) {
780         return GST_ROUND_UP_4 (width);
781       } else {
782         return GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
783       }
784     case GST_VIDEO_FORMAT_YUY2:
785     case GST_VIDEO_FORMAT_UYVY:
786       return GST_ROUND_UP_4 (width * 2);
787     case GST_VIDEO_FORMAT_AYUV:
788     case GST_VIDEO_FORMAT_RGBx:
789     case GST_VIDEO_FORMAT_BGRx:
790     case GST_VIDEO_FORMAT_xRGB:
791     case GST_VIDEO_FORMAT_xBGR:
792     case GST_VIDEO_FORMAT_RGBA:
793     case GST_VIDEO_FORMAT_BGRA:
794     case GST_VIDEO_FORMAT_ARGB:
795     case GST_VIDEO_FORMAT_ABGR:
796       return width * 4;
797     case GST_VIDEO_FORMAT_RGB:
798     case GST_VIDEO_FORMAT_BGR:
799       return GST_ROUND_UP_4 (width * 3);
800     case GST_VIDEO_FORMAT_Y41B:
801       if (component == 0) {
802         return GST_ROUND_UP_4 (width);
803       } else {
804         return GST_ROUND_UP_8 (width) / 4;
805       }
806     case GST_VIDEO_FORMAT_Y42B:
807       if (component == 0) {
808         return GST_ROUND_UP_4 (width);
809       } else {
810         return GST_ROUND_UP_8 (width) / 2;
811       }
812     default:
813       return 0;
814   }
815 }
816
817 /**
818  * gst_video_format_get_pixel_stride:
819  * @format: a #GstVideoFormat
820  * @component: the component index
821  *
822  * Calculates the pixel stride (number of bytes from one pixel to the
823  * pixel to its immediate left) for the video component with an index
824  * of @component.  See @gst_video_format_get_row_stride for a description
825  * of the component index.
826  *
827  * Since: 0.10.16
828  *
829  * Returns: pixel stride of component @component
830  */
831 int
832 gst_video_format_get_pixel_stride (GstVideoFormat format, int component)
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
837   switch (format) {
838     case GST_VIDEO_FORMAT_I420:
839     case GST_VIDEO_FORMAT_YV12:
840     case GST_VIDEO_FORMAT_Y41B:
841     case GST_VIDEO_FORMAT_Y42B:
842       return 1;
843     case GST_VIDEO_FORMAT_YUY2:
844     case GST_VIDEO_FORMAT_UYVY:
845       if (component == 0) {
846         return 2;
847       } else {
848         return 4;
849       }
850     case GST_VIDEO_FORMAT_AYUV:
851     case GST_VIDEO_FORMAT_RGBx:
852     case GST_VIDEO_FORMAT_BGRx:
853     case GST_VIDEO_FORMAT_xRGB:
854     case GST_VIDEO_FORMAT_xBGR:
855     case GST_VIDEO_FORMAT_RGBA:
856     case GST_VIDEO_FORMAT_BGRA:
857     case GST_VIDEO_FORMAT_ARGB:
858     case GST_VIDEO_FORMAT_ABGR:
859       return 4;
860     case GST_VIDEO_FORMAT_RGB:
861     case GST_VIDEO_FORMAT_BGR:
862       return 3;
863     default:
864       return 0;
865   }
866 }
867
868 /**
869  * gst_video_format_get_component_width:
870  * @format: a #GstVideoFormat
871  * @component: the component index
872  * @width: the width of video
873  *
874  * Calculates the width of the component.  See
875  * @gst_video_format_get_row_stride for a description
876  * of the component index.
877  *
878  * Since: 0.10.16
879  *
880  * Returns: width of component @component
881  */
882 int
883 gst_video_format_get_component_width (GstVideoFormat format, int component,
884     int width)
885 {
886   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
887   g_return_val_if_fail (component >= 0 && component <= 3, 0);
888   g_return_val_if_fail (width > 0, 0);
889
890   switch (format) {
891     case GST_VIDEO_FORMAT_I420:
892     case GST_VIDEO_FORMAT_YV12:
893     case GST_VIDEO_FORMAT_YUY2:
894     case GST_VIDEO_FORMAT_UYVY:
895       if (component == 0) {
896         return width;
897       } else {
898         return GST_ROUND_UP_2 (width) / 2;
899       }
900     case GST_VIDEO_FORMAT_Y41B:        /* CHECKME: component_width for Y41B */
901       if (component == 0) {
902         return width;
903       } else {
904         return GST_ROUND_UP_8 (width) / 4;
905       }
906     case GST_VIDEO_FORMAT_Y42B:        /* CHECKME: component_width for Y42B */
907       if (component == 0) {
908         return width;
909       } else {
910         return GST_ROUND_UP_8 (width) / 2;
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     case GST_VIDEO_FORMAT_RGB:
922     case GST_VIDEO_FORMAT_BGR:
923       return width;
924     default:
925       return 0;
926   }
927 }
928
929 /**
930  * gst_video_format_get_component_height:
931  * @format: a #GstVideoFormat
932  * @component: the component index
933  * @height: the height of video
934  *
935  * Calculates the height of the component.  See
936  * @gst_video_format_get_row_stride for a description
937  * of the component index.
938  *
939  * Since: 0.10.16
940  *
941  * Returns: height of component @component
942  */
943 int
944 gst_video_format_get_component_height (GstVideoFormat format, int component,
945     int height)
946 {
947   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
948   g_return_val_if_fail (component >= 0 && component <= 3, 0);
949   g_return_val_if_fail (height > 0, 0);
950
951   switch (format) {
952     case GST_VIDEO_FORMAT_I420:
953     case GST_VIDEO_FORMAT_YV12:
954       if (component == 0) {
955         return height;
956       } else {
957         return GST_ROUND_UP_2 (height) / 2;
958       }
959     case GST_VIDEO_FORMAT_Y41B:
960     case GST_VIDEO_FORMAT_Y42B:
961     case GST_VIDEO_FORMAT_YUY2:
962     case GST_VIDEO_FORMAT_UYVY:
963     case GST_VIDEO_FORMAT_AYUV:
964     case GST_VIDEO_FORMAT_RGBx:
965     case GST_VIDEO_FORMAT_BGRx:
966     case GST_VIDEO_FORMAT_xRGB:
967     case GST_VIDEO_FORMAT_xBGR:
968     case GST_VIDEO_FORMAT_RGBA:
969     case GST_VIDEO_FORMAT_BGRA:
970     case GST_VIDEO_FORMAT_ARGB:
971     case GST_VIDEO_FORMAT_ABGR:
972     case GST_VIDEO_FORMAT_RGB:
973     case GST_VIDEO_FORMAT_BGR:
974       return height;
975     default:
976       return 0;
977   }
978 }
979
980 /**
981  * gst_video_format_get_component_offset:
982  * @format: a #GstVideoFormat
983  * @component: the component index
984  * @width: the width of video
985  * @height: the height of video
986  *
987  * Calculates the offset (in bytes) of the first pixel of the component
988  * with index @component.  For packed formats, this will typically be a
989  * small integer (0, 1, 2, 3).  For planar formats, this will be a
990  * (relatively) large offset to the beginning of the second or third
991  * component planes.  See @gst_video_format_get_row_stride for a description
992  * of the component index.
993  *
994  * Since: 0.10.16
995  *
996  * Returns: offset of component @component
997  */
998 int
999 gst_video_format_get_component_offset (GstVideoFormat format, int component,
1000     int width, int height)
1001 {
1002   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1003   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1004   g_return_val_if_fail (width > 0 && height > 0, 0);
1005
1006   switch (format) {
1007     case GST_VIDEO_FORMAT_I420:
1008       if (component == 0)
1009         return 0;
1010       if (component == 1)
1011         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1012       if (component == 2) {
1013         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) +
1014             GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1015             (GST_ROUND_UP_2 (height) / 2);
1016       }
1017       return 0;
1018     case GST_VIDEO_FORMAT_YV12:        /* same as I420, but components 1+2 swapped */
1019       if (component == 0)
1020         return 0;
1021       if (component == 2)
1022         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1023       if (component == 1) {
1024         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) +
1025             GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1026             (GST_ROUND_UP_2 (height) / 2);
1027       }
1028       return 0;
1029     case GST_VIDEO_FORMAT_YUY2:
1030       if (component == 0)
1031         return 0;
1032       if (component == 1)
1033         return 1;
1034       if (component == 2)
1035         return 3;
1036       return 0;
1037     case GST_VIDEO_FORMAT_UYVY:
1038       if (component == 0)
1039         return 1;
1040       if (component == 1)
1041         return 0;
1042       if (component == 2)
1043         return 2;
1044       return 0;
1045     case GST_VIDEO_FORMAT_AYUV:
1046       if (component == 0)
1047         return 1;
1048       if (component == 1)
1049         return 2;
1050       if (component == 2)
1051         return 3;
1052       if (component == 3)
1053         return 0;
1054       return 0;
1055     case GST_VIDEO_FORMAT_RGBx:
1056     case GST_VIDEO_FORMAT_RGBA:
1057       if (component == 0)
1058         return 0;
1059       if (component == 1)
1060         return 1;
1061       if (component == 2)
1062         return 2;
1063       if (component == 3)
1064         return 3;
1065       return 0;
1066     case GST_VIDEO_FORMAT_BGRx:
1067     case GST_VIDEO_FORMAT_BGRA:
1068       if (component == 0)
1069         return 2;
1070       if (component == 1)
1071         return 1;
1072       if (component == 2)
1073         return 0;
1074       if (component == 3)
1075         return 3;
1076       return 0;
1077     case GST_VIDEO_FORMAT_xRGB:
1078     case GST_VIDEO_FORMAT_ARGB:
1079       if (component == 0)
1080         return 1;
1081       if (component == 1)
1082         return 2;
1083       if (component == 2)
1084         return 3;
1085       if (component == 3)
1086         return 0;
1087       return 0;
1088     case GST_VIDEO_FORMAT_xBGR:
1089     case GST_VIDEO_FORMAT_ABGR:
1090       if (component == 0)
1091         return 3;
1092       if (component == 1)
1093         return 2;
1094       if (component == 2)
1095         return 1;
1096       if (component == 3)
1097         return 0;
1098       return 0;
1099     case GST_VIDEO_FORMAT_RGB:
1100       if (component == 0)
1101         return 0;
1102       if (component == 1)
1103         return 1;
1104       if (component == 2)
1105         return 2;
1106       return 0;
1107     case GST_VIDEO_FORMAT_BGR:
1108       if (component == 0)
1109         return 2;
1110       if (component == 1)
1111         return 1;
1112       if (component == 2)
1113         return 0;
1114       return 0;
1115     case GST_VIDEO_FORMAT_Y41B:
1116       if (component == 0)
1117         return 0;
1118       if (component == 1)
1119         return GST_ROUND_UP_4 (width) * height;
1120       if (component == 2)
1121         return (GST_ROUND_UP_4 (width) + (GST_ROUND_UP_8 (width) / 4)) * height;
1122       return 0;
1123     case GST_VIDEO_FORMAT_Y42B:
1124       if (component == 0)
1125         return 0;
1126       if (component == 1)
1127         return GST_ROUND_UP_4 (width) * height;
1128       if (component == 2)
1129         return (GST_ROUND_UP_4 (width) + (GST_ROUND_UP_8 (width) / 2)) * height;
1130       return 0;
1131     default:
1132       return 0;
1133   }
1134 }
1135
1136 /**
1137  * gst_video_format_get_size:
1138  * @format: a #GstVideoFormat
1139  * @width: the width of video
1140  * @height: the height of video
1141  *
1142  * Calculates the total number of bytes in the raw video format.  This
1143  * number should be used when allocating a buffer for raw video.
1144  *
1145  * Since: 0.10.16
1146  *
1147  * Returns: size (in bytes) of raw video format
1148  */
1149 int
1150 gst_video_format_get_size (GstVideoFormat format, int width, int height)
1151 {
1152   int size;
1153
1154   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1155   g_return_val_if_fail (width > 0 && height > 0, 0);
1156
1157   switch (format) {
1158     case GST_VIDEO_FORMAT_I420:
1159     case GST_VIDEO_FORMAT_YV12:
1160       size = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1161       size += GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1162           (GST_ROUND_UP_2 (height) / 2) * 2;
1163       return size;
1164     case GST_VIDEO_FORMAT_YUY2:
1165     case GST_VIDEO_FORMAT_UYVY:
1166       return GST_ROUND_UP_4 (width * 2) * height;
1167     case GST_VIDEO_FORMAT_AYUV:
1168     case GST_VIDEO_FORMAT_RGBx:
1169     case GST_VIDEO_FORMAT_BGRx:
1170     case GST_VIDEO_FORMAT_xRGB:
1171     case GST_VIDEO_FORMAT_xBGR:
1172     case GST_VIDEO_FORMAT_RGBA:
1173     case GST_VIDEO_FORMAT_BGRA:
1174     case GST_VIDEO_FORMAT_ARGB:
1175     case GST_VIDEO_FORMAT_ABGR:
1176       return width * 4 * height;
1177     case GST_VIDEO_FORMAT_RGB:
1178     case GST_VIDEO_FORMAT_BGR:
1179       return GST_ROUND_UP_4 (width * 3) * height;
1180     case GST_VIDEO_FORMAT_Y41B:
1181       /* simplification of ROUNDUP4(w)*h + 2*((ROUNDUP8(w)/4)*h */
1182       return (GST_ROUND_UP_4 (width) + (GST_ROUND_UP_8 (width) / 2)) * height;
1183     case GST_VIDEO_FORMAT_Y42B:
1184       /* simplification of ROUNDUP4(w)*h + 2*(ROUNDUP8(w)/2)*h: */
1185       return (GST_ROUND_UP_4 (width) + GST_ROUND_UP_8 (width)) * height;
1186     default:
1187       return 0;
1188   }
1189 }
1190
1191 /**
1192  * gst_video_format_convert:
1193  * @format: a #GstVideoFormat
1194  * @width: the width of video
1195  * @height: the height of video
1196  * @fps_n: frame rate numerator
1197  * @fps_d: frame rate denominator
1198  * @src_format: #GstFormat of the @src_value
1199  * @src_value: value to convert
1200  * @dest_format: #GstFormat of the @dest_value
1201  * @dest_value: pointer to destination value
1202  *
1203  * Converts among various #GstFormat types.  This function handles
1204  * GST_FORMAT_BYTES, GST_FORMAT_TIME, and GST_FORMAT_DEFAULT.  For
1205  * raw video, GST_FORMAT_DEFAULT corresponds to video frames.  This
1206  * function can be to handle pad queries of the type GST_QUERY_CONVERT.
1207  *
1208  * Since: 0.10.16
1209  *
1210  * Returns: TRUE if the conversion was successful.
1211  */
1212 gboolean
1213 gst_video_format_convert (GstVideoFormat format, int width, int height,
1214     int fps_n, int fps_d,
1215     GstFormat src_format, gint64 src_value,
1216     GstFormat dest_format, gint64 * dest_value)
1217 {
1218   gboolean ret = FALSE;
1219   int size;
1220
1221   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1222   g_return_val_if_fail (width > 0 && height > 0, 0);
1223
1224   size = gst_video_format_get_size (format, width, height);
1225
1226   GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s to %s",
1227       src_value, gst_format_get_name (src_format),
1228       gst_format_get_name (dest_format));
1229
1230   if (src_format == dest_format) {
1231     *dest_value = src_value;
1232     ret = TRUE;
1233     goto done;
1234   }
1235
1236   if (src_value == -1) {
1237     *dest_value = -1;
1238     ret = TRUE;
1239     goto done;
1240   }
1241
1242   /* bytes to frames */
1243   if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_DEFAULT) {
1244     if (size != 0) {
1245       *dest_value = gst_util_uint64_scale_int (src_value, 1, size);
1246     } else {
1247       GST_ERROR ("blocksize is 0");
1248       *dest_value = 0;
1249     }
1250     ret = TRUE;
1251     goto done;
1252   }
1253
1254   /* frames to bytes */
1255   if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_BYTES) {
1256     *dest_value = gst_util_uint64_scale_int (src_value, size, 1);
1257     ret = TRUE;
1258     goto done;
1259   }
1260
1261   /* time to frames */
1262   if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_DEFAULT) {
1263     if (fps_d != 0) {
1264       *dest_value = gst_util_uint64_scale (src_value,
1265           fps_n, GST_SECOND * fps_d);
1266     } else {
1267       GST_ERROR ("framerate denominator is 0");
1268       *dest_value = 0;
1269     }
1270     ret = TRUE;
1271     goto done;
1272   }
1273
1274   /* frames to time */
1275   if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
1276     if (fps_n != 0) {
1277       *dest_value = gst_util_uint64_scale (src_value,
1278           GST_SECOND * fps_d, fps_n);
1279     } else {
1280       GST_ERROR ("framerate numerator is 0");
1281       *dest_value = 0;
1282     }
1283     ret = TRUE;
1284     goto done;
1285   }
1286
1287   /* time to bytes */
1288   if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) {
1289     if (fps_d != 0) {
1290       *dest_value = gst_util_uint64_scale (src_value,
1291           fps_n * size, GST_SECOND * fps_d);
1292     } else {
1293       GST_ERROR ("framerate denominator is 0");
1294       *dest_value = 0;
1295     }
1296     ret = TRUE;
1297     goto done;
1298   }
1299
1300   /* bytes to time */
1301   if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_TIME) {
1302     if (fps_n != 0 && size != 0) {
1303       *dest_value = gst_util_uint64_scale (src_value,
1304           GST_SECOND * fps_d, fps_n * size);
1305     } else {
1306       GST_ERROR ("framerate denominator and/or blocksize is 0");
1307       *dest_value = 0;
1308     }
1309     ret = TRUE;
1310   }
1311
1312 done:
1313
1314   GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, ret, *dest_value);
1315
1316   return ret;
1317 }