博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Directshow 捕捉程序的两个问题
阅读量:5995 次
发布时间:2019-06-20

本文共 6757 字,大约阅读时间需要 22 分钟。

之前写的程序里,一直存在两个问题。一个是程序运行时,点击打开视频后,关闭视频。再点击打开视频,就会弹出对话框“can’t build graph"。二是,无法改变采集的图像的大小,总是固定的320*240.注意,此处不是指显示窗口的大小。

     结合查找的一些资料,终于解决了。

    问题一:是Capturevidieo 类析构函数里,少释放了pVW。晕。网上找的类里,都漏了释放了。

   问题二:

               结合以下资料,解决了:

              1

(1)获得IAMStreamConfig接口 

hr = gcap.pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, 
&MEDIATYPE_Interleaved, 
gcap.pVCap, IID_IAMStreamConfig, (void **)&gcap.pVSC); 
(2)控制 
if(gcap.pVSC)// && gcap.fUseFrameRate) 
hr = gcap.pVSC->GetFormat(&pmt); 
// DV capture does not use a VIDEOINFOHEADER 
if(hr == NOERROR) 
if(pmt->formattype == FORMAT_VideoInfo) 
VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *)pmt->pbFormat; 
pvi->bmiHeader.biWidth=320; 
pvi->bmiHeader.biHeight =240; 
pvi->bmiHeader.biSizeImage=320*240*3; 
hr = gcap.pVSC->SetFormat(pmt); 
DeleteMediaType(pmt); 
}   
2

调整视频输出格式

我们知道视频流可以有多种输出格式,一个设备可以支持16-bit RGB, 32-bit RGB, and YUYV,在每一种格式下,设备还可以调整视频桢的大小。
在WDM驱动设备上,IAMStreamConfig 接口用来报告设备输出视频的格式的,VFW设备,可以采用对话框的方式来设置,参见前面的内容。
捕捉Filter的捕捉pin和预览pin都支持IAMStreamConfig 接口,可以通过ICaptureGraphBuilder2::FindInterface获得IAMStreamConfig接口。

IAMStreamConfig *pConfig = NULL;

hr = pBuild->FindInterface(
&PIN_CATEGORY_PREVIEW, // Preview pin.
0, // Any media type.
pCap, // Pointer to the capture filter.
IID_IAMStreamConfig, (void**)&pConfig);

设备还支持一系列的媒体类型,对于每一个媒体类型,设备都要支持一系列的属性,比如,桢的大小,图像如何缩放,桢率的范围等。

通过IAMStreamConfig::GetNumberOfCapabilities获得设备所支持的媒体类型的数量。这个方法返回两个值,一个是媒体类型的数量,二是属性所需结构的大小。
这个结构的大小很重要,因为这个方法是用于视频和音频的,视频采用的是VIDEO_STREAM_CONFIG_CAPS结构,音频用AUDIO_STREAM_CONFIG_CAPS结构。
通过函数IAMStreamConfig::GetStreamCaps来枚举媒体类型,要给这个函数传递一个序号作为参数,这个函数返回媒体类型和相应的属性结构体。看代码把

int iCount = 0, iSize = 0;

