*
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#ifndef WebCamera_h__
|
||||
#define WebCamera_h__
|
||||
|
||||
#include "../ICamera.h"
|
||||
#include "../IImage.h"
|
||||
#include <mfapi.h>
|
||||
#include <mfidl.h>
|
||||
#include <mferror.h>
|
||||
#include <mfcaptureengine.h>
|
||||
#include "WinMfImageGrabber.h"
|
||||
#include <shlwapi.h>
|
||||
#pragma comment(lib, "mf.lib")
|
||||
#pragma comment(lib, "mfplat.lib")
|
||||
#pragma comment(lib, "mfuuid.lib")
|
||||
#pragma comment(lib, "shlwapi.lib")
|
||||
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "../Delegate.h"
|
||||
|
||||
namespace LifeCore {
|
||||
class WebCameraDescription {
|
||||
public:
|
||||
virtual ~WebCameraDescription() {}
|
||||
virtual std::wstring GetName() = 0;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<WebCameraDescription> webcam_desc_ptr;
|
||||
|
||||
class WebCamera : public ICamera, public IImage
|
||||
{
|
||||
public:
|
||||
Delegate<WebCamera*, RawBuffer<uint8>*> Event_ImageCapture;
|
||||
WebCamera(webcam_desc_ptr desc);
|
||||
int2 GetSize();
|
||||
int32 GetBpp();
|
||||
bool Read(int2 size, uint8* buffer);
|
||||
static std::vector<webcam_desc_ptr> GetConnectedDevices();
|
||||
bool Open();
|
||||
void Close();
|
||||
void OnImageGrabbed(WinMfImageGrabber* grabber, RawBuffer<uint8>* image);
|
||||
void OnCaptureEvent(IMFMediaEvent* pEvent);
|
||||
void Update();
|
||||
RawBuffer<uint8>* GetImage();
|
||||
int FrameNumber;
|
||||
private:
|
||||
webcam_desc_ptr description;
|
||||
WinMfImageGrabber* grabber;
|
||||
IMFMediaSource *pSource;
|
||||
void* callback;
|
||||
};
|
||||
}
|
||||
#endif // WebCamera_h__
|
||||
@@ -0,0 +1,461 @@
|
||||
#include "WinMfFormatReader.h"
|
||||
#include "Strsafe.h"
|
||||
#include <Mfapi.h>
|
||||
#include <mfobjects.h>
|
||||
|
||||
namespace LifeCore {
|
||||
LPCWSTR GetGUIDNameConstNew(const GUID& guid);
|
||||
HRESULT GetGUIDNameNew(const GUID& guid, WCHAR **ppwsz);
|
||||
|
||||
HRESULT LogAttributeValueByIndexNew(IMFAttributes *pAttr, DWORD index);
|
||||
HRESULT SpecialCaseAttributeValueNew(GUID guid, const PROPVARIANT& var, WinMfMediaType &out);
|
||||
|
||||
unsigned int *GetParametr(GUID guid, WinMfMediaType &out) {
|
||||
if(guid == MF_MT_YUV_MATRIX)
|
||||
return &(out.MF_MT_YUV_MATRIX);
|
||||
|
||||
if(guid == MF_MT_VIDEO_LIGHTING)
|
||||
return &(out.MF_MT_VIDEO_LIGHTING);
|
||||
|
||||
if(guid == MF_MT_DEFAULT_STRIDE)
|
||||
return &(out.MF_MT_DEFAULT_STRIDE);
|
||||
|
||||
if(guid == MF_MT_VIDEO_CHROMA_SITING)
|
||||
return &(out.MF_MT_VIDEO_CHROMA_SITING);
|
||||
|
||||
if(guid == MF_MT_VIDEO_NOMINAL_RANGE)
|
||||
return &(out.MF_MT_VIDEO_NOMINAL_RANGE);
|
||||
|
||||
if(guid == MF_MT_ALL_SAMPLES_INDEPENDENT)
|
||||
return &(out.MF_MT_ALL_SAMPLES_INDEPENDENT);
|
||||
|
||||
if(guid == MF_MT_FIXED_SIZE_SAMPLES)
|
||||
return &(out.MF_MT_FIXED_SIZE_SAMPLES);
|
||||
|
||||
if(guid == MF_MT_SAMPLE_SIZE)
|
||||
return &(out.MF_MT_SAMPLE_SIZE);
|
||||
|
||||
if(guid == MF_MT_VIDEO_PRIMARIES)
|
||||
return &(out.MF_MT_VIDEO_PRIMARIES);
|
||||
|
||||
if(guid == MF_MT_INTERLACE_MODE)
|
||||
return &(out.MF_MT_INTERLACE_MODE);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HRESULT LogAttributeValueByIndexNew(IMFAttributes *pAttr, DWORD index, WinMfMediaType &out) {
|
||||
WCHAR *pGuidName = NULL;
|
||||
WCHAR *pGuidValName = NULL;
|
||||
|
||||
GUID guid = { 0 };
|
||||
|
||||
PROPVARIANT var;
|
||||
PropVariantInit(&var);
|
||||
|
||||
HRESULT hr = pAttr->GetItemByIndex(index, &guid, &var);
|
||||
|
||||
if(FAILED(hr)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
hr = GetGUIDNameNew(guid, &pGuidName);
|
||||
|
||||
if(FAILED(hr)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
hr = SpecialCaseAttributeValueNew(guid, var, out);
|
||||
|
||||
unsigned int *p;
|
||||
|
||||
if(FAILED(hr)) {
|
||||
goto done;
|
||||
}
|
||||
if(hr == S_FALSE) {
|
||||
switch(var.vt) {
|
||||
case VT_UI4:
|
||||
|
||||
p = GetParametr(guid, out);
|
||||
|
||||
if(p) {
|
||||
*p = var.ulVal;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case VT_UI8:
|
||||
|
||||
break;
|
||||
|
||||
case VT_R8:
|
||||
|
||||
break;
|
||||
|
||||
case VT_CLSID:
|
||||
if(guid == MF_MT_AM_FORMAT_TYPE) {
|
||||
hr = GetGUIDNameNew(*var.puuid, &pGuidValName);
|
||||
|
||||
if(SUCCEEDED(hr)) {
|
||||
out.MF_MT_AM_FORMAT_TYPE = MF_MT_AM_FORMAT_TYPE;
|
||||
|
||||
out.pMF_MT_AM_FORMAT_TYPEName = pGuidValName;
|
||||
|
||||
pGuidValName = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if(guid == MF_MT_MAJOR_TYPE) {
|
||||
hr = GetGUIDNameNew(*var.puuid, &pGuidValName);
|
||||
|
||||
if(SUCCEEDED(hr)) {
|
||||
out.MF_MT_MAJOR_TYPE = MF_MT_MAJOR_TYPE;
|
||||
|
||||
out.pMF_MT_MAJOR_TYPEName = pGuidValName;
|
||||
|
||||
pGuidValName = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if(guid == MF_MT_SUBTYPE) {
|
||||
hr = GetGUIDNameNew(*var.puuid, &pGuidValName);
|
||||
|
||||
if(SUCCEEDED(hr)) {
|
||||
out.MF_MT_SUBTYPE = MF_MT_SUBTYPE;
|
||||
|
||||
out.pMF_MT_SUBTYPEName = pGuidValName;
|
||||
|
||||
pGuidValName = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case VT_LPWSTR:
|
||||
|
||||
break;
|
||||
|
||||
case VT_VECTOR | VT_UI1:
|
||||
|
||||
break;
|
||||
|
||||
case VT_UNKNOWN:
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
CoTaskMemFree(pGuidName);
|
||||
CoTaskMemFree(pGuidValName);
|
||||
PropVariantClear(&var);
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT GetGUIDNameNew(const GUID& guid, WCHAR **ppwsz) {
|
||||
HRESULT hr = S_OK;
|
||||
WCHAR *pName = NULL;
|
||||
|
||||
LPCWSTR pcwsz = GetGUIDNameConstNew(guid);
|
||||
if(pcwsz) {
|
||||
size_t cchLength = 0;
|
||||
|
||||
hr = StringCchLengthW(pcwsz, STRSAFE_MAX_CCH, &cchLength);
|
||||
if(FAILED(hr)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
pName = (WCHAR*)CoTaskMemAlloc((cchLength + 1) * sizeof(WCHAR));
|
||||
|
||||
if(pName == NULL) {
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
hr = StringCchCopyW(pName, cchLength + 1, pcwsz);
|
||||
if(FAILED(hr)) {
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
hr = StringFromCLSID(guid, &pName);
|
||||
}
|
||||
|
||||
done:
|
||||
if(FAILED(hr)) {
|
||||
*ppwsz = NULL;
|
||||
CoTaskMemFree(pName);
|
||||
} else {
|
||||
*ppwsz = pName;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
void LogUINT32AsUINT64New(const PROPVARIANT& var, UINT32 &uHigh, UINT32 &uLow) {
|
||||
Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &uHigh, &uLow);
|
||||
|
||||
}
|
||||
|
||||
float OffsetToFloatNew(const MFOffset& offset) {
|
||||
return offset.value + (static_cast<float>(offset.fract) / 65536.0f);
|
||||
}
|
||||
|
||||
HRESULT LogVideoAreaNew(const PROPVARIANT& var) {
|
||||
if(var.caub.cElems < sizeof(MFVideoArea)) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
MFVideoArea *pArea = (MFVideoArea*)var.caub.pElems;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT SpecialCaseAttributeValueNew(GUID guid, const PROPVARIANT& var, WinMfMediaType &out) {
|
||||
if(guid == MF_MT_FRAME_SIZE) {
|
||||
UINT32 uHigh = 0, uLow = 0;
|
||||
|
||||
LogUINT32AsUINT64New(var, uHigh, uLow);
|
||||
|
||||
out.width = uHigh;
|
||||
|
||||
out.height = uLow;
|
||||
|
||||
out.MF_MT_FRAME_SIZE = out.width * out.height;
|
||||
} else
|
||||
if(guid == MF_MT_FRAME_RATE) {
|
||||
UINT32 uHigh = 0, uLow = 0;
|
||||
|
||||
LogUINT32AsUINT64New(var, uHigh, uLow);
|
||||
|
||||
out.MF_MT_FRAME_RATE = uHigh;
|
||||
|
||||
out.MF_MT_FRAME_RATE_low = uLow;
|
||||
} else
|
||||
if(guid == MF_MT_FRAME_RATE_RANGE_MAX) {
|
||||
UINT32 uHigh = 0, uLow = 0;
|
||||
|
||||
LogUINT32AsUINT64New(var, uHigh, uLow);
|
||||
|
||||
out.MF_MT_FRAME_RATE_RANGE_MAX = uHigh;
|
||||
|
||||
out.MF_MT_FRAME_RATE_RANGE_MAX_low = uLow;
|
||||
} else
|
||||
if(guid == MF_MT_FRAME_RATE_RANGE_MIN) {
|
||||
UINT32 uHigh = 0, uLow = 0;
|
||||
|
||||
LogUINT32AsUINT64New(var, uHigh, uLow);
|
||||
|
||||
out.MF_MT_FRAME_RATE_RANGE_MIN = uHigh;
|
||||
|
||||
out.MF_MT_FRAME_RATE_RANGE_MIN_low = uLow;
|
||||
} else
|
||||
if(guid == MF_MT_PIXEL_ASPECT_RATIO) {
|
||||
UINT32 uHigh = 0, uLow = 0;
|
||||
|
||||
LogUINT32AsUINT64New(var, uHigh, uLow);
|
||||
|
||||
out.MF_MT_PIXEL_ASPECT_RATIO = uHigh;
|
||||
|
||||
out.MF_MT_PIXEL_ASPECT_RATIO_low = uLow;
|
||||
} else {
|
||||
return S_FALSE;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifndef IF_EQUAL_RETURN
|
||||
#define IF_EQUAL_RETURN(param, val) if(val == param) return L#val
|
||||
#endif
|
||||
|
||||
LPCWSTR GetGUIDNameConstNew(const GUID& guid) {
|
||||
IF_EQUAL_RETURN(guid, MF_MT_MAJOR_TYPE);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_MAJOR_TYPE);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_SUBTYPE);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_ALL_SAMPLES_INDEPENDENT);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_FIXED_SIZE_SAMPLES);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_COMPRESSED);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_SAMPLE_SIZE);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_WRAPPED_TYPE);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_AUDIO_NUM_CHANNELS);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_AUDIO_SAMPLES_PER_SECOND);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_AUDIO_AVG_BYTES_PER_SECOND);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_AUDIO_BLOCK_ALIGNMENT);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_AUDIO_BITS_PER_SAMPLE);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_AUDIO_VALID_BITS_PER_SAMPLE);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_AUDIO_SAMPLES_PER_BLOCK);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_AUDIO_CHANNEL_MASK);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_AUDIO_FOLDDOWN_MATRIX);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_PEAKREF);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_PEAKTARGET);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_AVGREF);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_AVGTARGET);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_AUDIO_PREFER_WAVEFORMATEX);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_AAC_PAYLOAD_TYPE);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_FRAME_SIZE);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_FRAME_RATE);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_FRAME_RATE_RANGE_MAX);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_FRAME_RATE_RANGE_MIN);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_PIXEL_ASPECT_RATIO);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_DRM_FLAGS);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_PAD_CONTROL_FLAGS);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_SOURCE_CONTENT_HINT);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_VIDEO_CHROMA_SITING);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_INTERLACE_MODE);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_TRANSFER_FUNCTION);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_VIDEO_PRIMARIES);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_CUSTOM_VIDEO_PRIMARIES);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_YUV_MATRIX);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_VIDEO_LIGHTING);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_VIDEO_NOMINAL_RANGE);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_GEOMETRIC_APERTURE);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_MINIMUM_DISPLAY_APERTURE);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_PAN_SCAN_APERTURE);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_PAN_SCAN_ENABLED);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_AVG_BITRATE);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_AVG_BIT_ERROR_RATE);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_MAX_KEYFRAME_SPACING);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_DEFAULT_STRIDE);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_PALETTE);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_USER_DATA);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_AM_FORMAT_TYPE);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_MPEG_START_TIME_CODE);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_MPEG2_PROFILE);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_MPEG2_LEVEL);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_MPEG2_FLAGS);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_MPEG_SEQUENCE_HEADER);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_SRC_PACK_0);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_CTRL_PACK_0);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_SRC_PACK_1);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_CTRL_PACK_1);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_DV_VAUX_SRC_PACK);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_DV_VAUX_CTRL_PACK);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_ARBITRARY_HEADER);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_ARBITRARY_FORMAT);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_IMAGE_LOSS_TOLERANT);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_MPEG4_SAMPLE_DESCRIPTION);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_MPEG4_CURRENT_SAMPLE_ENTRY);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_ORIGINAL_4CC);
|
||||
IF_EQUAL_RETURN(guid, MF_MT_ORIGINAL_WAVE_FORMAT_TAG);
|
||||
|
||||
// Media types
|
||||
|
||||
IF_EQUAL_RETURN(guid, MFMediaType_Audio);
|
||||
IF_EQUAL_RETURN(guid, MFMediaType_Video);
|
||||
IF_EQUAL_RETURN(guid, MFMediaType_Protected);
|
||||
IF_EQUAL_RETURN(guid, MFMediaType_SAMI);
|
||||
IF_EQUAL_RETURN(guid, MFMediaType_Script);
|
||||
IF_EQUAL_RETURN(guid, MFMediaType_Image);
|
||||
IF_EQUAL_RETURN(guid, MFMediaType_HTML);
|
||||
IF_EQUAL_RETURN(guid, MFMediaType_Binary);
|
||||
IF_EQUAL_RETURN(guid, MFMediaType_FileTransfer);
|
||||
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_AI44); // FCC('AI44')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_ARGB32); // D3DFMT_A8R8G8B8
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_AYUV); // FCC('AYUV')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_DV25); // FCC('dv25')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_DV50); // FCC('dv50')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_DVH1); // FCC('dvh1')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_DVSD); // FCC('dvsd')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_DVSL); // FCC('dvsl')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_H264); // FCC('H264')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_I420); // FCC('I420')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_IYUV); // FCC('IYUV')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_M4S2); // FCC('M4S2')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_MJPG);
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_MP43); // FCC('MP43')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_MP4S); // FCC('MP4S')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_MP4V); // FCC('MP4V')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_MPG1); // FCC('MPG1')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_MSS1); // FCC('MSS1')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_MSS2); // FCC('MSS2')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_NV11); // FCC('NV11')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_NV12); // FCC('NV12')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_P010); // FCC('P010')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_P016); // FCC('P016')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_P210); // FCC('P210')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_P216); // FCC('P216')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_RGB24); // D3DFMT_R8G8B8
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_RGB32); // D3DFMT_X8R8G8B8
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_RGB555); // D3DFMT_X1R5G5B5
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_RGB565); // D3DFMT_R5G6B5
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_RGB8);
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_UYVY); // FCC('UYVY')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_v210); // FCC('v210')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_v410); // FCC('v410')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_WMV1); // FCC('WMV1')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_WMV2); // FCC('WMV2')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_WMV3); // FCC('WMV3')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_WVC1); // FCC('WVC1')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_Y210); // FCC('Y210')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_Y216); // FCC('Y216')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_Y410); // FCC('Y410')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_Y416); // FCC('Y416')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_Y41P);
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_Y41T);
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_YUY2); // FCC('YUY2')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_YV12); // FCC('YV12')
|
||||
IF_EQUAL_RETURN(guid, MFVideoFormat_YVYU);
|
||||
|
||||
IF_EQUAL_RETURN(guid, MFAudioFormat_PCM); // WAVE_FORMAT_PCM
|
||||
IF_EQUAL_RETURN(guid, MFAudioFormat_Float); // WAVE_FORMAT_IEEE_FLOAT
|
||||
IF_EQUAL_RETURN(guid, MFAudioFormat_DTS); // WAVE_FORMAT_DTS
|
||||
IF_EQUAL_RETURN(guid, MFAudioFormat_Dolby_AC3_SPDIF); // WAVE_FORMAT_DOLBY_AC3_SPDIF
|
||||
IF_EQUAL_RETURN(guid, MFAudioFormat_DRM); // WAVE_FORMAT_DRM
|
||||
IF_EQUAL_RETURN(guid, MFAudioFormat_WMAudioV8); // WAVE_FORMAT_WMAUDIO2
|
||||
IF_EQUAL_RETURN(guid, MFAudioFormat_WMAudioV9); // WAVE_FORMAT_WMAUDIO3
|
||||
IF_EQUAL_RETURN(guid, MFAudioFormat_WMAudio_Lossless); // WAVE_FORMAT_WMAUDIO_LOSSLESS
|
||||
IF_EQUAL_RETURN(guid, MFAudioFormat_WMASPDIF); // WAVE_FORMAT_WMASPDIF
|
||||
IF_EQUAL_RETURN(guid, MFAudioFormat_MSP1); // WAVE_FORMAT_WMAVOICE9
|
||||
IF_EQUAL_RETURN(guid, MFAudioFormat_MP3); // WAVE_FORMAT_MPEGLAYER3
|
||||
IF_EQUAL_RETURN(guid, MFAudioFormat_MPEG); // WAVE_FORMAT_MPEG
|
||||
IF_EQUAL_RETURN(guid, MFAudioFormat_AAC); // WAVE_FORMAT_MPEG_HEAAC
|
||||
IF_EQUAL_RETURN(guid, MFAudioFormat_ADTS); // WAVE_FORMAT_MPEG_ADTS_AAC
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
WinMfFormatReader::WinMfFormatReader(void) {}
|
||||
|
||||
WinMfMediaType WinMfFormatReader::Read(IMFMediaType *pType) {
|
||||
UINT32 count = 0;
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
WinMfMediaType out;
|
||||
|
||||
hr = pType->LockStore();
|
||||
|
||||
if(FAILED(hr)) {
|
||||
return out;
|
||||
}
|
||||
|
||||
hr = pType->GetCount(&count);
|
||||
|
||||
if(FAILED(hr)) {
|
||||
return out;
|
||||
}
|
||||
|
||||
for(UINT32 i = 0; i < count; i++) {
|
||||
hr = LogAttributeValueByIndexNew(pType, i, out);
|
||||
|
||||
if(FAILED(hr)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
hr = pType->UnlockStore();
|
||||
|
||||
if(FAILED(hr)) {
|
||||
return out;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
WinMfFormatReader::~WinMfFormatReader(void) {}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef WinMfFormatReader_h__
|
||||
#define WinMfFormatReader_h__
|
||||
|
||||
#include <guiddef.h>
|
||||
#include "WinMfMediaType.h"
|
||||
struct IMFMediaType;
|
||||
|
||||
namespace LifeCore {
|
||||
|
||||
|
||||
|
||||
/// Class for parsing info from IMFMediaType into the local MediaType
|
||||
class WinMfFormatReader {
|
||||
public:
|
||||
static WinMfMediaType Read(IMFMediaType *pType);
|
||||
~WinMfFormatReader(void);
|
||||
private:
|
||||
WinMfFormatReader(void);
|
||||
};
|
||||
}
|
||||
#endif // WinMfFormatReader_h__
|
||||
@@ -0,0 +1,342 @@
|
||||
#include "WinMfImageGrabber.h"
|
||||
#include <mfapi.h>
|
||||
#include "../log/NLog.h"
|
||||
#include "../Utils.h"
|
||||
#include "WinMfFormatReader.h"
|
||||
#include "WinMfMediaType.h"
|
||||
#include <shlwapi.h>
|
||||
#include "WebCamera.h"
|
||||
#include "../Com.h"
|
||||
|
||||
namespace LifeCore {
|
||||
WinMfImageGrabber::WinMfImageGrabber(WebCamera* cam)
|
||||
: m_cRef(1), ig_pSession(nullptr), camera(cam)
|
||||
{
|
||||
|
||||
}
|
||||
WinMfImageGrabber::~WinMfImageGrabber() {
|
||||
LogInfo() << "~WinMfImageGrabber ";
|
||||
/*if(ig_pSession) {
|
||||
LogInfo() << "~WinMfImageGrabber shutdown session";
|
||||
ig_pSession->Shutdown();
|
||||
}*/
|
||||
}
|
||||
HRESULT WinMfImageGrabber::initImageGrabber(IMFMediaSource *pSource, GUID VideoFormat) {
|
||||
IMFActivate *pSinkActivate = NULL;/**/
|
||||
IMFMediaType *pType = NULL;/**/
|
||||
IMFPresentationDescriptor *pPD = NULL;/**/
|
||||
IMFStreamDescriptor *pSD = NULL;/**/
|
||||
IMFMediaTypeHandler *pHandler = NULL;/**/
|
||||
IMFMediaType *pCurrentType = NULL;/**/
|
||||
WinMfMediaType MT;
|
||||
auto hr = pSource->CreatePresentationDescriptor(&pPD);
|
||||
if(FAILED(hr)) {
|
||||
LogError() << "Failed to create presentation descriptor!";
|
||||
goto err;
|
||||
}
|
||||
|
||||
BOOL fSelected;
|
||||
hr = pPD->GetStreamDescriptorByIndex(0, &fSelected, &pSD);
|
||||
if(FAILED(hr)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
hr = pSD->GetMediaTypeHandler(&pHandler);
|
||||
if(FAILED(hr)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
DWORD cTypes = 0;
|
||||
hr = pHandler->GetMediaTypeCount(&cTypes);
|
||||
if(FAILED(hr)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if(cTypes > 0) {
|
||||
hr = pHandler->GetCurrentMediaType(&pCurrentType);
|
||||
|
||||
if(FAILED(hr)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
MT = WinMfFormatReader::Read(pCurrentType);
|
||||
}
|
||||
|
||||
err:
|
||||
SafeRelease(&pPD);
|
||||
SafeRelease(&pSD);
|
||||
SafeRelease(&pHandler);
|
||||
SafeRelease(&pCurrentType);
|
||||
|
||||
unsigned int sizeRawImage = 0;
|
||||
if(VideoFormat == MFVideoFormat_RGB24) {
|
||||
sizeRawImage = MT.MF_MT_FRAME_SIZE * 3;
|
||||
} else if(VideoFormat == MFVideoFormat_RGB32) {
|
||||
sizeRawImage = MT.MF_MT_FRAME_SIZE * 4;
|
||||
}
|
||||
|
||||
buffer_first = new RawBuffer<uint8>(sizeRawImage, MT);
|
||||
buffer_second = new RawBuffer<uint8>(sizeRawImage, MT);
|
||||
buffer_active = buffer_second;
|
||||
|
||||
hr = MFCreateMediaType(&pType);
|
||||
hr = pType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
|
||||
hr = pType->SetGUID(MF_MT_SUBTYPE, VideoFormat);
|
||||
|
||||
// Create the sample grabber sink.
|
||||
hr = MFCreateSampleGrabberSinkActivate(pType, this, &pSinkActivate);
|
||||
|
||||
// To run as fast as possible, set this attribute (requires Windows 7):
|
||||
hr = pSinkActivate->SetUINT32(MF_SAMPLEGRABBERSINK_IGNORE_CLOCK, TRUE);
|
||||
|
||||
// Create the Media Session.
|
||||
|
||||
hr = MFCreateMediaSession(NULL, &ig_pSession);
|
||||
|
||||
// Create the topology.
|
||||
hr = CreateTopology(pSource, pSinkActivate, &ig_pTopology);
|
||||
|
||||
SafeRelease(&pSinkActivate);
|
||||
SafeRelease(&pType);
|
||||
return S_OK;
|
||||
|
||||
}
|
||||
|
||||
RawBuffer<uint8>* WinMfImageGrabber::GetImage() {
|
||||
return buffer_active;
|
||||
}
|
||||
|
||||
#define CHECK_HR(x) if (FAILED(x)) { goto done; }
|
||||
HRESULT WinMfImageGrabber::CreateTopology(IMFMediaSource *pSource, IMFActivate *pSinkActivate, IMFTopology **ppTopo) {
|
||||
IMFTopology *pTopology = NULL;
|
||||
IMFPresentationDescriptor *pPD = NULL;
|
||||
IMFStreamDescriptor *pSD = NULL;
|
||||
IMFMediaTypeHandler *pHandler = NULL;
|
||||
IMFTopologyNode *pNode1 = NULL;
|
||||
IMFTopologyNode *pNode2 = NULL;
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
DWORD cStreams = 0;
|
||||
|
||||
CHECK_HR(hr = MFCreateTopology(&pTopology));
|
||||
CHECK_HR(hr = pSource->CreatePresentationDescriptor(&pPD));
|
||||
CHECK_HR(hr = pPD->GetStreamDescriptorCount(&cStreams));
|
||||
|
||||
for(DWORD i = 0; i < cStreams; i++) {
|
||||
// In this example, we look for audio streams and connect them to the sink.
|
||||
|
||||
BOOL fSelected = FALSE;
|
||||
GUID majorType;
|
||||
|
||||
CHECK_HR(hr = pPD->GetStreamDescriptorByIndex(i, &fSelected, &pSD));
|
||||
CHECK_HR(hr = pSD->GetMediaTypeHandler(&pHandler));
|
||||
CHECK_HR(hr = pHandler->GetMajorType(&majorType));
|
||||
|
||||
if(majorType == MFMediaType_Video && fSelected) {
|
||||
CHECK_HR(hr = AddSourceNode(pTopology, pSource, pPD, pSD, &pNode1));
|
||||
CHECK_HR(hr = AddOutputNode(pTopology, pSinkActivate, 0, &pNode2));
|
||||
CHECK_HR(hr = pNode1->ConnectOutput(0, pNode2, 0));
|
||||
break;
|
||||
} else {
|
||||
CHECK_HR(hr = pPD->DeselectStream(i));
|
||||
}
|
||||
SafeRelease(&pSD);
|
||||
SafeRelease(&pHandler);
|
||||
}
|
||||
|
||||
*ppTopo = pTopology;
|
||||
(*ppTopo)->AddRef();
|
||||
|
||||
done:
|
||||
SAFE_RELEASE(pTopology);
|
||||
SAFE_RELEASE(pNode1);
|
||||
SAFE_RELEASE(pNode2);
|
||||
SAFE_RELEASE(pPD);
|
||||
SAFE_RELEASE(pSD);
|
||||
SAFE_RELEASE(pHandler);
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT WinMfImageGrabber::AddSourceNode(
|
||||
IMFTopology *pTopology, // Topology.
|
||||
IMFMediaSource *pSource, // Media source.
|
||||
IMFPresentationDescriptor *pPD, // Presentation descriptor.
|
||||
IMFStreamDescriptor *pSD, // Stream descriptor.
|
||||
IMFTopologyNode **ppNode) // Receives the node pointer.
|
||||
{
|
||||
IMFTopologyNode *pNode = NULL;
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
CHECK_HR(hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &pNode));
|
||||
CHECK_HR(hr = pNode->SetUnknown(MF_TOPONODE_SOURCE, pSource));
|
||||
CHECK_HR(hr = pNode->SetUnknown(MF_TOPONODE_PRESENTATION_DESCRIPTOR, pPD));
|
||||
CHECK_HR(hr = pNode->SetUnknown(MF_TOPONODE_STREAM_DESCRIPTOR, pSD));
|
||||
CHECK_HR(hr = pTopology->AddNode(pNode));
|
||||
|
||||
// Return the pointer to the caller.
|
||||
*ppNode = pNode;
|
||||
(*ppNode)->AddRef();
|
||||
|
||||
done:
|
||||
SafeRelease(&pNode);
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT WinMfImageGrabber::AddOutputNode(
|
||||
IMFTopology *pTopology, // Topology.
|
||||
IMFActivate *pActivate, // Media sink activation object.
|
||||
DWORD dwId, // Identifier of the stream sink.
|
||||
IMFTopologyNode **ppNode) // Receives the node pointer.
|
||||
{
|
||||
IMFTopologyNode *pNode = NULL;
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
CHECK_HR(hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &pNode));
|
||||
CHECK_HR(hr = pNode->SetObject(pActivate));
|
||||
CHECK_HR(hr = pNode->SetUINT32(MF_TOPONODE_STREAMID, dwId));
|
||||
CHECK_HR(hr = pNode->SetUINT32(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE));
|
||||
CHECK_HR(hr = pTopology->AddNode(pNode));
|
||||
|
||||
// Return the pointer to the caller.
|
||||
*ppNode = pNode;
|
||||
(*ppNode)->AddRef();
|
||||
|
||||
done:
|
||||
SafeRelease(&pNode);
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HRESULT WinMfImageGrabber::startGrabbing(void) {
|
||||
PROPVARIANT var;
|
||||
PropVariantInit(&var);
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
hr = ig_pSession->SetTopology(0, ig_pTopology);
|
||||
hr = ig_pSession->Start(&GUID_NULL, &var);
|
||||
return hr;
|
||||
}
|
||||
|
||||
bool WinMfImageGrabber::processGrabbing() {
|
||||
HRESULT hrStatus = S_OK;
|
||||
MediaEventType met;
|
||||
HRESULT hr;
|
||||
IMFMediaEvent *pEvent = NULL;
|
||||
|
||||
if(!ig_pSession) return false;
|
||||
hr = ig_pSession->GetEvent(0, &pEvent);
|
||||
if(!SUCCEEDED(hr)) {
|
||||
hr = S_OK;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = pEvent->GetStatus(&hrStatus);
|
||||
if(!SUCCEEDED(hr)) {
|
||||
hr = S_OK;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = pEvent->GetType(&met);
|
||||
if(!SUCCEEDED(hr)) {
|
||||
hr = S_OK;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if(met == MESessionEnded) {
|
||||
LogInfo() << "IMAGEGRABBER VIDEODEVICE %i: MESessionEnded ";
|
||||
|
||||
ig_pSession->Stop();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if(met == MESessionStopped) {
|
||||
LogInfo() << "IMAGEGRABBER VIDEODEVICE %i: MESessionStopped";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if(met == MEVideoCaptureDeviceRemoved) {
|
||||
LogInfo() << "IMAGEGRABBER VIDEODEVICE %i: MEVideoCaptureDeviceRemoved";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SafeRelease(&pEvent);
|
||||
return true;
|
||||
}
|
||||
|
||||
void WinMfImageGrabber::stopGrabbing() {
|
||||
if(ig_pSession) {
|
||||
ig_pSession->Stop();
|
||||
ig_pSession->Shutdown();
|
||||
SAFE_RELEASE(ig_pSession);
|
||||
SAFE_RELEASE(ig_pTopology);
|
||||
}
|
||||
|
||||
/*IMFMediaSource *ig_pSource;
|
||||
IMFMediaSession *ig_pSession;
|
||||
IMFTopology *ig_pTopology;*/
|
||||
|
||||
}
|
||||
|
||||
// IUnknown methods
|
||||
STDMETHODIMP WinMfImageGrabber::QueryInterface(REFIID iid, void** ppv) {
|
||||
// Creation tab of shifting interfaces from start of this class
|
||||
static const QITAB qit[] = {
|
||||
|
||||
QITABENT(WinMfImageGrabber, IMFSampleGrabberSinkCallback),
|
||||
QITABENT(WinMfImageGrabber, IMFClockStateSink), { 0 }
|
||||
};
|
||||
return QISearch(this, qit, iid, ppv);
|
||||
}
|
||||
STDMETHODIMP_(ULONG) WinMfImageGrabber::AddRef() {
|
||||
return InterlockedIncrement(&m_cRef);
|
||||
}
|
||||
STDMETHODIMP_(ULONG) WinMfImageGrabber::Release() {
|
||||
ULONG cRef = InterlockedDecrement(&m_cRef);
|
||||
if(cRef == 0) {
|
||||
delete this;
|
||||
}
|
||||
return cRef;
|
||||
}
|
||||
|
||||
// IMFClockStateSink methods
|
||||
STDMETHODIMP WinMfImageGrabber::OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset) {
|
||||
return S_OK;
|
||||
}
|
||||
STDMETHODIMP WinMfImageGrabber::OnClockStop(MFTIME hnsSystemTime) {
|
||||
return S_OK;
|
||||
}
|
||||
STDMETHODIMP WinMfImageGrabber::OnClockPause(MFTIME hnsSystemTime) {
|
||||
return S_OK;
|
||||
}
|
||||
STDMETHODIMP WinMfImageGrabber::OnClockRestart(MFTIME hnsSystemTime) {
|
||||
return S_OK;
|
||||
}
|
||||
STDMETHODIMP WinMfImageGrabber::OnClockSetRate(MFTIME hnsSystemTime, float flRate) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// IMFSampleGrabberSinkCallback methods
|
||||
STDMETHODIMP WinMfImageGrabber::OnSetPresentationClock(IMFPresentationClock* pClock) {
|
||||
return S_OK;
|
||||
}
|
||||
STDMETHODIMP WinMfImageGrabber::OnProcessSample(REFGUID guidMajorMediaType, DWORD dwSampleFlags,
|
||||
LONGLONG llSampleTime, LONGLONG llSampleDuration, const BYTE * pSampleBuffer,
|
||||
DWORD dwSampleSize)
|
||||
{
|
||||
LogInfo() << "Process sample";
|
||||
buffer_active->SetData((void*)pSampleBuffer);
|
||||
camera->OnImageGrabbed(this, buffer_active);
|
||||
return 0;
|
||||
}
|
||||
STDMETHODIMP WinMfImageGrabber::OnShutdown() {
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
#ifndef WinMfImageGrabber_h__
|
||||
#define WinMfImageGrabber_h__
|
||||
|
||||
#include <mfidl.h>
|
||||
#include "../RawBuffer.h"
|
||||
#include "../Types.h"
|
||||
|
||||
namespace LifeCore {
|
||||
|
||||
class WebCamera;
|
||||
class WinMfImageGrabber : IMFSampleGrabberSinkCallback {
|
||||
public:
|
||||
WinMfImageGrabber(WebCamera* cam);
|
||||
~WinMfImageGrabber();
|
||||
HRESULT initImageGrabber(IMFMediaSource *pSource, GUID VideoFormat);
|
||||
HRESULT startGrabbing(void);
|
||||
void stopGrabbing();
|
||||
|
||||
// IUnknown methods
|
||||
STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
|
||||
STDMETHODIMP_(ULONG) AddRef();
|
||||
STDMETHODIMP_(ULONG) Release();
|
||||
|
||||
// IMFClockStateSink methods
|
||||
STDMETHODIMP OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset);
|
||||
STDMETHODIMP OnClockStop(MFTIME hnsSystemTime);
|
||||
STDMETHODIMP OnClockPause(MFTIME hnsSystemTime);
|
||||
STDMETHODIMP OnClockRestart(MFTIME hnsSystemTime);
|
||||
STDMETHODIMP OnClockSetRate(MFTIME hnsSystemTime, float flRate);
|
||||
|
||||
// IMFSampleGrabberSinkCallback methods
|
||||
STDMETHODIMP OnSetPresentationClock(IMFPresentationClock* pClock);
|
||||
STDMETHODIMP OnProcessSample(REFGUID guidMajorMediaType, DWORD dwSampleFlags,
|
||||
LONGLONG llSampleTime, LONGLONG llSampleDuration, const BYTE * pSampleBuffer,
|
||||
DWORD dwSampleSize);
|
||||
STDMETHODIMP OnShutdown();
|
||||
bool processGrabbing();
|
||||
RawBuffer<uint8>* GetImage();
|
||||
private:
|
||||
WebCamera* camera;
|
||||
long m_cRef;
|
||||
//IMFMediaSource *ig_pSource;
|
||||
IMFMediaSession *ig_pSession;
|
||||
IMFTopology *ig_pTopology;
|
||||
RawBuffer<uint8>* buffer_first;
|
||||
RawBuffer<uint8>* buffer_second;
|
||||
RawBuffer<uint8>* buffer_active;
|
||||
|
||||
HRESULT CreateTopology(IMFMediaSource *pSource, IMFActivate *pSinkActivate, IMFTopology **ppTopo);
|
||||
HRESULT AddSourceNode(
|
||||
IMFTopology *pTopology,
|
||||
IMFMediaSource *pSource,
|
||||
IMFPresentationDescriptor *pPD,
|
||||
IMFStreamDescriptor *pSD,
|
||||
IMFTopologyNode **ppNode);
|
||||
|
||||
HRESULT AddOutputNode(
|
||||
IMFTopology *pTopology,
|
||||
IMFActivate *pActivate,
|
||||
DWORD dwId,
|
||||
IMFTopologyNode **ppNode);
|
||||
};
|
||||
|
||||
}
|
||||
#endif // WinMfImageGrabber_h__
|
||||
@@ -0,0 +1,129 @@
|
||||
#ifndef WinMfMediaType_h__
|
||||
#define WinMfMediaType_h__
|
||||
|
||||
#include <guiddef.h>
|
||||
|
||||
namespace LifeCore {
|
||||
// Structure for collecting info about types of video, which are supported by current video device
|
||||
struct WinMfMediaType {
|
||||
unsigned int MF_MT_FRAME_SIZE;
|
||||
|
||||
unsigned int height;
|
||||
|
||||
unsigned int width;
|
||||
|
||||
unsigned int MF_MT_YUV_MATRIX;
|
||||
|
||||
unsigned int MF_MT_VIDEO_LIGHTING;
|
||||
|
||||
unsigned int MF_MT_DEFAULT_STRIDE;
|
||||
|
||||
unsigned int MF_MT_VIDEO_CHROMA_SITING;
|
||||
|
||||
GUID MF_MT_AM_FORMAT_TYPE;
|
||||
|
||||
wchar_t *pMF_MT_AM_FORMAT_TYPEName;
|
||||
|
||||
unsigned int MF_MT_FIXED_SIZE_SAMPLES;
|
||||
|
||||
unsigned int MF_MT_VIDEO_NOMINAL_RANGE;
|
||||
|
||||
unsigned int MF_MT_FRAME_RATE;
|
||||
|
||||
unsigned int MF_MT_FRAME_RATE_low;
|
||||
|
||||
unsigned int MF_MT_PIXEL_ASPECT_RATIO;
|
||||
|
||||
unsigned int MF_MT_PIXEL_ASPECT_RATIO_low;
|
||||
|
||||
unsigned int MF_MT_ALL_SAMPLES_INDEPENDENT;
|
||||
|
||||
unsigned int MF_MT_FRAME_RATE_RANGE_MIN;
|
||||
|
||||
unsigned int MF_MT_FRAME_RATE_RANGE_MIN_low;
|
||||
|
||||
unsigned int MF_MT_SAMPLE_SIZE;
|
||||
|
||||
unsigned int MF_MT_VIDEO_PRIMARIES;
|
||||
|
||||
unsigned int MF_MT_INTERLACE_MODE;
|
||||
|
||||
unsigned int MF_MT_FRAME_RATE_RANGE_MAX;
|
||||
|
||||
unsigned int MF_MT_FRAME_RATE_RANGE_MAX_low;
|
||||
|
||||
GUID MF_MT_MAJOR_TYPE;
|
||||
|
||||
wchar_t *pMF_MT_MAJOR_TYPEName;
|
||||
|
||||
GUID MF_MT_SUBTYPE;
|
||||
|
||||
wchar_t *pMF_MT_SUBTYPEName;
|
||||
|
||||
WinMfMediaType() {
|
||||
pMF_MT_AM_FORMAT_TYPEName = NULL;
|
||||
|
||||
pMF_MT_MAJOR_TYPEName = NULL;
|
||||
|
||||
pMF_MT_SUBTYPEName = NULL;
|
||||
|
||||
Clear();
|
||||
}
|
||||
|
||||
~WinMfMediaType() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
|
||||
MF_MT_FRAME_SIZE = 0;
|
||||
|
||||
height = 0;
|
||||
|
||||
width = 0;
|
||||
|
||||
MF_MT_YUV_MATRIX = 0;
|
||||
|
||||
MF_MT_VIDEO_LIGHTING = 0;
|
||||
|
||||
MF_MT_DEFAULT_STRIDE = 0;
|
||||
|
||||
MF_MT_VIDEO_CHROMA_SITING = 0;
|
||||
|
||||
MF_MT_FIXED_SIZE_SAMPLES = 0;
|
||||
|
||||
MF_MT_VIDEO_NOMINAL_RANGE = 0;
|
||||
|
||||
MF_MT_FRAME_RATE = 0;
|
||||
|
||||
MF_MT_FRAME_RATE_low = 0;
|
||||
|
||||
MF_MT_PIXEL_ASPECT_RATIO = 0;
|
||||
|
||||
MF_MT_PIXEL_ASPECT_RATIO_low = 0;
|
||||
|
||||
MF_MT_ALL_SAMPLES_INDEPENDENT = 0;
|
||||
|
||||
MF_MT_FRAME_RATE_RANGE_MIN = 0;
|
||||
|
||||
MF_MT_FRAME_RATE_RANGE_MIN_low = 0;
|
||||
|
||||
MF_MT_SAMPLE_SIZE = 0;
|
||||
|
||||
MF_MT_VIDEO_PRIMARIES = 0;
|
||||
|
||||
MF_MT_INTERLACE_MODE = 0;
|
||||
|
||||
MF_MT_FRAME_RATE_RANGE_MAX = 0;
|
||||
|
||||
MF_MT_FRAME_RATE_RANGE_MAX_low = 0;
|
||||
|
||||
memset(&MF_MT_MAJOR_TYPE, 0, sizeof(GUID));
|
||||
|
||||
memset(&MF_MT_AM_FORMAT_TYPE, 0, sizeof(GUID));
|
||||
|
||||
memset(&MF_MT_SUBTYPE, 0, sizeof(GUID));
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif // WinMfMediaType_h__
|
||||
Reference in New Issue
Block a user