Encoders

Encoders convert decoded Limef::frame::DecodedFrames into encoded Limef::frame::PacketFrames. The abstract interface is Limef::encode::Encoder; the main implementation is Limef::encode::FFmpegEncoder.

namespace encode

Typedefs

using VideoEncoderParams = std::variant<FFmpegEncoderParams, V4L2EncoderParams>

Variant type for encoder parameters.

All backend param types are always present - no compile-time ifdefs. Use isEncoderAvailable() to check runtime availability before creating.

Example:

// FFmpeg backend (always available)
FFmpegEncoderParams ffmpeg_params;
ffmpeg_params.codec_id = AV_CODEC_ID_H264;
VideoEncoderParams params = ffmpeg_params;

// V4L2 backend (check availability first)
if (isEncoderAvailable(EncoderBackend::V4L2)) {
    V4L2EncoderParams v4l2_params;
    v4l2_params.device = "/dev/video2";
    VideoEncoderParams params = v4l2_params;
}

Enums

enum class EncoderBackend

Available encoder backends.

Values:

enumerator FFmpeg

FFmpeg-based software/hardware encoding.

enumerator V4L2

V4L2 Memory-to-Memory API (Jetson, embedded Linux)

enum class EncoderStatus

Status codes returned by encoder.

Values:

enumerator NeedsMoreData

Ready to accept more frames via push()

enumerator NeedsRead

Encoded packet available, call getPacket()

enumerator EndOfStream

End of stream (flushing complete)

enumerator Error

Something went wrong.

Functions

std::vector<EncoderBackend> getAvailableEncoders()

Query available encoder backends at runtime.

Returns backends that were compiled in and are functional. For V4L2, also checks if required devices exist.

Returns:

std::vector<EncoderBackend> List of available backends

bool isEncoderAvailable(EncoderBackend backend)

Check if a specific encoder backend is available.

EncoderBackend getBackend(const VideoEncoderParams &params)

Get the backend type from encoder params.

Encoder *createEncoder(const std::string &name, const VideoEncoderParams &params)

Create an encoder from variant parameters.

Factory function that creates the appropriate encoder based on the active type in the params variant.

Parameters:
  • name – Identifier for logging

  • params – Encoder parameters (variant of FFmpegEncoderParams, V4L2EncoderParams, etc.)

Throws:

std::runtime_error – if backend not compiled in or not available

Returns:

Encoder* Newly created encoder (caller owns)

std::string getEncoderName(AVCodecID codec_id, HWAccel hw_accel)

Get FFmpeg encoder name for codec + acceleration combination.

Maps (codec_id, hw_accel) to FFmpeg encoder name. Returns empty string if combination is not supported.

Examples:

  • (H264, VAAPI) -> “h264_vaapi”

  • (VP9, SW) -> “libvpx_vp9”

  • (H264, SW) -> “” (no GPL software encoder)

Parameters:
  • codec_id – Target codec

  • hw_accel – Hardware acceleration type

Returns:

std::string FFmpeg encoder name, or empty if unsupported

class Encoder
#include <encoder.h>

Abstract encoder interface for a single video or audio stream.

State machine that encodes decoded frames into packets. Call status() to determine what operation to do next.

Implementations:

  • FFmpegEncoder: FFmpeg-based software/hardware encoding

  • V4L2Encoder: V4L2 Memory-to-Memory API (Jetson, embedded Linux)

Example usage:

std::unique_ptr<Encoder> enc = std::make_unique<FFmpegEncoder>("my-encoder", params);
enc->setPacketFrame(packet_frame);

// Encoding loop:
EncoderStatus stat = enc->status();
if (stat == EncoderStatus::NeedsMoreData) {
    enc->push(&decoded_frame);
}
if (stat == EncoderStatus::NeedsRead) {
    const PacketFrame& pkt = enc->getPacket();
    // send packet downstream
}

All calls to encoder are non-blocking.

Subclassed by Limef::encode::FFmpegEncoder, Limef::encode::V4L2Encoder

