diff options
author | Yoann Lopes <yoann.lopes@digia.com> | 2013-09-03 14:35:46 +0200 |
---|---|---|
committer | Yoann Lopes <yoann.lopes@digia.com> | 2013-09-03 14:36:20 +0200 |
commit | 8c573d20999e8af0c1beca7e5256202de207e736 (patch) | |
tree | 692baf68340d61e55ba092f42ccb8406c09288f5 | |
parent | 39c7b87c4930f9eb3b2fd51b8e99381710e12d99 (diff) | |
parent | 71808302a572e622c20095726d74beaef152a9bc (diff) | |
download | qtmultimedia-8c573d20999e8af0c1beca7e5256202de207e736.tar.gz |
Merge branch 'dev' into wip/android
Change-Id: Idd0c4a5a88b1a2b876220f4e46262337320dccae
33 files changed, 283 insertions, 747 deletions
diff --git a/dist/changes-5.1.1 b/dist/changes-5.1.1 new file mode 100644 index 000000000..45fc4ded5 --- /dev/null +++ b/dist/changes-5.1.1 @@ -0,0 +1,45 @@ +Qt 5.1.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.1.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.1/ + +The Qt version 5.1 series is binary compatible with the 5.0.x series. +Applications compiled for 5.0 will continue to run with 5.1. + +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. + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Qt for Windows +-------------- + + - Use correct default audio output and input devices on Windows. + - [QTBUG-29206] DirectShow: avoid unnecessary RGB32 -> BGR32 conversion. + - [QTBUG-32282] DirectShow: Don't create the widget and renderer controls + until requested. + - [QTBUG-23822] Fix resource leak in directshow plugin. + - WMF: fixed MediaPlayer buffering logic. + +Qt for Android +-------------- + + - Fixed potential memory leak when destroying a media player. + - Fixed media player showing black frames on some hardware. + - [QTBUG-31422] Make it possible for the media player to play assets. + - Fixed Java exception being thrown at app startup when using multimedia. + +Qt for BlackBerry +----------------- + + - [QTBUG-31534] Fix frame size of video playback. diff --git a/examples/multimedia/video/qmlvideofx/main.cpp b/examples/multimedia/video/qmlvideofx/main.cpp index b0698e236..7465deab8 100644 --- a/examples/multimedia/video/qmlvideofx/main.cpp +++ b/examples/multimedia/video/qmlvideofx/main.cpp @@ -116,21 +116,13 @@ int main(int argc, char *argv[]) FileReader fileReader; viewer.rootContext()->setContextProperty("fileReader", &fileReader); - QUrl appPath(QString("file://%1").arg(app.applicationDirPath())); - QUrl imagePath; + const QUrl appPath(QUrl::fromLocalFile(app.applicationDirPath())); const QStringList picturesLocation = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation); - if (picturesLocation.isEmpty()) - imagePath = appPath.resolved(QUrl("images")); - else - imagePath = QString("file://%1").arg(picturesLocation.first()); + const QUrl imagePath = picturesLocation.isEmpty() ? appPath : QUrl::fromLocalFile(picturesLocation.first()); viewer.rootContext()->setContextProperty("imagePath", imagePath); - QUrl videoPath; const QStringList moviesLocation = QStandardPaths::standardLocations(QStandardPaths::MoviesLocation); - if (moviesLocation.isEmpty()) - videoPath = appPath.resolved(QUrl("./")); - else - videoPath = QString("file://%1").arg(moviesLocation.first()); + const QUrl videoPath = moviesLocation.isEmpty() ? appPath : QUrl::fromLocalFile(moviesLocation.first()); viewer.rootContext()->setContextProperty("videoPath", videoPath); viewer.setTitle("qmlvideofx"); diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileBrowser.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileBrowser.qml index 3d4343c25..7c8610361 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileBrowser.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileBrowser.qml @@ -102,7 +102,10 @@ Rectangle { Rectangle { id: wrapper function launch() { - var path = "file://" + filePath + var path = "file://"; + if (filePath.length > 2 && filePath[1] === ':') // Windows drive logic, see QUrl::fromLocalFile() + path += '/'; + path += filePath; if (folders.isFolder(index)) down(path); else @@ -307,7 +310,7 @@ Rectangle { MouseArea { id: upRegion; anchors.centerIn: parent width: 56 height: 56 - onClicked: if (folders.parentFolder != "") up() + onClicked: up() } states: [ State { @@ -353,6 +356,8 @@ Rectangle { function up() { var path = folders.parentFolder; + if (path.toString().length === 0 || path.toString() === 'file:') + return; if (folders == folders1) { view = view2 folders = folders2; diff --git a/src/gsttools/qgstreamerbushelper.cpp b/src/gsttools/qgstreamerbushelper.cpp index 5ead1080c..da7506ec4 100644 --- a/src/gsttools/qgstreamerbushelper.cpp +++ b/src/gsttools/qgstreamerbushelper.cpp @@ -118,7 +118,9 @@ private: guint m_tag; GstBus* m_bus; QGstreamerBusHelper* m_helper; +#ifdef QT_NO_GLIB QTimer* m_intervalTimer; +#endif private slots: void doProcessMessage(const QGstreamerMessage& msg) diff --git a/src/gsttools/qvideosurfacegstsink.cpp b/src/gsttools/qvideosurfacegstsink.cpp index 94aa1262e..f91c1192d 100644 --- a/src/gsttools/qvideosurfacegstsink.cpp +++ b/src/gsttools/qvideosurfacegstsink.cpp @@ -713,13 +713,14 @@ QVideoSurfaceFormat QVideoSurfaceGstSink::formatForCaps(GstCaps *caps, int *byte void QVideoSurfaceGstSink::setFrameTimeStamps(QVideoFrame *frame, GstBuffer *buffer) { + // GStreamer uses nanoseconds, Qt uses microseconds qint64 startTime = GST_BUFFER_TIMESTAMP(buffer); if (startTime >= 0) { - frame->setStartTime(startTime/G_GINT64_CONSTANT (1000000)); + frame->setStartTime(startTime/G_GINT64_CONSTANT (1000)); qint64 duration = GST_BUFFER_DURATION(buffer); if (duration >= 0) - frame->setEndTime((startTime + duration)/G_GINT64_CONSTANT (1000000)); + frame->setEndTime((startTime + duration)/G_GINT64_CONSTANT (1000)); } } diff --git a/src/multimedia/audio/qsoundeffect_qaudio_p.cpp b/src/multimedia/audio/qsoundeffect_qaudio_p.cpp index 835f60b45..524c856a2 100644 --- a/src/multimedia/audio/qsoundeffect_qaudio_p.cpp +++ b/src/multimedia/audio/qsoundeffect_qaudio_p.cpp @@ -369,7 +369,7 @@ void PrivateSoundSource::stateChanged(QAudio::State state) qint64 PrivateSoundSource::readData( char* data, qint64 len) { - if (m_runningCount > 0 && m_playing) { + if ((m_runningCount > 0 || m_runningCount == QSoundEffect::Infinite) && m_playing) { if (m_sample->state() != QSample::Ready) return 0; diff --git a/src/multimedia/gsttools_headers/qgstxvimagebuffer_p.h b/src/multimedia/gsttools_headers/qgstxvimagebuffer_p.h index 52efee8a3..30cc4c993 100644 --- a/src/multimedia/gsttools_headers/qgstxvimagebuffer_p.h +++ b/src/multimedia/gsttools_headers/qgstxvimagebuffer_p.h @@ -74,7 +74,8 @@ QT_BEGIN_NAMESPACE class QGstXvImageBufferPool; -struct QGstXvImageBuffer { +class QGstXvImageBuffer { +public: GstBuffer buffer; QGstXvImageBufferPool *pool; XvImage *xvImage; diff --git a/src/multimedia/multimedia.pro b/src/multimedia/multimedia.pro index 440bd6849..8df8118dd 100644 --- a/src/multimedia/multimedia.pro +++ b/src/multimedia/multimedia.pro @@ -66,9 +66,6 @@ ANDROID_BUNDLED_FILES += \ MODULE_PLUGIN_TYPES = \ mediaservice -mac { - LIBS += -framework AppKit -framework QuartzCore -framework QTKit -} win32:LIBS += -luuid HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS diff --git a/src/multimediawidgets/multimediawidgets.pro b/src/multimediawidgets/multimediawidgets.pro index c6f214679..d47742028 100644 --- a/src/multimediawidgets/multimediawidgets.pro +++ b/src/multimediawidgets/multimediawidgets.pro @@ -28,14 +28,6 @@ SOURCES += \ qvideowidgetcontrol.cpp \ qvideowidget.cpp -mac:!ios { - !simulator { - PRIVATE_HEADERS += qpaintervideosurface_mac_p.h - OBJECTIVE_SOURCES += qpaintervideosurface_mac.mm - } - LIBS += -framework AppKit -framework QuartzCore -framework QTKit -} - maemo6 { contains(QT_CONFIG, opengles2) { PRIVATE_HEADERS += qeglimagetexturesurface_p.h diff --git a/src/multimediawidgets/qpaintervideosurface.cpp b/src/multimediawidgets/qpaintervideosurface.cpp index e925f577f..8536ba4d1 100644 --- a/src/multimediawidgets/qpaintervideosurface.cpp +++ b/src/multimediawidgets/qpaintervideosurface.cpp @@ -40,7 +40,6 @@ ****************************************************************************/ #include "qpaintervideosurface_p.h" -#include "qpaintervideosurface_mac_p.h" #include <qmath.h> @@ -51,6 +50,7 @@ #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) #include <qglshaderprogram.h> #include <QtGui/QOpenGLContext> +#include <QtGui/QWindow> #ifndef GL_CLAMP_TO_EDGE #define GL_CLAMP_TO_EDGE 0x812F #endif @@ -1196,8 +1196,8 @@ QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::paint( if (scissorTestEnabled) glEnable(GL_SCISSOR_TEST); - const int width = QGLContext::currentContext()->device()->width(); - const int height = QGLContext::currentContext()->device()->height(); + const int width = QOpenGLContext::currentContext()->surface()->size().width(); + const int height = QOpenGLContext::currentContext()->surface()->size().height(); const QTransform transform = painter->deviceTransform(); @@ -1667,14 +1667,6 @@ void QPainterVideoSurface::createPainter() { Q_ASSERT(!m_painter); -#ifdef Q_OS_MAC - if (m_glContext) - m_glContext->makeCurrent(); - - m_painter = new QVideoSurfaceCoreGraphicsPainter(m_glContext != 0); - return; -#endif - #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) switch (m_shaderType) { #ifndef QT_OPENGL_ES diff --git a/src/multimediawidgets/qpaintervideosurface_mac.mm b/src/multimediawidgets/qpaintervideosurface_mac.mm deleted file mode 100644 index 9c076d041..000000000 --- a/src/multimediawidgets/qpaintervideosurface_mac.mm +++ /dev/null @@ -1,289 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <AppKit/AppKit.h> -#include <QuartzCore/CIContext.h> -#include <CGLCurrent.h> -#include <OpenGL/gl.h> - -#include "qpaintervideosurface_mac_p.h" - -#include <QtCore/qdatetime.h> - -#include <qmath.h> - -#include <qpainter.h> -#include <qvariant.h> -#include <qvideosurfaceformat.h> - -#include <QtDebug> - -QT_BEGIN_NAMESPACE - -extern CGContextRef qt_mac_cg_context(const QPaintDevice *pdev); //qpaintdevice_mac.cpp - -QVideoSurfaceCoreGraphicsPainter::QVideoSurfaceCoreGraphicsPainter(bool glSupported) - : ciContext(0) - , m_imageFormat(QImage::Format_Invalid) - , m_scanLineDirection(QVideoSurfaceFormat::TopToBottom) -{ - //qDebug() << "QVideoSurfaceCoreGraphicsPainter, GL supported:" << glSupported; - ciContext = 0; - m_imagePixelFormats - << QVideoFrame::Format_RGB32 - << QVideoFrame::Format_ARGB32 - << QVideoFrame::Format_ARGB32_Premultiplied - << QVideoFrame::Format_BGR32 - << QVideoFrame::Format_RGB24 - << QVideoFrame::Format_RGB565 - << QVideoFrame::Format_RGB555 - << QVideoFrame::Format_ARGB8565_Premultiplied; - - m_supportedHandles - << QAbstractVideoBuffer::NoHandle - << QAbstractVideoBuffer::CoreImageHandle; - - if (glSupported) - m_supportedHandles << QAbstractVideoBuffer::GLTextureHandle; -} - -QVideoSurfaceCoreGraphicsPainter::~QVideoSurfaceCoreGraphicsPainter() -{ - [(CIContext*)ciContext release]; -} - -QList<QVideoFrame::PixelFormat> QVideoSurfaceCoreGraphicsPainter::supportedPixelFormats( - QAbstractVideoBuffer::HandleType handleType) const -{ - return m_supportedHandles.contains(handleType) - ? m_imagePixelFormats - : QList<QVideoFrame::PixelFormat>(); -} - -bool QVideoSurfaceCoreGraphicsPainter::isFormatSupported(const QVideoSurfaceFormat &format) const -{ - return m_supportedHandles.contains(format.handleType()) - && m_imagePixelFormats.contains(format.pixelFormat()) - && !format.frameSize().isEmpty(); -} - -QAbstractVideoSurface::Error QVideoSurfaceCoreGraphicsPainter::start(const QVideoSurfaceFormat &format) -{ - m_frame = QVideoFrame(); - m_imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat()); - m_imageSize = format.frameSize(); - m_scanLineDirection = format.scanLineDirection(); - - return m_supportedHandles.contains(format.handleType()) - && ((m_imageFormat != QImage::Format_Invalid) || (format.handleType() == QAbstractVideoBuffer::GLTextureHandle)) - && !m_imageSize.isEmpty() - ? QAbstractVideoSurface::NoError - : QAbstractVideoSurface::UnsupportedFormatError; -} - -void QVideoSurfaceCoreGraphicsPainter::stop() -{ - m_frame = QVideoFrame(); -} - -QAbstractVideoSurface::Error QVideoSurfaceCoreGraphicsPainter::setCurrentFrame(const QVideoFrame &frame) -{ - m_frame = frame; - - return QAbstractVideoSurface::NoError; -} - -QAbstractVideoSurface::Error QVideoSurfaceCoreGraphicsPainter::paint( - const QRectF &target, QPainter *painter, const QRectF &source) -{ - if (m_frame.handleType() == QAbstractVideoBuffer::CoreImageHandle) { -//Non OpenGL CI rendering is disabled for now since qt_mac_cg_context is moved to platform plugin -#ifdef ENABLE_CORE_GRAPHICS_VIDEO_RENDERING - if (painter->paintEngine()->type() == QPaintEngine::CoreGraphics ) { - - CIImage *img = (CIImage*)(m_frame.handle().value<void*>()); - - if (img) { - CGContextRef cgContext = qt_mac_cg_context(painter->device()); - - if (cgContext) { - painter->beginNativePainting(); - - CGRect sRect = CGRectMake(source.x(), source.y(), source.width(), source.height()); - CGRect dRect = CGRectMake(target.x(), target.y(), target.width(), target.height()); - - NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithCIImage:img]; - - if (m_scanLineDirection == QVideoSurfaceFormat::TopToBottom) { - CGContextSaveGState( cgContext ); - CGContextTranslateCTM(cgContext, 0, dRect.origin.y + CGRectGetMaxY(dRect)); - CGContextScaleCTM(cgContext, 1, -1); - - CGContextDrawImage(cgContext, dRect, [bitmap CGImage]); - - CGContextRestoreGState(cgContext); - } else { - CGContextDrawImage(cgContext, dRect, [bitmap CGImage]); - } - - [bitmap release]; - - painter->endNativePainting(); - - return QAbstractVideoSurface::NoError; - } - } - } else -#endif - if (painter->paintEngine()->type() == QPaintEngine::OpenGL2 || - painter->paintEngine()->type() == QPaintEngine::OpenGL) { - CIImage *img = (CIImage*)(m_frame.handle().value<void*>()); - - if (img) { - CGLContextObj cglContext = CGLGetCurrentContext(); - - if (cglContext) { - - if (!ciContext) { - CGLContextObj cglContext = CGLGetCurrentContext(); - NSOpenGLPixelFormat *nsglPixelFormat = [NSOpenGLView defaultPixelFormat]; - CGLPixelFormatObj cglPixelFormat = static_cast<CGLPixelFormatObj>([nsglPixelFormat CGLPixelFormatObj]); - - ciContext = [CIContext contextWithCGLContext:cglContext - pixelFormat:cglPixelFormat - options:nil]; - - [(CIContext*)ciContext retain]; - } - - CGRect sRect = CGRectMake(source.x(), source.y(), source.width(), source.height()); - CGRect dRect = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom ? - CGRectMake(target.x(), target.y()+target.height(), target.width(), -target.height()) : - CGRectMake(target.x(), target.y(), target.width(), target.height()); - - - painter->beginNativePainting(); - - [(CIContext*)ciContext drawImage:img inRect:dRect fromRect:sRect]; - - painter->endNativePainting(); - - return QAbstractVideoSurface::NoError; - } - } - } - } - - if (m_frame.handleType() == QAbstractVideoBuffer::GLTextureHandle && - (painter->paintEngine()->type() == QPaintEngine::OpenGL2 || - painter->paintEngine()->type() == QPaintEngine::OpenGL)) { - - painter->beginNativePainting(); - GLuint texture = m_frame.handle().toUInt(); - - glDisable(GL_CULL_FACE); - glEnable(GL_TEXTURE_2D); - - glBindTexture(GL_TEXTURE_2D, texture); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - const float txLeft = source.left() / m_frame.width(); - const float txRight = source.right() / m_frame.width(); - const float txTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom - ? source.top() / m_frame.height() - : source.bottom() / m_frame.height(); - const float txBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom - ? source.bottom() / m_frame.height() - : source.top() / m_frame.height(); - - glBegin(GL_QUADS); - QRectF rect = target; - glTexCoord2f(txLeft, txBottom); - glVertex2f(rect.topLeft().x(), rect.topLeft().y()); - glTexCoord2f(txRight, txBottom); - glVertex2f(rect.topRight().x() + 1, rect.topRight().y()); - glTexCoord2f(txRight, txTop); - glVertex2f(rect.bottomRight().x() + 1, rect.bottomRight().y() + 1); - glTexCoord2f(txLeft, txTop); - glVertex2f(rect.bottomLeft().x(), rect.bottomLeft().y() + 1); - glEnd(); - painter->endNativePainting(); - - return QAbstractVideoSurface::NoError; - } - - //fallback case, software rendering - if (m_frame.map(QAbstractVideoBuffer::ReadOnly)) { - QImage image( - m_frame.bits(), - m_imageSize.width(), - m_imageSize.height(), - m_frame.bytesPerLine(), - m_imageFormat); - - if (m_scanLineDirection == QVideoSurfaceFormat::BottomToTop) { - const QTransform oldTransform = painter->transform(); - - painter->scale(1, -1); - painter->translate(0, -target.bottom()); - painter->drawImage( - QRectF(target.x(), 0, target.width(), target.height()), image, source); - painter->setTransform(oldTransform); - } else { - painter->drawImage(target, image, source); - } - - m_frame.unmap(); - } else if (m_frame.isValid()) { - return QAbstractVideoSurface::IncorrectFormatError; - } else { - painter->fillRect(target, Qt::black); - } - - return QAbstractVideoSurface::NoError; -} - -void QVideoSurfaceCoreGraphicsPainter::updateColors(int, int, int, int) -{ -} - -QT_END_NAMESPACE diff --git a/src/multimediawidgets/qpaintervideosurface_mac_p.h b/src/multimediawidgets/qpaintervideosurface_mac_p.h deleted file mode 100644 index a56a650d5..000000000 --- a/src/multimediawidgets/qpaintervideosurface_mac_p.h +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPAINTERVIDEOSURFACE_MAC_P_H -#define QPAINTERVIDEOSURFACE_MAC_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qpaintervideosurface_p.h" -#include <qvideosurfaceformat.h> -#include <qvideoframe.h> - -QT_BEGIN_NAMESPACE - - -class QVideoSurfaceCoreGraphicsPainter : public QVideoSurfacePainter -{ -public: - QVideoSurfaceCoreGraphicsPainter(bool glSupported); - ~QVideoSurfaceCoreGraphicsPainter(); - - QList<QVideoFrame::PixelFormat> supportedPixelFormats( - QAbstractVideoBuffer::HandleType handleType) const; - - bool isFormatSupported(const QVideoSurfaceFormat &format) const; - - QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format); - void stop(); - - QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame); - - QAbstractVideoSurface::Error paint( - const QRectF &target, QPainter *painter, const QRectF &source); - - void updateColors(int brightness, int contrast, int hue, int saturation); - -private: - void* ciContext; - QList<QVideoFrame::PixelFormat> m_imagePixelFormats; - QVideoFrame m_frame; - QSize m_imageSize; - QImage::Format m_imageFormat; - QVector<QAbstractVideoBuffer::HandleType> m_supportedHandles; - QVideoSurfaceFormat::Direction m_scanLineDirection; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java index d1abf658e..2ca07a63e 100644 --- a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java +++ b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java @@ -191,8 +191,8 @@ public class QtAndroidMediaPlayer extends MediaPlayer @Override public void onPrepared(final MediaPlayer mp) { - onMediaPlayerInfoNative(MEDIA_PLAYER_DURATION, getDuration(), mID); onMediaPlayerInfoNative(MEDIA_PLAYER_READY, 0, mID); + onMediaPlayerInfoNative(MEDIA_PLAYER_DURATION, getDuration(), mID); mPreparing = false; } diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp index a70f4e130..4dc56ebd9 100644 --- a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp +++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp @@ -98,8 +98,9 @@ QMediaPlayer::MediaStatus QAndroidMediaPlayerControl::mediaStatus() const qint64 QAndroidMediaPlayerControl::duration() const { return (mCurrentMediaStatus == QMediaPlayer::InvalidMedia - || mCurrentMediaStatus == QMediaPlayer::NoMedia) ? 0 - : mMediaPlayer->getDuration(); + || mCurrentMediaStatus == QMediaPlayer::NoMedia + || !mMediaPlayerReady) ? 0 + : mMediaPlayer->getDuration(); } qint64 QAndroidMediaPlayerControl::position() const @@ -330,14 +331,12 @@ void QAndroidMediaPlayerControl::onMediaPlayerInfo(qint32 what, qint32 extra) setState(QMediaPlayer::StoppedState); break; case JMediaPlayer::MEDIA_PLAYER_READY: + setMediaStatus(QMediaPlayer::LoadedMedia); if (mBuffering) { setMediaStatus(mBufferPercent == 100 ? QMediaPlayer::BufferedMedia : QMediaPlayer::BufferingMedia); } else { - setMediaStatus(QMediaPlayer::LoadedMedia); - mBufferPercent = 100; - Q_EMIT bufferStatusChanged(mBufferPercent); - updateAvailablePlaybackRanges(); + onBufferChanged(100); } setAudioAvailable(true); mMediaPlayerReady = true; @@ -402,7 +401,7 @@ void QAndroidMediaPlayerControl::onError(qint32 what, qint32 extra) void QAndroidMediaPlayerControl::onBufferChanged(qint32 percent) { - mBuffering = true; + mBuffering = percent != 100; mBufferPercent = percent; Q_EMIT bufferStatusChanged(mBufferPercent); diff --git a/src/plugins/android/src/wrappers/jsurfacetexture.cpp b/src/plugins/android/src/wrappers/jsurfacetexture.cpp index e5d7d2f17..60c85cdf0 100644 --- a/src/plugins/android/src/wrappers/jsurfacetexture.cpp +++ b/src/plugins/android/src/wrappers/jsurfacetexture.cpp @@ -60,13 +60,13 @@ JSurfaceTexture::JSurfaceTexture(unsigned int texName) , QJNIObject(g_qtSurfaceTextureClass, "(I)V", jint(texName)) , m_texID(int(texName)) { - if (m_jobject) + if (isValid()) g_objectMap.insert(int(texName), this); } JSurfaceTexture::~JSurfaceTexture() { - if (m_jobject) + if (isValid()) g_objectMap.remove(m_texID); } diff --git a/src/plugins/avfoundation/avfoundation.pro b/src/plugins/avfoundation/avfoundation.pro index 7f2ddb2fa..c05331d20 100644 --- a/src/plugins/avfoundation/avfoundation.pro +++ b/src/plugins/avfoundation/avfoundation.pro @@ -1,4 +1,4 @@ TEMPLATE = subdirs -SUBDIRS += camera \ - mediaplayer +SUBDIRS += mediaplayer \ + camera diff --git a/src/plugins/avfoundation/camera/camera.pro b/src/plugins/avfoundation/camera/camera.pro index 3c7511715..791ab8c48 100644 --- a/src/plugins/avfoundation/camera/camera.pro +++ b/src/plugins/avfoundation/camera/camera.pro @@ -8,10 +8,14 @@ PLUGIN_TYPE = mediaservice PLUGIN_CLASS_NAME = AVFServicePlugin load(qt_plugin) -LIBS += -framework AppKit -framework AudioUnit \ - -framework AudioToolbox -framework CoreAudio \ - -framework QuartzCore -framework AVFoundation \ +LIBS += -framework AudioToolbox \ + -framework CoreAudio \ + -framework QuartzCore \ + -framework AVFoundation \ -framework CoreMedia +osx:LIBS += -framework AppKit \ + -framework AudioUnit +ios:LIBS += -framework CoreVideo OTHER_FILES += avfcamera.json diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayerservice.mm b/src/plugins/avfoundation/mediaplayer/avfmediaplayerservice.mm index b916f47d4..398f00e2f 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayerservice.mm +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayerservice.mm @@ -43,11 +43,12 @@ #include "avfmediaplayersession.h" #include "avfmediaplayercontrol.h" #include "avfmediaplayermetadatacontrol.h" -#include "avfvideooutput.h" -#include "avfvideorenderercontrol.h" - +#if defined(Q_OS_OSX) +# include "avfvideooutput.h" +# include "avfvideorenderercontrol.h" +#endif #ifndef QT_NO_WIDGETS -#include "avfvideowidgetcontrol.h" +# include "avfvideowidgetcontrol.h" #endif QT_USE_NAMESPACE @@ -83,7 +84,7 @@ QMediaControl *AVFMediaPlayerService::requestControl(const char *name) if (qstrcmp(name, QMetaDataReaderControl_iid) == 0) return m_playerMetaDataControl; - +#if defined(Q_OS_OSX) if (qstrcmp(name, QVideoRendererControl_iid) == 0) { if (!m_videoOutput) m_videoOutput = new AVFVideoRendererControl(this); @@ -91,6 +92,7 @@ QMediaControl *AVFMediaPlayerService::requestControl(const char *name) m_session->setVideoOutput(qobject_cast<AVFVideoOutput*>(m_videoOutput)); return m_videoOutput; } +#endif #ifndef QT_NO_WIDGETS if (qstrcmp(name, QVideoWidgetControl_iid) == 0) { if (!m_videoOutput) @@ -100,7 +102,6 @@ QMediaControl *AVFMediaPlayerService::requestControl(const char *name) return m_videoOutput; } #endif - return 0; } @@ -109,7 +110,7 @@ void AVFMediaPlayerService::releaseControl(QMediaControl *control) #ifdef QT_DEBUG_AVF qDebug() << Q_FUNC_INFO << control; #endif - +#if defined(Q_OS_OSX) if (m_videoOutput == control) { AVFVideoRendererControl *renderControl = qobject_cast<AVFVideoRendererControl*>(m_videoOutput); if (renderControl) @@ -118,4 +119,5 @@ void AVFMediaPlayerService::releaseControl(QMediaControl *control) m_session->setVideoOutput(0); delete control; } +#endif } diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm index 7af6f4394..bb2bc75cb 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm @@ -240,9 +240,11 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe m_player = [AVPlayer playerWithPlayerItem:m_playerItem]; [m_player retain]; +#if defined(Q_OS_OSX) //Set the initial volume on new player object if (self.session) m_player.volume = m_session->volume() / 100.0f; +#endif //Create a new player layer if we don't have one already if (!m_playerLayer) @@ -735,10 +737,12 @@ void AVFMediaPlayerSession::setVolume(int volume) m_volume = volume; +#if defined(Q_OS_OSX) AVPlayer *player = [(AVFMediaPlayerSessionObserver*)m_observer player]; if (player) { [[(AVFMediaPlayerSessionObserver*)m_observer player] setVolume:m_volume / 100.0f]; } +#endif Q_EMIT volumeChanged(m_volume); } @@ -752,9 +756,9 @@ void AVFMediaPlayerSession::setMuted(bool muted) return; m_muted = muted; - +#if defined(Q_OS_OSX) [[(AVFMediaPlayerSessionObserver*)m_observer player] setMuted:m_muted]; - +#endif Q_EMIT mutedChanged(muted); } diff --git a/src/plugins/avfoundation/mediaplayer/avfvideoframerenderer.h b/src/plugins/avfoundation/mediaplayer/avfvideoframerenderer.h index 5b52e8e53..b33974759 100644 --- a/src/plugins/avfoundation/mediaplayer/avfvideoframerenderer.h +++ b/src/plugins/avfoundation/mediaplayer/avfvideoframerenderer.h @@ -56,15 +56,11 @@ class QOpenGLFramebufferObject; class QWindow; class QOpenGLContext; class QAbstractVideoSurface; -class QGLWidget; class AVFVideoFrameRenderer : public QObject { public: AVFVideoFrameRenderer(QAbstractVideoSurface *surface, QObject *parent = 0); -#ifndef QT_NO_WIDGETS - AVFVideoFrameRenderer(QGLWidget *glWidget, const QSize &size, QObject *parent = 0); -#endif virtual ~AVFVideoFrameRenderer(); @@ -76,9 +72,6 @@ private: void renderLayerToFBO(AVPlayerLayer *layer, QOpenGLFramebufferObject *fbo); CARenderer *m_videoLayerRenderer; -#ifndef QT_NO_WIDGETS - QGLWidget *m_glWidget; -#endif QAbstractVideoSurface *m_surface; QOpenGLFramebufferObject *m_fbo[2]; QWindow *m_offscreenSurface; diff --git a/src/plugins/avfoundation/mediaplayer/avfvideoframerenderer.mm b/src/plugins/avfoundation/mediaplayer/avfvideoframerenderer.mm index 210dd568b..fb63392bb 100644 --- a/src/plugins/avfoundation/mediaplayer/avfvideoframerenderer.mm +++ b/src/plugins/avfoundation/mediaplayer/avfvideoframerenderer.mm @@ -45,10 +45,6 @@ #include <QtGui/QOpenGLFramebufferObject> #include <QtGui/QWindow> -#ifndef QT_NO_WIDGETS -#include <QtOpenGL/QGLWidget> -#endif - #ifdef QT_DEBUG_AVF #include <QtCore/qdebug.h> #endif @@ -76,31 +72,6 @@ AVFVideoFrameRenderer::AVFVideoFrameRenderer(QAbstractVideoSurface *surface, QOb m_offscreenSurface->setGeometry(0, 0, 1, 1); m_offscreenSurface->create(); } -#ifndef QT_NO_WIDGETS -AVFVideoFrameRenderer::AVFVideoFrameRenderer(QGLWidget *glWidget, const QSize &size, QObject *parent) - : QObject(parent) - , m_videoLayerRenderer(0) - , m_glWidget(glWidget) - , m_surface(0) - , m_offscreenSurface(0) - , m_glContext(0) - , m_targetSize(size) - , m_currentBuffer(1) - , m_isContextShared(true) -{ - m_fbo[0] = 0; - m_fbo[1] = 0; - - //Create Hidden QWindow surface to create context in this thread - m_offscreenSurface = new QWindow(); - m_offscreenSurface->setSurfaceType(QWindow::OpenGLSurface); - //Needs geometry to be a valid surface, but size is not important - m_offscreenSurface->setGeometry(0, 0, 1, 1); - m_offscreenSurface->create(); - - -} -#endif AVFVideoFrameRenderer::~AVFVideoFrameRenderer() { @@ -168,10 +139,6 @@ QOpenGLFramebufferObject *AVFVideoFrameRenderer::initRenderer(AVPlayerLayer *lay if (m_surface) { //QOpenGLContext *renderThreadContext = 0; shareContext = qobject_cast<QOpenGLContext*>(m_surface->property("GLContext").value<QObject*>()); -#ifndef QT_NO_WIDGETS - } else { - shareContext = m_glWidget->context()->contextHandle(); -#endif } m_glContext = new QOpenGLContext(); m_glContext->setFormat(m_offscreenSurface->requestedFormat()); diff --git a/src/plugins/avfoundation/mediaplayer/avfvideowidget.h b/src/plugins/avfoundation/mediaplayer/avfvideowidget.h index 460d5305e..12b8c26b1 100644 --- a/src/plugins/avfoundation/mediaplayer/avfvideowidget.h +++ b/src/plugins/avfoundation/mediaplayer/avfvideowidget.h @@ -42,43 +42,44 @@ #ifndef AVFVIDEOWIDGET_H #define AVFVIDEOWIDGET_H -#include <QtOpenGL/QGLWidget> -#include <QtGui/QMatrix4x4> +#include <QtWidgets/QWidget> -QT_BEGIN_NAMESPACE +@class AVPlayerLayer; +#if defined(Q_OS_OSX) +@class NSView; +#else +@class UIView; +#endif -class QOpenGLShaderProgram; +QT_BEGIN_NAMESPACE -class AVFVideoWidget : public QGLWidget +class AVFVideoWidget : public QWidget { public: - AVFVideoWidget(QWidget *parent, const QGLFormat &format); + AVFVideoWidget(QWidget *parent); virtual ~AVFVideoWidget(); - void initializeGL(); - void resizeGL(int w, int h); - void paintGL(); - - void setTexture(GLuint texture); - QSize sizeHint() const; - void setNativeSize(const QSize &size); - + Qt::AspectRatioMode aspectRatioMode() const; void setAspectRatioMode(Qt::AspectRatioMode mode); + void setPlayerLayer(AVPlayerLayer *layer); + +protected: + void resizeEvent(QResizeEvent *); + void paintEvent(QPaintEvent *); private: - QRect displayRect() const; + void updateAspectRatio(); + void updatePlayerLayerBounds(const QSize &size); - GLuint m_textureId; QSize m_nativeSize; Qt::AspectRatioMode m_aspectRatioMode; - - QOpenGLShaderProgram *m_shaderProgram; - QMatrix4x4 m_transformMatrix; - - int m_matrixLocation; - int m_vertexCoordEntry; - int m_textureCoordEntry; + AVPlayerLayer *m_playerLayer; +#if defined(Q_OS_OSX) + NSView *m_nativeView; +#else + UIView *m_nativeView; +#endif }; QT_END_NAMESPACE diff --git a/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm b/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm index 518a6bcea..2e4de37f1 100644 --- a/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm +++ b/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm @@ -41,15 +41,19 @@ #include "avfvideowidget.h" #include <QtCore/QDebug> -#include <QtGui/QOpenGLShaderProgram> + +#include <AVFoundation/AVFoundation.h> +#include <QtGui/QResizeEvent> +#include <QtGui/QPaintEvent> +#include <QtGui/QPainter> QT_USE_NAMESPACE -AVFVideoWidget::AVFVideoWidget(QWidget *parent, const QGLFormat &format) - : QGLWidget(format, parent) - , m_textureId(0) +AVFVideoWidget::AVFVideoWidget(QWidget *parent) + : QWidget(parent) , m_aspectRatioMode(Qt::KeepAspectRatio) - , m_shaderProgram(0) + , m_playerLayer(0) + , m_nativeView(0) { setAutoFillBackground(false); } @@ -59,143 +63,114 @@ AVFVideoWidget::~AVFVideoWidget() #ifdef QT_DEBUG_AVF qDebug() << Q_FUNC_INFO; #endif - delete m_shaderProgram; + + if (m_playerLayer) + [m_playerLayer release]; } -void AVFVideoWidget::initializeGL() +QSize AVFVideoWidget::sizeHint() const { - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - - m_shaderProgram = new QOpenGLShaderProgram; - - static const char *textureVertexProgram = - "uniform highp mat4 matrix;\n" - "attribute highp vec3 vertexCoordEntry;\n" - "attribute highp vec2 textureCoordEntry;\n" - "varying highp vec2 textureCoord;\n" - "void main() {\n" - " textureCoord = textureCoordEntry;\n" - " gl_Position = matrix * vec4(vertexCoordEntry, 1);\n" - "}\n"; - - static const char *textureFragmentProgram = - "uniform sampler2D texture;\n" - "varying highp vec2 textureCoord;\n" - "void main() {\n" - " gl_FragColor = texture2D(texture, textureCoord);\n" - "}\n"; - - m_shaderProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram); - m_shaderProgram->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram); - m_shaderProgram->link(); + return m_nativeSize; } -void AVFVideoWidget::resizeGL(int w, int h) +Qt::AspectRatioMode AVFVideoWidget::aspectRatioMode() const { - glViewport(0, 0, GLsizei(w), GLsizei(h)); - updateGL(); + return m_aspectRatioMode; } -void AVFVideoWidget::paintGL() +void AVFVideoWidget::setAspectRatioMode(Qt::AspectRatioMode mode) { - glClear(GL_COLOR_BUFFER_BIT); - if (!m_textureId) - return; - - QRect targetRect = displayRect(); - GLfloat x1 = targetRect.left(); - GLfloat x2 = targetRect.right(); - GLfloat y1 = targetRect.bottom(); - GLfloat y2 = targetRect.top(); - GLfloat zValue = 0; + if (m_aspectRatioMode != mode) { + m_aspectRatioMode = mode; - const GLfloat textureCoordinates[] = { - 0, 0, - 1, 0, - 1, 1, - 0, 1 - }; + updateAspectRatio(); + } +} - const GLfloat vertexCoordinates[] = { - x1, y1, zValue, - x2, y1, zValue, - x2, y2, zValue, - x1, y2, zValue - }; +void AVFVideoWidget::setPlayerLayer(AVPlayerLayer *layer) +{ + if (m_playerLayer == layer) + return; - //Set matrix to transfrom geometry values into gl coordinate space. - m_transformMatrix.setToIdentity(); - m_transformMatrix.scale( 2.0f / size().width(), 2.0f / size().height() ); - m_transformMatrix.translate(-size().width() / 2.0f, -size().height() / 2.0f); + if (!m_nativeView) { + //make video widget a native window +#if defined(Q_OS_OSX) + m_nativeView = (NSView*)this->winId(); + [m_nativeView setWantsLayer:YES]; +#else + m_nativeView = (UIView*)this->winId(); +#endif + } - m_shaderProgram->bind(); + if (m_playerLayer) { + [m_playerLayer removeFromSuperlayer]; + [m_playerLayer release]; + } - m_vertexCoordEntry = m_shaderProgram->attributeLocation("vertexCoordEntry"); - m_textureCoordEntry = m_shaderProgram->attributeLocation("textureCoordEntry"); - m_matrixLocation = m_shaderProgram->uniformLocation("matrix"); + m_playerLayer = layer; - //attach the data! - glEnableVertexAttribArray(m_vertexCoordEntry); - glEnableVertexAttribArray(m_textureCoordEntry); + CALayer *nativeLayer = [m_nativeView layer]; - glVertexAttribPointer(m_vertexCoordEntry, 3, GL_FLOAT, GL_FALSE, 0, vertexCoordinates); - glVertexAttribPointer(m_textureCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates); - m_shaderProgram->setUniformValue(m_matrixLocation, m_transformMatrix); + if (layer) { + [layer retain]; - glBindTexture(GL_TEXTURE_2D, m_textureId); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + m_nativeSize = QSize(m_playerLayer.bounds.size.width, + m_playerLayer.bounds.size.height); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + updateAspectRatio(); + [nativeLayer addSublayer:m_playerLayer]; + updatePlayerLayerBounds(this->size()); + } - glBindTexture(GL_TEXTURE_2D, 0); + NSArray *sublayers = [nativeLayer sublayers]; + qDebug() << "playerlayer: " << "at z:" << [m_playerLayer zPosition] + << " frame: " << m_playerLayer.frame.size.width << "x" << m_playerLayer.frame.size.height; + qDebug() << "superlayer: " << "at z:" << [nativeLayer zPosition] + << " frame: " << nativeLayer.frame.size.width << "x" << nativeLayer.frame.size.height; + int i = 0; + for (CALayer *layer in sublayers) { + qDebug() << "layer " << i << ": at z:" << [layer zPosition] + << " frame: " << layer.frame.size.width << "x" << layer.frame.size.height; + i++; + } - glDisableVertexAttribArray(m_vertexCoordEntry); - glDisableVertexAttribArray(m_textureCoordEntry); - m_shaderProgram->release(); } -void AVFVideoWidget::setTexture(GLuint texture) +void AVFVideoWidget::resizeEvent(QResizeEvent *event) { - m_textureId = texture; - - if (isVisible()) { - makeCurrent(); - updateGL(); - } + updatePlayerLayerBounds(event->size()); + QWidget::resizeEvent(event); } -QSize AVFVideoWidget::sizeHint() const +void AVFVideoWidget::paintEvent(QPaintEvent *event) { - return m_nativeSize; -} + QPainter painter(this); + painter.fillRect(rect(), Qt::black); -void AVFVideoWidget::setNativeSize(const QSize &size) -{ - m_nativeSize = size; + QWidget::paintEvent(event); } -void AVFVideoWidget::setAspectRatioMode(Qt::AspectRatioMode mode) +void AVFVideoWidget::updateAspectRatio() { - if (m_aspectRatioMode != mode) { - m_aspectRatioMode = mode; - update(); + if (m_playerLayer) { + switch (m_aspectRatioMode) { + case Qt::IgnoreAspectRatio: + [m_playerLayer setVideoGravity:AVLayerVideoGravityResize]; + break; + case Qt::KeepAspectRatio: + [m_playerLayer setVideoGravity:AVLayerVideoGravityResizeAspect]; + break; + case Qt::KeepAspectRatioByExpanding: + [m_playerLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill]; + break; + default: + break; + } } } -QRect AVFVideoWidget::displayRect() const +void AVFVideoWidget::updatePlayerLayerBounds(const QSize &size) { - QRect displayRect = rect(); - - if (m_aspectRatioMode == Qt::KeepAspectRatio) { - QSize size = m_nativeSize; - size.scale(displayRect.size(), Qt::KeepAspectRatio); - - displayRect = QRect(QPoint(0, 0), size); - displayRect.moveCenter(rect().center()); - } - return displayRect; + m_playerLayer.bounds = CGRectMake(0.0f, 0.0f, (float)size.width(), (float)size.height()); } diff --git a/src/plugins/avfoundation/mediaplayer/avfvideowidgetcontrol.h b/src/plugins/avfoundation/mediaplayer/avfvideowidgetcontrol.h index 5230d7569..89d3e7f56 100644 --- a/src/plugins/avfoundation/mediaplayer/avfvideowidgetcontrol.h +++ b/src/plugins/avfoundation/mediaplayer/avfvideowidgetcontrol.h @@ -45,13 +45,11 @@ #include <qvideowidgetcontrol.h> #include "avfvideooutput.h" -#import <CoreVideo/CVBase.h> +@class AVPlayerLayer; QT_BEGIN_NAMESPACE -class AVFDisplayLink; class AVFVideoWidget; -class AVFVideoFrameRenderer; class AVFVideoWidgetControl : public QVideoWidgetControl, public AVFVideoOutput { @@ -83,24 +81,15 @@ public: int saturation() const; void setSaturation(int saturation); -private Q_SLOTS: - void updateVideoFrame(const CVTimeStamp &ts); - private: - void setupVideoOutput(); - - AVFDisplayLink *m_displayLink; AVFVideoWidget *m_videoWidget; - AVFVideoFrameRenderer *m_frameRenderer; - QSize m_nativeSize; - Qt::AspectRatioMode m_aspectRatioMode; + bool m_fullscreen; int m_brightness; int m_contrast; int m_hue; int m_saturation; - void *m_playerLayer; }; QT_END_NAMESPACE diff --git a/src/plugins/avfoundation/mediaplayer/avfvideowidgetcontrol.mm b/src/plugins/avfoundation/mediaplayer/avfvideowidgetcontrol.mm index f50117d81..0d62c394b 100644 --- a/src/plugins/avfoundation/mediaplayer/avfvideowidgetcontrol.mm +++ b/src/plugins/avfoundation/mediaplayer/avfvideowidgetcontrol.mm @@ -40,10 +40,7 @@ ****************************************************************************/ #include "avfvideowidgetcontrol.h" - #include "avfvideowidget.h" -#include "avfvideoframerenderer.h" -#include "avfdisplaylink.h" #ifdef QT_DEBUG_AVF #include <QtCore/QDebug> @@ -55,22 +52,13 @@ QT_USE_NAMESPACE AVFVideoWidgetControl::AVFVideoWidgetControl(QObject *parent) : QVideoWidgetControl(parent) - , m_frameRenderer(0) - , m_aspectRatioMode(Qt::KeepAspectRatio) , m_fullscreen(false) , m_brightness(0) , m_contrast(0) , m_hue(0) , m_saturation(0) - , m_playerLayer(0) { - QGLFormat format = QGLFormat::defaultFormat(); - format.setSwapInterval(1); // Vertical sync (avoid tearing) - format.setDoubleBuffer(true); - m_videoWidget = new AVFVideoWidget(0, format); - - m_displayLink = new AVFDisplayLink(this); - connect(m_displayLink, SIGNAL(tick(CVTimeStamp)), this, SLOT(updateVideoFrame(CVTimeStamp))); + m_videoWidget = new AVFVideoWidget(0); } AVFVideoWidgetControl::~AVFVideoWidgetControl() @@ -78,10 +66,6 @@ AVFVideoWidgetControl::~AVFVideoWidgetControl() #ifdef QT_DEBUG_AVF qDebug() << Q_FUNC_INFO; #endif - m_displayLink->stop(); - if (m_playerLayer) - [(AVPlayerLayer*)m_playerLayer release]; - delete m_videoWidget; } @@ -91,26 +75,8 @@ void AVFVideoWidgetControl::setLayer(void *playerLayer) qDebug() << Q_FUNC_INFO << playerLayer; #endif - if (m_playerLayer == playerLayer) - return; - - [(AVPlayerLayer*)playerLayer retain]; - [(AVPlayerLayer*)m_playerLayer release]; - - m_playerLayer = playerLayer; - - //If there is no layer to render, stop scheduling updates - if (m_playerLayer == 0) { - m_displayLink->stop(); - return; - } + m_videoWidget->setPlayerLayer((AVPlayerLayer*)playerLayer); - setupVideoOutput(); - - //make sure we schedule updates - if (!m_displayLink->isActive()) { - m_displayLink->start(); - } } QWidget *AVFVideoWidgetControl::videoWidget() @@ -130,12 +96,11 @@ void AVFVideoWidgetControl::setFullScreen(bool fullScreen) Qt::AspectRatioMode AVFVideoWidgetControl::aspectRatioMode() const { - return m_aspectRatioMode; + return m_videoWidget->aspectRatioMode(); } void AVFVideoWidgetControl::setAspectRatioMode(Qt::AspectRatioMode mode) { - m_aspectRatioMode = mode; m_videoWidget->setAspectRatioMode(mode); } @@ -179,41 +144,4 @@ void AVFVideoWidgetControl::setSaturation(int saturation) m_saturation = saturation; } -void AVFVideoWidgetControl::updateVideoFrame(const CVTimeStamp &ts) -{ - Q_UNUSED(ts) - - AVPlayerLayer *playerLayer = (AVPlayerLayer*)m_playerLayer; - - if (!playerLayer) { - qWarning("updateVideoFrame called without AVPlayerLayer (which shouldn't happen)"); - return; - } - - //Don't try to render a layer that is not ready - if (!playerLayer.readyForDisplay) - return; - - GLuint textureId = m_frameRenderer->renderLayerToTexture(playerLayer); - - //Make sure we have a valid texture - if (textureId == 0) { - qWarning("renderLayerToTexture failed"); - return; - } - - m_videoWidget->setTexture(textureId); -} - -void AVFVideoWidgetControl::setupVideoOutput() -{ - CGRect layerBounds = [(AVPlayerLayer*)m_playerLayer bounds]; - m_nativeSize = QSize(layerBounds.size.width, layerBounds.size.height); - m_videoWidget->setNativeSize(m_nativeSize); - - if (m_frameRenderer) - delete m_frameRenderer; - - m_frameRenderer = new AVFVideoFrameRenderer(m_videoWidget, m_nativeSize, this); -} - +#include "moc_avfvideowidgetcontrol.cpp" diff --git a/src/plugins/avfoundation/mediaplayer/mediaplayer.pro b/src/plugins/avfoundation/mediaplayer/mediaplayer.pro index a61c62d01..e5bccd150 100644 --- a/src/plugins/avfoundation/mediaplayer/mediaplayer.pro +++ b/src/plugins/avfoundation/mediaplayer/mediaplayer.pro @@ -21,9 +21,6 @@ HEADERS += \ avfmediaplayerservice.h \ avfmediaplayersession.h \ avfmediaplayerserviceplugin.h \ - avfvideorenderercontrol.h \ - avfdisplaylink.h \ - avfvideoframerenderer.h \ avfvideooutput.h OBJECTIVE_SOURCES += \ @@ -32,20 +29,30 @@ OBJECTIVE_SOURCES += \ avfmediaplayerservice.mm \ avfmediaplayerserviceplugin.mm \ avfmediaplayersession.mm \ - avfvideorenderercontrol.mm \ - avfdisplaylink.mm \ - avfvideoframerenderer.mm \ avfvideooutput.mm -qtHaveModule(widgets) { - QT += multimediawidgets-private opengl - HEADERS += \ - avfvideowidgetcontrol.h \ - avfvideowidget.h + qtHaveModule(widgets) { + QT += multimediawidgets-private + HEADERS += \ + avfvideowidgetcontrol.h \ + avfvideowidget.h + + OBJECTIVE_SOURCES += \ + avfvideowidgetcontrol.mm \ + avfvideowidget.mm + } +!ios { + LIBS += -framework QuartzCore -framework AppKit + + HEADERS += \ + avfvideorenderercontrol.h \ + avfdisplaylink.h \ + avfvideoframerenderer.h OBJECTIVE_SOURCES += \ - avfvideowidgetcontrol.mm \ - avfvideowidget.mm + avfvideorenderercontrol.mm \ + avfdisplaylink.mm \ + avfvideoframerenderer.mm } OTHER_FILES += \ diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index 1e0ea4386..742a4f7f0 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -47,10 +47,9 @@ unix:!mac:!android { mac:!simulator { SUBDIRS += audiocapture - !ios { - SUBDIRS += qt7 - config_avfoundation: SUBDIRS += avfoundation - } + config_avfoundation: SUBDIRS += avfoundation + + !ios: SUBDIRS += qt7 } config_opensles { diff --git a/src/plugins/pulseaudio/qaudioinput_pulse.h b/src/plugins/pulseaudio/qaudioinput_pulse.h index 4c1881e67..bb72628f8 100644 --- a/src/plugins/pulseaudio/qaudioinput_pulse.h +++ b/src/plugins/pulseaudio/qaudioinput_pulse.h @@ -130,11 +130,9 @@ private: int m_bufferSize; int m_periodSize; int m_intervalTime; - unsigned int m_bufferTime; unsigned int m_periodTime; QTimer *m_timer; qint64 m_elapsedTimeOffset; - char *audioBuffer; pa_stream *m_stream; QTime m_timeStamp; QTime m_clockStamp; diff --git a/src/plugins/wmf/evrcustompresenter.cpp b/src/plugins/wmf/evrcustompresenter.cpp index eb73e6720..70acbddba 100644 --- a/src/plugins/wmf/evrcustompresenter.cpp +++ b/src/plugins/wmf/evrcustompresenter.cpp @@ -50,6 +50,7 @@ #include <qabstractvideosurface.h> #include <qthread.h> #include <qcoreapplication.h> +#include <qmath.h> #include <QtCore/qdebug.h> #include <d3d9.h> #include <dshow.h> @@ -325,7 +326,7 @@ HRESULT Scheduler::processSample(IMFSample *sample, LONG *pNextSleep) // Adjust the sleep time for the clock rate. (The presentation clock runs // at m_fRate, but sleeping uses the system clock.) if (m_playbackRate != 0) - nextSleep = (LONG)(nextSleep / fabsf(m_playbackRate)); + nextSleep = (LONG)(nextSleep / qFabs(m_playbackRate)); // Don't present yet. presentNow = false; @@ -987,7 +988,7 @@ HRESULT EVRCustomPresenter::IsRateSupported(BOOL thin, float rate, float *neares // Note: We have no minimum rate (that is, we support anything down to 0). maxRate = getMaxRate(thin); - if (fabsf(rate) > maxRate) { + if (qFabs(rate) > maxRate) { // The (absolute) requested rate exceeds the maximum rate. hr = MF_E_UNSUPPORTED_RATE; diff --git a/src/plugins/wmf/evrd3dpresentengine.cpp b/src/plugins/wmf/evrd3dpresentengine.cpp index c67b5d448..01a5c3341 100644 --- a/src/plugins/wmf/evrd3dpresentengine.cpp +++ b/src/plugins/wmf/evrd3dpresentengine.cpp @@ -288,9 +288,21 @@ void D3DPresentEngine::presentSample(void *opaque, qint64) } if (surface && updateTexture(surface)) { - m_surface->present(QVideoFrame(new TextureVideoBuffer(m_glTexture), - m_surfaceFormat.frameSize(), - m_surfaceFormat.pixelFormat())); + QVideoFrame frame = QVideoFrame(new TextureVideoBuffer(m_glTexture), + m_surfaceFormat.frameSize(), + m_surfaceFormat.pixelFormat()); + + // WMF uses 100-nanosecond units, Qt uses microseconds + LONGLONG startTime = -1; + if (SUCCEEDED(sample->GetSampleTime(&startTime))) { + frame.setStartTime(startTime * 0.1); + + LONGLONG duration = -1; + if (SUCCEEDED(sample->GetSampleDuration(&duration))) + frame.setEndTime((startTime + duration) * 0.1); + } + + m_surface->present(frame); } done: diff --git a/src/plugins/wmf/mftvideo.cpp b/src/plugins/wmf/mftvideo.cpp index acec88d6b..8e7ce0693 100644 --- a/src/plugins/wmf/mftvideo.cpp +++ b/src/plugins/wmf/mftvideo.cpp @@ -632,13 +632,14 @@ QVideoFrame MFTransform::makeVideoFrame() // That is why we copy data from IMFMediaBuffer here. frame = QVideoFrame(new QMemoryVideoBuffer(array, m_bytesPerLine), m_format.frameSize(), m_format.pixelFormat()); + // WMF uses 100-nanosecond units, Qt uses microseconds LONGLONG startTime = -1; if (SUCCEEDED(m_sample->GetSampleTime(&startTime))) { - frame.setStartTime(startTime); + frame.setStartTime(startTime * 0.1); LONGLONG duration = -1; if (SUCCEEDED(m_sample->GetSampleDuration(&duration))) - frame.setEndTime(startTime + duration); + frame.setEndTime((startTime + duration) * 0.1); } } while (false); diff --git a/src/plugins/wmf/player/mfplayersession.cpp b/src/plugins/wmf/player/mfplayersession.cpp index fb150c3e9..4e4b56589 100644 --- a/src/plugins/wmf/player/mfplayersession.cpp +++ b/src/plugins/wmf/player/mfplayersession.cpp @@ -1918,19 +1918,17 @@ void MFPlayerSession::handleSessionEvent(IMFMediaEvent *sessionEvent) changeStatus(QMediaPlayer::BufferedMedia); emit bufferStatusChanged(bufferStatus()); break; - case MEEndOfPresentation: - stop(); - changeStatus(QMediaPlayer::EndOfMedia); - m_varStart.vt = VT_I8; - //keep reporting the final position after end of media - m_varStart.hVal.QuadPart = m_duration; - break; case MESessionEnded: m_pendingState = NoPending; m_state.command = CmdStop; m_state.prevCmd = CmdNone; m_request.command = CmdNone; m_request.prevCmd = CmdNone; + + changeStatus(QMediaPlayer::EndOfMedia); + m_varStart.vt = VT_I8; + //keep reporting the final position after end of media + m_varStart.hVal.QuadPart = m_duration; break; case MEEndOfPresentationSegment: break; @@ -1993,6 +1991,8 @@ void MFPlayerSession::handleSessionEvent(IMFMediaEvent *sessionEvent) } } break; + default: + break; } sessionEvent->Release(); diff --git a/src/plugins/wmf/player/mfvideorenderercontrol.cpp b/src/plugins/wmf/player/mfvideorenderercontrol.cpp index 8f73244c0..83768c8e2 100644 --- a/src/plugins/wmf/player/mfvideorenderercontrol.cpp +++ b/src/plugins/wmf/player/mfvideorenderercontrol.cpp @@ -254,6 +254,8 @@ namespace , m_workQueueCB(this, &MediaStream::onDispatchWorkItem) , m_finalizeResult(0) , m_scheduledBuffer(0) + , m_bufferStartTime(-1) + , m_bufferDuration(-1) , m_presentationClock(0) , m_currentMediaType(0) , m_prerolling(false) @@ -839,10 +841,13 @@ namespace QMutexLocker locker(&m_mutex); if (!m_scheduledBuffer) return; - m_surface->present(QVideoFrame( - new MediaSampleVideoBuffer(m_scheduledBuffer, m_bytesPerLine), - m_surfaceFormat.frameSize(), - m_surfaceFormat.pixelFormat())); + QVideoFrame frame = QVideoFrame( + new MediaSampleVideoBuffer(m_scheduledBuffer, m_bytesPerLine), + m_surfaceFormat.frameSize(), + m_surfaceFormat.pixelFormat()); + frame.setStartTime(m_bufferStartTime * 0.1); + frame.setEndTime((m_bufferStartTime + m_bufferDuration) * 0.1); + m_surface->present(frame); m_scheduledBuffer->Release(); m_scheduledBuffer = NULL; if (m_rate != 0) @@ -1309,8 +1314,10 @@ namespace HRESULT processSampleData(IMFSample *pSample) { - LONGLONG time; + LONGLONG time, duration = -1; HRESULT hr = pSample->GetSampleTime(&time); + if (SUCCEEDED(hr)) + pSample->GetSampleDuration(&duration); if (m_prerolling) { if (SUCCEEDED(hr) && time >= m_prerollTargetTime) { @@ -1320,6 +1327,7 @@ namespace SampleBuffer sb; sb.m_buffer = pBuffer; sb.m_time = time; + sb.m_duration = duration; m_bufferCache.push_back(sb); endPreroll(S_OK); } @@ -1336,6 +1344,7 @@ namespace SampleBuffer sb; sb.m_buffer = pBuffer; sb.m_time = time; + sb.m_duration = duration; m_bufferCache.push_back(sb); } if (m_rate == 0) @@ -1351,6 +1360,7 @@ namespace public: IMFMediaBuffer *m_buffer; LONGLONG m_time; + LONGLONG m_duration; }; QList<SampleBuffer> m_bufferCache; static const int BUFFER_CACHE_SIZE = 2; @@ -1383,6 +1393,8 @@ namespace continue; } m_scheduledBuffer = sb.m_buffer; + m_bufferStartTime = sb.m_time; + m_bufferDuration = sb.m_duration; QCoreApplication::postEvent(m_rendererControl, new PresentEvent(sb.m_time)); if (m_rate == 0) queueEvent(MEStreamSinkScrubSampleComplete, GUID_NULL, S_OK, NULL); @@ -1393,6 +1405,8 @@ namespace queueEvent(MEStreamSinkRequestSample, GUID_NULL, S_OK, NULL); } IMFMediaBuffer *m_scheduledBuffer; + MFTIME m_bufferStartTime; + MFTIME m_bufferDuration; IMFPresentationClock *m_presentationClock; float m_rate; }; |