Merge remote-tracking branch 'origin/stable' into dev

Change-Id: I310b468e9ba5b1e70f2e792df746a93ecb067c1a
This commit is contained in:
Frederik Gladhorn
2014-03-24 16:07:34 +01:00
71 changed files with 1691 additions and 678 deletions

View File

@@ -167,6 +167,7 @@ void AudioRecorder::updateStatus(QMediaRecorder::Status status)
statusMessage = tr("Paused"); statusMessage = tr("Paused");
break; break;
case QMediaRecorder::UnloadedStatus: case QMediaRecorder::UnloadedStatus:
case QMediaRecorder::LoadedStatus:
clearAudioLevels(); clearAudioLevels();
ui->recordButton->setText(tr("Record")); ui->recordButton->setText(tr("Record"));
ui->pauseButton->setText(tr("Pause")); ui->pauseButton->setText(tr("Pause"));

View File

@@ -110,6 +110,7 @@ FocusScope {
text: "Fluorescent" text: "Fluorescent"
} }
} }
onValueChanged: captureControls.camera.imageProcessing.whiteBalanceMode = wbModesButton.value
} }
CameraButton { CameraButton {

View File

@@ -47,6 +47,8 @@ Item {
property real maximumZoom : 1 property real maximumZoom : 1
signal zoomTo(real value) signal zoomTo(real value)
visible: zoomControl.maximumZoom > 1
MouseArea { MouseArea {
id : mouseArea id : mouseArea
anchors.fill: parent anchors.fill: parent
@@ -61,7 +63,7 @@ Item {
onPositionChanged: { onPositionChanged: {
if (pressed) { if (pressed) {
var target = initialZoom * Math.pow(2, (initialPos-mouseY)/zoomControl.height); var target = initialZoom * Math.pow(5, (initialPos-mouseY)/zoomControl.height);
target = Math.max(1, Math.min(target, zoomControl.maximumZoom)) target = Math.max(1, Math.min(target, zoomControl.maximumZoom))
zoomControl.zoomTo(target) zoomControl.zoomTo(target)
} }
@@ -74,45 +76,42 @@ Item {
y : parent.height/4 y : parent.height/4
width : 24 width : 24
height : parent.height/2 height : parent.height/2
opacity : 0
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
smooth: true smooth: true
radius: 8 radius: 8
border.color: "black" border.color: "white"
border.width: 2 border.width: 2
color: "white" color: "black"
opacity: 0.3 opacity: 0.3
} }
Rectangle { Rectangle {
id: groove
x : 0 x : 0
y : parent.height * (1.0 - (zoomControl.currentZoom-1.0) / (zoomControl.maximumZoom-1.0)) y : parent.height * (1.0 - (zoomControl.currentZoom-1.0) / (zoomControl.maximumZoom-1.0))
width: parent.width width: parent.width
height: parent.height - y height: parent.height - y
smooth: true smooth: true
radius: 8 radius: 8
color: "black" color: "white"
opacity: 0.5 opacity: 0.5
} }
states: State { Text {
name: "ShowBar" id: zoomText
when: mouseArea.pressed || zoomControl.currentZoom > 1.0 anchors {
PropertyChanges { target: bar; opacity: 1 } left: bar.right; leftMargin: 16
}
transitions: [
Transition {
to : "ShowBar"
NumberAnimation { properties: "opacity"; duration: 100 }
},
Transition {
from : "ShowBar"
NumberAnimation { properties: "opacity"; duration: 500 }
} }
] y: Math.min(parent.height - height, Math.max(0, groove.y - height / 2))
text: "x" + Math.round(zoomControl.currentZoom * 100) / 100
font.bold: true
color: "white"
style: Text.Raised; styleColor: "black"
opacity: 0.85
font.pixelSize: 18
}
} }
} }

View File

@@ -72,7 +72,11 @@ bool QGstAppSrc::setup(GstElement* appsrc)
if (m_setup || m_stream == 0 || appsrc == 0) if (m_setup || m_stream == 0 || appsrc == 0)
return false; return false;
if (m_appSrc)
gst_object_unref(G_OBJECT(m_appSrc));
m_appSrc = GST_APP_SRC(appsrc); m_appSrc = GST_APP_SRC(appsrc);
gst_object_ref(G_OBJECT(m_appSrc));
gst_app_src_set_callbacks(m_appSrc, (GstAppSrcCallbacks*)&m_callbacks, this, (GDestroyNotify)&QGstAppSrc::destroy_notify); gst_app_src_set_callbacks(m_appSrc, (GstAppSrcCallbacks*)&m_callbacks, this, (GDestroyNotify)&QGstAppSrc::destroy_notify);
g_object_get(G_OBJECT(m_appSrc), "max-bytes", &m_maxBytes, NULL); g_object_get(G_OBJECT(m_appSrc), "max-bytes", &m_maxBytes, NULL);

View File

@@ -93,6 +93,9 @@ QGstCodecsInfo::QGstCodecsInfo(QGstCodecsInfo::ElementType elementType)
gst_caps_remove_structure(caps, 0); gst_caps_remove_structure(caps, 0);
} }
gst_caps_unref(caps);
gst_caps_unref(allCaps);
#else #else
Q_UNUSED(elementType); Q_UNUSED(elementType);
#endif // GST_CHECK_VERSION(0,10,31) #endif // GST_CHECK_VERSION(0,10,31)
@@ -143,7 +146,7 @@ GstCaps* QGstCodecsInfo::supportedElementCaps(GstElementFactoryListType elementT
padTemplates = padTemplates->next; padTemplates = padTemplates->next;
if (padTemplate->direction == padDirection) { if (padTemplate->direction == padDirection) {
const GstCaps *caps = gst_static_caps_get(&padTemplate->static_caps); GstCaps *caps = gst_static_caps_get(&padTemplate->static_caps);
for (uint i=0; i<gst_caps_get_size(caps); i++) { for (uint i=0; i<gst_caps_get_size(caps); i++) {
const GstStructure *structure = gst_caps_get_structure(caps, i); const GstStructure *structure = gst_caps_get_structure(caps, i);
@@ -173,6 +176,7 @@ GstCaps* QGstCodecsInfo::supportedElementCaps(GstElementFactoryListType elementT
gst_caps_merge_structure(res, newStructure); gst_caps_merge_structure(res, newStructure);
} }
gst_caps_unref(caps);
} }
} }
} }

View File

@@ -216,6 +216,7 @@ GstElement *QGstreamerGLTextureRenderer::videoSink()
GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink"); GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink");
m_bufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padBufferProbe), this); m_bufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padBufferProbe), this);
gst_object_unref(GST_OBJECT(pad));
} }
} }

View File

@@ -41,6 +41,7 @@
#include "qgstreamervideorenderer_p.h" #include "qgstreamervideorenderer_p.h"
#include <private/qvideosurfacegstsink_p.h> #include <private/qvideosurfacegstsink_p.h>
#include <private/qgstutils_p.h>
#include <qabstractvideosurface.h> #include <qabstractvideosurface.h>
#include <QDebug> #include <QDebug>
@@ -62,8 +63,7 @@ GstElement *QGstreamerVideoRenderer::videoSink()
{ {
if (!m_videoSink && m_surface) { if (!m_videoSink && m_surface) {
m_videoSink = QVideoSurfaceGstSink::createSink(m_surface); m_videoSink = QVideoSurfaceGstSink::createSink(m_surface);
gst_object_ref(GST_OBJECT(m_videoSink)); //Take ownership qt_gst_object_ref_sink(GST_OBJECT(m_videoSink)); //Take ownership
gst_object_sink(GST_OBJECT(m_videoSink));
} }
return reinterpret_cast<GstElement*>(m_videoSink); return reinterpret_cast<GstElement*>(m_videoSink);

View File

@@ -137,8 +137,7 @@ void QGstreamerVideoWidgetControl::createVideoWidget()
if (!m_videoSink) if (!m_videoSink)
m_videoSink = gst_element_factory_make ("ximagesink", NULL); m_videoSink = gst_element_factory_make ("ximagesink", NULL);
gst_object_ref (GST_OBJECT (m_videoSink)); //Take ownership qt_gst_object_ref_sink(GST_OBJECT (m_videoSink)); //Take ownership
gst_object_sink (GST_OBJECT (m_videoSink));
} }
@@ -219,6 +218,7 @@ void QGstreamerVideoWidgetControl::updateNativeVideoSize()
//find video native size to update video widget size hint //find video native size to update video widget size hint
GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink"); GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink");
GstCaps *caps = gst_pad_get_negotiated_caps(pad); GstCaps *caps = gst_pad_get_negotiated_caps(pad);
gst_object_unref(GST_OBJECT(pad));
if (caps) { if (caps) {
m_widget->setNativeSize(QGstUtils::capsCorrectedResolution(caps)); m_widget->setNativeSize(QGstUtils::capsCorrectedResolution(caps));

View File

@@ -63,11 +63,11 @@ QGstreamerVideoWindow::QGstreamerVideoWindow(QObject *parent, const char *elemen
m_videoSink = gst_element_factory_make("xvimagesink", NULL); m_videoSink = gst_element_factory_make("xvimagesink", NULL);
if (m_videoSink) { if (m_videoSink) {
gst_object_ref(GST_OBJECT(m_videoSink)); //Take ownership qt_gst_object_ref_sink(GST_OBJECT(m_videoSink)); //Take ownership
gst_object_sink(GST_OBJECT(m_videoSink));
GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink"); GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink");
m_bufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padBufferProbe), this); m_bufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padBufferProbe), this);
gst_object_unref(GST_OBJECT(pad));
} }
} }
@@ -114,6 +114,7 @@ bool QGstreamerVideoWindow::processSyncMessage(const QGstreamerMessage &message)
GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink"); GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink");
m_bufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padBufferProbe), this); m_bufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padBufferProbe), this);
gst_object_unref(GST_OBJECT(pad));
return true; return true;
} }
@@ -319,6 +320,7 @@ void QGstreamerVideoWindow::updateNativeVideoSize()
//find video native size to update video widget size hint //find video native size to update video widget size hint
GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink"); GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink");
GstCaps *caps = gst_pad_get_negotiated_caps(pad); GstCaps *caps = gst_pad_get_negotiated_caps(pad);
gst_object_unref(GST_OBJECT(pad));
if (caps) { if (caps) {
m_nativeSize = QGstUtils::capsCorrectedResolution(caps); m_nativeSize = QGstUtils::capsCorrectedResolution(caps);

View File

@@ -401,4 +401,22 @@ QMultimedia::SupportEstimate QGstUtils::hasSupport(const QString &mimeType,
return QMultimedia::MaybeSupported; return QMultimedia::MaybeSupported;
} }
void qt_gst_object_ref_sink(gpointer object)
{
#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 24)
gst_object_ref_sink(object);
#else
g_return_if_fail (GST_IS_OBJECT(object));
GST_OBJECT_LOCK(object);
if (G_LIKELY(GST_OBJECT_IS_FLOATING(object))) {
GST_OBJECT_FLAG_UNSET(object, GST_OBJECT_FLOATING);
GST_OBJECT_UNLOCK(object);
} else {
GST_OBJECT_UNLOCK(object);
gst_object_ref(object);
}
#endif
}
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@@ -140,7 +140,7 @@ void QDeclarativeAttenuationModel::setName(const QString& name)
*/ */
/*! /*!
\qmlproperty string QtAudioEngine1::AttenuationModelLinear::name \qmlproperty string QtAudioEngine::AttenuationModelLinear::name
This property holds the name of AttenuationModelLinear, must be unique among all attenuation This property holds the name of AttenuationModelLinear, must be unique among all attenuation
models and only defined once. models and only defined once.
@@ -162,7 +162,7 @@ void QDeclarativeAttenuationModelLinear::componentComplete()
} }
/*! /*!
\qmlproperty real QtAudioEngine1::AttenuationModelLinear::start \qmlproperty real QtAudioEngine::AttenuationModelLinear::start
This property holds the start distance. There will be no attenuation if the distance from sound This property holds the start distance. There will be no attenuation if the distance from sound
to listener is within this range. to listener is within this range.
@@ -187,7 +187,7 @@ void QDeclarativeAttenuationModelLinear::setStartDistance(qreal startDist)
} }
/*! /*!
\qmlproperty real QtAudioEngine1::AttenuationModelLinear::end \qmlproperty real QtAudioEngine::AttenuationModelLinear::end
This property holds the end distance. There will be no sound hearable if the distance from sound This property holds the end distance. There will be no sound hearable if the distance from sound
to listener is larger than this. to listener is larger than this.
@@ -280,14 +280,14 @@ qreal QDeclarativeAttenuationModelLinear::calculateGain(const QVector3D &listene
*/ */
/*! /*!
\qmlproperty string QtAudioEngine1::AttenuationModelInverse::name \qmlproperty string QtAudioEngine::AttenuationModelInverse::name
This property holds the name of AttenuationModelInverse, must be unique among all attenuation This property holds the name of AttenuationModelInverse, must be unique among all attenuation
models and only defined once. models and only defined once.
*/ */
/*! /*!
\qmlproperty real QtAudioEngine1::AttenuationModelInverse::start \qmlproperty real QtAudioEngine::AttenuationModelInverse::start
This property holds the start distance. There will be no attenuation if the distance from sound This property holds the start distance. There will be no attenuation if the distance from sound
to listener is within this range. to listener is within this range.
@@ -295,7 +295,7 @@ qreal QDeclarativeAttenuationModelLinear::calculateGain(const QVector3D &listene
*/ */
/*! /*!
\qmlproperty real QtAudioEngine1::AttenuationModelInverse::end \qmlproperty real QtAudioEngine::AttenuationModelInverse::end
This property holds the end distance. There will be no further attenuation if the distance from This property holds the end distance. There will be no further attenuation if the distance from
sound to listener is larger than this. sound to listener is larger than this.
@@ -303,7 +303,7 @@ qreal QDeclarativeAttenuationModelLinear::calculateGain(const QVector3D &listene
*/ */
/*! /*!
\qmlproperty real QtAudioEngine1::AttenuationModelInverse::rolloff \qmlproperty real QtAudioEngine::AttenuationModelInverse::rolloff
This property holds the rolloff factor. The bigger the value is, the faster the sound attenuates. This property holds the rolloff factor. The bigger the value is, the faster the sound attenuates.
The default value is 1. The default value is 1.

View File

@@ -58,8 +58,8 @@ QT_USE_NAMESPACE
This type is part of the \b{QtAudioEngine 1.0} module. This type is part of the \b{QtAudioEngine 1.0} module.
An instance of AudioCategory can be accessed through QtAudioEngine1::AudioEngine::categories with its An instance of AudioCategory can be accessed through \l {QtAudioEngine::AudioEngine::categories}
unique name and must be defined inside AudioEngine. {AudioEngine.categories} with its unique name and must be defined inside AudioEngine.
\qml \qml
import QtQuick 2.0 import QtQuick 2.0
@@ -138,7 +138,7 @@ void QDeclarativeAudioCategory::componentComplete()
} }
/*! /*!
\qmlproperty real QtAudioEngine1::AudioCategory::volume \qmlproperty real QtAudioEngine::AudioCategory::volume
This property holds the volume of the category and will modulate all audio output from the This property holds the volume of the category and will modulate all audio output from the
instances which belong to this category. instances which belong to this category.
@@ -160,7 +160,7 @@ void QDeclarativeAudioCategory::setVolume(qreal volume)
} }
/*! /*!
\qmlproperty string QtAudioEngine1::AudioCategory::name \qmlproperty string QtAudioEngine::AudioCategory::name
This property holds the name of AudioCategory. The name must be unique among all categories and only This property holds the name of AudioCategory. The name must be unique among all categories and only
defined once. The name cannot be changed after the instance has been initialized. defined once. The name cannot be changed after the instance has been initialized.
@@ -180,7 +180,7 @@ QString QDeclarativeAudioCategory::name() const
} }
/*! /*!
\qmlmethod QtAudioEngine1::AudioCategory::stop() \qmlmethod QtAudioEngine::AudioCategory::stop()
Stops all active sound instances which belong to this category. Stops all active sound instances which belong to this category.
*/ */
@@ -190,7 +190,7 @@ void QDeclarativeAudioCategory::stop()
} }
/*! /*!
\qmlmethod QtAudioEngine1::AudioCategory::pause() \qmlmethod QtAudioEngine::AudioCategory::pause()
Pauses all active sound instances which belong to this category. Pauses all active sound instances which belong to this category.
*/ */
@@ -200,7 +200,7 @@ void QDeclarativeAudioCategory::pause()
} }
/*! /*!
\qmlmethod QtAudioEngine1::AudioCategory::pause() \qmlmethod QtAudioEngine::AudioCategory::pause()
Resumes all active sound instances from paused state which belong to this category. Resumes all active sound instances from paused state which belong to this category.
*/ */

View File

@@ -195,7 +195,7 @@ void QDeclarativeAudioEngine::releaseManagedDeclarativeSoundInstance(QDeclarativ
} }
/*! /*!
\qmlproperty int QtAudioEngine1::AudioEngine::liveInstances \qmlproperty int QtAudioEngine::AudioEngine::liveInstances
This property indicates how many live sound instances there are at the moment. This property indicates how many live sound instances there are at the moment.
*/ */
@@ -408,7 +408,7 @@ QQmlListProperty<QObject> QDeclarativeAudioEngine::bank()
} }
/*! /*!
\qmlproperty map QtAudioEngine1::AudioEngine::categories \qmlproperty map QtAudioEngine::AudioEngine::categories
Container of all AudioCategory instances. Container of all AudioCategory instances.
*/ */
@@ -418,7 +418,7 @@ QObject* QDeclarativeAudioEngine::categories()
} }
/*! /*!
\qmlproperty map QtAudioEngine1::AudioEngine::samples \qmlproperty map QtAudioEngine::AudioEngine::samples
Container of all AudioSample instances. Container of all AudioSample instances.
*/ */
@@ -428,7 +428,7 @@ QObject* QDeclarativeAudioEngine::samples()
} }
/*! /*!
\qmlproperty map QtAudioEngine1::AudioEngine::sounds \qmlproperty map QtAudioEngine::AudioEngine::sounds
Container of all Sound instances. Container of all Sound instances.
*/ */
@@ -438,7 +438,7 @@ QObject* QDeclarativeAudioEngine::sounds()
} }
/*! /*!
\qmlproperty QtAudioEngine1::AudioListener QtAudioEngine1::AudioEngine::listener \qmlproperty QtAudioEngine::AudioListener QtAudioEngine::AudioEngine::listener
This property holds the listener object. You can change various This property holds the listener object. You can change various
properties to affect the 3D positioning of sounds. properties to affect the 3D positioning of sounds.
@@ -451,7 +451,7 @@ QDeclarativeAudioListener* QDeclarativeAudioEngine::listener() const
} }
/*! /*!
\qmlproperty real QtAudioEngine1::AudioEngine::dopplerFactor \qmlproperty real QtAudioEngine::AudioEngine::dopplerFactor
This property holds a simple scaling for the effect of doppler shift. This property holds a simple scaling for the effect of doppler shift.
*/ */
@@ -466,7 +466,7 @@ void QDeclarativeAudioEngine::setDopplerFactor(qreal dopplerFactor)
} }
/*! /*!
\qmlproperty real QtAudioEngine1::AudioEngine::speedOfSound \qmlproperty real QtAudioEngine::AudioEngine::speedOfSound
This property holds the reference value of the sound speed (in meters per second) This property holds the reference value of the sound speed (in meters per second)
which will be used in doppler shift calculation. The doppler shift calculation is which will be used in doppler shift calculation. The doppler shift calculation is
@@ -485,7 +485,7 @@ void QDeclarativeAudioEngine::setSpeedOfSound(qreal speedOfSound)
} }
/*! /*!
\qmlproperty bool QtAudioEngine1::AudioEngine::loading \qmlproperty bool QtAudioEngine::AudioEngine::loading
This property indicates if the audio engine is loading any audio sample at the moment. This may This property indicates if the audio engine is loading any audio sample at the moment. This may
be useful if you specified the preloaded property in AudioSample and would like to show a loading screen be useful if you specified the preloaded property in AudioSample and would like to show a loading screen
@@ -505,7 +505,7 @@ void QDeclarativeAudioEngine::handleLoadingChanged()
} }
/*! /*!
\qmlsignal QtAudioEngine1::AudioEngine::finishedLoading() \qmlsignal QtAudioEngine::AudioEngine::finishedLoading()
This signal is emitted when \l loading has completed. This signal is emitted when \l loading has completed.
@@ -513,7 +513,7 @@ void QDeclarativeAudioEngine::handleLoadingChanged()
*/ */
/*! /*!
\qmlsignal QtAudioEngine1::AudioEngine::ready() \qmlsignal QtAudioEngine::AudioEngine::ready()
This signal is emitted when the AudioEngine is ready to use. This signal is emitted when the AudioEngine is ready to use.
@@ -521,7 +521,7 @@ void QDeclarativeAudioEngine::handleLoadingChanged()
*/ */
/*! /*!
\qmlsignal QtAudioEngine1::AudioEngine::liveInstanceCountChanged() \qmlsignal QtAudioEngine::AudioEngine::liveInstanceCountChanged()
This signal is emitted when the number of live instances managed by the This signal is emitted when the number of live instances managed by the
AudioEngine is changed. AudioEngine is changed.
@@ -530,7 +530,7 @@ void QDeclarativeAudioEngine::handleLoadingChanged()
*/ */
/*! /*!
\qmlsignal QtAudioEngine1::AudioEngine::isLoadingChanged() \qmlsignal QtAudioEngine::AudioEngine::isLoadingChanged()
This signal is emitted when the \l loading property changes. This signal is emitted when the \l loading property changes.

View File

@@ -88,11 +88,10 @@ QT_USE_NAMESPACE
loops: Animation.Infinite loops: Animation.Infinite
running: true running: true
NumberAnimation { NumberAnimation {
duration: 8000 duration: 8000
from: 0 from: 0
to: 1 to: 1
} }
} }
} }
} }
@@ -130,17 +129,16 @@ QT_USE_NAMESPACE
loops: Animation.Infinite loops: Animation.Infinite
running: true running: true
NumberAnimation { NumberAnimation {
duration: 8000 duration: 8000
from: 0 from: 0
to: 1 to: 1
} }
} }
} }
} }
\endqml \endqml
This separate AudioListener definition is allowed to make qml bindings easier in some case. This separate AudioListener definition is allowed to make QML bindings easier in some cases.
*/ */
QDeclarativeAudioListener::QDeclarativeAudioListener(QObject *parent) QDeclarativeAudioListener::QDeclarativeAudioListener(QObject *parent)
@@ -155,9 +153,9 @@ QDeclarativeAudioListener::~QDeclarativeAudioListener()
} }
/*! /*!
\qmlproperty QtAudioEngine1::AudioEngine QtAudioEngine1::AudioListener::engine \qmlproperty QtAudioEngine::AudioEngine QtAudioEngine::AudioListener::engine
This property holds the reference to AudioEngine, must be set only once. This property holds the reference to AudioEngine, and must only be set once.
*/ */
QDeclarativeAudioEngine* QDeclarativeAudioListener::engine() const QDeclarativeAudioEngine* QDeclarativeAudioListener::engine() const
{ {
@@ -171,9 +169,9 @@ void QDeclarativeAudioListener::setEngine(QDeclarativeAudioEngine *engine)
} }
/*! /*!
\qmlproperty vector3d QtAudioEngine1::AudioListener::position \qmlproperty vector3d QtAudioEngine::AudioListener::position
This property holds the 3d position of the listener. This property holds the 3D position of the listener.
*/ */
QVector3D QDeclarativeAudioListener::position() const QVector3D QDeclarativeAudioListener::position() const
{ {
@@ -190,9 +188,9 @@ void QDeclarativeAudioListener::setPosition(const QVector3D &position)
} }
/*! /*!
\qmlproperty vector3d QtAudioEngine1::AudioListener::direction \qmlproperty vector3d QtAudioEngine::AudioListener::direction
This property holds the normalized 3d direction vector of the listener. This property holds the normalized 3D direction vector of the listener.
*/ */
QVector3D QDeclarativeAudioListener::direction() const QVector3D QDeclarativeAudioListener::direction() const
{ {
@@ -209,9 +207,9 @@ void QDeclarativeAudioListener::setDirection(const QVector3D &direction)
} }
/*! /*!
\qmlproperty vector3d QtAudioEngine1::AudioListener::velocity \qmlproperty vector3d QtAudioEngine::AudioListener::velocity
This property holds the 3d velocity vector of the listener. This property holds the 3D velocity vector of the listener.
*/ */
QVector3D QDeclarativeAudioListener::velocity() const QVector3D QDeclarativeAudioListener::velocity() const
{ {
@@ -228,9 +226,9 @@ void QDeclarativeAudioListener::setVelocity(const QVector3D &velocity)
} }
/*! /*!
\qmlproperty vector3d QtAudioEngine1::AudioListener::up \qmlproperty vector3d QtAudioEngine::AudioListener::up
This property holds the normalized 3d up vector of the listener. This property holds the normalized 3D up vector of the listener.
*/ */
QVector3D QDeclarativeAudioListener::up() const QVector3D QDeclarativeAudioListener::up() const
{ {
@@ -247,7 +245,7 @@ void QDeclarativeAudioListener::setUp(const QVector3D &up)
} }
/*! /*!
\qmlproperty real QtAudioEngine1::AudioListener::gain \qmlproperty real QtAudioEngine::AudioListener::gain
This property will modulate all audio output from audio engine instances. This property will modulate all audio output from audio engine instances.
*/ */

View File

