Skip to content

Commit c9dfc79

Browse files
committed
new interfaces to support decoder fallback, encoder avoids cuda and vaapi hard coding, improved flush
1 parent f044c8d commit c9dfc79

File tree

8 files changed

+475
-116
lines changed

8 files changed

+475
-116
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ nvmpi like so:
7979
'ffmpeg_image_transport.preset': 'll',
8080
'ffmpeg_image_transport.gop_size': 15}]
8181
```
82+
Sometimes the ffmpeg parameters show up under different names. If the above
83+
settings don't work, try the command ``ros2 param dump <name_of_your_node>``
84+
*after* subscribing to the ffmpeg image topic with e.g. ``ros2 topic hz``.
85+
From the output you can see what the correct parameter names are.
8286
## License
8387

8488
This software is issued under the Apache License Version 2.0.

include/ffmpeg_encoder_decoder/decoder.hpp

Lines changed: 73 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,27 +44,90 @@ class Decoder
4444

4545
Decoder();
4646
~Decoder();
47+
/**
48+
* Test if decoder is initialized.
49+
* @return true if the decoder is initialized.
50+
*/
4751
bool isInitialized() const { return (codecContext_ != NULL); }
48-
// Initialize decoder upon first packet received,
49-
// providing callback to be called when frame is complete.
50-
// You must still call decodePacket(msg) afterward!
51-
bool initialize(const std::string & encoding, Callback callback, const std::string & dec);
52-
// clears all state, but leaves config intact
52+
/**
53+
* Initialize decoder, with multiple decoders to pick from.
54+
* Will pick hardware accelerated decoders first if available.
55+
* If decoders.empty() a default decoder will be chosen (if available).
56+
* @param encoding the encoding from the first packet. Can never change!
57+
* @param callback the function to call when frame has been decoded
58+
* @param decoder the decoder to use. If empty string,
59+
* the decoder will try to find a suitable one based on the encoding
60+
* @return true if successful
61+
*/
62+
63+
bool initialize(const std::string & encoding, Callback callback, const std::string & decoder);
64+
/**
65+
* Initialize decoder with multiple decoders to pick from.
66+
* Will pick hardware accelerated decoders first if available.
67+
* If decoders.empty() a default decoder will be chosen (if available).
68+
* @param encoding the encoding from the first packet. Can never change!
69+
* @param callback the function to call when frame has been decoded
70+
* @param decoders the set of decoders to try sequentially. If empty()
71+
* the decoder will try to find a suitable one based on the encoding
72+
* @return true if successful
73+
*/
74+
bool initialize(
75+
const std::string & encoding, Callback callback, const std::vector<std::string> & decoders);
76+
/**
77+
* Clears all decoder state but not timers, loggers, and other settings.
78+
*/
5379
void reset();
54-
// decode packet (may result in frame callback!)
80+
/**
81+
* Decodes packet. Decoder must have been initialized beforehand. Calling this
82+
* function may result in callback with decoded frame.
83+
* @param encoding the name of the encoding (typically from msg encoding)
84+
* @param data pointer to packet data
85+
* @param size size of packet data
86+
* @param pts presentation time stamp of data packet
87+
* @param frame_id ros frame id (from message header)
88+
* @param stamp ros message header time stamp
89+
*/
5590
bool decodePacket(
5691
const std::string & encoding, const uint8_t * data, size_t size, uint64_t pts,
5792
const std::string & frame_id, const rclcpp::Time & stamp);
58-
93+
/**
94+
* Override default logger
95+
* @param logger the logger to override the default with
96+
*/
97+
void setLogger(rclcpp::Logger logger) { logger_ = logger; }
98+
/**
99+
* deprecated, don't use!
100+
*/
101+
static const std::unordered_map<std::string, std::string> & getDefaultEncoderToDecoderMap();
102+
/**
103+
* Finds the name of hardware and software decoders that match a
104+
* certain encoding (or encoder)
105+
*/
106+
static void findDecoders(
107+
const std::string & encoding, std::vector<std::string> * hw_decoders,
108+
std::vector<std::string> * sw_decoders);
109+
/**
110+
* Finds the name of all hardware and software decoders that match
111+
* a certain encoding (or encoder)
112+
*/
113+
static std::vector<std::string> findDecoders(const std::string & encoding);
114+
/**
115+
* For performance debugging
116+
*/
59117
void setMeasurePerformance(bool p) { measurePerformance_ = p; }
118+
/**
119+
* For performance debugging
120+
*/
60121
void printTimers(const std::string & prefix) const;
122+
/**
123+
* For performance debugging
124+
*/
61125
void resetTimers();
62-
void setLogger(rclcpp::Logger logger) { logger_ = logger; }
63-
static const std::unordered_map<std::string, std::string> & getDefaultEncoderToDecoderMap();
64126

65127
private:
66128
rclcpp::Logger logger_;
67-
bool initDecoder(const std::string & encoding, const std::string & decoder);
129+
bool initSingleDecoder(const std::string & decoder);
130+
bool initDecoder(const std::vector<std::string> & decoders);
68131
// --------------- variables
69132
Callback callback_;
70133
PTSMap ptsToStamp_; // mapping of header

include/ffmpeg_encoder_decoder/encoder.hpp

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,8 @@ class Encoder
5050
Encoder();
5151
~Encoder();
5252
// ------- various encoding settings
53-
void setEncoder(const std::string & n)
54-
{
55-
Lock lock(mutex_);
56-
encoder_ = n;
57-
}
53+
void setEncoder(const std::string & n);
54+
5855
void setProfile(const std::string & p)
5956
{
6057
Lock lock(mutex_);
@@ -105,6 +102,16 @@ class Encoder
105102
Lock lock(mutex_);
106103
GOPSize_ = g;
107104
}
105+
int getMaxBFrames() const
106+
{
107+
Lock lock(mutex_);
108+
return (maxBFrames_);
109+
}
110+
void setMaxBFrames(int b)
111+
{
112+
Lock lock(mutex_);
113+
maxBFrames_ = b;
114+
}
108115
void setFrameRate(int frames, int second)
109116
{
110117
Lock lock(mutex_);
@@ -130,8 +137,22 @@ class Encoder
130137
// encode image
131138
void encodeImage(const cv::Mat & img, const Header & header, const rclcpp::Time & t0);
132139
void encodeImage(const Image & msg);
133-
// flush all packets. Need header to generate callback message
140+
/**!
141+
* flush all packets (produces callbacks).
142+
* \param frame_id the frame id that will be presented on callback
143+
*/
144+
void flush(const std::string & frame_id);
145+
/**!
146+
* flush all packets (produces callbacks).
147+
* \deprecated Only header.frame_id is used. Used flush(frame_id) now.
148+
*/
134149
void flush(const Header & header);
150+
151+
/**!
152+
* finds the encoding for a given encoder, i.e. returns h264 for h264_vaapi
153+
*/
154+
static std::string findEncoding(const std::string & encoder);
155+
135156
// ------- performance statistics
136157
void printTimers(const std::string & prefix) const;
137158
void resetTimers();
@@ -142,27 +163,31 @@ class Encoder
142163
bool openCodec(int width, int height);
143164
void doOpenCodec(int width, int height);
144165
void closeCodec();
145-
int drainPacket(const Header & hdr, int width, int height);
166+
int drainPacket(const std::string & frame_id, int width, int height);
146167
AVPixelFormat pixelFormat(const std::string & f) const;
147-
void openVAAPIDevice(const AVCodec * codec, int width, int height);
168+
void openHardwareDevice(
169+
const AVCodec * codec, enum AVHWDeviceType hwDevType, int width, int height);
148170
void setAVOption(const std::string & field, const std::string & value);
149171
// --------- variables
150172
rclcpp::Logger logger_;
151173
mutable std::recursive_mutex mutex_;
152174
Callback callback_;
153175
// config
154-
std::string encoder_; // e.g. "libx264"
155-
std::string preset_; // e.g. "slow", "medium", "lossless"
156-
std::string profile_; // e.g. "main", "high", "rext"
157-
std::string tune_; // e.g. "tune"
158-
std::string delay_; // default is 4 frames for parallel processing. 0 is lowest latency
159-
std::string crf_; // constant rate factor. 0 is lossless, 51 is worst quality
160-
int qmax_{0}; // max allowed quantization. The lower the better quality
161-
int GOPSize_{15}; // distance between two keyframes
176+
std::string encoder_; // e.g. "libx264"
177+
std::string encoding_; // e.g. "h264"
178+
std::string preset_; // e.g. "slow", "medium", "lossless"
179+
std::string profile_; // e.g. "main", "high", "rext"
180+
std::string tune_; // e.g. "tune"
181+
std::string delay_; // default is 4 frames for parallel processing. 0 is lowest latency
182+
std::string crf_; // constant rate factor. 0 is lossless, 51 is worst quality
183+
int qmax_{-1}; // max allowed quantization. The lower the better quality
184+
int GOPSize_{-1}; // distance between two keyframes
185+
int maxBFrames_{-1}; // maximum number of b-frames
186+
int64_t bitRate_{0}; // max rate in bits/s
187+
162188
AVPixelFormat pixFormat_{AV_PIX_FMT_NONE};
163189
AVRational timeBase_{1, 100};
164190
AVRational frameRate_{100, 1};
165-
int64_t bitRate_{1000000};
166191
bool usesHardwareFrames_{false};
167192
// ------ libav state
168193
AVCodecContext * codecContext_{nullptr};

include/ffmpeg_encoder_decoder/utils.hpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#ifndef FFMPEG_ENCODER_DECODER__UTILS_HPP_
1717
#define FFMPEG_ENCODER_DECODER__UTILS_HPP_
1818

19+
#include <map>
1920
#include <opencv2/core.hpp>
2021
#include <string>
2122
#include <vector>
@@ -62,7 +63,29 @@ std::vector<enum AVPixelFormat> get_encoder_formats(
6263
* picks from a vector of formats the "best" pixel format for a given encoder
6364
*/
6465
enum AVPixelFormat get_preferred_pixel_format(
65-
const std::string & encoder, const std::vector<AVPixelFormat> & fmts);
66+
bool useHWFormat, const std::vector<AVPixelFormat> & fmts);
67+
68+
/**!
69+
* finds the names of all available decoders for a given encoding (or encoder)
70+
*/
71+
void find_decoders(
72+
const std::string & encoding, std::vector<std::string> * hw_decoders,
73+
std::vector<std::string> * sw_decoders);
74+
75+
/**!
76+
* * get hardware device types
77+
*/
78+
std::vector<std::string> get_hwdevice_types();
79+
80+
/**!
81+
* find encoding for given encoder
82+
*/
83+
std::string find_encoding(const std::string & encoder);
84+
85+
/**!
86+
* gets hardware device type for specific codec
87+
*/
88+
enum AVHWDeviceType find_hw_device_type(const AVCodec * codec);
6689

6790
} // namespace utils
6891
} // namespace ffmpeg_encoder_decoder

0 commit comments

Comments
 (0)