diff options
author | Roman Shaposhnik <roman@shaposhnik.org> | 2003-10-24 18:28:01 +0000 |
---|---|---|
committer | Roman Shaposhnik <roman@shaposhnik.org> | 2003-10-24 18:28:01 +0000 |
commit | 10acc47995831802501d0dbb9aab4ba7f91cbcfb (patch) | |
tree | 845c52c076f79526aaaed3ad815056d1b0835715 /libavcodec/dv.c | |
parent | 01a2ddaf85037db70ae73efe1fcc74e148313523 (diff) | |
download | ffmpeg-10acc47995831802501d0dbb9aab4ba7f91cbcfb.tar.gz |
* introducing dct248 into the DSP context.
* simple/accurate implementation of dct248
* DV encoding now supports 2-4-8 DCT
* DV encoding gets a bit faster (but still miles away
from what I think it could do)
* misc. DV codec cleanups
Originally committed as revision 2425 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/dv.c')
-rw-r--r-- | libavcodec/dv.c | 135 |
1 files changed, 76 insertions, 59 deletions
diff --git a/libavcodec/dv.c b/libavcodec/dv.c index c969e937ba..23f12917f6 100644 --- a/libavcodec/dv.c +++ b/libavcodec/dv.c @@ -35,19 +35,18 @@ typedef struct DVVideoDecodeContext { const DVprofile* sys; - GetBitContext gb; AVFrame picture; - DCTELEM block[5*6][64] __align8; - /* FIXME: the following is extracted from DSP */ uint8_t dv_zigzag[2][64]; - uint8_t idct_permutation[64]; + uint8_t dv_idct_shift[2][22][64]; + uint8_t dv_dct_shift[2][22][64]; + void (*get_pixels)(DCTELEM *block, const uint8_t *pixels, int line_size); - void (*fdct)(DCTELEM *block); - - /* XXX: move it to static storage ? */ - uint8_t dv_shift[2][22][64]; + void (*fdct[2])(DCTELEM *block); void (*idct_put[2])(uint8_t *dest, int line_size, DCTELEM *block); + + GetBitContext gb; + DCTELEM block[5*6][64] __align8; } DVVideoDecodeContext; #define TEX_VLC_BITS 9 @@ -55,25 +54,29 @@ typedef struct DVVideoDecodeContext { static RL_VLC_ELEM *dv_rl_vlc[1]; static VLC_TYPE dv_vlc_codes[15][23]; -static void dv_build_unquantize_tables(DVVideoDecodeContext *s) +static void dv_build_unquantize_tables(DVVideoDecodeContext *s, uint8_t* perm) { int i, q, j; /* NOTE: max left shift is 6 */ for(q = 0; q < 22; q++) { - /* 88 unquant */ + /* 88DCT */ for(i = 1; i < 64; i++) { /* 88 table */ - j = s->idct_permutation[i]; - s->dv_shift[0][q][j] = + j = perm[i]; + s->dv_idct_shift[0][q][j] = dv_quant_shifts[q][dv_88_areas[i]] + 1; + s->dv_dct_shift[0][q][i] = + dv_quant_shifts[q][dv_88_areas[ff_zigzag_direct[i]]] + 4; } - /* 248 unquant */ + /* 248DCT */ for(i = 1; i < 64; i++) { /* 248 table */ - s->dv_shift[1][q][i] = - dv_quant_shifts[q][dv_248_areas[i]] + 1; + s->dv_idct_shift[1][q][i] = + dv_quant_shifts[q][dv_248_areas[i]] + 1; + s->dv_dct_shift[1][q][i] = + dv_quant_shifts[q][dv_248_areas[ff_zigzag248_direct[i]]] + 4; } } } @@ -81,8 +84,9 @@ static void dv_build_unquantize_tables(DVVideoDecodeContext *s) static int dvvideo_init(AVCodecContext *avctx) { DVVideoDecodeContext *s = avctx->priv_data; - MpegEncContext s2; + DSPContext dsp; static int done=0; + int i; if (!done) { int i; @@ -124,27 +128,23 @@ static int dvvideo_init(AVCodecContext *avctx) } } - /* ugly way to get the idct & scantable */ - /* XXX: fix it */ - memset(&s2, 0, sizeof(MpegEncContext)); - s2.avctx = avctx; - dsputil_init(&s2.dsp, avctx); - if (DCT_common_init(&s2) < 0) - return -1; + /* Generic DSP setup */ + dsputil_init(&dsp, avctx); + s->get_pixels = dsp.get_pixels; - s->get_pixels = s2.dsp.get_pixels; - s->fdct = s2.dsp.fdct; - - s->idct_put[0] = s2.dsp.idct_put; - memcpy(s->idct_permutation, s2.dsp.idct_permutation, 64); - memcpy(s->dv_zigzag[0], s2.intra_scantable.permutated, 64); + /* 88DCT setup */ + s->fdct[0] = dsp.fdct; + s->idct_put[0] = dsp.idct_put; + for (i=0; i<64; i++) + s->dv_zigzag[0][i] = dsp.idct_permutation[ff_zigzag_direct[i]]; - /* XXX: use MMX also for idct248 */ - s->idct_put[1] = simple_idct248_put; - memcpy(s->dv_zigzag[1], dv_248_zigzag, 64); + /* 248DCT setup */ + s->fdct[1] = dsp.fdct248; + s->idct_put[1] = simple_idct248_put; // FIXME: need to add it to DSP + memcpy(s->dv_zigzag[1], ff_zigzag248_direct, 64); /* XXX: do it only for constant case */ - dv_build_unquantize_tables(s); + dv_build_unquantize_tables(s, dsp.idct_permutation); /* FIXME: I really don't think this should be here */ if (dv_codec_profile(avctx)) @@ -367,7 +367,7 @@ static inline void dv_decode_video_segment(DVVideoDecodeContext *s, mb->scan_table = s->dv_zigzag[dct_mode]; class1 = get_bits(&s->gb, 2); mb->shift_offset = (class1 == 3); - mb->shift_table = s->dv_shift[dct_mode] + mb->shift_table = s->dv_idct_shift[dct_mode] [quant + dv_quant_offset[class1]]; dc = dc << 2; /* convert to unsigned because 128 is not added in the @@ -571,6 +571,8 @@ typedef struct EncBlockInfo { int block_size; DCTELEM *mb; PutBitContext pb; + const uint8_t* zigzag_scan; + uint8_t *dv_shift; } EncBlockInfo; static inline int dv_bits_left(EncBlockInfo* bi) @@ -583,11 +585,10 @@ static inline void dv_encode_ac(EncBlockInfo* bi, PutBitContext* heap) int i, level, size, run = 0; uint32_t vlc; PutBitContext* cpb = &bi->pb; + int bias = (bi->cno == 3); for (i=1; i<64; i++) { - level = bi->mb[ff_zigzag_direct[i]] / - (1<<(dv_quant_shifts[bi->qno + dv_quant_offset[bi->cno]] - [dv_88_areas[ff_zigzag_direct[i]]] + 4 + (bi->cno == 3))); + level = bi->mb[bi->zigzag_scan[i]] / (1<<(bi->dv_shift[i] + bias)); if (level != 0) { size = dv_rl2vlc(run, level, &vlc); put_vlc: @@ -663,11 +664,26 @@ static inline void dv_set_class_number(EncBlockInfo* bi, int j) bi->cno = 3; } +#define SQ(a) ((a)*(a)) +static int dv_score_lines(DCTELEM *s, int stride) { + int score=0; + int x, y; + + for(y=0; y<4; y++) { + for(x=0; x<8; x+=4){ + score+= SQ(s[x ] - s[x +stride]) + SQ(s[x+1] - s[x+1+stride]) + +SQ(s[x+2] - s[x+2+stride]) + SQ(s[x+3] - s[x+3+stride]); + } + s+= stride; + } + + return score; +} + /* * This is a very rough initial implementaion. The performance is - * horrible and some features are missing, mainly 2-4-8 DCT encoding. - * The weighting is missing as well, but it's missing from the decoding - * step also -- so at least we're on the same page with decoder ;-) + * horrible and the weighting is missing. But it's missing from the + * decoding step also -- so at least we're on the same page with decoder ;-) */ static inline void dv_encode_video_segment(DVVideoDecodeContext *s, uint8_t *dif, @@ -691,6 +707,7 @@ static inline void dv_encode_video_segment(DVVideoDecodeContext *s, /* Stage 1 -- doing DCT on 5 MBs */ block = &s->block[0][0]; + enc_blk = &enc_blks[0]; for(mb_index = 0; mb_index < 5; mb_index++) { v = *mb_pos_ptr++; mb_x = v & 0xff; @@ -731,36 +748,36 @@ static inline void dv_encode_video_segment(DVVideoDecodeContext *s, } else { /* Simple copy: 8x8 -> 8x8 */ s->get_pixels(block, data, linesize); } - - s->fdct(block); + + if (dv_score_lines(block, 8) + dv_score_lines(block+8*4, 8) - 100 > + dv_score_lines(block, 16) + dv_score_lines(block+8, 16)) { + enc_blk->dct_mode = 1; + enc_blk->zigzag_scan = ff_zigzag248_direct; + } else { + enc_blk->dct_mode = 0; + enc_blk->zigzag_scan = ff_zigzag_direct; + } + enc_blk->mb = block; + enc_blk->block_size = block_sizes[j]; + + s->fdct[enc_blk->dct_mode](block); + dv_set_class_number(enc_blk, j/4*(j%2)); + block += 64; + enc_blk++; } } - /* Stage 2 -- setup for encoding phase */ - enc_blk = &enc_blks[0]; - block = &s->block[0][0]; - for (i=0; i<5; i++) { - for (j=0; j<6; j++) { - enc_blk->mb = block; - enc_blk->dct_mode = 0; - enc_blk->block_size = block_sizes[j]; - - dv_set_class_number(enc_blk, j/4*(j%2)); - - block += 64; - enc_blk++; - } - } - - /* Stage 3 -- encoding by trial-and-error */ + /* Stage 2 -- encoding by trial-and-error */ encode_vs: enc_blk = &enc_blks[0]; for (i=0; i<5; i++) { uint8_t* p = dif + i*80 + 4; for (j=0; j<6; j++) { enc_blk->qno = QNO; + enc_blk->dv_shift = &(s->dv_dct_shift[0] + [QNO + dv_quant_offset[enc_blk->cno]][0]); init_put_bits(&enc_blk->pb, p, block_sizes[j]/8); enc_blk++; p += block_sizes[j]/8; |