PAL/hdmiIn/rk3588_hdmi_in_out-in_and_out/main.cpp

111 lines
3.5 KiB
C++
Raw Normal View History

#include "fps_counter.h"
#include "video_saver.h"
#include "virtual_device.h"
#include "framebuffer.h"
#include "hdmi_in.h"
#include "kaylordut/log/logger.h"
#include <opencv2/opencv.hpp>
#include <thread>
#include <unistd.h>
#include <cstdlib> // 为了使用系统函数
#include <sys/stat.h> // 为了使用 access 函数
int main(int argc, char **argv) {
// 执行 framebuffer 设置命令
int result = system("sudo fbset -xres 1280 -yres 720");
if (result != 0) {
KAYLORDUT_LOG_ERROR("Failed to set framebuffer resolution");
return -1;
}
std::string virtual_device = "/dev/video10";
// 检查虚拟设备是否存在
if (access(virtual_device.c_str(), F_OK) == -1) {
// 如果不存在,创建虚拟设备
result = system("sudo modprobe v4l2loopback video_nr=10 card_label=\"HDMI_Capture\" exclusive_caps=1");
if (result != 0) {
KAYLORDUT_LOG_ERROR("Failed to load v4l2loopback module");
return -1;
}
}
std::stringstream ss;
for (int i = 0; i < argc; ++i) {
ss << argv[i] << " ";
}
KAYLORDUT_LOG_ERROR("Command: {}", ss.str());
std::string device = "/dev/video0";
HdmiIn hdmi_in(device);
std::string fb = "/dev/fb0";
FrameBuffer frame_buffer(fb);
int vd_fd = init_virtual_device(virtual_device, 1280, 720);
if (vd_fd == -1) {
KAYLORDUT_LOG_ERROR("Failed to initialize virtual device");
return -1;
}
cv::Mat frame;
FPSCounter fps_counter;
const std::chrono::milliseconds frame_duration(1000 / 25);
auto next_frame_time = std::chrono::steady_clock::now();
frame = hdmi_in.get_next_frame();
if (frame.empty()) {
KAYLORDUT_LOG_ERROR("Failed to get initial frame to determine video size");
return -1;
}
VideoSaver video_saver(25, frame.cols, frame.rows);
std::thread writer_thread(virtual_device_writer, vd_fd);
std::thread deleter_thread(VideoSaver::file_deleter);
while (true) {
auto start_time = std::chrono::steady_clock::now();
frame = hdmi_in.get_next_frame();
if (!frame.empty()) {
double current_fps = fps_counter.update();
std::string fps_text = cv::format("FPS: %.1f", current_fps);
cv::putText(frame, fps_text, cv::Point(20, 40), cv::FONT_HERSHEY_SIMPLEX, 1.2, CV_RGB(0, 255, 0), 2);
frame_buffer.WriteFrameBuffer(frame);
video_saver.write_frame(frame);
{
std::lock_guard<std::mutex> lock(queue_mutex);
frame_queue.push(frame.clone());
queue_cv.notify_one();
}
}
auto process_time = std::chrono::steady_clock::now() - start_time;
next_frame_time += frame_duration;
std::this_thread::sleep_until(next_frame_time);
if (process_time > frame_duration) {
// KAYLORDUT_LOG_ERROR("Frame processing took too long: {}ms", std::chrono::duration_cast<std::chrono::milliseconds>(process_time).count());
}
}
{
std::lock_guard<std::mutex> lock(queue_mutex);
stop_thread = true;
queue_cv.notify_one();
}
writer_thread.join();
VideoSaver::stop_file_deleter();
deleter_thread.join();
if (vd_fd != -1) {
close(vd_fd);
}
return 0;
}