Visual Studio 2010 调用 DirectShow 采集摄像头图像

原文地址:https://blog.csdn.net/Sad_Sugar/article/details/24888341

一年前做的运动目标检测,平均能到每秒20帧左右。调用摄像头用的都是OpenCV提供的接口,前两天无意在OpenCV的一篇帮助文档中中看到在Windows下用DirectShow采集摄像头图像比OpenCV效率要高一些,于是趁着五一假期就弄了一下DirectShow,很麻烦。

网上已有的资料基本都是说下载DirectShow然后怎样怎样,但发现根本找不到DirectShow,后来看有文章说DirectShow是DirectX中的一部分,于是去Microsoft官网下了DirectX_11,装上以后,在Sample文件夹中死活找不到baseclass工程。。。各种无语。后来找到一位救命恩人,链接在这里:  http://blog.csdn.net/liuchen1206/article/details/8462637   详细讲解了在VS2010下怎样配置DirectShow,原来要去下载最新的Windows SDK。。于是又下了一次,装好后找到了baseclass工程,备份、打开后编译,把strmbasd.lib和strmbase.lib放到库目录下,又配置了VS2010的各种属性,才搞定。

搞定了DirectShow后,还有一个ARFrameGrabber类,一开始还以为是DirectShow库里面的,后来发现是有个哥们儿自己写的。。于是又在网上找到了ARFrameGrabber.cpp和ARFrmaeGrabber.h的源码,放进工程里面,这才调试正常。

采集摄像头视频代码如下:

// DirectShowExample.cpp : 定义控制台应用程序的入口点。
//
#include <stdio.h>
#include <time.h>
#include <opencv.hpp>
#include "ARFrameGrabber.h"
 
#define TIMEGAPINIT		int64 time_count64;\
						double TICKPERMILLISEC = cvGetTickFrequency() * 1000
#define TIMEGAPSTART		time_count64 = cvGetTickCount()
#define TIMEGAPEND(info)	printf(#info": %.2fms\n", (cvGetTickCount() - time_count64) / TICKPERMILLISEC)
 
#define WINDOWNAME "camera"
 
void frameInit(IplImage *pFrame, ARFrameGrabber *pFrameGrabber)
{
	int width = 0;
	int height = 0;
	int widthStep = 0;
 
	pFrameGrabber->Init(0, true);
	//frameGrabber.SetFlippedImage(false);
	width = pFrameGrabber->GetWidth();
	height = pFrameGrabber->GetHeight();
	widthStep = (width * sizeof(RGBTRIPLE) + 3) & -4;	// 4字节对齐,所以最后要与上11111100
	cvInitImageHeader(pFrame, cvSize(width, height), IPL_DEPTH_8U, 3, IPL_ORIGIN_BL);
	pFrame->widthStep = widthStep;
}
 
int main(int argc, char* argv[])
{
	static ARFrameGrabber frameGrabber;
	IplImage frame;
	int widthStep = 0;
 
	frameInit(&frame, &frameGrabber);
	widthStep = frame.widthStep;
 
	cvNamedWindow(WINDOWNAME);
	TIMEGAPINIT;
	int count = 0;
	time_t t0 = time(NULL);
	while (true) {
		++count;
		TIMEGAPSTART;
		frameGrabber.GrabByteFrame();	// 8~10ms
		TIMEGAPEND(GrabByteFrame);
 
		TIMEGAPSTART;
		frame.imageData = (char*)frameGrabber.GetByteBuffer();
		//cvSetData(&frame, frameGrabber.GetByteBuffer(), widthStep);	// 0ms
		TIMEGAPEND(cvSetData);
		// 视频分析部分
		TIMEGAPSTART;
		cvShowImage(WINDOWNAME, &frame);	// 0.5ms
		TIMEGAPEND(ShowImage);
		if (27 == cvWaitKey(1)) {
			break;
		}
	}
	printf("平均每秒%.1f帧\n", (double)count / (time(NULL) - t0));
 
	cvDestroyWindow(WINDOWNAME);
 
	
 
	return 0;
}

再附一段OpenCV对应的测试代码:

