/*
* (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;
}