📄 dv.c
字号:
mb->partial_bit_count = 0;#ifdef VLC_DEBUG printf("MB block: %d, %d ", mb_index, j);#endif dv_decode_ac(&gb, mb, block); /* write the remaining bits in a new buffer only if the block is finished */ if (mb->pos >= 64) bit_copy(&pb, &gb); block += 64; mb++; } /* pass 2 : we can do it just after */#ifdef VLC_DEBUG printf("***pass 2 size=%d MB#=%d\n", put_bits_count(&pb), mb_index);#endif block = block1; mb = mb1; init_get_bits(&gb, mb_bit_buffer, put_bits_count(&pb)); flush_put_bits(&pb); for(j = 0;j < 6; j++, block += 64, mb++) { if (mb->pos < 64 && get_bits_left(&gb) > 0) { dv_decode_ac(&gb, mb, block); /* if still not finished, no need to parse other blocks */ if (mb->pos < 64) break; } } /* all blocks are finished, so the extra bytes can be used at the video segment level */ if (j >= 6) bit_copy(&vs_pb, &gb); } /* we need a pass other the whole video segment */#ifdef VLC_DEBUG printf("***pass 3 size=%d\n", put_bits_count(&vs_pb));#endif block = &sblock[0][0]; mb = mb_data; init_get_bits(&gb, vs_bit_buffer, put_bits_count(&vs_pb)); flush_put_bits(&vs_pb); for(mb_index = 0; mb_index < 5; mb_index++) { for(j = 0;j < 6; j++) { if (mb->pos < 64) {#ifdef VLC_DEBUG printf("start %d:%d\n", mb_index, j);#endif dv_decode_ac(&gb, mb, block); } if (mb->pos >= 64 && mb->pos < 127) av_log(NULL, AV_LOG_ERROR, "AC EOB marker is absent pos=%d\n", mb->pos); block += 64; mb++; } } /* compute idct and place blocks */ block = &sblock[0][0]; mb = mb_data; for(mb_index = 0; mb_index < 5; mb_index++) { v = *mb_pos_ptr++; mb_x = v & 0xff; mb_y = v >> 8; if (s->sys->pix_fmt == PIX_FMT_YUV422P) { y_ptr = s->picture.data[0] + ((mb_y * s->picture.linesize[0] + (mb_x>>1))<<log2_blocksize); c_offset = ((mb_y * s->picture.linesize[1] + (mb_x >> 2))<<log2_blocksize); } else { /* 4:1:1 or 4:2:0 */ 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] + (mb_x >> 2))<<log2_blocksize); else /* 4:2:0 */ 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 && log2_blocksize==3]; if (s->sys->pix_fmt == PIX_FMT_YUV422P) { /* 4:2:2 */ if (j == 0 || j == 2) { /* Y0 Y1 */ idct_put(y_ptr + ((j >> 1)<<log2_blocksize), s->picture.linesize[0], block); } else if(j > 3) { /* Cr Cb */ idct_put(s->picture.data[6 - j] + c_offset, s->picture.linesize[6 - j], block); } /* note: j=1 and j=3 are "dummy" blocks in 4:2:2 */ } else { /* 4:1:1 or 4:2:0 */ 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<<log2_blocksize), s->picture.linesize[0], block); } else { 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, *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 < (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; } } else { /* don't ask me why they inverted Cb and Cr ! */ idct_put(s->picture.data[6 - j] + c_offset, s->picture.linesize[6 - j], block); } } } block += 64; mb++; } }}#ifdef DV_CODEC_TINY_TARGET/* Converts run and level (where level != 0) pair into vlc, returning bit size */static av_always_inline int dv_rl2vlc(int run, int level, int sign, uint32_t* vlc){ int size; 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; } else { if (level < DV_VLC_MAP_LEV_SIZE) { *vlc = dv_vlc_map[0][level].vlc | sign; size = dv_vlc_map[0][level].size; } else { *vlc = 0xfe00 | (level << 1) | sign; size = 16; } if (run) { *vlc |= ((run < 16) ? dv_vlc_map[run-1][0].vlc : (0x1f80 | (run - 1))) << size; size += (run < 16) ? dv_vlc_map[run-1][0].size : 13; } } return size;}static av_always_inline int dv_rl2vlc_size(int run, int level){ int size; if (run < DV_VLC_MAP_RUN_SIZE && level < DV_VLC_MAP_LEV_SIZE) { size = dv_vlc_map[run][level].size; } else { size = (level < DV_VLC_MAP_LEV_SIZE) ? dv_vlc_map[0][level].size : 16; if (run) { size += (run < 16) ? dv_vlc_map[run-1][0].size : 13; } } return size;}#elsestatic av_always_inline int dv_rl2vlc(int run, int l, int sign, uint32_t* vlc){ *vlc = dv_vlc_map[run][l].vlc | sign; return dv_vlc_map[run][l].size;}static av_always_inline int dv_rl2vlc_size(int run, int l){ return dv_vlc_map[run][l].size;}#endiftypedef struct EncBlockInfo { int area_q[4]; int bit_size[4]; int prev[5]; int cur_ac; int cno; int dct_mode; 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 av_always_inline PutBitContext* dv_encode_ac(EncBlockInfo* bi, PutBitContext* pb_pool, PutBitContext* pb_end){ 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; for(;;){ /* Find suitable storage space */ for (; size > (bits_left = put_bits_left(pb)); pb++) { if (bits_left) { size -= bits_left; put_bits(pb, bits_left, vlc >> size); vlc = vlc & ((1<<size)-1); } if (pb + 1 >= pb_end) { bi->partial_bit_count = size; bi->partial_bit_buffer = vlc; return pb; } } /* Store VLC */ put_bits(pb, size, vlc); if(bi->cur_ac>=64) break; /* Construct the next VLC */ 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 */ } } return pb;}static av_always_inline void dv_set_class_number(DCTELEM* blk, EncBlockInfo* bi, const uint8_t* zigzag_scan, const int *weight, int bias){ int i, area; /* We offer two different methods for class number assignment: the method suggested in SMPTE 314M Table 22, and an improved method. The SMPTE method is very conservative; it assigns class 3 (i.e. severe quantization) to any block where the largest AC component is greater than 36. ffmpeg's DV encoder tracks AC bit consumption precisely, so there is no need to bias most blocks towards strongly lossy compression. Instead, we assign class 2 to most blocks, and use class 3 only when strictly necessary (for blocks whose largest AC component exceeds 255). */#if 0 /* SMPTE spec method */ static const int classes[] = {12, 24, 36, 0xffff};#else /* improved ffmpeg method */ static const int classes[] = {-1, -1, 255, 0xffff};#endif int max=classes[0]; int prev=0; bi->mb[0] = blk[0]; 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]; i<mb_area_start[area+1]; i++) { int level = blk[zigzag_scan[i]]; if (level+15 > 30U) { bi->sign[i] = (level>>31)&1; /* weigh it and and shift down into range, adding for rounding */ /* the extra division by a factor of 2^4 reverses the 8x expansion of the DCT AND the 2x doubling of the weights */ level = (FFABS(level) * weight[i] + (1<<(dv_weight_bits+3))) >> (dv_weight_bits+4); bi->mb[i] = level; if(level>max) max= level; bi->bit_size[area] += dv_rl2vlc_size(i - prev - 1, level); bi->next[prev]= i; prev= i; } } } bi->next[prev]= i; for(bi->cno = 0; max > classes[bi->cno]; bi->cno++); bi->cno += bias; if (bi->cno >= 3) { bi->cno = 3; 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 av_always_inline int dv_guess_dct_mode(DCTELEM *blk) { DCTELEM *s; int score88 = 0; int score248 = 0; int i; /* Compute 8-8 score (small values give a better chance for 8-8 DCT) */ s = blk; for(i=0; i<7; i++) { score88 += SC(0, 8) + SC(1, 9) + SC(2, 10) + SC(3, 11) + SC(4, 12) + SC(5,13) + SC(6, 14) + SC(7, 15); s += 8; } /* Compute 2-4-8 score (small values give a better chance for 2-4-8 DCT) */ s = blk; for(i=0; i<6; i++) { score248 += SC(0, 16) + SC(1,17) + SC(2, 18) + SC(3, 19) + SC(4, 20) + SC(5,21) + SC(6, 22) + SC(7, 23); s += 8; } return (score88 - score248 > -10);}static inline void dv_guess_qnos(EncBlockInfo* blks, int* qnos){ int size[5]; int i, j, k, a, prev, a2; EncBlockInfo* b; size[0] = size[1] = size[2] = size[3] = size[4] = 1<<24; do { b = blks; for (i=0; i<5; i++) { if (!qnos[i]) continue; qnos[i]--; size[i] = 0; 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] = 1; // 4 areas 4 bits for EOB :) b->area_q[a]++; prev= b->prev[a]; assert(b->next[prev] >= mb_area_start[a+1] || b->mb[prev]); 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(k - prev - 1, b->mb[k]); prev= k; } else { if(b->next[k] >= mb_area_start[a+1] && b->next[k]<64){ for(a2=a+1; b->next[k] >= mb_area_start[a2+1]; a2++) b->prev[a2] = prev; assert(a2<4); assert(b->mb[b->next[k]]); b->bit_size[a2] += dv_rl2vlc_size(b->next[k] - prev - 1, b->mb[b->next[k]]) -dv_rl2vlc_size(b->next[k] - k - 1, b->mb[b->next[k]]); assert(b->prev[a2]==k && (a2+1 >= 4 || b->prev[a2+1]!=k)); b->prev[a2] = prev; } b->next[prev] = b->next[k]; } } b->prev[a+1]= prev; } size[i] += b->bit_size[a]; } } if(vs_total_ac_bits >= size[0] + size[1] + size[2] + size[3] + size[4]) return; } } while (qnos[0]|qnos[1]|qnos[2]|qnos[3]|qnos[4]); for(a=2; a==2 || vs_total_ac_bits < size[0]; a+=a){ b = blks; size[0] = 5*6*4; //EOB for (j=0; j<6*5; j++, b++) { prev= b->prev[0]; for (k= b->next[prev]; k<64; k= b->next[k]) { if(b->mb[k] < a && b->mb[k] > -a){ b->next[prev] = b->next[k]; }else{ size[0] += dv_rl2vlc_size(k - prev - 1, b->mb[k]); prev= k; } } } }}static inline void dv_encode_video_segment(DVVideoContext *s, uint8_t *dif, const uint16_t *mb_pos_ptr){ int mb_index, i, j, v; int mb_x, mb_y, c_offset, linesize; uint8_t* y_ptr; uint8_t* data; uint8_t* ptr; int do_edge_wrap;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -