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,50 @@
INCLUDEPATH += $$PWD \
$${SOURCE_DIR}/src/multimedia
INCLUDEPATH += camerabin
DEFINES += QMEDIA_GSTREAMER_CAMERABIN
LIBS += -lgstphotography-0.10
DEFINES += GST_USE_UNSTABLE_API #prevents warnings because of unstable photography API
HEADERS += \
$$PWD/camerabinservice.h \
$$PWD/camerabinsession.h \
$$PWD/camerabincontrol.h \
$$PWD/camerabinaudioencoder.h \
$$PWD/camerabinfocus.h \
$$PWD/camerabinimageencoder.h \
$$PWD/camerabinlocks.h \
$$PWD/camerabinrecorder.h \
$$PWD/camerabincontainer.h \
$$PWD/camerabinexposure.h \
$$PWD/camerabinflash.h \
$$PWD/camerabinimagecapture.h \
$$PWD/camerabinimageprocessing.h \
$$PWD/camerabinmetadata.h \
$$PWD/camerabinvideoencoder.h \
$$PWD/camerabinresourcepolicy.h \
$$PWD/camerabincapturedestination.h \
$$PWD/camerabincapturebufferformat.h
SOURCES += \
$$PWD/camerabinservice.cpp \
$$PWD/camerabinsession.cpp \
$$PWD/camerabincontrol.cpp \
$$PWD/camerabinaudioencoder.cpp \
$$PWD/camerabincontainer.cpp \
$$PWD/camerabinexposure.cpp \
$$PWD/camerabinflash.cpp \
$$PWD/camerabinfocus.cpp \
$$PWD/camerabinimagecapture.cpp \
$$PWD/camerabinimageencoder.cpp \
$$PWD/camerabinimageprocessing.cpp \
$$PWD/camerabinlocks.cpp \
$$PWD/camerabinmetadata.cpp \
$$PWD/camerabinrecorder.cpp \
$$PWD/camerabinvideoencoder.cpp \
$$PWD/camerabinresourcepolicy.cpp \
$$PWD/camerabincapturedestination.cpp \
$$PWD/camerabincapturebufferformat.cpp

View File

