⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 grabberds.cpp

📁 Handle Videos in Forms Delphi... Play/Stop/Pause/FullScreen
💻 CPP
📖 第 1 页 / 共 2 页
字号:
   hr = m_DSI_GB->QueryInterface(IID_IMediaSeeking, (void**)&m_DSI_MS);
   if(FAILED(hr))
    goto L_ERR;
 
   hr = S_OK;
   goto L_EXIT;
 
   L_ERR:
   ReleaseDShow();
   
   L_EXIT:
   return hr;
  }
  //
  virtual HRESULT __fastcall RenderVideoCaptureSource(LPCWSTR szName)
  {
   HRESULT hr;
   IPin *Pin = NULL;
   
   // Get the interface for DirectShow's GraphBuilder
   hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
					     IID_IGraphBuilder, (VOID **)&m_DSI_GB);
   if(FAILED(hr))
   {
    if(hr != CO_E_NOTINITIALIZED)
     goto L_ERR;
    hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    if(FAILED(hr))
     goto L_ERR;
    co_initialized = TRUE;
    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
					     IID_IGraphBuilder, (VOID **)&m_DSI_GB);
    if(FAILED(hr))
     goto L_ERR;
   }
   
   hr = m_DSI_GB->QueryInterface(IID_IFilterGraph2, (void**)&m_DSI_FG);
   if(FAILED(hr))
    goto L_ERR;
 
   hr = FindVideoCaptureSource(szName, &m_DSI_BF_source);
   if(FAILED(hr))
    goto L_ERR;
   
   hr = m_DSI_GB->AddFilter(m_DSI_BF_source, L"Video Capture Source");
   if(FAILED(hr))
    goto L_ERR;
   
   vR = (IBaseFilter*)this;
   vR->AddRef();
   hr = m_DSI_GB->AddFilter(vR, L"V-Renderer");
   if(FAILED(hr))
    goto L_ERR;
   
   hr = FindPinByCategory(m_DSI_BF_source, PINDIR_OUTPUT, PIN_CATEGORY_CAPTURE, &Pin);
   if(FAILED(hr))
    goto L_EXIT;
   
   if(capture_subtype != GUID_NULL)
   {
    IAMStreamConfig *cfg;
    if(SUCCEEDED(Pin->QueryInterface(IID_IAMStreamConfig, (void**)&cfg)))
    {
     AM_MEDIA_TYPE *pmt;
     if(SUCCEEDED(cfg->GetFormat(&pmt)))
     {
      BITMAPINFOHEADER *pBih = NULL;
      REFERENCE_TIME avg_time_per_frame = (__int64)(10000000.0f / (float)capture_fps + 0.5f);
      if(pmt->formattype == FORMAT_VideoInfo)
      {
	   VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)(pmt->pbFormat);
	   pVih->AvgTimePerFrame = avg_time_per_frame;
	   pBih = &(pVih->bmiHeader);
	   pVih->dwBitRate = 0;
	  }
	  else
	  if(pmt->formattype == FORMAT_VideoInfo2)
	  {
	   VIDEOINFOHEADER2 *pVih2 = (VIDEOINFOHEADER2*)(pmt->pbFormat);
	   pVih2->AvgTimePerFrame = avg_time_per_frame;
	   pVih2->dwBitRate = 0;
	   pVih2->dwInterlaceFlags = 0;
	   pVih2->dwPictAspectRatioX = capture_sz.cx;
	   pVih2->dwPictAspectRatioY = capture_sz.cy;
	   pVih2->dwControlFlags = 0;
	   pBih = &(pVih2->bmiHeader);
	  }
	  
	  if(pBih)
	  {
	   ZeroMemory(pBih, sizeof(BITMAPINFOHEADER));
	   pBih->biSize = sizeof(BITMAPINFOHEADER);
	   pBih->biWidth = capture_sz.cx;
	   pBih->biHeight = capture_sz.cy;
	   
	   if((capture_subtype == MEDIASUBTYPE_RGB32) ||
		  (capture_subtype == MEDIASUBTYPE_ARGB32))
	    pBih->biBitCount = 32;
	   else
	   if(capture_subtype == MEDIASUBTYPE_RGB24)
	    pBih->biBitCount = 24;
	   else
	   if((capture_subtype == MEDIASUBTYPE_RGB555) ||
	      (capture_subtype == MEDIASUBTYPE_RGB565))
	    pBih->biBitCount = 16;
	   else
	   if(capture_subtype == MEDIASUBTYPE_YUY2)
	   {
	    pBih->biCompression = MAKEFOURCC('Y', 'U', 'Y', '2');
	    pBih->biBitCount = 16;
	   }
	   else
	   if(capture_subtype == MEDIASUBTYPE_UYVY)
	   {
	    pBih->biCompression = MAKEFOURCC('U', 'Y', 'V', 'Y');
	    pBih->biBitCount = 16;
	   }
	   else
	   if(capture_subtype == MEDIASUBTYPE_YV12)
	   {
	    pBih->biCompression = MAKEFOURCC('Y', 'V', '1', '2');
	    pBih->biBitCount = 12;
	   }
	   else
	   if(capture_subtype == MEDIASUBTYPE_NV12)
	   {
	    pBih->biCompression = MAKEFOURCC('N', 'V', '1', '2');
	    pBih->biBitCount = 12;
	   }
	   
	   pBih->biSizeImage = (pBih->biWidth * pBih->biHeight * pBih->biBitCount) >> 3;
	   
	   pmt->subtype = capture_subtype;
	   
	   cfg->SetFormat(pmt);
	  }
      DeleteMediaType(pmt);
     }
     cfg->Release();
    }
   }
   
   hr = m_DSI_FG->RenderEx(Pin, AM_RENDEREX_RENDERTOEXISTINGRENDERERS, NULL);
   SAFE_RELEASE(Pin);
   if(FAILED(hr))
    goto L_ERR;
   
   // QueryInterface for DirectShow
   hr = m_DSI_GB->QueryInterface(IID_IMediaControl, (void**)&m_DSI_MC);
   if(FAILED(hr))
    goto L_ERR;
 
   hr = m_DSI_GB->QueryInterface(IID_IMediaSeeking, (void**)&m_DSI_MS);
   if(FAILED(hr))
    goto L_ERR;
   
   hr = S_OK;
   goto L_EXIT;
   
   L_ERR:
   ReleaseDShow();
   
   L_EXIT:
   return hr;
  }
  //
  virtual void __fastcall SetCallback(vg_callback callback)
  {
   CVRenderer::callback = callback;
  }
  //
  virtual void __fastcall SetUserObject(void *obj)
  {
   user_obj = obj;
  }
  //
  virtual void* __fastcall GetUserObject()
  {
   return user_obj;
  }
  //
  virtual IUnknown* __fastcall GetMediaControl()
  {
   return m_DSI_MC;
  }
  //
  virtual void __fastcall EnableLoop(BOOL bEnable)
  {
   if((bEnable) && (!m_hwnd))
   {
    WNDCLASS wnd;
    ZeroMemory(&wnd, sizeof(wnd));
    wnd.lpszClassName = "grabber_new";
    wnd.lpfnWndProc = WindowProcedure;
    RegisterClass(&wnd);
    m_hwnd = CreateWindowEx(0, wnd.lpszClassName, "", WS_POPUP,
						    0, 0, 0, 0, NULL, NULL, NULL, NULL);
    SetWindowLong(m_hwnd, GWL_USERDATA, (LONG)this);
   }
   b_loop_enabled = bEnable;
  }
  //
  virtual void __fastcall SuggestVideoCaptureFormat(const GUID *subtype, SIZE sz, float fps)
  {
   capture_subtype = *subtype;
   capture_sz = sz;
   capture_fps = fps;
  }
  //
  virtual HRESULT __fastcall GetVideoCaptureFormat(GUID *subtype, SIZE *sz, float *fps)
  {
   IPin *Pin = NULL;
   IAMStreamConfig *cfg = NULL;
   AM_MEDIA_TYPE *pmt = NULL;
   HRESULT hr;
   
   if(!m_DSI_BF_source)
   {
    hr = E_FAIL;
    goto L_EXIT;
   }
   
   hr = FindPinByCategory(m_DSI_BF_source, PINDIR_OUTPUT, PIN_CATEGORY_CAPTURE, &Pin);
   if(FAILED(hr))
    goto L_EXIT;
   
   hr = Pin->QueryInterface(IID_IAMStreamConfig, (void**)&cfg);
   if(FAILED(hr))
    goto L_EXIT;
   
   hr = cfg->GetFormat(&pmt);
   if(FAILED(hr))
    goto L_EXIT;
   
   *subtype = pmt->subtype;
   
   BITMAPINFOHEADER *pBih = NULL;
   if(pmt->formattype == FORMAT_VideoInfo)
   {
    VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)(pmt->pbFormat);
	*fps = 10000000.0f / (float)pVih->AvgTimePerFrame;
	pBih = &(pVih->bmiHeader);
   }
   else
   if(pmt->formattype == FORMAT_VideoInfo2)
   {
    VIDEOINFOHEADER2 *pVih2 = (VIDEOINFOHEADER2*)(pmt->pbFormat);
    *fps = 10000000.0f / (float)pVih2->AvgTimePerFrame;
    pBih = &(pVih2->bmiHeader);
   }
   if(pBih)
   {
    sz->cx = pBih->biWidth;
    sz->cy = pBih->biHeight;
   }
   
   hr = S_OK;
   
   L_EXIT:
   if(pmt)
    DeleteMediaType(pmt);
   SAFE_RELEASE(cfg);
   SAFE_RELEASE(Pin);
   return hr;
  }
  //
  virtual BOOL __fastcall IsVideo()
  {
   return b_video;
  }
  //
  virtual BOOL __fastcall IsAudio()
  {
   return b_audio;
  }
 
 // Overridables
 public:
  virtual CBasePin *GetPin(int n)
  {
   if(!m_pInputPin)
   {
    HRESULT hr;
    m_pInputPin = new CVPin(this, &hr, L"In");
   }
   return m_pInputPin;
  }
  //
  virtual HRESULT CheckMediaType(const CMediaType *pmt)
  {
   const GUID *type = pmt->Type();
   if(*type != MEDIATYPE_Video)
    return E_INVALIDARG;
   
   const GUID *formattype = pmt->FormatType();
   if((*formattype != FORMAT_VideoInfo) && (*formattype != FORMAT_VideoInfo2))
    return E_INVALIDARG;
   
   const GUID *subtype = pmt->Subtype();
   DWORD i;
   for(i = 0; i < N_SUBTYPES; i++)
    if((subtypes_enabled[i]) && (*subtype == g_subtypes[i]))
     break;
   if(i >= N_SUBTYPES)
    return E_INVALIDARG;
   
   return S_OK;
  }
   
  virtual HRESULT DoRenderSample(IMediaSample *pMediaSample)
  {
   BYTE *pBits = NULL;
   HRESULT hr = pMediaSample->GetPointer(&pBits);
   if(FAILED(hr))
    return hr;
   if((!pBits) || (!callback))
    return S_FALSE;
   if(callback)
    hr = (*callback)((IVideoGrabber*)(IVideoGrabberX*)this, pBits);
   if(SUCCEEDED(hr))
   {
    end_of_stream = FALSE;
    SetEvent(event);
   }
   return hr;
  }
  
  virtual HRESULT SetMediaType(const CMediaType *pmt)
  {
   const GUID *subtype = pmt->Subtype();
   const GUID *formattype = pmt->FormatType();
	
   if(*formattype == FORMAT_VideoInfo)
   {
    VIDEOINFOHEADER *pVI = (VIDEOINFOHEADER*)pmt->Format();
    aspect_x = pVI->bmiHeader.biWidth;
	aspect_y = pVI->bmiHeader.biHeight;
	memcpy(&bih, &pVI->bmiHeader, sizeof(BITMAPINFOHEADER));
   }
   else
   if(*formattype == FORMAT_VideoInfo2)
   {
    VIDEOINFOHEADER2 *pVI2 = (VIDEOINFOHEADER2*)pmt->Format();
	if((aspect_x != pVI2->dwPictAspectRatioX) ||
	   (aspect_y != pVI2->dwPictAspectRatioY))
	{
	 aspect_x = pVI2->dwPictAspectRatioX;
     aspect_y = pVI2->dwPictAspectRatioY;
    }
	memcpy(&bih, &pVI2->bmiHeader, sizeof(BITMAPINFOHEADER));
   }
   else
    return E_UNEXPECTED;

   DWORD i;
   for(i = 0; i < N_SUBTYPES; i++)
    if(g_subtypes[i] == *subtype)
    {
     current_subtype = &g_subtypes[i];
     break;
    }
   if(i >= N_SUBTYPES)
    return E_UNEXPECTED;

   return S_OK;
  }
  
  virtual void OnReceiveFirstSample(IMediaSample *pMediaSample)
  {
   DoRenderSample(pMediaSample);
  }
  
  virtual HRESULT EndOfStream()
  {
   if(b_loop_enabled)
    PostMessage(m_hwnd, WM_USER, 0, 0);
   end_of_stream = TRUE;
   SetEvent(event);
   return S_OK;
  }
  
  // Statis members
  public:
   static LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message,
										   WPARAM wParam, LPARAM lParam)
   {
    CVRenderer *obj = (CVRenderer*)GetWindowLong(hwnd, GWL_USERDATA);
    if(obj)
     return obj->WindowProc(hwnd, message, wParam, lParam);
    return DefWindowProc(hwnd, message, wParam, lParam);
   }
 };
