/* * (C) 2003-2006 Gabest * (C) 2006-2014 see Authors.txt * * This file is part of MPC-HC. * * MPC-HC is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * MPC-HC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "stdafx.h" #include "BaseSource.h" #include "../../../DSUtil/DSUtil.h" // // CBaseSource // // // CBaseStream // CBaseStream::CBaseStream(TCHAR* name, CSource* pParent, HRESULT* phr) : CSourceStream(name, phr, pParent, L"Output") , CSourceSeeking(name, (IPin*)this, phr, &m_cSharedState) , m_AvgTimePerFrame(0) , m_rtSampleTime(0) , m_rtPosition(0) , m_bDiscontinuity(FALSE) , m_bFlushing(FALSE) { CAutoLock cAutoLock(&m_cSharedState); m_rtDuration = m_rtStop = 0; } CBaseStream::~CBaseStream() { CAutoLock cAutoLock(&m_cSharedState); } STDMETHODIMP CBaseStream::NonDelegatingQueryInterface(REFIID riid, void** ppv) { CheckPointer(ppv, E_POINTER); return (riid == IID_IMediaSeeking) ? CSourceSeeking::NonDelegatingQueryInterface(riid, ppv) : CSourceStream::NonDelegatingQueryInterface(riid, ppv); } void CBaseStream::UpdateFromSeek() { if (ThreadExists()) { // next time around the loop, the worker thread will // pick up the position change. // We need to flush all the existing data - we must do that here // as our thread will probably be blocked in GetBuffer otherwise m_bFlushing = TRUE; DeliverBeginFlush(); // make sure we have stopped pushing Stop(); // complete the flush DeliverEndFlush(); m_bFlushing = FALSE; // restart Run(); } } HRESULT CBaseStream::SetRate(double dRate) { if (dRate <= 0) { return E_INVALIDARG; } { CAutoLock lock(CSourceSeeking::m_pLock); m_dRateSeeking = dRate; } UpdateFromSeek(); return S_OK; } HRESULT CBaseStream::OnThreadStartPlay() { m_bDiscontinuity = TRUE; return DeliverNewSegment(m_rtStart, m_rtStop, m_dRateSeeking); } HRESULT CBaseStream::ChangeStart() { { CAutoLock lock(CSourceSeeking::m_pLock); m_rtSampleTime = 0; m_rtPosition = m_rtStart; } UpdateFromSeek(); return S_OK; } HRESULT CBaseStream::ChangeStop() { { CAutoLock lock(CSourceSeeking::m_pLock); if (m_rtPosition < m_rtStop) { return S_OK; } } // We're already past the new stop time -- better flush the graph. UpdateFromSeek(); return S_OK; } HRESULT CBaseStream::OnThreadCreate() { CAutoLock cAutoLockShared(&m_cSharedState); m_rtSampleTime = 0; m_rtPosition = m_rtStart; return CSourceStream::OnThreadCreate(); } HRESULT CBaseStream::FillBuffer(IMediaSample* pSample) { { HRESULT hr; CAutoLock cAutoLockShared(&m_cSharedState); if (m_rtPosition >= m_rtStop) { return S_FALSE; } BYTE* pOut = nullptr; if (FAILED(hr = pSample->GetPointer(&pOut)) || !pOut) { return S_FALSE; } int nFrame = (int)(m_rtPosition / m_AvgTimePerFrame); long len = pSample->GetSize(); hr = FillBuffer(pSample, nFrame, pOut, len); if (hr != S_OK) { return hr; } pSample->SetActualDataLength(len); REFERENCE_TIME rtStart, rtStop; // The sample times are modified by the current rate. rtStart = static_cast(m_rtSampleTime / m_dRateSeeking); rtStop = rtStart + static_cast(m_AvgTimePerFrame / m_dRateSeeking); pSample->SetTime(&rtStart, &rtStop); m_rtSampleTime += m_AvgTimePerFrame; m_rtPosition += m_AvgTimePerFrame; } pSample->SetSyncPoint(TRUE); if (m_bDiscontinuity) { pSample->SetDiscontinuity(TRUE); m_bDiscontinuity = FALSE; } return S_OK; } STDMETHODIMP CBaseStream::Notify(IBaseFilter* pSender, Quality q) { return E_NOTIMPL; }