api: add missing enums and move all enums in dedicated components (#5576)
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
extends:
|
||||||
|
- recommended
|
||||||
|
|
||||||
|
rules:
|
||||||
|
operation-4xx-response: off
|
||||||
+174
-51
@@ -15,19 +15,158 @@ security: []
|
|||||||
|
|
||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
|
OKStatus:
|
||||||
|
type: string
|
||||||
|
enum: [ok]
|
||||||
|
|
||||||
|
ErrorStatus:
|
||||||
|
type: string
|
||||||
|
enum: [error]
|
||||||
|
|
||||||
|
PathSourceType:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- hlsSource
|
||||||
|
- redirect
|
||||||
|
- rpiCameraSource
|
||||||
|
- rtmpConn
|
||||||
|
- rtmpsConn
|
||||||
|
- rtmpSource
|
||||||
|
- rtspSession
|
||||||
|
- rtspSource
|
||||||
|
- rtspsSession
|
||||||
|
- srtConn
|
||||||
|
- srtSource
|
||||||
|
- mpegtsSource
|
||||||
|
- rtpSource
|
||||||
|
- webRTCSession
|
||||||
|
- webRTCSource
|
||||||
|
|
||||||
|
PathReaderType:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- hlsMuxer
|
||||||
|
- rpiCameraSecondary
|
||||||
|
- rtmpConn
|
||||||
|
- rtmpsConn
|
||||||
|
- rtspConn
|
||||||
|
- rtspSession
|
||||||
|
- rtspsConn
|
||||||
|
- rtspsSession
|
||||||
|
- srtConn
|
||||||
|
- webRTCSession
|
||||||
|
|
||||||
|
PathTrackCodec:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- AV1
|
||||||
|
- VP9
|
||||||
|
- VP8
|
||||||
|
- H265
|
||||||
|
- H264
|
||||||
|
- MPEG-4 Video
|
||||||
|
- MPEG-1 Video
|
||||||
|
- MJPEG
|
||||||
|
- Opus
|
||||||
|
- Vorbis
|
||||||
|
- MPEG-4 Audio
|
||||||
|
- MPEG-4 Audio LATM
|
||||||
|
- MPEG-1 Audio
|
||||||
|
- AC3
|
||||||
|
- Speex
|
||||||
|
- G726
|
||||||
|
- G722
|
||||||
|
- G711
|
||||||
|
- LPCM
|
||||||
|
- MPEG-TS
|
||||||
|
- KLV
|
||||||
|
- Generic
|
||||||
|
|
||||||
|
AlwaysAvailableTrackCodec:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- AV1
|
||||||
|
- VP9
|
||||||
|
- H265
|
||||||
|
- H264
|
||||||
|
- MPEG4Audio
|
||||||
|
- Opus
|
||||||
|
- G711
|
||||||
|
- LPCM
|
||||||
|
|
||||||
|
AuthAction:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- publish
|
||||||
|
- read
|
||||||
|
- playback
|
||||||
|
- api
|
||||||
|
- metrics
|
||||||
|
- pprof
|
||||||
|
|
||||||
|
AuthMethod:
|
||||||
|
type: string
|
||||||
|
enum: [internal, http, jwt]
|
||||||
|
|
||||||
|
Encryption:
|
||||||
|
type: string
|
||||||
|
enum: [no, optional, strict]
|
||||||
|
|
||||||
|
HLSVariant:
|
||||||
|
type: string
|
||||||
|
enum: [mpegts, fmp4, lowLatency]
|
||||||
|
|
||||||
|
LogDestination:
|
||||||
|
type: string
|
||||||
|
enum: [stdout, file, syslog]
|
||||||
|
|
||||||
|
LogLevel:
|
||||||
|
type: string
|
||||||
|
enum: [error, warn, info, debug]
|
||||||
|
|
||||||
|
RecordFormat:
|
||||||
|
type: string
|
||||||
|
enum: [fmp4, mpegts]
|
||||||
|
|
||||||
|
RTSPAuthMethod:
|
||||||
|
type: string
|
||||||
|
enum: [basic, digest]
|
||||||
|
|
||||||
|
RTSPRangeType:
|
||||||
|
type: string
|
||||||
|
enum: ['', clock, npt, smpte]
|
||||||
|
|
||||||
|
RTSPTransport:
|
||||||
|
type: string
|
||||||
|
enum: [udp, multicast, tcp, automatic]
|
||||||
|
|
||||||
|
RTMPConnState:
|
||||||
|
type: string
|
||||||
|
enum: [idle, read, publish]
|
||||||
|
|
||||||
|
RTSPSessionState:
|
||||||
|
type: string
|
||||||
|
enum: [idle, read, publish]
|
||||||
|
|
||||||
|
SRTConnState:
|
||||||
|
type: string
|
||||||
|
enum: [idle, read, publish]
|
||||||
|
|
||||||
|
WebRTCSessionState:
|
||||||
|
type: string
|
||||||
|
enum: [read, publish]
|
||||||
|
|
||||||
OK:
|
OK:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
status:
|
status:
|
||||||
type: string
|
$ref: '#/components/schemas/OKStatus'
|
||||||
enum: [ok]
|
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
status:
|
status:
|
||||||
type: string
|
$ref: '#/components/schemas/ErrorStatus'
|
||||||
enum: [error]
|
|
||||||
error:
|
error:
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
@@ -59,7 +198,7 @@ components:
|
|||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
action:
|
action:
|
||||||
type: string
|
$ref: '#/components/schemas/AuthAction'
|
||||||
path:
|
path:
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
@@ -68,11 +207,11 @@ components:
|
|||||||
properties:
|
properties:
|
||||||
# General
|
# General
|
||||||
logLevel:
|
logLevel:
|
||||||
type: string
|
$ref: '#/components/schemas/LogLevel'
|
||||||
logDestinations:
|
logDestinations:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
type: string
|
$ref: '#/components/schemas/LogDestination'
|
||||||
logStructured:
|
logStructured:
|
||||||
type: boolean
|
type: boolean
|
||||||
logFile:
|
logFile:
|
||||||
@@ -108,7 +247,7 @@ components:
|
|||||||
|
|
||||||
# Authentication
|
# Authentication
|
||||||
authMethod:
|
authMethod:
|
||||||
type: string
|
$ref: '#/components/schemas/AuthMethod'
|
||||||
authInternalUsers:
|
authInternalUsers:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
@@ -250,17 +389,21 @@ components:
|
|||||||
nullable: true
|
nullable: true
|
||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
|
enum: [udp, multicast, tcp]
|
||||||
deprecated: true
|
deprecated: true
|
||||||
rtspTransports:
|
rtspTransports:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
|
enum: [udp, multicast, tcp]
|
||||||
encryption:
|
encryption:
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
deprecated: true
|
deprecated: true
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/Encryption'
|
||||||
rtspEncryption:
|
rtspEncryption:
|
||||||
type: string
|
$ref: '#/components/schemas/Encryption'
|
||||||
rtspAddress:
|
rtspAddress:
|
||||||
type: string
|
type: string
|
||||||
rtspsAddress:
|
rtspsAddress:
|
||||||
@@ -295,12 +438,12 @@ components:
|
|||||||
type: array
|
type: array
|
||||||
nullable: true
|
nullable: true
|
||||||
items:
|
items:
|
||||||
type: string
|
$ref: '#/components/schemas/RTSPAuthMethod'
|
||||||
deprecated: true
|
deprecated: true
|
||||||
rtspAuthMethods:
|
rtspAuthMethods:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
type: string
|
$ref: '#/components/schemas/RTSPAuthMethod'
|
||||||
rtspUDPReadBufferSize:
|
rtspUDPReadBufferSize:
|
||||||
type: integer
|
type: integer
|
||||||
format: uint64
|
format: uint64
|
||||||
@@ -315,7 +458,7 @@ components:
|
|||||||
nullable: true
|
nullable: true
|
||||||
deprecated: true
|
deprecated: true
|
||||||
rtmpEncryption:
|
rtmpEncryption:
|
||||||
type: string
|
$ref: '#/components/schemas/Encryption'
|
||||||
rtmpAddress:
|
rtmpAddress:
|
||||||
type: string
|
type: string
|
||||||
rtmpsAddress:
|
rtmpsAddress:
|
||||||
@@ -355,7 +498,7 @@ components:
|
|||||||
hlsAlwaysRemux:
|
hlsAlwaysRemux:
|
||||||
type: boolean
|
type: boolean
|
||||||
hlsVariant:
|
hlsVariant:
|
||||||
type: string
|
$ref: '#/components/schemas/HLSVariant'
|
||||||
hlsSegmentCount:
|
hlsSegmentCount:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
@@ -461,6 +604,8 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
deprecated: true
|
deprecated: true
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/RecordFormat'
|
||||||
recordPartDuration:
|
recordPartDuration:
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
@@ -523,7 +668,7 @@ components:
|
|||||||
recordPath:
|
recordPath:
|
||||||
type: string
|
type: string
|
||||||
recordFormat:
|
recordFormat:
|
||||||
type: string
|
$ref: '#/components/schemas/RecordFormat'
|
||||||
recordPartDuration:
|
recordPartDuration:
|
||||||
type: string
|
type: string
|
||||||
recordMaxPartSize:
|
recordMaxPartSize:
|
||||||
@@ -575,19 +720,21 @@ components:
|
|||||||
|
|
||||||
# RTSP source
|
# RTSP source
|
||||||
rtspTransport:
|
rtspTransport:
|
||||||
type: string
|
$ref: '#/components/schemas/RTSPTransport'
|
||||||
rtspAnyPort:
|
rtspAnyPort:
|
||||||
type: boolean
|
type: boolean
|
||||||
sourceProtocol:
|
sourceProtocol:
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
deprecated: true
|
deprecated: true
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/RTSPTransport'
|
||||||
sourceAnyPortEnable:
|
sourceAnyPortEnable:
|
||||||
type: boolean
|
type: boolean
|
||||||
nullable: true
|
nullable: true
|
||||||
deprecated: true
|
deprecated: true
|
||||||
rtspRangeType:
|
rtspRangeType:
|
||||||
type: string
|
$ref: '#/components/schemas/RTSPRangeType'
|
||||||
rtspRangeStart:
|
rtspRangeStart:
|
||||||
type: string
|
type: string
|
||||||
rtspUDPReadBufferSize:
|
rtspUDPReadBufferSize:
|
||||||
@@ -801,8 +948,10 @@ components:
|
|||||||
confName:
|
confName:
|
||||||
type: string
|
type: string
|
||||||
source:
|
source:
|
||||||
$ref: '#/components/schemas/PathSource'
|
type: object
|
||||||
nullable: true
|
nullable: true
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/PathSource'
|
||||||
ready:
|
ready:
|
||||||
type: boolean
|
type: boolean
|
||||||
deprecated: true
|
deprecated: true
|
||||||
@@ -823,7 +972,7 @@ components:
|
|||||||
tracks:
|
tracks:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
type: string
|
$ref: '#/components/schemas/PathTrackCodec'
|
||||||
bytesReceived:
|
bytesReceived:
|
||||||
type: integer
|
type: integer
|
||||||
format: uint64
|
format: uint64
|
||||||
@@ -853,22 +1002,7 @@ components:
|
|||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
type:
|
type:
|
||||||
type: string
|
$ref: '#/components/schemas/PathSourceType'
|
||||||
enum:
|
|
||||||
- hlsSource
|
|
||||||
- redirect
|
|
||||||
- rpiCameraSource
|
|
||||||
- rtmpConn
|
|
||||||
- rtmpSource
|
|
||||||
- rtspSession
|
|
||||||
- rtspSource
|
|
||||||
- rtspsSession
|
|
||||||
- srtConn
|
|
||||||
- srtSource
|
|
||||||
- mpegtsSource
|
|
||||||
- rtpSource
|
|
||||||
- webRTCSession
|
|
||||||
- webRTCSource
|
|
||||||
id:
|
id:
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
@@ -876,14 +1010,7 @@ components:
|
|||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
type:
|
type:
|
||||||
type: string
|
$ref: '#/components/schemas/PathReaderType'
|
||||||
enum:
|
|
||||||
- hlsMuxer
|
|
||||||
- rtmpConn
|
|
||||||
- rtspSession
|
|
||||||
- rtspsSession
|
|
||||||
- srtConn
|
|
||||||
- webRTCSession
|
|
||||||
id:
|
id:
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
@@ -955,8 +1082,7 @@ components:
|
|||||||
remoteAddr:
|
remoteAddr:
|
||||||
type: string
|
type: string
|
||||||
state:
|
state:
|
||||||
type: string
|
$ref: '#/components/schemas/RTMPConnState'
|
||||||
enum: [idle, read, publish]
|
|
||||||
path:
|
path:
|
||||||
type: string
|
type: string
|
||||||
query:
|
query:
|
||||||
@@ -1032,8 +1158,7 @@ components:
|
|||||||
remoteAddr:
|
remoteAddr:
|
||||||
type: string
|
type: string
|
||||||
state:
|
state:
|
||||||
type: string
|
$ref: '#/components/schemas/RTSPSessionState'
|
||||||
enum: [idle, read, publish]
|
|
||||||
path:
|
path:
|
||||||
type: string
|
type: string
|
||||||
query:
|
query:
|
||||||
@@ -1107,8 +1232,7 @@ components:
|
|||||||
remoteAddr:
|
remoteAddr:
|
||||||
type: string
|
type: string
|
||||||
state:
|
state:
|
||||||
type: string
|
$ref: '#/components/schemas/SRTConnState'
|
||||||
enum: [idle, read, publish]
|
|
||||||
path:
|
path:
|
||||||
type: string
|
type: string
|
||||||
query:
|
query:
|
||||||
@@ -1344,7 +1468,7 @@ components:
|
|||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
codec:
|
codec:
|
||||||
type: string
|
$ref: '#/components/schemas/AlwaysAvailableTrackCodec'
|
||||||
sampleRate:
|
sampleRate:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
@@ -1383,8 +1507,7 @@ components:
|
|||||||
remoteCandidate:
|
remoteCandidate:
|
||||||
type: string
|
type: string
|
||||||
state:
|
state:
|
||||||
type: string
|
$ref: '#/components/schemas/WebRTCSessionState'
|
||||||
enum: [read, publish]
|
|
||||||
path:
|
path:
|
||||||
type: string
|
type: string
|
||||||
query:
|
query:
|
||||||
|
|||||||
+4
-4
@@ -223,13 +223,13 @@ func (a *API) writeError(ctx *gin.Context, status int, err error) {
|
|||||||
|
|
||||||
// add error to response
|
// add error to response
|
||||||
ctx.JSON(status, &defs.APIError{
|
ctx.JSON(status, &defs.APIError{
|
||||||
Status: "error",
|
Status: defs.APIErrorStatusError,
|
||||||
Error: err.Error(),
|
Error: err.Error(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) writeOK(ctx *gin.Context) {
|
func (a *API) writeOK(ctx *gin.Context) {
|
||||||
ctx.JSON(http.StatusOK, &defs.APIOK{Status: "ok"})
|
ctx.JSON(http.StatusOK, &defs.APIOK{Status: defs.APIOKStatusOK})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) middlewarePreflightRequests(ctx *gin.Context) {
|
func (a *API) middlewarePreflightRequests(ctx *gin.Context) {
|
||||||
@@ -255,7 +255,7 @@ func (a *API) middlewareAuth(ctx *gin.Context) {
|
|||||||
if err.AskCredentials {
|
if err.AskCredentials {
|
||||||
ctx.Header("WWW-Authenticate", `Basic realm="mediamtx"`)
|
ctx.Header("WWW-Authenticate", `Basic realm="mediamtx"`)
|
||||||
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
||||||
Status: "error",
|
Status: defs.APIErrorStatusError,
|
||||||
Error: "authentication error",
|
Error: "authentication error",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@@ -267,7 +267,7 @@ func (a *API) middlewareAuth(ctx *gin.Context) {
|
|||||||
<-time.After(auth.PauseAfterError)
|
<-time.After(auth.PauseAfterError)
|
||||||
|
|
||||||
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
||||||
Status: "error",
|
Status: defs.APIErrorStatusError,
|
||||||
Error: "authentication error",
|
Error: "authentication error",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -38,21 +38,21 @@ func TestPathsList(t *testing.T) {
|
|||||||
"test1": {
|
"test1": {
|
||||||
Name: "test1",
|
Name: "test1",
|
||||||
ConfName: "test1",
|
ConfName: "test1",
|
||||||
Source: &defs.APIPathSource{Type: "publisher", ID: "pub1"},
|
Source: &defs.APIPathSource{Type: defs.APIPathSourceTypeRTSPSession, ID: "pub1"},
|
||||||
Ready: true,
|
Ready: true,
|
||||||
ReadyTime: &now,
|
ReadyTime: &now,
|
||||||
Tracks: []string{"H264", "Opus"},
|
Tracks: []defs.APIPathTrackCodec{defs.APIPathTrackCodecH264, defs.APIPathTrackCodecOpus},
|
||||||
BytesReceived: 1000,
|
BytesReceived: 1000,
|
||||||
BytesSent: 2000,
|
BytesSent: 2000,
|
||||||
Readers: []defs.APIPathReader{
|
Readers: []defs.APIPathReader{
|
||||||
{Type: "reader", ID: "reader1"},
|
{Type: defs.APIPathReaderTypeRTSPSession, ID: "reader1"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"test2": {
|
"test2": {
|
||||||
Name: "test2",
|
Name: "test2",
|
||||||
ConfName: "test2",
|
ConfName: "test2",
|
||||||
Ready: false,
|
Ready: false,
|
||||||
Tracks: []string{},
|
Tracks: []defs.APIPathTrackCodec{},
|
||||||
BytesReceived: 500,
|
BytesReceived: 500,
|
||||||
BytesSent: 100,
|
BytesSent: 100,
|
||||||
Readers: []defs.APIPathReader{},
|
Readers: []defs.APIPathReader{},
|
||||||
@@ -91,15 +91,15 @@ func TestPathsGet(t *testing.T) {
|
|||||||
"mystream": {
|
"mystream": {
|
||||||
Name: "mystream",
|
Name: "mystream",
|
||||||
ConfName: "mystream",
|
ConfName: "mystream",
|
||||||
Source: &defs.APIPathSource{Type: "rtspSession", ID: "session123"},
|
Source: &defs.APIPathSource{Type: defs.APIPathSourceTypeRTSPSession, ID: "session123"},
|
||||||
Ready: true,
|
Ready: true,
|
||||||
ReadyTime: &now,
|
ReadyTime: &now,
|
||||||
Tracks: []string{"H264", "Opus"},
|
Tracks: []defs.APIPathTrackCodec{defs.APIPathTrackCodecH264, defs.APIPathTrackCodecOpus},
|
||||||
BytesReceived: 123456,
|
BytesReceived: 123456,
|
||||||
BytesSent: 789012,
|
BytesSent: 789012,
|
||||||
Readers: []defs.APIPathReader{
|
Readers: []defs.APIPathReader{
|
||||||
{Type: "hlsMuxer", ID: "muxer1"},
|
{Type: defs.APIPathReaderTypeHLSMuxer, ID: "muxer1"},
|
||||||
{Type: "webRTCSession", ID: "session456"},
|
{Type: defs.APIPathReaderTypeWebRTCSession, ID: "session456"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -128,7 +128,7 @@ func TestPathsGet(t *testing.T) {
|
|||||||
require.Equal(t, "mystream", out.ConfName)
|
require.Equal(t, "mystream", out.ConfName)
|
||||||
require.True(t, out.Ready)
|
require.True(t, out.Ready)
|
||||||
require.NotNil(t, out.Source)
|
require.NotNil(t, out.Source)
|
||||||
require.Equal(t, "rtspSession", out.Source.Type)
|
require.Equal(t, defs.APIPathSourceTypeRTSPSession, out.Source.Type)
|
||||||
require.Len(t, out.Tracks, 2)
|
require.Len(t, out.Tracks, 2)
|
||||||
require.Len(t, out.Readers, 2)
|
require.Len(t, out.Readers, 2)
|
||||||
require.Equal(t, uint64(123456), out.BytesReceived)
|
require.Equal(t, uint64(123456), out.BytesReceived)
|
||||||
|
|||||||
@@ -6,32 +6,12 @@ import (
|
|||||||
"github.com/bluenviron/mediamtx/internal/conf/jsonwrapper"
|
"github.com/bluenviron/mediamtx/internal/conf/jsonwrapper"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Codec is a codec of AlwaysAvailableTrack.
|
|
||||||
type Codec string
|
|
||||||
|
|
||||||
// available codecs.
|
|
||||||
const (
|
|
||||||
CodecAV1 Codec = "AV1"
|
|
||||||
CodecVP9 Codec = "VP9"
|
|
||||||
CodecH265 Codec = "H265"
|
|
||||||
CodecH264 Codec = "H264"
|
|
||||||
CodecMPEG4Audio Codec = "MPEG4Audio"
|
|
||||||
CodecOpus Codec = "Opus"
|
|
||||||
CodecG711 Codec = "G711"
|
|
||||||
CodecLPCM Codec = "LPCM"
|
|
||||||
)
|
|
||||||
|
|
||||||
// UnmarshalEnv implements env.Unmarshaler.
|
|
||||||
func (d *Codec) UnmarshalEnv(_ string, v string) error {
|
|
||||||
return jsonwrapper.Unmarshal([]byte(`"`+v+`"`), d)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AlwaysAvailableTrack is an item of alwaysAvailableTracks.
|
// AlwaysAvailableTrack is an item of alwaysAvailableTracks.
|
||||||
type AlwaysAvailableTrack struct {
|
type AlwaysAvailableTrack struct {
|
||||||
Codec Codec `json:"codec"`
|
Codec AlwaysAvailableTrackCodec `json:"codec"`
|
||||||
SampleRate int `json:"sampleRate"`
|
SampleRate int `json:"sampleRate"`
|
||||||
ChannelCount int `json:"channelCount"`
|
ChannelCount int `json:"channelCount"`
|
||||||
MULaw bool `json:"muLaw"`
|
MULaw bool `json:"muLaw"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements json.Unmarshaler.
|
// UnmarshalJSON implements json.Unmarshaler.
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package conf
|
||||||
|
|
||||||
|
import "github.com/bluenviron/mediamtx/internal/conf/jsonwrapper"
|
||||||
|
|
||||||
|
// AlwaysAvailableTrackCodec is a codec of AlwaysAvailableTrack.
|
||||||
|
type AlwaysAvailableTrackCodec string
|
||||||
|
|
||||||
|
// available codecs.
|
||||||
|
const (
|
||||||
|
CodecAV1 AlwaysAvailableTrackCodec = "AV1"
|
||||||
|
CodecVP9 AlwaysAvailableTrackCodec = "VP9"
|
||||||
|
CodecH265 AlwaysAvailableTrackCodec = "H265"
|
||||||
|
CodecH264 AlwaysAvailableTrackCodec = "H264"
|
||||||
|
CodecMPEG4Audio AlwaysAvailableTrackCodec = "MPEG4Audio"
|
||||||
|
CodecOpus AlwaysAvailableTrackCodec = "Opus"
|
||||||
|
CodecG711 AlwaysAvailableTrackCodec = "G711"
|
||||||
|
CodecLPCM AlwaysAvailableTrackCodec = "LPCM"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UnmarshalEnv implements env.Unmarshaler.
|
||||||
|
func (d *AlwaysAvailableTrackCodec) UnmarshalEnv(_ string, v string) error {
|
||||||
|
return jsonwrapper.Unmarshal([]byte(`"`+v+`"`), d)
|
||||||
|
}
|
||||||
+19
-18
@@ -26,6 +26,7 @@ import (
|
|||||||
pwebrtc "github.com/pion/webrtc/v4"
|
pwebrtc "github.com/pion/webrtc/v4"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/bluenviron/mediamtx/internal/defs"
|
||||||
"github.com/bluenviron/mediamtx/internal/protocols/webrtc"
|
"github.com/bluenviron/mediamtx/internal/protocols/webrtc"
|
||||||
"github.com/bluenviron/mediamtx/internal/protocols/whip"
|
"github.com/bluenviron/mediamtx/internal/protocols/whip"
|
||||||
"github.com/bluenviron/mediamtx/internal/test"
|
"github.com/bluenviron/mediamtx/internal/test"
|
||||||
@@ -79,12 +80,12 @@ func TestAPIPathsList(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type path struct {
|
type path struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Source pathSource `json:"source"`
|
Source pathSource `json:"source"`
|
||||||
Ready bool `json:"ready"`
|
Ready bool `json:"ready"`
|
||||||
Tracks []string `json:"tracks"`
|
Tracks []defs.APIPathTrackCodec `json:"tracks"`
|
||||||
BytesReceived uint64 `json:"bytesReceived"`
|
BytesReceived uint64 `json:"bytesReceived"`
|
||||||
BytesSent uint64 `json:"bytesSent"`
|
BytesSent uint64 `json:"bytesSent"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type pathList struct {
|
type pathList struct {
|
||||||
@@ -136,7 +137,7 @@ func TestAPIPathsList(t *testing.T) {
|
|||||||
Type: "rtspSession",
|
Type: "rtspSession",
|
||||||
},
|
},
|
||||||
Ready: true,
|
Ready: true,
|
||||||
Tracks: []string{"H264", "MPEG-4 Audio"},
|
Tracks: []defs.APIPathTrackCodec{defs.APIPathTrackCodecH264, defs.APIPathTrackCodecMPEG4Audio},
|
||||||
BytesReceived: 17,
|
BytesReceived: 17,
|
||||||
}},
|
}},
|
||||||
}, out)
|
}, out)
|
||||||
@@ -184,7 +185,7 @@ func TestAPIPathsList(t *testing.T) {
|
|||||||
Type: "rtspsSession",
|
Type: "rtspsSession",
|
||||||
},
|
},
|
||||||
Ready: true,
|
Ready: true,
|
||||||
Tracks: []string{"H264", "MPEG-4 Audio"},
|
Tracks: []defs.APIPathTrackCodec{defs.APIPathTrackCodecH264, defs.APIPathTrackCodecMPEG4Audio},
|
||||||
}},
|
}},
|
||||||
}, out)
|
}, out)
|
||||||
})
|
})
|
||||||
@@ -213,7 +214,7 @@ func TestAPIPathsList(t *testing.T) {
|
|||||||
Type: "rtspSource",
|
Type: "rtspSource",
|
||||||
},
|
},
|
||||||
Ready: false,
|
Ready: false,
|
||||||
Tracks: []string{},
|
Tracks: []defs.APIPathTrackCodec{},
|
||||||
}},
|
}},
|
||||||
}, out)
|
}, out)
|
||||||
})
|
})
|
||||||
@@ -242,7 +243,7 @@ func TestAPIPathsList(t *testing.T) {
|
|||||||
Type: "rtmpSource",
|
Type: "rtmpSource",
|
||||||
},
|
},
|
||||||
Ready: false,
|
Ready: false,
|
||||||
Tracks: []string{},
|
Tracks: []defs.APIPathTrackCodec{},
|
||||||
}},
|
}},
|
||||||
}, out)
|
}, out)
|
||||||
})
|
})
|
||||||
@@ -271,7 +272,7 @@ func TestAPIPathsList(t *testing.T) {
|
|||||||
Type: "hlsSource",
|
Type: "hlsSource",
|
||||||
},
|
},
|
||||||
Ready: false,
|
Ready: false,
|
||||||
Tracks: []string{},
|
Tracks: []defs.APIPathTrackCodec{},
|
||||||
}},
|
}},
|
||||||
}, out)
|
}, out)
|
||||||
})
|
})
|
||||||
@@ -295,12 +296,12 @@ func TestAPIPathsGet(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type path struct {
|
type path struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Source pathSource `json:"source"`
|
Source pathSource `json:"source"`
|
||||||
Ready bool `json:"Ready"`
|
Ready bool `json:"Ready"`
|
||||||
Tracks []string `json:"tracks"`
|
Tracks []defs.APIPathTrackCodec `json:"tracks"`
|
||||||
BytesReceived uint64 `json:"bytesReceived"`
|
BytesReceived uint64 `json:"bytesReceived"`
|
||||||
BytesSent uint64 `json:"bytesSent"`
|
BytesSent uint64 `json:"bytesSent"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var pathName string
|
var pathName string
|
||||||
@@ -329,7 +330,7 @@ func TestAPIPathsGet(t *testing.T) {
|
|||||||
Type: "rtspSession",
|
Type: "rtspSession",
|
||||||
},
|
},
|
||||||
Ready: true,
|
Ready: true,
|
||||||
Tracks: []string{"H264"},
|
Tracks: []defs.APIPathTrackCodec{defs.APIPathTrackCodecH264},
|
||||||
}, out)
|
}, out)
|
||||||
} else {
|
} else {
|
||||||
res, err := hc.Get("http://localhost:9997/v3/paths/get/" + pathName)
|
res, err := hc.Get("http://localhost:9997/v3/paths/get/" + pathName)
|
||||||
|
|||||||
@@ -655,9 +655,9 @@ func (pa *path) doAPIPathsGet(req pathAPIPathsGetReq) {
|
|||||||
v := pa.source.APISourceDescribe()
|
v := pa.source.APISourceDescribe()
|
||||||
return v
|
return v
|
||||||
}(),
|
}(),
|
||||||
Tracks: func() []string {
|
Tracks: func() []defs.APIPathTrackCodec {
|
||||||
if !pa.isAvailable() {
|
if !pa.isAvailable() {
|
||||||
return []string{}
|
return []defs.APIPathTrackCodec{}
|
||||||
}
|
}
|
||||||
return defs.MediasToCodecs(pa.stream.Desc.Medias)
|
return defs.MediasToCodecs(pa.stream.Desc.Medias)
|
||||||
}(),
|
}(),
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ func (*sourceRedirect) Log(logger.Level, string, ...any) {
|
|||||||
// APISourceDescribe implements source.
|
// APISourceDescribe implements source.
|
||||||
func (*sourceRedirect) APISourceDescribe() *defs.APIPathSource {
|
func (*sourceRedirect) APISourceDescribe() *defs.APIPathSource {
|
||||||
return &defs.APIPathSource{
|
return &defs.APIPathSource{
|
||||||
Type: "redirect",
|
Type: defs.APIPathSourceTypeRedirect,
|
||||||
ID: "",
|
ID: "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-388
@@ -3,62 +3,34 @@ package defs
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
|
|
||||||
"github.com/bluenviron/mediamtx/internal/conf"
|
"github.com/bluenviron/mediamtx/internal/conf"
|
||||||
)
|
)
|
||||||
|
|
||||||
// APIPathManager contains methods used by the API and Metrics server.
|
// APIOKStatus is the status of a successful response.
|
||||||
type APIPathManager interface {
|
type APIOKStatus string
|
||||||
APIPathsList() (*APIPathList, error)
|
|
||||||
APIPathsGet(string) (*APIPath, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIHLSServer contains methods used by the API and Metrics server.
|
// statuses.
|
||||||
type APIHLSServer interface {
|
const (
|
||||||
APIMuxersList() (*APIHLSMuxerList, error)
|
APIOKStatusOK APIOKStatus = "ok"
|
||||||
APIMuxersGet(string) (*APIHLSMuxer, error)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
// APIRTSPServer contains methods used by the API and Metrics server.
|
// APIErrorStatus is the status of an error response.
|
||||||
type APIRTSPServer interface {
|
type APIErrorStatus string
|
||||||
APIConnsList() (*APIRTSPConnsList, error)
|
|
||||||
APIConnsGet(uuid.UUID) (*APIRTSPConn, error)
|
|
||||||
APISessionsList() (*APIRTSPSessionList, error)
|
|
||||||
APISessionsGet(uuid.UUID) (*APIRTSPSession, error)
|
|
||||||
APISessionsKick(uuid.UUID) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIRTMPServer contains methods used by the API and Metrics server.
|
// statuses.
|
||||||
type APIRTMPServer interface {
|
const (
|
||||||
APIConnsList() (*APIRTMPConnList, error)
|
APIErrorStatusError APIErrorStatus = "error"
|
||||||
APIConnsGet(uuid.UUID) (*APIRTMPConn, error)
|
)
|
||||||
APIConnsKick(uuid.UUID) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// APISRTServer contains methods used by the API and Metrics server.
|
|
||||||
type APISRTServer interface {
|
|
||||||
APIConnsList() (*APISRTConnList, error)
|
|
||||||
APIConnsGet(uuid.UUID) (*APISRTConn, error)
|
|
||||||
APIConnsKick(uuid.UUID) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIWebRTCServer contains methods used by the API and Metrics server.
|
|
||||||
type APIWebRTCServer interface {
|
|
||||||
APISessionsList() (*APIWebRTCSessionList, error)
|
|
||||||
APISessionsGet(uuid.UUID) (*APIWebRTCSession, error)
|
|
||||||
APISessionsKick(uuid.UUID) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIOK is returned on success.
|
// APIOK is returned on success.
|
||||||
type APIOK struct {
|
type APIOK struct {
|
||||||
Status string `json:"status"`
|
Status APIOKStatus `json:"status"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// APIError is a generic error.
|
// APIError is a generic error.
|
||||||
type APIError struct {
|
type APIError struct {
|
||||||
Status string `json:"status"`
|
Status APIErrorStatus `json:"status"`
|
||||||
Error string `json:"error"`
|
Error string `json:"error"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// APIInfo is a info response.
|
// APIInfo is a info response.
|
||||||
@@ -73,348 +45,3 @@ type APIPathConfList struct {
|
|||||||
PageCount int `json:"pageCount"`
|
PageCount int `json:"pageCount"`
|
||||||
Items []conf.Path `json:"items"`
|
Items []conf.Path `json:"items"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// APIPathSource is a source.
|
|
||||||
type APIPathSource struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
ID string `json:"id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIPathReader is a reader.
|
|
||||||
type APIPathReader struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
ID string `json:"id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIPath is a path.
|
|
||||||
type APIPath struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
ConfName string `json:"confName"`
|
|
||||||
Ready bool `json:"ready" deprecated:"true"`
|
|
||||||
ReadyTime *time.Time `json:"readyTime" deprecated:"true"`
|
|
||||||
Available bool `json:"available"`
|
|
||||||
AvailableTime *time.Time `json:"availableTime"`
|
|
||||||
Online bool `json:"online"`
|
|
||||||
OnlineTime *time.Time `json:"onlineTime"`
|
|
||||||
Source *APIPathSource `json:"source"`
|
|
||||||
Tracks []string `json:"tracks"`
|
|
||||||
BytesReceived uint64 `json:"bytesReceived"`
|
|
||||||
BytesSent uint64 `json:"bytesSent"`
|
|
||||||
Readers []APIPathReader `json:"readers"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIPathList is a list of paths.
|
|
||||||
type APIPathList struct {
|
|
||||||
ItemCount int `json:"itemCount"`
|
|
||||||
PageCount int `json:"pageCount"`
|
|
||||||
Items []APIPath `json:"items"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIHLSMuxer is an HLS muxer.
|
|
||||||
type APIHLSMuxer struct {
|
|
||||||
Path string `json:"path"`
|
|
||||||
Created time.Time `json:"created"`
|
|
||||||
LastRequest time.Time `json:"lastRequest"`
|
|
||||||
BytesSent uint64 `json:"bytesSent"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIHLSMuxerList is a list of HLS muxers.
|
|
||||||
type APIHLSMuxerList struct {
|
|
||||||
ItemCount int `json:"itemCount"`
|
|
||||||
PageCount int `json:"pageCount"`
|
|
||||||
Items []APIHLSMuxer `json:"items"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIRTMPConnState is the state of a RTMP connection.
|
|
||||||
type APIRTMPConnState string
|
|
||||||
|
|
||||||
// states.
|
|
||||||
const (
|
|
||||||
APIRTMPConnStateIdle APIRTMPConnState = "idle"
|
|
||||||
APIRTMPConnStateRead APIRTMPConnState = "read"
|
|
||||||
APIRTMPConnStatePublish APIRTMPConnState = "publish"
|
|
||||||
)
|
|
||||||
|
|
||||||
// APIRTMPConn is a RTMP connection.
|
|
||||||
type APIRTMPConn struct {
|
|
||||||
ID uuid.UUID `json:"id"`
|
|
||||||
Created time.Time `json:"created"`
|
|
||||||
RemoteAddr string `json:"remoteAddr"`
|
|
||||||
State APIRTMPConnState `json:"state"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
Query string `json:"query"`
|
|
||||||
User string `json:"user"`
|
|
||||||
BytesReceived uint64 `json:"bytesReceived"`
|
|
||||||
BytesSent uint64 `json:"bytesSent"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIRTMPConnList is a list of RTMP connections.
|
|
||||||
type APIRTMPConnList struct {
|
|
||||||
ItemCount int `json:"itemCount"`
|
|
||||||
PageCount int `json:"pageCount"`
|
|
||||||
Items []APIRTMPConn `json:"items"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIRTSPConn is a RTSP connection.
|
|
||||||
type APIRTSPConn struct {
|
|
||||||
ID uuid.UUID `json:"id"`
|
|
||||||
Created time.Time `json:"created"`
|
|
||||||
RemoteAddr string `json:"remoteAddr"`
|
|
||||||
Session *uuid.UUID `json:"session"`
|
|
||||||
Tunnel string `json:"tunnel"`
|
|
||||||
BytesReceived uint64 `json:"bytesReceived"`
|
|
||||||
BytesSent uint64 `json:"bytesSent"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIRTSPConnsList is a list of RTSP connections.
|
|
||||||
type APIRTSPConnsList struct {
|
|
||||||
ItemCount int `json:"itemCount"`
|
|
||||||
PageCount int `json:"pageCount"`
|
|
||||||
Items []APIRTSPConn `json:"items"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIRTSPSessionState is the state of a RTSP session.
|
|
||||||
type APIRTSPSessionState string
|
|
||||||
|
|
||||||
// states.
|
|
||||||
const (
|
|
||||||
APIRTSPSessionStateIdle APIRTSPSessionState = "idle"
|
|
||||||
APIRTSPSessionStateRead APIRTSPSessionState = "read"
|
|
||||||
APIRTSPSessionStatePublish APIRTSPSessionState = "publish"
|
|
||||||
)
|
|
||||||
|
|
||||||
// APIRTSPSession is a RTSP session.
|
|
||||||
type APIRTSPSession struct {
|
|
||||||
ID uuid.UUID `json:"id"`
|
|
||||||
Created time.Time `json:"created"`
|
|
||||||
RemoteAddr string `json:"remoteAddr"`
|
|
||||||
State APIRTSPSessionState `json:"state"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
Query string `json:"query"`
|
|
||||||
User string `json:"user"`
|
|
||||||
Transport *string `json:"transport"`
|
|
||||||
Profile *string `json:"profile"`
|
|
||||||
Conns []uuid.UUID `json:"conns"`
|
|
||||||
BytesReceived uint64 `json:"bytesReceived"`
|
|
||||||
BytesSent uint64 `json:"bytesSent"`
|
|
||||||
RTPPacketsReceived uint64 `json:"rtpPacketsReceived"`
|
|
||||||
RTPPacketsSent uint64 `json:"rtpPacketsSent"`
|
|
||||||
RTPPacketsLost uint64 `json:"rtpPacketsLost"`
|
|
||||||
RTPPacketsInError uint64 `json:"rtpPacketsInError"`
|
|
||||||
RTPPacketsJitter float64 `json:"rtpPacketsJitter"`
|
|
||||||
RTCPPacketsReceived uint64 `json:"rtcpPacketsReceived"`
|
|
||||||
RTCPPacketsSent uint64 `json:"rtcpPacketsSent"`
|
|
||||||
RTCPPacketsInError uint64 `json:"rtcpPacketsInError"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIRTSPSessionList is a list of RTSP sessions.
|
|
||||||
type APIRTSPSessionList struct {
|
|
||||||
ItemCount int `json:"itemCount"`
|
|
||||||
PageCount int `json:"pageCount"`
|
|
||||||
Items []APIRTSPSession `json:"items"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// APISRTConnState is the state of a SRT connection.
|
|
||||||
type APISRTConnState string
|
|
||||||
|
|
||||||
// states.
|
|
||||||
const (
|
|
||||||
APISRTConnStateIdle APISRTConnState = "idle"
|
|
||||||
APISRTConnStateRead APISRTConnState = "read"
|
|
||||||
APISRTConnStatePublish APISRTConnState = "publish"
|
|
||||||
)
|
|
||||||
|
|
||||||
// APISRTConn is a SRT connection.
|
|
||||||
type APISRTConn struct {
|
|
||||||
ID uuid.UUID `json:"id"`
|
|
||||||
Created time.Time `json:"created"`
|
|
||||||
RemoteAddr string `json:"remoteAddr"`
|
|
||||||
State APISRTConnState `json:"state"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
Query string `json:"query"`
|
|
||||||
User string `json:"user"`
|
|
||||||
|
|
||||||
// The metric names/comments are pulled from GoSRT
|
|
||||||
|
|
||||||
// The total number of sent DATA packets, including retransmitted packets
|
|
||||||
PacketsSent uint64 `json:"packetsSent"`
|
|
||||||
// The total number of received DATA packets, including retransmitted packets
|
|
||||||
PacketsReceived uint64 `json:"packetsReceived"`
|
|
||||||
// The total number of unique DATA packets sent by the SRT sender
|
|
||||||
PacketsSentUnique uint64 `json:"packetsSentUnique"`
|
|
||||||
// The total number of unique original, retransmitted or recovered by the packet filter DATA packets
|
|
||||||
// received in time, decrypted without errors and, as a result, scheduled for delivery to the
|
|
||||||
// upstream application by the SRT receiver.
|
|
||||||
PacketsReceivedUnique uint64 `json:"packetsReceivedUnique"`
|
|
||||||
// The total number of data packets considered or reported as lost at the sender side.
|
|
||||||
// Does not correspond to the packets detected as lost at the receiver side.
|
|
||||||
PacketsSendLoss uint64 `json:"packetsSendLoss"`
|
|
||||||
// The total number of SRT DATA packets detected as presently missing (either reordered or lost) at the receiver side
|
|
||||||
PacketsReceivedLoss uint64 `json:"packetsReceivedLoss"`
|
|
||||||
// The total number of retransmitted packets sent by the SRT sender
|
|
||||||
PacketsRetrans uint64 `json:"packetsRetrans"`
|
|
||||||
// The total number of retransmitted packets registered at the receiver side
|
|
||||||
PacketsReceivedRetrans uint64 `json:"packetsReceivedRetrans"`
|
|
||||||
// The total number of sent ACK (Acknowledgement) control packets
|
|
||||||
PacketsSentACK uint64 `json:"packetsSentACK"`
|
|
||||||
// The total number of received ACK (Acknowledgement) control packets
|
|
||||||
PacketsReceivedACK uint64 `json:"packetsReceivedACK"`
|
|
||||||
// The total number of sent NAK (Negative Acknowledgement) control packets
|
|
||||||
PacketsSentNAK uint64 `json:"packetsSentNAK"`
|
|
||||||
// The total number of received NAK (Negative Acknowledgement) control packets
|
|
||||||
PacketsReceivedNAK uint64 `json:"packetsReceivedNAK"`
|
|
||||||
// The total number of sent KM (Key Material) control packets
|
|
||||||
PacketsSentKM uint64 `json:"packetsSentKM"`
|
|
||||||
// The total number of received KM (Key Material) control packets
|
|
||||||
PacketsReceivedKM uint64 `json:"packetsReceivedKM"`
|
|
||||||
// The total accumulated time in microseconds, during which the SRT sender has some data to transmit,
|
|
||||||
// including packets that have been sent, but not yet acknowledged
|
|
||||||
UsSndDuration uint64 `json:"usSndDuration"`
|
|
||||||
// ??
|
|
||||||
PacketsReceivedBelated uint64 `json:"packetsReceivedBelated"`
|
|
||||||
// The total number of dropped by the SRT sender DATA packets that have no chance to be delivered in time
|
|
||||||
PacketsSendDrop uint64 `json:"packetsSendDrop"`
|
|
||||||
// The total number of dropped by the SRT receiver and, as a result,
|
|
||||||
// not delivered to the upstream application DATA packets
|
|
||||||
PacketsReceivedDrop uint64 `json:"packetsReceivedDrop"`
|
|
||||||
// The total number of packets that failed to be decrypted at the receiver side
|
|
||||||
PacketsReceivedUndecrypt uint64 `json:"packetsReceivedUndecrypt"`
|
|
||||||
|
|
||||||
// Same as packetsReceived, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
|
|
||||||
BytesReceived uint64 `json:"bytesReceived"`
|
|
||||||
// Same as packetsSent, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
|
|
||||||
BytesSent uint64 `json:"bytesSent"`
|
|
||||||
// Same as packetsSentUnique, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
|
|
||||||
BytesSentUnique uint64 `json:"bytesSentUnique"`
|
|
||||||
// Same as packetsReceivedUnique, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
|
|
||||||
BytesReceivedUnique uint64 `json:"bytesReceivedUnique"`
|
|
||||||
// Same as packetsReceivedLoss, but expressed in bytes, including payload and all the headers (IP, TCP, SRT),
|
|
||||||
// bytes for the presently missing (either reordered or lost) packets' payloads are estimated
|
|
||||||
// based on the average packet size
|
|
||||||
BytesReceivedLoss uint64 `json:"bytesReceivedLoss"`
|
|
||||||
// Same as packetsRetrans, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
|
|
||||||
BytesRetrans uint64 `json:"bytesRetrans"`
|
|
||||||
// Same as packetsReceivedRetrans, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
|
|
||||||
BytesReceivedRetrans uint64 `json:"bytesReceivedRetrans"`
|
|
||||||
// Same as PacketsReceivedBelated, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
|
|
||||||
BytesReceivedBelated uint64 `json:"bytesReceivedBelated"`
|
|
||||||
// Same as packetsSendDrop, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
|
|
||||||
BytesSendDrop uint64 `json:"bytesSendDrop"`
|
|
||||||
// Same as packetsReceivedDrop, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
|
|
||||||
BytesReceivedDrop uint64 `json:"bytesReceivedDrop"`
|
|
||||||
// Same as packetsReceivedUndecrypt, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
|
|
||||||
BytesReceivedUndecrypt uint64 `json:"bytesReceivedUndecrypt"`
|
|
||||||
|
|
||||||
// Current minimum time interval between which consecutive packets are sent, in microseconds
|
|
||||||
UsPacketsSendPeriod float64 `json:"usPacketsSendPeriod"`
|
|
||||||
// The maximum number of packets that can be "in flight"
|
|
||||||
PacketsFlowWindow uint64 `json:"packetsFlowWindow"`
|
|
||||||
// The number of packets in flight
|
|
||||||
PacketsFlightSize uint64 `json:"packetsFlightSize"`
|
|
||||||
// Smoothed round-trip time (SRTT), an exponentially-weighted moving average (EWMA)
|
|
||||||
// of an endpoint's RTT samples, in milliseconds
|
|
||||||
MsRTT float64 `json:"msRTT"`
|
|
||||||
// Current transmission bandwidth, in Mbps
|
|
||||||
MbpsSendRate float64 `json:"mbpsSendRate"`
|
|
||||||
// Current receiving bandwidth, in Mbps
|
|
||||||
MbpsReceiveRate float64 `json:"mbpsReceiveRate"`
|
|
||||||
// Estimated capacity of the network link, in Mbps
|
|
||||||
MbpsLinkCapacity float64 `json:"mbpsLinkCapacity"`
|
|
||||||
// The available space in the sender's buffer, in bytes
|
|
||||||
BytesAvailSendBuf uint64 `json:"bytesAvailSendBuf"`
|
|
||||||
// The available space in the receiver's buffer, in bytes
|
|
||||||
BytesAvailReceiveBuf uint64 `json:"bytesAvailReceiveBuf"`
|
|
||||||
// Transmission bandwidth limit, in Mbps
|
|
||||||
MbpsMaxBW float64 `json:"mbpsMaxBW"`
|
|
||||||
// Maximum Segment Size (MSS), in bytes
|
|
||||||
ByteMSS uint64 `json:"byteMSS"`
|
|
||||||
// The number of packets in the sender's buffer that are already scheduled
|
|
||||||
// for sending or even possibly sent, but not yet acknowledged
|
|
||||||
PacketsSendBuf uint64 `json:"packetsSendBuf"`
|
|
||||||
// Instantaneous (current) value of packetsSndBuf, but expressed in bytes,
|
|
||||||
// including payload and all headers (IP, TCP, SRT)
|
|
||||||
BytesSendBuf uint64 `json:"bytesSendBuf"`
|
|
||||||
// The timespan (msec) of packets in the sender's buffer (unacknowledged packets)
|
|
||||||
MsSendBuf uint64 `json:"msSendBuf"`
|
|
||||||
// Timestamp-based Packet Delivery Delay value of the peer
|
|
||||||
MsSendTsbPdDelay uint64 `json:"msSendTsbPdDelay"`
|
|
||||||
// The number of acknowledged packets in receiver's buffer
|
|
||||||
PacketsReceiveBuf uint64 `json:"packetsReceiveBuf"`
|
|
||||||
// Instantaneous (current) value of packetsRcvBuf, expressed in bytes, including payload and all headers (IP, TCP, SRT)
|
|
||||||
BytesReceiveBuf uint64 `json:"bytesReceiveBuf"`
|
|
||||||
// The timespan (msec) of acknowledged packets in the receiver's buffer
|
|
||||||
MsReceiveBuf uint64 `json:"msReceiveBuf"`
|
|
||||||
// Timestamp-based Packet Delivery Delay value set on the socket via SRTO_RCVLATENCY or SRTO_LATENCY
|
|
||||||
MsReceiveTsbPdDelay uint64 `json:"msReceiveTsbPdDelay"`
|
|
||||||
// Instant value of the packet reorder tolerance
|
|
||||||
PacketsReorderTolerance uint64 `json:"packetsReorderTolerance"`
|
|
||||||
// Accumulated difference between the current time and the time-to-play of a packet that is received late
|
|
||||||
PacketsReceivedAvgBelatedTime uint64 `json:"packetsReceivedAvgBelatedTime"`
|
|
||||||
// Percentage of resent data vs. sent data
|
|
||||||
PacketsSendLossRate float64 `json:"packetsSendLossRate"`
|
|
||||||
// Percentage of retransmitted data vs. received data
|
|
||||||
PacketsReceivedLossRate float64 `json:"packetsReceivedLossRate"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// APISRTConnList is a list of SRT connections.
|
|
||||||
type APISRTConnList struct {
|
|
||||||
ItemCount int `json:"itemCount"`
|
|
||||||
PageCount int `json:"pageCount"`
|
|
||||||
Items []APISRTConn `json:"items"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIWebRTCSessionState is the state of a WebRTC connection.
|
|
||||||
type APIWebRTCSessionState string
|
|
||||||
|
|
||||||
// states.
|
|
||||||
const (
|
|
||||||
APIWebRTCSessionStateRead APIWebRTCSessionState = "read"
|
|
||||||
APIWebRTCSessionStatePublish APIWebRTCSessionState = "publish"
|
|
||||||
)
|
|
||||||
|
|
||||||
// APIWebRTCSession is a WebRTC session.
|
|
||||||
type APIWebRTCSession struct {
|
|
||||||
ID uuid.UUID `json:"id"`
|
|
||||||
Created time.Time `json:"created"`
|
|
||||||
RemoteAddr string `json:"remoteAddr"`
|
|
||||||
PeerConnectionEstablished bool `json:"peerConnectionEstablished"`
|
|
||||||
LocalCandidate string `json:"localCandidate"`
|
|
||||||
RemoteCandidate string `json:"remoteCandidate"`
|
|
||||||
State APIWebRTCSessionState `json:"state"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
Query string `json:"query"`
|
|
||||||
User string `json:"user"`
|
|
||||||
BytesReceived uint64 `json:"bytesReceived"`
|
|
||||||
BytesSent uint64 `json:"bytesSent"`
|
|
||||||
RTPPacketsReceived uint64 `json:"rtpPacketsReceived"`
|
|
||||||
RTPPacketsSent uint64 `json:"rtpPacketsSent"`
|
|
||||||
RTPPacketsLost uint64 `json:"rtpPacketsLost"`
|
|
||||||
RTPPacketsJitter float64 `json:"rtpPacketsJitter"`
|
|
||||||
RTCPPacketsReceived uint64 `json:"rtcpPacketsReceived"`
|
|
||||||
RTCPPacketsSent uint64 `json:"rtcpPacketsSent"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIWebRTCSessionList is a list of WebRTC sessions.
|
|
||||||
type APIWebRTCSessionList struct {
|
|
||||||
ItemCount int `json:"itemCount"`
|
|
||||||
PageCount int `json:"pageCount"`
|
|
||||||
Items []APIWebRTCSession `json:"items"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIRecordingSegment is a recording segment.
|
|
||||||
type APIRecordingSegment struct {
|
|
||||||
Start time.Time `json:"start"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIRecording is a recording.
|
|
||||||
type APIRecording struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Segments []APIRecordingSegment `json:"segments"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIRecordingList is a list of recordings.
|
|
||||||
type APIRecordingList struct {
|
|
||||||
ItemCount int `json:"itemCount"`
|
|
||||||
PageCount int `json:"pageCount"`
|
|
||||||
Items []APIRecording `json:"items"`
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package defs
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// APIHLSServer contains methods used by the API and Metrics server.
|
||||||
|
type APIHLSServer interface {
|
||||||
|
APIMuxersList() (*APIHLSMuxerList, error)
|
||||||
|
APIMuxersGet(string) (*APIHLSMuxer, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIHLSMuxer is an HLS muxer.
|
||||||
|
type APIHLSMuxer struct {
|
||||||
|
Path string `json:"path"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
LastRequest time.Time `json:"lastRequest"`
|
||||||
|
BytesSent uint64 `json:"bytesSent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIHLSMuxerList is a list of HLS muxers.
|
||||||
|
type APIHLSMuxerList struct {
|
||||||
|
ItemCount int `json:"itemCount"`
|
||||||
|
PageCount int `json:"pageCount"`
|
||||||
|
Items []APIHLSMuxer `json:"items"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
package defs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// APIPathManager contains methods used by the API and Metrics server.
|
||||||
|
type APIPathManager interface {
|
||||||
|
APIPathsList() (*APIPathList, error)
|
||||||
|
APIPathsGet(string) (*APIPath, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIPathSourceType is the type of a path source.
|
||||||
|
type APIPathSourceType string
|
||||||
|
|
||||||
|
// source types.
|
||||||
|
const (
|
||||||
|
APIPathSourceTypeHLSSource APIPathSourceType = "hlsSource"
|
||||||
|
APIPathSourceTypeRedirect APIPathSourceType = "redirect"
|
||||||
|
APIPathSourceTypeRPICameraSource APIPathSourceType = "rpiCameraSource"
|
||||||
|
APIPathSourceTypeRTMPConn APIPathSourceType = "rtmpConn"
|
||||||
|
APIPathSourceTypeRTMPSConn APIPathSourceType = "rtmpsConn"
|
||||||
|
APIPathSourceTypeRTMPSource APIPathSourceType = "rtmpSource"
|
||||||
|
APIPathSourceTypeRTSPSession APIPathSourceType = "rtspSession"
|
||||||
|
APIPathSourceTypeRTSPSource APIPathSourceType = "rtspSource"
|
||||||
|
APIPathSourceTypeRTSPSSession APIPathSourceType = "rtspsSession"
|
||||||
|
APIPathSourceTypeSRTConn APIPathSourceType = "srtConn"
|
||||||
|
APIPathSourceTypeSRTSource APIPathSourceType = "srtSource"
|
||||||
|
APIPathSourceTypeMPEGTSSource APIPathSourceType = "mpegtsSource"
|
||||||
|
APIPathSourceTypeRTPSource APIPathSourceType = "rtpSource"
|
||||||
|
APIPathSourceTypeWebRTCSession APIPathSourceType = "webRTCSession"
|
||||||
|
APIPathSourceTypeWebRTCSource APIPathSourceType = "webRTCSource"
|
||||||
|
)
|
||||||
|
|
||||||
|
// APIPathSource is a source.
|
||||||
|
type APIPathSource struct {
|
||||||
|
Type APIPathSourceType `json:"type"`
|
||||||
|
ID string `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIPathReaderType is the type of a path reader.
|
||||||
|
type APIPathReaderType string
|
||||||
|
|
||||||
|
// reader types.
|
||||||
|
const (
|
||||||
|
APIPathReaderTypeHLSMuxer APIPathReaderType = "hlsMuxer"
|
||||||
|
APIPathReaderTypeRTMPConn APIPathReaderType = "rtmpConn"
|
||||||
|
APIPathReaderTypeRTMPSConn APIPathReaderType = "rtmpsConn"
|
||||||
|
APIPathReaderTypeRTSPConn APIPathReaderType = "rtspConn"
|
||||||
|
APIPathReaderTypeRPICameraSecondary APIPathReaderType = "rpiCameraSecondary"
|
||||||
|
APIPathReaderTypeRTSPSession APIPathReaderType = "rtspSession"
|
||||||
|
APIPathReaderTypeRTSPSConn APIPathReaderType = "rtspsConn"
|
||||||
|
APIPathReaderTypeRTSPSSession APIPathReaderType = "rtspsSession"
|
||||||
|
APIPathReaderTypeSRTConn APIPathReaderType = "srtConn"
|
||||||
|
APIPathReaderTypeWebRTCSession APIPathReaderType = "webRTCSession"
|
||||||
|
)
|
||||||
|
|
||||||
|
// APIPathReader is a reader.
|
||||||
|
type APIPathReader struct {
|
||||||
|
Type APIPathReaderType `json:"type"`
|
||||||
|
ID string `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIPath is a path.
|
||||||
|
type APIPath struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
ConfName string `json:"confName"`
|
||||||
|
Ready bool `json:"ready" deprecated:"true"`
|
||||||
|
ReadyTime *time.Time `json:"readyTime" deprecated:"true"`
|
||||||
|
Available bool `json:"available"`
|
||||||
|
AvailableTime *time.Time `json:"availableTime"`
|
||||||
|
Online bool `json:"online"`
|
||||||
|
OnlineTime *time.Time `json:"onlineTime"`
|
||||||
|
Source *APIPathSource `json:"source"`
|
||||||
|
Tracks []APIPathTrackCodec `json:"tracks"`
|
||||||
|
BytesReceived uint64 `json:"bytesReceived"`
|
||||||
|
BytesSent uint64 `json:"bytesSent"`
|
||||||
|
Readers []APIPathReader `json:"readers"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIPathList is a list of paths.
|
||||||
|
type APIPathList struct {
|
||||||
|
ItemCount int `json:"itemCount"`
|
||||||
|
PageCount int `json:"pageCount"`
|
||||||
|
Items []APIPath `json:"items"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
package defs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/bluenviron/gortsplib/v5/pkg/description"
|
||||||
|
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||||
|
)
|
||||||
|
|
||||||
|
// APIPathTrackCodec is a path track codec.
|
||||||
|
type APIPathTrackCodec string
|
||||||
|
|
||||||
|
// path track codecs.
|
||||||
|
const (
|
||||||
|
// video
|
||||||
|
APIPathTrackCodecAV1 APIPathTrackCodec = "AV1"
|
||||||
|
APIPathTrackCodecVP9 APIPathTrackCodec = "VP9"
|
||||||
|
APIPathTrackCodecVP8 APIPathTrackCodec = "VP8"
|
||||||
|
APIPathTrackCodecH265 APIPathTrackCodec = "H265"
|
||||||
|
APIPathTrackCodecH264 APIPathTrackCodec = "H264"
|
||||||
|
APIPathTrackCodecMPEG4Video APIPathTrackCodec = "MPEG-4 Video"
|
||||||
|
APIPathTrackCodecMPEG1Video APIPathTrackCodec = "MPEG-1 Video"
|
||||||
|
APIPathTrackCodecMJPEG APIPathTrackCodec = "MJPEG"
|
||||||
|
// audio
|
||||||
|
APIPathTrackCodecOpus APIPathTrackCodec = "Opus"
|
||||||
|
APIPathTrackCodecVorbis APIPathTrackCodec = "Vorbis"
|
||||||
|
APIPathTrackCodecMPEG4Audio APIPathTrackCodec = "MPEG-4 Audio"
|
||||||
|
APIPathTrackCodecMPEG4AudioLATM APIPathTrackCodec = "MPEG-4 Audio LATM"
|
||||||
|
APIPathTrackCodecMPEG1Audio APIPathTrackCodec = "MPEG-1 Audio"
|
||||||
|
APIPathTrackCodecAC3 APIPathTrackCodec = "AC3"
|
||||||
|
APIPathTrackCodecSpeex APIPathTrackCodec = "Speex"
|
||||||
|
APIPathTrackCodecG726 APIPathTrackCodec = "G726"
|
||||||
|
APIPathTrackCodecG722 APIPathTrackCodec = "G722"
|
||||||
|
APIPathTrackCodecG711 APIPathTrackCodec = "G711"
|
||||||
|
APIPathTrackCodecLPCM APIPathTrackCodec = "LPCM"
|
||||||
|
// other
|
||||||
|
APIPathTrackCodecMPEGTS APIPathTrackCodec = "MPEG-TS"
|
||||||
|
APIPathTrackCodecKLV APIPathTrackCodec = "KLV"
|
||||||
|
APIPathTrackCodecGeneric APIPathTrackCodec = "Generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FormatsToCodecs returns codecs of given formats.
|
||||||
|
func FormatsToCodecs(formats []format.Format) []APIPathTrackCodec {
|
||||||
|
ret := make([]APIPathTrackCodec, len(formats))
|
||||||
|
|
||||||
|
for i, forma := range formats {
|
||||||
|
switch forma.(type) {
|
||||||
|
// video
|
||||||
|
case *format.AV1:
|
||||||
|
ret[i] = APIPathTrackCodecAV1
|
||||||
|
case *format.VP9:
|
||||||
|
ret[i] = APIPathTrackCodecVP9
|
||||||
|
case *format.VP8:
|
||||||
|
ret[i] = APIPathTrackCodecVP8
|
||||||
|
case *format.H265:
|
||||||
|
ret[i] = APIPathTrackCodecH265
|
||||||
|
case *format.H264:
|
||||||
|
ret[i] = APIPathTrackCodecH264
|
||||||
|
case *format.MPEG4Video:
|
||||||
|
ret[i] = APIPathTrackCodecMPEG4Video
|
||||||
|
case *format.MPEG1Video:
|
||||||
|
ret[i] = APIPathTrackCodecMPEG1Video
|
||||||
|
case *format.MJPEG:
|
||||||
|
ret[i] = APIPathTrackCodecMJPEG
|
||||||
|
// audio
|
||||||
|
case *format.Opus:
|
||||||
|
ret[i] = APIPathTrackCodecOpus
|
||||||
|
case *format.Vorbis:
|
||||||
|
ret[i] = APIPathTrackCodecVorbis
|
||||||
|
case *format.MPEG4Audio:
|
||||||
|
ret[i] = APIPathTrackCodecMPEG4Audio
|
||||||
|
case *format.MPEG4AudioLATM:
|
||||||
|
ret[i] = APIPathTrackCodecMPEG4AudioLATM
|
||||||
|
case *format.MPEG1Audio:
|
||||||
|
ret[i] = APIPathTrackCodecMPEG1Audio
|
||||||
|
case *format.AC3:
|
||||||
|
ret[i] = APIPathTrackCodecAC3
|
||||||
|
case *format.Speex:
|
||||||
|
ret[i] = APIPathTrackCodecSpeex
|
||||||
|
case *format.G726:
|
||||||
|
ret[i] = APIPathTrackCodecG726
|
||||||
|
case *format.G722:
|
||||||
|
ret[i] = APIPathTrackCodecG722
|
||||||
|
case *format.G711:
|
||||||
|
ret[i] = APIPathTrackCodecG711
|
||||||
|
case *format.LPCM:
|
||||||
|
ret[i] = APIPathTrackCodecLPCM
|
||||||
|
// other
|
||||||
|
case *format.MPEGTS:
|
||||||
|
ret[i] = APIPathTrackCodecMPEGTS
|
||||||
|
case *format.KLV:
|
||||||
|
ret[i] = APIPathTrackCodecKLV
|
||||||
|
default:
|
||||||
|
ret[i] = APIPathTrackCodecGeneric
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func gatherFormats(medias []*description.Media) []format.Format {
|
||||||
|
n := 0
|
||||||
|
for _, media := range medias {
|
||||||
|
n += len(media.Formats)
|
||||||
|
}
|
||||||
|
|
||||||
|
if n == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
formats := make([]format.Format, n)
|
||||||
|
n = 0
|
||||||
|
|
||||||
|
for _, media := range medias {
|
||||||
|
n += copy(formats[n:], media.Formats)
|
||||||
|
}
|
||||||
|
|
||||||
|
return formats
|
||||||
|
}
|
||||||
|
|
||||||
|
// MediasToCodecs returns codecs of given medias.
|
||||||
|
func MediasToCodecs(medias []*description.Media) []APIPathTrackCodec {
|
||||||
|
return FormatsToCodecs(gatherFormats(medias))
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package defs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFormatsToCodecs(t *testing.T) {
|
||||||
|
codecs := FormatsToCodecs([]format.Format{
|
||||||
|
&format.AV1{},
|
||||||
|
&format.VP9{},
|
||||||
|
&format.VP8{},
|
||||||
|
&format.H265{},
|
||||||
|
&format.H264{},
|
||||||
|
&format.MPEG4Video{},
|
||||||
|
&format.MPEG1Video{},
|
||||||
|
&format.MJPEG{},
|
||||||
|
&format.Opus{},
|
||||||
|
&format.Vorbis{},
|
||||||
|
&format.MPEG4Audio{},
|
||||||
|
&format.MPEG4AudioLATM{},
|
||||||
|
&format.MPEG1Audio{},
|
||||||
|
&format.AC3{},
|
||||||
|
&format.Speex{},
|
||||||
|
&format.G726{},
|
||||||
|
&format.G722{},
|
||||||
|
&format.G711{},
|
||||||
|
&format.LPCM{},
|
||||||
|
&format.MPEGTS{},
|
||||||
|
&format.KLV{},
|
||||||
|
&format.Generic{},
|
||||||
|
})
|
||||||
|
|
||||||
|
require.Equal(t, []APIPathTrackCodec{
|
||||||
|
APIPathTrackCodecAV1,
|
||||||
|
APIPathTrackCodecVP9,
|
||||||
|
APIPathTrackCodecVP8,
|
||||||
|
APIPathTrackCodecH265,
|
||||||
|
APIPathTrackCodecH264,
|
||||||
|
APIPathTrackCodecMPEG4Video,
|
||||||
|
APIPathTrackCodecMPEG1Video,
|
||||||
|
APIPathTrackCodecMJPEG,
|
||||||
|
APIPathTrackCodecOpus,
|
||||||
|
APIPathTrackCodecVorbis,
|
||||||
|
APIPathTrackCodecMPEG4Audio,
|
||||||
|
APIPathTrackCodecMPEG4AudioLATM,
|
||||||
|
APIPathTrackCodecMPEG1Audio,
|
||||||
|
APIPathTrackCodecAC3,
|
||||||
|
APIPathTrackCodecSpeex,
|
||||||
|
APIPathTrackCodecG726,
|
||||||
|
APIPathTrackCodecG722,
|
||||||
|
APIPathTrackCodecG711,
|
||||||
|
APIPathTrackCodecLPCM,
|
||||||
|
APIPathTrackCodecMPEGTS,
|
||||||
|
APIPathTrackCodecKLV,
|
||||||
|
APIPathTrackCodecGeneric,
|
||||||
|
}, codecs)
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package defs
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// APIRecordingSegment is a recording segment.
|
||||||
|
type APIRecordingSegment struct {
|
||||||
|
Start time.Time `json:"start"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIRecording is a recording.
|
||||||
|
type APIRecording struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Segments []APIRecordingSegment `json:"segments"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIRecordingList is a list of recordings.
|
||||||
|
type APIRecordingList struct {
|
||||||
|
ItemCount int `json:"itemCount"`
|
||||||
|
PageCount int `json:"pageCount"`
|
||||||
|
Items []APIRecording `json:"items"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package defs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// APIRTMPServer contains methods used by the API and Metrics server.
|
||||||
|
type APIRTMPServer interface {
|
||||||
|
APIConnsList() (*APIRTMPConnList, error)
|
||||||
|
APIConnsGet(uuid.UUID) (*APIRTMPConn, error)
|
||||||
|
APIConnsKick(uuid.UUID) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIRTMPConnState is the state of a RTMP connection.
|
||||||
|
type APIRTMPConnState string
|
||||||
|
|
||||||
|
// states.
|
||||||
|
const (
|
||||||
|
APIRTMPConnStateIdle APIRTMPConnState = "idle"
|
||||||
|
APIRTMPConnStateRead APIRTMPConnState = "read"
|
||||||
|
APIRTMPConnStatePublish APIRTMPConnState = "publish"
|
||||||
|
)
|
||||||
|
|
||||||
|
// APIRTMPConn is a RTMP connection.
|
||||||
|
type APIRTMPConn struct {
|
||||||
|
ID uuid.UUID `json:"id"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
RemoteAddr string `json:"remoteAddr"`
|
||||||
|
State APIRTMPConnState `json:"state"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
Query string `json:"query"`
|
||||||
|
User string `json:"user"`
|
||||||
|
BytesReceived uint64 `json:"bytesReceived"`
|
||||||
|
BytesSent uint64 `json:"bytesSent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIRTMPConnList is a list of RTMP connections.
|
||||||
|
type APIRTMPConnList struct {
|
||||||
|
ItemCount int `json:"itemCount"`
|
||||||
|
PageCount int `json:"pageCount"`
|
||||||
|
Items []APIRTMPConn `json:"items"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
package defs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// APIRTSPServer contains methods used by the API and Metrics server.
|
||||||
|
type APIRTSPServer interface {
|
||||||
|
APIConnsList() (*APIRTSPConnsList, error)
|
||||||
|
APIConnsGet(uuid.UUID) (*APIRTSPConn, error)
|
||||||
|
APISessionsList() (*APIRTSPSessionList, error)
|
||||||
|
APISessionsGet(uuid.UUID) (*APIRTSPSession, error)
|
||||||
|
APISessionsKick(uuid.UUID) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIRTSPConn is a RTSP connection.
|
||||||
|
type APIRTSPConn struct {
|
||||||
|
ID uuid.UUID `json:"id"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
RemoteAddr string `json:"remoteAddr"`
|
||||||
|
Session *uuid.UUID `json:"session"`
|
||||||
|
Tunnel string `json:"tunnel"`
|
||||||
|
BytesReceived uint64 `json:"bytesReceived"`
|
||||||
|
BytesSent uint64 `json:"bytesSent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIRTSPConnsList is a list of RTSP connections.
|
||||||
|
type APIRTSPConnsList struct {
|
||||||
|
ItemCount int `json:"itemCount"`
|
||||||
|
PageCount int `json:"pageCount"`
|
||||||
|
Items []APIRTSPConn `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIRTSPSessionState is the state of a RTSP session.
|
||||||
|
type APIRTSPSessionState string
|
||||||
|
|
||||||
|
// states.
|
||||||
|
const (
|
||||||
|
APIRTSPSessionStateIdle APIRTSPSessionState = "idle"
|
||||||
|
APIRTSPSessionStateRead APIRTSPSessionState = "read"
|
||||||
|
APIRTSPSessionStatePublish APIRTSPSessionState = "publish"
|
||||||
|
)
|
||||||
|
|
||||||
|
// APIRTSPSession is a RTSP session.
|
||||||
|
type APIRTSPSession struct {
|
||||||
|
ID uuid.UUID `json:"id"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
RemoteAddr string `json:"remoteAddr"`
|
||||||
|
State APIRTSPSessionState `json:"state"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
Query string `json:"query"`
|
||||||
|
User string `json:"user"`
|
||||||
|
Transport *string `json:"transport"`
|
||||||
|
Profile *string `json:"profile"`
|
||||||
|
Conns []uuid.UUID `json:"conns"`
|
||||||
|
BytesReceived uint64 `json:"bytesReceived"`
|
||||||
|
BytesSent uint64 `json:"bytesSent"`
|
||||||
|
RTPPacketsReceived uint64 `json:"rtpPacketsReceived"`
|
||||||
|
RTPPacketsSent uint64 `json:"rtpPacketsSent"`
|
||||||
|
RTPPacketsLost uint64 `json:"rtpPacketsLost"`
|
||||||
|
RTPPacketsInError uint64 `json:"rtpPacketsInError"`
|
||||||
|
RTPPacketsJitter float64 `json:"rtpPacketsJitter"`
|
||||||
|
RTCPPacketsReceived uint64 `json:"rtcpPacketsReceived"`
|
||||||
|
RTCPPacketsSent uint64 `json:"rtcpPacketsSent"`
|
||||||
|
RTCPPacketsInError uint64 `json:"rtcpPacketsInError"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIRTSPSessionList is a list of RTSP sessions.
|
||||||
|
type APIRTSPSessionList struct {
|
||||||
|
ItemCount int `json:"itemCount"`
|
||||||
|
PageCount int `json:"pageCount"`
|
||||||
|
Items []APIRTSPSession `json:"items"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
package defs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// APISRTServer contains methods used by the API and Metrics server.
|
||||||
|
type APISRTServer interface {
|
||||||
|
APIConnsList() (*APISRTConnList, error)
|
||||||
|
APIConnsGet(uuid.UUID) (*APISRTConn, error)
|
||||||
|
APIConnsKick(uuid.UUID) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// APISRTConnState is the state of a SRT connection.
|
||||||
|
type APISRTConnState string
|
||||||
|
|
||||||
|
// states.
|
||||||
|
const (
|
||||||
|
APISRTConnStateIdle APISRTConnState = "idle"
|
||||||
|
APISRTConnStateRead APISRTConnState = "read"
|
||||||
|
APISRTConnStatePublish APISRTConnState = "publish"
|
||||||
|
)
|
||||||
|
|
||||||
|
// APISRTConn is a SRT connection.
|
||||||
|
type APISRTConn struct {
|
||||||
|
ID uuid.UUID `json:"id"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
RemoteAddr string `json:"remoteAddr"`
|
||||||
|
State APISRTConnState `json:"state"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
Query string `json:"query"`
|
||||||
|
User string `json:"user"`
|
||||||
|
|
||||||
|
// The metric names/comments are pulled from GoSRT
|
||||||
|
|
||||||
|
// The total number of sent DATA packets, including retransmitted packets
|
||||||
|
PacketsSent uint64 `json:"packetsSent"`
|
||||||
|
// The total number of received DATA packets, including retransmitted packets
|
||||||
|
PacketsReceived uint64 `json:"packetsReceived"`
|
||||||
|
// The total number of unique DATA packets sent by the SRT sender
|
||||||
|
PacketsSentUnique uint64 `json:"packetsSentUnique"`
|
||||||
|
// The total number of unique original, retransmitted or recovered by the packet filter DATA packets
|
||||||
|
// received in time, decrypted without errors and, as a result, scheduled for delivery to the
|
||||||
|
// upstream application by the SRT receiver.
|
||||||
|
PacketsReceivedUnique uint64 `json:"packetsReceivedUnique"`
|
||||||
|
// The total number of data packets considered or reported as lost at the sender side.
|
||||||
|
// Does not correspond to the packets detected as lost at the receiver side.
|
||||||
|
PacketsSendLoss uint64 `json:"packetsSendLoss"`
|
||||||
|
// The total number of SRT DATA packets detected as presently missing (either reordered or lost) at the receiver side
|
||||||
|
PacketsReceivedLoss uint64 `json:"packetsReceivedLoss"`
|
||||||
|
// The total number of retransmitted packets sent by the SRT sender
|
||||||
|
PacketsRetrans uint64 `json:"packetsRetrans"`
|
||||||
|
// The total number of retransmitted packets registered at the receiver side
|
||||||
|
PacketsReceivedRetrans uint64 `json:"packetsReceivedRetrans"`
|
||||||
|
// The total number of sent ACK (Acknowledgement) control packets
|
||||||
|
PacketsSentACK uint64 `json:"packetsSentACK"`
|
||||||
|
// The total number of received ACK (Acknowledgement) control packets
|
||||||
|
PacketsReceivedACK uint64 `json:"packetsReceivedACK"`
|
||||||
|
// The total number of sent NAK (Negative Acknowledgement) control packets
|
||||||
|
PacketsSentNAK uint64 `json:"packetsSentNAK"`
|
||||||
|
// The total number of received NAK (Negative Acknowledgement) control packets
|
||||||
|
PacketsReceivedNAK uint64 `json:"packetsReceivedNAK"`
|
||||||
|
// The total number of sent KM (Key Material) control packets
|
||||||
|
PacketsSentKM uint64 `json:"packetsSentKM"`
|
||||||
|
// The total number of received KM (Key Material) control packets
|
||||||
|
PacketsReceivedKM uint64 `json:"packetsReceivedKM"`
|
||||||
|
// The total accumulated time in microseconds, during which the SRT sender has some data to transmit,
|
||||||
|
// including packets that have been sent, but not yet acknowledged
|
||||||
|
UsSndDuration uint64 `json:"usSndDuration"`
|
||||||
|
// ??
|
||||||
|
PacketsReceivedBelated uint64 `json:"packetsReceivedBelated"`
|
||||||
|
// The total number of dropped by the SRT sender DATA packets that have no chance to be delivered in time
|
||||||
|
PacketsSendDrop uint64 `json:"packetsSendDrop"`
|
||||||
|
// The total number of dropped by the SRT receiver and, as a result,
|
||||||
|
// not delivered to the upstream application DATA packets
|
||||||
|
PacketsReceivedDrop uint64 `json:"packetsReceivedDrop"`
|
||||||
|
// The total number of packets that failed to be decrypted at the receiver side
|
||||||
|
PacketsReceivedUndecrypt uint64 `json:"packetsReceivedUndecrypt"`
|
||||||
|
|
||||||
|
// Same as packetsReceived, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
|
||||||
|
BytesReceived uint64 `json:"bytesReceived"`
|
||||||
|
// Same as packetsSent, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
|
||||||
|
BytesSent uint64 `json:"bytesSent"`
|
||||||
|
// Same as packetsSentUnique, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
|
||||||
|
BytesSentUnique uint64 `json:"bytesSentUnique"`
|
||||||
|
// Same as packetsReceivedUnique, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
|
||||||
|
BytesReceivedUnique uint64 `json:"bytesReceivedUnique"`
|
||||||
|
// Same as packetsReceivedLoss, but expressed in bytes, including payload and all the headers (IP, TCP, SRT),
|
||||||
|
// bytes for the presently missing (either reordered or lost) packets' payloads are estimated
|
||||||
|
// based on the average packet size
|
||||||
|
BytesReceivedLoss uint64 `json:"bytesReceivedLoss"`
|
||||||
|
// Same as packetsRetrans, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
|
||||||
|
BytesRetrans uint64 `json:"bytesRetrans"`
|
||||||
|
// Same as packetsReceivedRetrans, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
|
||||||
|
BytesReceivedRetrans uint64 `json:"bytesReceivedRetrans"`
|
||||||
|
// Same as PacketsReceivedBelated, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
|
||||||
|
BytesReceivedBelated uint64 `json:"bytesReceivedBelated"`
|
||||||
|
// Same as packetsSendDrop, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
|
||||||
|
BytesSendDrop uint64 `json:"bytesSendDrop"`
|
||||||
|
// Same as packetsReceivedDrop, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
|
||||||
|
BytesReceivedDrop uint64 `json:"bytesReceivedDrop"`
|
||||||
|
// Same as packetsReceivedUndecrypt, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
|
||||||
|
BytesReceivedUndecrypt uint64 `json:"bytesReceivedUndecrypt"`
|
||||||
|
|
||||||
|
// Current minimum time interval between which consecutive packets are sent, in microseconds
|
||||||
|
UsPacketsSendPeriod float64 `json:"usPacketsSendPeriod"`
|
||||||
|
// The maximum number of packets that can be "in flight"
|
||||||
|
PacketsFlowWindow uint64 `json:"packetsFlowWindow"`
|
||||||
|
// The number of packets in flight
|
||||||
|
PacketsFlightSize uint64 `json:"packetsFlightSize"`
|
||||||
|
// Smoothed round-trip time (SRTT), an exponentially-weighted moving average (EWMA)
|
||||||
|
// of an endpoint's RTT samples, in milliseconds
|
||||||
|
MsRTT float64 `json:"msRTT"`
|
||||||
|
// Current transmission bandwidth, in Mbps
|
||||||
|
MbpsSendRate float64 `json:"mbpsSendRate"`
|
||||||
|
// Current receiving bandwidth, in Mbps
|
||||||
|
MbpsReceiveRate float64 `json:"mbpsReceiveRate"`
|
||||||
|
// Estimated capacity of the network link, in Mbps
|
||||||
|
MbpsLinkCapacity float64 `json:"mbpsLinkCapacity"`
|
||||||
|
// The available space in the sender's buffer, in bytes
|
||||||
|
BytesAvailSendBuf uint64 `json:"bytesAvailSendBuf"`
|
||||||
|
// The available space in the receiver's buffer, in bytes
|
||||||
|
BytesAvailReceiveBuf uint64 `json:"bytesAvailReceiveBuf"`
|
||||||
|
// Transmission bandwidth limit, in Mbps
|
||||||
|
MbpsMaxBW float64 `json:"mbpsMaxBW"`
|
||||||
|
// Maximum Segment Size (MSS), in bytes
|
||||||
|
ByteMSS uint64 `json:"byteMSS"`
|
||||||
|
// The number of packets in the sender's buffer that are already scheduled
|
||||||
|
// for sending or even possibly sent, but not yet acknowledged
|
||||||
|
PacketsSendBuf uint64 `json:"packetsSendBuf"`
|
||||||
|
// Instantaneous (current) value of packetsSndBuf, but expressed in bytes,
|
||||||
|
// including payload and all headers (IP, TCP, SRT)
|
||||||
|
BytesSendBuf uint64 `json:"bytesSendBuf"`
|
||||||
|
// The timespan (msec) of packets in the sender's buffer (unacknowledged packets)
|
||||||
|
MsSendBuf uint64 `json:"msSendBuf"`
|
||||||
|
// Timestamp-based Packet Delivery Delay value of the peer
|
||||||
|
MsSendTsbPdDelay uint64 `json:"msSendTsbPdDelay"`
|
||||||
|
// The number of acknowledged packets in receiver's buffer
|
||||||
|
PacketsReceiveBuf uint64 `json:"packetsReceiveBuf"`
|
||||||
|
// Instantaneous (current) value of packetsRcvBuf, expressed in bytes, including payload and all headers (IP, TCP, SRT)
|
||||||
|
BytesReceiveBuf uint64 `json:"bytesReceiveBuf"`
|
||||||
|
// The timespan (msec) of acknowledged packets in the receiver's buffer
|
||||||
|
MsReceiveBuf uint64 `json:"msReceiveBuf"`
|
||||||
|
// Timestamp-based Packet Delivery Delay value set on the socket via SRTO_RCVLATENCY or SRTO_LATENCY
|
||||||
|
MsReceiveTsbPdDelay uint64 `json:"msReceiveTsbPdDelay"`
|
||||||
|
// Instant value of the packet reorder tolerance
|
||||||
|
PacketsReorderTolerance uint64 `json:"packetsReorderTolerance"`
|
||||||
|
// Accumulated difference between the current time and the time-to-play of a packet that is received late
|
||||||
|
PacketsReceivedAvgBelatedTime uint64 `json:"packetsReceivedAvgBelatedTime"`
|
||||||
|
// Percentage of resent data vs. sent data
|
||||||
|
PacketsSendLossRate float64 `json:"packetsSendLossRate"`
|
||||||
|
// Percentage of retransmitted data vs. received data
|
||||||
|
PacketsReceivedLossRate float64 `json:"packetsReceivedLossRate"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// APISRTConnList is a list of SRT connections.
|
||||||
|
type APISRTConnList struct {
|
||||||
|
ItemCount int `json:"itemCount"`
|
||||||
|
PageCount int `json:"pageCount"`
|
||||||
|
Items []APISRTConn `json:"items"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package defs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// APIWebRTCServer contains methods used by the API and Metrics server.
|
||||||
|
type APIWebRTCServer interface {
|
||||||
|
APISessionsList() (*APIWebRTCSessionList, error)
|
||||||
|
APISessionsGet(uuid.UUID) (*APIWebRTCSession, error)
|
||||||
|
APISessionsKick(uuid.UUID) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIWebRTCSessionState is the state of a WebRTC connection.
|
||||||
|
type APIWebRTCSessionState string
|
||||||
|
|
||||||
|
// states.
|
||||||
|
const (
|
||||||
|
APIWebRTCSessionStateRead APIWebRTCSessionState = "read"
|
||||||
|
APIWebRTCSessionStatePublish APIWebRTCSessionState = "publish"
|
||||||
|
)
|
||||||
|
|
||||||
|
// APIWebRTCSession is a WebRTC session.
|
||||||
|
type APIWebRTCSession struct {
|
||||||
|
ID uuid.UUID `json:"id"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
RemoteAddr string `json:"remoteAddr"`
|
||||||
|
PeerConnectionEstablished bool `json:"peerConnectionEstablished"`
|
||||||
|
LocalCandidate string `json:"localCandidate"`
|
||||||
|
RemoteCandidate string `json:"remoteCandidate"`
|
||||||
|
State APIWebRTCSessionState `json:"state"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
Query string `json:"query"`
|
||||||
|
User string `json:"user"`
|
||||||
|
BytesReceived uint64 `json:"bytesReceived"`
|
||||||
|
BytesSent uint64 `json:"bytesSent"`
|
||||||
|
RTPPacketsReceived uint64 `json:"rtpPacketsReceived"`
|
||||||
|
RTPPacketsSent uint64 `json:"rtpPacketsSent"`
|
||||||
|
RTPPacketsLost uint64 `json:"rtpPacketsLost"`
|
||||||
|
RTPPacketsJitter float64 `json:"rtpPacketsJitter"`
|
||||||
|
RTCPPacketsReceived uint64 `json:"rtcpPacketsReceived"`
|
||||||
|
RTCPPacketsSent uint64 `json:"rtcpPacketsSent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIWebRTCSessionList is a list of WebRTC sessions.
|
||||||
|
type APIWebRTCSessionList struct {
|
||||||
|
ItemCount int `json:"itemCount"`
|
||||||
|
PageCount int `json:"pageCount"`
|
||||||
|
Items []APIWebRTCSession `json:"items"`
|
||||||
|
}
|
||||||
+7
-35
@@ -20,17 +20,14 @@ type Source interface {
|
|||||||
APISourceDescribe() *APIPathSource
|
APISourceDescribe() *APIPathSource
|
||||||
}
|
}
|
||||||
|
|
||||||
// FormatsToCodecs returns the name of codecs of given formats.
|
|
||||||
func FormatsToCodecs(formats []format.Format) []string {
|
|
||||||
ret := make([]string, len(formats))
|
|
||||||
for i, forma := range formats {
|
|
||||||
ret[i] = forma.Codec()
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
// FormatsInfo returns a description of formats.
|
// FormatsInfo returns a description of formats.
|
||||||
func FormatsInfo(formats []format.Format) string {
|
func FormatsInfo(formats []format.Format) string {
|
||||||
|
codecs := FormatsToCodecs(formats)
|
||||||
|
codecNames := make([]string, len(codecs))
|
||||||
|
for i, codec := range codecs {
|
||||||
|
codecNames[i] = string(codec)
|
||||||
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("%d %s (%s)",
|
return fmt.Sprintf("%d %s (%s)",
|
||||||
len(formats),
|
len(formats),
|
||||||
func() string {
|
func() string {
|
||||||
@@ -39,32 +36,7 @@ func FormatsInfo(formats []format.Format) string {
|
|||||||
}
|
}
|
||||||
return "tracks"
|
return "tracks"
|
||||||
}(),
|
}(),
|
||||||
strings.Join(FormatsToCodecs(formats), ", "))
|
strings.Join(codecNames, ", "))
|
||||||
}
|
|
||||||
|
|
||||||
func gatherFormats(medias []*description.Media) []format.Format {
|
|
||||||
n := 0
|
|
||||||
for _, media := range medias {
|
|
||||||
n += len(media.Formats)
|
|
||||||
}
|
|
||||||
|
|
||||||
if n == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
formats := make([]format.Format, n)
|
|
||||||
n = 0
|
|
||||||
|
|
||||||
for _, media := range medias {
|
|
||||||
n += copy(formats[n:], media.Formats)
|
|
||||||
}
|
|
||||||
|
|
||||||
return formats
|
|
||||||
}
|
|
||||||
|
|
||||||
// MediasToCodecs returns the name of codecs of given formats.
|
|
||||||
func MediasToCodecs(medias []*description.Media) []string {
|
|
||||||
return FormatsToCodecs(gatherFormats(medias))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MediasInfo returns a description of medias.
|
// MediasInfo returns a description of medias.
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ func OnConnect(params OnConnectParams) func() {
|
|||||||
_, port, _ := net.SplitHostPort(params.RTSPAddress)
|
_, port, _ := net.SplitHostPort(params.RTSPAddress)
|
||||||
env = externalcmd.Environment{
|
env = externalcmd.Environment{
|
||||||
"RTSP_PORT": port,
|
"RTSP_PORT": port,
|
||||||
"MTX_CONN_TYPE": params.Desc.Type,
|
"MTX_CONN_TYPE": string(params.Desc.Type),
|
||||||
"MTX_CONN_ID": params.Desc.ID,
|
"MTX_CONN_ID": params.Desc.ID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ func OnRead(params OnReadParams) func() {
|
|||||||
env = params.ExternalCmdEnv
|
env = params.ExternalCmdEnv
|
||||||
desc := params.Reader
|
desc := params.Reader
|
||||||
env["MTX_QUERY"] = params.Query
|
env["MTX_QUERY"] = params.Query
|
||||||
env["MTX_READER_TYPE"] = desc.Type
|
env["MTX_READER_TYPE"] = string(desc.Type)
|
||||||
env["MTX_READER_ID"] = desc.ID
|
env["MTX_READER_ID"] = desc.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ func OnReady(params OnReadyParams) func() {
|
|||||||
env = params.ExternalCmdEnv
|
env = params.ExternalCmdEnv
|
||||||
env["MTX_QUERY"] = params.Query
|
env["MTX_QUERY"] = params.Query
|
||||||
if params.Desc != nil {
|
if params.Desc != nil {
|
||||||
env["MTX_SOURCE_TYPE"] = params.Desc.Type
|
env["MTX_SOURCE_TYPE"] = string(params.Desc.Type)
|
||||||
env["MTX_SOURCE_ID"] = params.Desc.ID
|
env["MTX_SOURCE_ID"] = params.Desc.ID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,16 +17,35 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type openAPIProperty struct {
|
type openAPIProperty struct {
|
||||||
Ref string `yaml:"$ref"`
|
Ref string `yaml:"$ref"`
|
||||||
Type string `yaml:"type"`
|
Type string `yaml:"type"`
|
||||||
Format string `yaml:"format"`
|
Format string `yaml:"format"`
|
||||||
Nullable bool `yaml:"nullable"`
|
AllOf []openAPIProperty `yaml:"allOf"`
|
||||||
Deprecated bool `yaml:"deprecated"`
|
Nullable bool `yaml:"nullable"`
|
||||||
Items *openAPIProperty `yaml:"items"`
|
Deprecated bool `yaml:"deprecated"`
|
||||||
|
Enum []string `yaml:"enum"`
|
||||||
|
Items *openAPIProperty `yaml:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func wrapRef(rt reflect.Type, p openAPIProperty) openAPIProperty {
|
||||||
|
if p.Ref == "" {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := goEnumToApi(rt); ok {
|
||||||
|
p.Type = "string"
|
||||||
|
} else if rt.Kind() == reflect.Struct {
|
||||||
|
p.Type = "object"
|
||||||
|
}
|
||||||
|
|
||||||
|
p.AllOf = []openAPIProperty{{Ref: p.Ref}}
|
||||||
|
p.Ref = ""
|
||||||
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
type openAPISchema struct {
|
type openAPISchema struct {
|
||||||
Type string `yaml:"type"`
|
Type string `yaml:"type"`
|
||||||
|
Enum []string `yaml:"enum"`
|
||||||
Properties map[string]openAPIProperty `yaml:"properties"`
|
Properties map[string]openAPIProperty `yaml:"properties"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,13 +55,28 @@ type openAPI struct {
|
|||||||
} `yaml:"components"`
|
} `yaml:"components"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func fillProperty(t *testing.T, rt reflect.Type) openAPIProperty {
|
func schemaName(rt reflect.Type) string {
|
||||||
|
name := strings.TrimPrefix(rt.Name(), "API")
|
||||||
|
|
||||||
|
if rt.PkgPath() == "github.com/bluenviron/mediamtx/internal/conf" && name == "Path" {
|
||||||
|
return "PathConf"
|
||||||
|
}
|
||||||
|
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
func goStructToApi(t *testing.T, rt reflect.Type) openAPIProperty {
|
||||||
if rt.Kind() == reflect.Pointer {
|
if rt.Kind() == reflect.Pointer {
|
||||||
prop := fillProperty(t, rt.Elem())
|
prop := goStructToApi(t, rt.Elem())
|
||||||
|
prop = wrapRef(rt.Elem(), prop)
|
||||||
prop.Nullable = true
|
prop.Nullable = true
|
||||||
return prop
|
return prop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, ok := goEnumToApi(rt); ok {
|
||||||
|
return openAPIProperty{Ref: "#/components/schemas/" + schemaName(rt)}
|
||||||
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case rt == reflect.TypeOf(""):
|
case rt == reflect.TypeOf(""):
|
||||||
return openAPIProperty{Type: "string"}
|
return openAPIProperty{Type: "string"}
|
||||||
@@ -69,22 +103,7 @@ func fillProperty(t *testing.T, rt reflect.Type) openAPIProperty {
|
|||||||
rt == reflect.TypeOf(conf.Duration(0)) ||
|
rt == reflect.TypeOf(conf.Duration(0)) ||
|
||||||
rt == reflect.TypeOf(conf.IPNetwork{}) ||
|
rt == reflect.TypeOf(conf.IPNetwork{}) ||
|
||||||
rt == reflect.TypeOf(conf.Credential("")) ||
|
rt == reflect.TypeOf(conf.Credential("")) ||
|
||||||
rt == reflect.TypeOf(conf.RecordFormat("")) ||
|
rt == reflect.TypeOf(conf.StringSize(0)):
|
||||||
rt == reflect.TypeOf(conf.AuthAction("")) ||
|
|
||||||
rt == reflect.TypeOf(conf.Encryption("")) ||
|
|
||||||
rt == reflect.TypeOf(conf.RTSPTransport{}) ||
|
|
||||||
rt == reflect.TypeOf(conf.StringSize(0)) ||
|
|
||||||
rt == reflect.TypeOf(conf.RTSPRangeType("")) ||
|
|
||||||
rt == reflect.TypeOf(conf.LogLevel(0)) ||
|
|
||||||
rt == reflect.TypeOf(conf.AuthMethod("")) ||
|
|
||||||
rt == reflect.TypeOf(conf.LogDestination(0)) ||
|
|
||||||
rt == reflect.TypeOf(conf.RTSPAuthMethod(0)) ||
|
|
||||||
rt == reflect.TypeOf(conf.HLSVariant(0)) ||
|
|
||||||
rt == reflect.TypeOf(defs.APIRTMPConnState("")) ||
|
|
||||||
rt == reflect.TypeOf(defs.APIWebRTCSessionState("")) ||
|
|
||||||
rt == reflect.TypeOf(defs.APISRTConnState("")) ||
|
|
||||||
rt == reflect.TypeOf(defs.APIRTSPSessionState("")) ||
|
|
||||||
rt == reflect.TypeOf(conf.Codec("")):
|
|
||||||
return openAPIProperty{Type: "string"}
|
return openAPIProperty{Type: "string"}
|
||||||
|
|
||||||
case rt == reflect.TypeOf(conf.RTSPTransports{}):
|
case rt == reflect.TypeOf(conf.RTSPTransports{}):
|
||||||
@@ -92,21 +111,17 @@ func fillProperty(t *testing.T, rt reflect.Type) openAPIProperty {
|
|||||||
Type: "array",
|
Type: "array",
|
||||||
Items: &openAPIProperty{
|
Items: &openAPIProperty{
|
||||||
Type: "string",
|
Type: "string",
|
||||||
|
Enum: []string{"udp", "multicast", "tcp"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
case rt.Kind() == reflect.Struct:
|
case rt.Kind() == reflect.Struct:
|
||||||
schemaName := strings.TrimPrefix(rt.Name(), "API")
|
|
||||||
if rt.PkgPath() == "github.com/bluenviron/mediamtx/internal/conf" && schemaName == "Path" {
|
|
||||||
schemaName = "PathConf"
|
|
||||||
}
|
|
||||||
|
|
||||||
return openAPIProperty{
|
return openAPIProperty{
|
||||||
Ref: "#/components/schemas/" + schemaName,
|
Ref: "#/components/schemas/" + schemaName(rt),
|
||||||
}
|
}
|
||||||
|
|
||||||
case rt.Kind() == reflect.Slice:
|
case rt.Kind() == reflect.Slice:
|
||||||
items := fillProperty(t, rt.Elem())
|
items := goStructToApi(t, rt.Elem())
|
||||||
return openAPIProperty{
|
return openAPIProperty{
|
||||||
Type: "array",
|
Type: "array",
|
||||||
Items: &items,
|
Items: &items,
|
||||||
@@ -118,6 +133,175 @@ func fillProperty(t *testing.T, rt reflect.Type) openAPIProperty {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func goEnumToApi(rt reflect.Type) (openAPISchema, bool) {
|
||||||
|
switch rt {
|
||||||
|
case reflect.TypeOf(defs.APIOKStatus("")):
|
||||||
|
return openAPISchema{Type: "string", Enum: []string{"ok"}}, true
|
||||||
|
|
||||||
|
case reflect.TypeOf(defs.APIErrorStatus("")):
|
||||||
|
return openAPISchema{Type: "string", Enum: []string{"error"}}, true
|
||||||
|
|
||||||
|
case reflect.TypeOf(defs.APIPathSourceType("")):
|
||||||
|
return openAPISchema{Type: "string", Enum: []string{
|
||||||
|
"hlsSource",
|
||||||
|
"redirect",
|
||||||
|
"rpiCameraSource",
|
||||||
|
"rtmpConn",
|
||||||
|
"rtmpsConn",
|
||||||
|
"rtmpSource",
|
||||||
|
"rtspSession",
|
||||||
|
"rtspSource",
|
||||||
|
"rtspsSession",
|
||||||
|
"srtConn",
|
||||||
|
"srtSource",
|
||||||
|
"mpegtsSource",
|
||||||
|
"rtpSource",
|
||||||
|
"webRTCSession",
|
||||||
|
"webRTCSource",
|
||||||
|
}}, true
|
||||||
|
|
||||||
|
case reflect.TypeOf(defs.APIPathReaderType("")):
|
||||||
|
return openAPISchema{Type: "string", Enum: []string{
|
||||||
|
"hlsMuxer",
|
||||||
|
"rpiCameraSecondary",
|
||||||
|
"rtmpConn",
|
||||||
|
"rtmpsConn",
|
||||||
|
"rtspConn",
|
||||||
|
"rtspSession",
|
||||||
|
"rtspsConn",
|
||||||
|
"rtspsSession",
|
||||||
|
"srtConn",
|
||||||
|
"webRTCSession",
|
||||||
|
}}, true
|
||||||
|
|
||||||
|
case reflect.TypeOf(defs.APIPathTrackCodec("")):
|
||||||
|
return openAPISchema{Type: "string", Enum: []string{
|
||||||
|
"AV1",
|
||||||
|
"VP9",
|
||||||
|
"VP8",
|
||||||
|
"H265",
|
||||||
|
"H264",
|
||||||
|
"MPEG-4 Video",
|
||||||
|
"MPEG-1 Video",
|
||||||
|
"MJPEG",
|
||||||
|
"Opus",
|
||||||
|
"Vorbis",
|
||||||
|
"MPEG-4 Audio",
|
||||||
|
"MPEG-4 Audio LATM",
|
||||||
|
"MPEG-1 Audio",
|
||||||
|
"AC3",
|
||||||
|
"Speex",
|
||||||
|
"G726",
|
||||||
|
"G722",
|
||||||
|
"G711",
|
||||||
|
"LPCM",
|
||||||
|
"MPEG-TS",
|
||||||
|
"KLV",
|
||||||
|
"Generic",
|
||||||
|
}}, true
|
||||||
|
|
||||||
|
case reflect.TypeOf(conf.AlwaysAvailableTrackCodec("")):
|
||||||
|
return openAPISchema{Type: "string", Enum: []string{
|
||||||
|
"AV1",
|
||||||
|
"VP9",
|
||||||
|
"H265",
|
||||||
|
"H264",
|
||||||
|
"MPEG4Audio",
|
||||||
|
"Opus",
|
||||||
|
"G711",
|
||||||
|
"LPCM",
|
||||||
|
}}, true
|
||||||
|
|
||||||
|
case reflect.TypeOf(conf.AuthAction("")):
|
||||||
|
return openAPISchema{Type: "string", Enum: []string{
|
||||||
|
"publish",
|
||||||
|
"read",
|
||||||
|
"playback",
|
||||||
|
"api",
|
||||||
|
"metrics",
|
||||||
|
"pprof",
|
||||||
|
}}, true
|
||||||
|
|
||||||
|
case reflect.TypeOf(conf.AuthMethod("")):
|
||||||
|
return openAPISchema{Type: "string", Enum: []string{
|
||||||
|
"internal",
|
||||||
|
"http",
|
||||||
|
"jwt",
|
||||||
|
}}, true
|
||||||
|
|
||||||
|
case reflect.TypeOf(conf.Encryption("")):
|
||||||
|
return openAPISchema{Type: "string", Enum: []string{
|
||||||
|
"no",
|
||||||
|
"optional",
|
||||||
|
"strict",
|
||||||
|
}}, true
|
||||||
|
|
||||||
|
case reflect.TypeOf(conf.HLSVariant(0)):
|
||||||
|
return openAPISchema{Type: "string", Enum: []string{
|
||||||
|
"mpegts",
|
||||||
|
"fmp4",
|
||||||
|
"lowLatency",
|
||||||
|
}}, true
|
||||||
|
|
||||||
|
case reflect.TypeOf(conf.LogDestination(0)):
|
||||||
|
return openAPISchema{Type: "string", Enum: []string{
|
||||||
|
"stdout",
|
||||||
|
"file",
|
||||||
|
"syslog",
|
||||||
|
}}, true
|
||||||
|
|
||||||
|
case reflect.TypeOf(conf.LogLevel(0)):
|
||||||
|
return openAPISchema{Type: "string", Enum: []string{
|
||||||
|
"error",
|
||||||
|
"warn",
|
||||||
|
"info",
|
||||||
|
"debug",
|
||||||
|
}}, true
|
||||||
|
|
||||||
|
case reflect.TypeOf(conf.RecordFormat("")):
|
||||||
|
return openAPISchema{Type: "string", Enum: []string{
|
||||||
|
"fmp4",
|
||||||
|
"mpegts",
|
||||||
|
}}, true
|
||||||
|
|
||||||
|
case reflect.TypeOf(conf.RTSPAuthMethod(0)):
|
||||||
|
return openAPISchema{Type: "string", Enum: []string{
|
||||||
|
"basic",
|
||||||
|
"digest",
|
||||||
|
}}, true
|
||||||
|
|
||||||
|
case reflect.TypeOf(conf.RTSPRangeType("")):
|
||||||
|
return openAPISchema{Type: "string", Enum: []string{
|
||||||
|
"",
|
||||||
|
"clock",
|
||||||
|
"npt",
|
||||||
|
"smpte",
|
||||||
|
}}, true
|
||||||
|
|
||||||
|
case reflect.TypeOf(conf.RTSPTransport{}):
|
||||||
|
return openAPISchema{Type: "string", Enum: []string{
|
||||||
|
"udp",
|
||||||
|
"multicast",
|
||||||
|
"tcp",
|
||||||
|
"automatic",
|
||||||
|
}}, true
|
||||||
|
|
||||||
|
case reflect.TypeOf(defs.APIRTMPConnState("")):
|
||||||
|
return openAPISchema{Type: "string", Enum: []string{"idle", "read", "publish"}}, true
|
||||||
|
|
||||||
|
case reflect.TypeOf(defs.APIWebRTCSessionState("")):
|
||||||
|
return openAPISchema{Type: "string", Enum: []string{"read", "publish"}}, true
|
||||||
|
|
||||||
|
case reflect.TypeOf(defs.APISRTConnState("")):
|
||||||
|
return openAPISchema{Type: "string", Enum: []string{"idle", "read", "publish"}}, true
|
||||||
|
|
||||||
|
case reflect.TypeOf(defs.APIRTSPSessionState("")):
|
||||||
|
return openAPISchema{Type: "string", Enum: []string{"idle", "read", "publish"}}, true
|
||||||
|
}
|
||||||
|
|
||||||
|
return openAPISchema{}, false
|
||||||
|
}
|
||||||
|
|
||||||
func TestGo2API(t *testing.T) {
|
func TestGo2API(t *testing.T) {
|
||||||
byts, err := os.ReadFile("../../../api/openapi.yaml")
|
byts, err := os.ReadFile("../../../api/openapi.yaml")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -126,140 +310,177 @@ func TestGo2API(t *testing.T) {
|
|||||||
err = yaml.Unmarshal(byts, &doc)
|
err = yaml.Unmarshal(byts, &doc)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
for _, ca := range []struct {
|
t.Run("structs", func(t *testing.T) {
|
||||||
openAPIKey string
|
for _, ca := range []struct {
|
||||||
goStruct any
|
openAPIKey string
|
||||||
}{
|
goStruct any
|
||||||
{
|
}{
|
||||||
"AlwaysAvailableTrack",
|
{
|
||||||
conf.AlwaysAvailableTrack{},
|
"AlwaysAvailableTrack",
|
||||||
},
|
conf.AlwaysAvailableTrack{},
|
||||||
{
|
},
|
||||||
"AuthInternalUser",
|
{
|
||||||
conf.AuthInternalUser{},
|
"AuthInternalUser",
|
||||||
},
|
conf.AuthInternalUser{},
|
||||||
{
|
},
|
||||||
"AuthInternalUserPermission",
|
{
|
||||||
conf.AuthInternalUserPermission{},
|
"AuthInternalUserPermission",
|
||||||
},
|
conf.AuthInternalUserPermission{},
|
||||||
{
|
},
|
||||||
"GlobalConf",
|
{
|
||||||
conf.Conf{},
|
"GlobalConf",
|
||||||
},
|
conf.Conf{},
|
||||||
{
|
},
|
||||||
"HLSMuxer",
|
{
|
||||||
defs.APIHLSMuxer{},
|
"HLSMuxer",
|
||||||
},
|
defs.APIHLSMuxer{},
|
||||||
{
|
},
|
||||||
"HLSMuxerList",
|
{
|
||||||
defs.APIHLSMuxerList{},
|
"HLSMuxerList",
|
||||||
},
|
defs.APIHLSMuxerList{},
|
||||||
{
|
},
|
||||||
"Info",
|
{
|
||||||
defs.APIInfo{},
|
"Info",
|
||||||
},
|
defs.APIInfo{},
|
||||||
{
|
},
|
||||||
"Path",
|
{
|
||||||
defs.APIPath{},
|
"Path",
|
||||||
},
|
defs.APIPath{},
|
||||||
{
|
},
|
||||||
"PathConf",
|
{
|
||||||
conf.Path{},
|
"PathConf",
|
||||||
},
|
conf.Path{},
|
||||||
{
|
},
|
||||||
"PathConfList",
|
{
|
||||||
defs.APIPathConfList{},
|
"PathConfList",
|
||||||
},
|
defs.APIPathConfList{},
|
||||||
{
|
},
|
||||||
"PathList",
|
{
|
||||||
defs.APIPathList{},
|
"PathList",
|
||||||
},
|
defs.APIPathList{},
|
||||||
{
|
},
|
||||||
"PathReader",
|
{
|
||||||
defs.APIPathReader{},
|
"PathReader",
|
||||||
},
|
defs.APIPathReader{},
|
||||||
{
|
},
|
||||||
"PathSource",
|
{
|
||||||
defs.APIPathSource{},
|
"PathSource",
|
||||||
},
|
defs.APIPathSource{},
|
||||||
{
|
},
|
||||||
"Recording",
|
{
|
||||||
defs.APIRecording{},
|
"Recording",
|
||||||
},
|
defs.APIRecording{},
|
||||||
{
|
},
|
||||||
"RecordingList",
|
{
|
||||||
defs.APIRecordingList{},
|
"RecordingList",
|
||||||
},
|
defs.APIRecordingList{},
|
||||||
{
|
},
|
||||||
"RecordingSegment",
|
{
|
||||||
defs.APIRecordingSegment{},
|
"RecordingSegment",
|
||||||
},
|
defs.APIRecordingSegment{},
|
||||||
{
|
},
|
||||||
"RTMPConn",
|
{
|
||||||
defs.APIRTMPConn{},
|
"RTMPConn",
|
||||||
},
|
defs.APIRTMPConn{},
|
||||||
{
|
},
|
||||||
"RTMPConnList",
|
{
|
||||||
defs.APIRTMPConnList{},
|
"RTMPConnList",
|
||||||
},
|
defs.APIRTMPConnList{},
|
||||||
{
|
},
|
||||||
"RTSPConn",
|
{
|
||||||
defs.APIRTSPConn{},
|
"RTSPConn",
|
||||||
},
|
defs.APIRTSPConn{},
|
||||||
{
|
},
|
||||||
"RTSPConnList",
|
{
|
||||||
defs.APIRTSPConnsList{},
|
"RTSPConnList",
|
||||||
},
|
defs.APIRTSPConnsList{},
|
||||||
{
|
},
|
||||||
"RTSPSession",
|
{
|
||||||
defs.APIRTSPSession{},
|
"RTSPSession",
|
||||||
},
|
defs.APIRTSPSession{},
|
||||||
{
|
},
|
||||||
"RTSPSessionList",
|
{
|
||||||
defs.APIRTSPSessionList{},
|
"RTSPSessionList",
|
||||||
},
|
defs.APIRTSPSessionList{},
|
||||||
{
|
},
|
||||||
"SRTConn",
|
{
|
||||||
defs.APISRTConn{},
|
"SRTConn",
|
||||||
},
|
defs.APISRTConn{},
|
||||||
{
|
},
|
||||||
"SRTConnList",
|
{
|
||||||
defs.APISRTConnList{},
|
"SRTConnList",
|
||||||
},
|
defs.APISRTConnList{},
|
||||||
{
|
},
|
||||||
"WebRTCSession",
|
{
|
||||||
defs.APIWebRTCSession{},
|
"WebRTCSession",
|
||||||
},
|
defs.APIWebRTCSession{},
|
||||||
{
|
},
|
||||||
"WebRTCSessionList",
|
{
|
||||||
defs.APIWebRTCSessionList{},
|
"WebRTCSessionList",
|
||||||
},
|
defs.APIWebRTCSessionList{},
|
||||||
} {
|
},
|
||||||
t.Run(ca.openAPIKey, func(t *testing.T) {
|
} {
|
||||||
content1 := doc.Components.Schemas[ca.openAPIKey]
|
t.Run(ca.openAPIKey, func(t *testing.T) {
|
||||||
|
content1 := doc.Components.Schemas[ca.openAPIKey]
|
||||||
|
|
||||||
content2 := openAPISchema{
|
content2 := openAPISchema{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
Properties: make(map[string]openAPIProperty),
|
Properties: make(map[string]openAPIProperty),
|
||||||
}
|
|
||||||
|
|
||||||
ty := reflect.TypeOf(ca.goStruct)
|
|
||||||
|
|
||||||
for i := range ty.NumField() {
|
|
||||||
sf := ty.Field(i)
|
|
||||||
js := sf.Tag.Get("json")
|
|
||||||
name, _, _ := strings.Cut(js, ",")
|
|
||||||
deprecated := sf.Tag.Get("deprecated") == "true"
|
|
||||||
|
|
||||||
if name != "" && name != "-" && name != "paths" && name != "pathDefaults" &&
|
|
||||||
(!strings.Contains(js, ",omitempty") || deprecated) {
|
|
||||||
prop := fillProperty(t, sf.Type)
|
|
||||||
prop.Deprecated = deprecated
|
|
||||||
content2.Properties[name] = prop
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
require.Equal(t, content2, content1)
|
ty := reflect.TypeOf(ca.goStruct)
|
||||||
})
|
|
||||||
}
|
for i := range ty.NumField() {
|
||||||
|
sf := ty.Field(i)
|
||||||
|
js := sf.Tag.Get("json")
|
||||||
|
name, _, _ := strings.Cut(js, ",")
|
||||||
|
deprecated := sf.Tag.Get("deprecated") == "true"
|
||||||
|
|
||||||
|
if name != "" && name != "-" && name != "paths" && name != "pathDefaults" &&
|
||||||
|
(!strings.Contains(js, ",omitempty") || deprecated) {
|
||||||
|
prop := goStructToApi(t, sf.Type)
|
||||||
|
prop.Deprecated = deprecated
|
||||||
|
if deprecated {
|
||||||
|
prop = wrapRef(sf.Type, prop)
|
||||||
|
}
|
||||||
|
content2.Properties[name] = prop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
require.Equal(t, content2, content1)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("enums", func(t *testing.T) {
|
||||||
|
for _, rt := range []reflect.Type{
|
||||||
|
reflect.TypeOf(defs.APIOKStatus("")),
|
||||||
|
reflect.TypeOf(defs.APIErrorStatus("")),
|
||||||
|
reflect.TypeOf(defs.APIPathSourceType("")),
|
||||||
|
reflect.TypeOf(defs.APIPathReaderType("")),
|
||||||
|
reflect.TypeOf(defs.APIPathTrackCodec("")),
|
||||||
|
reflect.TypeOf(conf.AlwaysAvailableTrackCodec("")),
|
||||||
|
reflect.TypeOf(conf.AuthAction("")),
|
||||||
|
reflect.TypeOf(conf.AuthMethod("")),
|
||||||
|
reflect.TypeOf(conf.Encryption("")),
|
||||||
|
reflect.TypeOf(conf.HLSVariant(0)),
|
||||||
|
reflect.TypeOf(conf.LogDestination(0)),
|
||||||
|
reflect.TypeOf(conf.LogLevel(0)),
|
||||||
|
reflect.TypeOf(conf.RecordFormat("")),
|
||||||
|
reflect.TypeOf(conf.RTSPAuthMethod(0)),
|
||||||
|
reflect.TypeOf(conf.RTSPRangeType("")),
|
||||||
|
reflect.TypeOf(conf.RTSPTransport{}),
|
||||||
|
reflect.TypeOf(defs.APIRTMPConnState("")),
|
||||||
|
reflect.TypeOf(defs.APIRTSPSessionState("")),
|
||||||
|
reflect.TypeOf(defs.APISRTConnState("")),
|
||||||
|
reflect.TypeOf(defs.APIWebRTCSessionState("")),
|
||||||
|
} {
|
||||||
|
t.Run(rt.Name(), func(t *testing.T) {
|
||||||
|
content1 := doc.Components.Schemas[schemaName(rt)]
|
||||||
|
content2, ok := goEnumToApi(rt)
|
||||||
|
require.True(t, ok)
|
||||||
|
require.Equal(t, content2, content1)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ func (m *Metrics) middlewareAuth(ctx *gin.Context) {
|
|||||||
if err.AskCredentials {
|
if err.AskCredentials {
|
||||||
ctx.Header("WWW-Authenticate", `Basic realm="mediamtx"`)
|
ctx.Header("WWW-Authenticate", `Basic realm="mediamtx"`)
|
||||||
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
||||||
Status: "error",
|
Status: defs.APIErrorStatusError,
|
||||||
Error: "authentication error",
|
Error: "authentication error",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@@ -173,7 +173,7 @@ func (m *Metrics) middlewareAuth(ctx *gin.Context) {
|
|||||||
<-time.After(auth.PauseAfterError)
|
<-time.After(auth.PauseAfterError)
|
||||||
|
|
||||||
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
||||||
Status: "error",
|
Status: defs.APIErrorStatusError,
|
||||||
Error: "authentication error",
|
Error: "authentication error",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -32,17 +32,17 @@ func (dummyPathManager) APIPathsList() (*defs.APIPathList, error) {
|
|||||||
Name: "mypath",
|
Name: "mypath",
|
||||||
ConfName: "mypathconf",
|
ConfName: "mypathconf",
|
||||||
Source: &defs.APIPathSource{
|
Source: &defs.APIPathSource{
|
||||||
Type: "testing",
|
Type: defs.APIPathSourceTypeRTSPSession,
|
||||||
ID: "123324354",
|
ID: "123324354",
|
||||||
},
|
},
|
||||||
Ready: true,
|
Ready: true,
|
||||||
ReadyTime: ptrOf(time.Date(2003, 11, 4, 23, 15, 7, 0, time.UTC)),
|
ReadyTime: ptrOf(time.Date(2003, 11, 4, 23, 15, 7, 0, time.UTC)),
|
||||||
Tracks: []string{"H264", "H265"},
|
Tracks: []defs.APIPathTrackCodec{defs.APIPathTrackCodecH264, defs.APIPathTrackCodecH265},
|
||||||
BytesReceived: 123,
|
BytesReceived: 123,
|
||||||
BytesSent: 456,
|
BytesSent: 456,
|
||||||
Readers: []defs.APIPathReader{
|
Readers: []defs.APIPathReader{
|
||||||
{
|
{
|
||||||
Type: "testing",
|
Type: defs.APIPathReaderTypeRTSPSession,
|
||||||
ID: "345234423",
|
ID: "345234423",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ func (s *Server) doAuth(ctx *gin.Context, pathName string) bool {
|
|||||||
if err.AskCredentials {
|
if err.AskCredentials {
|
||||||
ctx.Header("WWW-Authenticate", `Basic realm="mediamtx"`)
|
ctx.Header("WWW-Authenticate", `Basic realm="mediamtx"`)
|
||||||
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
||||||
Status: "error",
|
Status: defs.APIErrorStatusError,
|
||||||
Error: "authentication error",
|
Error: "authentication error",
|
||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
@@ -142,7 +142,7 @@ func (s *Server) doAuth(ctx *gin.Context, pathName string) bool {
|
|||||||
<-time.After(auth.PauseAfterError)
|
<-time.After(auth.PauseAfterError)
|
||||||
|
|
||||||
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
||||||
Status: "error",
|
Status: defs.APIErrorStatusError,
|
||||||
Error: "authentication error",
|
Error: "authentication error",
|
||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ func (pp *PPROF) middlewareAuth(ctx *gin.Context) {
|
|||||||
if err.AskCredentials {
|
if err.AskCredentials {
|
||||||
ctx.Header("WWW-Authenticate", `Basic realm="mediamtx"`)
|
ctx.Header("WWW-Authenticate", `Basic realm="mediamtx"`)
|
||||||
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
||||||
Status: "error",
|
Status: defs.APIErrorStatusError,
|
||||||
Error: "authentication error",
|
Error: "authentication error",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@@ -120,7 +120,7 @@ func (pp *PPROF) middlewareAuth(ctx *gin.Context) {
|
|||||||
<-time.After(auth.PauseAfterError)
|
<-time.After(auth.PauseAfterError)
|
||||||
|
|
||||||
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
||||||
Status: "error",
|
Status: defs.APIErrorStatusError,
|
||||||
Error: "authentication error",
|
Error: "authentication error",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ func (s *httpServer) onRequest(ctx *gin.Context) {
|
|||||||
if terr.AskCredentials {
|
if terr.AskCredentials {
|
||||||
ctx.Header("WWW-Authenticate", `Basic realm="mediamtx"`)
|
ctx.Header("WWW-Authenticate", `Basic realm="mediamtx"`)
|
||||||
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
||||||
Status: "error",
|
Status: defs.APIErrorStatusError,
|
||||||
Error: "authentication error",
|
Error: "authentication error",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@@ -173,7 +173,7 @@ func (s *httpServer) onRequest(ctx *gin.Context) {
|
|||||||
<-time.After(auth.PauseAfterError)
|
<-time.After(auth.PauseAfterError)
|
||||||
|
|
||||||
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
||||||
Status: "error",
|
Status: defs.APIErrorStatusError,
|
||||||
Error: "authentication error",
|
Error: "authentication error",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ func (m *muxer) getInstance() *muxerInstance {
|
|||||||
// APIReaderDescribe implements reader.
|
// APIReaderDescribe implements reader.
|
||||||
func (m *muxer) APIReaderDescribe() *defs.APIPathReader {
|
func (m *muxer) APIReaderDescribe() *defs.APIPathReader {
|
||||||
return &defs.APIPathReader{
|
return &defs.APIPathReader{
|
||||||
Type: "hlsMuxer",
|
Type: defs.APIPathReaderTypeHLSMuxer,
|
||||||
ID: "",
|
ID: "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -291,11 +291,11 @@ func (c *conn) runPublish() error {
|
|||||||
// APIReaderDescribe implements reader.
|
// APIReaderDescribe implements reader.
|
||||||
func (c *conn) APIReaderDescribe() *defs.APIPathReader {
|
func (c *conn) APIReaderDescribe() *defs.APIPathReader {
|
||||||
return &defs.APIPathReader{
|
return &defs.APIPathReader{
|
||||||
Type: func() string {
|
Type: func() defs.APIPathReaderType {
|
||||||
if c.isTLS {
|
if c.isTLS {
|
||||||
return "rtmpsConn"
|
return defs.APIPathReaderTypeRTMPSConn
|
||||||
}
|
}
|
||||||
return "rtmpConn"
|
return defs.APIPathReaderTypeRTMPConn
|
||||||
}(),
|
}(),
|
||||||
ID: c.uuid.String(),
|
ID: c.uuid.String(),
|
||||||
}
|
}
|
||||||
@@ -304,11 +304,11 @@ func (c *conn) APIReaderDescribe() *defs.APIPathReader {
|
|||||||
// APISourceDescribe implements source.
|
// APISourceDescribe implements source.
|
||||||
func (c *conn) APISourceDescribe() *defs.APIPathSource {
|
func (c *conn) APISourceDescribe() *defs.APIPathSource {
|
||||||
return &defs.APIPathSource{
|
return &defs.APIPathSource{
|
||||||
Type: func() string {
|
Type: func() defs.APIPathSourceType {
|
||||||
if c.isTLS {
|
if c.isTLS {
|
||||||
return "rtmpsConn"
|
return defs.APIPathSourceTypeRTMPSConn
|
||||||
}
|
}
|
||||||
return "rtmpConn"
|
return defs.APIPathSourceTypeRTMPConn
|
||||||
}(),
|
}(),
|
||||||
ID: c.uuid.String(),
|
ID: c.uuid.String(),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,11 +86,11 @@ func (c *conn) initialize() {
|
|||||||
RunOnDisconnect: c.runOnDisconnect,
|
RunOnDisconnect: c.runOnDisconnect,
|
||||||
RTSPAddress: c.rtspAddress,
|
RTSPAddress: c.rtspAddress,
|
||||||
Desc: defs.APIPathReader{
|
Desc: defs.APIPathReader{
|
||||||
Type: func() string {
|
Type: func() defs.APIPathReaderType {
|
||||||
if c.isTLS {
|
if c.isTLS {
|
||||||
return "rtspsConn"
|
return defs.APIPathReaderTypeRTSPSConn
|
||||||
}
|
}
|
||||||
return "rtspConn"
|
return defs.APIPathReaderTypeRTSPConn
|
||||||
}(),
|
}(),
|
||||||
ID: c.uuid.String(),
|
ID: c.uuid.String(),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -380,11 +380,11 @@ func (s *session) onPause(_ *gortsplib.ServerHandlerOnPauseCtx) (*base.Response,
|
|||||||
// APIReaderDescribe implements reader.
|
// APIReaderDescribe implements reader.
|
||||||
func (s *session) APIReaderDescribe() *defs.APIPathReader {
|
func (s *session) APIReaderDescribe() *defs.APIPathReader {
|
||||||
return &defs.APIPathReader{
|
return &defs.APIPathReader{
|
||||||
Type: func() string {
|
Type: func() defs.APIPathReaderType {
|
||||||
if s.isTLS {
|
if s.isTLS {
|
||||||
return "rtspsSession"
|
return defs.APIPathReaderTypeRTSPSSession
|
||||||
}
|
}
|
||||||
return "rtspSession"
|
return defs.APIPathReaderTypeRTSPSession
|
||||||
}(),
|
}(),
|
||||||
ID: s.uuid.String(),
|
ID: s.uuid.String(),
|
||||||
}
|
}
|
||||||
@@ -393,11 +393,11 @@ func (s *session) APIReaderDescribe() *defs.APIPathReader {
|
|||||||
// APISourceDescribe implements source.
|
// APISourceDescribe implements source.
|
||||||
func (s *session) APISourceDescribe() *defs.APIPathSource {
|
func (s *session) APISourceDescribe() *defs.APIPathSource {
|
||||||
return &defs.APIPathSource{
|
return &defs.APIPathSource{
|
||||||
Type: func() string {
|
Type: func() defs.APIPathSourceType {
|
||||||
if s.isTLS {
|
if s.isTLS {
|
||||||
return "rtspsSession"
|
return defs.APIPathSourceTypeRTSPSSession
|
||||||
}
|
}
|
||||||
return "rtspSession"
|
return defs.APIPathSourceTypeRTSPSession
|
||||||
}(),
|
}(),
|
||||||
ID: s.uuid.String(),
|
ID: s.uuid.String(),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -347,7 +347,7 @@ func (c *conn) runRead(streamID *streamID) error {
|
|||||||
// APIReaderDescribe implements reader.
|
// APIReaderDescribe implements reader.
|
||||||
func (c *conn) APIReaderDescribe() *defs.APIPathReader {
|
func (c *conn) APIReaderDescribe() *defs.APIPathReader {
|
||||||
return &defs.APIPathReader{
|
return &defs.APIPathReader{
|
||||||
Type: "srtConn",
|
Type: defs.APIPathReaderTypeSRTConn,
|
||||||
ID: c.uuid.String(),
|
ID: c.uuid.String(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -355,7 +355,7 @@ func (c *conn) APIReaderDescribe() *defs.APIPathReader {
|
|||||||
// APISourceDescribe implements source.
|
// APISourceDescribe implements source.
|
||||||
func (c *conn) APISourceDescribe() *defs.APIPathSource {
|
func (c *conn) APISourceDescribe() *defs.APIPathSource {
|
||||||
return &defs.APIPathSource{
|
return &defs.APIPathSource{
|
||||||
Type: "srtConn",
|
Type: defs.APIPathSourceTypeSRTConn,
|
||||||
ID: c.uuid.String(),
|
ID: c.uuid.String(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ func mergePathAndQuery(path string, rawQuery string) string {
|
|||||||
|
|
||||||
func writeError(ctx *gin.Context, statusCode int, err error) {
|
func writeError(ctx *gin.Context, statusCode int, err error) {
|
||||||
ctx.JSON(statusCode, &defs.APIError{
|
ctx.JSON(statusCode, &defs.APIError{
|
||||||
Status: "error",
|
Status: defs.APIErrorStatusError,
|
||||||
Error: err.Error(),
|
Error: err.Error(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -143,7 +143,7 @@ func (s *httpServer) checkAuthOutsideSession(ctx *gin.Context, pathName string,
|
|||||||
if terr.AskCredentials {
|
if terr.AskCredentials {
|
||||||
ctx.Header("WWW-Authenticate", `Basic realm="mediamtx"`)
|
ctx.Header("WWW-Authenticate", `Basic realm="mediamtx"`)
|
||||||
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
||||||
Status: "error",
|
Status: defs.APIErrorStatusError,
|
||||||
Error: "authentication error",
|
Error: "authentication error",
|
||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
@@ -208,7 +208,7 @@ func (s *httpServer) onWHIPPost(ctx *gin.Context, pathName string, publish bool)
|
|||||||
if terr.AskCredentials {
|
if terr.AskCredentials {
|
||||||
ctx.Header("WWW-Authenticate", `Basic realm="mediamtx"`)
|
ctx.Header("WWW-Authenticate", `Basic realm="mediamtx"`)
|
||||||
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
||||||
Status: "error",
|
Status: defs.APIErrorStatusError,
|
||||||
Error: "authentication error",
|
Error: "authentication error",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@@ -220,7 +220,7 @@ func (s *httpServer) onWHIPPost(ctx *gin.Context, pathName string, publish bool)
|
|||||||
<-time.After(auth.PauseAfterError)
|
<-time.After(auth.PauseAfterError)
|
||||||
|
|
||||||
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
ctx.AbortWithStatusJSON(http.StatusUnauthorized, &defs.APIError{
|
||||||
Status: "error",
|
Status: defs.APIErrorStatusError,
|
||||||
Error: "authentication error",
|
Error: "authentication error",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@@ -288,7 +288,7 @@ func (s *httpServer) onWHIPPatch(ctx *gin.Context, pathName string, rawSecret st
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.AbortWithStatusJSON(http.StatusNoContent, &defs.APIOK{
|
ctx.AbortWithStatusJSON(http.StatusNoContent, &defs.APIOK{
|
||||||
Status: "ok",
|
Status: defs.APIOKStatusOK,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,7 +313,7 @@ func (s *httpServer) onWHIPDelete(ctx *gin.Context, pathName string, rawSecret s
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.AbortWithStatusJSON(http.StatusOK, &defs.APIOK{
|
ctx.AbortWithStatusJSON(http.StatusOK, &defs.APIOK{
|
||||||
Status: "ok",
|
Status: defs.APIOKStatusOK,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -451,7 +451,7 @@ func (s *session) addCandidates(
|
|||||||
// APIReaderDescribe implements reader.
|
// APIReaderDescribe implements reader.
|
||||||
func (s *session) APIReaderDescribe() *defs.APIPathReader {
|
func (s *session) APIReaderDescribe() *defs.APIPathReader {
|
||||||
return &defs.APIPathReader{
|
return &defs.APIPathReader{
|
||||||
Type: "webRTCSession",
|
Type: defs.APIPathReaderTypeWebRTCSession,
|
||||||
ID: s.uuid.String(),
|
ID: s.uuid.String(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -459,7 +459,7 @@ func (s *session) APIReaderDescribe() *defs.APIPathReader {
|
|||||||
// APISourceDescribe implements source.
|
// APISourceDescribe implements source.
|
||||||
func (s *session) APISourceDescribe() *defs.APIPathSource {
|
func (s *session) APISourceDescribe() *defs.APIPathSource {
|
||||||
return &defs.APIPathSource{
|
return &defs.APIPathSource{
|
||||||
Type: "webRTCSession",
|
Type: defs.APIPathSourceTypeWebRTCSession,
|
||||||
ID: s.uuid.String(),
|
ID: s.uuid.String(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ func (s *Source) Run(params defs.StaticSourceRunParams) error {
|
|||||||
// APISourceDescribe implements StaticSource.
|
// APISourceDescribe implements StaticSource.
|
||||||
func (*Source) APISourceDescribe() *defs.APIPathSource {
|
func (*Source) APISourceDescribe() *defs.APIPathSource {
|
||||||
return &defs.APIPathSource{
|
return &defs.APIPathSource{
|
||||||
Type: "hlsSource",
|
Type: defs.APIPathSourceTypeHLSSource,
|
||||||
ID: "",
|
ID: "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ func (s *Source) runReader(nc net.Conn) error {
|
|||||||
// APISourceDescribe implements StaticSource.
|
// APISourceDescribe implements StaticSource.
|
||||||
func (*Source) APISourceDescribe() *defs.APIPathSource {
|
func (*Source) APISourceDescribe() *defs.APIPathSource {
|
||||||
return &defs.APIPathSource{
|
return &defs.APIPathSource{
|
||||||
Type: "mpegtsSource",
|
Type: defs.APIPathSourceTypeMPEGTSSource,
|
||||||
ID: "",
|
ID: "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ func (r *secondaryReader) Close() {
|
|||||||
// APIReaderDescribe implements reader.
|
// APIReaderDescribe implements reader.
|
||||||
func (*secondaryReader) APIReaderDescribe() *defs.APIPathReader {
|
func (*secondaryReader) APIReaderDescribe() *defs.APIPathReader {
|
||||||
return &defs.APIPathReader{
|
return &defs.APIPathReader{
|
||||||
Type: "rpiCameraSecondary",
|
Type: defs.APIPathReaderTypeRPICameraSecondary,
|
||||||
ID: "",
|
ID: "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -361,7 +361,7 @@ func (s *Source) waitForPrimary(
|
|||||||
// APISourceDescribe implements StaticSource.
|
// APISourceDescribe implements StaticSource.
|
||||||
func (*Source) APISourceDescribe() *defs.APIPathSource {
|
func (*Source) APISourceDescribe() *defs.APIPathSource {
|
||||||
return &defs.APIPathSource{
|
return &defs.APIPathSource{
|
||||||
Type: "rpiCameraSource",
|
Type: defs.APIPathSourceTypeRPICameraSource,
|
||||||
ID: "",
|
ID: "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ func (s *Source) runReader(conn *gortmplib.Client) error {
|
|||||||
// APISourceDescribe implements StaticSource.
|
// APISourceDescribe implements StaticSource.
|
||||||
func (*Source) APISourceDescribe() *defs.APIPathSource {
|
func (*Source) APISourceDescribe() *defs.APIPathSource {
|
||||||
return &defs.APIPathSource{
|
return &defs.APIPathSource{
|
||||||
Type: "rtmpSource",
|
Type: defs.APIPathSourceTypeRTMPSource,
|
||||||
ID: "",
|
ID: "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ func (s *Source) runReader(desc *description.Session, nc net.Conn) error {
|
|||||||
// APISourceDescribe implements StaticSource.
|
// APISourceDescribe implements StaticSource.
|
||||||
func (*Source) APISourceDescribe() *defs.APIPathSource {
|
func (*Source) APISourceDescribe() *defs.APIPathSource {
|
||||||
return &defs.APIPathSource{
|
return &defs.APIPathSource{
|
||||||
Type: "rtpSource",
|
Type: defs.APIPathSourceTypeRTPSource,
|
||||||
ID: "",
|
ID: "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ func (s *Source) runInner(c *gortsplib.Client, u *base.URL, pathConf *conf.Path)
|
|||||||
// APISourceDescribe implements StaticSource.
|
// APISourceDescribe implements StaticSource.
|
||||||
func (*Source) APISourceDescribe() *defs.APIPathSource {
|
func (*Source) APISourceDescribe() *defs.APIPathSource {
|
||||||
return &defs.APIPathSource{
|
return &defs.APIPathSource{
|
||||||
Type: "rtspSource",
|
Type: defs.APIPathSourceTypeRTSPSource,
|
||||||
ID: "",
|
ID: "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ func (s *Source) runReader(sconn srt.Conn) error {
|
|||||||
// APISourceDescribe implements StaticSource.
|
// APISourceDescribe implements StaticSource.
|
||||||
func (*Source) APISourceDescribe() *defs.APIPathSource {
|
func (*Source) APISourceDescribe() *defs.APIPathSource {
|
||||||
return &defs.APIPathSource{
|
return &defs.APIPathSource{
|
||||||
Type: "srtSource",
|
Type: defs.APIPathSourceTypeSRTSource,
|
||||||
ID: "",
|
ID: "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ func (s *Source) Run(params defs.StaticSourceRunParams) error {
|
|||||||
// APISourceDescribe implements StaticSource.
|
// APISourceDescribe implements StaticSource.
|
||||||
func (*Source) APISourceDescribe() *defs.APIPathSource {
|
func (*Source) APISourceDescribe() *defs.APIPathSource {
|
||||||
return &defs.APIPathSource{
|
return &defs.APIPathSource{
|
||||||
Type: "webRTCSource",
|
Type: defs.APIPathSourceTypeWebRTCSource,
|
||||||
ID: "",
|
ID: "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user