// // CDXGraph.cpp // #include "stdafx.h" #include #include "CDXGraph.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif //////////////////////////////////////////////////////////////////////////////// CDXGraph::CDXGraph() { mGraph = NULL; mMediaControl = NULL; mEvent = NULL; mBasicVideo = NULL; mBasicAudio = NULL; mVideoWindow = NULL; mSeeking = NULL; mObjectTableEntry = 0; } CDXGraph::~CDXGraph() { Release(); } bool CDXGraph::Create(void) { if (!mGraph) { if (SUCCEEDED(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&mGraph))) { AddToObjectTable(); return QueryInterfaces(); } mGraph = 0; } return false; } bool CDXGraph::QueryInterfaces(void) { if (mGraph) { HRESULT hr = NOERROR; hr |= mGraph->QueryInterface(IID_IMediaControl, (void **)&mMediaControl); hr |= mGraph->QueryInterface(IID_IMediaEventEx, (void **)&mEvent); hr |= mGraph->QueryInterface(IID_IBasicVideo, (void **)&mBasicVideo); hr |= mGraph->QueryInterface(IID_IBasicAudio, (void **)&mBasicAudio); hr |= mGraph->QueryInterface(IID_IVideoWindow, (void **)&mVideoWindow); hr |= mGraph->QueryInterface(IID_IMediaSeeking, (void **)&mSeeking); if (mSeeking) { mSeeking->SetTimeFormat(&TIME_FORMAT_MEDIA_TIME); } return SUCCEEDED(hr); } return false; } void CDXGraph::Release(void) { if (mSeeking) { mSeeking->Release(); mSeeking = NULL; } if (mMediaControl) { mMediaControl->Release(); mMediaControl = NULL; } if (mEvent) { mEvent->Release(); mEvent = NULL; } if (mBasicVideo) { mBasicVideo->Release(); mBasicVideo = NULL; } if (mBasicAudio) { mBasicAudio->Release(); mBasicAudio = NULL; } if (mVideoWindow) { mVideoWindow->put_Visible(OAFALSE); mVideoWindow->put_MessageDrain((OAHWND)NULL); mVideoWindow->put_Owner(OAHWND(0)); mVideoWindow->Release(); mVideoWindow = NULL; } RemoveFromObjectTable(); if (mGraph) { mGraph->Release(); mGraph = NULL; } } bool CDXGraph::Attach(IGraphBuilder * inGraphBuilder) { Release(); if (inGraphBuilder) { inGraphBuilder->AddRef(); mGraph = inGraphBuilder; AddToObjectTable(); return QueryInterfaces(); } return true; } IGraphBuilder * CDXGraph::GetGraph(void) { return mGraph; } IMediaEventEx * CDXGraph::GetEventHandle(void) { return mEvent; } // Connect filter from the upstream output pin to the downstream input pin bool CDXGraph::ConnectFilters(IPin * inOutputPin, IPin * inInputPin, const AM_MEDIA_TYPE * inMediaType) { if (mGraph && inOutputPin && inInputPin) { HRESULT hr = mGraph->ConnectDirect(inOutputPin, inInputPin, inMediaType); return SUCCEEDED(hr) ? true : false; } return false; } void CDXGraph::DisconnectFilters(IPin * inOutputPin) { if (mGraph && inOutputPin) { HRESULT hr = mGraph->Disconnect(inOutputPin); } } bool CDXGraph::SetDisplayWindow(HWND inWindow) { if (mVideoWindow) { // long lVisible; // mVideoWindow->get_Visible(&lVisible); // Hide the video window first mVideoWindow->put_Visible(OAFALSE); mVideoWindow->put_Owner((OAHWND)inWindow); RECT windowRect; ::GetClientRect(inWindow, &windowRect); mVideoWindow->put_Left(0); mVideoWindow->put_Top(0); mVideoWindow->put_Width(windowRect.right - windowRect.left); mVideoWindow->put_Height(windowRect.bottom - windowRect.top); mVideoWindow->put_WindowStyle(WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS); mVideoWindow->put_MessageDrain((OAHWND) inWindow); // Restore the video window if (inWindow != NULL) { // mVideoWindow->put_Visible(lVisible); mVideoWindow->put_Visible(OATRUE); } else { mVideoWindow->put_Visible(OAFALSE); } return true; } return false; } bool CDXGraph::ResizeVideoWindow(long inLeft, long inTop, long inWidth, long inHeight) { if (mVideoWindow) { long lVisible = OATRUE; mVideoWindow->get_Visible(&lVisible); // Hide the video window first mVideoWindow->put_Visible(OAFALSE); mVideoWindow->put_Left(inLeft); mVideoWindow->put_Top(inTop); mVideoWindow->put_Width(inWidth); mVideoWindow->put_Height(inHeight); // Restore the video window mVideoWindow->put_Visible(lVisible); return true; } return false; } bool CDXGraph::SetNotifyWindow(HWND inWindow) { if (mEvent) { mEvent->SetNotifyWindow((OAHWND)inWindow, WM_GRAPHNOTIFY, 0); return true; } return false; } void CDXGraph::HandleEvent(WPARAM inWParam, LPARAM inLParam) { if (mEvent) { long eventCode = 0; LONG_PTR eventParam1 = 0, eventParam2 = 0; while (SUCCEEDED(mEvent->GetEvent(&eventCode, &eventParam1, &eventParam2, 0))) { mEvent->FreeEventParams(eventCode, eventParam1, eventParam2); switch (eventCode) { case EC_COMPLETE: break; case EC_USERABORT: case EC_ERRORABORT: break; default: break; } } } } bool CDXGraph::Run(void) { if (mGraph && mMediaControl) { if (!IsRunning()) { if (SUCCEEDED(mMediaControl->Run())) { return true; } } else { return true; } } return false; } bool CDXGraph::Stop(void) { if (mGraph && mMediaControl) { if (!IsStopped()) { if (SUCCEEDED(mMediaControl->Stop())) { return true; } } else { return true; } } return false; } bool CDXGraph::Pause(void) { if (mGraph && mMediaControl) { if (!IsPaused()) { if (SUCCEEDED(mMediaControl->Pause())) { return true; } } else { return true; } } return false; } bool CDXGraph::IsRunning(void) { if (mGraph && mMediaControl) { OAFilterState state = State_Stopped; if (SUCCEEDED(mMediaControl->GetState(10, &state))) { return state == State_Running; } } return false; } bool CDXGraph::IsStopped(void) { if (mGraph && mMediaControl) { OAFilterState state = State_Stopped; if (SUCCEEDED(mMediaControl->GetState(10, &state))) { return state == State_Stopped; } } return false; } bool CDXGraph::IsPaused(void) { if (mGraph && mMediaControl) { OAFilterState state = State_Stopped; if (SUCCEEDED(mMediaControl->GetState(10, &state))) { return state == State_Paused; } } return false; } bool CDXGraph::SetFullScreen(BOOL inEnabled) { if (mVideoWindow) { HRESULT hr = mVideoWindow->put_FullScreenMode(inEnabled ? OATRUE : OAFALSE); return SUCCEEDED(hr); } return false; } bool CDXGraph::GetFullScreen(void) { if (mVideoWindow) { long fullScreenMode = OAFALSE; mVideoWindow->get_FullScreenMode(&fullScreenMode); return (fullScreenMode == OATRUE); } return false; } // IMediaSeeking features bool CDXGraph::GetCurrentPosition(double * outPosition) { if (mSeeking) { __int64 position = 0; if (SUCCEEDED(mSeeking->GetCurrentPosition(&position))) { *outPosition = ((double)position) / 10000000.; return true; } } return false; } bool CDXGraph::GetStopPosition(double * outPosition) { if (mSeeking) { __int64 position = 0; if (SUCCEEDED(mSeeking->GetStopPosition(&position))) { *outPosition = ((double)position) / 10000000.; return true; } } return false; } bool CDXGraph::SetCurrentPosition(double inPosition) { if (mSeeking) { __int64 one = 10000000; __int64 position = (__int64)(one * inPosition); //HRESULT hr = mSeeking->SetPositions(&position, AM_SEEKING_AbsolutePositioning | AM_SEEKING_SeekToKeyFrame, // 0, AM_SEEKING_NoPositioning); HRESULT hr = mSeeking->SetPositions(&position, AM_SEEKING_AbsolutePositioning, 0, AM_SEEKING_NoPositioning); return SUCCEEDED(hr); } return false; } bool CDXGraph::SetStartStopPosition(double inStart, double inStop) { if (mSeeking) { __int64 one = 10000000; __int64 startPos = (__int64)(one * inStart); __int64 stopPos = (__int64)(one * inStop); HRESULT hr = mSeeking->SetPositions(&startPos, AM_SEEKING_AbsolutePositioning | AM_SEEKING_SeekToKeyFrame, &stopPos, AM_SEEKING_AbsolutePositioning | AM_SEEKING_SeekToKeyFrame); return SUCCEEDED(hr); } return false; } bool CDXGraph::GetDuration(double * outDuration) { if (mSeeking) { __int64 length = 0; if (SUCCEEDED(mSeeking->GetDuration(&length))) { *outDuration = ((double)length) / 10000000.; return true; } } return false; } bool CDXGraph::SetPlaybackRate(double inRate) { if (mSeeking) { if (SUCCEEDED(mSeeking->SetRate(inRate))) { return true; } } return false; } // Attention: range from -10000 to 0, and 0 is FULL_VOLUME. bool CDXGraph::SetAudioVolume(long inVolume) { if (mBasicAudio) { HRESULT hr = mBasicAudio->put_Volume(inVolume); return SUCCEEDED(hr); } return false; } long CDXGraph::GetAudioVolume(void) { long volume = 0; if (mBasicAudio) { mBasicAudio->get_Volume(&volume); } return volume; } // Attention: range from -10000(left) to 10000(right), and 0 is both. bool CDXGraph::SetAudioBalance(long inBalance) { if (mBasicAudio) { HRESULT hr = mBasicAudio->put_Balance(inBalance); return SUCCEEDED(hr); } return false; } long CDXGraph::GetAudioBalance(void) { long balance = 0; if (mBasicAudio) { mBasicAudio->get_Balance(&balance); } return balance; } bool CDXGraph::RenderFile(const TCHAR * inFile) { if (mGraph) { #ifdef _UNICODE if (SUCCEEDED(mGraph->RenderFile(inFile, NULL))) #else WCHAR szFilePath[MAX_PATH]; MultiByteToWideChar(CP_ACP, 0, inFile, -1, szFilePath, MAX_PATH); if (SUCCEEDED(mGraph->RenderFile(szFilePath, NULL))) #endif { return true; } } return false; } bool CDXGraph::SnapshotBitmap(const TCHAR * outFile) { if (mBasicVideo) { long bitmapSize = 0; if (SUCCEEDED(mBasicVideo->GetCurrentImage(&bitmapSize, 0))) { bool pass = false; unsigned char * buffer = new unsigned char[bitmapSize]; if (SUCCEEDED(mBasicVideo->GetCurrentImage(&bitmapSize, (long *)buffer))) { BITMAPFILEHEADER hdr; LPBITMAPINFOHEADER lpbi; lpbi = (LPBITMAPINFOHEADER)buffer; int nColors = 1 << lpbi->biBitCount; if (nColors > 256) nColors = 0; hdr.bfType = ((WORD) ('M' << 8) | 'B'); //always is "BM" hdr.bfSize = bitmapSize + sizeof( hdr ); hdr.bfReserved1 = 0; hdr.bfReserved2 = 0; hdr.bfOffBits = (DWORD) (sizeof(BITMAPFILEHEADER) + lpbi->biSize + nColors * sizeof(RGBQUAD)); CFile bitmapFile(outFile, CFile::modeReadWrite | CFile::modeCreate | CFile::typeBinary); bitmapFile.Write(&hdr, sizeof(BITMAPFILEHEADER)); bitmapFile.Write(buffer, bitmapSize); bitmapFile.Close(); pass = true; } delete [] buffer; return pass; } } return false; } //////////////////////// For GraphEdit Dubug purpose ///////////////////////////// void CDXGraph::AddToObjectTable(void) { IMoniker * pMoniker = 0; IRunningObjectTable * objectTable = 0; if (SUCCEEDED(GetRunningObjectTable(0, &objectTable))) { WCHAR wsz[256]; wsprintfW(wsz, L"FilterGraph %08p pid %08x", (DWORD_PTR)mGraph, GetCurrentProcessId()); HRESULT hr = CreateItemMoniker(L"!", wsz, &pMoniker); if (SUCCEEDED(hr)) { hr = objectTable->Register(0, mGraph, pMoniker, &mObjectTableEntry); pMoniker->Release(); } objectTable->Release(); } } void CDXGraph::RemoveFromObjectTable(void) { IRunningObjectTable * objectTable = 0; if (SUCCEEDED(GetRunningObjectTable(0, &objectTable))) { objectTable->Revoke(mObjectTableEntry); objectTable->Release(); mObjectTableEntry = 0; } }