*
This commit is contained in:
@@ -0,0 +1,225 @@
|
||||
#include "WebCamera.h"
|
||||
|
||||
|
||||
#include "../Utils.h"
|
||||
#include "../log/NLog.h"
|
||||
#include "../Com.h"
|
||||
|
||||
namespace LifeCore {
|
||||
class WinWebCameraDescription : public WebCameraDescription {
|
||||
public:
|
||||
friend class WebCamera;
|
||||
WinWebCameraDescription(IMFActivate* act, int id)
|
||||
: activate(act), deviceId(id)
|
||||
{
|
||||
if(activate != nullptr)
|
||||
activate->AddRef();
|
||||
}
|
||||
~WinWebCameraDescription() {
|
||||
SafeRelease(&activate);
|
||||
}
|
||||
std::wstring GetName() override{
|
||||
if(activate == nullptr)
|
||||
return std::wstring(L"");
|
||||
WCHAR *szFriendlyName = NULL;
|
||||
UINT32 cchName;
|
||||
auto hr = activate->GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, &szFriendlyName, &cchName);
|
||||
if(hr != S_OK)
|
||||
return std::wstring(L"");
|
||||
std::wstring result(szFriendlyName);
|
||||
CoTaskMemFree(szFriendlyName);
|
||||
return result;
|
||||
}
|
||||
int deviceId;
|
||||
protected:
|
||||
IMFActivate* activate;
|
||||
};
|
||||
struct ChooseDeviceParam {
|
||||
ChooseDeviceParam() : ppDevices(NULL), count(0) {}
|
||||
~ChooseDeviceParam() {
|
||||
for(DWORD i = 0; i < count; i++) {
|
||||
SafeRelease(&ppDevices[i]);
|
||||
}
|
||||
CoTaskMemFree(ppDevices);
|
||||
}
|
||||
|
||||
IMFActivate **ppDevices;
|
||||
UINT32 count;
|
||||
UINT32 selection;
|
||||
};
|
||||
class WinWebCamCallback : IMFCaptureEngineOnEventCallback {
|
||||
public:
|
||||
WinWebCamCallback(WebCamera* cam)
|
||||
: m_cRef(1), camera(cam), sleeping(false)
|
||||
{
|
||||
|
||||
}
|
||||
// IUnknown
|
||||
STDMETHODIMP QueryInterface(REFIID riid, void** ppv) {
|
||||
static const QITAB qit[] = {
|
||||
QITABENT(WinWebCamCallback, IMFCaptureEngineOnEventCallback), { 0 }
|
||||
};
|
||||
return QISearch(this, qit, riid, ppv);
|
||||
}
|
||||
STDMETHODIMP_(ULONG) AddRef() {
|
||||
return InterlockedIncrement(&m_cRef);
|
||||
}
|
||||
STDMETHODIMP_(ULONG) Release() {
|
||||
LONG cRef = InterlockedDecrement(&m_cRef);
|
||||
if(cRef == 0) {
|
||||
delete this;
|
||||
}
|
||||
return cRef;
|
||||
}
|
||||
|
||||
// IMFCaptureEngineOnEventCallback
|
||||
STDMETHODIMP OnEvent(_In_ IMFMediaEvent* pEvent) {
|
||||
if(sleeping && camera != nullptr) {
|
||||
// We're about to fall asleep, that means we've just asked the CE to stop the preview
|
||||
// and record. We need to handle it here since our message pump may be gone.
|
||||
GUID guidType;
|
||||
HRESULT hrStatus;
|
||||
HRESULT hr = pEvent->GetStatus(&hrStatus);
|
||||
if(FAILED(hr)) {
|
||||
hrStatus = hr;
|
||||
}
|
||||
|
||||
hr = pEvent->GetExtendedType(&guidType);
|
||||
if(SUCCEEDED(hr)) {
|
||||
if(guidType == MF_CAPTURE_ENGINE_PREVIEW_STOPPED) {
|
||||
LogInfo() << "Preview stopped";
|
||||
//m_pManager->OnPreviewStopped(hrStatus);
|
||||
// SetEvent(m_pManager->m_hEvent);
|
||||
} else if(guidType == MF_CAPTURE_ENGINE_RECORD_STOPPED) {
|
||||
LogInfo() << "Engine stopped";
|
||||
//m_pManager->OnRecordStopped(hrStatus);
|
||||
//SetEvent(m_pManager->m_hEvent);
|
||||
} else {
|
||||
// This is an event we don't know about, we don't really care and there's
|
||||
// no clean way to report the error so just set the event and fall through.
|
||||
//SetEvent(m_pManager->m_hEvent);
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
} else {
|
||||
LogInfo() << "Capture event";
|
||||
pEvent->AddRef(); // The application will release the pointer when it handles the message.
|
||||
camera->OnCaptureEvent(pEvent);
|
||||
//PostMessage(m_hwnd, WM_APP_CAPTURE_EVENT, (WPARAM)pEvent, 0L);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
protected:
|
||||
bool sleeping;
|
||||
long m_cRef;
|
||||
WebCamera* camera;
|
||||
};
|
||||
|
||||
WebCamera::WebCamera(webcam_desc_ptr desc)
|
||||
: description(desc), FrameNumber(0), pSource(nullptr), grabber(nullptr)
|
||||
{
|
||||
callback = new WinWebCamCallback(this);
|
||||
}
|
||||
void WebCamera::OnCaptureEvent(IMFMediaEvent* pEvent) {
|
||||
HRESULT hrStatus;
|
||||
GUID eventType;
|
||||
pEvent->GetStatus(&hrStatus);
|
||||
pEvent->GetExtendedType(&eventType);
|
||||
|
||||
}
|
||||
|
||||
RawBuffer<uint8>* WebCamera::GetImage() {
|
||||
return grabber->GetImage();
|
||||
}
|
||||
|
||||
void WebCamera::OnImageGrabbed(WinMfImageGrabber* grabber, RawBuffer<uint8>* image) {
|
||||
FrameNumber++;
|
||||
Event_ImageCapture.Call(this, image);
|
||||
}
|
||||
bool WebCamera::Open() {
|
||||
IMFActivate* pActivate = dynamic_cast<WinWebCameraDescription*>(description.get())->activate;
|
||||
|
||||
HRESULT hr = pActivate->ActivateObject(__uuidof(IMFMediaSource), (void**)&pSource);
|
||||
if(FAILED(hr)) {
|
||||
LogInfo() << "Failed to activate camera!";
|
||||
return false;
|
||||
}
|
||||
|
||||
grabber = new WinMfImageGrabber(this);
|
||||
if(FAILED(grabber->initImageGrabber(pSource, MFVideoFormat_RGB24)) || FAILED(grabber->startGrabbing())) {
|
||||
LogInfo() << "Failed to init camera grabber";
|
||||
pActivate->ShutdownObject();
|
||||
FINAL_RELEASE(grabber);
|
||||
FINAL_RELEASE(pSource);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void WebCamera::Close() {
|
||||
IMFActivate* pActivate = dynamic_cast<WinWebCameraDescription*>(description.get())->activate;
|
||||
if(grabber != nullptr)
|
||||
grabber->stopGrabbing();
|
||||
FINAL_RELEASE(grabber);
|
||||
FINAL_RELEASE(pSource);
|
||||
|
||||
pActivate->ShutdownObject();
|
||||
|
||||
pActivate->AddRef();
|
||||
auto val = pActivate->Release();
|
||||
LogInfo() << "Initial 2 pActivate refCount = " << val;
|
||||
FrameNumber = 0;
|
||||
}
|
||||
int2 WebCamera::GetSize() {
|
||||
return int2();
|
||||
}
|
||||
int32 WebCamera::GetBpp() {
|
||||
return -1;
|
||||
}
|
||||
bool WebCamera::Read(int2 size, uint8* buffer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void WebCamera::Update() {
|
||||
grabber->processGrabbing();
|
||||
}
|
||||
std::vector<webcam_desc_ptr> WebCamera::GetConnectedDevices() {
|
||||
std::vector<webcam_desc_ptr> result;
|
||||
|
||||
IMFAttributes *pAttributes = NULL;
|
||||
ChooseDeviceParam param;
|
||||
|
||||
HRESULT hr = MFCreateAttributes(&pAttributes, 1);
|
||||
if(FAILED(hr)) {
|
||||
printf("Failed\n");
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
// Ask for source type = video capture devices
|
||||
hr = pAttributes->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
|
||||
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID);
|
||||
if(FAILED(hr)) {
|
||||
printf("Failed\n");
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
// Enumerate devices.
|
||||
hr = MFEnumDeviceSources(pAttributes, ¶m.ppDevices, ¶m.count);
|
||||
if(FAILED(hr)) {
|
||||
printf("Failed\n");
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
for(UINT32 i = 0; i < param.count; ++i) {
|
||||
result.push_back(webcam_desc_ptr(new WinWebCameraDescription(param.ppDevices[i], i)));
|
||||
}
|
||||
|
||||
Exit:
|
||||
if(NULL != pAttributes) {
|
||||
pAttributes->Release();
|
||||
pAttributes = NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user