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 <qt_sanity_bot@ovi.com>
Reviewed-by: Michael Goddard <michael.goddard@nokia.com>
This commit is contained in:
Dmytro Poplavskiy
2011-08-02 14:33:38 +10:00
committed by Qt by Nokia
parent 6eac3bd648
commit e70ebfd2ed
20 changed files with 211 additions and 165 deletions

View File

@@ -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;
}

View File

@@ -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 *);

View File

@@ -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)

View File

@@ -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()

View File

@@ -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:

View File

@@ -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;

View File

@@ -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<QByteArray, QVariant> &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)

View File

@@ -76,12 +76,13 @@ public:
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 };
@@ -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<QByteArray, QVariant>&);
void setMuted(bool);
private slots:
void busMessage(const QGstreamerMessage &message);
private:
enum PipelineMode { EmptyPipeline, PreviewPipeline, RecordingPipeline, PreviewAndRecordingPipeline };

View File

@@ -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()));
}
if (videoOutput) {
connect(videoOutput, SIGNAL(sinkChanged()),
this, SLOT(updateVideoRenderer()));
connect(videoOutput, SIGNAL(readyChanged(bool)),
this, SLOT(updateVideoRenderer()));
m_busHelper->removeMessageFilter(m_videoOutput);
}
m_videoOutput = videoOutput;
if (m_videoOutput) {
connect(m_videoOutput, SIGNAL(sinkChanged()),
this, SLOT(updateVideoRenderer()));
connect(m_videoOutput, SIGNAL(readyChanged(bool)),
this, SLOT(updateVideoRenderer()));
m_busHelper->installMessageFilter(m_videoOutput);
}
}
QGstreamerVideoRendererInterface* renderer = qobject_cast<QGstreamerVideoRendererInterface*>(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()

View File

@@ -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();

View File

@@ -39,9 +39,10 @@
**
****************************************************************************/
#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"
@@ -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<QGstreamerSyncMessageFilter*> syncFilters;
QList<QGstreamerBusMessageFilter*> 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<QGstreamerSyncMessageFilter*> syncFilters;
QList<QGstreamerBusMessageFilter*> busFilters;
};
#endif
@@ -164,12 +177,12 @@ static GstBusSyncReply syncGstBusFilter(GstBus* bus, GstMessage* message, QGstre
Q_UNUSED(bus);
QMutexLocker lock(&d->filterMutex);
bool res = false;
foreach (QGstreamerSyncMessageFilter *filter, d->syncFilters) {
if (filter->processSyncMessage(QGstreamerMessage(message)))
return GST_BUS_DROP;
}
if (d->filter)
res = d->filter->processSyncMessage(QGstreamerMessage(message));
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<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"

View File

@@ -47,11 +47,23 @@
#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;
@@ -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;
};

View File

@@ -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()

View File

@@ -44,6 +44,7 @@
#include <qvideorenderercontrol.h>
#include "qvideosurfacegstsink.h"
#include "qgstreamerbushelper.h"
#include "qgstreamervideorendererinterface.h"
#include <QtGui/qcolor.h>
@@ -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;

View File

@@ -61,7 +61,6 @@ public:
void setSurface(QAbstractVideoSurface *surface);
GstElement *videoSink();
void precessNewStream() {}
bool isReady() const { return m_surface != 0; }

View File

@@ -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);

View File

@@ -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()

View File

@@ -45,6 +45,7 @@
#include <qvideowidgetcontrol.h>
#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();

View File

@@ -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

View File

@@ -45,6 +45,7 @@
#include <qvideowindowcontrol.h>
#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: