• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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