Merge remote-tracking branch 'origin/5.5' into dev

Change-Id: Ic09d6310fcb6d8198b6ec2dc0459c1694e9df8c9
This commit is contained in:
Liang Qi
2015-03-17 16:40:27 +01:00
18 changed files with 397 additions and 250 deletions

View File

@@ -3,14 +3,11 @@ which is assumed to be provided in RGB format. The OpenCL operation is done on
an OpenGL texture using CL-GL interop, without any further readbacks or copies an OpenGL texture using CL-GL interop, without any further readbacks or copies
(except for the initial texture upload, when necessary). (except for the initial texture upload, when necessary).
Currently OS X, Windows with real OpenGL (opengl32.dll) and Linux (GLX only) are Currently OS X, Windows with real OpenGL (opengl32.dll) and Linux (GLX) are
supported. Note that an OpenCL implementation with GPU support is required. The supported. Note that an OpenCL implementation with GPU support is required. The
platform and device selection logic supports NVIDIA, AMD and Intel. Porting to platform and device selection logic supports NVIDIA, AMD and Intel. Porting to
other platforms is probably simple, see clCreateContextFromType. other platforms is probably simple, see clCreateContextFromType.
On Windows you may need to edit testplugin.pro to specify the location of the
OpenCL headers and libraries.
YUV formats are not supported in this example. This is probably not an issue an YUV formats are not supported in this example. This is probably not an issue an
OS X and Windows, but will most likely disable the example on Linux. OS X and Windows, but will most likely disable the example on Linux.

View File

@@ -181,8 +181,6 @@ CLFilterRunnable::CLFilterRunnable(CLFilter *filter) :
CL_WGL_HDC_KHR, (cl_context_properties) wglGetCurrentDC(), CL_WGL_HDC_KHR, (cl_context_properties) wglGetCurrentDC(),
0 }; 0 };
#elif defined(Q_OS_LINUX) #elif defined(Q_OS_LINUX)
// An elegant alternative to glXGetCurrentContext. This will even survive
// (without interop) when using something other than GLX.
QVariant nativeGLXHandle = QOpenGLContext::currentContext()->nativeHandle(); QVariant nativeGLXHandle = QOpenGLContext::currentContext()->nativeHandle();
QGLXNativeContext nativeGLXContext; QGLXNativeContext nativeGLXContext;
if (!nativeGLXHandle.isNull() && nativeGLXHandle.canConvert<QGLXNativeContext>()) if (!nativeGLXHandle.isNull() && nativeGLXHandle.canConvert<QGLXNativeContext>())
@@ -191,6 +189,7 @@ CLFilterRunnable::CLFilterRunnable(CLFilter *filter) :
qWarning("Failed to get the underlying GLX context from the current QOpenGLContext"); qWarning("Failed to get the underlying GLX context from the current QOpenGLContext");
cl_context_properties contextProps[] = { CL_CONTEXT_PLATFORM, (cl_context_properties) platform, cl_context_properties contextProps[] = { CL_CONTEXT_PLATFORM, (cl_context_properties) platform,
CL_GL_CONTEXT_KHR, (cl_context_properties) nativeGLXContext.context(), CL_GL_CONTEXT_KHR, (cl_context_properties) nativeGLXContext.context(),
CL_GLX_DISPLAY_KHR, (cl_context_properties) glXGetCurrentDisplay(),
0 }; 0 };
#endif #endif
@@ -203,17 +202,23 @@ CLFilterRunnable::CLFilterRunnable(CLFilter *filter) :
// Get the GPU device id // Get the GPU device id
#if defined(Q_OS_OSX) #if defined(Q_OS_OSX)
// On OS X, get the "online" device/GPU. This is required for OpenCL/OpenGL context sharing. // On OS X, get the "online" device/GPU. This is required for OpenCL/OpenGL context sharing.
if (clGetGLContextInfoAPPLE(m_clContext, CGLGetCurrentContext(), err = clGetGLContextInfoAPPLE(m_clContext, CGLGetCurrentContext(),
CL_CGL_DEVICE_FOR_CURRENT_VIRTUAL_SCREEN_APPLE, CL_CGL_DEVICE_FOR_CURRENT_VIRTUAL_SCREEN_APPLE,
sizeof(cl_device_id), &m_clDeviceId, NULL) != CL_SUCCESS) { sizeof(cl_device_id), &m_clDeviceId, 0);
if (err != CL_SUCCESS) {
qWarning("Failed to get OpenCL device for current screen: %d", err); qWarning("Failed to get OpenCL device for current screen: %d", err);
return; return;
} }
#else #else
if (clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &m_clDeviceId, 0) != CL_SUCCESS) { clGetGLContextInfoKHR_fn getGLContextInfo = (clGetGLContextInfoKHR_fn) clGetExtensionFunctionAddress("clGetGLContextInfoKHR");
qWarning("Failed to get OpenCL device"); if (!getGLContextInfo || getGLContextInfo(contextProps, CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR,
sizeof(cl_device_id), &m_clDeviceId, 0) != CL_SUCCESS) {
err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &m_clDeviceId, 0);
if (err != CL_SUCCESS) {
qWarning("Failed to get OpenCL device: %d", err);
return; return;
} }
}
#endif #endif
m_clQueue = clCreateCommandQueue(m_clContext, m_clDeviceId, 0, &err); m_clQueue = clCreateCommandQueue(m_clContext, m_clDeviceId, 0, &err);
@@ -291,15 +296,9 @@ QVideoFrame CLFilterRunnable::run(QVideoFrame *input, const QVideoSurfaceFormat
Q_UNUSED(flags); Q_UNUSED(flags);
// This example supports RGB data only, either in system memory (typical with cameras on all // This example supports RGB data only, either in system memory (typical with cameras on all
// platforms) or as an OpenGL texture (e.g. video playback on OS X or on Windows with ANGLE). // platforms) or as an OpenGL texture (e.g. video playback on OS X).
// The latter is the fast path where everything happens on GPU. THe former involves a texture upload. // The latter is the fast path where everything happens on GPU. THe former involves a texture upload.
// ANGLE is not compatible with this example since we only do CL-GL interop, not D3D9/11.
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) {
qWarning("ANGLE is not supported");
return *input;
}
if (!input->isValid() if (!input->isValid()
|| (input->handleType() != QAbstractVideoBuffer::NoHandle || (input->handleType() != QAbstractVideoBuffer::NoHandle
&& input->handleType() != QAbstractVideoBuffer::GLTextureHandle)) { && input->handleType() != QAbstractVideoBuffer::GLTextureHandle)) {
@@ -483,6 +482,9 @@ QVideoFrame InfoFilterRunnable::run(QVideoFrame *input, const QVideoSurfaceForma
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
#ifdef Q_OS_WIN // avoid ANGLE on Windows
QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
#endif
QGuiApplication app(argc, argv); QGuiApplication app(argc, argv);
qmlRegisterType<CLFilter>("qmlvideofilter.cl.test", 1, 0, "CLFilter"); qmlRegisterType<CLFilter>("qmlvideofilter.cl.test", 1, 0, "CLFilter");

View File

@@ -14,9 +14,4 @@ INSTALLS += target
osx: LIBS += -framework OpenCL osx: LIBS += -framework OpenCL
unix: !osx: LIBS += -lOpenCL unix: !osx: LIBS += -lOpenCL
win32:!winrt { win32:!winrt: LIBS += -lopengl32 -lOpenCL
# Edit these as necessary
INCLUDEPATH += c:/cuda/include
LIBPATH += c:/cuda/lib/x64
LIBS += -lopengl32 -lOpenCL
}

View File

@@ -111,13 +111,12 @@ void QGstreamerAudioInputSelector::updateAlsaDevices()
{ {
#ifdef HAVE_ALSA #ifdef HAVE_ALSA
void **hints, **n; void **hints, **n;
int card = -1; if (snd_device_name_hint(-1, "pcm", &hints) < 0) {
qWarning()<<"no alsa devices available";
while (snd_card_next(&card) == 0 && card >= 0) { return;
if (snd_device_name_hint(card, "pcm", &hints) < 0) }
continue;
n = hints; n = hints;
while (*n != NULL) { while (*n != NULL) {
char *name = snd_device_name_get_hint(*n, "NAME"); char *name = snd_device_name_get_hint(*n, "NAME");
char *descr = snd_device_name_get_hint(*n, "DESC"); char *descr = snd_device_name_get_hint(*n, "DESC");
@@ -136,11 +135,9 @@ void QGstreamerAudioInputSelector::updateAlsaDevices()
free(descr); free(descr);
if (io != NULL) if (io != NULL)
free(io); free(io);
++n; n++;
} }
snd_device_name_free_hint(hints); snd_device_name_free_hint(hints);
}
#endif #endif
} }

View File

@@ -42,6 +42,7 @@
#include <QtCore/qstringlist.h> #include <QtCore/qstringlist.h>
#include <QtGui/qimage.h> #include <QtGui/qimage.h>
#include <qaudioformat.h> #include <qaudioformat.h>
#include <QtCore/qelapsedtimer.h>
#include <QtMultimedia/qvideosurfaceformat.h> #include <QtMultimedia/qvideosurfaceformat.h>
#include <gst/audio/audio.h> #include <gst/audio/audio.h>
@@ -510,6 +511,10 @@ Q_GLOBAL_STATIC(FactoryCameraInfoMap, qt_camera_device_info);
QVector<QGstUtils::CameraInfo> QGstUtils::enumerateCameras(GstElementFactory *factory) QVector<QGstUtils::CameraInfo> QGstUtils::enumerateCameras(GstElementFactory *factory)
{ {
static QElapsedTimer camerasCacheAgeTimer;
if (camerasCacheAgeTimer.isValid() && camerasCacheAgeTimer.elapsed() > 500) // ms
qt_camera_device_info()->clear();
FactoryCameraInfoMap::const_iterator it = qt_camera_device_info()->constFind(factory); FactoryCameraInfoMap::const_iterator it = qt_camera_device_info()->constFind(factory);
if (it != qt_camera_device_info()->constEnd()) if (it != qt_camera_device_info()->constEnd())
return *it; return *it;
@@ -568,6 +573,7 @@ QVector<QGstUtils::CameraInfo> QGstUtils::enumerateCameras(GstElementFactory *fa
} }
if (!devices.isEmpty() || !hasVideoSource) { if (!devices.isEmpty() || !hasVideoSource) {
camerasCacheAgeTimer.restart();
return devices; return devices;
} }
} }
@@ -626,6 +632,7 @@ QVector<QGstUtils::CameraInfo> QGstUtils::enumerateCameras(GstElementFactory *fa
} }
qt_safe_close(fd); qt_safe_close(fd);
} }
camerasCacheAgeTimer.restart();
#endif // USE_V4L #endif // USE_V4L
return devices; return devices;

