Microsoft Media Foundation官方文档翻译(9、10)《Media Foundation Primitives》《Attributes in Media Foundation》

官方英文文档链接:https://docs.microsoft.com/en-us/windows/desktop/medfound/media-foundation-primitives

基于05/31/2018

 

Media Foundation 定义了几种在整个 Media Foundation API 中都会用到的基本对象类型。

TopicDescription
Attributes Attributes 和 properties 是存储在对象中的键值对
Media Types 描述媒体格式
Media Buffers 管理一块内存,并且可以在对象之间分享
Media Samples 是包含了 media buffer 列表的对象

官方英文文档链接:https://docs.microsoft.com/en-us/windows/desktop/medfound/attributes-and-properties

基于05/31/2018

 

Attribute(属性) 是键值对,key 是 GUID,value 是一个 PROPVARIANT。Microsoft Media Foundation 中使用 attribute 用来配置对象,描述媒体格式,查询对象属性等等。

此文包含以下内容。

About Attributes

Attribute 是键值对,key 是 GUID,value 是一个 PROPVARIANT。Attribute 值仅限以下几种类型:

  • Unsigned 32-bit integer (UINT32).
  • Unsigned 64-bit integer (UINT64).
  • 64-bit floating-point number.
  • GUID.
  • Null-terminated wide-character string.
  • Byte array.
  • IUnknown pointer.

这些类型定义在 MF_ATTRIBUTE_TYPE 枚举中。如果需要设置或检索 Attribute,使用 IMFAttributes 接口。这个接口在设置数据的时候会使用“类型安全”(就是根据数据类型调用不同的方法)的方法。例如要设置一个32位 int,就调用 IMFAttributes::SetUINT32。 Attribute keys 在一个对象中是唯一的,如果对同一个 key 设置了两次不同的数值,那么第二次会覆盖第一次。

很多 Media Foundation 接口都继承了 IMFAttributes 接口。应用程序应该通过对象设置这些属性,bjects that expose this interface have optional or mandatory attributes that the application should set on the object, or have attributes that the application can retrieve. 此外,某些方法将 IMFAttributes 指针作为参数传递,使应用程序能够进行设置。应用程序必须创建一个新的 attribute 对象来存储设置。要创建新的 attribute ,调用 MFCreateAttributes

下面的代码包含两个方法。第一个方法创建了一个新的 attribute 对象来存储设置,这个属性叫做 MY_ATTRIBUTE ,值是一个 string。第二个函数获取此属性的值。

 

 1 extern const GUID MY_ATTRIBUTE;
 2 
 3 HRESULT ShowCreateAttributeStore(IMFAttributes **ppAttributes)
 4 {
 5     IMFAttributes *pAttributes = NULL;
 6     const UINT32 cElements = 10;  // Starting size.
 7 
 8     // Create the empty attribute store.
 9     HRESULT hr = MFCreateAttributes(&pAttributes, cElements);
10 
11     // Set the MY_ATTRIBUTE attribute with a string value.
12     if (SUCCEEDED(hr))
13     {
14         hr = pAttributes->SetString(
15             MY_ATTRIBUTE,
16             L"This is a string value"
17             );
18     }
19 
20     // Return the IMFAttributes pointer to the caller.
21     if (SUCCEEDED(hr))
22     {
23         *ppAttributes = pAttributes;
24         (*ppAttributes)->AddRef();
25     }
26 
27     SAFE_RELEASE(pAttributes);
28 
29     return hr;
30 }
31 
32 HRESULT ShowGetAttributes()
33 {
34     IMFAttributes *pAttributes = NULL;
35     WCHAR *pwszValue = NULL;
36     UINT32 cchLength = 0;
37 
38     // Create the attribute store.
39     HRESULT hr = ShowCreateAttributeStore(&pAttributes);
40 
41     // Get the attribute.
42     if (SUCCEEDED(hr))
43     {
44         hr = pAttributes->GetAllocatedString(
45             MY_ATTRIBUTE,
46             &pwszValue,
47             &cchLength
48             );
49     }
50 
51     CoTaskMemFree(pwszValue);
52     SAFE_RELEASE(pAttributes);
53 
54     return hr;
55 }

 

有关 Media Foundation 属性(attribute)的完整列表,查看 Media Foundation Attributes。. The expected data type for each attribute is documented there.

Serializing Attributes(序列化属性)

