⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 renbase.cpp

📁 basic class basic classbasic class
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// Constructor must be passed the base renderer object

CRendererInputPin::CRendererInputPin(CBaseRenderer *pRenderer,
                                     HRESULT *phr,
                                     LPCWSTR pPinName) :
CBaseInputPin(NAME("Renderer pin"),
              pRenderer,
              &pRenderer->m_InterfaceLock,
              (HRESULT *) phr,
              pPinName)
{
    m_pRenderer = pRenderer;
    ASSERT(m_pRenderer);
}


// Signals end of data stream on the input pin

STDMETHODIMP CRendererInputPin::EndOfStream()
{
    CAutoLock cRendererLock(&m_pRenderer->m_InterfaceLock);
    CAutoLock cSampleLock(&m_pRenderer->m_RendererLock);
    
    // Make sure we're streaming ok
    
    HRESULT hr = CheckStreaming();
    if (hr != NOERROR) {
        return hr;
    }
    
    // Pass it onto the renderer
    
    hr = m_pRenderer->EndOfStream();
    if (SUCCEEDED(hr)) {
        hr = CBaseInputPin::EndOfStream();
    }
    return hr;
}


// Signals start of flushing on the input pin - we just have the interface lock. 
// BeginFlush will do the renderer lock. ResetEndOfStream can't have the renderer lock
// because we call timeKillEvent, our timer callback method
// has to take the renderer lock to serialise our state. Therefore holding a
// renderer lock when calling timeKillEvent could cause a deadlock condition

STDMETHODIMP CRendererInputPin::BeginFlush()
{
    CAutoLock cRendererLock(&m_pRenderer->m_InterfaceLock);
    CBaseInputPin::BeginFlush();
    m_pRenderer->BeginFlush();
    return m_pRenderer->ResetEndOfStream();
}


// Signals end of flushing on the input pin

STDMETHODIMP CRendererInputPin::EndFlush()
{
    CAutoLock cRendererLock(&m_pRenderer->m_InterfaceLock);
    
    HRESULT hr = m_pRenderer->EndFlush();
    if (SUCCEEDED(hr)) {
        hr = CBaseInputPin::EndFlush();
    }
    return hr;
}


// Pass the sample straight through to the renderer object

STDMETHODIMP CRendererInputPin::Receive(IMediaSample *pSample)
{
    return m_pRenderer->Receive(pSample);
}


// Let the renderer object know that a new segment is starting

STDMETHODIMP CRendererInputPin::NewSegment(
                REFERENCE_TIME tStart,
                REFERENCE_TIME tStop,
                double dRate)
{
    HRESULT hr = CBaseInputPin::NewSegment (tStart, tStop, dRate);
    if (SUCCEEDED(hr))
    {
        m_pRenderer->OnNewSegment (tStart, tStop, dRate);
    }
    return hr;
}


// Called when the input pin is disconnected

HRESULT CRendererInputPin::BreakConnect()
{
    HRESULT hr = m_pRenderer->BreakConnect();
    if (FAILED(hr)) {
        return hr;
    }
    return CBaseInputPin::BreakConnect();
}


// Called when the input pin is connected

HRESULT CRendererInputPin::CompleteConnect(IPin *pReceivePin)
{
    HRESULT hr = m_pRenderer->CompleteConnect(pReceivePin);
    if (FAILED(hr)) {
        return hr;
    }
    return CBaseInputPin::CompleteConnect(pReceivePin);
}


// Give the pin id of our one and only pin

STDMETHODIMP CRendererInputPin::QueryId(LPWSTR *Id)
{
    CheckPointer(Id,E_POINTER);
    
    *Id = (LPWSTR)CoTaskMemAlloc(8);
    if (*Id == NULL) {
        return E_OUTOFMEMORY;
    }
    lstrcpyW(*Id, L"In");
    return NOERROR;
}


// Will the filter accept this media type

HRESULT CRendererInputPin::CheckMediaType(const CMediaType *pmt)
{
    return m_pRenderer->CheckMediaType(pmt);
}


// Called when we go paused or running

HRESULT CRendererInputPin::Active()
{
    return m_pRenderer->Active();
}


// Called when we go into a stopped state

HRESULT CRendererInputPin::Inactive()
{
    return m_pRenderer->Inactive();
}


// Tell derived classes about the media type agreed

