Merge "Merge remote-tracking branch 'origin/5.3' into 5.4" into refs/staging/5.4

This commit is contained in:
Yoann Lopes
2014-09-01 14:19:53 +02:00
committed by The Qt Project
38 changed files with 436 additions and 149 deletions

View File

@@ -100,6 +100,8 @@ config_gstreamer_appsrc {
LIBS_PRIVATE += -lgstapp-0.10
}
config_linux_v4l: DEFINES += USE_V4L
HEADERS += $$PRIVATE_HEADERS
DESTDIR = $$QT.multimedia.libs

View File

@@ -317,8 +317,10 @@ void QAndroidMediaPlayerControl::setMedia(const QMediaContent &mediaContent,
mMediaPlayer->setDataSource(mediaPath);
mMediaPlayer->prepareAsync();
if (!reloading)
if (!reloading) {
Q_EMIT mediaChanged(mMediaContent);
Q_EMIT actualMediaLocationChanged(mediaPath);
}
resetBufferingProgress();
}

View File

@@ -72,6 +72,7 @@ public:
Q_SIGNALS:
void metaDataUpdated();
void actualMediaLocationChanged(const QString &url);
public Q_SLOTS:
void setPosition(qint64 position) Q_DECL_OVERRIDE;

View File

@@ -45,8 +45,8 @@ QAndroidMediaService::QAndroidMediaService(QObject *parent)
{
mMediaControl = new QAndroidMediaPlayerControl;
mMetadataControl = new QAndroidMetaDataReaderControl;
connect(mMediaControl, SIGNAL(mediaChanged(QMediaContent)),
mMetadataControl, SLOT(onMediaChanged(QMediaContent)));
connect(mMediaControl, SIGNAL(actualMediaLocationChanged(QString)),
mMetadataControl, SLOT(onMediaChanged(QString)));
connect(mMediaControl, SIGNAL(metaDataUpdated()),
mMetadataControl, SLOT(onUpdateMetaData()));
}

View File

@@ -93,18 +93,18 @@ QStringList QAndroidMetaDataReaderControl::availableMetaData() const
return m_metadata.keys();
}
void QAndroidMetaDataReaderControl::onMediaChanged(const QMediaContent &media)
void QAndroidMetaDataReaderControl::onMediaChanged(const QString &url)
{
if (!m_retriever)
return;
m_mediaContent = media;
m_mediaLocation = url;
updateData();
}
void QAndroidMetaDataReaderControl::onUpdateMetaData()
{
if (!m_retriever || m_mediaContent.isNull())
if (!m_retriever || m_mediaLocation.isEmpty())
return;
updateData();
@@ -114,8 +114,8 @@ void QAndroidMetaDataReaderControl::updateData()
{
m_metadata.clear();
if (!m_mediaContent.isNull()) {
if (m_retriever->setDataSource(m_mediaContent.canonicalUrl())) {
if (!m_mediaLocation.isEmpty()) {
if (m_retriever->setDataSource(m_mediaLocation)) {
QString mimeType = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::MimeType);
if (!mimeType.isNull())
m_metadata.insert(QMediaMetaData::MediaType, mimeType);

View File

@@ -54,13 +54,13 @@ public:
QStringList availableMetaData() const Q_DECL_OVERRIDE;
public Q_SLOTS:
void onMediaChanged(const QMediaContent &media);
void onMediaChanged(const QString &url);
void onUpdateMetaData();
private:
void updateData();
QMediaContent m_mediaContent;
QString m_mediaLocation;
bool m_available;
QVariantMap m_metadata;

View File

@@ -35,9 +35,24 @@
#include <QtCore/private/qjnihelpers_p.h>
#include <QtCore/private/qjni_p.h>
#include <QtCore/QUrl>
#include <qdebug.h>
QT_BEGIN_NAMESPACE
static bool exceptionCheckAndClear(JNIEnv *env)
{
if (Q_UNLIKELY(env->ExceptionCheck())) {
#ifdef QT_DEBUG
env->ExceptionDescribe();
#endif // QT_DEBUG
env->ExceptionClear();
return true;
}
return false;
}
AndroidMediaMetadataRetriever::AndroidMediaMetadataRetriever()
{
m_metadataRetriever = QJNIObjectPrivate("android/media/MediaMetadataRetriever");
@@ -68,55 +83,105 @@ void AndroidMediaMetadataRetriever::release()
m_metadataRetriever.callMethod<void>("release");
}
bool AndroidMediaMetadataRetriever::setDataSource(const QUrl &url)
bool AndroidMediaMetadataRetriever::setDataSource(const QString &urlString)
{
if (!m_metadataRetriever.isValid())
return false;
QJNIEnvironmentPrivate env;
QUrl url(urlString);
bool loaded = false;
if (url.isLocalFile()) { // also includes qrc files (copied to a temp file)
QJNIObjectPrivate string = QJNIObjectPrivate::fromString(url.path());
QJNIObjectPrivate fileInputStream("java/io/FileInputStream",
"(Ljava/lang/String;)V",
string.object());
QJNIObjectPrivate string = QJNIObjectPrivate::fromString(url.toString());
if (exceptionCheckAndClear(env))
return false;
QJNIObjectPrivate uri = m_metadataRetriever.callStaticObjectMethod("android/net/Uri",
"parse",
"(Ljava/lang/String;)Landroid/net/Uri;",
string.object());
if (env->ExceptionCheck()) {
env->ExceptionClear();
QJNIObjectPrivate fd = fileInputStream.callObjectMethod("getFD",
"()Ljava/io/FileDescriptor;");
if (exceptionCheckAndClear(env)) {
fileInputStream.callMethod<void>("close");
exceptionCheckAndClear(env);
return false;
}
m_metadataRetriever.callMethod<void>("setDataSource",
"(Ljava/io/FileDescriptor;)V",
fd.object());
bool ok = !exceptionCheckAndClear(env);
fileInputStream.callMethod<void>("close");
exceptionCheckAndClear(env);
if (!ok)
return false;
} else if (url.scheme() == QLatin1String("assets")) {
QJNIObjectPrivate string = QJNIObjectPrivate::fromString(url.path().mid(1)); // remove first '/'
QJNIObjectPrivate activity(QtAndroidPrivate::activity());
QJNIObjectPrivate assetManager = activity.callObjectMethod("getAssets",
"()Landroid/content/res/AssetManager;");
QJNIObjectPrivate assetFd = assetManager.callObjectMethod("openFd",
"(Ljava/lang/String;)Landroid/content/res/AssetFileDescriptor;",
string.object());
if (exceptionCheckAndClear(env))
return false;
QJNIObjectPrivate fd = assetFd.callObjectMethod("getFileDescriptor",
"()Ljava/io/FileDescriptor;");
if (exceptionCheckAndClear(env)) {
assetFd.callMethod<void>("close");
exceptionCheckAndClear(env);
return false;
}
m_metadataRetriever.callMethod<void>("setDataSource",
"(Ljava/io/FileDescriptor;JJ)V",
fd.object(),
assetFd.callMethod<jlong>("getStartOffset"),
assetFd.callMethod<jlong>("getLength"));
bool ok = !exceptionCheckAndClear(env);
assetFd.callMethod<void>("close");
exceptionCheckAndClear(env);
if (!ok)
return false;
} else if (QtAndroidPrivate::androidSdkVersion() >= 14) {
// On API levels >= 14, only setDataSource(String, Map<String, String>) accepts remote media
QJNIObjectPrivate string = QJNIObjectPrivate::fromString(urlString);
QJNIObjectPrivate hash("java/util/HashMap");
m_metadataRetriever.callMethod<void>("setDataSource",
"(Ljava/lang/String;Ljava/util/Map;)V",
string.object(),
hash.object());
if (exceptionCheckAndClear(env))
return false;
} else {
// While on API levels < 14, only setDataSource(Context, Uri) is available and works for
// remote media...
QJNIObjectPrivate string = QJNIObjectPrivate::fromString(urlString);
QJNIObjectPrivate uri = m_metadataRetriever.callStaticObjectMethod("android/net/Uri",
"parse",
"(Ljava/lang/String;)Landroid/net/Uri;",
string.object());
if (exceptionCheckAndClear(env))
return false;
m_metadataRetriever.callMethod<void>("setDataSource",
"(Landroid/content/Context;Landroid/net/Uri;)V",
QtAndroidPrivate::activity(),
uri.object());
if (env->ExceptionCheck())
env->ExceptionClear();
else
loaded = true;
if (exceptionCheckAndClear(env))
return false;
}
return loaded;
}
bool AndroidMediaMetadataRetriever::setDataSource(const QString &path)
{
if (!m_metadataRetriever.isValid())
return false;
QJNIEnvironmentPrivate env;
bool loaded = false;
m_metadataRetriever.callMethod<void>("setDataSource",
"(Ljava/lang/String;)V",
QJNIObjectPrivate::fromString(path).object());
if (env->ExceptionCheck())
env->ExceptionClear();
else
loaded = true;
return loaded;
return true;
}
QT_END_NAMESPACE

View File

@@ -35,7 +35,6 @@
#define ANDROIDMEDIAMETADATARETRIEVER_H
#include <QtCore/private/qjni_p.h>
#include <qurl.h>
QT_BEGIN_NAMESPACE
@@ -73,8 +72,7 @@ public:
QString extractMetadata(MetadataKey key);
void release();
bool setDataSource(const QUrl &url);
bool setDataSource(const QString &path);
bool setDataSource(const QString &url);
private:
QJNIObjectPrivate m_metadataRetriever;

View File

@@ -135,9 +135,9 @@ QMediaControl *AVFCameraService::requestControl(const char *name)
void AVFCameraService::releaseControl(QMediaControl *control)
{
if (m_videoOutput == control) {
m_videoOutput = 0;
m_session->setVideoOutput(0);
delete control;
delete m_videoOutput;
m_videoOutput = 0;
}
}

View File

@@ -118,14 +118,15 @@ void AVFMediaPlayerService::releaseControl(QMediaControl *control)
#ifdef QT_DEBUG_AVF
qDebug() << Q_FUNC_INFO << control;
#endif
#if defined(Q_OS_OSX)
if (m_videoOutput == control) {
#if defined(Q_OS_OSX)
AVFVideoRendererControl *renderControl = qobject_cast<AVFVideoRendererControl*>(m_videoOutput);
if (renderControl)
renderControl->setSurface(0);
#endif
m_videoOutput = 0;
m_session->setVideoOutput(0);
delete control;
}
#endif
}

View File

@@ -148,6 +148,9 @@ private:
QByteArray rawData;
};
void setAudioAvailable(bool available);
void setVideoAvailable(bool available);
AVFMediaPlayerService *m_service;
AVFVideoOutput *m_videoOutput;

View File

@@ -70,15 +70,11 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe
AVPlayerItem *m_playerItem;
AVPlayerLayer *m_playerLayer;
NSURL *m_URL;
bool m_audioAvailable;
bool m_videoAvailable;
}
@property (readonly, getter=player) AVPlayer* m_player;
@property (readonly, getter=playerItem) AVPlayerItem* m_playerItem;
@property (readonly, getter=playerLayer) AVPlayerLayer* m_playerLayer;
@property (readonly, getter=audioAvailable) bool m_audioAvailable;
@property (readonly, getter=videoAvailable) bool m_videoAvailable;
@property (readonly, getter=session) AVFMediaPlayerSession* m_session;
- (AVFMediaPlayerSessionObserver *) initWithMediaPlayerSession:(AVFMediaPlayerSession *)session;
@@ -96,7 +92,7 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe
@implementation AVFMediaPlayerSessionObserver
@synthesize m_player, m_playerItem, m_playerLayer, m_audioAvailable, m_videoAvailable, m_session;
@synthesize m_player, m_playerItem, m_playerLayer, m_session;
- (AVFMediaPlayerSessionObserver *) initWithMediaPlayerSession:(AVFMediaPlayerSession *)session
{
@@ -186,18 +182,6 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe
return;
}
m_audioAvailable = false;
m_videoAvailable = false;
//Check each track of asset for audio and video content
NSArray *tracks = [asset tracks];
for (AVAssetTrack *track in tracks) {
if ([track hasMediaCharacteristic:AVMediaCharacteristicAudible])
m_audioAvailable = true;
if ([track hasMediaCharacteristic:AVMediaCharacteristicVisual])
m_videoAvailable = true;
}
//At this point we're ready to set up for playback of the asset.
//Stop observing our prior AVPlayerItem, if we have one.
if (m_playerItem)
@@ -258,18 +242,7 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe
m_playerLayer = [AVPlayerLayer playerLayerWithPlayer:m_player];
[m_playerLayer retain];
m_playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
//Get the native size of the new item, and reset the bounds of the player layer
AVAsset *asset = m_playerItem.asset;
if (asset) {
NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];
if ([tracks count]) {
AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
m_playerLayer.anchorPoint = CGPointMake(0.0f, 0.0f);
m_playerLayer.bounds = CGRectMake(0.0f, 0.0f, videoTrack.naturalSize.width, videoTrack.naturalSize.height);
}
}
m_playerLayer.anchorPoint = CGPointMake(0.0f, 0.0f);
}
//Observe the AVPlayer "currentItem" property to find out when any
@@ -366,22 +339,8 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe
{
AVPlayerItem *newPlayerItem = [change objectForKey:NSKeyValueChangeNewKey];
if (m_playerItem != newPlayerItem)
{
m_playerItem = newPlayerItem;
//Get the native size of the new item, and reset the bounds of the player layer
//AVAsset *asset = m_playerItem.asset;
AVAsset *asset = [m_playerItem asset];
if (asset) {
NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];
if ([tracks count]) {
AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
m_playerLayer.anchorPoint = CGPointMake(0.0f, 0.0f);
m_playerLayer.bounds = CGRectMake(0.0f, 0.0f, videoTrack.naturalSize.width, videoTrack.naturalSize.height);
}
}
}
if (self.session)
QMetaObject::invokeMethod(m_session, "processCurrentItemChanged", Qt::AutoConnection);
}
@@ -513,6 +472,9 @@ void AVFMediaPlayerSession::setMedia(const QMediaContent &content, QIODevice *st
m_resources = content;
m_mediaStream = stream;
setAudioAvailable(false);
setVideoAvailable(false);
QMediaPlayer::MediaStatus oldMediaStatus = m_mediaStatus;
if (content.isNull() || content.canonicalUrl().isEmpty()) {
@@ -582,14 +544,32 @@ bool AVFMediaPlayerSession::isMuted() const
return m_muted;
}
void AVFMediaPlayerSession::setAudioAvailable(bool available)
{
if (m_audioAvailable == available)
return;
m_audioAvailable = available;
Q_EMIT audioAvailableChanged(available);
}
bool AVFMediaPlayerSession::isAudioAvailable() const
{
return [(AVFMediaPlayerSessionObserver*)m_observer audioAvailable];
return m_audioAvailable;
}
void AVFMediaPlayerSession::setVideoAvailable(bool available)
{
if (m_videoAvailable == available)
return;
m_videoAvailable = available;
Q_EMIT videoAvailableChanged(available);
}
bool AVFMediaPlayerSession::isVideoAvailable() const
{
return [(AVFMediaPlayerSessionObserver*)m_observer videoAvailable];
return m_videoAvailable;
}
bool AVFMediaPlayerSession::isSeekable() const
@@ -802,16 +782,37 @@ void AVFMediaPlayerSession::processLoadStateChange()
bool isPlaying = (m_state != QMediaPlayer::StoppedState);
if (currentStatus == AVPlayerStatusReadyToPlay) {
AVPlayerItem *playerItem = [(AVFMediaPlayerSessionObserver*)m_observer playerItem];
if (playerItem) {
// Check each track for audio and video content
AVAssetTrack *videoTrack = nil;
NSArray *tracks = playerItem.tracks;
for (AVPlayerItemTrack *track in tracks) {
AVAssetTrack *assetTrack = track.assetTrack;
if (assetTrack) {
if ([assetTrack.mediaType isEqualToString:AVMediaTypeAudio])
setAudioAvailable(true);
if ([assetTrack.mediaType isEqualToString:AVMediaTypeVideo]) {
setVideoAvailable(true);
if (!videoTrack)
videoTrack = assetTrack;
}
}
}
// Get the native size of the video, and reset the bounds of the player layer
AVPlayerLayer *playerLayer = [(AVFMediaPlayerSessionObserver*)m_observer playerLayer];
if (videoTrack && playerLayer) {
playerLayer.bounds = CGRectMake(0.0f, 0.0f,
videoTrack.naturalSize.width,
videoTrack.naturalSize.height);
}
}
qint64 currentDuration = duration();
if (m_duration != currentDuration)
Q_EMIT durationChanged(m_duration = currentDuration);
if (m_audioAvailable != isAudioAvailable())
Q_EMIT audioAvailableChanged(m_audioAvailable = !m_audioAvailable);
if (m_videoAvailable != isVideoAvailable())
Q_EMIT videoAvailableChanged(m_videoAvailable = !m_videoAvailable);
newStatus = isPlaying ? QMediaPlayer::BufferedMedia : QMediaPlayer::LoadedMedia;
if (m_state == QMediaPlayer::PlayingState && [(AVFMediaPlayerSessionObserver*)m_observer player]) {

View File

@@ -64,8 +64,10 @@ AVFVideoWidget::~AVFVideoWidget()
qDebug() << Q_FUNC_INFO;
#endif
if (m_playerLayer)
if (m_playerLayer) {
[m_playerLayer removeFromSuperlayer];
[m_playerLayer release];
}
}
QSize AVFVideoWidget::sizeHint() const

View File

@@ -61,8 +61,10 @@ AVFVideoWindowControl::AVFVideoWindowControl(QObject *parent)
AVFVideoWindowControl::~AVFVideoWindowControl()
{
if (m_playerLayer)
if (m_playerLayer) {
[m_playerLayer removeFromSuperlayer];
[m_playerLayer release];
}
}
WId AVFVideoWindowControl::winId() const

View File

@@ -698,14 +698,14 @@ void CoreAudioOutput::audioThreadStop()
{
stopTimers();
if (m_audioThreadState.testAndSetAcquire(Running, Stopped))
m_threadFinished.wait(&m_mutex);
m_threadFinished.wait(&m_mutex, 500);
}
void CoreAudioOutput::audioThreadDrain()
{
stopTimers();
if (m_audioThreadState.testAndSetAcquire(Running, Draining))
m_threadFinished.wait(&m_mutex);
m_threadFinished.wait(&m_mutex, 500);
}
void CoreAudioOutput::audioDeviceStop()

View File

@@ -83,6 +83,8 @@ config_gstreamer_photography {
DEFINES += GST_USE_UNSTABLE_API #prevents warnings because of unstable photography API
}
config_linux_v4l: DEFINES += USE_V4L
OTHER_FILES += \
camerabin.json

View File

@@ -43,7 +43,10 @@
#include <private/qgstutils_p.h>
#include <private/qcore_unix_p.h>
#if defined(USE_V4L)
#include <linux/videodev2.h>
#endif
QT_BEGIN_NAMESPACE

View File

@@ -15,7 +15,6 @@ HEADERS += $$PWD/qgstreamercaptureservice.h \
$$PWD/qgstreamerrecordercontrol.h \
$$PWD/qgstreamermediacontainercontrol.h \
$$PWD/qgstreamercameracontrol.h \
$$PWD/qgstreamerv4l2input.h \
$$PWD/qgstreamercapturemetadatacontrol.h \
$$PWD/qgstreamerimagecapturecontrol.h \
$$PWD/qgstreamerimageencode.h \
@@ -28,7 +27,6 @@ SOURCES += $$PWD/qgstreamercaptureservice.cpp \
$$PWD/qgstreamerrecordercontrol.cpp \
$$PWD/qgstreamermediacontainercontrol.cpp \
$$PWD/qgstreamercameracontrol.cpp \
$$PWD/qgstreamerv4l2input.cpp \
$$PWD/qgstreamercapturemetadatacontrol.cpp \
$$PWD/qgstreamerimagecapturecontrol.cpp \
$$PWD/qgstreamerimageencode.cpp \
@@ -37,13 +35,18 @@ SOURCES += $$PWD/qgstreamercaptureservice.cpp \
# Camera usage with gstreamer needs to have
#CONFIG += use_gstreamer_camera
use_gstreamer_camera {
DEFINES += USE_GSTREAMER_CAMERA
use_gstreamer_camera:config_linux_v4l {
DEFINES += USE_GSTREAMER_CAMERA
OTHER_FILES += \
mediacapturecamera.json
HEADERS += \
$$PWD/qgstreamerv4l2input.h
SOURCES += \
$$PWD/qgstreamerv4l2input.cpp
OTHER_FILES += \
mediacapturecamera.json
} else {
OTHER_FILES += \
mediacapture.json
OTHER_FILES += \
mediacapture.json
}

View File

@@ -40,9 +40,12 @@
#include "qgstreamerimageencode.h"
#include "qgstreamercameracontrol.h"
#include <private/qgstreamerbushelper_p.h>
#include "qgstreamerv4l2input.h"
#include "qgstreamercapturemetadatacontrol.h"
#if defined(USE_GSTREAMER_CAMERA)
#include "qgstreamerv4l2input.h"
#endif
#include "qgstreamerimagecapturecontrol.h"
#include <private/qgstreameraudioinputselector_p.h>
#include <private/qgstreamervideoinputdevicecontrol_p.h>
@@ -66,7 +69,9 @@ QGstreamerCaptureService::QGstreamerCaptureService(const QString &service, QObje
m_cameraControl = 0;
m_metaDataControl = 0;
#if defined(USE_GSTREAMER_CAMERA)
m_videoInput = 0;
#endif
m_audioInputSelector = 0;
m_videoInputDevice = 0;
@@ -82,6 +87,7 @@ QGstreamerCaptureService::QGstreamerCaptureService(const QString &service, QObje
m_captureSession = new QGstreamerCaptureSession(QGstreamerCaptureSession::Audio, this);
}
#if defined(USE_GSTREAMER_CAMERA)
if (service == Q_MEDIASERVICE_CAMERA) {
m_captureSession = new QGstreamerCaptureSession(QGstreamerCaptureSession::AudioAndVideo, this);
m_cameraControl = new QGstreamerCameraControl(m_captureSession);
@@ -103,6 +109,7 @@ QGstreamerCaptureService::QGstreamerCaptureService(const QString &service, QObje
#endif
m_imageCaptureControl = new QGstreamerImageCaptureControl(m_captureSession);
}
#endif
m_audioInputSelector = new QGstreamerAudioInputSelector(this);
connect(m_audioInputSelector, SIGNAL(activeInputChanged(QString)), m_captureSession, SLOT(setCaptureDevice(QString)));

View File

@@ -70,7 +70,9 @@ private:
QGstreamerCaptureSession *m_captureSession;
QGstreamerCameraControl *m_cameraControl;
#if defined(USE_GSTREAMER_CAMERA)
QGstreamerV4L2Input *m_videoInput;
#endif
QGstreamerCaptureMetaDataControl *m_metaDataControl;
QAudioInputSelectorControl *m_audioInputSelector;

View File

@@ -70,7 +70,8 @@ QOpenSLESAudioOutput::QOpenSLESAudioOutput(const QByteArray &device)
m_periodSize(0),
m_elapsedTime(0),
m_processedBytes(0),
m_availableBuffers(BUFFER_COUNT)
m_availableBuffers(BUFFER_COUNT),
m_eventMask(SL_PLAYEVENT_HEADATEND)
{
#ifndef ANDROID
m_streamType = -1;
@@ -190,7 +191,33 @@ int QOpenSLESAudioOutput::bufferSize() const
void QOpenSLESAudioOutput::setNotifyInterval(int ms)
{
m_notifyInterval = ms > 0 ? ms : 0;
const int newInterval = ms > 0 ? ms : 0;
if (newInterval == m_notifyInterval)
return;
const SLuint32 newEvenMask = newInterval == 0 ? m_eventMask & ~SL_PLAYEVENT_HEADATNEWPOS
: m_eventMask & SL_PLAYEVENT_HEADATNEWPOS;
if (m_state == QAudio::StoppedState) {
m_eventMask = newEvenMask;
m_notifyInterval = newInterval;
return;
}
if (newEvenMask != m_eventMask
&& SL_RESULT_SUCCESS != (*m_playItf)->SetCallbackEventsMask(m_playItf, newEvenMask)) {
return;
}
m_eventMask = newEvenMask;
if (newInterval && SL_RESULT_SUCCESS != (*m_playItf)->SetPositionUpdatePeriod(m_playItf,
newInterval)) {
return;
}
m_notifyInterval = newInterval;
}
int QOpenSLESAudioOutput::notifyInterval() const
@@ -480,13 +507,12 @@ bool QOpenSLESAudioOutput::preparePlayer()
return false;
}
SLuint32 mask = SL_PLAYEVENT_HEADATEND;
if (m_notifyInterval && SL_RESULT_SUCCESS == (*m_playItf)->SetPositionUpdatePeriod(m_playItf,
m_notifyInterval)) {
mask |= SL_PLAYEVENT_HEADATNEWPOS;
m_eventMask |= SL_PLAYEVENT_HEADATNEWPOS;
}
if (SL_RESULT_SUCCESS != (*m_playItf)->SetCallbackEventsMask(m_playItf, mask)) {
if (SL_RESULT_SUCCESS != (*m_playItf)->SetCallbackEventsMask(m_playItf, m_eventMask)) {
setError(QAudio::FatalError);
return false;
}

View File

@@ -112,6 +112,7 @@ private:
qint64 m_elapsedTime;
qint64 m_processedBytes;
QAtomicInt m_availableBuffers;
SLuint32 m_eventMask;
qint32 m_streamType;
QTime m_clockStamp;

View File

@@ -44,7 +44,9 @@ unix:!mac:!android {
config_alsa: SUBDIRS += alsa
# v4l is turned off because it is not supported in Qt 5
# !maemo*:SUBDIRS += v4l
# config_linux_v4l {
# !maemo*:SUBDIRS += v4l
# }
}
mac:!simulator {

View File

@@ -404,6 +404,7 @@ QList<QByteArray> QWindowsAudioDeviceInfo::availableDevices(QAudio::Mode mode)
Q_UNUSED(mode)
QList<QByteArray> devices;
#ifndef Q_OS_WINCE
//enumerate device fullnames through directshow api
CoInitialize(NULL);
ICreateDevEnum *pDevEnum = NULL;
@@ -455,6 +456,35 @@ QList<QByteArray> QWindowsAudioDeviceInfo::availableDevices(QAudio::Mode mode)
}
}
CoUninitialize();
#else // Q_OS_WINCE
if (mode == QAudio::AudioOutput) {
WAVEOUTCAPS woc;
unsigned long iNumDevs,i;
iNumDevs = waveOutGetNumDevs();
for (i=0;i<iNumDevs;i++) {
if (waveOutGetDevCaps(i, &woc, sizeof(WAVEOUTCAPS))
== MMSYSERR_NOERROR) {
QByteArray device;
QDataStream ds(&device, QIODevice::WriteOnly);
ds << quint32(i) << QString::fromWCharArray(woc.szPname);
devices.append(device);
}
}
} else {
WAVEINCAPS woc;
unsigned long iNumDevs,i;
iNumDevs = waveInGetNumDevs();
for (i=0;i<iNumDevs;i++) {
if (waveInGetDevCaps(i, &woc, sizeof(WAVEINCAPS))
== MMSYSERR_NOERROR) {
QByteArray device;
QDataStream ds(&device, QIODevice::WriteOnly);
ds << quint32(i) << QString::fromWCharArray(woc.szPname);
devices.append(device);
}
}
}
#endif // !Q_OS_WINCE
return devices;
}

View File

@@ -5,7 +5,8 @@ PLUGIN_TYPE = audio
PLUGIN_CLASS_NAME = QWindowsAudioPlugin
load(qt_plugin)
LIBS += -lwinmm -lstrmiids -lole32 -loleaut32
LIBS += -lstrmiids -lole32 -loleaut32
!wince*:LIBS += -lwinmm
HEADERS += \
qwindowsaudioplugin.h \

View File

@@ -1395,14 +1395,17 @@ int MFPlayerSession::bufferStatus()
if (!m_netsourceStatistics)
return 0;
PROPVARIANT var;
PropVariantInit(&var);
PROPERTYKEY key;
key.fmtid = MFNETSOURCE_STATISTICS;
key.pid = MFNETSOURCE_BUFFERPROGRESS_ID;
int progress = -1;
if (SUCCEEDED(m_netsourceStatistics->GetValue(key, &var))) {
// GetValue returns S_FALSE if the property is not available, which has
// a value > 0. We therefore can't use the SUCCEEDED macro here.
if (m_netsourceStatistics->GetValue(key, &var) == S_OK) {
progress = var.lVal;
PropVariantClear(&var);
}
PropVariantClear(&var);
#ifdef DEBUG_MEDIAFOUNDATION
qDebug() << "bufferStatus: progress = " << progress;
@@ -1413,22 +1416,30 @@ int MFPlayerSession::bufferStatus()
QMediaTimeRange MFPlayerSession::availablePlaybackRanges()
{
if (!m_netsourceStatistics)
return QMediaTimeRange();
// defaults to the whole media
qint64 start = 0;
qint64 end = qint64(m_duration / 10000);
qint64 start = 0, end = 0;
PROPVARIANT var;
PROPERTYKEY key;
key.fmtid = MFNETSOURCE_STATISTICS;
key.pid = MFNETSOURCE_SEEKRANGESTART_ID;
if (SUCCEEDED(m_netsourceStatistics->GetValue(key, &var))) {
start = qint64(var.uhVal.QuadPart / 10000);
key.pid = MFNETSOURCE_SEEKRANGEEND_ID;
if (SUCCEEDED(m_netsourceStatistics->GetValue(key, &var))) {
end = qint64(var.uhVal.QuadPart / 10000);
if (m_netsourceStatistics) {
PROPVARIANT var;
PropVariantInit(&var);
PROPERTYKEY key;
key.fmtid = MFNETSOURCE_STATISTICS;
key.pid = MFNETSOURCE_SEEKRANGESTART_ID;
// GetValue returns S_FALSE if the property is not available, which has
// a value > 0. We therefore can't use the SUCCEEDED macro here.
if (m_netsourceStatistics->GetValue(key, &var) == S_OK) {
start = qint64(var.uhVal.QuadPart / 10000);
PropVariantClear(&var);
PropVariantInit(&var);
key.pid = MFNETSOURCE_SEEKRANGEEND_ID;
if (m_netsourceStatistics->GetValue(key, &var) == S_OK) {
end = qint64(var.uhVal.QuadPart / 10000);
PropVariantClear(&var);
}
}
}
PropVariantClear(&var);
return QMediaTimeRange(start, end);
}

View File

@@ -212,7 +212,7 @@ public:
stride /= 4;
}
m_width = qreal(m_frame.width() / stride);
m_width = qreal(m_frame.width()) / stride;
textureSize.setWidth(stride);
if (m_textureSize != textureSize) {