00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <mxcpcFramewiseMxPEGScanToJPEGConverterIPP.h>
00018 #include <mxcpcMxPEGDecoderBackEnd.h>
00019 #include <mxcpcMxPEGScanToJPEGConverterBackEnd.h>
00020 #include <mxcpc_exceptions.h>
00021
00022 #include <memory>
00023
00024
00025
00026 const unsigned char mxcpcFramewiseMxPEGScanToJPEGConverterIPP::ZigZag_StoreMap[64] = {
00027 0, 1, 5, 6, 14, 15, 27, 28,
00028 2, 4, 7, 13, 16, 26, 29, 42,
00029 3, 8, 12, 17, 25, 30, 41, 43,
00030 9, 11, 18, 24, 31, 40, 44, 53,
00031 10, 19, 23, 32, 39, 45, 52, 54,
00032 20, 22, 33, 38, 46, 51, 55, 60,
00033 21, 34, 37, 47, 50, 56, 59, 61,
00034 35, 36, 48, 49, 57, 58, 62, 63
00035 };
00036
00037
00038
00039 mxcpcFramewiseMxPEGScanToJPEGConverterIPP::mxcpcFramewiseMxPEGScanToJPEGConverterIPP(
00040 mxcpcMxPEGScanToJPEGConverterBackEnd *backend
00041 ) {
00042
00043 int huffman_size;
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 HuffmanEncodeSpec_Y_DC = 0;
00051 HuffmanEncodeSpec_Y_AC = 0;
00052 HuffmanEncodeSpec_UV_DC = 0;
00053 HuffmanEncodeSpec_UV_AC = 0;
00054
00055 ippiDecodeHuffmanSpecGetBufSize_JPEG_8u(&huffman_size);
00056 HuffmanTree_Y_DC = (IppiDecodeHuffmanSpec *)std::malloc(huffman_size);
00057 HuffmanTree_Y_AC = (IppiDecodeHuffmanSpec *)std::malloc(huffman_size);
00058 HuffmanTree_UV_DC = (IppiDecodeHuffmanSpec *)std::malloc(huffman_size);
00059 HuffmanTree_UV_AC = (IppiDecodeHuffmanSpec *)std::malloc(huffman_size);
00060 ippiEncodeHuffmanSpecGetBufSize_JPEG_8u(&huffman_size);
00061 HuffmanEncodeSpec_Y_DC = (IppiEncodeHuffmanSpec *)std::malloc(huffman_size);
00062 HuffmanEncodeSpec_Y_AC = (IppiEncodeHuffmanSpec *)std::malloc(huffman_size);
00063 HuffmanEncodeSpec_UV_DC = (IppiEncodeHuffmanSpec *)std::malloc(huffman_size);
00064 HuffmanEncodeSpec_UV_AC = (IppiEncodeHuffmanSpec *)std::malloc(huffman_size);
00065
00066 if( !HuffmanTree_Y_DC
00067 || !HuffmanTree_Y_AC
00068 || !HuffmanTree_UV_DC
00069 || !HuffmanTree_UV_AC
00070 || !HuffmanEncodeSpec_Y_DC
00071 || !HuffmanEncodeSpec_Y_AC
00072 || !HuffmanEncodeSpec_UV_DC
00073 || !HuffmanEncodeSpec_UV_AC) {
00074
00075 std::free(HuffmanTree_Y_DC);
00076 std::free(HuffmanTree_Y_AC);
00077 std::free(HuffmanTree_UV_DC);
00078 std::free(HuffmanTree_UV_AC);
00079 std::free(HuffmanEncodeSpec_Y_DC);
00080 std::free(HuffmanEncodeSpec_Y_AC);
00081 std::free(HuffmanEncodeSpec_UV_DC);
00082 std::free(HuffmanEncodeSpec_UV_AC);
00083
00084 throw std::bad_alloc();
00085 }
00086
00087 try {
00088
00089 if(ippiDecodeHuffmanSpecInit_JPEG_8u(&DefaultHuffmanTable_Y_DC[0],
00090 &DefaultHuffmanTable_Y_DC[16],
00091 HuffmanTree_Y_DC)
00092 != ippStsNoErr) throw mxcpcDidntWorkOutException();
00093 if(ippiDecodeHuffmanSpecInit_JPEG_8u(&DefaultHuffmanTable_Y_AC[0],
00094 &DefaultHuffmanTable_Y_AC[16],
00095 HuffmanTree_Y_AC)
00096 != ippStsNoErr) throw mxcpcDidntWorkOutException();
00097 if(ippiDecodeHuffmanSpecInit_JPEG_8u(&DefaultHuffmanTable_UV_DC[0],
00098 &DefaultHuffmanTable_UV_DC[16],
00099 HuffmanTree_UV_DC)
00100 != ippStsNoErr) throw mxcpcDidntWorkOutException();
00101 if(ippiDecodeHuffmanSpecInit_JPEG_8u(&DefaultHuffmanTable_UV_AC[0],
00102 &DefaultHuffmanTable_UV_AC[16],
00103 HuffmanTree_UV_AC)
00104 != ippStsNoErr) throw mxcpcDidntWorkOutException();
00105
00106 if(ippiEncodeHuffmanSpecInit_JPEG_8u(&DefaultHuffmanTable_Y_DC[0],
00107 &DefaultHuffmanTable_Y_DC[16],
00108 HuffmanEncodeSpec_Y_DC)
00109 != ippStsNoErr) throw mxcpcDidntWorkOutException();
00110 if(ippiEncodeHuffmanSpecInit_JPEG_8u(&DefaultHuffmanTable_Y_AC[0],
00111 &DefaultHuffmanTable_Y_AC[16],
00112 HuffmanEncodeSpec_Y_AC)
00113 != ippStsNoErr) throw mxcpcDidntWorkOutException();
00114 if(ippiEncodeHuffmanSpecInit_JPEG_8u(&DefaultHuffmanTable_UV_DC[0],
00115 &DefaultHuffmanTable_UV_DC[16],
00116 HuffmanEncodeSpec_UV_DC)
00117 != ippStsNoErr) throw mxcpcDidntWorkOutException();
00118 if(ippiEncodeHuffmanSpecInit_JPEG_8u(&DefaultHuffmanTable_UV_AC[0],
00119 &DefaultHuffmanTable_UV_AC[16],
00120 HuffmanEncodeSpec_UV_AC)
00121 != ippStsNoErr) throw mxcpcDidntWorkOutException();
00122
00123 } catch(mxcpcDidntWorkOutException) {
00124
00125 std::free(HuffmanTree_Y_DC);
00126 std::free(HuffmanTree_Y_AC);
00127 std::free(HuffmanTree_UV_DC);
00128 std::free(HuffmanTree_UV_AC);
00129 std::free(HuffmanEncodeSpec_Y_DC);
00130 std::free(HuffmanEncodeSpec_Y_AC);
00131 std::free(HuffmanEncodeSpec_UV_DC);
00132 std::free(HuffmanEncodeSpec_UV_AC);
00133
00134 throw;
00135 }
00136
00137 for(i = 0; i < 64; i++) {
00138 QuantizationTable_Y[i] = 0;
00139 QuantizationTable_UV[i] = 0;
00140 }
00141
00142 CoeffBuffer = 0;
00143 TileNumX = TileNumY = 0;
00144
00145
00146 FramesProcessed = 0;
00147
00148 ConverterBackEnd = backend;
00149
00150
00151
00152 APP0_Block.ff = 0xff;
00153 APP0_Block.app0_marker = mxcpc_mxpeg::MarkerId_APP0;
00154 APP0_Block.len_hi = (sizeof(mxcpc_mxpeg::APP0) - 2) / 256;
00155 APP0_Block.len_lo = (sizeof(mxcpc_mxpeg::APP0) - 2) % 256;
00156 std::strcpy(APP0_Block.id, "JFIF");
00157 APP0_Block.major_vers = 0x01;
00158 APP0_Block.minor_vers = 0x01;
00159 APP0_Block.units = 0x00;
00160 APP0_Block.xdpu_hi = 0;
00161 APP0_Block.xdpu_lo = 1;
00162 APP0_Block.ydpu_hi = 0;
00163 APP0_Block.ydpu_lo = 1;
00164 APP0_Block.thumbnail_x = 0;
00165 APP0_Block.thumbnail_y = 0;
00166
00167
00168 SOF0_Block.ff = 0xff;
00169 SOF0_Block.marker = mxcpc_mxpeg::MarkerId_SOF0;
00170 SOF0_Block.len_hi = (sizeof(mxcpc_mxpeg::SOF0) - 2) / 256;
00171 SOF0_Block.len_lo = (sizeof(mxcpc_mxpeg::SOF0) - 2) % 256;
00172 SOF0_Block.data_precision = 0x08;
00173 SOF0_Block.y_sz_hi = 0;
00174 SOF0_Block.y_sz_lo = 0;
00175 SOF0_Block.x_sz_hi = 0;
00176 SOF0_Block.x_sz_lo = 0;
00177 SOF0_Block.num_components = 3;
00178 SOF0_Block.components[0].component_id = 1;
00179 SOF0_Block.components[0].sampl_fact = 0x22;
00180 SOF0_Block.components[0].quant_tbl_no = 0;
00181 SOF0_Block.components[1].component_id = 2;
00182 SOF0_Block.components[1].sampl_fact = 0x11;
00183 SOF0_Block.components[1].quant_tbl_no = 1;
00184 SOF0_Block.components[2].component_id = 3;
00185 SOF0_Block.components[2].sampl_fact = 0x11;
00186 SOF0_Block.components[2].quant_tbl_no = 1;
00187
00188
00189 SOS_Block.ff = 0xff;
00190 SOS_Block.sos_marker = mxcpc_mxpeg::MarkerId_SOS;
00191 SOS_Block.sz_hi = (sizeof(mxcpc_mxpeg::SOS) - 2) / 256;
00192 SOS_Block.sz_lo = (sizeof(mxcpc_mxpeg::SOS) - 2) % 256;
00193 SOS_Block.comps_in_scan = 3;
00194 SOS_Block.components[0].comp_id = 1;
00195 SOS_Block.components[0].td_ta = 0x00;
00196 SOS_Block.components[1].comp_id = 2;
00197 SOS_Block.components[1].td_ta = 0x11;
00198 SOS_Block.components[2].comp_id = 3;
00199 SOS_Block.components[2].td_ta = 0x11;
00200 SOS_Block.Ss = 0x00;
00201 SOS_Block.Se = 0x3f;
00202 SOS_Block.Ah_Al = 0x00;
00203 }
00204
00205
00206 mxcpcFramewiseMxPEGScanToJPEGConverterIPP::~mxcpcFramewiseMxPEGScanToJPEGConverterIPP() {
00207
00208 delete ConverterBackEnd;
00209
00210 std::free(HuffmanTree_Y_DC);
00211 std::free(HuffmanTree_Y_AC);
00212 std::free(HuffmanTree_UV_DC);
00213 std::free(HuffmanTree_UV_AC);
00214 std::free(HuffmanEncodeSpec_Y_DC);
00215 std::free(HuffmanEncodeSpec_Y_AC);
00216 std::free(HuffmanEncodeSpec_UV_DC);
00217 std::free(HuffmanEncodeSpec_UV_AC);
00218
00219 delete[] CoeffBuffer;
00220 }
00221
00222
00223
00224 void mxcpcFramewiseMxPEGScanToJPEGConverterIPP::setYQuantizationTable(
00225 unsigned char *data_bytes) {
00226
00227 ippiQuantInvTableInit_JPEG_8u16u(data_bytes,
00228 QuantizationTable_Y);
00229 }
00230
00231
00232 void mxcpcFramewiseMxPEGScanToJPEGConverterIPP::setUVQuantizationTable(
00233 unsigned char *data_bytes) {
00234
00235 ippiQuantInvTableInit_JPEG_8u16u(data_bytes,
00236 QuantizationTable_UV);
00237 }
00238
00239
00240 void mxcpcFramewiseMxPEGScanToJPEGConverterIPP
00241 ::performScanSweep(mxcpcFramewiseMxPEGDecoder::UndecodedFrameDescriptor
00242 *frame_descriptor) {
00243
00244
00245
00246
00247 const IppiDecodeHuffmanSpec *dc_huffman_trees[6] = { HuffmanTree_Y_DC,
00248 HuffmanTree_Y_DC,
00249 HuffmanTree_Y_DC,
00250 HuffmanTree_Y_DC,
00251 HuffmanTree_UV_DC,
00252 HuffmanTree_UV_DC,
00253 };
00254 const IppiDecodeHuffmanSpec *ac_huffman_trees[6] = { HuffmanTree_Y_AC,
00255 HuffmanTree_Y_AC,
00256 HuffmanTree_Y_AC,
00257 HuffmanTree_Y_AC,
00258 HuffmanTree_UV_AC,
00259 HuffmanTree_UV_AC,
00260 };
00261 const IppiEncodeHuffmanSpec *dc_huffman_encode_specs[6] = { HuffmanEncodeSpec_Y_DC,
00262 HuffmanEncodeSpec_Y_DC,
00263 HuffmanEncodeSpec_Y_DC,
00264 HuffmanEncodeSpec_Y_DC,
00265 HuffmanEncodeSpec_UV_DC,
00266 HuffmanEncodeSpec_UV_DC,
00267 };
00268 const IppiEncodeHuffmanSpec *ac_huffman_encode_specs[6] = { HuffmanEncodeSpec_Y_AC,
00269 HuffmanEncodeSpec_Y_AC,
00270 HuffmanEncodeSpec_Y_AC,
00271 HuffmanEncodeSpec_Y_AC,
00272 HuffmanEncodeSpec_UV_AC,
00273 HuffmanEncodeSpec_UV_AC,
00274 };
00275 Ipp16s last_y_dc = 0, last_u_dc = 0, last_v_dc = 0;
00276 Ipp16s *last_dc_ptrs[6] = { &last_y_dc, &last_y_dc, &last_y_dc, &last_y_dc,
00277 &last_u_dc, &last_v_dc
00278 };
00279 int detected_marker = 0;
00280 Ipp32u prefetched_bits = 0;
00281 int prefetched_bit_num = 0;
00282 int pos = 0;
00283 Ipp8u bitstream_buffer[MXCPC_FRAMEWISEMXPEGSCANTOJPEGCONVERTERIPP_BITSTREAM_BUFFSIZE];
00284 int bitstream_pos = 0;
00285
00286
00287 IppStatus ipp_status;
00288 bool use_bitmask;
00289 int tilebits_left;
00290 unsigned char *tilebit_ptr, tilebit_mask;
00291 int x, y;
00292 bool next_tile_right_here;
00293 int tiles_to_write;
00294 Ipp16s *sub_mcu_coeffs;
00295 mxcpc::u8 quantization_table_to_write[64];
00296 Ipp16u *quant_coeff;
00297 const unsigned char *huffman_table_to_write;
00298 int huffman_table_to_write_size;
00299 char filename[100];
00300 int i, j;
00301
00302 mxcpc::u8 write_buffer[10];
00303
00304
00305
00306 if(!BackEnd) return;
00307
00308
00309
00310 if( (frame_descriptor->TileNumX != TileNumX)
00311 || (frame_descriptor->TileNumY != TileNumY)) {
00312
00313 delete[] CoeffBuffer;
00314
00315 try {
00316
00317 CoeffBuffer = new Ipp16s[frame_descriptor->TileNumX * frame_descriptor->TileNumY
00318 * 6 * 64];
00319 TileNumX = frame_descriptor->TileNumX;
00320 TileNumY = frame_descriptor->TileNumY;
00321
00322 mxcpc::sendStatusMsg("JPG converter : reallocated coeff buffer");
00323
00324 } catch(std::bad_alloc) {
00325
00326 CoeffBuffer = 0;
00327 TileNumX = TileNumY = 0;
00328 }
00329 }
00330 if(!CoeffBuffer) {
00331 BackEnd->errorEncountered();
00332 return;
00333 }
00334
00335
00336
00337 tilebits_left = frame_descriptor->TileNumX * frame_descriptor->TileNumY;
00338 tilebit_ptr = frame_descriptor->TileBits;
00339 tilebit_mask = 128;
00340 x = -1;
00341 y = 0;
00342 ipp_status = ippStsNoErr;
00343 next_tile_right_here = true;
00344 if(tilebit_ptr)
00345 use_bitmask = true;
00346 else
00347 use_bitmask = false;
00348
00349
00350
00351 while(tilebits_left) {
00352
00353
00354 x++;
00355 if(x == frame_descriptor->TileNumX) {
00356 x = 0;
00357 y++;
00358 }
00359
00360
00361 if(use_bitmask) {
00362 next_tile_right_here = (*tilebit_ptr & tilebit_mask) != 0;
00363 tilebit_mask /= 2;
00364 if(!tilebit_mask) {
00365 tilebit_mask = 128;
00366 tilebit_ptr++;
00367 }
00368 }
00369
00370 if(next_tile_right_here) {
00371
00372
00373 for(i = 0; i < 6; i++) {
00374
00375 if(ipp_status != ippStsNoErr) {
00376
00377 BackEnd->errorEncountered();
00378 return;
00379 }
00380
00381 ipp_status = ippiDecodeHuffman8x8_Direct_JPEG_1u16s_C1(
00382 frame_descriptor->ScanBytes, &pos,
00383 &CoeffBuffer[y * TileNumX * 6*64 + x * 6*64 + i * 64],
00384 last_dc_ptrs[i],
00385 &detected_marker,
00386 &prefetched_bits, &prefetched_bit_num,
00387 dc_huffman_trees[i], ac_huffman_trees[i]);
00388 }
00389
00390
00391
00392 BackEnd->videoTileReceived();
00393 }
00394
00395 tilebits_left--;
00396 }
00397
00398
00399
00400
00401
00402
00403
00404
00405 write_buffer[0] = 0xff;
00406 write_buffer[1] = mxcpc_mxpeg::MarkerId_SOI;
00407
00408 ConverterBackEnd->receiveJPEGBytes(write_buffer, 2);
00409
00410
00411
00412 ConverterBackEnd->receiveJPEGBytes((mxcpc::u8 *)&APP0_Block,
00413 sizeof(mxcpc_mxpeg::APP0));
00414
00415
00416 for(i = 0; i < 2; i++) {
00417
00418 write_buffer[0] = 0xff;
00419 write_buffer[1] = mxcpc_mxpeg::MarkerId_DQT;
00420 write_buffer[2] = 0;
00421 write_buffer[3] = 67;
00422 write_buffer[4] = i;
00423
00424 ConverterBackEnd->receiveJPEGBytes(write_buffer, 5);
00425
00426 if(!i) quant_coeff = QuantizationTable_Y;
00427 else quant_coeff = QuantizationTable_UV;
00428 for(j = 0; j < 64; j++)
00429 quantization_table_to_write[ZigZag_StoreMap[j]] = *quant_coeff++;
00430
00431 ConverterBackEnd->receiveJPEGBytes(quantization_table_to_write, 64);
00432 }
00433
00434
00435 SOF0_Block.x_sz_hi = frame_descriptor->Width / 256;
00436 SOF0_Block.x_sz_lo = frame_descriptor->Width % 256;
00437 SOF0_Block.y_sz_hi = frame_descriptor->Height / 256;
00438 SOF0_Block.y_sz_lo = frame_descriptor->Height % 256;
00439
00440 ConverterBackEnd->receiveJPEGBytes((mxcpc::u8 *)&SOF0_Block,
00441 sizeof(mxcpc_mxpeg::SOF0));
00442
00443
00444 for(i = 0; i < 4; i++) {
00445
00446 write_buffer[0] = 0xff;
00447 write_buffer[1] = mxcpc_mxpeg::MarkerId_DHT;
00448 if(i == 0) {
00449 write_buffer[4] = 0x00;
00450 huffman_table_to_write = DefaultHuffmanTable_Y_DC;
00451 huffman_table_to_write_size = DefaultHuffmanTable_Y_DC_Size;
00452 }
00453 else if(i == 1) {
00454 write_buffer[4] = 0x10;
00455 huffman_table_to_write = DefaultHuffmanTable_Y_AC;
00456 huffman_table_to_write_size = DefaultHuffmanTable_Y_AC_Size;
00457 }
00458 else if(i == 2) {
00459 write_buffer[4] = 0x01;
00460 huffman_table_to_write = DefaultHuffmanTable_UV_DC;
00461 huffman_table_to_write_size = DefaultHuffmanTable_UV_DC_Size;
00462 }
00463 else {
00464 write_buffer[4] = 0x11;
00465 huffman_table_to_write = DefaultHuffmanTable_UV_AC;
00466 huffman_table_to_write_size = DefaultHuffmanTable_UV_AC_Size;
00467 }
00468 write_buffer[2] = (huffman_table_to_write_size + 3) / 256;
00469 write_buffer[3] = (huffman_table_to_write_size + 3) % 256;
00470
00471
00472 ConverterBackEnd->receiveJPEGBytes(write_buffer, 5);
00473
00474 ConverterBackEnd->receiveJPEGBytes((mxcpc::u8 *)huffman_table_to_write,
00475 huffman_table_to_write_size);
00476 }
00477
00478
00479
00480 ConverterBackEnd->receiveJPEGBytes((mxcpc::u8 *)&SOS_Block,
00481 sizeof(mxcpc_mxpeg::SOS));
00482
00483
00484 last_y_dc = last_u_dc = last_v_dc = 0;
00485 sub_mcu_coeffs = CoeffBuffer;
00486 bitstream_pos = 0;
00487 tiles_to_write = TileNumX * TileNumY;
00488 while(tiles_to_write) {
00489
00490
00491 for(i = 0; i < 6; i++) {
00492
00493 ippiEncodeHuffman8x8_Direct_JPEG_16s1u_C1(sub_mcu_coeffs,
00494 bitstream_buffer,
00495 &bitstream_pos,
00496 last_dc_ptrs[i],
00497 dc_huffman_encode_specs[i],
00498 ac_huffman_encode_specs[i]);
00499
00500
00501
00502 if( FramesProcessed == 0 && i==0 && tiles_to_write == (TileNumX * TileNumY) ){
00503
00504 fprintf(stderr,"_____________________________________\n");
00505 fprintf(stderr,"First Frame, first sub tile! \n");
00506 fprintf(stderr,"_____________________________________\n");
00507
00508 for(int k=0;k<8;k++){
00509
00510 fprintf(stderr,"| %d\t%d\t%d\t%d\t%d\t%d\t%d\t%d | \n",
00511 sub_mcu_coeffs[k],
00512 sub_mcu_coeffs[k+1],
00513 sub_mcu_coeffs[k+2],
00514 sub_mcu_coeffs[k+3],
00515 sub_mcu_coeffs[k+4],
00516 sub_mcu_coeffs[k+5],
00517 sub_mcu_coeffs[k+6],
00518 sub_mcu_coeffs[k+7]);
00519 }
00520
00521 }
00522
00523
00524 if(bitstream_pos >= 8) {
00525
00526
00527 ConverterBackEnd->receiveJPEGBytes(bitstream_buffer, bitstream_pos/8);
00528
00529
00530 bitstream_buffer[0] = bitstream_buffer[bitstream_pos/8];
00531 bitstream_pos = bitstream_pos % 8;
00532 }
00533
00534 sub_mcu_coeffs += 64;
00535 }
00536
00537 tiles_to_write--;
00538 }
00539
00540
00541
00542 ConverterBackEnd->receiveJPEGBytes(bitstream_buffer, 1);
00543
00544
00545 write_buffer[0] = 0xff;
00546 write_buffer[1] = mxcpc_mxpeg::MarkerId_EOI;
00547
00548 ConverterBackEnd->receiveJPEGBytes(write_buffer, 2);
00549
00550
00551
00552
00553 ConverterBackEnd->endFrame();
00554
00555
00556 FramesProcessed++;
00557 }