Repo symbol

ffmpeg_encoder_decoder repository

ffmpeg_encoder_decoder

ROS Distro
humble

Repository Summary

Checkout URI https://github.com/ros-misc-utilities/ffmpeg_encoder_decoder.git
VCS Type git
VCS Version release
Last Updated 2025-08-08
Dev Status DEVELOPED
Released RELEASED
Tags No category tags.
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Packages

Name Version
ffmpeg_encoder_decoder 3.0.0

README

ROS2 FFMPeg encoder/decoder

This ROS2 package supports encoding/decoding with the FFMpeg library, for example encoding h264 and h265 or HEVC, using Nvidia or other hardware acceleration when available. This package is meant to be used by image transport plugins like the ffmpeg image transport and the foxglove compressed video transport.

Supported systems

Continuous integration is tested under Ubuntu with the following ROS2 distros:

Build Status Build Status Build Status Build Status

Installation

From packages

sudo apt-get install ros-${ROS_DISTRO}-ffmpeg-encoder-decoder

From source

Set the following shell variables:

repo=ffmpeg_encoder_decoder
url=https://github.com/ros-misc-utilities/${repo}.git

and follow the instructions here

Make sure to source your workspace’s install/setup.bash afterwards.

API overview

Preliminaries

When using libav it is important to understand the difference between the encoder and the codec. The codec is the standardized format in which images are encoded, for instance h264 or hevc. The encoder is a libav software module that can encode images for a given codec. For instance libx264, libx264rgb, h264_nvenc, and h264_vaapi` are all encoders that encode for the codec h264. Some of the encoders are hardware accelerated, some can handle more image formats than others, but in the end they all encode video for a specific codec.

For the many AV options available for various libav encoders, and for qmax, bit_rate and similar settings please refer to the ffmpeg documentation.

The inner workings

overview_diagram

The diagram above shows the stations that a ROS Image message passes as it traverses the encoder and decoder. 1) The ROS image (with ROS sensor_msgs/Image encoding) is first converted with the ROS cv_bridge into the cv_bridge_target_format. This conversion is necessary because some ROS encodings (like bayer images) are not supported by libswscale. The cv_bridge_target_format can be set via setCVBridgeTargetFormat(const std::string & fmt). If this format is not set explicitly the image will be converted to the default format of bgr8. This may not be what you want for e.g. mono8 (gray) or Bayer images. Ideally thecv_bridge_target_format can be directly used by the libav decoder so the next step becomes a no-op. But at the very least cv_bridge_target_format must be an acceptable libswscale input format (with the exception of special hacks for encoding single-channel images, see below). 2) The image is then converted to av_source_pixel_format using libswscale. The av_source_pixel_format can be set with setAVSourcePixelFormat(), defaulting to something that is acceptable to the libav encoder. You can use ffmpeg (ffmpeg -h encoder=libx264 | grep formats) to list all formats that an encoder supports. Note that the ffmpeg/libav format string notation is different from the ROS encoding strings, and the av_source_pixel_format is specified using the libav convention, whereas the cv_bridge_target_format uses ROS convention! (If you choose to bypass the cv_bridge conversion from step 1 by feeding the images to the encoder directly via the encodeImage(const cv::Mat & img ...) method, you must still set the cv_bridge_target_format such that the encoder knows what format the img argument has.) When aiming for lossless compression, beware of any av_source_pixel_format that reduces the color resolution, such as yuv420p, nv12 etc. For Bayer images, use the special hack for single-channel images.

3) The libav encoder encodes the packet with its supported codec, e.g. the libx264 will produce h264 packets. The encoding field of the FFMPEGPacket message will document all image format conversions and the codec, in reverse order, separated by semicolon. This way the decoder can attempt to reproduce the original ros_encoding.

4) The libav decoder decodes the packet into the original av_source_pixel_format.

5) Finally the image is converted to output_message_format using libswscale. This format can be set (in ROS encoding syntax!) with setOutputMessageEncoding(). The format must be supported by both ROS and libswscale (except when using the special hack for single-channel images).

Note that only very few combinations of libav encoders, cv_bridge_target_format and av_source_pixel_format have been tested. Please provide feedback if you observe crashes or find obvious bugs. PRs are always appreciated!

The special single-channel hack

Many libav encoders do not support single-channel formats (like mono8 or bayer). For this reason a special hack is implemented in the encoder that adds an empty (zero-value) color channel to the single-channel image. Later, the decoder removes it again. To utilitze this hack, specify a cv_bridge_target_format of e.g. bayer_rggb8. Without the special hack, this would trigger an error because Bayer formats are not acceptable to libswscale. Instead, the image is converted to yuv420p or nv12 by adding an empty color channel. These formats are acceptable to most encoders. The decoder in turn recognizes that the cv_bridge_target_format is a single-channel format, but yuv420p/nv12 are not, and therefore drops the color channel. This hack greatly improves the efficiency for lossless encoding of Bayer images because it avoids conversion to full RGB and back.

API usage

Encoder

Using the encoder involves the following steps:

  • instantiating the Encoder object.
  • setting properties like the libav encoder to use, the encoding formats, and AV options.
  • initializing the encoder object. This requires knowledge of the image size and therefore

File truncated at 100 lines see the full file

CONTRIBUTING

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that license:

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

Contributors must sign-off each commit by adding a Signed-off-by: ... line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the Developer Certificate of Origin (DCO).

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that [license](http://www.apache.org/licenses/LICENSE-2.0.html): ~~~ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. ~~~ Contributors must sign-off each commit by adding a `Signed-off-by: ...` line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the [Developer Certificate of Origin (DCO)](https://developercertificate.org/).
Repo symbol

ffmpeg_encoder_decoder repository

ffmpeg_encoder_decoder

ROS Distro
jazzy

Repository Summary

Checkout URI https://github.com/ros-misc-utilities/ffmpeg_encoder_decoder.git
VCS Type git
VCS Version release
Last Updated 2025-08-08
Dev Status DEVELOPED
Released RELEASED
Tags No category tags.
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Packages

Name Version
ffmpeg_encoder_decoder 3.0.0

README

ROS2 FFMPeg encoder/decoder

This ROS2 package supports encoding/decoding with the FFMpeg library, for example encoding h264 and h265 or HEVC, using Nvidia or other hardware acceleration when available. This package is meant to be used by image transport plugins like the ffmpeg image transport and the foxglove compressed video transport.

Supported systems

Continuous integration is tested under Ubuntu with the following ROS2 distros:

Build Status Build Status Build Status Build Status

Installation

From packages

sudo apt-get install ros-${ROS_DISTRO}-ffmpeg-encoder-decoder

From source

Set the following shell variables:

repo=ffmpeg_encoder_decoder
url=https://github.com/ros-misc-utilities/${repo}.git

and follow the instructions here

Make sure to source your workspace’s install/setup.bash afterwards.

API overview

Preliminaries

When using libav it is important to understand the difference between the encoder and the codec. The codec is the standardized format in which images are encoded, for instance h264 or hevc. The encoder is a libav software module that can encode images for a given codec. For instance libx264, libx264rgb, h264_nvenc, and h264_vaapi` are all encoders that encode for the codec h264. Some of the encoders are hardware accelerated, some can handle more image formats than others, but in the end they all encode video for a specific codec.

For the many AV options available for various libav encoders, and for qmax, bit_rate and similar settings please refer to the ffmpeg documentation.

The inner workings

overview_diagram

The diagram above shows the stations that a ROS Image message passes as it traverses the encoder and decoder. 1) The ROS image (with ROS sensor_msgs/Image encoding) is first converted with the ROS cv_bridge into the cv_bridge_target_format. This conversion is necessary because some ROS encodings (like bayer images) are not supported by libswscale. The cv_bridge_target_format can be set via setCVBridgeTargetFormat(const std::string & fmt). If this format is not set explicitly the image will be converted to the default format of bgr8. This may not be what you want for e.g. mono8 (gray) or Bayer images. Ideally thecv_bridge_target_format can be directly used by the libav decoder so the next step becomes a no-op. But at the very least cv_bridge_target_format must be an acceptable libswscale input format (with the exception of special hacks for encoding single-channel images, see below). 2) The image is then converted to av_source_pixel_format using libswscale. The av_source_pixel_format can be set with setAVSourcePixelFormat(), defaulting to something that is acceptable to the libav encoder. You can use ffmpeg (ffmpeg -h encoder=libx264 | grep formats) to list all formats that an encoder supports. Note that the ffmpeg/libav format string notation is different from the ROS encoding strings, and the av_source_pixel_format is specified using the libav convention, whereas the cv_bridge_target_format uses ROS convention! (If you choose to bypass the cv_bridge conversion from step 1 by feeding the images to the encoder directly via the encodeImage(const cv::Mat & img ...) method, you must still set the cv_bridge_target_format such that the encoder knows what format the img argument has.) When aiming for lossless compression, beware of any av_source_pixel_format that reduces the color resolution, such as yuv420p, nv12 etc. For Bayer images, use the special hack for single-channel images.

3) The libav encoder encodes the packet with its supported codec, e.g. the libx264 will produce h264 packets. The encoding field of the FFMPEGPacket message will document all image format conversions and the codec, in reverse order, separated by semicolon. This way the decoder can attempt to reproduce the original ros_encoding.

4) The libav decoder decodes the packet into the original av_source_pixel_format.

5) Finally the image is converted to output_message_format using libswscale. This format can be set (in ROS encoding syntax!) with setOutputMessageEncoding(). The format must be supported by both ROS and libswscale (except when using the special hack for single-channel images).

Note that only very few combinations of libav encoders, cv_bridge_target_format and av_source_pixel_format have been tested. Please provide feedback if you observe crashes or find obvious bugs. PRs are always appreciated!

The special single-channel hack

Many libav encoders do not support single-channel formats (like mono8 or bayer). For this reason a special hack is implemented in the encoder that adds an empty (zero-value) color channel to the single-channel image. Later, the decoder removes it again. To utilitze this hack, specify a cv_bridge_target_format of e.g. bayer_rggb8. Without the special hack, this would trigger an error because Bayer formats are not acceptable to libswscale. Instead, the image is converted to yuv420p or nv12 by adding an empty color channel. These formats are acceptable to most encoders. The decoder in turn recognizes that the cv_bridge_target_format is a single-channel format, but yuv420p/nv12 are not, and therefore drops the color channel. This hack greatly improves the efficiency for lossless encoding of Bayer images because it avoids conversion to full RGB and back.

API usage

Encoder

Using the encoder involves the following steps:

  • instantiating the Encoder object.
  • setting properties like the libav encoder to use, the encoding formats, and AV options.
  • initializing the encoder object. This requires knowledge of the image size and therefore

File truncated at 100 lines see the full file

CONTRIBUTING

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that license:

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

