Add examples/rtcp-processing

rtcp-processing demonstrates how to access RTCP Packets via ReadRTCP

Resolves #2027
This commit is contained in:
Sean DuBois
2021-11-20 22:04:00 -05:00
parent 883973804d
commit fa72a9529f
9 changed files with 234 additions and 3 deletions

View File

@@ -0,0 +1,38 @@
# rtcp-processing
rtcp-processing demonstrates the Public API for processing RTCP packets in Pion WebRTC.
This example is only processing messages for a RTPReceiver. A RTPReceiver is used for accepting
media from a remote peer. These APIs also exist on the RTPSender when sending media to a remote peer.
RTCP is used for statistics and control information for media in WebRTC. Using these messages
you can get information about the quality of the media, round trip time and packet loss. You can
also craft messages to influence the media quality.
## Instructions
### Download rtcp-processing
```
export GO111MODULE=on
go get github.com/pion/webrtc/v3/examples/rtcp-processing
```
### Open rtcp-processing example page
[jsfiddle.net](https://jsfiddle.net/Le3zg7sd/) you should see two text-areas, 'Start Session' button and 'Copy browser SessionDescription to clipboard'
### Run rtcp-processing with your browsers Session Description as stdin
In the jsfiddle press 'Copy browser Session Description to clipboard' or copy the base64 string manually.
Now use this value you just copied as the input to `rtcp-processing`
#### Linux/macOS
Run `echo $BROWSER_SDP | rtcp-processing`
#### Windows
1. Paste the SessionDescription into a file.
1. Run `rtcp-processing < my_file`
### Input rtcp-processing's Session Description into your browser
Copy the text that `rtcp-processing` just emitted and copy into the second text area in the jsfiddle
### Hit 'Start Session' in jsfiddle
You will see console messages for each inbound RTCP message from the remote peer.
Congrats, you have used Pion WebRTC! Now start building something cool

View File

@@ -0,0 +1,4 @@
textarea {
width: 500px;
min-height: 75px;
}

View File

@@ -0,0 +1,5 @@
---
name: rtcp-processing
description: play-from-disk demonstrates how to process RTCP messages from Pion WebRTC
authors:
- Sean DuBois

View File

@@ -0,0 +1,25 @@
Browser Session Description
<br/>
<textarea id="localSessionDescription" readonly="true"></textarea>
<br/>
<button onclick="window.copySessionDescription()">Copy browser Session Description to clipboard</button>
<br/>
<br/>
<br/>
Remote Session Description
<br/>
<textarea id="remoteSessionDescription"></textarea>
<br/>
<button onclick="window.startSession()">Start Session</button>
<br/>
<br/>
Video<br />
<video id="video1" width="160" height="120" autoplay muted></video> <br />
Logs
<br/>
<div id="div"></div>

View File

@@ -0,0 +1,62 @@
/* eslint-env browser */
const pc = new RTCPeerConnection({
iceServers: [{
urls: 'stun:stun.l.google.com:19302'
}]
})
const log = msg => {
document.getElementById('div').innerHTML += msg + '<br>'
}
pc.ontrack = function (event) {
const el = document.createElement(event.track.kind)
el.srcObject = event.streams[0]
el.autoplay = true
el.controls = true
document.getElementById('remoteVideos').appendChild(el)
}
pc.oniceconnectionstatechange = e => log(pc.iceConnectionState)
pc.onicecandidate = event => {
if (event.candidate === null) {
document.getElementById('localSessionDescription').value = btoa(JSON.stringify(pc.localDescription))
}
}
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(stream => {
document.getElementById('video1').srcObject = stream
stream.getTracks().forEach(track => pc.addTrack(track, stream))
pc.createOffer().then(d => pc.setLocalDescription(d)).catch(log)
}).catch(log)
window.startSession = () => {
const sd = document.getElementById('remoteSessionDescription').value
if (sd === '') {
return alert('Session Description must not be empty')
}
try {
pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(atob(sd))))
} catch (e) {
alert(e)
}
}
window.copySessionDescription = () => {
const browserSessionDescription = document.getElementById('localSessionDescription')
browserSessionDescription.focus()
browserSessionDescription.select()
try {
const successful = document.execCommand('copy')
const msg = successful ? 'successful' : 'unsuccessful'
log('Copying SessionDescription was ' + msg)
} catch (err) {
log('Oops, unable to copy SessionDescription ' + err)
}
}

View File

@@ -0,0 +1,91 @@
// +build !js
package main
import (
"fmt"
"github.com/pion/webrtc/v3"
"github.com/pion/webrtc/v3/examples/internal/signal"
)
func main() {
// Everything below is the Pion WebRTC API! Thanks for using it ❤️.
// Prepare the configuration
config := webrtc.Configuration{
ICEServers: []webrtc.ICEServer{
{
URLs: []string{"stun:stun.l.google.com:19302"},
},
},
}
// Create a new RTCPeerConnection
peerConnection, err := webrtc.NewPeerConnection(config)
if err != nil {
panic(err)
}
// Set a handler for when a new remote track starts
peerConnection.OnTrack(func(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) {
fmt.Printf("Track has started streamId(%s) id(%s) rid(%s) \n", track.StreamID(), track.ID(), track.RID())
for {
// Read the RTCP packets as they become available for our new remote track
rtcpPackets, _, rtcpErr := receiver.ReadRTCP()
if rtcpErr != nil {
panic(rtcpErr)
}
for _, r := range rtcpPackets {
// Print a string description of the packets
if stringer, canString := r.(fmt.Stringer); canString {
fmt.Printf("Received RTCP Packet: %v", stringer.String())
}
}
}
})
// Set the handler for ICE connection state
// This will notify you when the peer has connected/disconnected
peerConnection.OnICEConnectionStateChange(func(connectionState webrtc.ICEConnectionState) {
fmt.Printf("Connection State has changed %s \n", connectionState.String())
})
// Wait for the offer to be pasted
offer := webrtc.SessionDescription{}
signal.Decode(signal.MustReadStdin(), &offer)
// Set the remote SessionDescription
err = peerConnection.SetRemoteDescription(offer)
if err != nil {
panic(err)
}
// Create answer
answer, err := peerConnection.CreateAnswer(nil)
if err != nil {
panic(err)
}
// Create channel that is blocked until ICE Gathering is complete
gatherComplete := webrtc.GatheringCompletePromise(peerConnection)
// Sets the LocalDescription, and starts our UDP listeners
err = peerConnection.SetLocalDescription(answer)
if err != nil {
panic(err)
}
// Block until ICE Gathering is complete, disabling trickle ICE
// we do this because we only can exchange one signaling message
// in a production application you should exchange ICE Candidates via OnICECandidate
<-gatherComplete
// Output the answer in base64 so we can paste it in browser
fmt.Println(signal.Encode(*peerConnection.LocalDescription()))
// Block forever
select {}
}