shithub: dav1d

Download patch

ref: 0afc2039e707b2acdc209f0a8943043176376a5e
parent: 041f653545a5c6b677c1f099e9f98634c2cb1601
author: James Almer <[email protected]>
date: Sun Nov 25 15:46:11 EST 2018

Add a public function to parse the Sequence Header from raw bitstream data

Signed-off-by: James Almer <[email protected]>

--- a/include/dav1d/dav1d.h
+++ b/include/dav1d/dav1d.h
@@ -77,6 +77,22 @@
 DAV1D_API int dav1d_open(Dav1dContext **c_out, const Dav1dSettings *s);
 
 /**
+ * Parse a Sequence Header OBU from bitstream data.
+ *
+ * @param out Output Sequence Header.
+ * @param buf The data to be parser.
+ * @param sz  Size of the data.
+ *
+ * @return 0 on success, or < 0 (a negative errno code) on error.
+ *
+ * @note It is safe to feed this function data containing other OBUs than a
+ *       Sequence Header, as they will simply be ignored. If there is more than
+ *       one Sequence Header OBU present, only the last will be returned.
+ */
+DAV1D_API int dav1d_parse_sequence_header(Dav1dSequenceHeader *out,
+                                          const uint8_t *buf, const size_t sz);
+
+/**
  * Feed bitstream data to the decoder.
  *
  * @param   c Input decoder instance.
--- a/src/lib.c
+++ b/src/lib.c
@@ -167,6 +167,54 @@
     return -ENOMEM;
 }
 
+static void dummy_free(const uint8_t *const data, void *const user_data) {
+    assert(data && !user_data);
+}
+
+int dav1d_parse_sequence_header(Dav1dSequenceHeader *const out,
+                                const uint8_t *const ptr, const size_t sz)
+{
+    Dav1dData buf = { 0 };
+    int res;
+
+    validate_input_or_ret(out != NULL, -EINVAL);
+
+    Dav1dSettings s;
+    dav1d_default_settings(&s);
+
+    Dav1dContext *c;
+    res	= dav1d_open(&c, &s);
+    if (res < 0) return res;
+
+    if (ptr) {
+        res = dav1d_data_wrap(&buf, ptr, sz, dummy_free, NULL);
+        if (res < 0) goto error;
+    }
+
+    while (buf.sz > 0) {
+        res = dav1d_parse_obus(c, &buf, 1);
+        if (res < 0) goto error;
+
+        assert((size_t)res <= buf.sz);
+        buf.sz -= res;
+        buf.data += res;
+    }
+
+    if (!c->seq_hdr) {
+        res = -EINVAL;
+        goto error;
+    }
+
+    memcpy(out, c->seq_hdr, sizeof(*out));
+
+    res = 0;
+error:
+    dav1d_data_unref(&buf);
+    dav1d_close(&c);
+
+    return res;
+}
+
 int dav1d_send_data(Dav1dContext *const c, Dav1dData *const in)
 {
     validate_input_or_ret(c != NULL, -EINVAL);
@@ -266,7 +314,7 @@
     }
 
     while (in->sz > 0) {
-        if ((res = dav1d_parse_obus(c, in)) < 0) {
+        if ((res = dav1d_parse_obus(c, in, 0)) < 0) {
             dav1d_data_unref(in);
             return res;
         }
--- a/src/obu.c
+++ b/src/obu.c
@@ -1157,7 +1157,7 @@
     return 0;
 }
 
-int dav1d_parse_obus(Dav1dContext *const c, Dav1dData *const in) {
+int dav1d_parse_obus(Dav1dContext *const c, Dav1dData *const in, int global) {
     GetBits gb;
     int res;
 
@@ -1259,6 +1259,7 @@
         // fall-through
     case OBU_FRAME:
     case OBU_FRAME_HDR:
+        if (global) break;
         if (!c->seq_hdr) goto error;
         if (!c->frame_hdr_ref) {
             c->frame_hdr_ref = dav1d_ref_create(sizeof(Dav1dFrameHeader));
@@ -1298,6 +1299,7 @@
         dav1d_bytealign_get_bits(&gb);
         // fall-through
     case OBU_TILE_GRP: {
+        if (global) break;
         if (!c->frame_hdr) goto error;
         if (c->n_tile_data >= 256) goto error;
         parse_tile_hdr(c, &gb);
--- a/src/obu.h
+++ b/src/obu.h
@@ -31,6 +31,6 @@
 #include "dav1d/data.h"
 #include "src/internal.h"
 
-int dav1d_parse_obus(Dav1dContext *c, Dav1dData *in);
+int dav1d_parse_obus(Dav1dContext *c, Dav1dData *in, int global);
 
 #endif /* __DAV1D_SRC_OBU_H__ */