From b6e1c004142d64a1cb2f83f9928cd2bbadaf0914 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Mon, 29 Sep 2014 17:46:47 +0200 Subject: [PATCH 1/5] AVFoundation: fix build with iOS 8.0 SDK. Change-Id: I9d9b97ad88631ba12a289f7575ca53386e592bd1 Reviewed-by: Jake Petroules --- src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm index 106e81a3..d6f0607a 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm @@ -295,7 +295,7 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe //AVPlayerItem "status" property value observer. if (context == AVFMediaPlayerSessionObserverStatusObservationContext) { - AVPlayerStatus status = [[change objectForKey:NSKeyValueChangeNewKey] integerValue]; + AVPlayerStatus status = (AVPlayerStatus)[[change objectForKey:NSKeyValueChangeNewKey] integerValue]; switch (status) { //Indicates that the status of the player is not yet known because From b3d88c66be2ba6a6975cd3dd152a40fe429ecb6c Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 25 Sep 2014 07:15:25 +0200 Subject: [PATCH 2/5] WMF: Fix null ptr derefernce in MFPlayerSession. Checking the sender of the mediaSourceReady signal to prevent accessing the incorrect source resolver. When the source resolver has finished the asynchronous operation and the source resolver gets recreated in the player at the same time in a different thread the signal mediaSourceReady still gets emitted from the old source resolver. The player assumes that the signal was emitted from the current source resolver and accesses the unresolved media source in the handleMediaSourceReady slot. Task-number: QTBUG-39980 Change-Id: Ic52f6918995aac250048d91f89c520cfea111bd0 Reviewed-by: Yoann Lopes --- src/plugins/wmf/player/mfplayersession.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/wmf/player/mfplayersession.cpp b/src/plugins/wmf/player/mfplayersession.cpp index 0de0bdfd..2d4f46b1 100644 --- a/src/plugins/wmf/player/mfplayersession.cpp +++ b/src/plugins/wmf/player/mfplayersession.cpp @@ -250,7 +250,7 @@ void MFPlayerSession::handleSourceError(long hr) void MFPlayerSession::handleMediaSourceReady() { - if (QMediaPlayer::LoadingMedia != m_status || !m_sourceResolver) + if (QMediaPlayer::LoadingMedia != m_status || !m_sourceResolver || m_sourceResolver != sender()) return; #ifdef DEBUG_MEDIAFOUNDATION qDebug() << "handleMediaSourceReady"; From cda94f73a30cbdf3e6c32ec9a9f771d602ad1aa3 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 25 Sep 2014 07:18:13 +0200 Subject: [PATCH 3/5] WMF: Use media source only when it is initialized. Change-Id: I0efcf6139d0b81194cf25383025f080f8656728c Reviewed-by: Yoann Lopes --- src/plugins/wmf/player/mfplayersession.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/plugins/wmf/player/mfplayersession.cpp b/src/plugins/wmf/player/mfplayersession.cpp index 2d4f46b1..4ccf0ceb 100644 --- a/src/plugins/wmf/player/mfplayersession.cpp +++ b/src/plugins/wmf/player/mfplayersession.cpp @@ -256,8 +256,13 @@ void MFPlayerSession::handleMediaSourceReady() qDebug() << "handleMediaSourceReady"; #endif HRESULT hr = S_OK; - IMFPresentationDescriptor* sourcePD; IMFMediaSource* mediaSource = m_sourceResolver->mediaSource(); + + DWORD dwCharacteristics = 0; + mediaSource->GetCharacteristics(&dwCharacteristics); + emit seekableUpdate(MFMEDIASOURCE_CAN_SEEK & dwCharacteristics); + + IMFPresentationDescriptor* sourcePD; hr = mediaSource->CreatePresentationDescriptor(&sourcePD); if (SUCCEEDED(hr)) { m_duration = 0; @@ -1638,10 +1643,6 @@ void MFPlayerSession::handleSessionEvent(IMFMediaEvent *sessionEvent) } } - DWORD dwCharacteristics = 0; - m_sourceResolver->mediaSource()->GetCharacteristics(&dwCharacteristics); - emit seekableUpdate(MFMEDIASOURCE_CAN_SEEK & dwCharacteristics); - // Topology is resolved and successfuly set, this happens only after loading a new media. // Make sure we always start the media from the beginning m_varStart.vt = VT_I8; From 2d911d4e0926969528be8e170a02f74f4761ee25 Mon Sep 17 00:00:00 2001 From: Bernd Weimer Date: Wed, 24 Sep 2014 15:43:46 +0200 Subject: [PATCH 4/5] QNX: Fix resetting video surface If video surface object is set to 0, it must not be accessed to set a property on it. Task-number: QTBUG-40746 Change-Id: I1de0e5495918d3ea06706412fab15bf1af012f36 Reviewed-by: Fabian Bumberger --- .../qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp b/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp index b9fe9502..8b2f081e 100644 --- a/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp +++ b/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp @@ -78,7 +78,7 @@ void MmRendererPlayerVideoRendererControl::setSurface(QAbstractVideoSurface *sur m_surface = QPointer(surface); if (QOpenGLContext::currentContext()) m_windowGrabber->checkForEglImageExtension(); - else + else if (m_surface) m_surface->setProperty("_q_GLThreadCallback", QVariant::fromValue(this)); } From b366a99eb14f166ebdcfcb6d328b4d7552227b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Mon, 29 Sep 2014 16:18:49 +0200 Subject: [PATCH 5/5] Android: Use the new findClass() method. Avoid local caching. Change-Id: I1e30896da664c5a45c38c09412c16cb8ff70c5c7 Reviewed-by: Yoann Lopes --- .../src/wrappers/jni/androidcamera.cpp | 32 +++++++-------- .../src/wrappers/jni/androidmediaplayer.cpp | 41 +++++++++---------- .../src/wrappers/jni/androidmediarecorder.cpp | 28 ++++++------- .../wrappers/jni/androidsurfacetexture.cpp | 28 ++++++------- 4 files changed, 58 insertions(+), 71 deletions(-) diff --git a/src/plugins/android/src/wrappers/jni/androidcamera.cpp b/src/plugins/android/src/wrappers/jni/androidcamera.cpp index dbe9393c..b9ea1a6a 100644 --- a/src/plugins/android/src/wrappers/jni/androidcamera.cpp +++ b/src/plugins/android/src/wrappers/jni/androidcamera.cpp @@ -43,7 +43,7 @@ QT_BEGIN_NAMESPACE -static jclass g_qtCameraListenerClass = 0; +static const char QtCameraListenerClassName[] = "org/qtproject/qt5/android/multimedia/QtCameraListener"; static QMutex g_cameraMapMutex; typedef QMap CameraMap; Q_GLOBAL_STATIC(CameraMap, g_cameraMap) @@ -720,7 +720,7 @@ bool AndroidCameraPrivate::init(int cameraId) if (exceptionCheckAndClear(env) || !m_camera.isValid()) return false; - m_cameraListener = QJNIObjectPrivate(g_qtCameraListenerClass, "(I)V", m_cameraId); + m_cameraListener = QJNIObjectPrivate(QtCameraListenerClassName, "(I)V", m_cameraId); m_info = QJNIObjectPrivate("android/hardware/Camera$CameraInfo"); m_camera.callStaticMethod("android/hardware/Camera", "getCameraInfo", @@ -1392,24 +1392,22 @@ QStringList AndroidCameraPrivate::callParametersStringListMethod(const QByteArra return stringList; } -static JNINativeMethod methods[] = { - {"notifyAutoFocusComplete", "(IZ)V", (void *)notifyAutoFocusComplete}, - {"notifyPictureExposed", "(I)V", (void *)notifyPictureExposed}, - {"notifyPictureCaptured", "(I[B)V", (void *)notifyPictureCaptured}, - {"notifyFrameFetched", "(I[B)V", (void *)notifyFrameFetched} -}; - bool AndroidCamera::initJNI(JNIEnv *env) { - jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtCameraListener"); + jclass clazz = QJNIEnvironmentPrivate::findClass(QtCameraListenerClassName, + env); - if (!exceptionCheckAndClear(env) && clazz) { - g_qtCameraListenerClass = static_cast(env->NewGlobalRef(clazz)); - if (env->RegisterNatives(g_qtCameraListenerClass, - methods, - sizeof(methods) / sizeof(methods[0])) < 0) { - return false; - } + static const JNINativeMethod methods[] = { + {"notifyAutoFocusComplete", "(IZ)V", (void *)notifyAutoFocusComplete}, + {"notifyPictureExposed", "(I)V", (void *)notifyPictureExposed}, + {"notifyPictureCaptured", "(I[B)V", (void *)notifyPictureCaptured}, + {"notifyFrameFetched", "(I[B)V", (void *)notifyFrameFetched} + }; + + if (clazz && env->RegisterNatives(clazz, + methods, + sizeof(methods) / sizeof(methods[0])) != JNI_OK) { + return false; } return true; diff --git a/src/plugins/android/src/wrappers/jni/androidmediaplayer.cpp b/src/plugins/android/src/wrappers/jni/androidmediaplayer.cpp index a285f018..9f826456 100644 --- a/src/plugins/android/src/wrappers/jni/androidmediaplayer.cpp +++ b/src/plugins/android/src/wrappers/jni/androidmediaplayer.cpp @@ -39,7 +39,7 @@ #include "androidsurfacetexture.h" #include -static jclass mediaPlayerClass = Q_NULLPTR; +static const char QtAndroidMediaPlayerClassName[] = "org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer"; typedef QMap MediaPlayerMap; Q_GLOBAL_STATIC(MediaPlayerMap, mediaPlayers) @@ -50,10 +50,10 @@ AndroidMediaPlayer::AndroidMediaPlayer() { const jlong id = reinterpret_cast(this); - mMediaPlayer = QJNIObjectPrivate(mediaPlayerClass, - "(Landroid/app/Activity;J)V", - QtAndroidPrivate::activity(), - id); + mMediaPlayer = QJNIObjectPrivate(QtAndroidMediaPlayerClassName, + "(Landroid/app/Activity;J)V", + QtAndroidPrivate::activity(), + id); (*mediaPlayers)[id] = this; } @@ -233,26 +233,23 @@ static void onVideoSizeChangedNative(JNIEnv *env, bool AndroidMediaPlayer::initJNI(JNIEnv *env) { - jclass jClass = env->FindClass("org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer"); + jclass clazz = QJNIEnvironmentPrivate::findClass(QtAndroidMediaPlayerClassName, + env); - if (jClass) { - mediaPlayerClass = static_cast(env->NewGlobalRef(jClass)); + static const JNINativeMethod methods[] = { + {"onErrorNative", "(IIJ)V", reinterpret_cast(onErrorNative)}, + {"onBufferingUpdateNative", "(IJ)V", reinterpret_cast(onBufferingUpdateNative)}, + {"onProgressUpdateNative", "(IJ)V", reinterpret_cast(onProgressUpdateNative)}, + {"onDurationChangedNative", "(IJ)V", reinterpret_cast(onDurationChangedNative)}, + {"onInfoNative", "(IIJ)V", reinterpret_cast(onInfoNative)}, + {"onVideoSizeChangedNative", "(IIJ)V", reinterpret_cast(onVideoSizeChangedNative)}, + {"onStateChangedNative", "(IJ)V", reinterpret_cast(onStateChangedNative)} + }; - JNINativeMethod methods[] = { - {"onErrorNative", "(IIJ)V", reinterpret_cast(onErrorNative)}, - {"onBufferingUpdateNative", "(IJ)V", reinterpret_cast(onBufferingUpdateNative)}, - {"onProgressUpdateNative", "(IJ)V", reinterpret_cast(onProgressUpdateNative)}, - {"onDurationChangedNative", "(IJ)V", reinterpret_cast(onDurationChangedNative)}, - {"onInfoNative", "(IIJ)V", reinterpret_cast(onInfoNative)}, - {"onVideoSizeChangedNative", "(IIJ)V", reinterpret_cast(onVideoSizeChangedNative)}, - {"onStateChangedNative", "(IJ)V", reinterpret_cast(onStateChangedNative)} - }; - - if (env->RegisterNatives(mediaPlayerClass, - methods, - sizeof(methods) / sizeof(methods[0])) < 0) { + if (clazz && env->RegisterNatives(clazz, + methods, + sizeof(methods) / sizeof(methods[0])) != JNI_OK) { return false; - } } return true; diff --git a/src/plugins/android/src/wrappers/jni/androidmediarecorder.cpp b/src/plugins/android/src/wrappers/jni/androidmediarecorder.cpp index 074f1c92..2d2b6e2f 100644 --- a/src/plugins/android/src/wrappers/jni/androidmediarecorder.cpp +++ b/src/plugins/android/src/wrappers/jni/androidmediarecorder.cpp @@ -113,7 +113,7 @@ AndroidCamcorderProfile::AndroidCamcorderProfile(const QJNIObjectPrivate &camcor m_camcorderProfile = camcorderProfile; } -static jclass g_qtMediaRecorderListenerClass = 0; +static const char QtMediaRecorderListenerClassName[] = "org/qtproject/qt5/android/multimedia/QtMediaRecorderListener"; typedef QMap MediaRecorderMap; Q_GLOBAL_STATIC(MediaRecorderMap, mediaRecorders) @@ -137,7 +137,7 @@ AndroidMediaRecorder::AndroidMediaRecorder() { m_mediaRecorder = QJNIObjectPrivate("android/media/MediaRecorder"); if (m_mediaRecorder.isValid()) { - QJNIObjectPrivate listener(g_qtMediaRecorderListenerClass, "(J)V", m_id); + QJNIObjectPrivate listener(QtMediaRecorderListenerClassName, "(J)V", m_id); m_mediaRecorder.callMethod("setOnErrorListener", "(Landroid/media/MediaRecorder$OnErrorListener;)V", listener.object()); @@ -339,24 +339,20 @@ void AndroidMediaRecorder::setOutputFile(const QString &path) } } -static JNINativeMethod methods[] = { - {"notifyError", "(JII)V", (void *)notifyError}, - {"notifyInfo", "(JII)V", (void *)notifyInfo} -}; - bool AndroidMediaRecorder::initJNI(JNIEnv *env) { - jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtMediaRecorderListener"); - if (env->ExceptionCheck()) - env->ExceptionClear(); + jclass clazz = QJNIEnvironmentPrivate::findClass(QtMediaRecorderListenerClassName, + env); - if (clazz) { - g_qtMediaRecorderListenerClass = static_cast(env->NewGlobalRef(clazz)); - if (env->RegisterNatives(g_qtMediaRecorderListenerClass, - methods, - sizeof(methods) / sizeof(methods[0])) < 0) { + static const JNINativeMethod methods[] = { + {"notifyError", "(JII)V", (void *)notifyError}, + {"notifyInfo", "(JII)V", (void *)notifyInfo} + }; + + if (clazz && env->RegisterNatives(clazz, + methods, + sizeof(methods) / sizeof(methods[0])) != JNI_OK) { return false; - } } return true; diff --git a/src/plugins/android/src/wrappers/jni/androidsurfacetexture.cpp b/src/plugins/android/src/wrappers/jni/androidsurfacetexture.cpp index 261a644d..7cdab009 100644 --- a/src/plugins/android/src/wrappers/jni/androidsurfacetexture.cpp +++ b/src/plugins/android/src/wrappers/jni/androidsurfacetexture.cpp @@ -37,7 +37,7 @@ QT_BEGIN_NAMESPACE -static jclass g_qtSurfaceTextureListenerClass = 0; +static const char QtSurfaceTextureListenerClassName[] = "org/qtproject/qt5/android/multimedia/QtSurfaceTextureListener"; static QMap g_objectMap; // native method for QtSurfaceTexture.java @@ -70,7 +70,7 @@ AndroidSurfaceTexture::AndroidSurfaceTexture(unsigned int texName) if (m_surfaceTexture.isValid()) g_objectMap.insert(int(texName), this); - QJNIObjectPrivate listener(g_qtSurfaceTextureListenerClass, "(I)V", jint(texName)); + QJNIObjectPrivate listener(QtSurfaceTextureListenerClassName, "(I)V", jint(texName)); m_surfaceTexture.callMethod("setOnFrameAvailableListener", "(Landroid/graphics/SurfaceTexture$OnFrameAvailableListener;)V", listener.object()); @@ -144,27 +144,23 @@ jobject AndroidSurfaceTexture::surfaceHolder() return m_surfaceHolder.object(); } -static JNINativeMethod methods[] = { - {"notifyFrameAvailable", "(I)V", (void *)notifyFrameAvailable} -}; - bool AndroidSurfaceTexture::initJNI(JNIEnv *env) { // SurfaceTexture is available since API 11. if (QtAndroidPrivate::androidSdkVersion() < 11) return false; - jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtSurfaceTextureListener"); - if (env->ExceptionCheck()) - env->ExceptionClear(); + jclass clazz = QJNIEnvironmentPrivate::findClass(QtSurfaceTextureListenerClassName, + env); - if (clazz) { - g_qtSurfaceTextureListenerClass = static_cast(env->NewGlobalRef(clazz)); - if (env->RegisterNatives(g_qtSurfaceTextureListenerClass, - methods, - sizeof(methods) / sizeof(methods[0])) < 0) { - return false; - } + static const JNINativeMethod methods[] = { + {"notifyFrameAvailable", "(I)V", (void *)notifyFrameAvailable} + }; + + if (clazz && env->RegisterNatives(clazz, + methods, + sizeof(methods) / sizeof(methods[0])) != JNI_OK) { + return false; } return true;