exceptions
This commit is contained in:
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user