#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