IMediaBuffer 구현
[이 페이지와 연결된 기능인 DirectShow는 레거시 기능입니다. MediaPlayer, IMFMediaEngine 및 Media Foundation의 오디오/비디오 캡처로 대체되었습니다. 이러한 기능은 Windows 10 및 Windows 11 최적화되었습니다. 가능한 경우 새 코드에서 DirectShow 대신 MediaPlayer, IMFMediaEngine 및 오디오/비디오 캡처를 사용하는 것이 좋습니다. 가능한 경우 레거시 API를 사용하는 기존 코드를 다시 작성하여 새 API를 사용하도록 제안합니다.]
기본 DMO 스트리밍 모델에서 버퍼는 IMediaBuffer 인터페이스를 통해 관리됩니다. DMO의 클라이언트는 이 인터페이스를 노출하는 개체를 구현해야 합니다. IMediaBuffer 인터페이스에는 다음 세 가지 메서드가 있습니다.
- GetBufferAndLength 는 버퍼의 주소(즉, 데이터를 보유하는 실제 메모리 블록)와 버퍼에 있는 유효한 데이터의 크기를 반환합니다.
- GetMaxLength 는 버퍼의 크기를 반환합니다.
- SetLength 는 버퍼에 있는 유효한 데이터의 길이를 지정합니다.
현재 위치 처리에는 IMediaBuffer 인터페이스가 필요하지 않습니다. 다음 코드는 IMediaBuffer의 최소 구현을 보여줍니다.
// CMediaBuffer class.
#include <dmo.h>
class CMediaBuffer : public IMediaBuffer
{
private:
DWORD m_cbLength;
const DWORD m_cbMaxLength;
LONG m_nRefCount; // Reference count
BYTE *m_pbData;
CMediaBuffer(DWORD cbMaxLength, HRESULT& hr) :
m_nRefCount(1),
m_cbMaxLength(cbMaxLength),
m_cbLength(0),
m_pbData(NULL)
{
m_pbData = new BYTE[cbMaxLength];
if (!m_pbData)
{
hr = E_OUTOFMEMORY;
}
}
~CMediaBuffer()
{
if (m_pbData)
{
delete [] m_pbData;
}
}
public:
// Function to create a new IMediaBuffer object and return
// an AddRef'd interface pointer.
static HRESULT Create(long cbMaxLen, IMediaBuffer **ppBuffer)
{
HRESULT hr = S_OK;
CMediaBuffer *pBuffer = NULL;
if (ppBuffer == NULL)
{
return E_POINTER;
}
pBuffer = new CMediaBuffer(cbMaxLen, hr);
if (pBuffer == NULL)
{
hr = E_OUTOFMEMORY;
}
if (SUCCEEDED(hr))
{
*ppBuffer = pBuffer;
(*ppBuffer)->AddRef();
}
if (pBuffer)
{
pBuffer->Release();
}
return hr;
}
// IUnknown methods.
STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
{
if (ppv == NULL)
{
return E_POINTER;
}
else if (riid == IID_IMediaBuffer || riid == IID_IUnknown)
{
*ppv = static_cast<IMediaBuffer *>(this);
AddRef();
return S_OK;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
}
STDMETHODIMP_(ULONG) AddRef()
{
return InterlockedIncrement(&m_nRefCount);
}
STDMETHODIMP_(ULONG) Release()
{
LONG lRef = InterlockedDecrement(&m_nRefCount);
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;
}
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)
{
// Either parameter can be NULL, but not both.
if (ppbBuffer == NULL && pcbLength == NULL)
{
return E_POINTER;
}
if (ppbBuffer)
{
*ppbBuffer = m_pbData;
}
if (pcbLength)
{
*pcbLength = m_cbLength;
}
return S_OK;
}
};
관련 항목