client/UserInterface/MovieMan.cpp

687 lines
20 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "stdafx.h"
#include "MovieMan.h"
#include "PythonApplication.h"
// 2007-08-19, nuclei
// add following files to the [Project Settings-Linker-Input]
// DEBUG: ../dshow/strmbasd.lib ../dshow/dmoguids.lib ddraw.lib
// RELEASE: ../dshow/strmbase.lib ../dshow/dmoguids.lib ddraw.lib
// 2007-08-09, nuclei
// if one of following header files are missing,
// please install "Microsoft Platform SDK for Windows Server 2003 R2" or later
#include "ddraw.h"
#include "mmstream.h"
#include "amstream.h"
#include "ddstream.h"
#include "uuids.h"
#include "control.h"
#include "dmodshow.h"
#include "dmoreg.h"
#define LOGO_PMANG_FILE "ymir.mpg"
#define LOGO_NW_FILE "logoNW.mpg"
#define LOGO_EA_FILE "logoEA.mpg"
#define LOGO_EA_ENGLISH_FILE "logoEA_english.mpg"
#define LOGO_GAMEON "gameonbi.mpg" //for japan
#define LOGO_IAH_FILE "logoIAH.mpg"
#define INTRO_FILE "intro.mpg"
#define LEGAL_FILE_00 "legal00.mpg"
#define LEGAL_FILE_01 "legal01.mpg"
#define TUTORIAL_0 "TutorialMovie\\Tutorial0.mpg"
#define TUTORIAL_1 "TutorialMovie\\Tutorial1.mpg"
#define TUTORIAL_2 "TutorialMovie\\Tutorial2.mpg"
void CMovieMan::ClearToBlack()
{
PAINTSTRUCT ps;
HDC dc;
//
// Get the repaint DC and then fill the window with black.
//
HWND window = CPythonApplication::Instance().GetWindowHandle();//CFFClientApp::GetInstance()->GetMainWindow();
InvalidateRect( window, NULL, FALSE );
dc = BeginPaint( window, &ps );
PatBlt( dc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom, BLACKNESS);
EndPaint( window, &ps );
}
void CMovieMan::FillRect( RECT& fillRect, DWORD fillColor )
{
assert(m_pPrimarySurface);
if (fillRect.bottom == fillRect.top || fillRect.left == fillRect.right)
{
// ä¿ï ÇÊ¿ä ¾øÀ½
return;
}
DDBLTFX colorFillBltFX;
colorFillBltFX.dwSize = sizeof(DDBLTFX);
colorFillBltFX.dwFillColor = fillColor;
if (!m_usingRGB32 || FAILED(m_pPrimarySurface->Blt(&fillRect, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &colorFillBltFX)))
{
GDIFillRect(fillRect, fillColor);
return;
}
}
inline void CMovieMan::GDIFillRect( RECT& fillRect, DWORD fillColor )
{
HBRUSH fillBrush = CreateSolidBrush(
RGB((fillColor >> 16) & 255, (fillColor >> 8) & 255, fillColor & 255)
);
HDC desktopDC = GetDC(0);
::FillRect(desktopDC, &fillRect, fillBrush);
ReleaseDC(0, desktopDC);
DeleteObject(fillBrush);
}
//----------------------------------------------------------------------------------------------------
// ƯÁ¤ ¼­Çǽº¸¦ GDI·Î ¹ÙÅÁÈ­¸é¿¡ »Ñ¸°´Ù
//
inline void CMovieMan::GDIBlt(IDirectDrawSurface *pSrcSurface, RECT *pDestRect)
{
HDC surfaceDC;
HDC desktopDC = GetDC(0);
if (SUCCEEDED(pSrcSurface->GetDC(&surfaceDC)))
{
StretchBlt(desktopDC, pDestRect->left, pDestRect->top, pDestRect->right - pDestRect->left, pDestRect->bottom - pDestRect->top,
surfaceDC, 0, 0, m_movieWidth, m_movieHeight, SRCCOPY);
pSrcSurface->ReleaseDC(surfaceDC);
}
ReleaseDC(0, desktopDC);
}
void CMovieMan::PlayLogo(const char *pcszName)
{
PlayMovie(pcszName);
}
void CMovieMan::PlayIntro()
{
// ÀÎÆ®·Î ¿µ»óÀº Å°º¸µå ÀÔ·ÂÀ̳ª ¸¶¿ì½º Ŭ¸¯À¸·Î ½ºÅµ °¡´É
PlayMovie( INTRO_FILE, MOVIEMAN_SKIPPABLE_YES, MOVIEMAN_POSTEFFECT_FADEOUT, 0xFFFFFF );
}
BOOL CMovieMan::PlayTutorial(LONG nIdx)
{
BOOL bRet = FALSE;
ClearToBlack();
switch( nIdx ) {
case 0:
bRet = PlayMovie( TUTORIAL_0, MOVIEMAN_SKIPPABLE_YES, MOVIEMAN_POSTEFFECT_FADEOUT, 0xFFFFFF );
return bRet;
case 1:
bRet = PlayMovie( TUTORIAL_1, MOVIEMAN_SKIPPABLE_YES, MOVIEMAN_POSTEFFECT_FADEOUT, 0xFFFFFF );
return bRet;
case 2:
bRet = PlayMovie( TUTORIAL_2, MOVIEMAN_SKIPPABLE_YES, MOVIEMAN_POSTEFFECT_FADEOUT, 0xFFFFFF );
return bRet;
}
return bRet;
}
BOOL CMovieMan::PlayMovie( const char *cpFileName, const bool bSkipAllowed, const int nPostEffectID, const DWORD dwPostEffectData )
{
HWND hWnd = CPythonApplication::Instance().GetWindowHandle();
IDirectDraw *pDD = NULL;
DirectDrawCreate(NULL, &pDD, NULL);
pDD->SetCooperativeLevel(hWnd, DDSCL_NORMAL);
DDSURFACEDESC ddsd;
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
if (FAILED(pDD->CreateSurface(&ddsd, &m_pPrimarySurface, NULL)))
{
pDD->Release();
return FALSE;
}
// 32ºñÆ®ÀÎÁö ¾Ë¾Æº»´Ù
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_PIXELFORMAT;
m_pPrimarySurface->GetSurfaceDesc(&ddsd);
ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
m_usingRGB32 = (ddsd.ddpfPixelFormat.dwRGBBitCount == 32);
IDirectDrawClipper *pDDClipper = NULL;
HRESULT hr = pDD->CreateClipper(0, &pDDClipper, NULL);
if (SUCCEEDED(hr))
{
pDDClipper->SetHWnd(0, hWnd);
m_pPrimarySurface->SetClipper(pDDClipper);
}
IMultiMediaStream *pMMStream = NULL;
hr = RenderFileToMMStream(cpFileName, &pMMStream, pDD);
if (SUCCEEDED(hr))
{
IMediaStream *pPrimaryVidStream = NULL;
HRESULT hr = pMMStream->GetMediaStream(MSPID_PrimaryVideo, &pPrimaryVidStream);
if (SUCCEEDED(hr))
{
IDirectDrawMediaStream *pDDStream = NULL;
pPrimaryVidStream->QueryInterface(IID_IDirectDrawMediaStream, (void **) &pDDStream);
pPrimaryVidStream->Release();
ddsd.dwSize = sizeof(ddsd);
hr = pDDStream->GetFormat(&ddsd, NULL, NULL, NULL);
if (SUCCEEDED(hr))
{
// µ¿¿µ»ó Å©±â¿Í À©µµ¿ì Å©±â¸¦ ±âÁØÀ¸·Î µ¿¿µ»ó Àç»ýµÉ Àû´çÇÑ ¿µ¿ªÀ» ¼³Á¤
m_movieWidth = ddsd.dwWidth;
m_movieHeight = ddsd.dwHeight;
// ¹é¹öÆÛ´Â ¹«Á¶°Ç RGB32·Î ¸¸µé°í PrimarySurface¿Í Çü½ÄÀÌ ´Ù¸£¸é
// GDI fallback Çؼ­ StretchBlt ÇÑ´Ù
DDSURFACEDESC ddsdBackSurface;
ZeroMemory(&ddsdBackSurface, sizeof(ddsdBackSurface));
ddsdBackSurface.ddpfPixelFormat.dwSize = sizeof(ddsdBackSurface.ddpfPixelFormat);
ddsdBackSurface.ddpfPixelFormat.dwFlags = DDPF_RGB;
ddsdBackSurface.ddpfPixelFormat.dwRGBBitCount = 32;
ddsdBackSurface.ddpfPixelFormat.dwRBitMask = 255 << 16;
ddsdBackSurface.ddpfPixelFormat.dwGBitMask = 255 << 8;
ddsdBackSurface.ddpfPixelFormat.dwBBitMask = 255;
ddsdBackSurface.dwSize = sizeof(ddsdBackSurface);
ddsdBackSurface.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
ddsdBackSurface.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
ddsdBackSurface.dwHeight = m_movieHeight;
ddsdBackSurface.dwWidth = m_movieWidth;
IDirectDrawSurface *pSurface;
hr = pDD->CreateSurface(&ddsdBackSurface, &pSurface, NULL);
if (SUCCEEDED(hr))
{
RenderStreamToSurface(pSurface, pDDStream, pMMStream, bSkipAllowed, nPostEffectID, dwPostEffectData);
pSurface->Release();
}
}
pDDStream->Release();
}
pMMStream->Release();
}
m_pPrimarySurface->Release();
m_pPrimarySurface = NULL;
if (m_pBasicAudio)
{
m_pBasicAudio->Release();
m_pBasicAudio = NULL;
}
if (pDDClipper)
{
pDDClipper->Release();
pDDClipper = NULL;
}
pDD->Release();
// Å°º¸µå, ¸¶¿ì½º ¹öÆÛ ºñ¿ì±â
MSG msg;
while (PeekMessage(&msg, hWnd, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE));
while (PeekMessage(&msg, hWnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE));
return SUCCEEDED(hr);
}
//----------------------------------------------------------------------------------------------------
// ¸ÞÀÎ À©µµ¿ìÀÇ Screen ÁÂÇ¥¸¦ ¹Ýȯ
//
void CMovieMan::GetWindowRect(RECT& windowRect)
{
HWND hWnd = CPythonApplication::Instance().GetWindowHandle();
POINT p;
//
// Get the position of the upper-left client coordinate (in screen space).
//
p.x = 0;
p.y = 0;
ClientToScreen( hWnd, &p );
//
// Get the client rectangle of the window.
//
GetClientRect( hWnd, &windowRect );
// clientRect¸¦ ClientToScreen ÇÏ´Â °Í°ú °°À½
OffsetRect( &windowRect, p.x, p.y );
}
//----------------------------------------------------------------------------------------------------
// ¸ÞÀÎ À©µµ¿ì¿¡ µ¿¿µ»óÀ» ²Ëä¿ì´Â RECT ¹Ýȯ(°¡·Î/¼¼·Î ºñÀ² À¯Áö)
//
void CMovieMan::CalcMovieRect(int srcWidth, int srcHeight, RECT& movieRect)
{
RECT windowRect;
GetWindowRect(windowRect);
int nMovieWidth, nMovieHeight;
if (srcWidth >= srcHeight)
{
nMovieWidth = (windowRect.right - windowRect.left);
nMovieHeight = srcHeight * nMovieWidth / srcWidth;
if( nMovieHeight > windowRect.bottom - windowRect.top )
nMovieHeight = windowRect.bottom - windowRect.top;
}
else
{
nMovieHeight = (windowRect.bottom - windowRect.top);
nMovieWidth = srcWidth * nMovieHeight / srcHeight;
if( nMovieWidth > windowRect.right - windowRect.left )
nMovieWidth = windowRect.right - windowRect.left;
}
movieRect.left = windowRect.left + ((windowRect.right - windowRect.left) - nMovieWidth) / 2;
movieRect.top = windowRect.top + ((windowRect.bottom - windowRect.top) - nMovieHeight) / 2;
movieRect.right = movieRect.left + nMovieWidth;
movieRect.bottom = movieRect.top + nMovieHeight;
}
//----------------------------------------------------------------------------------------------------
// È­¸é À§¿¡¼­ µ¿¿µ»óÀÌ ¾Æ´Ñ °ËÀº»ö ¿µ¿ª, Ç×»ó 2°³ÀÇ RECT·Î Ç¥Çö °¡´É
//
void CMovieMan::CalcBackgroundRect(const RECT& movieRect, RECT& upperRect, RECT& lowerRect)
{
RECT windowRect;
GetWindowRect(windowRect);
if (m_movieWidth > m_movieHeight)
{
// À§¾Æ·¡ µÎ°³
SetRect(&upperRect, windowRect.left, windowRect.top, windowRect.right, movieRect.top);
SetRect(&lowerRect, windowRect.left, movieRect.bottom, windowRect.right, windowRect.bottom);
}
else
{
// ÁÂ¿ì µÎ°³
SetRect(&upperRect, windowRect.left, windowRect.top, movieRect.left, windowRect.bottom);
SetRect(&lowerRect, movieRect.right, windowRect.top, windowRect.right, windowRect.bottom);
}
}
//----------------------------------------------------------------------------------------------------
// ƯÁ¤ ¼­Çǽº¿¡ BlockingÀ¸·Î µ¿¿µ»óÀ» ±×¸°´Ù
//
HRESULT CMovieMan::RenderStreamToSurface(IDirectDrawSurface *pSurface, IDirectDrawMediaStream *pDDStream, IMultiMediaStream *pMMStream, bool bSkipAllowed, int nPostEffectID, DWORD dwPostEffectData)
{
#define KEY_DOWN(vk) (GetAsyncKeyState(vk) & 0x8000)
IDirectDrawStreamSample *pSample = NULL;
HRESULT hr = pDDStream->CreateSample(pSurface, NULL, 0, &pSample);
if (SUCCEEDED(hr))
{
// ÃÖÃÊ Çѹø °ËÀº»öÀ¸·Î ¹è°æÀ» Ä¥ÇØÁØ´Ù
RECT movieRect;
RECT upperRect, lowerRect;
CalcMovieRect(m_movieWidth, m_movieHeight, movieRect);
CalcBackgroundRect(movieRect, upperRect, lowerRect);
FillRect(upperRect, 0);
FillRect(lowerRect, 0);
pMMStream->SetState(STREAMSTATE_RUN);
while (pSample->Update(0, NULL, NULL, NULL) == S_OK)
{
// À©µµ¿ì Áß¾ÓÀ» ±âÁØÀ¸·Î ²ËÂ÷°Ô ±×¸°´Ù
CalcMovieRect(m_movieWidth, m_movieHeight, movieRect);
if (FAILED(m_pPrimarySurface->Blt(&movieRect, pSurface, NULL, DDBLT_WAIT, NULL)))
{
GDIBlt(pSurface, &movieRect);
}
// Áß°£¿¡ ½ºÅµ °¡´ÉÇϸé Å°º¸µåESC/¸¶¿ì½º ÀԷ½à ŻÃâ
if (bSkipAllowed && (KEY_DOWN(VK_LBUTTON) || KEY_DOWN(VK_ESCAPE) || KEY_DOWN(VK_SPACE)))
{
break;
}
}
// µ¿¿µ»ó Àç»ý Á¾·á½Ã¿¡ 2ÃÊ µ¿¾È ÆäÀ̵å¾Æ¿ô
switch(nPostEffectID)
{
case MOVIEMAN_POSTEFFECT_FADEOUT:
RenderPostEffectFadeOut(pSurface, MOVIEMAN_FADE_DURATION, dwPostEffectData);
break;
}
pMMStream->SetState(STREAMSTATE_STOP);
pSample->Release();
}
return hr;
}
HRESULT CMovieMan::RenderFileToMMStream(const char *cpFilename, IMultiMediaStream **ppMMStream, IDirectDraw *pDD)
{
IAMMultiMediaStream *pAMStream;
HRESULT hr = CoCreateInstance(CLSID_AMMultiMediaStream, NULL, CLSCTX_INPROC_SERVER, IID_IAMMultiMediaStream, (void **) &pAMStream);
if (FAILED(hr))
{
return hr;
}
WCHAR wPath[MAX_PATH + 1];
MultiByteToWideChar(CP_ACP, 0, cpFilename, -1, wPath, MAX_PATH + 1);
//
WCHAR wsDir[MAX_PATH + 1];
::memset(wsDir, 0, sizeof(wsDir));
::GetCurrentDirectoryW( MAX_PATH, wsDir );
::wcsncat( wsDir, L"\\", sizeof(WCHAR)*1 );
::wcsncat( wsDir, wPath, sizeof(WCHAR)*::wcsnlen(wPath, MAX_PATH) );
::memset(wPath, 0, sizeof(wPath));
::wcsncpy( wPath, wsDir, sizeof(WCHAR)*::wcsnlen(wsDir, MAX_PATH) );
//
pAMStream->Initialize(STREAMTYPE_READ, AMMSF_NOGRAPHTHREAD, NULL);
pAMStream->AddMediaStream(pDD, &MSPID_PrimaryVideo, 0, NULL);
pAMStream->AddMediaStream(NULL, &MSPID_PrimaryAudio, AMMSF_ADDDEFAULTRENDERER, NULL);
std::string ext;
GetFileExtension(cpFilename, strlen(cpFilename), &ext);
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
if (ext == "mpg")
{
// 2007-08-01, nuclei
// MPG¸¸ Àç»ýÇÑ´Ù°í °¡Á¤ÇÏ°í ¸Å´º¾ó·Î °¢Á¾ ÄÚµ¦À» ¿¬°áÇØ
// ¿ÜºÎ ÄÚµ¦(ffdshow µî)¿¡ ¿µÇâÀ» ¹ÞÁö ¾Êµµ·Ï ÇÑ´Ù
// (±âŸ ÆÄÀϵµ Àç»ýÀº µÇÁö¸¸ ÄÚµ¦¿¡ ¿µÇâÀ» ¹ÞÀ» ¼ö ÀÖÀ½)
hr = BuildFilterGraphManually(wPath, pAMStream, CLSID_MPEG1Splitter, CLSID_CMpegVideoCodec, CLSID_CMpegAudioCodec);
}
else if (ext == "mp43")
{
// 2007-08-12, nuclei
// MPEG-4, MP3 ÄÚµ¦À» ÀÌ¿ëÇÑ AVIÀÇ Àç»ý Ãß°¡(È®ÀåÀÚ´Â .mp43À¸·Î ÇؾßÇÔ)
hr = BuildFilterGraphManually(wPath, pAMStream, CLSID_AviSplitter, CLSID_MP4VideoCodec, CLSID_MP3AudioCodec);
}
else
{
hr = pAMStream->OpenFile(wPath, 0);
}
// Àç»ý ¼º°ø½Ã hrÀº S_OK
if (SUCCEEDED(hr))
{
pAMStream->QueryInterface(IID_IMultiMediaStream, (void**) ppMMStream);
}
pAMStream->Release();
return hr;
}
//----------------------------------------------------------------------------------------------------
// ƯÁ¤»öÀ¸·Î È­¸éÀÌ ¹à¾ÆÁö°Å³ª ¾îµÎ¿öÁü
//
HRESULT CMovieMan::RenderPostEffectFadeOut(IDirectDrawSurface *pSurface, int fadeOutDuration, DWORD fadeOutColor)
{
// Lock °É±â À§ÇØ ÃʱâÈ­
DDSURFACEDESC lockedSurfaceDesc;
int *pCopiedSrcSurBuf = NULL;
LONG fadeBegin = GetTickCount();
float fadeProgress = 0.0;
while ((fadeProgress = ((float)((LONG)GetTickCount()) - fadeBegin) / fadeOutDuration) < 1.0)
{
ZeroMemory(&lockedSurfaceDesc, sizeof(lockedSurfaceDesc));
lockedSurfaceDesc.dwSize = sizeof(lockedSurfaceDesc);
HRESULT hr = pSurface->Lock(NULL, &lockedSurfaceDesc, DDLOCK_WAIT | DDLOCK_NOSYSLOCK | DDLOCK_READONLY, NULL);
if (FAILED(hr))
{
return hr;
}
// ÃÖÃÊ 1ȸ¿¡ ¼­Çǽº º¹»çÇÏ°í º¹»çº»¿¡ FadeOut ó¸®ÇÑ´Ù
if (!pCopiedSrcSurBuf)
{
if (!(pCopiedSrcSurBuf = (int*)malloc((LONG)lockedSurfaceDesc.lPitch * m_movieHeight)))
{
pSurface->Unlock(lockedSurfaceDesc.lpSurface);
return E_OUTOFMEMORY;
}
CopyMemory(pCopiedSrcSurBuf, lockedSurfaceDesc.lpSurface, (LONG)lockedSurfaceDesc.lPitch * m_movieHeight);
}
// Çȼ¿ ÇöùÆÃ(32ºñÆ®)
int *pSrcSurfaceBuf = pCopiedSrcSurBuf;
int *pDestSurfaceBuf = (int*)lockedSurfaceDesc.lpSurface;
int fadeOutColorRed = (int)(((fadeOutColor >> 16) & 255) * fadeProgress);
int fadeOutColorGreen = (int)(((fadeOutColor >> 8) & 255) * fadeProgress);
int fadeOutColorBlue = (int)((fadeOutColor & 255) * fadeProgress);
for(int y = 0; y < m_movieHeight; ++y)
{
for(int x = 0; x < m_movieWidth; ++x)
{
DWORD srcPixel = *pSrcSurfaceBuf;
*pDestSurfaceBuf = RGB(
(srcPixel & 255) * (1 - fadeProgress) + fadeOutColorBlue,
((srcPixel >> 8) & 255) * (1 - fadeProgress) + fadeOutColorGreen,
((srcPixel >> 16) & 255) * (1 - fadeProgress) + fadeOutColorRed);
pSrcSurfaceBuf++;
pDestSurfaceBuf++;
}
pSrcSurfaceBuf += (lockedSurfaceDesc.lPitch / 4) - m_movieWidth;
pDestSurfaceBuf += (lockedSurfaceDesc.lPitch / 4) - m_movieWidth;
}
pSurface->Unlock(lockedSurfaceDesc.lpSurface);
// »ö»óÀÌ ¹Ù²ï µ¿¿µ»ó À̹ÌÁö ±×¸®±â
RECT movieRect;
CalcMovieRect(m_movieWidth, m_movieHeight, movieRect);
if (FAILED(m_pPrimarySurface->Blt(&movieRect, pSurface, NULL, DDBLT_WAIT, NULL)))
{
GDIBlt(pSurface, &movieRect);
}
// À§ ¶Ç´Â ÁÂÃø ºóÄ­ »öä¿ì±â
RECT upperRect, lowerRect;
CalcBackgroundRect(movieRect, upperRect, lowerRect);
FillRect(upperRect, (fadeOutColorRed << 16) | (fadeOutColorGreen << 8) | fadeOutColorBlue);
FillRect(lowerRect, (fadeOutColorRed << 16) | (fadeOutColorGreen << 8) | fadeOutColorBlue);
// À½·® Á¶Àý
if (m_pBasicAudio)
{
m_pBasicAudio->put_Volume((long)(-10000 * fadeProgress));
}
}
// ¸Þ¸ð¸® ÇØÁ¦
free(pCopiedSrcSurBuf);
// ¸¶Áö¸·¿£ 1.0À» ±âÁØÀ¸·Î ¿ÏÀüÈ÷ FadeOutµÈ È­¸é ±×¸®±â
RECT windowRect;
GetWindowRect(windowRect);
FillRect(windowRect, fadeOutColor);
return S_OK;
}
//----------------------------------------------------------------------------------------------------
// MPEG-1 ºñµð¿À ÆÄÀÏÀ» ¿ÜºÎ ÄÚµ¦ °£¼·¾øÀÌ ·»´õ¸µÇÏ´Â ÇÔ¼ö
//
HRESULT CMovieMan::BuildFilterGraphManually(
WCHAR* wpFilename,
IAMMultiMediaStream *pAMStream,
const GUID FAR clsidSplitter,
const GUID FAR clsidVideoCodec,
const GUID FAR clsidAudioCodec)
{
IGraphBuilder* pGraphBuilder = NULL;
pAMStream->GetFilterGraph(&pGraphBuilder);
assert(pGraphBuilder);
//#ifdef _DEBUG
// DWORD dwRegister;
// AddToRot(pGraphBuilder, &dwRegister);
//#endif
IBaseFilter *pSourceFilter = NULL;
IBaseFilter *pSplitterFilter = NULL;
IBaseFilter *pVideoFilter = NULL;
IBaseFilter *pAudioFilter = NULL;
CoCreateInstance(clsidSplitter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **) &pSplitterFilter);
CoCreateInstance(clsidVideoCodec, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **) &pVideoFilter);
CoCreateInstance(clsidAudioCodec, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **) &pAudioFilter);
// ¸¸¾à MP43 µðÄÚ´õ°¡ ¾ø´Ù¸é DMO ÄÚµ¦À» ´ë½Å ³Ö¾îÁØ´Ù
// MONSTERÆÀ¿¡¼­ ¹ß°ßµÈ ÄÉÀ̽º(ÄÚµ¦À» ´©±º°¡ °­Á¦·Î »èÁ¦)
if (!pVideoFilter && IsEqualGUID(clsidVideoCodec, CLSID_MP4VideoCodec))
{
// Create the DMO Wrapper filter.
HRESULT hr = CoCreateInstance(CLSID_DMOWrapperFilter, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void **)&pVideoFilter);
if (SUCCEEDED(hr))
{
IDMOWrapperFilter *pWrap;
hr = pVideoFilter->QueryInterface(IID_IDMOWrapperFilter, (void **)&pWrap);
if (SUCCEEDED(hr))
{
hr = pWrap->Init(CLSID_MP43DMOCodec, DMOCATEGORY_VIDEO_DECODER);
pWrap->Release();
}
}
}
pGraphBuilder->AddSourceFilter(wpFilename, L"Source Filter", &pSourceFilter);
pGraphBuilder->AddFilter(pSplitterFilter, L"Splitter");
pGraphBuilder->AddFilter(pVideoFilter, L"Video Decoder");
pGraphBuilder->AddFilter(pAudioFilter, L"Audio Decoder");
assert(m_pBasicAudio == NULL);
pGraphBuilder->QueryInterface(IID_IBasicAudio, (void**) &m_pBasicAudio);
// Connect "Source" -> "Splitter"
IPin *pInPin = NULL;
IPin *pOutPin = NULL;
IPin *pSplitterVideoOutPin = NULL;
IPin *pSplitterAudioOutPin = NULL;
IEnumPins *pEnumPins = NULL;
pSourceFilter->EnumPins(&pEnumPins);
pEnumPins->Next(1, &pOutPin, NULL);
pEnumPins->Release();
pSplitterFilter->EnumPins(&pEnumPins);
pEnumPins->Next(1, &pInPin, NULL);
pEnumPins->Release();
HRESULT hr = pGraphBuilder->Connect(pOutPin, pInPin);
pInPin->Release();
pOutPin->Release();
if (SUCCEEDED(hr))
{
// ¿¬°áÈÄ¿¡¸¸ Output ÇɵéÀÌ ³ªÅ¸³­´Ù
pSplitterFilter->EnumPins(&pEnumPins);
PIN_INFO pinInfo;
while( SUCCEEDED(pEnumPins->Next(1, &pInPin, NULL)) )
{
pInPin->QueryPinInfo(&pinInfo);
pinInfo.pFilter->Release();
if (pinInfo.dir == PINDIR_OUTPUT)
{
// PinÀÇ ¼ø¼­¸¦ ºñµð¿À-¿Àµð¿À·Î °¡Á¤
pSplitterVideoOutPin = pInPin;
pEnumPins->Next(1, &pSplitterAudioOutPin, NULL);
break;
}
pInPin->Release();
}
pEnumPins->Release();
// Splitter -> Video/Audio codecs
pVideoFilter->EnumPins(&pEnumPins);
pEnumPins->Next(1, &pInPin, NULL);
pEnumPins->Next(1, &pOutPin, NULL);
pEnumPins->Release();
hr = pGraphBuilder->Connect(pSplitterVideoOutPin, pInPin);
if (SUCCEEDED(hr))
{
// ºñµð¿À ·»´õ
hr = pGraphBuilder->Render(pOutPin);
pInPin->Release();
pOutPin->Release();
// ¿Àµð¿À´Â ÆÄÀÏ¿¡ µû¶ó ¾øÀ» ¼öµµ ÀÖ´Ù
if (pSplitterAudioOutPin && pAudioFilter)
{
pAudioFilter->EnumPins(&pEnumPins);
pEnumPins->Next(1, &pInPin, NULL);
pEnumPins->Next(1, &pOutPin, NULL);
pEnumPins->Release();
pGraphBuilder->Connect(pSplitterAudioOutPin, pInPin);
// ¿Àµð¿À ·»´õ´Â ½ÇÆÐÇصµ ³Ñ¾î°¥ ¼ö ÀÖÀ½
pGraphBuilder->Render(pOutPin);
pInPin->Release();
pOutPin->Release();
}
}
}
// ÇØÁ¦
//#ifdef _DEBUG
// RemoveFromRot(dwRegister);
//#endif
if (pSplitterVideoOutPin)
{
pSplitterVideoOutPin->Release();
}
if (pSplitterAudioOutPin)
{
pSplitterAudioOutPin->Release();
}
pVideoFilter->Release();
if (pAudioFilter)
{
pAudioFilter->Release();
}
pSplitterFilter->Release();
pSourceFilter->Release();
pGraphBuilder->Release();
return hr;
}
//#ifdef _DEBUG
//HRESULT CMovieMan::AddToRot(IGraphBuilder* pGraphBuilder, DWORD *pdwRegister)
//{
// assert(pGraphBuilder);
//
// IMoniker *pMoniker;
// IRunningObjectTable *pROT;
// if (FAILED(GetRunningObjectTable(0, &pROT))) {
// return E_FAIL;
// }
//
// ZString monikerName;
// monikerName.Format(_T("FilterGraph %08x pid %08x"), (DWORD_PTR)pGraphBuilder, GetCurrentProcessId());
// HRESULT hr = CreateItemMoniker(L"!", monikerName, &pMoniker);
// if (SUCCEEDED(hr)) {
// hr = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, pGraphBuilder,
// pMoniker, pdwRegister);
// pMoniker->Release();
// }
// pROT->Release();
// return hr;
//}
//
//void CMovieMan::RemoveFromRot(DWORD pdwRegister)
//{
// IRunningObjectTable *pROT;
// if (SUCCEEDED(GetRunningObjectTable(0, &pROT))) {
// pROT->Revoke(pdwRegister);
// pROT->Release();
// }
//}
//#endif