aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2002-09-07 00:16:30 +0000
committerMichael Niedermayer <michaelni@gmx.at>2002-09-07 00:16:30 +0000
commit3db48188df2b406e2972e30e2e341ecb01afe2fd (patch)
treea01e1e43c9064dc660b8e6ec28e7f0d870c89402
parent6ebd933b8f556d40774e81c9c182a1fd99fc6873 (diff)
downloadffmpeg-3db48188df2b406e2972e30e2e341ecb01afe2fd.tar.gz
optimizing mpeg4_encode_block(), generates allso slightly shorter bitstream as some codes can be represented as esc1 and esc2 and esc2 is shorter for a few of them
Originally committed as revision 911 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r--libavcodec/h263.c166
1 files changed, 152 insertions, 14 deletions
diff --git a/libavcodec/h263.c b/libavcodec/h263.c
index 44e54b600a..378ad2a090 100644
--- a/libavcodec/h263.c
+++ b/libavcodec/h263.c
@@ -48,7 +48,7 @@ static void h263_encode_block(MpegEncContext * s, DCTELEM * block,
int n);
static void h263_encode_motion(MpegEncContext * s, int val, int fcode);
static void h263p_encode_umotion(MpegEncContext * s, int val);
-static void mpeg4_encode_block(MpegEncContext * s, DCTELEM * block,
+static inline void mpeg4_encode_block(MpegEncContext * s, DCTELEM * block,
int n, int dc, UINT8 *scan_table,
PutBitContext *dc_pb, PutBitContext *ac_pb);
static int h263_decode_motion(MpegEncContext * s, int pred, int fcode);
@@ -71,6 +71,22 @@ static UINT8 umv_fcode_tab[MAX_MV*2+1];
static UINT16 uni_DCtab_lum [512][2];
static UINT16 uni_DCtab_chrom[512][2];
+static UINT32 uni_mpeg4_intra_rl_bits[64*64*2*2];
+static UINT8 uni_mpeg4_intra_rl_len [64*64*2*2];
+static UINT32 uni_mpeg4_inter_rl_bits[64*64*2*2];
+static UINT8 uni_mpeg4_inter_rl_len [64*64*2*2];
+#define UNI_MPEG4_ENC_INDEX(last,run,level) ((last)*128 + (run)*256 + (level))
+//#define UNI_MPEG4_ENC_INDEX(last,run,level) ((last)*128*64 + (run) + (level)*64)
+
+/* mpeg4
+inter
+max level: 24/6
+max run: 53/63
+
+intra
+max level: 53/16
+max run: 29/41
+*/
int h263_get_picture_format(int width, int height)
{
@@ -1085,6 +1101,91 @@ static void init_uni_dc_tab(void)
}
}
+static void init_uni_mpeg4_rl_tab(RLTable *rl, UINT32 *bits_tab, UINT8 *len_tab){
+ int slevel, run, last;
+
+ assert(MAX_LEVEL >= 64);
+ assert(MAX_RUN >= 63);
+
+ for(slevel=-64; slevel<64; slevel++){
+ if(slevel==0) continue;
+ for(run=0; run<64; run++){
+ for(last=0; last<=1; last++){
+ const int index= UNI_MPEG4_ENC_INDEX(last, run, slevel+64);
+ int level= slevel < 0 ? -slevel : slevel;
+ int sign= slevel < 0 ? 1 : 0;
+ int bits, len, code;
+ int level1, run1;
+
+ len_tab[index]= 100;
+
+ /* ESC0 */
+ code= get_rl_index(rl, last, run, level);
+ bits= rl->table_vlc[code][0];
+ len= rl->table_vlc[code][1];
+ bits=bits*2+sign; len++;
+
+ if(code!=rl->n && len < len_tab[index]){
+ bits_tab[index]= bits;
+ len_tab [index]= len;
+ }
+#if 1
+ /* ESC1 */
+ bits= rl->table_vlc[rl->n][0];
+ len= rl->table_vlc[rl->n][1];
+ bits=bits*2; len++; //esc1
+ level1= level - rl->max_level[last][run];
+ if(level1>0){
+ code= get_rl_index(rl, last, run, level1);
+ bits<<= rl->table_vlc[code][1];
+ len += rl->table_vlc[code][1];
+ bits += rl->table_vlc[code][0];
+ bits=bits*2+sign; len++;
+
+ if(code!=rl->n && len < len_tab[index]){
+ bits_tab[index]= bits;
+ len_tab [index]= len;
+ }
+ }
+#endif
+#if 1
+ /* ESC2 */
+ bits= rl->table_vlc[rl->n][0];
+ len= rl->table_vlc[rl->n][1];
+ bits=bits*4+2; len+=2; //esc2
+ run1 = run - rl->max_run[last][level] - 1;
+ if(run1>=0){
+ code= get_rl_index(rl, last, run1, level);
+ bits<<= rl->table_vlc[code][1];
+ len += rl->table_vlc[code][1];
+ bits += rl->table_vlc[code][0];
+ bits=bits*2+sign; len++;
+
+ if(code!=rl->n && len < len_tab[index]){
+ bits_tab[index]= bits;
+ len_tab [index]= len;
+ }
+ }
+#endif
+ /* ESC3 */
+ bits= rl->table_vlc[rl->n][0];
+ len = rl->table_vlc[rl->n][1];
+ bits=bits*4+3; len+=2; //esc3
+ bits=bits*2+last; len++;
+ bits=bits*64+run; len+=6;
+ bits=bits*2+1; len++; //marker
+ bits=bits*4096+(slevel&0xfff); len+=12;
+ bits=bits*2+1; len++; //marker
+
+ if(len < len_tab[index]){
+ bits_tab[index]= bits;
+ len_tab [index]= len;
+ }
+ }
+ }
+ }
+}
+
void h263_encode_init(MpegEncContext *s)
{
static int done = 0;
@@ -1097,6 +1198,9 @@ void h263_encode_init(MpegEncContext *s)
init_rl(&rl_inter);
init_rl(&rl_intra);
init_rl(&rl_intra_aic);
+
+ init_uni_mpeg4_rl_tab(&rl_intra, uni_mpeg4_intra_rl_bits, uni_mpeg4_intra_rl_len);
+ init_uni_mpeg4_rl_tab(&rl_inter, uni_mpeg4_inter_rl_bits, uni_mpeg4_inter_rl_len);
init_mv_penalty_and_fcode(s);
}
@@ -1529,34 +1633,69 @@ static inline void mpeg4_encode_dc(PutBitContext * s, int level, int n)
#endif
}
-static void mpeg4_encode_block(MpegEncContext * s, DCTELEM * block, int n, int intra_dc,
+static inline void mpeg4_encode_block(MpegEncContext * s, DCTELEM * block, int n, int intra_dc,
UINT8 *scan_table, PutBitContext *dc_pb, PutBitContext *ac_pb)
{
- int level, run, last, i, j, last_index, last_non_zero, sign, slevel;
+ int last, i, last_non_zero, sign;
int code;
const RLTable *rl;
+ UINT32 *bits_tab;
+ UINT8 *len_tab;
+ const int last_index = s->block_last_index[n];
- if (s->mb_intra) {
+ if (s->mb_intra) { //Note gcc (3.2.1 at least) will optimize this away
/* mpeg4 based DC predictor */
mpeg4_encode_dc(dc_pb, intra_dc, n);
+ if(last_index<1) return;
i = 1;
rl = &rl_intra;
+ bits_tab= uni_mpeg4_intra_rl_bits;
+ len_tab = uni_mpeg4_intra_rl_len;
} else {
+ if(last_index<0) return;
i = 0;
rl = &rl_inter;
+ bits_tab= uni_mpeg4_inter_rl_bits;
+ len_tab = uni_mpeg4_inter_rl_len;
}
/* AC coefs */
- last_index = s->block_last_index[n];
last_non_zero = i - 1;
- for (; i <= last_index; i++) {
- j = scan_table[i];
- level = block[j];
+#if 1
+ for (; i < last_index; i++) {
+ int level = block[ scan_table[i] ];
if (level) {
- run = i - last_non_zero - 1;
+ int run = i - last_non_zero - 1;
+ level+=64;
+ if((level&(~127)) == 0){
+ const int index= UNI_MPEG4_ENC_INDEX(0, run, level);
+ put_bits(ac_pb, len_tab[index], bits_tab[index]);
+ }else{ //ESC3
+ put_bits(ac_pb, 7+2+1+6+1+12+1, (3<<23)+(3<<21)+(0<<20)+(run<<14)+(1<<13)+(((level-64)&0xfff)<<1)+1);
+ }
+ last_non_zero = i;
+ }
+ }
+ /*if(i<=last_index)*/{
+ int level = block[ scan_table[i] ];
+ int run = i - last_non_zero - 1;
+ level+=64;
+ if((level&(~127)) == 0){
+ const int index= UNI_MPEG4_ENC_INDEX(1, run, level);
+ put_bits(ac_pb, len_tab[index], bits_tab[index]);
+ }else{ //ESC3
+ put_bits(ac_pb, 7+2+1+6+1+12+1, (3<<23)+(3<<21)+(1<<20)+(run<<14)+(1<<13)+(((level-64)&0xfff)<<1)+1);
+ }
+ }
+#else
+ for (; i <= last_index; i++) {
+ const int slevel = block[ scan_table[i] ];
+ if (slevel) {
+ int level;
+ int run = i - last_non_zero - 1;
last = (i == last_index);
sign = 0;
- slevel = level;
+ level = slevel;
if (level < 0) {
sign = 1;
level = -level;
@@ -1605,6 +1744,7 @@ static void mpeg4_encode_block(MpegEncContext * s, DCTELEM * block, int n, int i
last_non_zero = i;
}
}
+#endif
}
@@ -3831,7 +3971,7 @@ int mpeg4_decode_picture_header(MpegEncContext * s)
printf("low_delay flag set, but shouldnt, clearing it\n");
s->low_delay=0;
}
-// printf("pic: %d, qpel:%d\n", s->pict_type, s->quarter_sample);
+// printf("pic: %d, qpel:%d part:%d resync:%d\n", s->pict_type, s->quarter_sample, s->data_partitioning, s->resync_marker);
time_incr=0;
while (get_bits1(&s->gb) != 0)
time_incr++;
@@ -3935,11 +4075,10 @@ int mpeg4_decode_picture_header(MpegEncContext * s)
if (s->pict_type == B_TYPE) {
s->b_code = get_bits(&s->gb, 3);
-//printf("b-code %d\n", s->b_code);
}else
s->b_code=1;
-//printf("quant:%d fcode:%d bcode:%d type:%d\n", s->qscale, s->f_code, s->b_code, s->pict_type);
+//printf("quant:%d fcode:%d bcode:%d type:%d size:%d\n", s->qscale, s->f_code, s->b_code, s->pict_type, s->gb.size);
if(!s->scalability){
if (s->shape!=RECT_SHAPE && s->pict_type!=I_TYPE) {
skip_bits1(&s->gb); // vop shape coding type
@@ -3962,7 +4101,6 @@ int mpeg4_decode_picture_header(MpegEncContext * s)
}
s->picture_number++; // better than pic number==0 allways ;)
-//printf("done\n");
s->y_dc_scale_table= ff_mpeg4_y_dc_scale_table; //FIXME add short header support
s->c_dc_scale_table= ff_mpeg4_c_dc_scale_table;