HRESULT CBaseSplitterFilter::RenameOutputPin(DWORD TrackNumSrc, DWORD TrackNumDst, const AM_MEDIA_TYPE* pmt) { CAutoLock cAutoLock(&m_csPinMap); CBaseSplitterOutputPin* pPin; if (m_pPinMap.Lookup(TrackNumSrc, pPin)) { if (CComQIPtr<IPin> pPinTo = pPin->GetConnected()) { if (pmt && S_OK != pPinTo->QueryAccept(pmt)) { return VFW_E_TYPE_NOT_ACCEPTED; } } m_pPinMap.RemoveKey(TrackNumSrc); m_pPinMap[TrackNumDst] = pPin; if (pmt) { CAutoLock cAutoLock2(&m_csmtnew); m_mtnew[TrackNumDst] = *pmt; } return S_OK; } return E_FAIL; }
STDMETHODIMP CBaseSplitterFilter::GetStatus(int i, int& samples, int& size) { CAutoLock cAutoLock(m_pLock); if (POSITION pos = m_pOutputs.FindIndex(i)) { CBaseSplitterOutputPin* pPin = m_pOutputs.GetAt(pos); samples = pPin->QueueCount(); size = pPin->QueueSize(); return pPin->IsConnected() ? S_OK : S_FALSE; } return E_INVALIDARG; }
bool CBaseSplitterFilter::IsAnyPinDrying() { int totalcount = 0, totalsize = 0; POSITION pos = m_pActivePins.GetHeadPosition(); while (pos) { CBaseSplitterOutputPin* pPin = m_pActivePins.GetNext(pos); int count = pPin->QueueCount(); int size = pPin->QueueSize(); if (!pPin->IsDiscontinuous() && (count < MINPACKETS || size < MINPACKETSIZE)) { // if (m_priority != THREAD_PRIORITY_ABOVE_NORMAL && (count < MINPACKETS/3 || size < MINPACKETSIZE/3)) if (m_priority != THREAD_PRIORITY_BELOW_NORMAL && (count < MINPACKETS / 3 || size < MINPACKETSIZE / 3)) { // SetThreadPriority(m_hThread, m_priority = THREAD_PRIORITY_ABOVE_NORMAL); POSITION pos = m_pOutputs.GetHeadPosition(); while (pos) { m_pOutputs.GetNext(pos)->SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL); } m_priority = THREAD_PRIORITY_BELOW_NORMAL; } return true; } totalcount += count; totalsize += size; } if (m_priority != THREAD_PRIORITY_NORMAL && (totalcount > m_QueueMaxPackets * 2 / 3 || totalsize > MAXPACKETSIZE * 2 / 3)) { // SetThreadPriority(m_hThread, m_priority = THREAD_PRIORITY_NORMAL); POSITION pos = m_pOutputs.GetHeadPosition(); while (pos) { m_pOutputs.GetNext(pos)->SetThreadPriority(THREAD_PRIORITY_NORMAL); } m_priority = THREAD_PRIORITY_NORMAL; } if (totalcount < m_QueueMaxPackets && totalsize < MAXPACKETSIZE) { return true; } return false; }
HRESULT CBaseSplitterFilter::RenameOutputPin(DWORD TrackNumSrc, DWORD TrackNumDst, std::vector<CMediaType> mts, BOOL bNeedReconnect /*= FALSE*/) { CAutoLock cAutoLock(&m_csPinMap); CBaseSplitterOutputPin* pPin; if (m_pPinMap.Lookup(TrackNumSrc, pPin)) { AM_MEDIA_TYPE* pmt = NULL; HRESULT hr = S_OK; if (CComQIPtr<IPin> pPinTo = pPin->GetConnected()) { for (size_t i = 0; i < mts.size(); i++) { if (S_OK == pPinTo->QueryAccept(&mts[i])) { pmt = &mts[i]; break; } } if (!pmt) { pmt = &mts[0]; } if (bNeedReconnect) { hr = ReconnectPin(pPinTo, pmt); } } m_pPinMap.RemoveKey(TrackNumSrc); m_pPinMap[TrackNumDst] = pPin; if (pmt) { CAutoLock cAutoLock(&m_csmtnew); m_mtnew[TrackNumDst] = *pmt; } return hr; } return E_FAIL; }
bool CBaseSplitterFilter::IsAnyPinDrying(DWORD MaxQueuePackets) { size_t totalcount = 0, totalsize = 0; POSITION pos = m_pActivePins.GetHeadPosition(); while (pos) { CBaseSplitterOutputPin* pPin = m_pActivePins.GetNext(pos); size_t count = pPin->QueueCount(); size_t size = pPin->QueueSize(); if (!pPin->IsDiscontinuous() && (count < m_MinQueuePackets || size < GetMinQueueSize())) { if (m_priority != THREAD_PRIORITY_BELOW_NORMAL && (count < m_MinQueuePackets/3 || size < GetMinQueueSize()/3)) { POSITION pos = m_pOutputs.GetHeadPosition(); while (pos) { m_pOutputs.GetNext(pos)->SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL); } m_priority = THREAD_PRIORITY_BELOW_NORMAL; } return true; } totalcount += count; totalsize += size; } if (m_priority != THREAD_PRIORITY_NORMAL && (totalcount > MaxQueuePackets*2/3 || totalsize > GetMaxQueueSize()*2/3)) { POSITION pos = m_pOutputs.GetHeadPosition(); while (pos) { m_pOutputs.GetNext(pos)->SetThreadPriority(THREAD_PRIORITY_NORMAL); } m_priority = THREAD_PRIORITY_NORMAL; } if (totalcount < m_MaxQueuePackets && totalsize < GetMaxQueueSize()) { return true; } return false; }
DWORD CBaseSplitterFilter::ThreadProc() { if (m_pSyncReader) { m_pSyncReader->SetBreakEvent(GetRequestHandle()); } if (!DemuxInit()) { for (;;) { DWORD cmd = GetRequest(); if (cmd == CMD_EXIT) { CAMThread::m_hThread = nullptr; } Reply(S_OK); if (cmd == CMD_EXIT) { return 0; } } } m_eEndFlush.Set(); m_fFlushing = false; for (DWORD cmd = DWORD_ERROR; ; cmd = GetRequest()) { if (cmd == CMD_EXIT) { m_hThread = nullptr; Reply(S_OK); return 0; } SetThreadPriority(m_hThread, m_priority = THREAD_PRIORITY_NORMAL); m_rtStart = m_rtNewStart; m_rtStop = m_rtNewStop; DemuxSeek(m_rtStart); if (cmd != DWORD_ERROR) { Reply(S_OK); } m_eEndFlush.Wait(); m_pActivePins.RemoveAll(); POSITION pos = m_pOutputs.GetHeadPosition(); while (pos && !m_fFlushing) { CBaseSplitterOutputPin* pPin = m_pOutputs.GetNext(pos); if (pPin->IsConnected() && pPin->IsActive()) { m_pActivePins.AddTail(pPin); pPin->DeliverNewSegment(m_rtStart, m_rtStop, m_dRate); } } do { m_bDiscontinuitySent.RemoveAll(); } while (!DemuxLoop()); pos = m_pActivePins.GetHeadPosition(); while (pos && !CheckRequest(&cmd)) { m_pActivePins.GetNext(pos)->QueueEndOfStream(); } } ASSERT(0); // we should only exit via CMD_EXIT m_hThread = nullptr; return 0; }
HRESULT CBaseSplitterFilter::DeliverPacket(CAutoPtr<Packet> p) { HRESULT hr = S_FALSE; CBaseSplitterOutputPin* pPin = GetOutputPin(p->TrackNumber); if (!pPin || !pPin->IsConnected() || !m_pActivePins.Find(pPin)) { return S_FALSE; } if (p->rtStart != Packet::INVALID_TIME) { m_rtCurrent = p->rtStart; p->rtStart -= m_rtStart; p->rtStop -= m_rtStart; ASSERT(p->rtStart <= p->rtStop); } { CAutoLock cAutoLock(&m_csmtnew); CMediaType mt; if (m_mtnew.Lookup(p->TrackNumber, mt)) { p->pmt = CreateMediaType(&mt); m_mtnew.RemoveKey(p->TrackNumber); } } if (!m_bDiscontinuitySent.Find(p->TrackNumber)) { p->bDiscontinuity = TRUE; } DWORD TrackNumber = p->TrackNumber; BOOL bDiscontinuity = p->bDiscontinuity; #if defined(_DEBUG) && 0 TRACE(_T("[%d]: d%d s%d p%d, b=%d, [%20I64d - %20I64d]\n"), p->TrackNumber, p->bDiscontinuity, p->bSyncPoint, p->rtStart != Packet::INVALID_TIME && p->rtStart < 0, p->GetCount(), p->rtStart, p->rtStop); #endif hr = pPin->QueuePacket(p); if (S_OK != hr) { if (POSITION pos = m_pActivePins.Find(pPin)) { m_pActivePins.RemoveAt(pos); } if (!m_pActivePins.IsEmpty()) { // only die when all pins are down hr = S_OK; } return hr; } if (bDiscontinuity) { m_bDiscontinuitySent.AddTail(TrackNumber); } return hr; }