Updated FreeBSD ffmpeg integrations
This commit is contained in:
@@ -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 " + indexToItem(audios, audio)
|
||||||
}
|
}
|
||||||
|
|
||||||
return input + ` -i "` + video + `:` + 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
|
|
||||||
cmd := exec.Command(
|
|
||||||
Bin, "-hide_banner", "-list_devices", "true", "-f", "avfoundation", "-i", "",
|
|
||||||
)
|
|
||||||
b, _ := cmd.CombinedOutput()
|
|
||||||
|
|
||||||
re := regexp.MustCompile(`\[\d+] (.+)`)
|
for _, file := range files {
|
||||||
|
if !strings.HasPrefix(file.Name(), core.KindVideo) {
|
||||||
var kind string
|
|
||||||
for _, line := range strings.Split(string(b), "\n") {
|
|
||||||
switch {
|
|
||||||
case strings.HasSuffix(line, "video devices:"):
|
|
||||||
kind = core.KindVideo
|
|
||||||
continue
|
|
||||||
case strings.HasSuffix(line, "audio devices:"):
|
|
||||||
kind = core.KindAudio
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
m := re.FindStringSubmatch(line)
|
name := "/dev/" + file.Name()
|
||||||
if m == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
name := m[1]
|
cmd := exec.Command(
|
||||||
|
Bin, "-hide_banner", "-f", "v4l2", "-list_formats", "all", "-i", name,
|
||||||
|
)
|
||||||
|
b, _ := cmd.CombinedOutput()
|
||||||
|
|
||||||
|
// [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
|
||||||
|
re := regexp.MustCompile("(Raw *|Compressed): +(.+?) : +(.+?) : (.+)")
|
||||||
|
m := re.FindAllStringSubmatch(string(b), -1)
|
||||||
|
for _, i := range m {
|
||||||
|
size, _, _ := strings.Cut(i[4], " ")
|
||||||
|
stream := &api.Source{
|
||||||
|
Name: i[3],
|
||||||
|
Info: i[4],
|
||||||
|
URL: "ffmpeg:device?video=" + name + "&input_format=" + i[2] + "&video_size=" + size,
|
||||||
|
}
|
||||||
|
|
||||||
|
if i[1] != "Compressed" {
|
||||||
|
stream.URL += "#video=h264#hardware"
|
||||||
|
}
|
||||||
|
|
||||||
switch kind {
|
|
||||||
case core.KindVideo:
|
|
||||||
videos = append(videos, name)
|
videos = append(videos, name)
|
||||||
case core.KindAudio:
|
streams = append(streams, stream)
|
||||||
audios = append(audios, name)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = exec.Command(Bin, "-f", "oss", "-i", "/dev/dsp", "-t", "1", "-f", "null", "-").Run()
|
||||||
|
if err == nil {
|
||||||
|
stream := &api.Source{
|
||||||
|
Name: "OSS default",
|
||||||
|
Info: " ",
|
||||||
|
URL: "ffmpeg:device?audio=default&channels=1&sample_rate=16000&#audio=opus",
|
||||||
}
|
}
|
||||||
|
|
||||||
streams = append(streams, &api.Source{
|
audios = append(audios, "default")
|
||||||
Name: name, URL: "ffmpeg:device?" + kind + "=" + name,
|
streams = append(streams, stream)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +1,59 @@
|
|||||||
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 {
|
||||||
switch name {
|
if runtime.GOARCH == "arm64" || runtime.GOARCH == "arm" {
|
||||||
case "h264":
|
switch name {
|
||||||
if run(bin, ProbeVideoToolboxH264) {
|
case "h264":
|
||||||
return EngineVideoToolbox
|
if run(bin, ProbeV4L2M2MH264) {
|
||||||
|
return EngineV4L2M2M
|
||||||
|
}
|
||||||
|
if run(bin, ProbeRKMPPH264) {
|
||||||
|
return EngineRKMPP
|
||||||
|
}
|
||||||
|
case "h265":
|
||||||
|
if run(bin, ProbeV4L2M2MH265) {
|
||||||
|
return EngineV4L2M2M
|
||||||
|
}
|
||||||
|
if run(bin, ProbeRKMPPH265) {
|
||||||
|
return EngineRKMPP
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case "h265":
|
return EngineSoftware
|
||||||
if run(bin, ProbeVideoToolboxH265) {
|
|
||||||
return EngineVideoToolbox
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return EngineSoftware
|
return EngineSoftware
|
||||||
|
|||||||
Reference in New Issue
Block a user