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