HRESULT CRendererInputPin::SetMediaType(const CMediaType *pmt)
{
    HRESULT hr = CBaseInputPin::SetMediaType(pmt);
    if (FAILED(hr)) {
        return hr;
    }
    return m_pRenderer->SetMediaType(pmt);
}


CBaseVideoRenderer::CBaseVideoRenderer(
                                       REFCLSID RenderClass, // CLSID for this renderer
                                       TCHAR *pName,         // Debug ONLY description
                                       LPUNKNOWN pUnk,       // Aggregated owner object
                                       HRESULT *phr) :       // General OLE return code

CBaseRenderer(RenderClass,pName,pUnk,phr)
{
} // Constructor


// Destructor is just a placeholder

CBaseVideoRenderer::~CBaseVideoRenderer()
{
    ASSERT(m_dwAdvise == 0);
}


// Overidden to return our IQualProp interface

STDMETHODIMP
CBaseVideoRenderer::NonDelegatingQueryInterface(REFIID riid,VOID **ppv)
{
    // We return IQualProp and delegate everything else
    
    if (riid == IID_IQualProp) {
        return CVideoRendererQuality::NonDelegatingQueryInterface (riid, ppv);
    } else if (riid == IID_IQualityControl) {
        return GetInterface((IBaseFilter *) this, ppv);
    } else {
        return CBaseRenderer::NonDelegatingQueryInterface(riid,ppv);
    }

}


// Override JoinFilterGraph so that, just before leaving
// the graph we can send an EC_WINDOW_DESTROYED event

STDMETHODIMP
CBaseVideoRenderer::JoinFilterGraph(IFilterGraph *pGraph,LPCWSTR pName)
{
    // Since we send EC_ACTIVATE, we also need to ensure
    // we send EC_WINDOW_DESTROYED or the resource manager may be
    // holding us as a focus object
    if (!pGraph && m_pGraph) {
        
        // We were in a graph and now we're not
        // Do this properly in case we are aggregated
        IBaseFilter* pFilter;
        QueryInterface(IID_IBaseFilter,(void **) &pFilter);
        NotifyEvent(EC_WINDOW_DESTROYED, (LPARAM) pFilter, 0);
        pFilter->Release();
    }
    return CBaseFilter::JoinFilterGraph(pGraph, pName);
}


// The timing functions in this class are called by the window object and by
// the renderer's allocator.
// The windows object calls timing functions as it receives media sample
// images for drawing using GDI.
// The allocator calls timing functions when it starts passing DCI/DirectDraw
// surfaces which are not rendered in the same way; The decompressor writes
// directly to the surface with no separate rendering, so those code paths
// call direct into us.  Since we only ever hand out DCI/DirectDraw surfaces
// when we have allocated one and only one image we know there cannot be any
// conflict between the two.
//
// We use timeGetTime to return the timing counts we use (since it's relative
// performance we are interested in rather than absolute compared to a clock)
// The window object sets the accuracy of the system clock (normally 1ms) by
// calling timeBeginPeriod/timeEndPeriod when it changes streaming states


//
// IQualityControl methods
//
STDMETHODIMP CBaseVideoRenderer::SetSink( IQualityControl * piqc)
{   
    m_pQSink = piqc;
    
    return NOERROR;
} // SetSink


STDMETHODIMP CBaseVideoRenderer::Notify( IBaseFilter * pSelf, Quality q)
{
     return CVideoRendererQuality::NotifyQuality(q);
} // Notify


void CBaseVideoRenderer::PrepareRender()
{ 
    if (!m_bFirstFrameRendered)
    {
        NotifyEvent( EC_VIDEOFRAMEREADY, NULL, NULL );
        m_bFirstFrameRendered = TRUE;
    }
}


// Send a message to indicate what our supplier should do about quality.
HRESULT CBaseVideoRenderer::SendQuality(REFERENCE_TIME trLate,
                                        REFERENCE_TIME trRealStream)
{
    Quality q;

    CVideoRendererQuality::GetQuality(trLate, trRealStream, &q);
    
    // A specific sink interface may be set through IPin
    
    if (m_pQSink==NULL) {
        // Get our input pin's peer.  We send quality management messages
        // to any nominated receiver of these things (set in the IPin
        // interface), or else to our source filter.
        
        IQualityControl *pQC = NULL;
        IPin *pOutputPin = m_pInputPin->GetConnected();
        ASSERT(pOutputPin != NULL);
        
        // And get an AddRef'd quality control interface
        
        HRESULT hr = pOutputPin->QueryInterface(IID_IQualityControl,(void**) &pQC);
        if (SUCCEEDED(hr)) {
            m_pQSink = pQC;
        }
    }
    if (m_pQSink) {
        return m_pQSink->Notify(this,q);
    }
    
    return S_FALSE;
} // SendQuality


