Microsoft DirectX 9.0 |
In the default DMO streaming model, buffers are managed through the IMediaBuffer interface. The client of the DMO is responsible for implementing an object that exposes this interface. The IMediaBuffer interface has three methods:
In-place processing does not require the IMediaBuffer interface. The following code shows a minimal implementation of IMediaBuffer:
// CMediaBuffer class.
#include <new>
#include <dmo.h>
class CMediaBuffer : public IMediaBuffer
{
private:
DWORD m_cbLength;
const DWORD m_cbMaxLength;
LONG m_cRef;
BYTE *m_pbData;
public:
CMediaBuffer(DWORD cbMaxLength) :
m_cRef(0),
m_cbMaxLength(cbMaxLength),
m_cbLength(0),
m_pbData(NULL)
{
m_pbData = new BYTE[cbMaxLength];
if (!m_pbData) throw std::bad_alloc();
}
~CMediaBuffer()
{
if (m_pbData) {
delete [] m_pbData;
}
}
// Function to create a new IMediaBuffer object and return
// an AddRef'd interface pointer.
static HRESULT CreateBuffer(long cbMaxLen, REFIID iid, void **ppUnk)
{
try {
CMediaBuffer *pBuffer = new CMediaBuffer(cbMaxLen);
return pBuffer->QueryInterface(iid, ppUnk);
}
catch (std::bad_alloc)
{
return E_OUTOFMEMORY;
}
}
// IUnknown methods.
STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
{
if (ppv == NULL) {
return E_POINTER;
}
if (riid == IID_IMediaBuffer || riid == IID_IUnknown) {
*ppv = static_cast<IMediaBuffer *>(this);
AddRef();
return S_OK;
}
*ppv = NULL;
return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) AddRef()
{
return InterlockedIncrement(&m_cRef);
}
STDMETHODIMP_(ULONG) Release()
{
LONG lRef = InterlockedDecrement(&m_cRef);
if (lRef == 0) {
delete this;
// m_cRef is no longer valid! Return lRef.
}
return lRef;
}
// IMediaBuffer methods.
STDMETHODIMP SetLength(DWORD cbLength)
{
if (cbLength > m_cbMaxLength) {
return E_INVALIDARG;
} else {
m_cbLength = cbLength;
return S_OK;
}
}
STDMETHODIMP GetMaxLength(DWORD *pcbMaxLength)
{
if (pcbMaxLength == NULL) {
return E_POINTER;
}
*pcbMaxLength = m_cbMaxLength;
return S_OK;
}
STDMETHODIMP GetBufferAndLength(BYTE **ppbBuffer, DWORD *pcbLength)
{
if (ppbBuffer == NULL || pcbLength == NULL) {
return E_POINTER;
}
*ppbBuffer = m_pbData;
*pcbLength = m_cbLength;
return S_OK;
}
};