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,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