Пользовательские асинхронные результируемые объекты
В этом разделе описывается реализация интерфейса IMFAsyncResult .
Редко требуется написать пользовательскую реализацию интерфейса IMFAsyncResult . Почти во всех случаях достаточно стандартной реализации Media Foundation. (Эта реализация возвращается функцией MFCreateAsyncResult .) Однако при написании пользовательской реализации необходимо учитывать некоторые проблемы.
Во-первых, реализация должна наследовать структуру MFASYNCRESULT . Рабочие очереди Media Foundation используют эту структуру внутри для отправки операции. Инициализируйте все элементы структуры равными нулю, за исключением элемента pCallback , который содержит указатель на интерфейс обратного вызова вызывающего объекта.
Во-вторых, объект должен вызвать MFLockPlatform в конструкторе, чтобы заблокировать платформу Media Foundation. Вызовите 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.
}
};
Связанные темы