Browse Source

Merge pull request #622 from paullouisageneau/media-send-example

Add media sender example
Paul-Louis Ageneau 3 years ago
parent
commit
eb95a47fd8
37 changed files with 371 additions and 113 deletions
  1. 3 2
      CMakeLists.txt
  2. 3 2
      examples/README.md
  3. 35 0
      examples/media-receiver/CMakeLists.txt
  4. 20 0
      examples/media-receiver/README.md
  5. 5 2
      examples/media-receiver/main.cpp
  6. 47 0
      examples/media-receiver/main.html
  7. 0 0
      examples/media-receiver/uwp/Logo.png
  8. 0 0
      examples/media-receiver/uwp/SmallLogo.png
  9. 0 0
      examples/media-receiver/uwp/SmallLogo44x44.png
  10. 0 0
      examples/media-receiver/uwp/SplashScreen.png
  11. 0 0
      examples/media-receiver/uwp/StoreLogo.png
  12. 0 0
      examples/media-receiver/uwp/Windows_TemporaryKey.pfx
  13. 0 0
      examples/media-receiver/uwp/package.appxManifest
  14. 35 0
      examples/media-sender/CMakeLists.txt
  15. 18 0
      examples/media-sender/README.md
  16. 108 0
      examples/media-sender/main.cpp
  17. 47 0
      examples/media-sender/main.html
  18. 0 0
      examples/media-sender/uwp/Logo.png
  19. 0 0
      examples/media-sender/uwp/SmallLogo.png
  20. 0 0
      examples/media-sender/uwp/SmallLogo44x44.png
  21. 0 0
      examples/media-sender/uwp/SplashScreen.png
  22. 0 0
      examples/media-sender/uwp/StoreLogo.png
  23. 0 0
      examples/media-sender/uwp/Windows_TemporaryKey.pfx
  24. 42 0
      examples/media-sender/uwp/package.appxManifest
  25. 8 8
      examples/media-sfu/CMakeLists.txt
  26. 0 0
      examples/media-sfu/main.cpp
  27. 0 0
      examples/media-sfu/main.html
  28. BIN
      examples/media-sfu/uwp/Logo.png
  29. BIN
      examples/media-sfu/uwp/SmallLogo.png
  30. BIN
      examples/media-sfu/uwp/SmallLogo44x44.png
  31. BIN
      examples/media-sfu/uwp/SplashScreen.png
  32. BIN
      examples/media-sfu/uwp/StoreLogo.png
  33. BIN
      examples/media-sfu/uwp/Windows_TemporaryKey.pfx
  34. 0 0
      examples/media-sfu/uwp/package.appxManifest
  35. 0 35
      examples/media/CMakeLists.txt
  36. 0 19
      examples/media/README.md
  37. 0 45
      examples/media/main.html

+ 3 - 2
CMakeLists.txt

@@ -472,8 +472,9 @@ if(NOT NO_EXAMPLES)
 		add_subdirectory(examples/client-benchmark)
 	endif()
 	if(NOT NO_MEDIA)
-		add_subdirectory(examples/media)
-		add_subdirectory(examples/sfu-media)
+		add_subdirectory(examples/media-receiver)
+		add_subdirectory(examples/media-sender)
+		add_subdirectory(examples/media-sfu)
 	endif()
 	if(NOT NO_MEDIA AND NOT NO_WEBSOCKET)
     	add_subdirectory(examples/streamer)

+ 3 - 2
examples/README.md

