client/UserInterface/MovieMan.cpp

687 lines
20 KiB
C++
Raw Normal View History

#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)
{
// ä<><C3A4> <20>ʿ<EFBFBD> <20><><EFBFBD><EFBFBD>
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);
}
//----------------------------------------------------------------------------------------------------
// Ư<><C6AF> <20><><EFBFBD>ǽ<EFBFBD><C7BD><EFBFBD> GDI<44><49> <20><><EFBFBD><EFBFBD>ȭ<EFBFBD><20>Ѹ<EFBFBD><D1B8><EFBFBD>
//
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()
{
// <20><>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ű<><C5B0><EFBFBD><EFBFBD> <20>Է<EFBFBD><D4B7>̳<EFBFBD> <20><><EFBFBD>콺 Ŭ<><C5AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ŵ <20><><EFBFBD><EFBFBD>
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<33><32>Ʈ<EFBFBD><C6AE><EFBFBD><EFBFBD> <20>˾ƺ<CBBE><C6BA><EFBFBD>
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))
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ũ<><C5A9><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ũ<><20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
m_movieWidth = ddsd.dwWidth;
m_movieHeight = ddsd.dwHeight;
// <20><><EFBFBD><EFBFBD><EFBFBD>۴<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> RGB32<33><32> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> PrimarySurface<63><65> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ٸ<EFBFBD><D9B8><EFBFBD>
// GDI fallback <20>ؼ<EFBFBD> StretchBlt <20>Ѵ<EFBFBD>
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();
// Ű<><C5B0><EFBFBD><EFBFBD>, <20><><EFBFBD><20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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);
}
//----------------------------------------------------------------------------------------------------
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Screen <20><>ǥ<EFBFBD><C7A5> <20><>ȯ
//
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<63><74> ClientToScreen <20>ϴ<EFBFBD> <20>Ͱ<EFBFBD> <20><><EFBFBD><EFBFBD>
OffsetRect( &windowRect, p.x, p.y );
}
//----------------------------------------------------------------------------------------------------
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ä<EFBFBD><C3A4><EFBFBD><EFBFBD> RECT <20><>ȯ(<28><><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>)
//
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;
}
//----------------------------------------------------------------------------------------------------
// ȭ<><C8AD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ƴ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>, <20>׻<EFBFBD> 2<><32><EFBFBD><EFBFBD> RECT<43><54> ǥ<><C7A5> <20><><EFBFBD><EFBFBD>
//
void CMovieMan::CalcBackgroundRect(const RECT& movieRect, RECT& upperRect, RECT& lowerRect)
{
RECT windowRect;
GetWindowRect(windowRect);
if (m_movieWidth > m_movieHeight)
{
// <20><><EFBFBD>Ʒ<EFBFBD> <20>ΰ<EFBFBD>
SetRect(&upperRect, windowRect.left, windowRect.top, windowRect.right, movieRect.top);
SetRect(&lowerRect, windowRect.left, movieRect.bottom, windowRect.right, windowRect.bottom);
}
else
{
// <20>¿<EFBFBD> <20>ΰ<EFBFBD>
SetRect(&upperRect, windowRect.left, windowRect.top, movieRect.left, windowRect.bottom);
SetRect(&lowerRect, movieRect.right, windowRect.top, windowRect.right, windowRect.bottom);
}
}
//----------------------------------------------------------------------------------------------------
// Ư<><C6AF> <20><><EFBFBD>ǽ<EFBFBD><C7BD><EFBFBD> Blocking<6E><67><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>׸<EFBFBD><D7B8><EFBFBD>
//
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))
{
// <20><><EFBFBD><EFBFBD> <20>ѹ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ĥ<><C4A5><EFBFBD>ش<EFBFBD>
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)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߾<EFBFBD><DFBE><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>׸<EFBFBD><D7B8><EFBFBD>
CalcMovieRect(m_movieWidth, m_movieHeight, movieRect);
if (FAILED(m_pPrimarySurface->Blt(&movieRect, pSurface, NULL, DDBLT_WAIT, NULL)))
{
GDIBlt(pSurface, &movieRect);
}
// <20>߰<EFBFBD><DFB0><EFBFBD> <20><>ŵ <20><><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD> Ű<><C5B0><EFBFBD><EFBFBD>ESC/<2F><><EFBFBD><20>Է½<D4B7> Ż<><C5BB>
if (bSkipAllowed && (KEY_DOWN(VK_LBUTTON) || KEY_DOWN(VK_ESCAPE) || KEY_DOWN(VK_SPACE)))
{
break;
}
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD> 2<><32> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>̵<EFBFBD><CCB5>ƿ<EFBFBD>
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<50><47> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵٰ<D1B4> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> <20>Ŵ<EFBFBD><C5B4><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ڵ<EFBFBD><DAB5><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20>ܺ<EFBFBD> <20>ڵ<EFBFBD>(ffdshow <20><>)<29><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʵ<EFBFBD><CAB5><EFBFBD> <20>Ѵ<EFBFBD>
// (<28><>Ÿ <20><><EFBFBD>ϵ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ڵ<EFBFBD><DAB5><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>)
hr = BuildFilterGraphManually(wPath, pAMStream, CLSID_MPEG1Splitter, CLSID_CMpegVideoCodec, CLSID_CMpegAudioCodec);
}
else if (ext == "mp43")
{
// 2007-08-12, nuclei
// MPEG-4, MP3 <20>ڵ<EFBFBD><DAB5><EFBFBD> <20>̿<EFBFBD><CCBF><EFBFBD> AVI<56><49> <20><><EFBFBD><EFBFBD> <20>߰<EFBFBD><><C8AE><EFBFBD>ڴ<EFBFBD> .mp43<34><33><EFBFBD><EFBFBD> <20>ؾ<EFBFBD><D8BE><EFBFBD>)
hr = BuildFilterGraphManually(wPath, pAMStream, CLSID_AviSplitter, CLSID_MP4VideoCodec, CLSID_MP3AudioCodec);
}
else
{
hr = pAMStream->OpenFile(wPath, 0);
}
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> hr<68><72> S_OK
if (SUCCEEDED(hr))
{
pAMStream->QueryInterface(IID_IMultiMediaStream, (void**) ppMMStream);
}
pAMStream->Release();
return hr;
}
//----------------------------------------------------------------------------------------------------
// Ư<><C6AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ȭ<><C8AD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ų<EFBFBD> <20><><EFBFBD>ο<EFBFBD><CEBF><EFBFBD>
//
HRESULT CMovieMan::RenderPostEffectFadeOut(IDirectDrawSurface *pSurface, int fadeOutDuration, DWORD fadeOutColor)
{
// Lock <20>ɱ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʱ<EFBFBD>ȭ
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;
}
// <20><><EFBFBD><EFBFBD><31><C8B8> <20><><EFBFBD>ǽ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> <20><><EFBFBD><EFBFBD><E7BABB> FadeOut ó<><C3B3><EFBFBD>Ѵ<EFBFBD>
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);
}
// <20>ȼ<EFBFBD> <20>ö<EFBFBD><C3B6><EFBFBD>(32<33><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);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ٲ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>̹<EFBFBD><CCB9><EFBFBD> <20>׸<EFBFBD><D7B8><EFBFBD>
RECT movieRect;
CalcMovieRect(m_movieWidth, m_movieHeight, movieRect);
if (FAILED(m_pPrimarySurface->Blt(&movieRect, pSurface, NULL, DDBLT_WAIT, NULL)))
{
GDIBlt(pSurface, &movieRect);
}
// <20><> <20>Ǵ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ĭ <20><>ä<EFBFBD><C3A4><EFBFBD><EFBFBD>
RECT upperRect, lowerRect;
CalcBackgroundRect(movieRect, upperRect, lowerRect);
FillRect(upperRect, (fadeOutColorRed << 16) | (fadeOutColorGreen << 8) | fadeOutColorBlue);
FillRect(lowerRect, (fadeOutColorRed << 16) | (fadeOutColorGreen << 8) | fadeOutColorBlue);
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
if (m_pBasicAudio)
{
m_pBasicAudio->put_Volume((long)(-10000 * fadeProgress));
}
}
// <20>޸<EFBFBD><DEB8><EFBFBD> <20><><EFBFBD><EFBFBD>
free(pCopiedSrcSurBuf);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1.0<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> FadeOut<75><74> ȭ<><C8AD> <20>׸<EFBFBD><D7B8><EFBFBD>
RECT windowRect;
GetWindowRect(windowRect);
FillRect(windowRect, fadeOutColor);
return S_OK;
}
//----------------------------------------------------------------------------------------------------
// MPEG-1 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ܺ<EFBFBD> <20>ڵ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20>Լ<EFBFBD>
//
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);
// <20><><EFBFBD><EFBFBD> MP43 <20><><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD> <20><><EFBFBD>ٸ<EFBFBD> DMO <20>ڵ<EFBFBD><DAB5><EFBFBD> <20><><EFBFBD><EFBFBD> <20>־<EFBFBD><D6BE>ش<EFBFBD>
// MONSTER<45><52><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߰ߵ<DFB0> <20><><EFBFBD>̽<EFBFBD>(<28>ڵ<EFBFBD><DAB5><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>)
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))
{
// <20><><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD> Output <20>ɵ<EFBFBD><C9B5><EFBFBD> <20><>Ÿ<EFBFBD><C5B8><EFBFBD><EFBFBD>
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<69><6E> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
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))
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
hr = pGraphBuilder->Render(pOutPin);
pInPin->Release();
pOutPin->Release();
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>Ͽ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ִ<EFBFBD>
if (pSplitterAudioOutPin && pAudioFilter)
{
pAudioFilter->EnumPins(&pEnumPins);
pEnumPins->Next(1, &pInPin, NULL);
pEnumPins->Next(1, &pOutPin, NULL);
pEnumPins->Release();
pGraphBuilder->Connect(pSplitterAudioOutPin, pInPin);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD> <20>Ѿ <20><> <20><><EFBFBD><EFBFBD>
pGraphBuilder->Render(pOutPin);
pInPin->Release();
pOutPin->Release();
}
}
}
// <20><><EFBFBD><EFBFBD>
//#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