hr = pConfig->GetNumberOfCapabilities(&iCount, &iSize);
// Check the size to make sure we pass in the correct structure.
if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS)
{
// Use the video capabilities structure.
for (int iFormat = 0; iFormat < iCount; iFormat++)
{
VIDEO_STREAM_CONFIG_CAPS scc;
AM_MEDIA_TYPE *pmtConfig;
hr = pConfig->GetStreamCaps(iFormat, &pmtConfig, (BYTE*)&scc);
if (SUCCEEDED(hr))
{
/* Examine the format, and possibly use it. */
// Delete the media type when you are done.
hr = pConfig->SetFormat(pmtConfig);//重新设置视频格式
DeleteMediaType(pmtConfig);
}
}

你可以调用IAMStreamConfig::SetFormat设置新的媒体类型

hr = pConfig->SetFormat(pmtConfig);
如果pin没有连接,当连接的时候就试图用新的格式,如果pin已经在连接了,它就会用的新的媒体格式重新连接。在任何一种情况下,下游的filter都有可能拒绝新的媒体格式。
在SetFormat前你可以修改VIDEO_STREAM_CONFIG_CAPS结构来重新设置媒体类型。
例如:
如果GetStreamCaps返回的是24-bit RGB format,桢的大小是320 x 240 像素,你可以通过检查媒体类型的major type,subtpye,和format等值

if ((pmtConfig.majortype == MEDIATYPE_Video) &&

(pmtConfig.subtype == MEDIASUBTYPE_RGB24) &&
(pmtConfig.formattype == FORMAT_VideoInfo) &&
(pmtConfig.cbFormat >= sizeof (VIDEOINFOHEADER)) &&
(pmtConfig.pbFormat != NULL))
{
VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)pmtConfig.pbFormat;
// pVih contains the detailed format information.
LONG lWidth = pVih->bmiHeader.biWidth;
LONG lHeight = pVih->bmiHeader.biHeight;
}

VIDEO_STREAM_CONFIG_CAPS结构里包含了该媒体类型的视频长度和宽度的最大值和最小值,还有递增的幅度值,就是每次调整视频size的幅度,例如,设备可能返回如下的值

? MinOutputSize: 160 x 120 
? MaxOutputSize: 320 x 240 
? OutputGranularityX: 8 pixels (horizontal step size) 
? OutputGranularityY: 8 pixels (vertical step size) 
这样你可以在(160, 168, 176, ... 304, 312, 320) 范围内设置宽度,在 (120, 128, 136, ... 104, 112, 120).设置高度值,

图6

如果想设置新的值,直接修改在GetStreamCaps函数中返回的值即可,

pVih->bmiHeader.biWidth = 160;

pVih->bmiHeader.biHeight = 120;
pVih->bmiHeader.biSizeImage = DIBSIZE(pVih->bmiHeader);

然后将媒体类型传递给SetFormat函数,就可修改视频格式了。

 

三 自己修改后的程序如下:

cpp

CCaptureVideo::~CCaptureVideo()

{
// Stop media playback
if (bIsVideoOpen)
{ if(m_pMC)m_pMC->Stop();
if(m_pVW)
{
   m_pVW->put_Visible(OAFALSE);
   m_pVW->put_Owner(NULL);
}
    srelease(m_pBF);
    srelease(m_pCapture);
srelease(m_pMC);
srelease(m_pGB);
srelease(m_pVW);//加上这句,就可以了,晕,否则在程序里没法连续打开两次视频

CoUninitialize( );

}

HRESULT CCaptureVideo::Init(int iDeviceID, HWND hWnd)
{
HRESULT hr;
hr = InitCaptureGraphBuilder();
if (FAILED(hr))
{
   AfxMessageBox("Failed to get video interfaces!");
   return hr;
}
// Bind Device Filter. We know the device because the id was passed in
if(!BindFilter(iDeviceID, &m_pBF))
{
   AfxMessageBox("未找到USB摄像头!\n请检查设备后重试!");
        //PostQuitMessage(0);
        return S_FALSE;
}
hr = m_pGB->AddFilter(m_pBF, L"Capture Filter");

// hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, 

// m_pBF, NULL, NULL);

// create a sample grabber

hr = m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );
if( !m_pGrabber )
{
   AfxMessageBox("Fail to create SampleGrabber, maybe qedit.dll is not registered?");
   return hr;
}
CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );

//设置视频格式
   
   IAMStreamConfig *pConfig = NULL;
hr = m_pCapture->FindInterface(&PIN_CATEGORY_CAPTURE, 0, // Any media type.
   m_pBF, // Pointer to the capture filter.
   IID_IAMStreamConfig, (void**)&pConfig);
    AM_MEDIA_TYPE *pmt;
hr   =   pConfig ->GetFormat(&pmt); 
    //ZeroMemory(pmt, sizeof(AM_MEDIA_TYPE));
    pmt->majortype = MEDIATYPE_Video;
    pmt->subtype = MEDIASUBTYPE_RGB24;
pmt->formattype = FORMAT_VideoInfo;
VIDEOINFOHEADER   *pvi   =   (VIDEOINFOHEADER   *)pmt->pbFormat;   
pvi->bmiHeader.biWidth=640;   
pvi->bmiHeader.biHeight   =480;   
pvi->bmiHeader.biSizeImage=640*480*3;   //设置帧大小,而不是仅仅改变预览窗口大小
hr   =   pConfig->SetFormat(pmt);   
    
FreeMediaType(*pmt);    
AM_MEDIA_TYPE mt; 
//ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
//mt.majortype = MEDIATYPE_Video;
//mt.subtype = MEDIASUBTYPE_RGB24;
// mt.formattype = FORMAT_VideoInfo;
// VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) mt.pbFormat;//不能在这里设置图像文件信息
    // 
// hr = m_pGrabber->SetMediaType(&mt);

if( FAILED( hr ) )

{
   AfxMessageBox("Fail to set media type!");
   return hr;
}

hr = m_pGB->AddFilter( pGrabBase, L"Grabber" );

if( FAILED( hr ) )

{
   AfxMessageBox("Fail to put sample grabber in graph");
   return hr;
}

// try to render preview/capture pin

hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,m_pBF,pGrabBase,NULL);
if( FAILED( hr ) )
    hr = m_pCapture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,m_pBF,pGrabBase,NULL);
if( FAILED( hr ) )
{
   AfxMessageBox("Can’t build the graph");
   return hr;
}

hr = m_pGrabber->GetConnectedMediaType( &mt );

if ( FAILED( hr) )

{
   AfxMessageBox("Failt to read the connected media type");
   return hr;
}
    
VIDEOINFOHEADER * vihh = (VIDEOINFOHEADER*) mt.pbFormat;
     // vihh->bmiHeader.biWidth=320;
     // vihh->bmiHeader.biHeight=240;
     // vihh->bmiHeader.biSizeImage=320*240*3; 
// hr = m_pGrabber->SetMediaType(&mt);
mCB.lWidth =vihh->bmiHeader.biWidth;
      
mCB.lHeight =vihh->bmiHeader.biHeight;
FreeMediaType(mt);
    

hr = m_pGrabber->SetBufferSamples( false );

hr = m_pGrabber->SetOneShot( FALSE );
hr = m_pGrabber->SetCallback( &mCB, 1 );//影响回调

//设置视频捕捉窗口

m_hWnd = hWnd ; 
SetupVideoWindow();
hr = m_pMC->Run();//开始视频捕捉
if(FAILED(hr))
{
   AfxMessageBox("Couldn’t run the graph!");
   return hr;
}

    bIsVideoOpen = TRUE;

return S_OK;

}

本文转自博客园知识天地的博客,原文链接: ,如需转载请自行联系原博主。

你可能感兴趣的文章
ceph存储 磁盘IOPS常识
查看>>
ORA-12720: operation requires database is in EXCLUSIVE mode
查看>>
ELK日志服务使用-kafka传输日志(bbotte.com)
查看>>
linux系统之iptables其二命令注解
查看>>
Silverlight C# 游戏开发:高深莫测却浅显易懂的游戏开发
查看>>
标准ACL+扩展ACL+命名ACL
查看>>
Linux常用的基本命令14
查看>>
《zabbix进程组成结构与zabbix_agentd.conf配置文件参数详解》-3
查看>>
8-22学习练习[一个viewController整合增删移动功能]
查看>>
MySQL的字符集
查看>>
Selenium2+python自动化63-简易项目搭建
查看>>
Managed Debugging Assistant &#39;PInvokeStackImbalance&#39; has detected a problem in 解决方案
查看>>
centos7 安装mysql5.7.11注意事项
查看>>
[20150727]''与NULL.txt
查看>>
上海往事之教会宝宝学游泳
查看>>
SharePoint 2013 图文开发系列之创建内容类型
查看>>
cookie 简介
查看>>
ios和android内嵌h5页面联调小结
查看>>
两种jdk版本的多个tomcat按windows服务的安装问题的解决
查看>>
为IE创建更好的XMLHttpRequest对象
查看>>