mirror of
https://github.com/pion/webrtc.git
synced 2025-10-06 23:52:51 +08:00

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
153 lines
3.9 KiB
Go
153 lines
3.9 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"time"
|
|
|
|
"github.com/pions/rtcp"
|
|
"github.com/pions/webrtc"
|
|
|
|
"github.com/pions/webrtc/examples/internal/signal"
|
|
)
|
|
|
|
var peerConnectionConfig = webrtc.Configuration{
|
|
ICEServers: []webrtc.ICEServer{
|
|
{
|
|
URLs: []string{"stun:stun.l.google.com:19302"},
|
|
},
|
|
},
|
|
}
|
|
|
|
const (
|
|
rtcpPLIInterval = time.Second * 3
|
|
)
|
|
|
|
func main() {
|
|
sdpChan := signal.HTTPSDPServer()
|
|
|
|
// Everything below is the pion-WebRTC API, thanks for using it ❤️.
|
|
// Create a MediaEngine object to configure the supported codec
|
|
m := webrtc.MediaEngine{}
|
|
|
|
// Setup the codecs you want to use.
|
|
// Only support VP8, this makes our proxying code simpler
|
|
m.RegisterCodec(webrtc.NewRTPVP8Codec(webrtc.DefaultPayloadTypeVP8, 90000))
|
|
|
|
// Create the API object with the MediaEngine
|
|
api := webrtc.NewAPI(webrtc.WithMediaEngine(m))
|
|
|
|
offer := webrtc.SessionDescription{}
|
|
signal.Decode(<-sdpChan, &offer)
|
|
fmt.Println("")
|
|
|
|
// Create a new RTCPeerConnection
|
|
peerConnection, err := api.NewPeerConnection(peerConnectionConfig)
|
|
if err != nil {
|
|
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
|
|
peerConnection.OnTrack(func(remoteTrack *webrtc.Track, receiver *webrtc.RTPReceiver) {
|
|
// Send a PLI on an interval so that the publisher is pushing a keyframe every rtcpPLIInterval
|
|
// This can be less wasteful by processing incoming RTCP events, then we would emit a NACK/PLI when a viewer requests it
|
|
go func() {
|
|
ticker := time.NewTicker(rtcpPLIInterval)
|
|
for range ticker.C {
|
|
if rtcpSendErr := peerConnection.WriteRTCP(&rtcp.PictureLossIndication{MediaSSRC: remoteTrack.SSRC()}); rtcpSendErr != nil {
|
|
fmt.Println(rtcpSendErr)
|
|
}
|
|
}
|
|
}()
|
|
|
|
// Create a local track, all our SFU clients will be fed via this track
|
|
localTrack, newTrackErr := peerConnection.NewTrack(remoteTrack.PayloadType(), remoteTrack.SSRC(), "video", "pion")
|
|
if newTrackErr != nil {
|
|
panic(newTrackErr)
|
|
}
|
|
localTrackChan <- localTrack
|
|
|
|
rtpBuf := make([]byte, 1400)
|
|
for {
|
|
i, readErr := remoteTrack.Read(rtpBuf)
|
|
if readErr != nil {
|
|
panic(readErr)
|
|
}
|
|
|
|
// 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)
|
|
}
|
|
}
|
|
})
|
|
|
|
// 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)
|
|
}
|
|
|
|
// Sets the LocalDescription, and starts our UDP listeners
|
|
err = peerConnection.SetLocalDescription(answer)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// Get the LocalDescription and take it to base64 so we can paste in browser
|
|
fmt.Println(signal.Encode(answer))
|
|
|
|
localTrack := <-localTrackChan
|
|
for {
|
|
fmt.Println("")
|
|
fmt.Println("Curl an base64 SDP to start sendonly peer connection")
|
|
|
|
recvOnlyOffer := webrtc.SessionDescription{}
|
|
signal.Decode(<-sdpChan, &recvOnlyOffer)
|
|
|
|
// Create a new PeerConnection
|
|
peerConnection, err := api.NewPeerConnection(peerConnectionConfig)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
_, err = peerConnection.AddTrack(localTrack)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// Set the remote SessionDescription
|
|
err = peerConnection.SetRemoteDescription(recvOnlyOffer)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// Create answer
|
|
answer, err := peerConnection.CreateAnswer(nil)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// Sets the LocalDescription, and starts our UDP listeners
|
|
err = peerConnection.SetLocalDescription(answer)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// Get the LocalDescription and take it to base64 so we can paste in browser
|
|
fmt.Println(signal.Encode(answer))
|
|
}
|
|
}
|