View File

@@ -264,6 +264,8 @@ QAudioBuffer::QAudioBuffer(int numFrames, const QAudioFormat &format, qint64 sta
QAudioBuffer &QAudioBuffer::operator =(const QAudioBuffer &other) QAudioBuffer &QAudioBuffer::operator =(const QAudioBuffer &other)
{ {
if (this->d != other.d) { if (this->d != other.d) {
if (d)
d->deref();
d = QAudioBufferPrivate::acquire(other.d); d = QAudioBufferPrivate::acquire(other.d);
} }
return *this; return *this;

View File

@@ -91,15 +91,16 @@ QVideoSurfaceGenericPainter::QVideoSurfaceGenericPainter()
: m_imageFormat(QImage::Format_Invalid) : m_imageFormat(QImage::Format_Invalid)
, m_scanLineDirection(QVideoSurfaceFormat::TopToBottom) , m_scanLineDirection(QVideoSurfaceFormat::TopToBottom)
{ {
m_imagePixelFormats m_imagePixelFormats << QVideoFrame::Format_RGB32;
<< QVideoFrame::Format_RGB32
<< QVideoFrame::Format_ARGB32
<< QVideoFrame::Format_RGB565;
// The raster formats should be a subset of the GL formats. // The raster formats should be a subset of the GL formats.
#ifndef QT_NO_OPENGL #ifndef QT_NO_OPENGL
if (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGLES) if (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGLES)
#endif #endif
m_imagePixelFormats << QVideoFrame::Format_RGB24; m_imagePixelFormats << QVideoFrame::Format_RGB24;
m_imagePixelFormats << QVideoFrame::Format_ARGB32
<< QVideoFrame::Format_RGB565;
} }
QList<QVideoFrame::PixelFormat> QVideoSurfaceGenericPainter::supportedPixelFormats( QList<QVideoFrame::PixelFormat> QVideoSurfaceGenericPainter::supportedPixelFormats(
@@ -1055,7 +1056,13 @@ QVideoSurfaceGlslPainter::QVideoSurfaceGlslPainter(QGLContext *context)
m_imagePixelFormats m_imagePixelFormats
<< QVideoFrame::Format_RGB32 << QVideoFrame::Format_RGB32
<< QVideoFrame::Format_BGR32 << QVideoFrame::Format_BGR32
<< QVideoFrame::Format_ARGB32 << QVideoFrame::Format_ARGB32;
if (!context->contextHandle()->isOpenGLES()) {
m_imagePixelFormats
<< QVideoFrame::Format_RGB24
<< QVideoFrame::Format_BGR24;
}
m_imagePixelFormats
<< QVideoFrame::Format_RGB565 << QVideoFrame::Format_RGB565
<< QVideoFrame::Format_YUV444 << QVideoFrame::Format_YUV444
<< QVideoFrame::Format_AYUV444 << QVideoFrame::Format_AYUV444
@@ -1064,11 +1071,6 @@ QVideoSurfaceGlslPainter::QVideoSurfaceGlslPainter(QGLContext *context)
m_glPixelFormats m_glPixelFormats
<< QVideoFrame::Format_RGB32 << QVideoFrame::Format_RGB32
<< QVideoFrame::Format_ARGB32; << QVideoFrame::Format_ARGB32;
if (!context->contextHandle()->isOpenGLES()) {
m_imagePixelFormats
<< QVideoFrame::Format_RGB24
<< QVideoFrame::Format_BGR24;
}
} }
QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::start(const QVideoSurfaceFormat &format) QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::start(const QVideoSurfaceFormat &format)

View File

@@ -337,9 +337,14 @@ QList<QByteArray> QAlsaAudioDeviceInfo::availableDevices(QAudio::Mode mode)
#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
// Create a list of all current audio devices that support mode // Create a list of all current audio devices that support mode
void **hints; void **hints, **n;
char *name, *descr, *io; char *name, *descr, *io;
int card = -1;
if(snd_device_name_hint(-1, "pcm", &hints) < 0) {
qWarning() << "no alsa devices available";
return devices;
}
n = hints;
if(mode == QAudio::AudioInput) { if(mode == QAudio::AudioInput) {
filter = "Input"; filter = "Input";
@@ -347,11 +352,6 @@ QList<QByteArray> QAlsaAudioDeviceInfo::availableDevices(QAudio::Mode mode)
filter = "Output"; filter = "Output";
} }
while (snd_card_next(&card) == 0 && card >= 0) {
if (snd_device_name_hint(card, "pcm", &hints) < 0)
continue;
void **n = hints;
while (*n != NULL) { while (*n != NULL) {
name = snd_device_name_get_hint(*n, "NAME"); name = snd_device_name_get_hint(*n, "NAME");
if (name != 0 && qstrcmp(name, "null") != 0) { if (name != 0 && qstrcmp(name, "null") != 0) {
@@ -373,9 +373,7 @@ QList<QByteArray> QAlsaAudioDeviceInfo::availableDevices(QAudio::Mode mode)
free(name); free(name);
++n; ++n;
} }
snd_device_name_free_hint(hints); snd_device_name_free_hint(hints);
}
#else #else
int idx = 0; int idx = 0;
char* name; char* name;
@@ -416,15 +414,14 @@ void QAlsaAudioDeviceInfo::checkSurround()
surround51 = false; surround51 = false;
surround71 = false; surround71 = false;
void **hints; void **hints, **n;
char *name, *descr, *io; char *name, *descr, *io;
int card = -1;
while (snd_card_next(&card) == 0 && card >= 0) { if(snd_device_name_hint(-1, "pcm", &hints) < 0)
if (snd_device_name_hint(card, "pcm", &hints) < 0) return;
continue;
n = hints;
void **n = hints;
while (*n != NULL) { while (*n != NULL) {
name = snd_device_name_get_hint(*n, "NAME"); name = snd_device_name_get_hint(*n, "NAME");
descr = snd_device_name_get_hint(*n, "DESC"); descr = snd_device_name_get_hint(*n, "DESC");
@@ -448,9 +445,7 @@ void QAlsaAudioDeviceInfo::checkSurround()
free(io); free(io);
++n; ++n;
} }
snd_device_name_free_hint(hints); snd_device_name_free_hint(hints);
} }
}
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@@ -307,7 +307,7 @@ void QAndroidMediaPlayerControl::setMedia(const QMediaContent &mediaContent,
{ {
StateChangeNotifier notifier(this); StateChangeNotifier notifier(this);
mReloadingMedia = (mMediaContent == mediaContent); mReloadingMedia = (mMediaContent == mediaContent) && !mPendingSetMedia;
if (!mReloadingMedia) { if (!mReloadingMedia) {
mMediaContent = mediaContent; mMediaContent = mediaContent;
@@ -712,8 +712,8 @@ void QAndroidMediaPlayerControl::resetBufferingProgress()
void QAndroidMediaPlayerControl::flushPendingStates() void QAndroidMediaPlayerControl::flushPendingStates()
{ {
if (mPendingSetMedia) { if (mPendingSetMedia) {
mPendingSetMedia = false;
setMedia(mMediaContent, 0); setMedia(mMediaContent, 0);
mPendingSetMedia = false;
return; return;
} }

View File

@@ -80,6 +80,7 @@ public:
void addProbe(AVFMediaVideoProbeControl *probe); void addProbe(AVFMediaVideoProbeControl *probe);
void removeProbe(AVFMediaVideoProbeControl *probe); void removeProbe(AVFMediaVideoProbeControl *probe);
FourCharCode defaultCodec();
public Q_SLOTS: public Q_SLOTS:
void setState(QCamera::State state); void setState(QCamera::State state);
@@ -119,6 +120,7 @@ private:
QSet<AVFMediaVideoProbeControl *> m_videoProbes; QSet<AVFMediaVideoProbeControl *> m_videoProbes;
QMutex m_videoProbesMutex; QMutex m_videoProbesMutex;
FourCharCode m_defaultCodec;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@@ -41,6 +41,7 @@
#include "avfmediavideoprobecontrol.h" #include "avfmediavideoprobecontrol.h"
#include "avfcameraviewfindersettingscontrol.h" #include "avfcameraviewfindersettingscontrol.h"
#include "avfimageencodercontrol.h" #include "avfimageencodercontrol.h"
#include "avfcamerautility.h"
#include <CoreFoundation/CoreFoundation.h> #include <CoreFoundation/CoreFoundation.h>
#include <Foundation/Foundation.h> #include <Foundation/Foundation.h>
@@ -143,6 +144,7 @@ AVFCameraSession::AVFCameraSession(AVFCameraService *service, QObject *parent)
, m_active(false) , m_active(false)
, m_videoInput(nil) , m_videoInput(nil)
, m_audioInput(nil) , m_audioInput(nil)
, m_defaultCodec(0)
{ {
m_captureSession = [[AVCaptureSession alloc] init]; m_captureSession = [[AVCaptureSession alloc] init];
m_observer = [[AVFCameraSessionObserver alloc] initWithCameraSession:this]; m_observer = [[AVFCameraSessionObserver alloc] initWithCameraSession:this];
@@ -277,6 +279,8 @@ void AVFCameraSession::setState(QCamera::State newState)
Q_EMIT readyToConfigureConnections(); Q_EMIT readyToConfigureConnections();
[m_captureSession commitConfiguration]; [m_captureSession commitConfiguration];
[m_captureSession startRunning]; [m_captureSession startRunning];
m_defaultCodec = 0;
defaultCodec();
applyImageEncoderSettings(); applyImageEncoderSettings();
applyViewfinderSettings(); applyViewfinderSettings();
} }
@@ -407,6 +411,25 @@ void AVFCameraSession::removeProbe(AVFMediaVideoProbeControl *probe)
m_videoProbesMutex.unlock(); m_videoProbesMutex.unlock();
} }
FourCharCode AVFCameraSession::defaultCodec()
{
if (!m_defaultCodec) {
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_7, QSysInfo::MV_IOS_7_0)) {
if (AVCaptureDevice *device = videoCaptureDevice()) {
AVCaptureDeviceFormat *format = device.activeFormat;
if (!format || !format.formatDescription)
return m_defaultCodec;
m_defaultCodec = CMVideoFormatDescriptionGetCodecType(format.formatDescription);
}
}
#else
// TODO: extract media subtype.
#endif
}
return m_defaultCodec;
}
void AVFCameraSession::onCameraFrameFetched(const QVideoFrame &frame) void AVFCameraSession::onCameraFrameFetched(const QVideoFrame &frame)
{ {
m_videoProbesMutex.lock(); m_videoProbesMutex.lock();

View File

@@ -97,13 +97,17 @@ AVFRational qt_float_to_rational(qreal par, int limit);
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) #if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
bool qt_is_video_range_subtype(AVCaptureDeviceFormat *format); QVector<AVCaptureDeviceFormat *> qt_unique_device_formats(AVCaptureDevice *captureDevice,
FourCharCode preferredFormat);
QSize qt_device_format_resolution(AVCaptureDeviceFormat *format); QSize qt_device_format_resolution(AVCaptureDeviceFormat *format);
QSize qt_device_format_high_resolution(AVCaptureDeviceFormat *format); QSize qt_device_format_high_resolution(AVCaptureDeviceFormat *format);
QSize qt_device_format_pixel_aspect_ratio(AVCaptureDeviceFormat *format); QSize qt_device_format_pixel_aspect_ratio(AVCaptureDeviceFormat *format);
QVector<AVFPSRange> qt_device_format_framerates(AVCaptureDeviceFormat *format); QVector<AVFPSRange> qt_device_format_framerates(AVCaptureDeviceFormat *format);
AVCaptureDeviceFormat *qt_find_best_resolution_match(AVCaptureDevice *captureDevice, const QSize &res); AVCaptureDeviceFormat *qt_find_best_resolution_match(AVCaptureDevice *captureDevice, const QSize &res,
AVCaptureDeviceFormat *qt_find_best_framerate_match(AVCaptureDevice *captureDevice, Float64 fps); FourCharCode preferredFormat);
AVCaptureDeviceFormat *qt_find_best_framerate_match(AVCaptureDevice *captureDevice,
FourCharCode preferredFormat,
Float64 fps);
AVFrameRateRange *qt_find_supported_framerate_range(AVCaptureDeviceFormat *format, Float64 fps); AVFrameRateRange *qt_find_supported_framerate_range(AVCaptureDeviceFormat *format, Float64 fps);
#endif #endif

View File

@@ -37,6 +37,7 @@
#include <QtCore/qvector.h> #include <QtCore/qvector.h>
#include <QtCore/qpair.h> #include <QtCore/qpair.h>
#include <functional>
#include <algorithm> #include <algorithm>
#include <limits> #include <limits>
@@ -107,19 +108,6 @@ AVFRational qt_float_to_rational(qreal par, int limit)
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) #if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
bool qt_is_video_range_subtype(AVCaptureDeviceFormat *format)
{
Q_ASSERT(format);
#ifdef Q_OS_IOS
// Use only 420f on iOS, not 420v.
const FourCharCode subType = CMFormatDescriptionGetMediaSubType(format.formatDescription);
return subType == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
#else
Q_UNUSED(format)
#endif
return false;
}
namespace { namespace {
inline bool qt_area_sane(const QSize &size) inline bool qt_area_sane(const QSize &size)
@@ -128,40 +116,25 @@ inline bool qt_area_sane(const QSize &size)
&& std::numeric_limits<int>::max() / size.width() >= size.height(); && std::numeric_limits<int>::max() / size.width() >= size.height();
} }
inline bool avf_format_compare(AVCaptureDeviceFormat *f1, AVCaptureDeviceFormat *f2) struct ResolutionPredicate : std::binary_function<AVCaptureDeviceFormat *, AVCaptureDeviceFormat *, bool>
{ {
Q_ASSERT(f1); bool operator() (AVCaptureDeviceFormat *f1, AVCaptureDeviceFormat *f2)const
Q_ASSERT(f2); {
Q_ASSERT(f1 && f2);
const QSize r1(qt_device_format_resolution(f1)); const QSize r1(qt_device_format_resolution(f1));
const QSize r2(qt_device_format_resolution(f2)); const QSize r2(qt_device_format_resolution(f2));
return r1.width() > r2.width() && r1.height() > r2.height(); return r1.width() < r2.width() || (r2.width() == r1.width() && r1.height() < r2.height());
} }
};
QVector<AVCaptureDeviceFormat *> qt_sort_device_formats(AVCaptureDevice *captureDevice) struct FormatHasNoFPSRange : std::unary_function<AVCaptureDeviceFormat *, bool>
{ {
// Select only formats with framerate ranges + sort them by resoluions, bool operator() (AVCaptureDeviceFormat *format)
Q_ASSERT(captureDevice); {
Q_ASSERT(format);
QVector<AVCaptureDeviceFormat *>sorted; return !format.videoSupportedFrameRateRanges || !format.videoSupportedFrameRateRanges.count;
NSArray *formats = captureDevice.formats;
if (!formats || !formats.count)
return sorted;
sorted.reserve(formats.count);
for (AVCaptureDeviceFormat *format in formats) {
if (qt_is_video_range_subtype(format))
continue;
if (format.videoSupportedFrameRateRanges && format.videoSupportedFrameRateRanges.count) {
const QSize resolution(qt_device_format_resolution(format));
if (!resolution.isNull() && resolution.isValid())
sorted << format;
}
}
std::sort(sorted.begin(), sorted.end(), avf_format_compare);
return sorted;
} }
};
Float64 qt_find_min_framerate_distance(AVCaptureDeviceFormat *format, Float64 fps) Float64 qt_find_min_framerate_distance(AVCaptureDeviceFormat *format, Float64 fps)
{ {
@@ -180,6 +153,50 @@ Float64 qt_find_min_framerate_distance(AVCaptureDeviceFormat *format, Float64 fp
} // Unnamed namespace. } // Unnamed namespace.
QVector<AVCaptureDeviceFormat *> qt_unique_device_formats(AVCaptureDevice *captureDevice, FourCharCode filter)
{
// 'filter' is the format we prefer if we have duplicates.
Q_ASSERT(captureDevice);
QVector<AVCaptureDeviceFormat *> formats;
if (!captureDevice.formats || !captureDevice.formats.count)
return formats;
formats.reserve(captureDevice.formats.count);
for (AVCaptureDeviceFormat *format in captureDevice.formats) {
const QSize resolution(qt_device_format_resolution(format));
if (resolution.isNull() || !resolution.isValid())
continue;
formats << format;
}
if (!formats.size())
return formats;
std::sort(formats.begin(), formats.end(), ResolutionPredicate());
QSize size(qt_device_format_resolution(formats[0]));
FourCharCode codec = CMVideoFormatDescriptionGetCodecType(formats[0].formatDescription);
int last = 0;
for (int i = 1; i < formats.size(); ++i) {
const QSize nextSize(qt_device_format_resolution(formats[i]));
if (nextSize == size) {
if (codec == filter)
continue;
formats[last] = formats[i];
} else {
++last;
formats[last] = formats[i];
size = nextSize;
}
codec = CMVideoFormatDescriptionGetCodecType(formats[i].formatDescription);
}
formats.resize(last + 1);
return formats;
}
QSize qt_device_format_resolution(AVCaptureDeviceFormat *format) QSize qt_device_format_resolution(AVCaptureDeviceFormat *format)
{ {
Q_ASSERT(format); Q_ASSERT(format);
@@ -246,7 +263,9 @@ QSize qt_device_format_pixel_aspect_ratio(AVCaptureDeviceFormat *format)
return QSize(asRatio.first, asRatio.second); return QSize(asRatio.first, asRatio.second);
} }
AVCaptureDeviceFormat *qt_find_best_resolution_match(AVCaptureDevice *captureDevice, const QSize &request) AVCaptureDeviceFormat *qt_find_best_resolution_match(AVCaptureDevice *captureDevice,
const QSize &request,
FourCharCode filter)
{ {
Q_ASSERT(captureDevice); Q_ASSERT(captureDevice);
Q_ASSERT(!request.isNull() && request.isValid()); Q_ASSERT(!request.isNull() && request.isValid());
@@ -254,9 +273,10 @@ AVCaptureDeviceFormat *qt_find_best_resolution_match(AVCaptureDevice *captureDev
if (!captureDevice.formats || !captureDevice.formats.count) if (!captureDevice.formats || !captureDevice.formats.count)
return 0; return 0;
for (AVCaptureDeviceFormat *format in captureDevice.formats) { QVector<AVCaptureDeviceFormat *> formats(qt_unique_device_formats(captureDevice, filter));
if (qt_is_video_range_subtype(format))
continue; for (int i = 0; i < formats.size(); ++i) {
AVCaptureDeviceFormat *format = formats[i];
if (qt_device_format_resolution(format) == request) if (qt_device_format_resolution(format) == request)
return format; return format;
// iOS only (still images). // iOS only (still images).
@@ -269,31 +289,30 @@ AVCaptureDeviceFormat *qt_find_best_resolution_match(AVCaptureDevice *captureDev
typedef QPair<QSize, AVCaptureDeviceFormat *> FormatPair; typedef QPair<QSize, AVCaptureDeviceFormat *> FormatPair;
QVector<FormatPair> formats; QVector<FormatPair> pairs; // default|HR sizes
formats.reserve(captureDevice.formats.count); pairs.reserve(formats.size());
for (AVCaptureDeviceFormat *format in captureDevice.formats) { for (int i = 0; i < formats.size(); ++i) {
if (qt_is_video_range_subtype(format)) AVCaptureDeviceFormat *format = formats[i];
continue;
const QSize res(qt_device_format_resolution(format)); const QSize res(qt_device_format_resolution(format));
if (!res.isNull() && res.isValid() && qt_area_sane(res)) if (!res.isNull() && res.isValid() && qt_area_sane(res))
formats << FormatPair(res, format); pairs << FormatPair(res, format);
const QSize highRes(qt_device_format_high_resolution(format)); const QSize highRes(qt_device_format_high_resolution(format));
if (!highRes.isNull() && highRes.isValid() && qt_area_sane(highRes)) if (!highRes.isNull() && highRes.isValid() && qt_area_sane(highRes))
formats << FormatPair(highRes, format); pairs << FormatPair(highRes, format);
} }
if (!formats.size()) if (!pairs.size())
return 0; return 0;
AVCaptureDeviceFormat *best = formats[0].second; AVCaptureDeviceFormat *best = pairs[0].second;
QSize next(formats[0].first); QSize next(pairs[0].first);
int wDiff = qAbs(request.width() - next.width()); int wDiff = qAbs(request.width() - next.width());
int hDiff = qAbs(request.height() - next.height()); int hDiff = qAbs(request.height() - next.height());
const int area = request.width() * request.height(); const int area = request.width() * request.height();
int areaDiff = qAbs(area - next.width() * next.height()); int areaDiff = qAbs(area - next.width() * next.height());
for (int i = 1; i < formats.size(); ++i) { for (int i = 1; i < pairs.size(); ++i) {
next = formats[i].first; next = pairs[i].first;
const int newWDiff = qAbs(next.width() - request.width()); const int newWDiff = qAbs(next.width() - request.width());
const int newHDiff = qAbs(next.height() - request.height()); const int newHDiff = qAbs(next.height() - request.height());
const int newAreaDiff = qAbs(area - next.width() * next.height()); const int newAreaDiff = qAbs(area - next.width() * next.height());
@@ -302,7 +321,7 @@ AVCaptureDeviceFormat *qt_find_best_resolution_match(AVCaptureDevice *captureDev
|| ((newWDiff <= wDiff || newHDiff <= hDiff) && newAreaDiff <= areaDiff)) { || ((newWDiff <= wDiff || newHDiff <= hDiff) && newAreaDiff <= areaDiff)) {
wDiff = newWDiff; wDiff = newWDiff;
hDiff = newHDiff; hDiff = newHDiff;
best = formats[i].second; best = pairs[i].second;
areaDiff = newAreaDiff; areaDiff = newAreaDiff;
} }
} }
@@ -310,15 +329,21 @@ AVCaptureDeviceFormat *qt_find_best_resolution_match(AVCaptureDevice *captureDev
return best; return best;
} }
AVCaptureDeviceFormat *qt_find_best_framerate_match(AVCaptureDevice *captureDevice, Float64 fps) AVCaptureDeviceFormat *qt_find_best_framerate_match(AVCaptureDevice *captureDevice,
FourCharCode filter,
Float64 fps)
{ {
Q_ASSERT(captureDevice); Q_ASSERT(captureDevice);
Q_ASSERT(fps > 0.); Q_ASSERT(fps > 0.);
const qreal epsilon = 0.1; const qreal epsilon = 0.1;
// Sort formats by their resolution. QVector<AVCaptureDeviceFormat *>sorted(qt_unique_device_formats(captureDevice, filter));
const QVector<AVCaptureDeviceFormat *> sorted(qt_sort_device_formats(captureDevice)); // Sort formats by their resolution in decreasing order:
std::sort(sorted.begin(), sorted.end(), std::not2(ResolutionPredicate()));
// We can use only formats with framerate ranges:
sorted.erase(std::remove_if(sorted.begin(), sorted.end(), FormatHasNoFPSRange()), sorted.end());
if (!sorted.size()) if (!sorted.size())
return nil; return nil;

View File

@@ -279,9 +279,11 @@ QList<QCameraViewfinderSettings> AVFCameraViewfinderSettingsControl2::supportedV
return supportedSettings; return supportedSettings;
} }
for (AVCaptureDeviceFormat *format in m_captureDevice.formats) { const QVector<AVCaptureDeviceFormat *> formats(qt_unique_device_formats(m_captureDevice,
if (qt_is_video_range_subtype(format)) m_session->defaultCodec()));
continue; for (int i = 0; i < formats.size(); ++i) {
AVCaptureDeviceFormat *format = formats[i];
const QSize res(qt_device_format_resolution(format)); const QSize res(qt_device_format_resolution(format));
if (res.isNull() || !res.isValid()) if (res.isNull() || !res.isValid())
continue; continue;
@@ -435,12 +437,14 @@ AVCaptureDeviceFormat *AVFCameraViewfinderSettingsControl2::findBestFormatMatch(
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) #if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_7, QSysInfo::MV_IOS_7_0)) { if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_7, QSysInfo::MV_IOS_7_0)) {
Q_ASSERT(m_captureDevice); Q_ASSERT(m_captureDevice);
Q_ASSERT(m_session);
const QSize &resolution = settings.resolution(); const QSize &resolution = settings.resolution();
if (!resolution.isNull() && resolution.isValid()) { if (!resolution.isNull() && resolution.isValid()) {
// Either the exact match (including high resolution for images on iOS) // Either the exact match (including high resolution for images on iOS)
// or a format with a resolution close to the requested one. // or a format with a resolution close to the requested one.
return qt_find_best_resolution_match(m_captureDevice, resolution); return qt_find_best_resolution_match(m_captureDevice, resolution,
m_session->defaultCodec());
} }
// No resolution requested, what about framerates? // No resolution requested, what about framerates?
@@ -453,7 +457,8 @@ AVCaptureDeviceFormat *AVFCameraViewfinderSettingsControl2::findBestFormatMatch(
const qreal minFPS(settings.minimumFrameRate()); const qreal minFPS(settings.minimumFrameRate());
const qreal maxFPS(settings.maximumFrameRate()); const qreal maxFPS(settings.maximumFrameRate());
if (minFPS || maxFPS) if (minFPS || maxFPS)
return qt_find_best_framerate_match(m_captureDevice, maxFPS ? maxFPS : minFPS); return qt_find_best_framerate_match(m_captureDevice, maxFPS ? maxFPS : minFPS,
m_session->defaultCodec());
// Ignore PAR for the moment (PAR without resolution can // Ignore PAR for the moment (PAR without resolution can
// pick a format with really bad resolution). // pick a format with really bad resolution).
// No need to test pixel format, just return settings. // No need to test pixel format, just return settings.

View File

@@ -48,20 +48,6 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
QSize qt_image_high_resolution(AVCaptureDeviceFormat *format)
{
Q_ASSERT(format);
QSize res;
#if defined(Q_OS_IOS) && QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_8_0)
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_8_0) {
const CMVideoDimensions hrDim(format.highResolutionStillImageDimensions);
res.setWidth(hrDim.width);
res.setHeight(hrDim.height);
}
#endif
return res;
}
AVFImageEncoderControl::AVFImageEncoderControl(AVFCameraService *service) AVFImageEncoderControl::AVFImageEncoderControl(AVFCameraService *service)
: m_service(service) : m_service(service)
{ {
@@ -94,9 +80,11 @@ QList<QSize> AVFImageEncoderControl::supportedResolutions(const QImageEncoderSet
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) #if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_7, QSysInfo::MV_IOS_7_0)) { if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_7, QSysInfo::MV_IOS_7_0)) {
AVCaptureDevice *captureDevice = m_service->session()->videoCaptureDevice(); AVCaptureDevice *captureDevice = m_service->session()->videoCaptureDevice();
for (AVCaptureDeviceFormat *format in captureDevice.formats) { const QVector<AVCaptureDeviceFormat *> formats(qt_unique_device_formats(captureDevice,
if (qt_is_video_range_subtype(format)) m_service->session()->defaultCodec()));
continue;
for (int i = 0; i < formats.size(); ++i) {
AVCaptureDeviceFormat *format = formats[i];
const QSize res(qt_device_format_resolution(format)); const QSize res(qt_device_format_resolution(format));
if (!res.isNull() && res.isValid()) if (!res.isNull() && res.isValid())
@@ -108,7 +96,7 @@ QList<QSize> AVFImageEncoderControl::supportedResolutions(const QImageEncoderSet
// its source AVCaptureDevice instances activeFormat.formatDescription. However, // its source AVCaptureDevice instances activeFormat.formatDescription. However,
// if you set this property to YES, the receiver emits still images at the capture // if you set this property to YES, the receiver emits still images at the capture
// devices highResolutionStillImageDimensions value. // devices highResolutionStillImageDimensions value.
const QSize hrRes(qt_image_high_resolution(format)); const QSize hrRes(qt_device_format_high_resolution(format));
if (!hrRes.isNull() && hrRes.isValid()) if (!hrRes.isNull() && hrRes.isValid())
resolutions << res; resolutions << res;
} }
@@ -152,7 +140,7 @@ QImageEncoderSettings AVFImageEncoderControl::imageSettings() const
AVCaptureStillImageOutput *stillImageOutput = m_service->imageCaptureControl()->stillImageOutput(); AVCaptureStillImageOutput *stillImageOutput = m_service->imageCaptureControl()->stillImageOutput();
if (stillImageOutput.highResolutionStillImageOutputEnabled) if (stillImageOutput.highResolutionStillImageOutputEnabled)
res = qt_image_high_resolution(captureDevice.activeFormat); res = qt_device_format_high_resolution(captureDevice.activeFormat);
} }
#endif #endif
if (res.isNull() || !res.isValid()) { if (res.isNull() || !res.isValid()) {
@@ -179,7 +167,6 @@ void AVFImageEncoderControl::setImageSettings(const QImageEncoderSettings &setti
return; return;
m_settings = settings; m_settings = settings;
applySettings(); applySettings();
} }
@@ -223,7 +210,8 @@ void AVFImageEncoderControl::applySettings()
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) #if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_7, QSysInfo::MV_IOS_7_0)) { if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_7, QSysInfo::MV_IOS_7_0)) {
AVCaptureDevice *captureDevice = m_service->session()->videoCaptureDevice(); AVCaptureDevice *captureDevice = m_service->session()->videoCaptureDevice();
AVCaptureDeviceFormat *match = qt_find_best_resolution_match(captureDevice, res); AVCaptureDeviceFormat *match = qt_find_best_resolution_match(captureDevice, res,
m_service->session()->defaultCodec());
if (!match) { if (!match) {
qDebugCamera() << Q_FUNC_INFO << "unsupported resolution:" << res; qDebugCamera() << Q_FUNC_INFO << "unsupported resolution:" << res;
@@ -242,7 +230,7 @@ void AVFImageEncoderControl::applySettings()
#if defined(Q_OS_IOS) && QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_8_0) #if defined(Q_OS_IOS) && QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_8_0)
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_8_0) { if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_8_0) {
AVCaptureStillImageOutput *imageOutput = m_service->imageCaptureControl()->stillImageOutput(); AVCaptureStillImageOutput *imageOutput = m_service->imageCaptureControl()->stillImageOutput();
if (res == qt_image_high_resolution(captureDevice.activeFormat)) if (res == qt_device_format_high_resolution(captureDevice.activeFormat))
imageOutput.highResolutionStillImageOutputEnabled = YES; imageOutput.highResolutionStillImageOutputEnabled = YES;
else else
imageOutput.highResolutionStillImageOutputEnabled = NO; imageOutput.highResolutionStillImageOutputEnabled = NO;

View File

@@ -6,7 +6,11 @@
TEMPLATE = subdirs TEMPLATE = subdirs
SUBDIRS += m3u videonode SUBDIRS += m3u
qtHaveModule(quick) {
SUBDIRS += videonode
}
android { android {
SUBDIRS += android opensles SUBDIRS += android opensles

View File

@@ -41,7 +41,11 @@ MFAudioDecoderControl::MFAudioDecoderControl(QObject *parent)
, m_resampler(0) , m_resampler(0)
, m_state(QAudioDecoder::StoppedState) , m_state(QAudioDecoder::StoppedState)
, m_device(0) , m_device(0)
, m_mfInputStreamID(0)
, m_mfOutputStreamID(0)
, m_bufferReady(false) , m_bufferReady(false)
, m_duration(0)
, m_position(0)
, m_loadingSource(false) , m_loadingSource(false)
, m_mfOutputType(0) , m_mfOutputType(0)
, m_convertSample(0) , m_convertSample(0)
@@ -53,8 +57,6 @@ MFAudioDecoderControl::MFAudioDecoderControl(QObject *parent)
qCritical("MFAudioDecoderControl: Failed to create resampler(CLSID_CResamplerMediaObject)!"); qCritical("MFAudioDecoderControl: Failed to create resampler(CLSID_CResamplerMediaObject)!");
return; return;
} }
m_mfInputStreamID = 0;
m_mfOutputStreamID = 0;
m_resampler->AddInputStreams(1, &m_mfInputStreamID); m_resampler->AddInputStreams(1, &m_mfInputStreamID);
connect(m_sourceResolver, SIGNAL(mediaSourceReady()), this, SLOT(handleMediaSourceReady())); connect(m_sourceResolver, SIGNAL(mediaSourceReady()), this, SLOT(handleMediaSourceReady()));

View File

@@ -81,31 +81,46 @@ class tst_QMediaPlayer: public QObject
Q_OBJECT Q_OBJECT
public slots: public slots:
void initTestCase_data();
void initTestCase(); void initTestCase();
void cleanupTestCase(); void cleanupTestCase();
void init(); void init();
void cleanup(); void cleanup();
private slots: private slots:
void testNullService_data();
void testNullService(); void testNullService();
void testValid(); void testValid();
void testMedia_data();
void testMedia(); void testMedia();
void testDuration_data();
void testDuration(); void testDuration();
void testPosition_data();
void testPosition(); void testPosition();
void testVolume_data();
void testVolume(); void testVolume();
void testMuted_data();
void testMuted(); void testMuted();
void testIsAvailable(); void testIsAvailable();
void testVideoAvailable_data();
void testVideoAvailable(); void testVideoAvailable();
void testBufferStatus_data();
void testBufferStatus(); void testBufferStatus();
void testSeekable_data();
void testSeekable(); void testSeekable();
void testPlaybackRate_data();
void testPlaybackRate(); void testPlaybackRate();
void testError_data();
void testError(); void testError();
void testErrorString_data();
void testErrorString(); void testErrorString();
void testService(); void testService();
void testPlay_data();
void testPlay(); void testPlay();
void testPause_data();
void testPause(); void testPause();
void testStop_data();
void testStop(); void testStop();
void testMediaStatus_data();
void testMediaStatus(); void testMediaStatus();
void testPlaylist(); void testPlaylist();
void testNetworkAccess(); void testNetworkAccess();
@@ -120,12 +135,14 @@ private slots:
void testSupportedMimeTypes(); void testSupportedMimeTypes();
private: private:
void setupCommonTestData();
MockMediaServiceProvider *mockProvider; MockMediaServiceProvider *mockProvider;
MockMediaPlayerService *mockService; MockMediaPlayerService *mockService;
QMediaPlayer *player; QMediaPlayer *player;
}; };
void tst_QMediaPlayer::initTestCase_data() void tst_QMediaPlayer::setupCommonTestData()
{ {
QTest::addColumn<bool>("valid"); QTest::addColumn<bool>("valid");
QTest::addColumn<QMediaPlayer::State>("state"); QTest::addColumn<QMediaPlayer::State>("state");
@@ -193,6 +210,11 @@ void tst_QMediaPlayer::cleanup()
delete mockService; delete mockService;
} }
void tst_QMediaPlayer::testNullService_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testNullService() void tst_QMediaPlayer::testNullService()
{ {
mockProvider->service = 0; mockProvider->service = 0;
@@ -217,7 +239,7 @@ void tst_QMediaPlayer::testNullService()
QCOMPARE(player.availability(), QMultimedia::ServiceMissing); QCOMPARE(player.availability(), QMultimedia::ServiceMissing);
{ {
QFETCH_GLOBAL(QMediaContent, mediaContent); QFETCH(QMediaContent, mediaContent);
QSignalSpy spy(&player, SIGNAL(currentMediaChanged(QMediaContent))); QSignalSpy spy(&player, SIGNAL(currentMediaChanged(QMediaContent)));
QFile file; QFile file;
@@ -249,8 +271,8 @@ void tst_QMediaPlayer::testNullService()
QCOMPARE(stateSpy.count(), 0); QCOMPARE(stateSpy.count(), 0);
QCOMPARE(statusSpy.count(), 0); QCOMPARE(statusSpy.count(), 0);
} { } {
QFETCH_GLOBAL(int, volume); QFETCH(int, volume);
QFETCH_GLOBAL(bool, muted); QFETCH(bool, muted);
QSignalSpy volumeSpy(&player, SIGNAL(volumeChanged(int))); QSignalSpy volumeSpy(&player, SIGNAL(volumeChanged(int)));
QSignalSpy mutingSpy(&player, SIGNAL(mutedChanged(bool))); QSignalSpy mutingSpy(&player, SIGNAL(mutedChanged(bool)));
@@ -263,7 +285,7 @@ void tst_QMediaPlayer::testNullService()
QCOMPARE(player.isMuted(), false); QCOMPARE(player.isMuted(), false);
QCOMPARE(mutingSpy.count(), 0); QCOMPARE(mutingSpy.count(), 0);
} { } {
QFETCH_GLOBAL(qint64, position); QFETCH(qint64, position);
QSignalSpy spy(&player, SIGNAL(positionChanged(qint64))); QSignalSpy spy(&player, SIGNAL(positionChanged(qint64)));
@@ -271,7 +293,7 @@ void tst_QMediaPlayer::testNullService()
QCOMPARE(player.position(), qint64(0)); QCOMPARE(player.position(), qint64(0));
QCOMPARE(spy.count(), 0); QCOMPARE(spy.count(), 0);
} { } {
QFETCH_GLOBAL(qreal, playbackRate); QFETCH(qreal, playbackRate);
QSignalSpy spy(&player, SIGNAL(playbackRateChanged(qreal))); QSignalSpy spy(&player, SIGNAL(playbackRateChanged(qreal)));
@@ -307,16 +329,21 @@ void tst_QMediaPlayer::testNullService()
void tst_QMediaPlayer::testValid() void tst_QMediaPlayer::testValid()
{ {
/* /*
QFETCH_GLOBAL(bool, valid); QFETCH(bool, valid);
mockService->setIsValid(valid); mockService->setIsValid(valid);
QCOMPARE(player->isValid(), valid); QCOMPARE(player->isValid(), valid);
*/ */
} }
void tst_QMediaPlayer::testMedia_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testMedia() void tst_QMediaPlayer::testMedia()
{ {
QFETCH_GLOBAL(QMediaContent, mediaContent); QFETCH(QMediaContent, mediaContent);
mockService->setMedia(mediaContent); mockService->setMedia(mediaContent);
QCOMPARE(player->currentMedia(), mediaContent); QCOMPARE(player->currentMedia(), mediaContent);
@@ -327,20 +354,30 @@ void tst_QMediaPlayer::testMedia()
QCOMPARE((QBuffer*)player->mediaStream(), &stream); QCOMPARE((QBuffer*)player->mediaStream(), &stream);
} }
void tst_QMediaPlayer::testDuration_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testDuration() void tst_QMediaPlayer::testDuration()
{ {
QFETCH_GLOBAL(qint64, duration); QFETCH(qint64, duration);
mockService->setDuration(duration); mockService->setDuration(duration);
QVERIFY(player->duration() == duration); QVERIFY(player->duration() == duration);
} }
void tst_QMediaPlayer::testPosition_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testPosition() void tst_QMediaPlayer::testPosition()
{ {
QFETCH_GLOBAL(bool, valid); QFETCH(bool, valid);
QFETCH_GLOBAL(bool, seekable); QFETCH(bool, seekable);
QFETCH_GLOBAL(qint64, position); QFETCH(qint64, position);
QFETCH_GLOBAL(qint64, duration); QFETCH(qint64, duration);
mockService->setIsValid(valid); mockService->setIsValid(valid);
mockService->setSeekable(seekable); mockService->setSeekable(seekable);
@@ -384,10 +421,15 @@ void tst_QMediaPlayer::testPosition()
} }
} }
void tst_QMediaPlayer::testVolume_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testVolume() void tst_QMediaPlayer::testVolume()
{ {
QFETCH_GLOBAL(bool, valid); QFETCH(bool, valid);
QFETCH_GLOBAL(int, volume); QFETCH(int, volume);
mockService->setVolume(volume); mockService->setVolume(volume);
QVERIFY(player->volume() == volume); QVERIFY(player->volume() == volume);
@@ -415,11 +457,16 @@ void tst_QMediaPlayer::testVolume()
} }
} }
void tst_QMediaPlayer::testMuted_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testMuted() void tst_QMediaPlayer::testMuted()
{ {
QFETCH_GLOBAL(bool, valid); QFETCH(bool, valid);
QFETCH_GLOBAL(bool, muted); QFETCH(bool, muted);
QFETCH_GLOBAL(int, volume); QFETCH(int, volume);
if (valid) { if (valid) {
mockService->setMuted(muted); mockService->setMuted(muted);
@@ -434,34 +481,54 @@ void tst_QMediaPlayer::testMuted()
} }
} }
void tst_QMediaPlayer::testVideoAvailable_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testVideoAvailable() void tst_QMediaPlayer::testVideoAvailable()
{ {
QFETCH_GLOBAL(bool, videoAvailable); QFETCH(bool, videoAvailable);
mockService->setVideoAvailable(videoAvailable); mockService->setVideoAvailable(videoAvailable);
QVERIFY(player->isVideoAvailable() == videoAvailable); QVERIFY(player->isVideoAvailable() == videoAvailable);
} }
void tst_QMediaPlayer::testBufferStatus_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testBufferStatus() void tst_QMediaPlayer::testBufferStatus()
{ {
QFETCH_GLOBAL(int, bufferStatus); QFETCH(int, bufferStatus);
mockService->setBufferStatus(bufferStatus); mockService->setBufferStatus(bufferStatus);
QVERIFY(player->bufferStatus() == bufferStatus); QVERIFY(player->bufferStatus() == bufferStatus);
} }
void tst_QMediaPlayer::testSeekable_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testSeekable() void tst_QMediaPlayer::testSeekable()
{ {
QFETCH_GLOBAL(bool, seekable); QFETCH(bool, seekable);
mockService->setSeekable(seekable); mockService->setSeekable(seekable);
QVERIFY(player->isSeekable() == seekable); QVERIFY(player->isSeekable() == seekable);
} }
void tst_QMediaPlayer::testPlaybackRate_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testPlaybackRate() void tst_QMediaPlayer::testPlaybackRate()
{ {
QFETCH_GLOBAL(bool, valid); QFETCH(bool, valid);
QFETCH_GLOBAL(qreal, playbackRate); QFETCH(qreal, playbackRate);
if (valid) { if (valid) {
mockService->setPlaybackRate(playbackRate); mockService->setPlaybackRate(playbackRate);
@@ -474,17 +541,27 @@ void tst_QMediaPlayer::testPlaybackRate()
} }
} }
void tst_QMediaPlayer::testError_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testError() void tst_QMediaPlayer::testError()
{ {
QFETCH_GLOBAL(QMediaPlayer::Error, error); QFETCH(QMediaPlayer::Error, error);
mockService->setError(error); mockService->setError(error);
QVERIFY(player->error() == error); QVERIFY(player->error() == error);
} }
void tst_QMediaPlayer::testErrorString_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testErrorString() void tst_QMediaPlayer::testErrorString()
{ {
QFETCH_GLOBAL(QString, errorString); QFETCH(QString, errorString);
mockService->setErrorString(errorString); mockService->setErrorString(errorString);
QVERIFY(player->errorString() == errorString); QVERIFY(player->errorString() == errorString);
@@ -499,7 +576,7 @@ void tst_QMediaPlayer::testIsAvailable()
void tst_QMediaPlayer::testService() void tst_QMediaPlayer::testService()
{ {
/* /*
QFETCH_GLOBAL(bool, valid); QFETCH(bool, valid);
mockService->setIsValid(valid); mockService->setIsValid(valid);
@@ -510,11 +587,16 @@ void tst_QMediaPlayer::testService()
*/ */
} }
void tst_QMediaPlayer::testPlay_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testPlay() void tst_QMediaPlayer::testPlay()
{ {
QFETCH_GLOBAL(bool, valid); QFETCH(bool, valid);
QFETCH_GLOBAL(QMediaContent, mediaContent); QFETCH(QMediaContent, mediaContent);
QFETCH_GLOBAL(QMediaPlayer::State, state); QFETCH(QMediaPlayer::State, state);
mockService->setIsValid(valid); mockService->setIsValid(valid);
mockService->setState(state); mockService->setState(state);
@@ -536,11 +618,16 @@ void tst_QMediaPlayer::testPlay()
} }
} }
void tst_QMediaPlayer::testPause_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testPause() void tst_QMediaPlayer::testPause()
{ {
QFETCH_GLOBAL(bool, valid); QFETCH(bool, valid);
QFETCH_GLOBAL(QMediaContent, mediaContent); QFETCH(QMediaContent, mediaContent);
QFETCH_GLOBAL(QMediaPlayer::State, state); QFETCH(QMediaPlayer::State, state);
mockService->setIsValid(valid); mockService->setIsValid(valid);
mockService->setState(state); mockService->setState(state);
@@ -562,10 +649,15 @@ void tst_QMediaPlayer::testPause()
} }
} }
void tst_QMediaPlayer::testStop_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testStop() void tst_QMediaPlayer::testStop()
{ {
QFETCH_GLOBAL(QMediaContent, mediaContent); QFETCH(QMediaContent, mediaContent);
QFETCH_GLOBAL(QMediaPlayer::State, state); QFETCH(QMediaPlayer::State, state);
mockService->setState(state); mockService->setState(state);
mockService->setMedia(mediaContent); mockService->setMedia(mediaContent);
@@ -586,9 +678,14 @@ void tst_QMediaPlayer::testStop()
} }
} }
void tst_QMediaPlayer::testMediaStatus_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testMediaStatus() void tst_QMediaPlayer::testMediaStatus()
{ {
QFETCH_GLOBAL(int, bufferStatus); QFETCH(int, bufferStatus);
int bufferSignals = 0; int bufferSignals = 0;
player->setNotifyInterval(10); player->setNotifyInterval(10);