Halt tile component decoding at the first entropy error (this will be a desync and is not recoverable). If any tile components contain errors then discard the frame unless the output-corrupt flag is set.
Also fixes CID 1646764, which is the error case where the tile component is too large for get_bits to handle. --- libavcodec/apv_decode.c | 52 ++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/libavcodec/apv_decode.c b/libavcodec/apv_decode.c index 2a59c9b25d..7ee39e578a 100644 --- a/libavcodec/apv_decode.c +++ b/libavcodec/apv_decode.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <stdatomic.h> + #include "libavutil/mastering_display_metadata.h" #include "libavutil/mem_internal.h" #include "libavutil/pixdesc.h" @@ -42,6 +44,7 @@ typedef struct APVDecodeContext { APVVLCLUT decode_lut; AVFrame *output_frame; + atomic_int tile_errors; uint8_t warned_additional_frames; uint8_t warned_unknown_pbu_types; @@ -121,6 +124,8 @@ static av_cold int apv_decode_init(AVCodecContext *avctx) ff_apv_dsp_init(&apv->dsp); + atomic_init(&apv->tile_errors, 0); + return 0; } @@ -150,7 +155,7 @@ static int apv_decode_block(AVCodecContext *avctx, err = ff_apv_entropy_decode_block(coeff, gbc, entropy_state); if (err < 0) - return 0; + return err; apv->dsp.decode_transquant(output, pitch, coeff, qmatrix, @@ -207,8 +212,12 @@ static int apv_decode_tile_component(AVCodecContext *avctx, void *data, .prev_1st_ac_level = 0, }; - init_get_bits8(&gbc, tile->tile_data[comp_index], - tile->tile_header.tile_data_size[comp_index]); + int err; + + err = init_get_bits8(&gbc, tile->tile_data[comp_index], + tile->tile_header.tile_data_size[comp_index]); + if (err < 0) + goto fail; // Combine the bitstream quantisation matrix with the qp scaling // in advance. (Including qp_shift as well would overflow 16 bits.) @@ -243,12 +252,17 @@ static int apv_decode_tile_component(AVCodecContext *avctx, void *data, uint8_t *block_start = apv->output_frame->data[comp_index] + frame_y * frame_pitch + 2 * frame_x; - apv_decode_block(avctx, - block_start, frame_pitch, - &gbc, &entropy_state, - bit_depth, - qp_shift, - qmatrix_scaled); + err = apv_decode_block(avctx, + block_start, frame_pitch, + &gbc, &entropy_state, + bit_depth, + qp_shift, + qmatrix_scaled); + if (err < 0) { + // Error in block decode means entropy desync, + // so this is not recoverable. + goto fail; + } } } } @@ -260,6 +274,13 @@ static int apv_decode_tile_component(AVCodecContext *avctx, void *data, tile_start_x, tile_start_y); return 0; + +fail: + av_log(avctx, AV_LOG_VERBOSE, + "Decode error in tile %d component %d.\n", + tile_index, comp_index); + atomic_fetch_add(&apv->tile_errors, 1); + return err; } static int apv_decode(AVCodecContext *avctx, AVFrame *output, @@ -281,6 +302,7 @@ static int apv_decode(AVCodecContext *avctx, AVFrame *output, return err; apv->output_frame = output; + atomic_store(&apv->tile_errors, 0); // Each component within a tile is independent of every other, // so we can decode all in parallel. @@ -289,6 +311,18 @@ static int apv_decode(AVCodecContext *avctx, AVFrame *output, avctx->execute2(avctx, apv_decode_tile_component, input, NULL, job_count); + err = atomic_load(&apv->tile_errors); + if (err > 0) { + av_log(avctx, AV_LOG_ERROR, + "Decode errors in %d tile components.\n", err); + if (avctx->flags & AV_CODEC_FLAG_OUTPUT_CORRUPT) { + // Output the frame anyway. + output->flags |= AV_FRAME_FLAG_CORRUPT; + } else { + return AVERROR_INVALIDDATA; + } + } + return 0; } -- 2.47.2 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".