Initial copy of QtMultimediaKit.

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

View File

@@ -0,0 +1,25 @@
load(qt_module)
TARGET = qtmedia_audioengine
QT += multimediakit-private
PLUGIN_TYPE=mediaservice
load(qt_plugin)
DESTDIR = $$QT.multimediakit.plugins/$${PLUGIN_TYPE}
# Input
HEADERS += audioencodercontrol.h \
audiocontainercontrol.h \
audiomediarecordercontrol.h \
audioendpointselector.h \
audiocaptureservice.h \
audiocaptureserviceplugin.h \
audiocapturesession.h
SOURCES += audioencodercontrol.cpp \
audiocontainercontrol.cpp \
audiomediarecordercontrol.cpp \
audioendpointselector.cpp \
audiocaptureservice.cpp \
audiocaptureserviceplugin.cpp \
audiocapturesession.cpp

View File

@@ -0,0 +1,90 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "audiocaptureservice.h"
#include "audiocapturesession.h"
#include "audioendpointselector.h"
#include "audioencodercontrol.h"
#include "audiocontainercontrol.h"
#include "audiomediarecordercontrol.h"
AudioCaptureService::AudioCaptureService(QObject *parent):
QMediaService(parent)
{
m_session = new AudioCaptureSession(this);
m_encoderControl = new AudioEncoderControl(m_session);
m_containerControl = new AudioContainerControl(m_session);
m_mediaControl = new AudioMediaRecorderControl(m_session);
m_endpointSelector = new AudioEndpointSelector(m_session);
}
AudioCaptureService::~AudioCaptureService()
{
delete m_encoderControl;
delete m_containerControl;
delete m_endpointSelector;
delete m_mediaControl;
delete m_session;
}
QMediaControl *AudioCaptureService::requestControl(const char *name)
{
if (qstrcmp(name,QMediaRecorderControl_iid) == 0)
return m_mediaControl;
if (qstrcmp(name,QAudioEncoderControl_iid) == 0)
return m_encoderControl;
if (qstrcmp(name,QAudioEndpointSelector_iid) == 0)
return m_endpointSelector;
if (qstrcmp(name,QMediaContainerControl_iid) == 0)
return m_containerControl;
return 0;
}
void AudioCaptureService::releaseControl(QMediaControl *control)
{
Q_UNUSED(control)
}

View File

@@ -0,0 +1,74 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef AUDIOCAPTURESERVICE_H
#define AUDIOCAPTURESERVICE_H
#include <QtCore/qobject.h>
#include "qmediaservice.h"
class AudioCaptureSession;
class AudioEncoderControl;
class AudioContainerControl;
class AudioMediaRecorderControl;
class AudioEndpointSelector;
QT_USE_NAMESPACE
class AudioCaptureService : public QMediaService
{
Q_OBJECT
public:
AudioCaptureService(QObject *parent = 0);
~AudioCaptureService();
QMediaControl *requestControl(const char *interface);
void releaseControl(QMediaControl *control);
private:
AudioCaptureSession *m_session;
AudioEncoderControl *m_encoderControl;
AudioContainerControl *m_containerControl;
AudioEndpointSelector *m_endpointSelector;
AudioMediaRecorderControl *m_mediaControl;
};
#endif

View File

@@ -0,0 +1,69 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/qstring.h>
#include "audiocaptureserviceplugin.h"
#include "audiocaptureservice.h"
#include "qmediaserviceprovider.h"
QStringList AudioCaptureServicePlugin::keys() const
{
return QStringList() << QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE);
}
QMediaService* AudioCaptureServicePlugin::create(QString const& key)
{
if (key == QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE))
return new AudioCaptureService;
return 0;
}
void AudioCaptureServicePlugin::release(QMediaService *service)
{
delete service;
}
Q_EXPORT_PLUGIN2(qtmedia_audioengine, AudioCaptureServicePlugin);

View File

@@ -0,0 +1,60 @@
/****************************************************************************
**
** 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 AUDIOCAPTURESERVICEPLUGIN_H
#define AUDIOCAPTURESERVICEPLUGIN_H
#include "qmediaserviceproviderplugin.h"
QT_USE_NAMESPACE
class AudioCaptureServicePlugin : public QMediaServiceProviderPlugin
{
Q_OBJECT
public:
QStringList keys() const;
QMediaService* create(QString const& key);
void release(QMediaService *service);
};
#endif // AUDIOCAPTURESERVICEPLUGIN_H

View File

@@ -0,0 +1,358 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/qdebug.h>
#include <QtCore/qurl.h>
#include <QtCore/qdir.h>
#include <qaudiodeviceinfo.h>
#include "qmediarecorder.h"
#include "audiocapturesession.h"
AudioCaptureSession::AudioCaptureSession(QObject *parent):
QObject(parent)
{
m_deviceInfo = new QAudioDeviceInfo(QAudioDeviceInfo::defaultInputDevice());
m_audioInput = 0;
m_position = 0;
m_state = QMediaRecorder::StoppedState;
m_format.setFrequency(8000);
m_format.setChannels(1);
m_format.setSampleSize(8);
m_format.setSampleType(QAudioFormat::UnSignedInt);
m_format.setCodec("audio/pcm");
wavFile = true;
}
AudioCaptureSession::~AudioCaptureSession()
{
stop();
if(m_audioInput)
delete m_audioInput;
}
QAudioDeviceInfo* AudioCaptureSession::deviceInfo() const
{
return m_deviceInfo;
}
QAudioFormat AudioCaptureSession::format() const
{
return m_format;
}
bool AudioCaptureSession::isFormatSupported(const QAudioFormat &format) const
{
if(m_deviceInfo) {
if(format.codec().contains(QLatin1String("audio/x-wav"))) {
QAudioFormat fmt = format;
fmt.setCodec("audio/pcm");
return m_deviceInfo->isFormatSupported(fmt);
} else
return m_deviceInfo->isFormatSupported(format);
}
return false;
}
bool AudioCaptureSession::setFormat(const QAudioFormat &format)
{
if(m_deviceInfo) {
QAudioFormat fmt = format;
if(m_deviceInfo->isFormatSupported(fmt)) {
m_format = fmt;
if(m_audioInput) delete m_audioInput;
m_audioInput = 0;
QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
for(int i=0;i<devices.size();i++) {
if(qstrcmp(m_deviceInfo->deviceName().toLocal8Bit().constData(),
devices.at(i).deviceName().toLocal8Bit().constData()) == 0) {
m_audioInput = new QAudioInput(devices.at(i),m_format);
connect(m_audioInput,SIGNAL(stateChanged(QAudio::State)),this,SLOT(stateChanged(QAudio::State)));
connect(m_audioInput,SIGNAL(notify()),this,SLOT(notify()));
break;
}
}
} else {
m_format = m_deviceInfo->preferredFormat();
qWarning()<<"failed to setFormat using preferred...";
}
}
return false;
}
QStringList AudioCaptureSession::supportedContainers() const
{
QStringList list;
if(m_deviceInfo) {
if (m_deviceInfo->supportedCodecs().size() > 0) {
list << "audio/x-wav";
list << "audio/pcm";
}
}
return list;
}
QString AudioCaptureSession::containerDescription(const QString &formatMimeType) const
{
if(m_deviceInfo) {
if (formatMimeType.contains(QLatin1String("audio/pcm")))
return tr("RAW file format");
if (formatMimeType.contains(QLatin1String("audio/x-wav")))
return tr("WAV file format");
}
return QString();
}
void AudioCaptureSession::setContainerMimeType(const QString &formatMimeType)
{
if (!formatMimeType.contains(QLatin1String("audio/x-wav")) &&
!formatMimeType.contains(QLatin1String("audio/pcm")) &&
!formatMimeType.isEmpty())
return;
if(m_deviceInfo) {
if (!m_deviceInfo->supportedCodecs().contains(QLatin1String("audio/pcm")))
return;
if (formatMimeType.isEmpty() || formatMimeType.contains(QLatin1String("audio/x-wav"))) {
wavFile = true;
m_format.setCodec("audio/pcm");
} else {
wavFile = false;
m_format.setCodec(formatMimeType);
}
}
}
QString AudioCaptureSession::containerMimeType() const
{
if(wavFile)
return QString("audio/x-wav");
return QString("audio/pcm");
}
QUrl AudioCaptureSession::outputLocation() const
{
return m_actualSink;
}
bool AudioCaptureSession::setOutputLocation(const QUrl& sink)
{
m_sink = m_actualSink = sink;
return true;
}
qint64 AudioCaptureSession::position() const
{
return m_position;
}
int AudioCaptureSession::state() const
{
return int(m_state);
}
QDir AudioCaptureSession::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 AudioCaptureSession::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);
}
void AudioCaptureSession::record()
{
if(!m_audioInput) {
setFormat(m_format);
}
m_actualSink = m_sink;
if (m_actualSink.isEmpty()) {
QString ext = wavFile ? QLatin1String("wav") : QLatin1String("raw");
m_actualSink = generateFileName(defaultDir(), ext);
}
if(m_actualSink.toLocalFile().length() > 0)
file.setFileName(m_actualSink.toLocalFile());
else
file.setFileName(m_actualSink.toString());
if(m_audioInput) {
if(m_state == QMediaRecorder::StoppedState) {
if(file.open(QIODevice::WriteOnly)) {
memset(&header,0,sizeof(CombinedHeader));
memcpy(header.riff.descriptor.id,"RIFF",4);
header.riff.descriptor.size = 0xFFFFFFFF; // This should be updated on stop(), filesize-8
memcpy(header.riff.type,"WAVE",4);
memcpy(header.wave.descriptor.id,"fmt ",4);
header.wave.descriptor.size = 16;
header.wave.audioFormat = 1; // for PCM data
header.wave.numChannels = m_format.channels();
header.wave.sampleRate = m_format.frequency();
header.wave.byteRate = m_format.frequency()*m_format.channels()*m_format.sampleSize()/8;
header.wave.blockAlign = m_format.channels()*m_format.sampleSize()/8;
header.wave.bitsPerSample = m_format.sampleSize();
memcpy(header.data.descriptor.id,"data",4);
header.data.descriptor.size = 0xFFFFFFFF; // This should be updated on stop(),samples*channels*sampleSize/8
if (wavFile)
file.write((char*)&header,sizeof(CombinedHeader));
m_audioInput->start(qobject_cast<QIODevice*>(&file));
} else {
emit error(1,QString("can't open source, failed"));
m_state = QMediaRecorder::StoppedState;
emit stateChanged(m_state);
}
}
}
m_state = QMediaRecorder::RecordingState;
}
void AudioCaptureSession::pause()
{
if(m_audioInput)
m_audioInput->stop();
m_state = QMediaRecorder::PausedState;
}
void AudioCaptureSession::stop()
{
if(m_audioInput) {
m_audioInput->stop();
file.close();
if (wavFile) {
qint32 fileSize = file.size()-8;
file.open(QIODevice::ReadWrite | QIODevice::Unbuffered);
file.read((char*)&header,sizeof(CombinedHeader));
header.riff.descriptor.size = fileSize; // filesize-8
header.data.descriptor.size = fileSize-44; // samples*channels*sampleSize/8
file.seek(0);
file.write((char*)&header,sizeof(CombinedHeader));
file.close();
}
m_position = 0;
}
m_state = QMediaRecorder::StoppedState;
}
void AudioCaptureSession::stateChanged(QAudio::State state)
{
switch(state) {
case QAudio::ActiveState:
emit stateChanged(QMediaRecorder::RecordingState);
break;
default:
if(!((m_state == QMediaRecorder::PausedState)||(m_state == QMediaRecorder::StoppedState)))
m_state = QMediaRecorder::StoppedState;
emit stateChanged(m_state);
break;
}
}
void AudioCaptureSession::notify()
{
m_position += m_audioInput->notifyInterval();
emit positionChanged(m_position);
}
void AudioCaptureSession::setCaptureDevice(const QString &deviceName)
{
m_captureDevice = deviceName;
if(m_deviceInfo)
delete m_deviceInfo;
m_deviceInfo = 0;
QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
for(int i = 0; i < devices.size(); i++) {
if(qstrcmp(m_captureDevice.toLocal8Bit().constData(),
devices.at(i).deviceName().toLocal8Bit().constData())==0){
m_deviceInfo = new QAudioDeviceInfo(QAudioDeviceInfo::defaultInputDevice());
return;
}
}
m_deviceInfo = new QAudioDeviceInfo(QAudioDeviceInfo::defaultInputDevice());
}

View File

@@ -0,0 +1,152 @@
/****************************************************************************
**
** 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 AUDIOCAPTURESESSION_H
#define AUDIOCAPTURESESSION_H
#include <QFile>
#include <QUrl>
#include <QDir>
#include "audioencodercontrol.h"
#include "audioendpointselector.h"
#include "audiomediarecordercontrol.h"
#include <qaudioformat.h>
#include <qaudioinput.h>
#include <qaudiodeviceinfo.h>
QT_USE_NAMESPACE
class AudioCaptureSession : public QObject
{
Q_OBJECT
public:
AudioCaptureSession(QObject *parent = 0);
~AudioCaptureSession();
QAudioFormat format() const;
QAudioDeviceInfo* deviceInfo() const;
bool isFormatSupported(const QAudioFormat &format) const;
bool setFormat(const QAudioFormat &format);
QStringList supportedContainers() const;
QString containerMimeType() const;
void setContainerMimeType(const QString &formatMimeType);
QString containerDescription(const QString &formatMimeType) const;
QUrl outputLocation() const;
bool setOutputLocation(const QUrl& sink);
qint64 position() const;
int state() const;
void record();
void pause();
void stop();
public slots:
void setCaptureDevice(const QString &deviceName);
signals:
void stateChanged(QMediaRecorder::State state);
void positionChanged(qint64 position);
void error(int error, const QString &errorString);
private slots:
void stateChanged(QAudio::State state);
void notify();
private:
QDir defaultDir() const;
QString generateFileName(const QDir &dir, const QString &ext) const;
QFile file;
QString m_captureDevice;
QUrl m_sink;
QUrl m_actualSink;
QMediaRecorder::State m_state;
QAudioInput *m_audioInput;
QAudioDeviceInfo *m_deviceInfo;
QAudioFormat m_format;
qint64 m_position;
bool wavFile;
// WAV header stuff
struct chunk
{
char id[4];
quint32 size;
};
struct RIFFHeader
{
chunk descriptor;
char type[4];
};
struct WAVEHeader
{
chunk descriptor;
quint16 audioFormat; // PCM = 1
quint16 numChannels;
quint32 sampleRate;
quint32 byteRate;
quint16 blockAlign;
quint16 bitsPerSample;
};
struct DATAHeader
{
chunk descriptor;
// quint8 data[];
};
struct CombinedHeader
{
RIFFHeader riff;
WAVEHeader wave;
DATAHeader data;
};
CombinedHeader header;
};
#endif

View File

@@ -0,0 +1,74 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "audiocontainercontrol.h"
#include "audiocapturesession.h"
AudioContainerControl::AudioContainerControl(QObject *parent)
:QMediaContainerControl(parent)
{
m_session = qobject_cast<AudioCaptureSession*>(parent);
}
AudioContainerControl::~AudioContainerControl()
{
}
QStringList AudioContainerControl::supportedContainers() const
{
return m_session->supportedContainers();
}
QString AudioContainerControl::containerMimeType() const
{
return m_session->containerMimeType();
}
void AudioContainerControl::setContainerMimeType(const QString &formatMimeType)
{
m_session->setContainerMimeType(formatMimeType);
}
QString AudioContainerControl::containerDescription(const QString &formatMimeType) const
{
return m_session->containerDescription(formatMimeType);
}

View File

@@ -0,0 +1,70 @@
/****************************************************************************
**
** 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 AUDIOCONTAINERCONTROL_H
#define AUDIOCONTAINERCONTROL_H
#include "qmediacontainercontrol.h"
#include <QtCore/qstringlist.h>
#include <QtCore/qmap.h>
class AudioCaptureSession;
QT_USE_NAMESPACE
class AudioContainerControl : public QMediaContainerControl
{
Q_OBJECT
public:
AudioContainerControl(QObject *parent);
virtual ~AudioContainerControl();
QStringList supportedContainers() const;
QString containerMimeType() const;
void setContainerMimeType(const QString &formatMimeType);
QString containerDescription(const QString &formatMimeType) const;
private:
AudioCaptureSession* m_session;
};
#endif

View File

@@ -0,0 +1,168 @@
/****************************************************************************
**
** 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 "audioencodercontrol.h"
#include "audiocapturesession.h"
#include <qaudioformat.h>
#include <QtCore/qdebug.h>
AudioEncoderControl::AudioEncoderControl(QObject *parent)
:QAudioEncoderControl(parent)
{
m_session = qobject_cast<AudioCaptureSession*>(parent);
QT_PREPEND_NAMESPACE(QAudioFormat) fmt;
fmt.setSampleSize(8);
fmt.setChannels(1);
fmt.setFrequency(8000);
fmt.setSampleType(QT_PREPEND_NAMESPACE(QAudioFormat)::SignedInt);
fmt.setCodec("audio/pcm");
fmt.setByteOrder(QAudioFormat::LittleEndian);
m_session->setFormat(fmt);
m_settings.setEncodingMode(QtMultimediaKit::ConstantQualityEncoding);
m_settings.setCodec("audio/pcm");
m_settings.setBitRate(8000);
m_settings.setChannelCount(1);
m_settings.setSampleRate(8000);
m_settings.setQuality(QtMultimediaKit::LowQuality);
}
AudioEncoderControl::~AudioEncoderControl()
{
}
QStringList AudioEncoderControl::supportedAudioCodecs() const
{
QStringList list;
if (m_session->supportedContainers().size() > 0)
list.append("audio/pcm");
return list;
}
QString AudioEncoderControl::codecDescription(const QString &codecName) const
{
if (codecName.contains(QLatin1String("audio/pcm")))
return tr("PCM audio data");
return QString();
}
QStringList AudioEncoderControl::supportedEncodingOptions(const QString &codec) const
{
Q_UNUSED(codec)
QStringList list;
return list;
}
QVariant AudioEncoderControl::encodingOption(const QString &codec, const QString &name) const
{
Q_UNUSED(codec)
Q_UNUSED(name)
return QVariant();
}
void AudioEncoderControl::setEncodingOption(
const QString &codec, const QString &name, const QVariant &value)
{
Q_UNUSED(value)
Q_UNUSED(codec)
Q_UNUSED(name)
}
QList<int> AudioEncoderControl::supportedSampleRates(const QAudioEncoderSettings &, bool *continuous) const
{
if (continuous)
*continuous = false;
return m_session->deviceInfo()->supportedFrequencies();
}
QAudioEncoderSettings AudioEncoderControl::audioSettings() const
{
return m_settings;
}
void AudioEncoderControl::setAudioSettings(const QAudioEncoderSettings &settings)
{
QAudioFormat fmt = m_session->format();
if (settings.encodingMode() == QtMultimediaKit::ConstantQualityEncoding) {
if (settings.quality() == QtMultimediaKit::LowQuality) {
fmt.setSampleSize(8);
fmt.setChannels(1);
fmt.setFrequency(8000);
fmt.setSampleType(QAudioFormat::UnSignedInt);
} else if (settings.quality() == QtMultimediaKit::NormalQuality) {
fmt.setSampleSize(16);
fmt.setChannels(1);
fmt.setFrequency(22050);
fmt.setSampleType(QAudioFormat::SignedInt);
} else {
fmt.setSampleSize(16);
fmt.setChannels(1);
fmt.setFrequency(44100);
fmt.setSampleType(QAudioFormat::SignedInt);
}
} else {
fmt.setChannels(settings.channelCount());
fmt.setFrequency(settings.sampleRate());
if (settings.sampleRate() == 8000 && settings.bitRate() == 8000) {
fmt.setSampleType(QAudioFormat::UnSignedInt);
fmt.setSampleSize(8);
} else {
fmt.setSampleSize(16);
fmt.setSampleType(QAudioFormat::SignedInt);
}
}
fmt.setCodec("audio/pcm");
m_session->setFormat(fmt);
m_settings = settings;
}

View File

@@ -0,0 +1,79 @@
/****************************************************************************
**
** 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 AUDIOENCODERCONTROL_H
#define AUDIOENCODERCONTROL_H
#include "qaudioencodercontrol.h"
#include <QtCore/qstringlist.h>
#include <QtCore/qmap.h>
#include <qaudioformat.h>
class AudioCaptureSession;
QT_USE_NAMESPACE
class AudioEncoderControl : public QAudioEncoderControl
{
Q_OBJECT
public:
AudioEncoderControl(QObject *parent);
virtual ~AudioEncoderControl();
QStringList supportedAudioCodecs() const;
QString codecDescription(const QString &codecName) const;
QList<int> supportedSampleRates(const QAudioEncoderSettings &, bool *continuous = 0) const;
QAudioEncoderSettings audioSettings() const;
void setAudioSettings(const QAudioEncoderSettings&);
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);
private:
AudioCaptureSession* m_session;
QAudioEncoderSettings m_settings;
};
#endif

View File

@@ -0,0 +1,110 @@
/****************************************************************************
**
** 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 "audiocapturesession.h"
#include "audioendpointselector.h"
#include <qaudiodeviceinfo.h>
AudioEndpointSelector::AudioEndpointSelector(QObject *parent)
:QAudioEndpointSelector(parent)
{
m_session = qobject_cast<AudioCaptureSession*>(parent);
update();
m_audioInput = defaultEndpoint();
}
AudioEndpointSelector::~AudioEndpointSelector()
{
}
QList<QString> AudioEndpointSelector::availableEndpoints() const
{
return m_names;
}
QString AudioEndpointSelector::endpointDescription(const QString& name) const
{
QString desc;
for(int i = 0; i < m_names.count(); i++) {
if (m_names.at(i).compare(name) == 0) {
desc = m_names.at(i);
break;
}
}
return desc;
}
QString AudioEndpointSelector::defaultEndpoint() const
{
return QAudioDeviceInfo(QAudioDeviceInfo::defaultInputDevice()).deviceName();
}
QString AudioEndpointSelector::activeEndpoint() const
{
return m_audioInput;
}
void AudioEndpointSelector::setActiveEndpoint(const QString& name)
{
if (m_audioInput.compare(name) != 0) {
m_audioInput = name;
m_session->setCaptureDevice(name);
emit activeEndpointChanged(name);
}
}
void AudioEndpointSelector::update()
{
m_names.clear();
m_descriptions.clear();
QList<QAudioDeviceInfo> devices;
devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
for(int i = 0; i < devices.size(); ++i) {
m_names.append(devices.at(i).deviceName());
m_descriptions.append(devices.at(i).deviceName());
}
}

View File

@@ -0,0 +1,77 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef AUDIOENDPOINTSELECTOR_H
#define AUDIOENDPOINTSELECTOR_H
#include <QStringList>
#include "qaudioendpointselector.h"
class AudioCaptureSession;
QT_USE_NAMESPACE
class AudioEndpointSelector : public QAudioEndpointSelector
{
Q_OBJECT
public:
AudioEndpointSelector(QObject *parent);
virtual ~AudioEndpointSelector();
QList<QString> availableEndpoints() const;
QString endpointDescription(const QString& name) const;
QString defaultEndpoint() const;
QString activeEndpoint() const;
public Q_SLOTS:
void setActiveEndpoint(const QString& name);
private:
void update();
QString m_audioInput;
QList<QString> m_names;
QList<QString> m_descriptions;
AudioCaptureSession* m_session;
};
#endif // AUDIOENDPOINTSELECTOR_H

View File

@@ -0,0 +1,102 @@
/****************************************************************************
**
** 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 "audiocapturesession.h"
#include "audiomediarecordercontrol.h"
#include <QtCore/qdebug.h>
AudioMediaRecorderControl::AudioMediaRecorderControl(QObject *parent)
:QMediaRecorderControl(parent)
{
m_session = qobject_cast<AudioCaptureSession*>(parent);
connect(m_session,SIGNAL(positionChanged(qint64)),this,SIGNAL(durationChanged(qint64)));
connect(m_session,SIGNAL(stateChanged(QMediaRecorder::State)),this,SIGNAL(stateChanged(QMediaRecorder::State)));
connect(m_session,SIGNAL(error(int,QString)),this,SIGNAL(error(int,QString)));
}
AudioMediaRecorderControl::~AudioMediaRecorderControl()
{
}
QUrl AudioMediaRecorderControl::outputLocation() const
{
return m_session->outputLocation();
}
bool AudioMediaRecorderControl::setOutputLocation(const QUrl& sink)
{
return m_session->setOutputLocation(sink);
}
QMediaRecorder::State AudioMediaRecorderControl::state() const
{
return (QMediaRecorder::State)m_session->state();
}
qint64 AudioMediaRecorderControl::duration() const
{
return m_session->position();
}
void AudioMediaRecorderControl::record()
{
m_session->record();
}
void AudioMediaRecorderControl::pause()
{
m_session->stop();
}
void AudioMediaRecorderControl::stop()
{
m_session->stop();
}
bool AudioMediaRecorderControl::isMuted() const
{
return false;
}
void AudioMediaRecorderControl::setMuted(bool)
{
}

View File

@@ -0,0 +1,82 @@
/****************************************************************************
**
** 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 AUDIOMEDIARECORDERCONTROL_H
#define AUDIOMEDIARECORDERCONTROL_H
#include <QtCore/qobject.h>
#include "qmediarecorder.h"
#include "qmediarecordercontrol.h"
class AudioCaptureSession;
QT_USE_NAMESPACE
class AudioMediaRecorderControl : public QMediaRecorderControl
{
Q_OBJECT
public:
AudioMediaRecorderControl(QObject *parent = 0);
~AudioMediaRecorderControl();
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:
AudioCaptureSession* m_session;
};
#endif

View File

@@ -0,0 +1,31 @@
INCLUDEPATH += $$PWD
DEFINES += QMEDIA_DIRECTSHOW_CAMERA
win32-g++: DEFINES += QT_NO_WMSDK
win32: DEFINES += _CRT_SECURE_NO_WARNINGS
HEADERS += \
$$PWD/dscameraservice.h \
$$PWD/dscameracontrol.h \
$$PWD/dsvideorenderer.h \
$$PWD/dsvideodevicecontrol.h \
$$PWD/dsimagecapturecontrol.h \
$$PWD/dscamerasession.h \
$$PWD/dsvideowidgetcontrol.h \
$$PWD/dscameraservice.h \
$$PWD/directshowglobal.h
SOURCES += \
$$PWD/dscameraservice.cpp \
$$PWD/dscameracontrol.cpp \
$$PWD/dsvideorenderer.cpp \
$$PWD/dsvideodevicecontrol.cpp \
$$PWD/dsimagecapturecontrol.cpp \
$$PWD/dscamerasession.cpp \
$$PWD/dsvideowidgetcontrol.cpp
INCLUDEPATH += $(DXSDK_DIR)/include
LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32

View File

@@ -0,0 +1,236 @@
/****************************************************************************
**
** 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 DIRECTSHOWGLOBAL_H
#define DIRECTSHOWGLOBAL_H
#include <QtCore/qglobal.h>
#include <dshow.h>
DEFINE_GUID(MEDIASUBTYPE_I420,
0x30323449,0x0000,0x0010,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71);
extern const GUID MEDIASUBTYPE_RGB24;
extern const GUID MEDIASUBTYPE_RGB32;
extern const GUID MEDIASUBTYPE_YUY2;
extern const GUID MEDIASUBTYPE_MJPG;
extern const GUID MEDIASUBTYPE_RGB555;
extern const GUID MEDIASUBTYPE_YVU9;
extern const GUID MEDIASUBTYPE_UYVY;
extern const GUID PIN_CATEGORY_CAPTURE;
extern const GUID PIN_CATEGORY_PREVIEW;
extern const IID IID_IPropertyBag;
extern const IID IID_ISampleGrabber;
extern const IID IID_ICaptureGraphBuilder2;
extern const IID IID_IAMStreamConfig;
extern const CLSID CLSID_CVidCapClassManager;
extern const CLSID CLSID_VideoInputDeviceCategory;
extern const CLSID CLSID_SampleGrabber;
extern const CLSID CLSID_CaptureGraphBuilder2;
#define SAFE_RELEASE(x) { if(x) x->Release(); x = NULL; }
typedef struct IFileSinkFilter *LPFILESINKFILTER;
typedef struct IAMCopyCaptureFileProgress *LPAMCOPYCAPTUREFILEPROGRESS;
#ifndef __ICaptureGraphBuilder2_INTERFACE_DEFINED__
#define __ICaptureGraphBuilder2_INTERFACE_DEFINED__
struct ICaptureGraphBuilder2 : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE SetFiltergraph(
/* [in] */ IGraphBuilder *pfg) = 0;
virtual HRESULT STDMETHODCALLTYPE GetFiltergraph(
/* [out] */ IGraphBuilder **ppfg) = 0;
virtual HRESULT STDMETHODCALLTYPE SetOutputFileName(
/* [in] */ const GUID *pType,
/* [in] */ LPCOLESTR lpstrFile,
/* [out] */ IBaseFilter **ppf,
/* [out] */ IFileSinkFilter **ppSink) = 0;
virtual /* [local] */ HRESULT STDMETHODCALLTYPE FindInterface(
/* [in] */ const GUID *pCategory,
/* [in] */ const GUID *pType,
/* [in] */ IBaseFilter *pf,
/* [in] */ REFIID riid,
/* [out] */ void **ppint) = 0;
virtual HRESULT STDMETHODCALLTYPE RenderStream(
/* [in] */ const GUID *pCategory,
/* [in] */ const GUID *pType,
/* [in] */ IUnknown *pSource,
/* [in] */ IBaseFilter *pfCompressor,
/* [in] */ IBaseFilter *pfRenderer) = 0;
virtual HRESULT STDMETHODCALLTYPE ControlStream(
/* [in] */ const GUID *pCategory,
/* [in] */ const GUID *pType,
/* [in] */ IBaseFilter *pFilter,
/* [in] */ REFERENCE_TIME *pstart,
/* [in] */ REFERENCE_TIME *pstop,
/* [in] */ WORD wStartCookie,
/* [in] */ WORD wStopCookie) = 0;
virtual HRESULT STDMETHODCALLTYPE AllocCapFile(
/* [in] */ LPCOLESTR lpstr,
/* [in] */ DWORDLONG dwlSize) = 0;
virtual HRESULT STDMETHODCALLTYPE CopyCaptureFile(
/* [in] */ LPOLESTR lpwstrOld,
/* [in] */ LPOLESTR lpwstrNew,
/* [in] */ int fAllowEscAbort,
/* [in] */ IAMCopyCaptureFileProgress *pCallback) = 0;
virtual HRESULT STDMETHODCALLTYPE FindPin(
/* [in] */ IUnknown *pSource,
/* [in] */ PIN_DIRECTION pindir,
/* [in] */ const GUID *pCategory,
/* [in] */ const GUID *pType,
/* [in] */ BOOL fUnconnected,
/* [in] */ int num,
/* [out] */ IPin **ppPin) = 0;
};
#endif
#ifndef __IAMStreamConfig_INTERFACE_DEFINED__
#define __IAMStreamConfig_INTERFACE_DEFINED__
struct IAMStreamConfig : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE SetFormat(
/* [in] */ AM_MEDIA_TYPE *pmt) = 0;
virtual HRESULT STDMETHODCALLTYPE GetFormat(
/* [out] */ AM_MEDIA_TYPE **ppmt) = 0;
virtual HRESULT STDMETHODCALLTYPE GetNumberOfCapabilities(
/* [out] */ int *piCount,
/* [out] */ int *piSize) = 0;
virtual HRESULT STDMETHODCALLTYPE GetStreamCaps(
/* [in] */ int iIndex,
/* [out] */ AM_MEDIA_TYPE **ppmt,
/* [out] */ BYTE *pSCC) = 0;
};
#endif
#ifndef __IErrorLog_INTERFACE_DEFINED__
#define __IErrorLog_INTERFACE_DEFINED__
struct IErrorLog : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE AddError(
/* [in] */ LPCOLESTR pszPropName,
/* [in] */ EXCEPINFO *pExcepInfo) = 0;
};
#endif
#ifndef __IPropertyBag_INTERFACE_DEFINED__
#define __IPropertyBag_INTERFACE_DEFINED__
struct IPropertyBag : public IUnknown
{
public:
virtual /* [local] */ HRESULT STDMETHODCALLTYPE Read(
/* [in] */ LPCOLESTR pszPropName,
/* [out][in] */ VARIANT *pVar,
/* [in] */ IErrorLog *pErrorLog) = 0;
virtual HRESULT STDMETHODCALLTYPE Write(
/* [in] */ LPCOLESTR pszPropName,
/* [in] */ VARIANT *pVar) = 0;
};
#endif
typedef struct IMediaSample *LPMEDIASAMPLE;
EXTERN_C const IID IID_ISampleGrabberCB;
#ifndef __ISampleGrabberCB_INTERFACE_DEFINED__
#define __ISampleGrabberCB_INTERFACE_DEFINED__
#undef INTERFACE
#define INTERFACE ISampleGrabberCB
DECLARE_INTERFACE_(ISampleGrabberCB, IUnknown)
{
// STDMETHOD(QueryInterface) (THIS_ const GUID *, void **) PURE;
STDMETHOD(QueryInterface) (THIS_ REFIID riid, void **) PURE;
STDMETHOD_(ULONG, AddRef) (THIS) PURE;
STDMETHOD_(ULONG, Release) (THIS) PURE;
STDMETHOD_(HRESULT, SampleCB) (THIS_ double, LPMEDIASAMPLE) PURE;
STDMETHOD_(HRESULT, BufferCB) (THIS_ double, BYTE *, long) PURE;
};
#undef INTERFACE
#endif
#ifndef __ISampleGrabber_INTERFACE_DEFINED__
#define __ISampleGrabber_INTERFACE_DEFINED__
#define INTERFACE ISampleGrabber
DECLARE_INTERFACE_(ISampleGrabber,IUnknown)
{
STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
STDMETHOD(SetOneShot)(THIS_ BOOL) PURE;
STDMETHOD(SetMediaType)(THIS_ const AM_MEDIA_TYPE*) PURE;
STDMETHOD(GetConnectedMediaType)(THIS_ AM_MEDIA_TYPE*) PURE;
STDMETHOD(SetBufferSamples)(THIS_ BOOL) PURE;
STDMETHOD(GetCurrentBuffer)(THIS_ long*,long*) PURE;
STDMETHOD(GetCurrentSample)(THIS_ IMediaSample**) PURE;
STDMETHOD(SetCallback)(THIS_ ISampleGrabberCB *,long) PURE;
};
#undef INTERFACE
#endif
#endif

View File

@@ -0,0 +1,103 @@
/****************************************************************************
**
** 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 <QtCore/qdebug.h>
#include "dscameracontrol.h"
#include "dscameraservice.h"
#include "dscamerasession.h"
QT_BEGIN_NAMESPACE
DSCameraControl::DSCameraControl(QObject *parent)
:QCameraControl(parent), m_captureMode(QCamera::CaptureStillImage)
{
m_session = qobject_cast<DSCameraSession*>(parent);
connect(m_session, SIGNAL(stateChanged(QCamera::State)),this, SIGNAL(stateChanged(QCamera::State)));
}
DSCameraControl::~DSCameraControl()
{
}
void DSCameraControl::setState(QCamera::State state)
{
switch (state) {
case QCamera::ActiveState:
start();
break;
case QCamera::UnloadedState: /* fall through */
case QCamera::LoadedState:
stop();
break;
}
}
bool DSCameraControl::isCaptureModeSupported(QCamera::CaptureMode mode) const
{
bool bCaptureSupported = false;
switch (mode) {
case QCamera::CaptureStillImage:
bCaptureSupported = true;
break;
case QCamera::CaptureVideo:
bCaptureSupported = false;
break;
}
return bCaptureSupported;
}
void DSCameraControl::start()
{
m_session->record();
}
void DSCameraControl::stop()
{
m_session->stop();
}
QCamera::State DSCameraControl::state() const
{
return (QCamera::State)m_session->state();
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,94 @@
/****************************************************************************
**
** 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 DSCAMERACONTROL_H
#define DSCAMERACONTROL_H
#include <QtCore/qobject.h>
#include <qcameracontrol.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class DSCameraService;
class DSCameraSession;
class DSCameraControl : public QCameraControl
{
Q_OBJECT
public:
DSCameraControl(QObject *parent = 0);
~DSCameraControl();
void start();
void stop();
QCamera::State state() const;
QCamera::CaptureMode captureMode() const { return m_captureMode; }
void setCaptureMode(QCamera::CaptureMode mode)
{
if (m_captureMode != mode) {
m_captureMode = mode;
emit captureModeChanged(mode);
}
}
void setState(QCamera::State state);
QCamera::Status status() const { return QCamera::UnavailableStatus; }
bool isCaptureModeSupported(QCamera::CaptureMode mode) const;
bool canChangeProperty(PropertyChangeType /* changeType */, QCamera::Status /* status */) const {return false; }
private:
DSCameraSession *m_session;
DSCameraService *m_service;
QCamera::CaptureMode m_captureMode;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif

View File

@@ -0,0 +1,114 @@
/****************************************************************************
**
** 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 <QtCore/qvariant.h>
#include <QtCore/qdebug.h>
#include <QtGui/qwidget.h>
#include <QVideoWidgetControl.h>
#include "dscameraservice.h"
#include "dscameracontrol.h"
#include "dscamerasession.h"
#include "dsvideorenderer.h"
#include "dsvideodevicecontrol.h"
#include "dsimagecapturecontrol.h"
#include "dsvideowidgetcontrol.h"
QT_BEGIN_NAMESPACE
DSCameraService::DSCameraService(QObject *parent):
QMediaService(parent)
{
m_session = new DSCameraSession(this);
m_control = new DSCameraControl(m_session);
m_videoDevice = new DSVideoDeviceControl(m_session);
m_videoRenderer = new DSVideoRendererControl(m_session, this);
m_imageCapture = new DSImageCaptureControl(m_session);
m_viewFinderWidget = new DSVideoWidgetControl(m_session);
m_device = QByteArray("default");
}
DSCameraService::~DSCameraService()
{
delete m_control;
delete m_videoDevice;
delete m_videoRenderer;
delete m_imageCapture;
delete m_viewFinderWidget;
delete m_session;
}
QMediaControl* DSCameraService::requestControl(const char *name)
{
if(qstrcmp(name,QCameraControl_iid) == 0)
return m_control;
if (qstrcmp(name, QCameraImageCaptureControl_iid) == 0)
return m_imageCapture;
if (qstrcmp(name, QVideoWidgetControl_iid) == 0) {
if (m_viewFinderWidget) {
return m_viewFinderWidget;
}
}
if(qstrcmp(name,QVideoRendererControl_iid) == 0)
return m_videoRenderer;
if(qstrcmp(name,QVideoDeviceControl_iid) == 0)
return m_videoDevice;
return 0;
}
void DSCameraService::releaseControl(QMediaControl *control)
{
// Implemented as a singleton, so we do nothing.
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,88 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DSCAMERASERVICE_H
#define DSCAMERASERVICE_H
#include <QtCore/qobject.h>
#include <qmediaservice.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class DSCameraControl;
class DSCameraSession;
class DSVideoOutputControl;
class DSVideoDeviceControl;
class DSVideoRendererControl;
class DSImageCaptureControl;
class DSVideoWidgetControl;
class DSCameraService : public QMediaService
{
Q_OBJECT
public:
DSCameraService(QObject *parent = 0);
~DSCameraService();
virtual QMediaControl* requestControl(const char *name);
virtual void releaseControl(QMediaControl *control);
private:
DSCameraControl *m_control;
DSCameraSession *m_session;
DSVideoOutputControl *m_videoOutput;
DSVideoWidgetControl *m_viewFinderWidget;
DSVideoDeviceControl *m_videoDevice;
DSVideoRendererControl *m_videoRenderer;
DSImageCaptureControl *m_imageCapture;
QByteArray m_device;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,208 @@
/****************************************************************************
**
** 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 DSCAMERASESSION_H
#define DSCAMERASESSION_H
#include <QtCore/qobject.h>
#include <QTime>
#include <QUrl>
#include <QMutex>
#include <qcamera.h>
#include <QtMultimedia/qvideoframe.h>
#include <QtMultimedia/qabstractvideosurface.h>
#include <QtMultimedia/qvideosurfaceformat.h>
#include <tchar.h>
#include <dshow.h>
#include <objbase.h>
#include <initguid.h>
#pragma comment(lib, "strmiids.lib")
#pragma comment(lib, "ole32.lib")
#include <windows.h>
#pragma include_alias("dxtrans.h","qedit.h")
#define __IDxtCompositor_INTERFACE_DEFINED__
#define __IDxtAlphaSetter_INTERFACE_DEFINED__
#define __IDxtJpeg_INTERFACE_DEFINED__
#define __IDxtKey_INTERFACE_DEFINED__
#include <qedit.h>
struct ICaptureGraphBuilder2;
struct ISampleGrabber;
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class DSVideoRenderer;
class SampleGrabberCallbackPrivate;
struct video_buffer {
unsigned char* buffer;
int length;
qint64 time;
};
typedef QMap<unsigned int, QList<QSize> > FormatResolutionMap;
class DSCameraSession : public QObject
{
Q_OBJECT
public:
DSCameraSession(QObject *parent = 0);
~DSCameraSession();
bool deviceReady();
bool pictureInProgress();
// camera controls
int framerate() const;
void setFrameRate(int rate);
int brightness() const;
void setBrightness(int b);
int contrast() const;
void setContrast(int c);
int saturation() const;
void setSaturation(int s);
int hue() const;
void setHue(int h);
int sharpness() const;
void setSharpness(int s);
int zoom() const;
void setZoom(int z);
bool backlightCompensation() const;
void setBacklightCompensation(bool);
int whitelevel() const;
void setWhitelevel(int w);
int rotation() const;
void setRotation(int r);
bool flash() const;
void setFlash(bool f);
bool autofocus() const;
void setAutofocus(bool f);
QSize frameSize() const;
void setFrameSize(const QSize& s);
void setDevice(const QString &device);
QList<QVideoFrame::PixelFormat> supportedPixelFormats();
QVideoFrame::PixelFormat pixelFormat() const;
void setPixelFormat(QVideoFrame::PixelFormat fmt);
QList<QSize> supportedResolutions(QVideoFrame::PixelFormat format);
// media control
bool setOutputLocation(const QUrl &sink);
QUrl outputLocation() const;
qint64 position() const;
int state() const;
void record();
void pause();
void stop();
void setSurface(QAbstractVideoSurface* surface);
int captureImage(const QString &fileName);
AM_MEDIA_TYPE StillMediaType;
QList<video_buffer*> frames;
SampleGrabberCallbackPrivate* StillCapCB;
QMutex mutex;
Q_SIGNALS:
void stateChanged(QCamera::State);
void imageCaptured(int id, const QImage &preview);
void imageSaved(int id, const QString &fileName);
void readyForCaptureChanged(bool);
private Q_SLOTS:
void captureFrame();
private:
QVideoSurfaceFormat actualFormat;
QList<QVideoFrame::PixelFormat> types;
QTime timeStamp;
bool graph;
bool active;
bool opened;
bool available;
QCamera::State m_state;
QByteArray m_device;
QUrl m_sink;
DSVideoRenderer* m_output;
QAbstractVideoSurface* m_surface;
QVideoFrame::PixelFormat pixelF;
QSize m_windowSize;
FormatResolutionMap resolutions;
ICaptureGraphBuilder2* pBuild;
IGraphBuilder* pGraph;
IBaseFilter* pCap;
IBaseFilter* pSG_Filter;
ISampleGrabber *pSG;
QString m_snapshot;
int m_currentImageId;
protected:
HRESULT getPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin);
bool createFilterGraph();
void updateProperties();
bool setProperties();
bool openStream();
void closeStream();
bool startStream();
void stopStream();
void suspendStream();
void resumeStream();
};
QT_END_NAMESPACE
QT_END_HEADER
#endif

View File

@@ -0,0 +1,83 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/QDebug>
#include "dsimagecapturecontrol.h"
QT_BEGIN_NAMESPACE
DSImageCaptureControl::DSImageCaptureControl(DSCameraSession *session)
:QCameraImageCaptureControl(session), m_session(session), m_ready(false)
{
connect(m_session, SIGNAL(stateChanged(QCamera::State)), SLOT(updateState()));
connect(m_session, SIGNAL(imageCaptured(const int, QImage)),
this, SIGNAL(imageCaptured(const int, QImage)));
connect(m_session, SIGNAL(imageSaved(const int, const QString &)),
this, SIGNAL(imageSaved(const int, const QString &)));
connect(m_session, SIGNAL(readyForCaptureChanged(bool)),
this, SIGNAL(readyForCaptureChanged(bool)));
}
DSImageCaptureControl::~DSImageCaptureControl()
{
}
bool DSImageCaptureControl::isReadyForCapture() const
{
return m_ready;
}
int DSImageCaptureControl::capture(const QString &fileName)
{
return m_session->captureImage(fileName);
}
void DSImageCaptureControl::updateState()
{
bool ready = (m_session->state() == QCamera::ActiveState) &&
!m_session->pictureInProgress();
if(m_ready != ready)
emit readyForCaptureChanged(m_ready = ready);
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,80 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DSIMAGECAPTURECONTROL_H
#define DSIMAGECAPTURECONTROL_H
#include <qcameraimagecapturecontrol.h>
#include "dscamerasession.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class DSImageCaptureControl : public QCameraImageCaptureControl
{
Q_OBJECT
public:
DSImageCaptureControl(DSCameraSession *session);
virtual ~DSImageCaptureControl();
bool isReadyForCapture() const;
int capture(const QString &fileName);
virtual QCameraImageCapture::DriveMode driveMode() const { return QCameraImageCapture::SingleImageCapture; }
virtual void setDriveMode(QCameraImageCapture::DriveMode mode) { }
virtual void cancelCapture() {}
private slots:
void updateState();
private:
DSCameraSession *m_session;
bool m_ready;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // DSCAPTURECONTROL_H

View File

@@ -0,0 +1,168 @@
/****************************************************************************
**
** 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 <QDebug>
#include <QFile>
#include <QtGui/QIcon>
#include "dsvideodevicecontrol.h"
#include "dscamerasession.h"
#include <tchar.h>
#include <dshow.h>
#include <objbase.h>
#include <initguid.h>
#include <Ocidl.h>
#include <string.h>
extern const CLSID CLSID_VideoInputDeviceCategory;
QT_BEGIN_NAMESPACE
DSVideoDeviceControl::DSVideoDeviceControl(QObject *parent)
: QVideoDeviceControl(parent)
{
m_session = qobject_cast<DSCameraSession*>(parent);
devices.clear();
descriptions.clear();
CoInitialize(NULL);
ICreateDevEnum* pDevEnum = NULL;
IEnumMoniker* pEnum = NULL;
// Create the System device enumerator
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
reinterpret_cast<void**>(&pDevEnum));
if(SUCCEEDED(hr)) {
// Create the enumerator for the video capture category
hr = pDevEnum->CreateClassEnumerator(
CLSID_VideoInputDeviceCategory, &pEnum, 0);
if (S_OK == hr) {
pEnum->Reset();
// go through and find all video capture devices
IMoniker* pMoniker = NULL;
while(pEnum->Next(1, &pMoniker, NULL) == S_OK) {
IPropertyBag *pPropBag;
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
(void**)(&pPropBag));
if(FAILED(hr)) {
pMoniker->Release();
continue; // skip this one
}
// Find the description
WCHAR str[120];
VARIANT varName;
varName.vt = VT_BSTR;
hr = pPropBag->Read(L"FriendlyName", &varName, 0);
if(SUCCEEDED(hr)) {
wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0]));
QString temp(QString::fromUtf16((unsigned short*)str));
devices.append(QString("ds:%1").arg(temp).toLocal8Bit().constData());
hr = pPropBag->Read(L"Description", &varName, 0);
wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0]));
QString temp2(QString::fromUtf16((unsigned short*)str));
descriptions.append(temp2.toLocal8Bit().constData());
}
pPropBag->Release();
pMoniker->Release();
}
pEnum->Release();
}
pDevEnum->Release();
}
CoUninitialize();
selected = 0;
}
int DSVideoDeviceControl::deviceCount() const
{
return devices.count();
}
QString DSVideoDeviceControl::deviceName(int index) const
{
if(index >= 0 && index <= devices.count())
return devices.at(index);
return QString();
}
QString DSVideoDeviceControl::deviceDescription(int index) const
{
if(index >= 0 && index <= descriptions.count())
return descriptions.at(index);
return QString();
}
QIcon DSVideoDeviceControl::deviceIcon(int index) const
{
Q_UNUSED(index)
return QIcon();
}
int DSVideoDeviceControl::defaultDevice() const
{
return 0;
}
int DSVideoDeviceControl::selectedDevice() const
{
return selected;
}
void DSVideoDeviceControl::setSelectedDevice(int index)
{
if(index >= 0 && index <= devices.count()) {
if (m_session) {
QString device = devices.at(index);
if (device.startsWith("ds:"))
device.remove(0,3);
m_session->setDevice(device);
}
selected = index;
}
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,83 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DSVIDEODEVICECONTROL_H
#define DSVIDEODEVICECONTROL_H
#include <qvideodevicecontrol.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class DSCameraSession;
//QTM_USE_NAMESPACE
class DSVideoDeviceControl : public QVideoDeviceControl
{
Q_OBJECT
public:
DSVideoDeviceControl(QObject *parent = 0);
int deviceCount() const;
QString deviceName(int index) const;
QString deviceDescription(int index) const;
QIcon deviceIcon(int index) const;
int defaultDevice() const;
int selectedDevice() const;
public Q_SLOTS:
void setSelectedDevice(int index);
private:
DSCameraSession* m_session;
QList<QString> devices;
QList<QString> descriptions;
int selected;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif

View File

@@ -0,0 +1,72 @@
/****************************************************************************
**
** 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 <QtCore/qdebug.h>
#include "dsvideorenderer.h"
QT_BEGIN_NAMESPACE
DSVideoRendererControl::DSVideoRendererControl(DSCameraSession* session, QObject *parent)
:QVideoRendererControl(parent),
m_surface(0),
m_session(session)
{
}
DSVideoRendererControl::~DSVideoRendererControl()
{
}
QAbstractVideoSurface* DSVideoRendererControl::surface() const
{
return m_surface;
}
void DSVideoRendererControl::setSurface(QAbstractVideoSurface *surface)
{
m_surface = surface;
if(m_session)
m_session->setSurface(m_surface);
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,77 @@
/****************************************************************************
**
** 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 DSVIDEORENDERER_H
#define DSVIDEORENDERER_H
#include <qvideorenderercontrol.h>
#include "dscamerasession.h"
class CameraFormatConverter;
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class DSVideoRendererControl : public QVideoRendererControl
{
Q_OBJECT
public:
DSVideoRendererControl(DSCameraSession* session, QObject *parent = 0);
~DSVideoRendererControl();
QAbstractVideoSurface *surface() const;
void setSurface(QAbstractVideoSurface *surface);
void setSession(DSCameraSession* session);
private:
QAbstractVideoSurface* m_surface;
DSCameraSession* m_session;
CameraFormatConverter* converter;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // DSVIDEORENDERER_H

View File

@@ -0,0 +1,250 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/qcoreevent.h>
#include <QtCore/qtimer.h>
#include "DSVideoWidgetControl.h"
#include "dscamerasession.h"
QT_BEGIN_NAMESPACE
DSVideoWidgetSurface::DSVideoWidgetSurface(QLabel *pWidget, QObject *parent)
{
widget = pWidget;
myPixmap = 0;
}
QList<QVideoFrame::PixelFormat> DSVideoWidgetSurface::supportedPixelFormats(
QAbstractVideoBuffer::HandleType handleType) const
{
if (handleType == QAbstractVideoBuffer::NoHandle) {
return QList<QVideoFrame::PixelFormat>()
<< QVideoFrame::Format_RGB32
<< QVideoFrame::Format_RGB24;
} else {
return QList<QVideoFrame::PixelFormat>();
}
}
bool DSVideoWidgetSurface::present(const QVideoFrame &frame)
{
QVideoFrame myFrame = frame;
myFrame.map(QAbstractVideoBuffer::ReadOnly);
QImage image(
frame.bits(),
frame.width(),
frame.height(),
frame.bytesPerLine(),
imageFormat);
if (image.isNull())
{
// Try to adapt
QImage image2(
frame.bits(),
frame.width(),
frame.height(),
frame.bytesPerLine(),
QImage::Format_RGB888);
image = image2;
}
myFrame.unmap();
delete myPixmap;
myPixmap = new QPixmap(QPixmap::fromImage(image).scaled(widget->size()));
widget->setPixmap(*myPixmap);
widget->repaint();
return true;
}
void DSVideoWidgetSurface::setImageFormat(QImage::Format fmt)
{
imageFormat = fmt;
}
void DSVideoWidgetSurface::updateVideoRect()
{
}
void DSVideoWidgetSurface::paint(QPainter *painter)
{
}
DSVideoWidgetControl::DSVideoWidgetControl(DSCameraSession* session, QObject *parent) :
m_session(session), QVideoWidgetControl(parent),
m_widget(new QLabel()),
m_fullScreen(false)
{
m_widget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
m_widget->setAlignment(Qt::AlignCenter);
m_widget->setAttribute(Qt::WA_NoSystemBackground, true);
surface = new DSVideoWidgetSurface(m_widget);
QPalette palette;
palette.setColor(QPalette::Background, Qt::black);
m_widget->setPalette(palette);
m_widget->setAutoFillBackground( true );
// Request QEvents
m_widget->installEventFilter(this);
m_windowId = m_widget->effectiveWinId();
surface->setImageFormat(QImage::Format_RGB888);
session->setSurface(surface);
}
DSVideoWidgetControl::~DSVideoWidgetControl()
{
delete m_widget;
}
bool DSVideoWidgetControl::eventFilter(QObject *object, QEvent *e)
{
if (object == m_widget) {
switch (e->type()) {
case QEvent::ParentChange:
case QEvent::WinIdChange:
case QEvent::Show:
m_windowId = m_widget->effectiveWinId();
emit widgetUpdated();
break;
case QEvent::Resize:
emit widgetResized(m_widget->size());
break;
case QEvent::PolishRequest:
m_widget->ensurePolished();
break;
default:
// Do nothing
break;
}
}
return false;
}
QWidget *DSVideoWidgetControl::videoWidget()
{
return m_widget;
}
Qt::AspectRatioMode DSVideoWidgetControl::aspectRatioMode() const
{
return m_aspectRatioMode;
}
void DSVideoWidgetControl::setAspectRatioMode(Qt::AspectRatioMode ratio)
{
if (m_aspectRatioMode==ratio) {
return;
}
m_aspectRatioMode = ratio;
if (m_aspectRatioMode == Qt::KeepAspectRatio)
m_widget->setScaledContents(false);
else {
m_widget->setScaledContents(true);
}
}
bool DSVideoWidgetControl::isFullScreen() const
{
return m_fullScreen;
}
void DSVideoWidgetControl::setFullScreen(bool fullScreen)
{
if (m_widget && !fullScreen && m_fullScreen) {
m_widget->showNormal();
m_fullScreen = false;
} else if (m_widget && fullScreen) {
m_widget->showFullScreen();
m_fullScreen = true;
}
emit fullScreenChanged(fullScreen);
}
int DSVideoWidgetControl::brightness() const
{
return 0;
}
void DSVideoWidgetControl::setBrightness(int brightness)
{
Q_UNUSED(brightness);
}
int DSVideoWidgetControl::contrast() const
{
return 0;
}
void DSVideoWidgetControl::setContrast(int contrast)
{
Q_UNUSED(contrast);
}
int DSVideoWidgetControl::hue() const
{
return 0;
}
void DSVideoWidgetControl::setHue(int hue)
{
Q_UNUSED(hue);
}
int DSVideoWidgetControl::saturation() const
{
return 0;
}
void DSVideoWidgetControl::setSaturation(int saturation)
{
Q_UNUSED(saturation);
}
QT_END_NAMESPACE
// End of file

View File

@@ -0,0 +1,154 @@
/****************************************************************************
**
** 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 DSVIDEOWIDGETCONTROL_H
#define DSVIDEOWIDGETCONTROL_H
#include <QtCore/qobject.h>
#include <QtGui>
#include <QtMultimedia/qvideoframe.h>
#include <QtMultimedia/qabstractvideosurface.h>
#include <QtMultimedia/qvideosurfaceformat.h>
#include <qvideowidgetcontrol.h>
#include "DsCameraControl.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class DSVideoWidgetSurface : public QAbstractVideoSurface
{
Q_OBJECT
public:
DSVideoWidgetSurface(QLabel *pWidget, QObject *parent = 0);
QList<QVideoFrame::PixelFormat> supportedPixelFormats(
QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const;
bool present(const QVideoFrame &frame);
QRect videoRect() const { return targetRect; }
void updateVideoRect();
void paint(QPainter *painter);
void setImageFormat(QImage::Format fmt);
private:
QLabel *widget;
QImage::Format imageFormat;
QRect targetRect;
QSize imageSize;
QRect sourceRect;
QPixmap* myPixmap;
};
class DSVideoWidgetControl : public QVideoWidgetControl
{
Q_OBJECT
DSVideoWidgetSurface* surface;
public: // Constructor & Destructor
DSVideoWidgetControl(DSCameraSession* session, QObject *parent = 0);
virtual ~DSVideoWidgetControl();
public: // QVideoWidgetControl
QWidget *videoWidget();
// Aspect Ratio
Qt::AspectRatioMode aspectRatioMode() const;
void setAspectRatioMode(Qt::AspectRatioMode ratio);
// Full Screen
bool isFullScreen() const;
void setFullScreen(bool fullScreen);
// Brightness
int brightness() const;
void setBrightness(int brightness);
// Contrast
int contrast() const;
void setContrast(int contrast);
// Hue
int hue() const;
void setHue(int hue);
// Saturation
int saturation() const;
void setSaturation(int saturation);
public: // Internal
bool eventFilter(QObject *object, QEvent *event);
/*
Q_SIGNALS: // QVideoWidgetControl
void fullScreenChanged(bool fullScreen);
void brightnessChanged(int brightness);
void contrastChanged(int contrast);
void hueChanged(int hue);
void saturationChanged(int saturation);
*/
Q_SIGNALS: // Internal Signals
void widgetResized(QSize size);
void widgetUpdated();
private: // Data
DSCameraSession* m_session;
QLabel *m_widget;
WId m_windowId;
Qt::AspectRatioMode m_aspectRatioMode;
bool m_fullScreen;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // DSVideoWidgetControl_H

View File

@@ -0,0 +1,23 @@
TEMPLATE = lib
CONFIG += plugin
TARGET = $$qtLibraryTarget(dsengine)
PLUGIN_TYPE=mediaservice
include (../../../common.pri)
INCLUDEPATH+=../../multimediakit \
../../multimediakit/audio \
../../multimediakit/video
qtAddLibrary(QtMultimediaKit)
DEPENDPATH += .
HEADERS += dsserviceplugin.h
SOURCES += dsserviceplugin.cpp
!contains(wmsdk_enabled, yes): DEFINES += QT_NO_WMSDK
include (player/player.pri)
include (camera/camera.pri)

View File

@@ -0,0 +1,211 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/qstring.h>
#include <QtCore/qdebug.h>
#include <QtCore/QFile>
#include "dsserviceplugin.h"
#ifdef QMEDIA_DIRECTSHOW_CAMERA
#include "dscameraservice.h"
#endif
#ifdef QMEDIA_DIRECTSHOW_PLAYER
#include "directshowplayerservice.h"
#endif
#include <qmediaserviceprovider.h>
#ifdef QMEDIA_DIRECTSHOW_CAMERA
extern const CLSID CLSID_VideoInputDeviceCategory;
#ifndef _STRSAFE_H_INCLUDED_
#include <tchar.h>
#endif
#include <dshow.h>
#include <objbase.h>
#include <initguid.h>
#pragma comment(lib, "strmiids.lib")
#pragma comment(lib, "ole32.lib")
#include <windows.h>
#include <ocidl.h>
#endif
QT_USE_NAMESPACE
QStringList DSServicePlugin::keys() const
{
return QStringList()
#ifdef QMEDIA_DIRECTSHOW_CAMERA
<< QLatin1String(Q_MEDIASERVICE_CAMERA)
#endif
#ifdef QMEDIA_DIRECTSHOW_PLAYER
<< QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER)
#endif
;
}
QMediaService* DSServicePlugin::create(QString const& key)
{
#ifdef QMEDIA_DIRECTSHOW_CAMERA
if (key == QLatin1String(Q_MEDIASERVICE_CAMERA))
return new DSCameraService;
#endif
#ifdef QMEDIA_DIRECTSHOW_PLAYER
if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER))
return new DirectShowPlayerService;
#endif
qDebug() << "unsupported key:" << key;
return 0;
}
void DSServicePlugin::release(QMediaService *service)
{
delete service;
}
QMediaServiceProviderHint::Features DSServicePlugin::supportedFeatures(
const QByteArray &service) const
{
if (service == Q_MEDIASERVICE_MEDIAPLAYER)
return QMediaServiceProviderHint::StreamPlayback | QMediaServiceProviderHint::VideoSurface;
else
return QMediaServiceProviderHint::Features();
}
QList<QByteArray> DSServicePlugin::devices(const QByteArray &service) const
{
#ifdef QMEDIA_DIRECTSHOW_CAMERA
if (service == Q_MEDIASERVICE_CAMERA) {
if (m_cameraDevices.isEmpty())
updateDevices();
return m_cameraDevices;
}
#endif
return QList<QByteArray>();
}
QString DSServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device)
{
#ifdef QMEDIA_DIRECTSHOW_CAMERA
if (service == Q_MEDIASERVICE_CAMERA) {
if (m_cameraDevices.isEmpty())
updateDevices();
for (int i=0; i<m_cameraDevices.count(); i++)
if (m_cameraDevices[i] == device)
return m_cameraDescriptions[i];
}
#endif
return QString();
}
#ifdef QMEDIA_DIRECTSHOW_CAMERA
void DSServicePlugin::updateDevices() const
{
m_cameraDevices.clear();
m_cameraDescriptions.clear();
BOOL bFound = TRUE;
CoInitialize(NULL);
ICreateDevEnum* pDevEnum = NULL;
IEnumMoniker* pEnum = NULL;
// Create the System device enumerator
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
reinterpret_cast<void**>(&pDevEnum));
if(SUCCEEDED(hr)) {
// Create the enumerator for the video capture category
hr = pDevEnum->CreateClassEnumerator(
CLSID_VideoInputDeviceCategory, &pEnum, 0);
if (S_OK == hr) {
pEnum->Reset();
// go through and find all video capture devices
IMoniker* pMoniker = NULL;
while(pEnum->Next(1, &pMoniker, NULL) == S_OK) {
IPropertyBag *pPropBag;
hr = pMoniker->BindToStorage(0,0,IID_IPropertyBag,
(void**)(&pPropBag));
if(FAILED(hr)) {
pMoniker->Release();
continue; // skip this one
}
bFound = TRUE;
// Find the description
WCHAR str[120];
VARIANT varName;
varName.vt = VT_BSTR;
hr = pPropBag->Read(L"FriendlyName", &varName, 0);
if(SUCCEEDED(hr)) {
wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0]));
QString temp(QString::fromUtf16((unsigned short*)str));
m_cameraDevices.append(QString("ds:%1").arg(temp).toLocal8Bit().constData());
hr = pPropBag->Read(L"Description", &varName, 0);
wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0]));
QString temp2(QString::fromUtf16((unsigned short*)str));
m_cameraDescriptions.append(temp2);
} else {
qWarning() << "No friendly name";
}
pPropBag->Release();
pMoniker->Release();
}
pEnum->Release();
}
pDevEnum->Release();
}
CoUninitialize();
if (!bFound) {
qWarning() << "No camera devices found";
}
}
#endif
Q_EXPORT_PLUGIN2(qtmedia_dsengine, DSServicePlugin);

View File

@@ -0,0 +1,76 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DSSERVICEPLUGIN_H
#define DSSERVICEPLUGIN_H
#include "qmediaserviceproviderplugin.h"
QT_USE_NAMESPACE
class DSServicePlugin
: public QMediaServiceProviderPlugin
, public QMediaServiceSupportedDevicesInterface
, public QMediaServiceFeaturesInterface
{
Q_OBJECT
Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
Q_INTERFACES(QMediaServiceFeaturesInterface)
public:
QStringList keys() const;
QMediaService* create(QString const& key);
void release(QMediaService *service);
QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const;
QList<QByteArray> devices(const QByteArray &service) const;
QString deviceDescription(const QByteArray &service, const QByteArray &device);
private:
#ifdef QMEDIA_DIRECTSHOW_CAMERA
void updateDevices() const;
mutable QList<QByteArray> m_cameraDevices;
mutable QStringList m_cameraDescriptions;
#endif
};
#endif // DSSERVICEPLUGIN_H

View File

@@ -0,0 +1,161 @@
/****************************************************************************
**
** 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 "directshowaudioendpointcontrol.h"
#include "directshowglobal.h"
#include "directshowplayerservice.h"
DirectShowAudioEndpointControl::DirectShowAudioEndpointControl(
DirectShowPlayerService *service, QObject *parent)
: QAudioEndpointSelector(parent)
, m_service(service)
, m_bindContext(0)
, m_deviceEnumerator(0)
{
if (CreateBindCtx(0, &m_bindContext) == S_OK) {
m_deviceEnumerator = com_new<ICreateDevEnum>(CLSID_SystemDeviceEnum, IID_ICreateDevEnum);
updateEndpoints();
setActiveEndpoint(m_defaultEndpoint);
}
}
DirectShowAudioEndpointControl::~DirectShowAudioEndpointControl()
{
foreach (IMoniker *moniker, m_devices)
moniker->Release();
if (m_bindContext)
m_bindContext->Release();
if (m_deviceEnumerator)
m_deviceEnumerator->Release();
}
QList<QString> DirectShowAudioEndpointControl::availableEndpoints() const
{
return m_devices.keys();
}
QString DirectShowAudioEndpointControl::endpointDescription(const QString &name) const
{
#ifdef __IPropertyBag_INTERFACE_DEFINED__
QString description;
if (IMoniker *moniker = m_devices.value(name, 0)) {
IPropertyBag *propertyBag = 0;
if (SUCCEEDED(moniker->BindToStorage(
0, 0, IID_IPropertyBag, reinterpret_cast<void **>(&propertyBag)))) {
VARIANT name;
VariantInit(&name);
if (SUCCEEDED(propertyBag->Read(L"FriendlyName", &name, 0)))
description = QString::fromWCharArray(name.bstrVal);
VariantClear(&name);
propertyBag->Release();
}
}
return description;
#else
return name.section(QLatin1Char('\\'), -1);
#endif
}
QString DirectShowAudioEndpointControl::defaultEndpoint() const
{
return m_defaultEndpoint;
}
QString DirectShowAudioEndpointControl::activeEndpoint() const
{
return m_activeEndpoint;
}
void DirectShowAudioEndpointControl::setActiveEndpoint(const QString &name)
{
if (m_activeEndpoint == name)
return;
if (IMoniker *moniker = m_devices.value(name, 0)) {
IBaseFilter *filter = 0;
if (moniker->BindToObject(
m_bindContext,
0,
IID_IBaseFilter,
reinterpret_cast<void **>(&filter)) == S_OK) {
m_service->setAudioOutput(filter);
filter->Release();
}
}
}
void DirectShowAudioEndpointControl::updateEndpoints()
{
IMalloc *oleMalloc = 0;
if (m_deviceEnumerator && CoGetMalloc(1, &oleMalloc) == S_OK) {
IEnumMoniker *monikers = 0;
if (m_deviceEnumerator->CreateClassEnumerator(
CLSID_AudioRendererCategory, &monikers, 0) == S_OK) {
for (IMoniker *moniker = 0; monikers->Next(1, &moniker, 0) == S_OK; moniker->Release()) {
OLECHAR *string = 0;
if (moniker->GetDisplayName(m_bindContext, 0, &string) == S_OK) {
QString deviceId = QString::fromWCharArray(string);
oleMalloc->Free(string);
moniker->AddRef();
m_devices.insert(deviceId, moniker);
if (m_defaultEndpoint.isEmpty()
|| deviceId.endsWith(QLatin1String("Default DirectSound Device"))) {
m_defaultEndpoint = deviceId;
}
}
}
monikers->Release();
}
oleMalloc->Release();
}
}

View File

@@ -0,0 +1,82 @@
/****************************************************************************
**
** 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 DIRECTSHOWAUDIOENDPOINTCONTROL_H
#define DIRECTSHOWAUDIOENDPOINTCONTROL_H
#include "qaudioendpointselector.h"
#include <dshow.h>
class DirectShowPlayerService;
QT_USE_NAMESPACE
class DirectShowAudioEndpointControl : public QAudioEndpointSelector
{
Q_OBJECT
public:
DirectShowAudioEndpointControl(DirectShowPlayerService *service, QObject *parent = 0);
~DirectShowAudioEndpointControl();
QList<QString> availableEndpoints() const;
QString endpointDescription(const QString &name) const;
QString defaultEndpoint() const;
QString activeEndpoint() const;
void setActiveEndpoint(const QString& name);
private:
void updateEndpoints();
DirectShowPlayerService *m_service;
IBindCtx *m_bindContext;
ICreateDevEnum *m_deviceEnumerator;
QMap<QString, IMoniker *> m_devices;
QString m_defaultEndpoint;
QString m_activeEndpoint;
};
#endif

View File

@@ -0,0 +1,150 @@
/****************************************************************************
**
** 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 <directshoweventloop.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qcoreevent.h>
class DirectShowPostedEvent
{
public:
DirectShowPostedEvent(QObject *receiver, QEvent *event)
: receiver(receiver)
, event(event)
, next(0)
{
}
~DirectShowPostedEvent()
{
delete event;
}
QObject *receiver;
QEvent *event;
DirectShowPostedEvent *next;
};
DirectShowEventLoop::DirectShowEventLoop(QObject *parent)
: QObject(parent)
, m_postsHead(0)
, m_postsTail(0)
, m_eventHandle(::CreateEvent(0, 0, 0, 0))
, m_waitHandle(::CreateEvent(0, 0, 0, 0))
{
}
DirectShowEventLoop::~DirectShowEventLoop()
{
::CloseHandle(m_eventHandle);
::CloseHandle(m_waitHandle);
for (DirectShowPostedEvent *post = m_postsHead; post; post = m_postsHead) {
m_postsHead = m_postsHead->next;
delete post;
}
}
void DirectShowEventLoop::wait(QMutex *mutex)
{
::ResetEvent(m_waitHandle);
mutex->unlock();
HANDLE handles[] = { m_eventHandle, m_waitHandle };
while (::WaitForMultipleObjects(2, handles, false, INFINITE) == WAIT_OBJECT_0)
processEvents();
mutex->lock();
}
void DirectShowEventLoop::wake()
{
::SetEvent(m_waitHandle);
}
void DirectShowEventLoop::postEvent(QObject *receiver, QEvent *event)
{
QMutexLocker locker(&m_mutex);
DirectShowPostedEvent *post = new DirectShowPostedEvent(receiver, event);
if (m_postsTail)
m_postsTail->next = post;
else
m_postsHead = post;
m_postsTail = post;
QCoreApplication::postEvent(this, new QEvent(QEvent::User));
::SetEvent(m_eventHandle);
}
void DirectShowEventLoop::customEvent(QEvent *event)
{
if (event->type() == QEvent::User) {
processEvents();
} else {
QObject::customEvent(event);
}
}
void DirectShowEventLoop::processEvents()
{
QMutexLocker locker(&m_mutex);
::ResetEvent(m_eventHandle);
while(m_postsHead) {
DirectShowPostedEvent *post = m_postsHead;
m_postsHead = m_postsHead->next;
if (!m_postsHead)
m_postsTail = 0;
locker.unlock();
QCoreApplication::sendEvent(post->receiver, post->event);
delete post;
locker.relock();
}
}

View File

@@ -0,0 +1,78 @@
/****************************************************************************
**
** 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 DIRECTSHOWEVENTLOOP_H
#define DIRECTSHOWEVENTLOOP_H
#include <QtCore/qmutex.h>
#include <QtCore/qobject.h>
#include <QtCore/qwaitcondition.h>
#include <windows.h>
class DirectShowPostedEvent;
class DirectShowEventLoop : public QObject
{
Q_OBJECT
public:
DirectShowEventLoop(QObject *parent = 0);
~DirectShowEventLoop();
void wait(QMutex *mutex);
void wake();
void postEvent(QObject *object, QEvent *event);
protected:
void customEvent(QEvent *event);
private:
void processEvents();
DirectShowPostedEvent *m_postsHead;
DirectShowPostedEvent *m_postsTail;
HANDLE m_eventHandle;
HANDLE m_waitHandle;
QMutex m_mutex;
};
#endif

View File

@@ -0,0 +1,139 @@
/****************************************************************************
**
** 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 DIRECTSHOWGLOBAL_H
#define DIRECTSHOWGLOBAL_H
#include <QtCore/qglobal.h>
#include <dshow.h>
template <typename T> T *com_cast(IUnknown *unknown, const IID &iid)
{
T *iface = 0;
return unknown && unknown->QueryInterface(iid, reinterpret_cast<void **>(&iface)) == S_OK
? iface
: 0;
}
template <typename T> T *com_new(const IID &clsid, const IID &iid)
{
T *object = 0;
return CoCreateInstance(
clsid,
NULL,
CLSCTX_INPROC_SERVER,
iid,
reinterpret_cast<void **>(&object)) == S_OK
? object
: 0;
}
#ifndef __IFilterGraph2_INTERFACE_DEFINED__
#define __IFilterGraph2_INTERFACE_DEFINED__
#define INTERFACE IFilterGraph2
DECLARE_INTERFACE_(IFilterGraph2 ,IGraphBuilder)
{
STDMETHOD(AddSourceFilterForMoniker)(THIS_ IMoniker *, IBindCtx *, LPCWSTR,IBaseFilter **) PURE;
STDMETHOD(ReconnectEx)(THIS_ IPin *, const AM_MEDIA_TYPE *) PURE;
STDMETHOD(RenderEx)(IPin *, DWORD, DWORD *) PURE;
};
#undef INTERFACE
#endif
#ifndef __IAMFilterMiscFlags_INTERFACE_DEFINED__
#define __IAMFilterMiscFlags_INTERFACE_DEFINED__
#define INTERFACE IAMFilterMiscFlags
DECLARE_INTERFACE_(IAMFilterMiscFlags ,IUnknown)
{
STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
STDMETHOD_(ULONG,GetMiscFlags)(THIS) PURE;
};
#undef INTERFACE
#endif
#ifndef __IFileSourceFilter_INTERFACE_DEFINED__
#define __IFileSourceFilter_INTERFACE_DEFINED__
#define INTERFACE IFileSourceFilter
DECLARE_INTERFACE_(IFileSourceFilter ,IUnknown)
{
STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
STDMETHOD(Load)(THIS_ LPCOLESTR, const AM_MEDIA_TYPE *) PURE;
STDMETHOD(GetCurFile)(THIS_ LPOLESTR *ppszFileName, AM_MEDIA_TYPE *) PURE;
};
#undef INTERFACE
#endif
#ifndef __IAMOpenProgress_INTERFACE_DEFINED__
#define __IAMOpenProgress_INTERFACE_DEFINED__
#define INTERFACE IAMOpenProgress
DECLARE_INTERFACE_(IAMOpenProgress ,IUnknown)
{
STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
STDMETHOD(QueryProgress)(THIS_ LONGLONG *, LONGLONG *) PURE;
STDMETHOD(AbortOperation)(THIS) PURE;
};
#undef INTERFACE
#endif
#ifndef __IFilterChain_INTERFACE_DEFINED__
#define __IFilterChain_INTERFACE_DEFINED__
#define INTERFACE IFilterChain
DECLARE_INTERFACE_(IFilterChain ,IUnknown)
{
STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
STDMETHOD(StartChain)(IBaseFilter *, IBaseFilter *) PURE;
STDMETHOD(PauseChain)(IBaseFilter *, IBaseFilter *) PURE;
STDMETHOD(StopChain)(IBaseFilter *, IBaseFilter *) PURE;
STDMETHOD(RemoveChain)(IBaseFilter *, IBaseFilter *) PURE;
};
#undef INTERFACE
#endif
#endif

View File

@@ -0,0 +1,496 @@
/****************************************************************************
**
** 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 "directshowioreader.h"
#include "directshoweventloop.h"
#include "directshowglobal.h"
#include "directshowiosource.h"
#include <QtCore/qcoreapplication.h>
#include <QtCore/qcoreevent.h>
#include <QtCore/qiodevice.h>
#include <QtCore/qthread.h>
class DirectShowSampleRequest
{
public:
DirectShowSampleRequest(
IMediaSample *sample, DWORD_PTR userData, LONGLONG position, LONG length, BYTE *buffer)
: next(0)
, sample(sample)
, userData(userData)
, position(position)
, length(length)
, buffer(buffer)
, result(S_FALSE)
{
}
DirectShowSampleRequest *remove() { DirectShowSampleRequest *n = next; delete this; return n; }
DirectShowSampleRequest *next;
IMediaSample *sample;
DWORD_PTR userData;
LONGLONG position;
LONG length;
BYTE *buffer;
HRESULT result;
};
DirectShowIOReader::DirectShowIOReader(
QIODevice *device, DirectShowIOSource *source, DirectShowEventLoop *loop)
: m_source(source)
, m_device(device)
, m_loop(loop)
, m_pendingHead(0)
, m_pendingTail(0)
, m_readyHead(0)
, m_readyTail(0)
, m_synchronousPosition(0)
, m_synchronousLength(0)
, m_synchronousBytesRead(0)
, m_synchronousBuffer(0)
, m_synchronousResult(S_OK)
, m_totalLength(0)
, m_availableLength(0)
, m_flushing(false)
{
moveToThread(device->thread());
connect(device, SIGNAL(readyRead()), this, SLOT(readyRead()));
}
DirectShowIOReader::~DirectShowIOReader()
{
flushRequests();
}
HRESULT DirectShowIOReader::QueryInterface(REFIID riid, void **ppvObject)
{
return m_source->QueryInterface(riid, ppvObject);
}
ULONG DirectShowIOReader::AddRef()
{
return m_source->AddRef();
}
ULONG DirectShowIOReader::Release()
{
return m_source->Release();
}
// IAsyncReader
HRESULT DirectShowIOReader::RequestAllocator(
IMemAllocator *pPreferred, ALLOCATOR_PROPERTIES *pProps, IMemAllocator **ppActual)
{
if (!ppActual || !pProps) {
return E_POINTER;
} else {
ALLOCATOR_PROPERTIES actualProperties;
if (pProps->cbAlign == 0)
pProps->cbAlign = 1;
if (pPreferred && pPreferred->SetProperties(pProps, &actualProperties) == S_OK) {
pPreferred->AddRef();
*ppActual = pPreferred;
m_source->setAllocator(*ppActual);
return S_OK;
} else {
*ppActual = com_new<IMemAllocator>(CLSID_MemoryAllocator, IID_IMemAllocator);
if (*ppActual) {
if ((*ppActual)->SetProperties(pProps, &actualProperties) != S_OK) {
(*ppActual)->Release();
} else {
m_source->setAllocator(*ppActual);
return S_OK;
}
}
}
ppActual = 0;
return E_FAIL;
}
}
HRESULT DirectShowIOReader::Request(IMediaSample *pSample, DWORD_PTR dwUser)
{
QMutexLocker locker(&m_mutex);
if (!pSample) {
return E_POINTER;
} else if (m_flushing) {
return VFW_E_WRONG_STATE;
} else {
REFERENCE_TIME startTime = 0;
REFERENCE_TIME endTime = 0;
BYTE *buffer;
if (pSample->GetTime(&startTime, &endTime) != S_OK
|| pSample->GetPointer(&buffer) != S_OK) {
return VFW_E_SAMPLE_TIME_NOT_SET;
} else {
LONGLONG position = startTime / 10000000;
LONG length = (endTime - startTime) / 10000000;
DirectShowSampleRequest *request = new DirectShowSampleRequest(
pSample, dwUser, position, length, buffer);
if (m_pendingTail) {
m_pendingTail->next = request;
} else {
m_pendingHead = request;
m_loop->postEvent(this, new QEvent(QEvent::User));
}
m_pendingTail = request;
return S_OK;
}
}
}
HRESULT DirectShowIOReader::WaitForNext(
DWORD dwTimeout, IMediaSample **ppSample, DWORD_PTR *pdwUser)
{
if (!ppSample || !pdwUser)
return E_POINTER;
QMutexLocker locker(&m_mutex);
do {
if (m_readyHead) {
DirectShowSampleRequest *request = m_readyHead;
*ppSample = request->sample;
*pdwUser = request->userData;
HRESULT hr = request->result;
m_readyHead = request->next;
if (!m_readyHead)
m_readyTail = 0;
delete request;
return hr;
} else if (m_flushing) {
*ppSample = 0;
*pdwUser = 0;
return VFW_E_WRONG_STATE;
}
} while (m_wait.wait(&m_mutex, dwTimeout));
*ppSample = 0;
*pdwUser = 0;
return VFW_E_TIMEOUT;
}
HRESULT DirectShowIOReader::SyncReadAligned(IMediaSample *pSample)
{
if (!pSample) {
return E_POINTER;
} else {
REFERENCE_TIME startTime = 0;
REFERENCE_TIME endTime = 0;
BYTE *buffer;
if (pSample->GetTime(&startTime, &endTime) != S_OK
|| pSample->GetPointer(&buffer) != S_OK) {
return VFW_E_SAMPLE_TIME_NOT_SET;
} else {
LONGLONG position = startTime / 10000000;
LONG length = (endTime - startTime) / 10000000;
QMutexLocker locker(&m_mutex);
if (thread() == QThread::currentThread()) {
qint64 bytesRead = 0;
HRESULT hr = blockingRead(position, length, buffer, &bytesRead);
if (SUCCEEDED(hr))
pSample->SetActualDataLength(bytesRead);
return hr;
} else {
m_synchronousPosition = position;
m_synchronousLength = length;
m_synchronousBuffer = buffer;
m_loop->postEvent(this, new QEvent(QEvent::User));
m_wait.wait(&m_mutex);
m_synchronousBuffer = 0;
if (SUCCEEDED(m_synchronousResult))
pSample->SetActualDataLength(m_synchronousBytesRead);
return m_synchronousResult;
}
}
}
}
HRESULT DirectShowIOReader::SyncRead(LONGLONG llPosition, LONG lLength, BYTE *pBuffer)
{
if (!pBuffer) {
return E_POINTER;
} else {
if (thread() == QThread::currentThread()) {
qint64 bytesRead;
return blockingRead(llPosition, lLength, pBuffer, &bytesRead);
} else {
QMutexLocker locker(&m_mutex);
m_synchronousPosition = llPosition;
m_synchronousLength = lLength;
m_synchronousBuffer = pBuffer;
m_loop->postEvent(this, new QEvent(QEvent::User));
m_wait.wait(&m_mutex);
m_synchronousBuffer = 0;
return m_synchronousResult;
}
}
}
HRESULT DirectShowIOReader::Length(LONGLONG *pTotal, LONGLONG *pAvailable)
{
if (!pTotal || !pAvailable) {
return E_POINTER;
} else {
QMutexLocker locker(&m_mutex);
*pTotal = m_totalLength;
*pAvailable = m_availableLength;
return S_OK;
}
}
HRESULT DirectShowIOReader::BeginFlush()
{
QMutexLocker locker(&m_mutex);
if (m_flushing)
return S_FALSE;
m_flushing = true;
flushRequests();
m_wait.wakeAll();
return S_OK;
}
HRESULT DirectShowIOReader::EndFlush()
{
QMutexLocker locker(&m_mutex);
if (!m_flushing)
return S_FALSE;
m_flushing = false;
return S_OK;
}
void DirectShowIOReader::customEvent(QEvent *event)
{
if (event->type() == QEvent::User) {
readyRead();
} else {
QObject::customEvent(event);
}
}
void DirectShowIOReader::readyRead()
{
QMutexLocker locker(&m_mutex);
m_availableLength = m_device->bytesAvailable() + m_device->pos();
m_totalLength = m_device->size();
if (m_synchronousBuffer) {
if (nonBlockingRead(
m_synchronousPosition,
m_synchronousLength,
m_synchronousBuffer,
&m_synchronousBytesRead,
&m_synchronousResult)) {
m_wait.wakeAll();
}
} else {
qint64 bytesRead = 0;
while (m_pendingHead && nonBlockingRead(
m_pendingHead->position,
m_pendingHead->length,
m_pendingHead->buffer,
&bytesRead,
&m_pendingHead->result)) {
m_pendingHead->sample->SetActualDataLength(bytesRead);
if (m_readyTail)
m_readyTail->next = m_pendingHead;
m_readyTail = m_pendingHead;
m_pendingHead = m_pendingHead->next;
m_readyTail->next = 0;
if (!m_pendingHead)
m_pendingTail = 0;
if (!m_readyHead)
m_readyHead = m_readyTail;
m_wait.wakeAll();
}
}
}
HRESULT DirectShowIOReader::blockingRead(
LONGLONG position, LONG length, BYTE *buffer, qint64 *bytesRead)
{
*bytesRead = 0;
if (qint64(position) > m_device->size())
return S_FALSE;
const qint64 maxSize = qMin<qint64>(m_device->size(), position + length);
while (m_device->bytesAvailable() + m_device->pos() < maxSize) {
if (!m_device->waitForReadyRead(-1))
return S_FALSE;
}
if (m_device->pos() != position && !m_device->seek(position))
return S_FALSE;
const qint64 maxBytes = qMin<qint64>(length, m_device->bytesAvailable());
*bytesRead = m_device->read(reinterpret_cast<char *>(buffer), maxBytes);
if (*bytesRead != length) {
qMemSet(buffer + *bytesRead, 0, length - *bytesRead);
return S_FALSE;
} else {
return S_OK;
}
}
bool DirectShowIOReader::nonBlockingRead(
LONGLONG position, LONG length, BYTE *buffer, qint64 *bytesRead, HRESULT *result)
{
const qint64 maxSize = qMin<qint64>(m_device->size(), position + length);
if (position > m_device->size()) {
*bytesRead = 0;
*result = S_FALSE;
return true;
} else if (m_device->bytesAvailable() + m_device->pos() >= maxSize) {
if (m_device->pos() != position && !m_device->seek(position)) {
*bytesRead = 0;
*result = S_FALSE;
return true;
} else {
const qint64 maxBytes = qMin<qint64>(length, m_device->bytesAvailable());
*bytesRead = m_device->read(reinterpret_cast<char *>(buffer), maxBytes);
if (*bytesRead != length) {
qMemSet(buffer + *bytesRead, 0, length - *bytesRead);
*result = S_FALSE;
} else {
*result = S_OK;
}
return true;
}
} else {
return false;
}
}
void DirectShowIOReader::flushRequests()
{
while (m_pendingHead) {
m_pendingHead->result = VFW_E_WRONG_STATE;
if (m_readyTail)
m_readyTail->next = m_pendingHead;
m_readyTail = m_pendingHead;
m_pendingHead = m_pendingHead->next;
m_readyTail->next = 0;
if (!m_pendingHead)
m_pendingTail = 0;
if (!m_readyHead)
m_readyHead = m_readyTail;
}
}

View File

@@ -0,0 +1,120 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DIRECTSHOWIOREADER_H
#define DIRECTSHOWIOREADER_H
#include <QtCore/qmutex.h>
#include <QtCore/qobject.h>
#include <QtCore/qwaitcondition.h>
#include <dshow.h>
QT_BEGIN_NAMESPACE
class QIODevice;
QT_END_NAMESPACE
class DirectShowEventLoop;
class DirectShowIOSource;
class DirectShowSampleRequest;
class DirectShowIOReader : public QObject, public IAsyncReader
{
Q_OBJECT
public:
DirectShowIOReader(QIODevice *device, DirectShowIOSource *source, DirectShowEventLoop *loop);
~DirectShowIOReader();
// IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
// IAsyncReader
HRESULT STDMETHODCALLTYPE RequestAllocator(
IMemAllocator *pPreferred, ALLOCATOR_PROPERTIES *pProps, IMemAllocator **ppActual);
HRESULT STDMETHODCALLTYPE Request(IMediaSample *pSample, DWORD_PTR dwUser);
HRESULT STDMETHODCALLTYPE WaitForNext(
DWORD dwTimeout, IMediaSample **ppSample, DWORD_PTR *pdwUser);
HRESULT STDMETHODCALLTYPE SyncReadAligned(IMediaSample *pSample);
HRESULT STDMETHODCALLTYPE SyncRead(LONGLONG llPosition, LONG lLength, BYTE *pBuffer);
HRESULT STDMETHODCALLTYPE Length(LONGLONG *pTotal, LONGLONG *pAvailable);
HRESULT STDMETHODCALLTYPE BeginFlush();
HRESULT STDMETHODCALLTYPE EndFlush();
protected:
void customEvent(QEvent *event);
private Q_SLOTS:
void readyRead();
private:
HRESULT blockingRead(LONGLONG position, LONG length, BYTE *buffer, qint64 *bytesRead);
bool nonBlockingRead(
LONGLONG position, LONG length, BYTE *buffer, qint64 *bytesRead, HRESULT *result);
void flushRequests();
DirectShowIOSource *m_source;
QIODevice *m_device;
DirectShowEventLoop *m_loop;
DirectShowSampleRequest *m_pendingHead;
DirectShowSampleRequest *m_pendingTail;
DirectShowSampleRequest *m_readyHead;
DirectShowSampleRequest *m_readyTail;
LONGLONG m_synchronousPosition;
LONG m_synchronousLength;
qint64 m_synchronousBytesRead;
BYTE *m_synchronousBuffer;
HRESULT m_synchronousResult;
LONGLONG m_totalLength;
LONGLONG m_availableLength;
bool m_flushing;
QMutex m_mutex;
QWaitCondition m_wait;
};
#endif

View File

@@ -0,0 +1,639 @@
/****************************************************************************
**
** 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 "directshowiosource.h"
#include "directshowglobal.h"
#include "directshowmediatype.h"
#include "directshowpinenum.h"
#include <QtCore/qcoreapplication.h>
#include <QtCore/qurl.h>
static const GUID directshow_subtypes[] =
{
MEDIASUBTYPE_Avi,
MEDIASUBTYPE_WAVE,
MEDIASUBTYPE_NULL
};
DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop)
: m_ref(1)
, m_state(State_Stopped)
, m_reader(0)
, m_loop(loop)
, m_graph(0)
, m_clock(0)
, m_allocator(0)
, m_peerPin(0)
, m_pinId(QLatin1String("Data"))
{
QVector<AM_MEDIA_TYPE> mediaTypes;
AM_MEDIA_TYPE type =
{
MEDIATYPE_Stream, // majortype
MEDIASUBTYPE_NULL, // subtype
TRUE, // bFixedSizeSamples
FALSE, // bTemporalCompression
1, // lSampleSize
GUID_NULL, // formattype
0, // pUnk
0, // cbFormat
0, // pbFormat
};
static const int count = sizeof(directshow_subtypes) / sizeof(GUID);
for (int i = 0; i < count; ++i) {
type.subtype = directshow_subtypes[i];
mediaTypes.append(type);
}
setMediaTypes(mediaTypes);
}
DirectShowIOSource::~DirectShowIOSource()
{
Q_ASSERT(m_ref == 0);
delete m_reader;
}
void DirectShowIOSource::setDevice(QIODevice *device)
{
Q_ASSERT(!m_reader);
m_reader = new DirectShowIOReader(device, this, m_loop);
}
void DirectShowIOSource::setAllocator(IMemAllocator *allocator)
{
if (m_allocator)
m_allocator->Release();
m_allocator = allocator;
if (m_allocator)
m_allocator->AddRef();
}
// IUnknown
HRESULT DirectShowIOSource::QueryInterface(REFIID riid, void **ppvObject)
{
// 2dd74950-a890-11d1-abe8-00a0c905f375
static const GUID iid_IAmFilterMiscFlags = {
0x2dd74950, 0xa890, 0x11d1, {0xab, 0xe8, 0x00, 0xa0, 0xc9, 0x05, 0xf3, 0x75}};
if (!ppvObject) {
return E_POINTER;
} else if (riid == IID_IUnknown
|| riid == IID_IPersist
|| riid == IID_IMediaFilter
|| riid == IID_IBaseFilter) {
*ppvObject = static_cast<IBaseFilter *>(this);
} else if (riid == iid_IAmFilterMiscFlags) {
*ppvObject = static_cast<IAMFilterMiscFlags *>(this);
} else if (riid == IID_IPin) {
*ppvObject = static_cast<IPin *>(this);
} else if (riid == IID_IAsyncReader) {
*ppvObject = static_cast<IAsyncReader *>(m_reader);
} else {
*ppvObject = 0;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
ULONG DirectShowIOSource::AddRef()
{
return InterlockedIncrement(&m_ref);
}
ULONG DirectShowIOSource::Release()
{
ULONG ref = InterlockedDecrement(&m_ref);
if (ref == 0) {
delete this;
}
return ref;
}
// IPersist
HRESULT DirectShowIOSource::GetClassID(CLSID *pClassID)
{
*pClassID = CLSID_NULL;
return S_OK;
}
// IMediaFilter
HRESULT DirectShowIOSource::Run(REFERENCE_TIME tStart)
{
QMutexLocker locker(&m_mutex);
m_state = State_Running;
return S_OK;
}
HRESULT DirectShowIOSource::Pause()
{
QMutexLocker locker(&m_mutex);
m_state = State_Paused;
return S_OK;
}
HRESULT DirectShowIOSource::Stop()
{
QMutexLocker locker(&m_mutex);
m_state = State_Stopped;
return S_OK;
}
HRESULT DirectShowIOSource::GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
{
Q_UNUSED(dwMilliSecsTimeout);
if (!pState) {
return E_POINTER;
} else {
QMutexLocker locker(&m_mutex);
*pState = m_state;
return S_OK;
}
}
HRESULT DirectShowIOSource::SetSyncSource(IReferenceClock *pClock)
{
QMutexLocker locker(&m_mutex);
if (m_clock)
m_clock->Release();
m_clock = pClock;
if (m_clock)
m_clock->AddRef();
return S_OK;
}
HRESULT DirectShowIOSource::GetSyncSource(IReferenceClock **ppClock)
{
if (!ppClock) {
return E_POINTER;
} else {
if (!m_clock) {
*ppClock = 0;
return S_FALSE;
} else {
m_clock->AddRef();
*ppClock = m_clock;
return S_OK;
}
}
}
// IBaseFilter
HRESULT DirectShowIOSource::EnumPins(IEnumPins **ppEnum)
{
if (!ppEnum) {
return E_POINTER;
} else {
*ppEnum = new DirectShowPinEnum(QList<IPin *>() << this);
return S_OK;
}
}
HRESULT DirectShowIOSource::FindPin(LPCWSTR Id, IPin **ppPin)
{
if (!ppPin || !Id) {
return E_POINTER;
} else {
QMutexLocker locker(&m_mutex);
if (QString::fromWCharArray(Id) == m_pinId) {
AddRef();
*ppPin = this;
return S_OK;
} else {
*ppPin = 0;
return VFW_E_NOT_FOUND;
}
}
}
HRESULT DirectShowIOSource::JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName)
{
QMutexLocker locker(&m_mutex);
m_graph = pGraph;
m_filterName = QString::fromWCharArray(pName);
return S_OK;
}
HRESULT DirectShowIOSource::QueryFilterInfo(FILTER_INFO *pInfo)
{
if (!pInfo) {
return E_POINTER;
} else {
QString name = m_filterName;
if (name.length() >= MAX_FILTER_NAME)
name.truncate(MAX_FILTER_NAME - 1);
int length = name.toWCharArray(pInfo->achName);
pInfo->achName[length] = '\0';
if (m_graph)
m_graph->AddRef();
pInfo->pGraph = m_graph;
return S_OK;
}
}
HRESULT DirectShowIOSource::QueryVendorInfo(LPWSTR *pVendorInfo)
{
Q_UNUSED(pVendorInfo);
return E_NOTIMPL;
}
// IAMFilterMiscFlags
ULONG DirectShowIOSource::GetMiscFlags()
{
return AM_FILTER_MISC_FLAGS_IS_SOURCE;
}
// IPin
HRESULT DirectShowIOSource::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
{
QMutexLocker locker(&m_mutex);
if (!pReceivePin) {
return E_POINTER;
} else if (m_state != State_Stopped) {
return VFW_E_NOT_STOPPED;
} else if (m_peerPin) {
return VFW_E_ALREADY_CONNECTED;
} else {
HRESULT hr = VFW_E_TYPE_NOT_ACCEPTED;
m_peerPin = pReceivePin;
m_peerPin->AddRef();
if (!pmt) {
IEnumMediaTypes *mediaTypes = 0;
if (pReceivePin->EnumMediaTypes(&mediaTypes) == S_OK) {
for (AM_MEDIA_TYPE *type = 0;
mediaTypes->Next(1, &type, 0) == S_OK;
DirectShowMediaType::deleteType(type)) {
switch (tryConnect(pReceivePin, type)) {
case S_OK:
DirectShowMediaType::freeData(type);
mediaTypes->Release();
return S_OK;
case VFW_E_NO_TRANSPORT:
hr = VFW_E_NO_TRANSPORT;
break;
default:
break;
}
}
mediaTypes->Release();
}
AM_MEDIA_TYPE type =
{
MEDIATYPE_Stream, // majortype
MEDIASUBTYPE_NULL, // subtype
TRUE, // bFixedSizeSamples
FALSE, // bTemporalCompression
1, // lSampleSize
GUID_NULL, // formattype
0, // pUnk
0, // cbFormat
0, // pbFormat
};
static const int count = sizeof(directshow_subtypes) / sizeof(GUID);
for (int i = 0; i < count; ++i) {
type.subtype = directshow_subtypes[i];
switch (tryConnect(pReceivePin, &type)) {
case S_OK:
return S_OK;
case VFW_E_NO_TRANSPORT:
hr = VFW_E_NO_TRANSPORT;
break;
default:
break;
}
}
} else if (pmt->majortype == MEDIATYPE_Stream && (hr = tryConnect(pReceivePin, pmt))) {
return S_OK;
}
m_peerPin->Release();
m_peerPin = 0;
m_mediaType.clear();
return hr;
}
}
HRESULT DirectShowIOSource::tryConnect(IPin *pin, const AM_MEDIA_TYPE *type)
{
m_mediaType = *type;
HRESULT hr = pin->ReceiveConnection(this, type);
if (!SUCCEEDED(hr)) {
if (m_allocator) {
m_allocator->Release();
m_allocator = 0;
}
} else if (!m_allocator) {
hr = VFW_E_NO_TRANSPORT;
if (IMemInputPin *memPin = com_cast<IMemInputPin>(pin, IID_IMemInputPin)) {
if ((m_allocator = com_new<IMemAllocator>(CLSID_MemoryAllocator, IID_IMemAllocator))) {
ALLOCATOR_PROPERTIES properties;
if (memPin->GetAllocatorRequirements(&properties) == S_OK
|| m_allocator->GetProperties(&properties) == S_OK) {
if (properties.cbAlign == 0)
properties.cbAlign = 1;
ALLOCATOR_PROPERTIES actualProperties;
if (SUCCEEDED(hr = m_allocator->SetProperties(&properties, &actualProperties)))
hr = memPin->NotifyAllocator(m_allocator, TRUE);
}
if (!SUCCEEDED(hr)) {
m_allocator->Release();
m_allocator = 0;
}
}
memPin->Release();
}
if (!SUCCEEDED(hr))
pin->Disconnect();
}
return hr;
}
HRESULT DirectShowIOSource::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
{
Q_UNUSED(pConnector);
Q_UNUSED(pmt);
// Output pin.
return E_NOTIMPL;
}
HRESULT DirectShowIOSource::Disconnect()
{
if (!m_peerPin) {
return S_FALSE;
} else if (m_state != State_Stopped) {
return VFW_E_NOT_STOPPED;
} else {
HRESULT hr = m_peerPin->Disconnect();
if (!SUCCEEDED(hr))
return hr;
if (m_allocator) {
m_allocator->Release();
m_allocator = 0;
}
m_peerPin->Release();
m_peerPin = 0;
m_mediaType.clear();
return S_OK;
}
}
HRESULT DirectShowIOSource::ConnectedTo(IPin **ppPin)
{
if (!ppPin) {
return E_POINTER;
} else {
QMutexLocker locker(&m_mutex);
if (!m_peerPin) {
*ppPin = 0;
return VFW_E_NOT_CONNECTED;
} else {
m_peerPin->AddRef();
*ppPin = m_peerPin;
return S_OK;
}
}
}
HRESULT DirectShowIOSource::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
{
if (!pmt) {
return E_POINTER;
} else {
QMutexLocker locker(&m_mutex);
if (!m_peerPin) {
pmt = 0;
return VFW_E_NOT_CONNECTED;
} else {
DirectShowMediaType::copy(pmt, m_mediaType);
return S_OK;
}
}
}
HRESULT DirectShowIOSource::QueryPinInfo(PIN_INFO *pInfo)
{
if (!pInfo) {
return E_POINTER;
} else {
AddRef();
pInfo->pFilter = this;
pInfo->dir = PINDIR_OUTPUT;
const int bytes = qMin(MAX_FILTER_NAME, (m_pinId.length() + 1) * 2);
qMemCopy(pInfo->achName, m_pinId.utf16(), bytes);
return S_OK;
}
}
HRESULT DirectShowIOSource::QueryId(LPWSTR *Id)
{
if (!Id) {
return E_POINTER;
} else {
const int bytes = (m_pinId.length() + 1) * 2;
*Id = static_cast<LPWSTR>(::CoTaskMemAlloc(bytes));
qMemCopy(*Id, m_pinId.utf16(), bytes);
return S_OK;
}
}
HRESULT DirectShowIOSource::QueryAccept(const AM_MEDIA_TYPE *pmt)
{
if (!pmt) {
return E_POINTER;
} else if (pmt->majortype == MEDIATYPE_Stream) {
return S_OK;
} else {
return S_FALSE;
}
}
HRESULT DirectShowIOSource::EnumMediaTypes(IEnumMediaTypes **ppEnum)
{
if (!ppEnum) {
return E_POINTER;
} else {
*ppEnum = createMediaTypeEnum();
return S_OK;
}
}
HRESULT DirectShowIOSource::QueryInternalConnections(IPin **apPin, ULONG *nPin)
{
Q_UNUSED(apPin);
Q_UNUSED(nPin);
return E_NOTIMPL;
}
HRESULT DirectShowIOSource::EndOfStream()
{
return S_OK;
}
HRESULT DirectShowIOSource::BeginFlush()
{
return m_reader->BeginFlush();
}
HRESULT DirectShowIOSource::EndFlush()
{
return m_reader->EndFlush();
}
HRESULT DirectShowIOSource::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
{
Q_UNUSED(tStart);
Q_UNUSED(tStop);
Q_UNUSED(dRate);
return S_OK;
}
HRESULT DirectShowIOSource::QueryDirection(PIN_DIRECTION *pPinDir)
{
if (!pPinDir) {
return E_POINTER;
} else {
*pPinDir = PINDIR_OUTPUT;
return S_OK;
}
}
DirectShowRcSource::DirectShowRcSource(DirectShowEventLoop *loop)
: DirectShowIOSource(loop)
{
}
bool DirectShowRcSource::open(const QUrl &url)
{
m_file.moveToThread(QCoreApplication::instance()->thread());
m_file.setFileName(QLatin1Char(':') + url.path());
qDebug("qrc file %s", qPrintable(m_file.fileName()));
if (m_file.open(QIODevice::ReadOnly)) {
qDebug("Size %d", m_file.size());
qDebug("Sequential %d", int(m_file.isSequential()));
setDevice(&m_file);
return true;
} else {
return false;
}
}

View File

@@ -0,0 +1,149 @@
/****************************************************************************
**
** 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 DIRECTSHOWIOSOURCE_H
#define DIRECTSHOWIOSOURCE_H
#include "directshowglobal.h"
#include "directshowioreader.h"
#include "directshowmediatype.h"
#include "directshowmediatypelist.h"
#include <QtCore/qfile.h>
class DirectShowIOSource
: public DirectShowMediaTypeList
, public IBaseFilter
, public IAMFilterMiscFlags
, public IPin
{
public:
DirectShowIOSource(DirectShowEventLoop *loop);
~DirectShowIOSource();
void setDevice(QIODevice *device);
void setAllocator(IMemAllocator *allocator);
// IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
// IPersist
HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
// IMediaFilter
HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME tStart);
HRESULT STDMETHODCALLTYPE Pause();
HRESULT STDMETHODCALLTYPE Stop();
HRESULT STDMETHODCALLTYPE GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState);
HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *pClock);
HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **ppClock);
// IBaseFilter
HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **ppEnum);
HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR Id, IPin **ppPin);
HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName);
HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *pInfo);
HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *pVendorInfo);
// IAMFilterMiscFlags
ULONG STDMETHODCALLTYPE GetMiscFlags();
// IPin
HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt);
HRESULT STDMETHODCALLTYPE Disconnect();
HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **ppPin);
HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt);
HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo);
HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id);
HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt);
HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum);
HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin);
HRESULT STDMETHODCALLTYPE EndOfStream();
HRESULT STDMETHODCALLTYPE BeginFlush();
HRESULT STDMETHODCALLTYPE EndFlush();
HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir);
private:
HRESULT tryConnect(IPin *pin, const AM_MEDIA_TYPE *type);
volatile LONG m_ref;
FILTER_STATE m_state;
DirectShowIOReader *m_reader;
DirectShowEventLoop *m_loop;
IFilterGraph *m_graph;
IReferenceClock *m_clock;
IMemAllocator *m_allocator;
IPin *m_peerPin;
DirectShowMediaType m_mediaType;
QString m_filterName;
const QString m_pinId;
QMutex m_mutex;
};
class DirectShowRcSource : public DirectShowIOSource
{
public:
DirectShowRcSource(DirectShowEventLoop *loop);
bool open(const QUrl &url);
private:
QFile m_file;
};
#endif

View File

@@ -0,0 +1,184 @@
/****************************************************************************
**
** 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 "directshowmediatype.h"
namespace
{
struct TypeLookup
{
QVideoFrame::PixelFormat pixelFormat;
GUID mediaType;
};
static const TypeLookup qt_typeLookup[] =
{
{ QVideoFrame::Format_RGB32, /*MEDIASUBTYPE_RGB32*/ {0xe436eb7e, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} },
{ QVideoFrame::Format_BGR24, /*MEDIASUBTYPE_RGB24*/ {0xe436eb7d, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} },
{ QVideoFrame::Format_RGB565, /*MEDIASUBTYPE_RGB565*/ {0xe436eb7b, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} },
{ QVideoFrame::Format_RGB555, /*MEDIASUBTYPE_RGB555*/ {0xe436eb7c, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} },
{ QVideoFrame::Format_AYUV444, /*MEDIASUBTYPE_AYUV*/ {0x56555941, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
{ QVideoFrame::Format_YUYV, /*MEDIASUBTYPE_YUY2*/ {0x32595559, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
{ QVideoFrame::Format_UYVY, /*MEDIASUBTYPE_UYVY*/ {0x59565955, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
{ QVideoFrame::Format_IMC1, /*MEDIASUBTYPE_IMC1*/ {0x31434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
{ QVideoFrame::Format_IMC2, /*MEDIASUBTYPE_IMC2*/ {0x32434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
{ QVideoFrame::Format_IMC3, /*MEDIASUBTYPE_IMC3*/ {0x33434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
{ QVideoFrame::Format_IMC4, /*MEDIASUBTYPE_IMC4*/ {0x34434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
{ QVideoFrame::Format_YV12, /*MEDIASUBTYPE_YV12*/ {0x32315659, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
{ QVideoFrame::Format_NV12, /*MEDIASUBTYPE_NV12*/ {0x3231564E, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
{ QVideoFrame::Format_YUV420P, /*MEDIASUBTYPE_IYUV*/ {0x56555949, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} }
};
}
void DirectShowMediaType::copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE &source)
{
*target = source;
if (source.cbFormat > 0) {
target->pbFormat = reinterpret_cast<PBYTE>(CoTaskMemAlloc(source.cbFormat));
memcpy(target->pbFormat, source.pbFormat, source.cbFormat);
}
if (target->pUnk)
target->pUnk->AddRef();
}
void DirectShowMediaType::deleteType(AM_MEDIA_TYPE *type)
{
freeData(type);
CoTaskMemFree(type);
}
void DirectShowMediaType::freeData(AM_MEDIA_TYPE *type)
{
if (type->cbFormat > 0)
CoTaskMemFree(type->pbFormat);
if (type->pUnk)
type->pUnk->Release();
}
GUID DirectShowMediaType::convertPixelFormat(QVideoFrame::PixelFormat format)
{
// MEDIASUBTYPE_None;
static const GUID none = {
0xe436eb8e, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70} };
const int count = sizeof(qt_typeLookup) / sizeof(TypeLookup);
for (int i = 0; i < count; ++i)
if (qt_typeLookup[i].pixelFormat == format)
return qt_typeLookup[i].mediaType;
return none;
}
QVideoSurfaceFormat DirectShowMediaType::formatFromType(const AM_MEDIA_TYPE &type)
{
const int count = sizeof(qt_typeLookup) / sizeof(TypeLookup);
for (int i = 0; i < count; ++i) {
if (IsEqualGUID(qt_typeLookup[i].mediaType, type.subtype) && type.cbFormat > 0) {
if (IsEqualGUID(type.formattype, FORMAT_VideoInfo)) {
VIDEOINFOHEADER *header = reinterpret_cast<VIDEOINFOHEADER *>(type.pbFormat);
QVideoSurfaceFormat format(
QSize(header->bmiHeader.biWidth, qAbs(header->bmiHeader.biHeight)),
qt_typeLookup[i].pixelFormat);
if (header->AvgTimePerFrame > 0)
format.setFrameRate(10000 /header->AvgTimePerFrame);
format.setScanLineDirection(header->bmiHeader.biHeight < 0
? QVideoSurfaceFormat::TopToBottom
: QVideoSurfaceFormat::BottomToTop);
return format;
} else if (IsEqualGUID(type.formattype, FORMAT_VideoInfo2)) {
VIDEOINFOHEADER2 *header = reinterpret_cast<VIDEOINFOHEADER2 *>(type.pbFormat);
QVideoSurfaceFormat format(
QSize(header->bmiHeader.biWidth, qAbs(header->bmiHeader.biHeight)),
qt_typeLookup[i].pixelFormat);
if (header->AvgTimePerFrame > 0)
format.setFrameRate(10000 / header->AvgTimePerFrame);
format.setScanLineDirection(header->bmiHeader.biHeight < 0
? QVideoSurfaceFormat::TopToBottom
: QVideoSurfaceFormat::BottomToTop);
return format;
}
}
}
return QVideoSurfaceFormat();
}
int DirectShowMediaType::bytesPerLine(const QVideoSurfaceFormat &format)
{
switch (format.pixelFormat()) {
// 32 bpp packed formats.
case QVideoFrame::Format_RGB32:
case QVideoFrame::Format_AYUV444:
return format.frameWidth() * 4;
// 24 bpp packed formats.
case QVideoFrame::Format_RGB24:
return format.frameWidth() * 3 + 3 - format.frameWidth() % 4;
// 16 bpp packed formats.
case QVideoFrame::Format_RGB565:
case QVideoFrame::Format_RGB555:
case QVideoFrame::Format_YUYV:
case QVideoFrame::Format_UYVY:
return format.frameWidth() * 2 + 3 - format.frameWidth() % 4;
// Planar formats.
case QVideoFrame::Format_IMC1:
case QVideoFrame::Format_IMC2:
case QVideoFrame::Format_IMC3:
case QVideoFrame::Format_IMC4:
case QVideoFrame::Format_YV12:
case QVideoFrame::Format_NV12:
case QVideoFrame::Format_YUV420P:
return format.frameWidth() + 3 - format.frameWidth() % 4;
default:
return 0;
}
}

View File

@@ -0,0 +1,74 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DIRECTSHOWMEDIATYPE_H
#define DIRECTSHOWMEDIATYPE_H
#include <qvideosurfaceformat.h>
#include <dshow.h>
#include <dvdmedia.h>
class DirectShowMediaType : public AM_MEDIA_TYPE
{
public:
DirectShowMediaType() { memset(this, 0, sizeof(DirectShowMediaType)); }
DirectShowMediaType(const AM_MEDIA_TYPE &type) { copy(this, type); }
DirectShowMediaType(const DirectShowMediaType &other) { copy(this, other); }
DirectShowMediaType &operator =(const AM_MEDIA_TYPE &type) {
freeData(this); copy(this, type); return *this; }
DirectShowMediaType &operator =(const DirectShowMediaType &other) {
freeData(this); copy(this, other); return *this; }
~DirectShowMediaType() { freeData(this); }
void clear() { freeData(this); memset(this, 0, sizeof(DirectShowMediaType)); }
static void copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE &source);
static void freeData(AM_MEDIA_TYPE *type);
static void deleteType(AM_MEDIA_TYPE *type);
static GUID convertPixelFormat(QVideoFrame::PixelFormat format);
static QVideoSurfaceFormat formatFromType(const AM_MEDIA_TYPE &type);
static int bytesPerLine(const QVideoSurfaceFormat &format);
};
#endif

View File

@@ -0,0 +1,226 @@
/****************************************************************************
**
** 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 "directshowmediatypelist.h"
#include "directshowmediatype.h"
#include "videosurfacefilter.h"
class DirectShowMediaTypeEnum : public IEnumMediaTypes
{
public:
DirectShowMediaTypeEnum(DirectShowMediaTypeList *list, int token, int index = 0);
~DirectShowMediaTypeEnum();
// IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
// IEnumMediaTypes
HRESULT STDMETHODCALLTYPE Next(
ULONG cMediaTypes, AM_MEDIA_TYPE **ppMediaTypes, ULONG *pcFetched);
HRESULT STDMETHODCALLTYPE Skip(ULONG cMediaTypes);
HRESULT STDMETHODCALLTYPE Reset();
HRESULT STDMETHODCALLTYPE Clone(IEnumMediaTypes **ppEnum);
private:
LONG m_ref;
DirectShowMediaTypeList *m_list;
int m_mediaTypeToken;
int m_index;
};
DirectShowMediaTypeEnum::DirectShowMediaTypeEnum(
DirectShowMediaTypeList *list, int token, int index)
: m_ref(1)
, m_list(list)
, m_mediaTypeToken(token)
, m_index(index)
{
m_list->AddRef();
}
DirectShowMediaTypeEnum::~DirectShowMediaTypeEnum()
{
m_list->Release();
}
HRESULT DirectShowMediaTypeEnum::QueryInterface(REFIID riid, void **ppvObject)
{
if (!ppvObject) {
return E_POINTER;
} else if (riid == IID_IUnknown
|| riid == IID_IEnumMediaTypes) {
*ppvObject = static_cast<IEnumMediaTypes *>(this);
} else {
*ppvObject = 0;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
ULONG DirectShowMediaTypeEnum::AddRef()
{
return InterlockedIncrement(&m_ref);
}
ULONG DirectShowMediaTypeEnum::Release()
{
ULONG ref = InterlockedDecrement(&m_ref);
if (ref == 0) {
delete this;
}
return ref;
}
HRESULT DirectShowMediaTypeEnum::Next(
ULONG cMediaTypes, AM_MEDIA_TYPE **ppMediaTypes, ULONG *pcFetched)
{
return m_list->nextMediaType(m_mediaTypeToken, &m_index, cMediaTypes, ppMediaTypes, pcFetched);
}
HRESULT DirectShowMediaTypeEnum::Skip(ULONG cMediaTypes)
{
return m_list->skipMediaType(m_mediaTypeToken, &m_index, cMediaTypes);
}
HRESULT DirectShowMediaTypeEnum::Reset()
{
m_mediaTypeToken = m_list->currentMediaTypeToken();
m_index = 0;
return S_OK;
}
HRESULT DirectShowMediaTypeEnum::Clone(IEnumMediaTypes **ppEnum)
{
return m_list->cloneMediaType(m_mediaTypeToken, m_index, ppEnum);
}
DirectShowMediaTypeList::DirectShowMediaTypeList()
: m_mediaTypeToken(0)
{
}
IEnumMediaTypes *DirectShowMediaTypeList::createMediaTypeEnum()
{
return new DirectShowMediaTypeEnum(this, m_mediaTypeToken, 0);
}
void DirectShowMediaTypeList::setMediaTypes(const QVector<AM_MEDIA_TYPE> &types)
{
++m_mediaTypeToken;
m_mediaTypes = types;
}
int DirectShowMediaTypeList::currentMediaTypeToken()
{
return m_mediaTypeToken;
}
HRESULT DirectShowMediaTypeList::nextMediaType(
int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount)
{
if (!types || (count != 1 && !fetchedCount)) {
return E_POINTER;
} else if (m_mediaTypeToken != token) {
return VFW_E_ENUM_OUT_OF_SYNC;
} else {
int boundedCount = qBound<int>(0, count, m_mediaTypes.count() - *index);
for (int i = 0; i < boundedCount; ++i, ++(*index)) {
types[i] = reinterpret_cast<AM_MEDIA_TYPE *>(CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE)));
if (types[i]) {
DirectShowMediaType::copy(types[i], m_mediaTypes.at(*index));
} else {
for (--i; i >= 0; --i)
CoTaskMemFree(types[i]);
if (fetchedCount)
*fetchedCount = 0;
return E_OUTOFMEMORY;
}
}
if (fetchedCount)
*fetchedCount = boundedCount;
return boundedCount == count ? S_OK : S_FALSE;
}
}
HRESULT DirectShowMediaTypeList::skipMediaType(int token, int *index, ULONG count)
{
if (m_mediaTypeToken != token) {
return VFW_E_ENUM_OUT_OF_SYNC;
} else {
*index = qMin<int>(*index + count, m_mediaTypes.size());
return *index < m_mediaTypes.size() ? S_OK : S_FALSE;
}
}
HRESULT DirectShowMediaTypeList::cloneMediaType(int token, int index, IEnumMediaTypes **enumeration)
{
if (m_mediaTypeToken != token) {
return VFW_E_ENUM_OUT_OF_SYNC;
} else {
*enumeration = new DirectShowMediaTypeEnum(this, token, index);
return S_OK;
}
}

View File

@@ -0,0 +1,69 @@
/****************************************************************************
**
** 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 DIRECTSHOWMEDIATYPELIST_H
#define DIRECTSHOWMEDIATYPELIST_H
#include <QtCore/qvector.h>
#include <dshow.h>
class DirectShowMediaTypeList : public IUnknown
{
public:
DirectShowMediaTypeList();
IEnumMediaTypes *createMediaTypeEnum();
void setMediaTypes(const QVector<AM_MEDIA_TYPE> &types);
virtual int currentMediaTypeToken();
virtual HRESULT nextMediaType(
int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount);
virtual HRESULT skipMediaType(int token, int *index, ULONG count);
virtual HRESULT cloneMediaType(int token, int index, IEnumMediaTypes **enumeration);
private:
int m_mediaTypeToken;
QVector<AM_MEDIA_TYPE> m_mediaTypes;
};
#endif

View File

@@ -0,0 +1,352 @@
/****************************************************************************
**
** 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 <dshow.h>
#include <initguid.h>
#include <qnetwork.h>
#include "directshowmetadatacontrol.h"
#include "directshowplayerservice.h"
#include <QtCore/qcoreapplication.h>
#ifndef QT_NO_WMSDK
namespace
{
struct QWMMetaDataKeyLookup
{
QtMultimediaKit::MetaData key;
const wchar_t *token;
};
}
static const QWMMetaDataKeyLookup qt_wmMetaDataKeys[] =
{
{ QtMultimediaKit::Title, L"Title" },
{ QtMultimediaKit::SubTitle, L"WM/SubTitle" },
{ QtMultimediaKit::Author, L"Author" },
{ QtMultimediaKit::Comment, L"Comment" },
{ QtMultimediaKit::Description, L"Description" },
{ QtMultimediaKit::Category, L"WM/Category" },
{ QtMultimediaKit::Genre, L"WM/Genre" },
//{ QtMultimediaKit::Date, 0 },
{ QtMultimediaKit::Year, L"WM/Year" },
{ QtMultimediaKit::UserRating, L"UserRating" },
//{ QtMultimediaKit::MetaDatawords, 0 },
{ QtMultimediaKit::Language, L"Language" },
{ QtMultimediaKit::Publisher, L"WM/Publisher" },
{ QtMultimediaKit::Copyright, L"Copyright" },
{ QtMultimediaKit::ParentalRating, L"ParentalRating" },
{ QtMultimediaKit::RatingOrganisation, L"RatingOrganisation" },
// Media
{ QtMultimediaKit::Size, L"FileSize" },
{ QtMultimediaKit::MediaType, L"MediaType" },
{ QtMultimediaKit::Duration, L"Duration" },
// Audio
{ QtMultimediaKit::AudioBitRate, L"AudioBitRate" },
{ QtMultimediaKit::AudioCodec, L"AudioCodec" },
{ QtMultimediaKit::ChannelCount, L"ChannelCount" },
{ QtMultimediaKit::SampleRate, L"Frequency" },
// Music
{ QtMultimediaKit::AlbumTitle, L"WM/AlbumTitle" },
{ QtMultimediaKit::AlbumArtist, L"WM/AlbumArtist" },
{ QtMultimediaKit::ContributingArtist, L"Author" },
{ QtMultimediaKit::Composer, L"WM/Composer" },
{ QtMultimediaKit::Conductor, L"WM/Conductor" },
{ QtMultimediaKit::Lyrics, L"WM/Lyrics" },
{ QtMultimediaKit::Mood, L"WM/Mood" },
{ QtMultimediaKit::TrackNumber, L"WM/TrackNumber" },
//{ QtMultimediaKit::TrackCount, 0 },
//{ QtMultimediaKit::CoverArtUriSmall, 0 },
//{ QtMultimediaKit::CoverArtUriLarge, 0 },
// Image/Video
//{ QtMultimediaKit::Resolution, 0 },
//{ QtMultimediaKit::PixelAspectRatio, 0 },
// Video
//{ QtMultimediaKit::FrameRate, 0 },
{ QtMultimediaKit::VideoBitRate, L"VideoBitRate" },
{ QtMultimediaKit::VideoCodec, L"VideoCodec" },
//{ QtMultimediaKit::PosterUri, 0 },
// Movie
{ QtMultimediaKit::ChapterNumber, L"ChapterNumber" },
{ QtMultimediaKit::Director, L"WM/Director" },
{ QtMultimediaKit::LeadPerformer, L"LeadPerformer" },
{ QtMultimediaKit::Writer, L"WM/Writer" },
// Photos
{ QtMultimediaKit::CameraManufacturer, L"CameraManufacturer" },
{ QtMultimediaKit::CameraModel, L"CameraModel" },
{ QtMultimediaKit::Event, L"Event" },
{ QtMultimediaKit::Subject, L"Subject" }
};
static QVariant getValue(IWMHeaderInfo *header, const wchar_t *key)
{
WORD streamNumber = 0;
WMT_ATTR_DATATYPE type = WMT_TYPE_DWORD;
WORD size = 0;
if (header->GetAttributeByName(&streamNumber, key, &type, 0, &size) == S_OK) {
switch (type) {
case WMT_TYPE_DWORD:
if (size == sizeof(DWORD)) {
DWORD word;
if (header->GetAttributeByName(
&streamNumber,
key,
&type,
reinterpret_cast<BYTE *>(&word),
&size) == S_OK) {
return int(word);
}
}
break;
case WMT_TYPE_STRING:
{
QString string;
string.resize(size / 2 - 1);
if (header->GetAttributeByName(
&streamNumber,
key,
&type,
reinterpret_cast<BYTE *>(const_cast<ushort *>(string.utf16())),
&size) == S_OK) {
return string;
}
}
break;
case WMT_TYPE_BINARY:
{
QByteArray bytes;
bytes.resize(size);
if (header->GetAttributeByName(
&streamNumber,
key,
&type,
reinterpret_cast<BYTE *>(bytes.data()),
&size) == S_OK) {
return bytes;
}
}
break;
case WMT_TYPE_BOOL:
if (size == sizeof(DWORD)) {
DWORD word;
if (header->GetAttributeByName(
&streamNumber,
key,
&type,
reinterpret_cast<BYTE *>(&word),
&size) == S_OK) {
return bool(word);
}
}
break;
case WMT_TYPE_QWORD:
if (size == sizeof(QWORD)) {
QWORD word;
if (header->GetAttributeByName(
&streamNumber,
key,
&type,
reinterpret_cast<BYTE *>(&word),
&size) == S_OK) {
return qint64(word);
}
}
break;
case WMT_TYPE_WORD:
if (size == sizeof(WORD)){
WORD word;
if (header->GetAttributeByName(
&streamNumber,
key,
&type,
reinterpret_cast<BYTE *>(&word),
&size) == S_OK) {
return short(word);
}
}
break;
case WMT_TYPE_GUID:
if (size == 16) {
}
break;
default:
break;
}
}
return QVariant();
}
#endif
DirectShowMetaDataControl::DirectShowMetaDataControl(QObject *parent)
: QMetaDataReaderControl(parent)
, m_content(0)
#ifndef QT_NO_WMSDK
, m_headerInfo(0)
#endif
{
}
DirectShowMetaDataControl::~DirectShowMetaDataControl()
{
}
bool DirectShowMetaDataControl::isMetaDataAvailable() const
{
#ifndef QT_NO_WMSDK
return m_content || m_headerInfo;
#else
return m_content;
#endif
}
QVariant DirectShowMetaDataControl::metaData(QtMultimediaKit::MetaData key) const
{
QVariant value;
#ifndef QT_NO_WMSDK
if (m_headerInfo) {
static const int count = sizeof(qt_wmMetaDataKeys) / sizeof(QWMMetaDataKeyLookup);
for (int i = 0; i < count; ++i) {
if (qt_wmMetaDataKeys[i].key == key) {
value = getValue(m_headerInfo, qt_wmMetaDataKeys[i].token);
break;
}
}
} else if (m_content) {
#else
if (m_content) {
#endif
BSTR string = 0;
switch (key) {
case QtMultimediaKit::Author:
m_content->get_AuthorName(&string);
break;
case QtMultimediaKit::Title:
m_content->get_Title(&string);
break;
case QtMultimediaKit::ParentalRating:
m_content->get_Rating(&string);
break;
case QtMultimediaKit::Description:
m_content->get_Description(&string);
break;
case QtMultimediaKit::Copyright:
m_content->get_Copyright(&string);
break;
default:
break;
}
if (string) {
value = QString::fromUtf16(reinterpret_cast<ushort *>(string), ::SysStringLen(string));
::SysFreeString(string);
}
}
return value;
}
QList<QtMultimediaKit::MetaData> DirectShowMetaDataControl::availableMetaData() const
{
return QList<QtMultimediaKit::MetaData>();
}
QVariant DirectShowMetaDataControl::extendedMetaData(const QString &) const
{
return QVariant();
}
QStringList DirectShowMetaDataControl::availableExtendedMetaData() const
{
return QStringList();
}
void DirectShowMetaDataControl::updateGraph(IFilterGraph2 *graph, IBaseFilter *source)
{
if (m_content)
m_content->Release();
if (!graph || graph->QueryInterface(
IID_IAMMediaContent, reinterpret_cast<void **>(&m_content)) != S_OK) {
m_content = 0;
}
#ifdef QT_NO_WMSDK
Q_UNUSED(source);
#else
if (m_headerInfo)
m_headerInfo->Release();
m_headerInfo = com_cast<IWMHeaderInfo>(source, IID_IWMHeaderInfo);
#endif
// DirectShowMediaPlayerService holds a lock at this point so defer emitting signals to a later
// time.
QCoreApplication::postEvent(this, new QEvent(QEvent::Type(MetaDataChanged)));
}
void DirectShowMetaDataControl::customEvent(QEvent *event)
{
if (event->type() == QEvent::Type(MetaDataChanged)) {
event->accept();
emit metaDataChanged();
#ifndef QT_NO_WMSDK
emit metaDataAvailableChanged(m_content || m_headerInfo);
#else
emit metaDataAvailableChanged(m_content);
#endif
} else {
QMetaDataReaderControl::customEvent(event);
}
}

View File

@@ -0,0 +1,93 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DIRECTSHOWMETADATACONTROL_H
#define DIRECTSHOWMETADATACONTROL_H
#include <qmetadatareadercontrol.h>
#include "directshowglobal.h"
#include <qnetwork.h>
#ifndef QT_NO_WMSDK
#include <wmsdk.h>
#endif
#include <QtCore/qcoreevent.h>
class DirectShowPlayerService;
QT_USE_NAMESPACE
class DirectShowMetaDataControl : public QMetaDataReaderControl
{
Q_OBJECT
public:
DirectShowMetaDataControl(QObject *parent = 0);
~DirectShowMetaDataControl();
bool isMetaDataAvailable() const;
QVariant metaData(QtMultimediaKit::MetaData key) const;
QList<QtMultimediaKit::MetaData> availableMetaData() const;
QVariant extendedMetaData(const QString &key) const;
QStringList availableExtendedMetaData() const;
void updateGraph(IFilterGraph2 *graph, IBaseFilter *source);
protected:
void customEvent(QEvent *event);
private:
enum Event
{
MetaDataChanged = QEvent::User
};
IAMMediaContent *m_content;
#ifndef QT_NO_WMSDK
IWMHeaderInfo *m_headerInfo;
#endif
};
#endif

View File

@@ -0,0 +1,134 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "directshowpinenum.h"
DirectShowPinEnum::DirectShowPinEnum(const QList<IPin *> &pins)
: m_ref(1)
, m_pins(pins)
, m_index(0)
{
foreach (IPin *pin, m_pins)
pin->AddRef();
}
DirectShowPinEnum::~DirectShowPinEnum()
{
foreach (IPin *pin, m_pins)
pin->Release();
}
HRESULT DirectShowPinEnum::QueryInterface(REFIID riid, void **ppvObject)
{
if (riid == IID_IUnknown
|| riid == IID_IEnumPins) {
AddRef();
*ppvObject = static_cast<IEnumPins *>(this);
return S_OK;
} else {
*ppvObject = 0;
return E_NOINTERFACE;
}
}
ULONG DirectShowPinEnum::AddRef()
{
return InterlockedIncrement(&m_ref);
}
ULONG DirectShowPinEnum::Release()
{
ULONG ref = InterlockedDecrement(&m_ref);
if (ref == 0) {
delete this;
}
return ref;
}
HRESULT DirectShowPinEnum::Next(ULONG cPins, IPin **ppPins, ULONG *pcFetched)
{
if (ppPins && (pcFetched || cPins == 1)) {
ULONG count = qBound<ULONG>(0, cPins, m_pins.count() - m_index);
for (ULONG i = 0; i < count; ++i, ++m_index) {
ppPins[i] = m_pins.at(m_index);
ppPins[i]->AddRef();
}
if (pcFetched)
*pcFetched = count;
return count == cPins ? S_OK : S_FALSE;
} else {
return E_POINTER;
}
}
HRESULT DirectShowPinEnum::Skip(ULONG cPins)
{
m_index = qMin(int(m_index + cPins), m_pins.count());
return m_index < m_pins.count() ? S_OK : S_FALSE;
}
HRESULT DirectShowPinEnum::Reset()
{
m_index = 0;
return S_OK;
}
HRESULT DirectShowPinEnum::Clone(IEnumPins **ppEnum)
{
if (ppEnum) {
*ppEnum = new DirectShowPinEnum(m_pins);
return S_OK;
} else {
return E_POINTER;
}
}

View File

@@ -0,0 +1,72 @@
/****************************************************************************
**
** 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 DIRECTSHOWPINENUM_H
#define DIRECTSHOWPINENUM_H
#include <QtCore/qlist.h>
#include <dshow.h>
class DirectShowPinEnum : public IEnumPins
{
public:
DirectShowPinEnum(const QList<IPin *> &pins);
~DirectShowPinEnum();
// IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
// IEnumPins
HRESULT STDMETHODCALLTYPE Next(ULONG cPins, IPin **ppPins, ULONG *pcFetched);
HRESULT STDMETHODCALLTYPE Skip(ULONG cPins);
HRESULT STDMETHODCALLTYPE Reset();
HRESULT STDMETHODCALLTYPE Clone(IEnumPins **ppEnum);
private:
LONG m_ref;
QList<IPin *> m_pins;
int m_index;
};
#endif

View File

@@ -0,0 +1,405 @@
/****************************************************************************
**
** 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 "directshowplayercontrol.h"
#include "directshowplayerservice.h"
#include <QtCore/qcoreapplication.h>
#include <QtCore/qmath.h>
static int volumeToDecibels(int volume)
{
if (volume == 0) {
return -10000;
} else if (volume == 100) {
return 0;
#ifdef QT_USE_MATH_H_FLOATS
} else if (sizeof(qreal) == sizeof(float)) {
return qRound(::log10f(float(volume) / 100) * 5000);
#endif
} else {
return qRound(::log10(qreal(volume) / 100) * 5000);
}
}
static int decibelsToVolume(int dB)
{
if (dB == -10000) {
return 0;
} else if (dB == 0) {
return 100;
} else {
return qRound(100 * qPow(10, qreal(dB) / 5000));
}
}
DirectShowPlayerControl::DirectShowPlayerControl(DirectShowPlayerService *service, QObject *parent)
: QMediaPlayerControl(parent)
, m_service(service)
, m_audio(0)
, m_updateProperties(0)
, m_state(QMediaPlayer::StoppedState)
, m_status(QMediaPlayer::NoMedia)
, m_error(QMediaPlayer::NoError)
, m_streamTypes(0)
, m_muteVolume(-1)
, m_position(0)
, m_duration(0)
, m_playbackRate(0)
, m_seekable(false)
{
}
DirectShowPlayerControl::~DirectShowPlayerControl()
{
if (m_audio)
m_audio->Release();
}
QMediaPlayer::State DirectShowPlayerControl::state() const
{
return m_state;
}
QMediaPlayer::MediaStatus DirectShowPlayerControl::mediaStatus() const
{
return m_status;
}
qint64 DirectShowPlayerControl::duration() const
{
return m_duration;
}
qint64 DirectShowPlayerControl::position() const
{
return const_cast<qint64 &>(m_position) = m_service->position();
}
void DirectShowPlayerControl::setPosition(qint64 position)
{
m_service->seek(position);
}
int DirectShowPlayerControl::volume() const
{
if (m_muteVolume >= 0) {
return m_muteVolume;
} else if (m_audio) {
long dB = 0;
m_audio->get_Volume(&dB);
return decibelsToVolume(dB);
} else {
return 0;
}
}
void DirectShowPlayerControl::setVolume(int volume)
{
int boundedVolume = qBound(0, volume, 100);
if (m_muteVolume >= 0) {
m_muteVolume = boundedVolume;
emit volumeChanged(m_muteVolume);
} else if (m_audio) {
m_audio->put_Volume(volumeToDecibels(volume));
emit volumeChanged(boundedVolume);
}
}
bool DirectShowPlayerControl::isMuted() const
{
return m_muteVolume >= 0;
}
void DirectShowPlayerControl::setMuted(bool muted)
{
if (muted && m_muteVolume < 0) {
if (m_audio) {
long dB = 0;
m_audio->get_Volume(&dB);
m_muteVolume = decibelsToVolume(dB);
m_audio->put_Volume(-10000);
} else {
m_muteVolume = 0;
}
emit mutedChanged(muted);
} else if (!muted && m_muteVolume >= 0) {
if (m_audio) {
m_audio->put_Volume(volumeToDecibels(m_muteVolume));
}
m_muteVolume = -1;
emit mutedChanged(muted);
}
}
int DirectShowPlayerControl::bufferStatus() const
{
return m_service->bufferStatus();
}
bool DirectShowPlayerControl::isAudioAvailable() const
{
return m_streamTypes & DirectShowPlayerService::AudioStream;
}
bool DirectShowPlayerControl::isVideoAvailable() const
{
return m_streamTypes & DirectShowPlayerService::VideoStream;
}
bool DirectShowPlayerControl::isSeekable() const
{
return m_seekable;
}
QMediaTimeRange DirectShowPlayerControl::availablePlaybackRanges() const
{
return m_service->availablePlaybackRanges();
}
qreal DirectShowPlayerControl::playbackRate() const
{
return m_playbackRate;
}
void DirectShowPlayerControl::setPlaybackRate(qreal rate)
{
if (m_playbackRate != rate) {
m_service->setRate(rate);
emit playbackRateChanged(m_playbackRate = rate);
}
}
QMediaContent DirectShowPlayerControl::media() const
{
return m_media;
}
const QIODevice *DirectShowPlayerControl::mediaStream() const
{
return m_stream;
}
void DirectShowPlayerControl::setMedia(const QMediaContent &media, QIODevice *stream)
{
m_media = media;
m_stream = stream;
m_updateProperties &= PlaybackRateProperty;
m_service->load(media, stream);
emit mediaChanged(m_media);
emitPropertyChanges();
}
void DirectShowPlayerControl::play()
{
if (m_status == QMediaPlayer::NoMedia)
return;
if (m_status == QMediaPlayer::InvalidMedia) {
setMedia(m_media, m_stream);
if (m_error != QMediaPlayer::NoError)
return;
}
m_service->play();
emit stateChanged(m_state = QMediaPlayer::PlayingState);
}
void DirectShowPlayerControl::pause()
{
if (m_status == QMediaPlayer::NoMedia)
return;
if (m_status == QMediaPlayer::InvalidMedia) {
setMedia(m_media, m_stream);
if (m_error != QMediaPlayer::NoError)
return;
}
m_service->pause();
emit stateChanged(m_state = QMediaPlayer::PausedState);
}
void DirectShowPlayerControl::stop()
{
m_service->stop();
emit stateChanged(m_state = QMediaPlayer::StoppedState);
}
void DirectShowPlayerControl::customEvent(QEvent *event)
{
if (event->type() == QEvent::Type(PropertiesChanged)) {
emitPropertyChanges();
event->accept();
} else {
QMediaPlayerControl::customEvent(event);
}
}
void DirectShowPlayerControl::emitPropertyChanges()
{
int properties = m_updateProperties;
m_updateProperties = 0;
if ((properties & ErrorProperty) && m_error != QMediaPlayer::NoError)
emit error(m_error, m_errorString);
if (properties & PlaybackRateProperty)
emit playbackRateChanged(m_playbackRate);
if (properties & StreamTypesProperty) {
emit audioAvailableChanged(m_streamTypes & DirectShowPlayerService::AudioStream);
emit videoAvailableChanged(m_streamTypes & DirectShowPlayerService::VideoStream);
}
if (properties & PositionProperty)
emit positionChanged(m_position);
if (properties & DurationProperty)
emit durationChanged(m_duration);
if (properties & SeekableProperty)
emit seekableChanged(m_seekable);
if (properties & StatusProperty)
emit mediaStatusChanged(m_status);
if (properties & StateProperty)
emit stateChanged(m_state);
}
void DirectShowPlayerControl::scheduleUpdate(int properties)
{
if (m_updateProperties == 0)
QCoreApplication::postEvent(this, new QEvent(QEvent::Type(PropertiesChanged)));
m_updateProperties |= properties;
}
void DirectShowPlayerControl::updateState(QMediaPlayer::State state)
{
if (m_state != state) {
m_state = state;
scheduleUpdate(StateProperty);
}
}
void DirectShowPlayerControl::updateStatus(QMediaPlayer::MediaStatus status)
{
if (m_status != status) {
m_status = status;
scheduleUpdate(StatusProperty);
}
}
void DirectShowPlayerControl::updateMediaInfo(qint64 duration, int streamTypes, bool seekable)
{
int properties = 0;
if (m_duration != duration) {
m_duration = duration;
properties |= DurationProperty;
}
if (m_streamTypes != streamTypes) {
m_streamTypes = streamTypes;
properties |= StreamTypesProperty;
}
if (m_seekable != seekable) {
m_seekable = seekable;
properties |= SeekableProperty;
}
if (properties != 0)
scheduleUpdate(properties);
}
void DirectShowPlayerControl::updatePlaybackRate(qreal rate)
{
if (m_playbackRate != rate) {
m_playbackRate = rate;
scheduleUpdate(PlaybackRateProperty);
}
}
void DirectShowPlayerControl::updateAudioOutput(IBaseFilter *filter)
{
if (m_audio)
m_audio->Release();
m_audio = com_cast<IBasicAudio>(filter, IID_IBasicAudio);
}
void DirectShowPlayerControl::updateError(QMediaPlayer::Error error, const QString &errorString)
{
m_error = error;
m_errorString = errorString;
if (m_error != QMediaPlayer::NoError)
scheduleUpdate(ErrorProperty);
}
void DirectShowPlayerControl::updatePosition(qint64 position)
{
if (m_position != position) {
m_position = position;
scheduleUpdate(PositionProperty);
}
}

View File

@@ -0,0 +1,146 @@
/****************************************************************************
**
** 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 DIRECTSHOWPLAYERCONTROL_H
#define DIRECTSHOWPLAYERCONTROL_H
#include "qmediacontent.h"
#include "qmediaplayercontrol.h"
#include <QtCore/qcoreevent.h>
#include "directshowplayerservice.h"
QT_USE_NAMESPACE
class DirectShowPlayerControl : public QMediaPlayerControl
{
Q_OBJECT
public:
DirectShowPlayerControl(DirectShowPlayerService *service, QObject *parent = 0);
~DirectShowPlayerControl();
QMediaPlayer::State state() const;
QMediaPlayer::MediaStatus mediaStatus() const;
qint64 duration() const;
qint64 position() const;
void setPosition(qint64 position);
int volume() const;
void setVolume(int volume);
bool isMuted() const;
void setMuted(bool muted);
int bufferStatus() const;
bool isAudioAvailable() const;
bool isVideoAvailable() const;
bool isSeekable() const;
QMediaTimeRange availablePlaybackRanges() const;
qreal playbackRate() const;
void setPlaybackRate(qreal rate);
QMediaContent media() const;
const QIODevice *mediaStream() const;
void setMedia(const QMediaContent &media, QIODevice *stream);
void play();
void pause();
void stop();
void updateState(QMediaPlayer::State state);
void updateStatus(QMediaPlayer::MediaStatus status);
void updateMediaInfo(qint64 duration, int streamTypes, bool seekable);
void updatePlaybackRate(qreal rate);
void updateAudioOutput(IBaseFilter *filter);
void updateError(QMediaPlayer::Error error, const QString &errorString);
void updatePosition(qint64 position);
protected:
void customEvent(QEvent *event);
private:
enum Properties
{
StateProperty = 0x01,
StatusProperty = 0x02,
StreamTypesProperty = 0x04,
DurationProperty = 0x08,
PlaybackRateProperty = 0x10,
SeekableProperty = 0x20,
ErrorProperty = 0x40,
PositionProperty = 0x80
};
enum Event
{
PropertiesChanged = QEvent::User
};
void scheduleUpdate(int properties);
void emitPropertyChanges();
DirectShowPlayerService *m_service;
IBasicAudio *m_audio;
QIODevice *m_stream;
int m_updateProperties;
QMediaPlayer::State m_state;
QMediaPlayer::MediaStatus m_status;
QMediaPlayer::Error m_error;
int m_streamTypes;
int m_muteVolume;
qint64 m_position;
qint64 m_duration;
qreal m_playbackRate;
bool m_seekable;
QMediaContent m_media;
QString m_errorString;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,219 @@
/****************************************************************************
**
** 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 DIRECTSHOWPLAYERSERVICE_H
#define DIRECTSHOWPLAYERSERVICE_H
#include "qmediaplayer.h"
#include "qmediaresource.h"
#include "qmediaservice.h"
#include "qmediatimerange.h"
#include "directshoweventloop.h"
#include "directshowglobal.h"
#include <QtCore/qcoreevent.h>
#include <QtCore/qmutex.h>
#include <QtCore/qurl.h>
#include <QtCore/qwaitcondition.h>
class DirectShowAudioEndpointControl;
class DirectShowMetaDataControl;
class DirectShowPlayerControl;
class DirectShowVideoRendererControl;
#ifndef Q_WS_SIMULATOR
class Vmr9VideoWindowControl;
#endif
QT_BEGIN_NAMESPACE
class QMediaContent;
QT_END_NAMESPACE
QT_USE_NAMESPACE
class DirectShowPlayerService : public QMediaService
{
Q_OBJECT
public:
enum StreamType
{
AudioStream = 0x01,
VideoStream = 0x02
};
DirectShowPlayerService(QObject *parent = 0);
~DirectShowPlayerService();
QMediaControl* requestControl(const char *name);
void releaseControl(QMediaControl *control);
void load(const QMediaContent &media, QIODevice *stream);
void play();
void pause();
void stop();
qint64 position() const;
QMediaTimeRange availablePlaybackRanges() const;
void seek(qint64 position);
void setRate(qreal rate);
int bufferStatus() const;
void setAudioOutput(IBaseFilter *filter);
void setVideoOutput(IBaseFilter *filter);
protected:
void customEvent(QEvent *event);
private Q_SLOTS:
void videoOutputChanged();
private:
void releaseGraph();
void updateStatus();
int findStreamTypes(IBaseFilter *source) const;
int findStreamType(IPin *pin) const;
bool isConnected(IBaseFilter *filter, PIN_DIRECTION direction) const;
IBaseFilter *getConnected(IBaseFilter *filter, PIN_DIRECTION direction) const;
void run();
void doSetUrlSource(QMutexLocker *locker);
void doSetStreamSource(QMutexLocker *locker);
void doRender(QMutexLocker *locker);
void doFinalizeLoad(QMutexLocker *locker);
void doSetRate(QMutexLocker *locker);
void doSeek(QMutexLocker *locker);
void doPlay(QMutexLocker *locker);
void doPause(QMutexLocker *locker);
void doStop(QMutexLocker *locker);
void doReleaseAudioOutput(QMutexLocker *locker);
void doReleaseVideoOutput(QMutexLocker *locker);
void doReleaseGraph(QMutexLocker *locker);
void graphEvent(QMutexLocker *locker);
enum Task
{
Shutdown = 0x0001,
SetUrlSource = 0x0002,
SetStreamSource = 0x0004,
SetSource = SetUrlSource | SetStreamSource,
SetAudioOutput = 0x0008,
SetVideoOutput = 0x0010,
SetOutputs = SetAudioOutput | SetVideoOutput,
Render = 0x0020,
FinalizeLoad = 0x0040,
SetRate = 0x0080,
Seek = 0x0100,
Play = 0x0200,
Pause = 0x0400,
Stop = 0x0800,
ReleaseGraph = 0x1000,
ReleaseAudioOutput = 0x2000,
ReleaseVideoOutput = 0x4000,
ReleaseFilters = ReleaseGraph | ReleaseAudioOutput | ReleaseVideoOutput
};
enum Event
{
FinalizedLoad = QEvent::User,
Error,
RateChange,
Started,
Paused,
DurationChange,
StatusChange,
EndOfMedia,
PositionChange
};
enum GraphStatus
{
NoMedia,
Loading,
Loaded,
InvalidMedia
};
DirectShowPlayerControl *m_playerControl;
DirectShowMetaDataControl *m_metaDataControl;
DirectShowVideoRendererControl *m_videoRendererControl;
#ifndef Q_WS_SIMULATOR
Vmr9VideoWindowControl *m_videoWindowControl;
#endif
DirectShowAudioEndpointControl *m_audioEndpointControl;
QThread *m_taskThread;
DirectShowEventLoop *m_loop;
int m_pendingTasks;
int m_executingTask;
int m_executedTasks;
HANDLE m_taskHandle;
HANDLE m_eventHandle;
GraphStatus m_graphStatus;
QMediaPlayer::Error m_error;
QIODevice *m_stream;
IFilterGraph2 *m_graph;
IBaseFilter *m_source;
IBaseFilter *m_audioOutput;
IBaseFilter *m_videoOutput;
int m_streamTypes;
qreal m_rate;
qint64 m_position;
qint64 m_duration;
bool m_buffering;
bool m_seekable;
bool m_atEnd;
QMediaTimeRange m_playbackRange;
QUrl m_url;
QMediaResourceList m_resources;
QString m_errorString;
QMutex m_mutex;
friend class DirectShowPlayerServiceThread;
};
#endif

View File

@@ -0,0 +1,437 @@
/****************************************************************************
**
** 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 "directshowsamplescheduler.h"
#include <QtCore/qcoreapplication.h>
#include <QtCore/qcoreevent.h>
class DirectShowTimedSample
{
public:
DirectShowTimedSample(IMediaSample *sample)
: m_next(0)
, m_sample(sample)
, m_cookie(0)
, m_lastSample(false)
{
m_sample->AddRef();
}
~DirectShowTimedSample()
{
m_sample->Release();
}
IMediaSample *sample() const { return m_sample; }
DirectShowTimedSample *nextSample() const { return m_next; }
void setNextSample(DirectShowTimedSample *sample) { Q_ASSERT(!m_next); m_next = sample; }
DirectShowTimedSample *remove() {
DirectShowTimedSample *next = m_next; delete this; return next; }
bool schedule(IReferenceClock *clock, REFERENCE_TIME startTime, HANDLE handle);
void unschedule(IReferenceClock *clock);
bool isReady(IReferenceClock *clock) const;
bool isLast() const { return m_lastSample; }
void setLast() { m_lastSample = true; }
private:
DirectShowTimedSample *m_next;
IMediaSample *m_sample;
DWORD_PTR m_cookie;
bool m_lastSample;
};
bool DirectShowTimedSample::schedule(
IReferenceClock *clock, REFERENCE_TIME startTime, HANDLE handle)
{
REFERENCE_TIME sampleStartTime;
REFERENCE_TIME sampleEndTime;
if (m_sample->GetTime(&sampleStartTime, &sampleEndTime) == S_OK) {
if (clock->AdviseTime(
startTime, sampleStartTime, reinterpret_cast<HEVENT>(handle), &m_cookie) == S_OK) {
return true;
}
}
return false;
}
void DirectShowTimedSample::unschedule(IReferenceClock *clock)
{
clock->Unadvise(m_cookie);
}
bool DirectShowTimedSample::isReady(IReferenceClock *clock) const
{
REFERENCE_TIME sampleStartTime;
REFERENCE_TIME sampleEndTime;
REFERENCE_TIME currentTime;
if (m_sample->GetTime(&sampleStartTime, &sampleEndTime) == S_OK) {
if (clock->GetTime(&currentTime) == S_OK)
return currentTime >= sampleStartTime;
}
return true;
}
DirectShowSampleScheduler::DirectShowSampleScheduler(IUnknown *pin, QObject *parent)
: QObject(parent)
, m_pin(pin)
, m_clock(0)
, m_allocator(0)
, m_head(0)
, m_tail(0)
, m_maximumSamples(1)
, m_state(Stopped)
, m_startTime(0)
, m_timeoutEvent(::CreateEvent(0, 0, 0, 0))
, m_flushEvent(::CreateEvent(0, 0, 0, 0))
{
m_semaphore.release(m_maximumSamples);
}
DirectShowSampleScheduler::~DirectShowSampleScheduler()
{
::CloseHandle(m_timeoutEvent);
::CloseHandle(m_flushEvent);
Q_ASSERT(!m_clock);
Q_ASSERT(!m_allocator);
}
HRESULT DirectShowSampleScheduler::QueryInterface(REFIID riid, void **ppvObject)
{
return m_pin->QueryInterface(riid, ppvObject);
}
ULONG DirectShowSampleScheduler::AddRef()
{
return m_pin->AddRef();
}
ULONG DirectShowSampleScheduler::Release()
{
return m_pin->Release();
}
// IMemInputPin
HRESULT DirectShowSampleScheduler::GetAllocator(IMemAllocator **ppAllocator)
{
if (!ppAllocator) {
return E_POINTER;
} else {
QMutexLocker locker(&m_mutex);
if (!m_allocator) {
return VFW_E_NO_ALLOCATOR;
} else {
*ppAllocator = m_allocator;
return S_OK;
}
}
}
HRESULT DirectShowSampleScheduler::NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly)
{
Q_UNUSED(bReadOnly);
HRESULT hr;
ALLOCATOR_PROPERTIES properties;
if (!pAllocator) {
if (m_allocator)
m_allocator->Release();
m_allocator = 0;
return S_OK;
} else if ((hr = pAllocator->GetProperties(&properties)) != S_OK) {
return hr;
} else {
if (properties.cBuffers == 1) {
ALLOCATOR_PROPERTIES actual;
properties.cBuffers = 2;
if ((hr = pAllocator->SetProperties(&properties, &actual)) != S_OK)
return hr;
}
QMutexLocker locker(&m_mutex);
if (m_allocator)
m_allocator->Release();
m_allocator = pAllocator;
m_allocator->AddRef();
return S_OK;
}
}
HRESULT DirectShowSampleScheduler::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps)
{
if (!pProps)
return E_POINTER;
pProps->cBuffers = 2;
return S_OK;
}
HRESULT DirectShowSampleScheduler::Receive(IMediaSample *pSample)
{
if (!pSample)
return E_POINTER;
m_semaphore.acquire(1);
QMutexLocker locker(&m_mutex);
if (m_state & Flushing) {
m_semaphore.release(1);
return S_FALSE;
} else if (m_state == Stopped) {
m_semaphore.release();
return VFW_E_WRONG_STATE;
} else {
DirectShowTimedSample *timedSample = new DirectShowTimedSample(pSample);
if (m_tail)
m_tail->setNextSample(timedSample);
else
m_head = timedSample;
m_tail = timedSample;
if (m_state == Running) {
if (!timedSample->schedule(m_clock, m_startTime, m_timeoutEvent)) {
// Timing information is unavailable, so schedule frames immediately.
QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
} else {
locker.unlock();
HANDLE handles[] = { m_flushEvent, m_timeoutEvent };
DWORD result = ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
locker.relock();
if (result == WAIT_OBJECT_0 + 1)
QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
}
} else if (m_tail == m_head) {
// If this is the first frame make it available.
QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
if (m_state == Paused) {
::ResetEvent(m_timeoutEvent);
locker.unlock();
HANDLE handles[] = { m_flushEvent, m_timeoutEvent };
::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
locker.relock();
}
}
return S_OK;
}
}
HRESULT DirectShowSampleScheduler::ReceiveMultiple(
IMediaSample **pSamples, long nSamples, long *nSamplesProcessed)
{
if (!pSamples || !nSamplesProcessed)
return E_POINTER;
for (*nSamplesProcessed = 0; *nSamplesProcessed < nSamples; ++(*nSamplesProcessed)) {
HRESULT hr = Receive(pSamples[*nSamplesProcessed]);
if (hr != S_OK)
return hr;
}
return S_OK;
}
HRESULT DirectShowSampleScheduler::ReceiveCanBlock()
{
return S_OK;
}
void DirectShowSampleScheduler::run(REFERENCE_TIME startTime)
{
QMutexLocker locker(&m_mutex);
m_state = (m_state & Flushing) | Running;
m_startTime = startTime;
for (DirectShowTimedSample *sample = m_head; sample; sample = sample->nextSample()) {
sample->schedule(m_clock, m_startTime, m_timeoutEvent);
}
if (!(m_state & Flushing))
::ResetEvent(m_flushEvent);
if (!m_head)
::SetEvent(m_timeoutEvent);
}
void DirectShowSampleScheduler::pause()
{
QMutexLocker locker(&m_mutex);
m_state = (m_state & Flushing) | Paused;
for (DirectShowTimedSample *sample = m_head; sample; sample = sample->nextSample())
sample->unschedule(m_clock);
if (!(m_state & Flushing))
::ResetEvent(m_flushEvent);
}
void DirectShowSampleScheduler::stop()
{
QMutexLocker locker(&m_mutex);
m_state = m_state & Flushing;
for (DirectShowTimedSample *sample = m_head; sample; sample = sample->remove()) {
sample->unschedule(m_clock);
m_semaphore.release(1);
}
m_head = 0;
m_tail = 0;
::SetEvent(m_flushEvent);
}
void DirectShowSampleScheduler::setFlushing(bool flushing)
{
QMutexLocker locker(&m_mutex);
const bool isFlushing = m_state & Flushing;
if (isFlushing != flushing) {
if (flushing) {
m_state |= Flushing;
for (DirectShowTimedSample *sample = m_head; sample; sample = sample->remove()) {
sample->unschedule(m_clock);
m_semaphore.release(1);
}
m_head = 0;
m_tail = 0;
::SetEvent(m_flushEvent);
} else {
m_state &= ~Flushing;
if (m_state != Stopped)
::ResetEvent(m_flushEvent);
}
}
}
void DirectShowSampleScheduler::setClock(IReferenceClock *clock)
{
QMutexLocker locker(&m_mutex);
if (m_clock)
m_clock->Release();
m_clock = clock;
if (m_clock)
m_clock->AddRef();
}
IMediaSample *DirectShowSampleScheduler::takeSample(bool *eos)
{
QMutexLocker locker(&m_mutex);
if (m_head && m_head->isReady(m_clock)) {
IMediaSample *sample = m_head->sample();
sample->AddRef();
*eos = m_head->isLast();
m_head = m_head->remove();
if (!m_head)
m_tail = 0;
m_semaphore.release(1);
return sample;
} else {
return 0;
}
}
bool DirectShowSampleScheduler::scheduleEndOfStream()
{
QMutexLocker locker(&m_mutex);
if (m_tail) {
m_tail->setLast();
return true;
} else {
return false;
}
}
bool DirectShowSampleScheduler::event(QEvent *event)
{
if (event->type() == QEvent::UpdateRequest) {
emit sampleReady();
return true;
} else {
return QObject::event(event);
}
}

View File

@@ -0,0 +1,117 @@
/****************************************************************************
**
** 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 DIRECTSHOWSAMPLESCHEDULER_H
#define DIRECTSHOWSAMPLESCHEDULER_H
#include <QtCore/qmutex.h>
#include <QtCore/qobject.h>
#include <QtCore/qsemaphore.h>
#include <dshow.h>
class DirectShowTimedSample;
class DirectShowSampleScheduler : public QObject, public IMemInputPin
{
Q_OBJECT
public:
enum State
{
Stopped = 0x00,
Running = 0x01,
Paused = 0x02,
RunMask = 0x03,
Flushing = 0x04
};
DirectShowSampleScheduler(IUnknown *pin, QObject *parent = 0);
~DirectShowSampleScheduler();
// IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
// IMemInputPin
HRESULT STDMETHODCALLTYPE GetAllocator(IMemAllocator **ppAllocator);
HRESULT STDMETHODCALLTYPE NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly);
HRESULT STDMETHODCALLTYPE GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps);
HRESULT STDMETHODCALLTYPE Receive(IMediaSample *pSample);
HRESULT STDMETHODCALLTYPE ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed);
HRESULT STDMETHODCALLTYPE ReceiveCanBlock();
void run(REFERENCE_TIME startTime);
void pause();
void stop();
void setFlushing(bool flushing);
IReferenceClock *clock() const { return m_clock; }
void setClock(IReferenceClock *clock);
bool schedule(IMediaSample *sample);
bool scheduleEndOfStream();
IMediaSample *takeSample(bool *eos);
bool event(QEvent *event);
Q_SIGNALS:
void sampleReady();
private:
IUnknown *m_pin;
IReferenceClock *m_clock;
IMemAllocator *m_allocator;
DirectShowTimedSample *m_head;
DirectShowTimedSample *m_tail;
int m_maximumSamples;
int m_state;
REFERENCE_TIME m_startTime;
HANDLE m_timeoutEvent;
HANDLE m_flushEvent;
QSemaphore m_semaphore;
QMutex m_mutex;
};
#endif

View File

@@ -0,0 +1,86 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "directshowvideorenderercontrol.h"
#include "videosurfacefilter.h"
DirectShowVideoRendererControl::DirectShowVideoRendererControl(DirectShowEventLoop *loop, QObject *parent)
: QVideoRendererControl(parent)
, m_loop(loop)
, m_surface(0)
, m_filter(0)
{
}
DirectShowVideoRendererControl::~DirectShowVideoRendererControl()
{
delete m_filter;
}
QAbstractVideoSurface *DirectShowVideoRendererControl::surface() const
{
return m_surface;
}
void DirectShowVideoRendererControl::setSurface(QAbstractVideoSurface *surface)
{
if (surface != m_surface) {
m_surface = surface;
VideoSurfaceFilter *existingFilter = m_filter;
if (surface) {
m_filter = new VideoSurfaceFilter(surface, m_loop);
} else {
m_filter = 0;
}
emit filterChanged();
delete existingFilter;
}
}
IBaseFilter *DirectShowVideoRendererControl::filter()
{
return m_filter;
}

View File

@@ -0,0 +1,75 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DIRECTSHOWVIDEORENDERERCONTROL_H
#define DIRECTSHOWVIDEORENDERERCONTROL_H
#include "qvideorenderercontrol.h"
#include <dshow.h>
class DirectShowEventLoop;
class VideoSurfaceFilter;
QT_USE_NAMESPACE
class DirectShowVideoRendererControl : public QVideoRendererControl
{
Q_OBJECT
public:
DirectShowVideoRendererControl(DirectShowEventLoop *loop, QObject *parent = 0);
~DirectShowVideoRendererControl();
QAbstractVideoSurface *surface() const;
void setSurface(QAbstractVideoSurface *surface);
IBaseFilter *filter();
Q_SIGNALS:
void filterChanged();
private:
DirectShowEventLoop *m_loop;
QAbstractVideoSurface *m_surface;
VideoSurfaceFilter *m_filter;
};
#endif

View File

@@ -0,0 +1,86 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "mediasamplevideobuffer.h"
MediaSampleVideoBuffer::MediaSampleVideoBuffer(IMediaSample *sample, int bytesPerLine)
: QAbstractVideoBuffer(NoHandle)
, m_sample(sample)
, m_bytesPerLine(bytesPerLine)
, m_mapMode(NotMapped)
{
m_sample->AddRef();
}
MediaSampleVideoBuffer::~MediaSampleVideoBuffer()
{
m_sample->Release();
}
uchar *MediaSampleVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine)
{
if (m_mapMode == NotMapped && mode != NotMapped) {
if (numBytes)
*numBytes = m_sample->GetActualDataLength();
if (bytesPerLine)
*bytesPerLine = m_bytesPerLine;
BYTE *bytes = 0;
if (m_sample->GetPointer(&bytes) == S_OK) {
m_mapMode = mode;
return reinterpret_cast<uchar *>(bytes);
}
}
return 0;
}
void MediaSampleVideoBuffer::unmap()
{
m_mapMode = NotMapped;
}
QAbstractVideoBuffer::MapMode MediaSampleVideoBuffer::mapMode() const
{
return m_mapMode;
}

View File

@@ -0,0 +1,69 @@
/****************************************************************************
**
** 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 MEDIASAMPLEVIDEOBUFFER_H
#define MEDIASAMPLEVIDEOBUFFER_H
#include <qabstractvideobuffer.h>
#include <dshow.h>
class MediaSampleVideoBuffer : public QAbstractVideoBuffer
{
public:
MediaSampleVideoBuffer(IMediaSample *sample, int bytesPerLine);
~MediaSampleVideoBuffer();
IMediaSample *sample() { return m_sample; }
uchar *map(MapMode mode, int *numBytes, int *bytesPerLine);
void unmap();
MapMode mapMode() const;
private:
IMediaSample *m_sample;
int m_bytesPerLine;
MapMode m_mapMode;
};
#endif

View File

@@ -0,0 +1,47 @@
INCLUDEPATH += $$PWD
DEFINES += QMEDIA_DIRECTSHOW_PLAYER
HEADERS += \
$$PWD/directshowaudioendpointcontrol.h \
$$PWD/directshoweventloop.h \
$$PWD/directshowglobal.h \
$$PWD/directshowioreader.h \
$$PWD/directshowiosource.h \
$$PWD/directshowmediatype.h \
$$PWD/directshowmediatypelist.h \
$$PWD/directshowmetadatacontrol.h \
$$PWD/directshowpinenum.h \
$$PWD/directshowplayercontrol.h \
$$PWD/directshowplayerservice.h \
$$PWD/directshowsamplescheduler.h \
$$PWD/directshowvideorenderercontrol.h \
$$PWD/mediasamplevideobuffer.h \
$$PWD/videosurfacefilter.h
SOURCES += \
$$PWD/directshowaudioendpointcontrol.cpp \
$$PWD/directshoweventloop.cpp \
$$PWD/directshowioreader.cpp \
$$PWD/directshowiosource.cpp \
$$PWD/directshowmediatype.cpp \
$$PWD/directshowmediatypelist.cpp \
$$PWD/directshowmetadatacontrol.cpp \
$$PWD/directshowpinenum.cpp \
$$PWD/directshowplayercontrol.cpp \
$$PWD/directshowplayerservice.cpp \
$$PWD/directshowsamplescheduler.cpp \
$$PWD/directshowvideorenderercontrol.cpp \
$$PWD/mediasamplevideobuffer.cpp \
$$PWD/videosurfacefilter.cpp
!simulator {
HEADERS += \
$$PWD/vmr9videowindowcontrol.h
SOURCES += \
$$PWD/vmr9videowindowcontrol.cpp
}
LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32 -lgdi32

View File

@@ -0,0 +1,631 @@
/****************************************************************************
**
** 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 "videosurfacefilter.h"
#include "directshoweventloop.h"
#include "directshowglobal.h"
#include "directshowpinenum.h"
#include "mediasamplevideobuffer.h"
#include <QtCore/qcoreapplication.h>
#include <QtCore/qcoreevent.h>
#include <QtCore/qthread.h>
#include <qabstractvideosurface.h>
#include <initguid.h>
// { e23cad72-153d-406c-bf3f-4c4b523d96f2 }
DEFINE_GUID(CLSID_VideoSurfaceFilter,
0xe23cad72, 0x153d, 0x406c, 0xbf, 0x3f, 0x4c, 0x4b, 0x52, 0x3d, 0x96, 0xf2);
VideoSurfaceFilter::VideoSurfaceFilter(
QAbstractVideoSurface *surface, DirectShowEventLoop *loop, QObject *parent)
: QObject(parent)
, m_ref(1)
, m_state(State_Stopped)
, m_surface(surface)
, m_loop(loop)
, m_graph(0)
, m_peerPin(0)
, m_bytesPerLine(0)
, m_startResult(S_OK)
, m_pinId(QString::fromLatin1("reference"))
, m_sampleScheduler(static_cast<IPin *>(this))
{
connect(surface, SIGNAL(supportedFormatsChanged()), this, SLOT(supportedFormatsChanged()));
connect(&m_sampleScheduler, SIGNAL(sampleReady()), this, SLOT(sampleReady()));
}
VideoSurfaceFilter::~VideoSurfaceFilter()
{
Q_ASSERT(m_ref == 1);
}
HRESULT VideoSurfaceFilter::QueryInterface(REFIID riid, void **ppvObject)
{
// 2dd74950-a890-11d1-abe8-00a0c905f375
static const GUID iid_IAmFilterMiscFlags = {
0x2dd74950, 0xa890, 0x11d1, {0xab, 0xe8, 0x00, 0xa0, 0xc9, 0x05, 0xf3, 0x75} };
if (!ppvObject) {
return E_POINTER;
} else if (riid == IID_IUnknown
|| riid == IID_IPersist
|| riid == IID_IMediaFilter
|| riid == IID_IBaseFilter) {
*ppvObject = static_cast<IBaseFilter *>(this);
} else if (riid == iid_IAmFilterMiscFlags) {
*ppvObject = static_cast<IAMFilterMiscFlags *>(this);
} else if (riid == IID_IPin) {
*ppvObject = static_cast<IPin *>(this);
} else if (riid == IID_IMemInputPin) {
*ppvObject = static_cast<IMemInputPin *>(&m_sampleScheduler);
} else {
*ppvObject = 0;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
ULONG VideoSurfaceFilter::AddRef()
{
return InterlockedIncrement(&m_ref);
}
ULONG VideoSurfaceFilter::Release()
{
ULONG ref = InterlockedDecrement(&m_ref);
Q_ASSERT(ref != 0);
return ref;
}
HRESULT VideoSurfaceFilter::GetClassID(CLSID *pClassID)
{
*pClassID = CLSID_VideoSurfaceFilter;
return S_OK;
}
HRESULT VideoSurfaceFilter::Run(REFERENCE_TIME tStart)
{
m_state = State_Running;
m_sampleScheduler.run(tStart);
return S_OK;
}
HRESULT VideoSurfaceFilter::Pause()
{
m_state = State_Paused;
m_sampleScheduler.pause();
return S_OK;
}
HRESULT VideoSurfaceFilter::Stop()
{
m_state = State_Stopped;
m_sampleScheduler.stop();
return S_OK;
}
HRESULT VideoSurfaceFilter::GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
{
if (!pState)
return E_POINTER;
*pState = m_state;
return S_OK;
}
HRESULT VideoSurfaceFilter::SetSyncSource(IReferenceClock *pClock)
{
m_sampleScheduler.setClock(pClock);
return S_OK;
}
HRESULT VideoSurfaceFilter::GetSyncSource(IReferenceClock **ppClock)
{
if (!ppClock) {
return E_POINTER;
} else {
*ppClock = m_sampleScheduler.clock();
if (*ppClock) {
(*ppClock)->AddRef();
return S_OK;
} else {
return S_FALSE;
}
}
}
HRESULT VideoSurfaceFilter::EnumPins(IEnumPins **ppEnum)
{
if (ppEnum) {
*ppEnum = new DirectShowPinEnum(QList<IPin *>() << this);
return S_OK;
} else {
return E_POINTER;
}
}
HRESULT VideoSurfaceFilter::FindPin(LPCWSTR pId, IPin **ppPin)
{
if (!ppPin || !pId) {
return E_POINTER;
} else if (QString::fromWCharArray(pId) == m_pinId) {
AddRef();
*ppPin = this;
return S_OK;
} else {
return VFW_E_NOT_FOUND;
}
}
HRESULT VideoSurfaceFilter::JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName)
{
m_graph = pGraph;
m_name = QString::fromWCharArray(pName);
return S_OK;
}
HRESULT VideoSurfaceFilter::QueryFilterInfo(FILTER_INFO *pInfo)
{
if (pInfo) {
QString name = m_name;
if (name.length() >= MAX_FILTER_NAME)
name.truncate(MAX_FILTER_NAME - 1);
int length = name.toWCharArray(pInfo->achName);
pInfo->achName[length] = '\0';
if (m_graph)
m_graph->AddRef();
pInfo->pGraph = m_graph;
return S_OK;
} else {
return E_POINTER;
}
}
HRESULT VideoSurfaceFilter::QueryVendorInfo(LPWSTR *pVendorInfo)
{
Q_UNUSED(pVendorInfo);
return E_NOTIMPL;
}
ULONG VideoSurfaceFilter::GetMiscFlags()
{
return AM_FILTER_MISC_FLAGS_IS_RENDERER;
}
HRESULT VideoSurfaceFilter::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
{
// This is an input pin, you shouldn't be calling Connect on it.
return E_POINTER;
}
HRESULT VideoSurfaceFilter::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
{
if (!pConnector) {
return E_POINTER;
} else if (!pmt) {
return E_POINTER;
} else {
HRESULT hr;
QMutexLocker locker(&m_mutex);
if (m_peerPin) {
hr = VFW_E_ALREADY_CONNECTED;
} else if (pmt->majortype != MEDIATYPE_Video) {
hr = VFW_E_TYPE_NOT_ACCEPTED;
} else {
m_surfaceFormat = DirectShowMediaType::formatFromType(*pmt);
m_bytesPerLine = DirectShowMediaType::bytesPerLine(m_surfaceFormat);
if (thread() == QThread::currentThread()) {
hr = start();
} else {
m_loop->postEvent(this, new QEvent(QEvent::Type(StartSurface)));
m_wait.wait(&m_mutex);
hr = m_startResult;
}
}
if (hr == S_OK) {
m_peerPin = pConnector;
m_peerPin->AddRef();
DirectShowMediaType::copy(&m_mediaType, *pmt);
}
return hr;
}
}
HRESULT VideoSurfaceFilter::start()
{
if (!m_surface->isFormatSupported(m_surfaceFormat)) {
return VFW_E_TYPE_NOT_ACCEPTED;
}
if (!m_surface->start(m_surfaceFormat)) {
return VFW_E_TYPE_NOT_ACCEPTED;
} else {
return S_OK;
}
}
HRESULT VideoSurfaceFilter::Disconnect()
{
QMutexLocker locker(&m_mutex);
if (!m_peerPin)
return S_FALSE;
if (thread() == QThread::currentThread()) {
stop();
} else {
m_loop->postEvent(this, new QEvent(QEvent::Type(StopSurface)));
m_wait.wait(&m_mutex);
}
m_mediaType.clear();
m_sampleScheduler.NotifyAllocator(0, FALSE);
m_peerPin->Release();
m_peerPin = 0;
return S_OK;
}
void VideoSurfaceFilter::stop()
{
m_surface->stop();
}
HRESULT VideoSurfaceFilter::ConnectedTo(IPin **ppPin)
{
if (!ppPin) {
return E_POINTER;
} else {
QMutexLocker locker(&m_mutex);
if (!m_peerPin) {
return VFW_E_NOT_CONNECTED;
} else {
m_peerPin->AddRef();
*ppPin = m_peerPin;
return S_OK;
}
}
}
HRESULT VideoSurfaceFilter::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
{
if (!pmt) {
return E_POINTER;
} else {
QMutexLocker locker(&m_mutex);
if (!m_peerPin) {
return VFW_E_NOT_CONNECTED;
} else {
DirectShowMediaType::copy(pmt, m_mediaType);
return S_OK;
}
}
}
HRESULT VideoSurfaceFilter::QueryPinInfo(PIN_INFO *pInfo)
{
if (!pInfo) {
return E_POINTER;
} else {
AddRef();
pInfo->pFilter = this;
pInfo->dir = PINDIR_INPUT;
const int bytes = qMin(MAX_FILTER_NAME, (m_pinId.length() + 1) * 2);
qMemCopy(pInfo->achName, m_pinId.utf16(), bytes);
return S_OK;
}
}
HRESULT VideoSurfaceFilter::QueryId(LPWSTR *Id)
{
if (!Id) {
return E_POINTER;
} else {
const int bytes = (m_pinId.length() + 1) * 2;
*Id = static_cast<LPWSTR>(::CoTaskMemAlloc(bytes));
qMemCopy(*Id, m_pinId.utf16(), bytes);
return S_OK;
}
}
HRESULT VideoSurfaceFilter::QueryAccept(const AM_MEDIA_TYPE *pmt)
{
return !m_surface->isFormatSupported(DirectShowMediaType::formatFromType(*pmt))
? S_OK
: S_FALSE;
}
HRESULT VideoSurfaceFilter::EnumMediaTypes(IEnumMediaTypes **ppEnum)
{
if (!ppEnum) {
return E_POINTER;
} else {
QMutexLocker locker(&m_mutex);
*ppEnum = createMediaTypeEnum();
return S_OK;
}
}
HRESULT VideoSurfaceFilter::QueryInternalConnections(IPin **apPin, ULONG *nPin)
{
Q_UNUSED(apPin);
Q_UNUSED(nPin);
return E_NOTIMPL;
}
HRESULT VideoSurfaceFilter::EndOfStream()
{
QMutexLocker locker(&m_mutex);
if (!m_sampleScheduler.scheduleEndOfStream()) {
if (IMediaEventSink *sink = com_cast<IMediaEventSink>(m_graph, IID_IMediaEventSink)) {
sink->Notify(
EC_COMPLETE,
S_OK,
reinterpret_cast<LONG_PTR>(static_cast<IBaseFilter *>(this)));
sink->Release();
}
}
return S_OK;
}
HRESULT VideoSurfaceFilter::BeginFlush()
{
QMutexLocker locker(&m_mutex);
m_sampleScheduler.setFlushing(true);
if (thread() == QThread::currentThread()) {
flush();
} else {
m_loop->postEvent(this, new QEvent(QEvent::Type(FlushSurface)));
m_wait.wait(&m_mutex);
}
return S_OK;
}
HRESULT VideoSurfaceFilter::EndFlush()
{
QMutexLocker locker(&m_mutex);
m_sampleScheduler.setFlushing(false);
return S_OK;
}
void VideoSurfaceFilter::flush()
{
m_surface->present(QVideoFrame());
m_wait.wakeAll();
}
HRESULT VideoSurfaceFilter::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
{
Q_UNUSED(tStart);
Q_UNUSED(tStop);
Q_UNUSED(dRate);
return S_OK;
}
HRESULT VideoSurfaceFilter::QueryDirection(PIN_DIRECTION *pPinDir)
{
if (!pPinDir) {
return E_POINTER;
} else {
*pPinDir = PINDIR_INPUT;
return S_OK;
}
}
int VideoSurfaceFilter::currentMediaTypeToken()
{
QMutexLocker locker(&m_mutex);
return DirectShowMediaTypeList::currentMediaTypeToken();
}
HRESULT VideoSurfaceFilter::nextMediaType(
int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount)
{
QMutexLocker locker(&m_mutex);
return DirectShowMediaTypeList::nextMediaType(token, index, count, types, fetchedCount);
}
HRESULT VideoSurfaceFilter::skipMediaType(int token, int *index, ULONG count)
{
QMutexLocker locker(&m_mutex);
return DirectShowMediaTypeList::skipMediaType(token, index, count);
}
HRESULT VideoSurfaceFilter::cloneMediaType(int token, int index, IEnumMediaTypes **enumeration)
{
QMutexLocker locker(&m_mutex);
return DirectShowMediaTypeList::cloneMediaType(token, index, enumeration);
}
void VideoSurfaceFilter::customEvent(QEvent *event)
{
if (event->type() == StartSurface) {
QMutexLocker locker(&m_mutex);
m_startResult = start();
m_wait.wakeAll();
} else if (event->type() == StopSurface) {
QMutexLocker locker(&m_mutex);
stop();
m_wait.wakeAll();
} else if (event->type() == FlushSurface) {
QMutexLocker locker(&m_mutex);
flush();
m_wait.wakeAll();
} else {
QObject::customEvent(event);
}
}
void VideoSurfaceFilter::supportedFormatsChanged()
{
QMutexLocker locker(&m_mutex);
// MEDIASUBTYPE_None;
static const GUID none = {
0xe436eb8e, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70} };
QList<QVideoFrame::PixelFormat> formats = m_surface->supportedPixelFormats();
QVector<AM_MEDIA_TYPE> mediaTypes;
mediaTypes.reserve(formats.count());
AM_MEDIA_TYPE type;
type.majortype = MEDIATYPE_Video;
type.bFixedSizeSamples = TRUE;
type.bTemporalCompression = FALSE;
type.lSampleSize = 0;
type.formattype = GUID_NULL;
type.pUnk = 0;
type.cbFormat = 0;
type.pbFormat = 0;
foreach (QVideoFrame::PixelFormat format, formats) {
type.subtype = DirectShowMediaType::convertPixelFormat(format);
if (type.subtype != none)
mediaTypes.append(type);
}
setMediaTypes(mediaTypes);
}
void VideoSurfaceFilter::sampleReady()
{
bool eos = false;
IMediaSample *sample = m_sampleScheduler.takeSample(&eos);
if (sample) {
m_surface->present(QVideoFrame(
new MediaSampleVideoBuffer(sample, m_bytesPerLine),
m_surfaceFormat.frameSize(),
m_surfaceFormat.pixelFormat()));
sample->Release();
if (eos) {
if (IMediaEventSink *sink = com_cast<IMediaEventSink>(m_graph, IID_IMediaEventSink)) {
sink->Notify(
EC_COMPLETE,
S_OK,
reinterpret_cast<LONG_PTR>(static_cast<IBaseFilter *>(this)));
sink->Release();
}
}
}
}

View File

@@ -0,0 +1,176 @@
/****************************************************************************
**
** 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 VIDEOSURFACEFILTER_H
#define VIDEOSURFACEFILTER_H
#include "directshowglobal.h"
#include "directshowmediatypelist.h"
#include "directshowsamplescheduler.h"
#include "directshowmediatype.h"
#include <QtCore/qbasictimer.h>
#include <QtCore/qcoreevent.h>
#include <QtCore/qmutex.h>
#include <QtCore/qsemaphore.h>
#include <QtCore/qstring.h>
#include <QtCore/qwaitcondition.h>
#include <dshow.h>
QT_BEGIN_NAMESPACE
class QAbstractVideoSurface;
QT_END_NAMESPACE
class DirectShowEventLoop;
class VideoSurfaceFilter
: public QObject
, public DirectShowMediaTypeList
, public IBaseFilter
, public IAMFilterMiscFlags
, public IPin
{
Q_OBJECT
public:
VideoSurfaceFilter(
QAbstractVideoSurface *surface, DirectShowEventLoop *loop, QObject *parent = 0);
~VideoSurfaceFilter();
// IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
// IPersist
HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
// IMediaFilter
HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME tStart);
HRESULT STDMETHODCALLTYPE Pause();
HRESULT STDMETHODCALLTYPE Stop();
HRESULT STDMETHODCALLTYPE GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState);
HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *pClock);
HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **ppClock);
// IBaseFilter
HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **ppEnum);
HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR Id, IPin **ppPin);
HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName);
HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *pInfo);
HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *pVendorInfo);
// IAMFilterMiscFlags
ULONG STDMETHODCALLTYPE GetMiscFlags();
// IPin
HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt);
HRESULT STDMETHODCALLTYPE Disconnect();
HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **ppPin);
HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt);
HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo);
HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id);
HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt);
HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum);
HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin);
HRESULT STDMETHODCALLTYPE EndOfStream();
HRESULT STDMETHODCALLTYPE BeginFlush();
HRESULT STDMETHODCALLTYPE EndFlush();
HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir);
int currentMediaTypeToken();
HRESULT nextMediaType(
int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount);
HRESULT skipMediaType(int token, int *index, ULONG count);
HRESULT cloneMediaType(int token, int index, IEnumMediaTypes **enumeration);
protected:
void customEvent(QEvent *event);
private Q_SLOTS:
void supportedFormatsChanged();
void sampleReady();
private:
HRESULT start();
void stop();
void flush();
enum
{
StartSurface = QEvent::User,
StopSurface,
FlushSurface
};
LONG m_ref;
FILTER_STATE m_state;
QAbstractVideoSurface *m_surface;
DirectShowEventLoop *m_loop;
IFilterGraph *m_graph;
IPin *m_peerPin;
int m_bytesPerLine;
HRESULT m_startResult;
QString m_name;
QString m_pinId;
DirectShowMediaType m_mediaType;
QVideoSurfaceFormat m_surfaceFormat;
QMutex m_mutex;
QWaitCondition m_wait;
DirectShowSampleScheduler m_sampleScheduler;
};
#endif

View File

@@ -0,0 +1,329 @@
/****************************************************************************
**
** 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 "vmr9videowindowcontrol.h"
#include "directshowglobal.h"
Vmr9VideoWindowControl::Vmr9VideoWindowControl(QObject *parent)
: QVideoWindowControl(parent)
, m_filter(com_new<IBaseFilter>(CLSID_VideoMixingRenderer9, IID_IBaseFilter))
, m_windowId(0)
, m_dirtyValues(0)
, m_aspectRatioMode(Qt::KeepAspectRatio)
, m_brightness(0)
, m_contrast(0)
, m_hue(0)
, m_saturation(0)
, m_fullScreen(false)
{
if (IVMRFilterConfig9 *config = com_cast<IVMRFilterConfig9>(m_filter, IID_IVMRFilterConfig9)) {
config->SetRenderingMode(VMR9Mode_Windowless);
config->SetNumberOfStreams(1);
config->Release();
}
}
Vmr9VideoWindowControl::~Vmr9VideoWindowControl()
{
if (m_filter)
m_filter->Release();
}
WId Vmr9VideoWindowControl::winId() const
{
return m_windowId;
}
void Vmr9VideoWindowControl::setWinId(WId id)
{
m_windowId = id;
if (QWidget *widget = QWidget::find(m_windowId)) {
const QColor color = widget->palette().color(QPalette::Window);
m_windowColor = RGB(color.red(), color.green(), color.blue());
}
if (IVMRWindowlessControl9 *control = com_cast<IVMRWindowlessControl9>(
m_filter, IID_IVMRWindowlessControl9)) {
control->SetVideoClippingWindow(m_windowId);
control->SetBorderColor(m_windowColor);
control->Release();
}
}
QRect Vmr9VideoWindowControl::displayRect() const
{
return m_displayRect;
}
void Vmr9VideoWindowControl::setDisplayRect(const QRect &rect)
{
m_displayRect = rect;
if (IVMRWindowlessControl9 *control = com_cast<IVMRWindowlessControl9>(
m_filter, IID_IVMRWindowlessControl9)) {
RECT sourceRect = { 0, 0, 0, 0 };
RECT displayRect = { rect.left(), rect.top(), rect.right() + 1, rect.bottom() + 1 };
control->GetNativeVideoSize(&sourceRect.right, &sourceRect.bottom, 0, 0);
if (m_aspectRatioMode == Qt::KeepAspectRatioByExpanding) {
QSize clippedSize = rect.size();
clippedSize.scale(sourceRect.right, sourceRect.bottom, Qt::KeepAspectRatio);
sourceRect.left = (sourceRect.right - clippedSize.width()) / 2;
sourceRect.top = (sourceRect.bottom - clippedSize.height()) / 2;
sourceRect.right = sourceRect.left + clippedSize.width();
sourceRect.bottom = sourceRect.top + clippedSize.height();
}
control->SetVideoPosition(&sourceRect, &displayRect);
control->Release();
}
}
bool Vmr9VideoWindowControl::isFullScreen() const
{
return m_fullScreen;
}
void Vmr9VideoWindowControl::setFullScreen(bool fullScreen)
{
emit fullScreenChanged(m_fullScreen = fullScreen);
}
void Vmr9VideoWindowControl::repaint()
{
PAINTSTRUCT paint;
if (HDC dc = ::BeginPaint(m_windowId, &paint)) {
HRESULT hr = E_FAIL;
if (IVMRWindowlessControl9 *control = com_cast<IVMRWindowlessControl9>(
m_filter, IID_IVMRWindowlessControl9)) {
hr = control->RepaintVideo(m_windowId, dc);
control->Release();
}
if (!SUCCEEDED(hr)) {
HPEN pen = ::CreatePen(PS_SOLID, 1, m_windowColor);
HBRUSH brush = ::CreateSolidBrush(m_windowColor);
::SelectObject(dc, pen);
::SelectObject(dc, brush);
::Rectangle(
dc,
m_displayRect.left(),
m_displayRect.top(),
m_displayRect.right() + 1,
m_displayRect.bottom() + 1);
::DeleteObject(pen);
::DeleteObject(brush);
}
::EndPaint(m_windowId, &paint);
}
}
QSize Vmr9VideoWindowControl::nativeSize() const
{
QSize size;
if (IVMRWindowlessControl9 *control = com_cast<IVMRWindowlessControl9>(
m_filter, IID_IVMRWindowlessControl9)) {
LONG width;
LONG height;
if (control->GetNativeVideoSize(&width, &height, 0, 0) == S_OK)
size = QSize(width, height);
control->Release();
}
return size;
}
Qt::AspectRatioMode Vmr9VideoWindowControl::aspectRatioMode() const
{
return m_aspectRatioMode;
}
void Vmr9VideoWindowControl::setAspectRatioMode(Qt::AspectRatioMode mode)
{
m_aspectRatioMode = mode;
if (IVMRWindowlessControl9 *control = com_cast<IVMRWindowlessControl9>(
m_filter, IID_IVMRWindowlessControl9)) {
switch (mode) {
case Qt::IgnoreAspectRatio:
control->SetAspectRatioMode(VMR9ARMode_None);
break;
case Qt::KeepAspectRatio:
control->SetAspectRatioMode(VMR9ARMode_LetterBox);
break;
case Qt::KeepAspectRatioByExpanding:
control->SetAspectRatioMode(VMR9ARMode_LetterBox);
setDisplayRect(m_displayRect);
break;
default:
break;
}
control->Release();
}
}
int Vmr9VideoWindowControl::brightness() const
{
return m_brightness;
}
void Vmr9VideoWindowControl::setBrightness(int brightness)
{
m_brightness = brightness;
m_dirtyValues |= ProcAmpControl9_Brightness;
setProcAmpValues();
emit brightnessChanged(brightness);
}
int Vmr9VideoWindowControl::contrast() const
{
return m_contrast;
}
void Vmr9VideoWindowControl::setContrast(int contrast)
{
m_contrast = contrast;
m_dirtyValues |= ProcAmpControl9_Contrast;
setProcAmpValues();
emit contrastChanged(contrast);
}
int Vmr9VideoWindowControl::hue() const
{
return m_hue;
}
void Vmr9VideoWindowControl::setHue(int hue)
{
m_hue = hue;
m_dirtyValues |= ProcAmpControl9_Hue;
setProcAmpValues();
emit hueChanged(hue);
}
int Vmr9VideoWindowControl::saturation() const
{
return m_saturation;
}
void Vmr9VideoWindowControl::setSaturation(int saturation)
{
m_saturation = saturation;
m_dirtyValues |= ProcAmpControl9_Saturation;
setProcAmpValues();
emit saturationChanged(saturation);
}
void Vmr9VideoWindowControl::setProcAmpValues()
{
if (IVMRMixerControl9 *control = com_cast<IVMRMixerControl9>(m_filter, IID_IVMRMixerControl9)) {
VMR9ProcAmpControl procAmp;
procAmp.dwSize = sizeof(VMR9ProcAmpControl);
procAmp.dwFlags = m_dirtyValues;
if (m_dirtyValues & ProcAmpControl9_Brightness) {
procAmp.Brightness = scaleProcAmpValue(
control, ProcAmpControl9_Brightness, m_brightness);
}
if (m_dirtyValues & ProcAmpControl9_Contrast) {
procAmp.Contrast = scaleProcAmpValue(
control, ProcAmpControl9_Contrast, m_contrast);
}
if (m_dirtyValues & ProcAmpControl9_Hue) {
procAmp.Hue = scaleProcAmpValue(
control, ProcAmpControl9_Hue, m_hue);
}
if (m_dirtyValues & ProcAmpControl9_Saturation) {
procAmp.Saturation = scaleProcAmpValue(
control, ProcAmpControl9_Saturation, m_saturation);
}
if (SUCCEEDED(control->SetProcAmpControl(0, &procAmp))) {
m_dirtyValues = 0;
}
control->Release();
}
}
float Vmr9VideoWindowControl::scaleProcAmpValue(
IVMRMixerControl9 *control, VMR9ProcAmpControlFlags property, int value) const
{
float scaledValue = 0.0;
VMR9ProcAmpControlRange range;
range.dwSize = sizeof(VMR9ProcAmpControlRange);
range.dwProperty = property;
if (SUCCEEDED(control->GetProcAmpControlRange(0, &range))) {
scaledValue = range.DefaultValue;
if (value > 0)
scaledValue += float(value) * (range.MaxValue - range.DefaultValue) / 100;
else if (value < 0)
scaledValue -= float(value) * (range.MinValue - range.DefaultValue) / 100;
}
return scaledValue;
}

View File

@@ -0,0 +1,108 @@
/****************************************************************************
**
** 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 VMR9VIDEOWINDOWCONTROL_H
#define VMR9VIDEOWINDOWCONTROL_H
#include "qvideowindowcontrol.h"
#include <dshow.h>
#include <d3d9.h>
#include <vmr9.h>
QT_USE_NAMESPACE
class Vmr9VideoWindowControl : public QVideoWindowControl
{
Q_OBJECT
public:
Vmr9VideoWindowControl(QObject *parent = 0);
~Vmr9VideoWindowControl();
IBaseFilter *filter() const { return m_filter; }
WId winId() const;
void setWinId(WId id);
QRect displayRect() const;
void setDisplayRect(const QRect &rect);
bool isFullScreen() const;
void setFullScreen(bool fullScreen);
void repaint();
QSize nativeSize() const;
Qt::AspectRatioMode aspectRatioMode() const;
void setAspectRatioMode(Qt::AspectRatioMode mode);
int brightness() const;
void setBrightness(int brightness);
int contrast() const;
void setContrast(int contrast);
int hue() const;
void setHue(int hue);
int saturation() const;
void setSaturation(int saturation);
private:
void setProcAmpValues();
float scaleProcAmpValue(
IVMRMixerControl9 *control, VMR9ProcAmpControlFlags property, int value) const;
IBaseFilter *m_filter;
WId m_windowId;
COLORREF m_windowColor;
DWORD m_dirtyValues;
Qt::AspectRatioMode m_aspectRatioMode;
QRect m_displayRect;
int m_brightness;
int m_contrast;
int m_hue;
int m_saturation;
bool m_fullScreen;
};
#endif

View File

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

View File

@@ -0,0 +1,293 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "camerabinaudioencoder.h"
#include "camerabincontainer.h"
#include <QtCore/qdebug.h>
CameraBinAudioEncoder::CameraBinAudioEncoder(QObject *parent)
:QAudioEncoderControl(parent)
{
QList<QByteArray> codecCandidates;
#if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
codecCandidates << "audio/AAC" << "audio/PCM" << "audio/AMR" << "audio/AMR-WB" << "audio/speex"
<< "audio/ADPCM" << "audio/iLBC" << "audio/vorbis" << "audio/mpeg" << "audio/FLAC";
m_elementNames["audio/AAC"] = "nokiaaacenc";
m_elementNames["audio/speex"] = "speexenc";
m_elementNames["audio/PCM"] = "audioresample";
m_elementNames["audio/AMR"] = "nokiaamrnbenc";
m_elementNames["audio/AMR-WB"] = "nokiaamrwbenc";
m_elementNames["audio/ADPCM"] = "nokiaadpcmenc";
m_elementNames["audio/iLBC"] = "nokiailbcenc";
m_elementNames["audio/vorbis"] = "vorbisenc";
m_elementNames["audio/FLAC"] = "flacenc";
m_elementNames["audio/mpeg"] = "ffenc_mp2";
#else
codecCandidates << "audio/mpeg" << "audio/vorbis" << "audio/speex" << "audio/GSM"
<< "audio/PCM" << "audio/AMR" << "audio/AMR-WB";
m_elementNames["audio/mpeg"] = "lamemp3enc";
m_elementNames["audio/vorbis"] = "vorbisenc";
m_elementNames["audio/speex"] = "speexenc";
m_elementNames["audio/GSM"] = "gsmenc";
m_elementNames["audio/PCM"] = "audioresample";
m_elementNames["audio/AMR"] = "amrnbenc";
m_elementNames["audio/AMR-WB"] = "amrwbenc";
m_codecOptions["audio/vorbis"] = QStringList() << "min-bitrate" << "max-bitrate";
m_codecOptions["audio/mpeg"] = QStringList() << "mode";
m_codecOptions["audio/speex"] = QStringList() << "mode" << "vbr" << "vad" << "dtx";
m_codecOptions["audio/GSM"] = QStringList();
m_codecOptions["audio/PCM"] = QStringList();
m_codecOptions["audio/AMR"] = QStringList();
m_codecOptions["audio/AMR-WB"] = QStringList();
#endif
foreach( const QByteArray& codecName, codecCandidates ) {
QByteArray elementName = m_elementNames[codecName];
GstElementFactory *factory = gst_element_factory_find(elementName.constData());
if (factory) {
m_codecs.append(codecName);
const gchar *descr = gst_element_factory_get_description(factory);
if (codecName == QByteArray("audio/PCM"))
m_codecDescriptions.insert(codecName, tr("Raw PCM audio"));
else
m_codecDescriptions.insert(codecName, QString::fromUtf8(descr));
m_streamTypes.insert(codecName,
CameraBinContainer::supportedStreamTypes(factory, GST_PAD_SRC));
gst_object_unref(GST_OBJECT(factory));
}
}
}
CameraBinAudioEncoder::~CameraBinAudioEncoder()
{
}
QStringList CameraBinAudioEncoder::supportedAudioCodecs() const
{
return m_codecs;
}
QString CameraBinAudioEncoder::codecDescription(const QString &codecName) const
{
return m_codecDescriptions.value(codecName);
}
QStringList CameraBinAudioEncoder::supportedEncodingOptions(const QString &codec) const
{
return m_codecOptions.value(codec);
}
QVariant CameraBinAudioEncoder::encodingOption(
const QString &codec, const QString &name) const
{
return m_options[codec].value(name);
}
void CameraBinAudioEncoder::setEncodingOption(
const QString &codec, const QString &name, const QVariant &value)
{
m_options[codec][name] = value;
}
QList<int> CameraBinAudioEncoder::supportedSampleRates(const QAudioEncoderSettings &, bool *) const
{
//TODO check element caps to find actual values
return QList<int>();
}
QAudioEncoderSettings CameraBinAudioEncoder::audioSettings() const
{
return m_audioSettings;
}
void CameraBinAudioEncoder::setAudioSettings(const QAudioEncoderSettings &settings)
{
m_userSettings = settings;
m_audioSettings = settings;
emit settingsChanged();
}
void CameraBinAudioEncoder::setActualAudioSettings(const QAudioEncoderSettings &settings)
{
m_audioSettings = settings;
}
void CameraBinAudioEncoder::resetActualSettings()
{
m_audioSettings = m_userSettings;
}
GstElement *CameraBinAudioEncoder::createEncoder()
{
QString codec = m_audioSettings.codec();
QByteArray encoderElementName = m_elementNames.value(codec);
GstElement *encoderElement = gst_element_factory_make(encoderElementName.constData(), NULL);
if (!encoderElement)
return 0;
GstBin * encoderBin = GST_BIN(gst_bin_new("audio-encoder-bin"));
GstElement *capsFilter = gst_element_factory_make("capsfilter", NULL);
gst_bin_add(encoderBin, capsFilter);
gst_bin_add(encoderBin, encoderElement);
gst_element_link(capsFilter, encoderElement);
// add ghostpads
GstPad *pad = gst_element_get_static_pad(capsFilter, "sink");
gst_element_add_pad(GST_ELEMENT(encoderBin), gst_ghost_pad_new("sink", pad));
gst_object_unref(GST_OBJECT(pad));
pad = gst_element_get_static_pad(encoderElement, "src");
gst_element_add_pad(GST_ELEMENT(encoderBin), gst_ghost_pad_new("src", pad));
gst_object_unref(GST_OBJECT(pad));
if (m_audioSettings.sampleRate() > 0 || m_audioSettings.channelCount() > 0) {
GstCaps *caps = gst_caps_new_empty();
GstStructure *structure = gst_structure_new("audio/x-raw-int", NULL);
if (m_audioSettings.sampleRate() > 0)
gst_structure_set(structure, "rate", G_TYPE_INT, m_audioSettings.sampleRate(), NULL );
if (m_audioSettings.channelCount() > 0)
gst_structure_set(structure, "channels", G_TYPE_INT, m_audioSettings.channelCount(), NULL );
gst_caps_append_structure(caps,structure);
g_object_set(G_OBJECT(capsFilter), "caps", caps, NULL);
}
if (encoderElement) {
if (m_audioSettings.encodingMode() == QtMultimediaKit::ConstantQualityEncoding) {
QtMultimediaKit::EncodingQuality qualityValue = m_audioSettings.quality();
if (encoderElementName == "lamemp3enc") {
g_object_set(G_OBJECT(encoderElement), "target", 0, NULL); //constant quality mode
qreal quality[] = {
10.0, //VeryLow
6.0, //Low
4.0, //Normal
2.0, //High
0.0 //VeryHigh
};
g_object_set(G_OBJECT(encoderElement), "quality", quality[qualityValue], NULL);
} else if (encoderElementName == "ffenc_mp2") {
int quality[] = {
8000, //VeryLow
64000, //Low
128000, //Normal
192000, //High
320000 //VeryHigh
};
g_object_set(G_OBJECT(encoderElement), "bitrate", quality[qualityValue], NULL);
} else if (codec == QLatin1String("audio/speex")) {
//0-10 range with default 8
double qualityTable[] = {
2, //VeryLow
5, //Low
8, //Normal
9, //High
10 //VeryHigh
};
g_object_set(G_OBJECT(encoderElement), "quality", qualityTable[qualityValue], NULL);
} else if (codec.startsWith("audio/AMR")) {
int band[] = {
0, //VeryLow
2, //Low
4, //Normal
6, //High
7 //VeryHigh
};
g_object_set(G_OBJECT(encoderElement), "band-mode", band[qualityValue], NULL);
}
} else {
int bitrate = m_audioSettings.bitRate();
if (bitrate > 0) {
g_object_set(G_OBJECT(encoderElement), "bitrate", bitrate, NULL);
}
}
QMap<QString, QVariant> options = m_options.value(codec);
QMapIterator<QString,QVariant> it(options);
while (it.hasNext()) {
it.next();
QString option = it.key();
QVariant value = it.value();
switch (value.type()) {
case QVariant::Int:
g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toInt(), NULL);
break;
case QVariant::Bool:
g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toBool(), NULL);
break;
case QVariant::Double:
g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toDouble(), NULL);
break;
case QVariant::String:
g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toString().toUtf8().constData(), NULL);
break;
default:
qWarning() << "unsupported option type:" << option << value;
break;
}
}
}
return GST_ELEMENT(encoderBin);
}
QSet<QString> CameraBinAudioEncoder::supportedStreamTypes(const QString &codecName) const
{
return m_streamTypes.value(codecName);
}

View File

@@ -0,0 +1,105 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CAMERABINAUDIOENCODE_H
#define CAMERABINAUDIOENCODE_H
#include <qaudioencodercontrol.h>
class CameraBinSession;
#include <QtCore/qstringlist.h>
#include <QtCore/qmap.h>
#include <QtCore/qset.h>
#include <gst/gst.h>
#include <qaudioformat.h>
QT_USE_NAMESPACE
class CameraBinAudioEncoder : public QAudioEncoderControl
{
Q_OBJECT
public:
CameraBinAudioEncoder(QObject *parent);
virtual ~CameraBinAudioEncoder();
QStringList supportedAudioCodecs() const;
QString codecDescription(const QString &codecName) const;
QStringList supportedEncodingOptions(const QString &codec) const;
QVariant encodingOption(const QString &codec, const QString &name) const;
void setEncodingOption(const QString &codec, const QString &name, const QVariant &value);
QList<int> supportedSampleRates(const QAudioEncoderSettings &settings = QAudioEncoderSettings(),
bool *isContinuous = 0) const;
QList<int> supportedChannelCounts(const QAudioEncoderSettings &settings = QAudioEncoderSettings()) const;
QList<int> supportedSampleSizes(const QAudioEncoderSettings &settings = QAudioEncoderSettings()) const;
QAudioEncoderSettings audioSettings() const;
void setAudioSettings(const QAudioEncoderSettings&);
GstElement *createEncoder();
QSet<QString> supportedStreamTypes(const QString &codecName) const;
void setActualAudioSettings(const QAudioEncoderSettings&);
void resetActualSettings();
Q_SIGNALS:
void settingsChanged();
private:
QStringList m_codecs;
QMap<QString,QByteArray> m_elementNames;
QMap<QString,QString> m_codecDescriptions;
QMap<QString,QStringList> m_codecOptions;
QMap<QString, QMap<QString, QVariant> > m_options;
QMap<QString, QSet<QString> > m_streamTypes;
QAudioEncoderSettings m_audioSettings;
QAudioEncoderSettings m_userSettings;
};
#endif

View File

@@ -0,0 +1,78 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "camerabincapturebufferformat.h"
#include "camerabinsession.h"
CameraBinCaptureBufferFormat::CameraBinCaptureBufferFormat(CameraBinSession *session)
:QCameraCaptureBufferFormatControl(session)
, m_session(session)
, m_format(QVideoFrame::Format_Jpeg)
{
}
CameraBinCaptureBufferFormat::~CameraBinCaptureBufferFormat()
{
}
QList<QVideoFrame::PixelFormat> CameraBinCaptureBufferFormat::supportedBufferFormats() const
{
//the exact YUV format is unknown with camerabin until the first capture is requested
return QList<QVideoFrame::PixelFormat>()
<< QVideoFrame::Format_Jpeg
#ifdef Q_WS_MAEMO_6
<< QVideoFrame::Format_UYVY
#endif
;
}
QVideoFrame::PixelFormat CameraBinCaptureBufferFormat::bufferFormat() const
{
return m_format;
}
void CameraBinCaptureBufferFormat::setBufferFormat(QVideoFrame::PixelFormat format)
{
if (m_format != format) {
m_format = format;
emit bufferFormatChanged(format);
}
}

View File

@@ -0,0 +1,72 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CAMERABINCAPTUREBUFFERFORMAT_H
#define CAMERABINCAPTUREBUFFERFORMAT_H
#include <qcamera.h>
#include <qcameracapturebufferformatcontrol.h>
#include <gst/gst.h>
#include <glib.h>
class CameraBinSession;
QT_USE_NAMESPACE
class Q_MULTIMEDIA_EXPORT CameraBinCaptureBufferFormat : public QCameraCaptureBufferFormatControl
{
Q_OBJECT
public:
CameraBinCaptureBufferFormat(CameraBinSession *session);
virtual ~CameraBinCaptureBufferFormat();
QList<QVideoFrame::PixelFormat> supportedBufferFormats() const;
QVideoFrame::PixelFormat bufferFormat() const;
void setBufferFormat(QVideoFrame::PixelFormat format);
private:
CameraBinSession *m_session;
QVideoFrame::PixelFormat m_format;
};
#endif

View File

@@ -0,0 +1,74 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "camerabincapturedestination.h"
#include "camerabinsession.h"
CameraBinCaptureDestination::CameraBinCaptureDestination(CameraBinSession *session)
:QCameraCaptureDestinationControl(session)
, m_session(session)
, m_destination(QCameraImageCapture::CaptureToFile)
{
}
CameraBinCaptureDestination::~CameraBinCaptureDestination()
{
}
bool CameraBinCaptureDestination::isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const
{
//capture to buffer, file and both are supported.
return destination & (QCameraImageCapture::CaptureToFile | QCameraImageCapture::CaptureToBuffer);
}
QCameraImageCapture::CaptureDestinations CameraBinCaptureDestination::captureDestination() const
{
return m_destination;
}
void CameraBinCaptureDestination::setCaptureDestination(QCameraImageCapture::CaptureDestinations destination)
{
if (m_destination != destination) {
m_destination = destination;
emit captureDestinationChanged(m_destination);
}
}

View File

@@ -0,0 +1,69 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CAMERABINCAPTUREDESTINATION_H
#define CAMERABINCAPTUREDESTINATION_H
#include <qcameraimagecapture.h>
#include <qcameracapturedestinationcontrol.h>
class CameraBinSession;
QT_USE_NAMESPACE
class Q_MULTIMEDIA_EXPORT CameraBinCaptureDestination : public QCameraCaptureDestinationControl
{
Q_OBJECT
public:
CameraBinCaptureDestination(CameraBinSession *session);
virtual ~CameraBinCaptureDestination();
bool isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const;
QCameraImageCapture::CaptureDestinations captureDestination() const;
void setCaptureDestination(QCameraImageCapture::CaptureDestinations destination);
private:
CameraBinSession *m_session;
QCameraImageCapture::CaptureDestinations m_destination;
};
#endif // CAMERABINFLASHCONTROL_H

View File

@@ -0,0 +1,122 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "camerabincontainer.h"
#include <QtCore/qdebug.h>
CameraBinContainer::CameraBinContainer(QObject *parent)
:QMediaContainerControl(parent)
{
QList<QByteArray> formatCandidates;
formatCandidates << "mp4" << "ogg" << "wav" << "amr" << "mkv"
<< "avi" << "3gp" << "3gp2" << "webm" << "mjpeg" << "asf" << "mov";
QMap<QString,QByteArray> elementNames;
elementNames.insertMulti("mp4", "ffmux_mp4");
elementNames.insertMulti("mp4", "hantromp4mux");
elementNames.insertMulti("mp4", "mp4mux");
elementNames.insert("ogg", "oggmux");
elementNames["wav"] = "wavenc";
elementNames["amr"] = "ffmux_amr";
elementNames["mkv"] = "matroskamux";
elementNames["avi"] = "avimux";
elementNames["3gp"] = "ffmux_3gp";
elementNames["3gp2"] = "ffmux_3g2";
elementNames["webm"] = "webmmux";
elementNames["mjpeg"] = "ffmux_mjpeg";
elementNames["asf"] = "ffmux_asf";
elementNames["mov"] = "qtmux";
QSet<QString> allTypes;
foreach(const QByteArray &formatName, formatCandidates) {
foreach(const QByteArray &elementName, elementNames.values(formatName)) {
GstElementFactory *factory = gst_element_factory_find(elementName.constData());
if (factory) {
m_supportedContainers.append(formatName);
const gchar *descr = gst_element_factory_get_description(factory);
m_containerDescriptions.insert(formatName, QString::fromUtf8(descr));
if (formatName == QByteArray("raw")) {
m_streamTypes.insert(formatName, allTypes);
} else {
QSet<QString> types = supportedStreamTypes(factory, GST_PAD_SINK);
m_streamTypes.insert(formatName, types);
allTypes.unite(types);
}
gst_object_unref(GST_OBJECT(factory));
m_elementNames.insert(formatName, elementName);
break;
}
}
}
}
QSet<QString> CameraBinContainer::supportedStreamTypes(GstElementFactory *factory, GstPadDirection direction)
{
QSet<QString> types;
const GList *pads = gst_element_factory_get_static_pad_templates(factory);
for (const GList *pad = pads; pad; pad = g_list_next(pad)) {
GstStaticPadTemplate *templ = (GstStaticPadTemplate*)pad->data;
if (templ->direction == direction) {
GstCaps *caps = gst_static_caps_get(&templ->static_caps);
for (uint i=0; i<gst_caps_get_size(caps); i++) {
GstStructure *structure = gst_caps_get_structure(caps, i);
types.insert( QString::fromUtf8(gst_structure_get_name(structure)) );
}
gst_caps_unref(caps);
}
}
return types;
}
QSet<QString> CameraBinContainer::supportedStreamTypes(const QString &container) const
{
return m_streamTypes.value(container);
}

View File

@@ -0,0 +1,103 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CAMERABINMEDIACONTAINERCONTROL_H
#define CAMERABINMEDIACONTAINERCONTROL_H
#include <qmediacontainercontrol.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qset.h>
#include <gst/gst.h>
QT_USE_NAMESPACE
class CameraBinContainer : public QMediaContainerControl
{
Q_OBJECT
public:
CameraBinContainer(QObject *parent);
virtual ~CameraBinContainer() {}
virtual QStringList supportedContainers() const { return m_supportedContainers; }
virtual QString containerMimeType() const { return m_format; }
virtual void setContainerMimeType(const QString &formatMimeType)
{
m_format = formatMimeType;
if (m_userFormat != formatMimeType) {
m_userFormat = formatMimeType;
emit settingsChanged();
}
}
void setActualContainer(const QString &formatMimeType)
{
m_format = formatMimeType;
}
void resetActualContainer()
{
m_format = m_userFormat;
}
virtual QString containerDescription(const QString &formatMimeType) const { return m_containerDescriptions.value(formatMimeType); }
QByteArray formatElementName() const { return m_elementNames.value(containerMimeType()); }
QSet<QString> supportedStreamTypes(const QString &container) const;
static QSet<QString> supportedStreamTypes(GstElementFactory *factory, GstPadDirection direction);
Q_SIGNALS:
void settingsChanged();
private:
QString m_format; // backend selected format, using m_userFormat
QString m_userFormat;
QStringList m_supportedContainers;
QMap<QString,QByteArray> m_elementNames;
QMap<QString, QString> m_containerDescriptions;
QMap<QString, QSet<QString> > m_streamTypes;
};
#endif // CAMERABINMEDIACONTAINERCONTROL_H

View File

@@ -0,0 +1,356 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "camerabincontrol.h"
#include "camerabincontainer.h"
#include "camerabinaudioencoder.h"
#include "camerabinvideoencoder.h"
#include "camerabinimageencoder.h"
#include "camerabinresourcepolicy.h"
#include <QtCore/qdebug.h>
#include <QtCore/qfile.h>
#include <QtCore/qmetaobject.h>
#include <linux/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
//#define CAMEABIN_DEBUG 1
#define ENUM_NAME(c,e,v) (c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(e)).valueToKey((v)))
CameraBinControl::CameraBinControl(CameraBinSession *session)
:QCameraControl(session),
m_session(session),
m_state(QCamera::UnloadedState),
m_status(QCamera::UnloadedStatus),
m_reloadPending(false)
{
connect(m_session, SIGNAL(stateChanged(QCamera::State)),
this, SLOT(updateStatus()));
connect(m_session->audioEncodeControl(), SIGNAL(settingsChanged()),
SLOT(reloadLater()));
connect(m_session->videoEncodeControl(), SIGNAL(settingsChanged()),
SLOT(reloadLater()));
connect(m_session->mediaContainerControl(), SIGNAL(settingsChanged()),
SLOT(reloadLater()));
connect(m_session->imageEncodeControl(), SIGNAL(settingsChanged()),
SLOT(reloadLater()));
connect(m_session, SIGNAL(viewfinderChanged()),
SLOT(reloadLater()));
connect(m_session, SIGNAL(readyChanged(bool)),
SLOT(reloadLater()));
connect(m_session, SIGNAL(error(int,QString)),
SLOT(handleCameraError(int,QString)));
m_resourcePolicy = new CamerabinResourcePolicy(this);
connect(m_resourcePolicy, SIGNAL(resourcesGranted()),
SLOT(handleResourcesGranted()));
connect(m_resourcePolicy, SIGNAL(resourcesDenied()),
SLOT(handleResourcesLost()));
connect(m_resourcePolicy, SIGNAL(resourcesLost()),
SLOT(handleResourcesLost()));
connect(m_session, SIGNAL(busyChanged(bool)),
SLOT(handleBusyChanged(bool)));
}
CameraBinControl::~CameraBinControl()
{
}
QCamera::CaptureMode CameraBinControl::captureMode() const
{
return m_session->captureMode();
}
void CameraBinControl::setCaptureMode(QCamera::CaptureMode mode)
{
if (m_session->captureMode() != mode) {
m_session->setCaptureMode(mode);
reloadLater();
if (m_state == QCamera::ActiveState) {
m_resourcePolicy->setResourceSet(
captureMode() == QCamera::CaptureStillImage ?
CamerabinResourcePolicy::ImageCaptureResources :
CamerabinResourcePolicy::VideoCaptureResources);
}
emit captureModeChanged(mode);
}
}
bool CameraBinControl::isCaptureModeSupported(QCamera::CaptureMode mode) const
{
#ifdef Q_WS_MAEMO_5
//Front camera on N900 supports only video capture
if (m_session->cameraRole() == CameraBinSession::FrontCamera)
return mode == QCamera::CaptureVideo;
#endif
return mode == QCamera::CaptureStillImage || mode == QCamera::CaptureVideo;
}
void CameraBinControl::setState(QCamera::State state)
{
#ifdef CAMEABIN_DEBUG
qDebug() << Q_FUNC_INFO << ENUM_NAME(QCamera, "State", state);
#endif
if (m_state != state) {
m_state = state;
//special case for stopping the camera while it's busy,
//it should be delayed until the camera is idle
if (state == QCamera::LoadedState &&
m_session->state() == QCamera::ActiveState &&
m_session->isBusy()) {
#ifdef CAMEABIN_DEBUG
qDebug() << Q_FUNC_INFO << "Camera is busy, QCamera::stop() is delayed";
#endif
emit stateChanged(m_state);
return;
}
CamerabinResourcePolicy::ResourceSet resourceSet;
switch (state) {
case QCamera::UnloadedState:
resourceSet = CamerabinResourcePolicy::NoResources;
break;
case QCamera::LoadedState:
resourceSet = CamerabinResourcePolicy::LoadedResources;
break;
case QCamera::ActiveState:
resourceSet = captureMode() == QCamera::CaptureStillImage ?
CamerabinResourcePolicy::ImageCaptureResources :
CamerabinResourcePolicy::VideoCaptureResources;
break;
}
m_resourcePolicy->setResourceSet(resourceSet);
if (m_resourcePolicy->isResourcesGranted()) {
//postpone changing to Active if the session is nor ready yet
if (state == QCamera::ActiveState) {
if (m_session->isReady()) {
m_session->setState(state);
} else {
#ifdef CAMEABIN_DEBUG
qDebug() << "Camera session is not ready yet, postpone activating";
#endif
}
} else
m_session->setState(state);
}
emit stateChanged(m_state);
}
}
QCamera::State CameraBinControl::state() const
{
return m_state;
}
void CameraBinControl::updateStatus()
{
QCamera::State sessionState = m_session->state();
QCamera::Status oldStatus = m_status;
switch (m_state) {
case QCamera::UnloadedState:
m_status = QCamera::UnloadedStatus;
break;
case QCamera::LoadedState:
switch (sessionState) {
case QCamera::UnloadedState:
m_status = QCamera::LoadingStatus;
break;
case QCamera::LoadedState:
m_status = QCamera::LoadedStatus;
break;
case QCamera::ActiveState:
m_status = QCamera::ActiveStatus;
break;
}
break;
case QCamera::ActiveState:
switch (sessionState) {
case QCamera::UnloadedState:
m_status = QCamera::LoadingStatus;
break;
case QCamera::LoadedState:
m_status = QCamera::StartingStatus;
break;
case QCamera::ActiveState:
m_status = QCamera::ActiveStatus;
break;
}
}
if (m_status != oldStatus) {
#ifdef CAMEABIN_DEBUG
qDebug() << "Camera status changed" << ENUM_NAME(QCamera, "Status", m_status);
#endif
emit statusChanged(m_status);
}
}
void CameraBinControl::reloadLater()
{
#ifdef CAMEABIN_DEBUG
qDebug() << "CameraBinControl: reload pipeline requested" << ENUM_NAME(QCamera, "State", m_state);
#endif
if (!m_reloadPending && m_state == QCamera::ActiveState) {
m_reloadPending = true;
if (!m_session->isBusy()) {
m_session->setState(QCamera::LoadedState);
QMetaObject::invokeMethod(this, "delayedReload", Qt::QueuedConnection);
}
}
}
void CameraBinControl::handleResourcesLost()
{
#ifdef CAMEABIN_DEBUG
qDebug() << Q_FUNC_INFO << ENUM_NAME(QCamera, "State", m_state);
#endif
m_session->setState(QCamera::UnloadedState);
}
void CameraBinControl::handleResourcesGranted()
{
#ifdef CAMEABIN_DEBUG
qDebug() << Q_FUNC_INFO << ENUM_NAME(QCamera, "State", m_state);
#endif
//camera will be started soon by delayedReload()
if (m_reloadPending && m_state == QCamera::ActiveState)
return;
if (m_state == QCamera::ActiveState && m_session->isReady())
m_session->setState(QCamera::ActiveState);
else if (m_state == QCamera::LoadedState)
m_session->setState(QCamera::LoadedState);
}
void CameraBinControl::handleBusyChanged(bool busy)
{
if (!busy && m_session->state() == QCamera::ActiveState) {
if (m_state == QCamera::LoadedState) {
//handle delayed stop() because of busy camera
m_resourcePolicy->setResourceSet(CamerabinResourcePolicy::LoadedResources);
m_session->setState(QCamera::LoadedState);
} else if (m_state == QCamera::ActiveState && m_reloadPending) {
//handle delayed reload because of busy camera
m_session->setState(QCamera::LoadedState);
QMetaObject::invokeMethod(this, "delayedReload", Qt::QueuedConnection);
}
}
}
void CameraBinControl::handleCameraError(int errorCode, const QString &errorString)
{
emit error(errorCode, errorString);
setState(QCamera::UnloadedState);
}
void CameraBinControl::delayedReload()
{
#ifdef CAMEABIN_DEBUG
qDebug() << "CameraBinControl: reload pipeline";
#endif
if (m_reloadPending) {
m_reloadPending = false;
if (m_state == QCamera::ActiveState &&
m_session->isReady() &&
m_resourcePolicy->isResourcesGranted()) {
m_session->setState(QCamera::ActiveState);
}
}
}
bool CameraBinControl::canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const
{
Q_UNUSED(status);
switch (changeType) {
case QCameraControl::CaptureMode:
case QCameraControl::ImageEncodingSettings:
case QCameraControl::VideoEncodingSettings:
case QCameraControl::Viewfinder:
return true;
default:
return false;
}
}
#define VIEWFINDER_COLORSPACE_CONVERSION 0x00000004
bool CameraBinControl::viewfinderColorSpaceConversion() const
{
gint flags = 0;
g_object_get(G_OBJECT(m_session->cameraBin()), "flags", &flags, NULL);
return flags & VIEWFINDER_COLORSPACE_CONVERSION;
}
void CameraBinControl::setViewfinderColorSpaceConversion(bool enabled)
{
gint flags = 0;
g_object_get(G_OBJECT(m_session->cameraBin()), "flags", &flags, NULL);
if (enabled)
flags |= VIEWFINDER_COLORSPACE_CONVERSION;
else
flags &= ~VIEWFINDER_COLORSPACE_CONVERSION;
g_object_set(G_OBJECT(m_session->cameraBin()), "flags", flags, NULL);
}

View File

@@ -0,0 +1,101 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CAMERABINCONTROL_H
#define CAMERABINCONTROL_H
#include <QHash>
#include <qcameracontrol.h>
#include "camerabinsession.h"
QT_USE_NAMESPACE
class CamerabinResourcePolicy;
class CameraBinControl : public QCameraControl
{
Q_OBJECT
Q_PROPERTY(bool viewfinderColorSpaceConversion READ viewfinderColorSpaceConversion WRITE setViewfinderColorSpaceConversion)
public:
CameraBinControl( CameraBinSession *session );
virtual ~CameraBinControl();
bool isValid() const { return true; }
QCamera::State state() const;
void setState(QCamera::State state);
QCamera::Status status() const { return m_status; }
QCamera::CaptureMode captureMode() const;
void setCaptureMode(QCamera::CaptureMode mode);
bool isCaptureModeSupported(QCamera::CaptureMode mode) const;
bool canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const;
bool viewfinderColorSpaceConversion() const;
public slots:
void reloadLater();
void setViewfinderColorSpaceConversion(bool enabled);
private slots:
void updateStatus();
void delayedReload();
void handleResourcesGranted();
void handleResourcesLost();
void handleBusyChanged(bool);
void handleCameraError(int error, const QString &errorString);
private:
void updateSupportedResolutions(const QString &device);
CameraBinSession *m_session;
QCamera::State m_state;
QCamera::Status m_status;
CamerabinResourcePolicy *m_resourcePolicy;
bool m_reloadPending;
};
#endif // CAMERABINCONTROL_H

View File

@@ -0,0 +1,232 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "camerabinexposure.h"
#include "camerabinsession.h"
#include <gst/interfaces/photography.h>
#include <QDebug>
CameraBinExposure::CameraBinExposure(CameraBinSession *session)
:QCameraExposureControl(session),
m_session(session)
{
}
CameraBinExposure::~CameraBinExposure()
{
}
QCameraExposure::ExposureMode CameraBinExposure::exposureMode() const
{
GstSceneMode sceneMode;
gst_photography_get_scene_mode(m_session->photography(), &sceneMode);
switch (sceneMode) {
case GST_PHOTOGRAPHY_SCENE_MODE_PORTRAIT: return QCameraExposure::ExposurePortrait;
case GST_PHOTOGRAPHY_SCENE_MODE_SPORT: return QCameraExposure::ExposureSports;
case GST_PHOTOGRAPHY_SCENE_MODE_NIGHT: return QCameraExposure::ExposureNight;
case GST_PHOTOGRAPHY_SCENE_MODE_MANUAL: return QCameraExposure::ExposureManual;
case GST_PHOTOGRAPHY_SCENE_MODE_CLOSEUP: //no direct mapping available so mapping to auto mode
case GST_PHOTOGRAPHY_SCENE_MODE_LANDSCAPE: //no direct mapping available so mapping to auto mode
case GST_PHOTOGRAPHY_SCENE_MODE_AUTO:
default:
return QCameraExposure::ExposureAuto;
}
}
void CameraBinExposure::setExposureMode(QCameraExposure::ExposureMode mode)
{
GstSceneMode sceneMode;
gst_photography_get_scene_mode(m_session->photography(), &sceneMode);
switch (mode) {
case QCameraExposure::ExposureManual: sceneMode = GST_PHOTOGRAPHY_SCENE_MODE_MANUAL; break;
case QCameraExposure::ExposurePortrait: sceneMode = GST_PHOTOGRAPHY_SCENE_MODE_PORTRAIT; break;
case QCameraExposure::ExposureSports: sceneMode = GST_PHOTOGRAPHY_SCENE_MODE_SPORT; break;
case QCameraExposure::ExposureNight: sceneMode = GST_PHOTOGRAPHY_SCENE_MODE_NIGHT; break;
case QCameraExposure::ExposureAuto: sceneMode = GST_PHOTOGRAPHY_SCENE_MODE_AUTO; break;
default:
break;
}
gst_photography_set_scene_mode(m_session->photography(), sceneMode);
}
bool CameraBinExposure::isExposureModeSupported(QCameraExposure::ExposureMode mode) const
{
//Similar mode names can be found in gst as GstSceneMode
return mode == QCameraExposure::ExposureAuto ||
mode == QCameraExposure::ExposurePortrait ||
mode == QCameraExposure::ExposureSports ||
mode == QCameraExposure::ExposureNight;
//No direct mapping available for GST_PHOTOGRAPHY_SCENE_MODE_CLOSEUP and
//GST_PHOTOGRAPHY_SCENE_MODE_LANDSCAPE
}
QCameraExposure::MeteringMode CameraBinExposure::meteringMode() const
{
return QCameraExposure::MeteringMatrix;
}
void CameraBinExposure::setMeteringMode(QCameraExposure::MeteringMode mode)
{
Q_UNUSED(mode);
}
bool CameraBinExposure::isMeteringModeSupported(QCameraExposure::MeteringMode mode) const
{
return mode == QCameraExposure::MeteringMatrix;
}
bool CameraBinExposure::isParameterSupported(ExposureParameter parameter) const
{
switch (parameter) {
case QCameraExposureControl::ExposureCompensation:
case QCameraExposureControl::ISO:
case QCameraExposureControl::Aperture:
case QCameraExposureControl::ShutterSpeed:
return true;
default:
return false;
}
}
QVariant CameraBinExposure::exposureParameter(ExposureParameter parameter) const
{
switch (parameter) {
case QCameraExposureControl::ExposureCompensation:
{
gfloat ev;
gst_photography_get_ev_compensation(m_session->photography(), &ev);
return QVariant(ev);
}
case QCameraExposureControl::ISO:
{
guint isoSpeed = 0;
gst_photography_get_iso_speed(m_session->photography(), &isoSpeed);
return QVariant(isoSpeed);
}
case QCameraExposureControl::Aperture:
return QVariant(2.8);
case QCameraExposureControl::ShutterSpeed:
{
guint32 shutterSpeed = 0;
gst_photography_get_exposure(m_session->photography(), &shutterSpeed);
return QVariant(shutterSpeed/1000000.0);
}
default:
return QVariant();
}
}
QCameraExposureControl::ParameterFlags CameraBinExposure::exposureParameterFlags(ExposureParameter parameter) const
{
QCameraExposureControl::ParameterFlags flags = 0;
switch (parameter) {
case QCameraExposureControl::ExposureCompensation:
flags |= ContinuousRange;
break;
case QCameraExposureControl::Aperture:
flags |= ReadOnly;
break;
default:
break;
}
return flags;
}
QVariantList CameraBinExposure::supportedParameterRange(ExposureParameter parameter) const
{
QVariantList res;
switch (parameter) {
case QCameraExposureControl::ExposureCompensation:
res << -2.0 << 2.0;
break;
case QCameraExposureControl::ISO:
res << 100 << 200 << 400;
break;
case QCameraExposureControl::Aperture:
res << 2.8;
break;
default:
break;
}
return res;
}
bool CameraBinExposure::setExposureParameter(ExposureParameter parameter, const QVariant& value)
{
QVariant oldValue = exposureParameter(parameter);
switch (parameter) {
case QCameraExposureControl::ExposureCompensation:
gst_photography_set_ev_compensation(m_session->photography(), value.toReal());
break;
case QCameraExposureControl::ISO:
gst_photography_set_iso_speed(m_session->photography(), value.toInt());
break;
case QCameraExposureControl::Aperture:
gst_photography_set_aperture(m_session->photography(), guint(value.toReal()*1000000));
break;
case QCameraExposureControl::ShutterSpeed:
gst_photography_set_exposure(m_session->photography(), guint(value.toReal()*1000000));
break;
default:
return false;
}
QVariant newValue = exposureParameter(parameter);
if (!qFuzzyCompare(oldValue.toReal(), newValue.toReal()))
emit exposureParameterChanged(parameter);
return true;
}
QString CameraBinExposure::extendedParameterName(ExposureParameter)
{
return QString();
}

View File

@@ -0,0 +1,83 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CAMERABINEXPOSURECONTROL_MAEMO_H
#define CAMERABINEXPOSURECONTROL_MAEMO_H
#include <qcamera.h>
#include <qcameraexposurecontrol.h>
#include <gst/gst.h>
#include <glib.h>
class CameraBinSession;
QT_USE_NAMESPACE
class Q_MULTIMEDIA_EXPORT CameraBinExposure : public QCameraExposureControl
{
Q_OBJECT
public:
CameraBinExposure(CameraBinSession *session);
virtual ~CameraBinExposure();
QCameraExposure::ExposureMode exposureMode() const;
void setExposureMode(QCameraExposure::ExposureMode mode);
bool isExposureModeSupported(QCameraExposure::ExposureMode mode) const;
QCameraExposure::MeteringMode meteringMode() const;
void setMeteringMode(QCameraExposure::MeteringMode mode);
bool isMeteringModeSupported(QCameraExposure::MeteringMode mode) const;
bool isParameterSupported(ExposureParameter parameter) const;
QVariant exposureParameter(ExposureParameter parameter) const;
ParameterFlags exposureParameterFlags(ExposureParameter parameter) const;
QVariantList supportedParameterRange(ExposureParameter parameter) const;
bool setExposureParameter(ExposureParameter parameter, const QVariant& value);
QString extendedParameterName(ExposureParameter parameter);
private:
CameraBinSession *m_session;
};
#endif // CAMERABINEXPOSURECONTROL_MAEMO_H

View File

@@ -0,0 +1,104 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "camerabinflash.h"
#include "camerabinsession.h"
#include <gst/interfaces/photography.h>
#include <QDebug>
CameraBinFlash::CameraBinFlash(CameraBinSession *session)
:QCameraFlashControl(session),
m_session(session)
{
}
CameraBinFlash::~CameraBinFlash()
{
}
QCameraExposure::FlashModes CameraBinFlash::flashMode() const
{
GstFlashMode flashMode;
gst_photography_get_flash_mode(m_session->photography(), &flashMode);
QCameraExposure::FlashModes modes;
switch (flashMode) {
case GST_PHOTOGRAPHY_FLASH_MODE_AUTO: modes |= QCameraExposure::FlashAuto; break;
case GST_PHOTOGRAPHY_FLASH_MODE_OFF: modes |= QCameraExposure::FlashOff; break;
case GST_PHOTOGRAPHY_FLASH_MODE_ON: modes |= QCameraExposure::FlashOn; break;
case GST_PHOTOGRAPHY_FLASH_MODE_FILL_IN: modes |= QCameraExposure::FlashFill; break;
case GST_PHOTOGRAPHY_FLASH_MODE_RED_EYE: modes |= QCameraExposure::FlashRedEyeReduction; break;
default:
modes |= QCameraExposure::FlashAuto;
break;
}
return modes;
}
void CameraBinFlash::setFlashMode(QCameraExposure::FlashModes mode)
{
GstFlashMode flashMode;
gst_photography_get_flash_mode(m_session->photography(), &flashMode);
if (mode.testFlag(QCameraExposure::FlashAuto)) flashMode = GST_PHOTOGRAPHY_FLASH_MODE_AUTO;
else if (mode.testFlag(QCameraExposure::FlashOff)) flashMode = GST_PHOTOGRAPHY_FLASH_MODE_OFF;
else if (mode.testFlag(QCameraExposure::FlashOn)) flashMode = GST_PHOTOGRAPHY_FLASH_MODE_ON;
else if (mode.testFlag(QCameraExposure::FlashFill)) flashMode = GST_PHOTOGRAPHY_FLASH_MODE_FILL_IN;
else if (mode.testFlag(QCameraExposure::FlashRedEyeReduction)) flashMode = GST_PHOTOGRAPHY_FLASH_MODE_RED_EYE;
gst_photography_set_flash_mode(m_session->photography(), flashMode);
}
bool CameraBinFlash::isFlashModeSupported(QCameraExposure::FlashModes mode) const
{
return mode == QCameraExposure::FlashOff ||
mode == QCameraExposure::FlashOn ||
mode == QCameraExposure::FlashAuto ||
mode == QCameraExposure::FlashRedEyeReduction ||
mode == QCameraExposure::FlashFill;
}
bool CameraBinFlash::isFlashReady() const
{
return true;
}

View File

@@ -0,0 +1,73 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CAMERABINFLASHCONTROL_H
#define CAMERABINFLASHCONTROL_H
#include <qcamera.h>
#include <qcameraflashcontrol.h>
#include <gst/gst.h>
#include <glib.h>
class CameraBinSession;
QT_USE_NAMESPACE
class Q_MULTIMEDIA_EXPORT CameraBinFlash : public QCameraFlashControl
{
Q_OBJECT
public:
CameraBinFlash(CameraBinSession *session);
virtual ~CameraBinFlash();
QCameraExposure::FlashModes flashMode() const;
void setFlashMode(QCameraExposure::FlashModes mode);
bool isFlashModeSupported(QCameraExposure::FlashModes mode) const;
bool isFlashReady() const;
private:
CameraBinSession *m_session;
};
#endif // CAMERABINFLASHCONTROL_H

View File

@@ -0,0 +1,245 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "camerabinfocus.h"
#include "camerabinsession.h"
#include <gst/interfaces/photography.h>
#include <QDebug>
#include <QtCore/qmetaobject.h>
//#define CAMERABIN_DEBUG 1
#define ENUM_NAME(c,e,v) (c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(e)).valueToKey((v)))
CameraBinFocus::CameraBinFocus(CameraBinSession *session)
:QCameraFocusControl(session),
m_session(session),
m_focusMode(QCameraFocus::AutoFocus),
m_focusStatus(QCamera::Unlocked),
m_focusZoneStatus(QCameraFocusZone::Selected)
{
connect(m_session, SIGNAL(stateChanged(QCamera::State)),
this, SLOT(_q_handleCameraStateChange(QCamera::State)));
connect(m_session, SIGNAL(imageCaptured(int,QImage)),
this, SLOT(_q_handleCapturedImage()));
}
CameraBinFocus::~CameraBinFocus()
{
}
QCameraFocus::FocusMode CameraBinFocus::focusMode() const
{
return m_focusMode;
}
void CameraBinFocus::setFocusMode(QCameraFocus::FocusMode mode)
{
if (isFocusModeSupported(mode)) {
m_focusMode = mode;
}
}
bool CameraBinFocus::isFocusModeSupported(QCameraFocus::FocusMode mode) const
{
return mode & QCameraFocus::AutoFocus;
}
qreal CameraBinFocus::maximumOpticalZoom() const
{
return 1.0;
}
qreal CameraBinFocus::maximumDigitalZoom() const
{
return 10;
}
qreal CameraBinFocus::opticalZoom() const
{
return 1.0;
}
qreal CameraBinFocus::digitalZoom() const
{
#ifdef Q_WS_MAEMO_5
gint zoomFactor = 0;
g_object_get(GST_BIN(m_session->cameraBin()), "zoom", &zoomFactor, NULL);
return zoomFactor/100.0;
#else
gfloat zoomFactor = 1.0;
g_object_get(GST_BIN(m_session->cameraBin()), "zoom", &zoomFactor, NULL);
return zoomFactor;
#endif
}
void CameraBinFocus::zoomTo(qreal optical, qreal digital)
{
Q_UNUSED(optical);
digital = qBound(qreal(1.0), digital, qreal(10.0));
#ifdef Q_WS_MAEMO_5
g_object_set(GST_BIN(m_session->cameraBin()), "zoom", qRound(digital*100.0), NULL);
#else
g_object_set(GST_BIN(m_session->cameraBin()), "zoom", digital, NULL);
#endif
emit digitalZoomChanged(digital);
}
QCameraFocus::FocusPointMode CameraBinFocus::focusPointMode() const
{
return QCameraFocus::FocusPointAuto;
}
void CameraBinFocus::setFocusPointMode(QCameraFocus::FocusPointMode mode)
{
Q_UNUSED(mode);
}
bool CameraBinFocus::isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const
{
return mode == QCameraFocus::FocusPointAuto;
}
QPointF CameraBinFocus::customFocusPoint() const
{
return QPointF(0.5, 0.5);
}
void CameraBinFocus::setCustomFocusPoint(const QPointF &point)
{
Q_UNUSED(point);
}
QCameraFocusZoneList CameraBinFocus::focusZones() const
{
return QCameraFocusZoneList() << QCameraFocusZone(QRectF(0.35, 0.35, 0.3, 0.3), m_focusZoneStatus);
}
void CameraBinFocus::handleFocusMessage(GstMessage *gm)
{
//it's a sync message, so it's called from non main thread
if (gst_structure_has_name(gm->structure, GST_PHOTOGRAPHY_AUTOFOCUS_DONE)) {
gint status = GST_PHOTOGRAPHY_FOCUS_STATUS_NONE;
gst_structure_get_int (gm->structure, "status", &status);
QCamera::LockStatus focusStatus = m_focusStatus;
QCamera::LockChangeReason reason = QCamera::UserRequest;
switch (status) {
case GST_PHOTOGRAPHY_FOCUS_STATUS_FAIL:
focusStatus = QCamera::Unlocked;
reason = QCamera::LockFailed;
break;
case GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS:
focusStatus = QCamera::Locked;
break;
case GST_PHOTOGRAPHY_FOCUS_STATUS_NONE:
break;
case GST_PHOTOGRAPHY_FOCUS_STATUS_RUNNING:
focusStatus = QCamera::Searching;
break;
default:
break;
}
static int signalIndex = metaObject()->indexOfSlot(
"_q_setFocusStatus(QCamera::LockStatus,QCamera::LockChangeReason)");
metaObject()->method(signalIndex).invoke(this,
Qt::QueuedConnection,
Q_ARG(QCamera::LockStatus,focusStatus),
Q_ARG(QCamera::LockChangeReason,reason));
}
}
void CameraBinFocus::_q_setFocusStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason)
{
#ifdef CAMERABIN_DEBUG
qDebug() << Q_FUNC_INFO << "Current:"
<< ENUM_NAME(QCamera, "LockStatus", m_focusStatus)
<< "New:"
<< ENUM_NAME(QCamera, "LockStatus", status) << ENUM_NAME(QCamera, "LockChangeReason", reason);
#endif
if (m_focusStatus != status) {
m_focusStatus = status;
QCameraFocusZone::FocusZoneStatus zonesStatus =
m_focusStatus == QCamera::Locked ?
QCameraFocusZone::Focused : QCameraFocusZone::Selected;
if (m_focusZoneStatus != zonesStatus) {
m_focusZoneStatus = zonesStatus;
emit focusZonesChanged();
}
emit _q_focusStatusChanged(m_focusStatus, reason);
}
}
void CameraBinFocus::_q_handleCameraStateChange(QCamera::State state)
{
if (state != QCamera::ActiveState)
_q_setFocusStatus(QCamera::Unlocked, QCamera::LockLost);
}
void CameraBinFocus::_q_handleCapturedImage()
{
#ifdef Q_WS_MAEMO_5
//N900 lost focus after image capture
if (m_focusStatus != QCamera::Unlocked) {
m_focusStatus = QCamera::Unlocked;
emit _q_focusStatusChanged(QCamera::Unlocked, QCamera::LockLost);
}
#endif
}
void CameraBinFocus::_q_startFocusing()
{
_q_setFocusStatus(QCamera::Searching, QCamera::UserRequest);
gst_photography_set_autofocus(m_session->photography(), TRUE);
}
void CameraBinFocus::_q_stopFocusing()
{
gst_photography_set_autofocus(m_session->photography(), FALSE);
_q_setFocusStatus(QCamera::Unlocked, QCamera::UserRequest);
}

View File

@@ -0,0 +1,104 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CAMERABINFOCUSCONTROL_H
#define CAMERABINFOCUSCONTROL_H
#include <qcamera.h>
#include <qcamerafocuscontrol.h>
#include <gst/gst.h>
#include <glib.h>
class CameraBinSession;
QT_USE_NAMESPACE
class CameraBinFocus : public QCameraFocusControl
{
Q_OBJECT
public:
CameraBinFocus(CameraBinSession *session);
virtual ~CameraBinFocus();
QCameraFocus::FocusMode focusMode() const;
void setFocusMode(QCameraFocus::FocusMode mode);
bool isFocusModeSupported(QCameraFocus::FocusMode mode) const;
qreal maximumOpticalZoom() const;
qreal maximumDigitalZoom() const;
qreal opticalZoom() const;
qreal digitalZoom() const;
void zoomTo(qreal optical, qreal digital) ;
QCameraFocus::FocusPointMode focusPointMode() const;
void setFocusPointMode(QCameraFocus::FocusPointMode mode) ;
bool isFocusPointModeSupported(QCameraFocus::FocusPointMode) const;
QPointF customFocusPoint() const;
void setCustomFocusPoint(const QPointF &point);
QCameraFocusZoneList focusZones() const;
void handleFocusMessage(GstMessage*);
QCamera::LockStatus focusStatus() const { return m_focusStatus; }
Q_SIGNALS:
void _q_focusStatusChanged(QCamera::LockStatus status, QCamera::LockChangeReason reason);
public Q_SLOTS:
void _q_startFocusing();
void _q_stopFocusing();
private Q_SLOTS:
void _q_setFocusStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason);
void _q_handleCameraStateChange(QCamera::State state);
void _q_handleCapturedImage();
private:
CameraBinSession *m_session;
QCameraFocus::FocusMode m_focusMode;
QCamera::LockStatus m_focusStatus;
QCameraFocusZone::FocusZoneStatus m_focusZoneStatus;
};
#endif // CAMERABINFOCUSCONTROL_H

View File

@@ -0,0 +1,347 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "camerabinimagecapture.h"
#include "camerabincapturedestination.h"
#include "camerabincapturebufferformat.h"
#include "camerabinsession.h"
#include "qgstvideobuffer.h"
#include "qvideosurfacegstsink.h"
#include "qgstutils.h"
#include <QtCore/qdebug.h>
#include <QtCore/qbuffer.h>
#include <QtGui/qimagereader.h>
//#define DEBUG_CAPTURE
#ifdef Q_WS_MAEMO_5
#define IMAGE_DONE_SIGNAL "img-done"
#else
#define IMAGE_DONE_SIGNAL "image-done"
#endif
Q_DECLARE_METATYPE(QVideoFrame)
Q_DECLARE_METATYPE(QtMultimediaKit::MetaData)
namespace
{
class CameraRegisterMetaTypes
{
public:
CameraRegisterMetaTypes()
{
qRegisterMetaType<QVideoFrame>("QVideoFrame");
qRegisterMetaType<QtMultimediaKit::MetaData>("QtMultimediaKit::MetaData");
}
} _registerCameraMetaTypes;
}
CameraBinImageCapture::CameraBinImageCapture(CameraBinSession *session)
:QCameraImageCaptureControl(session)
, m_session(session)
, m_ready(false)
, m_requestId(0)
, m_jpegEncoderElement(0)
, m_metadataMuxerElement(0)
{
connect(m_session, SIGNAL(stateChanged(QCamera::State)), SLOT(updateState()));
connect(m_session, SIGNAL(imageExposed(int)), this, SIGNAL(imageExposed(int)));
connect(m_session, SIGNAL(imageCaptured(int,QImage)), this, SIGNAL(imageCaptured(int,QImage)));
connect(m_session, SIGNAL(busMessage(QGstreamerMessage)), SLOT(handleBusMessage(QGstreamerMessage)));
g_signal_connect(G_OBJECT(m_session->cameraBin()), IMAGE_DONE_SIGNAL, G_CALLBACK(handleImageSaved), this);
}
CameraBinImageCapture::~CameraBinImageCapture()
{
}
bool CameraBinImageCapture::isReadyForCapture() const
{
return m_ready;
}
int CameraBinImageCapture::capture(const QString &fileName)
{
m_requestId++;
if (!m_ready) {
emit error(m_requestId, QCameraImageCapture::NotReadyError, tr("Camera not ready"));
return m_requestId;
}
#ifdef DEBUG_CAPTURE
qDebug() << Q_FUNC_INFO << m_requestId << fileName;
#endif
m_session->captureImage(m_requestId, fileName);
return m_requestId;
}
void CameraBinImageCapture::cancelCapture()
{
}
void CameraBinImageCapture::updateState()
{
bool ready = m_session->state() == QCamera::ActiveState;
if (m_ready != ready) {
#ifdef DEBUG_CAPTURE
qDebug() << "readyForCaptureChanged" << ready;
#endif
emit readyForCaptureChanged(m_ready = ready);
}
}
gboolean CameraBinImageCapture::handleImageSaved(GstElement *camera,
const gchar *filename,
CameraBinImageCapture *self)
{
#ifdef DEBUG_CAPTURE
qDebug() << "Image saved" << filename;
#endif
Q_UNUSED(camera);
if (self->m_session->captureDestinationControl()->captureDestination() & QCameraImageCapture::CaptureToFile) {
QMetaObject::invokeMethod(self, "imageSaved",
Qt::QueuedConnection,
Q_ARG(int, self->m_requestId),
Q_ARG(QString, QString::fromUtf8(filename)));
} else {
#ifdef DEBUG_CAPTURE
qDebug() << Q_FUNC_INFO << "Dropped saving file" << filename;
#endif
//camerabin creates an empty file when captured buffer is dropped,
//let's remove it
QFileInfo info(QString::fromUtf8(filename));
if (info.isFile() &&
info.filePath().startsWith("/home") &&
info.size() == 0) {
QFile(info.absoluteFilePath()).remove();
}
}
return true;
}
gboolean CameraBinImageCapture::metadataEventProbe(GstPad *pad, GstEvent *event, CameraBinImageCapture *self)
{
if (GST_EVENT_TYPE(event) == GST_EVENT_TAG) {
GstTagList *gstTags;
gst_event_parse_tag(event, &gstTags);
QMap<QByteArray, QVariant> extendedTags = QGstUtils::gstTagListToMap(gstTags);
#ifdef DEBUG_CAPTURE
qDebug() << QString(gst_structure_to_string(gst_event_get_structure(event))).right(768);
qDebug() << "Capture event probe" << extendedTags;
#endif
QMap<QtMultimediaKit::MetaData, QVariant> tags;
tags[QtMultimediaKit::ISOSpeedRatings] = extendedTags.value("capturing-iso-speed");
tags[QtMultimediaKit::DigitalZoomRatio] = extendedTags.value("capturing-digital-zoom-ratio");
tags[QtMultimediaKit::ExposureTime] = extendedTags.value("capturing-shutter-speed");
tags[QtMultimediaKit::WhiteBalance] = extendedTags.value("capturing-white-balance");
tags[QtMultimediaKit::Flash] = extendedTags.value("capturing-flash-fired");
tags[QtMultimediaKit::FocalLengthIn35mmFilm] = extendedTags.value("capturing-focal-length");
tags[QtMultimediaKit::MeteringMode] = extendedTags.value("capturing-metering-mode");
tags[QtMultimediaKit::ExposureMode] = extendedTags.value("capturing-exposure-mode");
tags[QtMultimediaKit::FNumber] = extendedTags.value("capturing-focal-ratio");
tags[QtMultimediaKit::ExposureMode] = extendedTags.value("capturing-exposure-mode");
QMapIterator<QtMultimediaKit::MetaData, QVariant> i(tags);
while (i.hasNext()) {
i.next();
if (i.value().isValid()) {
QMetaObject::invokeMethod(self, "imageMetadataAvailable",
Qt::QueuedConnection,
Q_ARG(int, self->m_requestId),
Q_ARG(QtMultimediaKit::MetaData, i.key()),
Q_ARG(QVariant, i.value()));
}
}
}
return true;
}
gboolean CameraBinImageCapture::uncompressedBufferProbe(GstPad *pad, GstBuffer *buffer, CameraBinImageCapture *self)
{
Q_UNUSED(pad);
CameraBinSession *session = self->m_session;
#ifdef DEBUG_CAPTURE
qDebug() << "Uncompressed buffer probe" << gst_caps_to_string(GST_BUFFER_CAPS(buffer));
#endif
QCameraImageCapture::CaptureDestinations destination =
session->captureDestinationControl()->captureDestination();
QVideoFrame::PixelFormat format = session->captureBufferFormatControl()->bufferFormat();
if (destination & QCameraImageCapture::CaptureToBuffer) {
if (format != QVideoFrame::Format_Jpeg) {
GstCaps *caps = GST_BUFFER_CAPS(buffer);
int bytesPerLine = -1;
QVideoSurfaceFormat format = QVideoSurfaceGstSink::formatForCaps(caps, &bytesPerLine);
#ifdef DEBUG_CAPTURE
qDebug() << "imageAvailable(uncompressed):" << format;
#endif
QGstVideoBuffer *videoBuffer = new QGstVideoBuffer(buffer, bytesPerLine);
QVideoFrame frame(videoBuffer,
format.frameSize(),
format.pixelFormat());
QMetaObject::invokeMethod(self, "imageAvailable",
Qt::QueuedConnection,
Q_ARG(int, self->m_requestId),
Q_ARG(QVideoFrame, frame));
}
}
//keep the buffer if capture to file or jpeg buffer capture was reuqsted
bool keepBuffer = (destination & QCameraImageCapture::CaptureToFile) ||
((destination & QCameraImageCapture::CaptureToBuffer) &&
format == QVideoFrame::Format_Jpeg);
return keepBuffer;
}
gboolean CameraBinImageCapture::jpegBufferProbe(GstPad *pad, GstBuffer *buffer, CameraBinImageCapture *self)
{
Q_UNUSED(pad);
CameraBinSession *session = self->m_session;
#ifdef DEBUG_CAPTURE
qDebug() << "Jpeg buffer probe" << gst_caps_to_string(GST_BUFFER_CAPS(buffer));
#endif
QCameraImageCapture::CaptureDestinations destination =
session->captureDestinationControl()->captureDestination();
if ((destination & QCameraImageCapture::CaptureToBuffer) &&
session->captureBufferFormatControl()->bufferFormat() == QVideoFrame::Format_Jpeg) {
QGstVideoBuffer *videoBuffer = new QGstVideoBuffer(buffer,
-1); //bytesPerLine is not available for jpegs
QSize resolution = QGstUtils::capsCorrectedResolution(GST_BUFFER_CAPS(buffer));
//if resolution is not presented in caps, try to find it from encoded jpeg data:
if (resolution.isEmpty()) {
QBuffer data;
data.setData(reinterpret_cast<const char*>(GST_BUFFER_DATA(buffer)), GST_BUFFER_SIZE(buffer));
QImageReader reader(&data, "JPEG");
resolution = reader.size();
}
QVideoFrame frame(videoBuffer,
resolution,
QVideoFrame::Format_Jpeg);
QMetaObject::invokeMethod(self, "imageAvailable",
Qt::QueuedConnection,
Q_ARG(int, self->m_requestId),
Q_ARG(QVideoFrame, frame));
}
//drop the buffer if capture to file was disabled
return destination & QCameraImageCapture::CaptureToFile;
}
void CameraBinImageCapture::handleBusMessage(const QGstreamerMessage &message)
{
//Install metadata event and buffer probes
//The image capture pipiline is built dynamically,
//it's necessary to wait until jpeg encoder is added to pipeline
GstMessage *gm = message.rawMessage();
if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_STATE_CHANGED) {
GstState oldState;
GstState newState;
GstState pending;
gst_message_parse_state_changed(gm, &oldState, &newState, &pending);
if (newState == GST_STATE_READY) {
GstElement *element = GST_ELEMENT(GST_MESSAGE_SRC(gm));
if (!element)
return;
QString elementName = QString::fromLatin1(gst_element_get_name(element));
if (elementName.contains("jpegenc") && element != m_jpegEncoderElement) {
m_jpegEncoderElement = element;
GstPad *sinkpad = gst_element_get_static_pad(element, "sink");
//metadata event probe is installed before jpeg encoder
//to emit metadata available signal as soon as possible.
#ifdef DEBUG_CAPTURE
qDebug() << "install metadata probe";
#endif
gst_pad_add_event_probe(sinkpad,
G_CALLBACK(CameraBinImageCapture::metadataEventProbe),
this);
#ifdef DEBUG_CAPTURE
qDebug() << "install uncompressed buffer probe";
#endif
gst_pad_add_buffer_probe(sinkpad,
G_CALLBACK(CameraBinImageCapture::uncompressedBufferProbe),
this);
gst_object_unref(sinkpad);
} else if ((elementName.contains("jifmux") || elementName.startsWith("metadatamux"))
&& element != m_metadataMuxerElement) {
//Jpeg encoded buffer probe is added after jifmux/metadatamux
//element to ensure the resulting jpeg buffer contains capture metadata
m_metadataMuxerElement = element;
GstPad *srcpad = gst_element_get_static_pad(element, "src");
#ifdef DEBUG_CAPTURE
qDebug() << "install jpeg buffer probe";
#endif
gst_pad_add_buffer_probe(srcpad,
G_CALLBACK(CameraBinImageCapture::jpegBufferProbe),
this);
gst_object_unref(srcpad);
}
}
}
}

View File

@@ -0,0 +1,82 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CAMERABINIMAGECAPTURECONTROL_H
#define CAMERABINIMAGECAPTURECONTROL_H
#include <qcameraimagecapturecontrol.h>
#include "camerabinsession.h"
QT_USE_NAMESPACE
class CameraBinImageCapture : public QCameraImageCaptureControl
{
Q_OBJECT
public:
CameraBinImageCapture(CameraBinSession *session);
virtual ~CameraBinImageCapture();
QCameraImageCapture::DriveMode driveMode() const { return QCameraImageCapture::SingleImageCapture; }
void setDriveMode(QCameraImageCapture::DriveMode) {}
bool isReadyForCapture() const;
int capture(const QString &fileName);
void cancelCapture();
private slots:
void updateState();
void handleBusMessage(const QGstreamerMessage &message);
private:
static gboolean metadataEventProbe(GstPad *pad, GstEvent *event, CameraBinImageCapture *);
static gboolean uncompressedBufferProbe(GstPad *pad, GstBuffer *buffer, CameraBinImageCapture *);
static gboolean jpegBufferProbe(GstPad *pad, GstBuffer *buffer, CameraBinImageCapture *);
static gboolean handleImageSaved(GstElement *camera, const gchar *filename, CameraBinImageCapture *);
CameraBinSession *m_session;
bool m_ready;
int m_requestId;
GstElement *m_jpegEncoderElement;
GstElement *m_metadataMuxerElement;
};
#endif // CAMERABINCAPTURECORNTROL_H

View File

@@ -0,0 +1,87 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "camerabinimageencoder.h"
#include "camerabinsession.h"
#include <QtCore/qdebug.h>
CameraBinImageEncoder::CameraBinImageEncoder(CameraBinSession *session)
:QImageEncoderControl(session), m_session(session)
{
}
CameraBinImageEncoder::~CameraBinImageEncoder()
{
}
QList<QSize> CameraBinImageEncoder::supportedResolutions(const QImageEncoderSettings &, bool *continuous) const
{
qDebug() << "CameraBinImageEncoder::supportedResolutions()";
if (continuous)
*continuous = false;
return m_session->supportedResolutions(qMakePair<int,int>(0,0), continuous, QCamera::CaptureStillImage);
}
QStringList CameraBinImageEncoder::supportedImageCodecs() const
{
return QStringList() << "jpeg";
}
QString CameraBinImageEncoder::imageCodecDescription(const QString &codecName) const
{
if (codecName == "jpeg")
return tr("JPEG image");
return QString();
}
QImageEncoderSettings CameraBinImageEncoder::imageSettings() const
{
return m_settings;
}
void CameraBinImageEncoder::setImageSettings(const QImageEncoderSettings &settings)
{
m_settings = settings;
emit settingsChanged();
}

View File

@@ -0,0 +1,86 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CAMERABINIMAGEENCODE_H
#define CAMERABINIMAGEENCODE_H
class CameraBinSession;
#include <qimageencodercontrol.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qmap.h>
#include <gst/gst.h>
QT_USE_NAMESPACE
class CameraBinImageEncoder : public QImageEncoderControl
{
Q_OBJECT
public:
CameraBinImageEncoder(CameraBinSession *session);
virtual ~CameraBinImageEncoder();
QList<QSize> supportedResolutions(const QImageEncoderSettings &settings = QImageEncoderSettings(),
bool *continuous = 0) const;
QStringList supportedImageCodecs() const;
QString imageCodecDescription(const QString &formatName) const;
QImageEncoderSettings imageSettings() const;
void setImageSettings(const QImageEncoderSettings &settings);
Q_SIGNALS:
void settingsChanged();
private:
QImageEncoderSettings m_settings;
CameraBinSession *m_session;
// Added
QStringList m_codecs;
QMap<QString,QByteArray> m_elementNames;
QMap<QString,QString> m_codecDescriptions;
QMap<QString,QStringList> m_codecOptions;
};
#endif

View File

@@ -0,0 +1,171 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "camerabinimageprocessing.h"
#include "camerabinsession.h"
CameraBinImageProcessing::CameraBinImageProcessing(CameraBinSession *session)
:QCameraImageProcessingControl(session),
m_session(session)
{
m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_AUTO] = QCameraImageProcessing::WhiteBalanceAuto;
m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_DAYLIGHT] = QCameraImageProcessing::WhiteBalanceSunlight;
m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_CLOUDY] = QCameraImageProcessing::WhiteBalanceCloudy;
m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_SUNSET] = QCameraImageProcessing::WhiteBalanceSunset;
m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_TUNGSTEN] = QCameraImageProcessing::WhiteBalanceTungsten;
m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_FLUORESCENT] = QCameraImageProcessing::WhiteBalanceFluorescent;
updateColorBalanceValues();
}
CameraBinImageProcessing::~CameraBinImageProcessing()
{
}
void CameraBinImageProcessing::updateColorBalanceValues()
{
if (!GST_IS_COLOR_BALANCE(m_session->cameraBin())) {
// Camerabin doesn't implement gstcolorbalance interface
return;
}
GstColorBalance *balance = GST_COLOR_BALANCE(m_session->cameraBin());
const GList *controls = gst_color_balance_list_channels(balance);
const GList *item;
GstColorBalanceChannel *channel;
gint cur_value;
for (item = controls; item; item = g_list_next (item)) {
channel = (GstColorBalanceChannel *)item->data;
cur_value = gst_color_balance_get_value (balance, channel);
if (!g_ascii_strcasecmp (channel->label, "brightness")) {
m_values[QCameraImageProcessingControl::Brightness] = cur_value;
} else if (!g_ascii_strcasecmp (channel->label, "contrast")) {
m_values[QCameraImageProcessingControl::Contrast] = cur_value;
} else if (!g_ascii_strcasecmp (channel->label, "saturation")) {
m_values[QCameraImageProcessingControl::Saturation] = cur_value;
}
}
}
bool CameraBinImageProcessing::setColorBalanceValue(const QString& channel, int value)
{
if (!GST_IS_COLOR_BALANCE(m_session->cameraBin())) {
// Camerabin doesn't implement gstcolorbalance interface
return false;
}
GstColorBalance *balance = GST_COLOR_BALANCE(m_session->cameraBin());
const GList *controls = gst_color_balance_list_channels(balance);
const GList *item;
GstColorBalanceChannel *colorBalanceChannel;
for (item = controls; item; item = g_list_next (item)) {
colorBalanceChannel = (GstColorBalanceChannel *)item->data;
if (!g_ascii_strcasecmp (colorBalanceChannel->label, channel.toAscii())) {
gst_color_balance_set_value (balance, colorBalanceChannel, value);
return true;
}
}
return false;
}
QCameraImageProcessing::WhiteBalanceMode CameraBinImageProcessing::whiteBalanceMode() const
{
GstWhiteBalanceMode wbMode;
gst_photography_get_white_balance_mode(m_session->photography(), &wbMode);
return m_mappedWbValues[wbMode];
}
void CameraBinImageProcessing::setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceMode mode)
{
if (isWhiteBalanceModeSupported(mode))
gst_photography_set_white_balance_mode(m_session->photography(), m_mappedWbValues.key(mode));
}
bool CameraBinImageProcessing::isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceMode mode) const
{
return m_mappedWbValues.values().contains(mode);
}
bool CameraBinImageProcessing::isProcessingParameterSupported(QCameraImageProcessingControl::ProcessingParameter parameter) const
{
return parameter == QCameraImageProcessingControl::Contrast
|| parameter == QCameraImageProcessingControl::Brightness
|| parameter == QCameraImageProcessingControl::Saturation;
}
QVariant CameraBinImageProcessing::processingParameter(
QCameraImageProcessingControl::ProcessingParameter parameter) const
{
if (m_values.contains(parameter))
return m_values.value(parameter);
else
return QVariant();
}
void CameraBinImageProcessing::setProcessingParameter(
QCameraImageProcessingControl::ProcessingParameter parameter,
QVariant value)
{
switch (parameter) {
case Contrast:
setColorBalanceValue("contrast", value.toInt());
break;
case Brightness:
setColorBalanceValue("brightness", value.toInt());
break;
case Saturation:
setColorBalanceValue("saturation", value.toInt());
break;
default:
break;
}
updateColorBalanceValues();
}

View File

@@ -0,0 +1,84 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CAMERABINIMAGEPROCESSINGCONTROL_H
#define CAMERABINIMAGEPROCESSINGCONTROL_H
#include <qcamera.h>
#include <qcameraimageprocessingcontrol.h>
#include <gst/gst.h>
#include <glib.h>
#include <gst/interfaces/photography.h>
#include <gst/interfaces/colorbalance.h>
class CameraBinSession;
QT_USE_NAMESPACE
class CameraBinImageProcessing : public QCameraImageProcessingControl
{
Q_OBJECT
public:
CameraBinImageProcessing(CameraBinSession *session);
virtual ~CameraBinImageProcessing();
QCameraImageProcessing::WhiteBalanceMode whiteBalanceMode() const;
void setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceMode mode);
bool isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceMode mode) const;
bool isProcessingParameterSupported(ProcessingParameter) const;
QVariant processingParameter(ProcessingParameter parameter) const;
void setProcessingParameter(ProcessingParameter parameter, QVariant value);
private:
bool setColorBalanceValue(const QString& channel, int value);
void updateColorBalanceValues();
private:
CameraBinSession *m_session;
QMap<QCameraImageProcessingControl::ProcessingParameter, int> m_values;
QMap<GstWhiteBalanceMode, QCameraImageProcessing::WhiteBalanceMode> m_mappedWbValues;
};
#endif // CAMERABINIMAGEPROCESSINGCONTROL_H

View File

@@ -0,0 +1,88 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "camerabinlocks.h"
#include "camerabinsession.h"
#include "camerabinfocus.h"
#include <gst/interfaces/photography.h>
#include <QDebug>
CameraBinLocks::CameraBinLocks(CameraBinSession *session)
:QCameraLocksControl(session),
m_session(session),
m_focus(m_session->cameraFocusControl())
{
connect(m_focus, SIGNAL(_q_focusStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)),
this, SLOT(updateFocusStatus(QCamera::LockStatus, QCamera::LockChangeReason)));
}
CameraBinLocks::~CameraBinLocks()
{
}
QCamera::LockTypes CameraBinLocks::supportedLocks() const
{
return QCamera::LockFocus;
}
QCamera::LockStatus CameraBinLocks::lockStatus(QCamera::LockType lock) const
{
return lock == QCamera::LockFocus ? m_focus->focusStatus() : QCamera::Unlocked;
}
void CameraBinLocks::searchAndLock(QCamera::LockTypes locks)
{
if (locks & QCamera::LockFocus)
m_focus->_q_startFocusing();
}
void CameraBinLocks::unlock(QCamera::LockTypes locks)
{
if (locks & QCamera::LockFocus)
m_focus->_q_stopFocusing();
}
void CameraBinLocks::updateFocusStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason)
{
emit lockStatusChanged(QCamera::LockFocus, status, reason);
}

View File

@@ -0,0 +1,79 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CAMERABINLOCKSCONTROL_H
#define CAMERABINLOCKSCONTROL_H
#include <qcamera.h>
#include <qcameralockscontrol.h>
#include <gst/gst.h>
#include <glib.h>
class CameraBinSession;
class CameraBinFocus;
QT_USE_NAMESPACE
class CameraBinLocks : public QCameraLocksControl
{
Q_OBJECT
public:
CameraBinLocks(CameraBinSession *session);
virtual ~CameraBinLocks();
QCamera::LockTypes supportedLocks() const;
QCamera::LockStatus lockStatus(QCamera::LockType lock) const;
void searchAndLock(QCamera::LockTypes locks);
void unlock(QCamera::LockTypes locks);
private slots:
void updateFocusStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason);
private:
CameraBinSession *m_session;
CameraBinFocus *m_focus;
};
#endif

View File

@@ -0,0 +1,198 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "camerabinmetadata.h"
#include <gst/gst.h>
#include <gst/gstversion.h>
struct QGstreamerMetaDataKeyLookup
{
QtMultimediaKit::MetaData key;
const char *token;
};
static const QGstreamerMetaDataKeyLookup qt_gstreamerMetaDataKeys[] =
{
{ QtMultimediaKit::Title, GST_TAG_TITLE },
//{ QtMultimediaKit::SubTitle, 0 },
//{ QtMultimediaKit::Author, 0 },
{ QtMultimediaKit::Comment, GST_TAG_COMMENT },
{ QtMultimediaKit::Description, GST_TAG_DESCRIPTION },
//{ QtMultimediaKit::Category, 0 },
{ QtMultimediaKit::Genre, GST_TAG_GENRE },
//{ QtMultimediaKit::Year, 0 },
//{ QtMultimediaKit::UserRating, 0 },
{ QtMultimediaKit::Language, GST_TAG_LANGUAGE_CODE },
{ QtMultimediaKit::Publisher, GST_TAG_ORGANIZATION },
{ QtMultimediaKit::Copyright, GST_TAG_COPYRIGHT },
//{ QtMultimediaKit::ParentalRating, 0 },
//{ QtMultimediaKit::RatingOrganisation, 0 },
// Media
//{ QtMultimediaKit::Size, 0 },
//{ QtMultimediaKit::MediaType, 0 },
{ QtMultimediaKit::Duration, GST_TAG_DURATION },
// Audio
{ QtMultimediaKit::AudioBitRate, GST_TAG_BITRATE },
{ QtMultimediaKit::AudioCodec, GST_TAG_AUDIO_CODEC },
//{ QtMultimediaKit::ChannelCount, 0 },
//{ QtMultimediaKit::SampleRate, 0 },
// Music
{ QtMultimediaKit::AlbumTitle, GST_TAG_ALBUM },
{ QtMultimediaKit::AlbumArtist, GST_TAG_ARTIST},
{ QtMultimediaKit::ContributingArtist, GST_TAG_PERFORMER },
#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19)
{ QtMultimediaKit::Composer, GST_TAG_COMPOSER },
#endif
//{ QtMultimediaKit::Conductor, 0 },
//{ QtMultimediaKit::Lyrics, 0 },
//{ QtMultimediaKit::Mood, 0 },
{ QtMultimediaKit::TrackNumber, GST_TAG_TRACK_NUMBER },
//{ QtMultimediaKit::CoverArtUrlSmall, 0 },
//{ QtMultimediaKit::CoverArtUrlLarge, 0 },
// Image/Video
//{ QtMultimediaKit::Resolution, 0 },
//{ QtMultimediaKit::PixelAspectRatio, 0 },
// Video
//{ QtMultimediaKit::VideoFrameRate, 0 },
//{ QtMultimediaKit::VideoBitRate, 0 },
{ QtMultimediaKit::VideoCodec, GST_TAG_VIDEO_CODEC },
//{ QtMultimediaKit::PosterUrl, 0 },
// Movie
//{ QtMultimediaKit::ChapterNumber, 0 },
//{ QtMultimediaKit::Director, 0 },
{ QtMultimediaKit::LeadPerformer, GST_TAG_PERFORMER },
//{ QtMultimediaKit::Writer, 0 },
// Photos
//{ QtMultimediaKit::CameraManufacturer, 0 },
//{ QtMultimediaKit::CameraModel, 0 },
//{ QtMultimediaKit::Event, 0 },
//{ QtMultimediaKit::Subject, 0 }
};
CameraBinMetaData::CameraBinMetaData(QObject *parent)
:QMetaDataWriterControl(parent)
{
}
QVariant CameraBinMetaData::metaData(QtMultimediaKit::MetaData key) const
{
static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup);
for (int i = 0; i < count; ++i) {
if (qt_gstreamerMetaDataKeys[i].key == key) {
const char *name = qt_gstreamerMetaDataKeys[i].token;
return m_values.value(QByteArray::fromRawData(name, qstrlen(name)));
}
}
return QVariant();
}
void CameraBinMetaData::setMetaData(QtMultimediaKit::MetaData key, const QVariant &value)
{
static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup);
for (int i = 0; i < count; ++i) {
if (qt_gstreamerMetaDataKeys[i].key == key) {
const char *name = qt_gstreamerMetaDataKeys[i].token;
m_values.insert(QByteArray::fromRawData(name, qstrlen(name)), value);
emit QMetaDataWriterControl::metaDataChanged();
emit metaDataChanged(m_values);
return;
}
}
}
QList<QtMultimediaKit::MetaData> CameraBinMetaData::availableMetaData() const
{
static QMap<QByteArray, QtMultimediaKit::MetaData> keysMap;
if (keysMap.isEmpty()) {
const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup);
for (int i = 0; i < count; ++i) {
keysMap[QByteArray(qt_gstreamerMetaDataKeys[i].token)] = qt_gstreamerMetaDataKeys[i].key;
}
}
QList<QtMultimediaKit::MetaData> res;
foreach (const QByteArray &key, m_values.keys()) {
QtMultimediaKit::MetaData tag = keysMap.value(key, QtMultimediaKit::MetaData(-1));
if (tag != -1)
res.append(tag);
}
return res;
}
QVariant CameraBinMetaData::extendedMetaData(QString const &name) const
{
return m_values.value(name.toLatin1());
}
void CameraBinMetaData::setExtendedMetaData(QString const &name, QVariant const &value)
{
m_values.insert(name.toLatin1(), value);
emit QMetaDataWriterControl::metaDataChanged();
emit metaDataChanged(m_values);
}
QStringList CameraBinMetaData::availableExtendedMetaData() const
{
QStringList res;
foreach (const QByteArray &key, m_values.keys())
res.append(QString(key));
return res;
}

View File

@@ -0,0 +1,75 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CAMERABINCAPTUREMETADATACONTROL_H
#define CAMERABINCAPTUREMETADATACONTROL_H
#include <qmetadatawritercontrol.h>
QT_USE_NAMESPACE
class CameraBinMetaData : public QMetaDataWriterControl
{
Q_OBJECT
public:
CameraBinMetaData(QObject *parent);
virtual ~CameraBinMetaData() {}
bool isMetaDataAvailable() const { return true; }
bool isWritable() const { return true; }
QVariant metaData(QtMultimediaKit::MetaData key) const;
void setMetaData(QtMultimediaKit::MetaData key, const QVariant &value);
QList<QtMultimediaKit::MetaData> availableMetaData() const;
QVariant extendedMetaData(QString const &name) const;
void setExtendedMetaData(QString const &name, QVariant const &value);
QStringList availableExtendedMetaData() const;
Q_SIGNALS:
void metaDataChanged(const QMap<QByteArray, QVariant>&);
private:
QMap<QByteArray, QVariant> m_values;
};
#endif // CAMERABINCAPTUREMETADATACONTROL_H

View File

@@ -0,0 +1,225 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "camerabinrecorder.h"
#include "camerabinaudioencoder.h"
#include "camerabinvideoencoder.h"
#include "camerabincontainer.h"
#include <QtCore/QDebug>
CameraBinRecorder::CameraBinRecorder(CameraBinSession *session)
:QMediaRecorderControl(session),
m_session(session),
m_state(QMediaRecorder::StoppedState)
{
connect(m_session, SIGNAL(stateChanged(QCamera::State)), SLOT(updateState()));
connect(m_session, SIGNAL(durationChanged(qint64)), SIGNAL(durationChanged(qint64)));
connect(m_session, SIGNAL(mutedChanged(bool)), this, SIGNAL(mutedChanged(bool)));
}
CameraBinRecorder::~CameraBinRecorder()
{
}
QUrl CameraBinRecorder::outputLocation() const
{
return m_session->outputLocation();
}
bool CameraBinRecorder::setOutputLocation(const QUrl &sink)
{
m_session->setOutputLocation(sink);
return true;
}
QMediaRecorder::State CameraBinRecorder::state() const
{
return m_state;
}
void CameraBinRecorder::updateState()
{
if (m_session->state() != QCamera::ActiveState &&
m_state != QMediaRecorder::StoppedState) {
m_session->stopVideoRecording();
emit stateChanged(m_state = QMediaRecorder::StoppedState);
}
}
qint64 CameraBinRecorder::duration() const
{
return m_session->duration();
}
void CameraBinRecorder::record()
{
if (m_session->state() == QCamera::ActiveState) {
if (m_state == QMediaRecorder::PausedState)
m_session->resumeVideoRecording();
else
m_session->recordVideo();
emit stateChanged(m_state = QMediaRecorder::RecordingState);
} else
emit error(QMediaRecorder::ResourceError, tr("Service has not been started"));
}
void CameraBinRecorder::pause()
{
if (m_session->state() == QCamera::ActiveState) {
m_session->pauseVideoRecording();
emit stateChanged(m_state = QMediaRecorder::PausedState);
} else
emit error(QMediaRecorder::ResourceError, tr("Service has not been started"));
}
void CameraBinRecorder::stop()
{
if (m_session->state() == QCamera::ActiveState) {
m_session->stopVideoRecording();
emit stateChanged(m_state = QMediaRecorder::StoppedState);
}
}
bool CameraBinRecorder::findCodecs()
{
//Check the codecs are compatible with container,
//and choose the compatible codecs/container if omitted
CameraBinAudioEncoder *audioEncodeControl = m_session->audioEncodeControl();
CameraBinVideoEncoder *videoEncodeControl = m_session->videoEncodeControl();
CameraBinContainer *mediaContainerControl = m_session->mediaContainerControl();
audioEncodeControl->resetActualSettings();
videoEncodeControl->resetActualSettings();
mediaContainerControl->resetActualContainer();
QStringList containerCandidates;
if (mediaContainerControl->containerMimeType().isEmpty())
containerCandidates = mediaContainerControl->supportedContainers();
else
containerCandidates << mediaContainerControl->containerMimeType();
QStringList audioCandidates;
QAudioEncoderSettings audioSettings = audioEncodeControl->audioSettings();
if (audioSettings.codec().isEmpty())
audioCandidates = audioEncodeControl->supportedAudioCodecs();
else
audioCandidates << audioSettings.codec();
QStringList videoCandidates;
QVideoEncoderSettings videoSettings = videoEncodeControl->videoSettings();
if (videoSettings.codec().isEmpty())
videoCandidates = videoEncodeControl->supportedVideoCodecs();
else
videoCandidates << videoSettings.codec();
QString container;
QString audioCodec;
QString videoCodec;
foreach (const QString &containerCandidate, containerCandidates) {
QSet<QString> supportedTypes = mediaContainerControl->supportedStreamTypes(containerCandidate);
audioCodec.clear();
videoCodec.clear();
bool found = false;
foreach (const QString &audioCandidate, audioCandidates) {
QSet<QString> audioTypes = audioEncodeControl->supportedStreamTypes(audioCandidate);
if (!audioTypes.intersect(supportedTypes).isEmpty()) {
found = true;
audioCodec = audioCandidate;
break;
}
}
if (!found)
continue;
found = false;
foreach (const QString &videoCandidate, videoCandidates) {
QSet<QString> videoTypes = videoEncodeControl->supportedStreamTypes(videoCandidate);
if (!videoTypes.intersect(supportedTypes).isEmpty()) {
found = true;
videoCodec = videoCandidate;
break;
}
}
if (!found)
continue;
container = containerCandidate;
break;
}
if (container.isEmpty()) {
qWarning() << "Camera error: Not compatible codecs and container format.";
emit error(QMediaRecorder::FormatError, tr("Not compatible codecs and container format."));
return false;
} else {
mediaContainerControl->setActualContainer(container);
QAudioEncoderSettings audioSettings = audioEncodeControl->audioSettings();
audioSettings.setCodec(audioCodec);
audioEncodeControl->setActualAudioSettings(audioSettings);
QVideoEncoderSettings videoSettings = videoEncodeControl->videoSettings();
videoSettings.setCodec(videoCodec);
videoEncodeControl->setActualVideoSettings(videoSettings);
}
return true;
}
void CameraBinRecorder::applySettings()
{
findCodecs();
}
bool CameraBinRecorder::isMuted() const
{
return m_session->isMuted();
}
void CameraBinRecorder::setMuted(bool muted)
{
m_session->setMuted(muted);
}

View File

@@ -0,0 +1,85 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CAMERABINRECORDERCONTROL_H
#define CAMERABINRECORDERCONTROL_H
#include <qmediarecordercontrol.h>
#include "camerabinsession.h"
QT_USE_NAMESPACE
class CameraBinRecorder : public QMediaRecorderControl
{
Q_OBJECT
public:
CameraBinRecorder(CameraBinSession *session);
virtual ~CameraBinRecorder();
QUrl outputLocation() const;
bool setOutputLocation(const QUrl &sink);
QMediaRecorder::State state() const;
qint64 duration() const;
bool isMuted() const;
bool findCodecs();
void applySettings();
public slots:
void record();
void pause();
void stop();
void setMuted(bool);
private slots:
void updateState();
private:
CameraBinSession *m_session;
QMediaRecorder::State m_state;
};
#endif // CAMERABINCAPTURECORNTROL_H

View File

@@ -0,0 +1,188 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "camerabinresourcepolicy.h"
#ifdef Q_WS_MAEMO_6
#define HAVE_RESOURCE_POLICY
#endif
//#define DEBUG_RESOURCE_POLICY
#include <QtCore/qdebug.h>
#include <QtCore/qset.h>
#ifdef HAVE_RESOURCE_POLICY
#include <policy/resource.h>
#include <policy/resources.h>
#include <policy/resource-set.h>
#endif
CamerabinResourcePolicy::CamerabinResourcePolicy(QObject *parent) :
QObject(parent),
m_resourceSet(NoResources),
m_releasingResources(false)
{
#ifdef HAVE_RESOURCE_POLICY
//loaded resource set is also kept requested for image and video capture sets
m_resource = new ResourcePolicy::ResourceSet("camera");
m_resource->setAlwaysReply();
m_resource->initAndConnect();
connect(m_resource, SIGNAL(resourcesGranted(const QList<ResourcePolicy::ResourceType>)),
SIGNAL(resourcesGranted()));
connect(m_resource, SIGNAL(resourcesDenied()), SIGNAL(resourcesDenied()));
connect(m_resource, SIGNAL(lostResources()), SIGNAL(resourcesLost()));
connect(m_resource, SIGNAL(resourcesReleased()), SLOT(handleResourcesReleased()));
#endif
}
CamerabinResourcePolicy::~CamerabinResourcePolicy()
{
#ifdef HAVE_RESOURCE_POLICY
//ensure the resources are released
if (m_resourceSet != NoResources)
setResourceSet(NoResources);
//don't delete the resource set until resources are released
if (m_releasingResources) {
m_resource->connect(m_resource, SIGNAL(resourcesReleased()),
SLOT(deleteLater()));
} else {
delete m_resource;
m_resource = 0;
}
#endif
}
CamerabinResourcePolicy::ResourceSet CamerabinResourcePolicy::resourceSet() const
{
return m_resourceSet;
}
void CamerabinResourcePolicy::setResourceSet(CamerabinResourcePolicy::ResourceSet set)
{
CamerabinResourcePolicy::ResourceSet oldSet = m_resourceSet;
m_resourceSet = set;
#ifdef DEBUG_RESOURCE_POLICY
qDebug() << Q_FUNC_INFO << set;
#endif
#ifdef HAVE_RESOURCE_POLICY
QSet<ResourcePolicy::ResourceType> requestedTypes;
switch (set) {
case NoResources:
break;
case LoadedResources:
requestedTypes << ResourcePolicy::LensCoverType //to detect lens cover is opened/closed
<< ResourcePolicy::VideoRecorderType //to open camera device
<< ResourcePolicy::SnapButtonType; //to detect capture button events
break;
case ImageCaptureResources:
requestedTypes << ResourcePolicy::LensCoverType
<< ResourcePolicy::VideoPlaybackType
<< ResourcePolicy::VideoRecorderType
<< ResourcePolicy::AudioPlaybackType
<< ResourcePolicy::ScaleButtonType
<< ResourcePolicy::LedsType
<< ResourcePolicy::SnapButtonType;
break;
case VideoCaptureResources:
requestedTypes << ResourcePolicy::LensCoverType
<< ResourcePolicy::VideoPlaybackType
<< ResourcePolicy::VideoRecorderType
<< ResourcePolicy::AudioPlaybackType
<< ResourcePolicy::AudioRecorderType
<< ResourcePolicy::ScaleButtonType
<< ResourcePolicy::LedsType
<< ResourcePolicy::SnapButtonType;
break;
}
QSet<ResourcePolicy::ResourceType> currentTypes;
foreach (ResourcePolicy::Resource *resource, m_resource->resources())
currentTypes << resource->type();
foreach (ResourcePolicy::ResourceType resourceType, currentTypes - requestedTypes)
m_resource->deleteResource(resourceType);
foreach (ResourcePolicy::ResourceType resourceType, requestedTypes - currentTypes) {
if (resourceType == ResourcePolicy::LensCoverType) {
ResourcePolicy::LensCoverResource *lensCoverResource = new ResourcePolicy::LensCoverResource;
lensCoverResource->setOptional(true);
m_resource->addResourceObject(lensCoverResource);
} else {
m_resource->addResource(resourceType);
}
}
m_resource->update();
if (set != NoResources) {
m_resource->acquire();
} else {
if (oldSet != NoResources) {
m_releasingResources = true;
m_resource->release();
}
}
#endif
}
bool CamerabinResourcePolicy::isResourcesGranted() const
{
#ifdef HAVE_RESOURCE_POLICY
foreach (ResourcePolicy::Resource *resource, m_resource->resources())
if (!resource->isOptional() && !resource->isGranted())
return false;
#endif
return true;
}
void CamerabinResourcePolicy::handleResourcesReleased()
{
#ifdef HAVE_RESOURCE_POLICY
#ifdef DEBUG_RESOURCE_POLICY
qDebug() << Q_FUNC_INFO;
#endif
m_releasingResources = false;
#endif
}

View File

@@ -0,0 +1,84 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CAMERARESOURCEPOLICY_H
#define CAMERARESOURCEPOLICY_H
#include <QtCore/qobject.h>
namespace ResourcePolicy {
class ResourceSet;
};
class CamerabinResourcePolicy : public QObject
{
Q_OBJECT
public:
enum ResourceSet {
NoResources,
LoadedResources,
ImageCaptureResources,
VideoCaptureResources
};
CamerabinResourcePolicy(QObject *parent);
~CamerabinResourcePolicy();
ResourceSet resourceSet() const;
void setResourceSet(ResourceSet set);
bool isResourcesGranted() const;
Q_SIGNALS:
void resourcesDenied();
void resourcesGranted();
void resourcesLost();
private Q_SLOTS:
void handleResourcesReleased();
private:
ResourceSet m_resourceSet;
ResourcePolicy::ResourceSet *m_resource;
bool m_releasingResources;
};
#endif

View File

@@ -0,0 +1,261 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "camerabinservice.h"
#include "camerabinsession.h"
#include "camerabinrecorder.h"
#include "camerabincontainer.h"
#include "camerabinaudioencoder.h"
#include "camerabinvideoencoder.h"
#include "camerabinimageencoder.h"
#include "qgstreamerbushelper.h"
#include "camerabincontrol.h"
#include "camerabinlocks.h"
#include "camerabinmetadata.h"
#include "camerabinexposure.h"
#include "camerabinflash.h"
#include "camerabinfocus.h"
#include "camerabinimagecapture.h"
#include "camerabinimageprocessing.h"
#include "camerabincapturebufferformat.h"
#include "camerabincapturedestination.h"
#include "qgstreameraudioinputendpointselector.h"
#include "qgstreamervideoinputdevicecontrol.h"
#include "qgstreamervideooverlay.h"
#include "qgstreamervideowindow.h"
#include "qgstreamervideorenderer.h"
#if defined(Q_WS_MAEMO_6) && defined(__arm__)
#include "qgstreamergltexturerenderer.h"
#endif
#include "qgstreamervideowidget.h"
#include <qmediaserviceprovider.h>
#include <QtCore/qdebug.h>
#include <QtCore/qprocess.h>
#if defined(Q_WS_MAEMO_5)
#include "camerabuttonlistener_maemo.h"
#endif
#if defined(Q_WS_MAEMO_6)
#include "camerabuttonlistener_meego.h"
#endif
CameraBinService::CameraBinService(const QString &service, QObject *parent):
QMediaService(parent)
{
m_captureSession = 0;
m_cameraControl = 0;
m_metaDataControl = 0;
m_audioInputEndpointSelector = 0;
m_videoInputDevice = 0;
m_videoOutput = 0;
m_videoRenderer = 0;
m_videoWindow = 0;
m_videoWidgetControl = 0;
m_imageCaptureControl = 0;
if (service == Q_MEDIASERVICE_CAMERA) {
m_captureSession = new CameraBinSession(this);
m_cameraControl = new CameraBinControl(m_captureSession);
m_videoInputDevice = new QGstreamerVideoInputDeviceControl(m_captureSession);
m_imageCaptureControl = new CameraBinImageCapture(m_captureSession);
connect(m_videoInputDevice, SIGNAL(selectedDeviceChanged(QString)),
m_captureSession, SLOT(setDevice(QString)));
if (m_videoInputDevice->deviceCount())
m_captureSession->setDevice(m_videoInputDevice->deviceName(m_videoInputDevice->selectedDevice()));
#if defined(Q_WS_MAEMO_6) && defined(__arm__)
m_videoRenderer = new QGstreamerGLTextureRenderer(this);
#else
m_videoRenderer = new QGstreamerVideoRenderer(this);
#endif
#ifdef Q_WS_MAEMO_6
m_videoWindow = new QGstreamerVideoWindow(this, "omapxvsink");
//m_videoWindow = new QGstreamerVideoWindow(this);
#else
m_videoWindow = new QGstreamerVideoOverlay(this);
#endif
m_videoWidgetControl = new QGstreamerVideoWidgetControl(this);
}
if (!m_captureSession) {
qWarning() << Q_FUNC_INFO << "Service type is not supported:" << service;
return;
}
m_audioInputEndpointSelector = new QGstreamerAudioInputEndpointSelector(this);
connect(m_audioInputEndpointSelector, SIGNAL(activeEndpointChanged(QString)), m_captureSession, SLOT(setCaptureDevice(QString)));
if (m_captureSession && m_audioInputEndpointSelector->availableEndpoints().size() > 0)
m_captureSession->setCaptureDevice(m_audioInputEndpointSelector->defaultEndpoint());
m_metaDataControl = new CameraBinMetaData(this);
connect(m_metaDataControl, SIGNAL(metaDataChanged(QMap<QByteArray,QVariant>)),
m_captureSession, SLOT(setMetaData(QMap<QByteArray,QVariant>)));
#if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
new CameraButtonListener(this);
#endif
#if defined(Q_WS_MAEMO_5)
//disable the system camera application
QProcess::execute("/usr/sbin/dsmetool -k /usr/bin/camera-ui");
#endif
}
CameraBinService::~CameraBinService()
{
#if defined(Q_WS_MAEMO_5)
//restore the system camera application
QProcess::execute("/usr/sbin/dsmetool -U user -o /usr/bin/camera-ui");
#endif
}
QMediaControl *CameraBinService::requestControl(const char *name)
{
if (!m_captureSession)
return 0;
//qDebug() << "Request control" << name;
if (!m_videoOutput) {
if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
m_videoOutput = m_videoRenderer;
m_captureSession->setViewfinder(m_videoRenderer);
} else if (qstrcmp(name, QVideoWindowControl_iid) == 0) {
m_videoOutput = m_videoWindow;
m_captureSession->setViewfinder(m_videoWindow);
} else if (qstrcmp(name, QVideoWidgetControl_iid) == 0) {
m_captureSession->setViewfinder(m_videoWidgetControl);
m_videoOutput = m_videoWidgetControl;
}
if (m_videoOutput)
return m_videoOutput;
}
if (qstrcmp(name,QAudioEndpointSelector_iid) == 0)
return m_audioInputEndpointSelector;
if (qstrcmp(name,QVideoDeviceControl_iid) == 0)
return m_videoInputDevice;
if (qstrcmp(name,QMediaRecorderControl_iid) == 0)
return m_captureSession->recorderControl();
if (qstrcmp(name,QAudioEncoderControl_iid) == 0)
return m_captureSession->audioEncodeControl();
if (qstrcmp(name,QVideoEncoderControl_iid) == 0)
return m_captureSession->videoEncodeControl();
if (qstrcmp(name,QImageEncoderControl_iid) == 0)
return m_captureSession->imageEncodeControl();
if (qstrcmp(name,QMediaContainerControl_iid) == 0)
return m_captureSession->mediaContainerControl();
if (qstrcmp(name,QCameraControl_iid) == 0)
return m_cameraControl;
if (qstrcmp(name,QMetaDataWriterControl_iid) == 0)
return m_metaDataControl;
if (qstrcmp(name, QCameraImageCaptureControl_iid) == 0)
return m_imageCaptureControl;
if (qstrcmp(name, QCameraExposureControl_iid) == 0)
return m_captureSession->cameraExposureControl();
if (qstrcmp(name, QCameraFlashControl_iid) == 0)
return m_captureSession->cameraFlashControl();
if (qstrcmp(name, QCameraFocusControl_iid) == 0)
return m_captureSession->cameraFocusControl();
if (qstrcmp(name, QCameraImageProcessingControl_iid) == 0)
return m_captureSession->imageProcessingControl();
if (qstrcmp(name, QCameraLocksControl_iid) == 0)
return m_captureSession->cameraLocksControl();
if (qstrcmp(name, QCameraCaptureDestinationControl_iid) == 0)
return m_captureSession->captureDestinationControl();
if (qstrcmp(name, QCameraCaptureBufferFormatControl_iid) == 0)
return m_captureSession->captureBufferFormatControl();
return 0;
}
void CameraBinService::releaseControl(QMediaControl *control)
{
if (control && control == m_videoOutput) {
m_videoOutput = 0;
m_captureSession->setViewfinder(0);
}
}
bool CameraBinService::isCameraBinAvailable()
{
GstElementFactory *factory = gst_element_factory_find("camerabin");
if (factory) {
gst_object_unref(GST_OBJECT(factory));
return true;
}
return false;
}

View File

@@ -0,0 +1,96 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CAMERABINCAPTURESERVICE_H
#define CAMERABINCAPTURESERVICE_H
#include <qmediaservice.h>
#include <gst/gst.h>
QT_BEGIN_NAMESPACE
class QAudioEndpointSelector;
class QVideoDeviceControl;
QT_END_NAMESPACE
class CameraBinSession;
class CameraBinControl;
class QGstreamerMessage;
class QGstreamerBusHelper;
class QGstreamerVideoRenderer;
class QGstreamerVideoOverlay;
class QGstreamerVideoWidgetControl;
class QGstreamerElementFactory;
class CameraBinMetaData;
class CameraBinImageCapture;
class CameraBinMetaData;
class CameraBinService : public QMediaService
{
Q_OBJECT
public:
CameraBinService(const QString &service, QObject *parent = 0);
virtual ~CameraBinService();
QMediaControl *requestControl(const char *name);
void releaseControl(QMediaControl *);
static bool isCameraBinAvailable();
private:
void setAudioPreview(GstElement*);
CameraBinSession *m_captureSession;
CameraBinControl *m_cameraControl;
CameraBinMetaData *m_metaDataControl;
QAudioEndpointSelector *m_audioInputEndpointSelector;
QVideoDeviceControl *m_videoInputDevice;
QMediaControl *m_videoOutput;
QMediaControl *m_videoRenderer;
QMediaControl *m_videoWindow;
QGstreamerVideoWidgetControl *m_videoWidgetControl;
CameraBinImageCapture *m_imageCaptureControl;
};
#endif // CAMERABINCAPTURESERVICE_H

File diff suppressed because it is too large Load Diff

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