diff options
Diffstat (limited to 'src/libffmpeg/libavcodec/dv.c')
-rw-r--r-- | src/libffmpeg/libavcodec/dv.c | 245 |
1 files changed, 139 insertions, 106 deletions
diff --git a/src/libffmpeg/libavcodec/dv.c b/src/libffmpeg/libavcodec/dv.c index bc750bcbc..09fb77299 100644 --- a/src/libffmpeg/libavcodec/dv.c +++ b/src/libffmpeg/libavcodec/dv.c @@ -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 @@ 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 */ @@ -109,14 +113,13 @@ static int dvvideo_init(AVCodecContext *avctx) done = 1; - dv_vlc_map = av_mallocz(DV_VLC_MAP_LEV_SIZE*DV_VLC_MAP_RUN_SIZE*sizeof(struct dv_vlc_pair)); + dv_vlc_map = av_mallocz_static(DV_VLC_MAP_LEV_SIZE*DV_VLC_MAP_RUN_SIZE*sizeof(struct dv_vlc_pair)); if (!dv_vlc_map) return -ENOMEM; /* dv_anchor lets each thread know its Id */ dv_anchor = av_malloc(12*27*sizeof(void*)); if (!dv_anchor) { - av_free(dv_vlc_map); return -ENOMEM; } for (i=0; i<12*27; i++) @@ -149,7 +152,6 @@ static int dvvideo_init(AVCodecContext *avctx) dv_rl_vlc = av_malloc(dv_vlc.table_size * sizeof(RL_VLC_ELEM)); if (!dv_rl_vlc) { av_free(dv_anchor); - av_free(dv_vlc_map); return -ENOMEM; } for(i = 0; i < dv_vlc.table_size; i++){ @@ -226,7 +228,13 @@ static int dvvideo_init(AVCodecContext *avctx) /* 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); + if(avctx->lowres){ + for (i=0; i<64; i++){ + int j= ff_zigzag248_direct[i]; + s->dv_zigzag[1][i] = dsp.idct_permutation[(j&7) + (j&8)*4 + (j&48)/2]; + } + }else + memcpy(s->dv_zigzag[1], ff_zigzag248_direct, 64); /* XXX: do it only for constant case */ dv_build_unquantize_tables(s, dsp.idct_permutation); @@ -235,6 +243,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; } @@ -334,10 +343,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); } @@ -348,9 +356,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)); @@ -373,9 +381,13 @@ 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 */ + const int log2_blocksize= 3-s->avctx->lowres; + 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 */ @@ -477,39 +489,38 @@ static inline void dv_decode_video_segment(DVVideoContext *s, v = *mb_pos_ptr++; mb_x = v & 0xff; mb_y = v >> 8; - y_ptr = s->picture.data[0] + (mb_y * s->picture.linesize[0] * 8) + (mb_x * 8); + y_ptr = s->picture.data[0] + ((mb_y * s->picture.linesize[0] + mb_x)<<log2_blocksize); if (s->sys->pix_fmt == PIX_FMT_YUV411P) - c_offset = (mb_y * s->picture.linesize[1] * 8) + ((mb_x >> 2) * 8); + c_offset = ((mb_y * s->picture.linesize[1] + (mb_x >> 2))<<log2_blocksize); else - c_offset = ((mb_y >> 1) * s->picture.linesize[1] * 8) + ((mb_x >> 1) * 8); + c_offset = (((mb_y >> 1) * s->picture.linesize[1] + (mb_x >> 1))<<log2_blocksize); for(j = 0;j < 6; j++) { - idct_put = s->idct_put[mb->dct_mode]; + idct_put = s->idct_put[mb->dct_mode && log2_blocksize==3]; if (j < 4) { if (s->sys->pix_fmt == PIX_FMT_YUV411P && mb_x < (704 / 8)) { /* NOTE: at end of line, the macroblock is handled as 420 */ - idct_put(y_ptr + (j * 8), s->picture.linesize[0], block); + idct_put(y_ptr + (j<<log2_blocksize), s->picture.linesize[0], block); } else { - idct_put(y_ptr + ((j & 1) * 8) + ((j >> 1) * 8 * s->picture.linesize[0]), + idct_put(y_ptr + (((j & 1) + (j >> 1) * s->picture.linesize[0])<<log2_blocksize), s->picture.linesize[0], block); } } else { if (s->sys->pix_fmt == PIX_FMT_YUV411P && mb_x >= (704 / 8)) { uint64_t aligned_pixels[64/8]; uint8_t *pixels= (uint8_t*)aligned_pixels; - uint8_t *c_ptr, *c_ptr1, *ptr; - int y, linesize; + uint8_t *c_ptr, *c_ptr1, *ptr, *ptr1; + int x, y, linesize; /* NOTE: at end of line, the macroblock is handled as 420 */ idct_put(pixels, 8, block); linesize = s->picture.linesize[6 - j]; c_ptr = s->picture.data[6 - j] + c_offset; ptr = pixels; - for(y = 0;y < 8; y++) { - /* convert to 411P */ - c_ptr1 = c_ptr + 8*linesize; - c_ptr[0]= ptr[0]; c_ptr1[0]= ptr[4]; - c_ptr[1]= ptr[1]; c_ptr1[1]= ptr[5]; - c_ptr[2]= ptr[2]; c_ptr1[2]= ptr[6]; - c_ptr[3]= ptr[3]; c_ptr1[3]= ptr[7]; + for(y = 0;y < (1<<log2_blocksize); y++) { + ptr1= ptr + (1<<(log2_blocksize-1)); + c_ptr1 = c_ptr + (linesize<<log2_blocksize); + for(x=0; x < (1<<(log2_blocksize-1)); x++){ + c_ptr[x]= ptr[x]; c_ptr1[x]= ptr1[x]; + } c_ptr += linesize; ptr += 8; } @@ -527,14 +538,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; @@ -557,9 +563,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) { @@ -574,41 +579,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) { @@ -616,69 +623,84 @@ vlc_loop: 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; - } - } - - 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]; 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; @@ -707,9 +729,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++) { @@ -721,17 +743,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]; 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]; } @@ -757,13 +781,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]; @@ -810,21 +835,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); @@ -845,18 +871,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++) @@ -897,9 +927,10 @@ static int dvvideo_decode_frame(AVCodecContext *avctx, avctx->release_buffer(avctx, &s->picture); s->picture.reference = 0; + s->picture.key_frame = 1; + s->picture.pict_type = FF_I_TYPE; avctx->pix_fmt = s->sys->pix_fmt; - avctx->width = s->sys->width; - avctx->height = s->sys->height; + avcodec_set_dimensions(avctx, s->sys->width, s->sys->height); if(avctx->get_buffer(avctx, &s->picture) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return -1; @@ -933,6 +964,8 @@ static int dvvideo_encode_frame(AVCodecContext *c, uint8_t *buf, int buf_size, c->pix_fmt = s->sys->pix_fmt; s->picture = *((AVFrame *)data); + s->picture.key_frame = 1; + s->picture.pict_type = FF_I_TYPE; s->buf = buf; c->execute(c, dv_encode_mt, (void**)&dv_anchor[0], NULL, |