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

📄 fball.cpp

📁 最近在学习directshow, Directshow实务精选的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//------------------------------------------------------------------------------
// File: FBall.cpp
//
// Desc: DirectShow sample code - implementation of filter behaviors
//       for the bouncing ball source filter.  For more information,
//       refer to Ball.cpp.
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------------------------

#include <streams.h>
#include <olectl.h>
#include <initguid.h>
#include "ball.h"
#include "fball.h"
#include "CBallProp.h"

#pragma warning(disable:4710)  // 'function': function not inlined (optimzation)

// Setup data

const AMOVIESETUP_MEDIATYPE sudOpPinTypes =
{
    &MEDIATYPE_Video,       // Major type
    &MEDIASUBTYPE_NULL      // Minor type
};

const AMOVIESETUP_PIN sudOpPin =
{
    L"Output",              // Pin string name
    FALSE,                  // Is it rendered
    TRUE,                   // Is it an output
    FALSE,                  // Can we have none
    FALSE,                  // Can we have many
    &CLSID_NULL,            // Connects to filter
    NULL,                   // Connects to pin
    1,                      // Number of types
    &sudOpPinTypes };       // Pin details

const AMOVIESETUP_FILTER sudBallax =
{
    &CLSID_BouncingBall,    // Filter CLSID
    L"Bouncing Ball plus",  // String name
    MERIT_DO_NOT_USE,       // Filter merit
    1,                      // Number pins
    &sudOpPin               // Pin details
};


// COM global table of objects in this dll

CFactoryTemplate g_Templates[] = 
{
	{
		L"Bouncing Ball plus", 
		&CLSID_BouncingBall, 
		CBouncingBall::CreateInstance, 
		NULL, 
		&sudBallax 
	},
	{ 
		L"Ball Property Page",
		&CLSID_BouncingBallProp,
		CBallProp::CreateInstance 
	}
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);


////////////////////////////////////////////////////////////////////////
//
// Exported entry points for registration and unregistration 
// (in this case they only call through to default implementations).
//
////////////////////////////////////////////////////////////////////////

//
// DllRegisterServer
//
// Exported entry points for registration and unregistration
//
STDAPI DllRegisterServer()
{
    return AMovieDllRegisterServer2(TRUE);

} // DllRegisterServer


//
// DllUnregisterServer
//
STDAPI DllUnregisterServer()
{
    return AMovieDllRegisterServer2(FALSE);

} // DllUnregisterServer


//
// DllEntryPoint
//
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);

BOOL APIENTRY DllMain(HANDLE hModule, 
                      DWORD  dwReason, 
                      LPVOID lpReserved)
{
	return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
}

//
// CreateInstance
//
// The only allowed way to create Bouncing balls!
//
CUnknown * WINAPI CBouncingBall::CreateInstance(LPUNKNOWN lpunk, HRESULT *phr)
{
    ASSERT(phr);

    CUnknown *punk = new CBouncingBall(lpunk, phr);
    if(punk == NULL)
    {
        if(phr)
            *phr = E_OUTOFMEMORY;
    }
    return punk;

} // CreateInstance


//
// Constructor
//
// Initialise a CBallStream object so that we have a pin.
//
CBouncingBall::CBouncingBall(LPUNKNOWN lpunk, HRESULT *phr) :
CSource(NAME("Bouncing ball"), lpunk, CLSID_BouncingBall),
CPersistStream(lpunk, phr)
{
    ASSERT(phr);
    CAutoLock cAutoLock(&m_cStateLock);

    m_paStreams = (CSourceStream **) new CBallStream*[1];
    if(m_paStreams == NULL)
    {
        if(phr)
            *phr = E_OUTOFMEMORY;

        return;
    }

    m_paStreams[0] = new CBallStream(phr, this, L"Ball Out");
    if(m_paStreams[0] == NULL)
    {
        if(phr)
            *phr = E_OUTOFMEMORY;

        return;
    }

} // (Constructor)

// Added by HQ Tech
// Basic COM - used here to reveal our own interfaces
STDMETHODIMP CBouncingBall::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
{
	CheckPointer(ppv, E_POINTER);
	
	if (riid == IID_IBall)
	{
		return GetInterface((IBall *) this, ppv);
	}
	else if (riid == IID_ISpecifyPropertyPages) 
	{
		return GetInterface((ISpecifyPropertyPages *) this, ppv);
	}
	else if (riid == IID_IPersistStream) 
	{
		return GetInterface((IPersistStream *) this, ppv);
	}
	else
	{
		return CSource::NonDelegatingQueryInterface(riid, ppv);
	}
}

// Added by HQ Tech
// --- ISpecifyPropertyPages methods ---
STDMETHODIMP CBouncingBall::GetPages(CAUUID *pPages)
{
	pPages->cElems = 1;
	pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID));
	if (pPages->pElems == NULL) 
	{
		return E_OUTOFMEMORY;
	}
	*(pPages->pElems) = CLSID_BouncingBallProp;
	return NOERROR;
}

// --- IBall methods ---
STDMETHODIMP CBouncingBall::SetImageSize(int inWidth, int inHeight)
{
	if (IsStopped() && m_paStreams[0]->IsConnected() == FALSE)
	{
		((CBallStream*)m_paStreams[0])->SetImageSize(inWidth, inHeight);
		return S_OK;
	}
	return E_FAIL;
}

STDMETHODIMP CBouncingBall::GetImageSize(int * outWidth, int * outHeight)
{
	((CBallStream*)m_paStreams[0])->GetImageSize(outWidth, outHeight);
	return NOERROR;
}

// CPersistStream overrides
HRESULT CBouncingBall::WriteToStream(IStream *pStream)
{
	int width = 0, height = 0;
	GetImageSize(&width, &height);

	HRESULT hr = WriteInt(pStream, width);
	hr = WriteInt(pStream, height);
	return hr;
}

HRESULT CBouncingBall::ReadFromStream(IStream *pStream)
{
	HRESULT hr  = NOERROR;
	int  width  = ReadInt(pStream, hr);
	int  height = ReadInt(pStream, hr);
	SetImageSize(width, height);
	return hr;
}

int CBouncingBall::SizeMax()
{
	// When an int is expanded as characters it takes at most 12 characters
    // including a trailing delimiter.
    // Wide chars doubles this and we want two ints.
    //
	return (24 * 2);
}

STDMETHODIMP CBouncingBall::GetClassID(CLSID *pClsid)
{
	return CBaseFilter::GetClassID(pClsid);
}


//
// Constructor
//
CBallStream::CBallStream(HRESULT *phr,
                         CBouncingBall *pParent,
                         LPCWSTR pPinName) :
    CSourceStream(NAME("Bouncing Ball"),phr, pParent, pPinName),
    m_iImageWidth(320),
    m_iImageHeight(240),
    m_iDefaultRepeatTime(20)
{
    ASSERT(phr);
    CAutoLock cAutoLock(&m_cSharedState);

    m_Ball = new CBall(m_iImageWidth, m_iImageHeight);
    if(m_Ball == NULL)
    {
        if(phr)
            *phr = E_OUTOFMEMORY;
    }

} // (Constructor)


//
// Destructor
//
CBallStream::~CBallStream()
{
    CAutoLock cAutoLock(&m_cSharedState);
    if(m_Ball)
        delete m_Ball;

} // (Destructor)

// Added by HQ Tech
void CBallStream::SetImageSize(int inWidth, int inHeight)
{
	m_iImageWidth  = inWidth;
    m_iImageHeight = inHeight;
	if (m_Ball)
	{
		m_Ball->SetImageSize(m_iImageWidth, m_iImageHeight);
	}
}

void CBallStream::GetImageSize(int * outWidth, int * outHeight)
{
	if (outWidth && outHeight)
	{
		*outWidth  = m_iImageWidth;
		*outHeight = m_iImageHeight;
	}
}

//
// FillBuffer
//
// Plots a ball into the supplied video buffer
//
HRESULT CBallStream::FillBuffer(IMediaSample *pms)
{
	// Added by HQ Tech
	// Please using Sleep when you meet the problem, High Usage of CPU!
//	Sleep(40);

    CheckPointer(pms,E_POINTER);
    ASSERT(m_Ball);

    BYTE *pData;
    long lDataLen;

    pms->GetPointer(&pData);
    lDataLen = pms->GetSize();

    ZeroMemory(pData, lDataLen);
    {
        CAutoLock cAutoLockShared(&m_cSharedState);

        // If we haven't just cleared the buffer delete the old
        // ball and move the ball on

        m_Ball->MoveBall(m_rtSampleTime - (LONG) m_iRepeatTime);
        m_Ball->PlotBall(pData, m_BallPixel, m_iPixelSize);

        // The current time is the sample's start
        CRefTime rtStart = m_rtSampleTime;

        // Increment to find the finish time
        m_rtSampleTime += (LONG)m_iRepeatTime;

        pms->SetTime((REFERENCE_TIME *) &rtStart,(REFERENCE_TIME *) &m_rtSampleTime);
    }

    pms->SetSyncPoint(TRUE);
    return NOERROR;

} // FillBuffer


//
// Notify
//
// Alter the repeat rate according to quality management messages sent from
// the downstream filter (often the renderer).  Wind it up or down according
// to the flooding level - also skip forward if we are notified of Late-ness
//
STDMETHODIMP CBallStream::Notify(IBaseFilter * pSender, Quality q)
{
    // Adjust the repeat rate.
    if(q.Proportion<=0)
    {
        m_iRepeatTime = 1000;        // We don't go slower than 1 per second
    }
    else
    {
        m_iRepeatTime = m_iRepeatTime*1000 / q.Proportion;
        if(m_iRepeatTime>1000)
        {
            m_iRepeatTime = 1000;    // We don't go slower than 1 per second
        }
        else if(m_iRepeatTime<10)
        {
            m_iRepeatTime = 10;      // We don't go faster than 100/sec
        }
    }

    // skip forwards
    if(q.Late > 0)
        m_rtSampleTime += q.Late;

    return NOERROR;

} // Notify


//
// GetMediaType
//
// I _prefer_ 5 formats - 8, 16 (*2), 24 or 32 bits per pixel and
// I will suggest these with an image size of 320x240. However
// I can accept any image size which gives me some space to bounce.
//
// A bit of fun:
//      8 bit displays get red balls

⌨️ 快捷键说明

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