mirror of
https://github.com/bluenviron/mediamtx
synced 2024-12-26 00:22:16 +00:00
api: add published track list to /v1/paths/list
This commit is contained in:
parent
cb8aec8844
commit
101ea25448
@ -201,6 +201,23 @@ components:
|
||||
- $ref: '#/components/schemas/PathSourceHLSSource'
|
||||
sourceReady:
|
||||
type: boolean
|
||||
tracks:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
enum:
|
||||
- Generic
|
||||
- H264
|
||||
- H265
|
||||
- JPEG
|
||||
- MPEG2Audio
|
||||
- MPEG2Video
|
||||
- MPEG4Audio
|
||||
- Opus
|
||||
- PCMA
|
||||
- PCMU
|
||||
- VP8
|
||||
- VP9
|
||||
readers:
|
||||
type: array
|
||||
items:
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/aler9/gortsplib"
|
||||
"github.com/aler9/gortsplib/pkg/mpeg4audio"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@ -161,8 +162,9 @@ func TestAPIPathsList(t *testing.T) {
|
||||
}
|
||||
|
||||
type path struct {
|
||||
SourceReady bool
|
||||
Source pathSource `json:"source"`
|
||||
SourceReady bool `json:"sourceReady"`
|
||||
Tracks []string `json:"tracks"`
|
||||
}
|
||||
|
||||
type pathList struct {
|
||||
@ -176,15 +178,27 @@ func TestAPIPathsList(t *testing.T) {
|
||||
require.Equal(t, true, ok)
|
||||
defer p.close()
|
||||
|
||||
track := &gortsplib.TrackH264{
|
||||
PayloadType: 96,
|
||||
SPS: []byte{0x01, 0x02, 0x03, 0x04},
|
||||
PPS: []byte{0x01, 0x02, 0x03, 0x04},
|
||||
tracks := gortsplib.Tracks{
|
||||
&gortsplib.TrackH264{
|
||||
PayloadType: 96,
|
||||
SPS: []byte{0x01, 0x02, 0x03, 0x04},
|
||||
PPS: []byte{0x01, 0x02, 0x03, 0x04},
|
||||
},
|
||||
&gortsplib.TrackMPEG4Audio{
|
||||
PayloadType: 97,
|
||||
Config: &mpeg4audio.Config{
|
||||
Type: 2,
|
||||
SampleRate: 44100,
|
||||
ChannelCount: 2,
|
||||
},
|
||||
SizeLength: 13,
|
||||
IndexLength: 3,
|
||||
IndexDeltaLength: 3,
|
||||
},
|
||||
}
|
||||
|
||||
source := gortsplib.Client{}
|
||||
err := source.StartPublishing("rtsp://localhost:8554/mypath",
|
||||
gortsplib.Tracks{track})
|
||||
err := source.StartPublishing("rtsp://localhost:8554/mypath", tracks)
|
||||
require.NoError(t, err)
|
||||
defer source.Close()
|
||||
|
||||
@ -194,10 +208,11 @@ func TestAPIPathsList(t *testing.T) {
|
||||
require.Equal(t, pathList{
|
||||
Items: map[string]path{
|
||||
"mypath": {
|
||||
SourceReady: true,
|
||||
Source: pathSource{
|
||||
Type: "rtspSession",
|
||||
},
|
||||
SourceReady: true,
|
||||
Tracks: []string{"H264", "MPEG4Audio"},
|
||||
},
|
||||
},
|
||||
}, out)
|
||||
@ -221,15 +236,27 @@ func TestAPIPathsList(t *testing.T) {
|
||||
require.Equal(t, true, ok)
|
||||
defer p.close()
|
||||
|
||||
track := &gortsplib.TrackH264{
|
||||
PayloadType: 96,
|
||||
SPS: []byte{0x01, 0x02, 0x03, 0x04},
|
||||
PPS: []byte{0x01, 0x02, 0x03, 0x04},
|
||||
tracks := gortsplib.Tracks{
|
||||
&gortsplib.TrackH264{
|
||||
PayloadType: 96,
|
||||
SPS: []byte{0x01, 0x02, 0x03, 0x04},
|
||||
PPS: []byte{0x01, 0x02, 0x03, 0x04},
|
||||
},
|
||||
&gortsplib.TrackMPEG4Audio{
|
||||
PayloadType: 97,
|
||||
Config: &mpeg4audio.Config{
|
||||
Type: 2,
|
||||
SampleRate: 44100,
|
||||
ChannelCount: 2,
|
||||
},
|
||||
SizeLength: 13,
|
||||
IndexLength: 3,
|
||||
IndexDeltaLength: 3,
|
||||
},
|
||||
}
|
||||
|
||||
source := gortsplib.Client{TLSConfig: &tls.Config{InsecureSkipVerify: true}}
|
||||
err = source.StartPublishing("rtsps://localhost:8322/mypath",
|
||||
gortsplib.Tracks{track})
|
||||
err = source.StartPublishing("rtsps://localhost:8322/mypath", tracks)
|
||||
require.NoError(t, err)
|
||||
defer source.Close()
|
||||
|
||||
@ -239,10 +266,11 @@ func TestAPIPathsList(t *testing.T) {
|
||||
require.Equal(t, pathList{
|
||||
Items: map[string]path{
|
||||
"mypath": {
|
||||
SourceReady: true,
|
||||
Source: pathSource{
|
||||
Type: "rtspsSession",
|
||||
},
|
||||
SourceReady: true,
|
||||
Tracks: []string{"H264", "MPEG4Audio"},
|
||||
},
|
||||
},
|
||||
}, out)
|
||||
@ -263,10 +291,11 @@ func TestAPIPathsList(t *testing.T) {
|
||||
require.Equal(t, pathList{
|
||||
Items: map[string]path{
|
||||
"mypath": {
|
||||
SourceReady: false,
|
||||
Source: pathSource{
|
||||
Type: "rtspSource",
|
||||
},
|
||||
SourceReady: false,
|
||||
Tracks: []string{},
|
||||
},
|
||||
},
|
||||
}, out)
|
||||
@ -287,10 +316,11 @@ func TestAPIPathsList(t *testing.T) {
|
||||
require.Equal(t, pathList{
|
||||
Items: map[string]path{
|
||||
"mypath": {
|
||||
SourceReady: false,
|
||||
Source: pathSource{
|
||||
Type: "rtmpSource",
|
||||
},
|
||||
SourceReady: false,
|
||||
Tracks: []string{},
|
||||
},
|
||||
},
|
||||
}, out)
|
||||
@ -311,10 +341,11 @@ func TestAPIPathsList(t *testing.T) {
|
||||
require.Equal(t, pathList{
|
||||
Items: map[string]path{
|
||||
"mypath": {
|
||||
SourceReady: false,
|
||||
Source: pathSource{
|
||||
Type: "hlsSource",
|
||||
},
|
||||
SourceReady: false,
|
||||
Tracks: []string{},
|
||||
},
|
||||
},
|
||||
}, out)
|
||||
|
@ -182,6 +182,7 @@ type pathAPIPathsListItem struct {
|
||||
Conf *conf.PathConf `json:"conf"`
|
||||
Source interface{} `json:"source"`
|
||||
SourceReady bool `json:"sourceReady"`
|
||||
Tracks []string `json:"tracks"`
|
||||
Readers []interface{} `json:"readers"`
|
||||
}
|
||||
|
||||
@ -220,7 +221,6 @@ type path struct {
|
||||
ctx context.Context
|
||||
ctxCancel func()
|
||||
source source
|
||||
sourceReady bool
|
||||
stream *stream
|
||||
readers map[reader]pathReaderState
|
||||
describeRequestsOnHold []pathDescribeReq
|
||||
@ -544,7 +544,7 @@ func (pa *path) run() {
|
||||
req.res <- pathReaderSetupPlayRes{err: fmt.Errorf("terminated")}
|
||||
}
|
||||
|
||||
if pa.sourceReady {
|
||||
if pa.stream != nil {
|
||||
pa.sourceSetNotReady()
|
||||
}
|
||||
|
||||
@ -669,7 +669,6 @@ func (pa *path) sourceSetReady(tracks gortsplib.Tracks, generateRTPPackets bool)
|
||||
}
|
||||
|
||||
pa.stream = stream
|
||||
pa.sourceReady = true
|
||||
|
||||
if pa.conf.RunOnReady != "" {
|
||||
pa.log(logger.Info, "runOnReady command started")
|
||||
@ -702,8 +701,6 @@ func (pa *path) sourceSetNotReady() {
|
||||
pa.log(logger.Info, "runOnReady command stopped")
|
||||
}
|
||||
|
||||
pa.sourceReady = false
|
||||
|
||||
if pa.stream != nil {
|
||||
pa.stream.close()
|
||||
pa.stream = nil
|
||||
@ -721,7 +718,7 @@ func (pa *path) doReaderRemove(r reader) {
|
||||
}
|
||||
|
||||
func (pa *path) doPublisherRemove() {
|
||||
if pa.sourceReady {
|
||||
if pa.stream != nil {
|
||||
if pa.hasOnDemandPublisher() && pa.onDemandPublisherState != pathOnDemandStateInitial {
|
||||
pa.onDemandPublisherStop()
|
||||
} else {
|
||||
@ -740,7 +737,7 @@ func (pa *path) handleDescribe(req pathDescribeReq) {
|
||||
return
|
||||
}
|
||||
|
||||
if pa.sourceReady {
|
||||
if pa.stream != nil {
|
||||
req.res <- pathDescribeRes{
|
||||
stream: pa.stream,
|
||||
}
|
||||
@ -849,7 +846,7 @@ func (pa *path) handlePublisherRecord(req pathPublisherRecordReq) {
|
||||
}
|
||||
|
||||
func (pa *path) handlePublisherPause(req pathPublisherPauseReq) {
|
||||
if req.author == pa.source && pa.sourceReady {
|
||||
if req.author == pa.source && pa.stream != nil {
|
||||
if pa.hasOnDemandPublisher() && pa.onDemandPublisherState != pathOnDemandStateInitial {
|
||||
pa.onDemandPublisherStop()
|
||||
} else {
|
||||
@ -879,7 +876,7 @@ func (pa *path) handleReaderRemove(req pathReaderRemoveReq) {
|
||||
}
|
||||
|
||||
func (pa *path) handleReaderSetupPlay(req pathReaderSetupPlayReq) {
|
||||
if pa.sourceReady {
|
||||
if pa.stream != nil {
|
||||
pa.handleReaderSetupPlayPost(req)
|
||||
return
|
||||
}
|
||||
@ -952,7 +949,13 @@ func (pa *path) handleAPIPathsList(req pathAPIPathsListSubReq) {
|
||||
}
|
||||
return pa.source.apiSourceDescribe()
|
||||
}(),
|
||||
SourceReady: pa.sourceReady,
|
||||
SourceReady: pa.stream != nil,
|
||||
Tracks: func() []string {
|
||||
if pa.stream == nil {
|
||||
return []string{}
|
||||
}
|
||||
return sourceTrackNames(pa.stream.tracks())
|
||||
}(),
|
||||
Readers: func() []interface{} {
|
||||
ret := []interface{}{}
|
||||
for r := range pa.readers {
|
||||
|
@ -17,14 +17,17 @@ type source interface {
|
||||
apiSourceDescribe() interface{}
|
||||
}
|
||||
|
||||
func sourceTrackInfo(tracks gortsplib.Tracks) string {
|
||||
trackCodecs := make([]string, len(tracks))
|
||||
func sourceTrackNames(tracks gortsplib.Tracks) []string {
|
||||
ret := make([]string, len(tracks))
|
||||
for i, t := range tracks {
|
||||
n := reflect.TypeOf(t).Elem().Name()
|
||||
n = n[len("Track"):]
|
||||
trackCodecs[i] = n
|
||||
ret[i] = n
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func sourceTrackInfo(tracks gortsplib.Tracks) string {
|
||||
return fmt.Sprintf("%d %s (%s)",
|
||||
len(tracks),
|
||||
func() string {
|
||||
@ -33,5 +36,5 @@ func sourceTrackInfo(tracks gortsplib.Tracks) string {
|
||||
}
|
||||
return "tracks"
|
||||
}(),
|
||||
strings.Join(trackCodecs, ", "))
|
||||
strings.Join(sourceTrackNames(tracks), ", "))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user