CSource *m_pFilter; // The parent of this stream//在构造的时候作为输入参数
l 新增加的virtual函数:// Override this to provide the worker thread a means of processing a buffervirtual 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();//你可以重载这个函数,可以在play之前作一些操作 do { while (!CheckRequest(&com))////Determines if a command is waiting for the thread.
//TRUE if the pCom parameter contains a command; otherwise, returns FALSE
{ IMediaSample *pSample; HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,0); //这个函数是baseoutputpin的成员函数,返回一块空白的内存区域,需要去填充数据的 //实际上是调用 IMemAllocator::GetBuffer函数来实现的 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;} //上面的这个函数调用的是This method calls the method on the input pin. //Receive can block if the method returns S_OK. //这样你的接收的filter就阻塞去接收数据 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;} 上面的reply是下面的一个CAMThread的函数 上面BOOL CheckRequest(Command *pCom) { return CAMThread::CheckRequest( (DWORD *) pCom); } 继承的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); }
我们通过上面的代码发现, CAMThread和CBaseOutputPin关联很紧密,下面我们来看看 CAMThread是一个什么样的类l CAMThread的virtual函数// override these if you want to add thread commands// Return codes > 0 indicate an error occuredvirtual 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 filterCSourceStream(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);} 这个类要实现就是这个函数了,注意Reply函数经常调用,因为 CAMThread::Reply(DWORD dw) { m_dwReturnVal = dw; // The request is now complete so CheckRequest should fail from // now on // // This event should be reset BEFORE we signal the client or // the client may Set it before we reset it and we'll then // reset it (!) m_EventSend.Reset(); // Tell the client we're finished m_EventComplete.Set(); } 有兴趣的可以继续往下研究,我觉得个人开发需求,到这就够了。 后面,我们结合我们的代码,看看CSourceStream在实际的应用是怎么使用的。