diff --git a/libavcodec/cavs.c b/libavcodec/cavs.c index 65e12dd174..21660751b5 100644 --- a/libavcodec/cavs.c +++ b/libavcodec/cavs.c @@ -655,7 +655,9 @@ int ff_cavs_next_mb(AVSContext *h) { * ****************************************************************************/ -void ff_cavs_init_pic(AVSContext *h) { +int ff_cavs_init_pic(AVSContext *h) { + MpegEncContext *s = &h->s; + int ret; int i; /* clear some predictors */ @@ -675,6 +677,14 @@ void ff_cavs_init_pic(AVSContext *h) { h->luma_scan[3] = 8*h->l_stride+8; h->mbx = h->mby = h->mbidx = 0; h->flags = 0; + + if (!s->edge_emu_buffer && + (ret = ff_mpv_frame_size_alloc(s, h->picture.f.linesize[0])) < 0) { + av_log(s->avctx, AV_LOG_ERROR, + "get_buffer() failed to allocate context scratch buffers.\n"); + return ret; + } + return 0; } /***************************************************************************** diff --git a/libavcodec/cavs.h b/libavcodec/cavs.h index 039053dddb..c99ae95ea4 100644 --- a/libavcodec/cavs.h +++ b/libavcodec/cavs.h @@ -253,7 +253,7 @@ void ff_cavs_mv(AVSContext *h, enum cavs_mv_loc nP, enum cavs_mv_loc nC, enum cavs_mv_pred mode, enum cavs_block size, int ref); void ff_cavs_init_mb(AVSContext *h); int ff_cavs_next_mb(AVSContext *h); -void ff_cavs_init_pic(AVSContext *h); +int ff_cavs_init_pic(AVSContext *h); void ff_cavs_init_top_lines(AVSContext *h); int ff_cavs_init(AVCodecContext *avctx); int ff_cavs_end (AVCodecContext *avctx); diff --git a/libavcodec/cavsdec.c b/libavcodec/cavsdec.c index cf86ab4c96..cdcdccbd9c 100644 --- a/libavcodec/cavsdec.c +++ b/libavcodec/cavsdec.c @@ -966,7 +966,8 @@ static int decode_pic(AVSContext *h) { if ((ret = ff_get_buffer(s->avctx, &h->picture.f)) < 0) return ret; - ff_cavs_init_pic(h); + if ((ret = ff_cavs_init_pic(h)) < 0) + return ret; h->picture.poc = get_bits(&s->gb,8)*2; /* get temporal distances and MV scaling factors */ diff --git a/libavcodec/h264.c b/libavcodec/h264.c index c3f600f2a6..3e50ba58e0 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -2300,8 +2300,10 @@ static int field_end(H264Context *h, int in_setup) /** * Replicate H264 "master" context to thread contexts. */ -static void clone_slice(H264Context *dst, H264Context *src) +static int clone_slice(H264Context *dst, H264Context *src) { + int ret; + memcpy(dst->block_offset, src->block_offset, sizeof(dst->block_offset)); dst->s.current_picture_ptr = src->s.current_picture_ptr; dst->s.current_picture = src->s.current_picture; @@ -2309,6 +2311,13 @@ static void clone_slice(H264Context *dst, H264Context *src) dst->s.uvlinesize = src->s.uvlinesize; dst->s.first_field = src->s.first_field; + if (!dst->s.edge_emu_buffer && + (ret = ff_mpv_frame_size_alloc(&dst->s, dst->s.linesize))) { + av_log(dst->s.avctx, AV_LOG_ERROR, + "Failed to allocate scratch buffers\n"); + return ret; + } + dst->prev_poc_msb = src->prev_poc_msb; dst->prev_poc_lsb = src->prev_poc_lsb; dst->prev_frame_num_offset = src->prev_frame_num_offset; @@ -2322,6 +2331,8 @@ static void clone_slice(H264Context *dst, H264Context *src) memcpy(dst->dequant4_coeff, src->dequant4_coeff, sizeof(src->dequant4_coeff)); memcpy(dst->dequant8_coeff, src->dequant8_coeff, sizeof(src->dequant8_coeff)); + + return 0; } /** @@ -2901,8 +2912,8 @@ static int decode_slice_header(H264Context *h, H264Context *h0) ff_release_unused_pictures(s, 0); } } - if (h != h0) - clone_slice(h, h0); + if (h != h0 && (ret = clone_slice(h, h0)) < 0) + return ret; s->current_picture_ptr->frame_num = h->frame_num; // FIXME frame_num cleanup diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c index e32cce07cd..8aa836e7bb 100644 --- a/libavcodec/mpeg12.c +++ b/libavcodec/mpeg12.c @@ -2492,7 +2492,10 @@ static int decode_chunks(AVCodecContext *avctx, thread_context->end_mb_y = s2->mb_height; if (s->slice_count) { s2->thread_context[s->slice_count-1]->end_mb_y = mb_y; - ff_update_duplicate_context(thread_context, s2); + ret = ff_update_duplicate_context(thread_context, + s2); + if (ret < 0) + return ret; } init_get_bits(&thread_context->gb, buf_ptr, input_size*8); s->slice_count++; diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index a3eafe42c7..2d0b8a4ba6 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -232,12 +232,35 @@ static void free_frame_buffer(MpegEncContext *s, Picture *pic) av_freep(&pic->f.hwaccel_picture_private); } +int ff_mpv_frame_size_alloc(MpegEncContext *s, int linesize) +{ + int alloc_size = FFALIGN(FFABS(linesize) + 64, 32); + + // edge emu needs blocksize + filter length - 1 + // (= 17x17 for halfpel / 21x21 for h264) + // linesize * interlaced * MBsize + FF_ALLOCZ_OR_GOTO(s->avctx, s->edge_emu_buffer, alloc_size * 4 * 21, + fail); + + FF_ALLOCZ_OR_GOTO(s->avctx, s->me.scratchpad, alloc_size * 2 * 16 * 2, + fail) + s->me.temp = s->me.scratchpad; + s->rd_scratchpad = s->me.scratchpad; + s->b_scratchpad = s->me.scratchpad; + s->obmc_scratchpad = s->me.scratchpad + 16; + + return 0; +fail: + av_freep(&s->edge_emu_buffer); + return AVERROR(ENOMEM); +} + /** * Allocate a frame buffer */ static int alloc_frame_buffer(MpegEncContext *s, Picture *pic) { - int r; + int r, ret; if (s->avctx->hwaccel) { assert(!pic->f.hwaccel_picture_private); @@ -279,6 +302,14 @@ static int alloc_frame_buffer(MpegEncContext *s, Picture *pic) return -1; } + if (!s->edge_emu_buffer && + (ret = ff_mpv_frame_size_alloc(s, pic->f.linesize[0])) < 0) { + av_log(s->avctx, AV_LOG_ERROR, + "get_buffer() failed to allocate context scratch buffers.\n"); + free_frame_buffer(s, pic); + return ret; + } + return 0; } @@ -416,19 +447,13 @@ static int init_duplicate_context(MpegEncContext *s, MpegEncContext *base) int yc_size = y_size + 2 * c_size; int i; - // edge emu needs blocksize + filter length - 1 - // (= 17x17 for halfpel / 21x21 for h264) - FF_ALLOCZ_OR_GOTO(s->avctx, s->edge_emu_buffer, - (s->width + 95) * 2 * 21 * 4, fail); // (width + edge + align)*interlaced*MBsize*tolerance + s->edge_emu_buffer = + s->me.scratchpad = + s->me.temp = + s->rd_scratchpad = + s->b_scratchpad = + s->obmc_scratchpad = NULL; - // FIXME should be linesize instead of s->width * 2 - // but that is not known before get_buffer() - FF_ALLOCZ_OR_GOTO(s->avctx, s->me.scratchpad, - (s->width + 95) * 4 * 16 * 2 * sizeof(uint8_t), fail) - s->me.temp = s->me.scratchpad; - s->rd_scratchpad = s->me.scratchpad; - s->b_scratchpad = s->me.scratchpad; - s->obmc_scratchpad = s->me.scratchpad + 16; if (s->encoding) { FF_ALLOCZ_OR_GOTO(s->avctx, s->me.map, ME_MAP_SIZE * sizeof(uint32_t), fail) @@ -507,10 +532,10 @@ static void backup_duplicate_context(MpegEncContext *bak, MpegEncContext *src) #undef COPY } -void ff_update_duplicate_context(MpegEncContext *dst, MpegEncContext *src) +int ff_update_duplicate_context(MpegEncContext *dst, MpegEncContext *src) { MpegEncContext bak; - int i; + int i, ret; // FIXME copy only needed parts // START_TIMER backup_duplicate_context(&bak, dst); @@ -519,8 +544,15 @@ void ff_update_duplicate_context(MpegEncContext *dst, MpegEncContext *src) for (i = 0; i < 12; i++) { dst->pblocks[i] = &dst->block[i]; } + if (!dst->edge_emu_buffer && + (ret = ff_mpv_frame_size_alloc(dst, dst->linesize)) < 0) { + av_log(dst->avctx, AV_LOG_ERROR, "failed to allocate context " + "scratch buffers.\n"); + return ret; + } // STOP_TIMER("update_duplicate_context") // about 10k cycles / 0.01 sec for 1000frames on 1ghz with 2 threads + return 0; } int ff_mpeg_update_thread_context(AVCodecContext *dst, @@ -612,6 +644,19 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst, FF_INPUT_BUFFER_PADDING_SIZE); } + // linesize dependend scratch buffer allocation + if (!s->edge_emu_buffer) + if (s1->linesize) { + if (ff_mpv_frame_size_alloc(s, s1->linesize) < 0) { + av_log(s->avctx, AV_LOG_ERROR, "Failed to allocate context " + "scratch buffers.\n"); + return AVERROR(ENOMEM); + } + } else { + av_log(s->avctx, AV_LOG_ERROR, "Context scratch buffers could not " + "be allocated due to unknown size.\n"); + } + // MPEG2/interlacing info memcpy(&s->progressive_sequence, &s1->progressive_sequence, (char *) &s1->rtp_mode - (char *) &s1->progressive_sequence); diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index be23c3e35e..e7607d0c61 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -771,6 +771,7 @@ void ff_MPV_common_defaults(MpegEncContext *s); void ff_MPV_decode_defaults(MpegEncContext *s); int ff_MPV_common_init(MpegEncContext *s); +int ff_mpv_frame_size_alloc(MpegEncContext *s, int linesize); int ff_MPV_common_frame_size_change(MpegEncContext *s); void ff_MPV_common_end(MpegEncContext *s); void ff_MPV_decode_mb(MpegEncContext *s, DCTELEM block[12][64]); @@ -794,7 +795,7 @@ void ff_write_quant_matrix(PutBitContext *pb, uint16_t *matrix); void ff_release_unused_pictures(MpegEncContext *s, int remove_current); int ff_find_unused_picture(MpegEncContext *s, int shared); void ff_denoise_dct(MpegEncContext *s, DCTELEM *block); -void ff_update_duplicate_context(MpegEncContext *dst, MpegEncContext *src); +int ff_update_duplicate_context(MpegEncContext *dst, MpegEncContext *src); int ff_MPV_lowest_referenced_row(MpegEncContext *s, int dir); void ff_MPV_report_decode_progress(MpegEncContext *s); int ff_mpeg_update_thread_context(AVCodecContext *dst, const AVCodecContext *src); diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index aff12c6f8e..45e8c77d8a 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -3228,7 +3228,7 @@ static void set_frame_distances(MpegEncContext * s){ static int encode_picture(MpegEncContext *s, int picture_number) { - int i; + int i, ret; int bits; int context_count = s->slice_context_count; @@ -3278,7 +3278,9 @@ static int encode_picture(MpegEncContext *s, int picture_number) s->mb_intra=0; //for the rate distortion & bit compare functions for(i=1; ithread_context[i], s); + ret = ff_update_duplicate_context(s->thread_context[i], s); + if (ret < 0) + return ret; } if(ff_init_me(s)<0)