Updated FreeBSD ffmpeg integrations

This commit is contained in:
Rob van Oostenrijk
2024-01-30 19:10:53 +04:00
parent 93dad05bde
commit f73ee41d93
2 changed files with 95 additions and 61 deletions
+56 -45
View File
@@ -2,6 +2,7 @@ package device
import ( import (
"net/url" "net/url"
"os"
"os/exec" "os/exec"
"regexp" "regexp"
"strings" "strings"
@@ -11,76 +12,86 @@ import (
) )
func queryToInput(query url.Values) string { func queryToInput(query url.Values) string {
video := query.Get("video") if video := query.Get("video"); video != "" {
audio := query.Get("audio") // https://ffmpeg.org/ffmpeg-devices.html#video4linux2_002c-v4l2
input := "-f v4l2"
if video == "" && audio == "" {
return ""
}
// https://ffmpeg.org/ffmpeg-devices.html#avfoundation
input := "-f avfoundation"
if video != "" {
video = indexToItem(videos, video)
for key, value := range query { for key, value := range query {
switch key { switch key {
case "resolution": case "resolution":
input += " -video_size " + value[0] input += " -video_size " + value[0]
case "pixel_format", "framerate", "video_size", "capture_cursor", "capture_mouse_clicks", "capture_raw_data": case "video_size", "pixel_format", "input_format", "framerate", "use_libv4l2":
input += " -" + key + " " + value[0] input += " -" + key + " " + value[0]
} }
} }
return input + " -i " + indexToItem(videos, video)
} }
if audio != "" { if audio := query.Get("audio"); audio != "" {
audio = indexToItem(audios, audio) input := "-f oss"
for key, value := range query {
switch key {
case "channels", "sample_rate":
input += " -" + key + " " + value[0]
}
} }
return input + ` -i "` + video + `:` + audio + `"` return input + " -i " + indexToItem(audios, audio)
}
return ""
} }
func initDevices() { func initDevices() {
// [AVFoundation indev @ 0x147f04510] AVFoundation video devices: files, err := os.ReadDir("/dev")
// [AVFoundation indev @ 0x147f04510] [0] FaceTime HD Camera if err != nil {
// [AVFoundation indev @ 0x147f04510] [1] Capture screen 0 return
// [AVFoundation indev @ 0x147f04510] AVFoundation audio devices: }
// [AVFoundation indev @ 0x147f04510] [0] MacBook Pro Microphone
for _, file := range files {
if !strings.HasPrefix(file.Name(), core.KindVideo) {
continue
}
name := "/dev/" + file.Name()
cmd := exec.Command( cmd := exec.Command(
Bin, "-hide_banner", "-list_devices", "true", "-f", "avfoundation", "-i", "", Bin, "-hide_banner", "-f", "v4l2", "-list_formats", "all", "-i", name,
) )
b, _ := cmd.CombinedOutput() b, _ := cmd.CombinedOutput()
re := regexp.MustCompile(`\[\d+] (.+)`) // [video4linux2,v4l2 @ 0x860b92280] Raw : yuyv422 : YUYV 4:2:2 : 640x480 160x120 176x144 320x176 320x240 352x288 432x240 544x288 640x360 752x416 800x448 800x600 864x480 960x544 960x720 1024x576 1184x656 1280x720 1280x960
// [video4linux2,v4l2 @ 0x860b92280] Compressed: mjpeg : Motion-JPEG : 640x480 160x120 176x144 320x176 320x240 352x288 432x240 544x288 640x360 752x416 800x448 800x600 864x480 960x544 960x720 1024x576 1184x656 1280x720 1280x960
var kind string re := regexp.MustCompile("(Raw *|Compressed): +(.+?) : +(.+?) : (.+)")
for _, line := range strings.Split(string(b), "\n") { m := re.FindAllStringSubmatch(string(b), -1)
switch { for _, i := range m {
case strings.HasSuffix(line, "video devices:"): size, _, _ := strings.Cut(i[4], " ")
kind = core.KindVideo stream := &api.Source{
continue Name: i[3],
case strings.HasSuffix(line, "audio devices:"): Info: i[4],
kind = core.KindAudio URL: "ffmpeg:device?video=" + name + "&input_format=" + i[2] + "&video_size=" + size,
continue
} }
m := re.FindStringSubmatch(line) if i[1] != "Compressed" {
if m == nil { stream.URL += "#video=h264#hardware"
continue
} }
name := m[1]
switch kind {
case core.KindVideo:
videos = append(videos, name) videos = append(videos, name)
case core.KindAudio: streams = append(streams, stream)
audios = append(audios, name) }
} }
streams = append(streams, &api.Source{ err = exec.Command(Bin, "-f", "oss", "-i", "/dev/dsp", "-t", "1", "-f", "null", "-").Run()
Name: name, URL: "ffmpeg:device?" + kind + "=" + name, if err == nil {
}) stream := &api.Source{
Name: "OSS default",
Info: " ",
URL: "ffmpeg:device?audio=default&channels=1&sample_rate=16000&#audio=opus",
}
audios = append(audios, "default")
streams = append(streams, stream)
} }
} }
+34 -11
View File
@@ -1,37 +1,60 @@
package hardware package hardware
import ( import (
"runtime"
"github.com/AlexxIT/go2rtc/internal/api" "github.com/AlexxIT/go2rtc/internal/api"
) )
const ProbeVideoToolboxH264 = "-f lavfi -i testsrc2=size=svga -t 1 -c h264_videotoolbox -f null -" const (
const ProbeVideoToolboxH265 = "-f lavfi -i testsrc2=size=svga -t 1 -c hevc_videotoolbox -f null -" ProbeV4L2M2MH264 = "-f lavfi -i testsrc2 -t 1 -c h264_v4l2m2m -f null -"
ProbeV4L2M2MH265 = "-f lavfi -i testsrc2 -t 1 -c hevc_v4l2m2m -f null -"
ProbeRKMPPH264 = "-f lavfi -i testsrc2 -t 1 -c h264_rkmpp_encoder -f null -"
ProbeRKMPPH265 = "-f lavfi -i testsrc2 -t 1 -c hevc_rkmpp_encoder -f null -"
)
func ProbeAll(bin string) []*api.Source { func ProbeAll(bin string) []*api.Source {
return []*api.Source{ return []*api.Source{
{ {
Name: runToString(bin, ProbeVideoToolboxH264), Name: runToString(bin, ProbeV4L2M2MH264),
URL: "ffmpeg:...#video=h264#hardware=" + EngineVideoToolbox, URL: "ffmpeg:...#video=h264#hardware=" + EngineV4L2M2M,
}, },
{ {
Name: runToString(bin, ProbeVideoToolboxH265), Name: runToString(bin, ProbeV4L2M2MH265),
URL: "ffmpeg:...#video=h265#hardware=" + EngineVideoToolbox, URL: "ffmpeg:...#video=h265#hardware=" + EngineV4L2M2M,
},
{
Name: runToString(bin, ProbeRKMPPH264),
URL: "ffmpeg:...#video=h264#hardware=" + EngineRKMPP,
},
{
Name: runToString(bin, ProbeRKMPPH265),
URL: "ffmpeg:...#video=h265#hardware=" + EngineRKMPP,
}, },
} }
} }
func ProbeHardware(bin, name string) string { func ProbeHardware(bin, name string) string {
if runtime.GOARCH == "arm64" || runtime.GOARCH == "arm" {
switch name { switch name {
case "h264": case "h264":
if run(bin, ProbeVideoToolboxH264) { if run(bin, ProbeV4L2M2MH264) {
return EngineVideoToolbox return EngineV4L2M2M
}
if run(bin, ProbeRKMPPH264) {
return EngineRKMPP
} }
case "h265": case "h265":
if run(bin, ProbeVideoToolboxH265) { if run(bin, ProbeV4L2M2MH265) {
return EngineVideoToolbox return EngineV4L2M2M
}
if run(bin, ProbeRKMPPH265) {
return EngineRKMPP
} }
} }
return EngineSoftware return EngineSoftware
} }
return EngineSoftware
}