Building with Gstreamer on Windows
-
Looks like pkg-config did not work correctly but still... the manual way did work !
Glad you found a way and thanks for sharing !
-
Also for Windows, I needed to use d3dvideosink or autovideosink rather than glimagesink
It builds and renders the Gstreamer sample video.
Now my issue is getting it to stay within the application window rather than popping out into its own new window.
I got this error:
** (slim_qt.exe:5908): CRITICAL **: 16:15:15.218: gst_video_overlay_set_window_handle: assertion 'overlay != NULL' failed
So I added:
qDebug() << "slim_qt:gst() xwinid = " + QVariant(xwinid).toString();
and got this:
"slim_qt:gst() xwinid = 1770362"
So I am wondering why gst_video_overlay_set_window_handle failed.
-
You might want to take a look at the GStreamer backend plugin. With recent versions of Qt you can build custom pipelines and make them output to a Qt video widget naming the sink properly.
-
I got it to land in the QWidget. The trick was to call .show() before calling winId().
Here is the final .pro:
QT += core gui multimediawidgets greaterThan(QT_MAJOR_VERSION, 4): QT += widgets CONFIG += c++11 DEFINES += QT_DEPRECATED_WARNINGS SOURCES += \ main.cpp HEADERS += CONFIG += link_pkgconfig PKGCONFIG += gstreamer-1.0 \ glib-2.0 \ gobject-2.0 \ gio-2.0 linux { PKGCONFIG += gstvideo-1.0 LIBS += -L/usr/lib/i386-linux-gnu/ -lgstvideo-1.0 } mac { PKG_CONFIG = /usr/local/bin/pkg-config PKGCONFIG += gstreamer-video-1.0 } win32 { INCLUDEPATH += c:/gstreamer/1.0/x86_64/include \ c:/gstreamer/1.0/x86_64/lib/gstreamer-1.0/include \ c:/gstreamer/1.0/x86_64/include/gstreamer-1.0 \ c:/gstreamer/1.0/x86_64/include/glib-2.0 \ c:/gstreamer/1.0/x86_64/include/glib-2.0/glib \ c:/gstreamer/1.0/x86_64/include/glib-2.0/include DEPENDPATH += c:/gstreamer/1.0/x86_64/lib/ LIBS += -Lc:/gstreamer/1.0/x86_64/lib LIBS += c:/gstreamer/1.0/x86_64/lib/glib-2.0.lib LIBS += -lglib-2.0 -lwinpthread -lgstreamer-1.0 -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 LIBS += -lgstvideo-1.0 CONFIG += c:/gstreamer/1.0/x86_64/lib/pkgconfig } # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target
and main.cpp:
#include <QApplication> #include <QFrame> #include <QTimer> #include <QDebug> #include <QLabel> #include <QWidget> #include <QVBoxLayout> #include <gst/gst.h> #include <QtDebug> #include <gst/video/videooverlay.h> /* added to work on OSX */ #ifdef __APPLE__ #ifdef TARGET_OS_MAC #include <glib/deprecated/gthread.h> #endif #endif void gst(int argc, char *argv[]) { gst_init (&argc, &argv); QApplication app(argc, argv); app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit ())); // prepare the pipeline /* GstElement *pipeline = gst_parse_launch ( "videotestsrc is-live=true ! d3dvideosink", NULL); GstElement *sink = gst_bin_get_by_name(GST_BIN(pipeline), "sink"); */ GstElement *pipeline = gst_pipeline_new ("xvoverlay"); GstElement *src = gst_element_factory_make ("videotestsrc", NULL); GstElement *sink = gst_element_factory_make ("d3dvideosink", NULL); gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL); gst_element_link (src, sink); // prepare the ui QWidget window; QLabel *label = new QLabel("Hi"); QWidget *widget = new QWidget(); QVBoxLayout qboxLayout; qboxLayout.addWidget(label); qboxLayout.addWidget(widget); window.setLayout(&qboxLayout); window.resize(320, 240); window.show(); WId xwinid = widget->winId(); qDebug() << "slim_qt:gst() xwinid = " + QVariant(xwinid).toString(); gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (sink), xwinid); // run the pipeline GstStateChangeReturn sret = gst_element_set_state (pipeline, GST_STATE_PLAYING); if (sret == GST_STATE_CHANGE_FAILURE) { gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (pipeline); // Exit application QTimer::singleShot(0, QApplication::activeWindow(), SLOT(quit())); } app.exec(); } int main(int argc, char *argv[]) { gst(argc, argv); return true; }
and project build ENV settings:
Set GSL_PLUGIN_PATH to C:\gstreamer\1.0\x86_64\lib\gstreamer-1.0 Set GSTREAMER_INCDIR to C:\gstreamer\1.0\x86_64\include\gstreamer-1.0 Set GSTREAMER_LIBDIR to C:\gstreamer\1.0\x86_64\lib Set PKG_CONFIG_PATH to C:\gstreamer\1.0\x86_64\lib\pkgconfig\ Add to Path: C:\gstreamer\1.0\x86_64\bin\
-
QMediaPlayer::setMedia for thé documentation itself.
You might even be able just build the GStreamer backend and use it directly.
-
-
QMediaPlayer does not do anything directly. It uses the various plugins. Each platform has its corresponding plugin using native technologies. However nothing forbids you to provide additional plugins like for example for network cameras. So if you manage to build the GStreamer plugin, using it should also be possible.
-
I spoke too soon. I do have the application building but video is not yet playing. I was told that the issue may be because I am using MinGW rather than MSVC. I was able to trim down a sample application which I thought that I should share in case anyone else wants to give this a try. I see the video test pattern when I build it from QT Creator but not when I deploy it as a stand alone application. If you are able to see the test pattern as a stand alone application, please post here how you got it working. Thank you!
TEMPLATE = app TARGET = videoapp QT += multimedia multimediawidgets network widgets core gui CONFIG += link_pkgconfig PKGCONFIG += gstreamer-1.0 \ glib-2.0 \ gobject-2.0 \ gio-2.0 \ gstreamer-video-1.0 \ gstreamer-audio-1.0 linux { # PKGCONFIG += gstvideo-1.0 LIBS += -L/usr/lib/i386-linux-gnu/ -lgstvideo-1.0 # I don't think you need the INCLUDEPATH below if pkg-config is working correctly INCLUDEPATH += \ /usr/include/gstreamer-1.0 \ /usr/include/glib-2.0/ \ /usr/lib/x86_64-linux-gnu/glib-2.0/include/ } mac { PKG_CONFIG = /usr/local/bin/pkg-config PKGCONFIG += gstreamer-video-1.0 gstreamer-audio-1.0 } win32 { ## - Everything is set in the QT Project Build ENV, including: #Set GSL_PLUGIN_PATH to C:\gstreamer\1.0\x86_64\lib\gstreamer-1.0 #Set GSTREAMER_INCDIR to C:\gstreamer\1.0\x86_64\include\gstreamer-1.0 #Set GSTREAMER_LIBDIR to C:\gstreamer\1.0\x86_64\lib #Add this to Path: C:\gstreamer\1.0\x86_64\bin\ } HEADERS = SOURCES = \ main.cpp
main.cpp:
#include <QApplication> #include <QTimer> #include <QLabel> #include <QWidget> #include <QVBoxLayout> #include <gst/gst.h> #include <gst/video/videooverlay.h> /* added to work on OSX */ #ifdef __APPLE__ #ifdef TARGET_OS_MAC #include <glib/deprecated/gthread.h> #endif #endif void gst(int argc, char *argv[]) { gst_init (&argc, &argv); QApplication app(argc, argv); app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit ())); QString videosinkStr, audiosinkStr, pipelinestr; GstElement *m_pipeline, *sink; #ifdef _WIN32 // TODO: any difference on videosink definition between _WIN32 and _WIN64? videosinkStr = "d3dvideosink"; // test: dshowvideosink, d3dvideosink, directsoundsink audiosinkStr = "volume ! directsoundsink"; #endif #ifdef __APPLE__ #ifdef TARGET_OS_MAC videosinkStr = "glimagesink"; // also test: osxvideosink, osxaudiosink audiosinkStr = "volume ! osxaudiosink"; #endif #endif #ifdef __linux__ videosinkStr = "xvimagesink"; // ximagesink is a winner on my PopOS machine! //also test: ximagesink, xvimagesink, alsasink, pulsesink audiosinkStr = "volume ! alsasink"; #endif pipelinestr = "videotestsrc ! "+videosinkStr+" name=video_out"; m_pipeline = gst_parse_launch (pipelinestr.toStdString().c_str(), NULL ); sink = gst_bin_get_by_name(GST_BIN(m_pipeline), "video_out"); QWidget window; QLabel *label = new QLabel("Video Test Pattern"); QWidget *widget = new QWidget(); widget->setFixedSize(640,360); WId xwinid = widget->winId(); gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (sink), guintptr(xwinid)); QVBoxLayout qboxLayout; qboxLayout.addWidget(label); qboxLayout.addWidget(widget); window.setLayout(&qboxLayout); window.resize(660, 380); window.show(); // run the pipeline GstStateChangeReturn sret = gst_element_set_state (m_pipeline, GST_STATE_PLAYING); if (sret == GST_STATE_CHANGE_FAILURE) { gst_element_set_state (m_pipeline, GST_STATE_NULL); gst_object_unref (m_pipeline); // Exit application QTimer::singleShot(0, QApplication::activeWindow(), SLOT(quit())); } app.exec(); } int main(int argc, char *argv[]) { gst(argc, argv); return true; }
-
Did you deploy your application using windeployqt ?
-
Yes. It still needed the Gstreamer libs, so I copied all of those too. It also complained of other libs missing so I copied those as needed from the system until the application ran. Now it runs but video does not play. I suspect that this may be the mysterious issue with MinGW.
-
I received some useful Gstreamer debugging information on this forum post:
http://gstreamer-devel.966125.n4.nabble.com/How-to-debug-Gstreamer-on-Windows-td4693738.html -
OK. I got it to work by switching to MSVC, creating a plugins directory, setting a Gstreamer ENV to that path, like so: set GST_PLUGIN_PATH=C:\Users\vivoh\Desktop\mini\plugins, and dropping in the two required plugins, in this case: gstvideotestsrc.dll and gstd3d.dll