QMediaRecorder: GStreamer backend changes for media probing API.
authorLev Zelenskiy <lev.zelenskiy@nokia.com>
Wed, 15 Feb 2012 04:45:18 +0000 (14:45 +1000)
committerQt by Nokia <qt-info@nokia.com>
Thu, 16 Feb 2012 06:18:27 +0000 (07:18 +0100)
QGstreamerCaptureSession: Using GStreamer buffer probe
to access media data.

Change-Id: I2ee38e864fbd69fcba9efe90d4dcf138528e00c0
Reviewed-by: Michael Goddard <michael.goddard@nokia.com>
src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp
src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp
src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h

index 95b4444..405cc57 100644 (file)
@@ -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<QGstreamerAudioProbeControl*>(control);
+    if (audioProbe) {
+        if (m_captureSession)
+            m_captureSession->removeProbe(audioProbe);
+        delete audioProbe;
+        return;
+    }
 }
 
 QT_END_NAMESPACE
index 68f4444..60cda07 100644 (file)
@@ -46,6 +46,7 @@
 #include "qgstreameraudioencode.h"
 #include "qgstreamervideoencode.h"
 #include "qgstreamerimageencode.h"
+#include "qgstreameraudioprobecontrol.h"
 #include <qmediarecorder.h>
 #include <private/qgstreamerbushelper_p.h>
 
@@ -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<QGstreamerCaptureSession*>(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
index 2c2fd02..cb03b17 100644 (file)
@@ -45,6 +45,7 @@
 #include <qmediarecordercontrol.h>
 #include <qmediarecorder.h>
 
+#include <QtCore/qmutex.h>
 #include <QtCore/qurl.h>
 
 #include <gst/gst.h>
@@ -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<QByteArray, QVariant> m_metaData;
 
+    QList<QGstreamerAudioProbeControl*> m_audioProbes;
+    QMutex m_audioProbeMutex;
+    int m_audioBufferProbeId;
+
     QGstreamerElementFactory *m_audioInputFactory;
     QGstreamerElementFactory *m_audioPreviewFactory;
     QGstreamerVideoInput *m_videoInputFactory;