Public Functions

virtual void setLogger(std::shared_ptr<spdlog::logger> logger) = 0

Set logger for this encoder.

virtual void setPacketFrame(Limef::frame::PacketFrame &frame) = 0

Set output packet frame.

Must be called before encoder can be used. Frame will be reused for encoded output.

Parameters:

frame – Frame to use for encoded output

virtual EncoderStatus status() = 0

Get current encoder status.

Call this to determine what operation to do next:

  • NeedsMoreData: Call push() with next frame

  • NeedsRead: Call getPacket() to get encoded packet

  • Error: Handle error condition

Returns:

EncoderStatus Current status

virtual void push(const Limef::frame::DecodedFrame *frame) = 0

Push decoded frame for encoding.

Only call when status() returns NeedsMoreData. On first call, may initialize encoder dimensions from frame.

Parameters:

frame – DecodedFrame to encode

virtual const Limef::frame::PacketFrame &getPacket() = 0

Get encoded packet.

Only call when status() returns NeedsRead

Returns:

const PacketFrame& Reference to encoded packet

virtual void flush() = 0

Flush the encoder.

Forces encoder to output any buffered packets. Check status() after this to get remaining packets.

virtual int getStreamIndex() const = 0

Get the stream index this encoder produces.

virtual void setStreamIndex(int idx) = 0

Set stream index for output packets.

virtual bool isInitialized() const = 0

Check if encoder is fully initialized and ready to produce output.

virtual void configure(const AVStream *stream) = 0

Configure encoder timing from stream info.

Called when StreamFrame arrives. Extracts fps and timebase. Since StreamFrame uses AVFormatContext, all encoders receive AVStream*.

Parameters:

stream – Source stream info

virtual bool isConfigured() const = 0

Check if encoder has been configured (received stream info)

inline virtual const AVCodecParameters *getCodecParams() const

Get codec parameters for muxer/decoder setup.

Returns codec parameters after encoder is initialized. Used to create CodecFrame for downstream decoders.

Returns:

const AVCodecParameters* Codec parameters, or nullptr if not available/initialized

inline virtual AVRational getTimeBase() const

Get encoder output timebase.

Returns the timebase of encoded packets. Used for CodecFrame creation.

Returns:

AVRational Timebase (e.g., {1, 90000} for 90kHz)

inline virtual AVRational getFrameRate() const

Get encoder output frame rate.

Returns:

AVRational Frame rate (e.g., {30, 1} for 30fps)

class FFmpegEncoder : public Limef::encode::Encoder
#include <ffmpeg_encoder.h>

FFmpeg-based encoder for video and audio streams.

Supports both software encoding and hardware-accelerated encoding via FFmpeg’s hwaccel infrastructure (VAAPI, NVENC, etc.)

Initialization is two-phase:

  1. configure() - called when StreamFrame arrives (provides fps, timebase)

  2. initFromFrame() - called on first DecodedFrame (provides dimensions, format)

Example usage:

FFmpegEncoderParams params;
params.codec_id = AV_CODEC_ID_H264;
params.bitrate = 2000000;

FFmpegEncoder enc("my-encoder", params);

// When StreamFrame arrives:
enc.configure(stream_frame.getVideoStream());

// Set output packet frame:
enc.setPacketFrame(packet_frame);

// Encoding loop:
EncoderStatus stat = enc.status();
if (stat == EncoderStatus::NeedsMoreData) {
    enc.push(&decoded_frame);
}
if (stat == EncoderStatus::NeedsRead) {
    const PacketFrame& pkt = enc.getPacket();
    // send packet downstream
}

Public Functions

FFmpegEncoder(const std::string &name, const FFmpegEncoderParams &params)

Construct encoder with given parameters.

Parameters:
  • name – Identifier for logging

  • params – Encoding parameters (codec, bitrate, etc.)

inline virtual void setLogger(std::shared_ptr<spdlog::logger> logger) override

Set logger for this encoder.

