Program Listing for File video_encoder.hpp#

Return to documentation for file (src/video/video_encoder.hpp)

#pragma once
#include <QThread>
#include <memory>

#include "utils/ring_buffer.hpp"
#include "video/frame_timestamp_writer.hpp"
#include "video/video_frame.hpp"

namespace mosaic {

// Consumes VideoFrames from a ring buffer and encodes them to an MP4 file.
//
// Codec selection at compile time:
//   MOSAIC_HAVE_NVENC        → h264_nvenc  (NVIDIA GPU, Windows/Linux)
//   MOSAIC_HAVE_VIDEOTOOLBOX → h264_videotoolbox (Apple, zero-copy)
//   neither                  → libx264 software fallback
//
// When FFmpeg is not present at all (no MOSAIC_HAVE_NVENC and not Apple),
// the encoder writes a minimal raw-stream marker file and logs a warning.
//
// FrameTimestampWriter is owned by the encoder: it is started before the
// encode loop and stopped when encoding finishes.

class VideoEncoder : public QThread {
    Q_OBJECT
   public:
    struct Config {
        int cameraIndex = 0;
        QString outputPath;    // .mp4 file
        QString timestampPath; // timestamps_camN.csv
        QString codec  = "h264_nvenc";
        QString preset = "p4";
        int bitrate    = 5000; // kbit/s  (GPU encoder)
        int crf        = 23;   // quality  (CPU encoder, 0=lossless, 51=worst)
        int width      = 1920;
        int height     = 1080;
        double fps     = 30.0;
    };

    explicit VideoEncoder(const Config& cfg, RingBuffer<std::shared_ptr<VideoFrame>>& frameBuffer,
                          QObject* parent = nullptr);
    ~VideoEncoder() override;

    void start_encoding();
    void stop_encoding(); // sets stop flag; call wait() to join

    [[nodiscard]] int64_t frames_encoded() const;
    [[nodiscard]] int64_t frames_dropped() const;

   signals:
    void encoding_started(int cameraIndex);
    void encoding_stopped(int cameraIndex, int64_t totalFrames);
    void encoding_error(int cameraIndex, QString message);

   protected:
    void run() override;

   private:
    void run_ffmpeg_loop();
    void run_stub_loop();

    struct Impl;
    std::unique_ptr<Impl> d;
};

} // namespace mosaic