您的位置:首页 > 编程语言

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

2011-09-13 15:25 411 查看
 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) {
4000
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}

 

文章出处:http://www.zaoxue.com/article/tech-58796.htm
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