diff options
author | Yoann Lopes <yoann.lopes@digia.com> | 2013-03-25 18:11:27 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-12 12:56:57 +0200 |
commit | 0a7882f6b308296ff9d44d891d3bdfed91679ce2 (patch) | |
tree | 8a1e1575158d8213773fcf4e692a160bf4b301cd /src/plugins/android/src | |
parent | 99fff6941ba6b1929c1bd8d46dc8776a6cbf11c6 (diff) |
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 <christian.stromme@digia.com>
Diffstat (limited to 'src/plugins/android/src')
75 files changed, 10110 insertions, 0 deletions
diff --git a/src/plugins/android/src/android_mediaservice.json b/src/plugins/android/src/android_mediaservice.json new file mode 100644 index 000000000..a12be52bc --- /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 000000000..f99dad507 --- /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 000000000..7ae40358f --- /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 <qlist.h> + +QT_BEGIN_NAMESPACE + +int qt_findClosestValue(const QList<int> &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 000000000..1996209b0 --- /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 <qglobal.h> +#include <qsize.h> + +QT_BEGIN_NAMESPACE + +// return the index of the closest value to <value> in <list> +// (binary search) +int qt_findClosestValue(const QList<int> &list, int value); + +bool qt_sizeLessThan(const QSize &s1, const QSize &s2); + +QT_END_NAMESPACE + +#endif // QANDROIDMULTIMEDIAUTILS_H diff --git a/src/plugins/android/src/common/qandroidvideooutput.h b/src/plugins/android/src/common/qandroidvideooutput.h new file mode 100644 index 000000000..8110b67b0 --- /dev/null +++ b/src/plugins/android/src/common/qandroidvideooutput.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 QANDROIDVIDEOOUTPUT_H +#define QANDROIDVIDEOOUTPUT_H + +#include <qglobal.h> +#include <qsize.h> +#include <jni.h> + +QT_BEGIN_NAMESPACE + +typedef void (*TextureReadyCallback)(void*); + +class QAndroidVideoOutput +{ +public: + QAndroidVideoOutput() { } + virtual ~QAndroidVideoOutput() { } + + virtual jobject surfaceHolder() = 0; + + 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 + +#endif // QANDROIDVIDEOOUTPUT_H diff --git a/src/plugins/android/src/common/qandroidvideorendercontrol.cpp b/src/plugins/android/src/common/qandroidvideorendercontrol.cpp new file mode 100644 index 000000000..c5d38aebe --- /dev/null +++ b/src/plugins/android/src/common/qandroidvideorendercontrol.cpp @@ -0,0 +1,438 @@ +/**************************************************************************** +** +** 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 "qandroidvideorendercontrol.h" + +#include <QtPlatformSupport/private/qjnihelpers_p.h> +#include "jsurfacetextureholder.h" +#include <QAbstractVideoSurface> +#include <QOpenGLContext> +#include <QOffscreenSurface> +#include <QOpenGLFramebufferObject> +#include <QVideoSurfaceFormat> +#include <QOpenGLFunctions> +#include <QOpenGLShaderProgram> +#include <qevent.h> + +QT_BEGIN_NAMESPACE + +static const GLfloat g_vertex_data[] = { + -1.f, 1.f, + 1.f, 1.f, + 1.f, -1.f, + -1.f, -1.f +}; + +static const GLfloat g_texture_data[] = { + 0.f, 0.f, + 1.f, 0.f, + 1.f, 1.f, + 0.f, 1.f +}; + +class TextureVideoBuffer : public QAbstractVideoBuffer +{ +public: + TextureVideoBuffer(GLuint textureId) + : QAbstractVideoBuffer(GLTextureHandle) + , m_textureId(textureId) + {} + + virtual ~TextureVideoBuffer() {} + + MapMode mapMode() const { return NotMapped; } + uchar *map(MapMode, int*, int*) { return 0; } + void unmap() {} + + QVariant handle() const + { + return QVariant::fromValue<unsigned int>(m_textureId); + } + +private: + GLuint m_textureId; +}; + +class ImageVideoBuffer : public QAbstractVideoBuffer +{ +public: + ImageVideoBuffer(const QImage &image) + : QAbstractVideoBuffer(NoHandle) + , m_image(image) + , m_mode(NotMapped) + { + + } + + MapMode mapMode() const { return m_mode; } + uchar *map(MapMode mode, int *, int *) + { + if (mode != NotMapped && m_mode == NotMapped) { + m_mode = mode; + return m_image.bits(); + } + + return 0; + } + + void unmap() + { + m_mode = NotMapped; + } + +private: + QImage m_image; + MapMode m_mode; +}; + +QAndroidVideoRendererControl::QAndroidVideoRendererControl(QObject *parent) + : QVideoRendererControl(parent) + , m_surface(0) + , m_offscreenSurface(0) + , m_glContext(0) + , m_fbo(0) + , m_program(0) + , m_useImage(false) + , m_androidSurface(0) + , m_surfaceTexture(0) + , m_surfaceHolder(0) + , m_externalTex(0) + , m_textureReadyCallback(0) + , m_textureReadyContext(0) +{ +} + +QAndroidVideoRendererControl::~QAndroidVideoRendererControl() +{ + if (m_glContext) + m_glContext->makeCurrent(m_offscreenSurface); + + if (m_surfaceTexture) { + m_surfaceTexture->callMethod<void>("release"); + delete m_surfaceTexture; + m_surfaceTexture = 0; + } + if (m_androidSurface) { + m_androidSurface->callMethod<void>("release"); + delete m_androidSurface; + m_androidSurface = 0; + } + if (m_surfaceHolder) { + delete m_surfaceHolder; + m_surfaceHolder = 0; + } + if (m_externalTex) + glDeleteTextures(1, &m_externalTex); + + delete m_fbo; + delete m_program; + delete m_glContext; + delete m_offscreenSurface; +} + +QAbstractVideoSurface *QAndroidVideoRendererControl::surface() const +{ + return m_surface; +} + +void QAndroidVideoRendererControl::setSurface(QAbstractVideoSurface *surface) +{ + if (surface == m_surface) + return; + + if (m_surface && m_surface->isActive()) { + m_surface->stop(); + m_surface->removeEventFilter(this); + } + + m_surface = surface; + + if (m_surface) { + m_useImage = !m_surface->supportedPixelFormats(QAbstractVideoBuffer::GLTextureHandle).contains(QVideoFrame::Format_BGR32); + m_surface->installEventFilter(this); + } +} + +bool QAndroidVideoRendererControl::isTextureReady() +{ + return QOpenGLContext::currentContext() || (m_surface && m_surface->property("GLContext").isValid()); +} + +void QAndroidVideoRendererControl::setTextureReadyCallback(TextureReadyCallback cb, void *context) +{ + m_textureReadyCallback = cb; + m_textureReadyContext = context; +} + +bool QAndroidVideoRendererControl::initSurfaceTexture() +{ + if (m_surfaceTexture) + return true; + + if (!m_surface) + return false; + + QOpenGLContext *currContext = QOpenGLContext::currentContext(); + + // If we don't have a GL context in the current thread, create one and share it + // with the render thread GL context + if (!currContext && !m_glContext) { + QOpenGLContext *shareContext = qobject_cast<QOpenGLContext*>(m_surface->property("GLContext").value<QObject*>()); + if (!shareContext) + return false; + + m_offscreenSurface = new QOffscreenSurface; + QSurfaceFormat format; + format.setSwapBehavior(QSurfaceFormat::SingleBuffer); + m_offscreenSurface->setFormat(format); + m_offscreenSurface->create(); + + m_glContext = new QOpenGLContext; + m_glContext->setFormat(m_offscreenSurface->requestedFormat()); + + if (shareContext) + m_glContext->setShareContext(shareContext); + + if (!m_glContext->create()) { + delete m_glContext; + m_glContext = 0; + delete m_offscreenSurface; + m_offscreenSurface = 0; + return false; + } + + // if sharing contexts is not supported, fallback to image rendering and send the bits + // to the video surface + if (!m_glContext->shareContext()) + m_useImage = true; + } + + if (m_glContext) + m_glContext->makeCurrent(m_offscreenSurface); + + glGenTextures(1, &m_externalTex); + m_surfaceTexture = new JSurfaceTexture(m_externalTex); + + if (m_surfaceTexture->isValid()) { + connect(m_surfaceTexture, SIGNAL(frameAvailable()), this, SLOT(onFrameAvailable())); + } else { + delete m_surfaceTexture; + m_surfaceTexture = 0; + glDeleteTextures(1, &m_externalTex); + } + + return m_surfaceTexture != 0; +} + +jobject QAndroidVideoRendererControl::surfaceHolder() +{ + if (!initSurfaceTexture()) + return 0; + + if (!m_surfaceHolder) { + m_androidSurface = new QJNIObject("android/view/Surface", + "(Landroid/graphics/SurfaceTexture;)V", + m_surfaceTexture->object()); + + m_surfaceHolder = new JSurfaceTextureHolder(m_androidSurface->object()); + } + + 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; + m_fbo = 0; +} + +void QAndroidVideoRendererControl::stop() +{ + if (m_surface && m_surface->isActive()) + m_surface->stop(); + m_nativeSize = QSize(); +} + +QImage QAndroidVideoRendererControl::toImage() +{ + if (!m_fbo) + return QImage(); + + return m_fbo->toImage().mirrored(); +} + +void QAndroidVideoRendererControl::onFrameAvailable() +{ + if (m_glContext) + m_glContext->makeCurrent(m_offscreenSurface); + + m_surfaceTexture->updateTexImage(); + + if (!m_nativeSize.isValid()) + return; + + renderFrameToFbo(); + + QAbstractVideoBuffer *buffer = 0; + QVideoFrame frame; + + if (m_useImage) { + buffer = new ImageVideoBuffer(m_fbo->toImage().mirrored()); + frame = QVideoFrame(buffer, m_nativeSize, QVideoFrame::Format_RGB32); + } else { + buffer = new TextureVideoBuffer(m_fbo->texture()); + frame = QVideoFrame(buffer, m_nativeSize, QVideoFrame::Format_BGR32); + } + + if (m_surface && frame.isValid()) { + if (m_surface->isActive() && (m_surface->surfaceFormat().pixelFormat() != frame.pixelFormat() + || m_surface->nativeResolution() != frame.size())) { + m_surface->stop(); + } + + if (!m_surface->isActive()) { + QVideoSurfaceFormat format(frame.size(), frame.pixelFormat(), + m_useImage ? QAbstractVideoBuffer::NoHandle + : QAbstractVideoBuffer::GLTextureHandle); + + m_surface->start(format); + } + + if (m_surface->isActive()) + m_surface->present(frame); + } +} + +void QAndroidVideoRendererControl::renderFrameToFbo() +{ + createGLResources(); + + m_fbo->bind(); + + glViewport(0, 0, m_nativeSize.width(), m_nativeSize.height()); + + m_program->bind(); + m_program->enableAttributeArray(0); + m_program->enableAttributeArray(1); + m_program->setUniformValue("frameTexture", GLuint(0)); + m_program->setUniformValue("texMatrix", m_surfaceTexture->getTransformMatrix()); + + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, g_vertex_data); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, g_texture_data); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + m_program->disableAttributeArray(0); + m_program->disableAttributeArray(1); + m_program->release(); + + glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0); + m_fbo->release(); + + glFinish(); +} + +void QAndroidVideoRendererControl::createGLResources() +{ + if (!m_fbo) + m_fbo = new QOpenGLFramebufferObject(m_nativeSize); + + if (!m_program) { + m_program = new QOpenGLShaderProgram; + + QOpenGLShader *vertexShader = new QOpenGLShader(QOpenGLShader::Vertex, m_program); + vertexShader->compileSourceCode("attribute highp vec4 vertexCoordsArray; \n" \ + "attribute highp vec2 textureCoordArray; \n" \ + "uniform highp mat4 texMatrix; \n" \ + "varying highp vec2 textureCoords; \n" \ + "void main(void) \n" \ + "{ \n" \ + " gl_Position = vertexCoordsArray; \n" \ + " textureCoords = (texMatrix * vec4(textureCoordArray, 0.0, 1.0)).xy; \n" \ + "}\n"); + m_program->addShader(vertexShader); + + QOpenGLShader *fragmentShader = new QOpenGLShader(QOpenGLShader::Fragment, m_program); + fragmentShader->compileSourceCode("#extension GL_OES_EGL_image_external : require \n" \ + "varying highp vec2 textureCoords; \n" \ + "uniform samplerExternalOES frameTexture; \n" \ + "void main() \n" \ + "{ \n" \ + " gl_FragColor = texture2D(frameTexture, textureCoords); \n" \ + "}\n"); + m_program->addShader(fragmentShader); + + m_program->bindAttributeLocation("vertexCoordsArray", 0); + m_program->bindAttributeLocation("textureCoordArray", 1); + m_program->link(); + } +} + +bool QAndroidVideoRendererControl::eventFilter(QObject *, QEvent *e) +{ + if (e->type() == QEvent::DynamicPropertyChange) { + QDynamicPropertyChangeEvent *event = static_cast<QDynamicPropertyChangeEvent*>(e); + if (event->propertyName() == "GLContext" && m_textureReadyCallback) { + m_textureReadyCallback(m_textureReadyContext); + m_textureReadyCallback = 0; + m_textureReadyContext = 0; + } + } + + return false; +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/common/qandroidvideorendercontrol.h b/src/plugins/android/src/common/qandroidvideorendercontrol.h new file mode 100644 index 000000000..d8078f075 --- /dev/null +++ b/src/plugins/android/src/common/qandroidvideorendercontrol.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** 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 QANDROIDVIDEORENDERCONTROL_H +#define QANDROIDVIDEORENDERCONTROL_H + +#include <qvideorenderercontrol.h> +#include "qandroidvideooutput.h" +#include "jsurfacetexture.h" + +QT_BEGIN_NAMESPACE + +class QOpenGLContext; +class QOffscreenSurface; +class QOpenGLFramebufferObject; +class QOpenGLShaderProgram; +class JSurfaceTextureHolder; + +class QAndroidVideoRendererControl : public QVideoRendererControl, public QAndroidVideoOutput +{ + Q_OBJECT +public: + explicit QAndroidVideoRendererControl(QObject *parent = 0); + ~QAndroidVideoRendererControl() Q_DECL_OVERRIDE; + + QAbstractVideoSurface *surface() const Q_DECL_OVERRIDE; + void setSurface(QAbstractVideoSurface *surface) Q_DECL_OVERRIDE; + + 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; + +private Q_SLOTS: + void onFrameAvailable(); + +private: + bool initSurfaceTexture(); + void renderFrameToFbo(); + void createGLResources(); + + QAbstractVideoSurface *m_surface; + QOffscreenSurface *m_offscreenSurface; + QOpenGLContext *m_glContext; + QOpenGLFramebufferObject *m_fbo; + QOpenGLShaderProgram *m_program; + bool m_useImage; + QSize m_nativeSize; + + QJNIObject *m_androidSurface; + JSurfaceTexture *m_surfaceTexture; + JSurfaceTextureHolder *m_surfaceHolder; + uint m_externalTex; + + TextureReadyCallback m_textureReadyCallback; + void *m_textureReadyContext; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDVIDEORENDERCONTROL_H diff --git a/src/plugins/android/src/mediacapture/mediacapture.pri b/src/plugins/android/src/mediacapture/mediacapture.pri new file mode 100644 index 000000000..d994bebfd --- /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 000000000..8015ec38c --- /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<int> QAndroidAudioEncoderSettingsControl::supportedSampleRates(const QAudioEncoderSettings &settings, bool *continuous) const +{ + if (continuous) + *continuous = false; + + if (settings.isNull() || settings.codec().isNull() || settings.codec() == QLatin1String("aac")) { + return QList<int>() << 8000 << 11025 << 12000 << 16000 << 22050 + << 24000 << 32000 << 44100 << 48000 << 96000; + } else if (settings.codec() == QLatin1String("amr-nb")) { + return QList<int>() << 8000; + } else if (settings.codec() == QLatin1String("amr-wb")) { + return QList<int>() << 16000; + } + + return QList<int>(); +} + +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 000000000..11a35fe6a --- /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 <qaudioencodersettingscontrol.h> + +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<int> 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 000000000..4032b2d0b --- /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<QString> QAndroidAudioInputSelectorControl::availableInputs() const +{ + return QList<QString>() << 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<QByteArray> QAndroidAudioInputSelectorControl::availableDevices() +{ + return QList<QByteArray>() << "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 000000000..3dfa7c712 --- /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 <qaudioinputselectorcontrol.h> + +QT_BEGIN_NAMESPACE + +class QAndroidCaptureSession; + +class QAndroidAudioInputSelectorControl : public QAudioInputSelectorControl +{ + Q_OBJECT +public: + explicit QAndroidAudioInputSelectorControl(QAndroidCaptureSession *session); + + QList<QString> availableInputs() const; + QString inputDescription(const QString& name) const; + QString defaultInput() const; + + QString activeInput() const; + void setActiveInput(const QString& name); + + static QList<QByteArray> 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 000000000..dc7f20ee7 --- /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<QVideoFrame::PixelFormat> QAndroidCameraCaptureBufferFormatControl::supportedBufferFormats() const +{ + return (QList<QVideoFrame::PixelFormat>() << 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 000000000..cf8bd4933 --- /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 <qcameracapturebufferformatcontrol.h> + +QT_BEGIN_NAMESPACE + +class QAndroidCameraCaptureBufferFormatControl : public QCameraCaptureBufferFormatControl +{ + Q_OBJECT +public: + QAndroidCameraCaptureBufferFormatControl(); + + QList<QVideoFrame::PixelFormat> 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 000000000..870a4240d --- /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 000000000..46ff96bca --- /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 <qcameracapturedestinationcontrol.h> + +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 000000000..f91ae1e89 --- /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 000000000..f5070c13e --- /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 <qcameracontrol.h> + +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 000000000..03bbadb93 --- /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<QCameraExposure::ExposureMode>(); + 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 000000000..d07fea539 --- /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 <qcameraexposurecontrol.h> + +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 000000000..253b1baa5 --- /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 000000000..35ed71894 --- /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 <qcameraflashcontrol.h> + +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<QCameraExposure::FlashModes> 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 000000000..cb785fe1e --- /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<QRect> 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 000000000..4311e78ba --- /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 <qcamerafocuscontrol.h> + +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<QCameraFocus::FocusModes> m_supportedFocusModes; + bool m_continuousPictureFocusSupported; + bool m_continuousVideoFocusSupported; + + QList<QCameraFocus::FocusPointMode> 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 000000000..3c04d292f --- /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 000000000..f69913b14 --- /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 <qcameraimagecapturecontrol.h> + +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 000000000..ec5a3bcbf --- /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<QCameraImageProcessing::WhiteBalanceMode>()); +} + +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<QCameraImageProcessing::WhiteBalanceMode>(), 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 000000000..3ef3c3144 --- /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 <qcameraimageprocessingcontrol.h> + +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<QCameraImageProcessing::WhiteBalanceMode, QString> 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 000000000..d9f20ec04 --- /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 <qtimer.h> + +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 000000000..d49821bff --- /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 <qcameralockscontrol.h> + +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 000000000..761b716d1 --- /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 <QtConcurrent/qtconcurrentrun.h> +#include <qfile.h> +#include <qguiapplication.h> +#include <qdebug.h> + +QT_BEGIN_NAMESPACE + +static void textureReadyCallback(void *context) +{ + if (context) + reinterpret_cast<QAndroidCameraSession *>(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<QSize> 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<qreal>(size.width())/static_cast<qreal>(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<QSize> 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<int> 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 000000000..f1cf44eec --- /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 <qcamera.h> +#include <qmediaencodersettings.h> +#include <QCameraImageCapture> +#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 000000000..b7030e56b --- /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 <qmath.h> + +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 000000000..b102c5dda --- /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 <qcamerazoomcontrol.h> +#include <qcamera.h> + +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<int> 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 000000000..3468c64e5 --- /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 <qmediaserviceproviderplugin.h> + +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 000000000..71aaf2d64 --- /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 <qmediaservice.h> +#include <qmediacontrol.h> + +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 000000000..1927aeb8e --- /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 <QtPlatformSupport/private/qjnihelpers_p.h> + +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<int> 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<jboolean>("android/media/CamcorderProfile", + "hasProfile", + "(II)Z", + m_cameraSession->camera()->cameraId(), + id); + + if (hasProfile) { + QJNILocalRef<jobject> ref = QJNIObject::callStaticObjectMethod<jobject>("android/media/CamcorderProfile", + "get", + "(II)Landroid/media/CamcorderProfile;", + m_cameraSession->camera()->cameraId(), + id); + + + QJNIObject obj(ref.object()); + + profile.outputFormat = JMediaRecorder::OutputFormat(obj.getField<jint>("fileFormat")); + profile.audioEncoder = JMediaRecorder::AudioEncoder(obj.getField<jint>("audioCodec")); + profile.audioBitRate = obj.getField<jint>("audioBitRate"); + profile.audioChannels = obj.getField<jint>("audioChannels"); + profile.audioSampleRate = obj.getField<jint>("audioSampleRate"); + profile.videoEncoder = JMediaRecorder::VideoEncoder(obj.getField<jint>("videoCodec")); + profile.videoBitRate = obj.getField<jint>("videoBitRate"); + profile.videoFrameRate = obj.getField<jint>("videoFrameRate"); + profile.videoResolution = QSize(obj.getField<jint>("videoFrameWidth"), + obj.getField<jint>("videoFrameHeight")); + + if (profile.outputFormat == JMediaRecorder::MPEG_4) + 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 000000000..6d3645c13 --- /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 <qobject.h> +#include <qmediarecorder.h> +#include <qurl.h> +#include <qelapsedtimer.h> +#include <qtimer.h> +#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<QSize> supportedResolutions() const { return m_supportedResolutions; } + QList<qreal> 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<QSize> m_supportedResolutions; + QList<qreal> 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 000000000..79e0651a3 --- /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<QSize> 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 000000000..23e397d4d --- /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 <qimageencodercontrol.h> + +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<QSize> 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<QSize> 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 000000000..33f7f2351 --- /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 000000000..d52e8365f --- /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 <qmediacontainercontrol.h> + +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 000000000..dab9f3e30 --- /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 000000000..c518f7f70 --- /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 <qmediarecordercontrol.h> + +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 000000000..ee6734158 --- /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 000000000..2e63f3df5 --- /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 <QCamera> +#include <QDir> +#include <QHash> +#include <QMutex> + +QT_BEGIN_NAMESPACE + +class QAndroidMediaStorageLocation +{ +public: + enum CaptureSource { + Camera, + Audio + }; + + QAndroidMediaStorageLocation(); + + QDir defaultDir(CaptureSource source) const; + + QString generateFileName(const QString &requestedName, CaptureSource source, const QString &prefix, const QString &extension) const; + QString generateFileName(const QString &prefix, const QDir &dir, const QString &extension) const; + +private: + mutable QHash<QString, qint64> m_lastUsedIndex; + + mutable QMutex m_mutex; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDMEDIASTORAGELOCATION_H diff --git a/src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.cpp b/src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.cpp new file mode 100644 index 000000000..26dce565e --- /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 <QtPlatformSupport/private/qjnihelpers_p.h> + +QT_BEGIN_NAMESPACE + +QList<QByteArray> 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<jint>("android/hardware/Camera", + "getNumberOfCameras"); + + for (int i = 0; i < numCameras; ++i) { + QJNIObject::callStaticMethod<void>("android/hardware/Camera", + "getCameraInfo", + "(ILandroid/hardware/Camera$CameraInfo;)V", + i, cameraInfo.object()); + + JCamera::CameraFacing facing = JCamera::CameraFacing(cameraInfo.getField<jint>("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<QByteArray> 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 000000000..3ebf83ab2 --- /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 <qvideodeviceselectorcontrol.h> +#include <QtCore/qstringlist.h> + +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<QByteArray> availableDevices(); + static QString availableDeviceDescription(const QByteArray &device); + +private: + static void update(); + + int m_selectedDevice; + static QList<QByteArray> 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 000000000..20318c8bb --- /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<QSize> QAndroidVideoEncoderSettingsControl::supportedResolutions(const QVideoEncoderSettings &, bool *continuous) const +{ + if (continuous) + *continuous = false; + + return m_session->supportedResolutions(); +} + +QList<qreal> 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 000000000..1427924c0 --- /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 <qvideoencodersettingscontrol.h> + +QT_BEGIN_NAMESPACE + +class QAndroidCaptureSession; + +class QAndroidVideoEncoderSettingsControl : public QVideoEncoderSettingsControl +{ + Q_OBJECT +public: + explicit QAndroidVideoEncoderSettingsControl(QAndroidCaptureSession *session); + + QList<QSize> supportedResolutions(const QVideoEncoderSettings &settings, bool *continuous = 0) const Q_DECL_OVERRIDE; + QList<qreal> 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 000000000..c386d996b --- /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/src/mediaplayer/qandroidmediaplayercontrol.cpp b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp new file mode 100644 index 000000000..753c60662 --- /dev/null +++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp @@ -0,0 +1,535 @@ +/**************************************************************************** +** +** 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 "qandroidmediaplayercontrol.h" +#include "jmediaplayer.h" +#include "qandroidvideooutput.h" + +QT_BEGIN_NAMESPACE + +static void textureReadyCallback(void *context) +{ + if (context) + reinterpret_cast<QAndroidMediaPlayerControl *>(context)->onSurfaceTextureReady(); +} + +QAndroidMediaPlayerControl::QAndroidMediaPlayerControl(QObject *parent) + : QMediaPlayerControl(parent), + mMediaPlayer(new JMediaPlayer), + mCurrentState(QMediaPlayer::StoppedState), + mCurrentMediaStatus(QMediaPlayer::NoMedia), + mMediaStream(0), + mVideoOutput(0), + mSeekable(true), + mBufferPercent(-1), + mAudioAvailable(false), + mVideoAvailable(false), + mBuffering(false), + mMediaPlayerReady(false), + mPendingPosition(-1), + mPendingSetMedia(false) +{ + connect(mMediaPlayer, SIGNAL(bufferingUpdate(qint32)), + this, SLOT(onBufferChanged(qint32))); + connect(mMediaPlayer, SIGNAL(info(qint32, qint32)), + this, SLOT(onInfo(qint32, qint32))); + connect(mMediaPlayer, SIGNAL(error(qint32, qint32)), + this, SLOT(onError(qint32, qint32))); + connect(mMediaPlayer, SIGNAL(mediaPlayerInfo(qint32, qint32)), + this, SLOT(onMediaPlayerInfo(qint32, qint32))); + connect(mMediaPlayer, SIGNAL(videoSizeChanged(qint32,qint32)), + this, SLOT(onVideoSizeChanged(qint32,qint32))); +} + +QAndroidMediaPlayerControl::~QAndroidMediaPlayerControl() +{ + mMediaPlayer->stop(); + mMediaPlayer->release(); + delete mMediaPlayer; +} + +QMediaPlayer::State QAndroidMediaPlayerControl::state() const +{ + return mCurrentState; +} + +QMediaPlayer::MediaStatus QAndroidMediaPlayerControl::mediaStatus() const +{ + return mCurrentMediaStatus; +} + +qint64 QAndroidMediaPlayerControl::duration() const +{ + return (mCurrentMediaStatus == QMediaPlayer::InvalidMedia + || mCurrentMediaStatus == QMediaPlayer::NoMedia + || !mMediaPlayerReady) ? 0 + : mMediaPlayer->getDuration(); +} + +qint64 QAndroidMediaPlayerControl::position() const +{ + if (!mMediaPlayerReady) + return mPendingPosition < 0 ? 0 : mPendingPosition; + + return mMediaPlayer->getCurrentPosition(); +} + +void QAndroidMediaPlayerControl::setPosition(qint64 position) +{ + if (!mSeekable) + return; + + const int seekPosition = (position > INT_MAX) ? INT_MAX : position; + + if (!mMediaPlayerReady) { + mPendingPosition = seekPosition; + Q_EMIT positionChanged(seekPosition); + return; + } + + mMediaPlayer->seekTo(seekPosition); + mPendingPosition = -1; +} + +int QAndroidMediaPlayerControl::volume() const +{ + return mMediaPlayer->volume(); +} + +void QAndroidMediaPlayerControl::setVolume(int volume) +{ + mMediaPlayer->setVolume(volume); + Q_EMIT volumeChanged(volume); +} + +bool QAndroidMediaPlayerControl::isMuted() const +{ + return mMediaPlayer->isMuted(); +} + +void QAndroidMediaPlayerControl::setMuted(bool muted) +{ + mMediaPlayer->setMuted(muted); + Q_EMIT mutedChanged(muted); +} + +int QAndroidMediaPlayerControl::bufferStatus() const +{ + return mBufferPercent; +} + +bool QAndroidMediaPlayerControl::isAudioAvailable() const +{ + return mAudioAvailable; +} + +bool QAndroidMediaPlayerControl::isVideoAvailable() const +{ + return mVideoAvailable; +} + +bool QAndroidMediaPlayerControl::isSeekable() const +{ + return mSeekable; +} + +QMediaTimeRange QAndroidMediaPlayerControl::availablePlaybackRanges() const +{ + return mAvailablePlaybackRange; +} + +void QAndroidMediaPlayerControl::updateAvailablePlaybackRanges() +{ + if (mBuffering) { + const qint64 pos = position(); + const qint64 end = (duration() / 100) * mBufferPercent; + mAvailablePlaybackRange.addInterval(pos, end); + } else if (mSeekable) { + mAvailablePlaybackRange = QMediaTimeRange(0, duration()); + } else { + mAvailablePlaybackRange = QMediaTimeRange(); + } + + Q_EMIT availablePlaybackRangesChanged(mAvailablePlaybackRange); +} + +qreal QAndroidMediaPlayerControl::playbackRate() const +{ + return 1.0f; +} + +void QAndroidMediaPlayerControl::setPlaybackRate(qreal rate) +{ + Q_UNUSED(rate); +} + +QMediaContent QAndroidMediaPlayerControl::media() const +{ + return mMediaContent; +} + +const QIODevice *QAndroidMediaPlayerControl::mediaStream() const +{ + return mMediaStream; +} + +void QAndroidMediaPlayerControl::setMedia(const QMediaContent &mediaContent, + QIODevice *stream) +{ + mMediaContent = mediaContent; + mMediaStream = stream; + + if (mVideoOutput && !mMediaPlayer->display()) { + // if a video output is set but the video texture is not ready, delay loading the media + // since it can cause problems on some hardware + mPendingSetMedia = true; + return; + } + + const QString uri = mediaContent.canonicalUrl().toString(); + + if (!uri.isEmpty()) + mMediaPlayer->setDataSource(uri); + else + setMediaStatus(QMediaPlayer::NoMedia); + + Q_EMIT mediaChanged(mMediaContent); + + resetBufferingProgress(); + + // reset some properties + setAudioAvailable(false); + setVideoAvailable(false); + setSeekable(true); +} + +void QAndroidMediaPlayerControl::setVideoOutput(QAndroidVideoOutput *videoOutput) +{ + if (mVideoOutput) + mVideoOutput->stop(); + + mVideoOutput = videoOutput; + + if (mVideoOutput && !mMediaPlayer->display()) { + if (mVideoOutput->isTextureReady()) + mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder()); + else + mVideoOutput->setTextureReadyCallback(textureReadyCallback, this); + } +} + +void QAndroidMediaPlayerControl::play() +{ + if (!mMediaPlayerReady) { + mPendingState = QMediaPlayer::PlayingState; + if (mCurrentState == QMediaPlayer::StoppedState + && !mMediaContent.isNull() + && mCurrentMediaStatus != QMediaPlayer::LoadingMedia + && !mPendingSetMedia) { + setMedia(mMediaContent, 0); + } + return; + } + + mMediaPlayer->play(); + setState(QMediaPlayer::PlayingState); +} + +void QAndroidMediaPlayerControl::pause() +{ + if (!mMediaPlayerReady) { + mPendingState = QMediaPlayer::PausedState; + return; + } + + mMediaPlayer->pause(); + setState(QMediaPlayer::PausedState); +} + +void QAndroidMediaPlayerControl::stop() +{ + mMediaPlayer->stop(); + setState(QMediaPlayer::StoppedState); +} + +void QAndroidMediaPlayerControl::onInfo(qint32 what, qint32 extra) +{ + Q_UNUSED(extra); + switch (what) { + case JMediaPlayer::MEDIA_INFO_UNKNOWN: + break; + case JMediaPlayer::MEDIA_INFO_VIDEO_TRACK_LAGGING: + // IGNORE + break; + case JMediaPlayer::MEDIA_INFO_VIDEO_RENDERING_START: + break; + case JMediaPlayer::MEDIA_INFO_BUFFERING_START: + mPendingState = mCurrentState; + setState(QMediaPlayer::PausedState); + setMediaStatus(QMediaPlayer::StalledMedia); + break; + case JMediaPlayer::MEDIA_INFO_BUFFERING_END: + setMediaStatus(mBufferPercent == 100 ? QMediaPlayer::BufferedMedia : QMediaPlayer::BufferingMedia); + flushPendingStates(); + break; + case JMediaPlayer::MEDIA_INFO_BAD_INTERLEAVING: + break; + case JMediaPlayer::MEDIA_INFO_NOT_SEEKABLE: + setSeekable(false); + break; + case JMediaPlayer::MEDIA_INFO_METADATA_UPDATE: + Q_EMIT metaDataUpdated(); + break; + } +} + +void QAndroidMediaPlayerControl::onMediaPlayerInfo(qint32 what, qint32 extra) +{ + switch (what) { + case JMediaPlayer::MEDIA_PLAYER_INVALID_STATE: + setError(what, QStringLiteral("Error: Invalid state")); + break; + case JMediaPlayer::MEDIA_PLAYER_PREPARING: + setMediaStatus(QMediaPlayer::LoadingMedia); + setState(QMediaPlayer::StoppedState); + break; + case JMediaPlayer::MEDIA_PLAYER_READY: + setMediaStatus(QMediaPlayer::LoadedMedia); + if (mBuffering) { + setMediaStatus(mBufferPercent == 100 ? QMediaPlayer::BufferedMedia + : QMediaPlayer::BufferingMedia); + } else { + onBufferChanged(100); + } + setAudioAvailable(true); + mMediaPlayerReady = true; + flushPendingStates(); + break; + case JMediaPlayer::MEDIA_PLAYER_DURATION: + Q_EMIT durationChanged(extra); + break; + case JMediaPlayer::MEDIA_PLAYER_PROGRESS: + Q_EMIT positionChanged(extra); + break; + case JMediaPlayer::MEDIA_PLAYER_FINISHED: + setState(QMediaPlayer::StoppedState); + setMediaStatus(QMediaPlayer::EndOfMedia); + break; + } +} + +void QAndroidMediaPlayerControl::onError(qint32 what, qint32 extra) +{ + QString errorString; + QMediaPlayer::Error error = QMediaPlayer::ResourceError; + + switch (what) { + case JMediaPlayer::MEDIA_ERROR_UNKNOWN: + errorString = QLatin1String("Error:"); + break; + case JMediaPlayer::MEDIA_ERROR_SERVER_DIED: + errorString = QLatin1String("Error: Server died"); + error = QMediaPlayer::ServiceMissingError; + break; + } + + switch (extra) { + case JMediaPlayer::MEDIA_ERROR_IO: // Network OR file error + errorString += QLatin1String(" (I/O operation failed)"); + error = QMediaPlayer::NetworkError; + setMediaStatus(QMediaPlayer::InvalidMedia); + break; + case JMediaPlayer::MEDIA_ERROR_MALFORMED: + errorString += QLatin1String(" (Malformed bitstream)"); + error = QMediaPlayer::FormatError; + setMediaStatus(QMediaPlayer::InvalidMedia); + break; + case JMediaPlayer::MEDIA_ERROR_UNSUPPORTED: + errorString += QLatin1String(" (Unsupported media)"); + error = QMediaPlayer::FormatError; + setMediaStatus(QMediaPlayer::InvalidMedia); + break; + case JMediaPlayer::MEDIA_ERROR_TIMED_OUT: + errorString += QLatin1String(" (Timed out)"); + break; + case JMediaPlayer::MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK: + errorString += QLatin1String(" (Unable to start progressive playback')"); + error = QMediaPlayer::FormatError; + setMediaStatus(QMediaPlayer::InvalidMedia); + break; + } + + setError(error, errorString); +} + +void QAndroidMediaPlayerControl::onBufferChanged(qint32 percent) +{ + mBuffering = percent != 100; + mBufferPercent = percent; + Q_EMIT bufferStatusChanged(mBufferPercent); + + updateAvailablePlaybackRanges(); + + if (mBufferPercent == 100) + setMediaStatus(QMediaPlayer::BufferedMedia); +} + +void QAndroidMediaPlayerControl::onVideoSizeChanged(qint32 width, qint32 height) +{ + QSize newSize(width, height); + + if (width == 0 || height == 0 || newSize == mVideoSize) + return; + + setVideoAvailable(true); + mVideoSize = newSize; + + if (mVideoOutput) + mVideoOutput->setVideoSize(mVideoSize); +} + +void QAndroidMediaPlayerControl::onSurfaceTextureReady() +{ + if (!mMediaPlayer->display() && mVideoOutput) { + mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder()); + flushPendingStates(); + } +} + +void QAndroidMediaPlayerControl::setState(QMediaPlayer::State state) +{ + if (mCurrentState == state) + return; + + if (state == QMediaPlayer::StoppedState) { + if (mVideoOutput) + mVideoOutput->stop(); + resetBufferingProgress(); + mMediaPlayerReady = false; + mPendingPosition = -1; + Q_EMIT positionChanged(0); + } + + mCurrentState = state; + Q_EMIT stateChanged(mCurrentState); +} + +void QAndroidMediaPlayerControl::setMediaStatus(QMediaPlayer::MediaStatus status) +{ + if (mCurrentMediaStatus == status) + return; + + if (status == QMediaPlayer::NoMedia || status == QMediaPlayer::InvalidMedia) + Q_EMIT durationChanged(0); + + mCurrentMediaStatus = status; + Q_EMIT mediaStatusChanged(mCurrentMediaStatus); +} + +void QAndroidMediaPlayerControl::setError(int error, + const QString &errorString) +{ + setState(QMediaPlayer::StoppedState); + Q_EMIT QMediaPlayerControl::error(error, errorString); +} + +void QAndroidMediaPlayerControl::setSeekable(bool seekable) +{ + if (mSeekable == seekable) + return; + + mSeekable = seekable; + Q_EMIT seekableChanged(mSeekable); +} + +void QAndroidMediaPlayerControl::setAudioAvailable(bool available) +{ + if (mAudioAvailable == available) + return; + + mAudioAvailable = available; + Q_EMIT audioAvailableChanged(mAudioAvailable); +} + +void QAndroidMediaPlayerControl::setVideoAvailable(bool available) +{ + if (mVideoAvailable == available) + return; + + if (!available) + mVideoSize = QSize(); + + mVideoAvailable = available; + Q_EMIT videoAvailableChanged(mVideoAvailable); +} + +void QAndroidMediaPlayerControl::resetBufferingProgress() +{ + mBuffering = false; + mBufferPercent = 0; + mAvailablePlaybackRange = QMediaTimeRange(); + Q_EMIT bufferStatusChanged(mBufferPercent); +} + +void QAndroidMediaPlayerControl::flushPendingStates() +{ + if (mPendingSetMedia) { + setMedia(mMediaContent, 0); + mPendingSetMedia = false; + return; + } + + switch (mPendingState) { + case QMediaPlayer::PlayingState: + if (mPendingPosition > -1) + setPosition(mPendingPosition); + play(); + break; + case QMediaPlayer::PausedState: + pause(); + break; + case QMediaPlayer::StoppedState: + stop(); + break; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h new file mode 100644 index 000000000..93eced853 --- /dev/null +++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** 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 QANDROIDMEDIAPLAYERCONTROL_H +#define QANDROIDMEDIAPLAYERCONTROL_H + +#include <qglobal.h> +#include <QMediaPlayerControl> +#include <qsize.h> + +QT_BEGIN_NAMESPACE + +class JMediaPlayer; +class QAndroidVideoOutput; + +class QAndroidMediaPlayerControl : public QMediaPlayerControl +{ + Q_OBJECT +public: + explicit QAndroidMediaPlayerControl(QObject *parent = 0); + ~QAndroidMediaPlayerControl() Q_DECL_OVERRIDE; + + QMediaPlayer::State state() const Q_DECL_OVERRIDE; + QMediaPlayer::MediaStatus mediaStatus() const Q_DECL_OVERRIDE; + qint64 duration() const Q_DECL_OVERRIDE; + qint64 position() const Q_DECL_OVERRIDE; + int volume() const Q_DECL_OVERRIDE; + bool isMuted() const Q_DECL_OVERRIDE; + int bufferStatus() const Q_DECL_OVERRIDE; + bool isAudioAvailable() const Q_DECL_OVERRIDE; + bool isVideoAvailable() const Q_DECL_OVERRIDE; + bool isSeekable() const Q_DECL_OVERRIDE; + QMediaTimeRange availablePlaybackRanges() const Q_DECL_OVERRIDE; + qreal playbackRate() const Q_DECL_OVERRIDE; + void setPlaybackRate(qreal rate) Q_DECL_OVERRIDE; + QMediaContent media() const Q_DECL_OVERRIDE; + const QIODevice *mediaStream() const Q_DECL_OVERRIDE; + void setMedia(const QMediaContent &mediaContent, QIODevice *stream) Q_DECL_OVERRIDE; + + void setVideoOutput(QAndroidVideoOutput *videoOutput); + void onSurfaceTextureReady(); + +Q_SIGNALS: + void metaDataUpdated(); + +public Q_SLOTS: + void setPosition(qint64 position) Q_DECL_OVERRIDE; + void play() Q_DECL_OVERRIDE; + void pause() Q_DECL_OVERRIDE; + void stop() Q_DECL_OVERRIDE; + void setVolume(int volume) Q_DECL_OVERRIDE; + void setMuted(bool muted) Q_DECL_OVERRIDE; + +private Q_SLOTS: + void onError(qint32 what, qint32 extra); + void onInfo(qint32 what, qint32 extra); + void onMediaPlayerInfo(qint32 what, qint32 extra); + void onBufferChanged(qint32 percent); + void onVideoSizeChanged(qint32 width, qint32 height); + +private: + JMediaPlayer *mMediaPlayer; + QMediaPlayer::State mCurrentState; + QMediaPlayer::MediaStatus mCurrentMediaStatus; + QMediaContent mMediaContent; + QIODevice *mMediaStream; + QAndroidVideoOutput *mVideoOutput; + bool mSeekable; + int mBufferPercent; + bool mAudioAvailable; + bool mVideoAvailable; + QSize mVideoSize; + bool mBuffering; + QMediaTimeRange mAvailablePlaybackRange; + bool mMediaPlayerReady; + QMediaPlayer::State mPendingState; + qint64 mPendingPosition; + bool mPendingSetMedia; + + void setState(QMediaPlayer::State state); + void setMediaStatus(QMediaPlayer::MediaStatus status); + void setError(int error, const QString &errorString); + void setSeekable(bool seekable); + void setAudioAvailable(bool available); + void setVideoAvailable(bool available); + void updateAvailablePlaybackRanges(); + void resetBufferingProgress(); + void flushPendingStates(); +}; + +QT_END_NAMESPACE + +#endif // QANDROIDMEDIAPLAYERCONTROL_H diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaservice.cpp b/src/plugins/android/src/mediaplayer/qandroidmediaservice.cpp new file mode 100644 index 000000000..175958676 --- /dev/null +++ b/src/plugins/android/src/mediaplayer/qandroidmediaservice.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** 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 "qandroidmediaservice.h" + +#include "qandroidmediaplayercontrol.h" +#include "qandroidmetadatareadercontrol.h" +#include "qandroidvideorendercontrol.h" + +QT_BEGIN_NAMESPACE + +QAndroidMediaService::QAndroidMediaService(QObject *parent) + : QMediaService(parent) + , mVideoRendererControl(0) +{ + mMediaControl = new QAndroidMediaPlayerControl; + mMetadataControl = new QAndroidMetaDataReaderControl; + connect(mMediaControl, SIGNAL(mediaChanged(QMediaContent)), + mMetadataControl, SLOT(onMediaChanged(QMediaContent))); + connect(mMediaControl, SIGNAL(metaDataUpdated()), + mMetadataControl, SLOT(onUpdateMetaData())); +} + +QAndroidMediaService::~QAndroidMediaService() +{ + delete mMediaControl; + delete mMetadataControl; + delete mVideoRendererControl; +} + +QMediaControl *QAndroidMediaService::requestControl(const char *name) +{ + if (qstrcmp(name, QMediaPlayerControl_iid) == 0) + return mMediaControl; + + if (qstrcmp(name, QMetaDataReaderControl_iid) == 0) + return mMetadataControl; + + if (qstrcmp(name, QVideoRendererControl_iid) == 0) { + if (!mVideoRendererControl) { + mVideoRendererControl = new QAndroidVideoRendererControl; + mMediaControl->setVideoOutput(mVideoRendererControl); + return mVideoRendererControl; + } + } + + return 0; +} + +void QAndroidMediaService::releaseControl(QMediaControl *control) +{ + if (control == mVideoRendererControl) { + mMediaControl->setVideoOutput(0); + delete mVideoRendererControl; + mVideoRendererControl = 0; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaservice.h b/src/plugins/android/src/mediaplayer/qandroidmediaservice.h new file mode 100644 index 000000000..4d310e8e0 --- /dev/null +++ b/src/plugins/android/src/mediaplayer/qandroidmediaservice.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 QANDROIDMEDIASERVICE_H +#define QANDROIDMEDIASERVICE_H + +#include <QMediaService> + +QT_BEGIN_NAMESPACE + +class QAndroidMediaPlayerControl; +class QAndroidMetaDataReaderControl; +class QAndroidVideoRendererControl; + +class QAndroidMediaService : public QMediaService +{ + Q_OBJECT +public: + explicit QAndroidMediaService(QObject *parent = 0); + ~QAndroidMediaService() Q_DECL_OVERRIDE; + + QMediaControl* requestControl(const char *name) Q_DECL_OVERRIDE; + void releaseControl(QMediaControl *control) Q_DECL_OVERRIDE; + +private: + QAndroidMediaPlayerControl *mMediaControl; + QAndroidMetaDataReaderControl *mMetadataControl; + QAndroidVideoRendererControl *mVideoRendererControl; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDMEDIASERVICE_H diff --git a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp new file mode 100644 index 000000000..e52c46387 --- /dev/null +++ b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp @@ -0,0 +1,222 @@ +/**************************************************************************** +** +** 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 "qandroidmetadatareadercontrol.h" + +#include "jmediametadataretriever.h" +#include <QtMultimedia/qmediametadata.h> +#include <qsize.h> +#include <QDate> + +QT_BEGIN_NAMESPACE + +// Genre name ordered by ID +// see: http://id3.org/id3v2.3.0#Appendix_A_-_Genre_List_from_ID3v1 +static const char* qt_ID3GenreNames[] = +{ + "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", "Hip-Hop", "Jazz", + "Metal", "New Age", "Oldies", "Other", "Pop", "R&B", "Rap", "Reggae", "Rock", "Techno", + "Industrial", "Alternative", "Ska", "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", + "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental", + "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass", "Soul", "Punk", + "Space", "Meditative", "Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic", "Darkwave", + "Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy", + "Cult", "Gangsta", "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American", + "Cabaret", "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi", "Tribal", + "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk", + "Folk-Rock", "National Folk", "Swing", "Fast Fusion", "Bebob", "Latin", "Revival", "Celtic", + "Bluegrass", "Avantgarde", "Gothic Rock", "Progressive Rock", "Psychedelic Rock", + "Symphonic Rock", "Slow Rock", "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", + "Speech", "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus", + "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba", "Folklore", "Ballad", + "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet", "Punk Rock", "Drum Solo", "A capella", + "Euro-House", "Dance Hall" +}; + +QAndroidMetaDataReaderControl::QAndroidMetaDataReaderControl(QObject *parent) + : QMetaDataReaderControl(parent) + , m_available(false) + , m_retriever(0) +{ + m_retriever = new JMediaMetadataRetriever; + if (!m_retriever->isValid()) { + delete m_retriever; + m_retriever = 0; + } +} + +QAndroidMetaDataReaderControl::~QAndroidMetaDataReaderControl() +{ + if (m_retriever) { + m_retriever->release(); + delete m_retriever; + } +} + +bool QAndroidMetaDataReaderControl::isMetaDataAvailable() const +{ + return m_available; +} + +QVariant QAndroidMetaDataReaderControl::metaData(const QString &key) const +{ + return m_metadata.value(key); +} + +QStringList QAndroidMetaDataReaderControl::availableMetaData() const +{ + return m_metadata.keys(); +} + +void QAndroidMetaDataReaderControl::onMediaChanged(const QMediaContent &media) +{ + if (!m_retriever) + return; + + m_mediaContent = media; + updateData(); +} + +void QAndroidMetaDataReaderControl::onUpdateMetaData() +{ + if (!m_retriever || m_mediaContent.isNull()) + return; + + updateData(); +} + +void QAndroidMetaDataReaderControl::updateData() +{ + m_metadata.clear(); + + if (!m_mediaContent.isNull()) { + if (m_retriever->setDataSource(m_mediaContent.canonicalUrl())) { + QString mimeType = m_retriever->extractMetadata(JMediaMetadataRetriever::MimeType); + if (!mimeType.isNull()) + m_metadata.insert(QMediaMetaData::MediaType, mimeType); + + bool isVideo = !m_retriever->extractMetadata(JMediaMetadataRetriever::HasVideo).isNull() + || mimeType.startsWith(QStringLiteral("video")); + + QString string = m_retriever->extractMetadata(JMediaMetadataRetriever::Album); + if (!string.isNull()) + m_metadata.insert(QMediaMetaData::AlbumTitle, string); + + string = m_retriever->extractMetadata(JMediaMetadataRetriever::AlbumArtist); + if (!string.isNull()) + m_metadata.insert(QMediaMetaData::AlbumArtist, string); + + string = m_retriever->extractMetadata(JMediaMetadataRetriever::Artist); + if (!string.isNull()) { + m_metadata.insert(isVideo ? QMediaMetaData::LeadPerformer + : QMediaMetaData::ContributingArtist, + string.split('/', QString::SkipEmptyParts)); + } + + string = m_retriever->extractMetadata(JMediaMetadataRetriever::Author); + if (!string.isNull()) + m_metadata.insert(QMediaMetaData::Author, string.split('/', QString::SkipEmptyParts)); + + string = m_retriever->extractMetadata(JMediaMetadataRetriever::Bitrate); + if (!string.isNull()) { + m_metadata.insert(isVideo ? QMediaMetaData::VideoBitRate + : QMediaMetaData::AudioBitRate, + string.toInt()); + } + + string = m_retriever->extractMetadata(JMediaMetadataRetriever::CDTrackNumber); + if (!string.isNull()) + m_metadata.insert(QMediaMetaData::TrackNumber, string.toInt()); + + string = m_retriever->extractMetadata(JMediaMetadataRetriever::Composer); + if (!string.isNull()) + m_metadata.insert(QMediaMetaData::Composer, string.split('/', QString::SkipEmptyParts)); + + string = m_retriever->extractMetadata(JMediaMetadataRetriever::Date); + if (!string.isNull()) + m_metadata.insert(QMediaMetaData::Date, QDateTime::fromString(string, QStringLiteral("yyyyMMddTHHmmss.zzzZ")).date()); + + string = m_retriever->extractMetadata(JMediaMetadataRetriever::Duration); + if (!string.isNull()) + m_metadata.insert(QMediaMetaData::Duration, string.toLongLong()); + + string = m_retriever->extractMetadata(JMediaMetadataRetriever::Genre); + if (!string.isNull()) { + // The genre can be returned as an ID3v2 id, get the name for it in that case + if (string.startsWith('(') && string.endsWith(')')) { + bool ok = false; + int genreId = string.mid(1, string.length() - 2).toInt(&ok); + if (ok && genreId >= 0 && genreId <= 125) + string = QLatin1String(qt_ID3GenreNames[genreId]); + } + m_metadata.insert(QMediaMetaData::Genre, string); + } + + string = m_retriever->extractMetadata(JMediaMetadataRetriever::Title); + if (!string.isNull()) + m_metadata.insert(QMediaMetaData::Title, string); + + string = m_retriever->extractMetadata(JMediaMetadataRetriever::VideoHeight); + if (!string.isNull()) { + int height = string.toInt(); + int width = m_retriever->extractMetadata(JMediaMetadataRetriever::VideoWidth).toInt(); + m_metadata.insert(QMediaMetaData::Resolution, QSize(width, height)); + } + + string = m_retriever->extractMetadata(JMediaMetadataRetriever::Writer); + if (!string.isNull()) + m_metadata.insert(QMediaMetaData::Writer, string.split('/', QString::SkipEmptyParts)); + + string = m_retriever->extractMetadata(JMediaMetadataRetriever::Year); + if (!string.isNull()) + m_metadata.insert(QMediaMetaData::Year, string.toInt()); + } + } + + bool oldAvailable = m_available; + m_available = !m_metadata.isEmpty(); + if (m_available != oldAvailable) + Q_EMIT metaDataAvailableChanged(m_available); + + Q_EMIT metaDataChanged(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h new file mode 100644 index 000000000..7ea736ffd --- /dev/null +++ b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.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 QANDROIDMETADATAREADERCONTROL_H +#define QANDROIDMETADATAREADERCONTROL_H + +#include <QMetaDataReaderControl> +#include <qmediacontent.h> + +QT_BEGIN_NAMESPACE + +class JMediaMetadataRetriever; + +class QAndroidMetaDataReaderControl : public QMetaDataReaderControl +{ + Q_OBJECT +public: + explicit QAndroidMetaDataReaderControl(QObject *parent = 0); + ~QAndroidMetaDataReaderControl() Q_DECL_OVERRIDE; + + bool isMetaDataAvailable() const Q_DECL_OVERRIDE; + + QVariant metaData(const QString &key) const Q_DECL_OVERRIDE; + QStringList availableMetaData() const Q_DECL_OVERRIDE; + +public Q_SLOTS: + void onMediaChanged(const QMediaContent &media); + void onUpdateMetaData(); + +private: + void updateData(); + + QMediaContent m_mediaContent; + bool m_available; + QVariantMap m_metadata; + + JMediaMetadataRetriever *m_retriever; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDMETADATAREADERCONTROL_H diff --git a/src/plugins/android/src/qandroidmediaserviceplugin.cpp b/src/plugins/android/src/qandroidmediaserviceplugin.cpp new file mode 100644 index 000000000..d7a2cd29f --- /dev/null +++ b/src/plugins/android/src/qandroidmediaserviceplugin.cpp @@ -0,0 +1,149 @@ +/**************************************************************************** +** +** 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 "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 <qdebug.h> + +QT_BEGIN_NAMESPACE + +QAndroidMediaServicePlugin::QAndroidMediaServicePlugin() +{ +} + +QAndroidMediaServicePlugin::~QAndroidMediaServicePlugin() +{ +} + +QMediaService *QAndroidMediaServicePlugin::create(const QString &key) +{ + 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; +} + +void QAndroidMediaServicePlugin::release(QMediaService *service) +{ + delete service; +} + +QMediaServiceProviderHint::Features QAndroidMediaServicePlugin::supportedFeatures(const QByteArray &service) const +{ + if (service == Q_MEDIASERVICE_MEDIAPLAYER) + 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<QByteArray> QAndroidMediaServicePlugin::devices(const QByteArray &service) const +{ + if (service == Q_MEDIASERVICE_CAMERA) + return QAndroidVideoDeviceSelectorControl::availableDevices(); + + if (service == Q_MEDIASERVICE_AUDIOSOURCE) + return QAndroidAudioInputSelectorControl::availableDevices(); + + return QList<QByteArray>(); +} + +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*/) +{ + typedef union { + JNIEnv *nativeEnvironment; + void *venv; + } UnionJNIEnvToVoid; + + UnionJNIEnvToVoid uenv; + uenv.venv = NULL; + + if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) + return JNI_ERR; + + JNIEnv *jniEnv = uenv.nativeEnvironment; + + if (!JMediaPlayer::initJNI(jniEnv) || + !JSurfaceTexture::initJNI(jniEnv) || + !JSurfaceTextureHolder::initJNI(jniEnv) || + !JCamera::initJNI(jniEnv) || + !JMultimediaUtils::initJNI(jniEnv) || + !JMediaRecorder::initJNI(jniEnv)) { + return JNI_ERR; + } + + return JNI_VERSION_1_4; +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/qandroidmediaserviceplugin.h b/src/plugins/android/src/qandroidmediaserviceplugin.h new file mode 100644 index 000000000..18b1def21 --- /dev/null +++ b/src/plugins/android/src/qandroidmediaserviceplugin.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 QANDROIDMEDIASERVICEPLUGIN_H +#define QANDROIDMEDIASERVICEPLUGIN_H + +#include <QMediaServiceProviderPlugin> + +QT_BEGIN_NAMESPACE + +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 "android_mediaservice.json") + +public: + QAndroidMediaServicePlugin(); + ~QAndroidMediaServicePlugin(); + + 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<QByteArray> devices(const QByteArray &service) const; + QString deviceDescription(const QByteArray &service, const QByteArray &device); +}; + +QT_END_NAMESPACE + +#endif // QANDROIDMEDIASERVICEPLUGIN_H diff --git a/src/plugins/android/src/src.pro b/src/plugins/android/src/src.pro new file mode 100644 index 000000000..e99fd30f5 --- /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 000000000..9005ac6e0 --- /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 <QtPlatformSupport/private/qjnihelpers_p.h> +#include <qstringlist.h> +#include <qdebug.h> +#include "qandroidmultimediautils.h" + +QT_BEGIN_NAMESPACE + +static jclass g_qtCameraClass = 0; +static QMap<int, JCamera*> g_objectMap; + +static QRect areaToRect(jobject areaObj) +{ + QJNIObject area(areaObj); + QJNILocalRef<jobject> rectRef = area.getObjectField<jobject>("rect", "android/graphics/Rect"); + QJNIObject rect(rectRef.object()); + + return QRect(rect.getField<jint>("left"), + rect.getField<jint>("top"), + rect.callMethod<jint>("width"), + rect.callMethod<jint>("height")); +} + +static QJNILocalRef<jobject> 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<jobject>(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<void>("android/hardware/Camera", + "getCameraInfo", + "(ILandroid/hardware/Camera$CameraInfo;)V", + cameraId, m_info->object()); + + QJNILocalRef<jobject> params = callObjectMethod<jobject>("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<jobject> camera = callStaticObjectMethod<jobject>(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<void>("lock"); +} + +void JCamera::unlock() +{ + callMethod<void>("unlock"); +} + +void JCamera::reconnect() +{ + callMethod<void>("reconnect"); +} + +void JCamera::release() +{ + m_previewSize = QSize(); + delete m_parameters; + m_parameters = 0; + callMethod<void>("release"); +} + +JCamera::CameraFacing JCamera::getFacing() +{ + return CameraFacing(m_info->getField<jint>("facing")); +} + +int JCamera::getNativeOrientation() +{ + return m_info->getField<jint>("orientation"); +} + +QSize JCamera::getPreferredPreviewSizeForVideo() +{ + if (!m_parameters || !m_parameters->isValid()) + return QSize(); + + QJNILocalRef<jobject> sizeRef = m_parameters->callObjectMethod<jobject>("getPreferredPreviewSizeForVideo", + "()Landroid/hardware/Camera$Size;"); + + QJNIObject size(sizeRef.object()); + return QSize(size.getField<jint>("width"), size.getField<jint>("height")); +} + +QList<QSize> JCamera::getSupportedPreviewSizes() +{ + QList<QSize> list; + + if (m_parameters && m_parameters->isValid()) { + QJNILocalRef<jobject> sizeListRef = m_parameters->callObjectMethod<jobject>("getSupportedPreviewSizes", + "()Ljava/util/List;"); + QJNIObject sizeList(sizeListRef.object()); + int count = sizeList.callMethod<jint>("size"); + for (int i = 0; i < count; ++i) { + QJNILocalRef<jobject> sizeRef = sizeList.callObjectMethod<jobject>("get", + "(I)Ljava/lang/Object;", + i); + QJNIObject size(sizeRef.object()); + list.append(QSize(size.getField<jint>("width"), size.getField<jint>("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<void>("setPreviewSize", "(II)V", size.width(), size.height()); + applyParameters(); + + emit previewSizeChanged(); +} + +void JCamera::setPreviewTexture(jobject surfaceTexture) +{ + callMethod<void>("setPreviewTexture", "(Landroid/graphics/SurfaceTexture;)V", surfaceTexture); +} + +bool JCamera::isZoomSupported() +{ + if (!m_parameters || !m_parameters->isValid()) + return false; + + return m_parameters->callMethod<jboolean>("isZoomSupported"); +} + +int JCamera::getMaxZoom() +{ + if (!m_parameters || !m_parameters->isValid()) + return 0; + + return m_parameters->callMethod<jint>("getMaxZoom"); +} + +QList<int> JCamera::getZoomRatios() +{ + QList<int> ratios; + + if (m_parameters && m_parameters->isValid()) { + QJNILocalRef<jobject> ratioListRef = m_parameters->callObjectMethod<jobject>("getZoomRatios", + "()Ljava/util/List;"); + QJNIObject ratioList(ratioListRef.object()); + int count = ratioList.callMethod<jint>("size"); + for (int i = 0; i < count; ++i) { + QJNILocalRef<jobject> zoomRatioRef = ratioList.callObjectMethod<jobject>("get", + "(I)Ljava/lang/Object;", + i); + + QJNIObject zoomRatio(zoomRatioRef.object()); + ratios.append(zoomRatio.callMethod<jint>("intValue")); + } + } + + return ratios; +} + +int JCamera::getZoom() +{ + if (!m_parameters || !m_parameters->isValid()) + return 0; + + return m_parameters->callMethod<jint>("getZoom"); +} + +void JCamera::setZoom(int value) +{ + if (!m_parameters || !m_parameters->isValid()) + return; + + m_parameters->callMethod<void>("setZoom", "(I)V", value); + applyParameters(); +} + +QStringList JCamera::getSupportedFlashModes() +{ + return callStringListMethod("getSupportedFlashModes"); +} + +QString JCamera::getFlashMode() +{ + QString value; + + if (m_parameters && m_parameters->isValid()) { + QJNILocalRef<jstring> flashMode = m_parameters->callObjectMethod<jstring>("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<void>("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<jstring> focusMode = m_parameters->callObjectMethod<jstring>("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<void>("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<jint>("getMaxNumFocusAreas"); +} + +QList<QRect> JCamera::getFocusAreas() +{ + QList<QRect> areas; + + if (m_hasAPI14 && m_parameters && m_parameters->isValid()) { + QJNILocalRef<jobject> listRef = m_parameters->callObjectMethod<jobject>("getFocusAreas", + "()Ljava/util/List;"); + + if (!listRef.isNull()) { + QJNIObject list(listRef.object()); + int count = list.callMethod<jint>("size"); + for (int i = 0; i < count; ++i) { + QJNILocalRef<jobject> areaRef = list.callObjectMethod<jobject>("get", + "(I)Ljava/lang/Object;", + i); + + areas.append(areaToRect(areaRef.object())); + } + } + } + + return areas; +} + +void JCamera::setFocusAreas(const QList<QRect> &areas) +{ + if (!m_hasAPI14 || !m_parameters || !m_parameters->isValid()) + return; + + QJNILocalRef<jobject> 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<jboolean>("add", + "(Ljava/lang/Object;)Z", + rectToArea(areas.at(i)).object()); + if (env->ExceptionCheck()) + env->ExceptionClear(); + } + list = env->NewLocalRef(arrayList.object()); + } + + m_parameters->callMethod<void>("setFocusAreas", "(Ljava/util/List;)V", list.object()); + + applyParameters(); +} + +void JCamera::autoFocus() +{ + callMethod<void>("autoFocus"); + emit autoFocusStarted(); +} + +void JCamera::cancelAutoFocus() +{ + callMethod<void>("cancelAutoFocus"); +} + +bool JCamera::isAutoExposureLockSupported() +{ + if (!m_hasAPI14 || !m_parameters || !m_parameters->isValid()) + return false; + + return m_parameters->callMethod<jboolean>("isAutoExposureLockSupported"); +} + +bool JCamera::getAutoExposureLock() +{ + if (!m_hasAPI14 || !m_parameters || !m_parameters->isValid()) + return false; + + return m_parameters->callMethod<jboolean>("getAutoExposureLock"); +} + +void JCamera::setAutoExposureLock(bool toggle) +{ + if (!m_hasAPI14 || !m_parameters || !m_parameters->isValid()) + return; + + m_parameters->callMethod<void>("setAutoExposureLock", "(Z)V", toggle); + applyParameters(); +} + +bool JCamera::isAutoWhiteBalanceLockSupported() +{ + if (!m_hasAPI14 || !m_parameters || !m_parameters->isValid()) + return false; + + return m_parameters->callMethod<jboolean>("isAutoWhiteBalanceLockSupported"); +} + +bool JCamera::getAutoWhiteBalanceLock() +{ + if (!m_hasAPI14 || !m_parameters || !m_parameters->isValid()) + return false; + + return m_parameters->callMethod<jboolean>("getAutoWhiteBalanceLock"); +} + +void JCamera::setAutoWhiteBalanceLock(bool toggle) +{ + if (!m_hasAPI14 || !m_parameters || !m_parameters->isValid()) + return; + + m_parameters->callMethod<void>("setAutoWhiteBalanceLock", "(Z)V", toggle); + applyParameters(); +} + +int JCamera::getExposureCompensation() +{ + if (!m_parameters || !m_parameters->isValid()) + return 0; + + return m_parameters->callMethod<jint>("getExposureCompensation"); +} + +void JCamera::setExposureCompensation(int value) +{ + if (!m_parameters || !m_parameters->isValid()) + return; + + m_parameters->callMethod<void>("setExposureCompensation", "(I)V", value); + applyParameters(); +} + +float JCamera::getExposureCompensationStep() +{ + if (!m_parameters || !m_parameters->isValid()) + return 0; + + return m_parameters->callMethod<jfloat>("getExposureCompensationStep"); +} + +int JCamera::getMinExposureCompensation() +{ + if (!m_parameters || !m_parameters->isValid()) + return 0; + + return m_parameters->callMethod<jint>("getMinExposureCompensation"); +} + +int JCamera::getMaxExposureCompensation() +{ + if (!m_parameters || !m_parameters->isValid()) + return 0; + + return m_parameters->callMethod<jint>("getMaxExposureCompensation"); +} + +QStringList JCamera::getSupportedSceneModes() +{ + return callStringListMethod("getSupportedSceneModes"); +} + +QString JCamera::getSceneMode() +{ + QString value; + + if (m_parameters && m_parameters->isValid()) { + QJNILocalRef<jstring> sceneMode = m_parameters->callObjectMethod<jstring>("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<void>("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<jstring> wb = m_parameters->callObjectMethod<jstring>("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<void>("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<void>("setRotation", "(I)V", rotation); + applyParameters(); +} + +QList<QSize> JCamera::getSupportedPictureSizes() +{ + QList<QSize> list; + + if (m_parameters && m_parameters->isValid()) { + QJNILocalRef<jobject> sizeListRef = m_parameters->callObjectMethod<jobject>("getSupportedPictureSizes", + "()Ljava/util/List;"); + QJNIObject sizeList(sizeListRef.object()); + int count = sizeList.callMethod<jint>("size"); + for (int i = 0; i < count; ++i) { + QJNILocalRef<jobject> sizeRef = sizeList.callObjectMethod<jobject>("get", + "(I)Ljava/lang/Object;", + i); + QJNIObject size(sizeRef.object()); + list.append(QSize(size.getField<jint>("width"), size.getField<jint>("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<void>("setPictureSize", "(II)V", size.width(), size.height()); + applyParameters(); +} + +void JCamera::setJpegQuality(int quality) +{ + if (!m_parameters || !m_parameters->isValid()) + return; + + m_parameters->callMethod<void>("setJpegQuality", "(I)V", quality); + applyParameters(); +} + +void JCamera::takePicture() +{ + callMethod<void>("takePicture"); +} + +void JCamera::startPreview() +{ + callMethod<void>("startPreview"); +} + +void JCamera::stopPreview() +{ + callMethod<void>("stopPreview"); +} + +void JCamera::applyParameters() +{ + callMethod<void>("setParameters", + "(Landroid/hardware/Camera$Parameters;)V", + m_parameters->object()); +} + +QStringList JCamera::callStringListMethod(const char *methodName) +{ + QStringList stringList; + + if (m_parameters && m_parameters->isValid()) { + QJNILocalRef<jobject> listRef = m_parameters->callObjectMethod<jobject>(methodName, + "()Ljava/util/List;"); + + if (!listRef.isNull()) { + QJNIObject list(listRef.object()); + int count = list.callMethod<jint>("size"); + for (int i = 0; i < count; ++i) { + QJNILocalRef<jobject> stringRef = list.callObjectMethod<jobject>("get", + "(I)Ljava/lang/Object;", + i); + + QJNIObject string(stringRef.object()); + stringList.append(qt_convertJString(string.callObjectMethod<jstring>("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<jclass>(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 000000000..100628721 --- /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 <qobject.h> +#include <QtPlatformSupport/private/qjniobject_p.h> +#include <qsize.h> +#include <qrect.h> + +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<QSize> getSupportedPreviewSizes(); + + QSize previewSize() const { return m_previewSize; } + void setPreviewSize(const QSize &size); + void setPreviewTexture(jobject surfaceTexture); + + bool isZoomSupported(); + int getMaxZoom(); + QList<int> 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<QRect> getFocusAreas(); + void setFocusAreas(const QList<QRect> &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<QSize> 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/src/wrappers/jmediametadataretriever.cpp b/src/plugins/android/src/wrappers/jmediametadataretriever.cpp new file mode 100644 index 000000000..ae5abcf43 --- /dev/null +++ b/src/plugins/android/src/wrappers/jmediametadataretriever.cpp @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** 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 "jmediametadataretriever.h" + +#include <QtPlatformSupport/private/qjnihelpers_p.h> +#include <qpa/qplatformnativeinterface.h> +#include <qguiapplication.h> + +QT_BEGIN_NAMESPACE + +static jobject g_activity = 0; + +JMediaMetadataRetriever::JMediaMetadataRetriever() + : QJNIObject("android/media/MediaMetadataRetriever") +{ + if (!g_activity) { + QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); + g_activity = static_cast<jobject>(nativeInterface->nativeResourceForIntegration("QtActivity")); + } +} + +JMediaMetadataRetriever::~JMediaMetadataRetriever() +{ +} + +QString JMediaMetadataRetriever::extractMetadata(MetadataKey key) +{ + QString value; + + QJNILocalRef<jstring> metadata = callObjectMethod<jstring>("extractMetadata", + "(I)Ljava/lang/String;", + jint(key)); + if (!metadata.isNull()) + value = qt_convertJString(metadata.object()); + + return value; +} + +void JMediaMetadataRetriever::release() +{ + callMethod<void>("release"); +} + +bool JMediaMetadataRetriever::setDataSource(const QUrl &url) +{ + QAttachedJNIEnv env; + + bool loaded = false; + + QJNILocalRef<jstring> string = qt_toJString(url.toString()); + + QJNILocalRef<jobject> uri = callStaticObjectMethod<jobject>("android/net/Uri", + "parse", + "(Ljava/lang/String;)Landroid/net/Uri;", + string.object()); + if (env->ExceptionCheck()) { + env->ExceptionClear(); + } else { + callMethod<void>("setDataSource", + "(Landroid/content/Context;Landroid/net/Uri;)V", + g_activity, + uri.object()); + if (env->ExceptionCheck()) + env->ExceptionClear(); + else + loaded = true; + } + + return loaded; +} + +bool JMediaMetadataRetriever::setDataSource(const QString &path) +{ + QAttachedJNIEnv env; + + bool loaded = false; + + callMethod<void>("setDataSource", "(Ljava/lang/String;)V", qt_toJString(path).object()); + if (env->ExceptionCheck()) + env->ExceptionClear(); + else + loaded = true; + + return loaded; +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/wrappers/jmediametadataretriever.h b/src/plugins/android/src/wrappers/jmediametadataretriever.h new file mode 100644 index 000000000..dd63e0d87 --- /dev/null +++ b/src/plugins/android/src/wrappers/jmediametadataretriever.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** 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 JMEDIAMETADATARETRIEVER_H +#define JMEDIAMETADATARETRIEVER_H + +#include <QtPlatformSupport/private/qjniobject_p.h> +#include <qurl.h> + +QT_BEGIN_NAMESPACE + +class JMediaMetadataRetriever : public QJNIObject +{ +public: + enum MetadataKey { + Album = 1, + AlbumArtist = 13, + Artist = 2, + Author = 3, + Bitrate = 20, + CDTrackNumber = 0, + Compilation = 15, + Composer = 4, + Date = 5, + DiscNumber = 14, + Duration = 9, + Genre = 6, + HasAudio = 16, + HasVideo = 17, + Location = 23, + MimeType = 12, + NumTracks = 10, + Title = 7, + VideoHeight = 19, + VideoWidth = 18, + VideoRotation = 24, + Writer = 11, + Year = 8 + }; + + JMediaMetadataRetriever(); + ~JMediaMetadataRetriever(); + + QString extractMetadata(MetadataKey key); + void release(); + bool setDataSource(const QUrl &url); + bool setDataSource(const QString &path); + +}; + +QT_END_NAMESPACE + +#endif // JMEDIAMETADATARETRIEVER_H diff --git a/src/plugins/android/src/wrappers/jmediaplayer.cpp b/src/plugins/android/src/wrappers/jmediaplayer.cpp new file mode 100644 index 000000000..f6e03ee22 --- /dev/null +++ b/src/plugins/android/src/wrappers/jmediaplayer.cpp @@ -0,0 +1,270 @@ +/**************************************************************************** +** +** 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 "jmediaplayer.h" + +#include <QString> +#include <qpa/qplatformnativeinterface.h> +#include <qguiapplication.h> +#include <QtPlatformSupport/private/qjnihelpers_p.h> + +namespace { + +jclass mediaPlayerClass = 0; + +QMap<jlong, JMediaPlayer *> mplayers; + +} + +QT_BEGIN_NAMESPACE + +bool JMediaPlayer::mActivitySet = false; + +JMediaPlayer::JMediaPlayer() + : QObject() + , QJNIObject(mediaPlayerClass, "(J)V", reinterpret_cast<jlong>(this)) + , mId(reinterpret_cast<jlong>(this)) + , mDisplay(0) +{ + mplayers.insert(mId, this); + + if (!mActivitySet) { + QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); + jobject activity = static_cast<jobject>(nativeInterface->nativeResourceForIntegration("QtActivity")); + QJNIObject::callStaticMethod<void>(mediaPlayerClass, + "setActivity", + "(Landroid/app/Activity;)V", + activity); + mActivitySet = true; + } +} + +JMediaPlayer::~JMediaPlayer() +{ + mplayers.remove(mId); +} + +void JMediaPlayer::release() +{ + callMethod<void>("release"); +} + +void JMediaPlayer::onError(qint32 what, qint32 extra) +{ + Q_EMIT error(what, extra); +} + +void JMediaPlayer::onBufferingUpdate(qint32 percent) +{ + Q_EMIT bufferingUpdate(percent); +} + +void JMediaPlayer::onInfo(qint32 what, qint32 extra) +{ + Q_EMIT info(what, extra); +} + +void JMediaPlayer::onMediaPlayerInfo(qint32 what, qint32 extra) +{ + Q_EMIT mediaPlayerInfo(what, extra); +} + +void JMediaPlayer::onVideoSizeChanged(qint32 width, qint32 height) +{ + Q_EMIT videoSizeChanged(width, height); +} + +int JMediaPlayer::getCurrentPosition() +{ + return callMethod<jint>("getCurrentPosition"); +} + +int JMediaPlayer::getDuration() +{ + return callMethod<jint>("getDuration"); +} + +bool JMediaPlayer::isPlaying() +{ + return callMethod<jboolean>("isPlaying"); +} + +int JMediaPlayer::volume() +{ + return callMethod<jint>("getVolume"); +} + +bool JMediaPlayer::isMuted() +{ + return callMethod<jboolean>("isMuted"); +} + +void JMediaPlayer::play() +{ + callMethod<void>("start"); +} + +void JMediaPlayer::pause() +{ + callMethod<void>("pause"); +} + +void JMediaPlayer::stop() +{ + callMethod<void>("stop"); +} + +void JMediaPlayer::seekTo(qint32 msec) +{ + callMethod<void>("seekTo", "(I)V", jint(msec)); +} + +void JMediaPlayer::setMuted(bool mute) +{ + callMethod<void>("mute", "(Z)V", jboolean(mute)); +} + +void JMediaPlayer::setDataSource(const QString &path) +{ + QJNILocalRef<jstring> string = qt_toJString(path); + callMethod<void>("setMediaPath", "(Ljava/lang/String;)V", string.object()); +} + +void JMediaPlayer::setVolume(int volume) +{ + callMethod<void>("setVolume", "(I)V", jint(volume)); +} + +void JMediaPlayer::setDisplay(jobject surfaceHolder) +{ + mDisplay = surfaceHolder; + callMethod<void>("setDisplay", "(Landroid/view/SurfaceHolder;)V", mDisplay); +} + +QT_END_NAMESPACE + +static void onErrorNative(JNIEnv *env, jobject thiz, jint what, jint extra, jlong id) +{ + Q_UNUSED(env); + Q_UNUSED(thiz); + JMediaPlayer *const mp = mplayers[id]; + if (!mp) + return; + + mp->onError(what, extra); +} + +static void onBufferingUpdateNative(JNIEnv *env, jobject thiz, jint percent, jlong id) +{ + Q_UNUSED(env); + Q_UNUSED(thiz); + JMediaPlayer *const mp = mplayers[id]; + if (!mp) + return; + + mp->onBufferingUpdate(percent); +} + +static void onInfoNative(JNIEnv *env, jobject thiz, jint what, jint extra, jlong id) +{ + Q_UNUSED(env); + Q_UNUSED(thiz); + JMediaPlayer *const mp = mplayers[id]; + if (!mp) + return; + + mp->onInfo(what, extra); +} + +static void onMediaPlayerInfoNative(JNIEnv *env, jobject thiz, jint what, jint extra, jlong id) +{ + Q_UNUSED(env); + Q_UNUSED(thiz); + JMediaPlayer *const mp = mplayers[id]; + if (!mp) + return; + + mp->onMediaPlayerInfo(what, extra); +} + +static void onVideoSizeChangedNative(JNIEnv *env, + jobject thiz, + jint width, + jint height, + jlong id) +{ + Q_UNUSED(env); + Q_UNUSED(thiz); + JMediaPlayer *const mp = mplayers[id]; + if (!mp) + return; + + mp->onVideoSizeChanged(width, height); +} + +QT_BEGIN_NAMESPACE + +bool JMediaPlayer::initJNI(JNIEnv *env) +{ + jclass jClass = env->FindClass("org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer"); + + if (jClass) { + mediaPlayerClass = static_cast<jclass>(env->NewGlobalRef(jClass)); + + JNINativeMethod methods[] = { + {"onErrorNative", "(IIJ)V", reinterpret_cast<void *>(onErrorNative)}, + {"onBufferingUpdateNative", "(IJ)V", reinterpret_cast<void *>(onBufferingUpdateNative)}, + {"onInfoNative", "(IIJ)V", reinterpret_cast<void *>(onInfoNative)}, + {"onMediaPlayerInfoNative", "(IIJ)V", reinterpret_cast<void *>(onMediaPlayerInfoNative)}, + {"onVideoSizeChangedNative", "(IIJ)V", reinterpret_cast<void *>(onVideoSizeChangedNative)} + }; + + if (env->RegisterNatives(mediaPlayerClass, + methods, + sizeof(methods) / sizeof(methods[0])) < 0) { + return false; + } + } + + return true; +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/wrappers/jmediaplayer.h b/src/plugins/android/src/wrappers/jmediaplayer.h new file mode 100644 index 000000000..710246b9a --- /dev/null +++ b/src/plugins/android/src/wrappers/jmediaplayer.h @@ -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$ +** +****************************************************************************/ + +#ifndef QANDROIDMEDIAPLAYER_H +#define QANDROIDMEDIAPLAYER_H + +#include <QObject> +#include <QtPlatformSupport/private/qjniobject_p.h> + +QT_BEGIN_NAMESPACE + +class JMediaPlayer : public QObject, public QJNIObject +{ + Q_OBJECT +public: + JMediaPlayer(); + ~JMediaPlayer(); + + enum MediaError + { + // What + MEDIA_ERROR_UNKNOWN = 1, + MEDIA_ERROR_SERVER_DIED = 100, + // Extra + MEDIA_ERROR_IO = -1004, + MEDIA_ERROR_MALFORMED = -1007, + MEDIA_ERROR_UNSUPPORTED = -1010, + MEDIA_ERROR_TIMED_OUT = -110, + MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200 + }; + + enum MediaInfo + { + MEDIA_INFO_UNKNOWN = 1, + MEDIA_INFO_VIDEO_TRACK_LAGGING = 700, + MEDIA_INFO_VIDEO_RENDERING_START = 3, + MEDIA_INFO_BUFFERING_START = 701, + MEDIA_INFO_BUFFERING_END = 702, + MEDIA_INFO_BAD_INTERLEAVING = 800, + MEDIA_INFO_NOT_SEEKABLE = 801, + MEDIA_INFO_METADATA_UPDATE = 802 + }; + + enum MediaPlayerInfo + { + MEDIA_PLAYER_INVALID_STATE = 1, + MEDIA_PLAYER_PREPARING = 2, + MEDIA_PLAYER_READY = 3, + MEDIA_PLAYER_DURATION = 4, + MEDIA_PLAYER_PROGRESS = 5, + MEDIA_PLAYER_FINISHED = 6 + }; + + void release(); + + int getCurrentPosition(); + int getDuration(); + bool isPlaying(); + int volume(); + bool isMuted(); + jobject display() { return mDisplay; } + + void play(); + void pause(); + void stop(); + void seekTo(qint32 msec); + void setMuted(bool mute); + void setDataSource(const QString &path); + void setVolume(int volume); + void setDisplay(jobject surfaceHolder); + + void onError(qint32 what, qint32 extra); + void onBufferingUpdate(qint32 percent); + void onInfo(qint32 what, qint32 extra); + void onMediaPlayerInfo(qint32 what, qint32 extra); + void onVideoSizeChanged(qint32 width, qint32 height); + + static bool initJNI(JNIEnv *env); + +Q_SIGNALS: + void error(qint32 what, qint32 extra); + void bufferingUpdate(qint32 percent); + void completion(); + void info(qint32 what, qint32 extra); + void mediaPlayerInfo(qint32 what, qint32 extra); + void videoSizeChanged(qint32 width, qint32 height); + +private: + jlong mId; + jobject mDisplay; + + static bool mActivitySet; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDMEDIAPLAYER_H diff --git a/src/plugins/android/src/wrappers/jmediarecorder.cpp b/src/plugins/android/src/wrappers/jmediarecorder.cpp new file mode 100644 index 000000000..b7cbe5724 --- /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 <QtPlatformSupport/private/qjnihelpers_p.h> +#include <qmap.h> + +QT_BEGIN_NAMESPACE + +static jclass g_qtMediaRecorderClass = 0; +static QMap<jlong, JMediaRecorder*> 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<jlong>(this)) + , m_id(reinterpret_cast<jlong>(this)) +{ + if (isValid()) + g_objectMap.insert(m_id, this); +} + +JMediaRecorder::~JMediaRecorder() +{ + g_objectMap.remove(m_id); +} + +void JMediaRecorder::release() +{ + callMethod<void>("release"); +} + +bool JMediaRecorder::prepare() +{ + QAttachedJNIEnv env; + callMethod<void>("prepare"); + if (env->ExceptionCheck()) { + env->ExceptionClear(); + return false; + } + return true; +} + +void JMediaRecorder::reset() +{ + callMethod<void>("reset"); +} + +bool JMediaRecorder::start() +{ + QAttachedJNIEnv env; + callMethod<void>("start"); + if (env->ExceptionCheck()) { + env->ExceptionClear(); + return false; + } + return true; +} + +void JMediaRecorder::stop() +{ + QAttachedJNIEnv env; + callMethod<void>("stop"); + if (env->ExceptionCheck()) + env->ExceptionClear(); +} + +void JMediaRecorder::setAudioChannels(int numChannels) +{ + callMethod<void>("setAudioChannels", "(I)V", numChannels); +} + +void JMediaRecorder::setAudioEncoder(AudioEncoder encoder) +{ + QAttachedJNIEnv env; + callMethod<void>("setAudioEncoder", "(I)V", int(encoder)); + if (env->ExceptionCheck()) + env->ExceptionClear(); +} + +void JMediaRecorder::setAudioEncodingBitRate(int bitRate) +{ + callMethod<void>("setAudioEncodingBitRate", "(I)V", bitRate); +} + +void JMediaRecorder::setAudioSamplingRate(int samplingRate) +{ + callMethod<void>("setAudioSamplingRate", "(I)V", samplingRate); +} + +void JMediaRecorder::setAudioSource(AudioSource source) +{ + QAttachedJNIEnv env; + callMethod<void>("setAudioSource", "(I)V", int(source)); + if (env->ExceptionCheck()) + env->ExceptionClear(); +} + +void JMediaRecorder::setCamera(JCamera *camera) +{ + QJNILocalRef<jobject> cam = camera->getObjectField<jobject>("m_camera", "Landroid/hardware/Camera;"); + callMethod<void>("setCamera", "(Landroid/hardware/Camera;)V", cam.object()); +} + +void JMediaRecorder::setVideoEncoder(VideoEncoder encoder) +{ + QAttachedJNIEnv env; + callMethod<void>("setVideoEncoder", "(I)V", int(encoder)); + if (env->ExceptionCheck()) + env->ExceptionClear(); +} + +void JMediaRecorder::setVideoEncodingBitRate(int bitRate) +{ + callMethod<void>("setVideoEncodingBitRate", "(I)V", bitRate); +} + +void JMediaRecorder::setVideoFrameRate(int rate) +{ + QAttachedJNIEnv env; + callMethod<void>("setVideoFrameRate", "(I)V", rate); + if (env->ExceptionCheck()) + env->ExceptionClear(); +} + +void JMediaRecorder::setVideoSize(const QSize &size) +{ + QAttachedJNIEnv env; + callMethod<void>("setVideoSize", "(II)V", size.width(), size.height()); + if (env->ExceptionCheck()) + env->ExceptionClear(); +} + +void JMediaRecorder::setVideoSource(VideoSource source) +{ + QAttachedJNIEnv env; + callMethod<void>("setVideoSource", "(I)V", int(source)); + if (env->ExceptionCheck()) + env->ExceptionClear(); +} + +void JMediaRecorder::setOrientationHint(int degrees) +{ + QAttachedJNIEnv env; + callMethod<void>("setOrientationHint", "(I)V", degrees); + if (env->ExceptionCheck()) + env->ExceptionClear(); +} + +void JMediaRecorder::setOutputFormat(OutputFormat format) +{ + QAttachedJNIEnv env; + callMethod<void>("setOutputFormat", "(I)V", int(format)); + if (env->ExceptionCheck()) + env->ExceptionClear(); +} + +void JMediaRecorder::setOutputFile(const QString &path) +{ + QAttachedJNIEnv env; + callMethod<void>("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<jclass>(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 000000000..ef26b8a72 --- /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 <qobject.h> +#include <QtPlatformSupport/private/qjniobject_p.h> +#include <qsize.h> + +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 000000000..6832e6b6e --- /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 <QtPlatformSupport/private/qjnihelpers_p.h> + +QT_BEGIN_NAMESPACE + +static jclass g_qtMultimediaUtilsClass = 0; + +JMultimediaUtils::JMultimediaUtils() + : QObject() + , QJNIObject(g_qtMultimediaUtilsClass) +{ +} + +void JMultimediaUtils::enableOrientationListener(bool enable) +{ + callStaticMethod<void>(g_qtMultimediaUtilsClass, "enableOrientationListener", "(Z)V", enable); +} + +int JMultimediaUtils::getDeviceOrientation() +{ + return callStaticMethod<jint>(g_qtMultimediaUtilsClass, "getDeviceOrientation"); +} + +QString JMultimediaUtils::getDefaultMediaDirectory(MediaType type) +{ + QJNILocalRef<jstring> path = callStaticObjectMethod<jstring>(g_qtMultimediaUtilsClass, + "getDefaultMediaDirectory", + "(I)Ljava/lang/String;", + jint(type)); + return qt_convertJString(path.object()); +} + +void JMultimediaUtils::registerMediaFile(const QString &file) +{ + callStaticMethod<void>(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<jclass>(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 000000000..909f5c155 --- /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 <qobject.h> +#include <QtPlatformSupport/private/qjniobject_p.h> + +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/src/wrappers/jsurfacetexture.cpp b/src/plugins/android/src/wrappers/jsurfacetexture.cpp new file mode 100644 index 000000000..60c85cdf0 --- /dev/null +++ b/src/plugins/android/src/wrappers/jsurfacetexture.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 "jsurfacetexture.h" +#include <QtPlatformSupport/private/qjnihelpers_p.h> + +QT_BEGIN_NAMESPACE + +static jclass g_qtSurfaceTextureClass = 0; +static QMap<int, JSurfaceTexture*> g_objectMap; + +// native method for QtSurfaceTexture.java +static void notifyFrameAvailable(JNIEnv* , jobject, int id) +{ + JSurfaceTexture *obj = g_objectMap.value(id, 0); + if (obj) + Q_EMIT obj->frameAvailable(); +} + +JSurfaceTexture::JSurfaceTexture(unsigned int texName) + : QObject() + , QJNIObject(g_qtSurfaceTextureClass, "(I)V", jint(texName)) + , m_texID(int(texName)) +{ + if (isValid()) + g_objectMap.insert(int(texName), this); +} + +JSurfaceTexture::~JSurfaceTexture() +{ + if (isValid()) + g_objectMap.remove(m_texID); +} + +QMatrix4x4 JSurfaceTexture::getTransformMatrix() +{ + QAttachedJNIEnv env; + + QMatrix4x4 matrix; + jfloatArray array = env->NewFloatArray(16); + callMethod<void>("getTransformMatrix", "([F)V", array); + env->GetFloatArrayRegion(array, 0, 16, matrix.data()); + env->DeleteLocalRef(array); + + return matrix; +} + +void JSurfaceTexture::updateTexImage() +{ + callMethod<void>("updateTexImage"); +} + +static JNINativeMethod methods[] = { + {"notifyFrameAvailable", "(I)V", (void *)notifyFrameAvailable} +}; + +bool JSurfaceTexture::initJNI(JNIEnv *env) +{ + jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtSurfaceTexture"); + if (env->ExceptionCheck()) + env->ExceptionClear(); + + if (clazz) { + g_qtSurfaceTextureClass = static_cast<jclass>(env->NewGlobalRef(clazz)); + if (env->RegisterNatives(g_qtSurfaceTextureClass, + methods, + sizeof(methods) / sizeof(methods[0])) < 0) { + return false; + } + } + + return true; +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/wrappers/jsurfacetexture.h b/src/plugins/android/src/wrappers/jsurfacetexture.h new file mode 100644 index 000000000..2a2f27ae3 --- /dev/null +++ b/src/plugins/android/src/wrappers/jsurfacetexture.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 JSURFACETEXTURE_H +#define JSURFACETEXTURE_H + +#include <qobject.h> +#include <QtPlatformSupport/private/qjniobject_p.h> + +#include <QMatrix4x4> + +QT_BEGIN_NAMESPACE + +class JSurfaceTexture : public QObject, public QJNIObject +{ + Q_OBJECT +public: + explicit JSurfaceTexture(unsigned int texName); + ~JSurfaceTexture(); + + QMatrix4x4 getTransformMatrix(); + void updateTexImage(); + + static bool initJNI(JNIEnv *env); + +Q_SIGNALS: + void frameAvailable(); + +private: + int m_texID; +}; + +QT_END_NAMESPACE + +#endif // JSURFACETEXTURE_H diff --git a/src/plugins/android/src/wrappers/jsurfacetextureholder.cpp b/src/plugins/android/src/wrappers/jsurfacetextureholder.cpp new file mode 100644 index 000000000..4ec8935c2 --- /dev/null +++ b/src/plugins/android/src/wrappers/jsurfacetextureholder.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** 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 "jsurfacetextureholder.h" + +QT_BEGIN_NAMESPACE + +static jclass g_qtSurfaceTextureHolderClass = 0; + +JSurfaceTextureHolder::JSurfaceTextureHolder(jobject surface) + : QJNIObject(g_qtSurfaceTextureHolderClass, "(Landroid/view/Surface;)V", surface) +{ +} + +bool JSurfaceTextureHolder::initJNI(JNIEnv *env) +{ + jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtSurfaceTextureHolder"); + if (env->ExceptionCheck()) + env->ExceptionClear(); + + if (clazz) + g_qtSurfaceTextureHolderClass = static_cast<jclass>(env->NewGlobalRef(clazz)); + + return true; +} + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/wrappers/jsurfacetextureholder.h b/src/plugins/android/src/wrappers/jsurfacetextureholder.h new file mode 100644 index 000000000..5b567de3a --- /dev/null +++ b/src/plugins/android/src/wrappers/jsurfacetextureholder.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** 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 JSURFACETEXTUREHOLDER_H +#define JSURFACETEXTUREHOLDER_H + +#include <QtPlatformSupport/private/qjniobject_p.h> + +QT_BEGIN_NAMESPACE + +class JSurfaceTextureHolder : public QJNIObject +{ +public: + JSurfaceTextureHolder(jobject surface); + + static bool initJNI(JNIEnv *env); +}; + +QT_END_NAMESPACE + +#endif // JSURFACETEXTUREHOLDER_H diff --git a/src/plugins/android/src/wrappers/wrappers.pri b/src/plugins/android/src/wrappers/wrappers.pri new file mode 100644 index 000000000..b2faa5b79 --- /dev/null +++ b/src/plugins/android/src/wrappers/wrappers.pri @@ -0,0 +1,21 @@ +QT += platformsupport-private + +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/jmediaplayer.h \ + $$PWD/jsurfacetexture.h \ + $$PWD/jsurfacetextureholder.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/jcamera.cpp \ + $$PWD/jmultimediautils.cpp \ + $$PWD/jmediarecorder.cpp |