/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 | } |