Contributors must sign-off each commit by adding a Signed-off-by: ... line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the Developer Certificate of Origin (DCO).

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that [license](http://www.apache.org/licenses/LICENSE-2.0.html): ~~~ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. ~~~ Contributors must sign-off each commit by adding a `Signed-off-by: ...` line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the [Developer Certificate of Origin (DCO)](https://developercertificate.org/).
Repo symbol

ffmpeg_encoder_decoder repository

ffmpeg_encoder_decoder

ROS Distro
kilted

Repository Summary

Checkout URI https://github.com/ros-misc-utilities/ffmpeg_encoder_decoder.git
VCS Type git
VCS Version release
Last Updated 2025-08-08
Dev Status DEVELOPED
Released RELEASED
Tags No category tags.
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Packages

Name Version
ffmpeg_encoder_decoder 3.0.0

README

ROS2 FFMPeg encoder/decoder

This ROS2 package supports encoding/decoding with the FFMpeg library, for example encoding h264 and h265 or HEVC, using Nvidia or other hardware acceleration when available. This package is meant to be used by image transport plugins like the ffmpeg image transport and the foxglove compressed video transport.

Supported systems

Continuous integration is tested under Ubuntu with the following ROS2 distros:

Build Status Build Status Build Status Build Status

Installation

From packages

sudo apt-get install ros-${ROS_DISTRO}-ffmpeg-encoder-decoder

From source

Set the following shell variables:

repo=ffmpeg_encoder_decoder
url=https://github.com/ros-misc-utilities/${repo}.git

and follow the instructions here

Make sure to source your workspace’s install/setup.bash afterwards.

API overview

Preliminaries

When using libav it is important to understand the difference between the encoder and the codec. The codec is the standardized format in which images are encoded, for instance h264 or hevc. The encoder is a libav software module that can encode images for a given codec. For instance libx264, libx264rgb, h264_nvenc, and h264_vaapi` are all encoders that encode for the codec h264. Some of the encoders are hardware accelerated, some can handle more image formats than others, but in the end they all encode video for a specific codec.

For the many AV options available for various libav encoders, and for qmax, bit_rate and similar settings please refer to the ffmpeg documentation.

The inner workings

overview_diagram

The diagram above shows the stations that a ROS Image message passes as it traverses the encoder and decoder. 1) The ROS image (with ROS sensor_msgs/Image encoding) is first converted with the ROS cv_bridge into the cv_bridge_target_format. This conversion is necessary because some ROS encodings (like bayer images) are not supported by libswscale. The cv_bridge_target_format can be set via setCVBridgeTargetFormat(const std::string & fmt). If this format is not set explicitly the image will be converted to the default format of bgr8. This may not be what you want for e.g. mono8 (gray) or Bayer images. Ideally thecv_bridge_target_format can be directly used by the libav decoder so the next step becomes a no-op. But at the very least cv_bridge_target_format must be an acceptable libswscale input format (with the exception of special hacks for encoding single-channel images, see below). 2) The image is then converted to av_source_pixel_format using libswscale. The av_source_pixel_format can be set with setAVSourcePixelFormat(), defaulting to something that is acceptable to the libav encoder. You can use ffmpeg (ffmpeg -h encoder=libx264 | grep formats) to list all formats that an encoder supports. Note that the ffmpeg/libav format string notation is different from the ROS encoding strings, and the av_source_pixel_format is specified using the libav convention, whereas the cv_bridge_target_format uses ROS convention! (If you choose to bypass the cv_bridge conversion from step 1 by feeding the images to the encoder directly via the encodeImage(const cv::Mat & img ...) method, you must still set the cv_bridge_target_format such that the encoder knows what format the img argument has.) When aiming for lossless compression, beware of any av_source_pixel_format that reduces the color resolution, such as yuv420p, nv12 etc. For Bayer images, use the special hack for single-channel images.

3) The libav encoder encodes the packet with its supported codec, e.g. the libx264 will produce h264 packets. The encoding field of the FFMPEGPacket message will document all image format conversions and the codec, in reverse order, separated by semicolon. This way the decoder can attempt to reproduce the original ros_encoding.

4) The libav decoder decodes the packet into the original av_source_pixel_format.

5) Finally the image is converted to output_message_format using libswscale. This format can be set (in ROS encoding syntax!) with setOutputMessageEncoding(). The format must be supported by both ROS and libswscale (except when using the special hack for single-channel images).

Note that only very few combinations of libav encoders, cv_bridge_target_format and av_source_pixel_format have been tested. Please provide feedback if you observe crashes or find obvious bugs. PRs are always appreciated!

The special single-channel hack

Many libav encoders do not support single-channel formats (like mono8 or bayer). For this reason a special hack is implemented in the encoder that adds an empty (zero-value) color channel to the single-channel image. Later, the decoder removes it again. To utilitze this hack, specify a cv_bridge_target_format of e.g. bayer_rggb8. Without the special hack, this would trigger an error because Bayer formats are not acceptable to libswscale. Instead, the image is converted to yuv420p or nv12 by adding an empty color channel. These formats are acceptable to most encoders. The decoder in turn recognizes that the cv_bridge_target_format is a single-channel format, but yuv420p/nv12 are not, and therefore drops the color channel. This hack greatly improves the efficiency for lossless encoding of Bayer images because it avoids conversion to full RGB and back.

API usage

Encoder

Using the encoder involves the following steps:

  • instantiating the Encoder object.
  • setting properties like the libav encoder to use, the encoding formats, and AV options.
  • initializing the encoder object. This requires knowledge of the image size and therefore

File truncated at 100 lines see the full file

CONTRIBUTING

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that license:

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

Contributors must sign-off each commit by adding a Signed-off-by: ... line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the Developer Certificate of Origin (DCO).

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that [license](http://www.apache.org/licenses/LICENSE-2.0.html): ~~~ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. ~~~ Contributors must sign-off each commit by adding a `Signed-off-by: ...` line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the [Developer Certificate of Origin (DCO)](https://developercertificate.org/).
Repo symbol

ffmpeg_encoder_decoder repository

ffmpeg_encoder_decoder

ROS Distro
rolling

Repository Summary

Checkout URI https://github.com/ros-misc-utilities/ffmpeg_encoder_decoder.git
VCS Type git
VCS Version release
Last Updated 2025-08-08
Dev Status DEVELOPED
Released RELEASED
Tags No category tags.
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Packages

Name Version
ffmpeg_encoder_decoder 3.0.0

README

ROS2 FFMPeg encoder/decoder

This ROS2 package supports encoding/decoding with the FFMpeg library, for example encoding h264 and h265 or HEVC, using Nvidia or other hardware acceleration when available. This package is meant to be used by image transport plugins like the ffmpeg image transport and the foxglove compressed video transport.

Supported systems

Continuous integration is tested under Ubuntu with the following ROS2 distros:

Build Status Build Status Build Status Build Status

Installation

From packages

sudo apt-get install ros-${ROS_DISTRO}-ffmpeg-encoder-decoder

From source

Set the following shell variables:

repo=ffmpeg_encoder_decoder
url=https://github.com/ros-misc-utilities/${repo}.git

and follow the instructions here

Make sure to source your workspace’s install/setup.bash afterwards.

API overview

Preliminaries

When using libav it is important to understand the difference between the encoder and the codec. The codec is the standardized format in which images are encoded, for instance h264 or hevc. The encoder is a libav software module that can encode images for a given codec. For instance libx264, libx264rgb, h264_nvenc, and h264_vaapi` are all encoders that encode for the codec h264. Some of the encoders are hardware accelerated, some can handle more image formats than others, but in the end they all encode video for a specific codec.

For the many AV options available for various libav encoders, and for qmax, bit_rate and similar settings please refer to the ffmpeg documentation.

The inner workings

overview_diagram

The diagram above shows the stations that a ROS Image message passes as it traverses the encoder and decoder. 1) The ROS image (with ROS sensor_msgs/Image encoding) is first converted with the ROS cv_bridge into the cv_bridge_target_format. This conversion is necessary because some ROS encodings (like bayer images) are not supported by libswscale. The cv_bridge_target_format can be set via setCVBridgeTargetFormat(const std::string & fmt). If this format is not set explicitly the image will be converted to the default format of bgr8. This may not be what you want for e.g. mono8 (gray) or Bayer images. Ideally thecv_bridge_target_format can be directly used by the libav decoder so the next step becomes a no-op. But at the very least cv_bridge_target_format must be an acceptable libswscale input format (with the exception of special hacks for encoding single-channel images, see below). 2) The image is then converted to av_source_pixel_format using libswscale. The av_source_pixel_format can be set with setAVSourcePixelFormat(), defaulting to something that is acceptable to the libav encoder. You can use ffmpeg (ffmpeg -h encoder=libx264 | grep formats) to list all formats that an encoder supports. Note that the ffmpeg/libav format string notation is different from the ROS encoding strings, and the av_source_pixel_format is specified using the libav convention, whereas the cv_bridge_target_format uses ROS convention! (If you choose to bypass the cv_bridge conversion from step 1 by feeding the images to the encoder directly via the encodeImage(const cv::Mat & img ...) method, you must still set the cv_bridge_target_format such that the encoder knows what format the img argument has.) When aiming for lossless compression, beware of any av_source_pixel_format that reduces the color resolution, such as yuv420p, nv12 etc. For Bayer images, use the special hack for single-channel images.

3) The libav encoder encodes the packet with its supported codec, e.g. the libx264 will produce h264 packets. The encoding field of the FFMPEGPacket message will document all image format conversions and the codec, in reverse order, separated by semicolon. This way the decoder can attempt to reproduce the original ros_encoding.

4) The libav decoder decodes the packet into the original av_source_pixel_format.

5) Finally the image is converted to output_message_format using libswscale. This format can be set (in ROS encoding syntax!) with setOutputMessageEncoding(). The format must be supported by both ROS and libswscale (except when using the special hack for single-channel images).

Note that only very few combinations of libav encoders, cv_bridge_target_format and av_source_pixel_format have been tested. Please provide feedback if you observe crashes or find obvious bugs. PRs are always appreciated!

The special single-channel hack

Many libav encoders do not support single-channel formats (like mono8 or bayer). For this reason a special hack is implemented in the encoder that adds an empty (zero-value) color channel to the single-channel image. Later, the decoder removes it again. To utilitze this hack, specify a cv_bridge_target_format of e.g. bayer_rggb8. Without the special hack, this would trigger an error because Bayer formats are not acceptable to libswscale. Instead, the image is converted to yuv420p or nv12 by adding an empty color channel. These formats are acceptable to most encoders. The decoder in turn recognizes that the cv_bridge_target_format is a single-channel format, but yuv420p/nv12 are not, and therefore drops the color channel. This hack greatly improves the efficiency for lossless encoding of Bayer images because it avoids conversion to full RGB and back.

API usage

Encoder

Using the encoder involves the following steps:

  • instantiating the Encoder object.
  • setting properties like the libav encoder to use, the encoding formats, and AV options.
  • initializing the encoder object. This requires knowledge of the image size and therefore

File truncated at 100 lines see the full file

CONTRIBUTING

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that license:

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

Contributors must sign-off each commit by adding a Signed-off-by: ... line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the Developer Certificate of Origin (DCO).

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that [license](http://www.apache.org/licenses/LICENSE-2.0.html): ~~~ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. ~~~ Contributors must sign-off each commit by adding a `Signed-off-by: ...` line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the [Developer Certificate of Origin (DCO)](https://developercertificate.org/).
No version for distro ardent showing humble. Known supported distros are highlighted in the buttons above.
Repo symbol

ffmpeg_encoder_decoder repository

ffmpeg_encoder_decoder

ROS Distro
humble

Repository Summary

Checkout URI https://github.com/ros-misc-utilities/ffmpeg_encoder_decoder.git
VCS Type git
VCS Version release
Last Updated 2025-08-08
Dev Status DEVELOPED
Released RELEASED
Tags No category tags.
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Packages

Name Version
ffmpeg_encoder_decoder 3.0.0

README

ROS2 FFMPeg encoder/decoder

This ROS2 package supports encoding/decoding with the FFMpeg library, for example encoding h264 and h265 or HEVC, using Nvidia or other hardware acceleration when available. This package is meant to be used by image transport plugins like the ffmpeg image transport and the foxglove compressed video transport.

Supported systems

Continuous integration is tested under Ubuntu with the following ROS2 distros:

Build Status Build Status Build Status Build Status

Installation

From packages

sudo apt-get install ros-${ROS_DISTRO}-ffmpeg-encoder-decoder

From source

Set the following shell variables:

repo=ffmpeg_encoder_decoder
url=https://github.com/ros-misc-utilities/${repo}.git

and follow the instructions here

Make sure to source your workspace’s install/setup.bash afterwards.

API overview

Preliminaries

When using libav it is important to understand the difference between the encoder and the codec. The codec is the standardized format in which images are encoded, for instance h264 or hevc. The encoder is a libav software module that can encode images for a given codec. For instance libx264, libx264rgb, h264_nvenc, and h264_vaapi` are all encoders that encode for the codec h264. Some of the encoders are hardware accelerated, some can handle more image formats than others, but in the end they all encode video for a specific codec.

For the many AV options available for various libav encoders, and for qmax, bit_rate and similar settings please refer to the ffmpeg documentation.

The inner workings

overview_diagram

The diagram above shows the stations that a ROS Image message passes as it traverses the encoder and decoder. 1) The ROS image (with ROS sensor_msgs/Image encoding) is first converted with the ROS cv_bridge into the cv_bridge_target_format. This conversion is necessary because some ROS encodings (like bayer images) are not supported by libswscale. The cv_bridge_target_format can be set via setCVBridgeTargetFormat(const std::string & fmt). If this format is not set explicitly the image will be converted to the default format of bgr8. This may not be what you want for e.g. mono8 (gray) or Bayer images. Ideally thecv_bridge_target_format can be directly used by the libav decoder so the next step becomes a no-op. But at the very least cv_bridge_target_format must be an acceptable libswscale input format (with the exception of special hacks for encoding single-channel images, see below). 2) The image is then converted to av_source_pixel_format using libswscale. The av_source_pixel_format can be set with setAVSourcePixelFormat(), defaulting to something that is acceptable to the libav encoder. You can use ffmpeg (ffmpeg -h encoder=libx264 | grep formats) to list all formats that an encoder supports. Note that the ffmpeg/libav format string notation is different from the ROS encoding strings, and the av_source_pixel_format is specified using the libav convention, whereas the cv_bridge_target_format uses ROS convention! (If you choose to bypass the cv_bridge conversion from step 1 by feeding the images to the encoder directly via the encodeImage(const cv::Mat & img ...) method, you must still set the cv_bridge_target_format such that the encoder knows what format the img argument has.) When aiming for lossless compression, beware of any av_source_pixel_format that reduces the color resolution, such as yuv420p, nv12 etc. For Bayer images, use the special hack for single-channel images.

3) The libav encoder encodes the packet with its supported codec, e.g. the libx264 will produce h264 packets. The encoding field of the FFMPEGPacket message will document all image format conversions and the codec, in reverse order, separated by semicolon. This way the decoder can attempt to reproduce the original ros_encoding.

4) The libav decoder decodes the packet into the original av_source_pixel_format.

5) Finally the image is converted to output_message_format using libswscale. This format can be set (in ROS encoding syntax!) with setOutputMessageEncoding(). The format must be supported by both ROS and libswscale (except when using the special hack for single-channel images).

Note that only very few combinations of libav encoders, cv_bridge_target_format and av_source_pixel_format have been tested. Please provide feedback if you observe crashes or find obvious bugs. PRs are always appreciated!

The special single-channel hack

Many libav encoders do not support single-channel formats (like mono8 or bayer). For this reason a special hack is implemented in the encoder that adds an empty (zero-value) color channel to the single-channel image. Later, the decoder removes it again. To utilitze this hack, specify a cv_bridge_target_format of e.g. bayer_rggb8. Without the special hack, this would trigger an error because Bayer formats are not acceptable to libswscale. Instead, the image is converted to yuv420p or nv12 by adding an empty color channel. These formats are acceptable to most encoders. The decoder in turn recognizes that the cv_bridge_target_format is a single-channel format, but yuv420p/nv12 are not, and therefore drops the color channel. This hack greatly improves the efficiency for lossless encoding of Bayer images because it avoids conversion to full RGB and back.

API usage

Encoder

Using the encoder involves the following steps:

  • instantiating the Encoder object.
  • setting properties like the libav encoder to use, the encoding formats, and AV options.
  • initializing the encoder object. This requires knowledge of the image size and therefore

File truncated at 100 lines see the full file

CONTRIBUTING

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that license:

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

Contributors must sign-off each commit by adding a Signed-off-by: ... line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the Developer Certificate of Origin (DCO).

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that [license](http://www.apache.org/licenses/LICENSE-2.0.html): ~~~ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. ~~~ Contributors must sign-off each commit by adding a `Signed-off-by: ...` line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the [Developer Certificate of Origin (DCO)](https://developercertificate.org/).
No version for distro bouncy showing humble. Known supported distros are highlighted in the buttons above.
Repo symbol

ffmpeg_encoder_decoder repository

ffmpeg_encoder_decoder

ROS Distro
humble

Repository Summary

Checkout URI https://github.com/ros-misc-utilities/ffmpeg_encoder_decoder.git
VCS Type git
VCS Version release
Last Updated 2025-08-08
Dev Status DEVELOPED
Released RELEASED
Tags No category tags.
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Packages

Name Version
ffmpeg_encoder_decoder 3.0.0

README

ROS2 FFMPeg encoder/decoder

This ROS2 package supports encoding/decoding with the FFMpeg library, for example encoding h264 and h265 or HEVC, using Nvidia or other hardware acceleration when available. This package is meant to be used by image transport plugins like the ffmpeg image transport and the foxglove compressed video transport.

Supported systems

Continuous integration is tested under Ubuntu with the following ROS2 distros:

Build Status Build Status Build Status Build Status

Installation

From packages

sudo apt-get install ros-${ROS_DISTRO}-ffmpeg-encoder-decoder

From source

Set the following shell variables:

repo=ffmpeg_encoder_decoder
url=https://github.com/ros-misc-utilities/${repo}.git

and follow the instructions here

Make sure to source your workspace’s install/setup.bash afterwards.

API overview

Preliminaries

When using libav it is important to understand the difference between the encoder and the codec. The codec is the standardized format in which images are encoded, for instance h264 or hevc. The encoder is a libav software module that can encode images for a given codec. For instance libx264, libx264rgb, h264_nvenc, and h264_vaapi` are all encoders that encode for the codec h264. Some of the encoders are hardware accelerated, some can handle more image formats than others, but in the end they all encode video for a specific codec.

For the many AV options available for various libav encoders, and for qmax, bit_rate and similar settings please refer to the ffmpeg documentation.

The inner workings

overview_diagram

The diagram above shows the stations that a ROS Image message passes as it traverses the encoder and decoder. 1) The ROS image (with ROS sensor_msgs/Image encoding) is first converted with the ROS cv_bridge into the cv_bridge_target_format. This conversion is necessary because some ROS encodings (like bayer images) are not supported by libswscale. The cv_bridge_target_format can be set via setCVBridgeTargetFormat(const std::string & fmt). If this format is not set explicitly the image will be converted to the default format of bgr8. This may not be what you want for e.g. mono8 (gray) or Bayer images. Ideally thecv_bridge_target_format can be directly used by the libav decoder so the next step becomes a no-op. But at the very least cv_bridge_target_format must be an acceptable libswscale input format (with the exception of special hacks for encoding single-channel images, see below). 2) The image is then converted to av_source_pixel_format using libswscale. The av_source_pixel_format can be set with setAVSourcePixelFormat(), defaulting to something that is acceptable to the libav encoder. You can use ffmpeg (ffmpeg -h encoder=libx264 | grep formats) to list all formats that an encoder supports. Note that the ffmpeg/libav format string notation is different from the ROS encoding strings, and the av_source_pixel_format is specified using the libav convention, whereas the cv_bridge_target_format uses ROS convention! (If you choose to bypass the cv_bridge conversion from step 1 by feeding the images to the encoder directly via the encodeImage(const cv::Mat & img ...) method, you must still set the cv_bridge_target_format such that the encoder knows what format the img argument has.) When aiming for lossless compression, beware of any av_source_pixel_format that reduces the color resolution, such as yuv420p, nv12 etc. For Bayer images, use the special hack for single-channel images.