virtual void setPacketFrame(Limef::frame::PacketFrame &frame) override

Set output packet frame.

Must be called before encoder can be used. Frame will be reused for encoded output.

Parameters:

frame – Frame to use for encoded output

virtual EncoderStatus status() override

Get current encoder status.

Call this to determine what operation to do next:

  • NeedsMoreData: Call push() with next frame

  • NeedsRead: Call getPacket() to get encoded packet

  • Error: Handle error condition

Returns:

EncoderStatus Current status

virtual void push(const Limef::frame::DecodedFrame *frame) override

Push decoded frame for encoding.

Only call when status() returns NeedsMoreData. On first call, may initialize encoder dimensions from frame.

Parameters:

frame – DecodedFrame to encode

inline virtual const Limef::frame::PacketFrame &getPacket() override

Get encoded packet.

Only call when status() returns NeedsRead

Returns:

const PacketFrame& Reference to encoded packet

virtual void flush() override

Flush the encoder.

Forces encoder to output any buffered packets. Check status() after this to get remaining packets.

inline virtual int getStreamIndex() const override

Get the stream index this encoder produces.

inline virtual void setStreamIndex(int idx) override

Set stream index for output packets.

inline virtual bool isInitialized() const override

Check if encoder is fully initialized and ready to produce output.

virtual void configure(const AVStream *stream) override

Configure encoder timing from stream info.

Called when StreamFrame arrives. Extracts fps and timebase. Since StreamFrame uses AVFormatContext, all encoders receive AVStream*.

Parameters:

stream – Source stream info

inline virtual bool isConfigured() const override

Check if encoder has been configured (received stream info)

virtual const AVCodecParameters *getCodecParams() const override

Get codec parameters for muxer/decoder setup.

Returns codec parameters after encoder is initialized. Used to create CodecFrame for downstream decoders.

Returns:

const AVCodecParameters* Codec parameters, or nullptr if not available/initialized

inline virtual AVRational getTimeBase() const override

Get encoder output timebase.

Returns the timebase of encoded packets. Used for CodecFrame creation.

Returns:

AVRational Timebase (e.g., {1, 90000} for 90kHz)

inline virtual AVRational getFrameRate() const override

Get encoder output frame rate.

Returns:

AVRational Frame rate (e.g., {30, 1} for 30fps)

struct FFmpegEncoderParams
#include <ffmpeg_encoder.h>

Encoding parameters for FFmpegEncoder.

Contains codec selection and quality settings. Dimensions and format come from the incoming DecodedFrame. Timing (fps, timebase) comes from StreamFrame via configure().

Example usage:

// VAAPI H.264 encoding (no GPL issues)
FFmpegEncoderParams params;
params.codec_id = AV_CODEC_ID_H264;
params.hw_accel = HWAccel::VAAPI;
// hw_device uses sensible default, or specify:
// params.hw_device = "/dev/dri/renderD128";

// Software VP9 encoding (royalty-free)
FFmpegEncoderParams params;
params.codec_id = AV_CODEC_ID_VP9;
params.hw_accel = HWAccel::SW;  // uses libvpx

Public Members

AVCodecID codec_id = {AV_CODEC_ID_H264}

Target codec.

int64_t bitrate = {2000000}

Target bitrate in bits/sec.

HWAccel hw_accel = {HWAccel::SW}

Hardware acceleration backend.

std::string hw_device

Device path (empty = auto-detect)

std::string preset = {"medium"}

Encoder preset (SW: “ultrafast”..”veryslow”; NVENC: “p1”..”p7”)

std::string profile = {}

Codec profile (H.264: “baseline”,”main”,”high”)

std::string tune = {}

Tuning (SW: “zerolatency”,”film”; NVENC: “ll”,”ull”,”hq”)

int gop_size = {30}

Keyframe interval (0 = codec default)

int max_b_frames = {-1}

Max B-frames (-1 = codec default)

int crf = {-1}

Constant Rate Factor (-1 = use bitrate instead)

int thread_count = {0}

