Skip to content

Commit 1202dba

Browse files
committed
Migrate SDP generation to Unified Plan
This commit has breaking changes. This API change means we can no longer support an arbitrary number of receivers. For every track you want to receive you MUST call PeerConnection.AddTransceiver We do now support sending an multiple audio/video feeds. You can see this behavior via gstreamer-receive and gstreamer-send currently. Resolves #54
1 parent bc94eaa commit 1202dba

File tree

20 files changed

+338
-167
lines changed

20 files changed

+338
-167
lines changed

examples/gstreamer-receive/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ go get github.com/pions/webrtc/examples/gstreamer-receive
1414
```
1515

1616
### Open gstreamer-receive example page
17-
[jsfiddle.net](https://jsfiddle.net/pdm7bqfr/) you should see your Webcam, two text-areas and a 'Start Session' button
17+
[jsfiddle.net](https://jsfiddle.net/8t2g5Lar/) you should see your Webcam, two text-areas and a 'Start Session' button
1818

1919
### Run gstreamer-receive with your browsers SessionDescription as stdin
2020
In the jsfiddle the top textarea is your browser, copy that and:

examples/gstreamer-receive/jsfiddle/demo.html

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44

55
Golang base64 Session Description<br />
66
<textarea id="remoteSessionDescription"></textarea> <br/>
7-
<button onclick="window.startSession()"> Start Session </button><br />
7+
<button onclick="window.startSession()"> Start Session </button>
8+
<button onclick="window.addDisplayCapture()" id="displayCapture"> Display Capture </button><br />
89

910
<br />
1011

1112
Video<br />
12-
<video id="video1" width="160" height="120" autoplay muted></video> <br />
13+
<div id="localVideos"></div> <br />
14+
1315

1416
Logs<br />
1517
<div id="logs"></div>

examples/gstreamer-receive/jsfiddle/demo.js

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,24 @@ let pc = new RTCPeerConnection({
77
}
88
]
99
})
10-
var log = msg => {
10+
let log = msg => {
1111
document.getElementById('logs').innerHTML += msg + '<br>'
1212
}
13+
let displayVideo = video => {
14+
var el = document.createElement('video')
15+
el.srcObject = video
16+
el.autoplay = true
17+
el.muted = true
18+
el.width = 160
19+
el.height = 120
20+
21+
document.getElementById('localVideos').appendChild(el)
22+
return video
23+
}
1324

1425
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
1526
.then(stream => {
16-
pc.addStream(document.getElementById('video1').srcObject = stream)
27+
pc.addStream(displayVideo(stream))
1728
pc.createOffer().then(d => pc.setLocalDescription(d)).catch(log)
1829
}).catch(log)
1930

@@ -36,3 +47,11 @@ window.startSession = () => {
3647
alert(e)
3748
}
3849
}
50+
51+
window.addDisplayCapture = () => {
52+
navigator.mediaDevices.getDisplayMedia().then(stream => {
53+
document.getElementById('displayCapture').disabled = true
54+
pc.addStream(displayVideo(stream))
55+
pc.createOffer().then(d => pc.setLocalDescription(d)).catch(log)
56+
})
57+
}

examples/gstreamer-receive/main.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@ func gstreamerReceiveMain() {
3232
panic(err)
3333
}
3434

35+
// Allow us to receive 1 audio track, and 2 video tracks
36+
if _, err = peerConnection.AddTransceiver(webrtc.RTPCodecTypeAudio); err != nil {
37+
panic(err)
38+
} else if _, err = peerConnection.AddTransceiver(webrtc.RTPCodecTypeVideo); err != nil {
39+
panic(err)
40+
} else if _, err = peerConnection.AddTransceiver(webrtc.RTPCodecTypeVideo); err != nil {
41+
panic(err)
42+
}
43+
3544
// Set a handler for when a new remote track starts, this handler creates a gstreamer pipeline
3645
// for the given codec
3746
peerConnection.OnTrack(func(track *webrtc.Track, receiver *webrtc.RTPReceiver) {

examples/gstreamer-send/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ go get github.com/pions/webrtc/examples/gstreamer-send
1414
```
1515

