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_*
!tst_*.cpp !tst_*.cpp
tests/auto/cmake/build 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 \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 All that remains is to connect the afterRendering() signal of the QQuickView
object to a JavaScript function, which will eventually call frequencyItem.notify(): object to a JavaScript function, which will eventually call frequencyItem.notify():
\quotefromfile multimedia/video/qmlvideo/main.cpp \quotefromfile multimedia/video/qmlvideo/main.cpp
\skipto QmlApplicationViewer \skipto QGuiApplication
\printuntil ; \printuntil ;
\dots \dots
\skipto QQuickItem \skipto QQuickItem

View File

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

View File

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

View File

@@ -41,36 +41,18 @@
#include "filereader.h" #include "filereader.h"
#include "trace.h" #include "trace.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QTextStream>
QString adjustPath(const QString &path) #include <QCoreApplication>
{ #include <QDir>
#ifdef Q_OS_UNIX #include <QFile>
#ifdef Q_OS_MAC #include <QFileInfo>
if (!QDir::isAbsolutePath(path)) #include <QTextStream>
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;
}
QString FileReader::readFile(const QString &fileName) QString FileReader::readFile(const QString &fileName)
{ {
qtTrace() << "FileReader::readFile" << "fileName" << fileName; qtTrace() << "FileReader::readFile" << "fileName" << fileName;
QString content; QString content;
QFile file(adjustPath(fileName)); QFile file(fileName);
if (file.open(QIODevice::ReadOnly)) { if (file.open(QIODevice::ReadOnly)) {
QTextStream stream(&file); QTextStream stream(&file);
content = stream.readAll(); content = stream.readAll();

View File

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

View File

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

View File

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

View File

@@ -55,5 +55,5 @@ Effect {
property real step_x: 0.0015625 property real step_x: 0.0015625
property real step_y: targetHeight ? (step_x * targetWidth / targetHeight) : 0.0 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 // Transform slider values, and bind result to shader uniforms
property real threshold: parameters.get(0).value property real threshold: parameters.get(0).value
fragmentShaderFilename: "shaders/blackandwhite.fsh" fragmentShaderFilename: "blackandwhite.fsh"
} }

View File

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

View File

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

View File

@@ -42,5 +42,5 @@
import QtQuick 2.0 import QtQuick 2.0
Effect { 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 targetHue: parameters.get(0).value * 360
property real windowWidth: parameters.get(1).value * 60 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 d.oldTargetHeight = targetHeight
} }
fragmentShaderFilename: "shaders/magnify.fsh" fragmentShaderFilename: "magnify.fsh"
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent

View File

@@ -53,5 +53,5 @@ Effect {
// Transform slider values, and bind result to shader uniforms // Transform slider values, and bind result to shader uniforms
property real curlExtent: 1.0 - parameters.get(0).value 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 // Transform slider values, and bind result to shader uniforms
property real granularity: parameters.get(0).value * 20 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 property real numColors: 8.0
fragmentShaderFilename: "shaders/posterize.fsh" fragmentShaderFilename: "posterize.fsh"
} }

View File

@@ -60,5 +60,5 @@ Effect {
property real time: 0 property real time: 0
NumberAnimation on time { loops: Animation.Infinite; from: 0; to: Math.PI * 2; duration: 600 } 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 import QtQuick 2.0
Effect { Effect {
fragmentShaderFilename: "shaders/sepia.fsh" fragmentShaderFilename: "sepia.fsh"
} }

View File

@@ -52,5 +52,5 @@ Effect {
// Transform slider values, and bind result to shader uniforms // Transform slider values, and bind result to shader uniforms
property real amount: parameters.get(0).value * 18 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 resS: targetSize
property real resT: 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 // Transform slider values, and bind result to shader uniforms
property real weight: parameters.get(0).value property real weight: parameters.get(0).value
fragmentShaderFilename: "shaders/sobeledgedetection2.fsh" fragmentShaderFilename: "sobeledgedetection2.fsh"
} }

View File

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

View File

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

View File

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

View File

@@ -42,5 +42,5 @@
import QtQuick 2.0 import QtQuick 2.0
Effect { 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 } 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 QT += quick
LOCAL_SOURCES = filereader.cpp main.cpp SOURCES += filereader.cpp main.cpp
LOCAL_HEADERS = filereader.h trace.h HEADERS += filereader.h trace.h
SOURCES += $$LOCAL_SOURCES
HEADERS += $$LOCAL_HEADERS
RESOURCES += qmlvideofx.qrc RESOURCES += qmlvideofx.qrc
SNIPPETS_PATH = ../snippets include($$PWD/../snippets/performancemonitor/performancemonitordeclarative.pri)
include($$SNIPPETS_PATH/performancemonitor/performancemonitordeclarative.pri)
maemo6: { maemo6: {
DEFINES += SMALL_SCREEN_LAYOUT DEFINES += SMALL_SCREEN_LAYOUT

View File

@@ -44,5 +44,28 @@
<file>qml/qmlvideofx/main-smallscreen.qml</file> <file>qml/qmlvideofx/main-smallscreen.qml</file>
<file>qml/qmlvideofx/ParameterPanel.qml</file> <file>qml/qmlvideofx/ParameterPanel.qml</file>
<file>qml/qmlvideofx/Slider.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> </qresource>
</RCC> </RCC>

View File

@@ -42,7 +42,7 @@
#ifndef TRACE_H #ifndef TRACE_H
#define TRACE_H #define TRACE_H
#include <QtCore/QDebug> #include <QDebug>
#define ENABLE_TRACE #define ENABLE_TRACE
//#define VERBOSE_TRACE //#define VERBOSE_TRACE
@@ -74,12 +74,6 @@ inline QDebug& operator<<(QDebug &debug, const Trace::PtrWrapper<T> &wrapper)
return debug.space(); 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 #ifdef ENABLE_TRACE
inline QDebug qtTrace() { return qDebug() << "[qmlvideofx]"; } inline QDebug qtTrace() { return qDebug() << "[qmlvideofx]"; }
# ifdef VERBOSE_TRACE # ifdef VERBOSE_TRACE

View File

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

View File

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

View File

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

View File

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

View File

@@ -4,6 +4,7 @@ TARGET=declarative-camera
QT += quick qml multimedia QT += quick qml multimedia
SOURCES += qmlcamera.cpp SOURCES += qmlcamera.cpp
RESOURCES += declarative-camera.qrc
target.path = $$[QT_INSTALL_EXAMPLES]/multimediawidgets/declarative-camera target.path = $$[QT_INSTALL_EXAMPLES]/multimediawidgets/declarative-camera
INSTALLS += target 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 // Qt.quit() called in embedded .qml by default only emits
// quit() signal, so do this (optionally use Qt.exit()). // quit() signal, so do this (optionally use Qt.exit()).
QObject::connect(view.engine(), SIGNAL(quit()), qApp, SLOT(quit())); QObject::connect(view.engine(), SIGNAL(quit()), qApp, SLOT(quit()));
view.setSource(QUrl::fromLocalFile(QCoreApplication::applicationDirPath() + view.setSource(QUrl("qrc:///declarative-camera.qml"));
QLatin1String("/declarative-camera.qml")));
view.resize(800, 480); view.resize(800, 480);
view.show(); view.show();
return app.exec(); return app.exec();

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,7 +3,7 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
project = qtmultimedia project = qtmultimedia
description = Qt Multimedia Documentation description = Qt Multimedia Documentation
url = http://qt-project.org/doc/qtmultimedia 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 # 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 # 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 turns a stream of events (received via the notify() slot), into an
instantaneous and an averaged frequency: instantaneous and an averaged frequency:
\quotefromfile video/snippets/frequencymonitor/frequencymonitor.h \quotefromfile multimedia/video/snippets/frequencymonitor/frequencymonitor.h
\skipto class FrequencyMonitor : public QObject \skipto class FrequencyMonitor : public QObject
\printuntil Q_OBJECT \printuntil Q_OBJECT
\skipto Q_PROPERTY(qreal instantaneousFrequency \skipto Q_PROPERTY(qreal instantaneousFrequency
@@ -19,13 +19,13 @@ instantaneous and an averaged frequency:
The FrequencyMonitor class is exposed to QML like this 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 \skipto FrequencyMonitor::qmlRegisterType
\printuntil } \printuntil }
and its data is displayed by defining a QML item called FrequencyItem, like this: 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 \skipto import FrequencyMonitor
\printuntil id: root \printuntil id: root
\dots \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 TARGET = QtMultimedia
QT = core-private network gui QT = core-private network gui
contains(QT_CONFIG, opengl) | contains(QT_CONFIG, opengles2) {
} else {
DEFINES += QT_NO_OPENGL
}
QMAKE_DOCS = $$PWD/doc/qtmultimedia.qdocconf QMAKE_DOCS = $$PWD/doc/qtmultimedia.qdocconf
load(qt_module) load(qt_module)

View File

@@ -257,8 +257,8 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe
NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo]; NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];
if ([tracks count]) { if ([tracks count]) {
AVAssetTrack *videoTrack = [tracks objectAtIndex:0]; AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
m_playerLayer.anchorPoint = NSMakePoint(0.0f, 0.0f); m_playerLayer.anchorPoint = CGPointMake(0.0f, 0.0f);
m_playerLayer.bounds = NSMakeRect(0.0f, 0.0f, videoTrack.naturalSize.width, videoTrack.naturalSize.height); 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]; NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];
if ([tracks count]) { if ([tracks count]) {
AVAssetTrack *videoTrack = [tracks objectAtIndex:0]; AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
m_playerLayer.anchorPoint = NSMakePoint(0.0f, 0.0f); m_playerLayer.anchorPoint = CGPointMake(0.0f, 0.0f);
m_playerLayer.bounds = NSMakeRect(0.0f, 0.0f, videoTrack.naturalSize.width, videoTrack.naturalSize.height); 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() 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_nativeSize = QSize(layerBounds.size.width, layerBounds.size.height);
m_videoWidget->setNativeSize(m_nativeSize); m_videoWidget->setNativeSize(m_nativeSize);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -47,6 +47,7 @@
#include <uuids.h> #include <uuids.h>
#include <InitGuid.h> #include <InitGuid.h>
#include <d3d9.h> #include <d3d9.h>
#include <qdebug.h>
// This MFT sends all samples it processes to connected video probes. // This MFT sends all samples it processes to connected video probes.
// Sample is sent to probes in ProcessInput. // Sample is sent to probes in ProcessInput.
@@ -70,6 +71,9 @@ MFTransform::~MFTransform()
if (m_outputType) if (m_outputType)
m_outputType->Release(); m_outputType->Release();
for (int i = 0; i < m_mediaTypes.size(); ++i)
m_mediaTypes[i]->Release();
} }
void MFTransform::addProbe(MFVideoProbeControl *probe) void MFTransform::addProbe(MFVideoProbeControl *probe)
@@ -88,6 +92,14 @@ void MFTransform::removeProbe(MFVideoProbeControl *probe)
m_videoProbes.removeOne(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) STDMETHODIMP MFTransform::QueryInterface(REFIID riid, void** ppv)
{ {
if (!ppv) if (!ppv)
@@ -151,6 +163,8 @@ STDMETHODIMP MFTransform::GetStreamIDs(DWORD dwInputIDArraySize, DWORD *pdwInput
STDMETHODIMP MFTransform::GetInputStreamInfo(DWORD dwInputStreamID, MFT_INPUT_STREAM_INFO *pStreamInfo) STDMETHODIMP MFTransform::GetInputStreamInfo(DWORD dwInputStreamID, MFT_INPUT_STREAM_INFO *pStreamInfo)
{ {
QMutexLocker locker(&m_mutex);
if (dwInputStreamID > 0) if (dwInputStreamID > 0)
return MF_E_INVALIDSTREAMNUMBER; 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) STDMETHODIMP MFTransform::GetOutputStreamInfo(DWORD dwOutputStreamID, MFT_OUTPUT_STREAM_INFO *pStreamInfo)
{ {
QMutexLocker locker(&m_mutex);
if (dwOutputStreamID > 0) if (dwOutputStreamID > 0)
return MF_E_INVALIDSTREAMNUMBER; return MF_E_INVALIDSTREAMNUMBER;
@@ -243,16 +259,27 @@ STDMETHODIMP MFTransform::SetInputType(DWORD dwInputStreamID, IMFMediaType *pTyp
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
DWORD flags = 0; if (m_sample)
if (m_outputType && m_outputType->IsEqual(pType, &flags) != S_OK) { 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; return MF_E_INVALIDMEDIATYPE;
}
if (dwFlags == MFT_SET_TYPE_TEST_ONLY) if (dwFlags == MFT_SET_TYPE_TEST_ONLY)
return pType ? S_OK : E_POINTER; return pType ? S_OK : E_POINTER;
if (m_inputType) if (m_inputType) {
m_inputType->Release(); 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; m_inputType = pType;
@@ -269,16 +296,27 @@ STDMETHODIMP MFTransform::SetOutputType(DWORD dwOutputStreamID, IMFMediaType *pT
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
DWORD flags = 0; if (m_sample)
if (m_inputType && m_inputType->IsEqual(pType, &flags) != S_OK) { 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; return MF_E_INVALIDMEDIATYPE;
}
if (dwFlags == MFT_SET_TYPE_TEST_ONLY) if (dwFlags == MFT_SET_TYPE_TEST_ONLY)
return pType ? S_OK : E_POINTER; return pType ? S_OK : E_POINTER;
if (m_outputType) if (m_outputType) {
m_outputType->Release(); 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; m_outputType = pType;
@@ -645,3 +683,19 @@ QByteArray MFTransform::dataFromBuffer(IMFMediaBuffer *buffer, int height, int *
return array; 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 addProbe(MFVideoProbeControl* probe);
void removeProbe(MFVideoProbeControl* probe); void removeProbe(MFVideoProbeControl* probe);
void addSupportedMediaType(IMFMediaType *type);
// IUnknown methods // IUnknown methods
STDMETHODIMP QueryInterface(REFIID iid, void** ppv); STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) AddRef();
@@ -97,6 +99,7 @@ private:
static QVideoSurfaceFormat videoFormatForMFMediaType(IMFMediaType *mediaType, int *bytesPerLine); static QVideoSurfaceFormat videoFormatForMFMediaType(IMFMediaType *mediaType, int *bytesPerLine);
QVideoFrame makeVideoFrame(); QVideoFrame makeVideoFrame();
QByteArray dataFromBuffer(IMFMediaBuffer *buffer, int height, int *bytesPerLine); QByteArray dataFromBuffer(IMFMediaBuffer *buffer, int height, int *bytesPerLine);
bool isMediaTypeSupported(IMFMediaType *type);
long m_cRef; long m_cRef;
IMFMediaType *m_inputType; IMFMediaType *m_inputType;
@@ -104,6 +107,8 @@ private:
IMFSample *m_sample; IMFSample *m_sample;
QMutex m_mutex; QMutex m_mutex;
QList<IMFMediaType*> m_mediaTypes;
QList<MFVideoProbeControl*> m_videoProbes; QList<MFVideoProbeControl*> m_videoProbes;
QMutex m_videoProbeMutex; QMutex m_videoProbeMutex;

View File

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

View File

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

View File

@@ -39,12 +39,95 @@
** **
****************************************************************************/ ****************************************************************************/
#include <qdatetime.h>
#include <qimage.h>
#include "mfmetadatacontrol.h" #include "mfmetadatacontrol.h"
#include "mfplayerservice.h" #include "mfplayerservice.h"
#include "Propkey.h" #include "Propkey.h"
//#define DEBUG_MEDIAFOUNDATION //#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) MFMetaDataControl::MFMetaDataControl(QObject *parent)
: QMetaDataReaderControl(parent) : QMetaDataReaderControl(parent)
, m_metaData(0) , m_metaData(0)
@@ -83,9 +166,46 @@ QVariant MFMetaDataControl::metaData(const QString &key) const
else if (m_metaData) else if (m_metaData)
hr = m_metaData->GetProperty(reinterpret_cast<LPCWSTR>(m_commonNames[index].utf16()), &var); hr = m_metaData->GetProperty(reinterpret_cast<LPCWSTR>(m_commonNames[index].utf16()), &var);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr)) {
value = convertValue(var); 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); PropVariantClear(&var);
return value; return value;
} }
@@ -93,9 +213,6 @@ QVariant MFMetaDataControl::metaData(const QString &key) const
QVariant MFMetaDataControl::convertValue(const PROPVARIANT& var) const QVariant MFMetaDataControl::convertValue(const PROPVARIANT& var) const
{ {
QVariant value; 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) { switch (var.vt) {
case VT_LPWSTR: case VT_LPWSTR:
value = QString::fromUtf16(reinterpret_cast<const ushort*>(var.pwszVal)); value = QString::fromUtf16(reinterpret_cast<const ushort*>(var.pwszVal));
@@ -109,6 +226,33 @@ QVariant MFMetaDataControl::convertValue(const PROPVARIANT& var) const
case VT_BOOL: case VT_BOOL:
value = bool(var.boolVal); value = bool(var.boolVal);
break; 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; return value;
} }
@@ -147,13 +291,80 @@ void MFMetaDataControl::updateSource(IMFPresentationDescriptor* sourcePD, IMFMed
m_availableMetaDatas.push_back(QMediaMetaData::Author); m_availableMetaDatas.push_back(QMediaMetaData::Author);
} else if (key == PKEY_Title) { } else if (key == PKEY_Title) {
m_availableMetaDatas.push_back(QMediaMetaData::Title); m_availableMetaDatas.push_back(QMediaMetaData::Title);
} else if (key == PKEY_Media_SubTitle) {
m_availableMetaDatas.push_back(QMediaMetaData::SubTitle);
} else if (key == PKEY_ParentalRating) { } else if (key == PKEY_ParentalRating) {
m_availableMetaDatas.push_back(QMediaMetaData::ParentalRating); m_availableMetaDatas.push_back(QMediaMetaData::ParentalRating);
} else if (key == PKEY_Comment) { } else if (key == PKEY_Comment) {
m_availableMetaDatas.push_back(QMediaMetaData::Description); m_availableMetaDatas.push_back(QMediaMetaData::Description);
} else if (key == PKEY_Copyright) { } else if (key == PKEY_Copyright) {
m_availableMetaDatas.push_back(QMediaMetaData::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 { } else {
common = false; common = false;
//TODO: add more extended keys //TODO: add more extended keys

View File

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

View File

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

View File

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

View File

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

View File

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