// CameraExample.cpp : 定义控制台应用程序的入口点。
//
 
#include <stdio.h>
#include <time.h>
 
#include <Windows.h>
 
#include <opencv.hpp>
 
#define WINDOWNAME1	"video1"
#define WINDOWNAME2	"video2"
 
#define TIMEGAPINIT		int64 time_count64;\
						double TICKPERMILLISEC = cvGetTickFrequency() * 1000
#define TIMEGAPSTART		time_count64 = cvGetTickCount()
#define TIMEGAPEND(info)	printf(#info": %.2fms\n", (cvGetTickCount() - time_count64) / TICKPERMILLISEC)
 
 
int main()
{
	IplImage *pImage = NULL;
	CvCapture *pCapture = cvCreateCameraCapture(-1);
	cvNamedWindow(WINDOWNAME1, CV_WINDOW_AUTOSIZE);
 
 
	TIMEGAPINIT;
	int count = 0;
	time_t t0 = time(NULL);
	while (true) {
		++count;
		TIMEGAPSTART;
		pImage = cvQueryFrame(pCapture);
		TIMEGAPEND(cvQueryFrame);
 
		TIMEGAPSTART;
		cvShowImage(WINDOWNAME1, pImage);
		TIMEGAPEND(ShowImage);
 
		if (cvWaitKey(1) == 27) {
			break;
		}
	}
	printf("平均每秒%.1f帧\n", (double)count / (time(NULL) - t0));
 
	cvDestroyWindow(WINDOWNAME1);
	cvReleaseCapture(&pCapture);
 
	return 0;
}

笔记本的摄像头视频大小是640*480的,在均为Release模式下测试发现,DirectShow抓取一帧图像的速度能保持在8~10ms之间,而OpenCV则不稳定,今天测试时比较不给力,基本一帧图像要100ms以上。  当然有的时候是比较快的,可能能到20ms左右。具体为什么不稳定我也不太清楚。还没有研究到那么底层的东西。 如果有大神看到的话希望能给出写解释,感激不尽!

附ARFrameGrabber类的源码:

ARFrameGrabber.h

// ARFrameGrabber.h: interface for the ARFrameGrabber class.
//
//////////////////////////////////////////////////////////////////////
 
#if !defined(AFX_ARFRAMEGRABBER_H__C5553937_4BAB_4FEF_B4A6_1693AB0C99E3__INCLUDED_)
#define AFX_ARFRAMEGRABBER_H__C5553937_4BAB_4FEF_B4A6_1693AB0C99E3__INCLUDED_
 
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
 
//#include <AR/config.h>
 
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <dshow.h>
//#include <streams.h>
#include <atlbase.h>
#include "qedit.h"
 
class SmartString
{
public:
 SmartString():str(NULL) {}
 
 SmartString(char* pStr):str(NULL)
 {
  if (pStr)
  {
   int size = int(strlen(pStr));
   str = new char[size+1];
   strcpy(str, pStr);
  }
 }
 
 SmartString(SmartString& sStr)
 {
  SetString(sStr.GetBuffer());
 }
 
 ~SmartString()
 {
  if (str)
   delete[] str;
 }
 
 SmartString& operator =(char* pStr)
 {
  SetString(pStr);
  return *this;
 }
 
 SmartString& operator =(SmartString& sStr)
 {
  SetString(sStr.GetBuffer());
  return *this;
 }
 
 char* GetBuffer() {return str;}
 
protected:
 void SetString(char *pStr)
 {
  if (str)
   delete[] str;
 
  if (!pStr)
  {
   str = NULL;
  }
  else
  {
   int size = int(strlen(pStr));
   str = new char[size + 1];
   strcpy(str, pStr);
  }
 
 }
 
 
 char* str;
};
 
class DeviceInfo
{
public:
 DeviceInfo():next(NULL), deviceId(-1)
 {
 } 
 ~DeviceInfo()
 {
  if (next)
   delete next;
 }
 
 
 SmartString friendlyName;
 int   deviceId; 
 DeviceInfo* next;
};
 
 
class  ARFrameGrabber  
{
public:
 ARFrameGrabber();
 virtual ~ARFrameGrabber();
 
