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

📄 renbaseasync.cpp

📁 basic class basic classbasic class
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of your Microsoft Windows CE
// Source Alliance Program license form.  If you did not accept the terms of
// such a license, you are not authorized to use this source code.
//
//==========================================================================;
//
//  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
//  PURPOSE.
//
//
//--------------------------------------------------------------------------;

#include <streams.h>        // ActiveMovie 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

#pragma warning(disable:4355)

static DWORD s_dwVideoThreadPriority = -1;

// Implements the CBaseRendererAsync class

CBaseRendererAsync::CBaseRendererAsync(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),
m_pScheduledSample(NULL)
{
    if (-1 == s_dwVideoThreadPriority)
    {
        s_dwVideoThreadPriority = 248 + THREAD_PRIORITY_NORMAL;

        HKEY hKey;

        if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
                                          TEXT("SOFTWARE\\Microsoft\\DirectShow\\ThreadPriority"), 
                                          0, 0, &hKey))
        {
            DWORD dwType, dwSize, dwValue;

            // Use default value if the value isn't defined, or is invalidate
            dwSize = sizeof (DWORD);
            if (ERROR_SUCCESS == RegQueryValueEx (hKey, TEXT("Video"), NULL, &dwType, LPBYTE(&dwValue), &dwSize) &&
                REG_DWORD == dwType && dwValue < 256)
            {
                 s_dwVideoThreadPriority = dwValue;
            }

            RegCloseKey (hKey);
        }
    }
}


// Delete the dynamically allocated IMediaPosition and IMediaSeeking helper
// object. The object is created when somebody queries us. These are standard
// control interfaces for seeking and setting start/stop positions and rates.
// We will probably also have made an input pin based on CRendererInputPin
// that has to be deleted, it's created when an enumerator calls our GetPin

CBaseRendererAsync::~CBaseRendererAsync()
{
    KillThread();
    m_RendererQueue.Flush();
}



// Overriden to say what interfaces we support and where

STDMETHODIMP CBaseRendererAsync::NonDelegatingQueryInterface(REFIID riid,void **ppv)
{
    return CBaseRenderer::NonDelegatingQueryInterface(riid,ppv);
}


// For the asynchronous renderer case, the source thread never waits.
HRESULT CBaseRendererAsync::SourceThreadCanWait(BOOL bCanWait)
{
    return NOERROR;
}


#ifdef DEBUG
// Dump the current renderer state to the debug terminal. The hardest part of
// the renderer is the window where we unlock everything to wait for a clock
// to signal it is time to draw or for the application to cancel everything
// by stopping the filter. If we get things wrong we can leave the thread in
// WaitForRenderTime with no way for it to ever get out and we will deadlock

void CBaseRendererAsync::DisplayRendererState()
{
    CBaseRenderer::DisplayRendererState();

    DbgLog((LOG_TIMING, 1, TEXT("Sample currently scheduled %d"),m_pScheduledSample));
}
#endif

HRESULT CBaseRendererAsync::WaitForRenderTime()
{
    // should not have been called for the asynchronous renderer case
    ASSERT(0);
    return E_FAIL;
}


void CBaseRendererAsync::WaitForReceiveToComplete()
{
    // return immediately for the asynchronous renderer case
}


// When we stop the filter the things we do are:-

//      Decommit the allocator being used in the connection
//      Release the source filter if it's waiting in Receive
//      Cancel any advise link we set up with the clock
//      Any end of stream signalled is now obsolete so reset
//      Allow us to be stopped when we are not connected

STDMETHODIMP CBaseRendererAsync::Stop()
{
    CAutoLock cRendererLock(&m_InterfaceLock);

    DbgLog((LOG_TRACE, 2, TEXT("CBaseRendererAsync::Stop")));

    // Make sure there really is a state change
    
    if (m_State == State_Stopped) {
        // Even though we're "stopped", we may have gotten into
        // an indeterminate-state during a Pause() operation, leaving our CAMThread
        // running.  Let's make sure we use KillThread() to make any of those naughty
        // threads exit.
        if( KillThread() == NOERROR )
        {
            DEBUGMSG( 1, ( TEXT( "WMT: Closing CAMThread down properly!\n" ) ) );
        }
        return NOERROR;
    }

    // Make the worker thread go to a known state
    StopThread();

    // Now call the base class
    return CBaseRenderer::Stop();
}


// When we pause the filter the things we do are:-
//
// 
//      Commit the allocator being used in the connection
//      Allow a source filter thread to wait in Receive
//      Cancel any clock advise link (we may be running)
//      Possibly complete the state change if we have data
//      Allow us to be paused when we are not connected

