2011-08-09 5 views
3

비디오 프레임 (webcam)에서 어떻게 직접 그릴 수 있습니까? 모퉁이에 워터 마크를 놓아야하므로 파일에 비디오를 캡처 할 때이 워터 마크가 각 프레임에 있어야합니다?C++ DirectShow W32 직접 프레임에 그리기

struct Sampler : public CBaseVideoRenderer 
{ 
    Sampler(IUnknown* unk, HRESULT *hr) : CBaseVideoRenderer(__uuidof(CLSID_Sampler), NAME("Frame Sampler"), unk, hr) {}; 

    HRESULT CheckMediaType(const CMediaType *media) 
    {  
     VIDEOINFO* vi; 
     if(!IsEqualGUID(*media->Subtype(), MEDIASUBTYPE_RGB24) || !(vi=(VIDEOINFO *)media->Format())) return E_FAIL; 
     bmih=vi->bmiHeader; 
     return S_OK; 
    } 
    HRESULT DoRenderSample(IMediaSample *sample) 
    { 
      int w=bmih.biWidth; 
      int h=bmih.biHeight; 
      BYTE* data; sample->GetPointer(&data); 
      HDC dc=GetDC(hCameraWindow); 
      BITMAPINFO bmi={0}; bmi.bmiHeader=bmih; RECT r; GetClientRect(hCameraWindow, &r); 
      StretchDIBits(dc,0,0,r.right,r.bottom,0,0,bmih.biWidth,bmih.biHeight,data,&bmi,DIB_RGB_COLORS,SRCCOPY); 
      ReleaseDC(hCameraWindow,dc); 
      return S_OK; 
    } 
    HRESULT ShouldDrawSampleNow(IMediaSample *sample, REFERENCE_TIME *start, REFERENCE_TIME *stop) 
    { 
     return S_OK; // disable droping of frames 
    } 
}; 

을 그리고 초기화 :

hCameraWindow= CreateWindowEx(WS_EX_CLIENTEDGE, "Static", NULL, WS_CHILD | WS_VISIBLE , 20, 5, 640, 480, okno, NULL, GetModuleHandle(NULL), NULL); 
ShowWindow(hCameraWindow,SW_SHOW); 
if(!hCameraWindow)exit(0); 


IGraphBuilder* graph= 0;  hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC,IID_IGraphBuilder, (void **)&graph); 
IMediaControl* ctrl = 0;  hr = graph->QueryInterface(IID_IMediaControl, (void **)&ctrl); 
    IMediaEventEx* mediaEvent=0; hr = graph->QueryInterface(IID_IMediaEvent, (LPVOID *) &mediaEvent); 
    IVideoWindow* m_pVWMoniker=0; hr = graph->QueryInterface(IID_IVideoWindow, (LPVOID *) &m_pVWMoniker); 

m_pVWMoniker->put_Owner((OAHWND)hCameraWindow); 
m_pVWMoniker->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN); 
m_pVWMoniker->put_Visible(OATRUE); 
m_pVWMoniker->put_MessageDrain((OAHWND)hCameraWindow); 

Sampler*  sampler  = new Sampler(0,&hr); 


IPin*   rnd = 0; hr = sampler->FindPin(L"In", &rnd); 
          hr = graph->AddFilter((IBaseFilter*)sampler, L"Sampler"); 

