Coverage Report

Created: 2026-01-22 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gstreamer/subprojects/gst-plugins-base/gst-libs/gst/video/video-hdr.c
Line
Count
Source
1
/* GStreamer
2
 * Copyright (C) <2018-2019> Seungha Yang <seungha.yang@navercorp.com>
3
 *
4
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Library General Public
6
 * License as published by the Free Software Foundation; either
7
 * version 2 of the License, or (at your option) any later version.
8
 *
9
 * This library is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 * Library General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Library General Public
15
 * License along with this library; if not, write to the
16
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17
 * Boston, MA 02110-1301, USA.
18
 */
19
20
#ifdef HAVE_CONFIG_H
21
#  include "config.h"
22
#endif
23
24
#include <string.h>
25
26
#include "video-hdr.h"
27
28
0
#define N_ELEMENT_MASTERING_DISPLAY_INFO 10
29
#define MASTERING_FORMAT \
30
0
  "%d:%d:" \
31
0
  "%d:%d:" \
32
0
  "%d:%d:" \
33
0
  "%d:%d:" \
34
0
  "%d:%d"
35
36
#define MASTERING_PRINTF_ARGS(m) \
37
0
  (m)->display_primaries[0].x, (m)->display_primaries[0].y, \
38
0
  (m)->display_primaries[1].x, (m)->display_primaries[1].y, \
39
0
  (m)->display_primaries[2].x, (m)->display_primaries[2].y, \
40
0
  (m)->white_point.x, (m)->white_point.y, \
41
0
  (m)->max_display_mastering_luminance, \
42
0
  (m)->min_display_mastering_luminance
43
44
/**
45
 * gst_video_mastering_display_info_init:
46
 * @minfo: a #GstVideoMasteringDisplayInfo
47
 *
48
 * Initialize @minfo
49
 *
50
 * Since: 1.18
51
 */
52
void
53
gst_video_mastering_display_info_init (GstVideoMasteringDisplayInfo * minfo)
54
0
{
55
0
  g_return_if_fail (minfo != NULL);
56
57
0
  memset (minfo, 0, sizeof (GstVideoMasteringDisplayInfo));
58
0
}
59
60
/**
61
 * gst_video_mastering_display_info_from_string:
62
 * @minfo: (out): a #GstVideoMasteringDisplayInfo
63
 * @mastering: a #GstStructure representing #GstVideoMasteringDisplayInfo
64
 *
65
 * Extract #GstVideoMasteringDisplayInfo from @mastering
66
 *
67
 * Returns: %TRUE if @minfo was filled with @mastering
68
 *
69
 * Since: 1.18
70
 */
71
gboolean
72
gst_video_mastering_display_info_from_string (GstVideoMasteringDisplayInfo *
73
    minfo, const gchar * mastering)
74
0
{
75
0
  gboolean ret = FALSE;
76
0
  gchar **split;
77
0
  gint i;
78
0
  gint idx = 0;
79
0
  guint64 val;
80
81
0
  g_return_val_if_fail (minfo != NULL, FALSE);
82
0
  g_return_val_if_fail (mastering != NULL, FALSE);
83
84
0
  split = g_strsplit (mastering, ":", -1);
85
86
0
  if (g_strv_length (split) != N_ELEMENT_MASTERING_DISPLAY_INFO)
87
0
    goto out;
88
89
0
  for (i = 0; i < G_N_ELEMENTS (minfo->display_primaries); i++) {
90
0
    if (!g_ascii_string_to_unsigned (split[idx++],
91
0
            10, 0, G_MAXUINT16, &val, NULL))
92
0
      goto out;
93
94
0
    minfo->display_primaries[i].x = (guint16) val;
95
96
0
    if (!g_ascii_string_to_unsigned (split[idx++],
97
0
            10, 0, G_MAXUINT16, &val, NULL))
98
0
      goto out;
99
100
0
    minfo->display_primaries[i].y = (guint16) val;
101
0
  }
102
103
0
  if (!g_ascii_string_to_unsigned (split[idx++],
104
0
          10, 0, G_MAXUINT16, &val, NULL))
105
0
    goto out;
106
107
0
  minfo->white_point.x = (guint16) val;
108
109
0
  if (!g_ascii_string_to_unsigned (split[idx++],
110
0
          10, 0, G_MAXUINT16, &val, NULL))
111
0
    goto out;
112
113
0
  minfo->white_point.y = (guint16) val;
114
115
0
  if (!g_ascii_string_to_unsigned (split[idx++],
116
0
          10, 0, G_MAXUINT32, &val, NULL))
117
0
    goto out;
118
119
0
  minfo->max_display_mastering_luminance = (guint32) val;
120
121
0
  if (!g_ascii_string_to_unsigned (split[idx++],
122
0
          10, 0, G_MAXUINT32, &val, NULL))
123
0
    goto out;
124
125
0
  minfo->min_display_mastering_luminance = (guint32) val;
126
0
  ret = TRUE;
127
128
0
out:
129
0
  g_strfreev (split);
130
0
  if (!ret)
131
0
    gst_video_mastering_display_info_init (minfo);
132
133
0
  return ret;
134
0
}
135
136
/**
137
 * gst_video_mastering_display_info_to_string:
138
 * @minfo: a #GstVideoMasteringDisplayInfo
139
 *
140
 * Convert @minfo to its string representation
141
 *
142
 * Returns: (transfer full): a string representation of @minfo
143
 *
144
 * Since: 1.18
145
 */
