Tuesday, March 27, 2007

Directshow source filter developement_Abstraction

class CSnakeFilter : public CSource
{
friend class CSnakeStream;

public:
CSnakeFilter(LPUNKNOWN pUnk, HRESULT *phr);
virtual ~CSnakeFilter(void);

// static
public:
static CUnknown * WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);

// Attributes
public:

// Operations
public:

// Overrides
protected:

// Implementations
protected:
// IUnknown interface
DECLARE_IUNKNOWN;
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
return CSource::NonDelegatingQueryInterface(riid, ppv);
}


// member variables
private:
};

CSnakeFilter::CSnakeFilter(LPUNKNOWN pUnk, HRESULT *phr)
: CSource(NAME("CSnakeFilter"), pUnk, CLSID_Snake)
{
CAutoLock cAutoLock(&m_cStateLock);

//
// CSource::AddPin() is automatically called
// by creating a source stream (CSourceStream)
//

// Add one source stream (output pin)!
new CSnakeStream(phr, this, L"Out");

// TODO: add source stream here
}


//
// Destructor
//
CSnakeFilter::~CSnakeFilter()
{
}







// CSourceStream derived class....

class CSnakeStream : public CSourceStream
{
public:
CSnakeStream(HRESULT *phr, CSnakeFilter *pParent, LPCWSTR pPinName);
virtual ~CSnakeStream(void);

// Attributes
public:

// Operations
public:
LONGLONG m_llFrameCount;

BITMAPINFO m_bmpInfo;
void *m_pPaintBuffer;
HDC m_dcPaint;
int m_nLastX;
int m_nLastY;
int m_nScoreBoardHeight;
int m_nSnakeBlockHeight;
int m_nSnakeBlockWidth;
int m_nNumberSnakeBlocks;
int m_nSpaceBetweenBlock;

// Overrides
protected:
///////////////////////////
// Media Type support

// media types filter have
virtual HRESULT GetMediaType(CMediaType *pMediaType);

///////////////////////////
// Buffer Negotiation support

// buffer size
virtual HRESULT DecideBufferSize(IMemAllocator *pMemAlloc, ALLOCATOR_PROPERTIES *pProperties);

///////////////////////////
// Data Source support

// media sample
virtual HRESULT FillBuffer(IMediaSample *pSample);

// signal
virtual HRESULT OnThreadCreate(void);
virtual HRESULT OnThreadDestroy(void);
virtual HRESULT OnThreadStartPlay(void);

// Overrides
protected:

// Implementations
protected:

// member variables
private:

};


CSnakeStream::CSnakeStream(HRESULT *phr, CSnakeFilter *pParent, LPCWSTR pPinName)
: CSourceStream(NAME("CSnakeStream"), phr, pParent, pPinName)
, m_llFrameCount(0)

{
CAutoLock cAutoLock(m_pFilter->pStateLock());

}


//
// Destructor
//
CSnakeStream::~CSnakeStream()
{
}


//
// GetMediaType
//
HRESULT CSnakeStream::GetMediaType(CMediaType *pMediaType)
{
CAutoLock lock(m_pFilter->pStateLock());

ZeroMemory(pMediaType, sizeof(CMediaType));

// TODO: modify this option
{
VIDEOINFO *pvi = (VIDEOINFO *)pMediaType->AllocFormatBuffer(sizeof(VIDEOINFO));
if (NULL == pvi)
return E_OUTOFMEMORY;

ZeroMemory(pvi, sizeof(VIDEOINFO));

pvi->bmiHeader.biCompression = BI_RGB;
pvi->bmiHeader.biBitCount = 24;
pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pvi->bmiHeader.biWidth = 320;
pvi->bmiHeader.biHeight = 240;
pvi->bmiHeader.biPlanes = 1;
pvi->bmiHeader.biSizeImage = GetBitmapSize(&pvi->bmiHeader);
pvi->bmiHeader.biClrImportant = 0;

SetRectEmpty(&(pvi->rcSource)); // we want the whole image area rendered.
SetRectEmpty(&(pvi->rcTarget)); // no particular destination rectangle

pMediaType->SetType(&MEDIATYPE_Video);
pMediaType->SetFormatType(&FORMAT_VideoInfo);
pMediaType->SetTemporalCompression(FALSE);

const GUID SubTypeGUID = GetBitmapSubtype(&pvi->bmiHeader);
pMediaType->SetSubtype(&SubTypeGUID);
pMediaType->SetSampleSize(pvi->bmiHeader.biSizeImage);

m_bmpInfo.bmiHeader = pvi->bmiHeader;
}

return S_OK;
}


//
// DecideBufferSize
//
HRESULT CSnakeStream::DecideBufferSize(IMemAllocator *pMemAlloc, ALLOCATOR_PROPERTIES *pProperties)
{
CAutoLock cAutoLock(m_pFilter->pStateLock());
ASSERT(pMemAlloc);
ASSERT(pProperties);

HRESULT hr;

// TODO: set the properties
{
VIDEOINFO *pvi = (VIDEOINFO *)m_mt.Format();
pProperties->cBuffers = 3;
pProperties->cbBuffer = pvi->bmiHeader.biSizeImage;
}

// Ask the allocator to reserve us some sample memory, NOTE the function
// can succeed (that is return NOERROR) but still not have allocated the
// memory that we requested, so we must check we got whatever we wanted

ALLOCATOR_PROPERTIES Actual;
hr = pMemAlloc->SetProperties(pProperties, &Actual);
if (FAILED(hr))
{
return hr;
}

// Is this allocator unsuitable
if (Actual.cbBuffer < pProperties->cbBuffer)
{
return E_FAIL;
}

return S_OK;
}

int nFrameRate = 0;




// FillBuffer
//
HRESULT CSnakeStream::FillBuffer(IMediaSample *pSample)
{
CAutoLock lock(m_pFilter->pStateLock());

HRESULT hr;
BYTE *pBuffer;
long lSize;

hr = pSample->GetPointer(&pBuffer);
if (SUCCEEDED(hr))
{
lSize = pSample->GetSize();

//write the TExt to BackDC or MemDc
sprintf(str,"%ld",count++ );
DrawText(hMemDC,str,strlen(str),DT_CENTER);
CopyMemory(pBuffer,m_pPaintBuffer,lSize);
}

return S_OK;
}


//
// OnThreadCreate
//
HRESULT CSnakeStream::OnThreadCreate(void)
{
HBITMAP hDibSection = CreateDIBSection(NULL, (BITMAPINFO *) &m_bmpInfo, DIB_RGB_COLORS,&m_pPaintBuffer, NULL, 0);

HDC hDC = GetDC(NULL);
m_dcPaint = CreateCompatibleDC(hDC);
SetMapMode(m_dcPaint, GetMapMode(hDC));

HGDIOBJ OldObject = SelectObject(m_dcPaint,hDibSection);

m_nScoreBoardHeight = m_bmpInfo.bmiHeader.biHeight/8;
m_nSnakeBlockHeight = 4, m_nSnakeBlockWidth = 6;
m_nNumberSnakeBlocks = 6;
m_nSpaceBetweenBlock = 1;


m_nLastX = 0;//(m_bmpInfo.bmiHeader.biWidth/2) - (m_nSnakeBlockWidth+m_nSpaceBetweenBlock)*m_nNumberSnakeBlocks;
m_nLastY = 0;//(m_bmpInfo.bmiHeader.biHeight/2);


return CSourceStream::OnThreadCreate();
}


//
// OnThreadDestroy
//
HRESULT CSnakeStream::OnThreadDestroy(void)
{
return CSourceStream::OnThreadDestroy();
}


//
// OnThreadStartPlay
//
HRESULT CSnakeStream::OnThreadStartPlay(void)
{
return CSourceStream::OnThreadStartPlay();
}




/// Another file


// {92E9BF2A-4385-4a08-8236-397478EB34B8}
DEFINE_GUID(CLSID_Snake,
0x92e9bf2a, 0x4385, 0x4a08, 0x82, 0x36, 0x39, 0x74, 0x78, 0xeb, 0x34, 0xb8);


#include
#include "Snake.h"


//
// Setup data for filter registration
//
const AMOVIESETUP_MEDIATYPE sudPinTypes =
{ &MEDIATYPE_NULL, // Major CLSID
&MEDIASUBTYPE_NULL // Minor type
};

const AMOVIESETUP_PIN psudPins[] =
{
{
L"Output", // Pin's string name
FALSE, // Is it rendered
TRUE, // Is it an output
FALSE, // Allowed none
FALSE, // Allowed many
&CLSID_NULL, // Connects to filter
L"Input", // Connects to pin
1, // Number of types
&sudPinTypes // Pin type information
},
};

const AMOVIESETUP_FILTER sudSnake =
{
&CLSID_Snake, // CLSID of filter
L"Snake Filter", // Filter's name
MERIT_DO_NOT_USE, // Filter merit
1, // Number of pins
psudPins // Pin information
};


//
// Object creation template
//
CFactoryTemplate g_Templates[] =
{
{
L"Snake Filter",
&CLSID_Snake,
CSnakeFilter::CreateInstance,
NULL,
&sudSnake
},
};

int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);


//
// Filter registration functions
//
HRESULT DllRegisterServer()
{
return AMovieDllRegisterServer2(TRUE);
}

HRESULT DllUnregisterServer()
{
return AMovieDllRegisterServer2(FALSE);
}


//
// Create a new instance of this class
//
CUnknown *CSnakeFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *phr)
{
// DLLEntry does the right thing with the return code and
// returned value on failure
CUnknown *pUnknown = new CSnakeFilter(pUnk, phr);
if (pUnknown == NULL)
{
*phr = E_OUTOFMEMORY;
}

return pUnknown;
}

No comments: