分享
 
 
 

DirectShow 学习(五) CSource类和其一个具体实现例子的源代码分析

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

1. CSourceStream类,是CSource类的OutputPin[source.h/source.cpp]

派生自CAMThread和CBaseOutputPin

l 成员变量:

CSource *m_pFilter; // The parent of this stream

l 新增加的virtual函数:

// Override this to provide the worker thread a means of processing a buffer

virtual HRESULT FillBuffer(IMediaSample *pSamp) PURE;

// Called as the thread is created/destroyed - use to perform

// jobs such as start/stop streaming mode

// If OnThreadCreate returns an error the thread will exit.

virtual HRESULT OnThreadCreate(void) {return NOERROR;};

virtual HRESULT OnThreadDestroy(void) {return NOERROR;};

virtual HRESULT OnThreadStartPlay(void) {return NOERROR;};

virtual HRESULT DoBufferProcessingLoop(void); // the loop executed whilst running

{

Command com;

OnThreadStartPlay();

do

{

while (!CheckRequest(&com))

{

IMediaSample *pSample;

HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,0);

if (FAILED(hr)) { Sleep(1); continue;}

// Virtual function user will override.

hr = FillBuffer(pSample);

if (hr == S_OK)

{ hr = Deliver(pSample); pSample->Release();if(hr != S_OK) return S_OK;}

else if (hr == S_FALSE)

{ pSample->Release();DeliverEndOfStream();return S_OK;}

else

{

pSample->Release();DeliverEndOfStream();

m_pFilter->NotifyEvent(EC_ERRORABORT, hr, 0);

return hr;

}

}

if (com == CMD_RUN || com == CMD_PAUSE) { Reply(NOERROR); }

else if (com != CMD_STOP) { Reply((DWORD) E_UNEXPECTED);}

}

while (com != CMD_STOP);

return S_FALSE;

}

virtual HRESULT GetMediaType(CMediaType *pMediaType) {return E_UNEXPECTED;}

l 继承的CBasePin的virtual函数:

HRESULT Active(void); // Starts up the worker thread

{

CAutoLock lock(m_pFilter->pStateLock());

if (m_pFilter->IsActive()) {return S_FALSE;}

if (!IsConnected()) {return NOERROR;}

hr = CBaseOutputPin::Active();

if (FAILED(hr)) {return hr;}

ASSERT(!ThreadExists());

// start the thread

if (!Create()) {return E_FAIL;}

// Tell thread to initialize. If OnThreadCreate Fails, so does this.

hr = Init();

if (FAILED(hr)) return hr;

return Pause();

}

HRESULT Inactive(void); // Exits the worker thread.

{

CAutoLock lock(m_pFilter->pStateLock());

if (!IsConnected()) {return NOERROR;}

// !!! need to do this before trying to stop the thread, because

// we may be stuck waiting for our own allocator!!!

hr = CBaseOutputPin::Inactive(); // call this first to Decommit the allocator

if (FAILED(hr)) {return hr;}

if (ThreadExists())

{

hr = Stop();if (FAILED(hr)) {return hr;}

hr = Exit();if (FAILED(hr)) {return hr;}

Close(); // Wait for the thread to exit, then tidy up.

}

return NOERROR;

}

virtual HRESULT CheckMediaType(const CMediaType *pMediaType);

{

// 默认只支持一种格式,即只调用新增加的GetMediaType函数得到MediaType,

// 与输入的Type进行比较

}

virtual HRESULT GetMediaType(int iPosition, CMediaType *pMediaType); // List pos. 0-n

{

// 判断iPosition必须为0,返回新增加的GetMediaType函数

}

l 操作函数:

HRESULT Init(void) { return CallWorker(CMD_INIT); }

HRESULT Exit(void) { return CallWorker(CMD_EXIT); }

HRESULT Run(void) { return CallWorker(CMD_RUN); }

HRESULT Pause(void) { return CallWorker(CMD_PAUSE); }

HRESULT Stop(void) { return CallWorker(CMD_STOP); }

l CAMThread的virtual函数

// override these if you want to add thread commands

// Return codes > 0 indicate an error occured

virtual DWORD ThreadProc(void); // the thread function

{

// 整个函数实现了一个同步的通讯Thread。

Command com;

do { com = GetRequest();if (com != CMD_INIT) { Reply((DWORD) E_UNEXPECTED);} }

while (com != CMD_INIT);

hr = OnThreadCreate(); // perform set up tasks

if (FAILED(hr))

{

OnThreadDestroy();

Reply(hr); // send failed return code from OnThreadCreate

return 1;

}

Reply(NOERROR);

Command cmd;

do

{

cmd = GetRequest();

switch (cmd) {

case CMD_EXIT: Reply(NOERROR);

break;

case CMD_RUN:

case CMD_PAUSE:Reply(NOERROR); DoBufferProcessingLoop();

break;

case CMD_STOP: Reply(NOERROR);

break;

default: Reply((DWORD) E_NOTIMPL);

break;}

}

while (cmd != CMD_EXIT);

hr = OnThreadDestroy(); // tidy up.

if (FAILED(hr)) { return 1;}

return 0;

}

l Constructor:

// increments the number of pins present on the filter

CSourceStream(TCHAR *pObjectName, HRESULT *phr, CSource *ps, LPCWSTR pPinName)

: CBaseOutputPin(pObjectName, ps, ps->pStateLock(), phr, pPinName),

m_pFilter(ps) {*phr = m_pFilter->AddPin(this);}

l Deconstructor:

~CSourceStream(void) {m_pFilter->RemovePin(this);}

2. CSource类[source.h/source.cpp]

派生自CBaseFilter

l 成员变量:

int m_iPins; // The number of pins on this filter. Updated by CSourceStream constructors & destructors.

CSourceStream **m_paStreams; // the pins on this filter.

CCritSec m_cStateLock; // Lock this to serialize function accesses to the filter state

其中m_iPins初始化为0,m_paStreams初始化为NULL。

l 继承的CBaseFilter的virtual函数:

int GetPinCount(void);

CBasePin *GetPin(int n);

l 新增加的函数:

CCritSec* pStateLock(void) { return &m_cStateLock; } // provide our critical section

HRESULT AddPin(CSourceStream *);

{

CAutoLock lock(&m_cStateLock);

/* Allocate space for this pin and the old ones */

CSourceStream **paStreams = new CSourceStream *[m_iPins + 1];

if (paStreams == NULL) { return E_OUTOFMEMORY;}

// 如果m_paStreams已经存在,则将其复制到paStreams,略去该步代码…

if (m_paStreams != NULL)

{

CopyMemory((PVOID)paStreams, (PVOID)m_paStreams,

m_iPins * sizeof(m_paStreams[0]));

// 其实下面的这行实现复制功能的代码可有可无

paStreams[m_iPins] = pStream;

delete [] m_paStreams;

}

m_paStreams = paStreams;

m_paStreams[m_iPins] = pStream;

m_iPins++;

}

HRESULT RemovePin(CSourceStream *);

{

// 遍历所有的Pin,如果与输入的指针相同,则删除该Pin,如果只有一个Pin存在,释放m_paStreams,

// 否则将其后的Pin全部前移一位。

}

STDMETHODIMP FindPin(LPCWSTR Id, IPin ** ppPin );

{

// 输入的Id其实是一个数字字符串,用WstrToInt(Id) -1的结果调用GetPin,

// 输出Pin必须调用AddRef

}

int FindPinNumber(IPin *iPin);

{

// 遍历所有Pin,进行指针比较,返回相同那个Pin的Number,否则返回-1

}

3. DirectShow 中Source Filter的一个例子Ball[fball.h/fball.cpp]

Filter Ball是一个能生成跳跃小球的Source Filter。

l Filter类CBouncingBall:

i. 成员函数:

// The only allowed way to create Bouncing balls!

static CUnknown * WINAPI CreateInstance(LPUNKNOWN lpunk, HRESULT *phr);

{创建(new)了一个新的CBouncingBall的Object。}

ii. Constructor(private):

CBouncingBall::CBouncingBall(LPUNKNOWN lpunk, HRESULT *phr) :

CSource(NAME("Bouncing ball"), lpunk, CLSID_BouncingBall)

{

// 创建Output Pin,首先创建数组指针m_paStreams = (CSourceStream **) new CBallStream*[1];

// 创建真正的Output Pin:m_paStreams[0] = new CBallStream(phr, this, L"A Bouncing Ball!");

}

l Pin 类CBallStream:

派生自CSourceStream。CBall是一个具体实现其功能的类,这里不做分析。

