00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <mxcpcFramewiseMxPEGScanToJPEGConverterIPP.h>
00015 #include <mxcpcMxPEGDecoderBackEnd.h>
00016 #include <mxcpcJPEGReceiver.h>
00017 #include <mxcpc_exceptions.h>
00018
00019 #include <memory>
00020
00021
00022
00023 const unsigned char mxcpcFramewiseMxPEGScanToJPEGConverterIPP
00024 ::ZigZag_StoreMap[64] = {
00025 0, 1, 5, 6, 14, 15, 27, 28,
00026 2, 4, 7, 13, 16, 26, 29, 42,
00027 3, 8, 12, 17, 25, 30, 41, 43,
00028 9, 11, 18, 24, 31, 40, 44, 53,
00029 10, 19, 23, 32, 39, 45, 52, 54,
00030 20, 22, 33, 38, 46, 51, 55, 60,
00031 21, 34, 37, 47, 50, 56, 59, 61,
00032 35, 36, 48, 49, 57, 58, 62, 63
00033 };
00034
00035
00036
00037 mxcpcFramewiseMxPEGScanToJPEGConverterIPP
00038 ::mxcpcFramewiseMxPEGScanToJPEGConverterIPP(mxcpcJPEGReceiver *receiver)
00039 : mxcpcFramewiseMxPEGScanToJPEGConverter(receiver) {
00040
00041 int huffman_size;
00042 int i;
00043
00044 HuffmanTree_Y_DC = 0;
00045 HuffmanTree_Y_AC = 0;
00046 HuffmanTree_UV_DC = 0;
00047 HuffmanTree_UV_AC = 0;
00048 HuffmanEncodeSpec_Y_DC = 0;
00049 HuffmanEncodeSpec_Y_AC = 0;
00050 HuffmanEncodeSpec_UV_DC = 0;
00051 HuffmanEncodeSpec_UV_AC = 0;
00052
00053 ippiDecodeHuffmanSpecGetBufSize_JPEG_8u(&huffman_size);
00054 HuffmanTree_Y_DC = (IppiDecodeHuffmanSpec *)std::malloc(huffman_size);
00055 HuffmanTree_Y_AC = (IppiDecodeHuffmanSpec *)std::malloc(huffman_size);
00056 HuffmanTree_UV_DC = (IppiDecodeHuffmanSpec *)std::malloc(huffman_size);
00057 HuffmanTree_UV_AC = (IppiDecodeHuffmanSpec *)std::malloc(huffman_size);
00058 ippiEncodeHuffmanSpecGetBufSize_JPEG_8u(&huffman_size);
00059 HuffmanEncodeSpec_Y_DC = (IppiEncodeHuffmanSpec *)std::malloc(huffman_size);
00060 HuffmanEncodeSpec_Y_AC = (IppiEncodeHuffmanSpec *)std::malloc(huffman_size);
00061 HuffmanEncodeSpec_UV_DC = (IppiEncodeHuffmanSpec *)std::malloc(huffman_size);
00062 HuffmanEncodeSpec_UV_AC = (IppiEncodeHuffmanSpec *)std::malloc(huffman_size);
00063
00064 if( !HuffmanTree_Y_DC
00065 || !HuffmanTree_Y_AC
00066 || !HuffmanTree_UV_DC
00067 || !HuffmanTree_UV_AC
00068 || !HuffmanEncodeSpec_Y_DC
00069 || !HuffmanEncodeSpec_Y_AC
00070 || !HuffmanEncodeSpec_UV_DC
00071 || !HuffmanEncodeSpec_UV_AC) {
00072
00073 std::free(HuffmanTree_Y_DC);
00074 std::free(HuffmanTree_Y_AC);
00075 std::free(HuffmanTree_UV_DC);
00076 std::free(HuffmanTree_UV_AC);
00077 std::free(HuffmanEncodeSpec_Y_DC);
00078 std::free(HuffmanEncodeSpec_Y_AC);
00079 std::free(HuffmanEncodeSpec_UV_DC);
00080 std::free(HuffmanEncodeSpec_UV_AC);
00081
00082 throw std::bad_alloc();
00083 }
00084
00085 try {
00086
00087 if(ippiDecodeHuffmanSpecInit_JPEG_8u(&DefaultHuffmanTable_Y_DC[0],
00088 &DefaultHuffmanTable_Y_DC[16],
00089 HuffmanTree_Y_DC)
00090 != ippStsNoErr) throw mxcpcDidntWorkOutException();
00091 if(ippiDecodeHuffmanSpecInit_JPEG_8u(&DefaultHuffmanTable_Y_AC[0],
00092 &DefaultHuffmanTable_Y_AC[16],
00093 HuffmanTree_Y_AC)
00094 != ippStsNoErr) throw mxcpcDidntWorkOutException();
00095 if(ippiDecodeHuffmanSpecInit_JPEG_8u(&DefaultHuffmanTable_UV_DC[0],
00096 &DefaultHuffmanTable_UV_DC[16],
00097 HuffmanTree_UV_DC)
00098 != ippStsNoErr) throw mxcpcDidntWorkOutException();
00099 if(ippiDecodeHuffmanSpecInit_JPEG_8u(&DefaultHuffmanTable_UV_AC[0],
00100 &DefaultHuffmanTable_UV_AC[16],
00101 HuffmanTree_UV_AC)
00102 != ippStsNoErr) throw mxcpcDidntWorkOutException();
00103
00104 if(ippiEncodeHuffmanSpecInit_JPEG_8u(&DefaultHuffmanTable_Y_DC[0],
00105 &DefaultHuffmanTable_Y_DC[16],
00106 HuffmanEncodeSpec_Y_DC)
00107 != ippStsNoErr) throw mxcpcDidntWorkOutException();
00108 if(ippiEncodeHuffmanSpecInit_JPEG_8u(&DefaultHuffmanTable_Y_AC[0],
00109 &DefaultHuffmanTable_Y_AC[16],
00110 HuffmanEncodeSpec_Y_AC)
00111 != ippStsNoErr) throw mxcpcDidntWorkOutException();
00112 if(ippiEncodeHuffmanSpecInit_JPEG_8u(&DefaultHuffmanTable_UV_DC[0],
00113 &DefaultHuffmanTable_UV_DC[16],
00114 HuffmanEncodeSpec_UV_DC)
00115 != ippStsNoErr) throw mxcpcDidntWorkOutException();
00116 if(ippiEncodeHuffmanSpecInit_JPEG_8u(&DefaultHuffmanTable_UV_AC[0],
00117 &DefaultHuffmanTable_UV_AC[16],
00118 HuffmanEncodeSpec_UV_AC)
00119 != ippStsNoErr) throw mxcpcDidntWorkOutException();
00120
00121 } catch(mxcpcDidntWorkOutException) {
00122
00123 std::free(HuffmanTree_Y_DC);
00124 std::free(HuffmanTree_Y_AC);
00125 std::free(HuffmanTree_UV_DC);
00126 std::free(HuffmanTree_UV_AC);
00127 std::free(HuffmanEncodeSpec_Y_DC);
00128 std::free(HuffmanEncodeSpec_Y_AC);
00129 std::free(HuffmanEncodeSpec_UV_DC);
00130 std::free(HuffmanEncodeSpec_UV_AC);
00131
00132 throw;
00133 }
00134
00135 for(i = 0; i < 64; i++) {
00136 QuantizationTable_Y[i] = 0;
00137 QuantizationTable_UV[i] = 0;
00138 }
00139
00140 CoeffBuffer = 0;
00141 TileNumX = TileNumY = 0;
00142
00143 FramesProcessed = 0;
00144
00145
00146
00147 APP0_Block.ff = 0xff;
00148 APP0_Block.app0_marker = mxcpc_mxpeg::MarkerId_APP0;
00149 APP0_Block.len_hi = (sizeof(mxcpc_mxpeg::APP0) - 2) / 256;
00150 APP0_Block.len_lo = (sizeof(mxcpc_mxpeg::APP0) - 2) % 256;
00151 std::strcpy(APP0_Block.id, "JFIF");
00152 APP0_Block.major_vers = 0x01;
00153 APP0_Block.minor_vers = 0x01;
00154 APP0_Block.units = 0x00;
00155 APP0_Block.xdpu_hi = 0;
00156 APP0_Block.xdpu_lo = 1;
00157 APP0_Block.ydpu_hi = 0;
00158 APP0_Block.ydpu_lo = 1;
00159 APP0_Block.thumbnail_x = 0;
00160 APP0_Block.thumbnail_y = 0;
00161
00162
00163 SOF0_Block.ff = 0xff;
00164 SOF0_Block.marker = mxcpc_mxpeg::MarkerId_SOF0;
00165 SOF0_Block.len_hi = (sizeof(mxcpc_mxpeg::SOF0) - 2) / 256;
00166 SOF0_Block.len_lo = (sizeof(mxcpc_mxpeg::SOF0) - 2) % 256;
00167 SOF0_Block.data_precision = 0x08;
00168 SOF0_Block.y_sz_hi = 0;
00169 SOF0_Block.y_sz_lo = 0;
00170 SOF0_Block.x_sz_hi = 0;
00171 SOF0_Block.x_sz_lo = 0;
00172 SOF0_Block.num_components = 3;
00173 SOF0_Block.components[0].component_id = 1;
00174 SOF0_Block.components[0].sampl_fact = 0x22;
00175 SOF0_Block.components[0].quant_tbl_no = 0;
00176 SOF0_Block.components[1].component_id = 2;
00177 SOF0_Block.components[1].sampl_fact = 0x11;
00178 SOF0_Block.components[1].quant_tbl_no = 1;
00179 SOF0_Block.components[2].component_id = 3;
00180 SOF0_Block.components[2].sampl_fact = 0x11;
00181 SOF0_Block.components[2].quant_tbl_no = 1;
00182
00183
00184 SOS_Block.ff = 0xff;
00185 SOS_Block.sos_marker = mxcpc_mxpeg::MarkerId_SOS;
00186 SOS_Block.sz_hi = (sizeof(mxcpc_mxpeg::SOS) - 2) / 256;
00187 SOS_Block.sz_lo = (sizeof(mxcpc_mxpeg::SOS) - 2) % 256;
00188 SOS_Block.comps_in_scan = 3;
00189 SOS_Block.components[0].comp_id = 1;
00190 SOS_Block.components[0].td_ta = 0x00;
00191 SOS_Block.components[1].comp_id = 2;
00192 SOS_Block.components[1].td_ta = 0x11;
00193 SOS_Block.components[2].comp_id = 3;
00194 SOS_Block.components[2].td_ta = 0x11;
00195 SOS_Block.Ss = 0x00;
00196 SOS_Block.Se = 0x3f;
00197 SOS_Block.Ah_Al = 0x00;
00198 }
00199
00200
00201 mxcpcFramewiseMxPEGScanToJPEGConverterIPP
00202 ::~mxcpcFramewiseMxPEGScanToJPEGConverterIPP() {
00203
00204 std::free(HuffmanTree_Y_DC);
00205 std::free(HuffmanTree_Y_AC);
00206 std::free(HuffmanTree_UV_DC);
00207 std::free(HuffmanTree_UV_AC);
00208 std::free(HuffmanEncodeSpec_Y_DC);
00209 std::free(HuffmanEncodeSpec_Y_AC);
00210 std::free(HuffmanEncodeSpec_UV_DC);
00211 std::free(HuffmanEncodeSpec_UV_AC);
00212
00213 delete[] CoeffBuffer;
00214 }
00215
00216
00217
00218 const char *mxcpcFramewiseMxPEGScanToJPEGConverterIPP
00219 ::getAccelerationTypeString(void) {
00220
00221 return("Intel Performance Primitives");
00222 }
00223
00224
00225 void mxcpcFramewiseMxPEGScanToJPEGConverterIPP::setYQuantizationTable(
00226 unsigned char *data_bytes) {
00227
00228 ippiQuantInvTableInit_JPEG_8u16u(data_bytes,
00229 QuantizationTable_Y);
00230 }
00231
00232
00233 void mxcpcFramewiseMxPEGScanToJPEGConverterIPP::setUVQuantizationTable(
00234 unsigned char *data_bytes) {
00235
00236 ippiQuantInvTableInit_JPEG_8u16u(data_bytes,
00237 QuantizationTable_UV);
00238 }
00239
00240
00241 void mxcpcFramewiseMxPEGScanToJPEGConverterIPP
00242 ::performScanSweep(mxcpcFramewiseMxPEGDecoder::UndecodedFrameDescriptor
00243 *frame_descriptor) {
00244
00245
00246
00247
00248 const IppiDecodeHuffmanSpec *dc_huffman_trees[6] = { HuffmanTree_Y_DC,
00249 HuffmanTree_Y_DC,
00250 HuffmanTree_Y_DC,
00251 HuffmanTree_Y_DC,
00252 HuffmanTree_UV_DC,
00253 HuffmanTree_UV_DC,
00254 };
00255 const IppiDecodeHuffmanSpec *ac_huffman_trees[6] = { HuffmanTree_Y_AC,
00256 HuffmanTree_Y_AC,
00257 HuffmanTree_Y_AC,
00258 HuffmanTree_Y_AC,
00259 HuffmanTree_UV_AC,
00260 HuffmanTree_UV_AC,
00261 };
00262 const IppiEncodeHuffmanSpec *dc_huffman_encode_specs[6] = { HuffmanEncodeSpec_Y_DC,
00263 HuffmanEncodeSpec_Y_DC,
00264 HuffmanEncodeSpec_Y_DC,
00265 HuffmanEncodeSpec_Y_DC,
00266 HuffmanEncodeSpec_UV_DC,
00267 HuffmanEncodeSpec_UV_DC,
00268 };
00269 const IppiEncodeHuffmanSpec *ac_huffman_encode_specs[6] = { HuffmanEncodeSpec_Y_AC,
00270 HuffmanEncodeSpec_Y_AC,
00271 HuffmanEncodeSpec_Y_AC,
00272 HuffmanEncodeSpec_Y_AC,
00273 HuffmanEncodeSpec_UV_AC,
00274 HuffmanEncodeSpec_UV_AC,
00275 };
00276 Ipp16s last_y_dc = 0, last_u_dc = 0, last_v_dc = 0;
00277 Ipp16s *last_dc_ptrs[6] = { &last_y_dc, &last_y_dc, &last_y_dc, &last_y_dc,
00278 &last_u_dc, &last_v_dc
00279 };
00280 int detected_marker = 0;
00281 Ipp32u prefetched_bits = 0;
00282 int prefetched_bit_num = 0;
00283 int pos = 0;
00284 Ipp8u bitstream_buffer[MXCPC_FRAMEWISEMXPEGSCANTOJPEGCONVERTERIPP_BITSTREAM_BUFFSIZE];
00285 int bitstream_pos = 0;
00286
00287
00288 IppStatus ipp_status;
00289 bool use_bitmask;
00290 int tilebits_left;
00291 unsigned char *tilebit_ptr, tilebit_mask;
00292 int x, y;
00293 bool next_tile_right_here;
00294 int tiles_to_write;
00295 Ipp16s *sub_mcu_coeffs;
00296 mxcpc::u8 quantization_table_to_write[64];
00297 Ipp16u *quant_coeff;
00298 const unsigned char *huffman_table_to_write;
00299 int huffman_table_to_write_size;
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 Receiver->beginFrame();
00401
00402
00403 write_buffer[0] = 0xff;
00404 write_buffer[1] = mxcpc_mxpeg::MarkerId_SOI;
00405 Receiver->receiveJPEGBytes(write_buffer, 2);
00406
00407
00408 Receiver->receiveJPEGBytes((mxcpc::u8 *)&APP0_Block,
00409 sizeof(mxcpc_mxpeg::APP0));
00410
00411
00412 for(i = 0; i < 2; i++) {
00413
00414 write_buffer[0] = 0xff;
00415 write_buffer[1] = mxcpc_mxpeg::MarkerId_DQT;
00416 write_buffer[2] = 0;
00417 write_buffer[3] = 67;
00418 write_buffer[4] = i;
00419 Receiver->receiveJPEGBytes(write_buffer, 5);
00420
00421 if(!i) quant_coeff = QuantizationTable_Y;
00422 else quant_coeff = QuantizationTable_UV;
00423 for(j = 0; j < 64; j++)
00424 quantization_table_to_write[ZigZag_StoreMap[j]] = *quant_coeff++;
00425 Receiver->receiveJPEGBytes(quantization_table_to_write, 64);
00426 }
00427
00428
00429 SOF0_Block.x_sz_hi = frame_descriptor->Width / 256;
00430 SOF0_Block.x_sz_lo = frame_descriptor->Width % 256;
00431 SOF0_Block.y_sz_hi = frame_descriptor->Height / 256;
00432 SOF0_Block.y_sz_lo = frame_descriptor->Height % 256;
00433 Receiver->receiveJPEGBytes((mxcpc::u8 *)&SOF0_Block,
00434 sizeof(mxcpc_mxpeg::SOF0));
00435
00436
00437 for(i = 0; i < 4; i++) {
00438
00439 write_buffer[0] = 0xff;
00440 write_buffer[1] = mxcpc_mxpeg::MarkerId_DHT;
00441 if(i == 0) {
00442 write_buffer[4] = 0x00;
00443 huffman_table_to_write = DefaultHuffmanTable_Y_DC;
00444 huffman_table_to_write_size = DefaultHuffmanTable_Y_DC_Size;
00445 }
00446 else if(i == 1) {
00447 write_buffer[4] = 0x10;
00448 huffman_table_to_write = DefaultHuffmanTable_Y_AC;
00449 huffman_table_to_write_size = DefaultHuffmanTable_Y_AC_Size;
00450 }
00451 else if(i == 2) {
00452 write_buffer[4] = 0x01;
00453 huffman_table_to_write = DefaultHuffmanTable_UV_DC;
00454 huffman_table_to_write_size = DefaultHuffmanTable_UV_DC_Size;
00455 }
00456 else {
00457 write_buffer[4] = 0x11;
00458 huffman_table_to_write = DefaultHuffmanTable_UV_AC;
00459 huffman_table_to_write_size = DefaultHuffmanTable_UV_AC_Size;
00460 }
00461 write_buffer[2] = (huffman_table_to_write_size + 3) / 256;
00462 write_buffer[3] = (huffman_table_to_write_size + 3) % 256;
00463
00464 Receiver->receiveJPEGBytes(write_buffer, 5);
00465 Receiver->receiveJPEGBytes((mxcpc::u8 *)huffman_table_to_write,
00466 huffman_table_to_write_size);
00467 }
00468
00469
00470 Receiver->receiveJPEGBytes((mxcpc::u8 *)&SOS_Block,
00471 sizeof(mxcpc_mxpeg::SOS));
00472
00473
00474 last_y_dc = last_u_dc = last_v_dc = 0;
00475 sub_mcu_coeffs = CoeffBuffer;
00476 bitstream_pos = 0;
00477 tiles_to_write = TileNumX * TileNumY;
00478 while(tiles_to_write) {
00479
00480
00481 for(i = 0; i < 6; i++) {
00482
00483 ippiEncodeHuffman8x8_Direct_JPEG_16s1u_C1(sub_mcu_coeffs,
00484 bitstream_buffer,
00485 &bitstream_pos,
00486 last_dc_ptrs[i],
00487 dc_huffman_encode_specs[i],
00488 ac_huffman_encode_specs[i]);
00489
00490 if(bitstream_pos >= 8) {
00491
00492 Receiver->receiveJPEGBytes(bitstream_buffer, bitstream_pos/8);
00493
00494
00495 bitstream_buffer[0] = bitstream_buffer[bitstream_pos/8];
00496 bitstream_pos = bitstream_pos % 8;
00497 }
00498
00499 sub_mcu_coeffs += 64;
00500 }
00501
00502 tiles_to_write--;
00503 }
00504
00505
00506 Receiver->receiveJPEGBytes(bitstream_buffer, 1);
00507
00508
00509 write_buffer[0] = 0xff;
00510 write_buffer[1] = mxcpc_mxpeg::MarkerId_EOI;
00511 Receiver->receiveJPEGBytes(write_buffer, 2);
00512
00513 Receiver->endFrame();
00514
00515
00516 FramesProcessed++;
00517 }