//

//
extern "C"
HRESULT __fastcall VideoGrabberCreate(IVideoGrabber **grabber)
{
 HRESULT hr = S_OK;
 CVRenderer *obj = new CVRenderer(&hr);
 if(!obj)
  return E_OUTOFMEMORY;
 if(FAILED(hr))
 {
  delete obj;
  return hr;
 }
 obj->AddRef();
 *grabber = (IVideoGrabber*)(IVideoGrabberX*)obj;
 return S_OK;
}
//

//
extern "C"
HRESULT __fastcall EnumVideoCaptureSourcesStart(IUnknown **ppEnumMoniker)
{
 ICreateDevEnum *pDevEnum;
 IEnumMoniker *pEnum;
 
 // Create the System Device Enumerator.
 HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
							   IID_ICreateDevEnum, (void**)&pDevEnum);
 if(FAILED(hr))
  goto L_EXIT;

 // Create an enumerator for the video capture category.
 hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
 pDevEnum->Release();
 if(hr != S_OK)
  goto L_EXIT;
 
 *ppEnumMoniker = pEnum;
 hr = S_OK;
 
 L_EXIT:
 return hr;
}
//

//
extern "C"
HRESULT __fastcall EnumVideoCaptureSourcesNext(IUnknown *pEnumMoniker, VARIANT *pName,
											IUnknown **ppMoniker)
{
 IEnumMoniker *pEnum = (IEnumMoniker*)pEnumMoniker;
 IMoniker *pMoniker;
 HRESULT hr;
 
 while((hr = pEnum->Next(1, &pMoniker, NULL)) == S_OK)
 {
  IPropertyBag *pPropBag;
  hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPropBag);
  if(FAILED(hr))
  {
   pMoniker->Release();
   continue;  // Skip this one, maybe the next one will work.
  }
  
  // Find the description or friendly name.
  VariantInit(pName);
  hr = pPropBag->Read(L"FriendlyName", pName, 0);
  if((SUCCEEDED(hr)) && (pName->vt == VT_BSTR))
  {
   pPropBag->Release();
   if(ppMoniker)
    *ppMoniker = pMoniker;
   else
    pMoniker->Release();
   hr = S_OK;
   goto L_EXIT;
  }
  else
   VariantClear(pName);
  
  pPropBag->Release();
  pMoniker->Release();
 }
 
 L_EXIT:
 return hr;
}
//