@@ -0,0 +1,293 @@
/****************************************************************************
**
** 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 "camerabinaudioencoder.h"
#include "camerabincontainer.h"
#include <QtCore/qdebug.h>
CameraBinAudioEncoder::CameraBinAudioEncoder(QObject *parent)
:QAudioEncoderControl(parent)
{
QList<QByteArray> codecCandidates;
#if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
codecCandidates << "audio/AAC" << "audio/PCM" << "audio/AMR" << "audio/AMR-WB" << "audio/speex"
<< "audio/ADPCM" << "audio/iLBC" << "audio/vorbis" << "audio/mpeg" << "audio/FLAC";
m_elementNames["audio/AAC"] = "nokiaaacenc";
m_elementNames["audio/speex"] = "speexenc";
m_elementNames["audio/PCM"] = "audioresample";
m_elementNames["audio/AMR"] = "nokiaamrnbenc";
m_elementNames["audio/AMR-WB"] = "nokiaamrwbenc";
m_elementNames["audio/ADPCM"] = "nokiaadpcmenc";
m_elementNames["audio/iLBC"] = "nokiailbcenc";
m_elementNames["audio/vorbis"] = "vorbisenc";
m_elementNames["audio/FLAC"] = "flacenc";
m_elementNames["audio/mpeg"] = "ffenc_mp2";
#else
codecCandidates << "audio/mpeg" << "audio/vorbis" << "audio/speex" << "audio/GSM"
<< "audio/PCM" << "audio/AMR" << "audio/AMR-WB";
m_elementNames["audio/mpeg"] = "lamemp3enc";
m_elementNames["audio/vorbis"] = "vorbisenc";
m_elementNames["audio/speex"] = "speexenc";
m_elementNames["audio/GSM"] = "gsmenc";
m_elementNames["audio/PCM"] = "audioresample";
m_elementNames["audio/AMR"] = "amrnbenc";
m_elementNames["audio/AMR-WB"] = "amrwbenc";
m_codecOptions["audio/vorbis"] = QStringList() << "min-bitrate" << "max-bitrate";
m_codecOptions["audio/mpeg"] = QStringList() << "mode";
m_codecOptions["audio/speex"] = QStringList() << "mode" << "vbr" << "vad" << "dtx";
m_codecOptions["audio/GSM"] = QStringList();
m_codecOptions["audio/PCM"] = QStringList();
m_codecOptions["audio/AMR"] = QStringList();
m_codecOptions["audio/AMR-WB"] = QStringList();
#endif
foreach( const QByteArray& codecName, codecCandidates ) {
QByteArray elementName = m_elementNames[codecName];
GstElementFactory *factory = gst_element_factory_find(elementName.constData());
if (factory) {
m_codecs.append(codecName);
const gchar *descr = gst_element_factory_get_description(factory);
if (codecName == QByteArray("audio/PCM"))
m_codecDescriptions.insert(codecName, tr("Raw PCM audio"));
else
m_codecDescriptions.insert(codecName, QString::fromUtf8(descr));
m_streamTypes.insert(codecName,
CameraBinContainer::supportedStreamTypes(factory, GST_PAD_SRC));
gst_object_unref(GST_OBJECT(factory));
}
}
}
CameraBinAudioEncoder::~CameraBinAudioEncoder()
{
}
QStringList CameraBinAudioEncoder::supportedAudioCodecs() const
{
return m_codecs;
}
QString CameraBinAudioEncoder::codecDescription(const QString &codecName) const
{
return m_codecDescriptions.value(codecName);
}
QStringList CameraBinAudioEncoder::supportedEncodingOptions(const QString &codec) const
{
return m_codecOptions.value(codec);
}
QVariant CameraBinAudioEncoder::encodingOption(
const QString &codec, const QString &name) const
{
return m_options[codec].value(name);
}
void CameraBinAudioEncoder::setEncodingOption(
const QString &codec, const QString &name, const QVariant &value)
{
m_options[codec][name] = value;
}
QList<int> CameraBinAudioEncoder::supportedSampleRates(const QAudioEncoderSettings &, bool *) const
{
//TODO check element caps to find actual values
return QList<int>();
}
QAudioEncoderSettings CameraBinAudioEncoder::audioSettings() const
{
return m_audioSettings;
}
void CameraBinAudioEncoder::setAudioSettings(const QAudioEncoderSettings &settings)
{
m_userSettings = settings;
m_audioSettings = settings;
emit settingsChanged();
}
void CameraBinAudioEncoder::setActualAudioSettings(const QAudioEncoderSettings &settings)
{
m_audioSettings = settings;
}
void CameraBinAudioEncoder::resetActualSettings()
{
m_audioSettings = m_userSettings;
}
GstElement *CameraBinAudioEncoder::createEncoder()
{
QString codec = m_audioSettings.codec();
QByteArray encoderElementName = m_elementNames.value(codec);
GstElement *encoderElement = gst_element_factory_make(encoderElementName.constData(), NULL);
if (!encoderElement)
return 0;
GstBin * encoderBin = GST_BIN(gst_bin_new("audio-encoder-bin"));
GstElement *capsFilter = gst_element_factory_make("capsfilter", NULL);
gst_bin_add(encoderBin, capsFilter);
gst_bin_add(encoderBin, encoderElement);
gst_element_link(capsFilter, encoderElement);
// add ghostpads
GstPad *pad = gst_element_get_static_pad(capsFilter, "sink");
gst_element_add_pad(GST_ELEMENT(encoderBin), gst_ghost_pad_new("sink", pad));
gst_object_unref(GST_OBJECT(pad));
pad = gst_element_get_static_pad(encoderElement, "src");
gst_element_add_pad(GST_ELEMENT(encoderBin), gst_ghost_pad_new("src", pad));
gst_object_unref(GST_OBJECT(pad));
if (m_audioSettings.sampleRate() > 0 || m_audioSettings.channelCount() > 0) {
GstCaps *caps = gst_caps_new_empty();
GstStructure *structure = gst_structure_new("audio/x-raw-int", NULL);
if (m_audioSettings.sampleRate() > 0)
gst_structure_set(structure, "rate", G_TYPE_INT, m_audioSettings.sampleRate(), NULL );
if (m_audioSettings.channelCount() > 0)
gst_structure_set(structure, "channels", G_TYPE_INT, m_audioSettings.channelCount(), NULL );
gst_caps_append_structure(caps,structure);
g_object_set(G_OBJECT(capsFilter), "caps", caps, NULL);
}
if (encoderElement) {
if (m_audioSettings.encodingMode() == QtMultimediaKit::ConstantQualityEncoding) {
QtMultimediaKit::EncodingQuality qualityValue = m_audioSettings.quality();
if (encoderElementName == "lamemp3enc") {
g_object_set(G_OBJECT(encoderElement), "target", 0, NULL); //constant quality mode
qreal quality[] = {
10.0, //VeryLow
6.0, //Low
4.0, //Normal
2.0, //High
0.0 //VeryHigh
};
g_object_set(G_OBJECT(encoderElement), "quality", quality[qualityValue], NULL);
} else if (encoderElementName == "ffenc_mp2") {
int quality[] = {
8000, //VeryLow
64000, //Low
128000, //Normal
192000, //High
320000 //VeryHigh
};
g_object_set(G_OBJECT(encoderElement), "bitrate", quality[qualityValue], NULL);
} else if (codec == QLatin1String("audio/speex")) {
//0-10 range with default 8
double qualityTable[] = {
2, //VeryLow
5, //Low
8, //Normal
9, //High
10 //VeryHigh
};
g_object_set(G_OBJECT(encoderElement), "quality", qualityTable[qualityValue], NULL);
} else if (codec.startsWith("audio/AMR")) {
int band[] = {
0, //VeryLow
2, //Low
4, //Normal
6, //High
7 //VeryHigh
};
g_object_set(G_OBJECT(encoderElement), "band-mode", band[qualityValue], NULL);
}
} else {
int bitrate = m_audioSettings.bitRate();
if (bitrate > 0) {
g_object_set(G_OBJECT(encoderElement), "bitrate", bitrate, NULL);
}
}
QMap<QString, QVariant> options = m_options.value(codec);
QMapIterator<QString,QVariant> it(options);
while (it.hasNext()) {
it.next();
QString option = it.key();
QVariant value = it.value();
switch (value.type()) {
case QVariant::Int:
g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toInt(), NULL);
break;
case QVariant::Bool:
g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toBool(), NULL);
break;
case QVariant::Double:
g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toDouble(), NULL);
break;
case QVariant::String:
g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toString().toUtf8().constData(), NULL);
break;
default:
qWarning() << "unsupported option type:" << option << value;
break;
}
}
}
return GST_ELEMENT(encoderBin);
}
QSet<QString> CameraBinAudioEncoder::supportedStreamTypes(const QString &codecName) const
{
return m_streamTypes.value(codecName);
}

View File

@@ -0,0 +1,105 @@
/****************************************************************************
**
** 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 CAMERABINAUDIOENCODE_H
#define CAMERABINAUDIOENCODE_H
#include <qaudioencodercontrol.h>
class CameraBinSession;
#include <QtCore/qstringlist.h>
#include <QtCore/qmap.h>
#include <QtCore/qset.h>
#include <gst/gst.h>
#include <qaudioformat.h>
QT_USE_NAMESPACE
class CameraBinAudioEncoder : public QAudioEncoderControl
{
Q_OBJECT
public:
CameraBinAudioEncoder(QObject *parent);
virtual ~CameraBinAudioEncoder();
QStringList supportedAudioCodecs() const;
QString codecDescription(const QString &codecName) const;
QStringList supportedEncodingOptions(const QString &codec) const;
QVariant encodingOption(const QString &codec, const QString &name) const;
void setEncodingOption(const QString &codec, const QString &name, const QVariant &value);
QList<int> supportedSampleRates(const QAudioEncoderSettings &settings = QAudioEncoderSettings(),
bool *isContinuous = 0) const;
QList<int> supportedChannelCounts(const QAudioEncoderSettings &settings = QAudioEncoderSettings()) const;
QList<int> supportedSampleSizes(const QAudioEncoderSettings &settings = QAudioEncoderSettings()) const;
QAudioEncoderSettings audioSettings() const;
void setAudioSettings(const QAudioEncoderSettings&);
GstElement *createEncoder();
QSet<QString> supportedStreamTypes(const QString &codecName) const;
void setActualAudioSettings(const QAudioEncoderSettings&);
void resetActualSettings();
Q_SIGNALS:
void settingsChanged();
private:
QStringList m_codecs;
QMap<QString,QByteArray> m_elementNames;
QMap<QString,QString> m_codecDescriptions;
QMap<QString,QStringList> m_codecOptions;
QMap<QString, QMap<QString, QVariant> > m_options;
QMap<QString, QSet<QString> > m_streamTypes;
QAudioEncoderSettings m_audioSettings;
QAudioEncoderSettings m_userSettings;
};
#endif

View File

@@ -0,0 +1,78 @@
/****************************************************************************
**
** 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 "camerabincapturebufferformat.h"
#include "camerabinsession.h"
CameraBinCaptureBufferFormat::CameraBinCaptureBufferFormat(CameraBinSession *session)
:QCameraCaptureBufferFormatControl(session)
, m_session(session)
, m_format(QVideoFrame::Format_Jpeg)
{
}
CameraBinCaptureBufferFormat::~CameraBinCaptureBufferFormat()
{
}
QList<QVideoFrame::PixelFormat> CameraBinCaptureBufferFormat::supportedBufferFormats() const
{
//the exact YUV format is unknown with camerabin until the first capture is requested
return QList<QVideoFrame::PixelFormat>()
<< QVideoFrame::Format_Jpeg
#ifdef Q_WS_MAEMO_6
<< QVideoFrame::Format_UYVY
#endif
;
}
QVideoFrame::PixelFormat CameraBinCaptureBufferFormat::bufferFormat() const
{
return m_format;
}
void CameraBinCaptureBufferFormat::setBufferFormat(QVideoFrame::PixelFormat format)
{
if (m_format != format) {
m_format = format;
emit bufferFormatChanged(format);
}
}

View File

@@ -0,0 +1,72 @@
/****************************************************************************
**
** 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 CAMERABINCAPTUREBUFFERFORMAT_H
#define CAMERABINCAPTUREBUFFERFORMAT_H
#include <qcamera.h>
#include <qcameracapturebufferformatcontrol.h>
#include <gst/gst.h>
#include <glib.h>
class CameraBinSession;
QT_USE_NAMESPACE
class Q_MULTIMEDIA_EXPORT CameraBinCaptureBufferFormat : public QCameraCaptureBufferFormatControl
{
Q_OBJECT
public:
CameraBinCaptureBufferFormat(CameraBinSession *session);
virtual ~CameraBinCaptureBufferFormat();
QList<QVideoFrame::PixelFormat> supportedBufferFormats() const;
QVideoFrame::PixelFormat bufferFormat() const;
void setBufferFormat(QVideoFrame::PixelFormat format);
private:
CameraBinSession *m_session;
QVideoFrame::PixelFormat m_format;
};
#endif

View File

@@ -0,0 +1,74 @@
/****************************************************************************
**
** 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 "camerabincapturedestination.h"
#include "camerabinsession.h"
CameraBinCaptureDestination::CameraBinCaptureDestination(CameraBinSession *session)
:QCameraCaptureDestinationControl(session)
, m_session(session)
, m_destination(QCameraImageCapture::CaptureToFile)
{
}
CameraBinCaptureDestination::~CameraBinCaptureDestination()
{
}
bool CameraBinCaptureDestination::isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const
{
//capture to buffer, file and both are supported.
return destination & (QCameraImageCapture::CaptureToFile | QCameraImageCapture::CaptureToBuffer);
}
QCameraImageCapture::CaptureDestinations CameraBinCaptureDestination::captureDestination() const
{
return m_destination;
}
void CameraBinCaptureDestination::setCaptureDestination(QCameraImageCapture::CaptureDestinations destination)
{
if (m_destination != destination) {
m_destination = destination;
emit captureDestinationChanged(m_destination);
}
}

View File

@@ -0,0 +1,69 @@
/****************************************************************************
**
** 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 CAMERABINCAPTUREDESTINATION_H
#define CAMERABINCAPTUREDESTINATION_H
#include <qcameraimagecapture.h>
#include <qcameracapturedestinationcontrol.h>
class CameraBinSession;
QT_USE_NAMESPACE
class Q_MULTIMEDIA_EXPORT CameraBinCaptureDestination : public QCameraCaptureDestinationControl
{
Q_OBJECT
public:
CameraBinCaptureDestination(CameraBinSession *session);
virtual ~CameraBinCaptureDestination();
bool isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const;
QCameraImageCapture::CaptureDestinations captureDestination() const;
void setCaptureDestination(QCameraImageCapture::CaptureDestinations destination);
private:
CameraBinSession *m_session;
QCameraImageCapture::CaptureDestinations m_destination;
};
#endif // CAMERABINFLASHCONTROL_H

View File

@@ -0,0 +1,122 @@
/****************************************************************************
**
** 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 "camerabincontainer.h"
#include <QtCore/qdebug.h>
CameraBinContainer::CameraBinContainer(QObject *parent)
:QMediaContainerControl(parent)
{
QList<QByteArray> formatCandidates;
formatCandidates << "mp4" << "ogg" << "wav" << "amr" << "mkv"
<< "avi" << "3gp" << "3gp2" << "webm" << "mjpeg" << "asf" << "mov";
QMap<QString,QByteArray> elementNames;
elementNames.insertMulti("mp4", "ffmux_mp4");
elementNames.insertMulti("mp4", "hantromp4mux");
elementNames.insertMulti("mp4", "mp4mux");
elementNames.insert("ogg", "oggmux");
elementNames["wav"] = "wavenc";
elementNames["amr"] = "ffmux_amr";
elementNames["mkv"] = "matroskamux";
elementNames["avi"] = "avimux";
elementNames["3gp"] = "ffmux_3gp";
elementNames["3gp2"] = "ffmux_3g2";
elementNames["webm"] = "webmmux";
elementNames["mjpeg"] = "ffmux_mjpeg";
elementNames["asf"] = "ffmux_asf";
elementNames["mov"] = "qtmux";
QSet<QString> allTypes;
foreach(const QByteArray &formatName, formatCandidates) {
foreach(const QByteArray &elementName, elementNames.values(formatName)) {
GstElementFactory *factory = gst_element_factory_find(elementName.constData());
if (factory) {
m_supportedContainers.append(formatName);
const gchar *descr = gst_element_factory_get_description(factory);
m_containerDescriptions.insert(formatName, QString::fromUtf8(descr));
if (formatName == QByteArray("raw")) {
m_streamTypes.insert(formatName, allTypes);
} else {
QSet<QString> types = supportedStreamTypes(factory, GST_PAD_SINK);
m_streamTypes.insert(formatName, types);
allTypes.unite(types);
}
gst_object_unref(GST_OBJECT(factory));
m_elementNames.insert(formatName, elementName);
break;
}
}
}
}
QSet<QString> CameraBinContainer::supportedStreamTypes(GstElementFactory *factory, GstPadDirection direction)
{
QSet<QString> types;
const GList *pads = gst_element_factory_get_static_pad_templates(factory);
for (const GList *pad = pads; pad; pad = g_list_next(pad)) {
GstStaticPadTemplate *templ = (GstStaticPadTemplate*)pad->data;
if (templ->direction == direction) {
GstCaps *caps = gst_static_caps_get(&templ->static_caps);
for (uint i=0; i<gst_caps_get_size(caps); i++) {
GstStructure *structure = gst_caps_get_structure(caps, i);
types.insert( QString::fromUtf8(gst_structure_get_name(structure)) );
}
gst_caps_unref(caps);
}
}
return types;
}
QSet<QString> CameraBinContainer::supportedStreamTypes(const QString &container) const
{
return m_streamTypes.value(container);
}

View File

@@ -0,0 +1,103 @@
/****************************************************************************
**
** 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 CAMERABINMEDIACONTAINERCONTROL_H
#define CAMERABINMEDIACONTAINERCONTROL_H
#include <qmediacontainercontrol.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qset.h>
#include <gst/gst.h>
QT_USE_NAMESPACE
class CameraBinContainer : public QMediaContainerControl
{
Q_OBJECT
public:
CameraBinContainer(QObject *parent);
virtual ~CameraBinContainer() {}
virtual QStringList supportedContainers() const { return m_supportedContainers; }
virtual QString containerMimeType() const { return m_format; }
virtual void setContainerMimeType(const QString &formatMimeType)
{
m_format = formatMimeType;
if (m_userFormat != formatMimeType) {
m_userFormat = formatMimeType;
emit settingsChanged();
}
}
void setActualContainer(const QString &formatMimeType)
{
m_format = formatMimeType;
}
void resetActualContainer()
{
m_format = m_userFormat;
}
virtual QString containerDescription(const QString &formatMimeType) const { return m_containerDescriptions.value(formatMimeType); }
QByteArray formatElementName() const { return m_elementNames.value(containerMimeType()); }
QSet<QString> supportedStreamTypes(const QString &container) const;
static QSet<QString> supportedStreamTypes(GstElementFactory *factory, GstPadDirection direction);
Q_SIGNALS:
void settingsChanged();
private:
QString m_format; // backend selected format, using m_userFormat
QString m_userFormat;
QStringList m_supportedContainers;
QMap<QString,QByteArray> m_elementNames;
QMap<QString, QString> m_containerDescriptions;
QMap<QString, QSet<QString> > m_streamTypes;
};
#endif // CAMERABINMEDIACONTAINERCONTROL_H

View File

@@ -0,0 +1,356 @@
/****************************************************************************
**
** Copyright (C) 2009 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 "camerabincontrol.h"
#include "camerabincontainer.h"
#include "camerabinaudioencoder.h"
#include "camerabinvideoencoder.h"
#include "camerabinimageencoder.h"
#include "camerabinresourcepolicy.h"
#include <QtCore/qdebug.h>
#include <QtCore/qfile.h>
#include <QtCore/qmetaobject.h>
#include <linux/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
//#define CAMEABIN_DEBUG 1
#define ENUM_NAME(c,e,v) (c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(e)).valueToKey((v)))
CameraBinControl::CameraBinControl(CameraBinSession *session)
:QCameraControl(session),
m_session(session),
m_state(QCamera::UnloadedState),
m_status(QCamera::UnloadedStatus),
m_reloadPending(false)
{
connect(m_session, SIGNAL(stateChanged(QCamera::State)),
this, SLOT(updateStatus()));
connect(m_session->audioEncodeControl(), SIGNAL(settingsChanged()),
SLOT(reloadLater()));
connect(m_session->videoEncodeControl(), SIGNAL(settingsChanged()),
SLOT(reloadLater()));
connect(m_session->mediaContainerControl(), SIGNAL(settingsChanged()),
SLOT(reloadLater()));
connect(m_session->imageEncodeControl(), SIGNAL(settingsChanged()),
SLOT(reloadLater()));
connect(m_session, SIGNAL(viewfinderChanged()),
SLOT(reloadLater()));
connect(m_session, SIGNAL(readyChanged(bool)),
SLOT(reloadLater()));
connect(m_session, SIGNAL(error(int,QString)),
SLOT(handleCameraError(int,QString)));
m_resourcePolicy = new CamerabinResourcePolicy(this);
connect(m_resourcePolicy, SIGNAL(resourcesGranted()),
SLOT(handleResourcesGranted()));
connect(m_resourcePolicy, SIGNAL(resourcesDenied()),
SLOT(handleResourcesLost()));
connect(m_resourcePolicy, SIGNAL(resourcesLost()),
SLOT(handleResourcesLost()));
connect(m_session, SIGNAL(busyChanged(bool)),
SLOT(handleBusyChanged(bool)));
}
CameraBinControl::~CameraBinControl()
{
}
QCamera::CaptureMode CameraBinControl::captureMode() const
{
return m_session->captureMode();
}
void CameraBinControl::setCaptureMode(QCamera::CaptureMode mode)
{
if (m_session->captureMode() != mode) {
m_session->setCaptureMode(mode);
reloadLater();
if (m_state == QCamera::ActiveState) {
m_resourcePolicy->setResourceSet(
captureMode() == QCamera::CaptureStillImage ?
CamerabinResourcePolicy::ImageCaptureResources :
CamerabinResourcePolicy::VideoCaptureResources);
}
emit captureModeChanged(mode);
}
}
bool CameraBinControl::isCaptureModeSupported(QCamera::CaptureMode mode) const
{
#ifdef Q_WS_MAEMO_5
//Front camera on N900 supports only video capture
if (m_session->cameraRole() == CameraBinSession::FrontCamera)
return mode == QCamera::CaptureVideo;
#endif
return mode == QCamera::CaptureStillImage || mode == QCamera::CaptureVideo;
}
void CameraBinControl::setState(QCamera::State state)
{
#ifdef CAMEABIN_DEBUG
qDebug() << Q_FUNC_INFO << ENUM_NAME(QCamera, "State", state);
#endif
if (m_state != state) {
m_state = state;
//special case for stopping the camera while it's busy,
//it should be delayed until the camera is idle
if (state == QCamera::LoadedState &&
m_session->state() == QCamera::ActiveState &&
m_session->isBusy()) {
#ifdef CAMEABIN_DEBUG
qDebug() << Q_FUNC_INFO << "Camera is busy, QCamera::stop() is delayed";
#endif
emit stateChanged(m_state);
return;
}
CamerabinResourcePolicy::ResourceSet resourceSet;
switch (state) {
case QCamera::UnloadedState:
resourceSet = CamerabinResourcePolicy::NoResources;
break;
case QCamera::LoadedState:
resourceSet = CamerabinResourcePolicy::LoadedResources;
break;
case QCamera::ActiveState:
resourceSet = captureMode() == QCamera::CaptureStillImage ?
CamerabinResourcePolicy::ImageCaptureResources :
CamerabinResourcePolicy::VideoCaptureResources;
break;
}
m_resourcePolicy->setResourceSet(resourceSet);
if (m_resourcePolicy->isResourcesGranted()) {
//postpone changing to Active if the session is nor ready yet
if (state == QCamera::ActiveState) {
if (m_session->isReady()) {
m_session->setState(state);
} else {
#ifdef CAMEABIN_DEBUG
qDebug() << "Camera session is not ready yet, postpone activating";
#endif
}
} else
m_session->setState(state);
}
emit stateChanged(m_state);
}
}
QCamera::State CameraBinControl::state() const
{
return m_state;
}
void CameraBinControl::updateStatus()
{
QCamera::State sessionState = m_session->state();
QCamera::Status oldStatus = m_status;
switch (m_state) {
case QCamera::UnloadedState:
m_status = QCamera::UnloadedStatus;
break;
case QCamera::LoadedState:
switch (sessionState) {
case QCamera::UnloadedState:
m_status = QCamera::LoadingStatus;
break;
case QCamera::LoadedState:
m_status = QCamera::LoadedStatus;
break;
case QCamera::ActiveState:
m_status = QCamera::ActiveStatus;
break;
}
break;
case QCamera::ActiveState:
switch (sessionState) {
case QCamera::UnloadedState:
m_status = QCamera::LoadingStatus;
break;
case QCamera::LoadedState:
m_status = QCamera::StartingStatus;
break;
case QCamera::ActiveState:
m_status = QCamera::ActiveStatus;
break;
}
}
if (m_status != oldStatus) {
#ifdef CAMEABIN_DEBUG
qDebug() << "Camera status changed" << ENUM_NAME(QCamera, "Status", m_status);
#endif
emit statusChanged(m_status);
}
}
void CameraBinControl::reloadLater()
{
#ifdef CAMEABIN_DEBUG
qDebug() << "CameraBinControl: reload pipeline requested" << ENUM_NAME(QCamera, "State", m_state);
#endif
if (!m_reloadPending && m_state == QCamera::ActiveState) {
m_reloadPending = true;
if (!m_session->isBusy()) {
m_session->setState(QCamera::LoadedState);
QMetaObject::invokeMethod(this, "delayedReload", Qt::QueuedConnection);
}
}
}
void CameraBinControl::handleResourcesLost()
{
#ifdef CAMEABIN_DEBUG
qDebug() << Q_FUNC_INFO << ENUM_NAME(QCamera, "State", m_state);
#endif
m_session->setState(QCamera::UnloadedState);
}
void CameraBinControl::handleResourcesGranted()
{
#ifdef CAMEABIN_DEBUG
qDebug() << Q_FUNC_INFO << ENUM_NAME(QCamera, "State", m_state);
#endif
//camera will be started soon by delayedReload()
if (m_reloadPending && m_state == QCamera::ActiveState)
return;
if (m_state == QCamera::ActiveState && m_session->isReady())
m_session->setState(QCamera::ActiveState);
else if (m_state == QCamera::LoadedState)
m_session->setState(QCamera::LoadedState);
}
void CameraBinControl::handleBusyChanged(bool busy)
{
if (!busy && m_session->state() == QCamera::ActiveState) {
if (m_state == QCamera::LoadedState) {
//handle delayed stop() because of busy camera
m_resourcePolicy->setResourceSet(CamerabinResourcePolicy::LoadedResources);
m_session->setState(QCamera::LoadedState);
} else if (m_state == QCamera::ActiveState && m_reloadPending) {
//handle delayed reload because of busy camera
m_session->setState(QCamera::LoadedState);
QMetaObject::invokeMethod(this, "delayedReload", Qt::QueuedConnection);
}
}
}
void CameraBinControl::handleCameraError(int errorCode, const QString &errorString)
{
emit error(errorCode, errorString);
setState(QCamera::UnloadedState);
}
void CameraBinControl::delayedReload()
{
#ifdef CAMEABIN_DEBUG
qDebug() << "CameraBinControl: reload pipeline";
#endif
if (m_reloadPending) {
m_reloadPending = false;
if (m_state == QCamera::ActiveState &&
m_session->isReady() &&
m_resourcePolicy->isResourcesGranted()) {
m_session->setState(QCamera::ActiveState);
}
}
}
bool CameraBinControl::canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const
{
Q_UNUSED(status);
switch (changeType) {
case QCameraControl::CaptureMode:
case QCameraControl::ImageEncodingSettings:
case QCameraControl::VideoEncodingSettings:
case QCameraControl::Viewfinder:
return true;
default:
return false;
}
}
#define VIEWFINDER_COLORSPACE_CONVERSION 0x00000004
bool CameraBinControl::viewfinderColorSpaceConversion() const
{
gint flags = 0;
g_object_get(G_OBJECT(m_session->cameraBin()), "flags", &flags, NULL);
return flags & VIEWFINDER_COLORSPACE_CONVERSION;
}
void CameraBinControl::setViewfinderColorSpaceConversion(bool enabled)
{
gint flags = 0;
g_object_get(G_OBJECT(m_session->cameraBin()), "flags", &flags, NULL);
if (enabled)
flags |= VIEWFINDER_COLORSPACE_CONVERSION;
else
flags &= ~VIEWFINDER_COLORSPACE_CONVERSION;
g_object_set(G_OBJECT(m_session->cameraBin()), "flags", flags, NULL);
}

View File

@@ -0,0 +1,101 @@
/****************************************************************************
**
** Copyright (C) 2009 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 CAMERABINCONTROL_H
#define CAMERABINCONTROL_H
#include <QHash>
#include <qcameracontrol.h>
#include "camerabinsession.h"
QT_USE_NAMESPACE
class CamerabinResourcePolicy;
class CameraBinControl : public QCameraControl
{
Q_OBJECT
Q_PROPERTY(bool viewfinderColorSpaceConversion READ viewfinderColorSpaceConversion WRITE setViewfinderColorSpaceConversion)
public:
CameraBinControl( CameraBinSession *session );
virtual ~CameraBinControl();
bool isValid() const { return true; }
QCamera::State state() const;
void setState(QCamera::State state);
QCamera::Status status() const { return m_status; }
QCamera::CaptureMode captureMode() const;
void setCaptureMode(QCamera::CaptureMode mode);
bool isCaptureModeSupported(QCamera::CaptureMode mode) const;
bool canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const;
bool viewfinderColorSpaceConversion() const;
public slots:
void reloadLater();
void setViewfinderColorSpaceConversion(bool enabled);
private slots:
void updateStatus();
void delayedReload();
void handleResourcesGranted();
void handleResourcesLost();
void handleBusyChanged(bool);
void handleCameraError(int error, const QString &errorString);
private:
void updateSupportedResolutions(const QString &device);
CameraBinSession *m_session;
QCamera::State m_state;
QCamera::Status m_status;
CamerabinResourcePolicy *m_resourcePolicy;
bool m_reloadPending;
};
#endif // CAMERABINCONTROL_H

View File

@@ -0,0 +1,232 @@
/****************************************************************************
**
** Copyright (C) 2009 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 "camerabinexposure.h"
#include "camerabinsession.h"
#include <gst/interfaces/photography.h>
#include <QDebug>
CameraBinExposure::CameraBinExposure(CameraBinSession *session)
:QCameraExposureControl(session),
m_session(session)
{
}
CameraBinExposure::~CameraBinExposure()
{
}
QCameraExposure::ExposureMode CameraBinExposure::exposureMode() const
{
GstSceneMode sceneMode;
gst_photography_get_scene_mode(m_session->photography(), &sceneMode);
switch (sceneMode) {
case GST_PHOTOGRAPHY_SCENE_MODE_PORTRAIT: return QCameraExposure::ExposurePortrait;
case GST_PHOTOGRAPHY_SCENE_MODE_SPORT: return QCameraExposure::ExposureSports;
case GST_PHOTOGRAPHY_SCENE_MODE_NIGHT: return QCameraExposure::ExposureNight;
case GST_PHOTOGRAPHY_SCENE_MODE_MANUAL: return QCameraExposure::ExposureManual;
case GST_PHOTOGRAPHY_SCENE_MODE_CLOSEUP: //no direct mapping available so mapping to auto mode
case GST_PHOTOGRAPHY_SCENE_MODE_LANDSCAPE: //no direct mapping available so mapping to auto mode
case GST_PHOTOGRAPHY_SCENE_MODE_AUTO:
default:
return QCameraExposure::ExposureAuto;
}
}
void CameraBinExposure::setExposureMode(QCameraExposure::ExposureMode mode)
{
GstSceneMode sceneMode;
gst_photography_get_scene_mode(m_session->photography(), &sceneMode);
switch (mode) {
case QCameraExposure::ExposureManual: sceneMode = GST_PHOTOGRAPHY_SCENE_MODE_MANUAL; break;
case QCameraExposure::ExposurePortrait: sceneMode = GST_PHOTOGRAPHY_SCENE_MODE_PORTRAIT; break;
case QCameraExposure::ExposureSports: sceneMode = GST_PHOTOGRAPHY_SCENE_MODE_SPORT; break;
case QCameraExposure::ExposureNight: sceneMode = GST_PHOTOGRAPHY_SCENE_MODE_NIGHT; break;
case QCameraExposure::ExposureAuto: sceneMode = GST_PHOTOGRAPHY_SCENE_MODE_AUTO; break;
default:
break;
}
gst_photography_set_scene_mode(m_session->photography(), sceneMode);
}
bool CameraBinExposure::isExposureModeSupported(QCameraExposure::ExposureMode mode) const
{
//Similar mode names can be found in gst as GstSceneMode
return mode == QCameraExposure::ExposureAuto ||
mode == QCameraExposure::ExposurePortrait ||
mode == QCameraExposure::ExposureSports ||
mode == QCameraExposure::ExposureNight;
//No direct mapping available for GST_PHOTOGRAPHY_SCENE_MODE_CLOSEUP and
//GST_PHOTOGRAPHY_SCENE_MODE_LANDSCAPE
}
QCameraExposure::MeteringMode CameraBinExposure::meteringMode() const
{
return QCameraExposure::MeteringMatrix;
}
void CameraBinExposure::setMeteringMode(QCameraExposure::MeteringMode mode)
{
Q_UNUSED(mode);
}
bool CameraBinExposure::isMeteringModeSupported(QCameraExposure::MeteringMode mode) const
{
return mode == QCameraExposure::MeteringMatrix;
}
bool CameraBinExposure::isParameterSupported(ExposureParameter parameter) const
{
switch (parameter) {
case QCameraExposureControl::ExposureCompensation:
case QCameraExposureControl::ISO:
case QCameraExposureControl::Aperture:
case QCameraExposureControl::ShutterSpeed:
return true;
default:
return false;
}
}
QVariant CameraBinExposure::exposureParameter(ExposureParameter parameter) const
{
switch (parameter) {
case QCameraExposureControl::ExposureCompensation:
{
gfloat ev;
gst_photography_get_ev_compensation(m_session->photography(), &ev);
return QVariant(ev);
}
case QCameraExposureControl::ISO:
{
guint isoSpeed = 0;
gst_photography_get_iso_speed(m_session->photography(), &isoSpeed);
return QVariant(isoSpeed);
}
case QCameraExposureControl::Aperture:
return QVariant(2.8);
case QCameraExposureControl::ShutterSpeed:
{
guint32 shutterSpeed = 0;
gst_photography_get_exposure(m_session->photography(), &shutterSpeed);
return QVariant(shutterSpeed/1000000.0);
}
default:
return QVariant();
}
}
QCameraExposureControl::ParameterFlags CameraBinExposure::exposureParameterFlags(ExposureParameter parameter) const
{
QCameraExposureControl::ParameterFlags flags = 0;
switch (parameter) {
case QCameraExposureControl::ExposureCompensation:
flags |= ContinuousRange;
break;
case QCameraExposureControl::Aperture:
flags |= ReadOnly;
break;
default:
break;
}
return flags;
}
QVariantList CameraBinExposure::supportedParameterRange(ExposureParameter parameter) const
{
QVariantList res;
switch (parameter) {
case QCameraExposureControl::ExposureCompensation:
res << -2.0 << 2.0;
break;
case QCameraExposureControl::ISO:
res << 100 << 200 << 400;
break;
case QCameraExposureControl::Aperture:
res << 2.8;
break;
default:
break;
}
return res;
}
bool CameraBinExposure::setExposureParameter(ExposureParameter parameter, const QVariant& value)
{
QVariant oldValue = exposureParameter(parameter);
switch (parameter) {
case QCameraExposureControl::ExposureCompensation:
gst_photography_set_ev_compensation(m_session->photography(), value.toReal());
break;
case QCameraExposureControl::ISO:
gst_photography_set_iso_speed(m_session->photography(), value.toInt());
break;
case QCameraExposureControl::Aperture:
gst_photography_set_aperture(m_session->photography(), guint(value.toReal()*1000000));
break;
case QCameraExposureControl::ShutterSpeed:
gst_photography_set_exposure(m_session->photography(), guint(value.toReal()*1000000));
break;
default:
return false;
}
QVariant newValue = exposureParameter(parameter);
if (!qFuzzyCompare(oldValue.toReal(), newValue.toReal()))
emit exposureParameterChanged(parameter);
return true;
}
QString CameraBinExposure::extendedParameterName(ExposureParameter)
{
return QString();
}

View File

@@ -0,0 +1,83 @@
/****************************************************************************
**
** Copyright (C) 2009 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 CAMERABINEXPOSURECONTROL_MAEMO_H
#define CAMERABINEXPOSURECONTROL_MAEMO_H
#include <qcamera.h>
#include <qcameraexposurecontrol.h>
#include <gst/gst.h>
#include <glib.h>
class CameraBinSession;
QT_USE_NAMESPACE
class Q_MULTIMEDIA_EXPORT CameraBinExposure : public QCameraExposureControl
{
Q_OBJECT
public:
CameraBinExposure(CameraBinSession *session);
virtual ~CameraBinExposure();
QCameraExposure::ExposureMode exposureMode() const;
void setExposureMode(QCameraExposure::ExposureMode mode);
bool isExposureModeSupported(QCameraExposure::ExposureMode mode) const;
QCameraExposure::MeteringMode meteringMode() const;
void setMeteringMode(QCameraExposure::MeteringMode mode);
bool isMeteringModeSupported(QCameraExposure::MeteringMode mode) const;
bool isParameterSupported(ExposureParameter parameter) const;
QVariant exposureParameter(ExposureParameter parameter) const;
ParameterFlags exposureParameterFlags(ExposureParameter parameter) const;
QVariantList supportedParameterRange(ExposureParameter parameter) const;
bool setExposureParameter(ExposureParameter parameter, const QVariant& value);
QString extendedParameterName(ExposureParameter parameter);
private:
CameraBinSession *m_session;
};
#endif // CAMERABINEXPOSURECONTROL_MAEMO_H

View File

@@ -0,0 +1,104 @@
/****************************************************************************
**
** Copyright (C) 2009 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 "camerabinflash.h"
#include "camerabinsession.h"
#include <gst/interfaces/photography.h>
#include <QDebug>
CameraBinFlash::CameraBinFlash(CameraBinSession *session)
:QCameraFlashControl(session),
m_session(session)
{
}
CameraBinFlash::~CameraBinFlash()
{
}
QCameraExposure::FlashModes CameraBinFlash::flashMode() const
{
GstFlashMode flashMode;
gst_photography_get_flash_mode(m_session->photography(), &flashMode);
QCameraExposure::FlashModes modes;
switch (flashMode) {
case GST_PHOTOGRAPHY_FLASH_MODE_AUTO: modes |= QCameraExposure::FlashAuto; break;
case GST_PHOTOGRAPHY_FLASH_MODE_OFF: modes |= QCameraExposure::FlashOff; break;
case GST_PHOTOGRAPHY_FLASH_MODE_ON: modes |= QCameraExposure::FlashOn; break;
case GST_PHOTOGRAPHY_FLASH_MODE_FILL_IN: modes |= QCameraExposure::FlashFill; break;
case GST_PHOTOGRAPHY_FLASH_MODE_RED_EYE: modes |= QCameraExposure::FlashRedEyeReduction; break;
default:
modes |= QCameraExposure::FlashAuto;
break;
}
return modes;
}
void CameraBinFlash::setFlashMode(QCameraExposure::FlashModes mode)
{
GstFlashMode flashMode;
gst_photography_get_flash_mode(m_session->photography(), &flashMode);
if (mode.testFlag(QCameraExposure::FlashAuto)) flashMode = GST_PHOTOGRAPHY_FLASH_MODE_AUTO;
else if (mode.testFlag(QCameraExposure::FlashOff)) flashMode = GST_PHOTOGRAPHY_FLASH_MODE_OFF;
else if (mode.testFlag(QCameraExposure::FlashOn)) flashMode = GST_PHOTOGRAPHY_FLASH_MODE_ON;
else if (mode.testFlag(QCameraExposure::FlashFill)) flashMode = GST_PHOTOGRAPHY_FLASH_MODE_FILL_IN;
else if (mode.testFlag(QCameraExposure::FlashRedEyeReduction)) flashMode = GST_PHOTOGRAPHY_FLASH_MODE_RED_EYE;
gst_photography_set_flash_mode(m_session->photography(), flashMode);
}
bool CameraBinFlash::isFlashModeSupported(QCameraExposure::FlashModes mode) const
{
return mode == QCameraExposure::FlashOff ||
mode == QCameraExposure::FlashOn ||
mode == QCameraExposure::FlashAuto ||
mode == QCameraExposure::FlashRedEyeReduction ||
mode == QCameraExposure::FlashFill;
}
bool CameraBinFlash::isFlashReady() const
{
return true;
}

View File

@@ -0,0 +1,73 @@
/****************************************************************************
**
** Copyright (C) 2009 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 CAMERABINFLASHCONTROL_H
#define CAMERABINFLASHCONTROL_H
#include <qcamera.h>
#include <qcameraflashcontrol.h>
#include <gst/gst.h>
#include <glib.h>
class CameraBinSession;
QT_USE_NAMESPACE
class Q_MULTIMEDIA_EXPORT CameraBinFlash : public QCameraFlashControl
{
Q_OBJECT
public:
CameraBinFlash(CameraBinSession *session);
virtual ~CameraBinFlash();
QCameraExposure::FlashModes flashMode() const;
void setFlashMode(QCameraExposure::FlashModes mode);
bool isFlashModeSupported(QCameraExposure::FlashModes mode) const;
bool isFlashReady() const;
private:
CameraBinSession *m_session;
};
#endif // CAMERABINFLASHCONTROL_H

View File

@@ -0,0 +1,245 @@
/****************************************************************************
**
** Copyright (C) 2009 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 "camerabinfocus.h"
#include "camerabinsession.h"
#include <gst/interfaces/photography.h>
#include <QDebug>
#include <QtCore/qmetaobject.h>
//#define CAMERABIN_DEBUG 1
#define ENUM_NAME(c,e,v) (c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(e)).valueToKey((v)))
CameraBinFocus::CameraBinFocus(CameraBinSession *session)
:QCameraFocusControl(session),
m_session(session),
m_focusMode(QCameraFocus::AutoFocus),
m_focusStatus(QCamera::Unlocked),
m_focusZoneStatus(QCameraFocusZone::Selected)
{
connect(m_session, SIGNAL(stateChanged(QCamera::State)),
this, SLOT(_q_handleCameraStateChange(QCamera::State)));
connect(m_session, SIGNAL(imageCaptured(int,QImage)),
this, SLOT(_q_handleCapturedImage()));
}
CameraBinFocus::~CameraBinFocus()
{
}
QCameraFocus::FocusMode CameraBinFocus::focusMode() const
{
return m_focusMode;
}
void CameraBinFocus::setFocusMode(QCameraFocus::FocusMode mode)
{
if (isFocusModeSupported(mode)) {
m_focusMode = mode;
}
}
bool CameraBinFocus::isFocusModeSupported(QCameraFocus::FocusMode mode) const
{
return mode & QCameraFocus::AutoFocus;
}
qreal CameraBinFocus::maximumOpticalZoom() const
{
return 1.0;
}
qreal CameraBinFocus::maximumDigitalZoom() const
{
return 10;
}
qreal CameraBinFocus::opticalZoom() const
{
return 1.0;
}
qreal CameraBinFocus::digitalZoom() const
{
#ifdef Q_WS_MAEMO_5
gint zoomFactor = 0;
g_object_get(GST_BIN(m_session->cameraBin()), "zoom", &zoomFactor, NULL);
return zoomFactor/100.0;
#else
gfloat zoomFactor = 1.0;
g_object_get(GST_BIN(m_session->cameraBin()), "zoom", &zoomFactor, NULL);
return zoomFactor;
#endif
}
void CameraBinFocus::zoomTo(qreal optical, qreal digital)
{
Q_UNUSED(optical);
digital = qBound(qreal(1.0), digital, qreal(10.0));
#ifdef Q_WS_MAEMO_5
g_object_set(GST_BIN(m_session->cameraBin()), "zoom", qRound(digital*100.0), NULL);
#else
g_object_set(GST_BIN(m_session->cameraBin()), "zoom", digital, NULL);
#endif
emit digitalZoomChanged(digital);
}
QCameraFocus::FocusPointMode CameraBinFocus::focusPointMode() const
{
return QCameraFocus::FocusPointAuto;
}
void CameraBinFocus::setFocusPointMode(QCameraFocus::FocusPointMode mode)
{
Q_UNUSED(mode);
}
bool CameraBinFocus::isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const
{
return mode == QCameraFocus::FocusPointAuto;
}
QPointF CameraBinFocus::customFocusPoint() const
{
return QPointF(0.5, 0.5);
}
void CameraBinFocus::setCustomFocusPoint(const QPointF &point)
{
Q_UNUSED(point);
}
QCameraFocusZoneList CameraBinFocus::focusZones() const
{
return QCameraFocusZoneList() << QCameraFocusZone(QRectF(0.35, 0.35, 0.3, 0.3), m_focusZoneStatus);
}
void CameraBinFocus::handleFocusMessage(GstMessage *gm)
{
//it's a sync message, so it's called from non main thread
if (gst_structure_has_name(gm->structure, GST_PHOTOGRAPHY_AUTOFOCUS_DONE)) {
gint status = GST_PHOTOGRAPHY_FOCUS_STATUS_NONE;
gst_structure_get_int (gm->structure, "status", &status);
QCamera::LockStatus focusStatus = m_focusStatus;
QCamera::LockChangeReason reason = QCamera::UserRequest;
switch (status) {
case GST_PHOTOGRAPHY_FOCUS_STATUS_FAIL:
focusStatus = QCamera::Unlocked;
reason = QCamera::LockFailed;
break;
case GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS:
focusStatus = QCamera::Locked;
break;
case GST_PHOTOGRAPHY_FOCUS_STATUS_NONE:
break;
case GST_PHOTOGRAPHY_FOCUS_STATUS_RUNNING:
focusStatus = QCamera::Searching;
break;
default:
break;
}
static int signalIndex = metaObject()->indexOfSlot(
"_q_setFocusStatus(QCamera::LockStatus,QCamera::LockChangeReason)");
metaObject()->method(signalIndex).invoke(this,
Qt::QueuedConnection,
Q_ARG(QCamera::LockStatus,focusStatus),
Q_ARG(QCamera::LockChangeReason,reason));
}
}
void CameraBinFocus::_q_setFocusStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason)
{
#ifdef CAMERABIN_DEBUG
qDebug() << Q_FUNC_INFO << "Current:"
<< ENUM_NAME(QCamera, "LockStatus", m_focusStatus)
<< "New:"
<< ENUM_NAME(QCamera, "LockStatus", status) << ENUM_NAME(QCamera, "LockChangeReason", reason);
#endif
if (m_focusStatus != status) {
m_focusStatus = status;
QCameraFocusZone::FocusZoneStatus zonesStatus =
m_focusStatus == QCamera::Locked ?
QCameraFocusZone::Focused : QCameraFocusZone::Selected;
if (m_focusZoneStatus != zonesStatus) {
m_focusZoneStatus = zonesStatus;
emit focusZonesChanged();
}
emit _q_focusStatusChanged(m_focusStatus, reason);
}
}
void CameraBinFocus::_q_handleCameraStateChange(QCamera::State state)
{
if (state != QCamera::ActiveState)
_q_setFocusStatus(QCamera::Unlocked, QCamera::LockLost);
}
void CameraBinFocus::_q_handleCapturedImage()
{
#ifdef Q_WS_MAEMO_5
//N900 lost focus after image capture
if (m_focusStatus != QCamera::Unlocked) {
m_focusStatus = QCamera::Unlocked;
emit _q_focusStatusChanged(QCamera::Unlocked, QCamera::LockLost);
}
#endif
}
void CameraBinFocus::_q_startFocusing()
{
_q_setFocusStatus(QCamera::Searching, QCamera::UserRequest);
gst_photography_set_autofocus(m_session->photography(), TRUE);
}
void CameraBinFocus::_q_stopFocusing()
{
gst_photography_set_autofocus(m_session->photography(), FALSE);
_q_setFocusStatus(QCamera::Unlocked, QCamera::UserRequest);
}

View File

@@ -0,0 +1,104 @@
/****************************************************************************
**
** Copyright (C) 2009 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 CAMERABINFOCUSCONTROL_H
#define CAMERABINFOCUSCONTROL_H
#include <qcamera.h>
#include <qcamerafocuscontrol.h>
#include <gst/gst.h>
#include <glib.h>
class CameraBinSession;
QT_USE_NAMESPACE
class CameraBinFocus : public QCameraFocusControl
{
Q_OBJECT
public:
CameraBinFocus(CameraBinSession *session);
virtual ~CameraBinFocus();
QCameraFocus::FocusMode focusMode() const;
void setFocusMode(QCameraFocus::FocusMode mode);
bool isFocusModeSupported(QCameraFocus::FocusMode mode) const;
qreal maximumOpticalZoom() const;
qreal maximumDigitalZoom() const;
qreal opticalZoom() const;
qreal digitalZoom() const;
void zoomTo(qreal optical, qreal digital) ;
QCameraFocus::FocusPointMode focusPointMode() const;
void setFocusPointMode(QCameraFocus::FocusPointMode mode) ;
bool isFocusPointModeSupported(QCameraFocus::FocusPointMode) const;
QPointF customFocusPoint() const;
void setCustomFocusPoint(const QPointF &point);
QCameraFocusZoneList focusZones() const;
void handleFocusMessage(GstMessage*);
QCamera::LockStatus focusStatus() const { return m_focusStatus; }
Q_SIGNALS:
void _q_focusStatusChanged(QCamera::LockStatus status, QCamera::LockChangeReason reason);
public Q_SLOTS:
void _q_startFocusing();
void _q_stopFocusing();
private Q_SLOTS:
void _q_setFocusStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason);
void _q_handleCameraStateChange(QCamera::State state);
void _q_handleCapturedImage();
private:
CameraBinSession *m_session;
QCameraFocus::FocusMode m_focusMode;
QCamera::LockStatus m_focusStatus;
QCameraFocusZone::FocusZoneStatus m_focusZoneStatus;
};
#endif // CAMERABINFOCUSCONTROL_H

View File

@@ -0,0 +1,347 @@
/****************************************************************************
**
** Copyright (C) 2009 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 "camerabinimagecapture.h"
#include "camerabincapturedestination.h"
#include "camerabincapturebufferformat.h"
#include "camerabinsession.h"
#include "qgstvideobuffer.h"
#include "qvideosurfacegstsink.h"
#include "qgstutils.h"
#include <QtCore/qdebug.h>
#include <QtCore/qbuffer.h>
#include <QtGui/qimagereader.h>
//#define DEBUG_CAPTURE
#ifdef Q_WS_MAEMO_5
#define IMAGE_DONE_SIGNAL "img-done"
#else
#define IMAGE_DONE_SIGNAL "image-done"
#endif
Q_DECLARE_METATYPE(QVideoFrame)
Q_DECLARE_METATYPE(QtMultimediaKit::MetaData)
namespace
{
class CameraRegisterMetaTypes
{
public:
CameraRegisterMetaTypes()
{
qRegisterMetaType<QVideoFrame>("QVideoFrame");
qRegisterMetaType<QtMultimediaKit::MetaData>("QtMultimediaKit::MetaData");
}
} _registerCameraMetaTypes;
}
CameraBinImageCapture::CameraBinImageCapture(CameraBinSession *session)
:QCameraImageCaptureControl(session)
, m_session(session)
, m_ready(false)
, m_requestId(0)
, m_jpegEncoderElement(0)
, m_metadataMuxerElement(0)
{
connect(m_session, SIGNAL(stateChanged(QCamera::State)), SLOT(updateState()));
connect(m_session, SIGNAL(imageExposed(int)), this, SIGNAL(imageExposed(int)));
connect(m_session, SIGNAL(imageCaptured(int,QImage)), this, SIGNAL(imageCaptured(int,QImage)));
connect(m_session, SIGNAL(busMessage(QGstreamerMessage)), SLOT(handleBusMessage(QGstreamerMessage)));
g_signal_connect(G_OBJECT(m_session->cameraBin()), IMAGE_DONE_SIGNAL, G_CALLBACK(handleImageSaved), this);
}
CameraBinImageCapture::~CameraBinImageCapture()
{
}
bool CameraBinImageCapture::isReadyForCapture() const
{
return m_ready;
}
int CameraBinImageCapture::capture(const QString &fileName)
{
m_requestId++;
if (!m_ready) {
emit error(m_requestId, QCameraImageCapture::NotReadyError, tr("Camera not ready"));
return m_requestId;
}
#ifdef DEBUG_CAPTURE
qDebug() << Q_FUNC_INFO << m_requestId << fileName;
#endif
m_session->captureImage(m_requestId, fileName);
return m_requestId;
}
void CameraBinImageCapture::cancelCapture()
{
}
void CameraBinImageCapture::updateState()
{
bool ready = m_session->state() == QCamera::ActiveState;
if (m_ready != ready) {
#ifdef DEBUG_CAPTURE
qDebug() << "readyForCaptureChanged" << ready;
#endif
emit readyForCaptureChanged(m_ready = ready);
}
}
gboolean CameraBinImageCapture::handleImageSaved(GstElement *camera,
const gchar *filename,
CameraBinImageCapture *self)
{
#ifdef DEBUG_CAPTURE
qDebug() << "Image saved" << filename;
#endif
Q_UNUSED(camera);
if (self->m_session->captureDestinationControl()->captureDestination() & QCameraImageCapture::CaptureToFile) {
QMetaObject::invokeMethod(self, "imageSaved",
Qt::QueuedConnection,
Q_ARG(int, self->m_requestId),
Q_ARG(QString, QString::fromUtf8(filename)));
} else {
#ifdef DEBUG_CAPTURE
qDebug() << Q_FUNC_INFO << "Dropped saving file" << filename;
#endif
//camerabin creates an empty file when captured buffer is dropped,
//let's remove it
QFileInfo info(QString::fromUtf8(filename));
if (info.isFile() &&
info.filePath().startsWith("/home") &&
info.size() == 0) {
QFile(info.absoluteFilePath()).remove();
}
}
return true;
}
gboolean CameraBinImageCapture::metadataEventProbe(GstPad *pad, GstEvent *event, CameraBinImageCapture *self)
{
if (GST_EVENT_TYPE(event) == GST_EVENT_TAG) {
GstTagList *gstTags;
gst_event_parse_tag(event, &gstTags);
QMap<QByteArray, QVariant> extendedTags = QGstUtils::gstTagListToMap(gstTags);
#ifdef DEBUG_CAPTURE
qDebug() << QString(gst_structure_to_string(gst_event_get_structure(event))).right(768);
qDebug() << "Capture event probe" << extendedTags;
#endif
QMap<QtMultimediaKit::MetaData, QVariant> tags;
tags[QtMultimediaKit::ISOSpeedRatings] = extendedTags.value("capturing-iso-speed");
tags[QtMultimediaKit::DigitalZoomRatio] = extendedTags.value("capturing-digital-zoom-ratio");
tags[QtMultimediaKit::ExposureTime] = extendedTags.value("capturing-shutter-speed");
tags[QtMultimediaKit::WhiteBalance] = extendedTags.value("capturing-white-balance");
tags[QtMultimediaKit::Flash] = extendedTags.value("capturing-flash-fired");
tags[QtMultimediaKit::FocalLengthIn35mmFilm] = extendedTags.value("capturing-focal-length");
tags[QtMultimediaKit::MeteringMode] = extendedTags.value("capturing-metering-mode");
tags[QtMultimediaKit::ExposureMode] = extendedTags.value("capturing-exposure-mode");
tags[QtMultimediaKit::FNumber] = extendedTags.value("capturing-focal-ratio");
tags[QtMultimediaKit::ExposureMode] = extendedTags.value("capturing-exposure-mode");
QMapIterator<QtMultimediaKit::MetaData, QVariant> i(tags);
while (i.hasNext()) {
i.next();
if (i.value().isValid()) {
QMetaObject::invokeMethod(self, "imageMetadataAvailable",
Qt::QueuedConnection,
Q_ARG(int, self->m_requestId),
Q_ARG(QtMultimediaKit::MetaData, i.key()),
Q_ARG(QVariant, i.value()));
}
}
}
return true;
}
gboolean CameraBinImageCapture::uncompressedBufferProbe(GstPad *pad, GstBuffer *buffer, CameraBinImageCapture *self)
{
Q_UNUSED(pad);
CameraBinSession *session = self->m_session;
#ifdef DEBUG_CAPTURE
qDebug() << "Uncompressed buffer probe" << gst_caps_to_string(GST_BUFFER_CAPS(buffer));
#endif
QCameraImageCapture::CaptureDestinations destination =
session->captureDestinationControl()->captureDestination();
QVideoFrame::PixelFormat format = session->captureBufferFormatControl()->bufferFormat();
if (destination & QCameraImageCapture::CaptureToBuffer) {
if (format != QVideoFrame::Format_Jpeg) {
GstCaps *caps = GST_BUFFER_CAPS(buffer);
int bytesPerLine = -1;
QVideoSurfaceFormat format = QVideoSurfaceGstSink::formatForCaps(caps, &bytesPerLine);
#ifdef DEBUG_CAPTURE
qDebug() << "imageAvailable(uncompressed):" << format;
#endif
QGstVideoBuffer *videoBuffer = new QGstVideoBuffer(buffer, bytesPerLine);
QVideoFrame frame(videoBuffer,
format.frameSize(),
format.pixelFormat());
QMetaObject::invokeMethod(self, "imageAvailable",
Qt::QueuedConnection,
Q_ARG(int, self->m_requestId),
Q_ARG(QVideoFrame, frame));
}
}
//keep the buffer if capture to file or jpeg buffer capture was reuqsted
bool keepBuffer = (destination & QCameraImageCapture::CaptureToFile) ||
((destination & QCameraImageCapture::CaptureToBuffer) &&
format == QVideoFrame::Format_Jpeg);
return keepBuffer;
}
gboolean CameraBinImageCapture::jpegBufferProbe(GstPad *pad, GstBuffer *buffer, CameraBinImageCapture *self)
{
Q_UNUSED(pad);
CameraBinSession *session = self->m_session;
#ifdef DEBUG_CAPTURE
qDebug() << "Jpeg buffer probe" << gst_caps_to_string(GST_BUFFER_CAPS(buffer));
#endif
QCameraImageCapture::CaptureDestinations destination =
session->captureDestinationControl()->captureDestination();
if ((destination & QCameraImageCapture::CaptureToBuffer) &&
session->captureBufferFormatControl()->bufferFormat() == QVideoFrame::Format_Jpeg) {
QGstVideoBuffer *videoBuffer = new QGstVideoBuffer(buffer,
-1); //bytesPerLine is not available for jpegs
QSize resolution = QGstUtils::capsCorrectedResolution(GST_BUFFER_CAPS(buffer));
//if resolution is not presented in caps, try to find it from encoded jpeg data:
if (resolution.isEmpty()) {
QBuffer data;
data.setData(reinterpret_cast<const char*>(GST_BUFFER_DATA(buffer)), GST_BUFFER_SIZE(buffer));
QImageReader reader(&data, "JPEG");
resolution = reader.size();
}
QVideoFrame frame(videoBuffer,
resolution,
QVideoFrame::Format_Jpeg);
QMetaObject::invokeMethod(self, "imageAvailable",
Qt::QueuedConnection,
Q_ARG(int, self->m_requestId),
Q_ARG(QVideoFrame, frame));
}
//drop the buffer if capture to file was disabled
return destination & QCameraImageCapture::CaptureToFile;
}
void CameraBinImageCapture::handleBusMessage(const QGstreamerMessage &message)
{
//Install metadata event and buffer probes
//The image capture pipiline is built dynamically,
//it's necessary to wait until jpeg encoder is added to pipeline
GstMessage *gm = message.rawMessage();
if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_STATE_CHANGED) {
GstState oldState;
GstState newState;
GstState pending;
gst_message_parse_state_changed(gm, &oldState, &newState, &pending);
if (newState == GST_STATE_READY) {
GstElement *element = GST_ELEMENT(GST_MESSAGE_SRC(gm));
if (!element)
return;
QString elementName = QString::fromLatin1(gst_element_get_name(element));
if (elementName.contains("jpegenc") && element != m_jpegEncoderElement) {
m_jpegEncoderElement = element;
GstPad *sinkpad = gst_element_get_static_pad(element, "sink");
//metadata event probe is installed before jpeg encoder
//to emit metadata available signal as soon as possible.
#ifdef DEBUG_CAPTURE
qDebug() << "install metadata probe";
#endif
gst_pad_add_event_probe(sinkpad,
G_CALLBACK(CameraBinImageCapture::metadataEventProbe),
this);
#ifdef DEBUG_CAPTURE
qDebug() << "install uncompressed buffer probe";
#endif
gst_pad_add_buffer_probe(sinkpad,
G_CALLBACK(CameraBinImageCapture::uncompressedBufferProbe),
this);
gst_object_unref(sinkpad);
} else if ((elementName.contains("jifmux") || elementName.startsWith("metadatamux"))
&& element != m_metadataMuxerElement) {
//Jpeg encoded buffer probe is added after jifmux/metadatamux
//element to ensure the resulting jpeg buffer contains capture metadata
m_metadataMuxerElement = element;
GstPad *srcpad = gst_element_get_static_pad(element, "src");
#ifdef DEBUG_CAPTURE
qDebug() << "install jpeg buffer probe";
#endif
gst_pad_add_buffer_probe(srcpad,
G_CALLBACK(CameraBinImageCapture::jpegBufferProbe),
this);
gst_object_unref(srcpad);
}
}
}
}

View File

@@ -0,0 +1,82 @@
/****************************************************************************
**
** Copyright (C) 2009 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 CAMERABINIMAGECAPTURECONTROL_H
#define CAMERABINIMAGECAPTURECONTROL_H
#include <qcameraimagecapturecontrol.h>
#include "camerabinsession.h"
QT_USE_NAMESPACE
class CameraBinImageCapture : public QCameraImageCaptureControl
{
Q_OBJECT
public:
CameraBinImageCapture(CameraBinSession *session);
virtual ~CameraBinImageCapture();
QCameraImageCapture::DriveMode driveMode() const { return QCameraImageCapture::SingleImageCapture; }
void setDriveMode(QCameraImageCapture::DriveMode) {}
bool isReadyForCapture() const;
int capture(const QString &fileName);
void cancelCapture();
private slots:
void updateState();
void handleBusMessage(const QGstreamerMessage &message);
private:
static gboolean metadataEventProbe(GstPad *pad, GstEvent *event, CameraBinImageCapture *);
static gboolean uncompressedBufferProbe(GstPad *pad, GstBuffer *buffer, CameraBinImageCapture *);
static gboolean jpegBufferProbe(GstPad *pad, GstBuffer *buffer, CameraBinImageCapture *);
static gboolean handleImageSaved(GstElement *camera, const gchar *filename, CameraBinImageCapture *);
CameraBinSession *m_session;
bool m_ready;
int m_requestId;
GstElement *m_jpegEncoderElement;
GstElement *m_metadataMuxerElement;
};
#endif // CAMERABINCAPTURECORNTROL_H

View File

@@ -0,0 +1,87 @@
/****************************************************************************
**
** Copyright (C) 2009 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 "camerabinimageencoder.h"
#include "camerabinsession.h"
#include <QtCore/qdebug.h>
CameraBinImageEncoder::CameraBinImageEncoder(CameraBinSession *session)
:QImageEncoderControl(session), m_session(session)
{
}
CameraBinImageEncoder::~CameraBinImageEncoder()
{
}
QList<QSize> CameraBinImageEncoder::supportedResolutions(const QImageEncoderSettings &, bool *continuous) const
{
qDebug() << "CameraBinImageEncoder::supportedResolutions()";
if (continuous)
*continuous = false;
return m_session->supportedResolutions(qMakePair<int,int>(0,0), continuous, QCamera::CaptureStillImage);
}
QStringList CameraBinImageEncoder::supportedImageCodecs() const
{
return QStringList() << "jpeg";
}
QString CameraBinImageEncoder::imageCodecDescription(const QString &codecName) const
{
if (codecName == "jpeg")
return tr("JPEG image");
return QString();
}
QImageEncoderSettings CameraBinImageEncoder::imageSettings() const
{
return m_settings;
}
void CameraBinImageEncoder::setImageSettings(const QImageEncoderSettings &settings)
{
m_settings = settings;
emit settingsChanged();
}

View File

@@ -0,0 +1,86 @@
/****************************************************************************
**
** Copyright (C) 2009 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 CAMERABINIMAGEENCODE_H
#define CAMERABINIMAGEENCODE_H
class CameraBinSession;
#include <qimageencodercontrol.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qmap.h>
#include <gst/gst.h>
QT_USE_NAMESPACE
class CameraBinImageEncoder : public QImageEncoderControl
{
Q_OBJECT
public:
CameraBinImageEncoder(CameraBinSession *session);
virtual ~CameraBinImageEncoder();
QList<QSize> supportedResolutions(const QImageEncoderSettings &settings = QImageEncoderSettings(),
bool *continuous = 0) const;
QStringList supportedImageCodecs() const;
QString imageCodecDescription(const QString &formatName) const;
QImageEncoderSettings imageSettings() const;
void setImageSettings(const QImageEncoderSettings &settings);
Q_SIGNALS:
void settingsChanged();
private:
QImageEncoderSettings m_settings;
CameraBinSession *m_session;
// Added
QStringList m_codecs;
QMap<QString,QByteArray> m_elementNames;
QMap<QString,QString> m_codecDescriptions;
QMap<QString,QStringList> m_codecOptions;
};
#endif

View File

@@ -0,0 +1,171 @@
/****************************************************************************
**
** Copyright (C) 2009 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 "camerabinimageprocessing.h"
#include "camerabinsession.h"
CameraBinImageProcessing::CameraBinImageProcessing(CameraBinSession *session)
:QCameraImageProcessingControl(session),
m_session(session)
{
m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_AUTO] = QCameraImageProcessing::WhiteBalanceAuto;
m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_DAYLIGHT] = QCameraImageProcessing::WhiteBalanceSunlight;
m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_CLOUDY] = QCameraImageProcessing::WhiteBalanceCloudy;
m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_SUNSET] = QCameraImageProcessing::WhiteBalanceSunset;
m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_TUNGSTEN] = QCameraImageProcessing::WhiteBalanceTungsten;
m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_FLUORESCENT] = QCameraImageProcessing::WhiteBalanceFluorescent;
updateColorBalanceValues();
}
CameraBinImageProcessing::~CameraBinImageProcessing()
{
}
void CameraBinImageProcessing::updateColorBalanceValues()
{
if (!GST_IS_COLOR_BALANCE(m_session->cameraBin())) {
// Camerabin doesn't implement gstcolorbalance interface
return;
}
GstColorBalance *balance = GST_COLOR_BALANCE(m_session->cameraBin());
const GList *controls = gst_color_balance_list_channels(balance);
const GList *item;
GstColorBalanceChannel *channel;
gint cur_value;
for (item = controls; item; item = g_list_next (item)) {
channel = (GstColorBalanceChannel *)item->data;
cur_value = gst_color_balance_get_value (balance, channel);
if (!g_ascii_strcasecmp (channel->label, "brightness")) {
m_values[QCameraImageProcessingControl::Brightness] = cur_value;
} else if (!g_ascii_strcasecmp (channel->label, "contrast")) {
m_values[QCameraImageProcessingControl::Contrast] = cur_value;
} else if (!g_ascii_strcasecmp (channel->label, "saturation")) {
m_values[QCameraImageProcessingControl::Saturation] = cur_value;
}
}
}
bool CameraBinImageProcessing::setColorBalanceValue(const QString& channel, int value)
{
if (!GST_IS_COLOR_BALANCE(m_session->cameraBin())) {
// Camerabin doesn't implement gstcolorbalance interface
return false;
}
GstColorBalance *balance = GST_COLOR_BALANCE(m_session->cameraBin());
const GList *controls = gst_color_balance_list_channels(balance);
const GList *item;
GstColorBalanceChannel *colorBalanceChannel;
for (item = controls; item; item = g_list_next (item)) {
colorBalanceChannel = (GstColorBalanceChannel *)item->data;
if (!g_ascii_strcasecmp (colorBalanceChannel->label, channel.toAscii())) {
gst_color_balance_set_value (balance, colorBalanceChannel, value);
return true;
}
}
return false;
}
QCameraImageProcessing::WhiteBalanceMode CameraBinImageProcessing::whiteBalanceMode() const
{
GstWhiteBalanceMode wbMode;
gst_photography_get_white_balance_mode(m_session->photography(), &wbMode);
return m_mappedWbValues[wbMode];
}
void CameraBinImageProcessing::setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceMode mode)
{
if (isWhiteBalanceModeSupported(mode))
gst_photography_set_white_balance_mode(m_session->photography(), m_mappedWbValues.key(mode));
}
bool CameraBinImageProcessing::isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceMode mode) const
{
return m_mappedWbValues.values().contains(mode);
}
bool CameraBinImageProcessing::isProcessingParameterSupported(QCameraImageProcessingControl::ProcessingParameter parameter) const
{
return parameter == QCameraImageProcessingControl::Contrast
|| parameter == QCameraImageProcessingControl::Brightness
|| parameter == QCameraImageProcessingControl::Saturation;
}
QVariant CameraBinImageProcessing::processingParameter(
QCameraImageProcessingControl::ProcessingParameter parameter) const
{
if (m_values.contains(parameter))
return m_values.value(parameter);
else
return QVariant();
}
void CameraBinImageProcessing::setProcessingParameter(
QCameraImageProcessingControl::ProcessingParameter parameter,
QVariant value)
{
switch (parameter) {
case Contrast:
setColorBalanceValue("contrast", value.toInt());
break;
case Brightness:
setColorBalanceValue("brightness", value.toInt());
break;
case Saturation:
setColorBalanceValue("saturation", value.toInt());
break;
default:
break;
}
updateColorBalanceValues();
}

View File

@@ -0,0 +1,84 @@
/****************************************************************************
**
** Copyright (C) 2009 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 CAMERABINIMAGEPROCESSINGCONTROL_H
#define CAMERABINIMAGEPROCESSINGCONTROL_H
#include <qcamera.h>
#include <qcameraimageprocessingcontrol.h>
#include <gst/gst.h>
#include <glib.h>
#include <gst/interfaces/photography.h>
#include <gst/interfaces/colorbalance.h>
class CameraBinSession;
QT_USE_NAMESPACE
class CameraBinImageProcessing : public QCameraImageProcessingControl
{
Q_OBJECT
public:
CameraBinImageProcessing(CameraBinSession *session);
virtual ~CameraBinImageProcessing();
QCameraImageProcessing::WhiteBalanceMode whiteBalanceMode() const;
void setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceMode mode);
bool isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceMode mode) const;
bool isProcessingParameterSupported(ProcessingParameter) const;
QVariant processingParameter(ProcessingParameter parameter) const;
void setProcessingParameter(ProcessingParameter parameter, QVariant value);
private:
bool setColorBalanceValue(const QString& channel, int value);
void updateColorBalanceValues();
private:
CameraBinSession *m_session;
QMap<QCameraImageProcessingControl::ProcessingParameter, int> m_values;
QMap<GstWhiteBalanceMode, QCameraImageProcessing::WhiteBalanceMode> m_mappedWbValues;
};
#endif // CAMERABINIMAGEPROCESSINGCONTROL_H

View File

@@ -0,0 +1,88 @@
/****************************************************************************
**
** Copyright (C) 2009 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 "camerabinlocks.h"
#include "camerabinsession.h"
#include "camerabinfocus.h"
#include <gst/interfaces/photography.h>
#include <QDebug>
CameraBinLocks::CameraBinLocks(CameraBinSession *session)
:QCameraLocksControl(session),
m_session(session),
m_focus(m_session->cameraFocusControl())
{
connect(m_focus, SIGNAL(_q_focusStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)),
this, SLOT(updateFocusStatus(QCamera::LockStatus, QCamera::LockChangeReason)));
}
CameraBinLocks::~CameraBinLocks()
{
}
QCamera::LockTypes CameraBinLocks::supportedLocks() const
{
return QCamera::LockFocus;
}
QCamera::LockStatus CameraBinLocks::lockStatus(QCamera::LockType lock) const
{
return lock == QCamera::LockFocus ? m_focus->focusStatus() : QCamera::Unlocked;
}
void CameraBinLocks::searchAndLock(QCamera::LockTypes locks)
{
if (locks & QCamera::LockFocus)
m_focus->_q_startFocusing();
}
void CameraBinLocks::unlock(QCamera::LockTypes locks)
{
if (locks & QCamera::LockFocus)
m_focus->_q_stopFocusing();
}
void CameraBinLocks::updateFocusStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason)
{
emit lockStatusChanged(QCamera::LockFocus, status, reason);
}

View File

@@ -0,0 +1,79 @@
/****************************************************************************
**
** Copyright (C) 2009 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 CAMERABINLOCKSCONTROL_H
#define CAMERABINLOCKSCONTROL_H
#include <qcamera.h>
#include <qcameralockscontrol.h>
#include <gst/gst.h>
#include <glib.h>
class CameraBinSession;
class CameraBinFocus;
QT_USE_NAMESPACE
class CameraBinLocks : public QCameraLocksControl
{
Q_OBJECT
public:
CameraBinLocks(CameraBinSession *session);
virtual ~CameraBinLocks();
QCamera::LockTypes supportedLocks() const;
QCamera::LockStatus lockStatus(QCamera::LockType lock) const;
void searchAndLock(QCamera::LockTypes locks);
void unlock(QCamera::LockTypes locks);
private slots:
void updateFocusStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason);
private:
CameraBinSession *m_session;
CameraBinFocus *m_focus;
};
#endif

View File

@@ -0,0 +1,198 @@
/****************************************************************************
**
** 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 "camerabinmetadata.h"
#include <gst/gst.h>
#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, 0 },
//{ 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, 0 },
//{ QtMultimediaKit::PixelAspectRatio, 0 },
// 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 }
};
CameraBinMetaData::CameraBinMetaData(QObject *parent)
:QMetaDataWriterControl(parent)
{
}
QVariant CameraBinMetaData::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) {
const char *name = qt_gstreamerMetaDataKeys[i].token;
return m_values.value(QByteArray::fromRawData(name, qstrlen(name)));
}
}
return QVariant();
}
void CameraBinMetaData::setMetaData(QtMultimediaKit::MetaData key, const QVariant &value)
{
static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup);
for (int i = 0; i < count; ++i) {
if (qt_gstreamerMetaDataKeys[i].key == key) {
const char *name = qt_gstreamerMetaDataKeys[i].token;
m_values.insert(QByteArray::fromRawData(name, qstrlen(name)), value);
emit QMetaDataWriterControl::metaDataChanged();
emit metaDataChanged(m_values);
return;
}
}
}
QList<QtMultimediaKit::MetaData> CameraBinMetaData::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_values.keys()) {
QtMultimediaKit::MetaData tag = keysMap.value(key, QtMultimediaKit::MetaData(-1));
if (tag != -1)
res.append(tag);
}
return res;
}
QVariant CameraBinMetaData::extendedMetaData(QString const &name) const
{
return m_values.value(name.toLatin1());
}
void CameraBinMetaData::setExtendedMetaData(QString const &name, QVariant const &value)
{
m_values.insert(name.toLatin1(), value);
emit QMetaDataWriterControl::metaDataChanged();
emit metaDataChanged(m_values);
}
QStringList CameraBinMetaData::availableExtendedMetaData() const
{
QStringList res;
foreach (const QByteArray &key, m_values.keys())
res.append(QString(key));
return res;
}

View File

@@ -0,0 +1,75 @@
/****************************************************************************
**
** 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 CAMERABINCAPTUREMETADATACONTROL_H
#define CAMERABINCAPTUREMETADATACONTROL_H
#include <qmetadatawritercontrol.h>
QT_USE_NAMESPACE
class CameraBinMetaData : public QMetaDataWriterControl
{
Q_OBJECT
public:
CameraBinMetaData(QObject *parent);
virtual ~CameraBinMetaData() {}
bool isMetaDataAvailable() const { return true; }
bool isWritable() const { return true; }
QVariant metaData(QtMultimediaKit::MetaData key) const;
void setMetaData(QtMultimediaKit::MetaData key, const QVariant &value);
QList<QtMultimediaKit::MetaData> availableMetaData() const;
QVariant extendedMetaData(QString const &name) const;
void setExtendedMetaData(QString const &name, QVariant const &value);
QStringList availableExtendedMetaData() const;
Q_SIGNALS:
void metaDataChanged(const QMap<QByteArray, QVariant>&);
private:
QMap<QByteArray, QVariant> m_values;
};
#endif // CAMERABINCAPTUREMETADATACONTROL_H

View File

@@ -0,0 +1,225 @@
/****************************************************************************
**
** 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 "camerabinrecorder.h"
#include "camerabinaudioencoder.h"
#include "camerabinvideoencoder.h"
#include "camerabincontainer.h"
#include <QtCore/QDebug>
CameraBinRecorder::CameraBinRecorder(CameraBinSession *session)
:QMediaRecorderControl(session),
m_session(session),
m_state(QMediaRecorder::StoppedState)
{
connect(m_session, SIGNAL(stateChanged(QCamera::State)), SLOT(updateState()));
connect(m_session, SIGNAL(durationChanged(qint64)), SIGNAL(durationChanged(qint64)));
connect(m_session, SIGNAL(mutedChanged(bool)), this, SIGNAL(mutedChanged(bool)));
}
CameraBinRecorder::~CameraBinRecorder()
{
}
QUrl CameraBinRecorder::outputLocation() const
{
return m_session->outputLocation();
}
bool CameraBinRecorder::setOutputLocation(const QUrl &sink)
{
m_session->setOutputLocation(sink);
return true;
}
QMediaRecorder::State CameraBinRecorder::state() const
{
return m_state;
}
void CameraBinRecorder::updateState()
{
if (m_session->state() != QCamera::ActiveState &&
m_state != QMediaRecorder::StoppedState) {
m_session->stopVideoRecording();
emit stateChanged(m_state = QMediaRecorder::StoppedState);
}
}
qint64 CameraBinRecorder::duration() const
{
return m_session->duration();
}
void CameraBinRecorder::record()
{
if (m_session->state() == QCamera::ActiveState) {
if (m_state == QMediaRecorder::PausedState)
m_session->resumeVideoRecording();
else
m_session->recordVideo();
emit stateChanged(m_state = QMediaRecorder::RecordingState);
} else
emit error(QMediaRecorder::ResourceError, tr("Service has not been started"));
}
void CameraBinRecorder::pause()
{
if (m_session->state() == QCamera::ActiveState) {
m_session->pauseVideoRecording();
emit stateChanged(m_state = QMediaRecorder::PausedState);
} else
emit error(QMediaRecorder::ResourceError, tr("Service has not been started"));
}
void CameraBinRecorder::stop()
{
if (m_session->state() == QCamera::ActiveState) {
m_session->stopVideoRecording();
emit stateChanged(m_state = QMediaRecorder::StoppedState);
}
}
bool CameraBinRecorder::findCodecs()
{
//Check the codecs are compatible with container,
//and choose the compatible codecs/container if omitted
CameraBinAudioEncoder *audioEncodeControl = m_session->audioEncodeControl();
CameraBinVideoEncoder *videoEncodeControl = m_session->videoEncodeControl();
CameraBinContainer *mediaContainerControl = m_session->mediaContainerControl();
audioEncodeControl->resetActualSettings();
videoEncodeControl->resetActualSettings();
mediaContainerControl->resetActualContainer();
QStringList containerCandidates;
if (mediaContainerControl->containerMimeType().isEmpty())
containerCandidates = mediaContainerControl->supportedContainers();
else
containerCandidates << mediaContainerControl->containerMimeType();
QStringList audioCandidates;
QAudioEncoderSettings audioSettings = audioEncodeControl->audioSettings();
if (audioSettings.codec().isEmpty())
audioCandidates = audioEncodeControl->supportedAudioCodecs();
else
audioCandidates << audioSettings.codec();
QStringList videoCandidates;
QVideoEncoderSettings videoSettings = videoEncodeControl->videoSettings();
if (videoSettings.codec().isEmpty())
videoCandidates = videoEncodeControl->supportedVideoCodecs();
else
videoCandidates << videoSettings.codec();
QString container;
QString audioCodec;
QString videoCodec;
foreach (const QString &containerCandidate, containerCandidates) {
QSet<QString> supportedTypes = mediaContainerControl->supportedStreamTypes(containerCandidate);
audioCodec.clear();
videoCodec.clear();
bool found = false;
foreach (const QString &audioCandidate, audioCandidates) {
QSet<QString> audioTypes = audioEncodeControl->supportedStreamTypes(audioCandidate);
if (!audioTypes.intersect(supportedTypes).isEmpty()) {
found = true;
audioCodec = audioCandidate;
break;
}
}
if (!found)
continue;
found = false;
foreach (const QString &videoCandidate, videoCandidates) {
QSet<QString> videoTypes = videoEncodeControl->supportedStreamTypes(videoCandidate);
if (!videoTypes.intersect(supportedTypes).isEmpty()) {
found = true;
videoCodec = videoCandidate;
break;
}
}
if (!found)
continue;
container = containerCandidate;
break;
}
if (container.isEmpty()) {
qWarning() << "Camera error: Not compatible codecs and container format.";
emit error(QMediaRecorder::FormatError, tr("Not compatible codecs and container format."));
return false;
} else {
mediaContainerControl->setActualContainer(container);
QAudioEncoderSettings audioSettings = audioEncodeControl->audioSettings();
audioSettings.setCodec(audioCodec);
audioEncodeControl->setActualAudioSettings(audioSettings);
QVideoEncoderSettings videoSettings = videoEncodeControl->videoSettings();
videoSettings.setCodec(videoCodec);
videoEncodeControl->setActualVideoSettings(videoSettings);
}
return true;
}
void CameraBinRecorder::applySettings()
{
findCodecs();
}
bool CameraBinRecorder::isMuted() const
{
return m_session->isMuted();
}
void CameraBinRecorder::setMuted(bool muted)
{
m_session->setMuted(muted);
}

View File

@@ -0,0 +1,85 @@
/****************************************************************************
**
** 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 CAMERABINRECORDERCONTROL_H
#define CAMERABINRECORDERCONTROL_H
#include <qmediarecordercontrol.h>
#include "camerabinsession.h"
QT_USE_NAMESPACE
class CameraBinRecorder : public QMediaRecorderControl
{
Q_OBJECT
public:
CameraBinRecorder(CameraBinSession *session);
virtual ~CameraBinRecorder();
QUrl outputLocation() const;
bool setOutputLocation(const QUrl &sink);
QMediaRecorder::State state() const;
qint64 duration() const;
bool isMuted() const;
bool findCodecs();
void applySettings();
public slots:
void record();
void pause();
void stop();
void setMuted(bool);
private slots:
void updateState();
private:
CameraBinSession *m_session;
QMediaRecorder::State m_state;
};
#endif // CAMERABINCAPTURECORNTROL_H

View File

@@ -0,0 +1,188 @@
/****************************************************************************
**
** 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 "camerabinresourcepolicy.h"
#ifdef Q_WS_MAEMO_6
#define HAVE_RESOURCE_POLICY
#endif
//#define DEBUG_RESOURCE_POLICY
#include <QtCore/qdebug.h>
#include <QtCore/qset.h>
#ifdef HAVE_RESOURCE_POLICY
#include <policy/resource.h>
#include <policy/resources.h>
#include <policy/resource-set.h>
#endif
CamerabinResourcePolicy::CamerabinResourcePolicy(QObject *parent) :
QObject(parent),
m_resourceSet(NoResources),
m_releasingResources(false)
{
#ifdef HAVE_RESOURCE_POLICY
//loaded resource set is also kept requested for image and video capture sets
m_resource = new ResourcePolicy::ResourceSet("camera");
m_resource->setAlwaysReply();
m_resource->initAndConnect();
connect(m_resource, SIGNAL(resourcesGranted(const QList<ResourcePolicy::ResourceType>)),
SIGNAL(resourcesGranted()));
connect(m_resource, SIGNAL(resourcesDenied()), SIGNAL(resourcesDenied()));
connect(m_resource, SIGNAL(lostResources()), SIGNAL(resourcesLost()));
connect(m_resource, SIGNAL(resourcesReleased()), SLOT(handleResourcesReleased()));
#endif
}
CamerabinResourcePolicy::~CamerabinResourcePolicy()
{
#ifdef HAVE_RESOURCE_POLICY
//ensure the resources are released
if (m_resourceSet != NoResources)
setResourceSet(NoResources);
//don't delete the resource set until resources are released
if (m_releasingResources) {
m_resource->connect(m_resource, SIGNAL(resourcesReleased()),
SLOT(deleteLater()));
} else {
delete m_resource;
m_resource = 0;
}
#endif
}
CamerabinResourcePolicy::ResourceSet CamerabinResourcePolicy::resourceSet() const
{
return m_resourceSet;
}
void CamerabinResourcePolicy::setResourceSet(CamerabinResourcePolicy::ResourceSet set)
{
CamerabinResourcePolicy::ResourceSet oldSet = m_resourceSet;
m_resourceSet = set;
#ifdef DEBUG_RESOURCE_POLICY
qDebug() << Q_FUNC_INFO << set;
#endif
#ifdef HAVE_RESOURCE_POLICY
QSet<ResourcePolicy::ResourceType> requestedTypes;
switch (set) {
case NoResources:
break;
case LoadedResources:
requestedTypes << ResourcePolicy::LensCoverType //to detect lens cover is opened/closed
<< ResourcePolicy::VideoRecorderType //to open camera device
<< ResourcePolicy::SnapButtonType; //to detect capture button events
break;
case ImageCaptureResources:
requestedTypes << ResourcePolicy::LensCoverType
<< ResourcePolicy::VideoPlaybackType
<< ResourcePolicy::VideoRecorderType
<< ResourcePolicy::AudioPlaybackType
<< ResourcePolicy::ScaleButtonType
<< ResourcePolicy::LedsType
<< ResourcePolicy::SnapButtonType;
break;
case VideoCaptureResources:
requestedTypes << ResourcePolicy::LensCoverType
<< ResourcePolicy::VideoPlaybackType
<< ResourcePolicy::VideoRecorderType
<< ResourcePolicy::AudioPlaybackType
<< ResourcePolicy::AudioRecorderType
<< ResourcePolicy::ScaleButtonType
<< ResourcePolicy::LedsType
<< ResourcePolicy::SnapButtonType;
break;
}
QSet<ResourcePolicy::ResourceType> currentTypes;
foreach (ResourcePolicy::Resource *resource, m_resource->resources())
currentTypes << resource->type();
foreach (ResourcePolicy::ResourceType resourceType, currentTypes - requestedTypes)
m_resource->deleteResource(resourceType);
foreach (ResourcePolicy::ResourceType resourceType, requestedTypes - currentTypes) {
if (resourceType == ResourcePolicy::LensCoverType) {
ResourcePolicy::LensCoverResource *lensCoverResource = new ResourcePolicy::LensCoverResource;
lensCoverResource->setOptional(true);
m_resource->addResourceObject(lensCoverResource);
} else {
m_resource->addResource(resourceType);
}
}
m_resource->update();
if (set != NoResources) {
m_resource->acquire();
} else {
if (oldSet != NoResources) {
m_releasingResources = true;
m_resource->release();
}
}
#endif
}
bool CamerabinResourcePolicy::isResourcesGranted() const
{
#ifdef HAVE_RESOURCE_POLICY
foreach (ResourcePolicy::Resource *resource, m_resource->resources())
if (!resource->isOptional() && !resource->isGranted())
return false;
#endif
return true;
}
void CamerabinResourcePolicy::handleResourcesReleased()
{
#ifdef HAVE_RESOURCE_POLICY
#ifdef DEBUG_RESOURCE_POLICY
qDebug() << Q_FUNC_INFO;
#endif
m_releasingResources = false;
#endif
}

View File

@@ -0,0 +1,84 @@
/****************************************************************************
**
** 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 CAMERARESOURCEPOLICY_H
#define CAMERARESOURCEPOLICY_H
#include <QtCore/qobject.h>
namespace ResourcePolicy {
class ResourceSet;
};
class CamerabinResourcePolicy : public QObject
{
Q_OBJECT
public:
enum ResourceSet {
NoResources,
LoadedResources,
ImageCaptureResources,
VideoCaptureResources
};
CamerabinResourcePolicy(QObject *parent);
~CamerabinResourcePolicy();
ResourceSet resourceSet() const;
void setResourceSet(ResourceSet set);
bool isResourcesGranted() const;
Q_SIGNALS:
void resourcesDenied();
void resourcesGranted();
void resourcesLost();
private Q_SLOTS:
void handleResourcesReleased();
private:
ResourceSet m_resourceSet;
ResourcePolicy::ResourceSet *m_resource;
bool m_releasingResources;
};
#endif

View File

@@ -0,0 +1,261 @@
/****************************************************************************
**
** 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 "camerabinservice.h"
#include "camerabinsession.h"
#include "camerabinrecorder.h"
#include "camerabincontainer.h"
#include "camerabinaudioencoder.h"
#include "camerabinvideoencoder.h"
#include "camerabinimageencoder.h"
#include "qgstreamerbushelper.h"
#include "camerabincontrol.h"
#include "camerabinlocks.h"
#include "camerabinmetadata.h"
#include "camerabinexposure.h"
#include "camerabinflash.h"
#include "camerabinfocus.h"
#include "camerabinimagecapture.h"
#include "camerabinimageprocessing.h"
#include "camerabincapturebufferformat.h"
#include "camerabincapturedestination.h"
#include "qgstreameraudioinputendpointselector.h"
#include "qgstreamervideoinputdevicecontrol.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 <qmediaserviceprovider.h>
#include <QtCore/qdebug.h>
#include <QtCore/qprocess.h>
#if defined(Q_WS_MAEMO_5)
#include "camerabuttonlistener_maemo.h"
#endif
#if defined(Q_WS_MAEMO_6)
#include "camerabuttonlistener_meego.h"
#endif
CameraBinService::CameraBinService(const QString &service, QObject *parent):
QMediaService(parent)
{
m_captureSession = 0;
m_cameraControl = 0;
m_metaDataControl = 0;
m_audioInputEndpointSelector = 0;
m_videoInputDevice = 0;
m_videoOutput = 0;
m_videoRenderer = 0;
m_videoWindow = 0;
m_videoWidgetControl = 0;
m_imageCaptureControl = 0;
if (service == Q_MEDIASERVICE_CAMERA) {
m_captureSession = new CameraBinSession(this);
m_cameraControl = new CameraBinControl(m_captureSession);
m_videoInputDevice = new QGstreamerVideoInputDeviceControl(m_captureSession);
m_imageCaptureControl = new CameraBinImageCapture(m_captureSession);
connect(m_videoInputDevice, SIGNAL(selectedDeviceChanged(QString)),
m_captureSession, SLOT(setDevice(QString)));
if (m_videoInputDevice->deviceCount())
m_captureSession->setDevice(m_videoInputDevice->deviceName(m_videoInputDevice->selectedDevice()));
#if defined(Q_WS_MAEMO_6) && defined(__arm__)
m_videoRenderer = new QGstreamerGLTextureRenderer(this);
#else
m_videoRenderer = new QGstreamerVideoRenderer(this);
#endif
#ifdef Q_WS_MAEMO_6
m_videoWindow = new QGstreamerVideoWindow(this, "omapxvsink");
//m_videoWindow = new QGstreamerVideoWindow(this);
#else
m_videoWindow = new QGstreamerVideoOverlay(this);
#endif
m_videoWidgetControl = new QGstreamerVideoWidgetControl(this);
}
if (!m_captureSession) {
qWarning() << Q_FUNC_INFO << "Service type is not supported:" << service;
return;
}
m_audioInputEndpointSelector = new QGstreamerAudioInputEndpointSelector(this);
connect(m_audioInputEndpointSelector, SIGNAL(activeEndpointChanged(QString)), m_captureSession, SLOT(setCaptureDevice(QString)));
if (m_captureSession && m_audioInputEndpointSelector->availableEndpoints().size() > 0)
m_captureSession->setCaptureDevice(m_audioInputEndpointSelector->defaultEndpoint());
m_metaDataControl = new CameraBinMetaData(this);
connect(m_metaDataControl, SIGNAL(metaDataChanged(QMap<QByteArray,QVariant>)),
m_captureSession, SLOT(setMetaData(QMap<QByteArray,QVariant>)));
#if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
new CameraButtonListener(this);
#endif
#if defined(Q_WS_MAEMO_5)
//disable the system camera application
QProcess::execute("/usr/sbin/dsmetool -k /usr/bin/camera-ui");
#endif
}
CameraBinService::~CameraBinService()
{
#if defined(Q_WS_MAEMO_5)
//restore the system camera application
QProcess::execute("/usr/sbin/dsmetool -U user -o /usr/bin/camera-ui");
#endif
}
QMediaControl *CameraBinService::requestControl(const char *name)
{
if (!m_captureSession)
return 0;
//qDebug() << "Request control" << name;
if (!m_videoOutput) {
if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
m_videoOutput = m_videoRenderer;
m_captureSession->setViewfinder(m_videoRenderer);
} else if (qstrcmp(name, QVideoWindowControl_iid) == 0) {
m_videoOutput = m_videoWindow;
m_captureSession->setViewfinder(m_videoWindow);
} else if (qstrcmp(name, QVideoWidgetControl_iid) == 0) {
m_captureSession->setViewfinder(m_videoWidgetControl);
m_videoOutput = m_videoWidgetControl;
}
if (m_videoOutput)
return m_videoOutput;
}
if (qstrcmp(name,QAudioEndpointSelector_iid) == 0)
return m_audioInputEndpointSelector;
if (qstrcmp(name,QVideoDeviceControl_iid) == 0)
return m_videoInputDevice;
if (qstrcmp(name,QMediaRecorderControl_iid) == 0)
return m_captureSession->recorderControl();
if (qstrcmp(name,QAudioEncoderControl_iid) == 0)
return m_captureSession->audioEncodeControl();
if (qstrcmp(name,QVideoEncoderControl_iid) == 0)
return m_captureSession->videoEncodeControl();
if (qstrcmp(name,QImageEncoderControl_iid) == 0)
return m_captureSession->imageEncodeControl();
if (qstrcmp(name,QMediaContainerControl_iid) == 0)
return m_captureSession->mediaContainerControl();
if (qstrcmp(name,QCameraControl_iid) == 0)
return m_cameraControl;
if (qstrcmp(name,QMetaDataWriterControl_iid) == 0)
return m_metaDataControl;
if (qstrcmp(name, QCameraImageCaptureControl_iid) == 0)
return m_imageCaptureControl;
if (qstrcmp(name, QCameraExposureControl_iid) == 0)
return m_captureSession->cameraExposureControl();
if (qstrcmp(name, QCameraFlashControl_iid) == 0)
return m_captureSession->cameraFlashControl();
if (qstrcmp(name, QCameraFocusControl_iid) == 0)
return m_captureSession->cameraFocusControl();
if (qstrcmp(name, QCameraImageProcessingControl_iid) == 0)
return m_captureSession->imageProcessingControl();
if (qstrcmp(name, QCameraLocksControl_iid) == 0)
return m_captureSession->cameraLocksControl();
if (qstrcmp(name, QCameraCaptureDestinationControl_iid) == 0)
return m_captureSession->captureDestinationControl();
if (qstrcmp(name, QCameraCaptureBufferFormatControl_iid) == 0)
return m_captureSession->captureBufferFormatControl();
return 0;
}
void CameraBinService::releaseControl(QMediaControl *control)
{
if (control && control == m_videoOutput) {
m_videoOutput = 0;
m_captureSession->setViewfinder(0);
}
}
bool CameraBinService::isCameraBinAvailable()
{
GstElementFactory *factory = gst_element_factory_find("camerabin");
if (factory) {
gst_object_unref(GST_OBJECT(factory));
return true;
}
return false;
}

View File

@@ -0,0 +1,96 @@
/****************************************************************************
**
** 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 CAMERABINCAPTURESERVICE_H
#define CAMERABINCAPTURESERVICE_H
#include <qmediaservice.h>
#include <gst/gst.h>
QT_BEGIN_NAMESPACE
class QAudioEndpointSelector;
class QVideoDeviceControl;
QT_END_NAMESPACE
class CameraBinSession;
class CameraBinControl;
class QGstreamerMessage;
class QGstreamerBusHelper;
class QGstreamerVideoRenderer;
class QGstreamerVideoOverlay;
class QGstreamerVideoWidgetControl;
class QGstreamerElementFactory;
class CameraBinMetaData;
class CameraBinImageCapture;
class CameraBinMetaData;
class CameraBinService : public QMediaService
{
Q_OBJECT
public:
CameraBinService(const QString &service, QObject *parent = 0);
virtual ~CameraBinService();
QMediaControl *requestControl(const char *name);
void releaseControl(QMediaControl *);
static bool isCameraBinAvailable();
private:
void setAudioPreview(GstElement*);
CameraBinSession *m_captureSession;
CameraBinControl *m_cameraControl;
CameraBinMetaData *m_metaDataControl;
QAudioEndpointSelector *m_audioInputEndpointSelector;
QVideoDeviceControl *m_videoInputDevice;
QMediaControl *m_videoOutput;
QMediaControl *m_videoRenderer;
QMediaControl *m_videoWindow;
QGstreamerVideoWidgetControl *m_videoWidgetControl;
CameraBinImageCapture *m_imageCaptureControl;
};
#endif // CAMERABINCAPTURESERVICE_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,234 @@
/****************************************************************************
**
** 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 CAMERABINCAPTURESESSION_MAEMO_H
#define CAMERABINCAPTURESESSION_MAEMO_H
#include <qmediarecordercontrol.h>
#include <QtCore/qurl.h>
#include <QtCore/qdir.h>
#include <gst/gst.h>
#include <gst/interfaces/photography.h>
#include "qgstreamerbushelper.h"
#include "qcamera.h"
class QGstreamerMessage;
class QGstreamerBusHelper;
class CameraBinAudioEncoder;
class CameraBinVideoEncoder;
class CameraBinImageEncoder;
class CameraBinRecorder;
class CameraBinContainer;
class CameraBinExposure;
class CameraBinFlash;
class CameraBinFocus;
class CameraBinImageProcessing;
class CameraBinLocks;
class CameraBinCaptureDestination;
class CameraBinCaptureBufferFormat;
class QGstreamerVideoRendererInterface;
class QGstreamerElementFactory
{
public:
virtual GstElement *buildElement() = 0;
};
class CameraBinSession : public QObject, public QGstreamerSyncEventFilter
{
Q_OBJECT
Q_PROPERTY(qint64 duration READ duration NOTIFY durationChanged)
public:
enum CameraRole {
FrontCamera, // Secondary camera
BackCamera // Main photo camera
};
CameraBinSession(QObject *parent);
~CameraBinSession();
GstPhotography *photography();
GstElement *cameraBin() { return m_pipeline; }
CameraRole cameraRole() const;
QList< QPair<int,int> > supportedFrameRates(const QSize &frameSize, bool *continuous) const;
QList<QSize> supportedResolutions( QPair<int,int> rate, bool *continuous, QCamera::CaptureMode mode) const;
QCamera::CaptureMode captureMode() { return m_captureMode; }
void setCaptureMode(QCamera::CaptureMode mode);
QUrl outputLocation() const;
bool setOutputLocation(const QUrl& sink);
QDir defaultDir(QCamera::CaptureMode mode) const;
QString generateFileName(const QString &prefix, const QDir &dir, const QString &ext) const;
CameraBinAudioEncoder *audioEncodeControl() const { return m_audioEncodeControl; }
CameraBinVideoEncoder *videoEncodeControl() const { return m_videoEncodeControl; }
CameraBinImageEncoder *imageEncodeControl() const { return m_imageEncodeControl; }
CameraBinExposure *cameraExposureControl() const { return m_cameraExposureControl; }
CameraBinFlash *cameraFlashControl() const { return m_cameraFlashControl; }
CameraBinFocus *cameraFocusControl() const { return m_cameraFocusControl; }
CameraBinImageProcessing *imageProcessingControl() const { return m_imageProcessingControl; }
CameraBinLocks *cameraLocksControl() const { return m_cameraLocksControl; }
CameraBinCaptureDestination *captureDestinationControl() const { return m_captureDestinationControl; }
CameraBinCaptureBufferFormat *captureBufferFormatControl() const { return m_captureBufferFormatControl; }
CameraBinRecorder *recorderControl() const { return m_recorderControl; }
CameraBinContainer *mediaContainerControl() const { return m_mediaContainerControl; }
QGstreamerElementFactory *audioInput() const { return m_audioInputFactory; }
void setAudioInput(QGstreamerElementFactory *audioInput);
QGstreamerElementFactory *videoInput() const { return m_videoInputFactory; }
void setVideoInput(QGstreamerElementFactory *videoInput);
bool isReady() const;
QObject *viewfinder() const { return m_viewfinder; }
void setViewfinder(QObject *viewfinder);
void captureImage(int requestId, const QString &fileName);
QCamera::State state() const;
bool isBusy() const;
qint64 duration() const;
void recordVideo();
void pauseVideoRecording();
void resumeVideoRecording();
void stopVideoRecording();
bool isMuted() const;
bool processSyncMessage(const QGstreamerMessage &message);
signals:
void stateChanged(QCamera::State state);
void durationChanged(qint64 duration);
void error(int error, const QString &errorString);
void imageExposed(int requestId);
void imageCaptured(int requestId, const QImage &img);
void mutedChanged(bool);
void viewfinderChanged();
void readyChanged(bool);
void busyChanged(bool);
void busMessage(const QGstreamerMessage &message);
public slots:
void setDevice(const QString &device);
void setState(QCamera::State);
void setCaptureDevice(const QString &deviceName);
void setMetaData(const QMap<QByteArray, QVariant>&);
void setMuted(bool);
private slots:
void handleBusMessage(const QGstreamerMessage &message);
void handleViewfinderChange();
private:
bool setupCameraBin();
void setupCaptureResolution();
void updateVideoSourceCaps();
GstElement *buildVideoSrc();
static void updateBusyStatus(GObject *o, GParamSpec *p, gpointer d);
QUrl m_sink;
QUrl m_actualSink;
bool m_recordingActive;
QString m_captureDevice;
QCamera::State m_state;
QCamera::State m_pendingState;
QString m_inputDevice;
bool m_pendingResolutionUpdate;
bool m_muted;
bool m_busy;
QCamera::CaptureMode m_captureMode;
QMap<QByteArray, QVariant> m_metaData;
QGstreamerElementFactory *m_audioInputFactory;
QGstreamerElementFactory *m_videoInputFactory;
QObject *m_viewfinder;
QGstreamerVideoRendererInterface *m_viewfinderInterface;
CameraBinAudioEncoder *m_audioEncodeControl;
CameraBinVideoEncoder *m_videoEncodeControl;
CameraBinImageEncoder *m_imageEncodeControl;
CameraBinRecorder *m_recorderControl;
CameraBinContainer *m_mediaContainerControl;
CameraBinExposure *m_cameraExposureControl;
CameraBinFlash *m_cameraFlashControl;
CameraBinFocus *m_cameraFocusControl;
CameraBinImageProcessing *m_imageProcessingControl;
CameraBinLocks *m_cameraLocksControl;
CameraBinCaptureDestination *m_captureDestinationControl;
CameraBinCaptureBufferFormat *m_captureBufferFormatControl;
QGstreamerBusHelper *m_busHelper;
GstBus* m_bus;
GstElement *m_pipeline;
GstElement *m_videoSrc;
GstElement *m_viewfinderElement;
bool m_viewfinderHasChanged;
bool m_videoInputHasChanged;
GstCaps *m_sourceCaps;
GstElement *m_audioSrc;
GstElement *m_audioConvert;
GstElement *m_capsFilter;
GstElement *m_fileSink;
GstElement *m_audioEncoder;
GstElement *m_muxer;
public:
QString m_imageFileName;
int m_requestId;
};
#endif // CAMERABINCAPTURESESSION_MAEMO_H

View File

@@ -0,0 +1,346 @@
/****************************************************************************
**
** 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 "camerabinvideoencoder.h"
#include "camerabinsession.h"
#include "camerabincontainer.h"
#include <QtCore/qdebug.h>
CameraBinVideoEncoder::CameraBinVideoEncoder(CameraBinSession *session)
:QVideoEncoderControl(session), m_session(session)
{
QList<QByteArray> codecCandidates;
#if defined(Q_WS_MAEMO_5)
codecCandidates << "video/mpeg4" << "video/h264" << "video/h263" << "video/theora"
<< "video/mpeg2" << "video/mpeg1" << "video/mjpeg" << "video/VP8" << "video/h261";
m_elementNames["video/h264"] = "dsph264enc";
m_elementNames["video/mpeg4"] = "dspmp4venc";
m_elementNames["video/h263"] = "dsph263enc";
m_elementNames["video/theora"] = "theoraenc";
m_elementNames["video/mpeg2"] = "ffenc_mpeg2video";
m_elementNames["video/mpeg1"] = "ffenc_mpeg1video";
m_elementNames["video/mjpeg"] = "ffenc_mjpeg";
m_elementNames["video/VP8"] = "vp8enc";
m_elementNames["video/h261"] = "ffenc_h261";
m_codecOptions["video/mpeg4"] = QStringList() << "mode" << "keyframe-interval";
#elif defined(Q_WS_MAEMO_6)
codecCandidates << "video/mpeg4" << "video/h264" << "video/h263";
m_elementNames["video/h264"] = "dsph264enc";
m_elementNames["video/mpeg4"] = "dsphdmp4venc";
m_elementNames["video/h263"] = "dsph263enc";
QStringList options = QStringList() << "mode" << "keyframe-interval" << "max-bitrate" << "intra-refresh";
m_codecOptions["video/h264"] = options;
m_codecOptions["video/mpeg4"] = options;
m_codecOptions["video/h263"] = options;
#else
codecCandidates << "video/h264" << "video/xvid" << "video/mpeg4"
<< "video/mpeg1" << "video/mpeg2" << "video/theora"
<< "video/VP8" << "video/h261" << "video/mjpeg";
m_elementNames["video/h264"] = "x264enc";
m_elementNames["video/xvid"] = "xvidenc";
m_elementNames["video/mpeg4"] = "ffenc_mpeg4";
m_elementNames["video/mpeg1"] = "ffenc_mpeg1video";
m_elementNames["video/mpeg2"] = "ffenc_mpeg2video";
m_elementNames["video/theora"] = "theoraenc";
m_elementNames["video/mjpeg"] = "ffenc_mjpeg";
m_elementNames["video/VP8"] = "vp8enc";
m_elementNames["video/h261"] = "ffenc_h261";
m_codecOptions["video/h264"] = QStringList() << "quantizer";
m_codecOptions["video/xvid"] = QStringList() << "quantizer" << "profile";
m_codecOptions["video/mpeg4"] = QStringList() << "quantizer";
m_codecOptions["video/mpeg1"] = QStringList() << "quantizer";
m_codecOptions["video/mpeg2"] = QStringList() << "quantizer";
m_codecOptions["video/theora"] = QStringList();
#endif
foreach( const QByteArray& codecName, codecCandidates ) {
QByteArray elementName = m_elementNames[codecName];
GstElementFactory *factory = gst_element_factory_find(elementName.constData());
if (factory) {
m_codecs.append(codecName);
const gchar *descr = gst_element_factory_get_description(factory);
m_codecDescriptions.insert(codecName, QString::fromUtf8(descr));
m_streamTypes.insert(codecName,
CameraBinContainer::supportedStreamTypes(factory, GST_PAD_SRC));
gst_object_unref(GST_OBJECT(factory));
}
}
}
CameraBinVideoEncoder::~CameraBinVideoEncoder()
{
}
QList<QSize> CameraBinVideoEncoder::supportedResolutions(const QVideoEncoderSettings &settings, bool *continuous) const
{
if (continuous)
*continuous = false;
QPair<int,int> rate = rateAsRational(settings.frameRate());
//select the closest supported rational rate to settings.frameRate()
return m_session->supportedResolutions(rate, continuous, QCamera::CaptureVideo);
}
QList< qreal > CameraBinVideoEncoder::supportedFrameRates(const QVideoEncoderSettings &settings, bool *continuous) const
{
if (continuous)
*continuous = false;
QList< qreal > res;
QPair<int,int> rate;
foreach(rate, m_session->supportedFrameRates(settings.resolution(), continuous)) {
if (rate.second > 0)
res << qreal(rate.first)/rate.second;
}
return res;
}
QStringList CameraBinVideoEncoder::supportedVideoCodecs() const
{
return m_codecs;
}
QString CameraBinVideoEncoder::videoCodecDescription(const QString &codecName) const
{
return m_codecDescriptions.value(codecName);
}
QStringList CameraBinVideoEncoder::supportedEncodingOptions(const QString &codec) const
{
return m_codecOptions.value(codec);
}
QVariant CameraBinVideoEncoder::encodingOption(const QString &codec, const QString &name) const
{
return m_options[codec].value(name);
}
void CameraBinVideoEncoder::setEncodingOption(
const QString &codec, const QString &name, const QVariant &value)
{
m_options[codec][name] = value;
}
QVideoEncoderSettings CameraBinVideoEncoder::videoSettings() const
{
return m_videoSettings;
}
void CameraBinVideoEncoder::setVideoSettings(const QVideoEncoderSettings &settings)
{
m_videoSettings = settings;
m_userSettings = settings;
emit settingsChanged();
}
void CameraBinVideoEncoder::setActualVideoSettings(const QVideoEncoderSettings &settings)
{
m_videoSettings = settings;
}
void CameraBinVideoEncoder::resetActualSettings()
{
m_videoSettings = m_userSettings;
}
GstElement *CameraBinVideoEncoder::createEncoder()
{
QString codec = m_videoSettings.codec();
QByteArray elementName = m_elementNames.value(codec);
GstElement *encoderElement = gst_element_factory_make( elementName.constData(), "video-encoder");
if (encoderElement) {
if (m_videoSettings.encodingMode() == QtMultimediaKit::ConstantQualityEncoding) {
QtMultimediaKit::EncodingQuality qualityValue = m_videoSettings.quality();
if (elementName == "x264enc") {
//constant quantizer mode
g_object_set(G_OBJECT(encoderElement), "pass", 4, NULL);
int qualityTable[] = {
50, //VeryLow
35, //Low
21, //Normal
15, //High
8 //VeryHigh
};
g_object_set(G_OBJECT(encoderElement), "quantizer", qualityTable[qualityValue], NULL);
} else if (elementName == "xvidenc") {
//constant quantizer mode
g_object_set(G_OBJECT(encoderElement), "pass", 3, NULL);
int qualityTable[] = {
32, //VeryLow
12, //Low
5, //Normal
3, //High
2 //VeryHigh
};
int quant = qualityTable[qualityValue];
g_object_set(G_OBJECT(encoderElement), "quantizer", quant, NULL);
} else if (elementName == "ffenc_mpeg4" ||
elementName == "ffenc_mpeg1video" ||
elementName == "ffenc_mpeg2video" ) {
//constant quantizer mode
g_object_set(G_OBJECT(encoderElement), "pass", 2, NULL);
//quant from 1 to 30, default ~3
double qualityTable[] = {
20, //VeryLow
8.0, //Low
3.0, //Normal
2.5, //High
2.0 //VeryHigh
};
double quant = qualityTable[qualityValue];
g_object_set(G_OBJECT(encoderElement), "quantizer", quant, NULL);
} else if (elementName == "theoraenc") {
int qualityTable[] = {
8, //VeryLow
16, //Low
32, //Normal
45, //High
60 //VeryHigh
};
//quality from 0 to 63
int quality = qualityTable[qualityValue];
g_object_set(G_OBJECT(encoderElement), "quality", quality, NULL);
} else if (elementName == "dsph264enc" ||
elementName == "dspmp4venc" ||
elementName == "dsphdmp4venc" ||
elementName == "dsph263enc") {
//only bitrate parameter is supported
int qualityTable[] = {
1000000, //VeryLow
2000000, //Low
4000000, //Normal
8000000, //High
16000000 //VeryHigh
};
int bitrate = qualityTable[qualityValue];
g_object_set(G_OBJECT(encoderElement), "bitrate", bitrate, NULL);
}
} else {
int bitrate = m_videoSettings.bitRate();
if (bitrate > 0) {
g_object_set(G_OBJECT(encoderElement), "bitrate", bitrate, NULL);
}
}
QMap<QString,QVariant> options = m_options.value(codec);
QMapIterator<QString,QVariant> it(options);
while (it.hasNext()) {
it.next();
QString option = it.key();
QVariant value = it.value();
switch (value.type()) {
case QVariant::Int:
g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toInt(), NULL);
break;
case QVariant::Bool:
g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toBool(), NULL);
break;
case QVariant::Double:
g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toDouble(), NULL);
break;
case QVariant::String:
g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toString().toUtf8().constData(), NULL);
break;
default:
qWarning() << "unsupported option type:" << option << value;
break;
}
}
}
return encoderElement;
}
QPair<int,int> CameraBinVideoEncoder::rateAsRational(qreal frameRate) const
{
if (frameRate > 0.001) {
//convert to rational number
QList<int> denumCandidates;
denumCandidates << 1 << 2 << 3 << 5 << 10 << 25 << 30 << 50 << 100 << 1001 << 1000;
qreal error = 1.0;
int num = 1;
int denum = 1;
foreach (int curDenum, denumCandidates) {
int curNum = qRound(frameRate*curDenum);
qreal curError = qAbs(qreal(curNum)/curDenum - frameRate);
if (curError < error) {
error = curError;
num = curNum;
denum = curDenum;
}
if (curError < 1e-8)
break;
}
return QPair<int,int>(num,denum);
}
return QPair<int,int>();
}
QSet<QString> CameraBinVideoEncoder::supportedStreamTypes(const QString &codecName) const
{
return m_streamTypes.value(codecName);
}

View File

@@ -0,0 +1,106 @@
/****************************************************************************
**
** 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 CAMERABINVIDEOENCODE_H
#define CAMERABINVIDEOENCODE_H
#include <qvideoencodercontrol.h>
class CameraBinSession;
#include <QtCore/qstringlist.h>
#include <QtCore/qmap.h>
#include <QtCore/qset.h>
#include <gst/gst.h>
QT_USE_NAMESPACE
class CameraBinVideoEncoder : public QVideoEncoderControl
{
Q_OBJECT
public:
CameraBinVideoEncoder(CameraBinSession *session);
virtual ~CameraBinVideoEncoder();
QList<QSize> supportedResolutions(const QVideoEncoderSettings &settings = QVideoEncoderSettings(),
bool *continuous = 0) const;
QList< qreal > supportedFrameRates(const QVideoEncoderSettings &settings = QVideoEncoderSettings(),
bool *continuous = 0) const;
QPair<int,int> rateAsRational(qreal) const;
QStringList supportedVideoCodecs() const;
QString videoCodecDescription(const QString &codecName) const;
QVideoEncoderSettings videoSettings() const;
void setVideoSettings(const QVideoEncoderSettings &settings);
QStringList supportedEncodingOptions(const QString &codec) const;
QVariant encodingOption(const QString &codec, const QString &name) const;
void setEncodingOption(const QString &codec, const QString &name, const QVariant &value);
GstElement *createEncoder();
QSet<QString> supportedStreamTypes(const QString &codecName) const;
void setActualVideoSettings(const QVideoEncoderSettings&);
void resetActualSettings();
Q_SIGNALS:
void settingsChanged();
private:
CameraBinSession *m_session;
QStringList m_codecs;
QMap<QString,QString> m_codecDescriptions;
QMap<QString,QByteArray> m_elementNames;
QMap<QString,QStringList> m_codecOptions;
QVideoEncoderSettings m_videoSettings; // backend selected settings, using m_userSettings
QVideoEncoderSettings m_userSettings;
QMap<QString, QMap<QString, QVariant> > m_options;
QMap<QString, QSet<QString> > m_streamTypes;
};
#endif

View File

@@ -0,0 +1,121 @@
/****************************************************************************
**
** Copyright (C) 2009 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 "camerabuttonlistener_maemo.h"
#include <QtDBus/qdbusconnection.h>
#include <QtDBus/qdbusinterface.h>
#include <QtGui/qapplication.h>
#include <QtGui/qevent.h>
#include <QtGui/qwidget.h>
CameraButtonListener::CameraButtonListener(QObject *parent) :
QObject(parent),
m_focusPressed(false),
m_shutterPressed(false)
{
QDBusConnection::systemBus().connect(
QString(),
"/org/freedesktop/Hal/devices/platform_cam_launch",
"org.freedesktop.Hal.Device",
"PropertyModified",
this,
SLOT(updateShuterButtonState()));
QDBusConnection::systemBus().connect(
QString(),
"/org/freedesktop/Hal/devices/platform_cam_focus",
"org.freedesktop.Hal.Device",
"PropertyModified",
this,
SLOT(updateFocusButtonState()));
}
CameraButtonListener::~CameraButtonListener()
{
}
void CameraButtonListener::updateFocusButtonState()
{
QDBusInterface propertyInterface("org.freedesktop.Hal",
"/org/freedesktop/Hal/devices/platform_cam_focus",
"org.freedesktop.Hal.Device",
QDBusConnection::systemBus());
bool pressed = propertyInterface.call("GetProperty", "button.state.value").arguments().at(0).toBool();
if (m_focusPressed != pressed) {
m_focusPressed = pressed;
QWidget *window = QApplication::focusWidget();
if (window) {
QApplication::postEvent(window,
new QKeyEvent(pressed ? QEvent::KeyPress : QEvent::KeyRelease,
0x01100021, //Qt::Key_CameraFocus since Qt 4.7.0
Qt::NoModifier));
}
}
}
void CameraButtonListener::updateShuterButtonState()
{
QDBusInterface propertyInterface("org.freedesktop.Hal",
"/org/freedesktop/Hal/devices/platform_cam_launch",
"org.freedesktop.Hal.Device",
QDBusConnection::systemBus());
bool pressed = propertyInterface.call("GetProperty", "button.state.value").arguments().at(0).toBool();
if (m_shutterPressed != pressed) {
m_shutterPressed = pressed;
QWidget *window = QApplication::focusWidget();
if (window) {
QApplication::postEvent(window,
new QKeyEvent(pressed ? QEvent::KeyPress : QEvent::KeyRelease,
0x01100020, //Qt::Key_Camera since Qt 4.7.0
Qt::NoModifier));
}
}
}

View File

@@ -0,0 +1,64 @@
/****************************************************************************
**
** Copyright (C) 2009 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 CAMERABUTTONLISTENER_MAEMO_H
#define CAMERABUTTONLISTENER_MAEMO_H
#include <QObject>
class CameraButtonListener : public QObject
{
Q_OBJECT
public:
CameraButtonListener(QObject *parent = 0);
virtual ~CameraButtonListener();
private slots:
void updateFocusButtonState();
void updateShuterButtonState();
private:
bool m_focusPressed;
bool m_shutterPressed;
};
#endif // CAMERABUTTONLISTENER_MAEMO_H

View File

@@ -0,0 +1,92 @@
/****************************************************************************
**
** Copyright (C) 2009 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 "camerabuttonlistener_meego.h"
#include <QtGui/qapplication.h>
#include <QtGui/qevent.h>
#include <QtGui/qwidget.h>
#include <QtCore/qdebug.h>
CameraButtonListener::CameraButtonListener(QObject *parent) :
QObject(parent),
m_focusPressed(false),
m_shutterPressed(false)
{
m_keys = new MeeGo::QmKeys(this);
connect(m_keys, SIGNAL(keyEvent(MeeGo::QmKeys::Key, MeeGo::QmKeys::State)),
this, SLOT(handleQmKeyEvent(MeeGo::QmKeys::Key,MeeGo::QmKeys::State)));
}
CameraButtonListener::~CameraButtonListener()
{
}
void CameraButtonListener::handleQmKeyEvent(MeeGo::QmKeys::Key key, MeeGo::QmKeys::State state)
{
if (key == MeeGo::QmKeys::Camera) {
QWidget *window = QApplication::focusWidget();
bool focusPressed = (state == MeeGo::QmKeys::KeyHalfDown) ||
(state == MeeGo::QmKeys::KeyDown);
if (m_focusPressed != focusPressed) {
m_focusPressed = focusPressed;
if (window) {
QApplication::postEvent(window,
new QKeyEvent(focusPressed ? QEvent::KeyPress : QEvent::KeyRelease,
Qt::Key_CameraFocus,
Qt::NoModifier));
}
}
bool shutterPressed = (state == MeeGo::QmKeys::KeyDown);
if (m_shutterPressed != shutterPressed) {
m_shutterPressed = shutterPressed;
if (window) {
QApplication::postEvent(window,
new QKeyEvent(shutterPressed ? QEvent::KeyPress : QEvent::KeyRelease,
Qt::Key_Camera,
Qt::NoModifier));
}
}
}
}

View File

@@ -0,0 +1,65 @@
/****************************************************************************
**
** Copyright (C) 2009 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 CAMERABUTTONLISTENER_MEEGO_H
#define CAMERABUTTONLISTENER_MEEGO_H
#include <QtCore/qobject.h>
#include <qmsystem2/qmkeys.h>
class CameraButtonListener : public QObject
{
Q_OBJECT
public:
CameraButtonListener(QObject *parent = 0);
~CameraButtonListener();
private slots:
void handleQmKeyEvent(MeeGo::QmKeys::Key key, MeeGo::QmKeys::State state);
private:
MeeGo::QmKeys *m_keys;
bool m_focusPressed;
bool m_shutterPressed;
};
#endif // CAMERABUTTONLISTENER_MEEGO_H

View File

@@ -0,0 +1,101 @@
load(qt_module)
TARGET = qgstengine
QT += multimediakit-private network
PLUGIN_TYPE=mediaservice
load(qt_plugin)
DESTDIR = $$QT.multimediakit.plugins/$${PLUGIN_TYPE}
unix:contains(QT_CONFIG, alsa) {
DEFINES += HAVE_ALSA
LIBS += \
-lasound
}
CONFIG += link_pkgconfig
PKGCONFIG += \
gstreamer-0.10 \
gstreamer-base-0.10 \
gstreamer-interfaces-0.10 \
gstreamer-audio-0.10 \
gstreamer-video-0.10
maemo*:PKGCONFIG +=gstreamer-plugins-bad-0.10
contains(gstreamer-appsrc_enabled, yes): PKGCONFIG += gstreamer-app-0.10
maemo5 {
HEADERS += camerabuttonlistener_maemo.h
SOURCES += camerabuttonlistener_maemo.cpp
QT += dbus
}
maemo6 {
HEADERS += camerabuttonlistener_meego.h
SOURCES += camerabuttonlistener_meego.cpp
PKGCONFIG += qmsystem2 libresourceqt1
isEqual(QT_ARCH,armv6) {
HEADERS += qgstreamergltexturerenderer.h
SOURCES += qgstreamergltexturerenderer.cpp
QT += opengl
LIBS += -lEGL -lgstmeegointerfaces-0.10
}
}
# Input
HEADERS += \
qgstreamermessage.h \
qgstreamerbushelper.h \
qgstreamervideorendererinterface.h \
qgstreamerserviceplugin.h \
qgstreameraudioinputendpointselector.h \
qgstreamervideorenderer.h \
qgstvideobuffer.h \
qvideosurfacegstsink.h \
qgstreamervideoinputdevicecontrol.h \
gstvideoconnector.h \
qabstractgstbufferpool.h \
qgstutils.h
SOURCES += \
qgstreamermessage.cpp \
qgstreamerbushelper.cpp \
qgstreamervideorendererinterface.cpp \
qgstreamerserviceplugin.cpp \
qgstreameraudioinputendpointselector.cpp \
qgstreamervideorenderer.cpp \
qgstvideobuffer.cpp \
qvideosurfacegstsink.cpp \
qgstreamervideoinputdevicecontrol.cpp \
gstvideoconnector.c \
qgstutils.cpp
!win32:!contains(QT_CONFIG,embedded):!mac:!symbian:!simulator:!contains(QT_CONFIG, qpa) {
LIBS += -lXv -lX11 -lXext
HEADERS += \
qgstreamervideooverlay.h \
qgstreamervideowindow.h \
qgstreamervideowidget.h \
qx11videosurface.h \
qgstxvimagebuffer.h
SOURCES += \
qgstreamervideooverlay.cpp \
qgstreamervideowindow.cpp \
qgstreamervideowidget.cpp \
qx11videosurface.cpp \
qgstxvimagebuffer.cpp
}
include(mediaplayer/mediaplayer.pri)
include(mediacapture/mediacapture.pri)
contains(gstreamer-photography_enabled, yes) {
include(camerabin/camerabin.pri)
}

View File

@@ -0,0 +1,421 @@
/****************************************************************************
**
** 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 "gstvideoconnector.h"
/* signals */
enum
{
SIGNAL_RESEND_NEW_SEGMENT,
SIGNAL_CONNECTION_FAILED,
LAST_SIGNAL
};
static guint gst_video_connector_signals[LAST_SIGNAL] = { 0 };
GST_DEBUG_CATEGORY_STATIC (video_connector_debug);
#define GST_CAT_DEFAULT video_connector_debug
static GstStaticPadTemplate gst_video_connector_sink_factory =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
static GstStaticPadTemplate gst_video_connector_src_factory =
GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
#define _do_init(bla) \
GST_DEBUG_CATEGORY_INIT (video_connector_debug, \
"video-connector", 0, "An identity like element for reconnecting video stream");
GST_BOILERPLATE_FULL (GstVideoConnector, gst_video_connector, GstElement,
GST_TYPE_ELEMENT, _do_init);
static void gst_video_connector_dispose (GObject * object);
static GstFlowReturn gst_video_connector_chain (GstPad * pad, GstBuffer * buf);
static GstFlowReturn gst_video_connector_buffer_alloc (GstPad * pad,
guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
static GstStateChangeReturn gst_video_connector_change_state (GstElement *
element, GstStateChange transition);
static gboolean gst_video_connector_handle_sink_event (GstPad * pad,
GstEvent * event);
static gboolean gst_video_connector_new_buffer_probe(GstObject *pad, GstBuffer *buffer, guint * object);
static void gst_video_connector_resend_new_segment(GstElement * element, gboolean emitFailedSignal);
static gboolean gst_video_connector_setcaps (GstPad *pad, GstCaps *caps);
static GstCaps *gst_video_connector_getcaps (GstPad * pad);
static gboolean gst_video_connector_acceptcaps (GstPad * pad, GstCaps * caps);
static void
gst_video_connector_base_init (gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_set_details_simple (element_class, "Video Connector",
"Generic",
"An identity like element used for reconnecting video stream",
"Dmytro Poplavskiy <dmytro.poplavskiy@nokia.com>");
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&gst_video_connector_sink_factory));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&gst_video_connector_src_factory));
}
static void
gst_video_connector_class_init (GstVideoConnectorClass * klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
parent_class = g_type_class_peek_parent (klass);
gobject_class->dispose = gst_video_connector_dispose;
gstelement_class->change_state = gst_video_connector_change_state;
klass->resend_new_segment = gst_video_connector_resend_new_segment;
gst_video_connector_signals[SIGNAL_RESEND_NEW_SEGMENT] =
g_signal_new ("resend-new-segment", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GstVideoConnectorClass, resend_new_segment), NULL, NULL,
g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
gst_video_connector_signals[SIGNAL_CONNECTION_FAILED] =
g_signal_new ("connection-failed", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
}
static void
gst_video_connector_init (GstVideoConnector *element,
GstVideoConnectorClass *g_class)
{
element->sinkpad =
gst_pad_new_from_static_template (&gst_video_connector_sink_factory,
"sink");
gst_pad_set_chain_function(element->sinkpad,
GST_DEBUG_FUNCPTR (gst_video_connector_chain));
gst_pad_set_event_function(element->sinkpad,
GST_DEBUG_FUNCPTR (gst_video_connector_handle_sink_event));
gst_pad_set_bufferalloc_function(element->sinkpad,
GST_DEBUG_FUNCPTR (gst_video_connector_buffer_alloc));
gst_pad_set_setcaps_function(element->sinkpad,
GST_DEBUG_FUNCPTR (gst_video_connector_setcaps));
gst_pad_set_getcaps_function(element->sinkpad,
GST_DEBUG_FUNCPTR(gst_video_connector_getcaps));
gst_pad_set_acceptcaps_function(element->sinkpad,
GST_DEBUG_FUNCPTR(gst_video_connector_acceptcaps));
gst_element_add_pad (GST_ELEMENT (element), element->sinkpad);
element->srcpad =
gst_pad_new_from_static_template (&gst_video_connector_src_factory,
"src");
gst_pad_add_buffer_probe(element->srcpad,
G_CALLBACK(gst_video_connector_new_buffer_probe), element);
gst_element_add_pad (GST_ELEMENT (element), element->srcpad);
element->relinked = FALSE;
element->failedSignalEmited = FALSE;
gst_segment_init (&element->segment, GST_FORMAT_TIME);
element->latest_buffer = NULL;
}
static void
gst_video_connector_reset (GstVideoConnector * element)
{
element->relinked = FALSE;
element->failedSignalEmited = FALSE;
if (element->latest_buffer != NULL) {
gst_buffer_unref (element->latest_buffer);
element->latest_buffer = NULL;
}
gst_segment_init (&element->segment, GST_FORMAT_UNDEFINED);
}
static void
gst_video_connector_dispose (GObject * object)
{
GstVideoConnector *element = GST_VIDEO_CONNECTOR (object);
gst_video_connector_reset (element);
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static GstFlowReturn
gst_video_connector_buffer_alloc (GstPad * pad, guint64 offset, guint size,
GstCaps * caps, GstBuffer ** buf)
{
GstVideoConnector *element;
GstFlowReturn res = GST_FLOW_OK;
element = GST_VIDEO_CONNECTOR (GST_PAD_PARENT (pad));
if (!buf)
return GST_FLOW_ERROR;
*buf = NULL;
GST_OBJECT_LOCK (element);
gst_object_ref(element->srcpad);
GST_OBJECT_UNLOCK (element);
res = gst_pad_alloc_buffer(element->srcpad, offset, size, caps, buf);
gst_object_unref (element->srcpad);
GST_DEBUG_OBJECT (element, "buffer alloc finished: %s", gst_flow_get_name (res));
return res;
}
static gboolean
gst_video_connector_setcaps (GstPad *pad, GstCaps *caps)
{
GstVideoConnector *element;
element = GST_VIDEO_CONNECTOR (GST_PAD_PARENT (pad));
/* forward-negotiate */
gboolean res = gst_pad_set_caps(element->srcpad, caps);
GST_DEBUG_OBJECT(element, "gst_video_connector_setcaps %s %i", gst_caps_to_string(caps), res);
if (!res) {
//if set_caps failed, emit "connection-failed" signal
//so colorspace transformation elemnt can be inserted
GST_INFO_OBJECT(element, "gst_video_connector_setcaps failed, emit connection-failed signal");
g_signal_emit(G_OBJECT(element), gst_video_connector_signals[SIGNAL_CONNECTION_FAILED], 0);
return gst_pad_set_caps(element->srcpad, caps);
}
return TRUE;
}
static GstCaps *gst_video_connector_getcaps (GstPad * pad)
{
GstVideoConnector *element;
element = GST_VIDEO_CONNECTOR (GST_PAD_PARENT (pad));
#if (GST_VERSION_MICRO > 25)
GstCaps *caps = gst_pad_peer_get_caps_reffed(element->srcpad);
#else
GstCaps *caps = gst_pad_peer_get_caps(element->srcpad);
#endif
if (!caps)
caps = gst_caps_new_any();
return caps;
}
static gboolean gst_video_connector_acceptcaps (GstPad * pad, GstCaps * caps)
{
GstVideoConnector *element;
element = GST_VIDEO_CONNECTOR (GST_PAD_PARENT (pad));
return gst_pad_peer_accept_caps(element->srcpad, caps);
}
static void
gst_video_connector_resend_new_segment(GstElement * element, gboolean emitFailedSignal)
{
GST_INFO_OBJECT(element, "New segment requested, failed signal enabled: %i", emitFailedSignal);
GstVideoConnector *connector = GST_VIDEO_CONNECTOR(element);
connector->relinked = TRUE;
if (emitFailedSignal)
connector->failedSignalEmited = FALSE;
}
static gboolean gst_video_connector_new_buffer_probe(GstObject *pad, GstBuffer *buffer, guint * object)
{
GstVideoConnector *element = GST_VIDEO_CONNECTOR (object);
/*
If relinking is requested, the current buffer should be rejected and
the new segment + previous buffer should be pushed first
*/
if (element->relinked)
GST_LOG_OBJECT(element, "rejected buffer because of new segment request");
return !element->relinked;
}
static GstFlowReturn
gst_video_connector_chain (GstPad * pad, GstBuffer * buf)
{
GstFlowReturn res;
GstVideoConnector *element;
element = GST_VIDEO_CONNECTOR (gst_pad_get_parent (pad));
do {
/*
Resend the segment message and last buffer to preroll the new sink.
Sinks can be changed multiple times while paused,
while loop allows to send the segment message and preroll
all of them with the same buffer.
*/
while (element->relinked) {
element->relinked = FALSE;
gint64 pos = element->segment.last_stop;
if (element->latest_buffer && GST_BUFFER_TIMESTAMP_IS_VALID(element->latest_buffer)) {
pos = GST_BUFFER_TIMESTAMP (element->latest_buffer);
}
//push a new segment and last buffer
GstEvent *ev = gst_event_new_new_segment (TRUE,
element->segment.rate,
element->segment.format,
pos, //start
element->segment.stop,
pos);
GST_DEBUG_OBJECT (element, "Pushing new segment event");
if (!gst_pad_push_event (element->srcpad, ev)) {
GST_WARNING_OBJECT (element,
"Newsegment handling failed in %" GST_PTR_FORMAT,
element->srcpad);
}
if (element->latest_buffer) {
GST_DEBUG_OBJECT (element, "Pushing latest buffer...");
gst_buffer_ref(element->latest_buffer);
gst_pad_push(element->srcpad, element->latest_buffer);
}
}
gst_buffer_ref(buf);
//it's possible video sink is changed during gst_pad_push blocked by
//pad lock, in this case ( element->relinked == TRUE )
//the buffer should be rejected by the buffer probe and
//the new segment + prev buffer should be sent before
GST_LOG_OBJECT (element, "Pushing buffer...");
res = gst_pad_push (element->srcpad, buf);
GST_LOG_OBJECT (element, "Pushed buffer: %s", gst_flow_get_name (res));
//if gst_pad_push failed give the service another chance,
//it may still work with the colorspace element added
if (!element->failedSignalEmited && res == GST_FLOW_NOT_NEGOTIATED) {
element->failedSignalEmited = TRUE;
GST_INFO_OBJECT(element, "gst_pad_push failed, emit connection-failed signal");
g_signal_emit(G_OBJECT(element), gst_video_connector_signals[SIGNAL_CONNECTION_FAILED], 0);
}
} while (element->relinked);
if (element->latest_buffer) {
gst_buffer_unref (element->latest_buffer);
element->latest_buffer = NULL;
}
//don't save the last video buffer on maemo6 because of buffers shortage
//with omapxvsink
#ifndef Q_WS_MAEMO_6
element->latest_buffer = gst_buffer_ref(buf);
#endif
gst_buffer_unref(buf);
gst_object_unref (element);
return res;
}
static GstStateChangeReturn
gst_video_connector_change_state (GstElement * element,
GstStateChange transition)
{
GstVideoConnector *connector;
GstStateChangeReturn result;
connector = GST_VIDEO_CONNECTOR(element);
result = GST_ELEMENT_CLASS (parent_class)->change_state(element, transition);
switch (transition) {
case GST_STATE_CHANGE_PAUSED_TO_READY:
gst_video_connector_reset (connector);
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
connector->relinked = FALSE;
break;
default:
break;
}
return result;
}
static gboolean
gst_video_connector_handle_sink_event (GstPad * pad, GstEvent * event)
{
if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) {
GstVideoConnector *element = GST_VIDEO_CONNECTOR (gst_pad_get_parent (pad));
gboolean update;
GstFormat format;
gdouble rate, arate;
gint64 start, stop, time;
gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
&start, &stop, &time);
GST_LOG_OBJECT (element,
"NEWSEGMENT update %d, rate %lf, applied rate %lf, "
"format %d, " "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %"
G_GINT64_FORMAT, update, rate, arate, format, start, stop, time);
gst_segment_set_newsegment_full (&element->segment, update,
rate, arate, format, start, stop, time);
gst_object_unref (element);
}
return gst_pad_event_default (pad, event);
}

