赞
踩
现在手头上有一个项目就是需要优化采集方案。
我们这边之前使用的是作者Shiqi Yu写的开源代码,底层是基于DShow做的封装。但使用后发现采集到的视频流在进行回显时有点模糊,特别是文字部分。
现在通过万能的网络找到了三种替换方案:WebRTC 接、MediaFoundation、VideoInput。
1、WebRTC:现被Google整编,但由于需要翻墙才能下载和更新,所以没有使用。
2、MediaFoundation:微软基于DShow上做的优化框架,回显也明显清晰流畅了许多,但是继承了微软的封装特性,所以想嵌入自己的逻辑,相对于比较麻烦,所以放弃。
获取视频采集设备。
- HRESULT hr = S_OK;
- IMFAttributes *pAttributes;
- if (SUCCEEDED(hr))
- {
- hr = MFStartup(MF_VERSION); //这是必须的,不然无法绑定回调资源
- }
-
- if (SUCCEEDED(hr))
- {
- hr = MFCreateAttributes(&pAttributes, 1);
- }
-
- if (SUCCEEDED(hr))
- {
- hr = m_pAttributes->SetGUID(
- MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
- MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
- );
- }
-
-
- if (SUCCEEDED(hr))
- {
- hr = MFEnumDeviceSources(m_pAttributes, &m_param.ppDevices, &m_param.count);
- }
-
- SafeRelease(&pAttributes);

打开一个采集设备
- HRESULT hr = S_OK;
- IMFMediaSource *pSource = NULL;
- EnterCriticalSection(&m_critsec);
-
- IMFActivate* pActivate = m_param.ppDevices[nCamID];
- pActivate->AddRef();
-
- // Create the media source for the device.
- if (SUCCEEDED(hr))
- {
- hr = pActivate->ActivateObject(__uuidof(IMFMediaSource),
- (void**)&pSource
- );
- }
-
- // Get the symbolic link. This is needed to handle device-
- // loss notifications. (See CheckDeviceLost.)
-
- if (SUCCEEDED(hr))
- {
- hr = pActivate->GetAllocatedString(
- MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK,
- &m_pwszSymbolicLink,
- &m_cchSymbolicLink
- );
- }
-
- WCHAR *szFriendlyName = NULL;
- if (SUCCEEDED(hr))
- {
- hr = pActivate->GetAllocatedString(
- MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME,
- &szFriendlyName,
- NULL
- );
- }
-
- UINT32 unMaxSize = 0;
- if (SUCCEEDED(hr))
- {
- hr = pActivate->GetUINT32(
- MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_MAX_BUFFERS,
- &unMaxSize
- );
- }
-
- // When the method completes, MFPlay will call OnMediaPlayerEvent
- // with the MFP_EVENT_TYPE_MEDIAITEM_CREATED event.
- if (SUCCEEDED(hr))
- {
- hr = CreateSourceReaderAsync(pSource);
- }
-
-
-
- if (SUCCEEDED(hr))
- {
- m_pSource = pSource;
- m_pSource->AddRef();
- }
-
-
- if (FAILED(hr))
- {
- CloseCamera();
- }
- else
- {
- m_ob = ob;
- Start();
- }
-
- SafeRelease(&pSource);
- SafeRelease(&pActivate);
- LeaveCriticalSection(&m_critsec);

- HRESULT hr = S_OK;
- IMFAttributes *pAttributes = NULL;
- IMFMediaType * nativeType = NULL;
-
-
- hr = MFCreateAttributes(&pAttributes, 2);
-
-
- if (SUCCEEDED(hr))
- {
- hr = pAttributes->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, this);
- }
-
-
- if (SUCCEEDED(hr))
- {
- hr = MFCreateSourceReaderFromMediaSource(pSource,pAttributes,&m_pSourceReader);
- }
-
-
- if (SUCCEEDED(hr))
- {
- hr = m_pSourceReader->SetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM,NULL,nativeType);
- }
- SafeRelease(&nativeType);
- SafeRelease(&pAttributes);

视频流读取
- if (FAILED(hrStatus))
- {
- hr = hrStatus;
- LeaveCriticalSection(&m_critsec);
- return hr;
- }
-
-
- if(pSample )
- {
- DWORD maxLength,currentLength;
- BYTE* pBuffer = NULL;
- BYTE * pBitmapData = NULL;
- IMFMediaBuffer* pMBuffer = NULL;
- hr = pSample->GetBufferByIndex(0, &pMBuffer);
-
-
- //hr = pSample->ConvertToContiguousBuffer(&pMBuffer);
- if(SUCCEEDED(hr))
- {
- hr = pMBuffer->Lock(&pBuffer,&maxLength,¤tLength);
- }
-
-
- if(SUCCEEDED(hr))
- {
- hr = pMBuffer->Unlock();
-
-
- if(currentLength > 0)
- m_ob->onRGB((const char*)pBuffer,currentLength);
-
-
- SafeRelease(&pMBuffer);
- }
- }

3、VideoInput 被OpenCV收入的一个非常实用的开源视频采集库,现在我就使用的这个库。
打开一个采集设备
- if(pCamara)
- {
- delete pCamara;
- pCamara = NULL;
- }
-
- //videoInput::setComMultiThreaded(true); //如果项目中使用到不支持多线程的COM库,请不要执行此段代码
- pCamara = (void*)(new videoInput());
- ((videoInput*)pCamara)->setIdealFramerate(nCamID,25); //设置当前采集帧率默认为25帧,实际可能大于25帧。
- bool bRs = ((videoInput*)pCamara)->setupDevice(nCamID,nWidth,nHeight);
- if(bRs)
- {
- m_ob = ob;
- nDeviceId = nCamID;
- ((videoInput*)pCamara)->setUseCallback(true); //设置当前采集使用回调的方式获取数据
- hThread = (void*)CreateThread(NULL,0,OnCaptureFrame,this,0,0);
- m_bIsRun = true;
- }

- CCameraVI* pThis = (CCameraVI*)lpParam;
- while(pThis->isRun())
- {
- if(pThis->isFrameNew())
- {
- const char* pData = (const char*)pThis->GetFrame();
- pThis->getObserver()->onRGB(pData,pThis->GetWidth()*pThis->GetHeight()*3);
- }
- else
- {
- Sleep(1);
- }
- }
- return 0;
整个采集逻辑就是这么简单的两段代码实现。
获取设备数量
videoInput::listDevices();
- videoInput::listDevices();
- strncpy(sName,videoInput::getDeviceName(nCamID),nBufferSize);
- if (pCamara )
- {
- return ((videoInput*)pCamara)->getPixels(nDeviceId,false);
- }
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。