directX--关于CSource和CSourceStream (谁调用了fillbuffer)

简介: <span style="font-family: 宋体; font-size: 9pt;">CSourceStream</span><span style="font-family: 宋体; font-size: 9pt;">类,是CSource类的OutputPin</span><span style="font-family: Verdana, Arial, Helvetica, san
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_ERRORABORThr, 0); 
                    return
 hr;
               }
         }
         if (com == CMD_RUN || com == CMD_PAUSE) { Reply(NOERROR); } 
         else if (com != CMD_STOP) { Reply((DWORDE_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();
}
相关文章
|
7月前
win32编程 -- GDI绘图操作
win32编程 -- GDI绘图操作
55 0
|
存储 数据可视化 NoSQL
Qt Creator的CDB调试器--使用技巧与解决调试很慢的心得,重点是Symbols Path设置
Qt Creator的CDB调试器--使用技巧与解决调试很慢的心得,重点是Symbols Path设置
2706 0
Qt Creator的CDB调试器--使用技巧与解决调试很慢的心得,重点是Symbols Path设置
|
编译器 C# 图形学
Unity与 DLL文件 ☀️| 怎样使用VC++生成一个DLL文件并调用!(包括 在VS 中调用 和 在Unity中调用)
📢前言 🎬通过VC 生成DLL文件 🎥在VS中生成DLL文件 🏳️‍🌈第一步:新建一个dll项目 🏳️‍🌈第二步:新建一个`.h头文件`和`.cpp源文件` 🏳️‍🌈第三步:在`.h头文件`和`.cpp源文件`中编写代码 🏳️‍🌈第四步:生成dll和lib文件 🎥在VS中进行调用DLL文件 🚩第一步:先来新建一个项目 🚩第二步:复制firstDLLTest.dll和firstDLLTest.lib文件和上一个项目的头文件firstDLLTest.h 🚩第三步:在新项目里面添加C++代码 🚩第四步:添加头文件firstDLLTest.h和firstDLLTest.
Unity与 DLL文件 ☀️| 怎样使用VC++生成一个DLL文件并调用!(包括 在VS 中调用 和 在Unity中调用)
|
计算机视觉
Qt实用技巧:win将ffmpeg、opengl、osg等各种库封装成qt模块,运行需要dll,增加自动拷贝运行库到exe目录执行脚本
Qt实用技巧:win将ffmpeg、opengl、osg等各种库封装成qt模块,运行需要dll,增加自动拷贝运行库到exe目录执行脚本
|
编译器 C语言
QT应用编程: Window系统下QT5创建DLL动态库并完成调用
QT应用编程: Window系统下QT5创建DLL动态库并完成调用
403 0
QT应用编程: Window系统下QT5创建DLL动态库并完成调用
|
IDE 开发工具 Windows
QT应用编程: windows下QT调用COM组件并集成到QT界面
QT应用编程: windows下QT调用COM组件并集成到QT界面
558 0
QT应用编程: windows下QT调用COM组件并集成到QT界面
|
编解码 开发工具 Windows
产品百科 | RTC Windows SDK 如何调用屏幕分享接口
阿里云 RTC SDK 为您提供屏幕分享使用的接口方法,通过本文档您可以了解实现的具体调用流程。
产品百科 | RTC Windows SDK 如何调用屏幕分享接口
|
编解码 监控 图形学
unity设置程序
unity设置程序 Application.runInBackground 后台运行 Application.dataPath 数据路径 Application.persistentDataPath 持久数据路径 Application.
1021 0