Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Temporary fixes crash: "AddStream is not available with Unified Plan SdpSemantics. Please use AddTrack instead " #3

Open
wants to merge 7 commits into
base: ros2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
CMakeLists.txt
.vscode/
install/
log/
build/
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "async_web_server_cpp"]
path = async_web_server_cpp
url = https://github.com/erblinium/async_web_server_cpp.git
1 change: 1 addition & 0 deletions async_web_server_cpp
Submodule async_web_server_cpp added at a12cd9
17 changes: 17 additions & 0 deletions scripts/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env bash

set -e

# Get directory of this file
script_dir=$(dirname -- "$(readlink -f -- "$BASH_SOURCE")")
cd $script_dir/..

config=${1:-release}

source /opt/ros/humble/setup.bash

colcon build \
--event-handlers console_cohesion+ \
--cmake-args \
-DCMAKE_BUILD_TYPE=$config \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
12 changes: 11 additions & 1 deletion webrtc_ros/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.5)
project(webrtc_ros)

find_package(ament_cmake REQUIRED)
find_package(ament_cmake_python REQUIRED)
find_package(rclcpp REQUIRED)
find_package(async_web_server_cpp REQUIRED)
find_package(cv_bridge REQUIRED)
Expand All @@ -11,7 +12,7 @@ find_package(webrtc_ros_msgs REQUIRED)
find_package(webrtc REQUIRED)
find_package(X11 REQUIRED)
find_package(jsoncpp REQUIRED)

find_package(rclpy REQUIRED)