View File

@@ -0,0 +1,87 @@
/****************************************************************************
**
** 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 QGSTVIDEOCONNECTOR_H
#define QGSTVIDEOCONNECTOR_H
#include <gst/gst.h>
G_BEGIN_DECLS
#define GST_TYPE_VIDEO_CONNECTOR \
(gst_video_connector_get_type())
#define GST_VIDEO_CONNECTOR(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VIDEO_CONNECTOR, GstVideoConnector))
#define GST_VIDEO_CONNECTOR_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_VIDEO_CONNECTOR, GstVideoConnectorClass))
#define GST_IS_VIDEO_CONNECTOR(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VIDEO_CONNECTOR))
#define GST_IS_VIDEO_CONNECTOR_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VIDEO_CONNECTOR))
typedef struct _GstVideoConnector GstVideoConnector;
typedef struct _GstVideoConnectorClass GstVideoConnectorClass;
struct _GstVideoConnector {
GstElement element;
GstPad *srcpad;
GstPad *sinkpad;
gboolean relinked;
gboolean failedSignalEmited;
GstSegment segment;
GstBuffer *latest_buffer;
};
struct _GstVideoConnectorClass {
GstElementClass parent_class;
/* action signal to resend new segment */
void (*resend_new_segment) (GstElement * element, gboolean emitFailedSignal);
};
GType gst_video_connector_get_type (void);
G_END_DECLS
#endif

