void CBaseMuxerFilter::AddInput() { POSITION pos = m_pInputs.GetHeadPosition(); while(pos) { CBasePin* pPin = m_pInputs.GetNext(pos); if(!pPin->IsConnected()) return; } CStringW name; name.Format(L"Input %d", m_pInputs.GetCount()+1); CBaseMuxerInputPin* pInputPin = NULL; if(FAILED(CreateInput(name, &pInputPin)) || !pInputPin) {ASSERT(0); return;} CAutoPtr<CBaseMuxerInputPin> pAutoPtrInputPin(pInputPin); name.Format(L"~Output %d", m_pRawOutputs.GetCount()+1); CBaseMuxerRawOutputPin* pRawOutputPin = NULL; if(FAILED(CreateRawOutput(name, &pRawOutputPin)) || !pRawOutputPin) {ASSERT(0); return;} CAutoPtr<CBaseMuxerRawOutputPin> pAutoPtrRawOutputPin(pRawOutputPin); pInputPin->SetRelatedPin(pRawOutputPin); pRawOutputPin->SetRelatedPin(pInputPin); m_pInputs.AddTail(pAutoPtrInputPin); m_pRawOutputs.AddTail(pAutoPtrRawOutputPin); }
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); CBasePin* pPin = GetConnectedInputPin(lIndex); if(!pPin) return E_INVALIDARG; if(ppmt) *ppmt = CreateMediaType(&m_pOutput->CurrentMediaType()); if(pdwFlags) *pdwFlags = (m_pInput == pPin) ? AMSTREAMSELECTINFO_EXCLUSIVE : 0; if(plcid) *plcid = 0; if(pdwGroup) *pdwGroup = 0; if(ppszName && (*ppszName = (WCHAR*)CoTaskMemAlloc((wcslen(pPin->Name())+1)*sizeof(WCHAR)))) wcscpy(*ppszName, pPin->Name()); if(ppObject) *ppObject = NULL; if(ppUnk) *ppUnk = NULL; return S_OK; }
/////////////////////////////////////////////////////////// // all inherited virtual functions /////////////////////////////////////////////////////////// // 1. from CSource CBasePin *CVCam::GetPin(int n) { vcamLog(50, "CVCam::GetPin, n = %d", n); CBasePin *pin = CSource::GetPin(n); ASSERT(pin!=NULL); if(pin->IsConnected()) { vcamLog(50, " CVCam::GetPin: pin is connected"); } else { vcamLog(50, " CVCam::GetPin: pin is not connected"); } return pin; }
// if bSet, only accept settable pins SeekingCollection(CBaseFilter* pFilter) { for (int i = 0; i < pFilter->GetPinCount(); i++) { CBasePin* pPin = pFilter->GetPin(i); PIN_DIRECTION pindir; pPin->QueryDirection(&pindir); if (pindir == PINDIR_INPUT) { IMediaSeekingPtr pSeek = pPin->GetConnected(); if (pSeek != NULL) { m_Pins.push_back(pSeek.Detach()); } } } }
HRESULT GetPeer(CStreamSwitcherFilter* pFilter, T** ppT) { *ppT = NULL; CBasePin* pPin = pFilter->GetInputPin(); if(!pPin) return E_NOTIMPL; CComPtr<IPin> pConnected; if(FAILED(pPin->ConnectedTo(&pConnected))) return E_NOTIMPL; if(CComQIPtr<T> pT = pConnected) { *ppT = pT.Detach(); return S_OK; } return E_NOTIMPL; }
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; }
DWORD WINAPI PushDataThread(PVOID param) { PushParam* pushParam = (PushParam*)param; HANDLE PushSemaphore = pushParam->PushSemaphore; HANDLE PushDataMutex = pushParam->PushDataMutex; NetReceiveFilter* filter = pushParam->filter; std::map<REFERENCE_TIME, IMediaSample*>& SampleList = *pushParam->SampleList; delete pushParam; REFERENCE_TIME startTime,endTime; CRefTime streamTime(LONG(0)),lastStreamTime(LONG(0)); bool first = true; AM_MEDIA_TYPE mediaType; IMediaSample* sample ; while (SampleList.size() == 0) //等待足够多的数据 { WaitForSingleObject(PushSemaphore,INFINITE); } CBasePin* pin = filter->GetPin(0); pin->ConnectionMediaType(&mediaType); IFilterGraph* filterGraph = filter->GetFilterGraph(); ComReleaser filterGraphReleaser(filterGraph); HRESULT hr; IMediaControl* mediaControl; hr = filterGraph->QueryInterface(IID_IMediaControl, (void**)&mediaControl); if(FAILED(hr)) { ErrorPrint("Get media control error", hr); return false; } ComReleaser mediaControlReleaser(mediaControl); while (true) { WaitForSingleObject(PushDataMutex, INFINITE); if (filter->getPlayMode() == 0) // 如果只是尽快播放,则不考虑时间戳,而且一次一sample的往下传 { if (SampleList.size() == 0) { ReleaseMutex(PushDataMutex); while (SampleList.size() == 0) { WaitForSingleObject(PushSemaphore,INFINITE); } WaitForSingleObject(PushDataMutex, INFINITE); } sample = SampleList.begin()->second; } else if (filter->getPlayMode() == 1) //需要考虑时间戳 { NetReceiveFilter::State state = filter->getState(); if (SampleList.size() == 0) { g_ReferenceTimeFilter->pauseTime(); //暂停时钟 ReleaseMutex(PushDataMutex); while (SampleList.size() == 0) //等待足够多的数据 { WaitForSingleObject(PushSemaphore,INFINITE); } WaitForSingleObject(PushDataMutex, INFINITE); g_ReferenceTimeFilter->startTime(); //启动时钟 } if (state == NetReceiveFilter::Stopped) { ReleaseMutex(PushDataMutex); Sleep(50); continue; } if(g_ReferenceTimeFilter->isStop()) { ReleaseMutex(PushDataMutex); Sleep(50); continue; } sample = SampleList.begin()->second; sample->GetTime(&startTime,&endTime); filter->StreamTime(streamTime); //得到当前的流时间 g_ReferenceTimeFilter->GetTime(&startTime); g_ReferenceTimeFilter->GetTime(&endTime); if (mediaType.majortype == MEDIATYPE_Video) { int a = 0; } else { int b = 0; } if(state != NetReceiveFilter::Paused) //pause时不修正 { if(startTime - 10000000 > streamTime ) { ReleaseMutex(PushDataMutex); Sleep(50); continue; } sample->SetTime(&startTime, &endTime); } if (mediaType.majortype == MEDIATYPE_Video) { int a = 0; } else { int b = 0; } } // if (mediaType.majortype == MEDIATYPE_Video) // { // std::cout<<"Push video data."<<std::endl; // } SampleList.erase(SampleList.begin()); ReleaseMutex(PushDataMutex); if(!filter->PushData(sample)) { ErrorPrint("Push data error"); sample->Release(); continue; } sample->Release(); } return 0; }
STDMETHODIMP CEnumPins::Next(ULONG cPins, // place this many pins... IPin **ppPins, // ...in this array ULONG *pcFetched) // actual count passed returned here { CheckPointer(ppPins,E_POINTER); ValidateReadWritePtr(ppPins,cPins * sizeof(IPin *)); ASSERT(ppPins); if (pcFetched!=NULL) { ValidateWritePtr(pcFetched, sizeof(ULONG)); *pcFetched = 0; // default unless we succeed } // now check that the parameter is valid else if (cPins>1) { // pcFetched == NULL return E_INVALIDARG; } ULONG cFetched = 0; // increment as we get each one. /* Check we are still in sync with the filter */ if (AreWeOutOfSync() == TRUE) { // If we are out of sync, we should refresh the enumerator. // This will reset the position and update the other members, but // will not clear cache of pins we have already returned. Refresh(); } /* Calculate the number of available pins */ int cRealPins = min(m_PinCount - m_Position, (int) cPins); if (cRealPins == 0) { return S_FALSE; } /* Return each pin interface NOTE GetPin returns CBasePin * not addrefed so we must QI for the IPin (which increments its reference count) If while we are retrieving a pin from the filter an error occurs we assume that our internal state is stale with respect to the filter (for example someone has deleted a pin) so we return VFW_E_ENUM_OUT_OF_SYNC */ while (cRealPins && (m_PinCount - m_Position)) { /* Get the next pin object from the filter */ CBasePin *pPin = m_pFilter->GetPin(m_Position++); if (pPin == NULL) { // If this happend, and it's not the first time through, then we've got a problem, // since we should really go back and release the iPins, which we have previously // AddRef'ed. ASSERT( cFetched==0 ); return VFW_E_ENUM_OUT_OF_SYNC; } /* We only want to return this pin, if it is not in our cache */ if (0 == m_PinCache.Find(pPin)) { /* From the object get an IPin interface */ *ppPins = pPin; pPin->AddRef(); cFetched++; ppPins++; m_PinCache.AddTail(pPin); cRealPins--; } } if (pcFetched!=NULL) { *pcFetched = cFetched; } return (cPins==cFetched ? NOERROR : S_FALSE); }