Skip to content

Commit 57b41f1

Browse files
committed
DDS Streaming using H.264 mm extension
Signed-off-by: Victor Chang <vicchang@nvidia.com>
1 parent 3bacac0 commit 57b41f1

13 files changed

Lines changed: 1180 additions & 39 deletions

File tree

applications/dds/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@ cmake_minimum_required(VERSION 3.20)
1717
project(distributed_applications LANGUAGES NONE)
1818

1919

20+
add_holohub_application(dds_h264 DEPENDS
21+
OPERATORS dds_video_publisher
22+
dds_video_subscriber
23+
video_encoder
24+
tensor_to_video_buffer
25+
append_timestamp)
26+
27+
2028
add_holohub_application(dds_video DEPENDS
2129
OPERATORS dds_shapes_subscriber
2230
dds_video_publisher
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
cmake_minimum_required(VERSION 3.24)
17+
project(dds_h264)
18+
19+
find_package(holoscan 2.0 REQUIRED CONFIG
20+
PATHS "/opt/nvidia/holoscan" "/workspace/holoscan-sdk/install")
21+
22+
add_executable(dds_h264 dds_h264.cpp)
23+
target_link_libraries(dds_h264
24+
holoscan::core
25+
holoscan::ops::v4l2
26+
holoscan::ops::gxf_codelet
27+
holoscan::ops::holoviz
28+
holoscan::ops::video_encoder
29+
holoscan::ops::dds_video_publisher
30+
holoscan::ops::dds_video_subscriber
31+
holoscan::ops::append_timestamp
32+
holoscan::ops::format_converter
33+
holoscan::ops::tensor_to_video_buffer
34+
holoscan::ops::video_stream_replayer
35+
)
36+
37+
# Copy qos_profiles.xml to the binary directory
38+
add_custom_target(dds_video_qos_profiles_xml
39+
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/qos_profiles.xml" ${CMAKE_CURRENT_BINARY_DIR}
40+
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/qos_profiles.xml"
41+
)
42+
add_dependencies(dds_h264 dds_video_qos_profiles_xml)
43+
44+
# Copy config file
45+
add_custom_target(dds_h264_yaml
46+
COMMAND ${CMAKE_COMMAND} -E copy_if_different
47+
"${CMAKE_CURRENT_SOURCE_DIR}/dds_h264.yaml" ${CMAKE_CURRENT_BINARY_DIR}
48+
DEPENDS "dds_h264.yaml"
49+
BYPRODUCTS "dds_h264.yaml"
50+
)
51+
add_dependencies(dds_h264 dds_h264_yaml)
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# syntax=docker/dockerfile:1
2+
3+
# SPDX-FileCopyrightText: Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
18+
ARG BASE_IMAGE
19+
ARG GPU_TYPE
20+
21+
############################################################
22+
# Base image
23+
############################################################
24+
25+
ARG BASE_IMAGE
26+
ARG GPU_TYPE
27+
28+
FROM ${BASE_IMAGE} AS base
29+
30+
ARG DEBIAN_FRONTEND=noninteractive
31+
32+
# --------------------------------------------------------------------------
33+
#
34+
# Holohub run setup
35+
#
36+
37+
RUN mkdir -p /tmp/scripts
38+
COPY run /tmp/scripts/
39+
RUN mkdir -p /tmp/scripts/utilities
40+
COPY utilities/holohub_autocomplete /tmp/scripts/utilities/
41+
RUN chmod +x /tmp/scripts/run
42+
RUN /tmp/scripts/run setup
43+
44+
# Enable autocomplete
45+
RUN echo ". /etc/bash_completion.d/holohub_autocomplete" >> /etc/bash.bashrc
46+
47+
# - This variable is consumed by all dependencies below as an environment variable (CMake 3.22+)
48+
# - We use ARG to only set it at docker build time, so it does not affect cmake builds
49+
# performed at docker run time in case users want to use a different BUILD_TYPE
50+
ARG CMAKE_BUILD_TYPE=Release
51+
52+
# Qcap dependency
53+
RUN apt update \
54+
&& apt install --no-install-recommends -y \
55+
libgstreamer1.0-0 \
56+
libgstreamer-plugins-base1.0-0 \
57+
libgles2 \
58+
libopengl0
59+
60+
# For benchmarking
61+
RUN apt update \
62+
&& apt install --no-install-recommends -y \
63+
libcairo2-dev \
64+
libgirepository1.0-dev \
65+
gobject-introspection \
66+
libgtk-3-dev \
67+
libcanberra-gtk-module \
68+
graphviz\
69+
ninja-build
70+
71+
RUN pip install meson
72+
73+
RUN if ! grep -q "VERSION_ID=\"22.04\"" /etc/os-release; then \
74+
pip install setuptools; \
75+
fi
76+
COPY benchmarks/holoscan_flow_benchmarking/requirements.txt /tmp/benchmarking_requirements.txt
77+
RUN pip install -r /tmp/benchmarking_requirements.txt
78+
79+
# For RTI Connext DDS
80+
RUN apt update \
81+
&& apt install --no-install-recommends -y \
82+
openjdk-21-jre
83+
RUN echo 'export JREHOME=$(readlink /etc/alternatives/java | sed -e "s/\/bin\/java//")' >> /etc/bash.bashrc
84+
85+
# Set default Holohub data directory
86+
ENV HOLOSCAN_INPUT_PATH=/workspace/holohub/data
87+
88+
ENV NDDSHOME=/opt/rti.com/rti_connext_dds-7.3.0
89+
ENV RTI_CONNEXT_DDS_DIR=$NDDSHOME
90+
91+
# - Install libv4l-dev required for nvv4l2
92+
# - Install kmod as a workaround to fix iGPU support.
93+
# GXF ENC / DEC needs lsmod to check whether it's dGPU or iGPU.
94+
RUN apt update && apt install -y libv4l-dev kmod
95+
96+
# Below workarounds are required to get H.264 Encode and Decode working inside
97+
# the docker container.
98+
RUN if [ ! -e "/usr/lib/$(arch)-linux-gnu/libnvidia-encode.so" ]; then \
99+
ln -s /usr/lib/$(arch)-linux-gnu/libnvidia-encode.so.1 /usr/lib/$(arch)-linux-gnu/libnvidia-encode.so; \
100+
fi
101+
RUN mkdir /usr/lib/$(arch)-linux-gnu/libv4l/plugins/nv && \
102+
ln -s /usr/lib/$(arch)-linux-gnu/tegra/libv4l2_nvcuvidvideocodec.so /usr/lib/$(arch)-linux-gnu/libv4l/plugins/nv/libv4l2_nvcuvidvideocodec.so
103+
104+
COPY applications/h264/install_dependencies.sh /
105+
106+
WORKDIR /
107+
108+
# Uncomment the following line for aarch64 support
109+
#ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/aarch64-linux-gnu/tegra/
110+
111+
RUN /install_dependencies.sh
112+
113+
CMD ["/bin/bash", "-c", "source $NDDSHOME/resource/scripts/rtisetenv_x64Linux4gcc7.3.0.bash && exec /bin/bash"]
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# DDS Video & H.264 Streaming
2+
3+
This application demonstrates how to encode video frames with H.264 using the multimedia
4+
extension over DDS.
5+
6+
The application can be run as either a publisher or as a subscriber. In either case,
7+
it will use the [VideoFrame](../../../operators/dds/video/VideoFrame.idl) data topic
8+
registered by the `DDSVideoPublisherOp` or `DDSVideoSubscriberOp` operators in order
9+
to write or read the video frame data to/from the DDS databus, respectively.
10+
11+
When run as a publisher, the source for the input video frames can come from either an
12+
attached V4L2-compatible camera via the `V4L2VideoCaptureOp` operator or a video file via the
13+
`VideoStreamReplayerOp`. This can be configured in the `source` field inside the
14+
[dds_h264.yaml](./dds_h264.yaml) configuration file.
15+
16+
When run as a subscriber, the application will use Holoviz to render the received
17+
video frames to the display.
18+
19+
## Prerequisites
20+
21+
- This application requires [RTI Connext](https://content.rti.com/l/983311/2024-04-30/pz1wms)
22+
be installed and configured with a valid RTI Connext license prior to use.
23+
- V4L2 capable device
24+
25+
> [!NOTE]
26+
> Instructions below are based on the `.run' installer from RTI Connext. Refer to the
27+
> [Linux installation](https://community.rti.com/static/documentation/developers/get-started/full-install.html)
28+
> for details.
29+
30+
31+
## Quick Start
32+
33+
```bash
34+
# Start the publisher
35+
./dev_container build_and_run dds_h264 --container_args "-v $HOME/rti_connext_dds-7.3.0:/opt/rti.com/rti_connext_dds-7.3.0/" --run_args "-p"
36+
37+
# Start the subscriber
38+
./dev_container build_and_run dds_h264 --container_args "-v $HOME/rti_connext_dds-7.3.0:/opt/rti.com/rti_connext_dds-7.3.0/" --run_args "-s"
39+
```
40+
41+
42+
## Building the Application
43+
44+
To build on an IGX devkit (using the `armv8` architecture), follow the
45+
[instructions to build Connext DDS applications for embedded Arm targets](https://community.rti.com/kb/how-do-i-create-connext-dds-application-rti-code-generator-and-build-it-my-embedded-target-arm)
46+
up to, and including, step 5 (Installing Java and setting JREHOME).
47+
48+
To build the application, the `RTI_CONNEXT_DDS_DIR` CMake variable must point to
49+
the installation path for RTI Connext. This can be done automatically by setting
50+
the `NDDSHOME` environment variable to the RTI Connext installation directory
51+
(such as when using the RTI `setenv` scripts), or manually at build time, e.g.:
52+
53+
```sh
54+
$ ./run build dds_h264 --configure-args -DRTI_CONNEXT_DDS_DIR=~/rti/rti_connext_dds-7.3.0
55+
```
56+
57+
### Building with a Container
58+
59+
Due to the license requirements of RTI Connext it is not currently supported to
60+
install RTI Connext into a development container. Instead, Connext should be
61+
installed onto the host as above and then the development container can be
62+
launched with the RTI Connext folder mounted at runtime. To do so, ensure that
63+
the `NDDSHOME` and `CONNEXTDDS_ARCH` environment variables are set (which can be
64+
done using the RTI `setenv` script) and use the following:
65+
66+
```sh
67+
# 1. Build the container
68+
./dev_container build --docker_file applications/dds/dds_h264/Dockerfile
69+
# 2. Launch the container
70+
./dev_container launch --docker_opts "-v $HOME/rti_connext_dds-7.3.0:/opt/rti.com/rti_connext_dds-7.3.0/"
71+
# 3. Build the application
72+
./run build dds_h264
73+
# Continue to the next section to run the application with the publisher.
74+
# Open a new terminal to repeat step #2 and launch a new container for the subscriber.
75+
```
76+
77+
78+
79+
## Running the Application
80+
81+
Both a publisher and subscriber process must be launched to see the result of
82+
writing to and reading the video stream from DDS, respectively.
83+
84+
To run the publisher process, use the `-p` option:
85+
86+
```sh
87+
$ ./run launch dds_h264 --extra_args "-p"
88+
```
89+
90+
To run the subscriber process, use the `-s` option:
91+
92+
```sh
93+
$ ./run launch dds_h264 --extra_args "-s"
94+
```
95+
96+
If running the application generates an error about `RTI Connext DDS No Source
97+
for License information`, ensure that the RTI Connext license has either been
98+
installed system-wide or the `NDDSHOME` environment variable has been set to
99+
point to your user's RTI Connext installation path.
100+
101+
Note that these processes can be run on the same or different systems, so long as they
102+
are both discoverable by the other via RTI Connext. If the processes are run on
103+
different systems then they will communicate using UDPv4, for which optimizations have
104+
been defined in the default `qos_profiles.xml` file. These optimizations include
105+
increasing the buffer size used by RTI Connext for network sockets, and so the systems
106+
running the application must also be configured to increase their maximum send and
107+
receive socket buffer sizes. This can be done by running the `set_socket_buffer_sizes.sh`
108+
script within this directory:
109+
110+
```sh
111+
$ ./set_socket_buffer_sizes.sh
112+
```
113+
114+
For more details, see the [RTI Connext Guide to Improve DDS Network Performance on Linux Systems](https://community.rti.com/howto/improve-rti-connext-dds-network-performance-linux-systems)
115+
116+
The QoS profiles used by the application can also be modified by editing the
117+
`qos_profiles.xml` file in the application directory. For more information about modifying
118+
the QoS profiles, see the [RTI Connext Basic QoS](https://community.rti.com/static/documentation/connext-dds/7.3.0/doc/manuals/connext_dds_professional/getting_started_guide/cpp11/intro_qos.html)
119+
tutorial or the [RTI Connext QoS Reference Guide](https://community.rti.com/static/documentation/connext-dds/7.3.0/doc/manuals/connext_dds_professional/qos_reference/index.htm).
120+
121+
## Benchmarks
122+
123+
We collected latency benchmark results from the log output of the subscriber. The benchmark is conducted on x86_64 with NVIDIA ADA6000 GPU.
124+
125+
### Single System Setup
126+
127+
**Source**: Video Stream Replayer
128+
**Resolution**: 854x480
129+
130+
| Configuration | FPS | AVg. Transfer Time | Jitter | Input Size | Avg. Encoded Size |
131+
|-------------------|---------|--------------------|---------|------------|-------------------|
132+
| `realtime: false` | 685.068 | 1.576ms | 0.840ms | 1,229,760 | 25,053 |
133+
| `realtime: true` | 30.049 | 0.150ms | 0.059ms | 1,229,760 | 26,800 |
134+
135+
**Source** : V4L2 Camera
136+
**Frame Rate**: 30
137+
138+
| Resolution | FPS | AVg. Transfer Time | Jitter | Input Size | Avg. Encoded Size |
139+
|------------|--------|--------------------|---------|------------|-------------------|
140+
| 640x480 | 30.169 | 0.098ms | 0.030ms | 921,600 | 16,176 |
141+
| 1920x1080 | 30.281 | 0.104ms | 0.040ms | 6,220,800 | 86,222 |
142+
143+
### Multiple System Setup
144+
145+
The two systems are connected via VPNin this scenario.
146+
147+
**Average Ping Latency**: 22.529ms
148+
149+
150+
**Source**: Video Stream Replayer
151+
**Resolution**: 854x480
152+
153+
| Configuration | FPS | AVg. Transfer Time | Jitter | Input Size | Avg. Encoded Size |
154+
|-------------------|---------|--------------------|---------|------------|-------------------|
155+
| `realtime: false` | 607.581 | 12.278ms | 3.595ms | 1,229,760 | 22,679 |
156+
| `realtime: true` | 30.050 | 12.937ms | 3.856ms | 1,229,760 | 26,741 |
157+
158+
159+
**Source** : V4L2 Camera
160+
**Frame Rate**: 30
161+
162+
| Resolution | FPS | AVg. Transfer Time | Jitter | Input Size | Avg. Encoded Size |
163+
|------------|--------|--------------------|---------|------------|-------------------|
164+
| 640x480 | 30.047 | 10.771ms | 4.621ms | 921,600 | 11,571 |
165+
| 1920x1080 | 28.877 | 14.322ms | 3.420ms | 6,220,800 | 52,273 |

0 commit comments

Comments
 (0)