AllocatorStatus_t AllocatorSimple_c::Free(void) { int i; unsigned int LocalBufferSize; unsigned int MaxBlockSize; unsigned char *LocalOffset; OS_LockMutex(&Lock); memset(Blocks, 0x00, sizeof(Blocks)); LocalBufferSize = BufferSize; LocalOffset = NULL; MaxBlockSize = 0x4000000 - ((uintptr_t)PhysicalAddress & 0x03ffffff); HighestUsedBlockIndex = 0; for (i = 0; ((LocalBufferSize != 0) && (i < ALLOCATOR_SIMPLE_MAX_BLOCKS)); i++) { Blocks[i].InUse = true; Blocks[i].Size = min(LocalBufferSize, MaxBlockSize); Blocks[i].Base = LocalOffset; LocalBufferSize -= Blocks[i].Size; LocalOffset += Blocks[i].Size; MaxBlockSize = 0x4000000; HighestUsedBlockIndex = i; } OS_SetEvent(&EntryFreed); OS_UnLockMutex(&Lock); return AllocatorNoError; }
BufferStatus_t BufferPool_Generic_c::AbortBlockingGetBuffer( void ) { AbortGetBuffer = true; OS_SetEvent( &BufferReleaseSignal ); return BufferNoError; }
PlayerStatus_t Player_Generic_c::StreamStep(PlayerStream_t Stream) { report(severity_info, "Player_Generic_c::StreamStep - Step\n"); Stream->Step = true; OS_SetEvent(&Stream->SingleStepMayHaveHappened); return PlayerNoError; }
RingStatus_t RingGeneric_c::Insert( unsigned int Value ) { unsigned int OldNextInsert; OS_LockMutex( &Lock ); OldNextInsert = NextInsert; Storage[NextInsert] = Value; NextInsert++; if( NextInsert == Limit ) NextInsert = 0; if( NextInsert == NextExtract ) { NextInsert = OldNextInsert; OS_UnLockMutex( &Lock ); return RingTooManyEntries; } OS_UnLockMutex( &Lock ); OS_SetEvent( &Signal ); return RingNoError; }
AllocatorSimple_c::~AllocatorSimple_c(void) { BeingDeleted = true; OS_SetEvent(&EntryFreed); while (InAllocate) OS_SleepMilliSeconds(1); OS_TerminateEvent(&EntryFreed); OS_TerminateMutex(&Lock); }
RingGeneric_c::~RingGeneric_c( void ) { OS_SetEvent( &Signal ); OS_SleepMilliSeconds( 1 ); OS_TerminateMutex( &Lock ); OS_TerminateEvent( &Signal ); if( Storage != NULL ) delete Storage; }
PlayerStatus_t Player_Generic_c::CleanUpAfterStream(PlayerStream_t Stream) { PlayerStream_t *PointerToStream; unsigned int OwnerIdentifier; Buffer_t Buffer; // // Shut down the processes // OS_ResetEvent(&Stream->StartStopEvent); Stream->DiscardingUntilMarkerFramePostM = true; Stream->DiscardingUntilMarkerFrameDtoM = true; Stream->DiscardingUntilMarkerFramePtoD = true; Stream->DiscardingUntilMarkerFrameCtoP = true; Stream->Collator->DiscardAccumulatedData(); Stream->Collator->Halt(); Stream->FrameParser->Halt(); Stream->Codec->OutputPartialDecodeBuffers(); Stream->Codec->ReleaseReferenceFrame(CODEC_RELEASE_ALL); Stream->Codec->Halt(); Stream->OutputTimer->Halt(); if (Stream->Manifestor != NULL) { Stream->Manifestor->QueueNullManifestation(); Stream->Manifestor->Halt(); } Stream->Terminating = true; OS_SetEvent(&Stream->SingleStepMayHaveHappened); // Just in case they are waiting for a single step if (Stream->ProcessRunningCount != 0) { OS_WaitForEvent(&Stream->StartStopEvent, 2 * PLAYER_MAX_EVENT_WAIT); if (Stream->ProcessRunningCount != 0) report(severity_error, "Player_Generic_c::CleanUpAfterStream - Stream processes failed to terminate (%d).\n", Stream->ProcessRunningCount); } // // Strip the rings - NOTE we assume we are the first owner on any buffer // if (Stream->CollatedFrameRing != NULL) { while (Stream->CollatedFrameRing->NonEmpty()) { Stream->CollatedFrameRing->Extract((unsigned int *)(&Buffer)); Buffer->GetOwnerList(1, &OwnerIdentifier); Buffer->DecrementReferenceCount(OwnerIdentifier); } delete Stream->CollatedFrameRing; } // if (Stream->ParsedFrameRing != NULL) { while (Stream->ParsedFrameRing->NonEmpty()) { Stream->ParsedFrameRing->Extract((unsigned int *)(&Buffer)); Buffer->GetOwnerList(1, &OwnerIdentifier); Buffer->DecrementReferenceCount(OwnerIdentifier); } delete Stream->ParsedFrameRing; } // if (Stream->DecodedFrameRing != NULL) { while (Stream->DecodedFrameRing->NonEmpty()) { Stream->DecodedFrameRing->Extract((unsigned int *)(&Buffer)); Buffer->GetOwnerList(1, &OwnerIdentifier); Buffer->DecrementReferenceCount(OwnerIdentifier); } delete Stream->DecodedFrameRing; } // if (Stream->ManifestedBufferRing != NULL) { while (Stream->ManifestedBufferRing->NonEmpty()) { Stream->ManifestedBufferRing->Extract((unsigned int *)(&Buffer)); Buffer->GetOwnerList(1, &OwnerIdentifier); Buffer->DecrementReferenceCount(OwnerIdentifier); } delete Stream->ManifestedBufferRing; } // // Extract from playback list // OS_LockMutex(&Lock); for (PointerToStream = &Stream->Playback->ListOfStreams; (*PointerToStream) != NULL; PointerToStream = &((*PointerToStream)->Next)) if ((*PointerToStream) == Stream) { (*PointerToStream) = Stream->Next; break; } OS_UnLockMutex(&Lock); // // Now reset the individual classes // Stream->Collator->Reset(); Stream->FrameParser->Reset(); Stream->CodecReset = true; Stream->Codec->Reset(); Stream->OutputTimer->Reset(); Stream->Manifestor->Reset(); OS_TerminateEvent(&Stream->StartStopEvent); OS_TerminateEvent(&Stream->Drained); OS_TerminateEvent(&Stream->SwitchStreamLastOneOutOfTheCodec); OS_TerminateEvent(&Stream->SingleStepMayHaveHappened); // // If the playback no longer has any streams, we reset the // output coordinator refreshing the registration of the player. // if (Stream->Playback->ListOfStreams == NULL) { Stream->Playback->OutputCoordinator->Halt(); Stream->Playback->OutputCoordinator->Reset(); Stream->Playback->OutputCoordinator->RegisterPlayer(this, Stream->Playback, PlayerAllStreams); } // // Delete the code frame buffer pool // if (Stream->CodedFrameBufferPool != NULL) { BufferManager->DestroyPool(Stream->CodedFrameBufferPool); Stream->CodedFrameBufferPool = NULL; } if (Stream->CodedFrameMemory[CachedAddress] != NULL) { #if __KERNEL__ AllocatorClose(Stream->CodedFrameMemoryDevice); #endif Stream->CodedFrameMemory[CachedAddress] = NULL; Stream->CodedFrameMemory[UnCachedAddress] = NULL; Stream->CodedFrameMemory[PhysicalAddress] = NULL; } // // Delete the stream structure // delete Stream; // return PlayerNoError; }
// This is the coordinator task, the main beat for the tests comes from here. void TestTask0(void) { uint8_t ret,i; uint32_t ti,tj; uint16_t t; while(1) { switch(testcase) { case 0: // Task Priority assert(testvar ==0); testvar++; break; case 1: // Timer / Wait OS_WaitTicks(OSALMTest0, 3); t=10; OS_GetTicks(&ti); // get time OS_WaitTicks(OSALMTest0, t); OS_GetTicks(&tj); // get time assert(tj-ti == t); // waited time was correct break; case 2: // WaitEvent // SetEvent // wait for A, then A occurs testvar =0; OS_WaitTicks(OSALMTest0, 10); assert(testvar==1); OS_SetEvent(OSTestTskID1,1<<0); OS_WaitTicks(OSALMTest0, 2); assert(testvar==2); // A occurs, then wait for A testvar =3; OS_SetEvent(OSTestTskID1,1<<0); assert(testvar==3); OS_WaitTicks(OSALMTest0, 100); // other task wastes time... assert(testvar==4); // wait for more events, one occurs, then the other OS_SetEvent(OSTestTskID1,1<<2); assert(testvar==4); OS_WaitTicks(OSALMTest0, 10); assert(testvar==6); OS_SetEvent(OSTestTskID1,1<<1); assert(testvar==6); OS_WaitTicks(OSALMTest0, 10); assert(testvar==8); break; case 3: // MutexGet // MutexRelease break; case 4: // QueueIn // QueueOut OS_WaitTicks(OSALMTest0, 50); for (i=0;i<20;i++) // forward { ret = OS_QueueIn(&TestQ,&i); assert(ret==0); } OS_SetEvent(OSTestTskID1,1<<6); OS_WaitTicks(OSALMTest0, 50); for (i=20;i>0;i--) // backward { ret = OS_QueueIn(&TestQ,&i); assert(ret==0); } OS_SetEvent(OSTestTskID1,1<<6); OS_WaitTicks(OSALMTest0, 50); // check, if q is empty t = OS_GetQueueSpace(&TestQ); assert(t==64); for (i=0;i<64;i++) // overload the Q { ret = OS_QueueIn(&TestQ,&i); assert(ret==0); } // check, if none left t = OS_GetQueueSpace(&TestQ); assert(t==0); // now one too much: ret = OS_QueueIn(&TestQ,&i); assert(ret==1); break; case 5: // SetAlarm // WaitAlarm OS_SetAlarm(OSALMTest1,53); OS_SetAlarm(OSALMTest2,44); break; case 6: // Event with timeout OS_SetEvent(OSTestTskID1,1<<3); OS_WaitTicks(OSALMTest0, 50); // do not set the second one... break; case 7: //queue long test ret = OS_QueueOut(&TestQLong,(uint8_t*)&ti); // Q empty assert(ret == 1); for (i=0;i<10;i++) { ret = OS_QueueIn(&TestQLong,(uint8_t*)&longQtest[i]); assert (ret==0); } ret = OS_QueueIn(&TestQLong,(uint8_t*)&longQtest[9]); assert (ret==1); // Q full for (i=0;i<10;i++) { ret = OS_QueueOut(&TestQLong,(uint8_t*)&ti); assert(ret==0); assert(ti == longQtest[i]); } ret = OS_QueueOut(&TestQLong,(uint8_t*)&ti); assert(ret==1); // q empty break; case 8: // Nested Mutexes OS_MutexGet(0); WasteOfTime(1); OS_MutexGet(1); WasteOfTime(1); OS_MutexRelease(0); WasteOfTime(1); OS_MutexRelease(1); assert(1==1); // if it doesnt work, we do not come to here, break; case 9: // test of OS_GetUnusedStack (uint8_t TaskID) t=OS_GetUnusedStack(OSTestTskID0); // task0 assert(t>80 && t<150); t=OS_GetUnusedStack(OSTestTskID1); // task1 assert(t>80 && t<150); t=OS_GetUnusedStack(OSTestTskID2); // task2 assert(t>80 && t<150); t=OS_GetUnusedStack(5); // idle assert(t>2000 && t<2600); break; case 10: OS_GetTicks(&ti); OS_SetAlarm(OSALMTest0,39); OS_SetAlarm(OSALMTest3,64); OS_WaitAlarm(OSALMTest0); OS_GetTicks(&tj); assert(tj-ti == 39); OS_WaitAlarm(OSALMTest3); OS_GetTicks(&tj); assert(tj-ti == 64); break; case 11: assert(0); // just for proofing that it works! break; default: // The END while(1) { // sit here and wait for someone picking up the results out of "TestResults". 0 = OK. // "TestProcessed" shows the number of processed assertions. asm("break"); } break; } OS_WaitTicks(OSALMTest0, 500); // wait for tests to be processed... testcase++; OS_SetEvent(OSTestTskID1,1<<7); // tick other tasks in sync. OS_SetEvent(OSTestTskID2,1<<7); }//while(1) }
void TestTask2(void) { uint32_t ts,te; uint32_t i,j; uint16_t t; while(1) { switch(testcase) { case 0: // Task Priority assert(testvar ==2); testvar++; break; case 1: // Timer / Wait OS_WaitTicks(OSALMTest2, 2); t=50; OS_GetTicks(&i); // get time OS_WaitTicks(OSALMTest2, t); OS_GetTicks(&j); // get time assert(j-i == t); // waited time was correct break; case 2: // WaitEvent // SetEvent break; case 3: // MutexGet // MutexRelease // two cases: // 1:mutex is occupied by higher prio WasteOfTime(10); OS_MutexGet(0); testvar = 7; WasteOfTime(50); assert(testvar == 7); OS_MutexRelease(0); OS_SetEvent(OSTestTskID1,1<<1); // 2:mutex is occupied OS_MutexGet(0); testvar = 4; WasteOfTime(50); assert(testvar == 4); OS_MutexRelease(0); break; case 4: // QueueIn // QueueOut break; case 5: // SetAlarm // WaitAlarm OS_GetTicks(&ts); OS_WaitAlarm(OSALMTest2); OS_GetTicks(&te); assert(te-ts == 44); break; case 6: // Event with timeout break; case 7: // long queue break; default: break; } OS_WaitEvent(1<<7); }// while(1) }
ManifestorStatus_t Manifestor_Audio_c::QueueDecodeBuffer(class Buffer_c *Buffer) { ManifestorStatus_t Status; BufferStatus_t BufferStatus; unsigned int BufferIndex; //MANIFESTOR_DEBUG(">><<\n"); AssertComponentState("Manifestor_Audio_c::QueueDecodeBuffer", ComponentRunning); // // Obtain the index for the buffer and populate the parameter data. // BufferStatus = Buffer->GetIndex(&BufferIndex); if (BufferStatus != BufferNoError) { MANIFESTOR_ERROR("Unable to lookup buffer index %x.\n", BufferStatus); return ManifestorError; } StreamBuffer[BufferIndex].Buffer = Buffer; StreamBuffer[BufferIndex].EventPending = EventPending; EventPending = false; BufferStatus = Buffer->ObtainMetaDataReference(Player->MetaDataParsedFrameParametersReferenceType, (void **) &StreamBuffer[BufferIndex].FrameParameters); if (BufferStatus != BufferNoError) { MANIFESTOR_ERROR("Unable to access buffer parsed frame parameters %x.\n", BufferStatus); return ManifestorError; } BufferStatus = Buffer->ObtainMetaDataReference(Player->MetaDataParsedAudioParametersType, (void **) &StreamBuffer[BufferIndex].AudioParameters); if (BufferStatus != BufferNoError) { MANIFESTOR_ERROR("Unable to access buffer parsed audio parameters %x.\n", BufferStatus); return ManifestorError; } Buffer->DumpToRelayFS(ST_RELAY_TYPE_DECODED_AUDIO_BUFFER, ST_RELAY_SOURCE_AUDIO_MANIFESTOR + RelayfsIndex, (void *)Player); BufferStatus = Buffer->ObtainMetaDataReference(Player->MetaDataAudioOutputTimingType, (void **) &StreamBuffer[BufferIndex].AudioOutputTiming); if (BufferStatus != BufferNoError) { MANIFESTOR_ERROR("Unable to access buffer audio output timing parameters %x.\n", BufferStatus); return ManifestorError; } BufferStatus = Buffer->ObtainDataReference(NULL, NULL, (void **)(&StreamBuffer[BufferIndex].Data), UnCachedAddress); if (BufferStatus != BufferNoError) { MANIFESTOR_ERROR("Unable to obtain buffer's data reference %x.\n", BufferStatus); return ManifestorError; } StreamBuffer[BufferIndex].QueueAsCodedData = true; // // Check if there are new audio parameters (i.e. change of sample rate etc.) and note this // if (0 == memcmp(&LastSeenAudioParameters, StreamBuffer[BufferIndex].AudioParameters, sizeof(LastSeenAudioParameters))) { StreamBuffer[BufferIndex].UpdateAudioParameters = false; } else { StreamBuffer[BufferIndex].UpdateAudioParameters = true; memcpy(&LastSeenAudioParameters, StreamBuffer[BufferIndex].AudioParameters, sizeof(LastSeenAudioParameters)); } // // Allow the sub-class to have a peek at the buffer before we queue it for display // Status = QueueBuffer(BufferIndex); if (Status != ManifestorNoError) { MANIFESTOR_ERROR("Unable to queue buffer %x.\n", Status); return Status; } // // Enqueue the buffer for display within the playback thread // OS_LockMutex(&BufferQueueLock); QueuedBufferCount++; StreamBuffer[BufferIndex].NextIndex = INVALID_BUFFER_ID; // end marker if (BufferQueueHead == INVALID_BUFFER_ID) { BufferQueueHead = BufferIndex; } else { StreamBuffer[BufferQueueTail].NextIndex = BufferIndex; } BufferQueueTail = BufferIndex; OS_UnLockMutex(&BufferQueueLock); OS_SetEvent(&BufferQueueUpdated); return ManifestorNoError; }
//}}} //{{{ ~HavanaPlayer_c HavanaPlayer_c::~HavanaPlayer_c (void) { int i; class HavanaFactory_c* Factory; HAVANA_DEBUG("\n"); // remove event signal Player->SetEventSignal (PlayerAllPlaybacks, PlayerAllStreams, EventAllEvents, NULL); // Shut down event signal thread first if (EventSignalThreadId != OS_INVALID_THREAD) { EventSignalThreadRunning = false; EventSignalCallback = NULL; OS_SetEvent (&EventSignal); OS_WaitForEvent (&EventSignalThreadTerminated, OS_INFINITE); // Wait for display signal to exit EventSignalThreadId = OS_INVALID_THREAD; OS_TerminateEvent (&EventSignalThreadTerminated); OS_TerminateEvent (&EventSignal); OS_TerminateMutex (&Lock); } for (i = 0; i < MAX_PLAYBACKS; i++) { if (Playback[i] != NULL) delete Playback[i]; } for (i = 0; i < MAX_DEMUX_CONTEXTS; i++) { if (DemuxContext[i] != NULL) delete DemuxContext[i]; } for (i = 0; i < MAX_DISPLAYS; i++) { if (AudioDisplays[i] != NULL) delete AudioDisplays[i]; if (VideoDisplays[i] != NULL) delete VideoDisplays[i]; if (OtherDisplays[i] != NULL) delete OtherDisplays[i]; } if (BufferManager != NULL) delete BufferManager; if (Demultiplexor != NULL) delete Demultiplexor; while (FactoryList != NULL) { Factory = FactoryList; FactoryList = Factory->Next (); delete Factory; } DisplayDevice = NULL; EventSignalCallback = NULL; }
PlayerStatus_t Player_Generic_c::SetEventSignal( PlayerPlayback_t Playback, PlayerStream_t Stream, PlayerEventMask_t Events, OS_Event_t *Event ) { unsigned int i; PlayerStatus_t Status; unsigned int *PtrToIndex; // // Split into two paths, are we clearing a signal registration, or setting one // if( Event == NULL ) { for( i=0; i<PLAYER_MAX_EVENT_SIGNALS; i++ ) if( (ExternalEventSignals[i].Signal != NULL) && (ExternalEventSignals[i].Playback == Playback) && (ExternalEventSignals[i].Stream == Stream) && (ExternalEventSignals[i].Events == Events) ) { ExternalEventSignals[i].Signal = NULL; return PlayerNoError; } report( severity_error, "Player_Generic_c::SetEventSignal - Exact match not found for clearing event signal.\n" ); return PlayerMatchNotFound; } else // // Setting a new signal, first find a free entry and set it // Then check if there is an event record in the queue that // reuskts in us setting this event. // { OS_LockMutex( &Lock ); for( i=0; i<PLAYER_MAX_EVENT_SIGNALS; i++ ) if( ExternalEventSignals[i].Signal == NULL ) { ExternalEventSignals[i].Playback = Playback; ExternalEventSignals[i].Stream = Stream; ExternalEventSignals[i].Events = Events; ExternalEventSignals[i].Signal = Event; break; } OS_UnLockMutex( &Lock ); if( i == PLAYER_MAX_EVENT_SIGNALS ) { report( severity_error, "Player_Generic_c::SetEventSignal - Attempt to set too many signal conditions.\n" ); return PlayerToMany; } // Status = ScanEventListForMatch( Playback, Stream, Events, &PtrToIndex ); if( Status == PlayerNoError ) OS_SetEvent( Event ); } // return PlayerNoError; }
AllocatorStatus_t AllocatorSimple_c::Free(unsigned int Size, unsigned char *Block) { unsigned int i; unsigned int LowestFreeBlock; unsigned int NextHighestUsedBlockIndex; // Size = (((Size + SegmentSize - 1) / SegmentSize) * SegmentSize); LowestFreeBlock = HighestUsedBlockIndex + 1; NextHighestUsedBlockIndex = 0; OS_LockMutex(&Lock); // // Note by adding adjacent block records to the one we are trying to free, // this loop does concatenation of free blocks as well as freeing the // current block. // for (i = 0; i < (HighestUsedBlockIndex + 1); i++) { if (Blocks[i].InUse) { if (((Block + Size) == Blocks[i].Base) && !On64MBBoundary(Blocks[i].Base)) { Size += Blocks[i].Size; Blocks[i].InUse = false; } else if ((Block == (Blocks[i].Base + Blocks[i].Size)) && !On64MBBoundary(Block)) { Size += Blocks[i].Size; Block = Blocks[i].Base; Blocks[i].InUse = false; } else { NextHighestUsedBlockIndex = i; } } if (!Blocks[i].InUse) { LowestFreeBlock = min(LowestFreeBlock, i); } } // if (LowestFreeBlock == ALLOCATOR_SIMPLE_MAX_BLOCKS) { report(severity_error, "AllocatorSimple_c::Free - Unable to create a free block - too many.\n"); { report(severity_info, "\tBlocks\n"); for (i = 0; i < ALLOCATOR_SIMPLE_MAX_BLOCKS; i++) if (Blocks[i].InUse) report(severity_info, " %08x - %06x\n", Blocks[i].Base, Blocks[i].Size); } OS_SetEvent(&EntryFreed); OS_UnLockMutex(&Lock); return AllocatorError; } // Blocks[LowestFreeBlock].InUse = true; Blocks[LowestFreeBlock].Size = Size; Blocks[LowestFreeBlock].Base = Block; HighestUsedBlockIndex = max(LowestFreeBlock, NextHighestUsedBlockIndex); // OS_SetEvent(&EntryFreed); OS_UnLockMutex(&Lock); return AllocatorNoError; }
void Player_Generic_c::ProcessDecodeToManifest( PlayerStream_t Stream ) { unsigned int i; PlayerStatus_t Status; RingStatus_t RingStatus; unsigned int AccumulatedBufferTableOccupancy; PlayerBufferRecord_t *AccumulatedBufferTable; Buffer_t Buffer = NULL; Buffer_t OriginalCodedFrameBuffer; BufferType_t BufferType; PlayerControlStructure_t *ControlStructure; ParsedFrameParameters_t *ParsedFrameParameters; unsigned int LowestIndex; unsigned int LowestDisplayFrameIndex; unsigned int DesiredFrameIndex; unsigned int PossibleDecodeBuffers; unsigned int MaxDecodesOutOfOrder; PlayerSequenceNumber_t *SequenceNumberStructure; unsigned long long LastEntryTime; unsigned long long SequenceNumber; unsigned long long MinumumSequenceNumberAccumulated; unsigned long long MaximumActualSequenceNumberSeen; unsigned long long Time; unsigned int AccumulatedBeforeControlMessagesCount; unsigned int AccumulatedAfterControlMessagesCount; bool SequenceCheck; bool ProcessNow; unsigned int *Count; PlayerBufferRecord_t *Table; Buffer_t MarkerFrameBuffer; bool FirstFrame; bool DiscardBuffer; bool LastPreManifestDiscardBuffer; unsigned char SubmitInitialFrame; Buffer_t InitialFrameBuffer; // // Set parameters // AccumulatedBufferTableOccupancy = 0; AccumulatedBufferTable = Stream->AccumulatedDecodeBufferTable; LastEntryTime = OS_GetTimeInMicroSeconds(); SequenceNumber = INVALID_SEQUENCE_VALUE; Time = INVALID_TIME; AccumulatedBeforeControlMessagesCount = 0; AccumulatedAfterControlMessagesCount = 0; MinumumSequenceNumberAccumulated = 0xffffffffffffffffULL; MaximumActualSequenceNumberSeen = 0; DesiredFrameIndex = 0; FirstFrame = true; MarkerFrameBuffer = NULL; InitialFrameBuffer = NULL; LastPreManifestDiscardBuffer = false; // // Signal we have started // OS_LockMutex( &Lock ); Stream->ProcessRunningCount++; if( Stream->ProcessRunningCount == Stream->ExpectedProcessCount ) OS_SetEvent( &Stream->StartStopEvent ); OS_UnLockMutex( &Lock ); // // Main Loop // while( !Stream->Terminating ) { // // Buffer re-ordering loop // while( !Stream->Terminating ) { // // Scan the list of accumulated buffers to see if the next display frame is available // (whether because it was already accumulated, or because its display frame index has been updated) // MinumumSequenceNumberAccumulated = 0xffffffffffffffffULL; if( AccumulatedBufferTableOccupancy != 0 ) { LowestIndex = INVALID_INDEX; LowestDisplayFrameIndex = INVALID_INDEX; for( i=0; i<Stream->NumberOfDecodeBuffers; i++ ) if( AccumulatedBufferTable[i].Buffer != NULL ) { MinumumSequenceNumberAccumulated = min(MinumumSequenceNumberAccumulated, AccumulatedBufferTable[i].SequenceNumber); if( (AccumulatedBufferTable[i].ParsedFrameParameters->DisplayFrameIndex != INVALID_INDEX) && ((LowestIndex == INVALID_INDEX) || (AccumulatedBufferTable[i].ParsedFrameParameters->DisplayFrameIndex < LowestDisplayFrameIndex)) ) { LowestDisplayFrameIndex = AccumulatedBufferTable[i].ParsedFrameParameters->DisplayFrameIndex; LowestIndex = i; } } Stream->Manifestor->GetDecodeBufferCount( &PossibleDecodeBuffers ); MaxDecodesOutOfOrder = (Stream->Playback->Direction == PlayForward) ? (PossibleDecodeBuffers >> 1) : (3 * PossibleDecodeBuffers)/4; MaxDecodesOutOfOrder = min( (PossibleDecodeBuffers - PLAYER_MINIMUM_NUMBER_OF_WORKING_DECODE_BUFFERS), MaxDecodesOutOfOrder ); if( Stream->Playback->Direction == PlayForward ) MaxDecodesOutOfOrder = min( PLAYER_LIMIT_ON_OUT_OF_ORDER_DECODES, MaxDecodesOutOfOrder ); if( (LowestIndex != INVALID_INDEX) && ( (LowestDisplayFrameIndex == DesiredFrameIndex) || (AccumulatedBufferTableOccupancy >= MaxDecodesOutOfOrder) || (AccumulatedBufferTable[LowestIndex].ParsedFrameParameters->CollapseHolesInDisplayIndices) || (MarkerFrameBuffer != NULL) ) ) { Buffer = AccumulatedBufferTable[LowestIndex].Buffer; ParsedFrameParameters = AccumulatedBufferTable[LowestIndex].ParsedFrameParameters; SequenceNumber = AccumulatedBufferTable[LowestIndex].SequenceNumber; BufferType = Stream->DecodeBufferType; AccumulatedBufferTable[LowestIndex].Buffer = NULL; AccumulatedBufferTable[LowestIndex].ParsedFrameParameters = NULL; AccumulatedBufferTableOccupancy--; break; } } // // Skip any frame indices that were unused // while( CheckForNonDecodedFrame( Stream, DesiredFrameIndex ) ) DesiredFrameIndex++; // // If we get here with a marker frame, then we have emptied our accumulated list // if( MarkerFrameBuffer != NULL ) { SequenceNumber = SequenceNumberStructure->Value; MaximumActualSequenceNumberSeen = max(SequenceNumber, MaximumActualSequenceNumberSeen); ProcessAccumulatedControlMessages( Stream, &AccumulatedBeforeControlMessagesCount, PLAYER_MAX_DTOM_MESSAGES, Stream->AccumulatedBeforeDtoMControlMessages, SequenceNumber, Time ); ProcessAccumulatedControlMessages( Stream, &AccumulatedAfterControlMessagesCount, PLAYER_MAX_DTOM_MESSAGES, Stream->AccumulatedAfterDtoMControlMessages, SequenceNumber, Time ); Stream->ManifestedBufferRing->Insert( (unsigned int)MarkerFrameBuffer ); // Pass on the marker MarkerFrameBuffer = NULL; Stream->DiscardingUntilMarkerFrameDtoM = false; continue; } // // Get a new buffer (continue will still perform the scan) // RingStatus = Stream->DecodedFrameRing->Extract( (unsigned int *)(&Buffer), PLAYER_NEXT_FRAME_EVENT_WAIT ); if( (RingStatus == RingNothingToGet) || (Buffer == NULL) || Stream->Terminating ) continue; Buffer->TransferOwnership( IdentifierProcessDecodeToManifest ); Buffer->GetType( &BufferType ); if( BufferType != Stream->DecodeBufferType ) break; // // Obtain a sequence number from the buffer // Status = Buffer->ObtainAttachedBufferReference( Stream->CodedFrameBufferType, &OriginalCodedFrameBuffer ); if( Status != PlayerNoError ) { report( severity_error, "Player_Generic_c::ProcessDecodeToManifest - Unable to obtain the the original coded frame buffer - Implementation error\n" ); Buffer->DecrementReferenceCount( IdentifierProcessDecodeToManifest ); continue; } Status = OriginalCodedFrameBuffer->ObtainMetaDataReference( MetaDataSequenceNumberType, (void **)(&SequenceNumberStructure) ); if( Status != PlayerNoError ) { report( severity_error, "Player_Generic_c::ProcessDecodeToManifest - Unable to obtain the meta data \"SequenceNumber\" - Implementation error\n" ); Buffer->DecrementReferenceCount( IdentifierProcessDecodeToManifest ); continue; } SequenceNumberStructure->TimeEntryInProcess2 = OS_GetTimeInMicroSeconds(); SequenceNumberStructure->DeltaEntryInProcess2 = SequenceNumberStructure->TimeEntryInProcess2 - LastEntryTime; LastEntryTime = SequenceNumberStructure->TimeEntryInProcess2; SequenceNumber = SequenceNumberStructure->Value; // // Check, is this a marker frame // if( SequenceNumberStructure->MarkerFrame ) { MarkerFrameBuffer = Buffer; continue; // allow us to empty the accumulated buffer list } // // If this is the first seen decode buffer do we wish to offer it up as an initial frame // if( FirstFrame ) { FirstFrame = false; SubmitInitialFrame = PolicyValue( Stream->Playback, Stream, PolicyManifestFirstFrameEarly ); if( SubmitInitialFrame == PolicyValueApply ) { Status = Stream->Manifestor->InitialFrame( Buffer ); if( Status != ManifestorNoError ) report( severity_error, "Player_Generic_c::ProcessDecodeToManifest - Failed to apply InitialFrame action.\n" ); if( InitialFrameBuffer != NULL ) Stream->Codec->ReleaseDecodeBuffer( InitialFrameBuffer ); InitialFrameBuffer = Buffer; InitialFrameBuffer->IncrementReferenceCount(); } } // // Do we want to insert this in the table // Status = Buffer->ObtainMetaDataReference( MetaDataParsedFrameParametersReferenceType, (void **)(&ParsedFrameParameters) ); if( Status != PlayerNoError ) { report( severity_error, "Player_Generic_c::ProcessDecodeToManifest - Unable to obtain the meta data \"ParsedFrameParametersReference\" - Implementation error\n" ); Buffer->DecrementReferenceCount( IdentifierProcessDecodeToManifest ); continue; } #if 0 { unsigned int A, B; Stream->DecodeBufferPool->GetPoolUsage( &A, &B, NULL, NULL, NULL ); report( severity_info, "Got(%d) %3d (R = %d, K = %d) %d, %016llx - %d %d/%d\n", Stream->StreamType, ParsedFrameParameters->DecodeFrameIndex, ParsedFrameParameters->ReferenceFrame, ParsedFrameParameters->KeyFrame, ParsedFrameParameters->DisplayFrameIndex, ParsedFrameParameters->NormalizedPlaybackTime, AccumulatedBufferTableOccupancy, B, A ); } #endif if( ParsedFrameParameters->DisplayFrameIndex <= DesiredFrameIndex ) break; for( i=0; i<Stream->NumberOfDecodeBuffers; i++ ) if( AccumulatedBufferTable[i].Buffer == NULL ) { AccumulatedBufferTable[i].Buffer = Buffer; AccumulatedBufferTable[i].SequenceNumber = SequenceNumber; AccumulatedBufferTable[i].ParsedFrameParameters = ParsedFrameParameters; AccumulatedBufferTableOccupancy++; break; } if( i >= Stream->NumberOfDecodeBuffers ) { report( severity_error, "Player_Generic_c::ProcessDecodeToManifest - Unable to insert buffer in table - Implementation error.\n" ); break; // Assume it is immediate, as an implementation error this is pretty nasty } } if( Stream->Terminating ) continue; // -------------------------------------------------------------------------------------------- // We now have a buffer after frame re-ordering // // First calculate the sequence number that applies to this frame // this calculation may appear wierd, the idea is this, assume you // have a video stream IPBB, sequence numbers 0 1 2 3, frame reordering // will yield sequence numbers 0 2 3 1 IE any command to be executed at // the end of the stream will appear 1 frame early, the calculations // below will re-wossname the sequence numbers to 0 1 1 3 causing the // signal to occur at the correct point. // // // Deal with a coded frame buffer // if( BufferType == Stream->DecodeBufferType ) { // // Report any re-ordering problems // if( ParsedFrameParameters->CollapseHolesInDisplayIndices && (ParsedFrameParameters->DisplayFrameIndex > DesiredFrameIndex) ) DesiredFrameIndex = ParsedFrameParameters->DisplayFrameIndex; if( ParsedFrameParameters->DisplayFrameIndex > DesiredFrameIndex ) report( severity_error, "Player_Generic_c::ProcessDecodeToManifest - Hole in display frame indices (Got %d Expected %d).\n", ParsedFrameParameters->DisplayFrameIndex, DesiredFrameIndex ); if( ParsedFrameParameters->DisplayFrameIndex < DesiredFrameIndex ) report( severity_error, "Player_Generic_c::ProcessDecodeToManifest - Frame re-ordering failure (Got %d Expected %d) - Implementation error.\n", ParsedFrameParameters->DisplayFrameIndex, DesiredFrameIndex ); // // First calculate the sequence number that applies to this frame // this calculation may appear wierd, the idea is this, assume you // have a video stream IPBB, sequence numbers 0 1 2 3, frame reordering // will yield sequence numbers 0 2 3 1 IE any command to be executed at // the end of the stream will appear 1 frame early, the calculations // below will re-wossname the sequence numbers to 0 1 1 3 causing the // signal to occur at the correct point. // MaximumActualSequenceNumberSeen = max(SequenceNumber, MaximumActualSequenceNumberSeen); SequenceNumber = min(MaximumActualSequenceNumberSeen, MinumumSequenceNumberAccumulated ); Time = ParsedFrameParameters->NativePlaybackTime; // // Process any outstanding control messages to be applied before this buffer // ProcessAccumulatedControlMessages( Stream, &AccumulatedBeforeControlMessagesCount, PLAYER_MAX_DTOM_MESSAGES, Stream->AccumulatedBeforeDtoMControlMessages, SequenceNumber, Time ); // // If we are paused, then we loop waiting for something to happen // if( Stream->Playback->Speed == 0 ) { while( (Stream->Playback->Speed == 0) && !Stream->Step && !Stream->Terminating && !Stream->DiscardingUntilMarkerFrameDtoM ) { OS_WaitForEvent( &Stream->SingleStepMayHaveHappened, PLAYER_NEXT_FRAME_EVENT_WAIT ); OS_ResetEvent( &Stream->SingleStepMayHaveHappened ); } Stream->Step = false; } // // If we are not discarding everything, then procede to process the buffer // DiscardBuffer = Stream->DiscardingUntilMarkerFrameDtoM; // // Handle output timing functions, await entry into the decode window, // Then check for frame drop (whether due to trick mode, or because // we are running late). // NOTE1 Indicating we are not before decode, means // reference frames can be dropped, we will simply not display them // NOTE2 We may block in these functions, so it is important to // recheck flags // if( !DiscardBuffer ) { Status = Stream->OutputTimer->TestForFrameDrop( Buffer, OutputTimerBeforeOutputTiming ); if( Status == OutputTimerNoError ) { // // Note we loop here if we are engaged in re-timing the decoded frames // while( !Stream->Terminating && Stream->ReTimeQueuedFrames ) OS_SleepMilliSeconds( PLAYER_RETIMING_WAIT ); Stream->OutputTimer->GenerateFrameTiming( Buffer ); Status = Stream->OutputTimer->TestForFrameDrop( Buffer, OutputTimerBeforeManifestation ); } if( Stream->DiscardingUntilMarkerFrameDtoM || Stream->Terminating || (Status != OutputTimerNoError) ) DiscardBuffer = true; if( (DiscardBuffer != LastPreManifestDiscardBuffer) && (Status == OutputTimerUntimedFrame) ) { report( severity_error, "Discarding untimed frames.\n" ); } LastPreManifestDiscardBuffer = DiscardBuffer; #if 0 // Nick debug data if( Status != OutputTimerNoError ) report( severity_info, "Timer Discard(%d) %3d (before Manifest) %08x\n", Stream->StreamType, ParsedFrameParameters->DecodeFrameIndex, Status ); #endif } // // Pass the buffer to the manifestor for manifestation // we do not release our hold on this buffer, buffers passed // to the manifestor always re-appear on its output ring. // NOTE calculate next desired frame index before we // give away the buffer, because ParsedFrameParameters // can become invalid after either of the calls below. // DesiredFrameIndex = ParsedFrameParameters->DisplayFrameIndex + 1; if( !DiscardBuffer ) { SequenceNumberStructure->TimePassToManifestor = OS_GetTimeInMicroSeconds(); #if 0 { static unsigned long long LastOutputTime = 0; static unsigned long long LastOutputTime1 = 0; VideoOutputTiming_t *OutputTiming; unsigned int C0,C1,C2,C3; Buffer->ObtainMetaDataReference( MetaDataVideoOutputTimingType, (void **)&OutputTiming ); Stream->CodedFrameBufferPool->GetPoolUsage( &C0, &C1, NULL, NULL, NULL ); Stream->DecodeBufferPool->GetPoolUsage( &C2, &C3, NULL, NULL, NULL ); report( severity_info, "Ord %3d (R = %d, K = %d) %d, %6lld %6lld %6lld %6lld (%d/%d %d/%d) (%d %d) %6lld %6lld\n", ParsedFrameParameters->DecodeFrameIndex, ParsedFrameParameters->ReferenceFrame, ParsedFrameParameters->KeyFrame, ParsedFrameParameters->DisplayFrameIndex, OutputTiming->SystemPlaybackTime - SequenceNumberStructure->TimePassToManifestor, SequenceNumberStructure->TimePassToManifestor - SequenceNumberStructure->TimeEntryInProcess2, SequenceNumberStructure->TimePassToManifestor - SequenceNumberStructure->TimeEntryInProcess1, SequenceNumberStructure->TimePassToManifestor - SequenceNumberStructure->TimeEntryInProcess0, C0, C1, C2, C3, Stream->FramesToManifestorCount, Stream->FramesFromManifestorCount, OutputTiming->SystemPlaybackTime - LastOutputTime, ParsedFrameParameters->NormalizedPlaybackTime - LastOutputTime1 ); //Buffer->TransferOwnership( IdentifierProcessDecodeToManifest, IdentifierManifestor ); //if( (OutputTiming->SystemPlaybackTime - SequenceNumberStructure->TimePassToManifestor) > 0xffffffffULL ) // Stream->DecodeBufferPool->Dump( DumpAll ); LastOutputTime = OutputTiming->SystemPlaybackTime; LastOutputTime1 = ParsedFrameParameters->NormalizedPlaybackTime; } if( Stream->FramesToManifestorCount >= 55 ) { OS_SleepMilliSeconds( 1000 ); report( severity_info, "Ord(%d) %3d (R = %d, K = %d) %d, %016llx %016llx\n", Stream->StreamType, ParsedFrameParameters->DecodeFrameIndex, ParsedFrameParameters->ReferenceFrame, ParsedFrameParameters->KeyFrame, ParsedFrameParameters->DisplayFrameIndex, ParsedFrameParameters->NormalizedPlaybackTime, ParsedFrameParameters->NativePlaybackTime ); OS_SleepMilliSeconds( 4000 ); } #endif Stream->FramesToManifestorCount++; Status = Stream->Manifestor->QueueDecodeBuffer( Buffer ); if( Status != ManifestorNoError ) DiscardBuffer = true; if( InitialFrameBuffer != NULL ) { Stream->Codec->ReleaseDecodeBuffer( InitialFrameBuffer ); InitialFrameBuffer = NULL; } } if( DiscardBuffer ) { Stream->Codec->ReleaseDecodeBuffer( Buffer ); if( Stream->Playback->Speed == 0 ) Stream->Step = true; } // // Process any outstanding control messages to be applied after this buffer // ProcessAccumulatedControlMessages( Stream, &AccumulatedAfterControlMessagesCount, PLAYER_MAX_DTOM_MESSAGES, Stream->AccumulatedAfterDtoMControlMessages, SequenceNumber, Time ); } // // Deal with a player control structure // else if( BufferType == BufferPlayerControlStructureType ) { Buffer->ObtainDataReference( NULL, NULL, (void **)(&ControlStructure) ); ProcessNow = (ControlStructure->SequenceType == SequenceTypeImmediate); if( !ProcessNow ) { SequenceCheck = (ControlStructure->SequenceType == SequenceTypeBeforeSequenceNumber) || (ControlStructure->SequenceType == SequenceTypeAfterSequenceNumber); ProcessNow = SequenceCheck ? ((SequenceNumber != INVALID_SEQUENCE_VALUE) && (ControlStructure->SequenceValue <= MaximumActualSequenceNumberSeen)) : ((Time != INVALID_SEQUENCE_VALUE) && (ControlStructure->SequenceValue <= Time)); } if( ProcessNow ) ProcessControlMessage( Stream, Buffer, ControlStructure ); else { if( (ControlStructure->SequenceType == SequenceTypeBeforeSequenceNumber) || (ControlStructure->SequenceType == SequenceTypeBeforePlaybackTime) ) { Count = &AccumulatedBeforeControlMessagesCount; Table = Stream->AccumulatedBeforeDtoMControlMessages; } else { Count = &AccumulatedAfterControlMessagesCount; Table = Stream->AccumulatedAfterDtoMControlMessages; } AccumulateControlMessage( Buffer, ControlStructure, Count, PLAYER_MAX_DTOM_MESSAGES, Table ); } } else { report( severity_error, "Player_Generic_c::ProcessDecodeToManifest - Unknown buffer type received - Implementation error.\n" ); Buffer->DecrementReferenceCount(); } }
PlayerStatus_t Player_Generic_c::InternalDrainStream( PlayerStream_t Stream, bool NonBlocking, bool SignalEvent, void *EventUserData, PlayerPolicy_t PlayoutPolicy, bool ParseAllFrames) { PlayerStatus_t Status; unsigned char PlayoutPolicyValue; PlayerEventRecord_t Event; Buffer_t MarkerFrame; CodedFrameParameters_t *CodedFrameParameters; PlayerSequenceNumber_t *SequenceNumberStructure; unsigned long long PlayoutTime; unsigned long long Delay; // // Read the appropriate policy // PlayoutPolicyValue = PolicyValue(Stream->Playback, Stream, PlayoutPolicy); // // If we are to discard data in the drain, then perform the flushing // if (PlayoutPolicyValue == PolicyValueDiscard) { Stream->DiscardingUntilMarkerFramePostM = true; Stream->DiscardingUntilMarkerFrameDtoM = true; Stream->DiscardingUntilMarkerFramePtoD = true; Stream->DiscardingUntilMarkerFrameCtoP = !ParseAllFrames; Stream->ReTimeQueuedFrames = false; OS_SetEvent(&Stream->SingleStepMayHaveHappened); Status = Stream->Collator->InputJump(true, false); Status = Stream->Codec->DiscardQueuedDecodes(); Status = Stream->Codec->OutputPartialDecodeBuffers(); Status = Stream->Manifestor->ReleaseQueuedDecodeBuffers(); } // // Just in case there is another marker frame doing the rounds // if (Stream->MarkerInCodedFrameIndex != INVALID_INDEX) { Status = WaitForDrainCompletion(Stream, (PlayoutPolicyValue == PolicyValueDiscard)); if (Status != PlayerNoError) { report(severity_error, "Player_Generic_c::InternalDrainStream - Unable to launch a marker frame - Implementation error.\n"); MarkerFrame->DecrementReferenceCount(); return PlayerImplementationError; } } // // Insert a marker frame into the processing ring // Status = Stream->CodedFrameBufferPool->GetBuffer(&MarkerFrame, IdentifierDrain, 0); if (Status != BufferNoError) { report(severity_error, "Player_Generic_c::InternalDrainStream - Unable to obtain a marker frame.\n"); return Status; } // Status = MarkerFrame->ObtainMetaDataReference(MetaDataCodedFrameParametersType, (void **)(&CodedFrameParameters)); if (Status != BufferNoError) { report(severity_error, "Player_Generic_c::InternalDrainStream - Unable to obtain the meta data coded frame parameters.\n"); MarkerFrame->DecrementReferenceCount(); return Status; } memset(CodedFrameParameters, 0x00, sizeof(CodedFrameParameters_t)); // Status = MarkerFrame->ObtainMetaDataReference(MetaDataSequenceNumberType, (void **)(&SequenceNumberStructure)); if (Status != PlayerNoError) { report(severity_error, "Player_Generic_c::InternalDrainStream - Unable to obtain the meta data \"SequenceNumber\" - Implementation error\n"); MarkerFrame->DecrementReferenceCount(); return Status; } Stream->DrainSequenceNumber = Stream->NextBufferSequenceNumber + PLAYER_MAX_RING_SIZE; SequenceNumberStructure->MarkerFrame = true; SequenceNumberStructure->Value = Stream->DrainSequenceNumber; // // Reset the event indicating draining and insert the marker into the flow // OS_ResetEvent(&Stream->Drained); MarkerFrame->GetIndex(&Stream->MarkerInCodedFrameIndex); Stream->CollatedFrameRing->Insert((unsigned int)MarkerFrame); // // Issue an in sequence synchronization reset // Status = CallInSequence(Stream, SequenceTypeBeforeSequenceNumber, Stream->DrainSequenceNumber, OutputTimerFnResetTimeMapping, PlaybackContext); if (Status != PlayerNoError) { report(severity_error, "Player_Generic_c::InternalDrainStream - Failed to issue call to reset synchronization.\n"); return Status; } // // Do we want to raise a signal on drain completion // if (SignalEvent) { Event.Code = EventStreamDrained; Event.Playback = Stream->Playback; Event.Stream = Stream; Event.PlaybackTime = TIME_NOT_APPLICABLE; Event.UserData = EventUserData; Status = CallInSequence(Stream, SequenceTypeBeforeSequenceNumber, Stream->DrainSequenceNumber, ManifestorFnQueueEventSignal, &Event); if (Status != PlayerNoError) { report(severity_error, "Player_Generic_c::InternalDrainStream - Failed to issue call to signal drain completion.\n"); return Status; } } // // Queue the setting of the internal event, when the stream is drained // this allows us to commence multiple stream drains in a playback shutdown // and then block on completion of them all. // Status = CallInSequence(Stream, SequenceTypeAfterSequenceNumber, Stream->DrainSequenceNumber, OSFnSetEventOnPostManifestation, &Stream->Drained); if (Status != PlayerNoError) { report(severity_error, "Player_Generic_c::InternalDrainStream - Failed to request OS_SetEvent.\n"); return Status; } // // Are we a blocking/non-blocking call // if (!NonBlocking) { Status = WaitForDrainCompletion(Stream, (PlayoutPolicyValue == PolicyValueDiscard)); if (Status != PlayerNoError) { report(severity_error, "Player_Generic_c::InternalDrainStream - Failed to drain within allowed time (%d %d %d %d).\n", Stream->DiscardingUntilMarkerFrameCtoP, Stream->DiscardingUntilMarkerFramePtoD, Stream->DiscardingUntilMarkerFrameDtoM, Stream->DiscardingUntilMarkerFramePostM); return PlayerTimedOut; } // // If this was a playout drain, then check when the last // queued frame will complete and wait for it to do so. // if (PlayoutPolicyValue == PolicyValuePlayout) { // // The last frame will playout when the next frame could be displayed // Status = Stream->Manifestor->GetNextQueuedManifestationTime(&PlayoutTime); Delay = (PlayoutTime - OS_GetTimeInMicroSeconds()) / 1000; if ((Status == ManifestorNoError) && inrange(Delay, 1, (unsigned long long)Abs(RoundedLongLongIntegerPart(PLAYER_MAX_PLAYOUT_TIME / Stream->Playback->Speed)))) { report(severity_info, "Player_Generic_c::InternalDrainStream - Delay to manifest last frame is %lldms\n", Delay); OS_SleepMilliSeconds((unsigned int)Delay); } } } // return PlayerNoError; }
PlayerStatus_t Player_Generic_c::SetPlaybackSpeed( PlayerPlayback_t Playback, Rational_t Speed, PlayDirection_t Direction) { PlayerStatus_t Status; unsigned long long Now; unsigned long long NormalizedTimeAtStartOfDrain; bool ReTimeQueuedFrames; PlayerStream_t Stream; unsigned char Policy; // // Ensure that the playback interval is not cluttered by reversal clamps // Playback->PresentationIntervalReversalLimitStartNormalizedTime = INVALID_TIME; Playback->PresentationIntervalReversalLimitEndNormalizedTime = INVALID_TIME; // // Are we performing a direction flip // if (Playback->Direction != Direction) { // // Find the current playback time // Now = OS_GetTimeInMicroSeconds(); Status = Playback->OutputCoordinator->TranslateSystemTimeToPlayback(PlaybackContext, Now, &NormalizedTimeAtStartOfDrain); if (Status != PlayerNoError) { report(severity_error, "Player_Generic_c::SetPlaybackSpeed - Failed to translate system time to playback time.\n"); NormalizedTimeAtStartOfDrain = INVALID_TIME; } // // Drain with prejudice, but ensuring all frames are parsed // if (Playback->Speed == 0) SetPlaybackSpeed(Playback, 1, Playback->Direction); InternalDrainPlayback(Playback, (PlayerPolicy_t)PolicyPlayoutAlwaysDiscard, true); // // Find the current frames on display, and clamp the play // interval to ensure we don't go too far in the flip. // Policy = PolicyValue(Playback, PlayerAllStreams, PolicyClampPlaybackIntervalOnPlaybackDirectionChange); if (Policy == PolicyValueApply) { if (Direction == PlayForward) Playback->PresentationIntervalReversalLimitStartNormalizedTime = NormalizedTimeAtStartOfDrain; else Playback->PresentationIntervalReversalLimitEndNormalizedTime = NormalizedTimeAtStartOfDrain; } } // // Do we need to re-time the queued frames // ReTimeQueuedFrames = (Playback->Direction == Direction) && (Playback->Speed != Speed); // // Record the new speed and direction // Playback->Speed = Speed; Playback->Direction = Direction; // // Specifically inform the output coordinator of the change // Status = Playback->OutputCoordinator->SetPlaybackSpeed(PlaybackContext, Speed, Direction); if (Status != PlayerNoError) { report(severity_info, "Player_Generic_c::SetPlaybackSpeed - failed to inform output cordinator of speed change.\n"); return Status; } // // Perform queued frame re-timing, and release any single step waiters // for (Stream = Playback->ListOfStreams; Stream != NULL; Stream = Stream->Next) { if (ReTimeQueuedFrames) { Stream->ReTimeStart = OS_GetTimeInMicroSeconds(); Stream->ReTimeQueuedFrames = true; Stream->Manifestor->ReleaseQueuedDecodeBuffers(); } OS_SetEvent(&Stream->SingleStepMayHaveHappened); } // return PlayerNoError; }
PlayerStatus_t Player_Generic_c::SignalEvent( PlayerEventRecord_t *Record ) { unsigned int i; // OS_LockMutex( &Lock ); // // Find an empty vessel // for( i=0; i<PLAYER_MAX_OUTSTANDING_EVENTS; i++ ) if( EventList[i].Record.Code == EventIllegalIdentifier ) { memcpy( &EventList[i].Record, Record, sizeof(PlayerEventRecord_t) ); EventList[i].NextIndex = INVALID_INDEX; if( EventListTail != INVALID_INDEX ) { EventList[EventListTail].NextIndex = i; EventListTail = i; } else { EventListHead = i; EventListTail = i; } break; } if( i == PLAYER_MAX_OUTSTANDING_EVENTS ) { // // The easiest solution if there is no free slot, is to discard // the oldest event and then recurse into this function. // report( severity_error, "Player_Generic_c::SignalEvent - Discarding uncollected event (%08x)\n", EventList[EventListHead].Record.Code ); EventList[EventListHead].Record.Code = EventIllegalIdentifier; EventListHead = EventList[EventListHead].NextIndex; OS_UnLockMutex( &Lock ); return SignalEvent( Record ); } // // We are still locked, now we can see if any of the signals // that have been queued are interested in this event. // OS_SetEvent( &InternalEventSignal ); for( i=0; i<PLAYER_MAX_EVENT_SIGNALS; i++ ) if( (ExternalEventSignals[i].Signal != NULL) && EventMatchesCriteria( Record, ExternalEventSignals[i].Playback, ExternalEventSignals[i].Stream, ExternalEventSignals[i].Events ) ) OS_SetEvent( ExternalEventSignals[i].Signal ); // OS_UnLockMutex( &Lock ); return PlayerNoError; }
void Player_Generic_c::ProcessPostManifest( PlayerStream_t Stream ) { PlayerStatus_t Status; RingStatus_t RingStatus; Buffer_t Buffer; Buffer_t OriginalCodedFrameBuffer; BufferType_t BufferType; PlayerControlStructure_t *ControlStructure; ParsedFrameParameters_t *ParsedFrameParameters; PlayerSequenceNumber_t *SequenceNumberStructure; unsigned long long LastEntryTime; unsigned long long SequenceNumber; unsigned long long MaximumActualSequenceNumberSeen; unsigned long long Time; unsigned int AccumulatedBeforeControlMessagesCount; unsigned int AccumulatedAfterControlMessagesCount; bool ProcessNow; unsigned int *Count; PlayerBufferRecord_t *Table; VideoOutputTiming_t *OutputTiming; unsigned long long Now; // LastEntryTime = OS_GetTimeInMicroSeconds(); SequenceNumber = INVALID_SEQUENCE_VALUE; MaximumActualSequenceNumberSeen = 0; Time = INVALID_TIME; AccumulatedBeforeControlMessagesCount = 0; AccumulatedAfterControlMessagesCount = 0; // // Signal we have started // OS_LockMutex( &Lock ); Stream->ProcessRunningCount++; if( Stream->ProcessRunningCount == Stream->ExpectedProcessCount ) OS_SetEvent( &Stream->StartStopEvent ); OS_UnLockMutex( &Lock ); // // Main Loop // while( !Stream->Terminating ) { RingStatus = Stream->ManifestedBufferRing->Extract( (unsigned int *)(&Buffer), PLAYER_MAX_EVENT_WAIT ); Now = OS_GetTimeInMicroSeconds(); if( Stream->ReTimeQueuedFrames && ((Now - Stream->ReTimeStart) > PLAYER_MAX_TIME_IN_RETIMING) ) Stream->ReTimeQueuedFrames = false; if( RingStatus == RingNothingToGet ) continue; Buffer->GetType( &BufferType ); Buffer->TransferOwnership( IdentifierProcessPostManifest ); // // Deal with a coded frame buffer // if( BufferType == Stream->DecodeBufferType ) { Stream->FramesFromManifestorCount++; #if 0 { static unsigned long long LastTime = 0; static unsigned long long LastActualTime = 0; AudioOutputTiming_t *OutputTiming; Buffer->ObtainMetaDataReference( MetaDataAudioOutputTimingType, (void **)&OutputTiming); report( severity_info, "Post Dn = %d, DS= %6lld, DAS = %6lld, S = %016llx,AS = %016llx\n", OutputTiming->DisplayCount, OutputTiming->SystemPlaybackTime - LastTime, OutputTiming->ActualSystemPlaybackTime - LastActualTime, OutputTiming->SystemPlaybackTime, OutputTiming->ActualSystemPlaybackTime ); LastTime = OutputTiming->SystemPlaybackTime; LastActualTime = OutputTiming->ActualSystemPlaybackTime; } #endif #if 0 { static unsigned long long LastTime = 0; static unsigned long long LastActualTime = 0; VideoOutputTiming_t *OutputTiming; Buffer->ObtainMetaDataReference( MetaDataVideoOutputTimingType, (void **)&OutputTiming ); report( severity_info, "Post Dn = %d %d, I = %d, TFF = %d, DS= %6lld, DAS = %6lld, S = %016llx, AS = %016llx\n", OutputTiming->DisplayCount[0], OutputTiming->DisplayCount[1], OutputTiming->Interlaced, OutputTiming->TopFieldFirst, OutputTiming->SystemPlaybackTime - LastTime, OutputTiming->ActualSystemPlaybackTime - LastActualTime, OutputTiming->SystemPlaybackTime, OutputTiming->ActualSystemPlaybackTime ); LastTime = OutputTiming->SystemPlaybackTime; LastActualTime = OutputTiming->ActualSystemPlaybackTime; } #endif // // Obtain a sequence number from the buffer // Status = Buffer->ObtainAttachedBufferReference( Stream->CodedFrameBufferType, &OriginalCodedFrameBuffer ); if( Status != PlayerNoError ) { report( severity_error, "Player_Generic_c::ProcessPostManifest - Unable to obtain the the original coded frame buffer - Implementation error\n" ); Buffer->DecrementReferenceCount( IdentifierProcessPostManifest ); continue; } Status = OriginalCodedFrameBuffer->ObtainMetaDataReference( MetaDataSequenceNumberType, (void **)(&SequenceNumberStructure) ); if( Status != PlayerNoError ) { report( severity_error, "Player_Generic_c::ProcessPostManifest - Unable to obtain the meta data \"SequenceNumber\" - Implementation error\n" ); Buffer->DecrementReferenceCount( IdentifierProcessPostManifest ); continue; } Status = Buffer->ObtainMetaDataReference( MetaDataParsedFrameParametersReferenceType, (void **)(&ParsedFrameParameters) ); if( Status != PlayerNoError ) { report( severity_error, "Player_Generic_c::ProcessPostManifest - Unable to obtain the meta data \"ParsedFrameParametersReference\" - Implementation error\n" ); Buffer->DecrementReferenceCount( IdentifierProcessPostManifest ); continue; } // // Check for whether or not we are in re-timing // if( Stream->ReTimeQueuedFrames && !SequenceNumberStructure->MarkerFrame ) { Status = Buffer->ObtainMetaDataReference( (Stream->StreamType == StreamTypeVideo ? MetaDataVideoOutputTimingType : MetaDataAudioOutputTimingType), (void **)&OutputTiming ); if( Status != PlayerNoError ) { report( severity_error, "Player_Generic_c::ProcessPostManifest - Unable to obtain the meta data \"%s\" - Implementation error\n", (Stream->StreamType == StreamTypeVideo ? "VideoOutputTiming" : "AudioOutputTiming") ); Buffer->DecrementReferenceCount( IdentifierProcessPostManifest ); continue; } if( ValidTime(OutputTiming->ActualSystemPlaybackTime) ) { Stream->ReTimeQueuedFrames = false; } else { Stream->OutputTimer->GenerateFrameTiming( Buffer ); Status = Stream->OutputTimer->TestForFrameDrop( Buffer, OutputTimerBeforeManifestation ); if( !Stream->Terminating && (Status == OutputTimerNoError) ) { Stream->FramesToManifestorCount++; Stream->Manifestor->QueueDecodeBuffer( Buffer ); continue; } } } // // Extract the sequence number, and write the timing statistics // //report( severity_info, "MQ Post Man %d - %d\n", Stream->StreamType, ParsedFrameParameters->DisplayFrameIndex ); SequenceNumberStructure->TimeEntryInProcess3 = OS_GetTimeInMicroSeconds(); SequenceNumberStructure->DeltaEntryInProcess3 = SequenceNumberStructure->TimeEntryInProcess3 - LastEntryTime; LastEntryTime = SequenceNumberStructure->TimeEntryInProcess3; SequenceNumber = SequenceNumberStructure->Value; MaximumActualSequenceNumberSeen = max(SequenceNumber, MaximumActualSequenceNumberSeen); Time = ParsedFrameParameters->NativePlaybackTime; #ifndef __TDT__ ProcessStatistics( Stream, SequenceNumberStructure ); #endif if( SequenceNumberStructure->MarkerFrame ) { Stream->DiscardingUntilMarkerFramePostM = false; Time = INVALID_TIME; } // // Process any outstanding control messages to be applied before this buffer // ProcessAccumulatedControlMessages( Stream, &AccumulatedBeforeControlMessagesCount, PLAYER_MAX_POSTM_MESSAGES, Stream->AccumulatedBeforePostMControlMessages, SequenceNumber, Time ); // // Pass buffer back into output timer // and release the buffer. // if( !SequenceNumberStructure->MarkerFrame ) { Stream->OutputTimer->RecordActualFrameTiming( Buffer ); Stream->Codec->ReleaseDecodeBuffer( Buffer ); } else Buffer->DecrementReferenceCount( IdentifierProcessPostManifest ); // // Process any outstanding control messages to be applied after this buffer // ProcessAccumulatedControlMessages( Stream, &AccumulatedAfterControlMessagesCount, PLAYER_MAX_POSTM_MESSAGES, Stream->AccumulatedAfterPostMControlMessages, SequenceNumber, Time ); } // // Deal with a player control structure // else if( BufferType == BufferPlayerControlStructureType ) { Buffer->ObtainDataReference( NULL, NULL, (void **)(&ControlStructure) ); ProcessNow = (ControlStructure->SequenceType == SequenceTypeImmediate) || ((SequenceNumber != INVALID_SEQUENCE_VALUE) && (ControlStructure->SequenceValue <= MaximumActualSequenceNumberSeen)); if( ProcessNow ) ProcessControlMessage( Stream, Buffer, ControlStructure ); else { if( (ControlStructure->SequenceType == SequenceTypeBeforeSequenceNumber) || (ControlStructure->SequenceType == SequenceTypeBeforePlaybackTime) ) { Count = &AccumulatedBeforeControlMessagesCount; Table = Stream->AccumulatedBeforePostMControlMessages; } else { Count = &AccumulatedAfterControlMessagesCount; Table = Stream->AccumulatedAfterPostMControlMessages; } AccumulateControlMessage( Buffer, ControlStructure, Count, PLAYER_MAX_POSTM_MESSAGES, Table ); } } else { report( severity_error, "Player_Generic_c::ProcessPostManifest - Unknown buffer type received - Implementation error.\n" ); Buffer->DecrementReferenceCount(); } } report( severity_info, "3333 Holding control strutures %d\n", AccumulatedBeforeControlMessagesCount + AccumulatedAfterControlMessagesCount ); // // Make sur no one will wait for these // Stream->ReTimeQueuedFrames = false; // // Signal we have terminated // OS_LockMutex( &Lock ); Stream->ProcessRunningCount--; if( Stream->ProcessRunningCount == 0 ) OS_SetEvent( &Stream->StartStopEvent ); OS_UnLockMutex( &Lock ); }
PlayerStatus_t Player_Generic_c::PerformInSequenceCall( PlayerStream_t Stream, PlayerControlStructure_t *ControlStructure ) { PlayerStatus_t Status; // Status = PlayerNoError; // We ignore the status for some specific functions // switch( ControlStructure->InSequence.Fn ) { case CodecFnOutputPartialDecodeBuffers: Stream->Codec->OutputPartialDecodeBuffers(); break; case CodecFnReleaseReferenceFrame: //report(severity_info, "Performing a release %d\n", ControlStructure->InSequence.UnsignedInt ); Stream->Codec->ReleaseReferenceFrame( ControlStructure->InSequence.UnsignedInt ); break; case FrameParserFnSetModuleParameters: Status = Stream->FrameParser->SetModuleParameters( ControlStructure->InSequence.UnsignedInt, ControlStructure->InSequence.Block ); break; case CodecFnSetModuleParameters: Status = Stream->Codec->SetModuleParameters( ControlStructure->InSequence.UnsignedInt, ControlStructure->InSequence.Block ); break; case ManifestorFnSetModuleParameters: Status = Stream->Manifestor->SetModuleParameters( ControlStructure->InSequence.UnsignedInt, ControlStructure->InSequence.Block ); break; case ManifestorFnQueueEventSignal: Status = Stream->Manifestor->QueueEventSignal( &ControlStructure->InSequence.Event ); break; case ManifestorVideoFnSetInputWindow: { unsigned int *Words = (unsigned int *)ControlStructure->InSequence.Block; Status = ((Manifestor_Video_c *)Stream->Manifestor)->SetInputWindow( Words[0], Words[1], Words[2], Words[3] ); } break; case ManifestorVideoFnSetOutputWindow: { unsigned int *Words = (unsigned int *)ControlStructure->InSequence.Block; Status = ((Manifestor_Video_c *)Stream->Manifestor)->SetOutputWindow( Words[0], Words[1], Words[2], Words[3] ); } break; case OutputTimerFnResetTimeMapping: Status = Stream->OutputTimer->ResetTimeMapping(); break; case OutputTimerFnSetModuleParameters: Status = Stream->OutputTimer->SetModuleParameters( ControlStructure->InSequence.UnsignedInt, ControlStructure->InSequence.Block ); break; case OSFnSetEventOnManifestation: case OSFnSetEventOnPostManifestation: OS_SetEvent( (OS_Event_t *)ControlStructure->InSequence.Pointer ); break; case PlayerFnSwitchFrameParser: SwitchFrameParser( (PlayerStream_t)ControlStructure->InSequence.Pointer ); break; case PlayerFnSwitchCodec: SwitchCodec( (PlayerStream_t)ControlStructure->InSequence.Pointer ); break; case PlayerFnSwitchOutputTimer: SwitchOutputTimer( (PlayerStream_t)ControlStructure->InSequence.Pointer ); break; case PlayerFnSwitchComplete: SwitchComplete( (PlayerStream_t)ControlStructure->InSequence.Pointer ); break; default: report( severity_error, "Player_Generic_c::PerformInSequenceCall - Unsupported function call - Implementation error.\n" ); Status = PlayerNotSupported; break; } // return Status; }
/* 说明一下,IDLE的中断在串口无数据接收的情况下,是不会一直产生的, 产生的条件是这样的,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发, 一断接收的数据断流,没有接收到数据,即产生IDLE中断。*/ UINT32 IO_DataUartISR(UINT32 data) { static UINT32 index = 0; UINT16 rxc; UINT8 txc; UINT32 Fifodepth; UINT8* temp; #if 1 /*******************************************************/ /* handle RX interrupt */ /*******************************************************/ /* Service RX data ready as long as there is data in RX FIFO */ if( USART_GetIntBitState(USART1, USART_INT_RBNE) != RESET) { USART_INT_Set( USART1, USART_INT_IDLEF, ENABLE ); /* Read data from RX UART1 DR and store in buffer */ rxc = USART_DataReceive(USART1) & 0xff; UartDev.DATA.RxBufWrPtr[index] = (UINT8)rxc; UartDev.DATA.RxBufCount++; index++; USART_ClearIntBitState(USART1, USART_INT_RBNE); } if( USART_GetIntBitState(USART1, USART_INT_IDLEF) != RESET) { USART_INT_Set(USART1, USART_INT_IDLEF, DISABLE ); USART_ClearIntBitState(USART1, USART_INT_IDLEF); index = 0; temp = UartDev.DATA.RxBufRdPtr; UartDev.DATA.RxBufRdPtr = UartDev.DATA.RxBufWrPtr; UartDev.DATA.RxBufWrPtr = temp; OS_SetEvent(IO_EVENT_GROUP_ID, IO_UART_RXIND_FLG); } /*******************************************************/ /* handle TX interrupt */ /*******************************************************/ if( USART_GetIntBitState(USART1, USART_INT_TBE) != RESET) { USART_ClearIntBitState(USART1, USART_INT_TBE); /* Init FIFO count */ Fifodepth = UART_UART_TX_HW_FIFO_SIZE; /* Add data to TX UART FIFO until it is full */ while((UartDev.DATA.TxBufCount != 0) && (Fifodepth > 0)) { /* Write data byte to UART TX FIFO */ /* Write one byte to the transmit data register */ txc = *(UartDev.DATA.TxBufPtr); USART_DataSend( USART1 , txc ); UartDev.DATA.TxBufPtr++; /* Decrement Tx Serial count */ UartDev.DATA.TxBufCount--; /* Decrement FIFO count */ Fifodepth--; } /* if we have send all character in fifo */ if (UartDev.DATA.TxBufCount == 0 ) { /* disable the USART1 Transmoit interrupt */ USART_INT_Set(USART1, USART_INT_TBE, DISABLE ); OS_SetEvent(IO_EVENT_GROUP_ID, IO_UART_TXRSP_FLG); } } #else /*******************************************************/ /* handle RX interrupt */ /*******************************************************/ /* Service RX data ready as long as there is data in RX FIFO */ if( USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { USART_ITConfig( USART1, USART_IT_IDLE, ENABLE ); /* Read data from RX UART1 DR and store in buffer */ rxc = USART_ReceiveData(USART1) & 0xff; UartDev.DATA.RxBufWrPtr[index] = (UINT8)rxc; UartDev.DATA.RxBufCount++; index++; USART_ClearITPendingBit(USART1, USART_IT_RXNE); } if( USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) { USART_ClearITPendingBit(USART1, USART_IT_IDLE); USART_ITConfig(USART1, USART_IT_IDLE, DISABLE ); index = 0; temp = UartDev.DATA.RxBufRdPtr; UartDev.DATA.RxBufRdPtr = UartDev.DATA.RxBufWrPtr; UartDev.DATA.RxBufWrPtr = temp; OS_SetEvent(IO_EVENT_GROUP_ID, IO_UART_RXIND_FLG); } /*******************************************************/ /* handle TX interrupt */ /*******************************************************/ if( USART_GetITStatus(USART1, USART_IT_TXE) != RESET) { USART_ClearITPendingBit(USART1, USART_IT_TXE); /* Init FIFO count */ Fifodepth = UART_UART_TX_HW_FIFO_SIZE; /* Add data to TX UART FIFO until it is full */ while((UartDev.DATA.TxBufCount != 0) && (Fifodepth > 0)) { /* Write data byte to UART TX FIFO */ /* Write one byte to the transmit data register */ txc = *(UartDev.DATA.TxBufPtr); USART_SendData( USART1 , txc ); UartDev.DATA.TxBufPtr++; /* Decrement Tx Serial count */ UartDev.DATA.TxBufCount--; /* Decrement FIFO count */ Fifodepth--; } /* if we have send all character in fifo */ if (UartDev.DATA.TxBufCount == 0 ) { /* Enable the USART1 Transmoit interrupt */ USART_ITConfig(USART1, USART_IT_TXE, DISABLE ); OS_SetEvent(IO_EVENT_GROUP_ID, IO_UART_TXRSP_FLG); } } #endif return 0; }
BufferStatus_t BufferPool_Generic_c::ReleaseBuffer( Buffer_t Buffer ) { unsigned int i; Buffer_Generic_t LocalBuffer; Buffer_Generic_t *LocationOfBufferPointer; BlockDescriptor_t *LocationOfBlockPointer; BlockDescriptor_t Block; PlayerEventRecord_t ReleaseEvent; // LocalBuffer = (Buffer_Generic_t)Buffer; // // Do I want to signal this free ? // if( (EventMask & EventBufferRelease) != 0 ) { ReleaseEvent.Code = EventBufferRelease; ReleaseEvent.Playback = Playback; ReleaseEvent.Stream = Stream; ReleaseEvent.PlaybackTime = TIME_NOT_APPLICABLE; ReleaseEvent.Value[0].Pointer = LocalBuffer->BufferBlock->Address[0]; if( ReleaseEvent.Value[0].Pointer == NULL ) ReleaseEvent.Value[0].Pointer = LocalBuffer->BufferBlock->Address[1]; if( ReleaseEvent.Value[0].Pointer == NULL ) ReleaseEvent.Value[0].Pointer = LocalBuffer->BufferBlock->Address[2]; ReleaseEvent.Value[1].UnsignedInt = LocalBuffer->BufferBlock->Size; ReleaseEvent.UserData = EventUserData; Player->SignalEvent( &ReleaseEvent ); } // // Release any non-persistant meta data // LocationOfBlockPointer = &LocalBuffer->ListOfMetaData; while( *LocationOfBlockPointer != NULL ) { if( !((*LocationOfBlockPointer)->AttachedToPool) ) { // // Unthread the meta data item block // Block = *LocationOfBlockPointer; *LocationOfBlockPointer = Block->Next; DeAllocateMemoryBlock( Block ); delete Block; } else LocationOfBlockPointer = &((*LocationOfBlockPointer)->Next); } // // Release our hold on any attached buffers // OS_LockMutex( &LocalBuffer->Lock ); for( i=0; i<MAX_ATTACHED_BUFFERS; i++ ) { Buffer_t Temporary = LocalBuffer->AttachedBuffers[i]; if( Temporary != NULL ) { LocalBuffer->AttachedBuffers[i] = NULL; Temporary->DecrementReferenceCount(); } } OS_UnLockMutex( &LocalBuffer->Lock ); // // If non-persistant delete the memory associated with the block // if( !BufferDescriptor->AllocateOnPoolCreation && (BufferDescriptor->AllocationSource != NoAllocation) ) DeAllocateMemoryBlock( LocalBuffer->BufferBlock ); OS_LockMutex( &Lock ); TotalUsedMemory -= LocalBuffer->DataSize; LocalBuffer->DataSize = 0; // // If there are a fixed number of buffers insert this on the ring, // else unthread from list and delete the buffer // if( NumberOfBuffers != NOT_SPECIFIED ) { FreeBuffer->Insert( (unsigned int)LocalBuffer ); OS_SetEvent( &BufferReleaseSignal ); } else { for( LocationOfBufferPointer = &ListOfBuffers; *LocationOfBufferPointer != NULL; LocationOfBufferPointer = &((*LocationOfBufferPointer)->Next) ) if( (*LocationOfBufferPointer) == LocalBuffer ) break; if( *LocationOfBufferPointer == NULL ) { report( severity_error, "BufferPool_Generic_c::ReleaseBuffer - Buffer not found in list, internal consistency error.\n" ); return BufferError; } *LocationOfBufferPointer = LocalBuffer->Next; delete LocalBuffer; CountOfBuffers--; } CountOfReferencedBuffers--; OS_UnLockMutex( &Lock ); // return BufferNoError; }
//}}} //{{{ EventSignalThread void HavanaPlayer_c::EventSignalThread (void) { PlayerStatus_t PlayerStatus; struct PlayerEventRecord_s PlayerEvent; HavanaStatus_t HavanaStatus; int i; struct player_event_s Event; HAVANA_DEBUG("Starting\n"); while (EventSignalThreadRunning) { OS_WaitForEvent (&EventSignal, OS_INFINITE); OS_ResetEvent (&EventSignal); while (true) { PlayerStatus = Player->GetEventRecord (PlayerAllPlaybacks, PlayerAllStreams, EventAllEvents, &PlayerEvent, true); if (PlayerStatus != PlayerNoError) break; HAVANA_DEBUG("Got Event 0x%x\n", PlayerEvent.Code); OS_LockMutex (&Lock); // Make certain we cannot delete playback while checking the event for (i = 0; i < MAX_PLAYBACKS; i++) // Check to see if any streams are interested in this event { if (Playback[i] != NULL) { HavanaStatus = Playback[i]->CheckEvent (&PlayerEvent); if (HavanaStatus == HavanaNoError) // A stream has claimed event don't try any more. break; } } OS_UnLockMutex (&Lock); if ((EventSignalThreadRunning) && (EventSignalCallback != NULL)) //{{{ translate from a Player2 event record to the external Player event record. { Event.timestamp = PlayerEvent.PlaybackTime; Event.component = PlayerEvent.Value[0].Pointer; Event.playback = PlayerEvent.Playback; Event.stream = PlayerEvent.Stream; switch (PlayerEvent.Code) { case EventPlaybackCreated: Event.code = PLAYER_EVENT_PLAYBACK_CREATED; break; case EventPlaybackTerminated: Event.code = PLAYER_EVENT_PLAYBACK_TERMINATED; break; case EventStreamCreated: Event.code = PLAYER_EVENT_STREAM_CREATED; break; case EventStreamTerminated: Event.code = PLAYER_EVENT_STREAM_TERMINATED; break; case EventStreamSwitched: Event.code = PLAYER_EVENT_STREAM_SWITCHED; break; case EventStreamDrained: Event.code = PLAYER_EVENT_STREAM_DRAINED; break; case EventStreamUnPlayable: Event.code = PLAYER_EVENT_STREAM_UNPLAYABLE; break; case EventFirstFrameManifested: Event.code = PLAYER_EVENT_FIRST_FRAME_ON_DISPLAY; break; case EventTimeNotification: Event.code = PLAYER_EVENT_TIME_NOTIFICATION; break; case EventDecodeBufferAvailable: Event.code = PLAYER_EVENT_DECODE_BUFFER_AVAILABLE; break; case EventInputFormatCreated: Event.code = PLAYER_EVENT_INPUT_FORMAT_CREATED; break; case EventSupportedInputFormatCreated: Event.code = PLAYER_EVENT_SUPPORTED_INPUT_FORMAT_CREATED; break; case EventDecodeErrorsCreated: Event.code = PLAYER_EVENT_DECODE_ERRORS_CREATED; break; case EventSampleFrequencyCreated: Event.code = PLAYER_EVENT_SAMPLE_FREQUENCY_CREATED; break; case EventNumberChannelsCreated: Event.code = PLAYER_EVENT_NUMBER_CHANNELS_CREATED; break; case EventNumberOfSamplesProcessedCreated: Event.code = PLAYER_EVENT_NUMBER_OF_SAMPLES_PROCESSED; break; case EventInputFormatChanged: Event.code = PLAYER_EVENT_INPUT_FORMAT_CHANGED; break; case EventSourceSizeChangeManifest: Event.code = PLAYER_EVENT_SIZE_CHANGED; break; case EventSourceFrameRateChangeManifest: Event.code = PLAYER_EVENT_FRAME_RATE_CHANGED; break; case EventFailedToDecodeInTime: Event.code = PLAYER_EVENT_FRAME_DECODED_LATE; break; case EventFailedToDeliverDataInTime: Event.code = PLAYER_EVENT_DATA_DELIVERED_LATE; break; case EventBufferRelease: Event.code = PLAYER_EVENT_BUFFER_RELEASE; break; case EventTrickModeDomainChange: Event.code = PLAYER_EVENT_TRICK_MODE_CHANGE; break; case EventTimeMappingEstablished: Event.code = PLAYER_EVENT_TIME_MAPPING_ESTABLISHED; break; case EventTimeMappingReset: Event.code = PLAYER_EVENT_TIME_MAPPING_RESET; break; case EventFailureToPlaySmoothReverse: Event.code = PLAYER_EVENT_REVERSE_FAILURE; break; default: //HAVANA_TRACE("Unexpected event %x\n", PlayerEvent.Code); Event.code = PLAYER_EVENT_INVALID; //memset (Event, 0, sizeof (struct player_event_s)); //return HavanaError; } //HAVANA_TRACE("Code %x, at 0x%llx\n", Event.code, Event.timestamp); if (Event.code != PLAYER_EVENT_INVALID) EventSignalCallback (&Event); } //}}} } } OS_SetEvent (&EventSignalThreadTerminated); HAVANA_DEBUG ("Terminating\n"); }