diff options
author | Yoann Lopes <yoann.lopes@theqtcompany.com> | 2016-09-01 12:29:35 +0200 |
---|---|---|
committer | Yoann Lopes <yoann.lopes@theqtcompany.com> | 2016-09-01 12:29:35 +0200 |
commit | 9fb4597d5c0d3fa3340ae74ed2eb6bb8e3ee2d17 (patch) | |
tree | cc82491fc856e3d184b3b00727a06139d73c550b /src/plugins | |
parent | 29232a2bc207fb7dc44532f64bbe35d9181340c6 (diff) | |
parent | da7d462e315fb101fc9112a294b5ca2e3bd35a75 (diff) | |
download | qtmultimedia-9fb4597d5c0d3fa3340ae74ed2eb6bb8e3ee2d17.tar.gz |
Merge remote-tracking branch 'origin/5.7' into 5.8
Conflicts:
src/multimedia/audio/qaudiosystemplugin.cpp
src/plugins/directshow/helpers/directshowobject.cpp
src/plugins/directshow/player/directshowiosource.cpp
src/plugins/directshow/player/directshowiosource.h
Change-Id: I0e4632c7705128f81429ddbcb0d4abbc04858a8b
Diffstat (limited to 'src/plugins')
5 files changed, 116 insertions, 16 deletions
diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm index 87bb08e5c..473a18884 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm @@ -41,6 +41,8 @@ #include "avfmediaplayerservice.h" #include "avfvideooutput.h" +#include <qpointer.h> + #import <AVFoundation/AVFoundation.h> QT_USE_NAMESPACE @@ -111,15 +113,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<AVFMediaPlayerSession> 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]; }); }]; } diff --git a/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm b/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm index 3b270f9b6..7eb5a71cf 100644 --- a/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm +++ b/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm @@ -45,6 +45,12 @@ #include <QtGui/QPaintEvent> #include <QtGui/QPainter> +#if defined(Q_OS_MACOS) +#import <AppKit/AppKit.h> +#else +#import <UIKit/UIKit.h> +#endif + QT_USE_NAMESPACE AVFVideoWidget::AVFVideoWidget(QWidget *parent) diff --git a/src/plugins/directshow/player/directshowiosource.cpp b/src/plugins/directshow/player/directshowiosource.cpp index 4dc8bec3d..3c44dd1ed 100644 --- a/src/plugins/directshow/player/directshowiosource.cpp +++ b/src/plugins/directshow/player/directshowiosource.cpp @@ -47,6 +47,22 @@ #include <QtCore/qcoreapplication.h> #include <QtCore/qurl.h> +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) @@ -65,13 +81,26 @@ DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop) // // The filter works in pull mode, the downstream filter is responsible for requesting // samples from this one. - - m_outputType.majortype = MEDIATYPE_Stream; - m_outputType.subtype = MEDIASUBTYPE_NULL; // Wildcard - m_outputType.bFixedSizeSamples = TRUE; - m_outputType.lSampleSize = 1; - - m_supportedMediaTypes.append(m_outputType); + // + 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]; + m_supportedMediaTypes.append(type); + } } DirectShowIOSource::~DirectShowIOSource() @@ -328,14 +357,40 @@ 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. + for (const DirectShowMediaType &t : qAsConst(m_supportedMediaTypes)) { + m_connectionMediaType.subtype = t.subtype; + hr = pReceivePin->ReceiveConnection(this, &m_connectionMediaType); + if (SUCCEEDED(hr)) + break; + } + } else { // - No media type specified. + // Check if the receiving pin accepts any of the streaming types. + for (const DirectShowMediaType &t : qAsConst(m_supportedMediaTypes)) { + hr = pReceivePin->ReceiveConnection(this, &t); + if (SUCCEEDED(hr)) { + m_connectionMediaType = t; + break; + } + } + } if (SUCCEEDED(hr) && m_queriedForAsyncReader) { m_peerPin = pReceivePin; @@ -348,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; @@ -420,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 efcde7a27..702bfed61 100644 --- a/src/plugins/directshow/player/directshowiosource.h +++ b/src/plugins/directshow/player/directshowiosource.h @@ -123,7 +123,7 @@ private: IReferenceClock *m_clock; IMemAllocator *m_allocator; IPin *m_peerPin; - DirectShowMediaType m_outputType; + DirectShowMediaType m_connectionMediaType; QList<DirectShowMediaType> m_supportedMediaTypes; QString m_filterName; const QString m_pinId; diff --git a/src/plugins/opensles/qopenslesaudiooutput.cpp b/src/plugins/opensles/qopenslesaudiooutput.cpp index 26f2380b2..70d77a380 100644 --- a/src/plugins/opensles/qopenslesaudiooutput.cpp +++ b/src/plugins/opensles/qopenslesaudiooutput.cpp @@ -114,11 +114,18 @@ QAudio::State QOpenSLESAudioOutput::state() const void QOpenSLESAudioOutput::start(QIODevice *device) { Q_ASSERT(device); + + if (m_state != QAudio::StoppedState) + stop(); + if (!preparePlayer()) return; m_pullMode = true; m_audioSource = device; + m_nextBuffer = 0; + m_processedBytes = 0; + m_availableBuffers = BUFFER_COUNT; setState(QAudio::ActiveState); setError(QAudio::NoError); @@ -136,6 +143,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(); @@ -143,10 +153,15 @@ void QOpenSLESAudioOutput::start(QIODevice *device) QIODevice *QOpenSLESAudioOutput::start() { + if (m_state != QAudio::StoppedState) + stop(); + if (!preparePlayer()) 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); @@ -372,7 +387,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; } @@ -380,8 +398,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, @@ -606,6 +627,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); |