当然,可以将你的代码封装成一个类,以便于更好地管理和重用。以下是一个示例的 VideoCapture
类,它封装了 GStreamer 和 OpenCV 的功能:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <gst/gst.h>
class VideoCapture {
public:
VideoCapture(const std::string& device)
: pipeline(nullptr), appsink(nullptr) {
// 初始化GStreamer
gst_init(nullptr, nullptr);
// 创建GStreamer管道字符串
std::string pipelineStr = "v4l2src device=" + device + " ! videoconvert ! appsink name=sink";
// 创建GStreamer管道
pipeline = gst_parse_launch(pipelineStr.c_str(), nullptr);
if (!pipeline) {
throw std::runtime_error("Failed to create GStreamer pipeline.");
}
// 获取appsink元素并设置其属性
appsink = gst_bin_get_by_name(GST_BIN(pipeline), "sink");
g_object_set(appsink, "emit-signals", TRUE, NULL);
// 启动管道
gst_element_set_state(pipeline, GST_STATE_PLAYING);
}
~VideoCapture() {
if (pipeline) {
// 停止管道并清理资源
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(pipeline);
}
}
void capture() {
cv::Mat frame;
while (true) {
GstSample* sample = nullptr;
g_signal_emit_by_name(appsink, "pull-sample", &sample);
if (sample) {
GstBuffer* buffer = gst_sample_get_buffer(sample);
GstCaps* caps = gst_sample_get_caps(sample); // 获取caps
if (caps) {
GstStructure* structure = gst_caps_get_structure(caps, 0); // 获取第一个结构体
int width, height;
// 提取宽度和高度信息
gst_structure_get_int(structure, "width", &width);
gst_structure_get_int(structure, "height", &height);
GstMapInfo info;
if (gst_buffer_map(buffer, &info, GST_MAP_READ)) {
frame = cv::Mat(cv::Size(width, height), CV_8UC3, info.data).clone(); // 使用clone确保数据不被修改
cv::imshow("HDMI IN Video", frame);
cv::waitKey(1); // 添加等待以更新窗口
gst_buffer_unmap(buffer, &info);
}
}
// 释放样本
gst_sample_unref(sample);
}
if (cv::waitKey(30) >= 0) break; // 添加退出机制,比如按任意键退出循环
}
}
private:
GstElement* pipeline;
GstElement* appsink;
};
int main(int argc, char* argv[]) {
try {
VideoCapture videoCapture("/dev/video0");
videoCapture.capture();
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
}
return 0;
}
使用说明:
- 初始化: 在构造函数中,传入设备路径,例如
"/dev/video0"
。 - 捕获视频: 调用
capture()
方法开始从视频源捕获帧。 - 析构函数: 确保在对象销毁时停止 GStreamer 管道,并释放资源。
注意事项:
- 根据实际情况调整
pipelineStr
字符串中的元素。 - 错误处理方面可以进一步增强,例如针对每个可能失败的操作进行异常捕捉。
内容由零声教学AI助手提供,问题来源于学员提问