• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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