api: add published track list to /v1/paths/list

This commit is contained in:
aler9 2022-08-15 16:56:09 +02:00
parent cb8aec8844
commit 101ea25448
4 changed files with 86 additions and 32 deletions

View File

@ -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:

View File

@ -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)

View File

@ -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 {

View File

@ -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), ", "))
}