2014-11-03 5 views
2

저는 DirectShow 세계에서 초보자이며 Microsoft SDK 샘플에서 제공하는 간단한 "playcap"샘플을 공부했습니다. 이 작은 프로그램을 통해 웹캠 스트림으로 창을 가질 수있었습니다. 웹캠에서 두 장의 사진을 찍어 비교 (하드 디스크에 저장하지 않고도)하여 어떤 픽셀이 다른지 찾을 수 있습니까? Win32API 캡처 창을 사용하여이 작업을 쉽게 수행 할 수 있었지만 속도가 매우 느 렸으므로 빨리 수행해야합니다. 미리 감사드립니다. 제 프로젝트에서 매우 중요합니다.C++ - DirectShow - 웹캠으로 캡처 한 두 이미지의 비교

답변

-1

here을 검색하거나 Sample Grabber Filter의 샘플을 찾아 보는 것이 좋습니다. 자세한 내용은 직접 작성하십시오 here.

그래프에 샘플 그래버 필터를 추가하십시오.

IBaseFilter *pSG_Filter; 
    hr = CoCreateInstance(
    CLSID_SampleGrabber, 
    NULL, 
    CLSCTX_INPROC_SERVER, 
    IID_IBaseFilter, 
    (void**)&pSG_Filter 
); 

hr = pGraph->AddFilter(pSG_Filter, L"SampleGrab"); 

Null 렌더러 필터를 그래프에 추가하십시오.

IBaseFilter *pNull; 

hr = CoCreateInstance(
    CLSID_NullRenderer, 
    NULL, 
    CLSCTX_INPROC_SERVER, 
    IID_IBaseFilter, 
    (void**)&pNull 
    ); 

hr = pGraph->AddFilter(pNull, L"NullRender"); 

지금 당신은 샘플 그래버에 여전히 핀에서가는 하나의 메소드 호출에 세 가지 필터를 연결하기 위해 사용해 ICaptureGraphBuilder2 :: RenderStream 방법을 사용할 수 있으며, 샘플 그래버에서 널 렌더러에 :

당신이 방법 ISampleGrabbe 보라, 이제

ISampleGrabber *pSG = NULL; 

hr = pSG_Filter->QueryInterface(IID_ISampleGrabber, (void**)&pSG); 
if (SUCCEEDED(hr)) 
{ 
    hr = pSG->SetOneShot(FALSE); 
    hr = pSG->SetBufferSamples(TRUE); 

    ... 

:

hr = pBuild->RenderStream(
    &PIN_CATEGORY_STILL, // Connect this pin ... 
    &MEDIATYPE_Video, // with this media type ... 
    pCap,    // on this filter ... 
    pSG_Filter,   // to the Sample Grabber ... 
    pNull);    // ... and finally to the Null Renderer. 

지금은 샘플을 버퍼 수 있도록 샘플 그래버를 구성 할 ISampleGrabber 인터페이스를 사용 r :: SetOneShot 그리고 TRUE로 설정하십시오.

hr = pSG->SetCallback(&g_StillCapCB, 0); // 0 = Use the SampleCB callback method. 

은 여전히 ​​샘플 그래버와 연결하는 데 사용되는 핀 미디어 유형 가져 오기 :

가 콜백 객체에 대한 포인터와 콜백 인터페이스를 설정

// Store the media type for later use. 
AM_MEDIA_TYPE g_StillMediaType; 

hr = pSG->GetConnectedMediaType(&g_StillMediaType); 
pSG->Release(); 

을이 미디어 타입 것 정지 이미지의 형식을 정의하는 BITMAPINFOHEADER 구조체를 포함합니다.

다음은 콜백 클래스의 예입니다. 이 클래스는 ISampleGrabber 인터페이스를 통해 상속하는 IUnknown을 구현하지만 참조 횟수는 유지하지 않습니다. 이것은, 어플리케이션이 스택 상에 객체를 생성 해, 객체가 필터 그래프의 수명 내내 스코프 내에 남아 있기 (위해) 때문에 안전합니다.

모든 작업은 새로운 샘플이 생길 때마다 샘플 그래버가 호출하는 BufferCB 방법에서 발생합니다. 다음 예에서, 상기 방법은 파일에 비트 맵을 쓴다 :

class SampleGrabberCallback : public ISampleGrabberCB 
{ 
    public: 
    // Fake referance counting. 
    STDMETHODIMP_(ULONG) AddRef() { return 1; } 
    STDMETHODIMP_(ULONG) Release() { return 2; } 

    STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) 
    { 
     if (NULL == ppvObject) return E_POINTER; 
     if (riid == __uuidof(IUnknown)) 
     { 
      *ppvObject = static_cast<IUnknown*>(this); 
      return S_OK; 
     } 
     if (riid == __uuidof(ISampleGrabberCB)) 
     { 
      *ppvObject = static_cast<ISampleGrabberCB*>(this); 
      return S_OK; 
     } 
     return E_NOTIMPL; 
    } 

    STDMETHODIMP SampleCB(double Time, IMediaSample *pSample) 
    { 
     return E_NOTIMPL; 
    } 

    STDMETHODIMP BufferCB(double Time, BYTE *pBuffer, long BufferLen) 
    { 
     if ((g_StillMediaType.majortype != MEDIATYPE_Video) || 
      (g_StillMediaType.formattype != FORMAT_VideoInfo) || 
      (g_StillMediaType.cbFormat < sizeof(VIDEOINFOHEADER)) || 
      (g_StillMediaType.pbFormat == NULL)) 
     { 
      return VFW_E_INVALIDMEDIATYPE; 
     } 
     HANDLE hf = CreateFile("C:\\Example.bmp", GENERIC_WRITE, 
     FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL); 
     if (hf == INVALID_HANDLE_VALUE) 
     { 
      return E_FAIL; 
     } 
     long cbBitmapInfoSize = g_StillMediaType.cbFormat - SIZE_PREHEADER; 
     VIDEOINFOHEADER *pVideoHeader = 
      (VIDEOINFOHEADER*)g_StillMediaType.pbFormat; 

     BITMAPFILEHEADER bfh; 
     ZeroMemory(&bfh, sizeof(bfh)); 
     bfh.bfType = 'MB'; // Little-endian for "BM". 
     bfh.bfSize = sizeof(bfh) + BufferLen + cbBitmapInfoSize; 
     bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + cbBitmapInfoSize; 

     // Write the file header. 
     DWORD dwWritten = 0; 
     WriteFile(hf, &bfh, sizeof(bfh), &dwWritten, NULL); 
     WriteFile(hf, HEADER(pVideoHeader), cbBitmapInfoSize, &dwWritten, NULL);   
     WriteFile(hf, pBuffer, BufferLen, &dwWritten, NULL); 
     CloseHandle(hf); 
     return S_OK; 

    } 
}; 

무료 미디어 타입 응용 프로그램이 종료하기 전에 :이 링크는 질문에 대답 수 있지만

는,을 포함하는 것이 좋습니다
// On exit, remember to release the media type. 
FreeMediaType(g_StillMediaType); 
+0

여기에 대한 답변의 필수적인 부분과 참조 용 링크를 제공하십시오. 링크 된 페이지가 변경되면 링크 전용 답변이 유효하지 않게 될 수 있습니다. – Eran

+0

@Eran이 수정되었습니다. 이제 괜찮 니? –

관련 문제