From d8f055f8940b8ae2b1196ea0968ce0a942bab8ab Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Fri, 10 Mar 2017 17:18:13 +0100 Subject: DirectShow: support audio and video codec metadata Retrieve the audio and video codec metadata from media files. As the GUID of these codecs are only defined in the WMF API, we have to hardcode them here. Change-Id: I9a057e62d9473f605cf5078d3386c5827784ae28 Reviewed-by: Christian Stromme --- .../player/directshowmetadatacontrol.cpp | 108 +++++++++++++++++++++ 1 file changed, 108 insertions(+) (limited to 'src') diff --git a/src/plugins/directshow/player/directshowmetadatacontrol.cpp b/src/plugins/directshow/player/directshowmetadatacontrol.cpp index 45d3a958b..1f75e3340 100644 --- a/src/plugins/directshow/player/directshowmetadatacontrol.cpp +++ b/src/plugins/directshow/player/directshowmetadatacontrol.cpp @@ -87,6 +87,7 @@ DEFINE_PROPERTYKEY(PKEY_Media_AverageLevel, 0x09EDD5B6, 0xB301, 0x43C5, 0x99, 0x DEFINE_PROPERTYKEY(PKEY_Audio_ChannelCount, 0x64440490, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 7); DEFINE_PROPERTYKEY(PKEY_Audio_PeakValue, 0x2579E5D0, 0x1116, 0x4084, 0xBD, 0x9A, 0x9B, 0x4F, 0x7C, 0xB4, 0xDF, 0x5E, 100); DEFINE_PROPERTYKEY(PKEY_Audio_SampleRate, 0x64440490, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 5); +DEFINE_PROPERTYKEY(PKEY_Audio_Format, 0x64440490, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 2); DEFINE_PROPERTYKEY(PKEY_Music_AlbumTitle, 0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6, 4); DEFINE_PROPERTYKEY(PKEY_Music_AlbumArtist, 0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6, 13); DEFINE_PROPERTYKEY(PKEY_Music_Artist, 0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6, 2); @@ -104,8 +105,111 @@ DEFINE_PROPERTYKEY(PKEY_Video_VerticalAspectRatio, 0x64440491, 0x4C8B, 0x11D1, 0 DEFINE_PROPERTYKEY(PKEY_Video_FrameRate, 0x64440491, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 6); DEFINE_PROPERTYKEY(PKEY_Video_EncodingBitrate, 0x64440491, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 8); DEFINE_PROPERTYKEY(PKEY_Video_Director, 0x64440492, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 20); +DEFINE_PROPERTYKEY(PKEY_Video_Compression, 0x64440491, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 10); DEFINE_PROPERTYKEY(PKEY_Media_Writer, 0x64440492, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 23); +static QString nameForGUIDString(const QString &guid) +{ + // Audio formats + if (guid == "{00001610-0000-0010-8000-00AA00389B71}" || guid == "{000000FF-0000-0010-8000-00AA00389B71}") + return QStringLiteral("MPEG AAC Audio"); + else if (guid == "{00001600-0000-0010-8000-00AA00389B71}") + return QStringLiteral("MPEG ADTS AAC Audio"); + else if (guid == "{00000092-0000-0010-8000-00AA00389B71}") + return QStringLiteral("Dolby AC-3 SPDIF"); + else if (guid == "{E06D802C-DB46-11CF-B4D1-00805F6CBBEA}" || guid == "{00002000-0000-0010-8000-00AA00389B71}") + return QStringLiteral("Dolby AC-3"); + else if (guid == "{A7FB87AF-2D02-42FB-A4D4-05CD93843BDD}") + return QStringLiteral("Dolby Digital Plus"); + else if (guid == "{00000009-0000-0010-8000-00AA00389B71}") + return QStringLiteral("DRM"); + else if (guid == "{00000008-0000-0010-8000-00AA00389B71}") + return QStringLiteral("Digital Theater Systems Audio (DTS)"); + else if (guid == "{00000003-0000-0010-8000-00AA00389B71}") + return QStringLiteral("IEEE Float Audio"); + else if (guid == "{00000055-0000-0010-8000-00AA00389B71}") + return QStringLiteral("MPEG Audio Layer-3 (MP3)"); + else if (guid == "{00000050-0000-0010-8000-00AA00389B71}") + return QStringLiteral("MPEG-1 Audio"); + else if (guid == "{2E6D7033-767A-494D-B478-F29D25DC9037}") + return QStringLiteral("MPEG Audio Layer 1/2"); + else if (guid == "{0000000A-0000-0010-8000-00AA00389B71}") + return QStringLiteral("Windows Media Audio Voice"); + else if (guid == "{00000001-0000-0010-8000-00AA00389B71}") + return QStringLiteral("Uncompressed PCM Audio"); + else if (guid == "{00000164-0000-0010-8000-00AA00389B71}") + return QStringLiteral("Windows Media Audio 9 SPDIF"); + else if (guid == "{00000161-0000-0010-8000-00AA00389B71}") + return QStringLiteral("Windows Media Audio 8 (WMA2)"); + else if (guid == "{00000162-0000-0010-8000-00AA00389B71}") + return QStringLiteral("Windows Media Audio 9 (WMA3"); + else if (guid == "{00000163-0000-0010-8000-00AA00389B71}") + return QStringLiteral("Windows Media Audio 9 Lossless"); + else if (guid == "{8D2FD10B-5841-4a6b-8905-588FEC1ADED9}") + return QStringLiteral("Vorbis"); + else if (guid == "{0000F1AC-0000-0010-8000-00AA00389B71}") + return QStringLiteral("Free Lossless Audio Codec (FLAC)"); + else if (guid == "{00006C61-0000-0010-8000-00AA00389B71}") + return QStringLiteral("Apple Lossless Audio Codec (ALAC)"); + + // Video formats + if (guid == "{35327664-0000-0010-8000-00AA00389B71}") + return QStringLiteral("DVCPRO 25 (DV25)"); + else if (guid == "{30357664-0000-0010-8000-00AA00389B71}") + return QStringLiteral("DVCPRO 50 (DV50)"); + else if (guid == "{20637664-0000-0010-8000-00AA00389B71}") + return QStringLiteral("DVC/DV Video"); + else if (guid == "{31687664-0000-0010-8000-00AA00389B71}") + return QStringLiteral("DVCPRO 100 (DVH1)"); + else if (guid == "{64687664-0000-0010-8000-00AA00389B71}") + return QStringLiteral("HD-DVCR (DVHD)"); + else if (guid == "{64737664-0000-0010-8000-00AA00389B71}") + return QStringLiteral("SDL-DVCR (DVSD)"); + else if (guid == "{6C737664-0000-0010-8000-00AA00389B71}") + return QStringLiteral("SD-DVCR (DVSL)"); + else if (guid == "{33363248-0000-0010-8000-00AA00389B71}") + return QStringLiteral("H.263 Video"); + else if (guid == "{34363248-0000-0010-8000-00AA00389B71}") + return QStringLiteral("H.264 Video"); + else if (guid == "{35363248-0000-0010-8000-00AA00389B71}") + return QStringLiteral("H.265 Video"); + else if (guid == "{43564548-0000-0010-8000-00AA00389B71}") + return QStringLiteral("High Efficiency Video Coding (HEVC)"); + else if (guid == "{3253344D-0000-0010-8000-00AA00389B71}") + return QStringLiteral("MPEG-4 part 2 Video (M4S2)"); + else if (guid == "{47504A4D-0000-0010-8000-00AA00389B71}") + return QStringLiteral("Motion JPEG (MJPG)"); + else if (guid == "{3334504D-0000-0010-8000-00AA00389B71}") + return QStringLiteral("Microsoft MPEG 4 version 3 (MP43)"); + else if (guid == "{5334504D-0000-0010-8000-00AA00389B71}") + return QStringLiteral("ISO MPEG 4 version 1 (MP4S)"); + else if (guid == "{5634504D-0000-0010-8000-00AA00389B71}") + return QStringLiteral("MPEG-4 part 2 Video (MP4V)"); + else if (guid == "{E06D8026-DB46-11CF-B4D1-00805F6CBBEA}") + return QStringLiteral("MPEG-2 Video"); + else if (guid == "{3147504D-0000-0010-8000-00AA00389B71}") + return QStringLiteral("MPEG-1 Video"); + else if (guid == "{3153534D-0000-0010-8000-00AA00389B71}") + return QStringLiteral("Windows Media Screen 1 (MSS1)"); + else if (guid == "{3253534D-0000-0010-8000-00AA00389B71}") + return QStringLiteral("Windows Media Video 9 Screen (MSS2)"); + else if (guid == "{31564D57-0000-0010-8000-00AA00389B71}") + return QStringLiteral("Windows Media Video 7 (WMV1)"); + else if (guid == "{32564D57-0000-0010-8000-00AA00389B71}") + return QStringLiteral("Windows Media Video 8 (WMV2)"); + else if (guid == "{33564D57-0000-0010-8000-00AA00389B71}") + return QStringLiteral("Windows Media Video 9 (WMV3)"); + else if (guid == "{31435657-0000-0010-8000-00AA00389B71}") + return QStringLiteral("Windows Media Video VC1 (WVC1)"); + else if (guid == "{30385056-0000-0010-8000-00AA00389B71}") + return QStringLiteral("VP8 Video"); + else if (guid == "{30395056-0000-0010-8000-00AA00389B71}") + return QStringLiteral("VP9 Video"); + + else + return QStringLiteral("Unknown codec"); +} + typedef HRESULT (WINAPI *q_SHCreateItemFromParsingName)(PCWSTR, IBindCtx *, const GUID&, void **); static q_SHCreateItemFromParsingName sHCreateItemFromParsingName = 0; #endif @@ -498,6 +602,10 @@ void DirectShowMetaDataControl::updateMetadata(IFilterGraph2 *graph, IBaseFilter m_metadata.insert(QMediaMetaData::Director, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_Writer)) { m_metadata.insert(QMediaMetaData::Writer, convertValue(var)); + } else if (IsEqualPropertyKey(key, PKEY_Video_Compression)) { + m_metadata.insert(QMediaMetaData::VideoCodec, nameForGUIDString(convertValue(var).toString())); + } else if (IsEqualPropertyKey(key, PKEY_Audio_Format)) { + m_metadata.insert(QMediaMetaData::AudioCodec, nameForGUIDString(convertValue(var).toString())); } PropVariantClear(&var); -- cgit v1.2.1 From 70365a798c95db8ccf2c52def3f2d0da6199a8cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Mon, 12 Dec 2016 16:10:09 +0100 Subject: Android: Add logging category Adds logging category for the android plugin. Change-Id: I0b0868fa7da4ce5426b3682ab40c4317afb79cd0 Reviewed-by: Yoann Lopes --- src/plugins/android/src/common/common.pri | 1 + src/plugins/android/src/common/qandroidglobal.h | 52 ++++++++++++++++++++++ .../android/src/qandroidmediaserviceplugin.cpp | 6 ++- 3 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 src/plugins/android/src/common/qandroidglobal.h (limited to 'src') diff --git a/src/plugins/android/src/common/common.pri b/src/plugins/android/src/common/common.pri index 9c741bd94..1b02b99ea 100644 --- a/src/plugins/android/src/common/common.pri +++ b/src/plugins/android/src/common/common.pri @@ -1,6 +1,7 @@ INCLUDEPATH += $$PWD HEADERS += \ + $$PWD/qandroidglobal.h \ $$PWD/qandroidvideooutput.h \ $$PWD/qandroidmultimediautils.h diff --git a/src/plugins/android/src/common/qandroidglobal.h b/src/plugins/android/src/common/qandroidglobal.h new file mode 100644 index 000000000..e7342be97 --- /dev/null +++ b/src/plugins/android/src/common/qandroidglobal.h @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QANDROIDGLOBAL_H +#define QANDROIDGLOBAL_H + +#include +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(qtAndroidMediaPlugin) + +QT_END_NAMESPACE + +#endif // QANDROIDGLOBAL_H diff --git a/src/plugins/android/src/qandroidmediaserviceplugin.cpp b/src/plugins/android/src/qandroidmediaserviceplugin.cpp index 0de231c9d..f441baf0a 100644 --- a/src/plugins/android/src/qandroidmediaserviceplugin.cpp +++ b/src/plugins/android/src/qandroidmediaserviceplugin.cpp @@ -50,10 +50,12 @@ #include "androidmultimediautils.h" #include "androidmediarecorder.h" #include "androidsurfaceview.h" -#include +#include "qandroidglobal.h" QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(qtAndroidMediaPlugin, "qt.multimedia.plugins.android") + QAndroidMediaServicePlugin::QAndroidMediaServicePlugin() { } @@ -72,7 +74,7 @@ QMediaService *QAndroidMediaServicePlugin::create(const QString &key) return new QAndroidCaptureService(key); } - qWarning() << "Android service plugin: unsupported key:" << key; + qCWarning(qtAndroidMediaPlugin) << "Android service plugin: unsupported key:" << key; return 0; } -- cgit v1.2.1 From 4da8ca2397f0b5ca87c1915fc29e185d57e9020c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Mon, 12 Dec 2016 18:27:33 +0100 Subject: Android: Add convenience method for checking and requesting permissions This will be used to check and request permissions at run-time. Task-number: QTBUG-55992 Change-Id: I344859aeb05fecf09ac46064e9452787d615a8a1 Reviewed-by: Yoann Lopes --- .../android/src/common/qandroidmultimediautils.cpp | 29 ++++++++++++++++++++++ .../android/src/common/qandroidmultimediautils.h | 2 ++ 2 files changed, 31 insertions(+) (limited to 'src') diff --git a/src/plugins/android/src/common/qandroidmultimediautils.cpp b/src/plugins/android/src/common/qandroidmultimediautils.cpp index c7a16dcf0..a4a7f773d 100644 --- a/src/plugins/android/src/common/qandroidmultimediautils.cpp +++ b/src/plugins/android/src/common/qandroidmultimediautils.cpp @@ -38,8 +38,11 @@ ****************************************************************************/ #include "qandroidmultimediautils.h" +#include "qandroidglobal.h" #include +#include +#include QT_BEGIN_NAMESPACE @@ -110,4 +113,30 @@ AndroidCamera::ImageFormat qt_androidImageFormatFromPixelFormat(QVideoFrame::Pix } } +bool qt_androidRequestPermission(const QString &key) +{ + using namespace QtAndroidPrivate; + + if (androidSdkVersion() < 23) + return true; + + PermissionsResult res = checkPermission(key); + if (res == PermissionsResult::Granted) // Permission already granted? + return true; + + QJNIEnvironmentPrivate env; + const auto &results = requestPermissionsSync(env, QStringList() << key); + if (!results.contains(key)) { + qCWarning(qtAndroidMediaPlugin, "No permission found for key: %s", qPrintable(key)); + return false; + } + + if (results[key] == PermissionsResult::Denied) { + qCDebug(qtAndroidMediaPlugin, "%s - Permission denied by user!", qPrintable(key)); + return false; + } + + return true; +} + QT_END_NAMESPACE diff --git a/src/plugins/android/src/common/qandroidmultimediautils.h b/src/plugins/android/src/common/qandroidmultimediautils.h index 0e811ecb8..0a837ae3c 100644 --- a/src/plugins/android/src/common/qandroidmultimediautils.h +++ b/src/plugins/android/src/common/qandroidmultimediautils.h @@ -55,6 +55,8 @@ bool qt_sizeLessThan(const QSize &s1, const QSize &s2); QVideoFrame::PixelFormat qt_pixelFormatFromAndroidImageFormat(AndroidCamera::ImageFormat f); AndroidCamera::ImageFormat qt_androidImageFormatFromPixelFormat(QVideoFrame::PixelFormat f); +bool qt_androidRequestPermission(const QString &key); + QT_END_NAMESPACE #endif // QANDROIDMULTIMEDIAUTILS_H -- cgit v1.2.1 From fb1c0b7448ca48c1b1f21dfc1cd7cfed8b7d8c07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Wed, 15 Mar 2017 13:51:14 +0100 Subject: GStreamer: Fix position value at EndOfMedia Return the duration when we're at the EndOfMedia Task-number: QTBUG-59604 Change-Id: If057257a65d73aa456dd7dc52b6cb624dd4712d3 Reviewed-by: Yoann Lopes --- src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp index 54b31627e..0bfe76f2f 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp @@ -119,6 +119,9 @@ QMediaPlayerResourceSetInterface* QGstreamerPlayerControl::resources() const qint64 QGstreamerPlayerControl::position() const { + if (m_mediaStatus == QMediaPlayer::EndOfMedia) + return m_session->duration(); + return m_pendingSeekPosition != -1 ? m_pendingSeekPosition : m_session->position(); } -- cgit v1.2.1 From ceedee9a933697ef6a3db758adb57e03f42189eb Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Thu, 23 Mar 2017 18:23:35 +0100 Subject: GStreamer: improve the list of default recording formats Add some common codec combinations such as MP4/H.264/AAC or with alternative audio codecs such as MP3 or AC-3. Change-Id: If67c68112d0f170a1391bef750e2bc8fc0d246de Reviewed-by: Christian Stromme --- .../gstreamer/camerabin/camerabinrecorder.cpp | 35 ++++++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/plugins/gstreamer/camerabin/camerabinrecorder.cpp b/src/plugins/gstreamer/camerabin/camerabinrecorder.cpp index e9e8e0f71..b3505231b 100644 --- a/src/plugins/gstreamer/camerabin/camerabinrecorder.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinrecorder.cpp @@ -153,12 +153,41 @@ void CameraBinRecorder::applySettings() videoEncoderControl->videoSettings().codec().isEmpty()) { QList candidates; + + // By order of preference + + // .mp4 (h264, AAC) + candidates.append(QStringList() << "video/quicktime, variant=(string)iso" << "video/x-h264" << "audio/mpeg, mpegversion=(int)4"); + + // .mp4 (h264, AC3) + candidates.append(QStringList() << "video/quicktime, variant=(string)iso" << "video/x-h264" << "audio/x-ac3"); + + // .mp4 (h264, MP3) + candidates.append(QStringList() << "video/quicktime, variant=(string)iso" << "video/x-h264" << "audio/mpeg, mpegversion=(int)1, layer=(int)3"); + + // .mkv (h264, AAC) candidates.append(QStringList() << "video/x-matroska" << "video/x-h264" << "audio/mpeg, mpegversion=(int)4"); + + // .mkv (h264, AC3) + candidates.append(QStringList() << "video/x-matroska" << "video/x-h264" << "audio/x-ac3"); + + // .mkv (h264, MP3) + candidates.append(QStringList() << "video/x-matroska" << "video/x-h264" << "audio/mpeg, mpegversion=(int)1, layer=(int)3"); + + // .mov (h264, AAC) + candidates.append(QStringList() << "video/quicktime" << "video/x-h264" << "audio/mpeg, mpegversion=(int)4"); + + // .mov (h264, MP3) + candidates.append(QStringList() << "video/quicktime" << "video/x-h264" << "audio/mpeg, mpegversion=(int)1, layer=(int)3"); + + // .webm (VP8, Vorbis) candidates.append(QStringList() << "video/webm" << "video/x-vp8" << "audio/x-vorbis"); + + // .ogg (Theora, Vorbis) candidates.append(QStringList() << "application/ogg" << "video/x-theora" << "audio/x-vorbis"); - candidates.append(QStringList() << "video/quicktime" << "video/x-h264" << "audio/mpeg, mpegversion=(int)4"); - candidates.append(QStringList() << "video/quicktime" << "video/x-h264" << "audio/mpeg"); - candidates.append(QStringList() << "video/x-msvideo" << "video/x-divx" << "audio/mpeg"); + + // .avi (DivX, MP3) + candidates.append(QStringList() << "video/x-msvideo" << "video/x-divx" << "audio/mpeg, mpegversion=(int)1, layer=(int)3"); for (const QStringList &candidate : qAsConst(candidates)) { if (containerControl->supportedContainers().contains(candidate[0]) && -- cgit v1.2.1 From 954a85a1b3fb704a2b8590467e010300faee6798 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Mon, 12 Dec 2016 18:47:09 +0100 Subject: Android: Add run-time permission check for recording Check and request permission to record audio if needed. [ChangeLog][Android] Added run-time permission checks for media-recording. Task-number: QTBUG-55992 Change-Id: I781e5a5447f1ad03c069b2171637525ae9108d78 Reviewed-by: Yoann Lopes --- src/plugins/android/src/mediacapture/qandroidcapturesession.cpp | 9 +++++++++ src/plugins/android/src/wrappers/jni/androidmediarecorder.cpp | 6 ++++++ src/plugins/android/src/wrappers/jni/androidmediarecorder.h | 1 + 3 files changed, 16 insertions(+) (limited to 'src') diff --git a/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp b/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp index 9e38c8539..a5aff51cd 100644 --- a/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp @@ -44,6 +44,7 @@ #include "androidmultimediautils.h" #include "qandroidmultimediautils.h" #include "qandroidvideooutput.h" +#include "qandroidglobal.h" QT_BEGIN_NAMESPACE @@ -177,6 +178,14 @@ void QAndroidCaptureSession::start() m_mediaRecorder->release(); delete m_mediaRecorder; } + + + if (!AndroidMediaRecorder::requestRecordingPermission()) { + setStatus(QMediaRecorder::UnavailableStatus); + Q_EMIT error(QMediaRecorder::ResourceError, QLatin1String("Permission denied.")); + return; + } + m_mediaRecorder = new AndroidMediaRecorder; connect(m_mediaRecorder, SIGNAL(error(int,int)), this, SLOT(onError(int,int))); connect(m_mediaRecorder, SIGNAL(info(int,int)), this, SLOT(onInfo(int,int))); diff --git a/src/plugins/android/src/wrappers/jni/androidmediarecorder.cpp b/src/plugins/android/src/wrappers/jni/androidmediarecorder.cpp index a707dd903..d0101411b 100644 --- a/src/plugins/android/src/wrappers/jni/androidmediarecorder.cpp +++ b/src/plugins/android/src/wrappers/jni/androidmediarecorder.cpp @@ -42,6 +42,8 @@ #include "androidcamera.h" #include "androidsurfacetexture.h" #include "androidsurfaceview.h" +#include "qandroidglobal.h" +#include "qandroidmultimediautils.h" #include #include @@ -381,6 +383,10 @@ void AndroidMediaRecorder::setSurfaceHolder(AndroidSurfaceHolder *holder) } } +bool AndroidMediaRecorder::requestRecordingPermission() +{ + return qt_androidRequestPermission(QLatin1String("android.permission.RECORD_AUDIO")); +} bool AndroidMediaRecorder::initJNI(JNIEnv *env) { diff --git a/src/plugins/android/src/wrappers/jni/androidmediarecorder.h b/src/plugins/android/src/wrappers/jni/androidmediarecorder.h index e4b3a80ea..cd2d164d8 100644 --- a/src/plugins/android/src/wrappers/jni/androidmediarecorder.h +++ b/src/plugins/android/src/wrappers/jni/androidmediarecorder.h @@ -160,6 +160,7 @@ public: void setSurfaceTexture(AndroidSurfaceTexture *texture); void setSurfaceHolder(AndroidSurfaceHolder *holder); + static bool requestRecordingPermission(); static bool initJNI(JNIEnv *env); Q_SIGNALS: -- cgit v1.2.1 From d5d7dcfb15c0b5c5e9009b83fba922ea0b7e86f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Tue, 13 Dec 2016 17:26:18 +0100 Subject: OpenSL ES: Added run-time permission checks for recording on Android Make sure that we have permission to record before starting a recording session. [ChangeLog][OpenSL ES][Android] Added run-time permission checks for recording on Android. Task-number: QTBUG-55992 Change-Id: Iab7416384336975fdf4de8024f02ab2414033163 Reviewed-by: Yoann Lopes --- src/plugins/opensles/qopenslesaudioinput.cpp | 31 ++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'src') diff --git a/src/plugins/opensles/qopenslesaudioinput.cpp b/src/plugins/opensles/qopenslesaudioinput.cpp index 30860650b..c3f5ed422 100644 --- a/src/plugins/opensles/qopenslesaudioinput.cpp +++ b/src/plugins/opensles/qopenslesaudioinput.cpp @@ -46,6 +46,8 @@ #ifdef ANDROID #include +#include +#include #endif QT_BEGIN_NAMESPACE @@ -55,6 +57,32 @@ QT_BEGIN_NAMESPACE #define MINIMUM_PERIOD_TIME_MS 5 #ifdef ANDROID +static bool hasRecordingPermission() +{ + using namespace QtAndroidPrivate; + if (androidSdkVersion() < 23) + return true; + + const QString key(QLatin1String("android.permission.RECORD_AUDIO")); + PermissionsResult res = checkPermission(key); + if (res == PermissionsResult::Granted) // Permission already granted? + return true; + + QJNIEnvironmentPrivate env; + const auto &results = requestPermissionsSync(env, QStringList() << key); + if (!results.contains(key)) { + qWarning("No permission found for key: %s", qPrintable(key)); + return false; + } + + if (results[key] == PermissionsResult::Denied) { + qDebug("%s - Permission denied by user!", qPrintable(key)); + return false; + } + + return true; +} + static void bufferQueueCallback(SLAndroidSimpleBufferQueueItf, void *context) #else static void bufferQueueCallback(SLBufferQueueItf, void *context) @@ -179,6 +207,9 @@ QIODevice *QOpenSLESAudioInput::start() bool QOpenSLESAudioInput::startRecording() { + if (!hasRecordingPermission()) + return false; + m_processedBytes = 0; m_clockStamp.restart(); m_lastNotifyTime = 0; -- cgit v1.2.1