This commit is contained in:
Jan Stabenow 2024-01-26 15:19:39 +01:00
commit 77dfcbe749
18 changed files with 132 additions and 27 deletions

View File

@ -155,7 +155,7 @@ function SourceIcon(props) {
const id = 'alsa';
const name = <Trans>ALSA</Trans>;
const capabilities = ['audio'];
const ffversion = '^4.1.0 || ^5.0.0';
const ffversion = '^4.1.0 || ^5.0.0 || ^6.1.0';
const func = {
initSettings,

View File

@ -220,7 +220,7 @@ function SourceIcon(props) {
const id = 'avfoundation';
const name = <Trans>AVFoundation</Trans>;
const capabilities = ['audio', 'video'];
const ffversion = '^4.1.0 || ^5.0.0';
const ffversion = '^4.1.0 || ^5.0.0 || ^6.1.0';
const func = {
initSettings,

View File

@ -193,7 +193,7 @@ function SourceIcon(props) {
const id = 'audioloop';
const name = <Trans>Loop</Trans>;
const capabilities = ['audio'];
const ffversion = '^4.1.0 || ^5.0.0';
const ffversion = '^4.1.0 || ^5.0.0 || ^6.1.0';
const func = {
initSettings,

View File

@ -128,7 +128,7 @@ function SourceIcon(props) {
const id = 'fbdev';
const name = <Trans>Framebuffer</Trans>;
const capabilities = ['video'];
const ffversion = '^4.1.0 || ^5.0.0';
const ffversion = '^4.1.0 || ^5.0.0 || ^6.1.0';
const func = {
initSettings,

View File

@ -178,13 +178,15 @@ const initSkills = (initialSkills) => {
};
const createInputs = (settings, config, skills) => {
settings = initSettings(settings);
config = initConfig(config);
settings = initSettings(settings, config);
skills = initSkills(skills);
let ffmpeg_version = 4;
let ffmpeg_version = 6;
if (SemverSatisfies(skills.ffmpeg.version, '^5.0.0')) {
ffmpeg_version = 5;
} else if (SemverSatisfies(skills.ffmpeg.version, '^4.1.0')) {
ffmpeg_version = 4;
}
const input = {
@ -1173,7 +1175,7 @@ function SourceIcon(props) {
const id = 'network';
const name = <Trans>Network source</Trans>;
const capabilities = ['audio', 'video'];
const ffversion = '^4.1.0 || ^5.0.0';
const ffversion = '^4.1.0 || ^5.0.0 || ^6.1.0';
const func = {
initSettings,

View File

@ -4,6 +4,18 @@ import '@testing-library/jest-dom';
import * as Network from './Network';
const $skills_ffmpeg6 = {
ffmpeg: {
version: '6.1.1',
},
formats: {
demuxers: ['rtsp'],
},
protocols: {
input: ['http', 'https', 'rtmp', 'rtmps', 'srt'],
},
};
const $skills_ffmpeg5 = {
ffmpeg: {
version: '5.1.2',
@ -29,6 +41,7 @@ const $skills_ffmpeg4 = {
};
const $config = {
channelid: 'external',
rtmp: {
enabled: true,
app: '/live',
@ -64,9 +77,17 @@ test('source:network pull', async () => {
expect(queryByText(`This protocol is unknown or not supported by the available FFmpeg binary.`)).toBeInTheDocument();
rerender(<Source settings={$settings} skills={$skills_ffmpeg4} onChange={handleChange} />);
expect(queryByText(`This protocol is unknown or not supported by the available FFmpeg binary.`)).toBe(null);
rerender(<Source settings={$settings} skills={$skills_ffmpeg5} onChange={handleChange} />);
expect(queryByText(`This protocol is unknown or not supported by the available FFmpeg binary.`)).toBe(null);
rerender(<Source settings={$settings} skills={$skills_ffmpeg6} onChange={handleChange} />);
expect(queryByText(`This protocol is unknown or not supported by the available FFmpeg binary.`)).toBe(null);
});
const pullmatrix = {
@ -205,6 +226,56 @@ pullmatrix.tests = [
options: ['-fflags', '+genpts', '-thread_queue_size', 512],
},
},
{
name: 'RTSP',
settings: { ...pullmatrix.settings, address: 'rtsp://127.0.0.1/live/stream' },
skills: $skills_ffmpeg6,
input: {
address: 'rtsp://admin:foobar@127.0.0.1/live/stream',
options: ['-fflags', '+genpts', '-thread_queue_size', 512, '-timeout', 5000000, '-rtsp_transport', 'tcp'],
},
},
{
name: 'RTMP',
settings: { ...pullmatrix.settings, address: 'rtmp://127.0.0.1/live/stream' },
skills: $skills_ffmpeg6,
input: {
address: 'rtmp://admin:foobar@127.0.0.1/live/stream',
options: ['-fflags', '+genpts', '-thread_queue_size', 512, '-analyzeduration', 3000000],
},
},
{
name: 'HTTP',
settings: { ...pullmatrix.settings, address: 'http://127.0.0.1/live/stream.m3u8' },
skills: $skills_ffmpeg6,
input: {
address: 'http://admin:foobar@127.0.0.1/live/stream.m3u8',
options: [
'-fflags',
'+genpts',
'-thread_queue_size',
512,
'-analyzeduration',
20000000,
'-re',
'-r',
25,
'-user_agent',
'foobaz/1',
'-referer',
'http://example.com',
],
},
},
{
name: 'SRT',
settings: { ...pullmatrix.settings, address: 'srt://127.0.0.1?mode=caller&streamid=foobar' },
skills: $skills_ffmpeg6,
input: {
address: 'srt://127.0.0.1?mode=caller&streamid=foobar',
options: ['-fflags', '+genpts', '-thread_queue_size', 512],
},
},
];
test.each(pullmatrix.tests)('source:network pull $name input with ffmpeg $skills.ffmpeg.version', async (data) => {
@ -231,6 +302,7 @@ test('source:network push', async () => {
mode: 'push',
push: {
type: 'rtmp',
name: 'external',
},
};
const handleChange = (settings) => {
@ -244,9 +316,17 @@ test('source:network push', async () => {
expect(queryByText(`The available FFmpeg binary doesn't support any of the required protocols.`)).toBeInTheDocument();
rerender(<Source settings={$settings} skills={$skills_ffmpeg4} onChange={handleChange} />);
expect(queryByText(`The available FFmpeg binary doesn't support any of the required protocols.`)).toBe(null);
rerender(<Source settings={$settings} skills={$skills_ffmpeg5} onChange={handleChange} />);
expect(queryByText(`The available FFmpeg binary doesn't support any of the required protocols.`)).toBe(null);
rerender(<Source settings={$settings} skills={$skills_ffmpeg6} onChange={handleChange} />);
expect(queryByText(`The available FFmpeg binary doesn't support any of the required protocols.`)).toBe(null);
});
test('source:network push RTMP', async () => {
@ -254,6 +334,7 @@ test('source:network push RTMP', async () => {
mode: 'push',
push: {
type: 'rtmp',
name: 'external',
},
};
const handleChange = (settings) => {
@ -278,6 +359,7 @@ test('source:network push SRT', async () => {
mode: 'push',
push: {
type: 'srt',
name: 'external',
},
};
const handleChange = (settings) => {
@ -302,6 +384,7 @@ const pushmatrix = {
mode: 'push',
push: {
type: '',
name: 'external',
},
},
tests: [],
@ -348,6 +431,26 @@ pushmatrix.tests = [
options: ['-fflags', '+genpts', '-thread_queue_size', 512],
},
},
{
name: 'RTMP',
settings: { ...pushmatrix.settings, push: { ...pushmatrix.push, type: 'rtmp' } },
skills: $skills_ffmpeg6,
config: $config,
input: {
address: '{rtmp,name=external.stream}',
options: ['-fflags', '+genpts', '-thread_queue_size', 512, '-analyzeduration', 3000000],
},
},
{
name: 'SRT',
settings: { ...pushmatrix.settings, push: { ...pushmatrix.push, type: 'srt' } },
skills: $skills_ffmpeg6,
config: $config,
input: {
address: '{srt,name=external.stream,mode=request}',
options: ['-fflags', '+genpts', '-thread_queue_size', 512],
},
},
];
test.each(pushmatrix.tests)('source:network push $name input with ffmpeg $skills.ffmpeg.version', async (data) => {

View File

@ -44,7 +44,7 @@ function SourceIcon(props) {
const id = 'noaudio';
const name = <Trans>No audio</Trans>;
const capabilities = ['audio'];
const ffversion = '^4.1.0 || ^5.0.0';
const ffversion = '^4.1.0 || ^5.0.0 || ^6.1.0';
const func = {
initSettings,

View File

@ -143,7 +143,7 @@ function SourceIcon(props) {
const id = 'raspicam';
const name = <Trans>Raspberry Pi camera</Trans>;
const capabilities = ['video'];
const ffversion = '^4.1.0 || ^5.0.0';
const ffversion = '^4.1.0 || ^5.0.0 || ^6.1.0';
const func = {
initSettings,

View File

@ -153,7 +153,7 @@ function SourceIcon(props) {
const id = 'video4linux2';
const name = <Trans>Hardware device</Trans>;
const capabilities = ['video'];
const ffversion = '^4.1.0 || ^5.0.0';
const ffversion = '^4.1.0 || ^5.0.0 || ^6.1.0';
const func = {
initSettings,

View File

@ -44,7 +44,7 @@ function SourceIcon(props) {
const id = 'videoaudio';
const name = <Trans>Video source</Trans>;
const capabilities = ['audio'];
const ffversion = '^4.1.0 || ^5.0.0';
const ffversion = '^4.1.0 || ^5.0.0 || ^6.1.0';
const func = {
initSettings,

View File

@ -201,7 +201,7 @@ function SourceIcon(props) {
const id = 'videoloop';
const name = <Trans>Loop</Trans>;
const capabilities = ['video'];
const ffversion = '^4.1.0 || ^5.0.0';
const ffversion = '^4.1.0 || ^5.0.0 || ^6.1.0';
const func = {
initSettings,

View File

@ -186,7 +186,7 @@ function SourceIcon(props) {
const id = 'virtualaudio';
const name = <Trans>Virtual source</Trans>;
const capabilities = ['audio'];
const ffversion = '^4.1.0 || ^5.0.0';
const ffversion = '^4.1.0 || ^5.0.0 || ^6.1.0';
const func = {
initSettings,

View File

@ -205,7 +205,7 @@ function SourceIcon(props) {
const id = 'virtualvideo';
const name = <Trans>Virtual source</Trans>;
const capabilities = ['video'];
const ffversion = '^4.1.0 || ^5.0.0';
const ffversion = '^4.1.0 || ^5.0.0 || ^6.1.0';
const func = {
initSettings,

View File

@ -9,9 +9,9 @@ import * as S from '../../Sources/Network';
import BoxTextarea from '../../../../misc/BoxTextarea';
import Textarea from '../../../../misc/Textarea';
const initSettings = (initialSettings) => {
const initSettings = (initialSettings, config) => {
const settings = {
...S.func.initSettings(initialSettings),
...S.func.initSettings(initialSettings, config),
mode: 'push',
};
@ -21,8 +21,8 @@ const initSettings = (initialSettings) => {
};
function Source(props) {
const settings = initSettings(props.settings);
const config = S.func.initConfig(props.config);
const settings = initSettings(props.settings, config);
const skills = S.func.initSkills(props.skills);
const handleChange = (newSettings) => {

View File

@ -11,9 +11,9 @@ import * as S from '../../Sources/Network';
import BoxTextarea from '../../../../misc/BoxTextarea';
import Textarea from '../../../../misc/Textarea';
const initSettings = (initialSettings) => {
const initSettings = (initialSettings, config) => {
const settings = {
...S.func.initSettings(initialSettings),
...S.func.initSettings(initialSettings, config),
mode: 'push',
};
@ -24,8 +24,8 @@ const initSettings = (initialSettings) => {
function Source(props) {
const navigate = useNavigate();
const settings = initSettings(props.settings);
const config = S.func.initConfig(props.config);
const settings = initSettings(props.settings, config);
const skills = S.func.initSkills(props.skills);
const handleChange = (newSettings) => {

View File

@ -11,9 +11,9 @@ import * as S from '../../Sources/Network';
import BoxTextarea from '../../../../misc/BoxTextarea';
import Textarea from '../../../../misc/Textarea';
const initSettings = (initialSettings) => {
const initSettings = (initialSettings, config) => {
const settings = {
...S.func.initSettings(initialSettings),
...S.func.initSettings(initialSettings, config),
mode: 'push',
};
@ -24,8 +24,8 @@ const initSettings = (initialSettings) => {
function Source(props) {
const navigate = useNavigate();
const settings = initSettings(props.settings);
const config = S.func.initConfig(props.config);
const settings = initSettings(props.settings, config);
const skills = S.func.initSkills(props.skills);
const handleChange = (newSettings) => {

View File

@ -10,9 +10,9 @@ import * as S from '../../Sources/Network';
import Checkbox from '../../../../misc/Checkbox';
import Password from '../../../../misc/Password';
const initSettings = (initialSettings) => {
const initSettings = (initialSettings, config) => {
const settings = {
...S.func.initSettings(initialSettings),
...S.func.initSettings(initialSettings, config),
mode: 'pull',
};
@ -20,8 +20,8 @@ const initSettings = (initialSettings) => {
};
function Source(props) {
const settings = initSettings(props.settings);
const config = S.func.initConfig(props.config);
const settings = initSettings(props.settings, config);
const skills = S.func.initSkills(props.skills);
const handleChange = (newSettings) => {

View File

@ -97,7 +97,7 @@ function Source(props) {
options.push(
<MenuItem key="none" value="none" disabled={true}>
{i18n._(t`No input device available`)}
</MenuItem>
</MenuItem>,
);
}