How to set and verify v4l2-ctl parameters in Python using subprocess
The following code uses the v4l2-ctl
executable to get and set v4l2
parameters such as exposure_absolute
. It also provides means of writing a parameter and verifying if it has been set correctly.
def v4l2_set_parameters_once(params, device="/dev/video0"):
"""
Given a dict of parameters:
{
"exposure_auto": 1,
"exposure_absolute": 10,
}
this function sets those parameters using the v4l2-ctl command line executable
"""
set_ctrl_str = ",".join([f"{k}={v}" for k,v in params.items()]) # expsosure_absolute=400,exposure_auto=1
subprocess.check_output(["v4l2-ctl", "-d", device, f"--set-ctrl={set_ctrl_str}"])
def v4l2_get_parameters(params, device="/dev/video0"):
"""
Query a bunch of v4l2 parameters.
params is a list like
[
"exposure_auto",
"exposure_absolute"
]
Returns a dict of values:
{
"exposure_auto": 1,
"exposure_absolute": 10,
}
"""
get_ctrl_str = ",".join([f"{k}" for k in params])
out = subprocess.check_output(["v4l2-ctl", "-d", device, f"--get-ctrl={get_ctrl_str}"])
out = out.decode("utf-8")
result = {}
for line in out.split("\n"):
# line should be like "exposure_auto: 1"
if ":" not in line:
continue
k, _, v = line.partition(":")
result[k.strip()] = v.strip()
return result
def v4l2_set_params_until_effective(params, device="/dev/video0"):
"""
Set V4L2 params and check if they have been set correctly.
If V4L2 does not confirm the parameters correctly, they will be set again until they have an effect
params is a dict like {
"exposure_auto": 1,
"exposure_absolute": 10,
}
"""
while True:
v4l2_set_parameters_once(params, device=device)
result = v4l2_get_parameters(params.keys(), device=device)
# Check if queried parameters match set parameters
had_any_mismatch = False
for k, v in params.items():
if k not in result:
raise ValueError(f"Could not query {k}")
# Note: Values from v4l2 are always strings. So we need to compare as strings
if str(result.get(k)) != str(v):
print(f"Mismatch in {k} = {result.get(k)} but should be {v}")
had_any_mismatch = True
# Check if there has been any mismatch
if not had_any_mismatch:
return
Usage example:
v4l2_set_params_until_effective({
"exposure_auto": 1,
"exposure_absolute": 1000,
})