1 #include <QApplication>
2 #include <QQmlApplicationEngine>
3 #include <QQuickWindow>
4 #include <QQuickItem>
5 #include <QRunnable>
6 #include <QTimer>
7 #include <gst/gst.h>
8 #include <gst/gl/gl.h>
9
10 static GstBusSyncReply
on_sync_bus_message(GstBus * bus,GstMessage * msg,gpointer data)11 on_sync_bus_message (GstBus * bus, GstMessage * msg, gpointer data)
12 {
13 GstElement *pipeline = (GstElement *) data;
14
15 switch (GST_MESSAGE_TYPE (msg)) {
16 case GST_MESSAGE_HAVE_CONTEXT: {
17 GstContext *context;
18
19 gst_message_parse_have_context (msg, &context);
20
21 /* if you need specific behviour or a context from a specific element,
22 * you need to be selective about which context's you set on the
23 * pipeline */
24 if (gst_context_has_context_type (context, GST_GL_DISPLAY_CONTEXT_TYPE)) {
25 gst_println ("got have-context %p", context);
26 gst_element_set_context (pipeline, context);
27 }
28
29 if (context)
30 gst_context_unref (context);
31 gst_message_unref (msg);
32 return GST_BUS_DROP;
33 }
34 default:
35 break;
36 }
37
38 return GST_BUS_PASS;
39 }
40
41 static void
connect_tee(GstElement * tee,GstElement * queue)42 connect_tee (GstElement * tee, GstElement * queue)
43 {
44 gst_println ("attaching tee/queue %p %p", tee, queue);
45 gst_element_link (tee, queue);
46 }
47
48 static void
connect_qmlglsink(GstElement * pipeline,GstElement * tee,QQuickWindow * rootObject)49 connect_qmlglsink (GstElement * pipeline, GstElement * tee, QQuickWindow * rootObject)
50 {
51 GstElement *queue = gst_element_factory_make ("queue", NULL);
52 GstElement *qmlglsink = gst_element_factory_make ("qmlglsink", NULL);
53 QQuickItem *videoItem;
54
55 gst_println ("attaching qmlglsink %s at %p", GST_OBJECT_NAME (qmlglsink), qmlglsink);
56
57 gst_bin_add (GST_BIN (pipeline), queue);
58 gst_bin_add (GST_BIN (pipeline), qmlglsink);
59 gst_element_link (queue, qmlglsink);
60 gst_element_set_state (queue, GST_STATE_PLAYING);
61
62 videoItem = rootObject->findChild<QQuickItem *> ("videoItem");
63 g_assert (videoItem);
64 g_object_set (qmlglsink, "widget", videoItem, NULL);
65
66 gst_element_set_state (qmlglsink, GST_STATE_PAUSED);
67 connect_tee (tee, queue);
68 gst_element_set_state (qmlglsink, GST_STATE_PLAYING);
69 }
70
main(int argc,char * argv[])71 int main(int argc, char *argv[])
72 {
73 int ret;
74
75 gst_init (&argc, &argv);
76
77 {
78 QGuiApplication app(argc, argv);
79
80 /* test a whole bunch of elements respect the change in display
81 * and therefore OpenGL context */
82 GstElement *pipeline = gst_parse_launch ("gltestsrc ! "
83 "capsfilter caps=video/x-raw(ANY),framerate=10/1 ! glupload ! "
84 "glcolorconvert ! glalpha noise-level=16 method=green angle=40 ! "
85 "glcolorbalance hue=0.25 ! gltransformation rotation-x=30 ! "
86 "glvideomixerelement ! glviewconvert output-mode-override=side-by-side ! "
87 "glstereosplit name=s "
88 "glstereomix name=m ! tee name=t ! queue ! fakesink sync=true "
89 "s.left ! queue ! m.sink_0 "
90 "s.right ! queue ! m.sink_1", NULL);
91 GstBus *bus = gst_element_get_bus (pipeline);
92 gst_bus_set_sync_handler (bus, on_sync_bus_message, pipeline, NULL);
93 gst_object_unref (bus);
94 /* the plugin must be loaded before loading the qml file to register the
95 * GstGLVideoItem qml item */
96 GstElement *sink = gst_element_factory_make ("qmlglsink", NULL);
97
98 g_assert (pipeline && sink);
99 gst_object_unref (sink);
100
101 QQuickWindow *rootObject;
102
103 /* The Qml scene starts out with the widget not connected to any qmlglsink
104 * element */
105 QQmlApplicationEngine engine;
106 engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
107
108 /* find and set the videoItem on the sink */
109 rootObject = static_cast<QQuickWindow *> (engine.rootObjects().first());
110
111 gst_element_set_state (pipeline, GST_STATE_PLAYING);
112
113 GstElement *t = gst_bin_get_by_name (GST_BIN (pipeline), "t");
114 gst_object_unref (t); /* ref held by pipeline */
115 /* add the qmlglsink element */
116 QTimer::singleShot(5000, [pipeline, t, rootObject]() { connect_qmlglsink (pipeline, t, rootObject); } );
117
118 ret = app.exec();
119
120 gst_element_set_state (pipeline, GST_STATE_NULL);
121 gst_object_unref (pipeline);
122 }
123
124 gst_deinit ();
125
126 return ret;
127 }
128