I am writing a program to regulate a PTZ digicam linked through USB.
I can get entry to focus on digicam’s unique_id, and in addition different infos supplied by AVFoundation. However I do not know learn how to find my goal USB machine to ship a UVC ControlRequest.
There’s many Cameras with similar VendorID and ProductID linked at a time, so I would like a extra precise method to discover out which machine is my goal.
It seems to be that the unique_id supplied is (locationID<<32|VendorID<<16|ProductID) as hex string, however I am unsure if I can all the time assume this conduct will not change.
Is there is a doc declares how AVFoundation generate the unique_id for USB digicam, so I can assume this convert will all the time work? Or is there is a method to ship a PTZ management request to AVCaptureDevice?
https://stackoverflow.com/questions/40006908/usb-interface-of-an-avcapturedevice
I’ve seen this related query. However I am worrying that Exacting LocationID+VendorID+ProductID from unique_id looks like programming to implementation as an alternative of interface. So, if there’s some other higher method to management my digicam?
this is my instance code for getting unique_id:
//
// camera_unique_id_test.mm
// clang++ -framework AVFoundation -framework CoreMedia -framework Basis
// camera_unique_id_test.mm -o camera_unique_id_test
//
#embody
#embody
#embody
#import
#import
struct CameraInfo {
std::string uniqueId;
std::string localizedName;
std::string modelId;
bool isConnected;
bool isDefault;
};
std::vector getAllCameraDevices() {
std::vector cameras;
@autoreleasepool {
// 获取所有视频输入设备
NSArray* gadgets =
[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
// 获取默认摄像头设备
AVCaptureDevice* defaultDevice =
[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
// 遍历所有设备
for (AVCaptureDevice* machine in gadgets) {
CameraInfo data;
// 获取unique_id
data.uniqueId = std::string([device.uniqueID UTF8String]);
// 获取设备名称
data.localizedName = std::string([device.localizedName UTF8String]);
// 获取模型ID
data.modelId = std::string([device.modelID UTF8String]);
// 检查是否已连接
data.isConnected = machine.linked;
// 检查是否为默认设备
data.isDefault = [device.uniqueID isEqualToString:defaultDevice.uniqueID];
cameras.push_back(data);
}
}
return cameras;
}
int most important(int argc, char* argv[]) {
std::vector cameras = getAllCameraDevices();
for (size_t i = 0; i < cameras.dimension(); i++) {
const CameraInfo& digicam = cameras[i];
std::cout << " 设备 " << (i + 1) << ":" << std::endl;
std::cout << " unique_id: " << digicam.uniqueId << std::endl;
std::cout << " 设备名称: " << digicam.localizedName << std::endl;
std::cout << " 模型ID: " << digicam.modelId << std::endl;
std::cout << " 连接状态: "
<< (digicam.isConnected ? "已连接" : "未连接") << std::endl;
std::cout << " 是否默认: " << (digicam.isDefault ? "是" : "否")
<< std::endl;
std::cout << std::endl;
}
return 0;
}
and this is my code for UVC management:
// clang++ -framework Basis -framework IOKit uvc_test.cpp -o uvc_test
#embody
#embody
#embody
#embody
#embody
#embody
#embody
CFStringRef CreateCFStringFromIORegistryKey(io_service_t ioService,
const char* key) {
CFStringRef keyString = CFStringCreateWithCString(kCFAllocatorDefault, key,
kCFStringEncodingUTF8);
if (!keyString)
return nullptr;
CFStringRef outcome = static_cast(
IORegistryEntryCreateCFProperty(ioService, keyString, kCFAllocatorDefault,
kIORegistryIterateRecursively));
CFRelease(keyString);
return outcome;
}
std::string GetStringFromIORegistry(io_service_t ioService, const char* key) {
CFStringRef cfString = CreateCFStringFromIORegistryKey(ioService, key);
if (!cfString)
return "";
char buffer[256];
Boolean success = CFStringGetCString(cfString, buffer, sizeof(buffer),
kCFStringEncodingUTF8);
CFRelease(cfString);
return success ? std::string(buffer) : std::string("");
}
uint32_t GetUInt32FromIORegistry(io_service_t ioService, const char* key) {
CFStringRef keyString = CFStringCreateWithCString(kCFAllocatorDefault, key,
kCFStringEncodingUTF8);
if (!keyString)
return 0;
CFNumberRef quantity = static_cast(
IORegistryEntryCreateCFProperty(ioService, keyString, kCFAllocatorDefault,
kIORegistryIterateRecursively));
CFRelease(keyString);
if (!quantity)
return 0;
uint32_t worth = 0;
CFNumberGetValue(quantity, kCFNumberSInt32Type, &worth);
CFRelease(quantity);
return worth;
}
int most important() {
// Get matching dictionary for USB gadgets
CFMutableDictionaryRef matchingDict =
IOServiceMatching(kIOUSBDeviceClassName);
// Get iterator for matching providers
io_iterator_t serviceIterator;
IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict,
&serviceIterator);
// Iterate by matching gadgets
io_service_t usbService;
whereas ((usbService = IOIteratorNext(serviceIterator))) {
uint32_t locationId = GetUInt32FromIORegistry(usbService, "locationID");
uint32_t vendorId = GetUInt32FromIORegistry(usbService, "idVendor");
uint32_t productId = GetUInt32FromIORegistry(usbService, "idProduct");
IOCFPlugInInterface** plugInInterface = nullptr;
IOUSBDeviceInterface** deviceInterface = nullptr;
SInt32 rating;
// Get machine plugin interface
IOCreatePlugInInterfaceForService(usbService, kIOUSBDeviceUserClientTypeID,
kIOCFPlugInInterfaceID, &plugInInterface,
&rating);
// Get machine interface
(*plugInInterface)
->QueryInterface(plugInInterface,
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
(LPVOID*)&deviceInterface);
(*plugInInterface)->Launch(plugInInterface);
// Attempt to discover UVC management interface utilizing CreateInterfaceIterator
io_iterator_t interfaceIterator;
IOUSBFindInterfaceRequest interfaceRequest;
interfaceRequest.bInterfaceClass = kUSBVideoInterfaceClass; // 14
interfaceRequest.bInterfaceSubClass = kUSBVideoControlSubClass; // 1
interfaceRequest.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
interfaceRequest.bAlternateSetting = kIOUSBFindInterfaceDontCare;
(*deviceInterface)
->CreateInterfaceIterator(deviceInterface, &interfaceRequest,
&interfaceIterator);
(*deviceInterface)->Launch(deviceInterface);
io_service_t usbInterface = IOIteratorNext(interfaceIterator);
IOObjectRelease(interfaceIterator);
if (usbInterface) {
std::cout << "Get UVC machine with:" << std::endl;
std::cout << "locationId: " << std::hex << locationId << std::endl;
std::cout << "vendorId: " << std::hex << vendorId << std::endl;
std::cout << "productId: " << std::hex << productId << std::endl
<< std::endl;
IOObjectRelease(usbInterface);
}
IOObjectRelease(usbService);
}
IOObjectRelease(serviceIterator);
}
