From 953dd1894d8c87451f9b8798a3962eccaeb6c5d0 Mon Sep 17 00:00:00 2001 From: James Zern Date: Wed, 17 Dec 2014 12:00:05 -0800 Subject: [PATCH] vp9: add per-tile longjmp error handling this avoids longjmp'ing from another thread on error which will cause undesired behavior Change-Id: Ic9074ed8cc4243944bf2539d6e482f213f4e8c86 --- vp9/common/vp9_blockd.h | 2 ++ vp9/common/vp9_onyxc_int.h | 1 + vp9/decoder/vp9_decodeframe.c | 17 +++++++++++++++-- vp9/decoder/vp9_decodemv.c | 4 ++-- vp9/decoder/vp9_dthread.h | 2 ++ 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