Update uvc-wmf.cc & add xu_control_range

This commit is contained in:
John Zhao 2018-05-25 12:32:58 +08:00
parent f17eff7e01
commit 3673324079
7 changed files with 195 additions and 65 deletions

View File

@ -837,6 +837,18 @@ bool Channels::PuControlQuery(
return uvc::pu_control_query(*device_, option, query, value); 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( bool Channels::XuControlQuery(
channel_t channel, uvc::xu_query query, uint16_t size, channel_t channel, uvc::xu_query query, uint16_t size,
uint8_t *data) const { uint8_t *data) const {
@ -977,26 +989,11 @@ Channels::control_info_t Channels::XuControlInfo(Option option) const {
return {0, 0, 0}; return {0, 0, 0};
} }
control_info_t info{0, 0, 0}; int32_t min = 0, max = 0, def = 0;
if (!XuControlRange(CHANNEL_CAM_CTRL, &min, &max, &def)) {
data[0] = id & 0xFF; LOG(WARNING) << "Get XuControlInfo of " << option << " failed";
if (XuCamCtrlQuery(uvc::XU_QUERY_MIN, 3, data)) {
info.min = (data[1] << 8) | (data[2]);
} else {
LOG(WARNING) << "Get XuControlInfo.min of " << option << " failed";
} }
if (XuCamCtrlQuery(uvc::XU_QUERY_MAX, 3, data)) { return {min, max, def};
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;
} }
MYNTEYE_END_NAMESPACE MYNTEYE_END_NAMESPACE

View File

@ -97,6 +97,12 @@ class MYNTEYE_API Channels {
Option option, int32_t *min, int32_t *max, int32_t *def) const; 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 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( bool XuControlQuery(
channel_t channel, uvc::xu_query query, uint16_t size, channel_t channel, uvc::xu_query query, uint16_t size,
uint8_t *data) const; uint8_t *data) const;

10
src/uvc/README.md Normal file
View 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)

View File

@ -131,6 +131,19 @@ bool pu_control_query(
return false; 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( 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) {

View File

@ -491,6 +491,32 @@ bool pu_control_query(
return device.pu_control_query(get_cid(option), code, value); 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( 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) {

View File

@ -154,9 +154,10 @@ 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; std::ostringstream ss;
ss << call << ":"; ss << call << "(" << i << ") = ";
ss << "Data1: " << std::hex << guid.Data1 << ", "; ss << "Data1: " << std::hex << guid.Data1 << ", ";
ss << "Data2: " << std::hex << guid.Data2 << ", "; ss << "Data2: " << std::hex << guid.Data2 << ", ";
ss << "Data3: " << std::hex << guid.Data3 << ", "; ss << "Data3: " << std::hex << guid.Data3 << ", ";
@ -167,6 +168,7 @@ static void print_guid(const char *call, GUID guid) {
ss << "]"; ss << "]";
LOG(INFO) << ss.str(); LOG(INFO) << ss.str();
} }
*/
bool parse_usb_path(int &vid, int &pid, int &mi, std::string &unique_id, const std::string &path) { bool parse_usb_path(int &vid, int &pid, int &mi, std::string &unique_id, const std::string &path) {
auto name = path; auto name = path;
@ -322,7 +324,7 @@ struct device {
check("get_NumNodes", ks_topology_info->get_NumNodes(&numberOfNodes)); check("get_NumNodes", ks_topology_info->get_NumNodes(&numberOfNodes));
for (int i = 0; i < numberOfNodes; i++) { for (int i = 0; i < numberOfNodes; i++) {
check("get_NodeType", ks_topology_info->get_NodeType(i, &node_type)); 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)); check("get_NodeType", ks_topology_info->get_NodeType(xu.node, &node_type));
@ -507,22 +509,28 @@ bool pu_control_range(
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));
if (min) *min = static_cast<int>(minVal); if (min) *min = static_cast<int>(minVal);
if (max) *max = static_cast<int>(maxVal); if (max) *max = static_cast<int>(maxVal);
if (def) *def = static_cast<int>(defVal); if (def) *def = static_cast<int>(defVal);
return true; 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; 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) { static void pu_control_set(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(
@ -531,10 +539,10 @@ bool pu_control_query(
const_cast<uvc::device &>(device).get_media_source(); const_cast<uvc::device &>(device).get_media_source();
switch (query) { switch (query) {
case PU_QUERY_SET: case PU_QUERY_SET:
set_pu_control(device, get_cid(option), value); pu_control_set(device, get_cid(option), value);
return true; return true;
case PU_QUERY_GET: case PU_QUERY_GET:
get_pu_control(device, get_cid(option), value); pu_control_get(device, get_cid(option), value);
return true; return true;
default: default:
LOG(ERROR) << "pu_control_query request code is unaccepted"; LOG(ERROR) << "pu_control_query request code is unaccepted";
@ -542,49 +550,116 @@ bool pu_control_query(
} }
} }
bool xu_control_query( static std::vector<BYTE> xu_control_desc(const device &device, const xu &xu, ULONG id, ULONG flags) {
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);
auto ks_control = const_cast<uvc::device &>(device).get_ks_control(xu); 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; KSP_NODE node;
memset(&node, 0, sizeof(KSP_NODE)); memset(&node, 0, sizeof(KSP_NODE));
node.Property.Set = reinterpret_cast<const GUID &>(xu.id); node.Property.Set = reinterpret_cast<const GUID &>(xu.id);
node.Property.Id = selector; node.Property.Id = selector;
node.Property.Flags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_TOPOLOGY;
node.NodeId = xu.node; 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) { switch (query) {
case XU_QUERY_SET: case XU_QUERY_SET:
node.Property.Flags = KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_TOPOLOGY; xu_control_set(device, xu, selector, size, data);
break; return true;
case XU_QUERY_GET: case XU_QUERY_GET:
node.Property.Flags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_TOPOLOGY; xu_control_get(device, xu, selector, size, data);
break; return true;
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;
default: default:
LOG(ERROR) << "xu_control_query request code is unaccepted";
return false; 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) { void set_device_mode(device &device, int width, int height, int fourcc, int fps, video_channel_callback callback) {

View File

@ -72,7 +72,10 @@ MYNTEYE_API 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);
// Access XU (Extension Unit) controls // 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, const device &device, const xu &xu, uint8_t selector, xu_query query,
uint16_t size, uint8_t *data); uint16_t size, uint8_t *data);