 void Init(int deviceId, bool displayProperties = true);
 void BindFilter(int deviceId, IBaseFilter **pFilter);
 void GrabFrame(long* size, long** pBuffer);
 void GrabFrame();
 void Grab32BitFrame();
 void GrabByteFrame();
 void SetCrossBar();
 
 
 
 long  GetBufferSize() {return bufferSize;}
 long* GetBuffer() {return pBuffer;}
 BYTE* GetByteBuffer() {return pBYTEbuffer;}
 
 void SetFlippedImage(bool flag) {flipImage = flag;}
 
 void DisplayProperties();
 void EnumDevices(DeviceInfo *head);
    int GetWidth();
    int GetHeight();
 
protected:
 CComPtr<IGraphBuilder> pGraph;
 CComPtr<IBaseFilter> pDeviceFilter;
 CComPtr<IMediaControl> pMediaControl;
 CComPtr<IBaseFilter> pSampleGrabberFilter;
 CComPtr<ISampleGrabber> pSampleGrabber;
 CComPtr<IPin> pGrabberInput;
 CComPtr<IPin> pGrabberOutput;
 CComPtr<IPin> pCameraOutput;
 CComPtr<IMediaEvent> pMediaEvent;
 CComPtr<IBaseFilter> pNullFilter;
 CComPtr<IPin> pNullInputPin;
 
 void FlipImage(long* pBuf);
 
private:
 void ReportError(char *msg);
 
 bool flipImage;
 long bufferSize;
 long *pBuffer;
 BYTE *pBYTEbuffer;
    bool connected;
    int width;
    int height;
};
 
#endif // !defined(AFX_ARFRAMEGRABBER_H__C5553937_4BAB_4FEF_B4A6_1693AB0C99E3__INCLUDED_)

ARFrameGrabber.cpp

// ARFrameGrabber.cpp: implementation of the ARFrameGrabber class.
//
//////////////////////////////////////////////////////////////////////
 
#include "stdafx.h"
#include <assert.h>
#include "ARFrameGrabber.h"
 
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
 
ARFrameGrabber::ARFrameGrabber() 
    : pBuffer(NULL), bufferSize(0), flipImage(false), connected(false), width(0), height(0)
{
}
 
ARFrameGrabber::~ARFrameGrabber()
{
 pMediaControl->Stop();
 if (pBuffer)
  delete[] pBuffer;
 if(pBYTEbuffer)
  delete[] pBYTEbuffer;
}
 
 
void ARFrameGrabber::Init(int deviceId, bool displayProperties)
{
 HRESULT hr = S_OK;
 CoInitialize(NULL);
 // Create the Filter Graph Manager.
 hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
  IID_IGraphBuilder, (void **)&pGraph);
 
 hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, 
    IID_IBaseFilter, (LPVOID *)&pSampleGrabberFilter);
 
 hr = pGraph->QueryInterface(IID_IMediaControl, (void **) &pMediaControl);
 hr = pGraph->QueryInterface(IID_IMediaEvent, (void **) &pMediaEvent);
 
 hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER,
  IID_IBaseFilter, (LPVOID*) &pNullFilter);
 
 hr = pGraph->AddFilter(pNullFilter, L"NullRenderer");
 
 hr = pSampleGrabberFilter->QueryInterface(IID_ISampleGrabber, (void**)&pSampleGrabber);
 
 
 
 AM_MEDIA_TYPE   mt;
 ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
 mt.majortype = MEDIATYPE_Video;
 mt.subtype = MEDIASUBTYPE_RGB32;
 mt.formattype = FORMAT_VideoInfo; 
 hr = pSampleGrabber->SetMediaType(&mt);
 
 pGraph->AddFilter(pSampleGrabberFilter, L"Grabber");
 
 
 
 // Bind Device Filter.  We know the device because the id was passed in
 BindFilter(deviceId, &pDeviceFilter);
 pGraph->AddFilter(pDeviceFilter, NULL);
 
 CComPtr<IEnumPins> pEnum;
 pDeviceFilter->EnumPins(&pEnum);
 
 hr = pEnum->Reset();
 hr = pEnum->Next(1, &pCameraOutput, NULL);
 
 
 pEnum = NULL; 
 pSampleGrabberFilter->EnumPins(&pEnum);
 pEnum->Reset();
 hr = pEnum->Next(1, &pGrabberInput, NULL);
 
 pEnum = NULL;
 pSampleGrabberFilter->EnumPins(&pEnum);
 pEnum->Reset();
 pEnum->Skip(1);
 hr = pEnum->Next(1, &pGrabberOutput, NULL);
 
 
 
 
 pEnum = NULL;
 pNullFilter->EnumPins(&pEnum);
 pEnum->Reset();
 hr = pEnum->Next(1, &pNullInputPin, NULL);
 
  SetCrossBar();
 
    if (displayProperties) {
   CComPtr<ISpecifyPropertyPages> pPages;
 
   HRESULT hr = pCameraOutput->QueryInterface(IID_ISpecifyPropertyPages, (void**)&pPages);
   if (SUCCEEDED(hr))
   {
    PIN_INFO PinInfo;
    pCameraOutput->QueryPinInfo(&PinInfo);
 
    CAUUID caGUID;
    pPages->GetPages(&caGUID);
 
    OleCreatePropertyFrame(
     NULL,
     0,
     0,
     L"Property Sheet",
     1,
     (IUnknown **)&(pCameraOutput.p),
     caGUID.cElems,
     caGUID.pElems,
     0,
     0,
     NULL);
    CoTaskMemFree(caGUID.pElems);
    PinInfo.pFilter->Release();
   }
    }
 
    hr = pGraph->Connect(pCameraOutput, pGrabberInput);
 
 hr = pGraph->Connect(pGrabberOutput, pNullInputPin);
 
// hr = pGraph->Render(pGrabberOutput);
 
 if (FAILED(hr))
 {
  switch(hr)
  {
  case VFW_S_NOPREVIEWPIN :
   break;
  case E_FAIL :
   break;
  case E_INVALIDARG :
   break;
  case E_POINTER :
   break;
  }
 }
 
 pSampleGrabber->SetBufferSamples(TRUE);
 pSampleGrabber->SetOneShot(TRUE);
    
    hr = pSampleGrabber->GetConnectedMediaType(&mt);
    VIDEOINFOHEADER *videoHeader;
    assert(mt.formattype == FORMAT_VideoInfo);
    videoHeader = reinterpret_cast<VIDEOINFOHEADER*>(mt.pbFormat);
    width = videoHeader->bmiHeader.biWidth;
    height = videoHeader->bmiHeader.biHeight;
    connected = true;
}
 
void ARFrameGrabber::GrabFrame(long* size, long** pBuffer)
{
    if (!size)
  return;
 
 // don't want to leak mem, pBuffer must be NULL
 if (!pBuffer || *pBuffer)
  return;
 
 long evCode;
 
 
 pMediaControl->Run();
 pMediaEvent->WaitForCompletion(INFINITE, &evCode);
 pSampleGrabber->GetCurrentBuffer(size, NULL);
 if (*size)
 {
  *pBuffer = new long[*size];
 }
 
 pSampleGrabber->GetCurrentBuffer(size, *pBuffer);
}
 
void ARFrameGrabber::GrabFrame()
{
 long evCode;
 long size = 0;
 
 pMediaControl->Run();
 pMediaEvent->WaitForCompletion(INFINITE, &evCode);
 pSampleGrabber->GetCurrentBuffer(&size, NULL);
 
 // if buffer is not the same size as before, create a new one
 if (size != bufferSize)
 {
  if (pBuffer)
   delete[] pBuffer;
 
  bufferSize = size;
 
  pBuffer = new long[bufferSize];
 }
 
 pSampleGrabber->GetCurrentBuffer(&size, pBuffer);
 if (flipImage)
  FlipImage(pBuffer);
}
 
