zoukankan      html  css  js  c++  java
  • 关于CSource和CSourceStream .

    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();//你可以重载这个函数,可以在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 IMemInputPin::Receive method on the input pin.  //Receive can block if the IMemInputPin::ReceiveCanBlock 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 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);}


    这个类要实现就是这个函数了,注意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在实际的应用是怎么使用的。
  • 相关阅读:
    UDK Stat命令
    绝地求生-全军出击手游
    UE3中的时间
    Git原理与命令大全
    【SpringCloud】Spring Cloud Alibaba 之 Nacos注册中心(二十七)
    【SpringCloud】Spring Cloud Alibaba 及 Nacos介绍(二十六)
    【Web】Keepalived+Nginx 实现高可用集群
    【SpringCloud】Spring Cloud Sleuth + Zipkin + RabbitMQ 集成(二十五)
    【SpringCloud】Spring Cloud Sleuth 日志跟踪(二十六)
    Spring框架学习笔记(5)——Spring Boot创建与使用
  • 原文地址:https://www.cnblogs.com/wqj1212/p/2442380.html
Copyright © 2011-2022 走看看