From d44a327da4a956f62cc0d51095fa4c1d62e130d3 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Fri, 15 Jan 2016 16:04:09 +0100 Subject: DirectShow: fix playing resource files. Our custom filter that streams the data into the pipeline was incorrectly negotiating the sample type with the downstream filter. This also fixes playback when passing a QIODevice to QMediaPlayer. Task-number: QTBUG-46899 Change-Id: Iea8b8731d5404c416c8ed0d59cb61958b13b61b0 Reviewed-by: Christian Stromme --- .../directshow/player/directshowiosource.cpp | 169 +++++---------------- src/plugins/directshow/player/directshowiosource.h | 5 +- 2 files changed, 41 insertions(+), 133 deletions(-) (limited to 'src/plugins/directshow') diff --git a/src/plugins/directshow/player/directshowiosource.cpp b/src/plugins/directshow/player/directshowiosource.cpp index e1034a9c6..6fa3c7b9a 100644 --- a/src/plugins/directshow/player/directshowiosource.cpp +++ b/src/plugins/directshow/player/directshowiosource.cpp @@ -40,13 +40,6 @@ #include #include -static const GUID directshow_subtypes[] = -{ - MEDIASUBTYPE_Avi, - MEDIASUBTYPE_WAVE, - MEDIASUBTYPE_NULL -}; - DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop) : m_ref(1) , m_state(State_Stopped) @@ -57,30 +50,21 @@ DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop) , m_allocator(0) , m_peerPin(0) , m_pinId(QLatin1String("Data")) + , m_queriedForAsyncReader(false) { - 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); - } + // This filter has only one possible output type, that is, a stream of data + // with no particular subtype. The graph builder will try every demux/decode filters + // to find one able to decode the stream. + // + // 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; - setMediaTypes(mediaTypes); + setMediaTypes(QVector() << m_outputType); } DirectShowIOSource::~DirectShowIOSource() @@ -130,6 +114,7 @@ HRESULT DirectShowIOSource::QueryInterface(REFIID riid, void **ppvObject) } else if (riid == IID_IPin) { *ppvObject = static_cast(this); } else if (riid == IID_IAsyncReader) { + m_queriedForAsyncReader = true; *ppvObject = static_cast(m_reader); } else { *ppvObject = 0; @@ -324,116 +309,40 @@ ULONG DirectShowIOSource::GetMiscFlags() // IPin HRESULT DirectShowIOSource::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) { - QMutexLocker locker(&m_mutex); - if (!pReceivePin) { + if (!pReceivePin) return E_POINTER; - } else if (m_state != State_Stopped) { - return VFW_E_NOT_STOPPED; - } else if (m_peerPin) { - return VFW_E_ALREADY_CONNECTED; - } else { - HRESULT hr = VFW_E_TYPE_NOT_ACCEPTED; - - m_peerPin = pReceivePin; - m_peerPin->AddRef(); - if (!pmt) { - IEnumMediaTypes *mediaTypes = 0; - if (pReceivePin->EnumMediaTypes(&mediaTypes) == S_OK) { - for (AM_MEDIA_TYPE *type = 0; - mediaTypes->Next(1, &type, 0) == S_OK; - DirectShowMediaType::deleteType(type)) { - switch (tryConnect(pReceivePin, type)) { - case S_OK: - DirectShowMediaType::freeData(type); - mediaTypes->Release(); - return S_OK; - case VFW_E_NO_TRANSPORT: - hr = VFW_E_NO_TRANSPORT; - break; - default: - break; - } - } - mediaTypes->Release(); - } - 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]; - - switch (tryConnect(pReceivePin, &type)) { - case S_OK: - return S_OK; - case VFW_E_NO_TRANSPORT: - hr = VFW_E_NO_TRANSPORT; - break; - default: - break; - } - } - } else if (pmt->majortype == MEDIATYPE_Stream && (hr = tryConnect(pReceivePin, pmt))) { - return S_OK; - } - - m_peerPin->Release(); - m_peerPin = 0; + QMutexLocker locker(&m_mutex); - m_mediaType.clear(); + if (m_state != State_Stopped) + return VFW_E_NOT_STOPPED; - return hr; - } -} + if (m_peerPin) + return VFW_E_ALREADY_CONNECTED; -HRESULT DirectShowIOSource::tryConnect(IPin *pin, const AM_MEDIA_TYPE *type) -{ - m_mediaType = *type; + // If we get a type from the graph manager, check that we support that + if (pmt && (pmt->majortype != MEDIATYPE_Stream || pmt->subtype != MEDIASUBTYPE_NULL)) + return VFW_E_TYPE_NOT_ACCEPTED; - HRESULT hr = pin->ReceiveConnection(this, type); + // 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); - if (!SUCCEEDED(hr)) { + if (SUCCEEDED(hr) && m_queriedForAsyncReader) { + m_peerPin = pReceivePin; + m_peerPin->AddRef(); + } else { + pReceivePin->Disconnect(); if (m_allocator) { m_allocator->Release(); m_allocator = 0; } - } else if (!m_allocator) { - hr = VFW_E_NO_TRANSPORT; - - if (IMemInputPin *memPin = com_cast(pin, IID_IMemInputPin)) { - if ((m_allocator = com_new(CLSID_MemoryAllocator))) { - ALLOCATOR_PROPERTIES properties; - if (memPin->GetAllocatorRequirements(&properties) == S_OK - || m_allocator->GetProperties(&properties) == S_OK) { - if (properties.cbAlign == 0) - properties.cbAlign = 1; - - ALLOCATOR_PROPERTIES actualProperties; - if (SUCCEEDED(hr = m_allocator->SetProperties(&properties, &actualProperties))) - hr = memPin->NotifyAllocator(m_allocator, TRUE); - } - if (!SUCCEEDED(hr)) { - m_allocator->Release(); - m_allocator = 0; - } - } - memPin->Release(); - } - if (!SUCCEEDED(hr)) - pin->Disconnect(); + if (!m_queriedForAsyncReader) + hr = VFW_E_NO_TRANSPORT; } + return hr; } @@ -447,6 +356,8 @@ HRESULT DirectShowIOSource::ReceiveConnection(IPin *pConnector, const AM_MEDIA_T HRESULT DirectShowIOSource::Disconnect() { + QMutexLocker locker(&m_mutex); + if (!m_peerPin) { return S_FALSE; } else if (m_state != State_Stopped) { @@ -465,8 +376,6 @@ HRESULT DirectShowIOSource::Disconnect() m_peerPin->Release(); m_peerPin = 0; - m_mediaType.clear(); - return S_OK; } } @@ -504,7 +413,7 @@ HRESULT DirectShowIOSource::ConnectionMediaType(AM_MEDIA_TYPE *pmt) return VFW_E_NOT_CONNECTED; } else { - DirectShowMediaType::copy(pmt, m_mediaType); + DirectShowMediaType::copy(pmt, m_outputType); return S_OK; } diff --git a/src/plugins/directshow/player/directshowiosource.h b/src/plugins/directshow/player/directshowiosource.h index e45c8520d..f5e8ec6d1 100644 --- a/src/plugins/directshow/player/directshowiosource.h +++ b/src/plugins/directshow/player/directshowiosource.h @@ -111,8 +111,6 @@ public: HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir); private: - HRESULT tryConnect(IPin *pin, const AM_MEDIA_TYPE *type); - volatile LONG m_ref; FILTER_STATE m_state; DirectShowIOReader *m_reader; @@ -121,9 +119,10 @@ private: IReferenceClock *m_clock; IMemAllocator *m_allocator; IPin *m_peerPin; - DirectShowMediaType m_mediaType; + DirectShowMediaType m_outputType; QString m_filterName; const QString m_pinId; + bool m_queriedForAsyncReader; QMutex m_mutex; }; -- cgit v1.2.3