//============================================================================= // Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. // // File: fmvplayer.cpp // // Description: Implement FMVPlayer // // History: 17/04/2002 + Created -- NAME // //============================================================================= //======================================== // System Includes //======================================== // Foundation Tech #include #include #include #include #include #include #include #include //======================================== // Project Includes //======================================== #include
#include
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //****************************************************************************** // // Global Data, Local Data, Local Classes // //****************************************************************************** #define MOVIE_MAX_WIDTH 640 #ifdef PAL #define MOVIE_MAX_HEIGHT 512 #else #define MOVIE_MAX_HEIGHT 480 #endif #define MOVIE_ENCODED_VIDEO_BUFFER_SIZE ( 512 * 1024 ) #define MOVIE_PRIMARY_AUDIO_BUFFER_SIZE 2000 #define MOVIE_SECONDARY_AUDIO_BUFFER_SIZE 1000 #define MOVIE_AUDIO_BUFFER_SIZE_TYPE IRadSoundHalAudioFormat::Milliseconds #ifdef RAD_XBOX static const float VOLUME_MULTIPLIER = 0.75f; #else static const float VOLUME_MULTIPLIER = 1.0f; #endif //****************************************************************************** // // Public Member Functions // //****************************************************************************** //============================================================================== // FMVPlayer::FMVPlayer //============================================================================== // Description: Constructor. // // Parameters: None. // // Return: N/A. // //============================================================================== FMVPlayer::FMVPlayer() : m_refIRadMoviePlayer( NULL ), mElapsedTime( 0.0f ), mFadeOut(-1.0f) { m_UserInputHandler = new FMVUserInputHandler; m_UserInputHandler->AddRef(); } //============================================================================== // FMVPlayer::~FMVPlayer //============================================================================== // Description: Destructor. // // Parameters: None. // // Return: N/A. // //============================================================================== FMVPlayer::~FMVPlayer() { m_UserInputHandler->Release(); m_UserInputHandler = NULL; if( m_refIRadMoviePlayer != NULL ) { m_refIRadMoviePlayer->Unload( ); m_refIRadMoviePlayer = NULL; } } //============================================================================= // FMVPlayer::LoadData //============================================================================= // Description: Comment // // Parameters: ( const char* fileName, bool bInInventory ) // // Return: void // //============================================================================= void FMVPlayer::LoadData( const char* fileName, bool bInInventory, void* pUserData ) { if( GetState() == ANIM_IDLE || GetState() == ANIM_LOADING ) { GetSoundManager()->StopForMovie(); while( !( GetSoundManager()->IsStoppedForMovie() ) ) { ::radMovieService2( ); ::radFileService( ); SoundManager::GetInstance()->Update(); SoundManager::GetInstance()->UpdateOncePerFrame( 0, NUM_CONTEXTS, false ); } GameMemoryAllocator allocator = GMA_LEVEL_MOVIE; unsigned int audioIndex = 0; FMVEvent::FMVEventData* data = reinterpret_cast(pUserData); if( data ) { allocator = data->Allocator; if ( allocator >= GMA_ANYWHERE_IN_LEVEL ) { ::SetupAllocatorSearch( allocator ); allocator = GMA_ALLOCATOR_SEARCH; } audioIndex = data->AudioIndex; if( data->KillMusic ) { GetEventManager()->TriggerEvent( EVENT_STOP_THE_MUSIC ); } } HeapMgr()->PushHeap( allocator ); Initialize( allocator ); m_refIRadMoviePlayer->Load( fileName, audioIndex ); mDriveFinished = false; Game::GetInstance()->GetPlatform()->GetHostDrive()->AddCompletionCallback( this, 0 ); while( !mDriveFinished ) { ::radMovieService2( ); ::radFileService( ); SoundManager::GetInstance()->Update(); SoundManager::GetInstance()->UpdateOncePerFrame( 0, NUM_CONTEXTS, false ); } HeapMgr()->PopHeap(allocator); SetState( ANIM_LOADED ); } } //============================================================================= // FMVPlayer::Play //============================================================================= // Description: Comment // // Parameters: () // // Return: void // //============================================================================= void FMVPlayer::Play() { if(( GetState() == ANIM_LOADED ) && ( m_refIRadMoviePlayer != NULL )) { AnimationPlayer::Play(); FadeScreen(0.0f); p3d::context->SwapBuffers(); p3d::display->SetForceVSync(true); #ifdef FINAL m_UserInputHandler->SetEnabled(GetSkippable()); #endif // register GUI user input handler for all controllers for( unsigned i = 0; i < GetInputManager()->GetMaxControllers(); i++ ) { GetInputManager()->RegisterMappable( i, m_UserInputHandler ); } mElapsedTime = 0.0f; mFadeOut = -1.0f; mMovieVolume = VOLUME_MULTIPLIER; if(GetGameFlow()->GetCurrentContext() != CONTEXT_BOOTUP) { mMovieVolume *= GetSoundManager()->GetDialogueVolume(); } m_refIRadMoviePlayer->SetVolume(mMovieVolume); m_refIRadMoviePlayer->Play( ); } } /*============================================================================= Causes the movie to begin fading out. When it's finished fading out it stops. Fade out time is hard coded right now to half a second. =============================================================================*/ void FMVPlayer::Abort(void) { if(mFadeOut == -1.0f) { mFadeOut = 1.0f; } } //============================================================================= // FMVPlayer::Stop //============================================================================= // Description: Comment // // Parameters: () // // Return: void // //============================================================================= void FMVPlayer::Stop() { // Force a clear screen. FadeScreen(0.0f); p3d::context->SwapBuffers(); p3d::display->SetForceVSync(false); if( this->IsPlaying() && m_refIRadMoviePlayer != NULL ) { for( unsigned i = 0; i < GetInputManager()->GetMaxControllers(); i++ ) { GetInputManager()->UnregisterMappable( i, m_UserInputHandler ); } m_UserInputHandler->SetEnabled(true); GetSoundManager()->ResumeAfterMovie(); AnimationPlayer::Stop(); ClearData(); } mFadeOut = -1.0f; } //============================================================================= // FMVPlayer::ForceStop //============================================================================= // Description: Comment // // Parameters: () // // Return: void // //============================================================================= #ifdef RAD_WIN32 void FMVPlayer::ForceStop() { // Force a clear screen. if( this->IsPlaying() && m_refIRadMoviePlayer != NULL ) { for( unsigned i = 0; i < GetInputManager()->GetMaxControllers(); i++ ) { GetInputManager()->UnregisterMappable( i, m_UserInputHandler ); } m_UserInputHandler->SetEnabled(true); GetSoundManager()->ResumeAfterMovie(); AnimationPlayer::Stop(); ClearData(); } } #endif //============================================================================= // FMVPlayer::Pause //============================================================================= void FMVPlayer::Pause() { if( this->IsPlaying() && m_refIRadMoviePlayer != NULL ) { m_refIRadMoviePlayer->Pause( ); } } //============================================================================= // FMVPlayer::UnPause //============================================================================= void FMVPlayer::UnPause() { if( this->IsPlaying() && m_refIRadMoviePlayer != NULL ) { m_refIRadMoviePlayer->Play( ); } } //****************************************************************************** // // Private Member Functions // //****************************************************************************** //============================================================================= // FMVPlayer::Initialize //============================================================================= // Description: Comment // // Parameters: () // // Return: void // //============================================================================= void FMVPlayer::Initialize( radMemoryAllocator Allocator ) { // // Initialize the movie player. // // This is where all the memory will be allocated. // ref< IRadMovieRenderLoop > refIRadMovieRenderLoop = this; ref< IRadMovieRenderStrategy > refIRadMovieRenderStrategy = ::radMovieSimpleFullScreenRenderStrategyCreate( Allocator ); // Note that there is a problem if we start creating multiple movie players //(why would we ever do this???). The allocator is stored as a single global //value in the movieplayer (binkmovieplayer.cpp for instance) and it is set //when you call ::radMoviePlayerCreate2(). So if you make multiple calls //the most recent allocator you pass is the one used. m_refIRadMoviePlayer = ::radMoviePlayerCreate2( Allocator ); rAssert( m_refIRadMoviePlayer != NULL ); #if defined(RAD_XBOX) || defined(RAD_GAMECUBE) || defined(RAD_WIN32) m_refIRadMoviePlayer->Initialize( refIRadMovieRenderLoop, refIRadMovieRenderStrategy ); #else // PS2 m_refIRadMoviePlayer->Initialize( refIRadMovieRenderLoop, refIRadMovieRenderStrategy, MOVIE_MAX_WIDTH, MOVIE_MAX_HEIGHT, MOVIE_ENCODED_VIDEO_BUFFER_SIZE, MOVIE_PRIMARY_AUDIO_BUFFER_SIZE, MOVIE_SECONDARY_AUDIO_BUFFER_SIZE, MOVIE_AUDIO_BUFFER_SIZE_TYPE ); #endif } //============================================================================= // FMVPlayer::DoRender //============================================================================= // Description: Comment // // Parameters: () // // Return: void // //============================================================================= void FMVPlayer::DoRender() { IRadMoviePlayer2::State state = m_refIRadMoviePlayer->GetState( ); mFrameReady = false; while( !mFrameReady && (state != IRadMoviePlayer2::NoData)) { ::radMovieService2( ); ::radSoundHalSystemGet( )->Service( ); // ::radSoundHalSystemGet( )->ServiceOncePerFrame( ); ::radFileService( ); state = m_refIRadMoviePlayer->GetState( ); if ( state == IRadMoviePlayer2::ReadyToPlay ) { // [ps] Here we are paused, so fall out to the regular game. break; } } if((mFadeOut <= 0.0f) && (mFadeOut != -1.0f)) { Stop(); } if( (state == IRadMoviePlayer2::NoData) || ( m_refIRadMoviePlayer == NULL) ) { Stop(); } } void FMVPlayer::IterateLoop( IRadMoviePlayer2* pIRadMoviePlayer ) { rAssert( pIRadMoviePlayer != NULL ); pIRadMoviePlayer->Render(); if(mFadeOut > 0.0f ) { pIRadMoviePlayer->SetVolume(mMovieVolume * mFadeOut); FadeScreen(mFadeOut); } float deltaTime = mElapsedTime; mElapsedTime = pIRadMoviePlayer->GetCurrentFrameNumber() / pIRadMoviePlayer->GetFrameRate(); if(mFadeOut > 0.0f ) { deltaTime = mElapsedTime - deltaTime; mFadeOut -= deltaTime * 2.0f; // Half second fade. } mFrameReady = true; } //============================================================================= // FMVPlayer::Finalize //============================================================================= // Description: Comment // // Parameters: () // // Return: void // //============================================================================= void FMVPlayer::ClearData() { // // Free up the radmovie movie player stuff // if( m_refIRadMoviePlayer != NULL ) { // I think there is a case where the movie player doesn't shut down properly because the //decode buffer is still in use as a texture in the draw pipeline, preventing it from being //freed. p3d::pddi->DrawSync(); m_refIRadMoviePlayer->Unload( ); m_refIRadMoviePlayer = NULL; mDriveFinished = false; Game::GetInstance()->GetPlatform()->GetHostDrive()->AddCompletionCallback( this, 0 ); while( !mDriveFinished ) { ::radMovieService2( ); ::radFileService( ); SoundManager::GetInstance()->Update(); SoundManager::GetInstance()->UpdateOncePerFrame( 0, NUM_CONTEXTS, false ); } } AnimationPlayer::ClearData(); } void FMVPlayer::OnDriveOperationsComplete( void* pUserData ) { mDriveFinished = true; } void FMVPlayer::FadeScreen(float Alpha) { tColour c; c.Set( 0, 0, 0, int(0xFF * (1.0f - rmt::Clamp(Alpha, 0.0f, 1.0f))) ); p3d::stack->Push(); bool oldZWrite = p3d::pddi->GetZWrite(); pddiCompareMode oldZComp = p3d::pddi->GetZCompare(); if( oldZWrite ) { p3d::pddi->SetZWrite( false ); } if( oldZComp != PDDI_COMPARE_ALWAYS ) { p3d::pddi->SetZCompare( PDDI_COMPARE_ALWAYS ); } p3d::stack->LoadIdentity(); p3d::pddi->SetProjectionMode( PDDI_PROJECTION_ORTHOGRAPHIC ); pddiColour oldAmbient = p3d::pddi->GetAmbientLight(); p3d::pddi->SetAmbientLight( pddiColour( 255, 255, 255 ) ); pddiPrimStream* overlay = 0; pddiShader* overlayShader = BootupContext::GetInstance()->GetSharedShader(); rAssert( overlayShader ); overlayShader->SetInt( PDDI_SP_BLENDMODE, PDDI_BLEND_ALPHA ); overlayShader->SetInt( PDDI_SP_ISLIT, 0 ); overlayShader->SetInt( PDDI_SP_SHADEMODE, PDDI_SHADE_FLAT ); overlay = p3d::pddi->BeginPrims( overlayShader, PDDI_PRIM_TRISTRIP, PDDI_V_C, 4 ); overlay->Colour( c ); overlay->Coord( 0.5f, -0.5f, 1.0f ); overlay->Colour( c ); overlay->Coord( -0.5f, -0.5f, 1.0f ); overlay->Colour( c ); overlay->Coord( 0.5f, 0.5f, 1.0f ); overlay->Colour( c ); overlay->Coord( -0.5f, 0.5f, 1.0f ); p3d::pddi->EndPrims( overlay ); p3d::pddi->SetProjectionMode(PDDI_PROJECTION_PERSPECTIVE); p3d::pddi->SetAmbientLight( oldAmbient ); if( oldZWrite ) { p3d::pddi->SetZWrite( true ); } if( oldZComp != PDDI_COMPARE_ALWAYS ) { p3d::pddi->SetZCompare( oldZComp ); } p3d::stack->Pop(); }