FFmpeg
Loading...
Searching...
No Matches
dovi_rpudec.c
Go to the documentation of this file.
1/*
2 * Dolby Vision RPU decoder
3 *
4 * Copyright (C) 2021 Jan Ekström
5 * Copyright (C) 2021-2024 Niklas Haas
6 *
7 * This file is part of FFmpeg.
8 *
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include "libavutil/mem.h"
25#include "libavutil/crc.h"
26
27#include "avcodec.h"
28#include "dovi_rpu.h"
29#include "golomb.h"
30#include "get_bits.h"
31#include "libavutil/refstruct.h"
32
34{
35 AVDOVIMetadata *dovi;
36 size_t dovi_size;
37
38 if (!s->mapping || !s->color)
39 return 0; /* incomplete dovi metadata */
40
41 dovi = av_dovi_metadata_alloc(&dovi_size);
42 if (!dovi)
43 return AVERROR(ENOMEM);
44
45 /* Copy only the parts of these structs known to us at compiler-time. */
46#define COPY(t, a, b, last) memcpy(a, b, offsetof(t, last) + sizeof((b)->last))
47 COPY(AVDOVIRpuDataHeader, av_dovi_get_header(dovi), &s->header, ext_mapping_idc_5_7);
48 COPY(AVDOVIDataMapping, av_dovi_get_mapping(dovi), s->mapping, nlq_pivots);
49 COPY(AVDOVIColorMetadata, av_dovi_get_color(dovi), s->color, source_diagonal);
50
51 if (s->ext_blocks) {
52 const DOVIExt *ext = s->ext_blocks;
53 size_t ext_sz = FFMIN(sizeof(AVDOVIDmData), dovi->ext_block_size);
54 for (int i = 0; i < ext->num_static; i++)
55 memcpy(av_dovi_get_ext(dovi, dovi->num_ext_blocks++), &ext->dm_static[i], ext_sz);
56 for (int i = 0; i < ext->num_dynamic; i++)
57 memcpy(av_dovi_get_ext(dovi, dovi->num_ext_blocks++), &ext->dm_dynamic[i], ext_sz);
58 }
59
60 *out_metadata = dovi;
61 return dovi_size;
62}
63
65{
67 AVDOVIMetadata *dovi;
68 AVBufferRef *buf;
69 int size;
70
71 size = ff_dovi_get_metadata(s, &dovi);
72 if (size <= 0)
73 return size;
74
75 buf = av_buffer_create((uint8_t *) dovi, size, NULL, NULL, 0);
76 if (!buf) {
77 av_free(dovi);
78 return AVERROR(ENOMEM);
79 }
80
82 if (!sd) {
83 av_buffer_unref(&buf);
84 return AVERROR(ENOMEM);
85 }
86
87 return 0;
88}
89
90static inline uint64_t get_ue_coef(GetBitContext *gb, const AVDOVIRpuDataHeader *hdr)
91{
92 uint64_t ipart;
93 union { uint32_t u32; float f32; } fpart;
94
95 switch (hdr->coef_data_type) {
96 case RPU_COEFF_FIXED:
97 ipart = get_ue_golomb_long(gb);
98 fpart.u32 = get_bits_long(gb, hdr->coef_log2_denom);
99 return (ipart << hdr->coef_log2_denom) | fpart.u32;
100
101 case RPU_COEFF_FLOAT:
102 fpart.u32 = get_bits_long(gb, 32);
103 return fpart.f32 * (1LL << hdr->coef_log2_denom);
104 }
105
106 return 0; /* unreachable */
107}
108
110{
111 int64_t ipart;
112 union { uint32_t u32; float f32; } fpart;
113
114 switch (hdr->coef_data_type) {
115 case RPU_COEFF_FIXED:
116 ipart = get_se_golomb_long(gb);
117 fpart.u32 = get_bits_long(gb, hdr->coef_log2_denom);
118 return ipart * (1LL << hdr->coef_log2_denom) | fpart.u32;
119
120 case RPU_COEFF_FLOAT:
121 fpart.u32 = get_bits_long(gb, 32);
122 return fpart.f32 * (1LL << hdr->coef_log2_denom);
123 }
124
125 return 0; /* unreachable */
126}
127
128static inline unsigned get_variable_bits(GetBitContext *gb, int n)
129{
130 unsigned int value = get_bits(gb, n);
131 int read_more = get_bits1(gb);
132 while (read_more) {
133 value = (value + 1) << n;
134 value |= get_bits(gb, n);
135 read_more = get_bits1(gb);
136 }
137 return value;
138}
139
140#define VALIDATE(VAR, MIN, MAX) \
141 do { \
142 if (VAR < MIN || VAR > MAX) { \
143 av_log(s->logctx, AV_LOG_ERROR, "RPU validation failed: " \
144 #MIN" <= "#VAR" = %d <= "#MAX"\n", (int) VAR); \
145 ff_dovi_ctx_unref(s); \
146 return AVERROR_INVALIDDATA; \
147 } \
148 } while (0)
149
151{
152 switch (dm->level) {
153 case 1:
154 dm->l1.min_pq = get_bits(gb, 12);
155 dm->l1.max_pq = get_bits(gb, 12);
156 dm->l1.avg_pq = get_bits(gb, 12);
157 break;
158 case 2:
159 dm->l2.target_max_pq = get_bits(gb, 12);
160 dm->l2.trim_slope = get_bits(gb, 12);
161 dm->l2.trim_offset = get_bits(gb, 12);
162 dm->l2.trim_power = get_bits(gb, 12);
163 dm->l2.trim_chroma_weight = get_bits(gb, 12);
164 dm->l2.trim_saturation_gain = get_bits(gb, 12);
165 dm->l2.ms_weight = get_sbits(gb, 13);
166 VALIDATE(dm->l2.ms_weight, -1, 4095);
167 break;
168 case 4:
169 dm->l4.anchor_pq = get_bits(gb, 12);
170 dm->l4.anchor_power = get_bits(gb, 12);
171 break;
172 case 5:
173 dm->l5.left_offset = get_bits(gb, 13);
174 dm->l5.right_offset = get_bits(gb, 13);
175 dm->l5.top_offset = get_bits(gb, 13);
176 dm->l5.bottom_offset = get_bits(gb, 13);
177 break;
178 case 6:
179 dm->l6.max_luminance = get_bits(gb, 16);
180 dm->l6.min_luminance = get_bits(gb, 16);
181 dm->l6.max_cll = get_bits(gb, 16);
182 dm->l6.max_fall = get_bits(gb, 16);
183 break;
184 case 255:
185 dm->l255.dm_run_mode = get_bits(gb, 8);
186 dm->l255.dm_run_version = get_bits(gb, 8);
187 for (int i = 0; i < 4; i++)
188 dm->l255.dm_debug[i] = get_bits(gb, 8);
189 break;
190 default:
191 avpriv_request_sample(s->logctx, "Dolby Vision DM v1 level %u", dm->level);
192 }
193
194 return 0;
195}
196
198{
199 AVCIExy xy;
200 const int denom = 32767;
201 xy.x = av_make_q(get_sbits(gb, 16), denom);
202 xy.y = av_make_q(get_sbits(gb, 16), denom);
203 return xy;
204}
205
207 int ext_block_length)
208{
209 switch (dm->level) {
210 case 3:
211 dm->l3.min_pq_offset = get_bits(gb, 12);
212 dm->l3.max_pq_offset = get_bits(gb, 12);
213 dm->l3.avg_pq_offset = get_bits(gb, 12);
214 break;
215 case 8:
216 dm->l8.target_display_index = get_bits(gb, 8);
217 dm->l8.trim_slope = get_bits(gb, 12);
218 dm->l8.trim_offset = get_bits(gb, 12);
219 dm->l8.trim_power = get_bits(gb, 12);
220 dm->l8.trim_chroma_weight = get_bits(gb, 12);
221 dm->l8.trim_saturation_gain = get_bits(gb, 12);
222 dm->l8.ms_weight = get_bits(gb, 12);
223 if (ext_block_length < 12)
224 break;
225 dm->l8.target_mid_contrast = get_bits(gb, 12);
226 if (ext_block_length < 13)
227 break;
228 dm->l8.clip_trim = get_bits(gb, 12);
229 if (ext_block_length < 19)
230 break;
231 for (int i = 0; i < 6; i++)
232 dm->l8.saturation_vector_field[i] = get_bits(gb, 8);
233 if (ext_block_length < 25)
234 break;
235 for (int i = 0; i < 6; i++)
236 dm->l8.hue_vector_field[i] = get_bits(gb, 8);
237 break;
238 case 9:
239 dm->l9.source_primary_index = get_bits(gb, 8);
240 if (ext_block_length < 17)
241 break;
246 break;
247 case 10:
248 dm->l10.target_display_index = get_bits(gb, 8);
249 dm->l10.target_max_pq = get_bits(gb, 12);
250 dm->l10.target_min_pq = get_bits(gb, 12);
251 dm->l10.target_primary_index = get_bits(gb, 8);
252 if (ext_block_length < 21)
253 break;
258 break;
259 case 11:
260 dm->l11.content_type = get_bits(gb, 8);
261 dm->l11.whitepoint = get_bits(gb, 4);
263 skip_bits(gb, 3); /* reserved */
264 skip_bits(gb, 8); /* reserved */
265 skip_bits(gb, 8); /* reserved */
266 break;
267 case 254:
268 dm->l254.dm_mode = get_bits(gb, 8);
269 dm->l254.dm_version_index = get_bits(gb, 8);
270 break;
271 default:
272 avpriv_request_sample(s->logctx, "Dolby Vision DM v2 level %u", dm->level);
273 }
274
275 return 0;
276}
277
278static int parse_ext_blocks(DOVIContext *s, GetBitContext *gb, int ver,
279 int compression, int err_recognition)
280{
281 int num_ext_blocks, ext_block_length, start_pos, parsed_bits, ret;
282 DOVIExt *ext = s->ext_blocks;
283
284 num_ext_blocks = get_ue_golomb_31(gb);
285 align_get_bits(gb);
286
287 if (num_ext_blocks && !ext) {
288 ext = s->ext_blocks = av_refstruct_allocz(sizeof(*s->ext_blocks));
289 if (!ext)
290 return AVERROR(ENOMEM);
291 }
292
293 while (num_ext_blocks--) {
295 AVDOVIDmData *dm;
296 uint8_t level;
297
298 ext_block_length = get_ue_golomb_31(gb);
299 level = get_bits(gb, 8);
300 start_pos = get_bits_count(gb);
301
303 if (compression) {
304 av_log(s->logctx, AV_LOG_WARNING, "Compressed DM RPU contains "
305 "static extension block level %d\n", level);
306 if (err_recognition & (AV_EF_AGGRESSIVE | AV_EF_EXPLODE))
307 return AVERROR_INVALIDDATA;
308 dm = &dummy;
309 } else {
310 if (ext->num_static >= FF_ARRAY_ELEMS(ext->dm_static))
311 return AVERROR_INVALIDDATA;
312 dm = &ext->dm_static[ext->num_static++];
313 }
314 } else {
315 if (ext->num_dynamic >= FF_ARRAY_ELEMS(ext->dm_dynamic))
316 return AVERROR_INVALIDDATA;
317 dm = &ext->dm_dynamic[ext->num_dynamic++];
318 }
319
320 memset(dm, 0, sizeof(*dm));
321 dm->level = level;
322 switch (ver) {
323 case 1: ret = parse_ext_v1(s, gb, dm); break;
324 case 2: ret = parse_ext_v2(s, gb, dm, ext_block_length); break;
325 default:
326 avpriv_request_sample(s->logctx, "Dolby Vision DM v%d", ver);
327 goto skip;
328 }
329
330 if (ret < 0)
331 return ret;
332
333skip:
334 parsed_bits = get_bits_count(gb) - start_pos;
335 if (parsed_bits > ext_block_length * 8)
336 return AVERROR_INVALIDDATA;
337 skip_bits(gb, ext_block_length * 8 - parsed_bits);
338 }
339
340 return 0;
341}
342
343int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size,
344 int err_recognition)
345{
346 AVDOVIRpuDataHeader *hdr = &s->header;
347 GetBitContext *gb = &(GetBitContext){0};
348 int ret;
349
350 uint8_t rpu_type;
351 uint8_t vdr_seq_info_present;
352 uint8_t vdr_dm_metadata_present;
353 uint8_t dm_compression = 0;
354 uint8_t use_prev_vdr_rpu;
355 uint8_t use_nlq;
356 uint8_t profile;
357 uint8_t compression = s->cfg.dv_profile ? s->cfg.dv_md_compression : 0;
358
359 if (rpu_size < 5)
360 return AVERROR_INVALIDDATA;
361
362 /* Container */
363 if (s->cfg.dv_profile == 10 /* dav1.10 */) {
364 /* DV inside AV1 reuses an EMDF container skeleton, but with fixed
365 * values - so we can effectively treat this as a magic byte sequence.
366 *
367 * The exact fields are, as follows:
368 * emdf_version : f(2) = 0
369 * key_id : f(3) = 6
370 * emdf_payload_id : f(5) = 31
371 * emdf_payload_id_ext : var(5) = 225
372 * smploffste : f(1) = 0
373 * duratione : f(1) = 0
374 * groupide : f(1) = 0
375 * codecdatae : f(1) = 0
376 * discard_unknown_payload : f(1) = 1
377 */
378 const unsigned header_magic = 0x01be6841u;
379 unsigned emdf_header, emdf_payload_size, emdf_protection;
380 if ((ret = init_get_bits8(gb, rpu, rpu_size)) < 0)
381 return ret;
382 emdf_header = get_bits_long(gb, 27);
383 VALIDATE(emdf_header, header_magic, header_magic);
384 emdf_payload_size = get_variable_bits(gb, 8);
385 VALIDATE(emdf_payload_size, 6, 512);
386 if (emdf_payload_size * 8 > get_bits_left(gb))
387 return AVERROR_INVALIDDATA;
388
389 /* The payload is not byte-aligned (off by *one* bit, curse Dolby),
390 * so copy into a fresh buffer to preserve byte alignment of the
391 * RPU struct */
392 av_fast_padded_malloc(&s->rpu_buf, &s->rpu_buf_sz, emdf_payload_size);
393 if (!s->rpu_buf)
394 return AVERROR(ENOMEM);
395 for (int i = 0; i < emdf_payload_size; i++)
396 s->rpu_buf[i] = get_bits(gb, 8);
397 rpu = s->rpu_buf;
398 rpu_size = emdf_payload_size;
399
400 /* Validate EMDF footer */
401 emdf_protection = get_bits(gb, 5 + 12);
402 VALIDATE(emdf_protection, 0x400, 0x400);
403 } else {
404 /* NAL unit with prefix and trailing zeroes */
405 VALIDATE(rpu[0], 25, 25); /* NAL prefix */
406 rpu++;
407 rpu_size--;
408 }
409
410 if ((ret = init_get_bits8(gb, rpu, rpu_size)) < 0)
411 return ret;
412
413 /* RPU header */
414 rpu_type = get_bits(gb, 6);
415 if (rpu_type != 2) {
416 av_log(s->logctx, AV_LOG_WARNING, "Unrecognized RPU type "
417 "%"PRIu8", ignoring\n", rpu_type);
418 return 0;
419 }
420
421 hdr->rpu_type = rpu_type;
422 hdr->rpu_format = get_bits(gb, 11);
423
424 /* Values specific to RPU type 2 */
425 hdr->vdr_rpu_profile = get_bits(gb, 4);
426 hdr->vdr_rpu_level = get_bits(gb, 4);
427
428 vdr_seq_info_present = get_bits1(gb);
429 if (vdr_seq_info_present) {
431 hdr->coef_data_type = get_bits(gb, 2);
433 switch (hdr->coef_data_type) {
434 case RPU_COEFF_FIXED:
436 VALIDATE(hdr->coef_log2_denom, 13, 32);
437 break;
438 case RPU_COEFF_FLOAT:
439 hdr->coef_log2_denom = 32; /* arbitrary, choose maximum precision */
440 break;
441 }
442
443 hdr->vdr_rpu_normalized_idc = get_bits(gb, 2);
445
446 if ((hdr->rpu_format & 0x700) == 0) {
447 int bl_bit_depth_minus8 = get_ue_golomb_31(gb);
448 int el_bit_depth_minus8 = get_ue_golomb_long(gb);
449 int vdr_bit_depth_minus8 = get_ue_golomb_31(gb);
450 /* ext_mapping_idc is in the upper 8 bits of el_bit_depth_minus8 */
451 int ext_mapping_idc = el_bit_depth_minus8 >> 8;
452 el_bit_depth_minus8 = el_bit_depth_minus8 & 0xFF;
453 VALIDATE(bl_bit_depth_minus8, 0, 8);
454 VALIDATE(el_bit_depth_minus8, 0, 8);
455 VALIDATE(ext_mapping_idc, 0, 0xFF);
456 VALIDATE(vdr_bit_depth_minus8, 0, 8);
457 hdr->bl_bit_depth = bl_bit_depth_minus8 + 8;
458 hdr->el_bit_depth = el_bit_depth_minus8 + 8;
459 hdr->ext_mapping_idc_0_4 = ext_mapping_idc & 0x1f; /* 5 bits */
460 hdr->ext_mapping_idc_5_7 = ext_mapping_idc >> 5;
461 hdr->vdr_bit_depth = vdr_bit_depth_minus8 + 8;
463 dm_compression = get_bits(gb, 3);
466 } else {
467 avpriv_request_sample(s->logctx, "Unsupported RPU format 0x%x\n", hdr->rpu_format);
470 }
471 } else {
472 /* lack of documentation/samples */
473 avpriv_request_sample(s->logctx, "Missing RPU VDR sequence info\n");
476 }
477
478 vdr_dm_metadata_present = get_bits1(gb);
479 if (dm_compression > 1) {
480 /* It seems no device supports this */
481 av_log(s->logctx, AV_LOG_ERROR, "Dynamic metadata compression is not "
482 "yet implemented");
484 } else if (dm_compression && !vdr_dm_metadata_present) {
485 av_log(s->logctx, AV_LOG_ERROR, "Nonzero DM metadata compression method "
486 "but no DM metadata present");
487 return AVERROR_INVALIDDATA;
488 }
489
490 use_prev_vdr_rpu = get_bits1(gb);
491 use_nlq = (hdr->rpu_format & 0x700) == 0 && !hdr->disable_residual_flag;
492
493 profile = s->cfg.dv_profile ? s->cfg.dv_profile : ff_dovi_guess_profile_hevc(hdr);
494 if (profile == 5 && use_nlq) {
495 av_log(s->logctx, AV_LOG_ERROR, "Profile 5 RPUs should not use NLQ\n");
497 return AVERROR_INVALIDDATA;
498 }
499
500 if (err_recognition & (AV_EF_COMPLIANT | AV_EF_CAREFUL)) {
501 if (profile < 8 && compression) {
502 av_log(s->logctx, AV_LOG_ERROR, "Profile %d RPUs should not use "
503 "metadata compression.", profile);
504 return AVERROR_INVALIDDATA;
505 }
506
507 if (use_prev_vdr_rpu && !compression) {
508 av_log(s->logctx, AV_LOG_ERROR, "Uncompressed RPUs should not have "
509 "use_prev_vdr_rpu=1\n");
510 return AVERROR_INVALIDDATA;
511 }
512
513 if (dm_compression && !compression) {
514 av_log(s->logctx, AV_LOG_ERROR, "Uncompressed RPUs should not use "
515 "dm_compression=%d\n", dm_compression);
516 return AVERROR_INVALIDDATA;
517 }
518 }
519
520 if (use_prev_vdr_rpu) {
521 int prev_vdr_rpu_id = get_ue_golomb_31(gb);
522 VALIDATE(prev_vdr_rpu_id, 0, DOVI_MAX_DM_ID);
523 if (!s->vdr[prev_vdr_rpu_id])
524 prev_vdr_rpu_id = 0;
525 if (!s->vdr[prev_vdr_rpu_id]) {
526 /* FIXME: Technically, the spec says that in this case we should
527 * synthesize "neutral" vdr metadata, but easier to just error
528 * out as this corner case is not hit in practice */
529 av_log(s->logctx, AV_LOG_ERROR, "Unknown previous RPU ID: %u\n",
530 prev_vdr_rpu_id);
532 return AVERROR_INVALIDDATA;
533 }
534 s->mapping = s->vdr[prev_vdr_rpu_id];
535 } else {
536 AVDOVIDataMapping *mapping;
537 int vdr_rpu_id = get_ue_golomb_31(gb);
538 VALIDATE(vdr_rpu_id, 0, DOVI_MAX_DM_ID);
539 if (!s->vdr[vdr_rpu_id]) {
540 s->vdr[vdr_rpu_id] = av_refstruct_allocz(sizeof(AVDOVIDataMapping));
541 if (!s->vdr[vdr_rpu_id]) {
543 return AVERROR(ENOMEM);
544 }
545 }
546
547 s->mapping = mapping = s->vdr[vdr_rpu_id];
548 mapping->vdr_rpu_id = vdr_rpu_id;
551
552 for (int c = 0; c < 3; c++) {
553 AVDOVIReshapingCurve *curve = &mapping->curves[c];
554 int num_pivots_minus_2 = get_ue_golomb_31(gb);
555 int pivot = 0;
556
557 VALIDATE(num_pivots_minus_2, 0, AV_DOVI_MAX_PIECES - 1);
558 curve->num_pivots = num_pivots_minus_2 + 2;
559 for (int i = 0; i < curve->num_pivots; i++) {
560 pivot += get_bits(gb, hdr->bl_bit_depth);
561 curve->pivots[i] = av_clip_uint16(pivot);
562 }
563 }
564
565 if (use_nlq) {
566 int nlq_pivot = 0;
567 mapping->nlq_method_idc = get_bits(gb, 3);
568
569 for (int i = 0; i < 2; i++) {
570 nlq_pivot += get_bits(gb, hdr->bl_bit_depth);
571 mapping->nlq_pivots[i] = av_clip_uint16(nlq_pivot);
572 }
573
574 /**
575 * The patent mentions another legal value, NLQ_MU_LAW, but it's
576 * not documented anywhere how to parse or apply that type of NLQ.
577 */
579 } else {
581 }
582
583 mapping->num_x_partitions = get_ue_golomb_long(gb) + 1;
584 mapping->num_y_partitions = get_ue_golomb_long(gb) + 1;
585 VALIDATE(mapping->num_x_partitions, 1, 0xFFFF);
586 VALIDATE(mapping->num_y_partitions, 1, 0xFFFF);
587 /* End of rpu_data_header(), start of vdr_rpu_data_payload() */
588
589 for (int c = 0; c < 3; c++) {
590 AVDOVIReshapingCurve *curve = &mapping->curves[c];
591 for (int i = 0; i < curve->num_pivots - 1; i++) {
592 int mapping_idc = get_ue_golomb_31(gb);
593 VALIDATE(mapping_idc, 0, 1);
594 curve->mapping_idc[i] = mapping_idc;
595 switch (mapping_idc) {
597 int poly_order_minus1 = get_ue_golomb_31(gb);
598 VALIDATE(poly_order_minus1, 0, 1);
599 curve->poly_order[i] = poly_order_minus1 + 1;
600 if (poly_order_minus1 == 0) {
601 int linear_interp_flag = get_bits1(gb);
602 if (linear_interp_flag) {
603 /* lack of documentation/samples */
604 avpriv_request_sample(s->logctx, "Dolby Vision "
605 "linear interpolation");
608 }
609 }
610 for (int k = 0; k <= curve->poly_order[i]; k++)
611 curve->poly_coef[i][k] = get_se_coef(gb, hdr);
612 break;
613 }
614 case AV_DOVI_MAPPING_MMR: {
615 int mmr_order_minus1 = get_bits(gb, 2);
616 VALIDATE(mmr_order_minus1, 0, 2);
617 curve->mmr_order[i] = mmr_order_minus1 + 1;
618 curve->mmr_constant[i] = get_se_coef(gb, hdr);
619 for (int j = 0; j < curve->mmr_order[i]; j++) {
620 for (int k = 0; k < 7; k++)
621 curve->mmr_coef[i][j][k] = get_se_coef(gb, hdr);
622 }
623 break;
624 }
625 }
626 }
627 }
628
629 if (use_nlq) {
630 for (int c = 0; c < 3; c++) {
631 AVDOVINLQParams *nlq = &mapping->nlq[c];
632 nlq->nlq_offset = get_bits(gb, hdr->el_bit_depth);
633 nlq->vdr_in_max = get_ue_coef(gb, hdr);
634 switch (mapping->nlq_method_idc) {
636 nlq->linear_deadzone_slope = get_ue_coef(gb, hdr);
638 break;
639 }
640 }
641 }
642 }
643
644 if (vdr_dm_metadata_present) {
646 int affected_dm_id = get_ue_golomb_31(gb);
647 int current_dm_id = get_ue_golomb_31(gb);
648 VALIDATE(affected_dm_id, 0, DOVI_MAX_DM_ID);
649 VALIDATE(current_dm_id, 0, DOVI_MAX_DM_ID);
650 if (affected_dm_id != current_dm_id) {
651 /* The spec does not explain these fields at all, and there is
652 * a lack of samples to understand how they're supposed to work,
653 * so just assert them being equal for now */
654 avpriv_request_sample(s->logctx, "affected/current_dm_metadata_id "
655 "mismatch? %u != %u\n", affected_dm_id, current_dm_id);
658 }
659
660 if (!s->dm) {
662 if (!s->dm) {
664 return AVERROR(ENOMEM);
665 }
666 }
667
668 s->color = color = s->dm;
669 color->dm_metadata_id = affected_dm_id;
670 color->scene_refresh_flag = get_ue_golomb_31(gb);
671 if (!dm_compression) {
672 for (int i = 0; i < 9; i++)
673 color->ycc_to_rgb_matrix[i] = av_make_q(get_sbits(gb, 16), 1 << 13);
674 for (int i = 0; i < 3; i++) {
675 int denom = profile == 4 ? (1 << 30) : (1 << 28);
676 unsigned offset = get_bits_long(gb, 32);
677 if (offset > INT_MAX) {
678 /* Ensure the result fits inside AVRational */
679 offset >>= 1;
680 denom >>= 1;
681 }
682 color->ycc_to_rgb_offset[i] = av_make_q(offset, denom);
683 }
684 for (int i = 0; i < 9; i++)
685 color->rgb_to_lms_matrix[i] = av_make_q(get_sbits(gb, 16), 1 << 14);
686
687 color->signal_eotf = get_bits(gb, 16);
688 color->signal_eotf_param0 = get_bits(gb, 16);
689 color->signal_eotf_param1 = get_bits(gb, 16);
690 color->signal_eotf_param2 = get_bits_long(gb, 32);
691 color->signal_bit_depth = get_bits(gb, 5);
692 VALIDATE(color->signal_bit_depth, 8, 16);
693 color->signal_color_space = get_bits(gb, 2);
694 color->signal_chroma_format = get_bits(gb, 2);
695 color->signal_full_range_flag = get_bits(gb, 2);
696 color->source_min_pq = get_bits(gb, 12);
697 color->source_max_pq = get_bits(gb, 12);
698 color->source_diagonal = get_bits(gb, 10);
699 }
700
701 /* Parse extension blocks */
702 if (s->ext_blocks) {
703 DOVIExt *ext = s->ext_blocks;
704 if (!dm_compression)
705 ext->num_static = 0;
706 ext->num_dynamic = 0;
707 }
708 if ((ret = parse_ext_blocks(s, gb, 1, dm_compression, err_recognition)) < 0) {
710 return ret;
711 }
712
713 if (get_bits_left(gb) > 48 /* padding + CRC32 + terminator */) {
714 if ((ret = parse_ext_blocks(s, gb, 2, dm_compression, err_recognition)) < 0) {
716 return ret;
717 }
718 }
719 } else {
720 s->color = &ff_dovi_color_default;
721 av_refstruct_unref(&s->ext_blocks);
722 }
723
724 align_get_bits(gb);
725 skip_bits(gb, 32); /* CRC32 */
726 if (get_bits(gb, 8) != 0x80) {
727 avpriv_request_sample(s->logctx, "Unexpected RPU format");
730 }
731
732 if (err_recognition & AV_EF_CRCCHECK) {
733 rpu_size = get_bits_count(gb) / 8;
735 -1, rpu, rpu_size - 1)); /* exclude 0x80 */
736 if (crc) {
737 av_log(s->logctx, AV_LOG_ERROR, "RPU CRC mismatch: %X\n", crc);
738 if (err_recognition & AV_EF_EXPLODE) {
740 return AVERROR_INVALIDDATA;
741 }
742 }
743 }
744
745 return 0;
746}
Libavcodec external API header.
static void BS_FUNC skip(BSCTX *bc, unsigned int n)
Skip n bits in the buffer.
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define av_clip_uint16
Definition common.h:112
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
Public header for CRC hash function implementation.
#define AV_EF_CRCCHECK
Verify checksums embedded in the bitstream (could be of either encoded or decoded data,...
Definition defs.h:48
#define AV_EF_COMPLIANT
consider all spec non compliances as errors
Definition defs.h:55
#define AV_EF_EXPLODE
abort decoding on minor error detection
Definition defs.h:51
#define AV_EF_AGGRESSIVE
consider things that a sane encoder/muxer should not do as an error
Definition defs.h:56
#define AV_EF_CAREFUL
consider things that violate the spec, are fast to calculate and have not been seen in the wild as er...
Definition defs.h:54
static AVFrame * frame
AVDOVIMetadata * av_dovi_metadata_alloc(size_t *size)
Allocate an AVDOVIMetadata structure and initialize its fields to default values.
Definition dovi_meta.c:45
static av_always_inline AVDOVIColorMetadata * av_dovi_get_color(const AVDOVIMetadata *data)
Definition dovi_meta.h:375
static av_always_inline AVDOVIRpuDataHeader * av_dovi_get_header(const AVDOVIMetadata *data)
Definition dovi_meta.h:363
static av_always_inline AVDOVIDmData * av_dovi_get_ext(const AVDOVIMetadata *data, int index)
Gets the specified Dolby Vision Display Management (DM) metadata.
Definition dovi_meta.h:385
@ AV_DOVI_MAPPING_MMR
Definition dovi_meta.h:109
@ AV_DOVI_MAPPING_POLYNOMIAL
Definition dovi_meta.h:108
@ AV_DOVI_NLQ_NONE
Definition dovi_meta.h:131
@ AV_DOVI_NLQ_LINEAR_DZ
Definition dovi_meta.h:132
static av_always_inline AVDOVIDataMapping * av_dovi_get_mapping(const AVDOVIMetadata *data)
Definition dovi_meta.h:369
#define AV_DOVI_MAX_PIECES
Coefficients of a piece-wise function.
Definition dovi_meta.h:116
const AVDOVIColorMetadata ff_dovi_color_default
Definition dovi_rpu.c:94
int ff_dovi_guess_profile_hevc(const AVDOVIRpuDataHeader *hdr)
Internal helper function to guess the correct DV profile for HEVC.
Definition dovi_rpu.c:72
void ff_dovi_ctx_unref(DOVIContext *s)
Completely reset a DOVIContext, preserving only logctx.
Definition dovi_rpu.c:30
@ RPU_COEFF_FIXED
Definition dovi_rpu.h:183
@ RPU_COEFF_FLOAT
Definition dovi_rpu.h:184
static int ff_dovi_rpu_extension_is_static(int level)
Definition dovi_rpu.h:197
#define DOVI_MAX_DM_ID
Definition dovi_rpu.h:33
int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size, int err_recognition)
Parse the contents of a Dolby Vision RPU and update the parsed values in the DOVIContext struct.
#define VALIDATE(VAR, MIN, MAX)
static int parse_ext_v1(DOVIContext *s, GetBitContext *gb, AVDOVIDmData *dm)
static int parse_ext_v2(DOVIContext *s, GetBitContext *gb, AVDOVIDmData *dm, int ext_block_length)
#define COPY(t, a, b, last)
static unsigned get_variable_bits(GetBitContext *gb, int n)
static uint64_t get_ue_coef(GetBitContext *gb, const AVDOVIRpuDataHeader *hdr)
Definition dovi_rpudec.c:90
static int64_t get_se_coef(GetBitContext *gb, const AVDOVIRpuDataHeader *hdr)
static int parse_ext_blocks(DOVIContext *s, GetBitContext *gb, int ver, int compression, int err_recognition)
static AVCIExy get_cie_xy(GetBitContext *gb)
int ff_dovi_get_metadata(DOVIContext *s, AVDOVIMetadata **out_metadata)
Get the decoded AVDOVIMetadata.
Definition dovi_rpudec.c:33
int ff_dovi_attach_side_data(DOVIContext *s, AVFrame *frame)
Attach the decoded AVDOVIMetadata as side data to an AVFrame.
Definition dovi_rpudec.c:64
double value
Definition eval.c:102
static int dummy
Definition ffplay.c:3754
bitstream reader API header.
static unsigned int get_bits_long(GetBitContext *s, int n)
Read 0-32 bits.
Definition get_bits.h:424
static int get_sbits(GetBitContext *s, int n)
Definition get_bits.h:322
static int get_bits_left(GetBitContext *gb)
Definition get_bits.h:688
static unsigned int get_bits1(GetBitContext *s)
Definition get_bits.h:391
static void skip_bits(GetBitContext *s, int n)
Definition get_bits.h:383
static int init_get_bits8(GetBitContext *s, const uint8_t *buffer, int byte_size)
Initialize GetBitContext.
Definition get_bits.h:544
static const uint8_t * align_get_bits(GetBitContext *s)
Definition get_bits.h:560
static int get_bits_count(const GetBitContext *s)
Definition get_bits.h:254
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition get_bits.h:337
exp golomb vlc stuff
static int get_ue_golomb_31(GetBitContext *gb)
read unsigned exp golomb code, constraint to a max of 31.
Definition golomb.h:120
static int get_ue_golomb(GetBitContext *gb)
Read an unsigned Exp-Golomb code in the range 0 to 8190.
Definition golomb.h:53
static int get_se_golomb_long(GetBitContext *gb)
Definition golomb.h:294
static unsigned get_ue_golomb_long(GetBitContext *gb)
Read an unsigned Exp-Golomb code in the range 0 to UINT32_MAX-1.
Definition golomb.h:104
void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size)
Same behaviour av_fast_malloc but the buffer has additional AV_INPUT_BUFFER_PADDING_SIZE at the end w...
Definition utils.c:53
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition buffer.c:139
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition buffer.c:55
const AVCRC * av_crc_get_table(AVCRCId crc_id)
Get an initialized standard CRC table.
Definition crc.c:389
uint32_t av_crc(const AVCRC *ctx, uint32_t crc, const uint8_t *buffer, size_t length)
Calculate the CRC of a block.
Definition crc.c:421
@ AV_CRC_32_IEEE
Definition crc.h:52
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition error.h:64
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR(e)
Definition error.h:45
AVFrameSideData * av_frame_new_side_data_from_buf(AVFrame *frame, enum AVFrameSideDataType type, AVBufferRef *buf)
Add a new side data to a frame from an existing AVBufferRef.
Definition frame.c:638
@ AV_FRAME_DATA_DOVI_METADATA
Parsed Dolby Vision metadata, suitable for passing to a software implementation.
Definition frame.h:208
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition rational.h:71
unsigned offset
Definition libaomenc.c:763
#define FFMIN(a, b)
Definition macros.h:49
Memory handling functions.
int profile
Definition mxfenc.c:2299
void av_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
Definition refstruct.c:120
static void * av_refstruct_allocz(size_t size)
Equivalent to av_refstruct_alloc_ext(size, 0, NULL, NULL)
Definition refstruct.h:105
#define av_bswap32
Definition bswap.h:47
#define FF_ARRAY_ELEMS(a)
A reference to a data buffer.
Definition buffer.h:82
Struct containing chromaticity x and y values for the standard CIE 1931 chromaticity definition.
Definition csp.h:56
AVRational x
Definition csp.h:57
AVRational y
Definition csp.h:57
AVWhitepointCoefficients wp
Definition csp.h:79
AVPrimaryCoefficients prim
Definition csp.h:80
Dolby Vision RPU colorspace metadata parameters.
Definition dovi_meta.h:171
Dolby Vision RPU data mapping parameters.
Definition dovi_meta.h:152
uint32_t num_x_partitions
Definition dovi_meta.h:160
AVDOVINLQParams nlq[3]
Definition dovi_meta.h:162
uint8_t mapping_color_space
Definition dovi_meta.h:154
uint8_t mapping_chroma_format_idc
Definition dovi_meta.h:155
uint16_t nlq_pivots[2]
Definition dovi_meta.h:163
AVDOVIReshapingCurve curves[3]
Definition dovi_meta.h:156
enum AVDOVINLQMethod nlq_method_idc
Definition dovi_meta.h:159
uint32_t num_y_partitions
Definition dovi_meta.h:161
Dolby Vision metadata extension block.
Definition dovi_meta.h:318
AVDOVIDmLevel9 l9
Definition dovi_meta.h:329
AVDOVIDmLevel3 l3
Definition dovi_meta.h:323
uint8_t level
Definition dovi_meta.h:319
AVDOVIDmLevel8 l8
Definition dovi_meta.h:328
AVDOVIDmLevel254 l254
Definition dovi_meta.h:332
AVDOVIDmLevel6 l6
Definition dovi_meta.h:326
AVDOVIDmLevel4 l4
Definition dovi_meta.h:324
AVDOVIDmLevel1 l1
Definition dovi_meta.h:321
AVDOVIDmLevel11 l11
Definition dovi_meta.h:331
AVDOVIDmLevel5 l5
Definition dovi_meta.h:325
AVDOVIDmLevel10 l10
Definition dovi_meta.h:330
AVDOVIDmLevel255 l255
Definition dovi_meta.h:333
AVDOVIDmLevel2 l2
Definition dovi_meta.h:322
uint16_t target_min_pq
Definition dovi_meta.h:273
uint16_t target_max_pq
Definition dovi_meta.h:272
uint8_t target_primary_index
Definition dovi_meta.h:274
AVColorPrimariesDesc target_display_primaries
Definition dovi_meta.h:275
uint8_t target_display_index
Definition dovi_meta.h:271
uint8_t content_type
Definition dovi_meta.h:279
uint8_t whitepoint
Definition dovi_meta.h:280
uint8_t reference_mode_flag
Definition dovi_meta.h:281
uint16_t avg_pq
Definition dovi_meta.h:207
uint16_t min_pq
Definition dovi_meta.h:205
uint16_t max_pq
Definition dovi_meta.h:206
uint8_t dm_version_index
Definition dovi_meta.h:301
uint8_t dm_debug[4]
Definition dovi_meta.h:308
uint8_t dm_run_version
Definition dovi_meta.h:307
uint8_t dm_run_mode
Definition dovi_meta.h:306
int16_t ms_weight
Definition dovi_meta.h:218
uint16_t target_max_pq
Definition dovi_meta.h:212
uint16_t trim_slope
Definition dovi_meta.h:213
uint16_t trim_chroma_weight
Definition dovi_meta.h:216
uint16_t trim_saturation_gain
Definition dovi_meta.h:217
uint16_t trim_offset
Definition dovi_meta.h:214
uint16_t trim_power
Definition dovi_meta.h:215
uint16_t max_pq_offset
Definition dovi_meta.h:223
uint16_t avg_pq_offset
Definition dovi_meta.h:224
uint16_t min_pq_offset
Definition dovi_meta.h:222
uint16_t anchor_pq
Definition dovi_meta.h:228
uint16_t anchor_power
Definition dovi_meta.h:229
uint16_t bottom_offset
Definition dovi_meta.h:237
uint16_t top_offset
Definition dovi_meta.h:236
uint16_t left_offset
Definition dovi_meta.h:234
uint16_t right_offset
Definition dovi_meta.h:235
uint16_t min_luminance
Definition dovi_meta.h:243
uint16_t max_luminance
Definition dovi_meta.h:242
uint16_t max_fall
Definition dovi_meta.h:245
uint16_t max_cll
Definition dovi_meta.h:244
uint16_t trim_offset
Definition dovi_meta.h:252
uint8_t target_display_index
Definition dovi_meta.h:250
uint16_t target_mid_contrast
Definition dovi_meta.h:257
uint8_t saturation_vector_field[6]
Definition dovi_meta.h:259
uint16_t trim_power
Definition dovi_meta.h:253
uint8_t hue_vector_field[6]
Definition dovi_meta.h:260
uint16_t trim_saturation_gain
Definition dovi_meta.h:255
uint16_t trim_chroma_weight
Definition dovi_meta.h:254
uint16_t ms_weight
Definition dovi_meta.h:256
uint16_t clip_trim
Definition dovi_meta.h:258
uint16_t trim_slope
Definition dovi_meta.h:251
AVColorPrimariesDesc source_display_primaries
Definition dovi_meta.h:266
uint8_t source_primary_index
Definition dovi_meta.h:265
Combined struct representing a combination of header, mapping and color metadata, for attaching to fr...
Definition dovi_meta.h:345
size_t ext_block_size
Definition dovi_meta.h:355
Coefficients of the non-linear inverse quantization.
Definition dovi_meta.h:139
uint64_t linear_deadzone_slope
Definition dovi_meta.h:143
uint64_t linear_deadzone_threshold
Definition dovi_meta.h:144
uint16_t nlq_offset
Definition dovi_meta.h:140
uint64_t vdr_in_max
Definition dovi_meta.h:141
uint8_t poly_order[AV_DOVI_MAX_PIECES]
Definition dovi_meta.h:122
enum AVDOVIMappingMethod mapping_idc[AV_DOVI_MAX_PIECES]
Definition dovi_meta.h:120
int64_t mmr_constant[AV_DOVI_MAX_PIECES]
Definition dovi_meta.h:126
int64_t mmr_coef[AV_DOVI_MAX_PIECES][3][7]
Definition dovi_meta.h:127
int64_t poly_coef[AV_DOVI_MAX_PIECES][3]
Definition dovi_meta.h:123
uint16_t pivots[AV_DOVI_MAX_PIECES+1]
Definition dovi_meta.h:119
uint8_t mmr_order[AV_DOVI_MAX_PIECES]
Definition dovi_meta.h:125
Dolby Vision RPU data header.
Definition dovi_meta.h:87
uint8_t vdr_rpu_profile
Definition dovi_meta.h:90
uint8_t ext_mapping_idc_0_4
Definition dovi_meta.h:103
uint8_t spatial_resampling_filter_flag
Definition dovi_meta.h:100
uint8_t vdr_bit_depth
Definition dovi_meta.h:99
uint8_t el_spatial_resampling_filter_flag
Definition dovi_meta.h:101
uint8_t bl_video_full_range_flag
Definition dovi_meta.h:96
uint16_t rpu_format
Definition dovi_meta.h:89
uint8_t disable_residual_flag
Definition dovi_meta.h:102
uint8_t vdr_rpu_normalized_idc
Definition dovi_meta.h:95
uint8_t coef_log2_denom
Definition dovi_meta.h:94
uint8_t chroma_resampling_explicit_filter_flag
Definition dovi_meta.h:92
uint8_t coef_data_type
Definition dovi_meta.h:93
uint8_t ext_mapping_idc_5_7
Definition dovi_meta.h:104
uint8_t vdr_rpu_level
Definition dovi_meta.h:91
Structure to hold side data for an AVFrame.
Definition frame.h:327
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
int num_dynamic
Definition dovi_rpu.h:39
AVDOVIDmData dm_static[7]
static extension blocks
Definition dovi_rpu.h:36
int num_static
Definition dovi_rpu.h:38
AVDOVIDmData dm_dynamic[25]
dynamic extension blocks
Definition dovi_rpu.h:37
uint8_t level
Definition svq3.c:208
#define av_free(p)
#define avpriv_request_sample(...)
#define av_log(a,...)
int size
static double c[64]