Media Foundation 有两个用于属性序列化存储的方法。一个是将属性写入一个数组,另一个是将属性写入支持 IStream 接口的流。每个方法都有一个对应的函数来加载属性(就是反向,还原)

OperationByte ArrayIStream
存储 MFGetAttributesAsBlob MFSerializeAttributesToStream
加载 MFInitAttributesFromBlob MFDeserializeAttributesFromStream

 

要将属性存储的内容写入数组,调用 MFGetAttributesAsBlob。值为 IUnknow 指针的属性将被忽略(?原话Attributes with IUnknown pointer values are ignored.)。要将属性加载回 attribute,调用 MFInitAttributesFromBlob

若要将属性存储写入流,调用 MFSerializeAttributesToStream。这个方法可以封装发送 IUnknown 指针值。调用者必须提供实现了 IStream 接口的对象。要把属性从流加载回 attribute 对象,调用 MFDeserializeAttributesFromStream

Implementing IMFAttributes

Media Foundation 提供了 IMFAttributes 的(stock implementation),包含在 MFCreateAttributes 中。大多数情况下应使用此实现。

不过这里有一种情况你需要自己去实现 IMFAttributes 接口:如果你要实现一个继承自 IMFAttributes 的接口,在这种情况下,你必须自己实现 IMFAttributes 的各个方法。

