Merge remote-tracking branch 'origin/5.4' into 5.5
Conflicts: src/multimedia/playback/playlistfileparser.cpp src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp Change-Id: I52950def2b8283ae15797d05d4ead6a1256eba19
This commit is contained in:
@@ -58,25 +58,25 @@ int AVFCameraDeviceControl::deviceCount() const
|
||||
|
||||
QString AVFCameraDeviceControl::deviceName(int index) const
|
||||
{
|
||||
const QList<QByteArray> &devices = AVFCameraSession::availableCameraDevices();
|
||||
const QList<AVFCameraInfo> &devices = AVFCameraSession::availableCameraDevices();
|
||||
if (index < 0 || index >= devices.count())
|
||||
return QString();
|
||||
|
||||
return QString::fromUtf8(devices.at(index));
|
||||
return QString::fromUtf8(devices.at(index).deviceId);
|
||||
}
|
||||
|
||||
QString AVFCameraDeviceControl::deviceDescription(int index) const
|
||||
{
|
||||
const QList<QByteArray> &devices = AVFCameraSession::availableCameraDevices();
|
||||
const QList<AVFCameraInfo> &devices = AVFCameraSession::availableCameraDevices();
|
||||
if (index < 0 || index >= devices.count())
|
||||
return QString();
|
||||
|
||||
return AVFCameraSession::cameraDeviceInfo(devices.at(index)).description;
|
||||
return devices.at(index).description;
|
||||
}
|
||||
|
||||
int AVFCameraDeviceControl::defaultDevice() const
|
||||
{
|
||||
return AVFCameraSession::availableCameraDevices().indexOf(AVFCameraSession::defaultCameraDevice());
|
||||
return AVFCameraSession::defaultCameraIndex();
|
||||
}
|
||||
|
||||
int AVFCameraDeviceControl::selectedDevice() const
|
||||
|
||||
@@ -63,18 +63,26 @@ void AVFServicePlugin::release(QMediaService *service)
|
||||
|
||||
QByteArray AVFServicePlugin::defaultDevice(const QByteArray &service) const
|
||||
{
|
||||
if (service == Q_MEDIASERVICE_CAMERA)
|
||||
return AVFCameraSession::defaultCameraDevice();
|
||||
if (service == Q_MEDIASERVICE_CAMERA) {
|
||||
int i = AVFCameraSession::defaultCameraIndex();
|
||||
if (i != -1)
|
||||
return AVFCameraSession::availableCameraDevices().at(i).deviceId;
|
||||
}
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QList<QByteArray> AVFServicePlugin::devices(const QByteArray &service) const
|
||||
{
|
||||
if (service == Q_MEDIASERVICE_CAMERA)
|
||||
return AVFCameraSession::availableCameraDevices();
|
||||
QList<QByteArray> devs;
|
||||
|
||||
return QList<QByteArray>();
|
||||
if (service == Q_MEDIASERVICE_CAMERA) {
|
||||
const QList<AVFCameraInfo> &cameras = AVFCameraSession::availableCameraDevices();
|
||||
Q_FOREACH (const AVFCameraInfo &info, cameras)
|
||||
devs.append(info.deviceId);
|
||||
}
|
||||
|
||||
return devs;
|
||||
}
|
||||
|
||||
QString AVFServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device)
|
||||
|
||||
@@ -54,6 +54,7 @@ struct AVFCameraInfo
|
||||
AVFCameraInfo() : position(QCamera::UnspecifiedPosition), orientation(0)
|
||||
{ }
|
||||
|
||||
QByteArray deviceId;
|
||||
QString description;
|
||||
QCamera::Position position;
|
||||
int orientation;
|
||||
@@ -66,8 +67,8 @@ public:
|
||||
AVFCameraSession(AVFCameraService *service, QObject *parent = 0);
|
||||
~AVFCameraSession();
|
||||
|
||||
static const QByteArray &defaultCameraDevice();
|
||||
static const QList<QByteArray> &availableCameraDevices();
|
||||
static int defaultCameraIndex();
|
||||
static const QList<AVFCameraInfo> &availableCameraDevices();
|
||||
static AVFCameraInfo cameraDeviceInfo(const QByteArray &device);
|
||||
|
||||
void setVideoOutput(AVFCameraRendererControl *output);
|
||||
@@ -102,9 +103,8 @@ private:
|
||||
void applyImageEncoderSettings();
|
||||
void applyViewfinderSettings();
|
||||
|
||||
static QByteArray m_defaultCameraDevice;
|
||||
static QList<QByteArray> m_cameraDevices;
|
||||
static QMap<QByteArray, AVFCameraInfo> m_cameraInfo;
|
||||
static int m_defaultCameraIndex;
|
||||
static QList<AVFCameraInfo> m_cameraDevices;
|
||||
|
||||
AVFCameraService *m_service;
|
||||
AVFCameraRendererControl *m_videoOutput;
|
||||
|
||||
@@ -48,14 +48,14 @@
|
||||
|
||||
#include <QtCore/qdatetime.h>
|
||||
#include <QtCore/qurl.h>
|
||||
#include <QtCore/qelapsedtimer.h>
|
||||
|
||||
#include <QtCore/qdebug.h>
|
||||
|
||||
QT_USE_NAMESPACE
|
||||
|
||||
QByteArray AVFCameraSession::m_defaultCameraDevice;
|
||||
QList<QByteArray> AVFCameraSession::m_cameraDevices;
|
||||
QMap<QByteArray, AVFCameraInfo> AVFCameraSession::m_cameraInfo;
|
||||
int AVFCameraSession::m_defaultCameraIndex;
|
||||
QList<AVFCameraInfo> AVFCameraSession::m_cameraDevices;
|
||||
|
||||
@interface AVFCameraSessionObserver : NSObject
|
||||
{
|
||||
@@ -169,45 +169,55 @@ AVFCameraSession::~AVFCameraSession()
|
||||
[m_captureSession release];
|
||||
}
|
||||
|
||||
const QByteArray &AVFCameraSession::defaultCameraDevice()
|
||||
int AVFCameraSession::defaultCameraIndex()
|
||||
{
|
||||
if (m_cameraDevices.isEmpty())
|
||||
updateCameraDevices();
|
||||
|
||||
return m_defaultCameraDevice;
|
||||
updateCameraDevices();
|
||||
return m_defaultCameraIndex;
|
||||
}
|
||||
|
||||
const QList<QByteArray> &AVFCameraSession::availableCameraDevices()
|
||||
const QList<AVFCameraInfo> &AVFCameraSession::availableCameraDevices()
|
||||
{
|
||||
if (m_cameraDevices.isEmpty())
|
||||
updateCameraDevices();
|
||||
|
||||
updateCameraDevices();
|
||||
return m_cameraDevices;
|
||||
}
|
||||
|
||||
AVFCameraInfo AVFCameraSession::cameraDeviceInfo(const QByteArray &device)
|
||||
{
|
||||
if (m_cameraDevices.isEmpty())
|
||||
updateCameraDevices();
|
||||
updateCameraDevices();
|
||||
|
||||
return m_cameraInfo.value(device);
|
||||
Q_FOREACH (const AVFCameraInfo &info, m_cameraDevices) {
|
||||
if (info.deviceId == device)
|
||||
return info;
|
||||
}
|
||||
|
||||
return AVFCameraInfo();
|
||||
}
|
||||
|
||||
void AVFCameraSession::updateCameraDevices()
|
||||
{
|
||||
m_defaultCameraDevice.clear();
|
||||
#ifdef Q_OS_IOS
|
||||
// Cameras can't change dynamically on iOS. Update only once.
|
||||
if (!m_cameraDevices.isEmpty())
|
||||
return;
|
||||
#else
|
||||
// On OS X, cameras can be added or removed. Update the list every time, but not more than
|
||||
// once every 500 ms
|
||||
static QElapsedTimer timer;
|
||||
if (timer.isValid() && timer.elapsed() < 500) // ms
|
||||
return;
|
||||
#endif
|
||||
|
||||
m_defaultCameraIndex = -1;
|
||||
m_cameraDevices.clear();
|
||||
m_cameraInfo.clear();
|
||||
|
||||
AVCaptureDevice *defaultDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
|
||||
if (defaultDevice)
|
||||
m_defaultCameraDevice = QByteArray([[defaultDevice uniqueID] UTF8String]);
|
||||
|
||||
NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
|
||||
for (AVCaptureDevice *device in videoDevices) {
|
||||
QByteArray deviceId([[device uniqueID] UTF8String]);
|
||||
if (defaultDevice && [defaultDevice.uniqueID isEqualToString:device.uniqueID])
|
||||
m_defaultCameraIndex = m_cameraDevices.count();
|
||||
|
||||
AVFCameraInfo info;
|
||||
info.deviceId = QByteArray([[device uniqueID] UTF8String]);
|
||||
info.description = QString::fromNSString([device localizedName]);
|
||||
|
||||
// There is no API to get the camera sensor orientation, however, cameras are always
|
||||
@@ -232,9 +242,12 @@ void AVFCameraSession::updateCameraDevices()
|
||||
break;
|
||||
}
|
||||
|
||||
m_cameraDevices << deviceId;
|
||||
m_cameraInfo.insert(deviceId, info);
|
||||
m_cameraDevices.append(info);
|
||||
}
|
||||
|
||||
#ifndef Q_OS_IOS
|
||||
timer.restart();
|
||||
#endif
|
||||
}
|
||||
|
||||
void AVFCameraSession::setVideoOutput(AVFCameraRendererControl *output)
|
||||
|
||||
@@ -36,6 +36,10 @@
|
||||
#import <AVFoundation/AVAudioSession.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0)
|
||||
#include <AudioToolbox/AudioToolbox.h>
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@interface CoreAudioSessionObserver : NSObject
|
||||
@@ -71,19 +75,24 @@ QT_BEGIN_NAMESPACE
|
||||
self->m_sessionManager = sessionManager;
|
||||
self->m_audioSession = [AVAudioSession sharedInstance];
|
||||
|
||||
//Set up observers
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(audioSessionInterruption:)
|
||||
name:AVAudioSessionInterruptionNotification
|
||||
object:self->m_audioSession];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(audioSessionMediaServicesWereReset:)
|
||||
name:AVAudioSessionMediaServicesWereResetNotification
|
||||
object:self->m_audioSession];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(audioSessionRouteChange:)
|
||||
name:AVAudioSessionRouteChangeNotification
|
||||
object:self->m_audioSession];
|
||||
#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0)
|
||||
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_6_0)
|
||||
#endif
|
||||
{
|
||||
//Set up observers
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(audioSessionInterruption:)
|
||||
name:AVAudioSessionInterruptionNotification
|
||||
object:self->m_audioSession];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(audioSessionMediaServicesWereReset:)
|
||||
name:AVAudioSessionMediaServicesWereResetNotification
|
||||
object:self->m_audioSession];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(audioSessionRouteChange:)
|
||||
name:AVAudioSessionRouteChangeNotification
|
||||
object:self->m_audioSession];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
@@ -93,15 +102,22 @@ QT_BEGIN_NAMESPACE
|
||||
#ifdef QT_DEBUG_COREAUDIO
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
#endif
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:AVAudioSessionInterruptionNotification
|
||||
object:self->m_audioSession];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:AVAudioSessionMediaServicesWereResetNotification
|
||||
object:self->m_audioSession];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:AVAudioSessionRouteChangeNotification
|
||||
object:self->m_audioSession];
|
||||
|
||||
#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0)
|
||||
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_6_0)
|
||||
#endif
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:AVAudioSessionInterruptionNotification
|
||||
object:self->m_audioSession];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:AVAudioSessionMediaServicesWereResetNotification
|
||||
object:self->m_audioSession];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:AVAudioSessionRouteChangeNotification
|
||||
object:self->m_audioSession];
|
||||
}
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@@ -261,6 +277,9 @@ bool CoreAudioSessionManager::setCategory(CoreAudioSessionManager::AudioSessionC
|
||||
targetCategory = AVAudioSessionCategoryAudioProcessing;
|
||||
break;
|
||||
case CoreAudioSessionManager::MultiRoute:
|
||||
#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0)
|
||||
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_6_0)
|
||||
#endif
|
||||
targetCategory = AVAudioSessionCategoryMultiRoute;
|
||||
break;
|
||||
}
|
||||
@@ -268,9 +287,16 @@ bool CoreAudioSessionManager::setCategory(CoreAudioSessionManager::AudioSessionC
|
||||
if (targetCategory == nil)
|
||||
return false;
|
||||
|
||||
return [[m_sessionObserver audioSession] setCategory:targetCategory
|
||||
withOptions:(AVAudioSessionCategoryOptions)options
|
||||
error:nil];
|
||||
#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0)
|
||||
if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_6_0) {
|
||||
return [[m_sessionObserver audioSession] setCategory:targetCategory error:nil];
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
return [[m_sessionObserver audioSession] setCategory:targetCategory
|
||||
withOptions:(AVAudioSessionCategoryOptions)options
|
||||
error:nil];
|
||||
}
|
||||
}
|
||||
|
||||
bool CoreAudioSessionManager::setMode(CoreAudioSessionManager::AudioSessionModes mode)
|
||||
@@ -293,6 +319,9 @@ bool CoreAudioSessionManager::setMode(CoreAudioSessionManager::AudioSessionModes
|
||||
targetMode = AVAudioSessionModeMeasurement;
|
||||
break;
|
||||
case CoreAudioSessionManager::MoviePlayback:
|
||||
#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0)
|
||||
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_6_0)
|
||||
#endif
|
||||
targetMode = AVAudioSessionModeMoviePlayback;
|
||||
break;
|
||||
}
|
||||
@@ -321,7 +350,11 @@ CoreAudioSessionManager::AudioSessionCategorys CoreAudioSessionManager::category
|
||||
localCategory = PlayAndRecord;
|
||||
} else if (category == AVAudioSessionCategoryAudioProcessing) {
|
||||
localCategory = AudioProcessing;
|
||||
} else if (category == AVAudioSessionCategoryMultiRoute) {
|
||||
} else if (
|
||||
#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0)
|
||||
QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_6_0 &&
|
||||
#endif
|
||||
category == AVAudioSessionCategoryMultiRoute) {
|
||||
localCategory = MultiRoute;
|
||||
}
|
||||
|
||||
@@ -343,7 +376,11 @@ CoreAudioSessionManager::AudioSessionModes CoreAudioSessionManager::mode()
|
||||
localMode = VideoRecording;
|
||||
} else if (mode == AVAudioSessionModeMeasurement) {
|
||||
localMode = Measurement;
|
||||
} else if (mode == AVAudioSessionModeMoviePlayback) {
|
||||
} else if (
|
||||
#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0)
|
||||
QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_6_0 &&
|
||||
#endif
|
||||
mode == AVAudioSessionModeMoviePlayback) {
|
||||
localMode = MoviePlayback;
|
||||
}
|
||||
|
||||
@@ -372,12 +409,32 @@ QList<QByteArray> CoreAudioSessionManager::outputDevices()
|
||||
|
||||
float CoreAudioSessionManager::currentIOBufferDuration()
|
||||
{
|
||||
return [[m_sessionObserver audioSession] IOBufferDuration];
|
||||
#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0)
|
||||
if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_6_0) {
|
||||
Float32 duration;
|
||||
UInt32 size = sizeof(duration);
|
||||
AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration, &size, &duration);
|
||||
return duration;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
return [[m_sessionObserver audioSession] IOBufferDuration];
|
||||
}
|
||||
}
|
||||
|
||||
float CoreAudioSessionManager::preferredSampleRate()
|
||||
{
|
||||
return [[m_sessionObserver audioSession] preferredSampleRate];
|
||||
#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0)
|
||||
if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_6_0) {
|
||||
Float64 sampleRate;
|
||||
UInt32 size = sizeof(sampleRate);
|
||||
AudioSessionGetProperty(kAudioSessionProperty_PreferredHardwareSampleRate, &size, &sampleRate);
|
||||
return sampleRate;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
return [[m_sessionObserver audioSession] preferredSampleRate];
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef QT_DEBUG_COREAUDIO
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtCore/qdebug.h>
|
||||
#include <QWidget>
|
||||
#include <QFile>
|
||||
#include <QtConcurrent/QtConcurrentRun>
|
||||
#include <QtMultimedia/qabstractvideobuffer.h>
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <qelapsedtimer.h>
|
||||
|
||||
#include "dsvideodevicecontrol.h"
|
||||
#include "dscamerasession.h"
|
||||
@@ -48,33 +49,37 @@ extern const CLSID CLSID_VideoInputDeviceCategory;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_GLOBAL_STATIC(QList<DSVideoDeviceInfo>, deviceList)
|
||||
|
||||
DSVideoDeviceControl::DSVideoDeviceControl(QObject *parent)
|
||||
: QVideoDeviceSelectorControl(parent)
|
||||
{
|
||||
m_session = qobject_cast<DSCameraSession*>(parent);
|
||||
|
||||
enumerateDevices(&m_devices, &m_descriptions);
|
||||
|
||||
selected = 0;
|
||||
}
|
||||
|
||||
int DSVideoDeviceControl::deviceCount() const
|
||||
{
|
||||
return m_devices.count();
|
||||
updateDevices();
|
||||
return deviceList->count();
|
||||
}
|
||||
|
||||
QString DSVideoDeviceControl::deviceName(int index) const
|
||||
{
|
||||
if (index >= 0 && index <= m_devices.count())
|
||||
return QString::fromUtf8(m_devices.at(index).constData());
|
||||
updateDevices();
|
||||
|
||||
if (index >= 0 && index <= deviceList->count())
|
||||
return QString::fromUtf8(deviceList->at(index).first.constData());
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString DSVideoDeviceControl::deviceDescription(int index) const
|
||||
{
|
||||
if (index >= 0 && index <= m_descriptions.count())
|
||||
return m_descriptions.at(index);
|
||||
updateDevices();
|
||||
|
||||
if (index >= 0 && index <= deviceList->count())
|
||||
return deviceList->at(index).second;
|
||||
|
||||
return QString();
|
||||
}
|
||||
@@ -89,10 +94,34 @@ int DSVideoDeviceControl::selectedDevice() const
|
||||
return selected;
|
||||
}
|
||||
|
||||
void DSVideoDeviceControl::enumerateDevices(QList<QByteArray> *devices, QStringList *descriptions)
|
||||
void DSVideoDeviceControl::setSelectedDevice(int index)
|
||||
{
|
||||
devices->clear();
|
||||
descriptions->clear();
|
||||
updateDevices();
|
||||
|
||||
if (index >= 0 && index < deviceList->count()) {
|
||||
if (m_session) {
|
||||
QString device = deviceList->at(index).first;
|
||||
if (device.startsWith("ds:"))
|
||||
device.remove(0,3);
|
||||
m_session->setDevice(device);
|
||||
}
|
||||
selected = index;
|
||||
}
|
||||
}
|
||||
|
||||
const QList<DSVideoDeviceInfo> &DSVideoDeviceControl::availableDevices()
|
||||
{
|
||||
updateDevices();
|
||||
return *deviceList;
|
||||
}
|
||||
|
||||
void DSVideoDeviceControl::updateDevices()
|
||||
{
|
||||
static QElapsedTimer timer;
|
||||
if (timer.isValid() && timer.elapsed() < 500) // ms
|
||||
return;
|
||||
|
||||
deviceList->clear();
|
||||
|
||||
ICreateDevEnum* pDevEnum = NULL;
|
||||
IEnumMoniker* pEnum = NULL;
|
||||
@@ -116,7 +145,9 @@ void DSVideoDeviceControl::enumerateDevices(QList<QByteArray> *devices, QStringL
|
||||
if (SUCCEEDED(hr)) {
|
||||
QString output(QString::fromWCharArray(strName));
|
||||
mallocInterface->Free(strName);
|
||||
devices->append(output.toUtf8().constData());
|
||||
|
||||
DSVideoDeviceInfo devInfo;
|
||||
devInfo.first = output.toUtf8();
|
||||
|
||||
IPropertyBag *pPropBag;
|
||||
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)(&pPropBag));
|
||||
@@ -130,7 +161,9 @@ void DSVideoDeviceControl::enumerateDevices(QList<QByteArray> *devices, QStringL
|
||||
}
|
||||
pPropBag->Release();
|
||||
}
|
||||
descriptions->append(output);
|
||||
devInfo.second = output;
|
||||
|
||||
deviceList->append(devInfo);
|
||||
}
|
||||
pMoniker->Release();
|
||||
}
|
||||
@@ -139,19 +172,8 @@ void DSVideoDeviceControl::enumerateDevices(QList<QByteArray> *devices, QStringL
|
||||
}
|
||||
pDevEnum->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void DSVideoDeviceControl::setSelectedDevice(int index)
|
||||
{
|
||||
if (index >= 0 && index < m_devices.count()) {
|
||||
if (m_session) {
|
||||
QString device = m_devices.at(index);
|
||||
if (device.startsWith("ds:"))
|
||||
device.remove(0,3);
|
||||
m_session->setDevice(device);
|
||||
}
|
||||
selected = index;
|
||||
}
|
||||
timer.restart();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -42,6 +42,8 @@ class DSCameraSession;
|
||||
|
||||
//QTM_USE_NAMESPACE
|
||||
|
||||
typedef QPair<QByteArray, QString> DSVideoDeviceInfo;
|
||||
|
||||
class DSVideoDeviceControl : public QVideoDeviceSelectorControl
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -54,17 +56,15 @@ public:
|
||||
int defaultDevice() const;
|
||||
int selectedDevice() const;
|
||||
|
||||
static void enumerateDevices(QList<QByteArray> *devices, QStringList *descriptions);
|
||||
static const QList<DSVideoDeviceInfo> &availableDevices();
|
||||
|
||||
public Q_SLOTS:
|
||||
void setSelectedDevice(int index);
|
||||
|
||||
private:
|
||||
static void updateDevices();
|
||||
|
||||
DSCameraSession* m_session;
|
||||
|
||||
QList<QByteArray> m_devices;
|
||||
QStringList m_descriptions;
|
||||
|
||||
int selected;
|
||||
};
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
#include "dsvideodevicecontrol.h"
|
||||
|
||||
#ifdef QMEDIA_DIRECTSHOW_CAMERA
|
||||
#include <QtCore/QElapsedTimer>
|
||||
#include <dshow.h>
|
||||
#include "dscameraservice.h"
|
||||
#endif
|
||||
@@ -122,9 +121,9 @@ QByteArray DSServicePlugin::defaultDevice(const QByteArray &service) const
|
||||
{
|
||||
#ifdef QMEDIA_DIRECTSHOW_CAMERA
|
||||
if (service == Q_MEDIASERVICE_CAMERA) {
|
||||
updateDevices();
|
||||
|
||||
return m_defaultCameraDevice;
|
||||
const QList<DSVideoDeviceInfo> &devs = DSVideoDeviceControl::availableDevices();
|
||||
if (!devs.isEmpty())
|
||||
return devs.first().first;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -133,52 +132,29 @@ QByteArray DSServicePlugin::defaultDevice(const QByteArray &service) const
|
||||
|
||||
QList<QByteArray> DSServicePlugin::devices(const QByteArray &service) const
|
||||
{
|
||||
QList<QByteArray> result;
|
||||
|
||||
#ifdef QMEDIA_DIRECTSHOW_CAMERA
|
||||
if (service == Q_MEDIASERVICE_CAMERA) {
|
||||
updateDevices();
|
||||
|
||||
return m_cameraDevices;
|
||||
const QList<DSVideoDeviceInfo> &devs = DSVideoDeviceControl::availableDevices();
|
||||
Q_FOREACH (const DSVideoDeviceInfo &info, devs)
|
||||
result.append(info.first);
|
||||
}
|
||||
#endif
|
||||
|
||||
return QList<QByteArray>();
|
||||
return result;
|
||||
}
|
||||
|
||||
QString DSServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device)
|
||||
{
|
||||
#ifdef QMEDIA_DIRECTSHOW_CAMERA
|
||||
if (service == Q_MEDIASERVICE_CAMERA) {
|
||||
updateDevices();
|
||||
|
||||
for (int i=0; i<m_cameraDevices.count(); i++)
|
||||
if (m_cameraDevices[i] == device)
|
||||
return m_cameraDescriptions[i];
|
||||
const QList<DSVideoDeviceInfo> &devs = DSVideoDeviceControl::availableDevices();
|
||||
Q_FOREACH (const DSVideoDeviceInfo &info, devs) {
|
||||
if (info.first == device)
|
||||
return info.second;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return QString();
|
||||
}
|
||||
|
||||
#ifdef QMEDIA_DIRECTSHOW_CAMERA
|
||||
|
||||
void DSServicePlugin::updateDevices() const
|
||||
{
|
||||
static QElapsedTimer timer;
|
||||
if (timer.isValid() && timer.elapsed() < 500) // ms
|
||||
return;
|
||||
|
||||
addRefCount();
|
||||
|
||||
m_defaultCameraDevice.clear();
|
||||
DSVideoDeviceControl::enumerateDevices(&m_cameraDevices, &m_cameraDescriptions);
|
||||
|
||||
if (m_cameraDevices.isEmpty()) {
|
||||
qWarning() << "No camera devices found";
|
||||
} else {
|
||||
m_defaultCameraDevice = m_cameraDevices.first();
|
||||
}
|
||||
|
||||
releaseRefCount();
|
||||
timer.restart();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -65,15 +65,6 @@ public:
|
||||
QByteArray defaultDevice(const QByteArray &service) const;
|
||||
QList<QByteArray> devices(const QByteArray &service) const;
|
||||
QString deviceDescription(const QByteArray &service, const QByteArray &device);
|
||||
|
||||
private:
|
||||
#ifdef QMEDIA_DIRECTSHOW_CAMERA
|
||||
void updateDevices() const;
|
||||
|
||||
mutable QByteArray m_defaultCameraDevice;
|
||||
mutable QList<QByteArray> m_cameraDevices;
|
||||
mutable QStringList m_cameraDescriptions;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // DSSERVICEPLUGIN_H
|
||||
|
||||
@@ -160,3 +160,5 @@ void MmRendererMetaDataReaderControl::setMetaData(const MmRendererMetaData &data
|
||||
if (metaDataAvailable != oldMetaDataAvailable)
|
||||
emit metaDataAvailableChanged(metaDataAvailable);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include <QtCore/QDataStream>
|
||||
#include <mmsystem.h>
|
||||
#include "qwindowsaudiodeviceinfo.h"
|
||||
#include "qwindowsaudioutils.h"
|
||||
|
||||
#if defined(Q_CC_MINGW) && !defined(__MINGW64_VERSION_MAJOR)
|
||||
struct IBaseFilter; // Needed for strmif.h from stock MinGW.
|
||||
@@ -167,8 +168,7 @@ QString QWindowsAudioDeviceInfo::deviceName() const
|
||||
|
||||
QStringList QWindowsAudioDeviceInfo::supportedCodecs()
|
||||
{
|
||||
updateLists();
|
||||
return codecz;
|
||||
return QStringList() << QStringLiteral("audio/pcm");
|
||||
}
|
||||
|
||||
QList<int> QWindowsAudioDeviceInfo::supportedSampleRates()
|
||||
@@ -191,8 +191,7 @@ QList<int> QWindowsAudioDeviceInfo::supportedSampleSizes()
|
||||
|
||||
QList<QAudioFormat::Endian> QWindowsAudioDeviceInfo::supportedByteOrders()
|
||||
{
|
||||
updateLists();
|
||||
return byteOrderz;
|
||||
return QList<QAudioFormat::Endian>() << QAudioFormat::LittleEndian;
|
||||
}
|
||||
|
||||
QList<QAudioFormat::SampleType> QWindowsAudioDeviceInfo::supportedSampleTypes()
|
||||
@@ -213,118 +212,50 @@ void QWindowsAudioDeviceInfo::close()
|
||||
|
||||
bool QWindowsAudioDeviceInfo::testSettings(const QAudioFormat& format) const
|
||||
{
|
||||
// Set nearest to closest settings that do work.
|
||||
// See if what is in settings will work (return value).
|
||||
|
||||
bool failed = false;
|
||||
bool match = false;
|
||||
|
||||
// check codec
|
||||
for( int i = 0; i < codecz.count(); i++) {
|
||||
if (format.codec() == codecz.at(i))
|
||||
match = true;
|
||||
}
|
||||
if (!match) failed = true;
|
||||
|
||||
// check channel
|
||||
match = false;
|
||||
if (!failed) {
|
||||
for (int i = 0; i < channelz.count(); i++) {
|
||||
if (format.channelCount() == channelz.at(i)) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
WAVEFORMATEXTENSIBLE wfx;
|
||||
if (qt_convertFormat(format, &wfx)) {
|
||||
// query only, do not open device
|
||||
if (mode == QAudio::AudioOutput) {
|
||||
return (waveOutOpen(NULL, UINT_PTR(devId), &wfx.Format, NULL, NULL,
|
||||
WAVE_FORMAT_QUERY) == MMSYSERR_NOERROR);
|
||||
} else { // AudioInput
|
||||
return (waveInOpen(NULL, UINT_PTR(devId), &wfx.Format, NULL, NULL,
|
||||
WAVE_FORMAT_QUERY) == MMSYSERR_NOERROR);
|
||||
}
|
||||
if (!match)
|
||||
failed = true;
|
||||
}
|
||||
|
||||
// check sampleRate
|
||||
match = false;
|
||||
if (!failed) {
|
||||
for (int i = 0; i < sampleRatez.count(); i++) {
|
||||
if (format.sampleRate() == sampleRatez.at(i)) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match)
|
||||
failed = true;
|
||||
}
|
||||
|
||||
// check sample size
|
||||
match = false;
|
||||
if (!failed) {
|
||||
for( int i = 0; i < sizez.count(); i++) {
|
||||
if (format.sampleSize() == sizez.at(i)) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match)
|
||||
failed = true;
|
||||
}
|
||||
|
||||
// check byte order
|
||||
match = false;
|
||||
if (!failed) {
|
||||
for( int i = 0; i < byteOrderz.count(); i++) {
|
||||
if (format.byteOrder() == byteOrderz.at(i)) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match)
|
||||
failed = true;
|
||||
}
|
||||
|
||||
// check sample type
|
||||
match = false;
|
||||
if (!failed) {
|
||||
for( int i = 0; i < typez.count(); i++) {
|
||||
if (format.sampleType() == typez.at(i)) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match)
|
||||
failed = true;
|
||||
}
|
||||
|
||||
if(!failed) {
|
||||
// settings work
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void QWindowsAudioDeviceInfo::updateLists()
|
||||
{
|
||||
// redo all lists based on current settings
|
||||
bool match = false;
|
||||
if (!sizez.isEmpty())
|
||||
return;
|
||||
|
||||
bool hasCaps = false;
|
||||
DWORD fmt = 0;
|
||||
|
||||
if(mode == QAudio::AudioOutput) {
|
||||
WAVEOUTCAPS woc;
|
||||
if (waveOutGetDevCaps(devId, &woc, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR) {
|
||||
match = true;
|
||||
hasCaps = true;
|
||||
fmt = woc.dwFormats;
|
||||
}
|
||||
} else {
|
||||
WAVEINCAPS woc;
|
||||
if (waveInGetDevCaps(devId, &woc, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR) {
|
||||
match = true;
|
||||
hasCaps = true;
|
||||
fmt = woc.dwFormats;
|
||||
}
|
||||
}
|
||||
|
||||
sizez.clear();
|
||||
sampleRatez.clear();
|
||||
channelz.clear();
|
||||
byteOrderz.clear();
|
||||
typez.clear();
|
||||
codecz.clear();
|
||||
|
||||
if(match) {
|
||||
if (hasCaps) {
|
||||
// Check sample size
|
||||
if ((fmt & WAVE_FORMAT_1M08)
|
||||
|| (fmt & WAVE_FORMAT_1S08)
|
||||
|| (fmt & WAVE_FORMAT_2M08)
|
||||
@@ -334,8 +265,7 @@ void QWindowsAudioDeviceInfo::updateLists()
|
||||
|| (fmt & WAVE_FORMAT_48M08)
|
||||
|| (fmt & WAVE_FORMAT_48S08)
|
||||
|| (fmt & WAVE_FORMAT_96M08)
|
||||
|| (fmt & WAVE_FORMAT_96S08)
|
||||
) {
|
||||
|| (fmt & WAVE_FORMAT_96S08)) {
|
||||
sizez.append(8);
|
||||
}
|
||||
if ((fmt & WAVE_FORMAT_1M16)
|
||||
@@ -347,10 +277,11 @@ void QWindowsAudioDeviceInfo::updateLists()
|
||||
|| (fmt & WAVE_FORMAT_48M16)
|
||||
|| (fmt & WAVE_FORMAT_48S16)
|
||||
|| (fmt & WAVE_FORMAT_96M16)
|
||||
|| (fmt & WAVE_FORMAT_96S16)
|
||||
) {
|
||||
|| (fmt & WAVE_FORMAT_96S16)) {
|
||||
sizez.append(16);
|
||||
}
|
||||
|
||||
// Check sample rate
|
||||
if ((fmt & WAVE_FORMAT_1M08)
|
||||
|| (fmt & WAVE_FORMAT_1S08)
|
||||
|| (fmt & WAVE_FORMAT_1M16)
|
||||
@@ -381,23 +312,81 @@ void QWindowsAudioDeviceInfo::updateLists()
|
||||
|| (fmt & WAVE_FORMAT_96S16)) {
|
||||
sampleRatez.append(96000);
|
||||
}
|
||||
channelz.append(1);
|
||||
channelz.append(2);
|
||||
if (mode == QAudio::AudioOutput) {
|
||||
channelz.append(4);
|
||||
channelz.append(6);
|
||||
channelz.append(8);
|
||||
}
|
||||
|
||||
byteOrderz.append(QAudioFormat::LittleEndian);
|
||||
// Check channel count
|
||||
if (fmt & WAVE_FORMAT_1M08
|
||||
|| fmt & WAVE_FORMAT_1M16
|
||||
|| fmt & WAVE_FORMAT_2M08
|
||||
|| fmt & WAVE_FORMAT_2M16
|
||||
|| fmt & WAVE_FORMAT_4M08
|
||||
|| fmt & WAVE_FORMAT_4M16
|
||||
|| fmt & WAVE_FORMAT_48M08
|
||||
|| fmt & WAVE_FORMAT_48M16
|
||||
|| fmt & WAVE_FORMAT_96M08
|
||||
|| fmt & WAVE_FORMAT_96M16) {
|
||||
channelz.append(1);
|
||||
}
|
||||
if (fmt & WAVE_FORMAT_1S08
|
||||
|| fmt & WAVE_FORMAT_1S16
|
||||
|| fmt & WAVE_FORMAT_2S08
|
||||
|| fmt & WAVE_FORMAT_2S16
|
||||
|| fmt & WAVE_FORMAT_4S08
|
||||
|| fmt & WAVE_FORMAT_4S16
|
||||
|| fmt & WAVE_FORMAT_48S08
|
||||
|| fmt & WAVE_FORMAT_48S16
|
||||
|| fmt & WAVE_FORMAT_96S08
|
||||
|| fmt & WAVE_FORMAT_96S16) {
|
||||
channelz.append(2);
|
||||
}
|
||||
|
||||
typez.append(QAudioFormat::SignedInt);
|
||||
typez.append(QAudioFormat::UnSignedInt);
|
||||
|
||||
codecz.append(QLatin1String("audio/pcm"));
|
||||
// WAVEOUTCAPS and WAVEINCAPS contains information only for the previously tested parameters.
|
||||
// WaveOut and WaveInt might actually support more formats, the only way to know is to try
|
||||
// opening the device with it.
|
||||
QAudioFormat testFormat;
|
||||
testFormat.setCodec(QStringLiteral("audio/pcm"));
|
||||
testFormat.setByteOrder(QAudioFormat::LittleEndian);
|
||||
testFormat.setSampleType(QAudioFormat::SignedInt);
|
||||
testFormat.setChannelCount(channelz.first());
|
||||
testFormat.setSampleRate(sampleRatez.at(sampleRatez.size() / 2));
|
||||
testFormat.setSampleSize(sizez.last());
|
||||
const QAudioFormat defaultTestFormat(testFormat);
|
||||
|
||||
// Check if float samples are supported
|
||||
testFormat.setSampleType(QAudioFormat::Float);
|
||||
testFormat.setSampleSize(32);
|
||||
if (testSettings(testFormat))
|
||||
typez.append(QAudioFormat::Float);
|
||||
|
||||
// Check channel counts > 2
|
||||
testFormat = defaultTestFormat;
|
||||
for (int i = 3; i < 19; ++i) { // <mmreg.h> defines 18 different channels
|
||||
testFormat.setChannelCount(i);
|
||||
if (testSettings(testFormat))
|
||||
channelz.append(i);
|
||||
}
|
||||
|
||||
// Check more sample sizes
|
||||
testFormat = defaultTestFormat;
|
||||
QList<int> testSampleSizes = QList<int>() << 24 << 32 << 48 << 64;
|
||||
Q_FOREACH (int s, testSampleSizes) {
|
||||
testFormat.setSampleSize(s);
|
||||
if (testSettings(testFormat))
|
||||
sizez.append(s);
|
||||
}
|
||||
|
||||
// Check more sample rates
|
||||
testFormat = defaultTestFormat;
|
||||
QList<int> testSampleRates = QList<int>() << 8000 << 16000 << 32000 << 88200 << 192000;
|
||||
Q_FOREACH (int r, testSampleRates) {
|
||||
testFormat.setSampleRate(r);
|
||||
if (testSettings(testFormat))
|
||||
sampleRatez.append(r);
|
||||
}
|
||||
std::sort(sampleRatez.begin(), sampleRatez.end());
|
||||
}
|
||||
if (sampleRatez.count() > 0)
|
||||
sampleRatez.prepend(8000);
|
||||
}
|
||||
|
||||
QList<QByteArray> QWindowsAudioDeviceInfo::availableDevices(QAudio::Mode mode)
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
||||
const unsigned int MAX_SAMPLE_RATES = 5;
|
||||
const unsigned int SAMPLE_RATES[] = { 8000, 11025, 22050, 44100, 48000 };
|
||||
|
||||
@@ -91,15 +90,14 @@ private:
|
||||
QAudio::Mode mode;
|
||||
QString device;
|
||||
quint32 devId;
|
||||
QAudioFormat nearest;
|
||||
QList<int> sampleRatez;
|
||||
QList<int> channelz;
|
||||
QList<int> sizez;
|
||||
QList<QAudioFormat::Endian> byteOrderz;
|
||||
QStringList codecz;
|
||||
QList<QAudioFormat::SampleType> typez;
|
||||
};
|
||||
|
||||
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
||||
|
||||
@@ -298,18 +298,9 @@ bool QWindowsAudioInput::open()
|
||||
|
||||
period_size = 0;
|
||||
|
||||
if (!settings.isValid()) {
|
||||
if (!qt_convertFormat(settings, &wfx)) {
|
||||
qWarning("QAudioInput: open error, invalid format.");
|
||||
} else if (settings.channelCount() <= 0) {
|
||||
qWarning("QAudioInput: open error, invalid number of channels (%d).",
|
||||
settings.channelCount());
|
||||
} else if (settings.sampleSize() <= 0) {
|
||||
qWarning("QAudioInput: open error, invalid sample size (%d).",
|
||||
settings.sampleSize());
|
||||
} else if (settings.sampleRate() < 8000 || settings.sampleRate() > 96000) {
|
||||
qWarning("QAudioInput: open error, sample rate out of range (%d).", settings.sampleRate());
|
||||
} else if (buffer_size == 0) {
|
||||
|
||||
buffer_size
|
||||
= (settings.sampleRate()
|
||||
* settings.channelCount()
|
||||
@@ -329,20 +320,12 @@ bool QWindowsAudioInput::open()
|
||||
|
||||
timeStamp.restart();
|
||||
elapsedTimeOffset = 0;
|
||||
wfx.nSamplesPerSec = settings.sampleRate();
|
||||
wfx.wBitsPerSample = settings.sampleSize();
|
||||
wfx.nChannels = settings.channelCount();
|
||||
wfx.cbSize = 0;
|
||||
|
||||
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels;
|
||||
wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
|
||||
|
||||
QDataStream ds(&m_device, QIODevice::ReadOnly);
|
||||
quint32 deviceId;
|
||||
ds >> deviceId;
|
||||
|
||||
if (waveInOpen(&hWaveIn, UINT_PTR(deviceId), &wfx,
|
||||
if (waveInOpen(&hWaveIn, UINT_PTR(deviceId), &wfx.Format,
|
||||
(DWORD_PTR)&waveInProc,
|
||||
(DWORD_PTR) this,
|
||||
CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
|
||||
|
||||
@@ -45,8 +45,7 @@
|
||||
#ifndef QWINDOWSAUDIOINPUT_H
|
||||
#define QWINDOWSAUDIOINPUT_H
|
||||
|
||||
#include <QtCore/qt_windows.h>
|
||||
#include <mmsystem.h>
|
||||
#include "qwindowsaudioutils.h"
|
||||
|
||||
#include <QtCore/qfile.h>
|
||||
#include <QtCore/qdebug.h>
|
||||
@@ -121,7 +120,7 @@ private:
|
||||
qint64 totalTimeValue;
|
||||
bool pullMode;
|
||||
bool resuming;
|
||||
WAVEFORMATEX wfx;
|
||||
WAVEFORMATEXTENSIBLE wfx;
|
||||
HWAVEIN hWaveIn;
|
||||
MMRESULT result;
|
||||
WAVEHDR* waveBlocks;
|
||||
|
||||
@@ -43,56 +43,11 @@
|
||||
//
|
||||
|
||||
#include "qwindowsaudiooutput.h"
|
||||
#include "qwindowsaudiodeviceinfo.h"
|
||||
#include "qwindowsaudioutils.h"
|
||||
#include <QtEndian>
|
||||
#include <QtCore/QDataStream>
|
||||
|
||||
#ifndef SPEAKER_FRONT_LEFT
|
||||
#define SPEAKER_FRONT_LEFT 0x00000001
|
||||
#define SPEAKER_FRONT_RIGHT 0x00000002
|
||||
#define SPEAKER_FRONT_CENTER 0x00000004
|
||||
#define SPEAKER_LOW_FREQUENCY 0x00000008
|
||||
#define SPEAKER_BACK_LEFT 0x00000010
|
||||
#define SPEAKER_BACK_RIGHT 0x00000020
|
||||
#define SPEAKER_FRONT_LEFT_OF_CENTER 0x00000040
|
||||
#define SPEAKER_FRONT_RIGHT_OF_CENTER 0x00000080
|
||||
#define SPEAKER_BACK_CENTER 0x00000100
|
||||
#define SPEAKER_SIDE_LEFT 0x00000200
|
||||
#define SPEAKER_SIDE_RIGHT 0x00000400
|
||||
#define SPEAKER_TOP_CENTER 0x00000800
|
||||
#define SPEAKER_TOP_FRONT_LEFT 0x00001000
|
||||
#define SPEAKER_TOP_FRONT_CENTER 0x00002000
|
||||
#define SPEAKER_TOP_FRONT_RIGHT 0x00004000
|
||||
#define SPEAKER_TOP_BACK_LEFT 0x00008000
|
||||
#define SPEAKER_TOP_BACK_CENTER 0x00010000
|
||||
#define SPEAKER_TOP_BACK_RIGHT 0x00020000
|
||||
#define SPEAKER_RESERVED 0x7FFC0000
|
||||
#define SPEAKER_ALL 0x80000000
|
||||
#endif
|
||||
|
||||
#ifndef _WAVEFORMATEXTENSIBLE_
|
||||
|
||||
#define _WAVEFORMATEXTENSIBLE_
|
||||
typedef struct
|
||||
{
|
||||
WAVEFORMATEX Format; // Base WAVEFORMATEX data
|
||||
union
|
||||
{
|
||||
WORD wValidBitsPerSample; // Valid bits in each sample container
|
||||
WORD wSamplesPerBlock; // Samples per block of audio data; valid
|
||||
// if wBitsPerSample=0 (but rarely used).
|
||||
WORD wReserved; // Zero if neither case above applies.
|
||||
} Samples;
|
||||
DWORD dwChannelMask; // Positions of the audio channels
|
||||
GUID SubFormat; // Format identifier GUID
|
||||
} WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE, *LPPWAVEFORMATEXTENSIBLE;
|
||||
typedef const WAVEFORMATEXTENSIBLE* LPCWAVEFORMATEXTENSIBLE;
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(WAVE_FORMAT_EXTENSIBLE)
|
||||
#define WAVE_FORMAT_EXTENSIBLE 0xFFFE
|
||||
#endif
|
||||
|
||||
//#define DEBUG_AUDIO 1
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@@ -265,16 +220,8 @@ bool QWindowsAudioOutput::open()
|
||||
|
||||
period_size = 0;
|
||||
|
||||
if (!settings.isValid()) {
|
||||
if (!qt_convertFormat(settings, &wfx)) {
|
||||
qWarning("QAudioOutput: open error, invalid format.");
|
||||
} else if (settings.channelCount() <= 0) {
|
||||
qWarning("QAudioOutput: open error, invalid number of channels (%d).",
|
||||
settings.channelCount());
|
||||
} else if (settings.sampleSize() <= 0) {
|
||||
qWarning("QAudioOutput: open error, invalid sample size (%d).",
|
||||
settings.sampleSize());
|
||||
} else if (settings.sampleRate() < 8000 || settings.sampleRate() > 96000) {
|
||||
qWarning("QAudioOutput: open error, sample rate out of range (%d).", settings.sampleRate());
|
||||
} else if (buffer_size == 0) {
|
||||
// Default buffer size, 200ms, default period size is 40ms
|
||||
buffer_size
|
||||
@@ -308,67 +255,19 @@ bool QWindowsAudioOutput::open()
|
||||
timeStamp.restart();
|
||||
elapsedTimeOffset = 0;
|
||||
|
||||
wfx.nSamplesPerSec = settings.sampleRate();
|
||||
wfx.wBitsPerSample = settings.sampleSize();
|
||||
wfx.nChannels = settings.channelCount();
|
||||
wfx.cbSize = 0;
|
||||
|
||||
bool surround = false;
|
||||
|
||||
if (settings.channelCount() > 2)
|
||||
surround = true;
|
||||
|
||||
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels;
|
||||
wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
|
||||
|
||||
QDataStream ds(&m_device, QIODevice::ReadOnly);
|
||||
quint32 deviceId;
|
||||
ds >> deviceId;
|
||||
|
||||
if (!surround) {
|
||||
if (waveOutOpen(&hWaveOut, UINT_PTR(deviceId), &wfx,
|
||||
if (waveOutOpen(&hWaveOut, UINT_PTR(deviceId), &wfx.Format,
|
||||
(DWORD_PTR)&waveOutProc,
|
||||
(DWORD_PTR) this,
|
||||
CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
|
||||
errorState = QAudio::OpenError;
|
||||
deviceState = QAudio::StoppedState;
|
||||
emit stateChanged(deviceState);
|
||||
qWarning("QAudioOutput: open error");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
WAVEFORMATEXTENSIBLE wfex;
|
||||
wfex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||||
wfex.Format.nChannels = settings.channelCount();
|
||||
wfex.Format.wBitsPerSample = settings.sampleSize();
|
||||
wfex.Format.nSamplesPerSec = settings.sampleRate();
|
||||
wfex.Format.nBlockAlign = wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
|
||||
wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*wfex.Format.nBlockAlign;
|
||||
wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
|
||||
static const GUID _KSDATAFORMAT_SUBTYPE_PCM = {
|
||||
0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
|
||||
wfex.SubFormat=_KSDATAFORMAT_SUBTYPE_PCM;
|
||||
wfex.Format.cbSize=22;
|
||||
|
||||
wfex.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
|
||||
if (settings.channelCount() >= 4)
|
||||
wfex.dwChannelMask |= SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
|
||||
if (settings.channelCount() >= 6)
|
||||
wfex.dwChannelMask |= SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY;
|
||||
if (settings.channelCount() == 8)
|
||||
wfex.dwChannelMask |= SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT;
|
||||
|
||||
if (waveOutOpen(&hWaveOut, UINT_PTR(deviceId), &wfex.Format,
|
||||
(DWORD_PTR)&waveOutProc,
|
||||
(DWORD_PTR) this,
|
||||
CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
|
||||
errorState = QAudio::OpenError;
|
||||
deviceState = QAudio::StoppedState;
|
||||
emit stateChanged(deviceState);
|
||||
qWarning("QAudioOutput: open error");
|
||||
return false;
|
||||
}
|
||||
errorState = QAudio::OpenError;
|
||||
deviceState = QAudio::StoppedState;
|
||||
emit stateChanged(deviceState);
|
||||
qWarning("QAudioOutput: open error");
|
||||
return false;
|
||||
}
|
||||
|
||||
totalTimeValue = 0;
|
||||
|
||||
@@ -45,8 +45,7 @@
|
||||
#ifndef QWINDOWSAUDIOOUTPUT_H
|
||||
#define QWINDOWSAUDIOOUTPUT_H
|
||||
|
||||
#include <QtCore/qt_windows.h>
|
||||
#include <mmsystem.h>
|
||||
#include "qwindowsaudioutils.h"
|
||||
|
||||
#include <QtCore/qdebug.h>
|
||||
#include <QtCore/qtimer.h>
|
||||
@@ -132,7 +131,7 @@ private:
|
||||
bool open();
|
||||
void close();
|
||||
|
||||
WAVEFORMATEX wfx;
|
||||
WAVEFORMATEXTENSIBLE wfx;
|
||||
HWAVEOUT hWaveOut;
|
||||
MMRESULT result;
|
||||
WAVEHDR header;
|
||||
|
||||
111
src/plugins/windowsaudio/qwindowsaudioutils.cpp
Normal file
111
src/plugins/windowsaudio/qwindowsaudioutils.cpp
Normal file
@@ -0,0 +1,111 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 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:LGPL21$
|
||||
** 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 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** 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.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qwindowsaudioutils.h"
|
||||
|
||||
#ifndef SPEAKER_FRONT_LEFT
|
||||
#define SPEAKER_FRONT_LEFT 0x00000001
|
||||
#define SPEAKER_FRONT_RIGHT 0x00000002
|
||||
#define SPEAKER_FRONT_CENTER 0x00000004
|
||||
#define SPEAKER_LOW_FREQUENCY 0x00000008
|
||||
#define SPEAKER_BACK_LEFT 0x00000010
|
||||
#define SPEAKER_BACK_RIGHT 0x00000020
|
||||
#define SPEAKER_FRONT_LEFT_OF_CENTER 0x00000040
|
||||
#define SPEAKER_FRONT_RIGHT_OF_CENTER 0x00000080
|
||||
#define SPEAKER_BACK_CENTER 0x00000100
|
||||
#define SPEAKER_SIDE_LEFT 0x00000200
|
||||
#define SPEAKER_SIDE_RIGHT 0x00000400
|
||||
#define SPEAKER_TOP_CENTER 0x00000800
|
||||
#define SPEAKER_TOP_FRONT_LEFT 0x00001000
|
||||
#define SPEAKER_TOP_FRONT_CENTER 0x00002000
|
||||
#define SPEAKER_TOP_FRONT_RIGHT 0x00004000
|
||||
#define SPEAKER_TOP_BACK_LEFT 0x00008000
|
||||
#define SPEAKER_TOP_BACK_CENTER 0x00010000
|
||||
#define SPEAKER_TOP_BACK_RIGHT 0x00020000
|
||||
#define SPEAKER_RESERVED 0x7FFC0000
|
||||
#define SPEAKER_ALL 0x80000000
|
||||
#endif
|
||||
|
||||
#ifndef WAVE_FORMAT_EXTENSIBLE
|
||||
#define WAVE_FORMAT_EXTENSIBLE 0xFFFE
|
||||
#endif
|
||||
|
||||
#ifndef WAVE_FORMAT_IEEE_FLOAT
|
||||
#define WAVE_FORMAT_IEEE_FLOAT 0x0003
|
||||
#endif
|
||||
|
||||
static const GUID _KSDATAFORMAT_SUBTYPE_PCM = {
|
||||
0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
|
||||
|
||||
static const GUID _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {
|
||||
0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
bool qt_convertFormat(const QAudioFormat &format, WAVEFORMATEXTENSIBLE *wfx)
|
||||
{
|
||||
if (!wfx
|
||||
|| !format.isValid()
|
||||
|| format.codec() != QStringLiteral("audio/pcm")
|
||||
|| format.sampleRate() <= 0
|
||||
|| format.channelCount() <= 0
|
||||
|| format.sampleSize() <= 0
|
||||
|| format.byteOrder() != QAudioFormat::LittleEndian) {
|
||||
return false;
|
||||
}
|
||||
|
||||
wfx->Format.nSamplesPerSec = format.sampleRate();
|
||||
wfx->Format.wBitsPerSample = wfx->Samples.wValidBitsPerSample = format.sampleSize();
|
||||
wfx->Format.nChannels = format.channelCount();
|
||||
wfx->Format.nBlockAlign = (wfx->Format.wBitsPerSample / 8) * wfx->Format.nChannels;
|
||||
wfx->Format.nAvgBytesPerSec = wfx->Format.nBlockAlign * wfx->Format.nSamplesPerSec;
|
||||
wfx->Format.cbSize = 0;
|
||||
|
||||
if (format.sampleType() == QAudioFormat::Float) {
|
||||
wfx->Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
|
||||
wfx->SubFormat = _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
|
||||
} else {
|
||||
wfx->Format.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wfx->SubFormat = _KSDATAFORMAT_SUBTYPE_PCM;
|
||||
}
|
||||
|
||||
if (format.channelCount() > 2) {
|
||||
wfx->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||||
wfx->Format.cbSize = 22;
|
||||
wfx->dwChannelMask = 0xFFFFFFFF >> (32 - format.channelCount());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
67
src/plugins/windowsaudio/qwindowsaudioutils.h
Normal file
67
src/plugins/windowsaudio/qwindowsaudioutils.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 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:LGPL21$
|
||||
** 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 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** 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.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QWINDOWSAUDIOUTILS_H
|
||||
#define QWINDOWSAUDIOUTILS_H
|
||||
|
||||
#include <qaudioformat.h>
|
||||
#include <QtCore/qt_windows.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
#ifndef _WAVEFORMATEXTENSIBLE_
|
||||
|
||||
#define _WAVEFORMATEXTENSIBLE_
|
||||
typedef struct
|
||||
{
|
||||
WAVEFORMATEX Format; // Base WAVEFORMATEX data
|
||||
union
|
||||
{
|
||||
WORD wValidBitsPerSample; // Valid bits in each sample container
|
||||
WORD wSamplesPerBlock; // Samples per block of audio data; valid
|
||||
// if wBitsPerSample=0 (but rarely used).
|
||||
WORD wReserved; // Zero if neither case above applies.
|
||||
} Samples;
|
||||
DWORD dwChannelMask; // Positions of the audio channels
|
||||
GUID SubFormat; // Format identifier GUID
|
||||
} WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE, *LPPWAVEFORMATEXTENSIBLE;
|
||||
typedef const WAVEFORMATEXTENSIBLE* LPCWAVEFORMATEXTENSIBLE;
|
||||
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
bool qt_convertFormat(const QAudioFormat &format, WAVEFORMATEXTENSIBLE *wfx);
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QWINDOWSAUDIOUTILS_H
|
||||
@@ -12,13 +12,15 @@ HEADERS += \
|
||||
qwindowsaudioplugin.h \
|
||||
qwindowsaudiodeviceinfo.h \
|
||||
qwindowsaudioinput.h \
|
||||
qwindowsaudiooutput.h
|
||||
qwindowsaudiooutput.h \
|
||||
qwindowsaudioutils.h
|
||||
|
||||
SOURCES += \
|
||||
qwindowsaudioplugin.cpp \
|
||||
qwindowsaudiodeviceinfo.cpp \
|
||||
qwindowsaudioinput.cpp \
|
||||
qwindowsaudiooutput.cpp
|
||||
qwindowsaudiooutput.cpp \
|
||||
qwindowsaudioutils.cpp
|
||||
|
||||
OTHER_FILES += \
|
||||
windowsaudio.json
|
||||
|
||||
@@ -195,17 +195,6 @@ void MFAudioDecoderControl::handleMediaSourceReady()
|
||||
if (mediaType) {
|
||||
m_sourceOutputFormat = m_audioFormat;
|
||||
QAudioFormat af = m_audioFormat;
|
||||
GUID subType;
|
||||
if (SUCCEEDED(mediaType->GetGUID(MF_MT_SUBTYPE, &subType))) {
|
||||
if (subType == MFAudioFormat_Float) {
|
||||
m_sourceOutputFormat.setSampleType(QAudioFormat::Float);
|
||||
} else {
|
||||
m_sourceOutputFormat.setSampleType(QAudioFormat::SignedInt);
|
||||
}
|
||||
}
|
||||
if (m_sourceOutputFormat.sampleType() != QAudioFormat::Float) {
|
||||
m_sourceOutputFormat.setByteOrder(QAudioFormat::LittleEndian);
|
||||
}
|
||||
|
||||
UINT32 val = 0;
|
||||
if (SUCCEEDED(mediaType->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &val))) {
|
||||
@@ -218,6 +207,20 @@ void MFAudioDecoderControl::handleMediaSourceReady()
|
||||
m_sourceOutputFormat.setSampleSize(int(val));
|
||||
}
|
||||
|
||||
GUID subType;
|
||||
if (SUCCEEDED(mediaType->GetGUID(MF_MT_SUBTYPE, &subType))) {
|
||||
if (subType == MFAudioFormat_Float) {
|
||||
m_sourceOutputFormat.setSampleType(QAudioFormat::Float);
|
||||
} else if (m_sourceOutputFormat.sampleSize() == 8) {
|
||||
m_sourceOutputFormat.setSampleType(QAudioFormat::UnSignedInt);
|
||||
} else {
|
||||
m_sourceOutputFormat.setSampleType(QAudioFormat::SignedInt);
|
||||
}
|
||||
}
|
||||
if (m_sourceOutputFormat.sampleType() != QAudioFormat::Float) {
|
||||
m_sourceOutputFormat.setByteOrder(QAudioFormat::LittleEndian);
|
||||
}
|
||||
|
||||
if (m_audioFormat.sampleType() != QAudioFormat::Float
|
||||
&& m_audioFormat.sampleType() != QAudioFormat::SignedInt) {
|
||||
af.setSampleType(m_sourceOutputFormat.sampleType());
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
MFPlayerService::MFPlayerService(QObject *parent)
|
||||
: QMediaService(parent)
|
||||
, m_session(0)
|
||||
#ifndef Q_WS_SIMULATOR
|
||||
#if defined(HAVE_WIDGETS) && !defined(Q_WS_SIMULATOR)
|
||||
, m_videoWindowControl(0)
|
||||
#endif
|
||||
, m_videoRendererControl(0)
|
||||
@@ -65,7 +65,7 @@ MFPlayerService::~MFPlayerService()
|
||||
{
|
||||
m_session->close();
|
||||
|
||||
#ifndef Q_WS_SIMULATOR
|
||||
#if defined(HAVE_WIDGETS) && !defined(Q_WS_SIMULATOR)
|
||||
if (m_videoWindowControl)
|
||||
delete m_videoWindowControl;
|
||||
#endif
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
#include <QtCore/qbuffer.h>
|
||||
|
||||
#include "mfplayercontrol.h"
|
||||
#ifndef Q_WS_SIMULATOR
|
||||
#if defined(HAVE_WIDGETS) && !defined(Q_WS_SIMULATOR)
|
||||
#include "evr9videowindowcontrol.h"
|
||||
#endif
|
||||
#include "mfvideorenderercontrol.h"
|
||||
@@ -140,7 +140,7 @@ void MFPlayerSession::close()
|
||||
|
||||
if (m_playerService->videoRendererControl()) {
|
||||
m_playerService->videoRendererControl()->releaseActivate();
|
||||
#ifndef Q_WS_SIMULATOR
|
||||
#if defined(HAVE_WIDGETS) && !defined(Q_WS_SIMULATOR)
|
||||
} else if (m_playerService->videoWindowControl()) {
|
||||
m_playerService->videoWindowControl()->releaseActivate();
|
||||
#endif
|
||||
@@ -404,7 +404,7 @@ IMFTopologyNode* MFPlayerSession::addOutputNode(IMFStreamDescriptor *streamDesc,
|
||||
mediaType = Video;
|
||||
if (m_playerService->videoRendererControl()) {
|
||||
activate = m_playerService->videoRendererControl()->createActivate();
|
||||
#ifndef Q_WS_SIMULATOR
|
||||
#if defined(HAVE_WIDGETS) && !defined(Q_WS_SIMULATOR)
|
||||
} else if (m_playerService->videoWindowControl()) {
|
||||
activate = m_playerService->videoWindowControl()->createActivate();
|
||||
#endif
|
||||
@@ -556,7 +556,10 @@ QAudioFormat MFPlayerSession::audioFormatForMFMediaType(IMFMediaType *mediaType)
|
||||
format.setSampleSize(wfx->wBitsPerSample);
|
||||
format.setCodec("audio/pcm");
|
||||
format.setByteOrder(QAudioFormat::LittleEndian);
|
||||
format.setSampleType(QAudioFormat::SignedInt);
|
||||
if (format.sampleSize() == 8)
|
||||
format.setSampleType(QAudioFormat::UnSignedInt);
|
||||
else
|
||||
format.setSampleType(QAudioFormat::SignedInt);
|
||||
|
||||
CoTaskMemFree(wfx);
|
||||
return format;
|
||||
@@ -1577,7 +1580,7 @@ void MFPlayerSession::handleSessionEvent(IMFMediaEvent *sessionEvent)
|
||||
}
|
||||
|
||||
updatePendingCommands(CmdStart);
|
||||
#ifndef Q_WS_SIMULATOR
|
||||
#if defined(HAVE_WIDGETS) && !defined(Q_WS_SIMULATOR)
|
||||
// playback started, we can now set again the procAmpValues if they have been
|
||||
// changed previously (these are lost when loading a new media)
|
||||
if (m_playerService->videoWindowControl()) {
|
||||
@@ -1721,10 +1724,17 @@ void MFPlayerSession::updatePendingCommands(Command command)
|
||||
if (m_state.command != command || m_pendingState == NoPending)
|
||||
return;
|
||||
|
||||
// The current pending command has completed.
|
||||
// Seek while paused completed
|
||||
if (m_pendingState == SeekPending && m_state.prevCmd == CmdPause) {
|
||||
m_pendingState = NoPending;
|
||||
m_state.setCommand(CmdPause);
|
||||
// A seek operation actually restarts playback. If scrubbing is possible, playback rate
|
||||
// is set to 0.0 at this point and we just need to reset the current state to Pause.
|
||||
// If scrubbing is not possible, the playback rate was not changed and we explicitly need
|
||||
// to re-pause playback.
|
||||
if (!canScrub())
|
||||
pause();
|
||||
else
|
||||
m_state.setCommand(CmdPause);
|
||||
}
|
||||
|
||||
m_pendingState = NoPending;
|
||||
|
||||
@@ -813,7 +813,7 @@ namespace
|
||||
case QVideoFrame::Format_RGB32:
|
||||
mediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32);
|
||||
break;
|
||||
case QVideoFrame::Format_RGB24:
|
||||
case QVideoFrame::Format_BGR24: // MFVideoFormat_RGB24 has a BGR layout
|
||||
mediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24);
|
||||
break;
|
||||
case QVideoFrame::Format_RGB565:
|
||||
@@ -842,8 +842,11 @@ namespace
|
||||
mediaType->Release();
|
||||
continue;
|
||||
}
|
||||
m_pixelFormats.push_back(format);
|
||||
m_mediaTypes.push_back(mediaType);
|
||||
// QAbstractVideoSurface::supportedPixelFormats() returns formats in descending
|
||||
// order of preference, while IMFMediaTypeHandler is supposed to return supported
|
||||
// formats in ascending order of preference. We need to reverse the list.
|
||||
m_pixelFormats.prepend(format);
|
||||
m_mediaTypes.prepend(mediaType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1082,6 +1085,7 @@ namespace
|
||||
return format.frameWidth() * 4;
|
||||
// 24 bpp packed formats.
|
||||
case QVideoFrame::Format_RGB24:
|
||||
case QVideoFrame::Format_BGR24:
|
||||
return PAD_TO_DWORD(format.frameWidth() * 3);
|
||||
// 16 bpp packed formats.
|
||||
case QVideoFrame::Format_RGB565:
|
||||
|
||||
Reference in New Issue
Block a user