ICreateDevEnum* devs = 0; hr = CoCreateInstance (CLSID_SystemDeviceEnum, 0, CLSCTX_INPROC, IID_ICreateDevEnum, (void **) &devs); 
IEnumMoniker* cams = 0; hr = devs?devs->CreateClassEnumerator (CLSID_VideoInputDeviceCategory, &cams, 0):0; 
IMoniker*  mon = 0; hr = cams?cams->Next (1, &mon, 0):0; 
IBaseFilter* cam = 0; hr = mon?mon->BindToObject(0,0,IID_IBaseFilter, (void**)&cam):0; 
IEnumPins*  pins = 0; hr = cam?cam->EnumPins(&pins):0; 
IPin*   cap = 0; hr = pins?pins->Next(1,&cap, 0):0; 
          hr = graph->AddFilter(cam, L"Capture Source"); 
    // Change resolution 
    IAMStreamConfig *pConfig=0; 
    if(cap->QueryInterface(IID_IAMStreamConfig, (void **)&pConfig) == S_OK) 
    { 
     int iCount = 0; 
     int iSize = 0;  
     hr = pConfig->GetNumberOfCapabilities(&iCount, &iSize); 
     VIDEO_STREAM_CONFIG_CAPS caps; 
     AM_MEDIA_TYPE *pmtConfig; 
     for(int i=0;i<iSize;i++) 
     {   
      pConfig->GetStreamCaps(i, &pmtConfig, (BYTE*)&caps); 
      // if a resoltion has been found, set format to it 
      if(caps.MaxOutputSize.cx == 640 && caps.MinOutputSize.cy == 480) 
      { 
       pConfig->SetFormat(pmtConfig); 
      } 

     } 
     DeleteMediaType(pmtConfig); 
    } 

hr = graph->Connect(cap,rnd); 
hr = graph->Render(cap); 
hr = ctrl->Run(); 

나는 "DoRenderSample"로 프레임에 액세스 할 수 있습니다 다음과 같이

내 설정이다. DShow는 DShow 초보자에게는 매우 비 이용자입니다.

VFW에서 전환하고 프레임에서 GDI +로 그릴 필요가 있습니다. SetBitmapBits/GetBitmapBits를 사용하면 가능합니까?

답변

1

누군가가 관심이 있다면, 그것은 작동있어 확인 해결 된 이슈 - 코드에 아래에 보면, 그것이에는 GDIPlus와 텍스트 그릴 것 - 오류 처리, 내가 자신을 위해 떠난다.

int m_stride; 
VIDEOINFOHEADER m_videoInfo; 


    HRESULT CheckMediaType(const CMediaType *media) 
    {  
     VIDEOINFO* vi; 
     if(!IsEqualGUID(*media->Subtype(), MEDIASUBTYPE_RGB24) || !(vi=(VIDEOINFO *)media->Format())) return E_FAIL; 
     bmih=vi->bmiHeader; 
     m_stride = bmih.biBitCount/8 * bmih.biWidth;  
     return S_OK; 
    } 

HRESULT DoRenderSample(IMediaSample *sample) 
    {  BYTE* data; 
      int w=bmih.biWidth; 
      int h=bmih.biHeight; 
      int len = sample->GetActualDataLength(); 
      sample->GetPointer(&data); 


      BITMAPINFOHEADER bih = bmih; 
      Bitmap bmp(bih.biWidth, bih.biHeight, (bmih.biBitCount/8*bmih.biWidth), PixelFormat24bppRGB, data); 
      Graphics graphics(&bmp); 
      WCHAR wavists[1024];  
      char txt[1024]; 
      sprintf(txt,"THIS TEXT IS DISPLAYED ON EACH FRAME");MultiByteToWideChar(GetACP(), 0, txt, -1, wavists, strlen(txt));  
      graphics.DrawString(wavists,strlen(txt),&Font(&FontFamily(L"Tahoma"), 16, FontStyleBold, UnitPixel),PointF(0,0),&SolidBrush(Color(200,0,255,0))); 





      HDC dc=GetDC(hCameraWindow); 
      BITMAPINFO bmi={0}; bmi.bmiHeader=bmih; RECT r; GetClientRect(hCameraWindow, &r); 
      StretchDIBits(dc,0,0,r.right,r.bottom,0,0,bmih.biWidth,bmih.biHeight,data,&bmi,DIB_RGB_COLORS,SRCCOPY); 
      ReleaseDC(hCameraWindow,dc); 



}