在这种情况下,建议建议包装 Media Foundation 对 IMFAttributes 的现有实现。下面的代码展示了一个类模板,该类包含一个 IMFAttributes 指针和所有的 IMFAttributes 方法(IUnknown除外)。

 

  1 #include <assert.h>
  2 
  3 // Helper class to implement IMFAttributes. 
  4 
  5 // This is an abstract class; the derived class must implement the IUnknown 
  6 // methods. This class is a wrapper for the standard attribute store provided 
  7 // in Media Foundation.
  8 
  9 // template parameter: 
 10 // The interface you are implementing, either IMFAttributes or an interface 
 11 // that inherits IMFAttributes, such as IMFActivate
 12 
 13 template <class IFACE=IMFAttributes>
 14 class CBaseAttributes : public IFACE
 15 {
 16 protected:
 17     IMFAttributes *m_pAttributes;
 18 
 19     // This version of the constructor does not initialize the 
 20     // attribute store. The derived class must call Initialize() in 
 21     // its own constructor.
 22     CBaseAttributes() : m_pAttributes(NULL)
 23     {
 24     }
 25 
 26     // This version of the constructor initializes the attribute 
 27     // store, but the derived class must pass an HRESULT parameter 
 28     // to the constructor.
 29 
 30     CBaseAttributes(HRESULT& hr, UINT32 cInitialSize = 0) : m_pAttributes(NULL)
 31     {
 32         hr = Initialize(cInitialSize);
 33     }
 34 
 35     // The next version of the constructor uses a caller-provided 
 36     // implementation of IMFAttributes.
 37 
 38     // (Sometimes you want to delegate IMFAttributes calls to some 
 39     // other object that implements IMFAttributes, rather than using 
 40     // MFCreateAttributes.)
 41 
 42     CBaseAttributes(HRESULT& hr, IUnknown *pUnk)
 43     {
 44         hr = Initialize(pUnk);
 45     }
 46 
 47     virtual ~CBaseAttributes()
 48     {
 49         if (m_pAttributes)
 50         {
 51             m_pAttributes->Release();
 52         }
 53     }
 54 
 55     // Initializes the object by creating the standard Media Foundation attribute store.
 56     HRESULT Initialize(UINT32 cInitialSize = 0)
 57     {
 58         if (m_pAttributes == NULL)
 59         {
 60             return MFCreateAttributes(&m_pAttributes, cInitialSize); 
 61         }
 62         else
 63         {
 64             return S_OK;
 65         }
 66     }
 67 
 68     // Initializes this object from a caller-provided attribute store.
 69     // pUnk: Pointer to an object that exposes IMFAttributes.
 70     HRESULT Initialize(IUnknown *pUnk)
 71     {
 72         if (m_pAttributes)
 73         {
 74             m_pAttributes->Release();
 75             m_pAttributes = NULL;
 76         }
 77 
 78 
 79         return pUnk->QueryInterface(IID_PPV_ARGS(&m_pAttributes));
 80     }
 81 
 82 public:
 83 
 84     // IMFAttributes methods
 85 
 86     STDMETHODIMP GetItem(REFGUID guidKey, PROPVARIANT* pValue)
 87     {
 88         assert(m_pAttributes);
 89         return m_pAttributes->GetItem(guidKey, pValue);
 90     }
 91 
 92     STDMETHODIMP GetItemType(REFGUID guidKey, MF_ATTRIBUTE_TYPE* pType)
 93     {
 94         assert(m_pAttributes);
 95         return m_pAttributes->GetItemType(guidKey, pType);
 96     }
 97 
 98     STDMETHODIMP CompareItem(REFGUID guidKey, REFPROPVARIANT Value, BOOL* pbResult)
 99     {
100         assert(m_pAttributes);
101         return m_pAttributes->CompareItem(guidKey, Value, pbResult);
102     }
103 
104     STDMETHODIMP Compare(
105         IMFAttributes* pTheirs, 
106         MF_ATTRIBUTES_MATCH_TYPE MatchType, 
107         BOOL* pbResult
108         )
109     {
110         assert(m_pAttributes);
111         return m_pAttributes->Compare(pTheirs, MatchType, pbResult);
112     }
113 
114     STDMETHODIMP GetUINT32(REFGUID guidKey, UINT32* punValue)
115     {
116         assert(m_pAttributes);
117         return m_pAttributes->GetUINT32(guidKey, punValue);
118     }
119 
120     STDMETHODIMP GetUINT64(REFGUID guidKey, UINT64* punValue)
121     {
122         assert(m_pAttributes);
123         return m_pAttributes->GetUINT64(guidKey, punValue);
124     }
125 
126     STDMETHODIMP GetDouble(REFGUID guidKey, double* pfValue)
127     {
128         assert(m_pAttributes);
129         return m_pAttributes->GetDouble(guidKey, pfValue);
130     }
131 
132     STDMETHODIMP GetGUID(REFGUID guidKey, GUID* pguidValue)
133     {
134         assert(m_pAttributes);
135         return m_pAttributes->GetGUID(guidKey, pguidValue);
136     }
137 
138     STDMETHODIMP GetStringLength(REFGUID guidKey, UINT32* pcchLength)
139     {
140         assert(m_pAttributes);
141         return m_pAttributes->GetStringLength(guidKey, pcchLength);
142     }
143 
144     STDMETHODIMP GetString(REFGUID guidKey, LPWSTR pwszValue, UINT32 cchBufSize, UINT32* pcchLength)
145     {
146         assert(m_pAttributes);
147         return m_pAttributes->GetString(guidKey, pwszValue, cchBufSize, pcchLength);
148     }
149 
150     STDMETHODIMP GetAllocatedString(REFGUID guidKey, LPWSTR* ppwszValue, UINT32* pcchLength)
151     {
152         assert(m_pAttributes);
153         return m_pAttributes->GetAllocatedString(guidKey, ppwszValue, pcchLength);
154     }
155 
156     STDMETHODIMP GetBlobSize(REFGUID guidKey, UINT32* pcbBlobSize)
157     {
158         assert(m_pAttributes);
159         return m_pAttributes->GetBlobSize(guidKey, pcbBlobSize);
160     }
161 
162     STDMETHODIMP GetBlob(REFGUID guidKey, UINT8* pBuf, UINT32 cbBufSize, UINT32* pcbBlobSize)
163     {
164         assert(m_pAttributes);
165         return m_pAttributes->GetBlob(guidKey, pBuf, cbBufSize, pcbBlobSize);
166     }
167 
168     STDMETHODIMP GetAllocatedBlob(REFGUID guidKey, UINT8** ppBuf, UINT32* pcbSize)
169     {
170         assert(m_pAttributes);
171         return m_pAttributes->GetAllocatedBlob(guidKey, ppBuf, pcbSize);
172     }
173 
174     STDMETHODIMP GetUnknown(REFGUID guidKey, REFIID riid, LPVOID* ppv)
175     {
176         assert(m_pAttributes);
177         return m_pAttributes->GetUnknown(guidKey, riid, ppv);
178     }
179 
180     STDMETHODIMP SetItem(REFGUID guidKey, REFPROPVARIANT Value)
181     {
182         assert(m_pAttributes);
183         return m_pAttributes->SetItem(guidKey, Value);
184     }
185 
186     STDMETHODIMP DeleteItem(REFGUID guidKey)
187     {
188         assert(m_pAttributes);
189         return m_pAttributes->DeleteItem(guidKey);
190     }
191 
192     STDMETHODIMP DeleteAllItems()
193     {
194         assert(m_pAttributes);
195         return m_pAttributes->DeleteAllItems();
196     }
197 
198     STDMETHODIMP SetUINT32(REFGUID guidKey, UINT32 unValue)
199     {
200         assert(m_pAttributes);
201         return m_pAttributes->SetUINT32(guidKey, unValue);
202     }
203 
204     STDMETHODIMP SetUINT64(REFGUID guidKey,UINT64 unValue)
205     {
206         assert(m_pAttributes);
207         return m_pAttributes->SetUINT64(guidKey, unValue);
208     }
209 
210     STDMETHODIMP SetDouble(REFGUID guidKey, double fValue)
211     {
212         assert(m_pAttributes);
213         return m_pAttributes->SetDouble(guidKey, fValue);
214     }
215 
216     STDMETHODIMP SetGUID(REFGUID guidKey, REFGUID guidValue)
217     {
218         assert(m_pAttributes);
219         return m_pAttributes->SetGUID(guidKey, guidValue);
220     }
221 
222     STDMETHODIMP SetString(REFGUID guidKey, LPCWSTR wszValue)
223     {
224         assert(m_pAttributes);
225         return m_pAttributes->SetString(guidKey, wszValue);
226     }
227 
228     STDMETHODIMP SetBlob(REFGUID guidKey, const UINT8* pBuf, UINT32 cbBufSize)
229     {
230         assert(m_pAttributes);
231         return m_pAttributes->SetBlob(guidKey, pBuf, cbBufSize);
232     }
233 
234     STDMETHODIMP SetUnknown(REFGUID guidKey, IUnknown* pUnknown)
235     {
236         assert(m_pAttributes);
237         return m_pAttributes->SetUnknown(guidKey, pUnknown);
238     }
239 
240     STDMETHODIMP LockStore()
241     {
242         assert(m_pAttributes);
243         return m_pAttributes->LockStore();
244     }
245 
246     STDMETHODIMP UnlockStore()
247     {
248         assert(m_pAttributes);
249         return m_pAttributes->UnlockStore();
250     }
251 
252     STDMETHODIMP GetCount(UINT32* pcItems)
253     {
254         assert(m_pAttributes);
255         return m_pAttributes->GetCount(pcItems);
256     }
257 
258     STDMETHODIMP GetItemByIndex(UINT32 unIndex, GUID* pguidKey, PROPVARIANT* pValue)
259     {
260         assert(m_pAttributes);
261         return m_pAttributes->GetItemByIndex(unIndex, pguidKey, pValue);
262     }
263 
264     STDMETHODIMP CopyAllItems(IMFAttributes* pDest)
265     {
266         assert(m_pAttributes);
267         return m_pAttributes->CopyAllItems(pDest);
268     }
269 
270     // Helper functions
271     
272     HRESULT SerializeToStream(DWORD dwOptions, IStream* pStm)      
273         // dwOptions: Flags from MF_ATTRIBUTE_SERIALIZE_OPTIONS
274     {
275         assert(m_pAttributes);
276         return MFSerializeAttributesToStream(m_pAttributes, dwOptions, pStm);
277     }
278 
279     HRESULT DeserializeFromStream(DWORD dwOptions, IStream* pStm)
280     {
281         assert(m_pAttributes);
282         return MFDeserializeAttributesFromStream(m_pAttributes, dwOptions, pStm);
283     }
284 
285     // SerializeToBlob: Stores the attributes in a byte array. 
286     // 
287     // ppBuf: Receives a pointer to the byte array. 
288     // pcbSize: Receives the size of the byte array.
289     //
290     // The caller must free the array using CoTaskMemFree.
291     HRESULT SerializeToBlob(UINT8 **ppBuffer, UINT32 *pcbSize)
292     {
293         assert(m_pAttributes);
294 
295         if (ppBuffer == NULL)
296         {
297             return E_POINTER;
298         }
299         if (pcbSize == NULL)
300         {
301             return E_POINTER;
302         }
303 
304         *ppBuffer = NULL;
305         *pcbSize = 0;
306 
307         UINT32 cbSize = 0;
308         BYTE *pBuffer = NULL;
309 
310         HRESULT hr = MFGetAttributesAsBlobSize(m_pAttributes, &cbSize);
311 
312         if (FAILED(hr))
313         {
314             return hr;
315         }
316 
317         pBuffer = (BYTE*)CoTaskMemAlloc(cbSize);
318         if (pBuffer == NULL)
319         {
320             return E_OUTOFMEMORY;
321         }
322 
323         hr = MFGetAttributesAsBlob(m_pAttributes, pBuffer, cbSize);
324 
325         if (SUCCEEDED(hr))
326         {
327             *ppBuffer = pBuffer;
328             *pcbSize = cbSize;
329         }
330         else
331         {
332             CoTaskMemFree(pBuffer);
333         }
334         return hr;
335     }
336     
337     HRESULT DeserializeFromBlob(const UINT8* pBuffer, UINT cbSize)
338     {
339         assert(m_pAttributes);
340         return MFInitAttributesFromBlob(m_pAttributes, pBuffer, cbSize);
341     }
342 
343     HRESULT GetRatio(REFGUID guidKey, UINT32* pnNumerator, UINT32* punDenominator)
344     {
345         assert(m_pAttributes);
346         return MFGetAttributeRatio(m_pAttributes, guidKey, pnNumerator, punDenominator);
347     }
348 
349     HRESULT SetRatio(REFGUID guidKey, UINT32 unNumerator, UINT32 unDenominator)
350     {
351         assert(m_pAttributes);
352         return MFSetAttributeRatio(m_pAttributes, guidKey, unNumerator, unDenominator);
353     }
354 
355     // Gets an attribute whose value represents the size of something (eg a video frame).
356     HRESULT GetSize(REFGUID guidKey, UINT32* punWidth, UINT32* punHeight)
357     {
358         assert(m_pAttributes);
359         return MFGetAttributeSize(m_pAttributes, guidKey, punWidth, punHeight);
360     }
361 
362     // Sets an attribute whose value represents the size of something (eg a video frame).
363     HRESULT SetSize(REFGUID guidKey, UINT32 unWidth, UINT32 unHeight)
364     {
365         assert(m_pAttributes);
366         return MFSetAttributeSize (m_pAttributes, guidKey, unWidth, unHeight);
367     }
368 };

 

