Add hardware encoding

This commit is contained in:
Gerald Storer 2025-04-01 14:00:31 +08:00
parent 047f42084c
commit ac36d5eee6
No known key found for this signature in database
GPG Key ID: 5F418FD212632274
4 changed files with 51 additions and 3 deletions

View File

@ -60,6 +60,11 @@ sudo apt-get install libgstreamer-plugins-base1.0-dev libgstreamer-plugins-good1
# False = rtsp://0.0.0.0:portAndMountpoint (The stream is accessible from the outside)
# For example, to access the stream running on the machine with IP = 192.168.20.20,
# use rtsp://192.186.20.20:portAndMountpoint
encoder: "software" # Which encoder to use, "hardware" automatically selects an available hardware encoder.
# Use "nvidia", "intel" or "amd" to force an encoder if available.
# Use "software" to force the software encoder.
# Always falls back to software if a hardware encoder can't be found.
# Defaults to "software".
- Save your configuration and navigate to `ros2_ws` colcon root, source and build the package:
```bashrc
cd ~/ros2_ws/

View File

@ -19,3 +19,4 @@
# False = rtsp://0.0.0.0:portAndMountpoint (The stream is accessible from the outside)
# For example, to access the stream running on the machine with IP = 192.168.20.20,
# use rtsp://192.186.20.20:portAndMountpoint
encoder: "software"

View File

@ -28,8 +28,10 @@ private:
string pipeline_tail;
bool local_only;
bool camera;
string encoder;
GstAppSrc *appsrc;
std::string get_encoder_pipeline();
void video_mainloop_start();
void rtsp_server_add_url(const char *url, const char *sPipeline, GstElement **appsrc);
void topic_callback(const sensor_msgs::msg::Image::SharedPtr msg);

View File

@ -19,6 +19,7 @@ Image2rtsp::Image2rtsp() : Node("image2rtsp"){
this->declare_parameter("port", "8554");
this->declare_parameter("local_only", true);
this->declare_parameter("camera", false);
this->declare_parameter("encoder", "software");
source = this->get_parameter("source").as_string();
topic = this->get_parameter("topic").as_string();
@ -30,6 +31,7 @@ Image2rtsp::Image2rtsp() : Node("image2rtsp"){
port = this->get_parameter("port").as_string();
local_only = this->get_parameter("local_only").as_bool();
camera = this->get_parameter("camera").as_bool();
encoder = this->get_parameter("encoder").as_string();
// Start the subscription
subscription_ = this->create_subscription<sensor_msgs::msg::Image>(topic, 10, std::bind(&Image2rtsp::topic_callback, this, _1));
@ -39,11 +41,17 @@ Image2rtsp::Image2rtsp() : Node("image2rtsp"){
rtsp_server = rtsp_server_create(port, local_only);
appsrc = NULL;
// Setup the pipeline
pipeline_tail = " key-int-max=30 ! video/x-h264, profile=baseline ! rtph264pay name=pay0 pt=96 )";
pipeline_tail = " ! video/x-h264,profile=constrained-baseline ! rtph264pay name=pay0 pt=96 "
"config-interval=1 aggregate-mode=zero-latency ! "
"application/x-rtp,media=video )";
auto encoder = get_encoder_pipeline();
if (camera == false){
pipeline_head = "( appsrc name=imagesrc do-timestamp=true min-latency=0 max-latency=0 max-bytes=1000 is-live=true ! videoconvert ! videoscale ! ";
pipeline = pipeline_head + caps_1 + framerate + caps_2 + " ! x264enc tune=zerolatency bitrate=" + bitrate + pipeline_tail;
pipeline_head = "( appsrc name=imagesrc do-timestamp=true min-latency=0 "
"max-latency=0 max-bytes=2000000 is-live=true ! queue max-size-buffers=1 leaky=downstream ! videoconvert ! videoscale ! ";
pipeline = pipeline_head + caps_1 + framerate + caps_2 +
" ! " + encoder + " bitrate=" + bitrate + pipeline_tail;
rtsp_server_add_url(mountpoint.c_str(), pipeline.c_str(), (GstElement **)&(appsrc));
RCLCPP_INFO(this->get_logger(), "pipeline: %s", pipeline.c_str());
}
else {
pipeline = "( " + source + " ! videoconvert ! videoscale ! " + caps_1 + framerate + caps_2 + " ! x264enc tune=zerolatency bitrate=" + bitrate + pipeline_tail;
@ -52,6 +60,38 @@ Image2rtsp::Image2rtsp() : Node("image2rtsp"){
RCLCPP_INFO(this->get_logger(), "Stream available at rtsp://%s:%s%s", gst_rtsp_server_get_address(rtsp_server), port.c_str(), mountpoint.c_str());
}
std::string Image2rtsp::get_encoder_pipeline() {
GstElementFactory* factory;
// Check for NVIDIA encoder
factory = gst_element_factory_find("nvh264enc");
if (factory && (encoder == "hardware" || encoder == "nvidia")) {
gst_object_unref(factory);
RCLCPP_INFO(this->get_logger(), "Using NVIDIA hardware encoder");
return "nvh264enc preset=low-latency-hp rc-mode=cbr-ld-hq zerolatency=true";
}
// Check for VA-API encoder
factory = gst_element_factory_find("vaapih264enc");
if (factory && (encoder == "hardware" || encoder == "intel")) {
gst_object_unref(factory);
RCLCPP_INFO(this->get_logger(), "Using VA-API hardware encoder");
return "vaapipostproc ! vaapih264enc rate-control=cbr quality-level=7";
}
// Check for AMD encoder
factory = gst_element_factory_find("amfh264enc");
if (factory && (encoder == "hardware" || encoder == "amd")) {
gst_object_unref(factory);
RCLCPP_INFO(this->get_logger(), "Using AMD hardware encoder");
return "amfh264enc usage=ultra-low-latency";
}
// Fallback to software encoder
RCLCPP_INFO(this->get_logger(), "Using software encoder");
return "x264enc tune=zerolatency speed-preset=ultrafast";
}
int main(int argc, char *argv[]){
rclcpp::init(argc, argv);
auto node = std::make_shared<Image2rtsp>();