mirror of
https://github.com/AlexxIT/go2rtc.git
synced 2025-09-26 20:31:11 +08:00
92 lines
1.9 KiB
Go
92 lines
1.9 KiB
Go
//go:build linux && (386 || arm || mipsle || amd64 || arm64)
|
|
|
|
package v4l2
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/AlexxIT/go2rtc/internal/api"
|
|
"github.com/AlexxIT/go2rtc/internal/streams"
|
|
"github.com/AlexxIT/go2rtc/pkg/core"
|
|
"github.com/AlexxIT/go2rtc/pkg/v4l2"
|
|
"github.com/AlexxIT/go2rtc/pkg/v4l2/device"
|
|
)
|
|
|
|
func Init() {
|
|
streams.HandleFunc("v4l2", func(source string) (core.Producer, error) {
|
|
return v4l2.Open(source)
|
|
})
|
|
|
|
api.HandleFunc("api/v4l2", apiV4L2)
|
|
}
|
|
|
|
func apiV4L2(w http.ResponseWriter, r *http.Request) {
|
|
files, err := os.ReadDir("/dev")
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
var sources []*api.Source
|
|
|
|
for _, file := range files {
|
|
if !strings.HasPrefix(file.Name(), core.KindVideo) {
|
|
continue
|
|
}
|
|
|
|
path := "/dev/" + file.Name()
|
|
|
|
dev, err := device.Open(path)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
formats, _ := dev.ListFormats()
|
|
for _, fourCC := range formats {
|
|
name, ffmpeg := findFormat(fourCC)
|
|
source := &api.Source{Name: name}
|
|
|
|
sizes, _ := dev.ListSizes(fourCC)
|
|
for _, wh := range sizes {
|
|
if source.Info != "" {
|
|
source.Info += " "
|
|
}
|
|
|
|
source.Info += fmt.Sprintf("%dx%d", wh[0], wh[1])
|
|
|
|
frameRates, _ := dev.ListFrameRates(fourCC, wh[0], wh[1])
|
|
for _, fr := range frameRates {
|
|
source.Info += fmt.Sprintf("@%d", fr)
|
|
|
|
if source.URL == "" && ffmpeg != "" {
|
|
source.URL = fmt.Sprintf(
|
|
"v4l2:device?video=%s&input_format=%s&video_size=%dx%d&framerate=%d",
|
|
path, ffmpeg, wh[0], wh[1], fr,
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
if source.Info != "" {
|
|
sources = append(sources, source)
|
|
}
|
|
}
|
|
|
|
_ = dev.Close()
|
|
}
|
|
|
|
api.ResponseSources(w, sources)
|
|
}
|
|
|
|
func findFormat(fourCC uint32) (name, ffmpeg string) {
|
|
for _, format := range device.Formats {
|
|
if format.FourCC == fourCC {
|
|
return format.Name, format.FFmpeg
|
|
}
|
|
}
|
|
return string(binary.LittleEndian.AppendUint32(nil, fourCC)), ""
|
|
}
|