Coverage Report

Created: 2026-02-24 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gstreamer/subprojects/gst-plugins-base/gst-libs/gst/video/video.c
Line
Count
Source
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
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
0
{
66
0
  gint num, den;
67
0
  gint tmp_n, tmp_d;
68
69
0
  g_return_val_if_fail (dar_n != NULL, FALSE);
70
0
  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
0
  if (!gst_util_fraction_multiply (video_width, video_height, video_par_n,
75
0
          video_par_d, &tmp_n, &tmp_d))
76
0
    goto error_overflow;
77
78
0
  if (!gst_util_fraction_multiply (tmp_n, tmp_d, display_par_d, display_par_n,
79
0
          &num, &den))
80
0
    goto error_overflow;
81
82
0
  g_return_val_if_fail (num > 0, FALSE);
83
0
  g_return_val_if_fail (den > 0, FALSE);
84
85
0
  *dar_n = num;
86
0
  *dar_d = den;
87
88
0
  return TRUE;
89
90
  /* ERRORS */
91
0
error_overflow:
92
0
  {
93
0
    GST_WARNING ("overflow in multiply");
94
0
    return FALSE;
95
0
  }
96
0
}
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
119
gst_video_guess_framerate (GstClockTime duration, gint * dest_n, gint * dest_d)
120
0
{
121
0
  const int common_den[] = { 1, 2, 3, 4, 1001 };
122
0
  int best_n, best_d, gcd;
123
0
  guint64 best_error = G_MAXUINT64;
124
0
  guint64 a;
125
0
  int i;
126
127
0
  if (G_UNLIKELY (duration == 0))
128
0
    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
0
  if (duration > 100000) {
133
0
    best_n = GST_SECOND / 10000;
134
0
    best_d = duration / 10000;
135
0
  } else {
136
0
    best_n = GST_SECOND;
137
0
    best_d = duration;
138
0
  }
139
140
0
  for (i = 0; i < G_N_ELEMENTS (common_den); i++) {
141
0
    gint d = common_den[i];
142
0
    gint n = gst_util_uint64_scale_round (d, GST_SECOND, duration);
143
144
    /* For NTSC framerates, round to the nearest 1000 fps */
145
0
    if (d == 1001) {
146
0
      n += 500;
147
0
      n -= (n % 1000);
148
0
    }
149
150
0
    if (n > 0) {
151
      /* See what duration the given framerate should be */
152
0
      a = gst_util_uint64_scale_int (GST_SECOND, d, n);
153
      /* Compute absolute error */
154
0
      a = (a < duration) ? (duration - a) : (a - duration);
155
0
      if (a < 2) {
156
        /* Really precise - take this option */
157
0
        if (dest_n)
158
0
          *dest_n = n;
159
0
        if (dest_d)
160
0
          *dest_d = d;
161
0
        return TRUE;
162
0
      }
163
      /* If within 0.1%, remember this denominator */
164
0
      if (a * 1000 < duration && a < best_error) {
165
0
        best_error = a;
166
0
        best_n = n;
167
0
        best_d = d;
168
0
      }
169
0
    }
170
0
  }
171
172
  /* set results */
173
0
  gcd = gst_util_greatest_common_divisor (best_n, best_d);
174
0
  if (gcd) {
175
0
    best_n /= gcd;
176
0
    best_d /= gcd;
177
0
  }
178
0
  if (dest_n)
179
0
    *dest_n = best_n;
180
0
  if (dest_d)
181
0
    *dest_d = best_d;
182
183
0
  return (best_error != G_MAXUINT64);
184
0
}
185
186
/**
187
 * gst_video_is_common_aspect_ratio:
188
 * @width: Width of the video frame
189
 * @height: Height of the video frame
190
 * @par_n: Pixel aspect ratio numerator
191
 * @par_d: Pixel aspect ratio denominator
192
 *
193
 * Given a frame's dimensions and pixel aspect ratio, this function will
194
 * calculate the frame's aspect ratio and compare it against a set of
195
 * common well-known "standard" aspect ratios.
196
 *
197
 * Returns: %TRUE if a known "standard" aspect ratio was
198
 * recognised, and %FALSE otherwise.
199
 *
200
 * Since: 1.22
201
 */