//
extern "C"
void __fastcall EnumVideoCaptureSourcesEnd(IUnknown *pEnumMoniker)
{
 pEnumMoniker->Release();
}
//

//
extern "C"
HRESULT __fastcall EnumVideoCaptureFormatsStart(LPWSTR szVideoCaptureSource,
											 IUnknown **ppAMStreamConfig,
											 DWORD *nFormats)
{
 IBaseFilter *source = NULL;
 IPin *Pin = NULL;
 IAMStreamConfig *cfg = NULL;
 HRESULT hr;
 
 hr = FindVideoCaptureSource(szVideoCaptureSource, &source);
 if(FAILED(hr))
  goto L_EXIT;
   
 hr = FindPinByCategory(source, PINDIR_OUTPUT, PIN_CATEGORY_CAPTURE, &Pin);
 if(FAILED(hr))
  goto L_EXIT;
 
 hr = Pin->QueryInterface(IID_IAMStreamConfig, (void**)&cfg);
 if(FAILED(hr))
  goto L_EXIT;
 
 int iCount = 0, iSize = 0;
 hr = cfg->GetNumberOfCapabilities(&iCount, &iSize);
 if(FAILED(hr))
  goto L_EXIT;
 if(iSize != sizeof(VIDEO_STREAM_CONFIG_CAPS))
 {
  hr = E_UNEXPECTED;
  goto L_EXIT;
 }

 cfg->AddRef();
 *ppAMStreamConfig = cfg;
 *nFormats = iCount;
 hr = S_OK;
 
 L_EXIT:
 SAFE_RELEASE(cfg);
 SAFE_RELEASE(Pin);
 SAFE_RELEASE(source);
 return hr;
}
//

