From 57b1dc867cc29e0a7fb28ee6701cfa3e1b2257d2 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Fri, 12 Aug 2016 11:09:56 +0200 Subject: Doc: Change instances of 'OS X' to 'macOS' As of version 10.12 (Sierra), the name of Apple's desktop operating system will be macOS. Change all occurrences where the platform is discussed to use the macro \macos (defined in the documentation configuration in qtbase). Change-Id: I1ba3b1e3c11870523516d3a13790d40dd0803aad Reviewed-by: Leena Miettinen --- src/multimedia/audio/qaudiosystemplugin.cpp | 2 +- src/multimedia/doc/src/qtmultimedia-examples.qdoc | 2 +- src/multimedia/video/qabstractvideobuffer.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/multimedia/audio/qaudiosystemplugin.cpp b/src/multimedia/audio/qaudiosystemplugin.cpp index de719fceb..02e1eead2 100644 --- a/src/multimedia/audio/qaudiosystemplugin.cpp +++ b/src/multimedia/audio/qaudiosystemplugin.cpp @@ -66,7 +66,7 @@ QAudioSystemFactoryInterface::~QAudioSystemFactoryInterface() \sa QAbstractAudioDeviceInfo, QAbstractAudioOutput, QAbstractAudioInput - Qt supports win32, linux(alsa) and OS X standard (builtin to the + Qt supports win32, linux(alsa) and \macos standard (builtin to the QtMultimedia library at compile time). You can support other backends other than these predefined ones by diff --git a/src/multimedia/doc/src/qtmultimedia-examples.qdoc b/src/multimedia/doc/src/qtmultimedia-examples.qdoc index 582efc5e1..dd35aeb1a 100644 --- a/src/multimedia/doc/src/qtmultimedia-examples.qdoc +++ b/src/multimedia/doc/src/qtmultimedia-examples.qdoc @@ -32,6 +32,6 @@ \brief Demonstrates the multimedia functionality provided by Qt. The \l{Qt Multimedia} module provides low-level audio support on Linux, - Windows and OS X. It also provides audio plugin API to allow developers + Windows and \macos. It also provides audio plugin API to allow developers implement their own audio support for custom devices and platforms. */ diff --git a/src/multimedia/video/qabstractvideobuffer.cpp b/src/multimedia/video/qabstractvideobuffer.cpp index 6dca8dad8..b7f7db805 100644 --- a/src/multimedia/video/qabstractvideobuffer.cpp +++ b/src/multimedia/video/qabstractvideobuffer.cpp @@ -92,7 +92,7 @@ int QAbstractVideoBufferPrivate::map( \value NoHandle The buffer has no handle, its data can only be accessed by mapping the buffer. \value GLTextureHandle The handle of the buffer is an OpenGL texture ID. \value XvShmImageHandle The handle contains pointer to shared memory XVideo image. - \value CoreImageHandle The handle contains pointer to OS X CIImage. + \value CoreImageHandle The handle contains pointer to \macos CIImage. \value QPixmapHandle The handle of the buffer is a QPixmap. \value EGLImageHandle The handle of the buffer is an EGLImageKHR. \value UserHandle Start value for user defined handle types. -- cgit v1.2.1 From c7ae48c5fb5005efae05f2cabdeee7117f6f72fa Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Wed, 20 Jul 2016 13:09:39 +0200 Subject: PulseAudio: flush stream before loading a new source in a sound effect When loading a new QSoundEffect source, the data in the stream must be flushed to avoid that the old source plays right before the new one. Task-number: QTBUG-48982 Change-Id: Iff14884edb2fb4851f93e67ff8191b77ebb16359 Reviewed-by: Christian Stromme --- src/multimedia/audio/qsoundeffect_pulse_p.cpp | 45 ++++++++++++++++++++++----- src/multimedia/audio/qsoundeffect_pulse_p.h | 10 ++++-- 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/src/multimedia/audio/qsoundeffect_pulse_p.cpp b/src/multimedia/audio/qsoundeffect_pulse_p.cpp index 43d4a6cb0..48f3333c2 100644 --- a/src/multimedia/audio/qsoundeffect_pulse_p.cpp +++ b/src/multimedia/audio/qsoundeffect_pulse_p.cpp @@ -413,7 +413,13 @@ void QSoundEffectPrivate::setSource(const QUrl &url) #ifdef QT_PA_DEBUG qDebug() << this << "setSource =" << url; #endif + + // Make sure the stream is empty before loading a new source (otherwise whatever is there will + // be played before the new source) + emptyStream(); + stop(); + if (m_sample) { if (!m_sampleReady) { disconnect(m_sample, SIGNAL(error()), this, SLOT(decoderError())); @@ -588,7 +594,7 @@ void QSoundEffectPrivate::playAvailable() setLoopsRemaining(0); m_playQueued = true; Q_ASSERT(m_pulseStream); - emptyStream(); + emptyStream(ReloadSampleWhenDone); return; } setLoopsRemaining(m_loopCount); @@ -598,18 +604,25 @@ void QSoundEffectPrivate::playAvailable() setPlaying(true); } -void QSoundEffectPrivate::emptyStream() +void QSoundEffectPrivate::emptyStream(EmptyStreamOptions options) { #ifdef QT_PA_DEBUG qDebug() << this << "emptyStream"; #endif + if (!m_pulseStream || m_emptying) + return; + + const bool reloadSample = options.testFlag(ReloadSampleWhenDone); + pa_stream_success_cb_t flushCompleteCb = reloadSample ? stream_flush_reload_callback + : stream_flush_callback; + m_emptying = true; pa_stream_set_write_callback(m_pulseStream, 0, 0); pa_stream_set_underflow_callback(m_pulseStream, 0, 0); - pa_operation_unref(pa_stream_flush(m_pulseStream, stream_flush_callback, m_ref->getRef())); + pa_operation_unref(pa_stream_flush(m_pulseStream, flushCompleteCb, m_ref->getRef())); } -void QSoundEffectPrivate::emptyComplete(void *stream) +void QSoundEffectPrivate::emptyComplete(void *stream, bool reload) { PulseDaemonLocker locker; #ifdef QT_PA_DEBUG @@ -619,7 +632,7 @@ void QSoundEffectPrivate::emptyComplete(void *stream) m_emptying = false; if ((pa_stream *)stream == m_pulseStream) - pa_operation_unref(pa_stream_cork(m_pulseStream, 1, stream_cork_callback, m_ref->getRef())); + pa_operation_unref(pa_stream_cork(m_pulseStream, 1, reload ? stream_cork_callback : 0, m_ref->getRef())); } void QSoundEffectPrivate::sampleReady() @@ -851,7 +864,7 @@ void QSoundEffectPrivate::stop() PulseDaemonLocker locker; m_stopping = true; if (m_pulseStream) { - emptyStream(); + emptyStream(ReloadSampleWhenDone); if (m_reloadCategory) { unloadPulseStream(); // upon play we reconnect anyway } @@ -1094,10 +1107,26 @@ void QSoundEffectPrivate::stream_flush_callback(pa_stream *s, int success, void if (!success) qWarning("QSoundEffect(pulseaudio): faild to drain"); + + QMetaObject::invokeMethod(self, "emptyComplete", Qt::QueuedConnection, Q_ARG(void*, s), Q_ARG(bool, false)); +} + +void QSoundEffectPrivate::stream_flush_reload_callback(pa_stream *s, int success, void *userdata) +{ #ifdef QT_PA_DEBUG - qDebug() << self << "stream_flush_callback"; + qDebug() << "stream_flush_reload_callback"; #endif - QMetaObject::invokeMethod(self, "emptyComplete", Qt::QueuedConnection, Q_ARG(void*, s)); + Q_UNUSED(s); + QSoundEffectRef *ref = reinterpret_cast(userdata); + QSoundEffectPrivate *self = ref->soundEffect(); + ref->release(); + if (!self) + return; + + if (!success) + qWarning("QSoundEffect(pulseaudio): faild to drain"); + + QMetaObject::invokeMethod(self, "emptyComplete", Qt::QueuedConnection, Q_ARG(void*, s), Q_ARG(bool, true)); } void QSoundEffectPrivate::stream_write_done_callback(void *p) diff --git a/src/multimedia/audio/qsoundeffect_pulse_p.h b/src/multimedia/audio/qsoundeffect_pulse_p.h index 0f16b98a2..2eb20695a 100644 --- a/src/multimedia/audio/qsoundeffect_pulse_p.h +++ b/src/multimedia/audio/qsoundeffect_pulse_p.h @@ -111,7 +111,7 @@ private Q_SLOTS: void underRun(); void prepare(); void streamReady(); - void emptyComplete(void *stream); + void emptyComplete(void *stream, bool reload); void handleAvailabilityChanged(bool available); @@ -119,7 +119,12 @@ private: void playAvailable(); void playSample(); - void emptyStream(); + enum EmptyStreamOption { + ReloadSampleWhenDone = 0x1 + }; + Q_DECLARE_FLAGS(EmptyStreamOptions, EmptyStreamOption) + void emptyStream(EmptyStreamOptions options = EmptyStreamOptions()); + void createPulseStream(); void unloadPulseStream(); @@ -134,6 +139,7 @@ private: static void stream_underrun_callback(pa_stream *s, void *userdata); static void stream_cork_callback(pa_stream *s, int success, void *userdata); static void stream_flush_callback(pa_stream *s, int success, void *userdata); + static void stream_flush_reload_callback(pa_stream *s, int success, void *userdata); static void stream_write_done_callback(void *p); static void stream_adjust_prebuffer_callback(pa_stream *s, int success, void *userdata); static void stream_reset_buffer_callback(pa_stream *s, int success, void *userdata); -- cgit v1.2.1 From c9de25fa342ff8066d49541179c30d0ce45950b4 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Wed, 20 Jul 2016 13:15:20 +0200 Subject: PulseAudio (QSoundEffect): don't write data to an unready stream The PulseAudio stream must be ready to write data to it, otherwise an assert is raised. Change-Id: Iaa108124a135b018aa84845a37665895a005f380 Reviewed-by: Christian Stromme --- src/multimedia/audio/qsoundeffect_pulse_p.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/multimedia/audio/qsoundeffect_pulse_p.cpp b/src/multimedia/audio/qsoundeffect_pulse_p.cpp index 48f3333c2..1fb10d121 100644 --- a/src/multimedia/audio/qsoundeffect_pulse_p.cpp +++ b/src/multimedia/audio/qsoundeffect_pulse_p.cpp @@ -736,6 +736,10 @@ void QSoundEffectPrivate::prepare() if (!m_pulseStream || !m_sampleReady) return; PulseDaemonLocker locker; + + if (pa_stream_get_state(m_pulseStream) != PA_STREAM_READY) + return; + pa_stream_set_write_callback(m_pulseStream, stream_write_callback, this); pa_stream_set_underflow_callback(m_pulseStream, stream_underrun_callback, this); m_stopping = false; -- cgit v1.2.1 From a52aa624e69fa618aa0d29c2a147a7d472751de1 Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Wed, 17 Aug 2016 12:59:37 -0700 Subject: Fix instance method not found warning NSView/UIView were only forward declared here which led to warnings when calling methods on instances of them. Change-Id: Ic2b391bb0ed8d45306dc16e2a807ce7fcae5015e Reviewed-by: Gabriel de Dietrich --- src/plugins/avfoundation/mediaplayer/avfvideowidget.mm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm b/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm index f00146d1b..22cd41e69 100644 --- a/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm +++ b/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm @@ -39,6 +39,12 @@ #include #include +#if defined(Q_OS_MACOS) +#import +#else +#import +#endif + QT_USE_NAMESPACE AVFVideoWidget::AVFVideoWidget(QWidget *parent) -- cgit v1.2.1 From 69296d229eb2f5b5842f7855ef4110e0e4817da2 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Wed, 17 Aug 2016 14:03:49 +0200 Subject: AVFoundation: fix memory leak Using 'self' in a block maintains a strong reference to it, the previous code would never release that reference and therefore leak the AVFMediaPlayerSessionObserver object when the session was deleted. Captured variables used in the relevant block are now marked with '__block' to make sure no strong references are maintained. We now also make sure the session still exist when that callback block is called. Change-Id: I847b524d8692559fe5884517abb5b9cc7696b4fd Reviewed-by: Timur Pocheptsov --- .../avfoundation/mediaplayer/avfmediaplayersession.mm | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm index d3ec2ff9c..24b6fe464 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm @@ -35,6 +35,8 @@ #include "avfmediaplayerservice.h" #include "avfvideooutput.h" +#include + #import QT_USE_NAMESPACE @@ -105,15 +107,23 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe //Create an asset for inspection of a resource referenced by a given URL. //Load the values for the asset keys "tracks", "playable". - AVURLAsset *asset = [AVURLAsset URLAssetWithURL:m_URL options:nil]; - NSArray *requestedKeys = [NSArray arrayWithObjects:AVF_TRACKS_KEY, AVF_PLAYABLE_KEY, nil]; + // use __block to avoid maintaining strong references on variables captured by the + // following block callback + __block AVURLAsset *asset = [[AVURLAsset URLAssetWithURL:m_URL options:nil] retain]; + __block NSArray *requestedKeys = [[NSArray arrayWithObjects:AVF_TRACKS_KEY, AVF_PLAYABLE_KEY, nil] retain]; + + __block AVFMediaPlayerSessionObserver *blockSelf = self; + QPointer session(m_session); // Tells the asset to load the values of any of the specified keys that are not already loaded. [asset loadValuesAsynchronouslyForKeys:requestedKeys completionHandler: ^{ dispatch_async( dispatch_get_main_queue(), ^{ - [self prepareToPlayAsset:asset withKeys:requestedKeys]; + if (session) + [blockSelf prepareToPlayAsset:asset withKeys:requestedKeys]; + [asset release]; + [requestedKeys release]; }); }]; } -- cgit v1.2.1 From 0ce67605de8e71f0607b36e2ef28801c3fc5c655 Mon Sep 17 00:00:00 2001 From: Michael Dippold Date: Thu, 18 Aug 2016 09:10:21 -0700 Subject: OpenSL ES: Fix buffer corruption When start is called, the buffer is always filled starting from index 0 without regard to m_nexBuffer. m_nextBuffer could be set to 1 from the previous playback which causes the second buffer to be filled first, which is now the currently playing buffer. This is causing an audible hiccup right after starting in cases where m_nextBuffer starts at 1. Change-Id: Ia0d73638350d5258a51943d7a1c7cd6f22d068ee Reviewed-by: Christian Stromme --- src/plugins/opensles/qopenslesaudiooutput.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/opensles/qopenslesaudiooutput.cpp b/src/plugins/opensles/qopenslesaudiooutput.cpp index 3e0ab68c7..94476f58a 100644 --- a/src/plugins/opensles/qopenslesaudiooutput.cpp +++ b/src/plugins/opensles/qopenslesaudiooutput.cpp @@ -115,6 +115,7 @@ void QOpenSLESAudioOutput::start(QIODevice *device) m_pullMode = true; m_audioSource = device; + m_nextBuffer = 0; setState(QAudio::ActiveState); setError(QAudio::NoError); -- cgit v1.2.1 From 4025a05c64100b13615f856ac0b403b3623a5cf4 Mon Sep 17 00:00:00 2001 From: Christian Stromme Date: Fri, 12 Aug 2016 14:24:49 +0200 Subject: DirectShow: Restore negotiation of sample type in the io filter This functionality was removed in d44a327da4a956f62cc0d51, but is still needed, as we need to negotiate the media type with the input pin; even if we limit the scope to streaming types. Task-number: QTBUG-55264 Change-Id: I7cc02c5ea17cca9912c29c40813314b04b91bd18 Reviewed-by: Yoann Lopes --- .../directshow/player/directshowiosource.cpp | 82 +++++++++++++++++++--- src/plugins/directshow/player/directshowiosource.h | 2 +- .../directshow/player/directshowmediatypelist.h | 4 +- 3 files changed, 77 insertions(+), 11 deletions(-) diff --git a/src/plugins/directshow/player/directshowiosource.cpp b/src/plugins/directshow/player/directshowiosource.cpp index 6fa3c7b9a..1b74415e4 100644 --- a/src/plugins/directshow/player/directshowiosource.cpp +++ b/src/plugins/directshow/player/directshowiosource.cpp @@ -40,6 +40,22 @@ #include #include +static const GUID directshow_subtypes[] = +{ + MEDIASUBTYPE_NULL, + MEDIASUBTYPE_Avi, + MEDIASUBTYPE_Asf, + MEDIASUBTYPE_MPEG1Video, + MEDIASUBTYPE_QTMovie, + MEDIASUBTYPE_WAVE, + MEDIASUBTYPE_AIFF, + MEDIASUBTYPE_AU, + MEDIASUBTYPE_DssVideo, + MEDIASUBTYPE_MPEG1Audio, + MEDIASUBTYPE_MPEG1System, + MEDIASUBTYPE_MPEG1VideoCD +}; + DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop) : m_ref(1) , m_state(State_Stopped) @@ -58,13 +74,29 @@ DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop) // // The filter works in pull mode, the downstream filter is responsible for requesting // samples from this one. + // + QVector mediaTypes; + AM_MEDIA_TYPE type = + { + MEDIATYPE_Stream, // majortype + MEDIASUBTYPE_NULL, // subtype + TRUE, // bFixedSizeSamples + FALSE, // bTemporalCompression + 1, // lSampleSize + GUID_NULL, // formattype + 0, // pUnk + 0, // cbFormat + 0, // pbFormat + }; + + static const int count = sizeof(directshow_subtypes) / sizeof(GUID); + + for (int i = 0; i < count; ++i) { + type.subtype = directshow_subtypes[i]; + mediaTypes.append(type); + } - m_outputType.majortype = MEDIATYPE_Stream; - m_outputType.subtype = MEDIASUBTYPE_NULL; // Wildcard - m_outputType.bFixedSizeSamples = TRUE; - m_outputType.lSampleSize = 1; - - setMediaTypes(QVector() << m_outputType); + setMediaTypes(mediaTypes); } DirectShowIOSource::~DirectShowIOSource() @@ -321,14 +353,44 @@ HRESULT DirectShowIOSource::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) return VFW_E_ALREADY_CONNECTED; // If we get a type from the graph manager, check that we support that - if (pmt && (pmt->majortype != MEDIATYPE_Stream || pmt->subtype != MEDIASUBTYPE_NULL)) + if (pmt && pmt->majortype != MEDIATYPE_Stream) return VFW_E_TYPE_NOT_ACCEPTED; // This filter only works in pull mode, the downstream filter must query for the // AsyncReader interface during ReceiveConnection(). // If it doesn't, we can't connect to it. m_queriedForAsyncReader = false; - HRESULT hr = pReceivePin->ReceiveConnection(this, pmt ? pmt : &m_outputType); + HRESULT hr = 0; + // Negotiation of media type + // - Complete'ish type (Stream with subtype specified). + if (pmt && pmt->subtype != MEDIASUBTYPE_NULL /* aka. GUID_NULL */) { + hr = pReceivePin->ReceiveConnection(this, pmt); + // Update the media type for the current connection. + if (SUCCEEDED(hr)) + m_connectionMediaType = *pmt; + } else if (pmt && pmt->subtype == MEDIATYPE_NULL) { // - Partial type (Stream, but no subtype specified). + m_connectionMediaType = *pmt; + // Check if the receiving pin accepts any of the streaming subtypes. + QVector::const_iterator cit = m_mediaTypes.constBegin(); + while (cit != m_mediaTypes.constEnd()) { + m_connectionMediaType.subtype = cit->subtype; + hr = pReceivePin->ReceiveConnection(this, &m_connectionMediaType); + if (SUCCEEDED(hr)) + break; + ++cit; + } + } else { // - No media type specified. + // Check if the receiving pin accepts any of the streaming types. + QVector::const_iterator cit = m_mediaTypes.constBegin(); + while (cit != m_mediaTypes.constEnd()) { + hr = pReceivePin->ReceiveConnection(this, cit); + if (SUCCEEDED(hr)) { + m_connectionMediaType = *cit; + break; + } + ++cit; + } + } if (SUCCEEDED(hr) && m_queriedForAsyncReader) { m_peerPin = pReceivePin; @@ -341,6 +403,8 @@ HRESULT DirectShowIOSource::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) } if (!m_queriedForAsyncReader) hr = VFW_E_NO_TRANSPORT; + + m_connectionMediaType.clear(); } return hr; @@ -413,7 +477,7 @@ HRESULT DirectShowIOSource::ConnectionMediaType(AM_MEDIA_TYPE *pmt) return VFW_E_NOT_CONNECTED; } else { - DirectShowMediaType::copy(pmt, m_outputType); + DirectShowMediaType::copy(pmt, m_connectionMediaType); return S_OK; } diff --git a/src/plugins/directshow/player/directshowiosource.h b/src/plugins/directshow/player/directshowiosource.h index f5e8ec6d1..60300ba18 100644 --- a/src/plugins/directshow/player/directshowiosource.h +++ b/src/plugins/directshow/player/directshowiosource.h @@ -119,7 +119,7 @@ private: IReferenceClock *m_clock; IMemAllocator *m_allocator; IPin *m_peerPin; - DirectShowMediaType m_outputType; + DirectShowMediaType m_connectionMediaType; QString m_filterName; const QString m_pinId; bool m_queriedForAsyncReader; diff --git a/src/plugins/directshow/player/directshowmediatypelist.h b/src/plugins/directshow/player/directshowmediatypelist.h index 860334532..8dc6e17e4 100644 --- a/src/plugins/directshow/player/directshowmediatypelist.h +++ b/src/plugins/directshow/player/directshowmediatypelist.h @@ -54,9 +54,11 @@ public: virtual HRESULT skipMediaType(int token, int *index, ULONG count); virtual HRESULT cloneMediaType(int token, int index, IEnumMediaTypes **enumeration); +protected: + QVector m_mediaTypes; + private: int m_mediaTypeToken; - QVector m_mediaTypes; }; #endif -- cgit v1.2.1 From 7c7a97809b686869d19603bf828a468f3d6e274e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Mon, 22 Aug 2016 20:05:23 +0200 Subject: OpenSL ES: Reset states before starting Some of the state variables were not reset correctly. Change-Id: I22113072320dd1812529c598cda1a5f6cc8c780b Reviewed-by: Michael Dippold Reviewed-by: Yoann Lopes --- src/plugins/opensles/qopenslesaudiooutput.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugins/opensles/qopenslesaudiooutput.cpp b/src/plugins/opensles/qopenslesaudiooutput.cpp index 94476f58a..cbc6fca5c 100644 --- a/src/plugins/opensles/qopenslesaudiooutput.cpp +++ b/src/plugins/opensles/qopenslesaudiooutput.cpp @@ -116,6 +116,8 @@ void QOpenSLESAudioOutput::start(QIODevice *device) m_pullMode = true; m_audioSource = device; m_nextBuffer = 0; + m_processedBytes = 0; + m_availableBuffers = BUFFER_COUNT; setState(QAudio::ActiveState); setError(QAudio::NoError); @@ -144,6 +146,8 @@ QIODevice *QOpenSLESAudioOutput::start() return Q_NULLPTR; m_pullMode = false; + m_processedBytes = 0; + m_availableBuffers = BUFFER_COUNT; m_audioSource = new SLIODevicePrivate(this); m_audioSource->open(QIODevice::WriteOnly | QIODevice::Unbuffered); -- cgit v1.2.1 From 91d28b48cd7c3ffda21b6d961df29b6aab1caed1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Mon, 22 Aug 2016 20:12:23 +0200 Subject: OpenSL ES: Stop the device if it's not stopped already Change-Id: I4a9906d2d5aa1eaf8e67773f79ca217150a53ce5 Reviewed-by: Michael Dippold Reviewed-by: Yoann Lopes --- src/plugins/opensles/qopenslesaudiooutput.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/plugins/opensles/qopenslesaudiooutput.cpp b/src/plugins/opensles/qopenslesaudiooutput.cpp index cbc6fca5c..83691f127 100644 --- a/src/plugins/opensles/qopenslesaudiooutput.cpp +++ b/src/plugins/opensles/qopenslesaudiooutput.cpp @@ -110,6 +110,10 @@ QAudio::State QOpenSLESAudioOutput::state() const void QOpenSLESAudioOutput::start(QIODevice *device) { Q_ASSERT(device); + + if (m_state != QAudio::StoppedState) + stop(); + if (!preparePlayer()) return; @@ -142,6 +146,9 @@ void QOpenSLESAudioOutput::start(QIODevice *device) QIODevice *QOpenSLESAudioOutput::start() { + if (m_state != QAudio::StoppedState) + stop(); + if (!preparePlayer()) return Q_NULLPTR; -- cgit v1.2.1 From aa16b8187206c5763429105ec8e5014fb837b925 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Mon, 22 Aug 2016 20:10:22 +0200 Subject: OpenSL ES: Release audio device source in push mode The IO device was leaking in push mode, as a new one was created each time start was called. Change-Id: I78bb45e9e4e801772e88104b11d7baedc9e91ba8 Reviewed-by: Michael Dippold Reviewed-by: Yoann Lopes --- src/plugins/opensles/qopenslesaudiooutput.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/plugins/opensles/qopenslesaudiooutput.cpp b/src/plugins/opensles/qopenslesaudiooutput.cpp index 83691f127..06a990ec3 100644 --- a/src/plugins/opensles/qopenslesaudiooutput.cpp +++ b/src/plugins/opensles/qopenslesaudiooutput.cpp @@ -614,6 +614,12 @@ void QOpenSLESAudioOutput::stopPlayer() { setState(QAudio::StoppedState); + if (m_audioSource && !m_pullMode) { + m_audioSource->close(); + delete m_audioSource; + m_audioSource = Q_NULLPTR; + } + // We need to change the state manually... if (m_playItf) (*m_playItf)->SetPlayState(m_playItf, SL_PLAYSTATE_STOPPED); -- cgit v1.2.1 From 6d95682d7ff282180655f2f384d8aba69c4f67af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Tue, 23 Aug 2016 15:55:28 +0200 Subject: OpenSL ES: Fix EOS handling This fixes the remaining auto tests that were failing. Change-Id: I3b31263e7912422407cb98b4bf2db7080bcfc1a8 Reviewed-by: Yoann Lopes --- src/plugins/opensles/qopenslesaudiooutput.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/plugins/opensles/qopenslesaudiooutput.cpp b/src/plugins/opensles/qopenslesaudiooutput.cpp index 06a990ec3..a76f15b71 100644 --- a/src/plugins/opensles/qopenslesaudiooutput.cpp +++ b/src/plugins/opensles/qopenslesaudiooutput.cpp @@ -139,6 +139,9 @@ void QOpenSLESAudioOutput::start(QIODevice *device) m_processedBytes += readSize; } + if (m_processedBytes < 1) + onEOSEvent(); + // Change the state to playing. // We need to do this after filling the buffers or processedBytes might get corrupted. startPlayer(); @@ -380,7 +383,10 @@ void QOpenSLESAudioOutput::bufferAvailable(quint32 count, quint32 playIndex) if (!m_pullMode) { // We're in push mode. // Signal that there is a new open slot in the buffer and return - m_availableBuffers.fetchAndAddRelease(1); + const int val = m_availableBuffers.fetchAndAddRelease(1) + 1; + if (val == BUFFER_COUNT) + QMetaObject::invokeMethod(this, "onEOSEvent", Qt::QueuedConnection); + return; } @@ -388,8 +394,11 @@ void QOpenSLESAudioOutput::bufferAvailable(quint32 count, quint32 playIndex) const int index = m_nextBuffer * m_bufferSize; const qint64 readSize = m_audioSource->read(m_buffers + index, m_bufferSize); - if (1 > readSize) + if (readSize < 1) { + QMetaObject::invokeMethod(this, "onEOSEvent", Qt::QueuedConnection); return; + } + if (SL_RESULT_SUCCESS != (*m_bufferQueueItf)->Enqueue(m_bufferQueueItf, m_buffers + index, -- cgit v1.2.1