我正在开发一个DirectShow过滤器,它接收输入样本并将它们转换为修改后的输出样本,但输入和输出样本之间没有一对一的对应关系,所以CTransformFilter似乎不是这样的去吧。
编写此代码的最佳方法似乎是使用CBaseFilter,CBaseInputPin和CBaseOutputPin编写滤波器,其中样本在输入引脚上接收并由工作线程处理,工作线程从输出引脚创建并传送新样本。工作线程在开始工作之前复制输入样本数据,以便我的过滤器不必在输入CBaseInputPin :: Receive调用之外维护对输入样本的引用。
在这种情况下,保持线程安全和避免死锁的最佳做法是什么?输入和输出引脚是否应该共享相同的流锁定,还是应该为每个流式传输操作设置流式锁定?缓冲区分配,样本传递和其他输出引脚操作是否需要保持流式锁定和/或过滤器锁定?任何类似的示例代码?在这种情况下还有其他需要注意的问题吗?
DirectShow基类包含对CBaseOutputPin :: Deliver和CBaseOutputPin :: GetDeliveryBuffer的可怕注释,我不完全理解(粘贴在下面)。
/* Deliver a filled-in sample to the connected input pin. NOTE the object must
have locked itself before calling us otherwise we may get halfway through
executing this method only to find the filter graph has got in and
disconnected us from the input pin. If the filter has no worker threads
then the lock is best applied on Receive(), otherwise it should be done
when the worker thread is ready to deliver. There is a wee snag to worker
threads that this shows up. The worker thread must lock the object when
it is ready to deliver a sample, but it may have to wait until a state
change has completed, but that may never complete because the state change
is waiting for the worker thread to complete. The way to handle this is for
the state change code to grab the critical section, then set an abort event
for the worker thread, then release the critical section and wait for the
worker thread to see the event we set and then signal that it has finished
(with another event). At which point the state change code can complete */
答案 0 :(得分:2)
您在\Samples\multimedia\directshow\filters
的Windows SDK中有一些示例,早期版本的SDK甚至更多。这可能是您可以检查锁定实践的最佳示例代码。
过滤器和引脚通常使用共享的关键部分来确保线程安全。例如,CTransformFilter::m_csFilter保护过滤器的状态数据,而不仅仅是部分,但引脚也使用该部分。附加部分还用于序列化流请求(推送样本,发送EOS通知)。
您的过滤器可能正在使用状态关键部分,或者您也可以使用其他同步对象(部分,读写器锁或互斥锁),以避免关键部分可能被基类锁定的死锁。
常规建议适用:为避免死锁,您应确保锁定顺序的设计方式是,如果A部分可以锁定在已经锁定B部分的线程上,则只应锁定B [在其他线程上]没有A上的现有锁定,因此不会出现死锁。
通常,您有两种情况,大多数用例都属于这种情况: