From b6970e2e79aac9a63bc4db5f879a3f050889f991 Mon Sep 17 00:00:00 2001 From: Sergio Ahumada Date: Mon, 31 Mar 2014 18:11:02 +0200 Subject: Doc: Fix some documentation warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Can't link to 'QSlider' - Can't link to 'QImage' Change-Id: Ifa1a27ca5224959d6dbb4c0055a56114740469f0 Reviewed-by: Sze Howe Koh Reviewed-by: Jędrzej Nowacki --- src/multimedia/doc/qtmultimedia.qdocconf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/multimedia/doc/qtmultimedia.qdocconf b/src/multimedia/doc/qtmultimedia.qdocconf index 83abf5b49..d6ff6822e 100644 --- a/src/multimedia/doc/qtmultimedia.qdocconf +++ b/src/multimedia/doc/qtmultimedia.qdocconf @@ -43,7 +43,7 @@ sourcedirs += ../.. excludedirs += ../../multimediawidgets -depends += qtcore qtdoc qtquick qtqml qtmultimediawidgets +depends += qtcore qtdoc qtgui qtquick qtqml qtmultimediawidgets qtwidgets navigation.landingpage = "Qt Multimedia" navigation.cppclassespage = "Qt Multimedia C++ Classes" -- cgit v1.2.3 From d2b54b360ec0cedf2dfd64c72cc8f476fb93bc7c Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Mon, 31 Mar 2014 14:22:40 +0200 Subject: CoreAudio: fix supported channel count. We were using the number of channels actually used by audio devices as the maximum channel count. This is wrong as CoreAudio can automatically split or merge channels in order to accommodate the device. We now assume all channel configurations are valid. Task-number: QTBUG-37956 Change-Id: Ia8e8bbea8543caa7fecda305be74a2953b92fd25 Reviewed-by: Andy Nichols --- src/plugins/coreaudio/coreaudiodeviceinfo.mm | 36 ++++-------------------- src/plugins/coreaudio/coreaudiosessionmanager.h | 3 -- src/plugins/coreaudio/coreaudiosessionmanager.mm | 10 ------- 3 files changed, 6 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/plugins/coreaudio/coreaudiodeviceinfo.mm b/src/plugins/coreaudio/coreaudiodeviceinfo.mm index 56765cafd..ac41a310c 100644 --- a/src/plugins/coreaudio/coreaudiodeviceinfo.mm +++ b/src/plugins/coreaudio/coreaudiodeviceinfo.mm @@ -196,38 +196,14 @@ QList CoreAudioDeviceInfo::supportedSampleRates() QList CoreAudioDeviceInfo::supportedChannelCounts() { - QList supportedChannels; - int maxChannels = 0; + static QList supportedChannels; -#if defined(Q_OS_OSX) - UInt32 propSize = 0; - AudioObjectPropertyScope scope = m_mode == QAudio::AudioInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; - AudioObjectPropertyAddress streamConfigurationPropertyAddress = { kAudioDevicePropertyStreamConfiguration, - scope, - kAudioObjectPropertyElementMaster }; - - if (AudioObjectGetPropertyDataSize(m_deviceId, &streamConfigurationPropertyAddress, 0, NULL, &propSize) == noErr) { - AudioBufferList* audioBufferList = static_cast(malloc(propSize)); - - if (audioBufferList != 0) { - if (AudioObjectGetPropertyData(m_deviceId, &streamConfigurationPropertyAddress, 0, NULL, &propSize, audioBufferList) == noErr) { - for (int i = 0; i < int(audioBufferList->mNumberBuffers); ++i) - maxChannels += audioBufferList->mBuffers[i].mNumberChannels; - } - - free(audioBufferList); - } + if (supportedChannels.isEmpty()) { + // If the number of channels is not supported by an audio device, Core Audio will + // automatically convert the audio data. + for (int i = 1; i <= 16; ++i) + supportedChannels.append(i); } -#else //iOS - if (m_mode == QAudio::AudioInput) - maxChannels = CoreAudioSessionManager::instance().inputChannelCount(); - else if (m_mode == QAudio::AudioOutput) - maxChannels = CoreAudioSessionManager::instance().outputChannelCount(); -#endif - - // Assume all channel configurations are supported up to the maximum number of channels - for (int i = 1; i <= maxChannels; ++i) - supportedChannels.append(i); return supportedChannels; } diff --git a/src/plugins/coreaudio/coreaudiosessionmanager.h b/src/plugins/coreaudio/coreaudiosessionmanager.h index 61d8967b1..26f8fee09 100644 --- a/src/plugins/coreaudio/coreaudiosessionmanager.h +++ b/src/plugins/coreaudio/coreaudiosessionmanager.h @@ -92,9 +92,6 @@ public: QList inputDevices(); QList outputDevices(); - int inputChannelCount(); - int outputChannelCount(); - float currentIOBufferDuration(); float preferredSampleRate(); diff --git a/src/plugins/coreaudio/coreaudiosessionmanager.mm b/src/plugins/coreaudio/coreaudiosessionmanager.mm index 0e795e786..04c8b6ed4 100644 --- a/src/plugins/coreaudio/coreaudiosessionmanager.mm +++ b/src/plugins/coreaudio/coreaudiosessionmanager.mm @@ -377,16 +377,6 @@ QList CoreAudioSessionManager::outputDevices() return outputDevices; } -int CoreAudioSessionManager::inputChannelCount() -{ - return [[m_sessionObserver audioSession] inputNumberOfChannels]; -} - -int CoreAudioSessionManager::outputChannelCount() -{ - return [[m_sessionObserver audioSession] outputNumberOfChannels]; -} - float CoreAudioSessionManager::currentIOBufferDuration() { return [[m_sessionObserver audioSession] IOBufferDuration]; -- cgit v1.2.3 From 36649887e8ba8841b45522a772cf83b5c5130fca Mon Sep 17 00:00:00 2001 From: Fabian Bumberger Date: Fri, 21 Mar 2014 16:02:48 +0100 Subject: QNX: Remove most of the CPU overhead for video rendering This patch uses the GL_OES_EGL_image extension to create a OpenGL Texture handle for a libscreen pixmap. If the extension is not available it uses the "old" technique as fallback where the image data is copied into a QImage. This reduces the CPU load by more than 70% and allows HD videos to be played jitter-free. Task-number: QTBUG-37752 Change-Id: I4cad22c39390e4cf9eb5be5f0bfe446544a11b9e Reviewed-by: Bernd Weimer Reviewed-by: Sean Harmer --- src/plugins/qnx/camera/bbcamerasession.cpp | 2 +- src/plugins/qnx/common/windowgrabber.cpp | 173 +++++++++++++++------ src/plugins/qnx/common/windowgrabber.h | 29 +++- .../mmrendererplayervideorenderercontrol.cpp | 81 +++++++++- .../mmrendererplayervideorenderercontrol.h | 4 +- .../qdeclarativevideooutput_render.cpp | 10 ++ 6 files changed, 236 insertions(+), 63 deletions(-) (limited to 'src') diff --git a/src/plugins/qnx/camera/bbcamerasession.cpp b/src/plugins/qnx/camera/bbcamerasession.cpp index 77ba71493..618aca533 100644 --- a/src/plugins/qnx/camera/bbcamerasession.cpp +++ b/src/plugins/qnx/camera/bbcamerasession.cpp @@ -140,7 +140,7 @@ BbCameraSession::BbCameraSession(QObject *parent) connect(this, SIGNAL(captureModeChanged(QCamera::CaptureModes)), SLOT(updateReadyForCapture())); connect(m_orientationHandler, SIGNAL(orientationChanged(int)), SLOT(deviceOrientationChanged(int))); - connect(m_windowGrabber, SIGNAL(frameGrabbed(QImage)), SLOT(viewfinderFrameGrabbed(QImage))); + connect(m_windowGrabber, SIGNAL(frameGrabbed(QImage, int)), SLOT(viewfinderFrameGrabbed(QImage))); } BbCameraSession::~BbCameraSession() diff --git a/src/plugins/qnx/common/windowgrabber.cpp b/src/plugins/qnx/common/windowgrabber.cpp index 5ed54b87e..3f6eaca41 100644 --- a/src/plugins/qnx/common/windowgrabber.cpp +++ b/src/plugins/qnx/common/windowgrabber.cpp @@ -47,6 +47,8 @@ #include #include +#include + #ifdef Q_OS_BLACKBERRY #include #include @@ -57,13 +59,15 @@ QT_BEGIN_NAMESPACE WindowGrabber::WindowGrabber(QObject *parent) : QObject(parent), - m_screenBuffer(0), m_screenBufferWidth(-1), m_screenBufferHeight(-1), m_active(false), m_screenContextInitialized(false), - m_screenPixmapInitialized(false), - m_screenPixmapBufferInitialized(false) + m_screenPixmapBuffersInitialized(false), + m_currentFrame(0), + m_eglImageSupported(false), + m_eglImagesInitialized(false), + m_eglImageCheck(false) { // grab the window frame with 60 frames per second m_timer.setInterval(1000/60); @@ -76,6 +80,11 @@ WindowGrabber::WindowGrabber(QObject *parent) WindowGrabber::~WindowGrabber() { QCoreApplication::eventDispatcher()->removeNativeEventFilter(this); + if (eglImagesInitialized()) { + glDeleteTextures(2, imgTextures); + eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), img[0]); + eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), img[1]); + } } void WindowGrabber::setFrameRate(int frameRate) @@ -83,6 +92,37 @@ void WindowGrabber::setFrameRate(int frameRate) m_timer.setInterval(1000/frameRate); } +void WindowGrabber::createEglImages() +{ + // Do nothing if either egl images are not supported, the screen context is not valid + // or the images are already created + if (!eglImageSupported() || !m_screenContextInitialized || eglImagesInitialized()) + return; + + glGenTextures(2, imgTextures); + glBindTexture(GL_TEXTURE_2D, imgTextures[0]); + img[0] = eglCreateImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), EGL_NO_CONTEXT, + EGL_NATIVE_PIXMAP_KHR, + m_screenPixmaps[0], + 0); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, img[0]); + + glBindTexture(GL_TEXTURE_2D, imgTextures[1]); + img[1] = eglCreateImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), EGL_NO_CONTEXT, + EGL_NATIVE_PIXMAP_KHR, + m_screenPixmaps[1], + 0); + + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, img[1]); + + if (img[0] == 0 || img[1] == 0) { + qWarning() << "Failed to create KHR images" << img[0] << img[1] << strerror(errno) << errno; + m_eglImageSupported = false; + } else { + m_eglImagesInitialized = true; + } +} + void WindowGrabber::setWindowId(const QByteArray &windowId) { m_windowId = windowId; @@ -90,6 +130,9 @@ void WindowGrabber::setWindowId(const QByteArray &windowId) void WindowGrabber::start() { + if (m_active) + return; + int result = 0; #ifdef Q_OS_BLACKBERRY_TABLET @@ -124,30 +167,21 @@ void WindowGrabber::start() m_screenContextInitialized = true; } - result = screen_create_pixmap(&m_screenPixmap, m_screenContext); + result = screen_create_pixmap(&m_screenPixmaps[0], m_screenContext); + result = screen_create_pixmap(&m_screenPixmaps[1], m_screenContext); if (result != 0) { cleanup(); - qWarning() << "WindowGrabber: cannot create pixmap:" << strerror(errno); + qWarning() << "WindowGrabber: cannot create pixmaps:" << strerror(errno); return; - } else { - m_screenPixmapInitialized = true; } - const int usage = SCREEN_USAGE_READ | SCREEN_USAGE_NATIVE; - result = screen_set_pixmap_property_iv(m_screenPixmap, SCREEN_PROPERTY_USAGE, &usage); - if (result != 0) { - cleanup(); - qWarning() << "WindowGrabber: cannot set pixmap usage:" << strerror(errno); - return; - } + const int usage = SCREEN_USAGE_NATIVE; + result = screen_set_pixmap_property_iv(m_screenPixmaps[0], SCREEN_PROPERTY_USAGE, &usage); + result |= screen_set_pixmap_property_iv(m_screenPixmaps[1], SCREEN_PROPERTY_USAGE, &usage); - const int format = SCREEN_FORMAT_RGBA8888; - result = screen_set_pixmap_property_iv(m_screenPixmap, SCREEN_PROPERTY_FORMAT, &format); - if (result != 0) { - cleanup(); - qWarning() << "WindowGrabber: cannot set pixmap format:" << strerror(errno); - return; - } + const int format = SCREEN_FORMAT_RGBX8888; + screen_set_pixmap_property_iv(m_screenPixmaps[0], SCREEN_PROPERTY_FORMAT, &format); + screen_set_pixmap_property_iv(m_screenPixmaps[1], SCREEN_PROPERTY_FORMAT, &format); int size[2] = { 0, 0 }; @@ -172,37 +206,51 @@ void WindowGrabber::updateFrameSize() { int size[2] = { m_screenBufferWidth, m_screenBufferHeight }; - int result = screen_set_pixmap_property_iv(m_screenPixmap, SCREEN_PROPERTY_BUFFER_SIZE, size); - if (result != 0) { - cleanup(); - qWarning() << "WindowGrabber: cannot set pixmap size:" << strerror(errno); - return; - } + screen_set_pixmap_property_iv(m_screenPixmaps[0], SCREEN_PROPERTY_BUFFER_SIZE, size); + if (eglImageSupported()) + screen_set_pixmap_property_iv(m_screenPixmaps[1], SCREEN_PROPERTY_BUFFER_SIZE, size); + + int result = screen_create_pixmap_buffer(m_screenPixmaps[0]); + if (eglImageSupported()) + result |= screen_create_pixmap_buffer(m_screenPixmaps[1]); - result = screen_create_pixmap_buffer(m_screenPixmap); if (result != 0) { cleanup(); qWarning() << "WindowGrabber: cannot create pixmap buffer:" << strerror(errno); return; + } else { + m_screenPixmapBuffersInitialized = true; + } + + result = screen_get_pixmap_property_pv(m_screenPixmaps[0], SCREEN_PROPERTY_RENDER_BUFFERS, + (void**)&m_screenPixmapBuffers[0]); + if (eglImageSupported()) { + result |= screen_get_pixmap_property_pv(m_screenPixmaps[1], SCREEN_PROPERTY_RENDER_BUFFERS, + (void**)&m_screenPixmapBuffers[1]); } - result = screen_get_pixmap_property_pv(m_screenPixmap, SCREEN_PROPERTY_RENDER_BUFFERS, (void**)&m_screenPixmapBuffer); if (result != 0) { cleanup(); qWarning() << "WindowGrabber: cannot get pixmap buffer:" << strerror(errno); return; - } else { - m_screenPixmapBufferInitialized = true; } - result = screen_get_buffer_property_pv(m_screenPixmapBuffer, SCREEN_PROPERTY_POINTER, (void**)&m_screenBuffer); + result = screen_get_buffer_property_pv(m_screenPixmapBuffers[0], SCREEN_PROPERTY_POINTER, + (void**)&m_screenBuffers[0]); + if (eglImageSupported()) { + result |= screen_get_buffer_property_pv(m_screenPixmapBuffers[1], SCREEN_PROPERTY_POINTER, + (void**)&m_screenBuffers[1]); + } + if (result != 0) { cleanup(); qWarning() << "WindowGrabber: cannot get pixmap buffer pointer:" << strerror(errno); return; } - result = screen_get_buffer_property_iv(m_screenPixmapBuffer, SCREEN_PROPERTY_STRIDE, &m_screenBufferStride); + result = screen_get_buffer_property_iv(m_screenPixmapBuffers[0], SCREEN_PROPERTY_STRIDE, + &m_screenBufferStride); + if (result != 0) { cleanup(); qWarning() << "WindowGrabber: cannot get pixmap buffer stride:" << strerror(errno); @@ -310,8 +358,40 @@ QByteArray WindowGrabber::windowGroupId() const return QByteArray(groupIdData); } +bool WindowGrabber::eglImageSupported() +{ + return m_eglImageSupported; +} + +void WindowGrabber::checkForEglImageExtension() +{ + QOpenGLContext *m_context = QOpenGLContext::currentContext(); + if (!m_context) //Should not happen, because we are called from the render thread + return; + + QByteArray eglExtensions = QByteArray(eglQueryString(eglGetDisplay(EGL_DEFAULT_DISPLAY), + EGL_EXTENSIONS)); + m_eglImageSupported = m_context->hasExtension(QByteArrayLiteral("GL_OES_EGL_image")) + && eglExtensions.contains(QByteArrayLiteral("EGL_KHR_image")); + + m_eglImageCheck = true; +} + +bool WindowGrabber::eglImagesInitialized() +{ + return m_eglImagesInitialized; +} + void WindowGrabber::grab() { + if (!m_eglImageCheck) // We did not check for egl images yet + return; + + if (eglImageSupported()) + m_currentFrame = (m_currentFrame + 1) % 2; + else + m_currentFrame = 0; + int size[2] = { 0, 0 }; int result = screen_get_window_property_iv(m_window, SCREEN_PROPERTY_SOURCE_SIZE, size); @@ -324,40 +404,33 @@ void WindowGrabber::grab() if (m_screenBufferWidth != size[0] || m_screenBufferHeight != size[1]) { // The source viewport size changed, so we have to adapt our buffers - if (m_screenPixmapBufferInitialized) { - screen_destroy_pixmap_buffer(m_screenPixmap); - m_screenPixmapBufferInitialized = false; + if (m_screenPixmapBuffersInitialized) { + screen_destroy_pixmap_buffer(m_screenPixmaps[0]); + if (eglImageSupported()) + screen_destroy_pixmap_buffer(m_screenPixmaps[1]); } m_screenBufferWidth = size[0]; m_screenBufferHeight = size[1]; updateFrameSize(); + m_eglImagesInitialized = false; } const int rect[] = { 0, 0, m_screenBufferWidth, m_screenBufferHeight }; - result = screen_read_window(m_window, m_screenPixmapBuffer, 1, rect, 0); + result = screen_read_window(m_window, m_screenPixmapBuffers[m_currentFrame], 1, rect, 0); if (result != 0) return; - const QImage frame((unsigned char*)m_screenBuffer, m_screenBufferWidth, m_screenBufferHeight, - m_screenBufferStride, QImage::Format_ARGB32); + const QImage frame((unsigned char*)m_screenBuffers[m_currentFrame], m_screenBufferWidth, + m_screenBufferHeight, m_screenBufferStride, QImage::Format_ARGB32); - emit frameGrabbed(frame); + emit frameGrabbed(frame, imgTextures[m_currentFrame]); } void WindowGrabber::cleanup() { - if (m_screenPixmapBufferInitialized) { - screen_destroy_buffer(m_screenPixmapBuffer); - m_screenPixmapBufferInitialized = false; - } - - if (m_screenPixmapInitialized) { - screen_destroy_pixmap(m_screenPixmap); - m_screenPixmapInitialized = false; - } - + //We only need to destroy the context as it frees all resources associated with it if (m_screenContextInitialized) { screen_destroy_context(m_screenContext); m_screenContextInitialized = false; diff --git a/src/plugins/qnx/common/windowgrabber.h b/src/plugins/qnx/common/windowgrabber.h index 7ec4202a2..40351ef25 100644 --- a/src/plugins/qnx/common/windowgrabber.h +++ b/src/plugins/qnx/common/windowgrabber.h @@ -41,6 +41,12 @@ #ifndef WINDOWGRABBER_H #define WINDOWGRABBER_H +#define EGL_EGLEXT_PROTOTYPES = 1 +#define GL_GLEXT_PROTOTYPES = 1 +#include +#include +#include +#include #include #include #include @@ -59,6 +65,8 @@ public: void setFrameRate(int frameRate); + void createEglImages(); + void setWindowId(const QByteArray &windowId); void start(); @@ -73,8 +81,12 @@ public: QByteArray windowGroupId() const; + bool eglImageSupported(); + void checkForEglImageExtension(); + bool eglImagesInitialized(); + signals: - void frameGrabbed(const QImage &frame); + void frameGrabbed(const QImage &frame, int); private slots: void grab(); @@ -89,10 +101,10 @@ private: screen_window_t m_window; screen_context_t m_screenContext; - screen_pixmap_t m_screenPixmap; - screen_buffer_t m_screenPixmapBuffer; + screen_pixmap_t m_screenPixmaps[2]; + screen_buffer_t m_screenPixmapBuffers[2]; - char* m_screenBuffer; + char *m_screenBuffers[2]; int m_screenBufferWidth; int m_screenBufferHeight; @@ -100,8 +112,13 @@ private: bool m_active : 1; bool m_screenContextInitialized : 1; - bool m_screenPixmapInitialized : 1; - bool m_screenPixmapBufferInitialized : 1; + bool m_screenPixmapBuffersInitialized : 1; + int m_currentFrame; + EGLImageKHR img[2]; + GLuint imgTextures[2]; + bool m_eglImageSupported : 1; + bool m_eglImagesInitialized : 1; + bool m_eglImageCheck : 1; // We must not send a grabed frame before this is true }; QT_END_NAMESPACE diff --git a/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp b/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp index 0abdfec49..b9fe95026 100644 --- a/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp +++ b/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include @@ -59,7 +60,7 @@ MmRendererPlayerVideoRendererControl::MmRendererPlayerVideoRendererControl(QObje , m_context(0) , m_videoId(-1) { - connect(m_windowGrabber, SIGNAL(frameGrabbed(QImage)), SLOT(frameGrabbed(QImage))); + connect(m_windowGrabber, SIGNAL(frameGrabbed(QImage, int)), SLOT(frameGrabbed(QImage, int))); } MmRendererPlayerVideoRendererControl::~MmRendererPlayerVideoRendererControl() @@ -75,6 +76,10 @@ QAbstractVideoSurface *MmRendererPlayerVideoRendererControl::surface() const void MmRendererPlayerVideoRendererControl::setSurface(QAbstractVideoSurface *surface) { m_surface = QPointer(surface); + if (QOpenGLContext::currentContext()) + m_windowGrabber->checkForEglImageExtension(); + else + m_surface->setProperty("_q_GLThreadCallback", QVariant::fromValue(this)); } void MmRendererPlayerVideoRendererControl::attachDisplay(mmr_context_t *context) @@ -139,20 +144,86 @@ void MmRendererPlayerVideoRendererControl::resume() m_windowGrabber->resume(); } -void MmRendererPlayerVideoRendererControl::frameGrabbed(const QImage &frame) +class BBTextureBuffer : public QAbstractVideoBuffer +{ +public: + BBTextureBuffer(int handle) : + QAbstractVideoBuffer(QAbstractVideoBuffer::GLTextureHandle) + { + m_handle = handle; + } + MapMode mapMode() const { + return QAbstractVideoBuffer::ReadWrite; + } + void unmap() { + + } + uchar *map(MapMode mode, int * numBytes, int * bytesPerLine) { + Q_UNUSED(mode); + Q_UNUSED(numBytes); + Q_UNUSED(bytesPerLine); + return 0; + } + QVariant handle() const { + return m_handle; + } +private: + int m_handle; +}; + +void MmRendererPlayerVideoRendererControl::frameGrabbed(const QImage &frame, int handle) { if (m_surface) { if (!m_surface->isActive()) { - m_surface->start(QVideoSurfaceFormat(frame.size(), QVideoFrame::Format_ARGB32)); + if (m_windowGrabber->eglImageSupported()) { + if (QOpenGLContext::currentContext()) + m_windowGrabber->createEglImages(); + else + m_surface->setProperty("_q_GLThreadCallback", QVariant::fromValue(this)); + + m_surface->start(QVideoSurfaceFormat(frame.size(), QVideoFrame::Format_BGR32, + QAbstractVideoBuffer::GLTextureHandle)); + } else { + m_surface->start(QVideoSurfaceFormat(frame.size(), QVideoFrame::Format_ARGB32)); + } } else { if (m_surface->surfaceFormat().frameSize() != frame.size()) { + QAbstractVideoBuffer::HandleType type = m_surface->surfaceFormat().handleType(); m_surface->stop(); - m_surface->start(QVideoSurfaceFormat(frame.size(), QVideoFrame::Format_ARGB32)); + if (type != QAbstractVideoBuffer::NoHandle) { + m_surface->setProperty("_q_GLThreadCallback", QVariant::fromValue(this)); + m_surface->start(QVideoSurfaceFormat(frame.size(), QVideoFrame::Format_BGR32, + QAbstractVideoBuffer::GLTextureHandle)); + } else { + m_surface->start(QVideoSurfaceFormat(frame.size(), QVideoFrame::Format_ARGB32)); + } } } - m_surface->present(frame.copy()); + // Depending on the support of EGL images on the current platform we either pass a texture + // handle or a copy of the image data + if (m_surface->surfaceFormat().handleType() != QAbstractVideoBuffer::NoHandle) { + if (m_windowGrabber->eglImagesInitialized() && + m_surface->property("_q_GLThreadCallback") != 0) + m_surface->setProperty("_q_GLThreadCallback", 0); + + + BBTextureBuffer *textBuffer = new BBTextureBuffer(handle); + QVideoFrame actualFrame(textBuffer, frame.size(), QVideoFrame::Format_BGR32); + m_surface->present(actualFrame); + } else { + m_surface->present(frame.copy()); + } } } +void MmRendererPlayerVideoRendererControl::customEvent(QEvent *e) +{ + // This is running in the render thread (OpenGL enabled) + if (e->type() == QEvent::User) + m_windowGrabber->checkForEglImageExtension(); + else if (e->type() == QEvent::User + 1) + m_windowGrabber->createEglImages(); +} + QT_END_NAMESPACE diff --git a/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.h b/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.h index 4e271ad5d..5624b464e 100644 --- a/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.h +++ b/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.h @@ -67,8 +67,10 @@ public: void pause(); void resume(); + void customEvent(QEvent *) Q_DECL_OVERRIDE; + private Q_SLOTS: - void frameGrabbed(const QImage &frame); + void frameGrabbed(const QImage &frame, int); private: QPointer m_surface; diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp b/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp index cd03cd6b8..647732485 100644 --- a/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp +++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp @@ -201,6 +201,16 @@ QSGNode *QDeclarativeVideoRendererBackend::updatePaintNode(QSGNode *oldNode, obj->event(&ev); } } +#if defined (Q_OS_QNX) // On QNX we need to be called back again for creating the egl images + else { + // Internal mechanism to call back the surface renderer from the QtQuick render thread + QObject *obj = m_surface->property("_q_GLThreadCallback").value(); + if (obj) { + QEvent ev(static_cast(QEvent::User + 1)); + obj->event(&ev); + } + } +#endif if (m_frameChanged) { if (videoNode && videoNode->pixelFormat() != m_frame.pixelFormat()) { -- cgit v1.2.3 From feaa55716486711e6499ae1cc2c84326642f3daa Mon Sep 17 00:00:00 2001 From: Liang Jian Date: Tue, 1 Apr 2014 15:16:28 +0800 Subject: Fix QSGGeometry object leak Set QSGNode::OwnsGeometry flag to QSGVideoNode, otherwise the QSGGeometry object created in QSGVideoNode::setTexturedRectGeometry() will be leaked. Change-Id: I383b4fe2ff8c7921d2c9c101d4d90fac5a08365a Reviewed-by: Yoann Lopes --- src/qtmultimediaquicktools/qsgvideonode_p.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/qtmultimediaquicktools/qsgvideonode_p.cpp b/src/qtmultimediaquicktools/qsgvideonode_p.cpp index b958180a0..6fbc1443b 100644 --- a/src/qtmultimediaquicktools/qsgvideonode_p.cpp +++ b/src/qtmultimediaquicktools/qsgvideonode_p.cpp @@ -46,6 +46,7 @@ QT_BEGIN_NAMESPACE QSGVideoNode::QSGVideoNode() : m_orientation(-1) { + setFlag(QSGNode::OwnsGeometry); } /* Helpers */ -- cgit v1.2.3 From 155ae9e88b07ffb6d38f962624b8ef911f1efe45 Mon Sep 17 00:00:00 2001 From: Liang Jian Date: Tue, 1 Apr 2014 16:12:48 +0800 Subject: Fix SourceResolver::State object leak Initialize m_cRef to 0 in constructor of SourceResolver::State, otherwise it will be leaked Change-Id: I703ef8e91ad88112102ede7e8321d0eca795b840 Reviewed-by: Yoann Lopes --- src/plugins/wmf/sourceresolver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/wmf/sourceresolver.cpp b/src/plugins/wmf/sourceresolver.cpp index 9ac126bda..57da12282 100644 --- a/src/plugins/wmf/sourceresolver.cpp +++ b/src/plugins/wmf/sourceresolver.cpp @@ -278,7 +278,7 @@ IMFMediaSource* SourceResolver::mediaSource() const ///////////////////////////////////////////////////////////////////////////////// SourceResolver::State::State(IMFSourceResolver *sourceResolver, bool fromStream) - : m_cRef(1) + : m_cRef(0) , m_sourceResolver(sourceResolver) , m_fromStream(fromStream) { -- cgit v1.2.3 From 244c63f72a8ec6aededda40723bf61b7f32bf277 Mon Sep 17 00:00:00 2001 From: Liang Jian Date: Tue, 1 Apr 2014 14:41:30 +0800 Subject: Fix memory leak in SampleGrabberCallback Add virtual destructor to SampleGrabberCallback to let it properly destruct its subclass when calling 'detete this' Change-Id: I5f74f82314e22225a0a153c7f4bca531a79dd8f9 Reviewed-by: Friedemann Kleint Reviewed-by: Yoann Lopes --- src/plugins/wmf/samplegrabber.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/plugins/wmf/samplegrabber.h b/src/plugins/wmf/samplegrabber.h index 7a5c2260b..63cb5fa62 100644 --- a/src/plugins/wmf/samplegrabber.h +++ b/src/plugins/wmf/samplegrabber.h @@ -72,6 +72,9 @@ public: protected: SampleGrabberCallback() : m_cRef(1) {} +public: + virtual ~SampleGrabberCallback() {} + private: long m_cRef; }; -- cgit v1.2.3 From 3a18ec30f030d52026880c67d928654822eede8f Mon Sep 17 00:00:00 2001 From: Fabian Bumberger Date: Thu, 27 Mar 2014 16:18:11 +0100 Subject: BlackBerry: Fix the rotation of the viewfinder This fixes the rotation of the viewfinder. We have to adjust the orientation depending on the primary screen orientation. On a keyboard device, the viewfinder would not rotate at all (same if auto orientation is turned off). Task-number: QTBUG-37894 Change-Id: I2bf955fb3303ed236d3234154ded94fe78607455 Reviewed-by: Yoann Lopes Reviewed-by: Bernd Weimer Reviewed-by: Rafael Roquetto --- src/plugins/qnx/camera/bbcameraorientationhandler.cpp | 18 +++++++++++++++++- src/plugins/qnx/camera/bbcameraorientationhandler.h | 2 ++ src/plugins/qnx/camera/bbcamerasession.cpp | 11 ++++++++--- 3 files changed, 27 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/plugins/qnx/camera/bbcameraorientationhandler.cpp b/src/plugins/qnx/camera/bbcameraorientationhandler.cpp index b715249f9..393c9e6d8 100644 --- a/src/plugins/qnx/camera/bbcameraorientationhandler.cpp +++ b/src/plugins/qnx/camera/bbcameraorientationhandler.cpp @@ -41,7 +41,8 @@ #include "bbcameraorientationhandler.h" #include -#include +#include +#include #include #include @@ -87,6 +88,10 @@ bool BbCameraOrientationHandler::nativeEventFilter(const QByteArray&, void *mess const int angle = orientation_event_get_angle(event); if (angle != m_orientation) { +#ifndef Q_OS_BLACKBERRY_TABLET + if (angle == 180) // The screen does not rotate at 180 degrees + return false; +#endif m_orientation = angle; emit orientationChanged(m_orientation); } @@ -94,6 +99,17 @@ bool BbCameraOrientationHandler::nativeEventFilter(const QByteArray&, void *mess return false; // do not drop the event } +int BbCameraOrientationHandler::viewfinderOrientation() const +{ + // On a keyboard device we do not rotate the screen at all + if (qGuiApp->primaryScreen()->nativeOrientation() + != qGuiApp->primaryScreen()->primaryOrientation()) { + return m_orientation; + } + + return 0; +} + int BbCameraOrientationHandler::orientation() const { return m_orientation; diff --git a/src/plugins/qnx/camera/bbcameraorientationhandler.h b/src/plugins/qnx/camera/bbcameraorientationhandler.h index 3d236b884..42d68915b 100644 --- a/src/plugins/qnx/camera/bbcameraorientationhandler.h +++ b/src/plugins/qnx/camera/bbcameraorientationhandler.h @@ -57,6 +57,8 @@ public: int orientation() const; + int viewfinderOrientation() const; + Q_SIGNALS: void orientationChanged(int degree); diff --git a/src/plugins/qnx/camera/bbcamerasession.cpp b/src/plugins/qnx/camera/bbcamerasession.cpp index 618aca533..c5309b045 100644 --- a/src/plugins/qnx/camera/bbcamerasession.cpp +++ b/src/plugins/qnx/camera/bbcamerasession.cpp @@ -772,11 +772,16 @@ void BbCameraSession::viewfinderFrameGrabbed(const QImage &image) { QTransform transform; + // subtract out the native rotation transform.rotate(m_nativeCameraOrientation); + // subtract out the current device orientation + if (m_device == cameraIdentifierRear()) + transform.rotate(360 - m_orientationHandler->viewfinderOrientation()); + else + transform.rotate(m_orientationHandler->viewfinderOrientation()); + QImage frame = image.copy().transformed(transform); - if (m_device == cameraIdentifierFront()) - frame = frame.mirrored(true, false); QMutexLocker locker(&m_surfaceMutex); if (m_surface) { @@ -896,7 +901,7 @@ bool BbCameraSession::startViewFinder() return false; } - const int angle = m_orientationHandler->orientation(); + const int angle = m_orientationHandler->viewfinderOrientation(); const QSize rotatedSize = ((angle == 0 || angle == 180) ? viewfinderResolution : viewfinderResolution.transposed()); -- cgit v1.2.3 From 3d51c9565da75b533926ca8bb98fe5746fc37d3b Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Fri, 7 Mar 2014 17:02:37 +0100 Subject: GStreamer: each QMediaPlayer now has its own volume by default. We were using the volume property of GStreamer's playbin element to set the volume. This could behave differently depending on the system configuration; it could affect the system volume or the media player own audio stream. We now use a 'volume' element to do software attenuation on the audio data sent to the audio sink, it allows each QMediaPlayer to always have its own volume. To preserve the previous behavior, developers can set the QT_GSTREAMER_USE_PLAYBIN_VOLUME environment variable to true. [ChangeLog][QtMultimedia][GStreamer] QMediaPlayer::setVolume() doesn't change the system volume anymore (it could be the case before depending on the system configuration). Set the QT_GSTREAMER_USE_PLAYBIN_VOLUME environment variable to true to restore that behavior. Task-number: QTBUG-30317 Task-number: QTBUG-36511 Change-Id: Ia0249962a74ac21fb110fcb634c08706f8d5767a Reviewed-by: Wouter Huysentruit Reviewed-by: Christian Stromme --- .../mediaplayer/qgstreamerplayersession.cpp | 61 +++++++++++++++++----- .../mediaplayer/qgstreamerplayersession.h | 1 + 2 files changed, 49 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp index f4ac59420..f7522a5f7 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp @@ -67,6 +67,20 @@ QT_BEGIN_NAMESPACE +static bool usePlaybinVolume() +{ + static enum { Yes, No, Unknown } status = Unknown; + if (status == Unknown) { + QByteArray v = qgetenv("QT_GSTREAMER_USE_PLAYBIN_VOLUME"); + bool value = !v.isEmpty() && v != "0" && v != "false"; + if (value) + status = Yes; + else + status = No; + } + return status == Yes; +} + typedef enum { GST_PLAY_FLAG_VIDEO = 0x00000001, GST_PLAY_FLAG_AUDIO = 0x00000002, @@ -104,6 +118,7 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent) m_pendingVideoSink(0), m_nullVideoSink(0), m_audioSink(0), + m_volumeElement(0), m_bus(0), m_videoOutput(0), m_renderer(0), @@ -151,8 +166,28 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent) #endif g_object_set(G_OBJECT(m_playbin), "flags", flags, NULL); - m_audioSink = gst_element_factory_make("autoaudiosink", "audiosink"); - if (m_audioSink) { + GstElement *audioSink = gst_element_factory_make("autoaudiosink", "audiosink"); + if (audioSink) { + if (usePlaybinVolume()) { + m_audioSink = audioSink; + m_volumeElement = m_playbin; + } else { + m_volumeElement = gst_element_factory_make("volume", "volumeelement"); + if (m_volumeElement) { + m_audioSink = gst_bin_new("audio-output-bin"); + + gst_bin_add_many(GST_BIN(m_audioSink), m_volumeElement, audioSink, NULL); + gst_element_link(m_volumeElement, audioSink); + + GstPad *pad = gst_element_get_static_pad(m_volumeElement, "sink"); + gst_element_add_pad(GST_ELEMENT(m_audioSink), gst_ghost_pad_new("sink", pad)); + gst_object_unref(GST_OBJECT(pad)); + } else { + m_audioSink = audioSink; + m_volumeElement = m_playbin; + } + } + g_object_set(G_OBJECT(m_playbin), "audio-sink", m_audioSink, NULL); addAudioBufferProbe(); } @@ -193,12 +228,12 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent) g_signal_connect(G_OBJECT(m_playbin), "notify::source", G_CALLBACK(playbinNotifySource), this); g_signal_connect(G_OBJECT(m_playbin), "element-added", G_CALLBACK(handleElementAdded), this); - // Init volume and mute state - g_object_set(G_OBJECT(m_playbin), "volume", 1.0, NULL); - g_object_set(G_OBJECT(m_playbin), "mute", FALSE, NULL); - - g_signal_connect(G_OBJECT(m_playbin), "notify::volume", G_CALLBACK(handleVolumeChange), this); - g_signal_connect(G_OBJECT(m_playbin), "notify::mute", G_CALLBACK(handleMutedChange), this); + if (usePlaybinVolume()) { + updateVolume(); + updateMuted(); + g_signal_connect(G_OBJECT(m_playbin), "notify::volume", G_CALLBACK(handleVolumeChange), this); + g_signal_connect(G_OBJECT(m_playbin), "notify::mute", G_CALLBACK(handleMutedChange), this); + } g_signal_connect(G_OBJECT(m_playbin), "video-changed", G_CALLBACK(handleStreamsChange), this); g_signal_connect(G_OBJECT(m_playbin), "audio-changed", G_CALLBACK(handleStreamsChange), this); @@ -912,10 +947,8 @@ void QGstreamerPlayerSession::setVolume(int volume) if (m_volume != volume) { m_volume = volume; - if (m_playbin) { - //playbin2 allows to set volume and muted independently, - g_object_set(G_OBJECT(m_playbin), "volume", m_volume/100.0, NULL); - } + if (m_volumeElement) + g_object_set(G_OBJECT(m_volumeElement), "volume", m_volume / 100.0, NULL); emit volumeChanged(m_volume); } @@ -929,7 +962,9 @@ void QGstreamerPlayerSession::setMuted(bool muted) if (m_muted != muted) { m_muted = muted; - g_object_set(G_OBJECT(m_playbin), "mute", m_muted ? TRUE : FALSE, NULL); + if (m_volumeElement) + g_object_set(G_OBJECT(m_volumeElement), "mute", m_muted ? TRUE : FALSE, NULL); + emit mutedStateChanged(m_muted); } } diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h index 94a84e5dd..23e70315b 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h @@ -211,6 +211,7 @@ private: GstElement* m_nullVideoSink; GstElement* m_audioSink; + GstElement* m_volumeElement; GstBus* m_bus; QObject *m_videoOutput; -- cgit v1.2.3 From b0c68a1a07f546fe22a7d76b1a15bb2b39aa550f Mon Sep 17 00:00:00 2001 From: Dmitry Shachnev Date: Mon, 17 Mar 2014 08:44:24 +0400 Subject: Add support for running on big-endian systems Now qtmultimedia test suite passes on powerpc. Change-Id: I540dff93195115ad1dc5725af7293e3b8540403f Reviewed-by: Thiago Macieira Reviewed-by: Yoann Lopes --- src/multimedia/audio/qwavedecoder_p.cpp | 20 ++++++++++++++------ src/multimedia/audio/qwavedecoder_p.h | 2 +- 2 files changed, 15 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/multimedia/audio/qwavedecoder_p.cpp b/src/multimedia/audio/qwavedecoder_p.cpp index 497a146df..974a8f509 100644 --- a/src/multimedia/audio/qwavedecoder_p.cpp +++ b/src/multimedia/audio/qwavedecoder_p.cpp @@ -166,6 +166,8 @@ void QWaveDecoder::handleData() // Swizzle this if (bigEndian) { wave.audioFormat = qFromBigEndian(wave.audioFormat); + } else { + wave.audioFormat = qFromLittleEndian(wave.audioFormat); } if (wave.audioFormat != 0 && wave.audioFormat != 1) { @@ -207,6 +209,8 @@ void QWaveDecoder::handleData() source->read(reinterpret_cast(&descriptor), sizeof(chunk)); if (bigEndian) descriptor.size = qFromBigEndian(descriptor.size); + else + descriptor.size = qFromLittleEndian(descriptor.size); dataSize = descriptor.size; @@ -227,13 +231,15 @@ void QWaveDecoder::handleData() bool QWaveDecoder::enoughDataAvailable() { chunk descriptor; - if (!peekChunk(&descriptor)) + if (!peekChunk(&descriptor, false)) return false; // This is only called for the RIFF/RIFX header, before bigEndian is set, // so we have to manually swizzle if (qstrncmp(descriptor.id, "RIFX", 4) == 0) descriptor.size = qFromBigEndian(descriptor.size); + if (qstrncmp(descriptor.id, "RIFF", 4) == 0) + descriptor.size = qFromLittleEndian(descriptor.size); if (source->bytesAvailable() < qint64(sizeof(chunk) + descriptor.size)) return false; @@ -270,16 +276,18 @@ bool QWaveDecoder::findChunk(const char *chunkId) return false; } -// Handles endianness -bool QWaveDecoder::peekChunk(chunk *pChunk) +bool QWaveDecoder::peekChunk(chunk *pChunk, bool handleEndianness) { if (source->bytesAvailable() < qint64(sizeof(chunk))) return false; source->peek(reinterpret_cast(pChunk), sizeof(chunk)); - if (bigEndian) - pChunk->size = qFromBigEndian(pChunk->size); - + if (handleEndianness) { + if (bigEndian) + pChunk->size = qFromBigEndian(pChunk->size); + else + pChunk->size = qFromLittleEndian(pChunk->size); + } return true; } diff --git a/src/multimedia/audio/qwavedecoder_p.h b/src/multimedia/audio/qwavedecoder_p.h index c21d8cb5b..24cdb7885 100644 --- a/src/multimedia/audio/qwavedecoder_p.h +++ b/src/multimedia/audio/qwavedecoder_p.h @@ -103,7 +103,7 @@ private: char id[4]; quint32 size; }; - bool peekChunk(chunk* pChunk); + bool peekChunk(chunk* pChunk, bool handleEndianness = true); struct RIFFHeader { -- cgit v1.2.3 From d3ba2d6f3f7cbdd8a4e41a7967874f53a2caaec3 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Thu, 3 Apr 2014 15:17:49 +0200 Subject: GStreamer: cleanup system includes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaced some linux includes with to be more portable. Use qt_safe_open() and qt_safe_close() instead of ::open() and ::close(). Task-number: QTBUG-38061 Change-Id: Idb3f50d070ec1701cafba98e79e2e85824653a3a Reviewed-by: Lisandro Damián Nicanor Pérez Meyer Reviewed-by: Christian Stromme --- src/gsttools/gsttools.pro | 2 +- src/gsttools/qgstreamervideoinputdevicecontrol.cpp | 15 +++------------ .../audiodecoder/qgstreameraudiodecoderserviceplugin.cpp | 13 ------------- src/plugins/gstreamer/camerabin/camerabincontrol.cpp | 12 ------------ .../gstreamer/camerabin/camerabinserviceplugin.cpp | 16 +++------------- src/plugins/gstreamer/common.pri | 2 +- .../mediacapture/qgstreamercaptureserviceplugin.cpp | 16 +++------------- .../gstreamer/mediacapture/qgstreamerv4l2input.cpp | 11 +---------- .../mediaplayer/qgstreamerplayerserviceplugin.cpp | 14 -------------- 9 files changed, 12 insertions(+), 89 deletions(-) (limited to 'src') diff --git a/src/gsttools/gsttools.pro b/src/gsttools/gsttools.pro index 46184965c..2a0933bb3 100644 --- a/src/gsttools/gsttools.pro +++ b/src/gsttools/gsttools.pro @@ -2,7 +2,7 @@ TEMPLATE = lib TARGET = qgsttools_p QPRO_PWD = $$PWD -QT = core multimedia-private gui-private +QT = core-private multimedia-private gui-private !static:DEFINES += QT_MAKEDLL diff --git a/src/gsttools/qgstreamervideoinputdevicecontrol.cpp b/src/gsttools/qgstreamervideoinputdevicecontrol.cpp index ad61aefad..e4e202caf 100644 --- a/src/gsttools/qgstreamervideoinputdevicecontrol.cpp +++ b/src/gsttools/qgstreamervideoinputdevicecontrol.cpp @@ -44,16 +44,7 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include QGstreamerVideoInputDeviceControl::QGstreamerVideoInputDeviceControl(QObject *parent) @@ -135,7 +126,7 @@ void QGstreamerVideoInputDeviceControl::update() foreach( const QFileInfo &entryInfo, entries ) { //qDebug() << "Try" << entryInfo.filePath(); - int fd = ::open(entryInfo.filePath().toLatin1().constData(), O_RDWR ); + int fd = qt_safe_open(entryInfo.filePath().toLatin1().constData(), O_RDWR ); if (fd == -1) continue; @@ -165,6 +156,6 @@ void QGstreamerVideoInputDeviceControl::update() m_names.append(entryInfo.filePath()); m_descriptions.append(name); } - ::close(fd); + qt_safe_close(fd); } } diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp index 3085d1391..e6d24216f 100644 --- a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp +++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp @@ -49,19 +49,6 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - // #define QT_SUPPORTEDMIMETYPES_DEBUG QMediaService* QGstreamerAudioDecoderServicePlugin::create(const QString &key) diff --git a/src/plugins/gstreamer/camerabin/camerabincontrol.cpp b/src/plugins/gstreamer/camerabin/camerabincontrol.cpp index c84ebc41a..2ba9b07e8 100644 --- a/src/plugins/gstreamer/camerabin/camerabincontrol.cpp +++ b/src/plugins/gstreamer/camerabin/camerabincontrol.cpp @@ -50,18 +50,6 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - QT_BEGIN_NAMESPACE //#define CAMEABIN_DEBUG 1 diff --git a/src/plugins/gstreamer/camerabin/camerabinserviceplugin.cpp b/src/plugins/gstreamer/camerabin/camerabinserviceplugin.cpp index 37641b001..3decd6070 100644 --- a/src/plugins/gstreamer/camerabin/camerabinserviceplugin.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinserviceplugin.cpp @@ -50,18 +50,8 @@ #include "camerabinservice.h" #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include -#include QT_BEGIN_NAMESPACE @@ -148,7 +138,7 @@ void CameraBinServicePlugin::updateDevices() const QFileInfoList entries = devDir.entryInfoList(QStringList() << "video*"); foreach (const QFileInfo &entryInfo, entries) { - int fd = ::open(entryInfo.filePath().toLatin1().constData(), O_RDWR ); + int fd = qt_safe_open(entryInfo.filePath().toLatin1().constData(), O_RDWR ); if (fd == -1) continue; @@ -178,7 +168,7 @@ void CameraBinServicePlugin::updateDevices() const m_cameraDevices.append(entryInfo.filePath().toLocal8Bit()); m_cameraDescriptions.append(name); } - ::close(fd); + qt_safe_close(fd); } if (!m_cameraDevices.isEmpty()) diff --git a/src/plugins/gstreamer/common.pri b/src/plugins/gstreamer/common.pri index 98e427d71..8b421b8d1 100644 --- a/src/plugins/gstreamer/common.pri +++ b/src/plugins/gstreamer/common.pri @@ -1,5 +1,5 @@ -QT += multimedia-private network +QT += core-private multimedia-private network CONFIG += no_private_qt_headers_warning qtHaveModule(widgets) { diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp index 657b9806f..8b88fbb71 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp @@ -51,18 +51,8 @@ #include "qgstreamercaptureservice.h" #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include -#include QMediaService* QGstreamerCaptureServicePlugin::create(const QString &key) { @@ -155,7 +145,7 @@ void QGstreamerCaptureServicePlugin::updateDevices() const foreach( const QFileInfo &entryInfo, entries ) { //qDebug() << "Try" << entryInfo.filePath(); - int fd = ::open(entryInfo.filePath().toLatin1().constData(), O_RDWR ); + int fd = qt_safe_open(entryInfo.filePath().toLatin1().constData(), O_RDWR ); if (fd == -1) continue; @@ -185,7 +175,7 @@ void QGstreamerCaptureServicePlugin::updateDevices() const m_cameraDevices.append(entryInfo.filePath().toLocal8Bit()); m_cameraDescriptions.append(name); } - ::close(fd); + qt_safe_close(fd); } if (!m_cameraDevices.isEmpty()) diff --git a/src/plugins/gstreamer/mediacapture/qgstreamerv4l2input.cpp b/src/plugins/gstreamer/mediacapture/qgstreamerv4l2input.cpp index b618ab997..450bc51ea 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamerv4l2input.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreamerv4l2input.cpp @@ -44,16 +44,7 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include QT_BEGIN_NAMESPACE diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp index b2ad24899..a9052ca4b 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp @@ -51,20 +51,6 @@ #include "qgstreamerplayerservice.h" #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - QMediaService* QGstreamerPlayerServicePlugin::create(const QString &key) { QGstUtils::initializeGst(); -- cgit v1.2.3 From bfccbcfc4edf65e31fe4b086013e1bf132e9b047 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Fri, 4 Apr 2014 18:43:30 +0200 Subject: DirectShow: fix media seeking while stopped. When changing the position of a media player while stopped, playback was automatically resuming. We now cache the value and actually set the position only when starting playback. Task-number: QTBUG-38068 Change-Id: Ib35302e01967d70350125f9ad920551df2a3c25b Reviewed-by: Christian Stromme --- src/plugins/directshow/player/directshowplayercontrol.cpp | 13 +++++++++++++ src/plugins/directshow/player/directshowplayercontrol.h | 1 + 2 files changed, 14 insertions(+) (limited to 'src') diff --git a/src/plugins/directshow/player/directshowplayercontrol.cpp b/src/plugins/directshow/player/directshowplayercontrol.cpp index 553ccb43b..179f635ec 100644 --- a/src/plugins/directshow/player/directshowplayercontrol.cpp +++ b/src/plugins/directshow/player/directshowplayercontrol.cpp @@ -83,6 +83,7 @@ DirectShowPlayerControl::DirectShowPlayerControl(DirectShowPlayerService *servic , m_streamTypes(0) , m_muteVolume(-1) , m_position(0) + , m_pendingPosition(-1) , m_duration(0) , m_playbackRate(0) , m_seekable(false) @@ -112,12 +113,22 @@ qint64 DirectShowPlayerControl::duration() const qint64 DirectShowPlayerControl::position() const { + if (m_pendingPosition != -1) + return m_pendingPosition; + return const_cast(m_position) = m_service->position(); } void DirectShowPlayerControl::setPosition(qint64 position) { + if (m_state == QMediaPlayer::StoppedState && m_pendingPosition != position) { + m_pendingPosition = position; + emit positionChanged(m_pendingPosition); + return; + } + m_service->seek(position); + m_pendingPosition = -1; } int DirectShowPlayerControl::volume() const @@ -253,6 +264,8 @@ void DirectShowPlayerControl::play() return; } m_service->play(); + if (m_pendingPosition != -1) + setPosition(m_pendingPosition); emit stateChanged(m_state = QMediaPlayer::PlayingState); } diff --git a/src/plugins/directshow/player/directshowplayercontrol.h b/src/plugins/directshow/player/directshowplayercontrol.h index 478389de6..19dcb5a88 100644 --- a/src/plugins/directshow/player/directshowplayercontrol.h +++ b/src/plugins/directshow/player/directshowplayercontrol.h @@ -135,6 +135,7 @@ private: int m_streamTypes; int m_muteVolume; qint64 m_position; + qint64 m_pendingPosition; qint64 m_duration; qreal m_playbackRate; bool m_seekable; -- cgit v1.2.3 From 2d94b598d976374b5b67805f2c55b546582a757a Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 4 Apr 2014 17:09:37 +0200 Subject: make MODULE_PLUGIN_TYPES assignment actually have an effect it must be done before load()ing qt_plugin.prf. Change-Id: I0ad31f8d9761b2d059d656c9e4f674c8a7cc88a6 Reviewed-by: Yoann Lopes --- src/multimedia/multimedia.pro | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/multimedia/multimedia.pro b/src/multimedia/multimedia.pro index 5ed0cefc0..23cca2537 100644 --- a/src/multimedia/multimedia.pro +++ b/src/multimedia/multimedia.pro @@ -1,6 +1,12 @@ TARGET = QtMultimedia QT = core-private network gui-private +MODULE_PLUGIN_TYPES = \ + mediaservice \ + audio \ + video/videonode \ + playlistformats + QMAKE_DOCS = $$PWD/doc/qtmultimedia.qdocconf load(qt_module) @@ -67,11 +73,6 @@ ANDROID_FEATURES += \ android.hardware.camera \ android.hardware.camera.autofocus \ android.hardware.microphone -MODULE_PLUGIN_TYPES = \ - mediaservice \ - audio \ - video/videonode \ - playlistformats win32: LIBS_PRIVATE += -luuid -- cgit v1.2.3 From f78193c73095918695ce68595ee4bbcd0bb978eb Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 4 Apr 2014 18:14:28 +0200 Subject: let videonode plugins declare that they extend QtQuick Change-Id: I4facc9ca0616927f7b1101cecb989fece38c2f7a Reviewed-by: Yoann Lopes --- src/plugins/android/videonode/videonode.pro | 1 + src/plugins/videonode/imx6/imx6.pro | 1 + 2 files changed, 2 insertions(+) (limited to 'src') diff --git a/src/plugins/android/videonode/videonode.pro b/src/plugins/android/videonode/videonode.pro index 4ae2dc36e..661e36436 100644 --- a/src/plugins/android/videonode/videonode.pro +++ b/src/plugins/android/videonode/videonode.pro @@ -2,6 +2,7 @@ TARGET = qtsgvideonode_android QT += quick multimedia-private qtmultimediaquicktools-private PLUGIN_TYPE = video/videonode +PLUGIN_EXTENDS = quick PLUGIN_CLASS_NAME = QAndroidSGVideoNodeFactoryPlugin load(qt_plugin) diff --git a/src/plugins/videonode/imx6/imx6.pro b/src/plugins/videonode/imx6/imx6.pro index a2e6798e3..36e25e86b 100644 --- a/src/plugins/videonode/imx6/imx6.pro +++ b/src/plugins/videonode/imx6/imx6.pro @@ -2,6 +2,7 @@ TARGET = imx6vivantevideonode QT += multimedia-private qtmultimediaquicktools-private PLUGIN_TYPE=video/videonode +PLUGIN_EXTENDS = quick PLUGIN_CLASS_NAME = QSGVivanteVideoNodeFactory load(qt_plugin) -- cgit v1.2.3 From aa3b5edb6dd0442af6afe90ccc93e34eed503d2f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 2 Apr 2014 22:12:01 -0700 Subject: Tell glib not to complain about the use of API recently deprecated When building with glib 2.32 or later, without this #define, it prints a warning saying: function "g_value_get_char" was declared deprecated ("Use 'g_value_get_schar' instead") Since g_value_get_schar is new in 2.32, we can't use it without #ifdef around the call point. Since the old and new functions are identical in behavior, just ask glib not to complain about the use of old functions. I don't know which is the minimum version of glib we require, so I went for the lowest available macro. Change-Id: I33f9aa8497fc6bd50fffb3c59ee7e8e7fcdfe110 Reviewed-by: Yoann Lopes --- src/gsttools/gsttools.pro | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/gsttools/gsttools.pro b/src/gsttools/gsttools.pro index 2a0933bb3..15edd04d2 100644 --- a/src/gsttools/gsttools.pro +++ b/src/gsttools/gsttools.pro @@ -5,6 +5,7 @@ QPRO_PWD = $$PWD QT = core-private multimedia-private gui-private !static:DEFINES += QT_MAKEDLL +DEFINES += GLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_26 unix:!maemo*:contains(QT_CONFIG, alsa) { DEFINES += HAVE_ALSA -- cgit v1.2.3 From b770fefa819dabb7f53f4ed5fe544f3b68b6279c Mon Sep 17 00:00:00 2001 From: Fabian Bumberger Date: Mon, 24 Mar 2014 19:56:26 +0100 Subject: QNX: Fix MediaPlayer states handling Task-number: QTBUG-37753 Change-Id: I61ff490f061dedd8a9bdc22d76969d9afb9a6795 Reviewed-by: Bernd Weimer Reviewed-by: Yoann Lopes Reviewed-by: Rafael Roquetto --- src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp index 004eca36d..2555b2876 100644 --- a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp +++ b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp @@ -351,10 +351,11 @@ void MmRendererMediaPlayerControl::setState(QMediaPlayer::State state) { if (m_state != state) { if (m_videoRendererControl) { - if (state == QMediaPlayer::PausedState) + if (state == QMediaPlayer::PausedState || state == QMediaPlayer::StoppedState) { m_videoRendererControl->pause(); - else if ((state == QMediaPlayer::PlayingState) - && (m_state == QMediaPlayer::PausedState)) { + } else if ((state == QMediaPlayer::PlayingState) + && (m_state == QMediaPlayer::PausedState + || m_state == QMediaPlayer::StoppedState)) { m_videoRendererControl->resume(); } } -- cgit v1.2.3 From 5ff2f4c52d77798063afbd2117ee1a06942f3612 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Fri, 4 Apr 2014 15:06:07 +0200 Subject: WMF: support playback rate in our custom video sink. Change-Id: Ic8fde3398813df68d2f77b2542f1fa507c8ea674 Reviewed-by: Christian Stromme --- src/plugins/wmf/player/mfvideorenderercontrol.cpp | 114 +++++++++++++++++++--- 1 file changed, 99 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/plugins/wmf/player/mfvideorenderercontrol.cpp b/src/plugins/wmf/player/mfvideorenderercontrol.cpp index 1705b2a48..d4d341a45 100644 --- a/src/plugins/wmf/player/mfvideorenderercontrol.cpp +++ b/src/plugins/wmf/player/mfvideorenderercontrol.cpp @@ -772,9 +772,12 @@ namespace qDebug() << "MediaStream::setRate" << rate; #endif QMutexLocker locker(&m_mutex); - m_rate = rate; - queueEvent(MEStreamSinkRateChanged, GUID_NULL, S_OK, NULL); - return S_OK; + HRESULT hr = validateOperation(OpSetRate); + if (SUCCEEDED(hr)) { + m_rate = rate; + hr = queueAsyncOperation(OpSetRate); + } + return hr; } void supportedFormatsChanged() @@ -1158,7 +1161,7 @@ namespace hr = queueEvent(MEStreamSinkPaused, GUID_NULL, hr, NULL); break; case OpSetRate: - //TODO: + hr = queueEvent(MEStreamSinkRateChanged, GUID_NULL, S_OK, NULL); break; case OpProcessSample: case OpPlaceMarker: @@ -1335,7 +1338,7 @@ namespace pSample->GetSampleDuration(&duration); if (m_prerolling) { - if (SUCCEEDED(hr) && time >= m_prerollTargetTime) { + if (SUCCEEDED(hr) && ((time - m_prerollTargetTime) * m_rate) >= 0) { IMFMediaBuffer *pBuffer = NULL; hr = pSample->ConvertToContiguousBuffer(&pBuffer); if (SUCCEEDED(hr)) { @@ -1352,7 +1355,7 @@ namespace } else { bool requestSample = true; // If the time stamp is too early, just discard this sample. - if (SUCCEEDED(hr) && time >= m_startTime) { + if (SUCCEEDED(hr) && ((time - m_startTime) * m_rate) >= 0) { IMFMediaBuffer *pBuffer = NULL; hr = pSample->ConvertToContiguousBuffer(&pBuffer); if (SUCCEEDED(hr)) { @@ -1400,9 +1403,8 @@ namespace timeOK = false; } while (!m_bufferCache.isEmpty()) { - SampleBuffer sb = m_bufferCache.first(); - m_bufferCache.pop_front(); - if (timeOK && currentTime > sb.m_time) { + SampleBuffer sb = m_bufferCache.takeFirst(); + if (timeOK && ((sb.m_time - currentTime) * m_rate) < 0) { sb.m_buffer->Release(); #ifdef DEBUG_MEDIAFOUNDATION qDebug() << "currentPresentTime =" << float(currentTime / 10000) * 0.001f << " and sampleTime is" << float(sb.m_time / 10000) * 0.001f; @@ -1454,7 +1456,11 @@ namespace // 2. While paused, the sink accepts samples but does not process them. }; - class MediaSink : public IMFFinalizableMediaSink, public IMFClockStateSink, public IMFMediaSinkPreroll + class MediaSink : public IMFFinalizableMediaSink, + public IMFClockStateSink, + public IMFMediaSinkPreroll, + public IMFGetService, + public IMFRateSupport { public: MediaSink(MFVideoRendererControl *rendererControl) @@ -1526,10 +1532,14 @@ namespace return E_POINTER; if (riid == IID_IMFMediaSink) { *ppvObject = static_cast(this); + } else if (riid == IID_IMFGetService) { + *ppvObject = static_cast(this); } else if (riid == IID_IMFMediaSinkPreroll) { *ppvObject = static_cast(this); } else if (riid == IID_IMFClockStateSink) { *ppvObject = static_cast(this); + } else if (riid == IID_IMFRateSupport) { + *ppvObject = static_cast(this); } else if (riid == IID_IUnknown) { *ppvObject = static_cast(static_cast(this)); } else { @@ -1554,7 +1564,19 @@ namespace return cRef; } + // IMFGetService methods + STDMETHODIMP GetService(const GUID &guidService, + const IID &riid, + LPVOID *ppvObject) + { + if (!ppvObject) + return E_POINTER; + + if (guidService != MF_RATE_CONTROL_SERVICE) + return MF_E_UNSUPPORTED_SERVICE; + return QueryInterface(riid, ppvObject); + } //IMFMediaSinkPreroll STDMETHODIMP NotifyPreroll(MFTIME hnsUpcomingStartTime) @@ -1749,6 +1771,68 @@ namespace return m_stream->setRate(flRate); } + // IMFRateSupport methods + STDMETHODIMP GetFastestRate(MFRATE_DIRECTION eDirection, + BOOL fThin, + float *pflRate) + { + if (!pflRate) + return E_POINTER; + + *pflRate = (fThin ? 8.f : 2.0f) * (eDirection == MFRATE_FORWARD ? 1 : -1) ; + + return S_OK; + } + + STDMETHODIMP GetSlowestRate(MFRATE_DIRECTION eDirection, + BOOL fThin, + float *pflRate) + { + Q_UNUSED(eDirection); + Q_UNUSED(fThin); + + if (!pflRate) + return E_POINTER; + + // we support any rate + *pflRate = 0.f; + + return S_OK; + } + + STDMETHODIMP IsRateSupported(BOOL fThin, + float flRate, + float *pflNearestSupportedRate) + { + HRESULT hr = S_OK; + + if (!qFuzzyIsNull(flRate)) { + MFRATE_DIRECTION direction = flRate > 0.f ? MFRATE_FORWARD + : MFRATE_REVERSE; + + float fastestRate = 0.f; + float slowestRate = 0.f; + GetFastestRate(direction, fThin, &fastestRate); + GetSlowestRate(direction, fThin, &slowestRate); + + if (direction == MFRATE_REVERSE) + qSwap(fastestRate, slowestRate); + + if (flRate < slowestRate || flRate > fastestRate) { + hr = MF_E_UNSUPPORTED_RATE; + if (pflNearestSupportedRate) { + *pflNearestSupportedRate = qBound(slowestRate, + flRate, + fastestRate); + } + } + } else if (pflNearestSupportedRate) { + *pflNearestSupportedRate = flRate; + } + + return hr; + } + private: long m_cRef; QMutex m_mutex; @@ -2201,13 +2285,13 @@ void MFVideoRendererControl::customEvent(QEvent *event) MFTIME targetTime = static_cast(event)->targetTime(); MFTIME currentTime = static_cast(m_currentActivate)->getTime(); float playRate = static_cast(m_currentActivate)->getPlayRate(); - if (!qFuzzyIsNull(playRate)) { - // If the scheduled frame is too late or too much in advance, skip it - const int diff = (targetTime - currentTime) / 10000; - if (diff < 0 || diff > 500) + if (!qFuzzyIsNull(playRate) && targetTime != currentTime) { + // If the scheduled frame is too late, skip it + const int interval = ((targetTime - currentTime) / 10000) / playRate; + if (interval < 0) static_cast(m_currentActivate)->clearScheduledFrame(); else - QTimer::singleShot(diff / playRate, this, SLOT(present())); + QTimer::singleShot(interval, this, SLOT(present())); } else { present(); } -- cgit v1.2.3 From 47d2ed915eebff7016fd99bec9c3d6187240edd6 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Mon, 7 Apr 2014 14:33:32 +0200 Subject: WMF: don't return undefined value in Release() function. The function was returning a member variable after the object was deleted. Return a local copy instead. Change-Id: I077e7e1c184ed0cfd4899a80c9147a2939c93cd7 Reviewed-by: Christian Stromme --- src/plugins/wmf/mfactivate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/wmf/mfactivate.cpp b/src/plugins/wmf/mfactivate.cpp index cf64adc80..faa678ddf 100644 --- a/src/plugins/wmf/mfactivate.cpp +++ b/src/plugins/wmf/mfactivate.cpp @@ -85,5 +85,5 @@ ULONG MFAbstractActivate::Release(void) ULONG cRef = InterlockedDecrement(&m_cRef); if (cRef == 0) delete this; - return m_cRef; + return cRef; } -- cgit v1.2.3 From ebf9528eae8c400c9c1e64a6bca7a8d3613214a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Tue, 1 Apr 2014 19:04:12 +0200 Subject: Android: Fix MediaRecorder wrapper The QJNIObject was never intended to be used as a base class. Change-Id: I8311f909a37aeae6040eba4471b379cfc732297b Reviewed-by: Yoann Lopes --- .../android/src/wrappers/jmediarecorder.cpp | 46 +++++++++++----------- src/plugins/android/src/wrappers/jmediarecorder.h | 3 +- 2 files changed, 25 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/plugins/android/src/wrappers/jmediarecorder.cpp b/src/plugins/android/src/wrappers/jmediarecorder.cpp index 2c3eaeab7..85267286c 100644 --- a/src/plugins/android/src/wrappers/jmediarecorder.cpp +++ b/src/plugins/android/src/wrappers/jmediarecorder.cpp @@ -66,10 +66,10 @@ static void notifyInfo(JNIEnv* , jobject, jlong id, jint what, jint extra) JMediaRecorder::JMediaRecorder() : QObject() - , QJNIObjectPrivate(g_qtMediaRecorderClass, "(J)V", reinterpret_cast(this)) , m_id(reinterpret_cast(this)) { - if (isValid()) + m_mediaRecorder = QJNIObjectPrivate(g_qtMediaRecorderClass, "(J)V", m_id); + if (m_mediaRecorder.isValid()) g_objectMap.insert(m_id, this); } @@ -80,13 +80,13 @@ JMediaRecorder::~JMediaRecorder() void JMediaRecorder::release() { - callMethod("release"); + m_mediaRecorder.callMethod("release"); } bool JMediaRecorder::prepare() { QJNIEnvironmentPrivate env; - callMethod("prepare"); + m_mediaRecorder.callMethod("prepare"); if (env->ExceptionCheck()) { #ifdef QT_DEBUG env->ExceptionDescribe(); @@ -99,13 +99,13 @@ bool JMediaRecorder::prepare() void JMediaRecorder::reset() { - callMethod("reset"); + m_mediaRecorder.callMethod("reset"); } bool JMediaRecorder::start() { QJNIEnvironmentPrivate env; - callMethod("start"); + m_mediaRecorder.callMethod("start"); if (env->ExceptionCheck()) { #ifdef QT_DEBUG env->ExceptionDescribe(); @@ -119,7 +119,7 @@ bool JMediaRecorder::start() void JMediaRecorder::stop() { QJNIEnvironmentPrivate env; - callMethod("stop"); + m_mediaRecorder.callMethod("stop"); if (env->ExceptionCheck()) { #ifdef QT_DEBUG env->ExceptionDescribe(); @@ -130,13 +130,13 @@ void JMediaRecorder::stop() void JMediaRecorder::setAudioChannels(int numChannels) { - callMethod("setAudioChannels", "(I)V", numChannels); + m_mediaRecorder.callMethod("setAudioChannels", "(I)V", numChannels); } void JMediaRecorder::setAudioEncoder(AudioEncoder encoder) { QJNIEnvironmentPrivate env; - callMethod("setAudioEncoder", "(I)V", int(encoder)); + m_mediaRecorder.callMethod("setAudioEncoder", "(I)V", int(encoder)); if (env->ExceptionCheck()) { #ifdef QT_DEBUG env->ExceptionDescribe(); @@ -147,18 +147,18 @@ void JMediaRecorder::setAudioEncoder(AudioEncoder encoder) void JMediaRecorder::setAudioEncodingBitRate(int bitRate) { - callMethod("setAudioEncodingBitRate", "(I)V", bitRate); + m_mediaRecorder.callMethod("setAudioEncodingBitRate", "(I)V", bitRate); } void JMediaRecorder::setAudioSamplingRate(int samplingRate) { - callMethod("setAudioSamplingRate", "(I)V", samplingRate); + m_mediaRecorder.callMethod("setAudioSamplingRate", "(I)V", samplingRate); } void JMediaRecorder::setAudioSource(AudioSource source) { QJNIEnvironmentPrivate env; - callMethod("setAudioSource", "(I)V", int(source)); + m_mediaRecorder.callMethod("setAudioSource", "(I)V", int(source)); if (env->ExceptionCheck()) { #ifdef QT_DEBUG env->ExceptionDescribe(); @@ -170,13 +170,13 @@ void JMediaRecorder::setAudioSource(AudioSource source) void JMediaRecorder::setCamera(JCamera *camera) { QJNIObjectPrivate cam = camera->getCameraObject(); - callMethod("setCamera", "(Landroid/hardware/Camera;)V", cam.object()); + m_mediaRecorder.callMethod("setCamera", "(Landroid/hardware/Camera;)V", cam.object()); } void JMediaRecorder::setVideoEncoder(VideoEncoder encoder) { QJNIEnvironmentPrivate env; - callMethod("setVideoEncoder", "(I)V", int(encoder)); + m_mediaRecorder.callMethod("setVideoEncoder", "(I)V", int(encoder)); if (env->ExceptionCheck()) { #ifdef QT_DEBUG env->ExceptionDescribe(); @@ -187,13 +187,13 @@ void JMediaRecorder::setVideoEncoder(VideoEncoder encoder) void JMediaRecorder::setVideoEncodingBitRate(int bitRate) { - callMethod("setVideoEncodingBitRate", "(I)V", bitRate); + m_mediaRecorder.callMethod("setVideoEncodingBitRate", "(I)V", bitRate); } void JMediaRecorder::setVideoFrameRate(int rate) { QJNIEnvironmentPrivate env; - callMethod("setVideoFrameRate", "(I)V", rate); + m_mediaRecorder.callMethod("setVideoFrameRate", "(I)V", rate); if (env->ExceptionCheck()) { #ifdef QT_DEBUG env->ExceptionDescribe(); @@ -205,7 +205,7 @@ void JMediaRecorder::setVideoFrameRate(int rate) void JMediaRecorder::setVideoSize(const QSize &size) { QJNIEnvironmentPrivate env; - callMethod("setVideoSize", "(II)V", size.width(), size.height()); + m_mediaRecorder.callMethod("setVideoSize", "(II)V", size.width(), size.height()); if (env->ExceptionCheck()) { #ifdef QT_DEBUG env->ExceptionDescribe(); @@ -217,7 +217,7 @@ void JMediaRecorder::setVideoSize(const QSize &size) void JMediaRecorder::setVideoSource(VideoSource source) { QJNIEnvironmentPrivate env; - callMethod("setVideoSource", "(I)V", int(source)); + m_mediaRecorder.callMethod("setVideoSource", "(I)V", int(source)); if (env->ExceptionCheck()) { #ifdef QT_DEBUG env->ExceptionDescribe(); @@ -229,7 +229,7 @@ void JMediaRecorder::setVideoSource(VideoSource source) void JMediaRecorder::setOrientationHint(int degrees) { QJNIEnvironmentPrivate env; - callMethod("setOrientationHint", "(I)V", degrees); + m_mediaRecorder.callMethod("setOrientationHint", "(I)V", degrees); if (env->ExceptionCheck()) { #ifdef QT_DEBUG env->ExceptionDescribe(); @@ -241,7 +241,7 @@ void JMediaRecorder::setOrientationHint(int degrees) void JMediaRecorder::setOutputFormat(OutputFormat format) { QJNIEnvironmentPrivate env; - callMethod("setOutputFormat", "(I)V", int(format)); + m_mediaRecorder.callMethod("setOutputFormat", "(I)V", int(format)); if (env->ExceptionCheck()) { #ifdef QT_DEBUG env->ExceptionDescribe(); @@ -253,9 +253,9 @@ void JMediaRecorder::setOutputFormat(OutputFormat format) void JMediaRecorder::setOutputFile(const QString &path) { QJNIEnvironmentPrivate env; - callMethod("setOutputFile", - "(Ljava/lang/String;)V", - QJNIObjectPrivate::fromString(path).object()); + m_mediaRecorder.callMethod("setOutputFile", + "(Ljava/lang/String;)V", + QJNIObjectPrivate::fromString(path).object()); if (env->ExceptionCheck()) { #ifdef QT_DEBUG env->ExceptionDescribe(); diff --git a/src/plugins/android/src/wrappers/jmediarecorder.h b/src/plugins/android/src/wrappers/jmediarecorder.h index 2bdb06b9f..3a83e7e16 100644 --- a/src/plugins/android/src/wrappers/jmediarecorder.h +++ b/src/plugins/android/src/wrappers/jmediarecorder.h @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE class JCamera; -class JMediaRecorder : public QObject, public QJNIObjectPrivate +class JMediaRecorder : public QObject { Q_OBJECT public: @@ -127,6 +127,7 @@ Q_SIGNALS: private: jlong m_id; + QJNIObjectPrivate m_mediaRecorder; }; QT_END_NAMESPACE -- cgit v1.2.3 From a241874a7f750039d68925d452abf7709c51fed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Wed, 2 Apr 2014 18:57:16 +0200 Subject: Android: Remove inheritance to QJNIObject in the Camera wrapper The QJNIObject was never intended to be used as a base class. Change-Id: I4986aeaebecd6e4136fed311e69368e20da4d060 Reviewed-by: Yoann Lopes --- src/plugins/android/src/wrappers/jcamera.cpp | 47 +++++++++++++++------------- 1 file changed, 25 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/plugins/android/src/wrappers/jcamera.cpp b/src/plugins/android/src/wrappers/jcamera.cpp index 50a65a779..874d12cdf 100644 --- a/src/plugins/android/src/wrappers/jcamera.cpp +++ b/src/plugins/android/src/wrappers/jcamera.cpp @@ -145,7 +145,7 @@ private: QJNIObjectPrivate lastCamera; }; -class JCameraWorker : public QObject, public QJNIObjectPrivate +class JCameraWorker : public QObject { Q_OBJECT friend class JCamera; @@ -236,6 +236,7 @@ class JCameraWorker : public QObject, public QJNIObjectPrivate QThread *m_workerThread; QMutex m_parametersMutex; + QJNIObjectPrivate m_camera; Q_SIGNALS: void previewSizeChanged(); @@ -269,7 +270,7 @@ JCamera::JCamera(int cameraId, jobject cam, QThread *workerThread) JCamera::~JCamera() { - if (d->isValid()) { + if (d->m_camera.isValid()) { g_objectMapMutex.lock(); g_objectMap.remove(d->m_cameraId); g_objectMapMutex.unlock(); @@ -595,7 +596,7 @@ void JCamera::fetchLastPreviewFrame() QJNIObjectPrivate JCamera::getCameraObject() { - return d->getObjectField("m_camera", "Landroid/hardware/Camera;"); + return d->m_camera.getObjectField("m_camera", "Landroid/hardware/Camera;"); } void JCamera::startPreview() @@ -613,29 +614,29 @@ void JCamera::stopPreview() JCameraWorker::JCameraWorker(JCamera *camera, int cameraId, jobject cam, QThread *workerThread) : QObject(0) - , QJNIObjectPrivate(cam) , m_cameraId(cameraId) , m_rotation(0) , m_hasAPI14(false) , m_parametersMutex(QMutex::Recursive) + , m_camera(cam) { q = camera; m_workerThread = workerThread; moveToThread(m_workerThread); - if (isValid()) { + if (m_camera.isValid()) { g_objectMapMutex.lock(); g_objectMap.insert(cameraId, q); g_objectMapMutex.unlock(); m_info = QJNIObjectPrivate("android/hardware/Camera$CameraInfo"); - callStaticMethod("android/hardware/Camera", - "getCameraInfo", - "(ILandroid/hardware/Camera$CameraInfo;)V", - cameraId, m_info.object()); + m_camera.callStaticMethod("android/hardware/Camera", + "getCameraInfo", + "(ILandroid/hardware/Camera$CameraInfo;)V", + cameraId, m_info.object()); - QJNIObjectPrivate params = callObjectMethod("getParameters", - "()Landroid/hardware/Camera$Parameters;"); + QJNIObjectPrivate params = m_camera.callObjectMethod("getParameters", + "()Landroid/hardware/Camera$Parameters;"); m_parameters = QJNIObjectPrivate(params); // Check if API 14 is available @@ -668,7 +669,7 @@ void JCameraWorker::release() m_parametersMutex.lock(); m_parameters = QJNIObjectPrivate(); m_parametersMutex.unlock(); - callMethod("release"); + m_camera.callMethod("release"); } JCamera::CameraFacing JCameraWorker::getFacing() @@ -752,7 +753,9 @@ void JCameraWorker::updatePreviewSize() void JCameraWorker::setPreviewTexture(void *surfaceTexture) { - callMethod("setPreviewTexture", "(Landroid/graphics/SurfaceTexture;)V", static_cast(surfaceTexture)); + m_camera.callMethod("setPreviewTexture", + "(Landroid/graphics/SurfaceTexture;)V", + static_cast(surfaceTexture)); } bool JCameraWorker::isZoomSupported() @@ -940,7 +943,7 @@ void JCameraWorker::setFocusAreas(const QList &areas) void JCameraWorker::autoFocus() { - callMethod("autoFocus"); + m_camera.callMethod("autoFocus"); emit autoFocusStarted(); } @@ -1184,15 +1187,15 @@ void JCameraWorker::stopPreview() void JCameraWorker::fetchEachFrame(bool fetch) { - callMethod("fetchEachFrame", "(Z)V", fetch); + m_camera.callMethod("fetchEachFrame", "(Z)V", fetch); } void JCameraWorker::fetchLastPreviewFrame() { QJNIEnvironmentPrivate env; - QJNIObjectPrivate dataObj = callObjectMethod("lockAndFetchPreviewBuffer", "()[B"); + QJNIObjectPrivate dataObj = m_camera.callObjectMethod("lockAndFetchPreviewBuffer", "()[B"); if (!dataObj.object()) { - callMethod("unlockPreviewBuffer"); + m_camera.callMethod("unlockPreviewBuffer"); return; } jbyteArray data = static_cast(dataObj.object()); @@ -1200,16 +1203,16 @@ void JCameraWorker::fetchLastPreviewFrame() int arrayLength = env->GetArrayLength(data); bytes.resize(arrayLength); env->GetByteArrayRegion(data, 0, arrayLength, (jbyte*)bytes.data()); - callMethod("unlockPreviewBuffer"); + m_camera.callMethod("unlockPreviewBuffer"); emit previewFetched(bytes); } void JCameraWorker::applyParameters() { - callMethod("setParameters", - "(Landroid/hardware/Camera$Parameters;)V", - m_parameters.object()); + m_camera.callMethod("setParameters", + "(Landroid/hardware/Camera$Parameters;)V", + m_parameters.object()); } QStringList JCameraWorker::callParametersStringListMethod(const QByteArray &methodName) @@ -1239,7 +1242,7 @@ QStringList JCameraWorker::callParametersStringListMethod(const QByteArray &meth void JCameraWorker::callVoidMethod(const QByteArray &methodName) { - callMethod(methodName.constData()); + m_camera.callMethod(methodName.constData()); } -- cgit v1.2.3 From a8854cc5490fee2093093bc4486930bafe2a936c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Thu, 3 Apr 2014 11:17:30 +0200 Subject: Android: Use androidSdkVersion() to get the API level. Change-Id: Idc0b09ab2dc5d93e8da8dab3bd0e99e27fbc57e1 Reviewed-by: Yoann Lopes --- src/plugins/android/src/wrappers/jcamera.cpp | 70 ++++++++++++++++------------ 1 file changed, 39 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/plugins/android/src/wrappers/jcamera.cpp b/src/plugins/android/src/wrappers/jcamera.cpp index 874d12cdf..b0e9f89f3 100644 --- a/src/plugins/android/src/wrappers/jcamera.cpp +++ b/src/plugins/android/src/wrappers/jcamera.cpp @@ -47,6 +47,7 @@ #include "qandroidmultimediautils.h" #include #include +#include QT_BEGIN_NAMESPACE @@ -230,8 +231,6 @@ class JCameraWorker : public QObject QSize m_previewSize; int m_rotation; - bool m_hasAPI14; - JCamera *q; QThread *m_workerThread; @@ -616,7 +615,6 @@ JCameraWorker::JCameraWorker(JCamera *camera, int cameraId, jobject cam, QThread : QObject(0) , m_cameraId(cameraId) , m_rotation(0) - , m_hasAPI14(false) , m_parametersMutex(QMutex::Recursive) , m_camera(cam) { @@ -638,23 +636,6 @@ JCameraWorker::JCameraWorker(JCamera *camera, int cameraId, jobject cam, QThread QJNIObjectPrivate params = m_camera.callObjectMethod("getParameters", "()Landroid/hardware/Camera$Parameters;"); m_parameters = QJNIObjectPrivate(params); - - // Check if API 14 is available - QJNIEnvironmentPrivate env; - jclass clazz = env->FindClass("android/hardware/Camera"); - if (env->ExceptionCheck()) { - clazz = 0; - env->ExceptionClear(); - } - if (clazz) { - // startFaceDetection() was added in API 14 - jmethodID id = env->GetMethodID(clazz, "startFaceDetection", "()V"); - if (env->ExceptionCheck()) { - id = 0; - env->ExceptionClear(); - } - m_hasAPI14 = bool(id); - } } } @@ -881,9 +862,12 @@ void JCameraWorker::setFocusMode(const QString &value) int JCameraWorker::getMaxNumFocusAreas() { + if (QtAndroidPrivate::androidSdkVersion() < 14) + return 0; + QMutexLocker parametersLocker(&m_parametersMutex); - if (!m_hasAPI14 || !m_parameters.isValid()) + if (!m_parameters.isValid()) return 0; return m_parameters.callMethod("getMaxNumFocusAreas"); @@ -891,11 +875,14 @@ int JCameraWorker::getMaxNumFocusAreas() QList JCameraWorker::getFocusAreas() { - QMutexLocker parametersLocker(&m_parametersMutex); - QList areas; - if (m_hasAPI14 && m_parameters.isValid()) { + if (QtAndroidPrivate::androidSdkVersion() < 14) + return areas; + + QMutexLocker parametersLocker(&m_parametersMutex); + + if (m_parameters.isValid()) { QJNIObjectPrivate list = m_parameters.callObjectMethod("getFocusAreas", "()Ljava/util/List;"); @@ -916,9 +903,12 @@ QList JCameraWorker::getFocusAreas() void JCameraWorker::setFocusAreas(const QList &areas) { + if (QtAndroidPrivate::androidSdkVersion() < 14) + return; + QMutexLocker parametersLocker(&m_parametersMutex); - if (!m_hasAPI14 || !m_parameters.isValid()) + if (!m_parameters.isValid()) return; QJNIObjectPrivate list; @@ -949,9 +939,12 @@ void JCameraWorker::autoFocus() bool JCameraWorker::isAutoExposureLockSupported() { + if (QtAndroidPrivate::androidSdkVersion() < 14) + return false; + QMutexLocker parametersLocker(&m_parametersMutex); - if (!m_hasAPI14 || !m_parameters.isValid()) + if (!m_parameters.isValid()) return false; return m_parameters.callMethod("isAutoExposureLockSupported"); @@ -959,9 +952,12 @@ bool JCameraWorker::isAutoExposureLockSupported() bool JCameraWorker::getAutoExposureLock() { + if (QtAndroidPrivate::androidSdkVersion() < 14) + return false; + QMutexLocker parametersLocker(&m_parametersMutex); - if (!m_hasAPI14 || !m_parameters.isValid()) + if (!m_parameters.isValid()) return false; return m_parameters.callMethod("getAutoExposureLock"); @@ -969,9 +965,12 @@ bool JCameraWorker::getAutoExposureLock() void JCameraWorker::setAutoExposureLock(bool toggle) { + if (QtAndroidPrivate::androidSdkVersion() < 14) + return; + QMutexLocker parametersLocker(&m_parametersMutex); - if (!m_hasAPI14 || !m_parameters.isValid()) + if (!m_parameters.isValid()) return; m_parameters.callMethod("setAutoExposureLock", "(Z)V", toggle); @@ -980,9 +979,12 @@ void JCameraWorker::setAutoExposureLock(bool toggle) bool JCameraWorker::isAutoWhiteBalanceLockSupported() { + if (QtAndroidPrivate::androidSdkVersion() < 14) + return false; + QMutexLocker parametersLocker(&m_parametersMutex); - if (!m_hasAPI14 || !m_parameters.isValid()) + if (!m_parameters.isValid()) return false; return m_parameters.callMethod("isAutoWhiteBalanceLockSupported"); @@ -990,9 +992,12 @@ bool JCameraWorker::isAutoWhiteBalanceLockSupported() bool JCameraWorker::getAutoWhiteBalanceLock() { + if (QtAndroidPrivate::androidSdkVersion() < 14) + return false; + QMutexLocker parametersLocker(&m_parametersMutex); - if (!m_hasAPI14 || !m_parameters.isValid()) + if (!m_parameters.isValid()) return false; return m_parameters.callMethod("getAutoWhiteBalanceLock"); @@ -1000,9 +1005,12 @@ bool JCameraWorker::getAutoWhiteBalanceLock() void JCameraWorker::setAutoWhiteBalanceLock(bool toggle) { + if (QtAndroidPrivate::androidSdkVersion() < 14) + return; + QMutexLocker parametersLocker(&m_parametersMutex); - if (!m_hasAPI14 || !m_parameters.isValid()) + if (!m_parameters.isValid()) return; m_parameters.callMethod("setAutoWhiteBalanceLock", "(Z)V", toggle); -- cgit v1.2.3 From 6fb0d978389f3f578ce43ddeb6a1bad624df4154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Mon, 7 Apr 2014 15:09:00 +0200 Subject: Android: Fix QtMediaRecorder Don't extend the MediaRecorder class as this causes ART to fail when it doesn't find the postEventFromNative() function. Task-number: QTBUG-38166 Change-Id: Ia38ce4558a2cc95a9b4cd05b9f926d41e53fdc0d Reviewed-by: Yoann Lopes --- src/plugins/android/jar/jar.pri | 2 +- .../qt5/android/multimedia/QtMediaRecorder.java | 72 ---------------------- .../multimedia/QtMediaRecorderListener.java | 69 +++++++++++++++++++++ .../android/src/wrappers/jmediarecorder.cpp | 20 ++++-- 4 files changed, 84 insertions(+), 79 deletions(-) delete mode 100644 src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtMediaRecorder.java create mode 100644 src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtMediaRecorderListener.java (limited to 'src') diff --git a/src/plugins/android/jar/jar.pri b/src/plugins/android/jar/jar.pri index e56e3d966..d8bc59a72 100644 --- a/src/plugins/android/jar/jar.pri +++ b/src/plugins/android/jar/jar.pri @@ -10,7 +10,7 @@ JAVASOURCES += $$PWD/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlay $$PWD/src/org/qtproject/qt5/android/multimedia/QtSurfaceTextureListener.java \ $$PWD/src/org/qtproject/qt5/android/multimedia/QtSurfaceTextureHolder.java \ $$PWD/src/org/qtproject/qt5/android/multimedia/QtMultimediaUtils.java \ - $$PWD/src/org/qtproject/qt5/android/multimedia/QtMediaRecorder.java + $$PWD/src/org/qtproject/qt5/android/multimedia/QtMediaRecorderListener.java # install target.path = $$[QT_INSTALL_PREFIX]/jar diff --git a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtMediaRecorder.java b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtMediaRecorder.java deleted file mode 100644 index d76cd2221..000000000 --- a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtMediaRecorder.java +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** - ** - ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). - ** Contact: http://www.qt-project.org/legal - ** - ** This file is part of the QtMultimedia module of the Qt Toolkit. - ** - ** $QT_BEGIN_LICENSE:LGPL$ - ** 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 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 2.1 requirements - ** will be met: 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. - ** - ** GNU General Public License Usage - ** Alternatively, this file may be used under the terms of the GNU - ** General Public License version 3.0 as published by the Free Software - ** Foundation and appearing in the file LICENSE.GPL included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU General Public License version 3.0 requirements will be - ** met: http://www.gnu.org/copyleft/gpl.html. - ** - ** - ** $QT_END_LICENSE$ - ** - ****************************************************************************/ - -package org.qtproject.qt5.android.multimedia; - -import android.media.MediaRecorder; - -public class QtMediaRecorder extends MediaRecorder implements MediaRecorder.OnErrorListener, MediaRecorder.OnInfoListener -{ - private long m_id = -1; - - public QtMediaRecorder(long id) - { - super(); - m_id = id; - setOnErrorListener(this); - setOnInfoListener(this); - } - - @Override - public void onError(MediaRecorder mr, int what, int extra) - { - notifyError(m_id, what, extra); - } - - @Override - public void onInfo(MediaRecorder mr, int what, int extra) - { - notifyInfo(m_id, what, extra); - } - - private static native void notifyError(long id, int what, int extra); - private static native void notifyInfo(long id, int what, int extra); -} diff --git a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtMediaRecorderListener.java b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtMediaRecorderListener.java new file mode 100644 index 000000000..5c8557e88 --- /dev/null +++ b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtMediaRecorderListener.java @@ -0,0 +1,69 @@ +/**************************************************************************** + ** + ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/legal + ** + ** This file is part of the QtMultimedia module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** 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 as published by the Free Software + ** Foundation and appearing in the file LICENSE.LGPL included in the + ** packaging of this file. Please review the following information to + ** ensure the GNU Lesser General Public License version 2.1 requirements + ** will be met: 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. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 3.0 as published by the Free Software + ** Foundation and appearing in the file LICENSE.GPL included in the + ** packaging of this file. Please review the following information to + ** ensure the GNU General Public License version 3.0 requirements will be + ** met: http://www.gnu.org/copyleft/gpl.html. + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +package org.qtproject.qt5.android.multimedia; + +import android.media.MediaRecorder; + +public class QtMediaRecorderListener implements MediaRecorder.OnErrorListener, MediaRecorder.OnInfoListener +{ + private long m_id = -1; + + public QtMediaRecorderListener(long id) + { + m_id = id; + } + + @Override + public void onError(MediaRecorder mr, int what, int extra) + { + notifyError(m_id, what, extra); + } + + @Override + public void onInfo(MediaRecorder mr, int what, int extra) + { + notifyInfo(m_id, what, extra); + } + + private static native void notifyError(long id, int what, int extra); + private static native void notifyInfo(long id, int what, int extra); +} diff --git a/src/plugins/android/src/wrappers/jmediarecorder.cpp b/src/plugins/android/src/wrappers/jmediarecorder.cpp index 85267286c..675bc5dce 100644 --- a/src/plugins/android/src/wrappers/jmediarecorder.cpp +++ b/src/plugins/android/src/wrappers/jmediarecorder.cpp @@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE -static jclass g_qtMediaRecorderClass = 0; +static jclass g_qtMediaRecorderListenerClass = 0; static QMap g_objectMap; static void notifyError(JNIEnv* , jobject, jlong id, jint what, jint extra) @@ -68,9 +68,17 @@ JMediaRecorder::JMediaRecorder() : QObject() , m_id(reinterpret_cast(this)) { - m_mediaRecorder = QJNIObjectPrivate(g_qtMediaRecorderClass, "(J)V", m_id); - if (m_mediaRecorder.isValid()) + m_mediaRecorder = QJNIObjectPrivate("android/media/MediaRecorder"); + if (m_mediaRecorder.isValid()) { + QJNIObjectPrivate listener(g_qtMediaRecorderListenerClass, "(J)V", m_id); + m_mediaRecorder.callMethod("setOnErrorListener", + "(Landroid/media/MediaRecorder$OnErrorListener;)V", + listener.object()); + m_mediaRecorder.callMethod("setOnInfoListener", + "(Landroid/media/MediaRecorder$OnErrorListener;)V", + listener.object()); g_objectMap.insert(m_id, this); + } } JMediaRecorder::~JMediaRecorder() @@ -271,13 +279,13 @@ static JNINativeMethod methods[] = { bool JMediaRecorder::initJNI(JNIEnv *env) { - jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtMediaRecorder"); + jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtMediaRecorderListener"); if (env->ExceptionCheck()) env->ExceptionClear(); if (clazz) { - g_qtMediaRecorderClass = static_cast(env->NewGlobalRef(clazz)); - if (env->RegisterNatives(g_qtMediaRecorderClass, + g_qtMediaRecorderListenerClass = static_cast(env->NewGlobalRef(clazz)); + if (env->RegisterNatives(g_qtMediaRecorderListenerClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) { return false; -- cgit v1.2.3 From 08216062609dea47e78046dc0eeb12bc1ea8e49a Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Fri, 4 Apr 2014 15:09:03 +0200 Subject: WMF: more reliable video seeking. When seeking, the presentation clock can enter an undefined state until it is started again from the new position. Wait for the clock to be restarted before scheduling the prerolled frames, otherwise these frames might get a wrong presentation time. Change-Id: I02cb3338239775b7ef5d206ec5aa1b26719ac978 Reviewed-by: Christian Stromme --- src/plugins/wmf/player/mfvideorenderercontrol.cpp | 25 ++++++++++++++--------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/plugins/wmf/player/mfvideorenderercontrol.cpp b/src/plugins/wmf/player/mfvideorenderercontrol.cpp index d4d341a45..040682965 100644 --- a/src/plugins/wmf/player/mfvideorenderercontrol.cpp +++ b/src/plugins/wmf/player/mfvideorenderercontrol.cpp @@ -655,11 +655,6 @@ namespace m_presentationClock = NULL; } - if (m_scheduledBuffer) { - m_scheduledBuffer->Release(); - m_scheduledBuffer = NULL; - } - clearMediaTypes(); clearSampleQueue(); clearBufferCache(); @@ -677,6 +672,7 @@ namespace QMutexLocker locker(&m_mutex); HRESULT hr = validateOperation(OpPreroll); if (SUCCEEDED(hr)) { + m_state = State_Prerolling; m_prerollTargetTime = hnsUpcomingStartTime; hr = queueAsyncOperation(OpPreroll); } @@ -864,6 +860,7 @@ namespace if (m_scheduledBuffer) { m_scheduledBuffer->Release(); m_scheduledBuffer = NULL; + schedulePresentation(true); } } @@ -936,6 +933,7 @@ namespace { State_TypeNotSet = 0, // No media type is set State_Ready, // Media type is set, Start has never been called. + State_Prerolling, State_Started, State_Paused, State_Stopped, @@ -1124,6 +1122,9 @@ namespace break; } } + + if (m_state == State_Started) + schedulePresentation(true); case OpRestart: endPreroll(S_FALSE); if (SUCCEEDED(hr)) { @@ -1142,10 +1143,7 @@ namespace case OpStop: // Drop samples from queue. hr = processSamplesFromQueue(DropSamples); - if (m_scheduledBuffer) { - m_scheduledBuffer->Release(); - m_scheduledBuffer = NULL; - } + clearBufferCache(); // Send the event even if the previous call failed. hr = queueEvent(MEStreamSinkStopped, GUID_NULL, hr, NULL); if (m_surface->isActive()) { @@ -1388,11 +1386,16 @@ namespace foreach (SampleBuffer sb, m_bufferCache) sb.m_buffer->Release(); m_bufferCache.clear(); + + if (m_scheduledBuffer) { + m_scheduledBuffer->Release(); + m_scheduledBuffer = NULL; + } } void schedulePresentation(bool requestSample) { - if (m_state == State_Paused) + if (m_state == State_Paused || m_state == State_Prerolling) return; if (!m_scheduledBuffer) { //get time from presentation time @@ -1441,6 +1444,8 @@ namespace /* Ready */ TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, + /* Prerolling */ TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, + /* Start */ FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, /* Pause */ FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, -- cgit v1.2.3 From 464ed66119ba065a8604ceed9963b2626a9ca586 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Fri, 21 Mar 2014 19:10:23 +0100 Subject: GStreamer: correctly get metadata from live sources. For some unknown reason, "iradio-mode" was set to false on the source element, which was preventing new metadata to be received when playing live streams. Task-number: QTBUG-37640 Change-Id: Ib90297e81e26a99c3dfc753bdcd5cbd1ee2f6764 Reviewed-by: Christian Stromme --- .../mediaplayer/qgstreamermetadataprovider.cpp | 19 ++++++------------- .../gstreamer/mediaplayer/qgstreamerplayersession.cpp | 15 +++++---------- 2 files changed, 11 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp index 22f203665..fa837d3f4 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp @@ -162,25 +162,18 @@ void QGstreamerMetaDataProvider::updateTags() { QVariantMap oldTags = m_tags; m_tags.clear(); - - QSet allTags = QSet::fromList(m_tags.keys()); + bool changed = false; QMapIterator i(m_session->tags()); while (i.hasNext()) { i.next(); //use gstreamer native keys for elements not in m_keysMap QString key = m_keysMap.value(i.key(), i.key()); - m_tags[key] = i.value(); - allTags.insert(key); - } - - bool changed = false; - foreach (const QString &key, allTags) { - const QVariant value = m_tags.value(key); - if (value != oldTags.value(key)) { - changed = true; - emit metaDataChanged(key, value); - } + m_tags.insert(key, i.value()); + if (i.value() != oldTags.value(key)) { + changed = true; + emit metaDataChanged(key, i.value()); + } } if (changed) diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp index f7522a5f7..27446e07d 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp @@ -987,13 +987,15 @@ bool QGstreamerPlayerSession::processBusMessage(const QGstreamerMessage &message if (gm) { //tag message comes from elements inside playbin, not from playbin itself if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_TAG) { - //qDebug() << "tag message"; GstTagList *tag_list; gst_message_parse_tag(gm, &tag_list); - m_tags.unite(QGstUtils::gstTagListToMap(tag_list)); + + QMap newTags = QGstUtils::gstTagListToMap(tag_list); + QMap::const_iterator it = newTags.constBegin(); + for ( ; it != newTags.constEnd(); ++it) + m_tags.insert(it.key(), it.value()); // overwrite existing tags gst_tag_list_free(tag_list); - //qDebug() << m_tags; emit tagsChanged(); } else if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_DURATION) { @@ -1459,13 +1461,6 @@ void QGstreamerPlayerSession::playbinNotifySource(GObject *o, GParamSpec *p, gpo qDebug() << "Playbin source added:" << G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(source)); #endif - // Turn off icecast metadata request, will be re-set if in QNetworkRequest - // (souphttpsrc docs say is false by default, but header appears in request - // @version 0.10.21) - if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "iradio-mode") != 0) - g_object_set(G_OBJECT(source), "iradio-mode", FALSE, NULL); - - // Set Headers const QByteArray userAgentString("User-Agent"); -- cgit v1.2.3 From f6e57f80a85f5341d2db074ca7c6ecd468b8ca7f Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Tue, 25 Mar 2014 15:44:54 +0100 Subject: WMF: improve changing playback rate on a media player. When going back to normal rate after playing in fast forward (greater than 2x), playback seemed frozen for some amount of time (up to 8 seconds). When playing in fast forward, only key frames are shown, ignoring all the others. When returning to a normal rate, the source reader will usually be pointing to a key frame in the future compared to the player clock position, meaning that all the frames in between won't be shown until the player clock catches up with the latest key frame that was read. When leaving fast-forward, we now reset the position on the player to force the source reader to point back to the frame at the current clock position and avoid the seamingly frozen playback. Also, emit playbackRateChanged() signal when changing the playback rate. Change-Id: I4f04f0f250083378e94fb4a47f9f917abeaaf24e Reviewed-by: Christian Stromme --- src/plugins/wmf/player/mfplayersession.cpp | 53 ++++++++++++++++++++++++++---- src/plugins/wmf/player/mfplayersession.h | 1 + 2 files changed, 48 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/plugins/wmf/player/mfplayersession.cpp b/src/plugins/wmf/player/mfplayersession.cpp index 69958061b..f61f7aba2 100644 --- a/src/plugins/wmf/player/mfplayersession.cpp +++ b/src/plugins/wmf/player/mfplayersession.cpp @@ -1157,8 +1157,8 @@ void MFPlayerSession::setPositionInternal(qint64 position, Command requestCmd) qreal MFPlayerSession::playbackRate() const { - if (m_pendingState != NoPending) - return m_request.rate; + if (m_scrubbing) + return m_restoreRate; return m_state.rate; } @@ -1166,6 +1166,7 @@ void MFPlayerSession::setPlaybackRate(qreal rate) { if (m_scrubbing) { m_restoreRate = rate; + emit playbackRateChanged(rate); return; } setPlaybackRateInternal(rate); @@ -1194,6 +1195,8 @@ void MFPlayerSession::setPlaybackRateInternal(qreal rate) isThin = TRUE; if (FAILED(m_rateSupport->IsRateSupported(isThin, rate, NULL))) { qWarning() << "unable to set playbackrate = " << rate; + m_pendingRate = m_request.rate = m_state.rate; + return; } } if (m_pendingState != NoPending) { @@ -1219,6 +1222,7 @@ void MFPlayerSession::commitRateChange(qreal rate, BOOL isThin) MFTIME hnsSystemTime = 0; MFTIME hnsClockTime = 0; Command cmdNow = m_state.command; + bool resetPosition = false; // Allowed rate transitions: // Positive <-> negative: Stopped // Negative <-> zero: Stopped @@ -1229,7 +1233,12 @@ void MFPlayerSession::commitRateChange(qreal rate, BOOL isThin) m_presentationClock->GetCorrelatedTime(0, &hnsClockTime, &hnsSystemTime); Q_ASSERT(hnsSystemTime != 0); - m_request.setCommand(rate < 0 || m_state.rate < 0 ? CmdSeekResume : CmdStart); + if (rate < 0 || m_state.rate < 0) + m_request.setCommand(CmdSeekResume); + else if (isThin || m_state.isThin) + m_request.setCommand(CmdStartAndSeek); + else + m_request.setCommand(CmdStart); // We need to stop only when dealing with negative rates if (rate >= 0 && m_state.rate >= 0) @@ -1247,7 +1256,9 @@ void MFPlayerSession::commitRateChange(qreal rate, BOOL isThin) // session cannot transition back from stopped to paused. // Therefore, this rate transition is not supported while paused. qWarning() << "Unable to change rate from positive to negative or vice versa in paused state"; - return; + rate = m_state.rate; + isThin = m_state.isThin; + goto done; } // This happens when resuming playback after scrubbing in pause mode. @@ -1279,17 +1290,42 @@ void MFPlayerSession::commitRateChange(qreal rate, BOOL isThin) // Resume to the current position (stop() will reset the position to 0) m_request.start = hnsClockTime / 10000; + } else if (!isThin && m_state.isThin) { + if (cmdNow == CmdStart) { + // When thinning, only key frames are read and presented. Going back + // to normal playback requires to reset the current position to force + // the pipeline to decode the actual frame at the current position + // (which might be earlier than the last decoded key frame) + resetPosition = true; + } else if (cmdNow == CmdPause) { + // If paused, dont reset the position until we resume, otherwise + // a new frame will be rendered + m_presentationClock->GetCorrelatedTime(0, &hnsClockTime, &hnsSystemTime); + m_request.setCommand(CmdSeekResume); + m_request.start = hnsClockTime / 10000; + } + } // Set the rate. if (FAILED(m_rateControl->SetRate(isThin, rate))) { qWarning() << "failed to set playbackrate = " << rate; - return; + rate = m_state.rate; + isThin = m_state.isThin; + goto done; } + if (resetPosition) { + m_presentationClock->GetCorrelatedTime(0, &hnsClockTime, &hnsSystemTime); + setPosition(hnsClockTime / 10000); + } + +done: // Adjust our current rate and requested rate. m_pendingRate = m_request.rate = m_state.rate = rate; - + if (rate != 0) + m_state.isThin = isThin; + emit playbackRateChanged(rate); } void MFPlayerSession::scrub(bool enableScrub) @@ -1705,6 +1741,11 @@ void MFPlayerSession::updatePendingCommands(Command command) case CmdSeek: case CmdSeekResume: setPositionInternal(m_request.start, m_request.command); + break; + case CmdStartAndSeek: + start(); + setPositionInternal(m_request.start, m_request.command); + break; } m_request.setCommand(CmdNone); } diff --git a/src/plugins/wmf/player/mfplayersession.h b/src/plugins/wmf/player/mfplayersession.h index 3ba43ce58..2c87f3cc6 100644 --- a/src/plugins/wmf/player/mfplayersession.h +++ b/src/plugins/wmf/player/mfplayersession.h @@ -165,6 +165,7 @@ private: CmdPause, CmdSeek, CmdSeekResume, + CmdStartAndSeek }; void clear(); -- cgit v1.2.3 From a7b8872cd5de1908bb2daa08a32afb5bff879ac2 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Tue, 8 Apr 2014 18:50:23 +0200 Subject: Fix some MediaPlayer properties returning wrong values. Once the QML component is complete, don't cache any value anymore and always ask the backend for the actual value. Change-Id: I2c3ad55618e0532f713cfcc8258a70a1114fc975 Reviewed-by: Christian Stromme --- src/imports/multimedia/qdeclarativeaudio.cpp | 44 ++++++++++++++-------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/imports/multimedia/qdeclarativeaudio.cpp b/src/imports/multimedia/qdeclarativeaudio.cpp index 16828a4d1..37509b17e 100644 --- a/src/imports/multimedia/qdeclarativeaudio.cpp +++ b/src/imports/multimedia/qdeclarativeaudio.cpp @@ -290,15 +290,15 @@ void QDeclarativeAudio::setVolume(qreal volume) return; } - if (m_vol == volume) + if (this->volume() == volume) return; - m_vol = volume; - - if (m_complete) + if (m_complete) { m_player->setVolume(qRound(volume * 100)); - else + } else { + m_vol = volume; emit volumeChanged(); + } } bool QDeclarativeAudio::isMuted() const @@ -308,15 +308,15 @@ bool QDeclarativeAudio::isMuted() const void QDeclarativeAudio::setMuted(bool muted) { - if (m_muted == muted) + if (isMuted() == muted) return; - m_muted = muted; - - if (m_complete) + if (m_complete) { m_player->setMuted(muted); - else + } else { + m_muted = muted; emit mutedChanged(); + } } qreal QDeclarativeAudio::bufferProgress() const @@ -331,20 +331,20 @@ bool QDeclarativeAudio::isSeekable() const qreal QDeclarativeAudio::playbackRate() const { - return m_playbackRate; + return m_complete ? m_player->playbackRate() : m_playbackRate; } void QDeclarativeAudio::setPlaybackRate(qreal rate) { - if (m_playbackRate == rate) + if (playbackRate() == rate) return; - m_playbackRate = rate; - - if (m_complete) - m_player->setPlaybackRate(m_playbackRate); - else + if (m_complete) { + m_player->setPlaybackRate(rate); + } else { + m_playbackRate = rate; emit playbackRateChanged(); + } } QString QDeclarativeAudio::errorString() const @@ -426,12 +426,12 @@ void QDeclarativeAudio::seek(int position) if (this->position() == position) return; - m_position = position; - - if (m_complete) - m_player->setPosition(m_position); - else + if (m_complete) { + m_player->setPosition(position); + } else { + m_position = position; emit positionChanged(); + } } /*! -- cgit v1.2.3 From 03672d570dc06ed0439c8ab3d31506f53d38f31a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Wed, 9 Apr 2014 15:15:03 +0200 Subject: Android: Fix the signature for setOnInfoListener. The argument part of the signature should be OnInfoListener and not OnErrorListener. Change-Id: I735fe1b0338b66c2f729254ed9e3251136781cbe Reviewed-by: Yoann Lopes --- src/plugins/android/src/wrappers/jmediarecorder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/android/src/wrappers/jmediarecorder.cpp b/src/plugins/android/src/wrappers/jmediarecorder.cpp index 675bc5dce..81d5c1142 100644 --- a/src/plugins/android/src/wrappers/jmediarecorder.cpp +++ b/src/plugins/android/src/wrappers/jmediarecorder.cpp @@ -75,7 +75,7 @@ JMediaRecorder::JMediaRecorder() "(Landroid/media/MediaRecorder$OnErrorListener;)V", listener.object()); m_mediaRecorder.callMethod("setOnInfoListener", - "(Landroid/media/MediaRecorder$OnErrorListener;)V", + "(Landroid/media/MediaRecorder$OnInfoListener;)V", listener.object()); g_objectMap.insert(m_id, this); } -- cgit v1.2.3 From 8a047ef087cebba5953ad3ed7b2d99df7966b695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Mon, 7 Apr 2014 15:13:42 +0200 Subject: Android: Use Q_GLOBAL_STATIC instead of a static QMap Change-Id: I7b65e0874051c4ef504914a0bd66e8471ec34fa7 Reviewed-by: Yoann Lopes --- src/plugins/android/src/wrappers/jmediarecorder.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/plugins/android/src/wrappers/jmediarecorder.cpp b/src/plugins/android/src/wrappers/jmediarecorder.cpp index 81d5c1142..0b1498d99 100644 --- a/src/plugins/android/src/wrappers/jmediarecorder.cpp +++ b/src/plugins/android/src/wrappers/jmediarecorder.cpp @@ -48,18 +48,19 @@ QT_BEGIN_NAMESPACE static jclass g_qtMediaRecorderListenerClass = 0; -static QMap g_objectMap; +typedef QMap MediaRecorderMap; +Q_GLOBAL_STATIC(MediaRecorderMap, mediaRecorders) static void notifyError(JNIEnv* , jobject, jlong id, jint what, jint extra) { - JMediaRecorder *obj = g_objectMap.value(id, 0); + JMediaRecorder *obj = mediaRecorders->value(id, 0); if (obj) emit obj->error(what, extra); } static void notifyInfo(JNIEnv* , jobject, jlong id, jint what, jint extra) { - JMediaRecorder *obj = g_objectMap.value(id, 0); + JMediaRecorder *obj = mediaRecorders->value(id, 0); if (obj) emit obj->info(what, extra); } @@ -77,13 +78,13 @@ JMediaRecorder::JMediaRecorder() m_mediaRecorder.callMethod("setOnInfoListener", "(Landroid/media/MediaRecorder$OnInfoListener;)V", listener.object()); - g_objectMap.insert(m_id, this); + mediaRecorders->insert(m_id, this); } } JMediaRecorder::~JMediaRecorder() { - g_objectMap.remove(m_id); + mediaRecorders->remove(m_id); } void JMediaRecorder::release() -- cgit v1.2.3