ref: 704a5252e43765bc3383d53c63e0ae4cde57d720
parent: 6f979f815bb9256aa4e71f493c71f70dd94ced2f
author: Janne Grunau <[email protected]>
date: Sun Nov 4 17:19:24 EST 2018
frame threading: signal reference frame decoding errors Fixes #127
--- a/src/decode.c
+++ b/src/decode.c
@@ -665,8 +665,11 @@
unsigned seg_id = 8;
assert(f->frame_hdr.primary_ref_frame != PRIMARY_REF_NONE);
- dav1d_thread_picture_wait(&f->refp[f->frame_hdr.primary_ref_frame],
- (by + h4) * 4, PLANE_TYPE_BLOCK);
+ if (dav1d_thread_picture_wait(&f->refp[f->frame_hdr.primary_ref_frame],
+ (by + h4) * 4, PLANE_TYPE_BLOCK))
+ {
+ return 8;
+ }
ref_seg_map += by * stride + bx;
do {
@@ -730,7 +733,7 @@
have_left, have_top, b->ref[0], mask);
derive_warpmv(t, bw4, bh4, mask, b->mv[0], &t->warpmv);
}
- f->bd_fn.recon_b_inter(t, bs, b);
+ if (f->bd_fn.recon_b_inter(t, bs, b)) return -1;
const uint8_t *const filter = dav1d_filter_dir[b->filter2d];
#define set_ctx(type, dir, diridx, off, mul, rep_macro) \
@@ -773,9 +776,15 @@
int seg_pred = 0;
if (f->frame_hdr.segmentation.enabled) {
if (!f->frame_hdr.segmentation.update_map) {
- b->seg_id = f->prev_segmap ?
- get_prev_frame_segid(f, t->by, t->bx, w4, h4,
- f->prev_segmap, f->b4_stride) : 0;
+ if (f->prev_segmap) {
+ unsigned seg_id = get_prev_frame_segid(f, t->by, t->bx, w4, h4,
+ f->prev_segmap,
+ f->b4_stride);
+ if (seg_id >= 8) return -1;
+ b->seg_id = seg_id;
+ } else {
+ b->seg_id = 0;
+ }
} else if (f->frame_hdr.segmentation.seg_data.preskip) {
if (f->frame_hdr.segmentation.temporal &&
(seg_pred = msac_decode_bool_adapt(&ts->msac,
@@ -783,9 +792,16 @@
t->l.seg_pred[by4]])))
{
// temporal predicted seg_id
- b->seg_id = f->prev_segmap ?
- get_prev_frame_segid(f, t->by, t->bx, w4, h4,
- f->prev_segmap, f->b4_stride) : 0;
+ if (f->prev_segmap) {
+ unsigned seg_id = get_prev_frame_segid(f, t->by, t->bx,
+ w4, h4,
+ f->prev_segmap,
+ f->b4_stride);
+ if (seg_id >= 8) return -1;
+ b->seg_id = seg_id;
+ } else {
+ b->seg_id = 0;
+ }
} else {
int seg_ctx;
const unsigned pred_seg_id =
@@ -828,9 +844,15 @@
t->l.seg_pred[by4]])))
{
// temporal predicted seg_id
- b->seg_id = f->prev_segmap ?
- get_prev_frame_segid(f, t->by, t->bx, w4, h4,
- f->prev_segmap, f->b4_stride) : 0;
+ if (f->prev_segmap) {
+ unsigned seg_id = get_prev_frame_segid(f, t->by, t->bx, w4, h4,
+ f->prev_segmap,
+ f->b4_stride);
+ if (seg_id >= 8) return -1;
+ b->seg_id = seg_id;
+ } else {
+ b->seg_id = 0;
+ }
} else {
int seg_ctx;
const unsigned pred_seg_id =
@@ -1278,7 +1300,7 @@
if (f->frame_thread.pass == 1) {
f->bd_fn.read_coef_blocks(t, bs, b);
} else {
- f->bd_fn.recon_b_inter(t, bs, b);
+ if (f->bd_fn.recon_b_inter(t, bs, b)) return -1;
}
splat_intrabc_mv(f->mvs, f->b4_stride, t->by, t->bx, bs, b->mv[0]);
@@ -1770,7 +1792,7 @@
if (f->frame_thread.pass == 1) {
f->bd_fn.read_coef_blocks(t, bs, b);
} else {
- f->bd_fn.recon_b_inter(t, bs, b);
+ if (f->bd_fn.recon_b_inter(t, bs, b)) return -1;
}
const int is_globalmv =
@@ -2227,8 +2249,11 @@
if (c->n_fc > 1 && f->frame_hdr.use_ref_frame_mvs) {
for (int n = 0; n < 7; n++)
- dav1d_thread_picture_wait(&f->refp[n], 4 * (t->by + sb_step),
- PLANE_TYPE_BLOCK);
+ if (dav1d_thread_picture_wait(&f->refp[n], 4 * (t->by + sb_step),
+ PLANE_TYPE_BLOCK))
+ {
+ return 1;
+ }
av1_init_ref_mv_tile_row(f->libaom_cm,
ts->tiling.col_start, ts->tiling.col_end,
t->by, imin(t->by + sb_step, f->bh));
@@ -2745,6 +2770,8 @@
pthread_mutex_unlock(&ts->tile_thread.lock);
}
if (progress == TILE_ERROR) {
+ dav1d_thread_picture_signal(&f->cur, FRAME_ERROR,
+ progress_plane_type);
const uint64_t all_mask = ~0ULL >> (64 - f->n_tc);
pthread_mutex_lock(&f->tile_thread.lock);
while (f->tile_thread.available != all_mask)
@@ -2792,10 +2819,10 @@
}
}
- dav1d_thread_picture_signal(&f->cur, UINT_MAX, PLANE_TYPE_ALL);
-
retval = 0;
error:
+ dav1d_thread_picture_signal(&f->cur, retval == 0 ? UINT_MAX : FRAME_ERROR,
+ PLANE_TYPE_ALL);
for (int i = 0; i < 7; i++) {
if (f->refp[i].p.data[0])
dav1d_thread_picture_unref(&f->refp[i]);
--- a/src/picture.c
+++ b/src/picture.c
@@ -40,6 +40,7 @@
#include "src/picture.h"
#include "src/ref.h"
#include "src/thread.h"
+#include "src/thread_task.h"
int default_picture_allocator(Dav1dPicture *const p, void *cookie) {
assert(cookie == NULL);
@@ -211,13 +212,13 @@
p->progress = NULL;
}
-void dav1d_thread_picture_wait(const Dav1dThreadPicture *const p,
- int y_unclipped, const enum PlaneType plane_type)
+int dav1d_thread_picture_wait(const Dav1dThreadPicture *const p,
+ int y_unclipped, const enum PlaneType plane_type)
{
assert(plane_type != PLANE_TYPE_ALL);
if (!p->t)
- return;
+ return 0;
// convert to luma units; include plane delay from loopfilters; clip
const int ss_ver = p->p.p.layout == DAV1D_PIXEL_LAYOUT_I420;
@@ -225,14 +226,16 @@
y_unclipped += (plane_type != PLANE_TYPE_BLOCK) * 8; // delay imposed by loopfilter
const unsigned y = iclip(y_unclipped, 1, p->p.p.h);
atomic_uint *const progress = &p->progress[plane_type != PLANE_TYPE_BLOCK];
+ unsigned state;
- if (atomic_load_explicit(progress, memory_order_acquire) >= y)
- return;
+ if ((state = atomic_load_explicit(progress, memory_order_acquire)) >= y)
+ return state == FRAME_ERROR;
pthread_mutex_lock(&p->t->lock);
- while (atomic_load_explicit(progress, memory_order_relaxed) < y)
+ while ((state = atomic_load_explicit(progress, memory_order_relaxed)) < y)
pthread_cond_wait(&p->t->cond, &p->t->lock);
pthread_mutex_unlock(&p->t->lock);
+ return state == FRAME_ERROR;
}
void dav1d_thread_picture_signal(const Dav1dThreadPicture *const p,
--- a/src/picture.h
+++ b/src/picture.h
@@ -74,14 +74,17 @@
* units, else it is in chroma units.
* plane_type is used to determine how many pixels delay are
* introduced by loopfilter processes.
+ *
+ * Returns 0 on success, and 1 if there was an error while decoding p
*/
-void dav1d_thread_picture_wait(const Dav1dThreadPicture *p, int y,
+int dav1d_thread_picture_wait(const Dav1dThreadPicture *p, int y,
enum PlaneType plane_type);
/**
* Signal decoding progress.
*
- * y is in full-pixel luma units.
+ * y is in full-pixel luma units. FRAME_ERROR is used to signal a decoding
+ * error to frames using this frame as reference frame.
* plane_type denotes whether we have completed block data (pass 1;
* PLANE_TYPE_BLOCK), pixel data (pass 2, PLANE_TYPE_Y) or both (no
* 2-pass decoding; PLANE_TYPE_ALL).
--- a/src/recon.h
+++ b/src/recon.h
@@ -42,7 +42,7 @@
typedef decl_recon_b_intra_fn(*recon_b_intra_fn);
#define decl_recon_b_inter_fn(name) \
-void (name)(Dav1dTileContext *t, enum BlockSize bs, const Av1Block *b)
+int (name)(Dav1dTileContext *t, enum BlockSize bs, const Av1Block *b)
typedef decl_recon_b_inter_fn(*recon_b_inter_fn);
#define decl_filter_sbrow_fn(name) \
--- a/src/recon_tmpl.c
+++ b/src/recon_tmpl.c
@@ -488,12 +488,12 @@
}
}
-static void mc(Dav1dTileContext *const t,
- pixel *const dst8, coef *const dst16, const ptrdiff_t dst_stride,
- const int bw4, const int bh4,
- const int bx, const int by, const int pl,
- const mv mv, const Dav1dThreadPicture *const refp,
- const enum Filter2d filter_2d)
+static int mc(Dav1dTileContext *const t,
+ pixel *const dst8, coef *const dst16, const ptrdiff_t dst_stride,
+ const int bw4, const int bh4,
+ const int bx, const int by, const int pl,
+ const mv mv, const Dav1dThreadPicture *const refp,
+ const enum Filter2d filter_2d)
{
assert((dst8 != NULL) ^ (dst16 != NULL));
const Dav1dFrameContext *const f = t->f;
@@ -509,8 +509,11 @@
int w, h;
if (refp != &f->cur) { // i.e. not for intrabc
- dav1d_thread_picture_wait(refp, dy + bh4 * v_mul + !!my * 4,
- PLANE_TYPE_Y + !!pl);
+ if (dav1d_thread_picture_wait(refp, dy + bh4 * v_mul + !!my * 4,
+ PLANE_TYPE_Y + !!pl))
+ {
+ return -1;
+ }
w = (f->cur.p.p.w + ss_hor) >> ss_hor;
h = (f->cur.p.p.h + ss_ver) >> ss_ver;
} else {
@@ -538,12 +541,13 @@
f->dsp->mc.mct[filter_2d](dst16, ref, ref_stride, bw4 * h_mul,
bh4 * v_mul, mx << !ss_hor, my << !ss_ver);
}
+ return 0;
}
-static void obmc(Dav1dTileContext *const t,
- pixel *const dst, const ptrdiff_t dst_stride,
- const uint8_t *const b_dim, const int pl,
- const int bx4, const int by4, const int w4, const int h4)
+static int obmc(Dav1dTileContext *const t,
+ pixel *const dst, const ptrdiff_t dst_stride,
+ const uint8_t *const b_dim, const int pl,
+ const int bx4, const int by4, const int w4, const int h4)
{
assert(!(t->bx & 1) && !(t->by & 1));
const Dav1dFrameContext *const f = t->f;
@@ -564,6 +568,7 @@
const int ss_ver = !!pl && f->cur.p.p.layout == DAV1D_PIXEL_LAYOUT_I420;
const int ss_hor = !!pl && f->cur.p.p.layout != DAV1D_PIXEL_LAYOUT_I444;
const int h_mul = 4 >> ss_hor, v_mul = 4 >> ss_ver;
+ int res;
if (t->by > t->ts->tiling.row_start &&
(!pl || b_dim[0] * h_mul + b_dim[1] * v_mul >= 16))
@@ -577,10 +582,11 @@
if (a_r->ref[0] > 0) {
const int ow4 = iclip(a_b_dim[0], 2, b_dim[0]);
const int oh4 = imin(b_dim[1], 16) >> 1;
- mc(t, lap, NULL, ow4 * h_mul * sizeof(pixel), ow4, oh4,
- t->bx + x, t->by, pl, a_r->mv[0],
- &f->refp[a_r->ref[0] - 1],
- dav1d_filter_2d[t->a->filter[1][bx4 + x + 1]][t->a->filter[0][bx4 + x + 1]]);
+ res = mc(t, lap, NULL, ow4 * h_mul * sizeof(pixel), ow4, oh4,
+ t->bx + x, t->by, pl, a_r->mv[0],
+ &f->refp[a_r->ref[0] - 1],
+ dav1d_filter_2d[t->a->filter[1][bx4 + x + 1]][t->a->filter[0][bx4 + x + 1]]);
+ if (res) return res;
f->dsp->mc.blend(&dst[x * h_mul], dst_stride, lap,
h_mul * ow4, v_mul * oh4,
obmc_masks[imin(b_dim[3], 4) - ss_ver], 1);
@@ -600,10 +606,11 @@
if (l_r->ref[0] > 0) {
const int ow4 = imin(b_dim[0], 16) >> 1;
const int oh4 = iclip(l_b_dim[1], 2, b_dim[1]);
- mc(t, lap, NULL, h_mul * ow4 * sizeof(pixel), ow4, oh4,
- t->bx, t->by + y, pl, l_r->mv[0],
- &f->refp[l_r->ref[0] - 1],
- dav1d_filter_2d[t->l.filter[1][by4 + y + 1]][t->l.filter[0][by4 + y + 1]]);
+ res = mc(t, lap, NULL, h_mul * ow4 * sizeof(pixel), ow4, oh4,
+ t->bx, t->by + y, pl, l_r->mv[0],
+ &f->refp[l_r->ref[0] - 1],
+ dav1d_filter_2d[t->l.filter[1][by4 + y + 1]][t->l.filter[0][by4 + y + 1]]);
+ if (res) return res;
f->dsp->mc.blend(&dst[y * v_mul * PXSTRIDE(dst_stride)], dst_stride,
lap, h_mul * ow4, v_mul * oh4,
obmc_masks[imin(b_dim[2], 4) - ss_hor], 0);
@@ -611,13 +618,14 @@
}
y += imax(l_b_dim[1], 2);
}
+ return 0;
}
-static void warp_affine(Dav1dTileContext *const t,
- pixel *dst8, coef *dst16, const ptrdiff_t dstride,
- const uint8_t *const b_dim, const int pl,
- const Dav1dThreadPicture *const refp,
- const WarpedMotionParams *const wmp)
+static int warp_affine(Dav1dTileContext *const t,
+ pixel *dst8, coef *dst16, const ptrdiff_t dstride,
+ const uint8_t *const b_dim, const int pl,
+ const Dav1dThreadPicture *const refp,
+ const WarpedMotionParams *const wmp)
{
assert((dst8 != NULL) ^ (dst16 != NULL));
const Dav1dFrameContext *const f = t->f;
@@ -649,8 +657,11 @@
const pixel *ref_ptr;
ptrdiff_t ref_stride = refp->p.stride[!!pl];
- dav1d_thread_picture_wait(refp, dy + 4 + 8,
- PLANE_TYPE_Y + !!pl);
+ if (dav1d_thread_picture_wait(refp, dy + 4 + 8,
+ PLANE_TYPE_Y + !!pl))
+ {
+ return -1;
+ }
if (dx < 3 || dx + 8 + 4 > width || dy < 3 || dy + 8 + 4 > height) {
f->dsp->mc.emu_edge(t->emu_edge, 160 * sizeof(pixel),
refp->p.data[pl], ref_stride,
@@ -670,6 +681,7 @@
if (dst8) dst8 += 8 * PXSTRIDE(dstride);
else dst16 += 8 * dstride;
}
+ return 0;
}
void bytefn(dav1d_recon_b_intra)(Dav1dTileContext *const t, const enum BlockSize bs,
@@ -1054,7 +1066,7 @@
}
}
-void bytefn(dav1d_recon_b_inter)(Dav1dTileContext *const t, const enum BlockSize bs,
+int bytefn(dav1d_recon_b_inter)(Dav1dTileContext *const t, const enum BlockSize bs,
const Av1Block *const b)
{
Dav1dTileState *const ts = t->ts;
@@ -1072,6 +1084,7 @@
(bh4 > ss_ver || t->by & 1);
const int chr_layout_idx = f->cur.p.p.layout == DAV1D_PIXEL_LAYOUT_I400 ? 0 :
DAV1D_PIXEL_LAYOUT_I444 - f->cur.p.p.layout;
+ int res;
// prediction
const int cbh4 = (bh4 + ss_ver) >> ss_ver, cbw4 = (bw4 + ss_hor) >> ss_hor;
@@ -1081,13 +1094,16 @@
4 * ((t->bx >> ss_hor) + (t->by >> ss_ver) * PXSTRIDE(f->cur.p.stride[1]));
if (!(f->frame_hdr.frame_type & 1)) {
// intrabc
- mc(t, dst, NULL, f->cur.p.stride[0],
- bw4, bh4, t->bx, t->by, 0, b->mv[0], &f->cur, FILTER_2D_BILINEAR);
- if (has_chroma) for (int pl = 1; pl < 3; pl++)
- mc(t, ((pixel *) f->cur.p.data[pl]) + uvdstoff, NULL, f->cur.p.stride[1],
- bw4 << (bw4 == ss_hor), bh4 << (bh4 == ss_ver),
- t->bx & ~ss_hor, t->by & ~ss_ver,
- pl, b->mv[0], &f->cur, FILTER_2D_BILINEAR);
+ res = mc(t, dst, NULL, f->cur.p.stride[0],
+ bw4, bh4, t->bx, t->by, 0, b->mv[0], &f->cur, FILTER_2D_BILINEAR);
+ if (res) return res;
+ if (has_chroma) for (int pl = 1; pl < 3; pl++) {
+ res = mc(t, ((pixel *)f->cur.p.data[pl]) + uvdstoff, NULL, f->cur.p.stride[1],
+ bw4 << (bw4 == ss_hor), bh4 << (bh4 == ss_ver),
+ t->bx & ~ss_hor, t->by & ~ss_ver,
+ pl, b->mv[0], &f->cur, FILTER_2D_BILINEAR);
+ if (res) return res;
+ }
} else if (b->comp_type == COMP_INTER_NONE) {
const Dav1dThreadPicture *const refp = &f->refp[b->ref[0]];
const enum Filter2d filter_2d = b->filter2d;
@@ -1098,14 +1114,18 @@
(b->motion_mode == MM_WARP &&
t->warpmv.type > WM_TYPE_TRANSLATION)))
{
- warp_affine(t, dst, NULL, f->cur.p.stride[0], b_dim, 0, refp,
- b->motion_mode == MM_WARP ? &t->warpmv :
- &f->frame_hdr.gmv[b->ref[0]]);
+ res = warp_affine(t, dst, NULL, f->cur.p.stride[0], b_dim, 0, refp,
+ b->motion_mode == MM_WARP ? &t->warpmv :
+ &f->frame_hdr.gmv[b->ref[0]]);
+ if (res) return res;
} else {
- mc(t, dst, NULL, f->cur.p.stride[0],
- bw4, bh4, t->bx, t->by, 0, b->mv[0], refp, filter_2d);
- if (b->motion_mode == MM_OBMC)
- obmc(t, dst, f->cur.p.stride[0], b_dim, 0, bx4, by4, w4, h4);
+ res = mc(t, dst, NULL, f->cur.p.stride[0],
+ bw4, bh4, t->bx, t->by, 0, b->mv[0], refp, filter_2d);
+ if (res) return res;
+ if (b->motion_mode == MM_OBMC) {
+ res = obmc(t, dst, f->cur.p.stride[0], b_dim, 0, bx4, by4, w4, h4);
+ if (res) return res;
+ }
}
if (b->interintra_type) {
ALIGN_STK_32(pixel, tl_edge_buf, 65,);
@@ -1154,14 +1174,16 @@
assert(ss_hor == 1);
int h_off = 0, v_off = 0;
if (bw4 == 1 && bh4 == ss_ver) {
- for (int pl = 0; pl < 2; pl++)
- mc(t, ((pixel *) f->cur.p.data[1 + pl]) + uvdstoff,
- NULL, f->cur.p.stride[1],
- bw4, bh4, t->bx - 1, t->by - 1, 1 + pl,
- r[-(f->b4_stride + 1)].mv[0],
- &f->refp[r[-(f->b4_stride + 1)].ref[0] - 1],
- f->frame_thread.pass != 2 ? t->tl_4x4_filter :
- f->frame_thread.b[((t->by - 1) * f->b4_stride) + t->bx - 1].filter2d);
+ for (int pl = 0; pl < 2; pl++) {
+ res = mc(t, ((pixel *) f->cur.p.data[1 + pl]) + uvdstoff,
+ NULL, f->cur.p.stride[1],
+ bw4, bh4, t->bx - 1, t->by - 1, 1 + pl,
+ r[-(f->b4_stride + 1)].mv[0],
+ &f->refp[r[-(f->b4_stride + 1)].ref[0] - 1],
+ f->frame_thread.pass != 2 ? t->tl_4x4_filter :
+ f->frame_thread.b[((t->by - 1) * f->b4_stride) + t->bx - 1].filter2d);
+ if (res) return res;
+ }
v_off = 2 * PXSTRIDE(f->cur.p.stride[1]);
h_off = 2;
}
@@ -1168,29 +1190,35 @@
if (bw4 == 1) {
const enum Filter2d left_filter_2d =
dav1d_filter_2d[t->l.filter[1][by4]][t->l.filter[0][by4]];
- for (int pl = 0; pl < 2; pl++)
- mc(t, ((pixel *) f->cur.p.data[1 + pl]) + uvdstoff + v_off, NULL,
- f->cur.p.stride[1], bw4, bh4, t->bx - 1,
- t->by, 1 + pl, r[-1].mv[0], &f->refp[r[-1].ref[0] - 1],
- f->frame_thread.pass != 2 ? left_filter_2d :
- f->frame_thread.b[(t->by * f->b4_stride) + t->bx - 1].filter2d);
+ for (int pl = 0; pl < 2; pl++) {
+ res = mc(t, ((pixel *) f->cur.p.data[1 + pl]) + uvdstoff + v_off, NULL,
+ f->cur.p.stride[1], bw4, bh4, t->bx - 1,
+ t->by, 1 + pl, r[-1].mv[0], &f->refp[r[-1].ref[0] - 1],
+ f->frame_thread.pass != 2 ? left_filter_2d :
+ f->frame_thread.b[(t->by * f->b4_stride) + t->bx - 1].filter2d);
+ if (res) return res;
+ }
h_off = 2;
}
if (bh4 == ss_ver) {
const enum Filter2d top_filter_2d =
dav1d_filter_2d[t->a->filter[1][bx4]][t->a->filter[0][bx4]];
- for (int pl = 0; pl < 2; pl++)
- mc(t, ((pixel *) f->cur.p.data[1 + pl]) + uvdstoff + h_off, NULL,
- f->cur.p.stride[1], bw4, bh4, t->bx, t->by - 1,
- 1 + pl, r[-f->b4_stride].mv[0],
- &f->refp[r[-f->b4_stride].ref[0] - 1],
- f->frame_thread.pass != 2 ? top_filter_2d :
- f->frame_thread.b[((t->by - 1) * f->b4_stride) + t->bx].filter2d);
+ for (int pl = 0; pl < 2; pl++) {
+ res = mc(t, ((pixel *) f->cur.p.data[1 + pl]) + uvdstoff + h_off, NULL,
+ f->cur.p.stride[1], bw4, bh4, t->bx, t->by - 1,
+ 1 + pl, r[-f->b4_stride].mv[0],
+ &f->refp[r[-f->b4_stride].ref[0] - 1],
+ f->frame_thread.pass != 2 ? top_filter_2d :
+ f->frame_thread.b[((t->by - 1) * f->b4_stride) + t->bx].filter2d);
+ if (res) return res;
+ }
v_off = 2 * PXSTRIDE(f->cur.p.stride[1]);
}
- for (int pl = 0; pl < 2; pl++)
- mc(t, ((pixel *) f->cur.p.data[1 + pl]) + uvdstoff + h_off + v_off, NULL, f->cur.p.stride[1],
- bw4, bh4, t->bx, t->by, 1 + pl, b->mv[0], refp, filter_2d);
+ for (int pl = 0; pl < 2; pl++) {
+ res = mc(t, ((pixel *) f->cur.p.data[1 + pl]) + uvdstoff + h_off + v_off, NULL, f->cur.p.stride[1],
+ bw4, bh4, t->bx, t->by, 1 + pl, b->mv[0], refp, filter_2d);
+ if (res) return res;
+ }
} else {
if (imin(cbw4, cbh4) > 1 && !f->frame_hdr.force_integer_mv &&
((b->inter_mode == GLOBALMV &&
@@ -1198,21 +1226,26 @@
(b->motion_mode == MM_WARP &&
t->warpmv.type > WM_TYPE_TRANSLATION)))
{
- for (int pl = 0; pl < 2; pl++)
- warp_affine(t, ((pixel *) f->cur.p.data[1 + pl]) + uvdstoff, NULL,
- f->cur.p.stride[1], b_dim, 1 + pl, refp,
- b->motion_mode == MM_WARP ? &t->warpmv :
- &f->frame_hdr.gmv[b->ref[0]]);
+ for (int pl = 0; pl < 2; pl++) {
+ res = warp_affine(t, ((pixel *) f->cur.p.data[1 + pl]) + uvdstoff, NULL,
+ f->cur.p.stride[1], b_dim, 1 + pl, refp,
+ b->motion_mode == MM_WARP ? &t->warpmv :
+ &f->frame_hdr.gmv[b->ref[0]]);
+ if (res) return res;
+ }
} else {
for (int pl = 0; pl < 2; pl++) {
- mc(t, ((pixel *) f->cur.p.data[1 + pl]) + uvdstoff,
- NULL, f->cur.p.stride[1],
- bw4 << (bw4 == ss_hor), bh4 << (bh4 == ss_ver),
- t->bx & ~ss_hor, t->by & ~ss_ver,
- 1 + pl, b->mv[0], refp, filter_2d);
- if (b->motion_mode == MM_OBMC)
- obmc(t, ((pixel *) f->cur.p.data[1 + pl]) + uvdstoff,
- f->cur.p.stride[1], b_dim, 1 + pl, bx4, by4, w4, h4);
+ res = mc(t, ((pixel *) f->cur.p.data[1 + pl]) + uvdstoff,
+ NULL, f->cur.p.stride[1],
+ bw4 << (bw4 == ss_hor), bh4 << (bh4 == ss_ver),
+ t->bx & ~ss_hor, t->by & ~ss_ver,
+ 1 + pl, b->mv[0], refp, filter_2d);
+ if (res) return res;
+ if (b->motion_mode == MM_OBMC) {
+ res = obmc(t, ((pixel *) f->cur.p.data[1 + pl]) + uvdstoff,
+ f->cur.p.stride[1], b_dim, 1 + pl, bx4, by4, w4, h4);
+ if (res) return res;
+ }
}
}
if (b->interintra_type) {
@@ -1273,11 +1306,13 @@
if (b->inter_mode == GLOBALMV_GLOBALMV && !f->frame_hdr.force_integer_mv &&
f->frame_hdr.gmv[b->ref[i]].type > WM_TYPE_TRANSLATION)
{
- warp_affine(t, NULL, tmp[i], bw4 * 4, b_dim, 0, refp,
- &f->frame_hdr.gmv[b->ref[i]]);
+ res = warp_affine(t, NULL, tmp[i], bw4 * 4, b_dim, 0, refp,
+ &f->frame_hdr.gmv[b->ref[i]]);
+ if (res) return res;
} else {
- mc(t, NULL, tmp[i], 0, bw4, bh4, t->bx, t->by, 0,
- b->mv[i], refp, filter_2d);
+ res = mc(t, NULL, tmp[i], 0, bw4, bh4, t->bx, t->by, 0,
+ b->mv[i], refp, filter_2d);
+ if (res) return res;
}
}
switch (b->comp_type) {
@@ -1314,11 +1349,13 @@
imin(cbw4, cbh4) > 1 && !f->frame_hdr.force_integer_mv &&
f->frame_hdr.gmv[b->ref[i]].type > WM_TYPE_TRANSLATION)
{
- warp_affine(t, NULL, tmp[i], bw4 * 2, b_dim, 1 + pl,
- refp, &f->frame_hdr.gmv[b->ref[i]]);
+ res = warp_affine(t, NULL, tmp[i], bw4 * 2, b_dim, 1 + pl,
+ refp, &f->frame_hdr.gmv[b->ref[i]]);
+ if (res) return res;
} else {
- mc(t, NULL, tmp[i], 0, bw4, bh4, t->bx, t->by,
- 1 + pl, b->mv[i], refp, filter_2d);
+ res = mc(t, NULL, tmp[i], 0, bw4, bh4, t->bx, t->by,
+ 1 + pl, b->mv[i], refp, filter_2d);
+ if (res) return res;
}
}
pixel *const uvdst = ((pixel *) f->cur.p.data[1 + pl]) + uvdstoff;
@@ -1368,7 +1405,7 @@
case_set(cbw4, a->, 0, cbx4);
#undef set_ctx
}
- return;
+ return 0;
}
const TxfmInfo *const uvtx = &dav1d_txfm_dimensions[b->uvtx];
@@ -1465,6 +1502,7 @@
}
}
}
+ return 0;
}
void bytefn(dav1d_filter_sbrow)(Dav1dFrameContext *const f, const int sby) {
--- a/src/thread_task.h
+++ b/src/thread_task.h
@@ -32,6 +32,7 @@
#include "src/internal.h"
+#define FRAME_ERROR (UINT_MAX - 1)
#define TILE_ERROR (INT_MAX - 1)
int dav1d_decode_frame(Dav1dFrameContext *f);