Encoder threads (0 = auto)

struct V4L2Buffer
#include <v4l2_encoder.h>

Buffer info for mmap’d V4L2 buffers.

Public Members

void *start = {nullptr}

mmap’d address

size_t length = {0}

Buffer size.

int index = {-1}

Buffer index.

bool queued = {false}

Currently queued to driver.

class V4L2Encoder : public Limef::encode::Encoder
#include <v4l2_encoder.h>

V4L2 Memory-to-Memory encoder.

Implements the Encoder interface using V4L2 M2M API. Developed against vicodec, deployable to Jetson.

V4L2 M2M uses two buffer queues:

  • OUTPUT: Raw frames go IN (confusing naming from V4L2)

  • CAPTURE: Encoded packets come OUT

State machine:

  1. Open device, set formats

  2. Request and mmap buffers for both queues

  3. Start streaming on both queues

  4. Queue raw frame to OUTPUT, dequeue encoded from CAPTURE

Example:

V4L2EncoderParams params;
params.device = "/dev/video2";  // vicodec encoder
params.codec_fourcc = V4L2_PIX_FMT_FWHT;

V4L2Encoder enc("v4l2-enc", params);
enc.setPacketFrame(packet_frame);

// First frame initializes dimensions
enc.push(&decoded_frame);

// Check for output
if (enc.status() == EncoderStatus::NeedsRead) {
    const PacketFrame& pkt = enc.getPacket();
}

Public Functions

inline virtual void setLogger(std::shared_ptr<spdlog::logger> logger) override

Set logger for this encoder.

virtual void setPacketFrame(Limef::frame::PacketFrame &frame) override

Set output packet frame.

Must be called before encoder can be used. Frame will be reused for encoded output.

Parameters:

frame – Frame to use for encoded output

virtual EncoderStatus status() override

Get current encoder status.

Call this to determine what operation to do next:

  • NeedsMoreData: Call push() with next frame

  • NeedsRead: Call getPacket() to get encoded packet

  • Error: Handle error condition

Returns:

EncoderStatus Current status

virtual void push(const Limef::frame::DecodedFrame *frame) override

Push decoded frame for encoding.

Only call when status() returns NeedsMoreData. On first call, may initialize encoder dimensions from frame.

Parameters:

frame – DecodedFrame to encode

inline virtual const Limef::frame::PacketFrame &getPacket() override

Get encoded packet.

Only call when status() returns NeedsRead

Returns:

const PacketFrame& Reference to encoded packet

virtual void flush() override

Flush the encoder.

Forces encoder to output any buffered packets. Check status() after this to get remaining packets.

inline virtual int getStreamIndex() const override

Get the stream index this encoder produces.

inline virtual void setStreamIndex(int idx) override

Set stream index for output packets.

inline virtual bool isInitialized() const override

Check if encoder is fully initialized and ready to produce output.

virtual void configure(const AVStream *stream) override

Configure encoder timing from stream info.

Called when StreamFrame arrives. Extracts fps and timebase. Since StreamFrame uses AVFormatContext, all encoders receive AVStream*.

Parameters:

stream – Source stream info

inline virtual bool isConfigured() const override

Check if encoder has been configured (received stream info)

struct V4L2EncoderParams
#include <v4l2_encoder.h>

Encoding parameters for V4L2Encoder.

V4L2-specific parameters using fourcc codes instead of AVCodecID.

Public Members

std::string device = {"/dev/video2"}

V4L2 device path (vicodec encoder default)

uint32_t codec_fourcc = {V4L2_PIX_FMT_FWHT}

Output codec (FWHT, H264, HEVC)

uint32_t input_fourcc = {V4L2_PIX_FMT_NV12}

Input pixel format.

int64_t bitrate = {2000000}

Target bitrate in bits/sec.

int gop_size = {30}

Keyframe interval.

int num_output_buffers = {4}

Number of OUTPUT (raw frame) buffers.

int num_capture_buffers = {4}

Number of CAPTURE (encoded) buffers.