3) The libav encoder encodes the packet with its supported codec, e.g. the libx264 will produce h264 packets. The encoding field of the FFMPEGPacket message will document all image format conversions and the codec, in reverse order, separated by semicolon. This way the decoder can attempt to reproduce the original ros_encoding.

4) The libav decoder decodes the packet into the original av_source_pixel_format.

5) Finally the image is converted to output_message_format using libswscale. This format can be set (in ROS encoding syntax!) with setOutputMessageEncoding(). The format must be supported by both ROS and libswscale (except when using the special hack for single-channel images).

Note that only very few combinations of libav encoders, cv_bridge_target_format and av_source_pixel_format have been tested. Please provide feedback if you observe crashes or find obvious bugs. PRs are always appreciated!

The special single-channel hack

Many libav encoders do not support single-channel formats (like mono8 or bayer). For this reason a special hack is implemented in the encoder that adds an empty (zero-value) color channel to the single-channel image. Later, the decoder removes it again. To utilitze this hack, specify a cv_bridge_target_format of e.g. bayer_rggb8. Without the special hack, this would trigger an error because Bayer formats are not acceptable to libswscale. Instead, the image is converted to yuv420p or nv12 by adding an empty color channel. These formats are acceptable to most encoders. The decoder in turn recognizes that the cv_bridge_target_format is a single-channel format, but yuv420p/nv12 are not, and therefore drops the color channel. This hack greatly improves the efficiency for lossless encoding of Bayer images because it avoids conversion to full RGB and back.

API usage

Encoder

Using the encoder involves the following steps:

  • instantiating the Encoder object.
  • setting properties like the libav encoder to use, the encoding formats, and AV options.
  • initializing the encoder object. This requires knowledge of the image size and therefore

File truncated at 100 lines see the full file

CONTRIBUTING

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that license:

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

Contributors must sign-off each commit by adding a Signed-off-by: ... line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the Developer Certificate of Origin (DCO).

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that [license](http://www.apache.org/licenses/LICENSE-2.0.html): ~~~ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. ~~~ Contributors must sign-off each commit by adding a `Signed-off-by: ...` line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the [Developer Certificate of Origin (DCO)](https://developercertificate.org/).
No version for distro crystal showing humble. Known supported distros are highlighted in the buttons above.
Repo symbol

ffmpeg_encoder_decoder repository

ffmpeg_encoder_decoder

ROS Distro
humble

Repository Summary

Checkout URI https://github.com/ros-misc-utilities/ffmpeg_encoder_decoder.git
VCS Type git
VCS Version release
Last Updated 2025-08-08
Dev Status DEVELOPED
Released RELEASED
Tags No category tags.
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Packages

Name Version
ffmpeg_encoder_decoder 3.0.0

README

ROS2 FFMPeg encoder/decoder

This ROS2 package supports encoding/decoding with the FFMpeg library, for example encoding h264 and h265 or HEVC, using Nvidia or other hardware acceleration when available. This package is meant to be used by image transport plugins like the ffmpeg image transport and the foxglove compressed video transport.

Supported systems

Continuous integration is tested under Ubuntu with the following ROS2 distros:

Build Status Build Status Build Status Build Status

Installation

From packages

sudo apt-get install ros-${ROS_DISTRO}-ffmpeg-encoder-decoder

From source

Set the following shell variables:

repo=ffmpeg_encoder_decoder
url=https://github.com/ros-misc-utilities/${repo}.git

and follow the instructions here

Make sure to source your workspace’s install/setup.bash afterwards.

API overview

Preliminaries

When using libav it is important to understand the difference between the encoder and the codec. The codec is the standardized format in which images are encoded, for instance h264 or hevc. The encoder is a libav software module that can encode images for a given codec. For instance libx264, libx264rgb, h264_nvenc, and h264_vaapi` are all encoders that encode for the codec h264. Some of the encoders are hardware accelerated, some can handle more image formats than others, but in the end they all encode video for a specific codec.

For the many AV options available for various libav encoders, and for qmax, bit_rate and similar settings please refer to the ffmpeg documentation.

The inner workings

overview_diagram

The diagram above shows the stations that a ROS Image message passes as it traverses the encoder and decoder. 1) The ROS image (with ROS sensor_msgs/Image encoding) is first converted with the ROS cv_bridge into the cv_bridge_target_format. This conversion is necessary because some ROS encodings (like bayer images) are not supported by libswscale. The cv_bridge_target_format can be set via setCVBridgeTargetFormat(const std::string & fmt). If this format is not set explicitly the image will be converted to the default format of bgr8. This may not be what you want for e.g. mono8 (gray) or Bayer images. Ideally thecv_bridge_target_format can be directly used by the libav decoder so the next step becomes a no-op. But at the very least cv_bridge_target_format must be an acceptable libswscale input format (with the exception of special hacks for encoding single-channel images, see below). 2) The image is then converted to av_source_pixel_format using libswscale. The av_source_pixel_format can be set with setAVSourcePixelFormat(), defaulting to something that is acceptable to the libav encoder. You can use ffmpeg (ffmpeg -h encoder=libx264 | grep formats) to list all formats that an encoder supports. Note that the ffmpeg/libav format string notation is different from the ROS encoding strings, and the av_source_pixel_format is specified using the libav convention, whereas the cv_bridge_target_format uses ROS convention! (If you choose to bypass the cv_bridge conversion from step 1 by feeding the images to the encoder directly via the encodeImage(const cv::Mat & img ...) method, you must still set the cv_bridge_target_format such that the encoder knows what format the img argument has.) When aiming for lossless compression, beware of any av_source_pixel_format that reduces the color resolution, such as yuv420p, nv12 etc. For Bayer images, use the special hack for single-channel images.

3) The libav encoder encodes the packet with its supported codec, e.g. the libx264 will produce h264 packets. The encoding field of the FFMPEGPacket message will document all image format conversions and the codec, in reverse order, separated by semicolon. This way the decoder can attempt to reproduce the original ros_encoding.

4) The libav decoder decodes the packet into the original av_source_pixel_format.

5) Finally the image is converted to output_message_format using libswscale. This format can be set (in ROS encoding syntax!) with setOutputMessageEncoding(). The format must be supported by both ROS and libswscale (except when using the special hack for single-channel images).

Note that only very few combinations of libav encoders, cv_bridge_target_format and av_source_pixel_format have been tested. Please provide feedback if you observe crashes or find obvious bugs. PRs are always appreciated!

The special single-channel hack

Many libav encoders do not support single-channel formats (like mono8 or bayer). For this reason a special hack is implemented in the encoder that adds an empty (zero-value) color channel to the single-channel image. Later, the decoder removes it again. To utilitze this hack, specify a cv_bridge_target_format of e.g. bayer_rggb8. Without the special hack, this would trigger an error because Bayer formats are not acceptable to libswscale. Instead, the image is converted to yuv420p or nv12 by adding an empty color channel. These formats are acceptable to most encoders. The decoder in turn recognizes that the cv_bridge_target_format is a single-channel format, but yuv420p/nv12 are not, and therefore drops the color channel. This hack greatly improves the efficiency for lossless encoding of Bayer images because it avoids conversion to full RGB and back.

API usage

Encoder

Using the encoder involves the following steps:

  • instantiating the Encoder object.
  • setting properties like the libav encoder to use, the encoding formats, and AV options.
  • initializing the encoder object. This requires knowledge of the image size and therefore

File truncated at 100 lines see the full file

CONTRIBUTING

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that license:

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

Contributors must sign-off each commit by adding a Signed-off-by: ... line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the Developer Certificate of Origin (DCO).

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that [license](http://www.apache.org/licenses/LICENSE-2.0.html): ~~~ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. ~~~ Contributors must sign-off each commit by adding a `Signed-off-by: ...` line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the [Developer Certificate of Origin (DCO)](https://developercertificate.org/).
No version for distro eloquent showing humble. Known supported distros are highlighted in the buttons above.
Repo symbol

ffmpeg_encoder_decoder repository

ffmpeg_encoder_decoder

ROS Distro
humble

Repository Summary

Checkout URI https://github.com/ros-misc-utilities/ffmpeg_encoder_decoder.git
VCS Type git
VCS Version release
Last Updated 2025-08-08
Dev Status DEVELOPED
Released RELEASED
Tags No category tags.
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Packages

Name Version
ffmpeg_encoder_decoder 3.0.0

README

ROS2 FFMPeg encoder/decoder

This ROS2 package supports encoding/decoding with the FFMpeg library, for example encoding h264 and h265 or HEVC, using Nvidia or other hardware acceleration when available. This package is meant to be used by image transport plugins like the ffmpeg image transport and the foxglove compressed video transport.

Supported systems

Continuous integration is tested under Ubuntu with the following ROS2 distros:

Build Status Build Status Build Status Build Status

Installation

From packages

sudo apt-get install ros-${ROS_DISTRO}-ffmpeg-encoder-decoder

From source

Set the following shell variables:

repo=ffmpeg_encoder_decoder
url=https://github.com/ros-misc-utilities/${repo}.git

and follow the instructions here

Make sure to source your workspace’s install/setup.bash afterwards.

API overview

Preliminaries

When using libav it is important to understand the difference between the encoder and the codec. The codec is the standardized format in which images are encoded, for instance h264 or hevc. The encoder is a libav software module that can encode images for a given codec. For instance libx264, libx264rgb, h264_nvenc, and h264_vaapi` are all encoders that encode for the codec h264. Some of the encoders are hardware accelerated, some can handle more image formats than others, but in the end they all encode video for a specific codec.

For the many AV options available for various libav encoders, and for qmax, bit_rate and similar settings please refer to the ffmpeg documentation.

The inner workings

overview_diagram

The diagram above shows the stations that a ROS Image message passes as it traverses the encoder and decoder. 1) The ROS image (with ROS sensor_msgs/Image encoding) is first converted with the ROS cv_bridge into the cv_bridge_target_format. This conversion is necessary because some ROS encodings (like bayer images) are not supported by libswscale. The cv_bridge_target_format can be set via setCVBridgeTargetFormat(const std::string & fmt). If this format is not set explicitly the image will be converted to the default format of bgr8. This may not be what you want for e.g. mono8 (gray) or Bayer images. Ideally thecv_bridge_target_format can be directly used by the libav decoder so the next step becomes a no-op. But at the very least cv_bridge_target_format must be an acceptable libswscale input format (with the exception of special hacks for encoding single-channel images, see below). 2) The image is then converted to av_source_pixel_format using libswscale. The av_source_pixel_format can be set with setAVSourcePixelFormat(), defaulting to something that is acceptable to the libav encoder. You can use ffmpeg (ffmpeg -h encoder=libx264 | grep formats) to list all formats that an encoder supports. Note that the ffmpeg/libav format string notation is different from the ROS encoding strings, and the av_source_pixel_format is specified using the libav convention, whereas the cv_bridge_target_format uses ROS convention! (If you choose to bypass the cv_bridge conversion from step 1 by feeding the images to the encoder directly via the encodeImage(const cv::Mat & img ...) method, you must still set the cv_bridge_target_format such that the encoder knows what format the img argument has.) When aiming for lossless compression, beware of any av_source_pixel_format that reduces the color resolution, such as yuv420p, nv12 etc. For Bayer images, use the special hack for single-channel images.

3) The libav encoder encodes the packet with its supported codec, e.g. the libx264 will produce h264 packets. The encoding field of the FFMPEGPacket message will document all image format conversions and the codec, in reverse order, separated by semicolon. This way the decoder can attempt to reproduce the original ros_encoding.

4) The libav decoder decodes the packet into the original av_source_pixel_format.

5) Finally the image is converted to output_message_format using libswscale. This format can be set (in ROS encoding syntax!) with setOutputMessageEncoding(). The format must be supported by both ROS and libswscale (except when using the special hack for single-channel images).

Note that only very few combinations of libav encoders, cv_bridge_target_format and av_source_pixel_format have been tested. Please provide feedback if you observe crashes or find obvious bugs. PRs are always appreciated!

The special single-channel hack

Many libav encoders do not support single-channel formats (like mono8 or bayer). For this reason a special hack is implemented in the encoder that adds an empty (zero-value) color channel to the single-channel image. Later, the decoder removes it again. To utilitze this hack, specify a cv_bridge_target_format of e.g. bayer_rggb8. Without the special hack, this would trigger an error because Bayer formats are not acceptable to libswscale. Instead, the image is converted to yuv420p or nv12 by adding an empty color channel. These formats are acceptable to most encoders. The decoder in turn recognizes that the cv_bridge_target_format is a single-channel format, but yuv420p/nv12 are not, and therefore drops the color channel. This hack greatly improves the efficiency for lossless encoding of Bayer images because it avoids conversion to full RGB and back.

API usage

Encoder

Using the encoder involves the following steps:

  • instantiating the Encoder object.
  • setting properties like the libav encoder to use, the encoding formats, and AV options.
  • initializing the encoder object. This requires knowledge of the image size and therefore

File truncated at 100 lines see the full file

CONTRIBUTING

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that license:

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

Contributors must sign-off each commit by adding a Signed-off-by: ... line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the Developer Certificate of Origin (DCO).

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that [license](http://www.apache.org/licenses/LICENSE-2.0.html): ~~~ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. ~~~ Contributors must sign-off each commit by adding a `Signed-off-by: ...` line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the [Developer Certificate of Origin (DCO)](https://developercertificate.org/).
No version for distro dashing showing humble. Known supported distros are highlighted in the buttons above.
Repo symbol

ffmpeg_encoder_decoder repository

ffmpeg_encoder_decoder

ROS Distro
humble

Repository Summary

Checkout URI https://github.com/ros-misc-utilities/ffmpeg_encoder_decoder.git
VCS Type git
VCS Version release
Last Updated 2025-08-08
Dev Status DEVELOPED
Released RELEASED
Tags No category tags.
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Packages

Name Version
ffmpeg_encoder_decoder 3.0.0

README

ROS2 FFMPeg encoder/decoder

This ROS2 package supports encoding/decoding with the FFMpeg library, for example encoding h264 and h265 or HEVC, using Nvidia or other hardware acceleration when available. This package is meant to be used by image transport plugins like the ffmpeg image transport and the foxglove compressed video transport.

Supported systems

Continuous integration is tested under Ubuntu with the following ROS2 distros:

Build Status Build Status Build Status Build Status

Installation

From packages

sudo apt-get install ros-${ROS_DISTRO}-ffmpeg-encoder-decoder

From source

Set the following shell variables:

repo=ffmpeg_encoder_decoder
url=https://github.com/ros-misc-utilities/${repo}.git

and follow the instructions here

Make sure to source your workspace’s install/setup.bash afterwards.

API overview

Preliminaries

When using libav it is important to understand the difference between the encoder and the codec. The codec is the standardized format in which images are encoded, for instance h264 or hevc. The encoder is a libav software module that can encode images for a given codec. For instance libx264, libx264rgb, h264_nvenc, and h264_vaapi` are all encoders that encode for the codec h264. Some of the encoders are hardware accelerated, some can handle more image formats than others, but in the end they all encode video for a specific codec.

For the many AV options available for various libav encoders, and for qmax, bit_rate and similar settings please refer to the ffmpeg documentation.

The inner workings

overview_diagram

The diagram above shows the stations that a ROS Image message passes as it traverses the encoder and decoder. 1) The ROS image (with ROS sensor_msgs/Image encoding) is first converted with the ROS cv_bridge into the cv_bridge_target_format. This conversion is necessary because some ROS encodings (like bayer images) are not supported by libswscale. The cv_bridge_target_format can be set via setCVBridgeTargetFormat(const std::string & fmt). If this format is not set explicitly the image will be converted to the default format of bgr8. This may not be what you want for e.g. mono8 (gray) or Bayer images. Ideally thecv_bridge_target_format can be directly used by the libav decoder so the next step becomes a no-op. But at the very least cv_bridge_target_format must be an acceptable libswscale input format (with the exception of special hacks for encoding single-channel images, see below). 2) The image is then converted to av_source_pixel_format using libswscale. The av_source_pixel_format can be set with setAVSourcePixelFormat(), defaulting to something that is acceptable to the libav encoder. You can use ffmpeg (ffmpeg -h encoder=libx264 | grep formats) to list all formats that an encoder supports. Note that the ffmpeg/libav format string notation is different from the ROS encoding strings, and the av_source_pixel_format is specified using the libav convention, whereas the cv_bridge_target_format uses ROS convention! (If you choose to bypass the cv_bridge conversion from step 1 by feeding the images to the encoder directly via the encodeImage(const cv::Mat & img ...) method, you must still set the cv_bridge_target_format such that the encoder knows what format the img argument has.) When aiming for lossless compression, beware of any av_source_pixel_format that reduces the color resolution, such as yuv420p, nv12 etc. For Bayer images, use the special hack for single-channel images.

3) The libav encoder encodes the packet with its supported codec, e.g. the libx264 will produce h264 packets. The encoding field of the FFMPEGPacket message will document all image format conversions and the codec, in reverse order, separated by semicolon. This way the decoder can attempt to reproduce the original ros_encoding.

4) The libav decoder decodes the packet into the original av_source_pixel_format.

5) Finally the image is converted to output_message_format using libswscale. This format can be set (in ROS encoding syntax!) with setOutputMessageEncoding(). The format must be supported by both ROS and libswscale (except when using the special hack for single-channel images).

Note that only very few combinations of libav encoders, cv_bridge_target_format and av_source_pixel_format have been tested. Please provide feedback if you observe crashes or find obvious bugs. PRs are always appreciated!

The special single-channel hack

Many libav encoders do not support single-channel formats (like mono8 or bayer). For this reason a special hack is implemented in the encoder that adds an empty (zero-value) color channel to the single-channel image. Later, the decoder removes it again. To utilitze this hack, specify a cv_bridge_target_format of e.g. bayer_rggb8. Without the special hack, this would trigger an error because Bayer formats are not acceptable to libswscale. Instead, the image is converted to yuv420p or nv12 by adding an empty color channel. These formats are acceptable to most encoders. The decoder in turn recognizes that the cv_bridge_target_format is a single-channel format, but yuv420p/nv12 are not, and therefore drops the color channel. This hack greatly improves the efficiency for lossless encoding of Bayer images because it avoids conversion to full RGB and back.

API usage

Encoder

Using the encoder involves the following steps:

  • instantiating the Encoder object.
  • setting properties like the libav encoder to use, the encoding formats, and AV options.
  • initializing the encoder object. This requires knowledge of the image size and therefore

File truncated at 100 lines see the full file

CONTRIBUTING

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that license:

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

Contributors must sign-off each commit by adding a Signed-off-by: ... line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the Developer Certificate of Origin (DCO).

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that [license](http://www.apache.org/licenses/LICENSE-2.0.html): ~~~ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. ~~~ Contributors must sign-off each commit by adding a `Signed-off-by: ...` line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the [Developer Certificate of Origin (DCO)](https://developercertificate.org/).
No version for distro galactic showing humble. Known supported distros are highlighted in the buttons above.
Repo symbol

ffmpeg_encoder_decoder repository

ffmpeg_encoder_decoder

ROS Distro
humble

Repository Summary

Checkout URI https://github.com/ros-misc-utilities/ffmpeg_encoder_decoder.git
VCS Type git
VCS Version release
Last Updated 2025-08-08
Dev Status DEVELOPED
Released RELEASED
Tags No category tags.
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Packages

Name Version
ffmpeg_encoder_decoder 3.0.0

README

ROS2 FFMPeg encoder/decoder

This ROS2 package supports encoding/decoding with the FFMpeg library, for example encoding h264 and h265 or HEVC, using Nvidia or other hardware acceleration when available. This package is meant to be used by image transport plugins like the ffmpeg image transport and the foxglove compressed video transport.

Supported systems

Continuous integration is tested under Ubuntu with the following ROS2 distros:

Build Status Build Status Build Status Build Status

Installation

From packages

sudo apt-get install ros-${ROS_DISTRO}-ffmpeg-encoder-decoder

From source

Set the following shell variables:

repo=ffmpeg_encoder_decoder
url=https://github.com/ros-misc-utilities/${repo}.git

and follow the instructions here

Make sure to source your workspace’s install/setup.bash afterwards.

API overview

Preliminaries

When using libav it is important to understand the difference between the encoder and the codec. The codec is the standardized format in which images are encoded, for instance h264 or hevc. The encoder is a libav software module that can encode images for a given codec. For instance libx264, libx264rgb, h264_nvenc, and h264_vaapi` are all encoders that encode for the codec h264. Some of the encoders are hardware accelerated, some can handle more image formats than others, but in the end they all encode video for a specific codec.

For the many AV options available for various libav encoders, and for qmax, bit_rate and similar settings please refer to the ffmpeg documentation.

The inner workings

overview_diagram

The diagram above shows the stations that a ROS Image message passes as it traverses the encoder and decoder. 1) The ROS image (with ROS sensor_msgs/Image encoding) is first converted with the ROS cv_bridge into the cv_bridge_target_format. This conversion is necessary because some ROS encodings (like bayer images) are not supported by libswscale. The cv_bridge_target_format can be set via setCVBridgeTargetFormat(const std::string & fmt). If this format is not set explicitly the image will be converted to the default format of bgr8. This may not be what you want for e.g. mono8 (gray) or Bayer images. Ideally thecv_bridge_target_format can be directly used by the libav decoder so the next step becomes a no-op. But at the very least cv_bridge_target_format must be an acceptable libswscale input format (with the exception of special hacks for encoding single-channel images, see below). 2) The image is then converted to av_source_pixel_format using libswscale. The av_source_pixel_format can be set with setAVSourcePixelFormat(), defaulting to something that is acceptable to the libav encoder. You can use ffmpeg (ffmpeg -h encoder=libx264 | grep formats) to list all formats that an encoder supports. Note that the ffmpeg/libav format string notation is different from the ROS encoding strings, and the av_source_pixel_format is specified using the libav convention, whereas the cv_bridge_target_format uses ROS convention! (If you choose to bypass the cv_bridge conversion from step 1 by feeding the images to the encoder directly via the encodeImage(const cv::Mat & img ...) method, you must still set the cv_bridge_target_format such that the encoder knows what format the img argument has.) When aiming for lossless compression, beware of any av_source_pixel_format that reduces the color resolution, such as yuv420p, nv12 etc. For Bayer images, use the special hack for single-channel images.