View File

@@ -0,0 +1,27 @@
INCLUDEPATH += $$PWD
DEFINES += QMEDIA_GSTREAMER_CAPTURE
HEADERS += $$PWD/qgstreamercaptureservice.h \
$$PWD/qgstreamercapturesession.h \
$$PWD/qgstreameraudioencode.h \
$$PWD/qgstreamervideoencode.h \
$$PWD/qgstreamerrecordercontrol.h \
$$PWD/qgstreamermediacontainercontrol.h \
$$PWD/qgstreamercameracontrol.h \
$$PWD/qgstreamerv4l2input.h \
$$PWD/qgstreamercapturemetadatacontrol.h \
$$PWD/qgstreamerimagecapturecontrol.h \
$$PWD/qgstreamerimageencode.h
SOURCES += $$PWD/qgstreamercaptureservice.cpp \
$$PWD/qgstreamercapturesession.cpp \
$$PWD/qgstreameraudioencode.cpp \
$$PWD/qgstreamervideoencode.cpp \
$$PWD/qgstreamerrecordercontrol.cpp \
$$PWD/qgstreamermediacontainercontrol.cpp \
$$PWD/qgstreamercameracontrol.cpp \
$$PWD/qgstreamerv4l2input.cpp \
$$PWD/qgstreamercapturemetadatacontrol.cpp \
$$PWD/qgstreamerimagecapturecontrol.cpp \
$$PWD/qgstreamerimageencode.cpp

View File

@@ -0,0 +1,292 @@
/****************************************************************************
**
** 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 "qgstreameraudioencode.h"
#include "qgstreamercapturesession.h"
#include "qgstreamermediacontainercontrol.h"
#include <QtCore/qdebug.h>
#include <math.h>
QGstreamerAudioEncode::QGstreamerAudioEncode(QObject *parent)
:QAudioEncoderControl(parent)
{
QList<QByteArray> codecCandidates;
#if defined(Q_WS_MAEMO_5)
codecCandidates << "audio/PCM"; //<< "audio/AMR" << "audio/AMR-WB" << "audio/speex";
#elif defined(Q_WS_MAEMO_6)
codecCandidates << "audio/AAC" << "audio/mpeg" << "audio/vorbis" << "audio/speex" << "audio/GSM"
<< "audio/PCM" << "audio/AMR" << "audio/AMR-WB" << "audio/FLAC";
#else
codecCandidates << "audio/mpeg" << "audio/vorbis" << "audio/speex" << "audio/GSM"
<< "audio/PCM" << "audio/AMR" << "audio/AMR-WB" << "audio/FLAC";
#endif
#if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
m_elementNames["audio/AMR"] = "nokiaamrnbenc";
m_elementNames["audio/AMR-WB"] = "nokiaamrwbenc";
m_elementNames["audio/AAC"] = "nokiaaacenc";
#else
m_elementNames["audio/mpeg"] = "lamemp3enc";
m_elementNames["audio/AMR"] = "amrnbenc";
m_elementNames["audio/AMR-WB"] = "amrwbenc";
#endif
m_elementNames["audio/vorbis"] = "vorbisenc";
m_elementNames["audio/speex"] = "speexenc";
m_elementNames["audio/PCM"] = "audioresample";
m_elementNames["audio/FLAC"] = "flacenc";
m_elementNames["audio/GSM"] = "gsmenc";
m_codecOptions["audio/vorbis"] = QStringList() << "min-bitrate" << "max-bitrate";
m_codecOptions["audio/mpeg"] = QStringList() << "mode";
m_codecOptions["audio/speex"] = QStringList() << "mode" << "vbr" << "vad" << "dtx";
m_codecOptions["audio/GSM"] = QStringList();
m_codecOptions["audio/PCM"] = QStringList();
m_codecOptions["audio/AMR"] = QStringList();
m_codecOptions["audio/AMR-WB"] = QStringList();
foreach( const QByteArray& codecName, codecCandidates ) {
QByteArray elementName = m_elementNames[codecName];
GstElementFactory *factory = gst_element_factory_find(elementName.constData());
if (factory) {
m_codecs.append(codecName);
const gchar *descr = gst_element_factory_get_description(factory);
if (codecName == QByteArray("audio/PCM"))
m_codecDescriptions.insert(codecName, tr("Raw PCM audio"));
else
m_codecDescriptions.insert(codecName, QString::fromUtf8(descr));
m_streamTypes.insert(codecName,
QGstreamerMediaContainerControl::supportedStreamTypes(factory, GST_PAD_SRC));
gst_object_unref(GST_OBJECT(factory));
}
}
//if (!m_codecs.isEmpty())
// m_audioSettings.setCodec(m_codecs[0]);
}
QGstreamerAudioEncode::~QGstreamerAudioEncode()
{
}
QStringList QGstreamerAudioEncode::supportedAudioCodecs() const
{
return m_codecs;
}
QString QGstreamerAudioEncode::codecDescription(const QString &codecName) const
{
return m_codecDescriptions.value(codecName);
}
QStringList QGstreamerAudioEncode::supportedEncodingOptions(const QString &codec) const
{
return m_codecOptions.value(codec);
}
QVariant QGstreamerAudioEncode::encodingOption(
const QString &codec, const QString &name) const
{
return m_options[codec].value(name);
}
void QGstreamerAudioEncode::setEncodingOption(
const QString &codec, const QString &name, const QVariant &value)
{
m_options[codec][name] = value;
}
QList<int> QGstreamerAudioEncode::supportedSampleRates(const QAudioEncoderSettings &, bool *) const
{
//TODO check element caps to find actual values
return QList<int>();
}
QAudioEncoderSettings QGstreamerAudioEncode::audioSettings() const
{
return m_audioSettings;
}
void QGstreamerAudioEncode::setAudioSettings(const QAudioEncoderSettings &settings)
{
m_audioSettings = settings;
}
GstElement *QGstreamerAudioEncode::createEncoder()
{
QString codec = m_audioSettings.codec();
GstElement *encoderElement = gst_element_factory_make(m_elementNames.value(codec).constData(), NULL);
if (!encoderElement)
return 0;
GstBin * encoderBin = GST_BIN(gst_bin_new("audio-encoder-bin"));
GstElement *capsFilter = gst_element_factory_make("capsfilter", NULL);
gst_bin_add(encoderBin, capsFilter);
gst_bin_add(encoderBin, encoderElement);
gst_element_link(capsFilter, encoderElement);
// add ghostpads
GstPad *pad = gst_element_get_static_pad(capsFilter, "sink");
gst_element_add_pad(GST_ELEMENT(encoderBin), gst_ghost_pad_new("sink", pad));
gst_object_unref(GST_OBJECT(pad));
pad = gst_element_get_static_pad(encoderElement, "src");
gst_element_add_pad(GST_ELEMENT(encoderBin), gst_ghost_pad_new("src", pad));
gst_object_unref(GST_OBJECT(pad));
if (m_audioSettings.sampleRate() > 0 || m_audioSettings.channelCount() > 0) {
GstCaps *caps = gst_caps_new_empty();
GstStructure *structure = gst_structure_new("audio/x-raw-int", NULL);
if (m_audioSettings.sampleRate() > 0)
gst_structure_set(structure, "rate", G_TYPE_INT, m_audioSettings.sampleRate(), NULL );
if (m_audioSettings.channelCount() > 0)
gst_structure_set(structure, "channels", G_TYPE_INT, m_audioSettings.channelCount(), NULL );
gst_caps_append_structure(caps,structure);
//qDebug() << "set caps filter:" << gst_caps_to_string(caps);
g_object_set(G_OBJECT(capsFilter), "caps", caps, NULL);
}
if (encoderElement) {
if (m_audioSettings.encodingMode() == QtMultimediaKit::ConstantQualityEncoding) {
QtMultimediaKit::EncodingQuality qualityValue = m_audioSettings.quality();
if (codec == QLatin1String("audio/vorbis")) {
double qualityTable[] = {
0.1, //VeryLow
0.3, //Low
0.5, //Normal
0.7, //High
1.0 //VeryHigh
};
g_object_set(G_OBJECT(encoderElement), "quality", qualityTable[qualityValue], NULL);
} else if (codec == QLatin1String("audio/mpeg")) {
g_object_set(G_OBJECT(encoderElement), "target", 0, NULL); //constant quality mode
qreal quality[] = {
1, //VeryLow
3, //Low
5, //Normal
7, //High
9 //VeryHigh
};
g_object_set(G_OBJECT(encoderElement), "quality", quality[qualityValue], NULL);
} else if (codec == QLatin1String("audio/speex")) {
//0-10 range with default 8
double qualityTable[] = {
2, //VeryLow
5, //Low
8, //Normal
9, //High
10 //VeryHigh
};
g_object_set(G_OBJECT(encoderElement), "quality", qualityTable[qualityValue], NULL);
} else if (codec.startsWith("audio/AMR")) {
int band[] = {
0, //VeryLow
2, //Low
4, //Normal
6, //High
7 //VeryHigh
};
g_object_set(G_OBJECT(encoderElement), "band-mode", band[qualityValue], NULL);
}
} else {
int bitrate = m_audioSettings.bitRate();
if (bitrate > 0) {
if (codec == QLatin1String("audio/mpeg")) {
g_object_set(G_OBJECT(encoderElement), "target", 1, NULL); //constant bitrate mode
}
g_object_set(G_OBJECT(encoderElement), "bitrate", bitrate, NULL);
}
}
QMap<QString, QVariant> options = m_options.value(codec);
QMapIterator<QString,QVariant> it(options);
while (it.hasNext()) {
it.next();
QString option = it.key();
QVariant value = it.value();
switch (value.type()) {
case QVariant::Int:
g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toInt(), NULL);
break;
case QVariant::Bool:
g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toBool(), NULL);
break;
case QVariant::Double:
g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toDouble(), NULL);
break;
case QVariant::String:
g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toString().toUtf8().constData(), NULL);
break;
default:
qWarning() << "unsupported option type:" << option << value;
break;
}
}
}
return GST_ELEMENT(encoderBin);
}
QSet<QString> QGstreamerAudioEncode::supportedStreamTypes(const QString &codecName) const
{
return m_streamTypes.value(codecName);
}

View File

@@ -0,0 +1,97 @@
/****************************************************************************
**
** 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 QGSTREAMERAUDIOENCODE_H
#define QGSTREAMERAUDIOENCODE_H
#include <qaudioencodercontrol.h>
class QGstreamerCaptureSession;
#include <QtCore/qstringlist.h>
#include <QtCore/qmap.h>
#include <QtCore/qset.h>
#include <gst/gst.h>
#include <qaudioformat.h>
QT_USE_NAMESPACE
class QGstreamerAudioEncode : public QAudioEncoderControl
{
Q_OBJECT
public:
QGstreamerAudioEncode(QObject *parent);
virtual ~QGstreamerAudioEncode();
QStringList supportedAudioCodecs() const;
QString codecDescription(const QString &codecName) const;
QStringList supportedEncodingOptions(const QString &codec) const;
QVariant encodingOption(const QString &codec, const QString &name) const;
void setEncodingOption(const QString &codec, const QString &name, const QVariant &value);
QList<int> supportedSampleRates(const QAudioEncoderSettings &settings = QAudioEncoderSettings(),
bool *isContinuous = 0) const;
QList<int> supportedChannelCounts(const QAudioEncoderSettings &settings = QAudioEncoderSettings()) const;
QList<int> supportedSampleSizes(const QAudioEncoderSettings &settings = QAudioEncoderSettings()) const;
QAudioEncoderSettings audioSettings() const;
void setAudioSettings(const QAudioEncoderSettings&);
GstElement *createEncoder();
QSet<QString> supportedStreamTypes(const QString &codecName) const;
private:
QStringList m_codecs;
QMap<QString,QByteArray> m_elementNames;
QMap<QString,QString> m_codecDescriptions;
QMap<QString,QStringList> m_codecOptions;
QMap<QString, QMap<QString, QVariant> > m_options;
QMap<QString, QSet<QString> > m_streamTypes;
QAudioEncoderSettings m_audioSettings;
};
#endif

View File

@@ -0,0 +1,185 @@
/****************************************************************************
**
** Copyright (C) 2009 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 "qgstreamercameracontrol.h"
#include "qgstreamerimageencode.h"
#include <QtCore/qdebug.h>
#include <QtCore/qfile.h>
QGstreamerCameraControl::QGstreamerCameraControl(QGstreamerCaptureSession *session)
:QCameraControl(session),
m_captureMode(QCamera::CaptureStillImage),
m_session(session),
m_state(QCamera::UnloadedState),
m_status(QCamera::UnloadedStatus),
m_reloadPending(false)
{
connect(m_session, SIGNAL(stateChanged(QGstreamerCaptureSession::State)),
this, SLOT(updateStatus()));
connect(m_session->imageEncodeControl(), SIGNAL(settingsChanged()),
SLOT(reloadLater()));
connect(m_session, SIGNAL(viewfinderChanged()),
SLOT(reloadLater()));
connect(m_session, SIGNAL(readyChanged(bool)),
SLOT(reloadLater()));
}
QGstreamerCameraControl::~QGstreamerCameraControl()
{
}
void QGstreamerCameraControl::setCaptureMode(QCamera::CaptureMode mode)
{
if (m_captureMode == mode)
return;
switch (mode) {
case QCamera::CaptureStillImage:
m_session->setCaptureMode(QGstreamerCaptureSession::Image);
break;
case QCamera::CaptureVideo:
m_session->setCaptureMode(QGstreamerCaptureSession::AudioAndVideo);
break;
}
emit captureModeChanged(mode);
updateStatus();
reloadLater();
}
void QGstreamerCameraControl::setState(QCamera::State state)
{
if (m_state == state)
return;
m_state = state;
switch (state) {
case QCamera::UnloadedState:
case QCamera::LoadedState:
m_session->setState(QGstreamerCaptureSession::StoppedState);
break;
case QCamera::ActiveState:
//postpone changing to Active if the session is nor ready yet
if (m_session->isReady()) {
m_session->setState(QGstreamerCaptureSession::PreviewState);
} else {
#ifdef CAMEABIN_DEBUG
qDebug() << "Camera session is not ready yet, postpone activating";
#endif
}
break;
default:
emit error(QCamera::NotSupportedFeatureError, tr("State not supported."));
}
updateStatus();
emit stateChanged(m_state);
}
QCamera::State QGstreamerCameraControl::state() const
{
return m_state;
}
void QGstreamerCameraControl::updateStatus()
{
QCamera::Status oldStatus = m_status;
switch (m_state) {
case QCamera::UnloadedState:
m_status = QCamera::UnloadedStatus;
break;
case QCamera::LoadedState:
m_status = QCamera::LoadedStatus;
break;
case QCamera::ActiveState:
if (m_session->state() == QGstreamerCaptureSession::StoppedState)
m_status = QCamera::StartingStatus;
else
m_status = QCamera::ActiveStatus;
break;
}
if (oldStatus != m_status) {
//qDebug() << "Status changed:" << m_status;
emit statusChanged(m_status);
}
}
void QGstreamerCameraControl::reloadLater()
{
//qDebug() << "reload pipeline requested";
if (!m_reloadPending && m_state == QCamera::ActiveState) {
m_reloadPending = true;
m_session->setState(QGstreamerCaptureSession::StoppedState);
QMetaObject::invokeMethod(this, "reloadPipeline", Qt::QueuedConnection);
}
}
void QGstreamerCameraControl::reloadPipeline()
{
//qDebug() << "reload pipeline";
if (m_reloadPending) {
m_reloadPending = false;
if (m_state == QCamera::ActiveState && m_session->isReady()) {
m_session->setState(QGstreamerCaptureSession::PreviewState);
}
}
}
bool QGstreamerCameraControl::canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const
{
Q_UNUSED(status);
switch (changeType) {
case QCameraControl::CaptureMode:
case QCameraControl::ImageEncodingSettings:
case QCameraControl::VideoEncodingSettings:
case QCameraControl::Viewfinder:
return true;
default:
return false;
}
}

View File

@@ -0,0 +1,98 @@
/****************************************************************************
**
** Copyright (C) 2009 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 QGSTREAMERCAMERACONTROL_H
#define QGSTREAMERCAMERACONTROL_H
#include <QHash>
#include <qcameracontrol.h>
#include "qgstreamercapturesession.h"
QT_USE_NAMESPACE
QT_USE_NAMESPACE
class QGstreamerCameraControl : public QCameraControl
{
Q_OBJECT
public:
QGstreamerCameraControl( QGstreamerCaptureSession *session );
virtual ~QGstreamerCameraControl();
bool isValid() const { return true; }
QCamera::State state() const;
void setState(QCamera::State state);
QCamera::Status status() const { return m_status; }
QCamera::CaptureMode captureMode() const { return m_captureMode; }
void setCaptureMode(QCamera::CaptureMode mode);
bool isCaptureModeSupported(QCamera::CaptureMode mode) const
{
return mode == QCamera::CaptureStillImage || mode == QCamera::CaptureVideo;
}
QCamera::LockTypes supportedLocks() const
{
return QCamera::NoLock;
}
bool canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const;
public slots:
void reloadLater();
private slots:
void updateStatus();
void reloadPipeline();
private:
QCamera::CaptureMode m_captureMode;
QGstreamerCaptureSession *m_session;
QCamera::State m_state;
QCamera::Status m_status;
bool m_reloadPending;
};
#endif // QGSTREAMERCAMERACONTROL_H

View File

@@ -0,0 +1,198 @@
/****************************************************************************
**
** 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 "qgstreamercapturemetadatacontrol.h"
#include <gst/gst.h>
#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, 0 },
//{ 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, 0 },
//{ QtMultimediaKit::PixelAspectRatio, 0 },
// 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 }
};
QGstreamerCaptureMetaDataControl::QGstreamerCaptureMetaDataControl(QObject *parent)
:QMetaDataWriterControl(parent)
{
}
QVariant QGstreamerCaptureMetaDataControl::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) {
const char *name = qt_gstreamerMetaDataKeys[i].token;
return m_values.value(QByteArray::fromRawData(name, qstrlen(name)));
}
}
return QVariant();
}
void QGstreamerCaptureMetaDataControl::setMetaData(QtMultimediaKit::MetaData key, const QVariant &value)
{
static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup);
for (int i = 0; i < count; ++i) {
if (qt_gstreamerMetaDataKeys[i].key == key) {
const char *name = qt_gstreamerMetaDataKeys[i].token;
m_values.insert(QByteArray::fromRawData(name, qstrlen(name)), value);
emit QMetaDataWriterControl::metaDataChanged();
emit metaDataChanged(m_values);
return;
}
}
}
QList<QtMultimediaKit::MetaData> QGstreamerCaptureMetaDataControl::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_values.keys()) {
QtMultimediaKit::MetaData tag = keysMap.value(key, QtMultimediaKit::MetaData(-1));
if (tag != -1)
res.append(tag);
}
return res;
}
QVariant QGstreamerCaptureMetaDataControl::extendedMetaData(QString const &name) const
{
return m_values.value(name.toLatin1());
}
void QGstreamerCaptureMetaDataControl::setExtendedMetaData(QString const &name, QVariant const &value)
{
m_values.insert(name.toLatin1(), value);
emit QMetaDataWriterControl::metaDataChanged();
emit metaDataChanged(m_values);
}
QStringList QGstreamerCaptureMetaDataControl::availableExtendedMetaData() const
{
QStringList res;
foreach (const QByteArray &key, m_values.keys())
res.append(QString(key));
return res;
}

View File

@@ -0,0 +1,75 @@
/****************************************************************************
**
** 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 QGSTREAMERCAPTUREMETADATACONTROL_H
#define QGSTREAMERCAPTUREMETADATACONTROL_H
#include <qmetadatawritercontrol.h>
QT_USE_NAMESPACE
class QGstreamerCaptureMetaDataControl : public QMetaDataWriterControl
{
Q_OBJECT
public:
QGstreamerCaptureMetaDataControl(QObject *parent);
virtual ~QGstreamerCaptureMetaDataControl() {};
bool isMetaDataAvailable() const { return true; }
bool isWritable() const { return true; }
QVariant metaData(QtMultimediaKit::MetaData key) const;
void setMetaData(QtMultimediaKit::MetaData key, const QVariant &value);
QList<QtMultimediaKit::MetaData> availableMetaData() const;
QVariant extendedMetaData(QString const &name) const;
void setExtendedMetaData(QString const &name, QVariant const &value);
QStringList availableExtendedMetaData() const;
Q_SIGNALS:
void metaDataChanged(const QMap<QByteArray, QVariant>&);
private:
QMap<QByteArray, QVariant> m_values;
};
#endif // QGSTREAMERCAPTUREMETADATACONTROL_H

View File

@@ -0,0 +1,185 @@
/****************************************************************************
**
** 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 "qgstreamercaptureservice.h"
#include "qgstreamercapturesession.h"
#include "qgstreamerrecordercontrol.h"
#include "qgstreamermediacontainercontrol.h"
#include "qgstreameraudioencode.h"
#include "qgstreamervideoencode.h"
#include "qgstreamerimageencode.h"
#include "qgstreamerbushelper.h"
#include "qgstreamercameracontrol.h"
#include "qgstreamerv4l2input.h"
#include "qgstreamercapturemetadatacontrol.h"
#include "qgstreameraudioinputendpointselector.h"
#include "qgstreamervideoinputdevicecontrol.h"
#include "qgstreamerimagecapturecontrol.h"
#include "qgstreamervideooverlay.h"
#include "qgstreamervideorenderer.h"
#include "qgstreamervideowidget.h"
#include <qmediaserviceprovider.h>
QGstreamerCaptureService::QGstreamerCaptureService(const QString &service, QObject *parent):
QMediaService(parent)
{
m_captureSession = 0;
m_cameraControl = 0;
m_metaDataControl = 0;
m_videoInput = 0;
m_audioInputEndpointSelector = 0;
m_videoInputDevice = 0;
m_videoOutput = 0;
m_videoRenderer = 0;
m_videoWindow = 0;
m_videoWidgetControl = 0;
m_imageCaptureControl = 0;
if (service == Q_MEDIASERVICE_AUDIOSOURCE) {
m_captureSession = new QGstreamerCaptureSession(QGstreamerCaptureSession::Audio, this);
}
if (service == Q_MEDIASERVICE_CAMERA) {
m_captureSession = new QGstreamerCaptureSession(QGstreamerCaptureSession::AudioAndVideo, this);
m_cameraControl = new QGstreamerCameraControl(m_captureSession);
m_videoInput = new QGstreamerV4L2Input(this);
m_captureSession->setVideoInput(m_videoInput);
m_videoInputDevice = new QGstreamerVideoInputDeviceControl(this);
connect(m_videoInputDevice, SIGNAL(selectedDeviceChanged(QString)),
m_videoInput, SLOT(setDevice(QString)));
if (m_videoInputDevice->deviceCount())
m_videoInput->setDevice(m_videoInputDevice->deviceName(m_videoInputDevice->selectedDevice()));
m_videoRenderer = new QGstreamerVideoRenderer(this);
#if defined(Q_WS_X11) && !defined(QT_NO_XVIDEO)
m_videoWindow = new QGstreamerVideoOverlay(this);
m_videoWidgetControl = new QGstreamerVideoWidgetControl(this);
#endif
m_imageCaptureControl = new QGstreamerImageCaptureControl(m_captureSession);
}
m_audioInputEndpointSelector = new QGstreamerAudioInputEndpointSelector(this);
connect(m_audioInputEndpointSelector, SIGNAL(activeEndpointChanged(QString)), m_captureSession, SLOT(setCaptureDevice(QString)));
if (m_captureSession && m_audioInputEndpointSelector->availableEndpoints().size() > 0)
m_captureSession->setCaptureDevice(m_audioInputEndpointSelector->defaultEndpoint());
m_metaDataControl = new QGstreamerCaptureMetaDataControl(this);
connect(m_metaDataControl, SIGNAL(metaDataChanged(QMap<QByteArray,QVariant>)),
m_captureSession, SLOT(setMetaData(QMap<QByteArray,QVariant>)));
}
QGstreamerCaptureService::~QGstreamerCaptureService()
{
}
QMediaControl *QGstreamerCaptureService::requestControl(const char *name)
{
if (!m_captureSession)
return 0;
if (qstrcmp(name,QAudioEndpointSelector_iid) == 0)
return m_audioInputEndpointSelector;
if (qstrcmp(name,QVideoDeviceControl_iid) == 0)
return m_videoInputDevice;
if (qstrcmp(name,QMediaRecorderControl_iid) == 0)
return m_captureSession->recorderControl();
if (qstrcmp(name,QAudioEncoderControl_iid) == 0)
return m_captureSession->audioEncodeControl();
if (qstrcmp(name,QVideoEncoderControl_iid) == 0)
return m_captureSession->videoEncodeControl();
if (qstrcmp(name,QImageEncoderControl_iid) == 0)
return m_captureSession->imageEncodeControl();
if (qstrcmp(name,QMediaContainerControl_iid) == 0)
return m_captureSession->mediaContainerControl();
if (qstrcmp(name,QCameraControl_iid) == 0)
return m_cameraControl;
if (qstrcmp(name,QMetaDataWriterControl_iid) == 0)
return m_metaDataControl;
if (qstrcmp(name, QCameraImageCaptureControl_iid) == 0)
return m_imageCaptureControl;
if (!m_videoOutput) {
if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
m_videoOutput = m_videoRenderer;
m_captureSession->setVideoPreview(m_videoRenderer);
} else if (qstrcmp(name, QVideoWindowControl_iid) == 0) {
m_videoOutput = m_videoWindow;
m_captureSession->setVideoPreview(m_videoWindow);
} else if (qstrcmp(name, QVideoWidgetControl_iid) == 0) {
m_captureSession->setVideoPreview(m_videoWidgetControl);
m_videoOutput = m_videoWidgetControl;
}
if (m_videoOutput)
return m_videoOutput;
}
return 0;
}
void QGstreamerCaptureService::releaseControl(QMediaControl *control)
{
if (control && control == m_videoOutput) {
m_videoOutput = 0;
m_captureSession->setVideoPreview(0);
}
}

View File

@@ -0,0 +1,96 @@
/****************************************************************************
**
** 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 QGSTREAMERCAPTURESERVICE_H
#define QGSTREAMERCAPTURESERVICE_H
#include <qmediaservice.h>
#include <qmediacontrol.h>
#include <gst/gst.h>
QT_BEGIN_NAMESPACE
class QAudioEndpointSelector;
class QVideoDeviceControl;
QT_END_NAMESPACE
class QGstreamerCaptureSession;
class QGstreamerCameraControl;
class QGstreamerMessage;
class QGstreamerBusHelper;
class QGstreamerVideoRenderer;
class QGstreamerVideoOverlay;
class QGstreamerVideoWidgetControl;
class QGstreamerElementFactory;
class QGstreamerCaptureMetaDataControl;
class QGstreamerImageCaptureControl;
class QGstreamerV4L2Input;
class QGstreamerCaptureService : public QMediaService
{
Q_OBJECT
public:
QGstreamerCaptureService(const QString &service, QObject *parent = 0);
virtual ~QGstreamerCaptureService();
QMediaControl *requestControl(const char *name);
void releaseControl(QMediaControl *);
private:
void setAudioPreview(GstElement*);
QGstreamerCaptureSession *m_captureSession;
QGstreamerCameraControl *m_cameraControl;
QGstreamerV4L2Input *m_videoInput;
QGstreamerCaptureMetaDataControl *m_metaDataControl;
QAudioEndpointSelector *m_audioInputEndpointSelector;
QVideoDeviceControl *m_videoInputDevice;
QMediaControl *m_videoOutput;
QGstreamerVideoRenderer *m_videoRenderer;
QMediaControl *m_videoWindow;
QMediaControl *m_videoWidgetControl;
QGstreamerImageCaptureControl *m_imageCaptureControl;
};
#endif // QGSTREAMERCAPTURESERVICE_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,211 @@
/****************************************************************************
**
** 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 QGSTREAMERCAPTURESESSION_H
#define QGSTREAMERCAPTURESESSION_H
#include <qmediarecordercontrol.h>
#include <qmediarecorder.h>
#include <QtCore/qurl.h>
#include <gst/gst.h>
#include "qgstreamerbushelper.h"
QT_USE_NAMESPACE
class QGstreamerMessage;
class QGstreamerBusHelper;
class QGstreamerAudioEncode;
class QGstreamerVideoEncode;
class QGstreamerImageEncode;
class QGstreamerRecorderControl;
class QGstreamerMediaContainerControl;
class QGstreamerVideoRendererInterface;
class QGstreamerElementFactory
{
public:
virtual GstElement *buildElement() = 0;
virtual void prepareWinId() {}
};
class QGstreamerVideoInput : public QGstreamerElementFactory
{
public:
virtual QList<qreal> supportedFrameRates(const QSize &frameSize = QSize()) const = 0;
virtual QList<QSize> supportedResolutions(qreal frameRate = -1) const = 0;
};
class QGstreamerCaptureSession : public QObject, public QGstreamerSyncEventFilter
{
Q_OBJECT
Q_PROPERTY(qint64 duration READ duration NOTIFY durationChanged)
Q_ENUMS(State)
Q_ENUMS(CaptureMode)
public:
enum CaptureMode { Audio = 1, Video = 2, Image=4, AudioAndVideo = Audio | Video };
enum State { StoppedState, PreviewState, PausedState, RecordingState };
QGstreamerCaptureSession(CaptureMode captureMode, QObject *parent);
~QGstreamerCaptureSession();
CaptureMode captureMode() const { return m_captureMode; }
void setCaptureMode(CaptureMode);
QUrl outputLocation() const;
bool setOutputLocation(const QUrl& sink);
QGstreamerAudioEncode *audioEncodeControl() const { return m_audioEncodeControl; }
QGstreamerVideoEncode *videoEncodeControl() const { return m_videoEncodeControl; }
QGstreamerImageEncode *imageEncodeControl() const { return m_imageEncodeControl; }
QGstreamerRecorderControl *recorderControl() const { return m_recorderControl; }
QGstreamerMediaContainerControl *mediaContainerControl() const { return m_mediaContainerControl; }
QGstreamerElementFactory *audioInput() const { return m_audioInputFactory; }
void setAudioInput(QGstreamerElementFactory *audioInput);
QGstreamerElementFactory *audioPreview() const { return m_audioPreviewFactory; }
void setAudioPreview(QGstreamerElementFactory *audioPreview);
QGstreamerVideoInput *videoInput() const { return m_videoInputFactory; }
void setVideoInput(QGstreamerVideoInput *videoInput);
QObject *videoPreview() const { return m_viewfinder; }
void setVideoPreview(QObject *viewfinder);
void captureImage(int requestId, const QString &fileName);
State state() const;
qint64 duration() const;
bool isMuted() const { return m_muted; }
bool isReady() const;
bool processSyncMessage(const QGstreamerMessage &message);
signals:
void stateChanged(QGstreamerCaptureSession::State state);
void durationChanged(qint64 duration);
void error(int error, const QString &errorString);
void imageExposed(int requestId);
void imageCaptured(int requestId, const QImage &img);
void imageSaved(int requestId, const QString &path);
void mutedChanged(bool);
void readyChanged(bool);
void viewfinderChanged();
public slots:
void setState(QGstreamerCaptureSession::State);
void setCaptureDevice(const QString &deviceName);
void dumpGraph(const QString &fileName);
void setMetaData(const QMap<QByteArray, QVariant>&);
void setMuted(bool);
private slots:
void busMessage(const QGstreamerMessage &message);
private:
enum PipelineMode { EmptyPipeline, PreviewPipeline, RecordingPipeline, PreviewAndRecordingPipeline };
GstElement *buildEncodeBin();
GstElement *buildAudioSrc();
GstElement *buildAudioPreview();
GstElement *buildVideoSrc();
GstElement *buildVideoPreview();
GstElement *buildImageCapture();
void waitForStopped();
bool rebuildGraph(QGstreamerCaptureSession::PipelineMode newMode);
QUrl m_sink;
QString m_captureDevice;
State m_state;
State m_pendingState;
bool m_waitingForEos;
PipelineMode m_pipelineMode;
QGstreamerCaptureSession::CaptureMode m_captureMode;
QMap<QByteArray, QVariant> m_metaData;
QGstreamerElementFactory *m_audioInputFactory;
QGstreamerElementFactory *m_audioPreviewFactory;
QGstreamerVideoInput *m_videoInputFactory;
QObject *m_viewfinder;
QGstreamerVideoRendererInterface *m_viewfinderInterface;
QGstreamerAudioEncode *m_audioEncodeControl;
QGstreamerVideoEncode *m_videoEncodeControl;
QGstreamerImageEncode *m_imageEncodeControl;
QGstreamerRecorderControl *m_recorderControl;
QGstreamerMediaContainerControl *m_mediaContainerControl;
QGstreamerBusHelper *m_busHelper;
GstBus* m_bus;
GstElement *m_pipeline;
GstElement *m_audioSrc;
GstElement *m_audioTee;
GstElement *m_audioPreviewQueue;
GstElement *m_audioPreview;
GstElement *m_audioVolume;
bool m_muted;
GstElement *m_videoSrc;
GstElement *m_videoTee;
GstElement *m_videoPreviewQueue;
GstElement *m_videoPreview;
GstElement *m_imageCaptureBin;
GstElement *m_encodeBin;
public:
bool m_passImage;
bool m_passPrerollImage;
QString m_imageFileName;
int m_imageRequestId;
};
#endif // QGSTREAMERCAPTURESESSION_H

View File

@@ -0,0 +1,98 @@
/****************************************************************************
**
** Copyright (C) 2009 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 "qgstreamerimagecapturecontrol.h"
#include <QtCore/QDebug>
#include <QtCore/QDir>
QGstreamerImageCaptureControl::QGstreamerImageCaptureControl(QGstreamerCaptureSession *session)
:QCameraImageCaptureControl(session), m_session(session), m_ready(false), m_lastId(0)
{
connect(m_session, SIGNAL(stateChanged(QGstreamerCaptureSession::State)), SLOT(updateState()));
connect(m_session, SIGNAL(imageExposed(int)), this, SIGNAL(imageExposed(int)));
connect(m_session, SIGNAL(imageCaptured(int,QImage)), this, SIGNAL(imageCaptured(int,QImage)));
connect(m_session, SIGNAL(imageSaved(int,QString)), this, SIGNAL(imageSaved(int,QString)));
}
QGstreamerImageCaptureControl::~QGstreamerImageCaptureControl()
{
}
bool QGstreamerImageCaptureControl::isReadyForCapture() const
{
return m_ready;
}
int QGstreamerImageCaptureControl::capture(const QString &fileName)
{
QString path = fileName;
if (path.isEmpty()) {
int lastImage = 0;
QDir outputDir = QDir::currentPath();
foreach(QString fileName, outputDir.entryList(QStringList() << "img_*.jpg")) {
int imgNumber = fileName.mid(4, fileName.size()-8).toInt();
lastImage = qMax(lastImage, imgNumber);
}
path = QString("img_%1.jpg").arg(lastImage+1,
4, //fieldWidth
10,
QLatin1Char('0'));
}
m_lastId++;
m_session->captureImage(m_lastId, path);
return m_lastId;
}
void QGstreamerImageCaptureControl::cancelCapture()
{
}
void QGstreamerImageCaptureControl::updateState()
{
bool ready = m_session->state() == QGstreamerCaptureSession::PreviewState;
if (m_ready != ready) {
emit readyForCaptureChanged(m_ready = ready);
}
}

View File

@@ -0,0 +1,73 @@
/****************************************************************************
**
** Copyright (C) 2009 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 QGSTREAMERIMAGECAPTURECONTROL_H
#define QGSTREAMERIMAGECAPTURECONTROL_H
#include <qcameraimagecapturecontrol.h>
#include "qgstreamercapturesession.h"
QT_USE_NAMESPACE
class QGstreamerImageCaptureControl : public QCameraImageCaptureControl
{
Q_OBJECT
public:
QGstreamerImageCaptureControl(QGstreamerCaptureSession *session);
virtual ~QGstreamerImageCaptureControl();
QCameraImageCapture::DriveMode driveMode() const { return QCameraImageCapture::SingleImageCapture; }
void setDriveMode(QCameraImageCapture::DriveMode) {}
bool isReadyForCapture() const;
int capture(const QString &fileName);
void cancelCapture();
private slots:
void updateState();
private:
QGstreamerCaptureSession *m_session;
bool m_ready;
int m_lastId;
};
#endif // QGSTREAMERCAPTURECORNTROL_H

View File

@@ -0,0 +1,90 @@
/****************************************************************************
**
** Copyright (C) 2009 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 "qgstreamerimageencode.h"
#include "qgstreamercapturesession.h"
#include <QtCore/qdebug.h>
#include <math.h>
QGstreamerImageEncode::QGstreamerImageEncode(QGstreamerCaptureSession *session)
:QImageEncoderControl(session), m_session(session)
{
}
QGstreamerImageEncode::~QGstreamerImageEncode()
{
}
QList<QSize> QGstreamerImageEncode::supportedResolutions(const QImageEncoderSettings &, bool *continuous) const
{
if (continuous)
*continuous = m_session->videoInput() != 0;
return m_session->videoInput() ? m_session->videoInput()->supportedResolutions() : QList<QSize>();
}
QStringList QGstreamerImageEncode::supportedImageCodecs() const
{
return QStringList() << "jpeg";
}
QString QGstreamerImageEncode::imageCodecDescription(const QString &codecName) const
{
if (codecName == "jpeg")
return tr("JPEG image encoder");
return QString();
}
QImageEncoderSettings QGstreamerImageEncode::imageSettings() const
{
return m_settings;
}
void QGstreamerImageEncode::setImageSettings(const QImageEncoderSettings &settings)
{
if (m_settings != settings) {
m_settings = settings;
emit settingsChanged();
}
}

View File

@@ -0,0 +1,80 @@
/****************************************************************************
**
** Copyright (C) 2009 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 QGSTREAMERIMAGEENCODE_H
#define QGSTREAMERIMAGEENCODE_H
class QGstreamerCaptureSession;
#include <qimageencodercontrol.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qmap.h>
#include <gst/gst.h>
QT_USE_NAMESPACE
class QGstreamerImageEncode : public QImageEncoderControl
{
Q_OBJECT
public:
QGstreamerImageEncode(QGstreamerCaptureSession *session);
virtual ~QGstreamerImageEncode();
QList<QSize> supportedResolutions(const QImageEncoderSettings &settings = QImageEncoderSettings(),
bool *continuous = 0) const;
QStringList supportedImageCodecs() const;
QString imageCodecDescription(const QString &codecName) const;
QImageEncoderSettings imageSettings() const;
void setImageSettings(const QImageEncoderSettings &settings);
Q_SIGNALS:
void settingsChanged();
private:
QImageEncoderSettings m_settings;
QGstreamerCaptureSession *m_session;
};
#endif

View File

@@ -0,0 +1,135 @@
/****************************************************************************
**
** 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 "qgstreamermediacontainercontrol.h"
#include <QtCore/qdebug.h>
QGstreamerMediaContainerControl::QGstreamerMediaContainerControl(QObject *parent)
:QMediaContainerControl(parent)
{
QList<QByteArray> formatCandidates;
formatCandidates << "matroska" << "ogg" << "mp4" << "wav" << "quicktime" << "avi" << "3gpp";
formatCandidates << "flv" << "amr" << "asf" << "dv" << "gif";
formatCandidates << "mpeg" << "vob" << "mpegts" << "3g2" << "3gp";
formatCandidates << "raw";
m_elementNames["matroska"] = "matroskamux";
m_elementNames["ogg"] = "oggmux";
m_elementNames["mp4"] = "ffmux_mp4";
m_elementNames["quicktime"] = "ffmux_mov";
m_elementNames["avi"] = "avimux";
m_elementNames["3gpp"] = "gppmux";
m_elementNames["flv"] = "flvmux";
m_elementNames["wav"] = "wavenc";
m_elementNames["amr"] = "ffmux_amr";
m_elementNames["asf"] = "ffmux_asf";
m_elementNames["dv"] = "ffmux_dv";
m_elementNames["gif"] = "ffmux_gif";
m_elementNames["mpeg"] = "ffmux_mpeg";
m_elementNames["vob"] = "ffmux_vob";
m_elementNames["mpegts"] = "ffmux_mpegts";
m_elementNames["3g2"] = "ffmux_3g2";
m_elementNames["3gp"] = "ffmux_3gp";
m_elementNames["raw"] = "identity";
m_containerExtensions["matroska"] = "mkv";
m_containerExtensions["quicktime"] = "mov";
m_containerExtensions["mpegts"] = "m2t";
m_containerExtensions["mpeg"] = "mpg";
QSet<QString> allTypes;
foreach( const QByteArray& formatName, formatCandidates ) {
QByteArray elementName = m_elementNames[formatName];
GstElementFactory *factory = gst_element_factory_find(elementName.constData());
if (factory) {
m_supportedContainers.append(formatName);
const gchar *descr = gst_element_factory_get_description(factory);
m_containerDescriptions.insert(formatName, QString::fromUtf8(descr));
if (formatName == QByteArray("raw")) {
m_streamTypes.insert(formatName, allTypes);
} else {
QSet<QString> types = supportedStreamTypes(factory, GST_PAD_SINK);
m_streamTypes.insert(formatName, types);
allTypes.unite(types);
}
gst_object_unref(GST_OBJECT(factory));
}
}
//if (!m_supportedContainers.isEmpty())
// setContainerMimeType(m_supportedContainers[0]);
}
QSet<QString> QGstreamerMediaContainerControl::supportedStreamTypes(GstElementFactory *factory, GstPadDirection direction)
{
QSet<QString> types;
const GList *pads = gst_element_factory_get_static_pad_templates(factory);
for (const GList *pad = pads; pad; pad = g_list_next(pad)) {
GstStaticPadTemplate *templ = (GstStaticPadTemplate*)pad->data;
if (templ->direction == direction) {
GstCaps *caps = gst_static_caps_get(&templ->static_caps);
for (uint i=0; i<gst_caps_get_size(caps); i++) {
GstStructure *structure = gst_caps_get_structure(caps, i);
types.insert( QString::fromUtf8(gst_structure_get_name(structure)) );
}
gst_caps_unref(caps);
}
}
return types;
}
QSet<QString> QGstreamerMediaContainerControl::supportedStreamTypes(const QString &container) const
{
return m_streamTypes.value(container);
}
QString QGstreamerMediaContainerControl::containerExtension() const
{
return m_containerExtensions.value(m_format, m_format);
}

View File

@@ -0,0 +1,84 @@
/****************************************************************************
**
** 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 QGSTREAMERMEDIACONTAINERCONTROL_H
#define QGSTREAMERMEDIACONTAINERCONTROL_H
#include <qmediacontainercontrol.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qset.h>
#include <gst/gst.h>
QT_USE_NAMESPACE
class QGstreamerMediaContainerControl : public QMediaContainerControl
{
Q_OBJECT
public:
QGstreamerMediaContainerControl(QObject *parent);
virtual ~QGstreamerMediaContainerControl() {};
virtual QStringList supportedContainers() const { return m_supportedContainers; }
virtual QString containerMimeType() const { return m_format; }
virtual void setContainerMimeType(const QString &formatMimeType) { m_format = formatMimeType; }
virtual QString containerDescription(const QString &formatMimeType) const { return m_containerDescriptions.value(formatMimeType); }
QByteArray formatElementName() const { return m_elementNames.value(containerMimeType()); }
QSet<QString> supportedStreamTypes(const QString &container) const;
static QSet<QString> supportedStreamTypes(GstElementFactory *factory, GstPadDirection direction);
QString containerExtension() const;
private:
QString m_format;
QStringList m_supportedContainers;
QMap<QString,QByteArray> m_elementNames;
QMap<QString, QString> m_containerDescriptions;
QMap<QString, QString> m_containerExtensions;
QMap<QString, QSet<QString> > m_streamTypes;
};
#endif // QGSTREAMERMEDIACONTAINERCONTROL_H

View File

@@ -0,0 +1,289 @@
/****************************************************************************
**
** 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 "qgstreamerrecordercontrol.h"
#include "qgstreameraudioencode.h"
#include "qgstreamervideoencode.h"
#include "qgstreamermediacontainercontrol.h"
#include <QtCore/QDebug>
QGstreamerRecorderControl::QGstreamerRecorderControl(QGstreamerCaptureSession *session)
:QMediaRecorderControl(session), m_session(session), m_state(QMediaRecorder::StoppedState)
{
connect(m_session, SIGNAL(stateChanged(QGstreamerCaptureSession::State)), SLOT(updateState()));
connect(m_session, SIGNAL(error(int,QString)), SIGNAL(error(int,QString)));
connect(m_session, SIGNAL(durationChanged(qint64)), SIGNAL(durationChanged(qint64)));
connect(m_session, SIGNAL(mutedChanged(bool)), SIGNAL(mutedChanged(bool)));
m_hasPreviewState = m_session->captureMode() != QGstreamerCaptureSession::Audio;
}
QGstreamerRecorderControl::~QGstreamerRecorderControl()
{
}
QUrl QGstreamerRecorderControl::outputLocation() const
{
return m_session->outputLocation();
}
bool QGstreamerRecorderControl::setOutputLocation(const QUrl &sink)
{
m_outputLocation = sink;
m_session->setOutputLocation(sink);
return true;
}
QMediaRecorder::State QGstreamerRecorderControl::state() const
{
switch ( m_session->state() ) {
case QGstreamerCaptureSession::RecordingState:
return QMediaRecorder::RecordingState;
case QGstreamerCaptureSession::PausedState:
return QMediaRecorder::PausedState;
case QGstreamerCaptureSession::PreviewState:
case QGstreamerCaptureSession::StoppedState:
return QMediaRecorder::StoppedState;
}
return QMediaRecorder::StoppedState;
}
void QGstreamerRecorderControl::updateState()
{
QMediaRecorder::State newState = state();
if (m_state != newState) {
m_state = newState;
emit stateChanged(m_state);
}
}
qint64 QGstreamerRecorderControl::duration() const
{
return m_session->duration();
}
void QGstreamerRecorderControl::record()
{
if (m_outputLocation.isEmpty()) {
QString container = m_session->mediaContainerControl()->containerExtension();
if (container.isEmpty())
container = "raw";
m_session->setOutputLocation(QUrl(generateFileName(defaultDir(), container)));
}
m_session->dumpGraph("before-record");
if (!m_hasPreviewState || m_session->state() != QGstreamerCaptureSession::StoppedState) {
m_session->setState(QGstreamerCaptureSession::RecordingState);
} else
emit error(QMediaRecorder::ResourceError, tr("Service has not been started"));
m_session->dumpGraph("after-record");
}
void QGstreamerRecorderControl::pause()
{
m_session->dumpGraph("before-pause");
if (!m_hasPreviewState || m_session->state() != QGstreamerCaptureSession::StoppedState) {
m_session->setState(QGstreamerCaptureSession::PausedState);
} else
emit error(QMediaRecorder::ResourceError, tr("Service has not been started"));
}
void QGstreamerRecorderControl::stop()
{
if (!m_hasPreviewState) {
m_session->setState(QGstreamerCaptureSession::StoppedState);
} else {
if (m_session->state() != QGstreamerCaptureSession::StoppedState)
m_session->setState(QGstreamerCaptureSession::PreviewState);
}
}
void QGstreamerRecorderControl::applySettings()
{
//Check the codecs are compatible with container,
//and choose the compatible codecs/container if omitted
QGstreamerAudioEncode *audioEncodeControl = m_session->audioEncodeControl();
QGstreamerVideoEncode *videoEncodeControl = m_session->videoEncodeControl();
QGstreamerMediaContainerControl *mediaContainerControl = m_session->mediaContainerControl();
bool needAudio = m_session->captureMode() & QGstreamerCaptureSession::Audio;
bool needVideo = m_session->captureMode() & QGstreamerCaptureSession::Video;
QStringList containerCandidates;
if (mediaContainerControl->containerMimeType().isEmpty())
containerCandidates = mediaContainerControl->supportedContainers();
else
containerCandidates << mediaContainerControl->containerMimeType();
QStringList audioCandidates;
if (needAudio) {
QAudioEncoderSettings audioSettings = audioEncodeControl->audioSettings();
if (audioSettings.codec().isEmpty())
audioCandidates = audioEncodeControl->supportedAudioCodecs();
else
audioCandidates << audioSettings.codec();
}
QStringList videoCandidates;
if (needVideo) {
QVideoEncoderSettings videoSettings = videoEncodeControl->videoSettings();
if (videoSettings.codec().isEmpty())
videoCandidates = videoEncodeControl->supportedVideoCodecs();
else
videoCandidates << videoSettings.codec();
}
QString container;
QString audioCodec;
QString videoCodec;
foreach (const QString &containerCandidate, containerCandidates) {
QSet<QString> supportedTypes = mediaContainerControl->supportedStreamTypes(containerCandidate);
audioCodec.clear();
videoCodec.clear();
if (needAudio) {
bool found = false;
foreach (const QString &audioCandidate, audioCandidates) {
QSet<QString> audioTypes = audioEncodeControl->supportedStreamTypes(audioCandidate);
if (!audioTypes.intersect(supportedTypes).isEmpty()) {
found = true;
audioCodec = audioCandidate;
break;
}
}
if (!found)
continue;
}
if (needVideo) {
bool found = false;
foreach (const QString &videoCandidate, videoCandidates) {
QSet<QString> videoTypes = videoEncodeControl->supportedStreamTypes(videoCandidate);
if (!videoTypes.intersect(supportedTypes).isEmpty()) {
found = true;
videoCodec = videoCandidate;
break;
}
}
if (!found)
continue;
}
container = containerCandidate;
break;
}
if (container.isEmpty()) {
emit error(QMediaRecorder::FormatError, tr("Not compatible codecs and container format."));
} else {
mediaContainerControl->setContainerMimeType(container);
if (needAudio) {
QAudioEncoderSettings audioSettings = audioEncodeControl->audioSettings();
audioSettings.setCodec(audioCodec);
audioEncodeControl->setAudioSettings(audioSettings);
}
if (needVideo) {
QVideoEncoderSettings videoSettings = videoEncodeControl->videoSettings();
videoSettings.setCodec(videoCodec);
videoEncodeControl->setVideoSettings(videoSettings);
}
}
}
bool QGstreamerRecorderControl::isMuted() const
{
return m_session->isMuted();
}
void QGstreamerRecorderControl::setMuted(bool muted)
{
m_session->setMuted(muted);
}
QDir QGstreamerRecorderControl::defaultDir() const
{
QStringList dirCandidates;
#if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
dirCandidates << QLatin1String("/home/user/MyDocs");
#endif
dirCandidates << QDir::home().filePath("Documents");
dirCandidates << QDir::home().filePath("My Documents");
dirCandidates << QDir::homePath();
dirCandidates << QDir::currentPath();
dirCandidates << QDir::tempPath();
foreach (const QString &path, dirCandidates) {
QDir dir(path);
if (dir.exists() && QFileInfo(path).isWritable())
return dir;
}
return QDir();
}
QString QGstreamerRecorderControl::generateFileName(const QDir &dir, const QString &ext) const
{
int lastClip = 0;
foreach(QString fileName, dir.entryList(QStringList() << QString("clip_*.%1").arg(ext))) {
int imgNumber = fileName.mid(5, fileName.size()-6-ext.length()).toInt();
lastClip = qMax(lastClip, imgNumber);
}
QString name = QString("clip_%1.%2").arg(lastClip+1,
4, //fieldWidth
10,
QLatin1Char('0')).arg(ext);
return dir.absoluteFilePath(name);
}

View File

@@ -0,0 +1,91 @@
/****************************************************************************
**
** 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 QGSTREAMERRECORDERCONTROL_H
#define QGSTREAMERRECORDERCONTROL_H
#include <QtCore/QDir>
#include <qmediarecordercontrol.h>
#include "qgstreamercapturesession.h"
QT_USE_NAMESPACE
class QGstreamerRecorderControl : public QMediaRecorderControl
{
Q_OBJECT
public:
QGstreamerRecorderControl(QGstreamerCaptureSession *session);
virtual ~QGstreamerRecorderControl();
QUrl outputLocation() const;
bool setOutputLocation(const QUrl &sink);
QMediaRecorder::State state() const;
qint64 duration() const;
bool isMuted() const;
void applySettings();
public slots:
void record();
void pause();
void stop();
void setMuted(bool);
private slots:
void updateState();
private:
QDir defaultDir() const;
QString generateFileName(const QDir &dir, const QString &ext) const;
QUrl m_outputLocation;
QGstreamerCaptureSession *m_session;
QMediaRecorder::State m_state;
bool m_hasPreviewState;
};
#endif // QGSTREAMERCAPTURECORNTROL_H

View File

@@ -0,0 +1,297 @@
/****************************************************************************
**
** 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 "qgstreamerv4l2input.h"
#include <QtCore/qdebug.h>
#include <QtCore/qfile.h>
#include <linux/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
QT_BEGIN_NAMESPACE
static inline uint qHash(const QSize& key) { return uint(key.width()*256+key.height()); }
static bool operator<(const QSize &s1, const QSize s2)
{
return s1.width()*s1.height() < s2.width()*s2.height();
}
QT_END_NAMESPACE
QGstreamerV4L2Input::QGstreamerV4L2Input(QObject *parent)
:QObject(parent)
{
}
QGstreamerV4L2Input::~QGstreamerV4L2Input()
{
}
GstElement *QGstreamerV4L2Input::buildElement()
{
#ifndef Q_WS_MAEMO_5
GstElement *camera = gst_element_factory_make("v4l2src", "camera_source");
#else
GstElement *camera = gst_element_factory_make("v4l2camsrc", "camera_source");
#endif
if (camera && !m_device.isEmpty() )
g_object_set(G_OBJECT(camera), "device", m_device.constData(), NULL);
return camera;
}
void QGstreamerV4L2Input::setDevice(const QByteArray &newDevice)
{
if (m_device != newDevice) {
m_device = newDevice;
updateSupportedResolutions(newDevice);
}
}
void QGstreamerV4L2Input::setDevice(const QString &device)
{
setDevice(QFile::encodeName(device));
}
void QGstreamerV4L2Input::updateSupportedResolutions(const QByteArray &device)
{
m_frameRates.clear();
m_resolutions.clear();
m_ratesByResolution.clear();
QSet<QSize> allResolutions;
QSet<int> allFrameRates;
QFile f(device);
if (!f.open(QFile::ReadOnly))
return;
int fd = f.handle();
//get the list of formats:
QList<quint32> supportedFormats;
{
v4l2_fmtdesc fmt;
memset(&fmt, 0, sizeof(v4l2_fmtdesc));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
int sanity = 0;
for (fmt.index = 0;; fmt.index++) {
if (sanity++ > 8)
break;
if( ::ioctl(fd, VIDIOC_ENUM_FMT, &fmt) == -1) {
if(errno == EINVAL)
break;
}
supportedFormats.append(fmt.pixelformat);
}
}
QList<QSize> commonSizes;
commonSizes << QSize(128, 96)
<<QSize(160,120)
<<QSize(176, 144)
<<QSize(320, 240)
<<QSize(352, 288)
<<QSize(640, 480)
<<QSize(1024, 768)
<<QSize(1280, 1024)
<<QSize(1600, 1200)
<<QSize(1920, 1200)
<<QSize(2048, 1536)
<<QSize(2560, 1600)
<<QSize(2580, 1936);
QList<int> commonRates;
commonRates << 05*1000 << 75*1000 << 10*1000 << 15*1000 << 20*1000
<< 24*1000 << 25*1000 << 30*1000 << 50*1000 << 60*1000;
//get the list of resolutions:
foreach (quint32 format, supportedFormats) {
struct v4l2_frmsizeenum formatSize;
memset(&formatSize, 0, sizeof(formatSize));
formatSize.pixel_format = format;
QList<QSize> sizeList;
if (0) {
char formatStr[5];
memcpy(formatStr, &format, 4);
formatStr[4] = 0;
//qDebug() << "trying format" << formatStr;
}
for (int i=0;;i++) {
formatSize.index = i;
if (ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &formatSize) < 0)
break;
if (formatSize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
sizeList.append(QSize(formatSize.discrete.width, formatSize.discrete.height));
} else {
foreach (const QSize& candidate, commonSizes) {
if (candidate.width() <= (int)formatSize.stepwise.max_width &&
candidate.height() >= (int)formatSize.stepwise.min_width &&
candidate.width() % formatSize.stepwise.step_width == 0 &&
candidate.height() <= (int)formatSize.stepwise.max_height &&
candidate.height() >= (int)formatSize.stepwise.min_height &&
candidate.height() % formatSize.stepwise.step_height == 0) {
sizeList.append(candidate);
}
}
if (!sizeList.contains(QSize(formatSize.stepwise.min_width, formatSize.stepwise.min_height)))
sizeList.prepend(QSize(formatSize.stepwise.min_width, formatSize.stepwise.min_height));
if (!sizeList.contains(QSize(formatSize.stepwise.max_width, formatSize.stepwise.max_height)))
sizeList.append(QSize(formatSize.stepwise.max_width, formatSize.stepwise.max_height));
break; //stepwise values are returned only for index 0
}
}
//and frameRates for each resolution.
foreach (const QSize &s, sizeList) {
allResolutions.insert(s);
struct v4l2_frmivalenum formatInterval;
memset(&formatInterval, 0, sizeof(formatInterval));
formatInterval.pixel_format = format;
formatInterval.width = s.width();
formatInterval.height = s.height();
QList<int> frameRates; //in 1/1000 of fps
for (int i=0; ; i++) {
formatInterval.index = i;
if (ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &formatInterval) < 0)
break;
if (formatInterval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
//converts seconds to fps*1000
if (formatInterval.discrete.numerator)
frameRates.append(qRound(formatInterval.discrete.denominator*1000.0 / formatInterval.discrete.numerator));
} else {
if (formatInterval.stepwise.min.numerator == 0 ||
formatInterval.stepwise.max.numerator == 0) {
qWarning() << "received invalid frame interval";
break;
}
int minRate = qRound(formatInterval.stepwise.min.denominator*1000.0 /
formatInterval.stepwise.min.numerator);
int maxRate = qRound(formatInterval.stepwise.max.denominator*1000.0 /
formatInterval.stepwise.max.numerator);
foreach (int candidate, commonRates) {
if (candidate >= minRate && candidate <= maxRate)
frameRates.append(candidate);
}
if (!frameRates.contains(minRate))
frameRates.prepend(minRate);
if (!frameRates.contains(maxRate))
frameRates.append(maxRate);
break; //stepwise values are returned only for index 0
}
}
allFrameRates.unite(frameRates.toSet());
m_ratesByResolution[s].unite(frameRates.toSet());
}
}
f.close();
foreach(int rate, allFrameRates) {
m_frameRates.append(rate/1000.0);
}
qSort(m_frameRates);
m_resolutions = allResolutions.toList();
qSort(m_resolutions);
//qDebug() << "frame rates:" << m_frameRates;
//qDebug() << "resolutions:" << m_resolutions;
}
QList<qreal> QGstreamerV4L2Input::supportedFrameRates(const QSize &frameSize) const
{
if (frameSize.isEmpty())
return m_frameRates;
else {
QList<qreal> res;
foreach(int rate, m_ratesByResolution[frameSize]) {
res.append(rate/1000.0);
}
return res;
}
}
QList<QSize> QGstreamerV4L2Input::supportedResolutions(qreal frameRate) const
{
Q_UNUSED(frameRate);
return m_resolutions;
}

View File

@@ -0,0 +1,83 @@
/****************************************************************************
**
** 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 QGSTREAMERV4L2INPUT_H
#define QGSTREAMERV4L2INPUT_H
#include <QtCore/qhash.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qlist.h>
#include <QtCore/qsize.h>
#include "qgstreamercapturesession.h"
QT_USE_NAMESPACE
class QGstreamerV4L2Input : public QObject, public QGstreamerVideoInput
{
Q_OBJECT
public:
QGstreamerV4L2Input(QObject *parent = 0);
virtual ~QGstreamerV4L2Input();
GstElement *buildElement();
QList<qreal> supportedFrameRates(const QSize &frameSize = QSize()) const;
QList<QSize> supportedResolutions(qreal frameRate = -1) const;
QByteArray device() const;
public slots:
void setDevice(const QByteArray &device);
void setDevice(const QString &device);
private:
void updateSupportedResolutions(const QByteArray &device);
QList<qreal> m_frameRates;
QList<QSize> m_resolutions;
QHash<QSize, QSet<int> > m_ratesByResolution;
QByteArray m_device;
};
#endif // QGSTREAMERV4L2INPUT_H

View File

@@ -0,0 +1,331 @@
/****************************************************************************
**
** 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 "qgstreamervideoencode.h"
#include "qgstreamercapturesession.h"
#include "qgstreamermediacontainercontrol.h"
#include <QtCore/qdebug.h>
#include <math.h>
QGstreamerVideoEncode::QGstreamerVideoEncode(QGstreamerCaptureSession *session)
:QVideoEncoderControl(session), m_session(session)
{
QList<QByteArray> codecCandidates;
codecCandidates << "video/h264" << "video/xvid" << "video/mpeg4" << "video/mpeg1" << "video/mpeg2" << "video/theora";
m_elementNames["video/h264"] = "x264enc";
m_elementNames["video/xvid"] = "xvidenc";
m_elementNames["video/mpeg4"] = "ffenc_mpeg4";
m_elementNames["video/mpeg1"] = "ffenc_mpeg1video";
m_elementNames["video/mpeg2"] = "ffenc_mpeg2video";
m_elementNames["video/theora"] = "theoraenc";
m_codecOptions["video/h264"] = QStringList() << "quantizer";
m_codecOptions["video/xvid"] = QStringList() << "quantizer" << "profile";
m_codecOptions["video/mpeg4"] = QStringList() << "quantizer";
m_codecOptions["video/mpeg1"] = QStringList() << "quantizer";
m_codecOptions["video/mpeg2"] = QStringList() << "quantizer";
m_codecOptions["video/theora"] = QStringList();
foreach( const QByteArray& codecName, codecCandidates ) {
QByteArray elementName = m_elementNames[codecName];
GstElementFactory *factory = gst_element_factory_find(elementName.constData());
if (factory) {
m_codecs.append(codecName);
const gchar *descr = gst_element_factory_get_description(factory);
m_codecDescriptions.insert(codecName, QString::fromUtf8(descr));
m_streamTypes.insert(codecName,
QGstreamerMediaContainerControl::supportedStreamTypes(factory, GST_PAD_SRC));
gst_object_unref(GST_OBJECT(factory));
}
}
//if (!m_codecs.isEmpty())
// m_videoSettings.setCodec(m_codecs[0]);
}
QGstreamerVideoEncode::~QGstreamerVideoEncode()
{
}
QList<QSize> QGstreamerVideoEncode::supportedResolutions(const QVideoEncoderSettings &, bool *continuous) const
{
if (continuous)
*continuous = m_session->videoInput() != 0;
return m_session->videoInput() ? m_session->videoInput()->supportedResolutions() : QList<QSize>();
}
QList< qreal > QGstreamerVideoEncode::supportedFrameRates(const QVideoEncoderSettings &, bool *continuous) const
{
if (continuous)
*continuous = false;
return m_session->videoInput() ? m_session->videoInput()->supportedFrameRates() : QList<qreal>();
}
QStringList QGstreamerVideoEncode::supportedVideoCodecs() const
{
return m_codecs;
}
QString QGstreamerVideoEncode::videoCodecDescription(const QString &codecName) const
{
return m_codecDescriptions.value(codecName);
}
QStringList QGstreamerVideoEncode::supportedEncodingOptions(const QString &codec) const
{
return m_codecOptions.value(codec);
}
QVariant QGstreamerVideoEncode::encodingOption(const QString &codec, const QString &name) const
{
return m_options[codec].value(name);
}
void QGstreamerVideoEncode::setEncodingOption(
const QString &codec, const QString &name, const QVariant &value)
{
m_options[codec][name] = value;
}
QVideoEncoderSettings QGstreamerVideoEncode::videoSettings() const
{
return m_videoSettings;
}
void QGstreamerVideoEncode::setVideoSettings(const QVideoEncoderSettings &settings)
{
m_videoSettings = settings;
}
GstElement *QGstreamerVideoEncode::createEncoder()
{
QString codec = m_videoSettings.codec();
//qDebug() << "create encoder for video codec" << codec;
GstElement *encoderElement = gst_element_factory_make( m_elementNames.value(codec).constData(), "video-encoder");
if (!encoderElement)
return 0;
GstBin *encoderBin = GST_BIN(gst_bin_new("video-encoder-bin"));
GstElement *capsFilter = gst_element_factory_make("capsfilter", "capsfilter-video");
gst_bin_add(encoderBin, capsFilter);
GstElement *colorspace = gst_element_factory_make("ffmpegcolorspace", NULL);
gst_bin_add(encoderBin, colorspace);
gst_bin_add(encoderBin, encoderElement);
gst_element_link_many(capsFilter, colorspace, encoderElement, NULL);
// add ghostpads
GstPad *pad = gst_element_get_static_pad(capsFilter, "sink");
gst_element_add_pad(GST_ELEMENT(encoderBin), gst_ghost_pad_new("sink", pad));
gst_object_unref(GST_OBJECT(pad));
pad = gst_element_get_static_pad(encoderElement, "src");
gst_element_add_pad(GST_ELEMENT(encoderBin), gst_ghost_pad_new("src", pad));
gst_object_unref(GST_OBJECT(pad));
if (encoderElement) {
if (m_videoSettings.encodingMode() == QtMultimediaKit::ConstantQualityEncoding) {
QtMultimediaKit::EncodingQuality qualityValue = m_videoSettings.quality();
if (codec == QLatin1String("video/h264")) {
//constant quantizer mode
g_object_set(G_OBJECT(encoderElement), "pass", 4, NULL);
int qualityTable[] = {
50, //VeryLow
35, //Low
21, //Normal
15, //High
8 //VeryHigh
};
g_object_set(G_OBJECT(encoderElement), "quantizer", qualityTable[qualityValue], NULL);
} else if (codec == QLatin1String("video/xvid")) {
//constant quantizer mode
g_object_set(G_OBJECT(encoderElement), "pass", 3, NULL);
int qualityTable[] = {
32, //VeryLow
12, //Low
5, //Normal
3, //High
2 //VeryHigh
};
int quant = qualityTable[qualityValue];
g_object_set(G_OBJECT(encoderElement), "quantizer", quant, NULL);
} else if (codec == QLatin1String("video/mpeg4") ||
codec == QLatin1String("video/mpeg1") ||
codec == QLatin1String("video/mpeg2") ) {
//constant quantizer mode
g_object_set(G_OBJECT(encoderElement), "pass", 2, NULL);
//quant from 1 to 30, default ~3
double qualityTable[] = {
20, //VeryLow
8.0, //Low
3.0, //Normal
2.5, //High
2.0 //VeryHigh
};
double quant = qualityTable[qualityValue];
g_object_set(G_OBJECT(encoderElement), "quantizer", quant, NULL);
} else if (codec == QLatin1String("video/theora")) {
int qualityTable[] = {
8, //VeryLow
16, //Low
32, //Normal
45, //High
60 //VeryHigh
};
//quality from 0 to 63
int quality = qualityTable[qualityValue];
g_object_set(G_OBJECT(encoderElement), "quality", quality, NULL);
}
} else {
int bitrate = m_videoSettings.bitRate();
if (bitrate > 0) {
g_object_set(G_OBJECT(encoderElement), "bitrate", bitrate, NULL);
}
}
QMap<QString,QVariant> options = m_options.value(codec);
QMapIterator<QString,QVariant> it(options);
while (it.hasNext()) {
it.next();
QString option = it.key();
QVariant value = it.value();
switch (value.type()) {
case QVariant::Int:
g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toInt(), NULL);
break;
case QVariant::Bool:
g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toBool(), NULL);
break;
case QVariant::Double:
g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toDouble(), NULL);
break;
case QVariant::String:
g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toString().toUtf8().constData(), NULL);
break;
default:
qWarning() << "unsupported option type:" << option << value;
break;
}
}
}
if (!m_videoSettings.resolution().isEmpty() || m_videoSettings.frameRate() > 0.001) {
GstCaps *caps = gst_caps_new_empty();
QStringList structureTypes;
structureTypes << "video/x-raw-yuv" << "video/x-raw-rgb";
foreach(const QString &structureType, structureTypes) {
GstStructure *structure = gst_structure_new(structureType.toAscii().constData(), NULL);
if (!m_videoSettings.resolution().isEmpty()) {
gst_structure_set(structure, "width", G_TYPE_INT, m_videoSettings.resolution().width(), NULL);
gst_structure_set(structure, "height", G_TYPE_INT, m_videoSettings.resolution().height(), NULL);
}
if (m_videoSettings.frameRate() > 0.001) {
QPair<int,int> rate = rateAsRational();
//qDebug() << "frame rate:" << num << denum;
gst_structure_set(structure, "framerate", GST_TYPE_FRACTION, rate.first, rate.second, NULL);
}
gst_caps_append_structure(caps,structure);
}
//qDebug() << "set video caps filter:" << gst_caps_to_string(caps);
g_object_set(G_OBJECT(capsFilter), "caps", caps, NULL);
}
return GST_ELEMENT(encoderBin);
}
QPair<int,int> QGstreamerVideoEncode::rateAsRational() const
{
qreal frameRate = m_videoSettings.frameRate();
if (frameRate > 0.001) {
//convert to rational number
QList<int> denumCandidates;
denumCandidates << 1 << 2 << 3 << 5 << 10 << 1001 << 1000;
qreal error = 1.0;
int num = 1;
int denum = 1;
foreach (int curDenum, denumCandidates) {
int curNum = qRound(frameRate*curDenum);
qreal curError = qAbs(qreal(curNum)/curDenum - frameRate);
if (curError < error) {
error = curError;
num = curNum;
denum = curDenum;
}
if (curError < 1e-8)
break;
}
return QPair<int,int>(num,denum);
}
return QPair<int,int>();
}
QSet<QString> QGstreamerVideoEncode::supportedStreamTypes(const QString &codecName) const
{
return m_streamTypes.value(codecName);
}

View File

@@ -0,0 +1,98 @@
/****************************************************************************
**
** 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 QGSTREAMERVIDEOENCODE_H
#define QGSTREAMERVIDEOENCODE_H
#include <qvideoencodercontrol.h>
class QGstreamerCaptureSession;
#include <QtCore/qstringlist.h>
#include <QtCore/qmap.h>
#include <QtCore/qset.h>
#include <gst/gst.h>
QT_USE_NAMESPACE
class QGstreamerVideoEncode : public QVideoEncoderControl
{
Q_OBJECT
public:
QGstreamerVideoEncode(QGstreamerCaptureSession *session);
virtual ~QGstreamerVideoEncode();
QList<QSize> supportedResolutions(const QVideoEncoderSettings &settings = QVideoEncoderSettings(),
bool *continuous = 0) const;
QList< qreal > supportedFrameRates(const QVideoEncoderSettings &settings = QVideoEncoderSettings(),
bool *continuous = 0) const;
QPair<int,int> rateAsRational() const;
QStringList supportedVideoCodecs() const;
QString videoCodecDescription(const QString &codecName) const;
QVideoEncoderSettings videoSettings() const;
void setVideoSettings(const QVideoEncoderSettings &settings);
QStringList supportedEncodingOptions(const QString &codec) const;
QVariant encodingOption(const QString &codec, const QString &name) const;
void setEncodingOption(const QString &codec, const QString &name, const QVariant &value);
GstElement *createEncoder();
QSet<QString> supportedStreamTypes(const QString &codecName) const;
private:
QGstreamerCaptureSession *m_session;
QStringList m_codecs;
QMap<QString,QString> m_codecDescriptions;
QMap<QString,QByteArray> m_elementNames;
QMap<QString,QStringList> m_codecOptions;
QVideoEncoderSettings m_videoSettings;
QMap<QString, QMap<QString, QVariant> > m_options;
QMap<QString, QSet<QString> > m_streamTypes;
};
#endif

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

View File

@@ -0,0 +1,75 @@
/****************************************************************************
**
** 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 QGSTBUFFERPOOL_H
#define QGSTBUFFERPOOL_H
#include <qabstractvideobuffer.h>
#include <qvideosurfaceformat.h>
#include <gst/gst.h>
/*!
Abstract interface for video buffers allocation.
*/
class QAbstractGstBufferPool
{
public:
virtual ~QAbstractGstBufferPool() {}
virtual bool isFormatSupported(const QVideoSurfaceFormat &format) const = 0;
virtual GType bufferType() const = 0;
virtual GstBuffer *takeBuffer(const QVideoSurfaceFormat &format, GstCaps *caps) = 0;
virtual void clear() = 0;
virtual QAbstractVideoBuffer::HandleType handleType() const = 0;
/*!
Build an QAbstractVideoBuffer instance from compatible (mathcing gst buffer type)
GstBuffer.
This method is called from gstreamer video sink thread.
*/
virtual QAbstractVideoBuffer *prepareVideoBuffer(GstBuffer *buffer, int bytesPerLine) = 0;
};
#endif

