diff --git a/ffplay.c b/ffplay.c index bfff450cdf..ff655f7868 100644 --- a/ffplay.c +++ b/ffplay.c @@ -170,6 +170,7 @@ static int debug_mv = 0; static int step = 0; static int thread_count = 1; static int workaround_bugs = 1; +static int fast = 0; /* current context */ static int is_full_screen; @@ -1172,6 +1173,7 @@ static int stream_component_open(VideoState *is, int stream_index) enc->debug_mv = debug_mv; enc->debug = debug; enc->workaround_bugs = workaround_bugs; + if(fast) enc->flags2 |= CODEC_FLAG2_FAST; if (!codec || avcodec_open(enc, codec) < 0) return -1; @@ -1829,6 +1831,7 @@ const OptionDef options[] = { { "debug", HAS_ARG | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" }, { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" }, { "vismv", HAS_ARG | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" }, + { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" }, #ifdef CONFIG_NETWORK { "rtp_tcp", OPT_EXPERT, {(void*)&opt_rtp_tcp}, "force RTP/TCP protocol usage", "" }, #endif diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index e2da0f85a2..76bc946f3a 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -283,6 +283,8 @@ extern int motion_estimation_method; #define CODEC_FLAG_INTERLACED_ME 0x20000000 ///< interlaced motion estimation #define CODEC_FLAG_SVCD_SCAN_OFFSET 0x40000000 ///< will reserve space for SVCD scan offset user data #define CODEC_FLAG_CLOSED_GOP 0x80000000 +#define CODEC_FLAG2_FAST 0x00000001 ///< allow non spec compliant speedup tricks + /* Unsupported options : * Syntax Arithmetic coding (SAC) * Reference Picture Selection diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c index 1c8a6e2bfa..c31efad402 100644 --- a/libavcodec/mpeg12.c +++ b/libavcodec/mpeg12.c @@ -70,6 +70,7 @@ static inline int mpeg2_decode_block_non_intra(MpegEncContext *s, static inline int mpeg2_decode_block_intra(MpegEncContext *s, DCTELEM *block, int n); +static inline int mpeg2_fast_decode_block_non_intra(MpegEncContext *s, DCTELEM *block, int n); static int mpeg_decode_motion(MpegEncContext *s, int fcode, int pred); static void exchange_uv(MpegEncContext *s); @@ -1358,16 +1359,27 @@ static int mpeg_decode_mb(MpegEncContext *s, #endif if (s->codec_id == CODEC_ID_MPEG2VIDEO) { - cbp<<= 12-mb_block_count; - - for(i=0;ipblocks[i], i) < 0) - return -1; - } else { - s->block_last_index[i] = -1; + if(s->flags2 & CODEC_FLAG2_FAST){ + for(i=0;i<6;i++) { + if(cbp & 32) { + mpeg2_fast_decode_block_non_intra(s, s->pblocks[i], i); + } else { + s->block_last_index[i] = -1; + } + cbp+=cbp; + } + }else{ + cbp<<= 12-mb_block_count; + + for(i=0;ipblocks[i], i) < 0) + return -1; + } else { + s->block_last_index[i] = -1; + } + cbp+=cbp; } - cbp+=cbp; } } else { for(i=0;i<6;i++) { @@ -1592,8 +1604,6 @@ static inline int mpeg1_decode_block_inter(MpegEncContext *s, return 0; } -/* Also does unquantization here, since I will never support mpeg2 - encoding */ static inline int mpeg2_decode_block_non_intra(MpegEncContext *s, DCTELEM *block, int n) @@ -1673,6 +1683,67 @@ static inline int mpeg2_decode_block_non_intra(MpegEncContext *s, return 0; } +static inline int mpeg2_fast_decode_block_non_intra(MpegEncContext *s, + DCTELEM *block, + int n) +{ + int level, i, j, run; + RLTable *rl = &rl_mpeg1; + uint8_t * const scantable= s->intra_scantable.permutated; + const int qscale= s->qscale; + int v; + OPEN_READER(re, &s->gb); + i = -1; + + /* special case for the first coef. no need to add a second vlc table */ + UPDATE_CACHE(re, &s->gb); + v= SHOW_UBITS(re, &s->gb, 2); + if (v & 2) { + LAST_SKIP_BITS(re, &s->gb, 2); + level= (3*qscale)>>1; + if(v&1) + level= -level; + block[0] = level; + i++; + } + + /* now quantify & encode AC coefs */ + for(;;) { + UPDATE_CACHE(re, &s->gb); + GET_RL_VLC(level, run, re, &s->gb, rl->rl_vlc[0], TEX_VLC_BITS, 2); + + if(level == 127){ + break; + } else if(level != 0) { + i += run; + j = scantable[i]; + level= ((level*2+1)*qscale)>>1; + level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); + LAST_SKIP_BITS(re, &s->gb, 1); + } else { + /* escape */ + run = SHOW_UBITS(re, &s->gb, 6)+1; LAST_SKIP_BITS(re, &s->gb, 6); + UPDATE_CACHE(re, &s->gb); + level = SHOW_SBITS(re, &s->gb, 12); SKIP_BITS(re, &s->gb, 12); + + i += run; + j = scantable[i]; + if(level<0){ + level= ((-level*2+1)*qscale)>>1; + level= -level; + }else{ + level= ((level*2+1)*qscale)>>1; + } + } + + block[j] = level; + } + CLOSE_READER(re, &s->gb); + s->block_last_index[n] = i; + return 0; +} + + static inline int mpeg2_decode_block_intra(MpegEncContext *s, DCTELEM *block, int n)