From 696e434129c23fddb786e101c9efc7ede1f2943b Mon Sep 17 00:00:00 2001 From: Michael Goddard Date: Tue, 14 Feb 2012 16:14:08 +1000 Subject: Add a partial gstreamer based audio decoder service. Doesn't work yet. Change-Id: Iebd085d68346cb73af8df59c84e8e52a17de2a52 Reviewed-by: Michael Goddard --- .../gstreamer/audiodecoder/audiodecoder.pri | 15 + .../audiodecoder/qgstreameraudiodecodercontrol.cpp | 129 +++++++ .../audiodecoder/qgstreameraudiodecodercontrol.h | 94 +++++ .../audiodecoder/qgstreameraudiodecoderservice.cpp | 75 ++++ .../audiodecoder/qgstreameraudiodecoderservice.h | 71 ++++ .../audiodecoder/qgstreameraudiodecodersession.cpp | 380 +++++++++++++++++++++ .../audiodecoder/qgstreameraudiodecodersession.h | 128 +++++++ src/plugins/gstreamer/gstreamer.pro | 13 +- src/plugins/gstreamer/mediaplayer/mediaplayer.pri | 9 - src/plugins/gstreamer/mediaplayer/qgstappsrc.cpp | 227 ------------ src/plugins/gstreamer/mediaplayer/qgstappsrc.h | 106 ------ src/plugins/gstreamer/qgstappsrc.cpp | 227 ++++++++++++ src/plugins/gstreamer/qgstappsrc.h | 106 ++++++ src/plugins/gstreamer/qgstreamerserviceplugin.cpp | 13 +- 14 files changed, 1249 insertions(+), 344 deletions(-) create mode 100644 src/plugins/gstreamer/audiodecoder/audiodecoder.pri create mode 100644 src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodercontrol.cpp create mode 100644 src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodercontrol.h create mode 100644 src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderservice.cpp create mode 100644 src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderservice.h create mode 100644 src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.cpp create mode 100644 src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.h delete mode 100644 src/plugins/gstreamer/mediaplayer/qgstappsrc.cpp delete mode 100644 src/plugins/gstreamer/mediaplayer/qgstappsrc.h create mode 100644 src/plugins/gstreamer/qgstappsrc.cpp create mode 100644 src/plugins/gstreamer/qgstappsrc.h (limited to 'src/plugins') diff --git a/src/plugins/gstreamer/audiodecoder/audiodecoder.pri b/src/plugins/gstreamer/audiodecoder/audiodecoder.pri new file mode 100644 index 000000000..d2711e017 --- /dev/null +++ b/src/plugins/gstreamer/audiodecoder/audiodecoder.pri @@ -0,0 +1,15 @@ +INCLUDEPATH += $$PWD + +DEFINES += QMEDIA_GSTREAMER_AUDIO_DECODER + +HEADERS += \ + $$PWD/qgstreameraudiodecodercontrol.h \ + $$PWD/qgstreameraudiodecoderservice.h \ + $$PWD/qgstreameraudiodecodersession.h + +SOURCES += \ + $$PWD/qgstreameraudiodecodercontrol.cpp \ + $$PWD/qgstreameraudiodecoderservice.cpp \ + $$PWD/qgstreameraudiodecodersession.cpp + + diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodercontrol.cpp b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodercontrol.cpp new file mode 100644 index 000000000..db1b716eb --- /dev/null +++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodercontrol.cpp @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgstreameraudiodecodercontrol.h" +#include "qgstreameraudiodecodersession.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QGstreamerAudioDecoderControl::QGstreamerAudioDecoderControl(QGstreamerAudioDecoderSession *session, QObject *parent) + : QAudioDecoderControl(parent) + , m_session(session) +{ + connect(m_session, SIGNAL(bufferAvailableChanged(bool)), this, SIGNAL(bufferAvailableChanged(bool))); + connect(m_session, SIGNAL(bufferReady()), this, SIGNAL(bufferReady())); + connect(m_session, SIGNAL(error(int,QString)), this, SIGNAL(error(int,QString))); + connect(m_session, SIGNAL(formatChanged(QAudioFormat)), this, SIGNAL(formatChanged(QAudioFormat))); + connect(m_session, SIGNAL(stateChanged(QAudioDecoder::State)), this, SIGNAL(stateChanged(QAudioDecoder::State))); +} + +QGstreamerAudioDecoderControl::~QGstreamerAudioDecoderControl() +{ + +} + +QAudioDecoder::State QGstreamerAudioDecoderControl::state() const +{ + return m_session->state(); +} + +QString QGstreamerAudioDecoderControl::sourceFilename() const +{ + return m_session->sourceFilename(); +} + +void QGstreamerAudioDecoderControl::setSourceFilename(const QString &fileName) +{ + m_session->setSourceFilename(fileName); +} + +QIODevice* QGstreamerAudioDecoderControl::sourceDevice() const +{ + return m_session->sourceDevice(); +} + +void QGstreamerAudioDecoderControl::setSourceDevice(QIODevice *device) +{ + m_session->setSourceDevice(device); +} + +void QGstreamerAudioDecoderControl::start() +{ + m_session->start(); +} + +void QGstreamerAudioDecoderControl::stop() +{ + m_session->stop(); +} + +QAudioFormat QGstreamerAudioDecoderControl::audioFormat() const +{ + return m_session->audioFormat(); +} + +void QGstreamerAudioDecoderControl::setAudioFormat(const QAudioFormat &format) +{ + m_session->setAudioFormat(format); +} + +QAudioBuffer QGstreamerAudioDecoderControl::read(bool *ok) +{ + return m_session->read(ok); +} + +bool QGstreamerAudioDecoderControl::bufferAvailable() const +{ + return m_session->bufferAvailable(); +} + + +QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodercontrol.h b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodercontrol.h new file mode 100644 index 000000000..40699b697 --- /dev/null +++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodercontrol.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGSTREAMERPLAYERCONTROL_H +#define QGSTREAMERPLAYERCONTROL_H + +#include +#include + +#include +#include +#include +#include + +#include + + +QT_BEGIN_NAMESPACE + +class QGstreamerAudioDecoderSession; +class QGstreamerAudioDecoderService; + +class QGstreamerAudioDecoderControl : public QAudioDecoderControl +{ + Q_OBJECT + +public: + QGstreamerAudioDecoderControl(QGstreamerAudioDecoderSession *session, QObject *parent = 0); + ~QGstreamerAudioDecoderControl(); + + QAudioDecoder::State state() const; + + QString sourceFilename() const; + void setSourceFilename(const QString &fileName); + + QIODevice* sourceDevice() const; + void setSourceDevice(QIODevice *device); + + void start(); + void stop(); + + QAudioFormat audioFormat() const; + void setAudioFormat(const QAudioFormat &format); + + QAudioBuffer read(bool *ok); + bool bufferAvailable() const; + +private: + // Stuff goes here + + QGstreamerAudioDecoderSession *m_session; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderservice.cpp b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderservice.cpp new file mode 100644 index 000000000..afe0dff6a --- /dev/null +++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderservice.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include "qgstreameraudiodecoderservice.h" +#include "qgstreameraudiodecodercontrol.h" +#include "qgstreameraudiodecodersession.h" + +QT_BEGIN_NAMESPACE + +QGstreamerAudioDecoderService::QGstreamerAudioDecoderService(QObject *parent) + : QMediaService(parent) +{ + m_session = new QGstreamerAudioDecoderSession(this); + m_control = new QGstreamerAudioDecoderControl(m_session, this); +} + +QGstreamerAudioDecoderService::~QGstreamerAudioDecoderService() +{ +} + +QMediaControl *QGstreamerAudioDecoderService::requestControl(const char *name) +{ + if (qstrcmp(name, QAudioDecoderControl_iid) == 0) + return m_control; + + return 0; +} + +void QGstreamerAudioDecoderService::releaseControl(QMediaControl *control) +{ + Q_UNUSED(control); +} + +QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderservice.h b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderservice.h new file mode 100644 index 000000000..ebc244362 --- /dev/null +++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderservice.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGSTREAMERAUDIODECODERSERVICE_H +#define QGSTREAMERAUDIODECODERSERVICE_H + +#include +#include + +#include + +QT_BEGIN_NAMESPACE +class QGstreamerAudioDecoderControl; +class QGstreamerAudioDecoderSession; + +class QGstreamerAudioDecoderService : public QMediaService +{ + Q_OBJECT +public: + QGstreamerAudioDecoderService(QObject *parent = 0); + ~QGstreamerAudioDecoderService(); + + QMediaControl *requestControl(const char *name); + void releaseControl(QMediaControl *control); + +private: + QGstreamerAudioDecoderControl *m_control; + QGstreamerAudioDecoderSession *m_session; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.cpp b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.cpp new file mode 100644 index 000000000..4afee231d --- /dev/null +++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.cpp @@ -0,0 +1,380 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgstreameraudiodecodersession.h" +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QGstreamerAudioDecoderSession::QGstreamerAudioDecoderSession(QObject *parent) + : QObject(parent), + m_state(QAudioDecoder::StoppedState), + m_pendingState(QAudioDecoder::StoppedState), + m_busHelper(0), + m_bus(0), + m_playbin(0), +#if defined(HAVE_GST_APPSRC) + m_appSrc(0), +#endif + mDevice(0) +{ + // Default format + mFormat.setChannels(2); + mFormat.setSampleSize(16); + mFormat.setFrequency(48000); + mFormat.setCodec("audio/x-raw"); + mFormat.setSampleType(QAudioFormat::UnSignedInt); + + + // Create pipeline here +#if 0 + if (m_playbin != 0) { + // Sort out messages + m_bus = gst_element_get_bus(m_playbin); + m_busHelper = new QGstreamerBusHelper(m_bus, this); + m_busHelper->installMessageFilter(this); + } +#endif +} + +QGstreamerAudioDecoderSession::~QGstreamerAudioDecoderSession() +{ + if (m_playbin) { + stop(); + + delete m_busHelper; + gst_object_unref(GST_OBJECT(m_bus)); + gst_object_unref(GST_OBJECT(m_playbin)); + } +} + +#if defined(HAVE_GST_APPSRC) +void QGstreamerAudioDecoderSession::configureAppSrcElement(GObject* object, GObject *orig, GParamSpec *pspec, QGstreamerAudioDecoderSession* self) +{ + Q_UNUSED(object); + Q_UNUSED(pspec); + + if (self->appsrc()->isReady()) + return; + + GstElement *appsrc; + g_object_get(orig, "source", &appsrc, NULL); + + if (!self->appsrc()->setup(appsrc)) + qWarning()<<"Could not setup appsrc element"; +} +#endif + +#if 0 +void QGstreamerAudioDecoderSession::loadFromStream(const QNetworkRequest &request, QIODevice *appSrcStream) +{ +#if defined(HAVE_GST_APPSRC) +#ifdef DEBUG_PLAYBIN + qDebug() << Q_FUNC_INFO; +#endif + m_request = request; + m_duration = -1; + m_lastPosition = 0; + m_haveQueueElement = false; + + if (m_appSrc) + m_appSrc->deleteLater(); + m_appSrc = new QGstAppSrc(this); + m_appSrc->setStream(appSrcStream); + + if (m_playbin) { + m_tags.clear(); + emit tagsChanged(); + + g_signal_connect(G_OBJECT(m_playbin), "deep-notify::source", (GCallback) &QGstreamerAudioDecoderSession::configureAppSrcElement, (gpointer)this); + g_object_set(G_OBJECT(m_playbin), "uri", "appsrc://", NULL); + + if (!m_streamTypes.isEmpty()) { + m_streamProperties.clear(); + m_streamTypes.clear(); + + emit streamsChanged(); + } + } +#endif +} + +void QGstreamerAudioDecoderSession::loadFromUri(const QNetworkRequest &request) +{ +#ifdef DEBUG_PLAYBIN + qDebug() << Q_FUNC_INFO << request.url(); +#endif + m_request = request; + m_duration = -1; + m_lastPosition = 0; + m_haveQueueElement = false; + + if (m_playbin) { + m_tags.clear(); + emit tagsChanged(); + + g_object_set(G_OBJECT(m_playbin), "uri", m_request.url().toEncoded().constData(), NULL); + + if (!m_streamTypes.isEmpty()) { + m_streamProperties.clear(); + m_streamTypes.clear(); + + emit streamsChanged(); + } + } +} +#endif + +bool QGstreamerAudioDecoderSession::processBusMessage(const QGstreamerMessage &message) +{ + GstMessage* gm = message.rawMessage(); + if (gm) { + if (GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_playbin)) { + switch (GST_MESSAGE_TYPE(gm)) { + case GST_MESSAGE_STATE_CHANGED: + { + GstState oldState; + GstState newState; + GstState pending; + + gst_message_parse_state_changed(gm, &oldState, &newState, &pending); + +#ifdef DEBUG_PLAYBIN + QStringList states; + states << "GST_STATE_VOID_PENDING" << "GST_STATE_NULL" << "GST_STATE_READY" << "GST_STATE_PAUSED" << "GST_STATE_PLAYING"; + + qDebug() << QString("state changed: old: %1 new: %2 pending: %3") \ + .arg(states[oldState]) \ + .arg(states[newState]) \ + .arg(states[pending]); +#endif + + switch (newState) { + case GST_STATE_VOID_PENDING: + case GST_STATE_NULL: + if (m_state != QAudioDecoder::StoppedState) + emit stateChanged(m_state = QAudioDecoder::StoppedState); + break; + case GST_STATE_READY: + if (m_state != QAudioDecoder::StoppedState) + emit stateChanged(m_state = QAudioDecoder::StoppedState); + break; + case GST_STATE_PLAYING: + if (m_state != QAudioDecoder::DecodingState) + emit stateChanged(m_state = QAudioDecoder::DecodingState); + + break; + case GST_STATE_PAUSED: + if (m_state != QAudioDecoder::WaitingState) + emit stateChanged(m_state = QAudioDecoder::WaitingState); + break; + } + } + break; + + case GST_MESSAGE_EOS: + emit stateChanged(m_state = QAudioDecoder::StoppedState); + break; + + case GST_MESSAGE_TAG: + case GST_MESSAGE_STREAM_STATUS: + case GST_MESSAGE_UNKNOWN: + break; + case GST_MESSAGE_ERROR: { + GError *err; + gchar *debug; + gst_message_parse_error(gm, &err, &debug); + if (err->domain == GST_STREAM_ERROR && err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND) + processInvalidMedia(QAudioDecoder::FormatError, tr("Cannot play stream of type: ")); + else + processInvalidMedia(QAudioDecoder::ResourceError, QString::fromUtf8(err->message)); + qWarning() << "Error:" << QString::fromUtf8(err->message); + g_error_free(err); + g_free(debug); + } + break; + case GST_MESSAGE_WARNING: + { + GError *err; + gchar *debug; + gst_message_parse_warning (gm, &err, &debug); + qWarning() << "Warning:" << QString::fromUtf8(err->message); + g_error_free (err); + g_free (debug); + } + break; + case GST_MESSAGE_INFO: +#ifdef DEBUG_PLAYBIN + { + GError *err; + gchar *debug; + gst_message_parse_info (gm, &err, &debug); + qDebug() << "Info:" << QString::fromUtf8(err->message); + g_error_free (err); + g_free (debug); + } +#endif + break; + case GST_MESSAGE_BUFFERING: + case GST_MESSAGE_STATE_DIRTY: + case GST_MESSAGE_STEP_DONE: + case GST_MESSAGE_CLOCK_PROVIDE: + case GST_MESSAGE_CLOCK_LOST: + case GST_MESSAGE_NEW_CLOCK: + case GST_MESSAGE_STRUCTURE_CHANGE: + case GST_MESSAGE_APPLICATION: + case GST_MESSAGE_ELEMENT: + break; + case GST_MESSAGE_SEGMENT_START: + case GST_MESSAGE_SEGMENT_DONE: + break; + case GST_MESSAGE_LATENCY: +#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 13) + case GST_MESSAGE_ASYNC_START: + case GST_MESSAGE_ASYNC_DONE: +#if GST_VERSION_MICRO >= 23 + case GST_MESSAGE_REQUEST_STATE: +#endif +#endif + case GST_MESSAGE_ANY: + break; + default: + break; + } + } else if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ERROR) { + GError *err; + gchar *debug; + gst_message_parse_error(gm, &err, &debug); + // If the source has given up, so do we. + if (qstrcmp(GST_OBJECT_NAME(GST_MESSAGE_SRC(gm)), "source") == 0) { + processInvalidMedia(QAudioDecoder::ResourceError, QString::fromUtf8(err->message)); + } else if (err->domain == GST_STREAM_ERROR + && (err->code == GST_STREAM_ERROR_DECRYPT || err->code == GST_STREAM_ERROR_DECRYPT_NOKEY)) { + processInvalidMedia(QAudioDecoder::AccessDeniedError, QString::fromUtf8(err->message)); + } + g_error_free(err); + g_free(debug); + } + } + + return false; +} + +QString QGstreamerAudioDecoderSession::sourceFilename() const +{ + return mSource; +} + +void QGstreamerAudioDecoderSession::setSourceFilename(const QString &fileName) +{ + stop(); + mDevice = 0; + mSource = fileName; +} + +QIODevice *QGstreamerAudioDecoderSession::sourceDevice() const +{ + return mDevice; +} + +void QGstreamerAudioDecoderSession::setSourceDevice(QIODevice *device) +{ + stop(); + mSource.clear(); + mDevice = device; +} + +void QGstreamerAudioDecoderSession::start() +{ + // TODO +} + +void QGstreamerAudioDecoderSession::stop() +{ + // TODO +} + +QAudioFormat QGstreamerAudioDecoderSession::audioFormat() const +{ + return mFormat; +} + +void QGstreamerAudioDecoderSession::setAudioFormat(const QAudioFormat &format) +{ + if (mFormat != format) { + mFormat = format; + emit formatChanged(mFormat); + } +} + +QAudioBuffer QGstreamerAudioDecoderSession::read(bool *ok) +{ + // TODO + if (ok) + *ok = false; + return QAudioBuffer(); +} + +bool QGstreamerAudioDecoderSession::bufferAvailable() const +{ + return false; +} + +void QGstreamerAudioDecoderSession::processInvalidMedia(QAudioDecoder::Error errorCode, const QString& errorString) +{ + stop(); + emit error(int(errorCode), errorString); +} + +QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.h b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.h new file mode 100644 index 000000000..b6ac7516e --- /dev/null +++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGSTREAMERPLAYERSESSION_H +#define QGSTREAMERPLAYERSESSION_H + +#include +#include "qgstreameraudiodecodercontrol.h" +#include +#include + +#if defined(HAVE_GST_APPSRC) +#include "qgstappsrc.h" +#endif + +#include + +QT_BEGIN_NAMESPACE + +class QGstreamerBusHelper; +class QGstreamerMessage; + +class QGstreamerAudioDecoderSession : public QObject, + public QGstreamerBusMessageFilter +{ +Q_OBJECT +Q_INTERFACES(QGstreamerBusMessageFilter) + +public: + QGstreamerAudioDecoderSession(QObject *parent); + virtual ~QGstreamerAudioDecoderSession(); + + QGstreamerBusHelper *bus() const { return m_busHelper; } + + QAudioDecoder::State state() const { return m_state; } + QAudioDecoder::State pendingState() const { return m_pendingState; } + + bool processBusMessage(const QGstreamerMessage &message); + +#if defined(HAVE_GST_APPSRC) + QGstAppSrc *appsrc() const { return m_appSrc; } + static void configureAppSrcElement(GObject*, GObject*, GParamSpec*,QGstreamerAudioDecoderSession* _this); +#endif + + QString sourceFilename() const; + void setSourceFilename(const QString &fileName); + + QIODevice* sourceDevice() const; + void setSourceDevice(QIODevice *device); + + void start(); + void stop(); + + QAudioFormat audioFormat() const; + void setAudioFormat(const QAudioFormat &format); + + QAudioBuffer read(bool *ok); + bool bufferAvailable() const; + +signals: + void stateChanged(QAudioDecoder::State newState); + void formatChanged(const QAudioFormat &format); + + void error(int error, const QString &errorString); + + void bufferReady(); + void bufferAvailableChanged(bool available); + +private: + + void processInvalidMedia(QAudioDecoder::Error errorCode, const QString& errorString); + + QAudioDecoder::State m_state; + QAudioDecoder::State m_pendingState; + QGstreamerBusHelper* m_busHelper; + GstBus* m_bus; + GstElement* m_playbin; + +#if defined(HAVE_GST_APPSRC) + QGstAppSrc *m_appSrc; +#endif + + QString mSource; + QIODevice *mDevice; // QWeakPointer perhaps + QAudioFormat mFormat; +}; + +QT_END_NAMESPACE + +#endif // QGSTREAMERPLAYERSESSION_H diff --git a/src/plugins/gstreamer/gstreamer.pro b/src/plugins/gstreamer/gstreamer.pro index 14d40fd6a..77f7da9c0 100644 --- a/src/plugins/gstreamer/gstreamer.pro +++ b/src/plugins/gstreamer/gstreamer.pro @@ -33,7 +33,6 @@ PKGCONFIG += \ gstreamer-pbutils-0.10 maemo*:PKGCONFIG +=gstreamer-plugins-bad-0.10 -contains(config_test_gstreamer_appsrc, yes): PKGCONFIG += gstreamer-app-0.10 contains(config_test_resourcepolicy, yes) { DEFINES += HAVE_RESOURCE_POLICY @@ -97,6 +96,18 @@ contains(config_test_xvideo, yes):!isEmpty(QT.widgets.name): { } include(mediaplayer/mediaplayer.pri) include(mediacapture/mediacapture.pri) +include(audiodecoder/audiodecoder.pri) + +contains(config_test_gstreamer_appsrc, yes) { + PKGCONFIG += gstreamer-app-0.10 + HEADERS += $$PWD/qgstappsrc.h + SOURCES += $$PWD/qgstappsrc.cpp + + DEFINES += HAVE_GST_APPSRC + + LIBS += -lgstapp-0.10 +} + #Camerabin2 based camera backend is untested and currently disabled #contains(config_test_gstreamer_photography, yes) { diff --git a/src/plugins/gstreamer/mediaplayer/mediaplayer.pri b/src/plugins/gstreamer/mediaplayer/mediaplayer.pri index 310ed6f24..92cd79086 100644 --- a/src/plugins/gstreamer/mediaplayer/mediaplayer.pri +++ b/src/plugins/gstreamer/mediaplayer/mediaplayer.pri @@ -2,15 +2,6 @@ INCLUDEPATH += $$PWD DEFINES += QMEDIA_GSTREAMER_PLAYER -contains(config_test_gstreamer_appsrc, yes) { - HEADERS += $$PWD/qgstappsrc.h - SOURCES += $$PWD/qgstappsrc.cpp - - DEFINES += HAVE_GST_APPSRC - - LIBS += -lgstapp-0.10 -} - HEADERS += \ $$PWD/qgstreamerplayercontrol.h \ $$PWD/qgstreamerplayerservice.h \ diff --git a/src/plugins/gstreamer/mediaplayer/qgstappsrc.cpp b/src/plugins/gstreamer/mediaplayer/qgstappsrc.cpp deleted file mode 100644 index 08791ce6f..000000000 --- a/src/plugins/gstreamer/mediaplayer/qgstappsrc.cpp +++ /dev/null @@ -1,227 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include - -#include "qgstappsrc.h" -#include - -QGstAppSrc::QGstAppSrc(QObject *parent) - :QObject(parent) - ,m_stream(0) - ,m_appSrc(0) - ,m_sequential(false) - ,m_maxBytes(0) - ,m_setup(false) - ,m_dataRequestSize(-1) - ,m_dataRequested(false) - ,m_enoughData(false) - ,m_forceData(false) -{ - m_callbacks.need_data = &QGstAppSrc::on_need_data; - m_callbacks.enough_data = &QGstAppSrc::on_enough_data; - m_callbacks.seek_data = &QGstAppSrc::on_seek_data; -} - -QGstAppSrc::~QGstAppSrc() -{ - if (m_appSrc) - gst_object_unref(G_OBJECT(m_appSrc)); -} - -bool QGstAppSrc::setup(GstElement* appsrc) -{ - if (m_setup || m_stream == 0 || appsrc == 0) - return false; - - m_appSrc = GST_APP_SRC(appsrc); - gst_app_src_set_callbacks(m_appSrc, (GstAppSrcCallbacks*)&m_callbacks, this, (GDestroyNotify)&QGstAppSrc::destroy_notify); - - g_object_get(G_OBJECT(m_appSrc), "max-bytes", &m_maxBytes, NULL); - - if (m_sequential) - m_streamType = GST_APP_STREAM_TYPE_STREAM; - else - m_streamType = GST_APP_STREAM_TYPE_RANDOM_ACCESS; - gst_app_src_set_stream_type(m_appSrc, m_streamType); - gst_app_src_set_size(m_appSrc, (m_sequential) ? -1 : m_stream->size()); - - return m_setup = true; -} - -void QGstAppSrc::setStream(QIODevice *stream) -{ - if (stream == 0) - return; - if (m_stream) { - disconnect(m_stream, SIGNAL(readyRead()), this, SLOT(onDataReady())); - disconnect(m_stream, SIGNAL(destroyed()), this, SLOT(streamDestroyed())); - } - if (m_appSrc) - gst_object_unref(G_OBJECT(m_appSrc)); - - m_dataRequestSize = -1; - m_dataRequested = false; - m_enoughData = false; - m_forceData = false; - m_maxBytes = 0; - - m_appSrc = 0; - m_stream = stream; - connect(m_stream, SIGNAL(destroyed()), SLOT(streamDestroyed())); - connect(m_stream, SIGNAL(readyRead()), this, SLOT(onDataReady())); - m_sequential = m_stream->isSequential(); - m_setup = false; -} - -QIODevice *QGstAppSrc::stream() const -{ - return m_stream; -} - -GstAppSrc *QGstAppSrc::element() -{ - return m_appSrc; -} - -void QGstAppSrc::onDataReady() -{ - if (!m_enoughData) { - m_dataRequested = true; - pushDataToAppSrc(); - } -} - -void QGstAppSrc::streamDestroyed() -{ - if (sender() == m_stream) { - m_stream = 0; - sendEOS(); - } -} - -void QGstAppSrc::pushDataToAppSrc() -{ - if (!isStreamValid() || !m_setup) - return; - - if (m_dataRequested && !m_enoughData) { - qint64 size; - if (m_dataRequestSize == (unsigned int)-1) - size = qMin(m_stream->bytesAvailable(), queueSize()); - else - size = qMin(m_stream->bytesAvailable(), (qint64)m_dataRequestSize); - void *data = g_malloc(size); - GstBuffer* buffer = gst_app_buffer_new(data, size, g_free, data); - buffer->offset = m_stream->pos(); - qint64 bytesRead = m_stream->read((char*)GST_BUFFER_DATA(buffer), size); - buffer->offset_end = buffer->offset + bytesRead - 1; - - if (bytesRead > 0) { - m_dataRequested = false; - m_enoughData = false; - GstFlowReturn ret = gst_app_src_push_buffer (GST_APP_SRC (element()), buffer); - if (ret == GST_FLOW_ERROR) { - qWarning()<<"appsrc: push buffer error"; - } else if (ret == GST_FLOW_WRONG_STATE) { - qWarning()<<"appsrc: push buffer wrong state"; - } else if (ret == GST_FLOW_RESEND) { - qWarning()<<"appsrc: push buffer resend"; - } - } - } else if (m_stream->atEnd()) { - sendEOS(); - } -} - -bool QGstAppSrc::doSeek(qint64 value) -{ - if (isStreamValid()) - return stream()->seek(value); - return false; -} - - -gboolean QGstAppSrc::on_seek_data(GstAppSrc *element, guint64 arg0, gpointer userdata) -{ - Q_UNUSED(element); - QGstAppSrc *self = reinterpret_cast(userdata); - if (self && self->isStreamValid()) { - if (!self->stream()->isSequential()) - QMetaObject::invokeMethod(self, "doSeek", Qt::AutoConnection, Q_ARG(qint64, arg0)); - } - else - return false; - - return true; -} - -void QGstAppSrc::on_enough_data(GstAppSrc *element, gpointer userdata) -{ - Q_UNUSED(element); - QGstAppSrc *self = reinterpret_cast(userdata); - if (self) - self->enoughData() = true; -} - -void QGstAppSrc::on_need_data(GstAppSrc *element, guint arg0, gpointer userdata) -{ - Q_UNUSED(element); - QGstAppSrc *self = reinterpret_cast(userdata); - if (self) { - self->dataRequested() = true; - self->enoughData() = false; - self->dataRequestSize()= arg0; - QMetaObject::invokeMethod(self, "pushDataToAppSrc", Qt::AutoConnection); - } -} - -void QGstAppSrc::destroy_notify(gpointer data) -{ - Q_UNUSED(data); -} - -void QGstAppSrc::sendEOS() -{ - gst_app_src_end_of_stream(GST_APP_SRC(m_appSrc)); - if (isStreamValid() && !stream()->isSequential()) - stream()->reset(); -} diff --git a/src/plugins/gstreamer/mediaplayer/qgstappsrc.h b/src/plugins/gstreamer/mediaplayer/qgstappsrc.h deleted file mode 100644 index dc817e8f0..000000000 --- a/src/plugins/gstreamer/mediaplayer/qgstappsrc.h +++ /dev/null @@ -1,106 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGSTAPPSRC_H -#define QGSTAPPSRC_H - -#include -#include - -#include -#include -#include - -class QGstAppSrc : public QObject -{ - Q_OBJECT -public: - QGstAppSrc(QObject *parent = 0); - ~QGstAppSrc(); - - bool setup(GstElement *); - bool isReady() const { return m_setup; } - - void setStream(QIODevice *); - QIODevice *stream() const; - - GstAppSrc *element(); - - qint64 queueSize() const { return m_maxBytes; } - - bool& enoughData() { return m_enoughData; } - bool& dataRequested() { return m_dataRequested; } - unsigned int& dataRequestSize() { return m_dataRequestSize; } - - bool isStreamValid() const - { - return m_stream != 0 && - m_stream->isOpen(); - } - -private slots: - void pushDataToAppSrc(); - bool doSeek(qint64); - void onDataReady(); - - void streamDestroyed(); -private: - static gboolean on_seek_data(GstAppSrc *element, guint64 arg0, gpointer userdata); - static void on_enough_data(GstAppSrc *element, gpointer userdata); - static void on_need_data(GstAppSrc *element, uint arg0, gpointer userdata); - static void destroy_notify(gpointer data); - - void sendEOS(); - - QIODevice *m_stream; - GstAppSrc *m_appSrc; - bool m_sequential; - GstAppStreamType m_streamType; - GstAppSrcCallbacks m_callbacks; - qint64 m_maxBytes; - bool m_setup; - unsigned int m_dataRequestSize; - bool m_dataRequested; - bool m_enoughData; - bool m_forceData; -}; - -#endif diff --git a/src/plugins/gstreamer/qgstappsrc.cpp b/src/plugins/gstreamer/qgstappsrc.cpp new file mode 100644 index 000000000..08791ce6f --- /dev/null +++ b/src/plugins/gstreamer/qgstappsrc.cpp @@ -0,0 +1,227 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "qgstappsrc.h" +#include + +QGstAppSrc::QGstAppSrc(QObject *parent) + :QObject(parent) + ,m_stream(0) + ,m_appSrc(0) + ,m_sequential(false) + ,m_maxBytes(0) + ,m_setup(false) + ,m_dataRequestSize(-1) + ,m_dataRequested(false) + ,m_enoughData(false) + ,m_forceData(false) +{ + m_callbacks.need_data = &QGstAppSrc::on_need_data; + m_callbacks.enough_data = &QGstAppSrc::on_enough_data; + m_callbacks.seek_data = &QGstAppSrc::on_seek_data; +} + +QGstAppSrc::~QGstAppSrc() +{ + if (m_appSrc) + gst_object_unref(G_OBJECT(m_appSrc)); +} + +bool QGstAppSrc::setup(GstElement* appsrc) +{ + if (m_setup || m_stream == 0 || appsrc == 0) + return false; + + m_appSrc = GST_APP_SRC(appsrc); + gst_app_src_set_callbacks(m_appSrc, (GstAppSrcCallbacks*)&m_callbacks, this, (GDestroyNotify)&QGstAppSrc::destroy_notify); + + g_object_get(G_OBJECT(m_appSrc), "max-bytes", &m_maxBytes, NULL); + + if (m_sequential) + m_streamType = GST_APP_STREAM_TYPE_STREAM; + else + m_streamType = GST_APP_STREAM_TYPE_RANDOM_ACCESS; + gst_app_src_set_stream_type(m_appSrc, m_streamType); + gst_app_src_set_size(m_appSrc, (m_sequential) ? -1 : m_stream->size()); + + return m_setup = true; +} + +void QGstAppSrc::setStream(QIODevice *stream) +{ + if (stream == 0) + return; + if (m_stream) { + disconnect(m_stream, SIGNAL(readyRead()), this, SLOT(onDataReady())); + disconnect(m_stream, SIGNAL(destroyed()), this, SLOT(streamDestroyed())); + } + if (m_appSrc) + gst_object_unref(G_OBJECT(m_appSrc)); + + m_dataRequestSize = -1; + m_dataRequested = false; + m_enoughData = false; + m_forceData = false; + m_maxBytes = 0; + + m_appSrc = 0; + m_stream = stream; + connect(m_stream, SIGNAL(destroyed()), SLOT(streamDestroyed())); + connect(m_stream, SIGNAL(readyRead()), this, SLOT(onDataReady())); + m_sequential = m_stream->isSequential(); + m_setup = false; +} + +QIODevice *QGstAppSrc::stream() const +{ + return m_stream; +} + +GstAppSrc *QGstAppSrc::element() +{ + return m_appSrc; +} + +void QGstAppSrc::onDataReady() +{ + if (!m_enoughData) { + m_dataRequested = true; + pushDataToAppSrc(); + } +} + +void QGstAppSrc::streamDestroyed() +{ + if (sender() == m_stream) { + m_stream = 0; + sendEOS(); + } +} + +void QGstAppSrc::pushDataToAppSrc() +{ + if (!isStreamValid() || !m_setup) + return; + + if (m_dataRequested && !m_enoughData) { + qint64 size; + if (m_dataRequestSize == (unsigned int)-1) + size = qMin(m_stream->bytesAvailable(), queueSize()); + else + size = qMin(m_stream->bytesAvailable(), (qint64)m_dataRequestSize); + void *data = g_malloc(size); + GstBuffer* buffer = gst_app_buffer_new(data, size, g_free, data); + buffer->offset = m_stream->pos(); + qint64 bytesRead = m_stream->read((char*)GST_BUFFER_DATA(buffer), size); + buffer->offset_end = buffer->offset + bytesRead - 1; + + if (bytesRead > 0) { + m_dataRequested = false; + m_enoughData = false; + GstFlowReturn ret = gst_app_src_push_buffer (GST_APP_SRC (element()), buffer); + if (ret == GST_FLOW_ERROR) { + qWarning()<<"appsrc: push buffer error"; + } else if (ret == GST_FLOW_WRONG_STATE) { + qWarning()<<"appsrc: push buffer wrong state"; + } else if (ret == GST_FLOW_RESEND) { + qWarning()<<"appsrc: push buffer resend"; + } + } + } else if (m_stream->atEnd()) { + sendEOS(); + } +} + +bool QGstAppSrc::doSeek(qint64 value) +{ + if (isStreamValid()) + return stream()->seek(value); + return false; +} + + +gboolean QGstAppSrc::on_seek_data(GstAppSrc *element, guint64 arg0, gpointer userdata) +{ + Q_UNUSED(element); + QGstAppSrc *self = reinterpret_cast(userdata); + if (self && self->isStreamValid()) { + if (!self->stream()->isSequential()) + QMetaObject::invokeMethod(self, "doSeek", Qt::AutoConnection, Q_ARG(qint64, arg0)); + } + else + return false; + + return true; +} + +void QGstAppSrc::on_enough_data(GstAppSrc *element, gpointer userdata) +{ + Q_UNUSED(element); + QGstAppSrc *self = reinterpret_cast(userdata); + if (self) + self->enoughData() = true; +} + +void QGstAppSrc::on_need_data(GstAppSrc *element, guint arg0, gpointer userdata) +{ + Q_UNUSED(element); + QGstAppSrc *self = reinterpret_cast(userdata); + if (self) { + self->dataRequested() = true; + self->enoughData() = false; + self->dataRequestSize()= arg0; + QMetaObject::invokeMethod(self, "pushDataToAppSrc", Qt::AutoConnection); + } +} + +void QGstAppSrc::destroy_notify(gpointer data) +{ + Q_UNUSED(data); +} + +void QGstAppSrc::sendEOS() +{ + gst_app_src_end_of_stream(GST_APP_SRC(m_appSrc)); + if (isStreamValid() && !stream()->isSequential()) + stream()->reset(); +} diff --git a/src/plugins/gstreamer/qgstappsrc.h b/src/plugins/gstreamer/qgstappsrc.h new file mode 100644 index 000000000..dc817e8f0 --- /dev/null +++ b/src/plugins/gstreamer/qgstappsrc.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGSTAPPSRC_H +#define QGSTAPPSRC_H + +#include +#include + +#include +#include +#include + +class QGstAppSrc : public QObject +{ + Q_OBJECT +public: + QGstAppSrc(QObject *parent = 0); + ~QGstAppSrc(); + + bool setup(GstElement *); + bool isReady() const { return m_setup; } + + void setStream(QIODevice *); + QIODevice *stream() const; + + GstAppSrc *element(); + + qint64 queueSize() const { return m_maxBytes; } + + bool& enoughData() { return m_enoughData; } + bool& dataRequested() { return m_dataRequested; } + unsigned int& dataRequestSize() { return m_dataRequestSize; } + + bool isStreamValid() const + { + return m_stream != 0 && + m_stream->isOpen(); + } + +private slots: + void pushDataToAppSrc(); + bool doSeek(qint64); + void onDataReady(); + + void streamDestroyed(); +private: + static gboolean on_seek_data(GstAppSrc *element, guint64 arg0, gpointer userdata); + static void on_enough_data(GstAppSrc *element, gpointer userdata); + static void on_need_data(GstAppSrc *element, uint arg0, gpointer userdata); + static void destroy_notify(gpointer data); + + void sendEOS(); + + QIODevice *m_stream; + GstAppSrc *m_appSrc; + bool m_sequential; + GstAppStreamType m_streamType; + GstAppSrcCallbacks m_callbacks; + qint64 m_maxBytes; + bool m_setup; + unsigned int m_dataRequestSize; + bool m_dataRequested; + bool m_enoughData; + bool m_forceData; +}; + +#endif diff --git a/src/plugins/gstreamer/qgstreamerserviceplugin.cpp b/src/plugins/gstreamer/qgstreamerserviceplugin.cpp index d765fd70c..7c66eac13 100644 --- a/src/plugins/gstreamer/qgstreamerserviceplugin.cpp +++ b/src/plugins/gstreamer/qgstreamerserviceplugin.cpp @@ -60,6 +60,10 @@ #include "camerabinservice.h" #endif +#ifdef QMEDIA_GSTREAMER_AUDIO_DECODER +#include "qgstreameraudiodecoderservice.h" +#endif + #include #include @@ -81,7 +85,9 @@ QStringList QGstreamerServicePlugin::keys() const #ifdef QMEDIA_GSTREAMER_PLAYER << QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER) #endif - +#ifdef QMEDIA_GSTREAMER_AUDIO_DECODER + << QLatin1String(Q_MEDIASERVICE_AUDIODECODER) +#endif #ifdef QMEDIA_GSTREAMER_CAPTURE << QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE) << QLatin1String(Q_MEDIASERVICE_CAMERA) @@ -110,6 +116,11 @@ QMediaService* QGstreamerServicePlugin::create(const QString &key) return new CameraBinService(key); #endif +#ifdef QMEDIA_GSTREAMER_AUDIO_DECODER + if (key == QLatin1String(Q_MEDIASERVICE_AUDIODECODER)) + return new QGstreamerAudioDecoderService; +#endif + #ifdef QMEDIA_GSTREAMER_CAPTURE if (key == QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE)) return new QGstreamerCaptureService(key); -- cgit v1.2.3