94 lines
3.0 KiB
C++
94 lines
3.0 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; }
|
|
bool needsReconnect() const { return reconnect_needed_; }
|
|
|
|
// 协商像素格式与分辨率. 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;
|
|
bool reconnect_needed_ = false;
|
|
std::vector<MmapBuffer> buffers_;
|
|
int last_dequeued_ = -1; // 当前已出队但未归还的缓冲区索引
|
|
};
|
|
|
|
#endif // V4L2_CAPTURE_H
|