Mercurial > libavcodec.hg
changeset 2847:712c84b9d8ce libavcodec
optimizations
dc coeff rounding fix
class=3 num of bits fix
do interlaced check & idct only if CODEC_FLAG_INTERLACED_DCT
author | michael |
---|---|
date | Tue, 30 Aug 2005 20:03:19 +0000 |
parents | 40765c51a7a9 |
children | 78ad77267785 |
files | dv.c |
diffstat | 1 files changed, 112 insertions(+), 86 deletions(-) [+] |
line wrap: on
line diff
--- a/dv.c Fri Aug 26 19:05:44 2005 +0000 +++ b/dv.c Tue Aug 30 20:03:19 2005 +0000 @@ -34,9 +34,13 @@ #include "simple_idct.h" #include "dvdata.h" +//#undef NDEBUG +//#include <assert.h> + typedef struct DVVideoContext { const DVprofile* sys; AVFrame picture; + AVCodecContext *avctx; uint8_t *buf; uint8_t dv_zigzag[2][64]; @@ -54,7 +58,7 @@ #define DV_VLC_MAP_LEV_SIZE 23 #else #define DV_VLC_MAP_RUN_SIZE 64 -#define DV_VLC_MAP_LEV_SIZE 512 +#define DV_VLC_MAP_LEV_SIZE 512 //FIXME sign was removed so this should be /2 but needs check #endif /* MultiThreading */ @@ -233,6 +237,7 @@ if (dv_codec_profile(avctx)) avctx->pix_fmt = dv_codec_profile(avctx)->pix_fmt; avctx->coded_frame = &s->picture; + s->avctx= avctx; return 0; } @@ -332,10 +337,9 @@ if (pos >= 64) break; - if (level) { - pos1 = scan_table[pos]; - block[pos1] = level << shift_table[pos1]; - } + assert(level); + pos1 = scan_table[pos]; + block[pos1] = level << shift_table[pos1]; UPDATE_CACHE(re, gb); } @@ -346,9 +350,9 @@ static inline void bit_copy(PutBitContext *pb, GetBitContext *gb) { int bits_left = get_bits_left(gb); - while (bits_left >= 16) { - put_bits(pb, 16, get_bits(gb, 16)); - bits_left -= 16; + while (bits_left >= MIN_CACHE_BITS) { + put_bits(pb, MIN_CACHE_BITS, get_bits(gb, MIN_CACHE_BITS)); + bits_left -= MIN_CACHE_BITS; } if (bits_left > 0) { put_bits(pb, bits_left, get_bits(gb, bits_left)); @@ -371,9 +375,12 @@ GetBitContext gb; BlockInfo mb_data[5 * 6], *mb, *mb1; DCTELEM sblock[5*6][64] __align8; - uint8_t mb_bit_buffer[80 + 4]; /* allow some slack */ - uint8_t vs_bit_buffer[5 * 80 + 4]; /* allow some slack */ + uint8_t mb_bit_buffer[80 + 4] __align8; /* allow some slack */ + uint8_t vs_bit_buffer[5 * 80 + 4] __align8; /* allow some slack */ + assert((((int)mb_bit_buffer)&7)==0); + assert((((int)vs_bit_buffer)&7)==0); + memset(sblock, 0, sizeof(sblock)); /* pass 1 : read DC and AC coefficients in blocks */ @@ -525,14 +532,9 @@ #ifdef DV_CODEC_TINY_TARGET /* Converts run and level (where level != 0) pair into vlc, returning bit size */ -static always_inline int dv_rl2vlc(int run, int l, uint32_t* vlc) +static always_inline int dv_rl2vlc(int run, int level, int sign, uint32_t* vlc) { - int sign = l >> 8; - int level = (l ^ sign) - sign; int size; - - sign = (sign & 1); - if (run < DV_VLC_MAP_RUN_SIZE && level < DV_VLC_MAP_LEV_SIZE) { *vlc = dv_vlc_map[run][level].vlc | sign; size = dv_vlc_map[run][level].size; @@ -555,9 +557,8 @@ return size; } -static always_inline int dv_rl2vlc_size(int run, int l) +static always_inline int dv_rl2vlc_size(int run, int level) { - int level = (l ^ (l >> 8)) - (l >> 8); int size; if (run < DV_VLC_MAP_RUN_SIZE && level < DV_VLC_MAP_LEV_SIZE) { @@ -572,41 +573,43 @@ return size; } #else -static always_inline int dv_rl2vlc(int run, int l, uint32_t* vlc) +static always_inline int dv_rl2vlc(int run, int l, int sign, uint32_t* vlc) { - *vlc = dv_vlc_map[run][((uint16_t)l)&0x1ff].vlc; - return dv_vlc_map[run][((uint16_t)l)&0x1ff].size; + *vlc = dv_vlc_map[run][l].vlc | sign; + return dv_vlc_map[run][l].size; } static always_inline int dv_rl2vlc_size(int run, int l) { - return dv_vlc_map[run][((uint16_t)l)&0x1ff].size; + return dv_vlc_map[run][l].size; } #endif typedef struct EncBlockInfo { int area_q[4]; int bit_size[4]; - int prev_run[4]; + int prev[5]; int cur_ac; int cno; int dct_mode; - DCTELEM *mb; + DCTELEM mb[64]; + uint8_t next[64]; + uint8_t sign[64]; uint8_t partial_bit_count; uint32_t partial_bit_buffer; /* we can't use uint16_t here */ } EncBlockInfo; -static always_inline void dv_encode_ac(EncBlockInfo* bi, PutBitContext* pb_pool, - int pb_size) +static always_inline PutBitContext* dv_encode_ac(EncBlockInfo* bi, PutBitContext* pb_pool, + PutBitContext* pb_end) { - int run; + int prev; int bits_left; PutBitContext* pb = pb_pool; int size = bi->partial_bit_count; uint32_t vlc = bi->partial_bit_buffer; - + bi->partial_bit_count = bi->partial_bit_buffer = 0; -vlc_loop: + for(;;){ /* Find suitable storage space */ for (; size > (bits_left = put_bits_left(pb)); pb++) { if (bits_left) { @@ -614,69 +617,84 @@ put_bits(pb, bits_left, vlc >> size); vlc = vlc & ((1<<size)-1); } - if (pb_size == 1) { + if (pb + 1 >= pb_end) { bi->partial_bit_count = size; bi->partial_bit_buffer = vlc; - return; + return pb; } - --pb_size; } /* Store VLC */ put_bits(pb, size, vlc); + if(bi->cur_ac>=64) + break; + /* Construct the next VLC */ - run = 0; - for (; bi->cur_ac < 64; bi->cur_ac++, run++) { - if (bi->mb[bi->cur_ac]) { - size = dv_rl2vlc(run, bi->mb[bi->cur_ac], &vlc); - bi->cur_ac++; - goto vlc_loop; - } + prev= bi->cur_ac; + bi->cur_ac = bi->next[prev]; + if(bi->cur_ac < 64){ + size = dv_rl2vlc(bi->cur_ac - prev - 1, bi->mb[bi->cur_ac], bi->sign[bi->cur_ac], &vlc); + } else { + size = 4; vlc = 6; /* End Of Block stamp */ } - - if (bi->cur_ac == 64) { - size = 4; vlc = 6; /* End Of Block stamp */ - bi->cur_ac++; - goto vlc_loop; - } + } + return pb; } static always_inline void dv_set_class_number(DCTELEM* blk, EncBlockInfo* bi, const uint8_t* zigzag_scan, int bias) { int i, area; - int run; - int classes[] = {12, 24, 36, 0xffff}; + static const int classes[] = {12, 24, 36, 0xffff}; + int max=12; + int prev=0; - run = 0; bi->mb[0] = blk[0]; - bi->cno = 0; + for (area = 0; area < 4; area++) { - bi->prev_run[area] = run; - bi->bit_size[area] = 0; + bi->prev[area] = prev; + bi->bit_size[area] = 1; // 4 areas 4 bits for EOB :) for (i=mb_area_start[area]; i<mb_area_start[area+1]; i++) { - bi->mb[i] = (blk[zigzag_scan[i]] / 16); - while ((bi->mb[i] ^ (bi->mb[i] >> 8)) > classes[bi->cno]) - bi->cno++; + int level = blk[zigzag_scan[i]]; - if (bi->mb[i]) { - bi->bit_size[area] += dv_rl2vlc_size(run, bi->mb[i]); - run = 0; - } else - ++run; + if (level+15 > 30U) { + bi->sign[i] = (level>>31)&1; + bi->mb[i] = level= ABS(level)>>4; + if(level>max) max= level; + bi->bit_size[area] += dv_rl2vlc_size(i - prev - 1, level); + bi->next[prev]= i; + prev= i; + } } } - bi->bit_size[3] += 4; /* EOB marker */ + bi->next[prev]= i; + for(bi->cno = 0; max > classes[bi->cno]; bi->cno++); + bi->cno += bias; - if (bi->cno >= 3) { /* FIXME: we have to recreate bit_size[], prev_run[] */ + if (bi->cno >= 3) { bi->cno = 3; - for (i=1; i<64; i++) - bi->mb[i] /= 2; + prev=0; + i= bi->next[prev]; + for (area = 0; area < 4; area++) { + bi->prev[area] = prev; + bi->bit_size[area] = 1; // 4 areas 4 bits for EOB :) + for (; i<mb_area_start[area+1]; i= bi->next[i]) { + bi->mb[i] >>=1; + + if (bi->mb[i]) { + bi->bit_size[area] += dv_rl2vlc_size(i - prev - 1, bi->mb[i]); + bi->next[prev]= i; + prev= i; + } + } + } + bi->next[prev]= i; } } +//FIXME replace this by dsputil #define SC(x, y) ((s[x] - s[y]) ^ ((s[x] - s[y]) >> 7)) static always_inline int dv_guess_dct_mode(DCTELEM *blk) { DCTELEM *s; @@ -705,9 +723,9 @@ static inline void dv_guess_qnos(EncBlockInfo* blks, int* qnos) { int size[5]; - int i, j, k, a, run; + int i, j, k, a, prev; EncBlockInfo* b; - + do { b = blks; for (i=0; i<5; i++) { @@ -719,17 +737,19 @@ for (j=0; j<6; j++, b++) { for (a=0; a<4; a++) { if (b->area_q[a] != dv_quant_shifts[qnos[i] + dv_quant_offset[b->cno]][a]) { - b->bit_size[a] = (a==3)?4:0; + b->bit_size[a] = 1; // 4 areas 4 bits for EOB :) b->area_q[a]++; - run = b->prev_run[a]; - for (k=mb_area_start[a]; k<mb_area_start[a+1]; k++) { - b->mb[k] /= 2; + prev= b->prev[a]; + for (k= b->next[prev] ; k<mb_area_start[a+1]; k= b->next[k]) { + b->mb[k] >>= 1; if (b->mb[k]) { - b->bit_size[a] += dv_rl2vlc_size(run, b->mb[k]); - run = 0; - } else - ++run; + b->bit_size[a] += dv_rl2vlc_size(k - prev - 1, b->mb[k]); + prev= k; + } else { + b->next[prev] = b->next[k]; + } } + b->prev[a+1]= prev; } size[i] += b->bit_size[a]; } @@ -755,13 +775,14 @@ uint8_t* ptr; int do_edge_wrap; DCTELEM block[64] __align8; - DCTELEM sblock[5*6][64] __align8; EncBlockInfo enc_blks[5*6]; PutBitContext pbs[5*6]; PutBitContext* pb; EncBlockInfo* enc_blk; int vs_bit_size = 0; int qnos[5]; + + assert((((int)block) & 7) == 0); enc_blk = &enc_blks[0]; pb = &pbs[0]; @@ -808,21 +829,22 @@ s->get_pixels(block, data, linesize); } - enc_blk->dct_mode = dv_guess_dct_mode(block); - enc_blk->mb = &sblock[mb_index*6+j][0]; + if(s->avctx->flags & CODEC_FLAG_INTERLACED_DCT) + enc_blk->dct_mode = dv_guess_dct_mode(block); + else + enc_blk->dct_mode = 0; enc_blk->area_q[0] = enc_blk->area_q[1] = enc_blk->area_q[2] = enc_blk->area_q[3] = 0; enc_blk->partial_bit_count = 0; enc_blk->partial_bit_buffer = 0; - enc_blk->cur_ac = 1; + enc_blk->cur_ac = 0; s->fdct[enc_blk->dct_mode](block); dv_set_class_number(block, enc_blk, - enc_blk->dct_mode ? ff_zigzag248_direct : ff_zigzag_direct, - j/4*(j%2)); + enc_blk->dct_mode ? ff_zigzag248_direct : ff_zigzag_direct, j/4); init_put_bits(pb, ptr, block_sizes[j]/8); - put_bits(pb, 9, (uint16_t)(((enc_blk->mb[0] >> 3) - 1024) >> 2)); + put_bits(pb, 9, (uint16_t)(((enc_blk->mb[0] >> 3) - 1024 + 2) >> 2)); put_bits(pb, 1, enc_blk->dct_mode); put_bits(pb, 2, enc_blk->cno); @@ -843,18 +865,22 @@ /* First pass over individual cells only */ for (j=0; j<5*6; j++) - dv_encode_ac(&enc_blks[j], &pbs[j], 1); + dv_encode_ac(&enc_blks[j], &pbs[j], &pbs[j+1]); /* Second pass over each MB space */ - for (j=0; j<5*6; j++) { - if (enc_blks[j].cur_ac < 65 || enc_blks[j].partial_bit_count) - dv_encode_ac(&enc_blks[j], &pbs[(j/6)*6], 6); + for (j=0; j<5*6; j+=6) { + pb= &pbs[j]; + for (i=0; i<6; i++) { + if (enc_blks[i+j].partial_bit_count) + pb=dv_encode_ac(&enc_blks[i+j], pb, &pbs[j+6]); + } } /* Third and final pass over the whole vides segment space */ + pb= &pbs[0]; for (j=0; j<5*6; j++) { - if (enc_blks[j].cur_ac < 65 || enc_blks[j].partial_bit_count) - dv_encode_ac(&enc_blks[j], &pbs[0], 6*5); + if (enc_blks[j].partial_bit_count) + pb=dv_encode_ac(&enc_blks[j], pb, &pbs[6*5]); } for (j=0; j<5*6; j++)