diff --git a/.travis.yml b/.travis.yml index f6fc6d71c3a..91a7636a843 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,6 @@ install: - yarn install before_install: - - sudo apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev - wget https://raw.githubusercontent.com/creationix/nvm/v0.31.0/nvm.sh -O ~/.nvm/nvm.sh before_script: diff --git a/README.md b/README.md index f3557cb1b58..dc920ce3e87 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,8 @@ Use the tag [v1.2.0](https://github.com/pion/webrtc/tree/v1.2.0) if you'd like t ### Usage Check out the **[example applications](examples/README.md)** to help you along your Pion WebRTC journey. +For more full featured examples that use 3rd party libraries see our **[example-webrtc-applications](https://github.com/pion/example-webrtc-applications)** repo. + The Pion WebRTC API closely matches the JavaScript **[WebRTC API](https://w3c.github.io/webrtc-pc/)**. Most existing documentation is therefore also usefull when working with Pion. Furthermore, our **[GoDoc](https://godoc.org/github.com/pion/webrtc)** is actively maintained. Now go forth and build some awesome apps! Here are some **ideas** to get your creative juices flowing: diff --git a/examples/README.md b/examples/README.md index 2c9336c923d..0fa0b349454 100644 --- a/examples/README.md +++ b/examples/README.md @@ -4,15 +4,12 @@ We've build an extensive collection of examples covering common use-cases. You can modify and extend these examples to quickly get started. +For more full featured examples that use 3rd party libraries see our **[example-webrtc-applications](https://github.com/pion/example-webrtc-applications)** repo. + ### Overview #### Media API -* [Gstreamer Receive](gstreamer-receive): The gstreamer-receive example shows how to receive media from the browser and play it live. This example uses GStreamer for rendering. -* [Gstreamer Send](gstreamer-send): Example gstreamer-send shows how to send video to your browser. This example uses GStreamer to process the video. -* [Gstreamer Send Offer](gstreamer-send-offer): Example gstreamer-send-offer is a variant of gstreamer-send that initiates the WebRTC connection by sending an offer. * [Save to Disk](save-to-disk): The save-to-disk example shows how to record your webcam and save the footage to disk on the server side. -* [Janus Gateway](janus-gateway): Example janus-gateway is a collection of examples showing how to use Pion WebRTC with [janus-gateway](https://github.com/meetecho/janus-gateway). * [SFU Minimal](sfu-minimal): The SFU example demonstrates how to broadcast a video to multiple peers. A broadcaster uploads the video once and the server forwards it to all other peers. -* [SFU Websocket](sfu-ws): The SFU example demonstrates how to broadcast a video to multiple peers. A broadcaster uploads the video once and the server forwards it to all other peers. #### Data Channel API * [Data Channels](data-channels): The data-channels example shows how you can send/recv DataChannel messages from a web browser. diff --git a/examples/examples.json b/examples/examples.json index 97e53814927..df5b4076cb4 100644 --- a/examples/examples.json +++ b/examples/examples.json @@ -23,18 +23,6 @@ "description": "The data-channels-detach is an example that shows how you can detach a data channel.", "type": "browser" }, - { - "title": "Gstreamer Receive", - "link": "gstreamer-receive", - "description": "The gstreamer-receive example shows how to receive media from the browser and play it live. This example uses GStreamer for rendering.", - "type": "browser" - }, - { - "title": "Gstreamer Send", - "link": "gstreamer-send", - "description": "Example gstreamer-send shows how to send video to your browser. This example uses GStreamer to process the video.", - "type": "browser" - }, { "title": "Pion to Pion", "link": "#", @@ -46,17 +34,5 @@ "link": "save-to-disk", "description": "The save-to-disk example shows how to record your webcam and save the footage to disk on the server side.", "type": "browser" - }, - { - "title": "Minimal SFU", - "link": "sfu-minimal", - "description": "The minimal SFU example demonstrates how to broadcast a video to multiple peers. A broadcaster uploads the video once and the server forwards it to all other peers.", - "type": "browser" - }, - { - "title": "WebSocket SFU", - "link": "#", - "description": "The Websocket SFU example demonstrates how to broadcast a video to multiple peers. This is similar to Minimal SFU, but all signaling is done via websockets like a more full featured application.", - "type": "browser" } ] diff --git a/examples/gstreamer-receive/README.md b/examples/gstreamer-receive/README.md deleted file mode 100644 index 3b2d5174ce1..00000000000 --- a/examples/gstreamer-receive/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# gstreamer-receive -gstreamer-receive is a simple application that shows how to receive media using pion-WebRTC and play live using GStreamer. - -## Instructions -### Install GStreamer -This example requires you have GStreamer installed, these are the supported platforms -#### Debian/Ubuntu -`sudo apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev gstreamer1.0-plugins-good` -#### Windows MinGW64/MSYS2 -`pacman -S mingw-w64-x86_64-gstreamer mingw-w64-x86_64-gst-libav mingw-w64-x86_64-gst-plugins-good mingw-w64-x86_64-gst-plugins-bad mingw-w64-x86_64-gst-plugins-ugly` -### Download gstreamer-receive -``` -go get github.com/pion/webrtc/examples/gstreamer-receive -``` - -### Open gstreamer-receive example page -[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: -#### Linux/macOS -Run `echo $BROWSER_SDP | gstreamer-receive` -#### Windows -1. Paste the SessionDescription into a file. -1. Run `gstreamer-receive < my_file` - -### Input gstreamer-receive's SessionDescription into your browser -Copy the text that `gstreamer-receive` just emitted and copy into second text area - -### Hit 'Start Session' in jsfiddle, enjoy your media! -Your video and/or audio should popup automatically, and will continue playing until you close the application. - -Congrats, you have used pion-WebRTC! Now start building something cool diff --git a/examples/gstreamer-receive/jsfiddle/demo.css b/examples/gstreamer-receive/jsfiddle/demo.css deleted file mode 100644 index 9e43d340755..00000000000 --- a/examples/gstreamer-receive/jsfiddle/demo.css +++ /dev/null @@ -1,4 +0,0 @@ -textarea { - width: 500px; - min-height: 75px; -} \ No newline at end of file diff --git a/examples/gstreamer-receive/jsfiddle/demo.details b/examples/gstreamer-receive/jsfiddle/demo.details deleted file mode 100644 index 3a3ab37e258..00000000000 --- a/examples/gstreamer-receive/jsfiddle/demo.details +++ /dev/null @@ -1,5 +0,0 @@ ---- - name: gstreamer-receive - description: Example of using pion-WebRTC to play video using GStreamer - authors: - - Sean DuBois diff --git a/examples/gstreamer-receive/jsfiddle/demo.html b/examples/gstreamer-receive/jsfiddle/demo.html deleted file mode 100644 index 7612e161f2b..00000000000 --- a/examples/gstreamer-receive/jsfiddle/demo.html +++ /dev/null @@ -1,17 +0,0 @@ - -Browser base64 Session Description
-
- -Golang base64 Session Description
-
- -
- -
- -Video
-

