1 2 module macroblock; 3 4 import std.exception; 5 import std.stdio; 6 import bitstream; 7 import vlc; 8 import decoder; 9 10 enum PredictionType 11 { 12 Field, 13 Frame, 14 DualPrime, 15 Mc16x8, 16 } 17 18 enum MvFormat 19 { 20 Field, 21 Frame, 22 } 23 24 struct Block 25 { 26 short[64] coeffs; 27 } 28 29 struct MacroBlock 30 { 31 Slice s; 32 MbParams p; 33 ubyte incr; 34 uint type; 35 ubyte spartial_temporal_weight_code; 36 ubyte motion_type; 37 ubyte dct_type; 38 ubyte quantiser_scale_code; 39 bool[2][2] motion_vertical_field_select; 40 byte[2][2][2] motion_code; 41 ubyte[2][2][2] motion_residual; 42 ubyte[2] dmvector; 43 uint coded_block_pattern; 44 Block[12] blocks; 45 46 this(Slice s) 47 { 48 this.s = s; 49 } 50 51 void parse(BitstreamReader bs) 52 { 53 int temp_incr = bs.read_mb_inc(); 54 55 while(temp_incr == 34) 56 { 57 this.incr += 33; 58 temp_incr = bs.read_mb_inc(); 59 } 60 61 this.incr += temp_incr; 62 63 parse_modes(bs); 64 65 if(p.quant) 66 { 67 this.quantiser_scale_code = cast(ubyte) bs.read_u(5); 68 } 69 70 if(p.motion_forward || (p.intra && s.ph.concealment_motion_vectors)) 71 { 72 parse_motion_vectors(bs, 0); 73 } 74 75 if(p.motion_backward) 76 { 77 parse_motion_vectors(bs, 1); 78 } 79 80 if(p.intra && s.ph.concealment_motion_vectors) 81 { 82 enforce(bs.read_u1 == 1, "marker bit"); 83 } 84 85 if(p.pattern) 86 { 87 parse_coded_block_pattern(bs); 88 } 89 90 for(ubyte i=0; i< block_count(); ++i) 91 { 92 parse_block(bs, i); 93 } 94 } 95 96 ubyte block_count() const 97 { 98 immutable ubyte[] table = [ 99 0, // should not happen 100 6, 101 8, 102 12, 103 ]; 104 105 return table[s.ph.si.chroma_format]; 106 } 107 108 void parse_motion_vectors(BitstreamReader bs, ubyte s) 109 { 110 if(predinfo.motion_vector_count == 1) 111 { 112 if(predinfo.mv_format == MvFormat.Field && predinfo.dmv != 1) 113 { 114 motion_vertical_field_select[0][s] = bs.read_bool; 115 } 116 117 parse_mv(bs, 0, s); 118 } 119 else 120 { 121 motion_vertical_field_select[0][s] = bs.read_bool; 122 parse_mv(bs, 0, s); 123 motion_vertical_field_select[1][s] = bs.read_bool; 124 parse_mv(bs, 1, s); 125 } 126 } 127 128 void parse_mv(BitstreamReader bs, ubyte r, ubyte s) 129 { 130 motion_code[r][s][0] = bs.read_mc; 131 if(this.s.ph.f_code[s][0] != 1 && motion_code[r][s][0] != 0) 132 { 133 motion_residual[r][s][0] = bs.read_b(this.s.ph.f_code[s][0] - 1); 134 } 135 if(predinfo.dmv == 1) 136 { 137 dmvector[0] = bs.read_dmvector(); 138 } 139 140 motion_code[r][s][1] = bs.read_mc; 141 if(this.s.ph.f_code[s][1] != 1 && motion_code[r][s][1] != 0) 142 { 143 motion_residual[r][s][1] = bs.read_b(this.s.ph.f_code[s][1] - 1); 144 } 145 if(predinfo.dmv == 1) 146 { 147 dmvector[1] = bs.read_dmvector(); 148 } 149 } 150 151 void parse_coded_block_pattern(BitstreamReader bs) 152 { 153 coded_block_pattern = bs.read_cbp(); 154 if(s.ph.si.chroma_format == ChromaFormat.C422) 155 { 156 coded_block_pattern <<= 2; 157 coded_block_pattern |= bs.read_u(2); 158 } 159 if(s.ph.si.chroma_format == ChromaFormat.C444) 160 { 161 coded_block_pattern <<= 6; 162 coded_block_pattern |= bs.read_u(6); 163 } 164 } 165 166 bool pattern_code(ubyte i) 167 { 168 if(p.pattern) 169 { 170 return cast(bool)(coded_block_pattern & (1 << (block_count() - 1 - i))); 171 } 172 else 173 { 174 return p.intra; 175 } 176 } 177 178 void parse_block(BitstreamReader bs, ubyte i) 179 { 180 if(!pattern_code(i)) return; 181 182 if(p.intra) 183 { 184 // TODO: optimize 185 uint dc_size = bs.read_dc_size(i<4); 186 short dct_diff = bs.read_u!short(dc_size); 187 188 if ((dct_diff & (1<<(dc_size-1)))==0) 189 { 190 dct_diff-= (1<<dc_size) - 1; 191 } 192 193 //if(ddd >> (dc_size - 1)) 194 //{ 195 // ddd = cast(short) (ddd + 1 - (1 << dc_size)); 196 //} 197 blocks[i].coeffs[0] = dct_diff; 198 } 199 200 short run, level; 201 int idx = p.intra; 202 bool eob = !bs.read_dct(idx == 0, run, level, s.ph.intra_vlc_format); 203 while(!eob) 204 { 205 //writefln("block(%d): rl: (%d, %d) idx: %d", i, run, level, idx); 206 idx += run; 207 blocks[i].coeffs[idx] = level; 208 ++idx; 209 eob = !bs.read_dct(false, run, level, s.ph.intra_vlc_format); 210 } 211 } 212 213 PredictionInfo predinfo() const 214 { 215 if(s.ph.picture_structure == PictureStructure.Frame) 216 { 217 if(s.ph.frame_pred_frame_dct == 0) 218 return frame_prediction_info[motion_type][0]; 219 else 220 return frame_prediction_info[2][0]; // Frame-based 221 } 222 else 223 { 224 return field_prediction_info[motion_type][0]; 225 } 226 } 227 228 void parse_modes(BitstreamReader bs) 229 { 230 this.type = bs.read_mb_type(s.ph.picture_coding_type); 231 this.p = mb_params[s.ph.picture_coding_type][this.type]; 232 233 if(this.p.spartial_temporal_weight_code_flag 234 /* TODO: && spatial_temporal_weight_code_table_index != 00 */ 235 ) 236 { 237 throw new Exception("spartial prediction is not implemented"); 238 //this.spartial_temporal_weight_code = bs.read_u(8); 239 } 240 241 if(this.p.motion_forward || this.p.motion_backward) 242 { 243 if(s.ph.picture_structure == PictureStructure.Frame) 244 { 245 if(s.ph.frame_pred_frame_dct == 0) 246 { 247 this.motion_type = bs.read_b(2); 248 } 249 } 250 else 251 { 252 this.motion_type = bs.read_b(2); 253 } 254 } 255 256 if(s.ph.picture_structure == PictureStructure.Frame 257 && s.ph.frame_pred_frame_dct == 0 258 && (this.p.intra || this.p.pattern) 259 ) 260 { 261 this.dct_type = bs.read_u1; 262 } 263 } 264 265 void dump_block(int idx) 266 { 267 writefln(" block(%d):", idx); 268 for(size_t i=0; i<8; ++i) 269 { 270 writef(" "); 271 for(size_t j=0; j<8; ++j) 272 { 273 writef("%3d ", blocks[idx].coeffs[i*8+j]); 274 } 275 writefln(""); 276 } 277 } 278 279 void dump(bool with_blocks = false) 280 { 281 auto mb = this; 282 283 writefln("macroblock:"); 284 writefln(" params : %s", mb.p); 285 writefln(" type : %d", mb.type); 286 writefln(" incr : %d", mb.incr); 287 288 if(p.quant) 289 { 290 writefln(" type : %d", mb.quantiser_scale_code); 291 } 292 293 if(p.motion_forward || (p.intra && s.ph.concealment_motion_vectors)) 294 { 295 } 296 297 if(p.motion_backward) 298 { 299 } 300 301 if(p.pattern) 302 { 303 writefln(" cbp : %d", mb.coded_block_pattern); 304 } 305 306 if(with_blocks) 307 { 308 for(ubyte i=0; i< block_count(); ++i) 309 { 310 dump_block(i); 311 } 312 } 313 } 314 315 void dump2(int mba, bool with_blocks) const 316 { 317 writefln("mb.incr: %d MBA: %d cbp: %d", incr, mba, coded_block_pattern); 318 319 if(!with_blocks) return; 320 321 for(ubyte bidx=0; bidx< block_count(); ++bidx) 322 { 323 writefln("MBA #%d block #%d: ", mba, bidx); 324 325 for(size_t i=0; i<8; ++i) 326 { 327 writef(" "); 328 for(size_t j=0; j<8; ++j) 329 { 330 writef("%3d ", blocks[bidx].coeffs[i*8+j]); 331 } 332 writeln(); 333 } 334 writeln(); 335 } 336 337 } 338 } 339 340 struct MbParams 341 { 342 bool quant; 343 bool motion_forward; 344 bool motion_backward; 345 bool pattern; 346 bool intra; 347 bool spartial_temporal_weight_code_flag; 348 uint permitted_spatial_temporal_weight_classes; 349 350 string toString() 351 { 352 string s = ""; 353 354 if(quant) s ~= "quant,"; 355 if(motion_forward) s ~= "motion_forward,"; 356 if(motion_backward) s ~= "motion_backward,"; 357 if(pattern) s ~= "pattern,"; 358 if(intra) s ~= "intra,"; 359 if(spartial_temporal_weight_code_flag) s ~= "spartial_temporal_weight_code_flag,"; 360 361 if(s.length > 0) 362 s = s[0..$-1]; 363 364 return s; 365 } 366 } 367 368 struct PredictionInfo 369 { 370 PredictionType type; 371 ubyte motion_vector_count; 372 MvFormat mv_format; 373 bool dmv; 374 } 375 376 // Table 6-17 377 static immutable PredictionInfo[4][4] frame_prediction_info = [ 378 [ 379 {PredictionType.Frame, 1, MvFormat.Field, 0}, 380 ], 381 [ 382 {PredictionType.Field, 2, MvFormat.Field, 0}, 383 {PredictionType.Field, 2, MvFormat.Field, 0}, 384 {PredictionType.Field, 1, MvFormat.Field, 0}, 385 {PredictionType.Field, 1, MvFormat.Field, 0}, 386 ], 387 [ 388 {PredictionType.Frame, 1, MvFormat.Frame, 0}, 389 {PredictionType.Frame, 1, MvFormat.Frame, 0}, 390 {PredictionType.Frame, 1, MvFormat.Frame, 0}, 391 {PredictionType.Frame, 1, MvFormat.Frame, 0}, 392 ], 393 [ 394 {PredictionType.DualPrime, 1, MvFormat.Field, 1}, 395 {}, 396 {PredictionType.DualPrime, 1, MvFormat.Field, 1}, 397 {PredictionType.DualPrime, 1, MvFormat.Field, 1}, 398 ], 399 ]; 400 401 // Table 6-18 402 static immutable PredictionInfo[2][4] field_prediction_info = [ 403 [ 404 {PredictionType.Field, 1, MvFormat.Field, 0}, 405 ], 406 [ 407 {PredictionType.Field, 1, MvFormat.Field, 0}, 408 {PredictionType.Field, 1, MvFormat.Field, 0}, 409 ], 410 [ 411 {PredictionType.Mc16x8, 2, MvFormat.Field, 0}, 412 {PredictionType.Mc16x8, 2, MvFormat.Field, 0}, 413 ], 414 [ 415 {PredictionType.DualPrime, 1, MvFormat.Field, 1}, 416 ], 417 ]; 418 419 // Table B.2 420 immutable MbParams[] mb_params_I = [ 421 {0,0,0,0,1,0,0}, 422 {1,0,0,0,1,0,0}, 423 ]; 424 425 // Table B.3 426 immutable MbParams[] mb_params_P = [ 427 {0,1,0,1,0,0,0}, 428 {0,0,0,1,0,0,0}, 429 {0,1,0,0,0,0,0}, 430 {0,0,0,0,1,0,0}, 431 {1,1,0,1,0,0,0}, 432 {1,0,0,1,0,0,0}, 433 {1,0,0,0,1,0,0}, 434 ]; 435 436 // Table B.4 437 immutable MbParams[] mb_params_B = [ 438 {0,1,1,0,0,0,0}, 439 {0,1,1,1,0,0,0}, 440 {0,0,1,0,0,0,0}, 441 {0,0,1,1,0,0,0}, 442 {0,1,0,0,0,0,0}, 443 {0,1,0,1,0,0,0}, 444 {0,0,0,0,1,0,0}, 445 {1,1,1,1,0,0,0}, 446 {1,1,0,1,0,0,0}, 447 {1,0,1,1,0,0,0}, 448 {1,0,0,0,1,0,0}, 449 ]; 450 451 // TODO: 452 // Table B.5-8 453 454 455 immutable MbParams[][] mb_params = [ 456 [], 457 mb_params_I, 458 mb_params_P, 459 mb_params_B, 460 ];