STDMETHODIMP CStreamSwitcherInputPin::NonDelegatingQueryInterface(REFIID riid, void** ppv) { return QI(IStreamSwitcherInputPin) IsConnected() && GetCLSID(GetFilterFromPin(GetConnected())) == __uuidof(NeroAudioDecoder) && QI(IPinConnection) __super::NonDelegatingQueryInterface(riid, ppv); }
HRESULT CBaseMuxerInputPin::CompleteConnect(IPin* pReceivePin) { HRESULT hr = __super::CompleteConnect(pReceivePin); if (FAILED(hr)) { return hr; } // duration m_rtDuration = 0; CComQIPtr<IMediaSeeking> pMS; if ((pMS = GetFilterFromPin(pReceivePin)) || (pMS = pReceivePin)) { pMS->GetDuration(&m_rtDuration); } // properties for (CComPtr<IPin> pPin = pReceivePin; pPin; pPin = GetUpStreamPin(GetFilterFromPin(pPin))) { if (CComQIPtr<IDSMPropertyBag> pPB = pPin) { ULONG cProperties = 0; if (SUCCEEDED(pPB->CountProperties(&cProperties)) && cProperties > 0) { for (ULONG iProperty = 0; iProperty < cProperties; iProperty++) { PROPBAG2 PropBag; memset(&PropBag, 0, sizeof(PropBag)); ULONG cPropertiesReturned = 0; if (FAILED(pPB->GetPropertyInfo(iProperty, 1, &PropBag, &cPropertiesReturned))) { continue; } HRESULT hr2; CComVariant var; if (SUCCEEDED(pPB->Read(1, &PropBag, NULL, &var, &hr2)) && SUCCEEDED(hr2)) { SetProperty(PropBag.pstrName, &var); } CoTaskMemFree(PropBag.pstrName); } } } } (static_cast<CBaseMuxerFilter*>(m_pFilter))->AddInput(); return S_OK; }
HRESULT CStreamSwitcherOutputPin::CheckConnect(IPin* pPin) { CComPtr<IBaseFilter> pBF = GetFilterFromPin(pPin); return IsAudioWaveRenderer(pBF) || GetCLSID(pBF) == __uuidof(MatrixMixer) ? __super::CheckConnect(pPin) : E_FAIL; // return CComQIPtr<IPinConnection>(pPin) ? CBaseOutputPin::CheckConnect(pPin) : E_NOINTERFACE; // return CBaseOutputPin::CheckConnect(pPin); }
bool CBaseSplitterOutputPin::IsActive() { CComPtr<IPin> pPin = this; do { CComPtr<IPin> pPinTo; CComQIPtr<IStreamSwitcherInputPin> pSSIP; if (S_OK == pPin->ConnectedTo(&pPinTo) && (pSSIP = pPinTo) && !pSSIP->IsActive()) { return false; } pPin = GetFirstPin(GetFilterFromPin(pPinTo), PINDIR_OUTPUT); } while (pPin); return true; }
STDMETHODIMP CBaseMuxerFilter::SetPositions(LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags) { FILTER_STATE fs; if(SUCCEEDED(GetState(0, &fs)) && fs == State_Stopped) { POSITION pos = m_pInputs.GetHeadPosition(); while(pos) { CBasePin* pPin = m_pInputs.GetNext(pos); CComQIPtr<IMediaSeeking> pMS = pPin->GetConnected(); if(!pMS) pMS = GetFilterFromPin(pPin->GetConnected()); if(pMS) pMS->SetPositions(pCurrent, dwCurrentFlags, pStop, dwStopFlags); } return S_OK; } return VFW_E_WRONG_STATE; }
BeginEnumPins(pBFParent, pEP, pPin) { CComPtr<IPin> pPinTo; CComPtr<IBaseFilter> pBF; if(S_OK != m_pGB->IsPinDirection(pPin, PINDIR_OUTPUT) || FAILED(pPin->ConnectedTo(&pPinTo)) || !pPinTo || !(pBF = GetFilterFromPin(pPinTo))) continue; CTreeItem* t = NULL; if(pBF == m_pMux) { t = DNew CTreeItemPin(pPin, m_tree, hTIParent); } else { t = DNew CTreeItemFilter(pBF, m_tree, hTIParent); AddFilter(*t, pBF); } }
void CBaseSplitterOutputPin::MakeISCRHappy() { CComPtr<IPin> pPinTo = this, pTmp; while (pPinTo && SUCCEEDED(pPinTo->ConnectedTo(&pTmp)) && (pPinTo = pTmp)) { pTmp = nullptr; CComPtr<IBaseFilter> pBF = GetFilterFromPin(pPinTo); if (GetCLSID(pBF) == GUIDFromCString(_T("{48025243-2D39-11CE-875D-00608CB78066}"))) { // ISCR CAutoPtr<Packet> p(DEBUG_NEW Packet()); p->TrackNumber = DWORD_ERROR; p->rtStart = -1; p->rtStop = 0; p->bSyncPoint = FALSE; p->SetData(" ", 2); QueuePacket(p); break; } pPinTo = GetFirstPin(pBF, PINDIR_OUTPUT); } }
DWORD CBaseSplitterOutputPin::ThreadProc() { SetThreadName(DWORD(-1), "CBaseSplitterOutputPin"); m_hrDeliver = S_OK; m_fFlushing = m_fFlushed = false; m_eEndFlush.Set(); // fix for Microsoft DTV-DVD Video Decoder - video freeze after STOP/PLAY bool iHaaliRenderConnect = false; CComPtr<IPin> pPinTo = this, pTmp; while (pPinTo && SUCCEEDED(pPinTo->ConnectedTo(&pTmp)) && (pPinTo = pTmp)) { pTmp = nullptr; CComPtr<IBaseFilter> pBF = GetFilterFromPin(pPinTo); if (GetCLSID(pBF) == CLSID_DXR) { // Haali Renderer iHaaliRenderConnect = true; break; } pPinTo = GetFirstPin(pBF, PINDIR_OUTPUT); } if (IsConnected() && !iHaaliRenderConnect) { GetConnected()->BeginFlush(); GetConnected()->EndFlush(); } for (;;) { Sleep(1); DWORD cmd; if (CheckRequest(&cmd)) { m_hThread = nullptr; cmd = GetRequest(); Reply(S_OK); ASSERT(cmd == CMD_EXIT); return 0; } int cnt = 0; do { CAutoPtr<Packet> p; { CAutoLock cAutoLock(&m_queue); if ((cnt = m_queue.GetCount()) > 0) { p = m_queue.Remove(); } } if (S_OK == m_hrDeliver && cnt > 0) { ASSERT(!m_fFlushing); m_fFlushed = false; // flushing can still start here, to release a blocked deliver call HRESULT hr = p ? DeliverPacket(p) : DeliverEndOfStream(); m_eEndFlush.Wait(); // .. so we have to wait until it is done if (hr != S_OK && !m_fFlushed) { // and only report the error in m_hrDeliver if we didn't flush the stream // CAutoLock cAutoLock(&m_csQueueLock); m_hrDeliver = hr; break; } } } while (--cnt > 0); } }
HRESULT CStreamSwitcherInputPin::CompleteConnect(IPin* pReceivePin) { HRESULT hr = __super::CompleteConnect(pReceivePin); if (FAILED(hr)) { return hr; } (static_cast<CStreamSwitcherFilter*>(m_pFilter))->CompleteConnect(PINDIR_INPUT, this, pReceivePin); m_fCanBlock = false; bool fForkedSomewhere = false; CStringW fileName; CStringW pinName; IPin* pPin = (IPin*)this; IBaseFilter* pBF = (IBaseFilter*)m_pFilter; pPin = GetUpStreamPin(pBF, pPin); if (pPin) { pBF = GetFilterFromPin(pPin); } while (pPin && pBF) { if (IsSplitter(pBF)) { pinName = GetPinName(pPin); } CLSID clsid = GetCLSID(pBF); if (clsid == CLSID_AviSplitter || clsid == CLSID_OggSplitter) { m_fCanBlock = true; } int nIn, nOut, nInC, nOutC; CountPins(pBF, nIn, nOut, nInC, nOutC); fForkedSomewhere = fForkedSomewhere || nIn > 1 || nOut > 1; DWORD cStreams = 0; if (CComQIPtr<IAMStreamSelect> pSSF = pBF) { 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) { m_pSSF = pSSF; DeleteMediaType(pmt); break; } DeleteMediaType(pmt); } } } if (CComQIPtr<IFileSourceFilter> pFSF = pBF) { WCHAR* pszName = nullptr; AM_MEDIA_TYPE mt; if (SUCCEEDED(pFSF->GetCurFile(&pszName, &mt)) && pszName) { fileName = pszName; CoTaskMemFree(pszName); fileName.Replace('\\', '/'); CStringW fn = fileName.Mid(fileName.ReverseFind('/') + 1); if (!fn.IsEmpty()) { fileName = fn; } // Haali & LAVFSplitter return only one "Audio" pin name, cause CMainFrame::OnInitMenuPopup lookup find the wrong popmenu, // add space at the end to prevent this, internal filter never return "Audio" only. if (!pinName.IsEmpty()) { fileName = pinName + L" "; } WCHAR* pName = DEBUG_NEW WCHAR[fileName.GetLength() + 1]; if (pName) { wcscpy_s(pName, fileName.GetLength() + 1, fileName); if (m_pName) { delete [] m_pName; } m_pName = pName; if (cStreams == 1) { // Simple external track, no need to use the info from IAMStreamSelect m_pSSF.Release(); } } } break; } pPin = GetFirstPin(pBF); pPin = GetUpStreamPin(pBF, pPin); if (pPin) { pBF = GetFilterFromPin(pPin); } } if (!fForkedSomewhere) { m_fCanBlock = true; } m_hNotifyEvent = nullptr; return S_OK; }
HRESULT CStreamSwitcherInputPin::CompleteConnect(IPin* pReceivePin) { HRESULT hr = __super::CompleteConnect(pReceivePin); if(FAILED(hr)) return hr; ((CStreamSwitcherFilter*)m_pFilter)->CompleteConnect(PINDIR_INPUT, this, pReceivePin); m_fCanBlock = false; bool fForkedSomewhere = false; CStringW fileName; CStringW pinName; IPin* pPin = (IPin*)this; IBaseFilter* pBF = (IBaseFilter*)m_pFilter; while((pPin = GetUpStreamPin(pBF, pPin)) && (pBF = GetFilterFromPin(pPin))) { if(IsSplitter(pBF)) { pinName = GetPinName(pPin); } CLSID clsid = GetCLSID(pBF); if(clsid == CLSID_AviSplitter || clsid == CLSID_OggSplitter) m_fCanBlock = true; int nIn, nOut, nInC, nOutC; CountPins(pBF, nIn, nOut, nInC, nOutC); fForkedSomewhere = fForkedSomewhere || nIn > 1 || nOut > 1; if(CComQIPtr<IFileSourceFilter> pFSF = pBF) { WCHAR* pszName = NULL; AM_MEDIA_TYPE mt; if(SUCCEEDED(pFSF->GetCurFile(&pszName, &mt)) && pszName) { fileName = pszName; CoTaskMemFree(pszName); fileName.Replace('\\', '/'); CStringW fn = fileName.Mid(fileName.ReverseFind('/')+1); if(!fn.IsEmpty()) fileName = fn; if(!pinName.IsEmpty()) fileName += L" / " + pinName; WCHAR* pName = new WCHAR[fileName.GetLength()+1]; if(pName) { wcscpy(pName, fileName); if(m_pName) delete [] m_pName; m_pName = pName; } } break; } pPin = GetFirstPin(pBF); } if(!fForkedSomewhere) m_fCanBlock = true; m_hNotifyEvent = NULL; return S_OK; }
DWORD CStreamDriveThruFilter::ThreadProc() { while(1) { DWORD cmd = GetRequest(); switch(cmd) { default: case CMD_EXIT: Reply(S_OK); return 0; case CMD_STOP: Reply(S_OK); break; case CMD_PAUSE: Reply(S_OK); break; case CMD_RUN: Reply(S_OK); do { CComPtr<IAsyncReader> pAsyncReader; CComPtr<IStream> pStream; if(!m_pInput || !m_pInput->IsConnected() || FAILED(m_pInput->GetAsyncReader(&pAsyncReader)) || !m_pOutput || !m_pOutput->IsConnected() || FAILED(m_pOutput->GetStream(&pStream))) break; LARGE_INTEGER li = {0}; ULARGE_INTEGER uli = {0}; if(FAILED(pStream->Seek(li, STREAM_SEEK_SET, NULL)) || FAILED(pStream->SetSize(uli))) break; if(CComQIPtr<IFileSinkFilter2> pFSF = GetFilterFromPin(m_pOutput->GetConnected())) { pFSF->SetMode(AM_FILE_OVERWRITE); LPOLESTR pfn; if(SUCCEEDED(pFSF->GetCurFile(&pfn, NULL))) { pFSF->SetFileName(pfn, NULL); CoTaskMemFree(pfn); } } m_position = 0; BYTE buff[PACKETSIZE]; do { while(!CheckRequest(&cmd)) { CAutoLock csAutoLock(&m_csLock); LONGLONG total = 0, available = 0; if(FAILED(pAsyncReader->Length(&total, &available)) || m_position >= total) { cmd = CMD_STOP; break; } LONG size = (LONG)min(PACKETSIZE, total - m_position); if(FAILED(pAsyncReader->SyncRead(m_position, size, buff))) { cmd = CMD_STOP; break; } ULONG written = 0; if(FAILED(pStream->Write(buff, (ULONG)size, &written)) || (ULONG)size != written) { cmd = CMD_STOP; break; } m_position += size; } if(cmd == CMD_PAUSE) { Reply(S_OK); // reply to CMD_PAUSE while(!CheckRequest(&cmd)) Sleep(50); Reply(S_OK); // reply to something } } while(cmd == CMD_RUN); uli.QuadPart = m_position; pStream->SetSize(uli); if(CComPtr<IPin> pPin = m_pOutput->GetConnected()) pPin->EndOfStream(); } while(false); break; } } return 0; }
void CDSMMuxerFilter::MuxHeader(IBitStream* pBS) { CString muxer; muxer.Format(_T("DSM Muxer (%s)"), CString(__TIMESTAMP__)); SetProperty(L"MUXR", CStringW(muxer)); SetProperty(L"DATE", CStringW(CTime::GetCurrentTime().FormatGmt(_T("%Y-%m-%d %H:%M:%S")))); MuxFileInfo(pBS); POSITION pos = m_pPins.GetHeadPosition(); while (pos) { CBaseMuxerInputPin* pPin = m_pPins.GetNext(pos); const CMediaType& mt = pPin->CurrentMediaType(); ASSERT((mt.lSampleSize >> 30) == 0); // you don't need >1GB samples, do you? MuxPacketHeader(pBS, DSMP_MEDIATYPE, 5 + sizeof(GUID) * 3 + mt.FormatLength()); pBS->BitWrite(pPin->GetID(), 8); pBS->ByteWrite(&mt.majortype, sizeof(mt.majortype)); pBS->ByteWrite(&mt.subtype, sizeof(mt.subtype)); pBS->BitWrite(mt.bFixedSizeSamples, 1); pBS->BitWrite(mt.bTemporalCompression, 1); pBS->BitWrite(mt.lSampleSize, 30); pBS->ByteWrite(&mt.formattype, sizeof(mt.formattype)); pBS->ByteWrite(mt.Format(), mt.FormatLength()); MuxStreamInfo(pBS, pPin); } // resources & chapters CInterfaceList<IDSMResourceBag> pRBs; pRBs.AddTail(this); CComQIPtr<IDSMChapterBag> pCB = (IUnknown*)(INonDelegatingUnknown*)this; pos = m_pPins.GetHeadPosition(); while (pos) { for (CComPtr<IPin> pPin = m_pPins.GetNext(pos)->GetConnected(); pPin; pPin = GetUpStreamPin(GetFilterFromPin(pPin))) { if (m_fAutoRes) { CComQIPtr<IDSMResourceBag> pPB = GetFilterFromPin(pPin); if (pPB && !pRBs.Find(pPB)) { pRBs.AddTail(pPB); } } if (m_fAutoChap) { if (!pCB || pCB->ChapGetCount() == 0) { pCB = GetFilterFromPin(pPin); } } } } // resources pos = pRBs.GetHeadPosition(); while (pos) { IDSMResourceBag* pRB = pRBs.GetNext(pos); for (DWORD i = 0, j = pRB->ResGetCount(); i < j; i++) { CComBSTR name, desc, mime; BYTE* pData = NULL; DWORD len = 0; if (SUCCEEDED(pRB->ResGet(i, &name, &desc, &mime, &pData, &len, NULL))) { CStringA utf8_name = UTF16To8(name); CStringA utf8_desc = UTF16To8(desc); CStringA utf8_mime = UTF16To8(mime); MuxPacketHeader(pBS, DSMP_RESOURCE, 1 + utf8_name.GetLength() + 1 + utf8_desc.GetLength() + 1 + utf8_mime.GetLength() + 1 + len); pBS->BitWrite(0, 2); pBS->BitWrite(0, 6); // reserved pBS->ByteWrite(utf8_name, utf8_name.GetLength() + 1); pBS->ByteWrite(utf8_desc, utf8_desc.GetLength() + 1); pBS->ByteWrite(utf8_mime, utf8_mime.GetLength() + 1); pBS->ByteWrite(pData, len); CoTaskMemFree(pData); } } } // chapters if (pCB) { CAtlList<CDSMChapter> chapters; REFERENCE_TIME rtPrev = 0; int len = 0; pCB->ChapSort(); for (DWORD i = 0; i < pCB->ChapGetCount(); i++) { CDSMChapter c; CComBSTR name; if (SUCCEEDED(pCB->ChapGet(i, &c.rt, &name))) { REFERENCE_TIME rtDiff = c.rt - rtPrev; rtPrev = c.rt; c.rt = rtDiff; c.name = name; len += 1 + GetByteLength(myabs(c.rt)) + UTF16To8(c.name).GetLength() + 1; chapters.AddTail(c); } } if (chapters.GetCount()) { MuxPacketHeader(pBS, DSMP_CHAPTERS, len); pos = chapters.GetHeadPosition(); while (pos) { CDSMChapter& c = chapters.GetNext(pos); CStringA name = UTF16To8(c.name); int irt = GetByteLength(myabs(c.rt)); pBS->BitWrite(c.rt < 0, 1); pBS->BitWrite(irt, 3); pBS->BitWrite(0, 4); pBS->BitWrite(myabs(c.rt), irt << 3); pBS->ByteWrite((LPCSTR)name, name.GetLength() + 1); } } } }
HRESULT CStreamSwitcherInputPin::CompleteConnect(IPin* pReceivePin) { HRESULT hr = __super::CompleteConnect(pReceivePin); if (FAILED(hr)) { return hr; } (static_cast<CStreamSwitcherFilter*>(m_pFilter))->CompleteConnect(PINDIR_INPUT, this, pReceivePin); m_fCanBlock = false; bool fForkedSomewhere = false; CStringW fileName; CStringW pinName; IPin* pPin = (IPin*)this; IBaseFilter* pBF = (IBaseFilter*)m_pFilter; pPin = GetUpStreamPin(pBF, pPin); if (pPin) { pBF = GetFilterFromPin(pPin); } while (pPin && pBF) { if (IsSplitter(pBF)) { pinName = GetPinName(pPin); } CLSID clsid = GetCLSID(pBF); if (clsid == CLSID_AviSplitter || clsid == CLSID_OggSplitter) { m_fCanBlock = true; } int nIn, nOut, nInC, nOutC; CountPins(pBF, nIn, nOut, nInC, nOutC); fForkedSomewhere = fForkedSomewhere || nIn > 1 || nOut > 1; if (CComQIPtr<IFileSourceFilter> pFSF = pBF) { WCHAR* pszName = NULL; AM_MEDIA_TYPE mt; if (SUCCEEDED(pFSF->GetCurFile(&pszName, &mt)) && pszName) { fileName = pszName; CoTaskMemFree(pszName); fileName.Replace('\\', '/'); CStringW fn = fileName.Mid(fileName.ReverseFind('/')+1); if (!fn.IsEmpty()) { fileName = fn; } // Haali & LAVFSplitter return only one "Audio" pin name, cause CMainFrame::OnInitMenuPopup lookup find the wrong popmenu, // add space at the end to prevent this, internal filter never return "Audio" only. if (!pinName.IsEmpty()) { fileName = pinName + L" "; } WCHAR* pName = DNew WCHAR[fileName.GetLength()+1]; if (pName) { wcscpy_s(pName, fileName.GetLength() + 1, fileName); if (m_pName) { delete [] m_pName; } m_pName = pName; } } break; } pPin = GetFirstPin(pBF); pPin = GetUpStreamPin(pBF, pPin); if (pPin) { pBF = GetFilterFromPin(pPin); } } if (!fForkedSomewhere) { m_fCanBlock = true; } m_hNotifyEvent = NULL; return S_OK; }