bring back dshow renderer
This commit is contained in:
+219
-264
@@ -7,345 +7,300 @@
|
||||
|
||||
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
|
||||
Chris Danford
|
||||
Adapted from Nehe tutorial 35
|
||||
Glenn Maynard
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#pragma comment(lib, "winmm.lib")
|
||||
|
||||
// Link with the DirectShow base class libraries
|
||||
#if defined(DEBUG) | defined(_DEBUG)
|
||||
#pragma comment(lib, "baseclasses/debug/strmbasd.lib")
|
||||
#else
|
||||
#pragma comment(lib, "baseclasses/release/strmbase.lib")
|
||||
#endif
|
||||
|
||||
#include "RageMovieTextureHelper.h"
|
||||
|
||||
#include "RageMovieTexture.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageException.h"
|
||||
#include "RageDisplay.h"
|
||||
#include "RageTimer.h"
|
||||
#include "sdl_opengl.h"
|
||||
#include <vfw.h>
|
||||
|
||||
#pragma comment( lib, "vfw32.lib" )
|
||||
|
||||
|
||||
static int power_of_two(int input)
|
||||
{
|
||||
int value = 1;
|
||||
|
||||
while ( value < input ) value <<= 1;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
struct AviRenderer
|
||||
{
|
||||
private:
|
||||
AVISTREAMINFO psi; // Pointer To A Structure Containing Stream Info
|
||||
PAVISTREAM pavi; // Handle To An Open Stream
|
||||
PGETFRAME pgf; // Pointer To A GetFrame Object
|
||||
BITMAPINFOHEADER bmih; // Header Information For DrawDibDraw Decoding
|
||||
int videoWidth;
|
||||
int videoHeight;
|
||||
int frameWidth;
|
||||
int frameHeight;
|
||||
char *pdata; // Pointer To Texture Data
|
||||
int numFrames;
|
||||
float secsIntoPlay; // Will Hold seconds since beginning of this loop
|
||||
float streamSecs; // Will Hold seconds since beginning of this loop
|
||||
HDRAWDIB hdd; // Handle For Our Dib
|
||||
HBITMAP hBitmap; // Handle To A Device Dependant Bitmap
|
||||
HDC hdc; // Creates A Compatible Device Context
|
||||
unsigned char* data; // Pointer To Our Resized Image
|
||||
int last_frame; // true if frame hasn't let been requested
|
||||
bool frame_is_new; // true if frame hasn't let been requested
|
||||
|
||||
public:
|
||||
int GetVideoWidth() { return videoWidth; }
|
||||
int GetVideoHeight() { return videoHeight; }
|
||||
int GetFrameWidth() { return frameWidth; }
|
||||
int GetFrameHeight() { return frameHeight; }
|
||||
void Play() {}
|
||||
void Pause() {}
|
||||
void Stop() {}
|
||||
void SetPosition( float fSeconds ) {}
|
||||
bool IsPlaying() { return true; }
|
||||
|
||||
AviRenderer( CString sFile )
|
||||
{
|
||||
hdc = CreateCompatibleDC(0); // Creates A Compatible Device Context
|
||||
hdd = DrawDibOpen(); // Grab A Device Context For Our Dib
|
||||
|
||||
AVIFileInit(); // Opens The AVIFile Library
|
||||
|
||||
// Opens The AVI Stream
|
||||
if (AVIStreamOpenFromFile(&pavi, sFile, streamtypeVIDEO, 0, OF_READ, NULL) !=0 )
|
||||
throw RageException( "Failed To Open The AVI Stream" );
|
||||
|
||||
AVIStreamInfo(pavi, &psi, sizeof(psi)); // Reads Information About The Stream Into psi
|
||||
videoWidth=psi.rcFrame.right-psi.rcFrame.left; // Width Is Right Side Of Frame Minus Left
|
||||
videoHeight=psi.rcFrame.bottom-psi.rcFrame.top; // Height Is Bottom Of Frame Minus Top
|
||||
frameWidth = power_of_two( videoWidth );
|
||||
frameHeight = power_of_two( videoHeight );
|
||||
|
||||
last_frame = -1;
|
||||
|
||||
numFrames = AVIStreamLength(pavi); // The Last Frame Of The Stream
|
||||
streamSecs = AVIStreamSampleToTime(pavi,numFrames)/1000.f; // Calculate stream length
|
||||
secsIntoPlay = 0;
|
||||
|
||||
bmih.biSize = sizeof (BITMAPINFOHEADER); // Size Of The BitmapInfoHeader
|
||||
bmih.biPlanes = 1; // Bitplanes
|
||||
bmih.biBitCount = 24; // Bits Format We Want (24 Bit, 3 Bytes)
|
||||
bmih.biWidth = frameWidth; // Width We Want (256 Pixels)
|
||||
bmih.biHeight = frameHeight; // Height We Want (256 Pixels)
|
||||
bmih.biCompression = BI_RGB; // Requested Mode = RGB
|
||||
|
||||
hBitmap = CreateDIBSection (hdc, (BITMAPINFO*)(&bmih), DIB_RGB_COLORS, (void**)(&data), NULL, NULL);
|
||||
SelectObject (hdc, hBitmap); // Select hBitmap Into Our Device Context (hdc)
|
||||
|
||||
pgf=AVIStreamGetFrameOpen(pavi, NULL); // Create The PGETFRAME Using Our Request Mode
|
||||
if (pgf==NULL)
|
||||
throw RageException( "Failed To Open The AVI Frame" );
|
||||
}
|
||||
|
||||
~AviRenderer(void) // Properly Closes The Avi File
|
||||
{
|
||||
DeleteObject(hBitmap); // Delete The Device Dependant Bitmap Object
|
||||
DrawDibClose(hdd); // Closes The DrawDib Device Context
|
||||
AVIStreamGetFrameClose(pgf); // Deallocates The GetFrame Resources
|
||||
AVIStreamRelease(pavi); // Release The Stream
|
||||
AVIFileExit(); // Release The File
|
||||
}
|
||||
|
||||
void Update( float fDeltaTime )
|
||||
{
|
||||
secsIntoPlay += fDeltaTime;
|
||||
while( secsIntoPlay > streamSecs )
|
||||
{
|
||||
secsIntoPlay -= streamSecs;
|
||||
}
|
||||
|
||||
int this_frame = secsIntoPlay/streamSecs*numFrames;
|
||||
|
||||
if( last_frame != this_frame )
|
||||
{
|
||||
frame_is_new = true;
|
||||
GetFrame( this_frame );
|
||||
last_frame = this_frame;
|
||||
}
|
||||
}
|
||||
|
||||
void flipIt(void* buffer) // Flips The Red And Blue Bytes (256x256)
|
||||
{
|
||||
void* b = buffer; // Pointer To The Buffer
|
||||
unsigned int numFips = frameWidth*frameHeight;
|
||||
__asm // Assembler Code To Follow
|
||||
{
|
||||
mov ecx, numFips // Set Up A Counter (Dimensions Of Memory Block)
|
||||
mov ebx, b // Points ebx To Our Data (b)
|
||||
label: // Label Used For Looping
|
||||
mov al,[ebx+0] // Loads Value At ebx Into al
|
||||
mov ah,[ebx+2] // Loads Value At ebx+2 Into ah
|
||||
mov [ebx+2],al // Stores Value In al At ebx+2
|
||||
mov [ebx+0],ah // Stores Value In ah At ebx
|
||||
|
||||
add ebx,3 // Moves Through The Data By 3 Bytes
|
||||
dec ecx // Decreases Our Loop Counter
|
||||
jnz label // If Not Zero Jump Back To Label
|
||||
}
|
||||
}
|
||||
|
||||
bool IsNewFrameReady() // returns true only once when a new frame has been taken from the stream
|
||||
{
|
||||
bool bNew = frame_is_new;
|
||||
frame_is_new = false;
|
||||
return bNew;
|
||||
}
|
||||
|
||||
unsigned char* GetData() // Grabs current frame from the stream
|
||||
{
|
||||
Update( 1/60.f );
|
||||
return data;
|
||||
}
|
||||
|
||||
void GetFrame(int frame) // Grabs A Frame From The Stream
|
||||
{
|
||||
LPBITMAPINFOHEADER lpbi; // Holds The Bitmap Header Information
|
||||
lpbi = (LPBITMAPINFOHEADER)AVIStreamGetFrame(pgf, frame); // Grab Data From The AVI Stream
|
||||
pdata=(char *)lpbi+lpbi->biSize+lpbi->biClrUsed * sizeof(RGBQUAD); // Pointer To Data Returned By AVIStreamGetFrame
|
||||
|
||||
SelectObject (hdc, hBitmap); // Select hBitmap Into Our Device Context (hdc)
|
||||
|
||||
// (Skip The Header Info To Get To The Data)
|
||||
// 1:1 copy into the new surface
|
||||
DrawDibDraw (hdd, hdc, 0, 0, videoWidth, videoHeight, lpbi, pdata, 0, 0, videoWidth, videoHeight, 0);
|
||||
|
||||
flipIt(data); // Swap The Red And Blue Bytes (GL Compatability)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// Copy the bits
|
||||
// OPTIMIZATION OPPORTUNITY: Use a video and texture
|
||||
// format that allows a simpler copy than this one.
|
||||
// switch( m_TextureFormat )
|
||||
// {
|
||||
// case D3DFMT_A8R8G8B8:
|
||||
// {
|
||||
// for(int y = 0; y < m_pTexture->GetImageHeight(); y++ ) {
|
||||
// BYTE *pBmpBufferOld = pBmpBuffer;
|
||||
// BYTE *pTxtBufferOld = pTxtBuffer;
|
||||
// for (int x = 0; x < m_pTexture->GetImageWidth(); x++) {
|
||||
// pTxtBuffer[0] = pBmpBuffer[0];
|
||||
// pTxtBuffer[1] = pBmpBuffer[1];
|
||||
// pTxtBuffer[2] = pBmpBuffer[2];
|
||||
// pTxtBuffer[3] = 0xff;
|
||||
// pTxtBuffer += 4;
|
||||
// pBmpBuffer += 3;
|
||||
// }
|
||||
// pBmpBuffer = pBmpBufferOld + m_lVidPitch;
|
||||
// pTxtBuffer = pTxtBufferOld + lTxtPitch;
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
// case D3DFMT_A1R5G5B5:
|
||||
// {
|
||||
// for(int y = 0; y < m_pTexture->GetImageHeight(); y++ ) {
|
||||
// BYTE *pBmpBufferOld = pBmpBuffer;
|
||||
// BYTE *pTxtBufferOld = pTxtBuffer;
|
||||
// for (int x = 0; x < m_pTexture->GetImageWidth(); x++) {
|
||||
// *(WORD *)pTxtBuffer =
|
||||
// 0x8000 +
|
||||
// ((pBmpBuffer[2] & 0xF8) << 7) +
|
||||
// ((pBmpBuffer[1] & 0xF8) << 2) +
|
||||
// (pBmpBuffer[0] >> 3);
|
||||
// pTxtBuffer += 2;
|
||||
// pBmpBuffer += 3;
|
||||
// }
|
||||
// pBmpBuffer = pBmpBufferOld + m_lVidPitch;
|
||||
// pTxtBuffer = pTxtBufferOld + lTxtPitch;
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define NO_SDL_GLEXT
|
||||
#define __glext_h_ /* try harder to stop glext.h from being forced on us by someone else */
|
||||
#include "SDL_opengl.h"
|
||||
#include "glext.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// RageMovieTexture constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
RageMovieTexture::RageMovieTexture( CString sFilePath, RageTexturePrefs prefs ) :
|
||||
RageMovieTexture::RageMovieTexture( const CString &sFilePath, RageTexturePrefs prefs ) :
|
||||
RageTexture( sFilePath, prefs )
|
||||
{
|
||||
LOG->Trace( "RageBitmapTexture::RageBitmapTexture()" );
|
||||
|
||||
m_uGLTextureID = 0;
|
||||
pAviRenderer = new AviRenderer( m_sFilePath );
|
||||
pAviRenderer->Play();
|
||||
m_FilePath = sFilePath;
|
||||
buffer_changed = false;
|
||||
|
||||
m_uGLTextureID = 0;
|
||||
buffer = NULL;
|
||||
|
||||
Create();
|
||||
|
||||
CreateFrameRects();
|
||||
// flip all frame rects because movies are upside down
|
||||
for( unsigned i=0; i<m_TextureCoordRects.size(); i++ )
|
||||
{
|
||||
float fTemp = m_TextureCoordRects[i].top;
|
||||
m_TextureCoordRects[i].top = m_TextureCoordRects[i].bottom;
|
||||
m_TextureCoordRects[i].bottom = fTemp;
|
||||
}
|
||||
|
||||
m_bLoop = true;
|
||||
m_bPlaying = false;
|
||||
}
|
||||
|
||||
RageMovieTexture::~RageMovieTexture()
|
||||
{
|
||||
LOG->Trace("RageMovieTexture::~RageMovieTexture");
|
||||
|
||||
delete pAviRenderer;
|
||||
// Shut down the graph
|
||||
if (m_pGB) {
|
||||
Stop();
|
||||
m_pGB.Release ();
|
||||
}
|
||||
|
||||
delete [] buffer;
|
||||
|
||||
if(m_uGLTextureID)
|
||||
glDeleteTextures(1, &m_uGLTextureID);
|
||||
}
|
||||
|
||||
void RageMovieTexture::Reload( RageTexturePrefs prefs )
|
||||
{
|
||||
DISPLAY->SetTexture(0);
|
||||
// do nothing
|
||||
}
|
||||
|
||||
if(m_uGLTextureID)
|
||||
{
|
||||
glDeleteTextures(1, &m_uGLTextureID);
|
||||
m_uGLTextureID = 0;
|
||||
}
|
||||
|
||||
Create();
|
||||
unsigned int RageMovieTexture::GetGLTextureID()
|
||||
{
|
||||
CheckMovieStatus(); // restart the movie if we reach the end
|
||||
return m_uGLTextureID;
|
||||
}
|
||||
|
||||
void RageMovieTexture::Update(float fDeltaTime)
|
||||
{
|
||||
LockMutex L(buffer_mutex);
|
||||
|
||||
if(!buffer_changed)
|
||||
return;
|
||||
|
||||
buffer_changed = false;
|
||||
|
||||
DISPLAY->SetTexture(this);
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, m_iSourceWidth);
|
||||
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0,
|
||||
0, 0,
|
||||
min(m_iSourceWidth, m_iTextureWidth),
|
||||
min(m_iSourceHeight, m_iTextureHeight),
|
||||
GL_BGR, GL_UNSIGNED_BYTE, buffer);
|
||||
|
||||
glFlush();
|
||||
}
|
||||
|
||||
void HandleDivXError()
|
||||
{
|
||||
/* 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. */
|
||||
throw RageException(
|
||||
"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."
|
||||
);
|
||||
}
|
||||
|
||||
void RageMovieTexture::Create()
|
||||
{
|
||||
if(!m_uGLTextureID)
|
||||
glGenTextures(1, &m_uGLTextureID);
|
||||
HRESULT hr;
|
||||
|
||||
if( FAILED( hr=CoInitialize(NULL) ) )
|
||||
throw RageException( hr_ssprintf(hr, "Could not CoInitialize") );
|
||||
|
||||
/* Cap the max texture size to the hardware max. */
|
||||
m_prefs.iMaxSize = min( m_prefs.iMaxSize, DISPLAY->GetMaxTextureSize() );
|
||||
// Create the filter graph
|
||||
if( FAILED( hr=m_pGB.CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC) ) )
|
||||
throw RageException( hr_ssprintf(hr, "Could not create CLSID_FilterGraph!") );
|
||||
|
||||
// Create the Texture Renderer object
|
||||
CTextureRenderer *pCTR = new CTextureRenderer;
|
||||
|
||||
/* Get a pointer to the IBaseFilter on the TextureRenderer, and add it to the
|
||||
* graph. When m_pGB is released, it will free pFTR. */
|
||||
CComPtr<IBaseFilter> pFTR = pCTR;
|
||||
if( FAILED( hr = m_pGB->AddFilter(pFTR, L"TEXTURERENDERER" ) ) )
|
||||
throw RageException( hr_ssprintf(hr, "Could not add renderer filter to graph!") );
|
||||
|
||||
/* Save information about the source. */
|
||||
m_iSourceWidth = pAviRenderer->GetVideoWidth();
|
||||
m_iSourceHeight = pAviRenderer->GetVideoHeight();
|
||||
// Add the source filter
|
||||
CComPtr<IBaseFilter> pFSrc; // Source Filter
|
||||
WCHAR wFileName[MAX_PATH];
|
||||
MultiByteToWideChar(CP_ACP, 0, m_FilePath.GetString(), -1, wFileName, MAX_PATH);
|
||||
|
||||
// if this fails, it's probably because the user doesn't have DivX installed
|
||||
if( FAILED( hr = m_pGB->AddSourceFilter( wFileName, L"SOURCE", &pFSrc ) ) )
|
||||
{
|
||||
HandleDivXError();
|
||||
throw RageException( hr_ssprintf(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 ) ) )
|
||||
throw RageException( hr_ssprintf(hr, "Could not find input pin!") );
|
||||
|
||||
CComPtr<IPin> pFSrcPinOut; // Source Filter Output Pin
|
||||
if( FAILED( hr = pFSrc->FindPin( L"Output", &pFSrcPinOut ) ) )
|
||||
throw RageException( hr_ssprintf(hr, "Could not find output pin!") );
|
||||
|
||||
// Connect these two filters
|
||||
if( FAILED( hr = m_pGB->Connect( pFSrcPinOut, pFTRPinIn ) ) )
|
||||
{
|
||||
HandleDivXError();
|
||||
throw RageException( hr_ssprintf(hr, "Could not connect pins!") );
|
||||
}
|
||||
|
||||
// Pass us to our TextureRenderer.
|
||||
pCTR->SetRenderTarget(this);
|
||||
|
||||
// The graph is built, now get the set the output video width and height.
|
||||
// The source and image width will always be the same since we can't scale the video
|
||||
m_iSourceWidth = pCTR->GetVidWidth();
|
||||
m_iSourceHeight = pCTR->GetVidHeight();
|
||||
|
||||
/* We've set up the movie, so we know the dimensions we need. Set
|
||||
* up the texture. */
|
||||
CreateTexture();
|
||||
|
||||
// Start the graph running
|
||||
if( !PlayMovie() )
|
||||
throw RageException( "Could not run the DirectShow graph." );
|
||||
}
|
||||
|
||||
void RageMovieTexture::NewData(char *data)
|
||||
{
|
||||
LockMutex L(buffer_mutex);
|
||||
buffer_changed = true;
|
||||
memcpy(buffer, data, m_iSourceWidth * m_iSourceHeight * 3);
|
||||
}
|
||||
|
||||
bool RageMovieTexture::CreateTexture()
|
||||
{
|
||||
/* image size cannot exceed max size */
|
||||
m_iImageWidth = min( m_iSourceWidth, m_prefs.iMaxSize );
|
||||
m_iImageHeight = min( m_iSourceHeight, m_prefs.iMaxSize );
|
||||
|
||||
/* Texture dimensions need to be a power of two; jump to the next. */
|
||||
m_iTextureWidth = power_of_two( m_iSourceWidth );
|
||||
m_iTextureHeight = power_of_two( m_iSourceHeight );
|
||||
m_iTextureWidth = power_of_two(m_iImageWidth);
|
||||
m_iTextureHeight = power_of_two(m_iImageHeight);
|
||||
|
||||
buffer = new char[m_iSourceWidth * m_iSourceHeight * 3];
|
||||
if(!m_uGLTextureID)
|
||||
glGenTextures(1, &m_uGLTextureID);
|
||||
|
||||
glBindTexture( GL_TEXTURE_2D, m_uGLTextureID );
|
||||
DISPLAY->SetTexture(this);
|
||||
|
||||
// Create The Texture
|
||||
unsigned char* data = pAviRenderer->GetData();
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, m_iTextureWidth);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, m_iTextureWidth, m_iTextureHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
|
||||
|
||||
|
||||
CreateFrameRects();
|
||||
|
||||
// invert text coor rect
|
||||
m_TextureCoordRects[0].top = 1 - m_TextureCoordRects[0].top;
|
||||
m_TextureCoordRects[0].bottom = 1 - m_TextureCoordRects[0].bottom;
|
||||
/* Initialize the texture and set it to black. */
|
||||
string buf(m_iTextureWidth*m_iTextureHeight*3, 0);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8,
|
||||
m_iTextureWidth, m_iTextureHeight, 0, GL_BGR, GL_UNSIGNED_BYTE, buf.data());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int RageMovieTexture::GetGLTextureID()
|
||||
bool RageMovieTexture::PlayMovie()
|
||||
{
|
||||
if( pAviRenderer->IsNewFrameReady() )
|
||||
{
|
||||
unsigned char* data = pAviRenderer->GetData();
|
||||
LOG->Trace("RageMovieTexture::PlayMovie()");
|
||||
CComPtr<IMediaControl> pMC;
|
||||
m_pGB.QueryInterface(&pMC);
|
||||
|
||||
// Update The Texture
|
||||
glBindTexture( GL_TEXTURE_2D, m_uGLTextureID );
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, m_iTextureWidth);
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, m_iTextureWidth, m_iTextureHeight, GL_RGB, GL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
// Start the graph running;
|
||||
HRESULT hr;
|
||||
if( FAILED( hr = pMC->Run() ) )
|
||||
throw RageException( hr_ssprintf(hr, "Could not run the DirectShow graph.") );
|
||||
|
||||
return m_uGLTextureID;
|
||||
m_bPlaying = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RageMovieTexture::Update( float fDeltaTime )
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CheckMovieStatus: If the movie has ended, rewind to beginning
|
||||
//-----------------------------------------------------------------------------
|
||||
void RageMovieTexture::CheckMovieStatus()
|
||||
{
|
||||
pAviRenderer->Update( fDeltaTime );
|
||||
long lEventCode;
|
||||
long lParam1;
|
||||
long lParam2;
|
||||
|
||||
// Check for completion events
|
||||
CComPtr<IMediaEvent> pME;
|
||||
m_pGB.QueryInterface(&pME);
|
||||
pME->GetEvent( &lEventCode, &lParam1, &lParam2, 0 );
|
||||
if( EC_COMPLETE == lEventCode && m_bLoop )
|
||||
SetPosition(0);
|
||||
}
|
||||
|
||||
void RageMovieTexture::Play()
|
||||
{
|
||||
pAviRenderer->Play();
|
||||
PlayMovie();
|
||||
}
|
||||
|
||||
void RageMovieTexture::Pause()
|
||||
{
|
||||
pAviRenderer->Pause();
|
||||
LOG->Trace("RageMovieTexture::Pause()");
|
||||
CComPtr<IMediaControl> pMC;
|
||||
m_pGB.QueryInterface(&pMC);
|
||||
|
||||
HRESULT hr;
|
||||
if( FAILED( hr = pMC->Pause() ) )
|
||||
throw RageException( hr_ssprintf(hr, "Could not pause the DirectShow graph.") );
|
||||
|
||||
}
|
||||
|
||||
void RageMovieTexture::Stop()
|
||||
{
|
||||
pAviRenderer->Stop();
|
||||
LOG->Trace("RageMovieTexture::Stop()");
|
||||
CComPtr<IMediaControl> pMC;
|
||||
m_pGB.QueryInterface(&pMC);
|
||||
|
||||
HRESULT hr;
|
||||
if( FAILED( hr = pMC->Stop() ) )
|
||||
throw RageException( hr_ssprintf(hr, "Could not stop the DirectShow graph.") );
|
||||
|
||||
m_bPlaying = false;
|
||||
}
|
||||
|
||||
void RageMovieTexture::SetPosition( float fSeconds )
|
||||
{
|
||||
pAviRenderer->SetPosition( fSeconds );
|
||||
LOG->Trace("RageMovieTexture::Stop()");
|
||||
CComPtr<IMediaPosition> pMP;
|
||||
m_pGB.QueryInterface(&pMP);
|
||||
pMP->put_CurrentPosition(0);
|
||||
}
|
||||
|
||||
bool RageMovieTexture::IsPlaying() const
|
||||
{
|
||||
return pAviRenderer->IsPlaying();
|
||||
return m_bPlaying;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,18 +1,41 @@
|
||||
#pragma once
|
||||
#ifndef RAGEMOVIETEXTURE_H
|
||||
#define RAGEMOVIETEXTURE_H
|
||||
/*
|
||||
-----------------------------------------------------------------------------
|
||||
Class: RageMovieTexture
|
||||
|
||||
Desc: Based on the NeHe tutorial 35
|
||||
Desc: Based on the DShowTextures example in the DX8 SDK.
|
||||
|
||||
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
|
||||
Chris Danford
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "RageTexture.h"
|
||||
/* Don't know why we need this for the headers ... */
|
||||
typedef char TCHAR, *PTCHAR;
|
||||
|
||||
/* Prevent these from using Dbg stuff, which we don't link in. */
|
||||
#ifdef DEBUG
|
||||
#undef DEBUG
|
||||
#undef _DEBUG
|
||||
#define GIVE_BACK_DEBUG
|
||||
#endif
|
||||
|
||||
#include <atlbase.h>
|
||||
|
||||
#ifdef GIVE_BACK_DEBUG
|
||||
#undef GIVE_BACK_DEBUG
|
||||
#define _DEBUG
|
||||
#define DEBUG
|
||||
#endif
|
||||
|
||||
#include "baseclasses/streams.h"
|
||||
|
||||
#include "RageDisplay.h"
|
||||
#include "RageTexture.h"
|
||||
#include "RageThreads.h"
|
||||
|
||||
|
||||
struct AviRenderer; // defined in RageMovieTexture.cpp
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// RageMovieTexture Class Declarations
|
||||
@@ -20,24 +43,50 @@ struct AviRenderer; // defined in RageMovieTexture.cpp
|
||||
class RageMovieTexture : public RageTexture
|
||||
{
|
||||
public:
|
||||
RageMovieTexture( CString sFilePath, RageTexturePrefs prefs );
|
||||
RageMovieTexture( const CString &sFilePath, RageTexturePrefs prefs );
|
||||
virtual ~RageMovieTexture();
|
||||
virtual void Update( float fDeltaTime );
|
||||
virtual void Invalidate() { m_uGLTextureID = 0; }
|
||||
void Update(float fDeltaTime);
|
||||
|
||||
virtual void Reload( RageTexturePrefs prefs );
|
||||
|
||||
virtual void Play();
|
||||
virtual void Pause();
|
||||
virtual void Stop();
|
||||
virtual void SetPosition( float fSeconds );
|
||||
virtual bool IsAMovie() const { return true; };
|
||||
virtual bool IsPlaying() const;
|
||||
void SetLooping(bool looping);
|
||||
void SetLooping(bool looping=true) { m_bLoop = looping; }
|
||||
|
||||
// LPDIRECT3DTEXTURE8 GetBackBuffer() { return m_pd3dTexture[!m_iIndexFrontBuffer]; }
|
||||
// void Flip() { m_iIndexFrontBuffer = !m_iIndexFrontBuffer; }
|
||||
|
||||
void NewData(char *buffer);
|
||||
|
||||
protected:
|
||||
void Create(); // called by constructor and Reload
|
||||
// LPDIRECT3DTEXTURE8 m_pd3dTexture[2]; // double buffered
|
||||
int m_iIndexFrontBuffer; // index of the buffer that should be rendered from - either 0 or 1
|
||||
|
||||
char *buffer;
|
||||
bool buffer_changed;
|
||||
RageMutex buffer_mutex;
|
||||
|
||||
void Create();
|
||||
|
||||
bool CreateTexture();
|
||||
bool PlayMovie();
|
||||
void CheckMovieStatus();
|
||||
|
||||
CString m_FilePath;
|
||||
|
||||
virtual unsigned int GetGLTextureID();
|
||||
unsigned int m_uGLTextureID;
|
||||
|
||||
unsigned int m_uGLTextureID;
|
||||
struct AviRenderer* pAviRenderer;
|
||||
//-----------------------------------------------------------------------------
|
||||
// DirectShow pointers
|
||||
//-----------------------------------------------------------------------------
|
||||
CComPtr<IGraphBuilder> m_pGB; // GraphBuilder
|
||||
bool m_bLoop;
|
||||
bool m_bPlaying;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user