//
extern "C"
HRESULT __fastcall EnumVideoCaptureFormatsByIndex(IUnknown *pAMStreamConfig, DWORD iFormat,
											   GUID *subtype,
											   SIZE *szMin, SIZE *szMax, SIZE *szStep,
											   float *fpsMin, float *fpsMax,
											   SIZE *szDef, float *fpsDef)
{
 VIDEO_STREAM_CONFIG_CAPS scc;
 AM_MEDIA_TYPE *pmtConfig = NULL;
 IAMStreamConfig *cfg = (IAMStreamConfig*)pAMStreamConfig;
 HRESULT hr;
 
 hr = cfg->GetStreamCaps(iFormat, &pmtConfig, (BYTE*)&scc);
 if(FAILED(hr))
  goto L_EXIT;
 
 BITMAPINFOHEADER bih;
 if(pmtConfig->formattype == FORMAT_VideoInfo)
 {
  VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)(pmtConfig->pbFormat);
  bih = pVih->bmiHeader;
 }
 else
 if(pmtConfig->formattype == FORMAT_VideoInfo2)
 {
  VIDEOINFOHEADER2 *pVih2 = (VIDEOINFOHEADER2*)(pmtConfig->pbFormat);
  bih = pVih2->bmiHeader;
 }
 else
 {
  hr = E_UNEXPECTED;
  goto L_EXIT;
 }
 
 *subtype = pmtConfig->subtype;
 
 *szMin = scc.MinOutputSize;
 *szMax = scc.MaxOutputSize;
 szStep->cx = scc.OutputGranularityX;
 szStep->cy = scc.OutputGranularityY;
 
 *fpsMin = 10000000.0f / (float)scc.MaxFrameInterval;
 *fpsMax = 10000000.0f / (float)scc.MinFrameInterval;
 
 DeleteMediaType(pmtConfig);
 pmtConfig = NULL;
 hr = cfg->GetFormat(&pmtConfig);
 if((SUCCEEDED(hr)) && ((pmtConfig->formattype == FORMAT_VideoInfo) ||
						(pmtConfig->formattype == FORMAT_VideoInfo2)))
 {
  if(pmtConfig->formattype == FORMAT_VideoInfo)
  {
   VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)(pmtConfig->pbFormat);
   bih = pVih->bmiHeader;
   *fpsDef = 10000000.0f / (float)pVih->AvgTimePerFrame;
  }
  else
  {
   VIDEOINFOHEADER2 *pVih2 = (VIDEOINFOHEADER2*)(pmtConfig->pbFormat);
   bih = pVih2->bmiHeader;
   *fpsDef = 10000000.0f / (float)pVih2->AvgTimePerFrame;
  }
  szDef->cx = bih.biWidth;
  szDef->cy = bih.biHeight;
 }
 else
 {
  szDef->cx = 0;
  szDef->cy = 0;
  *fpsDef = 0.0f;
 }
 
 if(pmtConfig)
 {
  DeleteMediaType(pmtConfig);
  pmtConfig = NULL;
 }
 hr = cfg->GetFormat(&pmtConfig);
 if(SUCCEEDED(hr))
 {
  hr = (pmtConfig->subtype == *subtype) ? S_OK : S_FALSE;
 }
 else
  hr = S_FALSE;
 
 L_EXIT:
 if(pmtConfig)
  DeleteMediaType(pmtConfig);
 return hr;
}
//

//
extern "C"
void __fastcall EnumVideoCaptureFormatsEnd(IUnknown *pAMStreamConfig)
{
 pAMStreamConfig->Release();
}
//

// End

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -