-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #23 from vladimirvivien/device-controls
Adds support for user device controls
- Loading branch information
Showing
19 changed files
with
637 additions
and
140 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package device | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/vladimirvivien/go4vl/v4l2" | ||
) | ||
|
||
// GetControl queries the device for information about the specified control id. | ||
func (d *Device) GetControl(ctrlID v4l2.CtrlID) (v4l2.Control, error) { | ||
ctlr, err := v4l2.GetControl(d.fd, ctrlID) | ||
if err != nil { | ||
return v4l2.Control{}, fmt.Errorf("device: %s: %w", d.path, err) | ||
} | ||
return ctlr, nil | ||
} | ||
|
||
// SetControl updates the value of the specified control id. | ||
func (d *Device) SetControlValue(ctrlID v4l2.CtrlID, val v4l2.CtrlValue) error { | ||
err := v4l2.SetControlValue(d.fd, ctrlID, val) | ||
if err != nil { | ||
return fmt.Errorf("device: %s: %w", d.path, err) | ||
} | ||
return nil | ||
} | ||
|
||
// QueryAllControls fetches all supported device controls and their current values. | ||
func (d *Device) QueryAllControls() ([]v4l2.Control, error) { | ||
ctrls, err := v4l2.QueryAllControls(d.fd) | ||
if err != nil { | ||
return nil, fmt.Errorf("device: %s: %w", d.path, err) | ||
} | ||
return ctrls, nil | ||
} | ||
|
||
// SetControlBrightness is a convenience method for setting value for control v4l2.CtrlBrightness | ||
func (d *Device) SetControlBrightness(val v4l2.CtrlValue) error { | ||
return d.SetControlValue(v4l2.CtrlBrightness, val) | ||
} | ||
|
||
// SetControlContrast is a convenience method for setting value for control v4l2.CtrlContrast | ||
func (d *Device) SetControlContrast(val v4l2.CtrlValue) error { | ||
return d.SetControlValue(v4l2.CtrlContrast, val) | ||
} | ||
|
||
// SetControlSaturation is a convenience method for setting value for control v4l2.CtrlSaturation | ||
func (d *Device) SetControlSaturation(val v4l2.CtrlValue) error { | ||
return d.SetControlValue(v4l2.CtrlSaturation, val) | ||
} | ||
|
||
// SetControlHue is a convenience method for setting value for control v4l2.CtrlHue | ||
func (d *Device) SetControlHue(val v4l2.CtrlValue) error { | ||
return d.SetControlValue(v4l2.CtrlHue, val) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# Device Format Example | ||
|
||
The examples in this directory highlights the support for V4L2's device format API. It shows how to query format information and set video format for a selected device. | ||
|
||
```go | ||
|
||
func main() { | ||
|
||
device, err := dev.Open( | ||
devName, | ||
dev.WithPixFormat(v4l2.PixFormat{Width: uint32(width), Height: uint32(height), PixelFormat: fmtEnc, Field: v4l2.FieldNone}), | ||
dev.WithFPS(15), | ||
) | ||
|
||
... | ||
|
||
currFmt, err := device.GetPixFormat() | ||
if err != nil { | ||
log.Fatalf("unable to get format: %s", err) | ||
} | ||
log.Printf("Current format: %s", currFmt) | ||
|
||
... | ||
|
||
// FPS | ||
fps, err := device.GetFrameRate() | ||
if err != nil { | ||
log.Fatalf("failed to get fps: %s", err) | ||
} | ||
log.Printf("current frame rate: %d fps", fps) | ||
// update fps | ||
if fps < 30 { | ||
if err := device.SetFrameRate(30); err != nil { | ||
log.Fatalf("failed to set frame rate: %s", err) | ||
} | ||
} | ||
|
||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# Device user control |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"fmt" | ||
"log" | ||
"math" | ||
"os" | ||
|
||
dev "github.com/vladimirvivien/go4vl/device" | ||
"github.com/vladimirvivien/go4vl/v4l2" | ||
) | ||
|
||
var ( | ||
controls = map[string]v4l2.CtrlID{ | ||
"brightness": v4l2.CtrlBrightness, | ||
"contrast": v4l2.CtrlContrast, | ||
} | ||
) | ||
|
||
func main() { | ||
devName := "/dev/video0" | ||
flag.StringVar(&devName, "d", devName, "device name (path)") | ||
var list bool | ||
flag.BoolVar(&list, "list", list, "List current device controls") | ||
var ctrlName string | ||
flag.StringVar(&ctrlName, "c", ctrlName, fmt.Sprintf("Contrl name to set or get (supported %v)", controls)) | ||
ctrlVal := math.MinInt32 | ||
flag.IntVar(&ctrlVal, "v", ctrlVal, fmt.Sprintf("Value for selected control (supported %v)", controls)) | ||
|
||
flag.Parse() | ||
|
||
// open device | ||
device, err := dev.Open(devName) | ||
if err != nil { | ||
log.Fatalf("failed to open device: %s", err) | ||
} | ||
defer device.Close() | ||
|
||
if len(os.Args) < 2 || list { | ||
listUserControls(device) | ||
os.Exit(0) | ||
} | ||
|
||
ctrlID, ok := controls[ctrlName] | ||
if !ok { | ||
fmt.Printf("Program does not support ctrl [%s]; supported ctrls: %#v\n", ctrlName, controls) | ||
os.Exit(1) | ||
} | ||
|
||
if ctrlName != "" { | ||
if ctrlVal != math.MinInt32 { | ||
if err := setUserControlValue(device, ctrlID, ctrlVal); err != nil { | ||
fmt.Println(err) | ||
os.Exit(1) | ||
} | ||
} | ||
ctrl, err := device.GetControl(ctrlID) | ||
if err != nil { | ||
fmt.Printf("query controls: %s\n", err) | ||
os.Exit(1) | ||
} | ||
printUserControl(ctrl) | ||
} | ||
} | ||
|
||
func setUserControlValue(device *dev.Device, ctrlID v4l2.CtrlID, val int) error { | ||
if ctrlID == 0 { | ||
return fmt.Errorf("invalid control specified") | ||
} | ||
return device.SetControlValue(ctrlID, v4l2.CtrlValue(val)) | ||
} | ||
|
||
func listUserControls(device *dev.Device) { | ||
ctrls, err := device.QueryAllControls() | ||
if err != nil { | ||
log.Fatalf("query controls: %s", err) | ||
} | ||
|
||
for _, ctrl := range ctrls { | ||
printUserControl(ctrl) | ||
} | ||
} | ||
|
||
func printUserControl(ctrl v4l2.Control) { | ||
fmt.Printf("Control id (%d) name: %s\t[min: %d; max: %d; step: %d; default: %d current_val: %d]\n", | ||
ctrl.ID, ctrl.Name, ctrl.Minimum, ctrl.Maximum, ctrl.Step, ctrl.Default, ctrl.Value) | ||
|
||
if ctrl.IsMenu() { | ||
menus, err := ctrl.GetMenuItems() | ||
if err != nil { | ||
return | ||
} | ||
|
||
for _, m := range menus { | ||
fmt.Printf("\tMenu items for %s: %#v", ctrl.Name, m) | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Canonical Multipass VM | ||
|
||
Use this directory to setup a [Canonical Multipass](https://multipass.run/) Ubuntu VM to build and run project examples. This is useful if you want to build/run project in a non-Linux environment (i.e. Apple's OSX) or do not wish to test against your local environment directly. | ||
|
||
## Pre-requisites | ||
|
||
* Download [Canonical Multipass](https://multipass.run/) | ||
* `envsubst` util command (i.e. `brew install gettext` on Mac) | ||
|
||
## Run the VM | ||
|
||
Use the `start.sh` script to launch the VM. Ensure that your local machine has the required spare CPUs and memory, otherwise, adjust accordingly. | ||
|
||
Once launched, use `multipass shell go4vldev` to log into the ubuntu VM. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# cloud-config | ||
|
||
ssh_authorized_key: | ||
- ${SSH_PUBLIC_KEY} | ||
|
||
package_update: true | ||
package_upgrade: true | ||
packages: | ||
- v4l2loopback-dkms | ||
|
||
runcmd: | ||
- 'sudo apt -y install linux-modules-extra-$(uname -r)' | ||
- 'sudo apt -y install dkms' | ||
- 'sudo modprobe v4l2loopback exclusive_caps=1 video_nr=1,2' | ||
- 'curl -sL https://go.dev/dl/go1.19.linux-amd64.tar.gz | tar -C /usr/local -xz' | ||
- 'export PATH="${PATH}:/usr/local/go/bin' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#! /bin/bash | ||
|
||
root_dir=$(dirname "${BASH_SOURCE[0]}")/.. | ||
SSH_PUBLIC_KEY=$(cat ~/.ssh/id_rsa.pub) | ||
envsubst '$SSH_PUBLIC_KEY' < ./cloud-init.yaml | multipass launch jammy -v -n go4vldev --cpus 4 --mem 4g --disk 20g --mount $root_dir:/home/ubuntu/go4vl --cloud-init - |
Oops, something went wrong.