/* Make paying for the trip fair for all students. */ int main() { while(true) { // Parse input: std::string line; std::getline(std::cin, line); int N = readInt(line); if(N == 0) return 0; int paid[10000]; int sum = 0; for(int i = 0; i < N; ++i) { std::getline(std::cin, line); int val = readInt(line); paid[i] = val; sum += val; } // Compute output: int avg = (sum+N/2)/N; //std::cerr << " AVERAGE: " << avg << std::endl; int pay1 = computeFor(avg-1, avg, N, paid); int pay2 = computeFor(avg, avg+1, N, paid); int pay = pay1 < pay2 ? pay1 : pay2; //std::cerr << " TOTAL TRANSACTION: " << pay << std::endl; printf("$%i.%02i\n", pay/100, pay%100); //std::cerr << " " << pay << std::endl; } }
CallLinkStatus CallLinkStatus::computeFor( CodeBlock* profiledBlock, unsigned bytecodeIndex, const CallLinkInfoMap& map) { ConcurrentJITLocker locker(profiledBlock->m_lock); UNUSED_PARAM(profiledBlock); UNUSED_PARAM(bytecodeIndex); UNUSED_PARAM(map); #if ENABLE(DFG_JIT) if (profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCache)) || profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCacheWatchpoint)) || profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadExecutable))) return takesSlowPath(); CallLinkInfo* callLinkInfo = map.get(CodeOrigin(bytecodeIndex)); if (!callLinkInfo) return computeFromLLInt(locker, profiledBlock, bytecodeIndex); CallLinkStatus result = computeFor(locker, *callLinkInfo); if (!result) return computeFromLLInt(locker, profiledBlock, bytecodeIndex); if (profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadFunction))) result.makeClosureCall(); return result; #else return CallLinkStatus(); #endif }
void CallLinkStatus::computeDFGStatuses( CodeBlock* dfgCodeBlock, CallLinkStatus::ContextMap& map) { #if ENABLE(DFG_JIT) RELEASE_ASSERT(dfgCodeBlock->jitType() == JITCode::DFGJIT); CodeBlock* baselineCodeBlock = dfgCodeBlock->alternative(); for (auto iter = dfgCodeBlock->callLinkInfosBegin(); !!iter; ++iter) { CallLinkInfo& info = **iter; CodeOrigin codeOrigin = info.codeOrigin; bool takeSlowPath; bool badFunction; // Check if we had already previously made a terrible mistake in the FTL for this // code origin. Note that this is approximate because we could have a monovariant // inline in the FTL that ended up failing. We should fix that at some point by // having data structures to track the context of frequent exits. This is currently // challenging because it would require creating a CodeOrigin-based database in // baseline CodeBlocks, but those CodeBlocks don't really have a place to put the // InlineCallFrames. CodeBlock* currentBaseline = baselineCodeBlockForOriginAndBaselineCodeBlock(codeOrigin, baselineCodeBlock); { ConcurrentJITLocker locker(currentBaseline->m_lock); takeSlowPath = currentBaseline->hasExitSite(locker, DFG::FrequentExitSite(codeOrigin.bytecodeIndex, BadCache, ExitFromFTL)) || currentBaseline->hasExitSite(locker, DFG::FrequentExitSite(codeOrigin.bytecodeIndex, BadCacheWatchpoint, ExitFromFTL)) || currentBaseline->hasExitSite(locker, DFG::FrequentExitSite(codeOrigin.bytecodeIndex, BadExecutable, ExitFromFTL)); badFunction = currentBaseline->hasExitSite(locker, DFG::FrequentExitSite(codeOrigin.bytecodeIndex, BadFunction, ExitFromFTL)); } { ConcurrentJITLocker locker(dfgCodeBlock->m_lock); if (takeSlowPath) map.add(info.codeOrigin, takesSlowPath()); else { CallLinkStatus status = computeFor(locker, info); if (status.isSet()) { if (badFunction) status.makeClosureCall(); map.add(info.codeOrigin, status); } } } } #else UNUSED_PARAM(dfgCodeBlock); #endif // ENABLE(DFG_JIT) if (verbose) { dataLog("Context map:\n"); ContextMap::iterator iter = map.begin(); ContextMap::iterator end = map.end(); for (; iter != end; ++iter) { dataLog(" ", iter->key, ":\n"); dataLog(" ", iter->value, "\n"); } } }
GetByIdStatus GetByIdStatus::computeFor( CodeBlock* profiledBlock, CodeBlock* dfgBlock, StubInfoMap& baselineMap, StubInfoMap& dfgMap, CodeOrigin codeOrigin, StringImpl* uid) { #if ENABLE(DFG_JIT) if (dfgBlock) { GetByIdStatus result; { ConcurrentJITLocker locker(dfgBlock->m_lock); result = computeForStubInfo(locker, dfgBlock, dfgMap.get(codeOrigin), uid); } if (result.takesSlowPath()) return result; { ConcurrentJITLocker locker(profiledBlock->m_lock); if (hasExitSite(locker, profiledBlock, codeOrigin.bytecodeIndex, ExitFromFTL)) return GetByIdStatus(TakesSlowPath, true); } if (result.isSet()) return result; } #else UNUSED_PARAM(dfgBlock); UNUSED_PARAM(dfgMap); #endif return computeFor(profiledBlock, baselineMap, codeOrigin.bytecodeIndex, uid); }
PutByIdStatus PutByIdStatus::computeFor(CodeBlock* baselineBlock, CodeBlock* dfgBlock, StubInfoMap& baselineMap, StubInfoMap& dfgMap, CodeOrigin codeOrigin, StringImpl* uid) { #if ENABLE(DFG_JIT) if (dfgBlock) { CallLinkStatus::ExitSiteData exitSiteData; { ConcurrentJITLocker locker(baselineBlock->m_lock); if (hasExitSite(locker, baselineBlock, codeOrigin.bytecodeIndex, ExitFromFTL)) return PutByIdStatus(TakesSlowPath); exitSiteData = CallLinkStatus::computeExitSiteData( locker, baselineBlock, codeOrigin.bytecodeIndex, ExitFromFTL); } PutByIdStatus result; { ConcurrentJITLocker locker(dfgBlock->m_lock); result = computeForStubInfo( locker, dfgBlock, dfgMap.get(codeOrigin), uid, exitSiteData); } // We use TakesSlowPath in some cases where the stub was unset. That's weird and // it would be better not to do that. But it means that we have to defend // ourselves here. if (result.isSimple()) return result; } #else UNUSED_PARAM(dfgBlock); UNUSED_PARAM(dfgMap); #endif return computeFor(baselineBlock, baselineMap, codeOrigin.bytecodeIndex, uid); }
CallLinkStatus CallLinkStatus::computeFor( CodeBlock* profiledBlock, CodeOrigin codeOrigin, const CallLinkInfoMap& baselineMap, const CallLinkStatus::ContextMap& dfgMap) { auto iter = dfgMap.find(codeOrigin); if (iter != dfgMap.end()) return iter->value; return computeFor(profiledBlock, codeOrigin.bytecodeIndex, baselineMap); }
CallLinkStatus CallLinkStatus::computeFor( const ConcurrentJITLocker& locker, CallLinkInfo& callLinkInfo, ExitSiteData exitSiteData) { if (exitSiteData.m_takesSlowPath) return takesSlowPath(); CallLinkStatus result = computeFor(locker, callLinkInfo); if (exitSiteData.m_badFunction) result.makeClosureCall(); return result; }
CallLinkStatus CallLinkStatus::computeFor( const ConcurrentJITLocker& locker, CodeBlock* profiledBlock, CallLinkInfo& callLinkInfo, ExitSiteData exitSiteData) { CallLinkStatus result = computeFor(locker, profiledBlock, callLinkInfo); if (exitSiteData.m_badFunction) result.makeClosureCall(); if (exitSiteData.m_takesSlowPath) result.m_couldTakeSlowPath = true; return result; }
//////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////// ////////////JPEG SPECIFIC CODE HERE BELOW ////////////////////// //////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////// UINT8 EXTR::read_next_marker() { UINT8 tmp; tmp = read_8_bits(); if (tmp != 0xff) return ERROR_INVALID_FILL_BYTE; do { tmp = read_8_bits(); computeFor(1); } while (tmp == 0xff); return tmp; //SUCCESS; }
inline UINT8 EXTR::read_8_bits() { UINT8 inputValue; UINT8 alignment = (m_inputAdd & 0x3); if(alignment == 0 || !m_bufferValid) { // Address is a multiple of 4: need to read a new word from memory DeviceRead(JPEGRAM_ID, m_inputAdd & 0xFFFFFFFC, &m_inputBuffer[0], 4); m_bufferValid = true; } inputValue = m_inputBuffer[alignment]; m_inputAdd+=1; computeFor(1); return inputValue; }
void CallLinkStatus::computeDFGStatuses( CodeBlock* dfgCodeBlock, CallLinkStatus::ContextMap& map) { #if ENABLE(DFG_JIT) RELEASE_ASSERT(dfgCodeBlock->jitType() == JITCode::DFGJIT); CodeBlock* baselineCodeBlock = dfgCodeBlock->alternative(); for (auto iter = dfgCodeBlock->callLinkInfosBegin(); !!iter; ++iter) { CallLinkInfo& info = **iter; CodeOrigin codeOrigin = info.codeOrigin(); // Check if we had already previously made a terrible mistake in the FTL for this // code origin. Note that this is approximate because we could have a monovariant // inline in the FTL that ended up failing. We should fix that at some point by // having data structures to track the context of frequent exits. This is currently // challenging because it would require creating a CodeOrigin-based database in // baseline CodeBlocks, but those CodeBlocks don't really have a place to put the // InlineCallFrames. CodeBlock* currentBaseline = baselineCodeBlockForOriginAndBaselineCodeBlock(codeOrigin, baselineCodeBlock); ExitSiteData exitSiteData; { ConcurrentJITLocker locker(currentBaseline->m_lock); exitSiteData = computeExitSiteData( locker, currentBaseline, codeOrigin.bytecodeIndex); } { ConcurrentJITLocker locker(dfgCodeBlock->m_lock); map.add(info.codeOrigin(), computeFor(locker, dfgCodeBlock, info, exitSiteData)); } } #else UNUSED_PARAM(dfgCodeBlock); #endif // ENABLE(DFG_JIT) if (verbose) { dataLog("Context map:\n"); ContextMap::iterator iter = map.begin(); ContextMap::iterator end = map.end(); for (; iter != end; ++iter) { dataLog(" ", iter->key, ":\n"); dataLog(" ", iter->value, "\n"); } } }
void EXTR::launch_face_detection(void) { if (GetVerbose()) SpacePrint("EXTR: Launching Face Detection\n"); if (++m_currentBitmapImage > MAX_NB_IMAGE) m_currentBitmapImage = 1; JMSG messageToFace; messageToFace.command = SCMD_BEGIN_FACE_DETECTION; messageToFace.param0 = m_decompressedImageAddr[m_currentBitmapImage-1]; messageToFace.param1 = m_currentJPEGImageNo; computeFor(1); ModuleWrite(FACEDETECT_ID, SPACE_BLOCKING, &messageToFace); if (GetVerbose()) SpacePrint("EXTR: Returned from launch face detection for image #%d\n", m_currentBitmapImage); }
CallLinkStatus CallLinkStatus::computeFor( const ConcurrentJITLocker& locker, CodeBlock* profiledBlock, CallLinkInfo& callLinkInfo, ExitSiteData exitSiteData) { CallLinkStatus result = computeFor(locker, profiledBlock, callLinkInfo); if (exitSiteData.badFunction) { if (result.isBasedOnStub()) { // If we have a polymorphic stub, then having an exit site is not quite so useful. In // most cases, the information in the stub has higher fidelity. result.makeClosureCall(); } else { // We might not have a polymorphic stub for any number of reasons. When this happens, we // are in less certain territory, so exit sites mean a lot. result.m_couldTakeSlowPath = true; } } if (exitSiteData.takesSlowPath) result.m_couldTakeSlowPath = true; return result; }
CallLinkStatus CallLinkStatus::computeFor( CodeBlock* profiledBlock, unsigned bytecodeIndex, const CallLinkInfoMap& map) { ConcurrentJITLocker locker(profiledBlock->m_lock); UNUSED_PARAM(profiledBlock); UNUSED_PARAM(bytecodeIndex); UNUSED_PARAM(map); #if ENABLE(DFG_JIT) ExitSiteData exitSiteData = computeExitSiteData(locker, profiledBlock, bytecodeIndex); if (exitSiteData.m_takesSlowPath) return takesSlowPath(); CallLinkInfo* callLinkInfo = map.get(CodeOrigin(bytecodeIndex)); if (!callLinkInfo) return computeFromLLInt(locker, profiledBlock, bytecodeIndex); return computeFor(locker, *callLinkInfo, exitSiteData); #else return CallLinkStatus(); #endif }
GetByIdStatus GetByIdStatus::computeFor( CodeBlock* profiledBlock, CodeBlock* dfgBlock, StubInfoMap& baselineMap, StubInfoMap& dfgMap, CodeOrigin codeOrigin, UniquedStringImpl* uid) { #if ENABLE(DFG_JIT) if (dfgBlock) { CallLinkStatus::ExitSiteData exitSiteData; { ConcurrentJITLocker locker(profiledBlock->m_lock); exitSiteData = CallLinkStatus::computeExitSiteData( locker, profiledBlock, codeOrigin.bytecodeIndex); } GetByIdStatus result; { ConcurrentJITLocker locker(dfgBlock->m_lock); result = computeForStubInfoWithoutExitSiteFeedback( locker, dfgBlock, dfgMap.get(codeOrigin), uid, exitSiteData); } if (result.takesSlowPath()) return result; { ConcurrentJITLocker locker(profiledBlock->m_lock); if (hasExitSite(locker, profiledBlock, codeOrigin.bytecodeIndex)) return GetByIdStatus(TakesSlowPath, true); } if (result.isSet()) return result; } #else UNUSED_PARAM(dfgBlock); UNUSED_PARAM(dfgMap); #endif return computeFor(profiledBlock, baselineMap, codeOrigin.bytecodeIndex, uid); }
// // EXTR::decode_interleaved_scan ////////////////////////////////////////////////////////////////////////////// /// /// This is the loop that extracts the jpeg data /// /// /// @return => UINT16 : SUCCESS (always) /// /// @note => ////////////////////////////////////////////////////////////////////////////// UINT16 EXTR::decode_interleaved_scan() { UINT16 i, j, horizontal_mcus, vertical_mcus; space_uint2 k, number_of_image_components_in_frame; space_uint4 l, m, horizontal_sampling_factor, vertical_sampling_factor; JMSG msg; // use these shortcuts horizontal_mcus = m_jpeg_decoder_structure.horizontal_mcus; vertical_mcus = m_jpeg_decoder_structure.vertical_mcus; number_of_image_components_in_frame = m_jpeg_decoder_structure.number_of_image_components_in_frame; // // The jpeg image is stored in minimal component units or mcu. Each unit represents // a luminance block (Y) or a chrominance block (C). Since this decoder only supports // files that are encoded in the YUV 4:2:0 format, MCUs are stored in groups of 6. // The four first MCUs are luminance component. The two lasts are chrominance Cb and Cr // that are colour information for the 4 previous luminance blocks. // This can be seen as follow: // // _____________ // | | | // | Y1 | Y2 | // | ___|___ | // | | | | | // |--|Cb | Cr|--| // | |___|___| | // | | | // | Y3 | Y4 | // |______|______| // // we scan all the vertical & horizontal mcus for (i=1; i<=vertical_mcus; i++) //for (i=1; i<=vertical_mcus/2; i++) { for (j=1; j<=horizontal_mcus;j++) //for (j=1; j<=horizontal_mcus/4;j++) { // every mcu is composed of 3 components Y, Cb and Cr for (k=0; k<number_of_image_components_in_frame; k ++) { vertical_sampling_factor = m_jpeg_decoder_structure.vertical_sampling_factor [k]; horizontal_sampling_factor = m_jpeg_decoder_structure.horizontal_sampling_factor [k]; computeFor(1); for (l=0; l<vertical_sampling_factor; l++) { for (m=0; m<horizontal_sampling_factor; m++) { // triggers a notification to huffman thread to start Huffman decoding m_currentHuffmanComponent = k; // send information to HUFF module msg.command = SCMD_HUFFMAN_MCU; msg.param0 = m_currentHuffmanComponent; msg.param1 = m_inputAdd; computeFor(1); // send over request to huffman module ModuleWrite(HUFF_ID, SPACE_BLOCKING, &msg); computeFor(1); ModuleRead(HUFF_ID, SPACE_BLOCKING, &msg); if (GetVerbose()) { static int roulette = 1; switch (roulette) { case 1: //[ case 5: SpacePrint("|\b"); break; case 2: case 7: SpacePrint("/\b"); break; case 3: case 6: SpacePrint("-\b"); break; case 4: case 8: SpacePrint("\\\b"); break; } if (++roulette > 8) roulette = 1; } if (GetVerbose()) SpacePrint("EXTR: decode_interleave_scan returned i:%d j:%d k:%d l:%d m:%d\n", i, j, k, l, m); if (msg.command != SCMD_ACK) { SpacePrint("EXTRACTOR ERROR : decode_interleaved has received a FAIL %d from HUFFMAN module\n", msg.param0); //this->name(), msg.param0); sc_stop(); } else { m_inputAdd = msg.param0; m_bufferValid = false; } } } } } } // (.)(.) // < // ____ // \/ \/ // when we get here, it's the end of the image! if (GetVerbose()) SpacePrint("\n"); return SUCCESS; }
chunk *computeInstruction(ANTLR3_BASE_TREE *node) { debug(DEBUG_GENERATION, "\033[22;93mCompute instruction\033[0m"); chunk *chunk, *tmp_chunk; int i, scope_tmp; static int scope = 0; switch (node->getType(node)) { case INTEGER : case STRING : case ID : case FUNC_CALL : case SUP : case INF : case SUP_EQ : case INF_EQ : case EQ : case DIFF : case AND : case OR : case MINUS : case PLUS : case DIV : case MULT : case NEG : case ASSIGNE : return computeExpr(node); case IF: return computeIf(node); case WHILE : return computeWhile(node); case FOR : return computeFor(node); case VAR_DECLARATION : return computeVarDeclaration(node); case FUNC_DECLARATION : case LET : enterScopeN(scope); scope_tmp = scope; scope = 0; switch (node->getType(node)) { case LET: chunk = computeLet(node); break; case FUNC_DECLARATION: chunk = computeFuncDeclaration(node); break; } scope = scope_tmp; scope++; leaveScope(); return chunk; default: chunk = initChunk(); // Compute all children for (i = 0; i < node->getChildCount(node); i++) { tmp_chunk = computeInstruction(node->getChild(node, i)); appendChunks(chunk, tmp_chunk); // appendChunks replace chunk->registre with tmp_chunk's one // but freeChunk free the registre of tmp_chunk // we don't want chunk->registre to be overwritten ! if (tmp_chunk != NULL) tmp_chunk->registre = -1; freeChunk(tmp_chunk); } return chunk; } }
void EXTR::thread_extract_jpeg() { UINT8 last_marker; UINT8 last_returned; bool end_of_jpeg; bool has_at_least_one_jpeg_succeeded; JMSG outmsg; JMSG inmsg; m_currentJPEGImageNo = 0; m_currentBitmapImage = 0; m_bufferValid = false; // represents the distance between each jpeg image m_jpegDist = JPEG_IMAGE_SPACER; has_at_least_one_jpeg_succeeded = false; // reset to 0 structures and data related to jpeg decompression initialize(); while(1) { end_of_jpeg = false; // // selection of jpeg preloop - sets pointer on proper image // m_currentJPEGImageNo++; if (m_currentJPEGImageNo > MAX_NB_IMAGE) { // either we stop when we finish processing the images... launch_face_detection(); sc_stop(); // ...or we loop forever (comment out the previous line) m_currentJPEGImageNo = 1; if (has_at_least_one_jpeg_succeeded == false) { SpacePrint("........................................................\n"); SpacePrint("JPEG DECODER : ALL IMAGES SET FOR DECOMPRESSION\n"); SpacePrint("HAVE FAILED -- STOPPING\n"); SpacePrint("........................................................\n"); sc_stop(); } } m_infoImageHeaderAdd = (m_currentJPEGImageNo-1) * m_jpegDist; m_inputAdd = m_infoImageHeaderAdd + INFO_IMAGE_HEADER; m_bufferValid = false; computeFor(1); if (GetVerbose()) { SpacePrint("EXTR: ********************************************** \n"); SpacePrint("EXTR: Decompressing JPEG IMAGE no %d\n", m_currentJPEGImageNo); SpacePrint("EXTR: Input Address: 0x%x\n", m_inputAdd); SpacePrint("EXTR: ********************************************** \n"); } else { SpacePrint("***JPEG %d\n",m_currentJPEGImageNo); } // // decode jpeg! // while (!end_of_jpeg) { // // JPEG information is stored in between MARKERS. Each marker tells about // the upcoming information to be read from the data // // this section scans markers and execute appropriate code according // to last marker read last_marker = read_next_marker(); computeFor(1); switch (last_marker) { // // START OF FRAME MARKER // case SOF0: case SOF1: case SOF2: has_at_least_one_jpeg_succeeded = true; m_jpeg_decoder_structure.sof = last_marker; last_returned = read_sof_marker (); if (last_returned != SUCCESS) { SpacePrint("----------------------------------------\n"); SpacePrint("EXTRACTOR: JPEG SOF DECODING ERROR no %d - skipping JPEG\n", last_returned); //, this->name(), last_returned); initialize(); end_of_jpeg = true; } // write image header into memory // WORD 1 is X width // WORD 2 is Y height DeviceWrite(JPEGRAM_ID, m_infoImageHeaderAdd, &m_jpeg_decoder_structure.number_of_samples_per_line); DeviceWrite(JPEGRAM_ID, m_infoImageHeaderAdd+0x4ul, &m_jpeg_decoder_structure.number_of_lines); if (GetVerbose()) { SpacePrint("EXTR: JPEG STARTING DECOMPRESSION OF IMAGE no%d\n", m_currentJPEGImageNo); SpacePrint("EXTR: Image size: %dx%d\n", m_jpeg_decoder_structure.number_of_samples_per_line, m_jpeg_decoder_structure.number_of_lines); } else { SpacePrint("EXTR:JPEG%d\n", m_currentJPEGImageNo); } communicate_IJPEG(SCMD_NEW_IMAGE); //} break; // // START OF HUFFMAN TABLE MARKER AT 0xffc0 // case DHT: outmsg.command = SCMD_HUFFMAN_DHT; outmsg.param0 = m_inputAdd; if (GetVerbose()) SpacePrint("EXTR: Huffman Table found; sending address to HUFF module\n"); ModuleWrite(HUFF_ID, SPACE_BLOCKING, &outmsg); computeFor(1); // wait for acknowledgement ModuleRead(HUFF_ID, SPACE_BLOCKING, &inmsg); if (GetVerbose()) SpacePrint("EXTR: Return from blocking read - waiting Huffman ACK\n"); // ack received with update with memory pointer if (inmsg.command == SCMD_ACK) { m_inputAdd = inmsg.param0; m_bufferValid = false; } else { SpacePrint("----------------------------------------\n"); SpacePrint("EXTRACTOR: JPEG DHT DECODING ERROR no %d - skipping JPEG\n", inmsg.param0); //this->name(), inmsg.param0); initialize(); end_of_jpeg = true; } break; // // START OF SCAN MARKER (DATA) AT 0xffda // case SOS: skip_marker (); // extract file information /* last_returned = read_sos_marker (); if (last_returned != SUCCESS) { SpacePrint("----------------------------------------\n"); SpacePrint("EXTRACTOR: JPEG SOS DECODING ERROR no %d - skipping JPEG\n", last_returned); //this->name(), last_returned); initialize(); end_of_jpeg = true; } */ // this flys through the MCU and keep tracks of the current type of // block being processed - for HUffman_thread. This should be // optimised since it is always 4Y+CB+CR- TODO if (GetVerbose()) SpacePrint("EXTR: Start of Scan Marker found... interleaving scan decoding can start\n"); decode_interleaved_scan (); if (GetVerbose()) { SpacePrint("EXTR: End of Scan Marker... waiting for other modules to finish\n"); } // This is the end of the file, we terminate communicate_IJPEG(SCMD_END_IMAGE); // reinitialize buffers for jpeg decompression initialize(); // we get off this loop and prepare for next image end_of_jpeg = true; // we launch execution of face detection - // which emulates somne filters to render // new images launch_face_detection(); computeFor(1); break; // // START OF QUANTIZATION TABLE MARKER AT 0xffdb // case DQT: // ack received with update with memory pointer if (read_dqt_marker() != SUCCESS) { SpacePrint("----------------------------------------\n"); SpacePrint("EXTRACTOR: IQTZ DQT DECODING ERROR no %d - skipping JPEG\n", inmsg.param0); //this->name(), inmsg.param0); initialize(); end_of_jpeg = true; } break; // // START OF IMAGE && END OF IMAGE MARKERS // case SOI: if (GetVerbose()) SpacePrint("EXTR: START OF IMAGE marker detected - reading image\n"); break; // // START OF DEFINE RESTORE INTERVAL TABLE MARKER AT 0xffdb // /* case DRI: last_returned = read_dri_marker (); // read info and skip if (last_returned != SUCCESS) { SpacePrint("----------------------------------------\n"); SpacePrint("EXTRACTOR: JPEG DRI DECODING ERROR no %d - skipping JPEG\n", last_returned); //this->name(), last_returned); initialize(); end_of_jpeg = true; } break; */ // // END OF IMAGE MARKER - nothing to do // case MARKER_EOI: // END OF IMAGE MARKER break; // // MARKERS WE SKIP // case APP0: case APP1: case APP2: case APP3: case APP4: case APP5: case APP6: case APP7: case APP8: case APP9: case APP10: case APP11: case APP12: case APP13: case APP14: case APP15: case COM: case DRI: skip_marker (); break; // // ALL OTHER MARKERS ARE UNSUPPORTED BY THIS APPLICATION // default: SpacePrint("----------------------------------------\n"); SpacePrint("EXTRACTOR: JPEG DECODING UNDEFINED MARKER %d - skipping JPEG\n", last_marker); //this->name(), last_marker); initialize(); end_of_jpeg = true; break; } // switch case }// while end of jpeg } // while 1 }
////////////////////////////////////////////////////////////////////////////// /// /// Transmission of New Image command to IQTZ - wait for acknowledgement before /// continuing /// ////////////////////////////////////////////////////////////////////////////// void EXTR::communicate_IJPEG(unsigned short command) { JMSG newimage_message; switch (command) { case SCMD_NEW_IMAGE: if (GetVerbose()) SpacePrint("EXTR: Sending NEW_IMAGE command to IQTZ - waiting for ACK\n"); newimage_message.command = SCMD_NEW_IMAGE; newimage_message.param1 = m_currentJPEGImageNo; // current image number newimage_message.param0 = m_infoImageHeaderAdd; // current image info header computeFor(1); // transmitting request for decompressing new jpeg image - // paramete is address of jpeg iomage to decompress ModuleWrite(IQTZ_ID, SPACE_BLOCKING, &newimage_message); computeFor(1); // waiting for acknowledgement with a blocking read // parameter is address of decompressed-YUV data ModuleRead(IQTZ_ID, SPACE_BLOCKING, &newimage_message); computeFor(1); if (newimage_message.command == SCMD_NEW_IMAGE_ACK) // collect address of bitmap { m_decompressedImageAddr[m_currentJPEGImageNo-1] = newimage_message.param0; //m_decompressedImageAddr[m_currentJPEGImageNo-1][VALID] = FALSE; // image data not valid while decompressing } if (GetVerbose()) SpacePrint("EXTR: Return of ACK from IQTZ imageno:%d; address:%d\n", newimage_message.param0, m_decompressedImageAddr[m_currentJPEGImageNo-1]); computeFor(1); break; case SCMD_END_IMAGE: if (GetVerbose()) SpacePrint("EXTR: END_IMAGE command to send to IQTZ\n"); newimage_message.command = SCMD_END_IMAGE; newimage_message.param1 = m_currentJPEGImageNo; computeFor(1); // transmitting end of request decompressing jpeg image - // this tells the IJPEG module it will receive no more data ModuleWrite(HUFF_ID, SPACE_BLOCKING, &newimage_message); computeFor(1); // waiting for acknowledgement with a blocking read // parameter is address of decompressed-YUV data ModuleRead(IQTZ_ID, SPACE_BLOCKING, &newimage_message); computeFor(1); if (GetVerbose()) SpacePrint("EXTR: Return of ACK for END_IMAGE command sent\n"); break; } }
inline UINT16 EXTR::read_16_bits () { UINT16 value = (read_8_bits() << 8) | read_8_bits(); computeFor(1); return (value); }
// // ////////////////////////////////////////////////////////////////////////////// /// /// /// Read Start of Frame Marker /// /// @return => UINT16 EXTR::read_sof_marker : /// /// @note => ////////////////////////////////////////////////////////////////////////////// UINT8 EXTR::read_sof_marker() { UINT8 tmp, sof; UINT16 frame_header_length; UINT8 sample_precision; UINT16 number_of_lines, number_of_samples_per_line; space_uint2 i, number_of_image_components_in_frame; space_uint4 horizontal_sampling_factor, vertical_sampling_factor; //UINT16 quantization_table_destination_selector; UINT16 horizontal_mcus, vertical_mcus; // start_of_image must be detected only once if (m_jpeg_decoder_structure.sof_detected == 1) return ERROR_SOF_ALREADY_DETECTED; m_jpeg_decoder_structure.sof_detected = 1; sof = m_jpeg_decoder_structure.sof; computeFor(1); // frame_header_length = read_16_bits (); // sample precision must be baseline = 8 sample_precision = read_8_bits (); if (sample_precision != 8) { if ((sof == SOF0) || (sample_precision != 12)) return ERROR_INVALID_SAMPLE_PRECISION; return ERROR_TWELVE_BIT_SAMPLE_PRECISION_NOT_SUPPORTED; } // read # of lines in jpeg m_jpeg_decoder_structure.number_of_lines = number_of_lines = read_16_bits (); if (number_of_lines == 0) return ERROR_ZERO_NUMBER_OF_LINES_NOT_SUPPORTED; if (number_of_lines > MAXIMUM_NUMBER_OF_LINES) return ERROR_LARGE_NUMBER_OF_LINES_NOT_SUPPORTED; // read # of sample per lines in jpeg m_jpeg_decoder_structure.number_of_samples_per_line = number_of_samples_per_line = read_16_bits (); if (number_of_samples_per_line == 0) return ERROR_ZERO_SAMPLES_PER_LINE; if (number_of_samples_per_line > MAXIMUM_NUMBER_OF_SAMPLES_PER_LINE) return ERROR_LARGE_NUMBER_OF_SAMPLES_PER_LINE_NOT_SUPPORTED; // read # components per frame m_jpeg_decoder_structure.number_of_image_components_in_frame = number_of_image_components_in_frame = read_8_bits (); //if (number_of_image_components_in_frame != 1 && number_of_image_components_in_frame != 3) if (number_of_image_components_in_frame != 3) // luc: support only 4:2:0 return ERROR_INVALID_NUMBER_OF_IMAGE_COMPONENTS_IN_FRAME; if (frame_header_length != (number_of_image_components_in_frame * 3 + 8)) return ERROR_INVALID_FRAME_HEADER_LENGTH; computeFor(5); // for each component in frame for (i=0; i<number_of_image_components_in_frame; i++) { m_jpeg_decoder_structure.component_identifier [i] = read_8_bits (); tmp = read_8_bits (); // read horizontal & vertical sampling factor m_jpeg_decoder_structure.horizontal_sampling_factor [i] = horizontal_sampling_factor = tmp >> 4; if (horizontal_sampling_factor == 0 || horizontal_sampling_factor > 4) return ERROR_INVALID_HORIZONTAL_SAMPLING_FACTOR; m_jpeg_decoder_structure.vertical_sampling_factor [i] = vertical_sampling_factor = tmp & 0xf; if (vertical_sampling_factor == 0 || vertical_sampling_factor > 4) return ERROR_INVALID_VERTICAL_SAMPLING_FACTOR; // read quantization table selector //quantization_table_destination_selector = read_8_bits (); if (read_8_bits () > 3) return ERROR_INVALID_QUANTIZATION_TABLE_DESTINATION_SELECTOR; computeFor(3); } // compute the number of effective MCU H + V horizontal_mcus = (number_of_samples_per_line + 7) >> 3; vertical_mcus = (number_of_lines + 7) >> 3; computeFor(3); // // Fill structure for 4:2:0 image format. Others are rejected // if ((m_jpeg_decoder_structure . horizontal_sampling_factor [1] == 1) && (m_jpeg_decoder_structure . vertical_sampling_factor [1] == 1) && (m_jpeg_decoder_structure . horizontal_sampling_factor [2] == 1) && (m_jpeg_decoder_structure . vertical_sampling_factor [2] == 1)) { computeFor(1); if (m_jpeg_decoder_structure . horizontal_sampling_factor [0] == 2) { horizontal_mcus = (number_of_samples_per_line + 15) >> 4; computeFor(1); if (m_jpeg_decoder_structure . vertical_sampling_factor [0] == 2) { // 4:2:0 format m_jpeg_decoder_structure.mcu_size = 384; vertical_mcus = (number_of_lines + 15) >> 4; computeFor(3); }