mirror of
https://github.com/taigrr/vidnumerator.git
synced 2026-04-01 20:58:51 -07:00
initial commit
This commit is contained in:
3
.github/FUNDING.yml
vendored
Normal file
3
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: taigrr # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
12
LICENSE
Normal file
12
LICENSE
Normal file
@@ -0,0 +1,12 @@
|
||||
Copyright (C) 2023 by Tai Groot <tai@taigrr.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
7
README.md
Normal file
7
README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# VidNumerator
|
||||
|
||||
This is a tiny library that only exports one function: `EnumerateVideoDevices`.
|
||||
This function uses syscalls to efficiently determine which `/dev/videoN` devices
|
||||
are webcams and which are the additional metadata control handles.
|
||||
The list of strings returned are the full filepaths to valid devices.
|
||||
|
||||
5
go.mod
Normal file
5
go.mod
Normal file
@@ -0,0 +1,5 @@
|
||||
module github.com/taigrr/vidnumerator
|
||||
|
||||
go 1.20
|
||||
|
||||
require golang.org/x/sys v0.9.0
|
||||
2
go.sum
Normal file
2
go.sum
Normal file
@@ -0,0 +1,2 @@
|
||||
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
|
||||
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
92
vidnumerator.go
Normal file
92
vidnumerator.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package vidnumerator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
IOCNrBits = 8
|
||||
IOCTypeBits = 8
|
||||
IOCSizeBits = 14
|
||||
IOCDirBits = 2
|
||||
IOCNone = 0
|
||||
IOCWrite = 1
|
||||
IOCRead = 2
|
||||
IOCNrShift = 0
|
||||
|
||||
IOCTypeShift = (IOCNrShift + IOCNrBits)
|
||||
IOCSizeShift = (IOCTypeShift + IOCTypeBits)
|
||||
IOCDirShift = (IOCSizeShift + IOCSizeBits)
|
||||
|
||||
VidIOCQueryCap = (IOCRead << IOCDirShift) |
|
||||
(uintptr('V') << IOCTypeShift) |
|
||||
(0 << IOCNrShift) |
|
||||
(unsafe.Sizeof(cap{}) << IOCSizeShift)
|
||||
)
|
||||
|
||||
type cap struct {
|
||||
driver [16]uint8
|
||||
card [32]uint8
|
||||
busInfo [32]uint8
|
||||
version uint32
|
||||
capabilities uint32
|
||||
deviceCaps uint32
|
||||
reserved [3]uint32
|
||||
}
|
||||
|
||||
func (r *cap) QueryFd(fileDesciptor int) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil receiver")
|
||||
}
|
||||
_, _, errorNumber := unix.Syscall(
|
||||
unix.SYS_IOCTL,
|
||||
uintptr(fileDesciptor),
|
||||
VidIOCQueryCap,
|
||||
uintptr(unsafe.Pointer(r)),
|
||||
)
|
||||
if errorNumber != 0 {
|
||||
return errorNumber
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// this function checks the ioctl for VIDIOC_QUERYCAP to see if the device is a video capture device
|
||||
func EnumeratedVideoDevices() []string {
|
||||
// list all files in the /dev directory
|
||||
d, err := os.ReadDir("/dev")
|
||||
if err != nil {
|
||||
return []string{}
|
||||
}
|
||||
// iterate over the files in the directory
|
||||
devNames := []string{}
|
||||
for _, file := range d {
|
||||
if file.IsDir() {
|
||||
continue
|
||||
}
|
||||
fname := file.Name()
|
||||
if !strings.HasPrefix(fname, "video") {
|
||||
continue
|
||||
}
|
||||
fname = filepath.Join("/dev/", fname)
|
||||
f, err := os.OpenFile(fname, os.O_RDONLY, 0o755)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
fd := f.Fd()
|
||||
ic := cap{}
|
||||
err = ic.QueryFd(int(fd))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if ic.deviceCaps == 69206017 {
|
||||
devNames = append(devNames, fname)
|
||||
}
|
||||
}
|
||||
return devNames
|
||||
}
|
||||
Reference in New Issue
Block a user