From e70ebfd2ed8d522478f04ab823b527b48ed24671 Mon Sep 17 00:00:00 2001 From: Dmytro Poplavskiy Date: Tue, 2 Aug 2011 14:33:38 +1000 Subject: Gstreamer media backend cleanup. Moved controls specific bus/sync messages handling from player/camera/capture session to corresponding controls. Reviewed-by: Michael Goddard Change-Id: Ieb67976ed335b0ef1cde87dc60e8ad8da3409526 Reviewed-on: http://codereview.qt.nokia.com/2535 Reviewed-by: Qt Sanity Bot Reviewed-by: Michael Goddard --- .../gstreamer/camerabin/camerabinimagecapture.cpp | 8 ++- .../gstreamer/camerabin/camerabinimagecapture.h | 6 +- .../gstreamer/camerabin/camerabinservice.cpp | 7 +-- .../gstreamer/camerabin/camerabinsession.cpp | 27 +++------ src/plugins/gstreamer/camerabin/camerabinsession.h | 9 ++- .../mediacapture/qgstreamercaptureservice.cpp | 7 +-- .../mediacapture/qgstreamercapturesession.cpp | 37 +++--------- .../mediacapture/qgstreamercapturesession.h | 10 ++-- .../mediaplayer/qgstreamerplayersession.cpp | 59 ++++++------------- .../mediaplayer/qgstreamerplayersession.h | 10 +++- src/plugins/gstreamer/qgstreamerbushelper.cpp | 66 ++++++++++++++++------ src/plugins/gstreamer/qgstreamerbushelper.h | 18 +++++- .../gstreamer/qgstreamergltexturerenderer.cpp | 29 ++++++---- .../gstreamer/qgstreamergltexturerenderer.h | 13 +++-- src/plugins/gstreamer/qgstreamervideorenderer.h | 1 - .../gstreamer/qgstreamervideorendererinterface.h | 5 -- src/plugins/gstreamer/qgstreamervideowidget.cpp | 32 ++++++++++- src/plugins/gstreamer/qgstreamervideowidget.h | 8 ++- src/plugins/gstreamer/qgstreamervideowindow.cpp | 13 ++++- src/plugins/gstreamer/qgstreamervideowindow.h | 9 ++- 20 files changed, 210 insertions(+), 164 deletions(-) (limited to 'src') diff --git a/src/plugins/gstreamer/camerabin/camerabinimagecapture.cpp b/src/plugins/gstreamer/camerabin/camerabinimagecapture.cpp index 910c6c2ce..f27cd7f35 100644 --- a/src/plugins/gstreamer/camerabin/camerabinimagecapture.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinimagecapture.cpp @@ -82,8 +82,8 @@ CameraBinImageCapture::CameraBinImageCapture(CameraBinSession *session) connect(m_session, SIGNAL(stateChanged(QCamera::State)), SLOT(updateState())); connect(m_session, SIGNAL(imageExposed(int)), this, SIGNAL(imageExposed(int))); connect(m_session, SIGNAL(imageCaptured(int,QImage)), this, SIGNAL(imageCaptured(int,QImage))); - connect(m_session, SIGNAL(busMessage(QGstreamerMessage)), SLOT(handleBusMessage(QGstreamerMessage))); + m_session->bus()->installMessageFilter(this); g_signal_connect(G_OBJECT(m_session->cameraBin()), IMAGE_DONE_SIGNAL, G_CALLBACK(handleImageSaved), this); } @@ -281,7 +281,7 @@ gboolean CameraBinImageCapture::jpegBufferProbe(GstPad *pad, GstBuffer *buffer, return destination & QCameraImageCapture::CaptureToFile; } -void CameraBinImageCapture::handleBusMessage(const QGstreamerMessage &message) +bool CameraBinImageCapture::processBusMessage(const QGstreamerMessage &message) { //Install metadata event and buffer probes @@ -298,7 +298,7 @@ void CameraBinImageCapture::handleBusMessage(const QGstreamerMessage &message) if (newState == GST_STATE_READY) { GstElement *element = GST_ELEMENT(GST_MESSAGE_SRC(gm)); if (!element) - return; + return false; QString elementName = QString::fromLatin1(gst_element_get_name(element)); if (elementName.contains("jpegenc") && element != m_jpegEncoderElement) { @@ -339,4 +339,6 @@ void CameraBinImageCapture::handleBusMessage(const QGstreamerMessage &message) } } } + + return false; } diff --git a/src/plugins/gstreamer/camerabin/camerabinimagecapture.h b/src/plugins/gstreamer/camerabin/camerabinimagecapture.h index 6cc910dbe..ddb04e1ea 100644 --- a/src/plugins/gstreamer/camerabin/camerabinimagecapture.h +++ b/src/plugins/gstreamer/camerabin/camerabinimagecapture.h @@ -48,9 +48,10 @@ QT_USE_NAMESPACE -class CameraBinImageCapture : public QCameraImageCaptureControl +class CameraBinImageCapture : public QCameraImageCaptureControl, public QGstreamerBusMessageFilter { Q_OBJECT + Q_INTERFACES(QGstreamerBusMessageFilter) public: CameraBinImageCapture(CameraBinSession *session); virtual ~CameraBinImageCapture(); @@ -62,9 +63,10 @@ public: int capture(const QString &fileName); void cancelCapture(); + bool processBusMessage(const QGstreamerMessage &message); + private slots: void updateState(); - void handleBusMessage(const QGstreamerMessage &message); private: static gboolean metadataEventProbe(GstPad *pad, GstEvent *event, CameraBinImageCapture *); diff --git a/src/plugins/gstreamer/camerabin/camerabinservice.cpp b/src/plugins/gstreamer/camerabin/camerabinservice.cpp index 75d820bfd..93bcc6993 100644 --- a/src/plugins/gstreamer/camerabin/camerabinservice.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinservice.cpp @@ -160,17 +160,16 @@ QMediaControl *CameraBinService::requestControl(const char *name) if (!m_videoOutput) { if (qstrcmp(name, QVideoRendererControl_iid) == 0) { m_videoOutput = m_videoRenderer; - m_captureSession->setViewfinder(m_videoRenderer); } else if (qstrcmp(name, QVideoWindowControl_iid) == 0) { m_videoOutput = m_videoWindow; - m_captureSession->setViewfinder(m_videoWindow); } else if (qstrcmp(name, QVideoWidgetControl_iid) == 0) { - m_captureSession->setViewfinder(m_videoWidgetControl); m_videoOutput = m_videoWidgetControl; } - if (m_videoOutput) + if (m_videoOutput) { + m_captureSession->setViewfinder(m_videoOutput); return m_videoOutput; + } } if (qstrcmp(name,QAudioEndpointSelector_iid) == 0) diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.cpp b/src/plugins/gstreamer/camerabin/camerabinsession.cpp index d1552c0af..fbcc85266 100644 --- a/src/plugins/gstreamer/camerabin/camerabinsession.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinsession.cpp @@ -145,8 +145,8 @@ CameraBinSession::CameraBinSession(QObject *parent) m_bus = gst_element_get_bus(m_pipeline); m_busHelper = new QGstreamerBusHelper(m_bus, this); - m_busHelper->installSyncEventFilter(this); - connect(m_busHelper, SIGNAL(message(QGstreamerMessage)), SLOT(handleBusMessage(QGstreamerMessage))); + m_busHelper->installMessageFilter(this); + m_audioEncodeControl = new CameraBinAudioEncoder(this); m_videoEncodeControl = new CameraBinVideoEncoder(this); m_imageEncodeControl = new CameraBinImageEncoder(this); @@ -534,6 +534,8 @@ void CameraBinSession::setViewfinder(QObject *viewfinder) this, SLOT(handleViewfinderChange())); disconnect(m_viewfinder, SIGNAL(readyChanged(bool)), this, SIGNAL(readyChanged(bool))); + + m_busHelper->removeMessageFilter(m_viewfinder); } m_viewfinder = viewfinder; @@ -544,6 +546,8 @@ void CameraBinSession::setViewfinder(QObject *viewfinder) this, SLOT(handleViewfinderChange())); connect(m_viewfinder, SIGNAL(readyChanged(bool)), this, SIGNAL(readyChanged(bool))); + + m_busHelper->installMessageFilter(m_viewfinder); } emit viewfinderChanged(); @@ -795,24 +799,14 @@ bool CameraBinSession::processSyncMessage(const QGstreamerMessage &message) } } - if (gst_structure_has_name(gm->structure, "prepare-xwindow-id")) { - if (m_viewfinderInterface) - m_viewfinderInterface->precessNewStream(); - - return true; - } - if (gst_structure_has_name(gm->structure, GST_PHOTOGRAPHY_AUTOFOCUS_DONE)) m_cameraFocusControl->handleFocusMessage(gm); - - if (m_viewfinderInterface && GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_viewfinderElement)) - m_viewfinderInterface->handleSyncMessage(gm); } return false; } -void CameraBinSession::handleBusMessage(const QGstreamerMessage &message) +bool CameraBinSession::processBusMessage(const QGstreamerMessage &message) { GstMessage* gm = message.rawMessage(); @@ -911,12 +905,9 @@ void CameraBinSession::handleBusMessage(const QGstreamerMessage &message) } //qDebug() << "New session state:" << ENUM_NAME(CameraBinSession,"State",m_state); } - - if (m_viewfinderInterface && GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_viewfinderElement)) - m_viewfinderInterface->handleBusMessage(gm); - - emit busMessage(message); } + + return false; } void CameraBinSession::recordVideo() diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.h b/src/plugins/gstreamer/camerabin/camerabinsession.h index 5504bb505..cc646cbfd 100644 --- a/src/plugins/gstreamer/camerabin/camerabinsession.h +++ b/src/plugins/gstreamer/camerabin/camerabinsession.h @@ -76,10 +76,13 @@ public: virtual GstElement *buildElement() = 0; }; -class CameraBinSession : public QObject, public QGstreamerSyncEventFilter +class CameraBinSession : public QObject, + public QGstreamerBusMessageFilter, + public QGstreamerSyncMessageFilter { Q_OBJECT Q_PROPERTY(qint64 duration READ duration NOTIFY durationChanged) + Q_INTERFACES(QGstreamerBusMessageFilter QGstreamerSyncMessageFilter) public: enum CameraRole { FrontCamera, // Secondary camera @@ -91,6 +94,7 @@ public: GstPhotography *photography(); GstElement *cameraBin() { return m_pipeline; } + QGstreamerBusHelper *bus() { return m_busHelper; } CameraRole cameraRole() const; @@ -146,6 +150,7 @@ public: bool isMuted() const; bool processSyncMessage(const QGstreamerMessage &message); + bool processBusMessage(const QGstreamerMessage &message); signals: void stateChanged(QCamera::State state); @@ -157,7 +162,6 @@ signals: void viewfinderChanged(); void readyChanged(bool); void busyChanged(bool); - void busMessage(const QGstreamerMessage &message); public slots: void setDevice(const QString &device); @@ -167,7 +171,6 @@ public slots: void setMuted(bool); private slots: - void handleBusMessage(const QGstreamerMessage &message); void handleViewfinderChange(); private: diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp index eb4338b3f..d063b0e13 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp @@ -160,17 +160,16 @@ QMediaControl *QGstreamerCaptureService::requestControl(const char *name) if (!m_videoOutput) { if (qstrcmp(name, QVideoRendererControl_iid) == 0) { m_videoOutput = m_videoRenderer; - m_captureSession->setVideoPreview(m_videoRenderer); } else if (qstrcmp(name, QVideoWindowControl_iid) == 0) { m_videoOutput = m_videoWindow; - m_captureSession->setVideoPreview(m_videoWindow); } else if (qstrcmp(name, QVideoWidgetControl_iid) == 0) { - m_captureSession->setVideoPreview(m_videoWidgetControl); m_videoOutput = m_videoWidgetControl; } - if (m_videoOutput) + if (m_videoOutput) { + m_captureSession->setVideoPreview(m_videoOutput); return m_videoOutput; + } } return 0; diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp index b092af281..b685f5466 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp @@ -96,8 +96,8 @@ QGstreamerCaptureSession::QGstreamerCaptureSession(QGstreamerCaptureSession::Cap m_bus = gst_element_get_bus(m_pipeline); m_busHelper = new QGstreamerBusHelper(m_bus, this); - m_busHelper->installSyncEventFilter(this); - connect(m_busHelper, SIGNAL(message(QGstreamerMessage)), SLOT(busMessage(QGstreamerMessage))); + m_busHelper->installMessageFilter(this); + m_audioEncodeControl = new QGstreamerAudioEncode(this); m_videoEncodeControl = new QGstreamerVideoEncode(this); m_imageEncodeControl = new QGstreamerImageEncode(this); @@ -735,6 +735,8 @@ void QGstreamerCaptureSession::setVideoPreview(QObject *viewfinder) this, SIGNAL(viewfinderChanged())); disconnect(m_viewfinder, SIGNAL(readyChanged(bool)), this, SIGNAL(readyChanged(bool))); + + m_busHelper->removeMessageFilter(m_viewfinder); } m_viewfinder = viewfinder; @@ -745,6 +747,8 @@ void QGstreamerCaptureSession::setVideoPreview(QObject *viewfinder) this, SIGNAL(viewfinderChanged())); connect(m_viewfinder, SIGNAL(readyChanged(bool)), this, SIGNAL(readyChanged(bool))); + + m_busHelper->installMessageFilter(m_viewfinder); } emit viewfinderChanged(); @@ -917,29 +921,7 @@ void QGstreamerCaptureSession::setMetaData(const QMap &dat } } -bool QGstreamerCaptureSession::processSyncMessage(const QGstreamerMessage &message) -{ - GstMessage* gm = message.rawMessage(); - - if (gm && GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) { - if (GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_videoPreview)) - m_viewfinderInterface->handleSyncMessage(gm); - - if (gst_structure_has_name(gm->structure, "prepare-xwindow-id")) { - if (m_audioPreviewFactory) - m_audioPreviewFactory->prepareWinId(); - - if (m_viewfinderInterface) - m_viewfinderInterface->precessNewStream(); - - return true; - } - } - - return false; -} - -void QGstreamerCaptureSession::busMessage(const QGstreamerMessage &message) +bool QGstreamerCaptureSession::processBusMessage(const QGstreamerMessage &message) { GstMessage* gm = message.rawMessage(); @@ -1027,11 +1009,8 @@ void QGstreamerCaptureSession::busMessage(const QGstreamerMessage &message) } //qDebug() << "New session state:" << ENUM_NAME(QGstreamerCaptureSession,"State",m_state); } - - if (m_videoPreview && m_viewfinderInterface && - GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_videoPreview)) - m_viewfinderInterface->handleBusMessage(gm); } + return false; } void QGstreamerCaptureSession::setMuted(bool muted) diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h index 63d1b0bf6..e4c734600 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h +++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h @@ -76,12 +76,13 @@ public: virtual QList supportedResolutions(qreal frameRate = -1) const = 0; }; -class QGstreamerCaptureSession : public QObject, public QGstreamerSyncEventFilter +class QGstreamerCaptureSession : public QObject, public QGstreamerBusMessageFilter { Q_OBJECT Q_PROPERTY(qint64 duration READ duration NOTIFY durationChanged) Q_ENUMS(State) Q_ENUMS(CaptureMode) + Q_INTERFACES(QGstreamerBusMessageFilter) public: enum CaptureMode { Audio = 1, Video = 2, Image=4, AudioAndVideo = Audio | Video }; enum State { StoppedState, PreviewState, PausedState, RecordingState }; @@ -89,6 +90,8 @@ public: QGstreamerCaptureSession(CaptureMode captureMode, QObject *parent); ~QGstreamerCaptureSession(); + QGstreamerBusHelper *bus() { return m_busHelper; } + CaptureMode captureMode() const { return m_captureMode; } void setCaptureMode(CaptureMode); @@ -122,7 +125,7 @@ public: bool isReady() const; - bool processSyncMessage(const QGstreamerMessage &message); + bool processBusMessage(const QGstreamerMessage &message); signals: void stateChanged(QGstreamerCaptureSession::State state); @@ -144,9 +147,6 @@ public slots: void setMetaData(const QMap&); void setMuted(bool); -private slots: - void busMessage(const QGstreamerMessage &message); - private: enum PipelineMode { EmptyPipeline, PreviewPipeline, RecordingPipeline, PreviewAndRecordingPipeline }; diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp index 7cb5a661b..9e4e8bc69 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp @@ -155,8 +155,7 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent) // Sort out messages m_bus = gst_element_get_bus(m_playbin); m_busHelper = new QGstreamerBusHelper(m_bus, this); - connect(m_busHelper, SIGNAL(message(QGstreamerMessage)), SLOT(busMessage(QGstreamerMessage))); - m_busHelper->installSyncEventFilter(this); + m_busHelper->installMessageFilter(this); g_object_set(G_OBJECT(m_playbin), "video-sink", m_videoOutputBin, NULL); @@ -188,6 +187,11 @@ QGstreamerPlayerSession::~QGstreamerPlayerSession() } } +GstElement *QGstreamerPlayerSession::playbin() const +{ + return m_playbin; +} + #if defined(HAVE_GST_APPSRC) void QGstreamerPlayerSession::configureAppSrcElement(GObject* object, GObject *orig, GParamSpec *pspec, QGstreamerPlayerSession* self) { @@ -444,16 +448,20 @@ void QGstreamerPlayerSession::setVideoRenderer(QObject *videoOutput) this, SLOT(updateVideoRenderer())); disconnect(m_videoOutput, SIGNAL(readyChanged(bool)), this, SLOT(updateVideoRenderer())); + + m_busHelper->removeMessageFilter(m_videoOutput); } - if (videoOutput) { - connect(videoOutput, SIGNAL(sinkChanged()), + m_videoOutput = videoOutput; + + if (m_videoOutput) { + connect(m_videoOutput, SIGNAL(sinkChanged()), this, SLOT(updateVideoRenderer())); - connect(videoOutput, SIGNAL(readyChanged(bool)), + connect(m_videoOutput, SIGNAL(readyChanged(bool)), this, SLOT(updateVideoRenderer())); - } - m_videoOutput = videoOutput; + m_busHelper->installMessageFilter(m_videoOutput); + } } QGstreamerVideoRendererInterface* renderer = qobject_cast(videoOutput); @@ -877,29 +885,9 @@ void QGstreamerPlayerSession::setSeekable(bool seekable) } } -bool QGstreamerPlayerSession::processSyncMessage(const QGstreamerMessage &message) +bool QGstreamerPlayerSession::processBusMessage(const QGstreamerMessage &message) { GstMessage* gm = message.rawMessage(); - - if (gm && GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) { - if (m_renderer) { - if (GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_videoSink)) - m_renderer->handleSyncMessage(gm); - - if (gst_structure_has_name(gm->structure, "prepare-xwindow-id")) { - m_renderer->precessNewStream(); - return true; - } - } - } - - return false; -} - -void QGstreamerPlayerSession::busMessage(const QGstreamerMessage &message) -{ - GstMessage* gm = message.rawMessage(); - if (gm) { //tag message comes from elements inside playbin, not from playbin itself if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_TAG) { @@ -1111,19 +1099,6 @@ void QGstreamerPlayerSession::busMessage(const QGstreamerMessage &message) default: break; } - } else if (m_videoSink - && m_renderer - && GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_videoSink)) { - - m_renderer->handleBusMessage(gm); - if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_STATE_CHANGED) { - GstState oldState; - GstState newState; - gst_message_parse_state_changed(gm, &oldState, &newState, 0); - - if (oldState == GST_STATE_READY && newState == GST_STATE_PAUSED) - m_renderer->precessNewStream(); - } } else if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ERROR) { GError *err; gchar *debug; @@ -1196,6 +1171,8 @@ void QGstreamerPlayerSession::busMessage(const QGstreamerMessage &message) } } } + + return false; } void QGstreamerPlayerSession::getStreamsInfo() diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h index be32f5f79..297754b93 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h @@ -62,14 +62,19 @@ class QGstreamerVideoRendererInterface; QT_USE_NAMESPACE -class QGstreamerPlayerSession : public QObject, public QGstreamerSyncEventFilter +class QGstreamerPlayerSession : public QObject, + public QGstreamerBusMessageFilter { Q_OBJECT +Q_INTERFACES(QGstreamerBusMessageFilter) public: QGstreamerPlayerSession(QObject *parent); virtual ~QGstreamerPlayerSession(); + GstElement *playbin() const; + QGstreamerBusHelper *bus() const { return m_busHelper; } + QNetworkRequest request() const; QMediaPlayer::State state() const { return m_state; } @@ -105,7 +110,7 @@ public: int activeStream(QMediaStreamsControl::StreamType streamType) const; void setActiveStream(QMediaStreamsControl::StreamType streamType, int streamNumber); - bool processSyncMessage(const QGstreamerMessage &message); + bool processBusMessage(const QGstreamerMessage &message); #if defined(HAVE_GST_APPSRC) QGstAppSrc *appsrc() const { return m_appSrc; } @@ -145,7 +150,6 @@ signals: void playbackRateChanged(qreal); private slots: - void busMessage(const QGstreamerMessage &message); void getStreamsInfo(); void setSeekable(bool); void finishVideoOutputChange(); diff --git a/src/plugins/gstreamer/qgstreamerbushelper.cpp b/src/plugins/gstreamer/qgstreamerbushelper.cpp index 76cc83ada..92f2ee8b7 100644 --- a/src/plugins/gstreamer/qgstreamerbushelper.cpp +++ b/src/plugins/gstreamer/qgstreamerbushelper.cpp @@ -39,9 +39,10 @@ ** ****************************************************************************/ -#include -#include -#include +#include +#include +#include +#include #include "qgstreamerbushelper.h" @@ -57,7 +58,6 @@ public: setParent(helper); m_tag = gst_bus_add_watch_full(bus, 0, busCallback, this, NULL); m_helper = helper; - filter = 0; } void removeWatch(QGstreamerBusHelper* helper) @@ -75,7 +75,12 @@ private: void processMessage(GstBus* bus, GstMessage* message) { Q_UNUSED(bus); - emit m_helper->message(message); + QGstreamerMessage msg(message); + foreach (QGstreamerBusMessageFilter *filter, busFilters) { + if (filter->processBusMessage(msg)) + break; + } + emit m_helper->message(msg); } static gboolean busCallback(GstBus *bus, GstMessage *message, gpointer data) @@ -89,8 +94,9 @@ private: public: GstBus* bus; - QGstreamerSyncEventFilter *filter; QMutex filterMutex; + QList syncFilters; + QList busFilters; }; #else @@ -131,7 +137,13 @@ private slots: GstMessage* message; while ((message = gst_bus_poll(it.value(), GST_MESSAGE_ANY, 0)) != 0) { - emit it.key()->message(message); + QGstreamerMessage msg(message); + foreach (QGstreamerBusMessageFilter *filter, busFilters) { + if (filter->processBusMessage(msg)) + break; + } + emit it.key()->message(msg); + gst_message_unref(message); } @@ -153,8 +165,9 @@ private: public: GstBus* bus; - QGstreamerSyncEventFilter *filter; QMutex filterMutex; + QList syncFilters; + QList busFilters; }; #endif @@ -164,12 +177,12 @@ static GstBusSyncReply syncGstBusFilter(GstBus* bus, GstMessage* message, QGstre Q_UNUSED(bus); QMutexLocker lock(&d->filterMutex); - bool res = false; - - if (d->filter) - res = d->filter->processSyncMessage(QGstreamerMessage(message)); + foreach (QGstreamerSyncMessageFilter *filter, d->syncFilters) { + if (filter->processSyncMessage(QGstreamerMessage(message))) + return GST_BUS_DROP; + } - return res ? GST_BUS_DROP : GST_BUS_PASS; + return GST_BUS_PASS; } @@ -194,10 +207,31 @@ QGstreamerBusHelper::~QGstreamerBusHelper() gst_bus_set_sync_handler(d->bus,0,0); } -void QGstreamerBusHelper::installSyncEventFilter(QGstreamerSyncEventFilter *filter) +void QGstreamerBusHelper::installMessageFilter(QObject *filter) { - QMutexLocker lock(&d->filterMutex); - d->filter = filter; + QGstreamerSyncMessageFilter *syncFilter = qobject_cast(filter); + if (syncFilter) { + QMutexLocker lock(&d->filterMutex); + if (!d->syncFilters.contains(syncFilter)) + d->syncFilters.append(syncFilter); + } + + QGstreamerBusMessageFilter *busFilter = qobject_cast(filter); + if (busFilter && !d->busFilters.contains(busFilter)) + d->busFilters.append(busFilter); +} + +void QGstreamerBusHelper::removeMessageFilter(QObject *filter) +{ + QGstreamerSyncMessageFilter *syncFilter = qobject_cast(filter); + if (syncFilter) { + QMutexLocker lock(&d->filterMutex); + d->syncFilters.removeAll(syncFilter); + } + + QGstreamerBusMessageFilter *busFilter = qobject_cast(filter); + if (busFilter) + d->busFilters.removeAll(busFilter); } #include "qgstreamerbushelper.moc" diff --git a/src/plugins/gstreamer/qgstreamerbushelper.h b/src/plugins/gstreamer/qgstreamerbushelper.h index cfe6a6b1c..d09192a42 100644 --- a/src/plugins/gstreamer/qgstreamerbushelper.h +++ b/src/plugins/gstreamer/qgstreamerbushelper.h @@ -47,11 +47,23 @@ #include #include -class QGstreamerSyncEventFilter { +class QGstreamerSyncMessageFilter { public: //returns true if message was processed and should be dropped, false otherwise virtual bool processSyncMessage(const QGstreamerMessage &message) = 0; }; +#define QGstreamerSyncMessageFilter_iid "com.nokia.Qt.QGstreamerSyncMessageFilter/1.0" +Q_DECLARE_INTERFACE(QGstreamerSyncMessageFilter, QGstreamerSyncMessageFilter_iid) + + +class QGstreamerBusMessageFilter { +public: + //returns true if message was processed and should be dropped, false otherwise + virtual bool processBusMessage(const QGstreamerMessage &message) = 0; +}; +#define QGstreamerBusMessageFilter_iid "com.nokia.Qt.QGstreamerBusMessageFilter/1.0" +Q_DECLARE_INTERFACE(QGstreamerBusMessageFilter, QGstreamerBusMessageFilter_iid) + class QGstreamerBusHelperPrivate; @@ -64,12 +76,12 @@ public: QGstreamerBusHelper(GstBus* bus, QObject* parent = 0); ~QGstreamerBusHelper(); - void installSyncEventFilter(QGstreamerSyncEventFilter *filter); + void installMessageFilter(QObject *filter); + void removeMessageFilter(QObject *filter); signals: void message(QGstreamerMessage const& message); - private: QGstreamerBusHelperPrivate* d; }; diff --git a/src/plugins/gstreamer/qgstreamergltexturerenderer.cpp b/src/plugins/gstreamer/qgstreamergltexturerenderer.cpp index 2f5919f83..af68096bd 100644 --- a/src/plugins/gstreamer/qgstreamergltexturerenderer.cpp +++ b/src/plugins/gstreamer/qgstreamergltexturerenderer.cpp @@ -364,13 +364,16 @@ bool QGstreamerGLTextureRenderer::isReady() const return m_surface->supportedPixelFormats(EGLImageTextureHandle).isEmpty(); } -void QGstreamerGLTextureRenderer::handleBusMessage(GstMessage* gm) +bool QGstreamerGLTextureRenderer::processBusMessage(const QGstreamerMessage &message) { + GstMessage* gm = message.rawMessage(); + #ifdef GL_TEXTURE_SINK_DEBUG qDebug() << Q_FUNC_INFO << GST_MESSAGE_TYPE_NAME(gm); #endif - if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_STATE_CHANGED) { + if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_STATE_CHANGED && + GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_videoSink)) { GstState oldState; GstState newState; gst_message_parse_state_changed(gm, &oldState, &newState, 0); @@ -387,22 +390,20 @@ void QGstreamerGLTextureRenderer::handleBusMessage(GstMessage* gm) updateNativeVideoSize(); } } + + return false; } -void QGstreamerGLTextureRenderer::handleSyncMessage(GstMessage* gm) +bool QGstreamerGLTextureRenderer::processSyncMessage(const QGstreamerMessage &message) { + GstMessage* gm = message.rawMessage(); + + if ((GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) && + gst_structure_has_name(gm->structure, "prepare-xwindow-id") && + m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) { #ifdef GL_TEXTURE_SINK_DEBUG qDebug() << Q_FUNC_INFO; #endif - - if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT && - gst_structure_has_name(gm->structure, "prepare-xwindow-id")) - precessNewStream(); -} - -void QGstreamerGLTextureRenderer::precessNewStream() -{ - if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) { GstXOverlay *overlay = GST_X_OVERLAY(m_videoSink); gst_x_overlay_set_xwindow_id(overlay, m_winId); @@ -417,7 +418,11 @@ void QGstreamerGLTextureRenderer::precessNewStream() GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink"); m_bufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padBufferProbe), this); + + return true; } + + return false; } void QGstreamerGLTextureRenderer::stopRenderer() diff --git a/src/plugins/gstreamer/qgstreamergltexturerenderer.h b/src/plugins/gstreamer/qgstreamergltexturerenderer.h index 330fb4630..7a1bc65df 100644 --- a/src/plugins/gstreamer/qgstreamergltexturerenderer.h +++ b/src/plugins/gstreamer/qgstreamergltexturerenderer.h @@ -44,6 +44,7 @@ #include #include "qvideosurfacegstsink.h" +#include "qgstreamerbushelper.h" #include "qgstreamervideorendererinterface.h" #include @@ -54,10 +55,13 @@ QT_USE_NAMESPACE class QGLContext; -class QGstreamerGLTextureRenderer : public QVideoRendererControl, public QGstreamerVideoRendererInterface +class QGstreamerGLTextureRenderer : public QVideoRendererControl, + public QGstreamerVideoRendererInterface, + public QGstreamerSyncMessageFilter, + public QGstreamerBusMessageFilter { Q_OBJECT - Q_INTERFACES(QGstreamerVideoRendererInterface) + Q_INTERFACES(QGstreamerVideoRendererInterface QGstreamerSyncMessageFilter QGstreamerBusMessageFilter) Q_PROPERTY(bool overlayEnabled READ overlayEnabled WRITE setOverlayEnabled) Q_PROPERTY(qulonglong winId READ winId WRITE setWinId) @@ -75,9 +79,8 @@ public: GstElement *videoSink(); bool isReady() const; - void handleBusMessage(GstMessage* gm); - void handleSyncMessage(GstMessage* gm); - void precessNewStream(); + bool processBusMessage(const QGstreamerMessage &message); + bool processSyncMessage(const QGstreamerMessage &message); void stopRenderer(); int framebufferNumber() const; diff --git a/src/plugins/gstreamer/qgstreamervideorenderer.h b/src/plugins/gstreamer/qgstreamervideorenderer.h index 298ad9448..4fb8dda35 100644 --- a/src/plugins/gstreamer/qgstreamervideorenderer.h +++ b/src/plugins/gstreamer/qgstreamervideorenderer.h @@ -61,7 +61,6 @@ public: void setSurface(QAbstractVideoSurface *surface); GstElement *videoSink(); - void precessNewStream() {} bool isReady() const { return m_surface != 0; } diff --git a/src/plugins/gstreamer/qgstreamervideorendererinterface.h b/src/plugins/gstreamer/qgstreamervideorendererinterface.h index 600f0dfe5..da5107e07 100644 --- a/src/plugins/gstreamer/qgstreamervideorendererinterface.h +++ b/src/plugins/gstreamer/qgstreamervideorendererinterface.h @@ -51,7 +51,6 @@ class QGstreamerVideoRendererInterface public: virtual ~QGstreamerVideoRendererInterface(); virtual GstElement *videoSink() = 0; - virtual void precessNewStream() {} //stopRenderer() is called when the renderer element is stopped. //it can be reimplemented when video renderer can't detect @@ -62,10 +61,6 @@ public: //(winId is known, virtual bool isReady() const { return true; } - //video renderer may handle video sink specific gstreamer messages. - virtual void handleBusMessage(GstMessage*) {}; - virtual void handleSyncMessage(GstMessage*) {}; - //signals: //void sinkChanged(); //void readyChanged(bool); diff --git a/src/plugins/gstreamer/qgstreamervideowidget.cpp b/src/plugins/gstreamer/qgstreamervideowidget.cpp index 2f92e990a..e1bf0037d 100644 --- a/src/plugins/gstreamer/qgstreamervideowidget.cpp +++ b/src/plugins/gstreamer/qgstreamervideowidget.cpp @@ -179,10 +179,36 @@ bool QGstreamerVideoWidgetControl::eventFilter(QObject *object, QEvent *e) return false; } -void QGstreamerVideoWidgetControl::precessNewStream() +bool QGstreamerVideoWidgetControl::processSyncMessage(const QGstreamerMessage &message) { - setOverlay(); - QMetaObject::invokeMethod(this, "updateNativeVideoSize", Qt::QueuedConnection); + GstMessage* gm = message.rawMessage(); + + if (gm && (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) && + gst_structure_has_name(gm->structure, "prepare-xwindow-id")) { + + setOverlay(); + QMetaObject::invokeMethod(this, "updateNativeVideoSize", Qt::QueuedConnection); + return true; + } + + return false; +} + +bool QGstreamerVideoWidgetControl::processBusMessage(const QGstreamerMessage &message) +{ + GstMessage* gm = message.rawMessage(); + + if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_STATE_CHANGED && + GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_videoSink)) { + GstState oldState; + GstState newState; + gst_message_parse_state_changed(gm, &oldState, &newState, 0); + + if (oldState == GST_STATE_READY && newState == GST_STATE_PAUSED) + updateNativeVideoSize(); + } + + return false; } void QGstreamerVideoWidgetControl::setOverlay() diff --git a/src/plugins/gstreamer/qgstreamervideowidget.h b/src/plugins/gstreamer/qgstreamervideowidget.h index 0f0adea0d..8f3d62316 100644 --- a/src/plugins/gstreamer/qgstreamervideowidget.h +++ b/src/plugins/gstreamer/qgstreamervideowidget.h @@ -45,6 +45,7 @@ #include #include "qgstreamervideorendererinterface.h" +#include "qgstreamerbushelper.h" QT_USE_NAMESPACE @@ -53,15 +54,16 @@ class QGstreamerVideoWidget; class QGstreamerVideoWidgetControl : public QVideoWidgetControl , public QGstreamerVideoRendererInterface + , public QGstreamerSyncMessageFilter + , public QGstreamerBusMessageFilter { Q_OBJECT - Q_INTERFACES(QGstreamerVideoRendererInterface) + Q_INTERFACES(QGstreamerVideoRendererInterface QGstreamerSyncMessageFilter QGstreamerBusMessageFilter) public: QGstreamerVideoWidgetControl(QObject *parent = 0); virtual ~QGstreamerVideoWidgetControl(); GstElement *videoSink(); - void precessNewStream(); QWidget *videoWidget(); @@ -86,6 +88,8 @@ public: void setOverlay(); bool eventFilter(QObject *object, QEvent *event); + bool processSyncMessage(const QGstreamerMessage &message); + bool processBusMessage(const QGstreamerMessage &message); public slots: void updateNativeVideoSize(); diff --git a/src/plugins/gstreamer/qgstreamervideowindow.cpp b/src/plugins/gstreamer/qgstreamervideowindow.cpp index 0f92d76a9..d8d822269 100644 --- a/src/plugins/gstreamer/qgstreamervideowindow.cpp +++ b/src/plugins/gstreamer/qgstreamervideowindow.cpp @@ -115,14 +115,23 @@ void QGstreamerVideoWindow::setWinId(WId id) emit readyChanged(false); } -void QGstreamerVideoWindow::precessNewStream() +bool QGstreamerVideoWindow::processSyncMessage(const QGstreamerMessage &message) { - if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) { + GstMessage* gm = message.rawMessage(); + + if ((GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) && + gst_structure_has_name(gm->structure, "prepare-xwindow-id") && + m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) { + gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(m_videoSink), m_windowId); GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink"); m_bufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padBufferProbe), this); + + return true; } + + return false; } QRect QGstreamerVideoWindow::displayRect() const diff --git a/src/plugins/gstreamer/qgstreamervideowindow.h b/src/plugins/gstreamer/qgstreamervideowindow.h index acc22cdca..3a483e2c1 100644 --- a/src/plugins/gstreamer/qgstreamervideowindow.h +++ b/src/plugins/gstreamer/qgstreamervideowindow.h @@ -45,6 +45,7 @@ #include #include "qgstreamervideorendererinterface.h" +#include "qgstreamerbushelper.h" QT_BEGIN_NAMESPACE class QAbstractVideoSurface; @@ -55,10 +56,12 @@ class QX11VideoSurface; QT_USE_NAMESPACE -class QGstreamerVideoWindow : public QVideoWindowControl, public QGstreamerVideoRendererInterface +class QGstreamerVideoWindow : public QVideoWindowControl, + public QGstreamerVideoRendererInterface, + public QGstreamerSyncMessageFilter { Q_OBJECT - Q_INTERFACES(QGstreamerVideoRendererInterface) + Q_INTERFACES(QGstreamerVideoRendererInterface QGstreamerSyncMessageFilter) Q_PROPERTY(QColor colorKey READ colorKey WRITE setColorKey) Q_PROPERTY(bool autopaintColorKey READ autopaintColorKey WRITE setAutopaintColorKey) public: @@ -103,7 +106,7 @@ public: GstElement *videoSink(); - void precessNewStream(); + bool processSyncMessage(const QGstreamerMessage &message); bool isReady() const { return m_windowId != 0; } signals: -- cgit v1.2.3