void ARFrameGrabber::FlipImage(long* pBuf)
{
 DWORD *ptr = (DWORD*)pBuf;
 int pixelCount = bufferSize/4;
 
 
 if (!pBuf)
  return;
 
 for (int index = 0; index < pixelCount/2; index++)
 {
  ptr[index] = ptr[index] ^ ptr[pixelCount - index - 1];
  ptr[pixelCount - index - 1] = ptr[index] ^ ptr[pixelCount - index - 1];
  ptr[index] = ptr[index] ^ ptr[pixelCount - index - 1];
 }
 
}
//add by hardy 
void ARFrameGrabber::GrabByteFrame()
{
 
 long evCode;
 long size = 0;
 
 pMediaControl->Run();
 pMediaEvent->WaitForCompletion(INFINITE, &evCode);
 pSampleGrabber->GetCurrentBuffer(&size, NULL);
 
 // if buffer is not the same size as before, create a new one
 if (size != bufferSize)
 {
  if (pBuffer)
   delete[] pBuffer;
  bufferSize = size;
  pBuffer = new long[bufferSize];
  if(pBYTEbuffer)
   delete[] pBYTEbuffer;
  pBYTEbuffer = new BYTE[bufferSize/4*3];
 
 }
 
 pSampleGrabber->GetCurrentBuffer(&size, pBuffer);
 BYTE *pTemp = (BYTE*) pBuffer;
 BYTE *pBYTETemp =  pBYTEbuffer;
 for(int i =0 ;i<bufferSize;i++)
 {
/*
  *(pBYTEbuffer) = *(pTemp);     //G
  *(pBYTEbuffer++) = *(pTemp++); //B
  *(pBYTEbuffer++) = *(pTemp++); //R
  pTemp++;
  pTemp++;
  */
  if((i+1)%4==0) 
  {
   pTemp++;
  }
  else
  {
  *(pBYTETemp) = *(pTemp);     //G 
  pBYTETemp++;
  pTemp++;
  }
 }
}
 
void ARFrameGrabber::Grab32BitFrame()
{
 long evCode;
 long size = 0;
 long* pData;
 unsigned char* pTemp;
 unsigned char* ptr;
 
 pMediaControl->Run();
 pMediaEvent->WaitForCompletion(INFINITE, &evCode);
 pSampleGrabber->GetCurrentBuffer(&size, NULL);
 
 if (size != bufferSize)
 {
  if (pBuffer)
   delete[] pBuffer;
 
  bufferSize = size/3*4;  // add space for padding
 
  pBuffer = new long[bufferSize];
 }
 
 pData= (long*) new unsigned char[size];
 pSampleGrabber->GetCurrentBuffer(&size, pData);
 ptr = ((unsigned char*)pBuffer) + bufferSize - 1;
 pTemp = (unsigned char*) pData;
 
 
 // do the padding
 for (int index = 0; index < size/3; index++)
 {
  unsigned char r = *(pTemp++);
  unsigned char g = *(pTemp++);
  unsigned char b = *(pTemp++);
 
  *(ptr--) = 0;
  *(ptr--) = b;
  *(ptr--) = g;
  *(ptr--) = r;
 }
/*
 for (int index = 0; index < size; index++)
 {
  *ptr = ((unsigned char *)pTemp)[index];
  ptr--;
  if (index % 3 == 2)
  {
   *ptr = 0;
   ptr--;
  }
 }
*/
 delete[] pData;
}
 
void ARFrameGrabber::BindFilter(int deviceId, IBaseFilter **pFilter)
{
 if (deviceId < 0)
  return;
 
    // enumerate all video capture devices
 CComPtr<ICreateDevEnum> pCreateDevEnum;
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
     IID_ICreateDevEnum, (void**)&pCreateDevEnum);
    if (hr != NOERROR)
 {
//  ErrMsg("Error Creating Device Enumerator");
  return;
 }
 
    CComPtr<IEnumMoniker> pEm;
    hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
        &pEm, 0);
    if (hr != NOERROR) 
 {
//  ErrMsg("Sorry, you have no video capture hardware");
  return;
    }
 
    pEm->Reset();
    ULONG cFetched;
    IMoniker *pM;
 int index = 0;
    while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK, index <= deviceId)
    {
  IPropertyBag *pBag;
  hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
  if(SUCCEEDED(hr)) 
  {
   VARIANT var;
   var.vt = VT_BSTR;
   hr = pBag->Read(L"FriendlyName", &var, NULL);
   if (hr == NOERROR) 
   {
    if (index == deviceId)
    {
     pM->BindToObject(0, 0, IID_IBaseFilter, (void**)pFilter);
    }
    SysFreeString(var.bstrVal);
   }
   pBag->Release();
  }
  pM->Release();
  index++;
    }
}
 
