Files
chicken-counting-sukawarna-det/cpp/include/chicken_counter/video_writer.hpp
T
2026-07-22 00:03:02 +07:00

67 lines
2.2 KiB
C++

#pragma once
#include <cstdint>
#include <filesystem>
#include <iostream>
#include <string>
#include <vector>
#include <opencv2/videoio.hpp>
namespace cc {
inline cv::VideoWriter make_video_writer(
const std::string& path,
const cv::Size& frame_size,
double fps,
const std::string& encoder = "auto",
int output_bitrate_kbps = 4000,
const std::vector<std::string>& codec_preference = {})
{
namespace fs = std::filesystem;
fs::create_directories(fs::path(path).parent_path());
int bitrate_bps = std::max(1, output_bitrate_kbps) * 1000;
auto codecs = codec_preference.empty()
? std::vector<std::string>{"avc1", "mp4v", "H264"}
: codec_preference;
if (encoder == "auto" || encoder == "gstreamer") {
int fps_int = std::max(1, static_cast<int>(std::round(fps)));
std::string pipeline =
"appsrc ! video/x-raw, format=BGR ! "
"video/x-raw,width=" + std::to_string(frame_size.width) +
",height=" + std::to_string(frame_size.height) +
",framerate=" + std::to_string(fps_int) + "/1 ! "
"videoconvert ! nvvidconv ! "
"video/x-raw(memory:NVMM),format=NV12 ! "
"nvv4l2h264enc bitrate=" + std::to_string(bitrate_bps) +
" insert-sps-pps=true ! "
"h264parse ! mp4mux ! filesink location=" + path;
cv::VideoWriter writer(pipeline, cv::CAP_GSTREAMER, 0, fps, frame_size, true);
if (writer.isOpened()) {
std::cerr << "[video] opened GStreamer hardware encoder (bitrate="
<< output_bitrate_kbps << " kbps)\n";
return writer;
}
writer.release();
if (encoder == "gstreamer")
throw std::runtime_error("GStreamer video writer failed for: " + path);
}
for (const auto& codec : codecs) {
int fourcc = cv::VideoWriter::fourcc(codec[0], codec[1], codec[2], codec[3]);
cv::VideoWriter writer(path, fourcc, fps, frame_size);
if (writer.isOpened()) {
std::cerr << "[video] opened OpenCV encoder (codec=" << codec << ")\n";
return writer;
}
writer.release();
}
throw std::runtime_error("Unable to open video writer: " + path);
}
} // namespace cc