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
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();
|
|
}
|
|
|
|
|