3) The libav encoder encodes the packet with its supported codec, e.g. the libx264 will produce h264 packets. The encoding field of the FFMPEGPacket message will document all image format conversions and the codec, in reverse order, separated by semicolon. This way the decoder can attempt to reproduce the original ros_encoding.

4) The libav decoder decodes the packet into the original av_source_pixel_format.

5) Finally the image is converted to output_message_format using libswscale. This format can be set (in ROS encoding syntax!) with setOutputMessageEncoding(). The format must be supported by both ROS and libswscale (except when using the special hack for single-channel images).

Note that only very few combinations of libav encoders, cv_bridge_target_format and av_source_pixel_format have been tested. Please provide feedback if you observe crashes or find obvious bugs. PRs are always appreciated!

The special single-channel hack

Many libav encoders do not support single-channel formats (like mono8 or bayer). For this reason a special hack is implemented in the encoder that adds an empty (zero-value) color channel to the single-channel image. Later, the decoder removes it again. To utilitze this hack, specify a cv_bridge_target_format of e.g. bayer_rggb8. Without the special hack, this would trigger an error because Bayer formats are not acceptable to libswscale. Instead, the image is converted to yuv420p or nv12 by adding an empty color channel. These formats are acceptable to most encoders. The decoder in turn recognizes that the cv_bridge_target_format is a single-channel format, but yuv420p/nv12 are not, and therefore drops the color channel. This hack greatly improves the efficiency for lossless encoding of Bayer images because it avoids conversion to full RGB and back.

API usage

Encoder

Using the encoder involves the following steps:

  • instantiating the Encoder object.
  • setting properties like the libav encoder to use, the encoding formats, and AV options.
  • initializing the encoder object. This requires knowledge of the image size and therefore

File truncated at 100 lines see the full file

CONTRIBUTING

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that license:

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

Contributors must sign-off each commit by adding a Signed-off-by: ... line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the Developer Certificate of Origin (DCO).

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that [license](http://www.apache.org/licenses/LICENSE-2.0.html): ~~~ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. ~~~ Contributors must sign-off each commit by adding a `Signed-off-by: ...` line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the [Developer Certificate of Origin (DCO)](https://developercertificate.org/).
No version for distro foxy showing humble. Known supported distros are highlighted in the buttons above.
Repo symbol

ffmpeg_encoder_decoder repository

ffmpeg_encoder_decoder

ROS Distro
humble

Repository Summary

Checkout URI https://github.com/ros-misc-utilities/ffmpeg_encoder_decoder.git
VCS Type git
VCS Version release
Last Updated 2025-08-08
Dev Status DEVELOPED
Released RELEASED
Tags No category tags.
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Packages

Name Version
ffmpeg_encoder_decoder 3.0.0

README

ROS2 FFMPeg encoder/decoder

This ROS2 package supports encoding/decoding with the FFMpeg library, for example encoding h264 and h265 or HEVC, using Nvidia or other hardware acceleration when available. This package is meant to be used by image transport plugins like the ffmpeg image transport and the foxglove compressed video transport.

Supported systems

Continuous integration is tested under Ubuntu with the following ROS2 distros:

Build Status Build Status Build Status Build Status

Installation

From packages

sudo apt-get install ros-${ROS_DISTRO}-ffmpeg-encoder-decoder

From source

Set the following shell variables:

repo=ffmpeg_encoder_decoder
url=https://github.com/ros-misc-utilities/${repo}.git

and follow the instructions here

Make sure to source your workspace’s install/setup.bash afterwards.

API overview

Preliminaries

When using libav it is important to understand the difference between the encoder and the codec. The codec is the standardized format in which images are encoded, for instance h264 or hevc. The encoder is a libav software module that can encode images for a given codec. For instance libx264, libx264rgb, h264_nvenc, and h264_vaapi` are all encoders that encode for the codec h264. Some of the encoders are hardware accelerated, some can handle more image formats than others, but in the end they all encode video for a specific codec.

For the many AV options available for various libav encoders, and for qmax, bit_rate and similar settings please refer to the ffmpeg documentation.

The inner workings

overview_diagram

The diagram above shows the stations that a ROS Image message passes as it traverses the encoder and decoder. 1) The ROS image (with ROS sensor_msgs/Image encoding) is first converted with the ROS cv_bridge into the cv_bridge_target_format. This conversion is necessary because some ROS encodings (like bayer images) are not supported by libswscale. The cv_bridge_target_format can be set via setCVBridgeTargetFormat(const std::string & fmt). If this format is not set explicitly the image will be converted to the default format of bgr8. This may not be what you want for e.g. mono8 (gray) or Bayer images. Ideally thecv_bridge_target_format can be directly used by the libav decoder so the next step becomes a no-op. But at the very least cv_bridge_target_format must be an acceptable libswscale input format (with the exception of special hacks for encoding single-channel images, see below). 2) The image is then converted to av_source_pixel_format using libswscale. The av_source_pixel_format can be set with setAVSourcePixelFormat(), defaulting to something that is acceptable to the libav encoder. You can use ffmpeg (ffmpeg -h encoder=libx264 | grep formats) to list all formats that an encoder supports. Note that the ffmpeg/libav format string notation is different from the ROS encoding strings, and the av_source_pixel_format is specified using the libav convention, whereas the cv_bridge_target_format uses ROS convention! (If you choose to bypass the cv_bridge conversion from step 1 by feeding the images to the encoder directly via the encodeImage(const cv::Mat & img ...) method, you must still set the cv_bridge_target_format such that the encoder knows what format the img argument has.) When aiming for lossless compression, beware of any av_source_pixel_format that reduces the color resolution, such as yuv420p, nv12 etc. For Bayer images, use the special hack for single-channel images.

3) The libav encoder encodes the packet with its supported codec, e.g. the libx264 will produce h264 packets. The encoding field of the FFMPEGPacket message will document all image format conversions and the codec, in reverse order, separated by semicolon. This way the decoder can attempt to reproduce the original ros_encoding.

4) The libav decoder decodes the packet into the original av_source_pixel_format.

5) Finally the image is converted to output_message_format using libswscale. This format can be set (in ROS encoding syntax!) with setOutputMessageEncoding(). The format must be supported by both ROS and libswscale (except when using the special hack for single-channel images).

Note that only very few combinations of libav encoders, cv_bridge_target_format and av_source_pixel_format have been tested. Please provide feedback if you observe crashes or find obvious bugs. PRs are always appreciated!

The special single-channel hack

Many libav encoders do not support single-channel formats (like mono8 or bayer). For this reason a special hack is implemented in the encoder that adds an empty (zero-value) color channel to the single-channel image. Later, the decoder removes it again. To utilitze this hack, specify a cv_bridge_target_format of e.g. bayer_rggb8. Without the special hack, this would trigger an error because Bayer formats are not acceptable to libswscale. Instead, the image is converted to yuv420p or nv12 by adding an empty color channel. These formats are acceptable to most encoders. The decoder in turn recognizes that the cv_bridge_target_format is a single-channel format, but yuv420p/nv12 are not, and therefore drops the color channel. This hack greatly improves the efficiency for lossless encoding of Bayer images because it avoids conversion to full RGB and back.

API usage

Encoder

Using the encoder involves the following steps:

  • instantiating the Encoder object.
  • setting properties like the libav encoder to use, the encoding formats, and AV options.
  • initializing the encoder object. This requires knowledge of the image size and therefore

File truncated at 100 lines see the full file

CONTRIBUTING

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that license:

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

Contributors must sign-off each commit by adding a Signed-off-by: ... line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the Developer Certificate of Origin (DCO).

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that [license](http://www.apache.org/licenses/LICENSE-2.0.html): ~~~ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. ~~~ Contributors must sign-off each commit by adding a `Signed-off-by: ...` line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the [Developer Certificate of Origin (DCO)](https://developercertificate.org/).

Repository Summary

Checkout URI https://github.com/ros-misc-utilities/ffmpeg_encoder_decoder.git
VCS Type git
VCS Version release
Last Updated 2025-08-08
Dev Status DEVELOPED
Released RELEASED
Tags No category tags.
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Packages

Name Version
ffmpeg_encoder_decoder 3.0.0

README

ROS2 FFMPeg encoder/decoder

This ROS2 package supports encoding/decoding with the FFMpeg library, for example encoding h264 and h265 or HEVC, using Nvidia or other hardware acceleration when available. This package is meant to be used by image transport plugins like the ffmpeg image transport and the foxglove compressed video transport.

Supported systems

Continuous integration is tested under Ubuntu with the following ROS2 distros:

Build Status Build Status Build Status Build Status

Installation

From packages

sudo apt-get install ros-${ROS_DISTRO}-ffmpeg-encoder-decoder

From source

Set the following shell variables:

repo=ffmpeg_encoder_decoder
url=https://github.com/ros-misc-utilities/${repo}.git

and follow the instructions here

Make sure to source your workspace’s install/setup.bash afterwards.

API overview

Preliminaries

When using libav it is important to understand the difference between the encoder and the codec. The codec is the standardized format in which images are encoded, for instance h264 or hevc. The encoder is a libav software module that can encode images for a given codec. For instance libx264, libx264rgb, h264_nvenc, and h264_vaapi` are all encoders that encode for the codec h264. Some of the encoders are hardware accelerated, some can handle more image formats than others, but in the end they all encode video for a specific codec.

For the many AV options available for various libav encoders, and for qmax, bit_rate and similar settings please refer to the ffmpeg documentation.

The inner workings

overview_diagram

The diagram above shows the stations that a ROS Image message passes as it traverses the encoder and decoder. 1) The ROS image (with ROS sensor_msgs/Image encoding) is first converted with the ROS cv_bridge into the cv_bridge_target_format. This conversion is necessary because some ROS encodings (like bayer images) are not supported by libswscale. The cv_bridge_target_format can be set via setCVBridgeTargetFormat(const std::string & fmt). If this format is not set explicitly the image will be converted to the default format of bgr8. This may not be what you want for e.g. mono8 (gray) or Bayer images. Ideally thecv_bridge_target_format can be directly used by the libav decoder so the next step becomes a no-op. But at the very least cv_bridge_target_format must be an acceptable libswscale input format (with the exception of special hacks for encoding single-channel images, see below). 2) The image is then converted to av_source_pixel_format using libswscale. The av_source_pixel_format can be set with setAVSourcePixelFormat(), defaulting to something that is acceptable to the libav encoder. You can use ffmpeg (ffmpeg -h encoder=libx264 | grep formats) to list all formats that an encoder supports. Note that the ffmpeg/libav format string notation is different from the ROS encoding strings, and the av_source_pixel_format is specified using the libav convention, whereas the cv_bridge_target_format uses ROS convention! (If you choose to bypass the cv_bridge conversion from step 1 by feeding the images to the encoder directly via the encodeImage(const cv::Mat & img ...) method, you must still set the cv_bridge_target_format such that the encoder knows what format the img argument has.) When aiming for lossless compression, beware of any av_source_pixel_format that reduces the color resolution, such as yuv420p, nv12 etc. For Bayer images, use the special hack for single-channel images.

3) The libav encoder encodes the packet with its supported codec, e.g. the libx264 will produce h264 packets. The encoding field of the FFMPEGPacket message will document all image format conversions and the codec, in reverse order, separated by semicolon. This way the decoder can attempt to reproduce the original ros_encoding.

4) The libav decoder decodes the packet into the original av_source_pixel_format.

5) Finally the image is converted to output_message_format using libswscale. This format can be set (in ROS encoding syntax!) with setOutputMessageEncoding(). The format must be supported by both ROS and libswscale (except when using the special hack for single-channel images).

Note that only very few combinations of libav encoders, cv_bridge_target_format and av_source_pixel_format have been tested. Please provide feedback if you observe crashes or find obvious bugs. PRs are always appreciated!

The special single-channel hack

Many libav encoders do not support single-channel formats (like mono8 or bayer). For this reason a special hack is implemented in the encoder that adds an empty (zero-value) color channel to the single-channel image. Later, the decoder removes it again. To utilitze this hack, specify a cv_bridge_target_format of e.g. bayer_rggb8. Without the special hack, this would trigger an error because Bayer formats are not acceptable to libswscale. Instead, the image is converted to yuv420p or nv12 by adding an empty color channel. These formats are acceptable to most encoders. The decoder in turn recognizes that the cv_bridge_target_format is a single-channel format, but yuv420p/nv12 are not, and therefore drops the color channel. This hack greatly improves the efficiency for lossless encoding of Bayer images because it avoids conversion to full RGB and back.

API usage

Encoder

Using the encoder involves the following steps:

  • instantiating the Encoder object.
  • setting properties like the libav encoder to use, the encoding formats, and AV options.
  • initializing the encoder object. This requires knowledge of the image size and therefore

File truncated at 100 lines see the full file

CONTRIBUTING

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that license:

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

Contributors must sign-off each commit by adding a Signed-off-by: ... line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the Developer Certificate of Origin (DCO).

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that [license](http://www.apache.org/licenses/LICENSE-2.0.html): ~~~ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. ~~~ Contributors must sign-off each commit by adding a `Signed-off-by: ...` line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the [Developer Certificate of Origin (DCO)](https://developercertificate.org/).
No version for distro lunar showing humble. Known supported distros are highlighted in the buttons above.
Repo symbol

ffmpeg_encoder_decoder repository

ffmpeg_encoder_decoder

ROS Distro
humble

Repository Summary

Checkout URI https://github.com/ros-misc-utilities/ffmpeg_encoder_decoder.git
VCS Type git
VCS Version release
Last Updated 2025-08-08
Dev Status DEVELOPED
Released RELEASED
Tags No category tags.
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Packages

Name Version
ffmpeg_encoder_decoder 3.0.0

README

ROS2 FFMPeg encoder/decoder

This ROS2 package supports encoding/decoding with the FFMpeg library, for example encoding h264 and h265 or HEVC, using Nvidia or other hardware acceleration when available. This package is meant to be used by image transport plugins like the ffmpeg image transport and the foxglove compressed video transport.

Supported systems

Continuous integration is tested under Ubuntu with the following ROS2 distros:

Build Status Build Status Build Status Build Status

Installation

From packages

sudo apt-get install ros-${ROS_DISTRO}-ffmpeg-encoder-decoder

From source

Set the following shell variables:

repo=ffmpeg_encoder_decoder
url=https://github.com/ros-misc-utilities/${repo}.git

and follow the instructions here

Make sure to source your workspace’s install/setup.bash afterwards.

API overview

Preliminaries

When using libav it is important to understand the difference between the encoder and the codec. The codec is the standardized format in which images are encoded, for instance h264 or hevc. The encoder is a libav software module that can encode images for a given codec. For instance libx264, libx264rgb, h264_nvenc, and h264_vaapi` are all encoders that encode for the codec h264. Some of the encoders are hardware accelerated, some can handle more image formats than others, but in the end they all encode video for a specific codec.

For the many AV options available for various libav encoders, and for qmax, bit_rate and similar settings please refer to the ffmpeg documentation.

The inner workings

overview_diagram

The diagram above shows the stations that a ROS Image message passes as it traverses the encoder and decoder. 1) The ROS image (with ROS sensor_msgs/Image encoding) is first converted with the ROS cv_bridge into the cv_bridge_target_format. This conversion is necessary because some ROS encodings (like bayer images) are not supported by libswscale. The cv_bridge_target_format can be set via setCVBridgeTargetFormat(const std::string & fmt). If this format is not set explicitly the image will be converted to the default format of bgr8. This may not be what you want for e.g. mono8 (gray) or Bayer images. Ideally thecv_bridge_target_format can be directly used by the libav decoder so the next step becomes a no-op. But at the very least cv_bridge_target_format must be an acceptable libswscale input format (with the exception of special hacks for encoding single-channel images, see below). 2) The image is then converted to av_source_pixel_format using libswscale. The av_source_pixel_format can be set with setAVSourcePixelFormat(), defaulting to something that is acceptable to the libav encoder. You can use ffmpeg (ffmpeg -h encoder=libx264 | grep formats) to list all formats that an encoder supports. Note that the ffmpeg/libav format string notation is different from the ROS encoding strings, and the av_source_pixel_format is specified using the libav convention, whereas the cv_bridge_target_format uses ROS convention! (If you choose to bypass the cv_bridge conversion from step 1 by feeding the images to the encoder directly via the encodeImage(const cv::Mat & img ...) method, you must still set the cv_bridge_target_format such that the encoder knows what format the img argument has.) When aiming for lossless compression, beware of any av_source_pixel_format that reduces the color resolution, such as yuv420p, nv12 etc. For Bayer images, use the special hack for single-channel images.

3) The libav encoder encodes the packet with its supported codec, e.g. the libx264 will produce h264 packets. The encoding field of the FFMPEGPacket message will document all image format conversions and the codec, in reverse order, separated by semicolon. This way the decoder can attempt to reproduce the original ros_encoding.

4) The libav decoder decodes the packet into the original av_source_pixel_format.

5) Finally the image is converted to output_message_format using libswscale. This format can be set (in ROS encoding syntax!) with setOutputMessageEncoding(). The format must be supported by both ROS and libswscale (except when using the special hack for single-channel images).

Note that only very few combinations of libav encoders, cv_bridge_target_format and av_source_pixel_format have been tested. Please provide feedback if you observe crashes or find obvious bugs. PRs are always appreciated!

The special single-channel hack

Many libav encoders do not support single-channel formats (like mono8 or bayer). For this reason a special hack is implemented in the encoder that adds an empty (zero-value) color channel to the single-channel image. Later, the decoder removes it again. To utilitze this hack, specify a cv_bridge_target_format of e.g. bayer_rggb8. Without the special hack, this would trigger an error because Bayer formats are not acceptable to libswscale. Instead, the image is converted to yuv420p or nv12 by adding an empty color channel. These formats are acceptable to most encoders. The decoder in turn recognizes that the cv_bridge_target_format is a single-channel format, but yuv420p/nv12 are not, and therefore drops the color channel. This hack greatly improves the efficiency for lossless encoding of Bayer images because it avoids conversion to full RGB and back.

API usage

Encoder

Using the encoder involves the following steps:

  • instantiating the Encoder object.
  • setting properties like the libav encoder to use, the encoding formats, and AV options.
  • initializing the encoder object. This requires knowledge of the image size and therefore

File truncated at 100 lines see the full file

CONTRIBUTING

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that license:

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

Contributors must sign-off each commit by adding a Signed-off-by: ... line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the Developer Certificate of Origin (DCO).

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that [license](http://www.apache.org/licenses/LICENSE-2.0.html): ~~~ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. ~~~ Contributors must sign-off each commit by adding a `Signed-off-by: ...` line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the [Developer Certificate of Origin (DCO)](https://developercertificate.org/).
No version for distro jade showing humble. Known supported distros are highlighted in the buttons above.
Repo symbol

ffmpeg_encoder_decoder repository

ffmpeg_encoder_decoder

ROS Distro
humble

Repository Summary

Checkout URI https://github.com/ros-misc-utilities/ffmpeg_encoder_decoder.git
VCS Type git
VCS Version release
Last Updated 2025-08-08
Dev Status DEVELOPED
Released RELEASED
Tags No category tags.
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Packages

Name Version
ffmpeg_encoder_decoder 3.0.0

README

ROS2 FFMPeg encoder/decoder

This ROS2 package supports encoding/decoding with the FFMpeg library, for example encoding h264 and h265 or HEVC, using Nvidia or other hardware acceleration when available. This package is meant to be used by image transport plugins like the ffmpeg image transport and the foxglove compressed video transport.

Supported systems

Continuous integration is tested under Ubuntu with the following ROS2 distros:

Build Status Build Status Build Status Build Status

Installation

From packages

sudo apt-get install ros-${ROS_DISTRO}-ffmpeg-encoder-decoder

From source

Set the following shell variables:

repo=ffmpeg_encoder_decoder
url=https://github.com/ros-misc-utilities/${repo}.git

and follow the instructions here

Make sure to source your workspace’s install/setup.bash afterwards.

API overview

Preliminaries

When using libav it is important to understand the difference between the encoder and the codec. The codec is the standardized format in which images are encoded, for instance h264 or hevc. The encoder is a libav software module that can encode images for a given codec. For instance libx264, libx264rgb, h264_nvenc, and h264_vaapi` are all encoders that encode for the codec h264. Some of the encoders are hardware accelerated, some can handle more image formats than others, but in the end they all encode video for a specific codec.

For the many AV options available for various libav encoders, and for qmax, bit_rate and similar settings please refer to the ffmpeg documentation.

The inner workings

overview_diagram

The diagram above shows the stations that a ROS Image message passes as it traverses the encoder and decoder. 1) The ROS image (with ROS sensor_msgs/Image encoding) is first converted with the ROS cv_bridge into the cv_bridge_target_format. This conversion is necessary because some ROS encodings (like bayer images) are not supported by libswscale. The cv_bridge_target_format can be set via setCVBridgeTargetFormat(const std::string & fmt). If this format is not set explicitly the image will be converted to the default format of bgr8. This may not be what you want for e.g. mono8 (gray) or Bayer images. Ideally thecv_bridge_target_format can be directly used by the libav decoder so the next step becomes a no-op. But at the very least cv_bridge_target_format must be an acceptable libswscale input format (with the exception of special hacks for encoding single-channel images, see below). 2) The image is then converted to av_source_pixel_format using libswscale. The av_source_pixel_format can be set with setAVSourcePixelFormat(), defaulting to something that is acceptable to the libav encoder. You can use ffmpeg (ffmpeg -h encoder=libx264 | grep formats) to list all formats that an encoder supports. Note that the ffmpeg/libav format string notation is different from the ROS encoding strings, and the av_source_pixel_format is specified using the libav convention, whereas the cv_bridge_target_format uses ROS convention! (If you choose to bypass the cv_bridge conversion from step 1 by feeding the images to the encoder directly via the encodeImage(const cv::Mat & img ...) method, you must still set the cv_bridge_target_format such that the encoder knows what format the img argument has.) When aiming for lossless compression, beware of any av_source_pixel_format that reduces the color resolution, such as yuv420p, nv12 etc. For Bayer images, use the special hack for single-channel images.

3) The libav encoder encodes the packet with its supported codec, e.g. the libx264 will produce h264 packets. The encoding field of the FFMPEGPacket message will document all image format conversions and the codec, in reverse order, separated by semicolon. This way the decoder can attempt to reproduce the original ros_encoding.

4) The libav decoder decodes the packet into the original av_source_pixel_format.

5) Finally the image is converted to output_message_format using libswscale. This format can be set (in ROS encoding syntax!) with setOutputMessageEncoding(). The format must be supported by both ROS and libswscale (except when using the special hack for single-channel images).

Note that only very few combinations of libav encoders, cv_bridge_target_format and av_source_pixel_format have been tested. Please provide feedback if you observe crashes or find obvious bugs. PRs are always appreciated!

The special single-channel hack

Many libav encoders do not support single-channel formats (like mono8 or bayer). For this reason a special hack is implemented in the encoder that adds an empty (zero-value) color channel to the single-channel image. Later, the decoder removes it again. To utilitze this hack, specify a cv_bridge_target_format of e.g. bayer_rggb8. Without the special hack, this would trigger an error because Bayer formats are not acceptable to libswscale. Instead, the image is converted to yuv420p or nv12 by adding an empty color channel. These formats are acceptable to most encoders. The decoder in turn recognizes that the cv_bridge_target_format is a single-channel format, but yuv420p/nv12 are not, and therefore drops the color channel. This hack greatly improves the efficiency for lossless encoding of Bayer images because it avoids conversion to full RGB and back.

API usage

Encoder

Using the encoder involves the following steps:

  • instantiating the Encoder object.
  • setting properties like the libav encoder to use, the encoding formats, and AV options.
  • initializing the encoder object. This requires knowledge of the image size and therefore

File truncated at 100 lines see the full file

CONTRIBUTING

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that license:

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

