int gsiStartThread(GSThreadFunc aThreadFunc, gsi_u32 theStackSize, void *arg, GSIThreadID* theThreadIdOut) { if(theStackSize & 0x3) { theStackSize += 0x4; theStackSize &= ~0x3; } theThreadIdOut->mStack = gsimemalign(4, theStackSize); OS_CreateThread(&theThreadIdOut->mThread, aThreadFunc, arg, theThreadIdOut->mStack, theStackSize, 15); OS_WakeupThreadDirect(&theThreadIdOut->mThread); return 0; }
PlayerStatus_t Player_Generic_c::AddStream(PlayerPlayback_t Playback, PlayerStream_t *Stream, PlayerStreamType_t StreamType, Collator_t Collator, FrameParser_t FrameParser, Codec_t Codec, OutputTimer_t OutputTimer, Manifestor_t Manifestor, bool SignalEvent, void *EventUserData) { PlayerStream_t NewStream; PlayerStatus_t Status; OS_Status_t OSStatus; OS_Thread_t Thread; unsigned int Count; PlayerEventRecord_t Event; // // Check this is reasonable // if (StreamType == StreamTypeNone) { report(severity_error, "Player_Generic_c::AddStream - Stream type must be specified (not StreamTypeNone).\n"); return PlayerError; } // if ((Manifestor == NULL) && SignalEvent) { report(severity_error, "Player_Generic_c::AddStream - Request event on first manifestation, when no frames are to be manifested.\n"); return PlayerError; } // // Create new stream // NewStream = new struct PlayerStream_s; if (NewStream == NULL) { report(severity_error, "Player_Generic_c::AddStream - Unable to allocate new stream structure.\n"); return PlayerInsufficientMemory; } memset(NewStream, 0x00, sizeof(struct PlayerStream_s)); // // Initialize the stream structure // NewStream->Player = this; NewStream->Playback = Playback; NewStream->StreamType = StreamType; NewStream->Collator = Collator; NewStream->FrameParser = FrameParser; NewStream->Codec = Codec; NewStream->OutputTimer = OutputTimer; NewStream->Manifestor = Manifestor; NewStream->Demultiplexor = NULL; NewStream->UnPlayable = false; NewStream->Terminating = false; NewStream->ProcessRunningCount = 0; NewStream->ExpectedProcessCount = (Manifestor != NULL) ? 4 : 2; OS_InitializeEvent(&NewStream->StartStopEvent); OS_InitializeEvent(&NewStream->Drained); NewStream->CodecReset = false; NewStream->SwitchStreamInProgress = false; OS_InitializeEvent(&NewStream->SwitchStreamLastOneOutOfTheCodec); NewStream->Step = false; OS_InitializeEvent(&NewStream->SingleStepMayHaveHappened); NewStream->MarkerInCodedFrameIndex = INVALID_INDEX; NewStream->NextBufferSequenceNumber = 0; NewStream->ReTimeQueuedFrames = false; NewStream->InsertionsIntoNonDecodedBuffers = 0; NewStream->RemovalsFromNonDecodedBuffers = 0; NewStream->DisplayIndicesCollapse = 0; NewStream->RequestedPresentationIntervalStartNormalizedTime = Playback->RequestedPresentationIntervalStartNormalizedTime; NewStream->RequestedPresentationIntervalEndNormalizedTime = Playback->RequestedPresentationIntervalEndNormalizedTime; // // Get the coded frame parameters // switch (StreamType) { case StreamTypeAudio: NewStream->CodedFrameBufferType = BufferCodedFrameBufferType; NewStream->CodedFrameCount = Playback->AudioCodedFrameCount; NewStream->CodedMemorySize = Playback->AudioCodedMemorySize; NewStream->CodedFrameMaximumSize = Playback->AudioCodedFrameMaximumSize; memcpy(NewStream->CodedMemoryPartitionName, Playback->AudioCodedMemoryPartitionName, ALLOCATOR_MAX_PARTITION_NAME_SIZE); break; case StreamTypeVideo: NewStream->CodedFrameBufferType = BufferCodedFrameBufferType; NewStream->CodedFrameCount = Playback->VideoCodedFrameCount; NewStream->CodedMemorySize = Playback->VideoCodedMemorySize; NewStream->CodedFrameMaximumSize = Playback->VideoCodedFrameMaximumSize; memcpy(NewStream->CodedMemoryPartitionName, Playback->VideoCodedMemoryPartitionName, ALLOCATOR_MAX_PARTITION_NAME_SIZE); break; case StreamTypeOther: NewStream->CodedFrameBufferType = BufferCodedFrameBufferType; NewStream->CodedFrameCount = Playback->OtherCodedFrameCount; NewStream->CodedMemorySize = Playback->OtherCodedMemorySize; NewStream->CodedFrameMaximumSize = Playback->OtherCodedFrameMaximumSize; memcpy(NewStream->CodedMemoryPartitionName, Playback->OtherCodedMemoryPartitionName, ALLOCATOR_MAX_PARTITION_NAME_SIZE); break; default: break; } // // Register the player to the child classes, they will require it early, // these function do no work, so cannot return a fail status. // Collator->RegisterPlayer(this, Playback, NewStream, Collator, FrameParser, Codec, OutputTimer, Manifestor); FrameParser->RegisterPlayer(this, Playback, NewStream, Collator, FrameParser, Codec, OutputTimer, Manifestor); Codec->RegisterPlayer(this, Playback, NewStream, Collator, FrameParser, Codec, OutputTimer, Manifestor); OutputTimer->RegisterPlayer(this, Playback, NewStream, Collator, FrameParser, Codec, OutputTimer, Manifestor); if (Manifestor != NULL) Manifestor->RegisterPlayer(this, Playback, NewStream, Collator, FrameParser, Codec, OutputTimer, Manifestor); // // Get the buffer pools, and attach NOTE the get's provoke creation of the pools. // the sequence numbers to them // Status = GetCodedFrameBufferPool(NewStream, NULL, NULL); if (Status != PlayerNoError) { report(severity_error, "Player_Generic_c::AddStream - Failed to get the coded buffer pool.\n"); CleanUpAfterStream(NewStream); return Status; } Status = NewStream->CodedFrameBufferPool->AttachMetaData(MetaDataSequenceNumberType); if (Status != PlayerNoError) { report(severity_error, "Player_Generic_c::AddStream - Failed to get attach sequence numbers to the coded buffer pool.\n"); CleanUpAfterStream(NewStream); return Status; } // if (Manifestor != NULL) { Status = Manifestor->GetDecodeBufferPool(&NewStream->DecodeBufferPool); if (Status != PlayerNoError) { report(severity_error, "Player_Generic_c::AddStream - Failed to get the decode buffer pool.\n"); CleanUpAfterStream(NewStream); return Status; } Status = Manifestor->GetPostProcessControlBufferPool(&NewStream->PostProcessControlBufferPool); if (Status != PlayerNoError) { report(severity_error, "Player_Generic_c::AddStream - Failed to get the post processing control buffer pool.\n"); CleanUpAfterStream(NewStream); return Status; } } // // Create the rings needed to hold the buffers // during inter process communications. // NewStream->CollatedFrameRing = new RingGeneric_c(NewStream->CodedFrameCount + PLAYER_MAX_CONTROL_STRUCTURE_BUFFERS); if ((NewStream->CollatedFrameRing == NULL) || (NewStream->CollatedFrameRing->InitializationStatus != RingNoError)) { report(severity_error, "Player_Generic_c::AddStream - Unable to create interprocess collated frame ring.\n"); CleanUpAfterStream(NewStream); return PlayerInsufficientMemory; } NewStream->ParsedFrameRing = new RingGeneric_c(NewStream->CodedFrameCount + PLAYER_MAX_CONTROL_STRUCTURE_BUFFERS); if ((NewStream->ParsedFrameRing == NULL) || (NewStream->ParsedFrameRing->InitializationStatus != RingNoError)) { report(severity_error, "Player_Generic_c::AddStream - Unable to create interprocess parsed frame ring.\n"); CleanUpAfterStream(NewStream); return PlayerInsufficientMemory; } // if (Manifestor != NULL) { NewStream->DecodeBufferPool->GetType(&NewStream->DecodeBufferType); NewStream->DecodeBufferPool->GetPoolUsage(&Count, NULL, NULL, NULL, NULL); if (Count == 0) Count = DEFAULT_RING_SIZE; NewStream->NumberOfDecodeBuffers = Count; if (NewStream->NumberOfDecodeBuffers > PLAYER_MAX_DECODE_BUFFERS) { report(severity_error, "Player_Generic_c::AddStream - Too many decode buffers - Implementation constant range error.\n"); CleanUpAfterStream(NewStream); return PlayerImplementationError; } NewStream->DecodedFrameRing = new RingGeneric_c(Count + PLAYER_MAX_CONTROL_STRUCTURE_BUFFERS); if ((NewStream->DecodedFrameRing == NULL) || (NewStream->DecodedFrameRing->InitializationStatus != RingNoError)) { report(severity_error, "Player_Generic_c::AddStream - Unable to create interprocess decoded frame ring.\n"); CleanUpAfterStream(NewStream); return PlayerInsufficientMemory; } NewStream->ManifestedBufferRing = new RingGeneric_c(Count + PLAYER_MAX_CONTROL_STRUCTURE_BUFFERS); if ((NewStream->ManifestedBufferRing == NULL) || (NewStream->ManifestedBufferRing->InitializationStatus != RingNoError)) { report(severity_error, "Player_Generic_c::AddStream - Unable to create interprocess manifested frame ring.\n"); CleanUpAfterStream(NewStream); return PlayerInsufficientMemory; } } // // Create the tasks that pass data between components, // and provide them with a context in which to operate. // NOTE Since we are unsure about the startup, we use a // simple delay to shut down the threads if startup is not // as expected. // OS_ResetEvent(&NewStream->StartStopEvent); OSStatus = OS_CreateThread(&Thread, PlayerProcessCollateToParse, NewStream, ProcessNames[StreamType][0], (OS_MID_PRIORITY + 8)); if (OSStatus == OS_NO_ERROR) OSStatus = OS_CreateThread(&Thread, PlayerProcessParseToDecode, NewStream, ProcessNames[StreamType][1], (OS_MID_PRIORITY + 8)); if ((OSStatus == OS_NO_ERROR) && (Manifestor != NULL)) OSStatus = OS_CreateThread(&Thread, PlayerProcessDecodeToManifest, NewStream, ProcessNames[StreamType][2], (OS_MID_PRIORITY + 10)); if ((OSStatus == OS_NO_ERROR) && (Manifestor != NULL)) OSStatus = OS_CreateThread(&Thread, PlayerProcessPostManifest, NewStream, ProcessNames[StreamType][3], (OS_MID_PRIORITY + 12)); // if (OSStatus != OS_NO_ERROR) { report(severity_error, "Player_Generic_c::AddStream - Failed to create stream processes.\n"); NewStream->Terminating = true; OS_SleepMilliSeconds(2 * PLAYER_MAX_EVENT_WAIT); NewStream->ProcessRunningCount = 0; CleanUpAfterStream(NewStream); return PlayerError; } // OS_WaitForEvent(&NewStream->StartStopEvent, PLAYER_MAX_EVENT_WAIT); if (NewStream->ProcessRunningCount != NewStream->ExpectedProcessCount) { report(severity_error, "Player_Generic_c::AddStream - Stream processes failed to run.\n"); NewStream->Terminating = true; OS_SleepMilliSeconds(2 * PLAYER_MAX_EVENT_WAIT); NewStream->ProcessRunningCount = 0; CleanUpAfterStream(NewStream); return PlayerError; } // // Insert the stream into the playback list at this point // OS_LockMutex(&Lock); NewStream->Next = Playback->ListOfStreams; Playback->ListOfStreams = NewStream; OS_UnLockMutex(&Lock); // // Now exchange the appropriate information between the classes // Status = Collator->RegisterOutputBufferRing(NewStream->CollatedFrameRing); if (Status != PlayerNoError) { report(severity_error, "Player_Generic_c::AddStream - Failed to register stream parameters with Collator.\n"); CleanUpAfterStream(NewStream); return Status; } // Status = FrameParser->RegisterOutputBufferRing(NewStream->ParsedFrameRing); if (Status != PlayerNoError) { report(severity_error, "Player_Generic_c::AddStream - Failed to register stream parameters with Frame Parser.\n"); CleanUpAfterStream(NewStream); return Status; } // Status = Codec->RegisterOutputBufferRing(NewStream->DecodedFrameRing); /* NULL for no manifestor */ if (Status != PlayerNoError) { report(severity_error, "Player_Generic_c::AddStream - Failed to register stream parameters with Codec.\n"); CleanUpAfterStream(NewStream); return Status; } // Status = OutputTimer->RegisterOutputCoordinator(Playback->OutputCoordinator); if (Status != PlayerNoError) { report(severity_error, "Player_Generic_c::AddStream - Failed to register Output Coordinator with Output Timer.\n"); CleanUpAfterStream(NewStream); return Status; } // if (Manifestor != NULL) { Status = Manifestor->RegisterOutputBufferRing(NewStream->ManifestedBufferRing); if (Status != PlayerNoError) { report(severity_error, "Player_Generic_c::AddStream - Failed to register stream parameters with Manifestor.\n"); CleanUpAfterStream(NewStream); return Status; } } // // Do we need to queue an event on display of first frame and stream created // if (SignalEvent) { Event.Code = EventFirstFrameManifested; Event.Playback = Playback; Event.Stream = NewStream; Event.PlaybackTime = TIME_NOT_APPLICABLE; Event.UserData = EventUserData; Status = CallInSequence(NewStream, SequenceTypeImmediate, TIME_NOT_APPLICABLE, ManifestorFnQueueEventSignal, &Event); if (Status != PlayerNoError) { report(severity_error, "Player_Generic_c::AddStream - Failed to issue call to signal first frame event.\n"); CleanUpAfterStream(NewStream); return Status; } Event.Code = EventStreamCreated; Status = this->SignalEvent(&Event); if (Status != PlayerNoError) { report(severity_error, "Player_Generic_c::AddStream - Failed to issue stream created event.\n"); CleanUpAfterStream(NewStream); return Status; } } // *Stream = NewStream; // return PlayerNoError; }
//}}} //{{{ Init HavanaStatus_t HavanaPlayer_c::Init (void) { HAVANA_DEBUG("\n"); if (Player == NULL) Player = new Player_Generic_c(); if (Player == NULL) { HAVANA_ERROR("Unable to create player - insufficient memory\n"); return HavanaNoMemory; } //{{{ Event management // Create event signal thread and input mutexes if (EventSignalThreadId == OS_INVALID_THREAD) { if (OS_InitializeMutex (&Lock) != OS_NO_ERROR) { HAVANA_ERROR ("Failed to initialize Lock mutex\n"); return HavanaNoMemory; } if (OS_InitializeEvent (&EventSignal) != OS_NO_ERROR) { HAVANA_ERROR ("Failed to initialize EventSignal\n"); OS_TerminateMutex (&Lock); return HavanaError; } if (OS_InitializeEvent (&EventSignalThreadTerminated) != OS_NO_ERROR) { HAVANA_ERROR ("Failed to initialize EventSignalThreadTerminated event\n"); OS_TerminateEvent (&EventSignal); OS_TerminateMutex (&Lock); return HavanaError; } EventSignalThreadRunning = true; if (OS_CreateThread (&EventSignalThreadId, EventSignalThreadStub, this, "Havana player Event Signal Thread", OS_MID_PRIORITY) != OS_NO_ERROR) { HAVANA_ERROR("Unable to create Display Signal thread\n"); EventSignalThreadRunning = false; EventSignalThreadId = OS_INVALID_THREAD; OS_TerminateEvent (&EventSignalThreadTerminated); OS_TerminateEvent (&EventSignal); OS_TerminateMutex (&Lock); return HavanaError; } } //}}} if (BufferManager == NULL) BufferManager = new BufferManager_Generic_c(); if (BufferManager == NULL) { HAVANA_ERROR("Unable to create buffer manager - insufficient memory\n"); return HavanaNoMemory; } Player->RegisterBufferManager (BufferManager); if (Demultiplexor == NULL) Demultiplexor = new Demultiplexor_Ts_c (); if (Demultiplexor == NULL) { HAVANA_ERROR("Unable to create transport stream demultiplexor\n"); return HavanaNoMemory; } Player->RegisterDemultiplexor (Demultiplexor); DisplayDevice = NULL; if (Player->SetEventSignal (PlayerAllPlaybacks, PlayerAllStreams, EventAllEvents, &EventSignal) != PlayerNoError) { HAVANA_ERROR("Failed to set up player event signal\n"); return HavanaError; } //Player->SpecifySignalledEvents (PlayerAllPlaybacks, PlayerAllStreams, EventAllEvents); // Must be done by every stream return HavanaNoError; }