summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2016-08-27 20:23:52 +0200
committerLiang Qi <liang.qi@qt.io>2016-08-27 20:23:52 +0200
commitda7d462e315fb101fc9112a294b5ca2e3bd35a75 (patch)
tree843917c14a566949318d1e8e03aa84a6ccc041d4 /src/plugins
parent820205e604a5f281238c23464638fdff72b969d1 (diff)
parent6d95682d7ff282180655f2f384d8aba69c4f67af (diff)
Merge remote-tracking branch 'origin/5.6' into 5.7
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm16
-rw-r--r--src/plugins/avfoundation/mediaplayer/avfvideowidget.mm6
-rw-r--r--src/plugins/directshow/player/directshowiosource.cpp82
-rw-r--r--src/plugins/directshow/player/directshowiosource.h2
-rw-r--r--src/plugins/directshow/player/directshowmediatypelist.h4
-rw-r--r--src/plugins/opensles/qopenslesaudiooutput.cpp31
6 files changed, 125 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 bb4d0f00d..fa17e51af 100644
--- a/src/plugins/directshow/player/directshowiosource.cpp
+++ b/src/plugins/directshow/player/directshowiosource.cpp
@@ -46,6 +46,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)
@@ -64,13 +80,29 @@ DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop)
//
// The filter works in pull mode, the downstream filter is responsible for requesting
// samples from this one.
+ //
+ QVector<AM_MEDIA_TYPE> 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<AM_MEDIA_TYPE>() << m_outputType);
+ setMediaTypes(mediaTypes);
}
DirectShowIOSource::~DirectShowIOSource()
@@ -327,14 +359,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<AM_MEDIA_TYPE>::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<AM_MEDIA_TYPE>::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;
@@ -347,6 +409,8 @@ HRESULT DirectShowIOSource::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
}
if (!m_queriedForAsyncReader)
hr = VFW_E_NO_TRANSPORT;
+
+ m_connectionMediaType.clear();
}
return hr;
@@ -419,7 +483,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 225cfc1ab..3d5cd4dd7 100644
--- a/src/plugins/directshow/player/directshowiosource.h
+++ b/src/plugins/directshow/player/directshowiosource.h
@@ -125,7 +125,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 c6dac0e9b..2bd8dca59 100644
--- a/src/plugins/directshow/player/directshowmediatypelist.h
+++ b/src/plugins/directshow/player/directshowmediatypelist.h
@@ -60,9 +60,11 @@ public:
virtual HRESULT skipMediaType(int token, int *index, ULONG count);
virtual HRESULT cloneMediaType(int token, int index, IEnumMediaTypes **enumeration);
+protected:
+ QVector<AM_MEDIA_TYPE> m_mediaTypes;
+
private:
int m_mediaTypeToken;
- QVector<AM_MEDIA_TYPE> m_mediaTypes;
};
#endif
diff --git a/src/plugins/opensles/qopenslesaudiooutput.cpp b/src/plugins/opensles/qopenslesaudiooutput.cpp
index 8bf0b5602..47006ed34 100644
--- a/src/plugins/opensles/qopenslesaudiooutput.cpp
+++ b/src/plugins/opensles/qopenslesaudiooutput.cpp
@@ -116,11 +116,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);
@@ -138,6 +145,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();
@@ -145,10 +155,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);
@@ -374,7 +389,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;
}
@@ -382,8 +400,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,
@@ -608,6 +629,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);