Enhance Dockerfile and launch configuration for improved logging and UDP transport; update runtime dependencies and remove unnecessary dummy frames in video processing
This commit is contained in:
parent
5fd57decc9
commit
f151a78ebd
|
|
@ -35,7 +35,11 @@ RUN apt-get update \
|
|||
COPY --from=build /ws/install /ws/install
|
||||
COPY docker-entrypoint.sh /ros_entrypoint.sh
|
||||
RUN chmod +x /ros_entrypoint.sh
|
||||
# Bake FastDDS UDP-only profile into the image so the shared-memory transport
|
||||
# fix applies regardless of how the container is started (compose or docker run).
|
||||
COPY fastdds_no_shm.xml /ws/fastdds_no_shm.xml
|
||||
ENV ROS_DISTRO=humble
|
||||
ENV FASTRTPS_DEFAULT_PROFILES_FILE=/ws/fastdds_no_shm.xml
|
||||
|
||||
## Make ROS and workspace overlays available for interactive shells
|
||||
RUN echo "source /opt/ros/${ROS_DISTRO}/setup.bash || true" > /etc/profile.d/ros2.sh \
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ build-essential
|
|||
cmake
|
||||
pkg-config
|
||||
libopencv-dev
|
||||
python3-opencv
|
||||
python3-rosdep
|
||||
python3-rosdistro
|
||||
software-properties-common
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
libgstreamer1.0-0
|
||||
gstreamer1.0-plugins-base
|
||||
gstreamer1.0-plugins-good
|
||||
gstreamer1.0-plugins-bad
|
||||
gstreamer1.0-plugins-ugly
|
||||
libgstrtspserver-1.0-0
|
||||
python3-opencv
|
||||
ros-humble-ros2cli
|
||||
ros-humble-rclpy
|
||||
net-tools
|
||||
iputils-ping
|
||||
|
|
|
|||
|
|
@ -12,10 +12,11 @@ services:
|
|||
- RMW_IMPLEMENTATION=${RMW_IMPLEMENTATION:-}
|
||||
# GStreamer debug level (uncomment for verbose GStreamer logging)
|
||||
# - GST_DEBUG=${GST_DEBUG:-}
|
||||
# FASTRTPS_DEFAULT_PROFILES_FILE is set in the Dockerfile (baked into image)
|
||||
# Ensure the node binds to non-localhost interface (disable local_only)
|
||||
# and subscribe to the actual image topic available on the host
|
||||
|
||||
command: ["image2rtsp.launch.py", "local_only:=false", "topic:=/camera/image"]
|
||||
command: ["image2rtsp.launch.py", "local_only:=false", "topic:=/camera/image", "log_level:=debug"]
|
||||
|
||||
|
||||
restart: unless-stopped
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!-- Force UDP transport only.
|
||||
Shared memory transport fails between host and Docker container (different
|
||||
PID namespaces) even with network_mode: host. Disabling it forces FastDDS
|
||||
to use UDPv4, which works correctly over the loopback interface. -->
|
||||
<profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles">
|
||||
<transport_descriptors>
|
||||
<transport_descriptor>
|
||||
<transport_id>UDPv4Transport</transport_id>
|
||||
<type>UDPv4</type>
|
||||
</transport_descriptor>
|
||||
</transport_descriptors>
|
||||
<participant profile_name="default_participant" is_default_profile="true">
|
||||
<rtps>
|
||||
<userTransports>
|
||||
<transport_id>UDPv4Transport</transport_id>
|
||||
</userTransports>
|
||||
<useBuiltinTransports>false</useBuiltinTransports>
|
||||
</rtps>
|
||||
</participant>
|
||||
</profiles>
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
import os
|
||||
from ament_index_python.packages import get_package_share_directory
|
||||
from launch import LaunchDescription
|
||||
from launch.actions import DeclareLaunchArgument
|
||||
from launch.substitutions import LaunchConfiguration
|
||||
from launch_ros.actions import Node
|
||||
|
||||
def generate_launch_description():
|
||||
|
|
@ -10,13 +12,19 @@ def generate_launch_description():
|
|||
'parameters.yaml'
|
||||
)
|
||||
|
||||
log_level = LaunchConfiguration('log_level')
|
||||
|
||||
return LaunchDescription([
|
||||
DeclareLaunchArgument(
|
||||
'log_level',
|
||||
default_value='warn',
|
||||
description='ROS logger level (debug, info, warn, error, fatal)'
|
||||
),
|
||||
Node(
|
||||
package='image2rtsp',
|
||||
executable='image2rtsp',
|
||||
name='image2rtsp',
|
||||
parameters=[config],
|
||||
# Reduce runtime logging verbosity to WARN to avoid info spam in container logs
|
||||
arguments=['--ros-args', '--log-level', 'warn']
|
||||
arguments=['--ros-args', '--log-level', log_level]
|
||||
)
|
||||
])
|
||||
|
|
@ -69,7 +69,13 @@ Image2rtsp::Image2rtsp() : Node("image2rtsp"){
|
|||
framerate = extract_framerate(pipeline, 30);
|
||||
rtsp_server_add_url(mountpoint.c_str(), pipeline.c_str());
|
||||
|
||||
RCLCPP_DEBUG(this->get_logger(), "Stream available at rtsp://%s:%s%s", gst_rtsp_server_get_address(rtsp_server), port.c_str(), mountpoint.c_str());
|
||||
const char *server_address = gst_rtsp_server_get_address(rtsp_server);
|
||||
if (local_only) {
|
||||
RCLCPP_DEBUG(this->get_logger(), "Stream available at rtsp://%s:%s%s", server_address, port.c_str(), mountpoint.c_str());
|
||||
} else {
|
||||
RCLCPP_DEBUG(this->get_logger(), "RTSP server bound to %s:%s%s", server_address, port.c_str(), mountpoint.c_str());
|
||||
RCLCPP_DEBUG(this->get_logger(), "Connect clients using rtsp://<host-ip>:%s%s (0.0.0.0 is bind-only)", port.c_str(), mountpoint.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
uint Image2rtsp::extract_framerate(const std::string& pipeline, uint default_framerate = 30) {
|
||||
|
|
|
|||
|
|
@ -87,29 +87,9 @@ static void media_configure(GstRTSPMediaFactory *factory, GstRTSPMedia *media, g
|
|||
gst_app_src_set_max_bytes(node->appsrc, 0);
|
||||
gst_app_src_set_max_time(node->appsrc, 0);
|
||||
|
||||
/* create a minimal dummy preroll frame to satisfy pipeline preroll */
|
||||
guint width = 2;
|
||||
guint height = 2;
|
||||
guint fr = node->framerate > 0 ? node->framerate : 30;
|
||||
GstCaps *caps = gst_caps_new_simple("video/x-raw",
|
||||
"format", G_TYPE_STRING, "RGB",
|
||||
"width", G_TYPE_INT, width,
|
||||
"height", G_TYPE_INT, height,
|
||||
"framerate", GST_TYPE_FRACTION, fr, 1,
|
||||
NULL);
|
||||
gst_app_src_set_caps(node->appsrc, caps);
|
||||
|
||||
gsize buf_size = width * height * 3;
|
||||
GstBuffer *buf = gst_buffer_new_allocate(NULL, buf_size, NULL);
|
||||
GstMapInfo map;
|
||||
if (gst_buffer_map(buf, &map, GST_MAP_WRITE)){
|
||||
if (map.data) memset(map.data, 64, buf_size);
|
||||
gst_buffer_unmap(buf, &map);
|
||||
}
|
||||
GST_BUFFER_FLAG_SET(buf, GST_BUFFER_FLAG_LIVE);
|
||||
gst_app_src_push_buffer(node->appsrc, buf);
|
||||
|
||||
gst_caps_unref(caps);
|
||||
/* caps and first buffer are set by topic_callback from the real image
|
||||
* so that caps always match the actual camera resolution/format.
|
||||
* Pushing a dummy preroll with wrong caps breaks x264enc mid-stream. */
|
||||
gst_object_unref(pipeline);
|
||||
return;
|
||||
} else {
|
||||
|
|
@ -199,6 +179,7 @@ void Image2rtsp::topic_callback(const sensor_msgs::msg::Image::SharedPtr msg){
|
|||
// Set caps from message
|
||||
caps = gst_caps_new_from_image(msg);
|
||||
gst_app_src_set_caps(appsrc, caps);
|
||||
gst_caps_unref(caps);
|
||||
buf = gst_buffer_new_allocate(nullptr, msg->data.size(), nullptr);
|
||||
gst_buffer_fill(buf, 0, msg->data.data(), msg->data.size());
|
||||
GST_BUFFER_FLAG_SET(buf, GST_BUFFER_FLAG_LIVE);
|
||||
|
|
|
|||
Loading…
Reference in New Issue