Closed dhughes-xumak closed 3 years ago
Similar story here thanks for this CLI and also here first time Objective-C ... but luckily with success! (@dhughes-xumak funny the last commit is 5 years ago ... and we both struggle the same issue within a week)
We had the same issue with exposure-time-abs
and auto-exposure-mode
(issue here is the cam reports a value, that is treated as stepSize
in the process to realign it to that pattern, the value of the bitmap of exposure mode gets screwed up).
This is a patch you can apply with git apply patch.txt
to the current commit
We now added a different data type to handle the bitmap scheme (ignoring the stepsize which makes no sense for a mask)
no warranty it works for everything, we tested esp. with the exposure mode. Also we changed the output of the -S
be json like.
read the exposure mode
❯ ./uvc-util -I 0 -S auto-exposure-mode
{
"name": "auto-exposure-mode",
"type-description": "single value, unsigned 8-bit bitmap",
"step-size": 9,
"default-value": 8,
"current-value": 1
}
set the exposure mode to manual (manual=1
, automatic=8
)
❯ ./uvc-util -I 0 -s auto-exposure-mode=1
@constant-flow please go ahead and submit a pull request, I'd be happy to look over the changes (adding 8-bit bitmap type) and integrate them into the repository.
I love open source projects. This is great!
@constant-flow: hilarious that we ran into the exact same issue on a project that has been quiet for so long. Thank you for putting in the extra effort that I didn't, in order to solve the problem and contribute it for the rest of us.
@jtfrey: thank you again for sharing this project, and for coming back to it to review the PR.
Please checkout the 714cd3420575579e96750e34047535fa8bc176eb commit (bitmap8 branch). It has the bitmap types implemented as directed in the v1.5 specification. I also added the new Terminal and Processing Unit attributes that arrived in the v1.5 specification. Let me know if it works — I have no USB video devices with which to test this anymore.
Wow, you are fast.
I just tested your code. From what i see does it behave as before. All (few) settings, my cam lists do work as expected (auto-exposure-priority
doesn't have a noticeable effect, as before too)
auto-exposure-mode
only accepts 1
and 8
as before. But you explained it, it is masked in the stepSize
right now, which bits are allowed to flip (Just realized that, after scanning your code changes)
❯ ./uvc-util -I 0 -c
UVC controls implemented by this device:
zoom-abs
pan-tilt-abs
exposure-time-abs
auto-focus
auto-exposure-priority
auto-exposure-mode
focus-abs
❯ ./uvc-util -I 0 -d
------------ -------------- ------------ ------------ ------------------------------------------------
Index Vend:Prod LocationID UVC Version Device name
------------ -------------- ------------ ------------ ------------------------------------------------
0 0x046d:0x082d 0x14310000 1.00 HD Pro Webcam C920
------------ -------------- ------------ ------------ ------------------------------------------------
❯ ./uvc-util -I 0 -S auto-exposure-mode
auto-exposure-mode {
type-description: {
single value, unsigned 8-bit bitmap
},
step-size: 9
default-value: 8
current-value: 8
}
❯ ./uvc-util -I 0 -s auto-exposure-mode=1
❯ ./uvc-util -I 0 -s auto-exposure-mode=8
❯ ./uvc-util -I 0 -s auto-exposure-mode=2
ERROR: unable to write new value to control auto-exposure-mode
❯ ./uvc-util -I 0 -s auto-exposure-mode=4
ERROR: unable to write new value to control auto-exposure-mode
@dhughes-xumak Once auto-exposure-mode is changed to 1 (manual) some of the other controls should be usable (e.g. exposure time, iris).
Yup, seems to work for me now. I was able to set my camera to auto-exposure-mode 1 (Manual) or 8 (VVUVCKit reports this as Aperture Priority). The VVUVCKit test app also has options for Auto and Shutter Priority, but ./uvc-util -I 0 -g auto-exposure-mode
shows me that only Manual and Aperture Priority actually update that value.
VVUVCKit allows me to set several settings which are not available to me with uvc-util, such as brightness and contrast. uvc-util -I 0 -c
and uvc-util -I 0 -S *
don't list those controls.
However, after setting auto-exposure-mode=1, I'm able to set my camera's exposure-time-abs to some values, most notably 39, 78, and 117 [edit: updated list in my next comment] seemed to result in decent video with varying light levels. From the spec doc, I don't see any significance to these numbers.
for i in `seq 0 200`; do
echo $i
uvc-util -I0 -s exposure-time-abs=$i
sleep 5
done
This update was sufficient to get me to where I wanted to take this. Thank you again, both.
--
I've added a launch agent to poll for a UVC camera every 5 seconds, and set some default settings when one is found:
Copy uvc-util to /usr/local/bin/uvc-util.
Create file /usr/local/bin/uvcsetcameramanual (755)
#!/usr/bin/env bash
FLAG_FILE=$TMPDIR/uvcsetcameramanual.camera.connected
UVC_UTIL=/usr/local/bin/uvc-util CAMCONNECTED=$($UVC_UTIL -d)
if [ "$CAMCONNECTED" ]; then if [[ ! -f $FLAG_FILE ]]; then touch $FLAG_FILE $UVC_UTIL -I0 -s auto-exposure-mode=8 $UVC_UTIL -I0 -s brightness=30 $UVC_UTIL -I0 -s contrast=1 $UVC_UTIL -I0 -s saturation=125 fi else rm -f $FLAG_FILE fi
3. Create file ~/Library/LaunchAgents/uvc.setcameramanual.plist (544)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
4. And load it with `launchctl load ~/Library/LaunchAgents/uvc.setcameramanual.plist`
https://medium.com/swlh/how-to-use-launchd-to-run-services-in-macos-b972ed1e352
I pushed another update just now, this one with how control resolution is handled. The VVUVCKit doesn't seem to bother with control resolution. The implementation in uvc-util does check it, but was using the wrong formulation. It was checking (value % resolution) and rounding up/down to the nearest value that is cleanly divisible by resolution. But the UVC specification is such that ((value - minimum) % resolution) is rounded up/down to the nearest cleanly-divisible value. So given
min = 1, max = 101, res = 20
valid values should be 1, 21, 41, 61, 81, 101. But choosing 21:
(21 % 20) = 1
and the previous implementation would subtract 1 from value to yield 20. So just as for bitmap values incorrectly applying resolution to round (when it was actually a bitmask to be AND'ed), the integer controls with resolution were being resolved to incorrect values.
Let me know if all previous tests continue to produce the same results, and if additional controls now work properly.
@jtfrey, thanks again. Unfortunately, I don't think that helped me.
This setting actually has a resolution of 1, so the resolution-fixing doesn't apply.
$ uvc-util -I0 -Sexposure-time-abs
exposure-time-abs {
type-description: {
single value, unsigned 32-bit integer
},
minimum: 5
maximum: 20000
step-size: 1
default-value: 156
current-value: 78
}
The possible values seem to (more or less) follow a doubling series.
These values are working: 0, 1, 2, 3, 4, 5, 9, 10, 19, 20, 39, 78, 156, 312, 624.
9.75 and 19.5 belong in that series. Interestingly the integers on either side (9/10, 19/20) both work.
Any other value seems to be treated like the max value; 624 looks the same as anything >312.
Does VVUVCKit allow a continuous range of values for that control, or the same distinct values? The UVC 1.5 specification indicates that control over exposure-time-abs is partly a function of the frame interval for the device. My guess would be that what you're observing with the series is dependency on the frame rate (which can itself be dependent on other factors). The value 0 is supposed to be a reserved value with no defined meaning in the specification.
VVUVCKit provides a continuous slider ranging 5-20000, but it exhibits the same behaviour. Only the values which I identified before worked correctly, all others look just like 624.
Yes, I imagine these values may be specific to this particular camera.
So, I spent some time with the spec and identified that my missing settings (eg, brightness) are processing unit settings (vs camera terminal settings, which I can access).
I've tracked the missing PU settings to here: https://github.com/jtfrey/uvc-util/blob/master/src/UVCController.m#L950
While debugging I found that control->unit
was 2. By hard coding different unit values, I can access the additional PU controls; though I get different controls for different unit values.
I was also able to set these PU values after making a corresponding change to setValue
here:
https://github.com/jtfrey/uvc-util/blob/master/src/UVCController.m#L1021
EDIT: and with a little more effort, I located table A-5 in the spec (which already has corresponding constants in UVCController).
Based on this, I undid my prior changes and set UVC_PROCESSING_UNIT_ID = VC_INPUT_TERMINAL - 1
. This seems to give me the complete set of PU controls. Commit incoming...
Please see my comments on the UVC_PROCESSING_UNIT_ID fix. I've pushed another commit to the bitmap8-patch branch that should work regardless of what unit id the PU has for a specific device. E.g. with the default unitId changed to 0xFF and the actual unit now being noted by the UVCController class, the program still works on an Apeman 4K:
$ uvc-util -d
------------ -------------- ------------ ------------ ------------------------------------------------
Index Vend:Prod LocationID UVC Version Device name
------------ -------------- ------------ ------------ ------------------------------------------------
0 0x2aad:0x6373 0x14200000 1.00 iCatch V37
------------ -------------- ------------ ------------ ------------------------------------------------
$ uvc-util -I 0 -c
UVC controls implemented by this device:
white-balance-temp
exposure-time-abs
auto-focus
auto-exposure-priority
auto-exposure-mode
auto-white-balance-component
focus-abs
Please try it with your devices.
Hmm, with your latest commit, now the util reports no controls for my device. It chugs along for a while, but eventually reports no controls.
$ uvc-util -d
------------ -------------- ------------ ------------ ------------------------------------------------
Index Vend:Prod LocationID UVC Version Device name
------------ -------------- ------------ ------------ ------------------------------------------------
0 0x045e:0x075d 0x14140000 1.00 (null)
------------ -------------- ------------ ------------ ------------------------------------------------
$ uvc-util -I0 -c
UVC controls implemented by this device:
$ uvc-util -I0 -S*
$
The device is a Microsoft® LifeCam Cinema.
I added a chunk of code to dump the entire UVC interface header to a file (e.g. uvc-header-#.bin). Can you collect that for the LifeCam Cinema and get it to me so I can take a look at it?
$ xxd -b uvc-header-1.bin
00000000: 00001101 00100100 00000001 00000000 00000001 01010101 .$...U
00000006: 00000000 10000000 11000011 11001001 00000001 00000001 ......
0000000c: 00000001 00010010 00100100 00000010 00000001 00000001 ..$...
00000012: 00000010 00000000 00000000 00000000 00000000 00000000 ......
00000018: 00000000 00000000 00000000 00000011 00101010 00001010 ....*.
0000001e: 00000010 00001001 00100100 00000011 00000010 00000001 ..$...
00000024: 00000001 00000000 00000101 00000000 00000111 00100100 .....$
0000002a: 00000100 00000011 00000001 00000001 00000000 00001011 ......
00000030: 00100100 00000101 00000100 00000011 00000000 00000000 $.....
00000036: 00000010 01011011 00010101 00000000 00011011 00100100 .[...$
0000003c: 00000110 00000101 00101001 10100111 10000111 11001001 ..)...
00000042: 11010011 01011001 01101001 01000101 10000100 01100111 .YiE.g
00000048: 11111111 00001000 01001001 11111100 00011001 11101000 ..I...
0000004e: 00010000 00000001 00000100 00000010 11111111 11111111 ......
00000054: 00000000 .
The PU record wasn't the length I was expecting, until I checked the version: that's a UVC 1.0 device!
There really was nothing wrong with the UVC header, but there was a botched stringify directive in the UVC_CONTROL_INIT macro. Every control had a unit type string of @"U" rather than @"UVC_INPUT_TERMINAL_ID" versus @"UVC_PROCESSING_UNIT_ID", so lookup of the unit when interacting with the device (GET_CUR, et al.) was failing. It should be fixed now.
It was, indeed, UVC 1.0. Interestingly, looking back through this issue, it looks like all three of us had UVC 1.0 devices, at least based on the uvc-util -d
output that you both posted.
Anyways, I've tested it out and it seems to be working well.
I'm going to go ahead and close this issue now. Thanks again @jtfrey and @constant-flow!
PS, don't forget to merge branch bitmap8-patch into master. 😄
Let me start with thank you. Thank you for making this open source and contributing it to the world. I have nearly 20 years of development experience, and this was the first Objective C project I ever compiled. So there's that.
Unfortunately, the tool only worked for setting some of my camera's controls.
I also got this for exposure-time-abs. I suspect the issue may have been in the type handling (U8Int and U32Int), possibly related to the endian swap for some int types. I put a couple hours into trying to debug the issue, but again... first time with Objective C.
In addition to not accepting some of the values for certain settings, I also noticed that some settings/controls aren't accessible for my camera, such as brightness and contrast. These values can be set with other apps, however.
--
So, I ended up moving on and finding https://github.com/mrRay/VVUVCKit, which has a "Test App" with a GUI for configuring the camera's settings. Aside from the Test App, that project contains a framework. I don't have the Objective C chops to do this, but it would be awesome if somebody built a CLI like this project, using the VVUVCKit framework.
With a working CLI, I suspect you could create a service similar to https://github.com/pirj/noclamshell, which could poll ioreg to see if a particular camera is connected, and set the desired config programmatically.