146
gchar *
147
gst_video_mastering_display_info_to_string (const GstVideoMasteringDisplayInfo *
148
    minfo)
149
0
{
150
0
  g_return_val_if_fail (minfo != NULL, NULL);
151
152
0
  return g_strdup_printf (MASTERING_FORMAT, MASTERING_PRINTF_ARGS (minfo));
153
0
}
154
155
/**
156
 * gst_video_mastering_display_info_is_equal:
157
 * @minfo: a #GstVideoMasteringDisplayInfo
158
 * @other: a #GstVideoMasteringDisplayInfo
159
 *
160
 * Checks equality between @minfo and @other.
161
 *
162
 * Returns: %TRUE if @minfo and @other are equal.
163
 *
164
 * Since: 1.18
165
 */
166
gboolean
167
gst_video_mastering_display_info_is_equal (const GstVideoMasteringDisplayInfo *
168
    minfo, const GstVideoMasteringDisplayInfo * other)
169
0
{
170
0
  gint i;
171
172
0
  g_return_val_if_fail (minfo != NULL, FALSE);
173
0
  g_return_val_if_fail (other != NULL, FALSE);
174
175
0
  for (i = 0; i < G_N_ELEMENTS (minfo->display_primaries); i++) {
176
0
    if (minfo->display_primaries[i].x != other->display_primaries[i].x ||
177
0
        minfo->display_primaries[i].y != other->display_primaries[i].y)
178
0
      return FALSE;
179
0
  }
180
181
0
  if (minfo->white_point.x != other->white_point.x ||
182
0
      minfo->white_point.y != other->white_point.y ||
183
0
      minfo->max_display_mastering_luminance !=
184
0
      other->max_display_mastering_luminance
185
0
      || minfo->min_display_mastering_luminance !=
186
0
      other->min_display_mastering_luminance)
187
0
    return FALSE;
188
189
0
  return TRUE;
190
0
}
191
192
/**
193
 * gst_video_mastering_display_info_from_caps:
194
 * @minfo: a #GstVideoMasteringDisplayInfo
195
 * @caps: a #GstCaps
196
 *
197
 * Parse @caps and update @minfo
198
 *
199
 * Returns: %TRUE if @caps has #GstVideoMasteringDisplayInfo and could be parsed
200
 *
201
 * Since: 1.18
202
 */
203
gboolean
204
gst_video_mastering_display_info_from_caps (GstVideoMasteringDisplayInfo *
205
    minfo, const GstCaps * caps)
206
0
{
207
0
  GstStructure *structure;
208
0
  const gchar *s;
209
210
0
  g_return_val_if_fail (minfo != NULL, FALSE);
211
0
  g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
212
213
0
  structure = gst_caps_get_structure (caps, 0);
214
215
0
  if ((s = gst_structure_get_string (structure,
216
0
              "mastering-display-info")) == NULL)
217
0
    return FALSE;
218
219
0
  return gst_video_mastering_display_info_from_string (minfo, s);
220
0
}
221
222
/**
223
 * gst_video_mastering_display_info_add_to_caps:
224
 * @minfo: a #GstVideoMasteringDisplayInfo
225
 * @caps: a #GstCaps
226
 *
227
 * Set string representation of @minfo to @caps
228
 *
229
 * Returns: %TRUE if @minfo was successfully set to @caps
230
 *
231
 * Since: 1.18
232
 */
233
gboolean
234
gst_video_mastering_display_info_add_to_caps (const GstVideoMasteringDisplayInfo
235
    * minfo, GstCaps * caps)
236
0
{
237
0
  gchar *s;
238
239
0
  g_return_val_if_fail (minfo != NULL, FALSE);
240
0
  g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
241
0
  g_return_val_if_fail (gst_caps_is_writable (caps), FALSE);
242
243
0
  s = gst_video_mastering_display_info_to_string (minfo);
244
0
  if (!s)
245
0
    return FALSE;
246
247
0
  gst_caps_set_simple (caps, "mastering-display-info", G_TYPE_STRING, s, NULL);
248
0
  g_free (s);
249
250
0
  return TRUE;
251
0
}
252
253
/**
254
 * gst_video_content_light_level_init:
255
 * @linfo: a #GstVideoContentLightLevel
256
 *
257
 * Initialize @linfo
258
 *
259
 * Since: 1.18
260
 */
261
void
262
gst_video_content_light_level_init (GstVideoContentLightLevel * linfo)
263
0
{
264
0
  g_return_if_fail (linfo != NULL);
265
266
0
  memset (linfo, 0, sizeof (GstVideoContentLightLevel));
267
0
}
268
269
/**
270
 * gst_video_content_light_level_from_string:
271
 * @linfo: a #GstVideoContentLightLevel
272
 * @level: a content-light-level string from caps
273
 *
274
 * Parse the value of content-light-level caps field and update @minfo
275
 * with the parsed values.
276
 *
277
 * Returns: %TRUE if @linfo points to valid #GstVideoContentLightLevel.
278
 *
279
 * Since: 1.18
280
 */