Contributors must sign-off each commit by adding a Signed-off-by: ... line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the Developer Certificate of Origin (DCO).

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that [license](http://www.apache.org/licenses/LICENSE-2.0.html): ~~~ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. ~~~ Contributors must sign-off each commit by adding a `Signed-off-by: ...` line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the [Developer Certificate of Origin (DCO)](https://developercertificate.org/).
No version for distro indigo showing humble. Known supported distros are highlighted in the buttons above.
Repo symbol

ffmpeg_encoder_decoder repository

ffmpeg_encoder_decoder

ROS Distro
humble

Repository Summary

Checkout URI https://github.com/ros-misc-utilities/ffmpeg_encoder_decoder.git
VCS Type git
VCS Version release
Last Updated 2025-08-08
Dev Status DEVELOPED
Released RELEASED
Tags No category tags.
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Packages

Name Version
ffmpeg_encoder_decoder 3.0.0

README

ROS2 FFMPeg encoder/decoder

This ROS2 package supports encoding/decoding with the FFMpeg library, for example encoding h264 and h265 or HEVC, using Nvidia or other hardware acceleration when available. This package is meant to be used by image transport plugins like the ffmpeg image transport and the foxglove compressed video transport.

Supported systems

Continuous integration is tested under Ubuntu with the following ROS2 distros:

Build Status Build Status Build Status Build Status

Installation

From packages

sudo apt-get install ros-${ROS_DISTRO}-ffmpeg-encoder-decoder

From source

Set the following shell variables:

repo=ffmpeg_encoder_decoder
url=https://github.com/ros-misc-utilities/${repo}.git

and follow the instructions here

Make sure to source your workspace’s install/setup.bash afterwards.

API overview

Preliminaries

When using libav it is important to understand the difference between the encoder and the codec. The codec is the standardized format in which images are encoded, for instance h264 or hevc. The encoder is a libav software module that can encode images for a given codec. For instance libx264, libx264rgb, h264_nvenc, and h264_vaapi` are all encoders that encode for the codec h264. Some of the encoders are hardware accelerated, some can handle more image formats than others, but in the end they all encode video for a specific codec.

For the many AV options available for various libav encoders, and for qmax, bit_rate and similar settings please refer to the ffmpeg documentation.

The inner workings

overview_diagram

The diagram above shows the stations that a ROS Image message passes as it traverses the encoder and decoder. 1) The ROS image (with ROS sensor_msgs/Image encoding) is first converted with the ROS cv_bridge into the cv_bridge_target_format. This conversion is necessary because some ROS encodings (like bayer images) are not supported by libswscale. The cv_bridge_target_format can be set via setCVBridgeTargetFormat(const std::string & fmt). If this format is not set explicitly the image will be converted to the default format of bgr8. This may not be what you want for e.g. mono8 (gray) or Bayer images. Ideally thecv_bridge_target_format can be directly used by the libav decoder so the next step becomes a no-op. But at the very least cv_bridge_target_format must be an acceptable libswscale input format (with the exception of special hacks for encoding single-channel images, see below). 2) The image is then converted to av_source_pixel_format using libswscale. The av_source_pixel_format can be set with setAVSourcePixelFormat(), defaulting to something that is acceptable to the libav encoder. You can use ffmpeg (ffmpeg -h encoder=libx264 | grep formats) to list all formats that an encoder supports. Note that the ffmpeg/libav format string notation is different from the ROS encoding strings, and the av_source_pixel_format is specified using the libav convention, whereas the cv_bridge_target_format uses ROS convention! (If you choose to bypass the cv_bridge conversion from step 1 by feeding the images to the encoder directly via the encodeImage(const cv::Mat & img ...) method, you must still set the cv_bridge_target_format such that the encoder knows what format the img argument has.) When aiming for lossless compression, beware of any av_source_pixel_format that reduces the color resolution, such as yuv420p, nv12 etc. For Bayer images, use the special hack for single-channel images.

3) The libav encoder encodes the packet with its supported codec, e.g. the libx264 will produce h264 packets. The encoding field of the FFMPEGPacket message will document all image format conversions and the codec, in reverse order, separated by semicolon. This way the decoder can attempt to reproduce the original ros_encoding.

4) The libav decoder decodes the packet into the original av_source_pixel_format.

5) Finally the image is converted to output_message_format using libswscale. This format can be set (in ROS encoding syntax!) with setOutputMessageEncoding(). The format must be supported by both ROS and libswscale (except when using the special hack for single-channel images).

Note that only very few combinations of libav encoders, cv_bridge_target_format and av_source_pixel_format have been tested. Please provide feedback if you observe crashes or find obvious bugs. PRs are always appreciated!

The special single-channel hack

Many libav encoders do not support single-channel formats (like mono8 or bayer). For this reason a special hack is implemented in the encoder that adds an empty (zero-value) color channel to the single-channel image. Later, the decoder removes it again. To utilitze this hack, specify a cv_bridge_target_format of e.g. bayer_rggb8. Without the special hack, this would trigger an error because Bayer formats are not acceptable to libswscale. Instead, the image is converted to yuv420p or nv12 by adding an empty color channel. These formats are acceptable to most encoders. The decoder in turn recognizes that the cv_bridge_target_format is a single-channel format, but yuv420p/nv12 are not, and therefore drops the color channel. This hack greatly improves the efficiency for lossless encoding of Bayer images because it avoids conversion to full RGB and back.

API usage

Encoder

Using the encoder involves the following steps:

  • instantiating the Encoder object.
  • setting properties like the libav encoder to use, the encoding formats, and AV options.
  • initializing the encoder object. This requires knowledge of the image size and therefore

File truncated at 100 lines see the full file

CONTRIBUTING

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that license:

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

Contributors must sign-off each commit by adding a Signed-off-by: ... line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the Developer Certificate of Origin (DCO).

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that [license](http://www.apache.org/licenses/LICENSE-2.0.html): ~~~ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. ~~~ Contributors must sign-off each commit by adding a `Signed-off-by: ...` line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the [Developer Certificate of Origin (DCO)](https://developercertificate.org/).
No version for distro hydro showing humble. Known supported distros are highlighted in the buttons above.
Repo symbol

ffmpeg_encoder_decoder repository

ffmpeg_encoder_decoder

ROS Distro
humble

Repository Summary

Checkout URI https://github.com/ros-misc-utilities/ffmpeg_encoder_decoder.git
VCS Type git
VCS Version release
Last Updated 2025-08-08
Dev Status DEVELOPED
Released RELEASED
Tags No category tags.
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Packages

Name Version
ffmpeg_encoder_decoder 3.0.0

README

ROS2 FFMPeg encoder/decoder

This ROS2 package supports encoding/decoding with the FFMpeg library, for example encoding h264 and h265 or HEVC, using Nvidia or other hardware acceleration when available. This package is meant to be used by image transport plugins like the ffmpeg image transport and the foxglove compressed video transport.

Supported systems

Continuous integration is tested under Ubuntu with the following ROS2 distros:

Build Status Build Status Build Status Build Status

Installation

From packages

sudo apt-get install ros-${ROS_DISTRO}-ffmpeg-encoder-decoder

From source

Set the following shell variables:

repo=ffmpeg_encoder_decoder
url=https://github.com/ros-misc-utilities/${repo}.git

and follow the instructions here

Make sure to source your workspace’s install/setup.bash afterwards.

API overview

Preliminaries

When using libav it is important to understand the difference between the encoder and the codec. The codec is the standardized format in which images are encoded, for instance h264 or hevc. The encoder is a libav software module that can encode images for a given codec. For instance libx264, libx264rgb, h264_nvenc, and h264_vaapi` are all encoders that encode for the codec h264. Some of the encoders are hardware accelerated, some can handle more image formats than others, but in the end they all encode video for a specific codec.

For the many AV options available for various libav encoders, and for qmax, bit_rate and similar settings please refer to the ffmpeg documentation.

The inner workings

overview_diagram

The diagram above shows the stations that a ROS Image message passes as it traverses the encoder and decoder. 1) The ROS image (with ROS sensor_msgs/Image encoding) is first converted with the ROS cv_bridge into the cv_bridge_target_format. This conversion is necessary because some ROS encodings (like bayer images) are not supported by libswscale. The cv_bridge_target_format can be set via setCVBridgeTargetFormat(const std::string & fmt). If this format is not set explicitly the image will be converted to the default format of bgr8. This may not be what you want for e.g. mono8 (gray) or Bayer images. Ideally thecv_bridge_target_format can be directly used by the libav decoder so the next step becomes a no-op. But at the very least cv_bridge_target_format must be an acceptable libswscale input format (with the exception of special hacks for encoding single-channel images, see below). 2) The image is then converted to av_source_pixel_format using libswscale. The av_source_pixel_format can be set with setAVSourcePixelFormat(), defaulting to something that is acceptable to the libav encoder. You can use ffmpeg (ffmpeg -h encoder=libx264 | grep formats) to list all formats that an encoder supports. Note that the ffmpeg/libav format string notation is different from the ROS encoding strings, and the av_source_pixel_format is specified using the libav convention, whereas the cv_bridge_target_format uses ROS convention! (If you choose to bypass the cv_bridge conversion from step 1 by feeding the images to the encoder directly via the encodeImage(const cv::Mat & img ...) method, you must still set the cv_bridge_target_format such that the encoder knows what format the img argument has.) When aiming for lossless compression, beware of any av_source_pixel_format that reduces the color resolution, such as yuv420p, nv12 etc. For Bayer images, use the special hack for single-channel images.

3) The libav encoder encodes the packet with its supported codec, e.g. the libx264 will produce h264 packets. The encoding field of the FFMPEGPacket message will document all image format conversions and the codec, in reverse order, separated by semicolon. This way the decoder can attempt to reproduce the original ros_encoding.

4) The libav decoder decodes the packet into the original av_source_pixel_format.

5) Finally the image is converted to output_message_format using libswscale. This format can be set (in ROS encoding syntax!) with setOutputMessageEncoding(). The format must be supported by both ROS and libswscale (except when using the special hack for single-channel images).

Note that only very few combinations of libav encoders, cv_bridge_target_format and av_source_pixel_format have been tested. Please provide feedback if you observe crashes or find obvious bugs. PRs are always appreciated!

The special single-channel hack

Many libav encoders do not support single-channel formats (like mono8 or bayer). For this reason a special hack is implemented in the encoder that adds an empty (zero-value) color channel to the single-channel image. Later, the decoder removes it again. To utilitze this hack, specify a cv_bridge_target_format of e.g. bayer_rggb8. Without the special hack, this would trigger an error because Bayer formats are not acceptable to libswscale. Instead, the image is converted to yuv420p or nv12 by adding an empty color channel. These formats are acceptable to most encoders. The decoder in turn recognizes that the cv_bridge_target_format is a single-channel format, but yuv420p/nv12 are not, and therefore drops the color channel. This hack greatly improves the efficiency for lossless encoding of Bayer images because it avoids conversion to full RGB and back.

API usage

Encoder

Using the encoder involves the following steps:

  • instantiating the Encoder object.
  • setting properties like the libav encoder to use, the encoding formats, and AV options.
  • initializing the encoder object. This requires knowledge of the image size and therefore

File truncated at 100 lines see the full file

CONTRIBUTING

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that license:

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

