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

Showing the changes to libavcodec (1 of 1 file). Show all

Unified · Split

libavcodec/apv_decode.c+43−9
@@ -16,6 +16,8 @@ · 15 unmodified lines
1616 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1717 */
1818
19+#include <stdatomic.h>
20+
1921 #include "libavutil/mastering_display_metadata.h"
2022 #include "libavutil/mem_internal.h"
2123 #include "libavutil/pixdesc.h"
@@ -41,6 +43,7 @@ typedef struct APVDecodeContext { · 19 unmodified lines
4143 APVDerivedTileInfo tile_info;
4244
4345 AVFrame *output_frame;
46+ atomic_int tile_errors;
4447
4548 uint8_t warned_additional_frames;
4649 uint8_t warned_unknown_pbu_types;
@@ -129,6 +132,8 @@ static av_cold int apv_decode_init(AVCodecContext *avctx) · 82 unmodified lines
129132
130133 ff_apv_dsp_init(&apv->dsp);
131134
135+ atomic_init(&apv->tile_errors, 0);
136+
132137 return 0;
133138 }
134139
@@ -158,7 +163,7 @@ static int apv_decode_block(AVCodecContext *avctx, · 23 unmodified lines
158163
159164 err = ff_apv_entropy_decode_block(coeff, gbc, entropy_state);
160165 if (err < 0)
161− return 0;
166+ return err;
162167
163168 apv->dsp.decode_transquant(output, pitch,
164169 coeff, qmatrix,
@@ -215,8 +220,12 @@ static int apv_decode_tile_component(AVCodecContext *avctx, void *data, · 50 unmodified lines
215220 .prev_1st_ac_level = 0,
216221 };
217222
218− init_get_bits8(&gbc, tile->tile_data[comp_index],
219− tile->tile_header.tile_data_size[comp_index]);
223+ int err;
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;
220229
221230 // Combine the bitstream quantisation matrix with the qp scaling
222231 // 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
251260 uint8_t *block_start = apv->output_frame->data[comp_index] +
252261 frame_y * frame_pitch + 2 * frame_x;
253262
254− apv_decode_block(avctx,
255− block_start, frame_pitch,
256− &gbc, &entropy_state,
257− bit_depth,
258− qp_shift,
259− qmatrix_scaled);
263+ err = apv_decode_block(avctx,
264+ block_start, frame_pitch,
265+ &gbc, &entropy_state,
266+ bit_depth,
267+ qp_shift,
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+ }
260274 }
261275 }
262276 }
@@ -268,6 +282,13 @@ static int apv_decode_tile_component(AVCodecContext *avctx, void *data, · 5 unmodified lines
268282 tile_start_x, tile_start_y);
269283
270284 return 0;
285+
286+fail:
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;
271292 }
272293
273294 static int apv_decode(AVCodecContext *avctx, AVFrame *output,
@@ -289,6 +310,7 @@ static int apv_decode(AVCodecContext *avctx, AVFrame *output, · 15 unmodified lines
289310 return err;
290311
291312 apv->output_frame = output;
313+ atomic_store_explicit(&apv->tile_errors, 0, memory_order_relaxed);
292314
293315 // Each component within a tile is independent of every other,
294316 // so we can decode all in parallel.
@@ -297,6 +319,18 @@ static int apv_decode(AVCodecContext *avctx, AVFrame *output, · 2 unmodified lines
297319 avctx->execute2(avctx, apv_decode_tile_component,
298320 input, NULL, job_count);
299321
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+
300334 return 0;
301335 }
302336

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