Update RTSP Server response with all tracks by default

This commit is contained in:
Alexey Khit
2023-01-27 20:43:56 +03:00
parent 5243aca8e9
commit bef8e6454d
6 changed files with 80 additions and 55 deletions
+2
View File
@@ -142,6 +142,8 @@ func parseArgs(s string) *Args {
s += "?video"
case args.audio > 0 && args.video == 0:
s += "?audio"
default:
s += "?video&audio"
}
args.input = strings.Replace(defaults["rtsp"], "{input}", s, 1)
} else if strings.HasPrefix(s, "device?") {
+8 -38
View File
@@ -3,6 +3,7 @@ package rtsp
import (
"github.com/AlexxIT/go2rtc/cmd/app"
"github.com/AlexxIT/go2rtc/cmd/streams"
"github.com/AlexxIT/go2rtc/pkg/mp4"
"github.com/AlexxIT/go2rtc/pkg/rtsp"
"github.com/AlexxIT/go2rtc/pkg/streamer"
"github.com/AlexxIT/go2rtc/pkg/tcp"
@@ -164,13 +165,7 @@ func tcpHandler(conn *rtsp.Conn) {
conn.SessionName = app.UserAgent
conn.Medias = streamer.ParseQuery(conn.URL.Query())
if conn.Medias == nil {
conn.Medias = []*streamer.Media{
{Kind: streamer.KindVideo, Direction: streamer.DirectionRecvonly},
{Kind: streamer.KindAudio, Direction: streamer.DirectionRecvonly},
}
}
conn.Medias = ParseQuery(conn.URL.Query())
if err := stream.AddConsumer(conn); err != nil {
log.Warn().Err(err).Str("stream", name).Msg("[rtsp]")
@@ -235,36 +230,11 @@ func tcpHandler(conn *rtsp.Conn) {
_ = conn.Close()
}
func initMedias(conn *rtsp.Conn) {
// set media candidates from query list
for key, value := range conn.URL.Query() {
switch key {
case streamer.KindVideo, streamer.KindAudio:
for _, name := range value {
name = strings.ToUpper(name)
// check aliases
switch name {
case "COPY":
name = "" // pass empty codecs list
case "MJPEG":
name = streamer.CodecJPEG
case "AAC":
name = streamer.CodecAAC
}
media := &streamer.Media{
Kind: key, Direction: streamer.DirectionRecvonly,
}
// empty codecs match all codecs
if name != "" {
// empty clock rate and channels match any values
media.Codecs = []*streamer.Codec{{Name: name}}
}
conn.Medias = append(conn.Medias, media)
}
}
func ParseQuery(query map[string][]string) []*streamer.Media {
if query["mp4"] != nil {
cons := mp4.Consumer{}
return cons.GetMedias()
}
return streamer.ParseQuery(query)
}
+3 -1
View File
@@ -91,7 +91,9 @@ func (s *Stream) AddConsumer(cons streamer.Consumer) (err error) {
consumer.tracks = append(consumer.tracks, consTrack)
producers = append(producers, prod)
break producers
if !consMedia.MatchAll() {
break producers
}
}
}
}
+34 -6
View File
@@ -9,7 +9,26 @@ import (
// Element Producer
func (c *Conn) GetMedias() []*streamer.Media {
return c.Medias
if c.Medias != nil {
return c.Medias
}
return []*streamer.Media{
{
Kind: streamer.KindVideo,
Direction: streamer.DirectionRecvonly,
Codecs: []*streamer.Codec{
{Name: streamer.CodecAll},
},
},
{
Kind: streamer.KindAudio,
Direction: streamer.DirectionRecvonly,
Codecs: []*streamer.Codec{
{Name: streamer.CodecAll},
},
},
}
}
func (c *Conn) GetTrack(media *streamer.Media, codec *streamer.Codec) *streamer.Track {
@@ -63,11 +82,20 @@ func (c *Conn) AddTrack(media *streamer.Media, track *streamer.Track) *streamer.
codec := track.Codec.Clone()
codec.PayloadType = uint8(96 + i)
for i, m := range c.Medias {
if m == media {
media.Codecs = []*streamer.Codec{codec}
c.Medias[i] = media
break
if media.MatchAll() {
// fill consumer medias list
c.Medias = append(c.Medias, &streamer.Media{
Kind: media.Kind, Direction: media.Direction,
Codecs: []*streamer.Codec{codec},
})
} else {
// find consumer media and replace codec with right one
for i, m := range c.Medias {
if m == media {
media.Codecs = []*streamer.Codec{codec}
c.Medias[i] = media
break
}
}
}
+14 -10
View File
@@ -36,6 +36,9 @@ const (
CodecMP3 = "MPA" // payload: 14, aka MPEG-1 Layer III
CodecELD = "ELD" // AAC-ELD
CodecAll = "ALL"
CodecAny = "ANY"
)
const PayloadTypeRAW byte = 255
@@ -111,10 +114,6 @@ func (m *Media) MatchMedia(media *Media) *Codec {
}
for _, localCodec := range m.Codecs {
if media.Codecs == nil {
return localCodec
}
for _, remoteCodec := range media.Codecs {
if localCodec.Match(remoteCodec) {
return localCodec
@@ -124,6 +123,10 @@ func (m *Media) MatchMedia(media *Media) *Codec {
return nil
}
func (m *Media) MatchAll() bool {
return len(m.Codecs) > 0 && m.Codecs[0].Name == CodecAll
}
// Codec take best from:
// - deepch/vdk/av.CodecData
// - pion/webrtc.RTPCodecCapability
@@ -153,6 +156,11 @@ func (c *Codec) Clone() *Codec {
}
func (c *Codec) Match(codec *Codec) bool {
switch codec.Name {
case CodecAll, CodecAny:
return true
}
return c.Name == codec.Name &&
(c.ClockRate == codec.ClockRate || codec.ClockRate == 0) &&
(c.Channels == codec.Channels || codec.Channels == 0)
@@ -307,16 +315,12 @@ func ParseQuery(query map[string][]string) (medias []*Media) {
media := &Media{Kind: key, Direction: DirectionRecvonly}
for _, name := range strings.Split(value, ",") {
if name == "" {
continue
}
name = strings.ToUpper(name)
// check aliases
switch name {
case "COPY":
name = "" // pass empty codecs list
case "", "COPY":
name = CodecAny
case "MJPEG":
name = CodecJPEG
case "AAC":
+19
View File
@@ -3,6 +3,7 @@ package streamer
import (
"github.com/pion/sdp/v3"
"github.com/stretchr/testify/assert"
"net/url"
"testing"
)
@@ -21,3 +22,21 @@ func TestSDP(t *testing.T) {
err = sd.Unmarshal(data)
assert.Empty(t, err)
}
func TestParseQuery(t *testing.T) {
u, _ := url.Parse("rtsp://localhost:8554/camera1")
medias := ParseQuery(u.Query())
assert.Nil(t, medias)
for _, rawULR := range []string{
"rtsp://localhost:8554/camera1?video",
"rtsp://localhost:8554/camera1?video=copy",
"rtsp://localhost:8554/camera1?video=any",
} {
u, _ = url.Parse(rawULR)
medias = ParseQuery(u.Query())
assert.Equal(t, []*Media{
{Kind: KindVideo, Direction: DirectionRecvonly, Codecs: []*Codec{{Name: CodecAny}}},
}, medias)
}
}