Dshow--分析点播命令

来源:互联网 发布:拆分资金盘 源码 编辑:程序博客网 时间:2024/05/17 07:15

数据输出pin,class CVideoOutPin : public CSourceStream;

处理原数据的线程类 class AM_NOVTABLE CAMThread;
class CSourceStream : public CAMThread, public CBaseOutputPin {
...
    enum Command {CMD_INIT, CMD_PAUSE, CMD_RUN, CMD_STOP, CMD_EXIT};
    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); }
...
}

点播
graph调用mMediaControl->Run(),引起CBaseFilter::Pause(),CBaseFilter::Run(),引起CSourceStream::Active() ,
CSourceStream::Active(void) {
CBaseOutputPin::Active();//执行return m_pAllocator->Commit();
CAMThread::Create()//创建线程,调用CAMThread::InitialThreadProc。
Init();
}
接收处理
//循环的内容为:
DWORD CSourceStream::ThreadProc(void) {
...
 Command cmd;
    do {
 cmd = GetRequest();

 switch (cmd) {

 case CMD_EXIT:
     Reply(NOERROR);
     break;

 case CMD_RUN:
     DbgLog((LOG_ERROR, 1, TEXT("CMD_RUN received before a CMD_PAUSE???")));
     // !!! fall through???
 
 case CMD_PAUSE:
     Reply(NOERROR);
     DoBufferProcessingLoop();
     break;

 case CMD_STOP:
     Reply(NOERROR);
     break;

 default:
     DbgLog((LOG_ERROR, 1, TEXT("Unknown command %d received!"), cmd));
     Reply((DWORD) E_NOTIMPL);
     break;
 }
    } while (cmd != CMD_EXIT);
...
}
HRESULT CSourceStream::DoBufferProcessingLoop(void) {
    Command com;
    OnThreadStartPlay();
  do {
 while (!CheckRequest(&com)) {  退出的标志。

     IMediaSample *pSample;

     HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,0);
     if (FAILED(hr)) {
                Sleep(1);
  continue; // go round again. Perhaps the error will go away
       // or the allocator is decommited & we will be asked to
       // exit soon.
     }

     // Virtual function user will override.
     hr = FillBuffer(pSample); //填充数据

     if (hr == S_OK) {
  hr = Deliver(pSample); //发送数据
                pSample->Release(); //引用减减

                // downstream filter returns S_FALSE if it wants us to
                // stop or an error if it's reporting an error.
                if(hr != S_OK)
                {
                  DbgLog((LOG_TRACE, 2, TEXT("Deliver() returned %08x; stopping"), hr));
                  return S_OK;
                }

     } else if (hr == S_FALSE) {
                // derived class wants us to stop pushing data
  pSample->Release();
  DeliverEndOfStream();
  return S_OK;
     } else {
                // derived class encountered an error
                pSample->Release();
  DbgLog((LOG_ERROR, 1, TEXT("Error %08lX from FillBuffer!!!"), hr));
                DeliverEndOfStream();
                m_pFilter->NotifyEvent(EC_ERRORABORT, hr, 0);
                return hr;
     }

            // all paths release the sample
 }

        // For all commands sent to us there must be a Reply call!

 if (com == CMD_RUN || com == CMD_PAUSE) {
     Reply(NOERROR);
 } else if (com != CMD_STOP) {
     Reply((DWORD) E_UNEXPECTED);
     DbgLog((LOG_ERROR, 1, TEXT("Unexpected command!!!")));
 }
    } while (com != CMD_STOP);
    return S_FALSE;
}

CBaseOutputPin::Deliver(IMediaSample * pSample)
{
       return m_pInputPin->Receive(pSample); //下游的开始接收
}
暂停
调用CBaseFilter::Pause(),不能让DoBufferProcessingLoop()停止工作,除非把接收的函数堵住。
停止
mMediaControl->Stop()引起CBaseFilter::Stop(),引起如下:
HRESULT CSourceStream::Inactive(void) {
...
CBaseOutputPin::Inactive();//主要语句为return m_pAllocator->Decommit();。
Stop();//调用CAMThread::CallWorker(CMD_STOP)。
}

 

原创粉丝点击