api: add missing enums and move all enums in dedicated components (#5576)

This commit is contained in:
Alessandro Ros
2026-03-15 22:09:00 +01:00
committed by GitHub
parent c6bb332664
commit 3bad7045c1
44 changed files with 1344 additions and 745 deletions
+5
View File
@@ -0,0 +1,5 @@
extends:
- recommended
rules:
operation-4xx-response: off
+174 -51
View File
@@ -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
View File
@@ -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
+9 -9
View File
@@ -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)
+4 -24
View File
@@ -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
View File
@@ -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)
+2 -2
View File
@@ -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)
}(), }(),
+1 -1
View File
@@ -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
View File
@@ -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"`
}
+24
View File
@@ -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"`
}
+86
View File
@@ -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"`
}
+122
View File
@@ -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)
}
+21
View File
@@ -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"`
}
+44
View File
@@ -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"`
}
+75
View File
@@ -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"`
}
+163
View File
@@ -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"`
}
+52
View File
@@ -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
View File
@@ -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.
+1 -1
View File
@@ -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,
} }
} }
+1 -1
View File
@@ -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
} }
+1 -1
View File
@@ -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
} }
} }
+385 -164
View File
@@ -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)
})
}
})
} }
+2 -2
View File
@@ -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
+3 -3
View File
@@ -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",
}, },
}, },
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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: "",
} }
} }
+6 -6
View File
@@ -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(),
} }
+3 -3
View File
@@ -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(),
}, },
+6 -6
View File
@@ -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(),
} }
+2 -2
View File
@@ -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(),
} }
} }
+6 -6
View File
@@ -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,
}) })
} }
+2 -2
View File
@@ -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(),
} }
} }
+1 -1
View File
@@ -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: "",
} }
} }
+1 -1
View File
@@ -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: "",
} }
} }
+2 -2
View File
@@ -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: "",
} }
} }
+1 -1
View File
@@ -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: "",
} }
} }
+1 -1
View File
@@ -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: "",
} }
} }
+1 -1
View File
@@ -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: "",
} }
} }
+1 -1
View File
@@ -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: "",
} }
} }
+1 -1
View File
@@ -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: "",
} }
} }