@@ -61,7 +61,7 @@ QT_USE_NAMESPACE
\c AudioSample is part of the \b{QtAudioEngine 1.0} module. \c AudioSample is part of the \b{QtAudioEngine 1.0} module.
It can be accessed through QtAudioEngine1::AudioEngine::samples with its unique It can be accessed through QtAudioEngine::AudioEngine::samples with its unique
name and must be defined inside AudioEngine. name and must be defined inside AudioEngine.
\qml \qml
@@ -134,11 +134,12 @@ bool QDeclarativeAudioSample::isStreaming() const
} }
/*! /*!
\qmlproperty bool QtAudioEngine1::AudioSample::preloaded \qmlproperty bool QtAudioEngine::AudioSample::preloaded
This property indicates whether this sample needs to be preloaded or not. This property indicates whether this sample needs to be preloaded or not.
If true, the audio engine will start loading the sample file immediately when the app started, If \c true, the audio engine will start loading the sample file immediately
otherwise the sample will not be loaded until explicitly requested. when the application starts, otherwise the sample will not be loaded until
explicitly requested.
*/ */
bool QDeclarativeAudioSample::isPreloaded() const bool QDeclarativeAudioSample::isPreloaded() const
@@ -147,7 +148,7 @@ bool QDeclarativeAudioSample::isPreloaded() const
} }
/*! /*!
\qmlproperty bool QtAudioEngine1::AudioSample::loaded \qmlproperty bool QtAudioEngine::AudioSample::loaded
This property indicates whether this sample has been loaded into memory or not. This property indicates whether this sample has been loaded into memory or not.
*/ */
@@ -159,7 +160,7 @@ bool QDeclarativeAudioSample::isLoaded() const
} }
/*! /*!
\qmlmethod void QtAudioEngine1::AudioSample::load() \qmlmethod void QtAudioEngine::AudioSample::load()
Starts loading the sample into memory if not loaded. Starts loading the sample into memory if not loaded.
*/ */
@@ -193,10 +194,10 @@ void QDeclarativeAudioSample::setStreaming(bool streaming)
} }
/*! /*!
\qmlproperty string QtAudioEngine1::AudioSample::name \qmlproperty string QtAudioEngine::AudioSample::name
This property holds the name of AudioSample, must be unique among all samples and only This property holds the name of the sample, which must be unique among all
defined once. samples and only defined once.
*/ */
QString QDeclarativeAudioSample::name() const QString QDeclarativeAudioSample::name() const
{ {
@@ -237,9 +238,11 @@ QSoundBuffer* QDeclarativeAudioSample::soundBuffer() const
} }
/*! /*!
\qmlsignal QtAudioEngine1::AudioSample::onLoadedChanged() \qmlsignal QtAudioEngine::AudioSample::loadedChanged()
This handler is called when \l loaded is changed This signal is emitted when \l loaded is changed.
The corresponding handler is \c onLoadedChanged.
*/ */

View File

@@ -143,7 +143,7 @@ void QDeclarativePlayVariation::componentComplete()
} }
/*! /*!
\qmlproperty string QtAudioEngine1::PlayVariation::sample \qmlproperty string QtAudioEngine::PlayVariation::sample
This property specifies which \l AudioSample this variation will use. This property specifies which \l AudioSample this variation will use.
*/ */
@@ -162,7 +162,7 @@ void QDeclarativePlayVariation::setSample(const QString& sample)
} }
/*! /*!
\qmlproperty bool QtAudioEngine1::PlayVariation::looping \qmlproperty bool QtAudioEngine::PlayVariation::looping
This property indicates whether the playback will be looped or not. This property indicates whether the playback will be looped or not.
*/ */
@@ -181,7 +181,7 @@ void QDeclarativePlayVariation::setLooping(bool looping)
} }
/*! /*!
\qmlproperty real QtAudioEngine1::PlayVariation::maxGain \qmlproperty real QtAudioEngine::PlayVariation::maxGain
This property specifies the maximum gain adjustment that can be applied in any playback. This property specifies the maximum gain adjustment that can be applied in any playback.
*/ */
@@ -204,7 +204,7 @@ void QDeclarativePlayVariation::setMaxGain(qreal maxGain)
} }
/*! /*!
\qmlproperty real QtAudioEngine1::PlayVariation::minGain \qmlproperty real QtAudioEngine::PlayVariation::minGain
This property specifies the minimum gain adjustment that can be applied in any playback. This property specifies the minimum gain adjustment that can be applied in any playback.
*/ */
@@ -227,7 +227,7 @@ void QDeclarativePlayVariation::setMinGain(qreal minGain)
} }
/*! /*!
\qmlproperty real QtAudioEngine1::PlayVariation::maxPitch \qmlproperty real QtAudioEngine::PlayVariation::maxPitch
This property specifies the maximum pitch adjustment that can be applied in any playback. This property specifies the maximum pitch adjustment that can be applied in any playback.
*/ */
@@ -250,7 +250,7 @@ void QDeclarativePlayVariation::setMaxPitch(qreal maxPitch)
} }
/*! /*!
\qmlproperty real QtAudioEngine1::PlayVariation::minPitch \qmlproperty real QtAudioEngine::PlayVariation::minPitch
This property specifies the minimum pitch adjustment that can be applied in any playback. This property specifies the minimum pitch adjustment that can be applied in any playback.
*/ */

View File

@@ -150,7 +150,7 @@ void QDeclarativeSoundCone::componentComplete()
This type is part of the \b{QtAudioEngine 1.0} module. This type is part of the \b{QtAudioEngine 1.0} module.
Sound can be accessed through QtAudioEngine1::AudioEngine::sounds with its unique name Sound can be accessed through QtAudioEngine::AudioEngine::sounds with its unique name
and must be defined inside AudioEngine. and must be defined inside AudioEngine.
\qml \qml
@@ -228,7 +228,7 @@ void QDeclarativeSound::componentComplete()
} }
/*! /*!
\qmlproperty enumeration QtAudioEngine1::Sound::playType \qmlproperty enumeration QtAudioEngine::Sound::playType
This property holds the playType. It can be one of: This property holds the playType. It can be one of:
@@ -254,7 +254,7 @@ void QDeclarativeSound::setPlayType(PlayType playType)
} }
/*! /*!
\qmlproperty string QtAudioEngine1::Sound::category \qmlproperty string QtAudioEngine::Sound::category
This property specifies which AudioCategory this sound belongs to. This property specifies which AudioCategory this sound belongs to.
*/ */
@@ -273,7 +273,7 @@ void QDeclarativeSound::setCategory(const QString& category)
} }
/*! /*!
\qmlproperty string QtAudioEngine1::Sound::name \qmlproperty string QtAudioEngine::Sound::name
This property holds the name of Sound, must be unique among all sounds and only This property holds the name of Sound, must be unique among all sounds and only
defined once. defined once.
@@ -293,7 +293,7 @@ void QDeclarativeSound::setName(const QString& name)
} }
/*! /*!
\qmlproperty string QtAudioEngine1::Sound::attenuationModel \qmlproperty string QtAudioEngine::Sound::attenuationModel
This property specifies which attenuation model this sound will apply. This property specifies which attenuation model this sound will apply.
*/ */
@@ -382,7 +382,7 @@ void QDeclarativeSound::appendFunction(QQmlListProperty<QDeclarativePlayVariatio
} }
/*! /*!
\qmlmethod QtAudioEngine1::Sound::play() \qmlmethod QtAudioEngine::Sound::play()
Creates a new \l SoundInstance and starts playing. Creates a new \l SoundInstance and starts playing.
Position, direction and velocity are all set to \c "0,0,0". Position, direction and velocity are all set to \c "0,0,0".
@@ -393,7 +393,7 @@ void QDeclarativeSound::play()
} }
/*! /*!
\qmlmethod QtAudioEngine1::Sound::play(gain) \qmlmethod QtAudioEngine::Sound::play(gain)
Creates a new SoundInstance and starts playing with the adjusted \a gain. Creates a new SoundInstance and starts playing with the adjusted \a gain.
Position, direction and velocity are all set to \c "0,0,0". Position, direction and velocity are all set to \c "0,0,0".
@@ -404,7 +404,7 @@ void QDeclarativeSound::play(qreal gain)
} }
/*! /*!
\qmlmethod QtAudioEngine1::Sound::play(gain, pitch) \qmlmethod QtAudioEngine::Sound::play(gain, pitch)
Creates a new SoundInstance and starts playing with the adjusted \a gain and \a pitch. Creates a new SoundInstance and starts playing with the adjusted \a gain and \a pitch.
Position, direction and velocity are all set to \c "0,0,0". Position, direction and velocity are all set to \c "0,0,0".
@@ -415,7 +415,7 @@ void QDeclarativeSound::play(qreal gain, qreal pitch)
} }
/*! /*!
\qmlmethod QtAudioEngine1::Sound::play(position) \qmlmethod QtAudioEngine::Sound::play(position)
Creates a new SoundInstance and starts playing with specified \a position. Creates a new SoundInstance and starts playing with specified \a position.
Direction and velocity are all set to \c "0,0,0". Direction and velocity are all set to \c "0,0,0".
@@ -426,7 +426,7 @@ void QDeclarativeSound::play(const QVector3D& position)
} }
/*! /*!
\qmlmethod QtAudioEngine1::Sound::play(position, velocity) \qmlmethod QtAudioEngine::Sound::play(position, velocity)
Creates a new SoundInstance and starts playing with specified \a position and \a velocity. Creates a new SoundInstance and starts playing with specified \a position and \a velocity.
Direction is set to \c "0,0,0". Direction is set to \c "0,0,0".
@@ -437,7 +437,7 @@ void QDeclarativeSound::play(const QVector3D& position, const QVector3D& velocit
} }
/*! /*!
\qmlmethod QtAudioEngine1::Sound::play(position, velocity, direction) \qmlmethod QtAudioEngine::Sound::play(position, velocity, direction)
Creates a new SoundInstance and starts playing with specified \a position, \a velocity and Creates a new SoundInstance and starts playing with specified \a position, \a velocity and
\a direction. \a direction.
@@ -449,7 +449,7 @@ void QDeclarativeSound::play(const QVector3D& position, const QVector3D& velocit
} }
/*! /*!
\qmlmethod QtAudioEngine1::Sound::play(position, gain) \qmlmethod QtAudioEngine::Sound::play(position, gain)
Creates a new SoundInstance and starts playing with specified \a position and adjusted \a gain. Creates a new SoundInstance and starts playing with specified \a position and adjusted \a gain.
Direction and velocity are all set to \c "0,0,0". Direction and velocity are all set to \c "0,0,0".
@@ -460,7 +460,7 @@ void QDeclarativeSound::play(const QVector3D& position, qreal gain)
} }
/*! /*!
\qmlmethod QtAudioEngine1::Sound::play(position, velocity, gain) \qmlmethod QtAudioEngine::Sound::play(position, velocity, gain)
Creates a new SoundInstance and starts playing with specified \a position, \a velocity and Creates a new SoundInstance and starts playing with specified \a position, \a velocity and
adjusted \a gain. adjusted \a gain.
@@ -472,7 +472,7 @@ void QDeclarativeSound::play(const QVector3D& position, const QVector3D& velocit
} }
/*! /*!
\qmlmethod QtAudioEngine1::Sound::play(position, velocity, direction, gain) \qmlmethod QtAudioEngine::Sound::play(position, velocity, direction, gain)
Creates a new SoundInstance and starts playing with specified \a position, \a velocity, Creates a new SoundInstance and starts playing with specified \a position, \a velocity,
\a direction and adjusted \a gain. \a direction and adjusted \a gain.
@@ -483,7 +483,7 @@ void QDeclarativeSound::play(const QVector3D& position, const QVector3D& velocit
} }
/*! /*!
\qmlmethod QtAudioEngine1::Sound::play(position, gain, pitch) \qmlmethod QtAudioEngine::Sound::play(position, gain, pitch)
Creates a new SoundInstance and starts playing with specified \a position, adjusted \a gain and Creates a new SoundInstance and starts playing with specified \a position, adjusted \a gain and
\a pitch. \a pitch.
@@ -495,7 +495,7 @@ void QDeclarativeSound::play(const QVector3D& position, qreal gain, qreal pitch)
} }
/*! /*!
\qmlmethod QtAudioEngine1::Sound::play(position, velocity, gain, pitch) \qmlmethod QtAudioEngine::Sound::play(position, velocity, gain, pitch)
Creates a new SoundInstance and starts playing with specified \a position, \a velocity, Creates a new SoundInstance and starts playing with specified \a position, \a velocity,
adjusted \a gain and \a pitch. adjusted \a gain and \a pitch.
@@ -507,7 +507,7 @@ void QDeclarativeSound::play(const QVector3D& position, const QVector3D& velocit
} }
/*! /*!
\qmlmethod QtAudioEngine1::Sound::play(position, velocity, direction, gain, pitch) \qmlmethod QtAudioEngine::Sound::play(position, velocity, direction, gain, pitch)
Creates a new SoundInstance and starts playing with specified \a position, \a velocity, Creates a new SoundInstance and starts playing with specified \a position, \a velocity,
\a direction, adjusted \a gain and \a pitch. \a direction, adjusted \a gain and \a pitch.
@@ -542,7 +542,7 @@ void QDeclarativeSound::play(const QVector3D& position, const QVector3D& velocit
} }
/*! /*!
\qmlmethod QtAudioEngine1::SoundInstance QtAudioEngine1::Sound::newInstance() \qmlmethod QtAudioEngine::SoundInstance QtAudioEngine::Sound::newInstance()
Returns a new \l SoundInstance. Returns a new \l SoundInstance.
*/ */

View File

@@ -185,7 +185,7 @@ QDeclarativeSoundInstance::QDeclarativeSoundInstance(QObject *parent)
} }
/*! /*!
\qmlproperty QtAudioEngine1::AudioEngine QtAudioEngine1::SoundInstance::engine \qmlproperty QtAudioEngine::AudioEngine QtAudioEngine::SoundInstance::engine
This property holds the reference to AudioEngine, must be set only once. This property holds the reference to AudioEngine, must be set only once.
*/ */
@@ -234,7 +234,7 @@ QDeclarativeSoundInstance::~QDeclarativeSoundInstance()
} }
/*! /*!
\qmlproperty string QtAudioEngine1::SoundInstance::sound \qmlproperty string QtAudioEngine::SoundInstance::sound
This property specifies which Sound this SoundInstance will use. Unlike some properties in This property specifies which Sound this SoundInstance will use. Unlike some properties in
other types, this property can be changed dynamically. other types, this property can be changed dynamically.
@@ -294,7 +294,7 @@ void QDeclarativeSoundInstance::dropInstance()
} }
/*! /*!
\qmlproperty enumeration QtAudioEngine1::SoundInstance::state \qmlproperty enumeration QtAudioEngine::SoundInstance::state
This property holds the current playback state. It can be one of: This property holds the current playback state. It can be one of:
@@ -318,7 +318,7 @@ QDeclarativeSoundInstance::State QDeclarativeSoundInstance::state() const
} }
/*! /*!
\qmlmethod QtAudioEngine1::SoundInstance::play() \qmlmethod QtAudioEngine::SoundInstance::play()
Starts playback. Starts playback.
*/ */
@@ -335,7 +335,7 @@ void QDeclarativeSoundInstance::play()
} }
/*! /*!
\qmlmethod QtAudioEngine1::SoundInstance::play() \qmlmethod QtAudioEngine::SoundInstance::play()
Stops current playback. Stops current playback.
*/ */
@@ -351,7 +351,7 @@ void QDeclarativeSoundInstance::stop()
} }
/*! /*!
\qmlmethod QtAudioEngine1::SoundInstance::play() \qmlmethod QtAudioEngine::SoundInstance::play()
Pauses current playback. Pauses current playback.
*/ */
@@ -375,7 +375,7 @@ void QDeclarativeSoundInstance::updatePosition(qreal deltaTime)
} }
/*! /*!
\qmlproperty vector3d QtAudioEngine1::SoundInstance::position \qmlproperty vector3d QtAudioEngine::SoundInstance::position
This property holds the current 3d position. This property holds the current 3d position.
*/ */
@@ -397,7 +397,7 @@ void QDeclarativeSoundInstance::setPosition(const QVector3D& position)
} }
/*! /*!
\qmlproperty vector3d QtAudioEngine1::SoundInstance::direction \qmlproperty vector3d QtAudioEngine::SoundInstance::direction
This property holds the current 3d direction. This property holds the current 3d direction.
*/ */
@@ -419,7 +419,7 @@ void QDeclarativeSoundInstance::setDirection(const QVector3D& direction)
} }
/*! /*!
\qmlproperty vector3d QtAudioEngine1::SoundInstance::velocity \qmlproperty vector3d QtAudioEngine::SoundInstance::velocity
This property holds the current 3d velocity. This property holds the current 3d velocity.
*/ */
@@ -440,7 +440,7 @@ void QDeclarativeSoundInstance::setVelocity(const QVector3D& velocity)
} }
/*! /*!
\qmlproperty vector3d QtAudioEngine1::SoundInstance::gain \qmlproperty vector3d QtAudioEngine::SoundInstance::gain
This property holds the gain adjustment which will be used to modulate the audio output level This property holds the gain adjustment which will be used to modulate the audio output level
from this SoundInstance. from this SoundInstance.
@@ -466,7 +466,7 @@ void QDeclarativeSoundInstance::setGain(qreal gain)
} }
/*! /*!
\qmlproperty vector3d QtAudioEngine1::SoundInstance::pitch \qmlproperty vector3d QtAudioEngine::SoundInstance::pitch
This property holds the pitch adjustment which will be used to modulate the audio pitch This property holds the pitch adjustment which will be used to modulate the audio pitch
from this SoundInstance. from this SoundInstance.
@@ -527,43 +527,57 @@ void QDeclarativeSoundInstance::handleStateChanged()
} }
/*! /*!
\qmlsignal QtAudioEngine1::SoundInstance::onStateChanged(state) \qmlsignal QtAudioEngine::SoundInstance::stateChanged(state)
This handler is called when \l state is changed This signal is emitted when \l state is changed
The corresponding handler is \c onStateChanged.
*/ */
/*! /*!
\qmlsignal QtAudioEngine1::SoundInstance::onPositionChanged() \qmlsignal QtAudioEngine::SoundInstance::positionChanged()
This handler is called when \l position is changed This signal is emitted when \l position is changed
The corresponding handler is \c onPositionChanged.
*/ */
/*! /*!
\qmlsignal QtAudioEngine1::SoundInstance::onDirectionChanged() \qmlsignal QtAudioEngine::SoundInstance::directionChanged()
This handler is called when \l direction is changed This signal is emitted when \l direction is changed
The corresponding handler is \c onDirectionChanged.
*/ */
/*! /*!
\qmlsignal QtAudioEngine1::SoundInstance::onVelocityChanged() \qmlsignal QtAudioEngine::SoundInstance::velocityChanged()
This handler is called when \l velocity is changed This signal is emitted when \l velocity is changed
The corresponding handler is \c onVelocityChanged.
*/ */
/*! /*!
\qmlsignal QtAudioEngine1::SoundInstance::onGainChanged() \qmlsignal QtAudioEngine::SoundInstance::gainChanged()
This handler is called when \l gain is changed This signal is emitted when \l gain is changed
The corresponding handler is \c onGainChanged.
*/ */
/*! /*!
\qmlsignal QtAudioEngine1::SoundInstance::onPitchChanged() \qmlsignal QtAudioEngine::SoundInstance::pitchChanged()
This handler is called when \l pitch is changed This signal is emitted when \l pitch is changed
The corresponding handler is \c onPitchChanged.
*/ */
/*! /*!
\qmlsignal QtAudioEngine1::SoundInstance::onSoundChanged() \qmlsignal QtAudioEngine::SoundInstance::soundChanged()
This handler is called when \l sound is changed This signal is emitted when \l sound is changed
The corresponding handler is \c onSoundChanged.
*/ */

View File

