shithub: dav1d

Download patch

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));
 }