int ARFrameGrabber::GetWidth()
{
  return width;
}
 
int ARFrameGrabber::GetHeight()
{
  return height;
}
 
void ARFrameGrabber::EnumDevices(DeviceInfo *head)
{
 if (!head)
  return;
 
 DeviceInfo *ptr = head;
 int id = 0;
 
    // enumerate all video capture devices
 CComPtr<ICreateDevEnum> pCreateDevEnum;
//    ICreateDevEnum *pCreateDevEnum;
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
     IID_ICreateDevEnum, (void**)&pCreateDevEnum);
    if (hr != NOERROR)
 {
//  ErrMsg("Error Creating Device Enumerator");
  return;
 }
 
    CComPtr<IEnumMoniker> pEm;
    hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
        &pEm, 0);
    if (hr != NOERROR) 
 {
//  ErrMsg("Sorry, you have no video capture hardware");
  return;
    }
 
    pEm->Reset();
    ULONG cFetched;
    IMoniker *pM;
    while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)
    {
  IPropertyBag *pBag;
  hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
  if(SUCCEEDED(hr)) 
  {
   VARIANT var;
   var.vt = VT_BSTR;
   hr = pBag->Read(L"FriendlyName", &var, NULL);
   if (hr == NOERROR) 
   {
    char str[2048];
    
    if (ptr->deviceId != -1)
    {
     ptr->next = new DeviceInfo();
     ptr = ptr->next;
    }
 
 
    ptr->deviceId = id++;
    WideCharToMultiByte(CP_ACP,0,var.bstrVal, -1, str, 2048, NULL, NULL);
    
    ptr->friendlyName = str;
 
    SysFreeString(var.bstrVal);
   }
   pBag->Release();
  }
  pM->Release();
    }
}
 
 
void ARFrameGrabber::ReportError(char *msg)
{
 //MessageBox(NULL, msg, "ARFrameGrabber Error", MB_ICONSTOP);
}
//将输入crossbar变成PhysConn_Video_Composite
void ARFrameGrabber::SetCrossBar()
{
 IAMCrossbar *pXBar1 = NULL;
 ICaptureGraphBuilder2 *pBuilder = NULL;
 
 
 HRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
        CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, 
        (void **)&pBuilder);
 
 if (SUCCEEDED(hr))
    {
        hr = pBuilder->SetFiltergraph(pGraph);
    }
 
 
 hr = pBuilder->FindInterface(&LOOK_UPSTREAM_ONLY, NULL, 
  pDeviceFilter,IID_IAMCrossbar, (void**)&pXBar1);
 
 if (SUCCEEDED(hr)) 
 {
  
  long OutputPinCount;
  long InputPinCount;
  long PinIndexRelated;
  long PhysicalType;
  long inPort = 0;
  long outPort = 0;
 
  pXBar1->get_PinCounts(&OutputPinCount,&InputPinCount);
  for(int i =0;i<InputPinCount;i++)
  {
   pXBar1->get_CrossbarPinInfo(TRUE,i,&PinIndexRelated,&PhysicalType);
   if(PhysConn_Video_Composite==PhysicalType) 
   {
    inPort = i;
    break;
   }
  }
  for(int i =0;i<OutputPinCount;i++)
  {
   pXBar1->get_CrossbarPinInfo(FALSE,i,&PinIndexRelated,&PhysicalType);
   if(PhysConn_Video_VideoDecoder==PhysicalType) 
   {
    outPort = i;
    break;
   }
  }
  
  if(S_OK==pXBar1->CanRoute(outPort,inPort))
  {
   pXBar1->Route(outPort,inPort);
  }
  pXBar1->Release();  
 }
 pBuilder->Release();
}

结束

猜你喜欢

转载自blog.csdn.net/p312011150/article/details/82255107