Update uvc-wmf.cc & add xu_control_range
This commit is contained in:
parent
f17eff7e01
commit
3673324079
|
@ -837,6 +837,18 @@ bool Channels::PuControlQuery(
|
|||
return uvc::pu_control_query(*device_, option, query, value);
|
||||
}
|
||||
|
||||
bool Channels::XuControlRange(
|
||||
channel_t channel, int32_t *min, int32_t *max, int32_t *def) const {
|
||||
return XuControlRange(mynteye_xu, channel >> 8, min, max, def);
|
||||
}
|
||||
|
||||
bool Channels::XuControlRange(
|
||||
const uvc::xu &xu, uint8_t selector, int32_t *min, int32_t *max,
|
||||
int32_t *def) const {
|
||||
CHECK_NOTNULL(device_);
|
||||
return uvc::xu_control_range(*device_, xu, selector, min, max, def);
|
||||
}
|
||||
|
||||
bool Channels::XuControlQuery(
|
||||
channel_t channel, uvc::xu_query query, uint16_t size,
|
||||
uint8_t *data) const {
|
||||
|
@ -977,26 +989,11 @@ Channels::control_info_t Channels::XuControlInfo(Option option) const {
|
|||
return {0, 0, 0};
|
||||
}
|
||||
|
||||
control_info_t info{0, 0, 0};
|
||||
|
||||
data[0] = id & 0xFF;
|
||||
if (XuCamCtrlQuery(uvc::XU_QUERY_MIN, 3, data)) {
|
||||
info.min = (data[1] << 8) | (data[2]);
|
||||
} else {
|
||||
LOG(WARNING) << "Get XuControlInfo.min of " << option << " failed";
|
||||
int32_t min = 0, max = 0, def = 0;
|
||||
if (!XuControlRange(CHANNEL_CAM_CTRL, &min, &max, &def)) {
|
||||
LOG(WARNING) << "Get XuControlInfo of " << option << " failed";
|
||||
}
|
||||
if (XuCamCtrlQuery(uvc::XU_QUERY_MAX, 3, data)) {
|
||||
info.max = (data[1] << 8) | (data[2]);
|
||||
} else {
|
||||
LOG(WARNING) << "Get XuControlInfo.max of " << option << " failed";
|
||||
}
|
||||
if (XuCamCtrlQuery(uvc::XU_QUERY_DEF, 3, data)) {
|
||||
info.def = (data[1] << 8) | (data[2]);
|
||||
} else {
|
||||
LOG(WARNING) << "Get XuControlInfo.def of " << option << " failed";
|
||||
}
|
||||
|
||||
return info;
|
||||
return {min, max, def};
|
||||
}
|
||||
|
||||
MYNTEYE_END_NAMESPACE
|
||||
|
|
|
@ -97,6 +97,12 @@ class MYNTEYE_API Channels {
|
|||
Option option, int32_t *min, int32_t *max, int32_t *def) const;
|
||||
bool PuControlQuery(Option option, uvc::pu_query query, int32_t *value) const;
|
||||
|
||||
bool XuControlRange(
|
||||
channel_t channel, int32_t *min, int32_t *max, int32_t *def) const;
|
||||
bool XuControlRange(
|
||||
const uvc::xu &xu, uint8_t selector, int32_t *min, int32_t *max,
|
||||
int32_t *def) const;
|
||||
|
||||
bool XuControlQuery(
|
||||
channel_t channel, uvc::xu_query query, uint16_t size,
|
||||
uint8_t *data) const;
|
||||
|
|
10
src/uvc/README.md
Normal file
10
src/uvc/README.md
Normal file
|
@ -0,0 +1,10 @@
|
|||
|
||||
## `uvc-v4l2.cc`
|
||||
|
||||
* [Linux Media Subsystem Documentation](https://www.kernel.org/doc/html/latest/media/index.html)
|
||||
* [The Linux USB Video Class (UVC) driver](https://www.kernel.org/doc/html/latest/media/v4l-drivers/uvcvideo.html)
|
||||
|
||||
## `uvc-wmf.cc`
|
||||
|
||||
* [Media Foundation](https://msdn.microsoft.com/en-us/library/ms694197(VS.85).aspx)
|
||||
* [USB Video Class Driver](https://docs.microsoft.com/en-us/windows-hardware/drivers/stream/usb-video-class-driver)
|
|
@ -131,6 +131,19 @@ bool pu_control_query(
|
|||
return false;
|
||||
}
|
||||
|
||||
bool xu_control_range(
|
||||
const device &device, const xu &xu, uint8_t selector, int32_t *min,
|
||||
int32_t *max, int32_t *def) {
|
||||
// TODO(JohnZhao)
|
||||
UNUSED(device)
|
||||
UNUSED(xu)
|
||||
UNUSED(selector)
|
||||
UNUSED(min)
|
||||
UNUSED(max)
|
||||
UNUSED(def)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool xu_control_query(
|
||||
const device &device, const xu &xu, uint8_t selector, xu_query query,
|
||||
uint16_t size, uint8_t *data) {
|
||||
|
|
|
@ -491,6 +491,32 @@ bool pu_control_query(
|
|||
return device.pu_control_query(get_cid(option), code, value);
|
||||
}
|
||||
|
||||
bool xu_control_range(
|
||||
const device &device, const xu &xu, uint8_t selector, int32_t *min,
|
||||
int32_t *max, int32_t *def) {
|
||||
bool ret = true;
|
||||
std::uint8_t data[3]{};
|
||||
if (xu_control_query(device, xu, selcetor, XU_QUERY_MIN, 3, data)) {
|
||||
*min = (data[1] << 8) | (data[2]);
|
||||
} else {
|
||||
LOG(WARNING) << "xu_control_range query min failed";
|
||||
ret = false;
|
||||
}
|
||||
if (xu_control_query(device, xu, selcetor, XU_QUERY_MAX, 3, data)) {
|
||||
*max = (data[1] << 8) | (data[2]);
|
||||
} else {
|
||||
LOG(WARNING) << "xu_control_range query max failed";
|
||||
ret = false;
|
||||
}
|
||||
if (xu_control_query(device, xu, selcetor, XU_QUERY_DEF, 3, data)) {
|
||||
*def = (data[1] << 8) | (data[2]);
|
||||
} else {
|
||||
LOG(WARNING) << "xu_control_range query def failed";
|
||||
ret = false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool xu_control_query(
|
||||
const device &device, const xu &xu, uint8_t selector, xu_query query,
|
||||
uint16_t size, uint8_t *data) {
|
||||
|
|
|
@ -154,19 +154,21 @@ std::vector<std::string> tokenize(std::string string, char separator) {
|
|||
}
|
||||
}
|
||||
|
||||
static void print_guid(const char *call, GUID guid) {
|
||||
/*
|
||||
static void print_guid(const char *call, int i, GUID guid) {
|
||||
std::ostringstream ss;
|
||||
ss << call << ":";
|
||||
ss << " Data1: " << std::hex << guid.Data1 << ",";
|
||||
ss << " Data2: " << std::hex << guid.Data2 << ",";
|
||||
ss << " Data3: " << std::hex << guid.Data3 << ",";
|
||||
ss << " Data4: [ ";
|
||||
ss << call << "(" << i << ") = ";
|
||||
ss << "Data1: " << std::hex << guid.Data1 << ", ";
|
||||
ss << "Data2: " << std::hex << guid.Data2 << ", ";
|
||||
ss << "Data3: " << std::hex << guid.Data3 << ", ";
|
||||
ss << "Data4: [ ";
|
||||
for (int j = 0; j < 8; j++) {
|
||||
ss << std::hex << (int)guid.Data4[j] << " ";
|
||||
}
|
||||
ss << "]";
|
||||
LOG(INFO) << ss.str();
|
||||
}
|
||||
*/
|
||||
|
||||
bool parse_usb_path(int &vid, int &pid, int &mi, std::string &unique_id, const std::string &path) {
|
||||
auto name = path;
|
||||
|
@ -322,7 +324,7 @@ struct device {
|
|||
check("get_NumNodes", ks_topology_info->get_NumNodes(&numberOfNodes));
|
||||
for (int i = 0; i < numberOfNodes; i++) {
|
||||
check("get_NodeType", ks_topology_info->get_NodeType(i, &node_type));
|
||||
print_guid("node_type", node_type);
|
||||
print_guid("node_type", i, node_type);
|
||||
}
|
||||
*/
|
||||
check("get_NodeType", ks_topology_info->get_NodeType(xu.node, &node_type));
|
||||
|
@ -507,22 +509,28 @@ bool pu_control_range(
|
|||
int32_t *def) {
|
||||
const_cast<uvc::device &>(device).get_media_source();
|
||||
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));
|
||||
if (min) *min = static_cast<int>(minVal);
|
||||
if (max) *max = static_cast<int>(maxVal);
|
||||
if (def) *def = static_cast<int>(defVal);
|
||||
return true;
|
||||
}
|
||||
|
||||
void get_pu_control(const device &device, long property, int32_t *value) {
|
||||
static void pu_control_get(const device &device, long property, int32_t *value) {
|
||||
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;
|
||||
}
|
||||
|
||||
void set_pu_control(const device &device, long property, int32_t *value) {
|
||||
static void pu_control_set(const device &device, long property, int32_t *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(
|
||||
|
@ -531,10 +539,10 @@ bool pu_control_query(
|
|||
const_cast<uvc::device &>(device).get_media_source();
|
||||
switch (query) {
|
||||
case PU_QUERY_SET:
|
||||
set_pu_control(device, get_cid(option), value);
|
||||
pu_control_set(device, get_cid(option), value);
|
||||
return true;
|
||||
case PU_QUERY_GET:
|
||||
get_pu_control(device, get_cid(option), value);
|
||||
pu_control_get(device, get_cid(option), value);
|
||||
return true;
|
||||
default:
|
||||
LOG(ERROR) << "pu_control_query request code is unaccepted";
|
||||
|
@ -542,49 +550,116 @@ bool pu_control_query(
|
|||
}
|
||||
}
|
||||
|
||||
bool xu_control_query(
|
||||
const device &device, const xu &xu, uint8_t selector, xu_query query,
|
||||
uint16_t size, uint8_t *data) {
|
||||
CHECK_NOTNULL(data);
|
||||
int offset = 0;
|
||||
int range_offset = sizeof(KSPROPERTY_MEMBERSHEADER) + sizeof(KSPROPERTY_DESCRIPTION);
|
||||
|
||||
static std::vector<BYTE> xu_control_desc(const device &device, const xu &xu, ULONG id, ULONG flags) {
|
||||
auto ks_control = const_cast<uvc::device &>(device).get_ks_control(xu);
|
||||
|
||||
KSP_NODE node;
|
||||
memset(&node, 0, sizeof(KSP_NODE));
|
||||
node.Property.Set = reinterpret_cast<const GUID &>(xu.id);
|
||||
node.Property.Id = id;
|
||||
node.Property.Flags = flags;
|
||||
node.NodeId = xu.node;
|
||||
|
||||
KSPROPERTY_DESCRIPTION description;
|
||||
ULONG bytes_received = 0;
|
||||
check("IKsControl::KsProperty", ks_control->KsProperty(
|
||||
(PKSPROPERTY)&node,
|
||||
sizeof(node),
|
||||
&description,
|
||||
sizeof(KSPROPERTY_DESCRIPTION),
|
||||
&bytes_received));
|
||||
|
||||
ULONG size = description.DescriptionSize;
|
||||
std::vector<BYTE> buffer(size);
|
||||
|
||||
check("IKsControl::KsProperty", ks_control->KsProperty(
|
||||
(PKSPROPERTY)&node,
|
||||
sizeof(node),
|
||||
buffer.data(),
|
||||
size,
|
||||
&bytes_received));
|
||||
|
||||
if (bytes_received != size) { throw_error() << "wrong data"; }
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
bool xu_control_range(
|
||||
const device &device, const xu &xu, uint8_t selector, int32_t *min,
|
||||
int32_t *max, int32_t *def) {
|
||||
// get step, min and max values
|
||||
{
|
||||
auto &&buffer = xu_control_desc(device, xu, selector,
|
||||
KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_TOPOLOGY);
|
||||
|
||||
BYTE *values = buffer.data() + sizeof(KSPROPERTY_MEMBERSHEADER) + sizeof(KSPROPERTY_DESCRIPTION);
|
||||
|
||||
// *step = static_cast<int32_t>(*values);
|
||||
values++;
|
||||
*min = static_cast<int32_t>(*values);
|
||||
values++;
|
||||
*max = static_cast<int32_t>(*values);
|
||||
}
|
||||
// get def value
|
||||
{
|
||||
auto &&buffer = xu_control_desc(device, xu, selector,
|
||||
KSPROPERTY_TYPE_DEFAULTVALUES | KSPROPERTY_TYPE_TOPOLOGY);
|
||||
|
||||
BYTE *values = buffer.data() + sizeof(KSPROPERTY_MEMBERSHEADER) + sizeof(KSPROPERTY_DESCRIPTION);
|
||||
|
||||
*def = static_cast<int32_t>(*values);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void xu_control_get(const device &device, const xu &xu, uint8_t selector, int len, void *data) {
|
||||
auto &&ks_control = const_cast<uvc::device &>(device).get_ks_control(xu);
|
||||
|
||||
KSP_NODE node;
|
||||
memset(&node, 0, sizeof(KSP_NODE));
|
||||
node.Property.Set = reinterpret_cast<const GUID &>(xu.id);
|
||||
node.Property.Id = selector;
|
||||
node.Property.Flags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_TOPOLOGY;
|
||||
node.NodeId = xu.node;
|
||||
unsigned long bytes_received = 0;
|
||||
|
||||
ULONG bytes_received = 0;
|
||||
check("IKsControl::KsProperty", ks_control->KsProperty(
|
||||
(PKSPROPERTY)&node, sizeof(node), data, len, &bytes_received));
|
||||
|
||||
if (bytes_received != len)
|
||||
throw_error() << "xu_control_get did not return enough data";
|
||||
}
|
||||
|
||||
static void xu_control_set(const device &device, const xu &xu, uint8_t selector, int len, void *data) {
|
||||
auto &&ks_control = const_cast<uvc::device &>(device).get_ks_control(xu);
|
||||
|
||||
KSP_NODE node;
|
||||
memset(&node, 0, sizeof(KSP_NODE));
|
||||
node.Property.Set = reinterpret_cast<const GUID &>(xu.id);
|
||||
node.Property.Id = selector;
|
||||
node.Property.Flags = KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_TOPOLOGY;
|
||||
node.NodeId = xu.node;
|
||||
|
||||
ULONG bytes_received = 0;
|
||||
check("IKsControl::KsProperty", ks_control->KsProperty(
|
||||
(PKSPROPERTY)&node, sizeof(node), data, len, &bytes_received));
|
||||
}
|
||||
|
||||
bool xu_control_query(
|
||||
const device &device, const xu &xu, uint8_t selector, xu_query query,
|
||||
uint16_t size, uint8_t *data) {
|
||||
CHECK_NOTNULL(data);
|
||||
switch (query) {
|
||||
case XU_QUERY_SET:
|
||||
node.Property.Flags = KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_TOPOLOGY;
|
||||
break;
|
||||
xu_control_set(device, xu, selector, size, data);
|
||||
return true;
|
||||
case XU_QUERY_GET:
|
||||
node.Property.Flags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_TOPOLOGY;
|
||||
break;
|
||||
case XU_QUERY_MIN:
|
||||
offset = 1;
|
||||
node.Property.Flags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_TOPOLOGY;
|
||||
break;
|
||||
case XU_QUERY_MAX:
|
||||
offset = 2;
|
||||
node.Property.Flags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_TOPOLOGY;
|
||||
break;
|
||||
case XU_QUERY_DEF:
|
||||
node.Property.Flags = KSPROPERTY_TYPE_DEFAULTVALUES | KSPROPERTY_TYPE_TOPOLOGY;
|
||||
break;
|
||||
xu_control_get(device, xu, selector, size, data);
|
||||
return true;
|
||||
default:
|
||||
LOG(ERROR) << "xu_control_query request code is unaccepted";
|
||||
return false;
|
||||
}
|
||||
check("IKsControl::KsProperty", ks_control->KsProperty((PKSPROPERTY)&node, sizeof(node), data, size, &bytes_received));
|
||||
if (bytes_received != size) {
|
||||
throw_error() << "wrong data";
|
||||
}
|
||||
|
||||
*data = (int)*(data + offset);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void set_device_mode(device &device, int width, int height, int fourcc, int fps, video_channel_callback callback) {
|
||||
|
|
|
@ -72,7 +72,10 @@ MYNTEYE_API bool pu_control_query(
|
|||
const device &device, Option option, pu_query query, int32_t *value);
|
||||
|
||||
// Access XU (Extension Unit) controls
|
||||
MYNTEYE_API bool xu_control_query(
|
||||
MYNTEYE_API bool xu_control_range(
|
||||
const device &device, const xu &xu, uint8_t selector, int32_t *min,
|
||||
int32_t *max, int32_t *def);
|
||||
MYNTEYE_API bool xu_control_query( // XU_QUERY_SET, XU_QUERY_GET
|
||||
const device &device, const xu &xu, uint8_t selector, xu_query query,
|
||||
uint16_t size, uint8_t *data);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user