common > Utils.cpp

「common/Utils.cpp」の編集履歴(バックアップ)一覧はこちら

common/Utils.cpp」(2009/07/09 (木) 05:36:46) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

//------------------------------------------------------------------------------------ // $Id: Utils.cpp,v 1.10 2006/04/11 01:13:06 ivanr Exp $ // // Desc: DirectShow utility class implementation // // Copyright (c) Blackmagic Design 2005. All rights reserved. //------------------------------------------------------------------------------------ #include "stdafx.h" #include "Utils.h" //----------------------------------------------------------------------------- // CDSUtils - Directshow utility class //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // AddFilter // Attempts to locate a filter of a given class ID and name and add it to the graph HRESULT CDSUtils::AddFilter(IGraphBuilder* pGraph, const GUID &clsid, LPCWSTR pName, IBaseFilter** ppFilter) { HRESULT hr = S_OK; if (pGraph && pName && ppFilter) { *ppFilter = NULL; IBaseFilter* pFilter = NULL; hr = CoCreateInstance(clsid, 0, CLSCTX_INPROC_SERVER, IID_IBaseFilter, reinterpret_cast<void**>(&pFilter)); if (SUCCEEDED(hr)) { hr = pGraph->AddFilter(pFilter, pName); if (SUCCEEDED(hr)) { *ppFilter = pFilter; } else { SAFE_RELEASE(pFilter); } } } else { hr = E_INVALIDARG; } return hr; } //----------------------------------------------------------------------------- // AddFilter2 // Attempts to locate a filter of a given class category and name HRESULT CDSUtils::AddFilter2(IGraphBuilder* pGraph, const GUID &clsid, LPCWSTR pName, IBaseFilter** ppFilter) { HRESULT hr = S_OK; if (pGraph && pName && ppFilter) { // first enumerate the system devices for the specifed class and filter name CComPtr<ICreateDevEnum> pSysDevEnum = NULL; hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, reinterpret_cast<void**>(&pSysDevEnum)); if (SUCCEEDED(hr)) { CComPtr<IEnumMoniker> pEnumCat = NULL; hr = pSysDevEnum->CreateClassEnumerator(clsid, &pEnumCat, 0); if (S_OK == hr) { IMoniker* pMoniker = NULL; bool Loop = true; while ((S_OK == pEnumCat->Next(1, &pMoniker, NULL)) && Loop) { IPropertyBag* pPropBag = NULL; hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, reinterpret_cast<void**>(&pPropBag)); if (SUCCEEDED(hr)) { VARIANT varName; VariantInit(&varName); hr = pPropBag->Read(L"FriendlyName", &varName, 0); if (SUCCEEDED(hr)) { if (0 == wcscmp(varName.bstrVal, pName)) { hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, reinterpret_cast<void**>(ppFilter)); Loop = false; } } VariantClear(&varName); // contained within a loop, decrement the reference count SAFE_RELEASE(pPropBag); } SAFE_RELEASE(pMoniker); } } } // if a filter has been located add it to the graph if (*ppFilter) { hr = pGraph->AddFilter(reinterpret_cast<IBaseFilter*>(*ppFilter), pName); } else { hr = E_FAIL; } } else { hr = E_INVALIDARG; } return hr; } //------------------------------------------------------------------------------------------------- // GetUnconnectedPin // Attemptes to locate an unconnected pin on filter HRESULT CDSUtils::GetUnconnectedPin(IBaseFilter* pFilter, PIN_DIRECTION PinDir, IPin** ppPin) { HRESULT hr = S_OK; if (pFilter && ppPin) { CComPtr<IEnumPins> pEnum = NULL; IPin* pPin = NULL; hr = pFilter->EnumPins(&pEnum); if (SUCCEEDED(hr)) { while (pEnum->Next(1, &pPin, NULL) == S_OK) { PIN_DIRECTION ThisPinDir; pPin->QueryDirection(&ThisPinDir); if (ThisPinDir == PinDir) { IPin* pPinTemp = NULL; hr = pPin->ConnectedTo(&pPinTemp); if (SUCCEEDED(hr)) { SAFE_RELEASE(pPinTemp); } else { // unconnected, return this pin *ppPin = pPin; hr = S_OK; break; } } SAFE_RELEASE(pPin); } } if (NULL == *ppPin) { // failed to find an unconnected pin hr = E_FAIL; } } else { hr = E_INVALIDARG; } return hr; } //----------------------------------------------------------------------------- // GetPin // Find the pin of the specified name on the given filter // This method leaves an outstanding reference on the pin if successful HRESULT CDSUtils::GetPin(IBaseFilter* pFilter, const wchar_t* pName, IPin** ppPin) { HRESULT hr = S_OK; if (pFilter && pName && ppPin) { CComPtr<IEnumPins> pIEnumPins = NULL; hr = pFilter->EnumPins(&pIEnumPins); if (SUCCEEDED(hr)) { IPin* pIPin = NULL; while (S_OK == pIEnumPins->Next(1, &pIPin, NULL)) { PIN_INFO info = {0}; hr = pIPin->QueryPinInfo(&info); if (SUCCEEDED(hr)) { SAFE_RELEASE(info.pFilter); if (0 == wcsncmp(info.achName, pName, wcslen(pName))) { // matched the pin category *ppPin = pIPin; break; } } SAFE_RELEASE(pIPin); } } if (NULL == *ppPin) { // failed to find the named pin hr = E_FAIL; } } else { hr = E_INVALIDARG; } return hr; } //----------------------------------------------------------------------------- // GetPin // Find the pin of the specified format type on the given filter // This method leaves an outstanding reference on the pin if successful HRESULT CDSUtils::GetPin(IBaseFilter* pFilter, const GUID* pFormat, PIN_DIRECTION PinDir, IPin** ppPin) { HRESULT hr = S_OK; if (pFilter && pFormat && ppPin) { CComPtr<IEnumPins> pIEnumPins = NULL; hr = pFilter->EnumPins(&pIEnumPins); if (SUCCEEDED(hr)) { // find the pin with the specified format IPin* pIPin = NULL; while (S_OK == pIEnumPins->Next(1, &pIPin, NULL)) { // match the pin direction PIN_DIRECTION pinDir; pIPin->QueryDirection(&pinDir); if (pinDir == PinDir) { // match pin direction check the first media type returned from the upstream pin CComPtr<IEnumMediaTypes> pIEnumMT = NULL; hr = pIPin->EnumMediaTypes(&pIEnumMT); if (SUCCEEDED(hr)) { AM_MEDIA_TYPE* pmt = NULL; hr = pIEnumMT->Next(1, &pmt, NULL); if (S_OK == hr) { if (pmt->majortype == *pFormat) { // found the pin with the specified format *ppPin = pIPin; DeleteMediaType(pmt); break; } else { DeleteMediaType(pmt); } } } } SAFE_RELEASE(pIPin); } if (NULL == *ppPin) { // failed to find the named pin hr = E_FAIL; } } } else { hr = E_INVALIDARG; } return hr; } //----------------------------------------------------------------------------- // ConnectFiltersNamedPin // Connects two filters using the pin names, if no name is supplied the first // unconnected pin is used HRESULT CDSUtils::ConnectFilters(IGraphBuilder* pGraph, IBaseFilter* pUpstream, wchar_t* pUpstreamPinName, IBaseFilter* pDownstream, wchar_t* pDownstreamPinName) { HRESULT hr = S_OK; if (pUpstream && pDownstream) { // get the upstream output pin CComPtr<IPin> pIPinOutput = NULL; if (pUpstreamPinName) { hr = GetPin(pUpstream, pUpstreamPinName, &pIPinOutput); } else { hr = GetUnconnectedPin(pUpstream, PINDIR_OUTPUT, &pIPinOutput); } if (SUCCEEDED(hr)) { // get the downstream input pin CComPtr<IPin> pIPinInput = NULL; if (pDownstreamPinName) { hr = GetPin(pDownstream, pDownstreamPinName, &pIPinInput); } else { hr = GetUnconnectedPin(pDownstream, PINDIR_INPUT, &pIPinInput); } if (SUCCEEDED(hr)) { // connect the pins hr = pGraph->Connect(pIPinOutput, pIPinInput); } } } else { hr = E_INVALIDARG; } return hr; } //----------------------------------------------------------------------------- // ConnectFilters // Connects two filters by finding a pin on the upstream filter with the specified // major format type, e.g. For connecting an audio pin to a downstream filter HRESULT CDSUtils::ConnectFilters(IGraphBuilder* pGraph, IBaseFilter* pUpstream, IBaseFilter* pDownstream, const GUID* pFormat) { HRESULT hr = S_OK; if (pUpstream && pDownstream && pFormat) { // find the upstream output pin with the specified format CComPtr<IPin> pIPinOutput = NULL; hr = GetPin(pUpstream, pFormat, PINDIR_OUTPUT, &pIPinOutput); if (SUCCEEDED(hr)) { // get the downstream input pin CComPtr<IPin> pIPinInput = NULL; hr = GetPin(pDownstream, pFormat, PINDIR_INPUT, &pIPinInput); if (SUCCEEDED(hr)) { // connect the pins hr = pGraph->Connect(pIPinOutput, pIPinInput); } } } else { hr = E_INVALIDARG; } return hr; } //----------------------------------------------------------------------------- // RenderFilter // Renders the named output pin of the filter, or the first unconnected output if // no name is provided HRESULT CDSUtils::RenderFilter(IGraphBuilder* pGraph, IBaseFilter* pUpstream, wchar_t* pUpstreamPinName) { HRESULT hr = S_OK; if (pUpstream) { CComPtr<IPin> pIPinOutput = NULL; if (pUpstreamPinName) { hr = GetPin(pUpstream, pUpstreamPinName, &pIPinOutput); } else { hr = GetUnconnectedPin(pUpstream, PINDIR_OUTPUT, &pIPinOutput); } if (SUCCEEDED(hr)) { hr = pGraph->Render(pIPinOutput); } } else { hr = E_INVALIDARG; } return hr; } //----------------------------------------------------------------------------- // DisconnectAllPins // Disconnect all the pins of the filters in a graph HRESULT CDSUtils::DisconnectAllPins(IGraphBuilder* pGraph) { HRESULT hr = S_OK; if (pGraph) { CComPtr<IEnumFilters> pIEnumFilters = NULL; hr = pGraph->EnumFilters(&pIEnumFilters); if (SUCCEEDED(hr)) { IBaseFilter* pFilter = NULL; while (S_OK == pIEnumFilters->Next(1, &pFilter, NULL)) { CComPtr<IEnumPins> pIEnumPins = NULL; hr = pFilter->EnumPins(&pIEnumPins); if (SUCCEEDED(hr)) { IPin* pIPin = NULL; while (S_OK == pIEnumPins->Next(1, &pIPin, NULL)) { IPin* pIPinConnection = NULL; if (S_OK == pIPin->ConnectedTo(&pIPinConnection)) { // pins are connected, to disconnect filters, both pins must be disconnected hr = pGraph->Disconnect(pIPin); hr = pGraph->Disconnect(pIPinConnection); SAFE_RELEASE(pIPinConnection); } SAFE_RELEASE(pIPin); } } SAFE_RELEASE(pFilter); } } } else { hr = E_INVALIDARG; } return hr; } //----------------------------------------------------------------------------- // FindFilterInterface // Attempt to locate the specified interface HRESULT CDSUtils::FindFilterInterface(IBaseFilter* pFilter, const IID& riid, void** ppvInterface) { HRESULT hr = S_OK; if (pFilter && ppvInterface) { hr = pFilter->QueryInterface(riid, ppvInterface); } else { hr = E_INVALIDARG; } return hr; } //----------------------------------------------------------------------------- // FindPinInterface // Attempt to locate the interface on the named pin or on the first pin if no // name is provided. HRESULT CDSUtils::FindPinInterface(IBaseFilter* pFilter, wchar_t* pName, const IID& riid, void** ppvInterface) { HRESULT hr = S_OK; if (pFilter && ppvInterface) { CComPtr<IPin> pIPin = NULL; if (pName) { hr = GetPin(pFilter, pName, &pIPin); } else { CComPtr<IEnumPins> pIEnumPins = NULL; hr = pFilter->EnumPins(&pIEnumPins); if (SUCCEEDED(hr)) { hr = pIEnumPins->Next(1, &pIPin, NULL); } } if (SUCCEEDED(hr)) { hr = pIPin->QueryInterface(riid, ppvInterface); } } else { hr = E_INVALIDARG; } return hr; } //----------------------------------------------------------------------------- // FindPinInterface // Attempt to locate the interface on the pin with the specified format or on the first pin if no // format is provided. HRESULT CDSUtils::FindPinInterface(IBaseFilter* pFilter, const GUID* pFormat, PIN_DIRECTION PinDir, const IID& riid, void** ppvInterface) { HRESULT hr = S_OK; if (pFilter && ppvInterface) { CComPtr<IPin> pIPin = NULL; if (pFormat) { hr = GetPin(pFilter, pFormat, PinDir, &pIPin); } else { CComPtr<IEnumPins> pIEnumPins = NULL; hr = pFilter->EnumPins(&pIEnumPins); if (SUCCEEDED(hr)) { hr = pIEnumPins->Next(1, &pIPin, NULL); } } if (SUCCEEDED(hr)) { hr = pIPin->QueryInterface(riid, ppvInterface); } } else { hr = E_INVALIDARG; } return hr; } //----------------------------------------------------------------------------- // AddGraphToRot // Adds a DirectShow filter graph to the Running Object Table, // allowing GraphEdit to "spy" on a remote filter graph. HRESULT CDSUtils::AddGraphToRot(IUnknown* pUnkGraph, DWORD* pdwRegister) { HRESULT hr = S_OK; if (pUnkGraph && pdwRegister) { CComPtr<IRunningObjectTable> pROT = NULL; hr = GetRunningObjectTable(0, &pROT); if (SUCCEEDED(hr)) { WCHAR wsz[128]; StringCchPrintfW(wsz, 128, L"FilterGraph %08x pid %08x\0", (DWORD_PTR)pUnkGraph, GetCurrentProcessId()); CComPtr<IMoniker> pMoniker = NULL; hr = CreateItemMoniker(L"!", wsz, &pMoniker); if(SUCCEEDED(hr)) { // Use the ROTFLAGS_REGISTRATIONKEEPSALIVE to ensure a strong reference // to the object. Using this flag will cause the object to remain // registered until it is explicitly revoked with the Revoke() method. // // Not using this flag means that if GraphEdit remotely connects // to this graph and then GraphEdit exits, this object registration // will be deleted, causing future attempts by GraphEdit to fail until // this application is restarted or until the graph is registered again. hr = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, pUnkGraph, pMoniker, pdwRegister); } } } else { hr = E_INVALIDARG; } return hr; } //----------------------------------------------------------------------------- // RemoveGraphFromRot // Removes a filter graph from the Running Object Table void CDSUtils::RemoveGraphFromRot(DWORD pdwRegister) { CComPtr<IRunningObjectTable> pROT = NULL; if (SUCCEEDED(GetRunningObjectTable(0, &pROT))) { pROT->Revoke(pdwRegister); } } //------------------------------------------------------------------------------------ // CRegUtils - Registry utility class //------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------ // Constructor // CRegUtils::CRegUtils() : m_hKey(NULL) { } //------------------------------------------------------------------------------------ // Destructor // CRegUtils::~CRegUtils() { Close(); } //------------------------------------------------------------------------------------ // Open // Opens the specified subkey LONG CRegUtils::Open(LPCTSTR lpSubKey) { Close(); m_subKeyName = "Software\\Blackmagic Design\\Samples\\"; m_subKeyName += lpSubKey; return RegOpenKeyEx(HKEY_LOCAL_MACHINE, m_subKeyName.c_str(), 0, KEY_ALL_ACCESS, &m_hKey); } //------------------------------------------------------------------------------------ // Create // Creates the specified subkey LONG CRegUtils::Create(LPCTSTR lpSubKey) { Close(); m_subKeyName = "Software\\Blackmagic Design\\Samples\\"; m_subKeyName += lpSubKey; return RegCreateKeyEx(HKEY_LOCAL_MACHINE, m_subKeyName.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &m_hKey, NULL); } //------------------------------------------------------------------------------------ // Close // Closes the subkey void CRegUtils::Close() { RegCloseKey(m_hKey); m_hKey = NULL; m_subKeyName.empty(); } //------------------------------------------------------------------------------------ // SetString // Set the key for the named value of type string LONG CRegUtils::SetString(LPCTSTR valueName, const BYTE* lpData, DWORD cbData) { return RegSetValueEx(m_hKey, valueName, 0, REG_SZ, lpData, cbData); } //------------------------------------------------------------------------------------ // GetString // Query the key for the named value of type string LONG CRegUtils::GetString(LPCTSTR valueName, LPBYTE lpData, DWORD cbData) { LONG ret = ERROR_SUCCESS; DWORD size = cbData, type = 0; ret = RegQueryValueEx(m_hKey, valueName, NULL, &type, lpData, &size); if ((size != cbData) || (REG_SZ != type)) { ret = ERROR_INVALID_PARAMETER; } return ret; } //------------------------------------------------------------------------------------ // SetBinary // Set the key for the named value of type binary LONG CRegUtils::SetBinary(LPCTSTR valueName, const BYTE* lpData, DWORD cbData) { return RegSetValueEx(m_hKey, valueName, 0, REG_BINARY, lpData, cbData); } //------------------------------------------------------------------------------------ // GetBinary // Query the key for the named value of type binary LONG CRegUtils::GetBinary(LPCTSTR valueName, LPBYTE lpData, DWORD cbData) { LONG ret = ERROR_SUCCESS; DWORD size = cbData, type = 0; ret = RegQueryValueEx(m_hKey, valueName, NULL, &type, lpData, &size); if ((size != cbData) || (REG_BINARY != type)) { ret = ERROR_INVALID_PARAMETER; } return ret; } //------------------------------------------------------------------------------------ // SetDword // Set the key for the named value of type DWORD LONG CRegUtils::SetDword(LPCTSTR valueName, const BYTE* lpData, DWORD cbData) { return RegSetValueEx(m_hKey, valueName, 0, REG_DWORD, lpData, cbData); } //------------------------------------------------------------------------------------ // GetDword // Query the key for the named value of type DWORD LONG CRegUtils::GetDword(LPCTSTR valueName, LPBYTE lpData, DWORD cbData) { LONG ret = ERROR_SUCCESS; DWORD size = cbData, type = 0; ret = RegQueryValueEx(m_hKey, valueName, NULL, &type, lpData, &size); if ((size != cbData) || (REG_DWORD != type)) { ret = ERROR_INVALID_PARAMETER; } return ret; } //------------------------------------------------------------------------------------ // CUtils - utility class //------------------------------------------------------------------------------------ //----------------------------------------------------------------------------- // GetBMIHeader // Returns the BITMAPINFOHEADER structure from media type format extension BITMAPINFOHEADER* CUtils::GetBMIHeader(const AM_MEDIA_TYPE* pamt) { BITMAPINFOHEADER* pbmih = NULL; if (pamt) { if (FORMAT_VideoInfo == pamt->formattype) { VIDEOINFOHEADER* pvih = reinterpret_cast<VIDEOINFOHEADER*>(pamt->pbFormat); ASSERT(sizeof(VIDEOINFOHEADER) <= pamt->cbFormat); pbmih = &pvih->bmiHeader; } else if (FORMAT_VideoInfo2 == pamt->formattype) { VIDEOINFOHEADER2* pvih = reinterpret_cast<VIDEOINFOHEADER2*>(pamt->pbFormat); ASSERT(sizeof(VIDEOINFOHEADER2) <= pamt->cbFormat); pbmih = &pvih->bmiHeader; } } return pbmih; } //----------------------------------------------------------------------------- // GetBMIHeader // Returns the BITMAPINFOHEADER structure from media type format extension BITMAPINFOHEADER* CUtils::GetBMIHeader(const CMediaType& mt) { BITMAPINFOHEADER* pbmih = NULL; if (FORMAT_VideoInfo == mt.formattype) { VIDEOINFOHEADER* pvih = reinterpret_cast<VIDEOINFOHEADER*>(mt.pbFormat); ASSERT(sizeof(VIDEOINFOHEADER) <= mt.cbFormat); pbmih = &pvih->bmiHeader; } else if (FORMAT_VideoInfo2 == mt.formattype) { VIDEOINFOHEADER2* pvih = reinterpret_cast<VIDEOINFOHEADER2*>(mt.pbFormat); ASSERT(sizeof(VIDEOINFOHEADER2) <= mt.cbFormat); pbmih = &pvih->bmiHeader; } return pbmih; } //----------------------------------------------------------------------------- // GetAvgTimePerFrame // Returns the average time per frame from media type format extension REFERENCE_TIME CUtils::GetAvgTimePerFrame(const AM_MEDIA_TYPE* pamt) { REFERENCE_TIME rtAvgTimePerFrame = 0; if (pamt) { if (FORMAT_VideoInfo == pamt->formattype) { VIDEOINFOHEADER* pvih = reinterpret_cast<VIDEOINFOHEADER*>(pamt->pbFormat); ASSERT(sizeof(VIDEOINFOHEADER) <= pamt->cbFormat); rtAvgTimePerFrame = pvih->AvgTimePerFrame; } else if (FORMAT_VideoInfo2 == pamt->formattype) { VIDEOINFOHEADER2* pvih = reinterpret_cast<VIDEOINFOHEADER2*>(pamt->pbFormat); ASSERT(sizeof(VIDEOINFOHEADER2) <= pamt->cbFormat); rtAvgTimePerFrame = pvih->AvgTimePerFrame; } } return rtAvgTimePerFrame; } //------------------------------------------------------------------------------------ // GetImageSize // Calculates the image size unsigned long CUtils::GetImageSize(BITMAPINFOHEADER* pbmih) { unsigned long dwImageSize = 0; if (pbmih) { switch (pbmih->biCompression) { default: case BI_RGB: dwImageSize = (pbmih->biWidth * abs(pbmih->biHeight) * pbmih->biBitCount) >> 3; break; case 'YVYU': case '2YUY': dwImageSize = (pbmih->biWidth * abs(pbmih->biHeight) * 16) >> 3; break; } } return dwImageSize; }

表示オプション

横に並べて表示:
変化行の前後のみ表示:
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。