Beispiel #1
0
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;
}
Beispiel #2
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;
}