History

apv_decode: Improve reporting of decode errors

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.

Mark Thompson committed 1 year ago

Commit 1a9a2ba1 parent 5acd2141 file · +43 −9Browse files

Unified · Split

libavcodec/apv_decode.c+43−9
@@ -16,6 +16,8 @@ · 15 unmodified lines
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */17 */
18 18
19#include <stdatomic.h>
20
19#include "libavutil/mastering_display_metadata.h"21#include "libavutil/mastering_display_metadata.h"
20#include "libavutil/mem_internal.h"22#include "libavutil/mem_internal.h"
21#include "libavutil/pixdesc.h"23#include "libavutil/pixdesc.h"
@@ -41,6 +43,7 @@ typedef struct APVDecodeContext { · 19 unmodified lines
41 APVDerivedTileInfo tile_info;43 APVDerivedTileInfo tile_info;
42 44
43 AVFrame *output_frame;45 AVFrame *output_frame;
46 atomic_int tile_errors;
44 47
45 uint8_t warned_additional_frames;48 uint8_t warned_additional_frames;
46 uint8_t warned_unknown_pbu_types;49 uint8_t warned_unknown_pbu_types;
@@ -129,6 +132,8 @@ static av_cold int apv_decode_init(AVCodecContext *avctx) · 82 unmodified lines
129 132
130 ff_apv_dsp_init(&apv->dsp);133 ff_apv_dsp_init(&apv->dsp);
131 134
135 atomic_init(&apv->tile_errors, 0);
136
132 return 0;137 return 0;
133}138}
134 139
@@ -158,7 +163,7 @@ static int apv_decode_block(AVCodecContext *avctx, · 23 unmodified lines
158 163
159 err = ff_apv_entropy_decode_block(coeff, gbc, entropy_state);164 err = ff_apv_entropy_decode_block(coeff, gbc, entropy_state);
160 if (err < 0)165 if (err < 0)
161 return 0;166 return err;
162 167
163 apv->dsp.decode_transquant(output, pitch,168 apv->dsp.decode_transquant(output, pitch,
164 coeff, qmatrix,169 coeff, qmatrix,
@@ -215,8 +220,12 @@ static int apv_decode_tile_component(AVCodecContext *avctx, void *data, · 50 unmodified lines
215 .prev_1st_ac_level = 0,220 .prev_1st_ac_level = 0,
216 };221 };
217 222
218 init_get_bits8(&gbc, tile->tile_data[comp_index],223 int err;
219 tile->tile_header.tile_data_size[comp_index]);224
225 err = init_get_bits8(&gbc, tile->tile_data[comp_index],
226 tile->tile_header.tile_data_size[comp_index]);
227 if (err < 0)
228 goto fail;
220 229
221 // Combine the bitstream quantisation matrix with the qp scaling230 // Combine the bitstream quantisation matrix with the qp scaling
222 // in advance. (Including qp_shift as well would overflow 16 bits.)231 // in advance. (Including qp_shift as well would overflow 16 bits.)
@@ -251,12 +260,17 @@ static int apv_decode_tile_component(AVCodecContext *avctx, void *data, · 28 unmodified lines
251 uint8_t *block_start = apv->output_frame->data[comp_index] +260 uint8_t *block_start = apv->output_frame->data[comp_index] +
252 frame_y * frame_pitch + 2 * frame_x;261 frame_y * frame_pitch + 2 * frame_x;
253 262
254 apv_decode_block(avctx,263 err = apv_decode_block(avctx,
255 block_start, frame_pitch,264 block_start, frame_pitch,
256 &gbc, &entropy_state,265 &gbc, &entropy_state,
257 bit_depth,266 bit_depth,
258 qp_shift,267 qp_shift,
259 qmatrix_scaled);268 qmatrix_scaled);
269 if (err < 0) {
270 // Error in block decode means entropy desync,
271 // so this is not recoverable.
272 goto fail;
273 }
260 }274 }
261 }275 }
262 }276 }
@@ -268,6 +282,13 @@ static int apv_decode_tile_component(AVCodecContext *avctx, void *data, · 5 unmodified lines
268 tile_start_x, tile_start_y);282 tile_start_x, tile_start_y);
269 283
270 return 0;284 return 0;
285
286fail:
287 av_log(avctx, AV_LOG_VERBOSE,
288 "Decode error in tile %d component %d.\n",
289 tile_index, comp_index);
290 atomic_fetch_add_explicit(&apv->tile_errors, 1, memory_order_relaxed);
291 return err;
271}292}
272 293
273static int apv_decode(AVCodecContext *avctx, AVFrame *output,294static int apv_decode(AVCodecContext *avctx, AVFrame *output,
@@ -289,6 +310,7 @@ static int apv_decode(AVCodecContext *avctx, AVFrame *output, · 15 unmodified lines
289 return err;310 return err;
290 311
291 apv->output_frame = output;312 apv->output_frame = output;
313 atomic_store_explicit(&apv->tile_errors, 0, memory_order_relaxed);
292 314
293 // Each component within a tile is independent of every other,315 // Each component within a tile is independent of every other,
294 // so we can decode all in parallel.316 // so we can decode all in parallel.
@@ -297,6 +319,18 @@ static int apv_decode(AVCodecContext *avctx, AVFrame *output, · 2 unmodified lines
297 avctx->execute2(avctx, apv_decode_tile_component,319 avctx->execute2(avctx, apv_decode_tile_component,
298 input, NULL, job_count);320 input, NULL, job_count);
299 321
322 err = atomic_load_explicit(&apv->tile_errors, memory_order_relaxed);
323 if (err > 0) {
324 av_log(avctx, AV_LOG_ERROR,
325 "Decode errors in %d tile components.\n", err);
326 if (avctx->flags & AV_CODEC_FLAG_OUTPUT_CORRUPT) {
327 // Output the frame anyway.
328 output->flags |= AV_FRAME_FLAG_CORRUPT;
329 } else {
330 return AVERROR_INVALIDDATA;
331 }
332 }
333
300 return 0;334 return 0;
301}335}
302 336

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t