X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fmpegvideo.c;h=5635c26c830c8c088d0952d5b59878a7b860a987;hb=75644335b907919057960716508477239c26fed4;hp=f51184f9f6f8e1a3490dbf2fd9e672d013d3c96d;hpb=59383d574046616ede75e51eeb404c9eb8b56d40;p=ffmpeg diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index f51184f9f6f..5635c26c830 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -27,11 +27,12 @@ * The simplest mpeg encoder (well, it was the simplest!). */ -#include "libavutil/intmath.h" +#include "libavutil/avassert.h" #include "libavutil/imgutils.h" #include "avcodec.h" #include "dsputil.h" #include "internal.h" +#include "mathops.h" #include "mpegvideo.h" #include "mjpegenc.h" #include "msmpeg4.h" @@ -43,19 +44,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... */ @@ -125,56 +126,43 @@ 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 uint8_t *avpriv_mpv_find_start_code(const uint8_t *restrict p, - const uint8_t *end, - uint32_t * restrict state) +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) { - int i; + MpegEncContext *s = opaque; - assert(p <= end); - if (p >= end) - return end; + 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)); - for (i = 0; i < 3; i++) { - uint32_t tmp = *state << 8; - *state = tmp + *(p++); - if (tmp == 0x100 || p == end) - return p; - } + ff_init_block_index(s); + ff_update_block_index(s); - while (p < end) { - if (p[-1] > 1 ) p += 3; - else if (p[-2] ) p += 2; - else if (p[-3]|(p[-1]-1)) p++; - else { - p++; - break; - } - } + s->dsp.clear_blocks(s->block[0]); - p = FFMIN(p, end) - 4; - *state = AV_RB32(p); + 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); - return p + 4; + assert(ref == 0); + ff_MPV_decode_mb(s, s->block); } /* init common dct for both encoder and decoder */ 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; @@ -189,8 +177,6 @@ av_cold int ff_dct_common_init(MpegEncContext *s) 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 @@ -215,26 +201,29 @@ av_cold int ff_dct_common_init(MpegEncContext *s) return 0; } -void ff_copy_picture(Picture *dst, Picture *src) +int ff_mpv_frame_size_alloc(MpegEncContext *s, int linesize) { - *dst = *src; - dst->f.type = FF_BUFFER_TYPE_COPY; -} + int alloc_size = FFALIGN(FFABS(linesize) + 32, 32); -/** - * Release a frame buffer - */ -static void free_frame_buffer(MpegEncContext *s, Picture *pic) -{ - /* 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); + // 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); } /** @@ -242,71 +231,157 @@ static void free_frame_buffer(MpegEncContext *s, Picture *pic) */ static int alloc_frame_buffer(MpegEncContext *s, Picture *pic) { - int r; + int r, ret; + + pic->tf.f = &pic->f; + 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->tf, + pic->reference ? AV_GET_BUFFER_FLAG_REF : 0); + else { + pic->f.width = s->avctx->width; + pic->f.height = s->avctx->height; + pic->f.format = s->avctx->pix_fmt; + r = avcodec_default_get_buffer2(s->avctx, &pic->f, 0); + } + + if (r < 0 || !pic->f.data[0]) { + av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed (%d %p)\n", + r, pic->f.data[0]); + return -1; + } if (s->avctx->hwaccel) { - assert(!pic->f.hwaccel_picture_private); + assert(!pic->hwaccel_picture_private); if (s->avctx->hwaccel->priv_data_size) { - pic->f.hwaccel_picture_private = av_mallocz(s->avctx->hwaccel->priv_data_size); - if (!pic->f.hwaccel_picture_private) { + pic->hwaccel_priv_buf = av_buffer_allocz(s->avctx->hwaccel->priv_data_size); + if (!pic->hwaccel_priv_buf) { av_log(s->avctx, AV_LOG_ERROR, "alloc_frame_buffer() failed (hwaccel private data allocation)\n"); return -1; } + pic->hwaccel_picture_private = pic->hwaccel_priv_buf->data; } } - 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); - - if (r < 0 || !pic->f.type || !pic->f.data[0]) { - av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed (%d %d %p)\n", - r, pic->f.type, pic->f.data[0]); - av_freep(&pic->f.hwaccel_picture_private); - return -1; - } - if (s->linesize && (s->linesize != pic->f.linesize[0] || s->uvlinesize != pic->f.linesize[1])) { av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed (stride changed)\n"); - free_frame_buffer(s, pic); + ff_mpeg_unref_picture(s, pic); return -1; } if (pic->f.linesize[1] != pic->f.linesize[2]) { av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed (uv stride mismatch)\n"); - free_frame_buffer(s, pic); + ff_mpeg_unref_picture(s, 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"); + ff_mpeg_unref_picture(s, pic); + return ret; + } + return 0; } -/** - * Allocate a Picture. - * The pixels are allocated/set by calling get_buffer() if shared = 0 - */ -int ff_alloc_picture(MpegEncContext *s, Picture *pic, int shared) +static void free_picture_tables(Picture *pic) { - const int big_mb_num = s->mb_stride * (s->mb_height + 1) + 1; + int i; + + av_buffer_unref(&pic->mb_var_buf); + av_buffer_unref(&pic->mc_mb_var_buf); + av_buffer_unref(&pic->mb_mean_buf); + av_buffer_unref(&pic->mbskip_table_buf); + av_buffer_unref(&pic->qscale_table_buf); + av_buffer_unref(&pic->mb_type_buf); - // the + 1 is needed so memset(,,stride*height) does not sig11 + for (i = 0; i < 2; i++) { + av_buffer_unref(&pic->motion_val_buf[i]); + av_buffer_unref(&pic->ref_index_buf[i]); + } +} +static int alloc_picture_tables(MpegEncContext *s, Picture *pic) +{ + const int big_mb_num = s->mb_stride * (s->mb_height + 1) + 1; const int mb_array_size = s->mb_stride * s->mb_height; const int b8_array_size = s->b8_stride * s->mb_height * 2; - const int b4_array_size = s->b4_stride * s->mb_height * 4; int i; - int r = -1; + + + pic->mbskip_table_buf = av_buffer_allocz(mb_array_size + 2); + pic->qscale_table_buf = av_buffer_allocz(big_mb_num + s->mb_stride); + pic->mb_type_buf = av_buffer_allocz((big_mb_num + s->mb_stride) * + sizeof(uint32_t)); + if (!pic->mbskip_table_buf || !pic->qscale_table_buf || !pic->mb_type_buf) + return AVERROR(ENOMEM); + + if (s->encoding) { + pic->mb_var_buf = av_buffer_allocz(mb_array_size * sizeof(int16_t)); + pic->mc_mb_var_buf = av_buffer_allocz(mb_array_size * sizeof(int16_t)); + pic->mb_mean_buf = av_buffer_allocz(mb_array_size); + if (!pic->mb_var_buf || !pic->mc_mb_var_buf || !pic->mb_mean_buf) + return AVERROR(ENOMEM); + } + + if (s->out_format == FMT_H263 || s->encoding || + (s->avctx->debug & FF_DEBUG_MV) || s->avctx->debug_mv) { + int mv_size = 2 * (b8_array_size + 4) * sizeof(int16_t); + int ref_index_size = 4 * mb_array_size; + + for (i = 0; mv_size && i < 2; i++) { + pic->motion_val_buf[i] = av_buffer_allocz(mv_size); + pic->ref_index_buf[i] = av_buffer_allocz(ref_index_size); + if (!pic->motion_val_buf[i] || !pic->ref_index_buf[i]) + return AVERROR(ENOMEM); + } + } + + return 0; +} + +static int make_tables_writable(Picture *pic) +{ + int ret, i; +#define MAKE_WRITABLE(table) \ +do {\ + if (pic->table &&\ + (ret = av_buffer_make_writable(&pic->table)) < 0)\ + return ret;\ +} while (0) + + MAKE_WRITABLE(mb_var_buf); + MAKE_WRITABLE(mc_mb_var_buf); + MAKE_WRITABLE(mb_mean_buf); + MAKE_WRITABLE(mbskip_table_buf); + MAKE_WRITABLE(qscale_table_buf); + MAKE_WRITABLE(mb_type_buf); + + for (i = 0; i < 2; i++) { + MAKE_WRITABLE(motion_val_buf[i]); + MAKE_WRITABLE(ref_index_buf[i]); + } + + return 0; +} + +/** + * Allocate a Picture. + * The pixels are allocated/set by calling get_buffer() if shared = 0 + */ +int ff_alloc_picture(MpegEncContext *s, Picture *pic, int shared) +{ + int i, ret; if (shared) { assert(pic->f.data[0]); - assert(pic->f.type == 0 || pic->f.type == FF_BUFFER_TYPE_SHARED); - pic->f.type = FF_BUFFER_TYPE_SHARED; + pic->shared = 1; } else { assert(!pic->f.data[0]); @@ -317,123 +392,154 @@ int ff_alloc_picture(MpegEncContext *s, Picture *pic, int shared) s->uvlinesize = pic->f.linesize[1]; } - if (pic->f.qscale_table == NULL) { - if (s->encoding) { - FF_ALLOCZ_OR_GOTO(s->avctx, pic->mb_var, - mb_array_size * sizeof(int16_t), fail) - FF_ALLOCZ_OR_GOTO(s->avctx, pic->mc_mb_var, - mb_array_size * sizeof(int16_t), fail) - FF_ALLOCZ_OR_GOTO(s->avctx, pic->mb_mean, - mb_array_size * sizeof(int8_t ), fail) - } + if (!pic->qscale_table_buf) + ret = alloc_picture_tables(s, pic); + else + ret = make_tables_writable(pic); + if (ret < 0) + goto fail; - FF_ALLOCZ_OR_GOTO(s->avctx, pic->f.mbskip_table, - mb_array_size * sizeof(uint8_t) + 2, fail)// the + 2 is for the slice end check - FF_ALLOCZ_OR_GOTO(s->avctx, pic->qscale_table_base, - (big_mb_num + s->mb_stride) * sizeof(uint8_t), - fail) - FF_ALLOCZ_OR_GOTO(s->avctx, pic->mb_type_base, - (big_mb_num + s->mb_stride) * sizeof(uint32_t), - fail) - pic->f.mb_type = pic->mb_type_base + 2 * s->mb_stride + 1; - pic->f.qscale_table = pic->qscale_table_base + 2 * s->mb_stride + 1; - if (s->out_format == FMT_H264) { - for (i = 0; i < 2; i++) { - FF_ALLOCZ_OR_GOTO(s->avctx, pic->motion_val_base[i], - 2 * (b4_array_size + 4) * sizeof(int16_t), - fail) - pic->f.motion_val[i] = pic->motion_val_base[i] + 4; - FF_ALLOCZ_OR_GOTO(s->avctx, pic->f.ref_index[i], - 4 * mb_array_size * sizeof(uint8_t), fail) - } - pic->f.motion_subsample_log2 = 2; - } else if (s->out_format == FMT_H263 || s->encoding || - (s->avctx->debug & FF_DEBUG_MV) || s->avctx->debug_mv) { - for (i = 0; i < 2; i++) { - FF_ALLOCZ_OR_GOTO(s->avctx, pic->motion_val_base[i], - 2 * (b8_array_size + 4) * sizeof(int16_t), - fail) - pic->f.motion_val[i] = pic->motion_val_base[i] + 4; - FF_ALLOCZ_OR_GOTO(s->avctx, pic->f.ref_index[i], - 4 * mb_array_size * sizeof(uint8_t), fail) - } - pic->f.motion_subsample_log2 = 3; - } - 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) - } - pic->f.qstride = s->mb_stride; - FF_ALLOCZ_OR_GOTO(s->avctx, pic->f.pan_scan, - 1 * sizeof(AVPanScan), fail) + if (s->encoding) { + pic->mb_var = (uint16_t*)pic->mb_var_buf->data; + pic->mc_mb_var = (uint16_t*)pic->mc_mb_var_buf->data; + pic->mb_mean = pic->mb_mean_buf->data; } - pic->owner2 = s; + pic->mbskip_table = pic->mbskip_table_buf->data; + pic->qscale_table = pic->qscale_table_buf->data + 2 * s->mb_stride + 1; + pic->mb_type = (uint32_t*)pic->mb_type_buf->data + 2 * s->mb_stride + 1; + + if (pic->motion_val_buf[0]) { + for (i = 0; i < 2; i++) { + pic->motion_val[i] = (int16_t (*)[2])pic->motion_val_buf[i]->data + 4; + pic->ref_index[i] = pic->ref_index_buf[i]->data; + } + } return 0; -fail: // for the FF_ALLOCZ_OR_GOTO macro - if (r >= 0) - free_frame_buffer(s, pic); - return -1; +fail: + av_log(s->avctx, AV_LOG_ERROR, "Error allocating a picture.\n"); + ff_mpeg_unref_picture(s, pic); + free_picture_tables(pic); + return AVERROR(ENOMEM); } /** * Deallocate a picture. */ -static void free_picture(MpegEncContext *s, Picture *pic) +void ff_mpeg_unref_picture(MpegEncContext *s, Picture *pic) { - int i; + int off = offsetof(Picture, mb_mean) + sizeof(pic->mb_mean); - if (pic->f.data[0] && pic->f.type != FF_BUFFER_TYPE_SHARED) { - free_frame_buffer(s, pic); - } - - av_freep(&pic->mb_var); - av_freep(&pic->mc_mb_var); - 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; + pic->tf.f = &pic->f; + /* 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->tf); + else + av_frame_unref(&pic->f); + + av_buffer_unref(&pic->hwaccel_priv_buf); + + memset((uint8_t*)pic + off, 0, sizeof(*pic) - off); +} + +static int update_picture_tables(Picture *dst, Picture *src) +{ + int i; + +#define UPDATE_TABLE(table)\ +do {\ + if (src->table &&\ + (!dst->table || dst->table->buffer != src->table->buffer)) {\ + av_buffer_unref(&dst->table);\ + dst->table = av_buffer_ref(src->table);\ + if (!dst->table) {\ + free_picture_tables(dst);\ + return AVERROR(ENOMEM);\ + }\ + }\ +} while (0) + + UPDATE_TABLE(mb_var_buf); + UPDATE_TABLE(mc_mb_var_buf); + UPDATE_TABLE(mb_mean_buf); + UPDATE_TABLE(mbskip_table_buf); + UPDATE_TABLE(qscale_table_buf); + UPDATE_TABLE(mb_type_buf); 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; + UPDATE_TABLE(motion_val_buf[i]); + UPDATE_TABLE(ref_index_buf[i]); } - if (pic->f.type == FF_BUFFER_TYPE_SHARED) { - for (i = 0; i < 4; i++) { - pic->f.base[i] = - pic->f.data[i] = NULL; - } - pic->f.type = 0; + dst->mb_var = src->mb_var; + dst->mc_mb_var = src->mc_mb_var; + dst->mb_mean = src->mb_mean; + dst->mbskip_table = src->mbskip_table; + dst->qscale_table = src->qscale_table; + dst->mb_type = src->mb_type; + for (i = 0; i < 2; i++) { + dst->motion_val[i] = src->motion_val[i]; + dst->ref_index[i] = src->ref_index[i]; } + + return 0; } -static int init_duplicate_context(MpegEncContext *s, MpegEncContext *base) +int ff_mpeg_ref_picture(MpegEncContext *s, Picture *dst, Picture *src) +{ + int ret; + + av_assert0(!dst->f.buf[0]); + av_assert0(src->f.buf[0]); + + src->tf.f = &src->f; + dst->tf.f = &dst->f; + ret = ff_thread_ref_frame(&dst->tf, &src->tf); + if (ret < 0) + goto fail; + + ret = update_picture_tables(dst, src); + if (ret < 0) + goto fail; + + if (src->hwaccel_picture_private) { + dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf); + if (!dst->hwaccel_priv_buf) + goto fail; + dst->hwaccel_picture_private = dst->hwaccel_priv_buf->data; + } + + dst->field_picture = src->field_picture; + dst->mb_var_sum = src->mb_var_sum; + dst->mc_mb_var_sum = src->mc_mb_var_sum; + dst->b_frame_score = src->b_frame_score; + dst->needs_realloc = src->needs_realloc; + dst->reference = src->reference; + dst->shared = src->shared; + + return 0; +fail: + ff_mpeg_unref_picture(s, dst); + return ret; +} + +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) @@ -444,7 +550,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++) { @@ -512,10 +618,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); @@ -524,13 +630,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, ret; MpegEncContext *s = dst->priv_data, *s1 = src->priv_data; if (dst == src || !s1->context_initialized) @@ -542,14 +656,21 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst, memcpy(s, s1, sizeof(MpegEncContext)); s->avctx = dst; - s->picture_range_start += MAX_PICTURE_COUNT; - s->picture_range_end += MAX_PICTURE_COUNT; s->bitstream_buffer = NULL; s->bitstream_buffer_size = s->allocated_bitstream_buffer_size = 0; 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,9 +680,27 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst, s->picture_number = s1->picture_number; s->input_picture_number = s1->input_picture_number; - memcpy(s->picture, s1->picture, s1->picture_count * sizeof(Picture)); - memcpy(&s->last_picture, &s1->last_picture, - (char *) &s1->last_picture_ptr - (char *) &s1->last_picture); + for (i = 0; i < MAX_PICTURE_COUNT; i++) { + ff_mpeg_unref_picture(s, &s->picture[i]); + if (s1->picture[i].f.data[0] && + (ret = ff_mpeg_ref_picture(s, &s->picture[i], &s1->picture[i])) < 0) + return ret; + } + +#define UPDATE_PICTURE(pic)\ +do {\ + ff_mpeg_unref_picture(s, &s->pic);\ + if (s1->pic.f.data[0])\ + ret = ff_mpeg_ref_picture(s, &s->pic, &s1->pic);\ + else\ + ret = update_picture_tables(&s->pic, &s1->pic);\ + if (ret < 0)\ + return ret;\ +} while (0) + + UPDATE_PICTURE(current_picture); + UPDATE_PICTURE(last_picture); + UPDATE_PICTURE(next_picture); s->last_picture_ptr = REBASE_PICTURE(s1->last_picture_ptr, s, s1); s->current_picture_ptr = REBASE_PICTURE(s1->current_picture_ptr, s, s1); @@ -578,7 +717,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; @@ -596,6 +735,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); @@ -637,9 +790,6 @@ void ff_MPV_common_defaults(MpegEncContext *s) s->f_code = 1; s->b_code = 1; - s->picture_range_start = 0; - s->picture_range_end = MAX_PICTURE_COUNT; - s->slice_context_count = 1; } @@ -653,13 +803,190 @@ 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 + + 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; @@ -669,12 +996,12 @@ av_cold int ff_MPV_common_init(MpegEncContext *s) 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) + else 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; } @@ -699,34 +1026,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); @@ -735,42 +1038,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) * @@ -778,13 +1046,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, @@ -802,97 +1063,26 @@ av_cold int ff_MPV_common_init(MpegEncContext *s) FF_ALLOCZ_OR_GOTO(s->avctx, s->dct_offset, 2 * 64 * sizeof(uint16_t), 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); } } - s->picture_count = MAX_PICTURE_COUNT * FFMAX(1, s->avctx->thread_count); FF_ALLOCZ_OR_GOTO(s->avctx, s->picture, - s->picture_count * sizeof(Picture), fail); - for (i = 0; i < s->picture_count; i++) { + MAX_PICTURE_COUNT * sizeof(Picture), fail); + for (i = 0; i < MAX_PICTURE_COUNT; i++) { avcodec_get_frame_defaults(&s->picture[i].f); } + memset(&s->next_picture, 0, sizeof(s->next_picture)); + memset(&s->last_picture, 0, sizeof(s->last_picture)); + memset(&s->current_picture, 0, sizeof(s->current_picture)); + avcodec_get_frame_defaults(&s->next_picture.f); + avcodec_get_frame_defaults(&s->last_picture.f); + avcodec_get_frame_defaults(&s->current_picture.f); if (s->width && s->height) { - FF_ALLOC_OR_GOTO(s->avctx, s->er_temp_buffer, - mb_array_size * sizeof(uint8_t), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->error_status_table, - mb_array_size * sizeof(uint8_t), 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 (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; @@ -906,7 +1096,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; @@ -914,7 +1104,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; @@ -928,24 +1118,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); @@ -979,15 +1160,115 @@ 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; + + 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); + + if ((err = free_context_frame(s)) < 0) + return err; + + if (s->picture) + for (i = 0; i < MAX_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 + 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->er_temp_buffer); - 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); @@ -995,26 +1276,30 @@ void ff_MPV_common_end(MpegEncContext *s) av_freep(&s->input_picture); av_freep(&s->reordered_input_picture); av_freep(&s->dct_offset); - av_freep(&s->cplx_tab); - av_freep(&s->bits_tab); - if (s->picture && !s->avctx->internal->is_copy) { - for (i = 0; i < s->picture_count; i++) { - free_picture(s, &s->picture[i]); + if (s->picture) { + for (i = 0; i < MAX_PICTURE_COUNT; i++) { + free_picture_tables(&s->picture[i]); + ff_mpeg_unref_picture(s, &s->picture[i]); } } av_freep(&s->picture); + free_picture_tables(&s->last_picture); + ff_mpeg_unref_picture(s, &s->last_picture); + free_picture_tables(&s->current_picture); + ff_mpeg_unref_picture(s, &s->current_picture); + free_picture_tables(&s->next_picture); + ff_mpeg_unref_picture(s, &s->next_picture); + free_picture_tables(&s->new_picture); + ff_mpeg_unref_picture(s, &s->new_picture); + + free_context_frame(s); + 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, @@ -1114,32 +1399,35 @@ void ff_release_unused_pictures(MpegEncContext*s, int remove_current) int i; /* release non reference frames */ - for (i = 0; i < s->picture_count; i++) { - if (s->picture[i].f.data[0] && !s->picture[i].f.reference && - (!s->picture[i].owner2 || s->picture[i].owner2 == s) && - (remove_current || &s->picture[i] != s->current_picture_ptr) - /* && s->picture[i].type!= FF_BUFFER_TYPE_SHARED */) { - free_frame_buffer(s, &s->picture[i]); + for (i = 0; i < MAX_PICTURE_COUNT; i++) { + if (!s->picture[i].reference && + (remove_current || &s->picture[i] != s->current_picture_ptr)) { + ff_mpeg_unref_picture(s, &s->picture[i]); } } } -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->reference & DELAYED_PIC_REF)) + return 1; + return 0; +} + +static int find_unused_picture(MpegEncContext *s, int shared) { int i; if (shared) { - 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) + for (i = 0; i < MAX_PICTURE_COUNT; i++) { + if (s->picture[i].f.data[0] == NULL) return i; } } 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) - return i; // FIXME - } - for (i = s->picture_range_start; i < s->picture_range_end; i++) { - if (s->picture[i].f.data[0] == NULL) + for (i = 0; i < MAX_PICTURE_COUNT; i++) { + if (pic_is_unused(s, &s->picture[i])) return i; } } @@ -1147,6 +1435,21 @@ 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 < MAX_PICTURE_COUNT) { + if (s->picture[ret].needs_realloc) { + s->picture[ret].needs_realloc = 0; + free_picture_tables(&s->picture[ret]); + ff_mpeg_unref_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; @@ -1174,32 +1477,28 @@ static void update_noise_reduction(MpegEncContext *s) */ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) { - int i; + int i, ret; Picture *pic; s->mb_skipped = 0; /* mark & release old frames */ - 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]) { - if (s->last_picture_ptr->owner2 == s) - free_frame_buffer(s, s->last_picture_ptr); - } + 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]) { + ff_mpeg_unref_picture(s, s->last_picture_ptr); + } - /* release forgotten pictures */ - /* if (mpeg124/h263) */ - if (!s->encoding) { - for (i = 0; i < s->picture_count; i++) { - 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) { - if (!(avctx->active_thread_type & FF_THREAD_FRAME)) - av_log(avctx, AV_LOG_ERROR, - "releasing zombie picture\n"); - free_frame_buffer(s, &s->picture[i]); - } + /* release forgotten pictures */ + /* if (mpeg124/h263) */ + if (!s->encoding) { + for (i = 0; i < MAX_PICTURE_COUNT; i++) { + if (&s->picture[i] != s->last_picture_ptr && + &s->picture[i] != s->next_picture_ptr && + s->picture[i].reference && !s->picture[i].needs_realloc) { + if (!(avctx->active_thread_type & FF_THREAD_FRAME)) + av_log(avctx, AV_LOG_ERROR, + "releasing zombie picture\n"); + ff_mpeg_unref_picture(s, &s->picture[i]); } } } @@ -1214,15 +1513,17 @@ 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 == AV_CODEC_ID_H264) - pic->f.reference = s->picture_structure; - else if (s->pict_type != AV_PICTURE_TYPE_B) - pic->f.reference = 3; + pic->reference = 0; + if (!s->droppable) { + if (s->pict_type != AV_PICTURE_TYPE_B) + pic->reference = 3; } pic->f.coded_picture_number = s->coded_picture_number++; @@ -1249,76 +1550,98 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) // s->current_picture_ptr->quality = s->new_picture_ptr->quality; s->current_picture_ptr->f.key_frame = s->pict_type == AV_PICTURE_TYPE_I; - ff_copy_picture(&s->current_picture, s->current_picture_ptr); + ff_mpeg_unref_picture(s, &s->current_picture); + if ((ret = ff_mpeg_ref_picture(s, &s->current_picture, + s->current_picture_ptr)) < 0) + return ret; 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); */ - - 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)) { - if (s->pict_type != AV_PICTURE_TYPE_I) - av_log(avctx, AV_LOG_ERROR, - "warning: first frame is no keyframe\n"); - else if (s->picture_structure != PICT_FRAME) - av_log(avctx, AV_LOG_INFO, - "allocate dummy last picture for field based first keyframe\n"); - - /* Allocate a dummy frame */ - i = ff_find_unused_picture(s, 0); - 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; - } - 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; + 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->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"); + else if (s->picture_structure != PICT_FRAME) + av_log(avctx, AV_LOG_INFO, + "allocate dummy last picture for field based first keyframe\n"); + + /* 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; } - if ((s->next_picture_ptr == NULL || - s->next_picture_ptr->f.data[0] == NULL) && - s->pict_type == AV_PICTURE_TYPE_B) { - /* Allocate a dummy frame */ - i = ff_find_unused_picture(s, 0); - s->next_picture_ptr = &s->picture[i]; - if (ff_alloc_picture(s, s->next_picture_ptr, 0) < 0) { - s->next_picture_ptr = NULL; - return -1; - } - ff_thread_report_progress(&s->next_picture_ptr->f, INT_MAX, 0); - ff_thread_report_progress(&s->next_picture_ptr->f, INT_MAX, 1); - s->next_picture_ptr->f.reference = 3; + 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; } - } - if (s->last_picture_ptr) - ff_copy_picture(&s->last_picture, s->last_picture_ptr); - if (s->next_picture_ptr) - ff_copy_picture(&s->next_picture, s->next_picture_ptr); + 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->tf, INT_MAX, 0); + ff_thread_report_progress(&s->last_picture_ptr->tf, INT_MAX, 1); + } + if ((s->next_picture_ptr == NULL || + s->next_picture_ptr->f.data[0] == NULL) && + 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; + return -1; + } + ff_thread_report_progress(&s->next_picture_ptr->tf, INT_MAX, 0); + ff_thread_report_progress(&s->next_picture_ptr->tf, INT_MAX, 1); + } - if (HAVE_THREADS && (avctx->active_thread_type & FF_THREAD_FRAME) && - (s->out_format != FMT_H264 || s->codec_id == AV_CODEC_ID_SVQ3)) { - if (s->next_picture_ptr) - s->next_picture_ptr->owner2 = s; - if (s->last_picture_ptr) - s->last_picture_ptr->owner2 = s; + if (s->last_picture_ptr) { + ff_mpeg_unref_picture(s, &s->last_picture); + if (s->last_picture_ptr->f.data[0] && + (ret = ff_mpeg_ref_picture(s, &s->last_picture, + s->last_picture_ptr)) < 0) + return ret; + } + if (s->next_picture_ptr) { + ff_mpeg_unref_picture(s, &s->next_picture); + if (s->next_picture_ptr->f.data[0] && + (ret = ff_mpeg_ref_picture(s, &s->next_picture, + s->next_picture_ptr)) < 0) + return ret; } assert(s->pict_type == AV_PICTURE_TYPE_I || (s->last_picture_ptr && s->last_picture_ptr->f.data[0])); - if (s->picture_structure!= PICT_FRAME && s->out_format != FMT_H264) { + if (s->picture_structure!= PICT_FRAME) { int i; for (i = 0; i < 4; i++) { if (s->picture_structure == PICT_BOTTOM_FIELD) { @@ -1367,27 +1690,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->current_picture.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(); @@ -1410,11 +1734,9 @@ void ff_MPV_frame_end(MpegEncContext *s) if (s->encoding) { /* release non-reference frames */ - for (i = 0; i < s->picture_count; i++) { - if (s->picture[i].f.data[0] && !s->picture[i].f.reference - /* && s->picture[i].type != FF_BUFFER_TYPE_SHARED */) { - free_frame_buffer(s, &s->picture[i]); - } + for (i = 0; i < MAX_PICTURE_COUNT; i++) { + if (!s->picture[i].reference) + ff_mpeg_unref_picture(s, &s->picture[i]); } } // clear copies, to avoid confusion @@ -1425,106 +1747,19 @@ void ff_MPV_frame_end(MpegEncContext *s) #endif s->avctx->coded_frame = &s->current_picture_ptr->f; - 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); - } -} - -/** - * Draw a line from (ex, ey) -> (sx, sy). - * @param w width of the image - * @param h height of the image - * @param stride stride/linesize of the image - * @param color color of the arrow - */ -static void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey, - int w, int h, int stride, int color) -{ - int x, y, fr, f; - - sx = av_clip(sx, 0, w - 1); - sy = av_clip(sy, 0, h - 1); - ex = av_clip(ex, 0, w - 1); - ey = av_clip(ey, 0, h - 1); - - buf[sy * stride + sx] += color; - - if (FFABS(ex - sx) > FFABS(ey - sy)) { - if (sx > ex) { - FFSWAP(int, sx, ex); - FFSWAP(int, sy, ey); - } - buf += sx + sy * stride; - ex -= sx; - f = ((ey - sy) << 16) / ex; - for (x = 0; x = ex; x++) { - y = (x * f) >> 16; - fr = (x * f) & 0xFFFF; - buf[y * stride + x] += (color * (0x10000 - fr)) >> 16; - buf[(y + 1) * stride + x] += (color * fr ) >> 16; - } - } else { - if (sy > ey) { - FFSWAP(int, sx, ex); - FFSWAP(int, sy, ey); - } - buf += sx + sy * stride; - ey -= sy; - if (ey) - f = ((ex - sx) << 16) / ey; - else - f = 0; - for (y = 0; y = ey; y++) { - x = (y * f) >> 16; - fr = (y * f) & 0xFFFF; - buf[y * stride + x] += (color * (0x10000 - fr)) >> 16; - buf[y * stride + x + 1] += (color * fr ) >> 16; - } - } -} - -/** - * Draw an arrow from (ex, ey) -> (sx, sy). - * @param w width of the image - * @param h height of the image - * @param stride stride/linesize of the image - * @param color color of the arrow - */ -static void draw_arrow(uint8_t *buf, int sx, int sy, int ex, - int ey, int w, int h, int stride, int color) -{ - int dx,dy; - - sx = av_clip(sx, -100, w + 100); - sy = av_clip(sy, -100, h + 100); - ex = av_clip(ex, -100, w + 100); - ey = av_clip(ey, -100, h + 100); - - dx = ex - sx; - dy = ey - sy; - - if (dx * dx + dy * dy > 3 * 3) { - int rx = dx + dy; - int ry = -dx + dy; - int length = ff_sqrt((rx * rx + ry * ry) << 8); - - // FIXME subpixel accuracy - rx = ROUNDED_DIV(rx * 3 << 4, length); - ry = ROUNDED_DIV(ry * 3 << 4, length); - - draw_line(buf, sx, sy, sx + rx, sy + ry, w, h, stride, color); - draw_line(buf, sx, sy, sx - ry, sy + rx, w, h, stride, color); - } - draw_line(buf, sx, sy, ex, ey, w, h, stride, color); + if (s->current_picture.reference) + ff_thread_report_progress(&s->current_picture_ptr->tf, INT_MAX, 0); } /** * Print debugging info for the given picture. */ -void ff_print_debug_info(MpegEncContext *s, AVFrame *pict) +void ff_print_debug_info(MpegEncContext *s, Picture *p) { - if (s->avctx->hwaccel || !pict || !pict->mb_type) + AVFrame *pict; + if (s->avctx->hwaccel || !p || !p->mb_type) return; + pict = &p->f; if (s->avctx->debug & (FF_DEBUG_SKIP | FF_DEBUG_QP | FF_DEBUG_MB_TYPE)) { int x,y; @@ -1560,10 +1795,10 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict) } if (s->avctx->debug & FF_DEBUG_QP) { av_log(s->avctx, AV_LOG_DEBUG, "%2d", - pict->qscale_table[x + y * s->mb_stride]); + p->qscale_table[x + y * s->mb_stride]); } if (s->avctx->debug & FF_DEBUG_MB_TYPE) { - int mb_type = pict->mb_type[x + y * s->mb_stride]; + int mb_type = p->mb_type[x + y * s->mb_stride]; // Type & MV direction if (IS_PCM(mb_type)) av_log(s->avctx, AV_LOG_DEBUG, "P"); @@ -1610,220 +1845,10 @@ 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"); } } - - if ((s->avctx->debug & (FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE)) || - (s->avctx->debug_mv)) { - const int shift = 1 + s->quarter_sample; - int mb_y; - uint8_t *ptr; - int i; - int h_chroma_shift, v_chroma_shift, block_height; - const int width = s->avctx->width; - 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 == 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); - for (i = 0; i < 3; i++) { - memcpy(s->visualization_buffer[i], pict->data[i], - (i == 0) ? pict->linesize[i] * height: - pict->linesize[i] * height >> v_chroma_shift); - pict->data[i] = s->visualization_buffer[i]; - } - pict->type = FF_BUFFER_TYPE_COPY; - ptr = pict->data[0]; - block_height = 16 >> v_chroma_shift; - - for (mb_y = 0; mb_y < s->mb_height; mb_y++) { - int mb_x; - for (mb_x = 0; mb_x < s->mb_width; mb_x++) { - const int mb_index = mb_x + mb_y * s->mb_stride; - if ((s->avctx->debug_mv) && pict->motion_val) { - int type; - for (type = 0; type < 3; type++) { - int direction = 0; - switch (type) { - case 0: - if ((!(s->avctx->debug_mv & FF_DEBUG_VIS_MV_P_FOR)) || - (pict->pict_type!= AV_PICTURE_TYPE_P)) - continue; - direction = 0; - break; - case 1: - if ((!(s->avctx->debug_mv & FF_DEBUG_VIS_MV_B_FOR)) || - (pict->pict_type!= AV_PICTURE_TYPE_B)) - continue; - direction = 0; - break; - case 2: - if ((!(s->avctx->debug_mv & FF_DEBUG_VIS_MV_B_BACK)) || - (pict->pict_type!= AV_PICTURE_TYPE_B)) - continue; - direction = 1; - break; - } - if (!USES_LIST(pict->mb_type[mb_index], direction)) - continue; - - if (IS_8X8(pict->mb_type[mb_index])) { - int i; - for (i = 0; i < 4; i++) { - int sx = mb_x * 16 + 4 + 8 * (i & 1); - int sy = mb_y * 16 + 4 + 8 * (i >> 1); - int xy = (mb_x * 2 + (i & 1) + - (mb_y * 2 + (i >> 1)) * mv_stride) << (mv_sample_log2 - 1); - int mx = (pict->motion_val[direction][xy][0] >> shift) + sx; - int my = (pict->motion_val[direction][xy][1] >> shift) + sy; - draw_arrow(ptr, sx, sy, mx, my, width, - height, s->linesize, 100); - } - } else if (IS_16X8(pict->mb_type[mb_index])) { - int i; - for (i = 0; i < 2; i++) { - int sx = mb_x * 16 + 8; - int sy = mb_y * 16 + 4 + 8 * i; - int xy = (mb_x * 2 + (mb_y * 2 + i) * mv_stride) << (mv_sample_log2 - 1); - int mx = (pict->motion_val[direction][xy][0] >> shift); - int my = (pict->motion_val[direction][xy][1] >> shift); - - if (IS_INTERLACED(pict->mb_type[mb_index])) - my *= 2; - - draw_arrow(ptr, sx, sy, mx + sx, my + sy, width, - height, s->linesize, 100); - } - } else if (IS_8X16(pict->mb_type[mb_index])) { - int i; - for (i = 0; i < 2; i++) { - int sx = mb_x * 16 + 4 + 8 * i; - int sy = mb_y * 16 + 8; - int xy = (mb_x * 2 + i + mb_y * 2 * mv_stride) << (mv_sample_log2 - 1); - int mx = pict->motion_val[direction][xy][0] >> shift; - int my = pict->motion_val[direction][xy][1] >> shift; - - if (IS_INTERLACED(pict->mb_type[mb_index])) - my *= 2; - - draw_arrow(ptr, sx, sy, mx + sx, my + sy, width, - height, s->linesize, 100); - } - } else { - int sx = mb_x * 16 + 8; - int sy = mb_y * 16 + 8; - int xy = (mb_x + mb_y * mv_stride) << mv_sample_log2; - int mx = pict->motion_val[direction][xy][0] >> shift + sx; - int my = pict->motion_val[direction][xy][1] >> shift + sy; - draw_arrow(ptr, sx, sy, mx, my, width, height, s->linesize, 100); - } - } - } - if ((s->avctx->debug & FF_DEBUG_VIS_QP) && pict->motion_val) { - uint64_t c = (pict->qscale_table[mb_index] * 128 / 31) * - 0x0101010101010101ULL; - int y; - for (y = 0; y < block_height; y++) { - *(uint64_t *)(pict->data[1] + 8 * mb_x + - (block_height * mb_y + y) * - pict->linesize[1]) = c; - *(uint64_t *)(pict->data[2] + 8 * mb_x + - (block_height * mb_y + y) * - pict->linesize[2]) = c; - } - } - if ((s->avctx->debug & FF_DEBUG_VIS_MB_TYPE) && - pict->motion_val) { - int mb_type = pict->mb_type[mb_index]; - uint64_t u,v; - int y; -#define COLOR(theta, r) \ - u = (int)(128 + r * cos(theta * 3.141592 / 180)); \ - v = (int)(128 + r * sin(theta * 3.141592 / 180)); - - - u = v = 128; - if (IS_PCM(mb_type)) { - COLOR(120, 48) - } else if ((IS_INTRA(mb_type) && IS_ACPRED(mb_type)) || - IS_INTRA16x16(mb_type)) { - COLOR(30, 48) - } else if (IS_INTRA4x4(mb_type)) { - COLOR(90, 48) - } else if (IS_DIRECT(mb_type) && IS_SKIP(mb_type)) { - // COLOR(120, 48) - } else if (IS_DIRECT(mb_type)) { - COLOR(150, 48) - } else if (IS_GMC(mb_type) && IS_SKIP(mb_type)) { - COLOR(170, 48) - } else if (IS_GMC(mb_type)) { - COLOR(190, 48) - } else if (IS_SKIP(mb_type)) { - // COLOR(180, 48) - } else if (!USES_LIST(mb_type, 1)) { - COLOR(240, 48) - } else if (!USES_LIST(mb_type, 0)) { - COLOR(0, 48) - } else { - assert(USES_LIST(mb_type, 0) && USES_LIST(mb_type, 1)); - COLOR(300,48) - } - - u *= 0x0101010101010101ULL; - v *= 0x0101010101010101ULL; - for (y = 0; y < block_height; y++) { - *(uint64_t *)(pict->data[1] + 8 * mb_x + - (block_height * mb_y + y) * pict->linesize[1]) = u; - *(uint64_t *)(pict->data[2] + 8 * mb_x + - (block_height * mb_y + y) * pict->linesize[2]) = v; - } - - // segmentation - if (IS_8X8(mb_type) || IS_16X8(mb_type)) { - *(uint64_t *)(pict->data[0] + 16 * mb_x + 0 + - (16 * mb_y + 8) * pict->linesize[0]) ^= 0x8080808080808080ULL; - *(uint64_t *)(pict->data[0] + 16 * mb_x + 8 + - (16 * mb_y + 8) * pict->linesize[0]) ^= 0x8080808080808080ULL; - } - if (IS_8X8(mb_type) || IS_8X16(mb_type)) { - for (y = 0; y < 16; y++) - pict->data[0][16 * mb_x + 8 + (16 * mb_y + y) * - pict->linesize[0]] ^= 0x80; - } - if (IS_8X8(mb_type) && mv_sample_log2 >= 2) { - int dm = 1 << (mv_sample_log2 - 2); - for (i = 0; i < 4; i++) { - int sx = mb_x * 16 + 8 * (i & 1); - int sy = mb_y * 16 + 8 * (i >> 1); - int xy = (mb_x * 2 + (i & 1) + - (mb_y * 2 + (i >> 1)) * mv_stride) << (mv_sample_log2 - 1); - // FIXME bidir - int32_t *mv = (int32_t *) &pict->motion_val[0][xy]; - if (mv[0] != mv[dm] || - mv[dm * mv_stride] != mv[dm * (mv_stride + 1)]) - for (y = 0; y < 8; y++) - pict->data[0][sx + 4 + (sy + y) * pict->linesize[0]] ^= 0x80; - if (mv[0] != mv[dm * mv_stride] || mv[dm] != mv[dm * (mv_stride + 1)]) - *(uint64_t *)(pict->data[0] + sx + (sy + 4) * - pict->linesize[0]) ^= 0x8080808080808080ULL; - } - } - - if (IS_INTERLACED(mb_type) && - s->codec_id == AV_CODEC_ID_H264) { - // hmm - } - } - s->mbskip_table[mb_index] = 0; - } - } - } } /** @@ -1834,7 +1859,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: @@ -1865,7 +1891,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); @@ -1873,7 +1899,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); @@ -1881,7 +1907,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); @@ -1934,7 +1960,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; @@ -1944,20 +1970,18 @@ void MPV_decode_mb_internal(MpegEncContext *s, DCTELEM block[12][64], } if(s->avctx->debug&FF_DEBUG_DCT_COEFF) { - /* save DCT coefficients */ + /* print DCT coefficients */ int i,j; - DCTELEM *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++){ - *dct++ = block[i][s->dsp.idct_permutation[j]]; - av_log(s->avctx, AV_LOG_DEBUG, "%5d", dct[-1]); + av_log(s->avctx, AV_LOG_DEBUG, "%5d", block[i][s->dsp.idct_permutation[j]]); } av_log(s->avctx, AV_LOG_DEBUG, "\n"); } } - s->current_picture.f.qscale_table[mb_xy] = s->qscale; + s->current_picture.qscale_table[mb_xy] = s->qscale; /* update DC predictors for P macroblocks */ if (!s->mb_intra) { @@ -1992,7 +2016,7 @@ void MPV_decode_mb_internal(MpegEncContext *s, DCTELEM block[12][64], s->mb_skipped= 0; assert(s->pict_type!=AV_PICTURE_TYPE_I); *mbskip_ptr = 1; - } else if(!s->current_picture.f.reference) { + } else if(!s->current_picture.reference) { *mbskip_ptr = 1; } else{ *mbskip_ptr = 0; /* not skipped */ @@ -2019,12 +2043,12 @@ void MPV_decode_mb_internal(MpegEncContext *s, DCTELEM block[12][64], if(HAVE_THREADS && s->avctx->active_thread_type&FF_THREAD_FRAME) { if (s->mv_dir & MV_DIR_FORWARD) { - ff_thread_await_progress(&s->last_picture_ptr->f, + ff_thread_await_progress(&s->last_picture_ptr->tf, ff_MPV_lowest_referenced_row(s, 0), 0); } if (s->mv_dir & MV_DIR_BACKWARD) { - ff_thread_await_progress(&s->next_picture_ptr->f, + ff_thread_await_progress(&s->next_picture_ptr->tf, ff_MPV_lowest_referenced_row(s, 1), 0); } @@ -2165,7 +2189,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); @@ -2177,72 +2201,90 @@ 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->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_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]; @@ -2275,6 +2317,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; @@ -2282,12 +2353,8 @@ void ff_mpeg_flush(AVCodecContext *avctx){ if(s==NULL || s->picture==NULL) return; - for(i=0; ipicture_count; i++){ - if (s->picture[i].f.data[0] && - (s->picture[i].f.type == FF_BUFFER_TYPE_INTERNAL || - s->picture[i].f.type == FF_BUFFER_TYPE_USER)) - free_frame_buffer(s, &s->picture[i]); - } + for (i = 0; i < MAX_PICTURE_COUNT; i++) + ff_mpeg_unref_picture(s, &s->picture[i]); s->current_picture_ptr = s->last_picture_ptr = s->next_picture_ptr = NULL; s->mb_x= s->mb_y= 0; @@ -2303,7 +2370,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; @@ -2335,7 +2402,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; @@ -2364,7 +2431,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; @@ -2394,7 +2461,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; @@ -2427,7 +2494,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; @@ -2458,7 +2525,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; @@ -2495,7 +2562,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; @@ -2539,6 +2606,24 @@ 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) - ff_thread_report_progress(&s->current_picture_ptr->f, s->mb_y, 0); + if (s->pict_type != AV_PICTURE_TYPE_B && !s->partitioned_frame && !s->er.error_occurred) + ff_thread_report_progress(&s->current_picture_ptr->tf, s->mb_y, 0); +} + +#if CONFIG_ERROR_RESILIENCE +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); } +#endif /* CONFIG_ERROR_RESILIENCE */