Remove dshow movie rendering code.
It hasn't been built into the binary in years, not since before forking itgmania. https://github.com/itgmania/itgmania/blob/5d4f9dcb07493ed4c51d6be23e9b41978162305a/src/CMakeData-arch.cmake#L81-L91 https://github.com/stepmania/stepmania/blob/d55acb1ba26f1c5b5e3048d6d6c0bd116625216f/src/Makefile.am#L388 This helps to consolidate the movie rendering code into one main rendering path.
This commit is contained in:
@@ -1,582 +0,0 @@
|
||||
#include "global.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
/* XXX register thread */
|
||||
#pragma comment(lib, "winmm.lib")
|
||||
|
||||
// Link with the DirectShow base class libraries
|
||||
#if defined(DEBUG)
|
||||
#pragma comment(lib, "baseclasses/debug/strmbasd.lib")
|
||||
#else
|
||||
#pragma comment(lib, "baseclasses/release/strmbase.lib")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "MovieTexture_DShowHelper.h"
|
||||
#include "MovieTexture_DShow.h"
|
||||
|
||||
/* for TEXTUREMAN->GetTextureColorDepth() */
|
||||
#include "RageTextureManager.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageException.h"
|
||||
#include "RageSurface.h"
|
||||
#include "arch/Dialog/Dialog.h"
|
||||
#include "archutils/Win32/DirectXHelpers.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <vfw.h> /* for GetVideoCodecDebugInfo */
|
||||
#if defined(_MSC_VER)
|
||||
#pragma comment(lib, "vfw32.lib")
|
||||
#endif
|
||||
|
||||
RageMovieTexture *RageMovieTextureDriver_DShow::Create( RageTextureID ID, RString &sError )
|
||||
{
|
||||
MovieTexture_DShow *pRet = new MovieTexture_DShow( ID );
|
||||
sError = pRet->Init();
|
||||
if( !sError.empty() )
|
||||
SAFE_DELETE( pRet );
|
||||
return pRet;
|
||||
}
|
||||
|
||||
REGISTER_MOVIE_TEXTURE_CLASS( DShow );
|
||||
|
||||
static RString FourCCToString( int fcc )
|
||||
{
|
||||
char c[4];
|
||||
c[0] = char((fcc >> 0) & 0xFF);
|
||||
c[1] = char((fcc >> 8) & 0xFF);
|
||||
c[2] = char((fcc >> 16) & 0xFF);
|
||||
c[3] = char((fcc >> 24) & 0xFF);
|
||||
|
||||
RString s;
|
||||
for( int i = 0; i < 4; ++i )
|
||||
s += clamp( c[i], '\x20', '\x7e' );
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static void CheckCodecVersion( RString codec, RString desc )
|
||||
{
|
||||
if( !codec.CompareNoCase("DIVX") )
|
||||
{
|
||||
/* "DivX 5.0.5 Codec" */
|
||||
Regex GetDivXVersion;
|
||||
|
||||
int major, minor, rev;
|
||||
if( sscanf( desc, "DivX %i.%i.%i", &major, &minor, &rev ) != 3 &&
|
||||
sscanf( desc, "DivX Pro %i.%i.%i", &major, &minor, &rev ) != 3 )
|
||||
{
|
||||
LOG->Warn( "Couldn't parse DivX version \"%s\"", desc.c_str() );
|
||||
return;
|
||||
}
|
||||
|
||||
/* 5.0.0 through 5.0.4 are old and cause crashes. Warn. */
|
||||
if( major == 5 && minor == 0 && rev < 5 )
|
||||
{
|
||||
Dialog::OK(
|
||||
ssprintf("The version of DivX installed, %i.%i.%i, is out of date and may\n"
|
||||
"cause instability. Please upgrade to DivX 5.0.5 or newer, available at:\n"
|
||||
"\n"
|
||||
"http://www.divx.com/", major, minor, rev),
|
||||
desc );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void GetVideoCodecDebugInfo()
|
||||
{
|
||||
ICINFO info = { sizeof(ICINFO) };
|
||||
LOG->Info( "Video codecs:" );
|
||||
CHECKPOINT;
|
||||
int i;
|
||||
for( i=0; ICInfo(ICTYPE_VIDEO, i, &info); ++i )
|
||||
{
|
||||
CHECKPOINT;
|
||||
if( FourCCToString(info.fccHandler) == "ASV1" )
|
||||
{
|
||||
/* Broken. */
|
||||
LOG->Info("%i: %s: skipped", i, FourCCToString(info.fccHandler).c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG->Trace( "Scanning codec %s", FourCCToString(info.fccHandler).c_str() );
|
||||
CHECKPOINT;
|
||||
HIC hic = ICOpen( info.fccType, info.fccHandler, ICMODE_DECOMPRESS );
|
||||
if( !hic )
|
||||
{
|
||||
LOG->Info("Couldn't open video codec %s",
|
||||
FourCCToString(info.fccHandler).c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
CHECKPOINT;
|
||||
if( ICGetInfo(hic, &info, sizeof(ICINFO)) )
|
||||
{
|
||||
CheckCodecVersion( FourCCToString(info.fccHandler), WStringToRString(info.szDescription) );
|
||||
CHECKPOINT;
|
||||
|
||||
LOG->Info( " %s: %ls (%ls)",
|
||||
FourCCToString(info.fccHandler).c_str(), info.szName, info.szDescription );
|
||||
}
|
||||
else
|
||||
LOG->Info( "ICGetInfo(%s) failed", FourCCToString(info.fccHandler).c_str() );
|
||||
|
||||
CHECKPOINT;
|
||||
ICClose(hic);
|
||||
}
|
||||
|
||||
if( i == 0 )
|
||||
LOG->Info( " None found" );
|
||||
}
|
||||
|
||||
|
||||
MovieTexture_DShow::MovieTexture_DShow( RageTextureID ID ) :
|
||||
RageMovieTexture( ID ),
|
||||
buffer_lock( "buffer_lock", 1 ),
|
||||
buffer_finished( "buffer_finished", 0 )
|
||||
{
|
||||
LOG->Trace( "MovieTexture_DShow::MovieTexture_DShow()" );
|
||||
|
||||
static bool bFirst = true;
|
||||
if( bFirst )
|
||||
{
|
||||
bFirst = false;
|
||||
GetVideoCodecDebugInfo();
|
||||
}
|
||||
|
||||
m_bLoop = true;
|
||||
m_bPlaying = false;
|
||||
|
||||
m_uTexHandle = 0;
|
||||
buffer = nullptr;
|
||||
}
|
||||
|
||||
RString MovieTexture_DShow::Init()
|
||||
{
|
||||
RString sError = Create();
|
||||
if( sError != "" )
|
||||
return sError;
|
||||
|
||||
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 RString();
|
||||
}
|
||||
|
||||
/* Hold buffer_lock. If it's held, then the decoding thread is waiting
|
||||
* for us to process a frame; do so. */
|
||||
void MovieTexture_DShow::SkipUpdates()
|
||||
{
|
||||
while( buffer_lock.TryWait() )
|
||||
CheckFrame();
|
||||
}
|
||||
|
||||
void MovieTexture_DShow::StopSkippingUpdates()
|
||||
{
|
||||
buffer_lock.Post();
|
||||
}
|
||||
|
||||
MovieTexture_DShow::~MovieTexture_DShow()
|
||||
{
|
||||
LOG->Trace( "MovieTexture_DShow::~MovieTexture_DShow" );
|
||||
LOG->Flush();
|
||||
|
||||
SkipUpdates();
|
||||
|
||||
/* Shut down the graph. We can't call Stop() here, since that will
|
||||
* call SkipUpdates again, which will deadlock if we call it twice
|
||||
* in a row. */
|
||||
if( m_pGB )
|
||||
{
|
||||
LOG->Trace( "MovieTexture_DShow: shutdown" );
|
||||
LOG->Flush();
|
||||
CComPtr<IMediaControl> pMC;
|
||||
m_pGB.QueryInterface(&pMC);
|
||||
|
||||
HRESULT hr;
|
||||
if( FAILED( hr = pMC->Stop() ) )
|
||||
RageException::Throw( hr_ssprintf(hr, "Could not stop the DirectShow graph.") );
|
||||
|
||||
// Stop();
|
||||
m_pGB.Release();
|
||||
}
|
||||
LOG->Trace( "MovieTexture_DShow: shutdown ok" );
|
||||
LOG->Flush();
|
||||
if( m_uTexHandle )
|
||||
DISPLAY->DeleteTexture( m_uTexHandle );
|
||||
}
|
||||
|
||||
void MovieTexture_DShow::Reload()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/* If there's a frame waiting in the buffer, then the decoding thread put it there
|
||||
* and is waiting for us to do something with it. */
|
||||
void MovieTexture_DShow::CheckFrame()
|
||||
{
|
||||
if(buffer == nullptr)
|
||||
return;
|
||||
|
||||
CHECKPOINT;
|
||||
|
||||
/* Just in case we were invalidated: */
|
||||
CreateTexture();
|
||||
|
||||
// DirectShow feeds us in BGR8
|
||||
RageSurface *pFromDShow = CreateSurfaceFrom(
|
||||
m_iSourceWidth, m_iSourceHeight,
|
||||
24,
|
||||
0xFF0000,
|
||||
0x00FF00,
|
||||
0x0000FF,
|
||||
0x000000,
|
||||
(std::uint8_t *) buffer, m_iSourceWidth*3 );
|
||||
|
||||
/*
|
||||
* Optimization notes:
|
||||
*
|
||||
* With D3D, this surface can be anything; it'll convert it on the fly. If
|
||||
* it happens to exactly match the texture, it'll copy a little faster.
|
||||
*
|
||||
* With OpenGL, it's best that this be a real, supported texture format, though
|
||||
* it doesn't need to be that of the actual texture. If it isn't, it'll have
|
||||
* to do a very slow conversion. Both RGB8 and BGR8 are both (usually) valid
|
||||
* formats.
|
||||
*/
|
||||
CHECKPOINT;
|
||||
DISPLAY->UpdateTexture(
|
||||
m_uTexHandle,
|
||||
pFromDShow,
|
||||
0, 0,
|
||||
m_iImageWidth, m_iImageHeight );
|
||||
CHECKPOINT;
|
||||
|
||||
delete pFromDShow;
|
||||
|
||||
buffer = nullptr;
|
||||
|
||||
CHECKPOINT;
|
||||
|
||||
/* Start the decoding thread again. */
|
||||
buffer_finished.Post();
|
||||
|
||||
CHECKPOINT;
|
||||
}
|
||||
|
||||
void MovieTexture_DShow::Update(float fDeltaTime)
|
||||
{
|
||||
CHECKPOINT;
|
||||
|
||||
// restart the movie if we reach the end
|
||||
if( m_bLoop )
|
||||
{
|
||||
// Check for completion events
|
||||
CComPtr<IMediaEvent> pME;
|
||||
m_pGB.QueryInterface(&pME);
|
||||
|
||||
long lEventCode, lParam1, lParam2;
|
||||
pME->GetEvent( &lEventCode, &lParam1, &lParam2, 0 );
|
||||
if( lEventCode == EC_COMPLETE )
|
||||
SetPosition(0);
|
||||
}
|
||||
|
||||
CHECKPOINT;
|
||||
|
||||
CheckFrame();
|
||||
}
|
||||
|
||||
RString PrintCodecError( HRESULT hr, RString 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. */
|
||||
RString err = hr_ssprintf(hr, "%s", s.c_str());
|
||||
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() );
|
||||
}
|
||||
|
||||
RString MovieTexture_DShow::GetActiveFilterList()
|
||||
{
|
||||
RString ret;
|
||||
|
||||
IEnumFilters *pEnum = nullptr;
|
||||
HRESULT hr = m_pGB->EnumFilters(&pEnum);
|
||||
if (FAILED(hr))
|
||||
return hr_ssprintf(hr, "EnumFilters");
|
||||
|
||||
IBaseFilter *pF = nullptr;
|
||||
while( S_OK == pEnum->Next(1, &pF, 0) )
|
||||
{
|
||||
FILTER_INFO FilterInfo;
|
||||
pF->QueryFilterInfo( &FilterInfo );
|
||||
|
||||
if( ret != "" )
|
||||
ret += ", ";
|
||||
ret += WStringToRString(FilterInfo.achName);
|
||||
|
||||
if( FilterInfo.pGraph )
|
||||
FilterInfo.pGraph->Release();
|
||||
pF->Release();
|
||||
}
|
||||
pEnum->Release();
|
||||
return ret;
|
||||
}
|
||||
|
||||
RString MovieTexture_DShow::Create()
|
||||
{
|
||||
RageTextureID actualID = GetID();
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
actualID.iAlphaBits = 0;
|
||||
|
||||
if( FAILED( hr=CoInitialize(nullptr) ) )
|
||||
RageException::Throw( hr_ssprintf(hr, "Could not CoInitialize") );
|
||||
|
||||
// Create the filter graph
|
||||
if( FAILED( hr=m_pGB.CoCreateInstance(CLSID_FilterGraph, nullptr, CLSCTX_INPROC) ) )
|
||||
RageException::Throw( 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" ) ) )
|
||||
RageException::Throw( hr_ssprintf(hr, "Could not add renderer filter to graph!") );
|
||||
|
||||
// Add the source filter
|
||||
CComPtr<IBaseFilter> pFSrc; // Source Filter
|
||||
wstring wFileName = RStringToWstring(actualID.filename);
|
||||
|
||||
// if this fails, it's probably because the user doesn't have DivX installed
|
||||
/* No, it also happens if the movie can't be opened for some reason; for example,
|
||||
* 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 ) ) )
|
||||
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 ) ) )
|
||||
return hr_ssprintf(hr, "Could not find input pin" );
|
||||
|
||||
CComPtr<IPin> pFSrcPinOut; // Source Filter Output Pin
|
||||
if( FAILED( hr = pFSrc->FindPin( L"Output", &pFSrcPinOut ) ) )
|
||||
return hr_ssprintf( hr, "Could not find output pin" );
|
||||
|
||||
// Connect these two filters
|
||||
if( FAILED( hr = m_pGB->Connect( pFSrcPinOut, pFTRPinIn ) ) )
|
||||
return PrintCodecError( hr, "Could not connect pins" );
|
||||
|
||||
LOG->Trace( "Filters: %s", GetActiveFilterList().c_str() );
|
||||
|
||||
// Pass us to our TextureRenderer.
|
||||
pCTR->SetRenderTarget(this);
|
||||
|
||||
/* Cap the max texture size to the hardware max. */
|
||||
actualID.iMaxSize = std::min( actualID.iMaxSize, DISPLAY->GetMaxTextureSize() );
|
||||
|
||||
// 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();
|
||||
|
||||
/* image size cannot exceed max size */
|
||||
m_iImageWidth = std::min( m_iSourceWidth, actualID.iMaxSize );
|
||||
m_iImageHeight = std::min( m_iSourceHeight, actualID.iMaxSize );
|
||||
|
||||
/* Texture dimensions need to be a power of two; jump to the next. */
|
||||
m_iTextureWidth = power_of_two(m_iImageWidth);
|
||||
m_iTextureHeight = power_of_two(m_iImageHeight);
|
||||
|
||||
/* We've set up the movie, so we know the dimensions we need. Set
|
||||
* up the texture. */
|
||||
CreateTexture();
|
||||
|
||||
/* Pausing the graph will cause only one frame to be rendered. Do that, then
|
||||
* wait for the frame to be rendered, to guarantee that the texture is set
|
||||
* when this function returns. */
|
||||
Pause();
|
||||
|
||||
CHECKPOINT;
|
||||
pCTR->m_OneFrameDecoded.Wait();
|
||||
CHECKPOINT;
|
||||
CheckFrame();
|
||||
CHECKPOINT;
|
||||
|
||||
// Start the graph running
|
||||
Play();
|
||||
|
||||
return RString();
|
||||
}
|
||||
|
||||
|
||||
void MovieTexture_DShow::NewData(const char *data)
|
||||
{
|
||||
ASSERT(data);
|
||||
|
||||
/* Try to lock. */
|
||||
if( buffer_lock.TryWait() )
|
||||
{
|
||||
/* The main thread is doing something uncommon, such as pausing.
|
||||
* Drop this frame. */
|
||||
return;
|
||||
}
|
||||
|
||||
buffer = data;
|
||||
|
||||
buffer_finished.Wait();
|
||||
|
||||
ASSERT( buffer == nullptr );
|
||||
|
||||
buffer_lock.Post();
|
||||
}
|
||||
|
||||
|
||||
void MovieTexture_DShow::CreateTexture()
|
||||
{
|
||||
if( m_uTexHandle )
|
||||
return;
|
||||
|
||||
RagePixelFormat pixfmt;
|
||||
int depth = TEXTUREMAN->GetPrefs().m_iMovieColorDepth;
|
||||
switch( depth )
|
||||
{
|
||||
default:
|
||||
FAIL_M(ssprintf("Unsupported movie color depth: %i", depth));
|
||||
case 16:
|
||||
if( DISPLAY->SupportsTextureFormat(RagePixelFormat_RGB5) )
|
||||
pixfmt = RagePixelFormat_RGB5;
|
||||
else
|
||||
pixfmt = RagePixelFormat_RGBA4; // everything supports RGBA4
|
||||
break;
|
||||
case 32:
|
||||
if( DISPLAY->SupportsTextureFormat(RagePixelFormat_RGB8) )
|
||||
pixfmt = RagePixelFormat_RGB8;
|
||||
else if( DISPLAY->SupportsTextureFormat(RagePixelFormat_RGBA8) )
|
||||
pixfmt = RagePixelFormat_RGBA8;
|
||||
else if( DISPLAY->SupportsTextureFormat(RagePixelFormat_RGB5) )
|
||||
pixfmt = RagePixelFormat_RGB5;
|
||||
else
|
||||
pixfmt = RagePixelFormat_RGBA4; // everything supports RGBA4
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
const RageDisplay::RagePixelFormatDesc *pfd = DISPLAY->GetPixelFormatDesc(pixfmt);
|
||||
RageSurface *img = CreateSurface( m_iTextureWidth, m_iTextureHeight,
|
||||
pfd->bpp, pfd->masks[0], pfd->masks[1], pfd->masks[2], pfd->masks[3] );
|
||||
|
||||
m_uTexHandle = DISPLAY->CreateTexture( pixfmt, img, false );
|
||||
|
||||
delete img;
|
||||
}
|
||||
|
||||
|
||||
void MovieTexture_DShow::Play()
|
||||
{
|
||||
SkipUpdates();
|
||||
|
||||
LOG->Trace("MovieTexture_DShow::Play()");
|
||||
CComPtr<IMediaControl> pMC;
|
||||
m_pGB.QueryInterface(&pMC);
|
||||
|
||||
// Start the graph running;
|
||||
HRESULT hr;
|
||||
if( FAILED(hr = pMC->Run()) )
|
||||
RageException::Throw( hr_ssprintf(hr, "Could not run the DirectShow graph.") );
|
||||
|
||||
m_bPlaying = true;
|
||||
|
||||
StopSkippingUpdates();
|
||||
}
|
||||
|
||||
void MovieTexture_DShow::Pause()
|
||||
{
|
||||
SkipUpdates();
|
||||
|
||||
CComPtr<IMediaControl> pMC;
|
||||
m_pGB.QueryInterface(&pMC);
|
||||
|
||||
HRESULT hr;
|
||||
/* Use Pause(), so we'll get a still frame in CTextureRenderer::OnReceiveFirstSample. */
|
||||
if( FAILED(hr = pMC->Pause()) )
|
||||
RageException::Throw( hr_ssprintf(hr, "Could not pause the DirectShow graph.") );
|
||||
|
||||
StopSkippingUpdates();
|
||||
}
|
||||
|
||||
|
||||
void MovieTexture_DShow::SetPosition( float fSeconds )
|
||||
{
|
||||
SkipUpdates();
|
||||
|
||||
CComPtr<IMediaPosition> pMP;
|
||||
m_pGB.QueryInterface(&pMP);
|
||||
pMP->put_CurrentPosition(0);
|
||||
|
||||
StopSkippingUpdates();
|
||||
}
|
||||
|
||||
void MovieTexture_DShow::SetPlaybackRate( float fRate )
|
||||
{
|
||||
if( fRate == 0 )
|
||||
{
|
||||
this->Pause();
|
||||
return;
|
||||
}
|
||||
|
||||
SkipUpdates();
|
||||
|
||||
CComPtr<IMediaPosition> pMP;
|
||||
m_pGB.QueryInterface(&pMP);
|
||||
HRESULT hr = pMP->put_Rate(fRate); // fails on many codecs
|
||||
|
||||
StopSkippingUpdates();
|
||||
|
||||
if( FAILED(hr) )
|
||||
{
|
||||
this->Pause();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2001-2004 Chris Danford, Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -1,105 +0,0 @@
|
||||
/* MovieTexture_DShow - DirectShow movie renderer. */
|
||||
|
||||
#ifndef RAGE_MOVIE_TEXTURE_DSHOW_H
|
||||
#define RAGE_MOVIE_TEXTURE_DSHOW_H
|
||||
|
||||
#include "MovieTexture.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"
|
||||
|
||||
class MovieTexture_DShow : public RageMovieTexture
|
||||
{
|
||||
public:
|
||||
MovieTexture_DShow( RageTextureID ID );
|
||||
virtual ~MovieTexture_DShow();
|
||||
RString Init();
|
||||
|
||||
/* only called by RageTextureManager::InvalidateTextures */
|
||||
void Invalidate() { m_uTexHandle = 0; }
|
||||
void Update( float fDeltaTime );
|
||||
|
||||
virtual void Reload();
|
||||
|
||||
virtual void Play();
|
||||
virtual void Pause();
|
||||
virtual void SetPosition( float fSeconds );
|
||||
virtual void SetPlaybackRate( float fRate );
|
||||
|
||||
void SetLooping( bool bLooping=true ) { m_bLoop = bLooping; }
|
||||
|
||||
void NewData( const char *pBuffer );
|
||||
|
||||
private:
|
||||
const char *buffer;
|
||||
RageSemaphore buffer_lock, buffer_finished;
|
||||
|
||||
RString Create();
|
||||
|
||||
void CreateTexture();
|
||||
void SkipUpdates();
|
||||
void StopSkippingUpdates();
|
||||
void CheckFrame();
|
||||
RString GetActiveFilterList();
|
||||
|
||||
unsigned GetTexHandle() const { return m_uTexHandle; }
|
||||
unsigned m_uTexHandle;
|
||||
|
||||
CComPtr<IGraphBuilder> m_pGB; // GraphBuilder
|
||||
bool m_bLoop;
|
||||
bool m_bPlaying;
|
||||
};
|
||||
|
||||
class RageMovieTextureDriver_DShow: public RageMovieTextureDriver
|
||||
{
|
||||
public:
|
||||
virtual RageMovieTexture *Create( RageTextureID ID, RString &sError );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2001-2004 Chris Danford, Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -1,123 +0,0 @@
|
||||
#include "global.h"
|
||||
#include "MovieTexture_DShowHelper.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageLog.h"
|
||||
#include "archutils/Win32/DirectXHelpers.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Define GUID for Texture Renderer
|
||||
// {71771540-2017-11cf-AE26-0020AFD79767}
|
||||
//-----------------------------------------------------------------------------
|
||||
struct __declspec(uuid("{71771540-2017-11cf-ae26-0020afd79767}")) CLSID_TextureRenderer;
|
||||
|
||||
static HRESULT CBV_ret;
|
||||
CTextureRenderer::CTextureRenderer():
|
||||
CBaseVideoRenderer(__uuidof(CLSID_TextureRenderer),
|
||||
NAME("Texture Renderer"), nullptr, &CBV_ret),
|
||||
m_OneFrameDecoded( "m_OneFrameDecoded", 0 )
|
||||
{
|
||||
if( FAILED(CBV_ret) )
|
||||
RageException::Throw( hr_ssprintf(CBV_ret, "Could not create texture renderer object!") );
|
||||
|
||||
m_pTexture = nullptr;
|
||||
}
|
||||
|
||||
CTextureRenderer::~CTextureRenderer()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
HRESULT CTextureRenderer::CheckMediaType(const CMediaType *pmt)
|
||||
{
|
||||
VIDEOINFO *pvi;
|
||||
|
||||
// Reject the connection if this is not a video type
|
||||
if( *pmt->FormatType() != FORMAT_VideoInfo )
|
||||
return E_INVALIDARG;
|
||||
|
||||
/* Force the graph to R8G8B8. DirectShow won't generate a FMT_RGB5 that OpenGL
|
||||
* can handle. It's faster to generate FMT8 and let OpenGL convert on the fly
|
||||
* than to generate FMT_RGB5 and convert it ourself. */
|
||||
pvi = (VIDEOINFO *)pmt->Format();
|
||||
if( IsEqualGUID( *pmt->Type(), MEDIATYPE_Video) &&
|
||||
IsEqualGUID( *pmt->Subtype(), MEDIASUBTYPE_RGB24) )
|
||||
return S_OK;
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
|
||||
// SetMediaType: Graph connection has been made.
|
||||
HRESULT CTextureRenderer::SetMediaType(const CMediaType *pmt)
|
||||
{
|
||||
// Retrive the size of this media type
|
||||
VIDEOINFO *pviBmp; // Bitmap info header
|
||||
pviBmp = (VIDEOINFO *)pmt->Format();
|
||||
m_lVidWidth = pviBmp->bmiHeader.biWidth;
|
||||
m_lVidHeight = std::abs(pviBmp->bmiHeader.biHeight);
|
||||
m_lVidPitch = (m_lVidWidth * 3 + 3) + ~3; // We are forcing RGB24
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
void CTextureRenderer::SetRenderTarget( MovieTexture_DShow* pTexture )
|
||||
{
|
||||
m_pTexture = pTexture;
|
||||
}
|
||||
|
||||
// DoRenderSample: A sample has been delivered. Copy it.
|
||||
HRESULT CTextureRenderer::DoRenderSample( IMediaSample * pSample )
|
||||
{
|
||||
if( m_pTexture == nullptr )
|
||||
{
|
||||
LOG->Warn( "DoRenderSample called while m_pTexture was nullptr!" );
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
BYTE *pBmpBuffer; // Bitmap buffer
|
||||
|
||||
// Get the video bitmap buffer
|
||||
pSample->GetPointer( &pBmpBuffer );
|
||||
|
||||
// Copy the bits
|
||||
m_pTexture->NewData((char *) pBmpBuffer);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void CTextureRenderer::OnReceiveFirstSample( IMediaSample * pSample )
|
||||
{
|
||||
/* If the main thread is in MovieTexture_DShow::Create, kick: */
|
||||
if( m_OneFrameDecoded.GetValue() == 0 )
|
||||
m_OneFrameDecoded.Post();
|
||||
|
||||
DoRenderSample( pSample );
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2001-2004 Chris Danford, Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -1,66 +0,0 @@
|
||||
#ifndef RAGE_MOVIE_TEXTURE_DSHOW_HELPER_H
|
||||
#define RAGE_MOVIE_TEXTURE_DSHOW_HELPER_H
|
||||
|
||||
#include "MovieTexture_DShow.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CTextureRenderer Class Declarations
|
||||
//
|
||||
// Usage: 1) CheckMediaType is called by the graph
|
||||
// 2) SetMediaType is called by the graph
|
||||
// 3) call GetVidWidth and GetVidHeight to get texture information
|
||||
// 4) call SetRenderTarget
|
||||
// 5) Do RenderSample is called by the graph
|
||||
//-----------------------------------------------------------------------------
|
||||
class CTextureRenderer : public CBaseVideoRenderer
|
||||
{
|
||||
public:
|
||||
CTextureRenderer();
|
||||
~CTextureRenderer();
|
||||
|
||||
HRESULT CheckMediaType( const CMediaType *pmt ); // Format acceptable?
|
||||
HRESULT SetMediaType( const CMediaType *pmt ); // Video format notification
|
||||
HRESULT DoRenderSample( IMediaSample *pMediaSample ); // New video sample
|
||||
void OnReceiveFirstSample( IMediaSample * pSample );
|
||||
|
||||
long GetVidWidth() const { return m_lVidWidth; }
|
||||
long GetVidHeight() const { return m_lVidHeight; }
|
||||
void SetRenderTarget( MovieTexture_DShow* pTexture );
|
||||
|
||||
RageSemaphore m_OneFrameDecoded;
|
||||
|
||||
protected:
|
||||
// Video width, height, and pitch.
|
||||
long m_lVidWidth, m_lVidHeight, m_lVidPitch;
|
||||
|
||||
char *output;
|
||||
|
||||
MovieTexture_DShow* m_pTexture; // the video surface we will copy new frames to
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2001-2004 Chris Danford, Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -8,7 +8,7 @@
|
||||
#include "LowLevelWindow/LowLevelWindow_Win32.h"
|
||||
#include "MemoryCard/MemoryCardDriverThreaded_Windows.h"
|
||||
#define DEFAULT_INPUT_DRIVER_LIST "DirectInput,Pump,Para"
|
||||
#define DEFAULT_MOVIE_DRIVER_LIST "FFMpeg,DShow,Null"
|
||||
#define DEFAULT_MOVIE_DRIVER_LIST "FFMpeg,Null"
|
||||
#define DEFAULT_SOUND_DRIVER_LIST "WaveOut,DirectSound-sw,WDMKS,Null"
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user