shithub: dav1d

Download patch

ref: 03d4ede0656490a384e2a2ffe10b16c5aabdc8ec
parent: c371907ffea1cafa9ee5867df4127a53b836d68f
author: Ronald S. Bultje <rsbultje@gmail.com>
date: Sun Nov 18 11:47:46 EST 2018

Make frame_hdr a referenced object

--- a/src/decode.c
+++ b/src/decode.c
@@ -2948,6 +2948,7 @@
     dav1d_ref_dec(&f->prev_segmap_ref);
     dav1d_ref_dec(&f->mvs_ref);
     dav1d_ref_dec(&f->seq_hdr_ref);
+    dav1d_ref_dec(&f->frame_hdr_ref);
 
     for (int i = 0; i < f->n_tile_data; i++)
         dav1d_data_unref(&f->tile[i].data);
@@ -2990,7 +2991,10 @@
     f->seq_hdr = c->seq_hdr;
     f->seq_hdr_ref = c->seq_hdr_ref;
     dav1d_ref_inc(f->seq_hdr_ref);
-    *f->frame_hdr = *c->frame_hdr;
+    f->frame_hdr = c->frame_hdr;
+    f->frame_hdr_ref = c->frame_hdr_ref;
+    c->frame_hdr = NULL;
+    c->frame_hdr_ref = NULL;
     const int bd_idx = (f->seq_hdr->bpc - 8) >> 1;
     f->dsp = &c->dsp[bd_idx];
 
@@ -3309,6 +3313,7 @@
     dav1d_thread_picture_unref(&f->sr_cur);
     dav1d_ref_dec(&f->mvs_ref);
     dav1d_ref_dec(&f->seq_hdr_ref);
+    dav1d_ref_dec(&f->frame_hdr_ref);
 
     for (int i = 0; i < f->n_tile_data; i++)
         dav1d_data_unref(&f->tile[i].data);
--- a/src/internal.h
+++ b/src/internal.h
@@ -75,11 +75,12 @@
         Dav1dData data;
         int start, end;
     } tile[256];
-    int n_tile_data, have_frame_hdr;
+    int n_tile_data;
     int n_tiles;
     Dav1dRef *seq_hdr_ref;
     Av1SequenceHeader *seq_hdr;
-    Av1FrameHeader *frame_hdr, frame_hdr_mem; // FIXME make ref?
+    Dav1dRef *frame_hdr_ref;
+    Av1FrameHeader *frame_hdr;
 
     // decoded output picture queue
     Dav1dData in;
