This repository has been archived by the owner on Mar 16, 2022. It is now read-only.
forked from pion/webrtc
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This example consumes RTP via a listening UDP socket and then sends it a WebRTC peer
- Loading branch information
Showing
5 changed files
with
183 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# rtp-to-webrtc | ||
rtp-to-webrtc demonstrates how to consume a RTP stream video UDP, and then send to a WebRTC client. | ||
|
||
With this example we have pre-made GStreamer and ffmpeg pipelines, but you can use any tool you like! | ||
|
||
## Instructions | ||
### Download rtp-to-webrtc | ||
``` | ||
go get github.com/pion/webrtc/v2/examples/rtp-to-webrtc | ||
``` | ||
|
||
### Open jsfiddle example page | ||
[jsfiddle.net](https://jsfiddle.net/z7ms3u5r/) you should see two text-areas and a 'Start Session' button | ||
|
||
|
||
### Run rtp-to-webrtc with your browsers SessionDescription as stdin | ||
In the jsfiddle the top textarea is your browser's SessionDescription, copy that and: | ||
|
||
#### Linux/macOS | ||
Run `echo $BROWSER_SDP | rtp-to-webrtc` | ||
|
||
#### Windows | ||
1. Paste the SessionDescription into a file. | ||
1. Run `rtp-to-webrtc < my_file` | ||
|
||
### Send RTP to listening socket | ||
On startup you will get a message `Waiting for RTP Packets`, you can use any software to send VP8 packets to port 5004. We also have the pre made examples below | ||
|
||
|
||
#### GStreamer | ||
``` | ||
gst-launch-1.0 videotestsrc ! 'video/x-raw, width=640, height=480' ! videoconvert ! video/x-raw,format=I420 ! vp8enc error-resilient=partitions keyframe-max-dist=10 auto-alt-ref=true cpu-used=5 deadline=1 ! rtpvp8pay ! udpsink host=127.0.0.1 port=5004 | ||
``` | ||
|
||
#### ffmpeg | ||
``` | ||
ffmpeg -re -f lavfi -i testsrc=size=640x480:rate=30 -vcodec libvpx -cpu-used 5 -deadline 1 -g 10 -error-resilient 1 -auto-alt-ref 1 -f rtp rtp://127.0.0.1:5004 | ||
``` | ||
|
||
### Input rtp-to-webrtc's SessionDescription into your browser | ||
Copy the text that `rtp-to-webrtc` just emitted and copy into second text area | ||
|
||
### Hit 'Start Session' in jsfiddle, enjoy your video! | ||
A video should start playing in your browser above the input boxes. | ||
|
||
Congrats, you have used Pion WebRTC! Now start building something cool |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"net" | ||
|
||
"github.com/pion/rtp" | ||
"github.com/pion/webrtc/v2" | ||
"github.com/pion/webrtc/v2/examples/internal/signal" | ||
) | ||
|
||
func main() { | ||
// Wait for the offer to be pasted | ||
offer := webrtc.SessionDescription{} | ||
signal.Decode(signal.MustReadStdin(), &offer) | ||
|
||
// We make our own mediaEngine so we can place the sender's codecs in it. This because we must use the | ||
// dynamic media type from the sender in our answer. This is not required if we are the offerer | ||
mediaEngine := webrtc.MediaEngine{} | ||
err := mediaEngine.PopulateFromSDP(offer) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
// Search for VP8 Payload type. If the offer doesn't support VP8 exit since | ||
// since they won't be able to decode anything we send them | ||
var payloadType uint8 | ||
for _, videoCodec := range mediaEngine.GetCodecsByKind(webrtc.RTPCodecTypeVideo) { | ||
if videoCodec.Name == "VP8" { | ||
payloadType = videoCodec.PayloadType | ||
break | ||
} | ||
} | ||
if payloadType == 0 { | ||
panic("Remote peer does not support VP8") | ||
} | ||
|
||
// Create a new RTCPeerConnection | ||
api := webrtc.NewAPI(webrtc.WithMediaEngine(mediaEngine)) | ||
peerConnection, err := api.NewPeerConnection(webrtc.Configuration{ | ||
ICEServers: []webrtc.ICEServer{ | ||
{ | ||
URLs: []string{"stun:stun.l.google.com:19302"}, | ||
}, | ||
}, | ||
}) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
// Open a UDP Listener for RTP Packets on port 5004 | ||
listener, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 5004}) | ||
if err != nil { | ||
panic(err) | ||
} | ||
defer func() { | ||
if err = listener.Close(); err != nil { | ||
panic(err) | ||
} | ||
}() | ||
|
||
fmt.Println("Waiting for RTP Packets, please run GStreamer or ffmpeg now") | ||
|
||
// Listen for a single RTP Packet, we need this to determine the SSRC | ||
inboundRTPPacket := make([]byte, 4096) // UDP MTU | ||
n, _, err := listener.ReadFromUDP(inboundRTPPacket) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
// Unmarshal the incoming packet | ||
packet := &rtp.Packet{} | ||
if err = packet.Unmarshal(inboundRTPPacket[:n]); err != nil { | ||
panic(err) | ||
} | ||
|
||
// Create a video track, using the same SSRC as the incoming RTP Packet | ||
videoTrack, err := peerConnection.NewTrack(payloadType, packet.SSRC, "video", "pion") | ||
if err != nil { | ||
panic(err) | ||
} | ||
if _, err = peerConnection.AddTrack(videoTrack); err != nil { | ||
panic(err) | ||
} | ||
|
||
// 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()) | ||
}) | ||
|
||
// Set the remote SessionDescription | ||
if err = peerConnection.SetRemoteDescription(offer); err != nil { | ||
panic(err) | ||
} | ||
|
||
// Create answer | ||
answer, err := peerConnection.CreateAnswer(nil) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
// Sets the LocalDescription, and starts our UDP listeners | ||
if err = peerConnection.SetLocalDescription(answer); err != nil { | ||
panic(err) | ||
} | ||
|
||
// Output the answer in base64 so we can paste it in browser | ||
fmt.Println(signal.Encode(answer)) | ||
|
||
// Read RTP packets forever and send them to the WebRTC Client | ||
for { | ||
n, _, err := listener.ReadFrom(inboundRTPPacket) | ||
if err != nil { | ||
fmt.Printf("error during read: %s", err) | ||
panic(err) | ||
} | ||
|
||
packet := &rtp.Packet{} | ||
if err := packet.Unmarshal(inboundRTPPacket[:n]); err != nil { | ||
panic(err) | ||
} | ||
packet.Header.PayloadType = payloadType | ||
|
||
if writeErr := videoTrack.WriteRTP(packet); writeErr != nil { | ||
panic(writeErr) | ||
} | ||
} | ||
} |