avcodec/dovi_rpu: implement support for profile 10

Instead of the nal_prefix, this profile inside wraps the RPU inside an
EMDF container, as specified in ETSI TS 102 366. However, this
DV-specific EMDF container is restricted (by the specification) to
a fixed set of hard-coded parameters, which we can effecitvely treat as
a magic byte sequence.

Validated and tested using official Dolby sample files, which
I unfortunately cannot share. However, there are public sample files
available at the merge request link below.

Relevant links:
- https://www.etsi.org/deliver/etsi_ts/102300_102399/102366/01.04.01_60/ts_102366v010401p.pdf
- https://patentimages.storage.googleapis.com/8a/0b/da/28294acaed2182/EP3588964A1.pdf
- https://www.etsi.org/deliver/etsi_ts/103500_103599/103572/01.03.01_60/ts_103572v010301p.pdf
- https://gitlab.com/mbunkus/mkvtoolnix/-/merge_requests/2254
release/7.0
Niklas Haas 9 months ago
parent 3d1860ec8d
commit 9aecd717ab
  1. 45
      libavcodec/dovi_rpu.c

@ -174,6 +174,18 @@ static inline int64_t get_se_coef(GetBitContext *gb, const AVDOVIRpuDataHeader *
return 0; /* unreachable */
}
static inline unsigned get_variable_bits(GetBitContext *gb, int n)
{
unsigned int value = get_bits(gb, n);
int read_more = get_bits1(gb);
while (read_more) {
value = (value + 1) << n;
value |= get_bits(gb, n);
read_more = get_bits1(gb);
}
return value;
}
#define VALIDATE(VAR, MIN, MAX) \
do { \
if (VAR < MIN || VAR > MAX) { \
@ -200,9 +212,36 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size)
if ((ret = init_get_bits8(gb, rpu, rpu_size)) < 0)
return ret;
/* RPU header, common values */
nal_prefix = get_bits(gb, 8);
VALIDATE(nal_prefix, 25, 25);
/* Container header */
if (s->dv_profile == 10 /* dav1.10 */) {
/* DV inside AV1 re-uses an EMDF container skeleton, but with fixed
* values - so we can effectively treat this as a magic byte sequence.
*
* The exact fields are, as follows:
* emdf_version : f(2) = 0
* key_id : f(3) = 6
* emdf_payload_id : f(5) = 31
* emdf_payload_id_ext : var(5) = 225
* smploffste : f(1) = 0
* duratione : f(1) = 0
* groupide : f(1) = 0
* codecdatae : f(1) = 0
* discard_unknown_payload : f(1) = 1
*/
const unsigned header_magic = 0x01be6841u;
unsigned header, emdf_payload_size;
header = get_bits_long(gb, 27);
VALIDATE(header, header_magic, header_magic);
emdf_payload_size = get_variable_bits(gb, 8);
VALIDATE(emdf_payload_size, 6, 512);
if (emdf_payload_size * 8 > get_bits_left(gb))
return AVERROR_INVALIDDATA;
} else {
nal_prefix = get_bits(gb, 8);
VALIDATE(nal_prefix, 25, 25);
}
/* RPU header */
rpu_type = get_bits(gb, 6);
if (rpu_type != 2) {
av_log(s->logctx, AV_LOG_WARNING, "Unrecognized RPU type "

Loading…
Cancel
Save