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/plugins') 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.3 From 703f0ec4cba205e8adae8cf36c29ee62149941fb Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Tue, 21 Mar 2017 09:19:46 +0100 Subject: wasapi: Define CLASSIC_APP_BUILD for desktop build This partly reverts 7e48870c182e66a8408bbcb4c9469d751a777daa. The define is still needed for successful compilation of the wasapi backend on windows desktop. Change-Id: I1be1c08f5dd4a4cf5e0fa2211f0f8b330b0204a9 Reviewed-by: Oliver Wolff --- src/plugins/wasapi/wasapi.pro | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/wasapi/wasapi.pro b/src/plugins/wasapi/wasapi.pro index 63409ce72..11dfd8abe 100644 --- a/src/plugins/wasapi/wasapi.pro +++ b/src/plugins/wasapi/wasapi.pro @@ -20,7 +20,10 @@ OTHER_FILES += \ LIBS += Mmdevapi.lib -win32-*: LIBS += runtimeobject.lib +win32-* { + DEFINES += CLASSIC_APP_BUILD + LIBS += runtimeobject.lib +} PLUGIN_TYPE = audio PLUGIN_CLASS_NAME = QWasapiPlugin -- cgit v1.2.3 From 819dbf9432e1062cc952b4fdfa1518ee16c15f1b Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Mon, 20 Mar 2017 15:28:42 +0100 Subject: winrt: Fix video playback without autoplay enabled We have to ensure that a device handle is present and valid when calling setSource. Otherwise the engine switches into an error state when trying to continue loading. With autoPlay enabled that implicitly happened. Task-number: QTBUG-58152 Change-Id: Id504efd9b1b77b418ae05baed3ac0c52852cf49e Reviewed-by: Oliver Wolff --- src/plugins/winrt/qwinrtmediaplayercontrol.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/winrt/qwinrtmediaplayercontrol.cpp b/src/plugins/winrt/qwinrtmediaplayercontrol.cpp index a4df6306f..9fd48fd76 100644 --- a/src/plugins/winrt/qwinrtmediaplayercontrol.cpp +++ b/src/plugins/winrt/qwinrtmediaplayercontrol.cpp @@ -786,8 +786,12 @@ void QWinRTMediaPlayerControl::setMedia(const QMediaContent &media, QIODevice *s if (d->stream) { hr = d->engine->SetSourceFromByteStream(d->streamProvider.Get(), reinterpret_cast(urlString.data())); - if (FAILED(hr)) + if (FAILED(hr)) { emit error(QMediaPlayer::ResourceError, qt_error_string(hr)); + return; + } + if (d->videoRenderer) + d->videoRenderer->ensureReady(); return; } -- cgit v1.2.3 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/plugins') 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.3 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/plugins') 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.3 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/plugins') 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.3 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/plugins') 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.3 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/plugins') 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.3 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/plugins') 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.3 From 6de2c8aca6736550d87057b0a3f025464bf21246 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Wed, 8 Feb 2017 15:50:21 +0100 Subject: GStreamer: add QT_GSTREAMER_PLAYBIN_AUDIOSINK env variable Allows to set a custom audio sink to be used by the media player, instead of the default 'autoaudiosink'. Change-Id: I13ea93a787ba6412a42bf48ecf7d3a822060cbe4 Reviewed-by: Christian Stromme --- src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp index cf2ec6262..cc7aef367 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp @@ -160,7 +160,8 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent) } g_object_set(G_OBJECT(m_playbin), "flags", flags, NULL); - GstElement *audioSink = gst_element_factory_make("autoaudiosink", "audiosink"); + const QByteArray envAudioSink = qgetenv("QT_GSTREAMER_PLAYBIN_AUDIOSINK"); + GstElement *audioSink = gst_element_factory_make(envAudioSink.isEmpty() ? "autoaudiosink" : envAudioSink, "audiosink"); if (audioSink) { if (usePlaybinVolume()) { m_audioSink = audioSink; -- cgit v1.2.3 From 021e8989308fba30425e7a0f34f4e176a8aa3ccf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Tue, 4 Apr 2017 13:10:02 +0200 Subject: Android: Fix camera preview orientation Before API level 24 the display orientation (the preview) was always set to 0. On newer versions of Android the clockwise rotation is set to be either 0 or 180, depending on the hardware. Since we don't want Android to apply transformation on our surface, we'll just enforce that the display orientation is always set to 0. Task-number: QTBUG-56536 Change-Id: Ie1aacda97540d5c97e6cbd8edb2afc53e7041e1e Reviewed-by: Andy Shaw --- .../android/src/mediacapture/qandroidcamerasession.cpp | 6 ++++++ src/plugins/android/src/wrappers/jni/androidcamera.cpp | 12 ++++++++++++ src/plugins/android/src/wrappers/jni/androidcamera.h | 1 + 3 files changed, 19 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp index 8663f8c5f..b0dd7d900 100644 --- a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp @@ -52,6 +52,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -443,6 +444,11 @@ bool QAndroidCameraSession::startPreview() AndroidMultimediaUtils::enableOrientationListener(true); + // Before API level 24 the orientation was always 0, which is what we're expecting, so + // we'll enforce that here. + if (QtAndroidPrivate::androidSdkVersion() > 23) + m_camera->setDisplayOrientation(0); + m_camera->startPreview(); m_previewStarted = true; diff --git a/src/plugins/android/src/wrappers/jni/androidcamera.cpp b/src/plugins/android/src/wrappers/jni/androidcamera.cpp index 76d3ffb44..0f2a43531 100644 --- a/src/plugins/android/src/wrappers/jni/androidcamera.cpp +++ b/src/plugins/android/src/wrappers/jni/androidcamera.cpp @@ -196,6 +196,7 @@ public: Q_INVOKABLE void updatePreviewSize(); Q_INVOKABLE bool setPreviewTexture(void *surfaceTexture); Q_INVOKABLE bool setPreviewDisplay(void *surfaceHolder); + Q_INVOKABLE void setDisplayOrientation(int degrees); Q_INVOKABLE bool isZoomSupported(); Q_INVOKABLE int getMaxZoom(); @@ -481,6 +482,12 @@ bool AndroidCamera::setPreviewDisplay(AndroidSurfaceHolder *surfaceHolder) return ok; } +void AndroidCamera::setDisplayOrientation(int degrees) +{ + Q_D(AndroidCamera); + QMetaObject::invokeMethod(d, "setDisplayOrientation", Qt::QueuedConnection, Q_ARG(int, degrees)); +} + bool AndroidCamera::isZoomSupported() { Q_D(AndroidCamera); @@ -1079,6 +1086,11 @@ bool AndroidCameraPrivate::setPreviewDisplay(void *surfaceHolder) return !exceptionCheckAndClear(env); } +void AndroidCameraPrivate::setDisplayOrientation(int degrees) +{ + m_camera.callMethod("setDisplayOrientation", "(I)V", degrees); +} + bool AndroidCameraPrivate::isZoomSupported() { QMutexLocker parametersLocker(&m_parametersMutex); diff --git a/src/plugins/android/src/wrappers/jni/androidcamera.h b/src/plugins/android/src/wrappers/jni/androidcamera.h index 1a59ff3c7..e58a81f8e 100644 --- a/src/plugins/android/src/wrappers/jni/androidcamera.h +++ b/src/plugins/android/src/wrappers/jni/androidcamera.h @@ -136,6 +136,7 @@ public: void setPreviewSize(const QSize &size); bool setPreviewTexture(AndroidSurfaceTexture *surfaceTexture); bool setPreviewDisplay(AndroidSurfaceHolder *surfaceHolder); + void setDisplayOrientation(int degrees); bool isZoomSupported(); int getMaxZoom(); -- cgit v1.2.3