在学习CTransInPlaceFilter的过程中,发现了一个新东西:ddraw
这个东西有个overlay层,是真正通过显卡的overlay通道实现的,跟显卡正常显示的数据完全剥离,
用这个来做半透明滚动字幕刚好。
将CE下DDRAW的sample拿来看了下,它里面的那个蚊子就是实现overlay的,稍微改一下,OK可以了。
但是这个有个问题,就是ddraw的overlay需要附着一个ddraw的surface,所以还需要再搞一个surface给他附着。
并且我这个设备不支持overlay的alpha的,所以只能实现滚动字幕,但是背景却不是半透明的。
刚好前面我实现了filter的半透明功能,在字幕滚动的地方画上半透明背景,两者结合就可以实现了半透明滚动字幕了。
这样Filter的功能就极其简单。我就想将这个filter在程序里直接使用,不做成DLL调用了。
在陆其明老师的<DirectShow开发指南>第四章 filter开发 里,有介绍这种调用方式,二话不说,依样画葫芦,先把代码copy过来再说,我用网上找到的CDXGraph类构建完整媒体文件播放链路,renderfile,然后插入我自己写的filter。
编译一下,能通过,但是视频没有播放。
跑下DEBUG,发现问题是出在ConnectUpstreamOf(IBaseFilter* pFilter, IBaseFilter* pTransform)里
这个函数的作用是将pTransform插入到pFilter之前,这里的pfilter就是我们找到的Video Renderer(或者Overlay Mixer)
现在仔细看下ConnectUpstreamOf
HRESULT CDXGraph::ConnectUpstreamOf(IBaseFilter* pFilter, IBaseFilter* pTransform)
{
//取得pFilter的输入pin,要连接两个filter,
//我们应该将pTransform的outpin跟pFilter的inpin相连
//将pTransform的inpin跟pfilter的前一个filter的outpin相连
IPin* pPinIn = InputPinOf(pFilter);
if (!pPinIn)
{
return E_FAIL;
}
//取得与inpin相连的pin,即前一个filter的outpin
// Get the peer output pin
IPin* pPinOut = NULL;
HRESULT hr = pPinIn->ConnectedTo(&pPinOut);
if (FAILED(hr))
{
pPinIn->Release();
return hr;
}
//断开
// Disconnect the current connection
hr = mGraph->Disconnect(pPinOut);
if (SUCCEEDED(hr))
{
hr = mGraph->Disconnect(pPinIn);
}
// Insert pTransform filter by connecting its input pin and output pin
//将前一个filter的outpin与pTransform的inpin相连
if (SUCCEEDED(hr))
{
IPin* pPinInXfm = InputPinOf(pTransform);
hr = mGraph->Connect(pPinOut, pPinInXfm);
pPinInXfm->Release();
}
//将前一个pTransform的outpin与pFilter的inpin相连
if (SUCCEEDED(hr))
{
IPin* pPinOutXfm = OutputPinOf(pTransform);
hr = mGraph->Connect(pPinOutXfm, pPinIn);
pPinOutXfm->Release();
}
pPinIn->Release();
pPinOut->Release();
return hr;
}
这个函数的逻辑很清楚,就相当于在一个链表中插入一个节点,跑DEBUG发现,问题是出在
hr = mGraph->Connect(pPinOut, pPinInXfm);
连接两个pin出错。
上网搜索了下资料,怀疑是两个pin的mediatype不匹配照成的。
取得pPinInXfm的mediatype,发现mt里面为无效数据,再取pPinOut的mediatype,发现里面内容和pPinInXfm一样
pPinOut的filter是由IGraphBuilder::Renderfile智能构建的,应该是有媒体类型才对,为什么会这样呢?
联想起之前实现的checkinputtype,这个函数可能就是在这里发挥作用的,在
CAlphaFilter::CheckInputType(const CMediaType* mtIn)
中下断点,发现连接pin的确会执行这个函数,并且返回失败,mtIn->Subtype()不是支持的类型。
但是CFilterTitleOverlay的实现原理就是修改输入数据的值,如果不是RGB格式的话,那么就需要解码再处理,再编码,这样效率就完全不行了。。
这条路暂时走不通了,想办法在ddraw的overlay上实现alpha看看