assert(pmediatype->formattype == format_videoinfo);
videoinfoheader *pvih =
reinterpret_cast<videoinfoheader*>(pmediatype->pbformat);
pvih->bmiheader.bicompression = bi_rle8;
pvih->bmiheader.bisizeimage = dibsize(pvih->bmiheader);
return s_ok;
}
// else
return vfw_s_no_more_items;
}
这个例子函数中,调用了ipin::connectionmediatype从输入pin上得到输入的媒体类型。然后改变了媒体类型结构的几个filed,表示是压缩格式
1 it assigns a new subtype guid, which is constructed from the fourcc code 'mrle', using the fourccmap class.
2 it calls the cmediatype::setvariablesize method, which sets the bfixedsizesamples flag to false and the lsamplesize member to zero, indicating variable-sized samples.
3 it calls the cmediatype::settemporalcompression method with the value false, indicating that every frame is a key frame. (this field is informational only, so you could safely ignore it.)
4 it sets the bicompression field to bi_rle8.
5 it sets the bisizeimage field to the image size.
3 virtual hresult checktransform(const cmediatype* mtin, const cmediatype* mtout) pure;
ctransformfilter::checktransform检查输出的媒体类型和输入的媒体类型是否匹配。当输入pin在输出pin连接之后才开始连接的时候,输出pin会调用这个函数来检查输出媒体类型是否和输入媒体类型是否匹配。
下面的例子演示了查询数据的格式是否为rle8视频,图像的大小是否和输入的匹配,调色板的入口是否一致,如果图像大小不一致就要拒绝
hresult crlefilter::checktransform(
const cmediatype *mtin, const cmediatype *mtout)
{
// check the major type.
if (mtout->majortype != mediatype_video)
{
return vfw_e_type_not_accepted;
}
// check the subtype and format type.
fourccmap fccmap = fcc('mrle');
if (mtout->subtype != static_cast<guid>(fccmap))
{
return vfw_e_type_not_accepted;
}
if ((mtout->formattype != format_videoinfo) ||
(mtout->cbformat < sizeof(videoinfoheader)))
{
return vfw_e_type_not_accepted;
}
// compare the bitmap information against the input type.
assert(mtin->formattype == format_videoinfo);
bitmapinfoheader *pbmiout = header(mtout->pbformat);
bitmapinfoheader *pbmiin = header(mtin->pbformat);
if ((pbmiout->biplanes != 1) ||
(pbmiout->bibitcount != 8) ||
(pbmiout->bicompression != bi_rle8) ||
(pbmiout->biwidth != pbmiin->biwidth) ||
(pbmiout->biheight != pbmiin->biheight))
{
return vfw_e_type_not_accepted;
}
// compare source and target rectangles.
rect rcimg;
setrect(&rcimg, 0, 0, pbmiin->biwidth, pbmiin->biheight);
rect *prcsrc = &((videoinfoheader*)(mtin->pbformat))->rcsource;
rect *prctarget = &((videoinfoheader*)(mtout->pbformat))->rctarget;
if (!isrectempty(prcsrc) && !equalrect(prcsrc, &rcimg))
{
return vfw_e_invalidmediatype;
}
if (!isrectempty(prctarget) && !equalrect(prctarget, &rcimg))
{
return vfw_e_invalidmediatype;
}
// check the palette table.
if (pbmiout->biclrused != pbmiin->biclrused)
{
return vfw_e_type_not_accepted;
}
dword cbpalette = pbmiout->biclrused * sizeof(rgbquad);
if (mtout->cbformat < sizeof(videoinfoheader) + cbpalette)
{
return vfw_e_type_not_accepted;
}
if (0 != memcmp(pbmiout + 1, pbmiin + 1, cbpalette))
{
return vfw_e_type_not_accepted;
}
// everything is good.
return s_ok;
}
第四步 设置allocator属性
当连个pin就某个媒体类型达成一致协议的时候,他们就选择一个allocator,就allocator的属性进行设置,比如buffer大小,buffer的数量。
在ctransformfilter 类中,有两个allocator,一个用于上游的pin的连接,一个用于下游的pin的连接,上游的filter选择upstream allocator设置属性,无论上游的filter怎么设置这个upstream allocator,输入pin都会接受,如果你想改变这个中状况,你可以继承cbaseinputpin::notifyallocator函数
transform filter的输出pin选择下游的allocator,步骤如下
1 如果下游的filter可以提供一个allocator,那么输出pin就使用这个allocator,否则,输出pin就创建一个新的allocator。
2 输出pin通过下游filter的输入pin上的imeminputpin::getallocatorrequirements.方法来确定下游filter的allocator的要求。
3 输出pin调用transform filter上的ctransformfilter::decidebuffersize函数,这个函数也是一个纯虚的函数,
virtual hresult decidebuffersize( imemallocator * pallocator,
allocator_properties *pprop) pure;
这个函数有一个指向allocator的指针,和一个指向allocator_properties结构的指针,这个指针包含了对allocator的属性的设置,如果下游的filter对allocator没有设置属性,那么这个结构就是null。
4在decidebuffersize方法中,派生类的函数通过调用imemallocator::setproperties.函数来设置allocator的属性。
通常,派生类会根据输出的格式,下游filter得要求,自身得要求来设置allocator的属性,allocator属性的设置要符合下游filter的要求,否则的话,连接就可能被拒绝。
下面的例子中,
hresult crlefilter::decidebuffersize(
imemallocator *palloc, allocator_properties *pprop)
{
am_media_type mt;
hresult hr = m_poutput->connectionmediatype(&mt);
if (failed(hr))
{
return hr;
}