轉載自:http://blog.csdn.net/soliddream66/article/details/5353960
問題背景
錄音播音實際需求
1、隨時終止
2、錄音并非文件,而是形成rtp發送
3、播音并非源于文件,而是源于rtp
因此Waveform audio使用的buffer較小,不斷的裝載/發送 buffer,終止的時候Reset并且close.
大致如下調用的循環
錄音
waveInUnprepareHeader
waveInPrepareHeader
waveInAddBuffer
播音
waveOutUnprepareHeader
waveOutPrepareHeader
waveOutWrite
循環周期40ms,我采用的是回調函數。問題是有時候調用waveInReset/waveOutReset會形成死鎖,調用waveInReset/waveOutReset的線程與回調函數所在的線程死鎖在一塊了。
原因分析
這方面網上有文章提到,就是調用waveInReset/waveOutReset的同時調用了錄音/播音循環調用的某個函數會形成死鎖。我再稍作解釋下,我們知道buffer滿了或是調用Reset都會觸發消息(回調函數方式的話就是MM_WOM_DONE/MM_WIM_DATA),由于調用waveInReset/waveOutReset所在的線程,與回調函數所在的線程不是一個線程,因此很容易撞車,也就是說,你調用reset的時候,另一個線程正好在處理MM_WOM_DONE/MM_WIM_DATA,于是就這樣死鎖了。
解決方案
方案一
先加上標記(假設標記bReset:bool),令bReset為true;
標記作用如下
if(!bReset)
{
錄音
waveInUnprepareHeader
waveInPrepareHeader
waveInAddBuffer
播音
waveOutUnprepareHeader
waveOutPrepareHeader
waveOutWrite
}
延時調用waveInReset/waveOutReset,延時時間長度以循環周期為妙,我這個例子中也就是采用40ms。
當然也可以采用臨界保護。
方案二
換一個角度去考慮問題,之所以死鎖,是因為兩個線程沖突了的緣故,所以可以建立一個線程
錄音
waveInUnprepareHeader
waveInPrepareHeader
waveInAddBuffer
播音
waveOutUnprepareHeader
waveOutPrepareHeader
waveOutWrite
與waveInReset/waveOutReset都放到這個線程去處理,自然不會發生死鎖了。