//////////////////////////////////////////////////////////////////////////// /// /// 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; }
//////////////////////////////////////////////////////////////////////////// /// /// 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; }