diff options
author | Sergio Ahumada <sahumada@blackberry.com> | 2014-06-14 21:59:24 +0200 |
---|---|---|
committer | Sergio Ahumada <sahumada@blackberry.com> | 2014-06-14 21:59:24 +0200 |
commit | d691f5ca2b6749006673e199b1d668a6daa9b990 (patch) | |
tree | eacad24192e1e0c492320e14bdfd7c3c203a01e0 | |
parent | d415d3256d055ef6fd7dad5c0497ecfaa56ee64d (diff) | |
parent | 150ff6662de1312e3ba9d000895d80dd5805ea5b (diff) |
Merge remote-tracking branch 'origin/5.3' into dev
Conflicts:
.qmake.conf
Change-Id: Iecd8d7b94e52a8981526b12cffa40e99870ba62f
168 files changed, 2755 insertions, 2724 deletions
diff --git a/examples/multimedia/audiodevices/doc/src/audiodevices.qdoc b/examples/multimedia/audiodevices/doc/src/audiodevices.qdoc index d75584485..bdf1590fe 100644 --- a/examples/multimedia/audiodevices/doc/src/audiodevices.qdoc +++ b/examples/multimedia/audiodevices/doc/src/audiodevices.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -29,8 +29,8 @@ \example audiodevices \title Audio Devices Example \ingroup multimedia_examples - \brief The Audio Devices example shows the application of the audio devices APIs - + \brief The Audio Devices example shows the application of the audio devices + APIs. This example shows how to create a simple application to list and test the configuration for the various audio devices available on the device @@ -38,6 +38,5 @@ \image audiodevices.png + \include examples-run.qdocinc */ - - diff --git a/examples/multimedia/audioengine/doc/src/audioengine.qdoc b/examples/multimedia/audioengine/doc/src/audioengine.qdoc index c83247df1..52a377130 100644 --- a/examples/multimedia/audioengine/doc/src/audioengine.qdoc +++ b/examples/multimedia/audioengine/doc/src/audioengine.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -30,10 +30,10 @@ \title AudioEngine Example \ingroup multimedia_examples \brief The Audio Engine example demonstrates 3D sound control using - the QtAudioEngine API. + the Qt Audio Engine API. - \image audioengine.png + The Audio Engine example demonstrates 3D sound control using the + \l{Qt Audio Engine QML Types}{Qt Audio Engine} API. + \include examples-run.qdocinc */ - - diff --git a/examples/multimedia/audioinput/doc/src/audioinput.qdoc b/examples/multimedia/audioinput/doc/src/audioinput.qdoc index 39ef26156..11a513a99 100644 --- a/examples/multimedia/audioinput/doc/src/audioinput.qdoc +++ b/examples/multimedia/audioinput/doc/src/audioinput.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -37,7 +37,8 @@ Qt provides the QAudioInput class to enable audio functionality within a standard application user interface. - This example calculates the maximum linear value of the input audio from the microphone and displays the output. -*/ - + This example calculates the maximum linear value of the input audio from the + microphone and displays the output. + \include examples-run.qdocinc +*/ diff --git a/examples/multimedia/audiooutput/doc/src/audiooutput.qdoc b/examples/multimedia/audiooutput/doc/src/audiooutput.qdoc index bc79e6a5d..60c9d00d4 100644 --- a/examples/multimedia/audiooutput/doc/src/audiooutput.qdoc +++ b/examples/multimedia/audiooutput/doc/src/audiooutput.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -31,13 +31,14 @@ \ingroup multimedia_examples \brief The Audio Output Example show the use of the QAudioOutput API. - The example demonstrates the basic use cases of the QAudioOutput class. + The example demonstrates the basic use cases of the QAudioOutput class from + \l{Qt Multimedia}. \image audiooutput-example.png This example provides a tone generator to supply continuous audio playback. The first button allows pause and resume of the playback, and the second button allows toggling between push and pull modes of operation. -*/ - + \include examples-run.qdocinc +*/ diff --git a/examples/multimedia/audiorecorder/doc/src/audiorecorder.qdoc b/examples/multimedia/audiorecorder/doc/src/audiorecorder.qdoc index 8453ea34e..35f6c0511 100644 --- a/examples/multimedia/audiorecorder/doc/src/audiorecorder.qdoc +++ b/examples/multimedia/audiorecorder/doc/src/audiorecorder.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -34,6 +34,12 @@ It demonstrates the discovery of the supported devices and codecs and the use of recording functions in the QAudioRecorder class. + \image audiorecorder.png + + \include examples-run.qdocinc + + \section1 Displaying the Window and Audio Settings + We display a window for the user to select the appropriate audio input, codec, container, and sample rate. Allow a setting of either quality or bitrate. Finally, the output file can be selected and recording can be @@ -49,7 +55,7 @@ \l{QMultimedia::NormalQuality}, while the bitrates are hardcoded into the list. - \image audiorecorder.png + \section1 Recording Audio To record audio we simply create a QAudioRecorder object. @@ -96,5 +102,3 @@ ui->statusbar->showMessage(tr("Recorded %1 sec").arg(duration / 1000)); \endcode */ - - diff --git a/examples/multimedia/declarative-camera/doc/src/declarative-camera.qdoc b/examples/multimedia/declarative-camera/doc/src/declarative-camera.qdoc index 02e77854c..8c87b1d46 100644 --- a/examples/multimedia/declarative-camera/doc/src/declarative-camera.qdoc +++ b/examples/multimedia/declarative-camera/doc/src/declarative-camera.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -34,35 +34,22 @@ or video. \image qml-camera.png -This example demonstrates how to use the Qt Multimedia QML API to access -camera functions. It shows how to change settings and to capture images. +This example demonstrates how to use the +\l{Qt Multimedia QML Types}{Qt Multimedia QML API} to access camera functions. +It shows how to change settings and to capture images. + +\include examples-run.qdocinc + +\section1 Application Structure Most of the QML code supports the user interface for this application with the camera types being mostly found in \e {declarative-camera.qml} and \e {CaptureControls.qml}. -In \e {declarative-camera.qml} the \l Camera is initialized with an id -of \e {camera}, a photo preview is setup, states are implemented for image -preview or capture and \l CaptureControls is initialized. The initial -\e state is \e PhotoCapture. \l CameraCapture includes a handler, \e onImageCaptured, -for the \l {imageCaptured} signal. The handler sets up the application to process -the preview including a change in the user interface state. The \l PhotoPreview -becomes visible with any key press being picked up by the handler -in PhotoPreview and returning the state to \e PhotoCapture. - -\e CaptureControls, which is implemented in \e {CaptureControls.qml}, +CaptureControls, which is implemented in \e {CaptureControls.qml}, generates a column on the right hand side of the screen which includes control -buttons for \e focus (not initially visible), \e {capture}, \e {flash modes}, -\e {white balance}, \e {exposure compensation}, and if a preview is -available a \e {preview} button. The last button exits from the application. - -When the Capture button is pressed the \e onClicked handler calls -\l {Camera::captureImage()}{captureImage()} - - - - - - +buttons for focus (not initially visible), capture, flash modes, +white balance, exposure compensation, and if a preview is +available, a preview button. The last button exits from the application. */ diff --git a/examples/multimedia/declarative-radio/doc/src/declarative-radio.qdoc b/examples/multimedia/declarative-radio/doc/src/declarative-radio.qdoc index 99c41114a..bb1a5d89f 100644 --- a/examples/multimedia/declarative-radio/doc/src/declarative-radio.qdoc +++ b/examples/multimedia/declarative-radio/doc/src/declarative-radio.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -31,8 +31,8 @@ \brief Demonstrates the radio functionality \ingroup multimedia_examples - This examples uses the Qt Multimedia Radio QML type to list the available - channels on the FM frequency. -*/ - + This examples uses the \l{Qt Multimedia} \l Radio QML type to list the + available channels on the FM frequency. + \include examples-run.qdocinc +*/ diff --git a/examples/multimedia/spectrum/doc/src/spectrum.qdoc b/examples/multimedia/spectrum/doc/src/spectrum.qdoc index 280838956..3c846afdc 100644 --- a/examples/multimedia/spectrum/doc/src/spectrum.qdoc +++ b/examples/multimedia/spectrum/doc/src/spectrum.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -59,6 +59,6 @@ (FFT) of a segment of audio data. An open-source library, \l{http://ldesoras.free.fr/prod.html}{FFTReal}, against which the application is dynamically linked, is used to compute the transform. -*/ - + \include examples-run.qdocinc +*/ diff --git a/examples/multimedia/video/doc/images/qmlvideofx-camera-glow.jpg b/examples/multimedia/video/doc/images/qmlvideofx-camera-glow.jpg Binary files differnew file mode 100644 index 000000000..777ed4ffc --- /dev/null +++ b/examples/multimedia/video/doc/images/qmlvideofx-camera-glow.jpg diff --git a/examples/multimedia/video/doc/images/qmlvideofx-camera-glow.png b/examples/multimedia/video/doc/images/qmlvideofx-camera-glow.png Binary files differdeleted file mode 100644 index aca874b6c..000000000 --- a/examples/multimedia/video/doc/images/qmlvideofx-camera-glow.png +++ /dev/null diff --git a/examples/multimedia/video/doc/images/qmlvideofx-camera-magnify.png b/examples/multimedia/video/doc/images/qmlvideofx-camera-magnify.png Binary files differdeleted file mode 100644 index c3156ce96..000000000 --- a/examples/multimedia/video/doc/images/qmlvideofx-camera-magnify.png +++ /dev/null diff --git a/examples/multimedia/video/doc/images/qmlvideofx-camera-wobble.jpg b/examples/multimedia/video/doc/images/qmlvideofx-camera-wobble.jpg Binary files differnew file mode 100644 index 000000000..980ab0d15 --- /dev/null +++ b/examples/multimedia/video/doc/images/qmlvideofx-camera-wobble.jpg diff --git a/examples/multimedia/video/doc/images/qmlvideofx-effects-menu.jpg b/examples/multimedia/video/doc/images/qmlvideofx-effects-menu.jpg Binary files differnew file mode 100644 index 000000000..eb5b90321 --- /dev/null +++ b/examples/multimedia/video/doc/images/qmlvideofx-effects-menu.jpg diff --git a/examples/multimedia/video/doc/images/qmlvideofx-effects-menu.png b/examples/multimedia/video/doc/images/qmlvideofx-effects-menu.png Binary files differdeleted file mode 100644 index 507fd7384..000000000 --- a/examples/multimedia/video/doc/images/qmlvideofx-effects-menu.png +++ /dev/null diff --git a/examples/multimedia/video/doc/images/qmlvideofx-source-menu.png b/examples/multimedia/video/doc/images/qmlvideofx-source-menu.png Binary files differdeleted file mode 100644 index 661aaa73f..000000000 --- a/examples/multimedia/video/doc/images/qmlvideofx-source-menu.png +++ /dev/null diff --git a/examples/multimedia/video/doc/images/qmlvideofx-video-edgedetection.jpg b/examples/multimedia/video/doc/images/qmlvideofx-video-edgedetection.jpg Binary files differnew file mode 100644 index 000000000..35b36c036 --- /dev/null +++ b/examples/multimedia/video/doc/images/qmlvideofx-video-edgedetection.jpg diff --git a/examples/multimedia/video/doc/images/qmlvideofx-video-edgedetection.png b/examples/multimedia/video/doc/images/qmlvideofx-video-edgedetection.png Binary files differdeleted file mode 100644 index cedb314c5..000000000 --- a/examples/multimedia/video/doc/images/qmlvideofx-video-edgedetection.png +++ /dev/null diff --git a/examples/multimedia/video/doc/images/qmlvideofx-video-pagecurl.jpg b/examples/multimedia/video/doc/images/qmlvideofx-video-pagecurl.jpg Binary files differnew file mode 100644 index 000000000..5cd8d2bd2 --- /dev/null +++ b/examples/multimedia/video/doc/images/qmlvideofx-video-pagecurl.jpg diff --git a/examples/multimedia/video/doc/images/qmlvideofx-video-pagecurl.png b/examples/multimedia/video/doc/images/qmlvideofx-video-pagecurl.png Binary files differdeleted file mode 100644 index 5f5bdfb53..000000000 --- a/examples/multimedia/video/doc/images/qmlvideofx-video-pagecurl.png +++ /dev/null diff --git a/examples/multimedia/video/doc/src/qmlvideo.qdoc b/examples/multimedia/video/doc/src/qmlvideo.qdoc index 6d6833497..1e80cd176 100644 --- a/examples/multimedia/video/doc/src/qmlvideo.qdoc +++ b/examples/multimedia/video/doc/src/qmlvideo.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -34,8 +34,6 @@ resize; rotate; change aspect ratio) which can be applied to QML \l{VideoOutput} items. -\section1 Overview - This example demonstrates the various manipulations (move; resize; rotate; change aspect ratio) which can be applied to QML \l{VideoOutput} items. @@ -50,7 +48,9 @@ which moves across the \l{VideoOutput} item. \image qmlvideo-overlay.png -\section1 Application structure +\include examples-run.qdocinc + +\section1 Application Structure The \l{video/qmlvideo/qml/qmlvideo/main.qml} file creates a UI which includes the following items: @@ -127,7 +127,7 @@ instance, the embedded \l{video/qmlvideo/qml/qmlvideo/Content.qml}{Content} item creates either a \l{MediaPlayer} or a \l{Camera} item. -\section1 Calculating and displaying QML painting rate +\section1 Calculating and Displaying QML Painting Rate \input multimedia/doc/src/examples/video-qml-paint-rate.qdocinc @@ -145,4 +145,3 @@ object to a JavaScript function, which will eventually call frequencyItem.notify \printuntil SLOT(qmlFramePainted())); */ - diff --git a/examples/multimedia/video/doc/src/qmlvideofx.qdoc b/examples/multimedia/video/doc/src/qmlvideofx.qdoc index b7bd78ac7..edbd369c0 100644 --- a/examples/multimedia/video/doc/src/qmlvideofx.qdoc +++ b/examples/multimedia/video/doc/src/qmlvideofx.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -34,9 +34,11 @@ can be used to apply postprocessing effects, expressed in \c GLSL, to video and camera viewfinder content. +\include examples-run.qdocinc + \section1 Overview -This example shows how a \l {ShaderEffectItem} can be used to apply +This example shows how a \l {ShaderEffect} can be used to apply postprocessing effects, expressed in GLSL, to QML \l {VideoOutput} items. It also shows how native code can be combined with QML to implement more @@ -44,36 +46,30 @@ advanced functionality - in this case, C++ code is used to calculate the QML frame rate. This value is rendered in QML in a semi-transparent item overlaid on the video content. -Finally, this application demonstrates the use of different top-level QML -files to handle different physical screen sizes. On small-screen devices, -menus are by default hidden, and only appear when summoned by a gesture. -Large-screen devices show a more traditional layout in which menus are -displayed around the video content pane. - The following screenshots show shader effects being applied. In each case, the effect is implemented using a fragment shader. Here we see an edge detection algorithm being applied to a video clip -(\l{http://orange.blender.org/}{Elephant's Dream from blender.org}). -\image qmlvideofx-video-edgedetection.png +(\l{http://durian.blender.org/}{Sintel from blender.org}). +\image qmlvideofx-video-edgedetection.jpg This image shows a page curl effect, applied to the same video clip. -\image qmlvideofx-video-pagecurl.png +\image qmlvideofx-video-pagecurl.jpg Here we see a 'glow' effect (edge detection plus colour quantization) being applied to the camera viewfinder. -\image qmlvideofx-camera-glow.png +\image qmlvideofx-camera-glow.jpg -This image shows a 'lens magnification' effect applied to the viewfinder. -\image qmlvideofx-camera-magnify.png +This image shows a 'wobble' effect applied to the viewfinder. +\image qmlvideofx-camera-wobble.jpg The application includes many more effects than the ones shown here - look -for Effect*.qml files in the list above to see the full range. +for Effect*.qml files in the list of files below to see the full range. \section1 Application structure Shader effects can be applied to video or viewfinder content using -\l{ShaderEffectItem}, as shown in the following example, which applies +\l{ShaderEffect}, as shown in the following example, which applies a wiggly effect to the content: \code @@ -171,7 +167,7 @@ is based on the \l{ShaderEffect}: \skipto import \printuntil /^\}/ -The interface of the \l Effect allows for derived effects to specify the +The interface of Effect allows for derived effects to specify the number of parameters which they support (and therefore the number of sliders which should be displayed), and whether a vertical dividing line should be drawn between transformed and untransformed image regions. As an example, here is the @@ -195,11 +191,8 @@ vertical dividing line, which can be dragged left / right by the user. Finally, a \l{video/qmlvideofx/qml/qmlvideofx/ParameterPanel.qml}{ParameterPanel} item renders the sliders corresponding to each effect parameter. -Here is the source selection menu: -\image qmlvideofx-source-menu.png - -And here is the effect selection menu: -\image qmlvideofx-effects-menu.png +Here is the effect selection menu: +\image qmlvideofx-effects-menu.jpg \section1 Calculating and displaying QML painting rate @@ -219,4 +212,3 @@ object to a JavaScript function, which will eventually call frequencyItem.notify \printuntil SLOT(qmlFramePainted())); */ - diff --git a/examples/multimedia/video/qmlvideo/qml/qmlvideo/DisableScreenSaver.qml b/examples/multimedia/video/qmlvideo/qml/qmlvideo/DisableScreenSaver.qml index efc657cfc..01ed95e8a 100644 --- a/examples/multimedia/video/qmlvideo/qml/qmlvideo/DisableScreenSaver.qml +++ b/examples/multimedia/video/qmlvideo/qml/qmlvideo/DisableScreenSaver.qml @@ -41,6 +41,7 @@ import QtQuick 2.0 import QtSystemInfo 5.0 +// NOTE: The QtSystemInfo module is not yet part of Qt 5 Item { ScreenSaver { diff --git a/examples/multimedia/video/qmlvideofx/Info.plist b/examples/multimedia/video/qmlvideofx/Info.plist new file mode 100644 index 000000000..8fc242516 --- /dev/null +++ b/examples/multimedia/video/qmlvideofx/Info.plist @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>UISupportedInterfaceOrientations</key> + <array> + <string>UIInterfaceOrientationLandscapeRight</string> + </array> + <key>UIInterfaceOrientation</key> + <string>UIInterfaceOrientationLandscapeRight</string> + <key>CFBundleIconFile</key> + <string></string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleExecutable</key> + <string>qmlvideofx</string> + <key>CFBundleIdentifier</key> + <string>com.digia.${PRODUCT_NAME:rfc1034identifier}</string> + <key>CFBundleDisplayName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleVersion</key> + <string>1.0</string> +</dict> +</plist> diff --git a/examples/multimedia/video/qmlvideofx/android/AndroidManifest.xml b/examples/multimedia/video/qmlvideofx/android/AndroidManifest.xml new file mode 100644 index 000000000..0612d484c --- /dev/null +++ b/examples/multimedia/video/qmlvideofx/android/AndroidManifest.xml @@ -0,0 +1,48 @@ +<?xml version="1.0"?> +<manifest package="org.qtproject.example.qmlvideofx" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto"> + <application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="@string/app_name"> + <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="@string/app_name" android:screenOrientation="landscape" android:launchMode="singleTop"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="android.intent.category.LAUNCHER"/> + </intent-filter> + <meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/> + <meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/> + <meta-data android:name="android.app.repository" android:value="default"/> + <meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/> + <meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/> + <!-- Deploy Qt libs as part of package --> + <meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/> + <meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/> + <meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/> + <!-- Run with local libs --> + <meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/> + <meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/> + <meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/> + <meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/> + <meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/> + <!-- Messages maps --> + <meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/> + <meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/> + <meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/> + <!-- Messages maps --> + + <!-- Splash screen --> + <!-- + <meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/logo"/> + --> + <!-- Splash screen --> + </activity> + </application> + <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="14"/> + <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/> + + <!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application. + Remove the comment if you do not require these default permissions. --> + <!-- %%INSERT_PERMISSIONS --> + + <!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application. + Remove the comment if you do not require these default features. --> + <!-- %%INSERT_FEATURES --> + +</manifest> diff --git a/examples/multimedia/video/qmlvideofx/images/Dropdown_arrows.png b/examples/multimedia/video/qmlvideofx/images/Dropdown_arrows.png Binary files differnew file mode 100644 index 000000000..0a9e25ce2 --- /dev/null +++ b/examples/multimedia/video/qmlvideofx/images/Dropdown_arrows.png diff --git a/examples/multimedia/video/qmlvideofx/images/Slider_bar.png b/examples/multimedia/video/qmlvideofx/images/Slider_bar.png Binary files differnew file mode 100644 index 000000000..84be50fae --- /dev/null +++ b/examples/multimedia/video/qmlvideofx/images/Slider_bar.png diff --git a/examples/multimedia/video/qmlvideofx/images/Slider_handle.png b/examples/multimedia/video/qmlvideofx/images/Slider_handle.png Binary files differnew file mode 100644 index 000000000..aebecdf19 --- /dev/null +++ b/examples/multimedia/video/qmlvideofx/images/Slider_handle.png diff --git a/examples/multimedia/video/qmlvideofx/images/Triangle_Top.png b/examples/multimedia/video/qmlvideofx/images/Triangle_Top.png Binary files differnew file mode 100644 index 000000000..5768e9536 --- /dev/null +++ b/examples/multimedia/video/qmlvideofx/images/Triangle_Top.png diff --git a/examples/multimedia/video/qmlvideofx/images/Triangle_bottom.png b/examples/multimedia/video/qmlvideofx/images/Triangle_bottom.png Binary files differnew file mode 100644 index 000000000..509409666 --- /dev/null +++ b/examples/multimedia/video/qmlvideofx/images/Triangle_bottom.png diff --git a/examples/multimedia/video/qmlvideofx/images/close.png b/examples/multimedia/video/qmlvideofx/images/close.png Binary files differdeleted file mode 100644 index 6904df0e4..000000000 --- a/examples/multimedia/video/qmlvideofx/images/close.png +++ /dev/null diff --git a/examples/multimedia/video/qmlvideofx/images/folder.png b/examples/multimedia/video/qmlvideofx/images/folder.png Binary files differdeleted file mode 100644 index e53e2ad46..000000000 --- a/examples/multimedia/video/qmlvideofx/images/folder.png +++ /dev/null diff --git a/examples/multimedia/video/qmlvideofx/images/icon_BackArrow.png b/examples/multimedia/video/qmlvideofx/images/icon_BackArrow.png Binary files differnew file mode 100644 index 000000000..6823de004 --- /dev/null +++ b/examples/multimedia/video/qmlvideofx/images/icon_BackArrow.png diff --git a/examples/multimedia/video/qmlvideofx/images/icon_Folder.png b/examples/multimedia/video/qmlvideofx/images/icon_Folder.png Binary files differnew file mode 100644 index 000000000..62d97004f --- /dev/null +++ b/examples/multimedia/video/qmlvideofx/images/icon_Folder.png diff --git a/examples/multimedia/video/qmlvideofx/images/icon_Menu.png b/examples/multimedia/video/qmlvideofx/images/icon_Menu.png Binary files differnew file mode 100644 index 000000000..bc078612e --- /dev/null +++ b/examples/multimedia/video/qmlvideofx/images/icon_Menu.png diff --git a/examples/multimedia/video/qmlvideofx/images/titlebar.png b/examples/multimedia/video/qmlvideofx/images/titlebar.png Binary files differdeleted file mode 100644 index 51c90082d..000000000 --- a/examples/multimedia/video/qmlvideofx/images/titlebar.png +++ /dev/null diff --git a/examples/multimedia/video/qmlvideofx/images/titlebar.sci b/examples/multimedia/video/qmlvideofx/images/titlebar.sci deleted file mode 100644 index 0418d94cd..000000000 --- a/examples/multimedia/video/qmlvideofx/images/titlebar.sci +++ /dev/null @@ -1,5 +0,0 @@ -border.left: 10 -border.top: 12 -border.bottom: 12 -border.right: 10 -source: titlebar.png diff --git a/examples/multimedia/video/qmlvideofx/images/up.png b/examples/multimedia/video/qmlvideofx/images/up.png Binary files differdeleted file mode 100644 index b05f8025d..000000000 --- a/examples/multimedia/video/qmlvideofx/images/up.png +++ /dev/null diff --git a/examples/multimedia/video/qmlvideofx/main.cpp b/examples/multimedia/video/qmlvideofx/main.cpp index 7465deab8..1b09f7aa4 100644 --- a/examples/multimedia/video/qmlvideofx/main.cpp +++ b/examples/multimedia/video/qmlvideofx/main.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Mobility Components. @@ -48,12 +48,6 @@ #include "filereader.h" #include "trace.h" -#ifdef SMALL_SCREEN_LAYOUT - static const QLatin1String MainQmlFile("main-smallscreen.qml"); -#else - static const QLatin1String MainQmlFile("main-largescreen.qml"); -#endif - #ifdef PERFORMANCEMONITOR_SUPPORT #include "performancemonitordeclarative.h" #endif @@ -99,7 +93,7 @@ int main(int argc, char *argv[]) QQuickView viewer; - viewer.setSource(QLatin1String("qrc:///qml/qmlvideofx/") + MainQmlFile); + viewer.setSource(QUrl(QLatin1String("qrc:///qml/qmlvideofx/Main.qml"))); QQuickItem *rootObject = viewer.rootObject(); rootObject->setProperty("fileName", fileName); viewer.rootObject()->setProperty("volume", volume); @@ -128,13 +122,10 @@ int main(int argc, char *argv[]) viewer.setTitle("qmlvideofx"); viewer.setFlags(Qt::Window | Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint); - viewer.setMinimumSize(QSize(600, 400)); + viewer.setMinimumSize(QSize(1280, 720)); + viewer.setResizeMode(QQuickView::SizeRootObjectToView); -#ifdef SMALL_SCREEN_PHYSICAL - viewer.showFullScreen(); -#else viewer.show(); -#endif // Delay invocation of init until the event loop has started, to work around // a GL context issue on Harmattan: without this, we get the following error diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Button.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Button.qml index eb82aceed..203352832 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Button.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Button.qml @@ -43,29 +43,32 @@ import QtQuick 2.0 Rectangle { id: root - color: textColor - radius: 0.25 * height + color: "transparent" + height: itemHeight + width: itemWidth property string text - property color bgColor: "white" - property color bgColorSelected: "red" - property color textColor: "black" + property color bgColor: "transparent" + property color bgColorSelected: "#14aaff" + property color textColor: "white" property alias enabled: mouseArea.enabled + property bool active: true + property alias horizontalAlign: text.horizontalAlignment signal clicked Rectangle { anchors { fill: parent; margins: 1 } color: mouseArea.pressed ? bgColorSelected : bgColor - radius: 0.25 * height Text { id: text - anchors.centerIn: parent + clip: true text: root.text - font.pixelSize: 0.5 * parent.height - color: mouseArea.pressed ? bgColor : textColor - horizontalAlignment: Text.AlignHCenter + anchors { fill: parent; margins: scaledMargin } + font.pixelSize: fontSize + color: textColor + horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter } @@ -75,6 +78,7 @@ Rectangle { onClicked: { root.clicked() } + enabled: active } } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Content.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Content.qml index d3a2e9f42..72b7cca7e 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Content.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Content.qml @@ -39,11 +39,10 @@ ** ****************************************************************************/ -import QtQuick 2.0 +import QtQuick 2.1 Rectangle { id: root - color: "black" property alias effect: effectLoader.item property alias gripSize: divider.gripSize property string effectSource diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ContentImage.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ContentImage.qml index 0fa047bb1..2bce20bf0 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ContentImage.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ContentImage.qml @@ -39,7 +39,7 @@ ** ****************************************************************************/ -import QtQuick 2.0 +import QtQuick 2.1 Image { fillMode: Image.PreserveAspectFit diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ContentVideo.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ContentVideo.qml index be09f7ea5..6491ceff2 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ContentVideo.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ContentVideo.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Mobility Components. @@ -39,13 +39,14 @@ ** ****************************************************************************/ -import QtQuick 2.0 +import QtQuick 2.1 import QtMultimedia 5.0 VideoOutput { source: mediaPlayer property alias mediaSource: mediaPlayer.source property alias volume: mediaPlayer.volume + property bool isRunning: true MediaPlayer { id: mediaPlayer @@ -55,5 +56,21 @@ VideoOutput { } function play() { mediaPlayer.play() } + function pause() { mediaPlayer.pause() } function stop() { mediaPlayer.stop() } + + function toggleplay() { + if (isRunning) { + pause() + isRunning = false + } else { + play() + isRunning = true + } + } + + MouseArea { + anchors.fill: parent + onClicked: toggleplay() + } } diff --git a/examples/multimedia/video/qmlvideofx/shaders/sobeledgedetection2.fsh b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Curtain.qml index 039a567d2..253e3c397 100644 --- a/examples/multimedia/video/qmlvideofx/shaders/sobeledgedetection2.fsh +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Curtain.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Mobility Components. @@ -39,39 +39,56 @@ ** ****************************************************************************/ -// Based on http://rastergrid.com/blog/downloads/frei-chen-edge-detector/ +import QtQuick 2.0 -#version 130 -uniform sampler2D source; -uniform float dividerValue; -uniform float weight; -mat3 G[2] = mat3[]( - mat3( 1.0, 2.0, 1.0, 0.0, 0.0, 0.0, -1.0, -2.0, -1.0 ), - mat3( 1.0, 0.0, -1.0, 2.0, 0.0, -2.0, 1.0, 0.0, -1.0 ) -); -uniform lowp float qt_Opacity; -in vec2 qt_TexCoord0; -out vec4 FragmentColor; -void main() { - vec2 uv = qt_TexCoord0.xy; - vec4 c = vec4(0.0); - if (uv.x < dividerValue) { - mat3 intensity; - float conv[2]; - vec3 sample; - for (int i=0; i<3; ++i) { - for (int j=0; j<3; ++j) { - sample = texelFetch(source, ivec2(gl_FragCoord) + ivec2(i-1, j-1), 0).rgb; - intensity[i][j] = length(sample) * weight; - } +Rectangle { + id: root + color: "transparent" + radius: 5 + property alias value: grip.value + property color gripColor: "transparent" + property real gripSize: 20 + property real gripTolerance: 3.0 + property real increment: 0.1 + property bool enabled: true + property string imageSource: "qrc:/images/Triangle_Top.png" + + Rectangle { + id: grip + property real value: 0.5 + x: (value * parent.width) - width/2 + anchors.verticalCenter: parent.verticalCenter + width: root.gripTolerance * root.gripSize + height: width + radius: width/2 + color: "transparent" + + Image { + id: sliderhandleimage + source: imageSource + anchors.centerIn: parent } - for (int i=0; i<2; ++i) { - float dp3 = dot(G[i][0], intensity[0]) + dot(G[i][1], intensity[1]) + dot(G[i][2], intensity[2]); - conv[i] = dp3 * dp3; + + MouseArea { + id: mouseArea + enabled: root.enabled + anchors.fill: parent + drag { + target: grip + axis: Drag.XAxis + minimumX: -parent.width/2 + maximumX: root.width - parent.width/2 + } + onPositionChanged: { + if (drag.active) + updatePosition() + } + onReleased: { + updatePosition() + } + function updatePosition() { + value = (grip.x + grip.width/2) / grip.parent.width + } } - c = vec4(0.5 * sqrt(conv[0]*conv[0] + conv[1]*conv[1])); - } else { - c = texture2D(source, qt_TexCoord0); } - FragmentColor = qt_Opacity * c; } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/DisableScreenSaver.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/DisableScreenSaver.qml index f36b2b14f..362386bc4 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/DisableScreenSaver.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/DisableScreenSaver.qml @@ -41,6 +41,7 @@ import QtQuick 2.0 import QtMobility.systeminfo 1.1 +// NOTE: The QtSystemInfo module is not yet part of Qt 5 Item { ScreenSaver { diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Divider.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Divider.qml index 390818bbc..45c2606f9 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Divider.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Divider.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Mobility Components. @@ -39,7 +39,7 @@ ** ****************************************************************************/ -import QtQuick 2.0 +import QtQuick 2.1 Rectangle { id: root @@ -53,21 +53,34 @@ Rectangle { id: line anchors { top: parent.top; bottom: parent.bottom } x: parent.value * parent.width - (width / 2) - width: 2 - color: "red" + width: 4 + color: "#14aaff" } - Slider { + // topgrip + Curtain { id: slider increment: 0.0 - lineColor: "transparent" - fillColor: "transparent" - gripColor: "red" anchors { top: parent.top - topMargin: gripSize / 2 + topMargin: (gripSize / 2) + 5 left: parent.left right: parent.right } + onValueChanged: slider2.value = slider.value + } + + // bottomgrip + Curtain { + id: slider2 + increment: 0.0 + anchors { + bottom: parent.bottom + bottomMargin: (gripSize / 2) + 5 + left: parent.left + right: parent.right + } + imageSource: "qrc:/images/Triangle_bottom.png" + onValueChanged: slider.value = slider2.value } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectBillboard.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectBillboard.qml index 4e3adc3e2..1e2077246 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectBillboard.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectBillboard.qml @@ -44,7 +44,7 @@ import QtQuick 2.0 Effect { parameters: ListModel { ListElement { - name: "grid spacing" + name: "Grid Spacing" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectBlackAndWhite.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectBlackAndWhite.qml index 5e37c70ce..85f2abc7d 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectBlackAndWhite.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectBlackAndWhite.qml @@ -44,7 +44,7 @@ import QtQuick 2.0 Effect { parameters: ListModel { ListElement { - name: "threshold" + name: "Threshold" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectGaussianBlur.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectGaussianBlur.qml index 00fab0448..f0cad5288 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectGaussianBlur.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectGaussianBlur.qml @@ -49,7 +49,7 @@ Item { property real dividerValue: 0.5 property ListModel parameters: ListModel { ListElement { - name: "radius" + name: "Radius" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectIsolate.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectIsolate.qml index f3650419c..80c7ccaed 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectIsolate.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectIsolate.qml @@ -44,11 +44,11 @@ import QtQuick 2.0 Effect { parameters: ListModel { ListElement { - name: "hue" + name: "Hue" value: 0.5 } ListElement { - name: "width" + name: "Width" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectMagnify.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectMagnify.qml index d93e72c9e..3fd35eaae 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectMagnify.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectMagnify.qml @@ -46,11 +46,11 @@ Effect { divider: false parameters: ListModel { ListElement { - name: "radius" + name: "Radius" value: 0.5 } ListElement { - name: "diffraction" + name: "Diffraction" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPageCurl.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPageCurl.qml index e4fc1f78f..c035b9b62 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPageCurl.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPageCurl.qml @@ -45,7 +45,7 @@ Effect { divider: false parameters: ListModel { ListElement { - name: "extent" + name: "Extent" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPixelate.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPixelate.qml index 002a74a46..7a0f21984 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPixelate.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPixelate.qml @@ -44,7 +44,7 @@ import QtQuick 2.0 Effect { parameters: ListModel { ListElement { - name: "granularity" + name: "Granularity" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPosterize.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPosterize.qml index bda473764..084b28c17 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPosterize.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPosterize.qml @@ -44,7 +44,7 @@ import QtQuick 2.0 Effect { parameters: ListModel { ListElement { - name: "gamma" + name: "Gamma" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectRipple.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectRipple.qml index 7932b4c12..e0a2b0227 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectRipple.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectRipple.qml @@ -44,11 +44,11 @@ import QtQuick 2.0 Effect { parameters: ListModel { ListElement { - name: "amplitude" + name: "Amplitude" value: 0.5 } ListElement { - name: "frequency" + name: "Frequency" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSelectionList.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSelectionList.qml new file mode 100644 index 000000000..fa92bb7ca --- /dev/null +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSelectionList.qml @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +import QtQuick 2.0 + +ListModel { + id: sources + ListElement { name: "No effect"; source: "EffectPassThrough.qml" } + ListElement { name: "Billboard"; source: "EffectBillboard.qml" } + ListElement { name: "Black & white"; source: "EffectBlackAndWhite.qml" } + ListElement { name: "Blur"; source: "EffectGaussianBlur.qml" } + ListElement { name: "Edge detection"; source: "EffectSobelEdgeDetection1.qml" } + ListElement { name: "Emboss"; source: "EffectEmboss.qml" } + ListElement { name: "Glow"; source: "EffectGlow.qml" } + ListElement { name: "Isolate"; source: "EffectIsolate.qml" } + //ListElement { name: "Magnify"; source: "EffectMagnify.qml" } + ListElement { name: "Page curl"; source: "EffectPageCurl.qml" } + ListElement { name: "Pixelate"; source: "EffectPixelate.qml" } + ListElement { name: "Posterize"; source: "EffectPosterize.qml" } + ListElement { name: "Ripple"; source: "EffectRipple.qml" } + ListElement { name: "Sepia"; source: "EffectSepia.qml" } + ListElement { name: "Sharpen"; source: "EffectSharpen.qml" } + ListElement { name: "Shockwave"; source: "EffectShockwave.qml" } + ListElement { name: "Tilt shift"; source: "EffectTiltShift.qml" } + ListElement { name: "Toon"; source: "EffectToon.qml" } + ListElement { name: "Warhol"; source: "EffectWarhol.qml" } + ListElement { name: "Wobble"; source: "EffectWobble.qml" } + ListElement { name: "Vignette"; source: "EffectVignette.qml" } +} diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSelectionPanel.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSelectionPanel.qml deleted file mode 100644 index 948a4e888..000000000 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSelectionPanel.qml +++ /dev/null @@ -1,154 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Mobility Components. -** -** $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$ -** -****************************************************************************/ -import QtQuick 2.0 - -Rectangle { - id: root - property int itemHeight: 25 - property string effectSource: "" - - signal clicked - - QtObject { - id: d - property Item selectedItem - } - - ListModel { - id: sources - ListElement { name: "No effect"; source: "EffectPassThrough.qml" } - ListElement { name: "Billboard"; source: "EffectBillboard.qml" } - ListElement { name: "Black & white"; source: "EffectBlackAndWhite.qml" } - ListElement { name: "Blur"; source: "EffectGaussianBlur.qml" } - ListElement { name: "Edge detection"; source: "EffectSobelEdgeDetection1.qml" } - //ListElement { name: "Edge detection (Sobel, #2)"; source: "EffectSobelEdgeDetection2.qml" } - ListElement { name: "Emboss"; source: "EffectEmboss.qml" } - ListElement { name: "Glow"; source: "EffectGlow.qml" } - ListElement { name: "Isolate"; source: "EffectIsolate.qml" } - ListElement { name: "Magnify"; source: "EffectMagnify.qml" } - ListElement { name: "Page curl"; source: "EffectPageCurl.qml" } - ListElement { name: "Pixelate"; source: "EffectPixelate.qml" } - ListElement { name: "Posterize"; source: "EffectPosterize.qml" } - ListElement { name: "Ripple"; source: "EffectRipple.qml" } - ListElement { name: "Sepia"; source: "EffectSepia.qml" } - ListElement { name: "Sharpen"; source: "EffectSharpen.qml" } - ListElement { name: "Shockwave"; source: "EffectShockwave.qml" } - ListElement { name: "Tilt shift"; source: "EffectTiltShift.qml" } - ListElement { name: "Toon"; source: "EffectToon.qml" } - ListElement { name: "Warhol"; source: "EffectWarhol.qml" } - ListElement { name: "Wobble"; source: "EffectWobble.qml" } - ListElement { name: "Vignette"; source: "EffectVignette.qml" } - } - - Component { - id: sourceDelegate - Item { - id: sourceDelegateItem - width: root.width - height: itemHeight - - Button { - id: sourceSelectorItem - anchors.centerIn: parent - width: 0.9 * parent.width - height: 0.8 * itemHeight - text: name - onClicked: { - if (d.selectedItem) - d.selectedItem.state = "baseState" - d.selectedItem = sourceDelegateItem - d.selectedItem.state = "selected" - effectSource = source - root.clicked() - } - } - - states: [ - State { - name: "selected" - PropertyChanges { - target: sourceSelectorItem - bgColor: "#ff8888" - } - } - ] - - Component.onCompleted: { - if (name == "No effect") { - state = "selected" - d.selectedItem = sourceDelegateItem - } - } - - transitions: [ - Transition { - from: "*" - to: "*" - ColorAnimation { - properties: "color" - easing.type: Easing.OutQuart - duration: 500 - } - } - ] - } - } - - Flickable { - anchors.fill: parent - contentHeight: (itemHeight * sources.count) + layout.anchors.topMargin + layout.spacing - clip: true - - Column { - id: layout - - anchors { - fill: parent - topMargin: 10 - } - - Repeater { - model: sources - delegate: sourceDelegate - } - } - } -} diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSharpen.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSharpen.qml index 25215980d..f59544dc9 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSharpen.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSharpen.qml @@ -44,7 +44,7 @@ import QtQuick 2.0 Effect { parameters: ListModel { ListElement { - name: "sharpness" + name: "Sharpness" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectShockwave.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectShockwave.qml index 0e1b1785f..746445b46 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectShockwave.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectShockwave.qml @@ -45,7 +45,7 @@ Effect { id: root parameters: ListModel { ListElement { - name: "amplitude" + name: "Amplitude" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSobelEdgeDetection1.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSobelEdgeDetection1.qml index 6724a8449..7b03dbfdb 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSobelEdgeDetection1.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSobelEdgeDetection1.qml @@ -44,7 +44,7 @@ import QtQuick 2.0 Effect { parameters: ListModel { ListElement { - name: "threshold" + name: "Threshold" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectToon.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectToon.qml index ff985e563..ecba40623 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectToon.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectToon.qml @@ -44,7 +44,7 @@ import QtQuick 2.0 Effect { parameters: ListModel { ListElement { - name: "threshold" + name: "Threshold" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectWobble.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectWobble.qml index 97e7c061c..aa07c1a68 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectWobble.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectWobble.qml @@ -44,7 +44,7 @@ import QtQuick 2.0 Effect { parameters: ListModel { ListElement { - name: "amplitude" + name: "Amplitude" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileBrowser.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileBrowser.qml index 7c8610361..c75b6f255 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileBrowser.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileBrowser.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Mobility Components. @@ -39,12 +39,13 @@ ** ****************************************************************************/ -import QtQuick 2.0 -import Qt.labs.folderlistmodel 2.0 +import QtQuick 2.1 +import Qt.labs.folderlistmodel 2.1 Rectangle { id: fileBrowser color: "transparent" + z: 4 property string folder property bool shown: loader.sourceComponent @@ -75,12 +76,12 @@ Rectangle { Rectangle { id: root - color: "white" + color: "black" property bool showFocusHighlight: false property variant folders: folders1 property variant view: view1 property alias folder: folders1.folder - property color textColor: "black" + property color textColor: "white" FolderListModel { id: folders1 @@ -112,7 +113,7 @@ Rectangle { fileBrowser.selectFile(path) } width: root.width - height: 52 + height: itemHeight color: "transparent" Rectangle { @@ -126,10 +127,12 @@ Rectangle { } Item { - width: 48; height: 48 + width: itemHeight; height: itemHeight Image { - source: "qrc:/images/folder.png" - anchors.centerIn: parent + source: "qrc:/images/icon_Folder.png" + fillMode: Image.PreserveAspectFit + anchors.fill: parent + anchors.margins: scaledMargin visible: folders.isFolder(index) } } @@ -138,8 +141,8 @@ Rectangle { id: nameText anchors.fill: parent; verticalAlignment: Text.AlignVCenter text: fileName - anchors.leftMargin: 54 - font.pixelSize: 32 + anchors.leftMargin: itemHeight + scaledMargin + font.pixelSize: fontSize color: (wrapper.ListView.isCurrentItem && root.showFocusHighlight) ? palette.highlightedText : textColor elide: Text.ElideRight } @@ -262,56 +265,45 @@ Rectangle { Keys.onPressed: root.keyPressed(event.key) } - Rectangle { + Button { id: cancelButton - width: 100 - height: titleBar.height - 7 - color: "black" - anchors { bottom: parent.bottom; horizontalCenter: parent.horizontalCenter } - - Text { - anchors { fill: parent; margins: 4 } - text: "Cancel" - color: "white" - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - font.pixelSize: 20 - } - - MouseArea { - anchors.fill: parent - onClicked: fileBrowser.selectFile("") - } + width: itemWidth + height: itemHeight + color: "#353535" + anchors { bottom: parent.bottom; right: parent.right; margins: 5 * scaledMargin } + text: "Cancel" + horizontalAlign: Text.AlignHCenter + onClicked: fileBrowser.selectFile("") } Keys.onPressed: { root.keyPressed(event.key); - if (event.key == Qt.Key_Return || event.key == Qt.Key_Select || event.key == Qt.Key_Right) { + if (event.key === Qt.Key_Return || event.key === Qt.Key_Select || event.key === Qt.Key_Right) { view.currentItem.launch(); event.accepted = true; - } else if (event.key == Qt.Key_Left) { + } else if (event.key === Qt.Key_Left) { up(); } } - BorderImage { - source: "qrc:/images/titlebar.sci"; + // titlebar + Rectangle { + color: "black" width: parent.width; - height: 52 - y: -7 + height: itemHeight id: titleBar Rectangle { id: upButton - width: 48 - height: titleBar.height - 7 + width: titleBar.height + height: titleBar.height color: "transparent" - Image { anchors.centerIn: parent; source: "qrc:/images/up.png" } - MouseArea { id: upRegion; anchors.centerIn: parent - width: 56 - height: 56 - onClicked: up() - } + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + anchors.margins: scaledMargin + + Image { anchors.fill: parent; anchors.margins: scaledMargin; source: "qrc:/images/icon_BackArrow.png" } + MouseArea { id: upRegion; anchors.fill: parent; onClicked: up() } states: [ State { name: "pressed" @@ -321,23 +313,23 @@ Rectangle { ] } - Rectangle { - color: "gray" - x: 48 - width: 1 - height: 44 - } - Text { anchors.left: upButton.right; anchors.right: parent.right; height: parent.height - anchors.leftMargin: 4; anchors.rightMargin: 4 + anchors.leftMargin: 10; anchors.rightMargin: 4 text: folders.folder color: "white" - elide: Text.ElideLeft; horizontalAlignment: Text.AlignRight; verticalAlignment: Text.AlignVCenter - font.pixelSize: 32 + elide: Text.ElideLeft; horizontalAlignment: Text.AlignLeft; verticalAlignment: Text.AlignVCenter + font.pixelSize: fontSize } } + Rectangle { + color: "#353535" + width: parent.width + height: 1 + anchors.top: titleBar.bottom + } + function down(path) { if (folders == folders1) { view = view2 diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileOpen.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileOpen.qml index 716f4165b..a4de2cbb9 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileOpen.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileOpen.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Mobility Components. @@ -39,56 +39,115 @@ ** ****************************************************************************/ -import QtQuick 2.0 +import QtQuick 2.1 Rectangle { id: root - color: "white" - property int buttonHeight: 35 - property int topMargin: 0 - + color: "#151515" + signal openCamera signal openImage signal openVideo - signal openCamera signal close + Rectangle { + id: menuField + height: itemHeight + width: itemHeight + color: "transparent" + anchors.right: parent.right + Image { + id: menu + source: "qrc:///images/icon_Menu.png" + anchors { + right: parent.right + top: parent.top + margins: scaledMargin + } + } + MouseArea { + anchors.fill: parent + onClicked: fileOpen.state == "expanded" ? fileOpen.state = "collapsed" : fileOpen.state = "expanded" + } + } + + Column { anchors { - top: parent.top; - topMargin: root.topMargin - bottom: parent.bottom; - horizontalCenter: parent.horizontalCenter + top: menuField.bottom + right: parent.right + left: parent.left + bottom: parent.bottom + topMargin: 10 } - width: 0.9 * parent.width - color: "transparent" - Column { - anchors.fill: parent - spacing: 5 - Button { - text: "Open image" - height: buttonHeight - width: parent.width - onClicked: root.openImage() + spacing: 10 + visible: fileOpen.state == "expanded" + + Rectangle { + width: 0.9 * parent.width + height: 1 + color: "#353535" + anchors.left: parent.left + } + Button { + text: "Start camera" + height: itemHeight + width: parent.width + onClicked: { + fileOpen.state = "collapsed" + root.openCamera() } - Button { - text: "Open video" - height: buttonHeight - width: parent.width - onClicked: root.openVideo() + } + Rectangle { + width: 0.9 * parent.width + height: 1 + color: "#353535" + anchors.left: parent.left + } + Button { + text: "Open image" + height: itemHeight + width: parent.width + onClicked: { + fileOpen.state = "collapsed" + root.openImage() } - Button { - text: "Start camera" - height: buttonHeight - width: parent.width - onClicked: root.openCamera() + } + Rectangle { + width: 0.9 * parent.width + height: 1 + color: "#353535" + anchors.left: parent.left + } + Button { + text: "Open video" + height: itemHeight + width: parent.width + onClicked: { + fileOpen.state = "collapsed" + root.openVideo() } - Button { - text: "Reset" - height: buttonHeight - width: parent.width - onClicked: root.close() + } + Rectangle { + width: 0.9 * parent.width + height: 1 + color: "#353535" + anchors.left: parent.left + } + Button { + text: "Reset" + height: itemHeight + width: parent.width + onClicked: { + fileOpen.state = "collapsed" + root.close() } } + Rectangle { + width: 0.9 * parent.width + height: 1 + color: "#353535" + anchors.left: parent.left + } } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Main.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Main.qml new file mode 100644 index 000000000..e39eeafd7 --- /dev/null +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Main.qml @@ -0,0 +1,293 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.Window 2.1 + +Rectangle { + id: root + color: "black" + property string fileName + property alias volume: content.volume + property bool perfMonitorsLogging: false + property bool perfMonitorsVisible: false + property int pixDens: Math.ceil(Screen.pixelDensity) + property int itemWidth: 25 * pixDens + property int itemHeight: 10 * pixDens + property int windowWidth: Screen.desktopAvailableWidth + property int windowHeight: Screen.desktopAvailableHeight + property int scaledMargin: 2 * pixDens + property int fontSize: 5 * pixDens + + QtObject { + id: d + property real gripSize: 20 + } + + Content { + id: content + color: "transparent" + anchors { + top: parent.top + left: parent.left + right: parent.right + bottom: parameterPanel.top + margins: scaledMargin + leftMargin: scaledMargin + itemHeight + } + gripSize: d.gripSize + } + + ParameterPanel { + id: parameterPanel + anchors { + left: parent.left + right: effectName.left + bottom: parent.bottom + margins: scaledMargin + leftMargin: scaledMargin + itemHeight + } + gripSize: d.gripSize + height: root.itemHeight * 2.5 + width: root.itemWidth * 3 + } + + Button { + id: effectName + anchors { + right: parent.right + bottom: perfHolder.top + margins: scaledMargin + } + + text: "No effect" + width: itemWidth * 2 + height: itemHeight + onClicked: { + effectName.visible = false + listview.visible = true + lvbg.visible = true + } + color: "#303030" + } + + Rectangle { + id: lvbg + width: itemWidth * 2 + color: "black" + opacity: 0.8 + visible: false + + anchors { + right: parent.right + bottom: perfHolder.top + top: parent.top + margins: scaledMargin + } + + ListView { + id: listview + width: itemWidth * 2 + anchors.fill: parent + visible: false + + model: EffectSelectionList {} + delegate: effectDelegate + + clip: true + focus: true + + Component { + id: effectDelegate + Button { + text: name + width: itemWidth * 2 + onClicked: { + content.effectSource = source + listview.visible = false + lvbg.visible = false + effectName.text = name + effectName.visible = true + parameterPanel.model = content.effect.parameters + + } + } + } + } + } + + Rectangle { + id: perfHolder + color: "transparent" + anchors { + right: parent.right + bottom: parent.bottom + margins: scaledMargin + } + height: root.itemHeight * 1.5 + width: root.itemWidth + + Loader { + id: performanceLoader + function init() { + console.log("[qmlvideofx] performanceLoader.init logging " + root.perfMonitorsLogging + " visible " + root.perfMonitorsVisible) + var enabled = root.perfMonitorsLogging || root.perfMonitorsVisible + source = enabled ? "../performancemonitor/PerformanceItem.qml" : "" + } + onLoaded: { + item.parent = perfHolder + item.anchors.top = perfHolder.top + item.anchors.bottom = perfHolder.bottom + item.anchors.left = perfHolder.left + item.anchors.right = perfHolder.right + item.logging = root.perfMonitorsLogging + item.displayed = root.perfMonitorsVisible + item.init() + } + } + } + + FileOpen { + id: fileOpen + state: "collapsed" + anchors { + left: parent.left + top: parent.top + bottom: parent.bottom + margins: scaledMargin + } + width: itemHeight + scaledMargin + z: 2 + opacity: 0.9 + + states: [ + State { + name: "expanded" + PropertyChanges { + target: fileOpen + width: itemWidth * 1.5 + opacity: 0.8 + } + }, + State { + name: "collapsed" + PropertyChanges { + target: fileOpen + width: itemHeight + scaledMargin + opacity: 0.9 + } + } + ] + + transitions: [ + Transition { + NumberAnimation { target: fileOpen; property: "width"; duration: 100 } + NumberAnimation { target: fileOpen; property: "opacity"; duration: 100 } + } + ] + } + + FileBrowser { + id: imageFileBrowser + anchors.fill: root + Component.onCompleted: fileSelected.connect(content.openImage) + } + + FileBrowser { + id: videoFileBrowser + anchors.fill: root + Component.onCompleted: fileSelected.connect(content.openVideo) + } + + Component.onCompleted: { + fileOpen.openImage.connect(openImage) + fileOpen.openVideo.connect(openVideo) + fileOpen.openCamera.connect(openCamera) + fileOpen.close.connect(close) + } + + function init() { + if (Qt.platform.os === "linux" || Qt.platform.os === "windows" || Qt.platform.os === "osx" || Qt.platform.os === "unix") { + if (Screen.desktopAvailableWidth > 1280) { + windowWidth = 1280 + } + if (Screen.desktopAvailableHeight > 720) { + windowHeight = 720 + } + } + + height = windowHeight + width = windowWidth + + console.log("[qmlvideofx] root.init") + console.log("Height: ", Screen.desktopAvailableHeight) + console.log("Width: ", Screen.desktopAvailableWidth) + console.log("Pixels per mm: ", Math.ceil(Screen.pixelDensity)) + console.log("Orientation: ", Screen.orientation) + imageFileBrowser.folder = imagePath + videoFileBrowser.folder = videoPath + content.init() + performanceLoader.init() + if (fileName != "") + content.openVideo(fileName) + } + + function qmlFramePainted() { + if (performanceLoader.item) + performanceLoader.item.qmlFramePainted() + } + + function openImage() { + imageFileBrowser.show() + } + + function openVideo() { + videoFileBrowser.show() + } + + function openCamera() { + content.openCamera() + } + + function close() { + content.init() + } +} diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ParameterPanel.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ParameterPanel.qml index 83c0d4c8d..aa4315c9d 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ParameterPanel.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ParameterPanel.qml @@ -47,17 +47,12 @@ Rectangle { height: view.model.count * sliderHeight property color lineColor: "black" property real gripSize: 25 - property real spacing: 10 - property real sliderHeight: 40 + property real spacing: 20 + property real sliderHeight: 60 property ListModel model: ListModel { } - Rectangle { - anchors.fill: parent - color: "black" - opacity: 0.5 - radius: 10 - } + anchors.topMargin: 10 Component { id: editDelegate @@ -77,10 +72,10 @@ Rectangle { bottom: parent.bottom left: parent.left } - font.pixelSize: 0.5 * parent.height + font.pixelSize: fontSize horizontalAlignment: Text.AlignRight verticalAlignment: Text.AlignVCenter - width: 150 + width: 8 * fontSize } Slider { diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Slider.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Slider.qml index c12537022..97b52c87b 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Slider.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Slider.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Mobility Components. @@ -39,91 +39,84 @@ ** ****************************************************************************/ -import QtQuick 2.0 +import QtQuick 2.1 Rectangle { id: root color: "transparent" radius: 5 property alias value: grip.value - property color fillColor: "white" - property color lineColor: "black" - property color gripColor: "white" - property real gripSize: 20 + property color fillColor: "#14aaff" + property real gripSize: 40 property real gripTolerance: 3.0 property real increment: 0.1 property bool enabled: true Rectangle { - anchors { left: parent.left; right: parent.right; verticalCenter: parent.verticalCenter } - height: 3 - color: displayedColor(root.lineColor) + id: slider + anchors { + left: parent.left + right: parent.right + verticalCenter: parent.verticalCenter + } + height: 10 + color: "transparent" + BorderImage { + id: sliderbarimage + source: "qrc:/images/Slider_bar.png" + anchors { fill: parent; margins: 1 } + border.right: 5 + border.left: 5 + } Rectangle { - anchors { fill: parent; margins: 1 } + height: parent.height -2 + anchors.left: parent.left + anchors.right: grip.horizontalCenter color: root.fillColor + radius: 3 + border.width: 1 + border.color: Qt.darker(color, 1.3) + opacity: 0.8 } - } + Rectangle { + id: grip + property real value: 0.5 + x: (value * parent.width) - width/2 + anchors.verticalCenter: parent.verticalCenter + width: root.gripTolerance * root.gripSize + height: width + radius: width/2 + color: "transparent" - MouseArea { - anchors.fill: parent - enabled: root.enabled - onClicked: { - if (parent.width) { - var newValue = mouse.x / parent.width - if (Math.abs(newValue - parent.value) > parent.increment) { - if (newValue > parent.value) - parent.value = Math.min(1.0, parent.value + parent.increment) - else - parent.value = Math.max(0.0, parent.value - parent.increment) - } + Image { + id: sliderhandleimage + source: "qrc:/images/Slider_handle.png" + anchors.centerIn: parent } - } - } - - Rectangle { - id: grip - property real value: 0.5 - x: (value * parent.width) - width/2 - anchors.verticalCenter: parent.verticalCenter - width: root.gripTolerance * root.gripSize - height: width - radius: width/2 - color: "transparent" - MouseArea { - id: mouseArea - enabled: root.enabled - anchors.fill: parent - drag { - target: grip - axis: Drag.XAxis - minimumX: -parent.width/2 - maximumX: root.width - parent.width/2 - } - onPositionChanged: { - if (drag.active) + MouseArea { + id: mouseArea + enabled: root.enabled + anchors.fill: parent + drag { + target: grip + axis: Drag.XAxis + minimumX: -parent.width/2 + maximumX: root.width - parent.width/2 + } + onPositionChanged: { + if (drag.active) + updatePosition() + } + onReleased: { updatePosition() - } - onReleased: { - updatePosition() - } - function updatePosition() { - value = (grip.x + grip.width/2) / grip.parent.width + } + function updatePosition() { + value = (grip.x + grip.width/2) / slider.width + } } } - Rectangle { - anchors.centerIn: parent - width: root.gripSize - height: width - radius: width/2 - color: root.gripColor - } - } - - function displayedColor(c) { - var tint = Qt.rgba(c.r, c.g, c.b, 0.25) - return enabled ? c : Qt.tint(c, tint) } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/main-largescreen.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/main-largescreen.qml deleted file mode 100644 index 63a0a01ac..000000000 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/main-largescreen.qml +++ /dev/null @@ -1,186 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Mobility Components. -** -** $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$ -** -****************************************************************************/ - -import QtQuick 2.0 - -Rectangle { - id: root - width: 900 - height: 600 - color: "grey" - property string fileName - property alias volume: content.volume - property bool perfMonitorsLogging: false - property bool perfMonitorsVisible: false - - QtObject { - id: d - property real gripSize: 20 - } - - Rectangle { - id: inner - anchors.fill: parent - color: "grey" - - Content { - id: content - anchors { - top: parent.top - bottom: parent.bottom - left: parent.left - right: effectSelectionPanel.left - margins: 5 - } - gripSize: d.gripSize - width: 600 - height: 600 - } - - Loader { - id: performanceLoader - function init() { - console.log("[qmlvideofx] performanceLoader.init logging " + root.perfMonitorsLogging + " visible " + root.perfMonitorsVisible) - var enabled = root.perfMonitorsLogging || root.perfMonitorsVisible - source = enabled ? "../performancemonitor/PerformanceItem.qml" : "" - } - onLoaded: { - item.parent = content - item.anchors.top = content.top - item.anchors.left = content.left - item.anchors.right = content.right - item.logging = root.perfMonitorsLogging - item.displayed = root.perfMonitorsVisible - item.init() - } - } - - ParameterPanel { - id: parameterPanel - anchors { - left: parent.left - bottom: parent.bottom - right: effectSelectionPanel.left - margins: 20 - } - gripSize: d.gripSize - } - - EffectSelectionPanel { - id: effectSelectionPanel - anchors { - top: parent.top - bottom: fileOpen.top - right: parent.right - margins: 5 - } - width: 300 - itemHeight: 40 - onEffectSourceChanged: { - content.effectSource = effectSource - parameterPanel.model = content.effect.parameters - } - } - - FileOpen { - id: fileOpen - anchors { - right: parent.right - bottom: parent.bottom - margins: 5 - } - width: effectSelectionPanel.width - height: 165 - buttonHeight: 32 - topMargin: 10 - } - } - - FileBrowser { - id: imageFileBrowser - anchors.fill: root - Component.onCompleted: fileSelected.connect(content.openImage) - } - - FileBrowser { - id: videoFileBrowser - anchors.fill: root - Component.onCompleted: fileSelected.connect(content.openVideo) - } - - Component.onCompleted: { - fileOpen.openImage.connect(openImage) - fileOpen.openVideo.connect(openVideo) - fileOpen.openCamera.connect(openCamera) - fileOpen.close.connect(close) - } - - function init() { - console.log("[qmlvideofx] main.init") - imageFileBrowser.folder = imagePath - videoFileBrowser.folder = videoPath - content.init() - performanceLoader.init() - if (fileName != "") - content.openVideo(fileName) - } - - function qmlFramePainted() { - if (performanceLoader.item) - performanceLoader.item.qmlFramePainted() - } - - function openImage() { - imageFileBrowser.show() - } - - function openVideo() { - videoFileBrowser.show() - } - - function openCamera() { - content.openCamera() - } - - function close() { - content.openImage("qrc:/images/qt-logo.png") - } -} diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/main-smallscreen.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/main-smallscreen.qml deleted file mode 100644 index f715dc8c1..000000000 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/main-smallscreen.qml +++ /dev/null @@ -1,408 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Mobility Components. -** -** $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$ -** -****************************************************************************/ - -import QtQuick 2.0 - -Rectangle { - id: root - width: 640 - height: 360 - color: "grey" - property string fileName - property alias volume: content.volume - property bool perfMonitorsLogging: false - property bool perfMonitorsVisible: false - - QtObject { - id: d - property bool dialogShown: (fileOpenContainer.state == "shown" || - effectSelectionPanel.state == "shown" || - videoFileBrowser.shown || - imageFileBrowser.shown) - property real gripSize: 40 - } - - // Create ScreenSaver element via Loader, so this app will still run if the - // SystemInfo module is not available - Loader { - source: "DisableScreenSaver.qml" - } - - Loader { - id: performanceLoader - - Connections { - target: d - onDialogShownChanged: - if (performanceLoader.item) - performanceLoader.item.enabled = !d.dialogShown - ignoreUnknownSignals: true - } - - function init() { - console.log("[qmlvideofx] performanceLoader.init logging " + root.perfMonitorsLogging + " visible " + root.perfMonitorsVisible) - var enabled = root.perfMonitorsLogging || root.perfMonitorsVisible - source = enabled ? "../performancemonitor/PerformanceItem.qml" : "" - } - - onLoaded: { - item.parent = root - item.anchors.top = root.top - item.anchors.left = root.left - item.logging = root.perfMonitorsLogging - item.displayed = root.perfMonitorsVisible - item.init() - } - } - - Rectangle { - id: inner - anchors.fill: parent - color: "grey" - - Content { - id: content - anchors.fill: parent - gripSize: d.gripSize - onVideoFramePainted: performanceLoader.item.videoFramePainted() - } - - ParameterPanel { - id: parameterPanel - anchors { - left: parent.left; - right: parent.right; - margins: 10 - } - y: parent.height - gripSize: d.gripSize - - states: [ - State { - name: "shown" - PropertyChanges { - target: parameterPanel - y: parent.height - (parameterPanel.height + 10) - } - } - ] - - transitions: [ - Transition { - from: "*" - to: "*" - NumberAnimation { - properties: "y" - easing.type: Easing.OutQuart - duration: 500 - } - } - ] - - state: (enabled && !d.dialogShown) ? "shown" : "baseState" - } - - EffectSelectionPanel { - id: effectSelectionPanel - anchors { - top: parent.top; - bottom: parameterPanel.top; - margins: 10 - } - x: parent.width - width: parent.width - 40 - opacity: 0.75 - radius: 20 - itemHeight: 50 - - states: [ - State { - name: "shown" - PropertyChanges { - target: effectSelectionPanel - x: 20 - } - } - ] - - transitions: [ - Transition { - from: "*" - to: "*" - NumberAnimation { - properties: "x" - easing.type: Easing.OutQuart - duration: 500 - } - } - ] - - onEffectSourceChanged: { - content.effectSource = effectSource - if (content.effect.parameters.count) { - parameterPanel.model = content.effect.parameters - parameterPanel.enabled = true - } else { - parameterPanel.enabled = false - } - } - - onClicked: state = "baseState" - } - - Rectangle { - id: fileOpenContainer - anchors { - top: parent.top - bottom: parameterPanel.top - margins: 10 - } - x: -width - width: parent.width - 40 - color: "transparent" - - Column { - anchors.fill: parent - - FileOpen { - id: fileOpen - color: "transparent" - width: parent.width - height: 200 - opacity: 0.75 - radius: 20 - buttonHeight: 40 - } - - MouseArea { - width: parent.width - height: 250 - onClicked: fileOpenContainer.state = "baseState" - } - } - - states: [ - State { - name: "shown" - PropertyChanges { - target: fileOpenContainer - x: 20 - } - } - ] - - transitions: [ - Transition { - from: "*" - to: "*" - NumberAnimation { - properties: "x" - easing.type: Easing.OutQuart - duration: 500 - } - } - ] - } - - Rectangle { - id: splashScreen - anchors { - horizontalCenter: parent.horizontalCenter - verticalCenter: parent.verticalCenter - } - width: 300 - height: 200 - radius: 0.1 * height - color: "white" - opacity: 0.9 - border { color: "black"; width: 2 } - - Text { - anchors { - fill: parent - margins: 5 - } - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - font.pixelSize: 24 - text: "Tap on left side to switch between sources.\n\nTap on right side to switch between effects." - wrapMode: Text.WordWrap - } - - MouseArea { - anchors.fill: parent - onClicked: parent.state = "hidden" - } - - states: [ - State { - name: "hidden" - PropertyChanges { - target: splashScreen - opacity: 0.0 - } - } - ] - - transitions: [ - Transition { - from: "*" - to: "*" - NumberAnimation { - properties: "opacity" - easing.type: Easing.OutQuart - duration: 500 - } - } - ] - } - - HintedMouseArea { - id: fileOpenMouseArea - anchors { - left: parent.left; - top: parent.top; - bottom: parameterPanel.top; - topMargin: 75 - } - width: 100 - onClicked: { - fileOpenMouseArea.hintEnabled = false - effectSelectionPanelMouseArea.hintEnabled = false - splashScreen.state = "hidden" - fileOpenContainer.state = "shown" - } - enabled: !d.dialogShown - } - - HintedMouseArea { - id: effectSelectionPanelMouseArea - anchors { - right: parent.right; - top: parent.top; - bottom: parameterPanel.top; - topMargin: 75 - } - width: 100 - onClicked: { - fileOpenMouseArea.hintEnabled = false - effectSelectionPanelMouseArea.hintEnabled = false - splashScreen.state = "hidden" - effectSelectionPanel.state = "shown" - } - enabled: !d.dialogShown - } - - Image { - source: "qrc:/images/close.png" - - anchors { - top: parent.top - right: parent.right - margins: 5 - } - - MouseArea { - anchors.fill: parent - onClicked: Qt.quit() - } - } - } - - Component.onCompleted: { - fileOpen.openImage.connect(openImage) - fileOpen.openVideo.connect(openVideo) - fileOpen.openCamera.connect(openCamera) - fileOpen.close.connect(close) - } - - FileBrowser { - id: imageFileBrowser - anchors.fill: root - Component.onCompleted: fileSelected.connect(content.openImage) - } - - FileBrowser { - id: videoFileBrowser - anchors.fill: root - Component.onCompleted: fileSelected.connect(content.openVideo) - } - - // Called from main() once root properties have been set - function init() { - console.log("[qmlvideofx] main.init") - imageFileBrowser.folder = imagePath - videoFileBrowser.folder = videoPath - content.init() - performanceLoader.init() - if (fileName != "") { - fileOpenMouseArea.hintEnabled = false - effectSelectionPanelMouseArea.hintEnabled = false - splashScreen.state = "hidden" - content.openVideo(fileName) - } - } - - function qmlFramePainted() { - if (performanceLoader.item) - performanceLoader.item.qmlFramePainted() - } - - function openImage() { - fileOpenContainer.state = "baseState" - imageFileBrowser.show() - } - - function openVideo() { - fileOpenContainer.state = "baseState" - videoFileBrowser.show() - } - - function openCamera() { - fileOpenContainer.state = "baseState" - content.openCamera() - } - - function close() { - fileOpenContainer.state = "baseState" - content.openImage("qrc:/images/qt-logo.png") - } -} diff --git a/examples/multimedia/video/qmlvideofx/qmlvideofx.pro b/examples/multimedia/video/qmlvideofx/qmlvideofx.pro index 563444903..e9633954c 100644 --- a/examples/multimedia/video/qmlvideofx/qmlvideofx.pro +++ b/examples/multimedia/video/qmlvideofx/qmlvideofx.pro @@ -10,10 +10,12 @@ RESOURCES += qmlvideofx.qrc include($$PWD/../snippets/performancemonitor/performancemonitordeclarative.pri) -maemo6: { - DEFINES += SMALL_SCREEN_LAYOUT - DEFINES += SMALL_SCREEN_PHYSICAL -} - target.path = $$[QT_INSTALL_EXAMPLES]/multimedia/video/qmlvideofx INSTALLS += target + +ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android + +OTHER_FILES += \ + android/AndroidManifest.xml + +QMAKE_INFO_PLIST = Info.plist diff --git a/examples/multimedia/video/qmlvideofx/qmlvideofx.qrc b/examples/multimedia/video/qmlvideofx/qmlvideofx.qrc index 93cb4f1f5..e7a361246 100644 --- a/examples/multimedia/video/qmlvideofx/qmlvideofx.qrc +++ b/examples/multimedia/video/qmlvideofx/qmlvideofx.qrc @@ -1,10 +1,5 @@ <RCC> <qresource prefix="/"> - <file>images/close.png</file> - <file>images/folder.png</file> - <file>images/titlebar.png</file> - <file>images/titlebar.sci</file> - <file>images/up.png</file> <file>images/qt-logo.png</file> <file>qml/qmlvideofx/Button.qml</file> <file>qml/qmlvideofx/Content.qml</file> @@ -26,12 +21,10 @@ <file>qml/qmlvideofx/EffectPixelate.qml</file> <file>qml/qmlvideofx/EffectPosterize.qml</file> <file>qml/qmlvideofx/EffectRipple.qml</file> - <file>qml/qmlvideofx/EffectSelectionPanel.qml</file> <file>qml/qmlvideofx/EffectSepia.qml</file> <file>qml/qmlvideofx/EffectSharpen.qml</file> <file>qml/qmlvideofx/EffectShockwave.qml</file> <file>qml/qmlvideofx/EffectSobelEdgeDetection1.qml</file> - <file>qml/qmlvideofx/EffectSobelEdgeDetection2.qml</file> <file>qml/qmlvideofx/EffectTiltShift.qml</file> <file>qml/qmlvideofx/EffectToon.qml</file> <file>qml/qmlvideofx/EffectVignette.qml</file> @@ -40,8 +33,6 @@ <file>qml/qmlvideofx/FileBrowser.qml</file> <file>qml/qmlvideofx/FileOpen.qml</file> <file>qml/qmlvideofx/HintedMouseArea.qml</file> - <file>qml/qmlvideofx/main-largescreen.qml</file> - <file>qml/qmlvideofx/main-smallscreen.qml</file> <file>qml/qmlvideofx/ParameterPanel.qml</file> <file>qml/qmlvideofx/Slider.qml</file> <file>shaders/billboard.fsh</file> @@ -61,11 +52,21 @@ <file>shaders/sharpen.fsh</file> <file>shaders/shockwave.fsh</file> <file>shaders/sobeledgedetection1.fsh</file> - <file>shaders/sobeledgedetection2.fsh</file> <file>shaders/tiltshift.fsh</file> <file>shaders/toon.fsh</file> <file>shaders/vignette.fsh</file> <file>shaders/warhol.fsh</file> <file>shaders/wobble.fsh</file> + <file>images/Slider_handle.png</file> + <file>images/Slider_bar.png</file> + <file>qml/qmlvideofx/Curtain.qml</file> + <file>images/Triangle_bottom.png</file> + <file>images/Triangle_Top.png</file> + <file>images/Dropdown_arrows.png</file> + <file>images/icon_Folder.png</file> + <file>images/icon_BackArrow.png</file> + <file>qml/qmlvideofx/Main.qml</file> + <file>images/icon_Menu.png</file> + <file>qml/qmlvideofx/EffectSelectionList.qml</file> </qresource> </RCC> diff --git a/examples/multimediawidgets/camera/doc/src/camera.qdoc b/examples/multimediawidgets/camera/doc/src/camera.qdoc index d1a855d4e..5f6683484 100644 --- a/examples/multimediawidgets/camera/doc/src/camera.qdoc +++ b/examples/multimediawidgets/camera/doc/src/camera.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -35,10 +35,12 @@ \brief The Camera Example shows how to use the API to capture a still image or video. -The Camera Example demonstrates how you can use Qt Multimedia to implement +The Camera Example demonstrates how you can use \l{Qt Multimedia} to implement some basic Camera functionality to take still images and record video clips with audio. +\include examples-run.qdocinc + A Camera class is created that will act as our Camera. It has a user interface, control functions, setting values and a means of defining the location where the image or video clip is to be saved. It will also store the image and video @@ -74,5 +76,3 @@ is started with a call to \l {QMediaRecorder::record()}. \image camera-example.png */ - - diff --git a/examples/multimediawidgets/player/doc/src/player.qdoc b/examples/multimediawidgets/player/doc/src/player.qdoc index 2dfb7c3d0..29121dce4 100644 --- a/examples/multimediawidgets/player/doc/src/player.qdoc +++ b/examples/multimediawidgets/player/doc/src/player.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -34,6 +34,8 @@ This example creates a simple multimedia player. We can play audio and or video files using various codecs. + \include examples-run.qdocinc + The example uses a QMediaPlayer object passed into a QVideoWidget to control the video output. To give the application playlist capability we also use a QPlayList object. @@ -93,4 +95,3 @@ \endcode */ - diff --git a/examples/multimediawidgets/videographicsitem/doc/src/videographicsitem.qdoc b/examples/multimediawidgets/videographicsitem/doc/src/videographicsitem.qdoc index 3ccdba5f5..1e392ce8c 100644 --- a/examples/multimediawidgets/videographicsitem/doc/src/videographicsitem.qdoc +++ b/examples/multimediawidgets/videographicsitem/doc/src/videographicsitem.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -32,9 +32,11 @@ \brief This example demonstrates how to stream video on a graphics scene. The Video Graphics Item example shows how to implement a QGraphicsItem that displays video on a - graphics scene using Qt Multimedia's QAbstractVideoSurface. + graphics scene using \l{Qt Multimedia}'s QAbstractVideoSurface. \image video-videographicsitem.png \sa {Video Widget Example} + + \include examples-run.qdocinc */ diff --git a/examples/multimediawidgets/videowidget/doc/src/videowidget.qdoc b/examples/multimediawidgets/videowidget/doc/src/videowidget.qdoc index 805a830bc..6b93a3c19 100644 --- a/examples/multimediawidgets/videowidget/doc/src/videowidget.qdoc +++ b/examples/multimediawidgets/videowidget/doc/src/videowidget.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -32,7 +32,9 @@ \brief This example is a simple video player The Video Widget example denonstrates how to implement a video widget using - Qt Multimedia's QAbstractVideoSurface. + \l{Qt Multimedia}'s QAbstractVideoSurface. \image video-videowidget.png + + \include examples-run.qdocinc */ diff --git a/qtmultimedia.pro b/qtmultimedia.pro index 1deaab2aa..c7f093ccc 100644 --- a/qtmultimedia.pro +++ b/qtmultimedia.pro @@ -12,7 +12,7 @@ win32 { qtCompileTest(evr) } else:mac { qtCompileTest(avfoundation) -} else:android { +} else:android:!android-no-sdk { SDK_ROOT = $$(ANDROID_SDK_ROOT) isEmpty(SDK_ROOT): SDK_ROOT = $$DEFAULT_ANDROID_SDK_ROOT !exists($$SDK_ROOT/platforms/android-11/android.jar): error("QtMultimedia for Android requires API level 11") diff --git a/src/imports/multimedia/Video.qml b/src/imports/multimedia/Video.qml index 0b8dc1118..9da808462 100644 --- a/src/imports/multimedia/Video.qml +++ b/src/imports/multimedia/Video.qml @@ -85,6 +85,7 @@ import QtMultimedia 5.0 \sa MediaPlayer, VideoOutput +\omit \section1 Screen Saver If it is likely that an application will be playing video for an extended @@ -97,8 +98,11 @@ import QtMultimedia 5.0 ScreenSaver { screenSaverEnabled: false } \endqml +\endomit */ +// TODO: Restore Qt System Info docs when the module is released + Item { id: video diff --git a/src/imports/multimedia/multimedia.cpp b/src/imports/multimedia/multimedia.cpp index 94b697e85..5954db22c 100644 --- a/src/imports/multimedia/multimedia.cpp +++ b/src/imports/multimedia/multimedia.cpp @@ -95,6 +95,11 @@ public: qmlRegisterUncreatableType<QDeclarativeCameraImageProcessing>(uri, 5, 0, "CameraImageProcessing", trUtf8("CameraImageProcessing is provided by Camera")); + // Make types available for the 5.3 version + // Adding "import QtMultimedia 5.3" in QML will fail unless at least one type is registered + // for that version. + qmlRegisterType<QSoundEffect>(uri, 5, 3, "SoundEffect"); + qmlRegisterType<QDeclarativeMediaMetaData>(); } diff --git a/src/imports/multimedia/qdeclarativeaudio.cpp b/src/imports/multimedia/qdeclarativeaudio.cpp index 37509b17e..83e420196 100644 --- a/src/imports/multimedia/qdeclarativeaudio.cpp +++ b/src/imports/multimedia/qdeclarativeaudio.cpp @@ -601,8 +601,14 @@ bool QDeclarativeAudio::hasVideo() const /*! \qmlproperty real QtMultimedia::Audio::bufferProgress - This property holds how much of the data buffer is currently filled, from 0.0 (empty) to 1.0 - (full). + This property holds how much of the data buffer is currently filled, from \c 0.0 (empty) to + \c 1.0 (full). + + Playback can start or resume only when the buffer is entirely filled, in which case the + status is \c Audio.Buffered or \c Audio.Buffering. A value lower than \c 1.0 implies that + the status is \c Audio.Stalled. + + \sa status */ /*! @@ -1394,8 +1400,14 @@ void QDeclarativeAudio::_q_statusChanged() /*! \qmlproperty real QtMultimedia::MediaPlayer::bufferProgress - This property holds how much of the data buffer is currently filled, from 0.0 (empty) to 1.0 - (full). + This property holds how much of the data buffer is currently filled, from \c 0.0 (empty) to + \c 1.0 (full). + + Playback can start or resume only when the buffer is entirely filled, in which case the + status is \c MediaPlayer.Buffered or \c MediaPlayer.Buffering. A value lower than \c 1.0 + implies that the status is \c MediaPlayer.Stalled. + + \sa status */ /*! diff --git a/src/multimedia/audio/qaudio.cpp b/src/multimedia/audio/qaudio.cpp index 13cc2947f..5039729be 100644 --- a/src/multimedia/audio/qaudio.cpp +++ b/src/multimedia/audio/qaudio.cpp @@ -45,23 +45,15 @@ QT_BEGIN_NAMESPACE -namespace QAudio +static void qRegisterAudioMetaTypes() { - -class RegisterMetaTypes -{ -public: - RegisterMetaTypes() - { - qRegisterMetaType<QAudio::Error>(); - qRegisterMetaType<QAudio::State>(); - qRegisterMetaType<QAudio::Mode>(); - } - -} _register; - + qRegisterMetaType<QAudio::Error>(); + qRegisterMetaType<QAudio::State>(); + qRegisterMetaType<QAudio::Mode>(); } +Q_CONSTRUCTOR_FUNCTION(qRegisterAudioMetaTypes) + /*! \namespace QAudio \brief The QAudio namespace contains enums used by the audio classes. diff --git a/src/multimedia/audio/qaudiobuffer.cpp b/src/multimedia/audio/qaudiobuffer.cpp index 586ab4490..3d7346a97 100644 --- a/src/multimedia/audio/qaudiobuffer.cpp +++ b/src/multimedia/audio/qaudiobuffer.cpp @@ -47,18 +47,14 @@ QT_BEGIN_NAMESPACE -namespace + +static void qRegisterAudioBufferMetaTypes() { - class QAudioBufferPrivateRegisterMetaTypes - { - public: - QAudioBufferPrivateRegisterMetaTypes() - { - qRegisterMetaType<QAudioBuffer>(); - } - } _registerMetaTypes; + qRegisterMetaType<QAudioBuffer>(); } +Q_CONSTRUCTOR_FUNCTION(qRegisterAudioBufferMetaTypes) + class QAudioBufferPrivate : public QSharedData { diff --git a/src/multimedia/audio/qaudiodecoder.cpp b/src/multimedia/audio/qaudiodecoder.cpp index 3f0fcd4dd..9397d7419 100644 --- a/src/multimedia/audio/qaudiodecoder.cpp +++ b/src/multimedia/audio/qaudiodecoder.cpp @@ -72,19 +72,14 @@ QT_BEGIN_NAMESPACE \sa QAudioBuffer */ -namespace +static void qRegisterAudioDecoderMetaTypes() { -class AudioDecoderRegisterMetaTypes -{ -public: - AudioDecoderRegisterMetaTypes() - { - qRegisterMetaType<QAudioDecoder::State>("QAudioDecoder::State"); - qRegisterMetaType<QAudioDecoder::Error>("QAudioDecoder::Error"); - } -} _registerPlayerMetaTypes; + qRegisterMetaType<QAudioDecoder::State>("QAudioDecoder::State"); + qRegisterMetaType<QAudioDecoder::Error>("QAudioDecoder::Error"); } +Q_CONSTRUCTOR_FUNCTION(qRegisterAudioDecoderMetaTypes) + class QAudioDecoderPrivate : public QMediaObjectPrivate { Q_DECLARE_NON_CONST_PUBLIC(QAudioDecoder) diff --git a/src/multimedia/audio/qaudiodevicefactory.cpp b/src/multimedia/audio/qaudiodevicefactory.cpp index a36ab3932..50f4a7676 100644 --- a/src/multimedia/audio/qaudiodevicefactory.cpp +++ b/src/multimedia/audio/qaudiodevicefactory.cpp @@ -49,6 +49,11 @@ QT_BEGIN_NAMESPACE +static QString defaultKey() +{ + return QStringLiteral("default"); +} + #if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) Q_GLOBAL_STATIC_WITH_ARGS(QMediaPluginLoader, audioLoader, (QAudioSystemFactoryInterface_iid, QLatin1String("audio"), Qt::CaseInsensitive)) @@ -137,13 +142,18 @@ QList<QAudioDeviceInfo> QAudioDeviceFactory::availableDevices(QAudio::Mode mode) QAudioDeviceInfo QAudioDeviceFactory::defaultInputDevice() { #if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) - QAudioSystemFactoryInterface* plugin = qobject_cast<QAudioSystemFactoryInterface*>(audioLoader()->instance(QLatin1String("default"))); - + QAudioSystemFactoryInterface* plugin = qobject_cast<QAudioSystemFactoryInterface*>(audioLoader()->instance(defaultKey())); if (plugin) { QList<QByteArray> list = plugin->availableDevices(QAudio::AudioInput); if (list.size() > 0) - return QAudioDeviceInfo(QLatin1String("default"), list.at(0), QAudio::AudioInput); + return QAudioDeviceInfo(defaultKey(), list.at(0), QAudio::AudioInput); } + + // if no plugin is marked as default or if the default plugin doesn't have any input device, + // return the first input available from other plugins. + QList<QAudioDeviceInfo> inputDevices = availableDevices(QAudio::AudioInput); + if (!inputDevices.isEmpty()) + return inputDevices.first(); #endif return QAudioDeviceInfo(); @@ -152,13 +162,18 @@ QAudioDeviceInfo QAudioDeviceFactory::defaultInputDevice() QAudioDeviceInfo QAudioDeviceFactory::defaultOutputDevice() { #if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) - QAudioSystemFactoryInterface* plugin = qobject_cast<QAudioSystemFactoryInterface*>(audioLoader()->instance(QLatin1String("default"))); - + QAudioSystemFactoryInterface* plugin = qobject_cast<QAudioSystemFactoryInterface*>(audioLoader()->instance(defaultKey())); if (plugin) { QList<QByteArray> list = plugin->availableDevices(QAudio::AudioOutput); if (list.size() > 0) - return QAudioDeviceInfo(QLatin1String("default"), list.at(0), QAudio::AudioOutput); + return QAudioDeviceInfo(defaultKey(), list.at(0), QAudio::AudioOutput); } + + // if no plugin is marked as default or if the default plugin doesn't have any output device, + // return the first output available from other plugins. + QList<QAudioDeviceInfo> outputDevices = availableDevices(QAudio::AudioOutput); + if (!outputDevices.isEmpty()) + return outputDevices.first(); #endif return QAudioDeviceInfo(); diff --git a/src/multimedia/audio/qaudiodeviceinfo.cpp b/src/multimedia/audio/qaudiodeviceinfo.cpp index ff31f3534..ca42373e2 100644 --- a/src/multimedia/audio/qaudiodeviceinfo.cpp +++ b/src/multimedia/audio/qaudiodeviceinfo.cpp @@ -47,18 +47,13 @@ QT_BEGIN_NAMESPACE -namespace +static void qRegisterAudioDeviceInfoMetaTypes() { - class QAudioInfoPrivateRegisterMetaTypes - { - public: - QAudioInfoPrivateRegisterMetaTypes() - { - qRegisterMetaType<QAudioDeviceInfo>(); - } - } _registerMetaTypes; + qRegisterMetaType<QAudioDeviceInfo>(); } +Q_CONSTRUCTOR_FUNCTION(qRegisterAudioDeviceInfoMetaTypes) + class QAudioDeviceInfoPrivate : public QSharedData { public: diff --git a/src/multimedia/audio/qaudioformat.cpp b/src/multimedia/audio/qaudioformat.cpp index b83256a10..6992bf992 100644 --- a/src/multimedia/audio/qaudioformat.cpp +++ b/src/multimedia/audio/qaudioformat.cpp @@ -44,20 +44,14 @@ QT_BEGIN_NAMESPACE -namespace +static void qRegisterAudioFormatMetaTypes() { - class QAudioFormatPrivateRegisterMetaTypes - { - public: - QAudioFormatPrivateRegisterMetaTypes() - { - qRegisterMetaType<QAudioFormat>(); - qRegisterMetaType<QAudioFormat::SampleType>(); - qRegisterMetaType<QAudioFormat::Endian>(); - } - } _registerMetaTypes; + qRegisterMetaType<QAudioFormat>(); + qRegisterMetaType<QAudioFormat::SampleType>(); + qRegisterMetaType<QAudioFormat::Endian>(); } +Q_CONSTRUCTOR_FUNCTION(qRegisterAudioFormatMetaTypes) class QAudioFormatPrivate : public QSharedData { diff --git a/src/multimedia/camera/qcamera.cpp b/src/multimedia/camera/qcamera.cpp index 32bab0019..84833c6a3 100644 --- a/src/multimedia/camera/qcamera.cpp +++ b/src/multimedia/camera/qcamera.cpp @@ -56,26 +56,21 @@ #include <QDebug> -namespace -{ -class CameraRegisterMetaTypes +QT_BEGIN_NAMESPACE + +static void qRegisterCameraMetaTypes() { -public: - CameraRegisterMetaTypes() - { - qRegisterMetaType<QCamera::Error>("QCamera::Error"); - qRegisterMetaType<QCamera::State>("QCamera::State"); - qRegisterMetaType<QCamera::Status>("QCamera::Status"); - qRegisterMetaType<QCamera::CaptureModes>("QCamera::CaptureModes"); - qRegisterMetaType<QCamera::LockType>("QCamera::LockType"); - qRegisterMetaType<QCamera::LockStatus>("QCamera::LockStatus"); - qRegisterMetaType<QCamera::LockChangeReason>("QCamera::LockChangeReason"); - qRegisterMetaType<QCamera::Position>("QCamera::Position"); - } -} _registerCameraMetaTypes; + qRegisterMetaType<QCamera::Error>("QCamera::Error"); + qRegisterMetaType<QCamera::State>("QCamera::State"); + qRegisterMetaType<QCamera::Status>("QCamera::Status"); + qRegisterMetaType<QCamera::CaptureModes>("QCamera::CaptureModes"); + qRegisterMetaType<QCamera::LockType>("QCamera::LockType"); + qRegisterMetaType<QCamera::LockStatus>("QCamera::LockStatus"); + qRegisterMetaType<QCamera::LockChangeReason>("QCamera::LockChangeReason"); + qRegisterMetaType<QCamera::Position>("QCamera::Position"); } -QT_BEGIN_NAMESPACE +Q_CONSTRUCTOR_FUNCTION(qRegisterCameraMetaTypes) /*! \class QCamera diff --git a/src/multimedia/camera/qcameraexposure.cpp b/src/multimedia/camera/qcameraexposure.cpp index 4385cd4a4..7f1ef842a 100644 --- a/src/multimedia/camera/qcameraexposure.cpp +++ b/src/multimedia/camera/qcameraexposure.cpp @@ -65,20 +65,14 @@ QT_BEGIN_NAMESPACE //#define DEBUG_EXPOSURE_CHANGES 1 -namespace +static void qRegisterCameraExposureMetaTypes() { -class CameraExposureRegisterMetaTypes -{ -public: - CameraExposureRegisterMetaTypes() - { - qRegisterMetaType<QCameraExposure::ExposureMode>("QCameraExposure::ExposureMode"); - qRegisterMetaType<QCameraExposure::FlashModes>("QCameraExposure::FlashModes"); - qRegisterMetaType<QCameraExposure::MeteringMode>("QCameraExposure::MeteringMode"); - } -} _registerCameraExposureMetaTypes; + qRegisterMetaType<QCameraExposure::ExposureMode>("QCameraExposure::ExposureMode"); + qRegisterMetaType<QCameraExposure::FlashModes>("QCameraExposure::FlashModes"); + qRegisterMetaType<QCameraExposure::MeteringMode>("QCameraExposure::MeteringMode"); } +Q_CONSTRUCTOR_FUNCTION(qRegisterCameraExposureMetaTypes) class QCameraExposurePrivate diff --git a/src/multimedia/camera/qcamerafocus.cpp b/src/multimedia/camera/qcamerafocus.cpp index cae285167..0b6d331b4 100644 --- a/src/multimedia/camera/qcamerafocus.cpp +++ b/src/multimedia/camera/qcamerafocus.cpp @@ -55,19 +55,15 @@ QT_BEGIN_NAMESPACE -namespace +static void qRegisterCameraFocusMetaTypes() { -class CameraFocusRegisterMetaTypes -{ -public: - CameraFocusRegisterMetaTypes() - { - qRegisterMetaType<QCameraFocus::FocusModes>("QCameraFocus::FocusModes"); - qRegisterMetaType<QCameraFocus::FocusPointMode>("QCameraFocus::FocusPointMode"); - } -} _registerCameraFocusMetaTypes; + qRegisterMetaType<QCameraFocus::FocusModes>("QCameraFocus::FocusModes"); + qRegisterMetaType<QCameraFocus::FocusPointMode>("QCameraFocus::FocusPointMode"); } +Q_CONSTRUCTOR_FUNCTION(qRegisterCameraFocusMetaTypes) + + class QCameraFocusFakeZoomControl : public QCameraZoomControl { public: diff --git a/src/multimedia/camera/qcameraimagecapture.cpp b/src/multimedia/camera/qcameraimagecapture.cpp index 409db4947..400c2b925 100644 --- a/src/multimedia/camera/qcameraimagecapture.cpp +++ b/src/multimedia/camera/qcameraimagecapture.cpp @@ -83,20 +83,15 @@ QT_BEGIN_NAMESPACE \value CaptureToBuffer Capture the image to a buffer for further processing. */ -namespace +static void qRegisterCameraImageCaptureMetaTypes() { -class MediaRecorderRegisterMetaTypes -{ -public: - MediaRecorderRegisterMetaTypes() - { - qRegisterMetaType<QCameraImageCapture::Error>("QCameraImageCapture::Error"); - qRegisterMetaType<QCameraImageCapture::CaptureDestination>("QCameraImageCapture::CaptureDestination"); - qRegisterMetaType<QCameraImageCapture::CaptureDestinations>("QCameraImageCapture::CaptureDestinations"); - } -} _registerRecorderMetaTypes; + qRegisterMetaType<QCameraImageCapture::Error>("QCameraImageCapture::Error"); + qRegisterMetaType<QCameraImageCapture::CaptureDestination>("QCameraImageCapture::CaptureDestination"); + qRegisterMetaType<QCameraImageCapture::CaptureDestinations>("QCameraImageCapture::CaptureDestinations"); } +Q_CONSTRUCTOR_FUNCTION(qRegisterCameraImageCaptureMetaTypes) + class QCameraImageCapturePrivate { diff --git a/src/multimedia/camera/qcameraimageprocessing.cpp b/src/multimedia/camera/qcameraimageprocessing.cpp index 7df222458..6f08b7860 100644 --- a/src/multimedia/camera/qcameraimageprocessing.cpp +++ b/src/multimedia/camera/qcameraimageprocessing.cpp @@ -52,20 +52,15 @@ #include <QtCore/QDebug> -namespace -{ - class QCameraImageProcessingPrivateRegisterMetaTypes - { - public: - QCameraImageProcessingPrivateRegisterMetaTypes() +QT_BEGIN_NAMESPACE + +static void qRegisterCameraImageProcessingMetaTypes() { qRegisterMetaType<QCameraImageProcessing::WhiteBalanceMode>(); } - } _registerMetaTypes; -} +Q_CONSTRUCTOR_FUNCTION(qRegisterCameraImageProcessingMetaTypes) -QT_BEGIN_NAMESPACE /*! \class QCameraImageProcessing diff --git a/src/multimedia/controls/qcameraimageprocessingcontrol.cpp b/src/multimedia/controls/qcameraimageprocessingcontrol.cpp index f9cb8c86f..944b09643 100644 --- a/src/multimedia/controls/qcameraimageprocessingcontrol.cpp +++ b/src/multimedia/controls/qcameraimageprocessingcontrol.cpp @@ -44,18 +44,13 @@ QT_BEGIN_NAMESPACE -namespace +static void qRegisterCameraImageProcessingControlMetaTypes() { - class QCameraImageProcessingControlPrivateRegisterMetaTypes - { - public: - QCameraImageProcessingControlPrivateRegisterMetaTypes() - { - qRegisterMetaType<QCameraImageProcessingControl::ProcessingParameter>(); - } - } _registerMetaTypes; + qRegisterMetaType<QCameraImageProcessingControl::ProcessingParameter>(); } +Q_CONSTRUCTOR_FUNCTION(qRegisterCameraImageProcessingControlMetaTypes) + /*! \class QCameraImageProcessingControl \inmodule QtMultimedia diff --git a/src/multimedia/controls/qmediastreamscontrol.cpp b/src/multimedia/controls/qmediastreamscontrol.cpp index a054289f7..11d31599d 100644 --- a/src/multimedia/controls/qmediastreamscontrol.cpp +++ b/src/multimedia/controls/qmediastreamscontrol.cpp @@ -44,18 +44,14 @@ QT_BEGIN_NAMESPACE -namespace +static void qRegisterMediaStreamControlMetaTypes() { - class QMediaStreamsControlPrivateRegisterMetaTypes - { - public: - QMediaStreamsControlPrivateRegisterMetaTypes() - { - qRegisterMetaType<QMediaStreamsControl::StreamType>(); - } - } _registerMetaTypes; + qRegisterMetaType<QMediaStreamsControl::StreamType>(); } +Q_CONSTRUCTOR_FUNCTION(qRegisterMediaStreamControlMetaTypes) + + /*! \class QMediaStreamsControl \inmodule QtMultimedia diff --git a/src/multimedia/doc/src/audiooverview.qdoc b/src/multimedia/doc/src/audiooverview.qdoc index 54735da6c..32556543b 100644 --- a/src/multimedia/doc/src/audiooverview.qdoc +++ b/src/multimedia/doc/src/audiooverview.qdoc @@ -116,18 +116,14 @@ code but more buffering, which may affect latency. \section2 Decoding Compressed Audio to Memory In some cases you may want to decode a compressed audio file and do further -processing yourself (like mix multiple samples, or some custom digital signal -processing algorithms). Qt Multimedia 5.0 offers a preliminary API for this -case - the \l QAudioDecoder class. QAudioDecoder supports decoding local files -or from a QIODevice instances. +processing yourself (for example, mixing multiple samples or using custom +digital signal processing algorithms). QAudioDecoder supports decoding local +files or data streams from QIODevice instances. Here's an example of decoding a local file: \snippet multimedia-snippets/audio.cpp Local audio decoding -Note: This API is preliminary at this time - the API may change or be -removed before the final 5.0 release. - \section1 Examples There are both C++ and QML examples available. diff --git a/src/multimedia/multimedia.pro b/src/multimedia/multimedia.pro index 23cca2537..0f3ced913 100644 --- a/src/multimedia/multimedia.pro +++ b/src/multimedia/multimedia.pro @@ -21,7 +21,8 @@ PRIVATE_HEADERS += \ qmediaserviceprovider_p.h \ qmediaresourcepolicyplugin_p.h \ qmediaresourcepolicy_p.h \ - qmediaresourceset_p.h + qmediaresourceset_p.h \ + qmediastoragelocation_p.h PUBLIC_HEADERS += \ qmediabindableinterface.h \ @@ -47,6 +48,7 @@ SOURCES += \ qmediaresourcepolicyplugin_p.cpp \ qmediaresourcepolicy_p.cpp \ qmediaresourceset_p.cpp \ + qmediastoragelocation.cpp \ qmultimedia.cpp include(audio/audio.pri) diff --git a/src/multimedia/playback/playlistfileparser.cpp b/src/multimedia/playback/playlistfileparser.cpp index ae14d2159..1254d6131 100644 --- a/src/multimedia/playback/playlistfileparser.cpp +++ b/src/multimedia/playback/playlistfileparser.cpp @@ -307,9 +307,9 @@ Version=2 void setCount(int count) { m_count = count; - m_fileName = QString(tr("File%1")).arg(count); - m_titleName = QString(tr("Title%1")).arg(count); - m_lengthName = QString(tr("Length%1")).arg(count); + m_fileName = QStringLiteral("File%1").arg(count); + m_titleName = QStringLiteral("Title%1").arg(count); + m_lengthName = QStringLiteral("Length%1").arg(count); m_item.clear(); m_readFlags = 0; } diff --git a/src/multimedia/playback/qmediacontent.cpp b/src/multimedia/playback/qmediacontent.cpp index 4c32128f5..ff3ed28d3 100644 --- a/src/multimedia/playback/qmediacontent.cpp +++ b/src/multimedia/playback/qmediacontent.cpp @@ -48,18 +48,13 @@ QT_BEGIN_NAMESPACE -namespace +static void qRegisterMediaContentMetaTypes() { - class QMediaContentPrivateRegisterMetaTypes - { - public: - QMediaContentPrivateRegisterMetaTypes() - { - qRegisterMetaType<QMediaContent>(); - } - } _registerMetaTypes; + qRegisterMetaType<QMediaContent>(); } +Q_CONSTRUCTOR_FUNCTION(qRegisterMediaContentMetaTypes) + class QMediaContentPrivate : public QSharedData { diff --git a/src/multimedia/playback/qmediaplayer.cpp b/src/multimedia/playback/qmediaplayer.cpp index bf6294a1e..e8899ddff 100644 --- a/src/multimedia/playback/qmediaplayer.cpp +++ b/src/multimedia/playback/qmediaplayer.cpp @@ -90,20 +90,16 @@ QT_BEGIN_NAMESPACE \sa QMediaObject, QMediaService, QVideoWidget, QMediaPlaylist */ -namespace +static void qRegisterMediaPlayerMetaTypes() { -class MediaPlayerRegisterMetaTypes -{ -public: - MediaPlayerRegisterMetaTypes() - { - qRegisterMetaType<QMediaPlayer::State>("QMediaPlayer::State"); - qRegisterMetaType<QMediaPlayer::MediaStatus>("QMediaPlayer::MediaStatus"); - qRegisterMetaType<QMediaPlayer::Error>("QMediaPlayer::Error"); - } -} _registerPlayerMetaTypes; + qRegisterMetaType<QMediaPlayer::State>("QMediaPlayer::State"); + qRegisterMetaType<QMediaPlayer::MediaStatus>("QMediaPlayer::MediaStatus"); + qRegisterMetaType<QMediaPlayer::Error>("QMediaPlayer::Error"); } +Q_CONSTRUCTOR_FUNCTION(qRegisterMediaPlayerMetaTypes) + + #define MAX_NESTED_PLAYLISTS 16 class QMediaPlayerPrivate : public QMediaObjectPrivate @@ -1238,12 +1234,14 @@ QMultimedia::AvailabilityStatus QMediaPlayer::availability() const /*! \property QMediaPlayer::bufferStatus - \brief the percentage of the temporary buffer filled before playback begins. + \brief the percentage of the temporary buffer filled before playback begins or resumes, from + \c 0 (empty) to \c 100 (full). When the player object is buffering; this property holds the percentage of the temporary buffer that is filled. The buffer will need to reach 100% - filled before playback can resume, at which time the MediaStatus will be - BufferedMedia. + filled before playback can start or resume, at which time mediaStatus() will return + BufferedMedia or BufferingMedia. If the value is anything lower than \c 100, mediaStatus() will + return StalledMedia. \sa mediaStatus() */ diff --git a/src/multimedia/playback/qmediaplaylist.cpp b/src/multimedia/playback/qmediaplaylist.cpp index 68a8917f5..a81681079 100644 --- a/src/multimedia/playback/qmediaplaylist.cpp +++ b/src/multimedia/playback/qmediaplaylist.cpp @@ -61,19 +61,14 @@ QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC_WITH_ARGS(QMediaPluginLoader, playlistIOLoader, (QMediaPlaylistIOInterface_iid, QLatin1String("playlistformats"), Qt::CaseInsensitive)) -namespace -{ - class QMediaPlaylistPrivateRegisterMetaTypes - { - public: - QMediaPlaylistPrivateRegisterMetaTypes() - { - qRegisterMetaType<QMediaPlaylist::Error>(); - qRegisterMetaType<QMediaPlaylist::PlaybackMode>(); - } - } _registerMetaTypes; +static void qRegisterMediaPlaylistMetaTypes() +{ + qRegisterMetaType<QMediaPlaylist::Error>(); + qRegisterMetaType<QMediaPlaylist::PlaybackMode>(); } +Q_CONSTRUCTOR_FUNCTION(qRegisterMediaPlaylistMetaTypes) + /*! \class QMediaPlaylist diff --git a/src/multimedia/playback/qmediaresource.cpp b/src/multimedia/playback/qmediaresource.cpp index 62c982ca7..4997620a9 100644 --- a/src/multimedia/playback/qmediaresource.cpp +++ b/src/multimedia/playback/qmediaresource.cpp @@ -47,19 +47,15 @@ QT_BEGIN_NAMESPACE -namespace -{ - class QMediaResourcePrivateRegisterMetaTypes - { - public: - QMediaResourcePrivateRegisterMetaTypes() - { - qRegisterMetaType<QMediaResource>(); - qRegisterMetaType<QMediaResourceList>(); - } - } _registerMetaTypes; +static void qRegisterMediaResourceMetaTypes() +{ + qRegisterMetaType<QMediaResource>(); + qRegisterMetaType<QMediaResourceList>(); } +Q_CONSTRUCTOR_FUNCTION(qRegisterMediaResourceMetaTypes) + + /*! \class QMediaResource diff --git a/src/plugins/android/src/mediacapture/qandroidmediastoragelocation.cpp b/src/multimedia/qmediastoragelocation.cpp index 2bd3da195..877c12138 100644 --- a/src/plugins/android/src/mediacapture/qandroidmediastoragelocation.cpp +++ b/src/multimedia/qmediastoragelocation.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Toolkit. @@ -39,24 +39,40 @@ ** ****************************************************************************/ -#include "qandroidmediastoragelocation.h" +#include "qmediastoragelocation_p.h" -#include "jmultimediautils.h" +#include <QStandardPaths> QT_BEGIN_NAMESPACE -QAndroidMediaStorageLocation::QAndroidMediaStorageLocation() +QMediaStorageLocation::QMediaStorageLocation() { } -QDir QAndroidMediaStorageLocation::defaultDir(CaptureSource source) const +void QMediaStorageLocation::addStorageLocation(MediaType type, const QString &location) +{ + m_customLocations[type].append(location); +} + +QDir QMediaStorageLocation::defaultLocation(MediaType type) const { QStringList dirCandidates; - if (source == Camera) - dirCandidates << JMultimediaUtils::getDefaultMediaDirectory(JMultimediaUtils::DCIM); - else - dirCandidates << JMultimediaUtils::getDefaultMediaDirectory(JMultimediaUtils::Sounds); + dirCandidates << m_customLocations.value(type); + + switch (type) { + case Movies: + dirCandidates << QStandardPaths::writableLocation(QStandardPaths::MoviesLocation); + break; + case Music: + dirCandidates << QStandardPaths::writableLocation(QStandardPaths::MusicLocation); + break; + case Pictures: + dirCandidates << QStandardPaths::writableLocation(QStandardPaths::PicturesLocation); + default: + break; + } + dirCandidates << QDir::homePath(); dirCandidates << QDir::currentPath(); dirCandidates << QDir::tempPath(); @@ -69,31 +85,31 @@ QDir QAndroidMediaStorageLocation::defaultDir(CaptureSource source) const return QDir(); } -QString QAndroidMediaStorageLocation::generateFileName(const QString &requestedName, - CaptureSource source, - const QString &prefix, - const QString &extension) const +QString QMediaStorageLocation::generateFileName(const QString &requestedName, + MediaType type, + const QString &prefix, + const QString &extension) const { if (requestedName.isEmpty()) - return generateFileName(prefix, defaultDir(source), extension); + return generateFileName(prefix, defaultLocation(type), extension); QString path = requestedName; if (QFileInfo(path).isRelative()) - path = defaultDir(source).absoluteFilePath(path); + path = defaultLocation(type).absoluteFilePath(path); if (QFileInfo(path).isDir()) return generateFileName(prefix, QDir(path), extension); if (!path.endsWith(extension)) - path.append(QString(".%1").arg(extension)); + path.append(QString(QLatin1String(".%1")).arg(extension)); return path; } -QString QAndroidMediaStorageLocation::generateFileName(const QString &prefix, - const QDir &dir, - const QString &extension) const +QString QMediaStorageLocation::generateFileName(const QString &prefix, + const QDir &dir, + const QString &extension) const { QMutexLocker lock(&m_mutex); @@ -102,7 +118,7 @@ QString QAndroidMediaStorageLocation::generateFileName(const QString &prefix, 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))) { + Q_FOREACH (const QString &fileName, dir.entryList(QStringList() << QString(QLatin1String("%1*.%2")).arg(prefix).arg(extension))) { const qint64 mediaIndex = fileName.midRef(prefix.length(), fileName.size() - prefix.length() - extension.length() - 1).toInt(); lastMediaIndex = qMax(lastMediaIndex, mediaIndex); } @@ -111,7 +127,7 @@ QString QAndroidMediaStorageLocation::generateFileName(const QString &prefix, // 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) + const QString name = QString(QLatin1String("%1%2.%3")).arg(prefix) .arg(lastMediaIndex + 1, 8, 10, QLatin1Char('0')) .arg(extension); diff --git a/src/plugins/android/src/mediacapture/qandroidmediastoragelocation.h b/src/multimedia/qmediastoragelocation_p.h index 2e63f3df5..600fb63ff 100644 --- a/src/plugins/android/src/mediacapture/qandroidmediastoragelocation.h +++ b/src/multimedia/qmediastoragelocation_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Toolkit. @@ -39,37 +39,42 @@ ** ****************************************************************************/ -#ifndef QANDROIDMEDIASTORAGELOCATION_H -#define QANDROIDMEDIASTORAGELOCATION_H +#ifndef QMEDIASTORAGELOCATION_H +#define QMEDIASTORAGELOCATION_H -#include <QCamera> +#include <qtmultimediadefs.h> #include <QDir> +#include <QMap> #include <QHash> #include <QMutex> QT_BEGIN_NAMESPACE -class QAndroidMediaStorageLocation +class Q_MULTIMEDIA_EXPORT QMediaStorageLocation { public: - enum CaptureSource { - Camera, - Audio + enum MediaType { + Movies, + Music, + Pictures, + Sounds }; - QAndroidMediaStorageLocation(); + QMediaStorageLocation(); - QDir defaultDir(CaptureSource source) const; + void addStorageLocation(MediaType type, const QString &location); - QString generateFileName(const QString &requestedName, CaptureSource source, const QString &prefix, const QString &extension) const; + QDir defaultLocation(MediaType type) const; + + QString generateFileName(const QString &requestedName, MediaType type, 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; + mutable QHash<QString, qint64> m_lastUsedIndex; + QMap<MediaType, QStringList> m_customLocations; }; QT_END_NAMESPACE -#endif // QANDROIDMEDIASTORAGELOCATION_H +#endif // QMEDIASTORAGELOCATION_H diff --git a/src/multimedia/qmultimedia.cpp b/src/multimedia/qmultimedia.cpp index 0f4d98f7f..140d4a348 100644 --- a/src/multimedia/qmultimedia.cpp +++ b/src/multimedia/qmultimedia.cpp @@ -41,21 +41,17 @@ QT_BEGIN_NAMESPACE */ -namespace +static void qRegisterMultimediaMetaTypes() { - class QMultimediaNamespacePrivateRegisterMetaTypes - { - public: - QMultimediaNamespacePrivateRegisterMetaTypes() - { - qRegisterMetaType<QMultimedia::AvailabilityStatus>(); - qRegisterMetaType<QMultimedia::SupportEstimate>(); - qRegisterMetaType<QMultimedia::EncodingMode>(); - qRegisterMetaType<QMultimedia::EncodingQuality>(); - } - } _registerMetaTypes; + qRegisterMetaType<QMultimedia::AvailabilityStatus>(); + qRegisterMetaType<QMultimedia::SupportEstimate>(); + qRegisterMetaType<QMultimedia::EncodingMode>(); + qRegisterMetaType<QMultimedia::EncodingQuality>(); } +Q_CONSTRUCTOR_FUNCTION(qRegisterMultimediaMetaTypes) + + /*! \enum QMultimedia::SupportEstimate diff --git a/src/multimedia/radio/qradiodata.cpp b/src/multimedia/radio/qradiodata.cpp index 66b051a47..d6bde35ba 100644 --- a/src/multimedia/radio/qradiodata.cpp +++ b/src/multimedia/radio/qradiodata.cpp @@ -50,20 +50,15 @@ QT_BEGIN_NAMESPACE - -namespace +static void qRegisterRadioDataMetaTypes() { - class QRadioDataPrivateRegisterMetaTypes - { - public: - QRadioDataPrivateRegisterMetaTypes() - { - qRegisterMetaType<QRadioData::Error>(); - qRegisterMetaType<QRadioData::ProgramType>(); - } - } _registerMetaTypes; + qRegisterMetaType<QRadioData::Error>(); + qRegisterMetaType<QRadioData::ProgramType>(); } +Q_CONSTRUCTOR_FUNCTION(qRegisterRadioDataMetaTypes) + + /*! \class QRadioData \brief The QRadioData class provides interfaces to the RDS functionality of the system radio. diff --git a/src/multimedia/radio/qradiotuner.cpp b/src/multimedia/radio/qradiotuner.cpp index 9255783d0..29a0d6d37 100644 --- a/src/multimedia/radio/qradiotuner.cpp +++ b/src/multimedia/radio/qradiotuner.cpp @@ -52,22 +52,17 @@ QT_BEGIN_NAMESPACE -namespace -{ - class QRadioTunerPrivateRegisterMetaTypes - { - public: - QRadioTunerPrivateRegisterMetaTypes() - { - qRegisterMetaType<QRadioTuner::Band>(); - qRegisterMetaType<QRadioTuner::Error>(); - qRegisterMetaType<QRadioTuner::SearchMode>(); - qRegisterMetaType<QRadioTuner::State>(); - qRegisterMetaType<QRadioTuner::StereoMode>(); - } - } _registerMetaTypes; +static void qRegisterRadioTunerMetaTypes() +{ + qRegisterMetaType<QRadioTuner::Band>(); + qRegisterMetaType<QRadioTuner::Error>(); + qRegisterMetaType<QRadioTuner::SearchMode>(); + qRegisterMetaType<QRadioTuner::State>(); + qRegisterMetaType<QRadioTuner::StereoMode>(); } +Q_CONSTRUCTOR_FUNCTION(qRegisterRadioTunerMetaTypes) + /*! \class QRadioTuner diff --git a/src/multimedia/recording/qmediaencodersettings.cpp b/src/multimedia/recording/qmediaencodersettings.cpp index 731692643..e75115116 100644 --- a/src/multimedia/recording/qmediaencodersettings.cpp +++ b/src/multimedia/recording/qmediaencodersettings.cpp @@ -43,20 +43,16 @@ QT_BEGIN_NAMESPACE -namespace +static void qRegisterEncoderSettingsMetaTypes() { -class QMediaEncoderSettingsPrivateRegisterMetaTypes -{ -public: - QMediaEncoderSettingsPrivateRegisterMetaTypes() - { - qRegisterMetaType<QAudioEncoderSettings>(); - qRegisterMetaType<QVideoEncoderSettings>(); - qRegisterMetaType<QImageEncoderSettings>(); - } -} _registerMetaTypes; + qRegisterMetaType<QAudioEncoderSettings>(); + qRegisterMetaType<QVideoEncoderSettings>(); + qRegisterMetaType<QImageEncoderSettings>(); } +Q_CONSTRUCTOR_FUNCTION(qRegisterEncoderSettingsMetaTypes) + + class QAudioEncoderSettingsPrivate : public QSharedData { public: diff --git a/src/multimedia/recording/qmediarecorder.cpp b/src/multimedia/recording/qmediarecorder.cpp index f38de025c..7c28caf98 100644 --- a/src/multimedia/recording/qmediarecorder.cpp +++ b/src/multimedia/recording/qmediarecorder.cpp @@ -80,20 +80,16 @@ QT_BEGIN_NAMESPACE \sa QAudioRecorder */ -namespace +static void qRegisterMediaRecorderMetaTypes() { -class MediaRecorderRegisterMetaTypes -{ -public: - MediaRecorderRegisterMetaTypes() - { - qRegisterMetaType<QMediaRecorder::State>("QMediaRecorder::State"); - qRegisterMetaType<QMediaRecorder::Status>("QMediaRecorder::Status"); - qRegisterMetaType<QMediaRecorder::Error>("QMediaRecorder::Error"); - } -} _registerRecorderMetaTypes; + qRegisterMetaType<QMediaRecorder::State>("QMediaRecorder::State"); + qRegisterMetaType<QMediaRecorder::Status>("QMediaRecorder::Status"); + qRegisterMetaType<QMediaRecorder::Error>("QMediaRecorder::Error"); } +Q_CONSTRUCTOR_FUNCTION(qRegisterMediaRecorderMetaTypes) + + QMediaRecorderPrivate::QMediaRecorderPrivate(): mediaObject(0), control(0), diff --git a/src/multimedia/video/qabstractvideobuffer.cpp b/src/multimedia/video/qabstractvideobuffer.cpp index 5f69382e3..79da6f9b7 100644 --- a/src/multimedia/video/qabstractvideobuffer.cpp +++ b/src/multimedia/video/qabstractvideobuffer.cpp @@ -48,19 +48,15 @@ QT_BEGIN_NAMESPACE -namespace +static void qRegisterAbstractVideoBufferMetaTypes() { - class QAbstractVideoBufferPrivateRegisterMetaTypes - { - public: - QAbstractVideoBufferPrivateRegisterMetaTypes() - { - qRegisterMetaType<QAbstractVideoBuffer::HandleType>(); - qRegisterMetaType<QAbstractVideoBuffer::MapMode>(); - } - } _registerMetaTypes; + qRegisterMetaType<QAbstractVideoBuffer::HandleType>(); + qRegisterMetaType<QAbstractVideoBuffer::MapMode>(); } +Q_CONSTRUCTOR_FUNCTION(qRegisterAbstractVideoBufferMetaTypes) + + /*! \class QAbstractVideoBuffer \brief The QAbstractVideoBuffer class is an abstraction for video data. diff --git a/src/multimedia/video/qabstractvideosurface.cpp b/src/multimedia/video/qabstractvideosurface.cpp index e62c514d7..ff9356122 100644 --- a/src/multimedia/video/qabstractvideosurface.cpp +++ b/src/multimedia/video/qabstractvideosurface.cpp @@ -50,18 +50,13 @@ QT_BEGIN_NAMESPACE -namespace +static void qRegisterAbstractVideoSurfaceMetaTypes() { - class QAbstractVideoSurfacePrivateRegisterMetaTypes - { - public: - QAbstractVideoSurfacePrivateRegisterMetaTypes() - { - qRegisterMetaType<QAbstractVideoSurface::Error>(); - } - } _registerMetaTypes; + qRegisterMetaType<QAbstractVideoSurface::Error>(); } +Q_CONSTRUCTOR_FUNCTION(qRegisterAbstractVideoSurfaceMetaTypes) + class QAbstractVideoSurfacePrivate { public: diff --git a/src/multimedia/video/qvideoframe.cpp b/src/multimedia/video/qvideoframe.cpp index e4ce21361..4a32bc557 100644 --- a/src/multimedia/video/qvideoframe.cpp +++ b/src/multimedia/video/qvideoframe.cpp @@ -55,20 +55,15 @@ QT_BEGIN_NAMESPACE -namespace +static void qRegisterVideoFrameMetaTypes() { -class QVideoFramePrivateRegisterMetaTypes -{ -public: - QVideoFramePrivateRegisterMetaTypes() - { - qRegisterMetaType<QVideoFrame>(); - qRegisterMetaType<QVideoFrame::FieldType>(); - qRegisterMetaType<QVideoFrame::PixelFormat>(); - } -} _registerMetaTypes; + qRegisterMetaType<QVideoFrame>(); + qRegisterMetaType<QVideoFrame::FieldType>(); + qRegisterMetaType<QVideoFrame::PixelFormat>(); } +Q_CONSTRUCTOR_FUNCTION(qRegisterVideoFrameMetaTypes) + class QVideoFramePrivate : public QSharedData { diff --git a/src/multimedia/video/qvideosurfaceformat.cpp b/src/multimedia/video/qvideosurfaceformat.cpp index 5806f3b9b..56814f478 100644 --- a/src/multimedia/video/qvideosurfaceformat.cpp +++ b/src/multimedia/video/qvideosurfaceformat.cpp @@ -49,20 +49,15 @@ QT_BEGIN_NAMESPACE -namespace +static void qRegisterVideoSurfaceFormatMetaTypes() { - class QVideoSurfaceFormatPrivateRegisterMetaTypes - { - public: - QVideoSurfaceFormatPrivateRegisterMetaTypes() - { - qRegisterMetaType<QVideoSurfaceFormat>(); - qRegisterMetaType<QVideoSurfaceFormat::Direction>(); - qRegisterMetaType<QVideoSurfaceFormat::YCbCrColorSpace>(); - } - } _registerMetaTypes; + qRegisterMetaType<QVideoSurfaceFormat>(); + qRegisterMetaType<QVideoSurfaceFormat::Direction>(); + qRegisterMetaType<QVideoSurfaceFormat::YCbCrColorSpace>(); } +Q_CONSTRUCTOR_FUNCTION(qRegisterVideoSurfaceFormatMetaTypes) + class QVideoSurfaceFormatPrivate : public QSharedData { diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSobelEdgeDetection2.qml b/src/multimediawidgets/doc/snippets/multimedia-snippets/camera.cpp index 33336537f..70c3cb6fb 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSobelEdgeDetection2.qml +++ b/src/multimediawidgets/doc/snippets/multimedia-snippets/camera.cpp @@ -3,7 +3,7 @@ ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** -** This file is part of the Qt Mobility Components. +** This file is part of the documentation of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage @@ -39,18 +39,30 @@ ** ****************************************************************************/ -import QtQuick 2.0 +// Camera snippets +// Extracted from src/multimedia/doc/snippets/multimedia-snippets/camera.cpp +#include "qcamera.h" +#include "qcameraviewfinder.h" +#include "qcameraimagecapture.h" -Effect { - parameters: ListModel { - ListElement { - name: "threshold" - value: 0.5 - } - } +/* Globals so that everything is consistent. */ +QCamera *camera = 0; +QCameraViewfinder *viewfinder = 0; +QCameraImageCapture *imageCapture = 0; - // Transform slider values, and bind result to shader uniforms - property real weight: parameters.get(0).value +void camera_blah() +{ + //! [Camera] + camera = new QCamera; - fragmentShaderFilename: "sobeledgedetection2.fsh" + viewfinder = new QCameraViewfinder(); + viewfinder->show(); + + camera->setViewfinder(viewfinder); + + imageCapture = new QCameraImageCapture(camera); + + camera->setCaptureMode(QCamera::CaptureStillImage); + camera->start(); + //! [Camera] } diff --git a/src/multimediawidgets/doc/snippets/multimedia-snippets/video.cpp b/src/multimediawidgets/doc/snippets/multimedia-snippets/video.cpp new file mode 100644 index 000000000..717419409 --- /dev/null +++ b/src/multimediawidgets/doc/snippets/multimedia-snippets/video.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the documentation 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$ +** +****************************************************************************/ + +// Video related snippets +// Extracted from src/multimedia/doc/snippets/multimedia-snippets/video.cpp +#include "qmediaservice.h" +#include "qmediaplayer.h" +#include "qvideowidgetcontrol.h" +#include "qvideowindowcontrol.h" +#include "qgraphicsvideoitem.h" +#include "qmediaplaylist.h" + +#include <QFormLayout> +#include <QGraphicsView> + +class VideoExample : public QObject { + Q_OBJECT +public: + void VideoGraphicsItem(); + void VideoWidget(); + void VideoWidgetControl(); + +private: + // Common naming + QMediaService *mediaService; + QMediaPlaylist *playlist; + QVideoWidget *videoWidget; + QFormLayout *layout; + QMediaPlayer *player; + QGraphicsView *graphicsView; +}; + +void VideoExample::VideoWidget() +{ + //! [Video widget] + player = new QMediaPlayer; + + playlist = new QMediaPlaylist(player); + playlist->addMedia(QUrl("http://example.com/myclip1.mp4")); + playlist->addMedia(QUrl("http://example.com/myclip2.mp4")); + + videoWidget = new QVideoWidget; + player->setVideoOutput(videoWidget); + + videoWidget->show(); + playlist->setCurrentIndex(1); + player->play(); + //! [Video widget] + + player->stop(); +} + +void VideoExample::VideoWidgetControl() +{ + //! [Video widget control] + QVideoWidgetControl *widgetControl = mediaService->requestControl<QVideoWidgetControl *>(); + layout->addWidget(widgetControl->videoWidget()); + //! [Video widget control] +} + +void VideoExample::VideoGraphicsItem() +{ + //! [Video graphics item] + player = new QMediaPlayer(this); + + QGraphicsVideoItem *item = new QGraphicsVideoItem; + player->setVideoOutput(item); + graphicsView->scene()->addItem(item); + graphicsView->show(); + + player->setMedia(QUrl("http://example.com/myclip4.ogv")); + player->play(); + //! [Video graphics item] +} diff --git a/src/plugins/android/android.pro b/src/plugins/android/android.pro index 807f8ece8..fa322942b 100644 --- a/src/plugins/android/android.pro +++ b/src/plugins/android/android.pro @@ -1,7 +1,7 @@ TEMPLATE = subdirs -SUBDIRS += src \ - jar +SUBDIRS += src +android:!android-no-sdk: SUBDIRS += jar qtHaveModule(quick) { SUBDIRS += videonode diff --git a/src/plugins/android/jar/jar.pri b/src/plugins/android/jar/jar.pri index d8bc59a72..d31839c61 100644 --- a/src/plugins/android/jar/jar.pri +++ b/src/plugins/android/jar/jar.pri @@ -6,7 +6,7 @@ API_VERSION = android-11 JAVACLASSPATH += $$PWD/src JAVASOURCES += $$PWD/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java \ - $$PWD/src/org/qtproject/qt5/android/multimedia/QtCamera.java \ + $$PWD/src/org/qtproject/qt5/android/multimedia/QtCameraListener.java \ $$PWD/src/org/qtproject/qt5/android/multimedia/QtSurfaceTextureListener.java \ $$PWD/src/org/qtproject/qt5/android/multimedia/QtSurfaceTextureHolder.java \ $$PWD/src/org/qtproject/qt5/android/multimedia/QtMultimediaUtils.java \ diff --git a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java index 86ec30a5f..ff92af771 100644 --- a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java +++ b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java @@ -43,6 +43,7 @@ package org.qtproject.qt5.android.multimedia; import java.io.IOException; import java.lang.String; +import java.io.FileInputStream; // API is level is < 9 unless marked otherwise. import android.app.Activity; @@ -247,6 +248,8 @@ public class QtAndroidMediaPlayer if (mMediaPlayer == null) { mMediaPlayer = new MediaPlayer(); setState(State.Idle); + // Make sure the new media player has the volume that was set on the QMediaPlayer + setVolumeHelper(mMuted ? 0 : mVolume); } } @@ -376,6 +379,7 @@ public class QtAndroidMediaPlayer mMediaPlayer.setDisplay(mSurfaceHolder); AssetFileDescriptor afd = null; + FileInputStream fis = null; try { mUri = Uri.parse(path); final boolean inAssets = (mUri.getScheme().compareTo("assets") == 0); @@ -387,6 +391,10 @@ public class QtAndroidMediaPlayer final long length = afd.getLength(); FileDescriptor fd = afd.getFileDescriptor(); mMediaPlayer.setDataSource(fd, offset, length); + } else if (mUri.getScheme().compareTo("file") == 0) { + fis = new FileInputStream(mUri.getPath()); + FileDescriptor fd = fis.getFD(); + mMediaPlayer.setDataSource(fd); } else { mMediaPlayer.setDataSource(mActivity, mUri); } @@ -402,9 +410,13 @@ public class QtAndroidMediaPlayer } catch (final NullPointerException e) { Log.d(TAG, "" + e.getMessage()); } finally { - if (afd !=null) { - try { afd.close(); } catch (final IOException ioe) { /* Ignore... */ } - } + try { + if (afd != null) + afd.close(); + if (fis != null) + fis.close(); + } catch (final IOException ioe) { /* Ignore... */ } + if ((mState & State.Initialized) == 0) { setState(State.Error); onErrorNative(MediaPlayer.MEDIA_ERROR_UNKNOWN, @@ -472,6 +484,20 @@ public class QtAndroidMediaPlayer public void setVolume(int volume) { + if (volume < 0) + volume = 0; + + if (volume > 100) + volume = 100; + + mVolume = volume; + + if (!mMuted) + setVolumeHelper(mVolume); + } + + private void setVolumeHelper(int volume) + { if ((mState & (State.Idle | State.Initialized | State.Stopped @@ -482,18 +508,9 @@ public class QtAndroidMediaPlayer return; } - if (volume < 0) - volume = 0; - - if (volume > 100) - volume = 100; - - float newVolume = adjustVolume(volume); - try { + float newVolume = adjustVolume(volume); mMediaPlayer.setVolume(newVolume, newVolume); - if (!mMuted) - mVolume = volume; } catch (final IllegalStateException e) { Log.d(TAG, "" + e.getMessage()); } @@ -523,7 +540,7 @@ public class QtAndroidMediaPlayer public void mute(final boolean mute) { mMuted = mute; - setVolume(mute ? 0 : mVolume); + setVolumeHelper(mute ? 0 : mVolume); } public boolean isMuted() diff --git a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtCamera.java b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtCameraListener.java index f03053f17..27002fd29 100644 --- a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtCamera.java +++ b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtCameraListener.java @@ -48,148 +48,38 @@ import android.util.Log; import java.lang.Math; import java.util.concurrent.locks.ReentrantLock; -public class QtCamera implements Camera.ShutterCallback, - Camera.PictureCallback, - Camera.AutoFocusCallback, - Camera.PreviewCallback +public class QtCameraListener implements Camera.ShutterCallback, + Camera.PictureCallback, + Camera.AutoFocusCallback, + Camera.PreviewCallback { private int m_cameraId = -1; - private Camera m_camera = null; - private byte[] m_cameraPreviewFirstBuffer = null; - private byte[] m_cameraPreviewSecondBuffer = null; - private int m_actualPreviewBuffer = 0; + private byte[][] m_cameraPreviewBuffer = null; + private volatile int m_actualPreviewBuffer = 0; private final ReentrantLock m_buffersLock = new ReentrantLock(); - private boolean m_isReleased = false; private boolean m_fetchEachFrame = false; private static final String TAG = "Qt Camera"; - private QtCamera(int id, Camera cam) + private QtCameraListener(int id) { m_cameraId = id; - m_camera = cam; } - public static QtCamera open(int cameraId) + public void preparePreviewBuffer(Camera camera) { - try { - Camera cam = Camera.open(cameraId); - return new QtCamera(cameraId, cam); - } catch(Exception e) { - Log.d(TAG, e.getMessage()); - } - return null; - } - - public Camera.Parameters getParameters() - { - return m_camera.getParameters(); - } - - public void lock() - { - try { - m_camera.lock(); - } catch(Exception e) { - Log.d(TAG, e.getMessage()); - } - } - - public void unlock() - { - try { - m_camera.unlock(); - } catch(Exception e) { - Log.d(TAG, e.getMessage()); - } - } - - public void release() - { - m_isReleased = true; - m_camera.release(); - } - - public void reconnect() - { - try { - m_camera.reconnect(); - } catch(Exception e) { - Log.d(TAG, e.getMessage()); - } - } - - public void setDisplayOrientation(int degrees) - { - m_camera.setDisplayOrientation(degrees); - } - - public void setParameters(Camera.Parameters params) - { - try { - m_camera.setParameters(params); - } catch(Exception e) { - Log.d(TAG, e.getMessage()); - } - } - - public void setPreviewTexture(SurfaceTexture surfaceTexture) - { - try { - m_camera.setPreviewTexture(surfaceTexture); - } catch(Exception e) { - Log.d(TAG, e.getMessage()); - } - } - - public void fetchEachFrame(boolean fetch) - { - m_fetchEachFrame = fetch; - } - - public void startPreview() - { - Camera.Size previewSize = m_camera.getParameters().getPreviewSize(); - double bytesPerPixel = ImageFormat.getBitsPerPixel(m_camera.getParameters().getPreviewFormat()) / 8.0; + Camera.Size previewSize = camera.getParameters().getPreviewSize(); + double bytesPerPixel = ImageFormat.getBitsPerPixel(camera.getParameters().getPreviewFormat()) / 8.0; int bufferSizeNeeded = (int)Math.ceil(bytesPerPixel*previewSize.width*previewSize.height); - - //We need to clear preview buffers queue here, but there is no method to do it - //Though just resetting preview callback do the trick - m_camera.setPreviewCallback(null); m_buffersLock.lock(); - if (m_cameraPreviewFirstBuffer == null || m_cameraPreviewFirstBuffer.length < bufferSizeNeeded) - m_cameraPreviewFirstBuffer = new byte[bufferSizeNeeded]; - if (m_cameraPreviewSecondBuffer == null || m_cameraPreviewSecondBuffer.length < bufferSizeNeeded) - m_cameraPreviewSecondBuffer = new byte[bufferSizeNeeded]; - addCallbackBuffer(); + if (m_cameraPreviewBuffer == null || m_cameraPreviewBuffer[0].length < bufferSizeNeeded) + m_cameraPreviewBuffer = new byte[2][bufferSizeNeeded]; m_buffersLock.unlock(); - m_camera.setPreviewCallbackWithBuffer(this); - - m_camera.startPreview(); } - public void stopPreview() - { - m_camera.stopPreview(); - } - - public void autoFocus() - { - m_camera.autoFocus(this); - } - - public void cancelAutoFocus() - { - m_camera.cancelAutoFocus(); - } - - public void takePicture() + public void fetchEachFrame(boolean fetch) { - try { - m_camera.takePicture(this, null, this); - } catch(Exception e) { - Log.d(TAG, e.getMessage()); - } + m_fetchEachFrame = fetch; } public byte[] lockAndFetchPreviewBuffer() @@ -199,10 +89,7 @@ public class QtCamera implements Camera.ShutterCallback, //We should reset actualBuffer flag here to make sure we will not use old preview with future captures byte[] result = null; m_buffersLock.lock(); - if (m_actualPreviewBuffer == 1) - result = m_cameraPreviewFirstBuffer; - else if (m_actualPreviewBuffer == 2) - result = m_cameraPreviewSecondBuffer; + result = m_cameraPreviewBuffer[(m_actualPreviewBuffer == 1) ? 0 : 1]; m_actualPreviewBuffer = 0; return result; } @@ -213,14 +100,9 @@ public class QtCamera implements Camera.ShutterCallback, m_buffersLock.unlock(); } - private void addCallbackBuffer() + public byte[] callbackBuffer() { - if (m_isReleased) - return; - - m_camera.addCallbackBuffer((m_actualPreviewBuffer == 1) - ? m_cameraPreviewSecondBuffer - : m_cameraPreviewFirstBuffer); + return m_cameraPreviewBuffer[(m_actualPreviewBuffer == 1) ? 1 : 0]; } @Override @@ -243,13 +125,13 @@ public class QtCamera implements Camera.ShutterCallback, if (data != null && m_fetchEachFrame) notifyFrameFetched(m_cameraId, data); - if (data == m_cameraPreviewFirstBuffer) + if (data == m_cameraPreviewBuffer[0]) m_actualPreviewBuffer = 1; - else if (data == m_cameraPreviewSecondBuffer) + else if (data == m_cameraPreviewBuffer[1]) m_actualPreviewBuffer = 2; else m_actualPreviewBuffer = 0; - addCallbackBuffer(); + camera.addCallbackBuffer(m_cameraPreviewBuffer[(m_actualPreviewBuffer == 1) ? 1 : 0]); m_buffersLock.unlock(); } diff --git a/src/plugins/android/src/common/qandroidvideooutput.h b/src/plugins/android/src/common/qandroidvideooutput.h index 8bf6be6cb..e0335ec93 100644 --- a/src/plugins/android/src/common/qandroidvideooutput.h +++ b/src/plugins/android/src/common/qandroidvideooutput.h @@ -44,17 +44,17 @@ #include <qglobal.h> #include <qsize.h> -#include <jni.h> QT_BEGIN_NAMESPACE +class AndroidSurfaceTexture; + class QAndroidVideoOutput { public: virtual ~QAndroidVideoOutput() { } - virtual jobject surfaceHolder() = 0; - virtual jobject surfaceTexture() { return 0; } + virtual AndroidSurfaceTexture *surfaceTexture() { return 0; } virtual bool isReady() { return true; } diff --git a/src/plugins/android/src/common/qandroidvideorendercontrol.cpp b/src/plugins/android/src/common/qandroidvideorendercontrol.cpp index 5f14a4691..5532661db 100644 --- a/src/plugins/android/src/common/qandroidvideorendercontrol.cpp +++ b/src/plugins/android/src/common/qandroidvideorendercontrol.cpp @@ -40,8 +40,8 @@ ****************************************************************************/ #include "qandroidvideorendercontrol.h" +#include "androidsurfacetexture.h" -#include <QtCore/private/qjni_p.h> #include <QAbstractVideoSurface> #include <QVideoSurfaceFormat> #include <qevent.h> @@ -50,7 +50,6 @@ #include <qopenglfunctions.h> #include <qopenglshaderprogram.h> #include <qopenglframebufferobject.h> -#include <QtCore/private/qjnihelpers_p.h> QT_BEGIN_NAMESPACE @@ -110,9 +109,7 @@ private: QAndroidVideoRendererControl::QAndroidVideoRendererControl(QObject *parent) : QVideoRendererControl(parent) , m_surface(0) - , m_androidSurface(0) , m_surfaceTexture(0) - , m_surfaceHolder(0) , m_externalTex(0) , m_fbo(0) , m_program(0) @@ -175,9 +172,9 @@ bool QAndroidVideoRendererControl::initSurfaceTexture() return false; } - m_surfaceTexture = new JSurfaceTexture(m_externalTex); + m_surfaceTexture = new AndroidSurfaceTexture(m_externalTex); - if (m_surfaceTexture->object()) { + if (m_surfaceTexture->surfaceTexture() != 0) { connect(m_surfaceTexture, SIGNAL(frameAvailable()), this, SLOT(onFrameAvailable())); } else { delete m_surfaceTexture; @@ -196,42 +193,14 @@ void QAndroidVideoRendererControl::clearSurfaceTexture() delete m_surfaceTexture; m_surfaceTexture = 0; } - if (m_androidSurface) { - if (QtAndroidPrivate::androidSdkVersion() > 13) - m_androidSurface->callMethod<void>("release"); - delete m_androidSurface; - m_androidSurface = 0; - } - if (m_surfaceHolder) { - delete m_surfaceHolder; - m_surfaceHolder = 0; - } -} - -jobject QAndroidVideoRendererControl::surfaceHolder() -{ - if (!initSurfaceTexture()) - return 0; - - if (!m_surfaceHolder) { - m_androidSurface = new QJNIObjectPrivate("android/view/Surface", - "(Landroid/graphics/SurfaceTexture;)V", - m_surfaceTexture->object()); - - m_surfaceHolder = new QJNIObjectPrivate("org/qtproject/qt5/android/multimedia/QtSurfaceTextureHolder", - "(Landroid/view/Surface;)V", - m_androidSurface->object()); - } - - return m_surfaceHolder->object(); } -jobject QAndroidVideoRendererControl::surfaceTexture() +AndroidSurfaceTexture *QAndroidVideoRendererControl::surfaceTexture() { if (!initSurfaceTexture()) return 0; - return m_surfaceTexture->object(); + return m_surfaceTexture; } void QAndroidVideoRendererControl::setVideoSize(const QSize &size) @@ -267,7 +236,7 @@ void QAndroidVideoRendererControl::onFrameAvailable() QVideoFrame frame(buffer, m_nativeSize, QVideoFrame::Format_BGR32); if (m_surface->isActive() && (m_surface->surfaceFormat().pixelFormat() != frame.pixelFormat() - || m_surface->nativeResolution() != frame.size())) { + || m_surface->surfaceFormat().frameSize() != frame.size())) { m_surface->stop(); } diff --git a/src/plugins/android/src/common/qandroidvideorendercontrol.h b/src/plugins/android/src/common/qandroidvideorendercontrol.h index 75fd7ef12..6e70238c2 100644 --- a/src/plugins/android/src/common/qandroidvideorendercontrol.h +++ b/src/plugins/android/src/common/qandroidvideorendercontrol.h @@ -45,13 +45,13 @@ #include <qvideorenderercontrol.h> #include <qmutex.h> #include "qandroidvideooutput.h" -#include "jsurfacetexture.h" QT_BEGIN_NAMESPACE class QOpenGLTexture; class QOpenGLFramebufferObject; class QOpenGLShaderProgram; +class AndroidSurfaceTexture; class OpenGLResourcesDeleter : public QObject { @@ -86,8 +86,7 @@ public: QAbstractVideoSurface *surface() const Q_DECL_OVERRIDE; void setSurface(QAbstractVideoSurface *surface) Q_DECL_OVERRIDE; - jobject surfaceHolder() Q_DECL_OVERRIDE; - jobject surfaceTexture() Q_DECL_OVERRIDE; + AndroidSurfaceTexture *surfaceTexture() Q_DECL_OVERRIDE; bool isReady() Q_DECL_OVERRIDE; void setVideoSize(const QSize &size) Q_DECL_OVERRIDE; void stop() Q_DECL_OVERRIDE; @@ -112,9 +111,7 @@ private: QAbstractVideoSurface *m_surface; QSize m_nativeSize; - QJNIObjectPrivate *m_androidSurface; - JSurfaceTexture *m_surfaceTexture; - QJNIObjectPrivate *m_surfaceHolder; + AndroidSurfaceTexture *m_surfaceTexture; quint32 m_externalTex; QOpenGLFramebufferObject *m_fbo; diff --git a/src/plugins/android/src/mediacapture/mediacapture.pri b/src/plugins/android/src/mediacapture/mediacapture.pri index 01274414b..fde0e3d6f 100644 --- a/src/plugins/android/src/mediacapture/mediacapture.pri +++ b/src/plugins/android/src/mediacapture/mediacapture.pri @@ -12,7 +12,6 @@ SOURCES += \ $$PWD/qandroidcameraimagecapturecontrol.cpp \ $$PWD/qandroidcameracapturedestinationcontrol.cpp \ $$PWD/qandroidcameracapturebufferformatcontrol.cpp \ - $$PWD/qandroidmediastoragelocation.cpp \ $$PWD/qandroidcameraflashcontrol.cpp \ $$PWD/qandroidcamerafocuscontrol.cpp \ $$PWD/qandroidcameralockscontrol.cpp \ @@ -37,7 +36,6 @@ HEADERS += \ $$PWD/qandroidcameraimagecapturecontrol.h \ $$PWD/qandroidcameracapturedestinationcontrol.h \ $$PWD/qandroidcameracapturebufferformatcontrol.h \ - $$PWD/qandroidmediastoragelocation.h \ $$PWD/qandroidcameraflashcontrol.h \ $$PWD/qandroidcamerafocuscontrol.h \ $$PWD/qandroidcameralockscontrol.h \ diff --git a/src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.cpp index 03bbadb93..57057ebd7 100644 --- a/src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcameraexposurecontrol.cpp @@ -42,7 +42,7 @@ #include "qandroidcameraexposurecontrol.h" #include "qandroidcamerasession.h" -#include "jcamera.h" +#include "androidcamera.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.cpp index 253b1baa5..de8e521ee 100644 --- a/src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcameraflashcontrol.cpp @@ -42,7 +42,7 @@ #include "qandroidcameraflashcontrol.h" #include "qandroidcamerasession.h" -#include "jcamera.h" +#include "androidcamera.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.cpp index 345a29174..0b6ab80fc 100644 --- a/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.cpp @@ -42,7 +42,7 @@ #include "qandroidcamerafocuscontrol.h" #include "qandroidcamerasession.h" -#include "jcamera.h" +#include "androidcamera.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.cpp index ec5a3bcbf..4e4a416dd 100644 --- a/src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcameraimageprocessingcontrol.cpp @@ -42,7 +42,7 @@ #include "qandroidcameraimageprocessingcontrol.h" #include "qandroidcamerasession.h" -#include "jcamera.h" +#include "androidcamera.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcameralockscontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcameralockscontrol.cpp index d9f20ec04..bfb48d06e 100644 --- a/src/plugins/android/src/mediacapture/qandroidcameralockscontrol.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcameralockscontrol.cpp @@ -42,7 +42,7 @@ #include "qandroidcameralockscontrol.h" #include "qandroidcamerasession.h" -#include "jcamera.h" +#include "androidcamera.h" #include <qtimer.h> QT_BEGIN_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp index b1b3f848e..963952294 100644 --- a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Toolkit. @@ -41,8 +41,8 @@ #include "qandroidcamerasession.h" -#include "jcamera.h" -#include "jmultimediautils.h" +#include "androidcamera.h" +#include "androidmultimediautils.h" #include "qandroidvideooutput.h" #include "qandroidmediavideoprobecontrol.h" #include "qandroidmultimediautils.h" @@ -111,6 +111,10 @@ QAndroidCameraSession::QAndroidCameraSession(QObject *parent) , m_captureCanceled(false) , m_currentImageCaptureId(-1) { + m_mediaStorageLocation.addStorageLocation( + QMediaStorageLocation::Pictures, + AndroidMultimediaUtils::getDefaultMediaDirectory(AndroidMultimediaUtils::DCIM)); + if (qApp) { connect(qApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(onApplicationStateChanged(Qt::ApplicationState))); @@ -164,10 +168,12 @@ void QAndroidCameraSession::setState(QCamera::State state) emit error(QCamera::CameraError, QStringLiteral("Failed to open camera")); return; } - if (state == QCamera::ActiveState) - startPreview(); - else if (state == QCamera::LoadedState) + if (state == QCamera::ActiveState) { + if (!startPreview()) + return; + } else if (state == QCamera::LoadedState) { stopPreview(); + } break; } @@ -179,36 +185,10 @@ void QAndroidCameraSession::updateAvailableCameras() { g_availableCameras->clear(); - const QJNIObjectPrivate cameraInfo("android/hardware/Camera$CameraInfo"); - const int numCameras = QJNIObjectPrivate::callStaticMethod<jint>("android/hardware/Camera", - "getNumberOfCameras"); - + const int numCameras = AndroidCamera::getNumberOfCameras(); for (int i = 0; i < numCameras; ++i) { AndroidCameraInfo info; - - QJNIObjectPrivate::callStaticMethod<void>("android/hardware/Camera", - "getCameraInfo", - "(ILandroid/hardware/Camera$CameraInfo;)V", - i, cameraInfo.object()); - - JCamera::CameraFacing facing = JCamera::CameraFacing(cameraInfo.getField<jint>("facing")); - // The orientation provided by Android is counter-clockwise, we need it clockwise - info.orientation = (360 - cameraInfo.getField<jint>("orientation")) % 360; - - switch (facing) { - case JCamera::CameraFacingBack: - info.name = QByteArray("back"); - info.description = QStringLiteral("Rear-facing camera"); - info.position = QCamera::BackFace; - break; - case JCamera::CameraFacingFront: - info.name = QByteArray("front"); - info.description = QStringLiteral("Front-facing camera"); - info.position = QCamera::FrontFace; - break; - default: - break; - } + AndroidCamera::getCameraInfo(i, &info); if (!info.name.isNull()) g_availableCameras->append(info); @@ -230,7 +210,7 @@ bool QAndroidCameraSession::open() m_status = QCamera::LoadingStatus; emit statusChanged(m_status); - m_camera = JCamera::open(m_selectedCamera); + m_camera = AndroidCamera::open(m_selectedCamera); if (m_camera) { connect(m_camera, SIGNAL(pictureExposed()), this, SLOT(onCameraPictureExposed())); @@ -246,8 +226,8 @@ bool QAndroidCameraSession::open() m_status = QCamera::LoadedStatus; - if (m_camera->getPreviewFormat() != JCamera::NV21) - m_camera->setPreviewFormat(JCamera::NV21); + if (m_camera->getPreviewFormat() != AndroidCamera::NV21) + m_camera->setPreviewFormat(AndroidCamera::NV21); m_camera->fetchEachFrame(m_videoProbes.count()); @@ -286,8 +266,10 @@ void QAndroidCameraSession::close() void QAndroidCameraSession::setVideoPreview(QObject *videoOutput) { - if (m_videoOutput) + if (m_videoOutput) { m_videoOutput->stop(); + m_videoOutput->reset(); + } if (videoOutput) { connect(videoOutput, SIGNAL(readyChanged(bool)), this, SLOT(onVideoOutputReady(bool))); @@ -336,10 +318,23 @@ void QAndroidCameraSession::adjustViewfinderSize(const QSize &captureSize, bool } } -void QAndroidCameraSession::startPreview() +bool QAndroidCameraSession::startPreview() { - if (!m_camera || m_previewStarted) - return; + if (!m_camera) + return false; + + if (!m_videoOutput) { + Q_EMIT error(QCamera::InvalidRequestError, tr("Camera cannot be started without a viewfinder.")); + return false; + } + + if (m_previewStarted) + return true; + + if (m_videoOutput->isReady()) + m_camera->setPreviewTexture(m_videoOutput->surfaceTexture()); + else + return true; // delay starting until the video output is ready m_status = QCamera::StartingStatus; emit statusChanged(m_status); @@ -347,13 +342,12 @@ void QAndroidCameraSession::startPreview() applyImageSettings(); adjustViewfinderSize(m_imageSettings.resolution()); - if (m_videoOutput && m_videoOutput->isReady()) - onVideoOutputReady(true); - - JMultimediaUtils::enableOrientationListener(true); + AndroidMultimediaUtils::enableOrientationListener(true); m_camera->startPreview(); m_previewStarted = true; + + return true; } void QAndroidCameraSession::stopPreview() @@ -364,12 +358,16 @@ void QAndroidCameraSession::stopPreview() m_status = QCamera::StoppingStatus; emit statusChanged(m_status); - JMultimediaUtils::enableOrientationListener(false); + AndroidMultimediaUtils::enableOrientationListener(false); m_camera->stopPreview(); m_camera->setPreviewSize(QSize()); - if (m_videoOutput) + m_camera->setPreviewTexture(0); + + if (m_videoOutput) { m_videoOutput->stop(); + m_videoOutput->reset(); + } m_previewStarted = false; } @@ -397,8 +395,8 @@ int QAndroidCameraSession::currentCameraRotation() const // subtract natural camera orientation and physical device orientation int rotation = 0; - int deviceOrientation = (JMultimediaUtils::getDeviceOrientation() + 45) / 90 * 90; - if (m_camera->getFacing() == JCamera::CameraFacingFront) + int deviceOrientation = (AndroidMultimediaUtils::getDeviceOrientation() + 45) / 90 * 90; + if (m_camera->getFacing() == AndroidCamera::CameraFacingFront) rotation = (m_nativeOrientation - deviceOrientation + 360) % 360; else // back-facing camera rotation = (m_nativeOrientation + deviceOrientation) % 360; @@ -638,7 +636,7 @@ void QAndroidCameraSession::processCapturedImage(int id, if (dest & QCameraImageCapture::CaptureToFile) { const QString actualFileName = m_mediaStorageLocation.generateFileName(fileName, - QAndroidMediaStorageLocation::Camera, + QMediaStorageLocation::Pictures, QLatin1String("IMG_"), QLatin1String("jpg")); @@ -648,9 +646,9 @@ void QAndroidCameraSession::processCapturedImage(int id, // if the picture is saved into the standard picture location, register it // with the Android media scanner so it appears immediately in apps // such as the gallery. - QString standardLoc = JMultimediaUtils::getDefaultMediaDirectory(JMultimediaUtils::DCIM); + QString standardLoc = AndroidMultimediaUtils::getDefaultMediaDirectory(AndroidMultimediaUtils::DCIM); if (actualFileName.startsWith(standardLoc)) - JMultimediaUtils::registerMediaFile(actualFileName); + AndroidMultimediaUtils::registerMediaFile(actualFileName); emit imageSaved(id, actualFileName); } else { @@ -687,7 +685,7 @@ QImage QAndroidCameraSession::prepareImageFromPreviewData(const QByteArray &data // Preview display of front-facing cameras is flipped horizontally, but the frame data // we get here is not. Flip it ourselves if the camera is front-facing to match what the user // sees on the viewfinder. - if (m_camera->getFacing() == JCamera::CameraFacingFront) + if (m_camera->getFacing() == AndroidCamera::CameraFacingFront) transform.scale(-1, 1); transform.rotate(rotation); @@ -699,8 +697,8 @@ QImage QAndroidCameraSession::prepareImageFromPreviewData(const QByteArray &data void QAndroidCameraSession::onVideoOutputReady(bool ready) { - if (m_camera && m_videoOutput && ready) - m_camera->setPreviewTexture(m_videoOutput->surfaceTexture()); + if (ready && m_state == QCamera::ActiveState) + startPreview(); } void QAndroidCameraSession::onApplicationStateChanged(Qt::ApplicationState state) diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.h b/src/plugins/android/src/mediacapture/qandroidcamerasession.h index f3ac67894..04ba1605f 100644 --- a/src/plugins/android/src/mediacapture/qandroidcamerasession.h +++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Toolkit. @@ -47,22 +47,14 @@ #include <QCameraImageCapture> #include <QSet> #include <QMutex> -#include "qandroidmediastoragelocation.h" +#include <private/qmediastoragelocation_p.h> +#include "androidcamera.h" QT_BEGIN_NAMESPACE -class JCamera; class QAndroidVideoOutput; class QAndroidMediaVideoProbeControl; -struct AndroidCameraInfo -{ - QByteArray name; - QString description; - QCamera::Position position; - int orientation; -}; - class QAndroidCameraSession : public QObject { Q_OBJECT @@ -73,7 +65,7 @@ public: static const QList<AndroidCameraInfo> &availableCameras(); void setSelectedCamera(int cameraId) { m_selectedCamera = cameraId; } - JCamera *camera() const { return m_camera; } + AndroidCamera *camera() const { return m_camera; } QCamera::State state() const { return m_state; } void setState(QCamera::State state); @@ -141,7 +133,7 @@ private: bool open(); void close(); - void startPreview(); + bool startPreview(); void stopPreview(); void applyImageSettings(); @@ -154,7 +146,7 @@ private: const QString &fileName); int m_selectedCamera; - JCamera *m_camera; + AndroidCamera *m_camera; int m_nativeOrientation; QAndroidVideoOutput *m_videoOutput; @@ -174,7 +166,7 @@ private: int m_currentImageCaptureId; QString m_currentImageCaptureFileName; - QAndroidMediaStorageLocation m_mediaStorageLocation; + QMediaStorageLocation m_mediaStorageLocation; QSet<QAndroidMediaVideoProbeControl *> m_videoProbes; QMutex m_videoProbesMutex; diff --git a/src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.cpp index b7030e56b..385cd942a 100644 --- a/src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcamerazoomcontrol.cpp @@ -42,7 +42,7 @@ #include "qandroidcamerazoomcontrol.h" #include "qandroidcamerasession.h" -#include "jcamera.h" +#include "androidcamera.h" #include "qandroidmultimediautils.h" #include <qmath.h> diff --git a/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp b/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp index 008ebc7d5..383af812a 100644 --- a/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Toolkit. @@ -41,11 +41,10 @@ #include "qandroidcapturesession.h" -#include "jcamera.h" +#include "androidcamera.h" #include "qandroidcamerasession.h" -#include "jmultimediautils.h" +#include "androidmultimediautils.h" #include "qandroidmultimediautils.h" -#include <QtCore/private/qjni_p.h> QT_BEGIN_NAMESPACE @@ -53,7 +52,7 @@ QAndroidCaptureSession::QAndroidCaptureSession(QAndroidCameraSession *cameraSess : QObject() , m_mediaRecorder(0) , m_cameraSession(cameraSession) - , m_audioSource(JMediaRecorder::DefaultAudioSource) + , m_audioSource(AndroidMediaRecorder::DefaultAudioSource) , m_duration(0) , m_state(QMediaRecorder::StoppedState) , m_status(QMediaRecorder::UnloadedStatus) @@ -61,10 +60,18 @@ QAndroidCaptureSession::QAndroidCaptureSession(QAndroidCameraSession *cameraSess , m_containerFormatDirty(true) , m_videoSettingsDirty(true) , m_audioSettingsDirty(true) - , m_outputFormat(JMediaRecorder::DefaultOutputFormat) - , m_audioEncoder(JMediaRecorder::DefaultAudioEncoder) - , m_videoEncoder(JMediaRecorder::DefaultVideoEncoder) + , m_outputFormat(AndroidMediaRecorder::DefaultOutputFormat) + , m_audioEncoder(AndroidMediaRecorder::DefaultAudioEncoder) + , m_videoEncoder(AndroidMediaRecorder::DefaultVideoEncoder) { + m_mediaStorageLocation.addStorageLocation( + QMediaStorageLocation::Movies, + AndroidMultimediaUtils::getDefaultMediaDirectory(AndroidMultimediaUtils::DCIM)); + + m_mediaStorageLocation.addStorageLocation( + QMediaStorageLocation::Sounds, + AndroidMultimediaUtils::getDefaultMediaDirectory(AndroidMultimediaUtils::Sounds)); + connect(this, SIGNAL(stateChanged(QMediaRecorder::State)), this, SLOT(updateStatus())); if (cameraSession) { @@ -95,19 +102,19 @@ void QAndroidCaptureSession::setAudioInput(const QString &input) m_audioInput = input; if (m_audioInput == QLatin1String("default")) - m_audioSource = JMediaRecorder::DefaultAudioSource; + m_audioSource = AndroidMediaRecorder::DefaultAudioSource; else if (m_audioInput == QLatin1String("mic")) - m_audioSource = JMediaRecorder::Mic; + m_audioSource = AndroidMediaRecorder::Mic; else if (m_audioInput == QLatin1String("voice_uplink")) - m_audioSource = JMediaRecorder::VoiceUplink; + m_audioSource = AndroidMediaRecorder::VoiceUplink; else if (m_audioInput == QLatin1String("voice_downlink")) - m_audioSource = JMediaRecorder::VoiceDownlink; + m_audioSource = AndroidMediaRecorder::VoiceDownlink; else if (m_audioInput == QLatin1String("voice_call")) - m_audioSource = JMediaRecorder::VoiceCall; + m_audioSource = AndroidMediaRecorder::VoiceCall; else if (m_audioInput == QLatin1String("voice_recognition")) - m_audioSource = JMediaRecorder::VoiceRecognition; + m_audioSource = AndroidMediaRecorder::VoiceRecognition; else - m_audioSource = JMediaRecorder::DefaultAudioSource; + m_audioSource = AndroidMediaRecorder::DefaultAudioSource; emit audioInputChanged(m_audioInput); } @@ -176,7 +183,7 @@ bool QAndroidCaptureSession::start() m_mediaRecorder->release(); delete m_mediaRecorder; } - m_mediaRecorder = new JMediaRecorder; + m_mediaRecorder = new AndroidMediaRecorder; connect(m_mediaRecorder, SIGNAL(error(int,int)), this, SLOT(onError(int,int))); connect(m_mediaRecorder, SIGNAL(info(int,int)), this, SLOT(onInfo(int,int))); @@ -185,8 +192,8 @@ bool QAndroidCaptureSession::start() updateViewfinder(); m_cameraSession->camera()->unlock(); m_mediaRecorder->setCamera(m_cameraSession->camera()); - m_mediaRecorder->setAudioSource(JMediaRecorder::Camcorder); - m_mediaRecorder->setVideoSource(JMediaRecorder::Camera); + m_mediaRecorder->setAudioSource(AndroidMediaRecorder::Camcorder); + m_mediaRecorder->setVideoSource(AndroidMediaRecorder::Camera); } else { m_mediaRecorder->setAudioSource(m_audioSource); } @@ -214,8 +221,8 @@ bool QAndroidCaptureSession::start() QString filePath = m_mediaStorageLocation.generateFileName( m_requestedOutputLocation.isLocalFile() ? m_requestedOutputLocation.toLocalFile() : m_requestedOutputLocation.toString(), - m_cameraSession ? QAndroidMediaStorageLocation::Camera - : QAndroidMediaStorageLocation::Audio, + m_cameraSession ? QMediaStorageLocation::Movies + : QMediaStorageLocation::Sounds, m_cameraSession ? QLatin1String("VID_") : QLatin1String("REC_"), m_containerFormat); @@ -272,10 +279,10 @@ void QAndroidCaptureSession::stop(bool error) // with the Android media scanner so it appears immediately in apps // such as the gallery. QString mediaPath = m_actualOutputLocation.toLocalFile(); - QString standardLoc = m_cameraSession ? JMultimediaUtils::getDefaultMediaDirectory(JMultimediaUtils::DCIM) - : JMultimediaUtils::getDefaultMediaDirectory(JMultimediaUtils::Sounds); + QString standardLoc = m_cameraSession ? AndroidMultimediaUtils::getDefaultMediaDirectory(AndroidMultimediaUtils::DCIM) + : AndroidMultimediaUtils::getDefaultMediaDirectory(AndroidMultimediaUtils::Sounds); if (mediaPath.startsWith(standardLoc)) - JMultimediaUtils::registerMediaFile(mediaPath); + AndroidMultimediaUtils::registerMediaFile(mediaPath); m_actualOutputLocation = m_usedOutputLocation; emit actualLocationChanged(m_actualOutputLocation); @@ -339,14 +346,14 @@ void QAndroidCaptureSession::applySettings() m_containerFormat = m_defaultSettings.outputFileExtension; m_outputFormat = m_defaultSettings.outputFormat; } else if (m_containerFormat == QLatin1String("3gp")) { - m_outputFormat = JMediaRecorder::THREE_GPP; + m_outputFormat = AndroidMediaRecorder::THREE_GPP; } else if (!m_cameraSession && m_containerFormat == QLatin1String("amr")) { - m_outputFormat = JMediaRecorder::AMR_NB_Format; + m_outputFormat = AndroidMediaRecorder::AMR_NB_Format; } else if (!m_cameraSession && m_containerFormat == QLatin1String("awb")) { - m_outputFormat = JMediaRecorder::AMR_WB_Format; + m_outputFormat = AndroidMediaRecorder::AMR_WB_Format; } else { m_containerFormat = QStringLiteral("mp4"); - m_outputFormat = JMediaRecorder::MPEG_4; + m_outputFormat = AndroidMediaRecorder::MPEG_4; } m_containerFormatDirty = false; @@ -364,11 +371,11 @@ void QAndroidCaptureSession::applySettings() if (m_audioSettings.codec().isEmpty()) m_audioEncoder = m_defaultSettings.audioEncoder; else if (m_audioSettings.codec() == QLatin1String("aac")) - m_audioEncoder = JMediaRecorder::AAC; + m_audioEncoder = AndroidMediaRecorder::AAC; else if (m_audioSettings.codec() == QLatin1String("amr-nb")) - m_audioEncoder = JMediaRecorder::AMR_NB_Encoder; + m_audioEncoder = AndroidMediaRecorder::AMR_NB_Encoder; else if (m_audioSettings.codec() == QLatin1String("amr-wb")) - m_audioEncoder = JMediaRecorder::AMR_WB_Encoder; + m_audioEncoder = AndroidMediaRecorder::AMR_WB_Encoder; else m_audioEncoder = m_defaultSettings.audioEncoder; @@ -402,11 +409,11 @@ void QAndroidCaptureSession::applySettings() if (m_videoSettings.codec().isEmpty()) m_videoEncoder = m_defaultSettings.videoEncoder; else if (m_videoSettings.codec() == QLatin1String("h263")) - m_videoEncoder = JMediaRecorder::H263; + m_videoEncoder = AndroidMediaRecorder::H263; else if (m_videoSettings.codec() == QLatin1String("h264")) - m_videoEncoder = JMediaRecorder::H264; + m_videoEncoder = AndroidMediaRecorder::H264; else if (m_videoSettings.codec() == QLatin1String("mpeg4_sp")) - m_videoEncoder = JMediaRecorder::MPEG_4_SP; + m_videoEncoder = AndroidMediaRecorder::MPEG_4_SP; else m_videoEncoder = m_defaultSettings.videoEncoder; @@ -448,7 +455,7 @@ void QAndroidCaptureSession::onCameraOpened() for (int i = 0; i < 8; ++i) { CaptureProfile profile = getProfile(i); if (!profile.isNull) { - if (i == 1) // QUALITY_HIGH + if (i == AndroidCamcorderProfile::QUALITY_HIGH) m_defaultSettings = profile; if (!m_supportedResolutions.contains(profile.videoResolution)) @@ -467,38 +474,31 @@ void QAndroidCaptureSession::onCameraOpened() QAndroidCaptureSession::CaptureProfile QAndroidCaptureSession::getProfile(int id) { CaptureProfile profile; - bool hasProfile = QJNIObjectPrivate::callStaticMethod<jboolean>("android/media/CamcorderProfile", - "hasProfile", - "(II)Z", - m_cameraSession->camera()->cameraId(), - id); + const bool hasProfile = AndroidCamcorderProfile::hasProfile(m_cameraSession->camera()->cameraId(), + AndroidCamcorderProfile::Quality(id)); if (hasProfile) { - QJNIObjectPrivate obj = QJNIObjectPrivate::callStaticObjectMethod("android/media/CamcorderProfile", - "get", - "(II)Landroid/media/CamcorderProfile;", - m_cameraSession->camera()->cameraId(), - id); - - - profile.outputFormat = JMediaRecorder::OutputFormat(obj.getField<jint>("fileFormat")); - profile.audioEncoder = JMediaRecorder::AudioEncoder(obj.getField<jint>("audioCodec")); - profile.audioBitRate = obj.getField<jint>("audioBitRate"); - profile.audioChannels = obj.getField<jint>("audioChannels"); - profile.audioSampleRate = obj.getField<jint>("audioSampleRate"); - profile.videoEncoder = JMediaRecorder::VideoEncoder(obj.getField<jint>("videoCodec")); - profile.videoBitRate = obj.getField<jint>("videoBitRate"); - profile.videoFrameRate = obj.getField<jint>("videoFrameRate"); - profile.videoResolution = QSize(obj.getField<jint>("videoFrameWidth"), - obj.getField<jint>("videoFrameHeight")); - - if (profile.outputFormat == JMediaRecorder::MPEG_4) + AndroidCamcorderProfile camProfile = AndroidCamcorderProfile::get(m_cameraSession->camera()->cameraId(), + AndroidCamcorderProfile::Quality(id)); + + profile.outputFormat = AndroidMediaRecorder::OutputFormat(camProfile.getValue(AndroidCamcorderProfile::fileFormat)); + profile.audioEncoder = AndroidMediaRecorder::AudioEncoder(camProfile.getValue(AndroidCamcorderProfile::audioCodec)); + profile.audioBitRate = camProfile.getValue(AndroidCamcorderProfile::audioBitRate); + profile.audioChannels = camProfile.getValue(AndroidCamcorderProfile::audioChannels); + profile.audioSampleRate = camProfile.getValue(AndroidCamcorderProfile::audioSampleRate); + profile.videoEncoder = AndroidMediaRecorder::VideoEncoder(camProfile.getValue(AndroidCamcorderProfile::videoCodec)); + profile.videoBitRate = camProfile.getValue(AndroidCamcorderProfile::videoBitRate); + profile.videoFrameRate = camProfile.getValue(AndroidCamcorderProfile::videoFrameRate); + profile.videoResolution = QSize(camProfile.getValue(AndroidCamcorderProfile::videoFrameWidth), + camProfile.getValue(AndroidCamcorderProfile::videoFrameHeight)); + + if (profile.outputFormat == AndroidMediaRecorder::MPEG_4) profile.outputFileExtension = QStringLiteral("mp4"); - else if (profile.outputFormat == JMediaRecorder::THREE_GPP) + else if (profile.outputFormat == AndroidMediaRecorder::THREE_GPP) profile.outputFileExtension = QStringLiteral("3gp"); - else if (profile.outputFormat == JMediaRecorder::AMR_NB_Format) + else if (profile.outputFormat == AndroidMediaRecorder::AMR_NB_Format) profile.outputFileExtension = QStringLiteral("amr"); - else if (profile.outputFormat == JMediaRecorder::AMR_WB_Format) + else if (profile.outputFormat == AndroidMediaRecorder::AMR_WB_Format) profile.outputFileExtension = QStringLiteral("awb"); profile.isNull = false; diff --git a/src/plugins/android/src/mediacapture/qandroidcapturesession.h b/src/plugins/android/src/mediacapture/qandroidcapturesession.h index 32ca9d1ae..4ff2cb145 100644 --- a/src/plugins/android/src/mediacapture/qandroidcapturesession.h +++ b/src/plugins/android/src/mediacapture/qandroidcapturesession.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Toolkit. @@ -47,8 +47,8 @@ #include <qurl.h> #include <qelapsedtimer.h> #include <qtimer.h> -#include "qandroidmediastoragelocation.h" -#include "jmediarecorder.h" +#include <private/qmediastoragelocation_p.h> +#include "androidmediarecorder.h" QT_BEGIN_NAMESPACE @@ -106,15 +106,15 @@ private Q_SLOTS: private: struct CaptureProfile { - JMediaRecorder::OutputFormat outputFormat; + AndroidMediaRecorder::OutputFormat outputFormat; QString outputFileExtension; - JMediaRecorder::AudioEncoder audioEncoder; + AndroidMediaRecorder::AudioEncoder audioEncoder; int audioBitRate; int audioChannels; int audioSampleRate; - JMediaRecorder::VideoEncoder videoEncoder; + AndroidMediaRecorder::VideoEncoder videoEncoder; int videoBitRate; int videoFrameRate; QSize videoResolution; @@ -122,13 +122,13 @@ private: bool isNull; CaptureProfile() - : outputFormat(JMediaRecorder::MPEG_4) + : outputFormat(AndroidMediaRecorder::MPEG_4) , outputFileExtension(QLatin1String("mp4")) - , audioEncoder(JMediaRecorder::DefaultAudioEncoder) + , audioEncoder(AndroidMediaRecorder::DefaultAudioEncoder) , audioBitRate(128000) , audioChannels(2) , audioSampleRate(44100) - , videoEncoder(JMediaRecorder::DefaultVideoEncoder) + , videoEncoder(AndroidMediaRecorder::DefaultVideoEncoder) , videoBitRate(1) , videoFrameRate(-1) , videoResolution(320, 240) @@ -146,13 +146,13 @@ private: void updateViewfinder(); void restartViewfinder(); - JMediaRecorder *m_mediaRecorder; + AndroidMediaRecorder *m_mediaRecorder; QAndroidCameraSession *m_cameraSession; QString m_audioInput; - JMediaRecorder::AudioSource m_audioSource; + AndroidMediaRecorder::AudioSource m_audioSource; - QAndroidMediaStorageLocation m_mediaStorageLocation; + QMediaStorageLocation m_mediaStorageLocation; QElapsedTimer m_elapsedTime; QTimer m_notifyTimer; @@ -173,9 +173,9 @@ private: bool m_containerFormatDirty; bool m_videoSettingsDirty; bool m_audioSettingsDirty; - JMediaRecorder::OutputFormat m_outputFormat; - JMediaRecorder::AudioEncoder m_audioEncoder; - JMediaRecorder::VideoEncoder m_videoEncoder; + AndroidMediaRecorder::OutputFormat m_outputFormat; + AndroidMediaRecorder::AudioEncoder m_audioEncoder; + AndroidMediaRecorder::VideoEncoder m_videoEncoder; QList<QSize> m_supportedResolutions; QList<qreal> m_supportedFramerates; diff --git a/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.cpp b/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.cpp index 79e0651a3..a239f510b 100644 --- a/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.cpp +++ b/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.cpp @@ -42,7 +42,7 @@ #include "qandroidimageencodercontrol.h" #include "qandroidcamerasession.h" -#include "jcamera.h" +#include "androidcamera.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.h b/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.h index 23e397d4d..7dcc884a9 100644 --- a/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.h +++ b/src/plugins/android/src/mediacapture/qandroidimageencodercontrol.h @@ -69,4 +69,6 @@ private: QList<QSize> m_supportedResolutions; }; +QT_END_NAMESPACE + #endif // QANDROIDIMAGEENCODERCONTROL_H diff --git a/src/plugins/android/src/mediacapture/qandroidmediavideoprobecontrol.cpp b/src/plugins/android/src/mediacapture/qandroidmediavideoprobecontrol.cpp index a4ebc8fe4..8e0cf6d16 100644 --- a/src/plugins/android/src/mediacapture/qandroidmediavideoprobecontrol.cpp +++ b/src/plugins/android/src/mediacapture/qandroidmediavideoprobecontrol.cpp @@ -43,6 +43,8 @@ #include "qandroidmediavideoprobecontrol.h" #include <qvideoframe.h> +QT_BEGIN_NAMESPACE + QAndroidMediaVideoProbeControl::QAndroidMediaVideoProbeControl(QObject *parent) : QMediaVideoProbeControl(parent) { @@ -57,3 +59,5 @@ void QAndroidMediaVideoProbeControl::newFrameProbed(const QVideoFrame &frame) { emit videoFrameProbed(frame); } + +QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediacapture/qandroidmediavideoprobecontrol.h b/src/plugins/android/src/mediacapture/qandroidmediavideoprobecontrol.h index 7bb34d883..0a0007c9f 100644 --- a/src/plugins/android/src/mediacapture/qandroidmediavideoprobecontrol.h +++ b/src/plugins/android/src/mediacapture/qandroidmediavideoprobecontrol.h @@ -45,6 +45,8 @@ #include <qmediavideoprobecontrol.h> +QT_BEGIN_NAMESPACE + class QAndroidMediaVideoProbeControl : public QMediaVideoProbeControl { Q_OBJECT @@ -56,4 +58,6 @@ public: }; +QT_END_NAMESPACE + #endif // QANDROIDMEDIAVIDEOPROBECONTROL_H diff --git a/src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.cpp b/src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.cpp index 3fcb199f7..17a349d9d 100644 --- a/src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.cpp +++ b/src/plugins/android/src/mediacapture/qandroidvideodeviceselectorcontrol.cpp @@ -42,7 +42,7 @@ #include "qandroidvideodeviceselectorcontrol.h" #include "qandroidcamerasession.h" -#include "jcamera.h" +#include "androidcamera.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp index f5614a57a..6817d65b0 100644 --- a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp +++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp @@ -40,24 +40,25 @@ ****************************************************************************/ #include "qandroidmediaplayercontrol.h" -#include "jmediaplayer.h" +#include "androidmediaplayer.h" #include "qandroidvideooutput.h" QT_BEGIN_NAMESPACE QAndroidMediaPlayerControl::QAndroidMediaPlayerControl(QObject *parent) : QMediaPlayerControl(parent), - mMediaPlayer(new JMediaPlayer), + mMediaPlayer(new AndroidMediaPlayer), mCurrentState(QMediaPlayer::StoppedState), mCurrentMediaStatus(QMediaPlayer::NoMedia), mMediaStream(0), mVideoOutput(0), mSeekable(true), mBufferPercent(-1), + mBufferFilled(false), mAudioAvailable(false), mVideoAvailable(false), mBuffering(false), - mState(JMediaPlayer::Uninitialized), + mState(AndroidMediaPlayer::Uninitialized), mPendingState(-1), mPendingPosition(-1), mPendingSetMedia(false), @@ -98,11 +99,11 @@ QMediaPlayer::MediaStatus QAndroidMediaPlayerControl::mediaStatus() const qint64 QAndroidMediaPlayerControl::duration() const { - if ((mState & (JMediaPlayer::Prepared - | JMediaPlayer::Started - | JMediaPlayer::Paused - | JMediaPlayer::Stopped - | JMediaPlayer::PlaybackCompleted)) == 0) { + if ((mState & (AndroidMediaPlayer::Prepared + | AndroidMediaPlayer::Started + | AndroidMediaPlayer::Paused + | AndroidMediaPlayer::Stopped + | AndroidMediaPlayer::PlaybackCompleted)) == 0) { return 0; } @@ -114,13 +115,13 @@ qint64 QAndroidMediaPlayerControl::position() const if (mCurrentMediaStatus == QMediaPlayer::EndOfMedia) return duration(); - if ((mState & (JMediaPlayer::Idle - | JMediaPlayer::Initialized - | JMediaPlayer::Prepared - | JMediaPlayer::Started - | JMediaPlayer::Paused - | JMediaPlayer::Stopped - | JMediaPlayer::PlaybackCompleted)) == 0) { + if ((mState & (AndroidMediaPlayer::Idle + | AndroidMediaPlayer::Initialized + | AndroidMediaPlayer::Prepared + | AndroidMediaPlayer::Started + | AndroidMediaPlayer::Paused + | AndroidMediaPlayer::Stopped + | AndroidMediaPlayer::PlaybackCompleted)) == 0) { return (mPendingPosition == -1) ? 0 : mPendingPosition; } @@ -134,10 +135,10 @@ void QAndroidMediaPlayerControl::setPosition(qint64 position) const int seekPosition = (position > INT_MAX) ? INT_MAX : position; - if ((mState & (JMediaPlayer::Prepared - | JMediaPlayer::Started - | JMediaPlayer::Paused - | JMediaPlayer::PlaybackCompleted)) == 0) { + if ((mState & (AndroidMediaPlayer::Prepared + | AndroidMediaPlayer::Started + | AndroidMediaPlayer::Paused + | AndroidMediaPlayer::PlaybackCompleted)) == 0) { if (mPendingPosition != seekPosition) { mPendingPosition = seekPosition; Q_EMIT positionChanged(seekPosition); @@ -164,13 +165,13 @@ int QAndroidMediaPlayerControl::volume() const void QAndroidMediaPlayerControl::setVolume(int volume) { - if ((mState & (JMediaPlayer::Idle - | JMediaPlayer::Initialized - | JMediaPlayer::Stopped - | JMediaPlayer::Prepared - | JMediaPlayer::Started - | JMediaPlayer::Paused - | JMediaPlayer::PlaybackCompleted)) == 0) { + if ((mState & (AndroidMediaPlayer::Idle + | AndroidMediaPlayer::Initialized + | AndroidMediaPlayer::Stopped + | AndroidMediaPlayer::Prepared + | AndroidMediaPlayer::Started + | AndroidMediaPlayer::Paused + | AndroidMediaPlayer::PlaybackCompleted)) == 0) { if (mPendingVolume != volume) { mPendingVolume = volume; Q_EMIT volumeChanged(volume); @@ -195,13 +196,13 @@ bool QAndroidMediaPlayerControl::isMuted() const void QAndroidMediaPlayerControl::setMuted(bool muted) { - if ((mState & (JMediaPlayer::Idle - | JMediaPlayer::Initialized - | JMediaPlayer::Stopped - | JMediaPlayer::Prepared - | JMediaPlayer::Started - | JMediaPlayer::Paused - | JMediaPlayer::PlaybackCompleted)) == 0) { + if ((mState & (AndroidMediaPlayer::Idle + | AndroidMediaPlayer::Initialized + | AndroidMediaPlayer::Stopped + | AndroidMediaPlayer::Prepared + | AndroidMediaPlayer::Started + | AndroidMediaPlayer::Paused + | AndroidMediaPlayer::PlaybackCompleted)) == 0) { if (mPendingMute != muted) { mPendingMute = muted; Q_EMIT mutedChanged(muted); @@ -221,7 +222,7 @@ void QAndroidMediaPlayerControl::setMuted(bool muted) int QAndroidMediaPlayerControl::bufferStatus() const { - return mBufferPercent; + return mBufferFilled ? 100 : 0; } bool QAndroidMediaPlayerControl::isAudioAvailable() const @@ -290,7 +291,7 @@ void QAndroidMediaPlayerControl::setMedia(const QMediaContent &mediaContent, } // Release the mediaplayer if it's not in in Idle or Uninitialized state - if ((mState & (JMediaPlayer::Idle | JMediaPlayer::Uninitialized)) == 0) + if ((mState & (AndroidMediaPlayer::Idle | AndroidMediaPlayer::Uninitialized)) == 0) mMediaPlayer->release(); if (mediaContent.isNull()) { @@ -311,7 +312,7 @@ void QAndroidMediaPlayerControl::setMedia(const QMediaContent &mediaContent, const QString path = url.toString().mid(3); mTempFile.reset(QTemporaryFile::createNativeFile(path)); if (!mTempFile.isNull()) - mediaPath = QLatin1String("file://") + mTempFile->fileName(); + mediaPath = QStringLiteral("file://") + mTempFile->fileName(); } else { mediaPath = url.toString(); } @@ -319,8 +320,8 @@ void QAndroidMediaPlayerControl::setMedia(const QMediaContent &mediaContent, if (mVideoSize.isValid() && mVideoOutput) mVideoOutput->setVideoSize(mVideoSize); - if (!mMediaPlayer->display() && mVideoOutput) - mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder()); + if ((mMediaPlayer->display() == 0) && mVideoOutput) + mMediaPlayer->setDisplay(mVideoOutput->surfaceTexture()); mMediaPlayer->setDataSource(mediaPath); mMediaPlayer->prepareAsync(); @@ -344,7 +345,7 @@ void QAndroidMediaPlayerControl::setVideoOutput(QObject *videoOutput) return; if (mVideoOutput->isReady()) - mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder()); + mMediaPlayer->setDisplay(mVideoOutput->surfaceTexture()); connect(videoOutput, SIGNAL(readyChanged(bool)), this, SLOT(onVideoOutputReady(bool))); } @@ -352,16 +353,16 @@ void QAndroidMediaPlayerControl::setVideoOutput(QObject *videoOutput) void QAndroidMediaPlayerControl::play() { // We need to prepare the mediaplayer again. - if ((mState & JMediaPlayer::Stopped) && !mMediaContent.isNull()) { + if ((mState & AndroidMediaPlayer::Stopped) && !mMediaContent.isNull()) { setMedia(mMediaContent, mMediaStream); } setState(QMediaPlayer::PlayingState); - if ((mState & (JMediaPlayer::Prepared - | JMediaPlayer::Started - | JMediaPlayer::Paused - | JMediaPlayer::PlaybackCompleted)) == 0) { + if ((mState & (AndroidMediaPlayer::Prepared + | AndroidMediaPlayer::Started + | AndroidMediaPlayer::Paused + | AndroidMediaPlayer::PlaybackCompleted)) == 0) { mPendingState = QMediaPlayer::PlayingState; return; } @@ -373,9 +374,9 @@ void QAndroidMediaPlayerControl::pause() { setState(QMediaPlayer::PausedState); - if ((mState & (JMediaPlayer::Started - | JMediaPlayer::Paused - | JMediaPlayer::PlaybackCompleted)) == 0) { + if ((mState & (AndroidMediaPlayer::Started + | AndroidMediaPlayer::Paused + | AndroidMediaPlayer::PlaybackCompleted)) == 0) { mPendingState = QMediaPlayer::PausedState; return; } @@ -387,12 +388,12 @@ void QAndroidMediaPlayerControl::stop() { setState(QMediaPlayer::StoppedState); - if ((mState & (JMediaPlayer::Prepared - | JMediaPlayer::Started - | JMediaPlayer::Stopped - | JMediaPlayer::Paused - | JMediaPlayer::PlaybackCompleted)) == 0) { - if ((mState & (JMediaPlayer::Idle | JMediaPlayer::Uninitialized | JMediaPlayer::Error)) == 0) + if ((mState & (AndroidMediaPlayer::Prepared + | AndroidMediaPlayer::Started + | AndroidMediaPlayer::Stopped + | AndroidMediaPlayer::Paused + | AndroidMediaPlayer::PlaybackCompleted)) == 0) { + if ((mState & (AndroidMediaPlayer::Idle | AndroidMediaPlayer::Uninitialized | AndroidMediaPlayer::Error)) == 0) mPendingState = QMediaPlayer::StoppedState; return; } @@ -404,28 +405,28 @@ void QAndroidMediaPlayerControl::onInfo(qint32 what, qint32 extra) { Q_UNUSED(extra); switch (what) { - case JMediaPlayer::MEDIA_INFO_UNKNOWN: + case AndroidMediaPlayer::MEDIA_INFO_UNKNOWN: break; - case JMediaPlayer::MEDIA_INFO_VIDEO_TRACK_LAGGING: + case AndroidMediaPlayer::MEDIA_INFO_VIDEO_TRACK_LAGGING: // IGNORE break; - case JMediaPlayer::MEDIA_INFO_VIDEO_RENDERING_START: + case AndroidMediaPlayer::MEDIA_INFO_VIDEO_RENDERING_START: break; - case JMediaPlayer::MEDIA_INFO_BUFFERING_START: + case AndroidMediaPlayer::MEDIA_INFO_BUFFERING_START: mPendingState = mCurrentState; setState(QMediaPlayer::PausedState); setMediaStatus(QMediaPlayer::StalledMedia); break; - case JMediaPlayer::MEDIA_INFO_BUFFERING_END: + case AndroidMediaPlayer::MEDIA_INFO_BUFFERING_END: if (mCurrentState != QMediaPlayer::StoppedState) flushPendingStates(); break; - case JMediaPlayer::MEDIA_INFO_BAD_INTERLEAVING: + case AndroidMediaPlayer::MEDIA_INFO_BAD_INTERLEAVING: break; - case JMediaPlayer::MEDIA_INFO_NOT_SEEKABLE: + case AndroidMediaPlayer::MEDIA_INFO_NOT_SEEKABLE: setSeekable(false); break; - case JMediaPlayer::MEDIA_INFO_METADATA_UPDATE: + case AndroidMediaPlayer::MEDIA_INFO_METADATA_UPDATE: Q_EMIT metaDataUpdated(); break; } @@ -437,44 +438,44 @@ void QAndroidMediaPlayerControl::onError(qint32 what, qint32 extra) QMediaPlayer::Error error = QMediaPlayer::ResourceError; switch (what) { - case JMediaPlayer::MEDIA_ERROR_UNKNOWN: + case AndroidMediaPlayer::MEDIA_ERROR_UNKNOWN: errorString = QLatin1String("Error:"); break; - case JMediaPlayer::MEDIA_ERROR_SERVER_DIED: + case AndroidMediaPlayer::MEDIA_ERROR_SERVER_DIED: errorString = QLatin1String("Error: Server died"); error = QMediaPlayer::ServiceMissingError; break; - case JMediaPlayer::MEDIA_ERROR_INVALID_STATE: + case AndroidMediaPlayer::MEDIA_ERROR_INVALID_STATE: errorString = QLatin1String("Error: Invalid state"); error = QMediaPlayer::ServiceMissingError; break; } switch (extra) { - case JMediaPlayer::MEDIA_ERROR_IO: // Network OR file error + case AndroidMediaPlayer::MEDIA_ERROR_IO: // Network OR file error errorString += QLatin1String(" (I/O operation failed)"); error = QMediaPlayer::NetworkError; setMediaStatus(QMediaPlayer::InvalidMedia); break; - case JMediaPlayer::MEDIA_ERROR_MALFORMED: + case AndroidMediaPlayer::MEDIA_ERROR_MALFORMED: errorString += QLatin1String(" (Malformed bitstream)"); error = QMediaPlayer::FormatError; setMediaStatus(QMediaPlayer::InvalidMedia); break; - case JMediaPlayer::MEDIA_ERROR_UNSUPPORTED: + case AndroidMediaPlayer::MEDIA_ERROR_UNSUPPORTED: errorString += QLatin1String(" (Unsupported media)"); error = QMediaPlayer::FormatError; setMediaStatus(QMediaPlayer::InvalidMedia); break; - case JMediaPlayer::MEDIA_ERROR_TIMED_OUT: + case AndroidMediaPlayer::MEDIA_ERROR_TIMED_OUT: errorString += QLatin1String(" (Timed out)"); break; - case JMediaPlayer::MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK: + case AndroidMediaPlayer::MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK: errorString += QLatin1String(" (Unable to start progressive playback')"); error = QMediaPlayer::FormatError; setMediaStatus(QMediaPlayer::InvalidMedia); break; - case JMediaPlayer::MEDIA_ERROR_BAD_THINGS_ARE_GOING_TO_HAPPEN: + case AndroidMediaPlayer::MEDIA_ERROR_BAD_THINGS_ARE_GOING_TO_HAPPEN: errorString += QLatin1String(" (Unknown error/Insufficient resources)"); error = QMediaPlayer::ServiceMissingError; break; @@ -487,7 +488,6 @@ void QAndroidMediaPlayerControl::onBufferingChanged(qint32 percent) { mBuffering = percent != 100; mBufferPercent = percent; - Q_EMIT bufferStatusChanged(mBufferPercent); updateAvailablePlaybackRanges(); @@ -512,21 +512,21 @@ void QAndroidMediaPlayerControl::onVideoSizeChanged(qint32 width, qint32 height) void QAndroidMediaPlayerControl::onStateChanged(qint32 state) { // If reloading, don't report state changes unless the new state is Prepared or Error. - if ((mState & JMediaPlayer::Stopped) - && (state & (JMediaPlayer::Prepared | JMediaPlayer::Error | JMediaPlayer::Uninitialized)) == 0) { + if ((mState & AndroidMediaPlayer::Stopped) + && (state & (AndroidMediaPlayer::Prepared | AndroidMediaPlayer::Error | AndroidMediaPlayer::Uninitialized)) == 0) { return; } mState = state; switch (mState) { - case JMediaPlayer::Idle: + case AndroidMediaPlayer::Idle: break; - case JMediaPlayer::Initialized: + case AndroidMediaPlayer::Initialized: break; - case JMediaPlayer::Preparing: + case AndroidMediaPlayer::Preparing: setMediaStatus(QMediaPlayer::LoadingMedia); break; - case JMediaPlayer::Prepared: + case AndroidMediaPlayer::Prepared: setMediaStatus(QMediaPlayer::LoadedMedia); if (mBuffering) { setMediaStatus(mBufferPercent == 100 ? QMediaPlayer::BufferedMedia @@ -537,7 +537,7 @@ void QAndroidMediaPlayerControl::onStateChanged(qint32 state) setAudioAvailable(true); flushPendingStates(); break; - case JMediaPlayer::Started: + case AndroidMediaPlayer::Started: setState(QMediaPlayer::PlayingState); if (mBuffering) { setMediaStatus(mBufferPercent == 100 ? QMediaPlayer::BufferedMedia @@ -546,25 +546,25 @@ void QAndroidMediaPlayerControl::onStateChanged(qint32 state) setMediaStatus(QMediaPlayer::BufferedMedia); } break; - case JMediaPlayer::Paused: + case AndroidMediaPlayer::Paused: setState(QMediaPlayer::PausedState); break; - case JMediaPlayer::Error: + case AndroidMediaPlayer::Error: setState(QMediaPlayer::StoppedState); setMediaStatus(QMediaPlayer::UnknownMediaStatus); mMediaPlayer->release(); break; - case JMediaPlayer::Stopped: + case AndroidMediaPlayer::Stopped: setState(QMediaPlayer::StoppedState); setMediaStatus(QMediaPlayer::LoadedMedia); setPosition(0); break; - case JMediaPlayer::PlaybackCompleted: + case AndroidMediaPlayer::PlaybackCompleted: setState(QMediaPlayer::StoppedState); setPosition(0); setMediaStatus(QMediaPlayer::EndOfMedia); break; - case JMediaPlayer::Uninitialized: + case AndroidMediaPlayer::Uninitialized: // reset some properties resetBufferingProgress(); mPendingPosition = -1; @@ -579,7 +579,7 @@ void QAndroidMediaPlayerControl::onStateChanged(qint32 state) break; } - if ((mState & (JMediaPlayer::Stopped | JMediaPlayer::Uninitialized)) != 0) { + if ((mState & (AndroidMediaPlayer::Stopped | AndroidMediaPlayer::Uninitialized)) != 0) { mMediaPlayer->setDisplay(0); if (mVideoOutput) { mVideoOutput->stop(); @@ -590,8 +590,8 @@ void QAndroidMediaPlayerControl::onStateChanged(qint32 state) void QAndroidMediaPlayerControl::onVideoOutputReady(bool ready) { - if (!mMediaPlayer->display() && mVideoOutput && ready) - mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder()); + if ((mMediaPlayer->display() == 0) && mVideoOutput && ready) + mMediaPlayer->setDisplay(mVideoOutput->surfaceTexture()); flushPendingStates(); } @@ -621,6 +621,8 @@ void QAndroidMediaPlayerControl::setMediaStatus(QMediaPlayer::MediaStatus status mCurrentMediaStatus = status; Q_EMIT mediaStatusChanged(mCurrentMediaStatus); + + updateBufferStatus(); } void QAndroidMediaPlayerControl::setSeekable(bool seekable) @@ -658,7 +660,6 @@ void QAndroidMediaPlayerControl::resetBufferingProgress() mBuffering = false; mBufferPercent = 0; mAvailablePlaybackRange = QMediaTimeRange(); - Q_EMIT bufferStatusChanged(mBufferPercent); } void QAndroidMediaPlayerControl::flushPendingStates() @@ -694,4 +695,15 @@ void QAndroidMediaPlayerControl::flushPendingStates() } } +void QAndroidMediaPlayerControl::updateBufferStatus() +{ + bool bufferFilled = (mCurrentMediaStatus == QMediaPlayer::BufferedMedia + || mCurrentMediaStatus == QMediaPlayer::BufferingMedia); + + if (mBufferFilled != bufferFilled) { + mBufferFilled = bufferFilled; + Q_EMIT bufferStatusChanged(bufferStatus()); + } +} + QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h index 1be3b4428..5744c11b8 100644 --- a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h +++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h @@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE -class JMediaPlayer; +class AndroidMediaPlayer; class QAndroidVideoOutput; class QAndroidMediaPlayerControl : public QMediaPlayerControl @@ -98,7 +98,7 @@ private Q_SLOTS: void onStateChanged(qint32 state); private: - JMediaPlayer *mMediaPlayer; + AndroidMediaPlayer *mMediaPlayer; QMediaPlayer::State mCurrentState; QMediaPlayer::MediaStatus mCurrentMediaStatus; QMediaContent mMediaContent; @@ -106,6 +106,7 @@ private: QAndroidVideoOutput *mVideoOutput; bool mSeekable; int mBufferPercent; + bool mBufferFilled; bool mAudioAvailable; bool mVideoAvailable; QSize mVideoSize; @@ -127,6 +128,7 @@ private: void updateAvailablePlaybackRanges(); void resetBufferingProgress(); void flushPendingStates(); + void updateBufferStatus(); }; QT_END_NAMESPACE diff --git a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp index dcc3dfbe0..82bd74997 100644 --- a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp +++ b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp @@ -41,7 +41,7 @@ #include "qandroidmetadatareadercontrol.h" -#include "jmediametadataretriever.h" +#include "androidmediametadataretriever.h" #include <QtMultimedia/qmediametadata.h> #include <qsize.h> #include <QDate> @@ -74,7 +74,7 @@ static const char* qt_ID3GenreNames[] = QAndroidMetaDataReaderControl::QAndroidMetaDataReaderControl(QObject *parent) : QMetaDataReaderControl(parent) , m_available(false) - , m_retriever(new JMediaMetadataRetriever) + , m_retriever(new AndroidMediaMetadataRetriever) { } @@ -124,56 +124,56 @@ void QAndroidMetaDataReaderControl::updateData() if (!m_mediaContent.isNull()) { if (m_retriever->setDataSource(m_mediaContent.canonicalUrl())) { - QString mimeType = m_retriever->extractMetadata(JMediaMetadataRetriever::MimeType); + QString mimeType = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::MimeType); if (!mimeType.isNull()) m_metadata.insert(QMediaMetaData::MediaType, mimeType); - bool isVideo = !m_retriever->extractMetadata(JMediaMetadataRetriever::HasVideo).isNull() + bool isVideo = !m_retriever->extractMetadata(AndroidMediaMetadataRetriever::HasVideo).isNull() || mimeType.startsWith(QStringLiteral("video")); - QString string = m_retriever->extractMetadata(JMediaMetadataRetriever::Album); + QString string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::Album); if (!string.isNull()) m_metadata.insert(QMediaMetaData::AlbumTitle, string); - string = m_retriever->extractMetadata(JMediaMetadataRetriever::AlbumArtist); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::AlbumArtist); if (!string.isNull()) m_metadata.insert(QMediaMetaData::AlbumArtist, string); - string = m_retriever->extractMetadata(JMediaMetadataRetriever::Artist); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::Artist); if (!string.isNull()) { m_metadata.insert(isVideo ? QMediaMetaData::LeadPerformer : QMediaMetaData::ContributingArtist, string.split('/', QString::SkipEmptyParts)); } - string = m_retriever->extractMetadata(JMediaMetadataRetriever::Author); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::Author); if (!string.isNull()) m_metadata.insert(QMediaMetaData::Author, string.split('/', QString::SkipEmptyParts)); - string = m_retriever->extractMetadata(JMediaMetadataRetriever::Bitrate); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::Bitrate); if (!string.isNull()) { m_metadata.insert(isVideo ? QMediaMetaData::VideoBitRate : QMediaMetaData::AudioBitRate, string.toInt()); } - string = m_retriever->extractMetadata(JMediaMetadataRetriever::CDTrackNumber); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::CDTrackNumber); if (!string.isNull()) m_metadata.insert(QMediaMetaData::TrackNumber, string.toInt()); - string = m_retriever->extractMetadata(JMediaMetadataRetriever::Composer); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::Composer); if (!string.isNull()) m_metadata.insert(QMediaMetaData::Composer, string.split('/', QString::SkipEmptyParts)); - string = m_retriever->extractMetadata(JMediaMetadataRetriever::Date); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::Date); if (!string.isNull()) m_metadata.insert(QMediaMetaData::Date, QDateTime::fromString(string, QStringLiteral("yyyyMMddTHHmmss.zzzZ")).date()); - string = m_retriever->extractMetadata(JMediaMetadataRetriever::Duration); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::Duration); if (!string.isNull()) m_metadata.insert(QMediaMetaData::Duration, string.toLongLong()); - string = m_retriever->extractMetadata(JMediaMetadataRetriever::Genre); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::Genre); if (!string.isNull()) { // The genre can be returned as an ID3v2 id, get the name for it in that case if (string.startsWith('(') && string.endsWith(')')) { @@ -185,22 +185,22 @@ void QAndroidMetaDataReaderControl::updateData() m_metadata.insert(QMediaMetaData::Genre, string); } - string = m_retriever->extractMetadata(JMediaMetadataRetriever::Title); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::Title); if (!string.isNull()) m_metadata.insert(QMediaMetaData::Title, string); - string = m_retriever->extractMetadata(JMediaMetadataRetriever::VideoHeight); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::VideoHeight); if (!string.isNull()) { int height = string.toInt(); - int width = m_retriever->extractMetadata(JMediaMetadataRetriever::VideoWidth).toInt(); + int width = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::VideoWidth).toInt(); m_metadata.insert(QMediaMetaData::Resolution, QSize(width, height)); } - string = m_retriever->extractMetadata(JMediaMetadataRetriever::Writer); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::Writer); if (!string.isNull()) m_metadata.insert(QMediaMetaData::Writer, string.split('/', QString::SkipEmptyParts)); - string = m_retriever->extractMetadata(JMediaMetadataRetriever::Year); + string = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::Year); if (!string.isNull()) m_metadata.insert(QMediaMetaData::Year, string.toInt()); } diff --git a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h index 7ea736ffd..67b92f1eb 100644 --- a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h +++ b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h @@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE -class JMediaMetadataRetriever; +class AndroidMediaMetadataRetriever; class QAndroidMetaDataReaderControl : public QMetaDataReaderControl { @@ -72,7 +72,7 @@ private: bool m_available; QVariantMap m_metadata; - JMediaMetadataRetriever *m_retriever; + AndroidMediaMetadataRetriever *m_retriever; }; QT_END_NAMESPACE diff --git a/src/plugins/android/src/qandroidmediaserviceplugin.cpp b/src/plugins/android/src/qandroidmediaserviceplugin.cpp index 0af43210f..4d777ce97 100644 --- a/src/plugins/android/src/qandroidmediaserviceplugin.cpp +++ b/src/plugins/android/src/qandroidmediaserviceplugin.cpp @@ -46,11 +46,11 @@ #include "qandroidaudioinputselectorcontrol.h" #include "qandroidcamerainfocontrol.h" #include "qandroidcamerasession.h" -#include "jmediaplayer.h" -#include "jsurfacetexture.h" -#include "jcamera.h" -#include "jmultimediautils.h" -#include "jmediarecorder.h" +#include "androidmediaplayer.h" +#include "androidsurfacetexture.h" +#include "androidcamera.h" +#include "androidmultimediautils.h" +#include "androidmediarecorder.h" #include <qdebug.h> QT_BEGIN_NAMESPACE @@ -147,9 +147,12 @@ int QAndroidMediaServicePlugin::cameraOrientation(const QByteArray &device) cons return QAndroidCameraInfoControl::orientation(device); } +QT_END_NAMESPACE +#ifndef Q_OS_ANDROID_NO_SDK Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/) { + QT_USE_NAMESPACE typedef union { JNIEnv *nativeEnvironment; void *venv; @@ -163,15 +166,14 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/) JNIEnv *jniEnv = uenv.nativeEnvironment; - if (!JMediaPlayer::initJNI(jniEnv) || - !JCamera::initJNI(jniEnv) || - !JMediaRecorder::initJNI(jniEnv)) { + if (!AndroidMediaPlayer::initJNI(jniEnv) || + !AndroidCamera::initJNI(jniEnv) || + !AndroidMediaRecorder::initJNI(jniEnv)) { return JNI_ERR; } - JSurfaceTexture::initJNI(jniEnv); + AndroidSurfaceTexture::initJNI(jniEnv); return JNI_VERSION_1_4; } - -QT_END_NAMESPACE +#endif // Q_OS_ANDROID_NO_SDK diff --git a/src/plugins/android/src/src.pro b/src/plugins/android/src/src.pro index d071f6fcd..6a472a0a8 100644 --- a/src/plugins/android/src/src.pro +++ b/src/plugins/android/src/src.pro @@ -11,7 +11,7 @@ HEADERS += \ SOURCES += \ qandroidmediaserviceplugin.cpp -include (wrappers/wrappers.pri) +include (wrappers/jni/jni.pri) include (common/common.pri) include (mediaplayer/mediaplayer.pri) include (mediacapture/mediacapture.pri) diff --git a/src/plugins/android/src/wrappers/jcamera.cpp b/src/plugins/android/src/wrappers/jni/androidcamera.cpp index b0e9f89f3..c917bf2b7 100644 --- a/src/plugins/android/src/wrappers/jcamera.cpp +++ b/src/plugins/android/src/wrappers/jni/androidcamera.cpp @@ -39,21 +39,22 @@ ** ****************************************************************************/ -#include "jcamera.h" +#include "androidcamera.h" +#include "androidsurfacetexture.h" +#include "qandroidmultimediautils.h" -#include <QtCore/private/qjni_p.h> #include <qstringlist.h> #include <qdebug.h> -#include "qandroidmultimediautils.h" -#include <qthread.h> #include <qmutex.h> #include <QtCore/private/qjnihelpers_p.h> +#include <QtCore/qthread.h> QT_BEGIN_NAMESPACE -static jclass g_qtCameraClass = 0; -static QMap<int, JCamera*> g_objectMap; -static QMutex g_objectMapMutex; +static jclass g_qtCameraListenerClass = 0; +static QMutex g_cameraMapMutex; +typedef QMap<int, AndroidCamera *> CameraMap; +Q_GLOBAL_STATIC(CameraMap, g_cameraMap) static QRect areaToRect(jobject areaObj) { @@ -79,34 +80,30 @@ static QJNIObjectPrivate rectToArea(const QRect &rect) return area; } -// native method for QtCamera.java +// native method for QtCameraLisener.java static void notifyAutoFocusComplete(JNIEnv* , jobject, int id, jboolean success) { - g_objectMapMutex.lock(); - JCamera *obj = g_objectMap.value(id, 0); - g_objectMapMutex.unlock(); + QMutexLocker locker(&g_cameraMapMutex); + AndroidCamera *obj = g_cameraMap->value(id, 0); if (obj) Q_EMIT obj->autoFocusComplete(success); } static void notifyPictureExposed(JNIEnv* , jobject, int id) { - g_objectMapMutex.lock(); - JCamera *obj = g_objectMap.value(id, 0); - g_objectMapMutex.unlock(); + QMutexLocker locker(&g_cameraMapMutex); + AndroidCamera *obj = g_cameraMap->value(id, 0); if (obj) Q_EMIT obj->pictureExposed(); } static void notifyPictureCaptured(JNIEnv *env, jobject, int id, jbyteArray data) { - g_objectMapMutex.lock(); - JCamera *obj = g_objectMap.value(id, 0); - g_objectMapMutex.unlock(); + QMutexLocker locker(&g_cameraMapMutex); + AndroidCamera *obj = g_cameraMap->value(id, 0); if (obj) { - QByteArray bytes; - int arrayLength = env->GetArrayLength(data); - bytes.resize(arrayLength); + const int arrayLength = env->GetArrayLength(data); + QByteArray bytes(arrayLength, Qt::Uninitialized); env->GetByteArrayRegion(data, 0, arrayLength, (jbyte*)bytes.data()); Q_EMIT obj->pictureCaptured(bytes); } @@ -114,56 +111,39 @@ static void notifyPictureCaptured(JNIEnv *env, jobject, int id, jbyteArray data) static void notifyFrameFetched(JNIEnv *env, jobject, int id, jbyteArray data) { - g_objectMapMutex.lock(); - JCamera *obj = g_objectMap.value(id, 0); - g_objectMapMutex.unlock(); + QMutexLocker locker(&g_cameraMapMutex); + AndroidCamera *obj = g_cameraMap->value(id, 0); if (obj) { - QByteArray bytes; - int arrayLength = env->GetArrayLength(data); - bytes.resize(arrayLength); + const int arrayLength = env->GetArrayLength(data); + QByteArray bytes(arrayLength, Qt::Uninitialized); env->GetByteArrayRegion(data, 0, arrayLength, (jbyte*)bytes.data()); Q_EMIT obj->frameFetched(bytes); } } -class JCameraInstantiator : public QObject +class AndroidCameraPrivate : public QObject { Q_OBJECT public: - JCameraInstantiator() : QObject(0) {} - QJNIObjectPrivate result() {return lastCamera;} -public slots: - void openCamera(int cameraId) - { - QJNIEnvironmentPrivate env; - lastCamera = QJNIObjectPrivate::callStaticObjectMethod(g_qtCameraClass, - "open", - "(I)Lorg/qtproject/qt5/android/multimedia/QtCamera;", - cameraId); - } -private: - QJNIObjectPrivate lastCamera; -}; + AndroidCameraPrivate(); + ~AndroidCameraPrivate(); -class JCameraWorker : public QObject -{ - Q_OBJECT - friend class JCamera; - - JCameraWorker(JCamera *camera, int cameraId, jobject cam, QThread *workerThread); - ~JCameraWorker(); + Q_INVOKABLE bool init(int cameraId); Q_INVOKABLE void release(); + Q_INVOKABLE void lock(); + Q_INVOKABLE void unlock(); + Q_INVOKABLE void reconnect(); - Q_INVOKABLE JCamera::CameraFacing getFacing(); + Q_INVOKABLE AndroidCamera::CameraFacing getFacing(); Q_INVOKABLE int getNativeOrientation(); Q_INVOKABLE QSize getPreferredPreviewSizeForVideo(); Q_INVOKABLE QList<QSize> getSupportedPreviewSizes(); - Q_INVOKABLE JCamera::ImageFormat getPreviewFormat(); - Q_INVOKABLE void setPreviewFormat(JCamera::ImageFormat fmt); + Q_INVOKABLE AndroidCamera::ImageFormat getPreviewFormat(); + Q_INVOKABLE void setPreviewFormat(AndroidCamera::ImageFormat fmt); Q_INVOKABLE QSize previewSize() const { return m_previewSize; } Q_INVOKABLE void updatePreviewSize(); @@ -186,6 +166,7 @@ class JCameraWorker : public QObject Q_INVOKABLE void setFocusAreas(const QList<QRect> &areas); Q_INVOKABLE void autoFocus(); + Q_INVOKABLE void cancelAutoFocus(); Q_INVOKABLE bool isAutoExposureLockSupported(); Q_INVOKABLE bool getAutoExposureLock(); @@ -216,26 +197,23 @@ class JCameraWorker : public QObject Q_INVOKABLE void startPreview(); Q_INVOKABLE void stopPreview(); + Q_INVOKABLE void takePicture(); + Q_INVOKABLE void fetchEachFrame(bool fetch); Q_INVOKABLE void fetchLastPreviewFrame(); Q_INVOKABLE void applyParameters(); Q_INVOKABLE QStringList callParametersStringListMethod(const QByteArray &methodName); - Q_INVOKABLE void callVoidMethod(const QByteArray &methodName); int m_cameraId; - QJNIObjectPrivate m_info; - QJNIObjectPrivate m_parameters; - + QMutex m_parametersMutex; QSize m_previewSize; int m_rotation; - - JCamera *q; - - QThread *m_workerThread; - QMutex m_parametersMutex; + QJNIObjectPrivate m_info; + QJNIObjectPrivate m_parameters; QJNIObjectPrivate m_camera; + QJNIObjectPrivate m_cameraListener; Q_SIGNALS: void previewSizeChanged(); @@ -249,122 +227,137 @@ Q_SIGNALS: void previewFetched(const QByteArray &preview); }; +AndroidCamera::AndroidCamera(AndroidCameraPrivate *d, QThread *worker) + : QObject(), + d_ptr(d), + m_worker(worker) - -JCamera::JCamera(int cameraId, jobject cam, QThread *workerThread) - : QObject() { qRegisterMetaType<QList<int> >(); qRegisterMetaType<QList<QSize> >(); qRegisterMetaType<QList<QRect> >(); - d = new JCameraWorker(this, cameraId, cam, workerThread); - connect(d, &JCameraWorker::previewSizeChanged, this, &JCamera::previewSizeChanged); - connect(d, &JCameraWorker::previewStarted, this, &JCamera::previewStarted); - connect(d, &JCameraWorker::previewStopped, this, &JCamera::previewStopped); - connect(d, &JCameraWorker::autoFocusStarted, this, &JCamera::autoFocusStarted); - connect(d, &JCameraWorker::whiteBalanceChanged, this, &JCamera::whiteBalanceChanged); - connect(d, &JCameraWorker::previewFetched, this, &JCamera::previewFetched); + connect(d, &AndroidCameraPrivate::previewSizeChanged, this, &AndroidCamera::previewSizeChanged); + connect(d, &AndroidCameraPrivate::previewStarted, this, &AndroidCamera::previewStarted); + connect(d, &AndroidCameraPrivate::previewStopped, this, &AndroidCamera::previewStopped); + connect(d, &AndroidCameraPrivate::autoFocusStarted, this, &AndroidCamera::autoFocusStarted); + connect(d, &AndroidCameraPrivate::whiteBalanceChanged, this, &AndroidCamera::whiteBalanceChanged); + connect(d, &AndroidCameraPrivate::previewFetched, this, &AndroidCamera::previewFetched); } -JCamera::~JCamera() +AndroidCamera::~AndroidCamera() { + Q_D(AndroidCamera); if (d->m_camera.isValid()) { - g_objectMapMutex.lock(); - g_objectMap.remove(d->m_cameraId); - g_objectMapMutex.unlock(); + g_cameraMapMutex.lock(); + g_cameraMap->remove(d->m_cameraId); + g_cameraMapMutex.unlock(); } - d->deleteLater(); -} - -JCamera *JCamera::open(int cameraId) -{ - QThread *cameraThread = new QThread; - connect(cameraThread, &QThread::finished, cameraThread, &QThread::deleteLater); - cameraThread->start(); - JCameraInstantiator *instantiator = new JCameraInstantiator; - instantiator->moveToThread(cameraThread); - QMetaObject::invokeMethod(instantiator, "openCamera", - Qt::BlockingQueuedConnection, - Q_ARG(int, cameraId)); - QJNIObjectPrivate camera = instantiator->result(); - delete instantiator; - if (!camera.isValid()) { - cameraThread->terminate(); - delete cameraThread; + release(); + m_worker->exit(); + m_worker->wait(5000); +} + +AndroidCamera *AndroidCamera::open(int cameraId) +{ + AndroidCameraPrivate *d = new AndroidCameraPrivate(); + QThread *worker = new QThread; + worker->start(); + d->moveToThread(worker); + connect(worker, &QThread::finished, d, &AndroidCameraPrivate::deleteLater); + bool ok = false; + QMetaObject::invokeMethod(d, "init", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, ok), Q_ARG(int, cameraId)); + if (!ok) { + worker->quit(); + worker->wait(5000); + delete d; + delete worker; return 0; - } else { - return new JCamera(cameraId, camera.object(), cameraThread); } + + AndroidCamera *q = new AndroidCamera(d, worker); + g_cameraMapMutex.lock(); + g_cameraMap->insert(cameraId, q); + g_cameraMapMutex.unlock(); + return q; } -int JCamera::cameraId() const +int AndroidCamera::cameraId() const { + Q_D(const AndroidCamera); return d->m_cameraId; } -void JCamera::lock() +void AndroidCamera::lock() { - QMetaObject::invokeMethod(d, "callVoidMethod", - Qt::BlockingQueuedConnection, - Q_ARG(QByteArray, "lock")); + Q_D(AndroidCamera); + QMetaObject::invokeMethod(d, "lock", Qt::BlockingQueuedConnection); } -void JCamera::unlock() +void AndroidCamera::unlock() { - QMetaObject::invokeMethod(d, "callVoidMethod", - Qt::BlockingQueuedConnection, - Q_ARG(QByteArray, "unlock")); + Q_D(AndroidCamera); + QMetaObject::invokeMethod(d, "unlock", Qt::BlockingQueuedConnection); } -void JCamera::reconnect() +void AndroidCamera::reconnect() { - QMetaObject::invokeMethod(d, "callVoidMethod", Q_ARG(QByteArray, "reconnect")); + Q_D(AndroidCamera); + QMetaObject::invokeMethod(d, "reconnect"); } -void JCamera::release() +void AndroidCamera::release() { - QMetaObject::invokeMethod(d, "release"); + Q_D(AndroidCamera); + QMetaObject::invokeMethod(d, "release", Qt::BlockingQueuedConnection); } -JCamera::CameraFacing JCamera::getFacing() +AndroidCamera::CameraFacing AndroidCamera::getFacing() { + Q_D(AndroidCamera); return d->getFacing(); } -int JCamera::getNativeOrientation() +int AndroidCamera::getNativeOrientation() { + Q_D(AndroidCamera); return d->getNativeOrientation(); } -QSize JCamera::getPreferredPreviewSizeForVideo() +QSize AndroidCamera::getPreferredPreviewSizeForVideo() { + Q_D(AndroidCamera); return d->getPreferredPreviewSizeForVideo(); } -QList<QSize> JCamera::getSupportedPreviewSizes() +QList<QSize> AndroidCamera::getSupportedPreviewSizes() { + Q_D(AndroidCamera); return d->getSupportedPreviewSizes(); } -JCamera::ImageFormat JCamera::getPreviewFormat() +AndroidCamera::ImageFormat AndroidCamera::getPreviewFormat() { + Q_D(AndroidCamera); return d->getPreviewFormat(); } -void JCamera::setPreviewFormat(ImageFormat fmt) +void AndroidCamera::setPreviewFormat(ImageFormat fmt) { - QMetaObject::invokeMethod(d, "setPreviewFormat", Q_ARG(JCamera::ImageFormat, fmt)); + Q_D(AndroidCamera); + QMetaObject::invokeMethod(d, "setPreviewFormat", Q_ARG(AndroidCamera::ImageFormat, fmt)); } -QSize JCamera::previewSize() const +QSize AndroidCamera::previewSize() const { + Q_D(const AndroidCamera); return d->m_previewSize; } -void JCamera::setPreviewSize(const QSize &size) +void AndroidCamera::setPreviewSize(const QSize &size) { + Q_D(AndroidCamera); d->m_parametersMutex.lock(); bool areParametersValid = d->m_parameters.isValid(); d->m_parametersMutex.unlock(); @@ -375,178 +368,216 @@ void JCamera::setPreviewSize(const QSize &size) QMetaObject::invokeMethod(d, "updatePreviewSize"); } -void JCamera::setPreviewTexture(jobject surfaceTexture) +void AndroidCamera::setPreviewTexture(AndroidSurfaceTexture *surfaceTexture) { - QMetaObject::invokeMethod(d, "setPreviewTexture", Q_ARG(void *, surfaceTexture)); + Q_D(AndroidCamera); + QMetaObject::invokeMethod(d, + "setPreviewTexture", + Qt::BlockingQueuedConnection, + Q_ARG(void *, surfaceTexture ? surfaceTexture->surfaceTexture() : 0)); } -bool JCamera::isZoomSupported() +bool AndroidCamera::isZoomSupported() { + Q_D(AndroidCamera); return d->isZoomSupported(); } -int JCamera::getMaxZoom() +int AndroidCamera::getMaxZoom() { + Q_D(AndroidCamera); return d->getMaxZoom(); } -QList<int> JCamera::getZoomRatios() +QList<int> AndroidCamera::getZoomRatios() { + Q_D(AndroidCamera); return d->getZoomRatios(); } -int JCamera::getZoom() +int AndroidCamera::getZoom() { + Q_D(AndroidCamera); return d->getZoom(); } -void JCamera::setZoom(int value) +void AndroidCamera::setZoom(int value) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "setZoom", Q_ARG(int, value)); } -QStringList JCamera::getSupportedFlashModes() +QStringList AndroidCamera::getSupportedFlashModes() { + Q_D(AndroidCamera); return d->callParametersStringListMethod("getSupportedFlashModes"); } -QString JCamera::getFlashMode() +QString AndroidCamera::getFlashMode() { + Q_D(AndroidCamera); return d->getFlashMode(); } -void JCamera::setFlashMode(const QString &value) +void AndroidCamera::setFlashMode(const QString &value) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "setFlashMode", Q_ARG(QString, value)); } -QStringList JCamera::getSupportedFocusModes() +QStringList AndroidCamera::getSupportedFocusModes() { + Q_D(AndroidCamera); return d->callParametersStringListMethod("getSupportedFocusModes"); } -QString JCamera::getFocusMode() +QString AndroidCamera::getFocusMode() { + Q_D(AndroidCamera); return d->getFocusMode(); } -void JCamera::setFocusMode(const QString &value) +void AndroidCamera::setFocusMode(const QString &value) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "setFocusMode", Q_ARG(QString, value)); } -int JCamera::getMaxNumFocusAreas() +int AndroidCamera::getMaxNumFocusAreas() { + Q_D(AndroidCamera); return d->getMaxNumFocusAreas(); } -QList<QRect> JCamera::getFocusAreas() +QList<QRect> AndroidCamera::getFocusAreas() { + Q_D(AndroidCamera); return d->getFocusAreas(); } -void JCamera::setFocusAreas(const QList<QRect> &areas) +void AndroidCamera::setFocusAreas(const QList<QRect> &areas) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "setFocusAreas", Q_ARG(QList<QRect>, areas)); } -void JCamera::autoFocus() +void AndroidCamera::autoFocus() { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "autoFocus"); } -void JCamera::cancelAutoFocus() +void AndroidCamera::cancelAutoFocus() { - QMetaObject::invokeMethod(d, "callVoidMethod", Q_ARG(QByteArray, "cancelAutoFocus")); + Q_D(AndroidCamera); + QMetaObject::invokeMethod(d, "cancelAutoFocus", Qt::QueuedConnection); } -bool JCamera::isAutoExposureLockSupported() +bool AndroidCamera::isAutoExposureLockSupported() { + Q_D(AndroidCamera); return d->isAutoExposureLockSupported(); } -bool JCamera::getAutoExposureLock() +bool AndroidCamera::getAutoExposureLock() { + Q_D(AndroidCamera); return d->getAutoExposureLock(); } -void JCamera::setAutoExposureLock(bool toggle) +void AndroidCamera::setAutoExposureLock(bool toggle) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "setAutoExposureLock", Q_ARG(bool, toggle)); } -bool JCamera::isAutoWhiteBalanceLockSupported() +bool AndroidCamera::isAutoWhiteBalanceLockSupported() { + Q_D(AndroidCamera); return d->isAutoWhiteBalanceLockSupported(); } -bool JCamera::getAutoWhiteBalanceLock() +bool AndroidCamera::getAutoWhiteBalanceLock() { + Q_D(AndroidCamera); return d->getAutoWhiteBalanceLock(); } -void JCamera::setAutoWhiteBalanceLock(bool toggle) +void AndroidCamera::setAutoWhiteBalanceLock(bool toggle) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "setAutoWhiteBalanceLock", Q_ARG(bool, toggle)); } -int JCamera::getExposureCompensation() +int AndroidCamera::getExposureCompensation() { + Q_D(AndroidCamera); return d->getExposureCompensation(); } -void JCamera::setExposureCompensation(int value) +void AndroidCamera::setExposureCompensation(int value) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "setExposureCompensation", Q_ARG(int, value)); } -float JCamera::getExposureCompensationStep() +float AndroidCamera::getExposureCompensationStep() { + Q_D(AndroidCamera); return d->getExposureCompensationStep(); } -int JCamera::getMinExposureCompensation() +int AndroidCamera::getMinExposureCompensation() { + Q_D(AndroidCamera); return d->getMinExposureCompensation(); } -int JCamera::getMaxExposureCompensation() +int AndroidCamera::getMaxExposureCompensation() { + Q_D(AndroidCamera); return d->getMaxExposureCompensation(); } -QStringList JCamera::getSupportedSceneModes() +QStringList AndroidCamera::getSupportedSceneModes() { + Q_D(AndroidCamera); return d->callParametersStringListMethod("getSupportedSceneModes"); } -QString JCamera::getSceneMode() +QString AndroidCamera::getSceneMode() { + Q_D(AndroidCamera); return d->getSceneMode(); } -void JCamera::setSceneMode(const QString &value) +void AndroidCamera::setSceneMode(const QString &value) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "setSceneMode", Q_ARG(QString, value)); } -QStringList JCamera::getSupportedWhiteBalance() +QStringList AndroidCamera::getSupportedWhiteBalance() { + Q_D(AndroidCamera); return d->callParametersStringListMethod("getSupportedWhiteBalance"); } -QString JCamera::getWhiteBalance() +QString AndroidCamera::getWhiteBalance() { + Q_D(AndroidCamera); return d->getWhiteBalance(); } -void JCamera::setWhiteBalance(const QString &value) +void AndroidCamera::setWhiteBalance(const QString &value) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "setWhiteBalance", Q_ARG(QString, value)); } -void JCamera::setRotation(int rotation) +void AndroidCamera::setRotation(int rotation) { + Q_D(AndroidCamera); //We need to do it here and not in worker class because we cache rotation d->m_parametersMutex.lock(); bool areParametersValid = d->m_parameters.isValid(); @@ -558,112 +589,181 @@ void JCamera::setRotation(int rotation) QMetaObject::invokeMethod(d, "updateRotation"); } -int JCamera::getRotation() const +int AndroidCamera::getRotation() const { + Q_D(const AndroidCamera); return d->m_rotation; } -QList<QSize> JCamera::getSupportedPictureSizes() +QList<QSize> AndroidCamera::getSupportedPictureSizes() { + Q_D(AndroidCamera); return d->getSupportedPictureSizes(); } -void JCamera::setPictureSize(const QSize &size) +void AndroidCamera::setPictureSize(const QSize &size) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "setPictureSize", Q_ARG(QSize, size)); } -void JCamera::setJpegQuality(int quality) +void AndroidCamera::setJpegQuality(int quality) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "setJpegQuality", Q_ARG(int, quality)); } -void JCamera::takePicture() +void AndroidCamera::takePicture() { - QMetaObject::invokeMethod(d, "callVoidMethod", Q_ARG(QByteArray, "takePicture")); + Q_D(AndroidCamera); + QMetaObject::invokeMethod(d, "takePicture", Qt::BlockingQueuedConnection); } -void JCamera::fetchEachFrame(bool fetch) +void AndroidCamera::fetchEachFrame(bool fetch) { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "fetchEachFrame", Q_ARG(bool, fetch)); } -void JCamera::fetchLastPreviewFrame() +void AndroidCamera::fetchLastPreviewFrame() { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "fetchLastPreviewFrame"); } -QJNIObjectPrivate JCamera::getCameraObject() +QJNIObjectPrivate AndroidCamera::getCameraObject() { - return d->m_camera.getObjectField("m_camera", "Landroid/hardware/Camera;"); + Q_D(AndroidCamera); + return d->m_camera; } -void JCamera::startPreview() +int AndroidCamera::getNumberOfCameras() { + return QJNIObjectPrivate::callStaticMethod<jint>("android/hardware/Camera", + "getNumberOfCameras"); +} + +void AndroidCamera::getCameraInfo(int id, AndroidCameraInfo *info) +{ + Q_ASSERT(info); + + QJNIObjectPrivate cameraInfo("android/hardware/Camera$CameraInfo"); + QJNIObjectPrivate::callStaticMethod<void>("android/hardware/Camera", + "getCameraInfo", + "(ILandroid/hardware/Camera$CameraInfo;)V", + id, cameraInfo.object()); + + AndroidCamera::CameraFacing facing = AndroidCamera::CameraFacing(cameraInfo.getField<jint>("facing")); + // The orientation provided by Android is counter-clockwise, we need it clockwise + info->orientation = (360 - cameraInfo.getField<jint>("orientation")) % 360; + + switch (facing) { + case AndroidCamera::CameraFacingBack: + info->name = QByteArray("back"); + info->description = QStringLiteral("Rear-facing camera"); + info->position = QCamera::BackFace; + break; + case AndroidCamera::CameraFacingFront: + info->name = QByteArray("front"); + info->description = QStringLiteral("Front-facing camera"); + info->position = QCamera::FrontFace; + break; + default: + break; + } +} + +void AndroidCamera::startPreview() +{ + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "startPreview"); } -void JCamera::stopPreview() +void AndroidCamera::stopPreview() { + Q_D(AndroidCamera); QMetaObject::invokeMethod(d, "stopPreview"); } +AndroidCameraPrivate::AndroidCameraPrivate() + : QObject(), + m_parametersMutex(QMutex::Recursive) +{ +} -//JCameraWorker +AndroidCameraPrivate::~AndroidCameraPrivate() +{ +} -JCameraWorker::JCameraWorker(JCamera *camera, int cameraId, jobject cam, QThread *workerThread) - : QObject(0) - , m_cameraId(cameraId) - , m_rotation(0) - , m_parametersMutex(QMutex::Recursive) - , m_camera(cam) +bool AndroidCameraPrivate::init(int cameraId) { - q = camera; - m_workerThread = workerThread; - moveToThread(m_workerThread); + m_cameraId = cameraId; + m_camera = QJNIObjectPrivate::callStaticObjectMethod("android/hardware/Camera", + "open", + "(I)Landroid/hardware/Camera;", + cameraId); - if (m_camera.isValid()) { - g_objectMapMutex.lock(); - g_objectMap.insert(cameraId, q); - g_objectMapMutex.unlock(); + if (!m_camera.isValid()) + return false; - m_info = QJNIObjectPrivate("android/hardware/Camera$CameraInfo"); - m_camera.callStaticMethod<void>("android/hardware/Camera", - "getCameraInfo", - "(ILandroid/hardware/Camera$CameraInfo;)V", - cameraId, m_info.object()); + m_cameraListener = QJNIObjectPrivate(g_qtCameraListenerClass, "(I)V", m_cameraId); + m_info = QJNIObjectPrivate("android/hardware/Camera$CameraInfo"); + m_camera.callStaticMethod<void>("android/hardware/Camera", + "getCameraInfo", + "(ILandroid/hardware/Camera$CameraInfo;)V", + cameraId, + m_info.object()); - QJNIObjectPrivate params = m_camera.callObjectMethod("getParameters", - "()Landroid/hardware/Camera$Parameters;"); - m_parameters = QJNIObjectPrivate(params); - } -} + QJNIObjectPrivate params = m_camera.callObjectMethod("getParameters", + "()Landroid/hardware/Camera$Parameters;"); + m_parameters = QJNIObjectPrivate(params); -JCameraWorker::~JCameraWorker() -{ - m_workerThread->quit(); + return true; } -void JCameraWorker::release() +void AndroidCameraPrivate::release() { m_previewSize = QSize(); m_parametersMutex.lock(); m_parameters = QJNIObjectPrivate(); m_parametersMutex.unlock(); - m_camera.callMethod<void>("release"); + if (m_camera.isValid()) + m_camera.callMethod<void>("release"); +} + +void AndroidCameraPrivate::lock() +{ + m_camera.callMethod<void>("lock"); +} + +void AndroidCameraPrivate::unlock() +{ + m_camera.callMethod<void>("unlock"); } -JCamera::CameraFacing JCameraWorker::getFacing() +void AndroidCameraPrivate::reconnect() { - return JCamera::CameraFacing(m_info.getField<jint>("facing")); + QJNIEnvironmentPrivate env; + m_camera.callMethod<void>("reconnect"); + if (env->ExceptionCheck()) { +#ifdef QT_DEBUG + env->ExceptionDescribe(); +#endif // QT_DEBUG + env->ExceptionDescribe(); + } +} + +AndroidCamera::CameraFacing AndroidCameraPrivate::getFacing() +{ + return AndroidCamera::CameraFacing(m_info.getField<jint>("facing")); } -int JCameraWorker::getNativeOrientation() +int AndroidCameraPrivate::getNativeOrientation() { return m_info.getField<jint>("orientation"); } -QSize JCameraWorker::getPreferredPreviewSizeForVideo() +QSize AndroidCameraPrivate::getPreferredPreviewSizeForVideo() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -676,7 +776,7 @@ QSize JCameraWorker::getPreferredPreviewSizeForVideo() return QSize(size.getField<jint>("width"), size.getField<jint>("height")); } -QList<QSize> JCameraWorker::getSupportedPreviewSizes() +QList<QSize> AndroidCameraPrivate::getSupportedPreviewSizes() { QList<QSize> list; @@ -699,17 +799,17 @@ QList<QSize> JCameraWorker::getSupportedPreviewSizes() return list; } -JCamera::ImageFormat JCameraWorker::getPreviewFormat() +AndroidCamera::ImageFormat AndroidCameraPrivate::getPreviewFormat() { QMutexLocker parametersLocker(&m_parametersMutex); if (!m_parameters.isValid()) - return JCamera::Unknown; + return AndroidCamera::Unknown; - return JCamera::ImageFormat(m_parameters.callMethod<jint>("getPreviewFormat")); + return AndroidCamera::ImageFormat(m_parameters.callMethod<jint>("getPreviewFormat")); } -void JCameraWorker::setPreviewFormat(JCamera::ImageFormat fmt) +void AndroidCameraPrivate::setPreviewFormat(AndroidCamera::ImageFormat fmt) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -720,7 +820,7 @@ void JCameraWorker::setPreviewFormat(JCamera::ImageFormat fmt) applyParameters(); } -void JCameraWorker::updatePreviewSize() +void AndroidCameraPrivate::updatePreviewSize() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -732,14 +832,14 @@ void JCameraWorker::updatePreviewSize() emit previewSizeChanged(); } -void JCameraWorker::setPreviewTexture(void *surfaceTexture) +void AndroidCameraPrivate::setPreviewTexture(void *surfaceTexture) { m_camera.callMethod<void>("setPreviewTexture", "(Landroid/graphics/SurfaceTexture;)V", static_cast<jobject>(surfaceTexture)); } -bool JCameraWorker::isZoomSupported() +bool AndroidCameraPrivate::isZoomSupported() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -749,7 +849,7 @@ bool JCameraWorker::isZoomSupported() return m_parameters.callMethod<jboolean>("isZoomSupported"); } -int JCameraWorker::getMaxZoom() +int AndroidCameraPrivate::getMaxZoom() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -759,7 +859,7 @@ int JCameraWorker::getMaxZoom() return m_parameters.callMethod<jint>("getMaxZoom"); } -QList<int> JCameraWorker::getZoomRatios() +QList<int> AndroidCameraPrivate::getZoomRatios() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -781,7 +881,7 @@ QList<int> JCameraWorker::getZoomRatios() return ratios; } -int JCameraWorker::getZoom() +int AndroidCameraPrivate::getZoom() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -791,7 +891,7 @@ int JCameraWorker::getZoom() return m_parameters.callMethod<jint>("getZoom"); } -void JCameraWorker::setZoom(int value) +void AndroidCameraPrivate::setZoom(int value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -802,7 +902,7 @@ void JCameraWorker::setZoom(int value) applyParameters(); } -QString JCameraWorker::getFlashMode() +QString AndroidCameraPrivate::getFlashMode() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -818,7 +918,7 @@ QString JCameraWorker::getFlashMode() return value; } -void JCameraWorker::setFlashMode(const QString &value) +void AndroidCameraPrivate::setFlashMode(const QString &value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -831,7 +931,7 @@ void JCameraWorker::setFlashMode(const QString &value) applyParameters(); } -QString JCameraWorker::getFocusMode() +QString AndroidCameraPrivate::getFocusMode() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -847,7 +947,7 @@ QString JCameraWorker::getFocusMode() return value; } -void JCameraWorker::setFocusMode(const QString &value) +void AndroidCameraPrivate::setFocusMode(const QString &value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -860,7 +960,7 @@ void JCameraWorker::setFocusMode(const QString &value) applyParameters(); } -int JCameraWorker::getMaxNumFocusAreas() +int AndroidCameraPrivate::getMaxNumFocusAreas() { if (QtAndroidPrivate::androidSdkVersion() < 14) return 0; @@ -873,7 +973,7 @@ int JCameraWorker::getMaxNumFocusAreas() return m_parameters.callMethod<jint>("getMaxNumFocusAreas"); } -QList<QRect> JCameraWorker::getFocusAreas() +QList<QRect> AndroidCameraPrivate::getFocusAreas() { QList<QRect> areas; @@ -901,7 +1001,7 @@ QList<QRect> JCameraWorker::getFocusAreas() return areas; } -void JCameraWorker::setFocusAreas(const QList<QRect> &areas) +void AndroidCameraPrivate::setFocusAreas(const QList<QRect> &areas) { if (QtAndroidPrivate::androidSdkVersion() < 14) return; @@ -931,13 +1031,20 @@ void JCameraWorker::setFocusAreas(const QList<QRect> &areas) applyParameters(); } -void JCameraWorker::autoFocus() +void AndroidCameraPrivate::autoFocus() { - m_camera.callMethod<void>("autoFocus"); + m_camera.callMethod<void>("autoFocus", + "(Landroid/hardware/Camera$AutoFocusCallback;)V", + m_cameraListener.object()); emit autoFocusStarted(); } -bool JCameraWorker::isAutoExposureLockSupported() +void AndroidCameraPrivate::cancelAutoFocus() +{ + m_camera.callMethod<void>("cancelAutoFocus"); +} + +bool AndroidCameraPrivate::isAutoExposureLockSupported() { if (QtAndroidPrivate::androidSdkVersion() < 14) return false; @@ -950,7 +1057,7 @@ bool JCameraWorker::isAutoExposureLockSupported() return m_parameters.callMethod<jboolean>("isAutoExposureLockSupported"); } -bool JCameraWorker::getAutoExposureLock() +bool AndroidCameraPrivate::getAutoExposureLock() { if (QtAndroidPrivate::androidSdkVersion() < 14) return false; @@ -963,7 +1070,7 @@ bool JCameraWorker::getAutoExposureLock() return m_parameters.callMethod<jboolean>("getAutoExposureLock"); } -void JCameraWorker::setAutoExposureLock(bool toggle) +void AndroidCameraPrivate::setAutoExposureLock(bool toggle) { if (QtAndroidPrivate::androidSdkVersion() < 14) return; @@ -977,7 +1084,7 @@ void JCameraWorker::setAutoExposureLock(bool toggle) applyParameters(); } -bool JCameraWorker::isAutoWhiteBalanceLockSupported() +bool AndroidCameraPrivate::isAutoWhiteBalanceLockSupported() { if (QtAndroidPrivate::androidSdkVersion() < 14) return false; @@ -990,7 +1097,7 @@ bool JCameraWorker::isAutoWhiteBalanceLockSupported() return m_parameters.callMethod<jboolean>("isAutoWhiteBalanceLockSupported"); } -bool JCameraWorker::getAutoWhiteBalanceLock() +bool AndroidCameraPrivate::getAutoWhiteBalanceLock() { if (QtAndroidPrivate::androidSdkVersion() < 14) return false; @@ -1003,7 +1110,7 @@ bool JCameraWorker::getAutoWhiteBalanceLock() return m_parameters.callMethod<jboolean>("getAutoWhiteBalanceLock"); } -void JCameraWorker::setAutoWhiteBalanceLock(bool toggle) +void AndroidCameraPrivate::setAutoWhiteBalanceLock(bool toggle) { if (QtAndroidPrivate::androidSdkVersion() < 14) return; @@ -1017,7 +1124,7 @@ void JCameraWorker::setAutoWhiteBalanceLock(bool toggle) applyParameters(); } -int JCameraWorker::getExposureCompensation() +int AndroidCameraPrivate::getExposureCompensation() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1027,7 +1134,7 @@ int JCameraWorker::getExposureCompensation() return m_parameters.callMethod<jint>("getExposureCompensation"); } -void JCameraWorker::setExposureCompensation(int value) +void AndroidCameraPrivate::setExposureCompensation(int value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1038,7 +1145,7 @@ void JCameraWorker::setExposureCompensation(int value) applyParameters(); } -float JCameraWorker::getExposureCompensationStep() +float AndroidCameraPrivate::getExposureCompensationStep() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1048,7 +1155,7 @@ float JCameraWorker::getExposureCompensationStep() return m_parameters.callMethod<jfloat>("getExposureCompensationStep"); } -int JCameraWorker::getMinExposureCompensation() +int AndroidCameraPrivate::getMinExposureCompensation() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1058,7 +1165,7 @@ int JCameraWorker::getMinExposureCompensation() return m_parameters.callMethod<jint>("getMinExposureCompensation"); } -int JCameraWorker::getMaxExposureCompensation() +int AndroidCameraPrivate::getMaxExposureCompensation() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1068,7 +1175,7 @@ int JCameraWorker::getMaxExposureCompensation() return m_parameters.callMethod<jint>("getMaxExposureCompensation"); } -QString JCameraWorker::getSceneMode() +QString AndroidCameraPrivate::getSceneMode() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1084,7 +1191,7 @@ QString JCameraWorker::getSceneMode() return value; } -void JCameraWorker::setSceneMode(const QString &value) +void AndroidCameraPrivate::setSceneMode(const QString &value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1097,7 +1204,7 @@ void JCameraWorker::setSceneMode(const QString &value) applyParameters(); } -QString JCameraWorker::getWhiteBalance() +QString AndroidCameraPrivate::getWhiteBalance() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1113,7 +1220,7 @@ QString JCameraWorker::getWhiteBalance() return value; } -void JCameraWorker::setWhiteBalance(const QString &value) +void AndroidCameraPrivate::setWhiteBalance(const QString &value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1128,7 +1235,7 @@ void JCameraWorker::setWhiteBalance(const QString &value) emit whiteBalanceChanged(); } -void JCameraWorker::updateRotation() +void AndroidCameraPrivate::updateRotation() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1136,7 +1243,7 @@ void JCameraWorker::updateRotation() applyParameters(); } -QList<QSize> JCameraWorker::getSupportedPictureSizes() +QList<QSize> AndroidCameraPrivate::getSupportedPictureSizes() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1159,7 +1266,7 @@ QList<QSize> JCameraWorker::getSupportedPictureSizes() return list; } -void JCameraWorker::setPictureSize(const QSize &size) +void AndroidCameraPrivate::setPictureSize(const QSize &size) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1170,7 +1277,7 @@ void JCameraWorker::setPictureSize(const QSize &size) applyParameters(); } -void JCameraWorker::setJpegQuality(int quality) +void AndroidCameraPrivate::setJpegQuality(int quality) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1181,49 +1288,71 @@ void JCameraWorker::setJpegQuality(int quality) applyParameters(); } -void JCameraWorker::startPreview() -{ - callVoidMethod("startPreview"); +void AndroidCameraPrivate::startPreview() +{ + //We need to clear preview buffers queue here, but there is no method to do it + //Though just resetting preview callback do the trick + m_camera.callMethod<void>("setPreviewCallbackWithBuffer", + "(Landroid/hardware/Camera$PreviewCallback;)V", + jobject(0)); + m_cameraListener.callMethod<void>("preparePreviewBuffer", "(Landroid/hardware/Camera;)V", m_camera.object()); + QJNIObjectPrivate buffer = m_cameraListener.callObjectMethod<jbyteArray>("callbackBuffer"); + m_camera.callMethod<void>("addCallbackBuffer", "([B)V", buffer.object()); + m_camera.callMethod<void>("setPreviewCallbackWithBuffer", + "(Landroid/hardware/Camera$PreviewCallback;)V", + m_cameraListener.object()); + m_camera.callMethod<void>("startPreview"); emit previewStarted(); } -void JCameraWorker::stopPreview() +void AndroidCameraPrivate::stopPreview() { - callVoidMethod("stopPreview"); + m_camera.callMethod<void>("stopPreview"); emit previewStopped(); } -void JCameraWorker::fetchEachFrame(bool fetch) +void AndroidCameraPrivate::takePicture() { - m_camera.callMethod<void>("fetchEachFrame", "(Z)V", fetch); + m_camera.callMethod<void>("takePicture", "(Landroid/hardware/Camera$ShutterCallback;" + "Landroid/hardware/Camera$PictureCallback;" + "Landroid/hardware/Camera$PictureCallback;)V", + m_cameraListener.object(), + jobject(0), + m_cameraListener.object()); } -void JCameraWorker::fetchLastPreviewFrame() +void AndroidCameraPrivate::fetchEachFrame(bool fetch) +{ + m_cameraListener.callMethod<void>("fetchEachFrame", "(Z)V", fetch); +} + +void AndroidCameraPrivate::fetchLastPreviewFrame() { QJNIEnvironmentPrivate env; - QJNIObjectPrivate dataObj = m_camera.callObjectMethod("lockAndFetchPreviewBuffer", "()[B"); - if (!dataObj.object()) { - m_camera.callMethod<void>("unlockPreviewBuffer"); + QJNIObjectPrivate data = m_cameraListener.callObjectMethod("lockAndFetchPreviewBuffer", "()[B"); + if (!data.isValid()) { + m_cameraListener.callMethod<void>("unlockPreviewBuffer"); return; } - jbyteArray data = static_cast<jbyteArray>(dataObj.object()); - QByteArray bytes; - int arrayLength = env->GetArrayLength(data); - bytes.resize(arrayLength); - env->GetByteArrayRegion(data, 0, arrayLength, (jbyte*)bytes.data()); - m_camera.callMethod<void>("unlockPreviewBuffer"); + const int arrayLength = env->GetArrayLength(static_cast<jbyteArray>(data.object())); + QByteArray bytes(arrayLength, Qt::Uninitialized); + env->GetByteArrayRegion(static_cast<jbyteArray>(data.object()), + 0, + arrayLength, + reinterpret_cast<jbyte *>(bytes.data())); + m_cameraListener.callMethod<void>("unlockPreviewBuffer"); emit previewFetched(bytes); } -void JCameraWorker::applyParameters() +void AndroidCameraPrivate::applyParameters() { m_camera.callMethod<void>("setParameters", "(Landroid/hardware/Camera$Parameters;)V", m_parameters.object()); } -QStringList JCameraWorker::callParametersStringListMethod(const QByteArray &methodName) +QStringList AndroidCameraPrivate::callParametersStringListMethod(const QByteArray &methodName) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1239,7 +1368,6 @@ QStringList JCameraWorker::callParametersStringListMethod(const QByteArray &meth QJNIObjectPrivate string = list.callObjectMethod("get", "(I)Ljava/lang/Object;", i); - stringList.append(string.toString()); } } @@ -1248,12 +1376,6 @@ QStringList JCameraWorker::callParametersStringListMethod(const QByteArray &meth return stringList; } -void JCameraWorker::callVoidMethod(const QByteArray &methodName) -{ - m_camera.callMethod<void>(methodName.constData()); -} - - static JNINativeMethod methods[] = { {"notifyAutoFocusComplete", "(IZ)V", (void *)notifyAutoFocusComplete}, {"notifyPictureExposed", "(I)V", (void *)notifyPictureExposed}, @@ -1261,15 +1383,15 @@ static JNINativeMethod methods[] = { {"notifyFrameFetched", "(I[B)V", (void *)notifyFrameFetched} }; -bool JCamera::initJNI(JNIEnv *env) +bool AndroidCamera::initJNI(JNIEnv *env) { - jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtCamera"); + jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtCameraListener"); if (env->ExceptionCheck()) env->ExceptionClear(); if (clazz) { - g_qtCameraClass = static_cast<jclass>(env->NewGlobalRef(clazz)); - if (env->RegisterNatives(g_qtCameraClass, + g_qtCameraListenerClass = static_cast<jclass>(env->NewGlobalRef(clazz)); + if (env->RegisterNatives(g_qtCameraListenerClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) { return false; @@ -1281,4 +1403,4 @@ bool JCamera::initJNI(JNIEnv *env) QT_END_NAMESPACE -#include "jcamera.moc" +#include "androidcamera.moc" diff --git a/src/plugins/android/src/wrappers/jcamera.h b/src/plugins/android/src/wrappers/jni/androidcamera.h index 81c334eb4..2ea69b7e3 100644 --- a/src/plugins/android/src/wrappers/jcamera.h +++ b/src/plugins/android/src/wrappers/jni/androidcamera.h @@ -39,21 +39,31 @@ ** ****************************************************************************/ -#ifndef JCAMERA_H -#define JCAMERA_H +#ifndef ANDROIDCAMERA_H +#define ANDROIDCAMERA_H #include <qobject.h> #include <QtCore/private/qjni_p.h> #include <qsize.h> #include <qrect.h> +#include <QtMultimedia/qcamera.h> QT_BEGIN_NAMESPACE class QThread; -class JCameraWorker; +class AndroidCameraPrivate; +class AndroidSurfaceTexture; -class JCamera : public QObject +struct AndroidCameraInfo +{ + QByteArray name; + QString description; + QCamera::Position position; + int orientation; +}; + +class AndroidCamera : public QObject { Q_OBJECT Q_ENUMS(CameraFacing) @@ -74,9 +84,9 @@ public: YV12 = 842094169 }; - ~JCamera(); + ~AndroidCamera(); - static JCamera *open(int cameraId); + static AndroidCamera *open(int cameraId); int cameraId() const; @@ -96,7 +106,7 @@ public: QSize previewSize() const; void setPreviewSize(const QSize &size); - void setPreviewTexture(jobject surfaceTexture); + void setPreviewTexture(AndroidSurfaceTexture *surfaceTexture); bool isZoomSupported(); int getMaxZoom(); @@ -157,6 +167,9 @@ public: void fetchLastPreviewFrame(); QJNIObjectPrivate getCameraObject(); + static int getNumberOfCameras(); + static void getCameraInfo(int id, AndroidCameraInfo *info); + static bool initJNI(JNIEnv *env); Q_SIGNALS: @@ -175,11 +188,13 @@ Q_SIGNALS: void frameFetched(const QByteArray &frame); private: - JCamera(int cameraId, jobject cam, QThread *workerThread); + AndroidCamera(AndroidCameraPrivate *d, QThread *worker); - JCameraWorker *d; + Q_DECLARE_PRIVATE(AndroidCamera) + AndroidCameraPrivate *d_ptr; + QScopedPointer<QThread> m_worker; }; QT_END_NAMESPACE -#endif // JCAMERA_H +#endif // ANDROIDCAMERA_H diff --git a/src/plugins/android/src/wrappers/jmediametadataretriever.cpp b/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.cpp index 93b77ecb1..7dfc6a6e3 100644 --- a/src/plugins/android/src/wrappers/jmediametadataretriever.cpp +++ b/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.cpp @@ -39,23 +39,23 @@ ** ****************************************************************************/ -#include "jmediametadataretriever.h" +#include "androidmediametadataretriever.h" #include <QtCore/private/qjnihelpers_p.h> #include <QtCore/private/qjni_p.h> QT_BEGIN_NAMESPACE -JMediaMetadataRetriever::JMediaMetadataRetriever() +AndroidMediaMetadataRetriever::AndroidMediaMetadataRetriever() { m_metadataRetriever = QJNIObjectPrivate("android/media/MediaMetadataRetriever"); } -JMediaMetadataRetriever::~JMediaMetadataRetriever() +AndroidMediaMetadataRetriever::~AndroidMediaMetadataRetriever() { } -QString JMediaMetadataRetriever::extractMetadata(MetadataKey key) +QString AndroidMediaMetadataRetriever::extractMetadata(MetadataKey key) { QString value; @@ -68,7 +68,7 @@ QString JMediaMetadataRetriever::extractMetadata(MetadataKey key) return value; } -void JMediaMetadataRetriever::release() +void AndroidMediaMetadataRetriever::release() { if (!m_metadataRetriever.isValid()) return; @@ -76,7 +76,7 @@ void JMediaMetadataRetriever::release() m_metadataRetriever.callMethod<void>("release"); } -bool JMediaMetadataRetriever::setDataSource(const QUrl &url) +bool AndroidMediaMetadataRetriever::setDataSource(const QUrl &url) { if (!m_metadataRetriever.isValid()) return false; @@ -107,7 +107,7 @@ bool JMediaMetadataRetriever::setDataSource(const QUrl &url) return loaded; } -bool JMediaMetadataRetriever::setDataSource(const QString &path) +bool AndroidMediaMetadataRetriever::setDataSource(const QString &path) { if (!m_metadataRetriever.isValid()) return false; diff --git a/src/plugins/android/src/wrappers/jmediametadataretriever.h b/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.h index 7b0340c0d..f18cec11d 100644 --- a/src/plugins/android/src/wrappers/jmediametadataretriever.h +++ b/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.h @@ -39,15 +39,15 @@ ** ****************************************************************************/ -#ifndef JMEDIAMETADATARETRIEVER_H -#define JMEDIAMETADATARETRIEVER_H +#ifndef ANDROIDMEDIAMETADATARETRIEVER_H +#define ANDROIDMEDIAMETADATARETRIEVER_H #include <QtCore/private/qjni_p.h> #include <qurl.h> QT_BEGIN_NAMESPACE -class JMediaMetadataRetriever +class AndroidMediaMetadataRetriever { public: enum MetadataKey { @@ -76,8 +76,8 @@ public: Year = 8 }; - JMediaMetadataRetriever(); - ~JMediaMetadataRetriever(); + AndroidMediaMetadataRetriever(); + ~AndroidMediaMetadataRetriever(); QString extractMetadata(MetadataKey key); void release(); @@ -90,4 +90,4 @@ private: QT_END_NAMESPACE -#endif // JMEDIAMETADATARETRIEVER_H +#endif // ANDROIDMEDIAMETADATARETRIEVER_H diff --git a/src/plugins/android/src/wrappers/jmediaplayer.cpp b/src/plugins/android/src/wrappers/jni/androidmediaplayer.cpp index de86cd041..5aee7a857 100644 --- a/src/plugins/android/src/wrappers/jmediaplayer.cpp +++ b/src/plugins/android/src/wrappers/jni/androidmediaplayer.cpp @@ -39,20 +39,21 @@ ** ****************************************************************************/ -#include "jmediaplayer.h" +#include "androidmediaplayer.h" #include <QString> #include <QtCore/private/qjni_p.h> #include <QtCore/private/qjnihelpers_p.h> +#include "androidsurfacetexture.h" #include <QMap> static jclass mediaPlayerClass = Q_NULLPTR; -typedef QMap<jlong, JMediaPlayer *> MediaPlayerMap; +typedef QMap<jlong, AndroidMediaPlayer *> MediaPlayerMap; Q_GLOBAL_STATIC(MediaPlayerMap, mediaPlayers) QT_BEGIN_NAMESPACE -JMediaPlayer::JMediaPlayer() +AndroidMediaPlayer::AndroidMediaPlayer() : QObject() { @@ -64,104 +65,104 @@ JMediaPlayer::JMediaPlayer() (*mediaPlayers)[id] = this; } -JMediaPlayer::~JMediaPlayer() +AndroidMediaPlayer::~AndroidMediaPlayer() { mediaPlayers->remove(reinterpret_cast<jlong>(this)); } -void JMediaPlayer::release() +void AndroidMediaPlayer::release() { mMediaPlayer.callMethod<void>("release"); } -void JMediaPlayer::reset() +void AndroidMediaPlayer::reset() { mMediaPlayer.callMethod<void>("reset"); } -int JMediaPlayer::getCurrentPosition() +int AndroidMediaPlayer::getCurrentPosition() { return mMediaPlayer.callMethod<jint>("getCurrentPosition"); } -int JMediaPlayer::getDuration() +int AndroidMediaPlayer::getDuration() { return mMediaPlayer.callMethod<jint>("getDuration"); } -bool JMediaPlayer::isPlaying() +bool AndroidMediaPlayer::isPlaying() { return mMediaPlayer.callMethod<jboolean>("isPlaying"); } -int JMediaPlayer::volume() +int AndroidMediaPlayer::volume() { return mMediaPlayer.callMethod<jint>("getVolume"); } -bool JMediaPlayer::isMuted() +bool AndroidMediaPlayer::isMuted() { return mMediaPlayer.callMethod<jboolean>("isMuted"); } -jobject JMediaPlayer::display() +jobject AndroidMediaPlayer::display() { return mMediaPlayer.callObjectMethod("display", "()Landroid/view/SurfaceHolder;").object(); } -void JMediaPlayer::play() +void AndroidMediaPlayer::play() { mMediaPlayer.callMethod<void>("start"); } -void JMediaPlayer::pause() +void AndroidMediaPlayer::pause() { mMediaPlayer.callMethod<void>("pause"); } -void JMediaPlayer::stop() +void AndroidMediaPlayer::stop() { mMediaPlayer.callMethod<void>("stop"); } -void JMediaPlayer::seekTo(qint32 msec) +void AndroidMediaPlayer::seekTo(qint32 msec) { mMediaPlayer.callMethod<void>("seekTo", "(I)V", jint(msec)); } -void JMediaPlayer::setMuted(bool mute) +void AndroidMediaPlayer::setMuted(bool mute) { mMediaPlayer.callMethod<void>("mute", "(Z)V", jboolean(mute)); } -void JMediaPlayer::setDataSource(const QString &path) +void AndroidMediaPlayer::setDataSource(const QString &path) { QJNIObjectPrivate string = QJNIObjectPrivate::fromString(path); mMediaPlayer.callMethod<void>("setDataSource", "(Ljava/lang/String;)V", string.object()); } -void JMediaPlayer::prepareAsync() +void AndroidMediaPlayer::prepareAsync() { mMediaPlayer.callMethod<void>("prepareAsync"); } -void JMediaPlayer::setVolume(int volume) +void AndroidMediaPlayer::setVolume(int volume) { mMediaPlayer.callMethod<void>("setVolume", "(I)V", jint(volume)); } -void JMediaPlayer::setDisplay(jobject surfaceHolder) +void AndroidMediaPlayer::setDisplay(AndroidSurfaceTexture *surfaceTexture) { - mMediaPlayer.callMethod<void>("setDisplay", "(Landroid/view/SurfaceHolder;)V", surfaceHolder); + mMediaPlayer.callMethod<void>("setDisplay", + "(Landroid/view/SurfaceHolder;)V", + surfaceTexture ? surfaceTexture->surfaceHolder() : 0); } -QT_END_NAMESPACE - static void onErrorNative(JNIEnv *env, jobject thiz, jint what, jint extra, jlong id) { Q_UNUSED(env); Q_UNUSED(thiz); - JMediaPlayer *const mp = (*mediaPlayers)[id]; + AndroidMediaPlayer *const mp = (*mediaPlayers)[id]; if (!mp) return; @@ -172,7 +173,7 @@ static void onBufferingUpdateNative(JNIEnv *env, jobject thiz, jint percent, jlo { Q_UNUSED(env); Q_UNUSED(thiz); - JMediaPlayer *const mp = (*mediaPlayers)[id]; + AndroidMediaPlayer *const mp = (*mediaPlayers)[id]; if (!mp) return; @@ -183,7 +184,7 @@ static void onProgressUpdateNative(JNIEnv *env, jobject thiz, jint progress, jlo { Q_UNUSED(env); Q_UNUSED(thiz); - JMediaPlayer *const mp = (*mediaPlayers)[id]; + AndroidMediaPlayer *const mp = (*mediaPlayers)[id]; if (!mp) return; @@ -194,7 +195,7 @@ static void onDurationChangedNative(JNIEnv *env, jobject thiz, jint duration, jl { Q_UNUSED(env); Q_UNUSED(thiz); - JMediaPlayer *const mp = (*mediaPlayers)[id]; + AndroidMediaPlayer *const mp = (*mediaPlayers)[id]; if (!mp) return; @@ -205,7 +206,7 @@ static void onInfoNative(JNIEnv *env, jobject thiz, jint what, jint extra, jlong { Q_UNUSED(env); Q_UNUSED(thiz); - JMediaPlayer *const mp = (*mediaPlayers)[id]; + AndroidMediaPlayer *const mp = (*mediaPlayers)[id]; if (!mp) return; @@ -216,7 +217,7 @@ static void onStateChangedNative(JNIEnv *env, jobject thiz, jint state, jlong id { Q_UNUSED(env); Q_UNUSED(thiz); - JMediaPlayer *const mp = (*mediaPlayers)[id]; + AndroidMediaPlayer *const mp = (*mediaPlayers)[id]; if (!mp) return; @@ -231,16 +232,14 @@ static void onVideoSizeChangedNative(JNIEnv *env, { Q_UNUSED(env); Q_UNUSED(thiz); - JMediaPlayer *const mp = (*mediaPlayers)[id]; + AndroidMediaPlayer *const mp = (*mediaPlayers)[id]; if (!mp) return; Q_EMIT mp->videoSizeChanged(width, height); } -QT_BEGIN_NAMESPACE - -bool JMediaPlayer::initJNI(JNIEnv *env) +bool AndroidMediaPlayer::initJNI(JNIEnv *env) { jclass jClass = env->FindClass("org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer"); diff --git a/src/plugins/android/src/wrappers/jmediaplayer.h b/src/plugins/android/src/wrappers/jni/androidmediaplayer.h index cd469e677..976d886f8 100644 --- a/src/plugins/android/src/wrappers/jmediaplayer.h +++ b/src/plugins/android/src/wrappers/jni/androidmediaplayer.h @@ -39,20 +39,22 @@ ** ****************************************************************************/ -#ifndef QANDROIDMEDIAPLAYER_H -#define QANDROIDMEDIAPLAYER_H +#ifndef ANDROIDMEDIAPLAYER_H +#define ANDROIDMEDIAPLAYER_H #include <QObject> #include <QtCore/private/qjni_p.h> QT_BEGIN_NAMESPACE -class JMediaPlayer : public QObject +class AndroidSurfaceTexture; + +class AndroidMediaPlayer : public QObject { Q_OBJECT public: - JMediaPlayer(); - ~JMediaPlayer(); + AndroidMediaPlayer(); + ~AndroidMediaPlayer(); enum MediaError { @@ -113,7 +115,7 @@ public: void setDataSource(const QString &path); void prepareAsync(); void setVolume(int volume); - void setDisplay(jobject surfaceHolder); + void setDisplay(AndroidSurfaceTexture *surfaceTexture); static bool initJNI(JNIEnv *env); @@ -132,4 +134,4 @@ private: QT_END_NAMESPACE -#endif // QANDROIDMEDIAPLAYER_H +#endif // ANDROIDMEDIAPLAYER_H diff --git a/src/plugins/android/src/wrappers/jmediarecorder.cpp b/src/plugins/android/src/wrappers/jni/androidmediarecorder.cpp index 0b1498d99..71f88213f 100644 --- a/src/plugins/android/src/wrappers/jmediarecorder.cpp +++ b/src/plugins/android/src/wrappers/jni/androidmediarecorder.cpp @@ -39,33 +39,107 @@ ** ****************************************************************************/ -#include "jmediarecorder.h" +#include "androidmediarecorder.h" -#include "jcamera.h" +#include "androidcamera.h" #include <QtCore/private/qjni_p.h> #include <qmap.h> QT_BEGIN_NAMESPACE +typedef QMap<QString, QJNIObjectPrivate> CamcorderProfiles; +Q_GLOBAL_STATIC(CamcorderProfiles, g_camcorderProfiles) + +static QString profileKey() +{ + return QStringLiteral("%1-%2"); +} + +bool AndroidCamcorderProfile::hasProfile(jint cameraId, Quality quality) +{ + if (g_camcorderProfiles->contains(profileKey().arg(cameraId).arg(quality))) + return true; + + return QJNIObjectPrivate::callStaticMethod<jboolean>("android/media/CamcorderProfile", + "hasProfile", + "(II)Z", + cameraId, + quality); +} + +AndroidCamcorderProfile AndroidCamcorderProfile::get(jint cameraId, Quality quality) +{ + const QString key = profileKey().arg(cameraId).arg(quality); + QMap<QString, QJNIObjectPrivate>::const_iterator it = g_camcorderProfiles->constFind(key); + + if (it != g_camcorderProfiles->constEnd()) + return AndroidCamcorderProfile(*it); + + QJNIObjectPrivate camProfile = QJNIObjectPrivate::callStaticObjectMethod("android/media/CamcorderProfile", + "get", + "(II)Landroid/media/CamcorderProfile;", + cameraId, + quality); + + return AndroidCamcorderProfile((*g_camcorderProfiles)[key] = camProfile); +} + +int AndroidCamcorderProfile::getValue(AndroidCamcorderProfile::Field field) const +{ + switch (field) { + case audioBitRate: + return m_camcorderProfile.getField<jint>("audioBitRate"); + case audioChannels: + return m_camcorderProfile.getField<jint>("audioChannels"); + case audioCodec: + return m_camcorderProfile.getField<jint>("audioCodec"); + case audioSampleRate: + return m_camcorderProfile.getField<jint>("audioSampleRate"); + case duration: + return m_camcorderProfile.getField<jint>("duration"); + case fileFormat: + return m_camcorderProfile.getField<jint>("fileFormat"); + case quality: + return m_camcorderProfile.getField<jint>("quality"); + case videoBitRate: + return m_camcorderProfile.getField<jint>("videoBitRate"); + case videoCodec: + return m_camcorderProfile.getField<jint>("videoCodec"); + case videoFrameHeight: + return m_camcorderProfile.getField<jint>("videoFrameHeight"); + case videoFrameRate: + return m_camcorderProfile.getField<jint>("videoFrameRate"); + case videoFrameWidth: + return m_camcorderProfile.getField<jint>("videoFrameWidth"); + } + + return 0; +} + +AndroidCamcorderProfile::AndroidCamcorderProfile(const QJNIObjectPrivate &camcorderProfile) +{ + m_camcorderProfile = camcorderProfile; +} + static jclass g_qtMediaRecorderListenerClass = 0; -typedef QMap<jlong, JMediaRecorder*> MediaRecorderMap; +typedef QMap<jlong, AndroidMediaRecorder*> MediaRecorderMap; Q_GLOBAL_STATIC(MediaRecorderMap, mediaRecorders) static void notifyError(JNIEnv* , jobject, jlong id, jint what, jint extra) { - JMediaRecorder *obj = mediaRecorders->value(id, 0); + AndroidMediaRecorder *obj = mediaRecorders->value(id, 0); if (obj) emit obj->error(what, extra); } static void notifyInfo(JNIEnv* , jobject, jlong id, jint what, jint extra) { - JMediaRecorder *obj = mediaRecorders->value(id, 0); + AndroidMediaRecorder *obj = mediaRecorders->value(id, 0); if (obj) emit obj->info(what, extra); } -JMediaRecorder::JMediaRecorder() +AndroidMediaRecorder::AndroidMediaRecorder() : QObject() , m_id(reinterpret_cast<jlong>(this)) { @@ -82,17 +156,17 @@ JMediaRecorder::JMediaRecorder() } } -JMediaRecorder::~JMediaRecorder() +AndroidMediaRecorder::~AndroidMediaRecorder() { mediaRecorders->remove(m_id); } -void JMediaRecorder::release() +void AndroidMediaRecorder::release() { m_mediaRecorder.callMethod<void>("release"); } -bool JMediaRecorder::prepare() +bool AndroidMediaRecorder::prepare() { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("prepare"); @@ -106,12 +180,12 @@ bool JMediaRecorder::prepare() return true; } -void JMediaRecorder::reset() +void AndroidMediaRecorder::reset() { m_mediaRecorder.callMethod<void>("reset"); } -bool JMediaRecorder::start() +bool AndroidMediaRecorder::start() { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("start"); @@ -125,7 +199,7 @@ bool JMediaRecorder::start() return true; } -void JMediaRecorder::stop() +void AndroidMediaRecorder::stop() { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("stop"); @@ -137,12 +211,12 @@ void JMediaRecorder::stop() } } -void JMediaRecorder::setAudioChannels(int numChannels) +void AndroidMediaRecorder::setAudioChannels(int numChannels) { m_mediaRecorder.callMethod<void>("setAudioChannels", "(I)V", numChannels); } -void JMediaRecorder::setAudioEncoder(AudioEncoder encoder) +void AndroidMediaRecorder::setAudioEncoder(AudioEncoder encoder) { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("setAudioEncoder", "(I)V", int(encoder)); @@ -154,17 +228,17 @@ void JMediaRecorder::setAudioEncoder(AudioEncoder encoder) } } -void JMediaRecorder::setAudioEncodingBitRate(int bitRate) +void AndroidMediaRecorder::setAudioEncodingBitRate(int bitRate) { m_mediaRecorder.callMethod<void>("setAudioEncodingBitRate", "(I)V", bitRate); } -void JMediaRecorder::setAudioSamplingRate(int samplingRate) +void AndroidMediaRecorder::setAudioSamplingRate(int samplingRate) { m_mediaRecorder.callMethod<void>("setAudioSamplingRate", "(I)V", samplingRate); } -void JMediaRecorder::setAudioSource(AudioSource source) +void AndroidMediaRecorder::setAudioSource(AudioSource source) { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("setAudioSource", "(I)V", int(source)); @@ -176,13 +250,13 @@ void JMediaRecorder::setAudioSource(AudioSource source) } } -void JMediaRecorder::setCamera(JCamera *camera) +void AndroidMediaRecorder::setCamera(AndroidCamera *camera) { QJNIObjectPrivate cam = camera->getCameraObject(); m_mediaRecorder.callMethod<void>("setCamera", "(Landroid/hardware/Camera;)V", cam.object()); } -void JMediaRecorder::setVideoEncoder(VideoEncoder encoder) +void AndroidMediaRecorder::setVideoEncoder(VideoEncoder encoder) { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("setVideoEncoder", "(I)V", int(encoder)); @@ -194,12 +268,12 @@ void JMediaRecorder::setVideoEncoder(VideoEncoder encoder) } } -void JMediaRecorder::setVideoEncodingBitRate(int bitRate) +void AndroidMediaRecorder::setVideoEncodingBitRate(int bitRate) { m_mediaRecorder.callMethod<void>("setVideoEncodingBitRate", "(I)V", bitRate); } -void JMediaRecorder::setVideoFrameRate(int rate) +void AndroidMediaRecorder::setVideoFrameRate(int rate) { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("setVideoFrameRate", "(I)V", rate); @@ -211,7 +285,7 @@ void JMediaRecorder::setVideoFrameRate(int rate) } } -void JMediaRecorder::setVideoSize(const QSize &size) +void AndroidMediaRecorder::setVideoSize(const QSize &size) { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("setVideoSize", "(II)V", size.width(), size.height()); @@ -223,7 +297,7 @@ void JMediaRecorder::setVideoSize(const QSize &size) } } -void JMediaRecorder::setVideoSource(VideoSource source) +void AndroidMediaRecorder::setVideoSource(VideoSource source) { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("setVideoSource", "(I)V", int(source)); @@ -235,7 +309,7 @@ void JMediaRecorder::setVideoSource(VideoSource source) } } -void JMediaRecorder::setOrientationHint(int degrees) +void AndroidMediaRecorder::setOrientationHint(int degrees) { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("setOrientationHint", "(I)V", degrees); @@ -247,7 +321,7 @@ void JMediaRecorder::setOrientationHint(int degrees) } } -void JMediaRecorder::setOutputFormat(OutputFormat format) +void AndroidMediaRecorder::setOutputFormat(OutputFormat format) { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("setOutputFormat", "(I)V", int(format)); @@ -259,7 +333,7 @@ void JMediaRecorder::setOutputFormat(OutputFormat format) } } -void JMediaRecorder::setOutputFile(const QString &path) +void AndroidMediaRecorder::setOutputFile(const QString &path) { QJNIEnvironmentPrivate env; m_mediaRecorder.callMethod<void>("setOutputFile", @@ -278,7 +352,7 @@ static JNINativeMethod methods[] = { {"notifyInfo", "(JII)V", (void *)notifyInfo} }; -bool JMediaRecorder::initJNI(JNIEnv *env) +bool AndroidMediaRecorder::initJNI(JNIEnv *env) { jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtMediaRecorderListener"); if (env->ExceptionCheck()) diff --git a/src/plugins/android/src/wrappers/jmediarecorder.h b/src/plugins/android/src/wrappers/jni/androidmediarecorder.h index 3a83e7e16..686217dc8 100644 --- a/src/plugins/android/src/wrappers/jmediarecorder.h +++ b/src/plugins/android/src/wrappers/jni/androidmediarecorder.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef JMEDIARECORDER_H -#define JMEDIARECORDER_H +#ifndef ANDROIDMEDIARECORDER_H +#define ANDROIDMEDIARECORDER_H #include <qobject.h> #include <QtCore/private/qjni_p.h> @@ -48,9 +48,47 @@ QT_BEGIN_NAMESPACE -class JCamera; +class AndroidCamera; -class JMediaRecorder : public QObject +class AndroidCamcorderProfile +{ +public: + enum Quality { // Needs to match CamcorderProfile + QUALITY_LOW, + QUALITY_HIGH, + QUALITY_QCIF, + QUALITY_CIF, + QUALITY_480P, + QUALITY_720P, + QUALITY_1080P, + QUALITY_QVGA + }; + + enum Field { + audioBitRate, + audioChannels, + audioCodec, + audioSampleRate, + duration, + fileFormat, + quality, + videoBitRate, + videoCodec, + videoFrameHeight, + videoFrameRate, + videoFrameWidth + }; + + static bool hasProfile(jint cameraId, Quality quality); + static AndroidCamcorderProfile get(jint cameraId, Quality quality); + int getValue(Field field) const; + +private: + AndroidCamcorderProfile(const QJNIObjectPrivate &camcorderProfile); + QJNIObjectPrivate m_camcorderProfile; +}; + +class AndroidMediaRecorder : public QObject { Q_OBJECT public: @@ -91,8 +129,8 @@ public: AMR_WB_Format = 4 }; - JMediaRecorder(); - ~JMediaRecorder(); + AndroidMediaRecorder(); + ~AndroidMediaRecorder(); void release(); bool prepare(); @@ -107,7 +145,7 @@ public: void setAudioSamplingRate(int samplingRate); void setAudioSource(AudioSource source); - void setCamera(JCamera *camera); + void setCamera(AndroidCamera *camera); void setVideoEncoder(VideoEncoder encoder); void setVideoEncodingBitRate(int bitRate); void setVideoFrameRate(int rate); @@ -132,4 +170,4 @@ private: QT_END_NAMESPACE -#endif // JMEDIARECORDER_H +#endif // ANDROIDMEDIARECORDER_H diff --git a/src/plugins/android/src/wrappers/jmultimediautils.cpp b/src/plugins/android/src/wrappers/jni/androidmultimediautils.cpp index d1b0830c7..5c2f19a06 100644 --- a/src/plugins/android/src/wrappers/jmultimediautils.cpp +++ b/src/plugins/android/src/wrappers/jni/androidmultimediautils.cpp @@ -39,14 +39,14 @@ ** ****************************************************************************/ -#include "jmultimediautils.h" +#include "androidmultimediautils.h" #include <QtCore/private/qjni_p.h> QT_BEGIN_NAMESPACE -void JMultimediaUtils::enableOrientationListener(bool enable) +void AndroidMultimediaUtils::enableOrientationListener(bool enable) { QJNIObjectPrivate::callStaticMethod<void>("org/qtproject/qt5/android/multimedia/QtMultimediaUtils", "enableOrientationListener", @@ -54,13 +54,13 @@ void JMultimediaUtils::enableOrientationListener(bool enable) enable); } -int JMultimediaUtils::getDeviceOrientation() +int AndroidMultimediaUtils::getDeviceOrientation() { return QJNIObjectPrivate::callStaticMethod<jint>("org/qtproject/qt5/android/multimedia/QtMultimediaUtils", "getDeviceOrientation"); } -QString JMultimediaUtils::getDefaultMediaDirectory(MediaType type) +QString AndroidMultimediaUtils::getDefaultMediaDirectory(MediaType type) { QJNIObjectPrivate path = QJNIObjectPrivate::callStaticObjectMethod("org/qtproject/qt5/android/multimedia/QtMultimediaUtils", "getDefaultMediaDirectory", @@ -69,7 +69,7 @@ QString JMultimediaUtils::getDefaultMediaDirectory(MediaType type) return path.toString(); } -void JMultimediaUtils::registerMediaFile(const QString &file) +void AndroidMultimediaUtils::registerMediaFile(const QString &file) { QJNIObjectPrivate::callStaticMethod<void>("org/qtproject/qt5/android/multimedia/QtMultimediaUtils", "registerMediaFile", diff --git a/src/plugins/android/src/wrappers/jmultimediautils.h b/src/plugins/android/src/wrappers/jni/androidmultimediautils.h index b80ef4236..4617b08f8 100644 --- a/src/plugins/android/src/wrappers/jmultimediautils.h +++ b/src/plugins/android/src/wrappers/jni/androidmultimediautils.h @@ -39,15 +39,15 @@ ** ****************************************************************************/ -#ifndef JMULTIMEDIAUTILS_H -#define JMULTIMEDIAUTILS_H +#ifndef ANDROIDMULTIMEDIAUTILS_H +#define ANDROIDMULTIMEDIAUTILS_H #include <qobject.h> #include <QtCore/private/qjni_p.h> QT_BEGIN_NAMESPACE -class JMultimediaUtils +class AndroidMultimediaUtils { public: enum MediaType { @@ -65,4 +65,4 @@ public: QT_END_NAMESPACE -#endif // JMULTIMEDIAUTILS_H +#endif // ANDROIDMULTIMEDIAUTILS_H diff --git a/src/plugins/android/src/wrappers/jsurfacetexture.cpp b/src/plugins/android/src/wrappers/jni/androidsurfacetexture.cpp index 2b16ebd66..06dcd74ca 100644 --- a/src/plugins/android/src/wrappers/jsurfacetexture.cpp +++ b/src/plugins/android/src/wrappers/jni/androidsurfacetexture.cpp @@ -39,24 +39,24 @@ ** ****************************************************************************/ -#include "jsurfacetexture.h" +#include "androidsurfacetexture.h" #include <QtCore/private/qjni_p.h> #include <QtCore/private/qjnihelpers_p.h> QT_BEGIN_NAMESPACE static jclass g_qtSurfaceTextureListenerClass = 0; -static QMap<int, JSurfaceTexture*> g_objectMap; +static QMap<int, AndroidSurfaceTexture*> g_objectMap; // native method for QtSurfaceTexture.java static void notifyFrameAvailable(JNIEnv* , jobject, int id) { - JSurfaceTexture *obj = g_objectMap.value(id, 0); + AndroidSurfaceTexture *obj = g_objectMap.value(id, 0); if (obj) Q_EMIT obj->frameAvailable(); } -JSurfaceTexture::JSurfaceTexture(unsigned int texName) +AndroidSurfaceTexture::AndroidSurfaceTexture(unsigned int texName) : QObject() , m_texID(int(texName)) { @@ -84,15 +84,18 @@ JSurfaceTexture::JSurfaceTexture(unsigned int texName) listener.object()); } -JSurfaceTexture::~JSurfaceTexture() +AndroidSurfaceTexture::~AndroidSurfaceTexture() { + if (QtAndroidPrivate::androidSdkVersion() > 13 && m_surfaceView.isValid()) + m_surfaceView.callMethod<void>("release"); + if (m_surfaceTexture.isValid()) { release(); g_objectMap.remove(m_texID); } } -QMatrix4x4 JSurfaceTexture::getTransformMatrix() +QMatrix4x4 AndroidSurfaceTexture::getTransformMatrix() { QMatrix4x4 matrix; if (!m_surfaceTexture.isValid()) @@ -108,7 +111,7 @@ QMatrix4x4 JSurfaceTexture::getTransformMatrix() return matrix; } -void JSurfaceTexture::release() +void AndroidSurfaceTexture::release() { if (QtAndroidPrivate::androidSdkVersion() < 14) return; @@ -116,7 +119,7 @@ void JSurfaceTexture::release() m_surfaceTexture.callMethod<void>("release"); } -void JSurfaceTexture::updateTexImage() +void AndroidSurfaceTexture::updateTexImage() { if (!m_surfaceTexture.isValid()) return; @@ -124,16 +127,36 @@ void JSurfaceTexture::updateTexImage() m_surfaceTexture.callMethod<void>("updateTexImage"); } -jobject JSurfaceTexture::object() +jobject AndroidSurfaceTexture::surfaceTexture() { return m_surfaceTexture.object(); } +jobject AndroidSurfaceTexture::surfaceView() +{ + return m_surfaceView.object(); +} + +jobject AndroidSurfaceTexture::surfaceHolder() +{ + if (!m_surfaceHolder.isValid()) { + m_surfaceView = QJNIObjectPrivate("android/view/Surface", + "(Landroid/graphics/SurfaceTexture;)V", + m_surfaceTexture.object()); + + m_surfaceHolder = QJNIObjectPrivate("org/qtproject/qt5/android/multimedia/QtSurfaceTextureHolder", + "(Landroid/view/Surface;)V", + m_surfaceView.object()); + } + + return m_surfaceHolder.object(); +} + static JNINativeMethod methods[] = { {"notifyFrameAvailable", "(I)V", (void *)notifyFrameAvailable} }; -bool JSurfaceTexture::initJNI(JNIEnv *env) +bool AndroidSurfaceTexture::initJNI(JNIEnv *env) { // SurfaceTexture is available since API 11. if (QtAndroidPrivate::androidSdkVersion() < 11) diff --git a/src/plugins/android/src/wrappers/jsurfacetexture.h b/src/plugins/android/src/wrappers/jni/androidsurfacetexture.h index d53290a71..ee49244cd 100644 --- a/src/plugins/android/src/wrappers/jsurfacetexture.h +++ b/src/plugins/android/src/wrappers/jni/androidsurfacetexture.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef JSURFACETEXTURE_H -#define JSURFACETEXTURE_H +#ifndef ANDROIDSURFACETEXTURE_H +#define ANDROIDSURFACETEXTURE_H #include <qobject.h> #include <QtCore/private/qjni_p.h> @@ -49,15 +49,18 @@ QT_BEGIN_NAMESPACE -class JSurfaceTexture : public QObject +class AndroidSurfaceTexture : public QObject { Q_OBJECT public: - explicit JSurfaceTexture(unsigned int texName); - ~JSurfaceTexture(); + explicit AndroidSurfaceTexture(unsigned int texName); + ~AndroidSurfaceTexture(); int textureID() const { return m_texID; } - jobject object(); + jobject surfaceTexture(); + jobject surfaceView(); + jobject surfaceHolder(); + inline bool isValid() const { return m_surfaceTexture.isValid(); } QMatrix4x4 getTransformMatrix(); void release(); // API level 14 @@ -71,8 +74,10 @@ Q_SIGNALS: private: int m_texID; QJNIObjectPrivate m_surfaceTexture; + QJNIObjectPrivate m_surfaceView; + QJNIObjectPrivate m_surfaceHolder; }; QT_END_NAMESPACE -#endif // JSURFACETEXTURE_H +#endif // ANDROIDSURFACETEXTURE_H diff --git a/src/plugins/android/src/wrappers/jni/jni.pri b/src/plugins/android/src/wrappers/jni/jni.pri new file mode 100644 index 000000000..ba2ad0801 --- /dev/null +++ b/src/plugins/android/src/wrappers/jni/jni.pri @@ -0,0 +1,19 @@ +QT += platformsupport-private + +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/androidmediaplayer.h \ + $$PWD/androidsurfacetexture.h \ + $$PWD/androidmediametadataretriever.h \ + $$PWD/androidcamera.h \ + $$PWD/androidmultimediautils.h \ + $$PWD/androidmediarecorder.h + +SOURCES += \ + $$PWD/androidmediaplayer.cpp \ + $$PWD/androidsurfacetexture.cpp \ + $$PWD/androidmediametadataretriever.cpp \ + $$PWD/androidcamera.cpp \ + $$PWD/androidmultimediautils.cpp \ + $$PWD/androidmediarecorder.cpp diff --git a/src/plugins/android/src/wrappers/wrappers.pri b/src/plugins/android/src/wrappers/wrappers.pri deleted file mode 100644 index 126cfd0c1..000000000 --- a/src/plugins/android/src/wrappers/wrappers.pri +++ /dev/null @@ -1,19 +0,0 @@ -QT += platformsupport-private - -INCLUDEPATH += $$PWD - -HEADERS += \ - $$PWD/jmediaplayer.h \ - $$PWD/jsurfacetexture.h \ - $$PWD/jmediametadataretriever.h \ - $$PWD/jcamera.h \ - $$PWD/jmultimediautils.h \ - $$PWD/jmediarecorder.h - -SOURCES += \ - $$PWD/jmediaplayer.cpp \ - $$PWD/jsurfacetexture.cpp \ - $$PWD/jmediametadataretriever.cpp \ - $$PWD/jcamera.cpp \ - $$PWD/jmultimediautils.cpp \ - $$PWD/jmediarecorder.cpp diff --git a/src/plugins/directshow/player/directshowiosource.cpp b/src/plugins/directshow/player/directshowiosource.cpp index acce1de28..c6cb21824 100644 --- a/src/plugins/directshow/player/directshowiosource.cpp +++ b/src/plugins/directshow/player/directshowiosource.cpp @@ -622,17 +622,10 @@ DirectShowRcSource::DirectShowRcSource(DirectShowEventLoop *loop) bool DirectShowRcSource::open(const QUrl &url) { m_file.moveToThread(QCoreApplication::instance()->thread()); - m_file.setFileName(QLatin1Char(':') + url.path()); - qDebug("qrc file %s", qPrintable(m_file.fileName())); - if (m_file.open(QIODevice::ReadOnly)) { - qDebug("Size %d", int(m_file.size())); - qDebug("Sequential %d", int(m_file.isSequential())); - setDevice(&m_file); - return true; } else { return false; diff --git a/src/plugins/directshow/player/directshowmetadatacontrol.cpp b/src/plugins/directshow/player/directshowmetadatacontrol.cpp index 51d9574ba..96c9fab8b 100644 --- a/src/plugins/directshow/player/directshowmetadatacontrol.cpp +++ b/src/plugins/directshow/player/directshowmetadatacontrol.cpp @@ -104,75 +104,85 @@ static q_SHCreateItemFromParsingName sHCreateItemFromParsingName = 0; #endif #ifndef QT_NO_WMSDK + namespace { - struct QWMMetaDataKeyLookup + struct QWMMetaDataKey { - QString key; - const wchar_t *token; + QString qtName; + const wchar_t *wmName; + + QWMMetaDataKey(const QString &qtn, const wchar_t *wmn) : qtName(qtn), wmName(wmn) { } }; } -static const QWMMetaDataKeyLookup qt_wmMetaDataKeys[] = +typedef QList<QWMMetaDataKey> QWMMetaDataKeys; +Q_GLOBAL_STATIC(QWMMetaDataKeys, metadataKeys) + +static const QWMMetaDataKeys *qt_wmMetaDataKeys() { - { QMediaMetaData::Title, L"Title" }, - { QMediaMetaData::SubTitle, L"WM/SubTitle" }, - { QMediaMetaData::Author, L"Author" }, - { QMediaMetaData::Comment, L"Comment" }, - { QMediaMetaData::Description, L"Description" }, - { QMediaMetaData::Category, L"WM/Category" }, - { QMediaMetaData::Genre, L"WM/Genre" }, - //{ QMediaMetaData::Date, 0 }, - { QMediaMetaData::Year, L"WM/Year" }, - { QMediaMetaData::UserRating, L"Rating" }, - //{ QMediaMetaData::MetaDatawords, 0 }, - { QMediaMetaData::Language, L"WM/Language" }, - { QMediaMetaData::Publisher, L"WM/Publisher" }, - { QMediaMetaData::Copyright, L"Copyright" }, - { QMediaMetaData::ParentalRating, L"WM/ParentalRating" }, - //{ QMediaMetaData::RatingOrganisation, L"RatingOrganisation" }, - - // Media - { QMediaMetaData::Size, L"FileSize" }, - { QMediaMetaData::MediaType, L"MediaType" }, - { QMediaMetaData::Duration, L"Duration" }, - - // Audio - { QMediaMetaData::AudioBitRate, L"AudioBitRate" }, - { QMediaMetaData::AudioCodec, L"AudioCodec" }, - { QMediaMetaData::ChannelCount, L"ChannelCount" }, - { QMediaMetaData::SampleRate, L"Frequency" }, - - // Music - { QMediaMetaData::AlbumTitle, L"WM/AlbumTitle" }, - { QMediaMetaData::AlbumArtist, L"WM/AlbumArtist" }, - { QMediaMetaData::ContributingArtist, L"Author" }, - { QMediaMetaData::Composer, L"WM/Composer" }, - { QMediaMetaData::Conductor, L"WM/Conductor" }, - { QMediaMetaData::Lyrics, L"WM/Lyrics" }, - { QMediaMetaData::Mood, L"WM/Mood" }, - { QMediaMetaData::TrackNumber, L"WM/TrackNumber" }, - //{ QMediaMetaData::TrackCount, 0 }, - //{ QMediaMetaData::CoverArtUriSmall, 0 }, - //{ QMediaMetaData::CoverArtUriLarge, 0 }, - - // Image/Video - { QMediaMetaData::Resolution, L"WM/VideoHeight" }, - { QMediaMetaData::PixelAspectRatio, L"AspectRatioX" }, - - // Video - { QMediaMetaData::VideoFrameRate, L"WM/VideoFrameRate" }, - { QMediaMetaData::VideoBitRate, L"VideoBitRate" }, - { QMediaMetaData::VideoCodec, L"VideoCodec" }, - - //{ QMediaMetaData::PosterUri, 0 }, - - // Movie - { QMediaMetaData::ChapterNumber, L"ChapterNumber" }, - { QMediaMetaData::Director, L"WM/Director" }, - { QMediaMetaData::LeadPerformer, L"LeadPerformer" }, - { QMediaMetaData::Writer, L"WM/Writer" }, -}; + if (metadataKeys->isEmpty()) { + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Title, L"Title")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::SubTitle, L"WM/SubTitle")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Author, L"Author")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Comment, L"Comment")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Description, L"Description")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Category, L"WM/Category")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Genre, L"WM/Genre")); + //metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Date, 0)); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Year, L"WM/Year")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::UserRating, L"Rating")); + //metadataKeys->append(QWMMetaDataKey(QMediaMetaData::MetaDatawords, 0)); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Language, L"WM/Language")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Publisher, L"WM/Publisher")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Copyright, L"Copyright")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::ParentalRating, L"WM/ParentalRating")); + //metadataKeys->append(QWMMetaDataKey(QMediaMetaData::RatingOrganisation, L"RatingOrganisation")); + + // Media + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Size, L"FileSize")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::MediaType, L"MediaType")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Duration, L"Duration")); + + // Audio + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::AudioBitRate, L"AudioBitRate")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::AudioCodec, L"AudioCodec")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::ChannelCount, L"ChannelCount")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::SampleRate, L"Frequency")); + + // Music + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::AlbumTitle, L"WM/AlbumTitle")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::AlbumArtist, L"WM/AlbumArtist")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::ContributingArtist, L"Author")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Composer, L"WM/Composer")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Conductor, L"WM/Conductor")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Lyrics, L"WM/Lyrics")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Mood, L"WM/Mood")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::TrackNumber, L"WM/TrackNumber")); + //metadataKeys->append(QWMMetaDataKey(QMediaMetaData::TrackCount, 0)); + //metadataKeys->append(QWMMetaDataKey(QMediaMetaData::CoverArtUriSmall, 0)); + //metadataKeys->append(QWMMetaDataKey(QMediaMetaData::CoverArtUriLarge, 0)); + + // Image/Video + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Resolution, L"WM/VideoHeight")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::PixelAspectRatio, L"AspectRatioX")); + + // Video + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::VideoFrameRate, L"WM/VideoFrameRate")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::VideoBitRate, L"VideoBitRate")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::VideoCodec, L"VideoCodec")); + + //metadataKeys->append(QWMMetaDataKey(QMediaMetaData::PosterUri, 0)); + + // Movie + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::ChapterNumber, L"ChapterNumber")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Director, L"WM/Director")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::LeadPerformer, L"LeadPerformer")); + metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Writer, L"WM/Writer")); + } + + return metadataKeys; +} static QVariant getValue(IWMHeaderInfo *header, const wchar_t *key) { @@ -491,32 +501,29 @@ void DirectShowMetaDataControl::updateGraph(IFilterGraph2 *graph, IBaseFilter *s IWMHeaderInfo *info = com_cast<IWMHeaderInfo>(source, IID_IWMHeaderInfo); if (info) { - static const int count = sizeof(qt_wmMetaDataKeys) / sizeof(QWMMetaDataKeyLookup); - for (int i = 0; i < count; ++i) { - QVariant var = getValue(info, qt_wmMetaDataKeys[i].token); + Q_FOREACH (const QWMMetaDataKey &key, *qt_wmMetaDataKeys()) { + QVariant var = getValue(info, key.wmName); if (var.isValid()) { - QString key = qt_wmMetaDataKeys[i].key; - - if (key == QMediaMetaData::Duration) { + if (key.qtName == QMediaMetaData::Duration) { // duration is provided in 100-nanosecond units, convert to milliseconds var = (var.toLongLong() + 10000) / 10000; - } else if (key == QMediaMetaData::Resolution) { + } else if (key.qtName == QMediaMetaData::Resolution) { QSize res; res.setHeight(var.toUInt()); res.setWidth(getValue(info, L"WM/VideoWidth").toUInt()); var = res; - } else if (key == QMediaMetaData::VideoFrameRate) { + } else if (key.qtName == QMediaMetaData::VideoFrameRate) { var = var.toReal() / 1000.f; - } else if (key == QMediaMetaData::PixelAspectRatio) { + } else if (key.qtName == QMediaMetaData::PixelAspectRatio) { QSize aspectRatio; aspectRatio.setWidth(var.toUInt()); aspectRatio.setHeight(getValue(info, L"AspectRatioY").toUInt()); var = aspectRatio; - } else if (key == QMediaMetaData::UserRating) { + } else if (key.qtName == QMediaMetaData::UserRating) { var = (var.toUInt() - 1) / qreal(98) * 100; } - m_metadata.insert(key, var); + m_metadata.insert(key.qtName, var); } } diff --git a/src/plugins/gstreamer/camerabin/camerabinmetadata.cpp b/src/plugins/gstreamer/camerabin/camerabinmetadata.cpp index c2b7c33c3..170d25a07 100644 --- a/src/plugins/gstreamer/camerabin/camerabinmetadata.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinmetadata.cpp @@ -50,13 +50,6 @@ QT_BEGIN_NAMESPACE -struct QGstreamerMetaDataKeyLookup -{ - QString key; - const char *token; - QVariant::Type type; -}; - static QVariant fromGStreamerOrientation(const QVariant &value) { // Note gstreamer tokens either describe the counter clockwise rotation of the @@ -87,87 +80,109 @@ static QVariant toGStreamerOrientation(const QVariant &value) } } -static const QGstreamerMetaDataKeyLookup qt_gstreamerMetaDataKeys[] = +namespace { + struct QGStreamerMetaDataKey + { + QString qtName; + const char *gstName; + QVariant::Type type; + + QGStreamerMetaDataKey(const QString &qtn, const char *gstn, QVariant::Type t) + : qtName(qtn) + , gstName(gstn) + , type(t) + { } + }; +} + +typedef QList<QGStreamerMetaDataKey> QGStreamerMetaDataKeys; +Q_GLOBAL_STATIC(QGStreamerMetaDataKeys, metadataKeys) + +static const QGStreamerMetaDataKeys *qt_gstreamerMetaDataKeys() { - { QMediaMetaData::Title, GST_TAG_TITLE, QVariant::String }, - //{ QMediaMetaData::SubTitle, 0, QVariant::String }, - //{ QMediaMetaData::Author, 0, QVariant::String }, - { QMediaMetaData::Comment, GST_TAG_COMMENT, QVariant::String }, - { QMediaMetaData::Date, GST_TAG_DATE_TIME, QVariant::DateTime }, - { QMediaMetaData::Description, GST_TAG_DESCRIPTION, QVariant::String }, - //{ QMediaMetaData::Category, 0, QVariant::String }, - { QMediaMetaData::Genre, GST_TAG_GENRE, QVariant::String }, - //{ QMediaMetaData::Year, 0, QVariant::Int }, - //{ QMediaMetaData::UserRating, , QVariant::Int }, - - { QMediaMetaData::Language, GST_TAG_LANGUAGE_CODE, QVariant::String }, - - { QMediaMetaData::Publisher, GST_TAG_ORGANIZATION, QVariant::String }, - { QMediaMetaData::Copyright, GST_TAG_COPYRIGHT, QVariant::String }, - //{ QMediaMetaData::ParentalRating, 0, QVariant::String }, - //{ QMediaMetaData::RatingOrganisation, 0, QVariant::String }, - - // Media - //{ QMediaMetaData::Size, 0, QVariant::Int }, - //{ QMediaMetaData::MediaType, 0, QVariant::String }, - { QMediaMetaData::Duration, GST_TAG_DURATION, QVariant::Int }, - - // Audio - { QMediaMetaData::AudioBitRate, GST_TAG_BITRATE, QVariant::Int }, - { QMediaMetaData::AudioCodec, GST_TAG_AUDIO_CODEC, QVariant::String }, - //{ QMediaMetaData::ChannelCount, 0, QVariant::Int }, - //{ QMediaMetaData::SampleRate, 0, QVariant::Int }, - - // Music - { QMediaMetaData::AlbumTitle, GST_TAG_ALBUM, QVariant::String }, - { QMediaMetaData::AlbumArtist, GST_TAG_ARTIST, QVariant::String}, - { QMediaMetaData::ContributingArtist, GST_TAG_PERFORMER, QVariant::String }, + if (metadataKeys->isEmpty()) { + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Title, GST_TAG_TITLE, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::SubTitle, 0, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Author, 0, QVariant::String)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Comment, GST_TAG_COMMENT, QVariant::String)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Date, GST_TAG_DATE_TIME, QVariant::DateTime)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Description, GST_TAG_DESCRIPTION, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Category, 0, QVariant::String)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Genre, GST_TAG_GENRE, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Year, 0, QVariant::Int)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::UserRating, , QVariant::Int)); + + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Language, GST_TAG_LANGUAGE_CODE, QVariant::String)); + + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Publisher, GST_TAG_ORGANIZATION, QVariant::String)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Copyright, GST_TAG_COPYRIGHT, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::ParentalRating, 0, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::RatingOrganisation, 0, QVariant::String)); + + // Media + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Size, 0, QVariant::Int)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::MediaType, 0, QVariant::String)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Duration, GST_TAG_DURATION, QVariant::Int)); + + // Audio + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::AudioBitRate, GST_TAG_BITRATE, QVariant::Int)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::AudioCodec, GST_TAG_AUDIO_CODEC, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::ChannelCount, 0, QVariant::Int)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::SampleRate, 0, QVariant::Int)); + + // Music + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::AlbumTitle, GST_TAG_ALBUM, QVariant::String)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::AlbumArtist, GST_TAG_ARTIST, QVariant::String)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::ContributingArtist, GST_TAG_PERFORMER, QVariant::String)); #if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19) - { QMediaMetaData::Composer, GST_TAG_COMPOSER, QVariant::String }, + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Composer, GST_TAG_COMPOSER, QVariant::String)); #endif - //{ QMediaMetaData::Conductor, 0, QVariant::String }, - //{ QMediaMetaData::Lyrics, 0, QVariant::String }, - //{ QMediaMetaData::Mood, 0, QVariant::String }, - { QMediaMetaData::TrackNumber, GST_TAG_TRACK_NUMBER, QVariant::Int }, + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Conductor, 0, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Lyrics, 0, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Mood, 0, QVariant::String)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::TrackNumber, GST_TAG_TRACK_NUMBER, QVariant::Int)); - //{ QMediaMetaData::CoverArtUrlSmall, 0, QVariant::String }, - //{ QMediaMetaData::CoverArtUrlLarge, 0, QVariant::String }, + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::CoverArtUrlSmall, 0, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::CoverArtUrlLarge, 0, QVariant::String)); - // Image/Video - //{ QMediaMetaData::Resolution, 0, QVariant::Size }, - //{ QMediaMetaData::PixelAspectRatio, 0, QVariant::Size }, + // Image/Video + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Resolution, 0, QVariant::Size)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::PixelAspectRatio, 0, QVariant::Size)); - // Video - //{ QMediaMetaData::VideoFrameRate, 0, QVariant::String }, - //{ QMediaMetaData::VideoBitRate, 0, QVariant::Double }, - { QMediaMetaData::VideoCodec, GST_TAG_VIDEO_CODEC, QVariant::String }, + // Video + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::VideoFrameRate, 0, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::VideoBitRate, 0, QVariant::Double)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::VideoCodec, GST_TAG_VIDEO_CODEC, QVariant::String)); - //{ QMediaMetaData::PosterUrl, 0, QVariant::String }, + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::PosterUrl, 0, QVariant::String)); - // Movie - //{ QMediaMetaData::ChapterNumber, 0, QVariant::Int }, - //{ QMediaMetaData::Director, 0, QVariant::String }, - { QMediaMetaData::LeadPerformer, GST_TAG_PERFORMER, QVariant::String }, - //{ QMediaMetaData::Writer, 0, QVariant::String }, + // Movie + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::ChapterNumber, 0, QVariant::Int)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Director, 0, QVariant::String)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::LeadPerformer, GST_TAG_PERFORMER, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Writer, 0, QVariant::String)); #if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 30) - // Photos - { QMediaMetaData::CameraManufacturer, GST_TAG_DEVICE_MANUFACTURER, QVariant::String }, - { QMediaMetaData::CameraModel, GST_TAG_DEVICE_MODEL, QVariant::String }, - //{ QMediaMetaData::Event, 0, QVariant::String }, - //{ QMediaMetaData::Subject, 0, QVariant::String }, - - { QMediaMetaData::Orientation, GST_TAG_IMAGE_ORIENTATION, QVariant::String }, - - // GPS - { QMediaMetaData::GPSLatitude, GST_TAG_GEO_LOCATION_LATITUDE, QVariant::Double }, - { QMediaMetaData::GPSLongitude, GST_TAG_GEO_LOCATION_LONGITUDE, QVariant::Double }, - { QMediaMetaData::GPSAltitude, GST_TAG_GEO_LOCATION_ELEVATION, QVariant::Double }, - { QMediaMetaData::GPSTrack, GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, QVariant::Double }, - { QMediaMetaData::GPSSpeed, GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, QVariant::Double }, - { QMediaMetaData::GPSImgDirection, GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, QVariant::Double } + // Photos + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::CameraManufacturer, GST_TAG_DEVICE_MANUFACTURER, QVariant::String)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::CameraModel, GST_TAG_DEVICE_MODEL, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Event, 0, QVariant::String)); + //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Subject, 0, QVariant::String)); + + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Orientation, GST_TAG_IMAGE_ORIENTATION, QVariant::String)); + + // GPS + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::GPSLatitude, GST_TAG_GEO_LOCATION_LATITUDE, QVariant::Double)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::GPSLongitude, GST_TAG_GEO_LOCATION_LONGITUDE, QVariant::Double)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::GPSAltitude, GST_TAG_GEO_LOCATION_ELEVATION, QVariant::Double)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::GPSTrack, GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, QVariant::Double)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::GPSSpeed, GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, QVariant::Double)); + metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::GPSImgDirection, GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, QVariant::Double)); #endif -}; + } + + return metadataKeys; +} CameraBinMetaData::CameraBinMetaData(QObject *parent) :QMetaDataWriterControl(parent) @@ -183,14 +198,9 @@ QVariant CameraBinMetaData::metaData(const QString &key) const return (metersPerSec * 3600) / 1000; } - static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup); - - for (int i = 0; i < count; ++i) { - if (qt_gstreamerMetaDataKeys[i].key == key) { - const char *name = qt_gstreamerMetaDataKeys[i].token; - - return m_values.value(QByteArray::fromRawData(name, qstrlen(name))); - } + Q_FOREACH (const QGStreamerMetaDataKey &metadataKey, *qt_gstreamerMetaDataKeys()) { + if (metadataKey.qtName == key) + return m_values.value(QByteArray::fromRawData(metadataKey.gstName, qstrlen(metadataKey.gstName))); } return QVariant(); } @@ -207,14 +217,12 @@ void CameraBinMetaData::setMetaData(const QString &key, const QVariant &value) } } - static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup); - - for (int i = 0; i < count; ++i) { - if (qt_gstreamerMetaDataKeys[i].key == key) { - const char *name = qt_gstreamerMetaDataKeys[i].token; + Q_FOREACH (const QGStreamerMetaDataKey &metadataKey, *qt_gstreamerMetaDataKeys()) { + if (metadataKey.qtName == key) { + const char *name = metadataKey.gstName; if (correctedValue.isValid()) { - correctedValue.convert(qt_gstreamerMetaDataKeys[i].type); + correctedValue.convert(metadataKey.type); m_values.insert(QByteArray::fromRawData(name, qstrlen(name)), correctedValue); } else { m_values.remove(QByteArray::fromRawData(name, qstrlen(name))); @@ -232,14 +240,12 @@ QStringList CameraBinMetaData::availableMetaData() const { static QMap<QByteArray, QString> keysMap; if (keysMap.isEmpty()) { - const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup); - for (int i = 0; i < count; ++i) { - keysMap[QByteArray(qt_gstreamerMetaDataKeys[i].token)] = qt_gstreamerMetaDataKeys[i].key; - } + Q_FOREACH (const QGStreamerMetaDataKey &metadataKey, *qt_gstreamerMetaDataKeys()) + keysMap[QByteArray(metadataKey.gstName)] = metadataKey.qtName; } QStringList res; - foreach (const QByteArray &key, m_values.keys()) { + Q_FOREACH (const QByteArray &key, m_values.keys()) { QString tag = keysMap.value(key); if (!tag.isEmpty()) res.append(tag); diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp index fd7fb7d82..1080a5875 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp @@ -46,80 +46,82 @@ #include <gst/gst.h> #include <gst/gstversion.h> -struct QGstreamerMetaDataKeyLookup -{ - QString key; - const char *token; -}; -static const QGstreamerMetaDataKeyLookup qt_gstreamerMetaDataKeys[] = +typedef QMap<QString, QByteArray> QGstreamerMetaDataKeyLookup; +Q_GLOBAL_STATIC(QGstreamerMetaDataKeyLookup, metadataKeys) + +static const QGstreamerMetaDataKeyLookup *qt_gstreamerMetaDataKeys() { - { QMediaMetaData::Title, GST_TAG_TITLE }, - //{ QMediaMetaData::SubTitle, 0 }, - //{ QMediaMetaData::Author, 0 }, - { QMediaMetaData::Comment, GST_TAG_COMMENT }, - { QMediaMetaData::Description, GST_TAG_DESCRIPTION }, - //{ QMediaMetaData::Category, 0 }, - { QMediaMetaData::Genre, GST_TAG_GENRE }, - //{ QMediaMetaData::Year, 0 }, - //{ QMediaMetaData::UserRating, 0 }, - - { QMediaMetaData::Language, GST_TAG_LANGUAGE_CODE }, - - { QMediaMetaData::Publisher, GST_TAG_ORGANIZATION }, - { QMediaMetaData::Copyright, GST_TAG_COPYRIGHT }, - //{ QMediaMetaData::ParentalRating, 0 }, - //{ QMediaMetaData::RatingOrganisation, 0 }, - - // Media - //{ QMediaMetaData::Size, 0 }, - //{ QMediaMetaData::MediaType, 0 }, - { QMediaMetaData::Duration, GST_TAG_DURATION }, - - // Audio - { QMediaMetaData::AudioBitRate, GST_TAG_BITRATE }, - { QMediaMetaData::AudioCodec, GST_TAG_AUDIO_CODEC }, - //{ QMediaMetaData::ChannelCount, 0 }, - //{ QMediaMetaData::SampleRate, 0 }, - - // Music - { QMediaMetaData::AlbumTitle, GST_TAG_ALBUM }, - { QMediaMetaData::AlbumArtist, GST_TAG_ARTIST}, - { QMediaMetaData::ContributingArtist, GST_TAG_PERFORMER }, + if (metadataKeys->isEmpty()) { + metadataKeys->insert(QMediaMetaData::Title, GST_TAG_TITLE); + metadataKeys->insert(QMediaMetaData::SubTitle, 0); + //metadataKeys->insert(QMediaMetaData::Author, 0); + metadataKeys->insert(QMediaMetaData::Comment, GST_TAG_COMMENT); + metadataKeys->insert(QMediaMetaData::Description, GST_TAG_DESCRIPTION); + //metadataKeys->insert(QMediaMetaData::Category, 0); + metadataKeys->insert(QMediaMetaData::Genre, GST_TAG_GENRE); + //metadataKeys->insert(QMediaMetaData::Year, 0); + //metadataKeys->insert(QMediaMetaData::UserRating, 0); + + metadataKeys->insert(QMediaMetaData::Language, GST_TAG_LANGUAGE_CODE); + + metadataKeys->insert(QMediaMetaData::Publisher, GST_TAG_ORGANIZATION); + metadataKeys->insert(QMediaMetaData::Copyright, GST_TAG_COPYRIGHT); + //metadataKeys->insert(QMediaMetaData::ParentalRating, 0); + //metadataKeys->insert(QMediaMetaData::RatingOrganisation, 0); + + // Media + //metadataKeys->insert(QMediaMetaData::Size, 0); + //metadataKeys->insert(QMediaMetaData::MediaType, 0); + metadataKeys->insert(QMediaMetaData::Duration, GST_TAG_DURATION); + + // Audio + metadataKeys->insert(QMediaMetaData::AudioBitRate, GST_TAG_BITRATE); + metadataKeys->insert(QMediaMetaData::AudioCodec, GST_TAG_AUDIO_CODEC); + //metadataKeys->insert(QMediaMetaData::ChannelCount, 0); + //metadataKeys->insert(QMediaMetaData::SampleRate, 0); + + // Music + metadataKeys->insert(QMediaMetaData::AlbumTitle, GST_TAG_ALBUM); + metadataKeys->insert(QMediaMetaData::AlbumArtist, GST_TAG_ARTIST); + metadataKeys->insert(QMediaMetaData::ContributingArtist, GST_TAG_PERFORMER); #if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19) - { QMediaMetaData::Composer, GST_TAG_COMPOSER }, + metadataKeys->insert(QMediaMetaData::Composer, GST_TAG_COMPOSER); #endif - //{ QMediaMetaData::Conductor, 0 }, - //{ QMediaMetaData::Lyrics, 0 }, - //{ QMediaMetaData::Mood, 0 }, - { QMediaMetaData::TrackNumber, GST_TAG_TRACK_NUMBER }, - - //{ QMediaMetaData::CoverArtUrlSmall, 0 }, - //{ QMediaMetaData::CoverArtUrlLarge, 0 }, - - // Image/Video - //{ QMediaMetaData::Resolution, 0 }, - //{ QMediaMetaData::PixelAspectRatio, 0 }, - - // Video - //{ QMediaMetaData::VideoFrameRate, 0 }, - //{ QMediaMetaData::VideoBitRate, 0 }, - { QMediaMetaData::VideoCodec, GST_TAG_VIDEO_CODEC }, - - //{ QMediaMetaData::PosterUrl, 0 }, - - // Movie - //{ QMediaMetaData::ChapterNumber, 0 }, - //{ QMediaMetaData::Director, 0 }, - { QMediaMetaData::LeadPerformer, GST_TAG_PERFORMER }, - //{ QMediaMetaData::Writer, 0 }, - - // Photos - //{ QMediaMetaData::CameraManufacturer, 0 }, - //{ QMediaMetaData::CameraModel, 0 }, - //{ QMediaMetaData::Event, 0 }, - //{ QMediaMetaData::Subject, 0 } -}; + //metadataKeys->insert(QMediaMetaData::Conductor, 0); + //metadataKeys->insert(QMediaMetaData::Lyrics, 0); + //metadataKeys->insert(QMediaMetaData::Mood, 0); + metadataKeys->insert(QMediaMetaData::TrackNumber, GST_TAG_TRACK_NUMBER); + + //metadataKeys->insert(QMediaMetaData::CoverArtUrlSmall, 0); + //metadataKeys->insert(QMediaMetaData::CoverArtUrlLarge, 0); + + // Image/Video + //metadataKeys->insert(QMediaMetaData::Resolution, 0); + //metadataKeys->insert(QMediaMetaData::PixelAspectRatio, 0); + + // Video + //metadataKeys->insert(QMediaMetaData::VideoFrameRate, 0); + //metadataKeys->insert(QMediaMetaData::VideoBitRate, 0); + metadataKeys->insert(QMediaMetaData::VideoCodec, GST_TAG_VIDEO_CODEC); + + //metadataKeys->insert(QMediaMetaData::PosterUrl, 0); + + // Movie + //metadataKeys->insert(QMediaMetaData::ChapterNumber, 0); + //metadataKeys->insert(QMediaMetaData::Director, 0); + metadataKeys->insert(QMediaMetaData::LeadPerformer, GST_TAG_PERFORMER); + //metadataKeys->insert(QMediaMetaData::Writer, 0); + + // Photos + //metadataKeys->insert(QMediaMetaData::CameraManufacturer, 0); + //metadataKeys->insert(QMediaMetaData::CameraModel, 0); + //metadataKeys->insert(QMediaMetaData::Event, 0); + //metadataKeys->insert(QMediaMetaData::Subject, 0 } + } + + return metadataKeys; +} QGstreamerCaptureMetaDataControl::QGstreamerCaptureMetaDataControl(QObject *parent) :QMetaDataWriterControl(parent) @@ -128,50 +130,30 @@ QGstreamerCaptureMetaDataControl::QGstreamerCaptureMetaDataControl(QObject *pare QVariant QGstreamerCaptureMetaDataControl::metaData(const QString &key) const { - static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup); - - for (int i = 0; i < count; ++i) { - if (qt_gstreamerMetaDataKeys[i].key == key) { - const char *name = qt_gstreamerMetaDataKeys[i].token; + QGstreamerMetaDataKeyLookup::const_iterator it = qt_gstreamerMetaDataKeys()->find(key); + if (it != qt_gstreamerMetaDataKeys()->constEnd()) + return m_values.value(it.value()); - return m_values.value(QByteArray::fromRawData(name, qstrlen(name))); - } - } return QVariant(); } void QGstreamerCaptureMetaDataControl::setMetaData(const QString &key, const QVariant &value) { - static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup); - - for (int i = 0; i < count; ++i) { - if (qt_gstreamerMetaDataKeys[i].key == key) { - const char *name = qt_gstreamerMetaDataKeys[i].token; - - m_values.insert(QByteArray::fromRawData(name, qstrlen(name)), value); + QGstreamerMetaDataKeyLookup::const_iterator it = qt_gstreamerMetaDataKeys()->find(key); + if (it != qt_gstreamerMetaDataKeys()->constEnd()) { + m_values.insert(it.value(), value); - emit QMetaDataWriterControl::metaDataChanged(); - emit QMetaDataWriterControl::metaDataChanged(key, value); - emit metaDataChanged(m_values); - - return; - } + emit QMetaDataWriterControl::metaDataChanged(); + emit QMetaDataWriterControl::metaDataChanged(key, value); + emit metaDataChanged(m_values); } } QStringList QGstreamerCaptureMetaDataControl::availableMetaData() const { - static QMap<QByteArray, QString> keysMap; - if (keysMap.isEmpty()) { - const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup); - for (int i = 0; i < count; ++i) { - keysMap[QByteArray(qt_gstreamerMetaDataKeys[i].token)] = qt_gstreamerMetaDataKeys[i].key; - } - } - QStringList res; foreach (const QByteArray &key, m_values.keys()) { - QString tag = keysMap.value(key); + QString tag = qt_gstreamerMetaDataKeys()->key(key); if (!tag.isEmpty()) res.append(tag); } diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp index fa837d3f4..88faf607c 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp @@ -48,90 +48,86 @@ QT_BEGIN_NAMESPACE -struct QGstreamerMetaDataKeyLookup -{ - QString key; - const char *token; -}; +typedef QMap<QByteArray, QString> QGstreamerMetaDataKeyLookup; +Q_GLOBAL_STATIC(QGstreamerMetaDataKeyLookup, metadataKeys) -static const QGstreamerMetaDataKeyLookup qt_gstreamerMetaDataKeys[] = +static const QGstreamerMetaDataKeyLookup *qt_gstreamerMetaDataKeys() { - { QMediaMetaData::Title, GST_TAG_TITLE }, - //{ QMediaMetaData::SubTitle, 0 }, - //{ QMediaMetaData::Author, 0 }, - { QMediaMetaData::Comment, GST_TAG_COMMENT }, - { QMediaMetaData::Description, GST_TAG_DESCRIPTION }, - //{ QMediaMetaData::Category, 0 }, - { QMediaMetaData::Genre, GST_TAG_GENRE }, - { QMediaMetaData::Year, "year" }, - //{ QMediaMetaData::UserRating, 0 }, - - { QMediaMetaData::Language, GST_TAG_LANGUAGE_CODE }, - - { QMediaMetaData::Publisher, GST_TAG_ORGANIZATION }, - { QMediaMetaData::Copyright, GST_TAG_COPYRIGHT }, - //{ QMediaMetaData::ParentalRating, 0 }, - //{ QMediaMetaData::RatingOrganisation, 0 }, - - // Media - //{ QMediaMetaData::Size, 0 }, - //{ QMediaMetaData::MediaType, 0 }, - { QMediaMetaData::Duration, GST_TAG_DURATION }, - - // Audio - { QMediaMetaData::AudioBitRate, GST_TAG_BITRATE }, - { QMediaMetaData::AudioCodec, GST_TAG_AUDIO_CODEC }, - //{ QMediaMetaData::ChannelCount, 0 }, - //{ QMediaMetaData::SampleRate, 0 }, - - // Music - { QMediaMetaData::AlbumTitle, GST_TAG_ALBUM }, - { QMediaMetaData::AlbumArtist, GST_TAG_ARTIST}, - { QMediaMetaData::ContributingArtist, GST_TAG_PERFORMER }, + if (metadataKeys->isEmpty()) { + metadataKeys->insert(GST_TAG_TITLE, QMediaMetaData::Title); + //metadataKeys->insert(0, QMediaMetaData::SubTitle); + //metadataKeys->insert(0, QMediaMetaData::Author); + metadataKeys->insert(GST_TAG_COMMENT, QMediaMetaData::Comment); + metadataKeys->insert(GST_TAG_DESCRIPTION, QMediaMetaData::Description); + //metadataKeys->insert(0, QMediaMetaData::Category); + metadataKeys->insert(GST_TAG_GENRE, QMediaMetaData::Genre); + metadataKeys->insert("year", QMediaMetaData::Year); + //metadataKeys->insert(0, QMediaMetaData::UserRating); + + metadataKeys->insert(GST_TAG_LANGUAGE_CODE, QMediaMetaData::Language); + + metadataKeys->insert(GST_TAG_ORGANIZATION, QMediaMetaData::Publisher); + metadataKeys->insert(GST_TAG_COPYRIGHT, QMediaMetaData::Copyright); + //metadataKeys->insert(0, QMediaMetaData::ParentalRating); + //metadataKeys->insert(0, QMediaMetaData::RatingOrganisation); + + // Media + //metadataKeys->insert(0, QMediaMetaData::Size); + //metadataKeys->insert(0,QMediaMetaData::MediaType ); + metadataKeys->insert(GST_TAG_DURATION, QMediaMetaData::Duration); + + // Audio + metadataKeys->insert(GST_TAG_BITRATE, QMediaMetaData::AudioBitRate); + metadataKeys->insert(GST_TAG_AUDIO_CODEC, QMediaMetaData::AudioCodec); + //metadataKeys->insert(0, QMediaMetaData::ChannelCount); + //metadataKeys->insert(0, QMediaMetaData::SampleRate); + + // Music + metadataKeys->insert(GST_TAG_ALBUM, QMediaMetaData::AlbumTitle); + metadataKeys->insert(GST_TAG_ARTIST, QMediaMetaData::AlbumArtist); + metadataKeys->insert(GST_TAG_PERFORMER, QMediaMetaData::ContributingArtist); #if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19) - { QMediaMetaData::Composer, GST_TAG_COMPOSER }, + metadataKeys->insert(GST_TAG_COMPOSER, QMediaMetaData::Composer); #endif - //{ QMediaMetaData::Conductor, 0 }, - //{ QMediaMetaData::Lyrics, 0 }, - //{ QMediaMetaData::Mood, 0 }, - { QMediaMetaData::TrackNumber, GST_TAG_TRACK_NUMBER }, - - //{ QMediaMetaData::CoverArtUrlSmall, 0 }, - //{ QMediaMetaData::CoverArtUrlLarge, 0 }, - - // Image/Video - { QMediaMetaData::Resolution, "resolution" }, - { QMediaMetaData::PixelAspectRatio, "pixel-aspect-ratio" }, - - // Video - //{ QMediaMetaData::VideoFrameRate, 0 }, - //{ QMediaMetaData::VideoBitRate, 0 }, - { QMediaMetaData::VideoCodec, GST_TAG_VIDEO_CODEC }, - - //{ QMediaMetaData::PosterUrl, 0 }, - - // Movie - //{ QMediaMetaData::ChapterNumber, 0 }, - //{ QMediaMetaData::Director, 0 }, - { QMediaMetaData::LeadPerformer, GST_TAG_PERFORMER }, - //{ QMediaMetaData::Writer, 0 }, - - // Photos - //{ QMediaMetaData::CameraManufacturer, 0 }, - //{ QMediaMetaData::CameraModel, 0 }, - //{ QMediaMetaData::Event, 0 }, - //{ QMediaMetaData::Subject, 0 } -}; + //metadataKeys->insert(0, QMediaMetaData::Conductor); + //metadataKeys->insert(0, QMediaMetaData::Lyrics); + //metadataKeys->insert(0, QMediaMetaData::Mood); + metadataKeys->insert(GST_TAG_TRACK_NUMBER, QMediaMetaData::TrackNumber); + + //metadataKeys->insert(0, QMediaMetaData::CoverArtUrlSmall); + //metadataKeys->insert(0, QMediaMetaData::CoverArtUrlLarge); + + // Image/Video + metadataKeys->insert("resolution", QMediaMetaData::Resolution); + metadataKeys->insert("pixel-aspect-ratio", QMediaMetaData::PixelAspectRatio); + + // Video + //metadataKeys->insert(0, QMediaMetaData::VideoFrameRate); + //metadataKeys->insert(0, QMediaMetaData::VideoBitRate); + metadataKeys->insert(GST_TAG_VIDEO_CODEC, QMediaMetaData::VideoCodec); + + //metadataKeys->insert(0, QMediaMetaData::PosterUrl); + + // Movie + //metadataKeys->insert(0, QMediaMetaData::ChapterNumber); + //metadataKeys->insert(0, QMediaMetaData::Director); + metadataKeys->insert(GST_TAG_PERFORMER, QMediaMetaData::LeadPerformer); + //metadataKeys->insert(0, QMediaMetaData::Writer); + + // Photos + //metadataKeys->insert(0, QMediaMetaData::CameraManufacturer); + //metadataKeys->insert(0, QMediaMetaData::CameraModel); + //metadataKeys->insert(0, QMediaMetaData::Event); + //metadataKeys->insert(0, QMediaMetaData::Subject); + } + + return metadataKeys; +} QGstreamerMetaDataProvider::QGstreamerMetaDataProvider(QGstreamerPlayerSession *session, QObject *parent) :QMetaDataReaderControl(parent), m_session(session) { connect(m_session, SIGNAL(tagsChanged()), SLOT(updateTags())); - - const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup); - for (int i = 0; i < count; ++i) { - m_keysMap[QByteArray(qt_gstreamerMetaDataKeys[i].token)] = qt_gstreamerMetaDataKeys[i].key; - } } QGstreamerMetaDataProvider::~QGstreamerMetaDataProvider() @@ -167,8 +163,8 @@ void QGstreamerMetaDataProvider::updateTags() QMapIterator<QByteArray ,QVariant> i(m_session->tags()); while (i.hasNext()) { i.next(); - //use gstreamer native keys for elements not in m_keysMap - QString key = m_keysMap.value(i.key(), i.key()); + //use gstreamer native keys for elements not in our key map + QString key = qt_gstreamerMetaDataKeys()->value(i.key(), i.key()); m_tags.insert(key, i.value()); if (i.value() != oldTags.value(key)) { changed = true; diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.h b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.h index e36c127ad..7b3b266fa 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.h +++ b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.h @@ -67,7 +67,6 @@ private slots: private: QGstreamerPlayerSession *m_session; QVariantMap m_tags; - QMap<QByteArray, QString> m_keysMap; }; QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp index 27446e07d..87b71d7e2 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp @@ -1535,6 +1535,7 @@ void QGstreamerPlayerSession::playbinNotifySource(GObject *o, GParamSpec *p, gpo qDebug() << "Current source is a non-live source"; #endif + g_object_set(G_OBJECT(self->m_videoSink), "sync", !self->m_isLiveSource, NULL); gst_object_unref(source); } diff --git a/src/plugins/opensles/qopenslesaudiooutput.cpp b/src/plugins/opensles/qopenslesaudiooutput.cpp index df91e6ff1..49bea0b36 100644 --- a/src/plugins/opensles/qopenslesaudiooutput.cpp +++ b/src/plugins/opensles/qopenslesaudiooutput.cpp @@ -568,7 +568,7 @@ void QOpenSLESAudioOutput::destroyPlayer() qint64 QOpenSLESAudioOutput::writeData(const char *data, qint64 len) { - if (!len) + if (!len || !m_availableBuffers.load()) return 0; if (len > m_bufferSize) diff --git a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp index 2555b2876..abb682784 100644 --- a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp +++ b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp @@ -208,7 +208,8 @@ void MmRendererMediaPlayerControl::attach() if (m_videoWindowControl) m_videoWindowControl->attachDisplay(m_context); - m_audioId = mmr_output_attach(m_context, "audio:default", "audio"); + const QByteArray defaultAudioDevice = qgetenv("QQNX_RENDERER_DEFAULT_AUDIO_SINK"); + m_audioId = mmr_output_attach(m_context, defaultAudioDevice.isEmpty() ? "audio:default" : defaultAudioDevice.constData(), "audio"); if (m_audioId == -1) { emitMmError("mmr_output_attach() for audio failed"); return; diff --git a/src/plugins/videonode/imx6/qsgvivantevideomaterial.cpp b/src/plugins/videonode/imx6/qsgvivantevideomaterial.cpp index 44f9f4d12..0f3dd59f8 100644 --- a/src/plugins/videonode/imx6/qsgvivantevideomaterial.cpp +++ b/src/plugins/videonode/imx6/qsgvivantevideomaterial.cpp @@ -70,7 +70,7 @@ QSGVivanteVideoMaterial::QSGVivanteVideoMaterial() : QSGVivanteVideoMaterial::~QSGVivanteVideoMaterial() { - for (GLuint id : mBitsToTextureMap.values()) { + Q_FOREACH (GLuint id, mBitsToTextureMap.values()) { #ifdef QT_VIVANTE_VIDEO_DEBUG qDebug() << "delete texture: " << id; #endif @@ -154,7 +154,7 @@ GLuint QSGVivanteVideoMaterial::vivanteMapping(QVideoFrame vF) mWidth = vF.width(); mHeight = vF.height(); mFormat = vF.pixelFormat(); - for (GLuint id : mBitsToTextureMap.values()) { + Q_FOREACH (GLuint id, mBitsToTextureMap.values()) { #ifdef QT_VIVANTE_VIDEO_DEBUG qDebug() << "delete texture: " << id; #endif diff --git a/src/plugins/wmf/player/mfvideorenderercontrol.cpp b/src/plugins/wmf/player/mfvideorenderercontrol.cpp index 040682965..420473666 100644 --- a/src/plugins/wmf/player/mfvideorenderercontrol.cpp +++ b/src/plugins/wmf/player/mfvideorenderercontrol.cpp @@ -572,6 +572,18 @@ namespace QVideoSurfaceFormat format(QSize(width, height), m_pixelFormats[index]); m_surfaceFormat = format; + MFVideoArea viewport; + if (SUCCEEDED(pMediaType->GetBlob(MF_MT_GEOMETRIC_APERTURE, + reinterpret_cast<UINT8*>(&viewport), + sizeof(MFVideoArea), + NULL))) { + + m_surfaceFormat.setViewport(QRect(viewport.OffsetX.value, + viewport.OffsetY.value, + viewport.Area.cx, + viewport.Area.cy)); + } + if (FAILED(pMediaType->GetUINT32(MF_MT_DEFAULT_STRIDE, (UINT32*)&m_bytesPerLine))) { m_bytesPerLine = getBytesPerLine(format); } diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp b/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp index b13665f66..e904307df 100644 --- a/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp +++ b/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp @@ -104,6 +104,7 @@ QT_BEGIN_NAMESPACE \sa MediaPlayer, Camera +\omit \section1 Screen Saver If it is likely that an application will be playing video for an extended @@ -116,8 +117,11 @@ QT_BEGIN_NAMESPACE ScreenSaver { screenSaverEnabled: false } \endqml +\endomit */ +// TODO: Restore Qt System Info docs when the module is released + /*! \internal \class QDeclarativeVideoOutput diff --git a/src/qtmultimediaquicktools/qsgvideonode_i420.cpp b/src/qtmultimediaquicktools/qsgvideonode_i420.cpp index d7eb04863..2d84f6ed1 100644 --- a/src/qtmultimediaquicktools/qsgvideonode_i420.cpp +++ b/src/qtmultimediaquicktools/qsgvideonode_i420.cpp @@ -87,11 +87,15 @@ protected: virtual const char *vertexShader() const { const char *shader = "uniform highp mat4 qt_Matrix; \n" + "uniform highp float yWidth; \n" + "uniform highp float uvWidth; \n" "attribute highp vec4 qt_VertexPosition; \n" "attribute highp vec2 qt_VertexTexCoord; \n" - "varying highp vec2 qt_TexCoord; \n" + "varying highp vec2 yTexCoord; \n" + "varying highp vec2 uvTexCoord; \n" "void main() { \n" - " qt_TexCoord = qt_VertexTexCoord; \n" + " yTexCoord = qt_VertexTexCoord * vec2(yWidth, 1);\n" + " uvTexCoord = qt_VertexTexCoord * vec2(uvWidth, 1);\n" " gl_Position = qt_Matrix * qt_VertexPosition; \n" "}"; return shader; @@ -105,13 +109,14 @@ protected: "uniform mediump mat4 colorMatrix;" "uniform lowp float opacity;" "" - "varying highp vec2 qt_TexCoord;" + "varying highp vec2 yTexCoord;" + "varying highp vec2 uvTexCoord;" "" "void main()" "{" - " mediump float Y = texture2D(yTexture, qt_TexCoord).r;" - " mediump float U = texture2D(uTexture, qt_TexCoord).r;" - " mediump float V = texture2D(vTexture, qt_TexCoord).r;" + " mediump float Y = texture2D(yTexture, yTexCoord).r;" + " mediump float U = texture2D(uTexture, uvTexCoord).r;" + " mediump float V = texture2D(vTexture, uvTexCoord).r;" " mediump vec4 color = vec4(Y, U, V, 1.);" " gl_FragColor = colorMatrix * color * opacity;" "}"; @@ -120,6 +125,8 @@ protected: virtual void initialize() { m_id_matrix = program()->uniformLocation("qt_Matrix"); + m_id_yWidth = program()->uniformLocation("yWidth"); + m_id_uvWidth = program()->uniformLocation("uvWidth"); m_id_yTexture = program()->uniformLocation("yTexture"); m_id_uTexture = program()->uniformLocation("uTexture"); m_id_vTexture = program()->uniformLocation("vTexture"); @@ -128,6 +135,8 @@ protected: } int m_id_matrix; + int m_id_yWidth; + int m_id_uvWidth; int m_id_yTexture; int m_id_uTexture; int m_id_vTexture; @@ -181,6 +190,8 @@ public: GLuint m_textureIds[Num_Texture_IDs]; qreal m_opacity; + GLfloat m_yWidth; + GLfloat m_uvWidth; QMatrix4x4 m_colorMatrix; QVideoFrame m_frame; @@ -189,7 +200,9 @@ public: QSGVideoMaterial_YUV420::QSGVideoMaterial_YUV420(const QVideoSurfaceFormat &format) : m_format(format), - m_opacity(1.0) + m_opacity(1.0), + m_yWidth(1.0), + m_uvWidth(1.0) { memset(m_textureIds, 0, sizeof(m_textureIds)); @@ -245,21 +258,34 @@ void QSGVideoMaterial_YUV420::bind() } const uchar *bits = m_frame.bits(); - int bpl = m_frame.bytesPerLine(); - int bpl2 = (bpl / 2 + 3) & ~3; - int offsetU = bpl * fh; - int offsetV = bpl * fh + bpl2 * fh / 2; + int yStride = m_frame.bytesPerLine(); + // The UV stride is usually half the Y stride and is 32-bit aligned. + // However it's not always the case, at least on Windows where the + // UV planes are sometimes not aligned. + // We calculate the stride using the UV byte count to always + // have a correct stride. + int uvStride = (m_frame.mappedBytes() - yStride * fh) / fh; + int offsetU = yStride * fh; + int offsetV = yStride * fh + uvStride * fh / 2; + + m_yWidth = qreal(fw) / yStride; + m_uvWidth = qreal(fw) / (2 * uvStride); if (m_frame.pixelFormat() == QVideoFrame::Format_YV12) qSwap(offsetU, offsetV); + GLint previousAlignment; + glGetIntegerv(GL_UNPACK_ALIGNMENT, &previousAlignment); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); functions->glActiveTexture(GL_TEXTURE1); - bindTexture(m_textureIds[1], fw/2, fh / 2, bits + offsetU); + bindTexture(m_textureIds[1], uvStride, fh / 2, bits + offsetU); functions->glActiveTexture(GL_TEXTURE2); - bindTexture(m_textureIds[2], fw/2, fh / 2, bits + offsetV); + bindTexture(m_textureIds[2], uvStride, fh / 2, bits + offsetV); functions->glActiveTexture(GL_TEXTURE0); // Finish with 0 as default texture unit - bindTexture(m_textureIds[0], fw, fh, bits); + bindTexture(m_textureIds[0], yStride, fh, bits); + + glPixelStorei(GL_UNPACK_ALIGNMENT, previousAlignment); m_frame.unmap(); } @@ -318,6 +344,8 @@ void QSGVideoMaterialShader_YUV420::updateState(const RenderState &state, mat->bind(); program()->setUniformValue(m_id_colorMatrix, mat->m_colorMatrix); + program()->setUniformValue(m_id_yWidth, mat->m_yWidth); + program()->setUniformValue(m_id_uvWidth, mat->m_uvWidth); if (state.isOpacityDirty()) { mat->m_opacity = state.opacity(); program()->setUniformValue(m_id_opacity, GLfloat(mat->m_opacity)); diff --git a/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp b/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp index fbe60c9a7..ad01a08ae 100644 --- a/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp +++ b/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp @@ -79,6 +79,7 @@ public: QSGVideoMaterialShader_RGB(QVideoFrame::PixelFormat pixelFormat) : QSGMaterialShader(), m_id_matrix(-1), + m_id_width(-1), m_id_rgbTexture(-1), m_id_opacity(-1), m_pixelFormat(pixelFormat) @@ -101,11 +102,12 @@ protected: virtual const char *vertexShader() const { const char *shader = "uniform highp mat4 qt_Matrix; \n" + "uniform highp float width; \n" "attribute highp vec4 qt_VertexPosition; \n" "attribute highp vec2 qt_VertexTexCoord; \n" "varying highp vec2 qt_TexCoord; \n" "void main() { \n" - " qt_TexCoord = qt_VertexTexCoord; \n" + " qt_TexCoord = qt_VertexTexCoord * vec2(width, 1);\n" " gl_Position = qt_Matrix * qt_VertexPosition; \n" "}"; return shader; @@ -146,11 +148,13 @@ protected: virtual void initialize() { m_id_matrix = program()->uniformLocation("qt_Matrix"); + m_id_width = program()->uniformLocation("width"); m_id_rgbTexture = program()->uniformLocation("rgbTexture"); m_id_opacity = program()->uniformLocation("opacity"); } int m_id_matrix; + int m_id_width; int m_id_rgbTexture; int m_id_opacity; QVideoFrame::PixelFormat m_pixelFormat; @@ -163,7 +167,8 @@ public: QSGVideoMaterial_RGB(const QVideoSurfaceFormat &format) : m_format(format), m_textureId(0), - m_opacity(1.0) + m_opacity(1.0), + m_width(1.0) { setFlag(Blending, false); } @@ -204,11 +209,25 @@ public: QMutexLocker lock(&m_frameMutex); if (m_frame.isValid()) { if (m_frame.map(QAbstractVideoBuffer::ReadOnly)) { - if (m_textureSize != m_frame.size()) { + QSize textureSize = m_frame.size(); + + int stride = m_frame.bytesPerLine(); + switch (m_frame.pixelFormat()) { + case QVideoFrame::Format_RGB565: + stride /= 2; + break; + default: + stride /= 4; + } + + m_width = qreal(m_frame.width() / stride); + textureSize.setWidth(stride); + + if (m_textureSize != textureSize) { if (!m_textureSize.isEmpty()) glDeleteTextures(1, &m_textureId); glGenTextures(1, &m_textureId); - m_textureSize = m_frame.size(); + m_textureSize = textureSize; } GLint dataType = GL_UNSIGNED_BYTE; @@ -219,12 +238,18 @@ public: dataFormat = GL_RGB; } + GLint previousAlignment; + glGetIntegerv(GL_UNPACK_ALIGNMENT, &previousAlignment); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + functions->glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_textureId); glTexImage2D(GL_TEXTURE_2D, 0, dataFormat, m_textureSize.width(), m_textureSize.height(), 0, dataFormat, dataType, m_frame.bits()); + glPixelStorei(GL_UNPACK_ALIGNMENT, previousAlignment); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -245,6 +270,7 @@ public: QVideoSurfaceFormat m_format; GLuint m_textureId; qreal m_opacity; + GLfloat m_width; }; @@ -276,6 +302,7 @@ void QSGVideoMaterialShader_RGB::updateState(const RenderState &state, mat->bind(); + program()->setUniformValue(m_id_width, mat->m_width); if (state.isOpacityDirty()) { mat->m_opacity = state.opacity(); mat->updateBlending(); |