@@ -328,6 +328,8 @@ Item {
\qmlsignal Video::paused() \qmlsignal Video::paused()
This signal is emitted when playback is paused. This signal is emitted when playback is paused.
The corresponding handler is \c onPaused.
*/ */
signal paused signal paused
@@ -335,6 +337,8 @@ Item {
\qmlsignal Video::stopped() \qmlsignal Video::stopped()
This signal is emitted when playback is stopped. This signal is emitted when playback is stopped.
The corresponding handler is \c onStopped.
*/ */
signal stopped signal stopped
@@ -342,6 +346,8 @@ Item {
\qmlsignal Video::playing() \qmlsignal Video::playing()
This signal is emitted when playback is started or continued. This signal is emitted when playback is started or continued.
The corresponding handler is \c onPlaying.
*/ */
signal playing signal playing

View File

@@ -457,32 +457,40 @@ void QDeclarativeAudio::seek(int position)
This property indicates if loading of media should begin immediately. This property indicates if loading of media should begin immediately.
Defaults to true, if false media will not be loaded until playback is started. Defaults to \c true. If \c false, the media will not be loaded until playback is started.
*/ */
/*! /*!
\qmlsignal QtMultimedia::Audio::playbackStateChanged() \qmlsignal QtMultimedia::Audio::playbackStateChanged()
This handler is called when the \l playbackState property is altered. This signal is emitted when the \l playbackState property is altered.
The corresponding handler is \c onPlaybackStateChanged.
*/ */
/*! /*!
\qmlsignal QtMultimedia::Audio::paused() \qmlsignal QtMultimedia::Audio::paused()
This handler is called when playback is paused. This signal is emitted when playback is paused.
The corresponding handler is \c onPaused.
*/ */
/*! /*!
\qmlsignal QtMultimedia::Audio::stopped() \qmlsignal QtMultimedia::Audio::stopped()
This handler is called when playback is stopped. This signal is emitted when playback is stopped.
The corresponding handler is \c onStopped.
*/ */
/*! /*!
\qmlsignal QtMultimedia::Audio::playing() \qmlsignal QtMultimedia::Audio::playing()
This handler is called when playback is started or resumed. This signal is emitted when playback is started or resumed.
The corresponding handler is \c onPlaying.
*/ */
/*! /*!
@@ -531,7 +539,7 @@ QDeclarativeAudio::PlaybackState QDeclarativeAudio::playbackState() const
This property controls whether the media will begin to play on start up. This property controls whether the media will begin to play on start up.
Defaults to false, if set true the value of autoLoad will be overwritten to true. Defaults to \c false. If set to \c true, the value of autoLoad will be overwritten to \c true.
*/ */
/*! /*!
@@ -760,9 +768,11 @@ void QDeclarativeAudio::_q_statusChanged()
/*! /*!
\qmlsignal QtMultimedia::Audio::error(error, errorString) \qmlsignal QtMultimedia::Audio::error(error, errorString)
This handler is called when an \l {QMediaPlayer::Error}{error} has This signal is emitted when an \l {QMediaPlayer::Error}{error} has
occurred. The errorString parameter may contain more detailed occurred. The errorString parameter may contain more detailed
information about the error. information about the error.
The corresponding handler is \c onError.
*/ */
/*! /*!
@@ -1267,26 +1277,34 @@ void QDeclarativeAudio::_q_statusChanged()
/*! /*!
\qmlsignal QtMultimedia::MediaPlayer::playbackStateChanged() \qmlsignal QtMultimedia::MediaPlayer::playbackStateChanged()
This handler is called when the \l playbackState property is altered. This signal is emitted when the \l playbackState property is altered.
The corresponding handler is \c onPlaybackStateChanged.
*/ */
/*! /*!
\qmlsignal QtMultimedia::MediaPlayer::paused() \qmlsignal QtMultimedia::MediaPlayer::paused()
This handler is called when playback is paused. This signal is emitted when playback is paused.
The corresponding handler is \c onPaused.
*/ */
/*! /*!
\qmlsignal QtMultimedia::MediaPlayer::stopped() \qmlsignal QtMultimedia::MediaPlayer::stopped()
This handler is called when playback is stopped. This signal is emitted when playback is stopped.
The corresponding handler is \c onStopped.
*/ */
/*! /*!
\qmlsignal QtMultimedia::MediaPlayer::playing() \qmlsignal QtMultimedia::MediaPlayer::playing()
This handler is called when playback is started or resumed. This signal is emitted when playback is started or resumed.
The corresponding handler is \c onPlaying.
*/ */
/*! /*!
@@ -1324,7 +1342,7 @@ void QDeclarativeAudio::_q_statusChanged()
This property controls whether the media will begin to play on start up. This property controls whether the media will begin to play on start up.
Defaults to false, if set true the value of autoLoad will be overwritten to true. Defaults to \c false. If set to \c true, the value of autoLoad will be overwritten to \c true.
*/ */
/*! /*!
@@ -1440,9 +1458,11 @@ void QDeclarativeAudio::_q_statusChanged()
/*! /*!
\qmlsignal QtMultimedia::MediaPlayer::error(error, errorString) \qmlsignal QtMultimedia::MediaPlayer::error(error, errorString)
This handler is called when an \l {QMediaPlayer::Error}{error} has This signal is emitted when an \l {QMediaPlayer::Error}{error} has
occurred. The errorString parameter may contain more detailed occurred. The errorString parameter may contain more detailed
information about the error. information about the error.
The corresponding handler is \c onError.
*/ */
/*! /*!

View File

@@ -227,7 +227,7 @@ QDeclarativeCamera::Error QDeclarativeCamera::errorCode() const
This property holds the last error string, if any. This property holds the last error string, if any.
\sa QtMultimedia::Camera::onError \sa error, errorCode
*/ */
QString QDeclarativeCamera::errorString() const QString QDeclarativeCamera::errorString() const
{ {
@@ -594,13 +594,13 @@ void QDeclarativeCamera::setDigitalZoom(qreal value)
This property holds the last error code. This property holds the last error code.
\sa QtMultimedia::Camera::onError \sa error, errorString
*/ */
/*! /*!
\qmlsignal QtMultimedia::Camera::onError(errorCode, errorString) \qmlsignal QtMultimedia::Camera::error(errorCode, errorString)
This handler is called when an error occurs. The enumeration value This signal is emitted when an error occurs. The enumeration value
\a errorCode is one of the values defined below, and a descriptive string \a errorCode is one of the values defined below, and a descriptive string
value is available in \a errorString. value is available in \a errorString.
@@ -612,6 +612,10 @@ void QDeclarativeCamera::setDigitalZoom(qreal value)
\row \li ServiceMissingError \li No camera service available. \row \li ServiceMissingError \li No camera service available.
\row \li NotSupportedFeatureError \li The feature is not supported. \row \li NotSupportedFeatureError \li The feature is not supported.
\endtable \endtable
The corresponding handler is \c onError.
\sa errorCode, errorString
*/ */
/*! /*!
@@ -619,6 +623,8 @@ void QDeclarativeCamera::setDigitalZoom(qreal value)
This signal is emitted when the lock status (focus, exposure etc) changes. This signal is emitted when the lock status (focus, exposure etc) changes.
This can happen when locking (e.g. autofocusing) is complete or has failed. This can happen when locking (e.g. autofocusing) is complete or has failed.
The corresponding handler is \c onLockStatusChanged.
*/ */
/*! /*!
@@ -627,34 +633,44 @@ void QDeclarativeCamera::setDigitalZoom(qreal value)
This signal is emitted when the camera state has changed to \a state. Since the This signal is emitted when the camera state has changed to \a state. Since the
state changes may take some time to occur this signal may arrive sometime state changes may take some time to occur this signal may arrive sometime
after the state change has been requested. after the state change has been requested.
The corresponding handler is \c onStateChanged.
*/ */
/*! /*!
\qmlsignal Camera::opticalZoomChanged(zoom) \qmlsignal Camera::opticalZoomChanged(zoom)
The optical zoom setting has changed to \a zoom. This signal is emitted when the optical zoom setting has changed to \a zoom.
The corresponding handler is \c onOpticalZoomChanged.
*/ */
/*! /*!
\qmlsignal Camera::digitalZoomChanged(zoom) \qmlsignal Camera::digitalZoomChanged(zoom)
The digital zoom setting has changed to \a zoom. This signal is emitted when the digital zoom setting has changed to \a zoom.
The corresponding handler is \c onDigitalZoomChanged.
*/ */
/*! /*!
\qmlsignal Camera::maximumOpticalZoomChanged(zoom) \qmlsignal Camera::maximumOpticalZoomChanged(zoom)
The maximum optical zoom setting has changed to \a zoom. This This signal is emitted when the maximum optical zoom setting has
can occur when you change between video and still image capture changed to \a zoom. This can occur when you change between video
modes, or the capture settings are changed. and still image capture modes, or the capture settings are changed.
The corresponding handler is \c onMaximumOpticalZoomChanged.
*/ */
/*! /*!
\qmlsignal Camera::maximumDigitalZoomChanged(zoom) \qmlsignal Camera::maximumDigitalZoomChanged(zoom)
The maximum digital zoom setting has changed to \a zoom. This This signal is emitted when the maximum digital zoom setting has
can occur when you change between video and still image capture changed to \a zoom. This can occur when you change between video
modes, or the capture settings are changed. and still image capture modes, or the capture settings are changed.
The corresponding handler is \c onMaximumDigitalZoomChanged.
*/ */
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@@ -156,7 +156,7 @@ bool QDeclarativeCameraCapture::isReadyForCapture() const
/*! /*!
\qmlmethod QtMultimedia::CameraCapture::capture() \qmlmethod QtMultimedia::CameraCapture::capture()
Start image capture. The \l onImageCaptured() and \l onImageSaved() signals will Start image capture. The \l imageCaptured and \l imageSaved signals will
be emitted when the capture is complete. be emitted when the capture is complete.
The image will be captured to the default system location, typically The image will be captured to the default system location, typically
@@ -179,7 +179,7 @@ int QDeclarativeCameraCapture::capture()
/*! /*!
\qmlmethod QtMultimedia::CameraCapture::captureToLocation(location) \qmlmethod QtMultimedia::CameraCapture::captureToLocation(location)
Start image capture to specified \a location. The \l onImageCaptured() and \l onImageSaved() signals will Start image capture to specified \a location. The \l imageCaptured and \l imageSaved signals will
be emitted when the capture is complete. be emitted when the capture is complete.
CameraCapture::captureToLocation returns the capture requestId parameter, used with CameraCapture::captureToLocation returns the capture requestId parameter, used with
@@ -310,39 +310,47 @@ void QDeclarativeCameraCapture::setMetadata(const QString &key, const QVariant &
} }
/*! /*!
\qmlsignal QtMultimedia::CameraCapture::onCaptureFailed(requestId, message) \qmlsignal QtMultimedia::CameraCapture::captureFailed(requestId, message)
This handler is called when an error occurs during capture with \a requestId. This signal is emitted when an error occurs during capture with \a requestId.
A descriptive message is available in \a message. A descriptive message is available in \a message.
The corresponding handler is \c onCaptureFailed.
*/ */
/*! /*!
\qmlsignal QtMultimedia::CameraCapture::onImageCaptured(requestId, preview) \qmlsignal QtMultimedia::CameraCapture::imageCaptured(requestId, preview)
This handler is called when an image with \a requestId has been captured This signal is emitted when an image with \a requestId has been captured
but not yet saved to the filesystem. The \a preview but not yet saved to the filesystem. The \a preview
parameter can be used as the URL supplied to an \l Image. parameter can be used as the URL supplied to an \l Image.
\sa onImageSaved The corresponding handler is \c onImageCaptured.
\sa imageSaved
*/ */
/*! /*!
\qmlsignal QtMultimedia::CameraCapture::onImageSaved(requestId, path) \qmlsignal QtMultimedia::CameraCapture::imageSaved(requestId, path)
This handler is called after the image with \a requestId has been written to the filesystem. This signal is emitted after the image with \a requestId has been written to the filesystem.
The \a path is a local file path, not a URL. The \a path is a local file path, not a URL.
\sa onImageCaptured The corresponding handler is \c onImageSaved.
\sa imageCaptured
*/ */
/*! /*!
\qmlsignal QtMultimedia::CameraCapture::onImageMetadataAvailable(requestId, key, value) \qmlsignal QtMultimedia::CameraCapture::imageMetadataAvailable(requestId, key, value)
This handler is called when the image with \a requestId has new metadata This signal is emitted when the image with \a requestId has new metadata
available with the key \a key and value \a value. available with the key \a key and value \a value.
\sa onImageCaptured The corresponding handler is \c onImageMetadataAvailable.
\sa imageCaptured
*/ */

View File

@@ -353,12 +353,12 @@ void QDeclarativeCameraExposure::setAutoIsoSensitivity()
\endtable \endtable
*/ */
QDeclarativeCamera::ExposureMode QDeclarativeCameraExposure::exposureMode() const QDeclarativeCameraExposure::ExposureMode QDeclarativeCameraExposure::exposureMode() const
{ {
return QDeclarativeCamera::ExposureMode(m_exposure->exposureMode()); return QDeclarativeCameraExposure::ExposureMode(m_exposure->exposureMode());
} }
void QDeclarativeCameraExposure::setExposureMode(QDeclarativeCamera::ExposureMode mode) void QDeclarativeCameraExposure::setExposureMode(QDeclarativeCameraExposure::ExposureMode mode)
{ {
if (exposureMode() != mode) { if (exposureMode() != mode) {
m_exposure->setExposureMode(QCameraExposure::ExposureMode(mode)); m_exposure->setExposureMode(QCameraExposure::ExposureMode(mode));
@@ -413,14 +413,14 @@ void QDeclarativeCameraExposure::setSpotMeteringPoint(const QPointF &point)
\row \li Camera.MeteringSpot \li A specific location (\l spotMeteringPoint) is used to measure exposure. \row \li Camera.MeteringSpot \li A specific location (\l spotMeteringPoint) is used to measure exposure.
\endtable \endtable
*/ */
QDeclarativeCamera::MeteringMode QDeclarativeCameraExposure::meteringMode() const QDeclarativeCameraExposure::MeteringMode QDeclarativeCameraExposure::meteringMode() const
{ {
return QDeclarativeCamera::MeteringMode(m_exposure->meteringMode()); return QDeclarativeCameraExposure::MeteringMode(m_exposure->meteringMode());
} }
void QDeclarativeCameraExposure::setMeteringMode(QDeclarativeCamera::MeteringMode mode) void QDeclarativeCameraExposure::setMeteringMode(QDeclarativeCameraExposure::MeteringMode mode)
{ {
QDeclarativeCamera::MeteringMode oldMode = meteringMode(); QDeclarativeCameraExposure::MeteringMode oldMode = meteringMode();
m_exposure->setMeteringMode(QCameraExposure::MeteringMode(mode)); m_exposure->setMeteringMode(QCameraExposure::MeteringMode(mode));
if (oldMode != meteringMode()) if (oldMode != meteringMode())
emit meteringModeChanged(meteringMode()); emit meteringModeChanged(meteringMode());

View File

@@ -74,15 +74,38 @@ class QDeclarativeCameraExposure : public QObject
Q_PROPERTY(qreal manualAperture READ manualAperture WRITE setManualAperture NOTIFY manualApertureChanged) Q_PROPERTY(qreal manualAperture READ manualAperture WRITE setManualAperture NOTIFY manualApertureChanged)
Q_PROPERTY(qreal manualIso READ manualIsoSensitivity WRITE setManualIsoSensitivity NOTIFY manualIsoSensitivityChanged) Q_PROPERTY(qreal manualIso READ manualIsoSensitivity WRITE setManualIsoSensitivity NOTIFY manualIsoSensitivityChanged)
Q_PROPERTY(QDeclarativeCamera::ExposureMode exposureMode READ exposureMode WRITE setExposureMode NOTIFY exposureModeChanged) Q_PROPERTY(ExposureMode exposureMode READ exposureMode WRITE setExposureMode NOTIFY exposureModeChanged)
Q_PROPERTY(QPointF spotMeteringPoint READ spotMeteringPoint WRITE setSpotMeteringPoint NOTIFY spotMeteringPointChanged) Q_PROPERTY(QPointF spotMeteringPoint READ spotMeteringPoint WRITE setSpotMeteringPoint NOTIFY spotMeteringPointChanged)
Q_PROPERTY(QDeclarativeCamera::MeteringMode meteringMode READ meteringMode WRITE setMeteringMode NOTIFY meteringModeChanged) Q_PROPERTY(MeteringMode meteringMode READ meteringMode WRITE setMeteringMode NOTIFY meteringModeChanged)
Q_ENUMS(ExposureMode)
Q_ENUMS(MeteringMode)
public: public:
enum ExposureMode {
ExposureAuto = QCameraExposure::ExposureAuto,
ExposureManual = QCameraExposure::ExposureManual,
ExposurePortrait = QCameraExposure::ExposurePortrait,
ExposureNight = QCameraExposure::ExposureNight,
ExposureBacklight = QCameraExposure::ExposureBacklight,
ExposureSpotlight = QCameraExposure::ExposureSpotlight,
ExposureSports = QCameraExposure::ExposureSports,
ExposureSnow = QCameraExposure::ExposureSnow,
ExposureBeach = QCameraExposure::ExposureBeach,
ExposureLargeAperture = QCameraExposure::ExposureLargeAperture,
ExposureSmallAperture = QCameraExposure::ExposureSmallAperture,
ExposureModeVendor = QCameraExposure::ExposureModeVendor
};
enum MeteringMode {
MeteringMatrix = QCameraExposure::MeteringMatrix,
MeteringAverage = QCameraExposure::MeteringAverage,
MeteringSpot = QCameraExposure::MeteringSpot
};
~QDeclarativeCameraExposure(); ~QDeclarativeCameraExposure();
QDeclarativeCamera::ExposureMode exposureMode() const; ExposureMode exposureMode() const;
qreal exposureCompensation() const; qreal exposureCompensation() const;
int isoSensitivity() const; int isoSensitivity() const;
@@ -96,11 +119,11 @@ public:
QPointF spotMeteringPoint() const; QPointF spotMeteringPoint() const;
void setSpotMeteringPoint(const QPointF &point); void setSpotMeteringPoint(const QPointF &point);
QDeclarativeCamera::MeteringMode meteringMode() const; MeteringMode meteringMode() const;
void setMeteringMode(QDeclarativeCamera::MeteringMode mode); void setMeteringMode(MeteringMode mode);
public Q_SLOTS: public Q_SLOTS:
void setExposureMode(QDeclarativeCamera::ExposureMode); void setExposureMode(ExposureMode);
void setExposureCompensation(qreal ev); void setExposureCompensation(qreal ev);
void setManualAperture(qreal); void setManualAperture(qreal);
@@ -121,9 +144,9 @@ Q_SIGNALS:
void manualShutterSpeedChanged(qreal); void manualShutterSpeedChanged(qreal);
void exposureCompensationChanged(qreal); void exposureCompensationChanged(qreal);
void exposureModeChanged(QDeclarativeCamera::ExposureMode); void exposureModeChanged(ExposureMode);
void meteringModeChanged(QDeclarativeCamera::MeteringMode); void meteringModeChanged(MeteringMode);
void spotMeteringPointChanged(QPointF); void spotMeteringPointChanged(QPointF);
private: private:

View File

@@ -131,14 +131,14 @@ bool QDeclarativeCameraFlash::isFlashReady() const
\endtable \endtable
*/ */
int QDeclarativeCameraFlash::flashMode() const QDeclarativeCameraFlash::FlashMode QDeclarativeCameraFlash::flashMode() const
{ {
return m_exposure->flashMode(); return QDeclarativeCameraFlash::FlashMode(int(m_exposure->flashMode()));
} }
void QDeclarativeCameraFlash::setFlashMode(int mode) void QDeclarativeCameraFlash::setFlashMode(QDeclarativeCameraFlash::FlashMode mode)
{ {
if (m_exposure->flashMode() != mode) { if (flashMode() != mode) {
m_exposure->setFlashMode(QCameraExposure::FlashModes(mode)); m_exposure->setFlashMode(QCameraExposure::FlashModes(mode));
emit flashModeChanged(mode); emit flashModeChanged(mode);
} }
@@ -154,7 +154,7 @@ void QDeclarativeCameraFlash::setFlashMode(int mode)
\qmlsignal QtMultimedia::CameraFlash::flashReady(bool) \qmlsignal QtMultimedia::CameraFlash::flashReady(bool)
This signal is emitted when QCameraExposure indicates that This signal is emitted when QCameraExposure indicates that
the flash is ready to use. the flash is ready to use.
The corresponsing handler is \c onFlashReadyChanged. The corresponding handler is \c onFlashReadyChanged.
*/ */
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@@ -64,19 +64,34 @@ class QDeclarativeCameraFlash : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(bool ready READ isFlashReady NOTIFY flashReady) Q_PROPERTY(bool ready READ isFlashReady NOTIFY flashReady)
Q_PROPERTY(int mode READ flashMode WRITE setFlashMode NOTIFY flashModeChanged) Q_PROPERTY(FlashMode mode READ flashMode WRITE setFlashMode NOTIFY flashModeChanged)
Q_ENUMS(FlashMode)
public: public:
enum FlashMode {
FlashAuto = QCameraExposure::FlashAuto,
FlashOff = QCameraExposure::FlashOff,
FlashOn = QCameraExposure::FlashOn,
FlashRedEyeReduction = QCameraExposure::FlashRedEyeReduction,
FlashFill = QCameraExposure::FlashFill,
FlashTorch = QCameraExposure::FlashTorch,
FlashVideoLight = QCameraExposure::FlashVideoLight,
FlashSlowSyncFrontCurtain = QCameraExposure::FlashSlowSyncFrontCurtain,
FlashSlowSyncRearCurtain = QCameraExposure::FlashSlowSyncRearCurtain,
FlashManual = QCameraExposure::FlashManual
};
~QDeclarativeCameraFlash(); ~QDeclarativeCameraFlash();
int flashMode() const; FlashMode flashMode() const;
bool isFlashReady() const; bool isFlashReady() const;
public Q_SLOTS: public Q_SLOTS:
void setFlashMode(int); void setFlashMode(FlashMode);
Q_SIGNALS: Q_SIGNALS:
void flashReady(bool status); void flashReady(bool status);
void flashModeChanged(int); void flashModeChanged(FlashMode);
private: private:
friend class QDeclarativeCamera; friend class QDeclarativeCamera;

View File

@@ -161,9 +161,9 @@ QDeclarativeCameraFocus::~QDeclarativeCameraFocus()
and \l focusZones property provide information and control and \l focusZones property provide information and control
over how automatic focusing is performed. over how automatic focusing is performed.
*/ */
QDeclarativeCamera::FocusMode QDeclarativeCameraFocus::focusMode() const QDeclarativeCameraFocus::FocusMode QDeclarativeCameraFocus::focusMode() const
{ {
return QDeclarativeCamera::FocusMode(int(m_focus->focusMode())); return QDeclarativeCameraFocus::FocusMode(int(m_focus->focusMode()));
} }
/*! /*!
@@ -172,12 +172,12 @@ QDeclarativeCamera::FocusMode QDeclarativeCameraFocus::focusMode() const
Returns true if the supplied \a mode is a supported focus mode, and Returns true if the supplied \a mode is a supported focus mode, and
false otherwise. false otherwise.
*/ */
bool QDeclarativeCameraFocus::isFocusModeSupported(QDeclarativeCamera::FocusMode mode) const bool QDeclarativeCameraFocus::isFocusModeSupported(QDeclarativeCameraFocus::FocusMode mode) const
{ {
return m_focus->isFocusModeSupported(QCameraFocus::FocusModes(int(mode))); return m_focus->isFocusModeSupported(QCameraFocus::FocusModes(int(mode)));
} }
void QDeclarativeCameraFocus::setFocusMode(QDeclarativeCamera::FocusMode mode) void QDeclarativeCameraFocus::setFocusMode(QDeclarativeCameraFocus::FocusMode mode)
{ {
if (mode != focusMode()) { if (mode != focusMode()) {
m_focus->setFocusMode(QCameraFocus::FocusModes(int(mode))); m_focus->setFocusMode(QCameraFocus::FocusModes(int(mode)));
@@ -221,12 +221,12 @@ void QDeclarativeCameraFocus::setFocusMode(QDeclarativeCamera::FocusMode mode)
\li Focus to the custom point, defined by the customFocusPoint property. \li Focus to the custom point, defined by the customFocusPoint property.
\endtable \endtable
*/ */
QDeclarativeCamera::FocusPointMode QDeclarativeCameraFocus::focusPointMode() const QDeclarativeCameraFocus::FocusPointMode QDeclarativeCameraFocus::focusPointMode() const
{ {
return QDeclarativeCamera::FocusPointMode(m_focus->focusPointMode()); return QDeclarativeCameraFocus::FocusPointMode(m_focus->focusPointMode());
} }
void QDeclarativeCameraFocus::setFocusPointMode(QDeclarativeCamera::FocusPointMode mode) void QDeclarativeCameraFocus::setFocusPointMode(QDeclarativeCameraFocus::FocusPointMode mode)
{ {
if (mode != focusPointMode()) { if (mode != focusPointMode()) {
m_focus->setFocusPointMode(QCameraFocus::FocusPointMode(mode)); m_focus->setFocusPointMode(QCameraFocus::FocusPointMode(mode));
@@ -240,7 +240,7 @@ void QDeclarativeCameraFocus::setFocusPointMode(QDeclarativeCamera::FocusPointMo
Returns true if the supplied \a mode is a supported focus point mode, and Returns true if the supplied \a mode is a supported focus point mode, and
false otherwise. false otherwise.
*/ */
bool QDeclarativeCameraFocus::isFocusPointModeSupported(QDeclarativeCamera::FocusPointMode mode) const bool QDeclarativeCameraFocus::isFocusPointModeSupported(QDeclarativeCameraFocus::FocusPointMode mode) const
{ {
return m_focus->isFocusPointModeSupported(QCameraFocus::FocusPointMode(mode)); return m_focus->isFocusPointModeSupported(QCameraFocus::FocusPointMode(mode));
} }

View File

@@ -66,30 +66,49 @@ class QDeclarativeCamera;
class QDeclarativeCameraFocus : public QObject class QDeclarativeCameraFocus : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QDeclarativeCamera::FocusMode focusMode READ focusMode WRITE setFocusMode NOTIFY focusModeChanged) Q_PROPERTY(FocusMode focusMode READ focusMode WRITE setFocusMode NOTIFY focusModeChanged)
Q_PROPERTY(QDeclarativeCamera::FocusPointMode focusPointMode READ focusPointMode WRITE setFocusPointMode NOTIFY focusPointModeChanged) Q_PROPERTY(FocusPointMode focusPointMode READ focusPointMode WRITE setFocusPointMode NOTIFY focusPointModeChanged)
Q_PROPERTY(QPointF customFocusPoint READ customFocusPoint WRITE setCustomFocusPoint NOTIFY customFocusPointChanged) Q_PROPERTY(QPointF customFocusPoint READ customFocusPoint WRITE setCustomFocusPoint NOTIFY customFocusPointChanged)
Q_PROPERTY(QObject *focusZones READ focusZones CONSTANT) Q_PROPERTY(QObject *focusZones READ focusZones CONSTANT)
Q_ENUMS(FocusMode)
Q_ENUMS(FocusPointMode)
public: public:
enum FocusMode {
FocusManual = QCameraFocus::ManualFocus,
FocusHyperfocal = QCameraFocus::HyperfocalFocus,
FocusInfinity = QCameraFocus::InfinityFocus,
FocusAuto = QCameraFocus::AutoFocus,
FocusContinuous = QCameraFocus::ContinuousFocus,
FocusMacro = QCameraFocus::MacroFocus
};
enum FocusPointMode {
FocusPointAuto = QCameraFocus::FocusPointAuto,
FocusPointCenter = QCameraFocus::FocusPointCenter,
FocusPointFaceDetection = QCameraFocus::FocusPointFaceDetection,
FocusPointCustom = QCameraFocus::FocusPointCustom
};
~QDeclarativeCameraFocus(); ~QDeclarativeCameraFocus();
QDeclarativeCamera::FocusMode focusMode() const; FocusMode focusMode() const;
QDeclarativeCamera::FocusPointMode focusPointMode() const; FocusPointMode focusPointMode() const;
QPointF customFocusPoint() const; QPointF customFocusPoint() const;
QAbstractListModel *focusZones() const; QAbstractListModel *focusZones() const;
Q_INVOKABLE bool isFocusModeSupported(QDeclarativeCamera::FocusMode mode) const; Q_INVOKABLE bool isFocusModeSupported(FocusMode mode) const;
Q_INVOKABLE bool isFocusPointModeSupported(QDeclarativeCamera::FocusPointMode mode) const; Q_INVOKABLE bool isFocusPointModeSupported(FocusPointMode mode) const;
public Q_SLOTS: public Q_SLOTS:
void setFocusMode(QDeclarativeCamera::FocusMode); void setFocusMode(FocusMode);
void setFocusPointMode(QDeclarativeCamera::FocusPointMode mode); void setFocusPointMode(FocusPointMode mode);
void setCustomFocusPoint(const QPointF &point); void setCustomFocusPoint(const QPointF &point);
Q_SIGNALS: Q_SIGNALS:
void focusModeChanged(QDeclarativeCamera::FocusMode); void focusModeChanged(FocusMode);
void focusPointModeChanged(QDeclarativeCamera::FocusPointMode); void focusPointModeChanged(FocusPointMode);
void customFocusPointChanged(const QPointF &); void customFocusPointChanged(const QPointF &);
private Q_SLOTS: private Q_SLOTS:

View File

@@ -230,11 +230,15 @@ void QDeclarativeCameraImageProcessing::setDenoisingLevel(qreal value)
/*! /*!
\qmlsignal QtMultimedia::Camera::whiteBalanceModeChanged(Camera::WhiteBalanceMode) \qmlsignal QtMultimedia::Camera::whiteBalanceModeChanged(Camera::WhiteBalanceMode)
This signal is emitted when the \c whiteBalanceMode property is changed. This signal is emitted when the \c whiteBalanceMode property is changed.
The corresponding handler is \c onWhiteBalanceModeChanged.
*/ */
/*! /*!
\qmlsignal QtMultimedia::Camera::manualWhiteBalanceChanged(qreal) \qmlsignal QtMultimedia::Camera::manualWhiteBalanceChanged(qreal)
This signal is emitted when the \c manualWhiteBalance property is changed. This signal is emitted when the \c manualWhiteBalance property is changed.
The corresponding handler is \c onManualWhiteBalanceChanged.
*/ */
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@@ -540,6 +540,8 @@ void QDeclarativeRadio::_q_availabilityChanged(QMultimedia::AvailabilityStatus a
The \a frequency is returned in Hertz, and the \a stationId corresponds to the station Id The \a frequency is returned in Hertz, and the \a stationId corresponds to the station Id
in the \l RadioData for this radio station. in the \l RadioData for this radio station.
The corresponding handler is \c onStationFound.
*/ */
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@@ -104,7 +104,7 @@ QCameraInfo::QCameraInfo(const QCamera &camera)
: d(new QCameraInfoPrivate) : d(new QCameraInfoPrivate)
{ {
const QVideoDeviceSelectorControl *deviceControl = camera.d_func()->deviceControl; const QVideoDeviceSelectorControl *deviceControl = camera.d_func()->deviceControl;
if (deviceControl) { if (deviceControl && deviceControl->deviceCount() > 0) {
const int selectedDevice = deviceControl->selectedDevice(); const int selectedDevice = deviceControl->selectedDevice();
d->deviceName = deviceControl->deviceName(selectedDevice); d->deviceName = deviceControl->deviceName(selectedDevice);
d->description = deviceControl->deviceDescription(selectedDevice); d->description = deviceControl->deviceDescription(selectedDevice);

View File

@@ -78,6 +78,8 @@ namespace QGstUtils {
const QSet<QString> &supportedMimeTypeSet); const QSet<QString> &supportedMimeTypeSet);
} }
void qt_gst_object_ref_sink(gpointer object);
QT_END_NAMESPACE QT_END_NAMESPACE
#endif #endif

View File

@@ -53,59 +53,56 @@ import android.util.Log;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import android.content.res.AssetFileDescriptor; import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager; import android.content.res.AssetManager;
import android.view.SurfaceHolder;
public class QtAndroidMediaPlayer extends MediaPlayer public class QtAndroidMediaPlayer
{ {
// Native callback functions for MediaPlayer // Native callback functions for MediaPlayer
native public void onErrorNative(int what, int extra, long id); native public void onErrorNative(int what, int extra, long id);
native public void onBufferingUpdateNative(int percent, long id); native public void onBufferingUpdateNative(int percent, long id);
native public void onProgressUpdateNative(int progress, long id);
native public void onDurationChangedNative(int duration, long id);
native public void onInfoNative(int what, int extra, long id); native public void onInfoNative(int what, int extra, long id);
native public void onMediaPlayerInfoNative(int what, int extra, long id);
native public void onVideoSizeChangedNative(int width, int height, long id); native public void onVideoSizeChangedNative(int width, int height, long id);
native public void onStateChangedNative(int state, long id);
private MediaPlayer mMediaPlayer = null;
private Uri mUri = null; private Uri mUri = null;
private final long mID; private final long mID;
private final Activity mActivity;
private boolean mMuted = false; private boolean mMuted = false;
private boolean mPreparing = false;
private boolean mInitialized = false;
private int mVolume = 100; private int mVolume = 100;
private static final String TAG = "Qt MediaPlayer"; private static final String TAG = "Qt MediaPlayer";
private static Context mApplicationContext = null; private SurfaceHolder mSurfaceHolder = null;
final int MEDIA_PLAYER_INVALID_STATE = 1; private class State {
final int MEDIA_PLAYER_PREPARING = 2; final static int Uninitialized = 0x1 /* End */;
final int MEDIA_PLAYER_READY = 3; final static int Idle = 0x2;
final int MEDIA_PLAYER_DURATION = 4; final static int Preparing = 0x4;
final int MEDIA_PLAYER_PROGRESS = 5; final static int Prepared = 0x8;
final int MEDIA_PLAYER_FINISHED = 6; final static int Initialized = 0x10;
final static int Started = 0x20;
// Activity set by Qt on load. final static int Stopped = 0x40;
static public void setActivity(final Activity activity) final static int Paused = 0x80;
{ final static int PlaybackCompleted = 0x100;
try { final static int Error = 0x200;
mApplicationContext = activity.getApplicationContext();
} catch(final Exception e) {
Log.d(TAG, "" + e.getMessage());
}
} }
private class ProgressWatcher implements Runnable private volatile int mState = State.Uninitialized;
private class ProgressWatcher
implements Runnable
{ {
@Override @Override
public void run() public void run()
{ {
final int duratation = getDuration();
int currentPosition = getCurrentPosition();
try { try {
while (duratation >= currentPosition && isPlaying()) { while ((mState & (State.Started)) != 0) {
onMediaPlayerInfoNative(MEDIA_PLAYER_PROGRESS, currentPosition, mID); onProgressUpdateNative(getCurrentPosition(), mID);
Thread.sleep(1000); Thread.sleep(1000);
currentPosition = getCurrentPosition();
} }
} catch (final InterruptedException e) { } catch (final InterruptedException e) {
Log.d(TAG, "" + e.getMessage()); // Ignore
return;
} }
} }
} }
@@ -121,7 +118,7 @@ public class QtAndroidMediaPlayer extends MediaPlayer
final int what, final int what,
final int extra) final int extra)
{ {
reset(); setState(State.Error);
onErrorNative(what, extra, mID); onErrorNative(what, extra, mID);
return true; return true;
} }
@@ -158,7 +155,7 @@ public class QtAndroidMediaPlayer extends MediaPlayer
@Override @Override
public void onCompletion(final MediaPlayer mp) public void onCompletion(final MediaPlayer mp)
{ {
onMediaPlayerInfoNative(MEDIA_PLAYER_FINISHED, 0, mID); setState(State.PlaybackCompleted);
} }
} }
@@ -190,9 +187,8 @@ public class QtAndroidMediaPlayer extends MediaPlayer
@Override @Override
public void onPrepared(final MediaPlayer mp) public void onPrepared(final MediaPlayer mp)
{ {
mPreparing = false; setState(State.Prepared);
onMediaPlayerInfoNative(MEDIA_PLAYER_READY, 0, mID); onDurationChangedNative(getDuration(), mID);
onMediaPlayerInfoNative(MEDIA_PLAYER_DURATION, getDuration(), mID);
} }
} }
@@ -207,7 +203,7 @@ public class QtAndroidMediaPlayer extends MediaPlayer
@Override @Override
public void onSeekComplete(final MediaPlayer mp) public void onSeekComplete(final MediaPlayer mp)
{ {
onMediaPlayerInfoNative(MEDIA_PLAYER_PROGRESS, getCurrentPosition(), mID); onProgressUpdateNative(getCurrentPosition(), mID);
} }
} }
@@ -229,98 +225,117 @@ public class QtAndroidMediaPlayer extends MediaPlayer
} }
public QtAndroidMediaPlayer(final long id) public QtAndroidMediaPlayer(final Activity activity, final long id)
{ {
super();
mID = id; mID = id;
setOnBufferingUpdateListener(new MediaPlayerBufferingListener()); mActivity = activity;
setOnCompletionListener(new MediaPlayerCompletionListener()); }
setOnInfoListener(new MediaPlayerInfoListener());
setOnSeekCompleteListener(new MediaPlayerSeekCompleteListener()); private void setState(int state)
setOnVideoSizeChangedListener(new MediaPlayerVideoSizeChangedListener()); {
setOnErrorListener(new MediaPlayerErrorListener()); if (mState == state)
return;
mState = state;
onStateChangedNative(mState, mID);
}
private void init()
{
if (mMediaPlayer == null) {
mMediaPlayer = new MediaPlayer();
setState(State.Idle);
}
} }
@Override
public void start() public void start()
{ {
if (!mInitialized) { if ((mState & (State.Prepared
onMediaPlayerInfoNative(MEDIA_PLAYER_INVALID_STATE, 0, mID); | State.Started
| State.Paused
| State.PlaybackCompleted)) == 0) {
return; return;
} }
if (mApplicationContext == null)
return;
if (mPreparing)
return;
if (isPlaying())
return;
try { try {
super.start(); mMediaPlayer.start();
setState(State.Started);
Thread progressThread = new Thread(new ProgressWatcher()); Thread progressThread = new Thread(new ProgressWatcher());
progressThread.start(); progressThread.start();
} catch (final IllegalStateException e) { } catch (final IllegalStateException e) {
reset();
Log.d(TAG, "" + e.getMessage()); Log.d(TAG, "" + e.getMessage());
} }
} }
@Override
public void pause() public void pause()
{ {
if (!isPlaying()) if ((mState & (State.Started | State.Paused | State.PlaybackCompleted)) == 0)
return; return;
try { try {
super.pause(); mMediaPlayer.pause();
setState(State.Paused);
} catch (final IllegalStateException e) { } catch (final IllegalStateException e) {
reset();
Log.d(TAG, "" + e.getMessage()); Log.d(TAG, "" + e.getMessage());
} }
} }
@Override
public void stop() public void stop()
{ {
if (!mInitialized) if ((mState & (State.Prepared
| State.Started
| State.Stopped
| State.Paused
| State.PlaybackCompleted)) == 0) {
return; return;
}
try { try {
super.stop(); mMediaPlayer.stop();
setState(State.Stopped);
} catch (final IllegalStateException e) { } catch (final IllegalStateException e) {
Log.d(TAG, "" + e.getMessage()); Log.d(TAG, "" + e.getMessage());
} finally {
reset();
} }
} }
@Override
public void seekTo(final int msec) public void seekTo(final int msec)
{ {
if (!mInitialized) if ((mState & (State.Prepared
| State.Started
| State.Paused
| State.PlaybackCompleted)) == 0) {
return; return;
}
try { try {
super.seekTo(msec); mMediaPlayer.seekTo(msec);
onMediaPlayerInfoNative(MEDIA_PLAYER_PROGRESS, msec, mID); onProgressUpdateNative(msec, mID);
} catch (final IllegalStateException e) { } catch (final IllegalStateException e) {
Log.d(TAG, "" + e.getMessage()); Log.d(TAG, "" + e.getMessage());
} }
} }
@Override
public boolean isPlaying() public boolean isPlaying()
{ {
boolean playing = false; boolean playing = false;
if ((mState & (State.Idle
if (!mInitialized) | State.Initialized
| State.Prepared
| State.Started
| State.Paused
| State.Stopped
| State.PlaybackCompleted)) == 0) {
return playing; return playing;
}
try { try {
playing = super.isPlaying(); playing = mMediaPlayer.isPlaying();
} catch (final IllegalStateException e) { } catch (final IllegalStateException e) {
Log.d(TAG, "" + e.getMessage()); Log.d(TAG, "" + e.getMessage());
} }
@@ -328,34 +343,56 @@ public class QtAndroidMediaPlayer extends MediaPlayer
return playing; return playing;
} }
public void setMediaPath(final String path) public void prepareAsync()
{ {
if (mInitialized) if ((mState & (State.Initialized | State.Stopped)) == 0)
reset(); return;
try { try {
mPreparing = true; mMediaPlayer.prepareAsync();
onMediaPlayerInfoNative(MEDIA_PLAYER_PREPARING, 0, mID); setState(State.Preparing);
} catch (final IllegalStateException e) {
Log.d(TAG, "" + e.getMessage());
}
}
public void setDataSource(final String path)
{
if ((mState & State.Uninitialized) != 0)
init();
if ((mState & State.Idle) == 0)
return;
mMediaPlayer.setOnBufferingUpdateListener(new MediaPlayerBufferingListener());
mMediaPlayer.setOnCompletionListener(new MediaPlayerCompletionListener());
mMediaPlayer.setOnInfoListener(new MediaPlayerInfoListener());
mMediaPlayer.setOnSeekCompleteListener(new MediaPlayerSeekCompleteListener());
mMediaPlayer.setOnVideoSizeChangedListener(new MediaPlayerVideoSizeChangedListener());
mMediaPlayer.setOnErrorListener(new MediaPlayerErrorListener());
mMediaPlayer.setOnPreparedListener(new MediaPlayerPreparedListener());
if (mSurfaceHolder != null)
mMediaPlayer.setDisplay(mSurfaceHolder);
AssetFileDescriptor afd = null;
try {
mUri = Uri.parse(path); mUri = Uri.parse(path);
if (mUri.getScheme().compareTo("assets") == 0) { final boolean inAssets = (mUri.getScheme().compareTo("assets") == 0);
if (inAssets) {
final String asset = mUri.getPath().substring(1 /* Remove first '/' */); final String asset = mUri.getPath().substring(1 /* Remove first '/' */);
final AssetManager am = mApplicationContext.getAssets(); final AssetManager am = mActivity.getAssets();
final AssetFileDescriptor afd = am.openFd(asset); afd = am.openFd(asset);
final long offset = afd.getStartOffset(); final long offset = afd.getStartOffset();
final long length = afd.getLength(); final long length = afd.getLength();
FileDescriptor fd = afd.getFileDescriptor(); FileDescriptor fd = afd.getFileDescriptor();
setDataSource(fd, offset, length); mMediaPlayer.setDataSource(fd, offset, length);
} else { } else {
setDataSource(mApplicationContext, mUri); mMediaPlayer.setDataSource(mActivity, mUri);
} }
mInitialized = true; setState(State.Initialized);
setOnPreparedListener(new MediaPlayerPreparedListener());
prepareAsync();
} catch (final IOException e) { } catch (final IOException e) {
mPreparing = false; Log.d(TAG, "" + e.getMessage());
onErrorNative(MEDIA_ERROR_UNKNOWN,
/* MEDIA_ERROR_UNSUPPORTED= */ -1010,
mID);
} catch (final IllegalArgumentException e) { } catch (final IllegalArgumentException e) {
Log.d(TAG, "" + e.getMessage()); Log.d(TAG, "" + e.getMessage());
} catch (final SecurityException e) { } catch (final SecurityException e) {
@@ -364,19 +401,36 @@ public class QtAndroidMediaPlayer extends MediaPlayer
Log.d(TAG, "" + e.getMessage()); Log.d(TAG, "" + e.getMessage());
} catch (final NullPointerException e) { } catch (final NullPointerException e) {
Log.d(TAG, "" + e.getMessage()); Log.d(TAG, "" + e.getMessage());
} finally {
if (afd !=null) {
try { afd.close(); } catch (final IOException ioe) { /* Ignore... */ }
}
if ((mState & State.Initialized) == 0) {
setState(State.Error);
onErrorNative(MediaPlayer.MEDIA_ERROR_UNKNOWN,
-1004 /*MEDIA_ERROR_IO*/,
mID);
return;
}
} }
} }
@Override
public int getCurrentPosition() public int getCurrentPosition()
{ {
int currentPosition = 0; int currentPosition = 0;
if ((mState & (State.Idle
if (!mInitialized) | State.Initialized
| State.Prepared
| State.Started
| State.Paused
| State.Stopped
| State.PlaybackCompleted)) == 0) {
return currentPosition; return currentPosition;
}
try { try {
currentPosition = super.getCurrentPosition(); currentPosition = mMediaPlayer.getCurrentPosition();
} catch (final IllegalStateException e) { } catch (final IllegalStateException e) {
Log.d(TAG, "" + e.getMessage()); Log.d(TAG, "" + e.getMessage());
} }
@@ -384,16 +438,20 @@ public class QtAndroidMediaPlayer extends MediaPlayer
return currentPosition; return currentPosition;
} }
@Override
public int getDuration() public int getDuration()
{ {
int duration = 0; int duration = 0;
if ((mState & (State.Prepared
if (!mInitialized) | State.Started
| State.Paused
| State.Stopped
| State.PlaybackCompleted)) == 0) {
return duration; return duration;
}
try { try {
duration = super.getDuration(); duration = mMediaPlayer.getDuration();
} catch (final IllegalStateException e) { } catch (final IllegalStateException e) {
Log.d(TAG, "" + e.getMessage()); Log.d(TAG, "" + e.getMessage());
} }
@@ -414,6 +472,16 @@ public class QtAndroidMediaPlayer extends MediaPlayer
public void setVolume(int volume) public void setVolume(int volume)
{ {
if ((mState & (State.Idle
| State.Initialized
| State.Stopped
| State.Prepared
| State.Started
| State.Paused
| State.PlaybackCompleted)) == 0) {
return;
}
if (volume < 0) if (volume < 0)
volume = 0; volume = 0;
@@ -423,7 +491,7 @@ public class QtAndroidMediaPlayer extends MediaPlayer
float newVolume = adjustVolume(volume); float newVolume = adjustVolume(volume);
try { try {
super.setVolume(newVolume, newVolume); mMediaPlayer.setVolume(newVolume, newVolume);
if (!mMuted) if (!mMuted)
mVolume = volume; mVolume = volume;
} catch (final IllegalStateException e) { } catch (final IllegalStateException e) {
@@ -431,6 +499,22 @@ public class QtAndroidMediaPlayer extends MediaPlayer
} }
} }
public SurfaceHolder display()
{
return mSurfaceHolder;
}
public void setDisplay(SurfaceHolder sh)
{
mSurfaceHolder = sh;
if ((mState & State.Uninitialized) != 0)
return;
mMediaPlayer.setDisplay(mSurfaceHolder);
}
public int getVolume() public int getVolume()
{ {
return mVolume; return mVolume;
@@ -447,11 +531,32 @@ public class QtAndroidMediaPlayer extends MediaPlayer
return mMuted; return mMuted;
} }
@Override
public void reset() public void reset()
{ {
mInitialized = false; if ((mState & (State.Idle
super.reset(); | State.Initialized
| State.Prepared
| State.Started
| State.Paused
| State.Stopped
| State.PlaybackCompleted
| State.Error)) == 0) {
return;
}
mMediaPlayer.reset();
setState(State.Idle);
} }
public void release()
{
if (mMediaPlayer != null) {
mMediaPlayer.reset();
mMediaPlayer.release();
mMediaPlayer = null;
}
setState(State.Uninitialized);
}
} }

View File

@@ -60,6 +60,7 @@ public:
virtual void setVideoSize(const QSize &) { } virtual void setVideoSize(const QSize &) { }
virtual void stop() { } virtual void stop() { }
virtual void reset() { }
// signals: // signals:
// void readyChanged(bool); // void readyChanged(bool);

View File

@@ -122,20 +122,8 @@ QAndroidVideoRendererControl::QAndroidVideoRendererControl(QObject *parent)
QAndroidVideoRendererControl::~QAndroidVideoRendererControl() QAndroidVideoRendererControl::~QAndroidVideoRendererControl()
{ {
if (m_surfaceTexture) { clearSurfaceTexture();
m_surfaceTexture->callMethod<void>("release");
delete m_surfaceTexture;
m_surfaceTexture = 0;
}
if (m_androidSurface) {
m_androidSurface->callMethod<void>("release");
delete m_androidSurface;
m_androidSurface = 0;
}
if (m_surfaceHolder) {
delete m_surfaceHolder;
m_surfaceHolder = 0;
}
if (m_glDeleter) if (m_glDeleter)
m_glDeleter->deleteLater(); m_glDeleter->deleteLater();
} }
@@ -202,6 +190,24 @@ bool QAndroidVideoRendererControl::initSurfaceTexture()
return m_surfaceTexture != 0; return m_surfaceTexture != 0;
} }
void QAndroidVideoRendererControl::clearSurfaceTexture()
{
if (m_surfaceTexture) {
m_surfaceTexture->callMethod<void>("release");
delete m_surfaceTexture;
m_surfaceTexture = 0;
}
if (m_androidSurface) {
m_androidSurface->callMethod<void>("release");
delete m_androidSurface;
m_androidSurface = 0;
}
if (m_surfaceHolder) {
delete m_surfaceHolder;
m_surfaceHolder = 0;
}
}
jobject QAndroidVideoRendererControl::surfaceHolder() jobject QAndroidVideoRendererControl::surfaceHolder()
{ {
if (!initSurfaceTexture()) if (!initSurfaceTexture())
@@ -245,6 +251,11 @@ void QAndroidVideoRendererControl::stop()
m_nativeSize = QSize(); m_nativeSize = QSize();
} }
void QAndroidVideoRendererControl::reset()
{
clearSurfaceTexture();
}
void QAndroidVideoRendererControl::onFrameAvailable() void QAndroidVideoRendererControl::onFrameAvailable()
{ {
if (!m_nativeSize.isValid() || !m_surface) if (!m_nativeSize.isValid() || !m_surface)

View File

@@ -92,6 +92,7 @@ public:
bool isReady() Q_DECL_OVERRIDE; bool isReady() Q_DECL_OVERRIDE;
void setVideoSize(const QSize &size) Q_DECL_OVERRIDE; void setVideoSize(const QSize &size) Q_DECL_OVERRIDE;
void stop() Q_DECL_OVERRIDE; void stop() Q_DECL_OVERRIDE;
void reset() Q_DECL_OVERRIDE;
void customEvent(QEvent *) Q_DECL_OVERRIDE; void customEvent(QEvent *) Q_DECL_OVERRIDE;
@@ -107,6 +108,7 @@ private:
void createGLResources(); void createGLResources();
QMutex m_mutex; QMutex m_mutex;
void clearSurfaceTexture();
QAbstractVideoSurface *m_surface; QAbstractVideoSurface *m_surface;
QSize m_nativeSize; QSize m_nativeSize;

View File

@@ -65,12 +65,16 @@ QAndroidCaptureSession::QAndroidCaptureSession(QAndroidCameraSession *cameraSess
, m_audioEncoder(JMediaRecorder::DefaultAudioEncoder) , m_audioEncoder(JMediaRecorder::DefaultAudioEncoder)
, m_videoEncoder(JMediaRecorder::DefaultVideoEncoder) , m_videoEncoder(JMediaRecorder::DefaultVideoEncoder)
{ {
connect(this, SIGNAL(stateChanged(QMediaRecorder::State)), this, SLOT(updateStatus()));
if (cameraSession) { if (cameraSession) {
connect(cameraSession, SIGNAL(opened()), this, SLOT(onCameraOpened())); connect(cameraSession, SIGNAL(opened()), this, SLOT(onCameraOpened()));
connect(cameraSession, SIGNAL(statusChanged(QCamera::Status)), connect(cameraSession, SIGNAL(statusChanged(QCamera::Status)), this, SLOT(updateStatus()));
this, SLOT(onCameraStatusChanged(QCamera::Status)));
connect(cameraSession, SIGNAL(captureModeChanged(QCamera::CaptureModes)), connect(cameraSession, SIGNAL(captureModeChanged(QCamera::CaptureModes)),
this, SLOT(onCameraCaptureModeChanged(QCamera::CaptureModes))); this, SLOT(updateStatus()));
connect(cameraSession, SIGNAL(readyForCaptureChanged(bool)), this, SLOT(updateStatus()));
} else {
updateStatus();
} }
m_notifyTimer.setInterval(1000); m_notifyTimer.setInterval(1000);
@@ -126,7 +130,6 @@ bool QAndroidCaptureSession::setOutputLocation(const QUrl &location)
if (m_requestedOutputLocation.isValid() if (m_requestedOutputLocation.isValid()
&& (m_requestedOutputLocation.isLocalFile() || m_requestedOutputLocation.isRelative())) { && (m_requestedOutputLocation.isLocalFile() || m_requestedOutputLocation.isRelative())) {
emit actualLocationChanged(m_requestedOutputLocation);
return true; return true;
} }
@@ -164,10 +167,10 @@ void QAndroidCaptureSession::setState(QMediaRecorder::State state)
bool QAndroidCaptureSession::start() bool QAndroidCaptureSession::start()
{ {
if (m_state == QMediaRecorder::RecordingState) if (m_state == QMediaRecorder::RecordingState || m_status != QMediaRecorder::LoadedStatus)
return false; return false;
setStatus(QMediaRecorder::LoadingStatus); setStatus(QMediaRecorder::StartingStatus);
if (m_mediaRecorder) { if (m_mediaRecorder) {
m_mediaRecorder->release(); m_mediaRecorder->release();
@@ -179,17 +182,11 @@ bool QAndroidCaptureSession::start()
// Set audio/video sources // Set audio/video sources
if (m_cameraSession) { if (m_cameraSession) {
if (m_cameraSession->status() != QCamera::ActiveStatus) { updateViewfinder();
emit error(QMediaRecorder::ResourceError, QLatin1String("Camera must be active to record it.")); m_cameraSession->camera()->unlock();
setStatus(QMediaRecorder::UnloadedStatus); m_mediaRecorder->setCamera(m_cameraSession->camera());
return false; m_mediaRecorder->setAudioSource(JMediaRecorder::Camcorder);
} else { m_mediaRecorder->setVideoSource(JMediaRecorder::Camera);
updateViewfinder();
m_cameraSession->camera()->unlock();
m_mediaRecorder->setCamera(m_cameraSession->camera());
m_mediaRecorder->setAudioSource(JMediaRecorder::Camcorder);
m_mediaRecorder->setVideoSource(JMediaRecorder::Camera);
}
} else { } else {
m_mediaRecorder->setAudioSource(m_audioSource); m_mediaRecorder->setAudioSource(m_audioSource);
} }
@@ -213,7 +210,6 @@ bool QAndroidCaptureSession::start()
m_mediaRecorder->setOrientationHint(m_cameraSession->currentCameraRotation()); m_mediaRecorder->setOrientationHint(m_cameraSession->currentCameraRotation());
} }
// Set output file // Set output file
QString filePath = m_mediaStorageLocation.generateFileName( QString filePath = m_mediaStorageLocation.generateFileName(
m_requestedOutputLocation.isLocalFile() ? m_requestedOutputLocation.toLocalFile() m_requestedOutputLocation.isLocalFile() ? m_requestedOutputLocation.toLocalFile()
@@ -224,29 +220,21 @@ bool QAndroidCaptureSession::start()
: QLatin1String("REC_"), : QLatin1String("REC_"),
m_containerFormat); m_containerFormat);
m_actualOutputLocation = QUrl::fromLocalFile(filePath); m_usedOutputLocation = QUrl::fromLocalFile(filePath);
if (m_actualOutputLocation != m_requestedOutputLocation)
emit actualLocationChanged(m_actualOutputLocation);
m_mediaRecorder->setOutputFile(filePath); m_mediaRecorder->setOutputFile(filePath);
if (!m_mediaRecorder->prepare()) { if (!m_mediaRecorder->prepare()) {
emit error(QMediaRecorder::FormatError, QLatin1String("Unable to prepare the media recorder.")); emit error(QMediaRecorder::FormatError, QLatin1String("Unable to prepare the media recorder."));
setStatus(QMediaRecorder::UnloadedStatus); restartViewfinder();
return false; return false;
} }
setStatus(QMediaRecorder::LoadedStatus);
setStatus(QMediaRecorder::StartingStatus);
if (!m_mediaRecorder->start()) { if (!m_mediaRecorder->start()) {
emit error(QMediaRecorder::FormatError, QLatin1String("Unable to start the media recorder.")); emit error(QMediaRecorder::FormatError, QLatin1String("Unable to start the media recorder."));
setStatus(QMediaRecorder::UnloadedStatus); restartViewfinder();
return false; return false;
} }
setStatus(QMediaRecorder::RecordingStatus);
m_elapsedTime.start(); m_elapsedTime.start();
m_notifyTimer.start(); m_notifyTimer.start();
updateDuration(); updateDuration();
@@ -270,17 +258,15 @@ void QAndroidCaptureSession::stop(bool error)
updateDuration(); updateDuration();
m_elapsedTime.invalidate(); m_elapsedTime.invalidate();
if (m_cameraSession) {
m_cameraSession->camera()->reconnect();
// Viewport needs to be restarted
m_cameraSession->camera()->startPreview();
m_cameraSession->setReadyForCapture(true);
}
m_mediaRecorder->release(); m_mediaRecorder->release();
delete m_mediaRecorder; delete m_mediaRecorder;
m_mediaRecorder = 0; m_mediaRecorder = 0;
if (m_cameraSession) {
// Viewport needs to be restarted after recording
restartViewfinder();
}
if (!error) { if (!error) {
// if the media is saved into the standard media location, register it // if the media is saved into the standard media location, register it
// with the Android media scanner so it appears immediately in apps // with the Android media scanner so it appears immediately in apps
@@ -290,9 +276,10 @@ void QAndroidCaptureSession::stop(bool error)
: JMultimediaUtils::getDefaultMediaDirectory(JMultimediaUtils::Sounds); : JMultimediaUtils::getDefaultMediaDirectory(JMultimediaUtils::Sounds);
if (mediaPath.startsWith(standardLoc)) if (mediaPath.startsWith(standardLoc))
JMultimediaUtils::registerMediaFile(mediaPath); JMultimediaUtils::registerMediaFile(mediaPath);
}
setStatus(QMediaRecorder::UnloadedStatus); m_actualOutputLocation = m_usedOutputLocation;
emit actualLocationChanged(m_actualOutputLocation);
}
} }
void QAndroidCaptureSession::setStatus(QMediaRecorder::Status status) void QAndroidCaptureSession::setStatus(QMediaRecorder::Status status)
@@ -437,6 +424,13 @@ void QAndroidCaptureSession::updateViewfinder()
m_resolutionDirty = false; m_resolutionDirty = false;
} }
void QAndroidCaptureSession::restartViewfinder()
{
m_cameraSession->camera()->reconnect();
m_cameraSession->camera()->startPreview();
m_cameraSession->setReadyForCapture(true);
}
void QAndroidCaptureSession::updateDuration() void QAndroidCaptureSession::updateDuration()
{ {
if (m_elapsedTime.isValid()) if (m_elapsedTime.isValid())
@@ -513,16 +507,40 @@ QAndroidCaptureSession::CaptureProfile QAndroidCaptureSession::getProfile(int id
return profile; return profile;
} }
void QAndroidCaptureSession::onCameraStatusChanged(QCamera::Status status) void QAndroidCaptureSession::updateStatus()
{ {
if (status == QCamera::StoppingStatus) if (m_cameraSession) {
setState(QMediaRecorder::StoppedState); // Video recording
}
void QAndroidCaptureSession::onCameraCaptureModeChanged(QCamera::CaptureModes mode) // stop recording when stopping the camera
{ if (m_cameraSession->status() == QCamera::StoppingStatus
if (!mode.testFlag(QCamera::CaptureVideo)) || !m_cameraSession->captureMode().testFlag(QCamera::CaptureVideo)) {
setState(QMediaRecorder::StoppedState); setState(QMediaRecorder::StoppedState);
}
if (m_state == QMediaRecorder::RecordingState) {
setStatus(QMediaRecorder::RecordingStatus);
} else if (m_cameraSession->status() == QCamera::UnavailableStatus) {
setStatus(QMediaRecorder::UnavailableStatus);
} else if (m_cameraSession->captureMode().testFlag(QCamera::CaptureVideo)
&& m_cameraSession->isReadyForCapture()) {
if (m_cameraSession->status() == QCamera::StartingStatus)
setStatus(QMediaRecorder::LoadingStatus);
else if (m_cameraSession->status() == QCamera::ActiveStatus)
setStatus(QMediaRecorder::LoadedStatus);
else
setStatus(QMediaRecorder::UnloadedStatus);
} else {
setStatus(QMediaRecorder::UnloadedStatus);
}
} else {
// Audio-only recording
if (m_state == QMediaRecorder::RecordingState)
setStatus(QMediaRecorder::RecordingStatus);
else
setStatus(QMediaRecorder::LoadedStatus);
}
} }
void QAndroidCaptureSession::onError(int what, int extra) void QAndroidCaptureSession::onError(int what, int extra)

View File

@@ -99,8 +99,7 @@ Q_SIGNALS:
private Q_SLOTS: private Q_SLOTS:
void updateDuration(); void updateDuration();
void onCameraOpened(); void onCameraOpened();
void onCameraStatusChanged(QCamera::Status); void updateStatus();
void onCameraCaptureModeChanged(QCamera::CaptureModes mode);
void onError(int what, int extra); void onError(int what, int extra);
void onInfo(int what, int extra); void onInfo(int what, int extra);
@@ -145,6 +144,7 @@ private:
void setStatus(QMediaRecorder::Status status); void setStatus(QMediaRecorder::Status status);
void updateViewfinder(); void updateViewfinder();
void restartViewfinder();
JMediaRecorder *m_mediaRecorder; JMediaRecorder *m_mediaRecorder;
QAndroidCameraSession *m_cameraSession; QAndroidCameraSession *m_cameraSession;
@@ -161,6 +161,7 @@ private:
QMediaRecorder::State m_state; QMediaRecorder::State m_state;
QMediaRecorder::Status m_status; QMediaRecorder::Status m_status;
QUrl m_requestedOutputLocation; QUrl m_requestedOutputLocation;
QUrl m_usedOutputLocation;
QUrl m_actualOutputLocation; QUrl m_actualOutputLocation;
CaptureProfile m_defaultSettings; CaptureProfile m_defaultSettings;

View File

@@ -57,25 +57,31 @@ QAndroidMediaPlayerControl::QAndroidMediaPlayerControl(QObject *parent)
mAudioAvailable(false), mAudioAvailable(false),
mVideoAvailable(false), mVideoAvailable(false),
mBuffering(false), mBuffering(false),
mMediaPlayerReady(false), mState(JMediaPlayer::Uninitialized),
mPendingState(-1),
mPendingPosition(-1), mPendingPosition(-1),
mPendingSetMedia(false) mPendingSetMedia(false),
mPendingVolume(-1),
mPendingMute(-1)
{ {
connect(mMediaPlayer, SIGNAL(bufferingUpdate(qint32)), connect(mMediaPlayer,SIGNAL(bufferingChanged(qint32)),
this, SLOT(onBufferChanged(qint32))); this,SLOT(onBufferingChanged(qint32)));
connect(mMediaPlayer, SIGNAL(info(qint32,qint32)), connect(mMediaPlayer,SIGNAL(info(qint32,qint32)),
this, SLOT(onInfo(qint32,qint32))); this,SLOT(onInfo(qint32,qint32)));
connect(mMediaPlayer, SIGNAL(error(qint32,qint32)), connect(mMediaPlayer,SIGNAL(error(qint32,qint32)),
this, SLOT(onError(qint32,qint32))); this,SLOT(onError(qint32,qint32)));
connect(mMediaPlayer, SIGNAL(mediaPlayerInfo(qint32,qint32)), connect(mMediaPlayer,SIGNAL(stateChanged(qint32)),
this, SLOT(onMediaPlayerInfo(qint32,qint32))); this,SLOT(onStateChanged(qint32)));
connect(mMediaPlayer, SIGNAL(videoSizeChanged(qint32,qint32)), connect(mMediaPlayer,SIGNAL(videoSizeChanged(qint32,qint32)),
this, SLOT(onVideoSizeChanged(qint32,qint32))); this,SLOT(onVideoSizeChanged(qint32,qint32)));
connect(mMediaPlayer,SIGNAL(progressChanged(qint64)),
this,SIGNAL(positionChanged(qint64)));
connect(mMediaPlayer,SIGNAL(durationChanged(qint64)),
this,SIGNAL(durationChanged(qint64)));
} }
QAndroidMediaPlayerControl::~QAndroidMediaPlayerControl() QAndroidMediaPlayerControl::~QAndroidMediaPlayerControl()
{ {
mMediaPlayer->stop();
mMediaPlayer->release(); mMediaPlayer->release();
delete mMediaPlayer; delete mMediaPlayer;
} }
@@ -92,18 +98,33 @@ QMediaPlayer::MediaStatus QAndroidMediaPlayerControl::mediaStatus() const
qint64 QAndroidMediaPlayerControl::duration() const qint64 QAndroidMediaPlayerControl::duration() const
{ {
return (mCurrentMediaStatus == QMediaPlayer::InvalidMedia if ((mState & (JMediaPlayer::Prepared
|| mCurrentMediaStatus == QMediaPlayer::NoMedia | JMediaPlayer::Started
|| !mMediaPlayerReady) ? 0 | JMediaPlayer::Paused
: mMediaPlayer->getDuration(); | JMediaPlayer::Stopped
| JMediaPlayer::PlaybackCompleted)) == 0) {
return 0;
}
return mMediaPlayer->getDuration();
} }
qint64 QAndroidMediaPlayerControl::position() const qint64 QAndroidMediaPlayerControl::position() const
{ {
if (!mMediaPlayerReady) if (mCurrentMediaStatus == QMediaPlayer::EndOfMedia)
return mPendingPosition < 0 ? 0 : mPendingPosition; return duration();
return mMediaPlayer->getCurrentPosition(); if ((mState & (JMediaPlayer::Idle
| JMediaPlayer::Initialized
| JMediaPlayer::Prepared
| JMediaPlayer::Started
| JMediaPlayer::Paused
| JMediaPlayer::Stopped
| JMediaPlayer::PlaybackCompleted)) == 0) {
return (mPendingPosition == -1) ? 0 : mPendingPosition;
}
return (mCurrentState == QMediaPlayer::StoppedState) ? 0 : mMediaPlayer->getCurrentPosition();
} }
void QAndroidMediaPlayerControl::setPosition(qint64 position) void QAndroidMediaPlayerControl::setPosition(qint64 position)
@@ -113,35 +134,88 @@ void QAndroidMediaPlayerControl::setPosition(qint64 position)
const int seekPosition = (position > INT_MAX) ? INT_MAX : position; const int seekPosition = (position > INT_MAX) ? INT_MAX : position;
if (!mMediaPlayerReady) { if ((mState & (JMediaPlayer::Prepared
mPendingPosition = seekPosition; | JMediaPlayer::Started
Q_EMIT positionChanged(seekPosition); | JMediaPlayer::Paused
| JMediaPlayer::PlaybackCompleted)) == 0) {
if (mPendingPosition != seekPosition) {
mPendingPosition = seekPosition;
Q_EMIT positionChanged(seekPosition);
}
return; return;
} }
if (mCurrentMediaStatus == QMediaPlayer::EndOfMedia)
setMediaStatus(QMediaPlayer::LoadedMedia);
mMediaPlayer->seekTo(seekPosition); mMediaPlayer->seekTo(seekPosition);
mPendingPosition = -1;
if (mPendingPosition != -1) {
mPendingPosition = -1;
}
Q_EMIT positionChanged(seekPosition);
} }
int QAndroidMediaPlayerControl::volume() const int QAndroidMediaPlayerControl::volume() const
{ {
return mMediaPlayer->volume(); return (mPendingVolume == -1) ? mMediaPlayer->volume() : mPendingVolume;
} }
void QAndroidMediaPlayerControl::setVolume(int volume) void QAndroidMediaPlayerControl::setVolume(int volume)
{ {
if ((mState & (JMediaPlayer::Idle
| JMediaPlayer::Initialized
| JMediaPlayer::Stopped
| JMediaPlayer::Prepared
| JMediaPlayer::Started
| JMediaPlayer::Paused
| JMediaPlayer::PlaybackCompleted)) == 0) {
if (mPendingVolume != volume) {
mPendingVolume = volume;
Q_EMIT volumeChanged(volume);
}
return;
}
mMediaPlayer->setVolume(volume); mMediaPlayer->setVolume(volume);
if (mPendingVolume != -1) {
mPendingVolume = -1;
return;
}
Q_EMIT volumeChanged(volume); Q_EMIT volumeChanged(volume);
} }
bool QAndroidMediaPlayerControl::isMuted() const bool QAndroidMediaPlayerControl::isMuted() const
{ {
return mMediaPlayer->isMuted(); return (mPendingMute == -1) ? mMediaPlayer->isMuted() : (mPendingMute == 1);
} }
void QAndroidMediaPlayerControl::setMuted(bool muted) void QAndroidMediaPlayerControl::setMuted(bool muted)
{ {
if ((mState & (JMediaPlayer::Idle
| JMediaPlayer::Initialized
| JMediaPlayer::Stopped
| JMediaPlayer::Prepared
| JMediaPlayer::Started
| JMediaPlayer::Paused
| JMediaPlayer::PlaybackCompleted)) == 0) {
if (mPendingMute != muted) {
mPendingMute = muted;
Q_EMIT mutedChanged(muted);
}
return;
}
mMediaPlayer->setMuted(muted); mMediaPlayer->setMuted(muted);
if (mPendingMute != -1) {
mPendingMute = -1;
return;
}
Q_EMIT mutedChanged(muted); Q_EMIT mutedChanged(muted);
} }
@@ -208,10 +282,21 @@ const QIODevice *QAndroidMediaPlayerControl::mediaStream() const
void QAndroidMediaPlayerControl::setMedia(const QMediaContent &mediaContent, void QAndroidMediaPlayerControl::setMedia(const QMediaContent &mediaContent,
QIODevice *stream) QIODevice *stream)
{ {
mMediaContent = mediaContent; const bool reloading = (mMediaContent == mediaContent);
mMediaStream = stream;
if (mVideoOutput && !mMediaPlayer->display()) { if (!reloading) {
mMediaContent = mediaContent;
mMediaStream = stream;
}
mMediaPlayer->release();
if (mediaContent.isNull()) {
setMediaStatus(QMediaPlayer::NoMedia);
return;
}
if (mVideoOutput && !mVideoOutput->isReady()) {
// if a video output is set but the video texture is not ready, delay loading the media // if a video output is set but the video texture is not ready, delay loading the media
// since it can cause problems on some hardware // since it can cause problems on some hardware
mPendingSetMedia = true; mPendingSetMedia = true;
@@ -229,68 +314,88 @@ void QAndroidMediaPlayerControl::setMedia(const QMediaContent &mediaContent,
mediaPath = url.toString(); mediaPath = url.toString();
} }
if (!mediaPath.isEmpty()) if (mVideoSize.isValid() && mVideoOutput)
mMediaPlayer->setDataSource(mediaPath); mVideoOutput->setVideoSize(mVideoSize);
else
setMediaStatus(QMediaPlayer::NoMedia);
Q_EMIT mediaChanged(mMediaContent); if (!mMediaPlayer->display() && mVideoOutput)
mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder());
mMediaPlayer->setDataSource(mediaPath);
mMediaPlayer->prepareAsync();
if (!reloading)
Q_EMIT mediaChanged(mMediaContent);
resetBufferingProgress(); resetBufferingProgress();
// reset some properties
setAudioAvailable(false);
setVideoAvailable(false);
setSeekable(true);
} }
void QAndroidMediaPlayerControl::setVideoOutput(QObject *videoOutput) void QAndroidMediaPlayerControl::setVideoOutput(QObject *videoOutput)
{ {
if (mVideoOutput) if (mVideoOutput) {
mMediaPlayer->setDisplay(0);
mVideoOutput->stop(); mVideoOutput->stop();
mVideoOutput->reset();
}
mVideoOutput = qobject_cast<QAndroidVideoOutput *>(videoOutput); mVideoOutput = qobject_cast<QAndroidVideoOutput *>(videoOutput);
if (mVideoOutput && !mMediaPlayer->display()) { if (!mVideoOutput)
if (mVideoOutput->isReady()) return;
mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder());
else if (mVideoOutput->isReady())
connect(videoOutput, SIGNAL(readyChanged(bool)), this, SLOT(onVideoOutputReady(bool))); mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder());
}
connect(videoOutput, SIGNAL(readyChanged(bool)), this, SLOT(onVideoOutputReady(bool)));
} }
void QAndroidMediaPlayerControl::play() void QAndroidMediaPlayerControl::play()
{ {
if (!mMediaPlayerReady) { // We need to prepare the mediaplayer again.
if ((mState & JMediaPlayer::Stopped) && !mMediaContent.isNull()) {
setMedia(mMediaContent, mMediaStream);
}
setState(QMediaPlayer::PlayingState);
if ((mState & (JMediaPlayer::Prepared
| JMediaPlayer::Started
| JMediaPlayer::Paused
| JMediaPlayer::PlaybackCompleted)) == 0) {
mPendingState = QMediaPlayer::PlayingState; mPendingState = QMediaPlayer::PlayingState;
if (mCurrentState == QMediaPlayer::StoppedState
&& !mMediaContent.isNull()
&& mCurrentMediaStatus != QMediaPlayer::LoadingMedia
&& !mPendingSetMedia) {
setMedia(mMediaContent, 0);
}
return; return;
} }
mMediaPlayer->play(); mMediaPlayer->play();
setState(QMediaPlayer::PlayingState);
} }
void QAndroidMediaPlayerControl::pause() void QAndroidMediaPlayerControl::pause()
{ {
if (!mMediaPlayerReady) { setState(QMediaPlayer::PausedState);
if ((mState & (JMediaPlayer::Started
| JMediaPlayer::Paused
| JMediaPlayer::PlaybackCompleted)) == 0) {
mPendingState = QMediaPlayer::PausedState; mPendingState = QMediaPlayer::PausedState;
return; return;
} }
mMediaPlayer->pause(); mMediaPlayer->pause();
setState(QMediaPlayer::PausedState);
} }
void QAndroidMediaPlayerControl::stop() void QAndroidMediaPlayerControl::stop()
{ {
mMediaPlayer->stop();
setState(QMediaPlayer::StoppedState); 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)
mPendingState = QMediaPlayer::StoppedState;
return;
}
mMediaPlayer->stop();
} }
void QAndroidMediaPlayerControl::onInfo(qint32 what, qint32 extra) void QAndroidMediaPlayerControl::onInfo(qint32 what, qint32 extra)
@@ -310,8 +415,8 @@ void QAndroidMediaPlayerControl::onInfo(qint32 what, qint32 extra)
setMediaStatus(QMediaPlayer::StalledMedia); setMediaStatus(QMediaPlayer::StalledMedia);
break; break;
case JMediaPlayer::MEDIA_INFO_BUFFERING_END: case JMediaPlayer::MEDIA_INFO_BUFFERING_END:
setMediaStatus(mBufferPercent == 100 ? QMediaPlayer::BufferedMedia : QMediaPlayer::BufferingMedia); if (mCurrentState != QMediaPlayer::StoppedState)
flushPendingStates(); flushPendingStates();
break; break;
case JMediaPlayer::MEDIA_INFO_BAD_INTERLEAVING: case JMediaPlayer::MEDIA_INFO_BAD_INTERLEAVING:
break; break;
@@ -324,41 +429,6 @@ void QAndroidMediaPlayerControl::onInfo(qint32 what, qint32 extra)
} }
} }
void QAndroidMediaPlayerControl::onMediaPlayerInfo(qint32 what, qint32 extra)
{
switch (what) {
case JMediaPlayer::MEDIA_PLAYER_INVALID_STATE:
setError(what, QStringLiteral("Error: Invalid state"));
break;
case JMediaPlayer::MEDIA_PLAYER_PREPARING:
setMediaStatus(QMediaPlayer::LoadingMedia);
setState(QMediaPlayer::StoppedState);
break;
case JMediaPlayer::MEDIA_PLAYER_READY:
setMediaStatus(QMediaPlayer::LoadedMedia);
if (mBuffering) {
setMediaStatus(mBufferPercent == 100 ? QMediaPlayer::BufferedMedia
: QMediaPlayer::BufferingMedia);
} else {
onBufferChanged(100);
}
setAudioAvailable(true);
mMediaPlayerReady = true;
flushPendingStates();
break;
case JMediaPlayer::MEDIA_PLAYER_DURATION:
Q_EMIT durationChanged(extra);
break;
case JMediaPlayer::MEDIA_PLAYER_PROGRESS:
Q_EMIT positionChanged(extra);
break;
case JMediaPlayer::MEDIA_PLAYER_FINISHED:
stop();
setMediaStatus(QMediaPlayer::EndOfMedia);
break;
}
}
void QAndroidMediaPlayerControl::onError(qint32 what, qint32 extra) void QAndroidMediaPlayerControl::onError(qint32 what, qint32 extra)
{ {
QString errorString; QString errorString;
@@ -372,6 +442,10 @@ void QAndroidMediaPlayerControl::onError(qint32 what, qint32 extra)
errorString = QLatin1String("Error: Server died"); errorString = QLatin1String("Error: Server died");
error = QMediaPlayer::ServiceMissingError; error = QMediaPlayer::ServiceMissingError;
break; break;
case JMediaPlayer::MEDIA_ERROR_INVALID_STATE:
errorString = QLatin1String("Error: Invalid state");
error = QMediaPlayer::ServiceMissingError;
break;
} }
switch (extra) { switch (extra) {
@@ -398,12 +472,16 @@ void QAndroidMediaPlayerControl::onError(qint32 what, qint32 extra)
error = QMediaPlayer::FormatError; error = QMediaPlayer::FormatError;
setMediaStatus(QMediaPlayer::InvalidMedia); setMediaStatus(QMediaPlayer::InvalidMedia);
break; break;
case JMediaPlayer::MEDIA_ERROR_BAD_THINGS_ARE_GOING_TO_HAPPEN:
errorString += QLatin1String(" (Unknown error/Insufficient resources)");
error = QMediaPlayer::ServiceMissingError;
break;
} }
setError(error, errorString); Q_EMIT QMediaPlayerControl::error(error, errorString);
} }
void QAndroidMediaPlayerControl::onBufferChanged(qint32 percent) void QAndroidMediaPlayerControl::onBufferingChanged(qint32 percent)
{ {
mBuffering = percent != 100; mBuffering = percent != 100;
mBufferPercent = percent; mBufferPercent = percent;
@@ -411,8 +489,8 @@ void QAndroidMediaPlayerControl::onBufferChanged(qint32 percent)
updateAvailablePlaybackRanges(); updateAvailablePlaybackRanges();
if (mBufferPercent == 100) if (mCurrentState != QMediaPlayer::StoppedState)
setMediaStatus(QMediaPlayer::BufferedMedia); setMediaStatus(mBuffering ? QMediaPlayer::BufferingMedia : QMediaPlayer::BufferedMedia);
} }
void QAndroidMediaPlayerControl::onVideoSizeChanged(qint32 width, qint32 height) void QAndroidMediaPlayerControl::onVideoSizeChanged(qint32 width, qint32 height)
@@ -429,12 +507,89 @@ void QAndroidMediaPlayerControl::onVideoSizeChanged(qint32 width, qint32 height)
mVideoOutput->setVideoSize(mVideoSize); mVideoOutput->setVideoSize(mVideoSize);
} }
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)))
return;
mState = state;
switch (mState) {
case JMediaPlayer::Idle:
break;
case JMediaPlayer::Initialized:
break;
case JMediaPlayer::Preparing:
setMediaStatus(QMediaPlayer::LoadingMedia);
break;
case JMediaPlayer::Prepared:
setMediaStatus(QMediaPlayer::LoadedMedia);
if (mBuffering) {
setMediaStatus(mBufferPercent == 100 ? QMediaPlayer::BufferedMedia
: QMediaPlayer::BufferingMedia);
} else {
onBufferingChanged(100);
}
setAudioAvailable(true);
flushPendingStates();
break;
case JMediaPlayer::Started:
setState(QMediaPlayer::PlayingState);
if (mBuffering) {
setMediaStatus(mBufferPercent == 100 ? QMediaPlayer::BufferedMedia
: QMediaPlayer::BufferingMedia);
} else {
setMediaStatus(QMediaPlayer::BufferedMedia);
}
break;
case JMediaPlayer::Paused:
setState(QMediaPlayer::PausedState);
break;
case JMediaPlayer::Error:
setState(QMediaPlayer::StoppedState);
setMediaStatus(QMediaPlayer::UnknownMediaStatus);
mMediaPlayer->release();
break;
case JMediaPlayer::Stopped:
setState(QMediaPlayer::StoppedState);
setMediaStatus(QMediaPlayer::LoadedMedia);
setPosition(0);
break;
case JMediaPlayer::PlaybackCompleted:
setState(QMediaPlayer::StoppedState);
setPosition(0);
setMediaStatus(QMediaPlayer::EndOfMedia);
break;
case JMediaPlayer::Uninitialized:
// reset some properties
resetBufferingProgress();
mPendingPosition = -1;
mPendingSetMedia = false;
mPendingState = -1;
setAudioAvailable(false);
setVideoAvailable(false);
setSeekable(true);
break;
default:
break;
}
if ((mState & (JMediaPlayer::Stopped | JMediaPlayer::Uninitialized)) != 0) {
mMediaPlayer->setDisplay(0);
if (mVideoOutput) {
mVideoOutput->stop();
mVideoOutput->reset();
}
}
}
void QAndroidMediaPlayerControl::onVideoOutputReady(bool ready) void QAndroidMediaPlayerControl::onVideoOutputReady(bool ready)
{ {
if (!mMediaPlayer->display() && mVideoOutput && ready) { if (!mMediaPlayer->display() && mVideoOutput && ready)
mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder()); mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder());
flushPendingStates();
} flushPendingStates();
} }
void QAndroidMediaPlayerControl::setState(QMediaPlayer::State state) void QAndroidMediaPlayerControl::setState(QMediaPlayer::State state)
@@ -442,14 +597,8 @@ void QAndroidMediaPlayerControl::setState(QMediaPlayer::State state)
if (mCurrentState == state) if (mCurrentState == state)
return; return;
if (state == QMediaPlayer::StoppedState) { if (mCurrentState == QMediaPlayer::StoppedState && state == QMediaPlayer::PausedState)
if (mVideoOutput) return;
mVideoOutput->stop();
resetBufferingProgress();
mMediaPlayerReady = false;
mPendingPosition = -1;
Q_EMIT positionChanged(0);
}
mCurrentState = state; mCurrentState = state;
Q_EMIT stateChanged(mCurrentState); Q_EMIT stateChanged(mCurrentState);
@@ -463,17 +612,13 @@ void QAndroidMediaPlayerControl::setMediaStatus(QMediaPlayer::MediaStatus status
if (status == QMediaPlayer::NoMedia || status == QMediaPlayer::InvalidMedia) if (status == QMediaPlayer::NoMedia || status == QMediaPlayer::InvalidMedia)
Q_EMIT durationChanged(0); Q_EMIT durationChanged(0);
if (status == QMediaPlayer::EndOfMedia)
Q_EMIT durationChanged(duration());
mCurrentMediaStatus = status; mCurrentMediaStatus = status;
Q_EMIT mediaStatusChanged(mCurrentMediaStatus); Q_EMIT mediaStatusChanged(mCurrentMediaStatus);
} }
void QAndroidMediaPlayerControl::setError(int error,
const QString &errorString)
{
setState(QMediaPlayer::StoppedState);
Q_EMIT QMediaPlayerControl::error(error, errorString);
}
void QAndroidMediaPlayerControl::setSeekable(bool seekable) void QAndroidMediaPlayerControl::setSeekable(bool seekable)
{ {
if (mSeekable == seekable) if (mSeekable == seekable)
@@ -515,15 +660,23 @@ void QAndroidMediaPlayerControl::resetBufferingProgress()
void QAndroidMediaPlayerControl::flushPendingStates() void QAndroidMediaPlayerControl::flushPendingStates()
{ {
if (mPendingSetMedia) { if (mPendingSetMedia) {
setMedia(mMediaContent, 0);
mPendingSetMedia = false; mPendingSetMedia = false;
setMedia(mMediaContent, 0);
return; return;
} }
switch (mPendingState) { const int newState = mPendingState;
mPendingState = -1;
if (mPendingPosition != -1)
setPosition(mPendingPosition);
if (mPendingVolume != -1)
setVolume(mPendingVolume);
if (mPendingMute != -1)
setMuted((mPendingMute == 1));
switch (newState) {
case QMediaPlayer::PlayingState: case QMediaPlayer::PlayingState:
if (mPendingPosition > -1)
setPosition(mPendingPosition);
play(); play();
break; break;
case QMediaPlayer::PausedState: case QMediaPlayer::PausedState:
@@ -532,6 +685,8 @@ void QAndroidMediaPlayerControl::flushPendingStates()
case QMediaPlayer::StoppedState: case QMediaPlayer::StoppedState:
stop(); stop();
break; break;
default:
break;
} }
} }

View File

@@ -93,9 +93,9 @@ private Q_SLOTS:
void onVideoOutputReady(bool ready); void onVideoOutputReady(bool ready);
void onError(qint32 what, qint32 extra); void onError(qint32 what, qint32 extra);
void onInfo(qint32 what, qint32 extra); void onInfo(qint32 what, qint32 extra);
void onMediaPlayerInfo(qint32 what, qint32 extra); void onBufferingChanged(qint32 percent);
void onBufferChanged(qint32 percent);
void onVideoSizeChanged(qint32 width, qint32 height); void onVideoSizeChanged(qint32 width, qint32 height);
void onStateChanged(qint32 state);
private: private:
JMediaPlayer *mMediaPlayer; JMediaPlayer *mMediaPlayer;
@@ -111,15 +111,16 @@ private:
QSize mVideoSize; QSize mVideoSize;
bool mBuffering; bool mBuffering;
QMediaTimeRange mAvailablePlaybackRange; QMediaTimeRange mAvailablePlaybackRange;
bool mMediaPlayerReady; int mState;
QMediaPlayer::State mPendingState; int mPendingState;
qint64 mPendingPosition; qint64 mPendingPosition;
bool mPendingSetMedia; bool mPendingSetMedia;
int mPendingVolume;
int mPendingMute;
QScopedPointer<QTemporaryFile> mTempFile; QScopedPointer<QTemporaryFile> mTempFile;
void setState(QMediaPlayer::State state); void setState(QMediaPlayer::State state);
void setMediaStatus(QMediaPlayer::MediaStatus status); void setMediaStatus(QMediaPlayer::MediaStatus status);
void setError(int error, const QString &errorString);
void setSeekable(bool seekable); void setSeekable(bool seekable);
void setAudioAvailable(bool available); void setAudioAvailable(bool available);
void setVideoAvailable(bool available); void setVideoAvailable(bool available);

View File

@@ -306,12 +306,16 @@ int JCamera::cameraId() const
void JCamera::lock() void JCamera::lock()
{ {
QMetaObject::invokeMethod(d, "callVoidMethod", Q_ARG(QByteArray, "lock")); QMetaObject::invokeMethod(d, "callVoidMethod",
Qt::BlockingQueuedConnection,
Q_ARG(QByteArray, "lock"));
} }
void JCamera::unlock() void JCamera::unlock()
{ {
QMetaObject::invokeMethod(d, "callVoidMethod", Q_ARG(QByteArray, "unlock")); QMetaObject::invokeMethod(d, "callVoidMethod",
Qt::BlockingQueuedConnection,
Q_ARG(QByteArray, "unlock"));
} }
void JCamera::reconnect() void JCamera::reconnect()

View File

@@ -46,135 +46,113 @@
#include <QtCore/private/qjnihelpers_p.h> #include <QtCore/private/qjnihelpers_p.h>
#include <QMap> #include <QMap>
namespace { static jclass mediaPlayerClass = Q_NULLPTR;
typedef QMap<jlong, JMediaPlayer *> MediaPlayerMap;
jclass mediaPlayerClass = 0; Q_GLOBAL_STATIC(MediaPlayerMap, mediaPlayers)
QMap<jlong, JMediaPlayer *> mplayers;
}
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
bool JMediaPlayer::mActivitySet = false;
JMediaPlayer::JMediaPlayer() JMediaPlayer::JMediaPlayer()
: QObject() : QObject()
, QJNIObjectPrivate(mediaPlayerClass, "(J)V", reinterpret_cast<jlong>(this))
, mId(reinterpret_cast<jlong>(this))
, mDisplay(0)
{ {
mplayers.insert(mId, this);
if (!mActivitySet) { const jlong id = reinterpret_cast<jlong>(this);
QJNIObjectPrivate::callStaticMethod<void>(mediaPlayerClass, mMediaPlayer = QJNIObjectPrivate(mediaPlayerClass,
"setActivity", "(Landroid/app/Activity;J)V",
"(Landroid/app/Activity;)V", QtAndroidPrivate::activity(),
QtAndroidPrivate::activity()); id);
mActivitySet = true; (*mediaPlayers)[id] = this;
}
} }
JMediaPlayer::~JMediaPlayer() JMediaPlayer::~JMediaPlayer()
{ {
mplayers.remove(mId); mediaPlayers->remove(reinterpret_cast<jlong>(this));
} }
void JMediaPlayer::release() void JMediaPlayer::release()
{ {
callMethod<void>("release"); mMediaPlayer.callMethod<void>("release");
} }
void JMediaPlayer::onError(qint32 what, qint32 extra) void JMediaPlayer::reset()
{ {
Q_EMIT error(what, extra); mMediaPlayer.callMethod<void>("reset");
}
void JMediaPlayer::onBufferingUpdate(qint32 percent)
{
Q_EMIT bufferingUpdate(percent);
}
void JMediaPlayer::onInfo(qint32 what, qint32 extra)
{
Q_EMIT info(what, extra);
}
void JMediaPlayer::onMediaPlayerInfo(qint32 what, qint32 extra)
{
Q_EMIT mediaPlayerInfo(what, extra);
}
void JMediaPlayer::onVideoSizeChanged(qint32 width, qint32 height)
{
Q_EMIT videoSizeChanged(width, height);
} }
int JMediaPlayer::getCurrentPosition() int JMediaPlayer::getCurrentPosition()
{ {
return callMethod<jint>("getCurrentPosition"); return mMediaPlayer.callMethod<jint>("getCurrentPosition");
} }
int JMediaPlayer::getDuration() int JMediaPlayer::getDuration()
{ {
return callMethod<jint>("getDuration"); return mMediaPlayer.callMethod<jint>("getDuration");
} }
bool JMediaPlayer::isPlaying() bool JMediaPlayer::isPlaying()
{ {
return callMethod<jboolean>("isPlaying"); return mMediaPlayer.callMethod<jboolean>("isPlaying");
} }
int JMediaPlayer::volume() int JMediaPlayer::volume()
{ {
return callMethod<jint>("getVolume"); return mMediaPlayer.callMethod<jint>("getVolume");
} }
bool JMediaPlayer::isMuted() bool JMediaPlayer::isMuted()
{ {
return callMethod<jboolean>("isMuted"); return mMediaPlayer.callMethod<jboolean>("isMuted");
}
jobject JMediaPlayer::display()
{
return mMediaPlayer.callObjectMethod("display", "()Landroid/view/SurfaceHolder;").object();
} }
void JMediaPlayer::play() void JMediaPlayer::play()
{ {
callMethod<void>("start"); mMediaPlayer.callMethod<void>("start");
} }
void JMediaPlayer::pause() void JMediaPlayer::pause()
{ {
callMethod<void>("pause"); mMediaPlayer.callMethod<void>("pause");
} }
void JMediaPlayer::stop() void JMediaPlayer::stop()
{ {
callMethod<void>("stop"); mMediaPlayer.callMethod<void>("stop");
} }
void JMediaPlayer::seekTo(qint32 msec) void JMediaPlayer::seekTo(qint32 msec)
{ {
callMethod<void>("seekTo", "(I)V", jint(msec)); mMediaPlayer.callMethod<void>("seekTo", "(I)V", jint(msec));
} }
void JMediaPlayer::setMuted(bool mute) void JMediaPlayer::setMuted(bool mute)
{ {
callMethod<void>("mute", "(Z)V", jboolean(mute)); mMediaPlayer.callMethod<void>("mute", "(Z)V", jboolean(mute));
} }
void JMediaPlayer::setDataSource(const QString &path) void JMediaPlayer::setDataSource(const QString &path)
{ {
QJNIObjectPrivate string = QJNIObjectPrivate::fromString(path); QJNIObjectPrivate string = QJNIObjectPrivate::fromString(path);
callMethod<void>("setMediaPath", "(Ljava/lang/String;)V", string.object()); mMediaPlayer.callMethod<void>("setDataSource", "(Ljava/lang/String;)V", string.object());
}
void JMediaPlayer::prepareAsync()
{
mMediaPlayer.callMethod<void>("prepareAsync");
} }
void JMediaPlayer::setVolume(int volume) void JMediaPlayer::setVolume(int volume)
{ {
callMethod<void>("setVolume", "(I)V", jint(volume)); mMediaPlayer.callMethod<void>("setVolume", "(I)V", jint(volume));
} }
void JMediaPlayer::setDisplay(jobject surfaceHolder) void JMediaPlayer::setDisplay(jobject surfaceHolder)
{ {
mDisplay = surfaceHolder; mMediaPlayer.callMethod<void>("setDisplay", "(Landroid/view/SurfaceHolder;)V", surfaceHolder);
callMethod<void>("setDisplay", "(Landroid/view/SurfaceHolder;)V", mDisplay);
} }
QT_END_NAMESPACE QT_END_NAMESPACE
@@ -183,44 +161,66 @@ static void onErrorNative(JNIEnv *env, jobject thiz, jint what, jint extra, jlon
{ {
Q_UNUSED(env); Q_UNUSED(env);
Q_UNUSED(thiz); Q_UNUSED(thiz);
JMediaPlayer *const mp = mplayers[id]; JMediaPlayer *const mp = (*mediaPlayers)[id];
if (!mp) if (!mp)
return; return;
mp->onError(what, extra); Q_EMIT mp->error(what, extra);
} }
static void onBufferingUpdateNative(JNIEnv *env, jobject thiz, jint percent, jlong id) static void onBufferingUpdateNative(JNIEnv *env, jobject thiz, jint percent, jlong id)
{ {
Q_UNUSED(env); Q_UNUSED(env);
Q_UNUSED(thiz); Q_UNUSED(thiz);
JMediaPlayer *const mp = mplayers[id]; JMediaPlayer *const mp = (*mediaPlayers)[id];
if (!mp) if (!mp)
return; return;
mp->onBufferingUpdate(percent); Q_EMIT mp->bufferingChanged(percent);
}
static void onProgressUpdateNative(JNIEnv *env, jobject thiz, jint progress, jlong id)
{
Q_UNUSED(env);
Q_UNUSED(thiz);
JMediaPlayer *const mp = (*mediaPlayers)[id];
if (!mp)
return;
Q_EMIT mp->progressChanged(progress);
}
static void onDurationChangedNative(JNIEnv *env, jobject thiz, jint duration, jlong id)
{
Q_UNUSED(env);
Q_UNUSED(thiz);
JMediaPlayer *const mp = (*mediaPlayers)[id];
if (!mp)
return;
Q_EMIT mp->durationChanged(duration);
} }
static void onInfoNative(JNIEnv *env, jobject thiz, jint what, jint extra, jlong id) static void onInfoNative(JNIEnv *env, jobject thiz, jint what, jint extra, jlong id)
{ {
Q_UNUSED(env); Q_UNUSED(env);
Q_UNUSED(thiz); Q_UNUSED(thiz);
JMediaPlayer *const mp = mplayers[id]; JMediaPlayer *const mp = (*mediaPlayers)[id];
if (!mp) if (!mp)
return; return;
mp->onInfo(what, extra); Q_EMIT mp->info(what, extra);
} }
static void onMediaPlayerInfoNative(JNIEnv *env, jobject thiz, jint what, jint extra, jlong id) static void onStateChangedNative(JNIEnv *env, jobject thiz, jint state, jlong id)
{ {
Q_UNUSED(env); Q_UNUSED(env);
Q_UNUSED(thiz); Q_UNUSED(thiz);
JMediaPlayer *const mp = mplayers[id]; JMediaPlayer *const mp = (*mediaPlayers)[id];
if (!mp) if (!mp)
return; return;
mp->onMediaPlayerInfo(what, extra); Q_EMIT mp->stateChanged(state);
} }
static void onVideoSizeChangedNative(JNIEnv *env, static void onVideoSizeChangedNative(JNIEnv *env,
@@ -231,11 +231,11 @@ static void onVideoSizeChangedNative(JNIEnv *env,
{ {
Q_UNUSED(env); Q_UNUSED(env);
Q_UNUSED(thiz); Q_UNUSED(thiz);
JMediaPlayer *const mp = mplayers[id]; JMediaPlayer *const mp = (*mediaPlayers)[id];
if (!mp) if (!mp)
return; return;
mp->onVideoSizeChanged(width, height); Q_EMIT mp->videoSizeChanged(width, height);
} }
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@@ -250,9 +250,11 @@ bool JMediaPlayer::initJNI(JNIEnv *env)
JNINativeMethod methods[] = { JNINativeMethod methods[] = {
{"onErrorNative", "(IIJ)V", reinterpret_cast<void *>(onErrorNative)}, {"onErrorNative", "(IIJ)V", reinterpret_cast<void *>(onErrorNative)},
{"onBufferingUpdateNative", "(IJ)V", reinterpret_cast<void *>(onBufferingUpdateNative)}, {"onBufferingUpdateNative", "(IJ)V", reinterpret_cast<void *>(onBufferingUpdateNative)},
{"onProgressUpdateNative", "(IJ)V", reinterpret_cast<void *>(onProgressUpdateNative)},
{"onDurationChangedNative", "(IJ)V", reinterpret_cast<void *>(onDurationChangedNative)},
{"onInfoNative", "(IIJ)V", reinterpret_cast<void *>(onInfoNative)}, {"onInfoNative", "(IIJ)V", reinterpret_cast<void *>(onInfoNative)},
{"onMediaPlayerInfoNative", "(IIJ)V", reinterpret_cast<void *>(onMediaPlayerInfoNative)}, {"onVideoSizeChangedNative", "(IIJ)V", reinterpret_cast<void *>(onVideoSizeChangedNative)},
{"onVideoSizeChangedNative", "(IIJ)V", reinterpret_cast<void *>(onVideoSizeChangedNative)} {"onStateChangedNative", "(IJ)V", reinterpret_cast<void *>(onStateChangedNative)}
}; };
if (env->RegisterNatives(mediaPlayerClass, if (env->RegisterNatives(mediaPlayerClass,

View File

@@ -47,7 +47,7 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class JMediaPlayer : public QObject, public QJNIObjectPrivate class JMediaPlayer : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
@@ -59,12 +59,14 @@ public:
// What // What
MEDIA_ERROR_UNKNOWN = 1, MEDIA_ERROR_UNKNOWN = 1,
MEDIA_ERROR_SERVER_DIED = 100, MEDIA_ERROR_SERVER_DIED = 100,
MEDIA_ERROR_INVALID_STATE = -38, // Undocumented
// Extra // Extra
MEDIA_ERROR_IO = -1004, MEDIA_ERROR_IO = -1004,
MEDIA_ERROR_MALFORMED = -1007, MEDIA_ERROR_MALFORMED = -1007,
MEDIA_ERROR_UNSUPPORTED = -1010, MEDIA_ERROR_UNSUPPORTED = -1010,
MEDIA_ERROR_TIMED_OUT = -110, MEDIA_ERROR_TIMED_OUT = -110,
MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200 MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200,
MEDIA_ERROR_BAD_THINGS_ARE_GOING_TO_HAPPEN = -2147483648 // Undocumented
}; };
enum MediaInfo enum MediaInfo
@@ -79,24 +81,29 @@ public:
MEDIA_INFO_METADATA_UPDATE = 802 MEDIA_INFO_METADATA_UPDATE = 802
}; };
enum MediaPlayerInfo enum MediaPlayerState
{ {
MEDIA_PLAYER_INVALID_STATE = 1, Uninitialized = 0x1, /* End */
MEDIA_PLAYER_PREPARING = 2, Idle = 0x2,
MEDIA_PLAYER_READY = 3, Preparing = 0x4,
MEDIA_PLAYER_DURATION = 4, Prepared = 0x8,
MEDIA_PLAYER_PROGRESS = 5, Initialized = 0x10,
MEDIA_PLAYER_FINISHED = 6 Started = 0x20,
Stopped = 0x40,
Paused = 0x80,
PlaybackCompleted = 0x100,
Error = 0x200
}; };
void release(); void release();
void reset();
int getCurrentPosition(); int getCurrentPosition();
int getDuration(); int getDuration();
bool isPlaying(); bool isPlaying();
int volume(); int volume();
bool isMuted(); bool isMuted();
jobject display() { return mDisplay; } jobject display();
void play(); void play();
void pause(); void pause();
@@ -104,30 +111,23 @@ public:
void seekTo(qint32 msec); void seekTo(qint32 msec);
void setMuted(bool mute); void setMuted(bool mute);
void setDataSource(const QString &path); void setDataSource(const QString &path);
void prepareAsync();
void setVolume(int volume); void setVolume(int volume);
void setDisplay(jobject surfaceHolder); void setDisplay(jobject surfaceHolder);
void onError(qint32 what, qint32 extra);
void onBufferingUpdate(qint32 percent);
void onInfo(qint32 what, qint32 extra);
void onMediaPlayerInfo(qint32 what, qint32 extra);
void onVideoSizeChanged(qint32 width, qint32 height);
static bool initJNI(JNIEnv *env); static bool initJNI(JNIEnv *env);
Q_SIGNALS: Q_SIGNALS:
void error(qint32 what, qint32 extra); void error(qint32 what, qint32 extra);
void bufferingUpdate(qint32 percent); void bufferingChanged(qint32 percent);
void completion(); void durationChanged(qint64 duration);
void progressChanged(qint64 progress);
void stateChanged(qint32 state);
void info(qint32 what, qint32 extra); void info(qint32 what, qint32 extra);
void mediaPlayerInfo(qint32 what, qint32 extra);
void videoSizeChanged(qint32 width, qint32 height); void videoSizeChanged(qint32 width, qint32 height);
private: private:
jlong mId; QJNIObjectPrivate mMediaPlayer;
jobject mDisplay;
static bool mActivitySet;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@@ -88,6 +88,9 @@ bool JMediaRecorder::prepare()
QJNIEnvironmentPrivate env; QJNIEnvironmentPrivate env;
callMethod<void>("prepare"); callMethod<void>("prepare");
if (env->ExceptionCheck()) { if (env->ExceptionCheck()) {
#ifdef QT_DEBUG
env->ExceptionDescribe();
#endif
env->ExceptionClear(); env->ExceptionClear();
return false; return false;
} }
@@ -104,6 +107,9 @@ bool JMediaRecorder::start()
QJNIEnvironmentPrivate env; QJNIEnvironmentPrivate env;
callMethod<void>("start"); callMethod<void>("start");
if (env->ExceptionCheck()) { if (env->ExceptionCheck()) {
#ifdef QT_DEBUG
env->ExceptionDescribe();
#endif
env->ExceptionClear(); env->ExceptionClear();
return false; return false;
} }
@@ -114,8 +120,12 @@ void JMediaRecorder::stop()
{ {
QJNIEnvironmentPrivate env; QJNIEnvironmentPrivate env;
callMethod<void>("stop"); callMethod<void>("stop");
if (env->ExceptionCheck()) if (env->ExceptionCheck()) {
#ifdef QT_DEBUG
env->ExceptionDescribe();
#endif
env->ExceptionClear(); env->ExceptionClear();
}
} }
void JMediaRecorder::setAudioChannels(int numChannels) void JMediaRecorder::setAudioChannels(int numChannels)
@@ -127,8 +137,12 @@ void JMediaRecorder::setAudioEncoder(AudioEncoder encoder)
{ {
QJNIEnvironmentPrivate env; QJNIEnvironmentPrivate env;
callMethod<void>("setAudioEncoder", "(I)V", int(encoder)); callMethod<void>("setAudioEncoder", "(I)V", int(encoder));
if (env->ExceptionCheck()) if (env->ExceptionCheck()) {
#ifdef QT_DEBUG
env->ExceptionDescribe();
#endif
env->ExceptionClear(); env->ExceptionClear();
}
} }
void JMediaRecorder::setAudioEncodingBitRate(int bitRate) void JMediaRecorder::setAudioEncodingBitRate(int bitRate)
@@ -145,8 +159,12 @@ void JMediaRecorder::setAudioSource(AudioSource source)
{ {
QJNIEnvironmentPrivate env; QJNIEnvironmentPrivate env;
callMethod<void>("setAudioSource", "(I)V", int(source)); callMethod<void>("setAudioSource", "(I)V", int(source));
if (env->ExceptionCheck()) if (env->ExceptionCheck()) {
#ifdef QT_DEBUG
env->ExceptionDescribe();
#endif
env->ExceptionClear(); env->ExceptionClear();
}
} }
void JMediaRecorder::setCamera(JCamera *camera) void JMediaRecorder::setCamera(JCamera *camera)
@@ -159,8 +177,12 @@ void JMediaRecorder::setVideoEncoder(VideoEncoder encoder)
{ {
QJNIEnvironmentPrivate env; QJNIEnvironmentPrivate env;
callMethod<void>("setVideoEncoder", "(I)V", int(encoder)); callMethod<void>("setVideoEncoder", "(I)V", int(encoder));
if (env->ExceptionCheck()) if (env->ExceptionCheck()) {
#ifdef QT_DEBUG
env->ExceptionDescribe();
#endif
env->ExceptionClear(); env->ExceptionClear();
}
} }
void JMediaRecorder::setVideoEncodingBitRate(int bitRate) void JMediaRecorder::setVideoEncodingBitRate(int bitRate)
@@ -172,40 +194,60 @@ void JMediaRecorder::setVideoFrameRate(int rate)
{ {
QJNIEnvironmentPrivate env; QJNIEnvironmentPrivate env;
callMethod<void>("setVideoFrameRate", "(I)V", rate); callMethod<void>("setVideoFrameRate", "(I)V", rate);
if (env->ExceptionCheck()) if (env->ExceptionCheck()) {
#ifdef QT_DEBUG
env->ExceptionDescribe();
#endif
env->ExceptionClear(); env->ExceptionClear();
}
} }
void JMediaRecorder::setVideoSize(const QSize &size) void JMediaRecorder::setVideoSize(const QSize &size)
{ {
QJNIEnvironmentPrivate env; QJNIEnvironmentPrivate env;
callMethod<void>("setVideoSize", "(II)V", size.width(), size.height()); callMethod<void>("setVideoSize", "(II)V", size.width(), size.height());
if (env->ExceptionCheck()) if (env->ExceptionCheck()) {
#ifdef QT_DEBUG
env->ExceptionDescribe();
#endif
env->ExceptionClear(); env->ExceptionClear();
}
} }
void JMediaRecorder::setVideoSource(VideoSource source) void JMediaRecorder::setVideoSource(VideoSource source)
{ {
QJNIEnvironmentPrivate env; QJNIEnvironmentPrivate env;
callMethod<void>("setVideoSource", "(I)V", int(source)); callMethod<void>("setVideoSource", "(I)V", int(source));
if (env->ExceptionCheck()) if (env->ExceptionCheck()) {
#ifdef QT_DEBUG
env->ExceptionDescribe();
#endif
env->ExceptionClear(); env->ExceptionClear();
}
} }
void JMediaRecorder::setOrientationHint(int degrees) void JMediaRecorder::setOrientationHint(int degrees)
{ {
QJNIEnvironmentPrivate env; QJNIEnvironmentPrivate env;
callMethod<void>("setOrientationHint", "(I)V", degrees); callMethod<void>("setOrientationHint", "(I)V", degrees);
if (env->ExceptionCheck()) if (env->ExceptionCheck()) {
#ifdef QT_DEBUG
env->ExceptionDescribe();
#endif
env->ExceptionClear(); env->ExceptionClear();
}
} }
void JMediaRecorder::setOutputFormat(OutputFormat format) void JMediaRecorder::setOutputFormat(OutputFormat format)
{ {
QJNIEnvironmentPrivate env; QJNIEnvironmentPrivate env;
callMethod<void>("setOutputFormat", "(I)V", int(format)); callMethod<void>("setOutputFormat", "(I)V", int(format));
if (env->ExceptionCheck()) if (env->ExceptionCheck()) {
#ifdef QT_DEBUG
env->ExceptionDescribe();
#endif
env->ExceptionClear(); env->ExceptionClear();
}
} }
void JMediaRecorder::setOutputFile(const QString &path) void JMediaRecorder::setOutputFile(const QString &path)
@@ -214,8 +256,12 @@ void JMediaRecorder::setOutputFile(const QString &path)
callMethod<void>("setOutputFile", callMethod<void>("setOutputFile",
"(Ljava/lang/String;)V", "(Ljava/lang/String;)V",
QJNIObjectPrivate::fromString(path).object()); QJNIObjectPrivate::fromString(path).object());
if (env->ExceptionCheck()) if (env->ExceptionCheck()) {
#ifdef QT_DEBUG
env->ExceptionDescribe();
#endif
env->ExceptionClear(); env->ExceptionClear();
}
} }
static JNINativeMethod methods[] = { static JNINativeMethod methods[] = {

View File

@@ -60,7 +60,8 @@ AVFAudioInputSelectorControl::AVFAudioInputSelectorControl(AVFCameraService *ser
QString::fromUtf8([[device localizedName] UTF8String])); QString::fromUtf8([[device localizedName] UTF8String]));
} }
m_activeInput = m_devices.first(); if (m_devices.size() > 0)
m_activeInput = m_devices.first();
} }
AVFAudioInputSelectorControl::~AVFAudioInputSelectorControl() AVFAudioInputSelectorControl::~AVFAudioInputSelectorControl()
@@ -79,7 +80,7 @@ QString AVFAudioInputSelectorControl::inputDescription(const QString &name) cons
QString AVFAudioInputSelectorControl::defaultInput() const QString AVFAudioInputSelectorControl::defaultInput() const
{ {
return m_devices.first(); return m_devices.size() > 0 ? m_devices.first() : QString();
} }
QString AVFAudioInputSelectorControl::activeInput() const QString AVFAudioInputSelectorControl::activeInput() const

View File

@@ -50,6 +50,7 @@
#ifndef QT_NO_WIDGETS #ifndef QT_NO_WIDGETS
# include "avfvideowidgetcontrol.h" # include "avfvideowidgetcontrol.h"
#endif #endif
#include "avfvideowindowcontrol.h"
QT_USE_NAMESPACE QT_USE_NAMESPACE
@@ -102,6 +103,13 @@ QMediaControl *AVFMediaPlayerService::requestControl(const char *name)
return m_videoOutput; return m_videoOutput;
} }
#endif #endif
if (qstrcmp(name, QVideoWindowControl_iid) == 0) {
if (!m_videoOutput)
m_videoOutput = new AVFVideoWindowControl(this);
m_session->setVideoOutput(qobject_cast<AVFVideoOutput*>(m_videoOutput));
return m_videoOutput;
}
return 0; return 0;
} }

View File

@@ -404,6 +404,8 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe
#ifdef QT_DEBUG_AVF #ifdef QT_DEBUG_AVF
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
#endif #endif
[self unloadMedia];
if (m_player) { if (m_player) {
[m_player removeObserver:self forKeyPath:AVF_CURRENT_ITEM_KEY]; [m_player removeObserver:self forKeyPath:AVF_CURRENT_ITEM_KEY];
[m_player removeObserver:self forKeyPath:AVF_RATE_KEY]; [m_player removeObserver:self forKeyPath:AVF_RATE_KEY];
@@ -416,8 +418,6 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe
m_playerLayer = 0; m_playerLayer = 0;
} }
[self unloadMedia];
if (m_URL) { if (m_URL) {
[m_URL release]; [m_URL release];
} }

View File

@@ -0,0 +1,120 @@
/****************************************************************************
**
** 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.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef AVFVIDEOWINDOWCONTROL_H
#define AVFVIDEOWINDOWCONTROL_H
#include <QVideoWindowControl>
@class AVPlayerLayer;
#if defined(Q_OS_OSX)
@class NSView;
typedef NSView NativeView;
#else
@class UIView;
typedef UIView NativeView;
#endif
#include "avfvideooutput.h"
QT_BEGIN_NAMESPACE
class AVFVideoWindowControl : public QVideoWindowControl, public AVFVideoOutput
{
Q_OBJECT
Q_INTERFACES(AVFVideoOutput)
public:
AVFVideoWindowControl(QObject *parent = 0);
virtual ~AVFVideoWindowControl();
// QVideoWindowControl interface
public:
WId winId() const;
void setWinId(WId id);
QRect displayRect() const;
void setDisplayRect(const QRect &rect);
bool isFullScreen() const;
void setFullScreen(bool fullScreen);
void repaint();
QSize nativeSize() const;
Qt::AspectRatioMode aspectRatioMode() const;
void setAspectRatioMode(Qt::AspectRatioMode mode);
int brightness() const;
void setBrightness(int brightness);
int contrast() const;
void setContrast(int contrast);
int hue() const;
void setHue(int hue);
int saturation() const;
void setSaturation(int saturation);
// AVFVideoOutput interface
void setLayer(void *playerLayer);
private:
void updateAspectRatio();
void updatePlayerLayerBounds();
WId m_winId;
QRect m_displayRect;
bool m_fullscreen;
int m_brightness;
int m_contrast;
int m_hue;
int m_saturation;
Qt::AspectRatioMode m_aspectRatioMode;
QSize m_nativeSize;
AVPlayerLayer *m_playerLayer;
NativeView *m_nativeView;
};
QT_END_NAMESPACE
#endif // AVFVIDEOWINDOWCONTROL_H

View File

@@ -0,0 +1,246 @@
/****************************************************************************
**
** 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.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "avfvideowindowcontrol.h"
#include <AVFoundation/AVFoundation.h>
QT_USE_NAMESPACE
AVFVideoWindowControl::AVFVideoWindowControl(QObject *parent)
: QVideoWindowControl(parent)
, m_winId(0)
, m_fullscreen(false)
, m_brightness(0)
, m_contrast(0)
, m_hue(0)
, m_saturation(0)
, m_aspectRatioMode(Qt::IgnoreAspectRatio)
, m_playerLayer(0)
, m_nativeView(0)
{
}
AVFVideoWindowControl::~AVFVideoWindowControl()
{
if (m_playerLayer)
[m_playerLayer release];
}
WId AVFVideoWindowControl::winId() const
{
return m_winId;
}
void AVFVideoWindowControl::setWinId(WId id)
{
m_winId = id;
m_nativeView = (NativeView*)m_winId;
}
QRect AVFVideoWindowControl::displayRect() const
{
return m_displayRect;
}
void AVFVideoWindowControl::setDisplayRect(const QRect &rect)
{
if (m_displayRect != rect) {
m_displayRect = rect;
updatePlayerLayerBounds();
}
}
bool AVFVideoWindowControl::isFullScreen() const
{
return m_fullscreen;
}
void AVFVideoWindowControl::setFullScreen(bool fullScreen)
{
if (m_fullscreen != fullScreen) {
m_fullscreen = fullScreen;
Q_EMIT QVideoWindowControl::fullScreenChanged(fullScreen);
}
}
void AVFVideoWindowControl::repaint()
{
if (m_playerLayer)
[m_playerLayer setNeedsDisplay];
}
QSize AVFVideoWindowControl::nativeSize() const
{
return m_nativeSize;
}
Qt::AspectRatioMode AVFVideoWindowControl::aspectRatioMode() const
{
return m_aspectRatioMode;
}
void AVFVideoWindowControl::setAspectRatioMode(Qt::AspectRatioMode mode)
{
if (m_aspectRatioMode != mode) {
m_aspectRatioMode = mode;
updateAspectRatio();
}
}
int AVFVideoWindowControl::brightness() const
{
return m_brightness;
}
void AVFVideoWindowControl::setBrightness(int brightness)
{
if (m_brightness != brightness) {
m_brightness = brightness;
Q_EMIT QVideoWindowControl::brightnessChanged(brightness);
}
}
int AVFVideoWindowControl::contrast() const
{
return m_contrast;
}
void AVFVideoWindowControl::setContrast(int contrast)
{
if (m_contrast != contrast) {
m_contrast = contrast;
Q_EMIT QVideoWindowControl::contrastChanged(contrast);
}
}
int AVFVideoWindowControl::hue() const
{
return m_hue;
}
void AVFVideoWindowControl::setHue(int hue)
{
if (m_hue != hue) {
m_hue = hue;
Q_EMIT QVideoWindowControl::hueChanged(hue);
}
}
int AVFVideoWindowControl::saturation() const
{
return m_saturation;
}
void AVFVideoWindowControl::setSaturation(int saturation)
{
if (m_saturation != saturation) {
m_saturation = saturation;
Q_EMIT QVideoWindowControl::saturationChanged(saturation);
}
}
void AVFVideoWindowControl::setLayer(void *playerLayer)
{
AVPlayerLayer *layer = (AVPlayerLayer*)playerLayer;
if (m_playerLayer == layer)
return;
if (!m_winId) {
qDebug("AVFVideoWindowControl: No video window");
return;
}
#if defined(Q_OS_OSX)
[m_nativeView setWantsLayer:YES];
#endif
if (m_playerLayer) {
[m_playerLayer removeFromSuperlayer];
[m_playerLayer release];
}
m_playerLayer = layer;
CALayer *nativeLayer = [m_nativeView layer];
if (layer) {
[layer retain];
m_nativeSize = QSize(m_playerLayer.bounds.size.width,
m_playerLayer.bounds.size.height);
updateAspectRatio();
[nativeLayer addSublayer:m_playerLayer];
updatePlayerLayerBounds();
}
}
void AVFVideoWindowControl::updateAspectRatio()
{
if (m_playerLayer) {
switch (m_aspectRatioMode) {
case Qt::IgnoreAspectRatio:
[m_playerLayer setVideoGravity:AVLayerVideoGravityResize];
break;
case Qt::KeepAspectRatio:
[m_playerLayer setVideoGravity:AVLayerVideoGravityResizeAspect];
break;
case Qt::KeepAspectRatioByExpanding:
[m_playerLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
break;
default:
break;
}
}
}
void AVFVideoWindowControl::updatePlayerLayerBounds()
{
if (m_playerLayer) {
CGRect newBounds = CGRectMake(0, 0,
m_displayRect.width(), m_displayRect.height());
m_playerLayer.bounds = newBounds;
m_playerLayer.position = CGPointMake(m_displayRect.x(), m_displayRect.y());
}
}
#include "moc_avfvideowindowcontrol.cpp"

View File

@@ -21,7 +21,8 @@ HEADERS += \
avfmediaplayerservice.h \ avfmediaplayerservice.h \
avfmediaplayersession.h \ avfmediaplayersession.h \
avfmediaplayerserviceplugin.h \ avfmediaplayerserviceplugin.h \
avfvideooutput.h avfvideooutput.h \
avfvideowindowcontrol.h
OBJECTIVE_SOURCES += \ OBJECTIVE_SOURCES += \
avfmediaplayercontrol.mm \ avfmediaplayercontrol.mm \
@@ -29,7 +30,8 @@ OBJECTIVE_SOURCES += \
avfmediaplayerservice.mm \ avfmediaplayerservice.mm \
avfmediaplayerserviceplugin.mm \ avfmediaplayerserviceplugin.mm \
avfmediaplayersession.mm \ avfmediaplayersession.mm \
avfvideooutput.mm avfvideooutput.mm \
avfvideowindowcontrol.mm
qtHaveModule(widgets) { qtHaveModule(widgets) {
QT += multimediawidgets-private QT += multimediawidgets-private

View File

@@ -147,6 +147,7 @@ void QGstreamerAudioDecoderServicePlugin::updateSupportedMimeTypes() const
} }
} }
} }
gst_caps_unref(caps);
} }
} }
gst_object_unref (factory); gst_object_unref (factory);

View File

@@ -158,6 +158,8 @@ void QGstreamerAudioDecoderSession::configureAppSrcElement(GObject* object, GObj
if (!self->appsrc()->setup(appsrc)) if (!self->appsrc()->setup(appsrc))
qWarning()<<"Could not setup appsrc element"; qWarning()<<"Could not setup appsrc element";
g_object_unref(G_OBJECT(appsrc));
} }
#endif #endif
@@ -372,7 +374,8 @@ void QGstreamerAudioDecoderSession::start()
if (mFormat.isValid()) { if (mFormat.isValid()) {
setAudioFlags(false); setAudioFlags(false);
GstCaps *caps = QGstUtils::capsForAudioFormat(mFormat); GstCaps *caps = QGstUtils::capsForAudioFormat(mFormat);
gst_app_sink_set_caps(m_appSink, caps); // appsink unrefs caps gst_app_sink_set_caps(m_appSink, caps);
gst_caps_unref(caps);
} else { } else {
// We want whatever the native audio format is // We want whatever the native audio format is
setAudioFlags(true); setAudioFlags(true);

View File

@@ -114,11 +114,15 @@ GstEncodingProfile *CameraBinAudioEncoder::createProfile()
else else
caps = gst_caps_from_string(codec.toLatin1()); caps = gst_caps_from_string(codec.toLatin1());
return (GstEncodingProfile *)gst_encoding_audio_profile_new( GstEncodingProfile *profile = (GstEncodingProfile *)gst_encoding_audio_profile_new(
caps, caps,
!preset.isEmpty() ? preset.toLatin1().constData() : NULL, //preset !preset.isEmpty() ? preset.toLatin1().constData() : NULL, //preset
NULL, //restriction NULL, //restriction
0); //presence 0); //presence
gst_caps_unref(caps);
return profile;
} }
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@@ -124,11 +124,15 @@ GstEncodingContainerProfile *CameraBinContainer::createProfile()
caps = gst_caps_from_string(format.toLatin1()); caps = gst_caps_from_string(format.toLatin1());
} }
return (GstEncodingContainerProfile *)gst_encoding_container_profile_new( GstEncodingContainerProfile *profile = (GstEncodingContainerProfile *)gst_encoding_container_profile_new(
"camerabin2_profile", "camerabin2_profile",
(gchar *)"custom camera profile", (gchar *)"custom camera profile",
caps, caps,
NULL); //preset NULL); //preset
gst_caps_unref(caps);
return profile;
} }
/*! /*!

View File

@@ -191,10 +191,14 @@ GstEncodingContainerProfile *CameraBinRecorder::videoProfile()
GstEncodingProfile *audioProfile = m_session->audioEncodeControl()->createProfile(); GstEncodingProfile *audioProfile = m_session->audioEncodeControl()->createProfile();
GstEncodingProfile *videoProfile = m_session->videoEncodeControl()->createProfile(); GstEncodingProfile *videoProfile = m_session->videoEncodeControl()->createProfile();
if (audioProfile) if (audioProfile) {
gst_encoding_container_profile_add_profile(containerProfile, audioProfile); if (!gst_encoding_container_profile_add_profile(containerProfile, audioProfile))
if (videoProfile) gst_encoding_profile_unref(audioProfile);
gst_encoding_container_profile_add_profile(containerProfile, videoProfile); }
if (videoProfile) {
if (!gst_encoding_container_profile_add_profile(containerProfile, videoProfile))
gst_encoding_profile_unref(videoProfile);
}
} }
return containerProfile; return containerProfile;

View File

@@ -61,6 +61,7 @@
#include "camerabincapturebufferformat.h" #include "camerabincapturebufferformat.h"
#include <private/qgstreamerbushelper_p.h> #include <private/qgstreamerbushelper_p.h>
#include <private/qgstreamervideorendererinterface_p.h> #include <private/qgstreamervideorendererinterface_p.h>
#include <private/qgstutils_p.h>
#include <qmediarecorder.h> #include <qmediarecorder.h>
#ifdef HAVE_GST_PHOTOGRAPHY #ifdef HAVE_GST_PHOTOGRAPHY
@@ -108,9 +109,6 @@
#define CAMERABIN_IMAGE_MODE 1 #define CAMERABIN_IMAGE_MODE 1
#define CAMERABIN_VIDEO_MODE 2 #define CAMERABIN_VIDEO_MODE 2
#define gstRef(element) { gst_object_ref(GST_OBJECT(element)); gst_object_sink(GST_OBJECT(element)); }
#define gstUnref(element) { if (element) { gst_object_unref(GST_OBJECT(element)); element = 0; } }
#define PREVIEW_CAPS_4_3 \ #define PREVIEW_CAPS_4_3 \
"video/x-raw-rgb, width = (int) 640, height = (int) 480" "video/x-raw-rgb, width = (int) 640, height = (int) 480"
@@ -146,7 +144,7 @@ CameraBinSession::CameraBinSession(QObject *parent)
{ {
m_camerabin = gst_element_factory_make("camerabin2", "camerabin2"); m_camerabin = gst_element_factory_make("camerabin2", "camerabin2");
g_signal_connect(G_OBJECT(m_camerabin), "notify::idle", G_CALLBACK(updateBusyStatus), this); g_signal_connect(G_OBJECT(m_camerabin), "notify::idle", G_CALLBACK(updateBusyStatus), this);
gstRef(m_camerabin); qt_gst_object_ref_sink(m_camerabin);
m_bus = gst_element_get_bus(m_camerabin); m_bus = gst_element_get_bus(m_camerabin);
@@ -192,9 +190,11 @@ CameraBinSession::~CameraBinSession()
gst_element_set_state(m_camerabin, GST_STATE_NULL); gst_element_set_state(m_camerabin, GST_STATE_NULL);
gst_element_get_state(m_camerabin, NULL, NULL, GST_CLOCK_TIME_NONE); gst_element_get_state(m_camerabin, NULL, NULL, GST_CLOCK_TIME_NONE);
gstUnref(m_camerabin); gst_object_unref(GST_OBJECT(m_bus));
gstUnref(m_viewfinderElement); gst_object_unref(GST_OBJECT(m_camerabin));
} }
if (m_viewfinderElement)
gst_object_unref(GST_OBJECT(m_viewfinderElement));
} }
#ifdef HAVE_GST_PHOTOGRAPHY #ifdef HAVE_GST_PHOTOGRAPHY
@@ -239,7 +239,7 @@ bool CameraBinSession::setupCameraBin()
qWarning() << "Staring camera without viewfinder available"; qWarning() << "Staring camera without viewfinder available";
m_viewfinderElement = gst_element_factory_make("fakesink", NULL); m_viewfinderElement = gst_element_factory_make("fakesink", NULL);
} }
gst_object_ref(GST_OBJECT(m_viewfinderElement)); qt_gst_object_ref_sink(GST_OBJECT(m_viewfinderElement));
gst_element_set_state(m_camerabin, GST_STATE_NULL); gst_element_set_state(m_camerabin, GST_STATE_NULL);
g_object_set(G_OBJECT(m_camerabin), VIEWFINDER_SINK_PROPERTY, m_viewfinderElement, NULL); g_object_set(G_OBJECT(m_camerabin), VIEWFINDER_SINK_PROPERTY, m_viewfinderElement, NULL);
} }
@@ -438,6 +438,9 @@ GstElement *CameraBinSession::buildCameraSource()
if (m_videoSrc != videoSrc) if (m_videoSrc != videoSrc)
g_object_set(G_OBJECT(m_camerabin), CAMERA_SOURCE_PROPERTY, m_videoSrc, NULL); g_object_set(G_OBJECT(m_camerabin), CAMERA_SOURCE_PROPERTY, m_videoSrc, NULL);
if (videoSrc)
gst_object_unref(GST_OBJECT(videoSrc));
return m_videoSrc; return m_videoSrc;
} }
@@ -680,10 +683,12 @@ void CameraBinSession::setState(QCamera::State newState)
m_recorderControl->applySettings(); m_recorderControl->applySettings();
GstEncodingContainerProfile *profile = m_recorderControl->videoProfile();
g_object_set (G_OBJECT(m_camerabin), g_object_set (G_OBJECT(m_camerabin),
"video-profile", "video-profile",
m_recorderControl->videoProfile(), profile,
NULL); NULL);
gst_encoding_profile_unref(profile);
setAudioCaptureCaps(); setAudioCaptureCaps();
@@ -803,6 +808,7 @@ void CameraBinSession::setMetaData(const QMap<QByteArray, QVariant> &data)
} }
} }
} }
gst_iterator_free(elements);
} }
} }

View File

@@ -175,6 +175,8 @@ GstEncodingProfile *CameraBinVideoEncoder::createProfile()
NULL, //restriction NULL, //restriction
1); //presence 1); //presence
gst_caps_unref(caps);
gst_encoding_video_profile_set_pass(profile, 0); gst_encoding_video_profile_set_pass(profile, 0);
gst_encoding_video_profile_set_variableframerate(profile, TRUE); gst_encoding_video_profile_set_variableframerate(profile, TRUE);

View File

@@ -196,6 +196,8 @@ GstElement *QGstreamerAudioEncode::createEncoder()
//qDebug() << "set caps filter:" << gst_caps_to_string(caps); //qDebug() << "set caps filter:" << gst_caps_to_string(caps);
g_object_set(G_OBJECT(capsFilter), "caps", caps, NULL); g_object_set(G_OBJECT(capsFilter), "caps", caps, NULL);
gst_caps_unref(caps);
} }
if (encoderElement) { if (encoderElement) {

View File

@@ -261,6 +261,7 @@ void QGstreamerCaptureServicePlugin::updateSupportedMimeTypes() const
} }
} }
} }
gst_caps_unref(caps);
} }
} }
gst_object_unref (factory); gst_object_unref (factory);

View File

@@ -49,6 +49,7 @@
#include <private/qgstreamervideorendererinterface_p.h> #include <private/qgstreamervideorendererinterface_p.h>
#include <private/qgstreameraudioprobecontrol_p.h> #include <private/qgstreameraudioprobecontrol_p.h>
#include <private/qgstreamerbushelper_p.h> #include <private/qgstreamerbushelper_p.h>
#include <private/qgstutils_p.h>
#include <gst/gsttagsetter.h> #include <gst/gsttagsetter.h>
#include <gst/gstversion.h> #include <gst/gstversion.h>
@@ -64,9 +65,6 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
#define gstRef(element) { gst_object_ref(GST_OBJECT(element)); gst_object_sink(GST_OBJECT(element)); }
#define gstUnref(element) { if (element) { gst_object_unref(GST_OBJECT(element)); element = 0; } }
QGstreamerCaptureSession::QGstreamerCaptureSession(QGstreamerCaptureSession::CaptureMode captureMode, QObject *parent) QGstreamerCaptureSession::QGstreamerCaptureSession(QGstreamerCaptureSession::CaptureMode captureMode, QObject *parent)
:QObject(parent), :QObject(parent),
m_state(StoppedState), m_state(StoppedState),
@@ -97,7 +95,7 @@ QGstreamerCaptureSession::QGstreamerCaptureSession(QGstreamerCaptureSession::Cap
m_passPrerollImage(false) m_passPrerollImage(false)
{ {
m_pipeline = gst_pipeline_new("media-capture-pipeline"); m_pipeline = gst_pipeline_new("media-capture-pipeline");
gstRef(m_pipeline); qt_gst_object_ref_sink(m_pipeline);
m_bus = gst_element_get_bus(m_pipeline); m_bus = gst_element_get_bus(m_pipeline);
m_busHelper = new QGstreamerBusHelper(m_bus, this); m_busHelper = new QGstreamerBusHelper(m_bus, this);
@@ -116,6 +114,7 @@ QGstreamerCaptureSession::~QGstreamerCaptureSession()
{ {
setState(StoppedState); setState(StoppedState);
gst_element_set_state(m_pipeline, GST_STATE_NULL); gst_element_set_state(m_pipeline, GST_STATE_NULL);
gst_object_unref(GST_OBJECT(m_bus));
gst_object_unref(GST_OBJECT(m_pipeline)); gst_object_unref(GST_OBJECT(m_pipeline));
} }
@@ -160,6 +159,7 @@ GstElement *QGstreamerCaptureSession::buildEncodeBin()
gst_bin_add(GST_BIN(encodeBin), audioEncoder); gst_bin_add(GST_BIN(encodeBin), audioEncoder);
if (!gst_element_link_many(audioConvert, audioQueue, m_audioVolume, audioEncoder, muxer, NULL)) { if (!gst_element_link_many(audioConvert, audioQueue, m_audioVolume, audioEncoder, muxer, NULL)) {
m_audioVolume = 0;
gst_object_unref(encodeBin); gst_object_unref(encodeBin);
return 0; return 0;
} }
@@ -333,6 +333,7 @@ GstElement *QGstreamerCaptureSession::buildVideoPreview()
g_object_set(G_OBJECT(capsFilter), "caps", caps, NULL); g_object_set(G_OBJECT(capsFilter), "caps", caps, NULL);
gst_caps_unref(caps);
} }
// add ghostpads // add ghostpads
@@ -501,6 +502,7 @@ GstElement *QGstreamerCaptureSession::buildImageCapture()
GstPad *pad = gst_element_get_static_pad(queue, "src"); GstPad *pad = gst_element_get_static_pad(queue, "src");
Q_ASSERT(pad); Q_ASSERT(pad);
gst_pad_add_buffer_probe(pad, G_CALLBACK(passImageFilter), this); gst_pad_add_buffer_probe(pad, G_CALLBACK(passImageFilter), this);
gst_object_unref(GST_OBJECT(pad));
g_object_set(G_OBJECT(sink), "signal-handoffs", TRUE, NULL); g_object_set(G_OBJECT(sink), "signal-handoffs", TRUE, NULL);
g_signal_connect(G_OBJECT(sink), "handoff", g_signal_connect(G_OBJECT(sink), "handoff",
@@ -531,6 +533,7 @@ void QGstreamerCaptureSession::captureImage(int requestId, const QString &fileNa
#define REMOVE_ELEMENT(element) { if (element) {gst_bin_remove(GST_BIN(m_pipeline), element); element = 0;} } #define REMOVE_ELEMENT(element) { if (element) {gst_bin_remove(GST_BIN(m_pipeline), element); element = 0;} }
#define UNREF_ELEMENT(element) { if (element) { gst_object_unref(GST_OBJECT(element)); element = 0; } }
bool QGstreamerCaptureSession::rebuildGraph(QGstreamerCaptureSession::PipelineMode newMode) bool QGstreamerCaptureSession::rebuildGraph(QGstreamerCaptureSession::PipelineMode newMode)
{ {
@@ -562,6 +565,9 @@ bool QGstreamerCaptureSession::rebuildGraph(QGstreamerCaptureSession::PipelineMo
if (ok) { if (ok) {
gst_bin_add_many(GST_BIN(m_pipeline), m_audioSrc, m_audioPreview, NULL); gst_bin_add_many(GST_BIN(m_pipeline), m_audioSrc, m_audioPreview, NULL);
ok &= gst_element_link(m_audioSrc, m_audioPreview); ok &= gst_element_link(m_audioSrc, m_audioPreview);
} else {
UNREF_ELEMENT(m_audioSrc);
UNREF_ELEMENT(m_audioPreview);
} }
} }
if (m_captureMode & Video || m_captureMode & Image) { if (m_captureMode & Video || m_captureMode & Image) {
@@ -582,6 +588,12 @@ bool QGstreamerCaptureSession::rebuildGraph(QGstreamerCaptureSession::PipelineMo
ok &= gst_element_link(m_videoTee, m_videoPreviewQueue); ok &= gst_element_link(m_videoTee, m_videoPreviewQueue);
ok &= gst_element_link(m_videoPreviewQueue, m_videoPreview); ok &= gst_element_link(m_videoPreviewQueue, m_videoPreview);
ok &= gst_element_link(m_videoTee, m_imageCaptureBin); ok &= gst_element_link(m_videoTee, m_imageCaptureBin);
} else {
UNREF_ELEMENT(m_videoSrc);
UNREF_ELEMENT(m_videoTee);
UNREF_ELEMENT(m_videoPreviewQueue);
UNREF_ELEMENT(m_videoPreview);
UNREF_ELEMENT(m_imageCaptureBin);
} }
} }
break; break;
@@ -631,6 +643,11 @@ bool QGstreamerCaptureSession::rebuildGraph(QGstreamerCaptureSession::PipelineMo
ok &= gst_element_link(m_audioTee, m_audioPreviewQueue); ok &= gst_element_link(m_audioTee, m_audioPreviewQueue);
ok &= gst_element_link(m_audioPreviewQueue, m_audioPreview); ok &= gst_element_link(m_audioPreviewQueue, m_audioPreview);
ok &= gst_element_link(m_audioTee, m_encodeBin); ok &= gst_element_link(m_audioTee, m_encodeBin);
} else {
UNREF_ELEMENT(m_audioSrc);
UNREF_ELEMENT(m_audioPreview);
UNREF_ELEMENT(m_audioTee);
UNREF_ELEMENT(m_audioPreviewQueue);
} }
} }
@@ -648,6 +665,11 @@ bool QGstreamerCaptureSession::rebuildGraph(QGstreamerCaptureSession::PipelineMo
ok &= gst_element_link(m_videoSrc, m_videoTee); ok &= gst_element_link(m_videoSrc, m_videoTee);
ok &= gst_element_link(m_videoTee, m_videoPreviewQueue); ok &= gst_element_link(m_videoTee, m_videoPreviewQueue);
ok &= gst_element_link(m_videoPreviewQueue, m_videoPreview); ok &= gst_element_link(m_videoPreviewQueue, m_videoPreview);
} else {
UNREF_ELEMENT(m_videoSrc);
UNREF_ELEMENT(m_videoTee);
UNREF_ELEMENT(m_videoPreviewQueue);
UNREF_ELEMENT(m_videoPreview);
} }
if (ok && (m_captureMode & Video)) if (ok && (m_captureMode & Video))
@@ -917,6 +939,7 @@ void QGstreamerCaptureSession::setMetaData(const QMap<QByteArray, QVariant> &dat
} }
} }
gst_iterator_free(elements);
} }
} }
@@ -1096,8 +1119,10 @@ void QGstreamerCaptureSession::removeAudioBufferProbe()
return; return;
GstPad *pad = getAudioProbePad(); GstPad *pad = getAudioProbePad();
if (pad) if (pad) {
gst_pad_remove_buffer_probe(pad, m_audioBufferProbeId); gst_pad_remove_buffer_probe(pad, m_audioBufferProbeId);
gst_object_unref(G_OBJECT(pad));
}
m_audioBufferProbeId = -1; m_audioBufferProbeId = -1;
} }
@@ -1107,8 +1132,10 @@ void QGstreamerCaptureSession::addAudioBufferProbe()
Q_ASSERT(m_audioBufferProbeId == -1); Q_ASSERT(m_audioBufferProbeId == -1);
GstPad *pad = getAudioProbePad(); GstPad *pad = getAudioProbePad();
if (pad) if (pad) {
m_audioBufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padAudioBufferProbe), this); m_audioBufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padAudioBufferProbe), this);
gst_object_unref(G_OBJECT(pad));
}
} }
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@@ -286,6 +286,8 @@ GstElement *QGstreamerVideoEncode::createEncoder()
//qDebug() << "set video caps filter:" << gst_caps_to_string(caps); //qDebug() << "set video caps filter:" << gst_caps_to_string(caps);
g_object_set(G_OBJECT(capsFilter), "caps", caps, NULL); g_object_set(G_OBJECT(capsFilter), "caps", caps, NULL);
gst_caps_unref(caps);
} }
return GST_ELEMENT(encoderBin); return GST_ELEMENT(encoderBin);

View File

@@ -48,6 +48,7 @@
#include <private/gstvideoconnector_p.h> #include <private/gstvideoconnector_p.h>
#include <private/qgstutils_p.h> #include <private/qgstutils_p.h>
#include <private/playlistfileparser_p.h> #include <private/playlistfileparser_p.h>
#include <private/qgstutils_p.h>
#include <gst/gstvalue.h> #include <gst/gstvalue.h>
#include <gst/base/gstbasesrc.h> #include <gst/base/gstbasesrc.h>
@@ -157,17 +158,20 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent)
} }
} }
m_videoOutputBin = gst_bin_new("video-output-bin"); m_videoIdentity = GST_ELEMENT(g_object_new(gst_video_connector_get_type(), 0)); // floating ref
gst_object_ref(GST_OBJECT(m_videoOutputBin));
m_videoIdentity = GST_ELEMENT(g_object_new(gst_video_connector_get_type(), 0));
g_signal_connect(G_OBJECT(m_videoIdentity), "connection-failed", G_CALLBACK(insertColorSpaceElement), (gpointer)this); g_signal_connect(G_OBJECT(m_videoIdentity), "connection-failed", G_CALLBACK(insertColorSpaceElement), (gpointer)this);
m_colorSpace = gst_element_factory_make("ffmpegcolorspace", "ffmpegcolorspace-vo"); m_colorSpace = gst_element_factory_make("ffmpegcolorspace", "ffmpegcolorspace-vo");
gst_object_ref(GST_OBJECT(m_colorSpace)); // might not get a parent, take ownership to avoid leak
qt_gst_object_ref_sink(GST_OBJECT(m_colorSpace));
m_nullVideoSink = gst_element_factory_make("fakesink", NULL); m_nullVideoSink = gst_element_factory_make("fakesink", NULL);
g_object_set(G_OBJECT(m_nullVideoSink), "sync", true, NULL); g_object_set(G_OBJECT(m_nullVideoSink), "sync", true, NULL);
gst_object_ref(GST_OBJECT(m_nullVideoSink)); gst_object_ref(GST_OBJECT(m_nullVideoSink));
m_videoOutputBin = gst_bin_new("video-output-bin");
// might not get a parent, take ownership to avoid leak
qt_gst_object_ref_sink(GST_OBJECT(m_videoOutputBin));
gst_bin_add_many(GST_BIN(m_videoOutputBin), m_videoIdentity, m_nullVideoSink, NULL); gst_bin_add_many(GST_BIN(m_videoOutputBin), m_videoIdentity, m_nullVideoSink, NULL);
gst_element_link(m_videoIdentity, m_nullVideoSink); gst_element_link(m_videoIdentity, m_nullVideoSink);
@@ -238,6 +242,8 @@ void QGstreamerPlayerSession::configureAppSrcElement(GObject* object, GObject *o
if (!self->appsrc()->setup(appsrc)) if (!self->appsrc()->setup(appsrc))
qWarning()<<"Could not setup appsrc element"; qWarning()<<"Could not setup appsrc element";
g_object_unref(G_OBJECT(appsrc));
} }
#endif #endif
@@ -327,7 +333,7 @@ void QGstreamerPlayerSession::setPlaybackRate(qreal rate)
#endif #endif
if (!qFuzzyCompare(m_playbackRate, rate)) { if (!qFuzzyCompare(m_playbackRate, rate)) {
m_playbackRate = rate; m_playbackRate = rate;
if (m_playbin) { if (m_playbin && m_seekable) {
gst_element_seek(m_playbin, rate, GST_FORMAT_TIME, gst_element_seek(m_playbin, rate, GST_FORMAT_TIME,
GstSeekFlags(GST_SEEK_FLAG_FLUSH), GstSeekFlags(GST_SEEK_FLAG_FLUSH),
GST_SEEK_TYPE_NONE,0, GST_SEEK_TYPE_NONE,0,
@@ -877,7 +883,7 @@ bool QGstreamerPlayerSession::seek(qint64 ms)
qDebug() << Q_FUNC_INFO << ms; qDebug() << Q_FUNC_INFO << ms;
#endif #endif
//seek locks when the video output sink is changing and pad is blocked //seek locks when the video output sink is changing and pad is blocked
if (m_playbin && !m_pendingVideoSink && m_state != QMediaPlayer::StoppedState) { if (m_playbin && !m_pendingVideoSink && m_state != QMediaPlayer::StoppedState && m_seekable) {
ms = qMax(ms,qint64(0)); ms = qMax(ms,qint64(0));
gint64 position = ms * 1000000; gint64 position = ms * 1000000;
bool isSeeking = gst_element_seek(m_playbin, bool isSeeking = gst_element_seek(m_playbin,

View File

@@ -55,6 +55,7 @@ Q_GLOBAL_STATIC(QOpenSLESEngine, openslesEngine);
QOpenSLESEngine::QOpenSLESEngine() QOpenSLESEngine::QOpenSLESEngine()
: m_engineObject(0) : m_engineObject(0)
, m_engine(0) , m_engine(0)
, m_checkedInputFormats(false)
{ {
SLresult result; SLresult result;
@@ -66,8 +67,6 @@ QOpenSLESEngine::QOpenSLESEngine()
result = (*m_engineObject)->GetInterface(m_engineObject, SL_IID_ENGINE, &m_engine); result = (*m_engineObject)->GetInterface(m_engineObject, SL_IID_ENGINE, &m_engine);
CheckError("Failed to get engine interface"); CheckError("Failed to get engine interface");
checkSupportedInputFormats();
} }
QOpenSLESEngine::~QOpenSLESEngine() QOpenSLESEngine::~QOpenSLESEngine()
@@ -118,15 +117,20 @@ QList<QByteArray> QOpenSLESEngine::availableDevices(QAudio::Mode mode) const
QList<int> QOpenSLESEngine::supportedChannelCounts(QAudio::Mode mode) const QList<int> QOpenSLESEngine::supportedChannelCounts(QAudio::Mode mode) const
{ {
if (mode == QAudio::AudioInput) if (mode == QAudio::AudioInput) {
if (!m_checkedInputFormats)
const_cast<QOpenSLESEngine *>(this)->checkSupportedInputFormats();
return m_supportedInputChannelCounts; return m_supportedInputChannelCounts;
else } else {
return QList<int>() << 1 << 2; return QList<int>() << 1 << 2;
}
} }
QList<int> QOpenSLESEngine::supportedSampleRates(QAudio::Mode mode) const QList<int> QOpenSLESEngine::supportedSampleRates(QAudio::Mode mode) const
{ {
if (mode == QAudio::AudioInput) { if (mode == QAudio::AudioInput) {
if (!m_checkedInputFormats)
const_cast<QOpenSLESEngine *>(this)->checkSupportedInputFormats();
return m_supportedInputSampleRates; return m_supportedInputSampleRates;
} else { } else {
return QList<int>() << 8000 << 11025 << 12000 << 16000 << 22050 return QList<int>() << 8000 << 11025 << 12000 << 16000 << 22050
@@ -177,6 +181,8 @@ void QOpenSLESEngine::checkSupportedInputFormats()
if (inputFormatIsSupported(format)) if (inputFormatIsSupported(format))
m_supportedInputChannelCounts.append(2); m_supportedInputChannelCounts.append(2);
} }
m_checkedInputFormats = true;
} }
bool QOpenSLESEngine::inputFormatIsSupported(SLDataFormat_PCM format) bool QOpenSLESEngine::inputFormatIsSupported(SLDataFormat_PCM format)

View File

@@ -75,6 +75,7 @@ private:
QList<int> m_supportedInputChannelCounts; QList<int> m_supportedInputChannelCounts;
QList<int> m_supportedInputSampleRates; QList<int> m_supportedInputSampleRates;
bool m_checkedInputFormats;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@@ -103,11 +103,15 @@ bool BpsMediaPlayerControl::nativeEventFilter(const QByteArray &eventType, void
} }
if (bps_event_get_code(event) == MMRENDERER_STATUS_UPDATE) { if (bps_event_get_code(event) == MMRENDERER_STATUS_UPDATE) {
const qint64 newPosition = QString::fromLatin1(mmrenderer_event_get_position(event)).toLongLong(); const qint64 newPosition = QString::fromLatin1(mmrenderer_event_get_position(event)).
toLongLong();
handleMmStatusUpdate(newPosition); handleMmStatusUpdate(newPosition);
const QString bufferStatus = QString::fromLatin1(mmrenderer_event_get_bufferlevel(event)); const QString status = QString::fromLatin1(mmrenderer_event_get_bufferstatus(event));
setMmBufferStatus(bufferStatus); setMmBufferStatus(status);
const QString level = QString::fromLatin1(mmrenderer_event_get_bufferlevel(event));
setMmBufferLevel(level);
} }
} }

View File

@@ -73,7 +73,7 @@ MmRendererMediaPlayerControl::MmRendererMediaPlayerControl(QObject *parent)
m_playAfterMediaLoaded(false), m_playAfterMediaLoaded(false),
m_inputAttached(false), m_inputAttached(false),
m_stopEventsToIgnore(0), m_stopEventsToIgnore(0),
m_bufferStatus(0) m_bufferLevel(0)
{ {
m_loadingTimer.setSingleShot(true); m_loadingTimer.setSingleShot(true);
m_loadingTimer.setInterval(0); m_loadingTimer.setInterval(0);
@@ -234,8 +234,11 @@ void MmRendererMediaPlayerControl::attach()
m_inputAttached = true; m_inputAttached = true;
setMediaStatus(QMediaPlayer::LoadedMedia); setMediaStatus(QMediaPlayer::LoadedMedia);
m_bufferStatus = 0;
emit bufferStatusChanged(m_bufferStatus); // mm-renderer has buffer properties "status" and "level"
// QMediaPlayer's buffer status maps to mm-renderer's buffer level
m_bufferLevel = 0;
emit bufferStatusChanged(m_bufferLevel);
} }
void MmRendererMediaPlayerControl::detach() void MmRendererMediaPlayerControl::detach()
@@ -406,7 +409,9 @@ void MmRendererMediaPlayerControl::setMuted(bool muted)
int MmRendererMediaPlayerControl::bufferStatus() const int MmRendererMediaPlayerControl::bufferStatus() const
{ {
return m_bufferStatus; // mm-renderer has buffer properties "status" and "level"
// QMediaPlayer's buffer status maps to mm-renderer's buffer level
return m_bufferLevel;
} }
bool MmRendererMediaPlayerControl::isAudioAvailable() const bool MmRendererMediaPlayerControl::isAudioAvailable() const
@@ -585,13 +590,23 @@ void MmRendererMediaPlayerControl::setMmPosition(qint64 newPosition)
void MmRendererMediaPlayerControl::setMmBufferStatus(const QString &bufferStatus) void MmRendererMediaPlayerControl::setMmBufferStatus(const QString &bufferStatus)
{ {
const int slashPos = bufferStatus.indexOf('/'); if (bufferStatus == QLatin1String("buffering"))
setMediaStatus(QMediaPlayer::BufferingMedia);
else if (bufferStatus == QLatin1String("playing"))
setMediaStatus(QMediaPlayer::BufferedMedia);
// ignore "idle" buffer status
}
void MmRendererMediaPlayerControl::setMmBufferLevel(const QString &bufferLevel)
{
// buffer level has format level/capacity, e.g. "91319/124402"
const int slashPos = bufferLevel.indexOf('/');
if (slashPos != -1) { if (slashPos != -1) {
const int fill = bufferStatus.leftRef(slashPos).toInt(); const int fill = bufferLevel.leftRef(slashPos).toInt();
const int capacity = bufferStatus.midRef(slashPos + 1).toInt(); const int capacity = bufferLevel.midRef(slashPos + 1).toInt();
if (capacity != 0) { if (capacity != 0) {
m_bufferStatus = fill / static_cast<float>(capacity) * 100.0f; m_bufferLevel = fill / static_cast<float>(capacity) * 100.0f;
emit bufferStatusChanged(m_bufferStatus); emit bufferStatusChanged(m_bufferLevel);
} }
} }
} }

View File

@@ -115,6 +115,7 @@ protected:
void emitPError(const QString &msg); void emitPError(const QString &msg);
void setMmPosition(qint64 newPosition); void setMmPosition(qint64 newPosition);
void setMmBufferStatus(const QString &bufferStatus); void setMmBufferStatus(const QString &bufferStatus);
void setMmBufferLevel(const QString &bufferLevel);
void handleMmStopped(); void handleMmStopped();
void handleMmStatusUpdate(qint64 position); void handleMmStatusUpdate(qint64 position);
@@ -162,7 +163,7 @@ private:
bool m_playAfterMediaLoaded; bool m_playAfterMediaLoaded;
bool m_inputAttached; bool m_inputAttached;
int m_stopEventsToIgnore; int m_stopEventsToIgnore;
int m_bufferStatus; int m_bufferLevel;
QString m_tempMediaFileName; QString m_tempMediaFileName;
QTimer m_loadingTimer; QTimer m_loadingTimer;
}; };

View File

@@ -171,9 +171,12 @@ void PpsMediaPlayerControl::ppsReadyRead(int fd)
pps_decoder_push(&decoder, 0); pps_decoder_push(&decoder, 0);
const char *value = 0; const char *value = 0;
if (pps_decoder_get_string(&decoder, "bufferlevel", &value) == PPS_DECODER_OK) {
if (pps_decoder_get_string(&decoder, "bufferstatus", &value) == PPS_DECODER_OK)
setMmBufferStatus(QString::fromLatin1(value)); setMmBufferStatus(QString::fromLatin1(value));
}
if (pps_decoder_get_string(&decoder, "bufferlevel", &value) == PPS_DECODER_OK)
setMmBufferLevel(QString::fromLatin1(value));
if (pps_decoder_get_string(&decoder, "state", &value) == PPS_DECODER_OK) { if (pps_decoder_get_string(&decoder, "state", &value) == PPS_DECODER_OK) {
const QByteArray state = value; const QByteArray state = value;

View File

@@ -257,6 +257,7 @@ namespace
, m_bufferStartTime(-1) , m_bufferStartTime(-1)
, m_bufferDuration(-1) , m_bufferDuration(-1)
, m_presentationClock(0) , m_presentationClock(0)
, m_sampleRequested(false)
, m_currentMediaType(0) , m_currentMediaType(0)
, m_prerolling(false) , m_prerolling(false)
, m_prerollTargetTime(0) , m_prerollTargetTime(0)
@@ -854,6 +855,15 @@ namespace
schedulePresentation(true); schedulePresentation(true);
} }
void clearScheduledFrame()
{
QMutexLocker locker(&m_mutex);
if (m_scheduledBuffer) {
m_scheduledBuffer->Release();
m_scheduledBuffer = NULL;
}
}
enum enum
{ {
StartSurface = QEvent::User, StartSurface = QEvent::User,
@@ -871,7 +881,7 @@ namespace
{ {
} }
int targetTime() MFTIME targetTime()
{ {
return m_time; return m_time;
} }
@@ -1317,6 +1327,8 @@ namespace
HRESULT processSampleData(IMFSample *pSample) HRESULT processSampleData(IMFSample *pSample)
{ {
m_sampleRequested = false;
LONGLONG time, duration = -1; LONGLONG time, duration = -1;
HRESULT hr = pSample->GetSampleTime(&time); HRESULT hr = pSample->GetSampleTime(&time);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
@@ -1392,7 +1404,9 @@ namespace
m_bufferCache.pop_front(); m_bufferCache.pop_front();
if (timeOK && currentTime > sb.m_time) { if (timeOK && currentTime > sb.m_time) {
sb.m_buffer->Release(); sb.m_buffer->Release();
#ifdef DEBUG_MEDIAFOUNDATION
qDebug() << "currentPresentTime =" << float(currentTime / 10000) * 0.001f << " and sampleTime is" << float(sb.m_time / 10000) * 0.001f; qDebug() << "currentPresentTime =" << float(currentTime / 10000) * 0.001f << " and sampleTime is" << float(sb.m_time / 10000) * 0.001f;
#endif
continue; continue;
} }
m_scheduledBuffer = sb.m_buffer; m_scheduledBuffer = sb.m_buffer;
@@ -1404,13 +1418,16 @@ namespace
break; break;
} }
} }
if (requestSample && m_bufferCache.size() < BUFFER_CACHE_SIZE) if (requestSample && !m_sampleRequested && m_bufferCache.size() < BUFFER_CACHE_SIZE) {
m_sampleRequested = true;
queueEvent(MEStreamSinkRequestSample, GUID_NULL, S_OK, NULL); queueEvent(MEStreamSinkRequestSample, GUID_NULL, S_OK, NULL);
}
} }
IMFMediaBuffer *m_scheduledBuffer; IMFMediaBuffer *m_scheduledBuffer;
MFTIME m_bufferStartTime; MFTIME m_bufferStartTime;
MFTIME m_bufferDuration; MFTIME m_bufferDuration;
IMFPresentationClock *m_presentationClock; IMFPresentationClock *m_presentationClock;
bool m_sampleRequested;
float m_rate; float m_rate;
}; };
@@ -1478,6 +1495,14 @@ namespace
m_stream->present(); m_stream->present();
} }
void clearScheduledFrame()
{
QMutexLocker locker(&m_mutex);
if (m_shutdown)
return;
m_stream->clearScheduledFrame();
}
MFTIME getTime() MFTIME getTime()
{ {
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
@@ -2064,6 +2089,14 @@ namespace
m_sink->present(); m_sink->present();
} }
void clearScheduledFrame()
{
QMutexLocker locker(&m_mutex);
if (!m_sink)
return;
m_sink->clearScheduledFrame();
}
MFTIME getTime() MFTIME getTime()
{ {
if (m_sink) if (m_sink)
@@ -2168,10 +2201,16 @@ void MFVideoRendererControl::customEvent(QEvent *event)
MFTIME targetTime = static_cast<MediaStream::PresentEvent*>(event)->targetTime(); MFTIME targetTime = static_cast<MediaStream::PresentEvent*>(event)->targetTime();
MFTIME currentTime = static_cast<VideoRendererActivate*>(m_currentActivate)->getTime(); MFTIME currentTime = static_cast<VideoRendererActivate*>(m_currentActivate)->getTime();
float playRate = static_cast<VideoRendererActivate*>(m_currentActivate)->getPlayRate(); float playRate = static_cast<VideoRendererActivate*>(m_currentActivate)->getPlayRate();
if (playRate > 0.0001f && targetTime > currentTime) if (!qFuzzyIsNull(playRate)) {
QTimer::singleShot(int((float)((targetTime - currentTime) / 10000) / playRate), this, SLOT(present())); // If the scheduled frame is too late or too much in advance, skip it
else const int diff = (targetTime - currentTime) / 10000;
if (diff < 0 || diff > 500)
static_cast<VideoRendererActivate*>(m_currentActivate)->clearScheduledFrame();
else
QTimer::singleShot(diff / playRate, this, SLOT(present()));
} else {
present(); present();
}
return; return;
} }
if (event->type() >= MediaStream::StartSurface) { if (event->type() >= MediaStream::StartSurface) {

View File

@@ -464,7 +464,7 @@ void QDeclarativeVideoOutput::setOrientation(int orientation)
} }
/*! /*!
\qmlproperty int QtMultimedia::VideoOutput::autoOrientation \qmlproperty bool QtMultimedia::VideoOutput::autoOrientation
This property allows you to enable and disable auto orientation This property allows you to enable and disable auto orientation
of the video stream, so that its orientation always matches of the video stream, so that its orientation always matches

View File

@@ -9,4 +9,3 @@ CONFIG += testcase
SOURCES += tst_qcamerabackend.cpp SOURCES += tst_qcamerabackend.cpp
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
mac: CONFIG += insignificant_test # QTBUG-36040