2012-08-16 103 views
1

我有一個問題,似乎是非常普遍的谷歌,但它並沒有幫助我。當我的應用程序嘗試關閉所有內容時,釋放對象之前調用的最後一個函數是IMediaControl :: stop。有信號時一切正常。但是,當我沒有信號啓動應用程序(或在應用程序工作時終止它)程序從不停止()返回。更重要的是,如果我在已經掛起的時候提供信號,那麼一切都會恢復正常,程序懸空並正確退出。IMediaControl ::停止掛起時,沒有信號

這是我的代碼中的主要部分:由某些線程等待對方

hr = connectFilters(pGraph, pCaptureDevice, AUDIO_INPUT_DEVICE_PIN_NAME, 
pAnalyzerFilter, SPDIF_ANAL_FILTER_PIN_NAME); 
if(SUCCEEDED(hr)) 
{ 
    // run the graph 
    hr = pControl->Run(); 
    if(SUCCEEDED(hr)) 
    {   
     // wait for UI thread to finish 
     pFilterObject->WaitForThread(); 

     // stop the graph and exit 
     pControl->Stop(); 
    } 
} 

releaseObjects(); 
return 0; 

谷歌暗示死鎖(實際上它是)。 UI線程似乎不是問題,因爲我沒有基於這個應用程序的DLL,而且問題是一樣的。

非常感謝提前,

日食

編輯

我只有兩個過濾器:源和改造。這個問題肯定是在轉換過濾器中,因爲程序在沒有它的情況下運行良好。它會成爲未釋放緩衝區或樣本的問題嗎?我不確切知道DirectShow的工作原理,但如果沒有信號,可能還需要做一些額外的事情?

編輯2

我在谷歌發現,有人通過停止圖形之前停止源過濾器解決了這個問題。我也一樣,它也掛起......我用它來獲取源過濾:

hr = pFG2->AddSourceFilterForMoniker(pMoniker, pContext, wszName, &pSource); 
*ppF = pSource; 
(*ppF)->AddRef(); 

當我連接與調試它說,它無法顯示的代碼,所以我認爲這是在MS代碼某處。即使我評論我的函數處理IMediaSamples它仍然掛起。現在我用完了那些錯誤的想法。我也嘗試以不同的方式停止和刪除圖表中的過濾器。

+0

這是僵局。其中一個過濾器會讓你失望,你需要準確找出哪一個。 – 2012-08-16 10:01:20

+0

@Roman R.你能說我該怎麼檢查它?或者有什麼可能是錯的?DirectShow不是我的一杯茶,所以我甚至不知道去哪裏看... – eclipse 2012-08-16 10:09:03

+0

從圖中刪除過濾器,直到它開始正常工作。因爲這是一些過濾器失敗的原因,所以裝配者首先在那裏很重要,圖形的拓撲結構是什麼。 – 2012-08-16 10:13:07

回答

0

我試圖將來自後臺線程的傳入圖像發送到WPF窗口時遇到同樣的問題。一切都很好,直到我試圖停止mediacontrol或釋放任何東西。

問題在於調度程序調用該操作以將其傳送到UI線程。我暫時註釋了這個電話,它阻止了視頻在屏幕上顯示出來,但我可以隨時在採樣器中斷開,並看到它仍然在運行。

跨線程手動分離圖像是需要發生的。爲了解決這個問題,我在窗口中創建了一個dispatchertimer,將它的間隔設置爲1ms,它的回調函數進行UI更新,然後在抓取器,有buffercb事件將幀保存到獨立變量並啓用計時器。

這裏是什麼我結束了簡單的介紹一下:

InteropBitmap newbmp; 
    DispatcherTimer refreshTimer; 
    refreshTimer = new DispatcherTimer(TimeSpan.FromMilliseconds(1), DispatcherPriority.Render, ontimer, this.Dispatcher); 
    videoSampleCB.newframearrived += capGrabber_NewFrameArrived; 

    void capGrabber_NewFrameArrived(object sender, EventArgs e) 
    { 
     newbmp = videoSampleCB.newimage; 
     refreshTimer.IsEnabled = true; 
    } 
    void ontimerobject sender, EventArgs e) 
    { 
     this.BitmapSource = newbmp; 
     refreshTimer.IsEnabled = false; 
    } 
class VideoSampleGrabberCallBack : ISampleGrabberCB 
{ 
     event eventhandler newframearrived; 

     public InteropImage newimage; 
     public int BufferCB(double sampleTime, IntPtr buffer, int bufferLen) 
     { 
      newimage = ... 
      newframearrived(this, eventargs.empty); 
     } 
}