📄 intrax8.c
字号:
similar it would trigger if e.g. x=3;y=2; I guess somebody wrote something wrong and it became standard. */ if( (s->mb_x & s->mb_y) != 0 ) w->est_run=FFMIN(c,w->est_run); w->est_run>>=2; a&=3; b&=3; c&=3; i=( 0xFFEAF4C4>>(2*b+8*a) )&3; if(i!=3) w->orient=i; else w->orient=( 0xFFEAD8>>(2*c+8*(w->quant>12)) )&3;/*lut1[b][a]={->{0, 1, 0, pad}, {0, 1, X, pad}, {2, 2, 2, pad}} pad 2 2 2; pad X 1 0; pad 0 1 0 <--> 11 10 '10 10 '11 11'01 00 '11 00'01 00=>0xEAF4C4lut2[q>12][c]={ ->{0,2,1,pad}, {2,2,2,pad}} pad 2 2 2; pad 1 2 0 <--> 11 10'10 10 '11 01'10 00=>0xEAD8*/}static void x8_ac_compensation(IntraX8Context * const w, int const direction, int const dc_level){ MpegEncContext * const s= w->s; int t;#define B(x,y) s->block[0][s->dsp.idct_permutation[(x)+(y)*8]]#define T(x) ((x) * dc_level + 0x8000) >> 16; switch(direction){ case 0: t = T(3811);//h B(1,0) -= t; B(0,1) -= t; t = T(487);//e B(2,0) -= t; B(0,2) -= t; t = T(506);//f B(3,0) -= t; B(0,3) -= t; t = T(135);//c B(4,0) -= t; B(0,4) -= t; B(2,1) += t; B(1,2) += t; B(3,1) += t; B(1,3) += t; t = T(173);//d B(5,0) -= t; B(0,5) -= t; t = T(61);//b B(6,0) -= t; B(0,6) -= t; B(5,1) += t; B(1,5) += t; t = T(42); //a B(7,0) -= t; B(0,7) -= t; B(4,1) += t; B(1,4) += t; B(4,4) += t; t = T(1084);//g B(1,1) += t; s->block_last_index[0] = FFMAX(s->block_last_index[0], 7*8); break; case 1: B(0,1) -= T(6269); B(0,3) -= T( 708); B(0,5) -= T( 172); B(0,7) -= T( 73); s->block_last_index[0] = FFMAX(s->block_last_index[0], 7*8); break; case 2: B(1,0) -= T(6269); B(3,0) -= T( 708); B(5,0) -= T( 172); B(7,0) -= T( 73); s->block_last_index[0] = FFMAX(s->block_last_index[0], 7); break; }#undef B#undef T}static void dsp_x8_put_solidcolor(uint8_t const pix, uint8_t * dst, int const linesize){ int k; for(k=0;k<8;k++){ memset(dst,pix,8); dst+=linesize; }}static const int16_t quant_table[64] = { 256, 256, 256, 256, 256, 256, 259, 262, 265, 269, 272, 275, 278, 282, 285, 288, 292, 295, 299, 303, 306, 310, 314, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353, 358, 362, 366, 371, 375, 379, 384, 389, 393, 398, 403, 408, 413, 417, 422, 428, 433, 438, 443, 448, 454, 459, 465, 470, 476, 482, 488, 493, 499, 505, 511};static int x8_decode_intra_mb(IntraX8Context* const w, const int chroma){ MpegEncContext * const s= w->s; uint8_t * scantable; int final,run,level; int ac_mode,dc_mode,est_run,dc_level; int pos,n; int zeros_only; int use_quant_matrix; int sign; assert(w->orient<12); memset(s->block[0],0x00,64*sizeof(DCTELEM)); if(chroma){ dc_mode=2; }else{ dc_mode=!!w->est_run;//0,1 } if(x8_get_dc_rlf(w, dc_mode, &dc_level, &final)) return -1; n=0; zeros_only=0; if(!final){//decode ac use_quant_matrix=w->use_quant_matrix; if(chroma){ ac_mode = 1; est_run = 64;//not used }else{ if (w->raw_orient < 3){ use_quant_matrix = 0; } if(w->raw_orient > 4){ ac_mode = 0; est_run = 64; }else{ if(w->est_run > 1){ ac_mode = 2; est_run=w->est_run; }else{ ac_mode = 3; est_run = 64; } } } x8_select_ac_table(w,ac_mode); /*scantable_selector[12]={0,2,0,1,1,1,0,2,2,0,1,2};<- -> 10'01' 00'10' 10'00' 01'01' 01'00' 10'00 =>0x928548 */ scantable = w->scantable[ (0x928548>>(2*w->orient))&3 ].permutated; pos=0; do { n++; if( n >= est_run ){ ac_mode=3; x8_select_ac_table(w,3); } x8_get_ac_rlf(w,ac_mode,&run,&level,&final); pos+=run+1; if(pos>63){ //this also handles vlc error in x8_get_ac_rlf return -1; } level= (level+1) * w->dquant; level+= w->qsum; sign = - get_bits1(&s->gb); level = (level ^ sign) - sign; if(use_quant_matrix){ level = (level*quant_table[pos])>>8; } s->block[0][ scantable[pos] ]=level; }while(!final); s->block_last_index[0]=pos; }else{//DC only s->block_last_index[0]=0; if(w->flat_dc && ((unsigned)(dc_level+1)) < 3){//[-1;1] int32_t divide_quant= !chroma ? w->divide_quant_dc_luma: w->divide_quant_dc_chroma; int32_t dc_quant = !chroma ? w->quant: w->quant_dc_chroma; //original intent dc_level+=predicted_dc/quant; but it got lost somewhere in the rounding dc_level+= (w->predicted_dc*divide_quant + (1<<12) )>>13; dsp_x8_put_solidcolor( av_clip_uint8((dc_level*dc_quant+4)>>3), s->dest[chroma], s->current_picture.linesize[!!chroma]); goto block_placed; } zeros_only = (dc_level == 0); } if(!chroma){ s->block[0][0] = dc_level*w->quant; }else{ s->block[0][0] = dc_level*w->quant_dc_chroma; } //there is !zero_only check in the original, but dc_level check is enough if( (unsigned int)(dc_level+1) >= 3 && (w->edges&3) != 3 ){ int direction; /*ac_comp_direction[orient] = { 0, 3, 3, 1, 1, 0, 0, 0, 2, 2, 2, 1 };<- -> 01'10' 10'10' 00'00' 00'01' 01'11' 11'00 =>0x6A017C */ direction= (0x6A017C>>(w->orient*2))&3; if (direction != 3){ x8_ac_compensation(w, direction, s->block[0][0]);//modify block_last[] } } if(w->flat_dc){ dsp_x8_put_solidcolor(w->predicted_dc, s->dest[chroma], s->current_picture.linesize[!!chroma]); }else{ s->dsp.x8_spatial_compensation[w->orient]( s->edge_emu_buffer, s->dest[chroma], s->current_picture.linesize[!!chroma] ); } if(!zeros_only) s->dsp.idct_add ( s->dest[chroma], s->current_picture.linesize[!!chroma], s->block[0] );block_placed: if(!chroma){ x8_update_predictions(w,w->orient,n); } if(s->loop_filter){ uint8_t* ptr = s->dest[chroma]; int linesize = s->current_picture.linesize[!!chroma]; if(!( (w->edges&2) || ( zeros_only && (w->orient|4)==4 ) )){ s->dsp.x8_h_loop_filter(ptr, linesize, w->quant); } if(!( (w->edges&1) || ( zeros_only && (w->orient|8)==8 ) )){ s->dsp.x8_v_loop_filter(ptr, linesize, w->quant); } } return 0;}static void x8_init_block_index(MpegEncContext *s){ //FIXME maybe merge with ff_*//not s->linesize as this would be wrong for field pics//not that IntraX8 has interlacing support ;) const int linesize = s->current_picture.linesize[0]; const int uvlinesize= s->current_picture.linesize[1]; s->dest[0] = s->current_picture.data[0]; s->dest[1] = s->current_picture.data[1]; s->dest[2] = s->current_picture.data[2]; s->dest[0] += s->mb_y * linesize << 3; s->dest[1] += ( s->mb_y&(~1) ) * uvlinesize << 2;//chroma blocks are on add rows s->dest[2] += ( s->mb_y&(~1) ) * uvlinesize << 2;}/** * Initialize IntraX8 frame decoder. * Requires valid MpegEncContext with valid s->mb_width before calling. * @param w pointer to IntraX8Context * @param s pointer to MpegEncContext of the parent codec */void ff_intrax8_common_init(IntraX8Context * w, MpegEncContext * const s){ w->s=s; x8_vlc_init(); assert(s->mb_width>0); w->prediction_table=av_mallocz(s->mb_width*2*2);//two rows, 2 blocks per cannon mb ff_init_scantable(s->dsp.idct_permutation, &w->scantable[0], wmv1_scantable[0]); ff_init_scantable(s->dsp.idct_permutation, &w->scantable[1], wmv1_scantable[2]); ff_init_scantable(s->dsp.idct_permutation, &w->scantable[2], wmv1_scantable[3]);}/** * Destroy IntraX8 frame structure. * @param w pointer to IntraX8Context */void ff_intrax8_common_end(IntraX8Context * w){ av_freep(&w->prediction_table);}/** * Decode single IntraX8 frame. * The parent codec must fill s->loopfilter and s->gb (bitstream). * The parent codec must call MPV_frame_start(), ff_er_frame_start() before calling this function. * The parent codec must call ff_er_frame_end(), MPV_frame_end() after calling this function. * This function does not use MPV_decode_mb(). * lowres decoding is theoretically impossible. * @param w pointer to IntraX8Context * @param dquant doubled quantizer, it would be odd in case of VC-1 halfpq==1. * @param quant_offset offset away from zero *///FIXME extern uint8_t wmv3_dc_scale_table[32];int ff_intrax8_decode_picture(IntraX8Context * const w, int dquant, int quant_offset){ MpegEncContext * const s= w->s; int mb_xy; assert(s); w->use_quant_matrix = get_bits1(&s->gb); w->dquant = dquant; w->quant = dquant >> 1; w->qsum = quant_offset; w->divide_quant_dc_luma = ((1<<16) + (w->quant>>1)) / w->quant; if(w->quant < 5){ w->quant_dc_chroma = w->quant; w->divide_quant_dc_chroma = w->divide_quant_dc_luma; }else{ w->quant_dc_chroma = w->quant+((w->quant+3)>>3); w->divide_quant_dc_chroma = ((1<<16) + (w->quant_dc_chroma>>1)) / w->quant_dc_chroma; } x8_reset_vlc_tables(w); s->resync_mb_x=0; s->resync_mb_y=0; for(s->mb_y=0; s->mb_y < s->mb_height*2; s->mb_y++){ x8_init_block_index(s); mb_xy=(s->mb_y>>1)*s->mb_stride; for(s->mb_x=0; s->mb_x < s->mb_width*2; s->mb_x++){ x8_get_prediction(w); if(x8_setup_spatial_predictor(w,0)) goto error; if(x8_decode_intra_mb(w,0)) goto error; if( s->mb_x & s->mb_y & 1 ){ x8_get_prediction_chroma(w); /*when setting up chroma, no vlc is read, so no error condition can be reached*/ x8_setup_spatial_predictor(w,1); if(x8_decode_intra_mb(w,1)) goto error; x8_setup_spatial_predictor(w,2); if(x8_decode_intra_mb(w,2)) goto error; s->dest[1]+= 8; s->dest[2]+= 8; /*emulate MB info in the relevant tables*/ s->mbskip_table [mb_xy]=0; s->mbintra_table[mb_xy]=1; s->current_picture.qscale_table[mb_xy]=w->quant; mb_xy++; } s->dest[0]+= 8; } if(s->mb_y&1){ ff_draw_horiz_band(s, (s->mb_y-1)*8, 16); } }error: ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, (s->mb_x>>1)-1, (s->mb_y>>1)-1, (AC_END|DC_END|MV_END) ); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -