diff options
author | Sergio Ahumada <sahumada@blackberry.com> | 2014-06-14 21:59:24 +0200 |
---|---|---|
committer | Sergio Ahumada <sahumada@blackberry.com> | 2014-06-14 21:59:24 +0200 |
commit | d691f5ca2b6749006673e199b1d668a6daa9b990 (patch) | |
tree | eacad24192e1e0c492320e14bdfd7c3c203a01e0 /src/plugins | |
parent | d415d3256d055ef6fd7dad5c0497ecfaa56ee64d (diff) | |
parent | 150ff6662de1312e3ba9d000895d80dd5805ea5b (diff) |
Merge remote-tracking branch 'origin/5.3' into dev
Conflicts:
.qmake.conf
Change-Id: Iecd8d7b94e52a8981526b12cffa40e99870ba62f
Diffstat (limited to 'src/plugins')
56 files changed, 1404 insertions, 1455 deletions
diff --git a/src/plugins/android/android.pro b/src/plugins/android/android.pro index 807f8ece8..fa322942b 100644 --- a/src/plugins/android/android.pro +++ b/src/plugins/android/android.pro @@ -1,7 +1,7 @@ TEMPLATE = subdirs -SUBDIRS += src \ - jar +SUBDIRS += src +android:!android-no-sdk: SUBDIRS += jar qtHaveModule(quick) { SUBDIRS += videonode diff --git a/src/plugins/android/jar/jar.pri b/src/plugins/android/jar/jar.pri index d8bc59a72..d31839c61 100644 --- a/src/plugins/android/jar/jar.pri +++ b/src/plugins/android/jar/jar.pri @@ -6,7 +6,7 @@ API_VERSION = android-11 JAVACLASSPATH += $$PWD/src JAVASOURCES += $$PWD/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java \ - $$PWD/src/org/qtproject/qt5/android/multimedia/QtCamera.java \ + $$PWD/src/org/qtproject/qt5/android/multimedia/QtCameraListener.java \ $$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 \ diff --git a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java index 86ec30a5f..ff92af771 100644 --- a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java +++ b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java @@ -43,6 +43,7 @@ package org.qtproject.qt5.android.multimedia; import java.io.IOException; import java.lang.String; +import java.io.FileInputStream; // API is level is < 9 unless marked otherwise. import android.app.Activity; @@ -247,6 +248,8 @@ public class QtAndroidMediaPlayer if (mMediaPlayer == null) { mMediaPlayer = new MediaPlayer(); setState(State.Idle); + // Make sure the new media player has the volume that was set on the QMediaPlayer + setVolumeHelper(mMuted ? 0 : mVolume); } } @@ -376,6 +379,7 @@ public class QtAndroidMediaPlayer mMediaPlayer.setDisplay(mSurfaceHolder); AssetFileDescriptor afd = null; + FileInputStream fis = null; try { mUri = Uri.parse(path); final boolean inAssets = (mUri.getScheme().compareTo("assets") == 0); @@ -387,6 +391,10 @@ public class QtAndroidMediaPlayer final long length = afd.getLength(); FileDescriptor fd = afd.getFileDescriptor(); mMediaPlayer.setDataSource(fd, offset, length); + } else if (mUri.getScheme().compareTo("file") == 0) { + fis = new FileInputStream(mUri.getPath()); + FileDescriptor fd = fis.getFD(); + mMediaPlayer.setDataSource(fd); } else { mMediaPlayer.setDataSource(mActivity, mUri); } @@ -402,9 +410,13 @@ public class QtAndroidMediaPlayer } catch (final NullPointerException e) { Log.d(TAG, "" + e.getMessage()); } finally { - if (afd !=null) { - try { afd.close(); } catch (final IOException ioe) { /* Ignore... */ } - } + try { + if (afd != null) + afd.close(); + if (fis != null) + fis.close(); + } catch (final IOException ioe) { /* Ignore... */ } + if ((mState & State.Initialized) == 0) { setState(State.Error); onErrorNative(MediaPlayer.MEDIA_ERROR_UNKNOWN, @@ -472,6 +484,20 @@ public class QtAndroidMediaPlayer public void setVolume(int volume) { + if (volume < 0) + volume = 0; + + if (volume > 100) + volume = 100; + + mVolume = volume; + + if (!mMuted) + setVolumeHelper(mVolume); + } + + private void setVolumeHelper(int volume) + { if ((mState & (State.Idle | State.Initialized | State.Stopped @@ -482,18 +508,9 @@ public class QtAndroidMediaPlayer return; } - if (volume < 0) - volume = 0; - - if (volume > 100) - volume = 100; - - float newVolume = adjustVolume(volume); - try { + float newVolume = adjustVolume(volume); mMediaPlayer.setVolume(newVolume, newVolume); - if (!mMuted) - mVolume = volume; } catch (final IllegalStateException e) { Log.d(TAG, "" + e.getMessage()); } @@ -523,7 +540,7 @@ public class QtAndroidMediaPlayer public void mute(final boolean mute) { mMuted = mute; - setVolume(mute ? 0 : mVolume); + setVolumeHelper(mute ? 0 : mVolume); } public boolean isMuted() diff --git a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtCamera.java b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtCameraListener.java index f03053f17..27002fd29 100644 --- a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtCamera.java +++ b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtCameraListener.java @@ -48,148 +48,38 @@ import android.util.Log; import java.lang.Math; import java.util.concurrent.locks.ReentrantLock; -public class QtCamera implements Camera.ShutterCallback, - Camera.PictureCallback, - Camera.AutoFocusCallback, - Camera.PreviewCallback +public class QtCameraListener implements Camera.ShutterCallback, + Camera.PictureCallback, + Camera.AutoFocusCallback, + Camera.PreviewCallback { private int m_cameraId = -1; - private Camera m_camera = null; - private byte[] m_cameraPreviewFirstBuffer = null; - private byte[] m_cameraPreviewSecondBuffer = null; - private int m_actualPreviewBuffer = 0; + private byte[][] m_cameraPreviewBuffer = null; + private volatile int m_actualPreviewBuffer = 0; private final ReentrantLock m_buffersLock = new ReentrantLock(); - private boolean m_isReleased = false; private boolean m_fetchEachFrame = false; private static final String TAG = "Qt Camera"; - private QtCamera(int id, Camera cam) + private QtCameraListener(int id) { m_cameraId = id; - m_camera = cam; } - public static QtCamera open(int cameraId) + public void preparePreviewBuffer(Camera camera) { - try { - Camera cam = Camera.open(cameraId); - return new QtCamera(cameraId, cam); - } catch(Exception e) { - Log.d(TAG, e.getMessage()); - } - return null; - } - - public Camera.Parameters getParameters() - { - return m_camera.getParameters(); - } - - public void lock() - { - try { - m_camera.lock(); - } catch(Exception e) { - Log.d(TAG, e.getMessage()); - } - } - - public void unlock() - { - try { - m_camera.unlock(); - } catch(Exception e) { - Log.d(TAG, e.getMessage()); - } - } - - public void release() - { - m_isReleased = true; - m_camera.release(); - } - - public void reconnect() - { - try { - m_camera.reconnect(); - } catch(Exception e) { - Log.d(TAG, e.getMessage()); - } - } - - public void setDisplayOrientation(int degrees) - { - m_camera.setDisplayOrientation(degrees); - } - - public void setParameters(Camera.Parameters params) - { - try { - m_camera.setParameters(params); - } catch(Exception e) { - Log.d(TAG, e.getMessage()); - } - } - - public void setPreviewTexture(SurfaceTexture surfaceTexture) - { - try { - m_camera.setPreviewTexture(surfaceTexture); - } catch(Exception e) { - Log.d(TAG, e.getMessage()); - } - } - - public void fetchEachFrame(boolean fetch) - { - m_fetchEachFrame = fetch; - } - - public void startPreview() - { - Camera.Size previewSize = m_camera.getParameters().getPreviewSize(); - double bytesPerPixel = ImageFormat.getBitsPerPixel(m_camera.getParameters().getPreviewFormat()) / 8.0; + Camera.Size previewSize = camera.getParameters().getPreviewSize(); + double bytesPerPixel = ImageFormat.getBitsPerPixel(camera.getParameters().getPreviewFormat()) / 8.0; int bufferSizeNeeded = (int)Math.ceil(bytesPerPixel*previewSize.width*previewSize.height); - - //We need to clear preview buffers queue here, but there is no method to do it - //Though just resetting preview callback do the trick - m_camera.setPreviewCallback(null); m_buffersLock.lock(); - if (m_cameraPreviewFirstBuffer == null || m_cameraPreviewFirstBuffer.length < bufferSizeNeeded) - m_cameraPreviewFirstBuffer = new byte[bufferSizeNeeded]; - if (m_cameraPreviewSecondBuffer == null || m_cameraPreviewSecondBuffer.length < bufferSizeNeeded) - m_cameraPreviewSecondBuffer = new byte[bufferSizeNeeded]; - addCallbackBuffer(); + if (m_cameraPreviewBuffer == null || m_cameraPreviewBuffer[0].length < bufferSizeNeeded) + m_cameraPreviewBuffer = new byte[2][bufferSizeNeeded]; m_buffersLock.unlock(); - m_camera.setPreviewCallbackWithBuffer(this); - - m_camera.startPreview(); } - public void stopPreview() - { - m_camera.stopPreview(); - } - - public void autoFocus() - { - m_camera.autoFocus(this); - } - - public void cancelAutoFocus() - { - m_camera.cancelAutoFocus(); - } - - public void takePicture() + public void fetchEachFrame(boolean fetch) { - try { - m_camera.takePicture(this, null, this); - } catch(Exception e) { - Log.d(TAG, e.getMessage()); - } + m_fetchEachFrame = fetch; } public byte[] lockAndFetchPreviewBuffer() @@ -199,10 +89,7 @@ public class QtCamera implements Camera.ShutterCallback, //We should reset actualBuffer flag here to make sure we will not use old preview with future captures byte[] result = null; m_buffersLock.lock(); - if (m_actualPreviewBuffer == 1) - result = m_cameraPreviewFirstBuffer; - else if (m_actualPreviewBuffer == 2) - result = m_cameraPreviewSecondBuffer; + result = m_cameraPreviewBuffer[(m_actualPreviewBuffer == 1) ? 0 : 1]; m_actualPreviewBuffer = 0; return result; } @@ -213,14 +100,9 @@ public class QtCamera implements Camera.ShutterCallback, m_buffersLock.unlock(); } - private void addCallbackBuffer() + public byte[] callbackBuffer() { - if (m_isReleased) - return; - - m_camera.addCallbackBuffer((m_actualPreviewBuffer == 1) - ? m_cameraPreviewSecondBuffer - : m_cameraPreviewFirstBuffer); + return m_cameraPreviewBuffer[(m_actualPreviewBuffer == 1) ? 1 : 0]; } @Override @@ -243,13 +125,13 @@ public class QtCamera implements Camera.ShutterCallback, if (data != null && m_fetchEachFrame) notifyFrameFetched(m_cameraId, data); - if (data == m_cameraPreviewFirstBuffer) + if (data == m_cameraPreviewBuffer[0]) m_actualPreviewBuffer = 1; - else if (data == m_cameraPreviewSecondBuffer) + else if (data == m_cameraPreviewBuffer[1]) m_actualPreviewBuffer = 2; else m_actualPreviewBuffer = 0; - addCallbackBuffer(); + camera.addCallbackBuffer(m_cameraPreviewBuffer[(m_actualPreviewBuffer == 1) ? 1 : 0]); m_buffersLock.unlock(); } diff --git a/src/plugins/android/src/common/qandroidvideooutput.h b/src/plugins/android/src/common/qandroidvideooutput.h index 8bf6be6cb..e0335ec93 100644 --- a/src/plugins/android/src/common/qandroidvideooutput.h +++ b/src/plugins/android/src/common/qandroidvideooutput.h @@ -44,17 +44,17 @@ #include <qglobal.h> #include <qsize.h> -#include <jni.h> QT_BEGIN_NAMESPACE +class AndroidSurfaceTexture; + class QAndroidVideoOutput { public: virtual ~QAndroidVideoOutput() { } - virtual jobject surfaceHolder() = 0; - virtual jobject surfaceTexture() { return 0; } + virtual AndroidSurfaceTexture *surfaceTexture() { return 0; } virtual bool isReady() { return true; } diff --git a/src/plugins/android/src/common/qandroidvideorendercontrol.cpp b/src/plugins/android/src/common/qandroidvideorendercontrol.cpp index 5f14a4691..5532661db 100644 --- a/src/plugins/android/src/common/qandroidvideorendercontrol.cpp +++ b/src/plugins/android/src/common/qandroidvideorendercontrol.cpp @@ -40,8 +40,8 @@ ****************************************************************************/ #include "qandroidvideorendercontrol.h" +#include "androidsurfacetexture.h" -#include <QtCore/private/qjni_p.h> #include <QAbstractVideoSurface> #include <QVideoSurfaceFormat> #include <qevent.h> @@ -50,7 +50,6 @@ #include <qopenglfunctions.h> #include <qopenglshaderprogram.h> #include <qopenglframebufferobject.h> -#include <QtCore/private/qjnihelpers_p.h> QT_BEGIN_NAMESPACE @@ -110,9 +109,7 @@ private: QAndroidVideoRendererControl::QAndroidVideoRendererControl(QObject *parent) : QVideoRendererControl(parent) , m_surface(0) - , m_androidSurface(0) , m_surfaceTexture(0) - , m_surfaceHolder(0) , m_externalTex(0) , m_fbo(0) , m_program(0) @@ -175,9 +172,9 @@ bool QAndroidVideoRendererControl::initSurfaceTexture() return false; } - m_surfaceTexture = new JSurfaceTexture(m_externalTex); + m_surfaceTexture = new AndroidSurfaceTexture(m_externalTex); - if (m_surfaceTexture->object()) { + if (m_surfaceTexture->surfaceTexture() != 0) { connect(m_surfaceTexture, SIGNAL(frameAvailable()), this, SLOT(onFrameAvailable())); } else { delete m_surfaceTexture; @@ -196,42 +193,14 @@ void QAndroidVideoRendererControl::clearSurfaceTexture() delete m_surfaceTexture; m_surfaceTexture = 0; } - if (m_androidSurface) { - if (QtAndroidPrivate::androidSdkVersion() > 13) - m_androidSurface->callMethod<void>("release"); - delete m_androidSurface; - m_androidSurface = 0; - } - if (m_surfaceHolder) { - delete m_surfaceHolder; - m_surfaceHolder = 0; - } -} - -jobject QAndroidVideoRendererControl::surfaceHolder() -{ - if (!initSurfaceTexture()) - return 0; - - if (!m_surfaceHolder) { - m_androidSurface = new QJNIObjectPrivate("android/view/Surface", - "(Landroid/graphics/SurfaceTexture;)V", - m_surfaceTexture->object()); - - m_surfaceHolder = new QJNIObjectPrivate("org/qtproject/qt5/android/multimedia/QtSurfaceTextureHolder", - "(Landroid/view/Surface;)V", - m_androidSurface->object()); - } - - return m_surfaceHolder->object(); } -jobject QAndroidVideoRendererControl::surfaceTexture() +AndroidSurfaceTexture *QAndroidVideoRendererControl::surfaceTexture() { if (!initSurfaceTexture()) return 0; - return m_surfaceTexture->object(); + return m_surfaceTexture; } void QAndroidVideoRendererControl::setVideoSize(const QSize &size) @@ -267,7 +236,7 @@ void QAndroidVideoRendererControl::onFrameAvailable() QVideoFrame frame(buffer, m_nativeSize, QVideoFrame::Format_BGR32); if (m_surface->isActive() && (m_surface->surfaceFormat().pixelFormat() != frame.pixelFormat() - || m_surface->nativeResolution() != frame.size())) { + || m_surface->surfaceFormat().frameSize() != frame.size())) { m_surface->stop(); } diff --git a/src/plugins/android/src/common/qandroidvideorendercontrol.h b/src/plugins/android/src/common/qandroidvideorendercontrol.h index 75fd7ef12..6e70238c2 100644 --- a/src/plugins/android/src/common/qandroidvideorendercontrol.h +++ b/src/plugins/android/src/common/qandroidvideorendercontrol.h @@ -45,13 +45,13 @@ #include <qvideorenderercontrol.h> #include <qmutex.h> #include "qandroidvideooutput.h" -#include "jsurfacetexture.h" QT_BEGIN_NAMESPACE class QOpenGLTexture; class QOpenGLFramebufferObject; class QOpenGLShaderProgram; +class AndroidSurfaceTexture; class OpenGLResourcesDeleter : public QObject { @@ -86,8 +86,7 @@ public: QAbstractVideoSurface *surface() const Q_DECL_OVERRIDE; void setSurface(QAbstractVideoSurface *surface) Q_DECL_OVERRIDE; - jobject surfaceHolder() Q_DECL_OVERRIDE; - jobject surfaceTexture() Q_DECL_OVERRIDE; + AndroidSurfaceTexture *surfaceTexture() Q_DECL_OVERRIDE; bool isReady() Q_DECL_OVERRIDE; void setVideoSize(const QSize &size) Q_DECL_OVERRIDE; void stop() Q_DECL_OVERRIDE; @@ -112,9 +111,7 @@ private: QAbstractVideoSurface *m_surface; QSize m_nativeSize; - QJNIObjectPrivate *m_androidSurface; - JSurfaceTexture *m_surfaceTexture; - QJNIObjectPrivate *m_surfaceHolder; + AndroidSurfaceTexture *m_surfaceTexture; quint32 m_externalTex; QOpenGLFramebufferObject *m_fbo; diff --git a/src/plugins/android/src/mediacapture/mediacapture.pri b/src/plugins/android/src/mediacapture/mediacapture.pri index 01274414b..fde0e3d6f 100644 --- a/src/plugins/android/src/mediacapture/mediacapture.pri +++ b/src/plugins/android/src/mediacapture/mediacapture.pri @@ -12,7 +12,6 @@ SOURCES += \ $$PWD/qandroidcameraimagecapturecontrol.cpp \ $$PWD/qandroidcameracapturedestinationcontrol.cpp \ $$PWD/qandroidcameracapturebufferformatcontrol.cpp \ - $$PWD/qandroidmediastoragelocation.cpp \ $$PWD/qandroidcameraflashcontrol.cpp \ $$PWD/qandroidcamerafocuscontrol.cpp \ $$PWD/qandroidcameralockscontrol.cpp \ @@ -37,7 +36,6 @@ HEADERS += \ $$PWD/qandroidcameraimagecapturecontrol.h \ $$PWD/qandroidcameracapturedestinationcontrol.h \ $$PWD/qandroidcameracapturebufferformatcontrol.h \ - $$PWD/qandroidmediastoragelocation.h \ $$PWD/qandroidcameraflashcontrol.h \ $$PWD/qandroidcamerafocuscontrol.h \ $$PWD/qandroidcameralockscontrol.h \ diff --git a/src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.cpp index 03bbadb93..57057ebd7 100644 --- a/src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.cpp @@ -42,7 +42,7 @@ #include "qandroidcameraexposurecontrol.h" #include "qandroidcamerasession.h" -#include "jcamera.h" +#include "androidcamera.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.cpp index 253b1baa5..de8e521ee 100644 --- a/src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.cpp @@ -42,7 +42,7 @@ #include "qandroidcameraflashcontrol.h" #include "qandroidcamerasession.h" -#include "jcamera.h" +#include "androidcamera.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.cpp index 345a29174..0b6ab80fc 100644 --- a/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.cpp @@ -42,7 +42,7 @@ #include "qandroidcamerafocuscontrol.h" #include "qandroidcamerasession.h" -#include "jcamera.h" +#include "androidcamera.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.cpp index ec5a3bcbf..4e4a416dd 100644 --- a/src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.cpp @@ -42,7 +42,7 @@ #include "qandroidcameraimageprocessingcontrol.h" #include "qandroidcamerasession.h" -#include "jcamera.h" +#include "androidcamera.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcameralockscontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameralockscontrol.cpp index d9f20ec04..bfb48d06e 100644 --- a/src/plugins/android/src/mediacapture/qandroidcameralockscontrol.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcameralockscontrol.cpp @@ -42,7 +42,7 @@ #include "qandroidcameralockscontrol.h" #include "qandroidcamerasession.h" -#include "jcamera.h" +#include "androidcamera.h" #include <qtimer.h> QT_BEGIN_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp index b1b3f848e..963952294 100644 --- a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Toolkit. @@ -41,8 +41,8 @@ #include "qandroidcamerasession.h" -#include "jcamera.h" -#include "jmultimediautils.h" +#include "androidcamera.h" +#include "androidmultimediautils.h" #include "qandroidvideooutput.h" #include "qandroidmediavideoprobecontrol.h" #include "qandroidmultimediautils.h" @@ -111,6 +111,10 @@ QAndroidCameraSession::QAndroidCameraSession(QObject *parent) , m_captureCanceled(false) , m_currentImageCaptureId(-1) { + m_mediaStorageLocation.addStorageLocation( + QMediaStorageLocation::Pictures, + AndroidMultimediaUtils::getDefaultMediaDirectory(AndroidMultimediaUtils::DCIM)); + if (qApp) { connect(qApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(onApplicationStateChanged(Qt::ApplicationState))); @@ -164,10 +168,12 @@ void QAndroidCameraSession::setState(QCamera::State state) emit error(QCamera::CameraError, QStringLiteral("Failed to open camera")); return; } - if (state == QCamera::ActiveState) - startPreview(); - else if (state == QCamera::LoadedState) + if (state == QCamera::ActiveState) { + if (!startPreview()) + return; + } else if (state == QCamera::LoadedState) { stopPreview(); + } break; } @@ -179,36 +185,10 @@ void QAndroidCameraSession::updateAvailableCameras() { g_availableCameras->clear(); - const QJNIObjectPrivate cameraInfo("android/hardware/Camera$CameraInfo"); - const int numCameras = QJNIObjectPrivate::callStaticMethod<jint>("android/hardware/Camera", - "getNumberOfCameras"); - + const int numCameras = AndroidCamera::getNumberOfCameras(); for (int i = 0; i < numCameras; ++i) { AndroidCameraInfo info; - - QJNIObjectPrivate::callStaticMethod<void>("android/hardware/Camera", - "getCameraInfo", - "(ILandroid/hardware/Camera$CameraInfo;)V", - i, cameraInfo.object()); - - JCamera::CameraFacing facing = JCamera::CameraFacing(cameraInfo.getField<jint>("facing")); - // The orientation provided by Android is counter-clockwise, we need it clockwise - info.orientation = (360 - cameraInfo.getField<jint>("orientation")) % 360; - - switch (facing) { - case JCamera::CameraFacingBack: - info.name = QByteArray("back"); - info.description = QStringLiteral("Rear-facing camera"); - info.position = QCamera::BackFace; - break; - case JCamera::CameraFacingFront: - info.name = QByteArray("front"); - info.description = QStringLiteral("Front-facing camera"); - info.position = QCamera::FrontFace; - break; - default: - break; - } + AndroidCamera::getCameraInfo(i, &info); if (!info.name.isNull()) g_availableCameras->append(info); @@ -230,7 +210,7 @@ bool QAndroidCameraSession::open() m_status = QCamera::LoadingStatus; emit statusChanged(m_status); - m_camera = JCamera::open(m_selectedCamera); + m_camera = AndroidCamera::open(m_selectedCamera); if (m_camera) { connect(m_camera, SIGNAL(pictureExposed()), this, SLOT(onCameraPictureExposed())); @@ -246,8 +226,8 @@ bool QAndroidCameraSession::open() m_status = QCamera::LoadedStatus; - if (m_camera->getPreviewFormat() != JCamera::NV21) - m_camera->setPreviewFormat(JCamera::NV21); + if (m_camera->getPreviewFormat() != AndroidCamera::NV21) + m_camera->setPreviewFormat(AndroidCamera::NV21); m_camera->fetchEachFrame(m_videoProbes.count()); @@ -286,8 +266,10 @@ void QAndroidCameraSession::close() void QAndroidCameraSession::setVideoPreview(QObject *videoOutput) { - if (m_videoOutput) + if (m_videoOutput) { m_videoOutput->stop(); + m_videoOutput->reset(); + } if (videoOutput) { connect(videoOutput, SIGNAL(readyChanged(bool)), this, SLOT(onVideoOutputReady(bool))); @@ -336,10 +318,23 @@ void QAndroidCameraSession::adjustViewfinderSize(const QSize &captureSize, bool } } -void QAndroidCameraSession::startPreview() +bool QAndroidCameraSession::startPreview() { - if (!m_camera || m_previewStarted) - return; + if (!m_camera) + return false; + + if (!m_videoOutput) { + Q_EMIT error(QCamera::InvalidRequestError, tr("Camera cannot be started without a viewfinder.")); + return false; + } + + if (m_previewStarted) + return true; + + if (m_videoOutput->isReady()) + m_camera->setPreviewTexture(m_videoOutput->surfaceTexture()); + else + return true; // delay starting until the video output is ready m_status = QCamera::StartingStatus; emit statusChanged(m_status); @@ -347,13 +342,12 @@ void QAndroidCameraSession::startPreview() applyImageSettings(); adjustViewfinderSize(m_imageSettings.resolution()); - if (m_videoOutput && m_videoOutput->isReady()) - onVideoOutputReady(true); - - JMultimediaUtils::enableOrientationListener(true); + AndroidMultimediaUtils::enableOrientationListener(true); m_camera->startPreview(); m_previewStarted = true; + + return true; } void QAndroidCameraSession::stopPreview() @@ -364,12 +358,16 @@ void QAndroidCameraSession::stopPreview() m_status = QCamera::StoppingStatus; emit statusChanged(m_status); - JMultimediaUtils::enableOrientationListener(false); + AndroidMultimediaUtils::enableOrientationListener(false); m_camera->stopPreview(); m_camera->setPreviewSize(QSize()); - if (m_videoOutput) + m_camera->setPreviewTexture(0); + + if (m_videoOutput) { m_videoOutput->stop(); + m_videoOutput->reset(); + } m_previewStarted = false; } @@ -397,8 +395,8 @@ int QAndroidCameraSession::currentCameraRotation() const // subtract natural camera orientation and physical device orientation int rotation = 0; - int deviceOrientation = (JMultimediaUtils::getDeviceOrientation() + 45) / 90 * 90; - if (m_camera->getFacing() == JCamera::CameraFacingFront) + int deviceOrientation = (AndroidMultimediaUtils::getDeviceOrientation() + 45) / 90 * 90; + if (m_camera->getFacing() == AndroidCamera::CameraFacingFront) rotation = (m_nativeOrientation - deviceOrientation + 360) % 360; else // back-facing camera rotation = (m_nativeOrientation + deviceOrientation) % 360; @@ -638,7 +636,7 @@ void QAndroidCameraSession::processCapturedImage(int id, if (dest & QCameraImageCapture::CaptureToFile) { const QString actualFileName = m_mediaStorageLocation.generateFileName(fileName, - QAndroidMediaStorageLocation::Camera, + QMediaStorageLocation::Pictures, QLatin1String("IMG_"), QLatin1String("jpg")); @@ -648,9 +646,9 @@ void QAndroidCameraSession::processCapturedImage(int id, // if the picture is saved into the standard picture location, register it // with the Android media scanner so it appears immediately in apps // such as the gallery. - QString standardLoc = JMultimediaUtils::getDefaultMediaDirectory(JMultimediaUtils::DCIM); + QString standardLoc = AndroidMultimediaUtils::getDefaultMediaDirectory(AndroidMultimediaUtils::DCIM); if (actualFileName.startsWith(standardLoc)) - JMultimediaUtils::registerMediaFile(actualFileName); + AndroidMultimediaUtils::registerMediaFile(actualFileName); emit imageSaved(id, actualFileName); } else { @@ -687,7 +685,7 @@ QImage QAndroidCameraSession::prepareImageFromPreviewData(const QByteArray &data // Preview display of front-facing cameras is flipped horizontally, but the frame data // we get here is not. Flip it ourselves if the camera is front-facing to match what the user // sees on the viewfinder. - if (m_camera->getFacing() == JCamera::CameraFacingFront) + if (m_camera->getFacing() == AndroidCamera::CameraFacingFront) transform.scale(-1, 1); transform.rotate(rotation); @@ -699,8 +697,8 @@ QImage QAndroidCameraSession::prepareImageFromPreviewData(const QByteArray &data void QAndroidCameraSession::onVideoOutputReady(bool ready) { - if (m_camera && m_videoOutput && ready) - m_camera->setPreviewTexture(m_videoOutput->surfaceTexture()); + if (ready && m_state == QCamera::ActiveState) + startPreview(); } void QAndroidCameraSession::onApplicationStateChanged(Qt::ApplicationState state) diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.h b/src/plugins/android/src/mediacapture/qandroidcamerasession.h index f3ac67894..04ba1605f 100644 --- a/src/plugins/android/src/mediacapture/qandroidcamerasession.h +++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Toolkit. @@ -47,22 +47,14 @@ #include <QCameraImageCapture> #include <QSet> #include <QMutex> -#include "qandroidmediastoragelocation.h" +#include <private/qmediastoragelocation_p.h> +#include "androidcamera.h" QT_BEGIN_NAMESPACE -class JCamera; class QAndroidVideoOutput; class QAndroidMediaVideoProbeControl; -struct AndroidCameraInfo -{ - QByteArray name; - QString description; - QCamera::Position position; - int orientation; -}; - class QAndroidCameraSession : public QObject { Q_OBJECT @@ -73,7 +65,7 @@ public: static const QList<AndroidCameraInfo> &availableCameras(); void setSelectedCamera(int cameraId) { m_selectedCamera = cameraId; } - JCamera *camera() const { return m_camera; } + AndroidCamera *camera() const { return m_camera; } QCamera::State state() const { return m_state; } void setState(QCamera::State state); @@ -141,7 +133,7 @@ private: bool open(); void close(); - void startPreview(); + bool startPreview(); void stopPreview(); void applyImageSettings(); @@ -154,7 +146,7 @@ private: const QString &fileName); int m_selectedCamera; - JCamera *m_camera; + AndroidCamera *m_camera; int m_nativeOrientation; QAndroidVideoOutput *m_videoOutput; @@ -174,7 +166,7 @@ private: int m_currentImageCaptureId; QString m_currentImageCaptureFileName; - QAndroidMediaStorageLocation m_mediaStorageLocation; + QMediaStorageLocation m_mediaStorageLocation; QSet<QAndroidMediaVideoProbeControl *> m_videoProbes; QMutex m_videoProbesMutex; diff --git a/src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.cpp index b7030e56b..385cd942a 100644 --- a/src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.cpp @@ -42,7 +42,7 @@ #include "qandroidcamerazoomcontrol.h" #include "qandroidcamerasession.h" -#include "jcamera.h" +#include "androidcamera.h" #include "qandroidmultimediautils.h" #include <qmath.h> diff --git a/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp b/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp index 008ebc7d5..383af812a 100644 --- a/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Toolkit. @@ -41,11 +41,10 @@ #include "qandroidcapturesession.h" -#include "jcamera.h" +#include "androidcamera.h" #include "qandroidcamerasession.h" -#include "jmultimediautils.h" +#include "androidmultimediautils.h" #include "qandroidmultimediautils.h" -#include <QtCore/private/qjni_p.h> QT_BEGIN_NAMESPACE @@ -53,7 +52,7 @@ QAndroidCaptureSession::QAndroidCaptureSession(QAndroidCameraSession *cameraSess : QObject() , m_mediaRecorder(0) , m_cameraSession(cameraSession) - , m_audioSource(JMediaRecorder::DefaultAudioSource) + , m_audioSource(AndroidMediaRecorder::DefaultAudioSource) , m_duration(0) , m_state(QMediaRecorder::StoppedState) , m_status(QMediaRecorder::UnloadedStatus) @@ -61,10 +60,18 @@ QAndroidCaptureSession::QAndroidCaptureSession(QAndroidCameraSession *cameraSess , m_containerFormatDirty(true) , m_videoSettingsDirty(true) , m_audioSettingsDirty(true) - , m_outputFormat(JMediaRecorder::DefaultOutputFormat) - , m_audioEncoder(JMediaRecorder::DefaultAudioEncoder) - , m_videoEncoder(JMediaRecorder::DefaultVideoEncoder) + , m_outputFormat(AndroidMediaRecorder::DefaultOutputFormat) + , m_audioEncoder(AndroidMediaRecorder::DefaultAudioEncoder) + , m_videoEncoder(AndroidMediaRecorder::DefaultVideoEncoder) { + m_mediaStorageLocation.addStorageLocation( + QMediaStorageLocation::Movies, + AndroidMultimediaUtils::getDefaultMediaDirectory(AndroidMultimediaUtils::DCIM)); + + m_mediaStorageLocation.addStorageLocation( + QMediaStorageLocation::Sounds, + AndroidMultimediaUtils::getDefaultMediaDirectory(AndroidMultimediaUtils::Sounds)); + connect(this, SIGNAL(stateChanged(QMediaRecorder::State)), this, SLOT(updateStatus())); if (cameraSession) { @@ -95,19 +102,19 @@ void QAndroidCaptureSession::setAudioInput(const QString &input) m_audioInput = input; if (m_audioInput == QLatin1String("default")) - m_audioSource = JMediaRecorder::DefaultAudioSource; + m_audioSource = AndroidMediaRecorder::DefaultAudioSource; else if (m_audioInput == QLatin1String("mic")) - m_audioSource = JMediaRecorder::Mic; + m_audioSource = AndroidMediaRecorder::Mic; else if (m_audioInput == QLatin1String("voice_uplink")) - m_audioSource = JMediaRecorder::VoiceUplink; + m_audioSource = AndroidMediaRecorder::VoiceUplink; else if (m_audioInput == QLatin1String("voice_downlink")) - m_audioSource = JMediaRecorder::VoiceDownlink; + m_audioSource = AndroidMediaRecorder::VoiceDownlink; else if (m_audioInput == QLatin1String("voice_call")) - m_audioSource = JMediaRecorder::VoiceCall; + m_audioSource = AndroidMediaRecorder::VoiceCall; else if (m_audioInput == QLatin1String("voice_recognition")) - m_audioSource = JMediaRecorder::VoiceRecognition; + m_audioSource = AndroidMediaRecorder::VoiceRecognition; else - m_audioSource = JMediaRecorder::DefaultAudioSource; + m_audioSource = AndroidMediaRecorder::DefaultAudioSource; emit audioInputChanged(m_audioInput); } @@ -176,7 +183,7 @@ bool QAndroidCaptureSession::start() m_mediaRecorder->release(); delete m_mediaRecorder; } - m_mediaRecorder = new JMediaRecorder; + m_mediaRecorder = new AndroidMediaRecorder; connect(m_mediaRecorder, SIGNAL(error(int,int)), this, SLOT(onError(int,int))); connect(m_mediaRecorder, SIGNAL(info(int,int)), this, SLOT(onInfo(int,int))); @@ -185,8 +192,8 @@ bool QAndroidCaptureSession::start() updateViewfinder(); m_cameraSession->camera()->unlock(); m_mediaRecorder->setCamera(m_cameraSession->camera()); - m_mediaRecorder->setAudioSource(JMediaRecorder::Camcorder); - m_mediaRecorder->setVideoSource(JMediaRecorder::Camera); + m_mediaRecorder->setAudioSource(AndroidMediaRecorder::Camcorder); + m_mediaRecorder->setVideoSource(AndroidMediaRecorder::Camera); } else { m_mediaRecorder->setAudioSource(m_audioSource); } @@ -214,8 +221,8 @@ bool QAndroidCaptureSession::start() QString filePath = m_mediaStorageLocation.generateFileName( m_requestedOutputLocation.isLocalFile() ? m_requestedOutputLocation.toLocalFile() : m_requestedOutputLocation.toString(), - m_cameraSession ? QAndroidMediaStorageLocation::Camera - : QAndroidMediaStorageLocation::Audio, + m_cameraSession ? QMediaStorageLocation::Movies + : QMediaStorageLocation::Sounds, m_cameraSession ? QLatin1String("VID_") : QLatin1String("REC_"), m_containerFormat); @@ -272,10 +279,10 @@ void QAndroidCaptureSession::stop(bool error) // with the Android media scanner so it appears immediately in apps // such as the gallery. QString mediaPath = m_actualOutputLocation.toLocalFile(); - QString standardLoc = m_cameraSession ? JMultimediaUtils::getDefaultMediaDirectory(JMultimediaUtils::DCIM) - : JMultimediaUtils::getDefaultMediaDirectory(JMultimediaUtils::Sounds); + QString standardLoc = m_cameraSession ? AndroidMultimediaUtils::getDefaultMediaDirectory(AndroidMultimediaUtils::DCIM) + : AndroidMultimediaUtils::getDefaultMediaDirectory(AndroidMultimediaUtils::Sounds); if (mediaPath.startsWith(standardLoc)) - JMultimediaUtils::registerMediaFile(mediaPath); + AndroidMultimediaUtils::registerMediaFile(mediaPath); m_actualOutputLocation = m_usedOutputLocation; emit actualLocationChanged(m_actualOutputLocation); @@ -339,14 +346,14 @@ void QAndroidCaptureSession::applySettings() m_containerFormat = m_defaultSettings.outputFileExtension; m_outputFormat = m_defaultSettings.outputFormat; } else if (m_containerFormat == QLatin1String("3gp")) { - m_outputFormat = JMediaRecorder::THREE_GPP; + m_outputFormat = AndroidMediaRecorder::THREE_GPP; } else if (!m_cameraSession && m_containerFormat == QLatin1String("amr")) { - m_outputFormat = JMediaRecorder::AMR_NB_Format; + m_outputFormat = AndroidMediaRecorder::AMR_NB_Format; } else if (!m_cameraSession && m_containerFormat == QLatin1String("awb")) { - m_outputFormat = JMediaRecorder::AMR_WB_Format; + m_outputFormat = AndroidMediaRecorder::AMR_WB_Format; } else { m_containerFormat = QStringLiteral("mp4"); - m_outputFormat = JMediaRecorder::MPEG_4; + m_outputFormat = AndroidMediaRecorder::MPEG_4; } m_containerFormatDirty = false; @@ -364,11 +371,11 @@ void QAndroidCaptureSession::applySettings() if (m_audioSettings.codec().isEmpty()) m_audioEncoder = m_defaultSettings.audioEncoder; else if (m_audioSettings.codec() == QLatin1String("aac")) - m_audioEncoder = JMediaRecorder::AAC; + m_audioEncoder = AndroidMediaRecorder::AAC; else if (m_audioSettings.codec() == QLatin1String("amr-nb")) - m_audioEncoder = JMediaRecorder::AMR_NB_Encoder; + m_audioEncoder = AndroidMediaRecorder::AMR_NB_Encoder; else if (m_audioSettings.codec() == QLatin1String("amr-wb")) - m_audioEncoder = JMediaRecorder::AMR_WB_Encoder; + m_audioEncoder = AndroidMediaRecorder::AMR_WB_Encoder; else m_audioEncoder = m_defaultSettings.audioEncoder; @@ -402,11 +409,11 @@ void QAndroidCaptureSession::applySettings() if (m_videoSettings.codec().isEmpty()) m_videoEncoder = m_defaultSettings.videoEncoder; else if (m_videoSettings.codec() == QLatin1String("h263")) - m_videoEncoder = JMediaRecorder::H263; + m_videoEncoder = AndroidMediaRecorder::H263; else if (m_videoSettings.codec() == QLatin1String("h264")) - m_videoEncoder = JMediaRecorder::H264; + m_videoEncoder = AndroidMediaRecorder::H264; else if (m_videoSettings.codec() == QLatin1String("mpeg4_sp")) - m_videoEncoder = JMediaRecorder::MPEG_4_SP; + m_videoEncoder = AndroidMediaRecorder::MPEG_4_SP; else m_videoEncoder = m_defaultSettings.videoEncoder; @@ -448,7 +455,7 @@ void QAndroidCaptureSession::onCameraOpened() for (int i = 0; i < 8; ++i) { CaptureProfile profile = getProfile(i); if (!profile.isNull) { - if (i == 1) // QUALITY_HIGH + if (i == AndroidCamcorderProfile::QUALITY_HIGH) m_defaultSettings = profile; if (!m_supportedResolutions.contains(profile.videoResolution)) @@ -467,38 +474,31 @@ void QAndroidCaptureSession::onCameraOpened() QAndroidCaptureSession::CaptureProfile QAndroidCaptureSession::getProfile(int id) { CaptureProfile profile; - bool hasProfile = QJNIObjectPrivate::callStaticMethod<jboolean>("android/media/CamcorderProfile", - "hasProfile", - "(II)Z", - m_cameraSession->camera()->cameraId(), - id); + const bool hasProfile = AndroidCamcorderProfile::hasProfile(m_cameraSession->camera()->cameraId(), + AndroidCamcorderProfile::Quality(id)); if (hasProfile) { - QJNIObjectPrivate obj = QJNIObjectPrivate::callStaticObjectMethod("android/media/CamcorderProfile", - "get", - "(II)Landroid/media/CamcorderProfile;", - m_cameraSession->camera()->cameraId(), - id); - - - profile.outputFormat = JMediaRecorder::OutputFormat(obj.getField<jint>("fileFormat")); - profile.audioEncoder = JMediaRecorder::AudioEncoder(obj.getField<jint>("audioCodec")); - profile.audioBitRate = obj.getField<jint>("audioBitRate"); - profile.audioChannels = obj.getField<jint>("audioChannels"); - profile.audioSampleRate = obj.getField<jint>("audioSampleRate"); - profile.videoEncoder = JMediaRecorder::VideoEncoder(obj.getField<jint>("videoCodec")); - profile.videoBitRate = obj.getField<jint>("videoBitRate"); - profile.videoFrameRate = obj.getField<jint>("videoFrameRate"); - profile.videoResolution = QSize(obj.getField<jint>("videoFrameWidth"), - obj.getField<jint>("videoFrameHeight")); - - if (profile.outputFormat == JMediaRecorder::MPEG_4) + AndroidCamcorderProfile camProfile = AndroidCamcorderProfile::get(m_cameraSession->camera()->cameraId(), + AndroidCamcorderProfile::Quality(id)); + + profile.outputFormat = AndroidMediaRecorder::OutputFormat(camProfile.getValue(AndroidCamcorderProfile::fileFormat)); + profile.audioEncoder = AndroidMediaRecorder::AudioEncoder(camProfile.getValue(AndroidCamcorderProfile::audioCodec)); + profile.audioBitRate = camProfile.getValue(AndroidCamcorderProfile::audioBitRate); + profile.audioChannels = camProfile.getValue(AndroidCamcorderProfile::audioChannels); + profile.audioSampleRate = camProfile.getValue(AndroidCamcorderProfile::audioSampleRate); + profile.videoEncoder = AndroidMediaRecorder::VideoEncoder(camProfile.getValue(AndroidCamcorderProfile::videoCodec)); + profile.videoBitRate = camProfile.getValue(AndroidCamcorderProfile::videoBitRate); + profile.videoFrameRate = camProfile.getValue(AndroidCamcorderProfile::videoFrameRate); + profile.videoResolution = QSize(camProfile.getValue(AndroidCamcorderProfile::videoFrameWidth), + camProfile.getValue(AndroidCamcorderProfile::videoFrameHeight)); + + if (profile.outputFormat == AndroidMediaRecorder::MPEG_4) profile.outputFileExtension = QStringLiteral("mp4"); - else if (profile.outputFormat == JMediaRecorder::THREE_GPP) + else if (profile.outputFormat == AndroidMediaRecorder::THREE_GPP) profile.outputFileExtension = QStringLiteral("3gp"); - else if (profile.outputFormat == JMediaRecorder::AMR_NB_Format) + else if (profile.outputFormat == AndroidMediaRecorder::AMR_NB_Format) profile.outputFileExtension = QStringLiteral("amr"); - else if (profile.outputFormat == JMediaRecorder::AMR_WB_Format) + else if (profile.outputFormat == AndroidMediaRecorder::AMR_WB_Format) profile.outputFileExtension = QStringLiteral("awb"); profile.isNull = false; diff --git a/src/plugins/android/src/mediacapture/qandroidcapturesession.h b/src/plugins/android/src/mediacapture/qandroidcapturesession.h index 32ca9d1ae..4ff2cb145 100644 --- a/src/plugins/android/src/mediacapture/qandroidcapturesession.h +++ b/src/plugins/android/src/mediacapture/qandroidcapturesession.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Toolkit. @@ -47,8 +47,8 @@ #include <qurl.h> #include <qelapsedtimer.h> #include <qtimer.h> -#include "qandroidmediastoragelocation.h" -#include "jmediarecorder.h" +#include <private/qmediastoragelocation_p.h> +#include "androidmediarecorder.h" QT_BEGIN_NAMESPACE @@ -106,15 +106,15 @@ private Q_SLOTS: private: struct CaptureProfile { - JMediaRecorder::OutputFormat outputFormat; + AndroidMediaRecorder::OutputFormat outputFormat; QString outputFileExtension; - JMediaRecorder::AudioEncoder audioEncoder; + AndroidMediaRecorder::AudioEncoder audioEncoder; int audioBitRate; int audioChannels; int audioSampleRate; - JMediaRecorder::VideoEncoder videoEncoder; + AndroidMediaRecorder::VideoEncoder videoEncoder; int videoBitRate; int videoFrameRate; QSize videoResolution; @@ -122,13 +122,13 @@ private: bool isNull; CaptureProfile() - : outputFormat(JMediaRecorder::MPEG_4) + : outputFormat(AndroidMediaRecorder::MPEG_4) , outputFileExtension(QLatin1String("mp4")) - , audioEncoder(JMediaRecorder::DefaultAudioEncoder) + , audioEncoder(AndroidMediaRecorder::DefaultAudioEncoder) , audioBitRate(128000) , audioChannels(2) , audioSampleRate(44100) - , videoEncoder(JMediaRecorder::DefaultVideoEncoder) + , videoEncoder(AndroidMediaRecorder::DefaultVideoEncoder) , videoBitRate(1) , videoFrameRate(-1) , videoResolution(320, 240) @@ -146,13 +146,13 @@ private: void updateViewfinder(); void restartViewfinder(); - JMediaRecorder *m_mediaRecorder; + AndroidMediaRecorder *m_mediaRecorder; QAndroidCameraSession *m_cameraSession; QString m_audioInput; - JMediaRecorder::AudioSource m_audioSource; + AndroidMediaRecorder::AudioSource m_audioSource; - QAndroidMediaStorageLocation m_mediaStorageLocation; + QMediaStorageLocation m_mediaStorageLocation; QElapsedTimer m_elapsedTime; QTimer m_notifyTimer; @@ -173,9 +173,9 @@ private: bool m_containerFormatDirty; bool m_videoSettingsDirty; bool m_audioSettingsDirty; - JMediaRecorder::OutputFormat m_outputFormat; - JMediaRecorder::AudioEncoder m_audioEncoder; - JMediaRecorder::VideoEncoder m_videoEncoder; + AndroidMediaRecorder::OutputFormat m_outputFormat; + AndroidMediaRecorder::AudioEncoder m_audioEncoder; + AndroidMediaRecorder::VideoEncoder m_videoEncoder; QList<QSize> m_supportedResolutions; QList<qreal> m_supportedFramerates; diff --git a/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.cpp b/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.cpp index 79e0651a3..a239f510b 100644 --- a/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.cpp +++ b/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.cpp @@ -42,7 +42,7 @@ #include "qandroidimageencodercontrol.h" #include "qandroidcamerasession.h" -#include "jcamera.h" +#include "androidcamera.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.h b/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.h index 23e397d4d..7dcc884a9 100644 --- a/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.h +++ b/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.h @@ -69,4 +69,6 @@ private: QList<QSize> m_supportedResolutions; }; +QT_END_NAMESPACE + #endif // QANDROIDIMAGEENCODERCONTROL_H diff --git a/src/plugins/android/src/mediacapture/qandroidmediastoragelocation.cpp b/src/plugins/android/src/mediacapture/qandroidmediastoragelocation.cpp deleted file mode 100644 index 2bd3da195..000000000 --- a/src/plugins/android/src/mediacapture/qandroidmediastoragelocation.cpp +++ /dev/null @@ -1,130 +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 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$ -** -****************************************************************************/ - -#include "qandroidmediastoragelocation.h" - -#include "jmultimediautils.h" - -QT_BEGIN_NAMESPACE - -QAndroidMediaStorageLocation::QAndroidMediaStorageLocation() -{ -} - -QDir QAndroidMediaStorageLocation::defaultDir(CaptureSource source) const -{ - QStringList dirCandidates; - - if (source == Camera) - dirCandidates << JMultimediaUtils::getDefaultMediaDirectory(JMultimediaUtils::DCIM); - else - dirCandidates << JMultimediaUtils::getDefaultMediaDirectory(JMultimediaUtils::Sounds); - dirCandidates << QDir::homePath(); - dirCandidates << QDir::currentPath(); - dirCandidates << QDir::tempPath(); - - Q_FOREACH (const QString &path, dirCandidates) { - if (QFileInfo(path).isWritable()) - return QDir(path); - } - - return QDir(); -} - -QString QAndroidMediaStorageLocation::generateFileName(const QString &requestedName, - CaptureSource source, - const QString &prefix, - const QString &extension) const -{ - if (requestedName.isEmpty()) - return generateFileName(prefix, defaultDir(source), extension); - - QString path = requestedName; - - if (QFileInfo(path).isRelative()) - path = defaultDir(source).absoluteFilePath(path); - - if (QFileInfo(path).isDir()) - return generateFileName(prefix, QDir(path), extension); - - if (!path.endsWith(extension)) - path.append(QString(".%1").arg(extension)); - - return path; -} - -QString QAndroidMediaStorageLocation::generateFileName(const QString &prefix, - const QDir &dir, - const QString &extension) const -{ - QMutexLocker lock(&m_mutex); - - const QString lastMediaKey = dir.absolutePath() + QLatin1Char(' ') + prefix + QLatin1Char(' ') + extension; - qint64 lastMediaIndex = m_lastUsedIndex.value(lastMediaKey, 0); - - if (lastMediaIndex == 0) { - // first run, find the maximum media number during the fist capture - Q_FOREACH (const QString &fileName, dir.entryList(QStringList() << QString("%1*.%2").arg(prefix).arg(extension))) { - const qint64 mediaIndex = fileName.midRef(prefix.length(), fileName.size() - prefix.length() - extension.length() - 1).toInt(); - lastMediaIndex = qMax(lastMediaIndex, mediaIndex); - } - } - - // don't just rely on cached lastMediaIndex value, - // someone else may create a file after camera started - while (true) { - const QString name = QString("%1%2.%3").arg(prefix) - .arg(lastMediaIndex + 1, 8, 10, QLatin1Char('0')) - .arg(extension); - - const QString path = dir.absoluteFilePath(name); - if (!QFileInfo(path).exists()) { - m_lastUsedIndex[lastMediaKey] = lastMediaIndex + 1; - return path; - } - - lastMediaIndex++; - } - - return QString(); -} - -QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidmediastoragelocation.h b/src/plugins/android/src/mediacapture/qandroidmediastoragelocation.h deleted file mode 100644 index 2e63f3df5..000000000 --- a/src/plugins/android/src/mediacapture/qandroidmediastoragelocation.h +++ /dev/null @@ -1,75 +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 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$ -** -****************************************************************************/ - -#ifndef QANDROIDMEDIASTORAGELOCATION_H -#define QANDROIDMEDIASTORAGELOCATION_H - -#include <QCamera> -#include <QDir> -#include <QHash> -#include <QMutex> - -QT_BEGIN_NAMESPACE - -class QAndroidMediaStorageLocation -{ -public: - enum CaptureSource { - Camera, - Audio - }; - - QAndroidMediaStorageLocation(); - - QDir defaultDir(CaptureSource source) const; - - QString generateFileName(const QString &requestedName, CaptureSource source, const QString &prefix, const QString &extension) const; - QString generateFileName(const QString &prefix, const QDir &dir, const QString &extension) const; - -private: - mutable QHash<QString, qint64> m_lastUsedIndex; - - mutable QMutex m_mutex; -}; - -QT_END_NAMESPACE - -#endif // QANDROIDMEDIASTORAGELOCATION_H diff --git a/src/plugins/android/src/mediacapture/qandroidmediavideoprobecontrol.cpp b/src/plugins/android/src/mediacapture/qandroidmediavideoprobecontrol.cpp index a4ebc8fe4..8e0cf6d16 100644 --- a/src/plugins/android/src/mediacapture/qandroidmediavideoprobecontrol.cpp +++ b/src/plugins/android/src/mediacapture/qandroidmediavideoprobecontrol.cpp @@ -43,6 +43,8 @@ #include "qandroidmediavideoprobecontrol.h" #include <qvideoframe.h> +QT_BEGIN_NAMESPACE + QAndroidMediaVideoProbeControl::QAndroidMediaVideoProbeControl(QObject *parent) : QMediaVideoProbeControl(parent) { @@ -57,3 +59,5 @@ void QAndroidMediaVideoProbeControl::newFrameProbed(const QVideoFrame &frame) { emit videoFrameProbed(frame); } + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidmediavideoprobecontrol.h b/src/plugins/android/src/mediacapture/qandroidmediavideoprobecontrol.h index 7bb34d883..0a0007c9f 100644 --- a/src/plugins/android/src/mediacapture/qandroidmediavideoprobecontrol.h +++ b/src/plugins/android/src/mediacapture/qandroidmediavideoprobecontrol.h @@ -45,6 +45,8 @@ #include <qmediavideoprobecontrol.h> +QT_BEGIN_NAMESPACE + class QAndroidMediaVideoProbeControl : public QMediaVideoProbeControl { Q_OBJECT @@ -56,4 +58,6 @@ public: }; +QT_END_NAMESPACE + #endif // QANDROIDMEDIAVIDEOPROBECONTROL_H diff --git a/src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.cpp b/src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.cpp index 3fcb199f7..17a349d9d 100644 --- a/src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.cpp +++ b/src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.cpp @@ -42,7 +42,7 @@ #include "qandroidvideodeviceselectorcontrol.h" #include "qandroidcamerasession.h" -#include "jcamera.h" +#include "androidcamera.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp index f5614a57a..6817d65b0 100644 --- a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp +++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp @@ -40,24 +40,25 @@ ****************************************************************************/ #include "qandroidmediaplayercontrol.h" -#include "jmediaplayer.h" +#include "androidmediaplayer.h" #include "qandroidvideooutput.h" QT_BEGIN_NAMESPACE QAndroidMediaPlayerControl::QAndroidMediaPlayerControl(QObject *parent) : QMediaPlayerControl(parent), - mMediaPlayer(new JMediaPlayer), + mMediaPlayer(new AndroidMediaPlayer), mCurrentState(QMediaPlayer::StoppedState), mCurrentMediaStatus(QMediaPlayer::NoMedia), mMediaStream(0), mVideoOutput(0), mSeekable(true), mBufferPercent(-1), + mBufferFilled(false), mAudioAvailable(false), mVideoAvailable(false), mBuffering(false), - mState(JMediaPlayer::Uninitialized), + mState(AndroidMediaPlayer::Uninitialized), mPendingState(-1), mPendingPosition(-1), mPendingSetMedia(false), @@ -98,11 +99,11 @@ QMediaPlayer::MediaStatus QAndroidMediaPlayerControl::mediaStatus() const qint64 QAndroidMediaPlayerControl::duration() const { - if ((mState & (JMediaPlayer::Prepared - | JMediaPlayer::Started - | JMediaPlayer::Paused - | JMediaPlayer::Stopped - | JMediaPlayer::PlaybackCompleted)) == 0) { + if ((mState & (AndroidMediaPlayer::Prepared + | AndroidMediaPlayer::Started + | AndroidMediaPlayer::Paused + | AndroidMediaPlayer::Stopped + | AndroidMediaPlayer::PlaybackCompleted)) == 0) { return 0; } @@ -114,13 +115,13 @@ qint64 QAndroidMediaPlayerControl::position() const if (mCurrentMediaStatus == QMediaPlayer::EndOfMedia) return duration(); - if ((mState & (JMediaPlayer::Idle - | JMediaPlayer::Initialized - | JMediaPlayer::Prepared - | JMediaPlayer::Started - | JMediaPlayer::Paused - | JMediaPlayer::Stopped - | JMediaPlayer::PlaybackCompleted)) == 0) { + if ((mState & (AndroidMediaPlayer::Idle + | AndroidMediaPlayer::Initialized + | AndroidMediaPlayer::Prepared + | AndroidMediaPlayer::Started + | AndroidMediaPlayer::Paused + | AndroidMediaPlayer::Stopped + | AndroidMediaPlayer::PlaybackCompleted)) == 0) { return (mPendingPosition == -1) ? 0 : mPendingPosition; } @@ -134,10 +135,10 @@ void QAndroidMediaPlayerControl::setPosition(qint64 position) const int seekPosition = (position > INT_MAX) ? INT_MAX : position; - if ((mState & (JMediaPlayer::Prepared - | JMediaPlayer::Started - | JMediaPlayer::Paused - | JMediaPlayer::PlaybackCompleted)) == 0) { + if ((mState & (AndroidMediaPlayer::Prepared + | AndroidMediaPlayer::Started + | AndroidMediaPlayer::Paused + | AndroidMediaPlayer::PlaybackCompleted)) == 0) { if (mPendingPosition != seekPosition) { mPendingPosition = seekPosition; Q_EMIT positionChanged(seekPosition); @@ -164,13 +165,13 @@ int QAndroidMediaPlayerControl::volume() const void QAndroidMediaPlayerControl::setVolume(int volume) { - if ((mState & (JMediaPlayer::Idle - | JMediaPlayer::Initialized - | JMediaPlayer::Stopped - | JMediaPlayer::Prepared - | JMediaPlayer::Started - | JMediaPlayer::Paused - | JMediaPlayer::PlaybackCompleted)) == 0) { + if ((mState & (AndroidMediaPlayer::Idle + | AndroidMediaPlayer::Initialized + | AndroidMediaPlayer::Stopped + | AndroidMediaPlayer::Prepared + | AndroidMediaPlayer::Started + | AndroidMediaPlayer::Paused + | AndroidMediaPlayer::PlaybackCompleted)) == 0) { if (mPendingVolume != volume) { mPendingVolume = volume; Q_EMIT volumeChanged(volume); @@ -195,13 +196,13 @@ bool QAndroidMediaPlayerControl::isMuted() const void QAndroidMediaPlayerControl::setMuted(bool muted) { - if ((mState & (JMediaPlayer::Idle - | JMediaPlayer::Initialized - | JMediaPlayer::Stopped - | JMediaPlayer::Prepared - | JMediaPlayer::Started - | JMediaPlayer::Paused - | JMediaPlayer::PlaybackCompleted)) == 0) { + if ((mState & (AndroidMediaPlayer::Idle + | AndroidMediaPlayer::Initialized + | AndroidMediaPlayer::Stopped + | AndroidMediaPlayer::Prepared + | AndroidMediaPlayer::Started + | AndroidMediaPlayer::Paused + | AndroidMediaPlayer::PlaybackCompleted)) == 0) { if (mPendingMute != muted) { mPendingMute = muted; Q_EMIT mutedChanged(muted); @@ -221,7 +222,7 @@ void QAndroidMediaPlayerControl::setMuted(bool muted) int QAndroidMediaPlayerControl::bufferStatus() const { - return mBufferPercent; + return mBufferFilled ? 100 : 0; } bool QAndroidMediaPlayerControl::isAudioAvailable() const @@ -290,7 +291,7 @@ void QAndroidMediaPlayerControl::setMedia(const QMediaContent &mediaContent, } // Release the mediaplayer if it's not in in Idle or Uninitialized state - if ((mState & (JMediaPlayer::Idle | JMediaPlayer::Uninitialized)) == 0) + if ((mState & (AndroidMediaPlayer::Idle | AndroidMediaPlayer::Uninitialized)) == 0) mMediaPlayer->release(); if (mediaContent.isNull()) { @@ -311,7 +312,7 @@ void QAndroidMediaPlayerControl::setMedia(const QMediaContent &mediaContent, const QString path = url.toString().mid(3); mTempFile.reset(QTemporaryFile::createNativeFile(path)); if (!mTempFile.isNull()) - mediaPath = QLatin1String("file://") + mTempFile->fileName(); + mediaPath = QStringLiteral("file://") + mTempFile->fileName(); } else { mediaPath = url.toString(); } @@ -319,8 +320,8 @@ void QAndroidMediaPlayerControl::setMedia(const QMediaContent &mediaContent, if (mVideoSize.isValid() && mVideoOutput) mVideoOutput->setVideoSize(mVideoSize); - if (!mMediaPlayer->display() && mVideoOutput) - mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder()); + if ((mMediaPlayer->display() == 0) && mVideoOutput) + mMediaPlayer->setDisplay(mVideoOutput->surfaceTexture()); mMediaPlayer->setDataSource(mediaPath); mMediaPlayer->prepareAsync(); @@ -344,7 +345,7 @@ void QAndroidMediaPlayerControl::setVideoOutput(QObject *videoOutput) return; if (mVideoOutput->isReady()) - mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder()); + mMediaPlayer->setDisplay(mVideoOutput->surfaceTexture()); connect(videoOutput, SIGNAL(readyChanged(bool)), this, SLOT(onVideoOutputReady(bool))); } @@ -352,16 +353,16 @@ void QAndroidMediaPlayerControl::setVideoOutput(QObject *videoOutput) void QAndroidMediaPlayerControl::play() { // We need to prepare the mediaplayer again. - if ((mState & JMediaPlayer::Stopped) && !mMediaContent.isNull()) { + if ((mState & AndroidMediaPlayer::Stopped) && !mMediaContent.isNull()) { setMedia(mMediaContent, mMediaStream); } setState(QMediaPlayer::PlayingState); - if ((mState & (JMediaPlayer::Prepared - | JMediaPlayer::Started - | JMediaPlayer::Paused - | JMediaPlayer::PlaybackCompleted)) == 0) { + if ((mState & (AndroidMediaPlayer::Prepared + | AndroidMediaPlayer::Started + | AndroidMediaPlayer::Paused + | AndroidMediaPlayer::PlaybackCompleted)) == 0) { mPendingState = QMediaPlayer::PlayingState; return; } @@ -373,9 +374,9 @@ void QAndroidMediaPlayerControl::pause() { setState(QMediaPlayer::PausedState); - if ((mState & (JMediaPlayer::Started - | JMediaPlayer::Paused - | JMediaPlayer::PlaybackCompleted)) == 0) { + if ((mState & (AndroidMediaPlayer::Started + | AndroidMediaPlayer::Paused + | AndroidMediaPlayer::PlaybackCompleted)) == 0) { mPendingState = QMediaPlayer::PausedState; return; } @@ -387,12 +388,12 @@ void QAndroidMediaPlayerControl::stop() { setState(QMediaPlayer::StoppedState); - if ((mState & (JMediaPlayer::Prepared - | JMediaPlayer::Started - | JMediaPlayer::Stopped - | JMediaPlayer::Paused - | JMediaPlayer::PlaybackCompleted)) == 0) { - if ((mState & (JMediaPlayer::Idle | JMediaPlayer::Uninitialized | JMediaPlayer::Error)) == 0) + if ((mState & (AndroidMediaPlayer::Prepared + | AndroidMediaPlayer::Started + | AndroidMediaPlayer::Stopped + | AndroidMediaPlayer::Paused + | AndroidMediaPlayer::PlaybackCompleted)) == 0) { + if ((mState & (AndroidMediaPlayer::Idle | AndroidMediaPlayer::Uninitialized | AndroidMediaPlayer::Error)) == 0) mPendingState = QMediaPlayer::StoppedState; return; } @@ -404,28 +405,28 @@ void QAndroidMediaPlayerControl::onInfo(qint32 what, qint32 extra) { Q_UNUSED(extra); switch (what) { - case JMediaPlayer::MEDIA_INFO_UNKNOWN: + case AndroidMediaPlayer::MEDIA_INFO_UNKNOWN: break; - case JMediaPlayer::MEDIA_INFO_VIDEO_TRACK_LAGGING: + case AndroidMediaPlayer::MEDIA_INFO_VIDEO_TRACK_LAGGING: // IGNORE break; - case JMediaPlayer::MEDIA_INFO_VIDEO_RENDERING_START: + case AndroidMediaPlayer::MEDIA_INFO_VIDEO_RENDERING_START: break; - case JMediaPlayer::MEDIA_INFO_BUFFERING_START: + case AndroidMediaPlayer::MEDIA_INFO_BUFFERING_START: mPendingState = mCurrentState; setState(QMediaPlayer::PausedState); setMediaStatus(QMediaPlayer::StalledMedia); break; - case JMediaPlayer::MEDIA_INFO_BUFFERING_END: + case AndroidMediaPlayer::MEDIA_INFO_BUFFERING_END: if (mCurrentState != QMediaPlayer::StoppedState) flushPendingStates(); break; - case JMediaPlayer::MEDIA_INFO_BAD_INTERLEAVING: + case AndroidMediaPlayer::MEDIA_INFO_BAD_INTERLEAVING: break; - case JMediaPlayer::MEDIA_INFO_NOT_SEEKABLE: + case AndroidMediaPlayer::MEDIA_INFO_NOT_SEEKABLE: setSeekable(false); break; - case JMediaPlayer::MEDIA_INFO_METADATA_UPDATE: + case AndroidMediaPlayer::MEDIA_INFO_METADATA_UPDATE: Q_EMIT metaDataUpdated(); break; } @@ -437,44 +438,44 @@ void QAndroidMediaPlayerControl::onError(qint32 what, qint32 extra) QMediaPlayer::Error error = QMediaPlayer::ResourceError; switch (what) { - case JMediaPlayer::MEDIA_ERROR_UNKNOWN: + case AndroidMediaPlayer::MEDIA_ERROR_UNKNOWN: errorString = QLatin1String("Error:"); break; - case JMediaPlayer::MEDIA_ERROR_SERVER_DIED: + case AndroidMediaPlayer::MEDIA_ERROR_SERVER_DIED: errorString = QLatin1String("Error: Server died"); error = QMediaPlayer::ServiceMissingError; break; - case JMediaPlayer::MEDIA_ERROR_INVALID_STATE: + case AndroidMediaPlayer::MEDIA_ERROR_INVALID_STATE: errorString = QLatin1String("Error: Invalid state"); error = QMediaPlayer::ServiceMissingError; break; } switch (extra) { - case JMediaPlayer::MEDIA_ERROR_IO: // Network OR file error + case AndroidMediaPlayer::MEDIA_ERROR_IO: // Network OR file error errorString += QLatin1String(" (I/O operation failed)"); error = QMediaPlayer::NetworkError; setMediaStatus(QMediaPlayer::InvalidMedia); break; - case JMediaPlayer::MEDIA_ERROR_MALFORMED: + case AndroidMediaPlayer::MEDIA_ERROR_MALFORMED: errorString += QLatin1String(" (Malformed bitstream)"); error = QMediaPlayer::FormatError; setMediaStatus(QMediaPlayer::InvalidMedia); break; - case JMediaPlayer::MEDIA_ERROR_UNSUPPORTED: + case AndroidMediaPlayer::MEDIA_ERROR_UNSUPPORTED: errorString += QLatin1String(" (Unsupported media)"); error = QMediaPlayer::FormatError; setMediaStatus(QMediaPlayer::InvalidMedia); break; - case JMediaPlayer::MEDIA_ERROR_TIMED_OUT: + case AndroidMediaPlayer::MEDIA_ERROR_TIMED_OUT: errorString += QLatin1String(" (Timed out)"); break; - case JMediaPlayer::MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK: + case AndroidMediaPlayer::MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK: errorString += QLatin1String(" (Unable to start progressive playback')"); error = QMediaPlayer::FormatError; setMediaStatus(QMediaPlayer::InvalidMedia); break; - case JMediaPlayer::MEDIA_ERROR_BAD_THINGS_ARE_GOING_TO_HAPPEN: + case AndroidMediaPlayer::MEDIA_ERROR_BAD_THINGS_ARE_GOING_TO_HAPPEN: errorString += QLatin1String(" (Unknown error/Insufficient resources)"); error = QMediaPlayer::ServiceMissingError; break; @@ -487,7 +488,6 @@ void QAndroidMediaPlayerControl::onBufferingChanged(qint32 percent) { mBuffering = percent != 100; mBufferPercent = percent; - Q_EMIT bufferStatusChanged(mBufferPercent); updateAvailablePlaybackRanges(); @@ -512,21 +512,21 @@ void QAndroidMediaPlayerControl::onVideoSizeChanged(qint32 width, qint32 height) void QAndroidMediaPlayerControl::onStateChanged(qint32 state) { // If reloading, don't report state changes unless the new state is Prepared or Error. - if ((mState & JMediaPlayer::Stopped) - && (state & (JMediaPlayer::Prepared | JMediaPlayer::Error | JMediaPlayer::Uninitialized)) == 0) { + if ((mState & AndroidMediaPlayer::Stopped) + && (state & (AndroidMediaPlayer::Prepared | AndroidMediaPlayer::Error | AndroidMediaPlayer::Uninitialized)) == 0) { return; } mState = state; switch (mState) { - case JMediaPlayer::Idle: + case AndroidMediaPlayer::Idle: break; - case JMediaPlayer::Initialized: + case AndroidMediaPlayer::Initialized: break; - case JMediaPlayer::Preparing: + case AndroidMediaPlayer::Preparing: setMediaStatus(QMediaPlayer::LoadingMedia); break; - case JMediaPlayer::Prepared: + case AndroidMediaPlayer::Prepared: setMediaStatus(QMediaPlayer::LoadedMedia); if (mBuffering) { setMediaStatus(mBufferPercent == 100 ? QMediaPlayer::BufferedMedia @@ -537,7 +537,7 @@ void QAndroidMediaPlayerControl::onStateChanged(qint32 state) setAudioAvailable(true); flushPendingStates(); break; - case JMediaPlayer::Started: + case AndroidMediaPlayer::Started: setState(QMediaPlayer::PlayingState); if (mBuffering) { setMediaStatus(mBufferPercent == 100 ? QMediaPlayer::BufferedMedia @@ -546,25 +546,25 @@ void QAndroidMediaPlayerControl::onStateChanged(qint32 state) setMediaStatus(QMediaPlayer::BufferedMedia); } break; - case JMediaPlayer::Paused: + case AndroidMediaPlayer::Paused: setState(QMediaPlayer::PausedState); break; - case JMediaPlayer::Error: + case AndroidMediaPlayer::Error: setState(QMediaPlayer::StoppedState); setMediaStatus(QMediaPlayer::UnknownMediaStatus); mMediaPlayer->release(); break; - case JMediaPlayer::Stopped: + case AndroidMediaPlayer::Stopped: setState(QMediaPlayer::StoppedState); setMediaStatus(QMediaPlayer::LoadedMedia); setPosition(0); break; - case JMediaPlayer::PlaybackCompleted: + case AndroidMediaPlayer::PlaybackCompleted: setState(QMediaPlayer::StoppedState); setPosition(0); setMediaStatus(QMediaPlayer::EndOfMedia); break; - case JMediaPlayer::Uninitialized: + case AndroidMediaPlayer::Uninitialized: // reset some properties resetBufferingProgress(); mPendingPosition = -1; @@ -579,7 +579,7 @@ void QAndroidMediaPlayerControl::onStateChanged(qint32 state) break; } - if ((mState & (JMediaPlayer::Stopped | JMediaPlayer::Uninitialized)) != 0) { + if ((mState & (AndroidMediaPlayer::Stopped | AndroidMediaPlayer::Uninitialized)) != 0) { mMediaPlayer->setDisplay(0); if (mVideoOutput) { mVideoOutput->stop(); @@ -590,8 +590,8 @@ void QAndroidMediaPlayerControl::onStateChanged(qint32 state) void QAndroidMediaPlayerControl::onVideoOutputReady(bool ready) { - if (!mMediaPlayer->display() && mVideoOutput && ready) - mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder()); + if ((mMediaPlayer->display() == 0) && mVideoOutput && ready) + mMediaPlayer->setDisplay(mVideoOutput->surfaceTexture()); flushPendingStates(); } @@ -621,6 +621,8 @@ void QAndroidMediaPlayerControl::setMediaStatus(QMediaPlayer::MediaStatus status mCurrentMediaStatus = status; Q_EMIT mediaStatusChanged(mCurrentMediaStatus); + + updateBufferStatus(); } void QAndroidMediaPlayerControl::setSeekable(bool seekable) @@ -658,7 +660,6 @@ void QAndroidMediaPlayerControl::resetBufferingProgress() mBuffering = false; mBufferPercent = 0; mAvailablePlaybackRange = QMediaTimeRange(); - Q_EMIT bufferStatusChanged(mBufferPercent); } void QAndroidMediaPlayerControl::flushPendingStates() @@ -694,4 +695,15 @@ void QAndroidMediaPlayerControl::flushPendingStates() } } +void QAndroidMediaPlayerControl::updateBufferStatus() +{ + bool bufferFilled = (mCurrentMediaStatus == QMediaPlayer::BufferedMedia + || mCurrentMediaStatus == QMediaPlayer::BufferingMedia); + + if (mBufferFilled != bufferFilled) { + mBufferFilled = bufferFilled; + Q_EMIT bufferStatusChanged(bufferStatus()); + } +} + QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h index 1be3b4428..5744c11b8 100644 --- a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h +++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h @@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE -class JMediaPlayer; +class AndroidMediaPlayer; class QAndroidVideoOutput; class QAndroidMediaPlayerControl : public QMediaPlayerControl @@ -98,7 +98,7 @@ private Q_SLOTS: void onStateChanged(qint32 state); private: - JMediaPlayer *mMediaPlayer; + AndroidMediaPlayer *mMediaPlayer; QMediaPlayer::State mCurrentState; QMediaPlayer::MediaStatus mCurrentMediaStatus; QMediaContent mMediaContent; @@ -106,6 +106,7 @@ private: QAndroidVideoOutput *mVideoOutput; bool mSeekable; int mBufferPercent; + bool mBufferFilled; bool mAudioAvailable; bool mVideoAvailable; QSize mVideoSize; @@ -127,6 +128,7 @@ private: void updateAvailablePlaybackRanges(); void resetBufferingProgress(); void flushPendingStates(); + void updateBufferStatus(); }; QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp index dcc3dfbe0..82bd74997 100644 --- a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp +++ b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp @@ -41,7 +41,7 @@ #include "qandroidmetadatareadercontrol.h" -#include "jmediametadataretriever.h" +#include "androidmediametadataretriever.h" #include <QtMultimedia/qmediametadata.h> #include <qsize.h> #include <QDate> @@ -74,7 +74,7 @@ static const char* qt_ID3GenreNames[] = QAndroidMetaDataReaderControl::QAndroidMetaDataReaderControl(QObject *parent) : QMetaDataReaderControl(parent) , m_available(false) - , m_retriever(new JMediaMetadataRetriever) + , m_retriever(new AndroidMediaMetadataRetriever) { } @@ -124,56 +124,56 @@ void QAndroidMetaDataReaderControl::updateData() if (!m_mediaContent.isNull()) { if (m_retriever->setDataSource(m_mediaContent.canonicalUrl())) { - QString mimeType = m_retriever->extractMetadata(JMediaMetadataRetriever::MimeType); + QString mimeType = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::MimeType); if (!mimeType.isNull()) m_metadata.insert(QMediaMetaData::MediaType, mimeType); - bool isVideo = !m_retriever->extractMetadata(JMediaMetadataRetriever::HasVideo).isNull() + bool isVideo = !m_retriever->extractMetadata(AndroidMediaMetadataRetriever::HasVideo).isNull() || mimeType.startsWith(QStringLiteral("video")); - QString string = m_retriever->extractMetadata(JMediaMetadataRetriever::Album); + QString string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::Album); if (!string.isNull()) m_metadata.insert(QMediaMetaData::AlbumTitle, string); - string = m_retriever->extractMetadata(JMediaMetadataRetriever::AlbumArtist); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::AlbumArtist); if (!string.isNull()) m_metadata.insert(QMediaMetaData::AlbumArtist, string); - string = m_retriever->extractMetadata(JMediaMetadataRetriever::Artist); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::Artist); if (!string.isNull()) { m_metadata.insert(isVideo ? QMediaMetaData::LeadPerformer : QMediaMetaData::ContributingArtist, string.split('/', QString::SkipEmptyParts)); } - string = m_retriever->extractMetadata(JMediaMetadataRetriever::Author); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::Author); if (!string.isNull()) m_metadata.insert(QMediaMetaData::Author, string.split('/', QString::SkipEmptyParts)); - string = m_retriever->extractMetadata(JMediaMetadataRetriever::Bitrate); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::Bitrate); if (!string.isNull()) { m_metadata.insert(isVideo ? QMediaMetaData::VideoBitRate : QMediaMetaData::AudioBitRate, string.toInt()); } - string = m_retriever->extractMetadata(JMediaMetadataRetriever::CDTrackNumber); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::CDTrackNumber); if (!string.isNull()) m_metadata.insert(QMediaMetaData::TrackNumber, string.toInt()); - string = m_retriever->extractMetadata(JMediaMetadataRetriever::Composer); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::Composer); if (!string.isNull()) m_metadata.insert(QMediaMetaData::Composer, string.split('/', QString::SkipEmptyParts)); - string = m_retriever->extractMetadata(JMediaMetadataRetriever::Date); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::Date); if (!string.isNull()) m_metadata.insert(QMediaMetaData::Date, QDateTime::fromString(string, QStringLiteral("yyyyMMddTHHmmss.zzzZ")).date()); - string = m_retriever->extractMetadata(JMediaMetadataRetriever::Duration); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::Duration); if (!string.isNull()) m_metadata.insert(QMediaMetaData::Duration, string.toLongLong()); - string = m_retriever->extractMetadata(JMediaMetadataRetriever::Genre); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::Genre); if (!string.isNull()) { // The genre can be returned as an ID3v2 id, get the name for it in that case if (string.startsWith('(') && string.endsWith(')')) { @@ -185,22 +185,22 @@ void QAndroidMetaDataReaderControl::updateData() m_metadata.insert(QMediaMetaData::Genre, string); } - string = m_retriever->extractMetadata(JMediaMetadataRetriever::Title); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::Title); if (!string.isNull()) m_metadata.insert(QMediaMetaData::Title, string); - string = m_retriever->extractMetadata(JMediaMetadataRetriever::VideoHeight); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::VideoHeight); if (!string.isNull()) { int height = string.toInt(); - int width = m_retriever->extractMetadata(JMediaMetadataRetriever::VideoWidth).toInt(); + int width = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::VideoWidth).toInt(); m_metadata.insert(QMediaMetaData::Resolution, QSize(width, height)); } - string = m_retriever->extractMetadata(JMediaMetadataRetriever::Writer); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::Writer); if (!string.isNull()) m_metadata.insert(QMediaMetaData::Writer, string.split('/', QString::SkipEmptyParts)); - string = m_retriever->extractMetadata(JMediaMetadataRetriever::Year); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::Year); if (!string.isNull()) m_metadata.insert(QMediaMetaData::Year, string.toInt()); } diff --git a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h index 7ea736ffd..67b92f1eb 100644 --- a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h +++ b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h @@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE -class JMediaMetadataRetriever; +class AndroidMediaMetadataRetriever; class QAndroidMetaDataReaderControl : public QMetaDataReaderControl { @@ -72,7 +72,7 @@ private: bool m_available; QVariantMap m_metadata; - JMediaMetadataRetriever *m_retriever; + AndroidMediaMetadataRetriever *m_retriever; }; QT_END_NAMESPACE diff --git a/src/plugins/android/src/qandroidmediaserviceplugin.cpp b/src/plugins/android/src/qandroidmediaserviceplugin.cpp index 0af43210f..4d777ce97 100644 --- a/src/plugins/android/src/qandroidmediaserviceplugin.cpp +++ b/src/plugins/android/src/qandroidmediaserviceplugin.cpp @@ -46,11 +46,11 @@ #include "qandroidaudioinputselectorcontrol.h" #include "qandroidcamerainfocontrol.h" #include "qandroidcamerasession.h" -#include "jmediaplayer.h" -#include "jsurfacetexture.h" -#include "jcamera.h" -#include "jmultimediautils.h" -#include "jmediarecorder.h" +#include "androidmediaplayer.h" +#include "androidsurfacetexture.h" +#include "androidcamera.h" +#include "androidmultimediautils.h" +#include "androidmediarecorder.h" #include <qdebug.h> QT_BEGIN_NAMESPACE @@ -147,9 +147,12 @@ int QAndroidMediaServicePlugin::cameraOrientation(const QByteArray &device) cons return QAndroidCameraInfoControl::orientation(device); } +QT_END_NAMESPACE +#ifndef Q_OS_ANDROID_NO_SDK Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/) { + QT_USE_NAMESPACE typedef union { JNIEnv *nativeEnvironment; void *venv; @@ -163,15 +166,14 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/) JNIEnv *jniEnv = uenv.nativeEnvironment; - if (!JMediaPlayer::initJNI(jniEnv) || - !JCamera::initJNI(jniEnv) || - !JMediaRecorder::initJNI(jniEnv)) { + if (!AndroidMediaPlayer::initJNI(jniEnv) || + !AndroidCamera::initJNI(jniEnv) || + !AndroidMediaRecorder::initJNI(jniEnv)) { return JNI_ERR; } - JSurfaceTexture::initJNI(jniEnv); + AndroidSurfaceTexture::initJNI(jniEnv); return JNI_VERSION_1_4; } - -QT_END_NAMESPACE +#endif // Q_OS_ANDROID_NO_SDK diff --git a/src/plugins/android/src/src.pro b/src/plugins/android/src/src.pro index d071f6fcd..6a472a0a8 100644 --- a/src/plugins/android/src/src.pro +++ b/src/plugins/android/src/src.pro @@ -11,7 +11,7 @@ HEADERS += \ SOURCES += \ qandroidmediaserviceplugin.cpp -include (wrappers/wrappers.pri) +include (wrappers/jni/jni.pri) include (common/common.pri) include (mediaplayer/mediaplayer.pri) include (mediacapture/mediacapture.pri) diff --git a/src/plugins/android/src/wrappers/jcamera.cpp b/src/plugins/android/src/wrappers/jni/androidcamera.cpp index b0e9f89f3..c917bf2b7 100644 --- a/src/plugins/android/src/wrappers/jcamera.cpp +++ b/src/plugins/android/src/wrappers/jni/androidcamera.cpp @@ -39,21 +39,22 @@ ** ****************************************************************************/ -#include "jcamera.h" +#include "androidcamera.h" +#include "androidsurfacetexture.h" +#include "qandroidmultimediautils.h" -#include <QtCore/private/qjni_p.h> #include <qstringlist.h> #include <qdebug.h> -#include "qandroidmultimediautils.h" -#include <qthread.h> #include <qmutex.h> #include <QtCore/private/qjnihelpers_p.h> +#include <QtCore/qthread.h> QT_BEGIN_NAMESPACE -static jclass g_qtCameraClass = 0; -static QMap<int, JCamera*> g_objectMap; -static QMutex g_objectMapMutex; +static jclass g_qtCameraListenerClass = 0; +static QMutex g_cameraMapMutex; +typedef QMap<int, AndroidCamera *> CameraMap; +Q_GLOBAL_STATIC(CameraMap, g_cameraMap) static QRect areaToRect(jobject areaObj) { @@ -79,34 +80,30 @@ static QJNIObjectPrivate rectToArea(const QRect &rect) return area; } -// native method for QtCamera.java +// native method for QtCameraLisener.java static void notifyAutoFocusComplete(JNIEnv* , jobject, int id, jboolean success) { - g_objectMapMutex.lock(); - JCamera *obj = g_objectMap.value(id, 0); - g_objectMapMutex.unlock(); + QMutexLocker locker(&g_cameraMapMutex); + AndroidCamera *obj = g_cameraMap->value(id, 0); if (obj) Q_EMIT obj->autoFocusComplete(success); } static void notifyPictureExposed(JNIEnv* , jobject, int id) { - g_objectMapMutex.lock(); - JCamera *obj = g_objectMap.value(id, 0); - g_objectMapMutex.unlock(); + QMutexLocker locker(&g_cameraMapMutex); + AndroidCamera *obj = g_cameraMap->value(id, 0); if (obj) Q_EMIT obj->pictureExposed(); } static void notifyPictureCaptured(JNIEnv *env, jobject, int id, jbyteArray data) { - g_objectMapMutex.lock(); - JCamera *obj = g_objectMap.value(id, 0); - g_objectMapMutex.unlock(); + QMutexLocker locker(&g_cameraMapMutex); + AndroidCamera *obj = g_cameraMap->value(id, 0); if (obj) { - QByteArray bytes; - int arrayLength = env->GetArrayLength(data); - bytes.resize(arrayLength); + const int arrayLength = env->GetArrayLength(data); + QByteArray bytes(arrayLength, Qt::Uninitialized); env->GetByteArrayRegion(data, 0, arrayLength, (jbyte*)bytes.data()); Q_EMIT obj->pictureCaptured(bytes); } @@ -114,56 +111,39 @@ static void notifyPictureCaptured(JNIEnv *env, jobject, int id, jbyteArray data) static void notifyFrameFetched(JNIEnv *env, jobject, int id, jbyteArray data) { - g_objectMapMutex.lock(); - JCamera *obj = g_objectMap.value(id, 0); - g_objectMapMutex.unlock(); + QMutexLocker locker(&g_cameraMapMutex); + AndroidCamera *obj = g_cameraMap->value(id, 0); if (obj) { - QByteArray bytes; - int arrayLength = env->GetArrayLength(data); - bytes.resize(arrayLength); + const int arrayLength = env->GetArrayLength(data); + QByteArray bytes(arrayLength, Qt::Uninitialized); env->GetByteArrayRegion(data, 0, arrayLength, (jbyte*)bytes.data()); Q_EMIT obj->frameFetched(bytes); } } -class JCameraInstantiator : public QObject +class AndroidCameraPrivate : public QObject { Q_OBJECT public: - JCameraInstantiator() : QObject(0) {} - QJNIObjectPrivate result() {return lastCamera;} -public slots: - void openCamera(int cameraId) - { - QJNIEnvironmentPrivate env; - lastCamera = QJNIObjectPrivate::callStaticObjectMethod(g_qtCameraClass, - "open", - "(I)Lorg/qtproject/qt5/android/multimedia/QtCamera;", - cameraId); - } -private: - QJNIObjectPrivate lastCamera; -}; + AndroidCameraPrivate(); + ~AndroidCameraPrivate(); -class JCameraWorker : public QObject -{ - Q_OBJECT - friend class JCamera; - - JCameraWorker(JCamera *camera, int cameraId, jobject cam, QThread *workerThread); - ~JCameraWorker(); + Q_INVOKABLE bool init(int cameraId); Q_INVOKABLE void release(); + Q_INVOKABLE void lock(); + Q_INVOKABLE void unlock(); + Q_INVOKABLE void reconnect(); - Q_INVOKABLE JCamera::CameraFacing getFacing(); + Q_INVOKABLE AndroidCamera::CameraFacing getFacing(); Q_INVOKABLE int getNativeOrientation(); Q_INVOKABLE QSize getPreferredPreviewSizeForVideo(); Q_INVOKABLE QList<QSize> getSupportedPreviewSizes(); - Q_INVOKABLE JCamera::ImageFormat getPreviewFormat(); - Q_INVOKABLE void setPreviewFormat(JCamera::ImageFormat fmt); + Q_INVOKABLE AndroidCamera::ImageFormat getPreviewFormat(); + Q_INVOKABLE void setPreviewFormat(AndroidCamera::ImageFormat fmt); Q_INVOKABLE QSize previewSize() const { return m_previewSize; } Q_INVOKABLE void updatePreviewSize(); @@ -186,6 +166,7 @@ class JCameraWorker : public QObject Q_INVOKABLE void setFocusAreas(const QList<QRect> &areas); Q_INVOKABLE void autoFocus(); + Q_INVOKABLE void cancelAutoFocus(); Q_INVOKABLE bool isAutoExposureLockSupported(); Q_INVOKABLE bool getAutoExposureLock(); @@ -216,26 +197,23 @@ class JCameraWorker : public QObject Q_INVOKABLE void startPreview(); Q_INVOKABLE void stopPreview(); + Q_INVOKABLE void takePicture(); + Q_INVOKABLE void fetchEachFrame(bool fetch); Q_INVOKABLE void fetchLastPreviewFrame(); Q_INVOKABLE void applyParameters(); Q_INVOKABLE QStringList callParametersStringListMethod(const QByteArray &methodName); - Q_INVOKABLE void callVoidMethod(const QByteArray &methodName); int m_cameraId; - QJNIObjectPrivate m_info; - QJNIObjectPrivate m_parameters; - + QMutex m_parametersMutex; QSize m_previewSize; int m_rotation; - - JCamera *q; - - QThread *m_workerThread; - QMutex m_parametersMutex; + QJNIObjectPrivate m_info; + QJNIObjectPrivate m_parameters; QJNIObjectPrivate m_camera; + QJNIObjectPrivate m_cameraListener; Q_SIGNALS: void previewSizeChanged(); @@ -249,122 +227,137 @@ Q_SIGNALS: void previewFetched(const QByteArray &preview); }; +AndroidCamera::AndroidCamera(AndroidCameraPrivate *d, QThread *worker) + : QObject(), + d_ptr(d), + m_worker(worker) - -JCamera::JCamera(int cameraId, jobject cam, QThread *workerThread) - : QObject() { qRegisterMetaType<QList<int> >(); qRegisterMetaType<QList<QSize> >(); qRegisterMetaType<QList<QRect> >(); - d = new JCameraWorker(this, cameraId, cam, workerThread); - connect(d, &JCameraWorker::previewSizeChanged, this, &JCamera::previewSizeChanged); - connect(d, &JCameraWorker::previewStarted, this, &JCamera::previewStarted); - connect(d, &JCameraWorker::previewStopped, this, &JCamera::previewStopped); - connect(d, &JCameraWorker::autoFocusStarted, this, &JCamera::autoFocusStarted); - connect(d, &JCameraWorker::whiteBalanceChanged, this, &JCamera::whiteBalanceChanged); - connect(d, &JCameraWorker::previewFetched, this, &JCamera::previewFetched); + connect(d, &AndroidCameraPrivate::previewSizeChanged, this, &AndroidCamera::previewSizeChanged); + connect(d, &AndroidCameraPrivate::previewStarted, this, &AndroidCamera::previewStarted); + connect(d, &AndroidCameraPrivate::previewStopped, this, &AndroidCamera::previewStopped); + connect(d, &AndroidCameraPrivate::autoFocusStarted, this, &AndroidCamera::autoFocusStarted); + connect(d, &AndroidCameraPrivate::whiteBalanceChanged, this, &AndroidCamera::whiteBalanceChanged); + connect(d, &AndroidCameraPrivate::previewFetched, this, &AndroidCamera::previewFetched); } -JCamera::~JCamera() +AndroidCamera::~AndroidCamera() { + Q_D(AndroidCamera); if (d->m_camera.isValid()) { - g_objectMapMutex.lock(); - g_objectMap.remove(d->m_cameraId); - g_objectMapMutex.unlock(); + g_cameraMapMutex.lock(); + g_cameraMap->remove(d->m_cameraId); + g_cameraMapMutex.unlock(); } - d->deleteLater(); -} - -JCamera *JCamera::open(int cameraId) -{ - QThread *cameraThread = new QThread; - connect(cameraThread, &QThread::finished, cameraThread, &QThread::deleteLater); - cameraThread->start(); - JCameraInstantiator *instantiator = new JCameraInstantiator; - instantiator->moveToThread(cameraThread); - QMetaObject::invokeMethod(instantiator, "openCamera", - Qt::BlockingQueuedConnection, - Q_ARG(int, cameraId)); - QJNIObjectPrivate camera = instantiator->result(); - delete instantiator; - if (!camera.isValid()) { - cameraThread->terminate(); - delete cameraThread; + release(); + m_worker->exit(); + m_worker->wait(5000); +} + +AndroidCamera *AndroidCamera::open(int cameraId) +{ + AndroidCameraPrivate *d = new AndroidCameraPrivate(); + QThread *worker = new QThread; + worker->start(); + d->moveToThread(worker); + connect(worker, &QThread::finished, d, &AndroidCameraPrivate::deleteLater); + bool ok = false; + QMetaObject::invokeMethod(d, "init", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, ok), Q_ARG(int, cameraId)); + if (!ok) { + worker->quit(); + worker->wait(5000); + delete d; + delete worker; return 0; - } else { - return new JCamera(cameraId, camera.object(), cameraThread); } + + AndroidCamera *q = new AndroidCamera(d, worker); + g_cameraMapMutex.lock(); + g_cameraMap->insert(cameraId, q); + g_cameraMapMutex.unlock(); + return q; } -int JCamera::cameraId() const +int AndroidCamera::cameraId() const { + Q_D(const AndroidCamera); return d->m_cameraId; } -void JCamera::lock() +void AndroidCamera::lock() { - QMetaObject::invokeMethod(d, "callVoidMethod", - Qt::BlockingQueuedConnection, - Q_ARG(QByteArray, "lock")); + Q_D(AndroidCamera); + QMetaObject::invokeMethod(d, "lock", Qt::BlockingQueuedConnection); } -void JCamera::unlock() +void AndroidCamera::unlock() { - QMetaObject::invokeMethod(d, "callVoidMethod", - Qt::BlockingQueuedConnection, - Q_ARG(QByteArray, "unlock")); + Q_D(AndroidCamera); + QMetaObject::invokeMethod(d, "unlock", Qt::BlockingQueuedConnection); } -void JCamera::reconnect() +void AndroidCamera::reconnect() { - QMetaObject::invokeMethod(d, "callVoidMethod", Q_ARG(QByteArray, "reconnect")); + Q_D(AndroidCamera); + QMetaObject::invokeMethod(d, "reconnect"); } -void JCamera::release() +void AndroidCamera::release() { - QMetaObject::invokeMethod(d, "release"); + Q_D(AndroidCamera); + QMetaObject::invokeMethod(d, "release", Qt::BlockingQueuedConnection); } -JCamera::CameraFacing JCamera::getFacing() +AndroidCamera::CameraFacing AndroidCamera::getFacing() { + Q_D(AndroidCamera); return d->getFacing(); } -int JCamera::getNativeOrientation() +int AndroidCamera::getNativeOrientation() { + Q_D(AndroidCamera); return d->getNativeOrientation(); } -QSize JCamera::getPreferredPreviewSizeForVideo() +QSize AndroidCamera::getPreferredPreviewSizeForVideo() { + Q_D(AndroidCamera); return d->getPreferredPreviewSizeForVideo(); } -QList<QSize> JCamera::getSupportedPreviewSizes() +QList<QSize> AndroidCamera::getSupportedPreviewSizes() { + Q_D(AndroidCamera); return d->getSupportedPreviewSizes(); } -JCamera::ImageFormat JCamera::getPreviewFormat() +AndroidCamera::ImageFormat AndroidCamera::getPreviewFormat() { + Q_D(AndroidCamera); return d->getPreviewFormat(); } -void JCamera::setPreviewFormat(ImageFormat fmt) +void AndroidCamera::setPreviewFormat(ImageFormat fmt) { - QMetaObject::invokeMethod(d, "setPreviewFormat", Q_ARG(JCamera::ImageFormat, fmt)); + Q_D(AndroidCamera); + QMetaObject::invokeMethod(d, "setPreviewFormat", Q_ARG(AndroidCamera::ImageFormat, fmt)); } -QSize JCamera::previewSize() const +QSize AndroidCamera::previewSize() const { + Q_D(const AndroidCamera); return d->m_previewSize; } -void JCamera::setPreviewSize(const QSize &size) +void AndroidCamera::setPreviewSize(const QSize &size) { + Q_D(AndroidCamera); d->m_parametersMutex.lock(); bool areParametersValid = d->m_parameters.isValid(); d->m_parametersMutex.unlock(); @@ -375,178 +368,216 @@ void JCamera::setPreviewSize(const QSize &size) QMetaObject::invokeMethod(d, "updatePreviewSize"); } -void JCamera::setPreviewTexture(jobject surfaceTexture) +void AndroidCamera::setPreviewTexture(AndroidSurfaceTexture *surfaceTexture) { - QMetaObject::invokeMethod(d, "setPreviewTexture", Q_ARG(void *, surfaceTexture)); + Q_D(AndroidCamera); + QMetaObject::invokeMethod(d, + "setPreviewTexture", + Qt::BlockingQueuedConnection, + Q_ARG(void *, surfaceTexture ? surfaceTexture->surfaceTexture() : 0)); } -bool JCamera::isZoomSupported() +bool AndroidCamera::isZoomSupported() { + Q_D(AndroidCamera); return d->isZoomSupported(); } -int JCamera::getMaxZoom() +int AndroidCamera::getMaxZoom() { + Q_D(AndroidCamera); return d->getMaxZoom(); } -QList<int> JCamera::getZoomRatios() +QList<int> AndroidCamera::getZoomRatios() { + Q_D(AndroidCamera); return d->getZoomRatios(); } -int JCamera::getZoom() +int AndroidCamera::getZoom() { + Q_D(AndroidCamera); return d->getZoom(); } -void JCamera::setZoom(int value) +void AndroidCamera::setZoom(int value) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "setZoom", Q_ARG(int, value)); } -QStringList JCamera::getSupportedFlashModes() +QStringList AndroidCamera::getSupportedFlashModes() { + Q_D(AndroidCamera); return d->callParametersStringListMethod("getSupportedFlashModes"); } -QString JCamera::getFlashMode() +QString AndroidCamera::getFlashMode() { + Q_D(AndroidCamera); return d->getFlashMode(); } -void JCamera::setFlashMode(const QString &value) +void AndroidCamera::setFlashMode(const QString &value) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "setFlashMode", Q_ARG(QString, value)); } -QStringList JCamera::getSupportedFocusModes() +QStringList AndroidCamera::getSupportedFocusModes() { + Q_D(AndroidCamera); return d->callParametersStringListMethod("getSupportedFocusModes"); } -QString JCamera::getFocusMode() +QString AndroidCamera::getFocusMode() { + Q_D(AndroidCamera); return d->getFocusMode(); } -void JCamera::setFocusMode(const QString &value) +void AndroidCamera::setFocusMode(const QString &value) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "setFocusMode", Q_ARG(QString, value)); } -int JCamera::getMaxNumFocusAreas() +int AndroidCamera::getMaxNumFocusAreas() { + Q_D(AndroidCamera); return d->getMaxNumFocusAreas(); } -QList<QRect> JCamera::getFocusAreas() +QList<QRect> AndroidCamera::getFocusAreas() { + Q_D(AndroidCamera); return d->getFocusAreas(); } -void JCamera::setFocusAreas(const QList<QRect> &areas) +void AndroidCamera::setFocusAreas(const QList<QRect> &areas) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "setFocusAreas", Q_ARG(QList<QRect>, areas)); } -void JCamera::autoFocus() +void AndroidCamera::autoFocus() { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "autoFocus"); } -void JCamera::cancelAutoFocus() +void AndroidCamera::cancelAutoFocus() { - QMetaObject::invokeMethod(d, "callVoidMethod", Q_ARG(QByteArray, "cancelAutoFocus")); + Q_D(AndroidCamera); + QMetaObject::invokeMethod(d, "cancelAutoFocus", Qt::QueuedConnection); } -bool JCamera::isAutoExposureLockSupported() +bool AndroidCamera::isAutoExposureLockSupported() { + Q_D(AndroidCamera); return d->isAutoExposureLockSupported(); } -bool JCamera::getAutoExposureLock() +bool AndroidCamera::getAutoExposureLock() { + Q_D(AndroidCamera); return d->getAutoExposureLock(); } -void JCamera::setAutoExposureLock(bool toggle) +void AndroidCamera::setAutoExposureLock(bool toggle) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "setAutoExposureLock", Q_ARG(bool, toggle)); } -bool JCamera::isAutoWhiteBalanceLockSupported() +bool AndroidCamera::isAutoWhiteBalanceLockSupported() { + Q_D(AndroidCamera); return d->isAutoWhiteBalanceLockSupported(); } -bool JCamera::getAutoWhiteBalanceLock() +bool AndroidCamera::getAutoWhiteBalanceLock() { + Q_D(AndroidCamera); return d->getAutoWhiteBalanceLock(); } -void JCamera::setAutoWhiteBalanceLock(bool toggle) +void AndroidCamera::setAutoWhiteBalanceLock(bool toggle) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "setAutoWhiteBalanceLock", Q_ARG(bool, toggle)); } -int JCamera::getExposureCompensation() +int AndroidCamera::getExposureCompensation() { + Q_D(AndroidCamera); return d->getExposureCompensation(); } -void JCamera::setExposureCompensation(int value) +void AndroidCamera::setExposureCompensation(int value) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "setExposureCompensation", Q_ARG(int, value)); } -float JCamera::getExposureCompensationStep() +float AndroidCamera::getExposureCompensationStep() { + Q_D(AndroidCamera); return d->getExposureCompensationStep(); } -int JCamera::getMinExposureCompensation() +int AndroidCamera::getMinExposureCompensation() { + Q_D(AndroidCamera); return d->getMinExposureCompensation(); } -int JCamera::getMaxExposureCompensation() +int AndroidCamera::getMaxExposureCompensation() { + Q_D(AndroidCamera); return d->getMaxExposureCompensation(); } -QStringList JCamera::getSupportedSceneModes() +QStringList AndroidCamera::getSupportedSceneModes() { + Q_D(AndroidCamera); return d->callParametersStringListMethod("getSupportedSceneModes"); } -QString JCamera::getSceneMode() +QString AndroidCamera::getSceneMode() { + Q_D(AndroidCamera); return d->getSceneMode(); } -void JCamera::setSceneMode(const QString &value) +void AndroidCamera::setSceneMode(const QString &value) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "setSceneMode", Q_ARG(QString, value)); } -QStringList JCamera::getSupportedWhiteBalance() +QStringList AndroidCamera::getSupportedWhiteBalance() { + Q_D(AndroidCamera); return d->callParametersStringListMethod("getSupportedWhiteBalance"); } -QString JCamera::getWhiteBalance() +QString AndroidCamera::getWhiteBalance() { + Q_D(AndroidCamera); return d->getWhiteBalance(); } -void JCamera::setWhiteBalance(const QString &value) +void AndroidCamera::setWhiteBalance(const QString &value) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "setWhiteBalance", Q_ARG(QString, value)); } -void JCamera::setRotation(int rotation) +void AndroidCamera::setRotation(int rotation) { + Q_D(AndroidCamera); //We need to do it here and not in worker class because we cache rotation d->m_parametersMutex.lock(); bool areParametersValid = d->m_parameters.isValid(); @@ -558,112 +589,181 @@ void JCamera::setRotation(int rotation) QMetaObject::invokeMethod(d, "updateRotation"); } -int JCamera::getRotation() const +int AndroidCamera::getRotation() const { + Q_D(const AndroidCamera); return d->m_rotation; } -QList<QSize> JCamera::getSupportedPictureSizes() +QList<QSize> AndroidCamera::getSupportedPictureSizes() { + Q_D(AndroidCamera); return d->getSupportedPictureSizes(); } -void JCamera::setPictureSize(const QSize &size) +void AndroidCamera::setPictureSize(const QSize &size) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "setPictureSize", Q_ARG(QSize, size)); } -void JCamera::setJpegQuality(int quality) +void AndroidCamera::setJpegQuality(int quality) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "setJpegQuality", Q_ARG(int, quality)); } -void JCamera::takePicture() +void AndroidCamera::takePicture() { - QMetaObject::invokeMethod(d, "callVoidMethod", Q_ARG(QByteArray, "takePicture")); + Q_D(AndroidCamera); + QMetaObject::invokeMethod(d, "takePicture", Qt::BlockingQueuedConnection); } -void JCamera::fetchEachFrame(bool fetch) +void AndroidCamera::fetchEachFrame(bool fetch) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "fetchEachFrame", Q_ARG(bool, fetch)); } -void JCamera::fetchLastPreviewFrame() +void AndroidCamera::fetchLastPreviewFrame() { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "fetchLastPreviewFrame"); } -QJNIObjectPrivate JCamera::getCameraObject() +QJNIObjectPrivate AndroidCamera::getCameraObject() { - return d->m_camera.getObjectField("m_camera", "Landroid/hardware/Camera;"); + Q_D(AndroidCamera); + return d->m_camera; } -void JCamera::startPreview() +int AndroidCamera::getNumberOfCameras() { + return QJNIObjectPrivate::callStaticMethod<jint>("android/hardware/Camera", + "getNumberOfCameras"); +} + +void AndroidCamera::getCameraInfo(int id, AndroidCameraInfo *info) +{ + Q_ASSERT(info); + + QJNIObjectPrivate cameraInfo("android/hardware/Camera$CameraInfo"); + QJNIObjectPrivate::callStaticMethod<void>("android/hardware/Camera", + "getCameraInfo", + "(ILandroid/hardware/Camera$CameraInfo;)V", + id, cameraInfo.object()); + + AndroidCamera::CameraFacing facing = AndroidCamera::CameraFacing(cameraInfo.getField<jint>("facing")); + // The orientation provided by Android is counter-clockwise, we need it clockwise + info->orientation = (360 - cameraInfo.getField<jint>("orientation")) % 360; + + switch (facing) { + case AndroidCamera::CameraFacingBack: + info->name = QByteArray("back"); + info->description = QStringLiteral("Rear-facing camera"); + info->position = QCamera::BackFace; + break; + case AndroidCamera::CameraFacingFront: + info->name = QByteArray("front"); + info->description = QStringLiteral("Front-facing camera"); + info->position = QCamera::FrontFace; + break; + default: + break; + } +} + +void AndroidCamera::startPreview() +{ + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "startPreview"); } -void JCamera::stopPreview() +void AndroidCamera::stopPreview() { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "stopPreview"); } +AndroidCameraPrivate::AndroidCameraPrivate() + : QObject(), + m_parametersMutex(QMutex::Recursive) +{ +} -//JCameraWorker +AndroidCameraPrivate::~AndroidCameraPrivate() +{ +} -JCameraWorker::JCameraWorker(JCamera *camera, int cameraId, jobject cam, QThread *workerThread) - : QObject(0) - , m_cameraId(cameraId) - , m_rotation(0) - , m_parametersMutex(QMutex::Recursive) - , m_camera(cam) +bool AndroidCameraPrivate::init(int cameraId) { - q = camera; - m_workerThread = workerThread; - moveToThread(m_workerThread); + m_cameraId = cameraId; + m_camera = QJNIObjectPrivate::callStaticObjectMethod("android/hardware/Camera", + "open", + "(I)Landroid/hardware/Camera;", + cameraId); - if (m_camera.isValid()) { - g_objectMapMutex.lock(); - g_objectMap.insert(cameraId, q); - g_objectMapMutex.unlock(); + if (!m_camera.isValid()) + return false; - m_info = QJNIObjectPrivate("android/hardware/Camera$CameraInfo"); - m_camera.callStaticMethod<void>("android/hardware/Camera", - "getCameraInfo", - "(ILandroid/hardware/Camera$CameraInfo;)V", - cameraId, m_info.object()); + m_cameraListener = QJNIObjectPrivate(g_qtCameraListenerClass, "(I)V", m_cameraId); + m_info = QJNIObjectPrivate("android/hardware/Camera$CameraInfo"); + m_camera.callStaticMethod<void>("android/hardware/Camera", + "getCameraInfo", + "(ILandroid/hardware/Camera$CameraInfo;)V", + cameraId, + m_info.object()); - QJNIObjectPrivate params = m_camera.callObjectMethod("getParameters", - "()Landroid/hardware/Camera$Parameters;"); - m_parameters = QJNIObjectPrivate(params); - } -} + QJNIObjectPrivate params = m_camera.callObjectMethod("getParameters", + "()Landroid/hardware/Camera$Parameters;"); + m_parameters = QJNIObjectPrivate(params); -JCameraWorker::~JCameraWorker() -{ - m_workerThread->quit(); + return true; } -void JCameraWorker::release() +void AndroidCameraPrivate::release() { m_previewSize = QSize(); m_parametersMutex.lock(); m_parameters = QJNIObjectPrivate(); m_parametersMutex.unlock(); - m_camera.callMethod<void>("release"); + if (m_camera.isValid()) + m_camera.callMethod<void>("release"); +} + +void AndroidCameraPrivate::lock() +{ + m_camera.callMethod<void>("lock"); +} + +void AndroidCameraPrivate::unlock() +{ + m_camera.callMethod<void>("unlock"); } -JCamera::CameraFacing JCameraWorker::getFacing() +void AndroidCameraPrivate::reconnect() { - return JCamera::CameraFacing(m_info.getField<jint>("facing")); + QJNIEnvironmentPrivate env; + m_camera.callMethod<void>("reconnect"); + if (env->ExceptionCheck()) { +#ifdef QT_DEBUG + env->ExceptionDescribe(); +#endif // QT_DEBUG + env->ExceptionDescribe(); + } +} + +AndroidCamera::CameraFacing AndroidCameraPrivate::getFacing() +{ + return AndroidCamera::CameraFacing(m_info.getField<jint>("facing")); } -int JCameraWorker::getNativeOrientation() +int AndroidCameraPrivate::getNativeOrientation() { return m_info.getField<jint>("orientation"); } -QSize JCameraWorker::getPreferredPreviewSizeForVideo() +QSize AndroidCameraPrivate::getPreferredPreviewSizeForVideo() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -676,7 +776,7 @@ QSize JCameraWorker::getPreferredPreviewSizeForVideo() return QSize(size.getField<jint>("width"), size.getField<jint>("height")); } -QList<QSize> JCameraWorker::getSupportedPreviewSizes() +QList<QSize> AndroidCameraPrivate::getSupportedPreviewSizes() { QList<QSize> list; @@ -699,17 +799,17 @@ QList<QSize> JCameraWorker::getSupportedPreviewSizes() return list; } -JCamera::ImageFormat JCameraWorker::getPreviewFormat() +AndroidCamera::ImageFormat AndroidCameraPrivate::getPreviewFormat() { QMutexLocker parametersLocker(&m_parametersMutex); if (!m_parameters.isValid()) - return JCamera::Unknown; + return AndroidCamera::Unknown; - return JCamera::ImageFormat(m_parameters.callMethod<jint>("getPreviewFormat")); + return AndroidCamera::ImageFormat(m_parameters.callMethod<jint>("getPreviewFormat")); } -void JCameraWorker::setPreviewFormat(JCamera::ImageFormat fmt) +void AndroidCameraPrivate::setPreviewFormat(AndroidCamera::ImageFormat fmt) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -720,7 +820,7 @@ void JCameraWorker::setPreviewFormat(JCamera::ImageFormat fmt) applyParameters(); } -void JCameraWorker::updatePreviewSize() +void AndroidCameraPrivate::updatePreviewSize() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -732,14 +832,14 @@ void JCameraWorker::updatePreviewSize() emit previewSizeChanged(); } -void JCameraWorker::setPreviewTexture(void *surfaceTexture) +void AndroidCameraPrivate::setPreviewTexture(void *surfaceTexture) { m_camera.callMethod<void>("setPreviewTexture", "(Landroid/graphics/SurfaceTexture;)V", static_cast<jobject>(surfaceTexture)); } -bool JCameraWorker::isZoomSupported() +bool AndroidCameraPrivate::isZoomSupported() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -749,7 +849,7 @@ bool JCameraWorker::isZoomSupported() return m_parameters.callMethod<jboolean>("isZoomSupported"); } -int JCameraWorker::getMaxZoom() +int AndroidCameraPrivate::getMaxZoom() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -759,7 +859,7 @@ int JCameraWorker::getMaxZoom() return m_parameters.callMethod<jint>("getMaxZoom"); } -QList<int> JCameraWorker::getZoomRatios() +QList<int> AndroidCameraPrivate::getZoomRatios() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -781,7 +881,7 @@ QList<int> JCameraWorker::getZoomRatios() return ratios; } -int JCameraWorker::getZoom() +int AndroidCameraPrivate::getZoom() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -791,7 +891,7 @@ int JCameraWorker::getZoom() return m_parameters.callMethod<jint>("getZoom"); } -void JCameraWorker::setZoom(int value) +void AndroidCameraPrivate::setZoom(int value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -802,7 +902,7 @@ void JCameraWorker::setZoom(int value) applyParameters(); } -QString JCameraWorker::getFlashMode() +QString AndroidCameraPrivate::getFlashMode() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -818,7 +918,7 @@ QString JCameraWorker::getFlashMode() return value; } -void JCameraWorker::setFlashMode(const QString &value) +void AndroidCameraPrivate::setFlashMode(const QString &value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -831,7 +931,7 @@ void JCameraWorker::setFlashMode(const QString &value) applyParameters(); } -QString JCameraWorker::getFocusMode() +QString AndroidCameraPrivate::getFocusMode() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -847,7 +947,7 @@ QString JCameraWorker::getFocusMode() return value; } -void JCameraWorker::setFocusMode(const QString &value) +void AndroidCameraPrivate::setFocusMode(const QString &value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -860,7 +960,7 @@ void JCameraWorker::setFocusMode(const QString &value) applyParameters(); } -int JCameraWorker::getMaxNumFocusAreas() +int AndroidCameraPrivate::getMaxNumFocusAreas() { if (QtAndroidPrivate::androidSdkVersion() < 14) return 0; @@ -873,7 +973,7 @@ int JCameraWorker::getMaxNumFocusAreas() return m_parameters.callMethod<jint>("getMaxNumFocusAreas"); } -QList<QRect> JCameraWorker::getFocusAreas() +QList<QRect> AndroidCameraPrivate::getFocusAreas() { QList<QRect> areas; @@ -901,7 +1001,7 @@ QList<QRect> JCameraWorker::getFocusAreas() return areas; } -void JCameraWorker::setFocusAreas(const QList<QRect> &areas) +void AndroidCameraPrivate::setFocusAreas(const QList<QRect> &areas) { if (QtAndroidPrivate::androidSdkVersion() < 14) return; @@ -931,13 +1031,20 @@ void JCameraWorker::setFocusAreas(const QList<QRect> &areas) applyParameters(); } -void JCameraWorker::autoFocus() +void AndroidCameraPrivate::autoFocus() { - m_camera.callMethod<void>("autoFocus"); + m_camera.callMethod<void>("autoFocus", + "(Landroid/hardware/Camera$AutoFocusCallback;)V", + m_cameraListener.object()); emit autoFocusStarted(); } -bool JCameraWorker::isAutoExposureLockSupported() +void AndroidCameraPrivate::cancelAutoFocus() +{ + m_camera.callMethod<void>("cancelAutoFocus"); +} + +bool AndroidCameraPrivate::isAutoExposureLockSupported() { if (QtAndroidPrivate::androidSdkVersion() < 14) return false; @@ -950,7 +1057,7 @@ bool JCameraWorker::isAutoExposureLockSupported() return m_parameters.callMethod<jboolean>("isAutoExposureLockSupported"); } -bool JCameraWorker::getAutoExposureLock() +bool AndroidCameraPrivate::getAutoExposureLock() { if (QtAndroidPrivate::androidSdkVersion() < 14) return false; @@ -963,7 +1070,7 @@ bool JCameraWorker::getAutoExposureLock() return m_parameters.callMethod<jboolean>("getAutoExposureLock"); } -void JCameraWorker::setAutoExposureLock(bool toggle) +void AndroidCameraPrivate::setAutoExposureLock(bool toggle) { if (QtAndroidPrivate::androidSdkVersion() < 14) return; @@ -977,7 +1084,7 @@ void JCameraWorker::setAutoExposureLock(bool toggle) applyParameters(); } -bool JCameraWorker::isAutoWhiteBalanceLockSupported() +bool AndroidCameraPrivate::isAutoWhiteBalanceLockSupported() { if (QtAndroidPrivate::androidSdkVersion() < 14) return false; @@ -990,7 +1097,7 @@ bool JCameraWorker::isAutoWhiteBalanceLockSupported() return m_parameters.callMethod<jboolean>("isAutoWhiteBalanceLockSupported"); } -bool JCameraWorker::getAutoWhiteBalanceLock() +bool AndroidCameraPrivate::getAutoWhiteBalanceLock() { if (QtAndroidPrivate::androidSdkVersion() < 14) return false; @@ -1003,7 +1110,7 @@ bool JCameraWorker::getAutoWhiteBalanceLock() return m_parameters.callMethod<jboolean>("getAutoWhiteBalanceLock"); } -void JCameraWorker::setAutoWhiteBalanceLock(bool toggle) +void AndroidCameraPrivate::setAutoWhiteBalanceLock(bool toggle) { if (QtAndroidPrivate::androidSdkVersion() < 14) return; @@ -1017,7 +1124,7 @@ void JCameraWorker::setAutoWhiteBalanceLock(bool toggle) applyParameters(); } -int JCameraWorker::getExposureCompensation() +int AndroidCameraPrivate::getExposureCompensation() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1027,7 +1134,7 @@ int JCameraWorker::getExposureCompensation() return m_parameters.callMethod<jint>("getExposureCompensation"); } -void JCameraWorker::setExposureCompensation(int value) +void AndroidCameraPrivate::setExposureCompensation(int value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1038,7 +1145,7 @@ void JCameraWorker::setExposureCompensation(int value) applyParameters(); } -float JCameraWorker::getExposureCompensationStep() +float AndroidCameraPrivate::getExposureCompensationStep() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1048,7 +1155,7 @@ float JCameraWorker::getExposureCompensationStep() return m_parameters.callMethod<jfloat>("getExposureCompensationStep"); } -int JCameraWorker::getMinExposureCompensation() +int AndroidCameraPrivate::getMinExposureCompensation() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1058,7 +1165,7 @@ int JCameraWorker::getMinExposureCompensation() return m_parameters.callMethod<jint>("getMinExposureCompensation"); } -int JCameraWorker::getMaxExposureCompensation() +int AndroidCameraPrivate::getMaxExposureCompensation() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1068,7 +1175,7 @@ int JCameraWorker::getMaxExposureCompensation() return m_parameters.callMethod<jint>("getMaxExposureCompensation"); } -QString JCameraWorker::getSceneMode() +QString AndroidCameraPrivate::getSceneMode() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1084,7 +1191,7 @@ QString JCameraWorker::getSceneMode() return value; } -void JCameraWorker::setSceneMode(const QString &value) +void AndroidCameraPrivate::setSceneMode(const QString &value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1097,7 +1204,7 @@ void JCameraWorker::setSceneMode(const QString &value) applyParameters(); } -QString JCameraWorker::getWhiteBalance() +QString AndroidCameraPrivate::getWhiteBalance() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1113,7 +1220,7 @@ QString JCameraWorker::getWhiteBalance() return value; } -void JCameraWorker::setWhiteBalance(const QString &value) +void AndroidCameraPrivate::setWhiteBalance(const QString &value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1128,7 +1235,7 @@ void JCameraWorker::setWhiteBalance(const QString &value) emit whiteBalanceChanged(); } -void JCameraWorker::updateRotation() +void AndroidCameraPrivate::updateRotation() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1136,7 +1243,7 @@ void JCameraWorker::updateRotation() applyParameters(); } -QList<QSize> JCameraWorker::getSupportedPictureSizes() +QList<QSize> AndroidCameraPrivate::getSupportedPictureSizes() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1159,7 +1266,7 @@ QList<QSize> JCameraWorker::getSupportedPictureSizes() return list; } -void JCameraWorker::setPictureSize(const QSize &size) +void AndroidCameraPrivate::setPictureSize(const QSize &size) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1170,7 +1277,7 @@ void JCameraWorker::setPictureSize(const QSize &size) applyParameters(); } -void JCameraWorker::setJpegQuality(int quality) +void AndroidCameraPrivate::setJpegQuality(int quality) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1181,49 +1288,71 @@ void JCameraWorker::setJpegQuality(int quality) applyParameters(); } -void JCameraWorker::startPreview() -{ - callVoidMethod("startPreview"); +void AndroidCameraPrivate::startPreview() +{ + //We need to clear preview buffers queue here, but there is no method to do it + //Though just resetting preview callback do the trick + m_camera.callMethod<void>("setPreviewCallbackWithBuffer", + "(Landroid/hardware/Camera$PreviewCallback;)V", + jobject(0)); + m_cameraListener.callMethod<void>("preparePreviewBuffer", "(Landroid/hardware/Camera;)V", m_camera.object()); + QJNIObjectPrivate buffer = m_cameraListener.callObjectMethod<jbyteArray>("callbackBuffer"); + m_camera.callMethod<void>("addCallbackBuffer", "([B)V", buffer.object()); + m_camera.callMethod<void>("setPreviewCallbackWithBuffer", + "(Landroid/hardware/Camera$PreviewCallback;)V", + m_cameraListener.object()); + m_camera.callMethod<void>("startPreview"); emit previewStarted(); } -void JCameraWorker::stopPreview() +void AndroidCameraPrivate::stopPreview() { - callVoidMethod("stopPreview"); + m_camera.callMethod<void>("stopPreview"); emit previewStopped(); } -void JCameraWorker::fetchEachFrame(bool fetch) +void AndroidCameraPrivate::takePicture() { - m_camera.callMethod<void>("fetchEachFrame", "(Z)V", fetch); + m_camera.callMethod<void>("takePicture", "(Landroid/hardware/Camera$ShutterCallback;" + "Landroid/hardware/Camera$PictureCallback;" + "Landroid/hardware/Camera$PictureCallback;)V", + m_cameraListener.object(), + jobject(0), + m_cameraListener.object()); } -void JCameraWorker::fetchLastPreviewFrame() +void AndroidCameraPrivate::fetchEachFrame(bool fetch) +{ + m_cameraListener.callMethod<void>("fetchEachFrame", "(Z)V", fetch); +} + +void AndroidCameraPrivate::fetchLastPreviewFrame() { QJNIEnvironmentPrivate env; - QJNIObjectPrivate dataObj = m_camera.callObjectMethod("lockAndFetchPreviewBuffer", "()[B"); - if (!dataObj.object()) { - m_camera.callMethod<void>("unlockPreviewBuffer"); + QJNIObjectPrivate data = m_cameraListener.callObjectMethod("lockAndFetchPreviewBuffer", "()[B"); + if (!data.isValid()) { + m_cameraListener.callMethod<void>("unlockPreviewBuffer"); return; } - jbyteArray data = static_cast<jbyteArray>(dataObj.object()); - QByteArray bytes; - int arrayLength = env->GetArrayLength(data); - bytes.resize(arrayLength); - env->GetByteArrayRegion(data, 0, arrayLength, (jbyte*)bytes.data()); - m_camera.callMethod<void>("unlockPreviewBuffer"); + const int arrayLength = env->GetArrayLength(static_cast<jbyteArray>(data.object())); + QByteArray bytes(arrayLength, Qt::Uninitialized); + env->GetByteArrayRegion(static_cast<jbyteArray>(data.object()), + 0, + arrayLength, + reinterpret_cast<jbyte *>(bytes.data())); + m_cameraListener.callMethod<void>("unlockPreviewBuffer"); emit previewFetched(bytes); } -void JCameraWorker::applyParameters() +void AndroidCameraPrivate::applyParameters() { m_camera.callMethod<void>("setParameters", "(Landroid/hardware/Camera$Parameters;)V", m_parameters.object()); } -QStringList JCameraWorker::callParametersStringListMethod(const QByteArray &methodName) +QStringList AndroidCameraPrivate::callParametersStringListMethod(const QByteArray &methodName) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1239,7 +1368,6 @@ QStringList JCameraWorker::callParametersStringListMethod(const QByteArray &meth QJNIObjectPrivate string = list.callObjectMethod("get", "(I)Ljava/lang/Object;", i); - stringList.append(string.toString()); } } @@ -1248,12 +1376,6 @@ QStringList JCameraWorker::callParametersStringListMethod(const QByteArray &meth return stringList; } -void JCameraWorker::callVoidMethod(const QByteArray &methodName) -{ - m_camera.callMethod<void>(methodName.constData()); -} - - static JNINativeMethod methods[] = { {"notifyAutoFocusComplete", "(IZ)V", (void *)notifyAutoFocusComplete}, {"notifyPictureExposed", "(I)V", (void *)notifyPictureExposed}, @@ -1261,15 +1383,15 @@ static JNINativeMethod methods[] = { {"notifyFrameFetched", "(I[B)V", (void *)notifyFrameFetched} }; -bool JCamera::initJNI(JNIEnv *env) +bool AndroidCamera::initJNI(JNIEnv *env) { - jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtCamera"); + jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtCameraListener"); if (env->ExceptionCheck()) env->ExceptionClear(); if (clazz) { - g_qtCameraClass = static_cast<jclass>(env->NewGlobalRef(clazz)); - if (env->RegisterNatives(g_qtCameraClass, + g_qtCameraListenerClass = static_cast<jclass>(env->NewGlobalRef(clazz)); + if (env->RegisterNatives(g_qtCameraListenerClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) { return false; @@ -1281,4 +1403,4 @@ bool JCamera::initJNI(JNIEnv *env) QT_END_NAMESPACE -#include "jcamera.moc" +#include "androidcamera.moc" diff --git a/src/plugins/android/src/wrappers/jcamera.h b/src/plugins/android/src/wrappers/jni/androidcamera.h index 81c334eb4..2ea69b7e3 100644 --- a/src/plugins/android/src/wrappers/jcamera.h +++ b/src/plugins/android/src/wrappers/jni/androidcamera.h @@ -39,21 +39,31 @@ ** ****************************************************************************/ -#ifndef JCAMERA_H -#define JCAMERA_H +#ifndef ANDROIDCAMERA_H +#define ANDROIDCAMERA_H #include <qobject.h> #include <QtCore/private/qjni_p.h> #include <qsize.h> #include <qrect.h> +#include <QtMultimedia/qcamera.h> QT_BEGIN_NAMESPACE class QThread; -class JCameraWorker; +class AndroidCameraPrivate; +class AndroidSurfaceTexture; -class JCamera : public QObject +struct AndroidCameraInfo +{ + QByteArray name; + QString description; + QCamera::Position position; + int orientation; +}; + +class AndroidCamera : public QObject { Q_OBJECT Q_ENUMS(CameraFacing) @@ -74,9 +84,9 @@ public: YV12 = 842094169 }; - ~JCamera(); + ~AndroidCamera(); - static JCamera *open(int cameraId); + static AndroidCamera *open(int cameraId); int cameraId() const; @@ -96,7 +106,7 @@ public: QSize previewSize() const; void setPreviewSize(const QSize &size); - void setPreviewTexture(jobject surfaceTexture); + void setPreviewTexture(AndroidSurfaceTexture *surfaceTexture); bool isZoomSupported(); int getMaxZoom(); @@ -157,6 +167,9 @@ public: void fetchLastPreviewFrame(); QJNIObjectPrivate getCameraObject(); + static int getNumberOfCameras(); + static void getCameraInfo(int id, AndroidCameraInfo *info); + static bool initJNI(JNIEnv *env); Q_SIGNALS: @@ -175,11 +188,13 @@ Q_SIGNALS: void frameFetched(const QByteArray &frame); private: - JCamera(int cameraId, jobject cam, QThread *workerThread); + AndroidCamera(AndroidCameraPrivate *d, QThread *worker); - JCameraWorker *d; + Q_DECLARE_PRIVATE(AndroidCamera) + AndroidCameraPrivate *d_ptr; + QScopedPointer<QThread> m_worker; }; QT_END_NAMESPACE -#endif // JCAMERA_H +#endif // ANDROIDCAMERA_H diff --git a/src/plugins/android/src/wrappers/jmediametadataretriever.cpp b/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.cpp index 93b77ecb1..7dfc6a6e3 100644 --- a/src/plugins/android/src/wrappers/jmediametadataretriever.cpp +++ b/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.cpp @@ -39,23 +39,23 @@ ** ****************************************************************************/ -#include "jmediametadataretriever.h" +#include "androidmediametadataretriever.h" #include <QtCore/private/qjnihelpers_p.h> #include <QtCore/private/qjni_p.h> QT_BEGIN_NAMESPACE -JMediaMetadataRetriever::JMediaMetadataRetriever() +AndroidMediaMetadataRetriever::AndroidMediaMetadataRetriever() { m_metadataRetriever = QJNIObjectPrivate("android/media/MediaMetadataRetriever"); } -JMediaMetadataRetriever::~JMediaMetadataRetriever() +AndroidMediaMetadataRetriever::~AndroidMediaMetadataRetriever() { } -QString JMediaMetadataRetriever::extractMetadata(MetadataKey key) +QString AndroidMediaMetadataRetriever::extractMetadata(MetadataKey key) { QString value; @@ -68,7 +68,7 @@ QString JMediaMetadataRetriever::extractMetadata(MetadataKey key) return value; } -void JMediaMetadataRetriever::release() +void AndroidMediaMetadataRetriever::release() { if (!m_metadataRetriever.isValid()) return; @@ -76,7 +76,7 @@ void JMediaMetadataRetriever::release() m_metadataRetriever.callMethod<void>("release"); } -bool JMediaMetadataRetriever::setDataSource(const QUrl &url) +bool AndroidMediaMetadataRetriever::setDataSource(const QUrl &url) { if (!m_metadataRetriever.isValid()) return false; @@ -107,7 +107,7 @@ bool JMediaMetadataRetriever::setDataSource(const QUrl &url) return loaded; } -bool JMediaMetadataRetriever::setDataSource(const QString &path) +bool AndroidMediaMetadataRetriever::setDataSource(const QString &path) { if (!m_metadataRetriever.isValid()) return false; diff --git a/src/plugins/android/src/wrappers/jmediametadataretriever.h b/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.h index 7b0340c0d..f18cec11d 100644 --- a/src/plugins/android/src/wrappers/jmediametadataretriever.h +++ b/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.h @@ -39,15 +39,15 @@ ** ****************************************************************************/ -#ifndef JMEDIAMETADATARETRIEVER_H -#define JMEDIAMETADATARETRIEVER_H +#ifndef ANDROIDMEDIAMETADATARETRIEVER_H +#define ANDROIDMEDIAMETADATARETRIEVER_H #include <QtCore/private/qjni_p.h> #include <qurl.h> QT_BEGIN_NAMESPACE -class JMediaMetadataRetriever +class AndroidMediaMetadataRetriever { public: enum MetadataKey { @@ -76,8 +76,8 @@ public: Year = 8 }; - JMediaMetadataRetriever(); - ~JMediaMetadataRetriever(); + AndroidMediaMetadataRetriever(); + ~AndroidMediaMetadataRetriever(); QString extractMetadata(MetadataKey key); void release(); @@ -90,4 +90,4 @@ private: QT_END_NAMESPACE -#endif // JMEDIAMETADATARETRIEVER_H +#endif // ANDROIDMEDIAMETADATARETRIEVER_H diff --git a/src/plugins/android/src/wrappers/jmediaplayer.cpp b/src/plugins/android/src/wrappers/jni/androidmediaplayer.cpp index de86cd041..5aee7a857 100644 --- a/src/plugins/android/src/wrappers/jmediaplayer.cpp +++ b/src/plugins/android/src/wrappers/jni/androidmediaplayer.cpp @@ -39,20 +39,21 @@ ** ****************************************************************************/ -#include "jmediaplayer.h" +#include "androidmediaplayer.h" #include <QString> #include <QtCore/private/qjni_p.h> #include <QtCore/private/qjnihelpers_p.h> +#include "androidsurfacetexture.h" #include <QMap> static jclass mediaPlayerClass = Q_NULLPTR; -typedef QMap<jlong, JMediaPlayer *> MediaPlayerMap; +typedef QMap<jlong, AndroidMediaPlayer *> MediaPlayerMap; Q_GLOBAL_STATIC(MediaPlayerMap, mediaPlayers) QT_BEGIN_NAMESPACE -JMediaPlayer::JMediaPlayer() +AndroidMediaPlayer::AndroidMediaPlayer() : QObject() { @@ -64,104 +65,104 @@ JMediaPlayer::JMediaPlayer() (*mediaPlayers)[id] = this; } -JMediaPlayer::~JMediaPlayer() +AndroidMediaPlayer::~AndroidMediaPlayer() { mediaPlayers->remove(reinterpret_cast<jlong>(this)); } -void JMediaPlayer::release() +void AndroidMediaPlayer::release() { mMediaPlayer.callMethod<void>("release"); } -void JMediaPlayer::reset() +void AndroidMediaPlayer::reset() { mMediaPlayer.callMethod<void>("reset"); } -int JMediaPlayer::getCurrentPosition() +int AndroidMediaPlayer::getCurrentPosition() { return mMediaPlayer.callMethod<jint>("getCurrentPosition"); } -int JMediaPlayer::getDuration() +int AndroidMediaPlayer::getDuration() { return mMediaPlayer.callMethod<jint>("getDuration"); } -bool JMediaPlayer::isPlaying() +bool AndroidMediaPlayer::isPlaying() { return mMediaPlayer.callMethod<jboolean>("isPlaying"); } -int JMediaPlayer::volume() +int AndroidMediaPlayer::volume() { return mMediaPlayer.callMethod<jint>("getVolume"); } -bool JMediaPlayer::isMuted() +bool AndroidMediaPlayer::isMuted() { return mMediaPlayer.callMethod<jboolean>("isMuted"); } -jobject JMediaPlayer::display() +jobject AndroidMediaPlayer::display() { return mMediaPlayer.callObjectMethod("display", "()Landroid/view/SurfaceHolder;").object(); } -void JMediaPlayer::play() +void AndroidMediaPlayer::play() { mMediaPlayer.callMethod<void>("start"); } -void JMediaPlayer::pause() +void AndroidMediaPlayer::pause() { mMediaPlayer.callMethod<void>("pause"); } -void JMediaPlayer::stop() +void AndroidMediaPlayer::stop() { mMediaPlayer.callMethod<void>("stop"); } -void JMediaPlayer::seekTo(qint32 msec) +void AndroidMediaPlayer::seekTo(qint32 msec) { mMediaPlayer.callMethod<void>("seekTo", "(I)V", jint(msec)); } -void JMediaPlayer::setMuted(bool mute) +void AndroidMediaPlayer::setMuted(bool mute) { mMediaPlayer.callMethod<void>("mute", "(Z)V", jboolean(mute)); } -void JMediaPlayer::setDataSource(const QString &path) +void AndroidMediaPlayer::setDataSource(const QString &path) { QJNIObjectPrivate string = QJNIObjectPrivate::fromString(path); mMediaPlayer.callMethod<void>("setDataSource", "(Ljava/lang/String;)V", string.object()); } -void JMediaPlayer::prepareAsync() +void AndroidMediaPlayer::prepareAsync() { mMediaPlayer.callMethod<void>("prepareAsync"); } -void JMediaPlayer::setVolume(int volume) +void AndroidMediaPlayer::setVolume(int volume) { mMediaPlayer.callMethod<void>("setVolume", "(I)V", jint(volume)); } -void JMediaPlayer::setDisplay(jobject surfaceHolder) +void AndroidMediaPlayer::setDisplay(AndroidSurfaceTexture *surfaceTexture) { - mMediaPlayer.callMethod<void>("setDisplay", "(Landroid/view/SurfaceHolder;)V", surfaceHolder); + mMediaPlayer.callMethod<void>("setDisplay", + "(Landroid/view/SurfaceHolder;)V", + surfaceTexture ? surfaceTexture->surfaceHolder() : 0); } -QT_END_NAMESPACE - static void onErrorNative(JNIEnv *env, jobject thiz, jint what, jint extra, jlong id) { Q_UNUSED(env); Q_UNUSED(thiz); - JMediaPlayer *const mp = (*mediaPlayers)[id]; + AndroidMediaPlayer *const mp = (*mediaPlayers)[id]; if (!mp) return; @@ -172,7 +173,7 @@ static void onBufferingUpdateNative(JNIEnv *env, jobject thiz, jint percent, jlo { Q_UNUSED(env); Q_UNUSED(thiz); - JMediaPlayer *const mp = (*mediaPlayers)[id]; + AndroidMediaPlayer *const mp = (*mediaPlayers)[id]; if (!mp) return; @@ -183,7 +184,7 @@ static void onProgressUpdateNative(JNIEnv *env, jobject thiz, jint progress, jlo { Q_UNUSED(env); Q_UNUSED(thiz); - JMediaPlayer *const mp = (*mediaPlayers)[id]; + AndroidMediaPlayer *const mp = (*mediaPlayers)[id]; if (!mp) return; @@ -194,7 +195,7 @@ static void onDurationChangedNative(JNIEnv *env, jobject thiz, jint duration, jl { Q_UNUSED(env); Q_UNUSED(thiz); - JMediaPlayer *const mp = (*mediaPlayers)[id]; + AndroidMediaPlayer *const mp = (*mediaPlayers)[id]; if (!mp) return; @@ -205,7 +206,7 @@ static void onInfoNative(JNIEnv *env, jobject thiz, jint what, jint extra, jlong { Q_UNUSED(env); Q_UNUSED(thiz); - JMediaPlayer *const mp = (*mediaPlayers)[id]; + AndroidMediaPlayer *const mp = (*mediaPlayers)[id]; if (!mp) return; @@ -216,7 +217,7 @@ static void onStateChangedNative(JNIEnv *env, jobject thiz, jint state, jlong id { Q_UNUSED(env); Q_UNUSED(thiz); - JMediaPlayer *const mp = (*mediaPlayers)[id]; + AndroidMediaPlayer *const mp = (*mediaPlayers)[id]; if (!mp) return; @@ -231,16 +232,14 @@ static void onVideoSizeChangedNative(JNIEnv *env, { Q_UNUSED(env); Q_UNUSED(thiz); - JMediaPlayer *const mp = (*mediaPlayers)[id]; + AndroidMediaPlayer *const mp = (*mediaPlayers)[id]; if (!mp) return; Q_EMIT mp->videoSizeChanged(width, height); } -QT_BEGIN_NAMESPACE - -bool JMediaPlayer::initJNI(JNIEnv *env) +bool AndroidMediaPlayer::initJNI(JNIEnv *env) { jclass jClass = env->FindClass("org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer"); diff --git a/src/plugins/android/src/wrappers/jmediaplayer.h b/src/plugins/android/src/wrappers/jni/androidmediaplayer.h index cd469e677..976d886f8 100644 --- a/src/plugins/android/src/wrappers/jmediaplayer.h +++ b/src/plugins/android/src/wrappers/jni/androidmediaplayer.h @@ -39,20 +39,22 @@ ** ****************************************************************************/ -#ifndef QANDROIDMEDIAPLAYER_H -#define QANDROIDMEDIAPLAYER_H +#ifndef ANDROIDMEDIAPLAYER_H +#define ANDROIDMEDIAPLAYER_H #include <QObject> #include <QtCore/private/qjni_p.h> QT_BEGIN_NAMESPACE -class JMediaPlayer : public QObject +class AndroidSurfaceTexture; + +class AndroidMediaPlayer : public QObject { Q_OBJECT public: - JMediaPlayer(); - ~JMediaPlayer(); + AndroidMediaPlayer(); + ~AndroidMediaPlayer(); enum MediaError { @@ -113,7 +115,7 @@ public: void setDataSource(const QString &path); void prepareAsync(); void setVolume(int volume); - void setDisplay(jobject surfaceHolder); + void setDisplay(AndroidSurfaceTexture *surfaceTexture); static bool initJNI(JNIEnv *env); @@ -132,4 +134,4 @@ private: QT_END_NAMESPACE -#endif // QANDROIDMEDIAPLAYER_H +#endif // ANDROIDMEDIAPLAYER_H diff --git a/src/plugins/android/src/wrappers/jmediarecorder.cpp b/src/plugins/android/src/wrappers/jni/androidmediarecorder.cpp index 0b1498d99..71f88213f 100644 --- a/src/plugins/android/src/wrappers/jmediarecorder.cpp +++ b/src/plugins/android/src/wrappers/jni/androidmediarecorder.cpp @@ -39,33 +39,107 @@ ** ****************************************************************************/ -#include "jmediarecorder.h" +#include "androidmediarecorder.h" -#include "jcamera.h" +#include "androidcamera.h" #include <QtCore/private/qjni_p.h> #include <qmap.h> QT_BEGIN_NAMESPACE +typedef QMap<QString, QJNIObjectPrivate> CamcorderProfiles; +Q_GLOBAL_STATIC(CamcorderProfiles, g_camcorderProfiles) + +static QString profileKey() +{ + return QStringLiteral("%1-%2"); +} + +bool AndroidCamcorderProfile::hasProfile(jint cameraId, Quality quality) +{ + if (g_camcorderProfiles->contains(profileKey().arg(cameraId).arg(quality))) + return true; + + return QJNIObjectPrivate::callStaticMethod<jboolean>("android/media/CamcorderProfile", + "hasProfile", + "(II)Z", + cameraId, + quality); +} + +AndroidCamcorderProfile AndroidCamcorderProfile::get(jint cameraId, Quality quality) +{ + const QString key = profileKey().arg(cameraId).arg(quality); + QMap<QString, QJNIObjectPrivate>::const_iterator it = g_camcorderProfiles->constFind(key); + + if (it != g_camcorderProfiles->constEnd()) + return AndroidCamcorderProfile(*it); + + QJNIObjectPrivate camProfile = QJNIObjectPrivate::callStaticObjectMethod("android/media/CamcorderProfile", + "get", + "(II)Landroid/media/CamcorderProfile;", + cameraId, + quality); + + return AndroidCamcorderProfile((*g_camcorderProfiles)[key] = camProfile); +} + +int AndroidCamcorderProfile::getValue(AndroidCamcorderProfile::Field field) const +{ + switch (field) { + case audioBitRate: + return m_camcorderProfile.getField<jint>("audioBitRate"); + case audioChannels: + return m_camcorderProfile.getField<jint>("audioChannels"); + case audioCodec: + return m_camcorderProfile.getField<jint>("audioCodec"); + case audioSampleRate: + return m_camcorderProfile.getField<jint>("audioSampleRate"); + case duration: + return m_camcorderProfile.getField<jint>("duration"); + case fileFormat: + return m_camcorderProfile.getField<jint>("fileFormat"); + case quality: + return m_camcorderProfile.getField<jint>("quality"); + case videoBitRate: + return m_camcorderProfile.getField<jint>("videoBitRate"); + case videoCodec: + return m_camcorderProfile.getField<jint>("videoCodec"); + case videoFrameHeight: + return m_camcorderProfile.getField<jint>("videoFrameHeight"); + case videoFrameRate: + return m_camcorderProfile.getField<jint>("videoFrameRate"); + case videoFrameWidth: + return m_camcorderProfile.getField<jint>("videoFrameWidth"); + } + + return 0; +} + +AndroidCamcorderProfile::AndroidCamcorderProfile(const QJNIObjectPrivate &camcorderProfile) +{ + m_camcorderProfile = camcorderProfile; +} + static jclass g_qtMediaRecorderListenerClass = 0; -typedef QMap<jlong, JMediaRecorder*> MediaRecorderMap; +typedef QMap<jlong, AndroidMediaRecorder*> MediaRecorderMap; Q_GLOBAL_STATIC(MediaRecorderMap, mediaRecorders) static void notifyError(JNIEnv* , jobject, jlong id, jint what, jint extra) { - JMediaRecorder *obj = mediaRecorders->value(id, 0); + AndroidMediaRecorder *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 = mediaRecorders->value(id, 0); + AndroidMediaRecorder *obj = mediaRecorders->value(id, 0); if (obj) emit obj->info(what, extra); } -JMediaRecorder::JMediaRecorder() +AndroidMediaRecorder::AndroidMediaRecorder() : QObject() , m_id(reinterpret_cast<jlong>(this)) { @@ -82,17 +156,17 @@ JMediaRecorder::JMediaRecorder() } } -JMediaRecorder::~JMediaRecorder() +AndroidMediaRecorder::~AndroidMediaRecorder() { mediaRecorders->remove(m_id); } -void JMediaRecorder::release() +void AndroidMediaRecorder::release() { m_mediaRecorder.callMethod<void>("release"); } -bool JMediaRecorder::prepare() +bool AndroidMediaRecorder::prepare() { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("prepare"); @@ -106,12 +180,12 @@ bool JMediaRecorder::prepare() return true; } -void JMediaRecorder::reset() +void AndroidMediaRecorder::reset() { m_mediaRecorder.callMethod<void>("reset"); } -bool JMediaRecorder::start() +bool AndroidMediaRecorder::start() { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("start"); @@ -125,7 +199,7 @@ bool JMediaRecorder::start() return true; } -void JMediaRecorder::stop() +void AndroidMediaRecorder::stop() { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("stop"); @@ -137,12 +211,12 @@ void JMediaRecorder::stop() } } -void JMediaRecorder::setAudioChannels(int numChannels) +void AndroidMediaRecorder::setAudioChannels(int numChannels) { m_mediaRecorder.callMethod<void>("setAudioChannels", "(I)V", numChannels); } -void JMediaRecorder::setAudioEncoder(AudioEncoder encoder) +void AndroidMediaRecorder::setAudioEncoder(AudioEncoder encoder) { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("setAudioEncoder", "(I)V", int(encoder)); @@ -154,17 +228,17 @@ void JMediaRecorder::setAudioEncoder(AudioEncoder encoder) } } -void JMediaRecorder::setAudioEncodingBitRate(int bitRate) +void AndroidMediaRecorder::setAudioEncodingBitRate(int bitRate) { m_mediaRecorder.callMethod<void>("setAudioEncodingBitRate", "(I)V", bitRate); } -void JMediaRecorder::setAudioSamplingRate(int samplingRate) +void AndroidMediaRecorder::setAudioSamplingRate(int samplingRate) { m_mediaRecorder.callMethod<void>("setAudioSamplingRate", "(I)V", samplingRate); } -void JMediaRecorder::setAudioSource(AudioSource source) +void AndroidMediaRecorder::setAudioSource(AudioSource source) { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("setAudioSource", "(I)V", int(source)); @@ -176,13 +250,13 @@ void JMediaRecorder::setAudioSource(AudioSource source) } } -void JMediaRecorder::setCamera(JCamera *camera) +void AndroidMediaRecorder::setCamera(AndroidCamera *camera) { QJNIObjectPrivate cam = camera->getCameraObject(); m_mediaRecorder.callMethod<void>("setCamera", "(Landroid/hardware/Camera;)V", cam.object()); } -void JMediaRecorder::setVideoEncoder(VideoEncoder encoder) +void AndroidMediaRecorder::setVideoEncoder(VideoEncoder encoder) { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("setVideoEncoder", "(I)V", int(encoder)); @@ -194,12 +268,12 @@ void JMediaRecorder::setVideoEncoder(VideoEncoder encoder) } } -void JMediaRecorder::setVideoEncodingBitRate(int bitRate) +void AndroidMediaRecorder::setVideoEncodingBitRate(int bitRate) { m_mediaRecorder.callMethod<void>("setVideoEncodingBitRate", "(I)V", bitRate); } -void JMediaRecorder::setVideoFrameRate(int rate) +void AndroidMediaRecorder::setVideoFrameRate(int rate) { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("setVideoFrameRate", "(I)V", rate); @@ -211,7 +285,7 @@ void JMediaRecorder::setVideoFrameRate(int rate) } } -void JMediaRecorder::setVideoSize(const QSize &size) +void AndroidMediaRecorder::setVideoSize(const QSize &size) { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("setVideoSize", "(II)V", size.width(), size.height()); @@ -223,7 +297,7 @@ void JMediaRecorder::setVideoSize(const QSize &size) } } -void JMediaRecorder::setVideoSource(VideoSource source) +void AndroidMediaRecorder::setVideoSource(VideoSource source) { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("setVideoSource", "(I)V", int(source)); @@ -235,7 +309,7 @@ void JMediaRecorder::setVideoSource(VideoSource source) } } -void JMediaRecorder::setOrientationHint(int degrees) +void AndroidMediaRecorder::setOrientationHint(int degrees) { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("setOrientationHint", "(I)V", degrees); @@ -247,7 +321,7 @@ void JMediaRecorder::setOrientationHint(int degrees) } } -void JMediaRecorder::setOutputFormat(OutputFormat format) +void AndroidMediaRecorder::setOutputFormat(OutputFormat format) { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("setOutputFormat", "(I)V", int(format)); @@ -259,7 +333,7 @@ void JMediaRecorder::setOutputFormat(OutputFormat format) } } -void JMediaRecorder::setOutputFile(const QString &path) +void AndroidMediaRecorder::setOutputFile(const QString &path) { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("setOutputFile", @@ -278,7 +352,7 @@ static JNINativeMethod methods[] = { {"notifyInfo", "(JII)V", (void *)notifyInfo} }; -bool JMediaRecorder::initJNI(JNIEnv *env) +bool AndroidMediaRecorder::initJNI(JNIEnv *env) { jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtMediaRecorderListener"); if (env->ExceptionCheck()) diff --git a/src/plugins/android/src/wrappers/jmediarecorder.h b/src/plugins/android/src/wrappers/jni/androidmediarecorder.h index 3a83e7e16..686217dc8 100644 --- a/src/plugins/android/src/wrappers/jmediarecorder.h +++ b/src/plugins/android/src/wrappers/jni/androidmediarecorder.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef JMEDIARECORDER_H -#define JMEDIARECORDER_H +#ifndef ANDROIDMEDIARECORDER_H +#define ANDROIDMEDIARECORDER_H #include <qobject.h> #include <QtCore/private/qjni_p.h> @@ -48,9 +48,47 @@ QT_BEGIN_NAMESPACE -class JCamera; +class AndroidCamera; -class JMediaRecorder : public QObject +class AndroidCamcorderProfile +{ +public: + enum Quality { // Needs to match CamcorderProfile + QUALITY_LOW, + QUALITY_HIGH, + QUALITY_QCIF, + QUALITY_CIF, + QUALITY_480P, + QUALITY_720P, + QUALITY_1080P, + QUALITY_QVGA + }; + + enum Field { + audioBitRate, + audioChannels, + audioCodec, + audioSampleRate, + duration, + fileFormat, + quality, + videoBitRate, + videoCodec, + videoFrameHeight, + videoFrameRate, + videoFrameWidth + }; + + static bool hasProfile(jint cameraId, Quality quality); + static AndroidCamcorderProfile get(jint cameraId, Quality quality); + int getValue(Field field) const; + +private: + AndroidCamcorderProfile(const QJNIObjectPrivate &camcorderProfile); + QJNIObjectPrivate m_camcorderProfile; +}; + +class AndroidMediaRecorder : public QObject { Q_OBJECT public: @@ -91,8 +129,8 @@ public: AMR_WB_Format = 4 }; - JMediaRecorder(); - ~JMediaRecorder(); + AndroidMediaRecorder(); + ~AndroidMediaRecorder(); void release(); bool prepare(); @@ -107,7 +145,7 @@ public: void setAudioSamplingRate(int samplingRate); void setAudioSource(AudioSource source); - void setCamera(JCamera *camera); + void setCamera(AndroidCamera *camera); void setVideoEncoder(VideoEncoder encoder); void setVideoEncodingBitRate(int bitRate); void setVideoFrameRate(int rate); @@ -132,4 +170,4 @@ private: QT_END_NAMESPACE -#endif // JMEDIARECORDER_H +#endif // ANDROIDMEDIARECORDER_H diff --git a/src/plugins/android/src/wrappers/jmultimediautils.cpp b/src/plugins/android/src/wrappers/jni/androidmultimediautils.cpp index d1b0830c7..5c2f19a06 100644 --- a/src/plugins/android/src/wrappers/jmultimediautils.cpp +++ b/src/plugins/android/src/wrappers/jni/androidmultimediautils.cpp @@ -39,14 +39,14 @@ ** ****************************************************************************/ -#include "jmultimediautils.h" +#include "androidmultimediautils.h" #include <QtCore/private/qjni_p.h> QT_BEGIN_NAMESPACE -void JMultimediaUtils::enableOrientationListener(bool enable) +void AndroidMultimediaUtils::enableOrientationListener(bool enable) { QJNIObjectPrivate::callStaticMethod<void>("org/qtproject/qt5/android/multimedia/QtMultimediaUtils", "enableOrientationListener", @@ -54,13 +54,13 @@ void JMultimediaUtils::enableOrientationListener(bool enable) enable); } -int JMultimediaUtils::getDeviceOrientation() +int AndroidMultimediaUtils::getDeviceOrientation() { return QJNIObjectPrivate::callStaticMethod<jint>("org/qtproject/qt5/android/multimedia/QtMultimediaUtils", "getDeviceOrientation"); } -QString JMultimediaUtils::getDefaultMediaDirectory(MediaType type) +QString AndroidMultimediaUtils::getDefaultMediaDirectory(MediaType type) { QJNIObjectPrivate path = QJNIObjectPrivate::callStaticObjectMethod("org/qtproject/qt5/android/multimedia/QtMultimediaUtils", "getDefaultMediaDirectory", @@ -69,7 +69,7 @@ QString JMultimediaUtils::getDefaultMediaDirectory(MediaType type) return path.toString(); } -void JMultimediaUtils::registerMediaFile(const QString &file) +void AndroidMultimediaUtils::registerMediaFile(const QString &file) { QJNIObjectPrivate::callStaticMethod<void>("org/qtproject/qt5/android/multimedia/QtMultimediaUtils", "registerMediaFile", diff --git a/src/plugins/android/src/wrappers/jmultimediautils.h b/src/plugins/android/src/wrappers/jni/androidmultimediautils.h index b80ef4236..4617b08f8 100644 --- a/src/plugins/android/src/wrappers/jmultimediautils.h +++ b/src/plugins/android/src/wrappers/jni/androidmultimediautils.h @@ -39,15 +39,15 @@ ** ****************************************************************************/ -#ifndef JMULTIMEDIAUTILS_H -#define JMULTIMEDIAUTILS_H +#ifndef ANDROIDMULTIMEDIAUTILS_H +#define ANDROIDMULTIMEDIAUTILS_H #include <qobject.h> #include <QtCore/private/qjni_p.h> QT_BEGIN_NAMESPACE -class JMultimediaUtils +class AndroidMultimediaUtils { public: enum MediaType { @@ -65,4 +65,4 @@ public: QT_END_NAMESPACE -#endif // JMULTIMEDIAUTILS_H +#endif // ANDROIDMULTIMEDIAUTILS_H diff --git a/src/plugins/android/src/wrappers/jsurfacetexture.cpp b/src/plugins/android/src/wrappers/jni/androidsurfacetexture.cpp index 2b16ebd66..06dcd74ca 100644 --- a/src/plugins/android/src/wrappers/jsurfacetexture.cpp +++ b/src/plugins/android/src/wrappers/jni/androidsurfacetexture.cpp @@ -39,24 +39,24 @@ ** ****************************************************************************/ -#include "jsurfacetexture.h" +#include "androidsurfacetexture.h" #include <QtCore/private/qjni_p.h> #include <QtCore/private/qjnihelpers_p.h> QT_BEGIN_NAMESPACE static jclass g_qtSurfaceTextureListenerClass = 0; -static QMap<int, JSurfaceTexture*> g_objectMap; +static QMap<int, AndroidSurfaceTexture*> g_objectMap; // native method for QtSurfaceTexture.java static void notifyFrameAvailable(JNIEnv* , jobject, int id) { - JSurfaceTexture *obj = g_objectMap.value(id, 0); + AndroidSurfaceTexture *obj = g_objectMap.value(id, 0); if (obj) Q_EMIT obj->frameAvailable(); } -JSurfaceTexture::JSurfaceTexture(unsigned int texName) +AndroidSurfaceTexture::AndroidSurfaceTexture(unsigned int texName) : QObject() , m_texID(int(texName)) { @@ -84,15 +84,18 @@ JSurfaceTexture::JSurfaceTexture(unsigned int texName) listener.object()); } -JSurfaceTexture::~JSurfaceTexture() +AndroidSurfaceTexture::~AndroidSurfaceTexture() { + if (QtAndroidPrivate::androidSdkVersion() > 13 && m_surfaceView.isValid()) + m_surfaceView.callMethod<void>("release"); + if (m_surfaceTexture.isValid()) { release(); g_objectMap.remove(m_texID); } } -QMatrix4x4 JSurfaceTexture::getTransformMatrix() +QMatrix4x4 AndroidSurfaceTexture::getTransformMatrix() { QMatrix4x4 matrix; if (!m_surfaceTexture.isValid()) @@ -108,7 +111,7 @@ QMatrix4x4 JSurfaceTexture::getTransformMatrix() return matrix; } -void JSurfaceTexture::release() +void AndroidSurfaceTexture::release() { if (QtAndroidPrivate::androidSdkVersion() < 14) return; @@ -116,7 +119,7 @@ void JSurfaceTexture::release() m_surfaceTexture.callMethod<void>("release"); } -void JSurfaceTexture::updateTexImage() +void AndroidSurfaceTexture::updateTexImage() { if (!m_surfaceTexture.isValid()) return; @@ -124,16 +127,36 @@ void JSurfaceTexture::updateTexImage() m_surfaceTexture.callMethod<void>("updateTexImage"); } -jobject JSurfaceTexture::object() +jobject AndroidSurfaceTexture::surfaceTexture() { return m_surfaceTexture.object(); } +jobject AndroidSurfaceTexture::surfaceView() +{ + return m_surfaceView.object(); +} + +jobject AndroidSurfaceTexture::surfaceHolder() +{ + if (!m_surfaceHolder.isValid()) { + m_surfaceView = QJNIObjectPrivate("android/view/Surface", + "(Landroid/graphics/SurfaceTexture;)V", + m_surfaceTexture.object()); + + m_surfaceHolder = QJNIObjectPrivate("org/qtproject/qt5/android/multimedia/QtSurfaceTextureHolder", + "(Landroid/view/Surface;)V", + m_surfaceView.object()); + } + + return m_surfaceHolder.object(); +} + static JNINativeMethod methods[] = { {"notifyFrameAvailable", "(I)V", (void *)notifyFrameAvailable} }; -bool JSurfaceTexture::initJNI(JNIEnv *env) +bool AndroidSurfaceTexture::initJNI(JNIEnv *env) { // SurfaceTexture is available since API 11. if (QtAndroidPrivate::androidSdkVersion() < 11) diff --git a/src/plugins/android/src/wrappers/jsurfacetexture.h b/src/plugins/android/src/wrappers/jni/androidsurfacetexture.h index d53290a71..ee49244cd 100644 --- a/src/plugins/android/src/wrappers/jsurfacetexture.h +++ b/src/plugins/android/src/wrappers/jni/androidsurfacetexture.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef JSURFACETEXTURE_H -#define JSURFACETEXTURE_H +#ifndef ANDROIDSURFACETEXTURE_H +#define ANDROIDSURFACETEXTURE_H #include <qobject.h> #include <QtCore/private/qjni_p.h> @@ -49,15 +49,18 @@ QT_BEGIN_NAMESPACE -class JSurfaceTexture : public QObject +class AndroidSurfaceTexture : public QObject { Q_OBJECT public: - explicit JSurfaceTexture(unsigned int texName); - ~JSurfaceTexture(); + explicit AndroidSurfaceTexture(unsigned int texName); + ~AndroidSurfaceTexture(); int textureID() const { return m_texID; } - jobject object(); + jobject surfaceTexture(); + jobject surfaceView(); + jobject surfaceHolder(); + inline bool isValid() const { return m_surfaceTexture.isValid(); } QMatrix4x4 getTransformMatrix(); void release(); // API level 14 @@ -71,8 +74,10 @@ Q_SIGNALS: private: int m_texID; QJNIObjectPrivate m_surfaceTexture; + QJNIObjectPrivate m_surfaceView; + QJNIObjectPrivate m_surfaceHolder; }; QT_END_NAMESPACE -#endif // JSURFACETEXTURE_H +#endif // ANDROIDSURFACETEXTURE_H diff --git a/src/plugins/android/src/wrappers/jni/jni.pri b/src/plugins/android/src/wrappers/jni/jni.pri new file mode 100644 index 000000000..ba2ad0801 --- /dev/null +++ b/src/plugins/android/src/wrappers/jni/jni.pri @@ -0,0 +1,19 @@ +QT += platformsupport-private + +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/androidmediaplayer.h \ + $$PWD/androidsurfacetexture.h \ + $$PWD/androidmediametadataretriever.h \ + $$PWD/androidcamera.h \ + $$PWD/androidmultimediautils.h \ + $$PWD/androidmediarecorder.h + +SOURCES += \ + $$PWD/androidmediaplayer.cpp \ + $$PWD/androidsurfacetexture.cpp \ + $$PWD/androidmediametadataretriever.cpp \ + $$PWD/androidcamera.cpp \ + $$PWD/androidmultimediautils.cpp \ + $$PWD/androidmediarecorder.cpp diff --git a/src/plugins/android/src/wrappers/wrappers.pri b/src/plugins/android/src/wrappers/wrappers.pri deleted file mode 100644 index 126cfd0c1..000000000 --- a/src/plugins/android/src/wrappers/wrappers.pri +++ /dev/null @@ -1,19 +0,0 @@ -QT += platformsupport-private - -INCLUDEPATH += $$PWD - -HEADERS += \ - $$PWD/jmediaplayer.h \ - $$PWD/jsurfacetexture.h \ - $$PWD/jmediametadataretriever.h \ - $$PWD/jcamera.h \ - $$PWD/jmultimediautils.h \ - $$PWD/jmediarecorder.h - -SOURCES += \ - $$PWD/jmediaplayer.cpp \ - $$PWD/jsurfacetexture.cpp \ - $$PWD/jmediametadataretriever.cpp \ - $$PWD/jcamera.cpp \ - $$PWD/jmultimediautils.cpp \ - $$PWD/jmediarecorder.cpp diff --git a/src/plugins/directshow/player/directshowiosource.cpp b/src/plugins/directshow/player/directshowiosource.cpp index acce1de28..c6cb21824 100644 --- a/src/plugins/directshow/player/directshowiosource.cpp +++ b/src/plugins/directshow/player/directshowiosource.cpp @@ -622,17 +622,10 @@ DirectShowRcSource::DirectShowRcSource(DirectShowEventLoop *loop) bool DirectShowRcSource::open(const QUrl &url) { m_file.moveToThread(QCoreApplication::instance()->thread()); - m_file.setFileName(QLatin1Char(':') + url.path()); - qDebug("qrc file %s", qPrintable(m_file.fileName())); - if (m_file.open(QIODevice::ReadOnly)) { - qDebug("Size %d", int(m_file.size())); - qDebug("Sequential %d", int(m_file.isSequential())); - setDevice(&m_file); - return true; } else { return false; diff --git a/src/plugins/directshow/player/directshowmetadatacontrol.cpp b/src/plugins/directshow/player/directshowmetadatacontrol.cpp index 51d9574ba..96c9fab8b 100644 --- a/src/plugins/directshow/player/directshowmetadatacontrol.cpp +++ b/src/plugins/directshow/player/directshowmetadatacontrol.cpp @@ -104,75 +104,85 @@ static q_SHCreateItemFromParsingName sHCreateItemFromParsingName = 0; #endif #ifndef QT_NO_WMSDK + namespace { - struct QWMMetaDataKeyLookup + struct QWMMetaDataKey { - QString key; - const wchar_t *token; + QString qtName; + const wchar_t *wmName; + + QWMMetaDataKey(const QString &qtn, const wchar_t *wmn) : qtName(qtn), wmName(wmn) { } }; } -static const QWMMetaDataKeyLookup qt_wmMetaDataKeys[] = +typedef QList<QWMMetaDataKey> QWMMetaDataKeys; +Q_GLOBAL_STATIC(QWMMetaDataKeys, metadataKeys) + +static const QWMMetaDataKeys *qt_wmMetaDataKeys() { - { QMediaMetaData::Title, L"Title" }, - { QMediaMetaData::SubTitle, L"WM/SubTitle" }, - { QMediaMetaData::Author, L"Author" }, - { QMediaMetaData::Comment, L"Comment" }, - { QMediaMetaData::Description, L"Description" }, - { QMediaMetaData::Category, L"WM/Category" }, - { QMediaMetaData::Genre, L"WM/Genre" }, - //{ QMediaMetaData::Date, 0 }, - { QMediaMetaData::Year, L"WM/Year" }, - { QMediaMetaData::UserRating, L"Rating" }, - //{ QMediaMetaData::MetaDatawords, 0 }, - { QMediaMetaData::Language, L"WM/Language" }, - { QMediaMetaData::Publisher, L"WM/Publisher" }, - { QMediaMetaData::Copyright, L"Copyright" }, - { QMediaMetaData::ParentalRating, L"WM/ParentalRating" }, - //{ QMediaMetaData::RatingOrganisation, L"RatingOrganisation" }, - - // Media - { QMediaMetaData::Size, L"FileSize" }, - { QMediaMetaData::MediaType, L"MediaType" }, - { QMediaMetaData::Duration, L"Duration" }, - - // Audio - { QMediaMetaData::AudioBitRate, L"AudioBitRate" }, - { QMediaMetaData::AudioCodec, L"AudioCodec" }, - { QMediaMetaData::ChannelCount, L"ChannelCount" }, - { QMediaMetaData::SampleRate, L"Frequency" }, - - // Music - { QMediaMetaData::AlbumTitle, L"WM/AlbumTitle" }, - { QMediaMetaData::AlbumArtist, L"WM/AlbumArtist" }, - { QMediaMetaData::ContributingArtist, L"Author" }, - { QMediaMetaData::Composer, L"WM/Composer" }, - { QMediaMetaData::Conductor, L"WM/Conductor" }, - { QMediaMetaData::Lyrics, L"WM/Lyrics" }, - { QMediaMetaData::Mood, L"WM/Mood" }, - { QMediaMetaData::TrackNumber, L"WM/TrackNumber" }, - //{ QMediaMetaData::TrackCount, 0 }, - //{ QMediaMetaData::CoverArtUriSmall, 0 }, - //{ QMediaMetaData::CoverArtUriLarge, 0 }, - - // Image/Video - { QMediaMetaData::Resolution, L"WM/VideoHeight" }, - { QMediaMetaData::PixelAspectRatio, L"AspectRatioX" }, - - // Video - { QMediaMetaData::VideoFrameRate, L"WM/VideoFrameRate" }, - { QMediaMetaData::VideoBitRate, L"VideoBitRate" }, - { QMediaMetaData::VideoCodec, L"VideoCodec" }, - - //{ QMediaMetaData::PosterUri, 0 }, - - // Movie - { QMediaMetaData::ChapterNumber, L"ChapterNumber" }, - { QMediaMetaData::Director, L"WM/Director" }, - { QMediaMetaData::LeadPerformer, L"LeadPerformer" }, - { QMediaMetaData::Writer, L"WM/Writer" }, -}; + if (metadataKeys->isEmpty()) { + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Title, L"Title")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::SubTitle, L"WM/SubTitle")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Author, L"Author")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Comment, L"Comment")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Description, L"Description")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Category, L"WM/Category")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Genre, L"WM/Genre")); + //metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Date, 0)); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Year, L"WM/Year")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::UserRating, L"Rating")); + //metadataKeys->append(QWMMetaDataKey(QMediaMetaData::MetaDatawords, 0)); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Language, L"WM/Language")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Publisher, L"WM/Publisher")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Copyright, L"Copyright")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::ParentalRating, L"WM/ParentalRating")); + //metadataKeys->append(QWMMetaDataKey(QMediaMetaData::RatingOrganisation, L"RatingOrganisation")); + + // Media + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Size, L"FileSize")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::MediaType, L"MediaType")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Duration, L"Duration")); + + // Audio + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::AudioBitRate, L"AudioBitRate")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::AudioCodec, L"AudioCodec")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::ChannelCount, L"ChannelCount")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::SampleRate, L"Frequency")); + + // Music + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::AlbumTitle, L"WM/AlbumTitle")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::AlbumArtist, L"WM/AlbumArtist")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::ContributingArtist, L"Author")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Composer, L"WM/Composer")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Conductor, L"WM/Conductor")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Lyrics, L"WM/Lyrics")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Mood, L"WM/Mood")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::TrackNumber, L"WM/TrackNumber")); + //metadataKeys->append(QWMMetaDataKey(QMediaMetaData::TrackCount, 0)); + //metadataKeys->append(QWMMetaDataKey(QMediaMetaData::CoverArtUriSmall, 0)); + //metadataKeys->append(QWMMetaDataKey(QMediaMetaData::CoverArtUriLarge, 0)); + + // Image/Video + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Resolution, L"WM/VideoHeight")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::PixelAspectRatio, L"AspectRatioX")); + + // Video + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::VideoFrameRate, L"WM/VideoFrameRate")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::VideoBitRate, L"VideoBitRate")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::VideoCodec, L"VideoCodec")); + + //metadataKeys->append(QWMMetaDataKey(QMediaMetaData::PosterUri, 0)); + + // Movie + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::ChapterNumber, L"ChapterNumber")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Director, L"WM/Director")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::LeadPerformer, L"LeadPerformer")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Writer, L"WM/Writer")); + } + + return metadataKeys; +} static QVariant getValue(IWMHeaderInfo *header, const wchar_t *key) { @@ -491,32 +501,29 @@ void DirectShowMetaDataControl::updateGraph(IFilterGraph2 *graph, IBaseFilter *s IWMHeaderInfo *info = com_cast<IWMHeaderInfo>(source, IID_IWMHeaderInfo); if (info) { - static const int count = sizeof(qt_wmMetaDataKeys) / sizeof(QWMMetaDataKeyLookup); - for (int i = 0; i < count; ++i) { - QVariant var = getValue(info, qt_wmMetaDataKeys[i].token); + Q_FOREACH (const QWMMetaDataKey &key, *qt_wmMetaDataKeys()) { + QVariant var = getValue(info, key.wmName); if (var.isValid()) { - QString key = qt_wmMetaDataKeys[i].key; - - if (key == QMediaMetaData::Duration) { + if (key.qtName == QMediaMetaData::Duration) { // duration is provided in 100-nanosecond units, convert to milliseconds var = (var.toLongLong() + 10000) / 10000; - } else if (key == QMediaMetaData::Resolution) { + } else if (key.qtName == QMediaMetaData::Resolution) { QSize res; res.setHeight(var.toUInt()); res.setWidth(getValue(info, L"WM/VideoWidth").toUInt()); var = res; - } else if (key == QMediaMetaData::VideoFrameRate) { + } else if (key.qtName == QMediaMetaData::VideoFrameRate) { var = var.toReal() / 1000.f; - } else if (key == QMediaMetaData::PixelAspectRatio) { + } else if (key.qtName == QMediaMetaData::PixelAspectRatio) { QSize aspectRatio; aspectRatio.setWidth(var.toUInt()); aspectRatio.setHeight(getValue(info, L"AspectRatioY").toUInt()); var = aspectRatio; - } else if (key == QMediaMetaData::UserRating) { + } else if (key.qtName == QMediaMetaData::UserRating) { var = (var.toUInt() - 1) / qreal(98) * 100; } - m_metadata.insert(key, var); + m_metadata.insert(key.qtName, var); } } diff --git a/src/plugins/gstreamer/camerabin/camerabinmetadata.cpp b/src/plugins/gstreamer/camerabin/camerabinmetadata.cpp index c2b7c33c3..170d25a07 100644 --- a/src/plugins/gstreamer/camerabin/camerabinmetadata.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinmetadata.cpp @@ -50,13 +50,6 @@ QT_BEGIN_NAMESPACE -struct QGstreamerMetaDataKeyLookup -{ - QString key; - const char *token; - QVariant::Type type; -}; - static QVariant fromGStreamerOrientation(const QVariant &value) { // Note gstreamer tokens either describe the counter clockwise rotation of the @@ -87,87 +80,109 @@ static QVariant toGStreamerOrientation(const QVariant &value) } } -static const QGstreamerMetaDataKeyLookup qt_gstreamerMetaDataKeys[] = +namespace { + struct QGStreamerMetaDataKey + { + QString qtName; + const char *gstName; + QVariant::Type type; + + QGStreamerMetaDataKey(const QString &qtn, const char *gstn, QVariant::Type t) + : qtName(qtn) + , gstName(gstn) + , type(t) + { } + }; +} + +typedef QList<QGStreamerMetaDataKey> QGStreamerMetaDataKeys; +Q_GLOBAL_STATIC(QGStreamerMetaDataKeys, metadataKeys) + +static const QGStreamerMetaDataKeys *qt_gstreamerMetaDataKeys() { - { QMediaMetaData::Title, GST_TAG_TITLE, QVariant::String }, - //{ QMediaMetaData::SubTitle, 0, QVariant::String }, - //{ QMediaMetaData::Author, 0, QVariant::String }, - { QMediaMetaData::Comment, GST_TAG_COMMENT, QVariant::String }, - { QMediaMetaData::Date, GST_TAG_DATE_TIME, QVariant::DateTime }, - { QMediaMetaData::Description, GST_TAG_DESCRIPTION, QVariant::String }, - //{ QMediaMetaData::Category, 0, QVariant::String }, - { QMediaMetaData::Genre, GST_TAG_GENRE, QVariant::String }, - //{ QMediaMetaData::Year, 0, QVariant::Int }, - //{ QMediaMetaData::UserRating, , QVariant::Int }, - - { QMediaMetaData::Language, GST_TAG_LANGUAGE_CODE, QVariant::String }, - - { QMediaMetaData::Publisher, GST_TAG_ORGANIZATION, QVariant::String }, - { QMediaMetaData::Copyright, GST_TAG_COPYRIGHT, QVariant::String }, - //{ QMediaMetaData::ParentalRating, 0, QVariant::String }, - //{ QMediaMetaData::RatingOrganisation, 0, QVariant::String }, - - // Media - //{ QMediaMetaData::Size, 0, QVariant::Int }, - //{ QMediaMetaData::MediaType, 0, QVariant::String }, - { QMediaMetaData::Duration, GST_TAG_DURATION, QVariant::Int }, - - // Audio - { QMediaMetaData::AudioBitRate, GST_TAG_BITRATE, QVariant::Int }, - { QMediaMetaData::AudioCodec, GST_TAG_AUDIO_CODEC, QVariant::String }, - //{ QMediaMetaData::ChannelCount, 0, QVariant::Int }, - //{ QMediaMetaData::SampleRate, 0, QVariant::Int }, - - // Music - { QMediaMetaData::AlbumTitle, GST_TAG_ALBUM, QVariant::String }, - { QMediaMetaData::AlbumArtist, GST_TAG_ARTIST, QVariant::String}, - { QMediaMetaData::ContributingArtist, GST_TAG_PERFORMER, QVariant::String }, + if (metadataKeys->isEmpty()) { + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Title, GST_TAG_TITLE, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::SubTitle, 0, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Author, 0, QVariant::String)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Comment, GST_TAG_COMMENT, QVariant::String)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Date, GST_TAG_DATE_TIME, QVariant::DateTime)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Description, GST_TAG_DESCRIPTION, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Category, 0, QVariant::String)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Genre, GST_TAG_GENRE, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Year, 0, QVariant::Int)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::UserRating, , QVariant::Int)); + + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Language, GST_TAG_LANGUAGE_CODE, QVariant::String)); + + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Publisher, GST_TAG_ORGANIZATION, QVariant::String)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Copyright, GST_TAG_COPYRIGHT, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::ParentalRating, 0, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::RatingOrganisation, 0, QVariant::String)); + + // Media + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Size, 0, QVariant::Int)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::MediaType, 0, QVariant::String)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Duration, GST_TAG_DURATION, QVariant::Int)); + + // Audio + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::AudioBitRate, GST_TAG_BITRATE, QVariant::Int)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::AudioCodec, GST_TAG_AUDIO_CODEC, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::ChannelCount, 0, QVariant::Int)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::SampleRate, 0, QVariant::Int)); + + // Music + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::AlbumTitle, GST_TAG_ALBUM, QVariant::String)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::AlbumArtist, GST_TAG_ARTIST, QVariant::String)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::ContributingArtist, GST_TAG_PERFORMER, QVariant::String)); #if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19) - { QMediaMetaData::Composer, GST_TAG_COMPOSER, QVariant::String }, + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Composer, GST_TAG_COMPOSER, QVariant::String)); #endif - //{ QMediaMetaData::Conductor, 0, QVariant::String }, - //{ QMediaMetaData::Lyrics, 0, QVariant::String }, - //{ QMediaMetaData::Mood, 0, QVariant::String }, - { QMediaMetaData::TrackNumber, GST_TAG_TRACK_NUMBER, QVariant::Int }, + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Conductor, 0, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Lyrics, 0, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Mood, 0, QVariant::String)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::TrackNumber, GST_TAG_TRACK_NUMBER, QVariant::Int)); - //{ QMediaMetaData::CoverArtUrlSmall, 0, QVariant::String }, - //{ QMediaMetaData::CoverArtUrlLarge, 0, QVariant::String }, + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::CoverArtUrlSmall, 0, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::CoverArtUrlLarge, 0, QVariant::String)); - // Image/Video - //{ QMediaMetaData::Resolution, 0, QVariant::Size }, - //{ QMediaMetaData::PixelAspectRatio, 0, QVariant::Size }, + // Image/Video + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Resolution, 0, QVariant::Size)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::PixelAspectRatio, 0, QVariant::Size)); - // Video - //{ QMediaMetaData::VideoFrameRate, 0, QVariant::String }, - //{ QMediaMetaData::VideoBitRate, 0, QVariant::Double }, - { QMediaMetaData::VideoCodec, GST_TAG_VIDEO_CODEC, QVariant::String }, + // Video + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::VideoFrameRate, 0, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::VideoBitRate, 0, QVariant::Double)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::VideoCodec, GST_TAG_VIDEO_CODEC, QVariant::String)); - //{ QMediaMetaData::PosterUrl, 0, QVariant::String }, + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::PosterUrl, 0, QVariant::String)); - // Movie - //{ QMediaMetaData::ChapterNumber, 0, QVariant::Int }, - //{ QMediaMetaData::Director, 0, QVariant::String }, - { QMediaMetaData::LeadPerformer, GST_TAG_PERFORMER, QVariant::String }, - //{ QMediaMetaData::Writer, 0, QVariant::String }, + // Movie + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::ChapterNumber, 0, QVariant::Int)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Director, 0, QVariant::String)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::LeadPerformer, GST_TAG_PERFORMER, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Writer, 0, QVariant::String)); #if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 30) - // Photos - { QMediaMetaData::CameraManufacturer, GST_TAG_DEVICE_MANUFACTURER, QVariant::String }, - { QMediaMetaData::CameraModel, GST_TAG_DEVICE_MODEL, QVariant::String }, - //{ QMediaMetaData::Event, 0, QVariant::String }, - //{ QMediaMetaData::Subject, 0, QVariant::String }, - - { QMediaMetaData::Orientation, GST_TAG_IMAGE_ORIENTATION, QVariant::String }, - - // GPS - { QMediaMetaData::GPSLatitude, GST_TAG_GEO_LOCATION_LATITUDE, QVariant::Double }, - { QMediaMetaData::GPSLongitude, GST_TAG_GEO_LOCATION_LONGITUDE, QVariant::Double }, - { QMediaMetaData::GPSAltitude, GST_TAG_GEO_LOCATION_ELEVATION, QVariant::Double }, - { QMediaMetaData::GPSTrack, GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, QVariant::Double }, - { QMediaMetaData::GPSSpeed, GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, QVariant::Double }, - { QMediaMetaData::GPSImgDirection, GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, QVariant::Double } + // Photos + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::CameraManufacturer, GST_TAG_DEVICE_MANUFACTURER, QVariant::String)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::CameraModel, GST_TAG_DEVICE_MODEL, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Event, 0, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Subject, 0, QVariant::String)); + + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Orientation, GST_TAG_IMAGE_ORIENTATION, QVariant::String)); + + // GPS + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::GPSLatitude, GST_TAG_GEO_LOCATION_LATITUDE, QVariant::Double)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::GPSLongitude, GST_TAG_GEO_LOCATION_LONGITUDE, QVariant::Double)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::GPSAltitude, GST_TAG_GEO_LOCATION_ELEVATION, QVariant::Double)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::GPSTrack, GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, QVariant::Double)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::GPSSpeed, GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, QVariant::Double)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::GPSImgDirection, GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, QVariant::Double)); #endif -}; + } + + return metadataKeys; +} CameraBinMetaData::CameraBinMetaData(QObject *parent) :QMetaDataWriterControl(parent) @@ -183,14 +198,9 @@ QVariant CameraBinMetaData::metaData(const QString &key) const return (metersPerSec * 3600) / 1000; } - static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup); - - for (int i = 0; i < count; ++i) { - if (qt_gstreamerMetaDataKeys[i].key == key) { - const char *name = qt_gstreamerMetaDataKeys[i].token; - - return m_values.value(QByteArray::fromRawData(name, qstrlen(name))); - } + Q_FOREACH (const QGStreamerMetaDataKey &metadataKey, *qt_gstreamerMetaDataKeys()) { + if (metadataKey.qtName == key) + return m_values.value(QByteArray::fromRawData(metadataKey.gstName, qstrlen(metadataKey.gstName))); } return QVariant(); } @@ -207,14 +217,12 @@ void CameraBinMetaData::setMetaData(const QString &key, const QVariant &value) } } - static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup); - - for (int i = 0; i < count; ++i) { - if (qt_gstreamerMetaDataKeys[i].key == key) { - const char *name = qt_gstreamerMetaDataKeys[i].token; + Q_FOREACH (const QGStreamerMetaDataKey &metadataKey, *qt_gstreamerMetaDataKeys()) { + if (metadataKey.qtName == key) { + const char *name = metadataKey.gstName; if (correctedValue.isValid()) { - correctedValue.convert(qt_gstreamerMetaDataKeys[i].type); + correctedValue.convert(metadataKey.type); m_values.insert(QByteArray::fromRawData(name, qstrlen(name)), correctedValue); } else { m_values.remove(QByteArray::fromRawData(name, qstrlen(name))); @@ -232,14 +240,12 @@ QStringList CameraBinMetaData::availableMetaData() const { static QMap<QByteArray, QString> keysMap; if (keysMap.isEmpty()) { - const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup); - for (int i = 0; i < count; ++i) { - keysMap[QByteArray(qt_gstreamerMetaDataKeys[i].token)] = qt_gstreamerMetaDataKeys[i].key; - } + Q_FOREACH (const QGStreamerMetaDataKey &metadataKey, *qt_gstreamerMetaDataKeys()) + keysMap[QByteArray(metadataKey.gstName)] = metadataKey.qtName; } QStringList res; - foreach (const QByteArray &key, m_values.keys()) { + Q_FOREACH (const QByteArray &key, m_values.keys()) { QString tag = keysMap.value(key); if (!tag.isEmpty()) res.append(tag); diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp index fd7fb7d82..1080a5875 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp @@ -46,80 +46,82 @@ #include <gst/gst.h> #include <gst/gstversion.h> -struct QGstreamerMetaDataKeyLookup -{ - QString key; - const char *token; -}; -static const QGstreamerMetaDataKeyLookup qt_gstreamerMetaDataKeys[] = +typedef QMap<QString, QByteArray> QGstreamerMetaDataKeyLookup; +Q_GLOBAL_STATIC(QGstreamerMetaDataKeyLookup, metadataKeys) + +static const QGstreamerMetaDataKeyLookup *qt_gstreamerMetaDataKeys() { - { QMediaMetaData::Title, GST_TAG_TITLE }, - //{ QMediaMetaData::SubTitle, 0 }, - //{ QMediaMetaData::Author, 0 }, - { QMediaMetaData::Comment, GST_TAG_COMMENT }, - { QMediaMetaData::Description, GST_TAG_DESCRIPTION }, - //{ QMediaMetaData::Category, 0 }, - { QMediaMetaData::Genre, GST_TAG_GENRE }, - //{ QMediaMetaData::Year, 0 }, - //{ QMediaMetaData::UserRating, 0 }, - - { QMediaMetaData::Language, GST_TAG_LANGUAGE_CODE }, - - { QMediaMetaData::Publisher, GST_TAG_ORGANIZATION }, - { QMediaMetaData::Copyright, GST_TAG_COPYRIGHT }, - //{ QMediaMetaData::ParentalRating, 0 }, - //{ QMediaMetaData::RatingOrganisation, 0 }, - - // Media - //{ QMediaMetaData::Size, 0 }, - //{ QMediaMetaData::MediaType, 0 }, - { QMediaMetaData::Duration, GST_TAG_DURATION }, - - // Audio - { QMediaMetaData::AudioBitRate, GST_TAG_BITRATE }, - { QMediaMetaData::AudioCodec, GST_TAG_AUDIO_CODEC }, - //{ QMediaMetaData::ChannelCount, 0 }, - //{ QMediaMetaData::SampleRate, 0 }, - - // Music - { QMediaMetaData::AlbumTitle, GST_TAG_ALBUM }, - { QMediaMetaData::AlbumArtist, GST_TAG_ARTIST}, - { QMediaMetaData::ContributingArtist, GST_TAG_PERFORMER }, + if (metadataKeys->isEmpty()) { + metadataKeys->insert(QMediaMetaData::Title, GST_TAG_TITLE); + metadataKeys->insert(QMediaMetaData::SubTitle, 0); + //metadataKeys->insert(QMediaMetaData::Author, 0); + metadataKeys->insert(QMediaMetaData::Comment, GST_TAG_COMMENT); + metadataKeys->insert(QMediaMetaData::Description, GST_TAG_DESCRIPTION); + //metadataKeys->insert(QMediaMetaData::Category, 0); + metadataKeys->insert(QMediaMetaData::Genre, GST_TAG_GENRE); + //metadataKeys->insert(QMediaMetaData::Year, 0); + //metadataKeys->insert(QMediaMetaData::UserRating, 0); + + metadataKeys->insert(QMediaMetaData::Language, GST_TAG_LANGUAGE_CODE); + + metadataKeys->insert(QMediaMetaData::Publisher, GST_TAG_ORGANIZATION); + metadataKeys->insert(QMediaMetaData::Copyright, GST_TAG_COPYRIGHT); + //metadataKeys->insert(QMediaMetaData::ParentalRating, 0); + //metadataKeys->insert(QMediaMetaData::RatingOrganisation, 0); + + // Media + //metadataKeys->insert(QMediaMetaData::Size, 0); + //metadataKeys->insert(QMediaMetaData::MediaType, 0); + metadataKeys->insert(QMediaMetaData::Duration, GST_TAG_DURATION); + + // Audio + metadataKeys->insert(QMediaMetaData::AudioBitRate, GST_TAG_BITRATE); + metadataKeys->insert(QMediaMetaData::AudioCodec, GST_TAG_AUDIO_CODEC); + //metadataKeys->insert(QMediaMetaData::ChannelCount, 0); + //metadataKeys->insert(QMediaMetaData::SampleRate, 0); + + // Music + metadataKeys->insert(QMediaMetaData::AlbumTitle, GST_TAG_ALBUM); + metadataKeys->insert(QMediaMetaData::AlbumArtist, GST_TAG_ARTIST); + metadataKeys->insert(QMediaMetaData::ContributingArtist, GST_TAG_PERFORMER); #if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19) - { QMediaMetaData::Composer, GST_TAG_COMPOSER }, + metadataKeys->insert(QMediaMetaData::Composer, GST_TAG_COMPOSER); #endif - //{ QMediaMetaData::Conductor, 0 }, - //{ QMediaMetaData::Lyrics, 0 }, - //{ QMediaMetaData::Mood, 0 }, - { QMediaMetaData::TrackNumber, GST_TAG_TRACK_NUMBER }, - - //{ QMediaMetaData::CoverArtUrlSmall, 0 }, - //{ QMediaMetaData::CoverArtUrlLarge, 0 }, - - // Image/Video - //{ QMediaMetaData::Resolution, 0 }, - //{ QMediaMetaData::PixelAspectRatio, 0 }, - - // Video - //{ QMediaMetaData::VideoFrameRate, 0 }, - //{ QMediaMetaData::VideoBitRate, 0 }, - { QMediaMetaData::VideoCodec, GST_TAG_VIDEO_CODEC }, - - //{ QMediaMetaData::PosterUrl, 0 }, - - // Movie - //{ QMediaMetaData::ChapterNumber, 0 }, - //{ QMediaMetaData::Director, 0 }, - { QMediaMetaData::LeadPerformer, GST_TAG_PERFORMER }, - //{ QMediaMetaData::Writer, 0 }, - - // Photos - //{ QMediaMetaData::CameraManufacturer, 0 }, - //{ QMediaMetaData::CameraModel, 0 }, - //{ QMediaMetaData::Event, 0 }, - //{ QMediaMetaData::Subject, 0 } -}; + //metadataKeys->insert(QMediaMetaData::Conductor, 0); + //metadataKeys->insert(QMediaMetaData::Lyrics, 0); + //metadataKeys->insert(QMediaMetaData::Mood, 0); + metadataKeys->insert(QMediaMetaData::TrackNumber, GST_TAG_TRACK_NUMBER); + + //metadataKeys->insert(QMediaMetaData::CoverArtUrlSmall, 0); + //metadataKeys->insert(QMediaMetaData::CoverArtUrlLarge, 0); + + // Image/Video + //metadataKeys->insert(QMediaMetaData::Resolution, 0); + //metadataKeys->insert(QMediaMetaData::PixelAspectRatio, 0); + + // Video + //metadataKeys->insert(QMediaMetaData::VideoFrameRate, 0); + //metadataKeys->insert(QMediaMetaData::VideoBitRate, 0); + metadataKeys->insert(QMediaMetaData::VideoCodec, GST_TAG_VIDEO_CODEC); + + //metadataKeys->insert(QMediaMetaData::PosterUrl, 0); + + // Movie + //metadataKeys->insert(QMediaMetaData::ChapterNumber, 0); + //metadataKeys->insert(QMediaMetaData::Director, 0); + metadataKeys->insert(QMediaMetaData::LeadPerformer, GST_TAG_PERFORMER); + //metadataKeys->insert(QMediaMetaData::Writer, 0); + + // Photos + //metadataKeys->insert(QMediaMetaData::CameraManufacturer, 0); + //metadataKeys->insert(QMediaMetaData::CameraModel, 0); + //metadataKeys->insert(QMediaMetaData::Event, 0); + //metadataKeys->insert(QMediaMetaData::Subject, 0 } + } + + return metadataKeys; +} QGstreamerCaptureMetaDataControl::QGstreamerCaptureMetaDataControl(QObject *parent) :QMetaDataWriterControl(parent) @@ -128,50 +130,30 @@ QGstreamerCaptureMetaDataControl::QGstreamerCaptureMetaDataControl(QObject *pare QVariant QGstreamerCaptureMetaDataControl::metaData(const QString &key) const { - static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup); - - for (int i = 0; i < count; ++i) { - if (qt_gstreamerMetaDataKeys[i].key == key) { - const char *name = qt_gstreamerMetaDataKeys[i].token; + QGstreamerMetaDataKeyLookup::const_iterator it = qt_gstreamerMetaDataKeys()->find(key); + if (it != qt_gstreamerMetaDataKeys()->constEnd()) + return m_values.value(it.value()); - return m_values.value(QByteArray::fromRawData(name, qstrlen(name))); - } - } return QVariant(); } void QGstreamerCaptureMetaDataControl::setMetaData(const QString &key, const QVariant &value) { - static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup); - - for (int i = 0; i < count; ++i) { - if (qt_gstreamerMetaDataKeys[i].key == key) { - const char *name = qt_gstreamerMetaDataKeys[i].token; - - m_values.insert(QByteArray::fromRawData(name, qstrlen(name)), value); + QGstreamerMetaDataKeyLookup::const_iterator it = qt_gstreamerMetaDataKeys()->find(key); + if (it != qt_gstreamerMetaDataKeys()->constEnd()) { + m_values.insert(it.value(), value); - emit QMetaDataWriterControl::metaDataChanged(); - emit QMetaDataWriterControl::metaDataChanged(key, value); - emit metaDataChanged(m_values); - - return; - } + emit QMetaDataWriterControl::metaDataChanged(); + emit QMetaDataWriterControl::metaDataChanged(key, value); + emit metaDataChanged(m_values); } } QStringList QGstreamerCaptureMetaDataControl::availableMetaData() const { - static QMap<QByteArray, QString> keysMap; - if (keysMap.isEmpty()) { - const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup); - for (int i = 0; i < count; ++i) { - keysMap[QByteArray(qt_gstreamerMetaDataKeys[i].token)] = qt_gstreamerMetaDataKeys[i].key; - } - } - QStringList res; foreach (const QByteArray &key, m_values.keys()) { - QString tag = keysMap.value(key); + QString tag = qt_gstreamerMetaDataKeys()->key(key); if (!tag.isEmpty()) res.append(tag); } diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp index fa837d3f4..88faf607c 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp @@ -48,90 +48,86 @@ QT_BEGIN_NAMESPACE -struct QGstreamerMetaDataKeyLookup -{ - QString key; - const char *token; -}; +typedef QMap<QByteArray, QString> QGstreamerMetaDataKeyLookup; +Q_GLOBAL_STATIC(QGstreamerMetaDataKeyLookup, metadataKeys) -static const QGstreamerMetaDataKeyLookup qt_gstreamerMetaDataKeys[] = +static const QGstreamerMetaDataKeyLookup *qt_gstreamerMetaDataKeys() { - { QMediaMetaData::Title, GST_TAG_TITLE }, - //{ QMediaMetaData::SubTitle, 0 }, - //{ QMediaMetaData::Author, 0 }, - { QMediaMetaData::Comment, GST_TAG_COMMENT }, - { QMediaMetaData::Description, GST_TAG_DESCRIPTION }, - //{ QMediaMetaData::Category, 0 }, - { QMediaMetaData::Genre, GST_TAG_GENRE }, - { QMediaMetaData::Year, "year" }, - //{ QMediaMetaData::UserRating, 0 }, - - { QMediaMetaData::Language, GST_TAG_LANGUAGE_CODE }, - - { QMediaMetaData::Publisher, GST_TAG_ORGANIZATION }, - { QMediaMetaData::Copyright, GST_TAG_COPYRIGHT }, - //{ QMediaMetaData::ParentalRating, 0 }, - //{ QMediaMetaData::RatingOrganisation, 0 }, - - // Media - //{ QMediaMetaData::Size, 0 }, - //{ QMediaMetaData::MediaType, 0 }, - { QMediaMetaData::Duration, GST_TAG_DURATION }, - - // Audio - { QMediaMetaData::AudioBitRate, GST_TAG_BITRATE }, - { QMediaMetaData::AudioCodec, GST_TAG_AUDIO_CODEC }, - //{ QMediaMetaData::ChannelCount, 0 }, - //{ QMediaMetaData::SampleRate, 0 }, - - // Music - { QMediaMetaData::AlbumTitle, GST_TAG_ALBUM }, - { QMediaMetaData::AlbumArtist, GST_TAG_ARTIST}, - { QMediaMetaData::ContributingArtist, GST_TAG_PERFORMER }, + if (metadataKeys->isEmpty()) { + metadataKeys->insert(GST_TAG_TITLE, QMediaMetaData::Title); + //metadataKeys->insert(0, QMediaMetaData::SubTitle); + //metadataKeys->insert(0, QMediaMetaData::Author); + metadataKeys->insert(GST_TAG_COMMENT, QMediaMetaData::Comment); + metadataKeys->insert(GST_TAG_DESCRIPTION, QMediaMetaData::Description); + //metadataKeys->insert(0, QMediaMetaData::Category); + metadataKeys->insert(GST_TAG_GENRE, QMediaMetaData::Genre); + metadataKeys->insert("year", QMediaMetaData::Year); + //metadataKeys->insert(0, QMediaMetaData::UserRating); + + metadataKeys->insert(GST_TAG_LANGUAGE_CODE, QMediaMetaData::Language); + + metadataKeys->insert(GST_TAG_ORGANIZATION, QMediaMetaData::Publisher); + metadataKeys->insert(GST_TAG_COPYRIGHT, QMediaMetaData::Copyright); + //metadataKeys->insert(0, QMediaMetaData::ParentalRating); + //metadataKeys->insert(0, QMediaMetaData::RatingOrganisation); + + // Media + //metadataKeys->insert(0, QMediaMetaData::Size); + //metadataKeys->insert(0,QMediaMetaData::MediaType ); + metadataKeys->insert(GST_TAG_DURATION, QMediaMetaData::Duration); + + // Audio + metadataKeys->insert(GST_TAG_BITRATE, QMediaMetaData::AudioBitRate); + metadataKeys->insert(GST_TAG_AUDIO_CODEC, QMediaMetaData::AudioCodec); + //metadataKeys->insert(0, QMediaMetaData::ChannelCount); + //metadataKeys->insert(0, QMediaMetaData::SampleRate); + + // Music + metadataKeys->insert(GST_TAG_ALBUM, QMediaMetaData::AlbumTitle); + metadataKeys->insert(GST_TAG_ARTIST, QMediaMetaData::AlbumArtist); + metadataKeys->insert(GST_TAG_PERFORMER, QMediaMetaData::ContributingArtist); #if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19) - { QMediaMetaData::Composer, GST_TAG_COMPOSER }, + metadataKeys->insert(GST_TAG_COMPOSER, QMediaMetaData::Composer); #endif - //{ QMediaMetaData::Conductor, 0 }, - //{ QMediaMetaData::Lyrics, 0 }, - //{ QMediaMetaData::Mood, 0 }, - { QMediaMetaData::TrackNumber, GST_TAG_TRACK_NUMBER }, - - //{ QMediaMetaData::CoverArtUrlSmall, 0 }, - //{ QMediaMetaData::CoverArtUrlLarge, 0 }, - - // Image/Video - { QMediaMetaData::Resolution, "resolution" }, - { QMediaMetaData::PixelAspectRatio, "pixel-aspect-ratio" }, - - // Video - //{ QMediaMetaData::VideoFrameRate, 0 }, - //{ QMediaMetaData::VideoBitRate, 0 }, - { QMediaMetaData::VideoCodec, GST_TAG_VIDEO_CODEC }, - - //{ QMediaMetaData::PosterUrl, 0 }, - - // Movie - //{ QMediaMetaData::ChapterNumber, 0 }, - //{ QMediaMetaData::Director, 0 }, - { QMediaMetaData::LeadPerformer, GST_TAG_PERFORMER }, - //{ QMediaMetaData::Writer, 0 }, - - // Photos - //{ QMediaMetaData::CameraManufacturer, 0 }, - //{ QMediaMetaData::CameraModel, 0 }, - //{ QMediaMetaData::Event, 0 }, - //{ QMediaMetaData::Subject, 0 } -}; + //metadataKeys->insert(0, QMediaMetaData::Conductor); + //metadataKeys->insert(0, QMediaMetaData::Lyrics); + //metadataKeys->insert(0, QMediaMetaData::Mood); + metadataKeys->insert(GST_TAG_TRACK_NUMBER, QMediaMetaData::TrackNumber); + + //metadataKeys->insert(0, QMediaMetaData::CoverArtUrlSmall); + //metadataKeys->insert(0, QMediaMetaData::CoverArtUrlLarge); + + // Image/Video + metadataKeys->insert("resolution", QMediaMetaData::Resolution); + metadataKeys->insert("pixel-aspect-ratio", QMediaMetaData::PixelAspectRatio); + + // Video + //metadataKeys->insert(0, QMediaMetaData::VideoFrameRate); + //metadataKeys->insert(0, QMediaMetaData::VideoBitRate); + metadataKeys->insert(GST_TAG_VIDEO_CODEC, QMediaMetaData::VideoCodec); + + //metadataKeys->insert(0, QMediaMetaData::PosterUrl); + + // Movie + //metadataKeys->insert(0, QMediaMetaData::ChapterNumber); + //metadataKeys->insert(0, QMediaMetaData::Director); + metadataKeys->insert(GST_TAG_PERFORMER, QMediaMetaData::LeadPerformer); + //metadataKeys->insert(0, QMediaMetaData::Writer); + + // Photos + //metadataKeys->insert(0, QMediaMetaData::CameraManufacturer); + //metadataKeys->insert(0, QMediaMetaData::CameraModel); + //metadataKeys->insert(0, QMediaMetaData::Event); + //metadataKeys->insert(0, QMediaMetaData::Subject); + } + + return metadataKeys; +} QGstreamerMetaDataProvider::QGstreamerMetaDataProvider(QGstreamerPlayerSession *session, QObject *parent) :QMetaDataReaderControl(parent), m_session(session) { connect(m_session, SIGNAL(tagsChanged()), SLOT(updateTags())); - - const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup); - for (int i = 0; i < count; ++i) { - m_keysMap[QByteArray(qt_gstreamerMetaDataKeys[i].token)] = qt_gstreamerMetaDataKeys[i].key; - } } QGstreamerMetaDataProvider::~QGstreamerMetaDataProvider() @@ -167,8 +163,8 @@ void QGstreamerMetaDataProvider::updateTags() QMapIterator<QByteArray ,QVariant> 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()); + //use gstreamer native keys for elements not in our key map + QString key = qt_gstreamerMetaDataKeys()->value(i.key(), i.key()); m_tags.insert(key, i.value()); if (i.value() != oldTags.value(key)) { changed = true; diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.h b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.h index e36c127ad..7b3b266fa 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.h +++ b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.h @@ -67,7 +67,6 @@ private slots: private: QGstreamerPlayerSession *m_session; QVariantMap m_tags; - QMap<QByteArray, QString> m_keysMap; }; QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp index 27446e07d..87b71d7e2 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp @@ -1535,6 +1535,7 @@ void QGstreamerPlayerSession::playbinNotifySource(GObject *o, GParamSpec *p, gpo qDebug() << "Current source is a non-live source"; #endif + g_object_set(G_OBJECT(self->m_videoSink), "sync", !self->m_isLiveSource, NULL); gst_object_unref(source); } diff --git a/src/plugins/opensles/qopenslesaudiooutput.cpp b/src/plugins/opensles/qopenslesaudiooutput.cpp index df91e6ff1..49bea0b36 100644 --- a/src/plugins/opensles/qopenslesaudiooutput.cpp +++ b/src/plugins/opensles/qopenslesaudiooutput.cpp @@ -568,7 +568,7 @@ void QOpenSLESAudioOutput::destroyPlayer() qint64 QOpenSLESAudioOutput::writeData(const char *data, qint64 len) { - if (!len) + if (!len || !m_availableBuffers.load()) return 0; if (len > m_bufferSize) diff --git a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp index 2555b2876..abb682784 100644 --- a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp +++ b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp @@ -208,7 +208,8 @@ void MmRendererMediaPlayerControl::attach() if (m_videoWindowControl) m_videoWindowControl->attachDisplay(m_context); - m_audioId = mmr_output_attach(m_context, "audio:default", "audio"); + const QByteArray defaultAudioDevice = qgetenv("QQNX_RENDERER_DEFAULT_AUDIO_SINK"); + m_audioId = mmr_output_attach(m_context, defaultAudioDevice.isEmpty() ? "audio:default" : defaultAudioDevice.constData(), "audio"); if (m_audioId == -1) { emitMmError("mmr_output_attach() for audio failed"); return; diff --git a/src/plugins/videonode/imx6/qsgvivantevideomaterial.cpp b/src/plugins/videonode/imx6/qsgvivantevideomaterial.cpp index 44f9f4d12..0f3dd59f8 100644 --- a/src/plugins/videonode/imx6/qsgvivantevideomaterial.cpp +++ b/src/plugins/videonode/imx6/qsgvivantevideomaterial.cpp @@ -70,7 +70,7 @@ QSGVivanteVideoMaterial::QSGVivanteVideoMaterial() : QSGVivanteVideoMaterial::~QSGVivanteVideoMaterial() { - for (GLuint id : mBitsToTextureMap.values()) { + Q_FOREACH (GLuint id, mBitsToTextureMap.values()) { #ifdef QT_VIVANTE_VIDEO_DEBUG qDebug() << "delete texture: " << id; #endif @@ -154,7 +154,7 @@ GLuint QSGVivanteVideoMaterial::vivanteMapping(QVideoFrame vF) mWidth = vF.width(); mHeight = vF.height(); mFormat = vF.pixelFormat(); - for (GLuint id : mBitsToTextureMap.values()) { + Q_FOREACH (GLuint id, mBitsToTextureMap.values()) { #ifdef QT_VIVANTE_VIDEO_DEBUG qDebug() << "delete texture: " << id; #endif diff --git a/src/plugins/wmf/player/mfvideorenderercontrol.cpp b/src/plugins/wmf/player/mfvideorenderercontrol.cpp index 040682965..420473666 100644 --- a/src/plugins/wmf/player/mfvideorenderercontrol.cpp +++ b/src/plugins/wmf/player/mfvideorenderercontrol.cpp @@ -572,6 +572,18 @@ namespace QVideoSurfaceFormat format(QSize(width, height), m_pixelFormats[index]); m_surfaceFormat = format; + MFVideoArea viewport; + if (SUCCEEDED(pMediaType->GetBlob(MF_MT_GEOMETRIC_APERTURE, + reinterpret_cast<UINT8*>(&viewport), + sizeof(MFVideoArea), + NULL))) { + + m_surfaceFormat.setViewport(QRect(viewport.OffsetX.value, + viewport.OffsetY.value, + viewport.Area.cx, + viewport.Area.cy)); + } + if (FAILED(pMediaType->GetUINT32(MF_MT_DEFAULT_STRIDE, (UINT32*)&m_bytesPerLine))) { m_bytesPerLine = getBytesPerLine(format); } |