forked from zakaria/chicken-counting-sukawarna-det
67 lines
2.2 KiB
C++
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
|