STDMETHODIMP CBaseRendererAsync::Pause()
{
    CAutoLock cRendererLock(&m_InterfaceLock);
    FILTER_STATE OldState = m_State;
    HRESULT hr;

    DbgLog((LOG_TRACE, 2, TEXT("CBaseRendererAsync::Pause")));
    
    if (m_State != State_Paused)
    {
        // if we're going to Pause from Stopped, we're starting.
        // Create our worker thread (if needed) and put it in running mode.
        if (m_State == State_Stopped)
        {
            if (!ThreadExists())
            {
                if (!Create())
                {
                    return E_OUTOFMEMORY;
                }
            }
            RunThread();
        }
        m_bFirstSample = TRUE;       // set after a state change
    }

    hr = CBaseRenderer::Pause();

    return hr;
}


// When we run the filter the things we do are:-

//      Commit the allocator being used in the connection
//      Allow a source filter thread to wait in Receive
//      Signal the render event just to get us going
//      Start the base class by calling StartStreaming
//      Allow us to be run when we are not connected
//      Signal EC_COMPLETE if we are not connected

STDMETHODIMP CBaseRendererAsync::Run(REFERENCE_TIME StartTime)
{
    CAutoLock cRendererLock(&m_InterfaceLock);
    FILTER_STATE OldState = m_State;
    HRESULT hr;

    DbgLog((LOG_TRACE, 2, TEXT("CBaseRendererAsync::Run")));
    
    if (m_State == State_Stopped)
    {
        // if we're going to Run from Stopped, we're starting.
        // Create our worker thread (if needed) and put it in running mode.
        if (!ThreadExists())
        {
            if (!Create())
            {
                return E_OUTOFMEMORY;
            }
        }
        RunThread();
        m_bFirstSample = TRUE;       // set after a state change
    }

    hr = CBaseRenderer::Run(StartTime);

    return hr;
}


HRESULT CBaseRendererAsync::BeginFlush()
{
    CAutoLock cSampleLock(&m_RendererLock);

    // If paused then report state intermediate until we get some data    
    if (m_State == State_Paused) {
        NotReady();
    }
    
    CancelNotification();
    return NOERROR;
}


HRESULT CBaseRendererAsync::EndFlush()
{
    // sync with renderer thread -- stop the worker thread from delivering samples...
    StopThread();  

    // now that we know the worker thread is in a stopped state, we can get the RendererLock
    CAutoLock cSampleLock(&m_RendererLock);

    // Cancel any outstanding advise
    CancelNotification();

    ClearPendingSample();
    m_RendererQueue.Flush();

    // Reset the current sample media time
    if (m_pPosition) m_pPosition->ResetMediaTime();
    
    // put the worker thread in running mode again
    RunThread();

    return NOERROR;
}


// Called when we go into a stopped state
HRESULT CBaseRendererAsync::Inactive()
{
    HRESULT hr = CBaseRenderer::Inactive();
    m_RendererQueue.Flush();
    return hr;
}

HRESULT CBaseRendererAsync::BreakConnect()
{
    HRESULT hr = CBaseRenderer::BreakConnect();
    m_RendererQueue.Flush();
    return hr;
}


// We must always reset the current advise time to zero after a timer fires
// because there are several possible ways which lead us not to do any more
// scheduling such as the pending image being cleared after state changes

void CBaseRendererAsync::SignalTimerFired()
{
    m_dwAdvise = 0;
    if (m_pScheduledSample)
    {
        m_pScheduledSample->SetScheduled(FALSE);
        m_pScheduledSample = NULL;
    }
}


//
// Called when the source delivers us a sample. We go through a few checks to
// make sure the sample can be rendered. We queue the sample for further processing
// by the renderer thread. If we are running (streaming) then we set an event to awaken
// the renderer thread.
//
HRESULT CBaseRendererAsync::PrepareReceive(IMediaSample *pMediaSample)
{
    CAutoLock cRendererLock(&m_InterfaceLock);
    
    // Check our flushing and filter state
    
    PERFLOG_TRACE_OBJECT(PERFLOG_EV_RENDERER_OBJECT_RECEIVED, PERFLOG_STREAM_VIDEO, -1, pMediaSample, -1, -1, -1, -1, -1);

    HRESULT hr = m_pInputPin->CBaseInputPin::Receive(pMediaSample);
    
    if (hr != NOERROR) {
        return E_FAIL;
    }
    
    // Has the type changed on a media sample. We do all rendering
    // synchronously on the source thread, which has a side effect
    // that only one buffer is ever outstanding. Therefore when we
    // have Receive called we can go ahead and change the format
    // Since the format change can cause a SendMessage we just don't
    // lock
    if (m_pInputPin->SampleProps()->pMediaType) {
        m_pInputPin->SetMediaType(
            (CMediaType *)m_pInputPin->SampleProps()->pMediaType);
    }
    

⌨️ 快捷键说明

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