1616
### Open gstreamer-send example page
17-
[jsfiddle.net](https://jsfiddle.net/Laf7ujeo/164/) you should see two text-areas and a 'Start Session' button
17+
[jsfiddle.net](https://jsfiddle.net/z7ms3u5r/) you should see two text-areas and a 'Start Session' button
1818

1919
### Run gstreamer-send with your browsers SessionDescription as stdin
2020
In the jsfiddle the top textarea is your browser, copy that and:

examples/gstreamer-send/jsfiddle/demo.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@ pc.onicecandidate = event => {
2727
}
2828
}
2929

30-
pc.createOffer({ offerToReceiveVideo: true, offerToReceiveAudio: true }).then(d => pc.setLocalDescription(d)).catch(log)
30+
// Offer to receive 1 audio, and 2 video tracks
31+
pc.addTransceiver('audio', {'direction': 'recvonly'})
32+
pc.addTransceiver('video', {'direction': 'recvonly'})
33+
pc.addTransceiver('video', {'direction': 'recvonly'})
34+
pc.createOffer().then(d => pc.setLocalDescription(d)).catch(log)
3135

3236
window.startSession = () => {
3337
let sd = document.getElementById('remoteSessionDescription').value

examples/gstreamer-send/main.go

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,21 +40,31 @@ func main() {
4040
})
4141

4242
// Create a audio track
43-
opusTrack, err := peerConnection.NewTrack(webrtc.DefaultPayloadTypeOpus, rand.Uint32(), "audio", "pion1")
43+
audioTrack, err := peerConnection.NewTrack(webrtc.DefaultPayloadTypeOpus, rand.Uint32(), "audio", "pion1")
4444
if err != nil {
4545
panic(err)
4646
}
47-
_, err = peerConnection.AddTrack(opusTrack)
47+
_, err = peerConnection.AddTrack(audioTrack)
4848
if err != nil {
4949
panic(err)
5050
}
5151

5252
// Create a video track
53-
vp8Track, err := peerConnection.NewTrack(webrtc.DefaultPayloadTypeVP8, rand.Uint32(), "video", "pion2")
53+
firstVideoTrack, err := peerConnection.NewTrack(webrtc.DefaultPayloadTypeVP8, rand.Uint32(), "video", "pion2")
5454
if err != nil {
5555
panic(err)
5656
}
57-
_, err = peerConnection.AddTrack(vp8Track)
57+
_, err = peerConnection.AddTrack(firstVideoTrack)
58+
if err != nil {
59+
panic(err)
60+
}
61+
62+
// Create a second video track
63+
secondVideoTrack, err := peerConnection.NewTrack(webrtc.DefaultPayloadTypeVP8, rand.Uint32(), "video", "pion3")
64+
if err != nil {
65+
panic(err)
66+
}
67+
_, err = peerConnection.AddTrack(secondVideoTrack)
5868
if err != nil {
5969
panic(err)
6070
}
@@ -85,8 +95,8 @@ func main() {
8595
fmt.Println(signal.Encode(answer))
8696

8797
// Start pushing buffers on these tracks
88-
gst.CreatePipeline(webrtc.Opus, []*webrtc.Track{opusTrack}, *audioSrc).Start()
89-
gst.CreatePipeline(webrtc.VP8, []*webrtc.Track{vp8Track}, *videoSrc).Start()
98+
gst.CreatePipeline(webrtc.Opus, []*webrtc.Track{audioTrack}, *audioSrc).Start()
99+
gst.CreatePipeline(webrtc.VP8, []*webrtc.Track{firstVideoTrack, secondVideoTrack}, *videoSrc).Start()
90100

91101
// Block forever
92102
select {}

examples/janus-gateway/streaming/main.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ func main() {
6868
panic(err)
6969
}
7070

71+
// Allow us to receive 1 audio track, and 1 video track
72+
if _, err = peerConnection.AddTransceiver(webrtc.RTPCodecTypeAudio); err != nil {
73+
panic(err)
74+
} else if _, err = peerConnection.AddTransceiver(webrtc.RTPCodecTypeVideo); err != nil {
75+
panic(err)
76+
}
77+
7178
peerConnection.OnICEConnectionStateChange(func(connectionState webrtc.ICEConnectionState) {
7279
fmt.Printf("Connection State has changed %s \n", connectionState.String())
7380
})

examples/save-to-disk/main.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,13 @@ func main() {
6161
panic(err)
6262
}
6363

64+
// Allow us to receive 1 audio track, and 1 video track
65+
if _, err = peerConnection.AddTransceiver(webrtc.RTPCodecTypeAudio); err != nil {
66+
panic(err)
67+
} else if _, err = peerConnection.AddTransceiver(webrtc.RTPCodecTypeVideo); err != nil {
68+
panic(err)
69+
}
70+
6471
opusFile, err := opuswriter.New("output.opus", 48000, 2)
6572
if err != nil {
6673
panic(err)

examples/sfu-minimal/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ go get github.com/pions/webrtc/examples/sfu-minimal
1010
```
1111

1212
### Open sfu-minimal example page
13-
[jsfiddle.net](https://jsfiddle.net/4g03uqrx/) You should see two buttons 'Publish a Broadcast' and 'Join a Broadcast'
13+
[jsfiddle.net](https://jsfiddle.net/zhpya3n9/) You should see two buttons 'Publish a Broadcast' and 'Join a Broadcast'
1414

1515
### Run SFU Minimal
1616
#### Linux/macOS

examples/sfu-minimal/jsfiddle/demo.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ window.createSession = isPublisher => {
2727
.catch(log)
2828
}).catch(log)
2929
} else {
30-
pc.createOffer({ offerToReceiveVideo: true })
30+
pc.addTransceiver('video', {'direction': 'recvonly'})
31+
pc.createOffer()
3132
.then(d => pc.setLocalDescription(d))
3233
.catch(log)
3334

examples/sfu-minimal/main.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"fmt"
5+
"io"
56
"time"
67

78
"github.com/pions/rtcp"
@@ -46,6 +47,11 @@ func main() {
4647
panic(err)
4748
}
4849

50+
// Allow us to receive 1 video track
51+
if _, err = peerConnection.AddTransceiver(webrtc.RTPCodecTypeVideo); err != nil {
52+
panic(err)
53+
}
54+
4955
localTrackChan := make(chan *webrtc.Track)
5056
// Set a handler for when a new remote track starts, this just distributes all our packets
5157
// to connected peers
@@ -75,7 +81,8 @@ func main() {
7581
panic(readErr)
7682
}
7783

78-
if _, err = localTrack.Write(rtpBuf[:i]); err != nil {
84+
// ErrClosedPipe means we don't have any subscribers, this is ok if no peers have connected yet
85+
if _, err = localTrack.Write(rtpBuf[:i]); err != nil && err != io.ErrClosedPipe {
7986
panic(err)
8087
}
8188
}

examples/sfu-ws/room.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package main
22

33
import (
4+
"io"
45
"net/http"
56
"sync"
67

@@ -69,6 +70,12 @@ func room(w http.ResponseWriter, r *http.Request) {
6970
pubReceiver, err = api.NewPeerConnection(peerConnectionConfig)
7071
checkError(err)
7172

73+
_, err = pubReceiver.AddTransceiver(webrtc.RTPCodecTypeAudio)
74+
checkError(err)
75+
76+
_, err = pubReceiver.AddTransceiver(webrtc.RTPCodecTypeVideo)
77+
checkError(err)
78+
7279
pubReceiver.OnTrack(func(remoteTrack *webrtc.Track, receiver *webrtc.RTPReceiver) {
7380
if remoteTrack.PayloadType() == webrtc.DefaultPayloadTypeVP8 || remoteTrack.PayloadType() == webrtc.DefaultPayloadTypeVP9 || remoteTrack.PayloadType() == webrtc.DefaultPayloadTypeH264 {
7481

@@ -94,7 +101,10 @@ func room(w http.ResponseWriter, r *http.Request) {
94101
videoTrackLock.RLock()
95102
_, err = videoTrack.Write(rtpBuf[:i])
96103
videoTrackLock.RUnlock()
97-
checkError(err)
104+
105+
if err != io.ErrClosedPipe {
106+
checkError(err)
107+
}
98108
}
99109

100110
} else {
@@ -113,7 +123,9 @@ func room(w http.ResponseWriter, r *http.Request) {
113123
audioTrackLock.RLock()
114124
_, err = audioTrack.Write(rtpBuf[:i])
115125
audioTrackLock.RUnlock()
116-
checkError(err)
126+
if err != io.ErrClosedPipe {
127+
checkError(err)
128+
}
117129
}
118130
}
119131
})

examples/sfu-ws/sfu.html

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
return alert('Message must not be empty')
6767
}
6868
dataChannel.send(message)
69-
element.value = ''
69+
element.value = ''
7070
}
7171
}
7272

@@ -103,7 +103,10 @@
103103
document.getElementById('msginput').style = 'display: none'
104104
dataChannel = pc.createDataChannel('data')
105105
dataChannel.onmessage = e => log(`receive data from '${dataChannel.label}' payload '${e.data}'`)
106-
pc.createOffer({ offerToReceiveVideo: true , offerToReceiveAudio: true})
106+
pc.addTransceiver('audio', {'direction': 'recvonly'})
107+
pc.addTransceiver('video', {'direction': 'recvonly'})
108+
109+
pc.createOffer()
107110
.then(d => pc.setLocalDescription(d))
108111
.catch(log)
109112

mediaengine.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package webrtc
44

55
import (
66
"strconv"
7+
"strings"
78

89
"github.com/pions/rtp"
910
"github.com/pions/rtp/codecs"
@@ -164,6 +165,18 @@ func (t RTPCodecType) String() string {
164165
}
165166
}
166167

168+
// NewRTPCodecType creates a RTPCodecType from a string
169+
func NewRTPCodecType(r string) RTPCodecType {
170+
switch {
171+
case strings.EqualFold(r, "audio"):
172+
return RTPCodecTypeAudio
173+
case strings.EqualFold(r, "video"):
174+
return RTPCodecTypeVideo
175+
default:
176+
return RTPCodecType(0)
177+
}
178+
}
179+
167180
// RTPCodec represents a codec supported by the PeerConnection
168181
type RTPCodec struct {
169182
RTPCodecCapability

0 commit comments

Comments
 (0)