Merge "Merge remote-tracking branch 'origin/5.5' into dev" into refs/staging/dev

This commit is contained in:
Liang Qi
2015-06-30 13:29:49 +00:00
committed by The Qt Project
30 changed files with 563 additions and 86 deletions

118
dist/changes-5.5.0 vendored Normal file
View File

@@ -0,0 +1,118 @@
Qt 5.5 introduces many new features and improvements as well as bugfixes
over the 5.4.x series. For more details, refer to the online documentation
included in this distribution. The documentation is also available online:
http://doc.qt.io/qt-5.5
The Qt version 5.5 series is binary compatible with the 5.4.x series.
Applications compiled for 5.4 will continue to run with 5.5.
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
http://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* Library *
****************************************************************************
QtMultimedia
------------
- Added QAbstractVideoFilter that serves as a base class for QML
video filtering elements that integrate compute, vision, and image
processing frameworks with VideoOutput.
- Added new QCameraViewfinderSettings class.
- [QTBUG-40571] Fixed memory leak in QAudioDecoder.
- Camera (QML):
* Added imageProcessing.colorFilter, viewfinder.minimumFrameRate and
viewfinder.maximumFrameRate properties.
* Added new supportedViewfinderResolutions() and
supportedViewfinderFrameRateRanges() methods.
* Exposure modes extended to support Action, Landscape, NightPortrait,
Theatre, Sunset, SteadyPhoto, Fireworks, Party, Candlelight, and
Barcode modes
- QCamera:
* Added support for viewfinder settings. In addition to the getter and
setter, supportedViewfinderSettings(),
supportedViewfinderResolutions(), supportedViewfinderFrameRateRanges()
and supportedViewfinderPixelFormats() can be used to query for
supported values.
* Fixed searchAndLock() and supportedLocks() functions which could not
work at all on some platforms.
- QCameraExposure:
* Exposure modes extended to support Action, Landscape, NightPortrait,
Theatre, Sunset, SteadyPhoto, Fireworks, Party, Candlelight, and
Barcode modes
- QCameraImageProcessing:
* Added support for color filters.
****************************************************************************
* Platform Specific Changes *
****************************************************************************
Android
-------
- Added support for additional camera exposure modes (see list in
QCameraExposure changes).
iOS / OS X
----------
- Improved camera support:
* Image capture settings, focus, flash, exposure (iOS only) and
zoom (iOS only) APIs are now functional.
* QVideoProbe can now be used with a QCamera.
- VideoOutput, when used with a MediaPlayer on iOS, can now be displayed
under other elements and supports shader effects and advanced
transformations.
- QMediaRecorder now uses the correct system default audio capture
device.
- [QTBUG-36175] QMediaPlayer and the QML Audio and Mediaplayer types can
now play media files stored in a Qt resource file.
- [QTBUG-37655] Fixed video capture on iOS.
- [QTBUG-39240] QMediaPlayer and the QML Audio and Mediaplayer types now
support volume and mute on iOS 7.0 and later.
- [QTBUG-42035] Fixed crash when capturing an image after changing the
active camera device.
Linux
-----
- Added support for GStreamer 1.0. The 0.10 series is still used by default
and Qt needs to be configured with '-gstreamer 1.0' to enable 1.0
support. If only GStreamer 1.0 is available on the system, the configure
script will automatically configure Qt with GStreamer 1.0 support.
- QCamera now supports exposure and white balance locks.
- Added support for additional camera exposure modes (see list in
QCameraExposure changes).
- Fixed QCameraImageCapture::supportedResolutions(),
QMediaRecorder::supportedResolutions() and
QMediaRecorder::supportedFrameRates() that could return empty lists.
- [QTBUG-46169] QVideoWidget now works with any windowing system. It was
previously only working with X11.
Windows
-------
- [QTBUG-45571] QAudioBuffer::startTime() now returns the time in the
correct time scale.
WinRT
-----
- [QTBUG-42263] QMediaPlayer and the QML Audio and Mediaplayer types can
now play media files stored in a Qt resource file.
- [QTBUG-44838] Fixed camera preview on Lumia 630.
- [QTBUG-45920] Fixed camera preview on Lumia 530.
- [QTBUG-45667] Fixed crash that could occur when using the camera
preview.

View File