202
gboolean
203
gst_video_is_common_aspect_ratio (gint width, gint height, gint par_n,
204
    gint par_d)
205
0
{
206
0
  gint dar_n, dar_d;
207
208
0
  gst_util_fraction_multiply (width, height, par_n, par_d, &dar_n, &dar_d);
209
210
0
  if (dar_n == 16 && dar_d == 9)
211
0
    return TRUE;
212
0
  if (dar_n == 4 && dar_d == 3)
213
0
    return TRUE;
214
0
  if (dar_n == 14 && dar_d == 9)
215
0
    return TRUE;
216
0
  if (dar_n == 8 && dar_d == 5)
217
0
    return TRUE;
218
0
  if (dar_n == 21 && dar_d == 11)
219
0
    return TRUE;
220
221
0
  return FALSE;
222
0
}
223
224
225
/**
226
 * gst_video_alignment_reset:
227
 * @align: a #GstVideoAlignment
228
 *
229
 * Set @align to its default values with no padding and no alignment.
230
 */
231
void
232
gst_video_alignment_reset (GstVideoAlignment * align)
233
0
{
234
0
  gint i;
235
236
0
  g_return_if_fail (align != NULL);
237
238
0
  align->padding_top = 0;
239
0
  align->padding_bottom = 0;
240
0
  align->padding_left = 0;
241
0
  align->padding_right = 0;
242
0
  for (i = 0; i < GST_VIDEO_MAX_PLANES; i++)
243
0
    align->stride_align[i] = 0;
244
0
}
245
246
/**
247
 * gst_video_orientation_from_tag:
248
 * @taglist: A #GstTagList
249
 * @method: (out): The location where to return the orientation.
250
 *
251
 * Parses the "image-orientation" tag and transforms it into the
252
 * #GstVideoOrientationMethod enum.
253
 *
254
 * Returns: TRUE if there was a valid "image-orientation" tag in the taglist.
255
 *
256
 * Since: 1.20
257
 */
258
gboolean
259
gst_video_orientation_from_tag (GstTagList * taglist,
260
    GstVideoOrientationMethod * method)
261
0
{
262
0
  gchar *orientation;
263
0
  gboolean ret = TRUE;
264
265
0
  g_return_val_if_fail (GST_IS_TAG_LIST (taglist), FALSE);
266
0
  g_return_val_if_fail (method != NULL, FALSE);
267
268
0
  if (!gst_tag_list_get_string (taglist, "image-orientation", &orientation))
269
0
    return FALSE;
270
271
0
  if (!g_strcmp0 ("rotate-0", orientation))
272
0
    *method = GST_VIDEO_ORIENTATION_IDENTITY;
273
0
  else if (!g_strcmp0 ("rotate-90", orientation))
274
0
    *method = GST_VIDEO_ORIENTATION_90R;
275
0
  else if (!g_strcmp0 ("rotate-180", orientation))
276
0
    *method = GST_VIDEO_ORIENTATION_180;
277
0
  else if (!g_strcmp0 ("rotate-270", orientation))
278
0
    *method = GST_VIDEO_ORIENTATION_90L;
279
0
  else if (!g_strcmp0 ("flip-rotate-0", orientation))
280
0
    *method = GST_VIDEO_ORIENTATION_HORIZ;
281
0
  else if (!g_strcmp0 ("flip-rotate-90", orientation))
282
0
    *method = GST_VIDEO_ORIENTATION_UR_LL;
283
0
  else if (!g_strcmp0 ("flip-rotate-180", orientation))
284
0
    *method = GST_VIDEO_ORIENTATION_VERT;
285
0
  else if (!g_strcmp0 ("flip-rotate-270", orientation))
286
0
    *method = GST_VIDEO_ORIENTATION_UL_LR;
287
0
  else
288
0
    ret = FALSE;
289
290
0
  g_free (orientation);
291
292
0
  return ret;
293
0
}