281
gboolean
282
gst_video_content_light_level_from_string (GstVideoContentLightLevel * linfo,
283
    const gchar * level)
284
0
{
285
0
  gboolean ret = FALSE;
286
0
  gchar **split;
287
0
  guint64 val;
288
289
0
  g_return_val_if_fail (linfo != NULL, FALSE);
290
0
  g_return_val_if_fail (level != NULL, FALSE);
291
292
0
  split = g_strsplit (level, ":", -1);
293
294
0
  if (g_strv_length (split) != 2)
295
0
    goto out;
296
297
0
  if (!g_ascii_string_to_unsigned (split[0], 10, 0, G_MAXUINT16, &val, NULL))
298
0
    goto out;
299
300
0
  linfo->max_content_light_level = (guint16) val;
301
302
0
  if (!g_ascii_string_to_unsigned (split[1], 10, 0, G_MAXUINT16, &val, NULL))
303
0
    goto out;
304
305
0
  linfo->max_frame_average_light_level = (guint16) val;
306
307
0
  ret = TRUE;
308
309
0
out:
310
0
  g_strfreev (split);
311
0
  if (!ret)
312
0
    gst_video_content_light_level_init (linfo);
313
314
0
  return ret;
315
0
}
316
317
/**
318
 * gst_video_content_light_level_to_string:
319
 * @linfo: a #GstVideoContentLightLevel
320
 *
321
 * Convert @linfo to its string representation.
322
 *
323
 * Returns: (transfer full): a string representation of @linfo.
324
 *
325
 * Since: 1.18
326
 */
327
gchar *
328
gst_video_content_light_level_to_string (const GstVideoContentLightLevel *
329
    linfo)
330
0
{
331
0
  g_return_val_if_fail (linfo != NULL, NULL);
332
333
0
  return g_strdup_printf ("%d:%d",
334
0
      linfo->max_content_light_level, linfo->max_frame_average_light_level);
335
0
}
336
337
/**
338
 * gst_video_content_light_level_is_equal:
339
 * @linfo: a #GstVideoContentLightLevel
340
 * @other: a #GstVideoContentLightLevel
341
 *
342
 * Checks equality between @linfo and @other.
343
 *
344
 * Returns: %TRUE if @linfo and @other are equal.
345
 *
346
 * Since: 1.20
347
 */
348
gboolean
349
gst_video_content_light_level_is_equal (const GstVideoContentLightLevel * linfo,
350
    const GstVideoContentLightLevel * other)
351
0
{
352
0
  g_return_val_if_fail (linfo != NULL, FALSE);
353
0
  g_return_val_if_fail (other != NULL, FALSE);
354
355
0
  return (linfo->max_content_light_level == other->max_content_light_level &&
356
0
      linfo->max_frame_average_light_level ==
357
0
      other->max_frame_average_light_level);
358
0
}
359
360
/**
361
 * gst_video_content_light_level_from_caps:
362
 * @linfo: a #GstVideoContentLightLevel
363
 * @caps: a #GstCaps
364
 *
365
 * Parse @caps and update @linfo
366
 *
367
 * Returns: if @caps has #GstVideoContentLightLevel and could be parsed
368
 *
369
 * Since: 1.18
370
 */
371
gboolean
372
gst_video_content_light_level_from_caps (GstVideoContentLightLevel * linfo,
373
    const GstCaps * caps)
374
0
{
375
0
  GstStructure *structure;
376
0
  const gchar *s;
377
378
0
  g_return_val_if_fail (linfo != NULL, FALSE);
379
0
  g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
380
381
0
  structure = gst_caps_get_structure (caps, 0);
382
383
0
  if ((s = gst_structure_get_string (structure, "content-light-level")) == NULL)
384
0
    return FALSE;
385
386
0
  return gst_video_content_light_level_from_string (linfo, s);
387
0
}
388
389
/**
390
 * gst_video_content_light_level_add_to_caps:
391
 * @linfo: a #GstVideoContentLightLevel
392
 * @caps: a #GstCaps
393
 *
394
 * Parse @caps and update @linfo
395
 *
396
 * Returns: %TRUE if @linfo was successfully set to @caps
397
 *
398
 * Since: 1.18
399
 */
400
gboolean
401
gst_video_content_light_level_add_to_caps (const GstVideoContentLightLevel *
402
    linfo, GstCaps * caps)
403
0
{
404
0
  gchar *s;
405
406
0
  g_return_val_if_fail (linfo != NULL, FALSE);
407
0
  g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
408
0
  g_return_val_if_fail (gst_caps_is_writable (caps), FALSE);
409
410
0
  s = gst_video_content_light_level_to_string (linfo);
411
0
  gst_caps_set_simple (caps, "content-light-level", G_TYPE_STRING, s, NULL);
412
0
  g_free (s);
413
414
0
  return TRUE;
415
0
}