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