add some log
This commit is contained in:
parent
8d017f5e2d
commit
ff33770ca4
|
@ -49,7 +49,8 @@
|
||||||
|
|
||||||
MYNTEYE_BEGIN_NAMESPACE
|
MYNTEYE_BEGIN_NAMESPACE
|
||||||
|
|
||||||
namespace uvc {
|
namespace uvc
|
||||||
|
{
|
||||||
|
|
||||||
const std::map<uint32_t, uint32_t> fourcc_map = { { 0x56595559, 0x32595559 } ,{ 0x59555956, 0x59555932 }}; /* 'VYUY' => '2YUY','YUYV' => 'YUY2'. */
|
const std::map<uint32_t, uint32_t> fourcc_map = { { 0x56595559, 0x32595559 } ,{ 0x59555956, 0x59555932 }}; /* 'VYUY' => '2YUY','YUYV' => 'YUY2'. */
|
||||||
|
|
||||||
|
@ -82,35 +83,48 @@ struct throw_error {
|
||||||
template<class T> class com_ptr
|
template<class T> class com_ptr
|
||||||
{
|
{
|
||||||
T * p;
|
T * p;
|
||||||
void ref(T * new_p)
|
void ref(T * new_p) {
|
||||||
{
|
|
||||||
if(p == new_p) return;
|
if(p == new_p) return;
|
||||||
unref();
|
unref();
|
||||||
p = new_p;
|
p = new_p;
|
||||||
if(p) p->AddRef();
|
if(p) p->AddRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
void unref()
|
void unref() {
|
||||||
{
|
if(p) {
|
||||||
if(p)
|
|
||||||
{
|
|
||||||
p->Release();
|
p->Release();
|
||||||
p = nullptr;
|
p = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
com_ptr() : p() {}
|
com_ptr() : p() {}
|
||||||
com_ptr(T * p) : com_ptr() { ref(p); }
|
com_ptr(T * p) : com_ptr() {
|
||||||
|
ref(p);
|
||||||
|
}
|
||||||
com_ptr(const com_ptr & r) : com_ptr(r.p) {}
|
com_ptr(const com_ptr & r) : com_ptr(r.p) {}
|
||||||
~com_ptr() { unref(); }
|
~com_ptr() {
|
||||||
|
unref();
|
||||||
|
}
|
||||||
|
|
||||||
operator T * () const { return p; }
|
operator T * () const {
|
||||||
T & operator * () const { return *p; }
|
return p;
|
||||||
T * operator -> () const { return p; }
|
}
|
||||||
|
T & operator * () const {
|
||||||
|
return *p;
|
||||||
|
}
|
||||||
|
T * operator -> () const {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
T ** operator & () { unref(); return &p; }
|
T ** operator & () {
|
||||||
com_ptr & operator = (const com_ptr & r) { ref(r.p); return *this; }
|
unref();
|
||||||
};
|
return &p;
|
||||||
|
}
|
||||||
|
com_ptr & operator = (const com_ptr & r) {
|
||||||
|
ref(r.p);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static std::string win_to_utf(const WCHAR * s)
|
static std::string win_to_utf(const WCHAR * s)
|
||||||
{
|
{
|
||||||
|
@ -122,23 +136,20 @@ static std::string win_to_utf(const WCHAR * s)
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check(const char *call, HRESULT hr) {
|
static void check(const char *call, HRESULT hr)
|
||||||
|
{
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
std::cout << call << "(...) returned 0x" << std::hex << (uint32_t)hr << std::endl;
|
|
||||||
throw_error() << call << "(...) returned 0x" << std::hex << (uint32_t)hr;
|
throw_error() << call << "(...) returned 0x" << std::hex << (uint32_t)hr;
|
||||||
}
|
}
|
||||||
std::cout << call << " SUCCESSED " << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> tokenize(std::string string, char separator)
|
std::vector<std::string> tokenize(std::string string, char separator)
|
||||||
{
|
{
|
||||||
std::vector<std::string> tokens;
|
std::vector<std::string> tokens;
|
||||||
std::string::size_type i1 = 0;
|
std::string::size_type i1 = 0;
|
||||||
while(true)
|
while(true) {
|
||||||
{
|
|
||||||
auto i2 = string.find(separator, i1);
|
auto i2 = string.find(separator, i1);
|
||||||
if(i2 == std::string::npos)
|
if(i2 == std::string::npos) {
|
||||||
{
|
|
||||||
tokens.push_back(string.substr(i1));
|
tokens.push_back(string.substr(i1));
|
||||||
return tokens;
|
return tokens;
|
||||||
}
|
}
|
||||||
|
@ -153,35 +164,30 @@ bool parse_usb_path(int & vid, int & pid, int & mi, std::string & unique_id, con
|
||||||
std::transform(begin(name), end(name), begin(name), ::tolower);
|
std::transform(begin(name), end(name), begin(name), ::tolower);
|
||||||
auto tokens = tokenize(name, '#');
|
auto tokens = tokenize(name, '#');
|
||||||
if(tokens.size() < 1 || tokens[0] != R"(\\?\usb)") return false; // Not a USB device
|
if(tokens.size() < 1 || tokens[0] != R"(\\?\usb)") return false; // Not a USB device
|
||||||
if(tokens.size() < 3)
|
if(tokens.size() < 3) {
|
||||||
{
|
LOG_ERROR(WARNING,"malformed usb device path: " << name);
|
||||||
//LOG_ERROR("malformed usb device path: " + name);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ids = tokenize(tokens[1], '&');
|
auto ids = tokenize(tokens[1], '&');
|
||||||
if(ids[0].size() != 8 || ids[0].substr(0,4) != "vid_" || !(std::istringstream(ids[0].substr(4,4)) >> std::hex >> vid))
|
if(ids[0].size() != 8 || ids[0].substr(0,4) != "vid_" || !(std::istringstream(ids[0].substr(4,4)) >> std::hex >> vid)) {
|
||||||
{
|
LOG_ERROR(WARNING,"malformed vid string: " << tokens[1]);
|
||||||
//LOG_ERROR("malformed vid string: " + tokens[1]);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ids[1].size() != 8 || ids[1].substr(0,4) != "pid_" || !(std::istringstream(ids[1].substr(4,4)) >> std::hex >> pid))
|
if(ids[1].size() != 8 || ids[1].substr(0,4) != "pid_" || !(std::istringstream(ids[1].substr(4,4)) >> std::hex >> pid)) {
|
||||||
{
|
LOG_ERROR(WARNING,"malformed pid string: " << tokens[1]);
|
||||||
//LOG_ERROR("malformed pid string: " + tokens[1]);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ids[2].size() != 5 || ids[2].substr(0,3) != "mi_" || !(std::istringstream(ids[2].substr(3,2)) >> mi))
|
if(ids[2].size() != 5 || ids[2].substr(0,3) != "mi_" || !(std::istringstream(ids[2].substr(3,2)) >> mi)) {
|
||||||
{
|
LOG_ERROR(WARNING,"malformed mi string: " << tokens[1]);
|
||||||
//LOG_ERROR("malformed mi string: " + tokens[1]);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ids = tokenize(tokens[2], '&');
|
ids = tokenize(tokens[2], '&');
|
||||||
if(ids.size() < 2)
|
if(ids.size() < 2) {
|
||||||
{
|
LOG_ERROR(WARNING,"malformed id string: " << tokens[2]);
|
||||||
//LOG_ERROR("malformed id string: " + tokens[2]);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
unique_id = ids[1];
|
unique_id = ids[1];
|
||||||
|
@ -196,44 +202,37 @@ bool parse_usb_path_from_device_id(int & vid, int & pid, int & mi, std::string &
|
||||||
if (tokens.size() < 1 || tokens[0] != R"(usb)") return false; // Not a USB device
|
if (tokens.size() < 1 || tokens[0] != R"(usb)") return false; // Not a USB device
|
||||||
|
|
||||||
auto ids = tokenize(tokens[1], '&');
|
auto ids = tokenize(tokens[1], '&');
|
||||||
if (ids[0].size() != 8 || ids[0].substr(0, 4) != "vid_" || !(std::istringstream(ids[0].substr(4, 4)) >> std::hex >> vid))
|
if (ids[0].size() != 8 || ids[0].substr(0, 4) != "vid_" || !(std::istringstream(ids[0].substr(4, 4)) >> std::hex >> vid)) {
|
||||||
{
|
LOG_ERROR(WARNING,"malformed vid string: " << tokens[1]);
|
||||||
//LOG_ERROR("malformed vid string: " + tokens[1]);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ids[1].size() != 8 || ids[1].substr(0, 4) != "pid_" || !(std::istringstream(ids[1].substr(4, 4)) >> std::hex >> pid))
|
if (ids[1].size() != 8 || ids[1].substr(0, 4) != "pid_" || !(std::istringstream(ids[1].substr(4, 4)) >> std::hex >> pid)) {
|
||||||
{
|
LOG_ERROR(WARNING,"malformed pid string: " << tokens[1]);
|
||||||
//LOG_ERROR("malformed pid string: " + tokens[1]);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ids[2].size() != 5 || ids[2].substr(0, 3) != "mi_" || !(std::istringstream(ids[2].substr(3, 2)) >> mi))
|
if (ids[2].size() != 5 || ids[2].substr(0, 3) != "mi_" || !(std::istringstream(ids[2].substr(3, 2)) >> mi)) {
|
||||||
{
|
LOG_ERROR(WARNING,"malformed mi string: " << tokens[1]);
|
||||||
//LOG_ERROR("malformed mi string: " + tokens[1]);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ids = tokenize(tokens[2], '&');
|
ids = tokenize(tokens[2], '&');
|
||||||
if (ids.size() < 2)
|
if (ids.size() < 2) {
|
||||||
{
|
LOG_ERROR(WARNING,"malformed id string: " + tokens[2]);
|
||||||
//LOG_ERROR("malformed id string: " + tokens[2]);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
unique_id = ids[1];
|
unique_id = ids[1];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct context
|
struct context {
|
||||||
{
|
context() {
|
||||||
context()
|
|
||||||
{
|
|
||||||
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
MFStartup(MF_VERSION, MFSTARTUP_NOSOCKET);
|
MFStartup(MF_VERSION, MFSTARTUP_NOSOCKET);
|
||||||
}
|
}
|
||||||
~context()
|
~context() {
|
||||||
{
|
|
||||||
MFShutdown();
|
MFShutdown();
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
}
|
}
|
||||||
|
@ -247,22 +246,24 @@ class reader_callback : public IMFSourceReaderCallback
|
||||||
public:
|
public:
|
||||||
reader_callback(std::weak_ptr<device> owner) : owner(owner), ref_count() {}
|
reader_callback(std::weak_ptr<device> owner) : owner(owner), ref_count() {}
|
||||||
|
|
||||||
bool is_streaming() const { return streaming; }
|
bool is_streaming() const {
|
||||||
void on_start() { streaming = true; }
|
return streaming;
|
||||||
|
}
|
||||||
|
void on_start() {
|
||||||
|
streaming = true;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma warning( push )
|
#pragma warning( push )
|
||||||
#pragma warning( disable: 4838 )
|
#pragma warning( disable: 4838 )
|
||||||
// Implement IUnknown
|
// Implement IUnknown
|
||||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void ** ppvObject) override
|
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void ** ppvObject) override {
|
||||||
{
|
|
||||||
static const QITAB table[] = {QITABENT(reader_callback, IUnknown), QITABENT(reader_callback, IMFSourceReaderCallback), {0}};
|
static const QITAB table[] = {QITABENT(reader_callback, IUnknown), QITABENT(reader_callback, IMFSourceReaderCallback), {0}};
|
||||||
return QISearch(this, table, riid, ppvObject);
|
return QISearch(this, table, riid, ppvObject);
|
||||||
}
|
}
|
||||||
#pragma warning( pop )
|
#pragma warning( pop )
|
||||||
|
|
||||||
ULONG STDMETHODCALLTYPE AddRef() override { return InterlockedIncrement(&ref_count); }
|
ULONG STDMETHODCALLTYPE AddRef() override { return InterlockedIncrement(&ref_count); }
|
||||||
ULONG STDMETHODCALLTYPE Release() override
|
ULONG STDMETHODCALLTYPE Release() override {
|
||||||
{
|
|
||||||
ULONG count = InterlockedDecrement(&ref_count);
|
ULONG count = InterlockedDecrement(&ref_count);
|
||||||
if(count == 0) delete this;
|
if(count == 0) delete this;
|
||||||
return count;
|
return count;
|
||||||
|
@ -289,11 +290,12 @@ struct device {
|
||||||
com_ptr<IMFSourceReader> mf_source_reader;
|
com_ptr<IMFSourceReader> mf_source_reader;
|
||||||
video_channel_callback callback = nullptr;
|
video_channel_callback callback = nullptr;
|
||||||
|
|
||||||
device(std::shared_ptr<context> parent, int vid, int pid, std::string unique_id, std::string name) : parent(move(parent)), vid(vid), pid(pid), name(name)
|
device(std::shared_ptr<context> parent, int vid, int pid, std::string unique_id, std::string name) : parent(move(parent)), vid(vid), pid(pid), unique_id(move(unique_id)), name(name)
|
||||||
{
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
~device() { stop_streaming(); }
|
~device() {
|
||||||
|
stop_streaming();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
IKsControl * get_ks_control(const uvc::xu & xu) {
|
IKsControl * get_ks_control(const uvc::xu & xu) {
|
||||||
|
@ -308,7 +310,6 @@ struct device {
|
||||||
|
|
||||||
GUID node_type;
|
GUID node_type;
|
||||||
check("get_NodeType", ks_topology_info->get_NodeType(xu.node, &node_type));
|
check("get_NodeType", ks_topology_info->get_NodeType(xu.node, &node_type));
|
||||||
std::cout << "node_type" << node_type.Data1 << "," << node_type.Data2 << "," <<node_type.Data3 << "," << node_type.Data4 << "," <<std::endl;
|
|
||||||
//const GUID KSNODETYPE_DEV_SPECIFIC_LOCAL{0x6BDD1FC6, 0X810F, 0x11D0, {0xBE, 0xC7 ,0x08, 0x00, 0x2B, 0xE2, 0x09, 0x2F}};
|
//const GUID KSNODETYPE_DEV_SPECIFIC_LOCAL{0x6BDD1FC6, 0X810F, 0x11D0, {0xBE, 0xC7 ,0x08, 0x00, 0x2B, 0xE2, 0x09, 0x2F}};
|
||||||
//if(node_type != KSNODETYPE_DEV_SPECIFIC_LOCAL) throw_error() << "Invalid extension unit node ID: " << xu.node;
|
//if(node_type != KSNODETYPE_DEV_SPECIFIC_LOCAL) throw_error() << "Invalid extension unit node ID: " << xu.node;
|
||||||
|
|
||||||
|
@ -321,21 +322,17 @@ struct device {
|
||||||
return ks_controls[xu.node] = ks_control;
|
return ks_controls[xu.node] = ks_control;
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_streaming()
|
void start_streaming() {
|
||||||
{
|
if(mf_source_reader) {
|
||||||
if(mf_source_reader)
|
|
||||||
{
|
|
||||||
reader_callback->on_start();
|
reader_callback->on_start();
|
||||||
check("IMFSourceReader::ReadSample", mf_source_reader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, NULL, NULL, NULL, NULL));
|
check("IMFSourceReader::ReadSample", mf_source_reader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, NULL, NULL, NULL, NULL));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop_streaming()
|
void stop_streaming() {
|
||||||
{
|
|
||||||
|
|
||||||
if(mf_source_reader) mf_source_reader->Flush(MF_SOURCE_READER_FIRST_VIDEO_STREAM);
|
if(mf_source_reader) mf_source_reader->Flush(MF_SOURCE_READER_FIRST_VIDEO_STREAM);
|
||||||
while(true)
|
while(true) {
|
||||||
{
|
|
||||||
bool is_streaming = reader_callback->is_streaming();
|
bool is_streaming = reader_callback->is_streaming();
|
||||||
if(is_streaming) std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
if(is_streaming) std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
else break;
|
else break;
|
||||||
|
@ -345,25 +342,20 @@ struct device {
|
||||||
am_camera_control = nullptr;
|
am_camera_control = nullptr;
|
||||||
am_video_proc_amp = nullptr;
|
am_video_proc_amp = nullptr;
|
||||||
ks_controls.clear();
|
ks_controls.clear();
|
||||||
if(mf_media_source)
|
if(mf_media_source) {
|
||||||
{
|
|
||||||
mf_media_source = nullptr;
|
mf_media_source = nullptr;
|
||||||
check("IMFActivate::ShutdownObject", mf_activate->ShutdownObject());
|
check("IMFActivate::ShutdownObject", mf_activate->ShutdownObject());
|
||||||
}
|
}
|
||||||
callback = {};
|
callback = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
com_ptr<IMFMediaSource> get_media_source()
|
com_ptr<IMFMediaSource> get_media_source() {
|
||||||
{
|
if(!mf_media_source) {
|
||||||
if(!mf_media_source)
|
|
||||||
{
|
|
||||||
check("IMFActivate::ActivateObject", mf_activate->ActivateObject(__uuidof(IMFMediaSource), (void **)&mf_media_source));
|
check("IMFActivate::ActivateObject", mf_activate->ActivateObject(__uuidof(IMFMediaSource), (void **)&mf_media_source));
|
||||||
if (mf_media_source)
|
if (mf_media_source) {
|
||||||
{
|
|
||||||
check("IMFMediaSource::QueryInterface", mf_media_source->QueryInterface(__uuidof(IAMCameraControl), (void **)&am_camera_control));
|
check("IMFMediaSource::QueryInterface", mf_media_source->QueryInterface(__uuidof(IAMCameraControl), (void **)&am_camera_control));
|
||||||
if (SUCCEEDED(mf_media_source->QueryInterface(__uuidof(IAMVideoProcAmp), (void **)&am_video_proc_amp)));
|
if (SUCCEEDED(mf_media_source->QueryInterface(__uuidof(IAMVideoProcAmp), (void **)&am_video_proc_amp)));
|
||||||
}
|
} else throw_error() << "Invalid media source";
|
||||||
else throw_error() << "Invalid media source";
|
|
||||||
}
|
}
|
||||||
return mf_media_source;
|
return mf_media_source;
|
||||||
}
|
}
|
||||||
|
@ -372,41 +364,44 @@ struct device {
|
||||||
|
|
||||||
HRESULT reader_callback::OnReadSample(HRESULT hrStatus, DWORD dwStreamIndex, DWORD dwStreamFlags, LONGLONG llTimestamp, IMFSample * sample)
|
HRESULT reader_callback::OnReadSample(HRESULT hrStatus, DWORD dwStreamIndex, DWORD dwStreamFlags, LONGLONG llTimestamp, IMFSample * sample)
|
||||||
{
|
{
|
||||||
if(auto owner_ptr = owner.lock())
|
if(auto owner_ptr = owner.lock()) {
|
||||||
{
|
if(sample) {
|
||||||
if(sample)
|
|
||||||
{
|
|
||||||
std::cout << "sample is not null" << std::endl;
|
|
||||||
com_ptr<IMFMediaBuffer> buffer = NULL;
|
com_ptr<IMFMediaBuffer> buffer = NULL;
|
||||||
if(SUCCEEDED(sample->GetBufferByIndex(0, &buffer)))
|
if(SUCCEEDED(sample->GetBufferByIndex(0, &buffer))) {
|
||||||
{
|
BYTE * byte_buffer;
|
||||||
std::cout << "SUCCEEDED(sample->GetBufferByIndex(0, &buffer))" << std::endl;
|
DWORD max_length, current_length;
|
||||||
BYTE * byte_buffer; DWORD max_length, current_length;
|
if(SUCCEEDED(buffer->Lock(&byte_buffer, &max_length, ¤t_length))) {
|
||||||
if(SUCCEEDED(buffer->Lock(&byte_buffer, &max_length, ¤t_length)))
|
auto continuation = [buffer, this]() {
|
||||||
{
|
|
||||||
auto continuation = [buffer, this]()
|
|
||||||
{
|
|
||||||
buffer->Unlock();
|
buffer->Unlock();
|
||||||
};
|
};
|
||||||
|
|
||||||
owner_ptr->callback(byte_buffer);
|
owner_ptr->callback(byte_buffer);
|
||||||
std::cout << "owner_ptr->callback(byte_buffer);" << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto owner_ptr_new = owner.lock())
|
if (auto owner_ptr_new = owner.lock()) {
|
||||||
{
|
|
||||||
auto hr = owner_ptr_new->mf_source_reader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, NULL, NULL, NULL, NULL);
|
auto hr = owner_ptr_new->mf_source_reader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, NULL, NULL, NULL, NULL);
|
||||||
switch (hr)
|
switch (hr) {
|
||||||
{
|
case S_OK:
|
||||||
case S_OK: break;
|
break;
|
||||||
case MF_E_INVALIDREQUEST: LOG_ERROR(WARNING,"ReadSample returned MF_E_INVALIDREQUEST"); break;
|
case MF_E_INVALIDREQUEST:
|
||||||
case MF_E_INVALIDSTREAMNUMBER: LOG_ERROR(WARNING,"ReadSample returned MF_E_INVALIDSTREAMNUMBER"); break;
|
LOG_ERROR(WARNING,"ReadSample returned MF_E_INVALIDREQUEST");
|
||||||
case MF_E_NOTACCEPTING: LOG_ERROR(WARNING,"ReadSample returned MF_E_NOTACCEPTING"); break;
|
break;
|
||||||
case E_INVALIDARG: LOG_ERROR(WARNING,"ReadSample returned E_INVALIDARG"); break;
|
case MF_E_INVALIDSTREAMNUMBER:
|
||||||
case MF_E_VIDEO_RECORDING_DEVICE_INVALIDATED: LOG_ERROR(WARNING,"ReadSample returned MF_E_VIDEO_RECORDING_DEVICE_INVALIDATED"); break;
|
LOG_ERROR(WARNING,"ReadSample returned MF_E_INVALIDSTREAMNUMBER");
|
||||||
default: LOG_ERROR(WARNING,"ReadSample returned HRESULT " << std::hex << (uint32_t)hr); break;
|
break;
|
||||||
|
case MF_E_NOTACCEPTING:
|
||||||
|
LOG_ERROR(WARNING,"ReadSample returned MF_E_NOTACCEPTING");
|
||||||
|
break;
|
||||||
|
case E_INVALIDARG:
|
||||||
|
LOG_ERROR(WARNING,"ReadSample returned E_INVALIDARG");
|
||||||
|
break;
|
||||||
|
case MF_E_VIDEO_RECORDING_DEVICE_INVALIDATED:
|
||||||
|
LOG_ERROR(WARNING,"ReadSample returned MF_E_VIDEO_RECORDING_DEVICE_INVALIDATED");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG_ERROR(WARNING,"ReadSample returned HRESULT " << std::hex << (uint32_t)hr);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (hr != S_OK) streaming = false;
|
if (hr != S_OK) streaming = false;
|
||||||
}
|
}
|
||||||
|
@ -414,13 +409,13 @@ HRESULT reader_callback::OnReadSample(HRESULT hrStatus, DWORD dwStreamIndex, DWO
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<context> create_context() {
|
std::shared_ptr<context> create_context()
|
||||||
|
{
|
||||||
return std::make_shared<context>();
|
return std::make_shared<context>();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<device>> query_devices(
|
std::vector<std::shared_ptr<device>> query_devices(std::shared_ptr<context> context)
|
||||||
std::shared_ptr<context> context) {
|
{
|
||||||
|
|
||||||
IMFAttributes *pAttributes = NULL;
|
IMFAttributes *pAttributes = NULL;
|
||||||
check("MFCreateAttributes", MFCreateAttributes(&pAttributes, 1));
|
check("MFCreateAttributes", MFCreateAttributes(&pAttributes, 1));
|
||||||
check("IMFAttributes::SetGUID",pAttributes->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID));
|
check("IMFAttributes::SetGUID",pAttributes->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID));
|
||||||
|
@ -448,18 +443,17 @@ std::vector<std::shared_ptr<device>> query_devices(
|
||||||
auto name = win_to_utf(wchar_name); // Device description name
|
auto name = win_to_utf(wchar_name); // Device description name
|
||||||
CoTaskMemFree(wchar_name);
|
CoTaskMemFree(wchar_name);
|
||||||
|
|
||||||
int vid, pid, mi; std::string unique_id;
|
int vid, pid, mi;
|
||||||
|
std::string unique_id;
|
||||||
|
|
||||||
if (!parse_usb_path(vid, pid, mi, unique_id, dev_name)) continue;
|
if (!parse_usb_path(vid, pid, mi, unique_id, dev_name)) continue;
|
||||||
|
|
||||||
std::shared_ptr<device> dev;
|
std::shared_ptr<device> dev;
|
||||||
for(auto & d : devices)
|
for(auto & d : devices) {
|
||||||
{
|
|
||||||
if(d->vid == vid && d->pid == pid && d->unique_id == unique_id)
|
if(d->vid == vid && d->pid == pid && d->unique_id == unique_id)
|
||||||
dev = d;
|
dev = d;
|
||||||
}
|
}
|
||||||
if(!dev)
|
if(!dev) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
dev = std::make_shared<device>(context, vid, pid, unique_id, name);
|
dev = std::make_shared<device>(context, vid, pid, unique_id, name);
|
||||||
devices.push_back(dev);
|
devices.push_back(dev);
|
||||||
|
@ -480,23 +474,28 @@ std::vector<std::shared_ptr<device>> query_devices(
|
||||||
return devices;
|
return devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_vendor_id(const device &device) {
|
int get_vendor_id(const device &device)
|
||||||
|
{
|
||||||
return device.vid;
|
return device.vid;
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_product_id(const device &device) {
|
int get_product_id(const device &device)
|
||||||
|
{
|
||||||
return device.pid;
|
return device.pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string get_name(const device &device) {
|
std::string get_name(const device &device)
|
||||||
|
{
|
||||||
return device.name;
|
return device.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string get_video_name(const device &device) {
|
std::string get_video_name(const device &device)
|
||||||
|
{
|
||||||
return device.name;
|
return device.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long get_cid(Option option) {
|
static long get_cid(Option option)
|
||||||
|
{
|
||||||
switch (option) {
|
switch (option) {
|
||||||
case Option::GAIN:
|
case Option::GAIN:
|
||||||
return VideoProcAmp_Gain;
|
return VideoProcAmp_Gain;
|
||||||
|
@ -511,7 +510,8 @@ static long get_cid(Option option) {
|
||||||
|
|
||||||
bool pu_control_range(
|
bool pu_control_range(
|
||||||
const device &device, Option option, int32_t *min, int32_t *max,
|
const device &device, Option option, int32_t *min, int32_t *max,
|
||||||
int32_t *def) {
|
int32_t *def)
|
||||||
|
{
|
||||||
const_cast<uvc::device &>(device).get_media_source();
|
const_cast<uvc::device &>(device).get_media_source();
|
||||||
long minVal=0, maxVal=0, steppingDelta=0, defVal=0, capsFlag=0;
|
long minVal=0, maxVal=0, steppingDelta=0, defVal=0, capsFlag=0;
|
||||||
check("IAMVideoProcAmp::GetRange", const_cast<uvc::device &>(device).am_video_proc_amp->GetRange(get_cid(option), &minVal, &maxVal, &steppingDelta, &defVal, &capsFlag));
|
check("IAMVideoProcAmp::GetRange", const_cast<uvc::device &>(device).am_video_proc_amp->GetRange(get_cid(option), &minVal, &maxVal, &steppingDelta, &defVal, &capsFlag));
|
||||||
|
@ -521,19 +521,22 @@ bool pu_control_range(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_pu_control(const device &device, long property, int32_t *value) {
|
void get_pu_control(const device &device, long property, int32_t *value)
|
||||||
|
{
|
||||||
long data, flags=0;
|
long data, flags=0;
|
||||||
check("IAMVideoProcAmp::Get", const_cast<uvc::device &>(device).am_video_proc_amp->Get(property, &data, &flags));
|
check("IAMVideoProcAmp::Get", const_cast<uvc::device &>(device).am_video_proc_amp->Get(property, &data, &flags));
|
||||||
*value = data;
|
*value = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_pu_control(const device &device, long property, int32_t *value) {
|
void set_pu_control(const device &device, long property, int32_t *value)
|
||||||
|
{
|
||||||
long data = *value;
|
long data = *value;
|
||||||
check("IAMVideoProcAmp::Set", const_cast<uvc::device &>(device).am_video_proc_amp->Set(property, data, VideoProcAmp_Flags_Auto));
|
check("IAMVideoProcAmp::Set", const_cast<uvc::device &>(device).am_video_proc_amp->Set(property, data, VideoProcAmp_Flags_Auto));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pu_control_query(
|
bool pu_control_query(
|
||||||
const device &device, Option option, pu_query query, int32_t *value) {
|
const device &device, Option option, pu_query query, int32_t *value)
|
||||||
|
{
|
||||||
CHECK_NOTNULL(value);
|
CHECK_NOTNULL(value);
|
||||||
const_cast<uvc::device &>(device).get_media_source();
|
const_cast<uvc::device &>(device).get_media_source();
|
||||||
switch (query) {
|
switch (query) {
|
||||||
|
@ -582,7 +585,6 @@ void get_extension_control_range(const device &device, const xu &xu, uint8_t sel
|
||||||
|
|
||||||
KSPROPERTY_DESCRIPTION description;
|
KSPROPERTY_DESCRIPTION description;
|
||||||
unsigned long bytes_received = 0;
|
unsigned long bytes_received = 0;
|
||||||
std::cout << "query" << std::endl;
|
|
||||||
check("IKsControl::KsProperty", ks_control->KsProperty(
|
check("IKsControl::KsProperty", ks_control->KsProperty(
|
||||||
(PKSPROPERTY)&node,
|
(PKSPROPERTY)&node,
|
||||||
sizeof(node),
|
sizeof(node),
|
||||||
|
@ -600,7 +602,9 @@ void get_extension_control_range(const device &device, const xu &xu, uint8_t sel
|
||||||
size,
|
size,
|
||||||
&bytes_received));
|
&bytes_received));
|
||||||
|
|
||||||
if (bytes_received != size) { throw std::runtime_error("wrong data"); }
|
if (bytes_received != size) {
|
||||||
|
throw std::runtime_error("wrong data");
|
||||||
|
}
|
||||||
|
|
||||||
BYTE * pRangeValues = buffer.data() + sizeof(KSPROPERTY_MEMBERSHEADER) + sizeof(KSPROPERTY_DESCRIPTION);
|
BYTE * pRangeValues = buffer.data() + sizeof(KSPROPERTY_MEMBERSHEADER) + sizeof(KSPROPERTY_DESCRIPTION);
|
||||||
* data = (uint8_t)*(pRangeValues + offset);
|
* data = (uint8_t)*(pRangeValues + offset);
|
||||||
|
@ -609,7 +613,8 @@ void get_extension_control_range(const device &device, const xu &xu, uint8_t sel
|
||||||
|
|
||||||
bool xu_control_query(
|
bool xu_control_query(
|
||||||
const device &device, const xu &xu, uint8_t selector, xu_query query,
|
const device &device, const xu &xu, uint8_t selector, xu_query query,
|
||||||
uint16_t size, uint8_t *data) {
|
uint16_t size, uint8_t *data)
|
||||||
|
{
|
||||||
CHECK_NOTNULL(data);
|
CHECK_NOTNULL(data);
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
int range_offset = sizeof(KSPROPERTY_MEMBERSHEADER) + sizeof(KSPROPERTY_DESCRIPTION);
|
int range_offset = sizeof(KSPROPERTY_MEMBERSHEADER) + sizeof(KSPROPERTY_DESCRIPTION);
|
||||||
|
@ -621,14 +626,11 @@ bool xu_control_query(
|
||||||
node.Property.Id = selector;
|
node.Property.Id = selector;
|
||||||
node.NodeId = xu.node;
|
node.NodeId = xu.node;
|
||||||
unsigned long bytes_received = 0;
|
unsigned long bytes_received = 0;
|
||||||
std::cout << "selector: " << selector << std::endl;
|
|
||||||
switch (query) {
|
switch (query) {
|
||||||
case XU_QUERY_SET:
|
case XU_QUERY_SET:
|
||||||
std::cout << "XU_QUERY_SET" << std::endl;
|
|
||||||
node.Property.Flags = KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_TOPOLOGY;
|
node.Property.Flags = KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_TOPOLOGY;
|
||||||
break;
|
break;
|
||||||
case XU_QUERY_GET:
|
case XU_QUERY_GET:
|
||||||
std::cout << "XU_QUERY_GET" << std::endl;
|
|
||||||
node.Property.Flags = KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_TOPOLOGY;
|
node.Property.Flags = KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_TOPOLOGY;
|
||||||
break;
|
break;
|
||||||
case XU_QUERY_MIN:
|
case XU_QUERY_MIN:
|
||||||
|
@ -637,12 +639,12 @@ bool xu_control_query(
|
||||||
get_extension_control_range(device, xu, selector, query, data);
|
get_extension_control_range(device, xu, selector, query, data);
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
LOG(ERROR) << "xu range query request code is unaccepted";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::cout << "set & get" << std::endl;
|
|
||||||
check("IKsControl::KsProperty", ks_control->KsProperty((PKSPROPERTY)&node, sizeof(node), reinterpret_cast<void *>(data), size, &bytes_received));
|
check("IKsControl::KsProperty", ks_control->KsProperty((PKSPROPERTY)&node, sizeof(node), reinterpret_cast<void *>(data), size, &bytes_received));
|
||||||
if (bytes_received != size) { throw_error() << "wrong data"; }
|
if (bytes_received != size) {
|
||||||
|
throw_error() << "wrong data";
|
||||||
|
}
|
||||||
|
|
||||||
*data = (int)*(data+offset);
|
*data = (int)*(data+offset);
|
||||||
|
|
||||||
|
@ -651,8 +653,7 @@ bool xu_control_query(
|
||||||
|
|
||||||
void set_device_mode(device & device, int width, int height, int fourcc, int fps, video_channel_callback callback)
|
void set_device_mode(device & device, int width, int height, int fourcc, int fps, video_channel_callback callback)
|
||||||
{
|
{
|
||||||
if(!device.mf_source_reader)
|
if(!device.mf_source_reader) {
|
||||||
{
|
|
||||||
com_ptr<IMFAttributes> pAttributes;
|
com_ptr<IMFAttributes> pAttributes;
|
||||||
check("MFCreateAttributes", MFCreateAttributes(&pAttributes, 1));
|
check("MFCreateAttributes", MFCreateAttributes(&pAttributes, 1));
|
||||||
check("IMFAttributes::SetUnknown", pAttributes->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, static_cast<IUnknown *>(device.reader_callback)));
|
check("IMFAttributes::SetUnknown", pAttributes->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, static_cast<IUnknown *>(device.reader_callback)));
|
||||||
|
@ -661,14 +662,14 @@ void set_device_mode(device & device, int width, int height, int fourcc, int fps
|
||||||
|
|
||||||
if (fourcc_map.count(fourcc)) fourcc = fourcc_map.at(fourcc);
|
if (fourcc_map.count(fourcc)) fourcc = fourcc_map.at(fourcc);
|
||||||
|
|
||||||
for (DWORD j = 0; ; j++)
|
for (DWORD j = 0; ; j++) {
|
||||||
{
|
|
||||||
com_ptr<IMFMediaType> media_type;
|
com_ptr<IMFMediaType> media_type;
|
||||||
HRESULT hr = device.mf_source_reader->GetNativeMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, j, &media_type);
|
HRESULT hr = device.mf_source_reader->GetNativeMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, j, &media_type);
|
||||||
if (hr == MF_E_NO_MORE_TYPES) break;
|
if (hr == MF_E_NO_MORE_TYPES) break;
|
||||||
check("IMFSourceReader::GetNativeMediaType", hr);
|
check("IMFSourceReader::GetNativeMediaType", hr);
|
||||||
|
|
||||||
UINT32 uvc_width, uvc_height, uvc_fps_num, uvc_fps_denom; GUID subtype;
|
UINT32 uvc_width, uvc_height, uvc_fps_num, uvc_fps_denom;
|
||||||
|
GUID subtype;
|
||||||
check("MFGetAttributeSize", MFGetAttributeSize(media_type, MF_MT_FRAME_SIZE, &uvc_width, &uvc_height));
|
check("MFGetAttributeSize", MFGetAttributeSize(media_type, MF_MT_FRAME_SIZE, &uvc_width, &uvc_height));
|
||||||
if(uvc_width != width || uvc_height != height) continue;
|
if(uvc_width != width || uvc_height != height) continue;
|
||||||
|
|
||||||
|
@ -686,8 +687,14 @@ void set_device_mode(device & device, int width, int height, int fourcc, int fps
|
||||||
throw_error() << "no matching media type for pixel format " << std::hex << fourcc;
|
throw_error() << "no matching media type for pixel format " << std::hex << fourcc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_streaming(device & device, int num_transfer_bufs) { device.start_streaming(); }
|
void start_streaming(device & device, int num_transfer_bufs)
|
||||||
void stop_streaming(device & device) { device.stop_streaming(); }
|
{
|
||||||
|
device.start_streaming();
|
||||||
|
}
|
||||||
|
void stop_streaming(device & device)
|
||||||
|
{
|
||||||
|
device.stop_streaming();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace uvc
|
} // namespace uvc
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user