@@ -1094,8 +1094,8 @@ QJSValue QDeclarativeCamera::supportedViewfinderFrameRateRanges(const QSize &res
int i = 0;
Q_FOREACH (const QCamera::FrameRateRange &frameRateRange, frameRateRanges) {
QJSValue range = engine->newObject();
range.setProperty(QStringLiteral("minimumFrameRate"), frameRateRange.first);
range.setProperty(QStringLiteral("maximumFrameRate"), frameRateRange.second);
range.setProperty(QStringLiteral("minimumFrameRate"), frameRateRange.minimumFrameRate);
range.setProperty(QStringLiteral("maximumFrameRate"), frameRateRange.maximumFrameRate);
supportedFrameRateRanges.setProperty(i++, range);
}

View File

@@ -72,7 +72,7 @@ static bool qt_sizeLessThan(const QSize &s1, const QSize &s2)
static bool qt_frameRateRangeLessThan(const QCamera::FrameRateRange &s1, const QCamera::FrameRateRange &s2)
{
return s1.second < s2.second;
return s1.maximumFrameRate < s2.maximumFrameRate;
}
/*!
@@ -1028,15 +1028,29 @@ void QCamera::unlock()
/*!
\typedef QCamera::FrameRateRange
\class QCamera::FrameRateRange
\inmodule QtMultimedia
\ingroup multimedia
\ingroup multimedia_camera
\since 5.5
This is a typedef for QPair<qreal, qreal>.
\brief A FrameRateRange represents a range of frame rates as minimum and maximum rate.
A frame rate range contains a minimum and a maximum frame rate, respectively the first and
second element of the pair. If the minimum frame rate is equal to the maximum frame rate, the
frame rate is fixed. If not, the actual frame rate fluctuates between the minimum and the maximum.
If the minimum frame rate is equal to the maximum frame rate, the frame rate is fixed.
If not, the actual frame rate fluctuates between the minimum and the maximum.
\sa QCamera::supportedViewfinderFrameRateRanges(), QCameraViewfinderSettings
*/
/*!
\variable QCamera::FrameRateRange::minimumFrameRate
The minimum frame rate supported by the range, in frames per second.
*/
/*!
\variable QCamera::FrameRateRange::maximumFrameRate
The maximum frame rate supported by the range, in frames per second.
*/
/*!
\enum QCamera::State

View File

@@ -77,7 +77,21 @@ class Q_MULTIMEDIA_EXPORT QCamera : public QMediaObject
Q_ENUMS(LockType)
Q_ENUMS(Position)
public:
typedef QPair<qreal, qreal> FrameRateRange;
struct FrameRateRange
{
Q_DECL_CONSTEXPR FrameRateRange() Q_DECL_NOTHROW
: minimumFrameRate(0)
, maximumFrameRate(0)
{ }
Q_DECL_CONSTEXPR FrameRateRange(qreal minimum, qreal maximum) Q_DECL_NOTHROW
: minimumFrameRate(minimum)
, maximumFrameRate(maximum)
{ }
qreal minimumFrameRate;
qreal maximumFrameRate;
};
enum Status {
UnavailableStatus,
@@ -237,6 +251,14 @@ private:
Q_DECLARE_OPERATORS_FOR_FLAGS(QCamera::LockTypes)
Q_DECL_CONSTEXPR Q_INLINE_TEMPLATE bool operator==(const QCamera::FrameRateRange &r1, const QCamera::FrameRateRange &r2) Q_DECL_NOTHROW
{ return r1.minimumFrameRate == r2.minimumFrameRate && r1.maximumFrameRate == r2.maximumFrameRate; }
Q_DECL_CONSTEXPR Q_INLINE_TEMPLATE bool operator!=(const QCamera::FrameRateRange &r1, const QCamera::FrameRateRange &r2) Q_DECL_NOTHROW
{ return !(r1 == r2); }
Q_DECLARE_TYPEINFO(QCamera::FrameRateRange, Q_PRIMITIVE_TYPE);
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QCamera::State)

View File

@@ -136,32 +136,35 @@ QCameraViewfinderSettings &QCameraViewfinderSettings::operator=(const QCameraVie
}
/*!
Determines if \a other is of equal value to a viewfinder settings object.
\relates QCameraViewfinderSettings
\since 5.5
Determines if \a lhs is of equal value to \a rhs.
Returns true if the settings objects are of equal value, and false if they
are not of equal value.
*/
bool QCameraViewfinderSettings::operator==(const QCameraViewfinderSettings &other) const
bool operator==(const QCameraViewfinderSettings &lhs, const QCameraViewfinderSettings &rhs) Q_DECL_NOTHROW
{
return (d == other.d) ||
(d->isNull == other.d->isNull &&
d->resolution == other.d->resolution &&
qFuzzyCompare(d->minimumFrameRate, other.d->minimumFrameRate) &&
qFuzzyCompare(d->maximumFrameRate, other.d->maximumFrameRate) &&
d->pixelFormat == other.d->pixelFormat &&
d->pixelAspectRatio == other.d->pixelAspectRatio);
return (lhs.d == rhs.d) ||
(lhs.d->isNull == rhs.d->isNull &&
lhs.d->resolution == rhs.d->resolution &&
lhs.d->minimumFrameRate == rhs.d->minimumFrameRate &&
lhs.d->maximumFrameRate == rhs.d->maximumFrameRate &&
lhs.d->pixelFormat == rhs.d->pixelFormat &&
lhs.d->pixelAspectRatio == rhs.d->pixelAspectRatio);
}
/*!
Determines if \a other is of equal value to a viewfinder settings object.
\fn bool operator!=(const QCameraViewfinderSettings &lhs, const QCameraViewfinderSettings &rhs)
\relates QCameraViewfinderSettings
\since 5.5
Determines if \a lhs is of equal value to \a rhs.
Returns true if the settings objects are not of equal value, and false if
they are of equal value.
*/
bool QCameraViewfinderSettings::operator!=(const QCameraViewfinderSettings &other) const
{
return !(*this == other);
}
/*!
Identifies if a viewfinder settings object is uninitalized.

View File

@@ -34,10 +34,12 @@
#ifndef QCAMERAVIEWFINDERSETTINGS_H
#define QCAMERAVIEWFINDERSETTINGS_H
#include <QtCore/qsharedpointer.h>
#include <QtMultimedia/qtmultimediadefs.h>
#include <QtMultimedia/qvideoframe.h>
#include <QtCore/qshareddata.h>
#include <QtCore/qsize.h>
QT_BEGIN_NAMESPACE
class QCameraViewfinderSettingsPrivate;
@@ -51,9 +53,14 @@ public:
~QCameraViewfinderSettings();
QCameraViewfinderSettings& operator=(const QCameraViewfinderSettings &other);
bool operator==(const QCameraViewfinderSettings &other) const;
bool operator!=(const QCameraViewfinderSettings &other) const;
#ifdef Q_COMPILER_RVALUE_REFS
QCameraViewfinderSettings &operator=(QCameraViewfinderSettings &&other) Q_DECL_NOTHROW
{ swap(other); return *this; }
#endif
void swap(QCameraViewfinderSettings &other) Q_DECL_NOTHROW { d.swap(other.d); }
friend Q_MULTIMEDIA_EXPORT bool operator==(const QCameraViewfinderSettings &lhs, const QCameraViewfinderSettings &rhs) Q_DECL_NOTHROW;
bool isNull() const;
QSize resolution() const;
@@ -78,6 +85,11 @@ public:
private:
QSharedDataPointer<QCameraViewfinderSettingsPrivate> d;
};
Q_DECLARE_SHARED(QCameraViewfinderSettings)
inline bool operator!=(const QCameraViewfinderSettings &lhs, const QCameraViewfinderSettings &rhs) Q_DECL_NOTHROW
{ return !operator==(lhs, rhs); }
QT_END_NAMESPACE

View File

@@ -62,7 +62,7 @@ class Q_MULTIMEDIA_EXPORT QAbstractVideoFilter : public QObject
Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged)
public:
QAbstractVideoFilter(QObject *parent = 0);
explicit QAbstractVideoFilter(QObject *parent = 0);
~QAbstractVideoFilter();
bool isActive() const;

View File

@@ -38,6 +38,7 @@
#include <qpainter.h>
#include <qvariant.h>
#include <qvideosurfaceformat.h>
#include <private/qmediaopenglhelper_p.h>
#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
#include <qglshaderprogram.h>
@@ -261,6 +262,12 @@ protected:
void initYuv420PTextureInfo(const QSize &size);
void initYv12TextureInfo(const QSize &size);
bool needsSwizzling(const QVideoSurfaceFormat &format) const {
return !QMediaOpenGLHelper::isANGLE()
&& (format.pixelFormat() == QVideoFrame::Format_RGB32
|| format.pixelFormat() == QVideoFrame::Format_ARGB32);
}
#if !defined(QT_OPENGL_ES) && !defined(QT_OPENGL_DYNAMIC)
typedef void (APIENTRY *_glActiveTexture) (GLenum);
_glActiveTexture glActiveTexture;
@@ -702,7 +709,9 @@ QVideoSurfaceArbFpPainter::QVideoSurfaceArbFpPainter(QGLContext *context)
<< QVideoFrame::Format_YUV420P;
m_glPixelFormats
<< QVideoFrame::Format_RGB32
<< QVideoFrame::Format_ARGB32;
<< QVideoFrame::Format_ARGB32
<< QVideoFrame::Format_BGR32
<< QVideoFrame::Format_BGRA32;
}
QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::start(const QVideoSurfaceFormat &format)
@@ -766,9 +775,14 @@ QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::start(const QVideoSurfac
switch (format.pixelFormat()) {
case QVideoFrame::Format_RGB32:
case QVideoFrame::Format_ARGB32:
case QVideoFrame::Format_BGR32:
case QVideoFrame::Format_BGRA32:
m_yuv = false;
m_textureCount = 1;
program = qt_arbfp_rgbShaderProgram;
if (needsSwizzling(format))
program = qt_arbfp_xrgbShaderProgram;
else
program = qt_arbfp_rgbShaderProgram;
break;
default:
break;
@@ -1070,7 +1084,9 @@ QVideoSurfaceGlslPainter::QVideoSurfaceGlslPainter(QGLContext *context)
<< QVideoFrame::Format_YUV420P;
m_glPixelFormats
<< QVideoFrame::Format_RGB32
<< QVideoFrame::Format_ARGB32;
<< QVideoFrame::Format_ARGB32
<< QVideoFrame::Format_BGR32
<< QVideoFrame::Format_BGRA32;
}
QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::start(const QVideoSurfaceFormat &format)
@@ -1138,9 +1154,14 @@ QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::start(const QVideoSurface
switch (format.pixelFormat()) {
case QVideoFrame::Format_RGB32:
case QVideoFrame::Format_ARGB32:
case QVideoFrame::Format_BGR32:
case QVideoFrame::Format_BGRA32:
m_yuv = false;
m_textureCount = 1;
fragmentProgram = qt_glsl_rgbShaderProgram;
if (needsSwizzling(format))
fragmentProgram = qt_glsl_xrgbShaderProgram;
else
fragmentProgram = qt_glsl_rgbShaderProgram;
break;
default:
break;

View File

@@ -157,7 +157,7 @@ void AVFCameraFlashControl::cameraStateChanged(QCamera::State newState)
bool AVFCameraFlashControl::applyFlashSettings()
{
Q_ASSERT(m_session->state() == QCamera::ActiveState);
Q_ASSERT(m_session->requestedState() == QCamera::ActiveState);
AVCaptureDevice *captureDevice = m_session->videoCaptureDevice();
if (!captureDevice) {

View File

@@ -70,32 +70,32 @@ QT_END_NAMESPACE
@private
AVFCameraService *m_service;
QT_MANGLE_NAMESPACE(AVFScopedPointer)<AVAssetWriterInput> m_cameraWriterInput;
QT_MANGLE_NAMESPACE(AVFScopedPointer)<AVCaptureDeviceInput> m_audioInput;
QT_MANGLE_NAMESPACE(AVFScopedPointer)<AVCaptureAudioDataOutput> m_audioOutput;
QT_MANGLE_NAMESPACE(AVFScopedPointer)<AVAssetWriterInput> m_audioWriterInput;
QT_PREPEND_NAMESPACE(AVFScopedPointer)<AVAssetWriterInput> m_cameraWriterInput;
QT_PREPEND_NAMESPACE(AVFScopedPointer)<AVCaptureDeviceInput> m_audioInput;
QT_PREPEND_NAMESPACE(AVFScopedPointer)<AVCaptureAudioDataOutput> m_audioOutput;
QT_PREPEND_NAMESPACE(AVFScopedPointer)<AVAssetWriterInput> m_audioWriterInput;
// High priority serial queue for video output:
QT_MANGLE_NAMESPACE(AVFScopedPointer)<dispatch_queue_t> m_videoQueue;
QT_PREPEND_NAMESPACE(AVFScopedPointer)<dispatch_queue_t> m_videoQueue;
// Serial queue for audio output:
QT_MANGLE_NAMESPACE(AVFScopedPointer)<dispatch_queue_t> m_audioQueue;
QT_PREPEND_NAMESPACE(AVFScopedPointer)<dispatch_queue_t> m_audioQueue;
// Queue to write sample buffers:
__weak dispatch_queue_t m_writerQueue;
QT_MANGLE_NAMESPACE(AVFScopedPointer)<AVAssetWriter> m_assetWriter;
QT_PREPEND_NAMESPACE(AVFScopedPointer)<AVAssetWriter> m_assetWriter;
// Delegate's queue.
__weak dispatch_queue_t m_delegateQueue;
// TODO: QPointer??
QT_PREPEND_NAMESPACE(AVFMediaAssetWriterDelegate) *m_delegate;
bool m_setStartTime;
QT_MANGLE_NAMESPACE(AVFAtomicBool) m_stopped;
QT_PREPEND_NAMESPACE(AVFAtomicBool) m_stopped;
bool m_stoppedInternal;
bool m_aborted;
QT_MANGLE_NAMESPACE(QMutex) m_writerMutex;
QT_PREPEND_NAMESPACE(QMutex) m_writerMutex;
@public
QT_MANGLE_NAMESPACE(AVFAtomicInt64) m_durationInMs;
QT_PREPEND_NAMESPACE(AVFAtomicInt64) m_durationInMs;
@private
CMTime m_startTime;
CMTime m_lastTimeStamp;

View File

@@ -50,19 +50,13 @@ AVFVideoFrameRenderer::AVFVideoFrameRenderer(QAbstractVideoSurface *surface, QOb
: QObject(parent)
, m_videoLayerRenderer(0)
, m_surface(surface)
, m_offscreenSurface(0)
, m_glContext(0)
, 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();
}
AVFVideoFrameRenderer::~AVFVideoFrameRenderer()
@@ -94,7 +88,8 @@ GLuint AVFVideoFrameRenderer::renderLayerToTexture(AVPlayerLayer *layer)
return 0;
renderLayerToFBO(layer, fbo);
m_glContext->doneCurrent();
if (m_glContext)
m_glContext->doneCurrent();
return fbo->texture();
}
@@ -113,7 +108,8 @@ QImage AVFVideoFrameRenderer::renderLayerToImage(AVPlayerLayer *layer)
renderLayerToFBO(layer, fbo);
QImage fboImage = fbo->toImage();
m_glContext->doneCurrent();
if (m_glContext)
m_glContext->doneCurrent();
return fboImage;
}
@@ -125,7 +121,14 @@ QOpenGLFramebufferObject *AVFVideoFrameRenderer::initRenderer(AVPlayerLayer *lay
m_targetSize = QSize(layer.bounds.size.width, layer.bounds.size.height);
//Make sure we have an OpenGL context to make current
if (!m_glContext) {
if (!QOpenGLContext::currentContext() && !m_glContext) {
//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();
//Create OpenGL context and set share context from surface
QOpenGLContext *shareContext = 0;
if (m_surface) {
@@ -151,7 +154,8 @@ QOpenGLFramebufferObject *AVFVideoFrameRenderer::initRenderer(AVPlayerLayer *lay
}
//Need current context
m_glContext->makeCurrent(m_offscreenSurface);
if (m_glContext)
m_glContext->makeCurrent(m_offscreenSurface);
//Create the CARenderer if needed
if (!m_videoLayerRenderer) {

View File

@@ -789,7 +789,7 @@ void DSCameraSession::disconnectGraph()
static bool qt_frameRateRangeGreaterThan(const QCamera::FrameRateRange &r1, const QCamera::FrameRateRange &r2)
{
return r1.second > r2.second;
return r1.maximumFrameRate > r2.maximumFrameRate;
}
void DSCameraSession::updateSourceCapabilities()
@@ -896,8 +896,8 @@ void DSCameraSession::updateSourceCapabilities()
Q_FOREACH (const QCamera::FrameRateRange &frameRateRange, frameRateRanges) {
QCameraViewfinderSettings settings;
settings.setResolution(resolution);
settings.setMinimumFrameRate(frameRateRange.first);
settings.setMaximumFrameRate(frameRateRange.second);
settings.setMinimumFrameRate(frameRateRange.minimumFrameRate);
settings.setMaximumFrameRate(frameRateRange.maximumFrameRate);
settings.setPixelFormat(pixelFormat);
m_supportedViewfinderSettings.append(settings);

View File

@@ -56,7 +56,7 @@
using namespace Microsoft::WRL;
QT_USE_NAMESPACE
QT_BEGIN_NAMESPACE
#define BREAK_IF_FAILED(msg) RETURN_IF_FAILED(msg, break)
#define CONTINUE_IF_FAILED(msg) RETURN_IF_FAILED(msg, continue)
@@ -408,3 +408,5 @@ void QWinRTAbstractVideoRendererControl::present()
QVideoFrame frame(d->videoBuffer, d->format.frameSize(), d->format.pixelFormat());
d->surface->present(frame);
}
QT_END_NAMESPACE

View File

@@ -38,6 +38,7 @@
#include "qwinrtcameravideorenderercontrol.h"
#include "qwinrtvideodeviceselectorcontrol.h"
#include "qwinrtcameraimagecapturecontrol.h"
#include "qwinrtimageencodercontrol.h"
#include <QtCore/qfunctions_winrt.h>
#include <QtCore/QCoreApplication>
@@ -67,7 +68,7 @@ using namespace ABI::Windows::Media::Devices;
using namespace ABI::Windows::Media::MediaProperties;
using namespace ABI::Windows::Storage::Streams;
QT_USE_NAMESPACE
QT_BEGIN_NAMESPACE
#define RETURN_VOID_AND_EMIT_ERROR(msg) \
if (FAILED(hr)) { \
@@ -75,6 +76,10 @@ QT_USE_NAMESPACE
RETURN_VOID_IF_FAILED(msg); \
}
inline uint qHash (const QSize &key) {
return key.width() * key.height();
}
class CriticalSectionLocker
{
public:
@@ -129,6 +134,7 @@ public:
hr = deviceInfo->get_SystemSku(deviceModel.GetAddressOf());
Q_ASSERT_SUCCEEDED(hr);
m_flags |= bufferLockRequired(L"NOKIA RM-976", deviceModel);
m_flags |= bufferLockRequired(L"NOKIA RM-1019", deviceModel);
#endif
}
@@ -453,6 +459,7 @@ public:
QPointer<QWinRTCameraVideoRendererControl> videoRenderer;
QPointer<QWinRTVideoDeviceSelectorControl> videoDeviceSelector;
QPointer<QWinRTCameraImageCaptureControl> imageCaptureControl;
QPointer<QWinRTImageEncoderControl> imageEncoderControl;
};
QWinRTCameraControl::QWinRTCameraControl(QObject *parent)
@@ -470,6 +477,7 @@ QWinRTCameraControl::QWinRTCameraControl(QObject *parent)
this, &QWinRTCameraControl::onBufferRequested);
d->videoDeviceSelector = new QWinRTVideoDeviceSelectorControl(this);
d->imageCaptureControl = new QWinRTCameraImageCaptureControl(this);
d->imageEncoderControl = new QWinRTImageEncoderControl(this);
}
QWinRTCameraControl::~QWinRTCameraControl()
@@ -654,18 +662,18 @@ QCameraImageCaptureControl *QWinRTCameraControl::imageCaptureControl() const
return d->imageCaptureControl;
}
QImageEncoderControl *QWinRTCameraControl::imageEncoderControl() const
{
Q_D(const QWinRTCameraControl);
return d->imageEncoderControl;
}
IMediaCapture *QWinRTCameraControl::handle() const
{
Q_D(const QWinRTCameraControl);
return d->capture.Get();
}
QSize QWinRTCameraControl::imageSize() const
{
Q_D(const QWinRTCameraControl);
return d->size;
}
void QWinRTCameraControl::onBufferRequested()
{
Q_D(QWinRTCameraControl);
@@ -763,10 +771,11 @@ HRESULT QWinRTCameraControl::initialize()
Q_ASSERT_SUCCEEDED(hr);
d->size = QSize();
ComPtr<IVideoEncodingProperties> videoEncodingProperties;
quint32 encodingPropertiesListSize;
hr = encodingPropertiesList->get_Size(&encodingPropertiesListSize);
Q_ASSERT_SUCCEEDED(hr);
QHash<QSize, ComPtr<IVideoEncodingProperties>> videoEncodingPropertiesList;
int pixelCount = 0;
for (quint32 i = 0; i < encodingPropertiesListSize; ++i) {
ComPtr<IMediaEncodingProperties> properties;
hr = encodingPropertiesList->GetAt(i, &properties);
@@ -779,21 +788,33 @@ HRESULT QWinRTCameraControl::initialize()
Q_ASSERT_SUCCEEDED(hr);
hr = videoProperties->get_Height(&height);
Q_ASSERT_SUCCEEDED(hr);
// Choose the highest-quality format
if (int(width * height) > d->size.width() * d->size.height()) {
d->size = QSize(width, height);
videoEncodingProperties = videoProperties;
if (d->captureMode != QCamera::CaptureStillImage && int(width * height) > pixelCount) {
d->size = QSize(width, height);// Choose the Highest-quality format
pixelCount = d->size.width() * d->size.height();
}
videoEncodingPropertiesList.insert(QSize(width, height), videoProperties);
}
if (!videoEncodingProperties || d->size.isEmpty()) {
if (videoEncodingPropertiesList.isEmpty()) {
hr = MF_E_INVALID_FORMAT;
RETURN_HR_IF_FAILED("Failed to find a suitable video format");
}
if (d->captureMode == QCamera::CaptureStillImage) {
d->imageEncoderControl->setSupportedResolutionsList(videoEncodingPropertiesList.keys());
d->size = d->imageEncoderControl->imageSettings().resolution();
}
hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Media_MediaProperties_MediaEncodingProfile).Get(),
&d->encodingProfile);
Q_ASSERT_SUCCEEDED(hr);
const ComPtr<IVideoEncodingProperties> videoEncodingProperties = videoEncodingPropertiesList[d->size];
if (!videoEncodingProperties) {
hr = MF_E_INVALID_FORMAT;
RETURN_HR_IF_FAILED("Failed to find a suitable video format properties");
}
hr = d->encodingProfile->put_Video(videoEncodingProperties.Get());
Q_ASSERT_SUCCEEDED(hr);
if (d->videoRenderer)
@@ -832,3 +853,5 @@ HRESULT QWinRTCameraControl::onRecordLimitationExceeded(IMediaCapture *)
setState(QCamera::LoadedState);
return S_OK;
}
QT_END_NAMESPACE

View File

@@ -60,6 +60,7 @@ QT_BEGIN_NAMESPACE
class QVideoRendererControl;
class QVideoDeviceSelectorControl;
class QCameraImageCaptureControl;
class QImageEncoderControl;
class QWinRTCameraControlPrivate;
class QWinRTCameraControl : public QCameraControl
@@ -83,9 +84,9 @@ public:
QVideoRendererControl *videoRenderer() const;
QVideoDeviceSelectorControl *videoDeviceSelector() const;
QCameraImageCaptureControl *imageCaptureControl() const;
QImageEncoderControl *imageEncoderControl() const;
ABI::Windows::Media::Capture::IMediaCapture *handle() const;
QSize imageSize() const;
private slots:
void onBufferRequested();

View File

@@ -36,6 +36,7 @@
#include "qwinrtcameraimagecapturecontrol.h"
#include "qwinrtcameracontrol.h"
#include "qwinrtimageencodercontrol.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
@@ -64,7 +65,7 @@ using namespace ABI::Windows::Media::MediaProperties;
using namespace ABI::Windows::Storage::Streams;
using namespace ABI::Windows::Graphics::Imaging;
QT_USE_NAMESPACE
QT_BEGIN_NAMESPACE
#define wchar(str) reinterpret_cast<const wchar_t *>(str.utf16())
@@ -166,7 +167,7 @@ int QWinRTCameraImageCaptureControl::capture(const QString &fileName)
hr = g->encodingPropertiesFactory->CreateBmp(&request.imageFormat);
Q_ASSERT_SUCCEEDED(hr);
const QSize imageSize = d->cameraControl->imageSize();
const QSize imageSize = static_cast<QWinRTImageEncoderControl*>(d->cameraControl->imageEncoderControl())->imageSettings().resolution();
hr = request.imageFormat->put_Width(imageSize.width());
Q_ASSERT_SUCCEEDED(hr);
hr = request.imageFormat->put_Height(imageSize.height());
@@ -174,6 +175,10 @@ int QWinRTCameraImageCaptureControl::capture(const QString &fileName)
hr = capture->CapturePhotoToStreamAsync(request.imageFormat.Get(), request.stream.Get(), &request.op);
Q_ASSERT_SUCCEEDED(hr);
if (!request.op) {
qErrnoWarning("Camera photo capture failed.");
return -1;
}
d->requests.insert(request.op.Get(), request);
hr = request.op->put_Completed(Callback<IAsyncActionCompletedHandler>(
@@ -266,10 +271,33 @@ HRESULT QWinRTCameraImageCaptureControl::onCaptureCompleted(IAsyncAction *asyncI
const QImage image(pixelData, pixelWidth, pixelHeight, QImage::Format_RGBA8888,
reinterpret_cast<QImageCleanupFunction>(&CoTaskMemFree), pixelData);
emit imageCaptured(request.id, image);
if (image.save(request.fileName))
QWinRTImageEncoderControl *imageEncoderControl = static_cast<QWinRTImageEncoderControl*>(d->cameraControl->imageEncoderControl());
int imageQuality = 100;
switch (imageEncoderControl->imageSettings().quality()) {
case QMultimedia::VeryLowQuality:
imageQuality = 20;
break;
case QMultimedia::LowQuality:
imageQuality = 40;
break;
case QMultimedia::NormalQuality:
imageQuality = 60;
break;
case QMultimedia::HighQuality:
imageQuality = 80;
break;
case QMultimedia::VeryHighQuality:
imageQuality = 100;
break;
}
if (image.save(request.fileName, imageEncoderControl->imageSettings().codec().toLatin1().data(), imageQuality))
emit imageSaved(request.id, request.fileName);
else
emit error(request.id, QCameraImageCapture::ResourceError, tr("Image saving failed"));
return S_OK;
}
QT_END_NAMESPACE

View File

@@ -37,7 +37,7 @@
#include "qwinrtcamerainfocontrol.h"
#include "qwinrtvideodeviceselectorcontrol.h"
QT_USE_NAMESPACE
QT_BEGIN_NAMESPACE
QWinRTCameraInfoControl::QWinRTCameraInfoControl(QObject *parent)
: QCameraInfoControl(parent)
@@ -53,3 +53,5 @@ int QWinRTCameraInfoControl::cameraOrientation(const QString &deviceName) const
{
return QWinRTVideoDeviceSelectorControl::cameraOrientation(deviceName);
}
QT_END_NAMESPACE

View File

@@ -44,8 +44,9 @@
#include <QtMultimedia/QCameraImageCaptureControl>
#include <QtMultimedia/QVideoRendererControl>
#include <QtMultimedia/QVideoDeviceSelectorControl>
#include <QtMultimedia/QImageEncoderControl>
QT_USE_NAMESPACE
QT_BEGIN_NAMESPACE
class QWinRTCameraServicePrivate
{
@@ -90,6 +91,11 @@ QMediaControl *QWinRTCameraService::requestControl(const char *name)
return d->cameraControl->imageCaptureControl();
}
if (qstrcmp(name, QImageEncoderControl_iid) == 0) {
if (d->cameraControl)
return d->cameraControl->imageEncoderControl();
}
return Q_NULLPTR;
}
@@ -97,3 +103,5 @@ void QWinRTCameraService::releaseControl(QMediaControl *control)
{
Q_UNUSED(control);
}
QT_END_NAMESPACE

View File

@@ -45,7 +45,7 @@
#include <wrl.h>
using namespace Microsoft::WRL;
QT_USE_NAMESPACE
QT_BEGIN_NAMESPACE
class D3DVideoBlitter
{
@@ -210,3 +210,5 @@ void QWinRTCameraVideoRendererControl::discardBuffers()
for (ComPtr<IMF2DBuffer> &buffer : d->buffers)
buffer.Reset();
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,124 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd and/or its subsidiary(-ies).
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL3$
** 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 The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or later 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 2.0 requirements will be
** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qwinrtimageencodercontrol.h"
QT_BEGIN_NAMESPACE
class QWinRTImageEncoderControlPrivate
{
public:
QList<QSize> supportedResolutions;
QImageEncoderSettings imageEncoderSetting;
};
QWinRTImageEncoderControl::QWinRTImageEncoderControl(QObject *parent)
: QImageEncoderControl(parent), d_ptr(new QWinRTImageEncoderControlPrivate)
{
}
QStringList QWinRTImageEncoderControl::supportedImageCodecs() const
{
return QStringList() << QStringLiteral("jpeg");
}
QString QWinRTImageEncoderControl::imageCodecDescription(const QString &codecName) const
{
if (codecName == QStringLiteral("jpeg"))
return tr("JPEG image");
return QString();
}
QList<QSize> QWinRTImageEncoderControl::supportedResolutions(const QImageEncoderSettings &settings, bool *continuous) const
{
Q_UNUSED(settings);
Q_D(const QWinRTImageEncoderControl);
if (continuous)
*continuous = false;
return d->supportedResolutions;
}
QImageEncoderSettings QWinRTImageEncoderControl::imageSettings() const
{
Q_D(const QWinRTImageEncoderControl);
return d->imageEncoderSetting;
}
void QWinRTImageEncoderControl::setImageSettings(const QImageEncoderSettings &settings)
{
Q_D(QWinRTImageEncoderControl);
if (d->imageEncoderSetting == settings)
return;
d->imageEncoderSetting = settings;
applySettings();
}
void QWinRTImageEncoderControl::setSupportedResolutionsList(const QList<QSize> resolution)
{
Q_D(QWinRTImageEncoderControl);
d->supportedResolutions = resolution;
applySettings();
}
void QWinRTImageEncoderControl::applySettings()
{
Q_D(QWinRTImageEncoderControl);
d->imageEncoderSetting.setCodec(QStringLiteral("jpeg"));
QSize requestResolution = d->imageEncoderSetting.resolution();
if (d->supportedResolutions.isEmpty() || d->supportedResolutions.contains(requestResolution))
return;
if (!requestResolution.isValid())
requestResolution = QSize(0, 0);// Find the minimal available resolution
// Find closest resolution from the list
const int pixelCount = requestResolution.width() * requestResolution.height();
int minPixelCountGap = -1;
for (int i = 0; i < d->supportedResolutions.size(); ++i) {
int gap = qAbs(pixelCount - d->supportedResolutions.at(i).width() * d->supportedResolutions.at(i).height());
if (gap < minPixelCountGap || minPixelCountGap < 0) {
minPixelCountGap = gap;
requestResolution = d->supportedResolutions.at(i);
}
}
d->imageEncoderSetting.setResolution(requestResolution);
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,66 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd and/or its subsidiary(-ies).
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL3$
** 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 The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or later 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 2.0 requirements will be
** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QWINRTIMAGEENCODERCONTROL_H
#define QWINRTIMAGEENCODERCONTROL_H
#include <qimageencodercontrol.h>
QT_BEGIN_NAMESPACE
class QWinRTImageEncoderControlPrivate;
class QWinRTImageEncoderControl : public QImageEncoderControl
{
public:
explicit QWinRTImageEncoderControl(QObject *parent = 0);
QStringList supportedImageCodecs() const Q_DECL_OVERRIDE;
QString imageCodecDescription(const QString &codecName) const Q_DECL_OVERRIDE;
QList<QSize> supportedResolutions(const QImageEncoderSettings &settings, bool *continuous = 0) const Q_DECL_OVERRIDE;
QImageEncoderSettings imageSettings() const Q_DECL_OVERRIDE;
void setImageSettings(const QImageEncoderSettings &settings) Q_DECL_OVERRIDE;
void setSupportedResolutionsList(const QList<QSize> resolution);
void applySettings();
private:
QScopedPointer<QWinRTImageEncoderControlPrivate> d_ptr;
Q_DECLARE_PRIVATE(QWinRTImageEncoderControl)
};
QT_END_NAMESPACE
#endif // QWINRTIMAGEENCODERCONTROL_H

View File

@@ -55,7 +55,7 @@
#include <wrl.h>
using namespace Microsoft::WRL;
QT_USE_NAMESPACE
QT_BEGIN_NAMESPACE
#define QT_WINRT_MEDIAPLAYER_STREAM_ID "__qtmultimedia_winrt_player_stream"
@@ -892,3 +892,5 @@ void QWinRTMediaPlayerControl::finishRead()
Q_D(QWinRTMediaPlayerControl);
d->streamProvider->finishRead();
}
QT_END_NAMESPACE

View File

@@ -41,7 +41,7 @@
struct IMFMediaEngineClassFactory;
QT_USE_NAMESPACE
QT_BEGIN_NAMESPACE
class QVideoRendererControl;
@@ -96,4 +96,6 @@ private:
Q_DECLARE_PRIVATE(QWinRTMediaPlayerControl)
};
QT_END_NAMESPACE
#endif // QWINRTMEDIAPLAYERCONTROL_H

View File

@@ -47,7 +47,7 @@
using namespace Microsoft::WRL;
QT_USE_NAMESPACE
QT_BEGIN_NAMESPACE
class QWinRTMediaPlayerServicePrivate
{
@@ -104,3 +104,5 @@ void QWinRTMediaPlayerService::releaseControl(QMediaControl *control)
if (control == d->player)
d->player->deleteLater();
}
QT_END_NAMESPACE

View File

@@ -54,7 +54,7 @@
#include <wrl.h>
using namespace Microsoft::WRL;
QT_USE_NAMESPACE
QT_BEGIN_NAMESPACE
template <typename T>
class D3DDeviceLocker
@@ -149,3 +149,5 @@ bool QWinRTPlayerRendererControl::render(ID3D11Texture2D *texture)
RETURN_FALSE_IF_FAILED("Failed to transfer video frame to DXGI surface");
return true;
}
QT_END_NAMESPACE

View File

@@ -42,7 +42,7 @@
#include "qwinrtcameraservice.h"
#include "qwinrtvideodeviceselectorcontrol.h"
QT_USE_NAMESPACE
QT_BEGIN_NAMESPACE
QMediaService *QWinRTServicePlugin::create(QString const &key)
{
@@ -102,3 +102,5 @@ QByteArray QWinRTServicePlugin::defaultDevice(const QByteArray &service) const
return QByteArray();
}
QT_END_NAMESPACE

View File

@@ -39,7 +39,7 @@
#include <QtMultimedia/QMediaServiceProviderPlugin>
QT_USE_NAMESPACE
QT_BEGIN_NAMESPACE
class QWinRTServicePlugin : public QMediaServiceProviderPlugin
, public QMediaServiceFeaturesInterface
@@ -68,4 +68,6 @@ public:
QByteArray defaultDevice(const QByteArray &service) const Q_DECL_OVERRIDE;
};
QT_END_NAMESPACE
#endif // QWINRTSERVICEPLUGIN_H

View File

@@ -55,7 +55,7 @@ typedef ITypedEventHandler<DeviceWatcher *, DeviceInformation *> DeviceInformati
typedef ITypedEventHandler<DeviceWatcher *, DeviceInformationUpdate *> DeviceInformationUpdateHandler;
typedef ITypedEventHandler<DeviceWatcher *, IInspectable *> DeviceEnumerationCompletedHandler;
QT_USE_NAMESPACE
QT_BEGIN_NAMESPACE
static QString deviceName(IDeviceInformation *device)
{
@@ -386,3 +386,5 @@ void QWinRTVideoDeviceSelectorControl::setSelectedDevice(int index)
emit selectedDeviceChanged(deviceName(d->selectedDevice));
}
}
QT_END_NAMESPACE

View File

@@ -18,7 +18,8 @@ HEADERS += \
qwinrtmediaplayerservice.h \
qwinrtplayerrenderercontrol.h \
qwinrtserviceplugin.h \
qwinrtvideodeviceselectorcontrol.h
qwinrtvideodeviceselectorcontrol.h \
qwinrtimageencodercontrol.h
SOURCES += \
qwinrtabstractvideorenderercontrol.cpp \
@@ -31,7 +32,8 @@ SOURCES += \
qwinrtmediaplayerservice.cpp \
qwinrtplayerrenderercontrol.cpp \
qwinrtserviceplugin.cpp \
qwinrtvideodeviceselectorcontrol.cpp
qwinrtvideodeviceselectorcontrol.cpp \
qwinrtimageencodercontrol.cpp
OTHER_FILES += \
winrt.json

View File

@@ -420,6 +420,17 @@ QList<QVideoFrame::PixelFormat> QSGVideoItemSurface::supportedPixelFormats(
{
QList<QVideoFrame::PixelFormat> formats;
static bool noGLTextures = false;
static bool noGLTexturesChecked = false;
if (handleType == QAbstractVideoBuffer::GLTextureHandle) {
if (!noGLTexturesChecked) {
noGLTexturesChecked = true;
noGLTextures = qEnvironmentVariableIsSet("QT_QUICK_NO_TEXTURE_VIDEOFRAMES");
}
if (noGLTextures)
return formats;
}
foreach (QSGVideoNodeFactoryInterface* factory, m_backend->m_videoNodeFactories)
formats.append(factory->supportedPixelFormats(handleType));