QMediaRecorder: GStreamer backend changes for media probing API.
QGstreamerCaptureSession: Using GStreamer buffer probe to access media data. Change-Id: I2ee38e864fbd69fcba9efe90d4dcf138528e00c0 Reviewed-by: Michael Goddard <michael.goddard@nokia.com>
This commit is contained in:
committed by
Qt by Nokia
parent
0374f0de5e
commit
16aef59187
@@ -54,6 +54,7 @@
|
|||||||
#include "qgstreameraudioinputendpointselector.h"
|
#include "qgstreameraudioinputendpointselector.h"
|
||||||
#include "qgstreamervideoinputdevicecontrol.h"
|
#include "qgstreamervideoinputdevicecontrol.h"
|
||||||
#include "qgstreamerimagecapturecontrol.h"
|
#include "qgstreamerimagecapturecontrol.h"
|
||||||
|
#include "qgstreameraudioprobecontrol.h"
|
||||||
|
|
||||||
#include "qgstreamervideorenderer.h"
|
#include "qgstreamervideorenderer.h"
|
||||||
|
|
||||||
@@ -162,6 +163,15 @@ QMediaControl *QGstreamerCaptureService::requestControl(const char *name)
|
|||||||
if (qstrcmp(name, QCameraImageCaptureControl_iid) == 0)
|
if (qstrcmp(name, QCameraImageCaptureControl_iid) == 0)
|
||||||
return m_imageCaptureControl;
|
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 (!m_videoOutput) {
|
||||||
if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
|
if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
|
||||||
m_videoOutput = m_videoRenderer;
|
m_videoOutput = m_videoRenderer;
|
||||||
@@ -189,6 +199,14 @@ void QGstreamerCaptureService::releaseControl(QMediaControl *control)
|
|||||||
m_videoOutput = 0;
|
m_videoOutput = 0;
|
||||||
m_captureSession->setVideoPreview(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
|
QT_END_NAMESPACE
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
#include "qgstreameraudioencode.h"
|
#include "qgstreameraudioencode.h"
|
||||||
#include "qgstreamervideoencode.h"
|
#include "qgstreamervideoencode.h"
|
||||||
#include "qgstreamerimageencode.h"
|
#include "qgstreamerimageencode.h"
|
||||||
|
#include "qgstreameraudioprobecontrol.h"
|
||||||
#include <qmediarecorder.h>
|
#include <qmediarecorder.h>
|
||||||
#include <private/qgstreamerbushelper_p.h>
|
#include <private/qgstreamerbushelper_p.h>
|
||||||
|
|
||||||
@@ -73,6 +74,7 @@ QGstreamerCaptureSession::QGstreamerCaptureSession(QGstreamerCaptureSession::Cap
|
|||||||
m_waitingForEos(false),
|
m_waitingForEos(false),
|
||||||
m_pipelineMode(EmptyPipeline),
|
m_pipelineMode(EmptyPipeline),
|
||||||
m_captureMode(captureMode),
|
m_captureMode(captureMode),
|
||||||
|
m_audioBufferProbeId(-1),
|
||||||
m_audioInputFactory(0),
|
m_audioInputFactory(0),
|
||||||
m_audioPreviewFactory(0),
|
m_audioPreviewFactory(0),
|
||||||
m_videoInputFactory(0),
|
m_videoInputFactory(0),
|
||||||
@@ -530,6 +532,7 @@ void QGstreamerCaptureSession::captureImage(int requestId, const QString &fileNa
|
|||||||
|
|
||||||
bool QGstreamerCaptureSession::rebuildGraph(QGstreamerCaptureSession::PipelineMode newMode)
|
bool QGstreamerCaptureSession::rebuildGraph(QGstreamerCaptureSession::PipelineMode newMode)
|
||||||
{
|
{
|
||||||
|
removeAudioBufferProbe();
|
||||||
REMOVE_ELEMENT(m_audioSrc);
|
REMOVE_ELEMENT(m_audioSrc);
|
||||||
REMOVE_ELEMENT(m_audioPreview);
|
REMOVE_ELEMENT(m_audioPreview);
|
||||||
REMOVE_ELEMENT(m_audioPreviewQueue);
|
REMOVE_ELEMENT(m_audioPreviewQueue);
|
||||||
@@ -669,6 +672,7 @@ bool QGstreamerCaptureSession::rebuildGraph(QGstreamerCaptureSession::PipelineMo
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
|
addAudioBufferProbe();
|
||||||
m_pipelineMode = newMode;
|
m_pipelineMode = newMode;
|
||||||
} else {
|
} else {
|
||||||
m_pipelineMode = EmptyPipeline;
|
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
|
QT_END_NAMESPACE
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
#include <qmediarecordercontrol.h>
|
#include <qmediarecordercontrol.h>
|
||||||
#include <qmediarecorder.h>
|
#include <qmediarecorder.h>
|
||||||
|
|
||||||
|
#include <QtCore/qmutex.h>
|
||||||
#include <QtCore/qurl.h>
|
#include <QtCore/qurl.h>
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
@@ -61,6 +62,7 @@ class QGstreamerImageEncode;
|
|||||||
class QGstreamerRecorderControl;
|
class QGstreamerRecorderControl;
|
||||||
class QGstreamerMediaContainerControl;
|
class QGstreamerMediaContainerControl;
|
||||||
class QGstreamerVideoRendererInterface;
|
class QGstreamerVideoRendererInterface;
|
||||||
|
class QGstreamerAudioProbeControl;
|
||||||
|
|
||||||
class QGstreamerElementFactory
|
class QGstreamerElementFactory
|
||||||
{
|
{
|
||||||
@@ -127,6 +129,10 @@ public:
|
|||||||
|
|
||||||
bool processBusMessage(const QGstreamerMessage &message);
|
bool processBusMessage(const QGstreamerMessage &message);
|
||||||
|
|
||||||
|
void addProbe(QGstreamerAudioProbeControl* probe);
|
||||||
|
void removeProbe(QGstreamerAudioProbeControl* probe);
|
||||||
|
static gboolean padAudioBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void stateChanged(QGstreamerCaptureSession::State state);
|
void stateChanged(QGstreamerCaptureSession::State state);
|
||||||
void durationChanged(qint64 duration);
|
void durationChanged(qint64 duration);
|
||||||
@@ -160,6 +166,10 @@ private:
|
|||||||
void waitForStopped();
|
void waitForStopped();
|
||||||
bool rebuildGraph(QGstreamerCaptureSession::PipelineMode newMode);
|
bool rebuildGraph(QGstreamerCaptureSession::PipelineMode newMode);
|
||||||
|
|
||||||
|
GstPad *getAudioProbePad();
|
||||||
|
void removeAudioBufferProbe();
|
||||||
|
void addAudioBufferProbe();
|
||||||
|
|
||||||
QUrl m_sink;
|
QUrl m_sink;
|
||||||
QString m_captureDevice;
|
QString m_captureDevice;
|
||||||
State m_state;
|
State m_state;
|
||||||
@@ -169,6 +179,10 @@ private:
|
|||||||
QGstreamerCaptureSession::CaptureMode m_captureMode;
|
QGstreamerCaptureSession::CaptureMode m_captureMode;
|
||||||
QMap<QByteArray, QVariant> m_metaData;
|
QMap<QByteArray, QVariant> m_metaData;
|
||||||
|
|
||||||
|
QList<QGstreamerAudioProbeControl*> m_audioProbes;
|
||||||
|
QMutex m_audioProbeMutex;
|
||||||
|
int m_audioBufferProbeId;
|
||||||
|
|
||||||
QGstreamerElementFactory *m_audioInputFactory;
|
QGstreamerElementFactory *m_audioInputFactory;
|
||||||
QGstreamerElementFactory *m_audioPreviewFactory;
|
QGstreamerElementFactory *m_audioPreviewFactory;
|
||||||
QGstreamerVideoInput *m_videoInputFactory;
|
QGstreamerVideoInput *m_videoInputFactory;
|
||||||
|
|||||||
Reference in New Issue
Block a user