From b9c7bda69eceaedb134720bbf5c6d35d7940026b Mon Sep 17 00:00:00 2001 From: Ingo Oppermann Date: Mon, 11 Jul 2022 13:22:25 +0200 Subject: [PATCH] Add source selection for publication services --- src/misc/controls/HLS.js | 1 + src/misc/controls/SRT.js | 1 + src/misc/controls/Source.js | 97 +++++++++++++++++++++++++++++++++++ src/utils/metadata.js | 2 +- src/utils/restreamer.js | 8 ++- src/views/Main/index.js | 1 + src/views/Publication/Add.js | 68 +++++++++++++++++++++--- src/views/Publication/Edit.js | 60 ++++++++++++++++++++-- 8 files changed, 227 insertions(+), 11 deletions(-) create mode 100644 src/misc/controls/Source.js diff --git a/src/misc/controls/HLS.js b/src/misc/controls/HLS.js index 588fe4b..1988a8f 100644 --- a/src/misc/controls/HLS.js +++ b/src/misc/controls/HLS.js @@ -43,6 +43,7 @@ export default function Control(props) { props.onChange(settings, false); }; + return ( {/* diff --git a/src/misc/controls/SRT.js b/src/misc/controls/SRT.js index e7b5342..77760b9 100644 --- a/src/misc/controls/SRT.js +++ b/src/misc/controls/SRT.js @@ -38,6 +38,7 @@ export default function Control(props) { props.onChange(settings, false); }; + return ( diff --git a/src/misc/controls/Source.js b/src/misc/controls/Source.js new file mode 100644 index 0000000..2c7cae5 --- /dev/null +++ b/src/misc/controls/Source.js @@ -0,0 +1,97 @@ +import React from 'react'; + +import { Trans } from '@lingui/macro'; +import Grid from '@mui/material/Grid'; +import MenuItem from '@mui/material/MenuItem'; +import Typography from '@mui/material/Typography'; + +import Select from '../Select'; + +function init(settings) { + const initSettings = { + source: 'hls+memfs', + ...settings, + }; + + switch (initSettings.source) { + case 'hls+diskfs': + case 'rtmp': + case 'srt': + break; + default: + initSettings.source = 'hls+memfs'; + } + + return initSettings; +} + +export default function Control(props) { + const settings = init(props.settings); + + // Set the defaults + React.useEffect(() => { + props.onChange(settings, true); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const handleChange = (what) => (event) => { + const value = event.target.value; + + settings[what] = value; + + props.onChange(settings, false); + }; + + const items = []; + + if (props.sources.includes('hls+memfs')) { + items.push( + + HLS (memfs) + + ); + } + + if (props.sources.includes('hls+diskfs')) { + items.push( + + HLS (diskfs) + + ); + } + + if (props.sources.includes('rtmp')) { + items.push( + + RTMP + + ); + } + + if (props.sources.includes('srt')) { + items.push( + + SRT + + ); + } + + return ( + + + + + Stream source for publication service. + + + + ); +} + +Control.defaulProps = { + settings: {}, + sources: [], + onChange: function (settings, automatic) {}, +}; diff --git a/src/utils/metadata.js b/src/utils/metadata.js index ac79c76..844ce97 100644 --- a/src/utils/metadata.js +++ b/src/utils/metadata.js @@ -292,7 +292,7 @@ const defaultEgressMetadata = { staleTimeout: 30, }, source: { - source: 'memfs', + source: 'hls+memfs', }, }, outputs: [], diff --git a/src/utils/restreamer.js b/src/utils/restreamer.js index 64adb6f..df84723 100644 --- a/src/utils/restreamer.js +++ b/src/utils/restreamer.js @@ -2393,8 +2393,14 @@ class Restreamer { // from the inputs only the first is used and only its options are considered. let address = ''; - if (control.source.source === 'memfs') { + if (control.source.source === 'hls+memfs') { address = `{memfs}/${channel.channelid}.m3u8`; + } else if (control.source.source === 'hls+diskfs') { + address = `{diskfs}/${channel.channelid}.m3u8`; + } else if (control.source.source === 'rtmp') { + address = `{rtmp,name=${channel.channelid}.stream}`; + } else if (control.source.source === 'srt') { + address = `{srt,name=${channel.channelid},mode=request}`; } const config = { diff --git a/src/views/Main/index.js b/src/views/Main/index.js index 0924650..e951d55 100644 --- a/src/views/Main/index.js +++ b/src/views/Main/index.js @@ -144,6 +144,7 @@ export default function Main(props) { state.onConnect = null; } } + if ($metadata.control.rtmp.enable) { if (!$config.source.network.rtmp.enabled) { state.state = 'error'; diff --git a/src/views/Publication/Add.js b/src/views/Publication/Add.js index 890cd20..dd7b98e 100644 --- a/src/views/Publication/Add.js +++ b/src/views/Publication/Add.js @@ -31,6 +31,7 @@ import Paper from '../../misc/Paper'; import PaperHeader from '../../misc/PaperHeader'; import PaperFooter from '../../misc/PaperFooter'; import ProcessControl from '../../misc/controls/Process'; +import SourceControl from '../../misc/controls/Source'; import Services from './Services'; import TabPanel from '../../misc/TabPanel'; import TabsVerticalGrid from '../../misc/TabsVerticalGrid'; @@ -70,6 +71,7 @@ export default function Add(props) { const [$service, setService] = React.useState(''); const [$settings, setSettings] = React.useState(M.initEgressMetadata({})); const [$sources, setSources] = React.useState([]); + const [$localSources, setLocalSources] = React.useState([]); const [$filter, setFilter] = React.useState('all'); const [$tab, setTab] = React.useState('general'); const [$skills, setSkills] = React.useState(null); @@ -105,6 +107,20 @@ export default function Add(props) { license: ingest.license, }); + const localSources = []; + + localSources.push('hls+' + ingest.control.hls.storage); + + if (ingest.control.rtmp.enable) { + localSources.push('rtmp'); + } + + if (ingest.control.srt.enable) { + localSources.push('srt'); + } + + setLocalSources(localSources); + setSources(helper.createSourcesFromStreams(ingest.streams)); }; @@ -208,12 +224,12 @@ export default function Add(props) { }); }; - const handleProcessControlChange = (control) => { + const handleControlChange = (what) => (control) => { setSettings({ ...$settings, control: { ...$settings.control, - process: control, + [what]: control, }, }); }; @@ -250,8 +266,6 @@ export default function Add(props) { let service = {}; - const enableProcessing = true; - if ($service === '') { for (let s of Services.List()) { if ($filter !== 'all') { @@ -375,7 +389,8 @@ export default function Add(props) { General} value="general" /> Process control} value="process" /> - {enableProcessing && Encoding} value="encoding" />} + Source} value="source" /> + Encoding} value="encoding" /> @@ -446,7 +461,48 @@ export default function Add(props) { - + + + + + + + + Maintainer:{' '} + + {service.author.maintainer.name} + + + + + + + + + + + + + {service.name} + + v{service.version} + + + + + + + + + Source + + + + diff --git a/src/views/Publication/Edit.js b/src/views/Publication/Edit.js index 9c01c10..80e2837 100644 --- a/src/views/Publication/Edit.js +++ b/src/views/Publication/Edit.js @@ -33,6 +33,7 @@ import Process from './Process'; import ProcessControl from '../../misc/controls/Process'; import ProcessModal from '../../misc/modals/Process'; import Services from './Services'; +import SourceControl from '../../misc/controls/Source'; import TabPanel from '../../misc/TabPanel'; import TabsVerticalGrid from '../../misc/TabsVerticalGrid'; @@ -68,6 +69,7 @@ export default function Edit(props) { const [$ready, setReady] = React.useState(false); const [$settings, setSettings] = React.useState(M.getDefaultEgressMetadata()); const [$sources, setSources] = React.useState([]); + const [$localSources, setLocalSources] = React.useState([]); const [$tab, setTab] = React.useState('general'); const [$progress, setProgress] = React.useState({}); const [$processDetails, setProcessDetails] = React.useState({ @@ -145,6 +147,20 @@ export default function Edit(props) { license: ingest.license, }); + const localSources = []; + + localSources.push('hls+' + ingest.control.hls.storage); + + if (ingest.control.rtmp.enable) { + localSources.push('rtmp'); + } + + if (ingest.control.srt.enable) { + localSources.push('srt'); + } + + setLocalSources(localSources); + const sources = helper.createSourcesFromStreams(ingest.streams); setSources(sources); @@ -247,12 +263,12 @@ export default function Edit(props) { setUnsavedChanges(true); }; - const handleProcessControlChange = (control, automatic) => { + const handleControlChange = (what) => (control, automatic) => { setSettings({ ...$settings, control: { ...$settings.control, - process: control, + [what]: control, }, }); @@ -389,6 +405,7 @@ export default function Edit(props) { General} value="general" /> Process control} value="process" /> + Source} value="source" /> Encoding} value="encoding" /> @@ -454,7 +471,7 @@ export default function Edit(props) { - + @@ -497,6 +514,43 @@ export default function Edit(props) { + + + + + + + + {$service.name} + + v{$service.version} + + + + + + + + + Source + + + + + + + + + + + Maintainer:{' '} + + {$service.author.maintainer.name} + + + + +