forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			589 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			589 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
								 | 
							
								//------------------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								// File: PullPin.cpp
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Desc: DirectShow base classes - implements CPullPin class that pulls data
							 | 
						||
| 
								 | 
							
								//       from IAsyncReader.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
							 | 
						||
| 
								 | 
							
								//------------------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <streams.h>
							 | 
						||
| 
								 | 
							
								#include "pullpin.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef DXMPERF
							 | 
						||
| 
								 | 
							
								#include "dxmperf.h"
							 | 
						||
| 
								 | 
							
								#endif // DXMPERF
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								CPullPin::CPullPin()
							 | 
						||
| 
								 | 
							
								  : m_pReader(NULL),
							 | 
						||
| 
								 | 
							
								    m_pAlloc(NULL),
							 | 
						||
| 
								 | 
							
								    m_State(TM_Exit)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								#ifdef DXMPERF
							 | 
						||
| 
								 | 
							
									PERFLOG_CTOR( L"CPullPin", this );
							 | 
						||
| 
								 | 
							
								#endif // DXMPERF
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								CPullPin::~CPullPin()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    Disconnect();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef DXMPERF
							 | 
						||
| 
								 | 
							
									PERFLOG_DTOR( L"CPullPin", this );
							 | 
						||
| 
								 | 
							
								#endif // DXMPERF
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// returns S_OK if successfully connected to an IAsyncReader interface
							 | 
						||
| 
								 | 
							
								// from this object
							 | 
						||
| 
								 | 
							
								// Optional allocator should be proposed as a preferred allocator if
							 | 
						||
| 
								 | 
							
								// necessary
							 | 
						||
| 
								 | 
							
								HRESULT
							 | 
						||
| 
								 | 
							
								CPullPin::Connect(IUnknown* pUnk, IMemAllocator* pAlloc, BOOL bSync)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    CAutoLock lock(&m_AccessLock);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (m_pReader) {
							 | 
						||
| 
								 | 
							
									return VFW_E_ALREADY_CONNECTED;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    HRESULT hr = pUnk->QueryInterface(IID_IAsyncReader, (void**)&m_pReader);
							 | 
						||
| 
								 | 
							
								    if (FAILED(hr)) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef DXMPERF
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
										AM_MEDIA_TYPE *	pmt = NULL;
							 | 
						||
| 
								 | 
							
										PERFLOG_CONNECT( this, pUnk, hr, pmt );
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								#endif // DXMPERF
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return(hr);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    hr = DecideAllocator(pAlloc, NULL);
							 | 
						||
| 
								 | 
							
								    if (FAILED(hr)) {
							 | 
						||
| 
								 | 
							
									Disconnect();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef DXMPERF
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
										AM_MEDIA_TYPE *	pmt = NULL;
							 | 
						||
| 
								 | 
							
										PERFLOG_CONNECT( this, pUnk, hr, pmt );
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								#endif // DXMPERF
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return hr;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    LONGLONG llTotal, llAvail;
							 | 
						||
| 
								 | 
							
								    hr = m_pReader->Length(&llTotal, &llAvail);
							 | 
						||
| 
								 | 
							
								    if (FAILED(hr)) {
							 | 
						||
| 
								 | 
							
									Disconnect();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef DXMPERF
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
										AM_MEDIA_TYPE *	pmt = NULL;
							 | 
						||
| 
								 | 
							
										PERFLOG_CONNECT( this, pUnk, hr, pmt );
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return hr;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // convert from file position to reference time
							 | 
						||
| 
								 | 
							
								    m_tDuration = llTotal * UNITS;
							 | 
						||
| 
								 | 
							
								    m_tStop = m_tDuration;
							 | 
						||
| 
								 | 
							
								    m_tStart = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    m_bSync = bSync;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef DXMPERF
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
									AM_MEDIA_TYPE *	pmt = NULL;
							 | 
						||
| 
								 | 
							
									PERFLOG_CONNECT( this, pUnk, S_OK, pmt );
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								#endif // DXMPERF
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return S_OK;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// disconnect any connection made in Connect
							 | 
						||
| 
								 | 
							
								HRESULT
							 | 
						||
| 
								 | 
							
								CPullPin::Disconnect()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    CAutoLock lock(&m_AccessLock);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    StopThread();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef DXMPERF
							 | 
						||
| 
								 | 
							
									PERFLOG_DISCONNECT( this, m_pReader, S_OK );
							 | 
						||
| 
								 | 
							
								#endif // DXMPERF
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (m_pReader) {
							 | 
						||
| 
								 | 
							
									m_pReader->Release();
							 | 
						||
| 
								 | 
							
									m_pReader = NULL;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (m_pAlloc) {
							 | 
						||
| 
								 | 
							
									m_pAlloc->Release();
							 | 
						||
| 
								 | 
							
									m_pAlloc = NULL;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return S_OK;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// agree an allocator using RequestAllocator - optional
							 | 
						||
| 
								 | 
							
								// props param specifies your requirements (non-zero fields).
							 | 
						||
| 
								 | 
							
								// returns an error code if fail to match requirements.
							 | 
						||
| 
								 | 
							
								// optional IMemAllocator interface is offered as a preferred allocator
							 | 
						||
| 
								 | 
							
								// but no error occurs if it can't be met.
							 | 
						||
| 
								 | 
							
								HRESULT
							 | 
						||
| 
								 | 
							
								CPullPin::DecideAllocator(
							 | 
						||
| 
								 | 
							
								    IMemAllocator * pAlloc,
							 | 
						||
| 
								 | 
							
								    __inout_opt ALLOCATOR_PROPERTIES * pProps)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    ALLOCATOR_PROPERTIES *pRequest;
							 | 
						||
| 
								 | 
							
								    ALLOCATOR_PROPERTIES Request;
							 | 
						||
| 
								 | 
							
								    if (pProps == NULL) {
							 | 
						||
| 
								 | 
							
									Request.cBuffers = 3;
							 | 
						||
| 
								 | 
							
									Request.cbBuffer = 64*1024;
							 | 
						||
| 
								 | 
							
									Request.cbAlign = 0;
							 | 
						||
| 
								 | 
							
									Request.cbPrefix = 0;
							 | 
						||
| 
								 | 
							
									pRequest = &Request;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
									pRequest = pProps;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    HRESULT hr = m_pReader->RequestAllocator(
							 | 
						||
| 
								 | 
							
										    pAlloc,
							 | 
						||
| 
								 | 
							
										    pRequest,
							 | 
						||
| 
								 | 
							
										    &m_pAlloc);
							 | 
						||
| 
								 | 
							
								    return hr;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// start pulling data
							 | 
						||
| 
								 | 
							
								HRESULT
							 | 
						||
| 
								 | 
							
								CPullPin::Active(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    ASSERT(!ThreadExists());
							 | 
						||
| 
								 | 
							
								    return StartThread();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// stop pulling data
							 | 
						||
| 
								 | 
							
								HRESULT
							 | 
						||
| 
								 | 
							
								CPullPin::Inactive(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    StopThread();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return S_OK;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								HRESULT
							 | 
						||
| 
								 | 
							
								CPullPin::Seek(REFERENCE_TIME tStart, REFERENCE_TIME tStop)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    CAutoLock lock(&m_AccessLock);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ThreadMsg AtStart = m_State;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (AtStart == TM_Start) {
							 | 
						||
| 
								 | 
							
									BeginFlush();
							 | 
						||
| 
								 | 
							
									PauseThread();
							 | 
						||
| 
								 | 
							
									EndFlush();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    m_tStart = tStart;
							 | 
						||
| 
								 | 
							
								    m_tStop = tStop;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    HRESULT hr = S_OK;
							 | 
						||
| 
								 | 
							
								    if (AtStart == TM_Start) {
							 | 
						||
| 
								 | 
							
									hr = StartThread();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return hr;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								HRESULT
							 | 
						||
| 
								 | 
							
								CPullPin::Duration(__out REFERENCE_TIME* ptDuration)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    *ptDuration = m_tDuration;
							 | 
						||
| 
								 | 
							
								    return S_OK;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								HRESULT
							 | 
						||
| 
								 | 
							
								CPullPin::StartThread()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    CAutoLock lock(&m_AccessLock);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!m_pAlloc || !m_pReader) {
							 | 
						||
| 
								 | 
							
									return E_UNEXPECTED;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    HRESULT hr;
							 | 
						||
| 
								 | 
							
								    if (!ThreadExists()) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// commit allocator
							 | 
						||
| 
								 | 
							
									hr = m_pAlloc->Commit();
							 | 
						||
| 
								 | 
							
									if (FAILED(hr)) {
							 | 
						||
| 
								 | 
							
									    return hr;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// start thread
							 | 
						||
| 
								 | 
							
									if (!Create()) {
							 | 
						||
| 
								 | 
							
									    return E_FAIL;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    m_State = TM_Start;
							 | 
						||
| 
								 | 
							
								    hr = (HRESULT) CallWorker(m_State);
							 | 
						||
| 
								 | 
							
								    return hr;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								HRESULT
							 | 
						||
| 
								 | 
							
								CPullPin::PauseThread()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    CAutoLock lock(&m_AccessLock);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!ThreadExists()) {
							 | 
						||
| 
								 | 
							
									return E_UNEXPECTED;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // need to flush to ensure the thread is not blocked
							 | 
						||
| 
								 | 
							
								    // in WaitForNext
							 | 
						||
| 
								 | 
							
								    HRESULT hr = m_pReader->BeginFlush();
							 | 
						||
| 
								 | 
							
								    if (FAILED(hr)) {
							 | 
						||
| 
								 | 
							
									return hr;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    m_State = TM_Pause;
							 | 
						||
| 
								 | 
							
								    hr = CallWorker(TM_Pause);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    m_pReader->EndFlush();
							 | 
						||
| 
								 | 
							
								    return hr;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								HRESULT
							 | 
						||
| 
								 | 
							
								CPullPin::StopThread()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    CAutoLock lock(&m_AccessLock);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!ThreadExists()) {
							 | 
						||
| 
								 | 
							
									return S_FALSE;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // need to flush to ensure the thread is not blocked
							 | 
						||
| 
								 | 
							
								    // in WaitForNext
							 | 
						||
| 
								 | 
							
								    HRESULT hr = m_pReader->BeginFlush();
							 | 
						||
| 
								 | 
							
								    if (FAILED(hr)) {
							 | 
						||
| 
								 | 
							
									return hr;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    m_State = TM_Exit;
							 | 
						||
| 
								 | 
							
								    hr = CallWorker(TM_Exit);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    m_pReader->EndFlush();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // wait for thread to completely exit
							 | 
						||
| 
								 | 
							
								    Close();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // decommit allocator
							 | 
						||
| 
								 | 
							
								    if (m_pAlloc) {
							 | 
						||
| 
								 | 
							
									m_pAlloc->Decommit();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return S_OK;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								DWORD
							 | 
						||
| 
								 | 
							
								CPullPin::ThreadProc(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    while(1) {
							 | 
						||
| 
								 | 
							
									DWORD cmd = GetRequest();
							 | 
						||
| 
								 | 
							
									switch(cmd) {
							 | 
						||
| 
								 | 
							
									case TM_Exit:
							 | 
						||
| 
								 | 
							
									    Reply(S_OK);
							 | 
						||
| 
								 | 
							
									    return 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									case TM_Pause:
							 | 
						||
| 
								 | 
							
									    // we are paused already
							 | 
						||
| 
								 | 
							
									    Reply(S_OK);
							 | 
						||
| 
								 | 
							
									    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									case TM_Start:
							 | 
						||
| 
								 | 
							
									    Reply(S_OK);
							 | 
						||
| 
								 | 
							
									    Process();
							 | 
						||
| 
								 | 
							
									    break;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// at this point, there should be no outstanding requests on the
							 | 
						||
| 
								 | 
							
									// upstream filter.
							 | 
						||
| 
								 | 
							
									// We should force begin/endflush to ensure that this is true.
							 | 
						||
| 
								 | 
							
									// !!!Note that we may currently be inside a BeginFlush/EndFlush pair
							 | 
						||
| 
								 | 
							
									// on another thread, but the premature EndFlush will do no harm now
							 | 
						||
| 
								 | 
							
									// that we are idle.
							 | 
						||
| 
								 | 
							
									m_pReader->BeginFlush();
							 | 
						||
| 
								 | 
							
									CleanupCancelled();
							 | 
						||
| 
								 | 
							
									m_pReader->EndFlush();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								HRESULT
							 | 
						||
| 
								 | 
							
								CPullPin::QueueSample(
							 | 
						||
| 
								 | 
							
								    __inout REFERENCE_TIME& tCurrent,
							 | 
						||
| 
								 | 
							
								    REFERENCE_TIME tAlignStop,
							 | 
						||
| 
								 | 
							
								    BOOL bDiscontinuity
							 | 
						||
| 
								 | 
							
								    )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    IMediaSample* pSample;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    HRESULT hr = m_pAlloc->GetBuffer(&pSample, NULL, NULL, 0);
							 | 
						||
| 
								 | 
							
								    if (FAILED(hr)) {
							 | 
						||
| 
								 | 
							
									return hr;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    LONGLONG tStopThis = tCurrent + (pSample->GetSize() * UNITS);
							 | 
						||
| 
								 | 
							
								    if (tStopThis > tAlignStop) {
							 | 
						||
| 
								 | 
							
									tStopThis = tAlignStop;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    pSample->SetTime(&tCurrent, &tStopThis);
							 | 
						||
| 
								 | 
							
								    tCurrent = tStopThis;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    pSample->SetDiscontinuity(bDiscontinuity);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    hr = m_pReader->Request(
							 | 
						||
| 
								 | 
							
											pSample,
							 | 
						||
| 
								 | 
							
											0);
							 | 
						||
| 
								 | 
							
								    if (FAILED(hr)) {
							 | 
						||
| 
								 | 
							
									pSample->Release();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									CleanupCancelled();
							 | 
						||
| 
								 | 
							
									OnError(hr);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return hr;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								HRESULT
							 | 
						||
| 
								 | 
							
								CPullPin::CollectAndDeliver(
							 | 
						||
| 
								 | 
							
								    REFERENCE_TIME tStart,
							 | 
						||
| 
								 | 
							
								    REFERENCE_TIME tStop)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    IMediaSample* pSample = NULL;   // better be sure pSample is set
							 | 
						||
| 
								 | 
							
								    DWORD_PTR dwUnused;
							 | 
						||
| 
								 | 
							
								    HRESULT hr = m_pReader->WaitForNext(
							 | 
						||
| 
								 | 
							
											INFINITE,
							 | 
						||
| 
								 | 
							
											&pSample,
							 | 
						||
| 
								 | 
							
											&dwUnused);
							 | 
						||
| 
								 | 
							
								    if (FAILED(hr)) {
							 | 
						||
| 
								 | 
							
									if (pSample) {
							 | 
						||
| 
								 | 
							
									    pSample->Release();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
									hr = DeliverSample(pSample, tStart, tStop);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if (FAILED(hr)) {
							 | 
						||
| 
								 | 
							
									CleanupCancelled();
							 | 
						||
| 
								 | 
							
									OnError(hr);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return hr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								HRESULT
							 | 
						||
| 
								 | 
							
								CPullPin::DeliverSample(
							 | 
						||
| 
								 | 
							
								    IMediaSample* pSample,
							 | 
						||
| 
								 | 
							
								    REFERENCE_TIME tStart,
							 | 
						||
| 
								 | 
							
								    REFERENCE_TIME tStop
							 | 
						||
| 
								 | 
							
								    )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    // fix up sample if past actual stop (for sector alignment)
							 | 
						||
| 
								 | 
							
								    REFERENCE_TIME t1, t2;
							 | 
						||
| 
								 | 
							
								    if (S_OK == pSample->GetTime(&t1, &t2)) {
							 | 
						||
| 
								 | 
							
								        if (t2 > tStop) {
							 | 
						||
| 
								 | 
							
								            t2 = tStop;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // adjust times to be relative to (aligned) start time
							 | 
						||
| 
								 | 
							
								        t1 -= tStart;
							 | 
						||
| 
								 | 
							
								        t2 -= tStart;
							 | 
						||
| 
								 | 
							
								        HRESULT hr = pSample->SetTime(&t1, &t2);
							 | 
						||
| 
								 | 
							
								        if (FAILED(hr)) {
							 | 
						||
| 
								 | 
							
								            return hr;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef DXMPERF
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
									AM_MEDIA_TYPE *	pmt = NULL;
							 | 
						||
| 
								 | 
							
									pSample->GetMediaType( &pmt );
							 | 
						||
| 
								 | 
							
									PERFLOG_RECEIVE( L"CPullPin", m_pReader, this, pSample, pmt );
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    HRESULT hr = Receive(pSample);
							 | 
						||
| 
								 | 
							
								    pSample->Release();
							 | 
						||
| 
								 | 
							
								    return hr;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void
							 | 
						||
| 
								 | 
							
								CPullPin::Process(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    // is there anything to do?
							 | 
						||
| 
								 | 
							
								    if (m_tStop <= m_tStart) {
							 | 
						||
| 
								 | 
							
									EndOfStream();
							 | 
						||
| 
								 | 
							
									return;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    BOOL bDiscontinuity = TRUE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // if there is more than one sample at the allocator,
							 | 
						||
| 
								 | 
							
								    // then try to queue 2 at once in order to overlap.
							 | 
						||
| 
								 | 
							
								    // -- get buffer count and required alignment
							 | 
						||
| 
								 | 
							
								    ALLOCATOR_PROPERTIES Actual;
							 | 
						||
| 
								 | 
							
								    HRESULT hr = m_pAlloc->GetProperties(&Actual);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // align the start position downwards
							 | 
						||
| 
								 | 
							
								    REFERENCE_TIME tStart = AlignDown(m_tStart / UNITS, Actual.cbAlign) * UNITS;
							 | 
						||
| 
								 | 
							
								    REFERENCE_TIME tCurrent = tStart;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    REFERENCE_TIME tStop = m_tStop;
							 | 
						||
| 
								 | 
							
								    if (tStop > m_tDuration) {
							 | 
						||
| 
								 | 
							
									tStop = m_tDuration;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // align the stop position - may be past stop, but that
							 | 
						||
| 
								 | 
							
								    // doesn't matter
							 | 
						||
| 
								 | 
							
								    REFERENCE_TIME tAlignStop = AlignUp(tStop / UNITS, Actual.cbAlign) * UNITS;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    DWORD dwRequest;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!m_bSync) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									//  Break out of the loop either if we get to the end or we're asked
							 | 
						||
| 
								 | 
							
									//  to do something else
							 | 
						||
| 
								 | 
							
									while (tCurrent < tAlignStop) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    // Break out without calling EndOfStream if we're asked to
							 | 
						||
| 
								 | 
							
									    // do something different
							 | 
						||
| 
								 | 
							
									    if (CheckRequest(&dwRequest)) {
							 | 
						||
| 
								 | 
							
										return;
							 | 
						||
| 
								 | 
							
									    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    // queue a first sample
							 | 
						||
| 
								 | 
							
									    if (Actual.cBuffers > 1) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										hr = QueueSample(tCurrent, tAlignStop, TRUE);
							 | 
						||
| 
								 | 
							
										bDiscontinuity = FALSE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (FAILED(hr)) {
							 | 
						||
| 
								 | 
							
										    return;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    // loop queueing second and waiting for first..
							 | 
						||
| 
								 | 
							
									    while (tCurrent < tAlignStop) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										hr = QueueSample(tCurrent, tAlignStop, bDiscontinuity);
							 | 
						||
| 
								 | 
							
										bDiscontinuity = FALSE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (FAILED(hr)) {
							 | 
						||
| 
								 | 
							
										    return;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										hr = CollectAndDeliver(tStart, tStop);
							 | 
						||
| 
								 | 
							
										if (S_OK != hr) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										    // stop if error, or if downstream filter said
							 | 
						||
| 
								 | 
							
										    // to stop.
							 | 
						||
| 
								 | 
							
										    return;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    if (Actual.cBuffers > 1) {
							 | 
						||
| 
								 | 
							
										hr = CollectAndDeliver(tStart, tStop);
							 | 
						||
| 
								 | 
							
										if (FAILED(hr)) {
							 | 
						||
| 
								 | 
							
										    return;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									    }
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// sync version of above loop
							 | 
						||
| 
								 | 
							
									while (tCurrent < tAlignStop) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    // Break out without calling EndOfStream if we're asked to
							 | 
						||
| 
								 | 
							
									    // do something different
							 | 
						||
| 
								 | 
							
									    if (CheckRequest(&dwRequest)) {
							 | 
						||
| 
								 | 
							
										return;
							 | 
						||
| 
								 | 
							
									    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    IMediaSample* pSample;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    hr = m_pAlloc->GetBuffer(&pSample, NULL, NULL, 0);
							 | 
						||
| 
								 | 
							
									    if (FAILED(hr)) {
							 | 
						||
| 
								 | 
							
										OnError(hr);
							 | 
						||
| 
								 | 
							
										return;
							 | 
						||
| 
								 | 
							
									    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    LONGLONG tStopThis = tCurrent + (pSample->GetSize() * UNITS);
							 | 
						||
| 
								 | 
							
									    if (tStopThis > tAlignStop) {
							 | 
						||
| 
								 | 
							
										tStopThis = tAlignStop;
							 | 
						||
| 
								 | 
							
									    }
							 | 
						||
| 
								 | 
							
									    pSample->SetTime(&tCurrent, &tStopThis);
							 | 
						||
| 
								 | 
							
									    tCurrent = tStopThis;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    if (bDiscontinuity) {
							 | 
						||
| 
								 | 
							
										pSample->SetDiscontinuity(TRUE);
							 | 
						||
| 
								 | 
							
										bDiscontinuity = FALSE;
							 | 
						||
| 
								 | 
							
									    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    hr = m_pReader->SyncReadAligned(pSample);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    if (FAILED(hr)) {
							 | 
						||
| 
								 | 
							
										pSample->Release();
							 | 
						||
| 
								 | 
							
										OnError(hr);
							 | 
						||
| 
								 | 
							
										return;
							 | 
						||
| 
								 | 
							
									    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    hr = DeliverSample(pSample, tStart, tStop);
							 | 
						||
| 
								 | 
							
									    if (hr != S_OK) {
							 | 
						||
| 
								 | 
							
										if (FAILED(hr)) {
							 | 
						||
| 
								 | 
							
										    OnError(hr);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return;
							 | 
						||
| 
								 | 
							
									    }
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    EndOfStream();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// after a flush, cancelled i/o will be waiting for collection
							 | 
						||
| 
								 | 
							
								// and release
							 | 
						||
| 
								 | 
							
								void
							 | 
						||
| 
								 | 
							
								CPullPin::CleanupCancelled(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    while (1) {
							 | 
						||
| 
								 | 
							
									IMediaSample * pSample;
							 | 
						||
| 
								 | 
							
									DWORD_PTR dwUnused;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									HRESULT hr = m_pReader->WaitForNext(
							 | 
						||
| 
								 | 
							
											    0,          // no wait
							 | 
						||
| 
								 | 
							
											    &pSample,
							 | 
						||
| 
								 | 
							
											    &dwUnused);
							 | 
						||
| 
								 | 
							
									if(pSample) {
							 | 
						||
| 
								 | 
							
									    pSample->Release();
							 | 
						||
| 
								 | 
							
									} else {
							 | 
						||
| 
								 | 
							
									    // no more samples
							 | 
						||
| 
								 | 
							
									    return;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 |