Merge branch 'stable' into release

Change-Id: Ifa5ddfd7ee4a637f78947fc1cb945d3008506973
This commit is contained in:
Sergio Ahumada
2013-01-09 09:36:25 +01:00
65 changed files with 653 additions and 232 deletions

3
.gitignore vendored
View File

@@ -41,3 +41,6 @@ src/multimediawidgets/qtmultimediawidgetsversion.h
tst_*
!tst_*.cpp
tests/auto/cmake/build
# Generated static plugin import sources
*_plugin_import.cpp

51
dist/changes-5.0.1 vendored Normal file
View File

@@ -0,0 +1,51 @@
Qt 5.0.1 is a bug-fix release. It maintains both forward and backward
compatibility (source and binary) with Qt 5.0.0.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
http://qt-project.org/doc/qt-5.0/
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
http://bugreports.qt-project.org/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* General *
****************************************************************************
General Improvements
--------------------
Third party components
----------------------
****************************************************************************
* Library *
****************************************************************************
****************************************************************************
* Platform Specific Changes *
****************************************************************************
****************************************************************************
* Compiler Specific Changes *
****************************************************************************
****************************************************************************
* Tools *
****************************************************************************
****************************************************************************
* Plugins *
****************************************************************************

View File

@@ -129,13 +129,13 @@ instance, the embedded
\section1 Calculating and displaying QML painting rate
\input video-qml-paint-rate.qdocinc
\input multimedia/doc/src/examples/video-qml-paint-rate.qdocinc
All that remains is to connect the afterRendering() signal of the QQuickView
object to a JavaScript function, which will eventually call frequencyItem.notify():
\quotefromfile multimedia/video/qmlvideo/main.cpp
\skipto QmlApplicationViewer
\skipto QGuiApplication
\printuntil ;
\dots
\skipto QQuickItem

View File

@@ -203,13 +203,13 @@ And here is the effect selection menu:
\section1 Calculating and displaying QML painting rate
\input video-qml-paint-rate.qdocinc
\input multimedia/doc/src/examples/video-qml-paint-rate.qdocinc
All that remains is to connect the afterRendering() signal of the QQuickView
object to a JavaScript function, which will eventually call frequencyItem.notify():
\quotefromfile multimedia/video/qmlvideofx/main.cpp
\skipto QmlApplicationViewer
\skipto QGuiApplication
\printuntil ;
\dots
\skipto QQuickItem

View File

@@ -69,8 +69,8 @@ int main(int argc, char *argv[])
QStringList args = app.arguments();
PerformanceMonitor::State performanceMonitorState;
bool sourceIsUrl = false;
for (int i=1; i<args.count(); ++i) {
const QString &arg = args.at(i);
for (int i = 1; i < args.size(); ++i) {
const QByteArray arg = args.at(i).toUtf8();
if (arg.startsWith('-')) {
if ("-volume" == arg) {
if (i+1 < args.count())
@@ -79,7 +79,7 @@ int main(int argc, char *argv[])
qtTrace() << "Option \"-volume\" takes a value";
}
#ifdef PERFORMANCEMONITOR_SUPPORT
else if (PerformanceMonitor::parseArgument(arg, performanceMonitorState)) {
else if (performanceMonitorState.parseArgument(arg)) {
// Do nothing
}
#endif

View File

@@ -41,36 +41,18 @@
#include "filereader.h"
#include "trace.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QTextStream>
QString adjustPath(const QString &path)
{
#ifdef Q_OS_UNIX
#ifdef Q_OS_MAC
if (!QDir::isAbsolutePath(path))
return QCoreApplication::applicationDirPath()
+ QLatin1String("/../Resources/") + path;
#else
QString pathInInstallDir;
const QString applicationDirPath = QCoreApplication::applicationDirPath();
pathInInstallDir = QString::fromLatin1("%1/../%2").arg(applicationDirPath, path);
if (QFileInfo(pathInInstallDir).exists())
return pathInInstallDir;
#endif
#endif
return path;
}
#include <QCoreApplication>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QTextStream>
QString FileReader::readFile(const QString &fileName)
{
qtTrace() << "FileReader::readFile" << "fileName" << fileName;
QString content;
QFile file(adjustPath(fileName));
QFile file(fileName);
if (file.open(QIODevice::ReadOnly)) {
QTextStream stream(&file);
content = stream.readAll();

View File

@@ -39,7 +39,7 @@
**
****************************************************************************/
#include <QtCore/QObject>
#include <QObject>
class FileReader : public QObject
{

View File

@@ -72,17 +72,17 @@ int main(int argc, char *argv[])
#ifdef PERFORMANCEMONITOR_SUPPORT
PerformanceMonitor::State performanceMonitorState;
#endif
for (int i=1; i<args.count(); ++i) {
const QString &arg = args.at(i);
for (int i = 1; i < args.size(); ++i) {
const QByteArray arg = args.at(i).toUtf8();
if (arg.startsWith('-')) {
if ("-volume" == arg) {
if (i+1 < args.count())
if (i + 1 < args.size())
volume = 0.01 * args.at(++i).toInt();
else
qtTrace() << "Option \"-volume\" takes a value";
}
#ifdef PERFORMANCEMONITOR_SUPPORT
else if (PerformanceMonitor::parseArgument(arg, performanceMonitorState)) {
else if (performanceMonitorState.parseArgument(arg)) {
// Do nothing
}
#endif

View File

@@ -69,7 +69,7 @@ ShaderEffect {
// rather than being inline in the QML file
onFragmentShaderFilenameChanged:
fragmentShader = d.fragmentShaderCommon + fileReader.readFile(fragmentShaderFilename)
fragmentShader = d.fragmentShaderCommon + fileReader.readFile(":shaders/" + fragmentShaderFilename)
onVertexShaderFilenameChanged:
vertexShader = fileReader.readFile(vertexShaderFilename)
}

View File

@@ -55,5 +55,5 @@ Effect {
property real step_x: 0.0015625
property real step_y: targetHeight ? (step_x * targetWidth / targetHeight) : 0.0
fragmentShaderFilename: "shaders/billboard.fsh"
fragmentShaderFilename: "billboard.fsh"
}

View File

@@ -52,5 +52,5 @@ Effect {
// Transform slider values, and bind result to shader uniforms
property real threshold: parameters.get(0).value
fragmentShaderFilename: "shaders/blackandwhite.fsh"
fragmentShaderFilename: "blackandwhite.fsh"
}

View File

@@ -42,5 +42,5 @@
import QtQuick 2.0
Effect {
fragmentShaderFilename: "shaders/emboss.fsh"
fragmentShaderFilename: "emboss.fsh"
}

View File

@@ -63,7 +63,7 @@ Item {
anchors.fill: parent
dividerValue: parent.dividerValue
property real blurSize: 4.0 * parent.parameters.get(0).value / targetHeight
fragmentShaderFilename: "shaders/gaussianblur_v.fsh"
fragmentShaderFilename: "gaussianblur_v.fsh"
}
Effect {
@@ -71,7 +71,7 @@ Item {
anchors.fill: parent
dividerValue: parent.dividerValue
property real blurSize: 4.0 * parent.parameters.get(0).value / parent.targetWidth
fragmentShaderFilename: "shaders/gaussianblur_h.fsh"
fragmentShaderFilename: "gaussianblur_h.fsh"
source: horizontalShaderSource
ShaderEffectSource {

View File

@@ -42,5 +42,5 @@
import QtQuick 2.0
Effect {
fragmentShaderFilename: "shaders/glow.fsh"
fragmentShaderFilename: "glow.fsh"
}

View File

@@ -57,5 +57,5 @@ Effect {
property real targetHue: parameters.get(0).value * 360
property real windowWidth: parameters.get(1).value * 60
fragmentShaderFilename: "shaders/isolate.fsh"
fragmentShaderFilename: "isolate.fsh"
}

View File

@@ -84,7 +84,7 @@ Effect {
d.oldTargetHeight = targetHeight
}
fragmentShaderFilename: "shaders/magnify.fsh"
fragmentShaderFilename: "magnify.fsh"
MouseArea {
anchors.fill: parent

View File

@@ -53,5 +53,5 @@ Effect {
// Transform slider values, and bind result to shader uniforms
property real curlExtent: 1.0 - parameters.get(0).value
fragmentShaderFilename: "shaders/pagecurl.fsh"
fragmentShaderFilename: "pagecurl.fsh"
}

View File

@@ -52,5 +52,5 @@ Effect {
// Transform slider values, and bind result to shader uniforms
property real granularity: parameters.get(0).value * 20
fragmentShaderFilename: "shaders/pixelate.fsh"
fragmentShaderFilename: "pixelate.fsh"
}

View File

@@ -54,5 +54,5 @@ Effect {
property real numColors: 8.0
fragmentShaderFilename: "shaders/posterize.fsh"
fragmentShaderFilename: "posterize.fsh"
}

View File

@@ -60,5 +60,5 @@ Effect {
property real time: 0
NumberAnimation on time { loops: Animation.Infinite; from: 0; to: Math.PI * 2; duration: 600 }
fragmentShaderFilename: "shaders/ripple.fsh"
fragmentShaderFilename: "ripple.fsh"
}

View File

@@ -42,5 +42,5 @@
import QtQuick 2.0
Effect {
fragmentShaderFilename: "shaders/sepia.fsh"
fragmentShaderFilename: "sepia.fsh"
}

View File

@@ -52,5 +52,5 @@ Effect {
// Transform slider values, and bind result to shader uniforms
property real amount: parameters.get(0).value * 18
fragmentShaderFilename: "shaders/sharpen.fsh"
fragmentShaderFilename: "sharpen.fsh"
}

View File

@@ -76,5 +76,5 @@ Effect {
}
}
fragmentShaderFilename: "shaders/shockwave.fsh"
fragmentShaderFilename: "shockwave.fsh"
}

View File

@@ -55,5 +55,5 @@ Effect {
property real resS: targetSize
property real resT: targetSize
fragmentShaderFilename: "shaders/sobeledgedetection1.fsh"
fragmentShaderFilename: "sobeledgedetection1.fsh"
}

View File

@@ -52,5 +52,5 @@ Effect {
// Transform slider values, and bind result to shader uniforms
property real weight: parameters.get(0).value
fragmentShaderFilename: "shaders/sobeledgedetection2.fsh"
fragmentShaderFilename: "sobeledgedetection2.fsh"
}

View File

@@ -42,5 +42,5 @@
import QtQuick 2.0
Effect {
fragmentShaderFilename: "shaders/tiltshift.fsh"
fragmentShaderFilename: "tiltshift.fsh"
}

View File

@@ -59,5 +59,5 @@ Effect {
property real magTol: 0.3
property real quantize: 8.0
fragmentShaderFilename: "shaders/toon.fsh"
fragmentShaderFilename: "toon.fsh"
}

View File

@@ -42,5 +42,5 @@
import QtQuick 2.0
Effect {
fragmentShaderFilename: "shaders/vignette.fsh"
fragmentShaderFilename: "vignette.fsh"
}

View File

@@ -42,5 +42,5 @@
import QtQuick 2.0
Effect {
fragmentShaderFilename: "shaders/warhol.fsh"
fragmentShaderFilename: "warhol.fsh"
}

View File

@@ -57,5 +57,5 @@ Effect {
NumberAnimation on time { loops: Animation.Infinite; from: 0; to: Math.PI * 2; duration: 600 }
fragmentShaderFilename: "shaders/wobble.fsh"
fragmentShaderFilename: "wobble.fsh"
}

View File

@@ -3,16 +3,12 @@ TARGET = qmlvideofx
QT += quick
LOCAL_SOURCES = filereader.cpp main.cpp
LOCAL_HEADERS = filereader.h trace.h
SOURCES += $$LOCAL_SOURCES
HEADERS += $$LOCAL_HEADERS
SOURCES += filereader.cpp main.cpp
HEADERS += filereader.h trace.h
RESOURCES += qmlvideofx.qrc
SNIPPETS_PATH = ../snippets
include($$SNIPPETS_PATH/performancemonitor/performancemonitordeclarative.pri)
include($$PWD/../snippets/performancemonitor/performancemonitordeclarative.pri)
maemo6: {
DEFINES += SMALL_SCREEN_LAYOUT

View File

@@ -44,5 +44,28 @@
<file>qml/qmlvideofx/main-smallscreen.qml</file>
<file>qml/qmlvideofx/ParameterPanel.qml</file>
<file>qml/qmlvideofx/Slider.qml</file>
<file>shaders/billboard.fsh</file>
<file>shaders/blackandwhite.fsh</file>
<file>shaders/emboss.fsh</file>
<file>shaders/gaussianblur_h.fsh</file>
<file>shaders/gaussianblur_v.fsh</file>
<file>shaders/glow.fsh</file>
<file>shaders/isolate.fsh</file>
<file>shaders/magnify.fsh</file>
<file>shaders/pagecurl.fsh</file>
<file>shaders/pixelate.fsh</file>
<file>shaders/posterize.fsh</file>
<file>shaders/ripple.fsh</file>
<file>shaders/selectionpanel.fsh</file>
<file>shaders/sepia.fsh</file>
<file>shaders/sharpen.fsh</file>
<file>shaders/shockwave.fsh</file>
<file>shaders/sobeledgedetection1.fsh</file>
<file>shaders/sobeledgedetection2.fsh</file>
<file>shaders/tiltshift.fsh</file>
<file>shaders/toon.fsh</file>
<file>shaders/vignette.fsh</file>
<file>shaders/warhol.fsh</file>
<file>shaders/wobble.fsh</file>
</qresource>
</RCC>

View File

@@ -42,7 +42,7 @@
#ifndef TRACE_H
#define TRACE_H
#include <QtCore/QDebug>
#include <QDebug>
#define ENABLE_TRACE
//#define VERBOSE_TRACE
@@ -74,12 +74,6 @@ inline QDebug& operator<<(QDebug &debug, const Trace::PtrWrapper<T> &wrapper)
return debug.space();
}
template<typename T>
inline const void *qtVoidPtr(const T *ptr)
{ return static_cast<const void *>(ptr); }
#define qtThisPtr() qtVoidPtr(this)
#ifdef ENABLE_TRACE
inline QDebug qtTrace() { return qDebug() << "[qmlvideofx]"; }
# ifdef VERBOSE_TRACE

View File

@@ -40,11 +40,11 @@
****************************************************************************/
#include "frequencymonitor.h"
#include <QtCore/QDebug>
#include <QtCore/QElapsedTimer>
#include <QtCore/QString>
#include <QtCore/QTime>
#include <QtCore/QTimer>
#include <QDebug>
#include <QElapsedTimer>
#include <QString>
#include <QTime>
#include <QTimer>
//#define VERBOSE_TRACE
@@ -61,6 +61,7 @@ static const int DefaultTraceInterval = 0;
class FrequencyMonitorPrivate : public QObject
{
Q_OBJECT
public:
FrequencyMonitorPrivate(FrequencyMonitor *parent);
void calculateInstantaneousFrequency();
@@ -116,16 +117,16 @@ void FrequencyMonitorPrivate::calculateInstantaneousFrequency()
m_stalledTimer->start(3 * ms);
if (m_instantaneousFrequency)
q_ptr->setActive(true);
q_ptr->emit instantaneousFrequencyChanged(m_instantaneousFrequency);
q_ptr->emit frequencyChanged();
emit q_ptr->instantaneousFrequencyChanged(m_instantaneousFrequency);
emit q_ptr->frequencyChanged();
}
void FrequencyMonitorPrivate::calculateAverageFrequency()
{
const qint64 ms = m_averageElapsed.restart();
m_averageFrequency = qreal(m_count * 1000) / ms;
q_ptr->emit averageFrequencyChanged(m_averageFrequency);
q_ptr->emit frequencyChanged();
emit q_ptr->averageFrequencyChanged(m_averageFrequency);
emit q_ptr->frequencyChanged();
m_count = 0;
}
@@ -134,14 +135,13 @@ void FrequencyMonitorPrivate::stalled()
if (m_instantaneousFrequency) {
qtVerboseTrace() << "FrequencyMonitor::stalled";
m_instantaneousFrequency = 0;
q_ptr->emit instantaneousFrequencyChanged(m_instantaneousFrequency);
q_ptr->emit frequencyChanged();
emit q_ptr->instantaneousFrequencyChanged(m_instantaneousFrequency);
emit q_ptr->frequencyChanged();
}
}
FrequencyMonitor::FrequencyMonitor(QObject *parent)
: QObject(parent)
, d_ptr(0)
{
d_ptr = new FrequencyMonitorPrivate(this);
qtTrace() << "FrequencyMonitor::FrequencyMonitor";
@@ -152,7 +152,7 @@ FrequencyMonitor::~FrequencyMonitor()
}
const QString &FrequencyMonitor::label() const
QString FrequencyMonitor::label() const
{
return d_func()->m_label;
}

View File

@@ -42,8 +42,8 @@
#ifndef FREQUENCYMONITOR_H
#define FREQUENCYMONITOR_H
#include <QtCore/QObject>
#include <QtCore/QTimer>
#include <QObject>
#include <QTimer>
class FrequencyMonitorPrivate;
@@ -64,13 +64,14 @@ class FrequencyMonitor : public QObject
Q_PROPERTY(int traceInterval READ traceInterval WRITE setTraceInterval NOTIFY traceIntervalChanged)
Q_PROPERTY(qreal instantaneousFrequency READ instantaneousFrequency NOTIFY instantaneousFrequencyChanged)
Q_PROPERTY(qreal averageFrequency READ averageFrequency NOTIFY averageFrequencyChanged)
public:
FrequencyMonitor(QObject *parent = 0);
~FrequencyMonitor();
static void qmlRegisterType();
const QString &label() const;
QString label() const;
bool active() const;
int samplingInterval() const;
int traceInterval() const;

View File

@@ -43,27 +43,27 @@
namespace PerformanceMonitor {
bool parseArgument(const QString &arg, State &state)
bool State::parseArgument(const QByteArray &arg)
{
bool result = false;
if ("-log-perf" == arg) {
state.logging = true;
state.valid = true;
if (arg == "-log-perf") {
logging = true;
valid = true;
result = true;
} else if ("-no-log-perf" == arg) {
state.logging = false;
state.valid = true;
} else if (arg == "-no-log-perf") {
logging = false;
valid = true;
result = true;
} else if ("-show-perf" == arg) {
state.visible = true;
state.valid = true;
} else if (arg == "-show-perf") {
visible = true;
valid = true;
result = true;
} else if ("-hide-perf" == arg) {
state.visible = false;
state.valid = true;
} else if (arg == "-hide-perf") {
visible = false;
valid = true;
result = true;
}
return result;
}
}
} // namespace PerformanceMonitor

View File

@@ -42,24 +42,27 @@
#ifndef PERFORMANCEMONITOR_H
#define PERFORMANCEMONITOR_H
#include <QtCore/QString>
#include <QByteArray>
namespace PerformanceMonitor {
struct State {
bool valid;
bool logging;
bool visible;
struct State
{
State() : valid(true), logging(false), visible(true) { }
State(bool l, bool v) : valid(true), logging(l), visible(v) { }
bool operator==(const State &other) const
{ return logging == other.logging && visible == other.visible; }
bool operator!=(const State &other) const
{ return logging != other.logging || visible != other.visible; }
bool parseArgument(const QByteArray &arg);
bool valid;
bool logging;
bool visible;
};
bool parseArgument(const QString &arg, State &state);
}
} // namespace PerformanceMonitor
#endif // PERFORMANCEMONITOR_H

View File

@@ -4,6 +4,7 @@ TARGET=declarative-camera
QT += quick qml multimedia
SOURCES += qmlcamera.cpp
RESOURCES += declarative-camera.qrc
target.path = $$[QT_INSTALL_EXAMPLES]/multimediawidgets/declarative-camera
INSTALLS += target

View File

@@ -0,0 +1,26 @@
<RCC>
<qresource prefix="/">
<file>PhotoPreview.qml</file>
<file>ZoomControl.qml</file>
<file>VideoCaptureControls.qml</file>
<file>VideoPreview.qml</file>
<file>FocusButton.qml</file>
<file>PhotoCaptureControls.qml</file>
<file>declarative-camera.qml</file>
<file>CameraPropertyPopup.qml</file>
<file>CameraPropertyButton.qml</file>
<file>CameraButton.qml</file>
<file>images/camera_auto_mode.png</file>
<file>images/camera_camera_setting.png</file>
<file>images/camera_flash_auto.png</file>
<file>images/camera_flash_fill.png</file>
<file>images/camera_flash_off.png</file>
<file>images/camera_flash_redeye.png</file>
<file>images/camera_white_balance_cloudy.png</file>
<file>images/camera_white_balance_flourescent.png</file>
<file>images/camera_white_balance_incandescent.png</file>
<file>images/camera_white_balance_sunny.png</file>
<file>images/toolbutton.png</file>
<file>images/toolbutton.sci</file>
</qresource>
</RCC>

View File

@@ -50,8 +50,7 @@ int main(int argc, char* argv[])
// Qt.quit() called in embedded .qml by default only emits
// quit() signal, so do this (optionally use Qt.exit()).
QObject::connect(view.engine(), SIGNAL(quit()), qApp, SLOT(quit()));
view.setSource(QUrl::fromLocalFile(QCoreApplication::applicationDirPath() +
QLatin1String("/declarative-camera.qml")));
view.setSource(QUrl("qrc:///declarative-camera.qml"));
view.resize(800, 480);
view.show();
return app.exec();

View File

@@ -49,6 +49,7 @@ VideoPlayer::VideoPlayer(QWidget *parent)
, mediaPlayer(0, QMediaPlayer::VideoSurface)
, playButton(0)
, positionSlider(0)
, errorLabel(0)
{
QVideoWidget *videoWidget = new QVideoWidget;
@@ -68,6 +69,9 @@ VideoPlayer::VideoPlayer(QWidget *parent)
connect(positionSlider, SIGNAL(sliderMoved(int)),
this, SLOT(setPosition(int)));
errorLabel = new QLabel;
errorLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
QBoxLayout *controlLayout = new QHBoxLayout;
controlLayout->setMargin(0);
controlLayout->addWidget(openButton);
@@ -77,6 +81,7 @@ VideoPlayer::VideoPlayer(QWidget *parent)
QBoxLayout *layout = new QVBoxLayout;
layout->addWidget(videoWidget);
layout->addLayout(controlLayout);
layout->addWidget(errorLabel);
setLayout(layout);
@@ -85,6 +90,7 @@ VideoPlayer::VideoPlayer(QWidget *parent)
this, SLOT(mediaStateChanged(QMediaPlayer::State)));
connect(&mediaPlayer, SIGNAL(positionChanged(qint64)), this, SLOT(positionChanged(qint64)));
connect(&mediaPlayer, SIGNAL(durationChanged(qint64)), this, SLOT(durationChanged(qint64)));
connect(&mediaPlayer, SIGNAL(error(QMediaPlayer::Error)), this, SLOT(handleError()));
}
VideoPlayer::~VideoPlayer()
@@ -93,11 +99,12 @@ VideoPlayer::~VideoPlayer()
void VideoPlayer::openFile()
{
errorLabel->setText("");
QString fileName = QFileDialog::getOpenFileName(this, tr("Open Movie"),QDir::homePath());
if (!fileName.isEmpty()) {
mediaPlayer.setMedia(QUrl::fromLocalFile(fileName));
playButton->setEnabled(true);
}
}
@@ -140,3 +147,9 @@ void VideoPlayer::setPosition(int position)
{
mediaPlayer.setPosition(position);
}
void VideoPlayer::handleError()
{
playButton->setEnabled(false);
errorLabel->setText("Error: " + mediaPlayer.errorString());
}

View File

@@ -49,6 +49,7 @@
QT_BEGIN_NAMESPACE
class QAbstractButton;
class QSlider;
class QLabel;
QT_END_NAMESPACE
class VideoPlayer : public QWidget
@@ -67,11 +68,13 @@ private slots:
void positionChanged(qint64 position);
void durationChanged(qint64 duration);
void setPosition(int position);
void handleError();
private:
QMediaPlayer mediaPlayer;
QAbstractButton *playButton;
QSlider *positionSlider;
QLabel *errorLabel;
};
#endif

View File

@@ -1,3 +1,4 @@
module QtMultimedia
plugin declarative_multimedia
typeinfo plugins.qmltypes
Video 5.0 Video.qml

View File

@@ -57,7 +57,7 @@ class Q_MULTIMEDIA_EXPORT QSound : public QObject
public:
enum Loop
{
Infinite = -1,
Infinite = -1
};
static void play(const QString& filename);

View File

@@ -3,7 +3,7 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
project = qtmultimedia
description = Qt Multimedia Documentation
url = http://qt-project.org/doc/qtmultimedia
version = 5.0.0
version = 5.0.1
# The following parameters are for creating a qhp file, the qhelpgenerator
# program can convert the qhp file into a qch file which can be opened in

View File

@@ -2,7 +2,7 @@ The QML painting rate is calculated by the FrequencyMonitor class, which
turns a stream of events (received via the notify() slot), into an
instantaneous and an averaged frequency:
\quotefromfile video/snippets/frequencymonitor/frequencymonitor.h
\quotefromfile multimedia/video/snippets/frequencymonitor/frequencymonitor.h
\skipto class FrequencyMonitor : public QObject
\printuntil Q_OBJECT
\skipto Q_PROPERTY(qreal instantaneousFrequency
@@ -19,13 +19,13 @@ instantaneous and an averaged frequency:
The FrequencyMonitor class is exposed to QML like this
\quotefromfile video/snippets/frequencymonitor/frequencymonitordeclarative.cpp
\quotefromfile multimedia/video/snippets/frequencymonitor/frequencymonitordeclarative.cpp
\skipto FrequencyMonitor::qmlRegisterType
\printuntil }
and its data is displayed by defining a QML item called FrequencyItem, like this:
\quotefromfile video/snippets/frequencymonitor/qml/frequencymonitor/FrequencyItem.qml
\quotefromfile multimedia/video/snippets/frequencymonitor/qml/frequencymonitor/FrequencyItem.qml
\skipto import FrequencyMonitor
\printuntil id: root
\dots

View File

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@@ -1,11 +1,6 @@
TARGET = QtMultimedia
QT = core-private network gui
contains(QT_CONFIG, opengl) | contains(QT_CONFIG, opengles2) {
} else {
DEFINES += QT_NO_OPENGL
}
QMAKE_DOCS = $$PWD/doc/qtmultimedia.qdocconf
load(qt_module)

View File

@@ -257,8 +257,8 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe
NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];
if ([tracks count]) {
AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
m_playerLayer.anchorPoint = NSMakePoint(0.0f, 0.0f);
m_playerLayer.bounds = NSMakeRect(0.0f, 0.0f, videoTrack.naturalSize.width, videoTrack.naturalSize.height);
m_playerLayer.anchorPoint = CGPointMake(0.0f, 0.0f);
m_playerLayer.bounds = CGRectMake(0.0f, 0.0f, videoTrack.naturalSize.width, videoTrack.naturalSize.height);
}
}
@@ -368,8 +368,8 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe
NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];
if ([tracks count]) {
AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
m_playerLayer.anchorPoint = NSMakePoint(0.0f, 0.0f);
m_playerLayer.bounds = NSMakeRect(0.0f, 0.0f, videoTrack.naturalSize.width, videoTrack.naturalSize.height);
m_playerLayer.anchorPoint = CGPointMake(0.0f, 0.0f);
m_playerLayer.bounds = CGRectMake(0.0f, 0.0f, videoTrack.naturalSize.width, videoTrack.naturalSize.height);
}
}

View File

@@ -207,7 +207,7 @@ void AVFVideoWidgetControl::updateVideoFrame(const CVTimeStamp &ts)
void AVFVideoWidgetControl::setupVideoOutput()
{
NSRect layerBounds = [(AVPlayerLayer*)m_playerLayer bounds];
CGRect layerBounds = [(AVPlayerLayer*)m_playerLayer bounds];
m_nativeSize = QSize(layerBounds.size.width, layerBounds.size.height);
m_videoWidget->setNativeSize(m_nativeSize);

View File

@@ -44,7 +44,7 @@
#if defined(HAVE_WIDGETS)
#include <QtWidgets/qwidget.h>
#include <QVideoWidgetControl.h>
#include <QVideoWidgetControl>
#endif
#include "dscameraservice.h"

View File

@@ -49,7 +49,7 @@
#include <dshow.h>
#include <objbase.h>
#include <initguid.h>
#include <Ocidl.h>
#include <ocidl.h>
#include <string.h>
extern const CLSID CLSID_VideoInputDeviceCategory;

View File

@@ -42,7 +42,7 @@
#include <QtCore/qcoreevent.h>
#include <QtCore/qtimer.h>
#include "DSVideoWidgetControl.h"
#include "dsvideowidgetcontrol.h"
#include "dscamerasession.h"
QT_BEGIN_NAMESPACE

View File

@@ -49,7 +49,7 @@
#include <QtMultimedia/qvideosurfaceformat.h>
#include <qvideowidgetcontrol.h>
#include "DsCameraControl.h"
#include "dscameracontrol.h"
QT_BEGIN_HEADER

View File

@@ -23,7 +23,7 @@ LIBS += -framework AppKit -framework AudioUnit \
# QUICKTIME_C_API_AVAILABLE is true only on i386
# so make sure to link QuickTime
contains(QMAKE_HOST.arch, i386) {
contains(QT_ARCH, i386) {
LIBS += -framework QuickTime
}

View File

@@ -47,6 +47,7 @@
#include <uuids.h>
#include <InitGuid.h>
#include <d3d9.h>
#include <qdebug.h>
// This MFT sends all samples it processes to connected video probes.
// Sample is sent to probes in ProcessInput.
@@ -70,6 +71,9 @@ MFTransform::~MFTransform()
if (m_outputType)
m_outputType->Release();
for (int i = 0; i < m_mediaTypes.size(); ++i)
m_mediaTypes[i]->Release();
}
void MFTransform::addProbe(MFVideoProbeControl *probe)
@@ -88,6 +92,14 @@ void MFTransform::removeProbe(MFVideoProbeControl *probe)
m_videoProbes.removeOne(probe);
}
void MFTransform::addSupportedMediaType(IMFMediaType *type)
{
if (!type)
return;
QMutexLocker locker(&m_mutex);
m_mediaTypes.append(type);
}
STDMETHODIMP MFTransform::QueryInterface(REFIID riid, void** ppv)
{
if (!ppv)
@@ -151,6 +163,8 @@ STDMETHODIMP MFTransform::GetStreamIDs(DWORD dwInputIDArraySize, DWORD *pdwInput
STDMETHODIMP MFTransform::GetInputStreamInfo(DWORD dwInputStreamID, MFT_INPUT_STREAM_INFO *pStreamInfo)
{
QMutexLocker locker(&m_mutex);
if (dwInputStreamID > 0)
return MF_E_INVALIDSTREAMNUMBER;
@@ -167,6 +181,8 @@ STDMETHODIMP MFTransform::GetInputStreamInfo(DWORD dwInputStreamID, MFT_INPUT_ST
STDMETHODIMP MFTransform::GetOutputStreamInfo(DWORD dwOutputStreamID, MFT_OUTPUT_STREAM_INFO *pStreamInfo)
{
QMutexLocker locker(&m_mutex);
if (dwOutputStreamID > 0)
return MF_E_INVALIDSTREAMNUMBER;
@@ -243,16 +259,27 @@ STDMETHODIMP MFTransform::SetInputType(DWORD dwInputStreamID, IMFMediaType *pTyp
QMutexLocker locker(&m_mutex);
DWORD flags = 0;
if (m_outputType && m_outputType->IsEqual(pType, &flags) != S_OK) {
if (m_sample)
return MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
if (!isMediaTypeSupported(pType))
return MF_E_INVALIDMEDIATYPE;
DWORD flags = 0;
if (pType && !m_inputType && m_outputType && m_outputType->IsEqual(pType, &flags) != S_OK)
return MF_E_INVALIDMEDIATYPE;
}
if (dwFlags == MFT_SET_TYPE_TEST_ONLY)
return pType ? S_OK : E_POINTER;
if (m_inputType)
if (m_inputType) {
m_inputType->Release();
// Input type has changed, discard output type (if it's set) so it's reset later on
if (m_outputType && m_outputType->IsEqual(pType, &flags) != S_OK) {
m_outputType->Release();
m_outputType = 0;
}
}
m_inputType = pType;
@@ -269,16 +296,27 @@ STDMETHODIMP MFTransform::SetOutputType(DWORD dwOutputStreamID, IMFMediaType *pT
QMutexLocker locker(&m_mutex);
DWORD flags = 0;
if (m_inputType && m_inputType->IsEqual(pType, &flags) != S_OK) {
if (m_sample)
return MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
if (!isMediaTypeSupported(pType))
return MF_E_INVALIDMEDIATYPE;
DWORD flags = 0;
if (pType && !m_outputType && m_inputType && m_inputType->IsEqual(pType, &flags) != S_OK)
return MF_E_INVALIDMEDIATYPE;
}
if (dwFlags == MFT_SET_TYPE_TEST_ONLY)
return pType ? S_OK : E_POINTER;
if (m_outputType)
if (m_outputType) {
m_outputType->Release();
// Output type has changed, discard input type (if it's set) so it's reset later on
if (m_inputType && m_inputType->IsEqual(pType, &flags) != S_OK) {
m_inputType->Release();
m_inputType = 0;
}
}
m_outputType = pType;
@@ -645,3 +683,19 @@ QByteArray MFTransform::dataFromBuffer(IMFMediaBuffer *buffer, int height, int *
return array;
}
bool MFTransform::isMediaTypeSupported(IMFMediaType *type)
{
// if the list is empty, it supports all formats
if (!type || m_mediaTypes.isEmpty())
return true;
for (int i = 0; i < m_mediaTypes.size(); ++i) {
DWORD flags = 0;
m_mediaTypes.at(i)->IsEqual(type, &flags);
if (flags & MF_MEDIATYPE_EQUAL_FORMAT_TYPES)
return true;
}
return false;
}

View File

@@ -61,6 +61,8 @@ public:
void addProbe(MFVideoProbeControl* probe);
void removeProbe(MFVideoProbeControl* probe);
void addSupportedMediaType(IMFMediaType *type);
// IUnknown methods
STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
STDMETHODIMP_(ULONG) AddRef();
@@ -97,6 +99,7 @@ private:
static QVideoSurfaceFormat videoFormatForMFMediaType(IMFMediaType *mediaType, int *bytesPerLine);
QVideoFrame makeVideoFrame();
QByteArray dataFromBuffer(IMFMediaBuffer *buffer, int height, int *bytesPerLine);
bool isMediaTypeSupported(IMFMediaType *type);
long m_cRef;
IMFMediaType *m_inputType;
@@ -104,6 +107,8 @@ private:
IMFSample *m_sample;
QMutex m_mutex;
QList<IMFMediaType*> m_mediaTypes;
QList<MFVideoProbeControl*> m_videoProbes;
QMutex m_videoProbeMutex;

View File

@@ -85,6 +85,11 @@ void Evr9VideoWindowControl::clear()
m_currentActivate = NULL;
}
void Evr9VideoWindowControl::releaseActivate()
{
clear();
}
WId Evr9VideoWindowControl::winId() const
{
return m_windowId;

View File

@@ -86,6 +86,7 @@ public:
void setSaturation(int saturation);
IMFActivate* createActivate();
void releaseActivate();
void setProcAmpValues();

View File

@@ -39,12 +39,95 @@
**
****************************************************************************/
#include <qdatetime.h>
#include <qimage.h>
#include "mfmetadatacontrol.h"
#include "mfplayerservice.h"
#include "Propkey.h"
//#define DEBUG_MEDIAFOUNDATION
static QString nameForGUID(GUID guid)
{
// Audio formats
if (guid == MFAudioFormat_AAC)
return QStringLiteral("MPEG AAC Audio");
else if (guid == MFAudioFormat_ADTS)
return QStringLiteral("MPEG ADTS AAC Audio");
else if (guid == MFAudioFormat_Dolby_AC3_SPDIF)
return QStringLiteral("Dolby AC-3 SPDIF");
else if (guid == MFAudioFormat_DRM)
return QStringLiteral("DRM");
else if (guid == MFAudioFormat_DTS)
return QStringLiteral("Digital Theater Systems Audio (DTS)");
else if (guid == MFAudioFormat_Float)
return QStringLiteral("IEEE Float Audio");
else if (guid == MFAudioFormat_MP3)
return QStringLiteral("MPEG Audio Layer-3 (MP3)");
else if (guid == MFAudioFormat_MPEG)
return QStringLiteral("MPEG-1 Audio");
else if (guid == MFAudioFormat_MSP1)
return QStringLiteral("Windows Media Audio Voice");
else if (guid == MFAudioFormat_PCM)
return QStringLiteral("Uncompressed PCM Audio");
else if (guid == MFAudioFormat_WMASPDIF)
return QStringLiteral("Windows Media Audio 9 SPDIF");
else if (guid == MFAudioFormat_WMAudioV8)
return QStringLiteral("Windows Media Audio 8 (WMA2)");
else if (guid == MFAudioFormat_WMAudioV9)
return QStringLiteral("Windows Media Audio 9 (WMA3");
else if (guid == MFAudioFormat_WMAudio_Lossless)
return QStringLiteral("Windows Media Audio 9 Lossless");
// Video formats
if (guid == MFVideoFormat_DV25)
return QStringLiteral("DVCPRO 25 (DV25)");
else if (guid == MFVideoFormat_DV50)
return QStringLiteral("DVCPRO 50 (DV50)");
else if (guid == MFVideoFormat_DVC)
return QStringLiteral("DVC/DV Video");
else if (guid == MFVideoFormat_DVH1)
return QStringLiteral("DVCPRO 100 (DVH1)");
else if (guid == MFVideoFormat_DVHD)
return QStringLiteral("HD-DVCR (DVHD)");
else if (guid == MFVideoFormat_DVSD)
return QStringLiteral("SDL-DVCR (DVSD)");
else if (guid == MFVideoFormat_DVSL)
return QStringLiteral("SD-DVCR (DVSL)");
else if (guid == MFVideoFormat_H264)
return QStringLiteral("H.264 Video");
else if (guid == MFVideoFormat_M4S2)
return QStringLiteral("MPEG-4 part 2 Video (M4S2)");
else if (guid == MFVideoFormat_MJPG)
return QStringLiteral("Motion JPEG (MJPG)");
else if (guid == MFVideoFormat_MP43)
return QStringLiteral("Microsoft MPEG 4 version 3 (MP43)");
else if (guid == MFVideoFormat_MP4S)
return QStringLiteral("ISO MPEG 4 version 1 (MP4S)");
else if (guid == MFVideoFormat_MP4V)
return QStringLiteral("MPEG-4 part 2 Video (MP4V)");
else if (guid == MFVideoFormat_MPEG2)
return QStringLiteral("MPEG-2 Video");
else if (guid == MFVideoFormat_MPG1)
return QStringLiteral("MPEG-1 Video");
else if (guid == MFVideoFormat_MSS1)
return QStringLiteral("Windows Media Screen 1 (MSS1)");
else if (guid == MFVideoFormat_MSS2)
return QStringLiteral("Windows Media Video 9 Screen (MSS2)");
else if (guid == MFVideoFormat_WMV1)
return QStringLiteral("Windows Media Video 7 (WMV1)");
else if (guid == MFVideoFormat_WMV2)
return QStringLiteral("Windows Media Video 8 (WMV2)");
else if (guid == MFVideoFormat_WMV3)
return QStringLiteral("Windows Media Video 9 (WMV3)");
else if (guid == MFVideoFormat_WVC1)
return QStringLiteral("Windows Media Video VC1 (WVC1)");
else
return QStringLiteral("Unknown codec");
}
MFMetaDataControl::MFMetaDataControl(QObject *parent)
: QMetaDataReaderControl(parent)
, m_metaData(0)
@@ -83,9 +166,46 @@ QVariant MFMetaDataControl::metaData(const QString &key) const
else if (m_metaData)
hr = m_metaData->GetProperty(reinterpret_cast<LPCWSTR>(m_commonNames[index].utf16()), &var);
if (SUCCEEDED(hr))
if (SUCCEEDED(hr)) {
value = convertValue(var);
// some metadata needs to be reformatted
if (value.isValid() && m_content) {
if (key == QMediaMetaData::MediaType) {
QString v = value.toString();
if (v == QLatin1String("{D1607DBC-E323-4BE2-86A1-48A42A28441E}"))
value = QStringLiteral("Music");
else if (v == QLatin1String("{DB9830BD-3AB3-4FAB-8A37-1A995F7FF74B}"))
value = QStringLiteral("Video");
else if (v == QLatin1String("{01CD0F29-DA4E-4157-897B-6275D50C4F11}"))
value = QStringLiteral("Audio");
else if (v == QLatin1String("{FCF24A76-9A57-4036-990D-E35DD8B244E1}"))
value = QStringLiteral("Other");
} else if (key == QMediaMetaData::Duration) {
// duration is provided in 100-nanosecond units, convert to milliseconds
value = (value.toLongLong() + 10000) / 10000;
} else if (key == QMediaMetaData::AudioCodec || key == QMediaMetaData::VideoCodec) {
GUID guid;
if (SUCCEEDED(CLSIDFromString((const WCHAR*)value.toString().utf16(), &guid)))
value = nameForGUID(guid);
} else if (key == QMediaMetaData::Resolution) {
QSize res;
res.setHeight(value.toUInt());
if (m_content && SUCCEEDED(m_content->GetValue(PKEY_Video_FrameWidth, &var)))
res.setWidth(convertValue(var).toUInt());
value = res;
} else if (key == QMediaMetaData::PixelAspectRatio) {
QSize aspectRatio;
aspectRatio.setWidth(value.toUInt());
if (m_content && SUCCEEDED(m_content->GetValue(PKEY_Video_VerticalAspectRatio, &var)))
aspectRatio.setHeight(convertValue(var).toUInt());
value = aspectRatio;
} else if (key == QMediaMetaData::VideoFrameRate) {
value = value.toReal() / 1000.f;
}
}
}
PropVariantClear(&var);
return value;
}
@@ -93,9 +213,6 @@ QVariant MFMetaDataControl::metaData(const QString &key) const
QVariant MFMetaDataControl::convertValue(const PROPVARIANT& var) const
{
QVariant value;
//form MSDN: http://msdn.microsoft.com/en-us/library/ff384862%28v=VS.85%29.aspx
//it seems that those 4 types are enough for media foundation metadata
//add more later if necessary
switch (var.vt) {
case VT_LPWSTR:
value = QString::fromUtf16(reinterpret_cast<const ushort*>(var.pwszVal));
@@ -109,6 +226,33 @@ QVariant MFMetaDataControl::convertValue(const PROPVARIANT& var) const
case VT_BOOL:
value = bool(var.boolVal);
break;
case VT_FILETIME:
SYSTEMTIME sysDate;
if (!FileTimeToSystemTime(&var.filetime, &sysDate))
break;
value = QDate(sysDate.wYear, sysDate.wMonth, sysDate.wDay);
break;
case VT_STREAM:
{
STATSTG stat;
if (FAILED(var.pStream->Stat(&stat, STATFLAG_NONAME)))
break;
void *data = malloc(stat.cbSize.QuadPart);
ULONG read = 0;
if (FAILED(var.pStream->Read(data, stat.cbSize.QuadPart, &read))) {
free(data);
break;
}
value = QImage::fromData((const uchar*)data, read);
free(data);
}
break;
case VT_VECTOR | VT_LPWSTR:
QStringList vList;
for (ULONG i = 0; i < var.calpwstr.cElems; ++i)
vList.append(QString::fromUtf16(reinterpret_cast<const ushort*>(var.calpwstr.pElems[i])));
value = vList;
break;
}
return value;
}
@@ -147,13 +291,80 @@ void MFMetaDataControl::updateSource(IMFPresentationDescriptor* sourcePD, IMFMed
m_availableMetaDatas.push_back(QMediaMetaData::Author);
} else if (key == PKEY_Title) {
m_availableMetaDatas.push_back(QMediaMetaData::Title);
} else if (key == PKEY_Media_SubTitle) {
m_availableMetaDatas.push_back(QMediaMetaData::SubTitle);
} else if (key == PKEY_ParentalRating) {
m_availableMetaDatas.push_back(QMediaMetaData::ParentalRating);
} else if (key == PKEY_Comment) {
m_availableMetaDatas.push_back(QMediaMetaData::Description);
} else if (key == PKEY_Copyright) {
m_availableMetaDatas.push_back(QMediaMetaData::Copyright);
//TODO: add more common keys
} else if (key == PKEY_Comment) {
m_availableMetaDatas.push_back(QMediaMetaData::Comment);
} else if (key == PKEY_Media_ProviderStyle) {
m_availableMetaDatas.push_back(QMediaMetaData::Genre);
} else if (key == PKEY_Media_Year) {
m_availableMetaDatas.push_back(QMediaMetaData::Year);
} else if (key == PKEY_Media_DateEncoded) {
m_availableMetaDatas.push_back(QMediaMetaData::Date);
} else if (key == PKEY_Rating) {
m_availableMetaDatas.push_back(QMediaMetaData::UserRating);
} else if (key == PKEY_Keywords) {
m_availableMetaDatas.push_back(QMediaMetaData::Keywords);
} else if (key == PKEY_Language) {
m_availableMetaDatas.push_back(QMediaMetaData::Language);
} else if (key == PKEY_Media_Publisher) {
m_availableMetaDatas.push_back(QMediaMetaData::Publisher);
} else if (key == PKEY_Media_ClassPrimaryID) {
m_availableMetaDatas.push_back(QMediaMetaData::MediaType);
} else if (key == PKEY_Media_Duration) {
m_availableMetaDatas.push_back(QMediaMetaData::Duration);
} else if (key == PKEY_Audio_EncodingBitrate) {
m_availableMetaDatas.push_back(QMediaMetaData::AudioBitRate);
} else if (key == PKEY_Audio_Format) {
m_availableMetaDatas.push_back(QMediaMetaData::AudioCodec);
} else if (key == PKEY_Media_AverageLevel) {
m_availableMetaDatas.push_back(QMediaMetaData::AverageLevel);
} else if (key == PKEY_Audio_ChannelCount) {
m_availableMetaDatas.push_back(QMediaMetaData::ChannelCount);
} else if (key == PKEY_Audio_PeakValue) {
m_availableMetaDatas.push_back(QMediaMetaData::PeakValue);
} else if (key == PKEY_Audio_SampleRate) {
m_availableMetaDatas.push_back(QMediaMetaData::SampleRate);
} else if (key == PKEY_Music_AlbumTitle) {
m_availableMetaDatas.push_back(QMediaMetaData::AlbumTitle);
} else if (key == PKEY_Music_AlbumArtist) {
m_availableMetaDatas.push_back(QMediaMetaData::AlbumArtist);
} else if (key == PKEY_Music_Artist) {
m_availableMetaDatas.push_back(QMediaMetaData::ContributingArtist);
} else if (key == PKEY_Music_Composer) {
m_availableMetaDatas.push_back(QMediaMetaData::Composer);
} else if (key == PKEY_Music_Conductor) {
m_availableMetaDatas.push_back(QMediaMetaData::Conductor);
} else if (key == PKEY_Music_Lyrics) {
m_availableMetaDatas.push_back(QMediaMetaData::Lyrics);
} else if (key == PKEY_Music_Mood) {
m_availableMetaDatas.push_back(QMediaMetaData::Mood);
} else if (key == PKEY_Music_TrackNumber) {
m_availableMetaDatas.push_back(QMediaMetaData::TrackNumber);
} else if (key == PKEY_Music_Genre) {
m_availableMetaDatas.push_back(QMediaMetaData::Genre);
} else if (key == PKEY_ThumbnailStream) {
m_availableMetaDatas.push_back(QMediaMetaData::ThumbnailImage);
} else if (key == PKEY_Video_FrameHeight) {
m_availableMetaDatas.push_back(QMediaMetaData::Resolution);
} else if (key == PKEY_Video_HorizontalAspectRatio) {
m_availableMetaDatas.push_back(QMediaMetaData::PixelAspectRatio);
} else if (key == PKEY_Video_FrameRate) {
m_availableMetaDatas.push_back(QMediaMetaData::VideoFrameRate);
} else if (key == PKEY_Video_EncodingBitrate) {
m_availableMetaDatas.push_back(QMediaMetaData::VideoBitRate);
} else if (key == PKEY_Video_Compression) {
m_availableMetaDatas.push_back(QMediaMetaData::VideoCodec);
} else if (key == PKEY_Video_Director) {
m_availableMetaDatas.push_back(QMediaMetaData::Director);
} else if (key == PKEY_Media_Writer) {
m_availableMetaDatas.push_back(QMediaMetaData::Writer);
} else {
common = false;
//TODO: add more extended keys

View File

@@ -116,12 +116,11 @@ QMediaControl* MFPlayerService::requestControl(const char *name)
}
return 0;
} else if (qstrcmp(name,QMediaVideoProbeControl_iid) == 0) {
// FIXME!! Disabled in Qt 5.0 because it is unstable
// if (m_session) {
// MFVideoProbeControl *probe = new MFVideoProbeControl(this);
// m_session->addProbe(probe);
// return probe;
// }
if (m_session) {
MFVideoProbeControl *probe = new MFVideoProbeControl(this);
m_session->addProbe(probe);
return probe;
}
return 0;
}

View File

@@ -413,7 +413,7 @@ MFPlayerSession::MFPlayerSession(MFPlayerService *playerService)
, m_hCloseEvent(0)
, m_closing(false)
, m_pendingRate(1)
, m_volume(1)
, m_volume(100)
, m_muted(false)
, m_status(QMediaPlayer::NoMedia)
, m_scrubbing(false)
@@ -436,7 +436,6 @@ MFPlayerSession::MFPlayerSession(MFPlayerService *playerService)
m_request.rate = 1.0f;
m_audioSampleGrabber = new AudioSampleGrabberCallback;
m_videoProbeMFT = new MFTransform;
}
void MFPlayerSession::close()
@@ -472,6 +471,18 @@ void MFPlayerSession::close()
m_sourceResolver->Release();
m_sourceResolver = 0;
}
if (m_videoProbeMFT) {
m_videoProbeMFT->Release();
m_videoProbeMFT = 0;
}
if (m_playerService->videoRendererControl()) {
m_playerService->videoRendererControl()->releaseActivate();
#ifndef Q_WS_SIMULATOR
} else if (m_playerService->videoWindowControl()) {
m_playerService->videoWindowControl()->releaseActivate();
#endif
}
if (m_session)
m_session->Release();
@@ -493,18 +504,26 @@ void MFPlayerSession::removeProbe(MFAudioProbeControl *probe)
void MFPlayerSession::addProbe(MFVideoProbeControl* probe)
{
if (m_videoProbes.contains(probe))
return;
m_videoProbes.append(probe);
if (m_videoProbeMFT)
m_videoProbeMFT->addProbe(probe);
}
void MFPlayerSession::removeProbe(MFVideoProbeControl* probe)
{
m_videoProbes.removeOne(probe);
if (m_videoProbeMFT)
m_videoProbeMFT->removeProbe(probe);
}
MFPlayerSession::~MFPlayerSession()
{
m_audioSampleGrabber->Release();
m_videoProbeMFT->Release();
}
@@ -988,73 +1007,92 @@ IMFTopology *MFPlayerSession::insertMFT(IMFTopology *topology, TOPOID outputNode
if (FAILED(topoLoader->Load(topology, &resolvedTopology, NULL)))
break;
// FIXME!! VideoProbe disabled in Qt 5.0 because it is unstable.
// Commented out the following code to skip inserting the transform node
// getting the video frames.
// Get all output nodes and search for video output node.
// if (FAILED(resolvedTopology->GetOutputNodeCollection(&outputNodes)))
// break;
if (FAILED(resolvedTopology->GetOutputNodeCollection(&outputNodes)))
break;
// DWORD elementCount = 0;
// if (FAILED(outputNodes->GetElementCount(&elementCount)))
// break;
DWORD elementCount = 0;
if (FAILED(outputNodes->GetElementCount(&elementCount)))
break;
// for (DWORD n = 0; n < elementCount; n++) {
// IUnknown *element = 0;
// IMFTopologyNode *node = 0;
// IMFTopologyNode *inputNode = 0;
// IMFTopologyNode *mftNode = 0;
for (DWORD n = 0; n < elementCount; n++) {
IUnknown *element = 0;
IMFTopologyNode *node = 0;
IUnknown *outputObject = 0;
IMFMediaTypeHandler *videoSink = 0;
IMFTopologyNode *inputNode = 0;
IMFTopologyNode *mftNode = 0;
// do {
// if (FAILED(outputNodes->GetElement(n, &element)))
// break;
do {
if (FAILED(outputNodes->GetElement(n, &element)))
break;
// if (FAILED(element->QueryInterface(IID_IMFTopologyNode, (void**)&node)))
// break;
if (FAILED(element->QueryInterface(IID_IMFTopologyNode, (void**)&node)))
break;
// TOPOID id;
// if (FAILED(node->GetTopoNodeID(&id)))
// break;
TOPOID id;
if (FAILED(node->GetTopoNodeID(&id)))
break;
// if (id != outputNodeId)
// break;
if (id != outputNodeId)
break;
// // Insert MFT between the output node and the node connected to it.
// DWORD outputIndex = 0;
// if (FAILED(node->GetInput(0, &inputNode, &outputIndex)))
// break;
// Use output supported media types for the MFT
if (FAILED(node->GetObject(&outputObject)))
break;
// if (FAILED(MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &mftNode)))
// break;
if (FAILED(outputObject->QueryInterface(IID_IMFMediaTypeHandler, (void**)&videoSink)))
break;
// if (FAILED(mftNode->SetObject(m_videoProbeMFT)))
// break;
DWORD mtCount;
if (FAILED(videoSink->GetMediaTypeCount(&mtCount)))
break;
// if (FAILED(resolvedTopology->AddNode(mftNode)))
// break;
for (DWORD i = 0; i < mtCount; ++i) {
IMFMediaType *type = 0;
if (SUCCEEDED(videoSink->GetMediaTypeByIndex(i, &type)))
m_videoProbeMFT->addSupportedMediaType(type);
}
// if (FAILED(inputNode->ConnectOutput(0, mftNode, 0)))
// break;
// Insert MFT between the output node and the node connected to it.
DWORD outputIndex = 0;
if (FAILED(node->GetInput(0, &inputNode, &outputIndex)))
break;
// if (FAILED(mftNode->ConnectOutput(0, node, 0)))
// break;
if (FAILED(MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &mftNode)))
break;
// isNewTopology = true;
// } while (false);
if (FAILED(mftNode->SetObject(m_videoProbeMFT)))
break;
// if (mftNode)
// mftNode->Release();
// if (inputNode)
// inputNode->Release();
// if (node)
// node->Release();
// if (element)
// element->Release();
if (FAILED(resolvedTopology->AddNode(mftNode)))
break;
// if (isNewTopology)
// break;
// }
if (FAILED(inputNode->ConnectOutput(0, mftNode, 0)))
break;
if (FAILED(mftNode->ConnectOutput(0, node, 0)))
break;
isNewTopology = true;
} while (false);
if (mftNode)
mftNode->Release();
if (inputNode)
inputNode->Release();
if (node)
node->Release();
if (element)
element->Release();
if (videoSink)
videoSink->Release();
if (outputObject)
outputObject->Release();
if (isNewTopology)
break;
}
} while (false);
if (outputNodes)
@@ -1181,6 +1219,10 @@ void MFPlayerSession::createSession()
QObject::connect(m_sourceResolver, SIGNAL(mediaSourceReady()), this, SLOT(handleMediaSourceReady()));
QObject::connect(m_sourceResolver, SIGNAL(error(long)), this, SLOT(handleSourceError(long)));
m_videoProbeMFT = new MFTransform;
for (int i = 0; i < m_videoProbes.size(); ++i)
m_videoProbeMFT->addProbe(m_videoProbes.at(i));
Q_ASSERT(m_session == NULL);
HRESULT hr = MFCreateMediaSession(NULL, &m_session);
if (FAILED(hr)) {
@@ -1569,7 +1611,9 @@ void MFPlayerSession::handleSessionEvent(IMFMediaEvent *sessionEvent)
break;
case MESourceUnknown:
changeStatus(QMediaPlayer::InvalidMedia);
break;
case MEError:
changeStatus(QMediaPlayer::UnknownMediaStatus);
qWarning() << "handleSessionEvent: serious error = " << hrStatus;
emit error(QMediaPlayer::ResourceError, tr("Media session serious error."), true);
break;
@@ -1640,7 +1684,7 @@ void MFPlayerSession::handleSessionEvent(IMFMediaEvent *sessionEvent)
}
if (SUCCEEDED(MFGetService(m_session, MR_POLICY_VOLUME_SERVICE, IID_PPV_ARGS(&m_volumeControl)))) {
m_volumeControl->SetMasterVolume(m_volume);
m_volumeControl->SetMasterVolume(m_volume * 0.01f);
m_volumeControl->SetMute(m_muted);
}
@@ -1692,9 +1736,10 @@ void MFPlayerSession::handleSessionEvent(IMFMediaEvent *sessionEvent)
if (m_volumeControl) {
float currentVolume = 1;
if (SUCCEEDED(m_volumeControl->GetMasterVolume(&currentVolume))) {
if (currentVolume != m_volume) {
m_volume = currentVolume;
emit volumeChanged(int(m_volume * 100));
int scaledVolume = currentVolume * 100;
if (scaledVolume != m_volume) {
m_volume = scaledVolume;
emit volumeChanged(scaledVolume);
}
}
BOOL currentMuted = FALSE;

View File

@@ -232,6 +232,7 @@ private:
IMFTopology *insertMFT(IMFTopology *topology, TOPOID outputNodeId);
MFTransform *m_videoProbeMFT;
QList<MFVideoProbeControl*> m_videoProbes;
};

View File

@@ -318,6 +318,7 @@ namespace
, m_prerollTargetTime(0)
, m_startTime(0)
, m_rendererControl(rendererControl)
, m_rate(1.f)
{
m_sink = parent;
@@ -1780,6 +1781,7 @@ namespace
, m_sink(0)
, m_rendererControl(rendererControl)
, m_attributes(0)
, m_surface(0)
{
MFCreateAttributes(&m_attributes, 0);
m_sink = new MediaSink(rendererControl);
@@ -2142,6 +2144,9 @@ MFVideoRendererControl::~MFVideoRendererControl()
void MFVideoRendererControl::clear()
{
if (m_surface)
m_surface->stop();
if (m_currentActivate) {
m_currentActivate->ShutdownObject();
m_currentActivate->Release();
@@ -2149,6 +2154,11 @@ void MFVideoRendererControl::clear()
m_currentActivate = NULL;
}
void MFVideoRendererControl::releaseActivate()
{
clear();
}
QAbstractVideoSurface *MFVideoRendererControl::surface() const
{
return m_surface;
@@ -2208,10 +2218,8 @@ IMFActivate* MFVideoRendererControl::createActivate()
clear();
m_currentActivate = new VideoRendererActivate(this);
if (m_surface) {
if (m_surface)
setSurface(m_surface);
supportedFormatsChanged();
}
return m_currentActivate;
}

View File

@@ -59,6 +59,7 @@ public:
void setSurface(QAbstractVideoSurface *surface);
IMFActivate* createActivate();
void releaseActivate();
protected:
void customEvent(QEvent *event);