Libav 0.7.1
|
00001 /* 00002 * This file is part of Libav. 00003 * 00004 * Libav is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * Libav is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with Libav; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00017 */ 00018 00024 #include "avcodec.h" 00025 #include "get_bits.h" 00026 #include "mpegvideo.h" 00027 #include "msmpeg4data.h" 00028 #include "intrax8huf.h" 00029 #include "intrax8.h" 00030 00031 #define MAX_TABLE_DEPTH(table_bits, max_bits) ((max_bits+table_bits-1)/table_bits) 00032 00033 #define DC_VLC_BITS 9 00034 #define AC_VLC_BITS 9 00035 #define OR_VLC_BITS 7 00036 00037 #define DC_VLC_MTD MAX_TABLE_DEPTH(DC_VLC_BITS, MAX_DC_VLC_BITS) 00038 #define AC_VLC_MTD MAX_TABLE_DEPTH(AC_VLC_BITS, MAX_AC_VLC_BITS) 00039 #define OR_VLC_MTD MAX_TABLE_DEPTH(OR_VLC_BITS, MAX_OR_VLC_BITS) 00040 00041 static VLC j_ac_vlc[2][2][8]; //[quant<13],[intra/inter],[select] 00042 static VLC j_dc_vlc[2][8]; //[quant], [select] 00043 static VLC j_orient_vlc[2][4]; //[quant], [select] 00044 00045 static av_cold void x8_vlc_init(void){ 00046 int i; 00047 int offset = 0; 00048 int sizeidx = 0; 00049 static const uint16_t sizes[8*4 + 8*2 + 2 + 4] = { 00050 576, 548, 582, 618, 546, 616, 560, 642, 00051 584, 582, 704, 664, 512, 544, 656, 640, 00052 512, 648, 582, 566, 532, 614, 596, 648, 00053 586, 552, 584, 590, 544, 578, 584, 624, 00054 00055 528, 528, 526, 528, 536, 528, 526, 544, 00056 544, 512, 512, 528, 528, 544, 512, 544, 00057 00058 128, 128, 128, 128, 128, 128}; 00059 00060 static VLC_TYPE table[28150][2]; 00061 00062 #define init_ac_vlc(dst,src) \ 00063 dst.table = &table[offset]; \ 00064 dst.table_allocated = sizes[sizeidx]; \ 00065 offset += sizes[sizeidx++]; \ 00066 init_vlc(&dst, \ 00067 AC_VLC_BITS,77, \ 00068 &src[1],4,2, \ 00069 &src[0],4,2, \ 00070 INIT_VLC_USE_NEW_STATIC) 00071 //set ac tables 00072 for(i=0;i<8;i++){ 00073 init_ac_vlc( j_ac_vlc[0][0][i], x8_ac0_highquant_table[i][0] ); 00074 init_ac_vlc( j_ac_vlc[0][1][i], x8_ac1_highquant_table[i][0] ); 00075 init_ac_vlc( j_ac_vlc[1][0][i], x8_ac0_lowquant_table [i][0] ); 00076 init_ac_vlc( j_ac_vlc[1][1][i], x8_ac1_lowquant_table [i][0] ); 00077 } 00078 #undef init_ac_vlc 00079 00080 //set dc tables 00081 #define init_dc_vlc(dst,src) \ 00082 dst.table = &table[offset]; \ 00083 dst.table_allocated = sizes[sizeidx]; \ 00084 offset += sizes[sizeidx++]; \ 00085 init_vlc(&dst, \ 00086 DC_VLC_BITS,34, \ 00087 &src[1],4,2, \ 00088 &src[0],4,2, \ 00089 INIT_VLC_USE_NEW_STATIC); 00090 for(i=0;i<8;i++){ 00091 init_dc_vlc( j_dc_vlc[0][i], x8_dc_highquant_table[i][0]); 00092 init_dc_vlc( j_dc_vlc[1][i], x8_dc_lowquant_table [i][0]); 00093 } 00094 #undef init_dc_vlc 00095 00096 //set orient tables 00097 #define init_or_vlc(dst,src) \ 00098 dst.table = &table[offset]; \ 00099 dst.table_allocated = sizes[sizeidx]; \ 00100 offset += sizes[sizeidx++]; \ 00101 init_vlc(&dst, \ 00102 OR_VLC_BITS,12, \ 00103 &src[1],4,2, \ 00104 &src[0],4,2, \ 00105 INIT_VLC_USE_NEW_STATIC); 00106 for(i=0;i<2;i++){ 00107 init_or_vlc( j_orient_vlc[0][i], x8_orient_highquant_table[i][0]); 00108 } 00109 for(i=0;i<4;i++){ 00110 init_or_vlc( j_orient_vlc[1][i], x8_orient_lowquant_table [i][0]) 00111 } 00112 if (offset != sizeof(table)/sizeof(VLC_TYPE)/2) 00113 av_log(NULL, AV_LOG_ERROR, "table size %i does not match needed %i\n", (int)(sizeof(table)/sizeof(VLC_TYPE)/2), offset); 00114 } 00115 #undef init_or_vlc 00116 00117 static void x8_reset_vlc_tables(IntraX8Context * w){ 00118 memset(w->j_dc_vlc,0,sizeof(w->j_dc_vlc)); 00119 memset(w->j_ac_vlc,0,sizeof(w->j_ac_vlc)); 00120 w->j_orient_vlc=NULL; 00121 } 00122 00123 static inline void x8_select_ac_table(IntraX8Context * const w , int mode){ 00124 MpegEncContext * const s= w->s; 00125 int table_index; 00126 00127 assert(mode<4); 00128 00129 if( w->j_ac_vlc[mode] ) return; 00130 00131 table_index = get_bits(&s->gb, 3); 00132 w->j_ac_vlc[mode] = &j_ac_vlc[w->quant<13][mode>>1][table_index];//2 modes use same tables 00133 assert(w->j_ac_vlc[mode]); 00134 } 00135 00136 static inline int x8_get_orient_vlc(IntraX8Context * w){ 00137 MpegEncContext * const s= w->s; 00138 int table_index; 00139 00140 if(!w->j_orient_vlc ){ 00141 table_index = get_bits(&s->gb, 1+(w->quant<13) ); 00142 w->j_orient_vlc = &j_orient_vlc[w->quant<13][table_index]; 00143 } 00144 assert(w->j_orient_vlc); 00145 assert(w->j_orient_vlc->table); 00146 00147 return get_vlc2(&s->gb, w->j_orient_vlc->table, OR_VLC_BITS, OR_VLC_MTD); 00148 } 00149 00150 #define extra_bits(eb) (eb) 00151 #define extra_run (0xFF<<8) 00152 #define extra_level (0x00<<8) 00153 #define run_offset(r) ((r)<<16) 00154 #define level_offset(l) ((l)<<24) 00155 static const uint32_t ac_decode_table[]={ 00156 /*46*/ extra_bits(3) | extra_run | run_offset(16) | level_offset( 0), 00157 /*47*/ extra_bits(3) | extra_run | run_offset(24) | level_offset( 0), 00158 /*48*/ extra_bits(2) | extra_run | run_offset( 4) | level_offset( 1), 00159 /*49*/ extra_bits(3) | extra_run | run_offset( 8) | level_offset( 1), 00160 00161 /*50*/ extra_bits(5) | extra_run | run_offset(32) | level_offset( 0), 00162 /*51*/ extra_bits(4) | extra_run | run_offset(16) | level_offset( 1), 00163 00164 /*52*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset( 4), 00165 /*53*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset( 8), 00166 /*54*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset(12), 00167 /*55*/ extra_bits(3) | extra_level | run_offset( 0) | level_offset(16), 00168 /*56*/ extra_bits(3) | extra_level | run_offset( 0) | level_offset(24), 00169 00170 /*57*/ extra_bits(2) | extra_level | run_offset( 1) | level_offset( 3), 00171 /*58*/ extra_bits(3) | extra_level | run_offset( 1) | level_offset( 7), 00172 00173 /*59*/ extra_bits(2) | extra_run | run_offset(16) | level_offset( 0), 00174 /*60*/ extra_bits(2) | extra_run | run_offset(20) | level_offset( 0), 00175 /*61*/ extra_bits(2) | extra_run | run_offset(24) | level_offset( 0), 00176 /*62*/ extra_bits(2) | extra_run | run_offset(28) | level_offset( 0), 00177 /*63*/ extra_bits(4) | extra_run | run_offset(32) | level_offset( 0), 00178 /*64*/ extra_bits(4) | extra_run | run_offset(48) | level_offset( 0), 00179 00180 /*65*/ extra_bits(2) | extra_run | run_offset( 4) | level_offset( 1), 00181 /*66*/ extra_bits(3) | extra_run | run_offset( 8) | level_offset( 1), 00182 /*67*/ extra_bits(4) | extra_run | run_offset(16) | level_offset( 1), 00183 00184 /*68*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset( 4), 00185 /*69*/ extra_bits(3) | extra_level | run_offset( 0) | level_offset( 8), 00186 /*70*/ extra_bits(4) | extra_level | run_offset( 0) | level_offset(16), 00187 00188 /*71*/ extra_bits(2) | extra_level | run_offset( 1) | level_offset( 3), 00189 /*72*/ extra_bits(3) | extra_level | run_offset( 1) | level_offset( 7), 00190 }; 00191 //extra_bits = 3bits; extra_run/level = 1 bit; run_offset = 6bits; level_offset = 5 bits; 00192 #undef extra_bits 00193 #undef extra_run 00194 #undef extra_level 00195 #undef run_offset 00196 #undef level_offset 00197 00198 static void x8_get_ac_rlf(IntraX8Context * const w, const int mode, 00199 int * const run, int * const level, int * const final){ 00200 MpegEncContext * const s= w->s; 00201 int i,e; 00202 00203 // x8_select_ac_table(w,mode); 00204 i = get_vlc2(&s->gb, w->j_ac_vlc[mode]->table, AC_VLC_BITS, AC_VLC_MTD); 00205 00206 if(i<46){ //[0-45] 00207 int t,l; 00208 if(i<0){ 00209 (*level)=(*final)=//prevent 'may be used unilitialized' 00210 (*run)=64;//this would cause error exit in the ac loop 00211 return; 00212 } 00213 00214 (*final) = t = (i>22); 00215 i-=23*t; 00216 /* 00217 i== 0-15 r=0-15 l=0 ;r=i& %01111 00218 i==16-19 r=0-3 l=1 ;r=i& %00011 00219 i==20-21 r=0-1 l=2 ;r=i& %00001 00220 i==22 r=0 l=3 ;r=i& %00000 00221 l=lut_l[i/2]={0,0,0,0,0,0,0,0,1,1,2,3}[i>>1];// 11 10'01 01'00 00'00 00'00 00'00 00 => 0xE50000 00222 t=lut_mask[l]={0x0f,0x03,0x01,0x00}[l]; as i<256 the higher bits do not matter */ 00223 l=(0xE50000>>(i&(0x1E)))&3;/*0x1E or (~1) or ((i>>1)<<1)*/ 00224 t=(0x01030F>>(l<<3)); 00225 00226 (*run) = i&t; 00227 (*level) = l; 00228 }else if(i<73){//[46-72] 00229 uint32_t sm; 00230 uint32_t mask; 00231 00232 i-=46; 00233 sm=ac_decode_table[i]; 00234 00235 e=get_bits(&s->gb,sm&0xF);sm>>=8;//3bits 00236 mask=sm&0xff;sm>>=8; //1bit 00237 00238 (*run) =(sm&0xff) + (e&( mask));//6bits 00239 (*level)=(sm>>8) + (e&(~mask));//5bits 00240 (*final)=i>(58-46); 00241 }else if(i<75){//[73-74] 00242 static const uint8_t crazy_mix_runlevel[32]={ 00243 0x22,0x32,0x33,0x53,0x23,0x42,0x43,0x63, 00244 0x24,0x52,0x34,0x73,0x25,0x62,0x44,0x83, 00245 0x26,0x72,0x35,0x54,0x27,0x82,0x45,0x64, 00246 0x28,0x92,0x36,0x74,0x29,0xa2,0x46,0x84}; 00247 00248 (*final)=!(i&1); 00249 e=get_bits(&s->gb,5);//get the extra bits 00250 (*run) =crazy_mix_runlevel[e]>>4; 00251 (*level)=crazy_mix_runlevel[e]&0x0F; 00252 }else{ 00253 (*level)=get_bits( &s->gb, 7-3*(i&1)); 00254 (*run) =get_bits( &s->gb, 6); 00255 (*final)=get_bits1(&s->gb); 00256 } 00257 return; 00258 } 00259 00260 //static const uint8_t dc_extra_sbits[] ={0, 1,1, 1,1, 2,2, 3,3, 4,4, 5,5, 6,6, 7,7 }; 00261 static const uint8_t dc_index_offset[] ={ 0, 1,2, 3,4, 5,7, 9,13, 17,25, 33,49, 65,97, 129,193}; 00262 00263 static int x8_get_dc_rlf(IntraX8Context * const w,int const mode, int * const level, int * const final){ 00264 MpegEncContext * const s= w->s; 00265 int i,e,c; 00266 00267 assert(mode<3); 00268 if( !w->j_dc_vlc[mode] ) { 00269 int table_index; 00270 table_index = get_bits(&s->gb, 3); 00271 //4 modes, same table 00272 w->j_dc_vlc[mode]= &j_dc_vlc[w->quant<13][table_index]; 00273 } 00274 assert(w->j_dc_vlc); 00275 assert(w->j_dc_vlc[mode]->table); 00276 00277 i=get_vlc2(&s->gb, w->j_dc_vlc[mode]->table, DC_VLC_BITS, DC_VLC_MTD); 00278 00279 /*(i>=17) {i-=17;final=1;}*/ 00280 c= i>16; 00281 (*final)=c; 00282 i-=17*c; 00283 00284 if(i<=0){ 00285 (*level)=0; 00286 return -i; 00287 } 00288 c=(i+1)>>1;//hackish way to calculate dc_extra_sbits[] 00289 c-=c>1; 00290 00291 e=get_bits(&s->gb,c);//get the extra bits 00292 i=dc_index_offset[i]+(e>>1); 00293 00294 e= -(e & 1);//0,0xffffff 00295 (*level)= (i ^ e) - e;// (i^0)-0 , (i^0xff)-(-1) 00296 return 0; 00297 } 00298 //end of huffman 00299 00300 static int x8_setup_spatial_predictor(IntraX8Context * const w, const int chroma){ 00301 MpegEncContext * const s= w->s; 00302 int range; 00303 int sum; 00304 int quant; 00305 00306 s->dsp.x8_setup_spatial_compensation(s->dest[chroma], s->edge_emu_buffer, 00307 s->current_picture.linesize[chroma>0], 00308 &range, &sum, w->edges); 00309 if(chroma){ 00310 w->orient=w->chroma_orient; 00311 quant=w->quant_dc_chroma; 00312 }else{ 00313 quant=w->quant; 00314 } 00315 00316 w->flat_dc=0; 00317 if(range < quant || range < 3){ 00318 w->orient=0; 00319 if(range < 3){//yep you read right, a +-1 idct error may break decoding! 00320 w->flat_dc=1; 00321 sum+=9; 00322 w->predicted_dc = (sum*6899)>>17;//((1<<17)+9)/(8+8+1+2)=6899 00323 } 00324 } 00325 if(chroma) 00326 return 0; 00327 00328 assert(w->orient < 3); 00329 if(range < 2*w->quant){ 00330 if( (w->edges&3) == 0){ 00331 if(w->orient==1) w->orient=11; 00332 if(w->orient==2) w->orient=10; 00333 }else{ 00334 w->orient=0; 00335 } 00336 w->raw_orient=0; 00337 }else{ 00338 static const uint8_t prediction_table[3][12]={ 00339 {0,8,4, 10,11, 2,6,9,1,3,5,7}, 00340 {4,0,8, 11,10, 3,5,2,6,9,1,7}, 00341 {8,0,4, 10,11, 1,7,2,6,9,3,5} 00342 }; 00343 w->raw_orient=x8_get_orient_vlc(w); 00344 if(w->raw_orient<0) return -1; 00345 assert(w->raw_orient < 12 ); 00346 assert(w->orient<3); 00347 w->orient=prediction_table[w->orient][w->raw_orient]; 00348 } 00349 return 0; 00350 } 00351 00352 static void x8_update_predictions(IntraX8Context * const w, const int orient, const int est_run ){ 00353 MpegEncContext * const s= w->s; 00354 00355 w->prediction_table[s->mb_x*2+(s->mb_y&1)] = (est_run<<2) + 1*(orient==4) + 2*(orient==8); 00356 /* 00357 y=2n+0 ->//0 2 4 00358 y=2n+1 ->//1 3 5 00359 */ 00360 } 00361 static void x8_get_prediction_chroma(IntraX8Context * const w){ 00362 MpegEncContext * const s= w->s; 00363 00364 w->edges = 1*( !(s->mb_x>>1) ); 00365 w->edges|= 2*( !(s->mb_y>>1) ); 00366 w->edges|= 4*( s->mb_x >= (2*s->mb_width-1) );//mb_x for chroma would always be odd 00367 00368 w->raw_orient=0; 00369 if(w->edges&3){//lut_co[8]={inv,4,8,8, inv,4,8,8}<- =>{1,1,0,0;1,1,0,0} => 0xCC 00370 w->chroma_orient=4<<((0xCC>>w->edges)&1); 00371 return; 00372 } 00373 w->chroma_orient = (w->prediction_table[2*s->mb_x-2] & 0x03)<<2;//block[x-1][y|1-1)] 00374 } 00375 00376 static void x8_get_prediction(IntraX8Context * const w){ 00377 MpegEncContext * const s= w->s; 00378 int a,b,c,i; 00379 00380 w->edges = 1*( !s->mb_x ); 00381 w->edges|= 2*( !s->mb_y ); 00382 w->edges|= 4*( s->mb_x >= (2*s->mb_width-1) ); 00383 00384 switch(w->edges&3){ 00385 case 0: 00386 break; 00387 case 1: 00388 //take the one from the above block[0][y-1] 00389 w->est_run = w->prediction_table[!(s->mb_y&1)]>>2; 00390 w->orient = 1; 00391 return; 00392 case 2: 00393 //take the one from the previous block[x-1][0] 00394 w->est_run = w->prediction_table[2*s->mb_x-2]>>2; 00395 w->orient = 2; 00396 return; 00397 case 3: 00398 w->est_run = 16; 00399 w->orient = 0; 00400 return; 00401 } 00402 //no edge cases 00403 b= w->prediction_table[2*s->mb_x + !(s->mb_y&1) ];//block[x ][y-1] 00404 a= w->prediction_table[2*s->mb_x-2 + (s->mb_y&1) ];//block[x-1][y ] 00405 c= w->prediction_table[2*s->mb_x-2 + !(s->mb_y&1) ];//block[x-1][y-1] 00406 00407 w->est_run = FFMIN(b,a); 00408 /* This condition has nothing to do with w->edges, even if it looks 00409 similar it would trigger if e.g. x=3;y=2; 00410 I guess somebody wrote something wrong and it became standard. */ 00411 if( (s->mb_x & s->mb_y) != 0 ) w->est_run=FFMIN(c,w->est_run); 00412 w->est_run>>=2; 00413 00414 a&=3; 00415 b&=3; 00416 c&=3; 00417 00418 i=( 0xFFEAF4C4>>(2*b+8*a) )&3; 00419 if(i!=3) w->orient=i; 00420 else w->orient=( 0xFFEAD8>>(2*c+8*(w->quant>12)) )&3; 00421 /* 00422 lut1[b][a]={ 00423 ->{0, 1, 0, pad}, 00424 {0, 1, X, pad}, 00425 {2, 2, 2, pad}} 00426 pad 2 2 2; pad X 1 0; pad 0 1 0 <- 00427 -> 11 10 '10 10 '11 11'01 00 '11 00'01 00=>0xEAF4C4 00428 00429 lut2[q>12][c]={ 00430 ->{0,2,1,pad}, 00431 {2,2,2,pad}} 00432 pad 2 2 2; pad 1 2 0 <- 00433 -> 11 10'10 10 '11 01'10 00=>0xEAD8 00434 */ 00435 } 00436 00437 00438 static void x8_ac_compensation(IntraX8Context * const w, int const direction, int const dc_level){ 00439 MpegEncContext * const s= w->s; 00440 int t; 00441 #define B(x,y) s->block[0][s->dsp.idct_permutation[(x)+(y)*8]] 00442 #define T(x) ((x) * dc_level + 0x8000) >> 16; 00443 switch(direction){ 00444 case 0: 00445 t = T(3811);//h 00446 B(1,0) -= t; 00447 B(0,1) -= t; 00448 00449 t = T(487);//e 00450 B(2,0) -= t; 00451 B(0,2) -= t; 00452 00453 t = T(506);//f 00454 B(3,0) -= t; 00455 B(0,3) -= t; 00456 00457 t = T(135);//c 00458 B(4,0) -= t; 00459 B(0,4) -= t; 00460 B(2,1) += t; 00461 B(1,2) += t; 00462 B(3,1) += t; 00463 B(1,3) += t; 00464 00465 t = T(173);//d 00466 B(5,0) -= t; 00467 B(0,5) -= t; 00468 00469 t = T(61);//b 00470 B(6,0) -= t; 00471 B(0,6) -= t; 00472 B(5,1) += t; 00473 B(1,5) += t; 00474 00475 t = T(42); //a 00476 B(7,0) -= t; 00477 B(0,7) -= t; 00478 B(4,1) += t; 00479 B(1,4) += t; 00480 B(4,4) += t; 00481 00482 t = T(1084);//g 00483 B(1,1) += t; 00484 00485 s->block_last_index[0] = FFMAX(s->block_last_index[0], 7*8); 00486 break; 00487 case 1: 00488 B(0,1) -= T(6269); 00489 B(0,3) -= T( 708); 00490 B(0,5) -= T( 172); 00491 B(0,7) -= T( 73); 00492 00493 s->block_last_index[0] = FFMAX(s->block_last_index[0], 7*8); 00494 break; 00495 case 2: 00496 B(1,0) -= T(6269); 00497 B(3,0) -= T( 708); 00498 B(5,0) -= T( 172); 00499 B(7,0) -= T( 73); 00500 00501 s->block_last_index[0] = FFMAX(s->block_last_index[0], 7); 00502 break; 00503 } 00504 #undef B 00505 #undef T 00506 } 00507 00508 static void dsp_x8_put_solidcolor(uint8_t const pix, uint8_t * dst, int const linesize){ 00509 int k; 00510 for(k=0;k<8;k++){ 00511 memset(dst,pix,8); 00512 dst+=linesize; 00513 } 00514 } 00515 00516 static const int16_t quant_table[64] = { 00517 256, 256, 256, 256, 256, 256, 259, 262, 00518 265, 269, 272, 275, 278, 282, 285, 288, 00519 292, 295, 299, 303, 306, 310, 314, 317, 00520 321, 325, 329, 333, 337, 341, 345, 349, 00521 353, 358, 362, 366, 371, 375, 379, 384, 00522 389, 393, 398, 403, 408, 413, 417, 422, 00523 428, 433, 438, 443, 448, 454, 459, 465, 00524 470, 476, 482, 488, 493, 499, 505, 511 00525 }; 00526 00527 static int x8_decode_intra_mb(IntraX8Context* const w, const int chroma){ 00528 MpegEncContext * const s= w->s; 00529 00530 uint8_t * scantable; 00531 int final,run,level; 00532 int ac_mode,dc_mode,est_run,dc_level; 00533 int pos,n; 00534 int zeros_only; 00535 int use_quant_matrix; 00536 int sign; 00537 00538 assert(w->orient<12); 00539 s->dsp.clear_block(s->block[0]); 00540 00541 if(chroma){ 00542 dc_mode=2; 00543 }else{ 00544 dc_mode=!!w->est_run;//0,1 00545 } 00546 00547 if(x8_get_dc_rlf(w, dc_mode, &dc_level, &final)) return -1; 00548 n=0; 00549 zeros_only=0; 00550 if(!final){//decode ac 00551 use_quant_matrix=w->use_quant_matrix; 00552 if(chroma){ 00553 ac_mode = 1; 00554 est_run = 64;//not used 00555 }else{ 00556 if (w->raw_orient < 3){ 00557 use_quant_matrix = 0; 00558 } 00559 if(w->raw_orient > 4){ 00560 ac_mode = 0; 00561 est_run = 64; 00562 }else{ 00563 if(w->est_run > 1){ 00564 ac_mode = 2; 00565 est_run=w->est_run; 00566 }else{ 00567 ac_mode = 3; 00568 est_run = 64; 00569 } 00570 } 00571 } 00572 x8_select_ac_table(w,ac_mode); 00573 /*scantable_selector[12]={0,2,0,1,1,1,0,2,2,0,1,2};<- 00574 -> 10'01' 00'10' 10'00' 01'01' 01'00' 10'00 =>0x928548 */ 00575 scantable = w->scantable[ (0x928548>>(2*w->orient))&3 ].permutated; 00576 pos=0; 00577 do { 00578 n++; 00579 if( n >= est_run ){ 00580 ac_mode=3; 00581 x8_select_ac_table(w,3); 00582 } 00583 00584 x8_get_ac_rlf(w,ac_mode,&run,&level,&final); 00585 00586 pos+=run+1; 00587 if(pos>63){ 00588 //this also handles vlc error in x8_get_ac_rlf 00589 return -1; 00590 } 00591 level= (level+1) * w->dquant; 00592 level+= w->qsum; 00593 00594 sign = - get_bits1(&s->gb); 00595 level = (level ^ sign) - sign; 00596 00597 if(use_quant_matrix){ 00598 level = (level*quant_table[pos])>>8; 00599 } 00600 s->block[0][ scantable[pos] ]=level; 00601 }while(!final); 00602 00603 s->block_last_index[0]=pos; 00604 }else{//DC only 00605 s->block_last_index[0]=0; 00606 if(w->flat_dc && ((unsigned)(dc_level+1)) < 3){//[-1;1] 00607 int32_t divide_quant= !chroma ? w->divide_quant_dc_luma: 00608 w->divide_quant_dc_chroma; 00609 int32_t dc_quant = !chroma ? w->quant: 00610 w->quant_dc_chroma; 00611 00612 //original intent dc_level+=predicted_dc/quant; but it got lost somewhere in the rounding 00613 dc_level+= (w->predicted_dc*divide_quant + (1<<12) )>>13; 00614 00615 dsp_x8_put_solidcolor( av_clip_uint8((dc_level*dc_quant+4)>>3), 00616 s->dest[chroma], s->current_picture.linesize[!!chroma]); 00617 00618 goto block_placed; 00619 } 00620 zeros_only = (dc_level == 0); 00621 } 00622 if(!chroma){ 00623 s->block[0][0] = dc_level*w->quant; 00624 }else{ 00625 s->block[0][0] = dc_level*w->quant_dc_chroma; 00626 } 00627 00628 //there is !zero_only check in the original, but dc_level check is enough 00629 if( (unsigned int)(dc_level+1) >= 3 && (w->edges&3) != 3 ){ 00630 int direction; 00631 /*ac_comp_direction[orient] = { 0, 3, 3, 1, 1, 0, 0, 0, 2, 2, 2, 1 };<- 00632 -> 01'10' 10'10' 00'00' 00'01' 01'11' 11'00 =>0x6A017C */ 00633 direction= (0x6A017C>>(w->orient*2))&3; 00634 if (direction != 3){ 00635 x8_ac_compensation(w, direction, s->block[0][0]);//modify block_last[] 00636 } 00637 } 00638 00639 if(w->flat_dc){ 00640 dsp_x8_put_solidcolor(w->predicted_dc, s->dest[chroma], s->current_picture.linesize[!!chroma]); 00641 }else{ 00642 s->dsp.x8_spatial_compensation[w->orient]( s->edge_emu_buffer, 00643 s->dest[chroma], 00644 s->current_picture.linesize[!!chroma] ); 00645 } 00646 if(!zeros_only) 00647 s->dsp.idct_add ( s->dest[chroma], 00648 s->current_picture.linesize[!!chroma], 00649 s->block[0] ); 00650 00651 block_placed: 00652 00653 if(!chroma){ 00654 x8_update_predictions(w,w->orient,n); 00655 } 00656 00657 if(s->loop_filter){ 00658 uint8_t* ptr = s->dest[chroma]; 00659 int linesize = s->current_picture.linesize[!!chroma]; 00660 00661 if(!( (w->edges&2) || ( zeros_only && (w->orient|4)==4 ) )){ 00662 s->dsp.x8_h_loop_filter(ptr, linesize, w->quant); 00663 } 00664 if(!( (w->edges&1) || ( zeros_only && (w->orient|8)==8 ) )){ 00665 s->dsp.x8_v_loop_filter(ptr, linesize, w->quant); 00666 } 00667 } 00668 return 0; 00669 } 00670 00671 static void x8_init_block_index(MpegEncContext *s){ //FIXME maybe merge with ff_* 00672 //not s->linesize as this would be wrong for field pics 00673 //not that IntraX8 has interlacing support ;) 00674 const int linesize = s->current_picture.linesize[0]; 00675 const int uvlinesize= s->current_picture.linesize[1]; 00676 00677 s->dest[0] = s->current_picture.data[0]; 00678 s->dest[1] = s->current_picture.data[1]; 00679 s->dest[2] = s->current_picture.data[2]; 00680 00681 s->dest[0] += s->mb_y * linesize << 3; 00682 s->dest[1] += ( s->mb_y&(~1) ) * uvlinesize << 2;//chroma blocks are on add rows 00683 s->dest[2] += ( s->mb_y&(~1) ) * uvlinesize << 2; 00684 } 00685 00692 av_cold void ff_intrax8_common_init(IntraX8Context * w, MpegEncContext * const s){ 00693 00694 w->s=s; 00695 x8_vlc_init(); 00696 assert(s->mb_width>0); 00697 w->prediction_table=av_mallocz(s->mb_width*2*2);//two rows, 2 blocks per cannon mb 00698 00699 ff_init_scantable(s->dsp.idct_permutation, &w->scantable[0], wmv1_scantable[0]); 00700 ff_init_scantable(s->dsp.idct_permutation, &w->scantable[1], wmv1_scantable[2]); 00701 ff_init_scantable(s->dsp.idct_permutation, &w->scantable[2], wmv1_scantable[3]); 00702 } 00703 00708 av_cold void ff_intrax8_common_end(IntraX8Context * w) 00709 { 00710 av_freep(&w->prediction_table); 00711 } 00712 00724 //FIXME extern uint8_t wmv3_dc_scale_table[32]; 00725 int ff_intrax8_decode_picture(IntraX8Context * const w, int dquant, int quant_offset){ 00726 MpegEncContext * const s= w->s; 00727 int mb_xy; 00728 assert(s); 00729 w->use_quant_matrix = get_bits1(&s->gb); 00730 00731 w->dquant = dquant; 00732 w->quant = dquant >> 1; 00733 w->qsum = quant_offset; 00734 00735 w->divide_quant_dc_luma = ((1<<16) + (w->quant>>1)) / w->quant; 00736 if(w->quant < 5){ 00737 w->quant_dc_chroma = w->quant; 00738 w->divide_quant_dc_chroma = w->divide_quant_dc_luma; 00739 }else{ 00740 w->quant_dc_chroma = w->quant+((w->quant+3)>>3); 00741 w->divide_quant_dc_chroma = ((1<<16) + (w->quant_dc_chroma>>1)) / w->quant_dc_chroma; 00742 } 00743 x8_reset_vlc_tables(w); 00744 00745 s->resync_mb_x=0; 00746 s->resync_mb_y=0; 00747 00748 for(s->mb_y=0; s->mb_y < s->mb_height*2; s->mb_y++){ 00749 x8_init_block_index(s); 00750 mb_xy=(s->mb_y>>1)*s->mb_stride; 00751 00752 for(s->mb_x=0; s->mb_x < s->mb_width*2; s->mb_x++){ 00753 x8_get_prediction(w); 00754 if(x8_setup_spatial_predictor(w,0)) goto error; 00755 if(x8_decode_intra_mb(w,0)) goto error; 00756 00757 if( s->mb_x & s->mb_y & 1 ){ 00758 x8_get_prediction_chroma(w); 00759 00760 /*when setting up chroma, no vlc is read, 00761 so no error condition can be reached*/ 00762 x8_setup_spatial_predictor(w,1); 00763 if(x8_decode_intra_mb(w,1)) goto error; 00764 00765 x8_setup_spatial_predictor(w,2); 00766 if(x8_decode_intra_mb(w,2)) goto error; 00767 00768 s->dest[1]+= 8; 00769 s->dest[2]+= 8; 00770 00771 /*emulate MB info in the relevant tables*/ 00772 s->mbskip_table [mb_xy]=0; 00773 s->mbintra_table[mb_xy]=1; 00774 s->current_picture.qscale_table[mb_xy]=w->quant; 00775 mb_xy++; 00776 } 00777 s->dest[0]+= 8; 00778 } 00779 if(s->mb_y&1){ 00780 ff_draw_horiz_band(s, (s->mb_y-1)*8, 16); 00781 } 00782 } 00783 00784 error: 00785 ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, 00786 (s->mb_x>>1)-1, (s->mb_y>>1)-1, 00787 (AC_END|DC_END|MV_END) ); 00788 return 0; 00789 }