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:
committed by
Qt by Nokia
parent
6eac3bd648
commit
e70ebfd2ed
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 *);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 };
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -61,7 +61,6 @@ public:
|
||||
void setSurface(QAbstractVideoSurface *surface);
|
||||
|
||||
GstElement *videoSink();
|
||||
void precessNewStream() {}
|
||||
|
||||
bool isReady() const { return m_surface != 0; }
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user