WEB开发网
开发学院软件开发VC VC+DirectShow对视频进行图片处理之二 阅读

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 文件,加入下面代码。

上一页  1 2 3 4  下一页

Tags:VC DirectShow 视频

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接