Commit 8e80f57c authored by Vittorio Giovara's avatar Vittorio Giovara

Parse OBU metadata for HDR10 support

parent b4e6377a
......@@ -160,6 +160,22 @@ enum Dav1dChromaSamplePosition {
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;
......
......@@ -64,6 +64,10 @@ typedef struct Dav1dPicture {
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 {
......
......@@ -85,6 +85,11 @@ struct Dav1dContext {
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;
......
......@@ -43,6 +43,14 @@ enum ObuType {
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,
......
......@@ -417,6 +417,11 @@ void dav1d_flush(Dav1dContext *const c) {
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;
}
......
......@@ -1343,9 +1343,79 @@ int dav1d_parse_obus(Dav1dContext *const c, Dav1dData *const in, int global) {
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:
......
......@@ -150,6 +150,14 @@ static int picture_alloc_with_edges(Dav1dContext *const c, Dav1dPicture *const p
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 @@ void dav1d_picture_ref(Dav1dPicture *const dst, const Dav1dPicture *const src) {
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 @@ void dav1d_picture_unref_internal(Dav1dPicture *const p) {
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));
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment