// // FindSubtitleFilter // // be careful with this method, can cause deadlock with CSync::Stop, so should only be called in Run() HRESULT CTsReaderFilter::FindSubtitleFilter() { if( m_pDVBSubtitle ) { return S_OK; } //LogDebug( "FindSubtitleFilter - start"); IEnumFilters * piEnumFilters = NULL; if (GetFilterGraph() && SUCCEEDED(GetFilterGraph()->EnumFilters(&piEnumFilters))) { IBaseFilter * pFilter; while (piEnumFilters->Next(1, &pFilter, 0) == NOERROR ) { FILTER_INFO filterInfo; if (pFilter->QueryFilterInfo(&filterInfo) == S_OK) { if (!wcsicmp(L"MediaPortal DVBSub2", filterInfo.achName)) { HRESULT fhr = pFilter->QueryInterface( IID_IDVBSubtitle2, ( void**)&m_pDVBSubtitle ); assert( fhr == S_OK); //LogDebug("Testing that DVBSub2 works"); m_pDVBSubtitle->Test(1); } filterInfo.pGraph->Release(); } pFilter->Release(); pFilter = NULL; } piEnumFilters->Release(); } //LogDebug( "FindSubtitleFilter - End"); return S_OK; }
HRESULT CBDReaderFilter::FindSubtitleFilter() { if (m_pDVBSubtitle) return S_OK; HRESULT hr = S_FALSE; ULONG fetched = 0; IEnumFilters * piEnumFilters = NULL; if (GetFilterGraph() && SUCCEEDED(GetFilterGraph()->EnumFilters(&piEnumFilters))) { IBaseFilter * pFilter; while (piEnumFilters->Next(1, &pFilter, &fetched) == NOERROR) { FILTER_INFO filterInfo; if (pFilter->QueryFilterInfo(&filterInfo) == S_OK) { if (!wcsicmp(L"MediaPortal DVBSub3", filterInfo.achName)) hr = pFilter->QueryInterface(IID_IDVBSubtitle3, (void**)&m_pDVBSubtitle); filterInfo.pGraph->Release(); } pFilter->Release(); pFilter = NULL; } piEnumFilters->Release(); } return hr; }
HRESULT CWavPackDSSplitter::CleanupOnInputBreakConnect() { HRESULT hr = S_OK; DebugLog("CWavPackDSSplitter::CleanupOnInputBreakConnect... 0x%08X", GetCurrentThreadId()); IFilterGraph* pFG = GetFilterGraph(); if(m_pInputPinCorr != NULL) { if(m_pInputPinCorr->IsConnected()) { m_pInputPinCorr->GetConnected()->Disconnect(); m_pInputPinCorr->Disconnect(); } } if(m_pOutputPin != NULL) { if(m_pOutputPin->IsConnected()) { m_pOutputPin->GetConnected()->Disconnect(); m_pOutputPin->Disconnect(); } } m_bDontTryToLoadCorrectionFileAgain = FALSE; return hr; }
extern "C" int WINAPI pos(HWND,HWND,char *data,char*,BOOL,BOOL) { CComPtr<IFilterGraph> pFG; if(!GetFilterGraph(&pFG)) return 1; CComQIPtr<IMediaSeeking> pMS = pFG; REFERENCE_TIME pos, dur; if(FAILED(pMS->GetCurrentPosition(&pos)) || FAILED(pMS->GetDuration(&dur))) return 1; if(dur > 10000000i64*60*60) { sprintf(data, _T("%02d:%02d:%02d/%02d:%02d:%02d"), (int)(pos/10000000/60/60), (int)(pos/10000000/60)%60, (int)(pos/10000000)%60, (int)(dur/10000000/60/60), (int)(dur/10000000/60)%60, (int)(dur/10000000)%60); } else { sprintf(data, _T("%02d:%02d/%02d:%02d"), (int)(pos/10000000/60)%60, (int)(pos/10000000)%60, (int)(dur/10000000/60)%60, (int)(dur/10000000)%60); } return 3; }
// // Run // STDMETHODIMP CDVBSub::Run( REFERENCE_TIME tStart ) { CAutoLock cObjectLock( m_pLock ); LogDebug( "CDVBSub::Run" ); m_startTimestamp = tStart; HRESULT hr = CBaseFilter::Run( tStart ); if( hr != S_OK ) { LogDebug( "CDVBSub::Run - BaseFilter returned %i", hr ); return hr; } // Get media seeking interface if missing if( !m_pIMediaSeeking ) { IFilterGraph *pGraph = GetFilterGraph(); if( pGraph ) { pGraph->QueryInterface( &m_pIMediaSeeking ); pGraph->Release(); } } LogDebug( "CDVBSub::Run - done" ); return hr; }
extern "C" int WINAPI running(HWND,HWND,char *data,char*,BOOL,BOOL) { sprintf(data, _T("2")); CComPtr<IFilterGraph> pFG; CComQIPtr<IMediaControl> pMC; OAFilterState fs; if(!GetFilterGraph(&pFG) || !(pMC = pFG) || FAILED(pMC->GetState(0, &fs))) return 3; sprintf(data, _T("%d"), fs == State_Running ? 1 : 0); return 3; }
void CTsReaderFilter::SetMediaPosition(REFERENCE_TIME MediaPos) { { CAutoLock cObjectLock(&m_GetTimeLock); m_MediaPos = MediaPos ; m_BaseTime = (REFERENCE_TIME)GetTickCount() * 10000 ; // m_pClock->GetTime(&m_BaseTime) ; m_LastTime=m_BaseTime ; } // LogDebug("SetMediaPos : %f %f",(float)MediaPos/10000,(float)m_LastTime/10000) ; // This is not really the right place, but this is the only method called by "MPmain" that could allow // TsReader to "Pause" itself without deadlock issue. // This is also here to allow compatibility with previous releases, avoiding a new callback from MP. if (m_bRenderingClockTooFast) { if (m_bPauseOnClockTooFast) return ; // Do not re-enter ! if (GetCurrentThreadId()!=m_MPmainThreadID) return ; // Only MPmain can do that ! if (((m_MediaPos/10000)-m_absSeekTime.Millisecs()) < 30*1000) { return ; } m_bPauseOnClockTooFast=true ; if (State() == State_Running) { IMediaControl * ptrMediaCtrl; if (SUCCEEDED(GetFilterGraph()->QueryInterface(IID_IMediaControl, (void**)&ptrMediaCtrl))) { LogDebug("Pause 200mS renderer clock to match provider/RTSP clock...") ; ptrMediaCtrl->Pause() ; Sleep(200) ; // m_TestTime = GetTickCount() ; ptrMediaCtrl->Run() ; m_bRenderingClockTooFast=false ; } else LogDebug("Pause failed...") ; } m_bPauseOnClockTooFast=false ; } }
extern "C" int WINAPI file(HWND,HWND,char *data,char*,BOOL,BOOL) { CComPtr<IFilterGraph> pFG; if(!GetFilterGraph(&pFG)) return 1; CString fn; CComPtr<IEnumFilters> pEF; if(FAILED(pFG->EnumFilters(&pEF))) return 1; ULONG cFetched = 0; for(CComPtr<IBaseFilter> pBF; S_OK == pEF->Next(1, &pBF, &cFetched); pBF = NULL) { if(CComQIPtr<IFileSourceFilter> pFSF = pBF) { LPOLESTR pFileName = NULL; AM_MEDIA_TYPE mt; if(FAILED(pFSF->GetCurFile(&pFileName, &mt))) continue; fn = CStringW(pFileName); CoTaskMemFree(pFileName); FreeMediaType(mt); break; } } if(fn.IsEmpty()) return 1; sprintf(data, _T("%s"), fn); return 3; }
HRESULT CWavPackDSSplitter::TryToLoadCorrectionFile() { // Here is the nasty hacky stuff :> HRESULT hr = S_FALSE; IPin *pPinOutSrc = NULL; IFileSourceFilter *pFSF = NULL; LPOLESTR pszFileName = NULL; IBaseFilter* pSrcFilterCorr = NULL; IFileSourceFilter* pFSFCorr = NULL; IEnumPins *pEnum = NULL; IPin *pPinNew = NULL; BOOL bCorrectionFileLoaded = FALSE; IEnumFilters* pEnumFilers = NULL; BOOL bSrcFileAlreadyLoaded = FALSE; DebugLog("===> Entering CWavPackDSSplitter::TryToLoadCorrectionFile... 0x%08X", GetCurrentThreadId()); if((m_bDontTryToLoadCorrectionFileAgain == TRUE) || (m_pInputPinCorr == NULL) || (m_pInputPinCorr->IsConnected() == TRUE)) { DebugLog("<=== Leaving CWavPackDSSplitter::TryToLoadCorrectionFile already loaded ?... 0x%08X", GetCurrentThreadId()); return hr; } if((m_pInputPin->m_pWavPackParser->first_wphdr.flags & HYBRID_FLAG) != HYBRID_FLAG) { // Not an hybrid file, don't even try m_bDontTryToLoadCorrectionFileAgain = TRUE; DebugLog("<=== Leaving CWavPackDSSplitter::TryToLoadCorrectionFile not hybrid... 0x%08X", GetCurrentThreadId()); return hr; } #define IF_FAIL_BREAK(x) if(FAILED(x)) { break; } do { hr = m_pInputPin->ConnectedTo(&pPinOutSrc); IF_FAIL_BREAK(hr); // Get a pointer on the source filter PIN_INFO pi; pi.pFilter = NULL; hr = pPinOutSrc->QueryPinInfo(&pi); IF_FAIL_BREAK(hr); // Get source filter IFileSourceFilter interface hr = pi.pFilter->QueryInterface(IID_IFileSourceFilter, (void **)&pFSF); IF_FAIL_BREAK(hr); // Get filename hr = pFSF->GetCurFile(&pszFileName, NULL); IF_FAIL_BREAK(hr); // Create correction file filename WCHAR pszFileNameC[MAX_PATH]; ZeroMemory(pszFileNameC, sizeof(WCHAR)*MAX_PATH); int cch = lstrlenW(pszFileName); CopyMemory(pszFileNameC, pszFileName, cch*sizeof(WCHAR)); pszFileNameC[cch] = 'c'; IFilterGraph* pFG = GetFilterGraph(); // Search in the graph in case the source filter with correction file already exist hr = pFG->EnumFilters(&pEnumFilers); IF_FAIL_BREAK(hr); while(pEnumFilers->Next(1, &pSrcFilterCorr, 0) == S_OK) { HRESULT lhr; lhr = pSrcFilterCorr->QueryInterface(IID_IFileSourceFilter, (void**)&pFSFCorr); if(SUCCEEDED(lhr)) { LPOLESTR pszFileNameCandidate = NULL; pFSFCorr->GetCurFile(&pszFileNameCandidate, NULL); if(memcmp(pszFileNameCandidate,pszFileNameC,(cch+1)*sizeof(WCHAR)) == 0) { // This is the good file bSrcFileAlreadyLoaded = TRUE; if(pszFileNameCandidate != NULL) { CoTaskMemFree(pszFileNameCandidate); } break; } if(pszFileNameCandidate != NULL) { CoTaskMemFree(pszFileNameCandidate); } } pSrcFilterCorr->Release(); pSrcFilterCorr = NULL; } if(bSrcFileAlreadyLoaded == FALSE) { // Create new file source filter hr = CoCreateInstance(CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pSrcFilterCorr); IF_FAIL_BREAK(hr); hr = pFG->AddFilter(pSrcFilterCorr, pszFileNameC); IF_FAIL_BREAK(hr); hr = pSrcFilterCorr->QueryInterface(IID_IFileSourceFilter, (void**)&pFSFCorr); IF_FAIL_BREAK(hr); hr = pFSFCorr->Load(pszFileNameC, NULL); IF_FAIL_BREAK(hr); } // Get first pin and connect it hr = pSrcFilterCorr->EnumPins(&pEnum); IF_FAIL_BREAK(hr); if(pEnum->Next(1, &pPinNew, 0) == S_OK) { hr = pFG->ConnectDirect(pPinNew, m_pInputPinCorr, NULL); bCorrectionFileLoaded = SUCCEEDED(hr); } } while(0); if((bCorrectionFileLoaded == FALSE) && (pSrcFilterCorr != NULL)) { IFilterGraph* pFG = GetFilterGraph(); pFG->RemoveFilter(pSrcFilterCorr); } // Cleanup SAFE_RELEASE(pPinNew); SAFE_RELEASE(pEnum); SAFE_RELEASE(pEnumFilers); SAFE_RELEASE(pFSFCorr); SAFE_RELEASE(pSrcFilterCorr); if(pszFileName != NULL) { CoTaskMemFree(pszFileName); } SAFE_RELEASE(pFSF); SAFE_RELEASE(pPinOutSrc); #undef IF_FAIL_BREAK m_bDontTryToLoadCorrectionFileAgain = bCorrectionFileLoaded; if(bCorrectionFileLoaded) { DebugLog("<=== Leaving TryToLoadCorrectionFile successfull 0x%08X", GetCurrentThreadId()); } else { DebugLog("<=== Leaving TryToLoadCorrectionFile FAILED 0x%08X", GetCurrentThreadId()); } return hr; }
STDMETHODIMP CTsReaderFilter::Pause() { //m_ShowBufferVideo = INIT_SHOWBUFFERVIDEO; //m_ShowBufferAudio = INIT_SHOWBUFFERAUDIO; LogDebug("CTsReaderFilter::Pause() - IsTimeShifting = %d - state = %d", IsTimeShifting(), m_State); CAutoLock cObjectLock(m_pLock); if (m_State == State_Running) { m_lastPause = GetTickCount(); m_RandomCompensation = 0; } //pause filter HRESULT hr=CSource::Pause(); if (!m_bPauseOnClockTooFast) { //are we using rtsp? if (m_fileDuration==NULL) { //yes, are we busy seeking? if (!IsSeeking()) { //not seeking, is rtsp streaming at the moment? if (!m_rtspClient.IsRunning()) { //not streaming atm double startTime=m_seekTime.Millisecs(); startTime/=1000.0; long Old_rtspDuration = m_rtspClient.Duration() ; //clear buffers LogDebug(" -- Pause() ->start rtsp from %f", startTime); m_buffer.Clear(); m_demultiplexer.Flush(); //start streaming m_buffer.Run(true); m_rtspClient.Play(startTime,0.0); // m_tickCount = GetTickCount(); LogDebug(" -- Pause() ->rtsp started"); //update the duration of the stream CPcr pcrStart, pcrEnd, pcrMax ; double duration = m_rtspClient.Duration() / 1000.0f ; if (m_bTimeShifting) { // EndPcr is continuously increasing ( until ~26 hours for rollover that will fail ! ) // So, we refer duration to End, and just update start. pcrEnd = m_duration.EndPcr() ; double start = pcrEnd.ToClock() - duration; if (start<0) start=0 ; pcrStart.FromClock(start) ; m_duration.Set( pcrStart, pcrEnd, pcrMax) ; // Pause()-RTSP } else { // It's a record, eventually end can increase if recording is in progress, let the end virtually updated by ThreadProc() //m_bRecording = (Old_rtspDuration != m_rtspClient.Duration()) ; m_bRecording = true; // duration may have not increased in such a short time } LogDebug("Timeshift %d, Recording %d, StartPCR %f, EndPcr %f, Duration %f",m_bTimeShifting,m_bRecording,m_duration.StartPcr().ToClock(),m_duration.EndPcr().ToClock(),(float)m_duration.Duration().Millisecs()/1000.0f) ; } else { //we are streaming at the moment. //query the current position, so it can resume on un-pause at this position //can be required in multiseat with rtsp when changing audio streams IMediaSeeking * ptrMediaPos; if (SUCCEEDED(GetFilterGraph()->QueryInterface(IID_IMediaSeeking, (void**)&ptrMediaPos))) { ptrMediaPos->GetCurrentPosition(&m_seekTime.m_time); ptrMediaPos->Release(); } //pause the streaming LogDebug(" -- Pause() ->pause rtsp at position: %f", (m_seekTime.Millisecs() / 1000.0f)); m_rtspClient.Pause(); } } else //we are seeking { IMediaSeeking * ptrMediaPos; if (SUCCEEDED(GetFilterGraph()->QueryInterface(IID_IMediaSeeking, (void**)&ptrMediaPos))) { LONGLONG currentPos; ptrMediaPos->GetCurrentPosition(¤tPos); ptrMediaPos->Release(); double clock = currentPos;clock /= 10000000.0; float clockEnd = m_duration.EndPcr().ToClock() ; if (clock >= clockEnd && clockEnd > 0 ) { LogDebug("End of rtsp stream..."); m_demultiplexer.SetEndOfFile(true); } } } } m_demultiplexer.m_LastDataFromRtsp = GetTickCount() ; } //is the duration update thread running? if (!IsThreadRunning()) { //nop? then start it //LogDebug(" CTsReaderFilter::Pause()->start duration thread"); StartThread(); } LogDebug("CTsReaderFilter::Pause() - END - state = %d", m_State); return hr; }
DWORD WINAPI CBDReaderFilter::CommandThread() { SetThreadName(-1, "BDReader_COMMAND"); IFilterGraph* pGraph = NULL; pGraph = GetFilterGraph(); if (pGraph) { pGraph->QueryInterface(&m_pMediaSeeking); pGraph->Release(); } HANDLE handles[2]; handles[0] = m_hStopCommandThreadEvent; handles[1] = m_hCommandEvent; if (m_pMediaSeeking) { while(1) { //DWORD result = WaitForMultipleObjects(2, handles, false, 40); DWORD result = WaitForMultipleObjects(2, handles, false, INFINITE); if (result == WAIT_OBJECT_0) // exit event { LogDebug("CBDReaderFilter::Command thread: closing down"); return 0; } /* else if (result == WAIT_TIMEOUT) { LONGLONG pos = 0; HRESULT hr = m_pMediaSeeking->GetCurrentPosition(&pos); if (SUCCEEDED(hr)) { lib.ProvideUserInput(CONVERT_DS_90KHz(pos), BD_VK_NONE); } } */ else if (result == WAIT_OBJECT_0 + 1) // command in queue { LONGLONG posEnd = 0; LONGLONG zeroPos = 0; m_pMediaSeeking->GetDuration(&posEnd); ivecCommandQueue it; DS_CMD cmd; { // just fetch the command and release the lock CAutoLock lock(&m_csCommandQueue); it = m_commandQueue.begin(); cmd = (*it); m_commandQueue.erase(it); if (m_commandQueue.empty()) { ResetEvent(m_hCommandEvent); } } switch (cmd.id) { case REBUILD: { LogDebug("CBDReaderFilter::Command thread: issue rebuild!"); LONGLONG pos = 0; if (cmd.refTime.m_time < 0) { CAutoLock lock(&m_csClock); pos = m_rtCurrentTime; } else pos = cmd.refTime.m_time; m_eRebuild.Reset(); TriggerOnMediaChanged(); m_eRebuild.Wait(); if (m_bRebuildOngoing) { LogDebug("CBDReaderFilter::Command thread: graph rebuild has failed?"); return 0; } m_bUpdateStreamPositionOnly = true; LogDebug("CBDReaderFilter::Command thread: seek - pos: %06.3f (rebuild)", cmd.refTime.Millisecs() / 1000.0); m_pMediaSeeking->SetPositions(&pos, AM_SEEKING_AbsolutePositioning | AM_SEEKING_FakeSeek, &posEnd, AM_SEEKING_NoPositioning); m_eSeekDone.Wait(); m_eSeekDone.Reset(); m_demultiplexer.SetMediaChanging(false); m_demultiplexer.m_bRebuildOngoing = false; break; } case SEEK: m_bUpdateStreamPositionOnly = true; LogDebug("CBDReaderFilter::Command thread: seek requested - pos: %06.3f", cmd.refTime.Millisecs() / 1000.0); HRESULT hr = m_pMediaSeeking->SetPositions((LONGLONG*)&cmd.refTime.m_time, AM_SEEKING_AbsolutePositioning | AM_SEEKING_FakeSeek, &posEnd, AM_SEEKING_NoPositioning); m_eSeekDone.Wait(); m_eSeekDone.Reset(); break; } } else { DWORD error = GetLastError(); LogDebug("CBDReaderFilter::Command thread: WaitForMultipleObjects failed: %d", error); } } } return 0; }