exceptions

This commit is contained in:
Glenn Maynard
2004-11-30 21:17:13 +00:00
parent 4ec61b9812
commit 7d7c06eee4
6 changed files with 63 additions and 46 deletions
@@ -99,8 +99,18 @@ RageMovieTexture *MakeRageMovieTexture(RageTextureID ID)
if (!Driver.CompareNoCase("FFMpeg")) ret = new MovieTexture_FFMpeg(ID);
#endif
if (!Driver.CompareNoCase("Null")) ret = new MovieTexture_Null(ID);
if (!ret)
LOG->Warn("Unknown movie driver name: %s", Driver.c_str());
if( ret == NULL )
{
LOG->Warn( "Unknown movie driver name: %s", Driver.c_str() );
continue;
}
CString sError = ret->Init();
if( sError != "" )
{
LOG->Info( "Couldn't load driver %s: %s", Driver.c_str(), sError.c_str() );
SAFE_DELETE( ret );
}
} catch (const RageException &e) {
LOG->Info("Couldn't load driver %s: %s", Driver.c_str(), e.what());
}
@@ -8,6 +8,7 @@ class RageMovieTexture : public RageTexture
public:
RageMovieTexture( RageTextureID ID ): RageTexture(ID) { }
virtual ~RageMovieTexture() { }
virtual CString Init() { return ""; }
virtual void Update(float fDeltaTime) { }
virtual void Reload() = 0;
@@ -140,13 +140,20 @@ MovieTexture_DShow::MovieTexture_DShow( RageTextureID ID ) :
m_uTexHandle = 0;
buffer = NULL;
}
CString MovieTexture_DShow::Init()
{
CString sError = Create();
if( sError != "" )
return sError;
Create();
CreateFrameRects();
// flip all frame rects because movies are upside down
for( unsigned i=0; i<m_TextureCoordRects.size(); i++ )
swap(m_TextureCoordRects[i].top, m_TextureCoordRects[i].bottom);
return "";
}
/* Hold buffer_lock. If it's held, then the decoding thread is waiting
@@ -270,21 +277,20 @@ void MovieTexture_DShow::Update(float fDeltaTime)
CheckFrame();
}
void PrintCodecError(HRESULT hr, CString s)
CString PrintCodecError( HRESULT hr, CString s )
{
/* Actually, we might need XviD; we might want to look
* at the file and try to figure out if it's something
* common: DIV3, DIV4, DIV5, XVID, or maybe even MPEG2. */
CString err = hr_ssprintf(hr, "%s", s.c_str());
LOG->Warn(
return
ssprintf(
"There was an error initializing a movie: %s.\n"
"Could not locate the DivX video codec.\n"
"DivX is required to movie textures and must\n"
"be installed before running the application.\n\n"
"Please visit http://www.divx.com to download the latest version.",
err.c_str())
);
err.c_str() );
}
CString MovieTexture_DShow::GetActiveFilterList()
@@ -314,7 +320,7 @@ CString MovieTexture_DShow::GetActiveFilterList()
return ret;
}
void MovieTexture_DShow::Create()
CString MovieTexture_DShow::Create()
{
RageTextureID actualID = GetID();
@@ -347,26 +353,20 @@ void MovieTexture_DShow::Create()
* if another program has it open and locked. Missing codecs probably won't
* show up until Connect(). */
if( FAILED( hr = m_pGB->AddSourceFilter( wFileName.c_str(), wFileName.c_str(), &pFSrc ) ) )
{
PrintCodecError(hr, "Could not create source filter to graph!");
return; // survive and don't Run the graph.
}
return PrintCodecError( hr, "Could not create source filter to graph!" );
// Find the source's output and the renderer's input
CComPtr<IPin> pFTRPinIn; // Texture Renderer Input Pin
if( FAILED( hr = pFTR->FindPin( L"In", &pFTRPinIn ) ) )
RageException::Throw( hr_ssprintf(hr, "Could not find input pin!") );
return hr_ssprintf(hr, "Could not find input pin" );
CComPtr<IPin> pFSrcPinOut; // Source Filter Output Pin
if( FAILED( hr = pFSrc->FindPin( L"Output", &pFSrcPinOut ) ) )
RageException::Throw( hr_ssprintf(hr, "Could not find output pin!") );
return hr_ssprintf( hr, "Could not find output pin" );
// Connect these two filters
if( FAILED( hr = m_pGB->Connect( pFSrcPinOut, pFTRPinIn ) ) )
{
PrintCodecError(hr, "Could not connect pins!");
return; // survive and don't Run the graph.
}
return PrintCodecError( hr, "Could not connect pins" );
LOG->Trace( "Filters: %s", GetActiveFilterList().c_str() );
@@ -406,6 +406,8 @@ void MovieTexture_DShow::Create()
// Start the graph running
Play();
return "";
}
@@ -35,6 +35,8 @@ class MovieTexture_DShow : public RageMovieTexture
public:
MovieTexture_DShow( RageTextureID ID );
virtual ~MovieTexture_DShow();
CString Init();
/* only called by RageTextureManager::InvalidateTextures */
void Invalidate() { m_uTexHandle = 0; }
void Update(float fDeltaTime);
@@ -45,7 +47,6 @@ public:
virtual void Pause();
virtual void SetPosition( float fSeconds );
virtual void SetPlaybackRate( float fRate );
virtual bool IsPlaying() const { return m_bPlaying; }
void SetLooping(bool looping=true) { m_bLoop = looping; }
@@ -55,7 +56,7 @@ private:
const char *buffer;
RageSemaphore buffer_lock, buffer_finished;
void Create();
CString Create();
void CreateTexture();
void SkipUpdates();
@@ -399,7 +399,6 @@ MovieTexture_FFMpeg::MovieTexture_FFMpeg( RageTextureID ID ):
RageMovieTexture( ID ),
m_BufferFinished( "BufferFinished", 0 )
{
try {
LOG->Trace( "MovieTexture_FFMpeg::MovieTexture_FFMpeg(%s)", ID.filename.c_str() );
FixLilEndian();
@@ -416,27 +415,34 @@ try {
m_Clock = 0;
m_FrameSkipMode = false;
m_bThreaded = PREFSMAN->m_bThreadedMovieDecode;
}
CString MovieTexture_FFMpeg::Init()
{
CString sError = CreateDecoder();
if( sError != "" )
return sError;
CreateDecoder();
LOG->Trace("Bitrate: %i", decoder->m_stream->codec.bit_rate );
LOG->Trace("Codec pixel format: %s", avcodec::avcodec_get_pix_fmt_name(decoder->m_stream->codec.pix_fmt) );
/* Decode one frame, to guarantee that the texture is drawn when this function returns. */
int ret = decoder->GetFrame();
if( ret == -1 )
RageException::ThrowNonfatal( "%s: error getting first frame", GetID().filename.c_str() );
return ssprintf( "%s: error getting first frame", GetID().filename.c_str() );
if( ret == 0 )
{
/* There's nothing there. */
RageException::ThrowNonfatal( "%s: EOF getting first frame", GetID().filename.c_str() );
return ssprintf( "%s: EOF getting first frame", GetID().filename.c_str() );
}
m_ImageWaiting = FRAME_DECODED;
CreateTexture();
LOG->Trace("Resolution: %ix%i (%ix%i, %ix%i)",
LOG->Trace( "Resolution: %ix%i (%ix%i, %ix%i)",
m_iSourceWidth, m_iSourceHeight,
m_iImageWidth, m_iImageHeight, m_iTextureWidth, m_iTextureHeight);
LOG->Trace("Texture pixel format: %i", m_AVTexfmt );
m_iImageWidth, m_iImageHeight, m_iTextureWidth, m_iTextureHeight );
LOG->Trace( "Texture pixel format: %i", m_AVTexfmt );
CreateFrameRects();
@@ -446,17 +452,8 @@ try {
CHECKPOINT;
StartThread();
}
catch(...)
{
StopThread();
DestroyDecoder();
DestroyTexture();
delete decoder;
throw;
};
return "";
}
MovieTexture_FFMpeg::~MovieTexture_FFMpeg()
@@ -570,37 +567,39 @@ void MovieTexture_FFMpeg::RegisterProtocols()
avcodec::register_protocol( &RageProtocol );
}
void MovieTexture_FFMpeg::CreateDecoder()
CString MovieTexture_FFMpeg::CreateDecoder()
{
RegisterProtocols();
int ret = avcodec::av_open_input_file( &decoder->m_fctx, "rage://" + GetID().filename, NULL, 0, NULL );
if( ret < 0 )
RageException::Throw( averr_ssprintf(ret, "AVCodec: Couldn't open \"%s\"", GetID().filename.c_str()) );
return ssprintf( averr_ssprintf(ret, "AVCodec: Couldn't open \"%s\"", GetID().filename.c_str()) );
ret = avcodec::av_find_stream_info( decoder->m_fctx );
if ( ret < 0 )
RageException::Throw( averr_ssprintf(ret, "AVCodec (%s): Couldn't find codec parameters", GetID().filename.c_str()) );
return ssprintf( averr_ssprintf(ret, "AVCodec (%s): Couldn't find codec parameters", GetID().filename.c_str()) );
avcodec::AVStream *stream = FindVideoStream( decoder->m_fctx );
if ( stream == NULL )
RageException::Throw( "AVCodec (%s): Couldn't find any video streams", GetID().filename.c_str() );
return ssprintf( "AVCodec (%s): Couldn't find any video streams", GetID().filename.c_str() );
if( stream->codec.codec_id == avcodec::CODEC_ID_NONE )
RageException::ThrowNonfatal( "AVCodec (%s): Unsupported codec %08x", GetID().filename.c_str(), stream->codec.codec_tag );
return ssprintf( "AVCodec (%s): Unsupported codec %08x", GetID().filename.c_str(), stream->codec.codec_tag );
avcodec::AVCodec *codec = avcodec::avcodec_find_decoder( stream->codec.codec_id );
if( codec == NULL )
RageException::Throw( "AVCodec (%s): Couldn't find decoder %i", GetID().filename.c_str(), stream->codec.codec_id );
return ssprintf( "AVCodec (%s): Couldn't find decoder %i", GetID().filename.c_str(), stream->codec.codec_id );
LOG->Trace("Opening codec %s", codec->name );
ret = avcodec::avcodec_open( &stream->codec, codec );
if ( ret < 0 )
RageException::Throw( averr_ssprintf(ret, "AVCodec (%s): Couldn't open codec \"%s\"", GetID().filename.c_str(), codec->name) );
return ssprintf( averr_ssprintf(ret, "AVCodec (%s): Couldn't open codec \"%s\"", GetID().filename.c_str(), codec->name) );
/* Don't set this until we successfully open stream->codec, so we don't try to close it
* on an exception unless it was really opened. */
decoder->m_stream = stream;
return "";
}
@@ -754,7 +753,9 @@ bool MovieTexture_FFMpeg::DecodeFrame()
/* Restart. */
DestroyDecoder();
CreateDecoder();
CString sError = CreateDecoder();
if( sError != "" )
RageException::Throw( "Error rewinding stream %s: %s", GetID().filename.c_str(), sError.c_str() );
decoder->Init();
m_Clock = -fDelay;
@@ -20,6 +20,8 @@ class MovieTexture_FFMpeg: public RageMovieTexture
public:
MovieTexture_FFMpeg( RageTextureID ID );
virtual ~MovieTexture_FFMpeg();
CString Init();
/* only called by RageTextureManager::InvalidateTextures */
void Invalidate() { m_uTexHandle = 0; }
void Update(float fDeltaTime);
@@ -79,7 +81,7 @@ private:
void ConvertFrame();
void UpdateFrame();
void CreateDecoder();
CString CreateDecoder();
void CreateTexture();
void DestroyDecoder();
void DestroyTexture();