aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Zern <jzern@google.com>2014-12-17 12:00:05 -0800
committerJames Zern <jzern@google.com>2014-12-19 11:50:04 -0800
commit953dd1894d8c87451f9b8798a3962eccaeb6c5d0 (patch)
tree11b39d454e0d645641eb18962f76e7a12c19b2eb
parent8d558f2ca5867828cbf07ef1dce9ad457be7e818 (diff)
downloadlibvpx-953dd1894d8c87451f9b8798a3962eccaeb6c5d0.tar.gz
vp9: add per-tile longjmp error handling
this avoids longjmp'ing from another thread on error which will cause undesired behavior Change-Id: Ic9074ed8cc4243944bf2539d6e482f213f4e8c86
-rw-r--r--vp9/common/vp9_blockd.h2
-rw-r--r--vp9/common/vp9_onyxc_int.h1
-rw-r--r--vp9/decoder/vp9_decodeframe.c17
-rw-r--r--vp9/decoder/vp9_decodemv.c4
-rw-r--r--vp9/decoder/vp9_dthread.h2
5 files changed, 22 insertions, 4 deletions
diff --git a/vp9/common/vp9_blockd.h b/vp9/common/vp9_blockd.h
index ebb1d1d0a..e33d336a1 100644
--- a/vp9/common/vp9_blockd.h
+++ b/vp9/common/vp9_blockd.h
@@ -231,6 +231,8 @@ typedef struct macroblockd {
int lossless;
int corrupted;
+
+ struct vpx_internal_error_info *error_info;
} MACROBLOCKD;
static INLINE BLOCK_SIZE get_subsize(BLOCK_SIZE bsize,
diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h
index c166590e2..a7b681a07 100644
--- a/vp9/common/vp9_onyxc_int.h
+++ b/vp9/common/vp9_onyxc_int.h
@@ -271,6 +271,7 @@ static INLINE void init_macroblockd(VP9_COMMON *cm, MACROBLOCKD *xd) {
xd->above_seg_context = cm->above_seg_context;
xd->mi_stride = cm->mi_stride;
+ xd->error_info = &cm->error;
}
static INLINE int frame_is_intra_only(const VP9_COMMON *const cm) {
diff --git a/vp9/decoder/vp9_decodeframe.c b/vp9/decoder/vp9_decodeframe.c
index 58df87d0c..6914cb700 100644
--- a/vp9/decoder/vp9_decodeframe.c
+++ b/vp9/decoder/vp9_decodeframe.c
@@ -463,8 +463,8 @@ static void decode_partition(VP9_COMMON *const cm, MACROBLOCKD *const xd,
subsize = get_subsize(bsize, partition);
uv_subsize = ss_size_lookup[subsize][cm->subsampling_x][cm->subsampling_y];
if (subsize >= BLOCK_8X8 && uv_subsize == BLOCK_INVALID)
- vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME,
- "Invalid block size.");
+ vpx_internal_error(xd->error_info,
+ VPX_CODEC_CORRUPT_FRAME, "Invalid block size.");
if (subsize < BLOCK_8X8) {
decode_block(cm, xd, tile, mi_row, mi_col, r, subsize);
} else {
@@ -1019,6 +1019,15 @@ static int tile_worker_hook(TileWorkerData *const tile_data,
const TileInfo *const tile) {
int mi_row, mi_col;
+ if (setjmp(tile_data->error_info.jmp)) {
+ tile_data->error_info.setjmp = 0;
+ tile_data->xd.corrupted = 1;
+ return 0;
+ }
+
+ tile_data->error_info.setjmp = 1;
+ tile_data->xd.error_info = &tile_data->error_info;
+
for (mi_row = tile->mi_row_start; mi_row < tile->mi_row_end;
mi_row += MI_BLOCK_SIZE) {
vp9_zero(tile_data->xd.left_context);
@@ -1165,6 +1174,10 @@ static const uint8_t *decode_tiles_mt(VP9Decoder *pbi,
for (; i > 0; --i) {
VP9Worker *const worker = &pbi->tile_workers[i - 1];
+ // TODO(jzern): The tile may have specific error data associated with
+ // its vpx_internal_error_info which could be propagated to the main info
+ // in cm. Additionally once the threads have been synced and an error is
+ // detected, there's no point in continuing to decode tiles.
pbi->mb.corrupted |= !winterface->sync(worker);
}
if (final_worker > -1) {
diff --git a/vp9/decoder/vp9_decodemv.c b/vp9/decoder/vp9_decodemv.c
index cff94db2d..1c2603b0a 100644
--- a/vp9/decoder/vp9_decodemv.c
+++ b/vp9/decoder/vp9_decodemv.c
@@ -438,7 +438,7 @@ static void read_inter_block_mode_info(VP9_COMMON *const cm,
RefBuffer *ref_buf = &cm->frame_refs[frame - LAST_FRAME];
xd->block_refs[ref] = ref_buf;
if ((!vp9_is_valid_scale(&ref_buf->sf)))
- vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
+ vpx_internal_error(xd->error_info, VPX_CODEC_UNSUP_BITSTREAM,
"Reference frame has invalid dimensions");
vp9_setup_pre_planes(xd, ref, ref_buf->buf, mi_row, mi_col,
&ref_buf->sf);
@@ -451,7 +451,7 @@ static void read_inter_block_mode_info(VP9_COMMON *const cm,
if (vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
mbmi->mode = ZEROMV;
if (bsize < BLOCK_8X8) {
- vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
+ vpx_internal_error(xd->error_info, VPX_CODEC_UNSUP_BITSTREAM,
"Invalid usage of segement feature on small blocks");
return;
}
diff --git a/vp9/decoder/vp9_dthread.h b/vp9/decoder/vp9_dthread.h
index d5810b45b..664aaa32a 100644
--- a/vp9/decoder/vp9_dthread.h
+++ b/vp9/decoder/vp9_dthread.h
@@ -14,6 +14,7 @@
#include "./vpx_config.h"
#include "vp9/common/vp9_thread.h"
#include "vp9/decoder/vp9_reader.h"
+#include "vpx/internal/vpx_codec_internal.h"
struct VP9Common;
struct VP9Decoder;
@@ -22,6 +23,7 @@ typedef struct TileWorkerData {
struct VP9Common *cm;
vp9_reader bit_reader;
DECLARE_ALIGNED(16, struct macroblockd, xd);
+ struct vpx_internal_error_info error_info;
} TileWorkerData;
// Loopfilter row synchronization