Initial copy of QtMultimediaKit.
Comes from original repo, with SHA1: 2c82d5611655e5967f5c5095af50c0991c4378b2
This commit is contained in:
27
src/plugins/gstreamer/mediacapture/mediacapture.pri
Normal file
27
src/plugins/gstreamer/mediacapture/mediacapture.pri
Normal 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
|
||||
292
src/plugins/gstreamer/mediacapture/qgstreameraudioencode.cpp
Normal file
292
src/plugins/gstreamer/mediacapture/qgstreameraudioencode.cpp
Normal 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);
|
||||
}
|
||||
97
src/plugins/gstreamer/mediacapture/qgstreameraudioencode.h
Normal file
97
src/plugins/gstreamer/mediacapture/qgstreameraudioencode.h
Normal 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
|
||||
185
src/plugins/gstreamer/mediacapture/qgstreamercameracontrol.cpp
Normal file
185
src/plugins/gstreamer/mediacapture/qgstreamercameracontrol.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
98
src/plugins/gstreamer/mediacapture/qgstreamercameracontrol.h
Normal file
98
src/plugins/gstreamer/mediacapture/qgstreamercameracontrol.h
Normal 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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
185
src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp
Normal file
185
src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
1051
src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp
Normal file
1051
src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp
Normal file
File diff suppressed because it is too large
Load Diff
211
src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h
Normal file
211
src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h
Normal 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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
90
src/plugins/gstreamer/mediacapture/qgstreamerimageencode.cpp
Normal file
90
src/plugins/gstreamer/mediacapture/qgstreamerimageencode.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
80
src/plugins/gstreamer/mediacapture/qgstreamerimageencode.h
Normal file
80
src/plugins/gstreamer/mediacapture/qgstreamerimageencode.h
Normal 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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
289
src/plugins/gstreamer/mediacapture/qgstreamerrecordercontrol.cpp
Normal file
289
src/plugins/gstreamer/mediacapture/qgstreamerrecordercontrol.cpp
Normal 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);
|
||||
}
|
||||
@@ -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
|
||||
297
src/plugins/gstreamer/mediacapture/qgstreamerv4l2input.cpp
Normal file
297
src/plugins/gstreamer/mediacapture/qgstreamerv4l2input.cpp
Normal 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;
|
||||
}
|
||||
83
src/plugins/gstreamer/mediacapture/qgstreamerv4l2input.h
Normal file
83
src/plugins/gstreamer/mediacapture/qgstreamerv4l2input.h
Normal 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
|
||||
331
src/plugins/gstreamer/mediacapture/qgstreamervideoencode.cpp
Normal file
331
src/plugins/gstreamer/mediacapture/qgstreamervideoencode.cpp
Normal 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);
|
||||
}
|
||||
98
src/plugins/gstreamer/mediacapture/qgstreamervideoencode.h
Normal file
98
src/plugins/gstreamer/mediacapture/qgstreamervideoencode.h
Normal 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
|
||||
Reference in New Issue
Block a user