Qt 5 + Gstreamer cannot connect to stream
-
Hi Experts,
I'm trying to get stream from outside into my QT application.
The Project file:QT += core gui multimedia multimediawidgets network greaterThan(QT_MAJOR_VERSION, 4): QT += widgets CONFIG += c++11 CONFIG += link_pkgconfig LIBS += -lgstpbutils-1.0 LIBS += -lgstvideo-1.0 LIBS += -lgstaudio-1.0 LIBS += -lgstbase-1.0 LIBS += -lgstreamer-1.0 LIBS += -lgobject-2.0 LIBS += -lglib-2.0 # You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ Doorbell.cpp \ main.cpp \ videodoor.cpp \ CRC.cpp \ ECMD.cpp \ SRFID.cpp \ SysState.cpp \ UdpCommunication.cpp \ Uid.cpp HEADERS += videodoor.h \ CRC.h \ ECMD.h \ SRFID.h \ SysState.h \ UdpCommunication.h \ Uid.h \ Doorbell.h FORMS += \ videodoor.ui win32 { INCLUDEPATH += C:/gstreamer/1.0/mingw_x86_64/include \ C:/gstreamer/1.0/mingw_x86_64/include/gstreamer-1.0 \ C:/gstreamer/1.0/mingw_x86_64/include/glib-2.0 \ } unix { INCLUDEPATH += /usr/local/include/ \ /usr/include \ /usr/include/gstreamer-1.0 \ /usr/include/glib-2.0 \ /usr/lib/x86_64-linux-gnu/glib-2.0/include \ /usr/lib/x86_64-linux-gnu/gstreamer-1.0/include } # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target
The code in QT to start the video stream is the following
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); QVideoWidget *videoWidget = ui->videoWidget; player = new QMediaPlayer; doorbell = new Doorbell(this); player->setVideoOutput(videoWidget); player->setMedia(QUrl("gst-pipeline: udpsrc port=5000 caps=\"application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)JPEG, payload=(int)96\" ! rtpjpegdepay ! jpegdec ! videoconvert ! xvimagesink name=\"qtvideosink\"")); connect(player, &QMediaPlayer::stateChanged, this, &MainWindow::updatePlayer); player->play(); }
By starting of the program an error message depicted below is shown:
Using the same pipeline within the terminal causes any troubles and displays the stream correctly :
Could someone explain me what I'm doing wrong?
-
@Semiory said in Qt 5 + Gstreamer cannot connect to stream:
caps="
I guess
caps="
is not correct in the error message.You need to try the exactly same pipeline(different sink) from command line.
Another thing: Qt6 seems not to support this feature anymore. Therefore, your app is likely not working when you upgrade Qt to Qt6. Better to write raw gstreamer code with Qt sink and simply drop qt multimedia.
-
@JoeCFD
I changed the Pipeline, but that didn't help at all :(.
Hmm, the code is working a couple weeks ago....
Could it be that after the linux update (sudo apt-get update/upgrade) QT also updated to version 6 and that's why this feature is gone?
In case the raw gstreamer code with QT sink is used, will the QT application be able to show the video in some window? Sorry for the stupid question, I have never seen this approach :)
Could you please suggest where I could find an example of such realisation. -
@Semiory said in Qt 5 + Gstreamer cannot connect to stream:
QT also updated to version 6 and that's why this feature is gone?
Doubt that. Most Linux distributions do not do such big version jumps in same release.
Ubuntu 20.04 for example still provides Qt 5.12.8.
But you can easily check what Qt version you're using. -
@Semiory QT 5/6 are installed separately. If you use Qt5, Qt6 is not involved.
Try some simple pipelines first to make sure qt code works.
https://doc.qt.io/qt-5/qmediaplayer.html#setMediaThere is an example here for binding qml sink with gstreamer pipeline
https://github.com/GStreamer/gst-examples/blob/master/playback/player/qt/main.qml
If you use qt widgets, qml sink can be displayed in QQuickWidget. This is what I do. There are other ways to do it as well. Do your own research.
Qt5 Multimedia is a simple tool with gstreamer and there is not much control over the pipeline. If you prefer to use gstreamer, better to drop Qt5 Multimedia module. -
@JoeCFD
Thanks! I'll do so!P.S. The simple test example works:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); QVideoWidget *videoWidget = ui->videoWidget; player = new QMediaPlayer; doorbell = new Doorbell(this); player->setVideoOutput(videoWidget); player->setMedia(QUrl("gst-pipeline: videotestsrc ! xvimagesink name=\"qtvideosink\"")); connect(player, &QMediaPlayer::stateChanged, this, &MainWindow::updatePlayer); player->play(); }
-
I have found an Issue! I have used a port 5000 which is blocked on my machine, but only if the request comes not from terminal (No Idea how could it be... :) ).
To find it I have used the native approach:
#include <gst/video/videooverlay.h> #include <gst/gst.h> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); gst_init(NULL,NULL); // getting more information gst_debug_set_active(true); gst_debug_set_default_threshold(GST_LEVEL_INFO); GstElement *pipelineVideoIn = nullptr; GstStateChangeReturn ret; GstElement *source = nullptr; GstElement *capsfilter = nullptr; GstElement *rtpjpegdepay = nullptr; GstElement *jpegdec = nullptr; GstElement *videoconvert = nullptr; GstElement *sink = nullptr; GstCaps *caps; pipelineVideoIn = gst_pipeline_new("pipeline"); source = gst_element_factory_make("udpsrc", "source"); capsfilter = gst_element_factory_make("capsfilter", "capsfilter"); rtpjpegdepay = gst_element_factory_make("rtpjpegdepay", "rtpjpegdepay"); jpegdec = gst_element_factory_make("jpegdec", "jpegdec"); videoconvert = gst_element_factory_make("videoconvert", "videoconvert"); sink = gst_element_factory_make("qtvideosink", "sink"); gst_bin_add_many(GST_BIN(pipelineVideoIn), source, capsfilter, rtpjpegdepay, jpegdec, videoconvert, sink, nullptr); if (!gst_element_link_many(source, capsfilter, rtpjpegdepay, jpegdec, videoconvert, sink, nullptr)) { g_printerr("Elements could not be linked"); } g_object_set(source, "port", 5000, nullptr); caps = gst_caps_from_string("application/x-rtp, media=video, clock-rate=90000, encoding-name=JPEG, payload=96"); g_object_set(capsfilter, "caps", caps, nullptr); gst_caps_unref(caps); // get window handle WId xwinid = ui->videoWidget->winId(); // try to set overlay gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(sink), xwinid); GstStateChangeReturn sret = gst_element_set_state (pipelineVideoIn, GST_STATE_PLAYING); }
Unfortunately has this code an another problem, the overlay cannot be set :( and program crushes. But due to gst debug features, it is clear, that the gstreamer cannot connect the given address, because it is "already in use"
And after changing of the port on both sides (source and sink), streaming start to work with old application!
Ones Again, Thanks @JoeCFD for your Advice's! -