//////////////////////////////////////////////////////////////////////////// /// /// Pass accumulated data to the output ring and maintain class state variables. /// /// \todo If we were more clever about buffer management we wouldn't have to /// copy the frame header onto the stack. /// /// \return Collator status code, CollatorNoError indicates success. /// CollatorStatus_t Collator_PesAudio_c::InternalFrameFlush(void) { CollatorStatus_t Status; unsigned char CopiedFrameHeader[FrameHeaderLength]; // AssertComponentState("Collator_PesAudio_c::InternalFrameFlush", ComponentRunning); // COLLATOR_DEBUG(">><<\n"); // temporarily copy the following frame header (if there is one) to the stack if (AccumulatedFrameReady) { memcpy(CopiedFrameHeader, StoredFrameHeader, FrameHeaderLength); AccumulatedDataSize -= FrameHeaderLength; //Assert( BufferBase + AccumulatedDataLength == StoredFrameHeader ); } // now pass the complete frame onward Status = Collator_Pes_c::InternalFrameFlush(); if (Status != CodecNoError) return Status; if (AccumulatedFrameReady) { // put the stored frame header into the new buffer Status = AccumulateData(FrameHeaderLength, CopiedFrameHeader); if (Status != CollatorNoError) COLLATOR_DEBUG("Cannot accumulate data #8 (%d)\n", Status); AccumulatedFrameReady = false; } else { ResetCollatorStateAfterForcedFrameFlush(); } return CodecNoError; }
//////////////////////////////////////////////////////////////////////////// /// /// Accumulate data until we reach the next frame header. /// /// The function has little or no intelligence. Basically it will squirrel /// away data until Collator_PesAudio_c::GotPartialFrameHeaderBytes reaches /// Collator_PesAudio_c::FrameHeaderLength and then set /// Collator_PesAudio_c::GotPartialFrameHeader. /// /// \return Collator status code, CollatorNoError indicates success. /// CollatorStatus_t Collator_PesAudio_c::ReadFrame( void ) { CollatorStatus_t Status; unsigned int BytesToRead; // COLLATOR_DEBUG(">><<\n"); // // if the FramePayloadRemaining is -ve then we have no work to do except // record the fact that we've already accumulated part of the next frame header if (FramePayloadRemaining < 0) { GotPartialFrameHeaderBytes = -FramePayloadRemaining; CollatorState = SeekingFrameEnd; return CollatorNoError; } // BytesToRead = min( FramePayloadRemaining, RemainingElementaryLength ); if (CollatorState == ReadSubFrame) { Status = AccumulateData( BytesToRead, RemainingElementaryData ); if( Status != CollatorNoError ) COLLATOR_DEBUG( "Cannot accumulate data #4 (%d)\n", Status ); } else { Status = CollatorNoError; } if( Status == CollatorNoError ) { if (BytesToRead == FramePayloadRemaining) { GotPartialFrameHeaderBytes = 0; CollatorState = SeekingFrameEnd; } RemainingElementaryData += BytesToRead; RemainingElementaryLength -= BytesToRead; FramePayloadRemaining -= BytesToRead; } // return Status; }
void MemoryProfiler::Reset(LPCWSTR name, ArenaMemoryData * memoryData) { MemoryProfiler * memoryProfiler = memoryData->profiler; ArenaMemoryDataSummary * arenaMemoryDataSummary; bool hasItem = memoryProfiler->arenaDataMap.TryGetValue((LPWSTR)name, &arenaMemoryDataSummary); Assert(hasItem); AccumulateData(arenaMemoryDataSummary, memoryData, true); memoryData->allocatedBytes = 0; memoryData->alignmentBytes = 0; memoryData->requestBytes = 0; memoryData->requestCount = 0; memoryData->reuseBytes = 0; memoryData->reuseCount = 0; memoryData->freelistBytes = 0; memoryData->freelistCount = 0; memoryData->resetCount++; }
//////////////////////////////////////////////////////////////////////////// /// /// Accumulate data until we reach the next frame header. /// /// The function has little or no intelligence. Basically it will squirrel /// away data until Collator_PesAudio_c::GotPartialFrameHeaderBytes reaches /// Collator_PesAudio_c::FrameHeaderLength and then set /// Collator_PesAudio_c::GotPartialFrameHeader. /// /// \return Collator status code, CollatorNoError indicates success. /// CollatorStatus_t Collator_PesAudio_c::ReadFrame( void ) { CollatorStatus_t Status; unsigned int BytesToRead; // COLLATOR_DEBUG(">><<\n"); BytesToRead = min( FramePayloadRemaining, RemainingElementaryLength ); if (CollatorState == ReadSubFrame) { Status = AccumulateData( BytesToRead, RemainingElementaryData ); if( Status != CollatorNoError ) COLLATOR_DEBUG( "Cannot accumulate data #4 (%d)\n", Status ); } else { Status = CollatorNoError; } if( Status == CollatorNoError ) { if (BytesToRead == FramePayloadRemaining) { GotPartialFrameHeaderBytes = 0; CollatorState = SeekingFrameEnd; } RemainingElementaryData += BytesToRead; RemainingElementaryLength -= BytesToRead; FramePayloadRemaining -= BytesToRead; } // return Status; }
void MemoryProfiler::End(LPCWSTR name, ArenaMemoryData * memoryData) { MemoryProfiler * memoryProfiler = memoryData->profiler; ArenaMemoryDataSummary * arenaMemoryDataSummary; bool hasItem = memoryProfiler->arenaDataMap.TryGetValue((LPWSTR)name, &arenaMemoryDataSummary); Assert(hasItem); if (memoryData->next != nullptr) { memoryData->next->prev = memoryData->prev; } if (memoryData->prev != nullptr) { memoryData->prev->next = memoryData->next; } else { Assert(arenaMemoryDataSummary->data == memoryData); arenaMemoryDataSummary->data = memoryData->next; } AccumulateData(arenaMemoryDataSummary, memoryData); }
//////////////////////////////////////////////////////////////////////////// /// /// Accumulate incoming data until we have the full PES header. /// /// Strictly speaking this method handles two sub-states. In the first state /// we do not have sufficient data accumulated to determine how long the PES /// header is. In the second we still don't have a complete PES packet but /// at least we know how much more data we need. /// /// This code assumes that PES packet uses >=9 bytes PES headers rather than /// the 6 byte headers found in the program stream map, padding stream, /// private stream 2, etc. /// /// \return Collator status code, CollatorNoError indicates success. /// CollatorStatus_t Collator_PesAudio_c::ReadPartialPesHeader(void) { CollatorStatus_t Status; unsigned int PesHeaderBytes, BytesNeeded, BytesToRead; unsigned char PesPrivateData[MAX_PES_PRIVATE_DATA_LENGTH]; // if (GotPartialPesHeaderBytes < PES_INITIAL_HEADER_SIZE) { COLLATOR_DEBUG("Waiting for first part of PES header\n"); StoredPesHeader = BufferBase + AccumulatedDataSize - GotPartialPesHeaderBytes; BytesToRead = min(RemainingLength, PES_INITIAL_HEADER_SIZE - GotPartialPesHeaderBytes); Status = AccumulateData(BytesToRead, RemainingData); if (Status == CollatorNoError) { GotPartialPesHeaderBytes += BytesToRead; RemainingData += BytesToRead; RemainingLength -= BytesToRead; } else { COLLATOR_DEBUG("Cannot accumulate data #6 (%d)\n", Status); } return Status; } // // We now have accumulated sufficient data to know how long the PES header actually is! // // pass the stream_id field to the collator sub-class (might update Configuration.ExtendedHeaderLength) SetPesPrivateDataLength(StoredPesHeader[3]); PesHeaderBytes = PES_INITIAL_HEADER_SIZE + StoredPesHeader[8] + Configuration.ExtendedHeaderLength; BytesNeeded = PesHeaderBytes - GotPartialPesHeaderBytes; BytesToRead = min(RemainingLength, BytesNeeded); Status = AccumulateData(BytesToRead, RemainingData); if (Status == CollatorNoError) { GotPartialPesHeaderBytes += BytesToRead; RemainingData += BytesToRead; RemainingLength -= BytesToRead; COLLATOR_DEBUG("BytesNeeded %d; BytesToRead %d\n", BytesNeeded, BytesToRead); if (BytesNeeded == BytesToRead) { // // Woo hoo! We've got the whole header, examine it and change state // COLLATOR_DEBUG("Got entire PES header\n"); //report_dump_hex( severity_note, StoredPesHeader, PesHeaderBytes, 32, 0); Status = CollatorNoError; // strictly speaking this is a no-op but the code might change if (StoredPesHeader[0] != 0x00 || StoredPesHeader[1] != 0x00 || StoredPesHeader[2] != 0x01 || CollatorNoError != (Status = ReadPesHeader())) { COLLATOR_DEBUG("%s; seeking new PES header", (Status == CollatorNoError ? "Start code not where expected" : "Badly formed PES header")); SeekingPesHeader = true; DiscardAccumulatedData(); // we have contained the error by changing states... return CollatorNoError; } // // Placeholder: Generic stream id based PES filtering (configured by sub-class) could be inserted // here (set DiscardPesPacket to true to discard). // if (Configuration.ExtendedHeaderLength) { // store a pointer to the PES private header. it is located just above the end of the // accumulated data and is will be safely accumulated providing the private header is // smaller than the rest of the PES packet. if a very large PES private header is // encountered we will need to introduce a temporary buffer to store the header in. if (Configuration.ExtendedHeaderLength <= MAX_PES_PRIVATE_DATA_LENGTH) { memcpy(PesPrivateData, BufferBase + AccumulatedDataSize - Configuration.ExtendedHeaderLength, Configuration.ExtendedHeaderLength); } else { COLLATOR_ERROR("Implementation error: Pes Private data area too big for temporay buffer\n"); } Status = HandlePesPrivateData(PesPrivateData); if (Status != CollatorNoError) { COLLATOR_ERROR("Unhandled error when parsing PES private data\n"); return (Status); } } // discard the actual PES packet from the accumulate buffer AccumulatedDataSize -= PesHeaderBytes; // record the number of bytes we need to ignore before we reach the next start code PesPayloadRemaining = PesPayloadLength; // switch states and absorb the packet COLLATOR_DEBUG("Discovered PES packet (header %d bytes, payload %d bytes)\n", PesPacketLength - PesPayloadLength + 6, PesPayloadLength); GotPartialPesHeader = false; if (PassPesPrivateDataToElementaryStreamHandler && Configuration.ExtendedHeaderLength) { // update PesPacketLength (to ensure that GetOffsetIntoPacket gives the correct value) PesPayloadLength += Configuration.ExtendedHeaderLength; Status = HandleElementaryStream(Configuration.ExtendedHeaderLength, PesPrivateData); if (Status != CollatorNoError) { COLLATOR_ERROR("Failed not accumulate the PES private data area\n"); } } } } else { COLLATOR_DEBUG("Cannot accumulate data #7 (%d)\n", Status); } return Status; }
//////////////////////////////////////////////////////////////////////////// /// /// Scan the input until an appropriate PES start code is found. /// /// Scans any Collator_Pes_c::RemainingData searching for a PES start code. /// The configuration for this comes from Collator_Base_c::Configuration and /// is this means that only the interesting (e.g. PES audio packets) start /// codes will be detected. /// /// \return Collator status code, CollatorNoError indicates success. /// CollatorStatus_t Collator_PesAudio_c::SearchForPesHeader(void) { CollatorStatus_t Status; unsigned int CodeOffset; // // // If there are any trailing start codes handle those. // while (TrailingStartCodeBytes && RemainingLength) { if (TrailingStartCodeBytes == 3) { // We've got the 0, 0, 1 so if the code is *not* in the ignore range then we've got one unsigned char SpecificCode = RemainingData[0]; if (!inrange(SpecificCode, Configuration.IgnoreCodesRangeStart, Configuration.IgnoreCodesRangeEnd)) { COLLATOR_DEBUG("Found a trailing startcode 00, 00, 01, %x\n", SpecificCode); // Consume the specific start code RemainingData++; RemainingLength--; // Switch state (and reflect the data we are about to accumulate) SeekingPesHeader = false; GotPartialPesHeader = true; //assert( AccumulatedDataSize == 0 ); GotPartialPesHeaderBytes = 4; // There are now no trailing start code bytes TrailingStartCodeBytes = 0; // Finally, accumulate the data (by reconstructing it) unsigned char StartCode[4] = { 0, 0, 1, SpecificCode }; Status = AccumulateData(4, StartCode); if (Status != CollatorNoError) COLLATOR_DEBUG("Cannot accumulate data #5 (%d)\n", Status); return Status; } // Nope, that's not a suitable start code. COLLATOR_DEBUG("Trailing start code 00, 00, 01, %x was in the ignore range\n", SpecificCode); TrailingStartCodeBytes = 0; break; } else if (TrailingStartCodeBytes == 2) { // Got two zeros, a one gets us ready to read the code. if (RemainingData[0] == 1) { COLLATOR_DEBUG("Trailing start code looks good (found 00, 00; got 01)\n"); TrailingStartCodeBytes++; RemainingData++; RemainingLength--; continue; } // Got two zeros, another zero still leaves us with two zeros. if (RemainingData[0] == 0) { COLLATOR_DEBUG("Trailing start code looks OK (found 00, 00; got 00)\n"); RemainingData++; RemainingLength--; continue; } // Nope, that's not a suitable start code. COLLATOR_DEBUG("Trailing 00, 00 was not part of a start code\n"); TrailingStartCodeBytes = 0; break; } else if (TrailingStartCodeBytes == 1) { // Got one zero, another zero gives us two (duh). if (RemainingData[0] == 0) { COLLATOR_DEBUG("Trailing start code looks good (found 00; got 00)\n"); RemainingData++; RemainingLength--; continue; } // Nope, that's not a suitable start code. COLLATOR_DEBUG("Trailing 00 was not part of a start code\n"); TrailingStartCodeBytes = 0; break; } else { COLLATOR_ERROR("TrailingStartCodeBytes has illegal value: %d\n", TrailingStartCodeBytes); TrailingStartCodeBytes = 0; return CollatorError; } } if (RemainingLength == 0) { return CollatorNoError; } //assert(TrailingStartCodeBytes == 0); // Status = FindNextStartCode(&CodeOffset); if (Status == CollatorNoError) { COLLATOR_DEBUG("Locked to PES packet boundaries\n"); // discard any data leading up to the start code RemainingData += CodeOffset; RemainingLength -= CodeOffset; // switch state SeekingPesHeader = false; GotPartialPesHeader = true; GotPartialPesHeaderBytes = 0; } else { // examine the end of the buffer to determine if there is a (potential) trailing start code //assert( RemainingLength >= 1 ); if (RemainingData[RemainingLength - 1] < 1) { unsigned char LastBytes[3]; LastBytes[0] = (RemainingLength >= 3 ? RemainingData[RemainingLength - 3] : 0xff); LastBytes[1] = (RemainingLength >= 2 ? RemainingData[RemainingLength - 2] : 0xff); LastBytes[2] = RemainingData[RemainingLength - 1]; if (LastBytes[0] == 0 && LastBytes[1] == 0 && LastBytes[2] == 1) { TrailingStartCodeBytes = 3; } else if (LastBytes[1] == 0 && LastBytes[2] == 0) { TrailingStartCodeBytes = 2; } else if (LastBytes[2] == 0) { TrailingStartCodeBytes = 1; } } COLLATOR_DEBUG("Discarded %d bytes while searching for PES header (%d might be start code)\n", RemainingLength, TrailingStartCodeBytes); RemainingLength = 0; } // return CollatorNoError; }
//////////////////////////////////////////////////////////////////////////// /// /// Accumulate incoming data until we have the parseable frame header. /// /// Accumulate data until we have ::FrameHeaderLength /// bytes stashed away. At this point there is sufficient data accumulated /// to determine how many bytes will pass us by before the next frame header /// is expected. /// /// \return Collator status code, CollatorNoError indicates success. /// CollatorStatus_t Collator_PesAudio_c::ReadPartialFrameHeader(void) { CollatorStatus_t Status; unsigned int BytesNeeded, BytesToRead, FrameLength; CollatorState_t OldCollatorState; // COLLATOR_DEBUG(">><<\n"); // BytesNeeded = FrameHeaderLength - GotPartialFrameHeaderBytes; BytesToRead = min(RemainingElementaryLength, BytesNeeded); Status = AccumulateData(BytesToRead, RemainingElementaryData); if (Status == CollatorNoError) { GotPartialFrameHeaderBytes += BytesToRead; RemainingElementaryData += BytesToRead; RemainingElementaryLength -= BytesToRead; COLLATOR_DEBUG("BytesNeeded %d; BytesToRead %d\n", BytesNeeded, BytesToRead); if (BytesNeeded == BytesToRead) { // // Woo hoo! We've got the whole header, examine it and change state // StoredFrameHeader = BufferBase + (AccumulatedDataSize - FrameHeaderLength); COLLATOR_DEBUG("Got entire frame header packet\n"); //report_dump_hex( severity_note, StoredFrameHeader, FrameHeaderLength, 32, 0); OldCollatorState = CollatorState; Status = DecideCollatorNextStateAndGetLength(&FrameLength); if (Status != CollatorNoError) { COLLATOR_DEBUG("Badly formed frame header; seeking new frame header\n"); return HandleMissingNextFrameHeader(); } if (FrameLength == 0) { // The LPCM collator needs to do this in order to get a frame evicted before // accumulating data from the PES private data area into the frame. The only // way it can do this is by reporting a zero length frame and updating some // internal state variables. On the next call it will report a non-zero value // (i.e. we won't loop forever accumulating no data). COLLATOR_DEBUG("Sub-class reported unlikely (but potentially legitimate) frame length (%d)\n", FrameLength); } if (FrameLength > MaximumCodedFrameSize) { COLLATOR_ERROR("Sub-class reported absurd frame length (%d)\n", FrameLength); return HandleMissingNextFrameHeader(); } // this is the number of bytes we must absorb before switching state to SeekingFrameEnd. // if the value is negative then we've already started absorbing the subsequent frame // header. FramePayloadRemaining = FrameLength - FrameHeaderLength; if (CollatorState == GotCompleteFrame) { AccumulatedFrameReady = true; // // update the coded frame parameters using the parameters calculated the // last time we saw a frame header. // CodedFrameParameters->PlaybackTimeValid = NextPlaybackTimeValid; CodedFrameParameters->PlaybackTime = NextPlaybackTime; CodedFrameParameters->DecodeTimeValid = NextDecodeTimeValid; CodedFrameParameters->DecodeTime = NextDecodeTime; } else if (CollatorState == SkipSubFrame) { /* discard the accumulated frame header */ AccumulatedDataSize -= FrameHeaderLength; } if (CollatorState == GotCompleteFrame || OldCollatorState == GotSynchronized) { // // at this point we have discovered a frame header and need to attach a time to it. // we can choose between the normal stamp (the stamp of the current PES packet) or the // spanning stamp (the stamp of the previous PES packet). Basically if we have accumulated // a greater number of bytes than our current offset into the PES packet then we want to // use the spanning time. // bool WantSpanningTime = GetOffsetIntoPacket() < (int) GotPartialFrameHeaderBytes; if (WantSpanningTime && !UseSpanningTime) { COLLATOR_ERROR("Wanted to take the spanning time but this was not available."); WantSpanningTime = false; } if (WantSpanningTime) { NextPlaybackTimeValid = SpanningPlaybackTimeValid; NextPlaybackTime = SpanningPlaybackTime; SpanningPlaybackTimeValid = false; NextDecodeTimeValid = SpanningDecodeTimeValid; NextDecodeTime = SpanningDecodeTime; SpanningDecodeTimeValid = false; UseSpanningTime = false; } else { NextPlaybackTimeValid = PlaybackTimeValid; NextPlaybackTime = PlaybackTime; PlaybackTimeValid = false; NextDecodeTimeValid = DecodeTimeValid; NextDecodeTime = DecodeTime; DecodeTimeValid = false; } } // switch states and absorb the packet COLLATOR_DEBUG("Discovered frame header (frame length %d bytes)\n", FrameLength); } } else { COLLATOR_DEBUG("Cannot accumulate data #3 (%d)\n", Status); } return Status; }
//////////////////////////////////////////////////////////////////////////// /// /// Scan the input until an appropriate synchronization sequence is found. /// /// Scans any ::RemainingElementaryData searching for a /// synchronization sequence using ::FindNextSyncWord, /// a pure virtual method provided by sub-classes. /// /// \return Collator status code, CollatorNoError indicates success. /// CollatorStatus_t Collator_PesAudio_c::SearchForSyncWord(void) { CollatorStatus_t Status; int CodeOffset; // COLLATOR_DEBUG(">><<\n"); Status = FindNextSyncWord(&CodeOffset); if (Status == CollatorNoError) { COLLATOR_DEBUG("Tentatively locked to synchronization sequence (at %d)\n", CodeOffset); // switch state CollatorState = GotSynchronized; GotPartialFrameHeaderBytes = 0; if (CodeOffset >= 0) { // discard any data leading up to the start code RemainingElementaryData += CodeOffset; RemainingElementaryLength -= CodeOffset; } else { COLLATOR_DEBUG("Synchronization sequence spans multiple PES packets\n"); // accumulate any data from the old block Status = AccumulateData(-1 * CodeOffset, PotentialFrameHeader + PotentialFrameHeaderLength + CodeOffset); if (Status != CollatorNoError) COLLATOR_DEBUG("Cannot accumulate data #1 (%d)\n", Status); GotPartialFrameHeaderBytes += (-1 * CodeOffset); } PotentialFrameHeaderLength = 0; } else { // copy the last few bytes of the frame into PotentialFrameHeader (so that FindNextSyncWord // can return a negative CodeOffset if the synchronization sequence spans blocks) if (RemainingElementaryLength < FrameHeaderLength) { if (PotentialFrameHeaderLength + RemainingElementaryLength > FrameHeaderLength) { // shuffle the existing potential frame header downwards unsigned int BytesToKeep = FrameHeaderLength - RemainingElementaryLength; unsigned int ShuffleBy = PotentialFrameHeaderLength - BytesToKeep; memmove(PotentialFrameHeader, PotentialFrameHeader + ShuffleBy, BytesToKeep); PotentialFrameHeaderLength = BytesToKeep; } memcpy(PotentialFrameHeader + PotentialFrameHeaderLength, RemainingElementaryData, RemainingElementaryLength); PotentialFrameHeaderLength += RemainingElementaryLength; } else { memcpy(PotentialFrameHeader, RemainingElementaryData + RemainingElementaryLength - FrameHeaderLength, FrameHeaderLength); PotentialFrameHeaderLength = FrameHeaderLength; } COLLATOR_DEBUG("Discarded %d bytes while searching for synchronization sequence\n", RemainingElementaryLength); RemainingElementaryLength = 0; // we have contained the 'error' and don't want to propagate it Status = CollatorNoError; } // return Status; }
//////////////////////////////////////////////////////////////////////////// /// /// Determine the new state of the collator according to the incoming sub frame /// Also returns this sub frame length /// /// \return Collator status code, CollatorNoError indicates success. /// CollatorStatus_t Collator_PesAudioLpcm_c::DecideCollatorNextStateAndGetLength( unsigned int *FrameLength ) { CollatorStatus_t Status = CollatorNoError; // COLLATOR_DEBUG(">><<\n"); if ( IsFirstPacket ) { //case of very first packet, skip the packet portion before the FirstAccessUnitOffsetPointer CollatorState = SkipSubFrame; IsFirstPacket = false; // for the very first packet of dvd-audio, the stuffing bytes are not part of the PDA // since Configuration.ExtendedHeaderLength is not the same as PrivateHeaderLength, // so skip these bytes in this case *FrameLength = PesPrivateToSkip + NextParsedFrameHeader.FirstAccessUnitPointer + FirstAccessUnitOffset[StreamType] - NextParsedFrameHeader.PrivateHeaderLength; PesPrivateToSkip = 0; COLLATOR_TRACE("First packet: Skipping %d bytes\n", *FrameLength); return (Status); } // accumulate the private data area for the frame parser, // if some major parameter inside have changed... if ( AccumulatePrivateDataArea ) { // save the location of the private data area, to update it later... Status = AccumulateData( Configuration.ExtendedHeaderLength, &NewPesPrivateDataArea[0] ); if ( Status != CollatorNoError ) { return (Status); } AccumulatePrivateDataArea = false; COLLATOR_DEBUG("Accumulate PDA of length %d\n", Configuration.ExtendedHeaderLength); } if ( !IsPesPrivateDataAreaValid ) { //case of wrong packet passed to collator, skip the whole packet CollatorState = SkipSubFrame; *FrameLength = RemainingElementaryLength; } else if ( PesPrivateToSkip > 0 ) { CollatorState = SkipSubFrame; *FrameLength = min(PesPrivateToSkip, RemainingElementaryLength); PesPrivateToSkip -= *FrameLength; COLLATOR_DEBUG("Skipping %d bytes of pda\n", *FrameLength); } else if ( RemainingDataLength > 0 ) { CollatorState = ReadSubFrame; *FrameLength = min(RemainingDataLength, RemainingElementaryLength); RemainingDataLength -= *FrameLength; COLLATOR_DEBUG("Reading %d bytes (rest of frame)\n", *FrameLength); } else if ( (AccumulatedFrameNumber >= NbAudioFramesToGlob[StreamType][NextParsedFrameHeader.SamplingFrequency1]) || IsPesPrivateDataAreaNew ) { // flush the frame if we have already more than x accumulated frames // or if some pda key parameters are new CollatorState = GotCompleteFrame; COLLATOR_DEBUG("Flush after %d audio frames\n", AccumulatedFrameNumber); AccumulatedFrameNumber = 0; // prevent accumulating anything for this frame, the next thing we need to do // is accumlate the private data area for the frame parser but we can't do that // until we've cleared this frame from the accumulation buffer. *FrameLength = 0; // at next call of this function accumulate the pda AccumulatePrivateDataArea = true; // reset IsPesPrivateDataAreaNew = false; PlaybackTime += (GlobbedFramesOfNewPacket * LpcmPresentationTime[StreamType][NextParsedFrameHeader.SamplingFrequency1]); COLLATOR_DEBUG("PlaybackTime: %x\n", PlaybackTime); } else { // normal case: accumulate the audio frames CollatorState = ReadSubFrame; AccumulatedFrameNumber += 1; GlobbedFramesOfNewPacket += 1; COLLATOR_ASSERT(0 == RemainingDataLength); COLLATOR_ASSERT(0 == PesPrivateToSkip); // DVD-audio allows stuffing bytes to form part of the private data area (and these can be different // for each packet). We can't easily handle this in the PES layer since the length can't be predicted // and therefore we cannot set Configuration.ExtendedHeaderLength until it is too late. Instead // Collator_PesAudioLpcm_c::HandlePesPrivateData() records how many bytes we must skip // (PesPrivateToSkip) and leaves it to the state change logic to skip that data. This means that we // must ensure that this method will be called at the right point to skip data. We do this be making // sure we don't ever return a *FrameLength larger than the RemainingElementaryData . if ((RemainingElementaryLength < NextParsedFrameHeader.AudioFrameSize)) { RemainingDataLength = NextParsedFrameHeader.AudioFrameSize - RemainingElementaryLength; *FrameLength = RemainingElementaryLength; } else { // read the whole frame! *FrameLength = NextParsedFrameHeader.AudioFrameSize; } COLLATOR_DEBUG("Read frame of size %d (total frames in this chunk: %d)\n", *FrameLength, AccumulatedFrameNumber); } return Status; }
//{{{ Input //////////////////////////////////////////////////////////////////////////// /// /// Extract Frame length from Pes Private Data area if present. /// /// \return Collator status code, CollatorNoError indicates success. /// CollatorStatus_t Collator_PesFrame_c::Input(PlayerInputDescriptor_t *Input, unsigned int DataLength, void *Data, bool NonBlocking, unsigned int *DataLengthRemaining) { CollatorStatus_t Status = CollatorNoError; bool PrivateDataPresent; unsigned char *DataBlock = (unsigned char *)Data; unsigned char *PesHeader; unsigned char *PayloadStart; unsigned int PayloadLength; unsigned int PesLength; unsigned int Offset; COLLATOR_ASSERT(!NonBlocking); AssertComponentState("Collator_PesFrame_c::Input", ComponentRunning); InputEntry(Input, DataLength, Data, NonBlocking); Offset = 0; while (Offset < DataLength) { // Read the length of the payload PrivateDataPresent = false; PesHeader = DataBlock + Offset; PesLength = (PesHeader[4] << 8) + PesHeader[5]; if (PesLength != 0) PayloadLength = PesLength - PesHeader[8] - 3; else PayloadLength = 0; COLLATOR_DEBUG("DataLength %d, PesLength %d; PayloadLength %d, Offset %d\n", DataLength, PesLength, PayloadLength, Offset); Offset += PesLength + 6; // PES packet is PesLength + 6 bytes long Bits.SetPointer(PesHeader + 9); // Set bits pointer ready to process optional fields if ((PesHeader[7] & 0x80) == 0x80) // PTS present? //{{{ read PTS { Bits.FlushUnseen(4); PlaybackTime = (unsigned long long)(Bits.Get(3)) << 30; Bits.FlushUnseen(1); PlaybackTime |= Bits.Get(15) << 15; Bits.FlushUnseen(1); PlaybackTime |= Bits.Get(15); Bits.FlushUnseen(1); PlaybackTimeValid = true; COLLATOR_DEBUG("PTS %llu.\n", PlaybackTime); } //}}} if ((PesHeader[7] & 0xC0) == 0xC0) // DTS present? //{{{ read DTS { Bits.FlushUnseen(4); DecodeTime = (unsigned long long)(Bits.Get(3)) << 30; Bits.FlushUnseen(1); DecodeTime |= Bits.Get(15) << 15; Bits.FlushUnseen(1); DecodeTime |= Bits.Get(15); Bits.FlushUnseen(1); DecodeTimeValid = true; } //}}} else if ((PesHeader[7] & 0xC0) == 0x40) { COLLATOR_ERROR("Malformed pes header contains DTS without PTS.\n"); DiscardAccumulatedData(); // throw away previous frame as incomplete InputExit(); return CollatorError; } //}}} //{{{ walk down optional bits if ((PesHeader[7] & 0x20) == 0x20) // ESCR present Bits.FlushUnseen(48); // Size of ESCR if ((PesHeader[7] & 0x10) == 0x10) // ES Rate present Bits.FlushUnseen(24); // Size of ES Rate if ((PesHeader[7] & 0x08) == 0x08) // Trick mode control present Bits.FlushUnseen(8); // Size of Trick mode control if ((PesHeader[7] & 0x04) == 0x04) // Additional copy info present Bits.FlushUnseen(8); // Size of additional copy info if ((PesHeader[7] & 0x02) == 0x02) // PES CRC present Bits.FlushUnseen(16); // Size of previous packet CRC if ((PesHeader[7] & 0x01) == 0x01) // PES Extension flag { PrivateDataPresent = Bits.Get(1); Bits.FlushUnseen(7); // Size of Pes extension data } //}}} if (PrivateDataPresent) { if (RemainingDataLength != 0) { COLLATOR_ERROR("%s: Warning new frame indicated but %d bytes missing\n", __FUNCTION__, RemainingDataLength); DiscardAccumulatedData(); // throw away previous frame as incomplete } FrameSize = Bits.Get(8) + (Bits.Get(8) << 8) + (Bits.Get(8) << 16); RemainingDataLength = FrameSize; COLLATOR_DEBUG("%s: PlaybackTimeValid %d, PlaybackTime %llx, FrameSize %d\n", __FUNCTION__, PlaybackTimeValid, PlaybackTime, FrameSize); } if ((int)PayloadLength > RemainingDataLength) // Too much data - have some packets been lost? { if (RemainingDataLength != 0) { COLLATOR_ERROR("%s: Warning packet contains more bytes than needed %d bytes missing?\n", __FUNCTION__, RemainingDataLength); DiscardAccumulatedData(); // throw away previous frame as incomplete //RemainingDataLength = 0; //InputExit(); //return CollatorError; } RemainingDataLength = PayloadLength; // assume new packet is stand alone frame } AccumulateStartCode(PackStartCode(AccumulatedDataSize, 0x42)); PayloadStart = PesHeader + (PesLength + 6 - PayloadLength); Status = AccumulateData(PayloadLength, (unsigned char *)PayloadStart); if (Status != CollatorNoError) { InputExit(); return Status; } RemainingDataLength -= PayloadLength; if (RemainingDataLength <= 0) { Status = InternalFrameFlush(); // flush out collected frame if (Status != CollatorNoError) { InputExit(); return Status; } } COLLATOR_DEBUG("%s PrivateDataPresent %d, RemainingDataLength %d, PayloadLength %d\n", __FUNCTION__, PrivateDataPresent, RemainingDataLength, PayloadLength); } InputExit(); return CollatorNoError; }
//}}} //{{{ Input //////////////////////////////////////////////////////////////////////////// /// /// Extract Frame length from Pes Private Data area if present. /// /// \return Collator status code, CollatorNoError indicates success. /// CollatorStatus_t Collator_PesVideoMjpeg_c::Input(PlayerInputDescriptor_t *Input, unsigned int DataLength, void *Data, bool NonBlocking, unsigned int *DataLengthRemaining) { CollatorStatus_t Status = CollatorNoError; unsigned char *DataBlock = (unsigned char *)Data; unsigned char *PesHeader; unsigned int PesLength; unsigned int PayloadLength; unsigned int Offset; unsigned int CodeOffset; unsigned int Code; AssertComponentState("Collator_PacketPes_c::Input", ComponentRunning); COLLATOR_ASSERT(!NonBlocking); InputEntry(Input, DataLength, Data, NonBlocking); Offset = 0; RemainingData = (unsigned char *)Data; RemainingLength = DataLength; TerminationFlagIsSet = false; Offset = 0; while (Offset < DataLength) { // Read the length of the payload PesHeader = DataBlock + Offset; PesLength = (PesHeader[4] << 8) + PesHeader[5]; if (PesLength != 0) PayloadLength = PesLength - PesHeader[8] - 3; else PayloadLength = 0; COLLATOR_DEBUG("DataLength %d, PesLength %d; PayloadLength %d, Offset %d\n", DataLength, PesLength, PayloadLength, Offset); Offset += PesLength + 6; // PES packet is PesLength + 6 bytes long Bits.SetPointer(PesHeader + 9); // Set bits pointer ready to process optional fields if ((PesHeader[7] & 0x80) == 0x80) // PTS present? //{{{ read PTS { Bits.FlushUnseen(4); PlaybackTime = (unsigned long long)(Bits.Get(3)) << 30; Bits.FlushUnseen(1); PlaybackTime |= Bits.Get(15) << 15; Bits.FlushUnseen(1); PlaybackTime |= Bits.Get(15); Bits.FlushUnseen(1); PlaybackTimeValid = true; COLLATOR_DEBUG("PTS %llu.\n", PlaybackTime); } //}}} if ((PesHeader[7] & 0xC0) == 0xC0) // DTS present? //{{{ read DTS { Bits.FlushUnseen(4); DecodeTime = (unsigned long long)(Bits.Get(3)) << 30; Bits.FlushUnseen(1); DecodeTime |= Bits.Get(15) << 15; Bits.FlushUnseen(1); DecodeTime |= Bits.Get(15); Bits.FlushUnseen(1); DecodeTimeValid = true; } //}}} else if ((PesHeader[7] & 0xC0) == 0x40) { COLLATOR_ERROR("Malformed pes header contains DTS without PTS.\n"); DiscardAccumulatedData(); // throw away previous frame as incomplete InputExit(); return CollatorError; } RemainingData = PesHeader + (PesLength + 6 - PayloadLength); RemainingLength = PayloadLength; while (RemainingLength > 0) { Status = FindNextStartCode(&CodeOffset); if (Status != CollatorNoError) // Error indicates no start code found { Status = AccumulateData(RemainingLength, RemainingData); if (Status != CollatorNoError) DiscardAccumulatedData(); RemainingLength = 0; break; } // Got one accumulate up to and including it Status = AccumulateData(CodeOffset + 2, RemainingData); if (Status != CollatorNoError) { DiscardAccumulatedData(); break; } Code = RemainingData[CodeOffset + 1]; RemainingLength -= CodeOffset + 2; RemainingData += CodeOffset + 2; // Is it a block terminate code if ((Code == Configuration.BlockTerminateCode) && (AccumulatedDataSize > 2)) { AccumulatedDataSize -= 2; Status = InternalFrameFlush((Configuration.StreamTerminateFlushesFrame && (Code == Configuration.StreamTerminationCode))); if (Status != CollatorNoError) break; BufferBase[0] = 0xff; BufferBase[1] = Code; AccumulatedDataSize = 2; } // Accumulate the start code Status = AccumulateStartCode(PackStartCode(AccumulatedDataSize - 2, Code)); if (Status != CollatorNoError) { DiscardAccumulatedData(); InputExit(); return Status; } } } InputExit(); return CollatorNoError; }
//////////////////////////////////////////////////////////////////////////// /// /// Accumulate incoming data until we have the parseable frame header. /// /// Accumulate data until we have ::FrameHeaderLength /// bytes stashed away. At this point there is sufficient data accumulated /// to determine how many bytes will pass us by before the next frame header /// is expected. /// /// \return Collator status code, CollatorNoError indicates success. /// CollatorStatus_t Collator_PesAudio_c::ReadPartialFrameHeader( void ) { CollatorStatus_t Status; unsigned int BytesNeeded, BytesToRead, FrameLength; CollatorState_t OldCollatorState; // COLLATOR_DEBUG(">><<\n"); // BytesNeeded = FrameHeaderLength - GotPartialFrameHeaderBytes; BytesToRead = min( RemainingElementaryLength, BytesNeeded ); Status = AccumulateData( BytesToRead, RemainingElementaryData ); if( Status == CollatorNoError ) { GotPartialFrameHeaderBytes += BytesToRead; RemainingElementaryData += BytesToRead; RemainingElementaryLength -= BytesToRead; COLLATOR_DEBUG( "BytesNeeded %d; BytesToRead %d\n", BytesNeeded, BytesToRead ); if( BytesNeeded == BytesToRead ) { // // Woo hoo! We've got the whole header, examine it and change state // StoredFrameHeader = BufferBase + (AccumulatedDataSize - FrameHeaderLength); COLLATOR_DEBUG("Got entire frame header packet\n"); //report_dump_hex( severity_note, StoredFrameHeader, FrameHeaderLength, 32, 0); OldCollatorState = CollatorState; Status = DecideCollatorNextStateAndGetLength(&FrameLength); if( Status != CollatorNoError ) { COLLATOR_DEBUG( "Badly formed frame header; seeking new frame header\n" ); return HandleMissingNextFrameHeader(); } FramePayloadRemaining = FrameLength - FrameHeaderLength; if ((int)FramePayloadRemaining < 0) { if (CollatorState == GotCompleteFrame) { // accumulate the remainder of the frame before the FrameFlush method... Status = AccumulateData( FrameLength, RemainingElementaryData ); if (Status != CollatorNoError ) { COLLATOR_DEBUG( "Cannot accumulate data #2 (%d)\n", Status ); return Status; } StoredFrameHeader = BufferBase + (AccumulatedDataSize - FrameHeaderLength); RemainingElementaryData += FrameLength; RemainingElementaryLength -= FrameLength; // prepare the next call to ReadFrame by setting the correct FramePayloadRemaining Status = GetSpecificFrameLength(&FrameLength); if (Status != CollatorNoError ) { COLLATOR_DEBUG( "Cannot get the specific frame length (%d)\n", Status ); return Status; } FramePayloadRemaining = FrameLength - FrameHeaderLength; } else { // specific case: reading the header only accumulated too much data // so discard the extra data int NbBytesToDiscard = - (int)FramePayloadRemaining; int temp = NbBytesToDiscard - BytesToRead; AccumulatedDataSize -= NbBytesToDiscard; GotPartialFrameHeaderBytes = (temp > 0)?temp:0; NbBytesToDiscard = min((unsigned int) NbBytesToDiscard, BytesToRead); RemainingElementaryData -= NbBytesToDiscard; RemainingElementaryLength += NbBytesToDiscard; } } if (CollatorState == GotCompleteFrame) { AccumulatedFrameReady = true; // // update the coded frame parameters using the parameters calculated the // last time we saw a frame header. // CodedFrameParameters->PlaybackTimeValid = NextPlaybackTimeValid; CodedFrameParameters->PlaybackTime = NextPlaybackTime; CodedFrameParameters->DecodeTimeValid = NextDecodeTimeValid; CodedFrameParameters->DecodeTime = NextDecodeTime; } else if (CollatorState == SkipSubFrame) { /* discard the accumulated frame header */ AccumulatedDataSize -= FrameHeaderLength; } if (CollatorState == GotCompleteFrame || OldCollatorState == GotSynchronized) { // // at this point we have discovered a frame header and need to attach a time to it. // we can choose between the normal stamp (the stamp of the current PES packet) or the // spanning stamp (the stamp of the previous PES packet). Basically if we have accumulated // a greater number of bytes than our current offset into the PES packet then we want to // use the spanning time. // bool WantSpanningTime = GetOffsetIntoPacket() < (int) GotPartialFrameHeaderBytes; if( WantSpanningTime && !UseSpanningTime) { COLLATOR_ERROR("Wanted to take the spanning time but this was not available."); WantSpanningTime = false; } if( WantSpanningTime ) { NextPlaybackTimeValid = SpanningPlaybackTimeValid; NextPlaybackTime = SpanningPlaybackTime; SpanningPlaybackTimeValid = false; NextDecodeTimeValid = SpanningDecodeTimeValid; NextDecodeTime = SpanningDecodeTime; SpanningDecodeTimeValid = false; UseSpanningTime = false; } else { NextPlaybackTimeValid = PlaybackTimeValid; NextPlaybackTime = PlaybackTime; PlaybackTimeValid = false; NextDecodeTimeValid = DecodeTimeValid; NextDecodeTime = DecodeTime; DecodeTimeValid = false; } } // switch states and absorb the packet COLLATOR_DEBUG( "Discovered frame header (frame length %d bytes)\n", FrameLength ); } } else { COLLATOR_DEBUG( "Cannot accumulate data #3 (%d)\n", Status ); } return Status; }
CollatorStatus_t Collator_PesVideoRaw_c::Input(PlayerInputDescriptor_t *Input, unsigned int DataLength, void *Data, bool NonBlocking, unsigned int *DataLengthRemaining) { PlayerStatus_t Status = PlayerNoError; COLLATOR_ASSERT(!NonBlocking); AssertComponentState("Collator_PesRaw_c::Input", ComponentRunning); InputEntry(Input, DataLength, Data, NonBlocking); // Extract the descriptor timing information ActOnInputDescriptor(Input); COLLATOR_DEBUG("DataLength : %d\n", DataLength); if (DataRemaining == 0) //{{{ Treat the packet as a header, read metadata and build stream info { BufferStructure_t BufferStructure; class Buffer_c* Buffer; unsigned int Format; unsigned char* DataBlock; unsigned char* PesHeader = (unsigned char*)Data; unsigned int PesLength; unsigned int PesHeaderLength; unsigned int PayloadLength; COLLATOR_DEBUG("Header : %d\n", DataLength); //{{{ Read pes header // Read the length of the payload PesLength = (PesHeader[4] << 8) + PesHeader[5]; PesHeaderLength = PesHeader[8]; if (PesLength != 0) PayloadLength = PesLength - PesHeaderLength - 3; else PayloadLength = 0; COLLATOR_DEBUG("DataLength %d, PesLength %d, PesHeaderLength %d, PayloadLength %d\n", DataLength, PesLength, PesHeaderLength, PayloadLength); Bits.SetPointer(PesHeader + 9); // Set bits pointer ready to process optional fields if ((PesHeader[7] & 0x80) == 0x80) // PTS present? //{{{ read PTS { Bits.FlushUnseen(4); PlaybackTime = (unsigned long long)(Bits.Get(3)) << 30; Bits.FlushUnseen(1); PlaybackTime |= Bits.Get(15) << 15; Bits.FlushUnseen(1); PlaybackTime |= Bits.Get(15); Bits.FlushUnseen(1); PlaybackTimeValid = true; COLLATOR_DEBUG("PTS %llu.\n", PlaybackTime); } //}}} if ((PesHeader[7] & 0xC0) == 0xC0) // DTS present? //{{{ read DTS { Bits.FlushUnseen(4); DecodeTime = (unsigned long long)(Bits.Get(3)) << 30; Bits.FlushUnseen(1); DecodeTime |= Bits.Get(15) << 15; Bits.FlushUnseen(1); DecodeTime |= Bits.Get(15); Bits.FlushUnseen(1); DecodeTimeValid = true; } //}}} else if ((PesHeader[7] & 0xC0) == 0x40) { COLLATOR_ERROR("Malformed pes header contains DTS without PTS.\n"); InputExit(); return CollatorError; } //}}} DataBlock = PesHeader + 9 + PesHeaderLength; //{{{ Trace #if 0 report(severity_info, "(%d)\n%06d: ", PayloadLength, 0); for (int i = 0; i < PayloadLength; i++) { report(severity_info, "%02x ", DataBlock[i]); if (((i + 1) & 0x1f) == 0) report(severity_info, "\n%06d: ", i + 1); } report(severity_info, "\n"); #endif //}}} // Check that this is what we think it is if (strcmp((char*)DataBlock, "STMicroelectronics") != 0) { //COLLATOR_TRACE("Id : %s\n", Id); InputExit(); return FrameParserNoError; } DataBlock += strlen((char*)DataBlock) + 1; // Fill in stream info for frame parser memcpy(&StreamInfo.width, DataBlock, sizeof(unsigned int)); DataBlock += sizeof(unsigned int); memcpy(&StreamInfo.height, DataBlock, sizeof(unsigned int)); DataBlock += sizeof(unsigned int); memcpy(&StreamInfo.FrameRateNumerator, DataBlock, sizeof(unsigned long long)); DataBlock += sizeof(unsigned long long); memcpy(&StreamInfo.FrameRateDenominator, DataBlock, sizeof(unsigned long long)); DataBlock += sizeof(unsigned long long); memcpy(&Format, DataBlock, sizeof(unsigned int)); DataBlock += sizeof(unsigned int); //memcpy (&StreamInfo.interlaced, DataBlock, sizeof (unsigned int)); //DataBlock += sizeof (unsigned int); memcpy(&DataRemaining, DataBlock, sizeof(unsigned int)); DataBlock += sizeof(unsigned int); StreamInfo.interlaced = 0; StreamInfo.pixel_aspect_ratio.Numerator = 1; StreamInfo.pixel_aspect_ratio.Denominator = 1; //StreamInfo.FrameRateNumerator = 25; //StreamInfo.FrameRateDenominator = 1; StreamInfo.InputWindow.X = 0; StreamInfo.InputWindow.Y = 0; StreamInfo.InputWindow.Width = StreamInfo.width; StreamInfo.InputWindow.Height = StreamInfo.height; StreamInfo.OutputWindow = StreamInfo.InputWindow; memset(&StreamInfo.OutputWindow, 0, sizeof(StreamInfo.OutputWindow)); if (DecodeBuffer == NULL) { // Fill out the buffer structure request memset(&BufferStructure, 0x00, sizeof(BufferStructure_t)); BufferStructure.DimensionCount = 2; BufferStructure.Dimension[0] = StreamInfo.width; BufferStructure.Dimension[1] = StreamInfo.height; //{{{ determine buffer format switch (Format) { case CodeToInteger('N', 'V', '2', '2'): BufferStructure.Format = FormatVideo422_Raster; break; case CodeToInteger('R', 'G', 'B', 'P'): BufferStructure.Format = FormatVideo565_RGB; break; case CodeToInteger('R', 'G', 'B', '3'): BufferStructure.Format = FormatVideo888_RGB; break; case CodeToInteger('R', 'G', 'B', '4'): BufferStructure.Format = FormatVideo8888_ARGB; break; case CodeToInteger('Y', 'U', 'Y', 'V'): BufferStructure.Format = FormatVideo422_YUYV; break; default: COLLATOR_ERROR("Unsupported decode buffer format request %.4s\n", (char*) &Format); InputExit(); return CollatorError; } //}}} // Ask the manifestor for the buffer Status = Manifestor->GetDecodeBuffer(&BufferStructure, &Buffer); if (Status != ManifestorNoError) { COLLATOR_ERROR("Failed to get decode buffer\n"); InputExit(); return CollatorError; } StreamInfo.buffer_class = (unsigned int*)Buffer; // Get physical address of data buffer (not actually used later in pipeline) Status = Buffer->ObtainDataReference(NULL, NULL, (void**)&StreamInfo.buffer, PhysicalAddress); if (Status != BufferNoError) { COLLATOR_ERROR("Failed to get decode buffer data reference\n"); InputExit(); return CollatorError; } // Remember cached address so we can write to it Status = Buffer->ObtainDataReference(NULL, NULL, (void**)&DecodeBuffer, CachedAddress); if (Status != BufferNoError) { COLLATOR_ERROR("Failed to get decode buffer data reference\n"); InputExit(); return CollatorError; } CodedFrameBuffer->AttachBuffer(Buffer); // Attach to decode buffer (so it will be freed at the same time) Buffer->DecrementReferenceCount(); // and release ownership of the buffer to the decode buffer } COLLATOR_DEBUG("%s: ImageSize %6d\n", __FUNCTION__, DataRemaining); COLLATOR_DEBUG("%s: ImageWidth %6d\n", __FUNCTION__, StreamInfo.width); COLLATOR_DEBUG("%s: ImageHeight %6d\n", __FUNCTION__, StreamInfo.height); COLLATOR_DEBUG("%s: Format %.4s\n", __FUNCTION__, (char *) &Format); Status = CollatorNoError; } //}}} else //{{{ Assume packet is part of data - copy to decode buffer { if (DecodeBuffer == NULL) { COLLATOR_ERROR("No decode buffer available\n"); InputExit(); return CodecError; } // Transfer the packet to the next coded data frame and pass on memcpy(DecodeBuffer + DataCopied, Data, DataLength); DataRemaining -= DataLength; DataCopied += DataLength; if (DataRemaining <= 0) { Status = AccumulateData(sizeof(StreamInfo_t), (unsigned char*)&StreamInfo); DataRemaining = 0; DataCopied = 0; DecodeBuffer = NULL; if (Status != CollatorNoError) { COLLATOR_ERROR("Failed to accumulate StreamInfo\n"); InputExit(); return Status; } Status = InternalFrameFlush(); if (Status != CollatorNoError) COLLATOR_ERROR("Failed to flush frame\n"); } } //}}} InputExit(); return Status; }