summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYoann Lopes <yoann.lopes@digia.com>2014-09-01 14:19:53 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-09-01 14:19:53 +0200
commitbc1fa076c944c6af3250cb7210190da42a4de6ea (patch)
treeb6948fa95abbdd4ffbb30b76c7d3c09ae07e51db /src
parent0c3438c9a12fbc607eada8f938cf0ad8fdea374d (diff)
parent659f238bbbe040cce1bdf900f8f5500845ca8727 (diff)
downloadqtmultimedia-bc1fa076c944c6af3250cb7210190da42a4de6ea.tar.gz
Merge "Merge remote-tracking branch 'origin/5.3' into 5.4" into refs/staging/5.4v5.4.0-alpha1
Diffstat (limited to 'src')
-rw-r--r--src/gsttools/gsttools.pro2
-rw-r--r--src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp4
-rw-r--r--src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h1
-rw-r--r--src/plugins/android/src/mediaplayer/qandroidmediaservice.cpp4
-rw-r--r--src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp10
-rw-r--r--src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h4
-rw-r--r--src/plugins/android/src/wrappers/jni/androidmediametadataretriever.cpp133
-rw-r--r--src/plugins/android/src/wrappers/jni/androidmediametadataretriever.h4
-rw-r--r--src/plugins/avfoundation/camera/avfcameraservice.mm4
-rw-r--r--src/plugins/avfoundation/mediaplayer/avfmediaplayerservice.mm5
-rw-r--r--src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h3
-rw-r--r--src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm103
-rw-r--r--src/plugins/avfoundation/mediaplayer/avfvideowidget.mm4
-rw-r--r--src/plugins/avfoundation/mediaplayer/avfvideowindowcontrol.mm4
-rw-r--r--src/plugins/coreaudio/coreaudiooutput.mm4
-rw-r--r--src/plugins/gstreamer/camerabin/camerabin.pro2
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinserviceplugin.cpp3
-rw-r--r--src/plugins/gstreamer/mediacapture/mediacapture.pro21
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp9
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h2
-rw-r--r--src/plugins/opensles/qopenslesaudiooutput.cpp36
-rw-r--r--src/plugins/opensles/qopenslesaudiooutput.h1
-rw-r--r--src/plugins/plugins.pro4
-rw-r--r--src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp30
-rw-r--r--src/plugins/windowsaudio/windowsaudio.pro3
-rw-r--r--src/plugins/wmf/player/mfplayersession.cpp41
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_rgb.cpp2
27 files changed, 304 insertions, 139 deletions
diff --git a/src/gsttools/gsttools.pro b/src/gsttools/gsttools.pro
index 15edd04d2..7c809a777 100644
--- a/src/gsttools/gsttools.pro
+++ b/src/gsttools/gsttools.pro
@@ -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
diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp
index 47dd94ccd..bd936f86d 100644
--- a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp
+++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp
@@ -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();
}
diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h
index 86d99e822..ec4dd3280 100644
--- a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h
+++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h
@@ -72,6 +72,7 @@ public:
Q_SIGNALS:
void metaDataUpdated();
+ void actualMediaLocationChanged(const QString &url);
public Q_SLOTS:
void setPosition(qint64 position) Q_DECL_OVERRIDE;
diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaservice.cpp b/src/plugins/android/src/mediaplayer/qandroidmediaservice.cpp
index 00e8b6184..05cee3b9d 100644
--- a/src/plugins/android/src/mediaplayer/qandroidmediaservice.cpp
+++ b/src/plugins/android/src/mediaplayer/qandroidmediaservice.cpp
@@ -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()));
}
diff --git a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp
index a3598228c..a9c87488a 100644
--- a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp
+++ b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp
@@ -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);
diff --git a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h
index 72df6eecc..f8720b77a 100644
--- a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h
+++ b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h
@@ -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;
diff --git a/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.cpp b/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.cpp
index a01aacf5e..df5345053 100644
--- a/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.cpp
+++ b/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.cpp
@@ -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 fd = fileInputStream.callObjectMethod("getFD",
+ "()Ljava/io/FileDescriptor;");
+ if (exceptionCheckAndClear(env)) {
+ fileInputStream.callMethod<void>("close");
+ 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();
- } else {
m_metadataRetriever.callMethod<void>("setDataSource",
- "(Landroid/content/Context;Landroid/net/Uri;)V",
- QtAndroidPrivate::activity(),
- uri.object());
- if (env->ExceptionCheck())
- env->ExceptionClear();
- else
- loaded = true;
- }
+ "(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;
+ }
- return loaded;
-}
+ m_metadataRetriever.callMethod<void>("setDataSource",
+ "(Ljava/io/FileDescriptor;JJ)V",
+ fd.object(),
+ assetFd.callMethod<jlong>("getStartOffset"),
+ assetFd.callMethod<jlong>("getLength"));
-bool AndroidMediaMetadataRetriever::setDataSource(const QString &path)
-{
- if (!m_metadataRetriever.isValid())
- return false;
+ bool ok = !exceptionCheckAndClear(env);
- QJNIEnvironmentPrivate env;
+ assetFd.callMethod<void>("close");
+ exceptionCheckAndClear(env);
- bool loaded = false;
+ 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;)V",
- QJNIObjectPrivate::fromString(path).object());
- if (env->ExceptionCheck())
- env->ExceptionClear();
- else
- loaded = true;
+ 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 (exceptionCheckAndClear(env))
+ return false;
+ }
- return loaded;
+ return true;
}
QT_END_NAMESPACE
diff --git a/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.h b/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.h
index 1cf0bcc91..c1633580f 100644
--- a/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.h
+++ b/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.h
@@ -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;
diff --git a/src/plugins/avfoundation/camera/avfcameraservice.mm b/src/plugins/avfoundation/camera/avfcameraservice.mm
index 25111c5cc..966202ede 100644
--- a/src/plugins/avfoundation/camera/avfcameraservice.mm
+++ b/src/plugins/avfoundation/camera/avfcameraservice.mm
@@ -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;
}
}
diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayerservice.mm b/src/plugins/avfoundation/mediaplayer/avfmediaplayerservice.mm
index e5549803f..bb75adb8b 100644
--- a/src/plugins/avfoundation/mediaplayer/avfmediaplayerservice.mm
+++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayerservice.mm
@@ -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
}
diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h
index 09ac4b5b3..c850f45de 100644
--- a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h
+++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h
@@ -148,6 +148,9 @@ private:
QByteArray rawData;
};
+ void setAudioAvailable(bool available);
+ void setVideoAvailable(bool available);
+
AVFMediaPlayerService *m_service;
AVFVideoOutput *m_videoOutput;
diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm
index a73974ccd..106e81a37 100644
--- a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm
+++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm
@@ -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]) {
diff --git a/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm b/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm
index d4fa7c4c6..2893921f3 100644
--- a/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm
+++ b/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm
@@ -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
diff --git a/src/plugins/avfoundation/mediaplayer/avfvideowindowcontrol.mm b/src/plugins/avfoundation/mediaplayer/avfvideowindowcontrol.mm
index 17fc94de7..8e96d732f 100644
--- a/src/plugins/avfoundation/mediaplayer/avfvideowindowcontrol.mm
+++ b/src/plugins/avfoundation/mediaplayer/avfvideowindowcontrol.mm
@@ -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
diff --git a/src/plugins/coreaudio/coreaudiooutput.mm b/src/plugins/coreaudio/coreaudiooutput.mm
index e5e1c65e5..812d9dfe2 100644
--- a/src/plugins/coreaudio/coreaudiooutput.mm
+++ b/src/plugins/coreaudio/coreaudiooutput.mm
@@ -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()
diff --git a/src/plugins/gstreamer/camerabin/camerabin.pro b/src/plugins/gstreamer/camerabin/camerabin.pro
index bba797f5e..90a1040fb 100644
--- a/src/plugins/gstreamer/camerabin/camerabin.pro
+++ b/src/plugins/gstreamer/camerabin/camerabin.pro
@@ -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
diff --git a/src/plugins/gstreamer/camerabin/camerabinserviceplugin.cpp b/src/plugins/gstreamer/camerabin/camerabinserviceplugin.cpp
index 4e7630b72..8c943529e 100644
--- a/src/plugins/gstreamer/camerabin/camerabinserviceplugin.cpp
+++ b/src/plugins/gstreamer/camerabin/camerabinserviceplugin.cpp
@@ -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
diff --git a/src/plugins/gstreamer/mediacapture/mediacapture.pro b/src/plugins/gstreamer/mediacapture/mediacapture.pro
index e8d039f8d..5baa0fd8f 100644
--- a/src/plugins/gstreamer/mediacapture/mediacapture.pro
+++ b/src/plugins/gstreamer/mediacapture/mediacapture.pro
@@ -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
}
-
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp
index 2e73797ee..97a165dca 100644
--- a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp
+++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp
@@ -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)));
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h
index 2b1a0dcca..7ff8ce253 100644
--- a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h
+++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h
@@ -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;
diff --git a/src/plugins/opensles/qopenslesaudiooutput.cpp b/src/plugins/opensles/qopenslesaudiooutput.cpp
index f055796b5..f6583e542 100644
--- a/src/plugins/opensles/qopenslesaudiooutput.cpp
+++ b/src/plugins/opensles/qopenslesaudiooutput.cpp
@@ -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;
}
diff --git a/src/plugins/opensles/qopenslesaudiooutput.h b/src/plugins/opensles/qopenslesaudiooutput.h
index 60c8cfa86..d466ea64b 100644
--- a/src/plugins/opensles/qopenslesaudiooutput.h
+++ b/src/plugins/opensles/qopenslesaudiooutput.h
@@ -112,6 +112,7 @@ private:
qint64 m_elapsedTime;
qint64 m_processedBytes;
QAtomicInt m_availableBuffers;
+ SLuint32 m_eventMask;
qint32 m_streamType;
QTime m_clockStamp;
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index 0020203c3..f03a138ec 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -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 {
diff --git a/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp b/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp
index 59a9f661f..4f8f03836 100644
--- a/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp
+++ b/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp
@@ -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;
}
diff --git a/src/plugins/windowsaudio/windowsaudio.pro b/src/plugins/windowsaudio/windowsaudio.pro
index a1a327953..ead73251b 100644
--- a/src/plugins/windowsaudio/windowsaudio.pro
+++ b/src/plugins/windowsaudio/windowsaudio.pro
@@ -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 \
diff --git a/src/plugins/wmf/player/mfplayersession.cpp b/src/plugins/wmf/player/mfplayersession.cpp
index 77b19f1b0..4ddb82ee6 100644
--- a/src/plugins/wmf/player/mfplayersession.cpp
+++ b/src/plugins/wmf/player/mfplayersession.cpp
@@ -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);
}
diff --git a/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp b/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp
index e993609ad..72cbc9614 100644
--- a/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp
+++ b/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp
@@ -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) {