@@ -9,8 +9,9 @@ This directory contains different WebRTC clients and compatible WebSocket + JSON
 - [signaling-server-python](signaling-server-python) contains a similar signaling server in Python
 - [signaling-server-rust](signaling-server-rust) contains a similar signaling server in Rust (see [lerouxrgd/datachannel-rs](https://github.com/lerouxrgd/datachannel-rs) for Rust wrappers)
 
-- [media](media) is a copy/paste demo to send the webcam from your browser into gstreamer.
-- [sfu-media](sfu-media) is a copy/paste SFU demo to relay the webcam between browsers.
+- [media-receiver](media-receiver) is a copy/paste demo to send the webcam from your browser receive it into gstreamer.
+- [media-sender](media-sender) is a copy/paste demo to capture the webcam with gstreamer and send it to your browser.
+- [media-sfu](media-sfu) is a copy/paste SFU demo to relay the webcam between browsers.
 - [streamer](streamer) streams h264 and opus samples to web browsers (signaling-server-python is required).
 
 Additionally, it contains two debugging tools for libdatachannel with copy-pasting as signaling:

+ 35 - 0
examples/media-receiver/CMakeLists.txt

@@ -0,0 +1,35 @@
+cmake_minimum_required(VERSION 3.7)
+
+set(MEDIA_UWP_RESOURCES
+	uwp/Logo.png
+	uwp/package.appxManifest
+	uwp/SmallLogo.png
+	uwp/SmallLogo44x44.png
+	uwp/SplashScreen.png
+	uwp/StoreLogo.png
+	uwp/Windows_TemporaryKey.pfx
+)
+
+if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
+	add_executable(datachannel-media-receiver main.cpp ${MEDIA_UWP_RESOURCES})
+else()
+	add_executable(datachannel-media-receiver main.cpp)
+endif()
+
+set_target_properties(datachannel-media-receiver PROPERTIES
+    CXX_STANDARD 17
+    OUTPUT_NAME media-receiver)
+
+set_target_properties(datachannel-media-receiver PROPERTIES
+	XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER com.github.paullouisageneau.libdatachannel.examples.media-receiver)
+
+find_package(Threads REQUIRED)
+target_link_libraries(datachannel-media-receiver LibDataChannel::LibDataChannel Threads::Threads nlohmann_json)
+
+if(MSVC)
+	add_custom_command(TARGET datachannel-media-receiver POST_BUILD
+		COMMAND ${CMAKE_COMMAND} -E copy_if_different
+		"$<TARGET_FILE_DIR:datachannel>/datachannel.dll"
+		$<TARGET_FILE_DIR:datachannel-media-receiver>
+	)
+endif()

+ 20 - 0
examples/media-receiver/README.md

@@ -0,0 +1,20 @@
+# Example streaming from browser
+
+This is a copy/paste example to stream the webcam from the browser and forward it as RTP to port 5000.
+
+## How to use
+
+Open main.html in your browser (You must open it either as HTTPS or as a domain of http://localhost).
+
+Start the application and copy its offer into the text box on the web page.
+
+Copy the answer of the web page back into the application.
+
+You will now see RTP traffic on `localhost:5000` of the computer that the application is running on.
+
+Use the following gstreamer demo pipeline to display the traffic (You might need to wave your hand in front of your camera to force an I-frame):
+
+```
+$ gst-launch-1.0 udpsrc address=127.0.0.1 port=5000 caps="application/x-rtp" ! queue ! rtph264depay ! video/x-h264,stream-format=byte-stream ! queue ! avdec_h264 ! queue ! autovideosink
+```
+

+ 5 - 2
examples/media/main.cpp → examples/media-receiver/main.cpp

@@ -1,5 +1,5 @@
 /*
- * libdatachannel media example
+ * libdatachannel media receiver example
  * Copyright (c) 2020 Staz Modrzynski
  * Copyright (c) 2020 Paul-Louis Ageneau
  *
@@ -85,12 +85,15 @@ int main() {
 		std::cout << "Please copy/paste the answer provided by the browser: " << std::endl;
 		std::string sdp;
 		std::getline(std::cin, sdp);
+
 		std::cout << "Got answer" << sdp << std::endl;
 		json j = json::parse(sdp);
 		rtc::Description answer(j["sdp"].get<std::string>(), j["type"].get<std::string>());
 		pc->setRemoteDescription(answer);
+
 		std::cout << "Press any key to exit." << std::endl;
-		std::cin >> sdp;
+		char dummy;
+		std::cin >> dummy;
 
 	} catch (const std::exception &e) {
 		std::cerr << "Error: " << e.what() << std::endl;

+ 47 - 0
examples/media-receiver/main.html

@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>libdatachannel media receiver example</title>
+</head>
+<body>
+
+<p>Please enter the offer provided to you by the receiver application: </p>
+<textarea cols="80" rows="25"></textarea>
+<button>Submit</button>
+
+<script>
+    document.querySelector('button').addEventListener('click',  async () => {
+        const offer = JSON.parse(document.querySelector('textarea').value);
+        const pc = new RTCPeerConnection({
+            // Recommended for libdatachannel
+            bundlePolicy: "max-bundle",
+        });
+
+        pc.onicegatheringstatechange = (state) => {
+            if (pc.iceGatheringState === 'complete') {
+                // We only want to provide an answer once all of our candidates have been added to the SDP.
+                const answer = pc.localDescription;
+                document.querySelector('textarea').value = JSON.stringify({"type": answer.type, sdp: answer.sdp});
+                document.querySelector('p').value = 'Please paste the answer in the receiver application.';
+                alert('Please paste the answer in the receiver application.');
+            }
+        }
+
+        await pc.setRemoteDescription(offer);
+
+        const media = await navigator.mediaDevices.getUserMedia({
+            video: {
+                width: 1280,
+                height: 720
+            }
+        });
+        media.getTracks().forEach(track => pc.addTrack(track, media));
+
+        const answer = await pc.createAnswer();
+        await pc.setLocalDescription(answer);
+    })
+</script>
+
+</body>
+</html>

+ 0 - 0
examples/media/uwp/Logo.png → examples/media-receiver/uwp/Logo.png


+ 0 - 0
examples/media/uwp/SmallLogo.png → examples/media-receiver/uwp/SmallLogo.png


+ 0 - 0
examples/media/uwp/SmallLogo44x44.png → examples/media-receiver/uwp/SmallLogo44x44.png


+ 0 - 0
examples/media/uwp/SplashScreen.png → examples/media-receiver/uwp/SplashScreen.png


+ 0 - 0
examples/media/uwp/StoreLogo.png → examples/media-receiver/uwp/StoreLogo.png


+ 0 - 0
examples/media/uwp/Windows_TemporaryKey.pfx → examples/media-receiver/uwp/Windows_TemporaryKey.pfx


+ 0 - 0
examples/media/uwp/package.appxManifest → examples/media-receiver/uwp/package.appxManifest


+ 35 - 0
examples/media-sender/CMakeLists.txt

@@ -0,0 +1,35 @@
+cmake_minimum_required(VERSION 3.7)
+
+set(MEDIA_UWP_RESOURCES
+	uwp/Logo.png
+	uwp/package.appxManifest
+	uwp/SmallLogo.png
+	uwp/SmallLogo44x44.png
+	uwp/SplashScreen.png
+	uwp/StoreLogo.png
+	uwp/Windows_TemporaryKey.pfx
+)
+
+if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
+	add_executable(datachannel-media-sender main.cpp ${MEDIA_UWP_RESOURCES})
+else()
+	add_executable(datachannel-media-sender main.cpp)
+endif()
+
+set_target_properties(datachannel-media-sender PROPERTIES
+    CXX_STANDARD 17
+    OUTPUT_NAME media-sender)
+
+set_target_properties(datachannel-media-sender PROPERTIES
+	XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER com.github.paullouisageneau.libdatachannel.examples.media-sender)
+
+find_package(Threads REQUIRED)
+target_link_libraries(datachannel-media-sender LibDataChannel::LibDataChannel Threads::Threads nlohmann_json)
+
+if(MSVC)
+	add_custom_command(TARGET datachannel-media-sender POST_BUILD
+		COMMAND ${CMAKE_COMMAND} -E copy_if_different
+		"$<TARGET_FILE_DIR:datachannel>/datachannel.dll"
+		$<TARGET_FILE_DIR:datachannel-media-sender>
+	)
+endif()

+ 18 - 0
examples/media-sender/README.md

@@ -0,0 +1,18 @@
+# Example streaming to browser
+
+This is a copy/paste example to forward a local RTP stream to the browser.
+
+## How to use
+
+Open main.html in your browser.
+
+Start the application and copy its offer into the text box on the web page.
+
+Copy the answer of the web page back into the application.
+
+The application expects an incoming RTP h264 video stream with payload type 96 on `localhost:6000`. On Linux, use the following gstreamer demo pipeline to capture video from a V4L2 webcam and send it as RTP to port 6000 (You might need to change `/dev/video0` to your actual device):
+
+```
+$ gst-launch-1.0 v4l2src device=/dev/video0 ! video/x-raw,width=640,height=480 ! videoconvert ! queue ! x264enc tune=zerolatency bitrate=1000 key-int-max=30 ! video/x-h264, profile=constrained-baseline ! rtph264pay pt=96 mtu=1200 ! udpsink host=127.0.0.1 port=6000
+```
+

+ 108 - 0
examples/media-sender/main.cpp

@@ -0,0 +1,108 @@
+/*
+ * libdatachannel media sender example
+ * Copyright (c) 2020 Staz Modrzynski
+ * Copyright (c) 2020 Paul-Louis Ageneau
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "rtc/rtc.hpp"
+
+#include <cstddef>
+#include <iostream>
+#include <memory>
+#include <stdexcept>
+#include <utility>
+
+#include <nlohmann/json.hpp>
+
+#ifdef _WIN32
+#define _WINSOCK_DEPRECATED_NO_WARNINGS
+#include <winsock2.h>
+#else
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+typedef int SOCKET;
+#endif
+
+using nlohmann::json;
+
+const int BUFFER_SIZE = 2048;
+
+int main() {
+	try {
+		rtc::InitLogger(rtc::LogLevel::Debug);
+		auto pc = std::make_shared<rtc::PeerConnection>();
+
+		pc->onStateChange(
+		    [](rtc::PeerConnection::State state) { std::cout << "State: " << state << std::endl; });
+
+		pc->onGatheringStateChange([pc](rtc::PeerConnection::GatheringState state) {
+			std::cout << "Gathering State: " << state << std::endl;
+			if (state == rtc::PeerConnection::GatheringState::Complete) {
+				auto description = pc->localDescription();
+				json message = {{"type", description->typeString()},
+				                {"sdp", std::string(description.value())}};
+				std::cout << message << std::endl;
+			}
+		});
+
+		SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
+		sockaddr_in addr = {};
+		addr.sin_family = AF_INET;
+		addr.sin_addr.s_addr = inet_addr("127.0.0.1");
+		addr.sin_port = htons(6000);
+
+		if (bind(sock, reinterpret_cast<const sockaddr *>(&addr), sizeof(addr)) < 0)
+			throw std::runtime_error("Failed to bind UDP socket on 127.0.0.1:6000");
+
+		int rcvBufSize = 212992;
+		setsockopt(sock, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<const char *>(&rcvBufSize),
+		           sizeof(rcvBufSize));
+
+		const rtc::SSRC ssrc = 42;
+		rtc::Description::Video media("video", rtc::Description::Direction::SendOnly);
+		media.addH264Codec(96); // Must match the payload type of the external h264 RTP stream
+		media.addSSRC(ssrc, "video-send");
+		auto track = pc->addTrack(media);
+
+		pc->setLocalDescription();
+
+		std::cout << "RTP video stream expected on localhost:6000" << std::endl;
+		std::cout << "Please copy/paste the answer provided by the browser: " << std::endl;
+		std::string sdp;
+		std::getline(std::cin, sdp);
+
+		json j = json::parse(sdp);
+		rtc::Description answer(j["sdp"].get<std::string>(), j["type"].get<std::string>());
+		pc->setRemoteDescription(answer);
+
+		// Receive from UDP
+		char buffer[BUFFER_SIZE];
+		int len;
+		while ((len = recv(sock, buffer, BUFFER_SIZE, 0)) >= 0) {
+			if (len < sizeof(rtc::RtpHeader) || !track->isOpen())
+				continue;
+
+			auto rtp = reinterpret_cast<rtc::RtpHeader *>(buffer);
+			rtp->setSsrc(ssrc);
+
+			track->send(reinterpret_cast<const std::byte *>(buffer), len);
+		}
+
+	} catch (const std::exception &e) {
+		std::cerr << "Error: " << e.what() << std::endl;
+	}
+}

+ 47 - 0
examples/media-sender/main.html

@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>libdatachannel media sender example</title>
+</head>
+<body>
+
+<p>Please enter the offer provided to you by the sender application: </p>
+<textarea cols="80" rows="25"></textarea>
+<button>Submit</button>
+
+<video id="video-element" muted></video>
+
+<script>
+    document.querySelector('button').addEventListener('click',  async () => {
+        const offer = JSON.parse(document.querySelector('textarea').value);
+        const pc = new RTCPeerConnection({
+            // Recommended for libdatachannel
+            bundlePolicy: "max-bundle",
+        });
+
+        pc.onicegatheringstatechange = (state) => {
+            if (pc.iceGatheringState === 'complete') {
+                // We only want to provide an answer once all of our candidates have been added to the SDP.
+                const answer = pc.localDescription;
+                document.querySelector('textarea').value = JSON.stringify({"type": answer.type, sdp: answer.sdp});
+                document.querySelector('p').value = 'Please paste the answer in the sender application.';
+                alert('Please paste the answer in the sender application.');
+            }
+        }
+
+		pc.ontrack = (evt) => {
+			const videoElement = document.getElementById('video-element');
+			videoElement.srcObject = evt.streams[0];
+			videoElement.play();
+		};
+
+        await pc.setRemoteDescription(offer);
+
+        const answer = await pc.createAnswer();
+        await pc.setLocalDescription(answer);
+    })
+</script>
+
+</body>
+</html>

+ 0 - 0
examples/sfu-media/uwp/Logo.png → examples/media-sender/uwp/Logo.png


+ 0 - 0
examples/sfu-media/uwp/SmallLogo.png → examples/media-sender/uwp/SmallLogo.png


+ 0 - 0
examples/sfu-media/uwp/SmallLogo44x44.png → examples/media-sender/uwp/SmallLogo44x44.png


+ 0 - 0
examples/sfu-media/uwp/SplashScreen.png → examples/media-sender/uwp/SplashScreen.png


+ 0 - 0
examples/sfu-media/uwp/StoreLogo.png → examples/media-sender/uwp/StoreLogo.png


+ 0 - 0
examples/sfu-media/uwp/Windows_TemporaryKey.pfx → examples/media-sender/uwp/Windows_TemporaryKey.pfx


+ 42 - 0
examples/media-sender/uwp/package.appxManifest

@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Package
+	xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
+	xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
+	xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
+	xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
+	xmlns:iot2="http://schemas.microsoft.com/appx/manifest/iot/windows10/2"
+	IgnorableNamespaces="uap mp">
+
+	<Identity Name="6597869B-290B-3EC7-AC50-87D2B9B408A2" Publisher="CN=CMake" Version="1.0.0.0" />
+	<mp:PhoneIdentity PhoneProductId="6597869B-290B-3EC7-AC50-87D2B9B408A2" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
+	<Properties>
+		<DisplayName>datachannel-media</DisplayName>
+		<PublisherDisplayName>CMake</PublisherDisplayName>
+		<Logo>StoreLogo.png</Logo>
+	</Properties>
+	<Dependencies>
+		<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
+	</Dependencies>
+	<Resources>
+		<Resource Language="x-generate" />
+	</Resources>
+	<Applications>
+		<Application
+			Id="App"
+			Executable="media.exe"
+			EntryPoint="datachannel-media.App"
+			desktop4:Subsystem="console"
+			desktop4:SupportsMultipleInstances="true"
+			iot2:Subsystem="console"
+			iot2:SupportsMultipleInstances="true">
+			<uap:VisualElements
+				DisplayName="datachannel-media"
+				Description="datachannel-media"
+				BackgroundColor="#336699"
+				Square150x150Logo="Logo.png"
+				Square44x44Logo="SmallLogo44x44.png">
+				<uap:SplashScreen Image="SplashScreen.png" />
+			</uap:VisualElements>
+		</Application>
+	</Applications>
+</Package>

+ 8 - 8
examples/sfu-media/CMakeLists.txt → examples/media-sfu/CMakeLists.txt

@@ -11,24 +11,24 @@ set(SFU_MEDIA_UWP_RESOURCES
 )
 
 if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
-	add_executable(datachannel-sfu-media main.cpp ${SFU_MEDIA_UWP_RESOURCES})
+	add_executable(datachannel-media-sfu main.cpp ${SFU_MEDIA_UWP_RESOURCES})
 else()
-	add_executable(datachannel-sfu-media main.cpp)
+	add_executable(datachannel-media-sfu main.cpp)
 endif()
 
-set_target_properties(datachannel-sfu-media PROPERTIES
+set_target_properties(datachannel-media-sfu PROPERTIES
 	CXX_STANDARD 17
-	OUTPUT_NAME sfu-media)
+	OUTPUT_NAME media-sfu)
 
-set_target_properties(datachannel-sfu-media PROPERTIES
+set_target_properties(datachannel-media-sfu PROPERTIES
 	XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER com.github.paullouisageneau.libdatachannel.examples.sfumedia)
 
-target_link_libraries(datachannel-sfu-media LibDataChannel::LibDataChannel nlohmann_json)
+target_link_libraries(datachannel-media-sfu LibDataChannel::LibDataChannel nlohmann_json)
 
 if(MSVC)
-	add_custom_command(TARGET datachannel-sfu-media POST_BUILD
+	add_custom_command(TARGET datachannel-media-sfu POST_BUILD
 		COMMAND ${CMAKE_COMMAND} -E copy_if_different
 		"$<TARGET_FILE_DIR:datachannel>/datachannel.dll"
-		$<TARGET_FILE_DIR:datachannel-sfu-media>
+		$<TARGET_FILE_DIR:datachannel-media-sfu>
 	)
 endif()

+ 0 - 0
examples/sfu-media/main.cpp → examples/media-sfu/main.cpp


+ 0 - 0
examples/sfu-media/main.html → examples/media-sfu/main.html


BIN
examples/media-sfu/uwp/Logo.png


BIN
examples/media-sfu/uwp/SmallLogo.png


BIN
examples/media-sfu/uwp/SmallLogo44x44.png


BIN
examples/media-sfu/uwp/SplashScreen.png


BIN
examples/media-sfu/uwp/StoreLogo.png


BIN
examples/media-sfu/uwp/Windows_TemporaryKey.pfx


+ 0 - 0
examples/sfu-media/uwp/package.appxManifest → examples/media-sfu/uwp/package.appxManifest


+ 0 - 35
examples/media/CMakeLists.txt

@@ -1,35 +0,0 @@
-cmake_minimum_required(VERSION 3.7)
-
-set(MEDIA_UWP_RESOURCES
-	uwp/Logo.png
-	uwp/package.appxManifest
-	uwp/SmallLogo.png
-	uwp/SmallLogo44x44.png
-	uwp/SplashScreen.png
-	uwp/StoreLogo.png
-	uwp/Windows_TemporaryKey.pfx
-)
-
-if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
-	add_executable(datachannel-media main.cpp ${MEDIA_UWP_RESOURCES})
-else()
-	add_executable(datachannel-media main.cpp)
-endif()
-
-set_target_properties(datachannel-media PROPERTIES
-    CXX_STANDARD 17
-    OUTPUT_NAME media)
-
-set_target_properties(datachannel-media PROPERTIES
-	XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER com.github.paullouisageneau.libdatachannel.examples.media)
-
-find_package(Threads REQUIRED)
-target_link_libraries(datachannel-media LibDataChannel::LibDataChannel Threads::Threads nlohmann_json)
-
-if(MSVC)
-	add_custom_command(TARGET datachannel-media POST_BUILD
-		COMMAND ${CMAKE_COMMAND} -E copy_if_different
-		"$<TARGET_FILE_DIR:datachannel>/datachannel.dll"
-		$<TARGET_FILE_DIR:datachannel-media>
-	)
-endif()

+ 0 - 19
examples/media/README.md

@@ -1,19 +0,0 @@
-# Example Webcam from Browser to Port 5000
-This is an example copy/paste demo to send your webcam from your browser and out port 5000 through the demo application.
-
-## How to use
-Open main.html in your browser (you must open it either as HTTPS or as a domain of http://localhost).
-
-Start the application and copy it's offer into the text box of the web page.
-
-Copy the answer of the webpage back into the application.
-
-You will now see RTP traffic on `localhost:5000` of the computer that the application is running on.
-
-Use the following gstreamer demo pipeline to display the traffic
-(you might need to wave your hand in front of your camera to force an I-frame).
-
-```
-$ gst-launch-1.0 udpsrc address=127.0.0.1 port=5000 caps="application/x-rtp" ! queue ! rtph264depay ! video/x-h264,stream-format=byte-stream ! queue ! avdec_h264 ! queue ! autovideosink
-```
-

+ 0 - 45
examples/media/main.html

@@ -1,45 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-    <meta charset="UTF-8">
-    <title>libdatachannel media example</title>
-</head>
-<body>
-
-<p>Please enter the offer provided to you by the application: </p>
-<textarea cols="50" rows="50"></textarea>
-<button>Submit</button>
-
-<script>
-    document.querySelector('button').addEventListener('click',  async () => {
-        let offer = JSON.parse(document.querySelector('textarea').value);
-        rtc = new RTCPeerConnection({
-            // Recommended for libdatachannel
-            bundlePolicy: "max-bundle",
-        });
-
-        rtc.onicegatheringstatechange = (state) => {
-            if (rtc.iceGatheringState === 'complete') {
-                // We only want to provide an answer once all of our candidates have been added to the SDP.
-                let answer = rtc.localDescription;
-                document.querySelector('textarea').value = JSON.stringify({"type": answer.type, sdp: answer.sdp});
-                document.querySelector('p').value = 'Please paste the answer in the application.';
-                alert('Please paste the answer in the application.');
-            }
-        }
-        await rtc.setRemoteDescription(offer);
-
-        let media = await navigator.mediaDevices.getUserMedia({
-            video: {
-                width: 1280,
-                height: 720
-            }
-        });
-        media.getTracks().forEach(track => rtc.addTrack(track, media));
-        let answer = await rtc.createAnswer();
-        await rtc.setLocalDescription(answer);
-    })
-</script>
-
-</body>
-</html>