prevent using alwaysAvailableFile and alwaysAvailableTracks together (#5529)
This commit is contained in:
+2
-2
@@ -382,12 +382,12 @@ components:
|
|||||||
# Always available
|
# Always available
|
||||||
alwaysAvailable:
|
alwaysAvailable:
|
||||||
type: boolean
|
type: boolean
|
||||||
alwaysAvailableFile:
|
|
||||||
type: string
|
|
||||||
alwaysAvailableTracks:
|
alwaysAvailableTracks:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/AlwaysAvailableTrack'
|
$ref: '#/components/schemas/AlwaysAvailableTrack'
|
||||||
|
alwaysAvailableFile:
|
||||||
|
type: string
|
||||||
|
|
||||||
# Record
|
# Record
|
||||||
record:
|
record:
|
||||||
|
|||||||
+18
-10
@@ -48,14 +48,12 @@ func TestConfFromFile(t *testing.T) {
|
|||||||
pa, ok := conf.Paths["cam1"]
|
pa, ok := conf.Paths["cam1"]
|
||||||
require.Equal(t, true, ok)
|
require.Equal(t, true, ok)
|
||||||
require.Equal(t, &Path{
|
require.Equal(t, &Path{
|
||||||
Name: "cam1",
|
Name: "cam1",
|
||||||
Source: "publisher",
|
Source: "publisher",
|
||||||
SourceOnDemandStartTimeout: 10 * Duration(time.Second),
|
SourceOnDemandStartTimeout: 10 * Duration(time.Second),
|
||||||
SourceOnDemandCloseAfter: 10 * Duration(time.Second),
|
SourceOnDemandCloseAfter: 10 * Duration(time.Second),
|
||||||
OverridePublisher: true,
|
OverridePublisher: true,
|
||||||
AlwaysAvailableTracks: []AlwaysAvailableTrack{
|
AlwaysAvailableTracks: []AlwaysAvailableTrack{},
|
||||||
{Codec: "H264"},
|
|
||||||
},
|
|
||||||
RecordPath: "./recordings/%path/%Y-%m-%d_%H-%M-%S-%f",
|
RecordPath: "./recordings/%path/%Y-%m-%d_%H-%M-%S-%f",
|
||||||
RecordFormat: RecordFormatFMP4,
|
RecordFormat: RecordFormatFMP4,
|
||||||
RecordPartDuration: Duration(1 * time.Second),
|
RecordPartDuration: Duration(1 * time.Second),
|
||||||
@@ -739,6 +737,16 @@ func TestConfErrors(t *testing.T) {
|
|||||||
"playbackAddress: ''\n",
|
"playbackAddress: ''\n",
|
||||||
"'playbackAddress' must be set when playback is enabled",
|
"'playbackAddress' must be set when playback is enabled",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"alwaysAvailableTracks and alwaysAvailableFile together",
|
||||||
|
"paths:\n" +
|
||||||
|
" mypath:\n" +
|
||||||
|
" alwaysAvailable: yes\n" +
|
||||||
|
" alwaysAvailableTracks:\n" +
|
||||||
|
" - codec: H264\n" +
|
||||||
|
" alwaysAvailableFile: /path/to/file.mp4\n",
|
||||||
|
"'alwaysAvailableFile' and 'alwaysAvailableTracks' cannot be used together",
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(ca.name, func(t *testing.T) {
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
tmpf, err := createTempFile([]byte(ca.conf))
|
tmpf, err := createTempFile([]byte(ca.conf))
|
||||||
@@ -752,7 +760,7 @@ func TestConfErrors(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAlwaysAvailableFileErrorMagicBytes(t *testing.T) {
|
func TestAlwaysAvailableFileErrorMagicBytes(t *testing.T) {
|
||||||
tmpf, err := createTempFile([]byte("not an mp4 file"))
|
tmpf, err := createTempFile([]byte("ABCDEFGHI"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer os.Remove(tmpf)
|
defer os.Remove(tmpf)
|
||||||
|
|
||||||
@@ -764,7 +772,7 @@ func TestAlwaysAvailableFileErrorMagicBytes(t *testing.T) {
|
|||||||
defer os.Remove(tmpConf)
|
defer os.Remove(tmpConf)
|
||||||
|
|
||||||
_, _, err = Load(tmpConf, nil, nil)
|
_, _, err = Load(tmpConf, nil, nil)
|
||||||
require.EqualError(t, err, "invalid 'alwaysAvailableFile': file is not MP4, magic bytes are '[97 110 32 109]'")
|
require.EqualError(t, err, "invalid 'alwaysAvailableFile': file is not MP4, magic bytes are [69 70 71 72]")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSampleConfFile(t *testing.T) {
|
func TestSampleConfFile(t *testing.T) {
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ func checkMP4MagicBytes(f io.ReadSeeker) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !bytes.Equal(magicBytes, []byte("ftyp")) {
|
if !bytes.Equal(magicBytes, []byte("ftyp")) {
|
||||||
return fmt.Errorf("file is not MP4, magic bytes are '%v'", magicBytes)
|
return fmt.Errorf("file is not MP4, magic bytes are %v", magicBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = f.Seek(0, io.SeekStart)
|
_, err = f.Seek(0, io.SeekStart)
|
||||||
@@ -185,8 +185,8 @@ type Path struct {
|
|||||||
|
|
||||||
// Always available
|
// Always available
|
||||||
AlwaysAvailable bool `json:"alwaysAvailable"`
|
AlwaysAvailable bool `json:"alwaysAvailable"`
|
||||||
AlwaysAvailableFile string `json:"alwaysAvailableFile"`
|
|
||||||
AlwaysAvailableTracks []AlwaysAvailableTrack `json:"alwaysAvailableTracks"`
|
AlwaysAvailableTracks []AlwaysAvailableTrack `json:"alwaysAvailableTracks"`
|
||||||
|
AlwaysAvailableFile string `json:"alwaysAvailableFile"`
|
||||||
|
|
||||||
// Record
|
// Record
|
||||||
Record bool `json:"record"`
|
Record bool `json:"record"`
|
||||||
@@ -310,11 +310,6 @@ func (pconf *Path) setDefaults() {
|
|||||||
pconf.SourceOnDemandStartTimeout = 10 * Duration(time.Second)
|
pconf.SourceOnDemandStartTimeout = 10 * Duration(time.Second)
|
||||||
pconf.SourceOnDemandCloseAfter = 10 * Duration(time.Second)
|
pconf.SourceOnDemandCloseAfter = 10 * Duration(time.Second)
|
||||||
|
|
||||||
// Always available
|
|
||||||
pconf.AlwaysAvailableTracks = []AlwaysAvailableTrack{
|
|
||||||
{Codec: "H264"},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Record
|
// Record
|
||||||
pconf.RecordPath = "./recordings/%path/%Y-%m-%d_%H-%M-%S-%f"
|
pconf.RecordPath = "./recordings/%path/%Y-%m-%d_%H-%M-%S-%f"
|
||||||
pconf.RecordFormat = RecordFormatFMP4
|
pconf.RecordFormat = RecordFormatFMP4
|
||||||
@@ -734,6 +729,10 @@ func (pconf *Path) validate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if pconf.AlwaysAvailableFile != "" {
|
if pconf.AlwaysAvailableFile != "" {
|
||||||
|
if len(pconf.AlwaysAvailableTracks) != 0 {
|
||||||
|
return fmt.Errorf("'alwaysAvailableFile' and 'alwaysAvailableTracks' cannot be used together")
|
||||||
|
}
|
||||||
|
|
||||||
err := checkAlwaysAvailableFile(pconf.AlwaysAvailableFile)
|
err := checkAlwaysAvailableFile(pconf.AlwaysAvailableFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("invalid 'alwaysAvailableFile': %w", err)
|
return fmt.Errorf("invalid 'alwaysAvailableFile': %w", err)
|
||||||
|
|||||||
@@ -788,8 +788,8 @@ func (pa *path) setAvailable(desc *description.Session, replaceNTP bool) error {
|
|||||||
pa.stream = &stream.Stream{
|
pa.stream = &stream.Stream{
|
||||||
Desc: desc,
|
Desc: desc,
|
||||||
AlwaysAvailable: pa.conf.AlwaysAvailable,
|
AlwaysAvailable: pa.conf.AlwaysAvailable,
|
||||||
AlwaysAvailableFile: pa.conf.AlwaysAvailableFile,
|
|
||||||
AlwaysAvailableTracks: pa.conf.AlwaysAvailableTracks,
|
AlwaysAvailableTracks: pa.conf.AlwaysAvailableTracks,
|
||||||
|
AlwaysAvailableFile: pa.conf.AlwaysAvailableFile,
|
||||||
WriteQueueSize: pa.writeQueueSize,
|
WriteQueueSize: pa.writeQueueSize,
|
||||||
RTPMaxPayloadSize: pa.rtpMaxPayloadSize,
|
RTPMaxPayloadSize: pa.rtpMaxPayloadSize,
|
||||||
ReplaceNTP: replaceNTP,
|
ReplaceNTP: replaceNTP,
|
||||||
|
|||||||
@@ -221,8 +221,8 @@ func mediasFromAlwaysAvailableTracks(alwaysAvailableTracks []conf.AlwaysAvailabl
|
|||||||
type Stream struct {
|
type Stream struct {
|
||||||
Desc *description.Session
|
Desc *description.Session
|
||||||
AlwaysAvailable bool
|
AlwaysAvailable bool
|
||||||
AlwaysAvailableFile string
|
|
||||||
AlwaysAvailableTracks []conf.AlwaysAvailableTrack
|
AlwaysAvailableTracks []conf.AlwaysAvailableTrack
|
||||||
|
AlwaysAvailableFile string
|
||||||
WriteQueueSize int
|
WriteQueueSize int
|
||||||
RTPMaxPayloadSize int
|
RTPMaxPayloadSize int
|
||||||
ReplaceNTP bool
|
ReplaceNTP bool
|
||||||
|
|||||||
+9
-9
@@ -498,17 +498,17 @@ pathDefaults:
|
|||||||
|
|
||||||
# Enable always-available mode, in which a offline segment is played on repeat when the stream is not available.
|
# Enable always-available mode, in which a offline segment is played on repeat when the stream is not available.
|
||||||
alwaysAvailable: false
|
alwaysAvailable: false
|
||||||
# An MP4 file can be used instead of the default offline segment.
|
|
||||||
alwaysAvailableFile: ''
|
|
||||||
# Tracks of the default offline segment.
|
# Tracks of the default offline segment.
|
||||||
alwaysAvailableTracks:
|
alwaysAvailableTracks: []
|
||||||
# Available values are: AV1, VP9, H265, H264, Opus, MPEG4Audio, G711, LPCM
|
# Available values are: AV1, VP9, H265, H264, Opus, MPEG4Audio, G711, LPCM
|
||||||
- codec: H264
|
# - codec: H264
|
||||||
# in case of MPEG4Audio, G711, LPCM, sampleRate and ChannelCount must be provided too.
|
# # in case of MPEG4Audio, G711, LPCM, sampleRate and ChannelCount must be provided too.
|
||||||
# sampleRate: 48000
|
# sampleRate: 48000
|
||||||
# channelCount: 2
|
# channelCount: 2
|
||||||
# in case of G711, muLaw must be provided too.
|
# # in case of G711, muLaw must be provided too.
|
||||||
# muLaw: false
|
# muLaw: false
|
||||||
|
# A MP4 file can be used instead of the default offline segment.
|
||||||
|
alwaysAvailableFile: ''
|
||||||
|
|
||||||
###############################################
|
###############################################
|
||||||
# Default path settings -> Record
|
# Default path settings -> Record
|
||||||
|
|||||||
Reference in New Issue
Block a user