video: rework part 2
[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 <string.h>
27
28 #include "video.h"
29
30 static int get_size (GstVideoFormat format, int width, int height);
31 static int get_stride (GstVideoFormat format, int plane, int width);
32 static int fill_planes (GstVideoInfo * info);
33
34 typedef enum
35 {
36   VIDEO_FLAG_YUV = (1 << 0),
37   VIDEO_FLAG_RGB = (1 << 1),
38   VIDEO_FLAG_GRAY = (1 << 2),
39   VIDEO_FLAG_ALPHA = (1 << 3)
40 } VideoFlags;
41
42 typedef struct
43 {
44   const gchar *fmt;
45   GstVideoFormat format;
46   guint32 fourcc;
47   VideoFlags flags;
48   guint n_comp;
49   guint depth[GST_VIDEO_MAX_PLANES];
50   guint n_planes;
51 } VideoFormat;
52
53 #define COMP0            0, { 0, 0, 0, 0 }
54 #define COMP8            1, { 8, 0, 0, 0 }
55 #define COMP888          3, { 8, 8, 8, 0 }
56 #define COMP8888         4, { 8, 8, 8, 8 }
57 #define COMP10_10_10     3, { 10, 10, 10, 0 }
58 #define COMP16           1, { 16, 0, 0, 0 }
59 #define COMP16_16_16     3, { 16, 16, 16, 0 }
60 #define COMP16_16_16_16  4, { 16, 16, 16, 16 }
61 #define COMP555          3, { 5, 5, 5, 0 }
62 #define COMP565          3, { 5, 6, 5, 0 }
63
64 #define MAKE_YUV_FORMAT(name, fourcc, comp) \
65  { G_STRINGIFY(name), GST_VIDEO_FORMAT_ ##name, fourcc, VIDEO_FLAG_YUV, comp }
66 #define MAKE_YUVA_FORMAT(name, fourcc, comp) \
67  { G_STRINGIFY(name), GST_VIDEO_FORMAT_ ##name, fourcc, VIDEO_FLAG_YUV | VIDEO_FLAG_ALPHA, comp }
68
69 #define MAKE_RGB_FORMAT(name, comp) \
70  { G_STRINGIFY(name), GST_VIDEO_FORMAT_ ##name, 0x00000000, VIDEO_FLAG_RGB, comp }
71 #define MAKE_RGBA_FORMAT(name, comp) \
72  { G_STRINGIFY(name), GST_VIDEO_FORMAT_ ##name, 0x00000000, VIDEO_FLAG_RGB | VIDEO_FLAG_ALPHA, comp }
73
74 #define MAKE_GRAY_FORMAT(name, comp) \
75  { G_STRINGIFY(name), GST_VIDEO_FORMAT_ ##name, 0x00000000, VIDEO_FLAG_GRAY, comp }
76
77 static VideoFormat formats[] = {
78   {"UNKNOWN", GST_VIDEO_FORMAT_UNKNOWN, 0x00000000, 0, COMP0},
79
80   MAKE_YUV_FORMAT (I420, GST_MAKE_FOURCC ('I', '4', '2', '0'), COMP888),
81   MAKE_YUV_FORMAT (YV12, GST_MAKE_FOURCC ('Y', 'V', '1', '2'), COMP888),
82   MAKE_YUV_FORMAT (YUY2, GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'), COMP888),
83   MAKE_YUV_FORMAT (UYVY, GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'), COMP888),
84   MAKE_YUVA_FORMAT (AYUV, GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'), COMP8888),
85   MAKE_RGB_FORMAT (RGBx, COMP888),
86   MAKE_RGB_FORMAT (BGRx, COMP888),
87   MAKE_RGB_FORMAT (xRGB, COMP888),
88   MAKE_RGB_FORMAT (xBGR, COMP888),
89   MAKE_RGBA_FORMAT (RGBA, COMP8888),
90   MAKE_RGBA_FORMAT (BGRA, COMP8888),
91   MAKE_RGBA_FORMAT (ARGB, COMP8888),
92   MAKE_RGBA_FORMAT (ABGR, COMP8888),
93   MAKE_RGB_FORMAT (RGB, COMP888),
94   MAKE_RGB_FORMAT (BGR, COMP888),
95
96   MAKE_YUV_FORMAT (Y41B, GST_MAKE_FOURCC ('Y', '4', '1', 'B'), COMP888),
97   MAKE_YUV_FORMAT (Y42B, GST_MAKE_FOURCC ('Y', '4', '2', 'B'), COMP888),
98   MAKE_YUV_FORMAT (YVYU, GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'), COMP888),
99   MAKE_YUV_FORMAT (Y444, GST_MAKE_FOURCC ('Y', '4', '4', '4'), COMP888),
100   MAKE_YUV_FORMAT (v210, GST_MAKE_FOURCC ('v', '2', '1', '0'), COMP10_10_10),
101   MAKE_YUV_FORMAT (v216, GST_MAKE_FOURCC ('v', '2', '1', '6'), COMP16_16_16),
102   MAKE_YUV_FORMAT (NV12, GST_MAKE_FOURCC ('N', 'V', '1', '2'), COMP888),
103   MAKE_YUV_FORMAT (NV21, GST_MAKE_FOURCC ('N', 'V', '2', '1'), COMP888),
104
105   MAKE_GRAY_FORMAT (GRAY8, COMP8),
106   MAKE_GRAY_FORMAT (GRAY16_BE, COMP16),
107   MAKE_GRAY_FORMAT (GRAY16_LE, COMP16),
108
109   MAKE_YUV_FORMAT (v308, GST_MAKE_FOURCC ('v', '3', '0', '8'), COMP888),
110   MAKE_YUV_FORMAT (Y800, GST_MAKE_FOURCC ('Y', '8', '0', '0'), COMP8),
111   MAKE_YUV_FORMAT (Y16, GST_MAKE_FOURCC ('Y', '1', '6', ' '), COMP16),
112
113   MAKE_RGB_FORMAT (RGB16, COMP565),
114   MAKE_RGB_FORMAT (BGR16, COMP565),
115   MAKE_RGB_FORMAT (RGB15, COMP555),
116   MAKE_RGB_FORMAT (BGR15, COMP555),
117
118   MAKE_YUV_FORMAT (UYVP, GST_MAKE_FOURCC ('U', 'Y', 'V', 'P'), COMP10_10_10),
119   MAKE_YUVA_FORMAT (A420, GST_MAKE_FOURCC ('A', '4', '2', '0'), COMP888),
120   MAKE_RGBA_FORMAT (RGB8_PALETTED, COMP8888),
121   MAKE_YUV_FORMAT (YUV9, GST_MAKE_FOURCC ('Y', 'U', 'V', '9'), COMP888),
122   MAKE_YUV_FORMAT (YVU9, GST_MAKE_FOURCC ('Y', 'V', 'U', '9'), COMP888),
123   MAKE_YUV_FORMAT (IYU1, GST_MAKE_FOURCC ('I', 'Y', 'U', '1'), COMP888),
124   MAKE_RGBA_FORMAT (ARGB64, COMP16_16_16_16),
125   MAKE_YUVA_FORMAT (AYUV64, 0x00000000, COMP16_16_16_16),
126   MAKE_YUV_FORMAT (r210, GST_MAKE_FOURCC ('r', '2', '1', '0'), COMP10_10_10),
127 };
128
129 /**
130  * SECTION:gstvideo
131  * @short_description: Support library for video operations
132  *
133  * <refsect2>
134  * <para>
135  * This library contains some helper functions and includes the
136  * videosink and videofilter base classes.
137  * </para>
138  * </refsect2>
139  */
140
141 /**
142  * gst_video_calculate_display_ratio:
143  * @dar_n: Numerator of the calculated display_ratio
144  * @dar_d: Denominator of the calculated display_ratio
145  * @video_width: Width of the video frame in pixels
146  * @video_height: Height of the video frame in pixels
147  * @video_par_n: Numerator of the pixel aspect ratio of the input video.
148  * @video_par_d: Denominator of the pixel aspect ratio of the input video.
149  * @display_par_n: Numerator of the pixel aspect ratio of the display device
150  * @display_par_d: Denominator of the pixel aspect ratio of the display device
151  *
152  * Given the Pixel Aspect Ratio and size of an input video frame, and the
153  * pixel aspect ratio of the intended display device, calculates the actual
154  * display ratio the video will be rendered with.
155  *
156  * Returns: A boolean indicating success and a calculated Display Ratio in the
157  * dar_n and dar_d parameters.
158  * The return value is FALSE in the case of integer overflow or other error.
159  *
160  * Since: 0.10.7
161  */
162 gboolean
163 gst_video_calculate_display_ratio (guint * dar_n, guint * dar_d,
164     guint video_width, guint video_height,
165     guint video_par_n, guint video_par_d,
166     guint display_par_n, guint display_par_d)
167 {
168   gint num, den;
169   gint tmp_n, tmp_d;
170
171   g_return_val_if_fail (dar_n != NULL, FALSE);
172   g_return_val_if_fail (dar_d != NULL, FALSE);
173
174   /* Calculate (video_width * video_par_n * display_par_d) /
175    * (video_height * video_par_d * display_par_n) */
176   if (!gst_util_fraction_multiply (video_width, video_height, video_par_n,
177           video_par_d, &tmp_n, &tmp_d))
178     goto error_overflow;
179
180   if (!gst_util_fraction_multiply (tmp_n, tmp_d, display_par_d, display_par_n,
181           &num, &den))
182     goto error_overflow;
183
184   g_return_val_if_fail (num > 0, FALSE);
185   g_return_val_if_fail (den > 0, FALSE);
186
187   *dar_n = num;
188   *dar_d = den;
189
190   return TRUE;
191
192   /* ERRORS */
193 error_overflow:
194   {
195     GST_WARNING ("overflow in multiply");
196     return FALSE;
197   }
198 }
199
200 static GstVideoFormat
201 gst_video_format_from_rgb32_masks (int red_mask, int green_mask, int blue_mask)
202 {
203   if (red_mask == 0xff000000 && green_mask == 0x00ff0000 &&
204       blue_mask == 0x0000ff00) {
205     return GST_VIDEO_FORMAT_RGBx;
206   }
207   if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 &&
208       blue_mask == 0xff000000) {
209     return GST_VIDEO_FORMAT_BGRx;
210   }
211   if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 &&
212       blue_mask == 0x000000ff) {
213     return GST_VIDEO_FORMAT_xRGB;
214   }
215   if (red_mask == 0x000000ff && green_mask == 0x0000ff00 &&
216       blue_mask == 0x00ff0000) {
217     return GST_VIDEO_FORMAT_xBGR;
218   }
219
220   return GST_VIDEO_FORMAT_UNKNOWN;
221 }
222
223 static GstVideoFormat
224 gst_video_format_from_rgba32_masks (int red_mask, int green_mask,
225     int blue_mask, int alpha_mask)
226 {
227   if (red_mask == 0xff000000 && green_mask == 0x00ff0000 &&
228       blue_mask == 0x0000ff00 && alpha_mask == 0x000000ff) {
229     return GST_VIDEO_FORMAT_RGBA;
230   }
231   if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 &&
232       blue_mask == 0xff000000 && alpha_mask == 0x000000ff) {
233     return GST_VIDEO_FORMAT_BGRA;
234   }
235   if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 &&
236       blue_mask == 0x000000ff && alpha_mask == 0xff000000) {
237     return GST_VIDEO_FORMAT_ARGB;
238   }
239   if (red_mask == 0x000000ff && green_mask == 0x0000ff00 &&
240       blue_mask == 0x00ff0000 && alpha_mask == 0xff000000) {
241     return GST_VIDEO_FORMAT_ABGR;
242   }
243   return GST_VIDEO_FORMAT_UNKNOWN;
244 }
245
246 static GstVideoFormat
247 gst_video_format_from_rgb24_masks (int red_mask, int green_mask, int blue_mask)
248 {
249   if (red_mask == 0xff0000 && green_mask == 0x00ff00 && blue_mask == 0x0000ff) {
250     return GST_VIDEO_FORMAT_RGB;
251   }
252   if (red_mask == 0x0000ff && green_mask == 0x00ff00 && blue_mask == 0xff0000) {
253     return GST_VIDEO_FORMAT_BGR;
254   }
255
256   return GST_VIDEO_FORMAT_UNKNOWN;
257 }
258
259 #define GST_VIDEO_COMP1_MASK_16_INT 0xf800
260 #define GST_VIDEO_COMP2_MASK_16_INT 0x07e0
261 #define GST_VIDEO_COMP3_MASK_16_INT 0x001f
262
263 #define GST_VIDEO_COMP1_MASK_15_INT 0x7c00
264 #define GST_VIDEO_COMP2_MASK_15_INT 0x03e0
265 #define GST_VIDEO_COMP3_MASK_15_INT 0x001f
266
267 static GstVideoFormat
268 gst_video_format_from_rgb16_masks (int red_mask, int green_mask, int blue_mask)
269 {
270   if (red_mask == GST_VIDEO_COMP1_MASK_16_INT
271       && green_mask == GST_VIDEO_COMP2_MASK_16_INT
272       && blue_mask == GST_VIDEO_COMP3_MASK_16_INT) {
273     return GST_VIDEO_FORMAT_RGB16;
274   }
275   if (red_mask == GST_VIDEO_COMP3_MASK_16_INT
276       && green_mask == GST_VIDEO_COMP2_MASK_16_INT
277       && blue_mask == GST_VIDEO_COMP1_MASK_16_INT) {
278     return GST_VIDEO_FORMAT_BGR16;
279   }
280   if (red_mask == GST_VIDEO_COMP1_MASK_15_INT
281       && green_mask == GST_VIDEO_COMP2_MASK_15_INT
282       && blue_mask == GST_VIDEO_COMP3_MASK_15_INT) {
283     return GST_VIDEO_FORMAT_RGB15;
284   }
285   if (red_mask == GST_VIDEO_COMP3_MASK_15_INT
286       && green_mask == GST_VIDEO_COMP2_MASK_15_INT
287       && blue_mask == GST_VIDEO_COMP1_MASK_15_INT) {
288     return GST_VIDEO_FORMAT_BGR15;
289   }
290   return GST_VIDEO_FORMAT_UNKNOWN;
291 }
292
293 GstVideoFormat
294 gst_video_format_from_masks (gint depth, gint bpp, gint endianness,
295     gint red_mask, gint green_mask, gint blue_mask, gint alpha_mask)
296 {
297   GstVideoFormat format;
298
299   /* our caps system handles 24/32bpp RGB as big-endian. */
300   if ((bpp == 24 || bpp == 32) && endianness == G_LITTLE_ENDIAN) {
301     red_mask = GUINT32_TO_BE (red_mask);
302     green_mask = GUINT32_TO_BE (green_mask);
303     blue_mask = GUINT32_TO_BE (blue_mask);
304     endianness = G_BIG_ENDIAN;
305     if (bpp == 24) {
306       red_mask >>= 8;
307       green_mask >>= 8;
308       blue_mask >>= 8;
309     }
310   }
311
312   if (depth == 30 && bpp == 32) {
313     format = GST_VIDEO_FORMAT_r210;
314   } else if (depth == 24 && bpp == 32) {
315     format = gst_video_format_from_rgb32_masks (red_mask, green_mask,
316         blue_mask);
317   } else if (depth == 32 && bpp == 32 && alpha_mask) {
318     format = gst_video_format_from_rgba32_masks (red_mask, green_mask,
319         blue_mask, alpha_mask);
320   } else if (depth == 24 && bpp == 24) {
321     format = gst_video_format_from_rgb24_masks (red_mask, green_mask,
322         blue_mask);
323   } else if ((depth == 15 || depth == 16) && bpp == 16 &&
324       endianness == G_BYTE_ORDER) {
325     format = gst_video_format_from_rgb16_masks (red_mask, green_mask,
326         blue_mask);
327   } else if (depth == 8 && bpp == 8) {
328     format = GST_VIDEO_FORMAT_RGB8_PALETTED;
329   } else if (depth == 64 && bpp == 64) {
330     format = gst_video_format_from_rgba32_masks (red_mask, green_mask,
331         blue_mask, alpha_mask);
332     if (format == GST_VIDEO_FORMAT_ARGB) {
333       format = GST_VIDEO_FORMAT_ARGB64;
334     } else {
335       format = GST_VIDEO_FORMAT_UNKNOWN;
336     }
337   } else {
338     format = GST_VIDEO_FORMAT_UNKNOWN;
339   }
340   return format;
341 }
342
343 /**
344  * gst_video_format_from_fourcc:
345  * @fourcc: a FOURCC value representing raw YUV video
346  *
347  * Converts a FOURCC value into the corresponding #GstVideoFormat.
348  * If the FOURCC cannot be represented by #GstVideoFormat,
349  * #GST_VIDEO_FORMAT_UNKNOWN is returned.
350  *
351  * Since: 0.10.16
352  *
353  * Returns: the #GstVideoFormat describing the FOURCC value
354  */
355 GstVideoFormat
356 gst_video_format_from_fourcc (guint32 fourcc)
357 {
358   switch (fourcc) {
359     case GST_MAKE_FOURCC ('I', '4', '2', '0'):
360       return GST_VIDEO_FORMAT_I420;
361     case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
362       return GST_VIDEO_FORMAT_YV12;
363     case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
364       return GST_VIDEO_FORMAT_YUY2;
365     case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'):
366       return GST_VIDEO_FORMAT_YVYU;
367     case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
368       return GST_VIDEO_FORMAT_UYVY;
369     case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'):
370       return GST_VIDEO_FORMAT_AYUV;
371     case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
372       return GST_VIDEO_FORMAT_Y41B;
373     case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
374       return GST_VIDEO_FORMAT_Y42B;
375     case GST_MAKE_FOURCC ('Y', '4', '4', '4'):
376       return GST_VIDEO_FORMAT_Y444;
377     case GST_MAKE_FOURCC ('v', '2', '1', '0'):
378       return GST_VIDEO_FORMAT_v210;
379     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
380       return GST_VIDEO_FORMAT_v216;
381     case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
382       return GST_VIDEO_FORMAT_NV12;
383     case GST_MAKE_FOURCC ('N', 'V', '2', '1'):
384       return GST_VIDEO_FORMAT_NV21;
385     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
386       return GST_VIDEO_FORMAT_v308;
387     case GST_MAKE_FOURCC ('Y', '8', '0', '0'):
388     case GST_MAKE_FOURCC ('Y', '8', ' ', ' '):
389     case GST_MAKE_FOURCC ('G', 'R', 'E', 'Y'):
390       return GST_VIDEO_FORMAT_Y800;
391     case GST_MAKE_FOURCC ('Y', '1', '6', ' '):
392       return GST_VIDEO_FORMAT_Y16;
393     case GST_MAKE_FOURCC ('U', 'Y', 'V', 'P'):
394       return GST_VIDEO_FORMAT_UYVP;
395     case GST_MAKE_FOURCC ('A', '4', '2', '0'):
396       return GST_VIDEO_FORMAT_A420;
397     case GST_MAKE_FOURCC ('Y', 'U', 'V', '9'):
398       return GST_VIDEO_FORMAT_YUV9;
399     case GST_MAKE_FOURCC ('Y', 'V', 'U', '9'):
400       return GST_VIDEO_FORMAT_YVU9;
401     case GST_MAKE_FOURCC ('I', 'Y', 'U', '1'):
402       return GST_VIDEO_FORMAT_IYU1;
403     case GST_MAKE_FOURCC ('A', 'Y', '6', '4'):
404       return GST_VIDEO_FORMAT_AYUV64;
405     default:
406       return GST_VIDEO_FORMAT_UNKNOWN;
407   }
408 }
409
410 GstVideoFormat
411 gst_video_format_from_string (const gchar * format)
412 {
413   guint i;
414
415   for (i = 0; i < G_N_ELEMENTS (formats); i++) {
416     if (strcmp (formats[i].fmt, format) == 0)
417       return formats[i].format;
418   }
419   return GST_VIDEO_FORMAT_UNKNOWN;
420 }
421
422
423 /**
424  * gst_video_format_to_fourcc:
425  * @format: a #GstVideoFormat video format
426  *
427  * Converts a #GstVideoFormat value into the corresponding FOURCC.  Only
428  * a few YUV formats have corresponding FOURCC values.  If @format has
429  * no corresponding FOURCC value, 0 is returned.
430  *
431  * Since: 0.10.16
432  *
433  * Returns: the FOURCC corresponding to @format
434  */
435 guint32
436 gst_video_format_to_fourcc (GstVideoFormat format)
437 {
438   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
439
440   if (format >= G_N_ELEMENTS (formats))
441     return 0;
442
443   return formats[format].fourcc;
444 }
445
446 const gchar *
447 gst_video_format_to_string (GstVideoFormat format)
448 {
449   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
450
451   if (format >= G_N_ELEMENTS (formats))
452     return NULL;
453
454   return formats[format].fmt;
455 }
456
457 /**
458  * gst_video_format_is_rgb:
459  * @format: a #GstVideoFormat
460  *
461  * Determine whether the video format is an RGB format.
462  *
463  * Since: 0.10.16
464  *
465  * Returns: TRUE if @format represents RGB video
466  */
467 gboolean
468 gst_video_format_is_rgb (GstVideoFormat format)
469 {
470   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, FALSE);
471
472   if (format >= G_N_ELEMENTS (formats))
473     return FALSE;
474
475   return (formats[format].flags & VIDEO_FLAG_RGB) != 0;
476 }
477
478 /**
479  * gst_video_format_is_yuv:
480  * @format: a #GstVideoFormat
481  *
482  * Determine whether the video format is a YUV format.
483  *
484  * Since: 0.10.16
485  *
486  * Returns: TRUE if @format represents YUV video
487  */
488 gboolean
489 gst_video_format_is_yuv (GstVideoFormat format)
490 {
491   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, FALSE);
492
493   if (format >= G_N_ELEMENTS (formats))
494     return FALSE;
495
496   return (formats[format].flags & VIDEO_FLAG_YUV) != 0;
497 }
498
499 /**
500  * gst_video_format_is_gray:
501  * @format: a #GstVideoFormat
502  *
503  * Determine whether the video format is a grayscale format.
504  *
505  * Since: 0.10.29
506  *
507  * Returns: TRUE if @format represents grayscale video
508  */
509 gboolean
510 gst_video_format_is_gray (GstVideoFormat format)
511 {
512   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, FALSE);
513
514   if (format >= G_N_ELEMENTS (formats))
515     return FALSE;
516
517   return (formats[format].flags & VIDEO_FLAG_GRAY) != 0;
518 }
519
520 /**
521  * gst_video_format_has_alpha:
522  * @format: a #GstVideoFormat
523  *
524  * Returns TRUE or FALSE depending on if the video format provides an
525  * alpha channel.
526  *
527  * Since: 0.10.16
528  *
529  * Returns: TRUE if @format has an alpha channel
530  */
531 gboolean
532 gst_video_format_has_alpha (GstVideoFormat format)
533 {
534   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, FALSE);
535
536   if (format >= G_N_ELEMENTS (formats))
537     return FALSE;
538
539   return (formats[format].flags & VIDEO_FLAG_ALPHA) != 0;
540 }
541
542 /**
543  * gst_video_format_get_n_components:
544  * @format: a #GstVideoFormat
545  *
546  * Get the number of components for @format.
547  *
548  * Returns: the number of components for @format.
549  */
550 int
551 gst_video_format_get_n_components (GstVideoFormat format)
552 {
553   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
554
555   if (format >= G_N_ELEMENTS (formats))
556     return 0;
557
558   return formats[format].n_comp;
559 }
560
561 /**
562  * gst_video_format_get_component_depth:
563  * @format: a #GstVideoFormat
564  * @component: the video component (e.g. 0 for 'R' in RGB)
565  *
566  * Returns the number of bits used to encode an individual pixel of
567  * a given @component.  Typically this is 8, although higher and lower
568  * values are possible for some formats.
569  *
570  * Since: 0.10.33
571  *
572  * Returns: depth of component
573  */
574 int
575 gst_video_format_get_component_depth (GstVideoFormat format, int component)
576 {
577   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
578   g_return_val_if_fail (component < GST_VIDEO_MAX_PLANES, 0);
579
580   if (format >= G_N_ELEMENTS (formats))
581     return FALSE;
582
583   return formats[format].depth[component];
584 }
585
586 /**
587  * gst_video_format_get_pixel_stride:
588  * @format: a #GstVideoFormat
589  * @component: the component index
590  *
591  * Calculates the pixel stride (number of bytes from one pixel to the
592  * pixel to its immediate left) for the video component with an index
593  * of @component.  See @gst_video_format_get_row_stride for a description
594  * of the component index.
595  *
596  * Since: 0.10.16
597  *
598  * Returns: pixel stride of component @component
599  */
600 int
601 gst_video_format_get_pixel_stride (GstVideoFormat format, int component)
602 {
603   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
604   g_return_val_if_fail (component >= 0 && component <= 3, 0);
605
606   switch (format) {
607     case GST_VIDEO_FORMAT_I420:
608     case GST_VIDEO_FORMAT_YV12:
609     case GST_VIDEO_FORMAT_Y41B:
610     case GST_VIDEO_FORMAT_Y42B:
611     case GST_VIDEO_FORMAT_Y444:
612     case GST_VIDEO_FORMAT_A420:
613     case GST_VIDEO_FORMAT_YUV9:
614     case GST_VIDEO_FORMAT_YVU9:
615       return 1;
616     case GST_VIDEO_FORMAT_YUY2:
617     case GST_VIDEO_FORMAT_YVYU:
618     case GST_VIDEO_FORMAT_UYVY:
619       if (component == 0) {
620         return 2;
621       } else {
622         return 4;
623       }
624     case GST_VIDEO_FORMAT_IYU1:
625       /* doesn't make much sense for IYU1 because it's 1 or 3
626        * for luma depending on position */
627       return 0;
628     case GST_VIDEO_FORMAT_AYUV:
629     case GST_VIDEO_FORMAT_RGBx:
630     case GST_VIDEO_FORMAT_BGRx:
631     case GST_VIDEO_FORMAT_xRGB:
632     case GST_VIDEO_FORMAT_xBGR:
633     case GST_VIDEO_FORMAT_RGBA:
634     case GST_VIDEO_FORMAT_BGRA:
635     case GST_VIDEO_FORMAT_ARGB:
636     case GST_VIDEO_FORMAT_ABGR:
637     case GST_VIDEO_FORMAT_r210:
638       return 4;
639     case GST_VIDEO_FORMAT_RGB16:
640     case GST_VIDEO_FORMAT_BGR16:
641     case GST_VIDEO_FORMAT_RGB15:
642     case GST_VIDEO_FORMAT_BGR15:
643       return 2;
644     case GST_VIDEO_FORMAT_RGB:
645     case GST_VIDEO_FORMAT_BGR:
646     case GST_VIDEO_FORMAT_v308:
647       return 3;
648     case GST_VIDEO_FORMAT_v210:
649       /* v210 is packed at the bit level, so pixel stride doesn't make sense */
650       return 0;
651     case GST_VIDEO_FORMAT_v216:
652       if (component == 0) {
653         return 4;
654       } else {
655         return 8;
656       }
657     case GST_VIDEO_FORMAT_NV12:
658     case GST_VIDEO_FORMAT_NV21:
659       if (component == 0) {
660         return 1;
661       } else {
662         return 2;
663       }
664     case GST_VIDEO_FORMAT_GRAY8:
665     case GST_VIDEO_FORMAT_Y800:
666       return 1;
667     case GST_VIDEO_FORMAT_GRAY16_BE:
668     case GST_VIDEO_FORMAT_GRAY16_LE:
669     case GST_VIDEO_FORMAT_Y16:
670       return 2;
671     case GST_VIDEO_FORMAT_UYVP:
672       /* UYVP is packed at the bit level, so pixel stride doesn't make sense */
673       return 0;
674     case GST_VIDEO_FORMAT_RGB8_PALETTED:
675       return 1;
676     case GST_VIDEO_FORMAT_ARGB64:
677     case GST_VIDEO_FORMAT_AYUV64:
678       return 8;
679     default:
680       return 0;
681   }
682 }
683
684 /**
685  * gst_video_info_init:
686  * @info: a #GstVideoInfo
687  *
688  * Initialize @info with default values.
689  */
690 void
691 gst_video_info_init (GstVideoInfo * info)
692 {
693   g_return_if_fail (info != NULL);
694
695   memset (info, 0, sizeof (GstVideoInfo));
696 }
697
698 /**
699  * gst_video_info_set_format:
700  * @info: a #GstVideoInfo
701  * @format: the format
702  * @width: a width
703  * @height: a height
704  *
705  * Set the default info for a video frame of @format and @width and @height.
706  */
707 void
708 gst_video_info_set_format (GstVideoInfo * info, GstVideoFormat format,
709     guint width, guint height)
710 {
711   gint i;
712
713   g_return_if_fail (info != NULL);
714   g_return_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN);
715
716   info->format = format;
717   info->width = width;
718   info->height = height;
719
720   info->n_planes = formats[format].n_planes;
721   info->size = get_size (format, info->width, info->height);
722   fill_planes (info);
723
724   for (i = 0; i < info->n_planes; i++) {
725     info->plane[i].stride = get_stride (format, i, info->width);
726   }
727 }
728
729 /**
730  * gst_video_info_from_caps:
731  * @info: a #GstVideoInfo
732  * @caps: a #GstCaps
733  *
734  * Parse @caps and update @info.
735  *
736  * Returns: TRUE if @caps could be parsed
737  */
738 gboolean
739 gst_video_info_from_caps (GstVideoInfo * info, const GstCaps * caps)
740 {
741   GstStructure *structure;
742   const gchar *s;
743   GstVideoFormat format;
744   gint width, height;
745   gint fps_n, fps_d;
746   gboolean interlaced;
747   gint par_n, par_d;
748
749   g_return_val_if_fail (info != NULL, FALSE);
750   g_return_val_if_fail (caps != NULL, FALSE);
751   g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
752
753   structure = gst_caps_get_structure (caps, 0);
754
755   if (!gst_structure_has_name (structure, "video/x-raw"))
756     goto wrong_name;
757
758   if (!(s = gst_structure_get_string (structure, "format")))
759     goto no_format;
760
761   format = gst_video_format_from_string (s);
762   if (format == GST_VIDEO_FORMAT_UNKNOWN)
763     goto unknown_format;
764
765   if (!gst_structure_get_int (structure, "width", &width))
766     goto no_width;
767   if (!gst_structure_get_int (structure, "height", &height))
768     goto no_height;
769
770   gst_video_info_set_format (info, format, width, height);
771
772   if (gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d)) {
773     info->fps_n = fps_n;
774     info->fps_d = fps_d;
775   } else {
776     info->fps_n = 0;
777     info->fps_d = 1;
778   }
779
780   if (!gst_structure_get_boolean (structure, "interlaced", &interlaced))
781     interlaced = FALSE;
782   if (interlaced)
783     info->flags |= GST_VIDEO_FLAG_INTERLACED;
784   else
785     info->flags &= ~GST_VIDEO_FLAG_INTERLACED;
786
787   s = gst_structure_get_string (structure, "color-matrix");
788   if (s)
789     info->color_matrix = s;
790   else
791     info->color_matrix = "sdtv";
792
793   s = gst_structure_get_string (structure, "chroma-site");
794   if (s)
795     info->chroma_site = s;
796   else
797     info->chroma_site = "mpeg2";
798
799   if (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
800           &par_n, &par_d)) {
801     info->par_n = par_n;
802     info->par_d = par_d;
803   } else {
804     info->par_n = 1;
805     info->par_d = 1;
806   }
807   return TRUE;
808
809   /* ERROR */
810 wrong_name:
811   {
812     return FALSE;
813   }
814 no_format:
815   {
816     return FALSE;
817   }
818 unknown_format:
819   {
820     return FALSE;
821   }
822 no_width:
823   {
824     return FALSE;
825   }
826 no_height:
827   {
828     return FALSE;
829   }
830 }
831
832 /**
833  * gst_video_info_to_caps:
834  * @info: a #GstVideoInfo
835  *
836  * Convert the values of @info into a #GstCaps.
837  *
838  * Returns: a new #GstCaps containing the info of @info.
839  */
840 GstCaps *
841 gst_video_info_to_caps (GstVideoInfo * info)
842 {
843   GstCaps *caps;
844   const gchar *format;
845
846   g_return_val_if_fail (info != NULL, NULL);
847   g_return_val_if_fail (info->format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
848
849   format = gst_video_format_to_string (info->format);
850   g_return_val_if_fail (format != NULL, NULL);
851
852   caps = gst_caps_new_simple ("video/x-raw",
853       "format", G_TYPE_STRING, format,
854       "width", G_TYPE_INT, info->width,
855       "height", G_TYPE_INT, info->height,
856       "framerate", GST_TYPE_FRACTION, info->fps_n, info->fps_d,
857       "pixel-aspect-ratio", GST_TYPE_FRACTION, info->par_n, info->par_d, NULL);
858   if (info->flags & GST_VIDEO_FLAG_INTERLACED)
859     gst_caps_set_simple (caps, "interlaced", G_TYPE_BOOLEAN, TRUE, NULL);
860   if (info->color_matrix)
861     gst_caps_set_simple (caps, "color-matrix", G_TYPE_STRING,
862         info->color_matrix, NULL);
863   if (info->chroma_site)
864     gst_caps_set_simple (caps, "chromar-site", G_TYPE_STRING, info->chroma_site,
865         NULL);
866
867   return caps;
868 }
869
870 /**
871  * get_stride:
872  * @format: a #GstVideoFormat
873  * @component: the component index
874  * @width: the width of video
875  *
876  * Calculates the row stride (number of bytes from one row of pixels to
877  * the next) for the video component with an index of @component.  For
878  * YUV video, Y, U, and V have component indices of 0, 1, and 2,
879  * respectively.  For RGB video, R, G, and B have component indicies of
880  * 0, 1, and 2, respectively.  Alpha channels, if present, have a component
881  * index of 3.  The @width parameter always represents the width of the
882  * video, not the component.
883  *
884  * Since: 0.10.16
885  *
886  * Returns: row stride of component @component
887  */
888 static int
889 get_stride (GstVideoFormat format, int plane, int width)
890 {
891   switch (format) {
892     case GST_VIDEO_FORMAT_I420:
893     case GST_VIDEO_FORMAT_YV12:
894       if (plane == 0) {
895         return GST_ROUND_UP_4 (width);
896       } else {
897         return GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
898       }
899     case GST_VIDEO_FORMAT_YUY2:
900     case GST_VIDEO_FORMAT_YVYU:
901     case GST_VIDEO_FORMAT_UYVY:
902       return GST_ROUND_UP_4 (width * 2);
903     case GST_VIDEO_FORMAT_AYUV:
904     case GST_VIDEO_FORMAT_RGBx:
905     case GST_VIDEO_FORMAT_BGRx:
906     case GST_VIDEO_FORMAT_xRGB:
907     case GST_VIDEO_FORMAT_xBGR:
908     case GST_VIDEO_FORMAT_RGBA:
909     case GST_VIDEO_FORMAT_BGRA:
910     case GST_VIDEO_FORMAT_ARGB:
911     case GST_VIDEO_FORMAT_ABGR:
912     case GST_VIDEO_FORMAT_r210:
913       return width * 4;
914     case GST_VIDEO_FORMAT_RGB16:
915     case GST_VIDEO_FORMAT_BGR16:
916     case GST_VIDEO_FORMAT_RGB15:
917     case GST_VIDEO_FORMAT_BGR15:
918       return GST_ROUND_UP_4 (width * 2);
919     case GST_VIDEO_FORMAT_RGB:
920     case GST_VIDEO_FORMAT_BGR:
921     case GST_VIDEO_FORMAT_v308:
922       return GST_ROUND_UP_4 (width * 3);
923     case GST_VIDEO_FORMAT_Y41B:
924       if (plane == 0) {
925         return GST_ROUND_UP_4 (width);
926       } else {
927         return GST_ROUND_UP_16 (width) / 4;
928       }
929     case GST_VIDEO_FORMAT_Y42B:
930       if (plane == 0) {
931         return GST_ROUND_UP_4 (width);
932       } else {
933         return GST_ROUND_UP_8 (width) / 2;
934       }
935     case GST_VIDEO_FORMAT_Y444:
936       return GST_ROUND_UP_4 (width);
937     case GST_VIDEO_FORMAT_v210:
938       return ((width + 47) / 48) * 128;
939     case GST_VIDEO_FORMAT_v216:
940       return GST_ROUND_UP_8 (width * 4);
941     case GST_VIDEO_FORMAT_NV12:
942     case GST_VIDEO_FORMAT_NV21:
943       return GST_ROUND_UP_4 (width);
944     case GST_VIDEO_FORMAT_GRAY8:
945     case GST_VIDEO_FORMAT_Y800:
946       return GST_ROUND_UP_4 (width);
947     case GST_VIDEO_FORMAT_GRAY16_BE:
948     case GST_VIDEO_FORMAT_GRAY16_LE:
949     case GST_VIDEO_FORMAT_Y16:
950       return GST_ROUND_UP_4 (width * 2);
951     case GST_VIDEO_FORMAT_UYVP:
952       return GST_ROUND_UP_4 ((width * 2 * 5 + 3) / 4);
953     case GST_VIDEO_FORMAT_A420:
954       if (plane == 0 || plane == 3) {
955         return GST_ROUND_UP_4 (width);
956       } else {
957         return GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
958       }
959     case GST_VIDEO_FORMAT_RGB8_PALETTED:
960       return GST_ROUND_UP_4 (width);
961     case GST_VIDEO_FORMAT_YUV9:
962     case GST_VIDEO_FORMAT_YVU9:
963       if (plane == 0) {
964         return GST_ROUND_UP_4 (width);
965       } else {
966         return GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4);
967       }
968     case GST_VIDEO_FORMAT_IYU1:
969       return GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) +
970           GST_ROUND_UP_4 (width) / 2);
971     case GST_VIDEO_FORMAT_ARGB64:
972     case GST_VIDEO_FORMAT_AYUV64:
973       return width * 8;
974     default:
975       return 0;
976   }
977 }
978
979 #if 0
980 /**
981  * gst_video_format_get_component_width:
982  * @format: a #GstVideoFormat
983  * @component: the component index
984  * @width: the width of video
985  *
986  * Calculates the width of the component.  See
987  * @gst_video_format_get_row_stride for a description
988  * of the component index.
989  *
990  * Since: 0.10.16
991  *
992  * Returns: width of component @component
993  */
994 static int
995 gst_video_format_get_component_width (GstVideoFormat format,
996     int component, int width)
997 {
998   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
999   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1000   g_return_val_if_fail (width > 0, 0);
1001
1002   switch (format) {
1003     case GST_VIDEO_FORMAT_I420:
1004     case GST_VIDEO_FORMAT_YV12:
1005     case GST_VIDEO_FORMAT_YUY2:
1006     case GST_VIDEO_FORMAT_YVYU:
1007     case GST_VIDEO_FORMAT_UYVY:
1008     case GST_VIDEO_FORMAT_Y42B:
1009     case GST_VIDEO_FORMAT_v210:
1010     case GST_VIDEO_FORMAT_v216:
1011     case GST_VIDEO_FORMAT_NV12:
1012     case GST_VIDEO_FORMAT_NV21:
1013     case GST_VIDEO_FORMAT_UYVP:
1014       if (component == 0) {
1015         return width;
1016       } else {
1017         return GST_ROUND_UP_2 (width) / 2;
1018       }
1019     case GST_VIDEO_FORMAT_Y41B:
1020     case GST_VIDEO_FORMAT_YUV9:
1021     case GST_VIDEO_FORMAT_YVU9:
1022     case GST_VIDEO_FORMAT_IYU1:
1023       if (component == 0) {
1024         return width;
1025       } else {
1026         return GST_ROUND_UP_4 (width) / 4;
1027       }
1028     case GST_VIDEO_FORMAT_AYUV:
1029     case GST_VIDEO_FORMAT_RGBx:
1030     case GST_VIDEO_FORMAT_BGRx:
1031     case GST_VIDEO_FORMAT_xRGB:
1032     case GST_VIDEO_FORMAT_xBGR:
1033     case GST_VIDEO_FORMAT_RGBA:
1034     case GST_VIDEO_FORMAT_BGRA:
1035     case GST_VIDEO_FORMAT_ARGB:
1036     case GST_VIDEO_FORMAT_ABGR:
1037     case GST_VIDEO_FORMAT_RGB:
1038     case GST_VIDEO_FORMAT_BGR:
1039     case GST_VIDEO_FORMAT_RGB16:
1040     case GST_VIDEO_FORMAT_BGR16:
1041     case GST_VIDEO_FORMAT_RGB15:
1042     case GST_VIDEO_FORMAT_BGR15:
1043     case GST_VIDEO_FORMAT_Y444:
1044     case GST_VIDEO_FORMAT_v308:
1045     case GST_VIDEO_FORMAT_GRAY8:
1046     case GST_VIDEO_FORMAT_GRAY16_BE:
1047     case GST_VIDEO_FORMAT_GRAY16_LE:
1048     case GST_VIDEO_FORMAT_Y800:
1049     case GST_VIDEO_FORMAT_Y16:
1050     case GST_VIDEO_FORMAT_RGB8_PALETTED:
1051     case GST_VIDEO_FORMAT_ARGB64:
1052     case GST_VIDEO_FORMAT_AYUV64:
1053     case GST_VIDEO_FORMAT_r210:
1054       return width;
1055     case GST_VIDEO_FORMAT_A420:
1056       if (component == 0 || component == 3) {
1057         return width;
1058       } else {
1059         return GST_ROUND_UP_2 (width) / 2;
1060       }
1061     default:
1062       return 0;
1063   }
1064 }
1065 #endif
1066
1067 #if 0
1068 /**
1069  * gst_video_format_get_component_height:
1070  * @format: a #GstVideoFormat
1071  * @component: the component index
1072  * @height: the height of video
1073  *
1074  * Calculates the height of the component.  See
1075  * @gst_video_format_get_row_stride for a description
1076  * of the component index.
1077  *
1078  * Since: 0.10.16
1079  *
1080  * Returns: height of component @component
1081  */
1082 int
1083 gst_video_format_get_component_height (GstVideoFormat format,
1084     int component, int height)
1085 {
1086   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1087   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1088   g_return_val_if_fail (height > 0, 0);
1089
1090   switch (format) {
1091     case GST_VIDEO_FORMAT_I420:
1092     case GST_VIDEO_FORMAT_YV12:
1093     case GST_VIDEO_FORMAT_NV12:
1094     case GST_VIDEO_FORMAT_NV21:
1095       if (component == 0) {
1096         return height;
1097       } else {
1098         return GST_ROUND_UP_2 (height) / 2;
1099       }
1100     case GST_VIDEO_FORMAT_Y41B:
1101     case GST_VIDEO_FORMAT_Y42B:
1102     case GST_VIDEO_FORMAT_YUY2:
1103     case GST_VIDEO_FORMAT_YVYU:
1104     case GST_VIDEO_FORMAT_UYVY:
1105     case GST_VIDEO_FORMAT_AYUV:
1106     case GST_VIDEO_FORMAT_RGBx:
1107     case GST_VIDEO_FORMAT_BGRx:
1108     case GST_VIDEO_FORMAT_xRGB:
1109     case GST_VIDEO_FORMAT_xBGR:
1110     case GST_VIDEO_FORMAT_RGBA:
1111     case GST_VIDEO_FORMAT_BGRA:
1112     case GST_VIDEO_FORMAT_ARGB:
1113     case GST_VIDEO_FORMAT_ABGR:
1114     case GST_VIDEO_FORMAT_RGB:
1115     case GST_VIDEO_FORMAT_BGR:
1116     case GST_VIDEO_FORMAT_RGB16:
1117     case GST_VIDEO_FORMAT_BGR16:
1118     case GST_VIDEO_FORMAT_RGB15:
1119     case GST_VIDEO_FORMAT_BGR15:
1120     case GST_VIDEO_FORMAT_Y444:
1121     case GST_VIDEO_FORMAT_v210:
1122     case GST_VIDEO_FORMAT_v216:
1123     case GST_VIDEO_FORMAT_v308:
1124     case GST_VIDEO_FORMAT_GRAY8:
1125     case GST_VIDEO_FORMAT_GRAY16_BE:
1126     case GST_VIDEO_FORMAT_GRAY16_LE:
1127     case GST_VIDEO_FORMAT_Y800:
1128     case GST_VIDEO_FORMAT_Y16:
1129     case GST_VIDEO_FORMAT_UYVP:
1130     case GST_VIDEO_FORMAT_RGB8_PALETTED:
1131     case GST_VIDEO_FORMAT_IYU1:
1132     case GST_VIDEO_FORMAT_ARGB64:
1133     case GST_VIDEO_FORMAT_AYUV64:
1134     case GST_VIDEO_FORMAT_r210:
1135       return height;
1136     case GST_VIDEO_FORMAT_A420:
1137       if (component == 0 || component == 3) {
1138         return height;
1139       } else {
1140         return GST_ROUND_UP_2 (height) / 2;
1141       }
1142     case GST_VIDEO_FORMAT_YUV9:
1143     case GST_VIDEO_FORMAT_YVU9:
1144       if (component == 0) {
1145         return height;
1146       } else {
1147         return GST_ROUND_UP_4 (height) / 4;
1148       }
1149     default:
1150       return 0;
1151   }
1152 }
1153 #endif
1154
1155 #if 0
1156 /**
1157  * get_component_offset:
1158  * @format: a #GstVideoFormat
1159  * @component: the component index
1160  * @width: the width of video
1161  * @height: the height of video
1162  *
1163  * Calculates the offset (in bytes) of the first pixel of the component
1164  * with index @component.  For packed formats, this will typically be a
1165  * small integer (0, 1, 2, 3).  For planar formats, this will be a
1166  * (relatively) large offset to the beginning of the second or third
1167  * component planes.  See @gst_video_format_get_row_stride for a description
1168  * of the component index.
1169  *
1170  * Since: 0.10.16
1171  *
1172  * Returns: offset of component @component
1173  */
1174 static int
1175 get_component_offset (GstVideoFormat format,
1176     int component, int width, int height)
1177 {
1178   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1179   g_return_val_if_fail (component >= 0 && component <= 3, 0);
1180   g_return_val_if_fail ((!gst_video_format_is_yuv (format)) || (width > 0
1181           && height > 0), 0);
1182
1183   switch (format) {
1184     case GST_VIDEO_FORMAT_I420:
1185       if (component == 0)
1186         return 0;
1187       if (component == 1)
1188         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1189       if (component == 2) {
1190         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) +
1191             GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1192             (GST_ROUND_UP_2 (height) / 2);
1193       }
1194       break;
1195     case GST_VIDEO_FORMAT_YV12:        /* same as I420, but components 1+2 swapped */
1196       if (component == 0)
1197         return 0;
1198       if (component == 2)
1199         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1200       if (component == 1) {
1201         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) +
1202             GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1203             (GST_ROUND_UP_2 (height) / 2);
1204       }
1205       break;
1206     case GST_VIDEO_FORMAT_YUY2:
1207       if (component == 0)
1208         return 0;
1209       if (component == 1)
1210         return 1;
1211       if (component == 2)
1212         return 3;
1213       break;
1214     case GST_VIDEO_FORMAT_YVYU:
1215       if (component == 0)
1216         return 0;
1217       if (component == 1)
1218         return 3;
1219       if (component == 2)
1220         return 1;
1221       break;
1222     case GST_VIDEO_FORMAT_UYVY:
1223       if (component == 0)
1224         return 1;
1225       if (component == 1)
1226         return 0;
1227       if (component == 2)
1228         return 2;
1229       break;
1230     case GST_VIDEO_FORMAT_AYUV:
1231       if (component == 0)
1232         return 1;
1233       if (component == 1)
1234         return 2;
1235       if (component == 2)
1236         return 3;
1237       if (component == 3)
1238         return 0;
1239       break;
1240     case GST_VIDEO_FORMAT_RGBx:
1241     case GST_VIDEO_FORMAT_RGBA:
1242       if (component == 0)
1243         return 0;
1244       if (component == 1)
1245         return 1;
1246       if (component == 2)
1247         return 2;
1248       if (component == 3)
1249         return 3;
1250       break;
1251     case GST_VIDEO_FORMAT_BGRx:
1252     case GST_VIDEO_FORMAT_BGRA:
1253       if (component == 0)
1254         return 2;
1255       if (component == 1)
1256         return 1;
1257       if (component == 2)
1258         return 0;
1259       if (component == 3)
1260         return 3;
1261       break;
1262     case GST_VIDEO_FORMAT_xRGB:
1263     case GST_VIDEO_FORMAT_ARGB:
1264       if (component == 0)
1265         return 1;
1266       if (component == 1)
1267         return 2;
1268       if (component == 2)
1269         return 3;
1270       if (component == 3)
1271         return 0;
1272       break;
1273     case GST_VIDEO_FORMAT_xBGR:
1274     case GST_VIDEO_FORMAT_ABGR:
1275       if (component == 0)
1276         return 3;
1277       if (component == 1)
1278         return 2;
1279       if (component == 2)
1280         return 1;
1281       if (component == 3)
1282         return 0;
1283       break;
1284     case GST_VIDEO_FORMAT_RGB:
1285     case GST_VIDEO_FORMAT_v308:
1286       if (component == 0)
1287         return 0;
1288       if (component == 1)
1289         return 1;
1290       if (component == 2)
1291         return 2;
1292       break;
1293     case GST_VIDEO_FORMAT_BGR:
1294       if (component == 0)
1295         return 2;
1296       if (component == 1)
1297         return 1;
1298       if (component == 2)
1299         return 0;
1300       break;
1301     case GST_VIDEO_FORMAT_Y41B:
1302       if (component == 0)
1303         return 0;
1304       if (component == 1)
1305         return GST_ROUND_UP_4 (width) * height;
1306       if (component == 2)
1307         return (GST_ROUND_UP_4 (width) +
1308             (GST_ROUND_UP_16 (width) / 4)) * height;
1309       break;
1310     case GST_VIDEO_FORMAT_Y42B:
1311       if (component == 0)
1312         return 0;
1313       if (component == 1)
1314         return GST_ROUND_UP_4 (width) * height;
1315       if (component == 2)
1316         return (GST_ROUND_UP_4 (width) + (GST_ROUND_UP_8 (width) / 2)) * height;
1317       break;
1318     case GST_VIDEO_FORMAT_Y444:
1319       return GST_ROUND_UP_4 (width) * height * component;
1320     case GST_VIDEO_FORMAT_v210:
1321     case GST_VIDEO_FORMAT_r210:
1322       /* v210 is bit-packed, so this doesn't make sense */
1323       return 0;
1324     case GST_VIDEO_FORMAT_v216:
1325       if (component == 0)
1326         return 0;
1327       if (component == 1)
1328         return 2;
1329       if (component == 2)
1330         return 6;
1331       break;
1332     case GST_VIDEO_FORMAT_NV12:
1333       if (component == 0)
1334         return 0;
1335       if (component == 1)
1336         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1337       if (component == 2)
1338         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) + 1;
1339       break;
1340     case GST_VIDEO_FORMAT_NV21:
1341       if (component == 0)
1342         return 0;
1343       if (component == 1)
1344         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) + 1;
1345       if (component == 2)
1346         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1347       break;
1348     case GST_VIDEO_FORMAT_GRAY8:
1349     case GST_VIDEO_FORMAT_GRAY16_BE:
1350     case GST_VIDEO_FORMAT_GRAY16_LE:
1351     case GST_VIDEO_FORMAT_Y800:
1352     case GST_VIDEO_FORMAT_Y16:
1353       return 0;
1354     case GST_VIDEO_FORMAT_UYVP:
1355       /* UYVP is bit-packed, so this doesn't make sense */
1356       return 0;
1357     case GST_VIDEO_FORMAT_A420:
1358       if (component == 0)
1359         return 0;
1360       if (component == 1)
1361         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1362       if (component == 2) {
1363         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) +
1364             GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1365             (GST_ROUND_UP_2 (height) / 2);
1366       }
1367       if (component == 3) {
1368         return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) +
1369             2 * GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1370             (GST_ROUND_UP_2 (height) / 2);
1371       }
1372       break;
1373     case GST_VIDEO_FORMAT_RGB8_PALETTED:
1374       return 0;
1375     case GST_VIDEO_FORMAT_YUV9:
1376       if (component == 0)
1377         return 0;
1378       if (component == 1)
1379         return GST_ROUND_UP_4 (width) * height;
1380       if (component == 2) {
1381         return GST_ROUND_UP_4 (width) * height +
1382             GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4) *
1383             (GST_ROUND_UP_4 (height) / 4);
1384       }
1385       break;
1386     case GST_VIDEO_FORMAT_YVU9:
1387       if (component == 0)
1388         return 0;
1389       if (component == 1) {
1390         return GST_ROUND_UP_4 (width) * height +
1391             GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4) *
1392             (GST_ROUND_UP_4 (height) / 4);
1393       }
1394       if (component == 2)
1395         return GST_ROUND_UP_4 (width) * height;
1396       break;
1397     case GST_VIDEO_FORMAT_IYU1:
1398       if (component == 0)
1399         return 1;
1400       if (component == 1)
1401         return 0;
1402       if (component == 2)
1403         return 4;
1404       break;
1405     case GST_VIDEO_FORMAT_ARGB64:
1406     case GST_VIDEO_FORMAT_AYUV64:
1407       if (component == 0)
1408         return 2;
1409       if (component == 1)
1410         return 4;
1411       if (component == 2)
1412         return 6;
1413       if (component == 3)
1414         return 0;
1415       break;
1416     default:
1417       break;
1418   }
1419   GST_WARNING ("unhandled format %d or component %d", format, component);
1420   return 0;
1421 }
1422 #endif
1423
1424 /**
1425  * get_plane_offset:
1426  * @format: a #GstVideoFormat
1427  * @plane: the plane index
1428  * @width: the width of video
1429  * @height: the height of video
1430  *
1431  * Calculates the offset (in bytes) of the first pixel of the plane
1432  * with index @plane.  For packed formats, this will typically be 0.
1433  * For planar formats, this will be a (relatively) large offset to the
1434  * beginning of the second or third plane planes.
1435  * See @gst_video_format_get_row_stride for a description
1436  * of the plane index.
1437  *
1438  * Since: 0.10.16
1439  *
1440  * Returns: offset of plane @plane
1441  */
1442 static int
1443 fill_planes (GstVideoInfo * info)
1444 {
1445   int width;
1446   int height;
1447
1448   width = info->width;
1449   height = info->height;
1450
1451   switch (info->format) {
1452     case GST_VIDEO_FORMAT_YUY2:
1453     case GST_VIDEO_FORMAT_YVYU:
1454     case GST_VIDEO_FORMAT_UYVY:
1455     case GST_VIDEO_FORMAT_AYUV:
1456     case GST_VIDEO_FORMAT_RGBx:
1457     case GST_VIDEO_FORMAT_RGBA:
1458     case GST_VIDEO_FORMAT_BGRx:
1459     case GST_VIDEO_FORMAT_BGRA:
1460     case GST_VIDEO_FORMAT_xRGB:
1461     case GST_VIDEO_FORMAT_ARGB:
1462     case GST_VIDEO_FORMAT_xBGR:
1463     case GST_VIDEO_FORMAT_ABGR:
1464     case GST_VIDEO_FORMAT_RGB:
1465     case GST_VIDEO_FORMAT_v308:
1466     case GST_VIDEO_FORMAT_BGR:
1467     case GST_VIDEO_FORMAT_v210:
1468     case GST_VIDEO_FORMAT_r210:
1469     case GST_VIDEO_FORMAT_v216:
1470     case GST_VIDEO_FORMAT_GRAY8:
1471     case GST_VIDEO_FORMAT_GRAY16_BE:
1472     case GST_VIDEO_FORMAT_GRAY16_LE:
1473     case GST_VIDEO_FORMAT_Y800:
1474     case GST_VIDEO_FORMAT_Y16:
1475     case GST_VIDEO_FORMAT_UYVP:
1476     case GST_VIDEO_FORMAT_RGB8_PALETTED:
1477     case GST_VIDEO_FORMAT_IYU1:
1478     case GST_VIDEO_FORMAT_ARGB64:
1479     case GST_VIDEO_FORMAT_AYUV64:
1480       info->n_planes = 1;
1481       info->plane[0].offset = 0;
1482       break;
1483     case GST_VIDEO_FORMAT_I420:
1484       info->n_planes = 3;
1485       info->plane[0].offset = 0;
1486       info->plane[1].offset = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1487       info->plane[2].offset = info->plane[1].offset +
1488           GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1489           (GST_ROUND_UP_2 (height) / 2);
1490       break;
1491     case GST_VIDEO_FORMAT_YV12:        /* same as I420, but plane 1+2 swapped */
1492       info->n_planes = 3;
1493       info->plane[0].offset = 0;
1494       info->plane[2].offset = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1495       info->plane[1].offset = info->plane[2].offset +
1496           GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1497           (GST_ROUND_UP_2 (height) / 2);
1498       break;
1499     case GST_VIDEO_FORMAT_Y41B:
1500       info->n_planes = 3;
1501       info->plane[0].offset = 0;
1502       info->plane[1].offset = GST_ROUND_UP_4 (width) * height;
1503       info->plane[2].offset = (GST_ROUND_UP_4 (width) +
1504           (GST_ROUND_UP_16 (width) / 4)) * height;
1505       break;
1506     case GST_VIDEO_FORMAT_Y42B:
1507       info->n_planes = 3;
1508       info->plane[0].offset = 0;
1509       info->plane[1].offset = GST_ROUND_UP_4 (width) * height;
1510       info->plane[2].offset =
1511           (GST_ROUND_UP_4 (width) + (GST_ROUND_UP_8 (width) / 2)) * height;
1512       break;
1513     case GST_VIDEO_FORMAT_Y444:
1514       info->n_planes = 3;
1515       info->plane[0].offset = 0;
1516       info->plane[1].offset = GST_ROUND_UP_4 (width) * height;
1517       info->plane[2].offset = GST_ROUND_UP_4 (width) * height * 2;
1518       break;
1519     case GST_VIDEO_FORMAT_NV12:
1520     case GST_VIDEO_FORMAT_NV21:
1521       info->n_planes = 2;
1522       info->plane[0].offset = 0;
1523       info->plane[1].offset = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1524       break;
1525     case GST_VIDEO_FORMAT_A420:
1526       info->n_planes = 4;
1527       info->plane[0].offset = 0;
1528       info->plane[1].offset = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1529       info->plane[2].offset = info->plane[1].offset +
1530           GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1531           (GST_ROUND_UP_2 (height) / 2);
1532       info->plane[3].offset = info->plane[2].offset +
1533           GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1534           (GST_ROUND_UP_2 (height) / 2);
1535       break;
1536     case GST_VIDEO_FORMAT_YUV9:
1537       info->n_planes = 3;
1538       info->plane[0].offset = 0;
1539       info->plane[1].offset = GST_ROUND_UP_4 (width) * height;
1540       info->plane[2].offset = info->plane[1].offset +
1541           GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4) *
1542           (GST_ROUND_UP_4 (height) / 4);
1543       break;
1544     case GST_VIDEO_FORMAT_YVU9:
1545       info->n_planes = 3;
1546       info->plane[0].offset = 0;
1547       info->plane[2].offset = GST_ROUND_UP_4 (width) * height;
1548       info->plane[1].offset = info->plane[2].offset +
1549           GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4) *
1550           (GST_ROUND_UP_4 (height) / 4);
1551       break;
1552     default:
1553       break;
1554   }
1555   GST_WARNING ("unhandled format %d", info->format);
1556   return 0;
1557 }
1558
1559 /**
1560  * get_size:
1561  * @format: a #GstVideoFormat
1562  * @width: the width of video
1563  * @height: the height of video
1564  *
1565  * Calculates the total number of bytes in the raw video format.  This
1566  * number should be used when allocating a buffer for raw video.
1567  *
1568  * Returns: size (in bytes) of raw video format
1569  */
1570 static int
1571 get_size (GstVideoFormat format, int width, int height)
1572 {
1573   int size;
1574
1575   g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1576   g_return_val_if_fail (width > 0 && height > 0, 0);
1577
1578   switch (format) {
1579     case GST_VIDEO_FORMAT_I420:
1580     case GST_VIDEO_FORMAT_YV12:
1581       size = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1582       size += GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1583           (GST_ROUND_UP_2 (height) / 2) * 2;
1584       return size;
1585     case GST_VIDEO_FORMAT_IYU1:
1586       return GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) +
1587           GST_ROUND_UP_4 (width) / 2) * height;
1588     case GST_VIDEO_FORMAT_YUY2:
1589     case GST_VIDEO_FORMAT_YVYU:
1590     case GST_VIDEO_FORMAT_UYVY:
1591       return GST_ROUND_UP_4 (width * 2) * height;
1592     case GST_VIDEO_FORMAT_AYUV:
1593     case GST_VIDEO_FORMAT_RGBx:
1594     case GST_VIDEO_FORMAT_BGRx:
1595     case GST_VIDEO_FORMAT_xRGB:
1596     case GST_VIDEO_FORMAT_xBGR:
1597     case GST_VIDEO_FORMAT_RGBA:
1598     case GST_VIDEO_FORMAT_BGRA:
1599     case GST_VIDEO_FORMAT_ARGB:
1600     case GST_VIDEO_FORMAT_ABGR:
1601     case GST_VIDEO_FORMAT_r210:
1602       return width * 4 * height;
1603     case GST_VIDEO_FORMAT_RGB16:
1604     case GST_VIDEO_FORMAT_BGR16:
1605     case GST_VIDEO_FORMAT_RGB15:
1606     case GST_VIDEO_FORMAT_BGR15:
1607       return GST_ROUND_UP_4 (width * 2) * height;
1608     case GST_VIDEO_FORMAT_RGB:
1609     case GST_VIDEO_FORMAT_BGR:
1610     case GST_VIDEO_FORMAT_v308:
1611       return GST_ROUND_UP_4 (width * 3) * height;
1612     case GST_VIDEO_FORMAT_Y41B:
1613       /* simplification of ROUNDUP4(w)*h + 2*((ROUNDUP16(w)/4)*h */
1614       return (GST_ROUND_UP_4 (width) + (GST_ROUND_UP_16 (width) / 2)) * height;
1615     case GST_VIDEO_FORMAT_Y42B:
1616       /* simplification of ROUNDUP4(w)*h + 2*(ROUNDUP8(w)/2)*h */
1617       return (GST_ROUND_UP_4 (width) + GST_ROUND_UP_8 (width)) * height;
1618     case GST_VIDEO_FORMAT_Y444:
1619       return GST_ROUND_UP_4 (width) * height * 3;
1620     case GST_VIDEO_FORMAT_v210:
1621       return ((width + 47) / 48) * 128 * height;
1622     case GST_VIDEO_FORMAT_v216:
1623       return GST_ROUND_UP_8 (width * 4) * height;
1624     case GST_VIDEO_FORMAT_NV12:
1625     case GST_VIDEO_FORMAT_NV21:
1626       return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) * 3 / 2;
1627     case GST_VIDEO_FORMAT_GRAY8:
1628     case GST_VIDEO_FORMAT_Y800:
1629     case GST_VIDEO_FORMAT_RGB8_PALETTED:
1630       return GST_ROUND_UP_4 (width) * height;
1631     case GST_VIDEO_FORMAT_GRAY16_BE:
1632     case GST_VIDEO_FORMAT_GRAY16_LE:
1633     case GST_VIDEO_FORMAT_Y16:
1634       return GST_ROUND_UP_4 (width * 2) * height;
1635     case GST_VIDEO_FORMAT_UYVP:
1636       return GST_ROUND_UP_4 ((width * 2 * 5 + 3) / 4) * height;
1637     case GST_VIDEO_FORMAT_A420:
1638       size = 2 * GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
1639       size += GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) *
1640           (GST_ROUND_UP_2 (height) / 2) * 2;
1641       return size;
1642     case GST_VIDEO_FORMAT_YUV9:
1643     case GST_VIDEO_FORMAT_YVU9:
1644       size = GST_ROUND_UP_4 (width) * height;
1645       size += GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4) *
1646           (GST_ROUND_UP_4 (height) / 4) * 2;
1647       return size;
1648     case GST_VIDEO_FORMAT_ARGB64:
1649     case GST_VIDEO_FORMAT_AYUV64:
1650       return width * 8 * height;
1651     default:
1652       return 0;
1653   }
1654 }
1655
1656 /**
1657  * gst_video_format_convert:
1658  * @info: a #GstVideoInfo
1659  * @src_format: #GstFormat of the @src_value
1660  * @src_value: value to convert
1661  * @dest_format: #GstFormat of the @dest_value
1662  * @dest_value: pointer to destination value
1663  *
1664  * Converts among various #GstFormat types.  This function handles
1665  * GST_FORMAT_BYTES, GST_FORMAT_TIME, and GST_FORMAT_DEFAULT.  For
1666  * raw video, GST_FORMAT_DEFAULT corresponds to video frames.  This
1667  * function can be used to handle pad queries of the type GST_QUERY_CONVERT.
1668  *
1669  * Since: 0.10.16
1670  *
1671  * Returns: TRUE if the conversion was successful.
1672  */
1673 gboolean
1674 gst_video_info_convert (GstVideoInfo * info,
1675     GstFormat src_format, gint64 src_value,
1676     GstFormat dest_format, gint64 * dest_value)
1677 {
1678   gboolean ret = FALSE;
1679   int size, fps_n, fps_d;
1680
1681   g_return_val_if_fail (info != NULL, 0);
1682   g_return_val_if_fail (info->format != GST_VIDEO_FORMAT_UNKNOWN, 0);
1683   g_return_val_if_fail (info->size > 0, 0);
1684
1685   size = info->size;
1686   fps_n = info->fps_n;
1687   fps_d = info->fps_d;
1688
1689   GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s to %s",
1690       src_value, gst_format_get_name (src_format),
1691       gst_format_get_name (dest_format));
1692
1693   if (src_format == dest_format) {
1694     *dest_value = src_value;
1695     ret = TRUE;
1696     goto done;
1697   }
1698
1699   if (src_value == -1) {
1700     *dest_value = -1;
1701     ret = TRUE;
1702     goto done;
1703   }
1704
1705   /* bytes to frames */
1706   if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_DEFAULT) {
1707     if (size != 0) {
1708       *dest_value = gst_util_uint64_scale_int (src_value, 1, size);
1709     } else {
1710       GST_ERROR ("blocksize is 0");
1711       *dest_value = 0;
1712     }
1713     ret = TRUE;
1714     goto done;
1715   }
1716
1717   /* frames to bytes */
1718   if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_BYTES) {
1719     *dest_value = gst_util_uint64_scale_int (src_value, size, 1);
1720     ret = TRUE;
1721     goto done;
1722   }
1723
1724   /* time to frames */
1725   if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_DEFAULT) {
1726     if (fps_d != 0) {
1727       *dest_value = gst_util_uint64_scale (src_value,
1728           fps_n, GST_SECOND * fps_d);
1729     } else {
1730       GST_ERROR ("framerate denominator is 0");
1731       *dest_value = 0;
1732     }
1733     ret = TRUE;
1734     goto done;
1735   }
1736
1737   /* frames to time */
1738   if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
1739     if (fps_n != 0) {
1740       *dest_value = gst_util_uint64_scale (src_value,
1741           GST_SECOND * fps_d, fps_n);
1742     } else {
1743       GST_ERROR ("framerate numerator is 0");
1744       *dest_value = 0;
1745     }
1746     ret = TRUE;
1747     goto done;
1748   }
1749
1750   /* time to bytes */
1751   if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) {
1752     if (fps_d != 0) {
1753       *dest_value = gst_util_uint64_scale (src_value,
1754           fps_n * size, GST_SECOND * fps_d);
1755     } else {
1756       GST_ERROR ("framerate denominator is 0");
1757       *dest_value = 0;
1758     }
1759     ret = TRUE;
1760     goto done;
1761   }
1762
1763   /* bytes to time */
1764   if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_TIME) {
1765     if (fps_n != 0 && size != 0) {
1766       *dest_value = gst_util_uint64_scale (src_value,
1767           GST_SECOND * fps_d, fps_n * size);
1768     } else {
1769       GST_ERROR ("framerate denominator and/or blocksize is 0");
1770       *dest_value = 0;
1771     }
1772     ret = TRUE;
1773   }
1774
1775 done:
1776
1777   GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, ret, *dest_value);
1778
1779   return ret;
1780 }
1781
1782 #define GST_VIDEO_EVENT_STILL_STATE_NAME "GstEventStillFrame"
1783
1784 /**
1785  * gst_video_event_new_still_frame:
1786  * @in_still: boolean value for the still-frame state of the event.
1787  *
1788  * Creates a new Still Frame event. If @in_still is %TRUE, then the event
1789  * represents the start of a still frame sequence. If it is %FALSE, then
1790  * the event ends a still frame sequence.
1791  *
1792  * To parse an event created by gst_video_event_new_still_frame() use
1793  * gst_video_event_parse_still_frame().
1794  *
1795  * Returns: The new GstEvent
1796  * Since: 0.10.26
1797  */
1798 GstEvent *
1799 gst_video_event_new_still_frame (gboolean in_still)
1800 {
1801   GstEvent *still_event;
1802   GstStructure *s;
1803
1804   s = gst_structure_new (GST_VIDEO_EVENT_STILL_STATE_NAME,
1805       "still-state", G_TYPE_BOOLEAN, in_still, NULL);
1806   still_event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
1807
1808   return still_event;
1809 }
1810
1811 /**
1812  * gst_video_event_parse_still_frame:
1813  * @event: A #GstEvent to parse
1814  * @in_still: A boolean to receive the still-frame status from the event, or NULL
1815  *
1816  * Parse a #GstEvent, identify if it is a Still Frame event, and
1817  * return the still-frame state from the event if it is.
1818  * If the event represents the start of a still frame, the in_still
1819  * variable will be set to TRUE, otherwise FALSE. It is OK to pass NULL for the
1820  * in_still variable order to just check whether the event is a valid still-frame
1821  * event.
1822  *
1823  * Create a still frame event using gst_video_event_new_still_frame()
1824  *
1825  * Returns: %TRUE if the event is a valid still-frame event. %FALSE if not
1826  * Since: 0.10.26
1827  */
1828 gboolean
1829 gst_video_event_parse_still_frame (GstEvent * event, gboolean * in_still)
1830 {
1831   const GstStructure *s;
1832   gboolean ev_still_state;
1833
1834   g_return_val_if_fail (event != NULL, FALSE);
1835
1836   if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_DOWNSTREAM)
1837     return FALSE;               /* Not a still frame event */
1838
1839   s = gst_event_get_structure (event);
1840   if (s == NULL
1841       || !gst_structure_has_name (s, GST_VIDEO_EVENT_STILL_STATE_NAME))
1842     return FALSE;               /* Not a still frame event */
1843   if (!gst_structure_get_boolean (s, "still-state", &ev_still_state))
1844     return FALSE;               /* Not a still frame event */
1845   if (in_still)
1846     *in_still = ev_still_state;
1847   return TRUE;
1848 }
1849
1850 #if 0
1851 /**
1852  * gst_video_parse_caps_palette:
1853  * @caps: #GstCaps to parse
1854  *
1855  * Returns the palette data from the caps as a #GstBuffer. For
1856  * #GST_VIDEO_FORMAT_RGB8_PALETTED this is containing 256 #guint32
1857  * values, each containing ARGB colors in native endianness.
1858  *
1859  * Returns: a #GstBuffer containing the palette data. Unref after usage.
1860  * Since: 0.10.32
1861  */
1862 GstBuffer *
1863 gst_video_parse_caps_palette (GstCaps * caps)
1864 {
1865   GstStructure *s;
1866   const GValue *p_v;
1867   GstBuffer *p;
1868
1869   if (!gst_caps_is_fixed (caps))
1870     return NULL;
1871
1872   s = gst_caps_get_structure (caps, 0);
1873
1874   p_v = gst_structure_get_value (s, "palette_data");
1875   if (!p_v || !GST_VALUE_HOLDS_BUFFER (p_v))
1876     return NULL;
1877
1878   p = gst_buffer_ref (gst_value_get_buffer (p_v));
1879
1880   return p;
1881 }
1882 #endif