- - -Logs
-
diff --git a/examples/gstreamer-receive/jsfiddle/demo.js b/examples/gstreamer-receive/jsfiddle/demo.js deleted file mode 100644 index 8e185ec06fe..00000000000 --- a/examples/gstreamer-receive/jsfiddle/demo.js +++ /dev/null @@ -1,57 +0,0 @@ -/* eslint-env browser */ - -let pc = new RTCPeerConnection({ - iceServers: [ - { - urls: 'stun:stun.l.google.com:19302' - } - ] -}) -let log = msg => { - document.getElementById('logs').innerHTML += msg + '
' -} -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(displayVideo(stream)) - pc.createOffer().then(d => pc.setLocalDescription(d)).catch(log) - }).catch(log) - -pc.oniceconnectionstatechange = e => log(pc.iceConnectionState) -pc.onicecandidate = event => { - if (event.candidate === null) { - document.getElementById('localSessionDescription').value = btoa(JSON.stringify(pc.localDescription)) - } -} - -window.startSession = () => { - let 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.addDisplayCapture = () => { - navigator.mediaDevices.getDisplayMedia().then(stream => { - document.getElementById('displayCapture').disabled = true - pc.addStream(displayVideo(stream)) - pc.createOffer().then(d => pc.setLocalDescription(d)).catch(log) - }) -} diff --git a/examples/gstreamer-receive/main.go b/examples/gstreamer-receive/main.go deleted file mode 100644 index aa0e2395f31..00000000000 --- a/examples/gstreamer-receive/main.go +++ /dev/null @@ -1,120 +0,0 @@ -package main - -import ( - "fmt" - "runtime" - "time" - - "github.com/pion/rtcp" - "github.com/pion/webrtc" - - gst "github.com/pion/webrtc/examples/internal/gstreamer-sink" - "github.com/pion/webrtc/examples/internal/signal" -) - -// gstreamerReceiveMain is launched in a goroutine because the main thread is needed -// for Glib's main loop (Gstreamer uses Glib) -func gstreamerReceiveMain() { - // 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) - } - - // 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) { - // Send a PLI on an interval so that the publisher is pushing a keyframe every rtcpPLIInterval - // This is a temporary fix until we implement incoming RTCP events, then we would push a PLI only when a viewer requests it - go func() { - ticker := time.NewTicker(time.Second * 3) - for range ticker.C { - rtcpSendErr := peerConnection.WriteRTCP(&rtcp.PictureLossIndication{MediaSSRC: track.SSRC()}) - if rtcpSendErr != nil { - fmt.Println(rtcpSendErr) - } - } - }() - - codec := track.Codec() - fmt.Printf("Track has started, of type %d: %s \n", track.PayloadType(), codec.Name) - pipeline := gst.CreatePipeline(codec.Name) - pipeline.Start() - buf := make([]byte, 1400) - for { - i, readErr := track.Read(buf) - if readErr != nil { - panic(err) - } - - pipeline.Push(buf[:i]) - } - }) - - // 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 an 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) - } - - // Output the answer in base64 so we can paste it in browser - fmt.Println(signal.Encode(answer)) - - // Block forever - select {} -} - -func init() { - // This example uses Gstreamer's autovideosink element to display the received video - // This element, along with some others, sometimes require that the process' main thread is used - runtime.LockOSThread() -} - -func main() { - // Start a new thread to do the actual work for this application - go gstreamerReceiveMain() - // Use this goroutine (which has been runtime.LockOSThread'd to he the main thread) to run the Glib loop that Gstreamer requires - gst.StartMainLoop() -} diff --git a/examples/gstreamer-send-offer/README.md b/examples/gstreamer-send-offer/README.md deleted file mode 100644 index ede677c9355..00000000000 --- a/examples/gstreamer-send-offer/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# gstreamer-send-offer -gstreamer-send-offer is a simple application that shows how to send video using pion-WebRTC and GStreamer. This is meant to be used with `gstreamer-receive`, if you want to send via to your browser try `gstreamer-send` - -## Instructions -### Install GStreamer -This example requires you have GStreamer installed, these are the supported platforms -#### Debian/Ubuntu -`sudo apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev gstreamer1.0-plugins-good` -#### Windows MinGW64/MSYS2 -`pacman -S mingw-w64-x86_64-gstreamer mingw-w64-x86_64-gst-libav mingw-w64-x86_64-gst-plugins-good mingw-w64-x86_64-gst-plugins-bad mingw-w64-x86_64-gst-plugins-ugly` - -### Run gstreamer-send-offer and make an offer to gstreamer-receive via stdin -``` -go run examples/gstreamer-send-offer/*.go | go run examples/gstreamer-receive/*.go -``` - -### post the answer from gstreamer-receive back to gstreamer-send-offer -You will see a base64 SDP printed to your console. You now need to communicate this back to `gstreamer-send-offer` this can be done via a HTTP endpoint - -`curl localhost:8080/sdp -d "BASE_64_SDP"` - -### enjoy your video! -A video should start playing via GStreamer and will continue playing until you close the application. - -Congrats, you have used pion-WebRTC! Now start building something cool - -## Customizing your video or audio -`gstreamer-send-offer` also accepts the command line arguments `-video-src` and `-audio-src` allowing you to provide custom inputs. - -When prototyping with GStreamer it is highly recommended that you enable debug output, this is done by setting the `GST_DEBUG` enviroment variable. -You can read about that [here](https://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/gst-running.html) a good default value is `GST_DEBUG=*:3` - -You can also prototype a GStreamer pipeline by using `gst-launch-1.0` to see how things look before trying them with `gstreamer-send` for the examples below you -also may need additional setup to enable extra video codecs like H264. The output from GST_DEBUG should give you hints - -These pipelines work on Linux, they may have issues on other platforms. We would love PRs for more example pipelines that people find helpful! - -* a webcam, with computer generated audio. - - `gstreamer-send-offer -video-src "autovideosrc ! video/x-raw, width=320, height=240 ! videoconvert ! queue"` - -* a pre-recorded video, sintel.mkv is available [here](https://durian.blender.org/download/) - - `gstreamer-send-offer -video-src "uridecodebin uri=file:///tmp/sintel.mkv ! videoscale ! video/x-raw, width=320, height=240 ! queue " -audio-src "uridecodebin uri=file:///tmp/sintel.mkv ! queue ! audioconvert"` diff --git a/examples/gstreamer-send-offer/main.go b/examples/gstreamer-send-offer/main.go deleted file mode 100644 index 4cf29cfd53d..00000000000 --- a/examples/gstreamer-send-offer/main.go +++ /dev/null @@ -1,93 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "math/rand" - - "github.com/pion/webrtc" - - gst "github.com/pion/webrtc/examples/internal/gstreamer-src" - "github.com/pion/webrtc/examples/internal/signal" -) - -func main() { - audioSrc := flag.String("audio-src", "audiotestsrc", "GStreamer audio src") - videoSrc := flag.String("video-src", "videotestsrc", "GStreamer video src") - sdpChan := signal.HTTPSDPServer() - - // 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 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()) - }) - - // Create a audio track - opusTrack, err := peerConnection.NewTrack(webrtc.DefaultPayloadTypeOpus, rand.Uint32(), "audio", "pion1") - if err != nil { - panic(err) - } - _, err = peerConnection.AddTrack(opusTrack) - if err != nil { - panic(err) - } - - // Create a video track - vp8Track, err := peerConnection.NewTrack(webrtc.DefaultPayloadTypeVP8, rand.Uint32(), "video", "pion2") - if err != nil { - panic(err) - } - _, err = peerConnection.AddTrack(vp8Track) - if err != nil { - panic(err) - } - - // Create an offer to send to the browser - offer, err := peerConnection.CreateOffer(nil) - if err != nil { - panic(err) - } - - // Sets the LocalDescription, and starts our UDP listeners - err = peerConnection.SetLocalDescription(offer) - if err != nil { - panic(err) - } - - // Output the offer in base64 so we can paste it in browser - fmt.Println(signal.Encode(offer)) - - // Wait for the answer to be submitted via HTTP - answer := webrtc.SessionDescription{} - signal.Decode(<-sdpChan, &answer) - - // Set the remote SessionDescription - err = peerConnection.SetRemoteDescription(answer) - if err != nil { - panic(err) - } - - // Start pushing buffers on these tracks - gst.CreatePipeline(webrtc.Opus, []*webrtc.Track{opusTrack}, *audioSrc).Start() - gst.CreatePipeline(webrtc.VP8, []*webrtc.Track{vp8Track}, *videoSrc).Start() - - // Block forever - select {} -} diff --git a/examples/gstreamer-send/README.md b/examples/gstreamer-send/README.md deleted file mode 100644 index 6616c5a4f79..00000000000 --- a/examples/gstreamer-send/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# gstreamer-send -gstreamer-send is a simple application that shows how to send video to your browser using pion-WebRTC and GStreamer. - -## Instructions -### Install GStreamer -This example requires you have GStreamer installed, these are the supported platforms -#### Debian/Ubuntu -`sudo apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev gstreamer1.0-plugins-good` -#### Windows MinGW64/MSYS2 -`pacman -S mingw-w64-x86_64-gstreamer mingw-w64-x86_64-gst-libav mingw-w64-x86_64-gst-plugins-good mingw-w64-x86_64-gst-plugins-bad mingw-w64-x86_64-gst-plugins-ugly` -### Download gstreamer-send -``` -go get github.com/pion/webrtc/examples/gstreamer-send -``` - -### Open gstreamer-send example page -[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: -#### Linux/macOS -Run `echo $BROWSER_SDP | gstreamer-send` -#### Windows -1. Paste the SessionDescription into a file. -1. Run `gstreamer-send < my_file` - -### Input gstreamer-send's SessionDescription into your browser -Copy the text that `gstreamer-send` 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, and will continue playing until you close the application. - -Congrats, you have used pion-WebRTC! Now start building something cool - -## Customizing your video or audio -`gstreamer-send` also accepts the command line arguments `-video-src` and `-audio-src` allowing you to provide custom inputs. - -When prototyping with GStreamer it is highly recommended that you enable debug output, this is done by setting the `GST_DEBUG` enviroment variable. -You can read about that [here](https://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/gst-running.html) a good default value is `GST_DEBUG=*:3` - -You can also prototype a GStreamer pipeline by using `gst-launch-1.0` to see how things look before trying them with `gstreamer-send` for the examples below you -also may need additional setup to enable extra video codecs like H264. The output from GST_DEBUG should give you hints - -These pipelines work on Linux, they may have issues on other platforms. We would love PRs for more example pipelines that people find helpful! - -* a webcam, with computer generated audio. - - `echo $BROWSER_SDP | gstreamer-send -video-src "autovideosrc ! video/x-raw, width=320, height=240 ! videoconvert ! queue"` - -* a pre-recorded video, sintel.mkv is available [here](https://durian.blender.org/download/) - - `echo $BROWSER_SDP | gstreamer-send -video-src "uridecodebin uri=file:///tmp/sintel.mkv ! videoscale ! video/x-raw, width=320, height=240 ! queue " -audio-src "uridecodebin uri=file:///tmp/sintel.mkv ! queue ! audioconvert"` diff --git a/examples/gstreamer-send/jsfiddle/demo.css b/examples/gstreamer-send/jsfiddle/demo.css deleted file mode 100644 index 9e43d340755..00000000000 --- a/examples/gstreamer-send/jsfiddle/demo.css +++ /dev/null @@ -1,4 +0,0 @@ -textarea { - width: 500px; - min-height: 75px; -} \ No newline at end of file diff --git a/examples/gstreamer-send/jsfiddle/demo.details b/examples/gstreamer-send/jsfiddle/demo.details deleted file mode 100644 index dccded8ee74..00000000000 --- a/examples/gstreamer-send/jsfiddle/demo.details +++ /dev/null @@ -1,5 +0,0 @@ ---- - name: gstreamer-send - description: Example of using pion-WebRTC to send video to your browser using GStreamer - authors: - - Sean DuBois diff --git a/examples/gstreamer-send/jsfiddle/demo.html b/examples/gstreamer-send/jsfiddle/demo.html deleted file mode 100644 index 6dbbf2558b5..00000000000 --- a/examples/gstreamer-send/jsfiddle/demo.html +++ /dev/null @@ -1,14 +0,0 @@ -Browser base64 Session Description
-
- -Golang base64 Session Description
-
-
- -
- -Video
-

- -Logs
-
diff --git a/examples/gstreamer-send/jsfiddle/demo.js b/examples/gstreamer-send/jsfiddle/demo.js deleted file mode 100644 index 1acb68f31fd..00000000000 --- a/examples/gstreamer-send/jsfiddle/demo.js +++ /dev/null @@ -1,47 +0,0 @@ -/* eslint-env browser */ - -let pc = new RTCPeerConnection({ - iceServers: [ - { - urls: 'stun:stun.l.google.com:19302' - } - ] -}) -let log = msg => { - document.getElementById('div').innerHTML += msg + '
' -} - -pc.ontrack = function (event) { - var 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)) - } -} - -// 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 - if (sd === '') { - return alert('Session Description must not be empty') - } - - try { - pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(atob(sd)))) - } catch (e) { - alert(e) - } -} diff --git a/examples/gstreamer-send/main.go b/examples/gstreamer-send/main.go deleted file mode 100644 index a22fbefd761..00000000000 --- a/examples/gstreamer-send/main.go +++ /dev/null @@ -1,103 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "math/rand" - - "github.com/pion/webrtc" - - gst "github.com/pion/webrtc/examples/internal/gstreamer-src" - "github.com/pion/webrtc/examples/internal/signal" -) - -func main() { - audioSrc := flag.String("audio-src", "audiotestsrc", "GStreamer audio src") - videoSrc := flag.String("video-src", "videotestsrc", "GStreamer video src") - flag.Parse() - - // 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 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()) - }) - - // Create a audio track - audioTrack, err := peerConnection.NewTrack(webrtc.DefaultPayloadTypeOpus, rand.Uint32(), "audio", "pion1") - if err != nil { - panic(err) - } - _, err = peerConnection.AddTrack(audioTrack) - if err != nil { - panic(err) - } - - // Create a video track - firstVideoTrack, err := peerConnection.NewTrack(webrtc.DefaultPayloadTypeVP8, rand.Uint32(), "video", "pion2") - if err != nil { - panic(err) - } - _, 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) - } - - // 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 an 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) - } - - // Output the answer in base64 so we can paste it in browser - fmt.Println(signal.Encode(answer)) - - // Start pushing buffers on these tracks - gst.CreatePipeline(webrtc.Opus, []*webrtc.Track{audioTrack}, *audioSrc).Start() - gst.CreatePipeline(webrtc.VP8, []*webrtc.Track{firstVideoTrack, secondVideoTrack}, *videoSrc).Start() - - // Block forever - select {} -} diff --git a/examples/internal/gstreamer-sink/gst.c b/examples/internal/gstreamer-sink/gst.c deleted file mode 100644 index 322c507f14b..00000000000 --- a/examples/internal/gstreamer-sink/gst.c +++ /dev/null @@ -1,62 +0,0 @@ -#include "gst.h" - -#include - -GMainLoop *gstreamer_receive_main_loop = NULL; -void gstreamer_receive_start_mainloop(void) { - gstreamer_receive_main_loop = g_main_loop_new(NULL, FALSE); - - g_main_loop_run(gstreamer_receive_main_loop); -} - -static gboolean gstreamer_receive_bus_call(GstBus *bus, GstMessage *msg, gpointer data) { - switch (GST_MESSAGE_TYPE(msg)) { - - case GST_MESSAGE_EOS: - g_print("End of stream\n"); - exit(1); - break; - - case GST_MESSAGE_ERROR: { - gchar *debug; - GError *error; - - gst_message_parse_error(msg, &error, &debug); - g_free(debug); - - g_printerr("Error: %s\n", error->message); - g_error_free(error); - exit(1); - } - default: - break; - } - - return TRUE; -} - -GstElement *gstreamer_receive_create_pipeline(char *pipeline) { - gst_init(NULL, NULL); - GError *error = NULL; - return gst_parse_launch(pipeline, &error); -} - -void gstreamer_receive_start_pipeline(GstElement *pipeline) { - GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline)); - gst_bus_add_watch(bus, gstreamer_receive_bus_call, NULL); - gst_object_unref(bus); - - gst_element_set_state(pipeline, GST_STATE_PLAYING); -} - -void gstreamer_receive_stop_pipeline(GstElement *pipeline) { gst_element_set_state(pipeline, GST_STATE_NULL); } - -void gstreamer_receive_push_buffer(GstElement *pipeline, void *buffer, int len) { - GstElement *src = gst_bin_get_by_name(GST_BIN(pipeline), "src"); - if (src != NULL) { - gpointer p = g_memdup(buffer, len); - GstBuffer *buffer = gst_buffer_new_wrapped(p, len); - gst_app_src_push_buffer(GST_APP_SRC(src), buffer); - gst_object_unref(src); - } -} diff --git a/examples/internal/gstreamer-sink/gst.go b/examples/internal/gstreamer-sink/gst.go deleted file mode 100644 index 405d3e60c3e..00000000000 --- a/examples/internal/gstreamer-sink/gst.go +++ /dev/null @@ -1,67 +0,0 @@ -package gst - -/* -#cgo pkg-config: gstreamer-1.0 gstreamer-app-1.0 - -#include "gst.h" - -*/ -import "C" -import ( - "unsafe" - - "github.com/pion/webrtc" -) - -// StartMainLoop starts GLib's main loop -// It needs to be called from the process' main thread -// Because many gstreamer plugins require access to the main thread -// See: https://golang.org/pkg/runtime/#LockOSThread -func StartMainLoop() { - C.gstreamer_receive_start_mainloop() -} - -// Pipeline is a wrapper for a GStreamer Pipeline -type Pipeline struct { - Pipeline *C.GstElement -} - -// CreatePipeline creates a GStreamer Pipeline -func CreatePipeline(codecName string) *Pipeline { - pipelineStr := "appsrc format=time is-live=true do-timestamp=true name=src ! application/x-rtp" - switch codecName { - case webrtc.VP8: - pipelineStr += ", encoding-name=VP8-DRAFT-IETF-01 ! rtpvp8depay ! decodebin ! autovideosink" - case webrtc.Opus: - pipelineStr += ", payload=96, encoding-name=OPUS ! rtpopusdepay ! decodebin ! autoaudiosink" - case webrtc.VP9: - pipelineStr += " ! rtpvp9depay ! decodebin ! autovideosink" - case webrtc.H264: - pipelineStr += " ! rtph264depay ! decodebin ! autovideosink" - case webrtc.G722: - pipelineStr += " clock-rate=8000 ! rtpg722depay ! decodebin ! autoaudiosink" - default: - panic("Unhandled codec " + codecName) - } - - pipelineStrUnsafe := C.CString(pipelineStr) - defer C.free(unsafe.Pointer(pipelineStrUnsafe)) - return &Pipeline{Pipeline: C.gstreamer_receive_create_pipeline(pipelineStrUnsafe)} -} - -// Start starts the GStreamer Pipeline -func (p *Pipeline) Start() { - C.gstreamer_receive_start_pipeline(p.Pipeline) -} - -// Stop stops the GStreamer Pipeline -func (p *Pipeline) Stop() { - C.gstreamer_receive_stop_pipeline(p.Pipeline) -} - -// Push pushes a buffer on the appsrc of the GStreamer Pipeline -func (p *Pipeline) Push(buffer []byte) { - b := C.CBytes(buffer) - defer C.free(b) - C.gstreamer_receive_push_buffer(p.Pipeline, b, C.int(len(buffer))) -} diff --git a/examples/internal/gstreamer-sink/gst.h b/examples/internal/gstreamer-sink/gst.h deleted file mode 100644 index 35a14f8524c..00000000000 --- a/examples/internal/gstreamer-sink/gst.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef GST_H -#define GST_H - -#include -#include -#include -#include - -GstElement *gstreamer_receive_create_pipeline(char *pipeline); -void gstreamer_receive_start_pipeline(GstElement *pipeline); -void gstreamer_receive_stop_pipeline(GstElement *pipeline); -void gstreamer_receive_push_buffer(GstElement *pipeline, void *buffer, int len); -void gstreamer_receive_start_mainloop(void); - -#endif diff --git a/examples/internal/gstreamer-src/gst.c b/examples/internal/gstreamer-src/gst.c deleted file mode 100644 index 64d4cfa574e..00000000000 --- a/examples/internal/gstreamer-src/gst.c +++ /dev/null @@ -1,88 +0,0 @@ -#include "gst.h" - -#include - -typedef struct SampleHandlerUserData { - int pipelineId; -} SampleHandlerUserData; - -GMainLoop *gstreamer_send_main_loop = NULL; -void gstreamer_send_start_mainloop(void) { - gstreamer_send_main_loop = g_main_loop_new(NULL, FALSE); - - g_main_loop_run(gstreamer_send_main_loop); -} - -static gboolean gstreamer_send_bus_call(GstBus *bus, GstMessage *msg, gpointer data) { - switch (GST_MESSAGE_TYPE(msg)) { - - case GST_MESSAGE_EOS: - g_print("End of stream\n"); - exit(1); - break; - - case GST_MESSAGE_ERROR: { - gchar *debug; - GError *error; - - gst_message_parse_error(msg, &error, &debug); - g_free(debug); - - g_printerr("Error: %s\n", error->message); - g_error_free(error); - exit(1); - } - default: - break; - } - - return TRUE; -} - -GstFlowReturn gstreamer_send_new_sample_handler(GstElement *object, gpointer user_data) { - GstSample *sample = NULL; - GstBuffer *buffer = NULL; - gpointer copy = NULL; - gsize copy_size = 0; - SampleHandlerUserData *s = (SampleHandlerUserData *)user_data; - - g_signal_emit_by_name (object, "pull-sample", &sample); - if (sample) { - buffer = gst_sample_get_buffer(sample); - if (buffer) { - gst_buffer_extract_dup(buffer, 0, gst_buffer_get_size(buffer), ©, ©_size); - goHandlePipelineBuffer(copy, copy_size, GST_BUFFER_DURATION(buffer), s->pipelineId); - } - gst_sample_unref (sample); - } - - return GST_FLOW_OK; -} - -GstElement *gstreamer_send_create_pipeline(char *pipeline) { - gst_init(NULL, NULL); - GError *error = NULL; - return gst_parse_launch(pipeline, &error); -} - -void gstreamer_send_start_pipeline(GstElement *pipeline, int pipelineId) { - SampleHandlerUserData *s = calloc(1, sizeof(SampleHandlerUserData)); - s->pipelineId = pipelineId; - - GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline)); - gst_bus_add_watch(bus, gstreamer_send_bus_call, NULL); - gst_object_unref(bus); - - GstElement *appsink = gst_bin_get_by_name(GST_BIN(pipeline), "appsink"); - g_object_set(appsink, "emit-signals", TRUE, NULL); - g_signal_connect(appsink, "new-sample", G_CALLBACK(gstreamer_send_new_sample_handler), s); - gst_object_unref(appsink); - - gst_element_set_state(pipeline, GST_STATE_PLAYING); -} - -void gstreamer_send_stop_pipeline(GstElement *pipeline) { - gst_element_set_state(pipeline, GST_STATE_NULL); -} - - diff --git a/examples/internal/gstreamer-src/gst.go b/examples/internal/gstreamer-src/gst.go deleted file mode 100644 index 71f030e2724..00000000000 --- a/examples/internal/gstreamer-src/gst.go +++ /dev/null @@ -1,106 +0,0 @@ -package gst - -/* -#cgo pkg-config: gstreamer-1.0 gstreamer-app-1.0 - -#include "gst.h" - -*/ -import "C" -import ( - "fmt" - "sync" - "unsafe" - - "github.com/pion/webrtc" - "github.com/pion/webrtc/pkg/media" -) - -func init() { - go C.gstreamer_send_start_mainloop() -} - -// Pipeline is a wrapper for a GStreamer Pipeline -type Pipeline struct { - Pipeline *C.GstElement - tracks []*webrtc.Track - id int - codecName string -} - -var pipelines = make(map[int]*Pipeline) -var pipelinesLock sync.Mutex - -// CreatePipeline creates a GStreamer Pipeline -func CreatePipeline(codecName string, tracks []*webrtc.Track, pipelineSrc string) *Pipeline { - pipelineStr := "appsink name=appsink" - switch codecName { - case webrtc.VP8: - pipelineStr = pipelineSrc + " ! vp8enc error-resilient=partitions keyframe-max-dist=10 auto-alt-ref=true cpu-used=5 deadline=1 ! " + pipelineStr - case webrtc.VP9: - pipelineStr = pipelineSrc + " ! vp9enc ! " + pipelineStr - case webrtc.H264: - pipelineStr = pipelineSrc + " ! video/x-raw,format=I420 ! x264enc bframes=0 speed-preset=veryfast key-int-max=60 ! video/x-h264,stream-format=byte-stream ! " + pipelineStr - case webrtc.Opus: - pipelineStr = pipelineSrc + " ! opusenc ! " + pipelineStr - case webrtc.G722: - pipelineStr = pipelineSrc + " ! avenc_g722 ! " + pipelineStr - default: - panic("Unhandled codec " + codecName) - } - - pipelineStrUnsafe := C.CString(pipelineStr) - defer C.free(unsafe.Pointer(pipelineStrUnsafe)) - - pipelinesLock.Lock() - defer pipelinesLock.Unlock() - - pipeline := &Pipeline{ - Pipeline: C.gstreamer_send_create_pipeline(pipelineStrUnsafe), - tracks: tracks, - id: len(pipelines), - codecName: codecName, - } - - pipelines[pipeline.id] = pipeline - return pipeline -} - -// Start starts the GStreamer Pipeline -func (p *Pipeline) Start() { - C.gstreamer_send_start_pipeline(p.Pipeline, C.int(p.id)) -} - -// Stop stops the GStreamer Pipeline -func (p *Pipeline) Stop() { - C.gstreamer_send_stop_pipeline(p.Pipeline) -} - -const ( - videoClockRate = 90000 - audioClockRate = 48000 -) - -//export goHandlePipelineBuffer -func goHandlePipelineBuffer(buffer unsafe.Pointer, bufferLen C.int, duration C.int, pipelineID C.int) { - pipelinesLock.Lock() - pipeline, ok := pipelines[int(pipelineID)] - pipelinesLock.Unlock() - - if ok { - var samples uint32 - if pipeline.codecName == webrtc.Opus { - samples = uint32(audioClockRate * (float32(duration) / 1000000000)) - } else { - samples = uint32(videoClockRate * (float32(duration) / 1000000000)) - } - for _, t := range pipeline.tracks { - if err := t.WriteSample(media.Sample{Data: C.GoBytes(buffer, bufferLen), Samples: samples}); err != nil { - panic(err) - } - } - } else { - fmt.Printf("discarding buffer, no pipeline with id %d", int(pipelineID)) - } - C.free(buffer) -} diff --git a/examples/internal/gstreamer-src/gst.h b/examples/internal/gstreamer-src/gst.h deleted file mode 100644 index dcdc6baf719..00000000000 --- a/examples/internal/gstreamer-src/gst.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef GST_H -#define GST_H - -#include -#include -#include -#include - -extern void goHandlePipelineBuffer(void *buffer, int bufferLen, int samples, int pipelineId); - -GstElement *gstreamer_send_create_pipeline(char *pipeline); -void gstreamer_send_start_pipeline(GstElement *pipeline, int pipelineId); -void gstreamer_send_stop_pipeline(GstElement *pipeline); -void gstreamer_send_start_mainloop(void); - -#endif diff --git a/examples/janus-gateway/README.md b/examples/janus-gateway/README.md deleted file mode 100644 index 5f8ef2b00f8..00000000000 --- a/examples/janus-gateway/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# janus-gateway -janus-gateway is a collection of examples showing how to use pion-WebRTC with [janus-gateway](https://github.com/meetecho/janus-gateway) - -These examples require that you build+enable websockets with Janus - -## streaming -This example demonstrates how to download a video from a Janus streaming room. Before you run this example, you need to run `plugins/streams/test_gstreamer_1.sh` from Janus. - -You should confirm that you can successfully watch `Opus/VP8 live stream coming from gstreamer (live)` in the stream demo web UI - -### Running -run `main.go` in `github.com/pion/webrtc/examples/janus-gateway/streaming` - -If this worked you will see the following. -``` -Connection State has changed Checking -Connection State has changed Connected -Got VP8 track, saving to disk as output.ivf -``` - -You will see output.ivf in the current folder. - -## video-room -This example demonstrates how to stream to a Janus video-room using pion-WebRTC - -### Running -run `main.go` in `github.com/pion/webrtc/examples/janus-gateway/video-room` - -OSX -```sh -brew install pkg-config -https://gstreamer.freedesktop.org/data/pkg/osx/ - -export PKG_CONFIG_PATH=/Library/Frameworks/GStreamer.framework/Versions/Current/lib/pkgconfig -``` -Ubuntu -```sh -apt install pkg-config -apt install libgstreamer* -``` - -Build -```sh -cd example/janus-gateway/video-room -go build -``` - - - -If this worked you should see a test video in video-room `1234` - -This is the default demo-room that exists in the sample configs, and can quickly be accessed via the Janus demos. diff --git a/examples/janus-gateway/streaming/go.mod b/examples/janus-gateway/streaming/go.mod deleted file mode 100644 index bb414c0c6e7..00000000000 --- a/examples/janus-gateway/streaming/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module github.com/pion/webrtc/examples/janus-gateway/streaming - -replace github.com/pion/webrtc => ../../../ - -require ( - github.com/gorilla/websocket v1.4.0 // indirect - github.com/notedit/janus-go v0.0.0-20180821162543-a152adf0cb7b - github.com/pion/webrtc v1.1.1 -) diff --git a/examples/janus-gateway/streaming/go.sum b/examples/janus-gateway/streaming/go.sum deleted file mode 100644 index 8a06387806a..00000000000 --- a/examples/janus-gateway/streaming/go.sum +++ /dev/null @@ -1,20 +0,0 @@ -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/notedit/janus-go v0.0.0-20180821162543-a152adf0cb7b h1:GT1/zfKpQHX4Cz7F1QUE/tjE/OP0KM5aYaFiKVRgvkk= -github.com/notedit/janus-go v0.0.0-20180821162543-a152adf0cb7b/go.mod h1:BN/Txse3qz8tZOmCm2OfajB2wHVujWmX3o9nVdsI6gE= -github.com/pion/pkg v0.0.0-20181115215726-b60cd756f712 h1:ciXO7F7PusyAzW/EZJt01bETgfTxP/BIGoWQ15pBP54= -github.com/pion/pkg v0.0.0-20181115215726-b60cd756f712/go.mod h1:r9wKZs+Xxv2acLspex4CHQiIhFjGK1zGP+nUm/8klXA= -github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -golang.org/x/net v0.0.0-20181129055619-fae4c4e3ad76 h1:xx5MUFyRQRbPk6VjWjIE1epE/K5AoDD8QUN116NCy8k= -golang.org/x/net v0.0.0-20181129055619-fae4c4e3ad76/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -gotest.tools v2.2.0+incompatible h1:y0IMTfclpMdsdIbr6uwmJn5/WZ7vFuObxDMdrylFM3A= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= diff --git a/examples/janus-gateway/streaming/main.go b/examples/janus-gateway/streaming/main.go deleted file mode 100644 index e41e95d66ce..00000000000 --- a/examples/janus-gateway/streaming/main.go +++ /dev/null @@ -1,177 +0,0 @@ -package main - -import ( - "fmt" - "time" - - janus "github.com/notedit/janus-go" - "github.com/pion/webrtc" - "github.com/pion/webrtc/pkg/media" - "github.com/pion/webrtc/pkg/media/ivfwriter" - "github.com/pion/webrtc/pkg/media/opuswriter" -) - -func saveToDisk(i media.Writer, track *webrtc.Track) { - defer func() { - if err := i.Close(); err != nil { - panic(err) - } - }() - - for { - packet, err := track.ReadRTP() - if err != nil { - panic(err) - } - - if err := i.WriteRTP(packet); err != nil { - panic(err) - } - } -} - -func watchHandle(handle *janus.Handle) { - // wait for event - for { - msg := <-handle.Events - switch msg := msg.(type) { - case *janus.SlowLinkMsg: - fmt.Print("SlowLinkMsg type ", handle.Id) - case *janus.MediaMsg: - fmt.Print("MediaEvent type", msg.Type, " receiving ", msg.Receiving) - case *janus.WebRTCUpMsg: - fmt.Print("WebRTCUp type ", handle.Id) - case *janus.HangupMsg: - fmt.Print("HangupEvent type ", handle.Id) - case *janus.EventMsg: - fmt.Printf("EventMsg %+v", msg.Plugindata.Data) - } - - } -} - -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) - } - - // 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()) - }) - - peerConnection.OnTrack(func(track *webrtc.Track, receiver *webrtc.RTPReceiver) { - codec := track.Codec() - if codec.Name == webrtc.Opus { - fmt.Println("Got Opus track, saving to disk as output.opus") - i, opusNewErr := opuswriter.New("output.opus", codec.ClockRate, codec.Channels) - if opusNewErr != nil { - panic(opusNewErr) - } - saveToDisk(i, track) - } else if codec.Name == webrtc.VP8 { - fmt.Println("Got VP8 track, saving to disk as output.ivf") - i, ivfNewErr := ivfwriter.New("output.ivf") - if ivfNewErr != nil { - panic(ivfNewErr) - } - saveToDisk(i, track) - } - }) - - // Janus - gateway, err := janus.Connect("ws://localhost:8188/") - if err != nil { - panic(err) - } - - // Create session - session, err := gateway.Create() - if err != nil { - panic(err) - } - - // Create handle - handle, err := session.Attach("janus.plugin.streaming") - if err != nil { - panic(err) - } - - go watchHandle(handle) - - // Get streaming list - _, err = handle.Request(map[string]interface{}{ - "request": "list", - }) - if err != nil { - panic(err) - } - - // Watch the second stream - msg, err := handle.Message(map[string]interface{}{ - "request": "watch", - "id": 1, - }, nil) - if err != nil { - panic(err) - } - - if msg.Jsep != nil { - err = peerConnection.SetRemoteDescription(webrtc.SessionDescription{ - Type: webrtc.SDPTypeOffer, - SDP: msg.Jsep["sdp"].(string), - }) - if err != nil { - panic(err) - } - - answer, answerErr := peerConnection.CreateAnswer(nil) - if answerErr != nil { - panic(answerErr) - } - - err = peerConnection.SetLocalDescription(answer) - if err != nil { - panic(err) - } - - // now we start - _, err = handle.Message(map[string]interface{}{ - "request": "start", - }, map[string]interface{}{ - "type": "answer", - "sdp": answer.SDP, - "trickle": false, - }) - if err != nil { - panic(err) - } - } - for { - _, err = session.KeepAlive() - if err != nil { - panic(err) - } - - time.Sleep(5 * time.Second) - } -} diff --git a/examples/janus-gateway/video-room/go.mod b/examples/janus-gateway/video-room/go.mod deleted file mode 100644 index bb414c0c6e7..00000000000 --- a/examples/janus-gateway/video-room/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module github.com/pion/webrtc/examples/janus-gateway/streaming - -replace github.com/pion/webrtc => ../../../ - -require ( - github.com/gorilla/websocket v1.4.0 // indirect - github.com/notedit/janus-go v0.0.0-20180821162543-a152adf0cb7b - github.com/pion/webrtc v1.1.1 -) diff --git a/examples/janus-gateway/video-room/go.sum b/examples/janus-gateway/video-room/go.sum deleted file mode 100644 index 8a06387806a..00000000000 --- a/examples/janus-gateway/video-room/go.sum +++ /dev/null @@ -1,20 +0,0 @@ -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/notedit/janus-go v0.0.0-20180821162543-a152adf0cb7b h1:GT1/zfKpQHX4Cz7F1QUE/tjE/OP0KM5aYaFiKVRgvkk= -github.com/notedit/janus-go v0.0.0-20180821162543-a152adf0cb7b/go.mod h1:BN/Txse3qz8tZOmCm2OfajB2wHVujWmX3o9nVdsI6gE= -github.com/pion/pkg v0.0.0-20181115215726-b60cd756f712 h1:ciXO7F7PusyAzW/EZJt01bETgfTxP/BIGoWQ15pBP54= -github.com/pion/pkg v0.0.0-20181115215726-b60cd756f712/go.mod h1:r9wKZs+Xxv2acLspex4CHQiIhFjGK1zGP+nUm/8klXA= -github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -golang.org/x/net v0.0.0-20181129055619-fae4c4e3ad76 h1:xx5MUFyRQRbPk6VjWjIE1epE/K5AoDD8QUN116NCy8k= -golang.org/x/net v0.0.0-20181129055619-fae4c4e3ad76/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -gotest.tools v2.2.0+incompatible h1:y0IMTfclpMdsdIbr6uwmJn5/WZ7vFuObxDMdrylFM3A= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= diff --git a/examples/janus-gateway/video-room/main.go b/examples/janus-gateway/video-room/main.go deleted file mode 100644 index 217a81a221c..00000000000 --- a/examples/janus-gateway/video-room/main.go +++ /dev/null @@ -1,155 +0,0 @@ -package main - -import ( - "fmt" - "log" - "math/rand" - "time" - - janus "github.com/notedit/janus-go" - "github.com/pion/webrtc" - - gst "github.com/pion/webrtc/examples/internal/gstreamer-src" -) - -func watchHandle(handle *janus.Handle) { - // wait for event - for { - msg := <-handle.Events - switch msg := msg.(type) { - case *janus.SlowLinkMsg: - log.Println("SlowLinkMsg type ", handle.Id) - case *janus.MediaMsg: - log.Println("MediaEvent type", msg.Type, " receiving ", msg.Receiving) - case *janus.WebRTCUpMsg: - log.Println("WebRTCUp type ", handle.Id) - case *janus.HangupMsg: - log.Println("HangupEvent type ", handle.Id) - case *janus.EventMsg: - log.Printf("EventMsg %+v", msg.Plugindata.Data) - } - - } - -} - -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) - } - - peerConnection.OnICEConnectionStateChange(func(connectionState webrtc.ICEConnectionState) { - fmt.Printf("Connection State has changed %s \n", connectionState.String()) - }) - - // Create a audio track - opusTrack, err := peerConnection.NewTrack(webrtc.DefaultPayloadTypeOpus, rand.Uint32(), "audio", "pion1") - if err != nil { - panic(err) - } - _, err = peerConnection.AddTrack(opusTrack) - if err != nil { - panic(err) - } - - // Create a video track - vp8Track, err := peerConnection.NewTrack(webrtc.DefaultPayloadTypeVP8, rand.Uint32(), "video", "pion2") - if err != nil { - panic(err) - } - _, err = peerConnection.AddTrack(vp8Track) - if err != nil { - panic(err) - } - - offer, err := peerConnection.CreateOffer(nil) - if err != nil { - panic(err) - } - - err = peerConnection.SetLocalDescription(offer) - if err != nil { - panic(err) - } - - gateway, err := janus.Connect("ws://localhost:8188/janus") - if err != nil { - panic(err) - } - - session, err := gateway.Create() - if err != nil { - panic(err) - } - - handle, err := session.Attach("janus.plugin.videoroom") - if err != nil { - panic(err) - } - - go func() { - for { - if _, keepAliveErr := session.KeepAlive(); err != nil { - panic(keepAliveErr) - } - - time.Sleep(5 * time.Second) - } - }() - - go watchHandle(handle) - - _, err = handle.Message(map[string]interface{}{ - "request": "join", - "ptype": "publisher", - "room": 1234, - "id": 1, - }, nil) - if err != nil { - panic(err) - } - - msg, err := handle.Message(map[string]interface{}{ - "request": "publish", - "audio": true, - "video": true, - "data": false, - }, map[string]interface{}{ - "type": "offer", - "sdp": offer.SDP, - "trickle": false, - }) - if err != nil { - panic(err) - } - - if msg.Jsep != nil { - err = peerConnection.SetRemoteDescription(webrtc.SessionDescription{ - Type: webrtc.SDPTypeAnswer, - SDP: msg.Jsep["sdp"].(string), - }) - if err != nil { - panic(err) - } - - // Start pushing buffers on these tracks - gst.CreatePipeline(webrtc.Opus, []*webrtc.Track{opusTrack}, "audiotestsrc").Start() - gst.CreatePipeline(webrtc.VP8, []*webrtc.Track{vp8Track}, "videotestsrc").Start() - } - - select {} - -} diff --git a/examples/sfu-minimal/jsfiddle/demo.details b/examples/sfu-minimal/jsfiddle/demo.details index 3a3ab37e258..5662ab976aa 100644 --- a/examples/sfu-minimal/jsfiddle/demo.details +++ b/examples/sfu-minimal/jsfiddle/demo.details @@ -1,5 +1,5 @@ --- - name: gstreamer-receive - description: Example of using pion-WebRTC to play video using GStreamer + name: sfu-minimal + description: Example of a minimal SFU using Pion WebRTC authors: - Sean DuBois diff --git a/examples/sfu-ws/README.md b/examples/sfu-ws/README.md deleted file mode 100644 index 1f3b51c3544..00000000000 --- a/examples/sfu-ws/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# sfu-ws -sfu-ws is a pion-WebRTC application that demonstrates how to broadcast a video to many peers, while only requiring the broadcaster to upload once. - -This could serve as the building block to building conferencing software, and other applications where publishers are bandwidth constrained. - -## Instructions -### Download sfu-ws -``` -go get github.com/pion/webrtc/examples/sfu-ws -``` - -### Run SFU -#### Linux/macOS -go build -./sfu-ws - -### Start a publisher - -* Click `Publish` - -### Start a Subscriber -* Click `Subscribe` - - -You can start one publisher and many subscriber - -Congrats, you have used pion-WebRTC! Now start building something cool diff --git a/examples/sfu-ws/broadcast_data.go b/examples/sfu-ws/broadcast_data.go deleted file mode 100644 index 22308cc63ad..00000000000 --- a/examples/sfu-ws/broadcast_data.go +++ /dev/null @@ -1,47 +0,0 @@ -package main - -import ( - "sync" - - "github.com/pion/webrtc" -) - -type BroadcastHub struct { - broadcastChannel chan []byte - listenChannels map[*uint16]*webrtc.DataChannel - dataMutex *sync.RWMutex -} - -func newHub() *BroadcastHub { - hub := &BroadcastHub{ - broadcastChannel: make(chan []byte), - listenChannels: make(map[*uint16]*webrtc.DataChannel), - dataMutex: new(sync.RWMutex), - } - go hub.run() - return hub -} - -func (h *BroadcastHub) addListener(d *webrtc.DataChannel) { - h.dataMutex.Lock() - h.listenChannels[d.ID()] = d - h.dataMutex.Unlock() -} - -func (h *BroadcastHub) run() { - for { - select { - case message := <-h.broadcastChannel: - h.dataMutex.RLock() - channels := h.listenChannels - h.dataMutex.RUnlock() - for _, client := range channels { - if err := client.SendText(string(message)); err != nil { - h.dataMutex.Lock() - delete(h.listenChannels, client.ID()) - h.dataMutex.Unlock() - } - } - } - } -} diff --git a/examples/sfu-ws/go.mod b/examples/sfu-ws/go.mod deleted file mode 100644 index 3f410afeb9c..00000000000 --- a/examples/sfu-ws/go.mod +++ /dev/null @@ -1,11 +0,0 @@ -module github.com/pion/webrtc/examples/sfu-ws - -require ( - github.com/gorilla/websocket v1.4.0 - github.com/pion/rtcp v1.1.2 - github.com/pion/webrtc v1.2.0 - github.com/povilasv/prommod v0.0.11 - github.com/prometheus/client_golang v0.9.2 -) - -replace github.com/pion/webrtc => ../../ diff --git a/examples/sfu-ws/go.sum b/examples/sfu-ws/go.sum deleted file mode 100644 index f05524c1853..00000000000 --- a/examples/sfu-ws/go.sum +++ /dev/null @@ -1,101 +0,0 @@ -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= -github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= -github.com/cloudflare/sidh v0.0.0-20181111220428-fc8e6378752b h1:pqwbJdj1rgMkE38tDSNnP97wdMYHzV+Lt/aLL2qw2LQ= -github.com/cloudflare/sidh v0.0.0-20181111220428-fc8e6378752b/go.mod h1:o/DcCuWFr9jFzwO+c3y1hhwqKHHKfJ7HvLhWUwRnqfo= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/pion/datachannel v1.2.0 h1:N12qhHSRVlgBcaal2Hi4skdz7VI4yz6bNC5IJDMzCNw= -github.com/pion/datachannel v1.2.0/go.mod h1:MKPEKJRwX/a9/tyQvcVTUI9szyf8ZuUyZxSA9AVMSro= -github.com/pion/dtls v1.2.2 h1:izn/74bIBxVuHb+NdirkmWMH/yFNd8PBVXJgeH/ofGU= -github.com/pion/dtls v1.2.2/go.mod h1:5o0cLHyBEl8CvuA88enDDM6aBwn4SNo8md2dPhcynfc= -github.com/pion/ice v0.1.0 h1:V3RaaUV7QEFUrNk2tHzRqNo3ldCwwnghEpDIQ8+m/eA= -github.com/pion/ice v0.1.0/go.mod h1:vGnMrwYxOMmfR093luGSh2yMm1DDpPqj8lGRNsmo9VQ= -github.com/pion/ice v0.1.1 h1:SZouAvl9RnrNnCHxSnurOfzqK2+oD0ZeURSoxuOs0tI= -github.com/pion/ice v0.1.1/go.mod h1:vGnMrwYxOMmfR093luGSh2yMm1DDpPqj8lGRNsmo9VQ= -github.com/pion/logging v0.1.0 h1:vr+vInmjaRI06CqPWErEQpywxaqoIZcUjQ2eN68jRbk= -github.com/pion/logging v0.1.0/go.mod h1:duuz9/Se8ujqvq7OPzbnPpRlha6A0fk1Ba2wrbn4zew= -github.com/pion/qtls-vendor-extracted v0.0.0-20190210024908-018998217c65 h1:skcEQZ2eUdm1WKlYu7y1y0HBzOwa1pgSAwvhG6PrI2s= -github.com/pion/qtls-vendor-extracted v0.0.0-20190210024908-018998217c65/go.mod h1:tSUehzG/8OAT3JvWvnovveLfRMM8NvgfN1LzwSrBX5s= -github.com/pion/quic v0.0.1 h1:SvloojnZl+wiaee/yKI88n/wQosFMCvatAKyxoRoiFQ= -github.com/pion/quic v0.0.1/go.mod h1:q62rRbOZG6Keu45rWWljWZHXmB3H7fKdeJ1KtNcDrNQ= -github.com/pion/quic-go v0.7.1-0.20190211221741-ec20a8498576 h1:fD1z2bI0qf8yiZGDg5dxhVPP6xtsACP6FN5rDhpDVfM= -github.com/pion/quic-go v0.7.1-0.20190211221741-ec20a8498576/go.mod h1:YvOsXPS6wXEfRGJobrsWSOBmlN6dkEIg+cUpnSDLkhc= -github.com/pion/rtcp v1.1.2 h1:gTb+GOvOYDRZb+3OgZz5PE51xrHGZL0WIM5X37dGi60= -github.com/pion/rtcp v1.1.2/go.mod h1:E8DBOVSErqbHrUEs8KINt3yhzO7FvKuZr2bVUKTvyaw= -github.com/pion/rtp v1.1.0 h1:aioiXSi2UclJptFRqmii76GTrlgry5ucCGtdKc+5VDs= -github.com/pion/rtp v1.1.0/go.mod h1:Bro/2l0PS5C3SQaEpLA+H34kpKIurx3K2Zln/nKjRMs= -github.com/pion/sctp v1.3.0/go.mod h1:GZTG/xApE7wdUFEQq2Rmzgxl/+YaB/L1k8xUl1D5bmo= -github.com/pion/sctp v1.4.2 h1:oOV8oLmGds2GZnIeGSHn8d385kwBxNeWNJ0kJOIR4yY= -github.com/pion/sctp v1.4.2/go.mod h1:Yws4nn6vR0npKJ2n2R+Cm+0JGaMKca0M1pYdGXovz3o= -github.com/pion/sdp/v2 v2.1.0 h1:YbbbaceX1aB6j3hPVdQ6GnniIRKqT/rmfnt4XvKR/E0= -github.com/pion/sdp/v2 v2.1.0/go.mod h1:KGRBcHfpkgJXjrzKJz2wj/Jf1KWnsHdoIiqtayQ5QmE= -github.com/pion/srtp v1.1.2 h1:mMhn9jsMUokSq+Owyviz6zw9BblBQhHiCB21kpP8KOE= -github.com/pion/srtp v1.1.2/go.mod h1:oQrU6IspEuRx9kdWeX2eb54y6F0ieS0J8GZayc9yZY0= -github.com/pion/stun v0.2.0 h1:spIzpfkEg6HV+2iIo6qeOsAjtadZKzbXbrd2e9ZCCcs= -github.com/pion/stun v0.2.0/go.mod h1:rMdCIsqqnTLC4MOHJE3LNiFQRfIjUDzI1kzx//7oPOM= -github.com/pion/transport v0.0.0-20190110151433-e7cbf7d5f464/go.mod h1:HLhzI7I0k8TyiQ99hfRZNRf84lG76eaFnZHnVy/wFnM= -github.com/pion/transport v0.2.0/go.mod h1:HLhzI7I0k8TyiQ99hfRZNRf84lG76eaFnZHnVy/wFnM= -github.com/pion/transport v0.4.0 h1:1N6fluzmj5W/16eFLDsCB18s/xEkjVTek0K4IJz75FU= -github.com/pion/transport v0.4.0/go.mod h1:9gvUd8ZeyU4ZX7dhNuUq97mPoekopkd7eCJEyhKwVO0= -github.com/pion/transport v0.5.0 h1:/KGBCzjc8bvVh8P5NP8GiSGL/PbupzhqvEOEBSlZux0= -github.com/pion/transport v0.5.0/go.mod h1:9gvUd8ZeyU4ZX7dhNuUq97mPoekopkd7eCJEyhKwVO0= -github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/povilasv/prommod v0.0.11 h1:uiCU9z2UpNoMFyd5h3evJB8mTBuT9lZU3CYpMZkkyE0= -github.com/povilasv/prommod v0.0.11/go.mod h1:kMc6cpm22gp7m0cPEFRoRgIzXq75ZIJvNY6GbNu9EJk= -github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740= -github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 h1:PnBWHBf+6L0jOqq0gIVUe6Yk0/QMZ640k6NvkxcBf+8= -github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nLJdBg+pBmGgkJlSaKC2KaQmTCk1XDtE= -github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2 h1:NwxKRvbkH5MsNkvOtPZi3/3kmI8CAzs3mtv+GLQMkNo= -golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/examples/sfu-ws/main.go b/examples/sfu-ws/main.go deleted file mode 100644 index fad1e511cd1..00000000000 --- a/examples/sfu-ws/main.go +++ /dev/null @@ -1,55 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "net/http" - - "github.com/pion/webrtc" - "github.com/povilasv/prommod" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" -) - -func checkError(err error) { - if err != nil { - panic(err) - } -} - -func init() { - - // Generate pem file for https - genPem() - - // Create a MediaEngine object to configure the supported codec - m = webrtc.MediaEngine{} - - // Setup the codecs you want to use. - m.RegisterCodec(webrtc.NewRTPVP8Codec(webrtc.DefaultPayloadTypeVP8, 90000)) - m.RegisterCodec(webrtc.NewRTPOpusCodec(webrtc.DefaultPayloadTypeOpus, 48000)) - - // Create the API object with the MediaEngine - api = webrtc.NewAPI(webrtc.WithMediaEngine(m)) - -} - -func main() { - - prometheus.Register(prommod.NewCollector("sfu-ws")) - - port := flag.String("p", "8443", "https port") - flag.Parse() - - http.Handle("/metrics", promhttp.Handler()) - - // Websocket handle func - http.HandleFunc("/ws", room) - - // Html handle func - http.HandleFunc("/", web) - - // Support https, so we can test by lan - fmt.Println("Web listening :" + *port) - panic(http.ListenAndServeTLS(":"+*port, "cert.pem", "key.pem", nil)) -} diff --git a/examples/sfu-ws/room.go b/examples/sfu-ws/room.go deleted file mode 100644 index b62a5c86160..00000000000 --- a/examples/sfu-ws/room.go +++ /dev/null @@ -1,210 +0,0 @@ -package main - -import ( - "io" - "net/http" - "sync" - - "sync/atomic" - "time" - - "github.com/gorilla/websocket" - "github.com/pion/rtcp" - "github.com/pion/webrtc" -) - -// Peer config -var peerConnectionConfig = webrtc.Configuration{ - ICEServers: []webrtc.ICEServer{ - { - URLs: []string{"stun:stun.l.google.com:19302"}, - }, - }, -} - -var ( - // Media engine - m webrtc.MediaEngine - - // API object - api *webrtc.API - - // Publisher Peer - pubCount int32 - pubReceiver *webrtc.PeerConnection - - // Local track - videoTrack *webrtc.Track - audioTrack *webrtc.Track - videoTrackLock = sync.RWMutex{} - audioTrackLock = sync.RWMutex{} - - // Websocket upgrader - upgrader = websocket.Upgrader{} - - // Broadcast channels - broadcastHub = newHub() -) - -const ( - rtcpPLIInterval = time.Second * 3 -) - -func room(w http.ResponseWriter, r *http.Request) { - - // Websocket client - c, err := upgrader.Upgrade(w, r, nil) - checkError(err) - defer func() { - checkError(c.Close()) - }() - - // Read sdp from websocket - mt, msg, err := c.ReadMessage() - checkError(err) - - if atomic.LoadInt32(&pubCount) == 0 { - atomic.AddInt32(&pubCount, 1) - - // Create a new RTCPeerConnection - 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 { - - // Create a local video track, all our SFU clients will be fed via this track - var err error - videoTrackLock.Lock() - videoTrack, err = pubReceiver.NewTrack(remoteTrack.PayloadType(), remoteTrack.SSRC(), "video", "pion") - videoTrackLock.Unlock() - checkError(err) - - // Send a PLI on an interval so that the publisher is pushing a keyframe every rtcpPLIInterval - go func() { - ticker := time.NewTicker(rtcpPLIInterval) - for range ticker.C { - checkError(pubReceiver.WriteRTCP(&rtcp.PictureLossIndication{MediaSSRC: videoTrack.SSRC()})) - } - }() - - rtpBuf := make([]byte, 1400) - for { - i, err := remoteTrack.Read(rtpBuf) - checkError(err) - videoTrackLock.RLock() - _, err = videoTrack.Write(rtpBuf[:i]) - videoTrackLock.RUnlock() - - if err != io.ErrClosedPipe { - checkError(err) - } - } - - } else { - - // Create a local audio track, all our SFU clients will be fed via this track - var err error - audioTrackLock.Lock() - audioTrack, err = pubReceiver.NewTrack(remoteTrack.PayloadType(), remoteTrack.SSRC(), "audio", "pion") - audioTrackLock.Unlock() - checkError(err) - - rtpBuf := make([]byte, 1400) - for { - i, err := remoteTrack.Read(rtpBuf) - checkError(err) - audioTrackLock.RLock() - _, err = audioTrack.Write(rtpBuf[:i]) - audioTrackLock.RUnlock() - if err != io.ErrClosedPipe { - checkError(err) - } - } - } - }) - - // Set the remote SessionDescription - checkError(pubReceiver.SetRemoteDescription( - webrtc.SessionDescription{ - SDP: string(msg), - Type: webrtc.SDPTypeOffer, - })) - - // Create answer - answer, err := pubReceiver.CreateAnswer(nil) - checkError(err) - - // Sets the LocalDescription, and starts our UDP listeners - checkError(pubReceiver.SetLocalDescription(answer)) - - // Send server sdp to publisher - checkError(c.WriteMessage(mt, []byte(answer.SDP))) - - // Register incoming channel - pubReceiver.OnDataChannel(func(d *webrtc.DataChannel) { - d.OnMessage(func(msg webrtc.DataChannelMessage) { - // Broadcast the data to subSenders - broadcastHub.broadcastChannel <- msg.Data - }) - }) - } else { - - // Create a new PeerConnection - subSender, err := api.NewPeerConnection(peerConnectionConfig) - checkError(err) - - // Register data channel creation handling - subSender.OnDataChannel(func(d *webrtc.DataChannel) { - broadcastHub.addListener(d) - }) - - // Waiting for publisher track finish - for { - videoTrackLock.RLock() - if videoTrack == nil { - videoTrackLock.RUnlock() - //if videoTrack == nil, waiting.. - time.Sleep(100 * time.Millisecond) - } else { - videoTrackLock.RUnlock() - break - } - } - - // Add local video track - videoTrackLock.RLock() - _, err = subSender.AddTrack(videoTrack) - videoTrackLock.RUnlock() - checkError(err) - - // Add local audio track - audioTrackLock.RLock() - _, err = subSender.AddTrack(audioTrack) - audioTrackLock.RUnlock() - checkError(err) - - // Set the remote SessionDescription - checkError(subSender.SetRemoteDescription( - webrtc.SessionDescription{ - SDP: string(msg), - Type: webrtc.SDPTypeOffer, - })) - - // Create answer - answer, err := subSender.CreateAnswer(nil) - checkError(err) - - // Sets the LocalDescription, and starts our UDP listeners - checkError(subSender.SetLocalDescription(answer)) - - // Send server sdp to subscriber - checkError(c.WriteMessage(mt, []byte(answer.SDP))) - } -} diff --git a/examples/sfu-ws/sfu.html b/examples/sfu-ws/sfu.html deleted file mode 100644 index a053a4dd441..00000000000 --- a/examples/sfu-ws/sfu.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - sfu - - - - - -
-
- - - - - - -
- - - - - diff --git a/examples/sfu-ws/web.go b/examples/sfu-ws/web.go deleted file mode 100644 index 209077d0cf2..00000000000 --- a/examples/sfu-ws/web.go +++ /dev/null @@ -1,60 +0,0 @@ -package main - -import ( - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "crypto/x509/pkix" - "encoding/pem" - "html/template" - "math/big" - "net/http" - "os" - "time" -) - -func genPem() { - - privateKey, err := rsa.GenerateKey(rand.Reader, 2048) - checkError(err) - - SNLimit := new(big.Int).Lsh(big.NewInt(1), 128) - SN, err := rand.Int(rand.Reader, SNLimit) - checkError(err) - - template := x509.Certificate{ - SerialNumber: SN, - Subject: pkix.Name{ - Organization: []string{"test"}, - }, - NotBefore: time.Now(), - NotAfter: time.Now().Add(365 * 24 * time.Hour), - - KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, - BasicConstraintsValid: true, - } - template.DNSNames = append(template.DNSNames, "localhost") - template.EmailAddresses = append(template.EmailAddresses, "test@test.com") - - certBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey) - checkError(err) - - certFile, err := os.Create("cert.pem") - checkError(err) - checkError(pem.Encode(certFile, &pem.Block{Type: "CERTIFICATE", Bytes: certBytes})) - checkError(certFile.Close()) - - keyFile, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) - checkError(err) - // pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv.(*rsa.PrivateKey))}) - checkError(pem.Encode(keyFile, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)})) - checkError(keyFile.Close()) -} - -func web(w http.ResponseWriter, r *http.Request) { - if r.Method == "GET" { - t, _ := template.ParseFiles("sfu.html") - checkError(t.Execute(w, nil)) - } -}