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., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25
26 #include <string.h>
27 #include <stdio.h>
28
29 #include "video.h"
30 #include "gstvideometa.h"
31
32 /**
33 * SECTION:gstvideo
34 * @title: GstVideo
35 * @short_description: Support library for video operations
36 *
37 * This library contains some helper functions and includes the
38 * videosink and videofilter base classes.
39 */
40
41 /**
42 * gst_video_calculate_display_ratio:
43 * @dar_n: (out): Numerator of the calculated display_ratio
44 * @dar_d: (out): Denominator of the calculated display_ratio
45 * @video_width: Width of the video frame in pixels
46 * @video_height: Height of the video frame in pixels
47 * @video_par_n: Numerator of the pixel aspect ratio of the input video.
48 * @video_par_d: Denominator of the pixel aspect ratio of the input video.
49 * @display_par_n: Numerator of the pixel aspect ratio of the display device
50 * @display_par_d: Denominator of the pixel aspect ratio of the display device
51 *
52 * Given the Pixel Aspect Ratio and size of an input video frame, and the
53 * pixel aspect ratio of the intended display device, calculates the actual
54 * display ratio the video will be rendered with.
55 *
56 * Returns: A boolean indicating success and a calculated Display Ratio in the
57 * dar_n and dar_d parameters.
58 * The return value is FALSE in the case of integer overflow or other error.
59 */
60 gboolean
gst_video_calculate_display_ratio(guint * dar_n,guint * dar_d,guint video_width,guint video_height,guint video_par_n,guint video_par_d,guint display_par_n,guint display_par_d)61 gst_video_calculate_display_ratio (guint * dar_n, guint * dar_d,
62 guint video_width, guint video_height,
63 guint video_par_n, guint video_par_d,
64 guint display_par_n, guint display_par_d)
65 {
66 gint num, den;
67 gint tmp_n, tmp_d;
68
69 g_return_val_if_fail (dar_n != NULL, FALSE);
70 g_return_val_if_fail (dar_d != NULL, FALSE);
71
72 /* Calculate (video_width * video_par_n * display_par_d) /
73 * (video_height * video_par_d * display_par_n) */
74 if (!gst_util_fraction_multiply (video_width, video_height, video_par_n,
75 video_par_d, &tmp_n, &tmp_d))
76 goto error_overflow;
77
78 if (!gst_util_fraction_multiply (tmp_n, tmp_d, display_par_d, display_par_n,
79 &num, &den))
80 goto error_overflow;
81
82 g_return_val_if_fail (num > 0, FALSE);
83 g_return_val_if_fail (den > 0, FALSE);
84
85 *dar_n = num;
86 *dar_d = den;
87
88 return TRUE;
89
90 /* ERRORS */
91 error_overflow:
92 {
93 GST_WARNING ("overflow in multiply");
94 return FALSE;
95 }
96 }
97
98 /**
99 * gst_video_guess_framerate:
100 * @duration: Nominal duration of one frame
101 * @dest_n: (out) (allow-none): Numerator of the calculated framerate
102 * @dest_d: (out) (allow-none): Denominator of the calculated framerate
103 *
104 * Given the nominal duration of one video frame,
105 * this function will check some standard framerates for
106 * a close match (within 0.1%) and return one if possible,
107 *
108 * It will calculate an arbitrary framerate if no close
109 * match was found, and return %FALSE.
110 *
111 * It returns %FALSE if a duration of 0 is passed.
112 *
113 * Returns: %TRUE if a close "standard" framerate was
114 * recognised, and %FALSE otherwise.
115 *
116 * Since: 1.6
117 */
118 gboolean
gst_video_guess_framerate(GstClockTime duration,gint * dest_n,gint * dest_d)119 gst_video_guess_framerate (GstClockTime duration, gint * dest_n, gint * dest_d)
120 {
121 const int common_den[] = { 1, 2, 3, 4, 1001 };
122 int best_n, best_d, gcd;
123 guint64 best_error = G_MAXUINT64;
124 guint64 a;
125 int i;
126
127 if (G_UNLIKELY (duration == 0))
128 return FALSE;
129
130 /* Use a limited precision conversion by default for more sensible results,
131 * unless the frame duration is absurdly small (high speed cameras?) */
132 if (duration > 100000) {
133 best_n = GST_SECOND / 10000;
134 best_d = duration / 10000;
135 } else {
136 best_n = GST_SECOND;
137 best_d = duration;
138 }
139
140 for (i = 0; i < G_N_ELEMENTS (common_den); i++) {
141 gint d = common_den[i];
142 gint n = gst_util_uint64_scale_round (d, GST_SECOND, duration);
143
144 /* For NTSC framerates, round to the nearest 1000 fps */
145 if (d == 1001) {
146 n += 500;
147 n -= (n % 1000);
148 }
149
150 if (n > 0) {
151 /* See what duration the given framerate should be */
152 a = gst_util_uint64_scale_int (GST_SECOND, d, n);
153 /* Compute absolute error */
154 a = (a < duration) ? (duration - a) : (a - duration);
155 if (a < 2) {
156 /* Really precise - take this option */
157 if (dest_n)
158 *dest_n = n;
159 if (dest_d)
160 *dest_d = d;
161 return TRUE;
162 }
163 /* If within 0.1%, remember this denominator */
164 if (a * 1000 < duration && a < best_error) {
165 best_error = a;
166 best_n = n;
167 best_d = d;
168 }
169 }
170 }
171
172 /* set results */
173 gcd = gst_util_greatest_common_divisor (best_n, best_d);
174 if (gcd) {
175 best_n /= gcd;
176 best_d /= gcd;
177 }
178 if (dest_n)
179 *dest_n = best_n;
180 if (dest_d)
181 *dest_d = best_d;
182
183 return (best_error != G_MAXUINT64);
184 }
185
186
187 /**
188 * gst_video_alignment_reset:
189 * @align: a #GstVideoAlignment
190 *
191 * Set @align to its default values with no padding and no alignment.
192 */
193 void
gst_video_alignment_reset(GstVideoAlignment * align)194 gst_video_alignment_reset (GstVideoAlignment * align)
195 {
196 gint i;
197
198 g_return_if_fail (align != NULL);
199
200 align->padding_top = 0;
201 align->padding_bottom = 0;
202 align->padding_left = 0;
203 align->padding_right = 0;
204 for (i = 0; i < GST_VIDEO_MAX_PLANES; i++)
205 align->stride_align[i] = 0;
206 }
207
208 /**
209 * gst_video_orientation_from_tag:
210 * @taglist: A #GstTagList
211 * @method: (out): The location where to return the orientation.
212 *
213 * Parses the "image-orientation" tag and transforms it into the
214 * #GstVideoOrientationMethod enum.
215 *
216 * Returns: TRUE if there was a valid "image-orientation" tag in the taglist.
217 *
218 * Since: 1.20
219 */
220 gboolean
gst_video_orientation_from_tag(GstTagList * taglist,GstVideoOrientationMethod * method)221 gst_video_orientation_from_tag (GstTagList * taglist,
222 GstVideoOrientationMethod * method)
223 {
224 gchar *orientation;
225 gboolean ret = TRUE;
226
227 g_return_val_if_fail (GST_IS_TAG_LIST (taglist), FALSE);
228 g_return_val_if_fail (method != NULL, FALSE);
229
230 if (!gst_tag_list_get_string (taglist, "image-orientation", &orientation))
231 return FALSE;
232
233 if (!g_strcmp0 ("rotate-0", orientation))
234 *method = GST_VIDEO_ORIENTATION_IDENTITY;
235 else if (!g_strcmp0 ("rotate-90", orientation))
236 *method = GST_VIDEO_ORIENTATION_90R;
237 else if (!g_strcmp0 ("rotate-180", orientation))
238 *method = GST_VIDEO_ORIENTATION_180;
239 else if (!g_strcmp0 ("rotate-270", orientation))
240 *method = GST_VIDEO_ORIENTATION_90L;
241 else if (!g_strcmp0 ("flip-rotate-0", orientation))
242 *method = GST_VIDEO_ORIENTATION_HORIZ;
243 else if (!g_strcmp0 ("flip-rotate-90", orientation))
244 *method = GST_VIDEO_ORIENTATION_UR_LL;
245 else if (!g_strcmp0 ("flip-rotate-180", orientation))
246 *method = GST_VIDEO_ORIENTATION_VERT;
247 else if (!g_strcmp0 ("flip-rotate-270", orientation))
248 *method = GST_VIDEO_ORIENTATION_UL_LR;
249 else
250 ret = FALSE;
251
252 g_free (orientation);
253
254 return ret;
255 }
256