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