00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <mxcpcFramewiseMxPEGScanDecoderSoftwareOnly.h>
00018 #include <mxcpcMxPEGDecoderBackEnd.h>
00019 #include <mxcpc_namespace.h>
00020 #include <mxcpc_exceptions.h>
00021
00022 #include <cstring>
00023 #include <cstdio>
00024
00025
00026
00027 const int mxcpcFramewiseMxPEGScanDecoderSoftwareOnly
00028 ::ZigZagMap[64] = { 0, 1, 8, 16, 9, 2, 3, 10,
00029 17, 24, 32, 25, 18, 11, 4, 5,
00030 12, 19, 26, 33, 40, 48, 41, 34,
00031 27, 20, 13, 6, 7, 14, 21, 28,
00032 35, 42, 49, 56, 57, 50, 43, 36,
00033 29, 22, 15, 23, 30, 37, 44, 51,
00034 58, 59, 52, 45, 38, 31, 39, 46,
00035 53, 60, 61, 54, 47, 55, 62, 63
00036 };
00037 short mxcpcFramewiseMxPEGScanDecoderSoftwareOnly::iclip[1024];
00038 short *mxcpcFramewiseMxPEGScanDecoderSoftwareOnly::iclp;
00039
00040
00041 mxcpcFramewiseMxPEGScanDecoderSoftwareOnly::mxcpcFramewiseMxPEGScanDecoderSoftwareOnly() {
00042
00043 char txt[100];
00044 int i;
00045
00046 HuffmanTree_Y_DC = 0,
00047 HuffmanTree_Y_AC = 0;
00048 HuffmanTree_UV_DC = 0,
00049 HuffmanTree_UV_AC = 0;
00050
00051 try {
00052
00053 HuffmanTree_Y_DC = new mxcpcHuffmanTree();
00054 if(HuffmanTree_Y_DC->configureFromTable(DefaultHuffmanTable_Y_DC))
00055 throw mxcpcDidntWorkOutException();
00056 HuffmanTree_Y_AC = new mxcpcHuffmanTree();
00057 if(HuffmanTree_Y_AC->configureFromTable(DefaultHuffmanTable_Y_AC))
00058 throw mxcpcDidntWorkOutException();
00059 HuffmanTree_UV_DC = new mxcpcHuffmanTree();
00060 if(HuffmanTree_UV_DC->configureFromTable(DefaultHuffmanTable_UV_DC))
00061 throw mxcpcDidntWorkOutException();
00062 HuffmanTree_UV_AC = new mxcpcHuffmanTree();
00063 if(HuffmanTree_UV_AC->configureFromTable(DefaultHuffmanTable_UV_AC))
00064 throw mxcpcDidntWorkOutException();
00065
00066 fprintf(stderr,"\n Constructor: DefaultHuffmanTable_Y_DC[1] : %d \n\n", DefaultHuffmanTable_Y_DC[1] );
00067 fprintf(stderr,"\n Constructor: Get Root Value from HuffmanTree_Y_DC: %s \n\n", HuffmanTree_Y_DC->getRoot()->Value);
00068
00069 } catch(std::exception &e) {
00070
00071 MXCPC_RETHROW_UNHANDLED_EXCEPTION(e);
00072
00073 delete HuffmanTree_Y_DC;
00074 delete HuffmanTree_Y_AC;
00075 delete HuffmanTree_UV_DC;
00076 delete HuffmanTree_UV_AC;
00077
00078 throw;
00079 }
00080
00081 for(i = 0; i < 64; i++) {
00082 QuantizationTable_Y[i] = 0;
00083 QuantizationTable_UV[i] = 0;
00084 }
00085
00086 iclp = iclip + 512;
00087 for(i = -512; i < 512; i++) iclp[i] = (i < -256) ? -256 : ((i > 255) ? 255 : i);
00088
00089 std::sprintf(txt, "symbols in Y/DC Huffman table : %d",
00090 HuffmanTree_Y_DC->countLeaves());
00091 mxcpc::sendStatusMsg(txt, this);
00092 std::sprintf(txt, "symbols in Y/AC Huffman table : %d",
00093 HuffmanTree_Y_AC->countLeaves());
00094 mxcpc::sendStatusMsg(txt, this);
00095 std::sprintf(txt, "symbols in UV/DC Huffman table : %d",
00096 HuffmanTree_UV_DC->countLeaves());
00097 mxcpc::sendStatusMsg(txt, this);
00098 std::sprintf(txt, "symbols in UV/AC Huffman table : %d",
00099 HuffmanTree_UV_AC->countLeaves());
00100 mxcpc::sendStatusMsg(txt, this);
00101 }
00102
00103
00104 mxcpcFramewiseMxPEGScanDecoderSoftwareOnly::~mxcpcFramewiseMxPEGScanDecoderSoftwareOnly() {
00105
00106 delete HuffmanTree_Y_DC;
00107 delete HuffmanTree_Y_AC;
00108 delete HuffmanTree_UV_DC;
00109 delete HuffmanTree_UV_AC;
00110 }
00111
00112
00113
00114 void mxcpcFramewiseMxPEGScanDecoderSoftwareOnly
00115 ::setYQuantizationTable(unsigned char *data_bytes) {
00116
00117 int i;
00118
00119 for(i = 0; i < 64; i++) QuantizationTable_Y[ZigZagMap[i]] = *data_bytes++;
00120 }
00121
00122
00123 void mxcpcFramewiseMxPEGScanDecoderSoftwareOnly
00124 ::setUVQuantizationTable(unsigned char *data_bytes) {
00125
00126 int i;
00127
00128 for(i = 0; i < 64; i++) QuantizationTable_UV[ZigZagMap[i]] = *data_bytes++;
00129 }
00130
00131
00132 void mxcpcFramewiseMxPEGScanDecoderSoftwareOnly
00133 ::performScanSweep(mxcpcFramewiseMxPEGDecoder::UndecodedFrameDescriptor
00134 *frame_descriptor) {
00135
00136
00137 const mxcpcHuffmanTree::Node *Huffman_DC_Roots[6] = { HuffmanTree_Y_DC->getRoot(),
00138 HuffmanTree_Y_DC->getRoot(),
00139 HuffmanTree_Y_DC->getRoot(),
00140 HuffmanTree_Y_DC->getRoot(),
00141 HuffmanTree_UV_DC->getRoot(),
00142 HuffmanTree_UV_DC->getRoot()
00143 },
00144 *Huffman_AC_Roots[6] = { HuffmanTree_Y_AC->getRoot(),
00145 HuffmanTree_Y_AC->getRoot(),
00146 HuffmanTree_Y_AC->getRoot(),
00147 HuffmanTree_Y_AC->getRoot(),
00148 HuffmanTree_UV_AC->getRoot(),
00149 HuffmanTree_UV_AC->getRoot()
00150 };
00151
00152 mxcpc::s16 *quantization_table_ptrs[6] = { &QuantizationTable_Y[0],
00153 &QuantizationTable_Y[0],
00154 &QuantizationTable_Y[0],
00155 &QuantizationTable_Y[0],
00156 &QuantizationTable_UV[0],
00157 &QuantizationTable_UV[0]
00158 };
00159
00160 bool use_bitmask;
00161 int tilebits_left;
00162 unsigned char *tilebit_ptr, tilebit_mask;
00163 int x, y;
00164 bool next_tile_right_here;
00165 const mxcpcHuffmanTree::Node *huffman_leaf_node;
00166 int additional_bit_num;
00167 int ac_coeffs_needed;
00168 int ac_coeffs_to_output;
00169 mxcpc::s16 coeff_buffers[6][64];
00170 mxcpc::s16 dc_coeffs[3] = { 0, 0, 0};
00171
00172
00173 mxcpc::s16 *dc_coeff_ptrs[6] = { &dc_coeffs[0],
00174 &dc_coeffs[0],
00175 &dc_coeffs[0],
00176 &dc_coeffs[0],
00177 &dc_coeffs[1],
00178 &dc_coeffs[2]
00179 };
00180 mxcpc::s16 *coeff_buffer;
00181 mxcpc::s16 *src_ptr, *dest_ptr;
00182 int coeff_i;
00183 int color_y, color_u, color_v,
00184 color_r, color_g, color_b;
00185 mxcpc::u32 *pixel_target;
00186 int target_row_stepping;
00187 unsigned char *target_ptr;
00188 int i, j;
00189 unsigned int ii, jj;
00190
00191
00192
00193 if(!BackEnd) return;
00194
00195
00196
00197 CurrentScanByte = frame_descriptor->ScanBytes;
00198 ScanMask = 128;
00199 ScanBytesLeft = frame_descriptor->ScanLength;
00200 if(!CurrentScanByte || !ScanBytesLeft) {
00201 BackEnd->errorEncountered();
00202 return;
00203 }
00204 tilebits_left = frame_descriptor->TileNumX * frame_descriptor->TileNumY;
00205 tilebit_ptr = frame_descriptor->TileBits;
00206 tilebit_mask = 128;
00207 x = -1;
00208 y = 0;
00209 next_tile_right_here = true;
00210 if(tilebit_ptr)
00211 use_bitmask = true;
00212 else
00213 use_bitmask = false;
00214
00215
00216
00217 while(tilebits_left) {
00218
00219
00220
00221 x++;
00222 if(x == frame_descriptor->TileNumX) {
00223 x = 0;
00224 y++;
00225 }
00226
00227
00228 if(use_bitmask) {
00229 next_tile_right_here = (*tilebit_ptr & tilebit_mask) != 0;
00230 tilebit_mask /= 2;
00231 if(!tilebit_mask) {
00232 tilebit_mask = 128;
00233 tilebit_ptr++;
00234 }
00235 }
00237
00238 if(next_tile_right_here) {
00239
00240
00241 for(i = 0; i < 6; i++) {
00242
00243 coeff_buffer = coeff_buffers[i];
00244
00245
00246
00247
00248 huffman_leaf_node = consumeHuffmanCodeword(Huffman_DC_Roots[i]);
00249 if(!huffman_leaf_node) {
00250 BackEnd->errorEncountered();
00251 return;
00252 }
00253
00254
00255 additional_bit_num = (int)( (unsigned int)huffman_leaf_node->Value
00256 & (unsigned int)0x0f);
00257 if(additional_bit_num) {
00258 if(consumeAdditionalBits(additional_bit_num)) {
00259 BackEnd->errorEncountered();
00260 return;
00261 }
00262 coeff_buffer[0] = CoeffInAdditionalBits;
00263 }
00264 else {
00265 coeff_buffer[0] = 0;
00266 }
00267
00268
00269 coeff_buffer[0] += *dc_coeff_ptrs[i];
00270 *dc_coeff_ptrs[i] = coeff_buffer[0];
00271
00272
00273
00274 coeff_i = 1;
00275 ac_coeffs_needed = 63;
00276 while(ac_coeffs_needed) {
00277
00278
00279 huffman_leaf_node = consumeHuffmanCodeword(Huffman_AC_Roots[i]);
00280 if(!huffman_leaf_node) {
00281 BackEnd->errorEncountered();
00282 return;
00283 }
00284
00285
00286 if(huffman_leaf_node->Value == 0x00) {
00287 while(ac_coeffs_needed) {
00288 coeff_buffer[ZigZagMap[coeff_i]] = 0;
00289 coeff_i++;
00290 ac_coeffs_needed--;
00291 }
00292 continue;
00293 }
00294
00295
00296 additional_bit_num = (int)( (unsigned int)huffman_leaf_node->Value
00297 & (unsigned int)0x0f);
00298 if(additional_bit_num) {
00299 if(consumeAdditionalBits(additional_bit_num)) {
00300 BackEnd->errorEncountered();
00301 return;
00302 }
00303 }
00304 else
00305 CoeffInAdditionalBits = 0;
00306
00307
00308 ac_coeffs_to_output = huffman_leaf_node->Value/16 + 1;
00309 if(ac_coeffs_to_output > ac_coeffs_needed) {
00310 mxcpc::sendStatusMsg("too many AC coeffs!");
00311 BackEnd->errorEncountered();
00312 return;
00313 }
00314 for(j = 0; j < ac_coeffs_to_output-1; j++) {
00315 coeff_buffer[ZigZagMap[coeff_i]] = 0;
00316 coeff_i++;
00317 }
00318 coeff_buffer[ZigZagMap[coeff_i]] = CoeffInAdditionalBits;
00319 coeff_i++;
00320 if(coeff_i > 64) {
00321 mxcpc::sendStatusMsg("coeff buffer overflow!");
00322 BackEnd->errorEncountered();
00323 return;
00324 }
00325
00326 ac_coeffs_needed -= ac_coeffs_to_output;
00327 }
00328
00329
00330
00331
00332 src_ptr = quantization_table_ptrs[i];
00333 dest_ptr = coeff_buffer;
00334 j = 64;
00335 while(j) {
00336 *dest_ptr++ = *dest_ptr * *src_ptr++;
00337 j--;
00338 }
00339
00340
00341
00342 idct((short *)coeff_buffer);
00343
00344
00345 dest_ptr = coeff_buffer;
00346 j = 64;
00347 while(j) {
00348 mxcpc::clamp_s16(dest_ptr, -128, 127);
00349 *dest_ptr++ += (mxcpc::s16)128;
00350 j--;
00351 }
00352
00353 }
00354
00355
00356
00357
00358
00359
00360 BackEnd->provideVideoTilePixelTarget(x, y, &pixel_target, &target_row_stepping);
00361 target_ptr = (unsigned char *)pixel_target;
00362
00363 for(jj = 0; jj < 16; jj++) {
00364 for(ii = 0; ii < 16; ii++) {
00365
00366
00367 color_y = (int)(*(&coeff_buffers[0][0]
00368 + ((((jj>>3)<<1) + (ii>>3)) << 6)
00369 + ((jj & 0x07) << 3)
00370 + (ii & 0x07)
00371 )
00372 );
00373 color_u = (int)(*(coeff_buffers[4]
00374 + ((jj>>1) << 3)
00375 + (ii>>1)
00376 )
00377 ) - 128;
00378 color_v = (int)(*(coeff_buffers[5]
00379 + ((jj>>1) << 3)
00380 + (ii >> 1)
00381 )
00382 ) - 128;
00383
00384
00385
00386
00387 color_r = ((color_y<<10) + 1167*color_v) >> 10;
00388 color_g = ((color_y<<10) - 403*color_u - 595*color_v) >> 10;
00389 color_b = ((color_y<<10) + 2081*color_u ) >> 10;
00390
00391 mxcpc::clamp_int(&color_r, 0, 255);
00392 mxcpc::clamp_int(&color_g, 0, 255);
00393 mxcpc::clamp_int(&color_b, 0, 255);
00394
00395 *target_ptr++ = color_r;
00396 *target_ptr++ = color_g;
00397 *target_ptr++ = color_b;
00398 }
00399
00400 target_ptr += target_row_stepping*4;
00401 }
00402
00403 BackEnd->videoTileReceived();
00404 }
00405
00406 tilebits_left--;
00407 }
00408
00409 }
00410
00411
00412
00413
00414
00415 #define W1 2841
00416 #define W2 2676
00417 #define W3 2408
00418 #define W5 1609
00419 #define W6 1108
00420 #define W7 565
00421
00422
00423 void mxcpcFramewiseMxPEGScanDecoderSoftwareOnly::idctrow(short *blk) {
00424
00425 int x0, x1, x2, x3, x4, x5, x6, x7, x8;
00426
00427
00428
00429 if (!((x1 = blk[4]<<11) | (x2 = blk[6]) | (x3 = blk[2]) |
00430 (x4 = blk[1]) | (x5 = blk[7]) | (x6 = blk[5]) | (x7 = blk[3]))) {
00431
00432 blk[0]=blk[1]=blk[2]=blk[3]=blk[4]=blk[5]=blk[6]=blk[7]=blk[0]<<3;
00433 return;
00434 }
00435
00436 x0 = (blk[0]<<11) + 128;
00437
00438
00439 x8 = W7*(x4+x5);
00440 x4 = x8 + (W1-W7)*x4;
00441 x5 = x8 - (W1+W7)*x5;
00442 x8 = W3*(x6+x7);
00443 x6 = x8 - (W3-W5)*x6;
00444 x7 = x8 - (W3+W5)*x7;
00445
00446
00447 x8 = x0 + x1;
00448 x0 -= x1;
00449 x1 = W6*(x3+x2);
00450 x2 = x1 - (W2+W6)*x2;
00451 x3 = x1 + (W2-W6)*x3;
00452 x1 = x4 + x6;
00453 x4 -= x6;
00454 x6 = x5 + x7;
00455 x5 -= x7;
00456
00457
00458 x7 = x8 + x3;
00459 x8 -= x3;
00460 x3 = x0 + x2;
00461 x0 -= x2;
00462 x2 = (181*(x4+x5)+128)>>8;
00463 x4 = (181*(x4-x5)+128)>>8;
00464
00465
00466 blk[0] = (x7+x1)>>8;
00467 blk[1] = (x3+x2)>>8;
00468 blk[2] = (x0+x4)>>8;
00469 blk[3] = (x8+x6)>>8;
00470 blk[4] = (x8-x6)>>8;
00471 blk[5] = (x0-x4)>>8;
00472 blk[6] = (x3-x2)>>8;
00473 blk[7] = (x7-x1)>>8;
00474 }
00475
00476
00477 void mxcpcFramewiseMxPEGScanDecoderSoftwareOnly::idctcol(short *blk) {
00478
00479 int x0, x1, x2, x3, x4, x5, x6, x7, x8;
00480
00481 if (!((x1 = (blk[8*4]<<8)) | (x2 = blk[8*6]) | (x3 = blk[8*2]) |
00482 (x4 = blk[8*1]) | (x5 = blk[8*7]) | (x6 = blk[8*5]) | (x7 = blk[8*3]))) {
00483
00484 blk[8*0]=blk[8*1]=blk[8*2]=blk[8*3]=blk[8*4]=blk[8*5]=blk[8*6]=blk[8*7]
00485 = iclp[(blk[8*0]+32)>>6];
00486
00487 return;
00488 }
00489
00490 x0 = (blk[8*0]<<8) + 8192;
00491
00492
00493 x8 = W7*(x4+x5) + 4;
00494 x4 = (x8+(W1-W7)*x4)>>3;
00495 x5 = (x8-(W1+W7)*x5)>>3;
00496 x8 = W3*(x6+x7) + 4;
00497 x6 = (x8-(W3-W5)*x6)>>3;
00498 x7 = (x8-(W3+W5)*x7)>>3;
00499
00500
00501 x8 = x0 + x1;
00502 x0 -= x1;
00503 x1 = W6*(x3+x2) + 4;
00504 x2 = (x1-(W2+W6)*x2)>>3;
00505 x3 = (x1+(W2-W6)*x3)>>3;
00506 x1 = x4 + x6;
00507 x4 -= x6;
00508 x6 = x5 + x7;
00509 x5 -= x7;
00510
00511
00512 x7 = x8 + x3;
00513 x8 -= x3;
00514 x3 = x0 + x2;
00515 x0 -= x2;
00516 x2 = (181*(x4+x5)+128)>>8;
00517 x4 = (181*(x4-x5)+128)>>8;
00518
00519
00520 blk[8*0] = iclp[(x7+x1)>>14];
00521 blk[8*1] = iclp[(x3+x2)>>14];
00522 blk[8*2] = iclp[(x0+x4)>>14];
00523 blk[8*3] = iclp[(x8+x6)>>14];
00524 blk[8*4] = iclp[(x8-x6)>>14];
00525 blk[8*5] = iclp[(x0-x4)>>14];
00526 blk[8*6] = iclp[(x3-x2)>>14];
00527 blk[8*7] = iclp[(x7-x1)>>14];
00528 }
00529
00530
00531 void mxcpcFramewiseMxPEGScanDecoderSoftwareOnly::idct(short *block) {
00532
00533 int i;
00534
00535 for(i = 0; i < 8; i++) idctrow(block+8*i);
00536 for(i = 0; i < 8; i++) idctcol(block+i);
00537 }