Label streams, not tracks.

We used to label tracks individually, in a view to using the labelling
for simulcast.  Since then, the WebRTC community has converged on a
different strategy, where multiple tracks share a single mid and
are labelled with the rid extension.

We now label whole streams, which is simpler, and use the track's
kind (and, in the future, the rid) to disambiguate.  This changes the
protocol in two ways:

  * in offers, the "labels" dictionary is replaced by a single "label"
    field; and
  * the syntax of the "request" message has changed.
This commit is contained in:
Juliusz Chroboczek
2021-04-28 17:00:50 +02:00
parent b08a2e3943
commit be73380f9f
7 changed files with 147 additions and 269 deletions
+12 -55
View File
@@ -313,6 +313,10 @@ func (up *rtpUpTrack) Label() string {
return up.label
}
func (up *rtpUpTrack) Kind() webrtc.RTPCodecType {
return up.track.Kind()
}
func (up *rtpUpTrack) Codec() webrtc.RTPCodecCapability {
return up.track.Codec().RTPCodecCapability
}
@@ -328,10 +332,10 @@ func (up *rtpUpTrack) hasRtcpFb(tpe, parameter string) bool {
type rtpUpConnection struct {
id string
label string
userId string
username string
pc *webrtc.PeerConnection
labels map[string]string
iceCandidates []*webrtc.ICECandidateInit
mu sync.Mutex
@@ -363,6 +367,10 @@ func (up *rtpUpConnection) Id() string {
return up.id
}
func (up *rtpUpConnection) Label() string {
return up.label
}
func (up *rtpUpConnection) User() (string, string) {
return up.userId, up.username
}
@@ -413,33 +421,6 @@ func (up *rtpUpConnection) flushICECandidates() error {
return err
}
func getTrackMid(pc *webrtc.PeerConnection, track *webrtc.TrackRemote) string {
for _, t := range pc.GetTransceivers() {
if t.Receiver() != nil && t.Receiver().Track() == track {
return t.Mid()
}
}
return ""
}
// called locked
func (up *rtpUpConnection) complete() bool {
for mid := range up.labels {
found := false
for _, t := range up.tracks {
m := getTrackMid(up.pc, t.track)
if m == mid {
found = true
break
}
}
if !found {
return false
}
}
return true
}
// pushConnNow pushes a connection to all of the clients in a group
func pushConnNow(up *rtpUpConnection, g *group.Group, cs []group.Client) {
up.mu.Lock()
@@ -460,17 +441,11 @@ func pushConnNow(up *rtpUpConnection, g *group.Group, cs []group.Client) {
// pushConn schedules a call to pushConnNow
func pushConn(up *rtpUpConnection, g *group.Group, cs []group.Client) {
up.mu.Lock()
if up.complete() {
up.mu.Unlock()
pushConnNow(up, g, cs)
return
}
up.pushed = false
up.mu.Unlock()
go func(g *group.Group, cs []group.Client) {
time.Sleep(4 * time.Second)
time.Sleep(200 * time.Millisecond)
up.mu.Lock()
pushed := up.pushed
up.pushed = true
@@ -481,7 +456,7 @@ func pushConn(up *rtpUpConnection, g *group.Group, cs []group.Client) {
}(g, cs)
}
func newUpConn(c group.Client, id string, labels map[string]string, offer string) (*rtpUpConnection, error) {
func newUpConn(c group.Client, id string, label string, offer string) (*rtpUpConnection, error) {
var o sdp.SessionDescription
err := o.Unmarshal([]byte(offer))
if err != nil {
@@ -506,31 +481,13 @@ func newUpConn(c group.Client, id string, labels map[string]string, offer string
}
}
up := &rtpUpConnection{id: id, pc: pc, labels: labels}
up := &rtpUpConnection{id: id, label: label, pc: pc}
pc.OnTrack(func(remote *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) {
up.mu.Lock()
mid := getTrackMid(pc, remote)
if mid == "" {
log.Printf("Couldn't get track's mid")
return
}
label, ok := up.labels[mid]
if !ok {
log.Printf("Couldn't get track's label")
isvideo := remote.Kind() == webrtc.RTPCodecTypeVideo
if isvideo {
label = "video"
} else {
label = "audio"
}
}
track := &rtpUpTrack{
track: remote,
label: label,
cache: packetcache.New(minPacketCache(remote)),
rate: estimator.New(time.Second),
jitter: jitter.New(remote.Codec().ClockRate),