// We are called with a valid IMediaSample image to decide whether this is to
// be drawn or not.  There must be a reference clock in operation.
// Return S_OK if it is to be drawn Now (as soon as possible)
// Return S_FALSE if it is to be drawn when it's due
// Return an error if we want to drop it
// m_nNormal=-1 indicates that we dropped the previous frame and so this
// one should be drawn early.  Respect it and update it.
// Use current stream time plus a number of heuristics (detailed below)
// to make the decision

HRESULT CBaseVideoRenderer::ShouldDrawSampleNow(IMediaSample *pMediaSample,
                                                REFERENCE_TIME *ptrStart,
                                                REFERENCE_TIME *ptrEnd)
{
    REFERENCE_TIME trRealStream;     // the real time now expressed as stream time.
    REFERENCE_TIME trLate;

    m_pClock->GetTime(&trRealStream);
    trRealStream -= m_tStart;        // convert to stream time (this is a reftime)

    HRESULT hr = ComputeLateness (*ptrStart, trRealStream, &trLate);
    if (SUCCEEDED(hr))
    {
        hr = SendQuality (trLate, trRealStream);
        BOOL bSupplierHandlingQuality = (hr == S_OK);
        hr = CVideoRendererQuality::ShouldDrawSampleNow(pMediaSample, ptrStart, ptrEnd, trRealStream, bSupplierHandlingQuality);
    }
    return hr;
} // ShouldDrawSampleNow


// NOTE we're called by both the window thread and the source filter thread
// so we have to be protected by a critical section (locked before called)
// Also, when the window thread gets signalled to render an image, it always
// does so regardless of how late it is. All the degradation is done when we
// are scheduling the next sample to be drawn. Hence when we start an advise
// link to draw a sample, that sample's time will always become the last one
// drawn - unless of course we stop streaming in which case we cancel links

BOOL CBaseVideoRenderer::ScheduleSample(IMediaSample *pMediaSample)
{
    // We override ShouldDrawSampleNow to add quality management
    
    BOOL bDrawImage = CBaseRenderer::ScheduleSample(pMediaSample);
    if (bDrawImage == FALSE) {
        CVideoRendererQuality::FrameDropped (pMediaSample);
    }
    return bDrawImage;
}


// Implementation of IQualProp interface needed to support the property page
// This is how the property page gets the data out of the scheduler. We are
// passed into the constructor the owning object in the COM sense, this will
// either be the video renderer or an external IUnknown if we're aggregated.
// We initialise our CUnknown base class with this interface pointer. Then
// all we have to do is to override NonDelegatingQueryInterface to expose
// our IQualProp interface. The AddRef and Release are handled automatically
// by the base class and will be passed on to the appropriate outer object

STDMETHODIMP CBaseVideoRenderer::get_FramesDroppedInRenderer(int *pcFramesDropped)
{
    CAutoLock cVideoLock(&m_InterfaceLock);
    return CVideoRendererQuality::get_FramesDroppedInRenderer (pcFramesDropped);
} // get_FramesDroppedInRenderer


// Set *pcFramesDrawn to the number of frames drawn since
// streaming started.

STDMETHODIMP CBaseVideoRenderer::get_FramesDrawn( int *pcFramesDrawn)
{
    CAutoLock cVideoLock(&m_InterfaceLock);
    return CVideoRendererQuality::get_FramesDrawn (pcFramesDrawn);
} // get_FramesDrawn


// Set iAvgFrameRate to the frames per hundred secs since
// streaming started.  0 otherwise.

STDMETHODIMP CBaseVideoRenderer::get_AvgFrameRate( int *piAvgFrameRate)
{
    CAutoLock cVideoLock(&m_InterfaceLock);
    return CVideoRendererQuality::get_AvgFrameRate (piAvgFrameRate, m_bStreaming);
} // get_AvgFrameRate


// Set *piAvg to the average sync offset since streaming started
// in mSec.  The sync offset is the time in mSec between when the frame
// should have been drawn and when the frame was actually drawn.

STDMETHODIMP CBaseVideoRenderer::get_AvgSyncOffset( int *piAvg)
{
    CAutoLock cVideoLock(&m_InterfaceLock);
    return CVideoRendererQuality::get_

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -