我们在终端敲指令可以使用gstreamer方式去采集,如下所示,按1920*1080分辨率,60帧方式采集video0的视频。
gst-launch-1.0 v4l2src device=/dev/video0 ! video/x-raw, width=1920, height=1080, framerate=60/1 ! videoconvert ! autovideosink
敲完指令后会自动弹出一个显示窗口,那么如何让gstreamer与QT结合,使得视频显示在指定的QT窗体里呢。
首先我们把gst采集部分封装一下,可传入参数视频设备,分辨率,帧率等,同时包含一个用于显示的QWidget。
下边是头文件
class gstWidget : public QWidget
{
Q_OBJECT
public:
gstWidget(std::string device,int width,int height,int framerate,QWidget *parent = nullptr);
~gstWidget();
private:
GstElement *pipeline;
void startGStreamer(std::string device,int width,int height,int framerate);
};
下边是源文件
gstWidget::gstWidget(std::string device,int width,int height,int framerate,QWidget *parent)
: QWidget(parent)
{
gst_init(nullptr, nullptr);
startGStreamer(device,width,height,framerate);
}
gstWidget::~gstWidget()
{
if (pipeline) {
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(pipeline);
}
}
void gstWidget::startGStreamer(std::string device,int width,int height,int framerate)
{
std::string pipeline_str = "v4l2src device=" + device + " ! "
"video/x-raw,width="+std::to_string(width)+",height="+ std::to_string(height)+",framerate="+std::to_string(framerate)+"/1 ! "
"xvimagesink name=xvimagesink ";
pipeline = gst_parse_launch(pipeline_str.c_str(), nullptr);
WId winId = this->winId();
GstElement* xv_sink = gst_bin_get_by_name(GST_BIN(pipeline), "xvimagesink");
g_object_set(xv_sink, "force-aspect-ratio", true, NULL);
if (xv_sink) {
gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(xv_sink), (guintptr)winId);
} else {
qDebug() << "Failed to get xvimagesink element.";
}
gst_element_set_state(pipeline, GST_STATE_PLAYING);
}
后续如果要使用只需要调用gstWidget创建窗口即可,下边是一个使用示意,构造了一个带标题的cam显示窗口。
首先是头文件
class camWidget : public QWidget
{
Q_OBJECT
public:
camWidget(std::string device,QString title,int width,int height,int framerate,QWidget *parent = nullptr);
~camWidget();
public:
gstWidget *camDisp;
private:
QLabel *title_label;
};
然后是源文件
camWidget::camWidget(std::string device,QString title,int width,int height,int framerate,QWidget *parent)
: QWidget(parent)
{
QVBoxLayout *mainLayout = new QVBoxLayout(this);
camDisp=new gstWidget(device,width,height,framerate,this);
mainLayout->addWidget(camDisp);
setLayout(mainLayout);
title_label=new QLabel(this);
title_label->setAlignment(Qt::AlignCenter);
title_label->setStyleSheet("background: transparent; color: #FFFFFF");
title_label->setText(title);
}
camWidget::~camWidget()
{
}
接下来是真正的应用,在这里创建一个video0的显示窗口,标题为"cam",按1920*1080分辨率60帧去采集,显示窗口的大小为640*480。
camWidget cam=new camWidget("/dev/video0","cam",1920,1080,60,this);
cam->setGeometry(0,0,640,480);