| 1 | /* |
| 2 | * This file is part of FFmpeg. |
| 3 | * |
| 4 | * FFmpeg is free software; you can redistribute it and/or |
| 5 | * modify it under the terms of the GNU Lesser General Public |
| 6 | * License as published by the Free Software Foundation; either |
| 7 | * version 2.1 of the License, or (at your option) any later version. |
| 8 | * |
| 9 | * FFmpeg is distributed in the hope that it will be useful, |
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 12 | * Lesser General Public License for more details. |
| 13 | * |
| 14 | * You should have received a copy of the GNU Lesser General Public |
| 15 | * License along with FFmpeg; if not, write to the Free Software |
| 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 17 | */ |
| 18 | |
| 19 | /** |
| 20 | * @file |
| 21 | * @brief IntraX8 (J-Frame) subdecoder, used by WMV2 and VC-1 |
| 22 | */ |
| 23 | |
| 24 | #include "libavutil/avassert.h" |
| 25 | #include "avcodec.h" |
| 26 | #include "error_resilience.h" |
| 27 | #include "get_bits.h" |
| 28 | #include "idctdsp.h" |
| 29 | #include "mpegvideo.h" |
| 30 | #include "msmpeg4data.h" |
| 31 | #include "intrax8huf.h" |
| 32 | #include "intrax8.h" |
| 33 | #include "intrax8dsp.h" |
| 34 | |
| 35 | #define MAX_TABLE_DEPTH(table_bits, max_bits) ((max_bits+table_bits-1)/table_bits) |
| 36 | |
| 37 | #define DC_VLC_BITS 9 |
| 38 | #define AC_VLC_BITS 9 |
| 39 | #define OR_VLC_BITS 7 |
| 40 | |
| 41 | #define DC_VLC_MTD MAX_TABLE_DEPTH(DC_VLC_BITS, MAX_DC_VLC_BITS) |
| 42 | #define AC_VLC_MTD MAX_TABLE_DEPTH(AC_VLC_BITS, MAX_AC_VLC_BITS) |
| 43 | #define OR_VLC_MTD MAX_TABLE_DEPTH(OR_VLC_BITS, MAX_OR_VLC_BITS) |
| 44 | |
| 45 | static VLC j_ac_vlc[2][2][8]; //[quant<13],[intra/inter],[select] |
| 46 | static VLC j_dc_vlc[2][8]; //[quant], [select] |
| 47 | static VLC j_orient_vlc[2][4]; //[quant], [select] |
| 48 | |
| 49 | static av_cold void x8_vlc_init(void){ |
| 50 | int i; |
| 51 | int offset = 0; |
| 52 | int sizeidx = 0; |
| 53 | static const uint16_t sizes[8*4 + 8*2 + 2 + 4] = { |
| 54 | 576, 548, 582, 618, 546, 616, 560, 642, |
| 55 | 584, 582, 704, 664, 512, 544, 656, 640, |
| 56 | 512, 648, 582, 566, 532, 614, 596, 648, |
| 57 | 586, 552, 584, 590, 544, 578, 584, 624, |
| 58 | |
| 59 | 528, 528, 526, 528, 536, 528, 526, 544, |
| 60 | 544, 512, 512, 528, 528, 544, 512, 544, |
| 61 | |
| 62 | 128, 128, 128, 128, 128, 128}; |
| 63 | |
| 64 | static VLC_TYPE table[28150][2]; |
| 65 | |
| 66 | #define init_ac_vlc(dst,src) \ |
| 67 | dst.table = &table[offset]; \ |
| 68 | dst.table_allocated = sizes[sizeidx]; \ |
| 69 | offset += sizes[sizeidx++]; \ |
| 70 | init_vlc(&dst, \ |
| 71 | AC_VLC_BITS,77, \ |
| 72 | &src[1],4,2, \ |
| 73 | &src[0],4,2, \ |
| 74 | INIT_VLC_USE_NEW_STATIC) |
| 75 | //set ac tables |
| 76 | for(i=0;i<8;i++){ |
| 77 | init_ac_vlc( j_ac_vlc[0][0][i], x8_ac0_highquant_table[i][0] ); |
| 78 | init_ac_vlc( j_ac_vlc[0][1][i], x8_ac1_highquant_table[i][0] ); |
| 79 | init_ac_vlc( j_ac_vlc[1][0][i], x8_ac0_lowquant_table [i][0] ); |
| 80 | init_ac_vlc( j_ac_vlc[1][1][i], x8_ac1_lowquant_table [i][0] ); |
| 81 | } |
| 82 | #undef init_ac_vlc |
| 83 | |
| 84 | //set dc tables |
| 85 | #define init_dc_vlc(dst,src) \ |
| 86 | dst.table = &table[offset]; \ |
| 87 | dst.table_allocated = sizes[sizeidx]; \ |
| 88 | offset += sizes[sizeidx++]; \ |
| 89 | init_vlc(&dst, \ |
| 90 | DC_VLC_BITS,34, \ |
| 91 | &src[1],4,2, \ |
| 92 | &src[0],4,2, \ |
| 93 | INIT_VLC_USE_NEW_STATIC); |
| 94 | for(i=0;i<8;i++){ |
| 95 | init_dc_vlc( j_dc_vlc[0][i], x8_dc_highquant_table[i][0]); |
| 96 | init_dc_vlc( j_dc_vlc[1][i], x8_dc_lowquant_table [i][0]); |
| 97 | } |
| 98 | #undef init_dc_vlc |
| 99 | |
| 100 | //set orient tables |
| 101 | #define init_or_vlc(dst,src) \ |
| 102 | dst.table = &table[offset]; \ |
| 103 | dst.table_allocated = sizes[sizeidx]; \ |
| 104 | offset += sizes[sizeidx++]; \ |
| 105 | init_vlc(&dst, \ |
| 106 | OR_VLC_BITS,12, \ |
| 107 | &src[1],4,2, \ |
| 108 | &src[0],4,2, \ |
| 109 | INIT_VLC_USE_NEW_STATIC); |
| 110 | for(i=0;i<2;i++){ |
| 111 | init_or_vlc( j_orient_vlc[0][i], x8_orient_highquant_table[i][0]); |
| 112 | } |
| 113 | for(i=0;i<4;i++){ |
| 114 | init_or_vlc( j_orient_vlc[1][i], x8_orient_lowquant_table [i][0]) |
| 115 | } |
| 116 | if (offset != sizeof(table)/sizeof(VLC_TYPE)/2) |
| 117 | av_log(NULL, AV_LOG_ERROR, "table size %i does not match needed %i\n", (int)(sizeof(table)/sizeof(VLC_TYPE)/2), offset); |
| 118 | } |
| 119 | #undef init_or_vlc |
| 120 | |
| 121 | static void x8_reset_vlc_tables(IntraX8Context * w){ |
| 122 | memset(w->j_dc_vlc,0,sizeof(w->j_dc_vlc)); |
| 123 | memset(w->j_ac_vlc,0,sizeof(w->j_ac_vlc)); |
| 124 | w->j_orient_vlc=NULL; |
| 125 | } |
| 126 | |
| 127 | static inline void x8_select_ac_table(IntraX8Context * const w , int mode){ |
| 128 | MpegEncContext * const s= w->s; |
| 129 | int table_index; |
| 130 | |
| 131 | av_assert2(mode<4); |
| 132 | |
| 133 | if( w->j_ac_vlc[mode] ) return; |
| 134 | |
| 135 | table_index = get_bits(&s->gb, 3); |
| 136 | w->j_ac_vlc[mode] = &j_ac_vlc[w->quant<13][mode>>1][table_index];//2 modes use same tables |
| 137 | av_assert2(w->j_ac_vlc[mode]); |
| 138 | } |
| 139 | |
| 140 | static inline int x8_get_orient_vlc(IntraX8Context * w){ |
| 141 | MpegEncContext * const s= w->s; |
| 142 | int table_index; |
| 143 | |
| 144 | if(!w->j_orient_vlc ){ |
| 145 | table_index = get_bits(&s->gb, 1+(w->quant<13) ); |
| 146 | w->j_orient_vlc = &j_orient_vlc[w->quant<13][table_index]; |
| 147 | } |
| 148 | |
| 149 | return get_vlc2(&s->gb, w->j_orient_vlc->table, OR_VLC_BITS, OR_VLC_MTD); |
| 150 | } |
| 151 | |
| 152 | #define extra_bits(eb) (eb) |
| 153 | #define extra_run (0xFF<<8) |
| 154 | #define extra_level (0x00<<8) |
| 155 | #define run_offset(r) ((r)<<16) |
| 156 | #define level_offset(l) ((l)<<24) |
| 157 | static const uint32_t ac_decode_table[]={ |
| 158 | /*46*/ extra_bits(3) | extra_run | run_offset(16) | level_offset( 0), |
| 159 | /*47*/ extra_bits(3) | extra_run | run_offset(24) | level_offset( 0), |
| 160 | /*48*/ extra_bits(2) | extra_run | run_offset( 4) | level_offset( 1), |
| 161 | /*49*/ extra_bits(3) | extra_run | run_offset( 8) | level_offset( 1), |
| 162 | |
| 163 | /*50*/ extra_bits(5) | extra_run | run_offset(32) | level_offset( 0), |
| 164 | /*51*/ extra_bits(4) | extra_run | run_offset(16) | level_offset( 1), |
| 165 | |
| 166 | /*52*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset( 4), |
| 167 | /*53*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset( 8), |
| 168 | /*54*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset(12), |
| 169 | /*55*/ extra_bits(3) | extra_level | run_offset( 0) | level_offset(16), |
| 170 | /*56*/ extra_bits(3) | extra_level | run_offset( 0) | level_offset(24), |
| 171 | |
| 172 | /*57*/ extra_bits(2) | extra_level | run_offset( 1) | level_offset( 3), |
| 173 | /*58*/ extra_bits(3) | extra_level | run_offset( 1) | level_offset( 7), |
| 174 | |
| 175 | /*59*/ extra_bits(2) | extra_run | run_offset(16) | level_offset( 0), |
| 176 | /*60*/ extra_bits(2) | extra_run | run_offset(20) | level_offset( 0), |
| 177 | /*61*/ extra_bits(2) | extra_run | run_offset(24) | level_offset( 0), |
| 178 | /*62*/ extra_bits(2) | extra_run | run_offset(28) | level_offset( 0), |
| 179 | /*63*/ extra_bits(4) | extra_run | run_offset(32) | level_offset( 0), |
| 180 | /*64*/ extra_bits(4) | extra_run | run_offset(48) | level_offset( 0), |
| 181 | |
| 182 | /*65*/ extra_bits(2) | extra_run | run_offset( 4) | level_offset( 1), |
| 183 | /*66*/ extra_bits(3) | extra_run | run_offset( 8) | level_offset( 1), |
| 184 | /*67*/ extra_bits(4) | extra_run | run_offset(16) | level_offset( 1), |
| 185 | |
| 186 | /*68*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset( 4), |
| 187 | /*69*/ extra_bits(3) | extra_level | run_offset( 0) | level_offset( 8), |
| 188 | /*70*/ extra_bits(4) | extra_level | run_offset( 0) | level_offset(16), |
| 189 | |
| 190 | /*71*/ extra_bits(2) | extra_level | run_offset( 1) | level_offset( 3), |
| 191 | /*72*/ extra_bits(3) | extra_level | run_offset( 1) | level_offset( 7), |
| 192 | }; |
| 193 | //extra_bits = 3bits; extra_run/level = 1 bit; run_offset = 6bits; level_offset = 5 bits; |
| 194 | #undef extra_bits |
| 195 | #undef extra_run |
| 196 | #undef extra_level |
| 197 | #undef run_offset |
| 198 | #undef level_offset |
| 199 | |
| 200 | static void x8_get_ac_rlf(IntraX8Context * const w, const int mode, |
| 201 | int * const run, int * const level, int * const final){ |
| 202 | MpegEncContext * const s= w->s; |
| 203 | int i,e; |
| 204 | |
| 205 | // x8_select_ac_table(w,mode); |
| 206 | i = get_vlc2(&s->gb, w->j_ac_vlc[mode]->table, AC_VLC_BITS, AC_VLC_MTD); |
| 207 | |
| 208 | if(i<46){ //[0-45] |
| 209 | int t,l; |
| 210 | if(i<0){ |
| 211 | (*level)=(*final)=//prevent 'may be used unilitialized' |
| 212 | (*run)=64;//this would cause error exit in the ac loop |
| 213 | return; |
| 214 | } |
| 215 | |
| 216 | (*final) = t = (i>22); |
| 217 | i-=23*t; |
| 218 | /* |
| 219 | i== 0-15 r=0-15 l=0 ;r=i& %01111 |
| 220 | i==16-19 r=0-3 l=1 ;r=i& %00011 |
| 221 | i==20-21 r=0-1 l=2 ;r=i& %00001 |
| 222 | i==22 r=0 l=3 ;r=i& %00000 |
| 223 | 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 |
| 224 | t=lut_mask[l]={0x0f,0x03,0x01,0x00}[l]; as i<256 the higher bits do not matter */ |
| 225 | l=(0xE50000>>(i&(0x1E)))&3;/*0x1E or (~1) or ((i>>1)<<1)*/ |
| 226 | t=(0x01030F>>(l<<3)); |
| 227 | |
| 228 | (*run) = i&t; |
| 229 | (*level) = l; |
| 230 | }else if(i<73){//[46-72] |
| 231 | uint32_t sm; |
| 232 | uint32_t mask; |
| 233 | |
| 234 | i-=46; |
| 235 | sm=ac_decode_table[i]; |
| 236 | |
| 237 | e=get_bits(&s->gb,sm&0xF);sm>>=8;//3bits |
| 238 | mask=sm&0xff;sm>>=8; //1bit |
| 239 | |
| 240 | (*run) =(sm&0xff) + (e&( mask));//6bits |
| 241 | (*level)=(sm>>8) + (e&(~mask));//5bits |
| 242 | (*final)=i>(58-46); |
| 243 | }else if(i<75){//[73-74] |
| 244 | static const uint8_t crazy_mix_runlevel[32]={ |
| 245 | 0x22,0x32,0x33,0x53,0x23,0x42,0x43,0x63, |
| 246 | 0x24,0x52,0x34,0x73,0x25,0x62,0x44,0x83, |
| 247 | 0x26,0x72,0x35,0x54,0x27,0x82,0x45,0x64, |
| 248 | 0x28,0x92,0x36,0x74,0x29,0xa2,0x46,0x84}; |
| 249 | |
| 250 | (*final)=!(i&1); |
| 251 | e=get_bits(&s->gb,5);//get the extra bits |
| 252 | (*run) =crazy_mix_runlevel[e]>>4; |
| 253 | (*level)=crazy_mix_runlevel[e]&0x0F; |
| 254 | }else{ |
| 255 | (*level)=get_bits( &s->gb, 7-3*(i&1)); |
| 256 | (*run) =get_bits( &s->gb, 6); |
| 257 | (*final)=get_bits1(&s->gb); |
| 258 | } |
| 259 | return; |
| 260 | } |
| 261 | |
| 262 | //static const uint8_t dc_extra_sbits[] ={0, 1,1, 1,1, 2,2, 3,3, 4,4, 5,5, 6,6, 7,7 }; |
| 263 | static const uint8_t dc_index_offset[] ={ 0, 1,2, 3,4, 5,7, 9,13, 17,25, 33,49, 65,97, 129,193}; |
| 264 | |
| 265 | static int x8_get_dc_rlf(IntraX8Context * const w,int const mode, int * const level, int * const final){ |
| 266 | MpegEncContext * const s= w->s; |
| 267 | int i,e,c; |
| 268 | |
| 269 | av_assert2(mode<3); |
| 270 | if( !w->j_dc_vlc[mode] ) { |
| 271 | int table_index; |
| 272 | table_index = get_bits(&s->gb, 3); |
| 273 | //4 modes, same table |
| 274 | w->j_dc_vlc[mode]= &j_dc_vlc[w->quant<13][table_index]; |
| 275 | } |
| 276 | |
| 277 | i=get_vlc2(&s->gb, w->j_dc_vlc[mode]->table, DC_VLC_BITS, DC_VLC_MTD); |
| 278 | |
| 279 | /*(i>=17) {i-=17;final=1;}*/ |
| 280 | c= i>16; |
| 281 | (*final)=c; |
| 282 | i-=17*c; |
| 283 | |
| 284 | if(i<=0){ |
| 285 | (*level)=0; |
| 286 | return -i; |
| 287 | } |
| 288 | c=(i+1)>>1;//hackish way to calculate dc_extra_sbits[] |
| 289 | c-=c>1; |
| 290 | |
| 291 | e=get_bits(&s->gb,c);//get the extra bits |
| 292 | i=dc_index_offset[i]+(e>>1); |
| 293 | |
| 294 | e= -(e & 1);//0,0xffffff |
| 295 | (*level)= (i ^ e) - e;// (i^0)-0 , (i^0xff)-(-1) |
| 296 | return 0; |
| 297 | } |
| 298 | //end of huffman |
| 299 | |
| 300 | static int x8_setup_spatial_predictor(IntraX8Context * const w, const int chroma){ |
| 301 | MpegEncContext * const s= w->s; |
| 302 | int range; |
| 303 | int sum; |
| 304 | int quant; |
| 305 | |
| 306 | w->dsp.setup_spatial_compensation(s->dest[chroma], s->edge_emu_buffer, |
| 307 | s->current_picture.f->linesize[chroma>0], |
| 308 | &range, &sum, w->edges); |
| 309 | if(chroma){ |
| 310 | w->orient=w->chroma_orient; |
| 311 | quant=w->quant_dc_chroma; |
| 312 | }else{ |
| 313 | quant=w->quant; |
| 314 | } |
| 315 | |
| 316 | w->flat_dc=0; |
| 317 | if(range < quant || range < 3){ |
| 318 | w->orient=0; |
| 319 | if(range < 3){//yep you read right, a +-1 idct error may break decoding! |
| 320 | w->flat_dc=1; |
| 321 | sum+=9; |
| 322 | w->predicted_dc = (sum*6899)>>17;//((1<<17)+9)/(8+8+1+2)=6899 |
| 323 | } |
| 324 | } |
| 325 | if(chroma) |
| 326 | return 0; |
| 327 | |
| 328 | av_assert2(w->orient < 3); |
| 329 | if(range < 2*w->quant){ |
| 330 | if( (w->edges&3) == 0){ |
| 331 | if(w->orient==1) w->orient=11; |
| 332 | if(w->orient==2) w->orient=10; |
| 333 | }else{ |
| 334 | w->orient=0; |
| 335 | } |
| 336 | w->raw_orient=0; |
| 337 | }else{ |
| 338 | static const uint8_t prediction_table[3][12]={ |
| 339 | {0,8,4, 10,11, 2,6,9,1,3,5,7}, |
| 340 | {4,0,8, 11,10, 3,5,2,6,9,1,7}, |
| 341 | {8,0,4, 10,11, 1,7,2,6,9,3,5} |
| 342 | }; |
| 343 | w->raw_orient=x8_get_orient_vlc(w); |
| 344 | if(w->raw_orient<0) return -1; |
| 345 | av_assert2(w->raw_orient < 12 ); |
| 346 | av_assert2(w->orient<3); |
| 347 | w->orient=prediction_table[w->orient][w->raw_orient]; |
| 348 | } |
| 349 | return 0; |
| 350 | } |
| 351 | |
| 352 | static void x8_update_predictions(IntraX8Context * const w, const int orient, const int est_run ){ |
| 353 | MpegEncContext * const s= w->s; |
| 354 | |
| 355 | w->prediction_table[s->mb_x*2+(s->mb_y&1)] = (est_run<<2) + 1*(orient==4) + 2*(orient==8); |
| 356 | /* |
| 357 | y=2n+0 ->//0 2 4 |
| 358 | y=2n+1 ->//1 3 5 |
| 359 | */ |
| 360 | } |
| 361 | static void x8_get_prediction_chroma(IntraX8Context * const w){ |
| 362 | MpegEncContext * const s= w->s; |
| 363 | |
| 364 | w->edges = 1*( !(s->mb_x>>1) ); |
| 365 | w->edges|= 2*( !(s->mb_y>>1) ); |
| 366 | w->edges|= 4*( s->mb_x >= (2*s->mb_width-1) );//mb_x for chroma would always be odd |
| 367 | |
| 368 | w->raw_orient=0; |
| 369 | if(w->edges&3){//lut_co[8]={inv,4,8,8, inv,4,8,8}<- =>{1,1,0,0;1,1,0,0} => 0xCC |
| 370 | w->chroma_orient=4<<((0xCC>>w->edges)&1); |
| 371 | return; |
| 372 | } |
| 373 | w->chroma_orient = (w->prediction_table[2*s->mb_x-2] & 0x03)<<2;//block[x-1][y|1-1)] |
| 374 | } |
| 375 | |
| 376 | static void x8_get_prediction(IntraX8Context * const w){ |
| 377 | MpegEncContext * const s= w->s; |
| 378 | int a,b,c,i; |
| 379 | |
| 380 | w->edges = 1*( !s->mb_x ); |
| 381 | w->edges|= 2*( !s->mb_y ); |
| 382 | w->edges|= 4*( s->mb_x >= (2*s->mb_width-1) ); |
| 383 | |
| 384 | switch(w->edges&3){ |
| 385 | case 0: |
| 386 | break; |
| 387 | case 1: |
| 388 | //take the one from the above block[0][y-1] |
| 389 | w->est_run = w->prediction_table[!(s->mb_y&1)]>>2; |
| 390 | w->orient = 1; |
| 391 | return; |
| 392 | case 2: |
| 393 | //take the one from the previous block[x-1][0] |
| 394 | w->est_run = w->prediction_table[2*s->mb_x-2]>>2; |
| 395 | w->orient = 2; |
| 396 | return; |
| 397 | case 3: |
| 398 | w->est_run = 16; |
| 399 | w->orient = 0; |
| 400 | return; |
| 401 | } |
| 402 | //no edge cases |
| 403 | b= w->prediction_table[2*s->mb_x + !(s->mb_y&1) ];//block[x ][y-1] |
| 404 | a= w->prediction_table[2*s->mb_x-2 + (s->mb_y&1) ];//block[x-1][y ] |
| 405 | c= w->prediction_table[2*s->mb_x-2 + !(s->mb_y&1) ];//block[x-1][y-1] |
| 406 | |
| 407 | w->est_run = FFMIN(b,a); |
| 408 | /* This condition has nothing to do with w->edges, even if it looks |
| 409 | similar it would trigger if e.g. x=3;y=2; |
| 410 | I guess somebody wrote something wrong and it became standard. */ |
| 411 | if( (s->mb_x & s->mb_y) != 0 ) w->est_run=FFMIN(c,w->est_run); |
| 412 | w->est_run>>=2; |
| 413 | |
| 414 | a&=3; |
| 415 | b&=3; |
| 416 | c&=3; |
| 417 | |
| 418 | i=( 0xFFEAF4C4>>(2*b+8*a) )&3; |
| 419 | if(i!=3) w->orient=i; |
| 420 | else w->orient=( 0xFFEAD8>>(2*c+8*(w->quant>12)) )&3; |
| 421 | /* |
| 422 | lut1[b][a]={ |
| 423 | ->{0, 1, 0, pad}, |
| 424 | {0, 1, X, pad}, |
| 425 | {2, 2, 2, pad}} |
| 426 | pad 2 2 2; pad X 1 0; pad 0 1 0 <- |
| 427 | -> 11 10 '10 10 '11 11'01 00 '11 00'01 00=>0xEAF4C4 |
| 428 | |
| 429 | lut2[q>12][c]={ |
| 430 | ->{0,2,1,pad}, |
| 431 | {2,2,2,pad}} |
| 432 | pad 2 2 2; pad 1 2 0 <- |
| 433 | -> 11 10'10 10 '11 01'10 00=>0xEAD8 |
| 434 | */ |
| 435 | } |
| 436 | |
| 437 | |
| 438 | static void x8_ac_compensation(IntraX8Context * const w, int const direction, int const dc_level){ |
| 439 | MpegEncContext * const s= w->s; |
| 440 | int t; |
| 441 | #define B(x,y) s->block[0][w->idct_permutation[(x)+(y)*8]] |
| 442 | #define T(x) ((x) * dc_level + 0x8000) >> 16; |
| 443 | switch(direction){ |
| 444 | case 0: |
| 445 | t = T(3811);//h |
| 446 | B(1,0) -= t; |
| 447 | B(0,1) -= t; |
| 448 | |
| 449 | t = T(487);//e |
| 450 | B(2,0) -= t; |
| 451 | B(0,2) -= t; |
| 452 | |
| 453 | t = T(506);//f |
| 454 | B(3,0) -= t; |
| 455 | B(0,3) -= t; |
| 456 | |
| 457 | t = T(135);//c |
| 458 | B(4,0) -= t; |
| 459 | B(0,4) -= t; |
| 460 | B(2,1) += t; |
| 461 | B(1,2) += t; |
| 462 | B(3,1) += t; |
| 463 | B(1,3) += t; |
| 464 | |
| 465 | t = T(173);//d |
| 466 | B(5,0) -= t; |
| 467 | B(0,5) -= t; |
| 468 | |
| 469 | t = T(61);//b |
| 470 | B(6,0) -= t; |
| 471 | B(0,6) -= t; |
| 472 | B(5,1) += t; |
| 473 | B(1,5) += t; |
| 474 | |
| 475 | t = T(42); //a |
| 476 | B(7,0) -= t; |
| 477 | B(0,7) -= t; |
| 478 | B(4,1) += t; |
| 479 | B(1,4) += t; |
| 480 | B(4,4) += t; |
| 481 | |
| 482 | t = T(1084);//g |
| 483 | B(1,1) += t; |
| 484 | |
| 485 | s->block_last_index[0] = FFMAX(s->block_last_index[0], 7*8); |
| 486 | break; |
| 487 | case 1: |
| 488 | B(0,1) -= T(6269); |
| 489 | B(0,3) -= T( 708); |
| 490 | B(0,5) -= T( 172); |
| 491 | B(0,7) -= T( 73); |
| 492 | |
| 493 | s->block_last_index[0] = FFMAX(s->block_last_index[0], 7*8); |
| 494 | break; |
| 495 | case 2: |
| 496 | B(1,0) -= T(6269); |
| 497 | B(3,0) -= T( 708); |
| 498 | B(5,0) -= T( 172); |
| 499 | B(7,0) -= T( 73); |
| 500 | |
| 501 | s->block_last_index[0] = FFMAX(s->block_last_index[0], 7); |
| 502 | break; |
| 503 | } |
| 504 | #undef B |
| 505 | #undef T |
| 506 | } |
| 507 | |
| 508 | static void dsp_x8_put_solidcolor(uint8_t const pix, uint8_t * dst, int const linesize){ |
| 509 | int k; |
| 510 | for(k=0;k<8;k++){ |
| 511 | memset(dst,pix,8); |
| 512 | dst+=linesize; |
| 513 | } |
| 514 | } |
| 515 | |
| 516 | static const int16_t quant_table[64] = { |
| 517 | 256, 256, 256, 256, 256, 256, 259, 262, |
| 518 | 265, 269, 272, 275, 278, 282, 285, 288, |
| 519 | 292, 295, 299, 303, 306, 310, 314, 317, |
| 520 | 321, 325, 329, 333, 337, 341, 345, 349, |
| 521 | 353, 358, 362, 366, 371, 375, 379, 384, |
| 522 | 389, 393, 398, 403, 408, 413, 417, 422, |
| 523 | 428, 433, 438, 443, 448, 454, 459, 465, |
| 524 | 470, 476, 482, 488, 493, 499, 505, 511 |
| 525 | }; |
| 526 | |
| 527 | static int x8_decode_intra_mb(IntraX8Context* const w, const int chroma){ |
| 528 | MpegEncContext * const s= w->s; |
| 529 | |
| 530 | uint8_t * scantable; |
| 531 | int final,run,level; |
| 532 | int ac_mode,dc_mode,est_run,dc_level; |
| 533 | int pos,n; |
| 534 | int zeros_only; |
| 535 | int use_quant_matrix; |
| 536 | int sign; |
| 537 | |
| 538 | av_assert2(w->orient<12); |
| 539 | s->bdsp.clear_block(s->block[0]); |
| 540 | |
| 541 | if(chroma){ |
| 542 | dc_mode=2; |
| 543 | }else{ |
| 544 | dc_mode=!!w->est_run;//0,1 |
| 545 | } |
| 546 | |
| 547 | if(x8_get_dc_rlf(w, dc_mode, &dc_level, &final)) return -1; |
| 548 | n=0; |
| 549 | zeros_only=0; |
| 550 | if(!final){//decode ac |
| 551 | use_quant_matrix=w->use_quant_matrix; |
| 552 | if(chroma){ |
| 553 | ac_mode = 1; |
| 554 | est_run = 64;//not used |
| 555 | }else{ |
| 556 | if (w->raw_orient < 3){ |
| 557 | use_quant_matrix = 0; |
| 558 | } |
| 559 | if(w->raw_orient > 4){ |
| 560 | ac_mode = 0; |
| 561 | est_run = 64; |
| 562 | }else{ |
| 563 | if(w->est_run > 1){ |
| 564 | ac_mode = 2; |
| 565 | est_run=w->est_run; |
| 566 | }else{ |
| 567 | ac_mode = 3; |
| 568 | est_run = 64; |
| 569 | } |
| 570 | } |
| 571 | } |
| 572 | x8_select_ac_table(w,ac_mode); |
| 573 | /*scantable_selector[12]={0,2,0,1,1,1,0,2,2,0,1,2};<- |
| 574 | -> 10'01' 00'10' 10'00' 01'01' 01'00' 10'00 =>0x928548 */ |
| 575 | scantable = w->scantable[ (0x928548>>(2*w->orient))&3 ].permutated; |
| 576 | pos=0; |
| 577 | do { |
| 578 | n++; |
| 579 | if( n >= est_run ){ |
| 580 | ac_mode=3; |
| 581 | x8_select_ac_table(w,3); |
| 582 | } |
| 583 | |
| 584 | x8_get_ac_rlf(w,ac_mode,&run,&level,&final); |
| 585 | |
| 586 | pos+=run+1; |
| 587 | if(pos>63){ |
| 588 | //this also handles vlc error in x8_get_ac_rlf |
| 589 | return -1; |
| 590 | } |
| 591 | level= (level+1) * w->dquant; |
| 592 | level+= w->qsum; |
| 593 | |
| 594 | sign = - get_bits1(&s->gb); |
| 595 | level = (level ^ sign) - sign; |
| 596 | |
| 597 | if(use_quant_matrix){ |
| 598 | level = (level*quant_table[pos])>>8; |
| 599 | } |
| 600 | s->block[0][ scantable[pos] ]=level; |
| 601 | }while(!final); |
| 602 | |
| 603 | s->block_last_index[0]=pos; |
| 604 | }else{//DC only |
| 605 | s->block_last_index[0]=0; |
| 606 | if(w->flat_dc && ((unsigned)(dc_level+1)) < 3){//[-1;1] |
| 607 | int32_t divide_quant= !chroma ? w->divide_quant_dc_luma: |
| 608 | w->divide_quant_dc_chroma; |
| 609 | int32_t dc_quant = !chroma ? w->quant: |
| 610 | w->quant_dc_chroma; |
| 611 | |
| 612 | //original intent dc_level+=predicted_dc/quant; but it got lost somewhere in the rounding |
| 613 | dc_level+= (w->predicted_dc*divide_quant + (1<<12) )>>13; |
| 614 | |
| 615 | dsp_x8_put_solidcolor( av_clip_uint8((dc_level*dc_quant+4)>>3), |
| 616 | s->dest[chroma], s->current_picture.f->linesize[!!chroma]); |
| 617 | |
| 618 | goto block_placed; |
| 619 | } |
| 620 | zeros_only = (dc_level == 0); |
| 621 | } |
| 622 | if(!chroma){ |
| 623 | s->block[0][0] = dc_level*w->quant; |
| 624 | }else{ |
| 625 | s->block[0][0] = dc_level*w->quant_dc_chroma; |
| 626 | } |
| 627 | |
| 628 | //there is !zero_only check in the original, but dc_level check is enough |
| 629 | if( (unsigned int)(dc_level+1) >= 3 && (w->edges&3) != 3 ){ |
| 630 | int direction; |
| 631 | /*ac_comp_direction[orient] = { 0, 3, 3, 1, 1, 0, 0, 0, 2, 2, 2, 1 };<- |
| 632 | -> 01'10' 10'10' 00'00' 00'01' 01'11' 11'00 =>0x6A017C */ |
| 633 | direction= (0x6A017C>>(w->orient*2))&3; |
| 634 | if (direction != 3){ |
| 635 | x8_ac_compensation(w, direction, s->block[0][0]);//modify block_last[] |
| 636 | } |
| 637 | } |
| 638 | |
| 639 | if(w->flat_dc){ |
| 640 | dsp_x8_put_solidcolor(w->predicted_dc, s->dest[chroma], s->current_picture.f->linesize[!!chroma]); |
| 641 | }else{ |
| 642 | w->dsp.spatial_compensation[w->orient]( s->edge_emu_buffer, |
| 643 | s->dest[chroma], |
| 644 | s->current_picture.f->linesize[!!chroma] ); |
| 645 | } |
| 646 | if(!zeros_only) |
| 647 | w->wdsp.idct_add(s->dest[chroma], |
| 648 | s->current_picture.f->linesize[!!chroma], |
| 649 | s->block[0]); |
| 650 | |
| 651 | block_placed: |
| 652 | |
| 653 | if(!chroma){ |
| 654 | x8_update_predictions(w,w->orient,n); |
| 655 | } |
| 656 | |
| 657 | if(s->loop_filter){ |
| 658 | uint8_t* ptr = s->dest[chroma]; |
| 659 | int linesize = s->current_picture.f->linesize[!!chroma]; |
| 660 | |
| 661 | if(!( (w->edges&2) || ( zeros_only && (w->orient|4)==4 ) )){ |
| 662 | w->dsp.h_loop_filter(ptr, linesize, w->quant); |
| 663 | } |
| 664 | if(!( (w->edges&1) || ( zeros_only && (w->orient|8)==8 ) )){ |
| 665 | w->dsp.v_loop_filter(ptr, linesize, w->quant); |
| 666 | } |
| 667 | } |
| 668 | return 0; |
| 669 | } |
| 670 | |
| 671 | static void x8_init_block_index(MpegEncContext *s){ //FIXME maybe merge with ff_* |
| 672 | //not s->linesize as this would be wrong for field pics |
| 673 | //not that IntraX8 has interlacing support ;) |
| 674 | const int linesize = s->current_picture.f->linesize[0]; |
| 675 | const int uvlinesize = s->current_picture.f->linesize[1]; |
| 676 | |
| 677 | s->dest[0] = s->current_picture.f->data[0]; |
| 678 | s->dest[1] = s->current_picture.f->data[1]; |
| 679 | s->dest[2] = s->current_picture.f->data[2]; |
| 680 | |
| 681 | s->dest[0] += s->mb_y * linesize << 3; |
| 682 | s->dest[1] += ( s->mb_y&(~1) ) * uvlinesize << 2;//chroma blocks are on add rows |
| 683 | s->dest[2] += ( s->mb_y&(~1) ) * uvlinesize << 2; |
| 684 | } |
| 685 | |
| 686 | /** |
| 687 | * Initialize IntraX8 frame decoder. |
| 688 | * Requires valid MpegEncContext with valid s->mb_width before calling. |
| 689 | * @param w pointer to IntraX8Context |
| 690 | * @param s pointer to MpegEncContext of the parent codec |
| 691 | */ |
| 692 | av_cold void ff_intrax8_common_init(IntraX8Context * w, MpegEncContext * const s){ |
| 693 | |
| 694 | w->s=s; |
| 695 | x8_vlc_init(); |
| 696 | av_assert0(s->mb_width>0); |
| 697 | w->prediction_table=av_mallocz(s->mb_width*2*2);//two rows, 2 blocks per cannon mb |
| 698 | |
| 699 | ff_wmv2dsp_init(&w->wdsp); |
| 700 | ff_init_scantable_permutation(w->idct_permutation, |
| 701 | w->wdsp.idct_perm); |
| 702 | |
| 703 | ff_init_scantable(w->idct_permutation, &w->scantable[0], ff_wmv1_scantable[0]); |
| 704 | ff_init_scantable(w->idct_permutation, &w->scantable[1], ff_wmv1_scantable[2]); |
| 705 | ff_init_scantable(w->idct_permutation, &w->scantable[2], ff_wmv1_scantable[3]); |
| 706 | |
| 707 | ff_intrax8dsp_init(&w->dsp); |
| 708 | } |
| 709 | |
| 710 | /** |
| 711 | * Destroy IntraX8 frame structure. |
| 712 | * @param w pointer to IntraX8Context |
| 713 | */ |
| 714 | av_cold void ff_intrax8_common_end(IntraX8Context * w) |
| 715 | { |
| 716 | av_freep(&w->prediction_table); |
| 717 | } |
| 718 | |
| 719 | /** |
| 720 | * Decode single IntraX8 frame. |
| 721 | * The parent codec must fill s->loopfilter and s->gb (bitstream). |
| 722 | * The parent codec must call ff_mpv_frame_start(), ff_er_frame_start() before calling this function. |
| 723 | * The parent codec must call ff_er_frame_end(), ff_mpv_frame_end() after calling this function. |
| 724 | * This function does not use ff_mpv_decode_mb(). |
| 725 | * lowres decoding is theoretically impossible. |
| 726 | * @param w pointer to IntraX8Context |
| 727 | * @param dquant doubled quantizer, it would be odd in case of VC-1 halfpq==1. |
| 728 | * @param quant_offset offset away from zero |
| 729 | */ |
| 730 | int ff_intrax8_decode_picture(IntraX8Context * const w, int dquant, int quant_offset){ |
| 731 | MpegEncContext * const s= w->s; |
| 732 | int mb_xy; |
| 733 | w->use_quant_matrix = get_bits1(&s->gb); |
| 734 | |
| 735 | w->dquant = dquant; |
| 736 | w->quant = dquant >> 1; |
| 737 | w->qsum = quant_offset; |
| 738 | |
| 739 | w->divide_quant_dc_luma = ((1<<16) + (w->quant>>1)) / w->quant; |
| 740 | if(w->quant < 5){ |
| 741 | w->quant_dc_chroma = w->quant; |
| 742 | w->divide_quant_dc_chroma = w->divide_quant_dc_luma; |
| 743 | }else{ |
| 744 | w->quant_dc_chroma = w->quant+((w->quant+3)>>3); |
| 745 | w->divide_quant_dc_chroma = ((1<<16) + (w->quant_dc_chroma>>1)) / w->quant_dc_chroma; |
| 746 | } |
| 747 | x8_reset_vlc_tables(w); |
| 748 | |
| 749 | s->resync_mb_x=0; |
| 750 | s->resync_mb_y=0; |
| 751 | |
| 752 | for(s->mb_y=0; s->mb_y < s->mb_height*2; s->mb_y++){ |
| 753 | x8_init_block_index(s); |
| 754 | mb_xy=(s->mb_y>>1)*s->mb_stride; |
| 755 | |
| 756 | for(s->mb_x=0; s->mb_x < s->mb_width*2; s->mb_x++){ |
| 757 | x8_get_prediction(w); |
| 758 | if(x8_setup_spatial_predictor(w,0)) goto error; |
| 759 | if(x8_decode_intra_mb(w,0)) goto error; |
| 760 | |
| 761 | if( s->mb_x & s->mb_y & 1 ){ |
| 762 | x8_get_prediction_chroma(w); |
| 763 | |
| 764 | /*when setting up chroma, no vlc is read, |
| 765 | so no error condition can be reached*/ |
| 766 | x8_setup_spatial_predictor(w,1); |
| 767 | if(x8_decode_intra_mb(w,1)) goto error; |
| 768 | |
| 769 | x8_setup_spatial_predictor(w,2); |
| 770 | if(x8_decode_intra_mb(w,2)) goto error; |
| 771 | |
| 772 | s->dest[1]+= 8; |
| 773 | s->dest[2]+= 8; |
| 774 | |
| 775 | /*emulate MB info in the relevant tables*/ |
| 776 | s->mbskip_table [mb_xy]=0; |
| 777 | s->mbintra_table[mb_xy]=1; |
| 778 | s->current_picture.qscale_table[mb_xy] = w->quant; |
| 779 | mb_xy++; |
| 780 | } |
| 781 | s->dest[0]+= 8; |
| 782 | } |
| 783 | if(s->mb_y&1){ |
| 784 | ff_mpeg_draw_horiz_band(s, (s->mb_y-1)*8, 16); |
| 785 | } |
| 786 | } |
| 787 | |
| 788 | error: |
| 789 | ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, |
| 790 | (s->mb_x>>1)-1, (s->mb_y>>1)-1, |
| 791 | ER_MB_END ); |
| 792 | return 0; |
| 793 | } |