From 0a7882f6b308296ff9d44d891d3bdfed91679ce2 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Mon, 25 Mar 2013 18:11:27 +0100 Subject: [PATCH] Android: added camera support. This patch includes all camera features: viewport, settings, image capture, and video recording. It also adds support for QAudioRecorder. Change-Id: Ib962177cc8de4bac03f42a2bc0f534e03464bbfc Reviewed-by: Christian Stromme --- src/multimedia/multimedia.pro | 6 +- src/plugins/android/android.pro | 2 +- src/plugins/android/jar/jar.pri | 7 +- .../qtproject/qt5/android/multimedia/QtCamera.java | 182 ++++++ .../qt5/android/multimedia/QtMediaRecorder.java | 72 +++ .../qt5/android/multimedia/QtMultimediaUtils.java | 136 ++++ .../qt5/android/multimedia/QtSurfaceTexture.java | 18 +- .../android/multimedia/QtSurfaceTextureHolder.java | 13 + src/plugins/android/mediaplayer/mediaplayer.json | 4 - src/plugins/android/mediaplayer/mediaplayer.pro | 24 - src/plugins/android/src/android_mediaservice.json | 3 + src/plugins/android/src/common/common.pri | 10 + .../android/src/common/qandroidmultimediautils.cpp | 79 +++ .../android/src/common/qandroidmultimediautils.h | 58 ++ .../common}/qandroidvideooutput.h | 3 + .../common}/qandroidvideorendercontrol.cpp | 26 +- .../common}/qandroidvideorendercontrol.h | 2 + .../android/src/mediacapture/mediacapture.pri | 47 ++ .../qandroidaudioencodersettingscontrol.cpp | 98 +++ .../qandroidaudioencodersettingscontrol.h | 69 ++ .../qandroidaudioinputselectorcontrol.cpp | 113 ++++ .../qandroidaudioinputselectorcontrol.h | 73 +++ .../qandroidcameracapturebufferformatcontrol.cpp | 66 ++ .../qandroidcameracapturebufferformatcontrol.h | 62 ++ .../qandroidcameracapturedestinationcontrol.cpp | 71 ++ .../qandroidcameracapturedestinationcontrol.h | 67 ++ .../src/mediacapture/qandroidcameracontrol.cpp | 114 ++++ .../src/mediacapture/qandroidcameracontrol.h | 76 +++ .../mediacapture/qandroidcameraexposurecontrol.cpp | 227 +++++++ .../mediacapture/qandroidcameraexposurecontrol.h | 85 +++ .../mediacapture/qandroidcameraflashcontrol.cpp | 120 ++++ .../src/mediacapture/qandroidcameraflashcontrol.h | 73 +++ .../mediacapture/qandroidcamerafocuscontrol.cpp | 304 +++++++++ .../src/mediacapture/qandroidcamerafocuscontrol.h | 95 +++ .../qandroidcameraimagecapturecontrol.cpp | 86 +++ .../qandroidcameraimagecapturecontrol.h | 71 ++ .../qandroidcameraimageprocessingcontrol.cpp | 135 ++++ .../qandroidcameraimageprocessingcontrol.h | 73 +++ .../mediacapture/qandroidcameralockscontrol.cpp | 254 ++++++++ .../src/mediacapture/qandroidcameralockscontrol.h | 87 +++ .../src/mediacapture/qandroidcamerasession.cpp | 553 ++++++++++++++++ .../src/mediacapture/qandroidcamerasession.h | 158 +++++ .../src/mediacapture/qandroidcamerazoomcontrol.cpp | 141 ++++ .../src/mediacapture/qandroidcamerazoomcontrol.h | 80 +++ .../src/mediacapture/qandroidcaptureservice.cpp | 216 +++++++ .../src/mediacapture/qandroidcaptureservice.h | 109 ++++ .../src/mediacapture/qandroidcapturesession.cpp | 547 ++++++++++++++++ .../src/mediacapture/qandroidcapturesession.h | 184 ++++++ .../mediacapture/qandroidimageencodercontrol.cpp | 95 +++ .../src/mediacapture/qandroidimageencodercontrol.h | 72 +++ .../mediacapture/qandroidmediacontainercontrol.cpp | 86 +++ .../mediacapture/qandroidmediacontainercontrol.h | 68 ++ .../mediacapture/qandroidmediarecordercontrol.cpp | 120 ++++ .../mediacapture/qandroidmediarecordercontrol.h | 77 +++ .../mediacapture/qandroidmediastoragelocation.cpp | 130 ++++ .../mediacapture/qandroidmediastoragelocation.h | 75 +++ .../qandroidvideodeviceselectorcontrol.cpp | 150 +++++ .../qandroidvideodeviceselectorcontrol.h | 84 +++ .../qandroidvideoencodersettingscontrol.cpp | 99 +++ .../qandroidvideoencodersettingscontrol.h | 70 ++ .../android/src/mediaplayer/mediaplayer.pri | 11 + .../mediaplayer/qandroidmediaplayercontrol.cpp | 1 + .../mediaplayer/qandroidmediaplayercontrol.h | 0 .../{ => src}/mediaplayer/qandroidmediaservice.cpp | 0 .../{ => src}/mediaplayer/qandroidmediaservice.h | 0 .../mediaplayer/qandroidmetadatareadercontrol.cpp | 0 .../mediaplayer/qandroidmetadatareadercontrol.h | 0 .../qandroidmediaserviceplugin.cpp | 48 +- .../qandroidmediaserviceplugin.h | 11 +- src/plugins/android/src/src.pro | 19 + src/plugins/android/src/wrappers/jcamera.cpp | 712 +++++++++++++++++++++ src/plugins/android/src/wrappers/jcamera.h | 166 +++++ .../{ => src}/wrappers/jmediametadataretriever.cpp | 0 .../{ => src}/wrappers/jmediametadataretriever.h | 0 .../android/{ => src}/wrappers/jmediaplayer.cpp | 0 .../android/{ => src}/wrappers/jmediaplayer.h | 0 .../android/src/wrappers/jmediarecorder.cpp | 242 +++++++ src/plugins/android/src/wrappers/jmediarecorder.h | 134 ++++ .../android/src/wrappers/jmultimediautils.cpp | 95 +++ .../android/src/wrappers/jmultimediautils.h | 73 +++ .../android/{ => src}/wrappers/jsurfacetexture.cpp | 7 +- .../android/{ => src}/wrappers/jsurfacetexture.h | 2 - .../{ => src}/wrappers/jsurfacetextureholder.cpp | 0 .../{ => src}/wrappers/jsurfacetextureholder.h | 0 .../android/{ => src}/wrappers/wrappers.pri | 10 +- src/plugins/plugins.pro | 2 +- 86 files changed, 7687 insertions(+), 71 deletions(-) create mode 100644 src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtCamera.java create mode 100644 src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtMediaRecorder.java create mode 100644 src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtMultimediaUtils.java delete mode 100644 src/plugins/android/mediaplayer/mediaplayer.json delete mode 100644 src/plugins/android/mediaplayer/mediaplayer.pro create mode 100644 src/plugins/android/src/android_mediaservice.json create mode 100644 src/plugins/android/src/common/common.pri create mode 100644 src/plugins/android/src/common/qandroidmultimediautils.cpp create mode 100644 src/plugins/android/src/common/qandroidmultimediautils.h rename src/plugins/android/{mediaplayer => src/common}/qandroidvideooutput.h (97%) rename src/plugins/android/{mediaplayer => src/common}/qandroidvideorendercontrol.cpp (96%) rename src/plugins/android/{mediaplayer => src/common}/qandroidvideorendercontrol.h (97%) create mode 100644 src/plugins/android/src/mediacapture/mediacapture.pri create mode 100644 src/plugins/android/src/mediacapture/qandroidaudioencodersettingscontrol.cpp create mode 100644 src/plugins/android/src/mediacapture/qandroidaudioencodersettingscontrol.h create mode 100644 src/plugins/android/src/mediacapture/qandroidaudioinputselectorcontrol.cpp create mode 100644 src/plugins/android/src/mediacapture/qandroidaudioinputselectorcontrol.h create mode 100644 src/plugins/android/src/mediacapture/qandroidcameracapturebufferformatcontrol.cpp create mode 100644 src/plugins/android/src/mediacapture/qandroidcameracapturebufferformatcontrol.h create mode 100644 src/plugins/android/src/mediacapture/qandroidcameracapturedestinationcontrol.cpp create mode 100644 src/plugins/android/src/mediacapture/qandroidcameracapturedestinationcontrol.h create mode 100644 src/plugins/android/src/mediacapture/qandroidcameracontrol.cpp create mode 100644 src/plugins/android/src/mediacapture/qandroidcameracontrol.h create mode 100644 src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.cpp create mode 100644 src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.h create mode 100644 src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.cpp create mode 100644 src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.h create mode 100644 src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.cpp create mode 100644 src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.h create mode 100644 src/plugins/android/src/mediacapture/qandroidcameraimagecapturecontrol.cpp create mode 100644 src/plugins/android/src/mediacapture/qandroidcameraimagecapturecontrol.h create mode 100644 src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.cpp create mode 100644 src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.h create mode 100644 src/plugins/android/src/mediacapture/qandroidcameralockscontrol.cpp create mode 100644 src/plugins/android/src/mediacapture/qandroidcameralockscontrol.h create mode 100644 src/plugins/android/src/mediacapture/qandroidcamerasession.cpp create mode 100644 src/plugins/android/src/mediacapture/qandroidcamerasession.h create mode 100644 src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.cpp create mode 100644 src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.h create mode 100644 src/plugins/android/src/mediacapture/qandroidcaptureservice.cpp create mode 100644 src/plugins/android/src/mediacapture/qandroidcaptureservice.h create mode 100644 src/plugins/android/src/mediacapture/qandroidcapturesession.cpp create mode 100644 src/plugins/android/src/mediacapture/qandroidcapturesession.h create mode 100644 src/plugins/android/src/mediacapture/qandroidimageencodercontrol.cpp create mode 100644 src/plugins/android/src/mediacapture/qandroidimageencodercontrol.h create mode 100644 src/plugins/android/src/mediacapture/qandroidmediacontainercontrol.cpp create mode 100644 src/plugins/android/src/mediacapture/qandroidmediacontainercontrol.h create mode 100644 src/plugins/android/src/mediacapture/qandroidmediarecordercontrol.cpp create mode 100644 src/plugins/android/src/mediacapture/qandroidmediarecordercontrol.h create mode 100644 src/plugins/android/src/mediacapture/qandroidmediastoragelocation.cpp create mode 100644 src/plugins/android/src/mediacapture/qandroidmediastoragelocation.h create mode 100644 src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.cpp create mode 100644 src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.h create mode 100644 src/plugins/android/src/mediacapture/qandroidvideoencodersettingscontrol.cpp create mode 100644 src/plugins/android/src/mediacapture/qandroidvideoencodersettingscontrol.h create mode 100644 src/plugins/android/src/mediaplayer/mediaplayer.pri rename src/plugins/android/{ => src}/mediaplayer/qandroidmediaplayercontrol.cpp (99%) rename src/plugins/android/{ => src}/mediaplayer/qandroidmediaplayercontrol.h (100%) rename src/plugins/android/{ => src}/mediaplayer/qandroidmediaservice.cpp (100%) rename src/plugins/android/{ => src}/mediaplayer/qandroidmediaservice.h (100%) rename src/plugins/android/{ => src}/mediaplayer/qandroidmetadatareadercontrol.cpp (100%) rename src/plugins/android/{ => src}/mediaplayer/qandroidmetadatareadercontrol.h (100%) rename src/plugins/android/{mediaplayer => src}/qandroidmediaserviceplugin.cpp (66%) rename src/plugins/android/{mediaplayer => src}/qandroidmediaserviceplugin.h (89%) create mode 100644 src/plugins/android/src/src.pro create mode 100644 src/plugins/android/src/wrappers/jcamera.cpp create mode 100644 src/plugins/android/src/wrappers/jcamera.h rename src/plugins/android/{ => src}/wrappers/jmediametadataretriever.cpp (100%) rename src/plugins/android/{ => src}/wrappers/jmediametadataretriever.h (100%) rename src/plugins/android/{ => src}/wrappers/jmediaplayer.cpp (100%) rename src/plugins/android/{ => src}/wrappers/jmediaplayer.h (100%) create mode 100644 src/plugins/android/src/wrappers/jmediarecorder.cpp create mode 100644 src/plugins/android/src/wrappers/jmediarecorder.h create mode 100644 src/plugins/android/src/wrappers/jmultimediautils.cpp create mode 100644 src/plugins/android/src/wrappers/jmultimediautils.h rename src/plugins/android/{ => src}/wrappers/jsurfacetexture.cpp (94%) rename src/plugins/android/{ => src}/wrappers/jsurfacetexture.h (98%) rename src/plugins/android/{ => src}/wrappers/jsurfacetextureholder.cpp (100%) rename src/plugins/android/{ => src}/wrappers/jsurfacetextureholder.h (100%) rename src/plugins/android/{ => src}/wrappers/wrappers.pri (52%) diff --git a/src/multimedia/multimedia.pro b/src/multimedia/multimedia.pro index f1f4b38..54c6e0a 100644 --- a/src/multimedia/multimedia.pro +++ b/src/multimedia/multimedia.pro @@ -52,11 +52,11 @@ include(recording/recording.pri) include(video/video.pri) ANDROID_BUNDLED_JAR_DEPENDENCIES = \ - jar/QtMultimedia-bundled.jar + jar/QtMultimedia-bundled.jar:org.qtproject.qt5.android.multimedia.QtMultimediaUtils ANDROID_JAR_DEPENDENCIES = \ - jar/QtMultimedia.jar + jar/QtMultimedia.jar:org.qtproject.qt5.android.multimedia.QtMultimediaUtils ANDROID_LIB_DEPENDENCIES = \ - plugins/mediaservice/libandroidmediaplayer.so \ + plugins/mediaservice/libqtmedia_android.so \ lib/libQt5MultimediaQuick_p.so:Qt5Quick ANDROID_BUNDLED_FILES += \ lib/libQt5MultimediaQuick_p.so diff --git a/src/plugins/android/android.pro b/src/plugins/android/android.pro index 2cfc83f..288ae85 100644 --- a/src/plugins/android/android.pro +++ b/src/plugins/android/android.pro @@ -1,5 +1,5 @@ TEMPLATE = subdirs -SUBDIRS += mediaplayer \ +SUBDIRS += src \ jar diff --git a/src/plugins/android/jar/jar.pri b/src/plugins/android/jar/jar.pri index e6a3c63..9e23514 100644 --- a/src/plugins/android/jar/jar.pri +++ b/src/plugins/android/jar/jar.pri @@ -6,9 +6,14 @@ 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/QtSurfaceTexture.java \ - $$PWD/src/org/qtproject/qt5/android/multimedia/QtSurfaceTextureHolder.java + $$PWD/src/org/qtproject/qt5/android/multimedia/QtSurfaceTextureHolder.java \ + $$PWD/src/org/qtproject/qt5/android/multimedia/QtMultimediaUtils.java \ + $$PWD/src/org/qtproject/qt5/android/multimedia/QtMediaRecorder.java # install target.path = $$[QT_INSTALL_PREFIX]/jar INSTALLS += target + +OTHER_FILES += $$JAVASOURCES 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/QtCamera.java new file mode 100644 index 0000000..b0a4954 --- /dev/null +++ b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtCamera.java @@ -0,0 +1,182 @@ +/**************************************************************************** + ** + ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/legal + ** + ** This file is part of the QtMultimedia module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and Digia. For licensing terms and + ** conditions see http://qt.digia.com/licensing. For further information + ** use the contact form at http://qt.digia.com/contact-us. + ** + ** GNU Lesser General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU Lesser + ** General Public License version 2.1 as published by the Free Software + ** Foundation and appearing in the file LICENSE.LGPL included in the + ** packaging of this file. Please review the following information to + ** ensure the GNU Lesser General Public License version 2.1 requirements + ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Digia gives you certain additional + ** rights. These rights are described in the Digia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 3.0 as published by the Free Software + ** Foundation and appearing in the file LICENSE.GPL included in the + ** packaging of this file. Please review the following information to + ** ensure the GNU General Public License version 3.0 requirements will be + ** met: http://www.gnu.org/copyleft/gpl.html. + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +package org.qtproject.qt5.android.multimedia; + +import android.hardware.Camera; +import android.graphics.SurfaceTexture; +import android.util.Log; + +public class QtCamera implements Camera.ShutterCallback, Camera.PictureCallback, Camera.AutoFocusCallback +{ + private int m_cameraId = -1; + private Camera m_camera = null; + + private static final String TAG = "Qt Camera"; + + private QtCamera(int id, Camera cam) + { + m_cameraId = id; + m_camera = cam; + } + + public static QtCamera open(int cameraId) + { + 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_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 startPreview() + { + 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() + { + try { + m_camera.takePicture(this, null, this); + } catch(Exception e) { + Log.d(TAG, e.getMessage()); + } + } + + @Override + public void onShutter() + { + notifyPictureExposed(m_cameraId); + } + + @Override + public void onPictureTaken(byte[] data, Camera camera) + { + notifyPictureCaptured(m_cameraId, data); + } + + @Override + public void onAutoFocus(boolean success, Camera camera) + { + notifyAutoFocusComplete(m_cameraId, success); + } + + private static native void notifyAutoFocusComplete(int id, boolean success); + private static native void notifyPictureExposed(int id); + private static native void notifyPictureCaptured(int id, byte[] data); +} diff --git a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtMediaRecorder.java b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtMediaRecorder.java new file mode 100644 index 0000000..d76cd22 --- /dev/null +++ b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtMediaRecorder.java @@ -0,0 +1,72 @@ +/**************************************************************************** + ** + ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/legal + ** + ** This file is part of the QtMultimedia module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and Digia. For licensing terms and + ** conditions see http://qt.digia.com/licensing. For further information + ** use the contact form at http://qt.digia.com/contact-us. + ** + ** GNU Lesser General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU Lesser + ** General Public License version 2.1 as published by the Free Software + ** Foundation and appearing in the file LICENSE.LGPL included in the + ** packaging of this file. Please review the following information to + ** ensure the GNU Lesser General Public License version 2.1 requirements + ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Digia gives you certain additional + ** rights. These rights are described in the Digia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 3.0 as published by the Free Software + ** Foundation and appearing in the file LICENSE.GPL included in the + ** packaging of this file. Please review the following information to + ** ensure the GNU General Public License version 3.0 requirements will be + ** met: http://www.gnu.org/copyleft/gpl.html. + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +package org.qtproject.qt5.android.multimedia; + +import android.media.MediaRecorder; + +public class QtMediaRecorder extends MediaRecorder implements MediaRecorder.OnErrorListener, MediaRecorder.OnInfoListener +{ + private long m_id = -1; + + public QtMediaRecorder(long id) + { + super(); + m_id = id; + setOnErrorListener(this); + setOnInfoListener(this); + } + + @Override + public void onError(MediaRecorder mr, int what, int extra) + { + notifyError(m_id, what, extra); + } + + @Override + public void onInfo(MediaRecorder mr, int what, int extra) + { + notifyInfo(m_id, what, extra); + } + + private static native void notifyError(long id, int what, int extra); + private static native void notifyInfo(long id, int what, int extra); +} diff --git a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtMultimediaUtils.java b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtMultimediaUtils.java new file mode 100644 index 0000000..69422d0 --- /dev/null +++ b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtMultimediaUtils.java @@ -0,0 +1,136 @@ +/**************************************************************************** + ** + ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/legal + ** + ** This file is part of the QtMultimedia module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and Digia. For licensing terms and + ** conditions see http://qt.digia.com/licensing. For further information + ** use the contact form at http://qt.digia.com/contact-us. + ** + ** GNU Lesser General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU Lesser + ** General Public License version 2.1 as published by the Free Software + ** Foundation and appearing in the file LICENSE.LGPL included in the + ** packaging of this file. Please review the following information to + ** ensure the GNU Lesser General Public License version 2.1 requirements + ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Digia gives you certain additional + ** rights. These rights are described in the Digia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 3.0 as published by the Free Software + ** Foundation and appearing in the file LICENSE.GPL included in the + ** packaging of this file. Please review the following information to + ** ensure the GNU General Public License version 3.0 requirements will be + ** met: http://www.gnu.org/copyleft/gpl.html. + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +package org.qtproject.qt5.android.multimedia; + +import android.content.Context; +import android.app.Activity; +import android.view.OrientationEventListener; +import android.os.Environment; +import android.media.MediaScannerConnection; +import java.lang.String; +import java.io.File; + +public class QtMultimediaUtils +{ + static private class OrientationListener extends OrientationEventListener + { + static public int deviceOrientation = 0; + + public OrientationListener(Context context) + { + super(context); + } + + @Override + public void onOrientationChanged(int orientation) + { + if (orientation == ORIENTATION_UNKNOWN) + return; + + deviceOrientation = orientation; + } + } + + static private Activity m_activity = null; + static private OrientationListener m_orientationListener = null; + + static public void setActivity(Activity activity, Object activityDelegate) + { + m_activity = activity; + m_orientationListener = new OrientationListener(activity); + } + + public QtMultimediaUtils() + { + } + + static void enableOrientationListener(boolean enable) + { + if (enable) + m_orientationListener.enable(); + else + m_orientationListener.disable(); + } + + static int getDeviceOrientation() + { + return m_orientationListener.deviceOrientation; + } + + static String getDefaultMediaDirectory(int type) + { + String dirType = new String(); + switch (type) { + case 0: + dirType = Environment.DIRECTORY_MUSIC; + break; + case 1: + dirType = Environment.DIRECTORY_MOVIES; + break; + case 2: + dirType = Environment.DIRECTORY_DCIM; + break; + default: + break; + } + + File path = new File(""); + if (type == 3) { + // There is no API for knowing the standard location for sounds + // such as voice recording. Though, it's typically in the 'Sounds' + // directory at the root of the external storage + path = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + + File.separator + "Sounds"); + } else { + path = Environment.getExternalStoragePublicDirectory(dirType); + } + + path.mkdirs(); // make sure the directory exists + + return path.getAbsolutePath(); + } + + static void registerMediaFile(String file) + { + MediaScannerConnection.scanFile(m_activity, new String[] { file }, null, null); + } +} diff --git a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtSurfaceTexture.java b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtSurfaceTexture.java index b8837d5..7632abd 100644 --- a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtSurfaceTexture.java +++ b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtSurfaceTexture.java @@ -43,28 +43,18 @@ package org.qtproject.qt5.android.multimedia; import android.graphics.SurfaceTexture; -public class QtSurfaceTexture implements SurfaceTexture.OnFrameAvailableListener +public class QtSurfaceTexture extends SurfaceTexture implements SurfaceTexture.OnFrameAvailableListener { - public SurfaceTexture surfaceTexture; private int texID; public QtSurfaceTexture(int texName) { + super(texName); texID = texName; - surfaceTexture = new SurfaceTexture(texName); - surfaceTexture.setOnFrameAvailableListener(this); - } - - public void getTransformMatrix(float[] mtx) - { - surfaceTexture.getTransformMatrix(mtx); - } - - public void updateTexImage() - { - surfaceTexture.updateTexImage(); + setOnFrameAvailableListener(this); } + @Override public void onFrameAvailable(SurfaceTexture surfaceTexture) { notifyFrameAvailable(texID); diff --git a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtSurfaceTextureHolder.java b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtSurfaceTextureHolder.java index 15c5f23..e676559 100644 --- a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtSurfaceTextureHolder.java +++ b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtSurfaceTextureHolder.java @@ -55,59 +55,72 @@ public class QtSurfaceTextureHolder implements SurfaceHolder surfaceTexture = surface; } + @Override public void addCallback(SurfaceHolder.Callback callback) { } + @Override public Surface getSurface() { return surfaceTexture; } + @Override public Rect getSurfaceFrame() { return new Rect(); } + @Override public boolean isCreating() { return false; } + @Override public Canvas lockCanvas(Rect dirty) { return new Canvas(); } + @Override public Canvas lockCanvas() { return new Canvas(); } + @Override public void removeCallback(SurfaceHolder.Callback callback) { } + @Override public void setFixedSize(int width, int height) { } + @Override public void setFormat(int format) { } + @Override public void setKeepScreenOn(boolean screenOn) { } + @Override public void setSizeFromLayout() { } + @Override public void setType(int type) { } + @Override public void unlockCanvasAndPost(Canvas canvas) { } diff --git a/src/plugins/android/mediaplayer/mediaplayer.json b/src/plugins/android/mediaplayer/mediaplayer.json deleted file mode 100644 index f371ebf..0000000 --- a/src/plugins/android/mediaplayer/mediaplayer.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "Keys": ["androidmultimedia"], - "Services": ["org.qt-project.qt.mediaplayer"] -} diff --git a/src/plugins/android/mediaplayer/mediaplayer.pro b/src/plugins/android/mediaplayer/mediaplayer.pro deleted file mode 100644 index cabe4c6..0000000 --- a/src/plugins/android/mediaplayer/mediaplayer.pro +++ /dev/null @@ -1,24 +0,0 @@ -TARGET = androidmediaplayer -QT += multimedia-private gui-private platformsupport-private network - -PLUGIN_TYPE = mediaservice -PLUGIN_CLASS_NAME = QAndroidMediaPlayerServicePlugin -load(qt_plugin) - -HEADERS += \ - qandroidmediaplayercontrol.h \ - qandroidmediaservice.h \ - qandroidmetadatareadercontrol.h \ - qandroidmediaserviceplugin.h \ - qandroidvideorendercontrol.h \ - qandroidvideooutput.h -SOURCES += \ - qandroidmediaplayercontrol.cpp \ - qandroidmediaservice.cpp \ - qandroidmetadatareadercontrol.cpp \ - qandroidmediaserviceplugin.cpp \ - qandroidvideorendercontrol.cpp - -OTHER_FILES += mediaplayer.json - -include (../wrappers/wrappers.pri) diff --git a/src/plugins/android/src/android_mediaservice.json b/src/plugins/android/src/android_mediaservice.json new file mode 100644 index 0000000..a12be52 --- /dev/null +++ b/src/plugins/android/src/android_mediaservice.json @@ -0,0 +1,3 @@ +{ + "Keys": ["org.qt-project.qt.camera", "org.qt-project.qt.mediaplayer", "org.qt-project.qt.audiosource"] +} diff --git a/src/plugins/android/src/common/common.pri b/src/plugins/android/src/common/common.pri new file mode 100644 index 0000000..f99dad5 --- /dev/null +++ b/src/plugins/android/src/common/common.pri @@ -0,0 +1,10 @@ +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/qandroidvideooutput.h \ + $$PWD/qandroidvideorendercontrol.h \ + $$PWD/qandroidmultimediautils.h + +SOURCES += \ + $$PWD/qandroidvideorendercontrol.cpp \ + $$PWD/qandroidmultimediautils.cpp diff --git a/src/plugins/android/src/common/qandroidmultimediautils.cpp b/src/plugins/android/src/common/qandroidmultimediautils.cpp new file mode 100644 index 0000000..7ae4035 --- /dev/null +++ b/src/plugins/android/src/common/qandroidmultimediautils.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** 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 "qandroidmultimediautils.h" + +#include + +QT_BEGIN_NAMESPACE + +int qt_findClosestValue(const QList &list, int value) +{ + if (list.size() < 2) + return 0; + + int begin = 0; + int end = list.size() - 1; + int pivot = begin + (end - begin) / 2; + int v = list.at(pivot); + + while (end - begin > 1) { + if (value == v) + return pivot; + + if (value > v) + begin = pivot; + else + end = pivot; + + pivot = begin + (end - begin) / 2; + v = list.at(pivot); + } + + return value - v >= list.at(pivot + 1) - value ? pivot + 1 : pivot; +} + +bool qt_sizeLessThan(const QSize &s1, const QSize &s2) +{ + return s1.width() * s1.height() < s2.width() * s2.height(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/common/qandroidmultimediautils.h b/src/plugins/android/src/common/qandroidmultimediautils.h new file mode 100644 index 0000000..1996209 --- /dev/null +++ b/src/plugins/android/src/common/qandroidmultimediautils.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** 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 QANDROIDMULTIMEDIAUTILS_H +#define QANDROIDMULTIMEDIAUTILS_H + +#include +#include + +QT_BEGIN_NAMESPACE + +// return the index of the closest value to in +// (binary search) +int qt_findClosestValue(const QList &list, int value); + +bool qt_sizeLessThan(const QSize &s1, const QSize &s2); + +QT_END_NAMESPACE + +#endif // QANDROIDMULTIMEDIAUTILS_H diff --git a/src/plugins/android/mediaplayer/qandroidvideooutput.h b/src/plugins/android/src/common/qandroidvideooutput.h similarity index 97% rename from src/plugins/android/mediaplayer/qandroidvideooutput.h rename to src/plugins/android/src/common/qandroidvideooutput.h index d59971f..8110b67 100644 --- a/src/plugins/android/mediaplayer/qandroidvideooutput.h +++ b/src/plugins/android/src/common/qandroidvideooutput.h @@ -60,9 +60,12 @@ public: virtual bool isTextureReady() = 0; virtual void setTextureReadyCallback(TextureReadyCallback cb, void *context = 0) = 0; + virtual jobject surfaceTexture() = 0; virtual void setVideoSize(const QSize &size) = 0; virtual void stop() = 0; + + virtual QImage toImage() = 0; }; QT_END_NAMESPACE diff --git a/src/plugins/android/mediaplayer/qandroidvideorendercontrol.cpp b/src/plugins/android/src/common/qandroidvideorendercontrol.cpp similarity index 96% rename from src/plugins/android/mediaplayer/qandroidvideorendercontrol.cpp rename to src/plugins/android/src/common/qandroidvideorendercontrol.cpp index fe26b45..c5d38ae 100644 --- a/src/plugins/android/mediaplayer/qandroidvideorendercontrol.cpp +++ b/src/plugins/android/src/common/qandroidvideorendercontrol.cpp @@ -146,9 +146,7 @@ QAndroidVideoRendererControl::~QAndroidVideoRendererControl() m_glContext->makeCurrent(m_offscreenSurface); if (m_surfaceTexture) { - QJNILocalRef surfaceTex = m_surfaceTexture->surfaceTexture(); - QJNIObject obj(surfaceTex.object()); - obj.callMethod("release"); + m_surfaceTexture->callMethod("release"); delete m_surfaceTexture; m_surfaceTexture = 0; } @@ -270,11 +268,9 @@ jobject QAndroidVideoRendererControl::surfaceHolder() return 0; if (!m_surfaceHolder) { - QJNILocalRef surfaceTex = m_surfaceTexture->surfaceTexture(); - m_androidSurface = new QJNIObject("android/view/Surface", "(Landroid/graphics/SurfaceTexture;)V", - surfaceTex.object()); + m_surfaceTexture->object()); m_surfaceHolder = new JSurfaceTextureHolder(m_androidSurface->object()); } @@ -282,11 +278,21 @@ jobject QAndroidVideoRendererControl::surfaceHolder() return m_surfaceHolder->object(); } +jobject QAndroidVideoRendererControl::surfaceTexture() +{ + if (!initSurfaceTexture()) + return 0; + + return m_surfaceTexture->object(); +} + void QAndroidVideoRendererControl::setVideoSize(const QSize &size) { if (m_nativeSize == size) return; + stop(); + m_nativeSize = size; delete m_fbo; @@ -300,6 +306,14 @@ void QAndroidVideoRendererControl::stop() m_nativeSize = QSize(); } +QImage QAndroidVideoRendererControl::toImage() +{ + if (!m_fbo) + return QImage(); + + return m_fbo->toImage().mirrored(); +} + void QAndroidVideoRendererControl::onFrameAvailable() { if (m_glContext) diff --git a/src/plugins/android/mediaplayer/qandroidvideorendercontrol.h b/src/plugins/android/src/common/qandroidvideorendercontrol.h similarity index 97% rename from src/plugins/android/mediaplayer/qandroidvideorendercontrol.h rename to src/plugins/android/src/common/qandroidvideorendercontrol.h index cd93550..d8078f0 100644 --- a/src/plugins/android/mediaplayer/qandroidvideorendercontrol.h +++ b/src/plugins/android/src/common/qandroidvideorendercontrol.h @@ -67,8 +67,10 @@ public: jobject surfaceHolder() Q_DECL_OVERRIDE; bool isTextureReady() Q_DECL_OVERRIDE; void setTextureReadyCallback(TextureReadyCallback cb, void *context = 0) Q_DECL_OVERRIDE; + jobject surfaceTexture() Q_DECL_OVERRIDE; void setVideoSize(const QSize &size) Q_DECL_OVERRIDE; void stop() Q_DECL_OVERRIDE; + QImage toImage() Q_DECL_OVERRIDE; bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE; diff --git a/src/plugins/android/src/mediacapture/mediacapture.pri b/src/plugins/android/src/mediacapture/mediacapture.pri new file mode 100644 index 0000000..d994beb --- /dev/null +++ b/src/plugins/android/src/mediacapture/mediacapture.pri @@ -0,0 +1,47 @@ +INCLUDEPATH += $$PWD + +SOURCES += \ + $$PWD/qandroidcaptureservice.cpp \ + $$PWD/qandroidcameracontrol.cpp \ + $$PWD/qandroidvideodeviceselectorcontrol.cpp \ + $$PWD/qandroidcamerasession.cpp \ + $$PWD/qandroidcamerazoomcontrol.cpp \ + $$PWD/qandroidcameraexposurecontrol.cpp \ + $$PWD/qandroidcameraimageprocessingcontrol.cpp \ + $$PWD/qandroidimageencodercontrol.cpp \ + $$PWD/qandroidcameraimagecapturecontrol.cpp \ + $$PWD/qandroidcameracapturedestinationcontrol.cpp \ + $$PWD/qandroidcameracapturebufferformatcontrol.cpp \ + $$PWD/qandroidmediastoragelocation.cpp \ + $$PWD/qandroidcameraflashcontrol.cpp \ + $$PWD/qandroidcamerafocuscontrol.cpp \ + $$PWD/qandroidcameralockscontrol.cpp \ + $$PWD/qandroidcapturesession.cpp \ + $$PWD/qandroidmediarecordercontrol.cpp \ + $$PWD/qandroidaudioencodersettingscontrol.cpp \ + $$PWD/qandroidmediacontainercontrol.cpp \ + $$PWD/qandroidvideoencodersettingscontrol.cpp \ + $$PWD/qandroidaudioinputselectorcontrol.cpp + +HEADERS += \ + $$PWD/qandroidcaptureservice.h \ + $$PWD/qandroidcameracontrol.h \ + $$PWD/qandroidvideodeviceselectorcontrol.h \ + $$PWD/qandroidcamerasession.h \ + $$PWD/qandroidcamerazoomcontrol.h \ + $$PWD/qandroidcameraexposurecontrol.h \ + $$PWD/qandroidcameraimageprocessingcontrol.h \ + $$PWD/qandroidimageencodercontrol.h \ + $$PWD/qandroidcameraimagecapturecontrol.h \ + $$PWD/qandroidcameracapturedestinationcontrol.h \ + $$PWD/qandroidcameracapturebufferformatcontrol.h \ + $$PWD/qandroidmediastoragelocation.h \ + $$PWD/qandroidcameraflashcontrol.h \ + $$PWD/qandroidcamerafocuscontrol.h \ + $$PWD/qandroidcameralockscontrol.h \ + $$PWD/qandroidcapturesession.h \ + $$PWD/qandroidmediarecordercontrol.h \ + $$PWD/qandroidaudioencodersettingscontrol.h \ + $$PWD/qandroidmediacontainercontrol.h \ + $$PWD/qandroidvideoencodersettingscontrol.h \ + $$PWD/qandroidaudioinputselectorcontrol.h diff --git a/src/plugins/android/src/mediacapture/qandroidaudioencodersettingscontrol.cpp b/src/plugins/android/src/mediacapture/qandroidaudioencodersettingscontrol.cpp new file mode 100644 index 0000000..8015ec3 --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidaudioencodersettingscontrol.cpp @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** 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 "qandroidaudioencodersettingscontrol.h" + +#include "qandroidcapturesession.h" + +QT_BEGIN_NAMESPACE + +QAndroidAudioEncoderSettingsControl::QAndroidAudioEncoderSettingsControl(QAndroidCaptureSession *session) + : QAudioEncoderSettingsControl() + , m_session(session) +{ +} + +QStringList QAndroidAudioEncoderSettingsControl::supportedAudioCodecs() const +{ + return QStringList() << QLatin1String("amr-nb") << QLatin1String("amr-wb") << QLatin1String("aac"); +} + +QString QAndroidAudioEncoderSettingsControl::codecDescription(const QString &codecName) const +{ + if (codecName == QLatin1String("amr-nb")) + return tr("Adaptive Multi-Rate Narrowband (AMR-NB) audio codec"); + else if (codecName == QLatin1String("amr-wb")) + return tr("Adaptive Multi-Rate Wideband (AMR-WB) audio codec"); + else if (codecName == QLatin1String("aac")) + return tr("AAC Low Complexity (AAC-LC) audio codec"); + + return QString(); +} + +QList QAndroidAudioEncoderSettingsControl::supportedSampleRates(const QAudioEncoderSettings &settings, bool *continuous) const +{ + if (continuous) + *continuous = false; + + if (settings.isNull() || settings.codec().isNull() || settings.codec() == QLatin1String("aac")) { + return QList() << 8000 << 11025 << 12000 << 16000 << 22050 + << 24000 << 32000 << 44100 << 48000 << 96000; + } else if (settings.codec() == QLatin1String("amr-nb")) { + return QList() << 8000; + } else if (settings.codec() == QLatin1String("amr-wb")) { + return QList() << 16000; + } + + return QList(); +} + +QAudioEncoderSettings QAndroidAudioEncoderSettingsControl::audioSettings() const +{ + return m_session->audioSettings(); +} + +void QAndroidAudioEncoderSettingsControl::setAudioSettings(const QAudioEncoderSettings &settings) +{ + m_session->setAudioSettings(settings); +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidaudioencodersettingscontrol.h b/src/plugins/android/src/mediacapture/qandroidaudioencodersettingscontrol.h new file mode 100644 index 0000000..11a35fe --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidaudioencodersettingscontrol.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the 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 QANDROIDAUDIOENCODERSETTINGSCONTROL_H +#define QANDROIDAUDIOENCODERSETTINGSCONTROL_H + +#include + +QT_BEGIN_NAMESPACE + +class QAndroidCaptureSession; + +class QAndroidAudioEncoderSettingsControl : public QAudioEncoderSettingsControl +{ + Q_OBJECT +public: + explicit QAndroidAudioEncoderSettingsControl(QAndroidCaptureSession *session); + + QStringList supportedAudioCodecs() const Q_DECL_OVERRIDE; + QString codecDescription(const QString &codecName) const Q_DECL_OVERRIDE; + QList supportedSampleRates(const QAudioEncoderSettings &settings, bool *continuous = 0) const Q_DECL_OVERRIDE; + QAudioEncoderSettings audioSettings() const Q_DECL_OVERRIDE; + void setAudioSettings(const QAudioEncoderSettings &settings) Q_DECL_OVERRIDE; + +private: + QAndroidCaptureSession *m_session; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDAUDIOENCODERSETTINGSCONTROL_H diff --git a/src/plugins/android/src/mediacapture/qandroidaudioinputselectorcontrol.cpp b/src/plugins/android/src/mediacapture/qandroidaudioinputselectorcontrol.cpp new file mode 100644 index 0000000..4032b2d --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidaudioinputselectorcontrol.cpp @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** 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 "qandroidaudioinputselectorcontrol.h" + +#include "qandroidcapturesession.h" + +QT_BEGIN_NAMESPACE + +QAndroidAudioInputSelectorControl::QAndroidAudioInputSelectorControl(QAndroidCaptureSession *session) + : QAudioInputSelectorControl() + , m_session(session) +{ + connect(m_session, SIGNAL(audioInputChanged(QString)), this, SIGNAL(activeInputChanged(QString))); +} + +QList QAndroidAudioInputSelectorControl::availableInputs() const +{ + return QList() << QLatin1String("default") + << QLatin1String("mic") + << QLatin1String("voice_uplink") + << QLatin1String("voice_downlink") + << QLatin1String("voice_call") + << QLatin1String("voice_recognition"); +} + +QString QAndroidAudioInputSelectorControl::inputDescription(const QString& name) const +{ + return availableDeviceDescription(name.toLatin1()); +} + +QString QAndroidAudioInputSelectorControl::defaultInput() const +{ + return QLatin1String("default"); +} + +QString QAndroidAudioInputSelectorControl::activeInput() const +{ + return m_session->audioInput(); +} + +void QAndroidAudioInputSelectorControl::setActiveInput(const QString& name) +{ + m_session->setAudioInput(name); +} + +QList QAndroidAudioInputSelectorControl::availableDevices() +{ + return QList() << "default" + << "mic" + << "voice_uplink" + << "voice_downlink" + << "voice_call" + << "voice_recognition"; +} + +QString QAndroidAudioInputSelectorControl::availableDeviceDescription(const QByteArray &device) +{ + if (device == "default") + return QLatin1String("Default audio source"); + else if (device == "mic") + return QLatin1String("Microphone audio source"); + else if (device == "voice_uplink") + return QLatin1String("Voice call uplink (Tx) audio source"); + else if (device == "voice_downlink") + return QLatin1String("Voice call downlink (Rx) audio source"); + else if (device == "voice_call") + return QLatin1String("Voice call uplink + downlink audio source"); + else if (device == "voice_recognition") + return QLatin1String("Microphone audio source tuned for voice recognition"); + else + return QString(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidaudioinputselectorcontrol.h b/src/plugins/android/src/mediacapture/qandroidaudioinputselectorcontrol.h new file mode 100644 index 0000000..3dfa7c7 --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidaudioinputselectorcontrol.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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 QANDROIDAUDIOINPUTSELECTORCONTROL_H +#define QANDROIDAUDIOINPUTSELECTORCONTROL_H + +#include + +QT_BEGIN_NAMESPACE + +class QAndroidCaptureSession; + +class QAndroidAudioInputSelectorControl : public QAudioInputSelectorControl +{ + Q_OBJECT +public: + explicit QAndroidAudioInputSelectorControl(QAndroidCaptureSession *session); + + QList availableInputs() const; + QString inputDescription(const QString& name) const; + QString defaultInput() const; + + QString activeInput() const; + void setActiveInput(const QString& name); + + static QList availableDevices(); + static QString availableDeviceDescription(const QByteArray &device); + +private: + QAndroidCaptureSession *m_session; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDAUDIOINPUTSELECTORCONTROL_H diff --git a/src/plugins/android/src/mediacapture/qandroidcameracapturebufferformatcontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameracapturebufferformatcontrol.cpp new file mode 100644 index 0000000..dc7f20e --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcameracapturebufferformatcontrol.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** 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 "qandroidcameracapturebufferformatcontrol.h" + +QT_BEGIN_NAMESPACE + +QAndroidCameraCaptureBufferFormatControl::QAndroidCameraCaptureBufferFormatControl() + : QCameraCaptureBufferFormatControl() +{ +} + +QList QAndroidCameraCaptureBufferFormatControl::supportedBufferFormats() const +{ + return (QList() << QVideoFrame::Format_Jpeg); +} + +QVideoFrame::PixelFormat QAndroidCameraCaptureBufferFormatControl::bufferFormat() const +{ + return QVideoFrame::Format_Jpeg; +} + +void QAndroidCameraCaptureBufferFormatControl::setBufferFormat(QVideoFrame::PixelFormat format) +{ + Q_UNUSED(format) +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcameracapturebufferformatcontrol.h b/src/plugins/android/src/mediacapture/qandroidcameracapturebufferformatcontrol.h new file mode 100644 index 0000000..cf8bd49 --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcameracapturebufferformatcontrol.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** 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 QANDROIDCAMERACAPTUREBUFFERFORMATCONTROL_H +#define QANDROIDCAMERACAPTUREBUFFERFORMATCONTROL_H + +#include + +QT_BEGIN_NAMESPACE + +class QAndroidCameraCaptureBufferFormatControl : public QCameraCaptureBufferFormatControl +{ + Q_OBJECT +public: + QAndroidCameraCaptureBufferFormatControl(); + + QList supportedBufferFormats() const Q_DECL_OVERRIDE; + QVideoFrame::PixelFormat bufferFormat() const Q_DECL_OVERRIDE; + void setBufferFormat(QVideoFrame::PixelFormat format) Q_DECL_OVERRIDE; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDCAMERACAPTUREBUFFERFORMATCONTROL_H diff --git a/src/plugins/android/src/mediacapture/qandroidcameracapturedestinationcontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameracapturedestinationcontrol.cpp new file mode 100644 index 0000000..870a424 --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcameracapturedestinationcontrol.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** 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 "qandroidcameracapturedestinationcontrol.h" + +#include "qandroidcamerasession.h" + +QT_BEGIN_NAMESPACE + +QAndroidCameraCaptureDestinationControl::QAndroidCameraCaptureDestinationControl(QAndroidCameraSession *session) + : QCameraCaptureDestinationControl() + , m_session(session) +{ + connect(m_session, SIGNAL(captureDestinationChanged(QCameraImageCapture::CaptureDestinations)), + this, SIGNAL(captureDestinationChanged(QCameraImageCapture::CaptureDestinations))); +} + +bool QAndroidCameraCaptureDestinationControl::isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const +{ + return m_session->isCaptureDestinationSupported(destination); +} + +QCameraImageCapture::CaptureDestinations QAndroidCameraCaptureDestinationControl::captureDestination() const +{ + return m_session->captureDestination();; +} + +void QAndroidCameraCaptureDestinationControl::setCaptureDestination(QCameraImageCapture::CaptureDestinations destination) +{ + m_session->setCaptureDestination(destination); +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcameracapturedestinationcontrol.h b/src/plugins/android/src/mediacapture/qandroidcameracapturedestinationcontrol.h new file mode 100644 index 0000000..46ff96b --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcameracapturedestinationcontrol.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** 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 QANDROIDCAMERACAPTUREDESTINATIONCONTROL_H +#define QANDROIDCAMERACAPTUREDESTINATIONCONTROL_H + +#include + +QT_BEGIN_NAMESPACE + +class QAndroidCameraSession; + +class QAndroidCameraCaptureDestinationControl : public QCameraCaptureDestinationControl +{ + Q_OBJECT +public: + explicit QAndroidCameraCaptureDestinationControl(QAndroidCameraSession *session); + + bool isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const Q_DECL_OVERRIDE; + QCameraImageCapture::CaptureDestinations captureDestination() const Q_DECL_OVERRIDE; + void setCaptureDestination(QCameraImageCapture::CaptureDestinations destination) Q_DECL_OVERRIDE; + +private: + QAndroidCameraSession *m_session; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDCAMERACAPTUREDESTINATIONCONTROL_H diff --git a/src/plugins/android/src/mediacapture/qandroidcameracontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameracontrol.cpp new file mode 100644 index 0000000..f91ae1e --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcameracontrol.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** 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 "qandroidcameracontrol.h" + +#include "qandroidcamerasession.h" + +QT_BEGIN_NAMESPACE + +QAndroidCameraControl::QAndroidCameraControl(QAndroidCameraSession *session) + : QCameraControl(0) + , m_cameraSession(session) + +{ + connect(m_cameraSession, SIGNAL(statusChanged(QCamera::Status)), + this, SIGNAL(statusChanged(QCamera::Status))); + + connect(m_cameraSession, SIGNAL(stateChanged(QCamera::State)), + this, SIGNAL(stateChanged(QCamera::State))); + + connect(m_cameraSession, SIGNAL(error(int,QString)), this, SIGNAL(error(int,QString))); + + connect(m_cameraSession, SIGNAL(captureModeChanged(QCamera::CaptureModes)), + this, SIGNAL(captureModeChanged(QCamera::CaptureModes))); +} + +QAndroidCameraControl::~QAndroidCameraControl() +{ +} + +QCamera::CaptureModes QAndroidCameraControl::captureMode() const +{ + return m_cameraSession->captureMode(); +} + +void QAndroidCameraControl::setCaptureMode(QCamera::CaptureModes mode) +{ + m_cameraSession->setCaptureMode(mode); +} + +bool QAndroidCameraControl::isCaptureModeSupported(QCamera::CaptureModes mode) const +{ + return m_cameraSession->isCaptureModeSupported(mode); +} + +void QAndroidCameraControl::setState(QCamera::State state) +{ + m_cameraSession->setState(state); +} + +QCamera::State QAndroidCameraControl::state() const +{ + return m_cameraSession->state(); +} + +QCamera::Status QAndroidCameraControl::status() const +{ + return m_cameraSession->status(); +} + +bool QAndroidCameraControl::canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const +{ + Q_UNUSED(status); + + switch (changeType) { + case QCameraControl::CaptureMode: + case QCameraControl::ImageEncodingSettings: + case QCameraControl::VideoEncodingSettings: + case QCameraControl::Viewfinder: + return true; + default: + return false; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcameracontrol.h b/src/plugins/android/src/mediacapture/qandroidcameracontrol.h new file mode 100644 index 0000000..f5070c1 --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcameracontrol.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** 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 QANDROIDCAMERACONTROL_H +#define QANDROIDCAMERACONTROL_H + +#include + +QT_BEGIN_NAMESPACE + +class QAndroidCameraSession; + +class QAndroidCameraControl : public QCameraControl +{ + Q_OBJECT +public: + explicit QAndroidCameraControl(QAndroidCameraSession *session); + virtual ~QAndroidCameraControl(); + + QCamera::State state() const; + void setState(QCamera::State state); + + QCamera::Status status() const; + + QCamera::CaptureModes captureMode() const; + void setCaptureMode(QCamera::CaptureModes mode); + bool isCaptureModeSupported(QCamera::CaptureModes mode) const; + + bool canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const; + +private: + QAndroidCameraSession *m_cameraSession; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDCAMERACONTROL_H diff --git a/src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.cpp new file mode 100644 index 0000000..03bbadb --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.cpp @@ -0,0 +1,227 @@ +/**************************************************************************** +** +** 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 "qandroidcameraexposurecontrol.h" + +#include "qandroidcamerasession.h" +#include "jcamera.h" + +QT_BEGIN_NAMESPACE + +QAndroidCameraExposureControl::QAndroidCameraExposureControl(QAndroidCameraSession *session) + : QCameraExposureControl() + , m_session(session) + , m_minExposureCompensationIndex(0) + , m_maxExposureCompensationIndex(0) + , m_exposureCompensationStep(0.0) + , m_requestedExposureCompensation(0.0) + , m_actualExposureCompensation(0.0) + , m_requestedExposureMode(QCameraExposure::ExposureAuto) + , m_actualExposureMode(QCameraExposure::ExposureAuto) +{ + connect(m_session, SIGNAL(opened()), + this, SLOT(onCameraOpened())); +} + +bool QAndroidCameraExposureControl::isParameterSupported(ExposureParameter parameter) const +{ + switch (parameter) { + case QCameraExposureControl::ISO: + return false; + case QCameraExposureControl::Aperture: + return false; + case QCameraExposureControl::ShutterSpeed: + return false; + case QCameraExposureControl::ExposureCompensation: + return true; + case QCameraExposureControl::FlashPower: + return false; + case QCameraExposureControl::FlashCompensation: + return false; + case QCameraExposureControl::TorchPower: + return false; + case QCameraExposureControl::SpotMeteringPoint: + return false; + case QCameraExposureControl::ExposureMode: + return true; + case QCameraExposureControl::MeteringMode: + return false; + default: + return false; + } +} + +QVariantList QAndroidCameraExposureControl::supportedParameterRange(ExposureParameter parameter, bool *continuous) const +{ + if (!m_session->camera()) + return QVariantList(); + + if (continuous) + *continuous = false; + + if (parameter == QCameraExposureControl::ExposureCompensation) + return m_supportedExposureCompensations; + else if (parameter == QCameraExposureControl::ExposureMode) + return m_supportedExposureModes; + + return QVariantList(); +} + +QVariant QAndroidCameraExposureControl::requestedValue(ExposureParameter parameter) const +{ + if (parameter == QCameraExposureControl::ExposureCompensation) + return QVariant::fromValue(m_requestedExposureCompensation); + else if (parameter == QCameraExposureControl::ExposureMode) + return QVariant::fromValue(m_requestedExposureMode); + + return QVariant(); +} + +QVariant QAndroidCameraExposureControl::actualValue(ExposureParameter parameter) const +{ + if (parameter == QCameraExposureControl::ExposureCompensation) + return QVariant::fromValue(m_actualExposureCompensation); + else if (parameter == QCameraExposureControl::ExposureMode) + return QVariant::fromValue(m_actualExposureMode); + + return QVariant(); +} + +bool QAndroidCameraExposureControl::setValue(ExposureParameter parameter, const QVariant& value) +{ + if (!m_session->camera() || !value.isValid()) + return false; + + if (parameter == QCameraExposureControl::ExposureCompensation) { + m_requestedExposureCompensation = value.toReal(); + emit requestedValueChanged(QCameraExposureControl::ExposureCompensation); + + int expCompIndex = qRound(m_requestedExposureCompensation / m_exposureCompensationStep); + if (expCompIndex >= m_minExposureCompensationIndex + && expCompIndex <= m_maxExposureCompensationIndex) { + m_session->camera()->setExposureCompensation(expCompIndex); + + m_actualExposureCompensation = expCompIndex * m_exposureCompensationStep; + emit actualValueChanged(QCameraExposureControl::ExposureCompensation); + + return true; + } + + } else if (parameter == QCameraExposureControl::ExposureMode) { + m_requestedExposureMode = value.value(); + emit requestedValueChanged(QCameraExposureControl::ExposureMode); + + if (!m_supportedExposureModes.isEmpty()) { + m_actualExposureMode = m_requestedExposureMode; + + QString sceneMode; + switch (m_requestedExposureMode) { + case QCameraExposure::ExposureAuto: + sceneMode = QLatin1String("auto"); + break; + case QCameraExposure::ExposureSports: + sceneMode = QLatin1String("sports"); + break; + case QCameraExposure::ExposurePortrait: + sceneMode = QLatin1String("portrait"); + break; + case QCameraExposure::ExposureBeach: + sceneMode = QLatin1String("beach"); + break; + case QCameraExposure::ExposureSnow: + sceneMode = QLatin1String("snow"); + break; + case QCameraExposure::ExposureNight: + sceneMode = QLatin1String("night"); + break; + default: + sceneMode = QLatin1String("auto"); + m_actualExposureMode = QCameraExposure::ExposureAuto; + break; + } + + m_session->camera()->setSceneMode(sceneMode); + emit actualValueChanged(QCameraExposureControl::ExposureMode); + + return true; + } + } + + return false; +} + +void QAndroidCameraExposureControl::onCameraOpened() +{ + m_requestedExposureCompensation = m_actualExposureCompensation = 0.0; + m_requestedExposureMode = m_actualExposureMode = QCameraExposure::ExposureAuto; + emit requestedValueChanged(QCameraExposureControl::ExposureCompensation); + emit actualValueChanged(QCameraExposureControl::ExposureCompensation); + emit requestedValueChanged(QCameraExposureControl::ExposureMode); + emit actualValueChanged(QCameraExposureControl::ExposureMode); + + m_minExposureCompensationIndex = m_session->camera()->getMinExposureCompensation(); + m_maxExposureCompensationIndex = m_session->camera()->getMaxExposureCompensation(); + m_exposureCompensationStep = m_session->camera()->getExposureCompensationStep(); + for (int i = m_minExposureCompensationIndex; i <= m_maxExposureCompensationIndex; ++i) + m_supportedExposureCompensations.append(i * m_exposureCompensationStep); + emit parameterRangeChanged(QCameraExposureControl::ExposureCompensation); + + m_supportedExposureModes.clear(); + QStringList sceneModes = m_session->camera()->getSupportedSceneModes(); + for (int i = 0; i < sceneModes.size(); ++i) { + const QString &sceneMode = sceneModes.at(i); + if (sceneMode == QLatin1String("auto")) + m_supportedExposureModes << QVariant::fromValue(QCameraExposure::ExposureAuto); + else if (sceneMode == QLatin1String("beach")) + m_supportedExposureModes << QVariant::fromValue(QCameraExposure::ExposureBeach); + else if (sceneMode == QLatin1String("night")) + m_supportedExposureModes << QVariant::fromValue(QCameraExposure::ExposureNight); + else if (sceneMode == QLatin1String("portrait")) + m_supportedExposureModes << QVariant::fromValue(QCameraExposure::ExposurePortrait); + else if (sceneMode == QLatin1String("snow")) + m_supportedExposureModes << QVariant::fromValue(QCameraExposure::ExposureSnow); + else if (sceneMode == QLatin1String("sports")) + m_supportedExposureModes << QVariant::fromValue(QCameraExposure::ExposureSports); + } + emit parameterRangeChanged(QCameraExposureControl::ExposureMode); +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.h b/src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.h new file mode 100644 index 0000000..d07fea5 --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** 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 QANDROIDCAMERAEXPOSURECONTROL_H +#define QANDROIDCAMERAEXPOSURECONTROL_H + +#include + +QT_BEGIN_NAMESPACE + +class QAndroidCameraSession; + +class QAndroidCameraExposureControl : public QCameraExposureControl +{ + Q_OBJECT +public: + explicit QAndroidCameraExposureControl(QAndroidCameraSession *session); + + bool isParameterSupported(ExposureParameter parameter) const Q_DECL_OVERRIDE; + QVariantList supportedParameterRange(ExposureParameter parameter, bool *continuous) const Q_DECL_OVERRIDE; + + QVariant requestedValue(ExposureParameter parameter) const Q_DECL_OVERRIDE; + QVariant actualValue(ExposureParameter parameter) const Q_DECL_OVERRIDE; + bool setValue(ExposureParameter parameter, const QVariant& value) Q_DECL_OVERRIDE; + +private Q_SLOTS: + void onCameraOpened(); + +private: + QAndroidCameraSession *m_session; + + QVariantList m_supportedExposureCompensations; + QVariantList m_supportedExposureModes; + + int m_minExposureCompensationIndex; + int m_maxExposureCompensationIndex; + qreal m_exposureCompensationStep; + + qreal m_requestedExposureCompensation; + qreal m_actualExposureCompensation; + QCameraExposure::ExposureMode m_requestedExposureMode; + QCameraExposure::ExposureMode m_actualExposureMode; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDCAMERAEXPOSURECONTROL_H diff --git a/src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.cpp new file mode 100644 index 0000000..253b1ba --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.cpp @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** 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 "qandroidcameraflashcontrol.h" + +#include "qandroidcamerasession.h" +#include "jcamera.h" + +QT_BEGIN_NAMESPACE + +QAndroidCameraFlashControl::QAndroidCameraFlashControl(QAndroidCameraSession *session) + : QCameraFlashControl() + , m_session(session) + , m_flashMode(QCameraExposure::FlashOff) +{ + connect(m_session, SIGNAL(opened()), + this, SLOT(onCameraOpened())); +} + +QCameraExposure::FlashModes QAndroidCameraFlashControl::flashMode() const +{ + return m_flashMode; +} + +void QAndroidCameraFlashControl::setFlashMode(QCameraExposure::FlashModes mode) +{ + if (m_flashMode == mode || !m_session->camera() || !isFlashModeSupported(mode)) + return; + + // if torch was enabled, it first needs to be turned off before setting another mode + if (m_flashMode == QCameraExposure::FlashVideoLight) + m_session->camera()->setFlashMode(QLatin1String("off")); + + m_flashMode = mode; + + QString flashMode; + if (mode.testFlag(QCameraExposure::FlashAuto)) + flashMode = QLatin1String("auto"); + else if (mode.testFlag(QCameraExposure::FlashOn)) + flashMode = QLatin1String("on"); + else if (mode.testFlag(QCameraExposure::FlashRedEyeReduction)) + flashMode = QLatin1String("red-eye"); + else if (mode.testFlag(QCameraExposure::FlashVideoLight)) + flashMode = QLatin1String("torch"); + else // FlashOff + flashMode = QLatin1String("off"); + + m_session->camera()->setFlashMode(flashMode); +} + +bool QAndroidCameraFlashControl::isFlashModeSupported(QCameraExposure::FlashModes mode) const +{ + return m_supportedFlashModes.contains(mode); +} + +bool QAndroidCameraFlashControl::isFlashReady() const +{ + // Android doesn't have an API for that + return true; +} + +void QAndroidCameraFlashControl::onCameraOpened() +{ + m_supportedFlashModes.clear(); + + QStringList flashModes = m_session->camera()->getSupportedFlashModes(); + for (int i = 0; i < flashModes.size(); ++i) { + const QString &flashMode = flashModes.at(i); + if (flashMode == QLatin1String("off")) + m_supportedFlashModes << QCameraExposure::FlashOff; + else if (flashMode == QLatin1String("auto")) + m_supportedFlashModes << QCameraExposure::FlashAuto; + else if (flashMode == QLatin1String("on")) + m_supportedFlashModes << QCameraExposure::FlashOn; + else if (flashMode == QLatin1String("red-eye")) + m_supportedFlashModes << QCameraExposure::FlashRedEyeReduction; + else if (flashMode == QLatin1String("torch")) + m_supportedFlashModes << QCameraExposure::FlashVideoLight; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.h b/src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.h new file mode 100644 index 0000000..35ed718 --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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 QANDROIDCAMERAFLASHCONTROL_H +#define QANDROIDCAMERAFLASHCONTROL_H + +#include + +QT_BEGIN_NAMESPACE + +class QAndroidCameraSession; + +class QAndroidCameraFlashControl : public QCameraFlashControl +{ + Q_OBJECT +public: + explicit QAndroidCameraFlashControl(QAndroidCameraSession *session); + + QCameraExposure::FlashModes flashMode() const Q_DECL_OVERRIDE; + void setFlashMode(QCameraExposure::FlashModes mode) Q_DECL_OVERRIDE; + bool isFlashModeSupported(QCameraExposure::FlashModes mode) const Q_DECL_OVERRIDE; + bool isFlashReady() const Q_DECL_OVERRIDE; + +private Q_SLOTS: + void onCameraOpened(); + +private: + QAndroidCameraSession *m_session; + QList m_supportedFlashModes; + QCameraExposure::FlashModes m_flashMode; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDCAMERAFLASHCONTROL_H diff --git a/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.cpp new file mode 100644 index 0000000..cb785fe --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.cpp @@ -0,0 +1,304 @@ +/**************************************************************************** +** +** 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 "qandroidcamerafocuscontrol.h" + +#include "qandroidcamerasession.h" +#include "jcamera.h" + +QT_BEGIN_NAMESPACE + +static QRect adjustedArea(const QRectF &area) +{ + // Qt maps focus points in the range (0.0, 0.0) -> (1.0, 1.0) + // Android maps focus points in the range (-1000, -1000) -> (1000, 1000) + // Converts an area in Qt coordinates to Android coordinates + return QRect(-1000 + qRound(area.x() * 2000), + -1000 + qRound(area.y() * 2000), + qRound(area.width() * 2000), + qRound(area.height() * 2000)) + .intersected(QRect(-1000, -1000, 2000, 2000)); +} + +QAndroidCameraFocusControl::QAndroidCameraFocusControl(QAndroidCameraSession *session) + : QCameraFocusControl() + , m_session(session) + , m_focusMode(QCameraFocus::AutoFocus) + , m_focusPointMode(QCameraFocus::FocusPointAuto) + , m_actualFocusPoint(0.5, 0.5) + , m_continuousPictureFocusSupported(false) + , m_continuousVideoFocusSupported(false) +{ + connect(m_session, SIGNAL(opened()), + this, SLOT(onCameraOpened())); + connect(m_session, SIGNAL(captureModeChanged(QCamera::CaptureModes)), + this, SLOT(onCameraCaptureModeChanged())); +} + +QCameraFocus::FocusModes QAndroidCameraFocusControl::focusMode() const +{ + return m_focusMode; +} + +void QAndroidCameraFocusControl::setFocusMode(QCameraFocus::FocusModes mode) +{ + if (m_focusMode == mode || !m_session->camera() || !isFocusModeSupported(mode)) + return; + + QString focusMode = QLatin1String("fixed"); + + if (mode.testFlag(QCameraFocus::HyperfocalFocus)) { + focusMode = QLatin1String("edof"); + } else if (mode.testFlag(QCameraFocus::ManualFocus)) { + focusMode = QLatin1String("fixed"); + } else if (mode.testFlag(QCameraFocus::AutoFocus)) { + focusMode = QLatin1String("auto"); + } else if (mode.testFlag(QCameraFocus::MacroFocus)) { + focusMode = QLatin1String("macro"); + } else if (mode.testFlag(QCameraFocus::ContinuousFocus)) { + if ((m_session->captureMode().testFlag(QCamera::CaptureVideo) && m_continuousVideoFocusSupported) + || !m_continuousPictureFocusSupported) { + focusMode = QLatin1String("continuous-video"); + } else { + focusMode = QLatin1String("continuous-picture"); + } + } else if (mode.testFlag(QCameraFocus::InfinityFocus)) { + focusMode = QLatin1String("infinity"); + } + + m_session->camera()->setFocusMode(focusMode); + + // reset focus position + m_session->camera()->cancelAutoFocus(); + + m_focusMode = mode; + emit focusModeChanged(m_focusMode); +} + +bool QAndroidCameraFocusControl::isFocusModeSupported(QCameraFocus::FocusModes mode) const +{ + return m_supportedFocusModes.contains(mode); +} + +QCameraFocus::FocusPointMode QAndroidCameraFocusControl::focusPointMode() const +{ + return m_focusPointMode; +} + +void QAndroidCameraFocusControl::setFocusPointMode(QCameraFocus::FocusPointMode mode) +{ + if (!m_session->camera() || m_focusPointMode == mode || !isFocusPointModeSupported(mode)) + return; + + m_focusPointMode = mode; + + if (mode == QCameraFocus::FocusPointCustom) { + m_actualFocusPoint = m_customFocusPoint; + } else { + // FocusPointAuto | FocusPointCenter + // note: there is no way to know the actual focus point in FocusPointAuto mode, + // so just report the focus point to be at the center of the frame + m_actualFocusPoint = QPointF(0.5, 0.5); + } + + updateFocusZones(); + setCameraFocusArea(); + + emit focusPointModeChanged(mode); +} + +bool QAndroidCameraFocusControl::isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const +{ + return m_supportedFocusPointModes.contains(mode); +} + +QPointF QAndroidCameraFocusControl::customFocusPoint() const +{ + return m_customFocusPoint; +} + +void QAndroidCameraFocusControl::setCustomFocusPoint(const QPointF &point) +{ + if (m_customFocusPoint == point) + return; + + m_customFocusPoint = point; + emit customFocusPointChanged(m_customFocusPoint); + + if (m_focusPointMode == QCameraFocus::FocusPointCustom) { + m_actualFocusPoint = m_customFocusPoint; + updateFocusZones(); + setCameraFocusArea(); + } +} + +QCameraFocusZoneList QAndroidCameraFocusControl::focusZones() const +{ + return m_focusZones; +} + +void QAndroidCameraFocusControl::onCameraOpened() +{ + connect(m_session->camera(), SIGNAL(previewSizeChanged()), + this, SLOT(onViewportSizeChanged())); + connect(m_session->camera(), SIGNAL(autoFocusStarted()), + this, SLOT(onAutoFocusStarted())); + connect(m_session->camera(), SIGNAL(autoFocusComplete(bool)), + this, SLOT(onAutoFocusComplete(bool))); + + m_supportedFocusModes.clear(); + m_continuousPictureFocusSupported = false; + m_continuousVideoFocusSupported = false; + + m_focusPointMode = QCameraFocus::FocusPointAuto; + m_actualFocusPoint = QPointF(0.5, 0.5); + m_customFocusPoint = QPointF(); + m_supportedFocusPointModes.clear(); + m_focusZones.clear(); + + QStringList focusModes = m_session->camera()->getSupportedFocusModes(); + for (int i = 0; i < focusModes.size(); ++i) { + const QString &focusMode = focusModes.at(i); + if (focusMode == QLatin1String("auto")) { + m_supportedFocusModes << QCameraFocus::AutoFocus; + } else if (focusMode == QLatin1String("continuous-picture")) { + m_supportedFocusModes << QCameraFocus::ContinuousFocus; + m_continuousPictureFocusSupported = true; + } else if (focusMode == QLatin1String("continuous-video")) { + m_supportedFocusModes << QCameraFocus::ContinuousFocus; + m_continuousVideoFocusSupported = true; + } else if (focusMode == QLatin1String("edof")) { + m_supportedFocusModes << QCameraFocus::HyperfocalFocus; + } else if (focusMode == QLatin1String("fixed")) { + m_supportedFocusModes << QCameraFocus::ManualFocus; + } else if (focusMode == QLatin1String("infinity")) { + m_supportedFocusModes << QCameraFocus::InfinityFocus; + } else if (focusMode == QLatin1String("macro")) { + m_supportedFocusModes << QCameraFocus::MacroFocus; + } + } + + m_supportedFocusPointModes << QCameraFocus::FocusPointAuto; + if (m_session->camera()->getMaxNumFocusAreas() > 0) + m_supportedFocusPointModes << QCameraFocus::FocusPointCenter << QCameraFocus::FocusPointCustom; + + emit focusModeChanged(focusMode()); + emit focusPointModeChanged(m_focusPointMode); + emit customFocusPointChanged(m_customFocusPoint); + emit focusZonesChanged(); +} + +void QAndroidCameraFocusControl::updateFocusZones(QCameraFocusZone::FocusZoneStatus status) +{ + if (!m_session->camera()) + return; + + // create a focus zone (50x50 pixel) around the focus point + m_focusZones.clear(); + + if (m_actualFocusPoint.isNull()) + return; + + QSize viewportSize = m_session->camera()->previewSize(); + QSizeF focusSize(50.f / viewportSize.width(), 50.f / viewportSize.height()); + float x = qBound(0.f, + m_actualFocusPoint.x() - (focusSize.width() / 2), + 1.f - focusSize.width()); + float y = qBound(0.f, + m_actualFocusPoint.y() - (focusSize.height() / 2), + 1.f - focusSize.height()); + + QRectF area(QPointF(x, y), focusSize); + + m_focusZones.append(QCameraFocusZone(area, status)); + + emit focusZonesChanged(); +} + +void QAndroidCameraFocusControl::setCameraFocusArea() +{ + QList areas; + if (m_focusPointMode != QCameraFocus::FocusPointAuto) { + // in FocusPointAuto mode, leave the area list empty + // to let the driver choose the focus point. + + for (int i = 0; i < m_focusZones.size(); ++i) + areas.append(adjustedArea(m_focusZones.at(i).area())); + + } + m_session->camera()->setFocusAreas(areas); +} + +void QAndroidCameraFocusControl::onViewportSizeChanged() +{ + QCameraFocusZone::FocusZoneStatus status = QCameraFocusZone::Selected; + if (!m_focusZones.isEmpty()) + status = m_focusZones.at(0).status(); + updateFocusZones(status); +} + +void QAndroidCameraFocusControl::onCameraCaptureModeChanged() +{ + if (m_focusMode == QCameraFocus::ContinuousFocus) { + QString focusMode; + if ((m_session->captureMode().testFlag(QCamera::CaptureVideo) && m_continuousVideoFocusSupported) + || !m_continuousPictureFocusSupported) { + focusMode = QLatin1String("continuous-video"); + } else { + focusMode = QLatin1String("continuous-picture"); + } + m_session->camera()->setFocusMode(focusMode); + m_session->camera()->cancelAutoFocus(); + } +} + +void QAndroidCameraFocusControl::onAutoFocusStarted() +{ + updateFocusZones(QCameraFocusZone::Selected); +} + +void QAndroidCameraFocusControl::onAutoFocusComplete(bool success) +{ + if (success) + updateFocusZones(QCameraFocusZone::Focused); +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.h b/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.h new file mode 100644 index 0000000..4311e78 --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** 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 QANDROIDCAMERAFOCUSCONTROL_H +#define QANDROIDCAMERAFOCUSCONTROL_H + +#include + +QT_BEGIN_NAMESPACE + +class QAndroidCameraSession; + +class QAndroidCameraFocusControl : public QCameraFocusControl +{ + Q_OBJECT +public: + explicit QAndroidCameraFocusControl(QAndroidCameraSession *session); + + QCameraFocus::FocusModes focusMode() const Q_DECL_OVERRIDE; + void setFocusMode(QCameraFocus::FocusModes mode) Q_DECL_OVERRIDE; + bool isFocusModeSupported(QCameraFocus::FocusModes mode) const Q_DECL_OVERRIDE; + QCameraFocus::FocusPointMode focusPointMode() const Q_DECL_OVERRIDE; + void setFocusPointMode(QCameraFocus::FocusPointMode mode) Q_DECL_OVERRIDE; + bool isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const Q_DECL_OVERRIDE; + QPointF customFocusPoint() const Q_DECL_OVERRIDE; + void setCustomFocusPoint(const QPointF &point) Q_DECL_OVERRIDE; + QCameraFocusZoneList focusZones() const Q_DECL_OVERRIDE; + +private Q_SLOTS: + void onCameraOpened(); + void onViewportSizeChanged(); + void onCameraCaptureModeChanged(); + void onAutoFocusStarted(); + void onAutoFocusComplete(bool success); + +private: + void updateFocusZones(QCameraFocusZone::FocusZoneStatus status = QCameraFocusZone::Selected); + void setCameraFocusArea(); + + QAndroidCameraSession *m_session; + + QCameraFocus::FocusModes m_focusMode; + QCameraFocus::FocusPointMode m_focusPointMode; + QPointF m_actualFocusPoint; + QPointF m_customFocusPoint; + QCameraFocusZoneList m_focusZones; + + QList m_supportedFocusModes; + bool m_continuousPictureFocusSupported; + bool m_continuousVideoFocusSupported; + + QList m_supportedFocusPointModes; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDCAMERAFOCUSCONTROL_H diff --git a/src/plugins/android/src/mediacapture/qandroidcameraimagecapturecontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameraimagecapturecontrol.cpp new file mode 100644 index 0000000..3c04d29 --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcameraimagecapturecontrol.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** 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 "qandroidcameraimagecapturecontrol.h" + +#include "qandroidcamerasession.h" + +QT_BEGIN_NAMESPACE + +QAndroidCameraImageCaptureControl::QAndroidCameraImageCaptureControl(QAndroidCameraSession *session) + : QCameraImageCaptureControl() + , m_session(session) +{ + connect(m_session, SIGNAL(readyForCaptureChanged(bool)), this, SIGNAL(readyForCaptureChanged(bool))); + connect(m_session, SIGNAL(imageExposed(int)), this, SIGNAL(imageExposed(int))); + connect(m_session, SIGNAL(imageCaptured(int,QImage)), this, SIGNAL(imageCaptured(int,QImage))); + connect(m_session, SIGNAL(imageMetadataAvailable(int,QString,QVariant)), this, SIGNAL(imageMetadataAvailable(int,QString,QVariant))); + connect(m_session, SIGNAL(imageAvailable(int,QVideoFrame)), this, SIGNAL(imageAvailable(int,QVideoFrame))); + connect(m_session, SIGNAL(imageSaved(int,QString)), this, SIGNAL(imageSaved(int,QString))); + connect(m_session, SIGNAL(imageCaptureError(int,int,QString)), this, SIGNAL(error(int,int,QString))); +} + +bool QAndroidCameraImageCaptureControl::isReadyForCapture() const +{ + return m_session->isReadyForCapture(); +} + +QCameraImageCapture::DriveMode QAndroidCameraImageCaptureControl::driveMode() const +{ + return m_session->driveMode(); +} + +void QAndroidCameraImageCaptureControl::setDriveMode(QCameraImageCapture::DriveMode mode) +{ + m_session->setDriveMode(mode); +} + +int QAndroidCameraImageCaptureControl::capture(const QString &fileName) +{ + return m_session->capture(fileName); +} + +void QAndroidCameraImageCaptureControl::cancelCapture() +{ + m_session->cancelCapture(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcameraimagecapturecontrol.h b/src/plugins/android/src/mediacapture/qandroidcameraimagecapturecontrol.h new file mode 100644 index 0000000..f69913b --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcameraimagecapturecontrol.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** 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 QANDROIDCAMERAIMAGECAPTURECONTROL_H +#define QANDROIDCAMERAIMAGECAPTURECONTROL_H + +#include + +QT_BEGIN_NAMESPACE + +class QAndroidCameraSession; + +class QAndroidCameraImageCaptureControl : public QCameraImageCaptureControl +{ + Q_OBJECT +public: + explicit QAndroidCameraImageCaptureControl(QAndroidCameraSession *session); + + bool isReadyForCapture() const Q_DECL_OVERRIDE; + + QCameraImageCapture::DriveMode driveMode() const Q_DECL_OVERRIDE; + void setDriveMode(QCameraImageCapture::DriveMode mode) Q_DECL_OVERRIDE; + + int capture(const QString &fileName) Q_DECL_OVERRIDE; + void cancelCapture() Q_DECL_OVERRIDE; + +private: + QAndroidCameraSession *m_session; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDCAMERAIMAGECAPTURECONTROL_H diff --git a/src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.cpp new file mode 100644 index 0000000..ec5a3bc --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.cpp @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** 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 "qandroidcameraimageprocessingcontrol.h" + +#include "qandroidcamerasession.h" +#include "jcamera.h" + +QT_BEGIN_NAMESPACE + +QAndroidCameraImageProcessingControl::QAndroidCameraImageProcessingControl(QAndroidCameraSession *session) + : QCameraImageProcessingControl() + , m_session(session) +{ + connect(m_session, SIGNAL(opened()), + this, SLOT(onCameraOpened())); +} + +bool QAndroidCameraImageProcessingControl::isParameterSupported(ProcessingParameter parameter) const +{ + return (parameter == QCameraImageProcessingControl::WhiteBalancePreset); +} + +bool QAndroidCameraImageProcessingControl::isParameterValueSupported(ProcessingParameter parameter, + const QVariant &value) const +{ + if (parameter != QCameraImageProcessingControl::WhiteBalancePreset) + return false; + + if (!m_session->camera()) + return false; + + return m_supportedWhiteBalanceModes.contains(value.value()); +} + +QVariant QAndroidCameraImageProcessingControl::parameter(ProcessingParameter parameter) const +{ + if (parameter != QCameraImageProcessingControl::WhiteBalancePreset) + return QVariant(); + + if (!m_session->camera()) + return QVariant(); + + QString wb = m_session->camera()->getWhiteBalance(); + QCameraImageProcessing::WhiteBalanceMode mode = m_supportedWhiteBalanceModes.key(wb, QCameraImageProcessing::WhiteBalanceAuto); + + return QVariant::fromValue(mode); +} + +void QAndroidCameraImageProcessingControl::setParameter(ProcessingParameter parameter, const QVariant &value) +{ + if (parameter != QCameraImageProcessingControl::WhiteBalancePreset) + return; + + if (!m_session->camera()) + return; + + QString wb = m_supportedWhiteBalanceModes.value(value.value(), QString()); + if (!wb.isEmpty()) + m_session->camera()->setWhiteBalance(wb); +} + +void QAndroidCameraImageProcessingControl::onCameraOpened() +{ + m_supportedWhiteBalanceModes.clear(); + QStringList whiteBalanceModes = m_session->camera()->getSupportedWhiteBalance(); + for (int i = 0; i < whiteBalanceModes.size(); ++i) { + const QString &wb = whiteBalanceModes.at(i); + if (wb == QLatin1String("auto")) { + m_supportedWhiteBalanceModes.insert(QCameraImageProcessing::WhiteBalanceAuto, + QStringLiteral("auto")); + } else if (wb == QLatin1String("cloudy-daylight")) { + m_supportedWhiteBalanceModes.insert(QCameraImageProcessing::WhiteBalanceCloudy, + QStringLiteral("cloudy-daylight")); + } else if (wb == QLatin1String("daylight")) { + m_supportedWhiteBalanceModes.insert(QCameraImageProcessing::WhiteBalanceSunlight, + QStringLiteral("daylight")); + } else if (wb == QLatin1String("fluorescent")) { + m_supportedWhiteBalanceModes.insert(QCameraImageProcessing::WhiteBalanceFluorescent, + QStringLiteral("fluorescent")); + } else if (wb == QLatin1String("incandescent")) { + m_supportedWhiteBalanceModes.insert(QCameraImageProcessing::WhiteBalanceTungsten, + QStringLiteral("incandescent")); + } else if (wb == QLatin1String("shade")) { + m_supportedWhiteBalanceModes.insert(QCameraImageProcessing::WhiteBalanceShade, + QStringLiteral("shade")); + } else if (wb == QLatin1String("twilight")) { + m_supportedWhiteBalanceModes.insert(QCameraImageProcessing::WhiteBalanceSunset, + QStringLiteral("twilight")); + } else if (wb == QLatin1String("warm-fluorescent")) { + m_supportedWhiteBalanceModes.insert(QCameraImageProcessing::WhiteBalanceFlash, + QStringLiteral("warm-fluorescent")); + } + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.h b/src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.h new file mode 100644 index 0000000..3ef3c31 --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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 QANDROIDCAMERAIMAGEPROCESSINGCONTROL_H +#define QANDROIDCAMERAIMAGEPROCESSINGCONTROL_H + +#include + +QT_BEGIN_NAMESPACE + +class QAndroidCameraSession; + +class QAndroidCameraImageProcessingControl : public QCameraImageProcessingControl +{ + Q_OBJECT +public: + explicit QAndroidCameraImageProcessingControl(QAndroidCameraSession *session); + + bool isParameterSupported(ProcessingParameter) const Q_DECL_OVERRIDE; + bool isParameterValueSupported(ProcessingParameter parameter, const QVariant &value) const Q_DECL_OVERRIDE; + QVariant parameter(ProcessingParameter parameter) const Q_DECL_OVERRIDE; + void setParameter(ProcessingParameter parameter, const QVariant &value) Q_DECL_OVERRIDE; + +private Q_SLOTS: + void onCameraOpened(); + +private: + QAndroidCameraSession *m_session; + + QHash m_supportedWhiteBalanceModes; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDCAMERAIMAGEPROCESSINGCONTROL_H diff --git a/src/plugins/android/src/mediacapture/qandroidcameralockscontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameralockscontrol.cpp new file mode 100644 index 0000000..d9f20ec --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcameralockscontrol.cpp @@ -0,0 +1,254 @@ +/**************************************************************************** +** +** 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 "qandroidcameralockscontrol.h" + +#include "qandroidcamerasession.h" +#include "jcamera.h" +#include + +QT_BEGIN_NAMESPACE + +QAndroidCameraLocksControl::QAndroidCameraLocksControl(QAndroidCameraSession *session) + : QCameraLocksControl() + , m_session(session) + , m_supportedLocks(QCamera::NoLock) + , m_focusLockStatus(QCamera::Unlocked) + , m_exposureLockStatus(QCamera::Unlocked) + , m_whiteBalanceLockStatus(QCamera::Unlocked) +{ + connect(m_session, SIGNAL(opened()), + this, SLOT(onCameraOpened())); + + m_recalculateTimer = new QTimer(this); + m_recalculateTimer->setInterval(1000); + m_recalculateTimer->setSingleShot(true); + connect(m_recalculateTimer, SIGNAL(timeout()), this, SLOT(onRecalculateTimeOut())); +} + +QCamera::LockTypes QAndroidCameraLocksControl::supportedLocks() const +{ + return (QCamera::LockExposure | QCamera::LockWhiteBalance | QCamera::LockFocus); +} + +QCamera::LockStatus QAndroidCameraLocksControl::lockStatus(QCamera::LockType lock) const +{ + if (!m_supportedLocks.testFlag(lock) || !m_session->camera()) + return QCamera::Locked; + + if (lock == QCamera::LockFocus) + return m_focusLockStatus; + + if (lock == QCamera::LockExposure) + return m_exposureLockStatus; + + if (lock == QCamera::LockWhiteBalance) + return m_whiteBalanceLockStatus; + + return QCamera::Locked; +} + +void QAndroidCameraLocksControl::searchAndLock(QCamera::LockTypes locks) +{ + if (!m_session->camera()) + return; + + // filter out unsupported locks + locks &= m_supportedLocks; + + if (locks.testFlag(QCamera::LockFocus)) { + QString focusMode = m_session->camera()->getFocusMode(); + if (focusMode == QLatin1String("auto") + || focusMode == QLatin1String("macro") + || focusMode == QLatin1String("continuous-picture") + || focusMode == QLatin1String("continuous-video")) { + + if (m_focusLockStatus == QCamera::Searching) + m_session->camera()->cancelAutoFocus(); + else + setFocusLockStatus(QCamera::Searching, QCamera::UserRequest); + + m_session->camera()->autoFocus(); + + } else { + setFocusLockStatus(QCamera::Locked, QCamera::LockAcquired); + } + } + + if (locks.testFlag(QCamera::LockExposure) && m_exposureLockStatus != QCamera::Searching) { + if (m_session->camera()->getAutoExposureLock()) { + // if already locked, unlock and give some time to recalculate exposure + m_session->camera()->setAutoExposureLock(false); + setExposureLockStatus(QCamera::Searching, QCamera::UserRequest); + } else { + m_session->camera()->setAutoExposureLock(true); + setExposureLockStatus(QCamera::Locked, QCamera::LockAcquired); + } + } + + if (locks.testFlag(QCamera::LockWhiteBalance) && m_whiteBalanceLockStatus != QCamera::Searching) { + if (m_session->camera()->getAutoWhiteBalanceLock()) { + // if already locked, unlock and give some time to recalculate white balance + m_session->camera()->setAutoWhiteBalanceLock(false); + setWhiteBalanceLockStatus(QCamera::Searching, QCamera::UserRequest); + } else { + m_session->camera()->setAutoWhiteBalanceLock(true); + setWhiteBalanceLockStatus(QCamera::Locked, QCamera::LockAcquired); + } + } + + if (m_exposureLockStatus == QCamera::Searching || m_whiteBalanceLockStatus == QCamera::Searching) + m_recalculateTimer->start(); +} + +void QAndroidCameraLocksControl::unlock(QCamera::LockTypes locks) +{ + if (!m_session->camera()) + return; + + if (m_recalculateTimer->isActive()) + m_recalculateTimer->stop(); + + // filter out unsupported locks + locks &= m_supportedLocks; + + if (locks.testFlag(QCamera::LockFocus)) { + m_session->camera()->cancelAutoFocus(); + setFocusLockStatus(QCamera::Unlocked, QCamera::UserRequest); + } + + if (locks.testFlag(QCamera::LockExposure)) { + m_session->camera()->setAutoExposureLock(false); + setExposureLockStatus(QCamera::Unlocked, QCamera::UserRequest); + } + + if (locks.testFlag(QCamera::LockWhiteBalance)) { + m_session->camera()->setAutoWhiteBalanceLock(false); + setWhiteBalanceLockStatus(QCamera::Unlocked, QCamera::UserRequest); + } +} + +void QAndroidCameraLocksControl::onCameraOpened() +{ + m_supportedLocks = QCamera::NoLock; + m_focusLockStatus = QCamera::Unlocked; + m_exposureLockStatus = QCamera::Unlocked; + m_whiteBalanceLockStatus = QCamera::Unlocked; + + // check if focus lock is supported + QStringList focusModes = m_session->camera()->getSupportedFocusModes(); + for (int i = 0; i < focusModes.size(); ++i) { + const QString &focusMode = focusModes.at(i); + if (focusMode == QLatin1String("auto") + || focusMode == QLatin1String("continuous-picture") + || focusMode == QLatin1String("continuous-video") + || focusMode == QLatin1String("macro")) { + + m_supportedLocks |= QCamera::LockFocus; + setFocusLockStatus(QCamera::Unlocked, QCamera::UserRequest); + + connect(m_session->camera(), SIGNAL(autoFocusComplete(bool)), + this, SLOT(onCameraAutoFocusComplete(bool))); + + break; + } + } + + if (m_session->camera()->isAutoExposureLockSupported()) { + m_supportedLocks |= QCamera::LockExposure; + setExposureLockStatus(QCamera::Unlocked, QCamera::UserRequest); + } + + if (m_session->camera()->isAutoWhiteBalanceLockSupported()) { + m_supportedLocks |= QCamera::LockWhiteBalance; + setWhiteBalanceLockStatus(QCamera::Unlocked, QCamera::UserRequest); + + connect(m_session->camera(), SIGNAL(whiteBalanceChanged()), + this, SLOT(onWhiteBalanceChanged())); + } +} + +void QAndroidCameraLocksControl::onCameraAutoFocusComplete(bool success) +{ + m_focusLockStatus = success ? QCamera::Locked : QCamera::Unlocked; + QCamera::LockChangeReason reason = success ? QCamera::LockAcquired : QCamera::LockFailed; + emit lockStatusChanged(QCamera::LockFocus, m_focusLockStatus, reason); +} + +void QAndroidCameraLocksControl::onRecalculateTimeOut() +{ + if (m_exposureLockStatus == QCamera::Searching) { + m_session->camera()->setAutoExposureLock(true); + setExposureLockStatus(QCamera::Locked, QCamera::LockAcquired); + } + + if (m_whiteBalanceLockStatus == QCamera::Searching) { + m_session->camera()->setAutoWhiteBalanceLock(true); + setWhiteBalanceLockStatus(QCamera::Locked, QCamera::LockAcquired); + } +} + +void QAndroidCameraLocksControl::onWhiteBalanceChanged() +{ + // changing the white balance mode releases the white balance lock + if (m_whiteBalanceLockStatus != QCamera::Unlocked) + setWhiteBalanceLockStatus(QCamera::Unlocked, QCamera::LockLost); +} + +void QAndroidCameraLocksControl::setFocusLockStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason) +{ + m_focusLockStatus = status; + emit lockStatusChanged(QCamera::LockFocus, m_focusLockStatus, reason); +} + +void QAndroidCameraLocksControl::setWhiteBalanceLockStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason) +{ + m_whiteBalanceLockStatus = status; + emit lockStatusChanged(QCamera::LockWhiteBalance, m_whiteBalanceLockStatus, reason); +} + +void QAndroidCameraLocksControl::setExposureLockStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason) +{ + m_exposureLockStatus = status; + emit lockStatusChanged(QCamera::LockExposure, m_exposureLockStatus, reason); +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcameralockscontrol.h b/src/plugins/android/src/mediacapture/qandroidcameralockscontrol.h new file mode 100644 index 0000000..d49821b --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcameralockscontrol.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** 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 QANDROIDCAMERALOCKSCONTROL_H +#define QANDROIDCAMERALOCKSCONTROL_H + +#include + +QT_BEGIN_NAMESPACE + +class QAndroidCameraSession; +class QTimer; + +class QAndroidCameraLocksControl : public QCameraLocksControl +{ + Q_OBJECT +public: + explicit QAndroidCameraLocksControl(QAndroidCameraSession *session); + + QCamera::LockTypes supportedLocks() const Q_DECL_OVERRIDE; + QCamera::LockStatus lockStatus(QCamera::LockType lock) const Q_DECL_OVERRIDE; + void searchAndLock(QCamera::LockTypes locks) Q_DECL_OVERRIDE; + void unlock(QCamera::LockTypes locks) Q_DECL_OVERRIDE; + +private Q_SLOTS: + void onCameraOpened(); + void onCameraAutoFocusComplete(bool success); + void onRecalculateTimeOut(); + void onWhiteBalanceChanged(); + +private: + void setFocusLockStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason); + void setWhiteBalanceLockStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason); + void setExposureLockStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason); + + QAndroidCameraSession *m_session; + + QTimer *m_recalculateTimer; + + QCamera::LockTypes m_supportedLocks; + + QCamera::LockStatus m_focusLockStatus; + QCamera::LockStatus m_exposureLockStatus; + QCamera::LockStatus m_whiteBalanceLockStatus; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDCAMERALOCKSCONTROL_H diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp new file mode 100644 index 0000000..761b716 --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp @@ -0,0 +1,553 @@ +/**************************************************************************** +** +** 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 "qandroidcamerasession.h" + +#include "jcamera.h" +#include "jmultimediautils.h" +#include "qandroidvideooutput.h" +#include "qandroidmultimediautils.h" +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +static void textureReadyCallback(void *context) +{ + if (context) + reinterpret_cast(context)->onSurfaceTextureReady(); +} + +QAndroidCameraSession::QAndroidCameraSession(QObject *parent) + : QObject(parent) + , m_selectedCamera(0) + , m_camera(0) + , m_nativeOrientation(0) + , m_videoOutput(0) + , m_captureMode(QCamera::CaptureViewfinder) + , m_state(QCamera::UnloadedState) + , m_savedState(-1) + , m_status(QCamera::UnloadedStatus) + , m_previewStarted(false) + , m_imageSettingsDirty(true) + , m_captureDestination(QCameraImageCapture::CaptureToFile) + , m_captureImageDriveMode(QCameraImageCapture::SingleImageCapture) + , m_lastImageCaptureId(0) + , m_readyForCapture(false) + , m_captureCanceled(false) + , m_currentImageCaptureId(-1) +{ + if (qApp) { + connect(qApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)), + this, SLOT(onApplicationStateChanged(Qt::ApplicationState))); + } +} + +QAndroidCameraSession::~QAndroidCameraSession() +{ + close(); +} + +void QAndroidCameraSession::setCaptureMode(QCamera::CaptureModes mode) +{ + if (m_captureMode == mode || !isCaptureModeSupported(mode)) + return; + + m_captureMode = mode; + emit captureModeChanged(m_captureMode); + + if (m_previewStarted && m_captureMode.testFlag(QCamera::CaptureStillImage)) + adjustViewfinderSize(m_imageSettings.resolution()); +} + +bool QAndroidCameraSession::isCaptureModeSupported(QCamera::CaptureModes mode) const +{ + if (mode & (QCamera::CaptureStillImage & QCamera::CaptureVideo)) + return false; + + return true; +} + +void QAndroidCameraSession::setState(QCamera::State state) +{ + // If the application is inactive, the camera shouldn't be started. Save the desired state + // instead and it will be set when the application becomes active. + if (qApp->applicationState() != Qt::ApplicationActive) { + m_savedState = state; + return; + } + + if (m_state == state) + return; + + switch (state) { + case QCamera::UnloadedState: + close(); + break; + case QCamera::LoadedState: + case QCamera::ActiveState: + if (!m_camera && !open()) { + emit error(QCamera::CameraError, QStringLiteral("Failed to open camera")); + return; + } + if (state == QCamera::ActiveState) + startPreview(); + else if (state == QCamera::LoadedState) + stopPreview(); + break; + } + + m_state = state; + emit stateChanged(m_state); +} + +bool QAndroidCameraSession::open() +{ + close(); + + m_status = QCamera::LoadingStatus; + emit statusChanged(m_status); + + m_camera = JCamera::open(m_selectedCamera); + + if (m_camera) { + connect(m_camera, SIGNAL(pictureExposed()), this, SLOT(onCameraPictureExposed())); + connect(m_camera, SIGNAL(pictureCaptured(QByteArray)), this, SLOT(onCameraPictureCaptured(QByteArray))); + m_nativeOrientation = m_camera->getNativeOrientation(); + m_status = QCamera::LoadedStatus; + emit opened(); + } else { + m_status = QCamera::UnavailableStatus; + } + + emit statusChanged(m_status); + + return m_camera != 0; +} + +void QAndroidCameraSession::close() +{ + if (!m_camera) + return; + + stopPreview(); + + m_status = QCamera::UnloadingStatus; + emit statusChanged(m_status); + + m_readyForCapture = false; + m_currentImageCaptureId = -1; + m_currentImageCaptureFileName.clear(); + m_imageSettingsDirty = true; + + m_camera->release(); + delete m_camera; + m_camera = 0; + + m_status = QCamera::UnloadedStatus; + emit statusChanged(m_status); +} + +void QAndroidCameraSession::setVideoPreview(QAndroidVideoOutput *videoOutput) +{ + if (m_videoOutput) + m_videoOutput->stop(); + + m_videoOutput = videoOutput; +} + +void QAndroidCameraSession::adjustViewfinderSize(const QSize &captureSize, bool restartPreview) +{ + if (!m_camera) + return; + + QSize viewfinderResolution = m_camera->previewSize(); + const qreal aspectRatio = qreal(captureSize.width()) / qreal(captureSize.height()); + if (qFuzzyCompare(aspectRatio, qreal(viewfinderResolution.width()) / qreal(viewfinderResolution.height()))) + return; + + QList previewSizes = m_camera->getSupportedPreviewSizes(); + for (int i = previewSizes.count() - 1; i >= 0; --i) { + const QSize &size = previewSizes.at(i); + // search for viewfinder resolution with the same aspect ratio + if (qFuzzyCompare(aspectRatio, (static_cast(size.width())/static_cast(size.height())))) { + viewfinderResolution = size; + break; + } + } + + if (m_camera->previewSize() != viewfinderResolution) { + if (m_videoOutput) + m_videoOutput->setVideoSize(viewfinderResolution); + + // if preview is started, we have to stop it first before changing its size + if (m_previewStarted && restartPreview) + m_camera->stopPreview(); + + m_camera->setPreviewSize(viewfinderResolution); + + // restart preview + if (m_previewStarted && restartPreview) + m_camera->startPreview(); + } +} + +void QAndroidCameraSession::startPreview() +{ + if (!m_camera || m_previewStarted) + return; + + m_status = QCamera::StartingStatus; + emit statusChanged(m_status); + + applyImageSettings(); + adjustViewfinderSize(m_imageSettings.resolution()); + + if (m_videoOutput) { + if (m_videoOutput->isTextureReady()) + m_camera->setPreviewTexture(m_videoOutput->surfaceTexture()); + else + m_videoOutput->setTextureReadyCallback(textureReadyCallback, this); + } + + JMultimediaUtils::enableOrientationListener(true); + + m_camera->startPreview(); + m_previewStarted = true; + + m_status = QCamera::ActiveStatus; + emit statusChanged(m_status); + + setReadyForCapture(true); +} + +void QAndroidCameraSession::stopPreview() +{ + if (!m_camera || !m_previewStarted) + return; + + m_status = QCamera::StoppingStatus; + emit statusChanged(m_status); + + JMultimediaUtils::enableOrientationListener(false); + + m_camera->stopPreview(); + if (m_videoOutput) + m_videoOutput->stop(); + m_previewStarted = false; + + m_status = QCamera::LoadedStatus; + emit statusChanged(m_status); + + setReadyForCapture(false); +} + +void QAndroidCameraSession::setImageSettings(const QImageEncoderSettings &settings) +{ + if (m_imageSettings == settings) + return; + + m_imageSettings = settings; + if (m_imageSettings.codec().isEmpty()) + m_imageSettings.setCodec(QLatin1String("jpeg")); + + m_imageSettingsDirty = true; + + applyImageSettings(); + + if (m_readyForCapture && m_captureMode.testFlag(QCamera::CaptureStillImage)) + adjustViewfinderSize(m_imageSettings.resolution()); +} + +int QAndroidCameraSession::currentCameraRotation() const +{ + if (!m_camera) + return 0; + + // subtract natural camera orientation and physical device orientation + int rotation = 0; + int deviceOrientation = (JMultimediaUtils::getDeviceOrientation() + 45) / 90 * 90; + if (m_camera->getFacing() == JCamera::CameraFacingFront) + rotation = (m_nativeOrientation - deviceOrientation + 360) % 360; + else // back-facing camera + rotation = (m_nativeOrientation + deviceOrientation) % 360; + + return rotation; +} + +void QAndroidCameraSession::applyImageSettings() +{ + if (!m_camera || !m_imageSettingsDirty) + return; + + const QSize requestedResolution = m_imageSettings.resolution(); + const QList supportedResolutions = m_camera->getSupportedPictureSizes(); + + if (!requestedResolution.isValid()) { + // if no resolution is set, use the highest supported one + m_imageSettings.setResolution(supportedResolutions.last()); + } else if (!supportedResolutions.contains(requestedResolution)) { + // if the requested resolution is not supported, find the closest one + int reqPixelCount = requestedResolution.width() * requestedResolution.height(); + QList supportedPixelCounts; + for (int i = 0; i < supportedResolutions.size(); ++i) { + const QSize &s = supportedResolutions.at(i); + supportedPixelCounts.append(s.width() * s.height()); + } + int closestIndex = qt_findClosestValue(supportedPixelCounts, reqPixelCount); + m_imageSettings.setResolution(supportedResolutions.at(closestIndex)); + } + + int jpegQuality = 100; + switch (m_imageSettings.quality()) { + case QMultimedia::VeryLowQuality: + jpegQuality = 20; + break; + case QMultimedia::LowQuality: + jpegQuality = 40; + break; + case QMultimedia::NormalQuality: + jpegQuality = 60; + break; + case QMultimedia::HighQuality: + jpegQuality = 80; + break; + case QMultimedia::VeryHighQuality: + jpegQuality = 100; + break; + } + + m_camera->setPictureSize(m_imageSettings.resolution()); + m_camera->setJpegQuality(jpegQuality); + + m_imageSettingsDirty = false; +} + +bool QAndroidCameraSession::isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const +{ + return destination & (QCameraImageCapture::CaptureToFile | QCameraImageCapture::CaptureToBuffer); +} + +QCameraImageCapture::CaptureDestinations QAndroidCameraSession::captureDestination() const +{ + return m_captureDestination; +} + +void QAndroidCameraSession::setCaptureDestination(QCameraImageCapture::CaptureDestinations destination) +{ + if (m_captureDestination != destination) { + m_captureDestination = destination; + emit captureDestinationChanged(m_captureDestination); + } +} + +bool QAndroidCameraSession::isReadyForCapture() const +{ + return m_status == QCamera::ActiveStatus && m_readyForCapture; +} + +void QAndroidCameraSession::setReadyForCapture(bool ready) +{ + if (m_readyForCapture == ready) + return; + + m_readyForCapture = ready; + emit readyForCaptureChanged(ready); +} + +QCameraImageCapture::DriveMode QAndroidCameraSession::driveMode() const +{ + return m_captureImageDriveMode; +} + +void QAndroidCameraSession::setDriveMode(QCameraImageCapture::DriveMode mode) +{ + m_captureImageDriveMode = mode; +} + +int QAndroidCameraSession::capture(const QString &fileName) +{ + ++m_lastImageCaptureId; + + if (!isReadyForCapture()) { + emit imageCaptureError(m_lastImageCaptureId, QCameraImageCapture::NotReadyError, + tr("Camera not ready")); + return m_lastImageCaptureId; + } + + if (m_captureImageDriveMode == QCameraImageCapture::SingleImageCapture) { + setReadyForCapture(false); + + m_currentImageCaptureId = m_lastImageCaptureId; + m_currentImageCaptureFileName = fileName; + + applyImageSettings(); + adjustViewfinderSize(m_imageSettings.resolution()); + + // adjust picture rotation depending on the device orientation + m_camera->setRotation(currentCameraRotation()); + + m_camera->takePicture(); + } else { + emit imageCaptureError(m_lastImageCaptureId, QCameraImageCapture::NotSupportedFeatureError, + tr("Drive mode not supported")); + } + + return m_lastImageCaptureId; +} + +void QAndroidCameraSession::cancelCapture() +{ + if (m_readyForCapture) + return; + + m_captureCanceled = true; +} + +void QAndroidCameraSession::onCameraPictureExposed() +{ + if (m_captureCanceled) + return; + + emit imageExposed(m_currentImageCaptureId); +} + +void QAndroidCameraSession::onCameraPictureCaptured(const QByteArray &data) +{ + if (!m_captureCanceled) { + // generate a preview from the viewport + if (m_videoOutput) + emit imageCaptured(m_currentImageCaptureId, m_videoOutput->toImage()); + + // Loading and saving the captured image can be slow, do it in a separate thread + QtConcurrent::run(this, &QAndroidCameraSession::processCapturedImage, + m_currentImageCaptureId, + data, + m_captureDestination, + m_currentImageCaptureFileName); + } + + m_captureCanceled = false; + + // Preview needs to be restarted after taking a picture + m_camera->startPreview(); + + setReadyForCapture(true); +} + +void QAndroidCameraSession::processCapturedImage(int id, + const QByteArray &data, + QCameraImageCapture::CaptureDestinations dest, + const QString &fileName) +{ + + + if (dest & QCameraImageCapture::CaptureToFile) { + const QString actualFileName = m_mediaStorageLocation.generateFileName(fileName, + QAndroidMediaStorageLocation::Camera, + QLatin1String("IMG_"), + QLatin1String("jpg")); + + QFile file(actualFileName); + if (file.open(QFile::WriteOnly)) { + if (file.write(data) == data.size()) { + // 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); + if (actualFileName.startsWith(standardLoc)) + JMultimediaUtils::registerMediaFile(actualFileName); + + emit imageSaved(id, actualFileName); + } else { + emit imageCaptureError(id, QCameraImageCapture::OutOfSpaceError, file.errorString()); + } + } else { + const QString errorMessage = tr("Could not open destination file: %1").arg(actualFileName); + emit imageCaptureError(id, QCameraImageCapture::ResourceError, errorMessage); + } + } + + if (dest & QCameraImageCapture::CaptureToBuffer) { + QImage image; + const bool ok = image.loadFromData(data, "JPG"); + + if (ok) { + QVideoFrame frame(image); + emit imageAvailable(id, frame); + } else { + emit imageCaptureError(id, QCameraImageCapture::FormatError, + tr("Could not load JPEG data from captured image")); + } + } +} + +void QAndroidCameraSession::onSurfaceTextureReady() +{ + if (m_camera && m_videoOutput) + m_camera->setPreviewTexture(m_videoOutput->surfaceTexture()); +} + +void QAndroidCameraSession::onApplicationStateChanged(Qt::ApplicationState state) +{ + switch (state) { + case Qt::ApplicationInactive: + if (m_state != QCamera::UnloadedState) { + m_savedState = m_state; + close(); + m_state = QCamera::UnloadedState; + emit stateChanged(m_state); + } + break; + case Qt::ApplicationActive: + if (m_savedState != -1) { + setState(QCamera::State(m_savedState)); + m_savedState = -1; + } + break; + default: + break; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.h b/src/plugins/android/src/mediacapture/qandroidcamerasession.h new file mode 100644 index 0000000..f1cf44e --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.h @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** 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 QANDROIDCAMERASESSION_H +#define QANDROIDCAMERASESSION_H + +#include +#include +#include +#include "qandroidmediastoragelocation.h" + +QT_BEGIN_NAMESPACE + +class JCamera; +class QAndroidVideoOutput; + +class QAndroidCameraSession : public QObject +{ + Q_OBJECT +public: + explicit QAndroidCameraSession(QObject *parent = 0); + ~QAndroidCameraSession(); + + void setSelectedCamera(int cameraId) { m_selectedCamera = cameraId; } + JCamera *camera() const { return m_camera; } + + QCamera::State state() const { return m_state; } + void setState(QCamera::State state); + + QCamera::Status status() const { return m_status; } + + QCamera::CaptureModes captureMode() const { return m_captureMode; } + void setCaptureMode(QCamera::CaptureModes mode); + bool isCaptureModeSupported(QCamera::CaptureModes mode) const; + + void setVideoPreview(QAndroidVideoOutput *videoOutput); + void adjustViewfinderSize(const QSize &captureSize, bool restartPreview = true); + + QImageEncoderSettings imageSettings() const { return m_imageSettings; } + void setImageSettings(const QImageEncoderSettings &settings); + + bool isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const; + QCameraImageCapture::CaptureDestinations captureDestination() const; + void setCaptureDestination(QCameraImageCapture::CaptureDestinations destination); + + bool isReadyForCapture() const; + void setReadyForCapture(bool ready); + QCameraImageCapture::DriveMode driveMode() const; + void setDriveMode(QCameraImageCapture::DriveMode mode); + int capture(const QString &fileName); + void cancelCapture(); + + void onSurfaceTextureReady(); + + int currentCameraRotation() const; + +Q_SIGNALS: + void statusChanged(QCamera::Status status); + void stateChanged(QCamera::State); + void error(int error, const QString &errorString); + void captureModeChanged(QCamera::CaptureModes); + void opened(); + + void captureDestinationChanged(QCameraImageCapture::CaptureDestinations destination); + + void readyForCaptureChanged(bool); + void imageExposed(int id); + void imageCaptured(int id, const QImage &preview); + void imageMetadataAvailable(int id, const QString &key, const QVariant &value); + void imageAvailable(int id, const QVideoFrame &buffer); + void imageSaved(int id, const QString &fileName); + void imageCaptureError(int id, int error, const QString &errorString); + +private Q_SLOTS: + void onApplicationStateChanged(Qt::ApplicationState state); + + void onCameraPictureExposed(); + void onCameraPictureCaptured(const QByteArray &data); + +private: + bool open(); + void close(); + + void startPreview(); + void stopPreview(); + + void applyImageSettings(); + void processPreviewImage(int id); + void processCapturedImage(int id, + const QByteArray &data, + QCameraImageCapture::CaptureDestinations dest, + const QString &fileName); + + int m_selectedCamera; + JCamera *m_camera; + int m_nativeOrientation; + QAndroidVideoOutput *m_videoOutput; + + QCamera::CaptureModes m_captureMode; + QCamera::State m_state; + int m_savedState; + QCamera::Status m_status; + bool m_previewStarted; + + QImageEncoderSettings m_imageSettings; + bool m_imageSettingsDirty; + QCameraImageCapture::CaptureDestinations m_captureDestination; + QCameraImageCapture::DriveMode m_captureImageDriveMode; + int m_lastImageCaptureId; + bool m_readyForCapture; + bool m_captureCanceled; + int m_currentImageCaptureId; + QString m_currentImageCaptureFileName; + + QAndroidMediaStorageLocation m_mediaStorageLocation; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDCAMERASESSION_H diff --git a/src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.cpp new file mode 100644 index 0000000..b7030e5 --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.cpp @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** 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 "qandroidcamerazoomcontrol.h" + +#include "qandroidcamerasession.h" +#include "jcamera.h" +#include "qandroidmultimediautils.h" +#include + +QT_BEGIN_NAMESPACE + +QAndroidCameraZoomControl::QAndroidCameraZoomControl(QAndroidCameraSession *session) + : QCameraZoomControl() + , m_cameraSession(session) + , m_maximumZoom(1.0) + , m_requestedZoom(1.0) + , m_currentZoom(1.0) +{ + connect(m_cameraSession, SIGNAL(opened()), + this, SLOT(onCameraOpened())); +} + +qreal QAndroidCameraZoomControl::maximumOpticalZoom() const +{ + // Optical zoom not supported + return 1.0; +} + +qreal QAndroidCameraZoomControl::maximumDigitalZoom() const +{ + return m_maximumZoom; +} + +qreal QAndroidCameraZoomControl::requestedOpticalZoom() const +{ + // Optical zoom not supported + return 1.0; +} + +qreal QAndroidCameraZoomControl::requestedDigitalZoom() const +{ + return m_requestedZoom; +} + +qreal QAndroidCameraZoomControl::currentOpticalZoom() const +{ + // Optical zoom not supported + return 1.0; +} + +qreal QAndroidCameraZoomControl::currentDigitalZoom() const +{ + return m_currentZoom; +} + +void QAndroidCameraZoomControl::zoomTo(qreal optical, qreal digital) +{ + Q_UNUSED(optical); + + if (!m_cameraSession->camera() || + qFuzzyCompare(m_requestedZoom, digital) || + qFuzzyCompare(m_maximumZoom, qreal(1))) { + return; + } + + m_requestedZoom = digital; + emit requestedDigitalZoomChanged(m_requestedZoom); + + digital = qBound(qreal(1), digital, m_maximumZoom); + int validZoomIndex = qt_findClosestValue(m_zoomRatios, qRound(digital * 100)); + qreal newZoom = m_zoomRatios.at(validZoomIndex) / qreal(100); + if (!qFuzzyCompare(m_currentZoom, newZoom)) { + m_cameraSession->camera()->setZoom(validZoomIndex); + m_currentZoom = newZoom; + emit currentDigitalZoomChanged(m_currentZoom); + } +} + +void QAndroidCameraZoomControl::onCameraOpened() +{ + m_requestedZoom = 1.0; + m_currentZoom = 1.0; + emit requestedDigitalZoomChanged(m_requestedZoom); + emit currentDigitalZoomChanged(m_currentZoom); + + if (m_cameraSession->camera()->isZoomSupported()) { + m_zoomRatios = m_cameraSession->camera()->getZoomRatios(); + qreal maxZoom = m_zoomRatios.last() / qreal(100); + if (m_maximumZoom != maxZoom) { + m_maximumZoom = maxZoom; + emit maximumDigitalZoomChanged(m_maximumZoom); + } + } else { + m_zoomRatios.clear(); + if (!qFuzzyCompare(m_maximumZoom, qreal(1))) { + m_maximumZoom = 1.0; + emit maximumDigitalZoomChanged(m_maximumZoom); + } + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.h b/src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.h new file mode 100644 index 0000000..b102c5d --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** 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 QANDROIDCAMERAZOOMCONTROL_H +#define QANDROIDCAMERAZOOMCONTROL_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QAndroidCameraSession; + +class QAndroidCameraZoomControl : public QCameraZoomControl +{ + Q_OBJECT +public: + explicit QAndroidCameraZoomControl(QAndroidCameraSession *session); + + qreal maximumOpticalZoom() const Q_DECL_OVERRIDE; + qreal maximumDigitalZoom() const Q_DECL_OVERRIDE; + qreal requestedOpticalZoom() const Q_DECL_OVERRIDE; + qreal requestedDigitalZoom() const Q_DECL_OVERRIDE; + qreal currentOpticalZoom() const Q_DECL_OVERRIDE; + qreal currentDigitalZoom() const Q_DECL_OVERRIDE; + void zoomTo(qreal optical, qreal digital) Q_DECL_OVERRIDE; + +private Q_SLOTS: + void onCameraOpened(); + +private: + QAndroidCameraSession *m_cameraSession; + + qreal m_maximumZoom; + QList m_zoomRatios; + qreal m_requestedZoom; + qreal m_currentZoom; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDCAMERAZOOMCONTROL_H diff --git a/src/plugins/android/src/mediacapture/qandroidcaptureservice.cpp b/src/plugins/android/src/mediacapture/qandroidcaptureservice.cpp new file mode 100644 index 0000000..3468c64 --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcaptureservice.cpp @@ -0,0 +1,216 @@ +/**************************************************************************** +** +** 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 "qandroidcaptureservice.h" + +#include "qandroidmediarecordercontrol.h" +#include "qandroidcapturesession.h" +#include "qandroidcameracontrol.h" +#include "qandroidvideodeviceselectorcontrol.h" +#include "qandroidaudioinputselectorcontrol.h" +#include "qandroidcamerasession.h" +#include "qandroidvideorendercontrol.h" +#include "qandroidcamerazoomcontrol.h" +#include "qandroidcameraexposurecontrol.h" +#include "qandroidcameraflashcontrol.h" +#include "qandroidcamerafocuscontrol.h" +#include "qandroidcameralockscontrol.h" +#include "qandroidcameraimageprocessingcontrol.h" +#include "qandroidimageencodercontrol.h" +#include "qandroidcameraimagecapturecontrol.h" +#include "qandroidcameracapturedestinationcontrol.h" +#include "qandroidcameracapturebufferformatcontrol.h" +#include "qandroidaudioencodersettingscontrol.h" +#include "qandroidvideoencodersettingscontrol.h" +#include "qandroidmediacontainercontrol.h" + +#include + +QT_BEGIN_NAMESPACE + +QAndroidCaptureService::QAndroidCaptureService(const QString &service, QObject *parent) + : QMediaService(parent) + , m_service(service) + , m_videoRendererControl(0) +{ + if (m_service == QLatin1String(Q_MEDIASERVICE_CAMERA)) { + m_cameraSession = new QAndroidCameraSession; + m_cameraControl = new QAndroidCameraControl(m_cameraSession); + m_videoInputControl = new QAndroidVideoDeviceSelectorControl(m_cameraSession); + m_cameraZoomControl = new QAndroidCameraZoomControl(m_cameraSession); + m_cameraExposureControl = new QAndroidCameraExposureControl(m_cameraSession); + m_cameraFlashControl = new QAndroidCameraFlashControl(m_cameraSession); + m_cameraFocusControl = new QAndroidCameraFocusControl(m_cameraSession); + m_cameraLocksControl = new QAndroidCameraLocksControl(m_cameraSession); + m_cameraImageProcessingControl = new QAndroidCameraImageProcessingControl(m_cameraSession); + m_imageEncoderControl = new QAndroidImageEncoderControl(m_cameraSession); + m_imageCaptureControl = new QAndroidCameraImageCaptureControl(m_cameraSession); + m_captureDestinationControl = new QAndroidCameraCaptureDestinationControl(m_cameraSession); + m_captureBufferFormatControl = new QAndroidCameraCaptureBufferFormatControl; + m_audioInputControl = 0; + } else { + m_cameraSession = 0; + m_cameraControl = 0; + m_videoInputControl = 0; + m_cameraZoomControl = 0; + m_cameraExposureControl = 0; + m_cameraFlashControl = 0; + m_cameraFocusControl = 0; + m_cameraLocksControl = 0; + m_cameraImageProcessingControl = 0; + m_imageEncoderControl = 0; + m_imageCaptureControl = 0; + m_captureDestinationControl = 0; + m_captureBufferFormatControl = 0; + m_videoEncoderSettingsControl = 0; + } + + m_captureSession = new QAndroidCaptureSession(m_cameraSession); + m_recorderControl = new QAndroidMediaRecorderControl(m_captureSession); + m_audioEncoderSettingsControl = new QAndroidAudioEncoderSettingsControl(m_captureSession); + m_mediaContainerControl = new QAndroidMediaContainerControl(m_captureSession); + + if (m_service == QLatin1String(Q_MEDIASERVICE_CAMERA)) { + m_videoEncoderSettingsControl = new QAndroidVideoEncoderSettingsControl(m_captureSession); + } else { + m_audioInputControl = new QAndroidAudioInputSelectorControl(m_captureSession); + m_captureSession->setAudioInput(m_audioInputControl->defaultInput()); + } +} + +QAndroidCaptureService::~QAndroidCaptureService() +{ + delete m_audioEncoderSettingsControl; + delete m_videoEncoderSettingsControl; + delete m_mediaContainerControl; + delete m_recorderControl; + delete m_captureSession; + delete m_cameraControl; + delete m_audioInputControl; + delete m_videoInputControl; + delete m_videoRendererControl; + delete m_cameraZoomControl; + delete m_cameraExposureControl; + delete m_cameraFlashControl; + delete m_cameraFocusControl; + delete m_cameraLocksControl; + delete m_cameraImageProcessingControl; + delete m_imageEncoderControl; + delete m_imageCaptureControl; + delete m_captureDestinationControl; + delete m_captureBufferFormatControl; + delete m_cameraSession; +} + +QMediaControl *QAndroidCaptureService::requestControl(const char *name) +{ + if (qstrcmp(name, QMediaRecorderControl_iid) == 0) + return m_recorderControl; + + if (qstrcmp(name, QMediaContainerControl_iid) == 0) + return m_mediaContainerControl; + + if (qstrcmp(name, QAudioEncoderSettingsControl_iid) == 0) + return m_audioEncoderSettingsControl; + + if (qstrcmp(name, QVideoEncoderSettingsControl_iid) == 0) + return m_videoEncoderSettingsControl; + + if (qstrcmp(name, QCameraControl_iid) == 0) + return m_cameraControl; + + if (qstrcmp(name, QAudioInputSelectorControl_iid) == 0) + return m_audioInputControl; + + if (qstrcmp(name, QVideoDeviceSelectorControl_iid) == 0) + return m_videoInputControl; + + if (qstrcmp(name, QCameraZoomControl_iid) == 0) + return m_cameraZoomControl; + + if (qstrcmp(name, QCameraExposureControl_iid) == 0) + return m_cameraExposureControl; + + if (qstrcmp(name, QCameraFlashControl_iid) == 0) + return m_cameraFlashControl; + + if (qstrcmp(name, QCameraFocusControl_iid) == 0) + return m_cameraFocusControl; + + if (qstrcmp(name, QCameraLocksControl_iid) == 0) + return m_cameraLocksControl; + + if (qstrcmp(name, QCameraImageProcessingControl_iid) == 0) + return m_cameraImageProcessingControl; + + if (qstrcmp(name, QImageEncoderControl_iid) == 0) + return m_imageEncoderControl; + + if (qstrcmp(name, QCameraImageCaptureControl_iid) == 0) + return m_imageCaptureControl; + + if (qstrcmp(name, QCameraCaptureDestinationControl_iid) == 0) + return m_captureDestinationControl; + + if (qstrcmp(name, QCameraCaptureBufferFormatControl_iid) == 0) + return m_captureBufferFormatControl; + + if (qstrcmp(name, QVideoRendererControl_iid) == 0 + && m_service == QLatin1String(Q_MEDIASERVICE_CAMERA) + && !m_videoRendererControl) { + m_videoRendererControl = new QAndroidVideoRendererControl; + m_cameraSession->setVideoPreview(m_videoRendererControl); + return m_videoRendererControl; + } + + return 0; +} + +void QAndroidCaptureService::releaseControl(QMediaControl *control) +{ + if (control && control == m_videoRendererControl) { + m_cameraSession->setVideoPreview(0); + delete m_videoRendererControl; + m_videoRendererControl = 0; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcaptureservice.h b/src/plugins/android/src/mediacapture/qandroidcaptureservice.h new file mode 100644 index 0000000..71aaf2d --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcaptureservice.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** 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 QANDROIDCAPTURESERVICE_H +#define QANDROIDCAPTURESERVICE_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QAndroidMediaRecorderControl; +class QAndroidCaptureSession; +class QAndroidCameraControl; +class QAndroidVideoDeviceSelectorControl; +class QAndroidAudioInputSelectorControl; +class QAndroidCameraSession; +class QAndroidVideoRendererControl; +class QAndroidCameraZoomControl; +class QAndroidCameraExposureControl; +class QAndroidCameraFlashControl; +class QAndroidCameraFocusControl; +class QAndroidCameraLocksControl; +class QAndroidCameraImageProcessingControl; +class QAndroidImageEncoderControl; +class QAndroidCameraImageCaptureControl; +class QAndroidCameraCaptureDestinationControl; +class QAndroidCameraCaptureBufferFormatControl; +class QAndroidAudioEncoderSettingsControl; +class QAndroidVideoEncoderSettingsControl; +class QAndroidMediaContainerControl; + +class QAndroidCaptureService : public QMediaService +{ + Q_OBJECT + +public: + explicit QAndroidCaptureService(const QString &service, QObject *parent = 0); + virtual ~QAndroidCaptureService(); + + QMediaControl *requestControl(const char *name); + void releaseControl(QMediaControl *); + +private: + QString m_service; + + QAndroidMediaRecorderControl *m_recorderControl; + QAndroidCaptureSession *m_captureSession; + QAndroidCameraControl *m_cameraControl; + QAndroidVideoDeviceSelectorControl *m_videoInputControl; + QAndroidAudioInputSelectorControl *m_audioInputControl; + QAndroidCameraSession *m_cameraSession; + QAndroidVideoRendererControl *m_videoRendererControl; + QAndroidCameraZoomControl *m_cameraZoomControl; + QAndroidCameraExposureControl *m_cameraExposureControl; + QAndroidCameraFlashControl *m_cameraFlashControl; + QAndroidCameraFocusControl *m_cameraFocusControl; + QAndroidCameraLocksControl *m_cameraLocksControl; + QAndroidCameraImageProcessingControl *m_cameraImageProcessingControl; + QAndroidImageEncoderControl *m_imageEncoderControl; + QAndroidCameraImageCaptureControl *m_imageCaptureControl; + QAndroidCameraCaptureDestinationControl *m_captureDestinationControl; + QAndroidCameraCaptureBufferFormatControl *m_captureBufferFormatControl; + QAndroidAudioEncoderSettingsControl *m_audioEncoderSettingsControl; + QAndroidVideoEncoderSettingsControl *m_videoEncoderSettingsControl; + QAndroidMediaContainerControl *m_mediaContainerControl; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDCAPTURESERVICE_H diff --git a/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp b/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp new file mode 100644 index 0000000..1927aeb --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp @@ -0,0 +1,547 @@ +/**************************************************************************** +** +** 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 "qandroidcapturesession.h" + +#include "jcamera.h" +#include "qandroidcamerasession.h" +#include "jmultimediautils.h" +#include "qandroidmultimediautils.h" +#include + +QT_BEGIN_NAMESPACE + +QAndroidCaptureSession::QAndroidCaptureSession(QAndroidCameraSession *cameraSession) + : QObject() + , m_mediaRecorder(0) + , m_cameraSession(cameraSession) + , m_audioSource(JMediaRecorder::DefaultAudioSource) + , m_duration(0) + , m_state(QMediaRecorder::StoppedState) + , m_status(QMediaRecorder::UnloadedStatus) + , m_resolutionDirty(false) + , m_containerFormatDirty(true) + , m_videoSettingsDirty(true) + , m_audioSettingsDirty(true) + , m_outputFormat(JMediaRecorder::DefaultOutputFormat) + , m_audioEncoder(JMediaRecorder::DefaultAudioEncoder) + , m_videoEncoder(JMediaRecorder::DefaultVideoEncoder) +{ + if (cameraSession) { + connect(cameraSession, SIGNAL(opened()), this, SLOT(onCameraOpened())); + connect(cameraSession, SIGNAL(statusChanged(QCamera::Status)), + this, SLOT(onCameraStatusChanged(QCamera::Status))); + connect(cameraSession, SIGNAL(captureModeChanged(QCamera::CaptureModes)), + this, SLOT(onCameraCaptureModeChanged(QCamera::CaptureModes))); + } + + m_notifyTimer.setInterval(1000); + connect(&m_notifyTimer, SIGNAL(timeout()), this, SLOT(updateDuration())); +} + +QAndroidCaptureSession::~QAndroidCaptureSession() +{ + stop(); + delete m_mediaRecorder; +} + +void QAndroidCaptureSession::setAudioInput(const QString &input) +{ + if (m_audioInput == input) + return; + + m_audioInput = input; + + if (m_audioInput == QLatin1String("default")) + m_audioSource = JMediaRecorder::DefaultAudioSource; + else if (m_audioInput == QLatin1String("mic")) + m_audioSource = JMediaRecorder::Mic; + else if (m_audioInput == QLatin1String("voice_uplink")) + m_audioSource = JMediaRecorder::VoiceUplink; + else if (m_audioInput == QLatin1String("voice_downlink")) + m_audioSource = JMediaRecorder::VoiceDownlink; + else if (m_audioInput == QLatin1String("voice_call")) + m_audioSource = JMediaRecorder::VoiceCall; + else if (m_audioInput == QLatin1String("voice_recognition")) + m_audioSource = JMediaRecorder::VoiceRecognition; + else + m_audioSource = JMediaRecorder::DefaultAudioSource; + + emit audioInputChanged(m_audioInput); +} + +QUrl QAndroidCaptureSession::outputLocation() const +{ + return m_outputLocation; +} + +bool QAndroidCaptureSession::setOutputLocation(const QUrl &location) +{ + if (m_outputLocation == location) + return false; + + m_outputLocation = location; + + if (m_outputLocation.isEmpty()) + return true; + + if (m_outputLocation.isValid() && (m_outputLocation.isLocalFile() || m_outputLocation.isRelative())) { + emit actualLocationChanged(m_outputLocation); + return true; + } + + m_outputLocation = QUrl(); + return false; +} + +QMediaRecorder::State QAndroidCaptureSession::state() const +{ + return m_state; +} + +void QAndroidCaptureSession::setState(QMediaRecorder::State state) +{ + if (m_state == state) + return; + + switch (state) { + case QMediaRecorder::StoppedState: + stop(); + break; + case QMediaRecorder::RecordingState: + if (!start()) + return; + break; + case QMediaRecorder::PausedState: + // Not supported by Android API + qWarning("QMediaRecorder::PausedState is not supported on Android"); + return; + } + + m_state = state; + emit stateChanged(m_state); +} + +bool QAndroidCaptureSession::start() +{ + if (m_state == QMediaRecorder::RecordingState) + return false; + + setStatus(QMediaRecorder::LoadingStatus); + + if (m_mediaRecorder) { + m_mediaRecorder->release(); + delete m_mediaRecorder; + } + m_mediaRecorder = new JMediaRecorder; + connect(m_mediaRecorder, SIGNAL(error(int,int)), this, SLOT(onError(int,int))); + connect(m_mediaRecorder, SIGNAL(info(int,int)), this, SLOT(onInfo(int,int))); + + // Set audio/video sources + if (m_cameraSession) { + if (m_cameraSession->status() != QCamera::ActiveStatus) { + emit error(QMediaRecorder::ResourceError, QLatin1String("Camera must be active to record it.")); + setStatus(QMediaRecorder::UnloadedStatus); + return false; + } else { + updateViewfinder(); + m_cameraSession->camera()->unlock(); + m_mediaRecorder->setCamera(m_cameraSession->camera()); + m_mediaRecorder->setAudioSource(JMediaRecorder::Camcorder); + m_mediaRecorder->setVideoSource(JMediaRecorder::Camera); + } + } else { + m_mediaRecorder->setAudioSource(m_audioSource); + } + + // Set output format + m_mediaRecorder->setOutputFormat(m_outputFormat); + + // Set audio encoder settings + m_mediaRecorder->setAudioChannels(m_audioSettings.channelCount()); + m_mediaRecorder->setAudioEncodingBitRate(m_audioSettings.bitRate()); + m_mediaRecorder->setAudioSamplingRate(m_audioSettings.sampleRate()); + m_mediaRecorder->setAudioEncoder(m_audioEncoder); + + // Set video encoder settings + if (m_cameraSession) { + m_mediaRecorder->setVideoSize(m_videoSettings.resolution()); + m_mediaRecorder->setVideoFrameRate(qRound(m_videoSettings.frameRate())); + m_mediaRecorder->setVideoEncodingBitRate(m_videoSettings.bitRate()); + m_mediaRecorder->setVideoEncoder(m_videoEncoder); + + m_mediaRecorder->setOrientationHint(m_cameraSession->currentCameraRotation()); + } + + + // Set output file + QString filePath = m_mediaStorageLocation.generateFileName(m_outputLocation.isLocalFile() ? m_outputLocation.toLocalFile() + : m_outputLocation.toString(), + m_cameraSession ? QAndroidMediaStorageLocation::Camera + : QAndroidMediaStorageLocation::Audio, + m_cameraSession ? QLatin1String("VID_") + : QLatin1String("REC_"), + m_containerFormat); + m_outputLocation = QUrl::fromLocalFile(filePath); + emit actualLocationChanged(m_outputLocation); + + m_mediaRecorder->setOutputFile(filePath); + + if (!m_mediaRecorder->prepare()) { + emit error(QMediaRecorder::FormatError, QLatin1String("Unable to prepare the media recorder.")); + setStatus(QMediaRecorder::UnloadedStatus); + return false; + } + + setStatus(QMediaRecorder::LoadedStatus); + setStatus(QMediaRecorder::StartingStatus); + + if (!m_mediaRecorder->start()) { + emit error(QMediaRecorder::FormatError, QLatin1String("Unable to start the media recorder.")); + setStatus(QMediaRecorder::UnloadedStatus); + return false; + } + + setStatus(QMediaRecorder::RecordingStatus); + + m_elapsedTime.start(); + m_notifyTimer.start(); + updateDuration(); + + if (m_cameraSession) + m_cameraSession->setReadyForCapture(false); + + return true; +} + +void QAndroidCaptureSession::stop(bool error) +{ + if (m_state == QMediaRecorder::StoppedState) + return; + + setStatus(QMediaRecorder::FinalizingStatus); + + m_mediaRecorder->stop(); + + m_notifyTimer.stop(); + updateDuration(); + m_elapsedTime.invalidate(); + + if (m_cameraSession) { + m_cameraSession->camera()->reconnect(); + // Viewport needs to be restarted + m_cameraSession->camera()->startPreview(); + m_cameraSession->setReadyForCapture(true); + } + + m_mediaRecorder->release(); + delete m_mediaRecorder; + m_mediaRecorder = 0; + + if (!error) { + // if the media is saved into the standard media location, register it + // with the Android media scanner so it appears immediately in apps + // such as the gallery. + QString mediaPath = m_outputLocation.toLocalFile(); + QString standardLoc = m_cameraSession ? JMultimediaUtils::getDefaultMediaDirectory(JMultimediaUtils::DCIM) + : JMultimediaUtils::getDefaultMediaDirectory(JMultimediaUtils::Sounds); + if (mediaPath.startsWith(standardLoc)) + JMultimediaUtils::registerMediaFile(mediaPath); + } + + setStatus(QMediaRecorder::UnloadedStatus); +} + +void QAndroidCaptureSession::setStatus(QMediaRecorder::Status status) +{ + if (m_status == status) + return; + + m_status = status; + emit statusChanged(m_status); +} + +QMediaRecorder::Status QAndroidCaptureSession::status() const +{ + return m_status; +} + +qint64 QAndroidCaptureSession::duration() const +{ + return m_duration; +} + +void QAndroidCaptureSession::setContainerFormat(const QString &format) +{ + if (m_containerFormat == format) + return; + + m_containerFormat = format; + m_containerFormatDirty = true; +} + +void QAndroidCaptureSession::setAudioSettings(const QAudioEncoderSettings &settings) +{ + if (m_audioSettings == settings) + return; + + m_audioSettings = settings; + m_audioSettingsDirty = true; +} + +void QAndroidCaptureSession::setVideoSettings(const QVideoEncoderSettings &settings) +{ + if (!m_cameraSession || m_videoSettings == settings) + return; + + if (m_videoSettings.resolution() != settings.resolution()) + m_resolutionDirty = true; + + m_videoSettings = settings; + m_videoSettingsDirty = true; +} + +void QAndroidCaptureSession::applySettings() +{ + // container settings + if (m_containerFormatDirty) { + if (m_containerFormat.isEmpty()) { + m_containerFormat = m_defaultSettings.outputFileExtension; + m_outputFormat = m_defaultSettings.outputFormat; + } else if (m_containerFormat == QLatin1String("3gp")) { + m_outputFormat = JMediaRecorder::THREE_GPP; + } else if (!m_cameraSession && m_containerFormat == QLatin1String("amr")) { + m_outputFormat = JMediaRecorder::AMR_NB_Format; + } else if (!m_cameraSession && m_containerFormat == QLatin1String("awb")) { + m_outputFormat = JMediaRecorder::AMR_WB_Format; + } else { + m_containerFormat = QStringLiteral("mp4"); + m_outputFormat = JMediaRecorder::MPEG_4; + } + + m_containerFormatDirty = false; + } + + // audio settings + if (m_audioSettingsDirty) { + if (m_audioSettings.channelCount() <= 0) + m_audioSettings.setChannelCount(m_defaultSettings.audioChannels); + if (m_audioSettings.bitRate() <= 0) + m_audioSettings.setBitRate(m_defaultSettings.audioBitRate); + if (m_audioSettings.sampleRate() <= 0) + m_audioSettings.setSampleRate(m_defaultSettings.audioSampleRate); + + if (m_audioSettings.codec().isEmpty()) + m_audioEncoder = m_defaultSettings.audioEncoder; + else if (m_audioSettings.codec() == QLatin1String("aac")) + m_audioEncoder = JMediaRecorder::AAC; + else if (m_audioSettings.codec() == QLatin1String("amr-nb")) + m_audioEncoder = JMediaRecorder::AMR_NB_Encoder; + else if (m_audioSettings.codec() == QLatin1String("amr-wb")) + m_audioEncoder = JMediaRecorder::AMR_WB_Encoder; + else + m_audioEncoder = m_defaultSettings.audioEncoder; + + m_audioSettingsDirty = false; + } + + // video settings + if (m_cameraSession && m_videoSettingsDirty) { + if (m_videoSettings.resolution().isEmpty()) { + m_videoSettings.setResolution(m_defaultSettings.videoResolution); + m_resolutionDirty = true; + } else if (!m_supportedResolutions.contains(m_videoSettings.resolution())) { + // if the requested resolution is not supported, find the closest one + QSize reqSize = m_videoSettings.resolution(); + int reqPixelCount = reqSize.width() * reqSize.height(); + QList supportedPixelCounts; + for (int i = 0; i < m_supportedResolutions.size(); ++i) { + const QSize &s = m_supportedResolutions.at(i); + supportedPixelCounts.append(s.width() * s.height()); + } + int closestIndex = qt_findClosestValue(supportedPixelCounts, reqPixelCount); + m_videoSettings.setResolution(m_supportedResolutions.at(closestIndex)); + m_resolutionDirty = true; + } + + if (m_videoSettings.frameRate() <= 0) + m_videoSettings.setFrameRate(m_defaultSettings.videoFrameRate); + if (m_videoSettings.bitRate() <= 0) + m_videoSettings.setBitRate(m_defaultSettings.videoBitRate); + + if (m_videoSettings.codec().isEmpty()) + m_videoEncoder = m_defaultSettings.videoEncoder; + else if (m_videoSettings.codec() == QLatin1String("h263")) + m_videoEncoder = JMediaRecorder::H263; + else if (m_videoSettings.codec() == QLatin1String("h264")) + m_videoEncoder = JMediaRecorder::H264; + else if (m_videoSettings.codec() == QLatin1String("mpeg4_sp")) + m_videoEncoder = JMediaRecorder::MPEG_4_SP; + else + m_videoEncoder = m_defaultSettings.videoEncoder; + + m_videoSettingsDirty = false; + } +} + +void QAndroidCaptureSession::updateViewfinder() +{ + if (!m_resolutionDirty) + return; + + m_cameraSession->camera()->stopPreview(); + m_cameraSession->adjustViewfinderSize(m_videoSettings.resolution(), false); + m_resolutionDirty = false; +} + +void QAndroidCaptureSession::updateDuration() +{ + if (m_elapsedTime.isValid()) + m_duration = m_elapsedTime.elapsed(); + + emit durationChanged(m_duration); +} + +void QAndroidCaptureSession::onCameraOpened() +{ + m_supportedResolutions.clear(); + m_supportedFramerates.clear(); + + // get supported resolutions from predefined profiles + for (int i = 0; i < 8; ++i) { + CaptureProfile profile = getProfile(i); + if (!profile.isNull) { + if (i == 1) // QUALITY_HIGH + m_defaultSettings = profile; + + if (!m_supportedResolutions.contains(profile.videoResolution)) + m_supportedResolutions.append(profile.videoResolution); + if (!m_supportedFramerates.contains(profile.videoFrameRate)) + m_supportedFramerates.append(profile.videoFrameRate); + } + } + + qSort(m_supportedResolutions.begin(), m_supportedResolutions.end(), qt_sizeLessThan); + qSort(m_supportedFramerates.begin(), m_supportedFramerates.end()); +} + +QAndroidCaptureSession::CaptureProfile QAndroidCaptureSession::getProfile(int id) +{ + CaptureProfile profile; + bool hasProfile = QJNIObject::callStaticMethod("android/media/CamcorderProfile", + "hasProfile", + "(II)Z", + m_cameraSession->camera()->cameraId(), + id); + + if (hasProfile) { + QJNILocalRef ref = QJNIObject::callStaticObjectMethod("android/media/CamcorderProfile", + "get", + "(II)Landroid/media/CamcorderProfile;", + m_cameraSession->camera()->cameraId(), + id); + + + QJNIObject obj(ref.object()); + + profile.outputFormat = JMediaRecorder::OutputFormat(obj.getField("fileFormat")); + profile.audioEncoder = JMediaRecorder::AudioEncoder(obj.getField("audioCodec")); + profile.audioBitRate = obj.getField("audioBitRate"); + profile.audioChannels = obj.getField("audioChannels"); + profile.audioSampleRate = obj.getField("audioSampleRate"); + profile.videoEncoder = JMediaRecorder::VideoEncoder(obj.getField("videoCodec")); + profile.videoBitRate = obj.getField("videoBitRate"); + profile.videoFrameRate = obj.getField("videoFrameRate"); + profile.videoResolution = QSize(obj.getField("videoFrameWidth"), + obj.getField("videoFrameHeight")); + + if (profile.outputFormat == JMediaRecorder::MPEG_4) + profile.outputFileExtension = QStringLiteral("mp4"); + else if (profile.outputFormat == JMediaRecorder::THREE_GPP) + profile.outputFileExtension = QStringLiteral("3gp"); + else if (profile.outputFormat == JMediaRecorder::AMR_NB_Format) + profile.outputFileExtension = QStringLiteral("amr"); + else if (profile.outputFormat == JMediaRecorder::AMR_WB_Format) + profile.outputFileExtension = QStringLiteral("awb"); + + profile.isNull = false; + } + + return profile; +} + +void QAndroidCaptureSession::onCameraStatusChanged(QCamera::Status status) +{ + if (status == QCamera::StoppingStatus) + setState(QMediaRecorder::StoppedState); +} + +void QAndroidCaptureSession::onCameraCaptureModeChanged(QCamera::CaptureModes mode) +{ + if (!mode.testFlag(QCamera::CaptureVideo)) + setState(QMediaRecorder::StoppedState); +} + +void QAndroidCaptureSession::onError(int what, int extra) +{ + Q_UNUSED(what) + Q_UNUSED(extra) + stop(true); + m_state = QMediaRecorder::StoppedState; + emit stateChanged(m_state); + emit error(QMediaRecorder::ResourceError, QLatin1String("Unknown error.")); +} + +void QAndroidCaptureSession::onInfo(int what, int extra) +{ + Q_UNUSED(extra) + if (what == 800) { + // MEDIA_RECORDER_INFO_MAX_DURATION_REACHED + setState(QMediaRecorder::StoppedState); + emit error(QMediaRecorder::OutOfSpaceError, QLatin1String("Maximum duration reached.")); + } else if (what == 801) { + // MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED + setState(QMediaRecorder::StoppedState); + emit error(QMediaRecorder::OutOfSpaceError, QLatin1String("Maximum file size reached.")); + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcapturesession.h b/src/plugins/android/src/mediacapture/qandroidcapturesession.h new file mode 100644 index 0000000..6d3645c --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidcapturesession.h @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** 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 QANDROIDCAPTURESESSION_H +#define QANDROIDCAPTURESESSION_H + +#include +#include +#include +#include +#include +#include "qandroidmediastoragelocation.h" +#include "jmediarecorder.h" + +QT_BEGIN_NAMESPACE + +class QAndroidCameraSession; + +class QAndroidCaptureSession : public QObject +{ + Q_OBJECT +public: + explicit QAndroidCaptureSession(QAndroidCameraSession *cameraSession = 0); + ~QAndroidCaptureSession(); + + QList supportedResolutions() const { return m_supportedResolutions; } + QList supportedFrameRates() const { return m_supportedFramerates; } + + QString audioInput() const { return m_audioInput; } + void setAudioInput(const QString &input); + + QUrl outputLocation() const; + bool setOutputLocation(const QUrl &location); + + QMediaRecorder::State state() const; + void setState(QMediaRecorder::State state); + + QMediaRecorder::Status status() const; + + qint64 duration() const; + + QString containerFormat() const { return m_containerFormat; } + void setContainerFormat(const QString &format); + + QAudioEncoderSettings audioSettings() const { return m_audioSettings; } + void setAudioSettings(const QAudioEncoderSettings &settings); + + QVideoEncoderSettings videoSettings() const { return m_videoSettings; } + void setVideoSettings(const QVideoEncoderSettings &settings); + + void applySettings(); + +Q_SIGNALS: + void audioInputChanged(const QString& name); + void stateChanged(QMediaRecorder::State state); + void statusChanged(QMediaRecorder::Status status); + void durationChanged(qint64 position); + void actualLocationChanged(const QUrl &location); + void error(int error, const QString &errorString); + +private Q_SLOTS: + void updateDuration(); + void onCameraOpened(); + void onCameraStatusChanged(QCamera::Status); + void onCameraCaptureModeChanged(QCamera::CaptureModes mode); + + void onError(int what, int extra); + void onInfo(int what, int extra); + +private: + struct CaptureProfile { + JMediaRecorder::OutputFormat outputFormat; + QString outputFileExtension; + + JMediaRecorder::AudioEncoder audioEncoder; + int audioBitRate; + int audioChannels; + int audioSampleRate; + + JMediaRecorder::VideoEncoder videoEncoder; + int videoBitRate; + int videoFrameRate; + QSize videoResolution; + + bool isNull; + + CaptureProfile() + : outputFormat(JMediaRecorder::MPEG_4) + , outputFileExtension(QLatin1String("mp4")) + , audioEncoder(JMediaRecorder::DefaultAudioEncoder) + , audioBitRate(128000) + , audioChannels(2) + , audioSampleRate(44100) + , videoEncoder(JMediaRecorder::DefaultVideoEncoder) + , videoBitRate(1) + , videoFrameRate(-1) + , videoResolution(320, 240) + , isNull(true) + { } + }; + + CaptureProfile getProfile(int id); + + bool start(); + void stop(bool error = false); + + void setStatus(QMediaRecorder::Status status); + + void updateViewfinder(); + + JMediaRecorder *m_mediaRecorder; + QAndroidCameraSession *m_cameraSession; + + QString m_audioInput; + JMediaRecorder::AudioSource m_audioSource; + + QAndroidMediaStorageLocation m_mediaStorageLocation; + + QElapsedTimer m_elapsedTime; + QTimer m_notifyTimer; + qint64 m_duration; + + QMediaRecorder::State m_state; + QMediaRecorder::Status m_status; + QUrl m_outputLocation; + + CaptureProfile m_defaultSettings; + + QString m_containerFormat; + QAudioEncoderSettings m_audioSettings; + QVideoEncoderSettings m_videoSettings; + bool m_resolutionDirty; + bool m_containerFormatDirty; + bool m_videoSettingsDirty; + bool m_audioSettingsDirty; + JMediaRecorder::OutputFormat m_outputFormat; + JMediaRecorder::AudioEncoder m_audioEncoder; + JMediaRecorder::VideoEncoder m_videoEncoder; + + QList m_supportedResolutions; + QList m_supportedFramerates; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDCAPTURESESSION_H diff --git a/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.cpp b/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.cpp new file mode 100644 index 0000000..79e0651 --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.cpp @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** 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 "qandroidimageencodercontrol.h" + +#include "qandroidcamerasession.h" +#include "jcamera.h" + +QT_BEGIN_NAMESPACE + +QAndroidImageEncoderControl::QAndroidImageEncoderControl(QAndroidCameraSession *session) + : QImageEncoderControl() + , m_session(session) +{ + connect(m_session, SIGNAL(opened()), + this, SLOT(onCameraOpened())); +} + +QStringList QAndroidImageEncoderControl::supportedImageCodecs() const +{ + return QStringList() << QLatin1String("jpeg"); +} + +QString QAndroidImageEncoderControl::imageCodecDescription(const QString &codecName) const +{ + if (codecName == QLatin1String("jpeg")) + return tr("JPEG image"); + + return QString(); +} + +QList QAndroidImageEncoderControl::supportedResolutions(const QImageEncoderSettings &settings, bool *continuous) const +{ + Q_UNUSED(settings); + + if (continuous) + *continuous = false; + + return m_supportedResolutions; +} + +QImageEncoderSettings QAndroidImageEncoderControl::imageSettings() const +{ + return m_session->imageSettings(); +} + +void QAndroidImageEncoderControl::setImageSettings(const QImageEncoderSettings &settings) +{ + m_session->setImageSettings(settings); +} + +void QAndroidImageEncoderControl::onCameraOpened() +{ + m_supportedResolutions = m_session->camera()->getSupportedPictureSizes(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.h b/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.h new file mode 100644 index 0000000..23e397d --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** 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 QANDROIDIMAGEENCODERCONTROL_H +#define QANDROIDIMAGEENCODERCONTROL_H + +#include + +QT_BEGIN_NAMESPACE + +class QAndroidCameraSession; + +class QAndroidImageEncoderControl : public QImageEncoderControl +{ + Q_OBJECT +public: + explicit QAndroidImageEncoderControl(QAndroidCameraSession *session); + + QStringList supportedImageCodecs() const Q_DECL_OVERRIDE; + QString imageCodecDescription(const QString &codecName) const Q_DECL_OVERRIDE; + QList supportedResolutions(const QImageEncoderSettings &settings, bool *continuous = 0) const Q_DECL_OVERRIDE; + QImageEncoderSettings imageSettings() const Q_DECL_OVERRIDE; + void setImageSettings(const QImageEncoderSettings &settings) Q_DECL_OVERRIDE; + +private Q_SLOTS: + void onCameraOpened(); + +private: + QAndroidCameraSession *m_session; + + QList m_supportedResolutions; +}; + +#endif // QANDROIDIMAGEENCODERCONTROL_H diff --git a/src/plugins/android/src/mediacapture/qandroidmediacontainercontrol.cpp b/src/plugins/android/src/mediacapture/qandroidmediacontainercontrol.cpp new file mode 100644 index 0000000..33f7f23 --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidmediacontainercontrol.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** 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 "qandroidmediacontainercontrol.h" + +#include "qandroidcapturesession.h" + +QT_BEGIN_NAMESPACE + +QAndroidMediaContainerControl::QAndroidMediaContainerControl(QAndroidCaptureSession *session) + : QMediaContainerControl() + , m_session(session) +{ +} + +QStringList QAndroidMediaContainerControl::supportedContainers() const +{ + return QStringList() << QLatin1String("mp4") + << QLatin1String("3gp") + << QLatin1String("amr") + << QLatin1String("awb"); +} + +QString QAndroidMediaContainerControl::containerFormat() const +{ + return m_session->containerFormat(); +} + +void QAndroidMediaContainerControl::setContainerFormat(const QString &format) +{ + m_session->setContainerFormat(format); +} + +QString QAndroidMediaContainerControl::containerDescription(const QString &formatMimeType) const +{ + if (formatMimeType == QLatin1String("mp4")) + return tr("MPEG4 media file format"); + else if (formatMimeType == QLatin1String("3gp")) + return tr("3GPP media file format"); + else if (formatMimeType == QLatin1String("amr")) + return tr("AMR NB file format"); + else if (formatMimeType == QLatin1String("awb")) + return tr("AMR WB file format"); + + return QString(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidmediacontainercontrol.h b/src/plugins/android/src/mediacapture/qandroidmediacontainercontrol.h new file mode 100644 index 0000000..d52e836 --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidmediacontainercontrol.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** 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 QANDROIDMEDIACONTAINERCONTROL_H +#define QANDROIDMEDIACONTAINERCONTROL_H + +#include + +QT_BEGIN_NAMESPACE + +class QAndroidCaptureSession; + +class QAndroidMediaContainerControl : public QMediaContainerControl +{ + Q_OBJECT +public: + QAndroidMediaContainerControl(QAndroidCaptureSession *session); + + QStringList supportedContainers() const Q_DECL_OVERRIDE; + QString containerFormat() const Q_DECL_OVERRIDE; + void setContainerFormat(const QString &format) Q_DECL_OVERRIDE; + QString containerDescription(const QString &formatMimeType) const Q_DECL_OVERRIDE; + +private: + QAndroidCaptureSession *m_session; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDMEDIACONTAINERCONTROL_H diff --git a/src/plugins/android/src/mediacapture/qandroidmediarecordercontrol.cpp b/src/plugins/android/src/mediacapture/qandroidmediarecordercontrol.cpp new file mode 100644 index 0000000..dab9f3e --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidmediarecordercontrol.cpp @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** 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 "qandroidmediarecordercontrol.h" + +#include "qandroidcapturesession.h" + +QT_BEGIN_NAMESPACE + +QAndroidMediaRecorderControl::QAndroidMediaRecorderControl(QAndroidCaptureSession *session) + : QMediaRecorderControl() + , m_session(session) +{ + connect(m_session, SIGNAL(stateChanged(QMediaRecorder::State)), this, SIGNAL(stateChanged(QMediaRecorder::State))); + connect(m_session, SIGNAL(statusChanged(QMediaRecorder::Status)), this, SIGNAL(statusChanged(QMediaRecorder::Status))); + connect(m_session, SIGNAL(durationChanged(qint64)), this, SIGNAL(durationChanged(qint64))); + connect(m_session, SIGNAL(actualLocationChanged(QUrl)), this, SIGNAL(actualLocationChanged(QUrl))); + connect(m_session, SIGNAL(error(int,QString)), this, SIGNAL(error(int,QString))); +} + +QUrl QAndroidMediaRecorderControl::outputLocation() const +{ + return m_session->outputLocation(); +} + +bool QAndroidMediaRecorderControl::setOutputLocation(const QUrl &location) +{ + return m_session->setOutputLocation(location); +} + +QMediaRecorder::State QAndroidMediaRecorderControl::state() const +{ + return m_session->state(); +} + +QMediaRecorder::Status QAndroidMediaRecorderControl::status() const +{ + return m_session->status(); +} + +qint64 QAndroidMediaRecorderControl::duration() const +{ + return m_session->duration(); +} + +bool QAndroidMediaRecorderControl::isMuted() const +{ + // No API for this in Android + return false; +} + +qreal QAndroidMediaRecorderControl::volume() const +{ + // No API for this in Android + return 1.0; +} + +void QAndroidMediaRecorderControl::applySettings() +{ + m_session->applySettings(); +} + +void QAndroidMediaRecorderControl::setState(QMediaRecorder::State state) +{ + m_session->setState(state); +} + +void QAndroidMediaRecorderControl::setMuted(bool muted) +{ + // No API for this in Android + Q_UNUSED(muted) + qWarning("QMediaRecorder::setMuted() is not supported on Android."); +} + +void QAndroidMediaRecorderControl::setVolume(qreal volume) +{ + // No API for this in Android + Q_UNUSED(volume) + qWarning("QMediaRecorder::setVolume() is not supported on Android."); +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidmediarecordercontrol.h b/src/plugins/android/src/mediacapture/qandroidmediarecordercontrol.h new file mode 100644 index 0000000..c518f7f --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidmediarecordercontrol.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** 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 QANDROIDMEDIARECORDERCONTROL_H +#define QANDROIDMEDIARECORDERCONTROL_H + +#include + +QT_BEGIN_NAMESPACE + +class QAndroidCaptureSession; + +class QAndroidMediaRecorderControl : public QMediaRecorderControl +{ + Q_OBJECT +public: + explicit QAndroidMediaRecorderControl(QAndroidCaptureSession *session); + + QUrl outputLocation() const Q_DECL_OVERRIDE; + bool setOutputLocation(const QUrl &location) Q_DECL_OVERRIDE; + QMediaRecorder::State state() const Q_DECL_OVERRIDE; + QMediaRecorder::Status status() const Q_DECL_OVERRIDE; + qint64 duration() const Q_DECL_OVERRIDE; + bool isMuted() const Q_DECL_OVERRIDE; + qreal volume() const Q_DECL_OVERRIDE; + void applySettings() Q_DECL_OVERRIDE; + +public Q_SLOTS: + void setState(QMediaRecorder::State state) Q_DECL_OVERRIDE; + void setMuted(bool muted) Q_DECL_OVERRIDE; + void setVolume(qreal volume) Q_DECL_OVERRIDE; + +private: + QAndroidCaptureSession *m_session; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDMEDIARECORDERCONTROL_H diff --git a/src/plugins/android/src/mediacapture/qandroidmediastoragelocation.cpp b/src/plugins/android/src/mediacapture/qandroidmediastoragelocation.cpp new file mode 100644 index 0000000..ee67341 --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidmediastoragelocation.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** 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.mid(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 new file mode 100644 index 0000000..2e63f3d --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidmediastoragelocation.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** 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 +#include +#include +#include + +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 m_lastUsedIndex; + + mutable QMutex m_mutex; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDMEDIASTORAGELOCATION_H diff --git a/src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.cpp b/src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.cpp new file mode 100644 index 0000000..26dce56 --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.cpp @@ -0,0 +1,150 @@ +/**************************************************************************** +** +** 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 "qandroidvideodeviceselectorcontrol.h" + +#include "qandroidcamerasession.h" +#include "jcamera.h" +#include + +QT_BEGIN_NAMESPACE + +QList QAndroidVideoDeviceSelectorControl::m_names; +QStringList QAndroidVideoDeviceSelectorControl::m_descriptions; + +QAndroidVideoDeviceSelectorControl::QAndroidVideoDeviceSelectorControl(QAndroidCameraSession *session) + : QVideoDeviceSelectorControl(0) + , m_selectedDevice(0) + , m_cameraSession(session) +{ + if (m_names.isEmpty()) + update(); +} + +QAndroidVideoDeviceSelectorControl::~QAndroidVideoDeviceSelectorControl() +{ +} + +int QAndroidVideoDeviceSelectorControl::deviceCount() const +{ + return m_names.size(); +} + +QString QAndroidVideoDeviceSelectorControl::deviceName(int index) const +{ + return m_names.at(index); +} + +QString QAndroidVideoDeviceSelectorControl::deviceDescription(int index) const +{ + return m_descriptions.at(index); +} + +int QAndroidVideoDeviceSelectorControl::defaultDevice() const +{ + return 0; +} + +int QAndroidVideoDeviceSelectorControl::selectedDevice() const +{ + return m_selectedDevice; +} + +void QAndroidVideoDeviceSelectorControl::setSelectedDevice(int index) +{ + if (index != m_selectedDevice) { + m_selectedDevice = index; + m_cameraSession->setSelectedCamera(m_selectedDevice); + emit selectedDeviceChanged(index); + emit selectedDeviceChanged(deviceName(index)); + } +} + +void QAndroidVideoDeviceSelectorControl::update() +{ + m_names.clear(); + m_descriptions.clear(); + + QJNIObject cameraInfo("android/hardware/Camera$CameraInfo"); + int numCameras = QJNIObject::callStaticMethod("android/hardware/Camera", + "getNumberOfCameras"); + + for (int i = 0; i < numCameras; ++i) { + QJNIObject::callStaticMethod("android/hardware/Camera", + "getCameraInfo", + "(ILandroid/hardware/Camera$CameraInfo;)V", + i, cameraInfo.object()); + + JCamera::CameraFacing facing = JCamera::CameraFacing(cameraInfo.getField("facing")); + + switch (facing) { + case JCamera::CameraFacingBack: + m_names.append("back"); + m_descriptions.append(QStringLiteral("Rear-facing camera")); + break; + case JCamera::CameraFacingFront: + m_names.append("front"); + m_descriptions.append(QStringLiteral("Front-facing camera")); + break; + default: + break; + } + } +} + +QList QAndroidVideoDeviceSelectorControl::availableDevices() +{ + if (m_names.isEmpty()) + update(); + + return m_names; +} + +QString QAndroidVideoDeviceSelectorControl::availableDeviceDescription(const QByteArray &device) +{ + int i = m_names.indexOf(device); + if (i != -1) + return m_descriptions.at(i); + + return QString(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.h b/src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.h new file mode 100644 index 0000000..3ebf83a --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** 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 QANDROIDVIDEODEVICESELECTORCONTROL_H +#define QANDROIDVIDEODEVICESELECTORCONTROL_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QAndroidCameraSession; + +class QAndroidVideoDeviceSelectorControl : public QVideoDeviceSelectorControl +{ + Q_OBJECT +public: + explicit QAndroidVideoDeviceSelectorControl(QAndroidCameraSession *session); + ~QAndroidVideoDeviceSelectorControl(); + + int deviceCount() const; + + QString deviceName(int index) const; + QString deviceDescription(int index) const; + + int defaultDevice() const; + int selectedDevice() const; + + void setSelectedDevice(int index); + + static QList availableDevices(); + static QString availableDeviceDescription(const QByteArray &device); + +private: + static void update(); + + int m_selectedDevice; + static QList m_names; + static QStringList m_descriptions; + + QAndroidCameraSession *m_cameraSession; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDVIDEODEVICESELECTORCONTROL_H diff --git a/src/plugins/android/src/mediacapture/qandroidvideoencodersettingscontrol.cpp b/src/plugins/android/src/mediacapture/qandroidvideoencodersettingscontrol.cpp new file mode 100644 index 0000000..20318c8 --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidvideoencodersettingscontrol.cpp @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** 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 "qandroidvideoencodersettingscontrol.h" + +#include "qandroidcapturesession.h" + +QT_BEGIN_NAMESPACE + +QAndroidVideoEncoderSettingsControl::QAndroidVideoEncoderSettingsControl(QAndroidCaptureSession *session) + : QVideoEncoderSettingsControl() + , m_session(session) +{ +} + +QList QAndroidVideoEncoderSettingsControl::supportedResolutions(const QVideoEncoderSettings &, bool *continuous) const +{ + if (continuous) + *continuous = false; + + return m_session->supportedResolutions(); +} + +QList QAndroidVideoEncoderSettingsControl::supportedFrameRates(const QVideoEncoderSettings &, bool *continuous) const +{ + if (continuous) + *continuous = false; + + return m_session->supportedFrameRates(); +} + +QStringList QAndroidVideoEncoderSettingsControl::supportedVideoCodecs() const +{ + return QStringList() << QLatin1String("h263") + << QLatin1String("h264") + << QLatin1String("mpeg4_sp"); +} + +QString QAndroidVideoEncoderSettingsControl::videoCodecDescription(const QString &codecName) const +{ + if (codecName == QLatin1String("h263")) + return tr("H.263 compression"); + else if (codecName == QLatin1String("h264")) + return tr("H.264 compression"); + else if (codecName == QLatin1String("mpeg4_sp")) + return tr("MPEG-4 SP compression"); + + return QString(); +} + +QVideoEncoderSettings QAndroidVideoEncoderSettingsControl::videoSettings() const +{ + return m_session->videoSettings(); +} + +void QAndroidVideoEncoderSettingsControl::setVideoSettings(const QVideoEncoderSettings &settings) +{ + m_session->setVideoSettings(settings); +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidvideoencodersettingscontrol.h b/src/plugins/android/src/mediacapture/qandroidvideoencodersettingscontrol.h new file mode 100644 index 0000000..1427924 --- /dev/null +++ b/src/plugins/android/src/mediacapture/qandroidvideoencodersettingscontrol.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** 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 QANDROIDVIDEOENCODERSETTINGSCONTROL_H +#define QANDROIDVIDEOENCODERSETTINGSCONTROL_H + +#include + +QT_BEGIN_NAMESPACE + +class QAndroidCaptureSession; + +class QAndroidVideoEncoderSettingsControl : public QVideoEncoderSettingsControl +{ + Q_OBJECT +public: + explicit QAndroidVideoEncoderSettingsControl(QAndroidCaptureSession *session); + + QList supportedResolutions(const QVideoEncoderSettings &settings, bool *continuous = 0) const Q_DECL_OVERRIDE; + QList supportedFrameRates(const QVideoEncoderSettings &settings, bool *continuous = 0) const Q_DECL_OVERRIDE; + QStringList supportedVideoCodecs() const Q_DECL_OVERRIDE; + QString videoCodecDescription(const QString &codecName) const Q_DECL_OVERRIDE; + QVideoEncoderSettings videoSettings() const Q_DECL_OVERRIDE; + void setVideoSettings(const QVideoEncoderSettings &settings) Q_DECL_OVERRIDE; + +private: + QAndroidCaptureSession *m_session; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDVIDEOENCODERSETTINGSCONTROL_H diff --git a/src/plugins/android/src/mediaplayer/mediaplayer.pri b/src/plugins/android/src/mediaplayer/mediaplayer.pri new file mode 100644 index 0000000..c386d99 --- /dev/null +++ b/src/plugins/android/src/mediaplayer/mediaplayer.pri @@ -0,0 +1,11 @@ +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/qandroidmediaplayercontrol.h \ + $$PWD/qandroidmediaservice.h \ + $$PWD/qandroidmetadatareadercontrol.h + +SOURCES += \ + $$PWD/qandroidmediaplayercontrol.cpp \ + $$PWD/qandroidmediaservice.cpp \ + $$PWD/qandroidmetadatareadercontrol.cpp diff --git a/src/plugins/android/mediaplayer/qandroidmediaplayercontrol.cpp b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp similarity index 99% rename from src/plugins/android/mediaplayer/qandroidmediaplayercontrol.cpp rename to src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp index 4dc56eb..753c606 100644 --- a/src/plugins/android/mediaplayer/qandroidmediaplayercontrol.cpp +++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp @@ -81,6 +81,7 @@ QAndroidMediaPlayerControl::QAndroidMediaPlayerControl(QObject *parent) QAndroidMediaPlayerControl::~QAndroidMediaPlayerControl() { + mMediaPlayer->stop(); mMediaPlayer->release(); delete mMediaPlayer; } diff --git a/src/plugins/android/mediaplayer/qandroidmediaplayercontrol.h b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h similarity index 100% rename from src/plugins/android/mediaplayer/qandroidmediaplayercontrol.h rename to src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h diff --git a/src/plugins/android/mediaplayer/qandroidmediaservice.cpp b/src/plugins/android/src/mediaplayer/qandroidmediaservice.cpp similarity index 100% rename from src/plugins/android/mediaplayer/qandroidmediaservice.cpp rename to src/plugins/android/src/mediaplayer/qandroidmediaservice.cpp diff --git a/src/plugins/android/mediaplayer/qandroidmediaservice.h b/src/plugins/android/src/mediaplayer/qandroidmediaservice.h similarity index 100% rename from src/plugins/android/mediaplayer/qandroidmediaservice.h rename to src/plugins/android/src/mediaplayer/qandroidmediaservice.h diff --git a/src/plugins/android/mediaplayer/qandroidmetadatareadercontrol.cpp b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp similarity index 100% rename from src/plugins/android/mediaplayer/qandroidmetadatareadercontrol.cpp rename to src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp diff --git a/src/plugins/android/mediaplayer/qandroidmetadatareadercontrol.h b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h similarity index 100% rename from src/plugins/android/mediaplayer/qandroidmetadatareadercontrol.h rename to src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h diff --git a/src/plugins/android/mediaplayer/qandroidmediaserviceplugin.cpp b/src/plugins/android/src/qandroidmediaserviceplugin.cpp similarity index 66% rename from src/plugins/android/mediaplayer/qandroidmediaserviceplugin.cpp rename to src/plugins/android/src/qandroidmediaserviceplugin.cpp index 3bf7034..d7a2cd2 100644 --- a/src/plugins/android/mediaplayer/qandroidmediaserviceplugin.cpp +++ b/src/plugins/android/src/qandroidmediaserviceplugin.cpp @@ -42,9 +42,15 @@ #include "qandroidmediaserviceplugin.h" #include "qandroidmediaservice.h" +#include "qandroidcaptureservice.h" +#include "qandroidvideodeviceselectorcontrol.h" +#include "qandroidaudioinputselectorcontrol.h" #include "jmediaplayer.h" #include "jsurfacetexture.h" #include "jsurfacetextureholder.h" +#include "jcamera.h" +#include "jmultimediautils.h" +#include "jmediarecorder.h" #include QT_BEGIN_NAMESPACE @@ -59,9 +65,14 @@ QAndroidMediaServicePlugin::~QAndroidMediaServicePlugin() QMediaService *QAndroidMediaServicePlugin::create(const QString &key) { - if (key == QStringLiteral(Q_MEDIASERVICE_MEDIAPLAYER)) + if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER)) return new QAndroidMediaService; + if (key == QLatin1String(Q_MEDIASERVICE_CAMERA) + || key == QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE)) { + return new QAndroidCaptureService(key); + } + qWarning() << "Android service plugin: unsupported key:" << key; return 0; } @@ -74,11 +85,39 @@ void QAndroidMediaServicePlugin::release(QMediaService *service) QMediaServiceProviderHint::Features QAndroidMediaServicePlugin::supportedFeatures(const QByteArray &service) const { if (service == Q_MEDIASERVICE_MEDIAPLAYER) - return QMediaServiceProviderHint::VideoSurface; + return QMediaServiceProviderHint::VideoSurface; + + if (service == Q_MEDIASERVICE_CAMERA) + return QMediaServiceProviderHint::VideoSurface | QMediaServiceProviderHint::RecordingSupport; + + if (service == Q_MEDIASERVICE_AUDIOSOURCE) + return QMediaServiceProviderHint::RecordingSupport; return QMediaServiceProviderHint::Features(); } +QList QAndroidMediaServicePlugin::devices(const QByteArray &service) const +{ + if (service == Q_MEDIASERVICE_CAMERA) + return QAndroidVideoDeviceSelectorControl::availableDevices(); + + if (service == Q_MEDIASERVICE_AUDIOSOURCE) + return QAndroidAudioInputSelectorControl::availableDevices(); + + return QList(); +} + +QString QAndroidMediaServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device) +{ + if (service == Q_MEDIASERVICE_CAMERA) + return QAndroidVideoDeviceSelectorControl::availableDeviceDescription(device); + + if (service == Q_MEDIASERVICE_AUDIOSOURCE) + return QAndroidAudioInputSelectorControl::availableDeviceDescription(device); + + return QString(); +} + Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/) { @@ -97,7 +136,10 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/) if (!JMediaPlayer::initJNI(jniEnv) || !JSurfaceTexture::initJNI(jniEnv) || - !JSurfaceTextureHolder::initJNI(jniEnv)) { + !JSurfaceTextureHolder::initJNI(jniEnv) || + !JCamera::initJNI(jniEnv) || + !JMultimediaUtils::initJNI(jniEnv) || + !JMediaRecorder::initJNI(jniEnv)) { return JNI_ERR; } diff --git a/src/plugins/android/mediaplayer/qandroidmediaserviceplugin.h b/src/plugins/android/src/qandroidmediaserviceplugin.h similarity index 89% rename from src/plugins/android/mediaplayer/qandroidmediaserviceplugin.h rename to src/plugins/android/src/qandroidmediaserviceplugin.h index d004635..18b1def 100644 --- a/src/plugins/android/mediaplayer/qandroidmediaserviceplugin.h +++ b/src/plugins/android/src/qandroidmediaserviceplugin.h @@ -46,17 +46,16 @@ QT_BEGIN_NAMESPACE -class QMediaService; -class QAndroidMediaService; - class QAndroidMediaServicePlugin : public QMediaServiceProviderPlugin + , public QMediaServiceSupportedDevicesInterface , public QMediaServiceFeaturesInterface { Q_OBJECT + Q_INTERFACES(QMediaServiceSupportedDevicesInterface) Q_INTERFACES(QMediaServiceFeaturesInterface) Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" - FILE "mediaplayer.json") + FILE "android_mediaservice.json") public: QAndroidMediaServicePlugin(); @@ -64,7 +63,11 @@ public: QMediaService* create(QString const& key) Q_DECL_OVERRIDE; void release(QMediaService *service) Q_DECL_OVERRIDE; + QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const Q_DECL_OVERRIDE; + + QList devices(const QByteArray &service) const; + QString deviceDescription(const QByteArray &service, const QByteArray &device); }; QT_END_NAMESPACE diff --git a/src/plugins/android/src/src.pro b/src/plugins/android/src/src.pro new file mode 100644 index 0000000..e99fd30 --- /dev/null +++ b/src/plugins/android/src/src.pro @@ -0,0 +1,19 @@ +TARGET = qtmedia_android +QT += multimedia-private gui-private platformsupport-private network + +PLUGIN_TYPE = mediaservice +PLUGIN_CLASS_NAME = QAndroidMediaServicePlugin +load(qt_plugin) + +HEADERS += \ + qandroidmediaserviceplugin.h + +SOURCES += \ + qandroidmediaserviceplugin.cpp + +include (wrappers/wrappers.pri) +include (common/common.pri) +include (mediaplayer/mediaplayer.pri) +include (mediacapture/mediacapture.pri) + +OTHER_FILES += android_mediaservice.json diff --git a/src/plugins/android/src/wrappers/jcamera.cpp b/src/plugins/android/src/wrappers/jcamera.cpp new file mode 100644 index 0000000..9005ac6 --- /dev/null +++ b/src/plugins/android/src/wrappers/jcamera.cpp @@ -0,0 +1,712 @@ +/**************************************************************************** +** +** 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 "jcamera.h" + +#include +#include +#include +#include "qandroidmultimediautils.h" + +QT_BEGIN_NAMESPACE + +static jclass g_qtCameraClass = 0; +static QMap g_objectMap; + +static QRect areaToRect(jobject areaObj) +{ + QJNIObject area(areaObj); + QJNILocalRef rectRef = area.getObjectField("rect", "android/graphics/Rect"); + QJNIObject rect(rectRef.object()); + + return QRect(rect.getField("left"), + rect.getField("top"), + rect.callMethod("width"), + rect.callMethod("height")); +} + +static QJNILocalRef rectToArea(const QRect &rect) +{ + QJNIObject jrect("android/graphics/Rect", + "(IIII)V", + rect.left(), rect.top(), rect.right(), rect.bottom()); + + QJNIObject area("android/hardware/Camera$Area", + "(Landroid/graphics/Rect;I)V", + jrect.object(), 500); + + return QJNILocalRef(QAttachedJNIEnv()->NewLocalRef(area.object())); +} + +// native method for QtCamera.java +static void notifyAutoFocusComplete(JNIEnv* , jobject, int id, jboolean success) +{ + JCamera *obj = g_objectMap.value(id, 0); + if (obj) + Q_EMIT obj->autoFocusComplete(success); +} + +static void notifyPictureExposed(JNIEnv* , jobject, int id) +{ + JCamera *obj = g_objectMap.value(id, 0); + if (obj) + Q_EMIT obj->pictureExposed(); +} + +static void notifyPictureCaptured(JNIEnv *env, jobject, int id, jbyteArray data) +{ + JCamera *obj = g_objectMap.value(id, 0); + if (obj) { + QByteArray bytes; + int arrayLength = env->GetArrayLength(data); + bytes.resize(arrayLength); + env->GetByteArrayRegion(data, 0, arrayLength, (jbyte*)bytes.data()); + Q_EMIT obj->pictureCaptured(bytes); + } +} + +JCamera::JCamera(int cameraId, jobject cam) + : QObject() + , QJNIObject(cam) + , m_cameraId(cameraId) + , m_info(0) + , m_parameters(0) + , m_hasAPI14(false) +{ + if (isValid()) { + g_objectMap.insert(cameraId, this); + + m_info = new QJNIObject("android/hardware/Camera$CameraInfo"); + callStaticMethod("android/hardware/Camera", + "getCameraInfo", + "(ILandroid/hardware/Camera$CameraInfo;)V", + cameraId, m_info->object()); + + QJNILocalRef params = callObjectMethod("getParameters", + "()Landroid/hardware/Camera$Parameters;"); + m_parameters = new QJNIObject(params.object()); + + // Check if API 14 is available + QAttachedJNIEnv env; + jclass clazz = env->FindClass("android/hardware/Camera"); + if (env->ExceptionCheck()) { + clazz = 0; + env->ExceptionClear(); + } + if (clazz) { + // startFaceDetection() was added in API 14 + jmethodID id = env->GetMethodID(clazz, "startFaceDetection", "()V"); + if (env->ExceptionCheck()) { + id = 0; + env->ExceptionClear(); + } + m_hasAPI14 = bool(id); + } + } +} + +JCamera::~JCamera() +{ + if (isValid()) + g_objectMap.remove(m_cameraId); + delete m_parameters; + delete m_info; +} + +JCamera *JCamera::open(int cameraId) +{ + QAttachedJNIEnv env; + + QJNILocalRef camera = callStaticObjectMethod(g_qtCameraClass, + "open", + "(I)Lorg/qtproject/qt5/android/multimedia/QtCamera;", + cameraId); + + if (camera.isNull()) + return 0; + else + return new JCamera(cameraId, camera.object()); +} + +void JCamera::lock() +{ + callMethod("lock"); +} + +void JCamera::unlock() +{ + callMethod("unlock"); +} + +void JCamera::reconnect() +{ + callMethod("reconnect"); +} + +void JCamera::release() +{ + m_previewSize = QSize(); + delete m_parameters; + m_parameters = 0; + callMethod("release"); +} + +JCamera::CameraFacing JCamera::getFacing() +{ + return CameraFacing(m_info->getField("facing")); +} + +int JCamera::getNativeOrientation() +{ + return m_info->getField("orientation"); +} + +QSize JCamera::getPreferredPreviewSizeForVideo() +{ + if (!m_parameters || !m_parameters->isValid()) + return QSize(); + + QJNILocalRef sizeRef = m_parameters->callObjectMethod("getPreferredPreviewSizeForVideo", + "()Landroid/hardware/Camera$Size;"); + + QJNIObject size(sizeRef.object()); + return QSize(size.getField("width"), size.getField("height")); +} + +QList JCamera::getSupportedPreviewSizes() +{ + QList list; + + if (m_parameters && m_parameters->isValid()) { + QJNILocalRef sizeListRef = m_parameters->callObjectMethod("getSupportedPreviewSizes", + "()Ljava/util/List;"); + QJNIObject sizeList(sizeListRef.object()); + int count = sizeList.callMethod("size"); + for (int i = 0; i < count; ++i) { + QJNILocalRef sizeRef = sizeList.callObjectMethod("get", + "(I)Ljava/lang/Object;", + i); + QJNIObject size(sizeRef.object()); + list.append(QSize(size.getField("width"), size.getField("height"))); + } + + qSort(list.begin(), list.end(), qt_sizeLessThan); + } + + return list; +} + +void JCamera::setPreviewSize(const QSize &size) +{ + if (!m_parameters || !m_parameters->isValid()) + return; + + m_previewSize = size; + + m_parameters->callMethod("setPreviewSize", "(II)V", size.width(), size.height()); + applyParameters(); + + emit previewSizeChanged(); +} + +void JCamera::setPreviewTexture(jobject surfaceTexture) +{ + callMethod("setPreviewTexture", "(Landroid/graphics/SurfaceTexture;)V", surfaceTexture); +} + +bool JCamera::isZoomSupported() +{ + if (!m_parameters || !m_parameters->isValid()) + return false; + + return m_parameters->callMethod("isZoomSupported"); +} + +int JCamera::getMaxZoom() +{ + if (!m_parameters || !m_parameters->isValid()) + return 0; + + return m_parameters->callMethod("getMaxZoom"); +} + +QList JCamera::getZoomRatios() +{ + QList ratios; + + if (m_parameters && m_parameters->isValid()) { + QJNILocalRef ratioListRef = m_parameters->callObjectMethod("getZoomRatios", + "()Ljava/util/List;"); + QJNIObject ratioList(ratioListRef.object()); + int count = ratioList.callMethod("size"); + for (int i = 0; i < count; ++i) { + QJNILocalRef zoomRatioRef = ratioList.callObjectMethod("get", + "(I)Ljava/lang/Object;", + i); + + QJNIObject zoomRatio(zoomRatioRef.object()); + ratios.append(zoomRatio.callMethod("intValue")); + } + } + + return ratios; +} + +int JCamera::getZoom() +{ + if (!m_parameters || !m_parameters->isValid()) + return 0; + + return m_parameters->callMethod("getZoom"); +} + +void JCamera::setZoom(int value) +{ + if (!m_parameters || !m_parameters->isValid()) + return; + + m_parameters->callMethod("setZoom", "(I)V", value); + applyParameters(); +} + +QStringList JCamera::getSupportedFlashModes() +{ + return callStringListMethod("getSupportedFlashModes"); +} + +QString JCamera::getFlashMode() +{ + QString value; + + if (m_parameters && m_parameters->isValid()) { + QJNILocalRef flashMode = m_parameters->callObjectMethod("getFlashMode", + "()Ljava/lang/String;"); + if (!flashMode.isNull()) + value = qt_convertJString(flashMode.object()); + } + + return value; +} + +void JCamera::setFlashMode(const QString &value) +{ + if (!m_parameters || !m_parameters->isValid()) + return; + + m_parameters->callMethod("setFlashMode", + "(Ljava/lang/String;)V", + qt_toJString(value).object()); + applyParameters(); +} + +QStringList JCamera::getSupportedFocusModes() +{ + return callStringListMethod("getSupportedFocusModes"); +} + +QString JCamera::getFocusMode() +{ + QString value; + + if (m_parameters && m_parameters->isValid()) { + QJNILocalRef focusMode = m_parameters->callObjectMethod("getFocusMode", + "()Ljava/lang/String;"); + if (!focusMode.isNull()) + value = qt_convertJString(focusMode.object()); + } + + return value; +} + +void JCamera::setFocusMode(const QString &value) +{ + if (!m_parameters || !m_parameters->isValid()) + return; + + m_parameters->callMethod("setFocusMode", + "(Ljava/lang/String;)V", + qt_toJString(value).object()); + applyParameters(); +} + +int JCamera::getMaxNumFocusAreas() +{ + if (!m_hasAPI14 || !m_parameters || !m_parameters->isValid()) + return 0; + + return m_parameters->callMethod("getMaxNumFocusAreas"); +} + +QList JCamera::getFocusAreas() +{ + QList areas; + + if (m_hasAPI14 && m_parameters && m_parameters->isValid()) { + QJNILocalRef listRef = m_parameters->callObjectMethod("getFocusAreas", + "()Ljava/util/List;"); + + if (!listRef.isNull()) { + QJNIObject list(listRef.object()); + int count = list.callMethod("size"); + for (int i = 0; i < count; ++i) { + QJNILocalRef areaRef = list.callObjectMethod("get", + "(I)Ljava/lang/Object;", + i); + + areas.append(areaToRect(areaRef.object())); + } + } + } + + return areas; +} + +void JCamera::setFocusAreas(const QList &areas) +{ + if (!m_hasAPI14 || !m_parameters || !m_parameters->isValid()) + return; + + QJNILocalRef list(0); + + if (!areas.isEmpty()) { + QAttachedJNIEnv env; + QJNIObject arrayList("java/util/ArrayList", "(I)V", areas.size()); + for (int i = 0; i < areas.size(); ++i) { + arrayList.callMethod("add", + "(Ljava/lang/Object;)Z", + rectToArea(areas.at(i)).object()); + if (env->ExceptionCheck()) + env->ExceptionClear(); + } + list = env->NewLocalRef(arrayList.object()); + } + + m_parameters->callMethod("setFocusAreas", "(Ljava/util/List;)V", list.object()); + + applyParameters(); +} + +void JCamera::autoFocus() +{ + callMethod("autoFocus"); + emit autoFocusStarted(); +} + +void JCamera::cancelAutoFocus() +{ + callMethod("cancelAutoFocus"); +} + +bool JCamera::isAutoExposureLockSupported() +{ + if (!m_hasAPI14 || !m_parameters || !m_parameters->isValid()) + return false; + + return m_parameters->callMethod("isAutoExposureLockSupported"); +} + +bool JCamera::getAutoExposureLock() +{ + if (!m_hasAPI14 || !m_parameters || !m_parameters->isValid()) + return false; + + return m_parameters->callMethod("getAutoExposureLock"); +} + +void JCamera::setAutoExposureLock(bool toggle) +{ + if (!m_hasAPI14 || !m_parameters || !m_parameters->isValid()) + return; + + m_parameters->callMethod("setAutoExposureLock", "(Z)V", toggle); + applyParameters(); +} + +bool JCamera::isAutoWhiteBalanceLockSupported() +{ + if (!m_hasAPI14 || !m_parameters || !m_parameters->isValid()) + return false; + + return m_parameters->callMethod("isAutoWhiteBalanceLockSupported"); +} + +bool JCamera::getAutoWhiteBalanceLock() +{ + if (!m_hasAPI14 || !m_parameters || !m_parameters->isValid()) + return false; + + return m_parameters->callMethod("getAutoWhiteBalanceLock"); +} + +void JCamera::setAutoWhiteBalanceLock(bool toggle) +{ + if (!m_hasAPI14 || !m_parameters || !m_parameters->isValid()) + return; + + m_parameters->callMethod("setAutoWhiteBalanceLock", "(Z)V", toggle); + applyParameters(); +} + +int JCamera::getExposureCompensation() +{ + if (!m_parameters || !m_parameters->isValid()) + return 0; + + return m_parameters->callMethod("getExposureCompensation"); +} + +void JCamera::setExposureCompensation(int value) +{ + if (!m_parameters || !m_parameters->isValid()) + return; + + m_parameters->callMethod("setExposureCompensation", "(I)V", value); + applyParameters(); +} + +float JCamera::getExposureCompensationStep() +{ + if (!m_parameters || !m_parameters->isValid()) + return 0; + + return m_parameters->callMethod("getExposureCompensationStep"); +} + +int JCamera::getMinExposureCompensation() +{ + if (!m_parameters || !m_parameters->isValid()) + return 0; + + return m_parameters->callMethod("getMinExposureCompensation"); +} + +int JCamera::getMaxExposureCompensation() +{ + if (!m_parameters || !m_parameters->isValid()) + return 0; + + return m_parameters->callMethod("getMaxExposureCompensation"); +} + +QStringList JCamera::getSupportedSceneModes() +{ + return callStringListMethod("getSupportedSceneModes"); +} + +QString JCamera::getSceneMode() +{ + QString value; + + if (m_parameters && m_parameters->isValid()) { + QJNILocalRef sceneMode = m_parameters->callObjectMethod("getSceneMode", + "()Ljava/lang/String;"); + if (!sceneMode.isNull()) + value = qt_convertJString(sceneMode.object()); + } + + return value; +} + +void JCamera::setSceneMode(const QString &value) +{ + if (!m_parameters || !m_parameters->isValid()) + return; + + m_parameters->callMethod("setSceneMode", + "(Ljava/lang/String;)V", + qt_toJString(value).object()); + applyParameters(); +} + +QStringList JCamera::getSupportedWhiteBalance() +{ + return callStringListMethod("getSupportedWhiteBalance"); +} + +QString JCamera::getWhiteBalance() +{ + QString value; + + if (m_parameters && m_parameters->isValid()) { + QJNILocalRef wb = m_parameters->callObjectMethod("getWhiteBalance", + "()Ljava/lang/String;"); + if (!wb.isNull()) + value = qt_convertJString(wb.object()); + } + + return value; +} + +void JCamera::setWhiteBalance(const QString &value) +{ + if (!m_parameters || !m_parameters->isValid()) + return; + + m_parameters->callMethod("setWhiteBalance", + "(Ljava/lang/String;)V", + qt_toJString(value).object()); + applyParameters(); + + emit whiteBalanceChanged(); +} + +void JCamera::setRotation(int rotation) +{ + if (!m_parameters || !m_parameters->isValid()) + return; + + m_parameters->callMethod("setRotation", "(I)V", rotation); + applyParameters(); +} + +QList JCamera::getSupportedPictureSizes() +{ + QList list; + + if (m_parameters && m_parameters->isValid()) { + QJNILocalRef sizeListRef = m_parameters->callObjectMethod("getSupportedPictureSizes", + "()Ljava/util/List;"); + QJNIObject sizeList(sizeListRef.object()); + int count = sizeList.callMethod("size"); + for (int i = 0; i < count; ++i) { + QJNILocalRef sizeRef = sizeList.callObjectMethod("get", + "(I)Ljava/lang/Object;", + i); + QJNIObject size(sizeRef.object()); + list.append(QSize(size.getField("width"), size.getField("height"))); + } + + qSort(list.begin(), list.end(), qt_sizeLessThan); + } + + return list; +} + +void JCamera::setPictureSize(const QSize &size) +{ + if (!m_parameters || !m_parameters->isValid()) + return; + + m_parameters->callMethod("setPictureSize", "(II)V", size.width(), size.height()); + applyParameters(); +} + +void JCamera::setJpegQuality(int quality) +{ + if (!m_parameters || !m_parameters->isValid()) + return; + + m_parameters->callMethod("setJpegQuality", "(I)V", quality); + applyParameters(); +} + +void JCamera::takePicture() +{ + callMethod("takePicture"); +} + +void JCamera::startPreview() +{ + callMethod("startPreview"); +} + +void JCamera::stopPreview() +{ + callMethod("stopPreview"); +} + +void JCamera::applyParameters() +{ + callMethod("setParameters", + "(Landroid/hardware/Camera$Parameters;)V", + m_parameters->object()); +} + +QStringList JCamera::callStringListMethod(const char *methodName) +{ + QStringList stringList; + + if (m_parameters && m_parameters->isValid()) { + QJNILocalRef listRef = m_parameters->callObjectMethod(methodName, + "()Ljava/util/List;"); + + if (!listRef.isNull()) { + QJNIObject list(listRef.object()); + int count = list.callMethod("size"); + for (int i = 0; i < count; ++i) { + QJNILocalRef stringRef = list.callObjectMethod("get", + "(I)Ljava/lang/Object;", + i); + + QJNIObject string(stringRef.object()); + stringList.append(qt_convertJString(string.callObjectMethod("toString").object())); + } + } + } + + return stringList; +} + +static JNINativeMethod methods[] = { + {"notifyAutoFocusComplete", "(IZ)V", (void *)notifyAutoFocusComplete}, + {"notifyPictureExposed", "(I)V", (void *)notifyPictureExposed}, + {"notifyPictureCaptured", "(I[B)V", (void *)notifyPictureCaptured} +}; + +bool JCamera::initJNI(JNIEnv *env) +{ + jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtCamera"); + if (env->ExceptionCheck()) + env->ExceptionClear(); + + if (clazz) { + g_qtCameraClass = static_cast(env->NewGlobalRef(clazz)); + if (env->RegisterNatives(g_qtCameraClass, + methods, + sizeof(methods) / sizeof(methods[0])) < 0) { + return false; + } + } + + return true; +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/wrappers/jcamera.h b/src/plugins/android/src/wrappers/jcamera.h new file mode 100644 index 0000000..1006287 --- /dev/null +++ b/src/plugins/android/src/wrappers/jcamera.h @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** 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 JCAMERA_H +#define JCAMERA_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class JCamera : public QObject, public QJNIObject +{ + Q_OBJECT +public: + enum CameraFacing { + CameraFacingBack = 0, + CameraFacingFront = 1 + }; + + ~JCamera(); + + static JCamera *open(int cameraId); + + int cameraId() const { return m_cameraId; } + + void lock(); + void unlock(); + void reconnect(); + void release(); + + CameraFacing getFacing(); + int getNativeOrientation(); + + QSize getPreferredPreviewSizeForVideo(); + QList getSupportedPreviewSizes(); + + QSize previewSize() const { return m_previewSize; } + void setPreviewSize(const QSize &size); + void setPreviewTexture(jobject surfaceTexture); + + bool isZoomSupported(); + int getMaxZoom(); + QList getZoomRatios(); + int getZoom(); + void setZoom(int value); + + QStringList getSupportedFlashModes(); + QString getFlashMode(); + void setFlashMode(const QString &value); + + QStringList getSupportedFocusModes(); + QString getFocusMode(); + void setFocusMode(const QString &value); + + int getMaxNumFocusAreas(); + QList getFocusAreas(); + void setFocusAreas(const QList &areas); + + void autoFocus(); + void cancelAutoFocus(); + + bool isAutoExposureLockSupported(); + bool getAutoExposureLock(); + void setAutoExposureLock(bool toggle); + + bool isAutoWhiteBalanceLockSupported(); + bool getAutoWhiteBalanceLock(); + void setAutoWhiteBalanceLock(bool toggle); + + int getExposureCompensation(); + void setExposureCompensation(int value); + float getExposureCompensationStep(); + int getMinExposureCompensation(); + int getMaxExposureCompensation(); + + QStringList getSupportedSceneModes(); + QString getSceneMode(); + void setSceneMode(const QString &value); + + QStringList getSupportedWhiteBalance(); + QString getWhiteBalance(); + void setWhiteBalance(const QString &value); + + void setRotation(int rotation); + + QList getSupportedPictureSizes(); + void setPictureSize(const QSize &size); + void setJpegQuality(int quality); + + void startPreview(); + void stopPreview(); + + void takePicture(); + + static bool initJNI(JNIEnv *env); + +Q_SIGNALS: + void previewSizeChanged(); + + void autoFocusStarted(); + void autoFocusComplete(bool success); + + void whiteBalanceChanged(); + + void pictureExposed(); + void pictureCaptured(const QByteArray &data); + +private: + JCamera(int cameraId, jobject cam); + void applyParameters(); + + QStringList callStringListMethod(const char *methodName); + + int m_cameraId; + QJNIObject *m_info; + QJNIObject *m_parameters; + + QSize m_previewSize; + + bool m_hasAPI14; +}; + +QT_END_NAMESPACE + +#endif // JCAMERA_H diff --git a/src/plugins/android/wrappers/jmediametadataretriever.cpp b/src/plugins/android/src/wrappers/jmediametadataretriever.cpp similarity index 100% rename from src/plugins/android/wrappers/jmediametadataretriever.cpp rename to src/plugins/android/src/wrappers/jmediametadataretriever.cpp diff --git a/src/plugins/android/wrappers/jmediametadataretriever.h b/src/plugins/android/src/wrappers/jmediametadataretriever.h similarity index 100% rename from src/plugins/android/wrappers/jmediametadataretriever.h rename to src/plugins/android/src/wrappers/jmediametadataretriever.h diff --git a/src/plugins/android/wrappers/jmediaplayer.cpp b/src/plugins/android/src/wrappers/jmediaplayer.cpp similarity index 100% rename from src/plugins/android/wrappers/jmediaplayer.cpp rename to src/plugins/android/src/wrappers/jmediaplayer.cpp diff --git a/src/plugins/android/wrappers/jmediaplayer.h b/src/plugins/android/src/wrappers/jmediaplayer.h similarity index 100% rename from src/plugins/android/wrappers/jmediaplayer.h rename to src/plugins/android/src/wrappers/jmediaplayer.h diff --git a/src/plugins/android/src/wrappers/jmediarecorder.cpp b/src/plugins/android/src/wrappers/jmediarecorder.cpp new file mode 100644 index 0000000..b7cbe57 --- /dev/null +++ b/src/plugins/android/src/wrappers/jmediarecorder.cpp @@ -0,0 +1,242 @@ +/**************************************************************************** +** +** 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 "jmediarecorder.h" + +#include "jcamera.h" +#include +#include + +QT_BEGIN_NAMESPACE + +static jclass g_qtMediaRecorderClass = 0; +static QMap g_objectMap; + +static void notifyError(JNIEnv* , jobject, jlong id, jint what, jint extra) +{ + JMediaRecorder *obj = g_objectMap.value(id, 0); + if (obj) + emit obj->error(what, extra); +} + +static void notifyInfo(JNIEnv* , jobject, jlong id, jint what, jint extra) +{ + JMediaRecorder *obj = g_objectMap.value(id, 0); + if (obj) + emit obj->info(what, extra); +} + +JMediaRecorder::JMediaRecorder() + : QObject() + , QJNIObject(g_qtMediaRecorderClass, "(J)V", reinterpret_cast(this)) + , m_id(reinterpret_cast(this)) +{ + if (isValid()) + g_objectMap.insert(m_id, this); +} + +JMediaRecorder::~JMediaRecorder() +{ + g_objectMap.remove(m_id); +} + +void JMediaRecorder::release() +{ + callMethod("release"); +} + +bool JMediaRecorder::prepare() +{ + QAttachedJNIEnv env; + callMethod("prepare"); + if (env->ExceptionCheck()) { + env->ExceptionClear(); + return false; + } + return true; +} + +void JMediaRecorder::reset() +{ + callMethod("reset"); +} + +bool JMediaRecorder::start() +{ + QAttachedJNIEnv env; + callMethod("start"); + if (env->ExceptionCheck()) { + env->ExceptionClear(); + return false; + } + return true; +} + +void JMediaRecorder::stop() +{ + QAttachedJNIEnv env; + callMethod("stop"); + if (env->ExceptionCheck()) + env->ExceptionClear(); +} + +void JMediaRecorder::setAudioChannels(int numChannels) +{ + callMethod("setAudioChannels", "(I)V", numChannels); +} + +void JMediaRecorder::setAudioEncoder(AudioEncoder encoder) +{ + QAttachedJNIEnv env; + callMethod("setAudioEncoder", "(I)V", int(encoder)); + if (env->ExceptionCheck()) + env->ExceptionClear(); +} + +void JMediaRecorder::setAudioEncodingBitRate(int bitRate) +{ + callMethod("setAudioEncodingBitRate", "(I)V", bitRate); +} + +void JMediaRecorder::setAudioSamplingRate(int samplingRate) +{ + callMethod("setAudioSamplingRate", "(I)V", samplingRate); +} + +void JMediaRecorder::setAudioSource(AudioSource source) +{ + QAttachedJNIEnv env; + callMethod("setAudioSource", "(I)V", int(source)); + if (env->ExceptionCheck()) + env->ExceptionClear(); +} + +void JMediaRecorder::setCamera(JCamera *camera) +{ + QJNILocalRef cam = camera->getObjectField("m_camera", "Landroid/hardware/Camera;"); + callMethod("setCamera", "(Landroid/hardware/Camera;)V", cam.object()); +} + +void JMediaRecorder::setVideoEncoder(VideoEncoder encoder) +{ + QAttachedJNIEnv env; + callMethod("setVideoEncoder", "(I)V", int(encoder)); + if (env->ExceptionCheck()) + env->ExceptionClear(); +} + +void JMediaRecorder::setVideoEncodingBitRate(int bitRate) +{ + callMethod("setVideoEncodingBitRate", "(I)V", bitRate); +} + +void JMediaRecorder::setVideoFrameRate(int rate) +{ + QAttachedJNIEnv env; + callMethod("setVideoFrameRate", "(I)V", rate); + if (env->ExceptionCheck()) + env->ExceptionClear(); +} + +void JMediaRecorder::setVideoSize(const QSize &size) +{ + QAttachedJNIEnv env; + callMethod("setVideoSize", "(II)V", size.width(), size.height()); + if (env->ExceptionCheck()) + env->ExceptionClear(); +} + +void JMediaRecorder::setVideoSource(VideoSource source) +{ + QAttachedJNIEnv env; + callMethod("setVideoSource", "(I)V", int(source)); + if (env->ExceptionCheck()) + env->ExceptionClear(); +} + +void JMediaRecorder::setOrientationHint(int degrees) +{ + QAttachedJNIEnv env; + callMethod("setOrientationHint", "(I)V", degrees); + if (env->ExceptionCheck()) + env->ExceptionClear(); +} + +void JMediaRecorder::setOutputFormat(OutputFormat format) +{ + QAttachedJNIEnv env; + callMethod("setOutputFormat", "(I)V", int(format)); + if (env->ExceptionCheck()) + env->ExceptionClear(); +} + +void JMediaRecorder::setOutputFile(const QString &path) +{ + QAttachedJNIEnv env; + callMethod("setOutputFile", "(Ljava/lang/String;)V", qt_toJString(path).object()); + if (env->ExceptionCheck()) + env->ExceptionClear(); +} + +static JNINativeMethod methods[] = { + {"notifyError", "(JII)V", (void *)notifyError}, + {"notifyInfo", "(JII)V", (void *)notifyInfo} +}; + +bool JMediaRecorder::initJNI(JNIEnv *env) +{ + jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtMediaRecorder"); + if (env->ExceptionCheck()) + env->ExceptionClear(); + + if (clazz) { + g_qtMediaRecorderClass = static_cast(env->NewGlobalRef(clazz)); + if (env->RegisterNatives(g_qtMediaRecorderClass, + methods, + sizeof(methods) / sizeof(methods[0])) < 0) { + return false; + } + } + + return true; +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/wrappers/jmediarecorder.h b/src/plugins/android/src/wrappers/jmediarecorder.h new file mode 100644 index 0000000..ef26b8a --- /dev/null +++ b/src/plugins/android/src/wrappers/jmediarecorder.h @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** 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 JMEDIARECORDER_H +#define JMEDIARECORDER_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class JCamera; + +class JMediaRecorder : public QObject, public QJNIObject +{ + Q_OBJECT +public: + enum AudioEncoder { + DefaultAudioEncoder = 0, + AMR_NB_Encoder = 1, + AMR_WB_Encoder = 2, + AAC = 3 + }; + + enum AudioSource { + DefaultAudioSource = 0, + Mic = 1, + VoiceUplink = 2, + VoiceDownlink = 3, + VoiceCall = 4, + Camcorder = 5, + VoiceRecognition = 6 + }; + + enum VideoEncoder { + DefaultVideoEncoder = 0, + H263 = 1, + H264 = 2, + MPEG_4_SP = 3 + }; + + enum VideoSource { + DefaultVideoSource = 0, + Camera = 1 + }; + + enum OutputFormat { + DefaultOutputFormat = 0, + THREE_GPP = 1, + MPEG_4 = 2, + AMR_NB_Format = 3, + AMR_WB_Format = 4 + }; + + JMediaRecorder(); + ~JMediaRecorder(); + + void release(); + bool prepare(); + void reset(); + + bool start(); + void stop(); + + void setAudioChannels(int numChannels); + void setAudioEncoder(AudioEncoder encoder); + void setAudioEncodingBitRate(int bitRate); + void setAudioSamplingRate(int samplingRate); + void setAudioSource(AudioSource source); + + void setCamera(JCamera *camera); + void setVideoEncoder(VideoEncoder encoder); + void setVideoEncodingBitRate(int bitRate); + void setVideoFrameRate(int rate); + void setVideoSize(const QSize &size); + void setVideoSource(VideoSource source); + + void setOrientationHint(int degrees); + + void setOutputFormat(OutputFormat format); + void setOutputFile(const QString &path); + + static bool initJNI(JNIEnv *env); + +Q_SIGNALS: + void error(int what, int extra); + void info(int what, int extra); + +private: + jlong m_id; +}; + +QT_END_NAMESPACE + +#endif // JMEDIARECORDER_H diff --git a/src/plugins/android/src/wrappers/jmultimediautils.cpp b/src/plugins/android/src/wrappers/jmultimediautils.cpp new file mode 100644 index 0000000..6832e6b --- /dev/null +++ b/src/plugins/android/src/wrappers/jmultimediautils.cpp @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** 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 "jmultimediautils.h" + +#include + +QT_BEGIN_NAMESPACE + +static jclass g_qtMultimediaUtilsClass = 0; + +JMultimediaUtils::JMultimediaUtils() + : QObject() + , QJNIObject(g_qtMultimediaUtilsClass) +{ +} + +void JMultimediaUtils::enableOrientationListener(bool enable) +{ + callStaticMethod(g_qtMultimediaUtilsClass, "enableOrientationListener", "(Z)V", enable); +} + +int JMultimediaUtils::getDeviceOrientation() +{ + return callStaticMethod(g_qtMultimediaUtilsClass, "getDeviceOrientation"); +} + +QString JMultimediaUtils::getDefaultMediaDirectory(MediaType type) +{ + QJNILocalRef path = callStaticObjectMethod(g_qtMultimediaUtilsClass, + "getDefaultMediaDirectory", + "(I)Ljava/lang/String;", + jint(type)); + return qt_convertJString(path.object()); +} + +void JMultimediaUtils::registerMediaFile(const QString &file) +{ + callStaticMethod(g_qtMultimediaUtilsClass, + "registerMediaFile", + "(Ljava/lang/String;)V", + qt_toJString(file).object()); +} + +bool JMultimediaUtils::initJNI(JNIEnv *env) +{ + jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtMultimediaUtils"); + if (env->ExceptionCheck()) + env->ExceptionClear(); + + if (clazz) + g_qtMultimediaUtilsClass = static_cast(env->NewGlobalRef(clazz)); + + return true; +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/wrappers/jmultimediautils.h b/src/plugins/android/src/wrappers/jmultimediautils.h new file mode 100644 index 0000000..909f5c1 --- /dev/null +++ b/src/plugins/android/src/wrappers/jmultimediautils.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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 JMULTIMEDIAUTILS_H +#define JMULTIMEDIAUTILS_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class JMultimediaUtils : public QObject, public QJNIObject +{ + Q_OBJECT +public: + enum MediaType { + Music = 0, + Movies = 1, + DCIM = 2, + Sounds = 3 + }; + + JMultimediaUtils(); + + static void enableOrientationListener(bool enable); + static int getDeviceOrientation(); + static QString getDefaultMediaDirectory(MediaType type); + static void registerMediaFile(const QString &file); + + static bool initJNI(JNIEnv *env); +}; + +QT_END_NAMESPACE + +#endif // JMULTIMEDIAUTILS_H diff --git a/src/plugins/android/wrappers/jsurfacetexture.cpp b/src/plugins/android/src/wrappers/jsurfacetexture.cpp similarity index 94% rename from src/plugins/android/wrappers/jsurfacetexture.cpp rename to src/plugins/android/src/wrappers/jsurfacetexture.cpp index 34edf1b..60c85cd 100644 --- a/src/plugins/android/wrappers/jsurfacetexture.cpp +++ b/src/plugins/android/src/wrappers/jsurfacetexture.cpp @@ -45,7 +45,7 @@ QT_BEGIN_NAMESPACE static jclass g_qtSurfaceTextureClass = 0; -static QHash g_objectMap; +static QMap g_objectMap; // native method for QtSurfaceTexture.java static void notifyFrameAvailable(JNIEnv* , jobject, int id) @@ -88,11 +88,6 @@ void JSurfaceTexture::updateTexImage() callMethod("updateTexImage"); } -QJNILocalRef JSurfaceTexture::surfaceTexture() -{ - return getObjectField("surfaceTexture", "Landroid/graphics/SurfaceTexture;"); -} - static JNINativeMethod methods[] = { {"notifyFrameAvailable", "(I)V", (void *)notifyFrameAvailable} }; diff --git a/src/plugins/android/wrappers/jsurfacetexture.h b/src/plugins/android/src/wrappers/jsurfacetexture.h similarity index 98% rename from src/plugins/android/wrappers/jsurfacetexture.h rename to src/plugins/android/src/wrappers/jsurfacetexture.h index 49e0076..2a2f27a 100644 --- a/src/plugins/android/wrappers/jsurfacetexture.h +++ b/src/plugins/android/src/wrappers/jsurfacetexture.h @@ -59,8 +59,6 @@ public: QMatrix4x4 getTransformMatrix(); void updateTexImage(); - QJNILocalRef surfaceTexture(); - static bool initJNI(JNIEnv *env); Q_SIGNALS: diff --git a/src/plugins/android/wrappers/jsurfacetextureholder.cpp b/src/plugins/android/src/wrappers/jsurfacetextureholder.cpp similarity index 100% rename from src/plugins/android/wrappers/jsurfacetextureholder.cpp rename to src/plugins/android/src/wrappers/jsurfacetextureholder.cpp diff --git a/src/plugins/android/wrappers/jsurfacetextureholder.h b/src/plugins/android/src/wrappers/jsurfacetextureholder.h similarity index 100% rename from src/plugins/android/wrappers/jsurfacetextureholder.h rename to src/plugins/android/src/wrappers/jsurfacetextureholder.h diff --git a/src/plugins/android/wrappers/wrappers.pri b/src/plugins/android/src/wrappers/wrappers.pri similarity index 52% rename from src/plugins/android/wrappers/wrappers.pri rename to src/plugins/android/src/wrappers/wrappers.pri index 5b47ef5..b2faa5b 100644 --- a/src/plugins/android/wrappers/wrappers.pri +++ b/src/plugins/android/src/wrappers/wrappers.pri @@ -6,10 +6,16 @@ HEADERS += \ $$PWD/jmediaplayer.h \ $$PWD/jsurfacetexture.h \ $$PWD/jsurfacetextureholder.h \ - $$PWD/jmediametadataretriever.h + $$PWD/jmediametadataretriever.h \ + $$PWD/jcamera.h \ + $$PWD/jmultimediautils.h \ + $$PWD/jmediarecorder.h SOURCES += \ $$PWD/jmediaplayer.cpp \ $$PWD/jsurfacetexture.cpp \ $$PWD/jsurfacetextureholder.cpp \ - $$PWD/jmediametadataretriever.cpp + $$PWD/jmediametadataretriever.cpp \ + $$PWD/jcamera.cpp \ + $$PWD/jmultimediautils.cpp \ + $$PWD/jmediarecorder.cpp diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index b035663..742a4f7 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -29,7 +29,7 @@ win32 { config_wmf: SUBDIRS += wmf } -unix:!mac { +unix:!mac:!android { config_gstreamer { SUBDIRS += gstreamer } else { -- 2.7.4