📄 transfrm.cpp
字号:
// We may have an input connection but no output connection
// However, if we have an input pin we do have an output pin
else if (m_pOutput->IsConnected() == FALSE) {
m_State = State_Paused;
}
else {
if (m_State == State_Stopped) {
// allow a class derived from CTransformFilter
// to know about starting and stopping streaming
CAutoLock lck2(&m_csReceive);
hr = StartStreaming();
}
if (SUCCEEDED(hr)) {
hr = CBaseFilter::Pause();
}
}
m_bSampleSkipped = FALSE;
m_bQualityChanged = FALSE;
return hr;
}
HRESULT
CTransformFilter::NewSegment(
REFERENCE_TIME tStart,
REFERENCE_TIME tStop,
double dRate)
{
if (m_pOutput != NULL) {
return m_pOutput->DeliverNewSegment(tStart, tStop, dRate);
}
return S_OK;
}
// Check streaming status
HRESULT
CTransformInputPin::CheckStreaming()
{
ASSERT(m_pTransformFilter->m_pOutput != NULL);
if (!m_pTransformFilter->m_pOutput->IsConnected()) {
return VFW_E_NOT_CONNECTED;
} else {
// Shouldn't be able to get any data if we're not connected!
ASSERT(IsConnected());
// we're flushing
if (m_bFlushing) {
return S_FALSE;
}
// Don't process stuff in Stopped state
if (IsStopped()) {
return VFW_E_WRONG_STATE;
}
if (m_bRunTimeError) {
return VFW_E_RUNTIME_ERROR;
}
return S_OK;
}
}
// =================================================================
// Implements the CTransformInputPin class
// =================================================================
// constructor
CTransformInputPin::CTransformInputPin(
TCHAR *pObjectName,
CTransformFilter *pTransformFilter,
HRESULT * phr,
LPCWSTR pName)
: CBaseInputPin(pObjectName, pTransformFilter, &pTransformFilter->m_csFilter, phr, pName)
{
DbgLog((LOG_TRACE,2,TEXT("CTransformInputPin::CTransformInputPin")));
m_pTransformFilter = pTransformFilter;
}
#ifdef UNICODE
CTransformInputPin::CTransformInputPin(
CHAR *pObjectName,
CTransformFilter *pTransformFilter,
HRESULT * phr,
LPCWSTR pName)
: CBaseInputPin(pObjectName, pTransformFilter, &pTransformFilter->m_csFilter, phr, pName)
{
DbgLog((LOG_TRACE,2,TEXT("CTransformInputPin::CTransformInputPin")));
m_pTransformFilter = pTransformFilter;
}
#endif
// provides derived filter a chance to grab extra interfaces
HRESULT
CTransformInputPin::CheckConnect(IPin *pPin)
{
HRESULT hr = m_pTransformFilter->CheckConnect(PINDIR_INPUT,pPin);
if (FAILED(hr)) {
return hr;
}
return CBaseInputPin::CheckConnect(pPin);
}
// provides derived filter a chance to release it's extra interfaces
HRESULT
CTransformInputPin::BreakConnect()
{
// Can't disconnect unless stopped
ASSERT(IsStopped());
m_pTransformFilter->BreakConnect(PINDIR_INPUT);
return CBaseInputPin::BreakConnect();
}
// Let derived class know when the input pin is connected
HRESULT
CTransformInputPin::CompleteConnect(IPin *pReceivePin)
{
HRESULT hr = m_pTransformFilter->CompleteConnect(PINDIR_INPUT,pReceivePin);
if (FAILED(hr)) {
return hr;
}
return CBaseInputPin::CompleteConnect(pReceivePin);
}
// check that we can support a given media type
HRESULT
CTransformInputPin::CheckMediaType(const CMediaType* pmt)
{
// Check the input type
HRESULT hr = m_pTransformFilter->CheckInputType(pmt);
if (S_OK != hr) {
return hr;
}
// if the output pin is still connected, then we have
// to check the transform not just the input format
if ((m_pTransformFilter->m_pOutput != NULL) &&
(m_pTransformFilter->m_pOutput->IsConnected())) {
return m_pTransformFilter->CheckTransform(
pmt,
&m_pTransformFilter->m_pOutput->CurrentMediaType());
} else {
return hr;
}
}
// set the media type for this connection
HRESULT
CTransformInputPin::SetMediaType(const CMediaType* mtIn)
{
// Set the base class media type (should always succeed)
HRESULT hr = CBasePin::SetMediaType(mtIn);
if (FAILED(hr)) {
return hr;
}
// check the transform can be done (should always succeed)
ASSERT(SUCCEEDED(m_pTransformFilter->CheckInputType(mtIn)));
return m_pTransformFilter->SetMediaType(PINDIR_INPUT,mtIn);
}
// =================================================================
// Implements IMemInputPin interface
// =================================================================
// provide EndOfStream that passes straight downstream
// (there is no queued data)
STDMETHODIMP
CTransformInputPin::EndOfStream(void)
{
CAutoLock lck(&m_pTransformFilter->m_csReceive);
HRESULT hr = CheckStreaming();
if (S_OK == hr) {
hr = m_pTransformFilter->EndOfStream();
}
return hr;
}
// enter flushing state. Call default handler to block Receives, then
// pass to overridable method in filter
STDMETHODIMP
CTransformInputPin::BeginFlush(void)
{
CAutoLock lck(&m_pTransformFilter->m_csFilter);
// Are we actually doing anything?
ASSERT(m_pTransformFilter->m_pOutput != NULL);
if (!IsConnected() ||
!m_pTransformFilter->m_pOutput->IsConnected()) {
return VFW_E_NOT_CONNECTED;
}
HRESULT hr = CBaseInputPin::BeginFlush();
if (FAILED(hr)) {
return hr;
}
return m_pTransformFilter->BeginFlush();
}
// leave flushing state.
// Pass to overridable method in filter, then call base class
// to unblock receives (finally)
STDMETHODIMP
CTransformInputPin::EndFlush(void)
{
CAutoLock lck(&m_pTransformFilter->m_csFilter);
// Are we actually doing anything?
ASSERT(m_pTransformFilter->m_pOutput != NULL);
if (!IsConnected() ||
!m_pTransformFilter->m_pOutput->IsConnected()) {
return VFW_E_NOT_CONNECTED;
}
HRESULT hr = m_pTransformFilter->EndFlush();
if (FAILED(hr)) {
return hr;
}
return CBaseInputPin::EndFlush();
}
// here's the next block of data from the stream.
// AddRef it yourself if you need to hold it beyond the end
// of this call.
STDMETHODIMP
CTransformInputPin::Receive(IMediaSample * pSample)
{
HRESULT hr;
CAutoLock lck(&m_pTransformFilter->m_csReceive);
ASSERT(pSample);
// check all is well with the base class
hr = CBaseInputPin::Receive(pSample);
if (S_OK == hr) {
hr = m_pTransformFilter->Receive(pSample);
}
return hr;
}
// override to pass downstream
STDMETHODIMP
CTransformInputPin::NewSegment(
REFERENCE_TIME tStart,
REFERENCE_TIME tStop,
double dRate)
{
// Save the values in the pin
CBasePin::NewSegment(tStart, tStop, dRate);
return m_pTransformFilter->NewSegment(tStart, tStop, dRate);
}
// =================================================================
// Implements the CTransformOutputPin class
// =================================================================
// constructor
CTransformOutputPin::CTransformOutputPin(
TCHAR *pObjectName,
CTransformFilter *pTransformFilter,
HRESULT * phr,
LPCWSTR pPinName)
: CBaseOutputPin(pObjectName, pTransformFilter, &pTransformFilter->m_csFilter, phr, pPinName),
m_pPosition(NULL)
{
DbgLog((LOG_TRACE,2,TEXT("CTransformOutputPin::CTransformOutputPin")));
m_pTransformFilter = pTransformFilter;
}
#ifdef UNICODE
CTransformOutputPin::CTransformOutputPin(
CHAR *pObjectName,
CTransformFilter *pTransformFilter,
HRESULT * phr,
LPCWSTR pPinName)
: CBaseOutputPin(pObjectName, pTransformFilter, &pTransformFilter->m_csFilter, phr, pPinName),
m_pPosition(NULL)
{
DbgLog((LOG_TRACE,2,TEXT("CTransformOutputPin::CTransformOutputPin")));
m_pTransformFilter = pTransformFilter;
}
#endif
// destructor
CTransformOutputPin::~CTransformOutputPin()
{
DbgLog((LOG_TRACE,2,TEXT("CTransformOutputPin::~CTransformOutputPin")));
if (m_pPosition) m_pPosition->Release();
}
// overriden to expose IMediaPosition and IMediaSeeking control interfaces
STDMETHODIMP
CTransformOutputPin::NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
CheckPointer(ppv,E_POINTER);
ValidateReadWritePtr(ppv,sizeof(PVOID));
*ppv = NULL;
if (riid == IID_IMediaPosition || riid == IID_IMediaSeeking) {
// we should have an input pin by now
ASSERT(m_pTransformFilter->m_pInput != NULL);
if (m_pPosition == NULL) {
HRESULT hr = CreatePosPassThru(
GetOwner(),
FALSE,
(IPin *)m_pTransformFilter->m_pInput,
&m_pPosition);
if (FAILED(hr)) {
return hr;
}
}
return m_pPosition->QueryInterface(riid, ppv);
} else {
return CBaseOutputPin::NonDelegatingQueryInterface(riid, ppv);
}
}
// provides derived filter a chance to grab extra interfaces
HRESULT
CTransformOutputPin::CheckConnect(IPin *pPin)
{
// we should have an input connection first
ASSERT(m_pTransformFilter->m_pInput != NULL);
if ((m_pTransformFilter->m_pInput->IsConnected() == FALSE)) {
return E_UNEXPECTED;
}
HRESULT hr = m_pTransformFilter->CheckConnect(PINDIR_OUTPUT,pPin);
if (FAILED(hr)) {
return hr;
}
return CBaseOutputPin::CheckConnect(pPin);
}
// provides derived filter a chance to release it's extra interfaces
HRESULT
CTransformOutputPin::BreakConnect()
{
// Can't disconnect unless stopped
ASSERT(IsStopped());
m_pTransformFilter->BreakConnect(PINDIR_OUTPUT);
return CBaseOutputPin::BreakConnect();
}
// Let derived class know when the output pin is connected
HRESULT
CTransformOutputPin::CompleteConnect(IPin *pReceivePin)
{
HRESULT hr = m_pTransformFilter->CompleteConnect(PINDIR_OUTPUT,pReceivePin);
if (FAILED(hr)) {
return hr;
}
return CBaseOutputPin::CompleteConnect(pReceivePin);
}
// check a given transform - must have selected input type first
HRESULT
CTransformOutputPin::CheckMediaType(const CMediaType* pmtOut)
{
// must have selected input first
ASSERT(m_pTransformFilter->m_pInput != NULL);
if ((m_pTransformFilter->m_pInput->IsConnected() == FALSE)) {
return E_INVALIDARG;
}
return m_pTransformFilter->CheckTransform(
&m_pTransformFilter->m_pInput->CurrentMediaType(),
pmtOut);
}
// called after we have agreed a media type to actually set it in which case
// we run the CheckTransform function to get the output format type again
HRESULT
CTransformOutputPin::SetMediaType(const CMediaType* pmtOut)
{
HRESULT hr = NOERROR;
ASSERT(m_pTransformFilter->m_pInput != NULL);
ASSERT(m_pTransformFilter->m_pInput->CurrentMediaType().IsValid());
// Set the base class media type (should always succeed)
hr = CBasePin::SetMediaType(pmtOut);
if (FAILED(hr)) {
return hr;
}
#ifdef DEBUG
if (FAILED(m_pTransformFilter->CheckTransform(&m_pTransformFilter->
m_pInput->CurrentMediaType(),pmtOut))) {
DbgLog((LOG_ERROR,0,TEXT("*** This filter is accepting an output media type")));
DbgLog((LOG_ERROR,0,TEXT(" that it can't currently transform to. I hope")));
DbgLog((LOG_ERROR,0,TEXT(" it's smart enough to reconnect its input.")));
}
#endif
return m_pTransformFilter->SetMediaType(PINDIR_OUTPUT,pmtOut);
}
// pass the buffer size decision through to the main transform class
HRESULT
CTransformOutputPin::DecideBufferSize(
IMemAllocator * pAllocator,
ALLOCATOR_PROPERTIES* pProp)
{
return m_pTransformFilter->DecideBufferSize(pAllocator, pProp);
}
// return a specific media type indexed by iPosition
HRESULT
CTransformOutputPin::GetMediaType(
int iPosition,
CMediaType *pMediaType)
{
ASSERT(m_pTransformFilter->m_pInput != NULL);
// We don't have any media types if our input is not connected
if (m_pTransformFilter->m_pInput->IsConnected()) {
return m_pTransformFilter->GetMediaType(iPosition,pMediaType);
} else {
return VFW_S_NO_MORE_ITEMS;
}
}
// Override this if you can do something constructive to act on the
// quality message. Consider passing it upstream as well
// Pass the quality mesage on upstream.
STDMETHODIMP
CTransformOutputPin::Notify(IBaseFilter * pSender, Quality q)
{
UNREFERENCED_PARAMETER(pSender);
ValidateReadPtr(pSender,sizeof(IBaseFilter));
// First see if we want to handle this ourselves
HRESULT hr = m_pTransformFilter->AlterQuality(q);
if (hr!=S_FALSE) {
return hr; // either S_OK or a failure
}
// S_FALSE means we pass the message on.
// Find the quality sink for our input pin and send it there
ASSERT(m_pTransformFilter->m_pInput != NULL);
return m_pTransformFilter->m_pInput->PassNotify(q);
} // Notify
// the following removes a very large number of level 4 warnings from the microsoft
// compiler output, which are not useful at all in this case.
#pragma warning(disable:4514)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -