From ccecbe3c8ec585601cefff5d88f87f16e56b8999 Mon Sep 17 00:00:00 2001 From: Ingo Oppermann Date: Thu, 6 Jul 2023 21:41:10 +0200 Subject: [PATCH] Improve FFmpeg skills testing --- ffmpeg/skills/data.go | 57 --- ffmpeg/skills/skills.go | 12 +- ffmpeg/skills/skills_test.go | 707 +++++++++++---------------- ffmpeg/skills/v4l2_test.go | 8 +- internal/testhelper/ffmpeg/ffmpeg.go | 130 ++++- restream/restream_test.go | 2 +- 6 files changed, 429 insertions(+), 487 deletions(-) delete mode 100644 ffmpeg/skills/data.go diff --git a/ffmpeg/skills/data.go b/ffmpeg/skills/data.go deleted file mode 100644 index cf460fec..00000000 --- a/ffmpeg/skills/data.go +++ /dev/null @@ -1,57 +0,0 @@ -package skills - -var ffmpegdata = `ffmpeg version 4.4.1-datarhei Copyright (c) 2000-2021 the FFmpeg developers -built with gcc 10.3.1 (Alpine 10.3.1_git20211027) 20211027 -configuration: --extra-version=datarhei --prefix=/usr --extra-libs='-lpthread -lm -lz -lsupc++ -lstdc++ -lssl -lcrypto -lz -lc -ldl' --enable-nonfree --enable-gpl --enable-version3 --enable-postproc --enable-static --enable-openssl --enable-omx --enable-omx-rpi --enable-mmal --enable-v4l2_m2m --enable-libfreetype --enable-libsrt --enable-libx264 --enable-libx265 --enable-libvpx --enable-libmp3lame --enable-libopus --enable-libvorbis --disable-ffplay --disable-debug --disable-doc --disable-shared -libavutil 56. 70.100 / 56. 70.100 -libavcodec 58.134.100 / 58.134.100 -libavformat 58. 76.100 / 58. 76.100 -libavdevice 58. 13.100 / 58. 13.100 -libavfilter 7.110.100 / 7.110.100 -libswscale 5. 9.100 / 5. 9.100 -libswresample 3. 9.100 / 3. 9.100 -libpostproc 55. 9.100 / 55. 9.100` - -var filterdata = ` ... afirsrc |->A Generate a FIR coefficients audio stream. -... anoisesrc |->A Generate a noise audio signal. -... anullsrc |->A Null audio source, return empty audio frames. -... hilbert |->A Generate a Hilbert transform FIR coefficients. -... sinc |->A Generate a sinc kaiser-windowed low-pass, high-pass, band-pass, or band-reject FIR coefficients. -... sine |->A Generate sine wave audio signal. -... anullsink A->| Do absolutely nothing with the input audio. -... addroi V->V Add region of interest to frame. -... alphaextract V->N Extract an alpha channel as a grayscale image component. -T.. alphamerge VV->V Copy the luma value of the second input into the alpha channel of the first input.` - -var codecdata = ` DEAIL. aac AAC (Advanced Audio Coding) (decoders: aac aac_fixed aac_at ) (encoders: aac aac_at ) -DEVI.S y41p Uncompressed YUV 4:1:1 12-bit -DEV.LS h264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (encoders: libx264 libx264rgb h264_videotoolbox ) -DEV.L. flv1 FLV / Sorenson Spark / Sorenson H.263 (Flash Video) (decoders: flv ) (encoders: flv )` - -var formatdata = ` DE mpeg MPEG-1 Systems / MPEG program stream - E mpeg1video raw MPEG-1 video - E mpeg2video raw MPEG-2 video -DE mpegts MPEG-TS (MPEG-2 Transport Stream) -D mpegtsraw raw MPEG-TS (MPEG-2 Transport Stream) -D mpegvideo raw MPEG video` - -var protocoldata = `Input: -async -bluray -cache -Output: -crypto -file -ftp -gopher` - -var hwacceldata = `Hardware acceleration methods: -videotoolbox` - -var v4ldata = `mmal service 16.1 (platform:bcm2835-v4l2): - /dev/video0 - -Webcam C170: Webcam C170 (usb-3f980000.usb-1.3): - /dev/video1 - -` diff --git a/ffmpeg/skills/skills.go b/ffmpeg/skills/skills.go index 956c0a9d..da065c51 100644 --- a/ffmpeg/skills/skills.go +++ b/ffmpeg/skills/skills.go @@ -347,7 +347,7 @@ func filters(binary string) []Filter { cmd := exec.Command(binary, "-filters") cmd.Env = []string{} - stdout, _ := cmd.Output() + stdout, _ := cmd.CombinedOutput() return parseFilters(stdout) } @@ -381,7 +381,7 @@ func codecs(binary string) ffCodecs { cmd := exec.Command(binary, "-codecs") cmd.Env = []string{} - stdout, _ := cmd.Output() + stdout, _ := cmd.CombinedOutput() return parseCodecs(stdout) } @@ -440,7 +440,7 @@ func formats(binary string) ffFormats { cmd := exec.Command(binary, "-formats") cmd.Env = []string{} - stdout, _ := cmd.Output() + stdout, _ := cmd.CombinedOutput() return parseFormats(stdout) } @@ -484,7 +484,7 @@ func devices(binary string) ffDevices { cmd := exec.Command(binary, "-devices") cmd.Env = []string{} - stdout, _ := cmd.Output() + stdout, _ := cmd.CombinedOutput() return parseDevices(stdout, binary) } @@ -539,7 +539,7 @@ func protocols(binary string) ffProtocols { cmd := exec.Command(binary, "-protocols") cmd.Env = []string{} - stdout, _ := cmd.Output() + stdout, _ := cmd.CombinedOutput() return parseProtocols(stdout) } @@ -588,7 +588,7 @@ func hwaccels(binary string) []HWAccel { cmd := exec.Command(binary, "-hwaccels") cmd.Env = []string{} - stdout, _ := cmd.Output() + stdout, _ := cmd.CombinedOutput() return parseHWAccels(stdout) } diff --git a/ffmpeg/skills/skills_test.go b/ffmpeg/skills/skills_test.go index e4112236..7adf0a21 100644 --- a/ffmpeg/skills/skills_test.go +++ b/ffmpeg/skills/skills_test.go @@ -1,10 +1,9 @@ package skills import ( - "bytes" "testing" - "github.com/datarhei/core/v16/slices" + "github.com/datarhei/core/v16/internal/testhelper" "github.com/stretchr/testify/require" ) @@ -35,6 +34,290 @@ func TestNewInvalidBinary(t *testing.T) { require.Empty(t, skills.Protocols.Output) } +func TestNew(t *testing.T) { + binary, err := testhelper.BuildBinary("ffmpeg", "../../internal/testhelper") + require.NoError(t, err, "Failed to build helper program") + + skills, err := New(binary) + require.NoError(t, err) + require.Equal(t, Skills{ + FFmpeg: ffmpeg{ + Version: "4.4.1", + Compiler: "gcc 10.3.1 (Alpine 10.3.1_git20211027) 20211027", + Configuration: "--extra-version=datarhei --prefix=/usr --extra-libs='-lpthread -lm -lz -lsupc++ -lstdc++ -lssl -lcrypto -lz -lc -ldl' --enable-nonfree --enable-gpl --enable-version3 --enable-postproc --enable-static --enable-openssl --enable-omx --enable-omx-rpi --enable-mmal --enable-v4l2_m2m --enable-libfreetype --enable-libsrt --enable-libx264 --enable-libx265 --enable-libvpx --enable-libmp3lame --enable-libopus --enable-libvorbis --disable-ffplay --disable-debug --disable-doc --disable-shared", + Libraries: []Library{ + { + Name: "libavutil", + Compiled: "56. 70.100", + Linked: "56. 70.100", + }, + { + Name: "libavcodec", + Compiled: "58.134.100", + Linked: "58.134.100", + }, + { + Name: "libavformat", + Compiled: "58. 76.100", + Linked: "58. 76.100", + }, + { + Name: "libavdevice", + Compiled: "58. 13.100", + Linked: "58. 13.100", + }, + { + Name: "libavfilter", + Compiled: "7.110.100", + Linked: "7.110.100", + }, + { + Name: "libswscale", + Compiled: "5. 9.100", + Linked: "5. 9.100", + }, + { + Name: "libswresample", + Compiled: "3. 9.100", + Linked: "3. 9.100", + }, + { + Name: "libpostproc", + Compiled: "55. 9.100", + Linked: "55. 9.100", + }, + }, + }, + Filters: []Filter{ + { + Id: "afirsrc", + Name: "Generate a FIR coefficients audio stream.", + }, + { + Id: "anoisesrc", + Name: "Generate a noise audio signal.", + }, + { + Id: "anullsrc", + Name: "Null audio source, return empty audio frames.", + }, + { + Id: "hilbert", + Name: "Generate a Hilbert transform FIR coefficients.", + }, + { + Id: "sinc", + Name: "Generate a sinc kaiser-windowed low-pass, high-pass, band-pass, or band-reject FIR coefficients.", + }, + { + Id: "sine", + Name: "Generate sine wave audio signal.", + }, + { + Id: "anullsink", + Name: "Do absolutely nothing with the input audio.", + }, + { + Id: "addroi", + Name: "Add region of interest to frame.", + }, + { + Id: "alphaextract", + Name: "Extract an alpha channel as a grayscale image component.", + }, + { + Id: "alphamerge", + Name: "Copy the luma value of the second input into the alpha channel of the first input.", + }, + }, + HWAccels: []HWAccel{ + { + Id: "videotoolbox", + Name: "videotoolbox", + }, + }, + Codecs: ffCodecs{ + Audio: []Codec{ + { + Id: "aac", + Name: "AAC (Advanced Audio Coding)", + Encoders: []string{ + "aac", + "aac_at", + }, + Decoders: []string{ + "aac", + "aac_fixed", + "aac_at", + }, + }, + }, + Video: []Codec{ + { + Id: "y41p", + Name: "Uncompressed YUV 4:1:1 12-bit", + Encoders: []string{ + "y41p", + }, + Decoders: []string{ + "y41p", + }, + }, + { + Id: "h264", + Name: "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10", + Encoders: []string{ + "libx264", + "libx264rgb", + "h264_videotoolbox", + }, + Decoders: []string{ + "h264", + }, + }, + { + Id: "flv1", + Name: "FLV / Sorenson Spark / Sorenson H.263 (Flash Video)", + Encoders: []string{ + "flv", + }, + Decoders: []string{ + "flv", + }, + }, + }, + Subtitle: nil, + }, + Devices: ffDevices{ + Demuxers: []Device{ + { + Id: "avfoundation", + Name: "AVFoundation input device", + Devices: []HWDevice{ + { + Id: "0", + Name: "FaceTime HD Camera (Built-in)", + Extra: "", + Media: "video", + }, + { + Id: "1", + Name: "Capture screen 0", + Extra: "", + Media: "video", + }, + { + Id: "2", + Name: "Capture screen 1", + Extra: "", + Media: "video", + }, + { + Id: "0", + Name: "Built-in Microphone", + Extra: "", + Media: "audio", + }, + }, + }, + { + Id: "lavfi", + Name: "Libavfilter virtual input device", + Devices: []HWDevice(nil), + }, + { + Id: "x11grab", + Name: "X11 screen capture, using XCB", + Devices: []HWDevice(nil), + }, + }, Muxers: []Device{ + { + Id: "audiotoolbox", + Name: "AudioToolbox output device", + Devices: []HWDevice(nil), + }, + { + Id: "sdl", + Name: "SDL2 output device", + Devices: []HWDevice(nil), + }, + }, + }, + Formats: ffFormats{ + Demuxers: []Format{ + { + Id: "mpeg", + Name: "MPEG-1 Systems / MPEG program stream", + }, + { + Id: "mpegts", + Name: "MPEG-TS (MPEG-2 Transport Stream)", + }, + { + Id: "mpegtsraw", + Name: "raw MPEG-TS (MPEG-2 Transport Stream)", + }, + { + Id: "mpegvideo", + Name: "raw MPEG video", + }, + }, + Muxers: []Format{ + { + Id: "mpeg", + Name: "MPEG-1 Systems / MPEG program stream", + }, + { + Id: "mpeg1video", + Name: "raw MPEG-1 video", + }, + { + Id: "mpeg2video", + Name: "raw MPEG-2 video", + }, + { + Id: "mpegts", + Name: "MPEG-TS (MPEG-2 Transport Stream)", + }, + }, + }, + Protocols: ffProtocols{ + Input: []Protocol{ + { + Id: "async", + Name: "async", + }, + { + Id: "bluray", + Name: "bluray", + }, + { + Id: "cache", + Name: "cache", + }, + }, + Output: []Protocol{ + { + Id: "crypto", + Name: "crypto", + }, + { + Id: "file", + Name: "file", + }, + { + Id: "ftp", + Name: "ftp", + }, + { + Id: "gopher", + Name: "gopher", + }, + }, + }, + }, skills) +} + func TestEqualEmptySkills(t *testing.T) { s := Skills{} @@ -43,54 +326,17 @@ func TestEqualEmptySkills(t *testing.T) { } func TestEuqalSkills(t *testing.T) { - s1 := Skills{ - FFmpeg: parseVersion([]byte(ffmpegdata)), - Filters: parseFilters([]byte(filterdata)), - HWAccels: parseHWAccels([]byte(hwacceldata)), - Codecs: parseCodecs([]byte(codecdata)), - Devices: ffDevices{}, - Formats: parseFormats([]byte(formatdata)), - Protocols: parseProtocols([]byte(protocoldata)), - } + binary, err := testhelper.BuildBinary("ffmpeg", "../../internal/testhelper") + require.NoError(t, err, "Failed to build helper program") - devices := parseV4LDevices(bytes.NewBuffer(slices.Copy([]byte(v4ldata)))) - - s1.Devices.Demuxers = append(s1.Devices.Demuxers, Device{ - Id: "v4l2", - Name: "webcam", - Devices: devices, - }) - s1.Devices.Muxers = append(s1.Devices.Muxers, Device{ - Id: "v4l2", - Name: "webcam", - Devices: devices, - }) + s1, err := New(binary) + require.NoError(t, err) ok := s1.Equal(s1) require.True(t, ok) - s2 := Skills{ - FFmpeg: parseVersion([]byte(ffmpegdata)), - Filters: parseFilters([]byte(filterdata)), - HWAccels: parseHWAccels([]byte(hwacceldata)), - Codecs: parseCodecs([]byte(codecdata)), - Devices: ffDevices{}, - Formats: parseFormats([]byte(formatdata)), - Protocols: parseProtocols([]byte(protocoldata)), - } - - devices = parseV4LDevices(bytes.NewBuffer(slices.Copy([]byte(v4ldata)))) - - s2.Devices.Demuxers = append(s2.Devices.Demuxers, Device{ - Id: "v4l2", - Name: "webcam", - Devices: devices, - }) - s2.Devices.Muxers = append(s2.Devices.Muxers, Device{ - Id: "v4l2", - Name: "webcam", - Devices: devices, - }) + s2, err := New(binary) + require.NoError(t, err) ok = s1.Equal(s2) require.True(t, ok) @@ -100,390 +346,31 @@ func TestEuqalSkills(t *testing.T) { } func TestPatchVersion(t *testing.T) { - data := `ffmpeg version 4.3.1 Copyright (c) 2000-2020 the FFmpeg developers - built with Apple clang version 12.0.0 (clang-1200.0.32.29) - configuration: --enable-static --enable-debug --disable-doc --enable-libx264 --enable-gpl --enable-nonfree - libavutil 56. 51.100 / 56. 51.100 - libavcodec 58. 91.100 / 58. 91.100 - libavformat 58. 45.100 / 58. 45.100 - libavdevice 58. 10.100 / 58. 10.100 - libavfilter 7. 85.100 / 7. 85.100 - libswscale 5. 7.100 / 5. 7.100 - libswresample 3. 7.100 / 3. 7.100 - libpostproc 55. 7.100 / 55. 7.100` + data := `ffmpeg version 4.3.1 Copyright (c) 2000-2020 the FFmpeg developers` f := parseVersion([]byte(data)) require.Equal(t, ffmpeg{ - Version: "4.3.1", - Compiler: "Apple clang version 12.0.0 (clang-1200.0.32.29)", - Configuration: "--enable-static --enable-debug --disable-doc --enable-libx264 --enable-gpl --enable-nonfree", - Libraries: []Library{ - { - Name: "libavutil", - Compiled: "56. 51.100", - Linked: "56. 51.100", - }, - { - Name: "libavcodec", - Compiled: "58. 91.100", - Linked: "58. 91.100", - }, - { - Name: "libavformat", - Compiled: "58. 45.100", - Linked: "58. 45.100", - }, - { - Name: "libavdevice", - Compiled: "58. 10.100", - Linked: "58. 10.100", - }, - { - Name: "libavfilter", - Compiled: "7. 85.100", - Linked: "7. 85.100", - }, - { - Name: "libswscale", - Compiled: "5. 7.100", - Linked: "5. 7.100", - }, - { - Name: "libswresample", - Compiled: "3. 7.100", - Linked: "3. 7.100", - }, - { - Name: "libpostproc", - Compiled: "55. 7.100", - Linked: "55. 7.100", - }, - }, + Version: "4.3.1", }, f) } func TestMinorVersion(t *testing.T) { - data := `ffmpeg version 4.4 Copyright (c) 2000-2020 the FFmpeg developers - built with Apple clang version 12.0.0 (clang-1200.0.32.29) - configuration: --enable-static --enable-debug --disable-doc --enable-libx264 --enable-gpl --enable-nonfree - libavutil 56. 51.100 / 56. 51.100 - libavcodec 58. 91.100 / 58. 91.100 - libavformat 58. 45.100 / 58. 45.100 - libavdevice 58. 10.100 / 58. 10.100 - libavfilter 7. 85.100 / 7. 85.100 - libswscale 5. 7.100 / 5. 7.100 - libswresample 3. 7.100 / 3. 7.100 - libpostproc 55. 7.100 / 55. 7.100` + data := `ffmpeg version 4.4 Copyright (c) 2000-2020 the FFmpeg developers` f := parseVersion([]byte(data)) require.Equal(t, ffmpeg{ - Version: "4.4.0", - Compiler: "Apple clang version 12.0.0 (clang-1200.0.32.29)", - Configuration: "--enable-static --enable-debug --disable-doc --enable-libx264 --enable-gpl --enable-nonfree", - Libraries: []Library{ - { - Name: "libavutil", - Compiled: "56. 51.100", - Linked: "56. 51.100", - }, - { - Name: "libavcodec", - Compiled: "58. 91.100", - Linked: "58. 91.100", - }, - { - Name: "libavformat", - Compiled: "58. 45.100", - Linked: "58. 45.100", - }, - { - Name: "libavdevice", - Compiled: "58. 10.100", - Linked: "58. 10.100", - }, - { - Name: "libavfilter", - Compiled: "7. 85.100", - Linked: "7. 85.100", - }, - { - Name: "libswscale", - Compiled: "5. 7.100", - Linked: "5. 7.100", - }, - { - Name: "libswresample", - Compiled: "3. 7.100", - Linked: "3. 7.100", - }, - { - Name: "libpostproc", - Compiled: "55. 7.100", - Linked: "55. 7.100", - }, - }, + Version: "4.4.0", }, f) } func TestCustomVersion(t *testing.T) { - data := ffmpegdata + data := `ffmpeg version 4.4.1-datarhei Copyright (c) 2000-2021 the FFmpeg developers` f := parseVersion([]byte(data)) require.Equal(t, ffmpeg{ - Version: "4.4.1", - Compiler: "gcc 10.3.1 (Alpine 10.3.1_git20211027) 20211027", - Configuration: "--extra-version=datarhei --prefix=/usr --extra-libs='-lpthread -lm -lz -lsupc++ -lstdc++ -lssl -lcrypto -lz -lc -ldl' --enable-nonfree --enable-gpl --enable-version3 --enable-postproc --enable-static --enable-openssl --enable-omx --enable-omx-rpi --enable-mmal --enable-v4l2_m2m --enable-libfreetype --enable-libsrt --enable-libx264 --enable-libx265 --enable-libvpx --enable-libmp3lame --enable-libopus --enable-libvorbis --disable-ffplay --disable-debug --disable-doc --disable-shared", - Libraries: []Library{ - { - Name: "libavutil", - Compiled: "56. 70.100", - Linked: "56. 70.100", - }, - { - Name: "libavcodec", - Compiled: "58.134.100", - Linked: "58.134.100", - }, - { - Name: "libavformat", - Compiled: "58. 76.100", - Linked: "58. 76.100", - }, - { - Name: "libavdevice", - Compiled: "58. 13.100", - Linked: "58. 13.100", - }, - { - Name: "libavfilter", - Compiled: "7.110.100", - Linked: "7.110.100", - }, - { - Name: "libswscale", - Compiled: "5. 9.100", - Linked: "5. 9.100", - }, - { - Name: "libswresample", - Compiled: "3. 9.100", - Linked: "3. 9.100", - }, - { - Name: "libpostproc", - Compiled: "55. 9.100", - Linked: "55. 9.100", - }, - }, + Version: "4.4.1", }, f) } - -func TestFilters(t *testing.T) { - data := filterdata - - f := parseFilters([]byte(data)) - - require.Equal(t, []Filter{ - { - Id: "afirsrc", - Name: "Generate a FIR coefficients audio stream.", - }, - { - Id: "anoisesrc", - Name: "Generate a noise audio signal.", - }, - { - Id: "anullsrc", - Name: "Null audio source, return empty audio frames.", - }, - { - Id: "hilbert", - Name: "Generate a Hilbert transform FIR coefficients.", - }, - { - Id: "sinc", - Name: "Generate a sinc kaiser-windowed low-pass, high-pass, band-pass, or band-reject FIR coefficients.", - }, - { - Id: "sine", - Name: "Generate sine wave audio signal.", - }, - { - Id: "anullsink", - Name: "Do absolutely nothing with the input audio.", - }, - { - Id: "addroi", - Name: "Add region of interest to frame.", - }, - { - Id: "alphaextract", - Name: "Extract an alpha channel as a grayscale image component.", - }, - { - Id: "alphamerge", - Name: "Copy the luma value of the second input into the alpha channel of the first input.", - }, - }, f) -} - -func TestCodecs(t *testing.T) { - data := codecdata - - c := parseCodecs([]byte(data)) - - require.Equal(t, ffCodecs{ - Audio: []Codec{ - { - Id: "aac", - Name: "AAC (Advanced Audio Coding)", - Encoders: []string{ - "aac", - "aac_at", - }, - Decoders: []string{ - "aac", - "aac_fixed", - "aac_at", - }, - }, - }, - Video: []Codec{ - { - Id: "y41p", - Name: "Uncompressed YUV 4:1:1 12-bit", - Encoders: []string{ - "y41p", - }, - Decoders: []string{ - "y41p", - }, - }, - { - Id: "h264", - Name: "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10", - Encoders: []string{ - "libx264", - "libx264rgb", - "h264_videotoolbox", - }, - Decoders: []string{ - "h264", - }, - }, - { - Id: "flv1", - Name: "FLV / Sorenson Spark / Sorenson H.263 (Flash Video)", - Encoders: []string{ - "flv", - }, - Decoders: []string{ - "flv", - }, - }, - }, - Subtitle: nil, - }, c) -} - -func TestFormats(t *testing.T) { - data := formatdata - - f := parseFormats([]byte(data)) - - require.Equal(t, ffFormats{ - Demuxers: []Format{ - { - Id: "mpeg", - Name: "MPEG-1 Systems / MPEG program stream", - }, - { - Id: "mpegts", - Name: "MPEG-TS (MPEG-2 Transport Stream)", - }, - { - Id: "mpegtsraw", - Name: "raw MPEG-TS (MPEG-2 Transport Stream)", - }, - { - Id: "mpegvideo", - Name: "raw MPEG video", - }, - }, - Muxers: []Format{ - { - Id: "mpeg", - Name: "MPEG-1 Systems / MPEG program stream", - }, - { - Id: "mpeg1video", - Name: "raw MPEG-1 video", - }, - { - Id: "mpeg2video", - Name: "raw MPEG-2 video", - }, - { - Id: "mpegts", - Name: "MPEG-TS (MPEG-2 Transport Stream)", - }, - }, - }, f) -} - -func TestProtocols(t *testing.T) { - data := protocoldata - - p := parseProtocols([]byte(data)) - - require.Equal(t, ffProtocols{ - Input: []Protocol{ - { - Id: "async", - Name: "async", - }, - { - Id: "bluray", - Name: "bluray", - }, - { - Id: "cache", - Name: "cache", - }, - }, - Output: []Protocol{ - { - Id: "crypto", - Name: "crypto", - }, - { - Id: "file", - Name: "file", - }, - { - Id: "ftp", - Name: "ftp", - }, - { - Id: "gopher", - Name: "gopher", - }, - }, - }, p) -} - -func TestHWAccels(t *testing.T) { - data := hwacceldata - - p := parseHWAccels([]byte(data)) - - require.Equal(t, []HWAccel{ - { - Id: "videotoolbox", - Name: "videotoolbox", - }, - }, p) -} diff --git a/ffmpeg/skills/v4l2_test.go b/ffmpeg/skills/v4l2_test.go index 7464937c..a9a86d9e 100644 --- a/ffmpeg/skills/v4l2_test.go +++ b/ffmpeg/skills/v4l2_test.go @@ -17,7 +17,13 @@ func TestNoV4LDevices(t *testing.T) { } func TestV4LDevices(t *testing.T) { - data := v4ldata + data := `mmal service 16.1 (platform:bcm2835-v4l2): + /dev/video0 + +Webcam C170: Webcam C170 (usb-3f980000.usb-1.3): + /dev/video1 + +` devices := parseV4LDevices(bytes.NewBuffer(slices.Copy([]byte(data)))) diff --git a/internal/testhelper/ffmpeg/ffmpeg.go b/internal/testhelper/ffmpeg/ffmpeg.go index 285eed50..210673cb 100644 --- a/internal/testhelper/ffmpeg/ffmpeg.go +++ b/internal/testhelper/ffmpeg/ffmpeg.go @@ -6,21 +6,101 @@ import ( "os" "os/signal" "time" + + "github.com/datarhei/core/v16/slices" ) func main() { - header := `ffmpeg version 4.0.2 Copyright (c) 2000-2018 the FFmpeg developers - built with Apple LLVM version 9.1.0 (clang-902.0.39.2) - configuration: --prefix=/usr/local/Cellar/ffmpeg/4.0.2 --enable-shared --enable-pthreads --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-gpl --enable-libmp3lame --enable-libx264 --enable-libx265 --enable-libxvid --enable-opencl --enable-videotoolbox --disable-lzma - libavutil 56. 14.100 / 56. 14.100 - libavcodec 58. 18.100 / 58. 18.100 - libavformat 58. 12.100 / 58. 12.100 - libavdevice 58. 3.100 / 58. 3.100 - libavfilter 7. 16.100 / 7. 16.100 - libavresample 4. 0. 0 / 4. 0. 0 - libswscale 5. 1.100 / 5. 1.100 - libswresample 3. 1.100 / 3. 1.100 - libpostproc 55. 1.100 / 55. 1.100` + header := `ffmpeg version 4.4.1-datarhei Copyright (c) 2000-2021 the FFmpeg developers + built with gcc 10.3.1 (Alpine 10.3.1_git20211027) 20211027 + configuration: --extra-version=datarhei --prefix=/usr --extra-libs='-lpthread -lm -lz -lsupc++ -lstdc++ -lssl -lcrypto -lz -lc -ldl' --enable-nonfree --enable-gpl --enable-version3 --enable-postproc --enable-static --enable-openssl --enable-omx --enable-omx-rpi --enable-mmal --enable-v4l2_m2m --enable-libfreetype --enable-libsrt --enable-libx264 --enable-libx265 --enable-libvpx --enable-libmp3lame --enable-libopus --enable-libvorbis --disable-ffplay --disable-debug --disable-doc --disable-shared + libavutil 56. 70.100 / 56. 70.100 + libavcodec 58.134.100 / 58.134.100 + libavformat 58. 76.100 / 58. 76.100 + libavdevice 58. 13.100 / 58. 13.100 + libavfilter 7.110.100 / 7.110.100 + libswscale 5. 9.100 / 5. 9.100 + libswresample 3. 9.100 / 3. 9.100 + libpostproc 55. 9.100 / 55. 9.100` + + codecs := `Codecs: + D..... = Decoding supported + .E.... = Encoding supported + ..V... = Video codec + ..A... = Audio codec + ..S... = Subtitle codec + ..D... = Data codec + ..T... = Attachment codec + ...I.. = Intra frame-only codec + ....L. = Lossy compression + .....S = Lossless compression + ------- + DEAIL. aac AAC (Advanced Audio Coding) (decoders: aac aac_fixed aac_at ) (encoders: aac aac_at ) + DEVI.S y41p Uncompressed YUV 4:1:1 12-bit + DEV.LS h264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (encoders: libx264 libx264rgb h264_videotoolbox ) + DEV.L. flv1 FLV / Sorenson Spark / Sorenson H.263 (Flash Video) (decoders: flv ) (encoders: flv )` + + filters := `Filters: + T.. = Timeline support + .S. = Slice threading + ..C = Command support + A = Audio input/output + V = Video input/output + N = Dynamic number and/or type of input/output + | = Source or sink filter + ... afirsrc |->A Generate a FIR coefficients audio stream. + ... anoisesrc |->A Generate a noise audio signal. + ... anullsrc |->A Null audio source, return empty audio frames. + ... hilbert |->A Generate a Hilbert transform FIR coefficients. + ... sinc |->A Generate a sinc kaiser-windowed low-pass, high-pass, band-pass, or band-reject FIR coefficients. + ... sine |->A Generate sine wave audio signal. + ... anullsink A->| Do absolutely nothing with the input audio. + ... addroi V->V Add region of interest to frame. + ... alphaextract V->N Extract an alpha channel as a grayscale image component. + T.. alphamerge VV->V Copy the luma value of the second input into the alpha channel of the first input.` + + formats := `File formats: + D. = Demuxing supported + .E = Muxing supported + -- + DE mpeg MPEG-1 Systems / MPEG program stream + E mpeg1video raw MPEG-1 video + E mpeg2video raw MPEG-2 video + DE mpegts MPEG-TS (MPEG-2 Transport Stream) + D mpegtsraw raw MPEG-TS (MPEG-2 Transport Stream) + D mpegvideo raw MPEG video` + + devices := `Devices: + D. = Demuxing supported + .E = Muxing supported + -- + E audiotoolbox AudioToolbox output device + D avfoundation AVFoundation input device + D lavfi Libavfilter virtual input device + E sdl,sdl2 SDL2 output device + D x11grab X11 screen capture, using XCB` + + protocols := `Supported file protocols: +Input: + async + bluray + cache +Output: + crypto + file + ftp + gopher` + + hwaccels := `Hardware acceleration methods: +videotoolbox` + + avfoundation := `[AVFoundation input device @ 0x7fc2db40f240] AVFoundation video devices: +[AVFoundation input device @ 0x7fc2db40f240] [0] FaceTime HD Camera (Built-in) +[AVFoundation input device @ 0x7fc2db40f240] [1] Capture screen 0 +[AVFoundation input device @ 0x7fc2db40f240] [2] Capture screen 1 +[AVFoundation input device @ 0x7fc2db40f240] AVFoundation audio devices: +[AVFoundation input device @ 0x7fc2db40f240] [0] Built-in Microphone +: Input/output error` prelude := `Input #0, lavfi, from 'testsrc=size=1280x720:rate=25': Duration: N/A, start: 0.000000, bitrate: N/A @@ -59,12 +139,38 @@ Output #0, hls, to './data/testsrc.m3u8': os.Exit(2) } + if slices.EqualComparableElements(os.Args[1:], []string{"-f", "avfoundation", "-list_devices", "true", "-i", ""}) { + fmt.Fprintf(os.Stderr, "%s\n", avfoundation) + os.Exit(0) + } + lastArg := os.Args[len(os.Args)-1] if lastArg == "-version" { os.Exit(0) } + switch lastArg { + case "-codecs": + fmt.Fprintf(os.Stderr, "%s\n", codecs) + os.Exit(0) + case "-filters": + fmt.Fprintf(os.Stderr, "%s\n", filters) + os.Exit(0) + case "-formats": + fmt.Fprintf(os.Stderr, "%s\n", formats) + os.Exit(0) + case "-devices": + fmt.Fprintf(os.Stderr, "%s\n", devices) + os.Exit(0) + case "-protocols": + fmt.Fprintf(os.Stderr, "%s\n", protocols) + os.Exit(0) + case "-hwaccels": + fmt.Fprintf(os.Stderr, "%s\n", hwaccels) + os.Exit(0) + } + if len(lastArg) > 1 && lastArg[0] == '-' { os.Exit(2) } diff --git a/restream/restream_test.go b/restream/restream_test.go index 0a876e79..5726a37d 100644 --- a/restream/restream_test.go +++ b/restream/restream_test.go @@ -1389,7 +1389,7 @@ func TestProcessReplacer(t *testing.T) { process = &app.Config{ ID: "314159265359", Reference: "refref", - FFVersion: "^4.0.2", + FFVersion: "^4.4.1", Input: []app.ConfigIO{ { ID: "in_314159265359_refref",