Media Foundation의 특성
특성은 키/값 쌍입니다. 여기서 키는 GUID이고 값은 PROPVARIANT. 특성은 Microsoft Media Foundation 전체에서 개체를 구성하고 미디어 형식을 설명하고 개체 속성을 쿼리하는 데 사용됩니다.
이 항목에는 다음 섹션이 포함되어 있습니다.
- 특성 대한
- 특성 직렬화
- IMFAttributes 구현
- 관련 항목
특성 정보
특성은 키/값 쌍입니다. 여기서 키는 GUID이고 값은 PROPVARIANT. 특성 값은 다음 데이터 형식으로 제한됩니다.
- 부호 없는 32비트 정수(UINT32)입니다.
- 부호 없는 64비트 정수(UINT64)입니다.
- 64비트 부동 소수점 숫자입니다.
- GUID입니다.
- Null로 끝나는 와이드 문자열입니다.
- 바이트 배열입니다.
- IUnknown 포인터를.
이러한 형식은 MF_ATTRIBUTE_TYPE 열거형에 정의됩니다. 특성 값을 설정하거나 검색하려면 IMFAttributes 인터페이스를 사용합니다. 이 인터페이스에는 데이터 형식별로 값을 가져와서 설정하는 형식이 안전한 메서드가 포함되어 있습니다. 예를 들어 32비트 정수로 설정하려면 IMFAttributes::SetUINT32호출합니다. 특성 키는 개체 내에서 고유합니다. 동일한 키를 사용하여 서로 다른 두 값을 설정하면 두 번째 값이 첫 번째 값을 덮어씁니다.
여러 Media Foundation 인터페이스는 IMFAttributes 인터페이스를 상속합니다. 이 인터페이스를 노출하는 개체에는 애플리케이션이 개체에 설정해야 하는 선택적 또는 필수 특성이 있거나 애플리케이션에서 검색할 수 있는 특성이 있습니다. 또한 일부 메서드와 함수는 IMFAttributes 포인터를 매개 변수로 사용하여 애플리케이션이 구성 정보를 설정할 수 있도록 합니다. 애플리케이션은 구성 특성을 보유할 특성 저장소를 만들어야 합니다. 빈 특성 저장소를 만들려면 MFCreateAttributes호출합니다.
다음 코드에서는 두 가지 함수를 보여 줍니다. 첫 번째는 새 특성 저장소를 만들고 문자열 값이 있는 MY_ATTRIBUTE 가상 특성을 설정합니다. 두 번째 함수는 이 특성의 값을 검색합니다.
extern const GUID MY_ATTRIBUTE;
HRESULT ShowCreateAttributeStore(IMFAttributes **ppAttributes)
{
IMFAttributes *pAttributes = NULL;
const UINT32 cElements = 10; // Starting size.
// Create the empty attribute store.
HRESULT hr = MFCreateAttributes(&pAttributes, cElements);
// Set the MY_ATTRIBUTE attribute with a string value.
if (SUCCEEDED(hr))
{
hr = pAttributes->SetString(
MY_ATTRIBUTE,
L"This is a string value"
);
}
// Return the IMFAttributes pointer to the caller.
if (SUCCEEDED(hr))
{
*ppAttributes = pAttributes;
(*ppAttributes)->AddRef();
}
SAFE_RELEASE(pAttributes);
return hr;
}
HRESULT ShowGetAttributes()
{
IMFAttributes *pAttributes = NULL;
WCHAR *pwszValue = NULL;
UINT32 cchLength = 0;
// Create the attribute store.
HRESULT hr = ShowCreateAttributeStore(&pAttributes);
// Get the attribute.
if (SUCCEEDED(hr))
{
hr = pAttributes->GetAllocatedString(
MY_ATTRIBUTE,
&pwszValue,
&cchLength
);
}
CoTaskMemFree(pwszValue);
SAFE_RELEASE(pAttributes);
return hr;
}
Media Foundation 특성의 전체 목록은 Media Foundation 특성참조하세요. 각 특성에 대한 예상 데이터 형식이 설명되어 있습니다.
특성 직렬화
Media Foundation에는 특성 저장소를 직렬화하는 두 가지 함수가 있습니다. 하나는 바이트 배열에 특성을 쓰고, 다른 하나는 IStream 인터페이스를 지원하는 스트림에 씁니다. 각 함수에는 데이터를 로드하는 해당 함수가 있습니다.
수술 | 바이트 배열 | IStream |
---|---|---|
구해내다 | MFGetAttributesAsBlob | MFSerializeAttributesToStream |
부하 | MFInitAttributesFromBlob | MFDeserializeAttributesFromStream |
특성 저장소의 내용을 바이트 배열에 쓰려면 MFGetAttributesAsBlob호출합니다. IUnknown 포인터 값이 있는 특성은 무시됩니다. 특성을 다시 특성 저장소로 로드하려면 MFInitAttributesFromBlob호출합니다.
스트림에 특성 저장소를 쓰려면 MFSerializeAttributesToStream호출합니다. 이 함수는 IUnknown 포인터 값을 마샬링할 수 있습니다. 호출자는 IStream 인터페이스를 구현하는 스트림 개체를 제공해야 합니다. 스트림에서 특성 저장소를 로드하려면 MFDeserializeAttributesFromStream호출합니다.
IMFAttributes 구현
Media Foundation은 MFCreateAttributes 함수를 호출하여 얻은 IMFAttributes주식 구현을 제공합니다. 대부분의 경우 이 구현을 사용해야 하며 사용자 고유의 사용자 지정 구현을 제공하지 않아야 합니다.
IMFAttributes 인터페이스를 구현해야 할 수 있는 한 가지 상황이 있습니다. IMFAttributes상속하는 두 번째 인터페이스를 구현하는 경우. 이 경우 두 번째 인터페이스에서 상속된 IMFAttributes 메서드에 대한 구현을 제공해야 합니다.
이 경우 IMFAttributes기존 Media Foundation 구현을 래핑하는 것이 좋습니다. 다음 코드는 IMFAttributes 포인터를 보유하고 IUnknown 메서드를 제외하고 모든 IMFAttributes 메서드를 래핑하는 클래스 템플릿을 보여 줍니다.
#include <assert.h>
// Helper class to implement IMFAttributes.
// This is an abstract class; the derived class must implement the IUnknown
// methods. This class is a wrapper for the standard attribute store provided
// in Media Foundation.
// template parameter:
// The interface you are implementing, either IMFAttributes or an interface
// that inherits IMFAttributes, such as IMFActivate
template <class IFACE=IMFAttributes>
class CBaseAttributes : public IFACE
{
protected:
IMFAttributes *m_pAttributes;
// This version of the constructor does not initialize the
// attribute store. The derived class must call Initialize() in
// its own constructor.
CBaseAttributes() : m_pAttributes(NULL)
{
}
// This version of the constructor initializes the attribute
// store, but the derived class must pass an HRESULT parameter
// to the constructor.
CBaseAttributes(HRESULT& hr, UINT32 cInitialSize = 0) : m_pAttributes(NULL)
{
hr = Initialize(cInitialSize);
}
// The next version of the constructor uses a caller-provided
// implementation of IMFAttributes.
// (Sometimes you want to delegate IMFAttributes calls to some
// other object that implements IMFAttributes, rather than using
// MFCreateAttributes.)
CBaseAttributes(HRESULT& hr, IUnknown *pUnk)
{
hr = Initialize(pUnk);
}
virtual ~CBaseAttributes()
{
if (m_pAttributes)
{
m_pAttributes->Release();
}
}
// Initializes the object by creating the standard Media Foundation attribute store.
HRESULT Initialize(UINT32 cInitialSize = 0)
{
if (m_pAttributes == NULL)
{
return MFCreateAttributes(&m_pAttributes, cInitialSize);
}
else
{
return S_OK;
}
}
// Initializes this object from a caller-provided attribute store.
// pUnk: Pointer to an object that exposes IMFAttributes.
HRESULT Initialize(IUnknown *pUnk)
{
if (m_pAttributes)
{
m_pAttributes->Release();
m_pAttributes = NULL;
}
return pUnk->QueryInterface(IID_PPV_ARGS(&m_pAttributes));
}
public:
// IMFAttributes methods
STDMETHODIMP GetItem(REFGUID guidKey, PROPVARIANT* pValue)
{
assert(m_pAttributes);
return m_pAttributes->GetItem(guidKey, pValue);
}
STDMETHODIMP GetItemType(REFGUID guidKey, MF_ATTRIBUTE_TYPE* pType)
{
assert(m_pAttributes);
return m_pAttributes->GetItemType(guidKey, pType);
}
STDMETHODIMP CompareItem(REFGUID guidKey, REFPROPVARIANT Value, BOOL* pbResult)
{
assert(m_pAttributes);
return m_pAttributes->CompareItem(guidKey, Value, pbResult);
}
STDMETHODIMP Compare(
IMFAttributes* pTheirs,
MF_ATTRIBUTES_MATCH_TYPE MatchType,
BOOL* pbResult
)
{
assert(m_pAttributes);
return m_pAttributes->Compare(pTheirs, MatchType, pbResult);
}
STDMETHODIMP GetUINT32(REFGUID guidKey, UINT32* punValue)
{
assert(m_pAttributes);
return m_pAttributes->GetUINT32(guidKey, punValue);
}
STDMETHODIMP GetUINT64(REFGUID guidKey, UINT64* punValue)
{
assert(m_pAttributes);
return m_pAttributes->GetUINT64(guidKey, punValue);
}
STDMETHODIMP GetDouble(REFGUID guidKey, double* pfValue)
{
assert(m_pAttributes);
return m_pAttributes->GetDouble(guidKey, pfValue);
}
STDMETHODIMP GetGUID(REFGUID guidKey, GUID* pguidValue)
{
assert(m_pAttributes);
return m_pAttributes->GetGUID(guidKey, pguidValue);
}
STDMETHODIMP GetStringLength(REFGUID guidKey, UINT32* pcchLength)
{
assert(m_pAttributes);
return m_pAttributes->GetStringLength(guidKey, pcchLength);
}
STDMETHODIMP GetString(REFGUID guidKey, LPWSTR pwszValue, UINT32 cchBufSize, UINT32* pcchLength)
{
assert(m_pAttributes);
return m_pAttributes->GetString(guidKey, pwszValue, cchBufSize, pcchLength);
}
STDMETHODIMP GetAllocatedString(REFGUID guidKey, LPWSTR* ppwszValue, UINT32* pcchLength)
{
assert(m_pAttributes);
return m_pAttributes->GetAllocatedString(guidKey, ppwszValue, pcchLength);
}
STDMETHODIMP GetBlobSize(REFGUID guidKey, UINT32* pcbBlobSize)
{
assert(m_pAttributes);
return m_pAttributes->GetBlobSize(guidKey, pcbBlobSize);
}
STDMETHODIMP GetBlob(REFGUID guidKey, UINT8* pBuf, UINT32 cbBufSize, UINT32* pcbBlobSize)
{
assert(m_pAttributes);
return m_pAttributes->GetBlob(guidKey, pBuf, cbBufSize, pcbBlobSize);
}
STDMETHODIMP GetAllocatedBlob(REFGUID guidKey, UINT8** ppBuf, UINT32* pcbSize)
{
assert(m_pAttributes);
return m_pAttributes->GetAllocatedBlob(guidKey, ppBuf, pcbSize);
}
STDMETHODIMP GetUnknown(REFGUID guidKey, REFIID riid, LPVOID* ppv)
{
assert(m_pAttributes);
return m_pAttributes->GetUnknown(guidKey, riid, ppv);
}
STDMETHODIMP SetItem(REFGUID guidKey, REFPROPVARIANT Value)
{
assert(m_pAttributes);
return m_pAttributes->SetItem(guidKey, Value);
}
STDMETHODIMP DeleteItem(REFGUID guidKey)
{
assert(m_pAttributes);
return m_pAttributes->DeleteItem(guidKey);
}
STDMETHODIMP DeleteAllItems()
{
assert(m_pAttributes);
return m_pAttributes->DeleteAllItems();
}
STDMETHODIMP SetUINT32(REFGUID guidKey, UINT32 unValue)
{
assert(m_pAttributes);
return m_pAttributes->SetUINT32(guidKey, unValue);
}
STDMETHODIMP SetUINT64(REFGUID guidKey,UINT64 unValue)
{
assert(m_pAttributes);
return m_pAttributes->SetUINT64(guidKey, unValue);
}
STDMETHODIMP SetDouble(REFGUID guidKey, double fValue)
{
assert(m_pAttributes);
return m_pAttributes->SetDouble(guidKey, fValue);
}
STDMETHODIMP SetGUID(REFGUID guidKey, REFGUID guidValue)
{
assert(m_pAttributes);
return m_pAttributes->SetGUID(guidKey, guidValue);
}
STDMETHODIMP SetString(REFGUID guidKey, LPCWSTR wszValue)
{
assert(m_pAttributes);
return m_pAttributes->SetString(guidKey, wszValue);
}
STDMETHODIMP SetBlob(REFGUID guidKey, const UINT8* pBuf, UINT32 cbBufSize)
{
assert(m_pAttributes);
return m_pAttributes->SetBlob(guidKey, pBuf, cbBufSize);
}
STDMETHODIMP SetUnknown(REFGUID guidKey, IUnknown* pUnknown)
{
assert(m_pAttributes);
return m_pAttributes->SetUnknown(guidKey, pUnknown);
}
STDMETHODIMP LockStore()
{
assert(m_pAttributes);
return m_pAttributes->LockStore();
}
STDMETHODIMP UnlockStore()
{
assert(m_pAttributes);
return m_pAttributes->UnlockStore();
}
STDMETHODIMP GetCount(UINT32* pcItems)
{
assert(m_pAttributes);
return m_pAttributes->GetCount(pcItems);
}
STDMETHODIMP GetItemByIndex(UINT32 unIndex, GUID* pguidKey, PROPVARIANT* pValue)
{
assert(m_pAttributes);
return m_pAttributes->GetItemByIndex(unIndex, pguidKey, pValue);
}
STDMETHODIMP CopyAllItems(IMFAttributes* pDest)
{
assert(m_pAttributes);
return m_pAttributes->CopyAllItems(pDest);
}
// Helper functions
HRESULT SerializeToStream(DWORD dwOptions, IStream* pStm)
// dwOptions: Flags from MF_ATTRIBUTE_SERIALIZE_OPTIONS
{
assert(m_pAttributes);
return MFSerializeAttributesToStream(m_pAttributes, dwOptions, pStm);
}
HRESULT DeserializeFromStream(DWORD dwOptions, IStream* pStm)
{
assert(m_pAttributes);
return MFDeserializeAttributesFromStream(m_pAttributes, dwOptions, pStm);
}
// SerializeToBlob: Stores the attributes in a byte array.
//
// ppBuf: Receives a pointer to the byte array.
// pcbSize: Receives the size of the byte array.
//
// The caller must free the array using CoTaskMemFree.
HRESULT SerializeToBlob(UINT8 **ppBuffer, UINT32 *pcbSize)
{
assert(m_pAttributes);
if (ppBuffer == NULL)
{
return E_POINTER;
}
if (pcbSize == NULL)
{
return E_POINTER;
}
*ppBuffer = NULL;
*pcbSize = 0;
UINT32 cbSize = 0;
BYTE *pBuffer = NULL;
HRESULT hr = MFGetAttributesAsBlobSize(m_pAttributes, &cbSize);
if (FAILED(hr))
{
return hr;
}
pBuffer = (BYTE*)CoTaskMemAlloc(cbSize);
if (pBuffer == NULL)
{
return E_OUTOFMEMORY;
}
hr = MFGetAttributesAsBlob(m_pAttributes, pBuffer, cbSize);
if (SUCCEEDED(hr))
{
*ppBuffer = pBuffer;
*pcbSize = cbSize;
}
else
{
CoTaskMemFree(pBuffer);
}
return hr;
}
HRESULT DeserializeFromBlob(const UINT8* pBuffer, UINT cbSize)
{
assert(m_pAttributes);
return MFInitAttributesFromBlob(m_pAttributes, pBuffer, cbSize);
}
HRESULT GetRatio(REFGUID guidKey, UINT32* pnNumerator, UINT32* punDenominator)
{
assert(m_pAttributes);
return MFGetAttributeRatio(m_pAttributes, guidKey, pnNumerator, punDenominator);
}
HRESULT SetRatio(REFGUID guidKey, UINT32 unNumerator, UINT32 unDenominator)
{
assert(m_pAttributes);
return MFSetAttributeRatio(m_pAttributes, guidKey, unNumerator, unDenominator);
}
// Gets an attribute whose value represents the size of something (eg a video frame).
HRESULT GetSize(REFGUID guidKey, UINT32* punWidth, UINT32* punHeight)
{
assert(m_pAttributes);
return MFGetAttributeSize(m_pAttributes, guidKey, punWidth, punHeight);
}
// Sets an attribute whose value represents the size of something (eg a video frame).
HRESULT SetSize(REFGUID guidKey, UINT32 unWidth, UINT32 unHeight)
{
assert(m_pAttributes);
return MFSetAttributeSize (m_pAttributes, guidKey, unWidth, unHeight);
}
};
다음 코드는 이 템플릿에서 클래스를 파생하는 방법을 보여줍니다.
#include <shlwapi.h>
class MyObject : public CBaseAttributes<>
{
MyObject() : m_nRefCount(1) { }
~MyObject() { }
long m_nRefCount;
public:
// IUnknown
STDMETHODIMP MyObject::QueryInterface(REFIID riid, void** ppv)
{
static const QITAB qit[] =
{
QITABENT(MyObject, IMFAttributes),
{ 0 },
};
return QISearch(this, qit, riid, ppv);
}
STDMETHODIMP_(ULONG) MyObject::AddRef()
{
return InterlockedIncrement(&m_nRefCount);
}
STDMETHODIMP_(ULONG) MyObject::Release()
{
ULONG uCount = InterlockedDecrement(&m_nRefCount);
if (uCount == 0)
{
delete this;
}
return uCount;
}
// Static function to create an instance of the object.
static HRESULT CreateInstance(MyObject **ppObject)
{
HRESULT hr = S_OK;
MyObject *pObject = new MyObject();
if (pObject == NULL)
{
return E_OUTOFMEMORY;
}
// Initialize the attribute store.
hr = pObject->Initialize();
if (FAILED(hr))
{
delete pObject;
return hr;
}
*ppObject = pObject;
(*ppObject)->AddRef();
return S_OK;
}
};
특성 저장소를 만들려면 CBaseAttributes::Initialize
호출해야 합니다. 이전 예제에서는 정적 생성 함수 내에서 수행됩니다.
템플릿 인수는 인터페이스 형식이며, 기본값은IMFAttributes입니다. 개체가 IMFAttributes상속하는 인터페이스(예: IMFActivate)를 구현하는 경우 템플릿 인수를 파생 인터페이스의 이름과 동일하게 설정합니다.
관련 항목