From 16aef591875becad3e6f388af0a2f029cb68b775 Mon Sep 17 00:00:00 2001 From: Lev Zelenskiy Date: Wed, 15 Feb 2012 14:45:18 +1000 Subject: QMediaRecorder: GStreamer backend changes for media probing API. QGstreamerCaptureSession: Using GStreamer buffer probe to access media data. Change-Id: I2ee38e864fbd69fcba9efe90d4dcf138528e00c0 Reviewed-by: Michael Goddard --- .../mediacapture/qgstreamercaptureservice.cpp | 18 +++++ .../mediacapture/qgstreamercapturesession.cpp | 81 ++++++++++++++++++++++ .../mediacapture/qgstreamercapturesession.h | 14 ++++ 3 files changed, 113 insertions(+) (limited to 'src/plugins/gstreamer') diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp index 95b4444f3..405cc5778 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp @@ -54,6 +54,7 @@ #include "qgstreameraudioinputendpointselector.h" #include "qgstreamervideoinputdevicecontrol.h" #include "qgstreamerimagecapturecontrol.h" +#include "qgstreameraudioprobecontrol.h" #include "qgstreamervideorenderer.h" @@ -162,6 +163,15 @@ QMediaControl *QGstreamerCaptureService::requestControl(const char *name) if (qstrcmp(name, QCameraImageCaptureControl_iid) == 0) return m_imageCaptureControl; + if (qstrcmp(name,QMediaAudioProbeControl_iid) == 0) { + if (m_captureSession) { + QGstreamerAudioProbeControl *probe = new QGstreamerAudioProbeControl(this); + m_captureSession->addProbe(probe); + return probe; + } + return 0; + } + if (!m_videoOutput) { if (qstrcmp(name, QVideoRendererControl_iid) == 0) { m_videoOutput = m_videoRenderer; @@ -189,6 +199,14 @@ void QGstreamerCaptureService::releaseControl(QMediaControl *control) m_videoOutput = 0; m_captureSession->setVideoPreview(0); } + + QGstreamerAudioProbeControl* audioProbe = qobject_cast(control); + if (audioProbe) { + if (m_captureSession) + m_captureSession->removeProbe(audioProbe); + delete audioProbe; + return; + } } QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp index 68f4444cf..60cda07bc 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp @@ -46,6 +46,7 @@ #include "qgstreameraudioencode.h" #include "qgstreamervideoencode.h" #include "qgstreamerimageencode.h" +#include "qgstreameraudioprobecontrol.h" #include #include @@ -73,6 +74,7 @@ QGstreamerCaptureSession::QGstreamerCaptureSession(QGstreamerCaptureSession::Cap m_waitingForEos(false), m_pipelineMode(EmptyPipeline), m_captureMode(captureMode), + m_audioBufferProbeId(-1), m_audioInputFactory(0), m_audioPreviewFactory(0), m_videoInputFactory(0), @@ -530,6 +532,7 @@ void QGstreamerCaptureSession::captureImage(int requestId, const QString &fileNa bool QGstreamerCaptureSession::rebuildGraph(QGstreamerCaptureSession::PipelineMode newMode) { + removeAudioBufferProbe(); REMOVE_ELEMENT(m_audioSrc); REMOVE_ELEMENT(m_audioPreview); REMOVE_ELEMENT(m_audioPreviewQueue); @@ -669,6 +672,7 @@ bool QGstreamerCaptureSession::rebuildGraph(QGstreamerCaptureSession::PipelineMo } if (ok) { + addAudioBufferProbe(); m_pipelineMode = newMode; } else { m_pipelineMode = EmptyPipeline; @@ -1024,4 +1028,81 @@ void QGstreamerCaptureSession::setMuted(bool muted) } } +void QGstreamerCaptureSession::addProbe(QGstreamerAudioProbeControl* probe) +{ + QMutexLocker locker(&m_audioProbeMutex); + + if (m_audioProbes.contains(probe)) + return; + + m_audioProbes.append(probe); +} + +void QGstreamerCaptureSession::removeProbe(QGstreamerAudioProbeControl* probe) +{ + QMutexLocker locker(&m_audioProbeMutex); + m_audioProbes.removeOne(probe); +} + +gboolean QGstreamerCaptureSession::padAudioBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data) +{ + Q_UNUSED(pad); + + QGstreamerCaptureSession *session = reinterpret_cast(user_data); + QMutexLocker locker(&session->m_audioProbeMutex); + + if (session->m_audioProbes.isEmpty()) + return TRUE; + + foreach (QGstreamerAudioProbeControl* probe, session->m_audioProbes) + probe->bufferProbed(buffer); + + return TRUE; +} + +GstPad *QGstreamerCaptureSession::getAudioProbePad() +{ + // first see if preview element is available + if (m_audioPreview) { + GstPad *pad = gst_element_get_static_pad(m_audioPreview, "sink"); + if (pad) + return pad; + } + + // preview element is not available, + // try to use sink pin of audio encoder. + if (m_encodeBin) { + GstElement *audioEncoder = gst_bin_get_by_name(GST_BIN(m_encodeBin), "audio-encoder-bin"); + if (audioEncoder) { + GstPad *pad = gst_element_get_static_pad(audioEncoder, "sink"); + gst_object_unref(audioEncoder); + if (pad) + return pad; + } + } + + return 0; +} + +void QGstreamerCaptureSession::removeAudioBufferProbe() +{ + if (m_audioBufferProbeId == -1) + return; + + GstPad *pad = getAudioProbePad(); + if (pad) + gst_pad_remove_buffer_probe(pad, m_audioBufferProbeId); + + m_audioBufferProbeId = -1; +} + +void QGstreamerCaptureSession::addAudioBufferProbe() +{ + Q_ASSERT(m_audioBufferProbeId == -1); + + GstPad *pad = getAudioProbePad(); + if (pad) + m_audioBufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padAudioBufferProbe), this); +} + QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h index 2c2fd025f..cb03b173f 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h +++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h @@ -45,6 +45,7 @@ #include #include +#include #include #include @@ -61,6 +62,7 @@ class QGstreamerImageEncode; class QGstreamerRecorderControl; class QGstreamerMediaContainerControl; class QGstreamerVideoRendererInterface; +class QGstreamerAudioProbeControl; class QGstreamerElementFactory { @@ -127,6 +129,10 @@ public: bool processBusMessage(const QGstreamerMessage &message); + void addProbe(QGstreamerAudioProbeControl* probe); + void removeProbe(QGstreamerAudioProbeControl* probe); + static gboolean padAudioBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data); + signals: void stateChanged(QGstreamerCaptureSession::State state); void durationChanged(qint64 duration); @@ -160,6 +166,10 @@ private: void waitForStopped(); bool rebuildGraph(QGstreamerCaptureSession::PipelineMode newMode); + GstPad *getAudioProbePad(); + void removeAudioBufferProbe(); + void addAudioBufferProbe(); + QUrl m_sink; QString m_captureDevice; State m_state; @@ -169,6 +179,10 @@ private: QGstreamerCaptureSession::CaptureMode m_captureMode; QMap m_metaData; + QList m_audioProbes; + QMutex m_audioProbeMutex; + int m_audioBufferProbeId; + QGstreamerElementFactory *m_audioInputFactory; QGstreamerElementFactory *m_audioPreviewFactory; QGstreamerVideoInput *m_videoInputFactory; -- cgit v1.2.3