ref: 8e80f57c112e21f757e09401f566c89d424a31d6
parent: b4e6377a5b7aa5a34b67873d76e6f45b7b75d444
author: Vittorio Giovara <vittorio@vimeo.com>
date: Fri Feb 8 08:33:41 EST 2019
Parse OBU metadata for HDR10 support
--- a/include/dav1d/headers.h
+++ b/include/dav1d/headers.h
@@ -160,6 +160,22 @@
DAV1D_CHR_COLOCATED = 2, ///< Co-located with luma(0, 0) sample
};
+typedef struct Dav1dContentLightLevel {
+ int max_content_light_level;
+ int max_frame_average_light_level;
+} Dav1dContentLightLevel;
+
+typedef struct Dav1dMasteringDisplay {
+ ///< 0.16 fixed point
+ uint16_t primaries[3][2];
+ ///< 0.16 fixed point
+ uint16_t white_point[2];
+ ///< 24.8 fixed point
+ uint32_t max_luminance;
+ ///< 18.14 fixed point
+ uint32_t min_luminance;
+} Dav1dMasteringDisplay;
+
typedef struct Dav1dSequenceHeader {
/**
* Stream profile, 0 for 8-10 bits/component 4:2:0 or monochrome;
--- a/include/dav1d/picture.h
+++ b/include/dav1d/picture.h
@@ -64,6 +64,10 @@
struct Dav1dRef *frame_hdr_ref, *seq_hdr_ref, *ref; ///< allocation origins
void *allocator_data; ///< pointer managed by the allocator
+
+ Dav1dContentLightLevel *content_light;
+ Dav1dMasteringDisplay *mastering_display;
+ struct Dav1dRef *content_light_ref, *mastering_display_ref;
} Dav1dPicture;
typedef struct Dav1dPicAllocator {
--- a/src/internal.h
+++ b/src/internal.h
@@ -85,6 +85,11 @@
Dav1dRef *frame_hdr_ref;
Dav1dFrameHeader *frame_hdr;
+ Dav1dRef *content_light_ref;
+ Dav1dContentLightLevel *content_light;
+ Dav1dRef *mastering_display_ref;
+ Dav1dMasteringDisplay *mastering_display;
+
// decoded output picture queue
Dav1dData in;
Dav1dPicture out;
--- a/src/levels.h
+++ b/src/levels.h
@@ -43,6 +43,14 @@
OBU_PADDING = 15,
};
+enum ObuMetaType {
+ OBU_META_HDR_CLL = 1,
+ OBU_META_HDR_MDCV = 2,
+ OBU_META_SCALABILITY = 3,
+ OBU_META_ITUT_T35 = 4,
+ OBU_META_TIMECODE = 5,
+};
+
enum TxfmSize {
TX_4X4,
TX_8X8,
--- a/src/lib.c
+++ b/src/lib.c
@@ -417,6 +417,11 @@
c->seq_hdr = NULL;
dav1d_ref_dec(&c->seq_hdr_ref);
+ c->mastering_display = NULL;
+ c->content_light = NULL;
+ dav1d_ref_dec(&c->mastering_display_ref);
+ dav1d_ref_dec(&c->content_light_ref);
+
c->frame_thread.next = 0;
}
--- a/src/obu.c
+++ b/src/obu.c
@@ -1343,9 +1343,79 @@
c->n_tile_data++;
break;
}
+ case OBU_METADATA: {
+ // obu metadta type field
+ const enum ObuMetaType meta_type = dav1d_get_uleb128(&gb);
+ if (gb.error) goto error;
+ Dav1dRef *ref;
+ Dav1dContentLightLevel *content_light;
+ Dav1dMasteringDisplay *mastering_display;
+
+ switch (meta_type) {
+ case OBU_META_HDR_CLL:
+ ref = dav1d_ref_create(sizeof(Dav1dContentLightLevel));
+ if (!ref) return -ENOMEM;
+ content_light = ref->data;
+ memset(content_light, 0, sizeof(*content_light));
+
+ content_light->max_content_light_level = dav1d_get_bits(&gb, 16);
+ content_light->max_frame_average_light_level = dav1d_get_bits(&gb, 16);
+
+ // Skip the trailing bit, align to the next byte boundary and check for overrun.
+ dav1d_get_bits(&gb, 1);
+ dav1d_bytealign_get_bits(&gb);
+ if (check_for_overrun(c, &gb, init_bit_pos, len)) {
+ dav1d_ref_dec(&ref);
+ goto error;
+ }
+
+ dav1d_ref_dec(&c->content_light_ref);
+ c->content_light = content_light;
+ c->content_light_ref = ref;
+ break;
+ case OBU_META_HDR_MDCV: {
+ ref = dav1d_ref_create(sizeof(Dav1dMasteringDisplay));
+ if (!ref) return -ENOMEM;
+ mastering_display = ref->data;
+ memset(mastering_display, 0, sizeof(*mastering_display));
+
+ for (int i = 0; i < 3; i++) {
+ mastering_display->primaries[i][0] = dav1d_get_bits(&gb, 16);
+ mastering_display->primaries[i][1] = dav1d_get_bits(&gb, 16);
+ }
+ mastering_display->white_point[0] = dav1d_get_bits(&gb, 16);
+ mastering_display->white_point[1] = dav1d_get_bits(&gb, 16);
+
+ mastering_display->max_luminance = dav1d_get_bits(&gb, 32);
+ mastering_display->min_luminance = dav1d_get_bits(&gb, 32);
+
+ // Skip the trailing bit, align to the next byte boundary and check for overrun.
+ dav1d_get_bits(&gb, 1);
+ dav1d_bytealign_get_bits(&gb);
+ if (check_for_overrun(c, &gb, init_bit_pos, len)) {
+ dav1d_ref_dec(&ref);
+ goto error;
+ }
+
+ dav1d_ref_dec(&c->mastering_display_ref);
+ c->mastering_display = mastering_display;
+ c->mastering_display_ref = ref;
+ break;
+ }
+ case OBU_META_ITUT_T35:
+ case OBU_META_SCALABILITY:
+ case OBU_META_TIMECODE:
+ // ignore metadata OBUs we don't care about
+ break;
+ default:
+ // print a warning but don't fail for unknown types
+ dav1d_log(c, "Unknown Metadata OBU type %d\n", meta_type);
+ }
+
+ break;
+ }
case OBU_PADDING:
case OBU_TD:
- case OBU_METADATA:
// ignore OBUs we don't care about
break;
default:
--- a/src/picture.c
+++ b/src/picture.c
@@ -150,6 +150,14 @@
if (extra && extra_ptr)
*extra_ptr = &pic_ctx->extra_ptr;
+ p->content_light = c->content_light;
+ p->content_light_ref = c->content_light_ref;
+ if (c->content_light_ref) dav1d_ref_inc(c->content_light_ref);
+
+ p->mastering_display = c->mastering_display;
+ p->mastering_display_ref = c->mastering_display_ref;
+ if (c->mastering_display_ref) dav1d_ref_inc(c->mastering_display_ref);
+
return 0;
}
@@ -199,6 +207,8 @@
if (src->frame_hdr_ref) dav1d_ref_inc(src->frame_hdr_ref);
if (src->seq_hdr_ref) dav1d_ref_inc(src->seq_hdr_ref);
if (src->m.user_data.ref) dav1d_ref_inc(src->m.user_data.ref);
+ if (src->content_light_ref) dav1d_ref_inc(src->content_light_ref);
+ if (src->mastering_display_ref) dav1d_ref_inc(src->mastering_display_ref);
}
*dst = *src;
}
@@ -233,6 +243,8 @@
dav1d_ref_dec(&p->seq_hdr_ref);
dav1d_ref_dec(&p->frame_hdr_ref);
dav1d_ref_dec(&p->m.user_data.ref);
+ dav1d_ref_dec(&p->content_light_ref);
+ dav1d_ref_dec(&p->mastering_display_ref);
}
memset(p, 0, sizeof(*p));
}