From 3bb4e23a8aa15fc93b91b92d8c6437358fd71113 Mon Sep 17 00:00:00 2001 From: Fabrice Bellard Date: Tue, 24 Jul 2001 20:43:41 +0000 Subject: [PATCH] added skip macroblock optimization (big perf win on black regions for example) Originally committed as revision 13 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavcodec/h263.c | 1 + libavcodec/mpeg12.c | 1 + libavcodec/mpegvideo.c | 31 +++++++++++++++++++++++++++++++ libavcodec/mpegvideo.h | 4 ++++ libavcodec/msmpeg4.c | 1 + 5 files changed, 38 insertions(+) diff --git a/libavcodec/h263.c b/libavcodec/h263.c index 35ecb15c2e..03e4aa381b 100644 --- a/libavcodec/h263.c +++ b/libavcodec/h263.c @@ -738,6 +738,7 @@ int h263_decode_mb(MpegEncContext *s, s->mv_type = MV_TYPE_16X16; s->mv[0][0][0] = 0; s->mv[0][0][1] = 0; + s->mb_skiped = 1; return 0; } cbpc = get_vlc(&s->gb, &inter_MCBPC_vlc); diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c index 5b5411b1d4..e9e1e27e1a 100644 --- a/libavcodec/mpeg12.c +++ b/libavcodec/mpeg12.c @@ -542,6 +542,7 @@ static int mpeg_decode_mb(MpegEncContext *s, s->mv[1][0][0] = s->last_mv[1][0][0]; s->mv[1][0][1] = s->last_mv[1][0][1]; } + s->mb_skiped = 1; return 0; } diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 467062ddf6..dc053de426 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -171,6 +171,13 @@ int MPV_common_init(MpegEncContext *s) s->non_intra_matrix[i] = default_non_intra_matrix[i]; s->chroma_non_intra_matrix[i] = default_non_intra_matrix[i]; } + /* init macroblock skip table */ + if (!s->encoding) { + s->mbskip_table = av_mallocz(s->mb_width * s->mb_height); + if (!s->mbskip_table) + goto fail; + } + s->context_initialized = 1; return 0; fail: @@ -182,6 +189,8 @@ int MPV_common_init(MpegEncContext *s) free(s->ac_val[0]); if (s->coded_block) free(s->coded_block); + if (s->mbskip_table) + free(s->mbskip_table); for(i=0;i<3;i++) { if (s->last_picture_base[i]) free(s->last_picture_base[i]); @@ -205,6 +214,8 @@ void MPV_common_end(MpegEncContext *s) free(s->ac_val[0]); free(s->coded_block); } + if (s->mbskip_table) + free(s->mbskip_table); for(i=0;i<3;i++) { free(s->last_picture_base[i]); free(s->next_picture_base[i]); @@ -276,6 +287,8 @@ int MPV_encode_init(AVCodecContext *avctx) if (s->out_format == FMT_H263) h263_encode_init_vlc(s); + s->encoding = 1; + /* init */ if (MPV_common_init(s) < 0) return -1; @@ -712,6 +725,21 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) if (!s->intra_only) { UINT8 *dest_y, *dest_cb, *dest_cr; + UINT8 *mbskip_ptr; + + /* avoid copy if macroblock skipped in last frame too */ + if (!s->encoding) { + mbskip_ptr = &s->mbskip_table[s->mb_y * s->mb_width + s->mb_x]; + if (s->mb_skiped) { + s->mb_skiped = 0; + /* if previous was skipped too, then nothing to do ! */ + if (*mbskip_ptr != 0) + goto the_end; + *mbskip_ptr = 1; /* indicate that this time we skiped it */ + } else { + *mbskip_ptr = 0; /* not skipped */ + } + } dest_y = s->current_picture[0] + (mb_y * 16 * s->linesize) + mb_x * 16; dest_cb = s->current_picture[1] + (mb_y * 8 * (s->linesize >> 1)) + mb_x * 8; @@ -762,6 +790,8 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) put_dct(s, block[5], 5, dest_cr, dct_linesize >> 1); } } + the_end: + emms_c(); } static void encode_picture(MpegEncContext *s, int picture_number) @@ -885,6 +915,7 @@ static void encode_picture(MpegEncContext *s, int picture_number) ptr = s->last_picture[2] + offset; sub_pixels_2(block[5], ptr, s->linesize >> 1, dxy); } + emms_c(); /* DCT & quantize */ if (s->h263_msmpeg4) { diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index b04d7b7693..a097b01b00 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -44,6 +44,7 @@ typedef struct MpegEncContext { int h263_msmpeg4; /* generate MSMPEG4 compatible stream */ int h263_intel; /* use I263 intel h263 header */ int fixed_qscale; /* fixed qscale if non zero */ + int encoding; /* true if we are encoding (vs decoding) */ /* the following fields are managed internally by the encoder */ /* bit output */ @@ -70,6 +71,9 @@ typedef struct MpegEncContext { UINT8 *coded_block; /* used for coded block pattern prediction */ INT16 (*ac_val[3])[16]; /* used for for mpeg4 AC prediction */ int ac_pred; + int mb_skiped; /* MUST BE SET only during DECODING */ + UINT8 *mbskip_table; /* used to avoid copy if macroblock + skipped (for black regions for example) */ int qscale; int pict_type; diff --git a/libavcodec/msmpeg4.c b/libavcodec/msmpeg4.c index 044d964ee5..ac14da68f3 100644 --- a/libavcodec/msmpeg4.c +++ b/libavcodec/msmpeg4.c @@ -694,6 +694,7 @@ int msmpeg4_decode_mb(MpegEncContext *s, s->mv_type = MV_TYPE_16X16; s->mv[0][0][0] = 0; s->mv[0][0][1] = 0; + s->mb_skiped = 1; return 0; } }