@@ -125,7 +126,8 @@
 struct Dav1dFrameContext {
     Dav1dRef *seq_hdr_ref;
     Av1SequenceHeader *seq_hdr;
-    Av1FrameHeader *frame_hdr, frame_hdr_mem;
+    Dav1dRef *frame_hdr_ref;
+    Av1FrameHeader *frame_hdr;
     Dav1dThreadPicture refp[7];
     Dav1dPicture cur; // during block coding / reconstruction
     Dav1dThreadPicture sr_cur; // after super-resolution upscaling
--- a/src/lib.c
+++ b/src/lib.c
@@ -89,7 +89,6 @@
     if (!c) goto error;
     memset(c, 0, sizeof(*c));
 
-    c->frame_hdr = &c->frame_hdr_mem;
     c->allocator = s->allocator;
     c->apply_grain = s->apply_grain;
     c->operating_point = s->operating_point;
@@ -108,7 +107,6 @@
     for (int n = 0; n < s->n_frame_threads; n++) {
         Dav1dFrameContext *const f = &c->fc[n];
         f->c = c;
-        f->frame_hdr = &f->frame_hdr_mem;
         f->lf.last_sharpness = -1;
         f->n_tc = s->n_tile_threads;
         f->tc = dav1d_alloc_aligned(sizeof(*f->tc) * s->n_tile_threads, 32);
--- a/src/obu.c
+++ b/src/obu.c
@@ -1207,7 +1207,7 @@
         if (!ref) return -ENOMEM;
         Av1SequenceHeader *seq_hdr = ref->data;
         memset(seq_hdr, 0, sizeof(*seq_hdr));
-        c->have_frame_hdr = 0;
+        c->frame_hdr = NULL;
         if ((res = parse_seq_hdr(c, &gb, seq_hdr)) < 0) {
             dav1d_ref_dec(&ref);
             return res;
@@ -1235,16 +1235,22 @@
         break;
     }
     case OBU_REDUNDANT_FRAME_HDR:
-        if (c->have_frame_hdr) break;
+        if (c->frame_hdr) break;
         // fall-through
     case OBU_FRAME:
     case OBU_FRAME_HDR:
-        c->have_frame_hdr = 0;
         if (!c->seq_hdr) goto error;
+        if (!c->frame_hdr_ref) {
+            c->frame_hdr_ref = dav1d_ref_create(sizeof(Av1FrameHeader));
+            if (!c->frame_hdr_ref) return -ENOMEM;
+        }
+        c->frame_hdr = c->frame_hdr_ref->data;
         c->frame_hdr->temporal_id = temporal_id;
         c->frame_hdr->spatial_id = spatial_id;
-        if ((res = parse_frame_hdr(c, &gb)) < 0)
+        if ((res = parse_frame_hdr(c, &gb)) < 0) {
+            c->frame_hdr = NULL;
             return res;
+        }
         for (int n = 0; n < c->n_tile_data; n++)
             dav1d_data_unref(&c->tile[n].data);
         c->n_tile_data = 0;
@@ -1253,17 +1259,19 @@
             // This is actually a frame header OBU so read the
             // trailing bit and check for overrun.
             dav1d_get_bits(&gb, 1);
-            if (check_for_overrun(&gb, init_bit_pos, len))
+            if (check_for_overrun(&gb, init_bit_pos, len)) {
+                c->frame_hdr = NULL;
                 return -EINVAL;
+            }
 
-            c->have_frame_hdr = 1;
             break;
         }
         // OBU_FRAMEs shouldn't be signalled with show_existing_frame
-        if (c->frame_hdr->show_existing_frame) goto error;
+        if (c->frame_hdr->show_existing_frame) {
+            c->frame_hdr = NULL;
+            goto error;
+        }
 
-        c->have_frame_hdr = 1;
-
         // This is the frame header at the start of a frame OBU.
         // There's no trailing bit at the end to skip, but we do need
         // to align to the next byte.
@@ -1270,7 +1278,7 @@
         dav1d_bytealign_get_bits(&gb);
         // fall-through
     case OBU_TILE_GRP: {
-        if (!c->have_frame_hdr) goto error;
+        if (!c->frame_hdr) goto error;
         if (c->n_tile_data >= 256) goto error;
         parse_tile_hdr(c, &gb);
         // Align to the next byte boundary and check for overrun.
@@ -1313,75 +1321,73 @@
         return -EINVAL;
     }
 
-    if (c->seq_hdr && c->have_frame_hdr &&
-        c->n_tiles == c->frame_hdr->tiling.cols * c->frame_hdr->tiling.rows)
-    {
-        if (!c->n_tile_data)
-            return -EINVAL;
-        if ((res = dav1d_submit_frame(c)) < 0)
-            return res;
-        assert(!c->n_tile_data);
-        c->have_frame_hdr = 0;
-        c->n_tiles = 0;
-    } else if (c->seq_hdr && c->have_frame_hdr &&
-               c->frame_hdr->show_existing_frame)
-    {
-        if (c->n_fc == 1) {
-            dav1d_picture_ref(&c->out,
-                              &c->refs[c->frame_hdr->existing_frame_idx].p.p);
-            c->out.m = in->m;
-        } else {
-            // need to append this to the frame output queue
-            const unsigned next = c->frame_thread.next++;
-            if (c->frame_thread.next == c->n_fc)
-                c->frame_thread.next = 0;
+    if (c->seq_hdr && c->frame_hdr) {
+        if (c->frame_hdr->show_existing_frame) {
+            if (c->n_fc == 1) {
+                dav1d_picture_ref(&c->out,
+                                  &c->refs[c->frame_hdr->existing_frame_idx].p.p);
+                c->out.m = in->m;
+            } else {
+                // need to append this to the frame output queue
+                const unsigned next = c->frame_thread.next++;
+                if (c->frame_thread.next == c->n_fc)
+                    c->frame_thread.next = 0;
 
-            Dav1dFrameContext *const f = &c->fc[next];
-            pthread_mutex_lock(&f->frame_thread.td.lock);
-            while (f->n_tile_data > 0)
-                pthread_cond_wait(&f->frame_thread.td.cond,
-                                  &f->frame_thread.td.lock);
-            Dav1dThreadPicture *const out_delayed =
-                &c->frame_thread.out_delayed[next];
-            if (out_delayed->p.data[0]) {
-                const unsigned progress = atomic_load_explicit(&out_delayed->progress[1],
-                                                               memory_order_relaxed);
-                if (out_delayed->visible && progress != FRAME_ERROR)
-                    dav1d_picture_ref(&c->out, &out_delayed->p);
-                dav1d_thread_picture_unref(out_delayed);
+                Dav1dFrameContext *const f = &c->fc[next];
+                pthread_mutex_lock(&f->frame_thread.td.lock);
+                while (f->n_tile_data > 0)
+                    pthread_cond_wait(&f->frame_thread.td.cond,
+                                      &f->frame_thread.td.lock);
+                Dav1dThreadPicture *const out_delayed =
+                    &c->frame_thread.out_delayed[next];
+                if (out_delayed->p.data[0]) {
+                    const unsigned progress = atomic_load_explicit(&out_delayed->progress[1],
+                                                                   memory_order_relaxed);
+                    if (out_delayed->visible && progress != FRAME_ERROR)
+                        dav1d_picture_ref(&c->out, &out_delayed->p);
+                    dav1d_thread_picture_unref(out_delayed);
+                }
+                dav1d_thread_picture_ref(out_delayed,
+                                         &c->refs[c->frame_hdr->existing_frame_idx].p);
+                out_delayed->visible = 1;
+                out_delayed->p.m = in->m;
+                pthread_mutex_unlock(&f->frame_thread.td.lock);
             }
-            dav1d_thread_picture_ref(out_delayed,
-                                     &c->refs[c->frame_hdr->existing_frame_idx].p);
-            out_delayed->visible = 1;
-            out_delayed->p.m = in->m;
-            pthread_mutex_unlock(&f->frame_thread.td.lock);
-        }
-        c->have_frame_hdr = 0;
-        if (c->refs[c->frame_hdr->existing_frame_idx].p.p.p.type == DAV1D_FRAME_TYPE_KEY) {
-            const int r = c->frame_hdr->existing_frame_idx;
-            for (int i = 0; i < 8; i++) {
-                if (i == c->frame_hdr->existing_frame_idx) continue;
+            if (c->refs[c->frame_hdr->existing_frame_idx].p.p.p.type == DAV1D_FRAME_TYPE_KEY) {
+                const int r = c->frame_hdr->existing_frame_idx;
+                for (int i = 0; i < 8; i++) {
+                    if (i == c->frame_hdr->existing_frame_idx) continue;
 
-                if (c->refs[i].p.p.data[0])
-                    dav1d_thread_picture_unref(&c->refs[i].p);
-                dav1d_thread_picture_ref(&c->refs[i].p, &c->refs[r].p);
+                    if (c->refs[i].p.p.data[0])
+                        dav1d_thread_picture_unref(&c->refs[i].p);
+                    dav1d_thread_picture_ref(&c->refs[i].p, &c->refs[r].p);
 
-                if (c->cdf[i].cdf) dav1d_cdf_thread_unref(&c->cdf[i]);
-                dav1d_init_states(&c->cdf[i], c->refs[r].qidx);
+                    if (c->cdf[i].cdf) dav1d_cdf_thread_unref(&c->cdf[i]);
+                    dav1d_init_states(&c->cdf[i], c->refs[r].qidx);
 
-                c->refs[i].lf_mode_ref_deltas = c->refs[r].lf_mode_ref_deltas;
-                c->refs[i].seg_data = c->refs[r].seg_data;
-                for (int j = 0; j < 7; j++)
-                    c->refs[i].gmv[j] = dav1d_default_wm_params;
-                c->refs[i].film_grain = c->refs[r].film_grain;
+                    c->refs[i].lf_mode_ref_deltas = c->refs[r].lf_mode_ref_deltas;
+                    c->refs[i].seg_data = c->refs[r].seg_data;
+                    for (int j = 0; j < 7; j++)
+                        c->refs[i].gmv[j] = dav1d_default_wm_params;
+                    c->refs[i].film_grain = c->refs[r].film_grain;
 
-                dav1d_ref_dec(&c->refs[i].segmap);
-                c->refs[i].segmap = c->refs[r].segmap;
-                if (c->refs[r].segmap)
-                    dav1d_ref_inc(c->refs[r].segmap);
-                dav1d_ref_dec(&c->refs[i].refmvs);
-                c->refs[i].qidx = c->refs[r].qidx;
+                    dav1d_ref_dec(&c->refs[i].segmap);
+                    c->refs[i].segmap = c->refs[r].segmap;
+                    if (c->refs[r].segmap)
+                        dav1d_ref_inc(c->refs[r].segmap);
+                    dav1d_ref_dec(&c->refs[i].refmvs);
+                    c->refs[i].qidx = c->refs[r].qidx;
+                }
             }
+            c->frame_hdr = NULL;
+        } else if (c->n_tiles == c->frame_hdr->tiling.cols * c->frame_hdr->tiling.rows) {
+            if (!c->n_tile_data)
+                return -EINVAL;
+            if ((res = dav1d_submit_frame(c)) < 0)
+                return res;
+            assert(!c->n_tile_data);
+            c->frame_hdr = NULL;
+            c->n_tiles = 0;
         }
     }