added controls

This commit is contained in:
ston1th 2021-02-07 14:41:48 +01:00
commit 45063b7d97
3 changed files with 167 additions and 3 deletions

132
webcam.go
View file

@ -151,6 +151,30 @@ type frmsizeenum struct {
reserved [2]uint32
}
type queryctrl struct {
id uint32
_type uint32
name [32]uint8
minimum int32
maximum int32
step int32
default_value int32
flags uint32
reserved [2]uint32
}
type querymenu struct {
id uint32
index uint32
name [32]uint8
reserved uint32
}
type control struct {
id uint32
value int32
}
const (
_IOC_READ = 2
_IOC_WRITE = 1
@ -173,6 +197,55 @@ const (
_V4L2_FRMSIZE_TYPE_DISCRETE = 1
_V4L2_FRMSIZE_TYPE_CONTINUOUS = 2
_V4L2_FRMSIZE_TYPE_STEPWISE = 3
_V4L2_CTRL_FLAG_NEXT_CTRL = 0x80000000
_V4L2_CTRL_FLAG_DISABLED = 0x0001
_V4L2_CTRL_TYPE_MENU = 3
_V4L2_CTRL_CLASS_USER = 0x00980000
_V4L2_CID_BASE = _V4L2_CTRL_CLASS_USER | 0x900
_V4L2_CID_USER_BASE = _V4L2_CID_BASE
_V4L2_CID_USER_CLASS = _V4L2_CTRL_CLASS_USER | 1
// Controls
V4L2_CID_BRIGHTNESS = _V4L2_CID_BASE + 0
V4L2_CID_CONTRAST = _V4L2_CID_BASE + 1
V4L2_CID_SATURATION = _V4L2_CID_BASE + 2
V4L2_CID_HUE = _V4L2_CID_BASE + 3
V4L2_CID_AUDIO_VOLUME = _V4L2_CID_BASE + 5
V4L2_CID_AUDIO_BALANCE = _V4L2_CID_BASE + 6
V4L2_CID_AUDIO_BASS = _V4L2_CID_BASE + 7
V4L2_CID_AUDIO_TREBLE = _V4L2_CID_BASE + 8
V4L2_CID_AUDIO_MUTE = _V4L2_CID_BASE + 9
V4L2_CID_AUDIO_LOUDNESS = _V4L2_CID_BASE + 10
V4L2_CID_AUTO_WHITE_BALANCE = _V4L2_CID_BASE + 12
V4L2_CID_DO_WHITE_BALANCE = _V4L2_CID_BASE + 13
V4L2_CID_RED_BALANCE = _V4L2_CID_BASE + 14
V4L2_CID_BLUE_BALANCE = _V4L2_CID_BASE + 15
V4L2_CID_GAMMA = _V4L2_CID_BASE + 16
V4L2_CID_EXPOSURE = _V4L2_CID_BASE + 17
V4L2_CID_AUTOGAIN = _V4L2_CID_BASE + 18
V4L2_CID_GAIN = _V4L2_CID_BASE + 19
V4L2_CID_HFLIP = _V4L2_CID_BASE + 20
V4L2_CID_VFLIP = _V4L2_CID_BASE + 21
V4L2_CID_POWER_LINE_FREQUENCY = _V4L2_CID_BASE + 24
V4L2_CID_HUE_AUTO = _V4L2_CID_BASE + 25
V4L2_CID_WHITE_BALANCE_TEMPERATURE = _V4L2_CID_BASE + 26
V4L2_CID_SHARPNESS = _V4L2_CID_BASE + 27
V4L2_CID_BACKLIGHT_COMPENSATION = _V4L2_CID_BASE + 28
V4L2_CID_CHROMA_AGC = _V4L2_CID_BASE + 29
V4L2_CID_COLOR_KILLER = _V4L2_CID_BASE + 30
V4L2_CID_COLORFX = _V4L2_CID_BASE + 31
V4L2_CID_AUTOBRIGHTNESS = _V4L2_CID_BASE + 32
V4L2_CID_BAND_STOP_FILTER = _V4L2_CID_BASE + 33
V4L2_CID_ROTATE = _V4L2_CID_BASE + 34
V4L2_CID_BG_COLOR = _V4L2_CID_BASE + 35
V4L2_CID_CHROMA_GAIN = _V4L2_CID_BASE + 36
V4L2_CID_ILLUMINATORS_1 = _V4L2_CID_BASE + 37
V4L2_CID_ILLUMINATORS_2 = _V4L2_CID_BASE + 38
V4L2_CID_MIN_BUFFERS_FOR_CAPTURE = _V4L2_CID_BASE + 39
V4L2_CID_MIN_BUFFERS_FOR_OUTPUT = _V4L2_CID_BASE + 40
V4L2_CID_ALPHA_COMPONENT = _V4L2_CID_BASE + 41
V4L2_CID_COLORFX_CBCR = _V4L2_CID_BASE + 42
)
var (
@ -185,6 +258,10 @@ var (
_VIDIOC_DQBUF = _IOWR('V', 17, unsafe.Sizeof(buffer{}))
_VIDIOC_STREAMON = _IOW('V', 18, unsafe.Sizeof(int32(0)))
_VIDIOC_ENUM_FRAMESIZES = _IOWR('V', 74, unsafe.Sizeof(frmsizeenum{}))
_VIDIOC_QUERYCTRL = _IOWR('V', 36, unsafe.Sizeof(queryctrl{}))
_VIDIOC_QUERYMENU = _IOWR('V', 37, unsafe.Sizeof(querymenu{}))
_VIDIOC_G_CTRL = _IOWR('V', 27, unsafe.Sizeof(control{}))
_VIDIOC_S_CTRL = _IOWR('V', 28, unsafe.Sizeof(control{}))
)
func _IOC(dir, t, nr, size uintptr) uintptr {
@ -214,6 +291,17 @@ func ioctl(fd, cmd, ptr uintptr) error {
return nil
}
func u2s(a [32]uint8) string {
buf := make([]byte, 32)
for i, u := range a {
if u == 0 {
break
}
buf[i] = byte(u)
}
return string(buf)
}
func (w *Webcam) checkCapabilities() (video, stream bool, err error) {
c := new(capability)
err = ioctl(w.fd, _VIDIOC_QUERYCAP, uintptr(unsafe.Pointer(c)))
@ -222,6 +310,50 @@ func (w *Webcam) checkCapabilities() (video, stream bool, err error) {
return
}
func (w *Webcam) enumMenu(id uint32, min, max int32) (items []string) {
var qm querymenu
qm.id = id
for qm.index = uint32(min); qm.index <= uint32(max); qm.index++ {
if ioctl(w.fd, _VIDIOC_QUERYMENU, uintptr(unsafe.Pointer(&qm))) == nil {
items = append(items, u2s(qm.name))
}
}
return
}
func (w *Webcam) GetControls() (m map[string][]string) {
m = make(map[string][]string)
var qc queryctrl
qc.id = _V4L2_CTRL_FLAG_NEXT_CTRL
for ioctl(w.fd, _VIDIOC_QUERYCTRL, uintptr(unsafe.Pointer(&qc))) == nil {
if (qc.flags & _V4L2_CTRL_FLAG_DISABLED) == 0 {
items := []string{}
if qc._type == _V4L2_CTRL_TYPE_MENU {
items = w.enumMenu(qc.id, qc.minimum, qc.maximum)
}
m[u2s(qc.name)] = items
}
qc.id |= _V4L2_CTRL_FLAG_NEXT_CTRL
}
return
}
func (w *Webcam) SetControl(ctrl uint32, value int32) error {
var qc queryctrl
qc.id = ctrl
err := ioctl(w.fd, _VIDIOC_QUERYCTRL, uintptr(unsafe.Pointer(&qc)))
if err != nil {
return err
}
if (qc.flags & _V4L2_CTRL_FLAG_DISABLED) != 0 {
return errors.New("unsupported")
}
var c control
c.id = ctrl
c.value = value
return ioctl(w.fd, _VIDIOC_S_CTRL, uintptr(unsafe.Pointer(&c)))
}
func (w *Webcam) GetPixelFormats() (m map[uint32]string) {
m = make(map[uint32]string)
for i := uint32(0); ; i++ {