Files
vision-anti-pinch/native/include/v4l2_capture.h
T

92 lines
2.9 KiB
C++

#ifndef V4L2_CAPTURE_H
#define V4L2_CAPTURE_H
#include <cstdint>
#include <stddef.h>
#include <string>
#include <vector>
// V4L2 流式(MMAP)取图封装
// 参考 quick_bring_up_64g.sh 中 v4l2src 的行为:
// - 打开 /dev/videoN
// - 协商 UYVY 像素格式与分辨率
// - 设置相机控制(sensor_mode / trig_pin 等, 等价于 v4l2-ctl -c ...)
// - MMAP 方式申请内核缓冲区并流式采集
class V4l2Capture {
public:
// 单帧采集结果
struct Frame {
void *data = nullptr; // 指向 MMAP 缓冲区, 释放前有效
size_t size = 0; // 实际帧字节数(bytesused)
uint32_t width = 0;
uint32_t height = 0;
uint32_t pixelformat = 0; // V4L2_PIX_FMT_* (如 V4L2_PIX_FMT_UYVY)
uint32_t bytes_per_line = 0;
uint32_t sequence = 0; // 驱动序号
uint64_t timestamp_us = 0; // 单调时钟时间戳(us)
int index = -1; // 内部缓冲区索引
};
V4l2Capture() = default;
~V4l2Capture();
V4l2Capture(const V4l2Capture &) = delete;
V4l2Capture &operator=(const V4l2Capture &) = delete;
// 打开设备节点, 例如 /dev/video5
bool open(const std::string &device);
// 关闭设备并释放所有资源
void close();
bool isOpen() const { return fd_ >= 0; }
// 协商像素格式与分辨率. pixelformat 使用 V4L2_PIX_FMT_* 四字符码
bool setFormat(uint32_t width, uint32_t height, uint32_t pixelformat);
// 设置帧率(通过 VIDIOC_S_PARM). fps 分子/分母均为 fps/1
bool setFps(uint32_t fps);
// 设置 V4L2 控制, 等价 v4l2-ctl -c <name>=<value>. id 为 V4L2_CID_* 之四字符码
// 例如 sensor_mode=0x009a2008, trig_pin=0x009a2084
bool setControl(uint32_t id, int32_t value);
// 申请 MMAP 缓冲区, 默认 4 个
bool initMmap(uint32_t buffer_count = 4);
// 开始 / 停止采集
bool startStreaming();
bool stopStreaming();
// 阻塞取一帧, 超时 timeout_ms 毫秒. 成功返回 true, 需配对调用 releaseFrame()
bool getFrame(Frame &frame, int timeout_ms = 1000);
// 归还缓冲区给驱动队列, 必须在下次 getFrame 前调用
void releaseFrame(const Frame &frame);
uint32_t width() const { return width_; }
uint32_t height() const { return height_; }
uint32_t pixelformat() const { return pixelformat_; }
private:
struct MmapBuffer {
void *start = nullptr;
size_t length = 0;
bool queued = false; // 是否在驱动队列中
};
// 归还指定索引的缓冲区 (内部使用)
void releaseFrameByIndex(int idx);
int fd_ = -1;
uint32_t width_ = 0;
uint32_t height_ = 0;
uint32_t pixelformat_ = 0;
uint32_t bytes_per_line_ = 0;
bool streaming_ = false;
std::vector<MmapBuffer> buffers_;
int last_dequeued_ = -1; // 当前已出队但未归还的缓冲区索引
};
#endif // V4L2_CAPTURE_H