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

Added support for hardware-accelerated decoding #254

Open
wants to merge 2 commits into
base: develop
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
22 changes: 21 additions & 1 deletion config/usb_cam.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,27 @@ camera_transport_suffix: image_raw # Suffix used by image_transport to generate
camera_info_url: "" # URI for camera calibration data (likely a YML file obtained from camera_calibration)
image_width: 640 # Frame dimensions, should be supported by camera hardware
image_height: 480
framerate: 30 # Camera polling frequency, Hz (integer)
framerate: 10 # Camera polling frequency, Hz (integer)

# Hardware accelerated decoding (available only for FFMPEG-decoded pixel formats, especially for h264)
# The feature is supported only from libavcodec 52.00.100 built with --enable-vdpau --enable-cuvid --enable-nvenc or
# --enable-cuda options or any other options activating HWACCEL API like --enable-libdrm.
# The exact list of the available hardware accelerators can be printed with command:
# ffmpeg -hwaccels
# then the obtained names would be used to activate the decoder.
# Known accelerators:
# - cuda - for any kind of CUDA/NVENC nVidia-powered accelerators
# - vdpau - libvdpau, nVidia PureVideo HD or AMD VCE on selected devices (mostly incompatible with
# modern H.264 hardware encoders, but decodes almost any flavour of MotionJPEG streams)
# - drm - libdrm, Direct Object Rendering on ARM Mali GPUs supporting OpenCL
# - nvdec - nVidia Codec SDK for AV1 on compatible GPU
# - dxva2 - DirectX Video Accelerator API for Windows
# - vaapi - Intel QuickSync or AMD UVD/VCE decoder on compatible Intel chipsets or AMD Radeon GPUs
# If the desired accelerated decoder is not available or FFMPEG does not respond correctly on the activation request,
# the node falls back automatically to the default software decoder.
hardware_decoder:
enable: false # Instructs the node to try to use a hardware-accelerated video decoder
name: cuda # Name of the desired decoder from FFMPEG HWACCEL API

# Auxiliary camera parameters provided by libv4l2.
# Names for these parameters are generated automatically according to the intrinsic control names exported by the
Expand Down
15 changes: 15 additions & 0 deletions include/usb_cam/camera_driver.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef USB_CAM_CAMERA_DRIVER_H
#define USB_CAM_CAMERA_DRIVER_H

#include "libavutil/pixfmt.h"
#include <string>
#include <iostream>
#include <algorithm>
Expand All @@ -18,6 +19,7 @@ extern "C"
#include <libavutil/imgutils.h>
#include <libavutil/frame.h>
#include <libavutil/mem.h>
#include <libavutil/hwcontext.h>
}

#include <fcntl.h> // for O_* constants
Expand Down Expand Up @@ -65,6 +67,17 @@ class AbstractV4LUSBCam
static camera_image_t * image;
static bool capturing;
static std::vector<capture_format_t> supported_formats;
// Hardware decoder
static bool use_hardware_decoder;
static AVHWDeviceType hardware_decoder_type;
static std::string hardware_decoder_name;
static const AVCodecHWConfig* hardware_decoder_config;
static AVPixelFormat hardware_pixel_format;
static AVBufferRef* hardware_device_context;
static std::vector<std::string> supported_hardware_decoders;
static struct SwsContext* hardware_sws;
static enum AVPixelFormat get_hardware_pixel_format(AVCodecContext *ctx,
const enum AVPixelFormat *pix_fmts);

/* V4L camera parameters */
static bool streaming_status;
Expand Down Expand Up @@ -95,6 +108,7 @@ class AbstractV4LUSBCam
static bool init();
static bool start();
static bool init_decoder();
static bool init_hardware_decoder();
static void run_grabber(unsigned int& buffer_size);
static bool set_v4l_parameter(const std::string & param, const std::string & value);
static inline bool set_v4l_parameter(const std::string & param, int value){return set_v4l_parameter(param, std::to_string(value));}
Expand All @@ -115,6 +129,7 @@ class AbstractV4LUSBCam
public:
virtual ~AbstractV4LUSBCam();
static std::vector<capture_format_t>& get_supported_formats();
static std::vector<std::string>& get_supported_hardware_decoders();
};

} // namespace usb_cam
Expand Down
6 changes: 6 additions & 0 deletions include/usb_cam/usb_cam.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#define USB_CAM_USB_CAM_H

#include <ros/forwards.h>
#include "ros/service_server.h"
#include "usb_cam/camera_driver.h"

#include <ros/ros.h>
Expand Down Expand Up @@ -95,6 +96,11 @@ class UsbCam: public AbstractV4LUSBCam
static bool service_supported_controls_callback(std_srvs::Trigger::Request& request,
std_srvs::Trigger::Response& response);

ros::ServiceServer _service_supported_hardware_decoders;
static ros::ServiceServer* service_supported_hardware_decoders;
static bool service_supported_hardware_decoders_callback(std_srvs::Trigger::Request& request,
std_srvs::Trigger::Response& response);

/* Node parameters */
static std::string camera_name;
static std::string camera_frame_id;
Expand Down
Loading