View File

@@ -0,0 +1,174 @@
/****************************************************************************
**
** 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 "qgstreameraudioinputendpointselector.h"
#include <QtGui/QIcon>
#include <QtCore/QDir>
#include <QtCore/QDebug>
#include <gst/gst.h>
#ifdef HAVE_ALSA
#include <alsa/asoundlib.h>
#endif
QGstreamerAudioInputEndpointSelector::QGstreamerAudioInputEndpointSelector(QObject *parent)
:QAudioEndpointSelector(parent)
{
update();
}
QGstreamerAudioInputEndpointSelector::~QGstreamerAudioInputEndpointSelector()
{
}
QList<QString> QGstreamerAudioInputEndpointSelector::availableEndpoints() const
{
return m_names;
}
QString QGstreamerAudioInputEndpointSelector::endpointDescription(const QString& name) const
{
QString desc;
for (int i = 0; i < m_names.size(); i++) {
if (m_names.at(i).compare(name) == 0) {
desc = m_descriptions.at(i);
break;
}
}
return desc;
}
QString QGstreamerAudioInputEndpointSelector::defaultEndpoint() const
{
if (m_names.size() > 0)
return m_names.at(0);
return QString();
}
QString QGstreamerAudioInputEndpointSelector::activeEndpoint() const
{
return m_audioInput;
}
void QGstreamerAudioInputEndpointSelector::setActiveEndpoint(const QString& name)
{
if (m_audioInput.compare(name) != 0) {
m_audioInput = name;
emit activeEndpointChanged(name);
}
}
void QGstreamerAudioInputEndpointSelector::update()
{
m_names.clear();
m_descriptions.clear();
#ifndef Q_WS_MAEMO_5
updateAlsaDevices();
updateOssDevices();
#endif
updatePulseDevices();
if (m_names.size() > 0)
m_audioInput = m_names.at(0);
}
void QGstreamerAudioInputEndpointSelector::updateAlsaDevices()
{
#ifdef HAVE_ALSA
void **hints, **n;
if (snd_device_name_hint(-1, "pcm", &hints) < 0) {
qWarning()<<"no alsa devices available";
return;
}
n = hints;
while (*n != NULL) {
char *name = snd_device_name_get_hint(*n, "NAME");
char *descr = snd_device_name_get_hint(*n, "DESC");
char *io = snd_device_name_get_hint(*n, "IOID");
if ((name != NULL) && (descr != NULL)) {
if ( io == NULL || qstrcmp(io,"Input") == 0 ) {
m_names.append(QLatin1String("alsa:")+QString::fromUtf8(name));
m_descriptions.append(QString::fromUtf8(descr));
}
}
if (name != NULL)
free(name);
if (descr != NULL)
free(descr);
if (io != NULL)
free(io);
n++;
}
snd_device_name_free_hint(hints);
#endif
}
void QGstreamerAudioInputEndpointSelector::updateOssDevices()
{
QDir devDir("/dev");
devDir.setFilter(QDir::System);
#ifndef QT_QWS_N810
QFileInfoList entries = devDir.entryInfoList(QStringList() << "dsp*");
foreach(const QFileInfo& entryInfo, entries) {
m_names.append(QLatin1String("oss:")+entryInfo.filePath());
m_descriptions.append(QString("OSS device %1").arg(entryInfo.fileName()));
}
#else
m_names.append("dsppcm");
m_descriptions.append("PCM audio input");
#endif
}
void QGstreamerAudioInputEndpointSelector::updatePulseDevices()
{
GstElementFactory *factory = gst_element_factory_find("pulsesrc");
if (factory) {
m_names.append("pulseaudio:");
m_descriptions.append("PulseAudio device.");
gst_object_unref(GST_OBJECT(factory));
}
}

View File

@@ -0,0 +1,76 @@
/****************************************************************************
**
** 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 QGSTREAMERAUDIOINPUTENDPOINTSELECTOR_H
#define QGSTREAMERAUDIOINPUTENDPOINTSELECTOR_H
#include <qaudioendpointselector.h>
#include <QtCore/qstringlist.h>
QT_USE_NAMESPACE
class QGstreamerAudioInputEndpointSelector : public QAudioEndpointSelector
{
Q_OBJECT
public:
QGstreamerAudioInputEndpointSelector(QObject *parent);
~QGstreamerAudioInputEndpointSelector();
QList<QString> availableEndpoints() const;
QString endpointDescription(const QString& name) const;
QString defaultEndpoint() const;
QString activeEndpoint() const;
public Q_SLOTS:
void setActiveEndpoint(const QString& name);
private:
void update();
void updateAlsaDevices();
void updateOssDevices();
void updatePulseDevices();
QString m_audioInput;
QList<QString> m_names;
QList<QString> m_descriptions;
};
#endif // QGSTREAMERAUDIOINPUTENDPOINTSELECTOR_H

View File

@@ -0,0 +1,203 @@
/****************************************************************************
**
** 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 <QMap>
#include <QTimer>
#include <QMutex>
#include "qgstreamerbushelper.h"
#ifndef QT_NO_GLIB
class QGstreamerBusHelperPrivate : public QObject
{
Q_OBJECT
public:
void addWatch(GstBus* bus, QGstreamerBusHelper* helper)
{
setParent(helper);
m_tag = gst_bus_add_watch_full(bus, 0, busCallback, this, NULL);
m_helper = helper;
filter = 0;
}
void removeWatch(QGstreamerBusHelper* helper)
{
Q_UNUSED(helper);
g_source_remove(m_tag);
}
static QGstreamerBusHelperPrivate* instance()
{
return new QGstreamerBusHelperPrivate;
}
private:
void processMessage(GstBus* bus, GstMessage* message)
{
Q_UNUSED(bus);
emit m_helper->message(message);
}
static gboolean busCallback(GstBus *bus, GstMessage *message, gpointer data)
{
reinterpret_cast<QGstreamerBusHelperPrivate*>(data)->processMessage(bus, message);
return TRUE;
}
guint m_tag;
QGstreamerBusHelper* m_helper;
public:
GstBus* bus;
QGstreamerSyncEventFilter *filter;
QMutex filterMutex;
};
#else
class QGstreamerBusHelperPrivate : public QObject
{
Q_OBJECT
typedef QMap<QGstreamerBusHelper*, GstBus*> HelperMap;
public:
void addWatch(GstBus* bus, QGstreamerBusHelper* helper)
{
m_helperMap.insert(helper, bus);
if (m_helperMap.size() == 1)
m_intervalTimer->start();
}
void removeWatch(QGstreamerBusHelper* helper)
{
m_helperMap.remove(helper);
if (m_helperMap.size() == 0)
m_intervalTimer->stop();
}
static QGstreamerBusHelperPrivate* instance()
{
static QGstreamerBusHelperPrivate self;
return &self;
}
private slots:
void interval()
{
for (HelperMap::iterator it = m_helperMap.begin(); it != m_helperMap.end(); ++it) {
GstMessage* message;
while ((message = gst_bus_poll(it.value(), GST_MESSAGE_ANY, 0)) != 0) {
emit it.key()->message(message);
gst_message_unref(message);
}
emit it.key()->message(QGstreamerMessage());
}
}
private:
QGstreamerBusHelperPrivate()
{
m_intervalTimer = new QTimer(this);
m_intervalTimer->setInterval(250);
connect(m_intervalTimer, SIGNAL(timeout()), SLOT(interval()));
}
HelperMap m_helperMap;
QTimer* m_intervalTimer;
public:
GstBus* bus;
QGstreamerSyncEventFilter *filter;
QMutex filterMutex;
};
#endif
static GstBusSyncReply syncGstBusFilter(GstBus* bus, GstMessage* message, QGstreamerBusHelperPrivate *d)
{
Q_UNUSED(bus);
QMutexLocker lock(&d->filterMutex);
bool res = false;
if (d->filter)
res = d->filter->processSyncMessage(QGstreamerMessage(message));
return res ? GST_BUS_DROP : GST_BUS_PASS;
}
/*!
\class gstreamer::QGstreamerBusHelper
\internal
*/
QGstreamerBusHelper::QGstreamerBusHelper(GstBus* bus, QObject* parent):
QObject(parent),
d(QGstreamerBusHelperPrivate::instance())
{
d->bus = bus;
d->addWatch(bus, this);
gst_bus_set_sync_handler(bus, (GstBusSyncHandler)syncGstBusFilter, d);
}
QGstreamerBusHelper::~QGstreamerBusHelper()
{
d->removeWatch(this);
gst_bus_set_sync_handler(d->bus,0,0);
}
void QGstreamerBusHelper::installSyncEventFilter(QGstreamerSyncEventFilter *filter)
{
QMutexLocker lock(&d->filterMutex);
d->filter = filter;
}
#include "qgstreamerbushelper.moc"

View File

@@ -0,0 +1,77 @@
/****************************************************************************
**
** 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 QGSTREAMERBUSHELPER_H
#define QGSTREAMERBUSHELPER_H
#include <QObject>
#include <qgstreamermessage.h>
#include <gst/gst.h>
class QGstreamerSyncEventFilter {
public:
//returns true if message was processed and should be dropped, false otherwise
virtual bool processSyncMessage(const QGstreamerMessage &message) = 0;
};
class QGstreamerBusHelperPrivate;
class QGstreamerBusHelper : public QObject
{
Q_OBJECT
friend class QGstreamerBusHelperPrivate;
public:
QGstreamerBusHelper(GstBus* bus, QObject* parent = 0);
~QGstreamerBusHelper();
void installSyncEventFilter(QGstreamerSyncEventFilter *filter);
signals:
void message(QGstreamerMessage const& message);
private:
QGstreamerBusHelperPrivate* d;
};
#endif

View File

@@ -0,0 +1,578 @@
/****************************************************************************
**
** 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 "qvideosurfacegstsink.h"
#include "qabstractvideosurface.h"
#include "qgstutils.h"
#include <QtGui/qevent.h>
#include <QtGui/qapplication.h>
#include <QtGui/qx11info_x11.h>
#include <QtCore/qdebug.h>
#include <QtCore/qthread.h>
#include <QtOpenGL/qgl.h>
#include <gst/gst.h>
#include <gst/interfaces/xoverlay.h>
#include <gst/interfaces/propertyprobe.h>
#include <gst/interfaces/meegovideotexture.h>
#include <gst/interfaces/meegovideorenderswitch.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include "qgstreamergltexturerenderer.h"
//#define GL_TEXTURE_SINK_DEBUG 1
//from extdefs.h
typedef void *EGLSyncKHR;
typedef khronos_utime_nanoseconds_t EGLTimeKHR;
#define GL_TEXTURE_EXTERNAL_OES 0x8D65
#define EGL_SYNC_FENCE_KHR 0x30F9
typedef EGLSyncKHR (EGLAPIENTRYP _PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy,
EGLenum type, const EGLint * attrib_list);
typedef EGLBoolean (EGLAPIENTRYP _PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy,
EGLSyncKHR sync);
const QAbstractVideoBuffer::HandleType EGLImageTextureHandle =
QAbstractVideoBuffer::HandleType(QAbstractVideoBuffer::UserHandle+3434);
// EGLSync functions
_PFNEGLCREATESYNCKHRPROC eglCreateSyncKHR;
_PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR;
class QGStreamerGLTextureBuffer : public QAbstractVideoBuffer
{
public:
QGStreamerGLTextureBuffer(MeegoGstVideoTexture *textureSink, int frameNumber) :
QAbstractVideoBuffer(EGLImageTextureHandle),
m_textureSink(MEEGO_GST_VIDEO_TEXTURE(textureSink)),
m_frameNumber(frameNumber)
{
}
~QGStreamerGLTextureBuffer()
{
}
MapMode mapMode() const { return NotMapped; }
uchar *map(MapMode mode, int *numBytes, int *bytesPerLine)
{
Q_UNUSED(mode);
Q_UNUSED(numBytes);
Q_UNUSED(bytesPerLine);
//acquire_frame should really be called at buffer construction time
//but it conflicts with id-less implementation of gst texture sink.
#if defined(GL_TEXTURE_SINK_DEBUG) && GL_TEXTURE_SINK_DEBUG > 1
qDebug() << "acquire frame" << m_frameNumber;
#endif
if (!meego_gst_video_texture_acquire_frame(m_textureSink,m_frameNumber))
qWarning() << Q_FUNC_INFO << "acquire-frame failed" << m_frameNumber;
#if defined(GL_TEXTURE_SINK_DEBUG) && GL_TEXTURE_SINK_DEBUG > 1
qDebug() << "map frame" << m_frameNumber;
#endif
gboolean bind_status = meego_gst_video_texture_bind_frame(m_textureSink, GL_TEXTURE_EXTERNAL_OES, m_frameNumber);
if (!bind_status)
qWarning() << Q_FUNC_INFO << "bind-frame failed";
return (uchar*)1;
}
void unmap()
{
gboolean bind_status = meego_gst_video_texture_bind_frame(m_textureSink, GL_TEXTURE_EXTERNAL_OES, -1);
#if defined(GL_TEXTURE_SINK_DEBUG) && GL_TEXTURE_SINK_DEBUG > 1
qDebug() << "unmap frame" << m_frameNumber;
#endif
if (!bind_status)
qWarning() << Q_FUNC_INFO << "unbind-frame failed";
//release_frame should really be called in destructor
//but this conflicts with id-less implementation of gst texture sink.
#if defined(GL_TEXTURE_SINK_DEBUG) && GL_TEXTURE_SINK_DEBUG > 1
qDebug() << "release frame" << m_frameNumber;
#endif
EGLSyncKHR sync = eglCreateSyncKHR(eglGetDisplay((EGLNativeDisplayType)QX11Info::display()), EGL_SYNC_FENCE_KHR, NULL);
meego_gst_video_texture_release_frame(m_textureSink, m_frameNumber, sync);
}
QVariant handle() const
{
return m_frameNumber;
}
private:
MeegoGstVideoTexture *m_textureSink;
int m_frameNumber;
};
QGstreamerGLTextureRenderer::QGstreamerGLTextureRenderer(QObject *parent) :
QVideoRendererControl(parent),
m_videoSink(0),
m_surface(0),
m_context(0),
m_winId(0),
m_colorKey(49,0,49),
m_overlayEnabled(false),
m_bufferProbeId(-1)
{
eglCreateSyncKHR =
(_PFNEGLCREATESYNCKHRPROC)eglGetProcAddress("eglCreateSyncKHR");
eglDestroySyncKHR =
(_PFNEGLDESTROYSYNCKHRPROC)eglGetProcAddress("eglDestroySyncKHR");
}
QGstreamerGLTextureRenderer::~QGstreamerGLTextureRenderer()
{
if (m_surface && m_surface->isActive())
m_surface->stop();
if (m_videoSink)
gst_object_unref(GST_OBJECT(m_videoSink));
}
GstElement *QGstreamerGLTextureRenderer::videoSink()
{
if (!m_videoSink && isReady()) {
if (m_context && !m_surface->supportedPixelFormats(EGLImageTextureHandle).isEmpty()) {
#ifdef GL_TEXTURE_SINK_DEBUG
qDebug() << Q_FUNC_INFO << ": using gltexture sink";
#endif
if (m_context)
m_context->makeCurrent();
m_videoSink = gst_element_factory_make("gltexturesink", "egl-texture-sink");
g_object_set(G_OBJECT(m_videoSink),
"x-display", QX11Info::display(),
"egl-display", eglGetDisplay((EGLNativeDisplayType)QX11Info::display()),
"egl-context", eglGetCurrentContext(),
"colorkey", m_colorKey.rgb(),
"autopaint-colorkey", false,
"use-framebuffer-memory", true,
"render-mode", m_overlayEnabled ? VIDEO_RENDERSWITCH_XOVERLAY_MODE
: VIDEO_RENDERSWITCH_TEXTURE_STREAMING_MODE,
(char*)NULL);
g_signal_connect(G_OBJECT(m_videoSink), "frame-ready", G_CALLBACK(handleFrameReady), (gpointer)this);
} else {
qWarning() << Q_FUNC_INFO << ": Fallback to QVideoSurfaceGstSink since EGLImageTextureHandle is not supported";
m_videoSink = reinterpret_cast<GstElement*>(QVideoSurfaceGstSink::createSink(m_surface));
}
if (m_videoSink) {
gst_object_ref(GST_OBJECT(m_videoSink)); //Take ownership
gst_object_sink(GST_OBJECT(m_videoSink));
GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink");
m_bufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padBufferProbe), this);
}
}
return m_videoSink;
}
QAbstractVideoSurface *QGstreamerGLTextureRenderer::surface() const
{
return m_surface;
}
void QGstreamerGLTextureRenderer::setSurface(QAbstractVideoSurface *surface)
{
if (m_surface != surface) {
#ifdef GL_TEXTURE_SINK_DEBUG
qDebug() << Q_FUNC_INFO << surface;
#endif
bool oldReady = isReady();
m_context = const_cast<QGLContext*>(QGLContext::currentContext());
if (m_videoSink)
gst_object_unref(GST_OBJECT(m_videoSink));
m_videoSink = 0;
if (m_surface) {
disconnect(m_surface, SIGNAL(supportedFormatsChanged()),
this, SLOT(handleFormatChange()));
}
m_surface = surface;
if (oldReady != isReady())
emit readyChanged(!oldReady);
if (m_surface) {
connect(m_surface, SIGNAL(supportedFormatsChanged()),
this, SLOT(handleFormatChange()));
}
emit sinkChanged();
}
}
void QGstreamerGLTextureRenderer::handleFormatChange()
{
if (m_videoSink)
gst_object_unref(GST_OBJECT(m_videoSink));
m_videoSink = 0;
emit sinkChanged();
}
void QGstreamerGLTextureRenderer::handleFrameReady(GstElement *sink, gint frame, gpointer data)
{
Q_UNUSED(sink);
QGstreamerGLTextureRenderer* renderer = reinterpret_cast<QGstreamerGLTextureRenderer*>(data);
QMutexLocker locker(&renderer->m_mutex);
QMetaObject::invokeMethod(renderer, "renderGLFrame",
Qt::QueuedConnection,
Q_ARG(int, frame));
//we have to wait to ensure the frame is not reused,
//timeout is added to avoid deadlocks when the main thread is
//waiting for rendering to complete, this is possible for example during state chages.
//If frame is not rendered during 60ms (~1-2 frames interval) it's better to unblock and drop it if necessary
renderer->m_renderCondition.wait(&renderer->m_mutex, 60);
}
void QGstreamerGLTextureRenderer::renderGLFrame(int frame)
{
#if defined(GL_TEXTURE_SINK_DEBUG) && GL_TEXTURE_SINK_DEBUG > 1
qDebug() << Q_FUNC_INFO << "frame:" << frame << "surface active:" << m_surface->isActive();
#endif
QMutexLocker locker(&m_mutex);
if (!m_surface) {
m_renderCondition.wakeAll();
return;
}
MeegoGstVideoTexture *textureSink = MEEGO_GST_VIDEO_TEXTURE(m_videoSink);
if (m_context)
m_context->makeCurrent();
//don't try to render the frame if state is changed to NULL or READY
GstState pendingState = GST_STATE_NULL;
GstState newState = GST_STATE_NULL;
GstStateChangeReturn res = gst_element_get_state(m_videoSink,
&newState,
&pendingState,
0);//don't block and return immediately
if (res == GST_STATE_CHANGE_FAILURE ||
newState == GST_STATE_NULL ||
pendingState == GST_STATE_NULL) {
stopRenderer();
m_renderCondition.wakeAll();
return;
}
if (!m_surface->isActive()) {
//find the native video size
GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink");
GstCaps *caps = gst_pad_get_negotiated_caps(pad);
if (caps) {
QSize newNativeSize = QGstUtils::capsCorrectedResolution(caps);
if (m_nativeSize != newNativeSize) {
m_nativeSize = newNativeSize;
emit nativeSizeChanged();
}
gst_caps_unref(caps);
}
//start the surface...
QVideoSurfaceFormat format(m_nativeSize, QVideoFrame::Format_RGB32, EGLImageTextureHandle);
if (!m_surface->start(format)) {
qWarning() << Q_FUNC_INFO << "failed to start video surface" << format;
m_renderCondition.wakeAll();
return;
}
}
QGStreamerGLTextureBuffer *buffer = new QGStreamerGLTextureBuffer(textureSink, frame);
QVideoFrame videoFrame(buffer,
m_surface->surfaceFormat().frameSize(),
m_surface->surfaceFormat().pixelFormat());
m_surface->present(videoFrame);
m_renderCondition.wakeAll();
}
bool QGstreamerGLTextureRenderer::isReady() const
{
if (!m_surface)
return false;
if (m_winId > 0)
return true;
//winId is required only for EGLImageTextureHandle compatible surfaces
return m_surface->supportedPixelFormats(EGLImageTextureHandle).isEmpty();
}
void QGstreamerGLTextureRenderer::handleBusMessage(GstMessage* gm)
{
#ifdef GL_TEXTURE_SINK_DEBUG
qDebug() << Q_FUNC_INFO << GST_MESSAGE_TYPE_NAME(gm);
#endif
if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_STATE_CHANGED) {
GstState oldState;
GstState newState;
gst_message_parse_state_changed(gm, &oldState, &newState, 0);
#ifdef GL_TEXTURE_SINK_DEBUG
qDebug() << Q_FUNC_INFO << "State changed:" << oldState << newState;
#endif
if (newState == GST_STATE_READY || newState == GST_STATE_NULL) {
stopRenderer();
}
if (oldState == GST_STATE_READY && newState == GST_STATE_PAUSED) {
updateNativeVideoSize();
}
}
}
void QGstreamerGLTextureRenderer::handleSyncMessage(GstMessage* gm)
{
#ifdef GL_TEXTURE_SINK_DEBUG
qDebug() << Q_FUNC_INFO;
#endif
if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT &&
gst_structure_has_name(gm->structure, "prepare-xwindow-id"))
precessNewStream();
}
void QGstreamerGLTextureRenderer::precessNewStream()
{
if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) {
GstXOverlay *overlay = GST_X_OVERLAY(m_videoSink);
gst_x_overlay_set_xwindow_id(overlay, m_winId);
if (!m_displayRect.isEmpty()) {
gst_x_overlay_set_render_rectangle(overlay,
m_displayRect.x(),
m_displayRect.y(),
m_displayRect.width(),
m_displayRect.height());
}
GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink");
m_bufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padBufferProbe), this);
}
}
void QGstreamerGLTextureRenderer::stopRenderer()
{
#ifdef GL_TEXTURE_SINK_DEBUG
qDebug() << Q_FUNC_INFO;
#endif
if (m_surface && m_surface->isActive())
m_surface->stop();
if (!m_nativeSize.isEmpty()) {
m_nativeSize = QSize();
emit nativeSizeChanged();
}
}
bool QGstreamerGLTextureRenderer::overlayEnabled() const
{
return m_overlayEnabled;
}
void QGstreamerGLTextureRenderer::setOverlayEnabled(bool enabled)
{
if (m_videoSink && (m_overlayEnabled != enabled)) {
qDebug() << Q_FUNC_INFO << enabled;
g_object_set(G_OBJECT(m_videoSink),
"render-mode",
enabled ? VIDEO_RENDERSWITCH_XOVERLAY_MODE : VIDEO_RENDERSWITCH_TEXTURE_STREAMING_MODE,
(char *)NULL);
}
m_overlayEnabled = enabled;
}
WId QGstreamerGLTextureRenderer::winId() const
{
return m_winId;
}
void QGstreamerGLTextureRenderer::setWinId(WId id)
{
#ifdef GL_TEXTURE_SINK_DEBUG
qDebug() << Q_FUNC_INFO << id;
#endif
if (m_winId == id)
return;
bool oldReady = isReady();
m_winId = id;
if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) {
//don't set winId in NULL state,
//texture sink opens xvideo port on set_xwindow_id,
//this fails if video resource is not granted by resource policy yet.
//state is changed to READY/PAUSED/PLAYING only after resource is granted.
GstState pendingState = GST_STATE_NULL;
GstState newState = GST_STATE_NULL;
GstStateChangeReturn res = gst_element_get_state(m_videoSink,
&newState,
&pendingState,
0);//don't block and return immediately
if (res != GST_STATE_CHANGE_FAILURE &&
newState != GST_STATE_NULL &&
pendingState != GST_STATE_NULL)
gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(m_videoSink), m_winId);
}
if (oldReady != isReady())
emit readyChanged(!oldReady);
}
QRect QGstreamerGLTextureRenderer::overlayGeometry() const
{
return m_displayRect;
}
void QGstreamerGLTextureRenderer::setOverlayGeometry(const QRect &geometry)
{
if (m_displayRect != geometry) {
#ifdef GL_TEXTURE_SINK_DEBUG
qDebug() << Q_FUNC_INFO << geometry;
#endif
m_displayRect = geometry;
if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) {
if (m_displayRect.isEmpty())
gst_x_overlay_set_render_rectangle(GST_X_OVERLAY(m_videoSink), -1, -1, -1, -1);
else
gst_x_overlay_set_render_rectangle(GST_X_OVERLAY(m_videoSink),
m_displayRect.x(),
m_displayRect.y(),
m_displayRect.width(),
m_displayRect.height());
repaintOverlay();
}
}
}
QColor QGstreamerGLTextureRenderer::colorKey() const
{
return m_colorKey;
}
void QGstreamerGLTextureRenderer::repaintOverlay()
{
if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) {
//don't call gst_x_overlay_expose if the sink is in null state
GstState state = GST_STATE_NULL;
GstStateChangeReturn res = gst_element_get_state(m_videoSink, &state, NULL, 1000000);
if (res != GST_STATE_CHANGE_FAILURE && state != GST_STATE_NULL) {
gst_x_overlay_expose(GST_X_OVERLAY(m_videoSink));
}
}
}
QSize QGstreamerGLTextureRenderer::nativeSize() const
{
return m_nativeSize;
}
gboolean QGstreamerGLTextureRenderer::padBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data)
{
QGstreamerGLTextureRenderer *control = reinterpret_cast<QGstreamerGLTextureRenderer*>(user_data);
QMetaObject::invokeMethod(control, "updateNativeVideoSize", Qt::QueuedConnection);
gst_pad_remove_buffer_probe(pad, control->m_bufferProbeId);
return TRUE;
}
void QGstreamerGLTextureRenderer::updateNativeVideoSize()
{
const QSize oldSize = m_nativeSize;
if (m_videoSink) {
//find video native size to update video widget size hint
GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink");
GstCaps *caps = gst_pad_get_negotiated_caps(pad);
if (caps) {
m_nativeSize = QGstUtils::capsCorrectedResolution(caps);
gst_caps_unref(caps);
}
} else {
m_nativeSize = QSize();
}
#ifdef GL_TEXTURE_SINK_DEBUG
qDebug() << Q_FUNC_INFO << oldSize << m_nativeSize << m_videoSink;
#endif
if (m_nativeSize != oldSize)
emit nativeSizeChanged();
}

View File

@@ -0,0 +1,127 @@
/****************************************************************************
**
** 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 QGSTREAMERGLTEXTURERENDERER_H
#define QGSTREAMERGLTEXTURERENDERER_H
#include <qvideorenderercontrol.h>
#include "qvideosurfacegstsink.h"
#include "qgstreamervideorendererinterface.h"
#include <QtGui/qcolor.h>
#include <X11/extensions/Xv.h>
QT_USE_NAMESPACE
class QGLContext;
class QGstreamerGLTextureRenderer : public QVideoRendererControl, public QGstreamerVideoRendererInterface
{
Q_OBJECT
Q_INTERFACES(QGstreamerVideoRendererInterface)
Q_PROPERTY(bool overlayEnabled READ overlayEnabled WRITE setOverlayEnabled)
Q_PROPERTY(qulonglong winId READ winId WRITE setWinId)
Q_PROPERTY(QRect overlayGeometry READ overlayGeometry WRITE setOverlayGeometry)
Q_PROPERTY(QColor colorKey READ colorKey)
Q_PROPERTY(QSize nativeSize READ nativeSize NOTIFY nativeSizeChanged)
public:
QGstreamerGLTextureRenderer(QObject *parent = 0);
virtual ~QGstreamerGLTextureRenderer();
QAbstractVideoSurface *surface() const;
void setSurface(QAbstractVideoSurface *surface);
GstElement *videoSink();
bool isReady() const;
void handleBusMessage(GstMessage* gm);
void handleSyncMessage(GstMessage* gm);
void precessNewStream();
void stopRenderer();
int framebufferNumber() const;
bool overlayEnabled() const;
WId winId() const;
QRect overlayGeometry() const;
QColor colorKey() const;
QSize nativeSize() const;
public slots:
void renderGLFrame(int);
void setOverlayEnabled(bool);
void setWinId(WId id);
void setOverlayGeometry(const QRect &geometry);
void repaintOverlay();
signals:
void sinkChanged();
void readyChanged(bool);
void nativeSizeChanged();
private slots:
void handleFormatChange();
void updateNativeVideoSize();
private:
static void handleFrameReady(GstElement *sink, gint frame, gpointer data);
static gboolean padBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data);
GstElement *m_videoSink;
QAbstractVideoSurface *m_surface;
QGLContext *m_context;
QSize m_nativeSize;
WId m_winId;
QColor m_colorKey;
QRect m_displayRect;
bool m_overlayEnabled;
int m_bufferProbeId;
QMutex m_mutex;
QWaitCondition m_renderCondition;
};
#endif // QGSTREAMERVIDEORENDRER_H

View File

@@ -0,0 +1,93 @@
/****************************************************************************
**
** 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 <gst/gst.h>
#include "qgstreamermessage.h"
static int wuchi = qRegisterMetaType<QGstreamerMessage>();
/*!
\class gstreamer::QGstreamerMessage
\internal
*/
QGstreamerMessage::QGstreamerMessage():
m_message(0)
{
}
QGstreamerMessage::QGstreamerMessage(GstMessage* message):
m_message(message)
{
gst_message_ref(m_message);
}
QGstreamerMessage::QGstreamerMessage(QGstreamerMessage const& m):
m_message(m.m_message)
{
gst_message_ref(m_message);
}
QGstreamerMessage::~QGstreamerMessage()
{
if (m_message != 0)
gst_message_unref(m_message);
}
GstMessage* QGstreamerMessage::rawMessage() const
{
return m_message;
}
QGstreamerMessage& QGstreamerMessage::operator=(QGstreamerMessage const& rhs)
{
if (m_message != 0)
gst_message_unref(m_message);
if ((m_message = rhs.m_message) != 0)
gst_message_ref(m_message);
return *this;
}

