Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

286 lines
6.1 KiB

// Copyright (c) 1996 - 1999 Microsoft Corporation. All Rights Reserved.
#include <streams.h>
#include <initguid.h>
#include "fw.h"
// ------------------------------------------------------------------------
// filter
#pragma warning(disable:4355)
CBaseWriterFilter::CBaseWriterFilter(LPUNKNOWN pUnk, HRESULT *pHr) :
CBaseFilter(NAME("fw filter"), pUnk, &m_cs, CLSID_FileWriter),
m_inputPin(NAME("fw inpin"), this, &m_cs, pHr)
{
ASSERT(m_mtSet.majortype == GUID_NULL);
ASSERT(m_mtSet.subtype == GUID_NULL);
}
CBaseWriterFilter::~CBaseWriterFilter()
{
}
STDMETHODIMP
CBaseWriterFilter::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
{
if(riid == IID_IAMFilterMiscFlags)
return GetInterface((IAMFilterMiscFlags *)this, ppv);
else
return CBaseFilter::NonDelegatingQueryInterface(riid, ppv);
}
int CBaseWriterFilter::GetPinCount()
{
return 1;
}
CBasePin *CBaseWriterFilter::GetPin(int pin)
{
return pin == 0 ? &m_inputPin : 0;
}
HRESULT CBaseWriterFilter::Pause()
{
CAutoLock lock(&m_cs);
if(m_State == State_Stopped)
{
m_fEosSignaled = FALSE;
m_fErrorSignaled = FALSE;
HRESULT hr = CanPause();
if(FAILED(hr))
{
m_fErrorSignaled = TRUE;
return hr;
}
// send an EC_COMPLETE event first time we run with input
// disconnected
if(!m_inputPin.IsConnected())
{
m_fEosSignaled = TRUE;
}
hr = Open();
if(FAILED(hr))
{
m_fErrorSignaled = TRUE;
return hr;
}
}
return CBaseFilter::Pause();
}
HRESULT CBaseWriterFilter::Run(REFERENCE_TIME rtStart)
{
CAutoLock Lock(&m_cs);
HRESULT hr = CBaseFilter::Run(rtStart);
// every time we transition to Run, need to send EC_COMPLETE if
// we're done.
if(m_fEosSignaled && !m_fErrorSignaled)
{
NotifyEvent(EC_COMPLETE, S_OK, (LONG_PTR)(IBaseFilter *)this);
}
return hr;
}
HRESULT CBaseWriterFilter::Stop()
{
CAutoLock lock(&m_cs);
HRESULT hrClose = Close();
HRESULT hrStop = CBaseFilter::Stop();
if(m_fErrorSignaled)
return hrStop;
else
return FAILED(hrClose) ? hrClose : hrStop;
}
// could be used to close asynchronous file handle (used by
// IMemInputPin) early
STDMETHODIMP CBaseWriterFilter::EndOfStream()
{
DbgLog((LOG_TRACE, 3, TEXT("CBaseWriterFilter: EOS")));
CAutoLock lock(&m_cs);
ASSERT(!m_fEosSignaled);
m_fEosSignaled = TRUE;
if(!m_fErrorSignaled)
{
if(m_State == State_Running)
{
NotifyEvent(EC_COMPLETE, S_OK, (LONG_PTR)(IBaseFilter *)this);
}
else if(m_State == State_Paused)
{
// m_fEosSignaled set, so will be signaled on run
}
else
{
ASSERT(m_State == State_Stopped);
// we could have stopped already; ignore EOS
}
}
return S_OK;
}
// ------------------------------------------------------------------------
// input pin
CBaseWriterInput::CBaseWriterInput(
TCHAR *pObjectName,
CBaseWriterFilter *pFilter,
CCritSec *pLock,
HRESULT *phr) :
CBaseInputPin(pObjectName, pFilter, pLock, phr, L"in"),
m_pFwf(pFilter)
{
}
STDMETHODIMP
CBaseWriterInput::NonDelegatingQueryInterface(REFIID riid, void ** pv)
{
if(riid == IID_IStream)
{
return m_pFwf->CreateIStream(pv);
}
else
{
return CBaseInputPin::NonDelegatingQueryInterface(riid, pv);
}
}
HRESULT CBaseWriterInput::CheckMediaType(const CMediaType *pmt)
{
// accept what's set or anything if not set
if((m_pFwf->m_mtSet.majortype == pmt->majortype ||
m_pFwf->m_mtSet.majortype == GUID_NULL) &&
(m_pFwf->m_mtSet.subtype == pmt->subtype ||
m_pFwf->m_mtSet.subtype == GUID_NULL))
{
return S_OK;
}
else
{
return S_FALSE;
}
}
STDMETHODIMP
CBaseWriterInput::BeginFlush(void)
{
return E_UNEXPECTED;
}
STDMETHODIMP
CBaseWriterInput::EndFlush(void)
{
return E_UNEXPECTED;
}
STDMETHODIMP CBaseWriterInput::GetAllocator(IMemAllocator **ppA)
{
*ppA = 0;
// what do you want with my allocator.... you can't set the data
// pointer on it...
return E_INVALIDARG;
}
// return disk sector size through here
STDMETHODIMP CBaseWriterInput::GetAllocatorRequirements(
ALLOCATOR_PROPERTIES *pAp)
{
ULONG cb;
ZeroMemory(pAp, sizeof(*pAp));
HRESULT hr = m_pFwf->GetAlignReq(&cb);
ASSERT(hr == S_OK);
pAp->cbAlign = cb;
return S_OK;
}
STDMETHODIMP CBaseWriterInput::Receive(IMediaSample *pSample)
{
CAutoLock l(&m_pFwf->m_cs);
if(m_pFwf->m_fErrorSignaled)
return S_FALSE;
ASSERT(!m_pFwf->m_fEosSignaled);
REFERENCE_TIME rtStart, rtEnd;
HRESULT hr = pSample->GetTime(&rtStart, &rtEnd);
if(hr != S_OK)
{
m_pFwf->m_fErrorSignaled = TRUE;
m_pFwf->NotifyEvent(EC_ERRORABORT, hr, 0);
return hr;
}
// ULONG cb = pSample->GetActualDataLength();
// if(rtStart + cb != rtEnd)
// {
// DbgBreak("start, stop, and size don't mathc");
// return E_INVALIDARG;
// }
ULONG cb = (ULONG)(rtEnd - rtStart);
BYTE *pb;
hr = pSample->GetPointer(&pb);
ASSERT(hr == S_OK);
pSample->AddRef();
hr = m_pFwf->AsyncWrite(rtStart, cb, pb, Callback, pSample);
if(hr != S_OK)
{
DbgLog((LOG_ERROR, 5, TEXT("CBaseWriterInput: AsyncWrite returned %08x"),
hr));
// the call back is called only if AsyncWrite succeeds.
pSample->Release();
if(FAILED(hr))
{
DbgLog((LOG_ERROR, 1, TEXT("fw Receive: signalling error")));
m_pFwf->m_fErrorSignaled = TRUE;
m_pFwf->NotifyEvent(EC_ERRORABORT, hr, 0);
}
}
return hr;
}
STDMETHODIMP CBaseWriterInput::EndOfStream()
{
return m_pFwf->EndOfStream();
}
STDMETHODIMP
CBaseWriterInput::NotifyAllocator(
IMemAllocator * pAllocator,
BOOL bReadOnly)
{
HRESULT hr = CBaseInputPin::NotifyAllocator(pAllocator, bReadOnly);
if(FAILED(hr))
return hr;
else
return m_pFwf->NotifyAllocator(pAllocator, bReadOnly);
}
void CBaseWriterInput::Callback(void *pMisc)
{
IMediaSample *pSample = (IMediaSample *)pMisc;
pSample->Release();
}