大神们,一开始使用getcurrentimage用来抓图,结果抓图太慢而且有闪烁现象,考虑在链路中加入一个Sample grabber filter来抓图,这是我自己拉的一个图,
但是结果话,我使用网络数据包接收,却显示如下的图除非我在addfilterbyID之前加入了获取媒体类型就会显示如下的图片但是如果我在connect之前加入的话,就会在运行的时候报错,内存读取错误。这是我的代码建立graph过程,
bool CFilterGraph::BuildGraph(void)
{
m_bInit = false;    //初始化COM 组件
    HRESULT hr = CoInitialize(NULL);
    if(FAILED(hr))
    {
     ::MessageBox(NULL,_T("CoInitialize error"),NULL,MB_OK);
        return m_bInit;
    }
    
//Create filter graph
    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
                            IID_IGraphBuilder, (void**)&m_pGraph);
if (SUCCEEDED(hr))
{
hr = CoCreateInstance (CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC,
                           IID_ICaptureGraphBuilder2, (void **) &m_pCapture);
if (SUCCEEDED(hr))
{
m_pCapture->SetFiltergraph (m_pGraph);
m_bInit = true;
}
}
#ifdef _DEBUG
hr = AddToRot(m_pGraph, &dwRegister);//在用GraphEdit显示应用程序中构建的Filter Graph之前,应用程序必须把它创建的Filter Graph进行注册,可以在应用程序成功创建了一个Filter Graph之后调用AddToRot进行注册
#endif
if (m_bInit)
{
// Media control interface
hr = m_pGraph->QueryInterface(IID_IMediaControl, (void **)&m_pMediaControl);
if (FAILED(hr))
{
m_bInit = false;
}
} if (m_bInit)
{
// Media event interface
hr = m_pGraph->QueryInterface(IID_IMediaEvent, (void **)&m_pMediaEvent);
if (FAILED(hr)) 
{
m_bInit = false;
}
}

hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
                            IID_IBaseFilter, (void**)&m_pInterface); if (m_bInit)
{
// Media video window interface
hr = m_pGraph->QueryInterface(IID_IVideoWindow, (void **)&m_pVideoWindow);
if (FAILED(hr)) 
{
m_bInit = false;
}
}    //add filters
hr = AddFilterByCLSID(PushSource264, L"source", &m_pSource);
if (FAILED(hr))
{
  ::MessageBox(NULL,_T("PushSource264 error"),NULL,MB_OK);
        m_bInit = false;
}
hr = AddFilterByCLSID(ffdshow_video_decoder, L"decoder", &m_pDecoder);
if (FAILED(hr))
{
        m_bInit = false;
}

hr = AddFilterByCLSID(video_renderer, L"video", &m_pVideo);
if (FAILED(hr))
{
        m_bInit = false;
}
hr = AddFilterByCLSID(samplegrabber, L"grapper", &m_psample);
if (FAILED(hr))
{
        m_bInit = false;
}

/*hr =  AddSoundDeviceByCLSID(default_directsound_device,L"audiorender",&m_pAudio);
if (FAILED(hr))
{
        m_bInit = false;
}*/
hr = FindFilterInterface(m_pGraph,IID_IPushSource,(void**)&m_pPushSource);
if (FAILED(hr))
{
::MessageBox(NULL,_T("IID_IPushSource error"),NULL,MB_OK);
m_bInit = false;
}
if(m_pPushSource != NULL)
{

m_pPushSource->SetDecoder(m_resolution,m_framerate);

}

IVMRFilterConfig *pFilterConfig;
hr=m_pVideo->QueryInterface(IID_IVMRFilterConfig,(void **)&pFilterConfig);
hr=pFilterConfig->SetNumberOfStreams(2);
if(pFilterConfig != NULL)
{
pFilterConfig->Release();
pFilterConfig = NULL;
}
    //connect filters
/*hr = ConnectAudioFilters(m_pSource, m_pAudio);
if (FAILED(hr))
{
::MessageBox(NULL,_T("ConnectAudioFilters error"),NULL,MB_OK);
m_bInit = false;
}*/ hr = ConnectVideoFilters(m_pSource,m_pDecoder);
if (FAILED(hr))
{
::MessageBox(NULL,_T("ConnectVideoFilters error"),NULL,MB_OK);
m_bInit = false;
}
hr = ConnectFilters(m_pDecoder,m_psample);
if (FAILED(hr))
{
::MessageBox(NULL,_T("ConnectFilters error"),NULL,MB_OK);
m_bInit = false;
}
     hr = ConnectFilters(m_psample, m_pVideo);
if (FAILED(hr))
{
::MessageBox(NULL,_T("ConnectFilters error"),NULL,MB_OK);
m_bInit = false;
}

return m_bInit;求大神指教,其中的connect函数就是枚举找到为连接的pin然后把输入输出connect就可以了,求大神指导
FilterIsamplegrabber,抓图,

解决方案 »

  1.   

    本帖最后由 VisualEleven 于 2013-05-28 09:42:42 编辑
      

  2.   

    我的创建方法是这样的,你参考下看行不行BOOL CreateSampleGrabber()  //这里先创建好SampleGrabber,后面再连接
    {
    if(!pGrabberF)
    {


    HRESULT hr=CoCreateInstance(CLSID_SampleGrabber,NULL,CLSCTX_INPROC_SERVER,
    IID_IBaseFilter,reinterpret_cast<void**>(&pGrabberF));
    if(!SUCCEEDED(hr))
    {
    return hr;
    }
    hr=mGraph->AddFilter(pGrabberF,L"Sample Grabber");
    if(FAILED(hr))
    {
    return hr;
    }
    pGrabberF->QueryInterface(IID_ISampleGrabber,(void**)&pGrabber);
    AM_MEDIA_TYPE mt;
    ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
    mt.majortype = MEDIATYPE_Video;
    mt.subtype = MEDIASUBTYPE_RGB24;
    hr = pGrabber->SetMediaType(&mt);
    hr = pGrabber->SetOneShot(FALSE);
    hr = pGrabber->SetBufferSamples(TRUE);
    }
    }HRESULT CompleteBuildGraph(const char *inFile) //这里连接filter
    {
    WCHAR szFilePath[MAX_PATH];
    MultiByteToWideChar(CP_ACP, 0, inFile, -1, szFilePath, MAX_PATH);
    IBaseFilter *pSrc;
    HRESULT hr=mGraph->AddSourceFilter(szFilePath,L"Source", &pSrc);   
    hr = CoCreateInstance(CLSID_Colour,NULL,CLSCTX_INPROC_SERVER,IID_IBaseFilter,reinterpret_cast<void**>(&pDecoder)); hr = CoCreateInstance(CLSID_Colour,NULL,CLSCTX_INPROC_SERVER,IID_IBaseFilter,reinterpret_cast<void**>(&pDecoder2)); hr = mGraph->AddFilter(pDecoder, L"Color Space Converter");
    hr = mGraph->AddFilter(pDecoder2, L"Color Space Converter2");
    hr = ConnectFilters(mGraph,pSrc,pDecoder);

    hr = ConnectFilters(mGraph, pDecoder, pGrabberF); hr = ConnectFilters(mGraph, pGrabberF, pDecoder2); if(FAILED(hr))return hr;

    IBaseFilter *pNull = NULL;
    hr = CoCreateInstance(CLSID_VideoRenderer,NULL,CLSCTX_ALL,IID_IBaseFilter,reinterpret_cast<void**>(&pRender));
    if(FAILED(hr))return hr;
    hr = mGraph->AddFilter(pRender,L"Video Render");
    if(FAILED(hr))return hr;
    hr = ConnectFilters(mGraph, pDecoder2, pRender);
    return hr;
    }
      

  3.   

    ConnectFilters方法具体如下HRESULT CDXGraph::ConnectFilters(IGraphBuilder *pGraph, IBaseFilter *pFirst, IBaseFilter *pSecond)
    {
    IPin *pOut = NULL, *pIn = NULL;
    HRESULT hr = GetPin(pFirst, PINDIR_OUTPUT, &pOut);
    if (FAILED(hr)) return hr;
    hr = GetPin(pSecond, PINDIR_INPUT, &pIn);
    if (FAILED(hr))  
    {
    pOut->Release();
    return E_FAIL;
    }
    hr = pGraph->Connect(pOut, pIn);
    pIn->Release();
    pOut->Release();
    return hr;
    }和你的封装应该差不多,只不过我的是传递3个口相连,你的是两个
      

  4.   

    我的这个通过了编译运行
    大神,根据你的程序我做了修改,然后
    但是对graph进行run的时候返回错误值。。是什么原因呢??还有你怎么加入了两个colorcovert?
      

  5.   

    是的。。我看了是一样的,你的是把graph传进来我没传
    但是run的时候出现了一个错误是一个很大的负值,我查了以后是一个A product licensing error occurred..这是什么原因呢?
      

  6.   

    -2147220974 VFW_E_SIZENOTSET Cannot allocate memory because no size has been set.
    是这个错误原因
      

  7.   


    我拉了个和你给的graph差不多的,是没问题的,正常解码错误提示是没有足够的空间给你分配内存,一般导致这个错误的原因可能是你解码不对,你看下你的解码器是不是不能解码,或者你直接在Insert filtera 中拉一个directshow提供的简单解码器测试下看行不行
      

  8.   

    我添加两个colorcovert是因为项目中我不仅要解码还要抠图,所以解码和抠图前用了个,抠图后河渲染图像的地方又用了个
      

  9.   

    大神
    我反复检查了解码器,找不到任何原因啊还是出现run的错误原因郁闷啊,而且都是链路在edit显示是通的因为我是先判断是否能run起来后再接受数据,这就搞的很郁闷了。。我解码器用的是FFDSHOW的解码器直接加进去的。
    就是这个就是调用了接口,反复试过了不行。
      

  10.   

    怎么查看呢??我在run后面加入一个getlasterro??我程序里貌似没有加这个函数。。
      

  11.   


    http://msdn.microsoft.com/en-us/library/ms679360(VS.85).aspx看下这里,然后错误信息对照这里
    http://www.cnblogs.com/carekee/articles/2196518.html
      

  12.   

    用法http://msdn.microsoft.com/en-us/library/ms679360(VS.85).aspx
    返回错误信息对照http://www.cnblogs.com/carekee/articles/2196518.html
      

  13.   

    恩。。能把colourconvert的GUID发我吗老大??我看看一样不一样。。
      

  14.   

    OUR_GUID_ENTRY(CLSID_Colour,
    0x1643e180, 0x90f5, 0x11ce, 0x97, 0xd5, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a)
      

  15.   

    恩。。能把colourconvert的GUID发我吗老大??我看看一样不一样。。
    恩我今天把解码器和所有程序重头分析了一遍,单步跟踪了一遍所有步骤,没有使用getlasterrroe,但是我通过run返回的值是0x80040217,我通过MSDN查到是FW_E_CANNOT_CONNECT  No combination of intermediate filters could be found to make the connection.  0x80040217
    这样的说法,意为没有连接的找到能连接的filter,但是我通过edit看到remote connect的确实这样的:
    因为我做的是个插件所以看以看到运行的链路,明明是通的。。但是为什么run不起来,您用过我发的那个解码器吗??我一直觉得是解码器的引脚没有引用对。就是ffdshow的解码器。。麻烦您了。。我必须使用getlasterror才能发现问题?今天比较忙也没怎么改程序。。
      

  16.   

    系统的Sample Grabber Filter似乎对视频有些限制:http://msdn.microsoft.com/en-us/library/windows/desktop/dd377544(v=vs.85).aspxThe filter has the following limitations for video formats:
    It does not support video types with top-down orientation (negative biHeight).
    It does not support the VIDEOINFOHEADER2 format structure (format type equal to FORMAT_VideoInfo2).
    It rejects any video type where the surface stride does not match the video width.
    As a result, the Sample Grabber will not connect to the Video Mixing Renderer (VMR) for some video types所以,如果刚好在限制范围内,那么只能另谋他法了...
      

  17.   


    我在本地的视频播放和抓图中已经实现了功能,本地的视频和我从局域网拿到的数据包解包后是一样的,只是写在了本地。所以。现在这个问题太纠结了。那这样看来,网络的SOURCE和本地的SOURCE,在输出的OUTPUTPIN上的MEDIATYPE有不同,如果本地是好的,不妨把网络输出的MEDIATYPE改的和本地的一致?
      

  18.   


    我在本地的视频播放和抓图中已经实现了功能,本地的视频和我从局域网拿到的数据包解包后是一样的,只是写在了本地。所以。现在这个问题太纠结了。那这样看来,网络的SOURCE和本地的SOURCE,在输出的OUTPUTPIN上的MEDIATYPE有不同,如果本地是好的,不妨把网络输出的MEDIATYPE改的和本地的一致?
    在samplegrabber前面我已经设置了MEDIATYPE的类型,您看下设置方法对吗?AM_MEDIA_TYPE mt;
            ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
            mt.majortype = MEDIATYPE_Video;
            mt.subtype = MEDIASUBTYPE_RGB24;
            hr = pGrabber->SetMediaType(&mt);
            hr = pGrabber->SetOneShot(FALSE);
            hr = pGrabber->SetBufferSamples(TRUE);
      

  19.   

    我拉了个ffdshow的,我的是这样的,你在本地是没问题的吧,就是网络传输后不行?那你传输后,再解码的格式和本地的是一样的么?
      

  20.   


    我的意思是那个PushSource H264 Filter和source,这两个filter的outputpin的mediatype.
    不是说SampleGrabber Filter
      

  21.   


    我的意思是那个PushSource H264 Filter和source,这两个filter的outputpin的mediatype.
    不是说SampleGrabber Filter
    源的mediatype是能够设置吗?不是我获取到的是什么,然后解码时才能决定更改媒体类型吗?关键在网路上帧是264的码流,本地也是264的码流。没什么区别。还是链路连接上没连接好
      

  22.   


    我的意思是那个PushSource H264 Filter和source,这两个filter的outputpin的mediatype.
    不是说SampleGrabber Filter
    源的mediatype是能够设置吗?不是我获取到的是什么,然后解码时才能决定更改媒体类型吗?关键在网路上帧是264的码流,本地也是264的码流。没什么区别。还是链路连接上没连接好这样看来,source你用的是第三方的了,所以源的mediatype就不能够自己设置了。
    网络的source,应该是不区分数据类型的,所以其outputpin上的mediatype和本身就支持H264的PushSource H264 Filter的设置不同,这样就导致了后续的filter在连接时会有差异了。
    这种情况下,我觉得你需要在网络的source后面加一个splitter,把数据处理为与PushSource H264 Filter输出相同的类型,也许这样可以解决问题。
      

  23.   

    你可以看下source的outputpin的mediatype,应该和PushSource H264 Filter的outputpin不一样。
      

  24.   

    我刚刚改了改程序看了一下确实不一样,从push264出来的为这样的类型
    sourece是这样的
      

  25.   

    一样的。。这个是一样的。。我看过了都是RGB32格式的。。因为解码器用的是一样额。。不伦进入的而是什么,出来的肯定都是一样的。。
      

  26.   

    样的。。这个是一样的。。我看过了都是RGB32格式的。。因为解码器用的是一样额。。不伦进入的而是什么,出来的肯定都是一样的。。 。。现在就是出不来图像,什么都是没问题的,链路通过edit看也连上了
      

  27.   

    这样看来,你确实需要在网络的source后面加一个splitter,分离出正确的H264码流之后应该就可以和本地一样了。
    看mediatype,估计你需要的是一个MPEG-2 Splitter
      

  28.   

    这样看来,你确实需要在网络的source后面加一个splitter,分离出正确的H264码流之后应该就可以和本地一样了。
    看mediatype,估计你需要的是一个MPEG-2 Splitter
    我前面已经加了spaceconvert,非要加这个spilter?感觉解码器和render之间的问题太大了。。要连不上也是解码器和render之间连不上啊,因为我不加samplegrabber话,网络上的数据是完全可以接受的啊,而且播放正常,都已经要发布产品了,就是加了sample后就不行了。。我觉得还是在sample和render和decoder之间想办法,但是不知道为什么本地的就可以。设想的挺简单的没想到搞了这么几天都没有成功。
      

  29.   

    ColorSpaceConvert只是进行颜色空间的转换,并不会将视频流从文件格式容器中分离出来。Splitter的作用是:正确分离出Source的原始数据流,从中分离出解码前的视频、音频,将这些数据送入Decoder进行解码,解码完成后,视频就能拿到图像数据了,在Decoder后挂ColorSpaceConvert,作用只是把图象从一种颜色空间转变为另一种颜色空间而已。所以,我个人的想法是,就是在网络Source后面挂Splitter,因为网络Source只有一个OutputPin,你的原始数据是MPEG-2文件的话,那么网络Source出来的数据就还是MPEG-2文件。而PushSource H264 Filter,具备了一定Splitter的能力,所以出来的数据流已经是H264数据流了。另外,我不知道你如果source -> decoder -> VMR,这样可以播放吗?decoder出来的outputpin类型又是怎样的?
      

  30.   

    是的,是sourece-decoder-vmr7这样的是可以播放的,这个是decoder出来的数据
    恩。。同时从sorce出来的源的数据也是mpeg2这个我都看过了。所以就太奇怪了。我奇怪的是mpeg2到底表示的是什么意思我百度也没找到,本地那个能使用的源里面设置的format是inforheader2,网络上的也是能设置,服务器发送来的数据时264的格式的,但是在接收的时候我对format进行了赋值是mpeg2(参考别人的)然后就能正常的播放了,改为和本地的一样的源和decoder都连接不上了。format我知道是描述流的具体信息的但是到底描述的是什么也不知道,所以根本找不出原因来。对filter理解的不深刻啊。感觉没把握到问题的关键。