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);
}
return destination & QCameraImageCapture::CaptureToFile;
}
-void CameraBinImageCapture::handleBusMessage(const QGstreamerMessage &message)
+bool CameraBinImageCapture::processBusMessage(const QGstreamerMessage &message)
{
//Install metadata event and buffer probes
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) {
}
}
}
+
+ return false;
}
QT_USE_NAMESPACE
-class CameraBinImageCapture : public QCameraImageCaptureControl
+class CameraBinImageCapture : public QCameraImageCaptureControl, public QGstreamerBusMessageFilter
{
Q_OBJECT
+ Q_INTERFACES(QGstreamerBusMessageFilter)
public:
CameraBinImageCapture(CameraBinSession *session);
virtual ~CameraBinImageCapture();
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 *);
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)
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);
this, SLOT(handleViewfinderChange()));
disconnect(m_viewfinder, SIGNAL(readyChanged(bool)),
this, SIGNAL(readyChanged(bool)));
+
+ m_busHelper->removeMessageFilter(m_viewfinder);
}
m_viewfinder = viewfinder;
this, SLOT(handleViewfinderChange()));
connect(m_viewfinder, SIGNAL(readyChanged(bool)),
this, SIGNAL(readyChanged(bool)));
+
+ m_busHelper->installMessageFilter(m_viewfinder);
}
emit viewfinderChanged();
}
}
- 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();
}
//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()
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
GstPhotography *photography();
GstElement *cameraBin() { return m_pipeline; }
+ QGstreamerBusHelper *bus() { return m_busHelper; }
CameraRole cameraRole() const;
bool isMuted() const;
bool processSyncMessage(const QGstreamerMessage &message);
+ bool processBusMessage(const QGstreamerMessage &message);
signals:
void stateChanged(QCamera::State state);
void viewfinderChanged();
void readyChanged(bool);
void busyChanged(bool);
- void busMessage(const QGstreamerMessage &message);
public slots:
void setDevice(const QString &device);
void setMuted(bool);
private slots:
- void handleBusMessage(const QGstreamerMessage &message);
void handleViewfinderChange();
private:
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;
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);
this, SIGNAL(viewfinderChanged()));
disconnect(m_viewfinder, SIGNAL(readyChanged(bool)),
this, SIGNAL(readyChanged(bool)));
+
+ m_busHelper->removeMessageFilter(m_viewfinder);
}
m_viewfinder = viewfinder;
this, SIGNAL(viewfinderChanged()));
connect(m_viewfinder, SIGNAL(readyChanged(bool)),
this, SIGNAL(readyChanged(bool)));
+
+ m_busHelper->installMessageFilter(m_viewfinder);
}
emit viewfinderChanged();
}
}
-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();
}
//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)
virtual QList<QSize> 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 };
QGstreamerCaptureSession(CaptureMode captureMode, QObject *parent);
~QGstreamerCaptureSession();
+ QGstreamerBusHelper *bus() { return m_busHelper; }
+
CaptureMode captureMode() const { return m_captureMode; }
void setCaptureMode(CaptureMode);
bool isReady() const;
- bool processSyncMessage(const QGstreamerMessage &message);
+ bool processBusMessage(const QGstreamerMessage &message);
signals:
void stateChanged(QGstreamerCaptureSession::State state);
void setMetaData(const QMap<QByteArray, QVariant>&);
void setMuted(bool);
-private slots:
- void busMessage(const QGstreamerMessage &message);
-
private:
enum PipelineMode { EmptyPipeline, PreviewPipeline, RecordingPipeline, PreviewAndRecordingPipeline };
// 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);
}
}
+GstElement *QGstreamerPlayerSession::playbin() const
+{
+ return m_playbin;
+}
+
#if defined(HAVE_GST_APPSRC)
void QGstreamerPlayerSession::configureAppSrcElement(GObject* object, GObject *orig, GParamSpec *pspec, QGstreamerPlayerSession* self)
{
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<QGstreamerVideoRendererInterface*>(videoOutput);
}
}
-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) {
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;
}
}
}
+
+ return false;
}
void QGstreamerPlayerSession::getStreamsInfo()
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; }
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; }
void playbackRateChanged(qreal);
private slots:
- void busMessage(const QGstreamerMessage &message);
void getStreamsInfo();
void setSeekable(bool);
void finishVideoOutputChange();
**
****************************************************************************/
-#include <QMap>
-#include <QTimer>
-#include <QMutex>
+#include <QtCore/qmap.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qlist.h>
#include "qgstreamerbushelper.h"
setParent(helper);
m_tag = gst_bus_add_watch_full(bus, 0, busCallback, this, NULL);
m_helper = helper;
- filter = 0;
}
void removeWatch(QGstreamerBusHelper* helper)
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)
public:
GstBus* bus;
- QGstreamerSyncEventFilter *filter;
QMutex filterMutex;
+ QList<QGstreamerSyncMessageFilter*> syncFilters;
+ QList<QGstreamerBusMessageFilter*> busFilters;
};
#else
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);
}
public:
GstBus* bus;
- QGstreamerSyncEventFilter *filter;
QMutex filterMutex;
+ QList<QGstreamerSyncMessageFilter*> syncFilters;
+ QList<QGstreamerBusMessageFilter*> busFilters;
};
#endif
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;
}
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<QGstreamerSyncMessageFilter*>(filter);
+ if (syncFilter) {
+ QMutexLocker lock(&d->filterMutex);
+ if (!d->syncFilters.contains(syncFilter))
+ d->syncFilters.append(syncFilter);
+ }
+
+ QGstreamerBusMessageFilter *busFilter = qobject_cast<QGstreamerBusMessageFilter*>(filter);
+ if (busFilter && !d->busFilters.contains(busFilter))
+ d->busFilters.append(busFilter);
+}
+
+void QGstreamerBusHelper::removeMessageFilter(QObject *filter)
+{
+ QGstreamerSyncMessageFilter *syncFilter = qobject_cast<QGstreamerSyncMessageFilter*>(filter);
+ if (syncFilter) {
+ QMutexLocker lock(&d->filterMutex);
+ d->syncFilters.removeAll(syncFilter);
+ }
+
+ QGstreamerBusMessageFilter *busFilter = qobject_cast<QGstreamerBusMessageFilter*>(filter);
+ if (busFilter)
+ d->busFilters.removeAll(busFilter);
}
#include "qgstreamerbushelper.moc"
#include <qgstreamermessage.h>
#include <gst/gst.h>
-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;
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;
};
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);
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);
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()
#include <qvideorenderercontrol.h>
#include "qvideosurfacegstsink.h"
+#include "qgstreamerbushelper.h"
#include "qgstreamervideorendererinterface.h"
#include <QtGui/qcolor.h>
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)
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;
void setSurface(QAbstractVideoSurface *surface);
GstElement *videoSink();
- void precessNewStream() {}
bool isReady() const { return m_surface != 0; }
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
//(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);
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()
#include <qvideowidgetcontrol.h>
#include "qgstreamervideorendererinterface.h"
+#include "qgstreamerbushelper.h"
QT_USE_NAMESPACE
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();
void setOverlay();
bool eventFilter(QObject *object, QEvent *event);
+ bool processSyncMessage(const QGstreamerMessage &message);
+ bool processBusMessage(const QGstreamerMessage &message);
public slots:
void updateNativeVideoSize();
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
#include <qvideowindowcontrol.h>
#include "qgstreamervideorendererinterface.h"
+#include "qgstreamerbushelper.h"
QT_BEGIN_NAMESPACE
class QAbstractVideoSurface;
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:
GstElement *videoSink();
- void precessNewStream();
+ bool processSyncMessage(const QGstreamerMessage &message);
bool isReady() const { return m_windowId != 0; }
signals: