Add hardware encoding
This commit is contained in:
parent
047f42084c
commit
ac36d5eee6
|
|
@ -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)
|
# 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,
|
# For example, to access the stream running on the machine with IP = 192.168.20.20,
|
||||||
# use rtsp://192.186.20.20:portAndMountpoint
|
# 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:
|
- Save your configuration and navigate to `ros2_ws` colcon root, source and build the package:
|
||||||
```bashrc
|
```bashrc
|
||||||
cd ~/ros2_ws/
|
cd ~/ros2_ws/
|
||||||
|
|
|
||||||
|
|
@ -19,3 +19,4 @@
|
||||||
# False = rtsp://0.0.0.0:portAndMountpoint (The stream is accessible from the outside)
|
# 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,
|
# For example, to access the stream running on the machine with IP = 192.168.20.20,
|
||||||
# use rtsp://192.186.20.20:portAndMountpoint
|
# use rtsp://192.186.20.20:portAndMountpoint
|
||||||
|
encoder: "software"
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,10 @@ private:
|
||||||
string pipeline_tail;
|
string pipeline_tail;
|
||||||
bool local_only;
|
bool local_only;
|
||||||
bool camera;
|
bool camera;
|
||||||
|
string encoder;
|
||||||
GstAppSrc *appsrc;
|
GstAppSrc *appsrc;
|
||||||
|
|
||||||
|
std::string get_encoder_pipeline();
|
||||||
void video_mainloop_start();
|
void video_mainloop_start();
|
||||||
void rtsp_server_add_url(const char *url, const char *sPipeline, GstElement **appsrc);
|
void rtsp_server_add_url(const char *url, const char *sPipeline, GstElement **appsrc);
|
||||||
void topic_callback(const sensor_msgs::msg::Image::SharedPtr msg);
|
void topic_callback(const sensor_msgs::msg::Image::SharedPtr msg);
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ Image2rtsp::Image2rtsp() : Node("image2rtsp"){
|
||||||
this->declare_parameter("port", "8554");
|
this->declare_parameter("port", "8554");
|
||||||
this->declare_parameter("local_only", true);
|
this->declare_parameter("local_only", true);
|
||||||
this->declare_parameter("camera", false);
|
this->declare_parameter("camera", false);
|
||||||
|
this->declare_parameter("encoder", "software");
|
||||||
|
|
||||||
source = this->get_parameter("source").as_string();
|
source = this->get_parameter("source").as_string();
|
||||||
topic = this->get_parameter("topic").as_string();
|
topic = this->get_parameter("topic").as_string();
|
||||||
|
|
@ -30,6 +31,7 @@ Image2rtsp::Image2rtsp() : Node("image2rtsp"){
|
||||||
port = this->get_parameter("port").as_string();
|
port = this->get_parameter("port").as_string();
|
||||||
local_only = this->get_parameter("local_only").as_bool();
|
local_only = this->get_parameter("local_only").as_bool();
|
||||||
camera = this->get_parameter("camera").as_bool();
|
camera = this->get_parameter("camera").as_bool();
|
||||||
|
encoder = this->get_parameter("encoder").as_string();
|
||||||
|
|
||||||
// Start the subscription
|
// Start the subscription
|
||||||
subscription_ = this->create_subscription<sensor_msgs::msg::Image>(topic, 10, std::bind(&Image2rtsp::topic_callback, this, _1));
|
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);
|
rtsp_server = rtsp_server_create(port, local_only);
|
||||||
appsrc = NULL;
|
appsrc = NULL;
|
||||||
// Setup the pipeline
|
// 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){
|
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_head = "( appsrc name=imagesrc do-timestamp=true min-latency=0 "
|
||||||
pipeline = pipeline_head + caps_1 + framerate + caps_2 + " ! x264enc tune=zerolatency bitrate=" + bitrate + pipeline_tail;
|
"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));
|
rtsp_server_add_url(mountpoint.c_str(), pipeline.c_str(), (GstElement **)&(appsrc));
|
||||||
|
RCLCPP_INFO(this->get_logger(), "pipeline: %s", pipeline.c_str());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pipeline = "( " + source + " ! videoconvert ! videoscale ! " + caps_1 + framerate + caps_2 + " ! x264enc tune=zerolatency bitrate=" + bitrate + pipeline_tail;
|
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());
|
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[]){
|
int main(int argc, char *argv[]){
|
||||||
rclcpp::init(argc, argv);
|
rclcpp::init(argc, argv);
|
||||||
auto node = std::make_shared<Image2rtsp>();
|
auto node = std::make_shared<Image2rtsp>();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue