//}}} //{{{ InjectData HavanaStatus_t HavanaDemux_c::InjectData (const unsigned char* Data, unsigned int DataLength) { Buffer_t Buffer; PlayerInputDescriptor_t* InputDescriptor; //OS_LockMutex (&InputLock); Player->GetInjectBuffer (&Buffer); Buffer->ObtainMetaDataReference (Player->MetaDataInputDescriptorType, (void**)&InputDescriptor); InputDescriptor->MuxType = MuxTypeTransportStream; InputDescriptor->DemultiplexorContext = DemuxContext; InputDescriptor->PlaybackTimeValid = false; InputDescriptor->DecodeTimeValid = false; InputDescriptor->DataSpecificFlags = 0; Buffer->RegisterDataReference (DataLength, (void*)Data); Buffer->SetUsedDataSize (DataLength); Player->InjectData (PlayerPlayback, Buffer); //OS_UnLockMutex (&InputLock); return HavanaNoError; }
//////////////////////////////////////////////////////////////////////////// /// /// 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; }