Fix capture video stream in uvc-wmf
This commit is contained in:
parent
ca0ae22aea
commit
58fdc4c01b
|
@ -14,8 +14,17 @@
|
||||||
|
|
||||||
struct frame {
|
struct frame {
|
||||||
const void *data = nullptr;
|
const void *data = nullptr;
|
||||||
|
std::function<void()> continuation = nullptr;
|
||||||
|
frame() {
|
||||||
|
// VLOG(2) << __func__;
|
||||||
|
}
|
||||||
~frame() {
|
~frame() {
|
||||||
|
// VLOG(2) << __func__;
|
||||||
data = nullptr;
|
data = nullptr;
|
||||||
|
if (continuation) {
|
||||||
|
continuation();
|
||||||
|
continuation = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -28,7 +37,11 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
auto context = uvc::create_context();
|
auto context = uvc::create_context();
|
||||||
auto devices = uvc::query_devices(context);
|
auto devices = uvc::query_devices(context);
|
||||||
LOG_IF(FATAL, devices.size() <= 0) << "No devices :(";
|
if (devices.size() <= 0) {
|
||||||
|
LOG(ERROR) << "No devices :(";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto &&device : devices) {
|
for (auto &&device : devices) {
|
||||||
auto vid = uvc::get_vendor_id(*device);
|
auto vid = uvc::get_vendor_id(*device);
|
||||||
// auto pid = uvc::get_product_id(*device);
|
// auto pid = uvc::get_product_id(*device);
|
||||||
|
@ -41,7 +54,10 @@ int main(int argc, char *argv[]) {
|
||||||
// std::string dashes(80, '-');
|
// std::string dashes(80, '-');
|
||||||
|
|
||||||
size_t n = mynteye_devices.size();
|
size_t n = mynteye_devices.size();
|
||||||
LOG_IF(FATAL, n <= 0) << "No MYNT EYE devices :(";
|
if (n <= 0) {
|
||||||
|
LOG(ERROR) << "No MYNT EYE devices :(";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
LOG(INFO) << "MYNT EYE devices: ";
|
LOG(INFO) << "MYNT EYE devices: ";
|
||||||
for (size_t i = 0; i < n; i++) {
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
@ -74,18 +90,21 @@ int main(int argc, char *argv[]) {
|
||||||
std::mutex mtx;
|
std::mutex mtx;
|
||||||
std::condition_variable cv;
|
std::condition_variable cv;
|
||||||
|
|
||||||
std::vector<frame> frames;
|
std::shared_ptr<frame> frame = nullptr;
|
||||||
const auto frame_ready = [&frames]() { return !frames.empty(); };
|
const auto frame_ready = [&frame]() { return frame != nullptr; };
|
||||||
const auto frame_empty = [&frames]() { return frames.empty(); };
|
const auto frame_empty = [&frame]() { return frame == nullptr; };
|
||||||
|
|
||||||
uvc::set_device_mode(
|
uvc::set_device_mode(
|
||||||
*device, 752, 480, static_cast<int>(Format::YUYV), 25,
|
*device, 752, 480, static_cast<int>(Format::YUYV), 25,
|
||||||
[&mtx, &cv, &frames, &frame_ready](const void *data) {
|
[&mtx, &cv, &frame, &frame_ready](
|
||||||
|
const void *data, std::function<void()> continuation) {
|
||||||
// reinterpret_cast<const std::uint8_t *>(data);
|
// reinterpret_cast<const std::uint8_t *>(data);
|
||||||
std::unique_lock<std::mutex> lock(mtx);
|
std::unique_lock<std::mutex> lock(mtx);
|
||||||
frame frame;
|
if (frame == nullptr) {
|
||||||
frame.data = data; // not copy
|
frame = std::make_shared<struct frame>();
|
||||||
frames.push_back(frame);
|
}
|
||||||
|
frame->data = data; // not copy here
|
||||||
|
frame->continuation = continuation;
|
||||||
if (frame_ready())
|
if (frame_ready())
|
||||||
cv.notify_one();
|
cv.notify_one();
|
||||||
});
|
});
|
||||||
|
@ -106,13 +125,12 @@ int main(int argc, char *argv[]) {
|
||||||
throw std::runtime_error("Timeout waiting for frame.");
|
throw std::runtime_error("Timeout waiting for frame.");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto frame = frames.back(); // only last one is valid
|
// only lastest frame is valid
|
||||||
|
cv::Mat img(480, 752, CV_8UC2, const_cast<void *>(frame->data));
|
||||||
cv::Mat img(480, 752, CV_8UC2, const_cast<void *>(frame.data));
|
|
||||||
cv::cvtColor(img, img, cv::COLOR_YUV2BGR_YUY2);
|
cv::cvtColor(img, img, cv::COLOR_YUV2BGR_YUY2);
|
||||||
cv::imshow("frame", img);
|
cv::imshow("frame", img);
|
||||||
|
|
||||||
frames.clear();
|
frame = nullptr;
|
||||||
|
|
||||||
char key = static_cast<char>(cv::waitKey(1));
|
char key = static_cast<char>(cv::waitKey(1));
|
||||||
if (key == 27 || key == 'q' || key == 'Q') { // ESC/Q
|
if (key == 27 || key == 'q' || key == 'Q') { // ESC/Q
|
||||||
|
|
|
@ -376,7 +376,7 @@ void Device::StartVideoStreaming() {
|
||||||
uvc::set_device_mode(
|
uvc::set_device_mode(
|
||||||
*device_, stream_request.width, stream_request.height,
|
*device_, stream_request.width, stream_request.height,
|
||||||
static_cast<int>(stream_request.format), stream_request.fps,
|
static_cast<int>(stream_request.format), stream_request.fps,
|
||||||
[this](const void *data) {
|
[this](const void *data, std::function<void()> continuation) {
|
||||||
// drop the first stereo stream data
|
// drop the first stereo stream data
|
||||||
static std::uint8_t drop_count = 1;
|
static std::uint8_t drop_count = 1;
|
||||||
if (drop_count > 0) {
|
if (drop_count > 0) {
|
||||||
|
@ -385,6 +385,7 @@ void Device::StartVideoStreaming() {
|
||||||
}
|
}
|
||||||
std::lock_guard<std::mutex> _(mtx_streams_);
|
std::lock_guard<std::mutex> _(mtx_streams_);
|
||||||
streams_->PushStream(Capabilities::STEREO, data);
|
streams_->PushStream(Capabilities::STEREO, data);
|
||||||
|
continuation();
|
||||||
if (HasStreamCallback(Stream::LEFT)) {
|
if (HasStreamCallback(Stream::LEFT)) {
|
||||||
auto &&stream_datas = streams_->stream_datas(Stream::LEFT);
|
auto &&stream_datas = streams_->stream_datas(Stream::LEFT);
|
||||||
if (stream_datas.size() > 0) {
|
if (stream_datas.size() > 0) {
|
||||||
|
|
|
@ -49,15 +49,12 @@
|
||||||
|
|
||||||
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 }, // 'VYUY' => '2YUY'
|
||||||
#define LOG_ERROR(severity, str) \
|
{ 0x59555956, 0x59555932 } // 'YUYV' => 'YUY2'
|
||||||
do { \
|
};
|
||||||
LOG(severity) << str << " error " << errno << ", " << strerror(errno); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
struct throw_error {
|
struct throw_error {
|
||||||
throw_error() = default;
|
throw_error() = default;
|
||||||
|
@ -68,7 +65,6 @@ struct throw_error {
|
||||||
|
|
||||||
~throw_error() noexcept(false) {
|
~throw_error() noexcept(false) {
|
||||||
throw std::runtime_error(ss.str());
|
throw std::runtime_error(ss.str());
|
||||||
// throw device_error(ss.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
|
@ -80,8 +76,16 @@ struct throw_error {
|
||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T> class com_ptr
|
static void check(const char *call, HRESULT hr) {
|
||||||
{
|
if (FAILED(hr)) {
|
||||||
|
throw_error() << call << "(...) returned 0x" << std::hex
|
||||||
|
<< static_cast<uint32_t>(hr);
|
||||||
|
} else {
|
||||||
|
LOG(INFO) << call << " SUCCESSED";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
@ -136,14 +140,6 @@ static std::string win_to_utf(const WCHAR * s)
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check(const char *call, HRESULT hr)
|
|
||||||
{
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
throw_error() << call << "(...) returned 0x" << std::hex << (uint32_t)hr;
|
|
||||||
}
|
|
||||||
LOG(INFO) << call << " SUCCESSED";
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
||||||
|
@ -178,29 +174,29 @@ bool parse_usb_path(int & vid, int & pid, int & mi, std::string & unique_id, con
|
||||||
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];
|
||||||
|
@ -216,23 +212,23 @@ bool parse_usb_path_from_device_id(int & vid, int & pid, int & mi, std::string &
|
||||||
|
|
||||||
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];
|
||||||
|
@ -278,7 +274,7 @@ public:
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,8 +299,9 @@ 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), unique_id(move(unique_id)), 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() {
|
~device() {
|
||||||
stop_streaming();
|
stop_streaming();
|
||||||
|
@ -312,7 +309,6 @@ struct device {
|
||||||
|
|
||||||
|
|
||||||
IKsControl * get_ks_control(const uvc::xu & xu) {
|
IKsControl * get_ks_control(const uvc::xu & xu) {
|
||||||
|
|
||||||
auto it = ks_controls.find(xu.node);
|
auto it = ks_controls.find(xu.node);
|
||||||
if(it != end(ks_controls)) return it->second;
|
if(it != end(ks_controls)) return it->second;
|
||||||
|
|
||||||
|
@ -346,18 +342,18 @@ struct device {
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,7 +361,7 @@ 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());
|
||||||
}
|
}
|
||||||
|
@ -397,7 +393,7 @@ HRESULT reader_callback::OnReadSample(HRESULT hrStatus, DWORD dwStreamIndex, DWO
|
||||||
auto continuation = [buffer, this]() {
|
auto continuation = [buffer, this]() {
|
||||||
buffer->Unlock();
|
buffer->Unlock();
|
||||||
};
|
};
|
||||||
owner_ptr->callback(byte_buffer);
|
owner_ptr->callback(byte_buffer, continuation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -405,26 +401,13 @@ HRESULT reader_callback::OnReadSample(HRESULT hrStatus, DWORD dwStreamIndex, DWO
|
||||||
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) << "ReadSample returned MF_E_INVALIDREQUEST"; break;
|
||||||
case MF_E_INVALIDREQUEST:
|
case MF_E_INVALIDSTREAMNUMBER: LOG(ERROR) << "ReadSample returned MF_E_INVALIDSTREAMNUMBER"; break;
|
||||||
LOG_ERROR(WARNING,"ReadSample returned MF_E_INVALIDREQUEST");
|
case MF_E_NOTACCEPTING: LOG(ERROR) << "ReadSample returned MF_E_NOTACCEPTING"; break;
|
||||||
break;
|
case E_INVALIDARG: LOG(ERROR) << "ReadSample returned E_INVALIDARG"; break;
|
||||||
case MF_E_INVALIDSTREAMNUMBER:
|
case MF_E_VIDEO_RECORDING_DEVICE_INVALIDATED: LOG(ERROR) << "ReadSample returned MF_E_VIDEO_RECORDING_DEVICE_INVALIDATED"; break;
|
||||||
LOG_ERROR(WARNING,"ReadSample returned MF_E_INVALIDSTREAMNUMBER");
|
default: LOG(ERROR) << "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;
|
||||||
}
|
}
|
||||||
|
@ -441,11 +424,12 @@ std::vector<std::shared_ptr<device>> query_devices(std::shared_ptr<context> cont
|
||||||
{
|
{
|
||||||
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));
|
||||||
|
|
||||||
IMFActivate **ppDevices;
|
IMFActivate **ppDevices;
|
||||||
UINT32 numDevices;
|
UINT32 numDevices;
|
||||||
check("MFEnumDeviceSources",MFEnumDeviceSources(pAttributes, &ppDevices, &numDevices));
|
check("MFEnumDeviceSources", MFEnumDeviceSources(pAttributes, &ppDevices, &numDevices));
|
||||||
|
|
||||||
std::vector<std::shared_ptr<device>> devices;
|
std::vector<std::shared_ptr<device>> devices;
|
||||||
for (UINT32 i = 0; i < numDevices; ++i) {
|
for (UINT32 i = 0; i < numDevices; ++i) {
|
||||||
|
@ -490,7 +474,6 @@ std::vector<std::shared_ptr<device>> query_devices(std::shared_ptr<context> cont
|
||||||
dev->mf_activate = pDevice;
|
dev->mf_activate = pDevice;
|
||||||
dev->vid = vid;
|
dev->vid = vid;
|
||||||
dev->pid = pid;
|
dev->pid = pid;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CoTaskMemFree(ppDevices);
|
CoTaskMemFree(ppDevices);
|
||||||
|
@ -682,14 +665,14 @@ 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)));
|
||||||
check("MFCreateSourceReaderFromMediaSource", MFCreateSourceReaderFromMediaSource(device.get_media_source(), pAttributes, &device.mf_source_reader));
|
check("MFCreateSourceReaderFromMediaSource", MFCreateSourceReaderFromMediaSource(device.get_media_source(), pAttributes, &device.mf_source_reader));
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
@ -700,13 +683,15 @@ void set_device_mode(device & device, int width, int height, int fourcc, int fps
|
||||||
UINT32 uvc_width, uvc_height, uvc_fps_num, uvc_fps_denom;
|
UINT32 uvc_width, uvc_height, uvc_fps_num, uvc_fps_denom;
|
||||||
GUID subtype;
|
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;
|
||||||
|
|
||||||
check("IMFMediaType::GetGUID", media_type->GetGUID(MF_MT_SUBTYPE, &subtype));
|
check("IMFMediaType::GetGUID", media_type->GetGUID(MF_MT_SUBTYPE, &subtype));
|
||||||
if(subtype.Data1 != fourcc) continue;
|
if (subtype.Data1 != fourcc) continue;
|
||||||
|
|
||||||
check("MFGetAttributeRatio", MFGetAttributeRatio(media_type, MF_MT_FRAME_RATE, &uvc_fps_num, &uvc_fps_denom));
|
check("MFGetAttributeRatio", MFGetAttributeRatio(media_type, MF_MT_FRAME_RATE, &uvc_fps_num, &uvc_fps_denom));
|
||||||
if(uvc_fps_denom == 0) continue;
|
if (uvc_fps_denom == 0) continue;
|
||||||
|
//int uvc_fps = uvc_fps_num / uvc_fps_denom;
|
||||||
|
//LOG(INFO) << "uvc_fps: " << uvc_fps;
|
||||||
|
|
||||||
check("IMFSourceReader::SetCurrentMediaType", device.mf_source_reader->SetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, NULL, media_type));
|
check("IMFSourceReader::SetCurrentMediaType", device.mf_source_reader->SetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, NULL, media_type));
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,11 @@ typedef enum pu_query {
|
||||||
PU_QUERY_LAST
|
PU_QUERY_LAST
|
||||||
} pu_query;
|
} pu_query;
|
||||||
|
|
||||||
struct guid { uint32_t data1; uint16_t data2, data3; uint8_t data4[8]; };
|
struct MYNTEYE_API guid {
|
||||||
|
uint32_t data1;
|
||||||
|
uint16_t data2, data3;
|
||||||
|
uint8_t data4[8];
|
||||||
|
};
|
||||||
|
|
||||||
// Extension Unit
|
// Extension Unit
|
||||||
struct MYNTEYE_API xu {
|
struct MYNTEYE_API xu {
|
||||||
|
@ -73,7 +77,8 @@ MYNTEYE_API bool xu_control_query(
|
||||||
uint16_t size, uint8_t *data);
|
uint16_t size, uint8_t *data);
|
||||||
|
|
||||||
// Control streaming
|
// Control streaming
|
||||||
typedef std::function<void(const void *frame)> video_channel_callback;
|
typedef std::function<void(const void *frame,
|
||||||
|
std::function<void()> continuation)> video_channel_callback;
|
||||||
|
|
||||||
MYNTEYE_API void set_device_mode(
|
MYNTEYE_API void set_device_mode(
|
||||||
device &device, int width, int height, int fourcc, int fps, // NOLINT
|
device &device, int width, int height, int fourcc, int fps, // NOLINT
|
||||||
|
|
Loading…
Reference in New Issue
Block a user