X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fmpegvideo.c;h=08d4cbbf8f11376b79012781abbfc451cd66506d;hb=09031b4639667273354d6bcd1705d9f24fc9bdd4;hp=d1c42331c2e6bffe44e5d0d60802f262bfa8ba57;hpb=2bcbd98459915baefc15043d02f4a942ebcd33da;p=ffmpeg diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index d1c42331c2e..08d4cbbf8f1 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -27,16 +27,14 @@ * The simplest mpeg encoder (well, it was the simplest!). */ -#include "libavutil/intmath.h" #include "libavutil/imgutils.h" #include "avcodec.h" #include "dsputil.h" #include "internal.h" +#include "mathops.h" #include "mpegvideo.h" -#include "mpegvideo_common.h" #include "mjpegenc.h" #include "msmpeg4.h" -#include "faandct.h" #include "xvmc_internal.h" #include "thread.h" #include @@ -45,19 +43,19 @@ //#include static void dct_unquantize_mpeg1_intra_c(MpegEncContext *s, - DCTELEM *block, int n, int qscale); + int16_t *block, int n, int qscale); static void dct_unquantize_mpeg1_inter_c(MpegEncContext *s, - DCTELEM *block, int n, int qscale); + int16_t *block, int n, int qscale); static void dct_unquantize_mpeg2_intra_c(MpegEncContext *s, - DCTELEM *block, int n, int qscale); + int16_t *block, int n, int qscale); static void dct_unquantize_mpeg2_intra_bitexact(MpegEncContext *s, - DCTELEM *block, int n, int qscale); + int16_t *block, int n, int qscale); static void dct_unquantize_mpeg2_inter_c(MpegEncContext *s, - DCTELEM *block, int n, int qscale); + int16_t *block, int n, int qscale); static void dct_unquantize_h263_intra_c(MpegEncContext *s, - DCTELEM *block, int n, int qscale); + int16_t *block, int n, int qscale); static void dct_unquantize_h263_inter_c(MpegEncContext *s, - DCTELEM *block, int n, int qscale); + int16_t *block, int n, int qscale); /* enable all paranoid tests for rounding, overflows, etc... */ @@ -127,19 +125,55 @@ const uint8_t *const ff_mpeg2_dc_scale_table[4] = { mpeg2_dc_scale_table3, }; -const enum PixelFormat ff_pixfmt_list_420[] = { - PIX_FMT_YUV420P, - PIX_FMT_NONE +const enum AVPixelFormat ff_pixfmt_list_420[] = { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE }; -const enum PixelFormat ff_hwaccel_pixfmt_list_420[] = { - PIX_FMT_DXVA2_VLD, - PIX_FMT_VAAPI_VLD, - PIX_FMT_VDA_VLD, - PIX_FMT_YUV420P, - PIX_FMT_NONE +const enum AVPixelFormat ff_hwaccel_pixfmt_list_420[] = { +#if CONFIG_DXVA2 + AV_PIX_FMT_DXVA2_VLD, +#endif +#if CONFIG_VAAPI + AV_PIX_FMT_VAAPI_VLD, +#endif +#if CONFIG_VDA + AV_PIX_FMT_VDA_VLD, +#endif +#if CONFIG_VDPAU + AV_PIX_FMT_VDPAU, +#endif + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE }; +static void mpeg_er_decode_mb(void *opaque, int ref, int mv_dir, int mv_type, + int (*mv)[2][4][2], + int mb_x, int mb_y, int mb_intra, int mb_skipped) +{ + MpegEncContext *s = opaque; + + s->mv_dir = mv_dir; + s->mv_type = mv_type; + s->mb_intra = mb_intra; + s->mb_skipped = mb_skipped; + s->mb_x = mb_x; + s->mb_y = mb_y; + memcpy(s->mv, mv, sizeof(*mv)); + + ff_init_block_index(s); + ff_update_block_index(s); + + s->dsp.clear_blocks(s->block[0]); + + s->dest[0] = s->current_picture.f.data[0] + (s->mb_y * 16 * s->linesize) + s->mb_x * 16; + s->dest[1] = s->current_picture.f.data[1] + (s->mb_y * (16 >> s->chroma_y_shift) * s->uvlinesize) + s->mb_x * (16 >> s->chroma_x_shift); + s->dest[2] = s->current_picture.f.data[2] + (s->mb_y * (16 >> s->chroma_y_shift) * s->uvlinesize) + s->mb_x * (16 >> s->chroma_x_shift); + + assert(ref == 0); + ff_MPV_decode_mb(s, s->block); +} + const uint8_t *avpriv_mpv_find_start_code(const uint8_t *restrict p, const uint8_t *end, uint32_t * restrict state) @@ -177,6 +211,7 @@ const uint8_t *avpriv_mpv_find_start_code(const uint8_t *restrict p, av_cold int ff_dct_common_init(MpegEncContext *s) { ff_dsputil_init(&s->dsp, s->avctx); + ff_videodsp_init(&s->vdsp, s->avctx->bits_per_raw_sample); s->dct_unquantize_h263_intra = dct_unquantize_h263_intra_c; s->dct_unquantize_h263_inter = dct_unquantize_h263_inter_c; @@ -187,12 +222,10 @@ av_cold int ff_dct_common_init(MpegEncContext *s) s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_bitexact; s->dct_unquantize_mpeg2_inter = dct_unquantize_mpeg2_inter_c; -#if HAVE_MMX - ff_MPV_common_init_mmx(s); +#if ARCH_X86 + ff_MPV_common_init_x86(s); #elif ARCH_ALPHA ff_MPV_common_init_axp(s); -#elif HAVE_MMI - ff_MPV_common_init_mmi(s); #elif ARCH_ARM ff_MPV_common_init_arm(s); #elif HAVE_ALTIVEC @@ -228,22 +261,48 @@ void ff_copy_picture(Picture *dst, Picture *src) */ static void free_frame_buffer(MpegEncContext *s, Picture *pic) { - /* Windows Media Image codecs allocate internal buffers with different - * dimensions; ignore user defined callbacks for these - */ - if (s->codec_id != CODEC_ID_WMV3IMAGE && s->codec_id != CODEC_ID_VC1IMAGE) + /* WM Image / Screen codecs allocate internal buffers with different + * dimensions / colorspaces; ignore user-defined callbacks for these. */ + if (s->codec_id != AV_CODEC_ID_WMV3IMAGE && + s->codec_id != AV_CODEC_ID_VC1IMAGE && + s->codec_id != AV_CODEC_ID_MSS2) ff_thread_release_buffer(s->avctx, &pic->f); else avcodec_default_release_buffer(s->avctx, &pic->f); av_freep(&pic->f.hwaccel_picture_private); } +int ff_mpv_frame_size_alloc(MpegEncContext *s, int linesize) +{ + int alloc_size = FFALIGN(FFABS(linesize) + 32, 32); + + // edge emu needs blocksize + filter length - 1 + // (= 17x17 for halfpel / 21x21 for h264) + // VC1 computes luma and chroma simultaneously and needs 19X19 + 9x9 + // at uvlinesize. It supports only YUV420 so 24x24 is enough + // linesize * interlaced * MBsize + FF_ALLOCZ_OR_GOTO(s->avctx, s->edge_emu_buffer, alloc_size * 2 * 24, + 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); @@ -256,7 +315,9 @@ static int alloc_frame_buffer(MpegEncContext *s, Picture *pic) } } - if (s->codec_id != CODEC_ID_WMV3IMAGE && s->codec_id != CODEC_ID_VC1IMAGE) + if (s->codec_id != AV_CODEC_ID_WMV3IMAGE && + s->codec_id != AV_CODEC_ID_VC1IMAGE && + s->codec_id != AV_CODEC_ID_MSS2) r = ff_thread_get_buffer(s->avctx, &pic->f); else r = avcodec_default_get_buffer(s->avctx, &pic->f); @@ -283,6 +344,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; } @@ -360,7 +429,7 @@ int ff_alloc_picture(MpegEncContext *s, Picture *pic, int shared) } if (s->avctx->debug&FF_DEBUG_DCT_COEFF) { FF_ALLOCZ_OR_GOTO(s->avctx, pic->f.dct_coeff, - 64 * mb_array_size * sizeof(DCTELEM) * 6, fail) + 64 * mb_array_size * sizeof(int16_t) * 6, fail) } pic->f.qstride = s->mb_stride; FF_ALLOCZ_OR_GOTO(s->avctx, pic->f.pan_scan, @@ -392,13 +461,16 @@ static void free_picture(MpegEncContext *s, Picture *pic) av_freep(&pic->mb_mean); av_freep(&pic->f.mbskip_table); av_freep(&pic->qscale_table_base); + pic->f.qscale_table = NULL; av_freep(&pic->mb_type_base); + pic->f.mb_type = NULL; av_freep(&pic->f.dct_coeff); av_freep(&pic->f.pan_scan); pic->f.mb_type = NULL; for (i = 0; i < 2; i++) { av_freep(&pic->motion_val_base[i]); av_freep(&pic->f.ref_index[i]); + pic->f.motion_val[i] = NULL; } if (pic->f.type == FF_BUFFER_TYPE_SHARED) { @@ -410,26 +482,20 @@ static void free_picture(MpegEncContext *s, Picture *pic) } } -static int init_duplicate_context(MpegEncContext *s, MpegEncContext *base) +static int init_duplicate_context(MpegEncContext *s) { int y_size = s->b8_stride * (2 * s->mb_height + 1); int c_size = s->mb_stride * (s->mb_height + 1); 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 + 64) * 2 * 21 * 2, 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 + 64) * 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) @@ -440,7 +506,7 @@ static int init_duplicate_context(MpegEncContext *s, MpegEncContext *base) 2 * 64 * sizeof(int), fail) } } - FF_ALLOCZ_OR_GOTO(s->avctx, s->blocks, 64 * 12 * 2 * sizeof(DCTELEM), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->blocks, 64 * 12 * 2 * sizeof(int16_t), fail) s->block = s->blocks[0]; for (i = 0; i < 12; i++) { @@ -508,10 +574,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); @@ -520,13 +586,21 @@ 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, const AVCodecContext *src) { + int i; MpegEncContext *s = dst->priv_data, *s1 = src->priv_data; if (dst == src || !s1->context_initialized) @@ -546,6 +620,15 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst, ff_MPV_common_init(s); } + if (s->height != s1->height || s->width != s1->width || s->context_reinit) { + int err; + s->context_reinit = 0; + s->height = s1->height; + s->width = s1->width; + if ((err = ff_MPV_common_frame_size_change(s)) < 0) + return err; + } + s->avctx->coded_height = s1->avctx->coded_height; s->avctx->coded_width = s1->avctx->coded_width; s->avctx->width = s1->avctx->width; @@ -559,6 +642,10 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst, memcpy(&s->last_picture, &s1->last_picture, (char *) &s1->last_picture_ptr - (char *) &s1->last_picture); + // reset s->picture[].f.extended_data to s->picture[].f.data + for (i = 0; i < s->picture_count; i++) + s->picture[i].f.extended_data = s->picture[i].f.data; + s->last_picture_ptr = REBASE_PICTURE(s1->last_picture_ptr, s, s1); s->current_picture_ptr = REBASE_PICTURE(s1->current_picture_ptr, s, s1); s->next_picture_ptr = REBASE_PICTURE(s1->next_picture_ptr, s, s1); @@ -574,7 +661,7 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst, // B-frame info s->max_b_frames = s1->max_b_frames; s->low_delay = s1->low_delay; - s->dropable = s1->dropable; + s->droppable = s1->droppable; // DivX handling (doesn't work) s->divx_packed = s1->divx_packed; @@ -592,6 +679,20 @@ 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"); + return AVERROR_BUG; + } + // MPEG2/interlacing info memcpy(&s->progressive_sequence, &s1->progressive_sequence, (char *) &s1->rtp_mode - (char *) &s1->progressive_sequence); @@ -649,13 +750,200 @@ void ff_MPV_decode_defaults(MpegEncContext *s) ff_MPV_common_defaults(s); } +static int init_er(MpegEncContext *s) +{ + ERContext *er = &s->er; + int mb_array_size = s->mb_height * s->mb_stride; + int i; + + er->avctx = s->avctx; + er->dsp = &s->dsp; + + er->mb_index2xy = s->mb_index2xy; + er->mb_num = s->mb_num; + er->mb_width = s->mb_width; + er->mb_height = s->mb_height; + er->mb_stride = s->mb_stride; + er->b8_stride = s->b8_stride; + + er->er_temp_buffer = av_malloc(s->mb_height * s->mb_stride); + er->error_status_table = av_mallocz(mb_array_size); + if (!er->er_temp_buffer || !er->error_status_table) + goto fail; + + er->mbskip_table = s->mbskip_table; + er->mbintra_table = s->mbintra_table; + + for (i = 0; i < FF_ARRAY_ELEMS(s->dc_val); i++) + er->dc_val[i] = s->dc_val[i]; + + er->decode_mb = mpeg_er_decode_mb; + er->opaque = s; + + return 0; +fail: + av_freep(&er->er_temp_buffer); + av_freep(&er->error_status_table); + return AVERROR(ENOMEM); +} + +/** + * Initialize and allocates MpegEncContext fields dependent on the resolution. + */ +static int init_context_frame(MpegEncContext *s) +{ + int y_size, c_size, yc_size, i, mb_array_size, mv_table_size, x, y; + + s->mb_width = (s->width + 15) / 16; + s->mb_stride = s->mb_width + 1; + s->b8_stride = s->mb_width * 2 + 1; + s->b4_stride = s->mb_width * 4 + 1; + mb_array_size = s->mb_height * s->mb_stride; + mv_table_size = (s->mb_height + 2) * s->mb_stride + 1; + + /* set default edge pos, will be overriden + * in decode_header if needed */ + s->h_edge_pos = s->mb_width * 16; + s->v_edge_pos = s->mb_height * 16; + + s->mb_num = s->mb_width * s->mb_height; + + s->block_wrap[0] = + s->block_wrap[1] = + s->block_wrap[2] = + s->block_wrap[3] = s->b8_stride; + s->block_wrap[4] = + s->block_wrap[5] = s->mb_stride; + + y_size = s->b8_stride * (2 * s->mb_height + 1); + c_size = s->mb_stride * (s->mb_height + 1); + yc_size = y_size + 2 * c_size; + + FF_ALLOCZ_OR_GOTO(s->avctx, s->mb_index2xy, (s->mb_num + 1) * sizeof(int), + fail); // error ressilience code looks cleaner with this + for (y = 0; y < s->mb_height; y++) + for (x = 0; x < s->mb_width; x++) + s->mb_index2xy[x + y * s->mb_width] = x + y * s->mb_stride; + + s->mb_index2xy[s->mb_height * s->mb_width] = + (s->mb_height - 1) * s->mb_stride + s->mb_width; // FIXME really needed? + + if (s->encoding) { + /* Allocate MV tables */ + FF_ALLOCZ_OR_GOTO(s->avctx, s->p_mv_table_base, + mv_table_size * 2 * sizeof(int16_t), fail); + FF_ALLOCZ_OR_GOTO(s->avctx, s->b_forw_mv_table_base, + mv_table_size * 2 * sizeof(int16_t), fail); + FF_ALLOCZ_OR_GOTO(s->avctx, s->b_back_mv_table_base, + mv_table_size * 2 * sizeof(int16_t), fail); + FF_ALLOCZ_OR_GOTO(s->avctx, s->b_bidir_forw_mv_table_base, + mv_table_size * 2 * sizeof(int16_t), fail); + FF_ALLOCZ_OR_GOTO(s->avctx, s->b_bidir_back_mv_table_base, + mv_table_size * 2 * sizeof(int16_t), fail); + FF_ALLOCZ_OR_GOTO(s->avctx, s->b_direct_mv_table_base, + mv_table_size * 2 * sizeof(int16_t), fail); + s->p_mv_table = s->p_mv_table_base + s->mb_stride + 1; + s->b_forw_mv_table = s->b_forw_mv_table_base + s->mb_stride + 1; + s->b_back_mv_table = s->b_back_mv_table_base + s->mb_stride + 1; + s->b_bidir_forw_mv_table = s->b_bidir_forw_mv_table_base + + s->mb_stride + 1; + s->b_bidir_back_mv_table = s->b_bidir_back_mv_table_base + + s->mb_stride + 1; + s->b_direct_mv_table = s->b_direct_mv_table_base + s->mb_stride + 1; + + /* Allocate MB type table */ + FF_ALLOCZ_OR_GOTO(s->avctx, s->mb_type, mb_array_size * + sizeof(uint16_t), fail); // needed for encoding + + FF_ALLOCZ_OR_GOTO(s->avctx, s->lambda_table, mb_array_size * + sizeof(int), fail); + + FF_ALLOC_OR_GOTO(s->avctx, s->cplx_tab, + mb_array_size * sizeof(float), fail); + FF_ALLOC_OR_GOTO(s->avctx, s->bits_tab, + mb_array_size * sizeof(float), fail); + + } + + if (s->codec_id == AV_CODEC_ID_MPEG4 || + (s->flags & CODEC_FLAG_INTERLACED_ME)) { + /* interlaced direct mode decoding tables */ + for (i = 0; i < 2; i++) { + int j, k; + for (j = 0; j < 2; j++) { + for (k = 0; k < 2; k++) { + FF_ALLOCZ_OR_GOTO(s->avctx, + s->b_field_mv_table_base[i][j][k], + mv_table_size * 2 * sizeof(int16_t), + fail); + s->b_field_mv_table[i][j][k] = s->b_field_mv_table_base[i][j][k] + + s->mb_stride + 1; + } + FF_ALLOCZ_OR_GOTO(s->avctx, s->b_field_select_table [i][j], + mb_array_size * 2 * sizeof(uint8_t), fail); + FF_ALLOCZ_OR_GOTO(s->avctx, s->p_field_mv_table_base[i][j], + mv_table_size * 2 * sizeof(int16_t), fail); + s->p_field_mv_table[i][j] = s->p_field_mv_table_base[i][j] + + s->mb_stride + 1; + } + FF_ALLOCZ_OR_GOTO(s->avctx, s->p_field_select_table[i], + mb_array_size * 2 * sizeof(uint8_t), fail); + } + } + if (s->out_format == FMT_H263) { + /* cbp values */ + FF_ALLOCZ_OR_GOTO(s->avctx, s->coded_block_base, y_size, fail); + s->coded_block = s->coded_block_base + s->b8_stride + 1; + + /* cbp, ac_pred, pred_dir */ + FF_ALLOCZ_OR_GOTO(s->avctx, s->cbp_table, + mb_array_size * sizeof(uint8_t), fail); + FF_ALLOCZ_OR_GOTO(s->avctx, s->pred_dir_table, + mb_array_size * sizeof(uint8_t), fail); + } + + if (s->h263_pred || s->h263_plus || !s->encoding) { + /* dc values */ + // MN: we need these for error resilience of intra-frames + FF_ALLOCZ_OR_GOTO(s->avctx, s->dc_val_base, + yc_size * sizeof(int16_t), fail); + s->dc_val[0] = s->dc_val_base + s->b8_stride + 1; + s->dc_val[1] = s->dc_val_base + y_size + s->mb_stride + 1; + s->dc_val[2] = s->dc_val[1] + c_size; + for (i = 0; i < yc_size; i++) + s->dc_val_base[i] = 1024; + } + + /* which mb is a intra block */ + FF_ALLOCZ_OR_GOTO(s->avctx, s->mbintra_table, mb_array_size, fail); + memset(s->mbintra_table, 1, mb_array_size); + + /* init macroblock skip table */ + FF_ALLOCZ_OR_GOTO(s->avctx, s->mbskip_table, mb_array_size + 2, fail); + // Note the + 1 is for a quicker mpeg4 slice_end detection + + if ((s->avctx->debug & (FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE)) || + s->avctx->debug_mv) { + s->visualization_buffer[0] = av_malloc((s->mb_width * 16 + + 2 * EDGE_WIDTH) * s->mb_height * 16 + 2 * EDGE_WIDTH); + s->visualization_buffer[1] = av_malloc((s->mb_width * 16 + + 2 * EDGE_WIDTH) * s->mb_height * 16 + 2 * EDGE_WIDTH); + s->visualization_buffer[2] = av_malloc((s->mb_width * 16 + + 2 * EDGE_WIDTH) * s->mb_height * 16 + 2 * EDGE_WIDTH); + } + + return init_er(s); +fail: + return AVERROR(ENOMEM); +} + /** * init common structure for both encoder and decoder. * this assumes that some variables like width/height are already set */ av_cold int ff_MPV_common_init(MpegEncContext *s) { - int y_size, c_size, yc_size, i, mb_array_size, mv_table_size, x, y; + int i; int nb_slices = (HAVE_THREADS && s->avctx->active_thread_type & FF_THREAD_SLICE) ? s->avctx->thread_count : 1; @@ -663,14 +951,14 @@ av_cold int ff_MPV_common_init(MpegEncContext *s) if (s->encoding && s->avctx->slices) nb_slices = s->avctx->slices; - if (s->codec_id == CODEC_ID_MPEG2VIDEO && !s->progressive_sequence) + if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO && !s->progressive_sequence) s->mb_height = (s->height + 31) / 32 * 2; - else if (s->codec_id != CODEC_ID_H264) + else if (s->codec_id != AV_CODEC_ID_H264) s->mb_height = (s->height + 15) / 16; - if (s->avctx->pix_fmt == PIX_FMT_NONE) { + if (s->avctx->pix_fmt == AV_PIX_FMT_NONE) { av_log(s->avctx, AV_LOG_ERROR, - "decoding to PIX_FMT_NONE is not supported.\n"); + "decoding to AV_PIX_FMT_NONE is not supported.\n"); return -1; } @@ -695,34 +983,10 @@ av_cold int ff_MPV_common_init(MpegEncContext *s) s->flags2 = s->avctx->flags2; if (s->width && s->height) { - s->mb_width = (s->width + 15) / 16; - s->mb_stride = s->mb_width + 1; - s->b8_stride = s->mb_width * 2 + 1; - s->b4_stride = s->mb_width * 4 + 1; - mb_array_size = s->mb_height * s->mb_stride; - mv_table_size = (s->mb_height + 2) * s->mb_stride + 1; - /* set chroma shifts */ - avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &s->chroma_x_shift, - &s->chroma_y_shift); - - /* set default edge pos, will be overriden - * in decode_header if needed */ - s->h_edge_pos = s->mb_width * 16; - s->v_edge_pos = s->mb_height * 16; - - s->mb_num = s->mb_width * s->mb_height; - - s->block_wrap[0] = - s->block_wrap[1] = - s->block_wrap[2] = - s->block_wrap[3] = s->b8_stride; - s->block_wrap[4] = - s->block_wrap[5] = s->mb_stride; - - y_size = s->b8_stride * (2 * s->mb_height + 1); - c_size = s->mb_stride * (s->mb_height + 1); - yc_size = y_size + 2 * c_size; + av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt, + &s->chroma_x_shift, + &s->chroma_y_shift); /* convert fourcc to upper case */ s->codec_tag = avpriv_toupper4(s->avctx->codec_tag); @@ -731,42 +995,7 @@ av_cold int ff_MPV_common_init(MpegEncContext *s) s->avctx->coded_frame = &s->current_picture.f; - FF_ALLOCZ_OR_GOTO(s->avctx, s->mb_index2xy, (s->mb_num + 1) * sizeof(int), - fail); // error ressilience code looks cleaner with this - for (y = 0; y < s->mb_height; y++) - for (x = 0; x < s->mb_width; x++) - s->mb_index2xy[x + y * s->mb_width] = x + y * s->mb_stride; - - s->mb_index2xy[s->mb_height * s->mb_width] = - (s->mb_height - 1) * s->mb_stride + s->mb_width; // FIXME really needed? - if (s->encoding) { - /* Allocate MV tables */ - FF_ALLOCZ_OR_GOTO(s->avctx, s->p_mv_table_base, - mv_table_size * 2 * sizeof(int16_t), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->b_forw_mv_table_base, - mv_table_size * 2 * sizeof(int16_t), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->b_back_mv_table_base, - mv_table_size * 2 * sizeof(int16_t), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->b_bidir_forw_mv_table_base, - mv_table_size * 2 * sizeof(int16_t), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->b_bidir_back_mv_table_base, - mv_table_size * 2 * sizeof(int16_t), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->b_direct_mv_table_base, - mv_table_size * 2 * sizeof(int16_t), fail); - s->p_mv_table = s->p_mv_table_base + - s->mb_stride + 1; - s->b_forw_mv_table = s->b_forw_mv_table_base + - s->mb_stride + 1; - s->b_back_mv_table = s->b_back_mv_table_base + - s->mb_stride + 1; - s->b_bidir_forw_mv_table = s->b_bidir_forw_mv_table_base + - s->mb_stride + 1; - s->b_bidir_back_mv_table = s->b_bidir_back_mv_table_base + - s->mb_stride + 1; - s->b_direct_mv_table = s->b_direct_mv_table_base + - s->mb_stride + 1; - if (s->msmpeg4_version) { FF_ALLOCZ_OR_GOTO(s->avctx, s->ac_stats, 2 * 2 * (MAX_LEVEL + 1) * @@ -774,13 +1003,6 @@ av_cold int ff_MPV_common_init(MpegEncContext *s) } FF_ALLOCZ_OR_GOTO(s->avctx, s->avctx->stats_out, 256, fail); - /* Allocate MB type table */ - FF_ALLOCZ_OR_GOTO(s->avctx, s->mb_type, mb_array_size * - sizeof(uint16_t), fail); // needed for encoding - - FF_ALLOCZ_OR_GOTO(s->avctx, s->lambda_table, mb_array_size * - sizeof(int), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->q_intra_matrix, 64 * 32 * sizeof(int), fail); FF_ALLOCZ_OR_GOTO(s->avctx, s->q_inter_matrix, @@ -809,79 +1031,10 @@ av_cold int ff_MPV_common_init(MpegEncContext *s) } if (s->width && s->height) { - FF_ALLOCZ_OR_GOTO(s->avctx, s->error_status_table, - mb_array_size * sizeof(uint8_t), fail); - - if (s->codec_id == CODEC_ID_MPEG4 || - (s->flags & CODEC_FLAG_INTERLACED_ME)) { - /* interlaced direct mode decoding tables */ - for (i = 0; i < 2; i++) { - int j, k; - for (j = 0; j < 2; j++) { - for (k = 0; k < 2; k++) { - FF_ALLOCZ_OR_GOTO(s->avctx, - s->b_field_mv_table_base[i][j][k], - mv_table_size * 2 * sizeof(int16_t), - fail); - s->b_field_mv_table[i][j][k] = s->b_field_mv_table_base[i][j][k] + - s->mb_stride + 1; - } - FF_ALLOCZ_OR_GOTO(s->avctx, s->b_field_select_table [i][j], - mb_array_size * 2 * sizeof(uint8_t), - fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->p_field_mv_table_base[i][j], - mv_table_size * 2 * sizeof(int16_t), - fail); - s->p_field_mv_table[i][j] = s->p_field_mv_table_base[i][j] - + s->mb_stride + 1; - } - FF_ALLOCZ_OR_GOTO(s->avctx, s->p_field_select_table[i], - mb_array_size * 2 * sizeof(uint8_t), - fail); - } - } - if (s->out_format == FMT_H263) { - /* cbp values */ - FF_ALLOCZ_OR_GOTO(s->avctx, s->coded_block_base, y_size, fail); - s->coded_block = s->coded_block_base + s->b8_stride + 1; - - /* cbp, ac_pred, pred_dir */ - FF_ALLOCZ_OR_GOTO(s->avctx, s->cbp_table, - mb_array_size * sizeof(uint8_t), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->pred_dir_table, - mb_array_size * sizeof(uint8_t), fail); - } - - if (s->h263_pred || s->h263_plus || !s->encoding) { - /* dc values */ - // MN: we need these for error resilience of intra-frames - FF_ALLOCZ_OR_GOTO(s->avctx, s->dc_val_base, - yc_size * sizeof(int16_t), fail); - s->dc_val[0] = s->dc_val_base + s->b8_stride + 1; - s->dc_val[1] = s->dc_val_base + y_size + s->mb_stride + 1; - s->dc_val[2] = s->dc_val[1] + c_size; - for (i = 0; i < yc_size; i++) - s->dc_val_base[i] = 1024; - } - - /* which mb is a intra block */ - FF_ALLOCZ_OR_GOTO(s->avctx, s->mbintra_table, mb_array_size, fail); - memset(s->mbintra_table, 1, mb_array_size); - - /* init macroblock skip table */ - FF_ALLOCZ_OR_GOTO(s->avctx, s->mbskip_table, mb_array_size + 2, fail); - // Note the + 1 is for a quicker mpeg4 slice_end detection + if (init_context_frame(s)) + goto fail; s->parse_context.state = -1; - if ((s->avctx->debug & (FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE)) || - s->avctx->debug_mv) { - s->visualization_buffer[0] = av_malloc((s->mb_width * 16 + - 2 * EDGE_WIDTH) * s->mb_height * 16 + 2 * EDGE_WIDTH); - s->visualization_buffer[1] = av_malloc((s->mb_width * 16 + - 2 * EDGE_WIDTH) * s->mb_height * 16 + 2 * EDGE_WIDTH); - s->visualization_buffer[2] = av_malloc((s->mb_width * 16 + - 2 * EDGE_WIDTH) * s->mb_height * 16 + 2 * EDGE_WIDTH); - } } s->context_initialized = 1; @@ -895,7 +1048,7 @@ av_cold int ff_MPV_common_init(MpegEncContext *s) } for (i = 0; i < nb_slices; i++) { - if (init_duplicate_context(s->thread_context[i], s) < 0) + if (init_duplicate_context(s->thread_context[i]) < 0) goto fail; s->thread_context[i]->start_mb_y = (s->mb_height * (i) + nb_slices / 2) / nb_slices; @@ -903,7 +1056,7 @@ av_cold int ff_MPV_common_init(MpegEncContext *s) (s->mb_height * (i + 1) + nb_slices / 2) / nb_slices; } } else { - if (init_duplicate_context(s, s) < 0) + if (init_duplicate_context(s) < 0) goto fail; s->start_mb_y = 0; s->end_mb_y = s->mb_height; @@ -917,24 +1070,15 @@ av_cold int ff_MPV_common_init(MpegEncContext *s) return -1; } -/* init common structure for both encoder and decoder */ -void ff_MPV_common_end(MpegEncContext *s) +/** + * Frees and resets MpegEncContext fields depending on the resolution. + * Is used during resolution changes to avoid a full reinitialization of the + * codec. + */ +static int free_context_frame(MpegEncContext *s) { int i, j, k; - if (s->slice_context_count > 1) { - for (i = 0; i < s->slice_context_count; i++) { - free_duplicate_context(s->thread_context[i]); - } - for (i = 1; i < s->slice_context_count; i++) { - av_freep(&s->thread_context[i]); - } - s->slice_context_count = 1; - } else free_duplicate_context(s); - - av_freep(&s->parse_context.buffer); - s->parse_context.buffer_size = 0; - av_freep(&s->mb_type); av_freep(&s->p_mv_table_base); av_freep(&s->b_forw_mv_table_base); @@ -968,14 +1112,117 @@ void ff_MPV_common_end(MpegEncContext *s) av_freep(&s->pred_dir_table); av_freep(&s->mbskip_table); + + av_freep(&s->er.error_status_table); + av_freep(&s->er.er_temp_buffer); + av_freep(&s->mb_index2xy); + av_freep(&s->lambda_table); + av_freep(&s->cplx_tab); + av_freep(&s->bits_tab); + + s->linesize = s->uvlinesize = 0; + + for (i = 0; i < 3; i++) + av_freep(&s->visualization_buffer[i]); + + return 0; +} + +int ff_MPV_common_frame_size_change(MpegEncContext *s) +{ + int i, err = 0; + + if (s->slice_context_count > 1) { + for (i = 0; i < s->slice_context_count; i++) { + free_duplicate_context(s->thread_context[i]); + } + for (i = 1; i < s->slice_context_count; i++) { + av_freep(&s->thread_context[i]); + } + } else + free_duplicate_context(s); + + free_context_frame(s); + + if (s->picture) + for (i = 0; i < s->picture_count; i++) { + s->picture[i].needs_realloc = 1; + } + + s->last_picture_ptr = + s->next_picture_ptr = + s->current_picture_ptr = NULL; + + // init + if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO && !s->progressive_sequence) + s->mb_height = (s->height + 31) / 32 * 2; + else if (s->codec_id != AV_CODEC_ID_H264) + s->mb_height = (s->height + 15) / 16; + + if ((s->width || s->height) && + av_image_check_size(s->width, s->height, 0, s->avctx)) + return AVERROR_INVALIDDATA; + + if ((err = init_context_frame(s))) + goto fail; + + s->thread_context[0] = s; + + if (s->width && s->height) { + int nb_slices = s->slice_context_count; + if (nb_slices > 1) { + for (i = 1; i < nb_slices; i++) { + s->thread_context[i] = av_malloc(sizeof(MpegEncContext)); + memcpy(s->thread_context[i], s, sizeof(MpegEncContext)); + } + + for (i = 0; i < nb_slices; i++) { + if (init_duplicate_context(s->thread_context[i]) < 0) + goto fail; + s->thread_context[i]->start_mb_y = + (s->mb_height * (i) + nb_slices / 2) / nb_slices; + s->thread_context[i]->end_mb_y = + (s->mb_height * (i + 1) + nb_slices / 2) / nb_slices; + } + } else { + if (init_duplicate_context(s) < 0) + goto fail; + s->start_mb_y = 0; + s->end_mb_y = s->mb_height; + } + s->slice_context_count = nb_slices; + } + + return 0; + fail: + ff_MPV_common_end(s); + return err; +} + +/* init common structure for both encoder and decoder */ +void ff_MPV_common_end(MpegEncContext *s) +{ + int i; + + if (s->slice_context_count > 1) { + for (i = 0; i < s->slice_context_count; i++) { + free_duplicate_context(s->thread_context[i]); + } + for (i = 1; i < s->slice_context_count; i++) { + av_freep(&s->thread_context[i]); + } + s->slice_context_count = 1; + } else free_duplicate_context(s); + + av_freep(&s->parse_context.buffer); + s->parse_context.buffer_size = 0; + av_freep(&s->bitstream_buffer); s->allocated_bitstream_buffer_size = 0; av_freep(&s->avctx->stats_out); av_freep(&s->ac_stats); - av_freep(&s->error_status_table); - av_freep(&s->mb_index2xy); - av_freep(&s->lambda_table); + av_freep(&s->q_intra_matrix); av_freep(&s->q_inter_matrix); av_freep(&s->q_intra_matrix16); @@ -990,17 +1237,17 @@ void ff_MPV_common_end(MpegEncContext *s) } } av_freep(&s->picture); + + free_context_frame(s); + + if (!(s->avctx->active_thread_type & FF_THREAD_FRAME)) + avcodec_default_free_buffers(s->avctx); + s->context_initialized = 0; s->last_picture_ptr = s->next_picture_ptr = s->current_picture_ptr = NULL; s->linesize = s->uvlinesize = 0; - - for (i = 0; i < 3; i++) - av_freep(&s->visualization_buffer[i]); - - if (!(s->avctx->active_thread_type & FF_THREAD_FRAME)) - avcodec_default_free_buffers(s->avctx); } void ff_init_rl(RLTable *rl, @@ -1110,7 +1357,17 @@ void ff_release_unused_pictures(MpegEncContext*s, int remove_current) } } -int ff_find_unused_picture(MpegEncContext *s, int shared) +static inline int pic_is_unused(MpegEncContext *s, Picture *pic) +{ + if (pic->f.data[0] == NULL) + return 1; + if (pic->needs_realloc && !(pic->f.reference & DELAYED_PIC_REF)) + if (!pic->owner2 || pic->owner2 == s) + return 1; + return 0; +} + +static int find_unused_picture(MpegEncContext *s, int shared) { int i; @@ -1121,11 +1378,11 @@ int ff_find_unused_picture(MpegEncContext *s, int shared) } } else { for (i = s->picture_range_start; i < s->picture_range_end; i++) { - if (s->picture[i].f.data[0] == NULL && s->picture[i].f.type != 0) + if (pic_is_unused(s, &s->picture[i]) && s->picture[i].f.type != 0) return i; // FIXME } for (i = s->picture_range_start; i < s->picture_range_end; i++) { - if (s->picture[i].f.data[0] == NULL) + if (pic_is_unused(s, &s->picture[i])) return i; } } @@ -1133,6 +1390,20 @@ int ff_find_unused_picture(MpegEncContext *s, int shared) return AVERROR_INVALIDDATA; } +int ff_find_unused_picture(MpegEncContext *s, int shared) +{ + int ret = find_unused_picture(s, shared); + + if (ret >= 0 && ret < s->picture_range_end) { + if (s->picture[ret].needs_realloc) { + s->picture[ret].needs_realloc = 0; + free_picture(s, &s->picture[ret]); + avcodec_get_frame_defaults(&s->picture[ret].f); + } + } + return ret; +} + static void update_noise_reduction(MpegEncContext *s) { int intra, i; @@ -1164,11 +1435,8 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) Picture *pic; s->mb_skipped = 0; - assert(s->last_picture_ptr == NULL || s->out_format != FMT_H264 || - s->codec_id == CODEC_ID_SVQ3); - /* mark & release old frames */ - if (s->out_format != FMT_H264 || s->codec_id == CODEC_ID_SVQ3) { + if (s->out_format != FMT_H264 || s->codec_id == AV_CODEC_ID_SVQ3) { if (s->pict_type != AV_PICTURE_TYPE_B && s->last_picture_ptr && s->last_picture_ptr != s->next_picture_ptr && s->last_picture_ptr->f.data[0]) { @@ -1183,7 +1451,7 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) if (s->picture[i].owner2 == s && s->picture[i].f.data[0] && &s->picture[i] != s->last_picture_ptr && &s->picture[i] != s->next_picture_ptr && - s->picture[i].f.reference) { + s->picture[i].f.reference && !s->picture[i].needs_realloc) { if (!(avctx->active_thread_type & FF_THREAD_FRAME)) av_log(avctx, AV_LOG_ERROR, "releasing zombie picture\n"); @@ -1203,12 +1471,16 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) pic = s->current_picture_ptr; } else { i = ff_find_unused_picture(s, 0); + if (i < 0) { + av_log(s->avctx, AV_LOG_ERROR, "no frame buffer available\n"); + return i; + } pic = &s->picture[i]; } pic->f.reference = 0; - if (!s->dropable) { - if (s->codec_id == CODEC_ID_H264) + if (!s->droppable) { + if (s->codec_id == AV_CODEC_ID_H264) pic->f.reference = s->picture_structure; else if (s->pict_type != AV_PICTURE_TYPE_B) pic->f.reference = 3; @@ -1222,8 +1494,8 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) s->current_picture_ptr = pic; // FIXME use only the vars from current_pic s->current_picture_ptr->f.top_field_first = s->top_field_first; - if (s->codec_id == CODEC_ID_MPEG1VIDEO || - s->codec_id == CODEC_ID_MPEG2VIDEO) { + if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO || + s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { if (s->picture_structure != PICT_FRAME) s->current_picture_ptr->f.top_field_first = (s->picture_structure == PICT_TOP_FIELD) == s->first_field; @@ -1242,21 +1514,24 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) if (s->pict_type != AV_PICTURE_TYPE_B) { s->last_picture_ptr = s->next_picture_ptr; - if (!s->dropable) + if (!s->droppable) s->next_picture_ptr = s->current_picture_ptr; } - /* av_log(s->avctx, AV_LOG_DEBUG, "L%p N%p C%p L%p N%p C%p type:%d drop:%d\n", - s->last_picture_ptr, s->next_picture_ptr,s->current_picture_ptr, - s->last_picture_ptr ? s->last_picture_ptr->f.data[0] : NULL, - s->next_picture_ptr ? s->next_picture_ptr->f.data[0] : NULL, - s->current_picture_ptr ? s->current_picture_ptr->f.data[0] : NULL, - s->pict_type, s->dropable); */ + av_dlog(s->avctx, "L%p N%p C%p L%p N%p C%p type:%d drop:%d\n", + s->last_picture_ptr, s->next_picture_ptr,s->current_picture_ptr, + s->last_picture_ptr ? s->last_picture_ptr->f.data[0] : NULL, + s->next_picture_ptr ? s->next_picture_ptr->f.data[0] : NULL, + s->current_picture_ptr ? s->current_picture_ptr->f.data[0] : NULL, + s->pict_type, s->droppable); - if (s->codec_id != CODEC_ID_H264) { + if (s->codec_id != AV_CODEC_ID_H264) { if ((s->last_picture_ptr == NULL || s->last_picture_ptr->f.data[0] == NULL) && (s->pict_type != AV_PICTURE_TYPE_I || s->picture_structure != PICT_FRAME)) { + int h_chroma_shift, v_chroma_shift; + av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt, + &h_chroma_shift, &v_chroma_shift); if (s->pict_type != AV_PICTURE_TYPE_I) av_log(avctx, AV_LOG_ERROR, "warning: first frame is no keyframe\n"); @@ -1266,11 +1541,25 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) /* Allocate a dummy frame */ i = ff_find_unused_picture(s, 0); + if (i < 0) { + av_log(s->avctx, AV_LOG_ERROR, "no frame buffer available\n"); + return i; + } s->last_picture_ptr = &s->picture[i]; if (ff_alloc_picture(s, s->last_picture_ptr, 0) < 0) { s->last_picture_ptr = NULL; return -1; } + + memset(s->last_picture_ptr->f.data[0], 0, + avctx->height * s->last_picture_ptr->f.linesize[0]); + memset(s->last_picture_ptr->f.data[1], 0x80, + (avctx->height >> v_chroma_shift) * + s->last_picture_ptr->f.linesize[1]); + memset(s->last_picture_ptr->f.data[2], 0x80, + (avctx->height >> v_chroma_shift) * + s->last_picture_ptr->f.linesize[2]); + ff_thread_report_progress(&s->last_picture_ptr->f, INT_MAX, 0); ff_thread_report_progress(&s->last_picture_ptr->f, INT_MAX, 1); s->last_picture_ptr->f.reference = 3; @@ -1280,6 +1569,10 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) s->pict_type == AV_PICTURE_TYPE_B) { /* Allocate a dummy frame */ i = ff_find_unused_picture(s, 0); + if (i < 0) { + av_log(s->avctx, AV_LOG_ERROR, "no frame buffer available\n"); + return i; + } s->next_picture_ptr = &s->picture[i]; if (ff_alloc_picture(s, s->next_picture_ptr, 0) < 0) { s->next_picture_ptr = NULL; @@ -1296,8 +1589,7 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) if (s->next_picture_ptr) ff_copy_picture(&s->next_picture, s->next_picture_ptr); - if (HAVE_THREADS && (avctx->active_thread_type & FF_THREAD_FRAME) && - (s->out_format != FMT_H264 || s->codec_id == CODEC_ID_SVQ3)) { + if (HAVE_THREADS && (avctx->active_thread_type & FF_THREAD_FRAME)) { if (s->next_picture_ptr) s->next_picture_ptr->owner2 = s; if (s->last_picture_ptr) @@ -1325,7 +1617,7 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) /* set dequantizer, we can't do it during init as * it might change for mpeg4 and we can't do it in the header * decode as init is not called for mpeg4 there yet */ - if (s->mpeg_quant || s->codec_id == CODEC_ID_MPEG2VIDEO) { + if (s->mpeg_quant || s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { s->dct_unquantize_intra = s->dct_unquantize_mpeg2_intra; s->dct_unquantize_inter = s->dct_unquantize_mpeg2_inter; } else if (s->out_format == FMT_H263 || s->out_format == FMT_H261) { @@ -1356,27 +1648,28 @@ void ff_MPV_frame_end(MpegEncContext *s) // just to make sure that all data is rendered. if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration) { ff_xvmc_field_end(s); - } else if ((s->error_count || s->encoding) && + } else if ((s->er.error_count || s->encoding) && !s->avctx->hwaccel && !(s->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) && s->unrestricted_mv && s->current_picture.f.reference && !s->intra_only && !(s->flags & CODEC_FLAG_EMU_EDGE)) { - int hshift = av_pix_fmt_descriptors[s->avctx->pix_fmt].log2_chroma_w; - int vshift = av_pix_fmt_descriptors[s->avctx->pix_fmt].log2_chroma_h; - s->dsp.draw_edges(s->current_picture.f.data[0], s->linesize, - s->h_edge_pos, s->v_edge_pos, - EDGE_WIDTH, EDGE_WIDTH, - EDGE_TOP | EDGE_BOTTOM); - s->dsp.draw_edges(s->current_picture.f.data[1], s->uvlinesize, - s->h_edge_pos >> hshift, s->v_edge_pos >> vshift, - EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift, - EDGE_TOP | EDGE_BOTTOM); - s->dsp.draw_edges(s->current_picture.f.data[2], s->uvlinesize, - s->h_edge_pos >> hshift, s->v_edge_pos >> vshift, - EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift, - EDGE_TOP | EDGE_BOTTOM); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->avctx->pix_fmt); + int hshift = desc->log2_chroma_w; + int vshift = desc->log2_chroma_h; + s->dsp.draw_edges(s->current_picture.f.data[0], s->linesize, + s->h_edge_pos, s->v_edge_pos, + EDGE_WIDTH, EDGE_WIDTH, + EDGE_TOP | EDGE_BOTTOM); + s->dsp.draw_edges(s->current_picture.f.data[1], s->uvlinesize, + s->h_edge_pos >> hshift, s->v_edge_pos >> vshift, + EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift, + EDGE_TOP | EDGE_BOTTOM); + s->dsp.draw_edges(s->current_picture.f.data[2], s->uvlinesize, + s->h_edge_pos >> hshift, s->v_edge_pos >> vshift, + EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift, + EDGE_TOP | EDGE_BOTTOM); } emms_c(); @@ -1414,7 +1707,7 @@ void ff_MPV_frame_end(MpegEncContext *s) #endif s->avctx->coded_frame = &s->current_picture_ptr->f; - if (s->codec_id != CODEC_ID_H264 && s->current_picture.f.reference) { + if (s->codec_id != AV_CODEC_ID_H264 && s->current_picture.f.reference) { ff_thread_report_progress(&s->current_picture_ptr->f, INT_MAX, 0); } } @@ -1446,7 +1739,7 @@ static void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey, buf += sx + sy * stride; ex -= sx; f = ((ey - sy) << 16) / ex; - for (x = 0; x = ex; x++) { + for (x = 0; x <= ex; x++) { y = (x * f) >> 16; fr = (x * f) & 0xFFFF; buf[y * stride + x] += (color * (0x10000 - fr)) >> 16; @@ -1599,7 +1892,6 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict) else av_log(s->avctx, AV_LOG_DEBUG, " "); } - // av_log(s->avctx, AV_LOG_DEBUG, " "); } av_log(s->avctx, AV_LOG_DEBUG, "\n"); } @@ -1616,11 +1908,11 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict) const int height = s->avctx->height; const int mv_sample_log2 = 4 - pict->motion_subsample_log2; const int mv_stride = (s->mb_width << mv_sample_log2) + - (s->codec_id == CODEC_ID_H264 ? 0 : 1); + (s->codec_id == AV_CODEC_ID_H264 ? 0 : 1); s->low_delay = 0; // needed to see the vectors without trashing the buffers - avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, - &h_chroma_shift, &v_chroma_shift); + av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt, + &h_chroma_shift, &v_chroma_shift); for (i = 0; i < 3; i++) { memcpy(s->visualization_buffer[i], pict->data[i], (i == 0) ? pict->linesize[i] * height: @@ -1805,7 +2097,7 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict) } if (IS_INTERLACED(mb_type) && - s->codec_id == CODEC_ID_H264) { + s->codec_id == AV_CODEC_ID_H264) { // hmm } } @@ -1823,7 +2115,8 @@ int ff_MPV_lowest_referenced_row(MpegEncContext *s, int dir) int my_max = INT_MIN, my_min = INT_MAX, qpel_shift = !s->quarter_sample; int my, off, i, mvs; - if (s->picture_structure != PICT_FRAME) goto unhandled; + if (s->picture_structure != PICT_FRAME || s->mcsel) + goto unhandled; switch (s->mv_type) { case MV_TYPE_16X16: @@ -1854,7 +2147,7 @@ unhandled: /* put block[] to dest[] */ static inline void put_dct(MpegEncContext *s, - DCTELEM *block, int i, uint8_t *dest, int line_size, int qscale) + int16_t *block, int i, uint8_t *dest, int line_size, int qscale) { s->dct_unquantize_intra(s, block, i, qscale); s->dsp.idct_put (dest, line_size, block); @@ -1862,7 +2155,7 @@ static inline void put_dct(MpegEncContext *s, /* add block[] to dest[] */ static inline void add_dct(MpegEncContext *s, - DCTELEM *block, int i, uint8_t *dest, int line_size) + int16_t *block, int i, uint8_t *dest, int line_size) { if (s->block_last_index[i] >= 0) { s->dsp.idct_add (dest, line_size, block); @@ -1870,7 +2163,7 @@ static inline void add_dct(MpegEncContext *s, } static inline void add_dequant_dct(MpegEncContext *s, - DCTELEM *block, int i, uint8_t *dest, int line_size, int qscale) + int16_t *block, int i, uint8_t *dest, int line_size, int qscale) { if (s->block_last_index[i] >= 0) { s->dct_unquantize_inter(s, block, i, qscale); @@ -1923,7 +2216,7 @@ void ff_clean_intra_table_entries(MpegEncContext *s) s->interlaced_dct : true if interlaced dct used (mpeg2) */ static av_always_inline -void MPV_decode_mb_internal(MpegEncContext *s, DCTELEM block[12][64], +void MPV_decode_mb_internal(MpegEncContext *s, int16_t block[12][64], int is_mpeg12) { const int mb_xy = s->mb_y * s->mb_stride + s->mb_x; @@ -1935,7 +2228,7 @@ void MPV_decode_mb_internal(MpegEncContext *s, DCTELEM block[12][64], if(s->avctx->debug&FF_DEBUG_DCT_COEFF) { /* save DCT coefficients */ int i,j; - DCTELEM *dct = &s->current_picture.f.dct_coeff[mb_xy * 64 * 6]; + int16_t *dct = &s->current_picture.f.dct_coeff[mb_xy * 64 * 6]; av_log(s->avctx, AV_LOG_DEBUG, "DCT coeffs of MB at %dx%d:\n", s->mb_x, s->mb_y); for(i=0; i<6; i++){ for(j=0; j<64; j++){ @@ -2026,12 +2319,12 @@ void MPV_decode_mb_internal(MpegEncContext *s, DCTELEM block[12][64], op_pix = s->dsp.put_no_rnd_pixels_tab; } if (s->mv_dir & MV_DIR_FORWARD) { - MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture.f.data, op_pix, op_qpix); + ff_MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture.f.data, op_pix, op_qpix); op_pix = s->dsp.avg_pixels_tab; op_qpix= s->me.qpel_avg; } if (s->mv_dir & MV_DIR_BACKWARD) { - MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture.f.data, op_pix, op_qpix); + ff_MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture.f.data, op_pix, op_qpix); } } @@ -2044,8 +2337,8 @@ void MPV_decode_mb_internal(MpegEncContext *s, DCTELEM block[12][64], } /* add dct residue */ - if(s->encoding || !( s->msmpeg4_version || s->codec_id==CODEC_ID_MPEG1VIDEO || s->codec_id==CODEC_ID_MPEG2VIDEO - || (s->codec_id==CODEC_ID_MPEG4 && !s->mpeg_quant))){ + if(s->encoding || !( s->msmpeg4_version || s->codec_id==AV_CODEC_ID_MPEG1VIDEO || s->codec_id==AV_CODEC_ID_MPEG2VIDEO + || (s->codec_id==AV_CODEC_ID_MPEG4 && !s->mpeg_quant))){ add_dequant_dct(s, block[0], 0, dest_y , dct_linesize, s->qscale); add_dequant_dct(s, block[1], 1, dest_y + block_size, dct_linesize, s->qscale); add_dequant_dct(s, block[2], 2, dest_y + dct_offset , dct_linesize, s->qscale); @@ -2064,7 +2357,7 @@ void MPV_decode_mb_internal(MpegEncContext *s, DCTELEM block[12][64], add_dequant_dct(s, block[7], 7, dest_cr + dct_offset, dct_linesize, s->chroma_qscale); } } - } else if(is_mpeg12 || (s->codec_id != CODEC_ID_WMV2)){ + } else if(is_mpeg12 || (s->codec_id != AV_CODEC_ID_WMV2)){ add_dct(s, block[0], 0, dest_y , dct_linesize); add_dct(s, block[1], 1, dest_y + block_size, dct_linesize); add_dct(s, block[2], 2, dest_y + dct_offset , dct_linesize); @@ -2097,7 +2390,7 @@ void MPV_decode_mb_internal(MpegEncContext *s, DCTELEM block[12][64], } } else { /* dct only in intra block */ - if(s->encoding || !(s->codec_id==CODEC_ID_MPEG1VIDEO || s->codec_id==CODEC_ID_MPEG2VIDEO)){ + if(s->encoding || !(s->codec_id==AV_CODEC_ID_MPEG1VIDEO || s->codec_id==AV_CODEC_ID_MPEG2VIDEO)){ put_dct(s, block[0], 0, dest_y , dct_linesize, s->qscale); put_dct(s, block[1], 1, dest_y + block_size, dct_linesize, s->qscale); put_dct(s, block[2], 2, dest_y + dct_offset , dct_linesize, s->qscale); @@ -2154,7 +2447,7 @@ skip_idct: } } -void ff_MPV_decode_mb(MpegEncContext *s, DCTELEM block[12][64]){ +void ff_MPV_decode_mb(MpegEncContext *s, int16_t block[12][64]){ #if !CONFIG_SMALL if(s->out_format == FMT_MPEG1) { MPV_decode_mb_internal(s, block, 1); @@ -2166,72 +2459,91 @@ void ff_MPV_decode_mb(MpegEncContext *s, DCTELEM block[12][64]){ /** * @param h is the normal height, this will be reduced automatically if needed for the last row */ -void ff_draw_horiz_band(MpegEncContext *s, int y, int h){ - const int field_pic= s->picture_structure != PICT_FRAME; +void ff_draw_horiz_band(AVCodecContext *avctx, DSPContext *dsp, Picture *cur, + Picture *last, int y, int h, int picture_structure, + int first_field, int draw_edges, int low_delay, + int v_edge_pos, int h_edge_pos) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); + int hshift = desc->log2_chroma_w; + int vshift = desc->log2_chroma_h; + const int field_pic = picture_structure != PICT_FRAME; if(field_pic){ h <<= 1; y <<= 1; } - if (!s->avctx->hwaccel - && !(s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU) - && s->unrestricted_mv - && s->current_picture.f.reference - && !s->intra_only - && !(s->flags&CODEC_FLAG_EMU_EDGE)) { + if (!avctx->hwaccel && + !(avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) && + draw_edges && + cur->f.reference && + !(avctx->flags & CODEC_FLAG_EMU_EDGE)) { + int *linesize = cur->f.linesize; int sides = 0, edge_h; - int hshift = av_pix_fmt_descriptors[s->avctx->pix_fmt].log2_chroma_w; - int vshift = av_pix_fmt_descriptors[s->avctx->pix_fmt].log2_chroma_h; if (y==0) sides |= EDGE_TOP; - if (y + h >= s->v_edge_pos) sides |= EDGE_BOTTOM; + if (y + h >= v_edge_pos) + sides |= EDGE_BOTTOM; - edge_h= FFMIN(h, s->v_edge_pos - y); + edge_h= FFMIN(h, v_edge_pos - y); - s->dsp.draw_edges(s->current_picture_ptr->f.data[0] + y *s->linesize, - s->linesize, s->h_edge_pos, edge_h, - EDGE_WIDTH, EDGE_WIDTH, sides); - s->dsp.draw_edges(s->current_picture_ptr->f.data[1] + (y>>vshift)*s->uvlinesize, - s->uvlinesize, s->h_edge_pos>>hshift, edge_h>>vshift, - EDGE_WIDTH>>hshift, EDGE_WIDTH>>vshift, sides); - s->dsp.draw_edges(s->current_picture_ptr->f.data[2] + (y>>vshift)*s->uvlinesize, - s->uvlinesize, s->h_edge_pos>>hshift, edge_h>>vshift, - EDGE_WIDTH>>hshift, EDGE_WIDTH>>vshift, sides); + dsp->draw_edges(cur->f.data[0] + y * linesize[0], + linesize[0], h_edge_pos, edge_h, + EDGE_WIDTH, EDGE_WIDTH, sides); + dsp->draw_edges(cur->f.data[1] + (y >> vshift) * linesize[1], + linesize[1], h_edge_pos >> hshift, edge_h >> vshift, + EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift, sides); + dsp->draw_edges(cur->f.data[2] + (y >> vshift) * linesize[2], + linesize[2], h_edge_pos >> hshift, edge_h >> vshift, + EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift, sides); } - h= FFMIN(h, s->avctx->height - y); + h = FFMIN(h, avctx->height - y); - if(field_pic && s->first_field && !(s->avctx->slice_flags&SLICE_FLAG_ALLOW_FIELD)) return; + if(field_pic && first_field && !(avctx->slice_flags&SLICE_FLAG_ALLOW_FIELD)) return; - if (s->avctx->draw_horiz_band) { + if (avctx->draw_horiz_band) { AVFrame *src; int offset[AV_NUM_DATA_POINTERS]; int i; - if(s->pict_type==AV_PICTURE_TYPE_B || s->low_delay || (s->avctx->slice_flags&SLICE_FLAG_CODED_ORDER)) - src = &s->current_picture_ptr->f; - else if(s->last_picture_ptr) - src = &s->last_picture_ptr->f; + if(cur->f.pict_type == AV_PICTURE_TYPE_B || low_delay || + (avctx->slice_flags & SLICE_FLAG_CODED_ORDER)) + src = &cur->f; + else if (last) + src = &last->f; else return; - if(s->pict_type==AV_PICTURE_TYPE_B && s->picture_structure == PICT_FRAME && s->out_format != FMT_H264){ + if (cur->f.pict_type == AV_PICTURE_TYPE_B && + picture_structure == PICT_FRAME && + avctx->codec_id != AV_CODEC_ID_H264 && + avctx->codec_id != AV_CODEC_ID_SVQ3) { for (i = 0; i < AV_NUM_DATA_POINTERS; i++) offset[i] = 0; }else{ - offset[0]= y * s->linesize; + offset[0]= y * src->linesize[0]; offset[1]= - offset[2]= (y >> s->chroma_y_shift) * s->uvlinesize; + offset[2]= (y >> vshift) * src->linesize[1]; for (i = 3; i < AV_NUM_DATA_POINTERS; i++) offset[i] = 0; } emms_c(); - s->avctx->draw_horiz_band(s->avctx, src, offset, - y, s->picture_structure, h); + avctx->draw_horiz_band(avctx, src, offset, + y, picture_structure, h); } } +void ff_mpeg_draw_horiz_band(MpegEncContext *s, int y, int h) +{ + int draw_edges = s->unrestricted_mv && !s->intra_only; + ff_draw_horiz_band(s->avctx, &s->dsp, &s->current_picture, + &s->last_picture, y, h, s->picture_structure, + s->first_field, draw_edges, s->low_delay, + s->v_edge_pos, s->h_edge_pos); +} + void ff_init_block_index(MpegEncContext *s){ //FIXME maybe rename const int linesize = s->current_picture.f.linesize[0]; //not s->linesize as this would be wrong for field pics const int uvlinesize = s->current_picture.f.linesize[1]; @@ -2264,6 +2576,35 @@ void ff_init_block_index(MpegEncContext *s){ //FIXME maybe rename } } +/** + * Permute an 8x8 block. + * @param block the block which will be permuted according to the given permutation vector + * @param permutation the permutation vector + * @param last the last non zero coefficient in scantable order, used to speed the permutation up + * @param scantable the used scantable, this is only used to speed the permutation up, the block is not + * (inverse) permutated to scantable order! + */ +void ff_block_permute(int16_t *block, uint8_t *permutation, const uint8_t *scantable, int last) +{ + int i; + int16_t temp[64]; + + if(last<=0) return; + //if(permutation[1]==1) return; //FIXME it is ok but not clean and might fail for some permutations + + for(i=0; i<=last; i++){ + const int j= scantable[i]; + temp[j]= block[j]; + block[j]=0; + } + + for(i=0; i<=last; i++){ + const int j= scantable[i]; + const int perm_j= permutation[j]; + block[perm_j]= temp[j]; + } +} + void ff_mpeg_flush(AVCodecContext *avctx){ int i; MpegEncContext *s = avctx->priv_data; @@ -2292,7 +2633,7 @@ void ff_mpeg_flush(AVCodecContext *avctx){ } static void dct_unquantize_mpeg1_intra_c(MpegEncContext *s, - DCTELEM *block, int n, int qscale) + int16_t *block, int n, int qscale) { int i, level, nCoeffs; const uint16_t *quant_matrix; @@ -2324,7 +2665,7 @@ static void dct_unquantize_mpeg1_intra_c(MpegEncContext *s, } static void dct_unquantize_mpeg1_inter_c(MpegEncContext *s, - DCTELEM *block, int n, int qscale) + int16_t *block, int n, int qscale) { int i, level, nCoeffs; const uint16_t *quant_matrix; @@ -2353,7 +2694,7 @@ static void dct_unquantize_mpeg1_inter_c(MpegEncContext *s, } static void dct_unquantize_mpeg2_intra_c(MpegEncContext *s, - DCTELEM *block, int n, int qscale) + int16_t *block, int n, int qscale) { int i, level, nCoeffs; const uint16_t *quant_matrix; @@ -2383,7 +2724,7 @@ static void dct_unquantize_mpeg2_intra_c(MpegEncContext *s, } static void dct_unquantize_mpeg2_intra_bitexact(MpegEncContext *s, - DCTELEM *block, int n, int qscale) + int16_t *block, int n, int qscale) { int i, level, nCoeffs; const uint16_t *quant_matrix; @@ -2416,7 +2757,7 @@ static void dct_unquantize_mpeg2_intra_bitexact(MpegEncContext *s, } static void dct_unquantize_mpeg2_inter_c(MpegEncContext *s, - DCTELEM *block, int n, int qscale) + int16_t *block, int n, int qscale) { int i, level, nCoeffs; const uint16_t *quant_matrix; @@ -2447,7 +2788,7 @@ static void dct_unquantize_mpeg2_inter_c(MpegEncContext *s, } static void dct_unquantize_h263_intra_c(MpegEncContext *s, - DCTELEM *block, int n, int qscale) + int16_t *block, int n, int qscale) { int i, level, qmul, qadd; int nCoeffs; @@ -2484,7 +2825,7 @@ static void dct_unquantize_h263_intra_c(MpegEncContext *s, } static void dct_unquantize_h263_inter_c(MpegEncContext *s, - DCTELEM *block, int n, int qscale) + int16_t *block, int n, int qscale) { int i, level, qmul, qadd; int nCoeffs; @@ -2528,6 +2869,22 @@ void ff_set_qscale(MpegEncContext * s, int qscale) void ff_MPV_report_decode_progress(MpegEncContext *s) { - if (s->pict_type != AV_PICTURE_TYPE_B && !s->partitioned_frame && !s->error_occurred) + if (s->pict_type != AV_PICTURE_TYPE_B && !s->partitioned_frame && !s->er.error_occurred) ff_thread_report_progress(&s->current_picture_ptr->f, s->mb_y, 0); } + +void ff_mpeg_er_frame_start(MpegEncContext *s) +{ + ERContext *er = &s->er; + + er->cur_pic = s->current_picture_ptr; + er->last_pic = s->last_picture_ptr; + er->next_pic = s->next_picture_ptr; + + er->pp_time = s->pp_time; + er->pb_time = s->pb_time; + er->quarter_sample = s->quarter_sample; + er->partitioned_frame = s->partitioned_frame; + + ff_er_frame_start(er); +}