Initial copy of QtMultimediaKit.

Comes from original repo, with SHA1:
2c82d5611655e5967f5c5095af50c0991c4378b2
This commit is contained in:
Michael Goddard
2011-06-29 13:38:46 +10:00
commit 2a34e88c1e
1048 changed files with 206259 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
INCLUDEPATH += $$PWD
DEFINES += QMEDIA_GSTREAMER_PLAYER
contains(gstreamer-appsrc_enabled, yes) {
HEADERS += $$PWD/qgstappsrc.h
SOURCES += $$PWD/qgstappsrc.cpp
DEFINES += HAVE_GST_APPSRC
LIBS += -lgstapp-0.10
}
HEADERS += \
$$PWD/qgstreamerplayercontrol.h \
$$PWD/qgstreamerplayerservice.h \
$$PWD/qgstreamerplayersession.h \
$$PWD/qgstreamerstreamscontrol.h \
$$PWD/qgstreamermetadataprovider.h \
$$PWD/playerresourcepolicy.h
SOURCES += \
$$PWD/qgstreamerplayercontrol.cpp \
$$PWD/qgstreamerplayerservice.cpp \
$$PWD/qgstreamerplayersession.cpp \
$$PWD/qgstreamerstreamscontrol.cpp \
$$PWD/qgstreamermetadataprovider.cpp \
$$PWD/playerresourcepolicy.cpp

View File

@@ -0,0 +1,180 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "playerresourcepolicy.h"
#ifdef Q_WS_MAEMO_6
#define HAVE_RESOURCE_POLICY
#endif
//#define DEBUG_RESOURCE_POLICY
#include <QtCore/qdebug.h>
#ifdef HAVE_RESOURCE_POLICY
#include <policy/resource.h>
#include <policy/resources.h>
#include <policy/resource-set.h>
#endif
PlayerResourcePolicy::PlayerResourcePolicy(QObject *parent) :
QObject(parent),
m_videoEnabled(true),
m_resourceSet(0),
m_status(PlayerResourcePolicy::Initial)
{
#ifdef HAVE_RESOURCE_POLICY
m_resourceSet = new ResourcePolicy::ResourceSet("player", this);
m_resourceSet->setAlwaysReply();
ResourcePolicy::AudioResource *audioResource = new ResourcePolicy::AudioResource("player");
audioResource->setProcessID(QCoreApplication::applicationPid());
audioResource->setStreamTag("media.name", "*");
m_resourceSet->addResourceObject(audioResource);
m_resourceSet->addResource(ResourcePolicy::VideoPlaybackType);
m_resourceSet->update();
connect(m_resourceSet, SIGNAL(resourcesGranted(const QList<ResourcePolicy::ResourceType>)),
this, SLOT(handleResourcesGranted()));
connect(m_resourceSet, SIGNAL(resourcesDenied()),
this, SLOT(handleResourcesDenied()));
connect(m_resourceSet, SIGNAL(lostResources()),
this, SLOT(handleResourcesLost()));
connect(m_resourceSet, SIGNAL(resourcesReleasedByManager()),
this, SLOT(handleResourcesLost()));
#endif
}
PlayerResourcePolicy::~PlayerResourcePolicy()
{
}
bool PlayerResourcePolicy::isVideoEnabled() const
{
return m_videoEnabled;
}
void PlayerResourcePolicy::setVideoEnabled(bool enabled)
{
if (m_videoEnabled != enabled) {
m_videoEnabled = enabled;
#ifdef HAVE_RESOURCE_POLICY
if (enabled)
m_resourceSet->addResource(ResourcePolicy::VideoPlaybackType);
else
m_resourceSet->deleteResource(ResourcePolicy::VideoPlaybackType);
m_resourceSet->update();
#endif
}
}
void PlayerResourcePolicy::acquire()
{
#ifdef HAVE_RESOURCE_POLICY
#ifdef DEBUG_RESOURCE_POLICY
qDebug() << Q_FUNC_INFO << "Acquire resource";
#endif
m_status = RequestedResource;
m_resourceSet->acquire();
#else
m_status = GrantedResource;
#endif
}
void PlayerResourcePolicy::release()
{
#ifdef HAVE_RESOURCE_POLICY
#ifdef DEBUG_RESOURCE_POLICY
qDebug() << Q_FUNC_INFO << "Release resource";
#endif
m_resourceSet->release();
#endif
m_status = Initial;
}
bool PlayerResourcePolicy::isGranted() const
{
return m_status == GrantedResource;
}
bool PlayerResourcePolicy::isRequested() const
{
return m_status == RequestedResource;
}
void PlayerResourcePolicy::handleResourcesGranted()
{
m_status = GrantedResource;
#ifdef DEBUG_RESOURCE_POLICY
qDebug() << Q_FUNC_INFO << "Resource granted";
#endif
emit resourcesGranted();
}
void PlayerResourcePolicy::handleResourcesDenied()
{
m_status = Initial;
#ifdef DEBUG_RESOURCE_POLICY
qDebug() << Q_FUNC_INFO << "Resource denied";
#endif
emit resourcesDenied();
}
void PlayerResourcePolicy::handleResourcesLost()
{
#ifdef DEBUG_RESOURCE_POLICY
qDebug() << Q_FUNC_INFO << "Resource lost";
#endif
if (m_status != Initial) {
m_status = Initial;
emit resourcesLost();
}
#ifdef HAVE_RESOURCE_POLICY
m_resourceSet->release();
#endif
}

View File

@@ -0,0 +1,90 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef PLAYERRESOURCEPOLICY_H
#define PLAYERRESOURCEPOLICY_H
#include <QtCore/qobject.h>
namespace ResourcePolicy {
class ResourceSet;
};
class PlayerResourcePolicy : public QObject
{
Q_OBJECT
public:
PlayerResourcePolicy(QObject *parent = 0);
~PlayerResourcePolicy();
bool isVideoEnabled() const;
bool isGranted() const;
bool isRequested() const;
Q_SIGNALS:
void resourcesDenied();
void resourcesGranted();
void resourcesLost();
public Q_SLOTS:
void acquire();
void release();
void setVideoEnabled(bool enabled);
private Q_SLOTS:
void handleResourcesGranted();
void handleResourcesDenied();
void handleResourcesLost();
private:
enum ResourceStatus {
Initial = 0,
RequestedResource,
GrantedResource
};
bool m_videoEnabled;
ResourcePolicy::ResourceSet *m_resourceSet;
ResourceStatus m_status;
};
#endif

View File

@@ -0,0 +1,224 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QDebug>
#include "qgstappsrc.h"
#include <QtNetwork>
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)
{
}
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);
m_callbacks.need_data = &QGstAppSrc::on_need_data;
m_callbacks.enough_data = &QGstAppSrc::on_enough_data;
m_callbacks.seek_data = &QGstAppSrc::on_seek_data;
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)
{
QGstAppSrc *self = reinterpret_cast<QGstAppSrc*>(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)
{
QGstAppSrc *self = reinterpret_cast<QGstAppSrc*>(userdata);
if (self)
self->enoughData() = true;
}
void QGstAppSrc::on_need_data(GstAppSrc *element, guint arg0, gpointer userdata)
{
QGstAppSrc *self = reinterpret_cast<QGstAppSrc*>(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();
}

View File

@@ -0,0 +1,106 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGSTAPPSRC_H
#define QGSTAPPSRC_H
#include <QtCore/qobject.h>
#include <QtCore/qiodevice.h>
#include <gst/gst.h>
#include <gst/app/gstappsrc.h>
#include <gst/app/gstappbuffer.h>
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

View File

@@ -0,0 +1,192 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qgstreamermetadataprovider.h"
#include "qgstreamerplayersession.h"
#include <QDebug>
#include <gst/gstversion.h>
struct QGstreamerMetaDataKeyLookup
{
QtMultimediaKit::MetaData key;
const char *token;
};
static const QGstreamerMetaDataKeyLookup qt_gstreamerMetaDataKeys[] =
{
{ QtMultimediaKit::Title, GST_TAG_TITLE },
//{ QtMultimediaKit::SubTitle, 0 },
//{ QtMultimediaKit::Author, 0 },
{ QtMultimediaKit::Comment, GST_TAG_COMMENT },
{ QtMultimediaKit::Description, GST_TAG_DESCRIPTION },
//{ QtMultimediaKit::Category, 0 },
{ QtMultimediaKit::Genre, GST_TAG_GENRE },
{ QtMultimediaKit::Year, "year" },
//{ QtMultimediaKit::UserRating, 0 },
{ QtMultimediaKit::Language, GST_TAG_LANGUAGE_CODE },
{ QtMultimediaKit::Publisher, GST_TAG_ORGANIZATION },
{ QtMultimediaKit::Copyright, GST_TAG_COPYRIGHT },
//{ QtMultimediaKit::ParentalRating, 0 },
//{ QtMultimediaKit::RatingOrganisation, 0 },
// Media
//{ QtMultimediaKit::Size, 0 },
//{ QtMultimediaKit::MediaType, 0 },
{ QtMultimediaKit::Duration, GST_TAG_DURATION },
// Audio
{ QtMultimediaKit::AudioBitRate, GST_TAG_BITRATE },
{ QtMultimediaKit::AudioCodec, GST_TAG_AUDIO_CODEC },
//{ QtMultimediaKit::ChannelCount, 0 },
//{ QtMultimediaKit::SampleRate, 0 },
// Music
{ QtMultimediaKit::AlbumTitle, GST_TAG_ALBUM },
{ QtMultimediaKit::AlbumArtist, GST_TAG_ARTIST},
{ QtMultimediaKit::ContributingArtist, GST_TAG_PERFORMER },
#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19)
{ QtMultimediaKit::Composer, GST_TAG_COMPOSER },
#endif
//{ QtMultimediaKit::Conductor, 0 },
//{ QtMultimediaKit::Lyrics, 0 },
//{ QtMultimediaKit::Mood, 0 },
{ QtMultimediaKit::TrackNumber, GST_TAG_TRACK_NUMBER },
//{ QtMultimediaKit::CoverArtUrlSmall, 0 },
//{ QtMultimediaKit::CoverArtUrlLarge, 0 },
// Image/Video
{ QtMultimediaKit::Resolution, "resolution" },
{ QtMultimediaKit::PixelAspectRatio, "pixel-aspect-ratio" },
// Video
//{ QtMultimediaKit::VideoFrameRate, 0 },
//{ QtMultimediaKit::VideoBitRate, 0 },
{ QtMultimediaKit::VideoCodec, GST_TAG_VIDEO_CODEC },
//{ QtMultimediaKit::PosterUrl, 0 },
// Movie
//{ QtMultimediaKit::ChapterNumber, 0 },
//{ QtMultimediaKit::Director, 0 },
{ QtMultimediaKit::LeadPerformer, GST_TAG_PERFORMER },
//{ QtMultimediaKit::Writer, 0 },
// Photos
//{ QtMultimediaKit::CameraManufacturer, 0 },
//{ QtMultimediaKit::CameraModel, 0 },
//{ QtMultimediaKit::Event, 0 },
//{ QtMultimediaKit::Subject, 0 }
};
QGstreamerMetaDataProvider::QGstreamerMetaDataProvider(QGstreamerPlayerSession *session, QObject *parent)
:QMetaDataReaderControl(parent), m_session(session)
{
connect(m_session, SIGNAL(tagsChanged()), SLOT(updateTags()));
}
QGstreamerMetaDataProvider::~QGstreamerMetaDataProvider()
{
}
bool QGstreamerMetaDataProvider::isMetaDataAvailable() const
{
return !m_session->tags().isEmpty();
}
bool QGstreamerMetaDataProvider::isWritable() const
{
return false;
}
QVariant QGstreamerMetaDataProvider::metaData(QtMultimediaKit::MetaData key) const
{
static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup);
for (int i = 0; i < count; ++i) {
if (qt_gstreamerMetaDataKeys[i].key == key) {
return m_session->tags().value(QByteArray(qt_gstreamerMetaDataKeys[i].token));
}
}
return QVariant();
}
QList<QtMultimediaKit::MetaData> QGstreamerMetaDataProvider::availableMetaData() const
{
static QMap<QByteArray, QtMultimediaKit::MetaData> keysMap;
if (keysMap.isEmpty()) {
const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup);
for (int i = 0; i < count; ++i) {
keysMap[QByteArray(qt_gstreamerMetaDataKeys[i].token)] = qt_gstreamerMetaDataKeys[i].key;
}
}
QList<QtMultimediaKit::MetaData> res;
foreach (const QByteArray &key, m_session->tags().keys()) {
QtMultimediaKit::MetaData tag = keysMap.value(key, QtMultimediaKit::MetaData(-1));
if (tag != -1)
res.append(tag);
}
return res;
}
QVariant QGstreamerMetaDataProvider::extendedMetaData(const QString &key) const
{
return m_session->tags().value(key.toLatin1());
}
QStringList QGstreamerMetaDataProvider::availableExtendedMetaData() const
{
QStringList res;
foreach (const QByteArray &key, m_session->tags().keys())
res.append(QString(key));
return res;
}
void QGstreamerMetaDataProvider::updateTags()
{
emit metaDataChanged();
}

View File

@@ -0,0 +1,74 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGSTREAMERMETADATAPROVIDER_H
#define QGSTREAMERMETADATAPROVIDER_H
#include <qmetadatareadercontrol.h>
QT_USE_NAMESPACE
class QGstreamerPlayerSession;
class QGstreamerMetaDataProvider : public QMetaDataReaderControl
{
Q_OBJECT
public:
QGstreamerMetaDataProvider( QGstreamerPlayerSession *session, QObject *parent );
virtual ~QGstreamerMetaDataProvider();
bool isMetaDataAvailable() const;
bool isWritable() const;
QVariant metaData(QtMultimediaKit::MetaData key) const;
QList<QtMultimediaKit::MetaData> availableMetaData() const;
QVariant extendedMetaData(const QString &key) const ;
QStringList availableExtendedMetaData() const;
private slots:
void updateTags();
private:
QGstreamerPlayerSession *m_session;
};
#endif // QGSTREAMERMETADATAPROVIDER_H

View File

@@ -0,0 +1,748 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qgstreamerplayercontrol.h"
#include "qgstreamerplayersession.h"
#include "playerresourcepolicy.h"
#include <qmediaplaylistnavigator.h>
#include <QtCore/qdir.h>
#include <QtCore/qsocketnotifier.h>
#include <QtCore/qurl.h>
#include <QtCore/qdebug.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
//#define DEBUG_PLAYBIN
QGstreamerPlayerControl::QGstreamerPlayerControl(QGstreamerPlayerSession *session, QObject *parent)
: QMediaPlayerControl(parent)
, m_ownStream(false)
, m_session(session)
, m_state(QMediaPlayer::StoppedState)
, m_mediaStatus(QMediaPlayer::NoMedia)
, m_bufferProgress(-1)
, m_seekToStartPending(false)
, m_pendingSeekPosition(-1)
, m_stream(0)
, m_fifoNotifier(0)
, m_fifoCanWrite(false)
, m_bufferSize(0)
, m_bufferOffset(0)
{
m_fifoFd[0] = -1;
m_fifoFd[1] = -1;
m_resources = new PlayerResourcePolicy(this);
connect(m_session, SIGNAL(positionChanged(qint64)),
this, SIGNAL(positionChanged(qint64)));
connect(m_session, SIGNAL(durationChanged(qint64)),
this, SIGNAL(durationChanged(qint64)));
connect(m_session, SIGNAL(mutedStateChanged(bool)),
this, SIGNAL(mutedChanged(bool)));
connect(m_session, SIGNAL(volumeChanged(int)),
this, SIGNAL(volumeChanged(int)));
connect(m_session, SIGNAL(stateChanged(QMediaPlayer::State)),
this, SLOT(updateSessionState(QMediaPlayer::State)));
connect(m_session,SIGNAL(bufferingProgressChanged(int)),
this, SLOT(setBufferProgress(int)));
connect(m_session, SIGNAL(playbackFinished()),
this, SLOT(processEOS()));
connect(m_session, SIGNAL(audioAvailableChanged(bool)),
this, SIGNAL(audioAvailableChanged(bool)));
connect(m_session, SIGNAL(videoAvailableChanged(bool)),
this, SIGNAL(videoAvailableChanged(bool)));
connect(m_session, SIGNAL(seekableChanged(bool)),
this, SIGNAL(seekableChanged(bool)));
connect(m_session, SIGNAL(error(int,QString)),
this, SIGNAL(error(int,QString)));
connect(m_session, SIGNAL(invalidMedia()),
this, SLOT(handleInvalidMedia()));
connect(m_session, SIGNAL(playbackRateChanged(qreal)),
this, SIGNAL(playbackRateChanged(qreal)));
connect(m_session, SIGNAL(seekableChanged(bool)),
this, SLOT(applyPendingSeek(bool)));
connect(m_resources, SIGNAL(resourcesGranted()), SLOT(handleResourcesGranted()));
connect(m_resources, SIGNAL(resourcesDenied()), SLOT(handleResourcesLost()));
connect(m_resources, SIGNAL(resourcesLost()), SLOT(handleResourcesLost()));
}
QGstreamerPlayerControl::~QGstreamerPlayerControl()
{
if (m_fifoFd[0] >= 0) {
::close(m_fifoFd[0]);
::close(m_fifoFd[1]);
m_fifoFd[0] = -1;
m_fifoFd[1] = -1;
}
}
qint64 QGstreamerPlayerControl::position() const
{
return m_seekToStartPending ? 0 : m_session->position();
}
qint64 QGstreamerPlayerControl::duration() const
{
return m_session->duration();
}
QMediaPlayer::State QGstreamerPlayerControl::state() const
{
return m_state;
}
QMediaPlayer::MediaStatus QGstreamerPlayerControl::mediaStatus() const
{
return m_mediaStatus;
}
int QGstreamerPlayerControl::bufferStatus() const
{
if (m_bufferProgress == -1) {
return m_session->state() == QMediaPlayer::StoppedState ? 0 : 100;
} else
return m_bufferProgress;
}
int QGstreamerPlayerControl::volume() const
{
return m_session->volume();
}
bool QGstreamerPlayerControl::isMuted() const
{
return m_session->isMuted();
}
bool QGstreamerPlayerControl::isSeekable() const
{
return m_session->isSeekable();
}
QMediaTimeRange QGstreamerPlayerControl::availablePlaybackRanges() const
{
return m_session->availablePlaybackRanges();
}
qreal QGstreamerPlayerControl::playbackRate() const
{
return m_session->playbackRate();
}
void QGstreamerPlayerControl::setPlaybackRate(qreal rate)
{
m_session->setPlaybackRate(rate);
}
void QGstreamerPlayerControl::setPosition(qint64 pos)
{
#ifdef DEBUG_PLAYBIN
qDebug() << Q_FUNC_INFO << pos/1000.0;
#endif
pushState();
if (m_mediaStatus == QMediaPlayer::EndOfMedia) {
m_mediaStatus = QMediaPlayer::LoadedMedia;
m_seekToStartPending = true;
}
if (m_session->isSeekable() && m_session->seek(pos)) {
m_seekToStartPending = false;
m_pendingSeekPosition = -1;
} else {
m_pendingSeekPosition = pos;
}
popAndNotifyState();
}
void QGstreamerPlayerControl::play()
{
#ifdef DEBUG_PLAYBIN
qDebug() << Q_FUNC_INFO;
#endif
playOrPause(QMediaPlayer::PlayingState);
}
void QGstreamerPlayerControl::pause()
{
#ifdef DEBUG_PLAYBIN
qDebug() << Q_FUNC_INFO;
#endif
playOrPause(QMediaPlayer::PausedState);
}
void QGstreamerPlayerControl::playOrPause(QMediaPlayer::State newState)
{
if (m_mediaStatus == QMediaPlayer::NoMedia)
return;
pushState();
#ifdef Q_WS_MAEMO_6
//this is a work around for the gstreamer bug,
//should be remove once it get fixed
if (newState == QMediaPlayer::PlayingState && m_mediaStatus == QMediaPlayer::InvalidMedia) {
setMedia(m_currentResource, m_stream);
}
#endif
if (m_mediaStatus == QMediaPlayer::EndOfMedia) {
m_mediaStatus = QMediaPlayer::BufferedMedia;
m_seekToStartPending = true;
}
if (!m_resources->isGranted() && !m_resources->isRequested())
m_resources->acquire();
if (m_resources->isGranted()) {
if (m_seekToStartPending) {
m_session->pause();
if (!m_session->seek(0)) {
m_bufferProgress = -1;
m_session->stop();
m_mediaStatus = QMediaPlayer::LoadingMedia;
}
m_seekToStartPending = false;
}
bool ok = false;
if (newState == QMediaPlayer::PlayingState)
ok = m_session->play();
else
ok = m_session->pause();
if (!ok)
newState = QMediaPlayer::StoppedState;
}
if (m_mediaStatus == QMediaPlayer::InvalidMedia)
m_mediaStatus = QMediaPlayer::LoadingMedia;
m_state = newState;
if (m_mediaStatus == QMediaPlayer::EndOfMedia || m_mediaStatus == QMediaPlayer::LoadedMedia) {
if (m_bufferProgress == -1 || m_bufferProgress == 100)
m_mediaStatus = QMediaPlayer::BufferedMedia;
else
m_mediaStatus = QMediaPlayer::BufferingMedia;
}
popAndNotifyState();
emit positionChanged(position());
}
void QGstreamerPlayerControl::stop()
{
#ifdef DEBUG_PLAYBIN
qDebug() << Q_FUNC_INFO;
#endif
pushState();
if (m_state != QMediaPlayer::StoppedState) {
m_state = QMediaPlayer::StoppedState;
if (m_resources->isGranted())
m_session->pause();
if (m_mediaStatus != QMediaPlayer::EndOfMedia) {
m_seekToStartPending = true;
emit positionChanged(position());
}
}
popAndNotifyState();
}
void QGstreamerPlayerControl::setVolume(int volume)
{
m_session->setVolume(volume);
}
void QGstreamerPlayerControl::setMuted(bool muted)
{
m_session->setMuted(muted);
}
QMediaContent QGstreamerPlayerControl::media() const
{
return m_currentResource;
}
const QIODevice *QGstreamerPlayerControl::mediaStream() const
{
return m_stream;
}
void QGstreamerPlayerControl::setMedia(const QMediaContent &content, QIODevice *stream)
{
#ifdef DEBUG_PLAYBIN
qDebug() << Q_FUNC_INFO;
#endif
pushState();
m_state = QMediaPlayer::StoppedState;
QMediaContent oldMedia = m_currentResource;
m_pendingSeekPosition = -1;
if (!content.isNull() || stream) {
if (!m_resources->isRequested() && !m_resources->isGranted())
m_resources->acquire();
if (!m_resources->isGranted()) {
m_currentResource = content;
m_stream = stream;
m_state = QMediaPlayer::StoppedState;
m_mediaStatus = QMediaPlayer::LoadingMedia;
if (m_currentResource != oldMedia)
emit mediaChanged(m_currentResource);
popAndNotifyState();
return;
}
} else {
m_resources->release();
}
m_session->stop();
bool userStreamValid = false;
if (m_bufferProgress != -1) {
m_bufferProgress = -1;
emit bufferStatusChanged(0);
}
if (m_stream) {
#if !defined(HAVE_GST_APPSRC)
closeFifo();
disconnect(m_stream, SIGNAL(readyRead()), this, SLOT(writeFifo()));
#endif
if (m_ownStream)
delete m_stream;
m_stream = 0;
m_ownStream = false;
}
// If the canonical URL refers to a Qt resource, open with QFile and use
// the stream playback capability to play.
if (stream == 0 && content.canonicalUrl().scheme() == QLatin1String("qrc")) {
stream = new QFile(QLatin1Char(':') + content.canonicalUrl().path(), this);
if (!stream->open(QIODevice::ReadOnly)) {
delete stream;
m_mediaStatus = QMediaPlayer::InvalidMedia;
m_currentResource = content;
emit mediaChanged(m_currentResource);
emit error(QMediaPlayer::FormatError, tr("Attempting to play invalid Qt resource"));
if (m_state != QMediaPlayer::PlayingState)
m_resources->release();
popAndNotifyState();
return;
}
m_ownStream = true;
}
m_currentResource = content;
m_stream = stream;
m_seekToStartPending = false;
QNetworkRequest request;
if (m_stream) {
#if !defined(HAVE_GST_APPSRC)
if (m_stream->isReadable() && openFifo()) {
request = QNetworkRequest(QUrl(QString(QLatin1String("fd://%1")).arg(m_fifoFd[0])));
}
#else
userStreamValid = stream->isOpen() && m_stream->isReadable();
request = content.canonicalRequest();
#endif
} else if (!content.isNull()) {
request = content.canonicalRequest();
}
#if !defined(HAVE_GST_APPSRC)
m_session->loadFromUri(request);
#else
if (m_stream) {
if (userStreamValid){
m_session->loadFromStream(request, m_stream);
} else {
m_mediaStatus = QMediaPlayer::InvalidMedia;
emit error(QMediaPlayer::FormatError, tr("Attempting to play invalid user stream"));
if (m_state != QMediaPlayer::PlayingState)
m_resources->release();
popAndNotifyState();
return;
}
} else
m_session->loadFromUri(request);
#endif
#if !defined(HAVE_GST_APPSRC)
if (m_fifoFd[1] >= 0) {
m_fifoCanWrite = true;
writeFifo();
}
#endif
#if defined(HAVE_GST_APPSRC)
if (!request.url().isEmpty() || userStreamValid) {
#else
if (!request.url().isEmpty()) {
#endif
m_mediaStatus = QMediaPlayer::LoadingMedia;
m_session->pause();
} else {
m_mediaStatus = QMediaPlayer::NoMedia;
setBufferProgress(0);
}
if (m_currentResource != oldMedia)
emit mediaChanged(m_currentResource);
emit positionChanged(position());
if (content.isNull() && !stream)
m_resources->release();
popAndNotifyState();
}
void QGstreamerPlayerControl::setVideoOutput(QObject *output)
{
m_session->setVideoRenderer(output);
}
bool QGstreamerPlayerControl::isAudioAvailable() const
{
return m_session->isAudioAvailable();
}
bool QGstreamerPlayerControl::isVideoAvailable() const
{
return m_session->isVideoAvailable();
}
void QGstreamerPlayerControl::updateSessionState(QMediaPlayer::State state)
{
pushState();
if (state == QMediaPlayer::StoppedState)
m_state = QMediaPlayer::StoppedState;
updateMediaStatus();
popAndNotifyState();
}
void QGstreamerPlayerControl::updateMediaStatus()
{
pushState();
QMediaPlayer::MediaStatus oldStatus = m_mediaStatus;
switch (m_session->state()) {
case QMediaPlayer::StoppedState:
if (m_currentResource.isNull())
m_mediaStatus = QMediaPlayer::NoMedia;
else if (oldStatus != QMediaPlayer::InvalidMedia)
m_mediaStatus = QMediaPlayer::LoadingMedia;
break;
case QMediaPlayer::PlayingState:
case QMediaPlayer::PausedState:
if (m_state == QMediaPlayer::StoppedState) {
m_mediaStatus = QMediaPlayer::LoadedMedia;
} else {
if (m_bufferProgress == -1 || m_bufferProgress == 100)
m_mediaStatus = QMediaPlayer::BufferedMedia;
else
m_mediaStatus = QMediaPlayer::StalledMedia;
}
break;
}
if (m_state == QMediaPlayer::PlayingState && !m_resources->isGranted())
m_mediaStatus = QMediaPlayer::StalledMedia;
//EndOfMedia status should be kept, until reset by pause, play or setMedia
if (oldStatus == QMediaPlayer::EndOfMedia)
m_mediaStatus = QMediaPlayer::EndOfMedia;
popAndNotifyState();
}
void QGstreamerPlayerControl::processEOS()
{
pushState();
m_mediaStatus = QMediaPlayer::EndOfMedia;
emit positionChanged(position());
stop();
popAndNotifyState();
}
void QGstreamerPlayerControl::setBufferProgress(int progress)
{
if (m_bufferProgress == progress || m_mediaStatus == QMediaPlayer::NoMedia)
return;
#ifdef DEBUG_PLAYBIN
qDebug() << Q_FUNC_INFO << progress;
#endif
m_bufferProgress = progress;
if (m_resources->isGranted()) {
if (m_state == QMediaPlayer::PlayingState &&
m_bufferProgress == 100 &&
m_session->state() != QMediaPlayer::PlayingState)
m_session->play();
if (m_bufferProgress < 100 &&
(m_session->state() == QMediaPlayer::PlayingState ||
m_session->pendingState() == QMediaPlayer::PlayingState))
m_session->pause();
}
updateMediaStatus();
emit bufferStatusChanged(m_bufferProgress);
}
void QGstreamerPlayerControl::writeFifo()
{
if (m_fifoCanWrite) {
qint64 bytesToRead = qMin<qint64>(
m_stream->bytesAvailable(), PIPE_BUF - m_bufferSize);
if (bytesToRead > 0) {
int bytesRead = m_stream->read(&m_buffer[m_bufferOffset + m_bufferSize], bytesToRead);
if (bytesRead > 0)
m_bufferSize += bytesRead;
}
if (m_bufferSize > 0) {
int bytesWritten = ::write(m_fifoFd[1], &m_buffer[m_bufferOffset], size_t(m_bufferSize));
if (bytesWritten > 0) {
m_bufferOffset += bytesWritten;
m_bufferSize -= bytesWritten;
if (m_bufferSize == 0)
m_bufferOffset = 0;
} else if (errno == EAGAIN) {
m_fifoCanWrite = false;
} else {
closeFifo();
}
}
}
m_fifoNotifier->setEnabled(m_stream->bytesAvailable() > 0);
}
void QGstreamerPlayerControl::fifoReadyWrite(int socket)
{
if (socket == m_fifoFd[1]) {
m_fifoCanWrite = true;
writeFifo();
}
}
bool QGstreamerPlayerControl::openFifo()
{
Q_ASSERT(m_fifoFd[0] < 0);
Q_ASSERT(m_fifoFd[1] < 0);
if (::pipe(m_fifoFd) == 0) {
int flags = ::fcntl(m_fifoFd[1], F_GETFD);
if (::fcntl(m_fifoFd[1], F_SETFD, flags | O_NONBLOCK) >= 0) {
m_fifoNotifier = new QSocketNotifier(m_fifoFd[1], QSocketNotifier::Write);
connect(m_fifoNotifier, SIGNAL(activated(int)), this, SLOT(fifoReadyWrite(int)));
return true;
} else {
qWarning("Failed to make pipe non blocking %d", errno);
::close(m_fifoFd[0]);
::close(m_fifoFd[1]);
m_fifoFd[0] = -1;
m_fifoFd[1] = -1;
return false;
}
} else {
qWarning("Failed to create pipe %d", errno);
return false;
}
}
void QGstreamerPlayerControl::closeFifo()
{
if (m_fifoFd[0] >= 0) {
delete m_fifoNotifier;
m_fifoNotifier = 0;
::close(m_fifoFd[0]);
::close(m_fifoFd[1]);
m_fifoFd[0] = -1;
m_fifoFd[1] = -1;
m_fifoCanWrite = false;
m_bufferSize = 0;
m_bufferOffset = 0;
}
}
void QGstreamerPlayerControl::applyPendingSeek(bool isSeekable)
{
if (isSeekable && m_pendingSeekPosition != -1)
setPosition(m_pendingSeekPosition);
}
void QGstreamerPlayerControl::handleInvalidMedia()
{
pushState();
m_mediaStatus = QMediaPlayer::InvalidMedia;
m_state = QMediaPlayer::StoppedState;
popAndNotifyState();
}
void QGstreamerPlayerControl::handleResourcesGranted()
{
pushState();
QMediaPlayer::State state = m_state;
//preserve m_pendingSeekPosition, it's reset on setMedia
qint64 pos = m_pendingSeekPosition;
setMedia(m_currentResource, m_stream);
if (pos != -1)
setPosition(pos);
if (state != QMediaPlayer::StoppedState)
playOrPause(state);
else
updateMediaStatus();
popAndNotifyState();
}
void QGstreamerPlayerControl::handleResourcesLost()
{
//on resource lost the pipeline should be stopped
//player status is changed to paused
pushState();
QMediaPlayer::State oldState = m_state;
qint64 pos = m_session->position();
m_session->stop();
m_pendingSeekPosition = pos;
if (oldState != QMediaPlayer::StoppedState )
m_state = QMediaPlayer::PausedState;
popAndNotifyState();
}
bool QGstreamerPlayerControl::isMediaDownloadEnabled() const
{
return m_session->property("mediaDownloadEnabled").toBool();
}
void QGstreamerPlayerControl::setMediaDownloadEnabled(bool enabled)
{
m_session->setProperty("mediaDownloadEnabled", enabled);
}
void QGstreamerPlayerControl::pushState()
{
m_stateStack.push(m_state);
m_mediaStatusStack.push(m_mediaStatus);
}
void QGstreamerPlayerControl::popAndNotifyState()
{
Q_ASSERT(!m_stateStack.isEmpty());
QMediaPlayer::State oldState = m_stateStack.pop();
QMediaPlayer::MediaStatus oldMediaStatus = m_mediaStatusStack.pop();
if (m_stateStack.isEmpty()) {
if (m_state != oldState) {
#ifdef DEBUG_PLAYBIN
qDebug() << "State changed:" << m_state;
#endif
emit stateChanged(m_state);
}
if (m_mediaStatus != oldMediaStatus) {
#ifdef DEBUG_PLAYBIN
qDebug() << "Media status changed:" << m_mediaStatus;
#endif
emit mediaStatusChanged(m_mediaStatus);
}
}
}

View File

@@ -0,0 +1,157 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGSTREAMERPLAYERCONTROL_H
#define QGSTREAMERPLAYERCONTROL_H
#include <QtCore/qobject.h>
#include <QtCore/qstack.h>
#include <qmediaplayercontrol.h>
#include <qmediaplayer.h>
#include <limits.h>
QT_BEGIN_NAMESPACE
class QMediaPlaylist;
class QMediaPlaylistNavigator;
class QSocketNotifier;
QT_END_NAMESPACE
QT_USE_NAMESPACE
class QGstreamerPlayerSession;
class QGstreamerPlayerService;
class PlayerResourcePolicy;
class QGstreamerPlayerControl : public QMediaPlayerControl
{
Q_OBJECT
Q_PROPERTY(bool mediaDownloadEnabled READ isMediaDownloadEnabled WRITE setMediaDownloadEnabled)
public:
QGstreamerPlayerControl(QGstreamerPlayerSession *session, QObject *parent = 0);
~QGstreamerPlayerControl();
QMediaPlayer::State state() const;
QMediaPlayer::MediaStatus mediaStatus() const;
qint64 position() const;
qint64 duration() const;
int bufferStatus() const;
int volume() const;
bool isMuted() const;
bool isAudioAvailable() const;
bool isVideoAvailable() const;
void setVideoOutput(QObject *output);
bool isSeekable() const;
QMediaTimeRange availablePlaybackRanges() const;
qreal playbackRate() const;
void setPlaybackRate(qreal rate);
QMediaContent media() const;
const QIODevice *mediaStream() const;
void setMedia(const QMediaContent&, QIODevice *);
bool isMediaDownloadEnabled() const;
void setMediaDownloadEnabled(bool enabled);
public Q_SLOTS:
void setPosition(qint64 pos);
void play();
void pause();
void stop();
void setVolume(int volume);
void setMuted(bool muted);
private Q_SLOTS:
void writeFifo();
void fifoReadyWrite(int socket);
void updateSessionState(QMediaPlayer::State state);
void updateMediaStatus();
void processEOS();
void setBufferProgress(int progress);
void applyPendingSeek(bool isSeekable);
void handleInvalidMedia();
void handleResourcesGranted();
void handleResourcesLost();
private:
bool openFifo();
void closeFifo();
void playOrPause(QMediaPlayer::State state);
void pushState();
void popAndNotifyState();
bool m_ownStream;
QGstreamerPlayerSession *m_session;
QMediaPlayer::State m_state;
QMediaPlayer::MediaStatus m_mediaStatus;
QStack<QMediaPlayer::State> m_stateStack;
QStack<QMediaPlayer::MediaStatus> m_mediaStatusStack;
int m_bufferProgress;
bool m_seekToStartPending;
qint64 m_pendingSeekPosition;
QMediaContent m_currentResource;
QIODevice *m_stream;
QSocketNotifier *m_fifoNotifier;
int m_fifoFd[2];
bool m_fifoCanWrite;
int m_bufferSize;
int m_bufferOffset;
char m_buffer[PIPE_BUF];
PlayerResourcePolicy *m_resources;
};
#endif

View File

@@ -0,0 +1,134 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/qvariant.h>
#include <QtCore/qdebug.h>
#include <QtGui/qwidget.h>
#include "qgstreamerplayerservice.h"
#include "qgstreamerplayercontrol.h"
#include "qgstreamerplayersession.h"
#include "qgstreamermetadataprovider.h"
#include "qgstreamervideooverlay.h"
#include "qgstreamervideowindow.h"
#include "qgstreamervideorenderer.h"
#if defined(Q_WS_MAEMO_6) && defined(__arm__)
#include "qgstreamergltexturerenderer.h"
#endif
#include "qgstreamervideowidget.h"
#include "qgstreamerstreamscontrol.h"
#include <qmediaplaylistnavigator.h>
#include <qmediaplaylist.h>
QGstreamerPlayerService::QGstreamerPlayerService(QObject *parent):
QMediaService(parent),
m_videoOutput(0),
m_videoRenderer(0),
m_videoWindow(0),
m_videoWidget(0)
{
m_session = new QGstreamerPlayerSession(this);
m_control = new QGstreamerPlayerControl(m_session, this);
m_metaData = new QGstreamerMetaDataProvider(m_session, this);
m_streamsControl = new QGstreamerStreamsControl(m_session,this);
#if defined(Q_WS_MAEMO_6) && defined(__arm__)
m_videoRenderer = new QGstreamerGLTextureRenderer(this);
#else
m_videoRenderer = new QGstreamerVideoRenderer(this);
#endif
#if defined(Q_WS_X11) && !defined(QT_NO_XVIDEO)
#ifdef Q_WS_MAEMO_6
m_videoWindow = new QGstreamerVideoWindow(this, "omapxvsink");
#else
m_videoWindow = new QGstreamerVideoOverlay(this);
#endif
m_videoWidget = new QGstreamerVideoWidgetControl(this);
#endif
}
QGstreamerPlayerService::~QGstreamerPlayerService()
{
}
QMediaControl *QGstreamerPlayerService::requestControl(const char *name)
{
if (qstrcmp(name,QMediaPlayerControl_iid) == 0)
return m_control;
if (qstrcmp(name,QMetaDataReaderControl_iid) == 0)
return m_metaData;
if (qstrcmp(name,QMediaStreamsControl_iid) == 0)
return m_streamsControl;
if (!m_videoOutput) {
if (qstrcmp(name, QVideoWidgetControl_iid) == 0)
m_videoOutput = m_videoWidget;
else if (qstrcmp(name, QVideoRendererControl_iid) == 0)
m_videoOutput = m_videoRenderer;
else if (qstrcmp(name, QVideoWindowControl_iid) == 0)
m_videoOutput = m_videoWindow;
if (m_videoOutput) {
m_control->setVideoOutput(m_videoOutput);
return m_videoOutput;
}
}
return 0;
}
void QGstreamerPlayerService::releaseControl(QMediaControl *control)
{
if (control == m_videoOutput) {
m_videoOutput = 0;
m_control->setVideoOutput(0);
}
}

View File

@@ -0,0 +1,90 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGSTREAMERPLAYERSERVICE_H
#define QGSTREAMERPLAYERSERVICE_H
#include <QtCore/qobject.h>
#include <QtCore/qiodevice.h>
#include <qmediaservice.h>
QT_BEGIN_NAMESPACE
class QMediaMetaData;
class QMediaPlayerControl;
class QMediaPlaylist;
class QMediaPlaylistNavigator;
QT_END_NAMESPACE
class QGstreamerMetaData;
class QGstreamerPlayerControl;
class QGstreamerPlayerSession;
class QGstreamerMetaDataProvider;
class QGstreamerStreamsControl;
class QGstreamerVideoRenderer;
class QGstreamerVideoOverlay;
class QGstreamerVideoWidgetControl;
QT_USE_NAMESPACE
class QGstreamerPlayerService : public QMediaService
{
Q_OBJECT
public:
QGstreamerPlayerService(QObject *parent = 0);
~QGstreamerPlayerService();
QMediaControl *requestControl(const char *name);
void releaseControl(QMediaControl *control);
private:
QGstreamerPlayerControl *m_control;
QGstreamerPlayerSession *m_session;
QGstreamerMetaDataProvider *m_metaData;
QGstreamerStreamsControl *m_streamsControl;
QMediaControl *m_videoOutput;
QMediaControl *m_videoRenderer;
QMediaControl *m_videoWindow;
QMediaControl *m_videoWidget;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,217 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGSTREAMERPLAYERSESSION_H
#define QGSTREAMERPLAYERSESSION_H
#include <QObject>
#include <QtNetwork/qnetworkrequest.h>
#include "qgstreamerplayercontrol.h"
#include "qgstreamerbushelper.h"
#include <qmediaplayer.h>
#include <qmediastreamscontrol.h>
#if defined(HAVE_GST_APPSRC)
#include "qgstappsrc.h"
#endif
#include <gst/gst.h>
class QGstreamerBusHelper;
class QGstreamerMessage;
class QGstreamerVideoRendererInterface;
QT_USE_NAMESPACE
class QGstreamerPlayerSession : public QObject, public QGstreamerSyncEventFilter
{
Q_OBJECT
public:
QGstreamerPlayerSession(QObject *parent);
virtual ~QGstreamerPlayerSession();
QNetworkRequest request() const;
QMediaPlayer::State state() const { return m_state; }
QMediaPlayer::State pendingState() const { return m_pendingState; }
qint64 duration() const;
qint64 position() const;
bool isBuffering() const;
int bufferingProgress() const;
int volume() const;
bool isMuted() const;
bool isAudioAvailable() const;
void setVideoRenderer(QObject *renderer);
bool isVideoAvailable() const;
bool isSeekable() const;
qreal playbackRate() const;
void setPlaybackRate(qreal rate);
QMediaTimeRange availablePlaybackRanges() const;
QMap<QByteArray ,QVariant> tags() const { return m_tags; }
QMap<QtMultimediaKit::MetaData,QVariant> streamProperties(int streamNumber) const { return m_streamProperties[streamNumber]; }
int streamCount() const { return m_streamProperties.count(); }
QMediaStreamsControl::StreamType streamType(int streamNumber) { return m_streamTypes.value(streamNumber, QMediaStreamsControl::UnknownStream); }
int activeStream(QMediaStreamsControl::StreamType streamType) const;
void setActiveStream(QMediaStreamsControl::StreamType streamType, int streamNumber);
bool processSyncMessage(const QGstreamerMessage &message);
#if defined(HAVE_GST_APPSRC)
QGstAppSrc *appsrc() const { return m_appSrc; }
static void configureAppSrcElement(GObject*, GObject*, GParamSpec*,QGstreamerPlayerSession* _this);
#endif
public slots:
void loadFromUri(const QNetworkRequest &url);
void loadFromStream(const QNetworkRequest &url, QIODevice *stream);
bool play();
bool pause();
void stop();
bool seek(qint64 pos);
void setVolume(int volume);
void setMuted(bool muted);
signals:
void durationChanged(qint64 duration);
void positionChanged(qint64 position);
void stateChanged(QMediaPlayer::State state);
void volumeChanged(int volume);
void mutedStateChanged(bool muted);
void audioAvailableChanged(bool audioAvailable);
void videoAvailableChanged(bool videoAvailable);
void bufferingChanged(bool buffering);
void bufferingProgressChanged(int percentFilled);
void playbackFinished();
void tagsChanged();
void streamsChanged();
void seekableChanged(bool);
void error(int error, const QString &errorString);
void invalidMedia();
void playbackRateChanged(qreal);
private slots:
void busMessage(const QGstreamerMessage &message);
void getStreamsInfo();
void setSeekable(bool);
void finishVideoOutputChange();
void updateVideoRenderer();
void updateVideoResolutionTag();
void updateVolume();
void updateMuted();
void updateDuration();
private:
static void playbinNotifySource(GObject *o, GParamSpec *p, gpointer d);
static void handleVolumeChange(GObject *o, GParamSpec *p, gpointer d);
static void handleMutedChange(GObject *o, GParamSpec *p, gpointer d);
static void insertColorSpaceElement(GstElement *element, gpointer data);
static void handleElementAdded(GstBin *bin, GstElement *element, QGstreamerPlayerSession *session);
void processInvalidMedia(QMediaPlayer::Error errorCode, const QString& errorString);
QNetworkRequest m_request;
QMediaPlayer::State m_state;
QMediaPlayer::State m_pendingState;
QGstreamerBusHelper* m_busHelper;
GstElement* m_playbin;
bool m_usePlaybin2;
GstElement* m_videoOutputBin;
GstElement* m_videoIdentity;
GstElement* m_colorSpace;
bool m_usingColorspaceElement;
GstElement* m_videoSink;
GstElement* m_pendingVideoSink;
GstElement* m_nullVideoSink;
GstBus* m_bus;
QObject *m_videoOutput;
QGstreamerVideoRendererInterface *m_renderer;
bool m_haveQueueElement;
#if defined(HAVE_GST_APPSRC)
QGstAppSrc *m_appSrc;
#endif
QMap<QByteArray, QVariant> m_tags;
QList< QMap<QtMultimediaKit::MetaData,QVariant> > m_streamProperties;
QList<QMediaStreamsControl::StreamType> m_streamTypes;
QMap<QMediaStreamsControl::StreamType, int> m_playbin2StreamOffset;
int m_volume;
qreal m_playbackRate;
bool m_muted;
bool m_audioAvailable;
bool m_videoAvailable;
bool m_seekable;
mutable qint64 m_lastPosition;
qint64 m_duration;
int m_durationQueries;
enum SourceType
{
UnknownSrc,
SoupHTTPSrc,
UDPSrc,
MMSSrc
};
SourceType m_sourceType;
bool m_everPlayed;
};
#endif // QGSTREAMERPLAYERSESSION_H

View File

@@ -0,0 +1,89 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qgstreamerstreamscontrol.h"
#include "qgstreamerplayersession.h"
QGstreamerStreamsControl::QGstreamerStreamsControl(QGstreamerPlayerSession *session, QObject *parent)
:QMediaStreamsControl(parent), m_session(session)
{
connect(m_session, SIGNAL(streamsChanged()), SIGNAL(streamsChanged()));
}
QGstreamerStreamsControl::~QGstreamerStreamsControl()
{
}
int QGstreamerStreamsControl::streamCount()
{
return m_session->streamCount();
}
QMediaStreamsControl::StreamType QGstreamerStreamsControl::streamType(int streamNumber)
{
return m_session->streamType(streamNumber);
}
QVariant QGstreamerStreamsControl::metaData(int streamNumber, QtMultimediaKit::MetaData key)
{
return m_session->streamProperties(streamNumber).value(key);
}
bool QGstreamerStreamsControl::isActive(int streamNumber)
{
return streamNumber != -1 && streamNumber == m_session->activeStream(streamType(streamNumber));
}
void QGstreamerStreamsControl::setActive(int streamNumber, bool state)
{
QMediaStreamsControl::StreamType type = m_session->streamType(streamNumber);
if (type == QMediaStreamsControl::UnknownStream)
return;
if (state)
m_session->setActiveStream(type, streamNumber);
else {
//only one active stream of certain type is supported
if (m_session->activeStream(type) == streamNumber)
m_session->setActiveStream(type, -1);
}
}

View File

@@ -0,0 +1,71 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGSTREAMERSTREAMSCONTROL_H
#define QGSTREAMERSTREAMSCONTROL_H
#include <qmediastreamscontrol.h>
QT_USE_NAMESPACE
class QGstreamerPlayerSession;
class QGstreamerStreamsControl : public QMediaStreamsControl
{
Q_OBJECT
public:
QGstreamerStreamsControl(QGstreamerPlayerSession *session, QObject *parent);
virtual ~QGstreamerStreamsControl();
virtual int streamCount();
virtual StreamType streamType(int streamNumber);
virtual QVariant metaData(int streamNumber, QtMultimediaKit::MetaData key);
virtual bool isActive(int streamNumber);
virtual void setActive(int streamNumber, bool state);
private:
QGstreamerPlayerSession *m_session;
};
#endif // QGSTREAMERSTREAMSCONTROL_H