Contributors must sign-off each commit by adding a Signed-off-by: ... line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the Developer Certificate of Origin (DCO).

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that [license](http://www.apache.org/licenses/LICENSE-2.0.html): ~~~ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. ~~~ Contributors must sign-off each commit by adding a `Signed-off-by: ...` line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the [Developer Certificate of Origin (DCO)](https://developercertificate.org/).
No version for distro kinetic showing humble. Known supported distros are highlighted in the buttons above.
Repo symbol

ffmpeg_encoder_decoder repository

ffmpeg_encoder_decoder

ROS Distro
humble

Repository Summary

Checkout URI https://github.com/ros-misc-utilities/ffmpeg_encoder_decoder.git
VCS Type git
VCS Version release
Last Updated 2025-08-08
Dev Status DEVELOPED
Released RELEASED
Tags No category tags.
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Packages

Name Version
ffmpeg_encoder_decoder 3.0.0

README

ROS2 FFMPeg encoder/decoder

This ROS2 package supports encoding/decoding with the FFMpeg library, for example encoding h264 and h265 or HEVC, using Nvidia or other hardware acceleration when available. This package is meant to be used by image transport plugins like the ffmpeg image transport and the foxglove compressed video transport.

Supported systems

Continuous integration is tested under Ubuntu with the following ROS2 distros:

Build Status Build Status Build Status Build Status

Installation

From packages

sudo apt-get install ros-${ROS_DISTRO}-ffmpeg-encoder-decoder

From source

Set the following shell variables:

repo=ffmpeg_encoder_decoder
url=https://github.com/ros-misc-utilities/${repo}.git

and follow the instructions here

Make sure to source your workspace’s install/setup.bash afterwards.

API overview

Preliminaries

When using libav it is important to understand the difference between the encoder and the codec. The codec is the standardized format in which images are encoded, for instance h264 or hevc. The encoder is a libav software module that can encode images for a given codec. For instance libx264, libx264rgb, h264_nvenc, and h264_vaapi` are all encoders that encode for the codec h264. Some of the encoders are hardware accelerated, some can handle more image formats than others, but in the end they all encode video for a specific codec.

For the many AV options available for various libav encoders, and for qmax, bit_rate and similar settings please refer to the ffmpeg documentation.

The inner workings

overview_diagram

The diagram above shows the stations that a ROS Image message passes as it traverses the encoder and decoder. 1) The ROS image (with ROS sensor_msgs/Image encoding) is first converted with the ROS cv_bridge into the cv_bridge_target_format. This conversion is necessary because some ROS encodings (like bayer images) are not supported by libswscale. The cv_bridge_target_format can be set via setCVBridgeTargetFormat(const std::string & fmt). If this format is not set explicitly the image will be converted to the default format of bgr8. This may not be what you want for e.g. mono8 (gray) or Bayer images. Ideally thecv_bridge_target_format can be directly used by the libav decoder so the next step becomes a no-op. But at the very least cv_bridge_target_format must be an acceptable libswscale input format (with the exception of special hacks for encoding single-channel images, see below). 2) The image is then converted to av_source_pixel_format using libswscale. The av_source_pixel_format can be set with setAVSourcePixelFormat(), defaulting to something that is acceptable to the libav encoder. You can use ffmpeg (ffmpeg -h encoder=libx264 | grep formats) to list all formats that an encoder supports. Note that the ffmpeg/libav format string notation is different from the ROS encoding strings, and the av_source_pixel_format is specified using the libav convention, whereas the cv_bridge_target_format uses ROS convention! (If you choose to bypass the cv_bridge conversion from step 1 by feeding the images to the encoder directly via the encodeImage(const cv::Mat & img ...) method, you must still set the cv_bridge_target_format such that the encoder knows what format the img argument has.) When aiming for lossless compression, beware of any av_source_pixel_format that reduces the color resolution, such as yuv420p, nv12 etc. For Bayer images, use the special hack for single-channel images.

3) The libav encoder encodes the packet with its supported codec, e.g. the libx264 will produce h264 packets. The encoding field of the FFMPEGPacket message will document all image format conversions and the codec, in reverse order, separated by semicolon. This way the decoder can attempt to reproduce the original ros_encoding.

4) The libav decoder decodes the packet into the original av_source_pixel_format.

5) Finally the image is converted to output_message_format using libswscale. This format can be set (in ROS encoding syntax!) with setOutputMessageEncoding(). The format must be supported by both ROS and libswscale (except when using the special hack for single-channel images).

Note that only very few combinations of libav encoders, cv_bridge_target_format and av_source_pixel_format have been tested. Please provide feedback if you observe crashes or find obvious bugs. PRs are always appreciated!

The special single-channel hack

Many libav encoders do not support single-channel formats (like mono8 or bayer). For this reason a special hack is implemented in the encoder that adds an empty (zero-value) color channel to the single-channel image. Later, the decoder removes it again. To utilitze this hack, specify a cv_bridge_target_format of e.g. bayer_rggb8. Without the special hack, this would trigger an error because Bayer formats are not acceptable to libswscale. Instead, the image is converted to yuv420p or nv12 by adding an empty color channel. These formats are acceptable to most encoders. The decoder in turn recognizes that the cv_bridge_target_format is a single-channel format, but yuv420p/nv12 are not, and therefore drops the color channel. This hack greatly improves the efficiency for lossless encoding of Bayer images because it avoids conversion to full RGB and back.

API usage

Encoder

Using the encoder involves the following steps:

  • instantiating the Encoder object.
  • setting properties like the libav encoder to use, the encoding formats, and AV options.
  • initializing the encoder object. This requires knowledge of the image size and therefore

File truncated at 100 lines see the full file

CONTRIBUTING

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that license:

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

Contributors must sign-off each commit by adding a Signed-off-by: ... line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the Developer Certificate of Origin (DCO).

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that [license](http://www.apache.org/licenses/LICENSE-2.0.html): ~~~ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. ~~~ Contributors must sign-off each commit by adding a `Signed-off-by: ...` line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the [Developer Certificate of Origin (DCO)](https://developercertificate.org/).
No version for distro melodic showing humble. Known supported distros are highlighted in the buttons above.
Repo symbol

ffmpeg_encoder_decoder repository

ffmpeg_encoder_decoder

ROS Distro
humble

Repository Summary

Checkout URI https://github.com/ros-misc-utilities/ffmpeg_encoder_decoder.git
VCS Type git
VCS Version release
Last Updated 2025-08-08
Dev Status DEVELOPED
Released RELEASED
Tags No category tags.
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Packages

Name Version
ffmpeg_encoder_decoder 3.0.0

README

ROS2 FFMPeg encoder/decoder

This ROS2 package supports encoding/decoding with the FFMpeg library, for example encoding h264 and h265 or HEVC, using Nvidia or other hardware acceleration when available. This package is meant to be used by image transport plugins like the ffmpeg image transport and the foxglove compressed video transport.

Supported systems

Continuous integration is tested under Ubuntu with the following ROS2 distros:

Build Status Build Status Build Status Build Status

Installation

From packages

sudo apt-get install ros-${ROS_DISTRO}-ffmpeg-encoder-decoder

From source

Set the following shell variables:

repo=ffmpeg_encoder_decoder
url=https://github.com/ros-misc-utilities/${repo}.git

and follow the instructions here

Make sure to source your workspace’s install/setup.bash afterwards.

API overview

Preliminaries

When using libav it is important to understand the difference between the encoder and the codec. The codec is the standardized format in which images are encoded, for instance h264 or hevc. The encoder is a libav software module that can encode images for a given codec. For instance libx264, libx264rgb, h264_nvenc, and h264_vaapi` are all encoders that encode for the codec h264. Some of the encoders are hardware accelerated, some can handle more image formats than others, but in the end they all encode video for a specific codec.

For the many AV options available for various libav encoders, and for qmax, bit_rate and similar settings please refer to the ffmpeg documentation.

The inner workings

overview_diagram

The diagram above shows the stations that a ROS Image message passes as it traverses the encoder and decoder. 1) The ROS image (with ROS sensor_msgs/Image encoding) is first converted with the ROS cv_bridge into the cv_bridge_target_format. This conversion is necessary because some ROS encodings (like bayer images) are not supported by libswscale. The cv_bridge_target_format can be set via setCVBridgeTargetFormat(const std::string & fmt). If this format is not set explicitly the image will be converted to the default format of bgr8. This may not be what you want for e.g. mono8 (gray) or Bayer images. Ideally thecv_bridge_target_format can be directly used by the libav decoder so the next step becomes a no-op. But at the very least cv_bridge_target_format must be an acceptable libswscale input format (with the exception of special hacks for encoding single-channel images, see below). 2) The image is then converted to av_source_pixel_format using libswscale. The av_source_pixel_format can be set with setAVSourcePixelFormat(), defaulting to something that is acceptable to the libav encoder. You can use ffmpeg (ffmpeg -h encoder=libx264 | grep formats) to list all formats that an encoder supports. Note that the ffmpeg/libav format string notation is different from the ROS encoding strings, and the av_source_pixel_format is specified using the libav convention, whereas the cv_bridge_target_format uses ROS convention! (If you choose to bypass the cv_bridge conversion from step 1 by feeding the images to the encoder directly via the encodeImage(const cv::Mat & img ...) method, you must still set the cv_bridge_target_format such that the encoder knows what format the img argument has.) When aiming for lossless compression, beware of any av_source_pixel_format that reduces the color resolution, such as yuv420p, nv12 etc. For Bayer images, use the special hack for single-channel images.

3) The libav encoder encodes the packet with its supported codec, e.g. the libx264 will produce h264 packets. The encoding field of the FFMPEGPacket message will document all image format conversions and the codec, in reverse order, separated by semicolon. This way the decoder can attempt to reproduce the original ros_encoding.

4) The libav decoder decodes the packet into the original av_source_pixel_format.

5) Finally the image is converted to output_message_format using libswscale. This format can be set (in ROS encoding syntax!) with setOutputMessageEncoding(). The format must be supported by both ROS and libswscale (except when using the special hack for single-channel images).

Note that only very few combinations of libav encoders, cv_bridge_target_format and av_source_pixel_format have been tested. Please provide feedback if you observe crashes or find obvious bugs. PRs are always appreciated!

The special single-channel hack

Many libav encoders do not support single-channel formats (like mono8 or bayer). For this reason a special hack is implemented in the encoder that adds an empty (zero-value) color channel to the single-channel image. Later, the decoder removes it again. To utilitze this hack, specify a cv_bridge_target_format of e.g. bayer_rggb8. Without the special hack, this would trigger an error because Bayer formats are not acceptable to libswscale. Instead, the image is converted to yuv420p or nv12 by adding an empty color channel. These formats are acceptable to most encoders. The decoder in turn recognizes that the cv_bridge_target_format is a single-channel format, but yuv420p/nv12 are not, and therefore drops the color channel. This hack greatly improves the efficiency for lossless encoding of Bayer images because it avoids conversion to full RGB and back.

API usage

Encoder

Using the encoder involves the following steps:

  • instantiating the Encoder object.
  • setting properties like the libav encoder to use, the encoding formats, and AV options.
  • initializing the encoder object. This requires knowledge of the image size and therefore

File truncated at 100 lines see the full file

CONTRIBUTING

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that license:

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

Contributors must sign-off each commit by adding a Signed-off-by: ... line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the Developer Certificate of Origin (DCO).

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that [license](http://www.apache.org/licenses/LICENSE-2.0.html): ~~~ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. ~~~ Contributors must sign-off each commit by adding a `Signed-off-by: ...` line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the [Developer Certificate of Origin (DCO)](https://developercertificate.org/).
No version for distro noetic showing humble. Known supported distros are highlighted in the buttons above.
Repo symbol

ffmpeg_encoder_decoder repository

ffmpeg_encoder_decoder

ROS Distro
humble

Repository Summary

Checkout URI https://github.com/ros-misc-utilities/ffmpeg_encoder_decoder.git
VCS Type git
VCS Version release
Last Updated 2025-08-08
Dev Status DEVELOPED
Released RELEASED
Tags No category tags.
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Packages

Name Version
ffmpeg_encoder_decoder 3.0.0

README

ROS2 FFMPeg encoder/decoder

This ROS2 package supports encoding/decoding with the FFMpeg library, for example encoding h264 and h265 or HEVC, using Nvidia or other hardware acceleration when available. This package is meant to be used by image transport plugins like the ffmpeg image transport and the foxglove compressed video transport.

Supported systems

Continuous integration is tested under Ubuntu with the following ROS2 distros:

Build Status Build Status Build Status Build Status

Installation

From packages

sudo apt-get install ros-${ROS_DISTRO}-ffmpeg-encoder-decoder

From source

Set the following shell variables:

repo=ffmpeg_encoder_decoder
url=https://github.com/ros-misc-utilities/${repo}.git

and follow the instructions here

Make sure to source your workspace’s install/setup.bash afterwards.

API overview

Preliminaries

When using libav it is important to understand the difference between the encoder and the codec. The codec is the standardized format in which images are encoded, for instance h264 or hevc. The encoder is a libav software module that can encode images for a given codec. For instance libx264, libx264rgb, h264_nvenc, and h264_vaapi` are all encoders that encode for the codec h264. Some of the encoders are hardware accelerated, some can handle more image formats than others, but in the end they all encode video for a specific codec.

For the many AV options available for various libav encoders, and for qmax, bit_rate and similar settings please refer to the ffmpeg documentation.

The inner workings

overview_diagram

The diagram above shows the stations that a ROS Image message passes as it traverses the encoder and decoder. 1) The ROS image (with ROS sensor_msgs/Image encoding) is first converted with the ROS cv_bridge into the cv_bridge_target_format. This conversion is necessary because some ROS encodings (like bayer images) are not supported by libswscale. The cv_bridge_target_format can be set via setCVBridgeTargetFormat(const std::string & fmt). If this format is not set explicitly the image will be converted to the default format of bgr8. This may not be what you want for e.g. mono8 (gray) or Bayer images. Ideally thecv_bridge_target_format can be directly used by the libav decoder so the next step becomes a no-op. But at the very least cv_bridge_target_format must be an acceptable libswscale input format (with the exception of special hacks for encoding single-channel images, see below). 2) The image is then converted to av_source_pixel_format using libswscale. The av_source_pixel_format can be set with setAVSourcePixelFormat(), defaulting to something that is acceptable to the libav encoder. You can use ffmpeg (ffmpeg -h encoder=libx264 | grep formats) to list all formats that an encoder supports. Note that the ffmpeg/libav format string notation is different from the ROS encoding strings, and the av_source_pixel_format is specified using the libav convention, whereas the cv_bridge_target_format uses ROS convention! (If you choose to bypass the cv_bridge conversion from step 1 by feeding the images to the encoder directly via the encodeImage(const cv::Mat & img ...) method, you must still set the cv_bridge_target_format such that the encoder knows what format the img argument has.) When aiming for lossless compression, beware of any av_source_pixel_format that reduces the color resolution, such as yuv420p, nv12 etc. For Bayer images, use the special hack for single-channel images.

3) The libav encoder encodes the packet with its supported codec, e.g. the libx264 will produce h264 packets. The encoding field of the FFMPEGPacket message will document all image format conversions and the codec, in reverse order, separated by semicolon. This way the decoder can attempt to reproduce the original ros_encoding.

4) The libav decoder decodes the packet into the original av_source_pixel_format.

5) Finally the image is converted to output_message_format using libswscale. This format can be set (in ROS encoding syntax!) with setOutputMessageEncoding(). The format must be supported by both ROS and libswscale (except when using the special hack for single-channel images).

Note that only very few combinations of libav encoders, cv_bridge_target_format and av_source_pixel_format have been tested. Please provide feedback if you observe crashes or find obvious bugs. PRs are always appreciated!

The special single-channel hack

Many libav encoders do not support single-channel formats (like mono8 or bayer). For this reason a special hack is implemented in the encoder that adds an empty (zero-value) color channel to the single-channel image. Later, the decoder removes it again. To utilitze this hack, specify a cv_bridge_target_format of e.g. bayer_rggb8. Without the special hack, this would trigger an error because Bayer formats are not acceptable to libswscale. Instead, the image is converted to yuv420p or nv12 by adding an empty color channel. These formats are acceptable to most encoders. The decoder in turn recognizes that the cv_bridge_target_format is a single-channel format, but yuv420p/nv12 are not, and therefore drops the color channel. This hack greatly improves the efficiency for lossless encoding of Bayer images because it avoids conversion to full RGB and back.

API usage

Encoder

Using the encoder involves the following steps:

  • instantiating the Encoder object.
  • setting properties like the libav encoder to use, the encoding formats, and AV options.
  • initializing the encoder object. This requires knowledge of the image size and therefore

File truncated at 100 lines see the full file

CONTRIBUTING

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that license:

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

Contributors must sign-off each commit by adding a Signed-off-by: ... line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the Developer Certificate of Origin (DCO).

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that [license](http://www.apache.org/licenses/LICENSE-2.0.html): ~~~ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. ~~~ Contributors must sign-off each commit by adding a `Signed-off-by: ...` line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the [Developer Certificate of Origin (DCO)](https://developercertificate.org/).