カスタム非同期結果オブジェクト
このトピックでは、 IMFAsyncResult インターフェイスを実装する方法について説明します。
IMFAsyncResult インターフェイスのカスタム実装を記述する必要はまれです。 ほとんどの場合、標準的な Media Foundation の実装で十分です。 (この実装は MFCreateAsyncResult 関数によって返されます)。ただし、カスタム実装を記述する場合は、注意すべきいくつかの問題があります。
まず、実装で MFASYNCRESULT 構造体を継承する必要があります。 Media Foundation 作業キューは、この構造体を内部的に使用して操作をディスパッチします。 呼び出し元のコールバック インターフェイスへのポインターを含む pCallback メンバーを除き、すべての構造体メンバーを 0 に初期化します。
次に、Media Foundation プラットフォームをロックするには、オブジェクトのコンストラクターで MFLockPlatform を呼び出す必要があります。 MFUnlockPlatform を呼び出して、プラットフォームのロックを解除します。 これらの関数は、オブジェクトが破棄される前にプラットフォームがシャットダウンされるのを防ぐのに役立ちます。 詳細については、「 作業キュー」を参照してください。
次のコードは、 IMFAsyncResult インターフェイスの基本的な実装を示しています。 示されているように、このコードでは、標準の Media Foundation 実装以外の追加機能は提供されません。
///////////////////////////////////////////////////////////////////////////////
// CMyAsyncResult
//
// Custom implementation of IMFAsyncResult. All implementations of this
// interface must inherit the MFASYNCRESULT structure.
//
///////////////////////////////////////////////////////////////////////////////
class CMyAsyncResult : public MFASYNCRESULT
{
protected:
LONG m_cRef; // Reference count.
BOOL m_bLockPlatform; // Locked the Media Foundation platform?
IUnknown* m_pState; // Caller's state object.
IUnknown* m_pObject; // Optional object. See IMFAsyncResult::GetObject.
// Constructor.
CMyAsyncResult(IMFAsyncCallback *pCallback, IUnknown *pState, HRESULT *phr) :
m_cRef(1),
m_bLockPlatform(FALSE),
m_pObject(NULL),
m_pState(pState)
{
*phr = MFLockPlatform();
m_bLockPlatform = TRUE;
// Initialize the MFASYNCRESULT members.
ZeroMemory(&this->overlapped, sizeof(OVERLAPPED));
hrStatusResult = S_OK;
dwBytesTransferred = 0;
hEvent = NULL;
this->pCallback = pCallback;
if (pCallback)
{
this->pCallback->AddRef();
}
if (m_pState)
{
m_pState->AddRef();
}
}
virtual ~CMyAsyncResult()
{
SafeRelease(&pCallback);
SafeRelease(&m_pState);
SafeRelease(&m_pObject);
if (m_bLockPlatform)
{
MFUnlockPlatform();
}
}
public:
// Static method to create an instance of this object.
static HRESULT CreateInstance(
IMFAsyncCallback *pCallback, // Callback to invoke.
IUnknown *pState, // Optional state object.
CMyAsyncResult **ppResult // Receives a pointer to the object.
)
{
HRESULT hr = S_OK;
*ppResult = NULL;
CMyAsyncResult *pResult =
new (std::nothrow) CMyAsyncResult(pCallback, pState, &hr);
if (pResult == NULL)
{
return E_OUTOFMEMORY;
}
if (FAILED(hr))
{
delete pResult;
return hr;
}
// If the callback is NULL, create an event that will be signaled.
if (pCallback == NULL)
{
pResult->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (pResult->hEvent == NULL)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
}
if (SUCCEEDED(hr))
{
*ppResult = pResult; // Return the pointer to the caller.
}
else
{
pResult->Release();
}
return hr;
}
// SetObject: Sets the optional result object.
// (This method is not part of the interface.)
HRESULT SetObject(IUnknown *pObject)
{
SafeRelease(&m_pObject);
m_pObject = pObject;
if (pObject)
{
m_pObject->AddRef();
}
return S_OK;
}
// IUnknown methods.
STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
{
static const QITAB qit[] =
{
QITABENT(CMyAsyncResult, IMFAsyncResult),
{ 0 }
};
return QISearch(this, qit, riid, ppv);
}
STDMETHODIMP_(ULONG) AddRef()
{
return InterlockedIncrement(&m_cRef);
}
STDMETHODIMP_(ULONG) Release()
{
LONG cRef = InterlockedDecrement(&m_cRef);
if (cRef == 0)
{
delete this;
}
return cRef;
}
// IMFAsyncResult methods.
STDMETHODIMP GetState(IUnknown** ppunkState)
{
if (ppunkState == NULL)
{
return E_POINTER;
}
*ppunkState = m_pState;
if (m_pState)
{
(*ppunkState)->AddRef();
}
return S_OK;
}
STDMETHODIMP GetStatus( void)
{
return hrStatusResult;
}
STDMETHODIMP STDMETHODCALLTYPE SetStatus(HRESULT hrStatus)
{
hrStatusResult = hrStatus;
return S_OK;
}
STDMETHODIMP GetObject(IUnknown **ppObject)
{
if (ppObject == NULL)
{
return E_POINTER;
}
*ppObject = m_pObject;
if (m_pObject)
{
(*ppObject)->AddRef();
}
return S_OK;
}
IUnknown* STDMETHODCALLTYPE GetStateNoAddRef()
{
return m_pState; // Warning! Can be NULL.
}
};
関連トピック