i. 成员变量:

int m_iImageHeight; // The current image height

int m_iImageWidth; // And current image width

int m_iRepeatTime; // Time in msec between frames

const int m_iDefaultRepeatTime; // Initial m_iRepeatTime

BYTE m_BallPixel[4]; // Represents one coloured ball

int m_iPixelSize; // The pixel size in bytes

PALETTEENTRY m_Palette[256]; // The optimal palette for the image

CCritSec m_cSharedState; // Lock on m_rtSampleTime and m_Ball

CRefTime m_rtSampleTime; // The time stamp for each sample

CBall *m_Ball; // The current ball object

ii. 从CBasePin和CBaseOutputPin继承的virtual函数:

// Ask for buffers of the size appropriate to the agreed media type

HRESULT DecideBufferSize(IMemAllocator *pIMemAlloc, ALLOCATOR_PROPERTIES *pProperties);

{

CAutoLock cAutoLock(m_pFilter->pStateLock());

VIDEOINFO *pvi = (VIDEOINFO *) m_mt.Format();

pProperties->cBuffers = 1;

pProperties->cbBuffer = pvi->bmiHeader.biSizeImage;

ALLOCATOR_PROPERTIES Actual;

hr = pAlloc->SetProperties(pProperties,&Actual);

if(Actual.cbBuffer < pProperties->cbBuffer) return E_FAIL;

}

// Set the agreed media type, and set up the necessary ball parameters

HRESULT SetMediaType(const CMediaType *pMediaType);

{

HRESULT hr = CSourceStream::SetMediaType(pMediaType);

VIDEOINFO * pvi = (VIDEOINFO *) m_mt.Format();

switch(pvi->bmiHeader.biBitCount)

{

// 根据位数不同,8,16,32来对成员变量进行不同的设置

}

}

// We will accept 8, 16, 24 or 32 bit video formats, in any

HRESULT CheckMediaType(const CMediaType *pMediaType);

{

if((*(pMediaType->Type()) != MEDIATYPE_Video) || // we only output video

!(pMediaType->IsFixedSize())) // in fixed size samples

return E_INVALIDARG;

// Check for the subtypes we support

const GUID *SubType = pMediaType->Subtype();

if((*SubType != MEDIASUBTYPE_RGB8)

&& (*SubType != MEDIASUBTYPE_RGB565)

&& (*SubType != MEDIASUBTYPE_RGB555)

&& (*SubType != MEDIASUBTYPE_RGB24)

&& (*SubType != MEDIASUBTYPE_RGB32))

return E_INVALIDARG;

// Get the format area of the media type

VIDEOINFO *pvi = (VIDEOINFO *) pMediaType->Format();

if((pvi->bmiHeader.biWidth < 20) || ( abs(pvi->bmiHeader.biHeight) < 20))

return E_INVALIDARG;

// 别的校验…

}

HRESULT GetMediaType(int iPosition, CMediaType *pmt);

{

CAutoLock cAutoLock(m_pFilter->pStateLock());

if((iPosition < 0) || (if(iPosition < 0))) 错误。

VIDEOINFO *pvi = (VIDEOINFO *) pmt->AllocFormatBuffer(sizeof(VIDEOINFO));

ZeroMemory(pvi, sizeof(VIDEOINFO));

switch(iPosition)

{

case 0: // Return our highest quality 32bit format

case 1: // Return our 24bit format

case 2: // 16 bit per pixel RGB565

case 3: // 16 bits per pixel RGB555

case 4: // 8 bit palettised

}

// 填充pmt的另外一些值

}

// Quality control notifications sent to us

STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);

{

// Notify主要设置了一些成员变量以调节速度

}

iii. 从CSourceStream继承的virtual 函数:

// plots a ball into the supplied video frame

HRESULT FillBuffer(IMediaSample *pms);

{

// 得到Sample的数据指针:pms->GetPointer(&pData);

// 调用m_Ball的成员函数填充该数据领域

// 设置时间pms->SetTime((REFERENCE_TIME *) &rtStart,(REFERENCE_TIME *) &m_rtSampleTime);

// pms->SetSyncPoint(TRUE);

}

// Resets the stream time to zero

HRESULT OnThreadCreate(void);{初始化了变量m_rtSampleTime和m_iRepeatTime}

前一篇:(四)部分Helper Classes类源代码分析

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有