FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavutil/hdr_dynamic_metadata.c
Date: 2026-09-02 11:02:20
Exec Total Coverage
Lines: 392 440 89.1%
Functions: 8 8 100.0%
Branches: 282 364 77.5%

Line Branch Exec Source
1 /**
2 * Copyright (c) 2018 Mohammad Izadi <moh.izadi at gmail.com>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg 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 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include "avassert.h"
22 #include "hdr_dynamic_metadata.h"
23 #include "mem.h"
24 #include "libavcodec/defs.h"
25 #include "libavcodec/get_bits.h"
26 #include "libavcodec/put_bits.h"
27
28 static const int64_t luminance_den = 1;
29 static const int32_t peak_luminance_den = 15;
30 static const int64_t rgb_den = 100000;
31 static const int32_t fraction_pixel_den = 1000;
32 static const int32_t knee_point_den = 4095;
33 static const int32_t bezier_anchor_den = 1023;
34 static const int32_t saturation_weight_den = 8;
35
36 22 AVDynamicHDRPlus *av_dynamic_hdr_plus_alloc(size_t *size)
37 {
38 22 AVDynamicHDRPlus *hdr_plus = av_mallocz(sizeof(AVDynamicHDRPlus));
39
40
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 3 times.
22 if (size)
41
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 1 times.
19 *size = hdr_plus ? sizeof(*hdr_plus) : 0;
42
43 22 return hdr_plus;
44 }
45
46 1 AVDynamicHDRPlus *av_dynamic_hdr_plus_create_side_data(AVFrame *frame)
47 {
48 1 AVFrameSideData *side_data = av_frame_new_side_data(frame,
49 AV_FRAME_DATA_DYNAMIC_HDR_PLUS,
50 sizeof(AVDynamicHDRPlus));
51
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!side_data)
52 return NULL;
53
54 1 memset(side_data->data, 0, sizeof(AVDynamicHDRPlus));
55
56 1 return (AVDynamicHDRPlus *)side_data->data;
57 }
58
59 22 int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data,
60 size_t size)
61 {
62 uint8_t padded_buf[AV_HDR_PLUS_MAX_PAYLOAD_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
63 22 GetBitContext gbc, *gb = &gbc;
64 int ret;
65
66
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 21 times.
22 if (!s)
67 1 return AVERROR(EINVAL);
68
69
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 20 times.
21 if (size > AV_HDR_PLUS_MAX_PAYLOAD_SIZE)
70 1 return AVERROR(EINVAL);
71
72 20 memcpy(padded_buf, data, size);
73 // Zero-initialize the buffer padding to avoid overreads into uninitialized data.
74 20 memset(padded_buf + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
75
76 20 ret = init_get_bits8(gb, padded_buf, size);
77
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (ret < 0)
78 return ret;
79
80
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 if (get_bits_left(gb) < 10)
81 return AVERROR_INVALIDDATA;
82
83 20 s->application_version = get_bits(gb, 8);
84 20 s->num_windows = get_bits(gb, 2);
85
86
2/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 20 times.
20 if (s->num_windows < 1 || s->num_windows > 3) {
87 return AVERROR_INVALIDDATA;
88 }
89
90
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 if (get_bits_left(gb) < ((19 * 8 + 1) * (s->num_windows - 1)))
91 return AVERROR_INVALIDDATA;
92
93
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 20 times.
21 for (int w = 1; w < s->num_windows; w++) {
94 // The corners are set to absolute coordinates here. They should be
95 // converted to the relative coordinates (in [0, 1]) in the decoder.
96 1 AVHDRPlusColorTransformParams *params = &s->params[w];
97 1 params->window_upper_left_corner_x =
98 1 (AVRational){get_bits(gb, 16), 1};
99 1 params->window_upper_left_corner_y =
100 1 (AVRational){get_bits(gb, 16), 1};
101 1 params->window_lower_right_corner_x =
102 1 (AVRational){get_bits(gb, 16), 1};
103 1 params->window_lower_right_corner_y =
104 1 (AVRational){get_bits(gb, 16), 1};
105
106 1 params->center_of_ellipse_x = get_bits(gb, 16);
107 1 params->center_of_ellipse_y = get_bits(gb, 16);
108 1 params->rotation_angle = get_bits(gb, 8);
109 1 params->semimajor_axis_internal_ellipse = get_bits(gb, 16);
110 1 params->semimajor_axis_external_ellipse = get_bits(gb, 16);
111 1 params->semiminor_axis_external_ellipse = get_bits(gb, 16);
112 1 params->overlap_process_option = get_bits1(gb);
113 }
114
115
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 if (get_bits_left(gb) < 28)
116 return AVERROR_INVALIDDATA;
117
118 20 s->targeted_system_display_maximum_luminance =
119 20 (AVRational){get_bits_long(gb, 27), luminance_den};
120 20 s->targeted_system_display_actual_peak_luminance_flag = get_bits1(gb);
121
122
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 19 times.
20 if (s->targeted_system_display_actual_peak_luminance_flag) {
123 int rows, cols;
124
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (get_bits_left(gb) < 10)
125 return AVERROR_INVALIDDATA;
126 1 rows = get_bits(gb, 5);
127 1 cols = get_bits(gb, 5);
128
4/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
1 if (((rows < 2) || (rows > 25)) || ((cols < 2) || (cols > 25))) {
129 return AVERROR_INVALIDDATA;
130 }
131 1 s->num_rows_targeted_system_display_actual_peak_luminance = rows;
132 1 s->num_cols_targeted_system_display_actual_peak_luminance = cols;
133
134
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (get_bits_left(gb) < (rows * cols * 4))
135 return AVERROR_INVALIDDATA;
136
137
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (int i = 0; i < rows; i++) {
138
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (int j = 0; j < cols; j++) {
139 6 s->targeted_system_display_actual_peak_luminance[i][j] =
140 6 (AVRational){get_bits(gb, 4), peak_luminance_den};
141 }
142 }
143 }
144
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 20 times.
41 for (int w = 0; w < s->num_windows; w++) {
145 21 AVHDRPlusColorTransformParams *params = &s->params[w];
146
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
21 if (get_bits_left(gb) < (3 * 17 + 17 + 4))
147 return AVERROR_INVALIDDATA;
148
149
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 21 times.
84 for (int i = 0; i < 3; i++) {
150 63 params->maxscl[i] =
151 63 (AVRational){get_bits(gb, 17), rgb_den};
152 }
153 21 params->average_maxrgb =
154 21 (AVRational){get_bits(gb, 17), rgb_den};
155 21 params->num_distribution_maxrgb_percentiles = get_bits(gb, 4);
156
157 21 if (get_bits_left(gb) <
158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 (params->num_distribution_maxrgb_percentiles * 24))
159 return AVERROR_INVALIDDATA;
160
161
2/2
✓ Branch 0 taken 174 times.
✓ Branch 1 taken 21 times.
195 for (int i = 0; i < params->num_distribution_maxrgb_percentiles; i++) {
162 174 params->distribution_maxrgb[i].percentage = get_bits(gb, 7);
163 174 params->distribution_maxrgb[i].percentile =
164 174 (AVRational){get_bits(gb, 17), rgb_den};
165 }
166
167
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
21 if (get_bits_left(gb) < 10)
168 return AVERROR_INVALIDDATA;
169
170 21 params->fraction_bright_pixels = (AVRational){get_bits(gb, 10), fraction_pixel_den};
171 }
172
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 if (get_bits_left(gb) < 1)
173 return AVERROR_INVALIDDATA;
174 20 s->mastering_display_actual_peak_luminance_flag = get_bits1(gb);
175
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 19 times.
20 if (s->mastering_display_actual_peak_luminance_flag) {
176 int rows, cols;
177
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (get_bits_left(gb) < 10)
178 return AVERROR_INVALIDDATA;
179 1 rows = get_bits(gb, 5);
180 1 cols = get_bits(gb, 5);
181
4/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
1 if (((rows < 2) || (rows > 25)) || ((cols < 2) || (cols > 25))) {
182 return AVERROR_INVALIDDATA;
183 }
184 1 s->num_rows_mastering_display_actual_peak_luminance = rows;
185 1 s->num_cols_mastering_display_actual_peak_luminance = cols;
186
187
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (get_bits_left(gb) < (rows * cols * 4))
188 return AVERROR_INVALIDDATA;
189
190
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 for (int i = 0; i < rows; i++) {
191
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 for (int j = 0; j < cols; j++) {
192 6 s->mastering_display_actual_peak_luminance[i][j] =
193 6 (AVRational){get_bits(gb, 4), peak_luminance_den};
194 }
195 }
196 }
197
198
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 20 times.
41 for (int w = 0; w < s->num_windows; w++) {
199 21 AVHDRPlusColorTransformParams *params = &s->params[w];
200
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
21 if (get_bits_left(gb) < 1)
201 return AVERROR_INVALIDDATA;
202
203 21 params->tone_mapping_flag = get_bits1(gb);
204
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 if (params->tone_mapping_flag) {
205
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
21 if (get_bits_left(gb) < 28)
206 return AVERROR_INVALIDDATA;
207
208 21 params->knee_point_x =
209 21 (AVRational){get_bits(gb, 12), knee_point_den};
210 21 params->knee_point_y =
211 21 (AVRational){get_bits(gb, 12), knee_point_den};
212 21 params->num_bezier_curve_anchors = get_bits(gb, 4);
213
214
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
21 if (get_bits_left(gb) < (params->num_bezier_curve_anchors * 10))
215 return AVERROR_INVALIDDATA;
216
217
2/2
✓ Branch 0 taken 177 times.
✓ Branch 1 taken 21 times.
198 for (int i = 0; i < params->num_bezier_curve_anchors; i++) {
218 177 params->bezier_curve_anchors[i] =
219 177 (AVRational){get_bits(gb, 10), bezier_anchor_den};
220 }
221 }
222
223
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
21 if (get_bits_left(gb) < 1)
224 return AVERROR_INVALIDDATA;
225 21 params->color_saturation_mapping_flag = get_bits1(gb);
226
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 19 times.
21 if (params->color_saturation_mapping_flag) {
227
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (get_bits_left(gb) < 6)
228 return AVERROR_INVALIDDATA;
229 2 params->color_saturation_weight =
230 2 (AVRational){get_bits(gb, 6), saturation_weight_den};
231 }
232 }
233
234 20 return 0;
235 }
236
237 11 int av_dynamic_hdr_plus_to_t35(const AVDynamicHDRPlus *s, uint8_t **data, size_t *size)
238 {
239 uint8_t *buf;
240 size_t size_bits, size_bytes;
241 11 PutBitContext pbc, *pb = &pbc;
242
243
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 if (!s)
244 1 return AVERROR(EINVAL);
245
6/6
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 5 times.
10 if ((!data || *data) && !size)
246 1 return AVERROR(EINVAL);
247
248 /**
249 * Buffer size per CTA-861-H p.253-254:
250 * 48 header bits (excluded from the serialized payload)
251 * 8 bits for application_mode
252 * 2 bits for num_windows
253 * 153 bits for window geometry, for each window above 1
254 * 27 bits for targeted_system_display_maximum_luminance
255 * 1-2511 bits for targeted system display peak luminance information
256 * 82-442 bits per window for pixel distribution information
257 * 1-2511 bits for mastering display peak luminance information
258 * 1-179 bits per window for tonemapping information
259 * 1-7 bits per window for color saturation mapping information
260 * Total: 123-7249 bits, excluding trimmed header bits
261 */
262 9 size_bits = 8;
263
264 9 size_bits += 2;
265
266
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9 times.
10 for (int w = 1; w < s->num_windows; w++)
267 1 size_bits += 153;
268
269 9 size_bits += 27;
270
271 9 size_bits += 1;
272
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
9 if (s->targeted_system_display_actual_peak_luminance_flag)
273 1 size_bits += 10 +
274 1 s->num_rows_targeted_system_display_actual_peak_luminance *
275 1 s->num_cols_targeted_system_display_actual_peak_luminance * 4;
276
277
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 9 times.
19 for (int w = 0; w < s->num_windows; w++)
278 10 size_bits += 72 + s->params[w].num_distribution_maxrgb_percentiles * 24 + 10;
279
280 9 size_bits += 1;
281
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
9 if (s->mastering_display_actual_peak_luminance_flag)
282 1 size_bits += 10 +
283 1 s->num_rows_mastering_display_actual_peak_luminance *
284 1 s->num_cols_mastering_display_actual_peak_luminance * 4;
285
286
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 9 times.
19 for (int w = 0; w < s->num_windows; w++) {
287 10 size_bits += 1;
288
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (s->params[w].tone_mapping_flag)
289 10 size_bits += 28 + s->params[w].num_bezier_curve_anchors * 10;
290
291 10 size_bits += 1;
292
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (s->params[w].color_saturation_mapping_flag)
293 2 size_bits += 6;
294 }
295
296 9 size_bytes = (size_bits + 7) / 8;
297
298
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 av_assert0(size_bytes <= AV_HDR_PLUS_MAX_PAYLOAD_SIZE);
299
300
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
9 if (!data) {
301 1 *size = size_bytes;
302 1 return 0;
303
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 } else if (*data) {
304
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (*size < size_bytes)
305 1 return AVERROR_BUFFER_TOO_SMALL;
306 3 buf = *data;
307 } else {
308 4 buf = av_malloc(size_bytes);
309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!buf)
310 return AVERROR(ENOMEM);
311 }
312
313 7 init_put_bits(pb, buf, size_bytes);
314
315 // application_mode is set to Application Version 1
316 7 put_bits(pb, 8, 1);
317
318 // Payload as per CTA-861-H p.253-254
319 7 put_bits(pb, 2, s->num_windows);
320
321
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 for (int w = 1; w < s->num_windows; w++) {
322 1 put_bits(pb, 16, s->params[w].window_upper_left_corner_x.num / s->params[w].window_upper_left_corner_x.den);
323 1 put_bits(pb, 16, s->params[w].window_upper_left_corner_y.num / s->params[w].window_upper_left_corner_y.den);
324 1 put_bits(pb, 16, s->params[w].window_lower_right_corner_x.num / s->params[w].window_lower_right_corner_x.den);
325 1 put_bits(pb, 16, s->params[w].window_lower_right_corner_y.num / s->params[w].window_lower_right_corner_y.den);
326 1 put_bits(pb, 16, s->params[w].center_of_ellipse_x);
327 1 put_bits(pb, 16, s->params[w].center_of_ellipse_y);
328 1 put_bits(pb, 8, s->params[w].rotation_angle);
329 1 put_bits(pb, 16, s->params[w].semimajor_axis_internal_ellipse);
330 1 put_bits(pb, 16, s->params[w].semimajor_axis_external_ellipse);
331 1 put_bits(pb, 16, s->params[w].semiminor_axis_external_ellipse);
332 1 put_bits(pb, 1, s->params[w].overlap_process_option);
333 }
334
335 7 put_bits(pb, 27, s->targeted_system_display_maximum_luminance.num * luminance_den /
336 7 s->targeted_system_display_maximum_luminance.den);
337 7 put_bits(pb, 1, s->targeted_system_display_actual_peak_luminance_flag);
338
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (s->targeted_system_display_actual_peak_luminance_flag) {
339 1 put_bits(pb, 5, s->num_rows_targeted_system_display_actual_peak_luminance);
340 1 put_bits(pb, 5, s->num_cols_targeted_system_display_actual_peak_luminance);
341
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (int i = 0; i < s->num_rows_targeted_system_display_actual_peak_luminance; i++) {
342
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (int j = 0; j < s->num_cols_targeted_system_display_actual_peak_luminance; j++)
343 6 put_bits(pb, 4, s->targeted_system_display_actual_peak_luminance[i][j].num * peak_luminance_den /
344 6 s->targeted_system_display_actual_peak_luminance[i][j].den);
345 }
346 }
347
348
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7 times.
15 for (int w = 0; w < s->num_windows; w++) {
349
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8 times.
32 for (int i = 0; i < 3; i++)
350 24 put_bits(pb, 17, s->params[w].maxscl[i].num * rgb_den / s->params[w].maxscl[i].den);
351 8 put_bits(pb, 17, s->params[w].average_maxrgb.num * rgb_den / s->params[w].average_maxrgb.den);
352 8 put_bits(pb, 4, s->params[w].num_distribution_maxrgb_percentiles);
353
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 8 times.
65 for (int i = 0; i < s->params[w].num_distribution_maxrgb_percentiles; i++) {
354 57 put_bits(pb, 7, s->params[w].distribution_maxrgb[i].percentage);
355 57 put_bits(pb, 17, s->params[w].distribution_maxrgb[i].percentile.num * rgb_den /
356 57 s->params[w].distribution_maxrgb[i].percentile.den);
357 }
358 8 put_bits(pb, 10, s->params[w].fraction_bright_pixels.num * fraction_pixel_den /
359 8 s->params[w].fraction_bright_pixels.den);
360 }
361
362 7 put_bits(pb, 1, s->mastering_display_actual_peak_luminance_flag);
363
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (s->mastering_display_actual_peak_luminance_flag) {
364 1 put_bits(pb, 5, s->num_rows_mastering_display_actual_peak_luminance);
365 1 put_bits(pb, 5, s->num_cols_mastering_display_actual_peak_luminance);
366
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 for (int i = 0; i < s->num_rows_mastering_display_actual_peak_luminance; i++) {
367
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 for (int j = 0; j < s->num_cols_mastering_display_actual_peak_luminance; j++)
368 6 put_bits(pb, 4, s->mastering_display_actual_peak_luminance[i][j].num * peak_luminance_den /
369 6 s->mastering_display_actual_peak_luminance[i][j].den);
370 }
371 }
372
373
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7 times.
15 for (int w = 0; w < s->num_windows; w++) {
374 8 put_bits(pb, 1, s->params[w].tone_mapping_flag);
375
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (s->params[w].tone_mapping_flag) {
376 8 put_bits(pb, 12, s->params[w].knee_point_x.num * knee_point_den / s->params[w].knee_point_x.den);
377 8 put_bits(pb, 12, s->params[w].knee_point_y.num * knee_point_den / s->params[w].knee_point_y.den);
378 8 put_bits(pb, 4, s->params[w].num_bezier_curve_anchors);
379
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 8 times.
68 for (int i = 0; i < s->params[w].num_bezier_curve_anchors; i++)
380 60 put_bits(pb, 10, s->params[w].bezier_curve_anchors[i].num * bezier_anchor_den /
381 60 s->params[w].bezier_curve_anchors[i].den);
382 8 put_bits(pb, 1, s->params[w].color_saturation_mapping_flag);
383
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
8 if (s->params[w].color_saturation_mapping_flag)
384 2 put_bits(pb, 6, s->params[w].color_saturation_weight.num * saturation_weight_den /
385 2 s->params[w].color_saturation_weight.den);
386 }
387 }
388
389 7 flush_put_bits(pb);
390
391 7 *data = buf;
392
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (size)
393 7 *size = size_bytes;
394 7 return 0;
395 }
396
397 4 AVDynamicHDRSmpte2094App5 *av_dynamic_hdr_smpte2094_app5_alloc(size_t *size)
398 {
399 4 AVDynamicHDRSmpte2094App5 *smpte2094_app5 = av_mallocz(sizeof(AVDynamicHDRSmpte2094App5));
400
401
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (size)
402
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 *size = smpte2094_app5 ? sizeof(*smpte2094_app5) : 0;
403
404 4 return smpte2094_app5;
405 }
406
407 1 AVDynamicHDRSmpte2094App5 *av_dynamic_hdr_smpte2094_app5_create_side_data(AVFrame *frame)
408 {
409 1 AVFrameSideData *side_data = av_frame_new_side_data(frame,
410 AV_FRAME_DATA_DYNAMIC_HDR_SMPTE_2094_APP5,
411 sizeof(AVDynamicHDRSmpte2094App5));
412
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!side_data)
413 return NULL;
414
415 1 memset(side_data->data, 0, sizeof(AVDynamicHDRSmpte2094App5));
416
417 1 return (AVDynamicHDRSmpte2094App5 *)side_data->data;
418 }
419
420 #define GET_BITS_OR_FAIL(var, n) \
421 do { \
422 if (get_bits_left(gb) < n) { \
423 ret = AVERROR_INVALIDDATA; \
424 goto end; \
425 } \
426 var = get_bits(gb, n); \
427 } while (0)
428
429 5 int av_dynamic_hdr_smpte2094_app5_from_t35(AVDynamicHDRSmpte2094App5 *s, const uint8_t *data,
430 size_t size)
431 {
432 5 GetBitContext gbc, *gb = &gbc;
433 int ret, reserved_zero;
434 5 size_t padded_size = size + AV_INPUT_BUFFER_PADDING_SIZE;
435
436
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (!s)
437 1 return AVERROR(EINVAL);
438
439 4 uint8_t *padded_data = av_mallocz(padded_size);
440
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!padded_data)
441 return AVERROR(ENOMEM);
442
443 4 memcpy(padded_data, data, size);
444 4 ret = init_get_bits8(gb, padded_data, size);
445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
446 goto end;
447
448 // Table C.1
449
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 GET_BITS_OR_FAIL(s->application_version, 3);
450
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 GET_BITS_OR_FAIL(s->minimum_application_version, 3);
451
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 GET_BITS_OR_FAIL(reserved_zero, 2);
452
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (reserved_zero) {
453 ret = AVERROR_INVALIDDATA;
454 goto end;
455 }
456
457 // Table C.2
458
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 GET_BITS_OR_FAIL(s->has_custom_hdr_reference_white_flag, 1);
459
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 GET_BITS_OR_FAIL(s->has_adaptive_tone_map_flag, 1);
460
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 GET_BITS_OR_FAIL(reserved_zero, 6);
461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (reserved_zero) {
462 ret = AVERROR_INVALIDDATA;
463 goto end;
464 }
465
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (s->has_custom_hdr_reference_white_flag)
466
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 GET_BITS_OR_FAIL(s->hdr_reference_white, 16);
467
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (!s->has_adaptive_tone_map_flag) {
468 1 ret = 0;
469 1 goto end;
470 }
471
472 // Table C.3
473
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 GET_BITS_OR_FAIL(s->baseline_hdr_headroom, 16);
474
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 GET_BITS_OR_FAIL(s->use_reference_white_tone_mapping_flag, 1);
475
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (s->use_reference_white_tone_mapping_flag) {
476
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 GET_BITS_OR_FAIL(reserved_zero, 7);
477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 ret = reserved_zero ? AVERROR_INVALIDDATA : 0;
478 1 goto end;
479 }
480
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 GET_BITS_OR_FAIL(s->num_alternate_images, 3);
481
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (s->num_alternate_images > 4) {
482 ret = AVERROR_INVALIDDATA;
483 goto end;
484 }
485
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 GET_BITS_OR_FAIL(s->gain_application_space_chromaticities_flag, 2);
486
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 GET_BITS_OR_FAIL(s->has_common_component_mix_params_flag, 1);
487
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 GET_BITS_OR_FAIL(s->has_common_curve_params_flag, 1);
488
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (s->gain_application_space_chromaticities_flag == 3)
489
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
9 for (int r = 0; r < 8; r++)
490
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 GET_BITS_OR_FAIL(s->gain_application_space_chromaticities[r], 16);
491
492
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
7 for (int a = 0; a < s->num_alternate_images; a++) {
493
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 GET_BITS_OR_FAIL(s->alternate_hdr_headrooms[a], 16);
494
495 // Table C.4
496
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
5 if (!a || !s->has_common_component_mix_params_flag) {
497
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 GET_BITS_OR_FAIL(s->component_mixing_type[a], 2);
498
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (s->component_mixing_type[a] != 3) {
499
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 GET_BITS_OR_FAIL(reserved_zero, 6);
500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (reserved_zero) {
501 ret = AVERROR_INVALIDDATA;
502 goto end;
503 }
504 } else {
505
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 2 times.
14 for (int k = 0; k < 6; k++)
506
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
12 GET_BITS_OR_FAIL(s->has_component_mixing_coefficient_flag[a][k], 1);
507
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 2 times.
14 for (int k = 0; k < 6; k++) {
508
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (s->has_component_mixing_coefficient_flag[a][k]) {
509
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 GET_BITS_OR_FAIL(s->component_mixing_coefficient[a][k], 16);
510 } else {
511 6 s->component_mixing_coefficient[a][k] = 0;
512 }
513 }
514 }
515 } else {
516 2 s->component_mixing_type[a] = s->component_mixing_type[0];
517
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (s->component_mixing_type[a] == 3) {
518 for (int k = 0; k < 6; k++) {
519 s->has_component_mixing_coefficient_flag[a][k] =
520 s->has_component_mixing_coefficient_flag[0][k];
521 s->component_mixing_coefficient[a][k] = s->component_mixing_coefficient[0][k];
522 }
523 }
524 }
525
526 // Table C.5
527
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
5 if (!a || !s->has_common_curve_params_flag) {
528
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 GET_BITS_OR_FAIL(s->gain_curve_num_control_points_minus_1[a], 5);
529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (s->gain_curve_num_control_points_minus_1[a] > 31) {
530 ret = AVERROR_INVALIDDATA;
531 goto end;
532 }
533
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 GET_BITS_OR_FAIL(s->gain_curve_use_pchip_slope_flag[a], 1);
534
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 GET_BITS_OR_FAIL(reserved_zero, 2);
535
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (reserved_zero) {
536 ret = AVERROR_INVALIDDATA;
537 goto end;
538 }
539
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
10 for (int c = 0; c <= s->gain_curve_num_control_points_minus_1[a]; c++) {
540
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 GET_BITS_OR_FAIL(s->gain_curve_control_points_x[a][c], 16);
541 }
542 } else {
543 2 s->gain_curve_num_control_points_minus_1[a] =
544 2 s->gain_curve_num_control_points_minus_1[0];
545 2 s->gain_curve_use_pchip_slope_flag[a] = s->gain_curve_use_pchip_slope_flag[0];
546
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (int c = 0; c <= s->gain_curve_num_control_points_minus_1[a]; c++) {
547 6 s->gain_curve_control_points_x[a][c] = s->gain_curve_control_points_x[0][c];
548 }
549 }
550
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 5 times.
18 for (int c = 0; c <= s->gain_curve_num_control_points_minus_1[a]; c++)
551
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 GET_BITS_OR_FAIL(s->gain_curve_control_points_y[a][c], 16);
552
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 if (!s->gain_curve_use_pchip_slope_flag[a]) {
553
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int c = 0; c <= s->gain_curve_num_control_points_minus_1[a]; c++)
554
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 GET_BITS_OR_FAIL(s->gain_curve_control_points_theta[a][c], 16);
555 }
556 }
557 2 ret = 0;
558 4 end:
559 4 av_free(padded_data);
560 4 return ret;
561 }
562
563 10 int av_dynamic_hdr_smpte2094_app5_to_t35(const AVDynamicHDRSmpte2094App5 *s, uint8_t **data,
564 size_t *size)
565 {
566 uint8_t *buf;
567 size_t size_bytes, size_bits;
568 10 PutBitContext pbc, *pb = &pbc;
569
570
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9 times.
10 if (!s)
571 1 return AVERROR(EINVAL);
572
4/6
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
9 if ((!data || *data) && !size)
573 return AVERROR(EINVAL);
574
575
4/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7 times.
9 if (s->application_version >= 8 || s->minimum_application_version >= 3)
576 2 return AVERROR_INVALIDDATA;
577 7 size_bits = 0;
578 7 size_bits += 3 + 3 + 2;
579 7 size_bits += 1 + 1 + 6;
580
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
7 if (s->has_custom_hdr_reference_white_flag)
581 3 size_bits += 16;
582
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (s->has_adaptive_tone_map_flag) {
583 4 size_bits += 16 + 1;
584
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (s->use_reference_white_tone_mapping_flag) {
585 1 size_bits += 7;
586 } else {
587 3 size_bits += 3 + 2 + 1 + 1;
588
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (s->gain_application_space_chromaticities_flag == 3)
589 1 size_bits += 16 * 8;
590
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (s->num_alternate_images > 4)
591 1 return AVERROR_INVALIDDATA;
592
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
7 for (int a = 0; a < s->num_alternate_images; a++) {
593 5 size_bits += 16;
594
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
5 if (!a || !s->has_common_component_mix_params_flag) {
595 3 size_bits += 2;
596
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (s->component_mixing_type[a] != 3) {
597 1 size_bits += 6;
598 } else {
599 2 size_bits += 6;
600
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 2 times.
14 for (int k = 0; k < 6; k++)
601
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (s->has_component_mixing_coefficient_flag[a][k])
602 6 size_bits += 16;
603 }
604 }
605
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
5 if (!a || !s->has_common_curve_params_flag) {
606 3 size_bits += 5 + 1 + 2;
607
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (s->gain_curve_num_control_points_minus_1[a] > 31)
608 return AVERROR_INVALIDDATA;
609 3 size_bits += 16 * (s->gain_curve_num_control_points_minus_1[a] + 1);
610 }
611 5 size_bits += 16 * (s->gain_curve_num_control_points_minus_1[a] + 1);
612
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 if (!s->gain_curve_use_pchip_slope_flag[a])
613 2 size_bits += 16 * (s->gain_curve_num_control_points_minus_1[a] + 1);
614 }
615 }
616 }
617
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (size_bits % 8)
618 return AVERROR_INVALIDDATA;
619 6 size_bytes = size_bits >> 3;
620
621
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (!data) {
622 1 *size = size_bytes;
623 1 return 0;
624
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 } else if (*data) {
625 if (*size < size_bytes)
626 return AVERROR_BUFFER_TOO_SMALL;
627 buf = *data;
628 } else {
629 5 buf = av_malloc(size_bytes);
630
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!buf)
631 return AVERROR(ENOMEM);
632 }
633
634 5 init_put_bits(pb, buf, size_bytes);
635
636 // Table C.1
637 5 put_bits(pb, 3, s->application_version);
638 5 put_bits(pb, 3, s->minimum_application_version);
639 5 put_bits(pb, 2, 0); // reserved_zero
640
641 // Table C.2
642 5 put_bits(pb, 1, s->has_custom_hdr_reference_white_flag);
643 5 put_bits(pb, 1, s->has_adaptive_tone_map_flag);
644 5 put_bits(pb, 6, 0); // reserved_zero
645
646
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 if (s->has_custom_hdr_reference_white_flag)
647 2 put_bits(pb, 16, s->hdr_reference_white);
648
649
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 if (s->has_adaptive_tone_map_flag) {
650 // Table C.3
651 3 put_bits(pb, 16, s->baseline_hdr_headroom);
652 3 put_bits(pb, 1, s->use_reference_white_tone_mapping_flag);
653
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (s->use_reference_white_tone_mapping_flag) {
654 1 put_bits(pb, 7, 0); // reserved_zero
655 } else {
656 2 put_bits(pb, 3, s->num_alternate_images);
657 2 put_bits(pb, 2, s->gain_application_space_chromaticities_flag);
658 2 put_bits(pb, 1, s->has_common_component_mix_params_flag);
659 2 put_bits(pb, 1, s->has_common_curve_params_flag);
660
661
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (s->gain_application_space_chromaticities_flag == 3)
662
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
9 for (int r = 0; r < 8; r++)
663 8 put_bits(pb, 16, s->gain_application_space_chromaticities[r]);
664
665
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
7 for (int a = 0; a < s->num_alternate_images; a++) {
666 5 put_bits(pb, 16, s->alternate_hdr_headrooms[a]);
667
668 // Table C.4
669
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
5 if (!a || !s->has_common_component_mix_params_flag) {
670 3 put_bits(pb, 2, s->component_mixing_type[a]);
671
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (s->component_mixing_type[a] != 3) {
672 1 put_bits(pb, 6, 0); // reserved_zero
673 } else {
674
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 2 times.
14 for (int k = 0; k < 6; k++)
675 12 put_bits(pb, 1, s->has_component_mixing_coefficient_flag[a][k]);
676
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 2 times.
14 for (int k = 0; k < 6; k++)
677
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (s->has_component_mixing_coefficient_flag[a][k])
678 6 put_bits(pb, 16, s->component_mixing_coefficient[a][k]);
679 }
680 }
681
682 // Table C.5
683
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
5 if (!a || !s->has_common_curve_params_flag) {
684 3 put_bits(pb, 5, s->gain_curve_num_control_points_minus_1[a]);
685 3 put_bits(pb, 1, s->gain_curve_use_pchip_slope_flag[a]);
686 3 put_bits(pb, 2, 0); // reserved_zero
687
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
10 for (int c = 0; c <= s->gain_curve_num_control_points_minus_1[a]; c++)
688 7 put_bits(pb, 16, s->gain_curve_control_points_x[a][c]);
689 }
690
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 5 times.
18 for (int c = 0; c <= s->gain_curve_num_control_points_minus_1[a]; c++)
691 13 put_bits(pb, 16, s->gain_curve_control_points_y[a][c]);
692
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 if (!s->gain_curve_use_pchip_slope_flag[a]) {
693
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int c = 0; c <= s->gain_curve_num_control_points_minus_1[a]; c++)
694 4 put_bits(pb, 16, s->gain_curve_control_points_theta[a][c]);
695 }
696 }
697 }
698 }
699
700 5 flush_put_bits(pb);
701
702 5 *data = buf;
703
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (size)
704 5 *size = size_bytes;
705 5 return 0;
706 }
707