1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include "dynamic_hdr_vivid.h"
20 #include "get_bits.h"
21 
22 static const int32_t maxrgb_den = 4095;
23 static const int32_t color_saturation_gain_den = 128;
24 static const int32_t maximum_luminance_den = 4095;
25 static const int32_t base_param_m_p_den = 16383;
26 static const int32_t base_param_m_m_den = 10;
27 static const int32_t base_param_m_a_den = 1023;
28 static const int32_t base_param_m_b_den = 1023;
29 static const int32_t base_param_m_n_den = 10;
30 static const int32_t base_param_Delta_den = 127;
31 
ff_parse_itu_t_t35_to_dynamic_hdr_vivid(AVDynamicHDRVivid *s, const uint8_t *data, int size)32 int ff_parse_itu_t_t35_to_dynamic_hdr_vivid(AVDynamicHDRVivid *s, const uint8_t *data,
33                                              int size)
34 {
35     GetBitContext gbc, *gb = &gbc;
36     int ret;
37 
38     if (!s)
39         return AVERROR(ENOMEM);
40 
41     ret = init_get_bits8(gb, data, size);
42     if (ret < 0)
43         return ret;
44 
45     if (get_bits_left(gb) < 8)
46         return AVERROR_INVALIDDATA;
47 
48     s->system_start_code = get_bits(gb, 8);
49     if (s->system_start_code == 0x01) {
50         s->num_windows = 1;
51 
52         if (get_bits_left(gb) < 12 * 4 * s->num_windows)
53             return AVERROR_INVALIDDATA;
54         for (int w = 0; w < s->num_windows; w++) {
55             AVHDRVividColorTransformParams *params = &s->params[w];
56 
57             params->minimum_maxrgb  = (AVRational){get_bits(gb, 12), maxrgb_den};
58             params->average_maxrgb  = (AVRational){get_bits(gb, 12), maxrgb_den};
59             params->variance_maxrgb = (AVRational){get_bits(gb, 12), maxrgb_den};
60             params->maximum_maxrgb  = (AVRational){get_bits(gb, 12), maxrgb_den};
61         }
62 
63         if (get_bits_left(gb) < 2 * s->num_windows)
64             return AVERROR_INVALIDDATA;
65         for (int w = 0; w < s->num_windows; w++) {
66             AVHDRVividColorTransformParams *params = &s->params[w];
67 
68             params->tone_mapping_mode_flag = get_bits(gb, 1);
69             if (params->tone_mapping_mode_flag) {
70                 if (get_bits_left(gb) < 1 )
71                     return AVERROR_INVALIDDATA;
72                 params->tone_mapping_param_num = get_bits(gb, 1) + 1;
73                 for (int i = 0; i < params->tone_mapping_param_num; i++) {
74                     AVHDRVividColorToneMappingParams *tm_params = &params->tm_params[i];
75 
76                     if (get_bits_left(gb) < 13)
77                         return AVERROR_INVALIDDATA;
78                     tm_params->targeted_system_display_maximum_luminance = (AVRational){get_bits(gb, 12), maximum_luminance_den};
79                     tm_params->base_enable_flag = get_bits(gb, 1);
80                     if (tm_params->base_enable_flag) {
81                         if (get_bits_left(gb) < (14 + 6 + 10 + 10 + 6 + 8 + 10))
82                             return AVERROR_INVALIDDATA;
83                         tm_params->base_param_m_p = (AVRational){get_bits(gb, 14), base_param_m_p_den};
84                         tm_params->base_param_m_m = (AVRational){get_bits(gb,  6), base_param_m_m_den};
85                         tm_params->base_param_m_a = (AVRational){get_bits(gb, 10), base_param_m_a_den};
86                         tm_params->base_param_m_b = (AVRational){get_bits(gb, 10), base_param_m_b_den};
87                         tm_params->base_param_m_n = (AVRational){get_bits(gb,  6), base_param_m_n_den};
88                         tm_params->base_param_k1 = get_bits(gb, 2);
89                         tm_params->base_param_k2 = get_bits(gb, 2);
90                         tm_params->base_param_k3 = get_bits(gb, 4);
91                         tm_params->base_param_Delta_enable_mode = get_bits(gb, 3);
92                         if (tm_params->base_param_Delta_enable_mode == 2 || tm_params->base_param_Delta_enable_mode == 6)
93                             tm_params->base_param_Delta = (AVRational){get_bits(gb, 7) * -1, base_param_Delta_den};
94                         else
95                             tm_params->base_param_Delta = (AVRational){get_bits(gb, 7), base_param_Delta_den};
96 
97                         if (get_bits_left(gb) < 1)
98                             return AVERROR_INVALIDDATA;
99                         tm_params->three_Spline_enable_flag = get_bits(gb, 1);
100                         if (tm_params->three_Spline_enable_flag) {
101                             if (get_bits_left(gb) < 1 + tm_params->three_Spline_num * (2 + 12 + 28 + 1))
102                                 return AVERROR_INVALIDDATA;
103                             tm_params->three_Spline_num = get_bits(gb, 1) + 1;
104                             for (int j = 0; j < tm_params->three_Spline_num; j++) {
105                                 tm_params->three_Spline_TH_mode = get_bits(gb, 2);
106                                 if (tm_params->three_Spline_TH_mode == 0 || tm_params->three_Spline_TH_mode == 2) {
107                                     if (get_bits_left(gb) < 8)
108                                         return AVERROR_INVALIDDATA;
109                                     tm_params->three_Spline_TH_enable_MB = (AVRational){get_bits(gb, 8),  255};
110                                 }
111                                 tm_params->three_Spline_TH_enable = (AVRational){get_bits(gb, 12),  4095};
112                                 tm_params->three_Spline_TH_Delta1 = (AVRational){get_bits(gb, 10),  1023};
113                                 tm_params->three_Spline_TH_Delta2 = (AVRational){get_bits(gb, 10),  1023};
114                                 tm_params->three_Spline_enable_Strength = (AVRational){get_bits(gb,  8),  255};
115                             }
116                         } else {
117                             tm_params->three_Spline_num     = 1;
118                             tm_params->three_Spline_TH_mode = 0;
119                         }
120 
121                     }
122                 }
123             }
124 
125             params->color_saturation_mapping_flag = get_bits(gb, 1);
126             if (params->color_saturation_mapping_flag) {
127                 if (get_bits_left(gb) < 3 + params->color_saturation_num * 8)
128                     return AVERROR_INVALIDDATA;
129 
130                 params->color_saturation_num = get_bits(gb, 3);
131                 for (int i = 0; i < params->color_saturation_num; i++) {
132                     params->color_saturation_gain[i] = (AVRational){get_bits(gb, 8), color_saturation_gain_den};
133                 }
134             }
135         }
136     }
137 
138     return 0;
139 }
140