Implement looping.
This commit is contained in:
Glenn Maynard
2003-09-02 06:08:02 +00:00
parent 834195f462
commit 7f96a91be9
2 changed files with 68 additions and 41 deletions
@@ -7,7 +7,6 @@
#include "SDL_utils.h" #include "SDL_utils.h"
#include "SDL_endian.h" #include "SDL_endian.h"
/* TODO: implement m_bLoop */
#if defined(_WIN32) #if defined(_WIN32)
#pragma comment(lib, "ffmpeg/lib/avcodec.lib") #pragma comment(lib, "ffmpeg/lib/avcodec.lib")
@@ -135,8 +134,32 @@ MovieTexture_FFMpeg::MovieTexture_FFMpeg( RageTextureID ID ):
m_BufferFinished = SDL_CreateSemaphore(0); m_BufferFinished = SDL_CreateSemaphore(0);
m_OneFrameDecoded = SDL_CreateSemaphore(0); m_OneFrameDecoded = SDL_CreateSemaphore(0);
Create(); CreateDecoder();
LOG->Trace("Codec: %s", m_codec->name );
LOG->Trace("Resolution: %ix%i (%ix%i, %ix%i)",
m_iSourceWidth, m_iSourceHeight,
m_iImageWidth, m_iImageHeight, m_iTextureWidth, m_iTextureHeight);
LOG->Trace("Bitrate: %i", m_stream->codec.bit_rate );
LOG->Trace("Codec pixel format: %i", m_stream->codec.pix_fmt );
CreateTexture();
StartThread();
CreateFrameRects(); CreateFrameRects();
/* Wait until we decode one frame, to guarantee that the texture is
* drawn when this function returns. */
ASSERT( m_State == PAUSE_DECODER );
CHECKPOINT;
m_State = PLAYING_ONE;
SDL_SemWait( m_OneFrameDecoded );
CHECKPOINT;
m_State = PAUSE_DECODER;
CheckFrame();
CHECKPOINT;
Play();
} }
static CString averr_ssprintf( int err, const char *fmt, ... ) static CString averr_ssprintf( int err, const char *fmt, ... )
@@ -164,13 +187,10 @@ static CString averr_ssprintf( int err, const char *fmt, ... )
} }
void MovieTexture_FFMpeg::CreateDecoder()
void MovieTexture_FFMpeg::Create()
{ {
m_Timer = 0; m_Timer = 0;
ASSERT( m_State == DECODER_QUIT );
RageTextureID actualID = GetID(); RageTextureID actualID = GetID();
actualID.iAlphaBits = 0; actualID.iAlphaBits = 0;
@@ -209,40 +229,22 @@ void MovieTexture_FFMpeg::Create()
/* Texture dimensions need to be a power of two; jump to the next. */ /* Texture dimensions need to be a power of two; jump to the next. */
m_iTextureWidth = power_of_two(m_iImageWidth); m_iTextureWidth = power_of_two(m_iImageWidth);
m_iTextureHeight = power_of_two(m_iImageHeight); m_iTextureHeight = power_of_two(m_iImageHeight);
LOG->Trace("Codec: %s", m_codec->name );
LOG->Trace("Resolution: %ix%i (%ix%i, %ix%i)",
m_iSourceWidth, m_iSourceHeight,
m_iImageWidth, m_iImageHeight, m_iTextureWidth, m_iTextureHeight);
LOG->Trace("Bitrate: %i", m_stream->codec.bit_rate );
LOG->Trace("Codec pixel format: %i", m_stream->codec.pix_fmt );
/* We've set up the movie, so we know the dimensions we need. Set
* up the texture. */
CreateTexture();
StartThread();
/* Wait until we decode one frame, to guarantee that the texture is
* drawn when this function returns. */
ASSERT( m_State == PAUSE_DECODER );
CHECKPOINT;
m_State = PLAYING_ONE;
SDL_SemWait( m_OneFrameDecoded );
CHECKPOINT;
m_State = PAUSE_DECODER;
CheckFrame();
CHECKPOINT;
Play();
} }
void MovieTexture_FFMpeg::Destroy()
{
StopThread();
/* Delete the decoder. The decoding thread must be stopped. */
void MovieTexture_FFMpeg::DestroyDecoder()
{
avcodec::avcodec_close( &m_stream->codec ); avcodec::avcodec_close( &m_stream->codec );
avcodec::av_close_input_file( m_fctx ); m_fctx = NULL; avcodec::av_close_input_file( m_fctx );
m_fctx = NULL;
m_stream = NULL;
}
/* Delete the surface and texture. The decoding thread must be stopped, and this
* is normally done after destroying the decoder. */
void MovieTexture_FFMpeg::DestroyTexture()
{
if( m_img ) if( m_img )
{ {
SDL_FreeSurface( m_img ); SDL_FreeSurface( m_img );
@@ -365,6 +367,24 @@ void MovieTexture_FFMpeg::DecoderThread()
{ {
CHECKPOINT; CHECKPOINT;
int ret = avcodec::av_read_packet(m_fctx, &pkt); int ret = avcodec::av_read_packet(m_fctx, &pkt);
if( ret == -1 )
{
/* EOF. */
if( !m_bLoop )
return;
/* Restart. */
DestroyDecoder();
CreateDecoder();
CurrentTimestamp = Last_IP_Timestamp = 0;
GetNextTimestamp = true;
FrameSkipMode = false;
Frame = 0;
LastFrameDelay = 0;
continue;
}
if( ret < 0 ) if( ret < 0 )
{ {
/* XXX ? */ /* XXX ? */
@@ -518,7 +538,9 @@ void MovieTexture_FFMpeg::DecoderThread()
MovieTexture_FFMpeg::~MovieTexture_FFMpeg() MovieTexture_FFMpeg::~MovieTexture_FFMpeg()
{ {
Destroy(); StopThread();
DestroyDecoder();
DestroyTexture();
SDL_DestroySemaphore( m_BufferFinished ); SDL_DestroySemaphore( m_BufferFinished );
SDL_DestroySemaphore( m_OneFrameDecoded ); SDL_DestroySemaphore( m_OneFrameDecoded );
@@ -615,8 +637,12 @@ void MovieTexture_FFMpeg::SetPosition( float fSeconds )
LOG->Trace( "Seek to %f (from %f)", fSeconds, m_Position ); LOG->Trace( "Seek to %f (from %f)", fSeconds, m_Position );
State OldState = m_State; State OldState = m_State;
Destroy(); /* Recreate the decoder. Do this without touching the actual texture, and without waiting
Create(); * for the first frame to be decoded, so we don't take too long. */
StopThread();
DestroyDecoder();
CreateDecoder();
StartThread();
m_State = OldState; m_State = OldState;
} }
@@ -108,9 +108,10 @@ private:
void DecoderThread(); void DecoderThread();
RageThread m_DecoderThread; RageThread m_DecoderThread;
void Create(); void CreateDecoder();
void Destroy();
void CreateTexture(); void CreateTexture();
void DestroyDecoder();
void DestroyTexture();
void CheckFrame(); void CheckFrame();
void StartThread(); void StartThread();
void StopThread(); void StopThread();