VC+DirectShow对视频进行图片处理之二
2007-03-15 21:48:41 来源:WEB开发网核心提示: //===// 创建进程,CUnknown* WINAPI CVideoRenderer::CreateInstance(LPUNKNOWN pUnk,HRESULT* phr){return new CVideoRenderer(pUnk,phr);}//===// 构造函数CVideo
//===========================================================
// 创建进程。
CUnknown* WINAPI CVideoRenderer::CreateInstance(LPUNKNOWN pUnk,HRESULT* phr)
{
return new CVideoRenderer(pUnk,phr);
}
//===========================================================
// 构造函数
CVideoRenderer::CVideoRenderer(LPUNKNOWN pUnk,HRESULT *phr) : CBaseVideoRenderer(CLSID_lwVideoRenderer,"lw Video Renderer",pUnk,phr)
{
m_pCopyBuffer = NULL;
m_pFunCLS = NULL;
m_pPF = NULL;
m_pixelNum = 0;
}
//===========================================================
// 释构函数
CVideoRenderer::~CVideoRenderer()
{
if(this->m_pCopyBuffer){
delete [] m_pCopyBuffer;
}
}
//===========================================================
// 检查媒体类型
HRESULT CVideoRenderer::CheckMediaType(const CMediaType* pmt)
{
VIDEOINFO *pvi;
// 只接受视频
if( *pmt->FormatType() != FORMAT_VideoInfo ) {
return E_INVALIDARG;
}
// 只接受 RGB24 格式,即 R、G、B各 1 Byte
pvi = (VIDEOINFO *)pmt->Format();
if(IsEqualGUID( *pmt->Type(),MEDIATYPE_Video) && IsEqualGUID( *pmt->Subtype(),MEDIASUBTYPE_RGB24)){
return S_OK;
}
return E_INVALIDARG;
}
//===========================================================
// 设置媒体类型,获取图像的各种信息(宽、高等具体信息),处理图像要用到
HRESULT CVideoRenderer::SetMediaType(const CMediaType* pmt)
{
VIDEOINFO *pviBmp; // Bitmap info header
pviBmp = (VIDEOINFO *)pmt->Format();
memset(&m_bmpInfo,0,sizeof(BITMAPINFO)); // 清零
m_bmpInfo.bmiHeader = pviBmp->bmiHeader;
// 改为 32bit,因为我会把它处理成 32bit 的
m_bmpInfo.bmiHeader.biBitCount = 32;
// 当然,缓冲区大小也变了
m_bmpInfo.bmiHeader.biSizeImage = m_bmpInfo.bmiHeader.biSizeImage * 4 / 3;
// 开辟新 32bit 图片的缓冲区
if(m_pCopyBuffer){ delete [] m_pCopyBuffer;}
m_pCopyBuffer = new BYTE[m_bmpInfo.bmiHeader.biSizeImage];
m_pixelNum = m_bmpInfo.bmiHeader.biWidth * m_bmpInfo.bmiHeader.biHeight;
return S_OK;
}
//===========================================================
// 处理媒体采样
HRESULT CVideoRenderer::DoRenderSample(IMediaSample* pMediaSample)
{
// 获取采样的数据区指针,即 24bit 图片的数据区指针
BYTE* pb = NULL;
pMediaSample->GetPointer(&pb);
if(!pb){
return E_FAIL;
}
// 加锁!锁住我要操作的数据区,以防处理到一半的时候被打断而造成错误
// 其实就是多线程编程中经常使用的临界区的类形式,
// 利用构造函数和释构函数来进入和退出临界区
// m_RendererLock 是 CBaseVideoRenderer 的成员,继承得来。
CAutoLock cAutoLock(&this->m_RendererLock);
// 把 24bit 图片处理成 32bit
BYTE* pb32 = m_pCopyBuffer; // 指向 32bit 缓冲区的指针
for(UINT i = 0; i < m_pixelNum; i ++){
pb32[0] = pb[0];
pb32[1] = pb[1];
pb32[2] = pb[2];
pb32[3] = 0xff; // 0xff 即 255
pb += 3;
pb32 += 4;
}
// 如果有回调类,进行回调处理
if(m_pFunCLS){
m_pFunCLS->procFun(&m_bmpInfo,m_pCopyBuffer);
}
// 如果有回调函数,进行处理
if(m_pPF){
m_pPF(&m_bmpInfo,m_pCopyBuffer);
}
return S_OK;
}
至此,一个简单的 Filter 完成了,可以编译成功、用regsvr32.exe 注册并到GraphEdit.exe 中进行测试了。不过如果要在程序中使用的话,您会发现无法设置回调函数或回调类。这个Filter 是如此的无用,除了IBaseFilter 接口的基本功能外我们从它身上得不到任何有用的东西。所以,还得给它写个接口,让我们可以设置一些东西。写接口也不是难事,只要有一个接口的例子,随便谁都可以对照写出一个来,我就抄写了一个。新建一个 IVRControl.h 文件,加入下面代码。
Tags:VC DirectShow 视频
编辑录入:爽爽 [复制链接] [打 印]更多精彩
赞助商链接