From 9b6aafba6c06ef62783dd5e9c5ed668f3a095128 Mon Sep 17 00:00:00 2001 From: John Brooks Date: Mon, 12 Dec 2011 17:04:14 -0700 Subject: mpegvideo: fix invalid memory access for small video dimensions When either video dimension is only one macroblock, subtractions based on v_edge_pos and the macroblock size may be negative. In that situation, an unsigned comparison isn't sufficent to test for MV overruns, because a limit of (unsigned)-1 will let any other value pass. Signed-off-by: Anton Khirnov --- libavcodec/mpegvideo.c | 12 ++++++------ libavcodec/mpegvideo_common.h | 28 ++++++++++++++-------------- 2 files changed, 20 insertions(+), 20 deletions(-) (limited to 'libavcodec') diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index f711d36aec..50e6ad6da4 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -1843,8 +1843,8 @@ static inline int hpel_motion_lowres(MpegEncContext *s, src += src_y * stride + src_x; - if ((unsigned)src_x > h_edge_pos - (!!sx) - w || - (unsigned)src_y > (v_edge_pos >> field_based) - (!!sy) - h) { + if ((unsigned)src_x > FFMAX( h_edge_pos - (!!sx) - w, 0) || + (unsigned)src_y > FFMAX((v_edge_pos >> field_based) - (!!sy) - h, 0)) { s->dsp.emulated_edge_mc(s->edge_emu_buffer, src, s->linesize, w + 1, (h + 1) << field_based, src_x, src_y << field_based, @@ -1928,8 +1928,8 @@ static av_always_inline void mpeg_motion_lowres(MpegEncContext *s, ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x; ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x; - if ((unsigned) src_x > h_edge_pos - (!!sx) - 2 * block_s || - (unsigned) src_y > (v_edge_pos >> field_based) - (!!sy) - h) { + if ((unsigned) src_x > FFMAX( h_edge_pos - (!!sx) - 2 * block_s, 0) || + (unsigned) src_y > FFMAX((v_edge_pos >> field_based) - (!!sy) - h, 0)) { s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr_y, s->linesize, 17, 17 + field_based, src_x, src_y << field_based, h_edge_pos, @@ -2011,8 +2011,8 @@ static inline void chroma_4mv_motion_lowres(MpegEncContext *s, offset = src_y * s->uvlinesize + src_x; ptr = ref_picture[1] + offset; if (s->flags & CODEC_FLAG_EMU_EDGE) { - if ((unsigned) src_x > h_edge_pos - (!!sx) - block_s || - (unsigned) src_y > v_edge_pos - (!!sy) - block_s) { + if ((unsigned) src_x > FFMAX(h_edge_pos - (!!sx) - block_s, 0) || + (unsigned) src_y > FFMAX(v_edge_pos - (!!sy) - block_s, 0)) { s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9, src_x, src_y, h_edge_pos, v_edge_pos); ptr = s->edge_emu_buffer; diff --git a/libavcodec/mpegvideo_common.h b/libavcodec/mpegvideo_common.h index d64404d8c5..9f6307ea7c 100644 --- a/libavcodec/mpegvideo_common.h +++ b/libavcodec/mpegvideo_common.h @@ -81,8 +81,8 @@ static inline void gmc1_motion(MpegEncContext *s, ptr = ref_picture[0] + (src_y * linesize) + src_x; if(s->flags&CODEC_FLAG_EMU_EDGE){ - if( (unsigned)src_x >= s->h_edge_pos - 17 - || (unsigned)src_y >= s->v_edge_pos - 17){ + if( (unsigned)src_x >= FFMAX(s->h_edge_pos - 17, 0) + || (unsigned)src_y >= FFMAX(s->v_edge_pos - 17, 0)){ s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr, linesize, 17, 17, src_x, src_y, s->h_edge_pos, s->v_edge_pos); ptr= s->edge_emu_buffer; } @@ -120,8 +120,8 @@ static inline void gmc1_motion(MpegEncContext *s, offset = (src_y * uvlinesize) + src_x; ptr = ref_picture[1] + offset; if(s->flags&CODEC_FLAG_EMU_EDGE){ - if( (unsigned)src_x >= (s->h_edge_pos>>1) - 9 - || (unsigned)src_y >= (s->v_edge_pos>>1) - 9){ + if( (unsigned)src_x >= FFMAX((s->h_edge_pos>>1) - 9, 0) + || (unsigned)src_y >= FFMAX((s->v_edge_pos>>1) - 9, 0)){ s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr, uvlinesize, 9, 9, src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1); ptr= s->edge_emu_buffer; emu=1; @@ -221,8 +221,8 @@ static inline int hpel_motion(MpegEncContext *s, src += src_y * stride + src_x; if(s->unrestricted_mv && (s->flags&CODEC_FLAG_EMU_EDGE)){ - if( (unsigned)src_x > h_edge_pos - (motion_x&1) - w - || (unsigned)src_y > v_edge_pos - (motion_y&1) - h){ + if( (unsigned)src_x > FFMAX(h_edge_pos - (motion_x&1) - w, 0) + || (unsigned)src_y > FFMAX(v_edge_pos - (motion_y&1) - h, 0)){ s->dsp.emulated_edge_mc(s->edge_emu_buffer, src, s->linesize, w+1, (h+1)<v_edge_pos); src= s->edge_emu_buffer; @@ -307,8 +307,8 @@ if(s->quarter_sample) ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x; ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x; - if( (unsigned)src_x > s->h_edge_pos - (motion_x&1) - 16 - || (unsigned)src_y > v_edge_pos - (motion_y&1) - h){ + if( (unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x&1) - 16, 0) + || (unsigned)src_y > FFMAX( v_edge_pos - (motion_y&1) - h , 0)){ if(is_mpeg12 || s->codec_id == CODEC_ID_MPEG2VIDEO || s->codec_id == CODEC_ID_MPEG1VIDEO){ av_log(s->avctx,AV_LOG_DEBUG, @@ -510,8 +510,8 @@ static inline void qpel_motion(MpegEncContext *s, ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x; ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x; - if( (unsigned)src_x > s->h_edge_pos - (motion_x&3) - 16 - || (unsigned)src_y > v_edge_pos - (motion_y&3) - h ){ + if( (unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x&3) - 16, 0) + || (unsigned)src_y > FFMAX( v_edge_pos - (motion_y&3) - h , 0)){ s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr_y, s->linesize, 17, 17+field_based, src_x, src_y<h_edge_pos, s->v_edge_pos); @@ -588,8 +588,8 @@ static inline void chroma_4mv_motion(MpegEncContext *s, offset = src_y * s->uvlinesize + src_x; ptr = ref_picture[1] + offset; if(s->flags&CODEC_FLAG_EMU_EDGE){ - if( (unsigned)src_x > (s->h_edge_pos>>1) - (dxy &1) - 8 - || (unsigned)src_y > (s->v_edge_pos>>1) - (dxy>>1) - 8){ + if( (unsigned)src_x > FFMAX((s->h_edge_pos>>1) - (dxy &1) - 8, 0) + || (unsigned)src_y > FFMAX((s->v_edge_pos>>1) - (dxy>>1) - 8, 0)){ s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9, src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1); @@ -760,8 +760,8 @@ static av_always_inline void MPV_motion_internal(MpegEncContext *s, ptr = ref_picture[0] + (src_y * s->linesize) + (src_x); if(s->flags&CODEC_FLAG_EMU_EDGE){ - if( (unsigned)src_x > s->h_edge_pos - (motion_x&3) - 8 - || (unsigned)src_y > s->v_edge_pos - (motion_y&3) - 8 ){ + if( (unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x&3) - 8, 0) + || (unsigned)src_y > FFMAX(s->v_edge_pos - (motion_y&3) - 8, 0)){ s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->linesize, 9, 9, src_x, src_y, -- cgit v1.2.3 From f88949214cea6b23a6f48e5d1b032cd6cf0f78cb Mon Sep 17 00:00:00 2001 From: Dustin Brody Date: Fri, 20 Jan 2012 03:57:32 -0500 Subject: lavc: rename err_filter option to err_detect and document it Signed-off-by: Anton Khirnov --- libavcodec/options.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'libavcodec') diff --git a/libavcodec/options.c b/libavcodec/options.c index 00d80e07c3..0d41da52ac 100644 --- a/libavcodec/options.c +++ b/libavcodec/options.c @@ -208,11 +208,11 @@ static const AVOption options[]={ {"very_aggressive", NULL, 0, AV_OPT_TYPE_CONST, {.dbl = FF_ER_VERY_AGGRESSIVE }, INT_MIN, INT_MAX, V|D, "er"}, {"explode", "abort decoding on error recognition", 0, AV_OPT_TYPE_CONST, {.dbl = FF_ER_EXPLODE }, INT_MIN, INT_MAX, V|D, "er"}, #endif /* FF_API_ER */ -{"err_filter", "set error detection filter flags", OFFSET(err_recognition), AV_OPT_TYPE_FLAGS, {.dbl = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, A|V|D, "err_filter"}, -{"crccheck", NULL, 0, AV_OPT_TYPE_CONST, {.dbl = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, V|D, "err_filter"}, -{"bitstream", NULL, 0, AV_OPT_TYPE_CONST, {.dbl = AV_EF_BITSTREAM }, INT_MIN, INT_MAX, V|D, "err_filter"}, -{"buffer", NULL, 0, AV_OPT_TYPE_CONST, {.dbl = AV_EF_BUFFER }, INT_MIN, INT_MAX, V|D, "err_filter"}, -{"explode", "abort decoding on minor error recognition", 0, AV_OPT_TYPE_CONST, {.dbl = AV_EF_EXPLODE }, INT_MIN, INT_MAX, V|D, "err_filter"}, +{"err_detect", "set error detection flags", OFFSET(err_recognition), AV_OPT_TYPE_FLAGS, {.dbl = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, +{"crccheck", "verify embedded CRCs", 0, AV_OPT_TYPE_CONST, {.dbl = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, V|D, "err_detect"}, +{"bitstream", "detect bitstream specification deviations", 0, AV_OPT_TYPE_CONST, {.dbl = AV_EF_BITSTREAM }, INT_MIN, INT_MAX, V|D, "err_detect"}, +{"buffer", "detect improper bitstream length", 0, AV_OPT_TYPE_CONST, {.dbl = AV_EF_BUFFER }, INT_MIN, INT_MAX, V|D, "err_detect"}, +{"explode", "abort decoding on minor error detection", 0, AV_OPT_TYPE_CONST, {.dbl = AV_EF_EXPLODE }, INT_MIN, INT_MAX, V|D, "err_detect"}, {"has_b_frames", NULL, OFFSET(has_b_frames), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX}, {"block_align", NULL, OFFSET(block_align), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX}, #if FF_API_PARSE_FRAME -- cgit v1.2.3 From d2a0041c2075a553bb8d4f94591f8556680190c8 Mon Sep 17 00:00:00 2001 From: Dustin Brody Date: Mon, 16 Jan 2012 08:25:04 -0500 Subject: mpegaudiodec: switch error detection check to AV_EF_BUFFER Signed-off-by: Anton Khirnov --- libavcodec/mpegaudiodec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libavcodec') diff --git a/libavcodec/mpegaudiodec.c b/libavcodec/mpegaudiodec.c index 6a06afa680..a83b1621fd 100644 --- a/libavcodec/mpegaudiodec.c +++ b/libavcodec/mpegaudiodec.c @@ -985,7 +985,7 @@ static int huffman_decode(MPADecodeContext *s, GranuleDef *g, /* skip extension bits */ bits_left = end_pos2 - get_bits_count(&s->gb); //av_log(NULL, AV_LOG_ERROR, "left:%d buf:%p\n", bits_left, s->in_gb.buffer); - if (bits_left < 0 && (s->err_recognition & AV_EF_BITSTREAM)) { + if (bits_left < 0 && (s->err_recognition & AV_EF_BUFFER)) { av_log(s->avctx, AV_LOG_ERROR, "bits_left=%d\n", bits_left); s_index=0; } else if (bits_left > 0 && (s->err_recognition & AV_EF_BUFFER)) { -- cgit v1.2.3 From afb8b207d6c82bc063ab984b2875074457db2e4f Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Fri, 20 Jan 2012 13:37:00 +0100 Subject: threads: update slice_count and slice_offset from user context They are used to signal the number of slices and offsets of each slice out of band to the decoder. --- libavcodec/pthread.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'libavcodec') diff --git a/libavcodec/pthread.c b/libavcodec/pthread.c index 0688d9d8f0..a4e3081272 100644 --- a/libavcodec/pthread.c +++ b/libavcodec/pthread.c @@ -413,7 +413,6 @@ static int update_context_from_thread(AVCodecContext *dst, AVCodecContext *src, dst->has_b_frames = src->has_b_frames; dst->idct_algo = src->idct_algo; - dst->slice_count = src->slice_count; dst->bits_per_coded_sample = src->bits_per_coded_sample; dst->sample_aspect_ratio = src->sample_aspect_ratio; @@ -447,8 +446,9 @@ static int update_context_from_thread(AVCodecContext *dst, AVCodecContext *src, * * @param dst The destination context. * @param src The source context. + * @return 0 on success, negative error code on failure */ -static void update_context_from_user(AVCodecContext *dst, AVCodecContext *src) +static int update_context_from_user(AVCodecContext *dst, AVCodecContext *src) { #define copy_fields(s, e) memcpy(&dst->s, &src->s, (char*)&dst->e - (char*)&dst->s); dst->flags = src->flags; @@ -469,6 +469,22 @@ static void update_context_from_user(AVCodecContext *dst, AVCodecContext *src) dst->frame_number = src->frame_number; dst->reordered_opaque = src->reordered_opaque; + + if (src->slice_count && src->slice_offset) { + if (dst->slice_count < src->slice_count) { + int *tmp = av_realloc(dst->slice_offset, src->slice_count * + sizeof(*dst->slice_offset)); + if (!tmp) { + av_free(dst->slice_offset); + return AVERROR(ENOMEM); + } + dst->slice_offset = tmp; + } + memcpy(dst->slice_offset, src->slice_offset, + src->slice_count * sizeof(*dst->slice_offset)); + } + dst->slice_count = src->slice_count; + return 0; #undef copy_fields } @@ -579,7 +595,8 @@ int ff_thread_decode_frame(AVCodecContext *avctx, */ p = &fctx->threads[fctx->next_decoding]; - update_context_from_user(p->avctx, avctx); + err = update_context_from_user(p->avctx, avctx); + if (err) return err; err = submit_packet(p, avpkt); if (err) return err; @@ -750,6 +767,7 @@ static void frame_thread_free(AVCodecContext *avctx, int thread_count) if (i) { av_freep(&p->avctx->priv_data); av_freep(&p->avctx->internal); + av_freep(&p->avctx->slice_offset); } av_freep(&p->avctx); -- cgit v1.2.3 From 2473a45c85dce6872617b33fce396dbbd6347e8e Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 18 Jan 2012 10:53:41 +0100 Subject: threads: change the default for threads back to 1 Using threaded decoding by default breaks backward compatibility if AVHWAccel is used or if an appliction sets threadunsafe callbacks. Avconv and avplay still use -threads auto if not specified. --- avconv.c | 4 ++++ avplay.c | 2 ++ libavcodec/options.c | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) (limited to 'libavcodec') diff --git a/avconv.c b/avconv.c index 008cfe0275..46f3090755 100644 --- a/avconv.c +++ b/avconv.c @@ -2210,6 +2210,8 @@ static int init_input_stream(int ist_index, OutputStream *output_streams, int nb ist->st->codec->opaque = ist; } + if (!av_dict_get(ist->opts, "threads", NULL, 0)) + av_dict_set(&ist->opts, "threads", "auto", 0); if (avcodec_open2(ist->st->codec, codec, &ist->opts) < 0) { snprintf(error, error_len, "Error while opening decoder for input stream #%d:%d", ist->file_index, ist->st->index); @@ -2512,6 +2514,8 @@ static int transcode_init(OutputFile *output_files, memcpy(ost->st->codec->subtitle_header, dec->subtitle_header, dec->subtitle_header_size); ost->st->codec->subtitle_header_size = dec->subtitle_header_size; } + if (!av_dict_get(ost->opts, "threads", NULL, 0)) + av_dict_set(&ost->opts, "threads", "auto", 0); if (avcodec_open2(ost->st->codec, codec, &ost->opts) < 0) { snprintf(error, sizeof(error), "Error while opening encoder for output stream #%d:%d - maybe incorrect parameters such as bit_rate, rate, width or height", ost->file_index, ost->index); diff --git a/avplay.c b/avplay.c index 85e03770e5..432afc11b3 100644 --- a/avplay.c +++ b/avplay.c @@ -2194,6 +2194,8 @@ static int stream_component_open(VideoState *is, int stream_index) if (lowres) avctx->flags |= CODEC_FLAG_EMU_EDGE; if (fast) avctx->flags2 |= CODEC_FLAG2_FAST; + if (!av_dict_get(opts, "threads", NULL, 0)) + av_dict_set(&opts, "threads", "auto", 0); if (!codec || avcodec_open2(avctx, codec, &opts) < 0) return -1; diff --git a/libavcodec/options.c b/libavcodec/options.c index 0d41da52ac..2689d32a92 100644 --- a/libavcodec/options.c +++ b/libavcodec/options.c @@ -372,7 +372,7 @@ static const AVOption options[]={ {"float", NULL, 0, AV_OPT_TYPE_CONST, {.dbl = FF_AA_FLOAT }, INT_MIN, INT_MAX, V|D, "aa"}, #endif {"qns", "quantizer noise shaping", OFFSET(quantizer_noise_shaping), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E}, -{"threads", NULL, OFFSET(thread_count), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, V|E|D, "threads"}, +{"threads", NULL, OFFSET(thread_count), AV_OPT_TYPE_INT, {.dbl = 1 }, 0, INT_MAX, V|E|D, "threads"}, {"auto", "detect a good number of threads", 0, AV_OPT_TYPE_CONST, {.dbl = 0 }, INT_MIN, INT_MAX, V|E|D, "threads"}, {"me_threshold", "motion estimaton threshold", OFFSET(me_threshold), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E}, {"mb_threshold", "macroblock threshold", OFFSET(mb_threshold), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E}, -- cgit v1.2.3