Skip to content

Commit

Permalink
added initial support for controls and menus along with camera conven…
Browse files Browse the repository at this point in the history
…ience interface
  • Loading branch information
peterhagelund committed Mar 11, 2024
1 parent b29f95f commit e48f162
Show file tree
Hide file tree
Showing 9 changed files with 899 additions and 392 deletions.
166 changes: 53 additions & 113 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ V4L2 definitions for Go.

## Copyright and Licensing

Copyright (c) 2020-2023 Peter Hagelund
Copyright (c) 2020-2024 Peter Hagelund

This software is licensed under the [MIT License](https://en.wikipedia.org/wiki/MIT_License)

Expand All @@ -13,15 +13,7 @@ See `LICENSE.txt`
## Installing

```bash
go get -u github.com/peterhagelund/go-v4l2
```

### Using modules

In `go.mod`:

```
require "github.com/peterhagelund/go-v4l2/pkg/v4l2" v0.5.0
go get github.com/peterhagelund/go-v4l2
```

## Using
Expand All @@ -34,105 +26,56 @@ import (
"fmt"
"image"
"image/jpeg"
"log"
"os"
"unsafe"
"time"

"github.com/peterhagelund/go-v4l2/v4l2"
"golang.org/x/sys/unix"
)

func main() {
fd, err := unix.Open("/dev/video0", unix.O_RDWR, 0)
if err != nil {
panic(err)
}
defer unix.Close(fd)
capability, err := v4l2.QueryCapabilities(fd)
if err != nil {
panic(err)
}
fmt.Printf("Driver....: %s\n", v4l2.BytesToString(capability.Driver[:]))
fmt.Printf("Card......: %s\n", v4l2.BytesToString(capability.Card[:]))
fmt.Printf("BusInfo...: %s\n", v4l2.BytesToString(capability.BusInfo[:]))
fmtDescs, err := v4l2.EnumFormats(fd, v4l2.BufTypeVideoCapture)
camera, err := v4l2.NewCamera(&v4l2.CameraConfig{
Path: "/dev/video0",
BufType: v4l2.BufTypeVideoCapture,
PixFormat: v4l2.PixFmtMJPEG,
Width: 1920,
Height: 1280,
Memory: v4l2.MemoryMmap,
BufCount: 4,
})
if err != nil {
panic(err)
}
fmt.Printf("Formats:\n")
for _, fmtDesc := range fmtDescs {
fmt.Printf("\tFormat...: %s\n", v4l2.BytesToString(fmtDesc.Description[:]))
log.Fatal(err)
}
fmt.Printf("Frame sizes for JPEG:\n")
frameSizeEnums, err := v4l2.EnumFrameSizes(fd, v4l2.PixFmtJPEG)
if err != nil {
panic(err)
defer camera.Close()
fmt.Printf("Driver....: %s\n", camera.Driver())
fmt.Printf("Card......: %s\n", camera.Card())
fmt.Printf("BusInfo...: %s\n", camera.BusInfo())
if err := camera.StreamOn(); err != nil {
log.Fatal(err)
}
for _, frameSizeEnum := range frameSizeEnums {
if frameSizeEnum.Type == v4l2.FrmSizeTypeDiscrete {
discrete := (*v4l2.FrameSizeDiscrete)(unsafe.Pointer(&frameSizeEnum.M))
fmt.Printf("\tDiscrete:\n")
fmt.Printf("\t\tWidth....: %d\n", discrete.Width)
fmt.Printf("\t\tHeight...: %d\n", discrete.Height)
} else {
if frameSizeEnum.Type == v4l2.FrmSizeTypeStepwise {
fmt.Printf("\tStepwise:\n")
} else {
fmt.Printf("\tContinuous:\n")
}
stepwise := (*v4l2.FrameSizeStepwise)(unsafe.Pointer(&frameSizeEnum.M))
fmt.Printf("\t\tMinWidth.....: %d\n", stepwise.MinWidth)
fmt.Printf("\t\tMaxWidth.....: %d\n", stepwise.MaxWidth)
fmt.Printf("\t\tStepWidth....: %d\n", stepwise.StepWidth)
fmt.Printf("\t\tMinHeight....: %d\n", stepwise.MinHeight)
fmt.Printf("\t\tMaxHeight....: %d\n", stepwise.MaxHeight)
fmt.Printf("\t\tStepHeight...: %d\n", stepwise.StepHeight)
defer camera.StreamOff()
for i := 1; i <= 5; i++ {
frame, err := camera.GrabFrame()
if err != nil {
log.Fatal(err)
}
}
width, height, err := v4l2.SetFormat(fd, v4l2.BufTypeVideoCapture, v4l2.PixFmtJPEG, 1024, 768)
if err != nil {
panic(err)
}
fmt.Printf("Frame size:\n")
fmt.Printf("\tWidth....: %d\n", width)
fmt.Printf("\tHeight...: %d\n", height)
count, err := v4l2.RequestDriverBuffers(fd, 4, v4l2.BufTypeVideoCapture, v4l2.MemoryMmap)
if err != nil {
panic(err)
}
defer v4l2.RequestDriverBuffers(fd, 0, v4l2.BufTypeVideoCapture, v4l2.MemoryMmap)
fmt.Printf("Driver buffer count...: %d\n", count)
buffers, err := v4l2.MmapBuffers(fd, count, v4l2.BufTypeVideoCapture)
if err != nil {
panic(err)
}
defer v4l2.MunmapBuffers(buffers)
if err := v4l2.StreamOn(fd, v4l2.BufTypeVideoCapture); err != nil {
panic(err)
}
defer v4l2.StreamOff(fd, v4l2.BufTypeVideoCapture)
frame, err := v4l2.GrabFrame(fd, v4l2.BufTypeVideoCapture, v4l2.MemoryMmap, buffers)
if err != nil {
panic(err)
}
if err := os.WriteFile("test1.jpeg", frame, 0644); err != nil {
panic(err)
}
buffer := bytes.NewBuffer(frame)
img, name, err := image.Decode(buffer)
if err != nil {
panic(err)
}
fmt.Printf("Image:\n")
fmt.Printf("\tName.....: %s\n", name)
fmt.Printf("\tWidth....: %d\n", img.Bounds().Dx())
fmt.Printf("\tHeight...: %d\n", img.Bounds().Dy())
file, err := os.Create("test2.jpeg")
if err != nil {
panic(err)
}
err = jpeg.Encode(file, img, nil)
if err != nil {
panic(err)
if err := os.WriteFile(fmt.Sprintf("grab_%d.jpeg", i), frame, 0644); err != nil {
log.Fatal(err)
}
buffer := bytes.NewBuffer(frame)
img, _, err := image.Decode(buffer)
if err != nil {
log.Fatal(err)
}
file, err := os.Create(fmt.Sprintf("decode_%d.jpeg", i))
if err != nil {
log.Fatal(err)
}
err = jpeg.Encode(file, img, nil)
if err != nil {
log.Fatal(err)
}
time.Sleep(time.Second)
}
}
```
Expand All @@ -143,20 +86,17 @@ func main() {
Driver....: uvcvideo
Card......: Streaming Webcam: Streaming Web
BusInfo...: usb-0000:00:14.0-8
Formats:
Format...: Motion-JPEG
Format...: YUYV 4:2:2
Frame sizes for JPEG:
Frame size:
Width....: 1024
Height...: 768
Driver buffer count...: 4
Image:
Name.....: jpeg
Width....: 1024
Height...: 768
```
```bash
$ ls -l *.jpeg
.rw-r--r-- 129k peter 1 Mar 18:51 test1.jpeg
.rw-rw-r-- 63k peter 1 Mar 18:51 test2.jpeg
.rw-rw-r-- 130k peter 10 Mar 20:21 decode_1.jpeg
.rw-rw-r-- 129k peter 10 Mar 20:21 decode_2.jpeg
.rw-rw-r-- 129k peter 10 Mar 20:21 decode_3.jpeg
.rw-rw-r-- 129k peter 10 Mar 20:22 decode_4.jpeg
.rw-rw-r-- 129k peter 10 Mar 20:22 decode_5.jpeg
.rw-r--r-- 269k peter 10 Mar 20:21 grab_1.jpeg
.rw-r--r-- 268k peter 10 Mar 20:21 grab_2.jpeg
.rw-r--r-- 268k peter 10 Mar 20:21 grab_3.jpeg
.rw-r--r-- 268k peter 10 Mar 20:22 grab_4.jpeg
.rw-r--r-- 267k peter 10 Mar 20:22 grab_5.jpeg
```
129 changes: 40 additions & 89 deletions cmd/demo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,104 +25,55 @@ import (
"fmt"
"image"
"image/jpeg"
"log"
"os"
"unsafe"
"time"

"github.com/peterhagelund/go-v4l2/v4l2"
"golang.org/x/sys/unix"
)

func main() {
fd, err := unix.Open("/dev/video0", unix.O_RDWR, 0)
camera, err := v4l2.NewCamera(&v4l2.CameraConfig{
Path: "/dev/video0",
BufType: v4l2.BufTypeVideoCapture,
PixFormat: v4l2.PixFmtMJPEG,
Width: 1920,
Height: 1280,
Memory: v4l2.MemoryMmap,
BufCount: 4,
})
if err != nil {
panic(err)
log.Fatal(err)
}
defer unix.Close(fd)
capability, err := v4l2.QueryCapabilities(fd)
if err != nil {
panic(err)
}
fmt.Printf("Driver....: %s\n", v4l2.BytesToString(capability.Driver[:]))
fmt.Printf("Card......: %s\n", v4l2.BytesToString(capability.Card[:]))
fmt.Printf("BusInfo...: %s\n", v4l2.BytesToString(capability.BusInfo[:]))
fmtDescs, err := v4l2.EnumFormats(fd, v4l2.BufTypeVideoCapture)
if err != nil {
panic(err)
}
fmt.Printf("Formats:\n")
for _, fmtDesc := range fmtDescs {
fmt.Printf("\tFormat...: %s\n", v4l2.BytesToString(fmtDesc.Description[:]))
defer camera.Close()
fmt.Printf("Driver....: %s\n", camera.Driver())
fmt.Printf("Card......: %s\n", camera.Card())
fmt.Printf("BusInfo...: %s\n", camera.BusInfo())
if err := camera.StreamOn(); err != nil {
log.Fatal(err)
}
fmt.Printf("Frame sizes for JPEG:\n")
frameSizeEnums, err := v4l2.EnumFrameSizes(fd, v4l2.PixFmtJPEG)
if err != nil {
panic(err)
}
for _, frameSizeEnum := range frameSizeEnums {
if frameSizeEnum.Type == v4l2.FrmSizeTypeDiscrete {
discrete := (*v4l2.FrameSizeDiscrete)(unsafe.Pointer(&frameSizeEnum.M))
fmt.Printf("\tDiscrete:\n")
fmt.Printf("\t\tWidth....: %d\n", discrete.Width)
fmt.Printf("\t\tHeight...: %d\n", discrete.Height)
} else {
if frameSizeEnum.Type == v4l2.FrmSizeTypeStepwise {
fmt.Printf("\tStepwise:\n")
} else {
fmt.Printf("\tContinuous:\n")
}
stepwise := (*v4l2.FrameSizeStepwise)(unsafe.Pointer(&frameSizeEnum.M))
fmt.Printf("\t\tMinWidth.....: %d\n", stepwise.MinWidth)
fmt.Printf("\t\tMaxWidth.....: %d\n", stepwise.MaxWidth)
fmt.Printf("\t\tStepWidth....: %d\n", stepwise.StepWidth)
fmt.Printf("\t\tMinHeight....: %d\n", stepwise.MinHeight)
fmt.Printf("\t\tMaxHeight....: %d\n", stepwise.MaxHeight)
fmt.Printf("\t\tStepHeight...: %d\n", stepwise.StepHeight)
defer camera.StreamOff()
for i := 1; i <= 5; i++ {
frame, err := camera.GrabFrame()
if err != nil {
log.Fatal(err)
}
}
width, height, err := v4l2.SetFormat(fd, v4l2.BufTypeVideoCapture, v4l2.PixFmtJPEG, 1024, 768)
if err != nil {
panic(err)
}
fmt.Printf("Frame size:\n")
fmt.Printf("\tWidth....: %d\n", width)
fmt.Printf("\tHeight...: %d\n", height)
count, err := v4l2.RequestDriverBuffers(fd, 4, v4l2.BufTypeVideoCapture, v4l2.MemoryMmap)
if err != nil {
panic(err)
}
defer v4l2.RequestDriverBuffers(fd, 0, v4l2.BufTypeVideoCapture, v4l2.MemoryMmap)
fmt.Printf("Driver buffer count...: %d\n", count)
buffers, err := v4l2.MmapBuffers(fd, count, v4l2.BufTypeVideoCapture)
if err != nil {
panic(err)
}
defer v4l2.MunmapBuffers(buffers)
if err := v4l2.StreamOn(fd, v4l2.BufTypeVideoCapture); err != nil {
panic(err)
}
defer v4l2.StreamOff(fd, v4l2.BufTypeVideoCapture)
frame, err := v4l2.GrabFrame(fd, v4l2.BufTypeVideoCapture, v4l2.MemoryMmap, buffers)
if err != nil {
panic(err)
}
if err := os.WriteFile("test1.jpeg", frame, 0644); err != nil {
panic(err)
}
buffer := bytes.NewBuffer(frame)
img, name, err := image.Decode(buffer)
if err != nil {
panic(err)
}
fmt.Printf("Image:\n")
fmt.Printf("\tName.....: %s\n", name)
fmt.Printf("\tWidth....: %d\n", img.Bounds().Dx())
fmt.Printf("\tHeight...: %d\n", img.Bounds().Dy())
file, err := os.Create("test2.jpeg")
if err != nil {
panic(err)
}
err = jpeg.Encode(file, img, nil)
if err != nil {
panic(err)
if err := os.WriteFile(fmt.Sprintf("grab_%d.jpeg", i), frame, 0644); err != nil {
log.Fatal(err)
}
buffer := bytes.NewBuffer(frame)
img, _, err := image.Decode(buffer)
if err != nil {
log.Fatal(err)
}
file, err := os.Create(fmt.Sprintf("decode_%d.jpeg", i))
if err != nil {
log.Fatal(err)
}
err = jpeg.Encode(file, img, nil)
if err != nil {
log.Fatal(err)
}
time.Sleep(time.Second)
}
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ module github.com/peterhagelund/go-v4l2

go 1.22

require golang.org/x/sys v0.17.0
require golang.org/x/sys v0.18.0
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6 h1:DvY3Zkh7KabQE/kfzMvYvKirS
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
Loading

0 comments on commit e48f162

Please sign in to comment.