gstreamer是插件式的,我们一般测试的时候,都是使用命令行工具来测试功能,比如:
window:
gst-launch-1.0.exe ksvideosrc ! image/jpeg,width=1280,height=720,framerate=30/1 ! jpegdec ! videoconvert ! autovideosink
Linux:
gst-launch-1.0 v4l2 ! image/jpeg,width=1280,height=720,framerate=30/1 ! jpegdec ! videoconvert ! autovideosink
但是!!!
如果我们想使用C++代码来测试的时候,比如使用QT来测试的时候,就没有那么容易了,需要写一大堆的代码来实现命令行非常简单的功能,那么是否有快速的方式呢?
最近还真的被我发现一种方式,实现起来会比较简单。
原理非常简单,就是使用 pipeline 在创建的时候,使用 gst_parse_launch 即可。
比如我们实现播放播放测试视频流:
window的命令:
Linux的命令:
那么我们只需要在创建 pipeline 的时候,将gst-launch-1.0后面的内容,写在 gst_parse_launch 里面即可。例如刚刚的代码,就是
GstElement *pipeline = gst_parse_launch("videotestsrc ! autovideosink", NULL);
实现效果:
只能说,跟命令行的效果一样,但是我们可以在上面使用一些QT的元素。
下面是使用更加复杂的实现将摄像头数据进行播放的案例,大家基本上只需要更改gst_parse_launch的内容即可:
#include
#include
#include
#include
#include
// Callback function to retrieve the actual video sink
static void on_child_added(GstChildProxy *proxy, GObject *object, gchar *name, gpointer user_data) {
WId *window_handle = (WId *)user_data;
if (GST_IS_VIDEO_OVERLAY(object)) {
gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(object), (guintptr)(*window_handle));
}
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget window;
WId window_handle;
gst_init(&argc, &argv);
// Create GStreamer pipeline
// 源代码是 gst-launch-1.0 ksvideosrc ! image/jpeg,width=1920,height=1080,framerate=30/1 ! jpegdec ! videoconvert ! autovideosink
GstElement *pipeline = gst_parse_launch("ksvideosrc ! image/jpeg,width=1920,height=1080,framerate=30/1 ! jpegdec ! videoconvert ! autovideosink", NULL);
// Get the sink element from the pipeline
GstElement *sink = gst_bin_get_by_name(GST_BIN(pipeline), "autovideosink0");
window.show();
window_handle = window.winId();
// Connect to child-added signal to retrieve the actual video sink
g_signal_connect(sink, "child-added", G_CALLBACK(on_child_added), &window_handle);
// Start playing
gst_element_set_state(pipeline, GST_STATE_PLAYING);
// Run the QT application loop
int ret = app.exec();
// Clean up
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(GST_OBJECT(pipeline));
return ret;
}
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
gst_init(&argc, &argv);
// 准备pipeline
GstElement *pipeline = gst_parse_launch ("playbin uri=file:home/enpht/Videos/1081.mp4", NULL);
// 准备ui,Qwidget就行。是否显示无所谓。
QWidget *window = new QWidget();
window->resize(900, 600);
window->show();
// 将刚刚界面的WID传给gstreamer的sink
GstElement *vsink = gst_element_factory_make ("ximagesink", "vsink");
WId xwinid = window->winId();
gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (vsink), xwinid);
g_object_set(GST_OBJECT(pipeline), "video-sink", vsink, NULL);
// 开始播放
gst_element_set_state(pipeline, GST_STATE_PLAYING);
int ret = app.exec();
// 清除缓存
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(GST_OBJECT(pipeline));
return ret;
}
这种方法,通过 gst_bin_get_by_name 获取到管道内的元素,然后设置属性。
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget window;
WId window_handle;
gst_init(&argc, &argv);
// 创建管道 pipeline
GstElement *pipeline = gst_parse_launch("filesrc name=mysrc ! qtdemux name=demux demux.video_0 ! h264parse ! avdec_h264 ! videoconvert ! videoscale ! video/x-raw, width=640,height=480 ! ximagesink name=vsink", NULL);
//GstElement *pipeline = gst_parse_launch("videotestsrc ! ximagesink name=vsink",NULL);
// 设置管道中的属性
GstElement *mysrc = gst_bin_get_by_name (GST_BIN (pipeline), "mysrc");
g_object_set (mysrc, "location", "/home/enpht/Videos/1081.mp4", NULL);
g_object_unref (mysrc);
// 创建界面
window.show();
window_handle = window.winId();
// 链接到QT:
GstElement *vsink = gst_bin_get_by_name (GST_BIN (pipeline), "vsink");
gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (vsink), window_handle);
// Start playing
gst_element_set_state(pipeline, GST_STATE_PLAYING);
// Run the QT application loop
int ret = app.exec();
// Clean up
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(GST_OBJECT(pipeline));
return ret;
}
但是后期测试发现,无法在widget上面添加控件,添加了无法正常显示,后续会想办法嵌入其他控件,或者将这个封装一层嵌入其他界面中。