- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# BaseSource.cpp

    00001 /*
    00002  *      Copyright (C) 2003-2005 Gabest
    00003  *      http://www.gabest.org
    00004  *
    00005  *  This Program is free software; you can redistribute it and/or modify
    00006  *  it under the terms of the GNU General Public License as published by
    00007  *  the Free Software Foundation; either version 2, or (at your option)
    00008  *  any later version.
    00009  *
    00010  *  This Program is distributed in the hope that it will be useful,
    00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    00013  *  GNU General Public License for more details.
    00014  *
    00015  *  You should have received a copy of the GNU General Public License
    00016  *  along with GNU Make; see the file COPYING.  If not, write to
    00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
    00018  *  http://www.gnu.org/copyleft/gpl.html
    00019  *
    00020  */
    00021
    00022 #include "stdafx.h"
    00023 #include "BaseSource.h"
    00024 #include "..\..\..\DSUtil\DSUtil.h"
    00025
    00026 //
    00027 // CBaseSource
    00028 //
    00029
    00030 //
    00031 // CBaseStream
    00032 //
    00033
    00034 CBaseStream::CBaseStream(TCHAR* name, CSource* pParent, HRESULT* phr)
    00035         : CSourceStream(name, phr, pParent, L"Output")
    00036         , CSourceSeeking(name, (IPin*)this, phr, &m_cSharedState)
    00037         , m_bDiscontinuity(FALSE), m_bFlushing(FALSE)
    00038 {
    00039         CAutoLock cAutoLock(&m_cSharedState);
    00040
    00041         m_AvgTimePerFrame = 0;
    00042         m_rtDuration = 0;
    00043         m_rtStop = m_rtDuration;
    00044 }
    00045
    00046 CBaseStream::~CBaseStream()
    00047 {
    00048         CAutoLock cAutoLock(&m_cSharedState);
    00049 }
    00050
    00051 STDMETHODIMP CBaseStream::NonDelegatingQueryInterface(REFIID riid, void** ppv)
    00052 {
    00053     CheckPointer(ppv, E_POINTER);
    00054
    00055         return (riid == IID_IMediaSeeking) ? CSourceSeeking::NonDelegatingQueryInterface(riid, ppv)
    00056                 : CSourceStream::NonDelegatingQueryInterface(riid, ppv);
    00057 }
    00058
    00059 void CBaseStream::UpdateFromSeek()
    00060 {
    00061         if(ThreadExists())
    00062         {
    00063                 // next time around the loop, the worker thread will
    00064                 // pick up the position change.
    00065                 // We need to flush all the existing data - we must do that here
    00066                 // as our thread will probably be blocked in GetBuffer otherwise
    00067
    00068                 m_bFlushing = TRUE;
    00069
    00070                 DeliverBeginFlush();
    00071                 // make sure we have stopped pushing
    00072                 Stop();
    00073                 // complete the flush
    00074                 DeliverEndFlush();
    00075
    00076         m_bFlushing = FALSE;
    00077
    00078                 // restart
    00079                 Run();
    00080         }
    00081 }
    00082
    00083 HRESULT CBaseStream::SetRate(double dRate)
    00084 {
    00085         if(dRate <= 0)
    00086                 return E_INVALIDARG;
    00087
    00088         {
    00089                 CAutoLock lock(CSourceSeeking::m_pLock);
    00090                 m_dRateSeeking = dRate;
    00091         }
    00092
    00093         UpdateFromSeek();
    00094
    00095         return S_OK;
    00096 }
    00097
    00098 HRESULT CBaseStream::OnThreadStartPlay()
    00099 {
    00100     m_bDiscontinuity = TRUE;
    00101     return DeliverNewSegment(m_rtStart, m_rtStop, m_dRateSeeking);
    00102 }
    00103
    00104 HRESULT CBaseStream::ChangeStart()
    00105 {
    00106     {
    00107         CAutoLock lock(CSourceSeeking::m_pLock);
    00108                 m_rtSampleTime = 0;
    00109                 m_rtPosition = m_rtStart;
    00110     }
    00111
    00112     UpdateFromSeek();
    00113
    00114     return S_OK;
    00115 }
    00116
    00117 HRESULT CBaseStream::ChangeStop()
    00118 {
    00119     {
    00120         CAutoLock lock(CSourceSeeking::m_pLock);
    00121         if(m_rtPosition < m_rtStop)
    00122                         return S_OK;
    00123     }
    00124
    00125     // We're already past the new stop time -- better flush the graph.
    00126     UpdateFromSeek();
    00127
    00128     return S_OK;
    00129 }
    00130
    00131 HRESULT CBaseStream::OnThreadCreate()
    00132 {
    00133     CAutoLock cAutoLockShared(&m_cSharedState);
    00134
    00135     m_rtSampleTime = 0;
    00136     m_rtPosition = m_rtStart;
    00137
    00138     return CSourceStream::OnThreadCreate();
    00139 }
    00140
    00141 HRESULT CBaseStream::FillBuffer(IMediaSample* pSample)
    00142 {
    00143         HRESULT hr;
    00144
    00145         {
    00146                 CAutoLock cAutoLockShared(&m_cSharedState);
    00147
    00148         if(m_rtPosition >= m_rtStop)
    00149                         return S_FALSE;
    00150
    00151                 BYTE* pOut = NULL;
    00152                 if(FAILED(hr = pSample->GetPointer(&pOut)) || !pOut)
    00153                         return S_FALSE;
    00154
    00155                 int nFrame = m_rtPosition / m_AvgTimePerFrame; // (int)(1.0 * m_rtPosition / m_AvgTimePerFrame + 0.5);
    00156
    00157                 long len = pSample->GetSize();
    00158
    00159                 hr = FillBuffer(pSample, nFrame, pOut, len);
    00160                 if(hr != S_OK) return hr;
    00161
    00162                 pSample->SetActualDataLength(len);
    00163
    00164                 REFERENCE_TIME rtStart, rtStop;
    00165         // The sample times are modified by the current rate.
    00166         rtStart = static_cast<REFERENCE_TIME>(m_rtSampleTime / m_dRateSeeking);
    00167         rtStop  = rtStart + static_cast<int>(m_AvgTimePerFrame / m_dRateSeeking);
    00168                 pSample->SetTime(&rtStart, &rtStop);
    00169
    00170         m_rtSampleTime += m_AvgTimePerFrame;
    00171         m_rtPosition += m_AvgTimePerFrame;
    00172         }
    00173
    00174         pSample->SetSyncPoint(TRUE);
    00175
    00176         if(m_bDiscontinuity)
    00177     {
    00178                 pSample->SetDiscontinuity(TRUE);
    00179                 m_bDiscontinuity = FALSE;
    00180         }
    00181
    00182         return S_OK;
    00183 }
    00184
    00185 STDMETHODIMP CBaseStream::Notify(IBaseFilter* pSender, Quality q)
    00186 {
    00187         return E_NOTIMPL;
    00188 }