00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef __MXCPC_FRAMEWISEMXPEGSCANTOJPEGCONVERTERSOFTWAREONLY_H__
00018 #define __MXCPC_FRAMEWISEMXPEGSCANTOJPEGCONVERTERSOFTWAREONLY_H__
00019
00020
00021 #define MXCPC_FRAMEWISEMXPEGSCANTOJPEGCONVERTER_BITSTREAM_BUFFSIZE 0x100000
00022
00023
00024 #include <mxcpcFramewiseMxPEGScanDecoder.h>
00025 #include <mxcpcHuffmanTree.h>
00026 #include <mxcpc_mxpeg_namespace.h>
00027
00028 #include <cstdio>
00029 #include <cstring>
00030 #include <cstdlib>
00031
00032 class mxcpcMxPEGScanToJPEGConverterBackEnd;
00033
00034
00035
00044 class mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly : public mxcpcFramewiseMxPEGScanDecoder {
00045
00046 private:
00047 static const unsigned char ZigZag_StoreMap[64];
00048 static const int ZigZagMap[64];
00049
00050
00052 typedef struct {
00053
00054
00057 mxcpc::u8 bits_dc[16];
00058
00061 mxcpc::u8 val_dc[12];
00062
00063 } HuffCompDC;
00064
00066 typedef struct {
00067
00072 mxcpc::u8 bits_ac[16];
00073
00074 mxcpc::u8 val_ac[162];
00075
00076 } HuffCompAC;
00077
00078 static const HuffCompDC HuffTbl_Y_UV_DC[2];
00079
00080 static const HuffCompAC HuffTbl_Y_UV_AC[2];
00081
00082
00084 typedef struct {
00085
00087 unsigned int code_msk: 26;
00089 unsigned int fill_0bit: 1;
00091 unsigned int bit_len: 5;
00092
00093 } HuffCodeTblEntry;
00094
00095
00097 typedef union {
00098
00099 HuffCodeTblEntry table_entry;
00100 mxcpc::u32 u32_word;
00101
00102 } u32t;
00103
00105 typedef struct {
00106
00108 HuffCodeTblEntry ac_tbl[1];
00110 HuffCodeTblEntry dc_tbl[12];
00111
00113 int free_13;
00115 int free_14;
00117 HuffCodeTblEntry dc_tbl_0FtoAF[161];
00118
00119 } FoldedHuffTbl_DC_AC;
00120
00122 static FoldedHuffTbl_DC_AC Huff_Y_UV[2];
00123
00125 typedef struct {
00126
00127 mxcpc::u8* buf_start;
00128 mxcpc::u8* buf_end1;
00129 mxcpc::u8* buf_current_w_pos;
00132 mxcpc::u32 huf_accu;
00133 unsigned int huf_bits_used;
00134
00135 } HuffmanBufferStateStructure;
00136
00138 static HuffmanBufferStateStructure HuffmanBufferState;
00139
00141 mxcpc::u8* HuffmanEncoderBuffer;
00142
00143 private:
00144
00145 mxcpcHuffmanTree *HuffmanTree_Y_DC,
00146 *HuffmanTree_Y_AC;
00147
00148 mxcpcHuffmanTree *HuffmanTree_UV_DC,
00149 *HuffmanTree_UV_AC;
00150
00151 mxcpc::s16 QuantizationTable_Y[64],
00152 QuantizationTable_UV[64];
00153
00155 mxcpc::s16* CoeffBuffer;
00156
00158 int TileNumX, TileNumY;
00159
00162 unsigned char *CurrentScanByte,
00163 ScanMask;
00164
00165 int ScanBytesLeft;
00166 int CoeffInAdditionalBits;
00167
00168 std::FILE *OutStream;
00169
00170 mxcpc_mxpeg::APP0 APP0_Block;
00171 mxcpc_mxpeg::SOF0 SOF0_Block;
00172 mxcpc_mxpeg::SOS SOS_Block;
00173 int FramesProcessed;
00174
00176 mxcpcMxPEGScanToJPEGConverterBackEnd *ConverterBackEnd;
00177
00178
00179 public:
00181 mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly(mxcpcMxPEGScanToJPEGConverterBackEnd *backend);
00182 ~mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly();
00183
00184 public:
00186 void setYQuantizationTable(unsigned char *data_bytes);
00188 void setUVQuantizationTable(unsigned char *data_bytes);
00190 void performScanSweep(mxcpcFramewiseMxPEGDecoder::UndecodedFrameDescriptor
00191 *frame_descriptor);
00192
00193 private:
00194
00197 void calcFoldedHuffTables(void);
00198
00200
00212 void generateHuffTables1(
00213 const mxcpc::u8 * bits_tbl_off1,
00214 const mxcpc::u8 * val_tbl,
00215 int swap_symbol,
00216 HuffCodeTblEntry * folded_tbl_p);
00217
00219 void initHuffmanEncoderBufferState();
00220
00221 void resetHuffmanEncoderBufferState();
00222
00223
00226
00231 inline bool consumeScanBit(void) {
00232
00233 bool bit_was_set;
00234 unsigned char last_scan_byte;
00235
00236 bit_was_set = *CurrentScanByte & ScanMask;
00237
00238 ScanMask /= 2;
00239 if(!ScanMask) {
00240
00241 last_scan_byte = *CurrentScanByte;
00242
00243 CurrentScanByte++;
00244 ScanBytesLeft--;
00245 if(last_scan_byte == 0xff) {
00246 if(*CurrentScanByte == 0x00) {
00247 if(!ScanBytesLeft) {
00248 mxcpc::sendStatusMsg("not more scan bytes!");
00249 std::exit(666);
00250 }
00251 else {
00252 CurrentScanByte++;
00253 ScanBytesLeft--;
00254 }
00255 }
00256 else {
00257 mxcpc::sendStatusMsg("unexpected marker encountered!");
00258 std::exit(666);
00259 }
00260
00261
00262 }
00263
00264 ScanMask = 128;
00265 }
00266
00267 return(bit_was_set);
00268 }
00269
00272
00283 inline const mxcpcHuffmanTree
00284 ::Node *consumeHuffmanCodeword(
00285 const mxcpcHuffmanTree::Node *current_huffman_node) {
00286
00287 const mxcpcHuffmanTree::Node *last_huffman_node;
00288
00289 do {
00290
00291 if(!ScanBytesLeft) return(0);
00292
00293 last_huffman_node = current_huffman_node;
00294
00295 if(consumeScanBit())
00296 current_huffman_node = current_huffman_node->Child1;
00297 else
00298 current_huffman_node = current_huffman_node->Child0;
00299
00300 if(current_huffman_node == last_huffman_node) {
00301 std::printf(" !!! invalid codeword !!!\n");
00302 std::exit(666);
00303 return(0);
00304 }
00305
00306 } while(!current_huffman_node->IsLeaf);
00307
00308 return(current_huffman_node);
00309 }
00310
00311
00314
00326 inline bool consumeAdditionalBits(int n) {
00327
00328 bool positive;
00329 int base;
00330 static int bases[] = { -666, -666, 2, 4, 8, 16, 32, 64, 128, 256, 512 };
00331
00332
00333 if(!ScanBytesLeft) return(true);
00334 positive = consumeScanBit();
00335 if(n == 1) {
00336 if(positive) CoeffInAdditionalBits = 1;
00337 else CoeffInAdditionalBits = -1;
00338 return(false);
00339 }
00340
00341
00342 base = bases[n];
00343 if(!positive) {
00344 base *= 2;
00345 base = -base;
00346 base++;
00347 }
00348 n--;
00349 CoeffInAdditionalBits = 0;
00350 while(n) {
00351
00352 if(!ScanBytesLeft) return(true);
00353
00354 CoeffInAdditionalBits *= 2;
00355
00356 if(consumeScanBit())
00357 CoeffInAdditionalBits += 1;
00358
00359 n--;
00360 }
00361 CoeffInAdditionalBits += base;
00362
00363 return(false);
00364 }
00365
00366
00375 inline void encodeSubMCUTiles(mxcpc::s16* coef_matrix,
00376 mxcpc::s16* last_dc_coeff,
00377 FoldedHuffTbl_DC_AC* huff_code_tbl_entry,
00378 HuffmanBufferStateStructure* hbuf_state_ptr) {
00379
00380
00381
00382 unsigned int huff_bits_used = hbuf_state_ptr->huf_bits_used;
00383 mxcpc::u32 huff_accu_32 = hbuf_state_ptr->huf_accu;
00384
00385 u32t union_accu_tmp;
00386 int total_bits=0;
00387 int bits=0;
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 mxcpc::u32 dc_encoded_word;
00412
00413 mxcpc::s16 delta = coef_matrix[0] - (*last_dc_coeff);
00414 *last_dc_coeff = coef_matrix[0];
00415
00416
00417 if ((delta < -2046) || (delta > 2046)) {
00418 mxcpc::sendStatusMsg("Out of Range");
00419 std::exit(666);
00420 }
00421
00422
00423 if( delta ==0 ) bits=0;
00424 if(delta > 0 )bits = returnBitsInCoef(delta );
00425 if(delta < 0 )bits = returnBitsInCoef(-delta );
00426
00427 union_accu_tmp.table_entry = (*huff_code_tbl_entry).dc_tbl[bits];
00428 dc_encoded_word = union_accu_tmp.u32_word;
00429
00430
00431 if (delta < 0) delta = (delta -1 ) & (0x7fffffff >> (31 - bits));
00432
00433
00434
00435
00436
00437
00438 dc_encoded_word = dc_encoded_word | delta ;
00439 total_bits = dc_encoded_word >> 27;
00440
00441
00442 dc_encoded_word = dc_encoded_word << (32 - total_bits);
00443
00444
00445
00446 huff_accu_32 = huff_accu_32 | (dc_encoded_word >> huff_bits_used);
00447
00448
00449
00450
00451 huff_bits_used += total_bits;
00452
00453
00454
00455 if( huff_bits_used >= 32 ){
00456
00457
00458
00459
00460 copyAccuToGlobalHuffBuffer( huff_accu_32,
00461 hbuf_state_ptr);
00462 huff_bits_used -= 32;
00463 huff_accu_32 = dc_encoded_word << (total_bits - huff_bits_used);
00464
00465 }
00466
00467
00468
00469
00470
00471 int run_len=0;
00472
00473
00474 for(int ac_coef=1; ac_coef<=63; ac_coef++){
00475
00476
00477 mxcpc::u32 new_bit_accu;
00478
00479 bits=0;
00480 int symbol=0;
00481
00482 int c = coef_matrix[ZigZagMap[ac_coef]];
00483
00484 if(c == 0 ){
00485
00486 run_len +=1;
00487
00488 }
00489 else{
00490
00491
00492 while (run_len > 15) {
00493
00494 mxcpc::u32 u32_zero_lenght;
00495
00496 union_accu_tmp.table_entry = (*huff_code_tbl_entry).ac_tbl[0x0f];
00497 u32_zero_lenght = union_accu_tmp.u32_word;
00498
00499 total_bits = u32_zero_lenght >> 27;
00500
00501 u32_zero_lenght = u32_zero_lenght << (32 - total_bits);
00502
00503 huff_accu_32 = huff_accu_32 | ( u32_zero_lenght >> huff_bits_used);
00504
00505 huff_bits_used += total_bits;
00506
00507 if( huff_bits_used >= 32 ){
00508
00509 copyAccuToGlobalHuffBuffer( huff_accu_32,
00510 hbuf_state_ptr);
00511
00512
00513 huff_bits_used -= 32;
00514
00515 huff_accu_32 = u32_zero_lenght << (total_bits - huff_bits_used);
00516
00517
00518 }
00519 run_len -= 16;
00520 }
00521
00522
00523 if(c >=0 )bits = returnBitsInCoef(c);
00524 else { bits = returnBitsInCoef(-c); }
00525
00526
00527
00528 symbol = (bits << 4) + run_len;
00529
00530
00531
00532
00533
00534
00535
00536 union_accu_tmp.table_entry = (*huff_code_tbl_entry).ac_tbl[symbol];
00537 new_bit_accu = union_accu_tmp.u32_word;
00538
00539
00540
00541 if (c < 0) c = (c -1 ) & (0x7fffffff >> (31 - bits));
00542
00543 new_bit_accu = new_bit_accu | c;
00544 total_bits = new_bit_accu >> 27;
00545
00546
00547
00548 new_bit_accu = new_bit_accu << (32 - total_bits);
00549
00550
00551
00552
00553
00554 huff_accu_32 = huff_accu_32 | (new_bit_accu >> huff_bits_used);
00555
00556
00557
00558
00559
00560 huff_bits_used += total_bits;
00561
00562 if (huff_bits_used >= 32) {
00563 copyAccuToGlobalHuffBuffer( huff_accu_32,
00564 hbuf_state_ptr);
00565 huff_bits_used -= 32;
00566 huff_accu_32 = new_bit_accu << (total_bits - huff_bits_used);
00567
00568 }
00569
00570 run_len =0;
00571 }
00572
00573
00574 }
00575
00576
00577 if(run_len != 0){
00578
00579 mxcpc::u32 eob_tag;
00580
00581 union_accu_tmp.table_entry = (*huff_code_tbl_entry).ac_tbl[0x00];
00582 eob_tag = union_accu_tmp.u32_word;
00583
00584 total_bits = eob_tag >> 27;
00585
00586 eob_tag = eob_tag << (32 - total_bits);
00587
00588 huff_accu_32 = huff_accu_32 | (eob_tag >> huff_bits_used);
00589
00590 huff_bits_used += total_bits;
00591
00592 if (huff_bits_used >= 32) {
00593 copyAccuToGlobalHuffBuffer( huff_accu_32,
00594 hbuf_state_ptr);
00595 huff_bits_used -= 32;
00596 huff_accu_32 = eob_tag << (total_bits - huff_bits_used);
00597 }
00598
00599 }
00600
00601
00602 hbuf_state_ptr->huf_bits_used = huff_bits_used;
00603 hbuf_state_ptr->huf_accu = huff_accu_32;
00604
00605 }
00606
00613 static inline void copyAccuToGlobalHuffBuffer( mxcpc::u32 huff_accu_32,
00614 HuffmanBufferStateStructure* huff_buf_state_ptr){
00615
00616 mxcpc::u8 b;
00617 mxcpc::u8* p = huff_buf_state_ptr->buf_current_w_pos;
00618
00619 if ((p+8) >= huff_buf_state_ptr->buf_end1) {
00620 mxcpc::sendStatusMsg("Huffman Buffer Overflow!");
00621 std::exit(666);
00622 }
00623
00624
00625
00626
00627
00628
00629
00630 b = (huff_accu_32 >> 24); *p++ = b;
00631 if (b == 0xff) *p++ = 0x00;
00632
00633
00634 b = (huff_accu_32 >> 16) & 0xff; *p++ = b;
00635 if (b == 0xff) *p++ = 0x00;
00636
00637
00638 b = (huff_accu_32 >> 8) & 0xff; *p++ = b;
00639 if (b == 0xff) *p++ = 0x00;
00640
00641
00642 b = (huff_accu_32 ) & 0xff; *p++ = b;
00643 if (b == 0xff) *p++ = 0x00;
00644
00645 huff_buf_state_ptr->buf_current_w_pos = p;
00646
00647 }
00648
00653 static int shutDownHuffAccu( ){
00654
00655 mxcpc::u8 b;
00656 mxcpc::u8* p = HuffmanBufferState.buf_current_w_pos;
00657
00658 if ((p+8) >= HuffmanBufferState.buf_end1) {
00659 mxcpc::sendStatusMsg("Huffman Buffer Overflow!");
00660 std::exit(666);
00661 }
00662
00663 if(HuffmanBufferState.huf_bits_used == 2 && HuffmanBufferState.huf_accu == 0 ){
00664
00665 b = 0x0 ;
00666 *p++ = b;
00667
00668 HuffmanBufferState.buf_current_w_pos = p;
00669
00670 }
00671 else{
00672 while (HuffmanBufferState.huf_accu) {
00673
00674 b = (HuffmanBufferState.huf_accu >> 24); *p++ = b;
00675 if (b == 0xff) *p++ = 0x00;
00676 HuffmanBufferState.huf_accu <<= 8;
00677 }
00678
00679 HuffmanBufferState.buf_current_w_pos = p;
00680 }
00681 return(0);
00682 }
00683
00684
00685
00686
00687
00693 static inline int returnBitsInCoef(mxcpc::s16 c){
00694
00695
00696 int bits = 1;
00697
00698 while ( c >>= 1 ){ bits +=1;}
00699
00700 return (bits);
00701
00702 }
00703
00704
00705 };
00706
00707
00708 #endif // __MXCPC_FRAMEWISEMXPEGSCANTOJPEGCONVERTERSOFTWAREONLY_H__