下面的代码展示了如何用这个类模板来实例化一个类:

 

 1 #include <shlwapi.h>
 2 
 3 class MyObject : public CBaseAttributes<>
 4 {
 5     MyObject() : m_nRefCount(1) { }
 6     ~MyObject() { }
 7 
 8     long m_nRefCount;
 9 
10 public:
11 
12     // IUnknown
13     STDMETHODIMP MyObject::QueryInterface(REFIID riid, void** ppv)
14     {
15         static const QITAB qit[] = 
16         {
17             QITABENT(MyObject, IMFAttributes),
18             { 0 },
19         };
20         return QISearch(this, qit, riid, ppv);
21     }
22 
23     STDMETHODIMP_(ULONG) MyObject::AddRef()
24     {
25         return InterlockedIncrement(&m_nRefCount);
26     }
27 
28     STDMETHODIMP_(ULONG) MyObject::Release()
29     {
30         ULONG uCount = InterlockedDecrement(&m_nRefCount);
31         if (uCount == 0)
32         {
33             delete this;
34         }
35         return uCount;
36     }
37 
38     // Static function to create an instance of the object.
39 
40     static HRESULT CreateInstance(MyObject **ppObject)
41     {
42         HRESULT hr = S_OK;
43 
44         MyObject *pObject = new MyObject();
45         if (pObject == NULL)
46         {
47             return E_OUTOFMEMORY;
48         }
49 
50         // Initialize the attribute store.
51         hr = pObject->Initialize();
52 
53         if (FAILED(hr))
54         {
55             delete pObject;
56             return hr;
57         }
58 
59         *ppObject = pObject;
60         (*ppObject)->AddRef();
61 
62         return S_OK;
63     }
64 };

 

你必须调用 CBaseAttributes::Initialize 来创建一个 attribute store。在上面的代码中,这一步在一个静态的创建方法(static HRESULT CreateInstance(MyObject **ppObject);)中完成。 

模板参数是一个接口类型,默认是 IMFAttributes 。如果要实例化继承自 IMFAttributes 的接口,例如 IMFActivate,设置模板参数为派生接口名称即可。

posted @ 2019-04-21 20:27  CaliforniaCHAO  阅读(713)  评论(0编辑  收藏  举报