Add backchannel support for rtsp server
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/AlexxIT/go2rtc/internal/app"
|
"github.com/AlexxIT/go2rtc/internal/app"
|
||||||
"github.com/AlexxIT/go2rtc/internal/streams"
|
"github.com/AlexxIT/go2rtc/internal/streams"
|
||||||
|
"github.com/AlexxIT/go2rtc/pkg/aac"
|
||||||
"github.com/AlexxIT/go2rtc/pkg/core"
|
"github.com/AlexxIT/go2rtc/pkg/core"
|
||||||
"github.com/AlexxIT/go2rtc/pkg/rtsp"
|
"github.com/AlexxIT/go2rtc/pkg/rtsp"
|
||||||
"github.com/AlexxIT/go2rtc/pkg/tcp"
|
"github.com/AlexxIT/go2rtc/pkg/tcp"
|
||||||
@@ -184,6 +185,23 @@ func tcpHandler(conn *rtsp.Conn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if query.Get("backchannel") == "1" {
|
||||||
|
conn.Medias = append(conn.Medias, &core.Media{
|
||||||
|
Kind: core.KindAudio,
|
||||||
|
Direction: core.DirectionRecvonly,
|
||||||
|
Codecs: []*core.Codec{
|
||||||
|
{Name: core.CodecOpus, ClockRate: 48000, Channels: 2},
|
||||||
|
{Name: core.CodecPCM, ClockRate: 16000},
|
||||||
|
{Name: core.CodecPCMA, ClockRate: 16000},
|
||||||
|
{Name: core.CodecPCMU, ClockRate: 16000},
|
||||||
|
{Name: core.CodecPCM, ClockRate: 8000},
|
||||||
|
{Name: core.CodecPCMA, ClockRate: 8000},
|
||||||
|
{Name: core.CodecPCMU, ClockRate: 8000},
|
||||||
|
{Name: core.CodecAAC, ClockRate: 16000, FmtpLine: aac.FMTP + "1408"},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if s := query.Get("pkt_size"); s != "" {
|
if s := query.Get("pkt_size"); s != "" {
|
||||||
conn.PacketSize = uint16(core.Atoi(s))
|
conn.PacketSize = uint16(core.Atoi(s))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,6 +141,10 @@ func MarshalSDP(name string, medias []*Media) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
md.WithCodec(codec.PayloadType, name, codec.ClockRate, codec.Channels, codec.FmtpLine)
|
md.WithCodec(codec.PayloadType, name, codec.ClockRate, codec.Channels, codec.FmtpLine)
|
||||||
|
|
||||||
|
if media.Direction != "" {
|
||||||
|
md.WithPropertyAttribute(media.Direction)
|
||||||
|
}
|
||||||
|
|
||||||
if media.ID != "" {
|
if media.ID != "" {
|
||||||
md.WithValueAttribute("control", media.ID)
|
md.WithValueAttribute("control", media.ID)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ func (c *Conn) GetTrack(media *core.Media, codec *core.Codec) (*core.Receiver, e
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch c.mode {
|
||||||
|
case core.ModeActiveProducer:
|
||||||
c.stateMu.Lock()
|
c.stateMu.Lock()
|
||||||
defer c.stateMu.Unlock()
|
defer c.stateMu.Unlock()
|
||||||
|
|
||||||
@@ -37,6 +39,20 @@ func (c *Conn) GetTrack(media *core.Media, codec *core.Codec) (*core.Receiver, e
|
|||||||
c.Receivers = append(c.Receivers, track)
|
c.Receivers = append(c.Receivers, track)
|
||||||
|
|
||||||
return track, nil
|
return track, nil
|
||||||
|
case core.ModePassiveConsumer:
|
||||||
|
// Backchannel
|
||||||
|
c.stateMu.Lock()
|
||||||
|
defer c.stateMu.Unlock()
|
||||||
|
|
||||||
|
channel := byte(len(c.Senders)) * 2
|
||||||
|
track := core.NewReceiver(media, codec)
|
||||||
|
track.ID = channel
|
||||||
|
c.Receivers = append(c.Receivers, track)
|
||||||
|
|
||||||
|
return track, nil
|
||||||
|
default:
|
||||||
|
return nil, errors.New("rtsp: wrong mode for GetTrack")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) Start() (err error) {
|
func (c *Conn) Start() (err error) {
|
||||||
|
|||||||
+23
-4
@@ -129,6 +129,16 @@ func (c *Conn) Accept() error {
|
|||||||
medias = append(medias, media)
|
medias = append(medias, media)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for i, track := range c.Receivers {
|
||||||
|
media := &core.Media{
|
||||||
|
Kind: core.GetKind(track.Codec.Name),
|
||||||
|
Direction: core.DirectionSendonly,
|
||||||
|
Codecs: []*core.Codec{track.Codec},
|
||||||
|
ID: "trackID=" + strconv.Itoa(i+len(c.Senders)),
|
||||||
|
}
|
||||||
|
medias = append(medias, media)
|
||||||
|
}
|
||||||
|
|
||||||
res.Body, err = core.MarshalSDP(c.SessionName, medias)
|
res.Body, err = core.MarshalSDP(c.SessionName, medias)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -154,11 +164,20 @@ func (c *Conn) Accept() error {
|
|||||||
c.state = StateSetup
|
c.state = StateSetup
|
||||||
|
|
||||||
if c.mode == core.ModePassiveConsumer {
|
if c.mode == core.ModePassiveConsumer {
|
||||||
if i := reqTrackID(req); i >= 0 && i < len(c.Senders) {
|
trackID := reqTrackID(req)
|
||||||
// mark sender as SETUP
|
|
||||||
c.Senders[i].Media.ID = MethodSetup
|
if trackID >= 0 {
|
||||||
tr = fmt.Sprintf("RTP/AVP/TCP;unicast;interleaved=%d-%d", i*2, i*2+1)
|
if trackID < len(c.Senders) {
|
||||||
|
c.Senders[trackID].Media.ID = MethodSetup
|
||||||
|
tr = fmt.Sprintf("RTP/AVP/TCP;unicast;interleaved=%d-%d", trackID*2, trackID*2+1)
|
||||||
res.Header.Set("Transport", tr)
|
res.Header.Set("Transport", tr)
|
||||||
|
} else if trackID >= len(c.Senders) && trackID < len(c.Senders)+len(c.Receivers) {
|
||||||
|
c.Receivers[trackID-len(c.Senders)].Media.ID = MethodSetup
|
||||||
|
tr = fmt.Sprintf("RTP/AVP/TCP;unicast;interleaved=%d-%d", trackID*2, trackID*2+1)
|
||||||
|
res.Header.Set("Transport", tr)
|
||||||
|
} else {
|
||||||
|
res.Status = "400 Bad Request"
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
res.Status = "400 Bad Request"
|
res.Status = "400 Bad Request"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user