###########
## Build ##
Expand Down Expand Up @@ -69,6 +70,15 @@ target_link_libraries(${PROJECT_NAME}_server_node

set_target_properties(${PROJECT_NAME}_server_node PROPERTIES COMPILE_OPTIONS "-std=c++17")

# Install Python executables
install(PROGRAMS
scripts/ice_server_service.py
DESTINATION lib/${PROJECT_NAME}
)

# Install Python modules
ament_python_install_package(${PROJECT_NAME})

#############
## Install ##
#############
Expand Down
5 changes: 5 additions & 0 deletions webrtc_ros/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@
<depend>webrtc_ros_msgs</depend>
<depend>async_web_server_cpp</depend>

<build_depend>rclpy</build_depend>
<exec_depend>rclpy</exec_depend>


<buildtool_depend>ament_cmake</buildtool_depend>
<buildtool_depend>ament_cmake_python</buildtool_depend>
<build_depend>rosidl_default_generators</build_depend>

<exec_depend>rosidl_default_runtime</exec_depend>
Expand Down
73 changes: 39 additions & 34 deletions webrtc_ros/scripts/ice_server_service.py
Original file line number Diff line number Diff line change
@@ -1,73 +1,78 @@
#!/usr/bin/env python
#!/usr/bin/env python3

import json
import rospy
import rclpy
from rclpy.node import Node
from webrtc_ros_msgs.msg import IceServer
from webrtc_ros_msgs.srv import GetIceServers
import requests
from webrtc_ros.msg import IceServer
from webrtc_ros.srv import GetIceServers, GetIceServersResponse


class IceServerManager(object):
class IceServerManager(Node):
""" Manages providing ice server information to the webrtc system """

def __init__(self):
rospy.init_node('ice_server_provider')
super().__init__('ice_server_provider')

self.stun_servers = rospy.get_param('~stun_servers', [
self.stun_servers = self.get_parameter_or('stun_servers', [
'stun:stun1.l.google.com:19302', 'stun:stun2.l.google.com:19302'])
self.turn_server_uris = rospy.get_param('~turn_server_uris', '')
self.turn_creds_uri = rospy.get_param('~turn_server_creds_uri', '')
self.turn_creds_username = rospy.get_param(
'~turn_server_creds_username', '')
self.turn_creds_password = rospy.get_param(
'~turn_server_creds_password', '')
self.turn_server_uris = self.get_parameter_or('turn_server_uris', [])
self.turn_creds_uri = self.get_parameter_or('turn_server_creds_uri', '')
self.turn_creds_username = self.get_parameter_or(
'turn_server_creds_username', '')
self.turn_creds_password = self.get_parameter_or(
'turn_server_creds_password', '')

self.get_ice_servers_service = rospy.Service(
'get_ice_servers', GetIceServers, self.get_ice_servers)
self.get_ice_servers_service = self.create_service(
GetIceServers, 'get_ice_servers', self.get_ice_servers)

rospy.loginfo('Ice Server Provider Up')
rospy.spin()
self.get_logger().info('Ice Server Provider Up')

def get_turn_creds(self):
"""Get the credentials from the turn server."""
if self.turn_creds_uri:
rospy.logdebug('getting turn server credentials')
resp = requests.post(self.turn_creds_uri,
{'username': self.turn_creds_username,
'password': self.turn_creds_password})
self.get_logger().debug('getting turn server credentials')
resp = requests.post(self.turn_creds_uri, json={
'username': self.turn_creds_username,
'password': self.turn_creds_password
})
try:
rospy.loginfo('trying to parse response from server')
self.get_logger().info('trying to parse response from server')
data = resp.json()
if('username' in data and 'password' in data):
rospy.loginfo('succesfully received turn credentials')
if 'username' in data and 'password' in data:
self.get_logger().info('successfully received turn credentials')
return data
rospy.logwarn(
self.get_logger().warn(
'response did not have username and password fields')
except AttributeError:
rospy.logerr(
self.get_logger().error(
'server did not respond with JSON, response code: %i',
resp.status_code)
else:
rospy.logdebug('No uri provided for turn credentials')
self.get_logger().debug('No URI provided for turn credentials')
return False

def get_ice_servers(self, _):
def get_ice_servers(self, request, response):
"""Callback for service. Returns the ice servers"""
resp = GetIceServersResponse()
turn_creds = self.get_turn_creds()
if turn_creds:
for uri in self.turn_server_uris:
serv = IceServer()
serv.uri = uri
serv.username = turn_creds['username']
serv.password = turn_creds['password']
resp.servers.append(serv)
response.servers.append(serv)
for suri in self.stun_servers:
serv = IceServer()
serv.uri = suri
resp.servers.append(serv)
return resp
response.servers.append(serv)
return response

def main(args=None):
rclpy.init(args=args)
ice_server_manager = IceServerManager()
rclpy.spin(ice_server_manager)
ice_server_manager.destroy_node()
rclpy.shutdown()

if __name__ == '__main__':
IceServerManager()
main()
1 change: 1 addition & 0 deletions webrtc_ros/src/ros_video_capturer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ void RosVideoCapturer::imageCallback(const sensor_msgs::msg::Image::ConstPtr& ms
int64_t translated_camera_time_us;
if (AdaptFrame(bgr.cols, bgr.rows, system_time_us, &out_width, &out_height, &roi.width, &roi.height, &roi.x, &roi.y))
{
// Warning: When resizing to YUV format image width and height must be even size (w%2 == 0 )
cv::Mat yuv;
if (out_width == roi.width && out_height == roi.height)
{
Expand Down
16 changes: 7 additions & 9 deletions webrtc_ros/src/webrtc_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,21 +146,21 @@ bool WebrtcClient::initPeerConnection()
}
}
}
config.sdp_semantics = webrtc::SdpSemantics::kPlanB_DEPRECATED;

WebrtcClientWeakPtr weak_this(keep_alive_this_);
webrtc_observer_proxy_ = new rtc::RefCountedObject<WebrtcClientObserverProxy>(weak_this);
peer_connection_ = peer_connection_factory_->CreatePeerConnection(
config,
nullptr,
nullptr,
webrtc_observer_proxy_.get()
);
if (!peer_connection_.get())
auto dependencies = webrtc::PeerConnectionDependencies{webrtc_observer_proxy_.get()};
auto peer_connection_or_error = peer_connection_factory_->CreatePeerConnectionOrError(config, webrtc::PeerConnectionDependencies{webrtc_observer_proxy_.get()});
if (!peer_connection_or_error.ok())
{
RCLCPP_WARN(nh_->get_logger(), "Could not create peer connection");
invalidate();
return false;
}

peer_connection_ = peer_connection_or_error.value();

return true;
}
else
Expand Down Expand Up @@ -281,9 +281,7 @@ void WebrtcClient::handle_message(MessageHandler::Type type, const std::string&

if(action.type == ConfigureAction::kAddStreamActionName) {
FIND_PROPERTY_OR_CONTINUE("id", stream_id);

rtc::scoped_refptr<webrtc::MediaStreamInterface> stream = peer_connection_factory_->CreateLocalMediaStream(stream_id);

if (!peer_connection_->AddStream(stream.get()))
{
RCLCPP_WARN(nh_->get_logger(), "Adding stream to PeerConnection failed");
Expand Down
3 changes: 2 additions & 1 deletion webrtc_ros/web/webrtc_ros.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ window.WebrtcRos = (function() {
"dest":local_stream_config.video.dest
});
}
self.peerConnection.addStream(stream);
// self.peerConnection.addStream(stream);
stream?.getTracks().forEach((track) => {peerConnection.addTrack(track, stream)})
resolve({
"stream": stream,
"remove": new Promise(function(resolve, reject) {
Expand Down
1 change: 1 addition & 0 deletions webrtc_ros/webrtc_ros/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/usr/bin/env python3