View File

@@ -0,0 +1,68 @@
/****************************************************************************
**
** 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 QGSTREAMERMESSAGE_H
#define QGSTREAMERMESSAGE_H
#include <QMetaType>
#include <gst/gst.h>
class QGstreamerMessage
{
public:
QGstreamerMessage();
QGstreamerMessage(GstMessage* message);
QGstreamerMessage(QGstreamerMessage const& m);
~QGstreamerMessage();
GstMessage* rawMessage() const;
QGstreamerMessage& operator=(QGstreamerMessage const& rhs);
private:
GstMessage* m_message;
};
Q_DECLARE_METATYPE(QGstreamerMessage);
#endif

View File

@@ -0,0 +1,401 @@
/****************************************************************************
**
** 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/qstring.h>
#include <QtCore/qdebug.h>
#include <QtGui/QIcon>
#include <QtCore/QDir>
#include <QtCore/QDebug>
#include "qgstreamerserviceplugin.h"
//#define QT_SUPPORTEDMIMETYPES_DEBUG
#ifdef QMEDIA_GSTREAMER_PLAYER
#include "qgstreamerplayerservice.h"
#endif
#if defined(QMEDIA_GSTREAMER_CAPTURE)
#include "qgstreamercaptureservice.h"
#endif
#ifdef QMEDIA_GSTREAMER_CAMERABIN
#include "camerabinservice.h"
#endif
#include <qmediaserviceprovider.h>
#include <linux/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
QStringList QGstreamerServicePlugin::keys() const
{
return QStringList()
#ifdef QMEDIA_GSTREAMER_PLAYER
<< QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER)
#endif
#ifdef QMEDIA_GSTREAMER_CAPTURE
<< QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE)
<< QLatin1String(Q_MEDIASERVICE_CAMERA)
#elif defined(QMEDIA_GSTREAMER_CAMERABIN)
<< QLatin1String(Q_MEDIASERVICE_CAMERA)
#endif
;
}
QMediaService* QGstreamerServicePlugin::create(const QString &key)
{
static bool initialized = false;
if (!initialized) {
initialized = true;
gst_init(NULL, NULL);
}
#ifdef QMEDIA_GSTREAMER_PLAYER
if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER))
return new QGstreamerPlayerService;
#endif
#ifdef QMEDIA_GSTREAMER_CAMERABIN
if (key == QLatin1String(Q_MEDIASERVICE_CAMERA) && CameraBinService::isCameraBinAvailable())
return new CameraBinService(key);
#endif
#ifdef QMEDIA_GSTREAMER_CAPTURE
if (key == QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE))
return new QGstreamerCaptureService(key);
if (key == QLatin1String(Q_MEDIASERVICE_CAMERA))
return new QGstreamerCaptureService(key);
#endif
qWarning() << "Gstreamer service plugin: unsupported key:" << key;
return 0;
}
void QGstreamerServicePlugin::release(QMediaService *service)
{
delete service;
}
QMediaServiceProviderHint::Features QGstreamerServicePlugin::supportedFeatures(
const QByteArray &service) const
{
if (service == Q_MEDIASERVICE_MEDIAPLAYER)
return QMediaServiceProviderHint::StreamPlayback | QMediaServiceProviderHint::VideoSurface;
else if (service == Q_MEDIASERVICE_CAMERA)
return QMediaServiceProviderHint::VideoSurface;
else
return QMediaServiceProviderHint::Features();
}
QList<QByteArray> QGstreamerServicePlugin::devices(const QByteArray &service) const
{
if (service == Q_MEDIASERVICE_CAMERA) {
if (m_cameraDevices.isEmpty())
updateDevices();
return m_cameraDevices;
}
return QList<QByteArray>();
}
QString QGstreamerServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device)
{
if (service == Q_MEDIASERVICE_CAMERA) {
if (m_cameraDevices.isEmpty())
updateDevices();
for (int i=0; i<m_cameraDevices.count(); i++)
if (m_cameraDevices[i] == device)
return m_cameraDescriptions[i];
}
return QString();
}
QVariant QGstreamerServicePlugin::deviceProperty(const QByteArray &service, const QByteArray &device, const QByteArray &property)
{
Q_UNUSED(service);
Q_UNUSED(device);
Q_UNUSED(property);
return QVariant();
}
void QGstreamerServicePlugin::updateDevices() const
{
m_cameraDevices.clear();
m_cameraDescriptions.clear();
#ifdef Q_WS_MAEMO_5
m_cameraDevices << "/dev/video0" << "/dev/video1";
m_cameraDescriptions << tr("Main Camera") << tr("Front Camera");
return;
#endif
#ifdef Q_WS_MAEMO_6
m_cameraDevices << "primary" << "secondary";
m_cameraDescriptions << tr("Main camera") << tr("Front camera");
return;
#endif
QDir devDir("/dev");
devDir.setFilter(QDir::System);
QFileInfoList entries = devDir.entryInfoList(QStringList() << "video*");
foreach( const QFileInfo &entryInfo, entries ) {
//qDebug() << "Try" << entryInfo.filePath();
int fd = ::open(entryInfo.filePath().toLatin1().constData(), O_RDWR );
if (fd == -1)
continue;
bool isCamera = false;
v4l2_input input;
memset(&input, 0, sizeof(input));
for (; ::ioctl(fd, VIDIOC_ENUMINPUT, &input) >= 0; ++input.index) {
if(input.type == V4L2_INPUT_TYPE_CAMERA || input.type == 0) {
isCamera = ::ioctl(fd, VIDIOC_S_INPUT, input.index) != 0;
break;
}
}
if (isCamera) {
// find out its driver "name"
QString name;
struct v4l2_capability vcap;
memset(&vcap, 0, sizeof(struct v4l2_capability));
if (ioctl(fd, VIDIOC_QUERYCAP, &vcap) != 0)
name = entryInfo.fileName();
else
name = QString((const char*)vcap.card);
//qDebug() << "found camera: " << name;
m_cameraDevices.append(entryInfo.filePath().toLocal8Bit());
m_cameraDescriptions.append(name);
}
::close(fd);
}
}
namespace {
const char* getCodecAlias(const QString &codec)
{
if (codec.startsWith("avc1."))
return "video/x-h264";
if (codec.startsWith("mp4a."))
return "audio/mpeg4";
if (codec.startsWith("mp4v.20."))
return "video/mpeg4";
if (codec == "samr")
return "audio/amr";
return 0;
}
const char* getMimeTypeAlias(const QString &mimeType)
{
if (mimeType == "video/mp4")
return "video/mpeg4";
if (mimeType == "audio/mp4")
return "audio/mpeg4";
if (mimeType == "video/ogg"
|| mimeType == "audio/ogg")
return "application/ogg";
return 0;
}
}
QtMultimediaKit::SupportEstimate QGstreamerServicePlugin::hasSupport(const QString &mimeType,
const QStringList& codecs) const
{
if (m_supportedMimeTypeSet.isEmpty())
updateSupportedMimeTypes();
QString mimeTypeLowcase = mimeType.toLower();
bool containsMimeType = m_supportedMimeTypeSet.contains(mimeTypeLowcase);
if (!containsMimeType) {
const char* mimeTypeAlias = getMimeTypeAlias(mimeTypeLowcase);
containsMimeType = m_supportedMimeTypeSet.contains(mimeTypeAlias);
if (!containsMimeType) {
containsMimeType = m_supportedMimeTypeSet.contains("video/" + mimeTypeLowcase)
|| m_supportedMimeTypeSet.contains("video/x-" + mimeTypeLowcase)
|| m_supportedMimeTypeSet.contains("audio/" + mimeTypeLowcase)
|| m_supportedMimeTypeSet.contains("audio/x-" + mimeTypeLowcase);
}
}
int supportedCodecCount = 0;
foreach(const QString &codec, codecs) {
QString codecLowcase = codec.toLower();
const char* codecAlias = getCodecAlias(codecLowcase);
if (codecAlias) {
if (m_supportedMimeTypeSet.contains(codecAlias))
supportedCodecCount++;
} else if (m_supportedMimeTypeSet.contains("video/" + codecLowcase)
|| m_supportedMimeTypeSet.contains("video/x-" + codecLowcase)
|| m_supportedMimeTypeSet.contains("audio/" + codecLowcase)
|| m_supportedMimeTypeSet.contains("audio/x-" + codecLowcase)) {
supportedCodecCount++;
}
}
if (supportedCodecCount > 0 && supportedCodecCount == codecs.size())
return QtMultimediaKit::ProbablySupported;
if (supportedCodecCount == 0 && !containsMimeType)
return QtMultimediaKit::NotSupported;
return QtMultimediaKit::MaybeSupported;
}
void QGstreamerServicePlugin::updateSupportedMimeTypes() const
{
//enumerate supported mime types
gst_init(NULL, NULL);
GList *plugins, *orig_plugins;
orig_plugins = plugins = gst_default_registry_get_plugin_list ();
while (plugins) {
GList *features, *orig_features;
GstPlugin *plugin = (GstPlugin *) (plugins->data);
plugins = g_list_next (plugins);
if (plugin->flags & (1<<1)) //GST_PLUGIN_FLAG_BLACKLISTED
continue;
orig_features = features = gst_registry_get_feature_list_by_plugin(gst_registry_get_default (),
plugin->desc.name);
while (features) {
if (!G_UNLIKELY(features->data == NULL)) {
GstPluginFeature *feature = GST_PLUGIN_FEATURE(features->data);
if (GST_IS_ELEMENT_FACTORY (feature)) {
GstElementFactory *factory = GST_ELEMENT_FACTORY(gst_plugin_feature_load(feature));
if (factory
&& factory->numpadtemplates > 0
&& (qstrcmp(factory->details.klass, "Codec/Decoder/Audio") == 0
|| qstrcmp(factory->details.klass, "Codec/Decoder/Video") == 0
|| qstrcmp(factory->details.klass, "Codec/Demux") == 0 )) {
const GList *pads = factory->staticpadtemplates;
while (pads) {
GstStaticPadTemplate *padtemplate = (GstStaticPadTemplate*)(pads->data);
pads = g_list_next (pads);
if (padtemplate->direction != GST_PAD_SINK)
continue;
if (padtemplate->static_caps.string) {
GstCaps *caps = gst_static_caps_get(&padtemplate->static_caps);
if (!gst_caps_is_any (caps) && ! gst_caps_is_empty (caps)) {
for (guint i = 0; i < gst_caps_get_size(caps); i++) {
GstStructure *structure = gst_caps_get_structure(caps, i);
QString nameLowcase = QString(gst_structure_get_name (structure)).toLower();
m_supportedMimeTypeSet.insert(nameLowcase);
if (nameLowcase.contains("mpeg")) {
//Because mpeg version number is only included in the detail
//description, it is necessary to manually extract this information
//in order to match the mime type of mpeg4.
const GValue *value = gst_structure_get_value(structure, "mpegversion");
if (value) {
gchar *str = gst_value_serialize (value);
QString versions(str);
QStringList elements = versions.split(QRegExp("\\D+"), QString::SkipEmptyParts);
foreach(const QString &e, elements)
m_supportedMimeTypeSet.insert(nameLowcase + e);
g_free (str);
}
}
}
}
}
}
gst_object_unref (factory);
}
} else if (GST_IS_TYPE_FIND_FACTORY(feature)) {
QString name(gst_plugin_feature_get_name(feature));
if (name.contains('/')) //filter out any string without '/' which is obviously not a mime type
m_supportedMimeTypeSet.insert(name.toLower());
}
}
features = g_list_next (features);
}
gst_plugin_feature_list_free (orig_features);
}
gst_plugin_list_free (orig_plugins);
#if defined QT_SUPPORTEDMIMETYPES_DEBUG
QStringList list = m_supportedMimeTypeSet.toList();
list.sort();
if (qgetenv("QT_DEBUG_PLUGINS").toInt() > 0) {
foreach(const QString &type, list)
qDebug() << type;
}
#endif
}
QStringList QGstreamerServicePlugin::supportedMimeTypes() const
{
return QStringList();
}
Q_EXPORT_PLUGIN2(qtmedia_gstengine, QGstreamerServicePlugin);

View File

@@ -0,0 +1,86 @@
/****************************************************************************
**
** 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 QGSTREAMERSERVICEPLUGIN_H
#define QGSTREAMERSERVICEPLUGIN_H
#include <qmediaserviceproviderplugin.h>
#include <QtCore/qset.h>
QT_USE_NAMESPACE
class QGstreamerServicePlugin
: public QMediaServiceProviderPlugin
, public QMediaServiceSupportedDevicesInterface
, public QMediaServiceFeaturesInterface
, public QMediaServiceSupportedFormatsInterface
{
Q_OBJECT
Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
Q_INTERFACES(QMediaServiceFeaturesInterface)
Q_INTERFACES(QMediaServiceSupportedFormatsInterface)
public:
QStringList keys() const;
QMediaService* create(QString const& key);
void release(QMediaService *service);
QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const;
QList<QByteArray> devices(const QByteArray &service) const;
QString deviceDescription(const QByteArray &service, const QByteArray &device);
QVariant deviceProperty(const QByteArray &service, const QByteArray &device, const QByteArray &property);
QtMultimediaKit::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const;
QStringList supportedMimeTypes() const;
private:
void updateDevices() const;
mutable QList<QByteArray> m_cameraDevices;
mutable QStringList m_cameraDescriptions;
mutable QSet<QString> m_supportedMimeTypeSet; //for fast access
void updateSupportedMimeTypes() const;
};
#endif // QGSTREAMERSERVICEPLUGIN_H

View File

@@ -0,0 +1,162 @@
/****************************************************************************
**
** 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 "qgstreamervideoinputdevicecontrol.h"
#include <QtGui/QIcon>
#include <QtCore/QDir>
#include <QtCore/QDebug>
#include <linux/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
QGstreamerVideoInputDeviceControl::QGstreamerVideoInputDeviceControl(QObject *parent)
:QVideoDeviceControl(parent), m_selectedDevice(0)
{
update();
}
QGstreamerVideoInputDeviceControl::~QGstreamerVideoInputDeviceControl()
{
}
int QGstreamerVideoInputDeviceControl::deviceCount() const
{
return m_names.size();
}
QString QGstreamerVideoInputDeviceControl::deviceName(int index) const
{
return m_names[index];
}
QString QGstreamerVideoInputDeviceControl::deviceDescription(int index) const
{
return m_descriptions[index];
}
QIcon QGstreamerVideoInputDeviceControl::deviceIcon(int index) const
{
Q_UNUSED(index);
return QIcon();
}
int QGstreamerVideoInputDeviceControl::defaultDevice() const
{
return 0;
}
int QGstreamerVideoInputDeviceControl::selectedDevice() const
{
return m_selectedDevice;
}
void QGstreamerVideoInputDeviceControl::setSelectedDevice(int index)
{
if (index != m_selectedDevice) {
m_selectedDevice = index;
emit selectedDeviceChanged(index);
emit selectedDeviceChanged(deviceName(index));
}
}
void QGstreamerVideoInputDeviceControl::update()
{
m_names.clear();
m_descriptions.clear();
#ifdef Q_WS_MAEMO_6
m_names << QLatin1String("primary") << QLatin1String("secondary");
m_descriptions << tr("Main camera") << tr("Front camera");
#else
QDir devDir("/dev");
devDir.setFilter(QDir::System);
QFileInfoList entries = devDir.entryInfoList(QStringList() << "video*");
foreach( const QFileInfo &entryInfo, entries ) {
//qDebug() << "Try" << entryInfo.filePath();
int fd = ::open(entryInfo.filePath().toLatin1().constData(), O_RDWR );
if (fd == -1)
continue;
bool isCamera = false;
v4l2_input input;
memset(&input, 0, sizeof(input));
for (; ::ioctl(fd, VIDIOC_ENUMINPUT, &input) >= 0; ++input.index) {
if(input.type == V4L2_INPUT_TYPE_CAMERA || input.type == 0) {
isCamera = ::ioctl(fd, VIDIOC_S_INPUT, input.index) != 0;
break;
}
}
if (isCamera) {
// find out its driver "name"
QString name;
struct v4l2_capability vcap;
memset(&vcap, 0, sizeof(struct v4l2_capability));
if (ioctl(fd, VIDIOC_QUERYCAP, &vcap) != 0)
name = entryInfo.fileName();
else
name = QString((const char*)vcap.card);
//qDebug() << "found camera: " << name;
m_names.append(entryInfo.filePath());
m_descriptions.append(name);
}
::close(fd);
}
#endif
}

View File

@@ -0,0 +1,77 @@
/****************************************************************************
**
** 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 QGSTREAMERVIDEOINPUTDEVICECONTROL_H
#define QGSTREAMERVIDEOINPUTDEVICECONTROL_H
#include <qvideodevicecontrol.h>
#include <QtCore/qstringlist.h>
QT_USE_NAMESPACE
class QGstreamerVideoInputDeviceControl : public QVideoDeviceControl
{
Q_OBJECT
public:
QGstreamerVideoInputDeviceControl(QObject *parent);
~QGstreamerVideoInputDeviceControl();
int deviceCount() const;
QString deviceName(int index) const;
QString deviceDescription(int index) const;
QIcon deviceIcon(int index) const;
int defaultDevice() const;
int selectedDevice() const;
public Q_SLOTS:
void setSelectedDevice(int index);
private:
void update();
int m_selectedDevice;
QStringList m_names;
QStringList m_descriptions;
};
#endif // QGSTREAMERAUDIOINPUTDEVICECONTROL_H

View File

@@ -0,0 +1,232 @@
/****************************************************************************
**
** 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 "qgstreamervideooverlay.h"
#include "qvideosurfacegstsink.h"
#include <qvideosurfaceformat.h>
#include "qx11videosurface.h"
#ifndef QT_NO_XVIDEO
QGstreamerVideoOverlay::QGstreamerVideoOverlay(QObject *parent)
: QVideoWindowControl(parent)
, m_surface(new QX11VideoSurface)
, m_videoSink(reinterpret_cast<GstElement*>(QVideoSurfaceGstSink::createSink(m_surface)))
, m_aspectRatioMode(Qt::KeepAspectRatio)
, m_fullScreen(false)
{
if (m_videoSink) {
gst_object_ref(GST_OBJECT(m_videoSink)); //Take ownership
gst_object_sink(GST_OBJECT(m_videoSink));
}
connect(m_surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)),
this, SLOT(surfaceFormatChanged()));
}
QGstreamerVideoOverlay::~QGstreamerVideoOverlay()
{
if (m_videoSink)
gst_object_unref(GST_OBJECT(m_videoSink));
delete m_surface;
}
WId QGstreamerVideoOverlay::winId() const
{
return m_surface->winId();
}
void QGstreamerVideoOverlay::setWinId(WId id)
{
bool wasReady = isReady();
m_surface->setWinId(id);
if (isReady() != wasReady)
emit readyChanged(!wasReady);
}
QRect QGstreamerVideoOverlay::displayRect() const
{
return m_displayRect;
}
void QGstreamerVideoOverlay::setDisplayRect(const QRect &rect)
{
m_displayRect = rect;
setScaledDisplayRect();
}
Qt::AspectRatioMode QGstreamerVideoOverlay::aspectRatioMode() const
{
return m_aspectRatioMode;
}
void QGstreamerVideoOverlay::setAspectRatioMode(Qt::AspectRatioMode mode)
{
m_aspectRatioMode = mode;
setScaledDisplayRect();
}
void QGstreamerVideoOverlay::repaint()
{
}
int QGstreamerVideoOverlay::brightness() const
{
return m_surface->brightness();
}
void QGstreamerVideoOverlay::setBrightness(int brightness)
{
m_surface->setBrightness(brightness);
emit brightnessChanged(m_surface->brightness());
}
int QGstreamerVideoOverlay::contrast() const
{
return m_surface->contrast();
}
void QGstreamerVideoOverlay::setContrast(int contrast)
{
m_surface->setContrast(contrast);
emit contrastChanged(m_surface->contrast());
}
int QGstreamerVideoOverlay::hue() const
{
return m_surface->hue();
}
void QGstreamerVideoOverlay::setHue(int hue)
{
m_surface->setHue(hue);
emit hueChanged(m_surface->hue());
}
int QGstreamerVideoOverlay::saturation() const
{
return m_surface->saturation();
}
void QGstreamerVideoOverlay::setSaturation(int saturation)
{
m_surface->setSaturation(saturation);
emit saturationChanged(m_surface->saturation());
}
bool QGstreamerVideoOverlay::isFullScreen() const
{
return m_fullScreen;
}
void QGstreamerVideoOverlay::setFullScreen(bool fullScreen)
{
emit fullScreenChanged(m_fullScreen = fullScreen);
}
QSize QGstreamerVideoOverlay::nativeSize() const
{
return m_surface->surfaceFormat().sizeHint();
}
QAbstractVideoSurface *QGstreamerVideoOverlay::surface() const
{
return m_surface;
}
GstElement *QGstreamerVideoOverlay::videoSink()
{
return m_videoSink;
}
void QGstreamerVideoOverlay::surfaceFormatChanged()
{
setScaledDisplayRect();
emit nativeSizeChanged();
}
void QGstreamerVideoOverlay::setScaledDisplayRect()
{
QRect formatViewport = m_surface->surfaceFormat().viewport();
switch (m_aspectRatioMode) {
case Qt::KeepAspectRatio:
{
QSize size = m_surface->surfaceFormat().sizeHint();
size.scale(m_displayRect.size(), Qt::KeepAspectRatio);
QRect rect(QPoint(0, 0), size);
rect.moveCenter(m_displayRect.center());
m_surface->setDisplayRect(rect);
m_surface->setViewport(formatViewport);
}
break;
case Qt::IgnoreAspectRatio:
m_surface->setDisplayRect(m_displayRect);
m_surface->setViewport(formatViewport);
break;
case Qt::KeepAspectRatioByExpanding:
{
QSize size = m_displayRect.size();
size.scale(m_surface->surfaceFormat().sizeHint(), Qt::KeepAspectRatio);
QRect viewport(QPoint(0, 0), size);
viewport.moveCenter(formatViewport.center());
m_surface->setDisplayRect(m_displayRect);
m_surface->setViewport(viewport);
}
break;
};
}
#endif //QT_NO_XVIDEO

View File

@@ -0,0 +1,119 @@
/****************************************************************************
**
** 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 QGSTREAMERVIDEOOVERLAY_H
#define QGSTREAMERVIDEOOVERLAY_H
#include <qvideowindowcontrol.h>
#include "qgstreamervideorendererinterface.h"
QT_BEGIN_NAMESPACE
class QAbstractVideoSurface;
QT_END_NAMESPACE
class QX11VideoSurface;
#if defined(Q_WS_X11) && !defined(QT_NO_XVIDEO)
QT_USE_NAMESPACE
class QGstreamerVideoOverlay : public QVideoWindowControl, public QGstreamerVideoRendererInterface
{
Q_OBJECT
Q_INTERFACES(QGstreamerVideoRendererInterface)
public:
QGstreamerVideoOverlay(QObject *parent = 0);
~QGstreamerVideoOverlay();
WId winId() const;
void setWinId(WId id);
QRect displayRect() const;
void setDisplayRect(const QRect &rect);
bool isFullScreen() const;
void setFullScreen(bool fullScreen);
QSize nativeSize() const;
Qt::AspectRatioMode aspectRatioMode() const;
void setAspectRatioMode(Qt::AspectRatioMode mode);
void repaint();
int brightness() const;
void setBrightness(int brightness);
int contrast() const;
void setContrast(int contrast);
int hue() const;
void setHue(int hue);
int saturation() const;
void setSaturation(int saturation);
QAbstractVideoSurface *surface() const;
GstElement *videoSink();
bool isReady() const { return winId() != 0; }
signals:
void sinkChanged();
void readyChanged(bool);
private slots:
void surfaceFormatChanged();
private:
void setScaledDisplayRect();
QX11VideoSurface *m_surface;
GstElement *m_videoSink;
Qt::AspectRatioMode m_aspectRatioMode;
QRect m_displayRect;
bool m_fullScreen;
};
#endif //QT_NO_XVIDEO
#endif

View File

@@ -0,0 +1,120 @@
/****************************************************************************
**
** 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 "qgstreamervideorenderer.h"
#include "qvideosurfacegstsink.h"
#include "qabstractvideosurface.h"
#include <QEvent>
#include <QApplication>
#include <QDebug>
#include <gst/gst.h>
QGstreamerVideoRenderer::QGstreamerVideoRenderer(QObject *parent)
:QVideoRendererControl(parent),m_videoSink(0), m_surface(0)
{
}
QGstreamerVideoRenderer::~QGstreamerVideoRenderer()
{
if (m_videoSink)
gst_object_unref(GST_OBJECT(m_videoSink));
}
GstElement *QGstreamerVideoRenderer::videoSink()
{
if (!m_videoSink && m_surface) {
m_videoSink = QVideoSurfaceGstSink::createSink(m_surface);
gst_object_ref(GST_OBJECT(m_videoSink)); //Take ownership
gst_object_sink(GST_OBJECT(m_videoSink));
}
return reinterpret_cast<GstElement*>(m_videoSink);
}
QAbstractVideoSurface *QGstreamerVideoRenderer::surface() const
{
return m_surface;
}
void QGstreamerVideoRenderer::setSurface(QAbstractVideoSurface *surface)
{
if (m_surface != surface) {
//qDebug() << Q_FUNC_INFO << surface;
if (m_videoSink)
gst_object_unref(GST_OBJECT(m_videoSink));
m_videoSink = 0;
if (m_surface) {
disconnect(m_surface, SIGNAL(supportedFormatsChanged()),
this, SLOT(handleFormatChange()));
}
m_surface = surface;
if (surface && !m_surface)
emit readyChanged(true);
if (!surface && m_surface)
emit readyChanged(false);
if (m_surface) {
connect(m_surface, SIGNAL(supportedFormatsChanged()),
this, SLOT(handleFormatChange()));
}
emit sinkChanged();
}
}
void QGstreamerVideoRenderer::handleFormatChange()
{
//qDebug() << "Supported formats list has changed, reload video output";
if (m_videoSink)
gst_object_unref(GST_OBJECT(m_videoSink));
m_videoSink = 0;
emit sinkChanged();
}

View File

@@ -0,0 +1,80 @@
/****************************************************************************
**
** 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 QGSTREAMERVIDEORENDERER_H
#define QGSTREAMERVIDEORENDERER_H
#include <qvideorenderercontrol.h>
#include "qvideosurfacegstsink.h"
#include "qgstreamervideorendererinterface.h"
QT_USE_NAMESPACE
class QGstreamerVideoRenderer : public QVideoRendererControl, public QGstreamerVideoRendererInterface
{
Q_OBJECT
Q_INTERFACES(QGstreamerVideoRendererInterface)
public:
QGstreamerVideoRenderer(QObject *parent = 0);
virtual ~QGstreamerVideoRenderer();
QAbstractVideoSurface *surface() const;
void setSurface(QAbstractVideoSurface *surface);
GstElement *videoSink();
void precessNewStream() {}
bool isReady() const { return m_surface != 0; }
signals:
void sinkChanged();
void readyChanged(bool);
private slots:
void handleFormatChange();
private:
QVideoSurfaceGstSink *m_videoSink;
QAbstractVideoSurface *m_surface;
};
#endif // QGSTREAMERVIDEORENDRER_H

View File

@@ -0,0 +1,46 @@
/****************************************************************************
**
** 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 "qgstreamervideorendererinterface.h"
QGstreamerVideoRendererInterface::~QGstreamerVideoRendererInterface()
{
}

Some files were not shown because too many files have changed in this diff Show More