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 #include <math.h>
29
30 #include "video-color.h"
31
32 #ifndef GST_DISABLE_GST_DEBUG
33 #define GST_CAT_DEFAULT ensure_debug_category()
34 static GstDebugCategory *
ensure_debug_category(void)35 ensure_debug_category (void)
36 {
37 static gsize cat_gonce = 0;
38
39 if (g_once_init_enter (&cat_gonce)) {
40 gsize cat_done;
41
42 cat_done = (gsize) _gst_debug_category_new ("video-color", 0,
43 "video-color object");
44
45 g_once_init_leave (&cat_gonce, cat_done);
46 }
47
48 return (GstDebugCategory *) cat_gonce;
49 }
50 #else
51 #define ensure_debug_category() /* NOOP */
52 #endif /* GST_DISABLE_GST_DEBUG */
53
54 typedef struct
55 {
56 const gchar *name;
57 GstVideoColorimetry color;
58 } ColorimetryInfo;
59
60 #define MAKE_COLORIMETRY(n,r,m,t,p) { GST_VIDEO_COLORIMETRY_ ##n, \
61 { GST_VIDEO_COLOR_RANGE ##r, GST_VIDEO_COLOR_MATRIX_ ##m, \
62 GST_VIDEO_TRANSFER_ ##t, GST_VIDEO_COLOR_PRIMARIES_ ##p } }
63
64 #define GST_VIDEO_COLORIMETRY_NONAME NULL
65
66 static const ColorimetryInfo colorimetry[] = {
67 MAKE_COLORIMETRY (BT601, _16_235, BT601, BT601, SMPTE170M),
68 MAKE_COLORIMETRY (BT709, _16_235, BT709, BT709, BT709),
69 MAKE_COLORIMETRY (SMPTE240M, _16_235, SMPTE240M, SMPTE240M, SMPTE240M),
70 MAKE_COLORIMETRY (SRGB, _0_255, RGB, SRGB, BT709),
71 MAKE_COLORIMETRY (BT2020, _16_235, BT2020, BT2020_12, BT2020),
72 MAKE_COLORIMETRY (BT2020_10, _16_235, BT2020, BT2020_10, BT2020),
73 MAKE_COLORIMETRY (BT2100_PQ, _16_235, BT2020, SMPTE2084, BT2020),
74 MAKE_COLORIMETRY (BT2100_HLG, _16_235, BT2020, ARIB_STD_B67, BT2020),
75 MAKE_COLORIMETRY (NONAME, _0_255, BT601, UNKNOWN, UNKNOWN),
76 MAKE_COLORIMETRY (NONAME, _UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN), /* Keep last! */
77 };
78
79 #define DEFAULT_UNKNOWN (G_N_ELEMENTS(colorimetry)-1)
80
81 static const ColorimetryInfo *
gst_video_get_colorimetry(const gchar * s)82 gst_video_get_colorimetry (const gchar * s)
83 {
84 gint i;
85
86 for (i = 0; colorimetry[i].name; i++) {
87 if (g_str_equal (colorimetry[i].name, s))
88 return &colorimetry[i];
89 }
90 return NULL;
91 }
92
93 #define CI_IS_EQUAL(ci,i) (((ci)->range == (i)->range) && \
94 ((ci)->matrix == (i)->matrix) && \
95 ((ci)->transfer == (i)->transfer) && \
96 ((ci)->primaries == (i)->primaries))
97
98 #define IS_EQUAL(ci,i) CI_IS_EQUAL(&(ci)->color, (i))
99
100 #define IS_UNKNOWN(ci) (IS_EQUAL (&colorimetry[DEFAULT_UNKNOWN], ci))
101
102 /**
103 * gst_video_colorimetry_from_string:
104 * @cinfo: a #GstVideoColorimetry
105 * @color: a colorimetry string
106 *
107 * Parse the colorimetry string and update @cinfo with the parsed
108 * values.
109 *
110 * Returns: %TRUE if @color points to valid colorimetry info.
111 */
112 gboolean
gst_video_colorimetry_from_string(GstVideoColorimetry * cinfo,const gchar * color)113 gst_video_colorimetry_from_string (GstVideoColorimetry * cinfo,
114 const gchar * color)
115 {
116 const ColorimetryInfo *ci;
117 gboolean res = FALSE;
118
119 if (!color) {
120 *cinfo = colorimetry[DEFAULT_UNKNOWN].color;
121 res = TRUE;
122 } else if ((ci = gst_video_get_colorimetry (color))) {
123 *cinfo = ci->color;
124 res = TRUE;
125 } else {
126 gint r, m, t, p;
127
128 if (sscanf (color, "%d:%d:%d:%d", &r, &m, &t, &p) == 4) {
129 cinfo->range = r;
130 cinfo->matrix = m;
131 cinfo->transfer = t;
132 cinfo->primaries = p;
133 res = TRUE;
134 }
135 }
136 return res;
137 }
138
139 /**
140 * gst_video_colorimetry_to_string:
141 * @cinfo: a #GstVideoColorimetry
142 *
143 * Make a string representation of @cinfo.
144 *
145 * Returns: (transfer full) (nullable): a string representation of @cinfo
146 * or %NULL if all the entries of @cinfo are unknown values.
147 */
148 gchar *
gst_video_colorimetry_to_string(const GstVideoColorimetry * cinfo)149 gst_video_colorimetry_to_string (const GstVideoColorimetry * cinfo)
150 {
151 gint i;
152
153 for (i = 0; colorimetry[i].name; i++) {
154 if (IS_EQUAL (&colorimetry[i], cinfo)) {
155 return g_strdup (colorimetry[i].name);
156 }
157 }
158 if (!IS_UNKNOWN (cinfo)) {
159 return g_strdup_printf ("%d:%d:%d:%d", cinfo->range, cinfo->matrix,
160 cinfo->transfer, cinfo->primaries);
161 }
162 return NULL;
163 }
164
165 /**
166 * gst_video_colorimetry_matches:
167 * @cinfo: a #GstVideoInfo
168 * @color: a colorimetry string
169 *
170 * Check if the colorimetry information in @info matches that of the
171 * string @color.
172 *
173 * Returns: %TRUE if @color conveys the same colorimetry info as the color
174 * information in @info.
175 */
176 gboolean
gst_video_colorimetry_matches(const GstVideoColorimetry * cinfo,const gchar * color)177 gst_video_colorimetry_matches (const GstVideoColorimetry * cinfo,
178 const gchar * color)
179 {
180 const ColorimetryInfo *ci;
181
182 if ((ci = gst_video_get_colorimetry (color)))
183 return IS_EQUAL (ci, cinfo);
184
185 return FALSE;
186 }
187
188 /**
189 * gst_video_color_range_offsets:
190 * @range: a #GstVideoColorRange
191 * @info: a #GstVideoFormatInfo
192 * @offset: (out caller-allocates) (array fixed-size=4): output offsets
193 * @scale: (out caller-allocates) (array fixed-size=4): output scale
194 *
195 * Compute the offset and scale values for each component of @info. For each
196 * component, (c[i] - offset[i]) / scale[i] will scale the component c[i] to the
197 * range [0.0 .. 1.0].
198 *
199 * The reverse operation (c[i] * scale[i]) + offset[i] can be used to convert
200 * the component values in range [0.0 .. 1.0] back to their representation in
201 * @info and @range.
202 */
203 void
gst_video_color_range_offsets(GstVideoColorRange range,const GstVideoFormatInfo * info,gint offset[GST_VIDEO_MAX_COMPONENTS],gint scale[GST_VIDEO_MAX_COMPONENTS])204 gst_video_color_range_offsets (GstVideoColorRange range,
205 const GstVideoFormatInfo * info, gint offset[GST_VIDEO_MAX_COMPONENTS],
206 gint scale[GST_VIDEO_MAX_COMPONENTS])
207 {
208 gboolean yuv;
209
210 yuv = GST_VIDEO_FORMAT_INFO_IS_YUV (info);
211
212 switch (range) {
213 default:
214 case GST_VIDEO_COLOR_RANGE_0_255:
215 offset[0] = 0;
216 if (yuv) {
217 offset[1] = 1 << (info->depth[1] - 1);
218 offset[2] = 1 << (info->depth[2] - 1);
219 } else {
220 offset[1] = 0;
221 offset[2] = 0;
222 }
223 scale[0] = (1 << info->depth[0]) - 1;
224 scale[1] = (1 << info->depth[1]) - 1;
225 scale[2] = (1 << info->depth[2]) - 1;
226 break;
227 case GST_VIDEO_COLOR_RANGE_16_235:
228 offset[0] = 1 << (info->depth[0] - 4);
229 scale[0] = 219 << (info->depth[0] - 8);
230 if (yuv) {
231 offset[1] = 1 << (info->depth[1] - 1);
232 offset[2] = 1 << (info->depth[2] - 1);
233 scale[1] = 224 << (info->depth[1] - 8);
234 scale[2] = 224 << (info->depth[2] - 8);
235 } else {
236 offset[1] = 1 << (info->depth[1] - 4);
237 offset[2] = 1 << (info->depth[2] - 4);
238 scale[1] = 219 << (info->depth[1] - 8);
239 scale[2] = 219 << (info->depth[2] - 8);
240 }
241 break;
242 }
243 /* alpha channel is always full range */
244 offset[3] = 0;
245 scale[3] = (1 << info->depth[3]) - 1;
246
247 GST_DEBUG ("scale: %d %d %d %d", scale[0], scale[1], scale[2], scale[3]);
248 GST_DEBUG ("offset: %d %d %d %d", offset[0], offset[1], offset[2], offset[3]);
249 }
250
251 /**
252 * gst_video_colorimetry_is_equal:
253 * @cinfo: a #GstVideoColorimetry
254 * @other: another #GstVideoColorimetry
255 *
256 * Compare the 2 colorimetry sets for equality
257 *
258 * Returns: %TRUE if @cinfo and @other are equal.
259 *
260 * Since: 1.6
261 */
262 gboolean
gst_video_colorimetry_is_equal(const GstVideoColorimetry * cinfo,const GstVideoColorimetry * other)263 gst_video_colorimetry_is_equal (const GstVideoColorimetry * cinfo,
264 const GstVideoColorimetry * other)
265 {
266 g_return_val_if_fail (cinfo != NULL, FALSE);
267 g_return_val_if_fail (other != NULL, FALSE);
268
269 return CI_IS_EQUAL (cinfo, other);
270 }
271
272 #define WP_C 0.31006, 0.31616
273 #define WP_D65 0.31271, 0.32902
274 #define WP_CENTRE (1/3), (1/3)
275 #define WP_WHITE 0.314, 0.351
276
277 static const GstVideoColorPrimariesInfo color_primaries[] = {
278 {GST_VIDEO_COLOR_PRIMARIES_UNKNOWN, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
279 {GST_VIDEO_COLOR_PRIMARIES_BT709, WP_D65, 0.64, 0.33, 0.30, 0.60, 0.15, 0.06},
280 {GST_VIDEO_COLOR_PRIMARIES_BT470M, WP_C, 0.67, 0.33, 0.21, 0.71, 0.14, 0.08},
281 {GST_VIDEO_COLOR_PRIMARIES_BT470BG, WP_D65, 0.64, 0.33, 0.29, 0.60, 0.15,
282 0.06},
283 {GST_VIDEO_COLOR_PRIMARIES_SMPTE170M, WP_D65, 0.63, 0.34, 0.31, 0.595, 0.155,
284 0.07},
285 {GST_VIDEO_COLOR_PRIMARIES_SMPTE240M, WP_D65, 0.63, 0.34, 0.31, 0.595, 0.155,
286 0.07},
287 {GST_VIDEO_COLOR_PRIMARIES_FILM, WP_C, 0.681, 0.319, 0.243, 0.692, 0.145,
288 0.049},
289 {GST_VIDEO_COLOR_PRIMARIES_BT2020, WP_D65, 0.708, 0.292, 0.170, 0.797, 0.131,
290 0.046},
291 {GST_VIDEO_COLOR_PRIMARIES_ADOBERGB, WP_D65, 0.64, 0.33, 0.21, 0.71, 0.15,
292 0.06},
293 {GST_VIDEO_COLOR_PRIMARIES_SMPTEST428, WP_CENTRE, 1.0, 0.0, 0.0, 1.0, 0.0,
294 0.0},
295 {GST_VIDEO_COLOR_PRIMARIES_SMPTERP431, WP_WHITE, 0.68, 0.32, 0.265, 0.69,
296 0.15, 0.06},
297 {GST_VIDEO_COLOR_PRIMARIES_SMPTEEG432, WP_D65, 0.68, 0.32, 0.265, 0.69, 0.15,
298 0.06},
299 {GST_VIDEO_COLOR_PRIMARIES_EBU3213, WP_D65, 0.63, 0.34, 0.295, 0.605, 0.155,
300 0.077},
301 };
302
303 /**
304 * gst_video_color_primaries_get_info:
305 * @primaries: a #GstVideoColorPrimaries
306 *
307 * Get information about the chromaticity coordinates of @primaries.
308 *
309 * Returns: a #GstVideoColorPrimariesInfo for @primaries.
310 *
311 * Since: 1.6
312 */
313 const GstVideoColorPrimariesInfo *
gst_video_color_primaries_get_info(GstVideoColorPrimaries primaries)314 gst_video_color_primaries_get_info (GstVideoColorPrimaries primaries)
315 {
316 g_return_val_if_fail ((gint) primaries <
317 G_N_ELEMENTS (color_primaries), NULL);
318
319 return &color_primaries[primaries];
320 }
321
322 /**
323 * gst_video_color_matrix_get_Kr_Kb:
324 * @matrix: a #GstVideoColorMatrix
325 * @Kr: (out): result red channel coefficient
326 * @Kb: (out): result blue channel coefficient
327 *
328 * Get the coefficients used to convert between Y'PbPr and R'G'B' using @matrix.
329 *
330 * When:
331 *
332 * |[
333 * 0.0 <= [Y',R',G',B'] <= 1.0)
334 * (-0.5 <= [Pb,Pr] <= 0.5)
335 * ]|
336 *
337 * the general conversion is given by:
338 *
339 * |[
340 * Y' = Kr*R' + (1-Kr-Kb)*G' + Kb*B'
341 * Pb = (B'-Y')/(2*(1-Kb))
342 * Pr = (R'-Y')/(2*(1-Kr))
343 * ]|
344 *
345 * and the other way around:
346 *
347 * |[
348 * R' = Y' + Cr*2*(1-Kr)
349 * G' = Y' - Cb*2*(1-Kb)*Kb/(1-Kr-Kb) - Cr*2*(1-Kr)*Kr/(1-Kr-Kb)
350 * B' = Y' + Cb*2*(1-Kb)
351 * ]|
352 *
353 * Returns: TRUE if @matrix was a YUV color format and @Kr and @Kb contain valid
354 * values.
355 *
356 * Since: 1.6
357 */
358 gboolean
gst_video_color_matrix_get_Kr_Kb(GstVideoColorMatrix matrix,gdouble * Kr,gdouble * Kb)359 gst_video_color_matrix_get_Kr_Kb (GstVideoColorMatrix matrix, gdouble * Kr,
360 gdouble * Kb)
361 {
362 gboolean res = TRUE;
363
364 switch (matrix) {
365 /* RGB */
366 default:
367 case GST_VIDEO_COLOR_MATRIX_RGB:
368 res = FALSE;
369 break;
370 /* YUV */
371 case GST_VIDEO_COLOR_MATRIX_FCC:
372 *Kr = 0.30;
373 *Kb = 0.11;
374 break;
375 case GST_VIDEO_COLOR_MATRIX_BT709:
376 *Kr = 0.2126;
377 *Kb = 0.0722;
378 break;
379 case GST_VIDEO_COLOR_MATRIX_BT601:
380 *Kr = 0.2990;
381 *Kb = 0.1140;
382 break;
383 case GST_VIDEO_COLOR_MATRIX_SMPTE240M:
384 *Kr = 0.212;
385 *Kb = 0.087;
386 break;
387 case GST_VIDEO_COLOR_MATRIX_BT2020:
388 *Kr = 0.2627;
389 *Kb = 0.0593;
390 break;
391 }
392 GST_DEBUG ("matrix: %d, Kr %f, Kb %f", matrix, *Kr, *Kb);
393
394 return res;
395 }
396
397 /**
398 * gst_video_color_transfer_encode:
399 * @func: a #GstVideoTransferFunction
400 * @val: a value
401 *
402 * Deprecated: 1.20: Use gst_video_transfer_function_encode() instead.
403 *
404 * Since: 1.6
405 */
406 gdouble
gst_video_color_transfer_encode(GstVideoTransferFunction func,gdouble val)407 gst_video_color_transfer_encode (GstVideoTransferFunction func, gdouble val)
408 {
409 return gst_video_transfer_function_encode (func, val);
410 }
411
412 /**
413 * gst_video_transfer_function_encode:
414 * @func: a #GstVideoTransferFunction
415 * @val: a value
416 *
417 * Convert @val to its gamma encoded value.
418 *
419 * For a linear value L in the range [0..1], conversion to the non-linear
420 * (gamma encoded) L' is in general performed with a power function like:
421 *
422 * |[
423 * L' = L ^ (1 / gamma)
424 * ]|
425 *
426 * Depending on @func, different formulas might be applied. Some formulas
427 * encode a linear segment in the lower range.
428 *
429 * Returns: the gamma encoded value of @val
430 *
431 * Since: 1.20
432 */
433 gdouble
gst_video_transfer_function_encode(GstVideoTransferFunction func,gdouble val)434 gst_video_transfer_function_encode (GstVideoTransferFunction func, gdouble val)
435 {
436 gdouble res;
437
438 switch (func) {
439 case GST_VIDEO_TRANSFER_UNKNOWN:
440 case GST_VIDEO_TRANSFER_GAMMA10:
441 default:
442 res = val;
443 break;
444 case GST_VIDEO_TRANSFER_GAMMA18:
445 res = pow (val, 1.0 / 1.8);
446 break;
447 case GST_VIDEO_TRANSFER_GAMMA20:
448 res = pow (val, 1.0 / 2.0);
449 break;
450 case GST_VIDEO_TRANSFER_GAMMA22:
451 res = pow (val, 1.0 / 2.2);
452 break;
453 case GST_VIDEO_TRANSFER_BT601:
454 case GST_VIDEO_TRANSFER_BT709:
455 case GST_VIDEO_TRANSFER_BT2020_10:
456 if (val < 0.018)
457 res = 4.5 * val;
458 else
459 res = 1.099 * pow (val, 0.45) - 0.099;
460 break;
461 case GST_VIDEO_TRANSFER_SMPTE240M:
462 if (val < 0.0228)
463 res = val * 4.0;
464 else
465 res = 1.1115 * pow (val, 0.45) - 0.1115;
466 break;
467 case GST_VIDEO_TRANSFER_SRGB:
468 if (val <= 0.0031308)
469 res = 12.92 * val;
470 else
471 res = 1.055 * pow (val, 1.0 / 2.4) - 0.055;
472 break;
473 case GST_VIDEO_TRANSFER_GAMMA28:
474 res = pow (val, 1 / 2.8);
475 break;
476 case GST_VIDEO_TRANSFER_LOG100:
477 if (val < 0.01)
478 res = 0.0;
479 else
480 res = 1.0 + log10 (val) / 2.0;
481 break;
482 case GST_VIDEO_TRANSFER_LOG316:
483 if (val < 0.0031622777)
484 res = 0.0;
485 else
486 res = 1.0 + log10 (val) / 2.5;
487 break;
488 case GST_VIDEO_TRANSFER_BT2020_12:
489 if (val < 0.0181)
490 res = 4.5 * val;
491 else
492 res = 1.0993 * pow (val, 0.45) - 0.0993;
493 break;
494 case GST_VIDEO_TRANSFER_ADOBERGB:
495 res = pow (val, 1.0 / 2.19921875);
496 break;
497 case GST_VIDEO_TRANSFER_SMPTE2084:
498 {
499 gdouble c1 = 0.8359375;
500 gdouble c2 = 18.8515625;
501 gdouble c3 = 18.6875;
502 gdouble m1 = 0.1593017578125;
503 gdouble m2 = 78.84375;
504 gdouble Ln = pow (val, m1);
505
506 /* val equal to 1 for peak white is ordinarily intended to
507 * correspond to a reference output luminance level of 10000 cd/m^2 */
508 res = pow ((c1 + c2 * Ln) / (1.0 + c3 * Ln), m2);
509 break;
510 }
511 case GST_VIDEO_TRANSFER_ARIB_STD_B67:
512 {
513 gdouble a = 0.17883277;
514 gdouble b = 0.28466892;
515 gdouble c = 0.55991073;
516
517 /* For [0, 1] normalized source as defined by HEVC specification */
518 if (val > (1.0 / 12.0))
519 res = a * log (12.0 * val - b) + c;
520 else
521 res = sqrt (3.0 * val);
522
523 break;
524 }
525 }
526 return res;
527 }
528
529 /**
530 * gst_video_color_transfer_decode:
531 * @func: a #GstVideoTransferFunction
532 * @val: a value
533 *
534 * Deprecated: 1.20: Use gst_video_transfer_function_decode() instead.
535 *
536 * Since: 1.6
537 */
538 gdouble
gst_video_color_transfer_decode(GstVideoTransferFunction func,gdouble val)539 gst_video_color_transfer_decode (GstVideoTransferFunction func, gdouble val)
540 {
541 return gst_video_transfer_function_decode (func, val);
542 }
543
544 /**
545 * gst_video_transfer_function_decode:
546 * @func: a #GstVideoTransferFunction
547 * @val: a value
548 *
549 * Convert @val to its gamma decoded value. This is the inverse operation of
550 * gst_video_color_transfer_encode().
551 *
552 * For a non-linear value L' in the range [0..1], conversion to the linear
553 * L is in general performed with a power function like:
554 *
555 * |[
556 * L = L' ^ gamma
557 * ]|
558 *
559 * Depending on @func, different formulas might be applied. Some formulas
560 * encode a linear segment in the lower range.
561 *
562 * Returns: the gamma decoded value of @val
563 *
564 * Since: 1.20
565 */
566 gdouble
gst_video_transfer_function_decode(GstVideoTransferFunction func,gdouble val)567 gst_video_transfer_function_decode (GstVideoTransferFunction func, gdouble val)
568 {
569 gdouble res;
570
571 switch (func) {
572 case GST_VIDEO_TRANSFER_UNKNOWN:
573 case GST_VIDEO_TRANSFER_GAMMA10:
574 default:
575 res = val;
576 break;
577 case GST_VIDEO_TRANSFER_GAMMA18:
578 res = pow (val, 1.8);
579 break;
580 case GST_VIDEO_TRANSFER_GAMMA20:
581 res = pow (val, 2.0);
582 break;
583 case GST_VIDEO_TRANSFER_GAMMA22:
584 res = pow (val, 2.2);
585 break;
586 case GST_VIDEO_TRANSFER_BT601:
587 case GST_VIDEO_TRANSFER_BT709:
588 case GST_VIDEO_TRANSFER_BT2020_10:
589 if (val < 0.081)
590 res = val / 4.5;
591 else
592 res = pow ((val + 0.099) / 1.099, 1.0 / 0.45);
593 break;
594 case GST_VIDEO_TRANSFER_SMPTE240M:
595 if (val < 0.0913)
596 res = val / 4.0;
597 else
598 res = pow ((val + 0.1115) / 1.1115, 1.0 / 0.45);
599 break;
600 case GST_VIDEO_TRANSFER_SRGB:
601 if (val <= 0.04045)
602 res = val / 12.92;
603 else
604 res = pow ((val + 0.055) / 1.055, 2.4);
605 break;
606 case GST_VIDEO_TRANSFER_GAMMA28:
607 res = pow (val, 2.8);
608 break;
609 case GST_VIDEO_TRANSFER_LOG100:
610 if (val == 0.0)
611 res = 0.0;
612 else
613 res = pow (10.0, 2.0 * (val - 1.0));
614 break;
615 case GST_VIDEO_TRANSFER_LOG316:
616 if (val == 0.0)
617 res = 0.0;
618 else
619 res = pow (10.0, 2.5 * (val - 1.0));
620 break;
621 case GST_VIDEO_TRANSFER_BT2020_12:
622 if (val < 0.08145)
623 res = val / 4.5;
624 else
625 res = pow ((val + 0.0993) / 1.0993, 1.0 / 0.45);
626 break;
627 case GST_VIDEO_TRANSFER_ADOBERGB:
628 res = pow (val, 2.19921875);
629 break;
630 case GST_VIDEO_TRANSFER_SMPTE2084:
631 {
632 gdouble c1 = 0.8359375;
633 gdouble c2 = 18.8515625;
634 gdouble c3 = 18.6875;
635 gdouble m1 = 0.1593017578125;
636 gdouble m2 = 78.84375;
637 gdouble tmp = pow (val, 1 / m2);
638 gdouble tmp2 = MAX (tmp - c1, 0.0f);
639
640 res = pow (tmp2 / (c2 - c3 * tmp), 1 / m1);
641 break;
642 }
643 case GST_VIDEO_TRANSFER_ARIB_STD_B67:
644 {
645 gdouble a = 0.17883277;
646 gdouble b = 0.28466892;
647 gdouble c = 0.55991073;
648
649 if (val > 0.5)
650 res = (exp ((val - c) / a) + b) / 12.0;
651 else
652 res = val * val / 3.0;
653
654 break;
655 }
656 }
657 return res;
658 }
659
660 /* conversion between GStreamer color{matrix,transfer,primaries} enum
661 * and indices defined by ITU-T H.273 and ISO/IEC 230001-8 specification */
662
663 /* FIXME 2.0: Define color{matrix,transfer,primaries} with explicit numbering
664 * to be matched with specification
665 */
666
667 /**
668 * gst_video_color_matrix_to_iso:
669 * @matrix: a #GstVideoColorMatrix
670 *
671 * Converts #GstVideoColorMatrix to the "matrix coefficients"
672 * (MatrixCoefficients) value defined by "ISO/IEC 23001-8 Section 7.3 Table 4"
673 * and "ITU-T H.273 Table 4".
674 * "H.264 Table E-5" and "H.265 Table E.5" share the identical values.
675 *
676 * Returns: The value of ISO/IEC 23001-8 matrix coefficients.
677 *
678 * Since: 1.18
679 */
680 guint
gst_video_color_matrix_to_iso(GstVideoColorMatrix matrix)681 gst_video_color_matrix_to_iso (GstVideoColorMatrix matrix)
682 {
683 switch (matrix) {
684 case GST_VIDEO_COLOR_MATRIX_RGB:
685 return 0;
686 case GST_VIDEO_COLOR_MATRIX_BT709:
687 return 1;
688 case GST_VIDEO_COLOR_MATRIX_FCC:
689 return 4;
690 case GST_VIDEO_COLOR_MATRIX_BT601:
691 return 6;
692 case GST_VIDEO_COLOR_MATRIX_SMPTE240M:
693 return 7;
694 case GST_VIDEO_COLOR_MATRIX_BT2020:
695 return 9;
696 case GST_VIDEO_COLOR_MATRIX_UNKNOWN:
697 default:
698 return 2;
699 }
700 }
701
702 /**
703 * gst_video_transfer_function_to_iso:
704 * @func: a #GstVideoTransferFunction
705 *
706 * Converts #GstVideoTransferFunction to the "transfer characteristics"
707 * (TransferCharacteristics) value defined by "ISO/IEC 23001-8 Section 7.2 Table 3"
708 * and "ITU-T H.273 Table 3".
709 * "H.264 Table E-4" and "H.265 Table E.4" share the identical values.
710 *
711 * Returns: The value of ISO/IEC 23001-8 transfer characteristics.
712 *
713 * Since: 1.18
714 */
715 guint
gst_video_transfer_function_to_iso(GstVideoTransferFunction func)716 gst_video_transfer_function_to_iso (GstVideoTransferFunction func)
717 {
718 switch (func) {
719 case GST_VIDEO_TRANSFER_BT709:
720 return 1;
721 case GST_VIDEO_TRANSFER_GAMMA22:
722 return 4;
723 case GST_VIDEO_TRANSFER_GAMMA28:
724 return 5;
725 case GST_VIDEO_TRANSFER_BT601:
726 return 6;
727 case GST_VIDEO_TRANSFER_SMPTE240M:
728 return 7;
729 case GST_VIDEO_TRANSFER_GAMMA10:
730 return 8;
731 case GST_VIDEO_TRANSFER_LOG100:
732 return 9;
733 case GST_VIDEO_TRANSFER_LOG316:
734 return 10;
735 case GST_VIDEO_TRANSFER_SRGB:
736 return 13;
737 case GST_VIDEO_TRANSFER_BT2020_10:
738 return 14;
739 case GST_VIDEO_TRANSFER_BT2020_12:
740 return 15;
741 case GST_VIDEO_TRANSFER_SMPTE2084:
742 return 16;
743 case GST_VIDEO_TRANSFER_ARIB_STD_B67:
744 return 18;
745 case GST_VIDEO_TRANSFER_GAMMA18:
746 case GST_VIDEO_TRANSFER_GAMMA20:
747 case GST_VIDEO_TRANSFER_ADOBERGB:
748 case GST_VIDEO_TRANSFER_UNKNOWN:
749 default:
750 return 2;
751 }
752 }
753
754 /**
755 * gst_video_color_primaries_to_iso:
756 * @primaries: a #GstVideoColorPrimaries
757 *
758 * Converts #GstVideoColorPrimaries to the "colour primaries" (ColourPrimaries)
759 * value defined by "ISO/IEC 23001-8 Section 7.1 Table 2"
760 * and "ITU-T H.273 Table 2".
761 * "H.264 Table E-3" and "H.265 Table E.3" share the identical values.
762 *
763 * Returns: The value of ISO/IEC 23001-8 colour primaries.
764 *
765 * Since: 1.18
766 */
767 guint
gst_video_color_primaries_to_iso(GstVideoColorPrimaries primaries)768 gst_video_color_primaries_to_iso (GstVideoColorPrimaries primaries)
769 {
770 switch (primaries) {
771 case GST_VIDEO_COLOR_PRIMARIES_BT709:
772 return 1;
773 case GST_VIDEO_COLOR_PRIMARIES_BT470M:
774 return 4;
775 case GST_VIDEO_COLOR_PRIMARIES_BT470BG:
776 return 5;
777 case GST_VIDEO_COLOR_PRIMARIES_SMPTE170M:
778 return 6;
779 case GST_VIDEO_COLOR_PRIMARIES_SMPTE240M:
780 return 7;
781 case GST_VIDEO_COLOR_PRIMARIES_FILM:
782 return 8;
783 case GST_VIDEO_COLOR_PRIMARIES_BT2020:
784 return 9;
785 case GST_VIDEO_COLOR_PRIMARIES_SMPTEST428:
786 return 10;
787 case GST_VIDEO_COLOR_PRIMARIES_SMPTERP431:
788 return 11;
789 case GST_VIDEO_COLOR_PRIMARIES_SMPTEEG432:
790 return 12;
791 case GST_VIDEO_COLOR_PRIMARIES_EBU3213:
792 return 22;
793 case GST_VIDEO_COLOR_PRIMARIES_ADOBERGB:
794 case GST_VIDEO_COLOR_PRIMARIES_UNKNOWN:
795 default:
796 return 2;
797 }
798 }
799
800 /**
801 * gst_video_color_matrix_from_iso:
802 * @value: a ITU-T H.273 matrix coefficients value
803 *
804 * Converts the @value to the #GstVideoColorMatrix
805 * The matrix coefficients (MatrixCoefficients) value is
806 * defined by "ISO/IEC 23001-8 Section 7.3 Table 4"
807 * and "ITU-T H.273 Table 4".
808 * "H.264 Table E-5" and "H.265 Table E.5" share the identical values.
809 *
810 * Returns: the matched #GstVideoColorMatrix
811 *
812 * Since: 1.18
813 */
814 GstVideoColorMatrix
gst_video_color_matrix_from_iso(guint value)815 gst_video_color_matrix_from_iso (guint value)
816 {
817 switch (value) {
818 case 0:
819 return GST_VIDEO_COLOR_MATRIX_RGB;
820 case 1:
821 return GST_VIDEO_COLOR_MATRIX_BT709;
822 case 4:
823 return GST_VIDEO_COLOR_MATRIX_FCC;
824 case 5:
825 case 6:
826 return GST_VIDEO_COLOR_MATRIX_BT601;
827 case 7:
828 return GST_VIDEO_COLOR_MATRIX_SMPTE240M;
829 case 9:
830 return GST_VIDEO_COLOR_MATRIX_BT2020;
831 case 2:
832 default:
833 return GST_VIDEO_COLOR_MATRIX_UNKNOWN;
834 }
835 }
836
837 /**
838 * gst_video_transfer_function_from_iso:
839 * @value: a ITU-T H.273 transfer characteristics value
840 *
841 * Converts the @value to the #GstVideoTransferFunction
842 * The transfer characteristics (TransferCharacteristics) value is
843 * defined by "ISO/IEC 23001-8 Section 7.2 Table 3"
844 * and "ITU-T H.273 Table 3".
845 * "H.264 Table E-4" and "H.265 Table E.4" share the identical values.
846 *
847 * Returns: the matched #GstVideoTransferFunction
848 *
849 * Since: 1.18
850 */
851 GstVideoTransferFunction
gst_video_transfer_function_from_iso(guint value)852 gst_video_transfer_function_from_iso (guint value)
853 {
854 switch (value) {
855 case 1:
856 return GST_VIDEO_TRANSFER_BT709;
857 case 4:
858 return GST_VIDEO_TRANSFER_GAMMA22;
859 case 5:
860 return GST_VIDEO_TRANSFER_GAMMA28;
861 case 6:
862 return GST_VIDEO_TRANSFER_BT601;
863 case 7:
864 return GST_VIDEO_TRANSFER_SMPTE240M;
865 case 8:
866 return GST_VIDEO_TRANSFER_GAMMA10;
867 case 9:
868 return GST_VIDEO_TRANSFER_LOG100;
869 case 10:
870 return GST_VIDEO_TRANSFER_LOG316;
871 case 13:
872 return GST_VIDEO_TRANSFER_SRGB;
873 case 14:
874 return GST_VIDEO_TRANSFER_BT2020_10;
875 case 15:
876 return GST_VIDEO_TRANSFER_BT2020_12;
877 case 16:
878 return GST_VIDEO_TRANSFER_SMPTE2084;
879 case 18:
880 return GST_VIDEO_TRANSFER_ARIB_STD_B67;
881 case 2:
882 default:
883 return GST_VIDEO_TRANSFER_UNKNOWN;
884 }
885 }
886
887 /**
888 * gst_video_color_primaries_from_iso:
889 * @value: a ITU-T H.273 colour primaries value
890 *
891 * Converts the @value to the #GstVideoColorPrimaries
892 * The colour primaries (ColourPrimaries) value is
893 * defined by "ISO/IEC 23001-8 Section 7.1 Table 2" and "ITU-T H.273 Table 2".
894 * "H.264 Table E-3" and "H.265 Table E.3" share the identical values.
895 *
896 * Returns: the matched #GstVideoColorPrimaries
897 *
898 * Since: 1.18
899 */
900 GstVideoColorPrimaries
gst_video_color_primaries_from_iso(guint value)901 gst_video_color_primaries_from_iso (guint value)
902 {
903 switch (value) {
904 case 1:
905 return GST_VIDEO_COLOR_PRIMARIES_BT709;
906 case 4:
907 return GST_VIDEO_COLOR_PRIMARIES_BT470M;
908 case 5:
909 return GST_VIDEO_COLOR_PRIMARIES_BT470BG;
910 case 6:
911 return GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
912 case 7:
913 return GST_VIDEO_COLOR_PRIMARIES_SMPTE240M;
914 case 8:
915 return GST_VIDEO_COLOR_PRIMARIES_FILM;
916 case 9:
917 return GST_VIDEO_COLOR_PRIMARIES_BT2020;
918 case 10:
919 return GST_VIDEO_COLOR_PRIMARIES_SMPTEST428;
920 case 11:
921 return GST_VIDEO_COLOR_PRIMARIES_SMPTERP431;
922 case 12:
923 return GST_VIDEO_COLOR_PRIMARIES_SMPTEEG432;
924 case 22:
925 return GST_VIDEO_COLOR_PRIMARIES_EBU3213;
926 case 2:
927 default:
928 return GST_VIDEO_COLOR_PRIMARIES_UNKNOWN;
929 }
930 }
931
932 static GstVideoTransferFunction
map_equivalent_transfer(GstVideoTransferFunction func,guint bpp)933 map_equivalent_transfer (GstVideoTransferFunction func, guint bpp)
934 {
935 switch (func) {
936 case GST_VIDEO_TRANSFER_BT2020_12:
937 if (bpp >= 12)
938 break;
939 /* fallthrough */
940 case GST_VIDEO_TRANSFER_BT709:
941 case GST_VIDEO_TRANSFER_BT601:
942 case GST_VIDEO_TRANSFER_BT2020_10:
943 return GST_VIDEO_TRANSFER_BT709;
944 default:
945 break;
946 }
947
948 return func;
949 }
950
951 /**
952 * gst_video_transfer_function_is_equivalent:
953 * @from_func: #GstVideoTransferFunction to convert from
954 * @from_bpp: bits per pixel to convert from
955 * @to_func: #GstVideoTransferFunction to convert into
956 * @to_bpp: bits per pixel to convert into
957 *
958 * Returns whether @from_func and @to_func are equivalent. There are cases
959 * (e.g. BT601, BT709, and BT2020_10) where several functions are functionally
960 * identical. In these cases, when doing conversion, we should consider them
961 * as equivalent. Also, BT2020_12 is the same as the aforementioned three for
962 * less than 12 bits per pixel.
963 *
964 * Returns: TRUE if @from_func and @to_func can be considered equivalent.
965 *
966 * Since: 1.18
967 */
968 gboolean
gst_video_transfer_function_is_equivalent(GstVideoTransferFunction from_func,guint from_bpp,GstVideoTransferFunction to_func,guint to_bpp)969 gst_video_transfer_function_is_equivalent (GstVideoTransferFunction from_func,
970 guint from_bpp, GstVideoTransferFunction to_func, guint to_bpp)
971 {
972 from_func = map_equivalent_transfer (from_func, from_bpp);
973 to_func = map_equivalent_transfer (to_func, to_bpp);
974 if (from_func == GST_VIDEO_TRANSFER_BT2020_12 && to_bpp < 12 &&
975 to_func == GST_VIDEO_TRANSFER_BT709)
976 return TRUE;
977 return from_func == to_func;
978 }
979