//------------------------------------------------------------------------------
// File: AMExtra.cpp
//
// Desc: DirectShow base classes - implements CRenderedInputPin class.
//
// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------------------------


#include <streams.h>        // DirectShow base class definitions
#include <mmsystem.h>       // Needed for definition of timeGetTime
#include <limits.h>         // Standard data type limit definitions
#include <measure.h>        // Used for time critical log functions

#include "amextra.h"

#pragma warning(disable:4355)

//  Implements CRenderedInputPin class

CRenderedInputPin::CRenderedInputPin(__in_opt LPCTSTR pObjectName,
                                     __in CBaseFilter *pFilter,
                                     __in CCritSec *pLock,
                                     __inout HRESULT *phr,
                                     __in_opt LPCWSTR pName) :
    CBaseInputPin(pObjectName, pFilter, pLock, phr, pName),
    m_bAtEndOfStream(FALSE),
    m_bCompleteNotified(FALSE)
{
}
#ifdef UNICODE
CRenderedInputPin::CRenderedInputPin(__in_opt LPCSTR pObjectName,
                                     __in CBaseFilter *pFilter,
                                     __in CCritSec *pLock,
                                     __inout HRESULT *phr,
                                     __in_opt LPCWSTR pName) :
    CBaseInputPin(pObjectName, pFilter, pLock, phr, pName),
    m_bAtEndOfStream(FALSE),
    m_bCompleteNotified(FALSE)
{
}
#endif

// Flush end of stream condition - caller should do any
// necessary stream level locking before calling this

STDMETHODIMP CRenderedInputPin::EndOfStream()
{
    HRESULT hr = CheckStreaming();

    //  Do EC_COMPLETE handling for rendered pins
    if (S_OK == hr  && !m_bAtEndOfStream) {
        m_bAtEndOfStream = TRUE;
        FILTER_STATE fs;
        EXECUTE_ASSERT(SUCCEEDED(m_pFilter->GetState(0, &fs)));
        if (fs == State_Running) {
            DoCompleteHandling();
        }
    }
    return hr;
}


// Called to complete the flush

STDMETHODIMP CRenderedInputPin::EndFlush()
{
    CAutoLock lck(m_pLock);

    // Clean up renderer state
    m_bAtEndOfStream = FALSE;
    m_bCompleteNotified = FALSE;

    return CBaseInputPin::EndFlush();
}


// Notify of Run() from filter

HRESULT CRenderedInputPin::Run(REFERENCE_TIME tStart)
{
    UNREFERENCED_PARAMETER(tStart);
    m_bCompleteNotified = FALSE;
    if (m_bAtEndOfStream) {
        DoCompleteHandling();
    }
    return S_OK;
}


//  Clear status on going into paused state

HRESULT CRenderedInputPin::Active()
{
    m_bAtEndOfStream = FALSE;
    m_bCompleteNotified = FALSE;
    return CBaseInputPin::Active();
}


//  Do stuff to deliver end of stream

void CRenderedInputPin::DoCompleteHandling()
{
    ASSERT(m_bAtEndOfStream);
    if (!m_bCompleteNotified) {
        m_bCompleteNotified = TRUE;
        m_pFilter->NotifyEvent(EC_COMPLETE, S_OK, (LONG_PTR)(IBaseFilter *)m_pFilter);
    }
}
