From c619ff6daf93a8f3c03decf2d3345d2474c3db91 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 30 Aug 2005 20:03:19 +0000 Subject: [PATCH] optimizations dc coeff rounding fix class=3 num of bits fix do interlaced check & idct only if CODEC_FLAG_INTERLACED_DCT Originally committed as revision 4542 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavcodec/dv.c | 196 +++++++++++++++++++--------------- tests/ffmpeg.regression.ref | 6 +- tests/rotozoom.regression.ref | 6 +- 3 files changed, 117 insertions(+), 91 deletions(-) diff --git a/libavcodec/dv.c b/libavcodec/dv.c index 1cfdae65b2..f661689c3d 100644 --- a/libavcodec/dv.c +++ b/libavcodec/dv.c @@ -34,9 +34,13 @@ #include "simple_idct.h" #include "dvdata.h" +//#undef NDEBUG +//#include + typedef struct DVVideoContext { const DVprofile* sys; AVFrame picture; + AVCodecContext *avctx; uint8_t *buf; uint8_t dv_zigzag[2][64]; @@ -54,7 +58,7 @@ typedef struct DVVideoContext { #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 @@ static int dvvideo_init(AVCodecContext *avctx) 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 @@ static void dv_decode_ac(GetBitContext *gb, BlockInfo *mb, DCTELEM *block) 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 void dv_decode_ac(GetBitContext *gb, BlockInfo *mb, DCTELEM *block) 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 @@ static inline void dv_decode_video_segment(DVVideoContext *s, 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 @@ static inline void dv_decode_video_segment(DVVideoContext *s, #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 @@ static always_inline int dv_rl2vlc(int run, int l, uint32_t* vlc) 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 @@ static always_inline int dv_rl2vlc_size(int run, int l) 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 @@ vlc_loop: put_bits(pb, bits_left, vlc >> size); vlc = vlc & ((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; - } - } - - if (bi->cur_ac == 64) { + 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 */ - 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]; imb[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 (; inext[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 always_inline int dv_guess_dct_mode(DCTELEM *blk) { 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 @@ static inline void dv_guess_qnos(EncBlockInfo* blks, int* qnos) 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]; kmb[k] /= 2; + prev= b->prev[a]; + for (k= b->next[prev] ; knext[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 @@ static inline void dv_encode_video_segment(DVVideoContext *s, 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 @@ static inline void dv_encode_video_segment(DVVideoContext *s, 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 @@ static inline void dv_encode_video_segment(DVVideoContext *s, /* 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++) diff --git a/tests/ffmpeg.regression.ref b/tests/ffmpeg.regression.ref index bd5f1980f1..3c102d528b 100644 --- a/tests/ffmpeg.regression.ref +++ b/tests/ffmpeg.regression.ref @@ -127,10 +127,10 @@ de8eac1454746a37eae0b1ff88c0f849 *./data/a-snow53.avi 3535414 ./data/a-snow53.avi 799d3db687f6cdd7a837ec156efc171f *./data/out.yuv stddev: 0.00 PSNR:99.99 bytes:7602176 -6f80191e31d7ebe1aebde0a7b8a6d12c *./data/a-dv.dv +e1da20e3f52f4d2aa18e9486986161fc *./data/a-dv.dv 7200000 ./data/a-dv.dv -5d4e7b87003931ed0de6b02538e4e5d1 *./data/out.yuv -stddev: 9.25 PSNR:28.80 bytes:7602176 +55612d1a7246c82a32414638d601ac95 *./data/out.yuv +stddev: 9.15 PSNR:28.88 bytes:7602176 b5b6275f58f012de73644bbaa9080097 *./data/a-svq1.mov 1383999 ./data/a-svq1.mov ccc201054669e94717022bb4f2aea4ce *./data/out.yuv diff --git a/tests/rotozoom.regression.ref b/tests/rotozoom.regression.ref index dd087403cf..35e12db928 100644 --- a/tests/rotozoom.regression.ref +++ b/tests/rotozoom.regression.ref @@ -127,10 +127,10 @@ d0a8bdb25d7ed641eab0debcac396eb7 *./data/a-snow53.avi 2725842 ./data/a-snow53.avi dde5895817ad9d219f79a52d0bdfb001 *./data/out.yuv stddev: 0.00 PSNR:99.99 bytes:7602176 -feb77e60f0d3c4cb6856a949cf135f21 *./data/a-dv.dv +a553532dcd54c1c421b52c3b6fece6ef *./data/a-dv.dv 7200000 ./data/a-dv.dv -8d6956ba685c53e97dd2a7501d2fe917 *./data/out.yuv -stddev: 3.33 PSNR:37.66 bytes:7602176 +1a1717b271a7536d641d5e1750d852d9 *./data/out.yuv +stddev: 3.16 PSNR:38.12 bytes:7602176 920c610ec324b772d882b0717e375943 *./data/a-svq1.mov 768683 ./data/a-svq1.mov 89b1946242e6998e05fc9a6e09668edd *./data/out.yuv