FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/itut35.c
Date: 2026-06-16 12:54:33
Exec Total Coverage
Lines: 114 261 43.7%
Functions: 3 4 75.0%
Branches: 41 146 28.1%

Line Branch Exec Source
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 "libavutil/buffer.h"
20 #include "libavutil/frame.h"
21 #include "libavutil/hdr_dynamic_metadata.h"
22 #include "libavutil/internal.h"
23 #include "libavutil/mem.h"
24
25 #include "avcodec.h"
26 #include "atsc_a53.h"
27 #include "bytestream.h"
28 #include "decode.h"
29 #include "dynamic_hdr_vivid.h"
30 #include "dovi_rpu.h"
31 #include "itut35.h"
32 #include "version.h"
33
34 1525 int ff_itut_t35_parse_buffer(FFITUTT35 *const itut_t35, const uint8_t *buf,
35 size_t buf_size, int flags) {
36 GetByteContext gb;
37 int provider_code, country_code;
38 1525 unsigned int provider_oriented_code = 0;
39
40 1525 bytestream2_init(&gb, buf, buf_size);
41
42
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1525 times.
1525 if (flags & FF_ITUT_T35_FLAG_COUNTRY_CODE)
43 country_code = itut_t35->country_code;
44 else {
45 1525 country_code = bytestream2_get_byte(&gb);
46
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1525 times.
1525 if (country_code == 0xFF) {
47 if (bytestream2_get_bytes_left(&gb) < 1)
48 return AVERROR_INVALIDDATA;
49
50 bytestream2_skipu(&gb, 1); // itu_t_t35_country_code_extension_byte
51 }
52 }
53
54
3/4
✓ Branch 0 taken 1186 times.
✓ Branch 1 taken 336 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
1525 switch (country_code) {
55 1186 case ITU_T_T35_COUNTRY_CODE_US:
56
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1186 times.
1186 if (bytestream2_get_bytes_left(&gb) < 2)
57 return AVERROR_INVALIDDATA;
58 1186 provider_code = bytestream2_get_be16u(&gb);
59
60
2/6
✓ Branch 0 taken 1175 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1186 switch (provider_code) {
61 1175 case ITU_T_T35_PROVIDER_CODE_ATSC:
62
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1175 times.
1175 if (bytestream2_get_bytes_left(&gb) < 4)
63 return AVERROR_INVALIDDATA;
64 1175 provider_oriented_code = bytestream2_get_be32u(&gb);
65
2/3
✓ Branch 0 taken 1169 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
1175 switch (provider_oriented_code) {
66 1169 case MKBETAG('D', 'T', 'G', '1'): // afd_data
67
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1169 times.
1169 if (bytestream2_get_bytes_left(&gb) < 2)
68 return AVERROR_INVALIDDATA;
69
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1169 times.
1169 if (!(bytestream2_get_byteu(&gb) & 0x40)) // active_format_flag
70 return 0; //ignore
71 1169 break;
72 6 case MKBETAG('G', 'A', '9', '4'): // closed captions
73 6 break;
74 default: // ignore unsupported identifiers
75 return 0;
76 }
77 1175 break;
78 case ITU_T_T35_PROVIDER_CODE_AOM:
79 if (bytestream2_get_bytes_left(&gb) < 1)
80 return AVERROR_INVALIDDATA;
81
82 provider_oriented_code = bytestream2_get_byteu(&gb);
83 if (provider_oriented_code != 0x0001)
84 return 0; // ignore
85 break;
86 11 case ITU_T_T35_PROVIDER_CODE_SAMSUNG:
87
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if (bytestream2_get_bytes_left(&gb) < 3)
88 return AVERROR_INVALIDDATA;
89 11 provider_oriented_code = bytestream2_get_be16u(&gb);
90 11 int application_identifier = bytestream2_get_byteu(&gb);
91
92
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
11 if (provider_oriented_code != 1 || application_identifier != 4)
93 return 0; // ignore
94 11 break;
95 case ITU_T_T35_PROVIDER_CODE_DOLBY:
96 if (bytestream2_get_bytes_left(&gb) < 4)
97 return AVERROR_INVALIDDATA;
98 provider_oriented_code = bytestream2_get_be32u(&gb);
99 if (provider_oriented_code != 0x800)
100 return 0; // ignore
101 break;
102 case ITU_T_T35_PROVIDER_CODE_SMPTE:
103 if (bytestream2_get_bytes_left(&gb) < 2)
104 return AVERROR_INVALIDDATA;
105 provider_oriented_code = bytestream2_get_be16u(&gb);
106 if (provider_oriented_code != 1)
107 return 0; // ignore
108 break;
109 default: // ignore unsupported provider codes
110 return 0;
111 }
112 1186 break;
113 336 case ITU_T_T35_COUNTRY_CODE_UK:
114
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 336 times.
336 if (bytestream2_get_bytes_left(&gb) < 3)
115 return AVERROR_INVALIDDATA;
116
117 336 bytestream2_skipu(&gb, 1); // t35_uk_country_code_second_octet
118 336 provider_code = bytestream2_get_be16u(&gb);
119
120
1/2
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
336 switch (provider_code) {
121 336 case ITU_T_T35_PROVIDER_CODE_VNOVA:
122 336 break;
123 default: // ignore unsupported provider codes
124 return 0;
125 }
126 336 break;
127 3 case ITU_T_T35_COUNTRY_CODE_CN:
128
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (bytestream2_get_bytes_left(&gb) < 2)
129 return AVERROR_INVALIDDATA;
130 3 provider_code = bytestream2_get_be16u(&gb);
131
132
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 switch (provider_code) {
133 3 case ITU_T_T35_PROVIDER_CODE_HDR_VIVID:
134
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (bytestream2_get_bytes_left(&gb) < 2)
135 return AVERROR_INVALIDDATA;
136
137 3 provider_oriented_code = bytestream2_get_be16u(&gb);
138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (provider_oriented_code != 0x0005)
139 return 0; //ignore
140 3 break;
141 default: // ignore unsupported provider codes
142 return 0;
143 }
144 3 break;
145
146 default: // ignore unsupported country codes
147 return 0;
148 }
149
150
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1525 times.
1525 if (!bytestream2_get_bytes_left(&gb))
151 return AVERROR_INVALIDDATA;
152
153 1525 itut_t35->payload = gb.buffer;
154 1525 itut_t35->payload_size = bytestream2_get_bytes_left(&gb);
155
156 1525 itut_t35->country_code = country_code;
157 1525 itut_t35->provider_code = provider_code;
158 1525 itut_t35->provider_oriented_code = provider_oriented_code;
159
160 1525 return 1;
161 }
162
163 1525 int ff_itut_t35_parse_payload_to_struct(FFITUTT35 *const itut_t35, FFITUTT35Aux *const aux,
164 FFITUTT35Meta *metadata, int err_recognition)
165 {
166 int ret;
167
168
3/4
✓ Branch 0 taken 1186 times.
✓ Branch 1 taken 336 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
1525 switch (itut_t35->country_code) {
169 1186 case ITU_T_T35_COUNTRY_CODE_US:
170
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1175 times.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1186 switch (itut_t35->provider_code) {
171 case ITU_T_T35_PROVIDER_CODE_AOM:
172 ff_aom_uninit_film_grain_params(&metadata->aom_film_grain);
173 ret = ff_aom_parse_film_grain_sets(&metadata->aom_film_grain,
174 itut_t35->payload, itut_t35->payload_size);
175 if (ret < 0)
176 return ret;
177 break;
178 1175 case ITU_T_T35_PROVIDER_CODE_ATSC:
179
2/3
✓ Branch 0 taken 1169 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
1175 switch (itut_t35->provider_oriented_code) {
180 1169 case MKBETAG('D', 'T', 'G', '1'): // afd_data
181 1169 av_buffer_unref(&metadata->afd);
182 1169 metadata->afd = av_buffer_alloc(1);
183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1169 times.
1169 if (!metadata->afd)
184 return AVERROR(ENOMEM);
185
186 1169 *metadata->afd->data = *itut_t35->payload & 0xf;
187
188 1169 break;
189 6 case MKBETAG('G', 'A', '9', '4'): // closed captions
190 6 ret = ff_parse_a53_cc(&metadata->a53_cc, itut_t35->payload, itut_t35->payload_size);
191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (ret < 0)
192 return ret;
193
194 6 break;
195 default: // ignore unsupported identifiers
196 break;
197 }
198 1175 break;
199 11 case ITU_T_T35_PROVIDER_CODE_SAMSUNG: {
200 size_t size;
201 11 AVDynamicHDRPlus *hdr_plus = av_dynamic_hdr_plus_alloc(&size);
202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!hdr_plus)
203 return AVERROR(ENOMEM);
204
205 11 ret = av_dynamic_hdr_plus_from_t35(hdr_plus, itut_t35->payload,
206 itut_t35->payload_size);
207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0) {
208 av_free(hdr_plus);
209 return ret;
210 }
211
212 11 av_buffer_unref(&metadata->hdr_plus);
213 11 metadata->hdr_plus = av_buffer_create((uint8_t *)hdr_plus, size, NULL, NULL, 0);
214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!metadata->hdr_plus) {
215 av_free(hdr_plus);
216 return AVERROR(ENOMEM);
217 }
218
219 11 break;
220 }
221 case ITU_T_T35_PROVIDER_CODE_DOLBY: {
222 AVDOVIMetadata *dovi;
223
224 if (!aux || !aux->dovi)
225 return 0; // ignore
226
227 ret = ff_dovi_rpu_parse(aux->dovi, itut_t35->payload, itut_t35->payload_size,
228 err_recognition);
229 if (ret < 0)
230 return 0; // ignore
231
232 ret = ff_dovi_get_metadata(aux->dovi, &dovi);
233 if (ret <= 0)
234 return ret;
235
236 av_buffer_unref(&metadata->dovi);
237 metadata->dovi = av_buffer_create((uint8_t *)dovi, ret, NULL, NULL, 0);
238 if (!metadata->dovi) {
239 av_free(dovi);
240 return AVERROR(ENOMEM);
241 }
242
243 break;
244 }
245 case ITU_T_T35_PROVIDER_CODE_SMPTE: {
246 size_t size;
247 AVDynamicHDRSmpte2094App5 *hdr_smpte2094_app5 = av_dynamic_hdr_smpte2094_app5_alloc(&size);
248 if (!hdr_smpte2094_app5)
249 return AVERROR(ENOMEM);
250
251 ret = av_dynamic_hdr_smpte2094_app5_from_t35(hdr_smpte2094_app5, itut_t35->payload,
252 itut_t35->payload_size);
253 if (ret < 0) {
254 av_free(hdr_smpte2094_app5);
255 return ret;
256 }
257
258 av_buffer_unref(&metadata->hdr_smpte2094_app5);
259 metadata->hdr_smpte2094_app5 = av_buffer_create((uint8_t *)hdr_smpte2094_app5, size, NULL, NULL, 0);
260 if (!metadata->hdr_smpte2094_app5) {
261 av_free(hdr_smpte2094_app5);
262 return AVERROR(ENOMEM);
263 }
264
265 break;
266 }
267 default:
268 break;
269 }
270 1186 break;
271 336 case ITU_T_T35_COUNTRY_CODE_UK:
272
1/2
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
336 switch (itut_t35->provider_code) {
273 336 case ITU_T_T35_PROVIDER_CODE_VNOVA:
274 336 av_buffer_unref(&metadata->lcevc);
275 336 metadata->lcevc = av_buffer_alloc(itut_t35->payload_size);
276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 336 times.
336 if (!metadata->lcevc)
277 return AVERROR(ENOMEM);
278
279 336 memcpy(metadata->lcevc->data, itut_t35->payload, itut_t35->payload_size);
280
281 336 break;
282 default:
283 break;
284 }
285 336 break;
286 3 case ITU_T_T35_COUNTRY_CODE_CN:
287
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 switch (itut_t35->provider_code) {
288 3 case ITU_T_T35_PROVIDER_CODE_HDR_VIVID: {
289 size_t size;
290 3 AVDynamicHDRVivid *hdr_vivid = av_dynamic_hdr_vivid_alloc(&size);
291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!hdr_vivid)
292 return AVERROR(ENOMEM);
293
294 3 ret = ff_parse_itu_t_t35_to_dynamic_hdr_vivid(hdr_vivid, itut_t35->payload,
295 3 itut_t35->payload_size);
296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
297 av_free(hdr_vivid);
298 return ret;
299 }
300
301 3 av_buffer_unref(&metadata->hdr_vivid);
302 3 metadata->hdr_vivid = av_buffer_create((uint8_t *)hdr_vivid, size, NULL, NULL, 0);
303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!metadata->hdr_vivid) {
304 av_free(hdr_vivid);
305 return AVERROR(ENOMEM);
306 }
307 3 break;
308 }
309 default:
310 break;
311 }
312 3 break;
313
314 default:
315 // ignore unsupported provider codes
316 break;
317 }
318
319 1525 return 0;
320 }
321
322 int ff_itut_t35_parse_payload_to_frame(FFITUTT35 *const itut_t35, FFITUTT35Aux *const aux,
323 AVCodecContext *const avctx, AVFrame *const frame)
324 {
325 FFITUTT35Meta metadata = { 0 };
326 int ret;
327
328 ret = ff_itut_t35_parse_payload_to_struct(itut_t35, aux, &metadata, avctx->err_recognition);
329 if (ret < 0)
330 return ret;
331
332 if (metadata.afd) {
333 if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_AFD, metadata.afd))
334 av_buffer_unref(&metadata.afd);
335 metadata.afd = NULL;
336 }
337
338 if (metadata.a53_cc) {
339 ret = ff_frame_new_side_data_from_buf(avctx, frame, AV_FRAME_DATA_A53_CC, &metadata.a53_cc);
340 if (ret < 0)
341 return ret;
342
343 #if FF_API_CODEC_PROPS
344 FF_DISABLE_DEPRECATION_WARNINGS
345 avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS;
346 FF_ENABLE_DEPRECATION_WARNINGS
347 #endif
348 }
349
350 if (metadata.aom_film_grain.enable) {
351 ret = ff_aom_attach_film_grain_sets(&metadata.aom_film_grain, frame);
352 if (ret < 0)
353 return ret;
354 }
355
356 if (metadata.hdr_plus) {
357 ret = ff_frame_new_side_data_from_buf(avctx, frame, AV_FRAME_DATA_DYNAMIC_HDR_PLUS,
358 &metadata.hdr_plus);
359 if (ret < 0)
360 return ret;
361 }
362
363 if (metadata.dovi) {
364 AVFrameSideData *sd = av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_DOVI_METADATA,
365 metadata.dovi);
366 if (!sd) {
367 av_buffer_unref(&metadata.dovi);
368 return AVERROR(ENOMEM);
369 }
370 metadata.dovi = NULL;
371 }
372
373 if (metadata.hdr_smpte2094_app5) {
374 ret = ff_frame_new_side_data_from_buf(avctx, frame, AV_FRAME_DATA_DYNAMIC_HDR_SMPTE_2094_APP5,
375 &metadata.hdr_smpte2094_app5);
376 if (ret < 0)
377 return ret;
378 }
379
380 if (metadata.lcevc) {
381 ret = ff_frame_new_side_data_from_buf(avctx, frame, AV_FRAME_DATA_LCEVC,
382 &metadata.lcevc);
383 if (ret < 0)
384 return ret;
385 }
386
387 if (metadata.hdr_vivid) {
388 ret = ff_frame_new_side_data_from_buf(avctx, frame, AV_FRAME_DATA_DYNAMIC_HDR_VIVID,
389 &metadata.hdr_vivid);
390 if (ret < 0)
391 return ret;
392 }
393
394 ff_itut_t35_unref(&metadata);
395
396 return 0;
397 }
398
399 77833 void ff_itut_t35_unref(FFITUTT35Meta *metadata)
400 {
401 77833 ff_aom_uninit_film_grain_params(&metadata->aom_film_grain);
402 77833 av_buffer_unref(&metadata->afd);
403 77833 av_buffer_unref(&metadata->a53_cc);
404 77833 av_buffer_unref(&metadata->hdr_plus);
405 77833 av_buffer_unref(&metadata->hdr_smpte2094_app5);
406 77833 av_buffer_unref(&metadata->lcevc);
407 77833 av_buffer_unref(&metadata->dovi);
408 77833 av_buffer_unref(&metadata->hdr_vivid);
409 77833 }
410