145 lines
2.9 KiB
Go
145 lines
2.9 KiB
Go
package webrtc
|
|
|
|
import (
|
|
"github.com/AlexxIT/go2rtc/pkg/streamer"
|
|
"github.com/pion/rtp"
|
|
"github.com/pion/webrtc/v3"
|
|
)
|
|
|
|
func (c *Conn) GetTrack(media *streamer.Media, codec *streamer.Codec) *streamer.Track {
|
|
switch c.Mode {
|
|
case streamer.ModeActiveProducer:
|
|
// active producer (webrtc source, webtorrent source):
|
|
// - creates empty track for remote sendonly media
|
|
// - bind go2rtc with pion track for remote recv media (backchannel)
|
|
for _, track := range c.tracks {
|
|
if track.Codec == codec {
|
|
return track
|
|
}
|
|
}
|
|
|
|
var track *streamer.Track
|
|
if media.Direction == streamer.DirectionSendonly {
|
|
track = streamer.NewTrack(media, codec)
|
|
} else {
|
|
track = c.getProducerSendTrack(media, codec)
|
|
}
|
|
|
|
c.tracks = append(c.tracks, track)
|
|
return track
|
|
|
|
case streamer.ModePassiveProducer:
|
|
// passive producer (WHIP)
|
|
for _, track := range c.tracks {
|
|
if track.Codec == codec {
|
|
return track
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
panic("not implemented")
|
|
}
|
|
|
|
func (c *Conn) Start() error {
|
|
c.closed.Wait()
|
|
return nil
|
|
}
|
|
|
|
func (c *Conn) Stop() error {
|
|
return c.pc.Close()
|
|
}
|
|
|
|
func (c *Conn) getProducerSendTrack(media *streamer.Media, codec *streamer.Codec) *streamer.Track {
|
|
tr := c.getTranseiver(media.MID)
|
|
if tr == nil {
|
|
return nil
|
|
}
|
|
|
|
sender := tr.Sender()
|
|
if sender == nil {
|
|
return nil
|
|
}
|
|
|
|
oldTrack := sender.Track()
|
|
track := &Track{
|
|
kind: media.Kind,
|
|
payloadType: codec.PayloadType,
|
|
|
|
id: oldTrack.ID(),
|
|
rid: oldTrack.RID(),
|
|
streamID: oldTrack.StreamID(),
|
|
}
|
|
|
|
if err := sender.ReplaceTrack(track); err != nil {
|
|
return nil
|
|
}
|
|
|
|
push := func(packet *rtp.Packet) error {
|
|
c.send += packet.MarshalSize()
|
|
return track.WriteRTP(packet)
|
|
}
|
|
|
|
return streamer.NewTrack(media, codec).Bind(push)
|
|
}
|
|
|
|
func (c *Conn) getTranseiver(mid string) *webrtc.RTPTransceiver {
|
|
for _, tr := range c.pc.GetTransceivers() {
|
|
if tr.Mid() == mid {
|
|
return tr
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type Track struct {
|
|
kind string
|
|
id string
|
|
rid string
|
|
streamID string
|
|
payloadType byte
|
|
ssrc uint32
|
|
writer webrtc.TrackLocalWriter
|
|
}
|
|
|
|
func (t *Track) Bind(context webrtc.TrackLocalContext) (webrtc.RTPCodecParameters, error) {
|
|
t.ssrc = uint32(context.SSRC())
|
|
t.writer = context.WriteStream()
|
|
|
|
for _, parameters := range context.CodecParameters() {
|
|
if byte(parameters.PayloadType) == t.payloadType {
|
|
return parameters, nil
|
|
}
|
|
}
|
|
|
|
return webrtc.RTPCodecParameters{}, nil
|
|
}
|
|
|
|
func (t *Track) Unbind(context webrtc.TrackLocalContext) error {
|
|
return nil
|
|
}
|
|
|
|
func (t *Track) ID() string {
|
|
return t.id
|
|
}
|
|
|
|
func (t *Track) RID() string {
|
|
return t.rid
|
|
}
|
|
|
|
func (t *Track) StreamID() string {
|
|
return t.streamID
|
|
}
|
|
|
|
func (t *Track) Kind() webrtc.RTPCodecType {
|
|
return webrtc.NewRTPCodecType(t.kind)
|
|
}
|
|
|
|
func (t *Track) WriteRTP(packet *rtp.Packet) error {
|
|
header := packet.Header
|
|
header.SSRC = t.ssrc
|
|
header.PayloadType = t.payloadType
|
|
_, err := t.writer.WriteRTP(&header, packet.Payload)
|
|
return err
|
|
}
|