mirror of
https://github.com/pion/webrtc.git
synced 2025-11-03 09:40:59 +08:00
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
This commit is contained in:
@@ -14,7 +14,7 @@ go get github.com/pions/webrtc/examples/gstreamer-receive
|
||||
```
|
||||
|
||||
### Open gstreamer-receive example page
|
||||
[jsfiddle.net](https://jsfiddle.net/pdm7bqfr/) you should see your Webcam, two text-areas and a 'Start Session' button
|
||||
[jsfiddle.net](https://jsfiddle.net/8t2g5Lar/) you should see your Webcam, two text-areas and a 'Start Session' button
|
||||
|
||||
### Run gstreamer-receive with your browsers SessionDescription as stdin
|
||||
In the jsfiddle the top textarea is your browser, copy that and:
|
||||
|
||||
@@ -4,12 +4,14 @@ Browser base64 Session Description<br />
|
||||
|
||||
Golang base64 Session Description<br />
|
||||
<textarea id="remoteSessionDescription"></textarea> <br/>
|
||||
<button onclick="window.startSession()"> Start Session </button><br />
|
||||
<button onclick="window.startSession()"> Start Session </button>
|
||||
<button onclick="window.addDisplayCapture()" id="displayCapture"> Display Capture </button><br />
|
||||
|
||||
<br />
|
||||
|
||||
Video<br />
|
||||
<video id="video1" width="160" height="120" autoplay muted></video> <br />
|
||||
<div id="localVideos"></div> <br />
|
||||
|
||||
|
||||
Logs<br />
|
||||
<div id="logs"></div>
|
||||
|
||||
@@ -7,13 +7,24 @@ let pc = new RTCPeerConnection({
|
||||
}
|
||||
]
|
||||
})
|
||||
var log = msg => {
|
||||
let log = msg => {
|
||||
document.getElementById('logs').innerHTML += msg + '<br>'
|
||||
}
|
||||
let displayVideo = video => {
|
||||
var el = document.createElement('video')
|
||||
el.srcObject = video
|
||||
el.autoplay = true
|
||||
el.muted = true
|
||||
el.width = 160
|
||||
el.height = 120
|
||||
|
||||
document.getElementById('localVideos').appendChild(el)
|
||||
return video
|
||||
}
|
||||
|
||||
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
|
||||
.then(stream => {
|
||||
pc.addStream(document.getElementById('video1').srcObject = stream)
|
||||
pc.addStream(displayVideo(stream))
|
||||
pc.createOffer().then(d => pc.setLocalDescription(d)).catch(log)
|
||||
}).catch(log)
|
||||
|
||||
@@ -36,3 +47,11 @@ window.startSession = () => {
|
||||
alert(e)
|
||||
}
|
||||
}
|
||||
|
||||
window.addDisplayCapture = () => {
|
||||
navigator.mediaDevices.getDisplayMedia().then(stream => {
|
||||
document.getElementById('displayCapture').disabled = true
|
||||
pc.addStream(displayVideo(stream))
|
||||
pc.createOffer().then(d => pc.setLocalDescription(d)).catch(log)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -32,6 +32,15 @@ func gstreamerReceiveMain() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Allow us to receive 1 audio track, and 2 video tracks
|
||||
if _, err = peerConnection.AddTransceiver(webrtc.RTPCodecTypeAudio); err != nil {
|
||||
panic(err)
|
||||
} else if _, err = peerConnection.AddTransceiver(webrtc.RTPCodecTypeVideo); err != nil {
|
||||
panic(err)
|
||||
} else if _, err = peerConnection.AddTransceiver(webrtc.RTPCodecTypeVideo); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Set a handler for when a new remote track starts, this handler creates a gstreamer pipeline
|
||||
// for the given codec
|
||||
peerConnection.OnTrack(func(track *webrtc.Track, receiver *webrtc.RTPReceiver) {
|
||||
|
||||
@@ -14,7 +14,7 @@ go get github.com/pions/webrtc/examples/gstreamer-send
|
||||
```
|
||||
|
||||
### Open gstreamer-send example page
|
||||
[jsfiddle.net](https://jsfiddle.net/Laf7ujeo/164/) you should see two text-areas and a 'Start Session' button
|
||||
[jsfiddle.net](https://jsfiddle.net/z7ms3u5r/) you should see two text-areas and a 'Start Session' button
|
||||
|
||||
### Run gstreamer-send with your browsers SessionDescription as stdin
|
||||
In the jsfiddle the top textarea is your browser, copy that and:
|
||||
|
||||
@@ -27,7 +27,11 @@ pc.onicecandidate = event => {
|
||||
}
|
||||
}
|
||||
|
||||
pc.createOffer({ offerToReceiveVideo: true, offerToReceiveAudio: true }).then(d => pc.setLocalDescription(d)).catch(log)
|
||||
// Offer to receive 1 audio, and 2 video tracks
|
||||
pc.addTransceiver('audio', {'direction': 'recvonly'})
|
||||
pc.addTransceiver('video', {'direction': 'recvonly'})
|
||||
pc.addTransceiver('video', {'direction': 'recvonly'})
|
||||
pc.createOffer().then(d => pc.setLocalDescription(d)).catch(log)
|
||||
|
||||
window.startSession = () => {
|
||||
let sd = document.getElementById('remoteSessionDescription').value
|
||||
|
||||
@@ -40,21 +40,31 @@ func main() {
|
||||
})
|
||||
|
||||
// Create a audio track
|
||||
opusTrack, err := peerConnection.NewTrack(webrtc.DefaultPayloadTypeOpus, rand.Uint32(), "audio", "pion1")
|
||||
audioTrack, err := peerConnection.NewTrack(webrtc.DefaultPayloadTypeOpus, rand.Uint32(), "audio", "pion1")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, err = peerConnection.AddTrack(opusTrack)
|
||||
_, err = peerConnection.AddTrack(audioTrack)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Create a video track
|
||||
vp8Track, err := peerConnection.NewTrack(webrtc.DefaultPayloadTypeVP8, rand.Uint32(), "video", "pion2")
|
||||
firstVideoTrack, err := peerConnection.NewTrack(webrtc.DefaultPayloadTypeVP8, rand.Uint32(), "video", "pion2")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, err = peerConnection.AddTrack(vp8Track)
|
||||
_, err = peerConnection.AddTrack(firstVideoTrack)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Create a second video track
|
||||
secondVideoTrack, err := peerConnection.NewTrack(webrtc.DefaultPayloadTypeVP8, rand.Uint32(), "video", "pion3")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, err = peerConnection.AddTrack(secondVideoTrack)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -85,8 +95,8 @@ func main() {
|
||||
fmt.Println(signal.Encode(answer))
|
||||
|
||||
// Start pushing buffers on these tracks
|
||||
gst.CreatePipeline(webrtc.Opus, []*webrtc.Track{opusTrack}, *audioSrc).Start()
|
||||
gst.CreatePipeline(webrtc.VP8, []*webrtc.Track{vp8Track}, *videoSrc).Start()
|
||||
gst.CreatePipeline(webrtc.Opus, []*webrtc.Track{audioTrack}, *audioSrc).Start()
|
||||
gst.CreatePipeline(webrtc.VP8, []*webrtc.Track{firstVideoTrack, secondVideoTrack}, *videoSrc).Start()
|
||||
|
||||
// Block forever
|
||||
select {}
|
||||
|
||||
@@ -68,6 +68,13 @@ func main() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Allow us to receive 1 audio track, and 1 video track
|
||||
if _, err = peerConnection.AddTransceiver(webrtc.RTPCodecTypeAudio); err != nil {
|
||||
panic(err)
|
||||
} else if _, err = peerConnection.AddTransceiver(webrtc.RTPCodecTypeVideo); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
peerConnection.OnICEConnectionStateChange(func(connectionState webrtc.ICEConnectionState) {
|
||||
fmt.Printf("Connection State has changed %s \n", connectionState.String())
|
||||
})
|
||||
|
||||
@@ -61,6 +61,13 @@ func main() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Allow us to receive 1 audio track, and 1 video track
|
||||
if _, err = peerConnection.AddTransceiver(webrtc.RTPCodecTypeAudio); err != nil {
|
||||
panic(err)
|
||||
} else if _, err = peerConnection.AddTransceiver(webrtc.RTPCodecTypeVideo); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
opusFile, err := opuswriter.New("output.opus", 48000, 2)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
||||
@@ -10,7 +10,7 @@ go get github.com/pions/webrtc/examples/sfu-minimal
|
||||
```
|
||||
|
||||
### Open sfu-minimal example page
|
||||
[jsfiddle.net](https://jsfiddle.net/4g03uqrx/) You should see two buttons 'Publish a Broadcast' and 'Join a Broadcast'
|
||||
[jsfiddle.net](https://jsfiddle.net/zhpya3n9/) You should see two buttons 'Publish a Broadcast' and 'Join a Broadcast'
|
||||
|
||||
### Run SFU Minimal
|
||||
#### Linux/macOS
|
||||
|
||||
@@ -27,7 +27,8 @@ window.createSession = isPublisher => {
|
||||
.catch(log)
|
||||
}).catch(log)
|
||||
} else {
|
||||
pc.createOffer({ offerToReceiveVideo: true })
|
||||
pc.addTransceiver('video', {'direction': 'recvonly'})
|
||||
pc.createOffer()
|
||||
.then(d => pc.setLocalDescription(d))
|
||||
.catch(log)
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/pions/rtcp"
|
||||
@@ -46,6 +47,11 @@ func main() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Allow us to receive 1 video track
|
||||
if _, err = peerConnection.AddTransceiver(webrtc.RTPCodecTypeVideo); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
localTrackChan := make(chan *webrtc.Track)
|
||||
// Set a handler for when a new remote track starts, this just distributes all our packets
|
||||
// to connected peers
|
||||
@@ -75,7 +81,8 @@ func main() {
|
||||
panic(readErr)
|
||||
}
|
||||
|
||||
if _, err = localTrack.Write(rtpBuf[:i]); err != nil {
|
||||
// ErrClosedPipe means we don't have any subscribers, this is ok if no peers have connected yet
|
||||
if _, err = localTrack.Write(rtpBuf[:i]); err != nil && err != io.ErrClosedPipe {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
@@ -69,6 +70,12 @@ func room(w http.ResponseWriter, r *http.Request) {
|
||||
pubReceiver, err = api.NewPeerConnection(peerConnectionConfig)
|
||||
checkError(err)
|
||||
|
||||
_, err = pubReceiver.AddTransceiver(webrtc.RTPCodecTypeAudio)
|
||||
checkError(err)
|
||||
|
||||
_, err = pubReceiver.AddTransceiver(webrtc.RTPCodecTypeVideo)
|
||||
checkError(err)
|
||||
|
||||
pubReceiver.OnTrack(func(remoteTrack *webrtc.Track, receiver *webrtc.RTPReceiver) {
|
||||
if remoteTrack.PayloadType() == webrtc.DefaultPayloadTypeVP8 || remoteTrack.PayloadType() == webrtc.DefaultPayloadTypeVP9 || remoteTrack.PayloadType() == webrtc.DefaultPayloadTypeH264 {
|
||||
|
||||
@@ -94,7 +101,10 @@ func room(w http.ResponseWriter, r *http.Request) {
|
||||
videoTrackLock.RLock()
|
||||
_, err = videoTrack.Write(rtpBuf[:i])
|
||||
videoTrackLock.RUnlock()
|
||||
checkError(err)
|
||||
|
||||
if err != io.ErrClosedPipe {
|
||||
checkError(err)
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -113,7 +123,9 @@ func room(w http.ResponseWriter, r *http.Request) {
|
||||
audioTrackLock.RLock()
|
||||
_, err = audioTrack.Write(rtpBuf[:i])
|
||||
audioTrackLock.RUnlock()
|
||||
checkError(err)
|
||||
if err != io.ErrClosedPipe {
|
||||
checkError(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -66,7 +66,7 @@ window.sendMessage = element => {
|
||||
return alert('Message must not be empty')
|
||||
}
|
||||
dataChannel.send(message)
|
||||
element.value = ''
|
||||
element.value = ''
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,10 @@ window.createSession = isPublisher => {
|
||||
document.getElementById('msginput').style = 'display: none'
|
||||
dataChannel = pc.createDataChannel('data')
|
||||
dataChannel.onmessage = e => log(`receive data from '${dataChannel.label}' payload '${e.data}'`)
|
||||
pc.createOffer({ offerToReceiveVideo: true , offerToReceiveAudio: true})
|
||||
pc.addTransceiver('audio', {'direction': 'recvonly'})
|
||||
pc.addTransceiver('video', {'direction': 'recvonly'})
|
||||
|
||||
pc.createOffer()
|
||||
.then(d => pc.setLocalDescription(d))
|
||||
.catch(log)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user