HRESULT CStreamSwitcherOutputPin::GetMediaType(int iPosition, CMediaType* pmt) { CStreamSwitcherInputPin* pIn = (static_cast<CStreamSwitcherFilter*>(m_pFilter))->GetInputPin(); if (!pIn || !pIn->IsConnected()) { return E_UNEXPECTED; } CComPtr<IEnumMediaTypes> pEM; if (FAILED(pIn->GetConnected()->EnumMediaTypes(&pEM))) { return VFW_S_NO_MORE_ITEMS; } if (iPosition > 0 && FAILED(pEM->Skip(iPosition))) { return VFW_S_NO_MORE_ITEMS; } AM_MEDIA_TYPE* tmp = nullptr; if (S_OK != pEM->Next(1, &tmp, nullptr) || !tmp) { return VFW_S_NO_MORE_ITEMS; } CopyMediaType(pmt, tmp); DeleteMediaType(tmp); /* if (iPosition < 0) return E_INVALIDARG; if (iPosition > 0) return VFW_S_NO_MORE_ITEMS; CopyMediaType(pmt, &pIn->CurrentMediaType()); */ return S_OK; }
STDMETHODIMP CStreamSwitcherFilter::Count(DWORD* pcStreams) { if (!pcStreams) { return E_POINTER; } CAutoLock cAutoLock(&m_csPins); *pcStreams = 0; POSITION pos = m_pInputs.GetHeadPosition(); while (pos) { CStreamSwitcherInputPin* pInputPin = m_pInputs.GetNext(pos); if (pInputPin->IsConnected()) { if (CComPtr<IAMStreamSelect> pSSF = pInputPin->GetStreamSelectionFilter()) { DWORD cStreams = 0; HRESULT hr = pSSF->Count(&cStreams); if (SUCCEEDED(hr)) { for (int i = 0; i < (int)cStreams; i++) { AM_MEDIA_TYPE* pmt = nullptr; hr = pSSF->Info(i, &pmt, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); if (SUCCEEDED(hr) && pmt && pmt->majortype == MEDIATYPE_Audio) { (*pcStreams)++; } DeleteMediaType(pmt); } } } else { (*pcStreams)++; } } } return S_OK; }
HRESULT CStreamSwitcherOutputPin::DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties) { CStreamSwitcherInputPin* pIn = (static_cast<CStreamSwitcherFilter*>(m_pFilter))->GetInputPin(); if (!pIn || !pIn->IsConnected()) { return E_UNEXPECTED; } CComPtr<IMemAllocator> pAllocatorIn; pIn->GetAllocator(&pAllocatorIn); if (!pAllocatorIn) { return E_UNEXPECTED; } HRESULT hr; if (FAILED(hr = pAllocatorIn->GetProperties(pProperties))) { return hr; } if (pProperties->cBuffers < 8 && pIn->CurrentMediaType().majortype == MEDIATYPE_Audio) { pProperties->cBuffers = 8; } ALLOCATOR_PROPERTIES Actual; if (FAILED(hr = pAllocator->SetProperties(pProperties, &Actual))) { return hr; } return (pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer ? E_FAIL : NOERROR); }
STDMETHODIMP CStreamSwitcherOutputPin::Notify(IBaseFilter* pSender, Quality q) { CStreamSwitcherInputPin* pIn = (static_cast<CStreamSwitcherFilter*>(m_pFilter))->GetInputPin(); if (!pIn || !pIn->IsConnected()) { return VFW_E_NOT_CONNECTED; } return pIn->PassNotify(q); }
STDMETHODIMP CStreamSwitcherFilter::Enable(long lIndex, DWORD dwFlags) { if (dwFlags != AMSTREAMSELECTENABLE_ENABLE) { return E_NOTIMPL; } PauseGraph; bool bFound = false; int i = 0; CStreamSwitcherInputPin* pNewInputPin = nullptr; POSITION pos = m_pInputs.GetHeadPosition(); while (pos && !bFound) { pNewInputPin = m_pInputs.GetNext(pos); if (pNewInputPin->IsConnected()) { if (CComPtr<IAMStreamSelect> pSSF = pNewInputPin->GetStreamSelectionFilter()) { DWORD cStreams = 0; HRESULT hr = pSSF->Count(&cStreams); if (SUCCEEDED(hr)) { for (i = 0; i < (int)cStreams; i++) { AM_MEDIA_TYPE* pmt = nullptr; hr = pSSF->Info(i, &pmt, nullptr, nullptr, NULL, nullptr, nullptr, nullptr); if (SUCCEEDED(hr) && pmt && pmt->majortype == MEDIATYPE_Audio) { if (lIndex == 0) { bFound = true; DeleteMediaType(pmt); break; } else { lIndex--; } } DeleteMediaType(pmt); } } } else if (lIndex == 0) { bFound = true; } else { lIndex--; } } } if (!bFound) { return E_INVALIDARG; } SelectInput(pNewInputPin); if (CComPtr<IAMStreamSelect> pSSF = pNewInputPin->GetStreamSelectionFilter()) { pSSF->Enable(i, dwFlags); } ResumeGraph; return S_OK; }
HRESULT CStreamSwitcherOutputPin::DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties) { CStreamSwitcherInputPin* pIn = ((CStreamSwitcherFilter*)m_pFilter)->GetInputPin(); if(!pIn || !pIn->IsConnected()) { SVP_LogMsg5(L"DecideBufferSize if(!pIn || !pIn->IsConnected()) {"); return E_UNEXPECTED; } CComPtr<IMemAllocator> pAllocatorIn; pIn->GetAllocator(&pAllocatorIn); if(!pAllocatorIn){ SVP_LogMsg5(L"DecideBufferSize pIn->GetAllocator(&pAllocatorIn);"); return E_UNEXPECTED; } HRESULT hr; if(FAILED(hr = pAllocatorIn->GetProperties(pProperties))) { SVP_LogMsg5(L"DecideBufferSize if(FAILED(hr = pAllocatorIn->GetProperties(pProperties))) {"); return hr; } if( pIn->CurrentMediaType().majortype == MEDIATYPE_Audio){ if(pProperties->cBuffers < 8) pProperties->cBuffers = 8; WAVEFORMATEX* wfe = (WAVEFORMATEX*)pIn->CurrentMediaType().pbFormat; pProperties->cbBuffer = (long) ((__int64) pProperties->cbBuffer * 8 / min( wfe->nChannels ,8 ) * 96000 / min( wfe->nSamplesPerSec, 96000)); } ALLOCATOR_PROPERTIES Actual; if(FAILED(hr = pAllocator->SetProperties(pProperties, &Actual))) { SVP_LogMsg5(L"DecideBufferSize if(FAILED(hr = pAllocator->SetProperties(pProperties, &Actual))) {"); return hr; } hr = (pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer ? E_FAIL : NOERROR); SVP_LogMsg5(L"DecideBufferSize %d %d %d %d %x",pProperties->cBuffers ,Actual.cBuffers , pProperties->cbBuffer , Actual.cbBuffer , hr ); return hr; }
CStreamSwitcherInputPin* CStreamSwitcherFilter::GetConnectedInputPin(int n) { if (n >= 0) { POSITION pos = m_pInputs.GetHeadPosition(); while (pos) { CStreamSwitcherInputPin* pPin = m_pInputs.GetNext(pos); if (pPin->IsConnected()) { if (n == 0) { return pPin; } n--; } } } return nullptr; }
HRESULT CStreamSwitcherOutputPin::QueryAcceptUpstream(const AM_MEDIA_TYPE* pmt) { HRESULT hr = S_FALSE; CStreamSwitcherInputPin* pIn = (static_cast<CStreamSwitcherFilter*>(m_pFilter))->GetInputPin(); if (pIn && pIn->IsConnected() && (pIn->IsUsingOwnAllocator() || pIn->CurrentMediaType() == *pmt)) { if (CComQIPtr<IPin> pPinTo = pIn->GetConnected()) { if (S_OK != (hr = pPinTo->QueryAccept(pmt))) { return VFW_E_TYPE_NOT_ACCEPTED; } } else { return E_FAIL; } } return hr; }
HRESULT CStreamSwitcherOutputPin::CompleteConnect(IPin* pReceivePin) { m_pPinConnection = CComQIPtr<IPinConnection>(pReceivePin); HRESULT hr = __super::CompleteConnect(pReceivePin); CStreamSwitcherInputPin* pIn = (static_cast<CStreamSwitcherFilter*>(m_pFilter))->GetInputPin(); CMediaType mt; if (SUCCEEDED(hr) && pIn && pIn->IsConnected() && SUCCEEDED(pIn->GetConnected()->ConnectionMediaType(&mt)) && m_mt != mt) { if (pIn->GetConnected()->QueryAccept(&m_mt) == S_OK) { hr = m_pFilter->ReconnectPin(pIn->GetConnected(), &m_mt); } else { hr = VFW_E_TYPE_NOT_ACCEPTED; } } return hr; }
// pdwGroup value is set to: // - 0 if the track isn't controlled by any underlying IAMStreamSelect interface // - 1 if the track is controlled by an underlying IAMStreamSelect interface and is not selected at that level // - 2 if the track is controlled by an underlying IAMStreamSelect interface and is selected at that level STDMETHODIMP CStreamSwitcherFilter::Info(long lIndex, AM_MEDIA_TYPE** ppmt, DWORD* pdwFlags, LCID* plcid, DWORD* pdwGroup, WCHAR** ppszName, IUnknown** ppObject, IUnknown** ppUnk) { CAutoLock cAutoLock(&m_csPins); IUnknown* pObject = nullptr; bool bFound = false; POSITION pos = m_pInputs.GetHeadPosition(); while (pos && !bFound) { CStreamSwitcherInputPin* pInputPin = m_pInputs.GetNext(pos); if (pInputPin->IsConnected()) { if (CComPtr<IAMStreamSelect> pSSF = pInputPin->GetStreamSelectionFilter()) { DWORD cStreams = 0; HRESULT hr = pSSF->Count(&cStreams); if (SUCCEEDED(hr)) { for (int i = 0; i < (int)cStreams; i++) { AM_MEDIA_TYPE* pmt = nullptr; DWORD dwFlags; LPWSTR pszName = nullptr; hr = pSSF->Info(i, &pmt, &dwFlags, plcid, NULL, &pszName, nullptr, nullptr); if (SUCCEEDED(hr) && pmt && pmt->majortype == MEDIATYPE_Audio) { if (lIndex == 0) { bFound = true; pObject = pSSF; if (ppmt) { *ppmt = pmt; } else { DeleteMediaType(pmt); } if (pdwFlags) { *pdwFlags = (m_pInput == pInputPin) ? dwFlags : 0; } if (pdwGroup) { *pdwGroup = (dwFlags & (AMSTREAMSELECTINFO_ENABLED | AMSTREAMSELECTINFO_EXCLUSIVE)) ? 2 : 1; } if (ppszName) { *ppszName = pszName; } else { CoTaskMemFree(pszName); } break; } else { lIndex--; } } DeleteMediaType(pmt); CoTaskMemFree(pszName); } } } else if (lIndex == 0) { bFound = true; if (ppmt) { *ppmt = CreateMediaType(&m_pOutput->CurrentMediaType()); } if (pdwFlags) { *pdwFlags = (m_pInput == pInputPin) ? AMSTREAMSELECTINFO_EXCLUSIVE : 0; } if (plcid) { *plcid = 0; } if (pdwGroup) { *pdwGroup = 0; } if (ppszName) { *ppszName = (WCHAR*)CoTaskMemAlloc((wcslen(pInputPin->Name()) + 1) * sizeof(WCHAR)); if (*ppszName) { wcscpy_s(*ppszName, wcslen(pInputPin->Name()) + 1, pInputPin->Name()); } } } else { lIndex--; } } } if (!bFound) { return E_INVALIDARG; } if (ppObject) { *ppObject = pObject; if (pObject) { pObject->AddRef(); } } if (ppUnk) { *ppUnk = nullptr; } return S_OK; }