From c70519c95d3b19bc45c92d4eb14a5f46e2c1726f Mon Sep 17 00:00:00 2001 From: f-fl0 Date: Fri, 18 Mar 2022 11:42:22 +0900 Subject: [PATCH] Add functions to set and get framerate - Mostly taken from https://github.com/blackjack/webcam/pull/32. - This branch is no longer available. --- v4l2.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ webcam.go | 13 ++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/v4l2.go b/v4l2.go index 578c111..4a9794e 100644 --- a/v4l2.go +++ b/v4l2.go @@ -3,6 +3,7 @@ package webcam import ( "bytes" "encoding/binary" + "fmt" "unsafe" "github.com/blackjack/webcam/ioctl" @@ -75,6 +76,8 @@ var ( VIDIOC_QUERYBUF = ioctl.IoRW(uintptr('V'), 9, unsafe.Sizeof(v4l2_buffer{})) VIDIOC_QBUF = ioctl.IoRW(uintptr('V'), 15, unsafe.Sizeof(v4l2_buffer{})) VIDIOC_DQBUF = ioctl.IoRW(uintptr('V'), 17, unsafe.Sizeof(v4l2_buffer{})) + VIDIOC_G_PARM = ioctl.IoRW(uintptr('V'), 21, unsafe.Sizeof(v4l2_streamparm{})) + VIDIOC_S_PARM = ioctl.IoRW(uintptr('V'), 22, unsafe.Sizeof(v4l2_streamparm{})) VIDIOC_G_CTRL = ioctl.IoRW(uintptr('V'), 27, unsafe.Sizeof(v4l2_control{})) VIDIOC_S_CTRL = ioctl.IoRW(uintptr('V'), 28, unsafe.Sizeof(v4l2_control{})) VIDIOC_QUERYCTRL = ioctl.IoRW(uintptr('V'), 36, unsafe.Sizeof(v4l2_queryctrl{})) @@ -203,6 +206,26 @@ type v4l2_control struct { value int32 } +type v4l2_fract struct { + numerator uint32 + denominator uint32 +} + +type v4l2_streamparm_union struct { + capability uint32 + output_mode uint32 + time_per_frame v4l2_fract + extended_mode uint32 + buffers uint32 + reserved [4]uint32 + data [200 - (10 * unsafe.Sizeof(uint32(0)))]byte +} + +type v4l2_streamparm struct { + _type uint32 + union v4l2_streamparm_union +} + func checkCapabilities(fd uintptr) (supportsVideoCapture bool, supportsVideoStreaming bool, err error) { caps := &v4l2_capability{} @@ -466,6 +489,29 @@ func setControl(fd uintptr, id uint32, val int32) error { return ioctl.Ioctl(fd, VIDIOC_S_CTRL, uintptr(unsafe.Pointer(ctrl))) } +func getFramerate(fd uintptr) (float32, error) { + param := &v4l2_streamparm{} + param._type = V4L2_BUF_TYPE_VIDEO_CAPTURE + + err := ioctl.Ioctl(fd, VIDIOC_G_PARM, uintptr(unsafe.Pointer(param))) + if err != nil { + return 0, err + } + tf := param.union.time_per_frame + if tf.denominator == 0 || tf.numerator == 0 { + return 0, fmt.Errorf("Invalid framerate (%d/%d)", tf.denominator, tf.numerator) + } + return float32(tf.denominator) / float32(tf.numerator), nil +} + +func setFramerate(fd uintptr, num, denom uint32) error { + param := &v4l2_streamparm{} + param._type = V4L2_BUF_TYPE_VIDEO_CAPTURE + param.union.time_per_frame.numerator = num + param.union.time_per_frame.denominator = denom + return ioctl.Ioctl(fd, VIDIOC_S_PARM, uintptr(unsafe.Pointer(param))) +} + func queryControls(fd uintptr) []control { controls := []control{} var err error diff --git a/webcam.go b/webcam.go index 19d3559..9b9ff27 100644 --- a/webcam.go +++ b/webcam.go @@ -5,9 +5,10 @@ package webcam import ( "errors" - "golang.org/x/sys/unix" "reflect" "unsafe" + + "golang.org/x/sys/unix" ) // Webcam object @@ -153,6 +154,16 @@ func (w *Webcam) SetControl(id ControlID, value int32) error { return setControl(w.fd, uint32(id), value) } +// Get the framerate. +func (w *Webcam) GetFramerate() (float32, error) { + return getFramerate(w.fd) +} + +// Set FPS +func (w *Webcam) SetFramerate(fps float32) error { + return setFramerate(w.fd, 1000, uint32(1000*(fps))) +} + // Start streaming process func (w *Webcam) StartStreaming() error { if w.streaming {