/src/ffmpeg/libavcodec/itut35.c
Line | Count | 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 | | int ff_itut_t35_parse_buffer(FFITUTT35 *const itut_t35, const uint8_t *buf, |
35 | 2.24M | size_t buf_size, int flags) { |
36 | 2.24M | GetByteContext gb; |
37 | 2.24M | int provider_code, country_code; |
38 | 2.24M | unsigned int provider_oriented_code = 0; |
39 | | |
40 | 2.24M | bytestream2_init(&gb, buf, buf_size); |
41 | | |
42 | 2.24M | if (flags & FF_ITUT_T35_FLAG_COUNTRY_CODE) |
43 | 0 | country_code = itut_t35->country_code; |
44 | 2.24M | else { |
45 | 2.24M | country_code = bytestream2_get_byte(&gb); |
46 | 2.24M | if (country_code == 0xFF) { |
47 | 32.1k | if (bytestream2_get_bytes_left(&gb) < 1) |
48 | 4.03k | return AVERROR_INVALIDDATA; |
49 | | |
50 | 28.1k | bytestream2_skipu(&gb, 1); // itu_t_t35_country_code_extension_byte |
51 | 28.1k | } |
52 | 2.24M | } |
53 | | |
54 | 2.24M | switch (country_code) { |
55 | 965k | case ITU_T_T35_COUNTRY_CODE_US: |
56 | 965k | if (bytestream2_get_bytes_left(&gb) < 2) |
57 | 3.61k | return AVERROR_INVALIDDATA; |
58 | 961k | provider_code = bytestream2_get_be16u(&gb); |
59 | | |
60 | 961k | switch (provider_code) { |
61 | 72.5k | case ITU_T_T35_PROVIDER_CODE_ATSC: |
62 | 72.5k | if (bytestream2_get_bytes_left(&gb) < 4) |
63 | 4.36k | return AVERROR_INVALIDDATA; |
64 | 68.2k | provider_oriented_code = bytestream2_get_be32u(&gb); |
65 | 68.2k | switch (provider_oriented_code) { |
66 | 9.58k | case MKBETAG('D', 'T', 'G', '1'): // afd_data |
67 | 9.58k | if (bytestream2_get_bytes_left(&gb) < 2) |
68 | 1.20k | return AVERROR_INVALIDDATA; |
69 | 8.37k | if (!(bytestream2_get_byteu(&gb) & 0x40)) // active_format_flag |
70 | 3.22k | return 0; //ignore |
71 | 5.15k | break; |
72 | 44.1k | case MKBETAG('G', 'A', '9', '4'): // closed captions |
73 | 44.1k | break; |
74 | 14.5k | default: // ignore unsupported identifiers |
75 | 14.5k | return 0; |
76 | 68.2k | } |
77 | 49.2k | break; |
78 | 261k | case ITU_T_T35_PROVIDER_CODE_AOM: |
79 | 261k | if (bytestream2_get_bytes_left(&gb) < 1) |
80 | 2.58k | return AVERROR_INVALIDDATA; |
81 | | |
82 | 258k | provider_oriented_code = bytestream2_get_byteu(&gb); |
83 | 258k | if (provider_oriented_code != 0x0001) |
84 | 15.3k | return 0; // ignore |
85 | 243k | break; |
86 | 385k | case ITU_T_T35_PROVIDER_CODE_SAMSUNG: |
87 | 385k | if (bytestream2_get_bytes_left(&gb) < 3) |
88 | 38.1k | return AVERROR_INVALIDDATA; |
89 | 347k | provider_oriented_code = bytestream2_get_be16u(&gb); |
90 | 347k | int application_identifier = bytestream2_get_byteu(&gb); |
91 | | |
92 | 347k | if (provider_oriented_code != 1 || application_identifier != 4) |
93 | 35.5k | return 0; // ignore |
94 | 311k | break; |
95 | 311k | case ITU_T_T35_PROVIDER_CODE_DOLBY: |
96 | 11.2k | if (bytestream2_get_bytes_left(&gb) < 4) |
97 | 2.81k | return AVERROR_INVALIDDATA; |
98 | 8.45k | provider_oriented_code = bytestream2_get_be32u(&gb); |
99 | 8.45k | if (provider_oriented_code != 0x800) |
100 | 6.23k | return 0; // ignore |
101 | 2.21k | break; |
102 | 173k | case ITU_T_T35_PROVIDER_CODE_SMPTE: |
103 | 173k | if (bytestream2_get_bytes_left(&gb) < 2) |
104 | 6.15k | return AVERROR_INVALIDDATA; |
105 | 167k | provider_oriented_code = bytestream2_get_be16u(&gb); |
106 | 167k | if (provider_oriented_code != 1) |
107 | 8.51k | return 0; // ignore |
108 | 158k | break; |
109 | 158k | default: // ignore unsupported provider codes |
110 | 57.7k | return 0; |
111 | 961k | } |
112 | 765k | break; |
113 | 765k | case ITU_T_T35_COUNTRY_CODE_UK: |
114 | 23.5k | if (bytestream2_get_bytes_left(&gb) < 3) |
115 | 6.28k | return AVERROR_INVALIDDATA; |
116 | | |
117 | 17.2k | bytestream2_skipu(&gb, 1); // t35_uk_country_code_second_octet |
118 | 17.2k | provider_code = bytestream2_get_be16u(&gb); |
119 | | |
120 | 17.2k | switch (provider_code) { |
121 | 4.60k | case ITU_T_T35_PROVIDER_CODE_VNOVA: |
122 | 4.60k | break; |
123 | 12.6k | default: // ignore unsupported provider codes |
124 | 12.6k | return 0; |
125 | 17.2k | } |
126 | 4.60k | break; |
127 | 137k | case ITU_T_T35_COUNTRY_CODE_CN: |
128 | 137k | if (bytestream2_get_bytes_left(&gb) < 2) |
129 | 4.22k | return AVERROR_INVALIDDATA; |
130 | 133k | provider_code = bytestream2_get_be16u(&gb); |
131 | | |
132 | 133k | switch (provider_code) { |
133 | 115k | case ITU_T_T35_PROVIDER_CODE_HDR_VIVID: |
134 | 115k | if (bytestream2_get_bytes_left(&gb) < 2) |
135 | 8.39k | return AVERROR_INVALIDDATA; |
136 | | |
137 | 106k | provider_oriented_code = bytestream2_get_be16u(&gb); |
138 | 106k | if (provider_oriented_code != 0x0005) |
139 | 13.7k | return 0; //ignore |
140 | 92.8k | break; |
141 | 92.8k | default: // ignore unsupported provider codes |
142 | 18.4k | return 0; |
143 | 133k | } |
144 | 92.8k | break; |
145 | | |
146 | 1.11M | default: // ignore unsupported country codes |
147 | 1.11M | return 0; |
148 | 2.24M | } |
149 | | |
150 | 862k | if (!bytestream2_get_bytes_left(&gb)) |
151 | 4.86k | return AVERROR_INVALIDDATA; |
152 | | |
153 | 857k | itut_t35->payload = gb.buffer; |
154 | 857k | itut_t35->payload_size = bytestream2_get_bytes_left(&gb); |
155 | | |
156 | 857k | itut_t35->country_code = country_code; |
157 | 857k | itut_t35->provider_code = provider_code; |
158 | 857k | itut_t35->provider_oriented_code = provider_oriented_code; |
159 | | |
160 | 857k | return 1; |
161 | 862k | } |
162 | | |
163 | | int ff_itut_t35_parse_payload_to_struct(FFITUTT35 *const itut_t35, FFITUTT35Aux *const aux, |
164 | | FFITUTT35Meta *metadata, int err_recognition) |
165 | 857k | { |
166 | 857k | int ret; |
167 | | |
168 | 857k | switch (itut_t35->country_code) { |
169 | 762k | case ITU_T_T35_COUNTRY_CODE_US: |
170 | 762k | switch (itut_t35->provider_code) { |
171 | 242k | case ITU_T_T35_PROVIDER_CODE_AOM: |
172 | 242k | ff_aom_uninit_film_grain_params(&metadata->aom_film_grain); |
173 | 242k | ret = ff_aom_parse_film_grain_sets(&metadata->aom_film_grain, |
174 | 242k | itut_t35->payload, itut_t35->payload_size); |
175 | 242k | if (ret < 0) |
176 | 172k | return ret; |
177 | 69.8k | break; |
178 | 69.8k | case ITU_T_T35_PROVIDER_CODE_ATSC: |
179 | 48.9k | switch (itut_t35->provider_oriented_code) { |
180 | 5.15k | case MKBETAG('D', 'T', 'G', '1'): // afd_data |
181 | 5.15k | av_buffer_unref(&metadata->afd); |
182 | 5.15k | metadata->afd = av_buffer_alloc(1); |
183 | 5.15k | if (!metadata->afd) |
184 | 0 | return AVERROR(ENOMEM); |
185 | | |
186 | 5.15k | *metadata->afd->data = *itut_t35->payload & 0xf; |
187 | | |
188 | 5.15k | break; |
189 | 43.7k | case MKBETAG('G', 'A', '9', '4'): // closed captions |
190 | 43.7k | ret = ff_parse_a53_cc(&metadata->a53_cc, itut_t35->payload, itut_t35->payload_size); |
191 | 43.7k | if (ret < 0) |
192 | 9.14k | return ret; |
193 | | |
194 | 34.6k | break; |
195 | 34.6k | default: // ignore unsupported identifiers |
196 | 0 | break; |
197 | 48.9k | } |
198 | 39.7k | break; |
199 | 310k | case ITU_T_T35_PROVIDER_CODE_SAMSUNG: { |
200 | 310k | size_t size; |
201 | 310k | AVDynamicHDRPlus *hdr_plus = av_dynamic_hdr_plus_alloc(&size); |
202 | 310k | if (!hdr_plus) |
203 | 0 | return AVERROR(ENOMEM); |
204 | | |
205 | 310k | ret = av_dynamic_hdr_plus_from_t35(hdr_plus, itut_t35->payload, |
206 | 310k | itut_t35->payload_size); |
207 | 310k | if (ret < 0) { |
208 | 236k | av_free(hdr_plus); |
209 | 236k | return ret; |
210 | 236k | } |
211 | | |
212 | 74.3k | av_buffer_unref(&metadata->hdr_plus); |
213 | 74.3k | metadata->hdr_plus = av_buffer_create((uint8_t *)hdr_plus, size, NULL, NULL, 0); |
214 | 74.3k | if (!metadata->hdr_plus) { |
215 | 0 | av_free(hdr_plus); |
216 | 0 | return AVERROR(ENOMEM); |
217 | 0 | } |
218 | | |
219 | 74.3k | break; |
220 | 74.3k | } |
221 | 74.3k | case ITU_T_T35_PROVIDER_CODE_DOLBY: { |
222 | 2.08k | AVDOVIMetadata *dovi; |
223 | | |
224 | 2.08k | if (!aux || !aux->dovi) |
225 | 2.08k | return 0; // ignore |
226 | | |
227 | 0 | ret = ff_dovi_rpu_parse(aux->dovi, itut_t35->payload, itut_t35->payload_size, |
228 | 0 | err_recognition); |
229 | 0 | if (ret < 0) |
230 | 0 | return 0; // ignore |
231 | | |
232 | 0 | ret = ff_dovi_get_metadata(aux->dovi, &dovi); |
233 | 0 | if (ret <= 0) |
234 | 0 | return ret; |
235 | | |
236 | 0 | av_buffer_unref(&metadata->dovi); |
237 | 0 | metadata->dovi = av_buffer_create((uint8_t *)dovi, ret, NULL, NULL, 0); |
238 | 0 | if (!metadata->dovi) { |
239 | 0 | av_free(dovi); |
240 | 0 | return AVERROR(ENOMEM); |
241 | 0 | } |
242 | | |
243 | 0 | break; |
244 | 0 | } |
245 | 158k | case ITU_T_T35_PROVIDER_CODE_SMPTE: { |
246 | 158k | size_t size; |
247 | 158k | AVDynamicHDRSmpte2094App5 *hdr_smpte2094_app5 = av_dynamic_hdr_smpte2094_app5_alloc(&size); |
248 | 158k | if (!hdr_smpte2094_app5) |
249 | 0 | return AVERROR(ENOMEM); |
250 | | |
251 | 158k | ret = av_dynamic_hdr_smpte2094_app5_from_t35(hdr_smpte2094_app5, itut_t35->payload, |
252 | 158k | itut_t35->payload_size); |
253 | 158k | if (ret < 0) { |
254 | 119k | av_free(hdr_smpte2094_app5); |
255 | 119k | return ret; |
256 | 119k | } |
257 | | |
258 | 38.3k | av_buffer_unref(&metadata->hdr_smpte2094_app5); |
259 | 38.3k | metadata->hdr_smpte2094_app5 = av_buffer_create((uint8_t *)hdr_smpte2094_app5, size, NULL, NULL, 0); |
260 | 38.3k | if (!metadata->hdr_smpte2094_app5) { |
261 | 0 | av_free(hdr_smpte2094_app5); |
262 | 0 | return AVERROR(ENOMEM); |
263 | 0 | } |
264 | | |
265 | 38.3k | break; |
266 | 38.3k | } |
267 | 38.3k | default: |
268 | 0 | break; |
269 | 762k | } |
270 | 222k | break; |
271 | 222k | case ITU_T_T35_COUNTRY_CODE_UK: |
272 | 2.89k | switch (itut_t35->provider_code) { |
273 | 2.89k | case ITU_T_T35_PROVIDER_CODE_VNOVA: |
274 | 2.89k | av_buffer_unref(&metadata->lcevc); |
275 | 2.89k | metadata->lcevc = av_buffer_alloc(itut_t35->payload_size); |
276 | 2.89k | if (!metadata->lcevc) |
277 | 0 | return AVERROR(ENOMEM); |
278 | | |
279 | 2.89k | memcpy(metadata->lcevc->data, itut_t35->payload, itut_t35->payload_size); |
280 | | |
281 | 2.89k | break; |
282 | 0 | default: |
283 | 0 | break; |
284 | 2.89k | } |
285 | 2.89k | break; |
286 | 92.2k | case ITU_T_T35_COUNTRY_CODE_CN: |
287 | 92.2k | switch (itut_t35->provider_code) { |
288 | 92.2k | case ITU_T_T35_PROVIDER_CODE_HDR_VIVID: { |
289 | 92.2k | size_t size; |
290 | 92.2k | AVDynamicHDRVivid *hdr_vivid = av_dynamic_hdr_vivid_alloc(&size); |
291 | 92.2k | if (!hdr_vivid) |
292 | 0 | return AVERROR(ENOMEM); |
293 | | |
294 | 92.2k | ret = ff_parse_itu_t_t35_to_dynamic_hdr_vivid(hdr_vivid, itut_t35->payload, |
295 | 92.2k | itut_t35->payload_size); |
296 | 92.2k | if (ret < 0) { |
297 | 48.9k | av_free(hdr_vivid); |
298 | 48.9k | return ret; |
299 | 48.9k | } |
300 | | |
301 | 43.3k | av_buffer_unref(&metadata->hdr_vivid); |
302 | 43.3k | metadata->hdr_vivid = av_buffer_create((uint8_t *)hdr_vivid, size, NULL, NULL, 0); |
303 | 43.3k | if (!metadata->hdr_vivid) { |
304 | 0 | av_free(hdr_vivid); |
305 | 0 | return AVERROR(ENOMEM); |
306 | 0 | } |
307 | 43.3k | break; |
308 | 43.3k | } |
309 | 43.3k | default: |
310 | 0 | break; |
311 | 92.2k | } |
312 | 43.3k | break; |
313 | | |
314 | 43.3k | default: |
315 | | // ignore unsupported provider codes |
316 | 0 | break; |
317 | 857k | } |
318 | | |
319 | 268k | return 0; |
320 | 857k | } |
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 | 0 | { |
325 | 0 | FFITUTT35Meta metadata = { 0 }; |
326 | 0 | int ret; |
327 | |
|
328 | 0 | ret = ff_itut_t35_parse_payload_to_struct(itut_t35, aux, &metadata, avctx->err_recognition); |
329 | 0 | if (ret < 0) |
330 | 0 | return ret; |
331 | | |
332 | 0 | if (metadata.afd) { |
333 | 0 | if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_AFD, metadata.afd)) |
334 | 0 | av_buffer_unref(&metadata.afd); |
335 | 0 | metadata.afd = NULL; |
336 | 0 | } |
337 | |
|
338 | 0 | if (metadata.a53_cc) { |
339 | 0 | ret = ff_frame_new_side_data_from_buf(avctx, frame, AV_FRAME_DATA_A53_CC, &metadata.a53_cc); |
340 | 0 | if (ret < 0) |
341 | 0 | return ret; |
342 | 0 | } |
343 | | |
344 | 0 | if (metadata.aom_film_grain.enable) { |
345 | 0 | ret = ff_aom_attach_film_grain_sets(&metadata.aom_film_grain, frame); |
346 | 0 | if (ret < 0) |
347 | 0 | return ret; |
348 | 0 | } |
349 | | |
350 | 0 | if (metadata.hdr_plus) { |
351 | 0 | ret = ff_frame_new_side_data_from_buf(avctx, frame, AV_FRAME_DATA_DYNAMIC_HDR_PLUS, |
352 | 0 | &metadata.hdr_plus); |
353 | 0 | if (ret < 0) |
354 | 0 | return ret; |
355 | 0 | } |
356 | | |
357 | 0 | if (metadata.dovi) { |
358 | 0 | AVFrameSideData *sd = av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_DOVI_METADATA, |
359 | 0 | metadata.dovi); |
360 | 0 | if (!sd) { |
361 | 0 | av_buffer_unref(&metadata.dovi); |
362 | 0 | return AVERROR(ENOMEM); |
363 | 0 | } |
364 | 0 | metadata.dovi = NULL; |
365 | 0 | } |
366 | | |
367 | 0 | if (metadata.hdr_smpte2094_app5) { |
368 | 0 | ret = ff_frame_new_side_data_from_buf(avctx, frame, AV_FRAME_DATA_DYNAMIC_HDR_SMPTE_2094_APP5, |
369 | 0 | &metadata.hdr_smpte2094_app5); |
370 | 0 | if (ret < 0) |
371 | 0 | return ret; |
372 | 0 | } |
373 | | |
374 | 0 | if (metadata.lcevc) { |
375 | 0 | ret = ff_frame_new_side_data_from_buf(avctx, frame, AV_FRAME_DATA_LCEVC, |
376 | 0 | &metadata.lcevc); |
377 | 0 | if (ret < 0) |
378 | 0 | return ret; |
379 | 0 | } |
380 | | |
381 | 0 | if (metadata.hdr_vivid) { |
382 | 0 | ret = ff_frame_new_side_data_from_buf(avctx, frame, AV_FRAME_DATA_DYNAMIC_HDR_VIVID, |
383 | 0 | &metadata.hdr_vivid); |
384 | 0 | if (ret < 0) |
385 | 0 | return ret; |
386 | 0 | } |
387 | | |
388 | 0 | ff_itut_t35_unref(&metadata); |
389 | |
|
390 | 0 | return 0; |
391 | 0 | } |
392 | | |
393 | | void ff_itut_t35_unref(FFITUTT35Meta *metadata) |
394 | 18.6M | { |
395 | 18.6M | ff_aom_uninit_film_grain_params(&metadata->aom_film_grain); |
396 | 18.6M | av_buffer_unref(&metadata->afd); |
397 | 18.6M | av_buffer_unref(&metadata->a53_cc); |
398 | 18.6M | av_buffer_unref(&metadata->hdr_plus); |
399 | 18.6M | av_buffer_unref(&metadata->hdr_smpte2094_app5); |
400 | 18.6M | av_buffer_unref(&metadata->lcevc); |
401 | 18.6M | av_buffer_unref(&metadata->dovi); |
402 | 18.6M | av_buffer_unref(&metadata->hdr_vivid); |
403 | 18.6M | } |