FreeMediaType与DeleteMediaType
FreeMediaType和DeleteMediaType很容易被混淆使用,它们的区别主要体现在操作的对象不同。要弄清这个问题,首先要熟悉AM_MEDIA_TYPE这个结构体。下面就是这个机构体的定义:
typedef struct _MediaType {
GUID majortype;
GUID subtype;
BOOL bFixedSizeSamples;
BOOL bTemporalCompression;
ULONG lSampleSize;
GUID formattype;
IUnknown *pUnk;
ULONG cbFormat;
[size_is(cbFormat)] BYTE *pbFormat;
} AM_MEDIA_TYPE;
在这里
pbFormat
实际上是一个
BYTE
指针,用来指向一块随机分配的内存。
cbFormat
用来指明
pbFormat
这个指针所指内存块的大小。既然是这样,作为这块内存的使用
者就应该知道这块内存到底有多大。
cbFormat
就是起这个作用的。
AM_MEDIA_TYPE
本身不是通过new得来的,而是有专门的函数来负责:CreateMediaType,其原型如
下:
AM_MEDIA_TYPE * WINAPI CreateMediaType(AM_MEDIA_TYPE const
*pSrc
);
该函数首先分配一个新的
AM_MEDIA_TYPE
,包括格式数据块,然后把
pSrc
所指的
结构体数据全部都拷贝进来。如果不出现意外的话,函数返回的就是这个新分配的
AM_MEDIA_TYPE
了。否则返回
NULL
。为保证程序的健壮性,最好在函数返回时检
查返回值。不论是格式数据块,还是
AM_MEDIA_TYPE
本身都不能通过
new
来分配
内存。既然如此,当然就不能简单地
delete
这些内存了,而也必须有专门的函数来
释放。一个是格式数据,一个是结构体本身。格式数据由
FreeMediaType
释放,结
构体本身由
DeleteMediaType
释放。另外格式数据必须在结构体本身释放之前释放,
以免导致异
常。为加强理解,下面是它们的等价形式,如果不愿意使用库函数,完全
可以用它们取
而代之:
void MyDeleteMediaType(AM_MEDIA_TYPE *pmt)
{
if (pmt != NULL)
{
// See FreeMediaType for the implementation.
MyFreeMediaType(*pmt);
CoTaskMemFree(pmt);
}
}
void MyFreeMediaType(AM_MEDIA_TYPE& mt)
{
if (mt.cbFormat != 0)
{
CoTaskMemFree((PVOID)mt.pbFormat);
mt.cbFormat = 0;
mt.pbFormat = NULL;
}
if (mt.pUnk != NULL)
{
// Unecessary because pUnk should not be used, but safest.
mt.pUnk->Release();
mt.pUnk = NULL;
}
}
其中最让我们犯糊涂的就是结构体的最后两个成员:
cbFormat
和
pbFormat
。