void CMTDHistory::SetPVector(const CSimpleVector<double>& pvector) { unsigned int curr_position = 0; CMTDBuffer* p_buff = NULL; int loc = 0; Deallocate(); while(loc < pvector.GetLength()) { if((p_buff == NULL) || (curr_position >= MaxBufferSize)) { // allocate new buffer p_buff = GetNewBuffer(MaxBufferSize); curr_position = 0; } // now set height p_buff->SetHeight(curr_position,pvector[loc++]); for(unsigned int i=0; i < GetNumberOfCoords(); i++) { // set value and width p_buff->SetValue(curr_position,i,pvector[loc++]); p_buff->SetWidth(curr_position,i,pvector[loc++]); } p_buff->IncNumberOfHills(); curr_position++; } }
void CMTDHistory::AddMTDData(CXMLElement* p_ele) { if(p_ele == NULL) { INVALID_ARGUMENT("p_ele is NULL"); } CXMLElement* p_history = p_ele->GetFirstChildElement("HISTORY"); if(p_history == NULL) { LOGIC_ERROR("unable to open HISTORY element"); } unsigned int num_of_hills; // this is total number of hills if(p_history->GetAttribute("numofhills",num_of_hills) == false) { LOGIC_ERROR("unable to get number of hills"); } if(num_of_hills == 0) return; // there are no data in received history CXMLBinData* p_hele = p_history->GetFirstChildBinData("BUFFER"); unsigned int control_num_of_hills = 0; while(p_hele != NULL) { unsigned int num_of_values; if(p_hele->GetAttribute("numofhills",num_of_values) == false) { LOGIC_ERROR("unable to get number of hills in buffer"); } control_num_of_hills += num_of_values; // now allocate buffer CMTDBuffer* p_buffer = GetNewBuffer(num_of_values); p_buffer->ReadBufferData(p_hele); p_hele = p_hele->GetNextSiblingBinData("BUFFER"); } if(control_num_of_hills != num_of_hills) { LOGIC_ERROR("mismatch in number of hills"); } }
//////////////////////////////////////////////////////////////////////////// /// /// Handle losing lock on the frame headers. /// /// This function is called to handle the data that was spuriously accumulated /// when the frame header was badly parsed. /// /// In principle this function is quite simple. We allocate a new accumulation buffer and /// use the currently accumulated data is the data source to run the elementary stream /// state machine. There is however a little extra logic to get rid of recursion. /// Specificially we change the error handling behaviour if this method is re-entered /// so that there error is reported back to the already executing copy of the method. /// /// \return Collator status code, CollatorNoError indicates success. /// CollatorStatus_t Collator_PesAudio_c::HandleMissingNextFrameHeader(void) { CollatorStatus_t Status; // // Mark the collator as having lost frame lock. // Yes! We really do want to do this before the re-entry checks. // CollatorState = SeekingSyncWord; // we really do want to do this before the re-entry checks AccumulatedFrameReady = false; // // Check for re-entry // if (AlreadyHandlingMissingNextFrameHeader) { COLLATOR_DEBUG("Re-entered the error recovery handler, initiating stack unwind\n"); return CollatorUnwindStack; } // // Check whether the sub-class wants trivial or aggressive error recovery // if (!ReprocessAccumulatedDataDuringErrorRecovery) { DiscardAccumulatedData(); return CollatorNoError; } // // Remember the original elementary stream pointers for when we return to 'normal' processing. // unsigned char *OldRemainingElementaryOrigin = RemainingElementaryOrigin; unsigned char *OldRemainingElementaryData = RemainingElementaryData; unsigned int OldRemainingElementaryLength = RemainingElementaryLength; // // Take ownership of the already accumulated data // Buffer_t ReprocessingDataBuffer = CodedFrameBuffer; unsigned char *ReprocessingData = BufferBase; unsigned int ReprocessingDataLength = AccumulatedDataSize; ReprocessingDataBuffer->SetUsedDataSize(ReprocessingDataLength); Status = ReprocessingDataBuffer->ShrinkBuffer(max(ReprocessingDataLength, 1)); if (Status != BufferNoError) { COLLATOR_ERROR("Failed to shrink the reprocessing buffer to size (%08x).\n", Status); // not fatal - we're merely wasting memory } // At the time of writing GetNewBuffer() doesn't check for leaks. This is good because otherwise // we wouldn't have transfer the ownership of the ReprocessingDataBuffer by making this call. Status = GetNewBuffer(); if (Status != CollatorNoError) { COLLATOR_ERROR("Cannot get new buffer during error recovery\n"); return CollatorError; } // // Remember that we are re-processing the previously accumulated elementary stream // AlreadyHandlingMissingNextFrameHeader = true; // // WARNING: From this point on we own the ReprocessingDataBuffer, have set the recursion avoidance // marker and may have damaged the RemainingElementaryData pointer. There should be no // short-circuit exit paths used after this point otherwise we risk avoiding the clean up // at the bottom of the method. // while (ReprocessingDataLength > 1) { // // Remove the first byte from the recovery buffer (to avoid detecting again the same start code). // ReprocessingData += 1; ReprocessingDataLength -= 1; // // Search for a start code in the reprocessing data. This allows us to throw away data that we // know will never need reprocessing which makes the recursion avoidance code more efficient. // RemainingElementaryOrigin = ReprocessingData; RemainingElementaryData = ReprocessingData; RemainingElementaryLength = ReprocessingDataLength; int CodeOffset; PotentialFrameHeaderLength = 0; // ensure no (now voided) historic data is considered by sub-class Status = FindNextSyncWord(&CodeOffset); if (Status == CodecNoError) { COLLATOR_ASSERT(CodeOffset >= 0); COLLATOR_DEBUG("Found start code during error recovery (byte %d of %d)\n", CodeOffset, ReprocessingDataLength); // We found a start code, snip off all preceding data ReprocessingData += CodeOffset; ReprocessingDataLength -= CodeOffset; } else { // We didn't find a start code, snip off everything except the last few bytes. This // final fragment may contain a partial start code so we want to pass if through the // elementary stream handler again. unsigned FinalBytes = min(ReprocessingDataLength, FrameHeaderLength - 1); COLLATOR_DEBUG("Found no start code during error recovery (processing final %d bytes of %d)\n", ReprocessingDataLength, FinalBytes); ReprocessingData += ReprocessingDataLength; ReprocessingDataLength = FinalBytes; ReprocessingData -= ReprocessingDataLength; } // // Process the elementary stream // Status = HandleElementaryStream(ReprocessingDataLength, ReprocessingData); if (CollatorNoError == Status) { COLLATOR_DEBUG("Error recovery completed, returning to normal processing\n"); // All data consumed and stored in the subsequent accumulation buffer break; // Success will propagate when we return Status } else if (CollatorUnwindStack == Status) { COLLATOR_DEBUG("Stack unwound successfully, re-trying error recovery\n"); // We found a frame header but lost lock again... let's have another go AccumulatedDataSize = 0; // make sure no accumulated data is carried round the loop continue; } else { COLLATOR_ERROR("Error handling elementary stream during error recovery\n"); break; // Failure will propagate when we return Status } } // // Free the buffer we just consumed and restore the original elementary stream pointers // RemainingElementaryOrigin = OldRemainingElementaryOrigin; RemainingElementaryData = OldRemainingElementaryData; RemainingElementaryLength = OldRemainingElementaryLength; (void) ReprocessingDataBuffer->DecrementReferenceCount(IdentifierCollator); AlreadyHandlingMissingNextFrameHeader = false; return Status; }
CMTDBuffer* CMTDHistory::AddMTDDataAsSingleBuffer(CXMLElement* p_ele) { if(p_ele == NULL) { INVALID_ARGUMENT("p_ele is NULL"); } CXMLElement* p_history = p_ele->GetFirstChildElement("HISTORY"); if(p_history == NULL) { LOGIC_ERROR("unable to open HISTORY element"); } unsigned int num_of_hills; // this is total number of hills if(p_history->GetAttribute("numofhills",num_of_hills) == false) { LOGIC_ERROR("unable to get number of hills"); } if(num_of_hills == 0) return(NULL); // there are no data in received history CMTDBuffer* p_buffer = GetNewBuffer(num_of_hills); CXMLBinData* p_hele = p_history->GetFirstChildBinData("BUFFER"); if(p_hele != NULL) { // set level and start from the first buffer unsigned int level_id; unsigned int start_id; if(p_hele->GetAttribute("level",level_id) == false) { LOGIC_ERROR("unable to get buffer level id"); } if(p_hele->GetAttribute("start",start_id) == false) { LOGIC_ERROR("unable to get buffer start id"); } p_buffer->SetLevel(level_id); p_buffer->SetStart(start_id); } unsigned int control_num_of_hills = 0; while(p_hele != NULL) { unsigned int num_of_values; if(p_hele->GetAttribute("numofhills",num_of_values) == false) { LOGIC_ERROR("unable to get number of hills in buffer"); } unsigned int history_size = num_of_values*(1 + 2*NCoords)*sizeof(double); if((history_size == 0) || (history_size != p_hele->GetLength())) { LOGIC_ERROR("inconsistent history size"); } double* src = (double*)p_hele->GetData(); if(src == NULL) { LOGIC_ERROR("data array is NULL"); } // copy data for(unsigned int i=0; i < num_of_values; i++) { p_buffer->SetHeight(control_num_of_hills+i,*src++); for(unsigned int j=0; j < NCoords; j++) { p_buffer->SetValue(control_num_of_hills+i,j,*src++); p_buffer->SetWidth(control_num_of_hills+i,j,*src++); } p_buffer->IncNumberOfHills(); } control_num_of_hills += num_of_values; p_hele = p_hele->GetNextSiblingBinData("BUFFER"); } if(control_num_of_hills != num_of_hills) { LOGIC_ERROR("mismatch in number of hills"); } return(p_buffer); }
void CMTDHistory::Load(FILE* fin) { if( fin == NULL ) { INVALID_ARGUMENT("stream is not open"); } // read MTD accumulator header ------------------ char mtd_id[4]; char ver_id[3]; int numofcoords = 0; int nr; // first line can contain either two or four records for version 0 char buffer[80]; if( fgets(buffer,80,fin) == NULL ) { RUNTIME_ERROR("unable to read the first line"); } nr = sscanf(buffer,"%3s %2s %d",mtd_id,ver_id,&numofcoords); if( nr != 3 ){ RUNTIME_ERROR("wrong header"); } mtd_id[3]='\0'; ver_id[2]='\0'; // check ID string if(strcmp(mtd_id,"MTD") != 0) { CSmallString error; error << "'MTD' magic word was not found in the first line (line: " << buffer << ")"; RUNTIME_ERROR(error); } if(strcmp(ver_id,"V3") != 0) { CSmallString error; error << "'illegal MTD history version (V3 expected) (line: " << buffer << ")"; RUNTIME_ERROR(error); } if(numofcoords <= 0) { CSmallString error; error << "number of coordinates has to be greater than zero, but " << numofcoords << " was found"; RUNTIME_ERROR(error); } SetNumberOfCoords(numofcoords); if( fin == NULL ) { INVALID_ARGUMENT("stream is not open"); } // read coordinate specification ---------------- for(unsigned int i=0; i < NCoords; i++) { unsigned int id = 0; char type[11]; char name[51]; double min_value = 0.0; double max_value = 0.0; int nbins = 0; int tr = 0; memset(type,0,11); memset(name,0,51); // read item tr = fscanf(fin,"%u %10s %lf %lf %d",&id,type,&min_value,&max_value,&nbins); if( tr != 5 ) { CSmallString error; error << "unable to read coordinate definition, id: " << i+1 << " (number of collums read: " << tr << ")"; RUNTIME_ERROR(error); } // some tests if(id != i+1) { CSmallString error; error << "coordinate id does not match, read: " << id << ", expected: " << i+1; RUNTIME_ERROR(error); } if(max_value <= min_value) { CSmallString error; error << "min value is not smaller than max value, id: " << id; RUNTIME_ERROR(error); } if(nbins <= 0) { CSmallString error; error << "number of bins has to be grater than zero, id: " << id; RUNTIME_ERROR(error); } tr = fscanf(fin,"%u %55s",&id,name); if( tr != 2 ) { CSmallString error; error << "unable to read coordinate definition, id: " << i+1 << " (number of collums read: " << tr << ")"; RUNTIME_ERROR(error); } // some tests if(id != i+1) { CSmallString error; error << "coordinate id does not match, read: " << id << ", expected: " << i+1; RUNTIME_ERROR(error); } // init coordinate SetCoordinate(i,name,type,min_value,max_value,nbins); } // now read records ----------------------------- unsigned int curr_position = 0; unsigned int position = 1; CMTDBuffer* p_buff = NULL; while(feof(fin) == 0) { int nr,level,time; if((p_buff == NULL) || (curr_position >= MaxBufferSize)) { // allocate new buffer p_buff = GetNewBuffer(MaxBufferSize); if(p_buff == NULL) { CSmallString error; error << "unable to allocate new buffer (pos: " << position << ")"; RUNTIME_ERROR(error); } curr_position = 0; } // read level and time nr = fscanf(fin,"%d %d",&level,&time); if(nr <= 0) break; // end of file if(nr != 2) { CSmallString error; error << "level and time were not successfully read (pos: " << position << ")"; RUNTIME_ERROR(error); } // now read height double height; nr = fscanf(fin,"%lf",&height); if(nr != 1) { CSmallString error; error << "unable to read height (pos: " << position << ")"; RUNTIME_ERROR(error); } p_buff->SetHeight(curr_position,height); for(unsigned int i=0; i < GetNumberOfCoords(); i++) { double value,width; nr = fscanf(fin,"%lf %lf",&value,&width); if(nr != 2) { CSmallString error; error << "unable to read value and width (pos: " << position << ")"; RUNTIME_ERROR(error); } // register value and width p_buff->SetValue(curr_position,i,value); p_buff->SetWidth(curr_position,i,width); } p_buff->IncNumberOfHills(); curr_position++; position++; } }