diff options
Diffstat (limited to 'src/plugins/directshow/player/directshowiosource.cpp')
-rw-r--r-- | src/plugins/directshow/player/directshowiosource.cpp | 169 |
1 files changed, 39 insertions, 130 deletions
diff --git a/src/plugins/directshow/player/directshowiosource.cpp b/src/plugins/directshow/player/directshowiosource.cpp index 6dee14fb0..bb4d0f00d 100644 --- a/src/plugins/directshow/player/directshowiosource.cpp +++ b/src/plugins/directshow/player/directshowiosource.cpp @@ -46,13 +46,6 @@ #include <QtCore/qcoreapplication.h> #include <QtCore/qurl.h> -static const GUID directshow_subtypes[] = -{ - MEDIASUBTYPE_Avi, - MEDIASUBTYPE_WAVE, - MEDIASUBTYPE_NULL -}; - DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop) : m_ref(1) , m_state(State_Stopped) @@ -63,30 +56,21 @@ DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop) , m_allocator(0) , m_peerPin(0) , m_pinId(QLatin1String("Data")) + , m_queriedForAsyncReader(false) { - 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); - } + // 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<AM_MEDIA_TYPE>() << m_outputType); } DirectShowIOSource::~DirectShowIOSource() @@ -136,6 +120,7 @@ HRESULT DirectShowIOSource::QueryInterface(REFIID riid, void **ppvObject) } else if (riid == IID_IPin) { *ppvObject = static_cast<IPin *>(this); } else if (riid == IID_IAsyncReader) { + m_queriedForAsyncReader = true; *ppvObject = static_cast<IAsyncReader *>(m_reader); } else { *ppvObject = 0; @@ -330,116 +315,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<IMemInputPin>(pin, IID_IMemInputPin)) { - if ((m_allocator = com_new<IMemAllocator>(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; } @@ -453,6 +362,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) { @@ -471,8 +382,6 @@ HRESULT DirectShowIOSource::Disconnect() m_peerPin->Release(); m_peerPin = 0; - m_mediaType.clear(); - return S_OK; } } @@ -510,7 +419,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; } |