2012-04-11 29 views
2

這一個真的讓我拉我的頭髮。我寫了一個從CTransformFilter派生的DirectShow轉換過濾器。我從CTransformInputPin派生了一個輸入引腳。當我的輸入引腳的Receive方法被調用時,它將IMediaSample的演示時間記錄到一個文件中。這一切都正常工作,直到我停止圖形並再次啓動(我正在使用MS的graphedt)。大多數時候,再次運行時,沒有問題。但是,每停止一次,我就停止一次,然後再次運行圖表,開始顯示時間爲負值。隨着圖形的運行,它最終增加到零,並且上升到零以上,但它始終趕不上流時間,結果是流時間仍然是每個樣本的展示開始時間的顯着頭部。在DirectShow中的負面演示時間

我用羅技攝像頭Pro 9000和羅技C600攝像頭觀察到了這一點,但沒有與Winbook相機,所以我想知道這是否是羅技問題。在停止並再次運行之後,是否有其他人在視頻IMediaSamples上看到否定呈現時間? (我看過的IMediaSample預卷標誌:它始終是S_FALSE)

UPDATE:

我已經覆蓋CTransformFilter的(實際上,CBaseFilter的),Run方法與此:

STDMETHODIMP MyTransformFilter::Run(REFERENCE_TIME tStart) 
{ 
    char buff[1000]; 
    REFERENCE_TIME rTime; 

    m_pClock->GetTime(&rTime); 
    sprintf(buff, "Run tstart = %lld, rTime = %lld", tStart, rTime); 
    Trace(buff); // open my log file, add buff, close my log file 
    return CTransformFilter::Run(tStart); 
} 

我用graphedt來啓動圖形,運行10秒,暫停5秒,然後重新開始。這裏的輸出:

Run tstart = 7855978550000, rTime = 7855978450000 
Run tstart = 7856030610000, rTime = 7856126960000 

兩次通過運行相差5.2秒(大約我暫停的時間)。兩個參考時鐘時間相差14.6秒(約兩次調用之間的總時間)。除了輕微的增加,過濾器圖形管理器增加了傳遞給Run的時間(在第一次調用中爲10 mS),我希望這些在每次調用Run時都幾乎相同。相反,在第二次通話中傳遞給Run的時間比參考時鐘落後大約10秒。我非常感謝幫助理解爲什麼在第二次調用中傳遞給Run的時間與在第二次調用中由參考時鐘返回的時間沒有(幾乎)相同。

更新2:

問題似乎是在羅技版本13.31.1044.0驅動程序。請參閱下面的答案。

回答

1

經過相當多的實驗後,我得出結論,這個問題很可能是羅技13.31.1044.0相機驅動特有的。使用早期的Logitech 12.10.1110驅動程序,使用Winbook DC-6120相機(及其驅動程序)和Chicony USB 2.0相機(及其驅動程序),我無法使問題重演。由於沒有明顯的原因,羅技13驅動程序會以負面展示時間開始提供樣本,每隔大約十分之一時間一次,包括它的圖形會重新啓動(即,在我停止繪圖後再重新啓動它之後) )。將這些時間與流時間進行比較並不能提供MSDN描述的樣本是否計劃在過去,現在或將來顯示的信息,因爲流時間似乎沒有受到影響。在每次重新啓動時,無論相機的演示時間是從何時開始,流時間都會從零開始,正如您所期望的那樣。 (請注意,Logitech採用RGB24子流式傳輸,沒有壓縮幀。)

我正在研究一種多線程傳遞過濾器,它可能能夠根據流時間重新分配演示時間值,並且足夠快地「僞造」正確的值,並且如果我得到有意義的結果將在這裏發佈。此外,我會記錄我的測試並將它們傳達給Logitech。如果他們迴應,我也會在這裏發佈。

如果其他人正在使用使用上述驅動程序的Logitech產品(或者觀察我描述的行爲),請在此處發表評論。我很樂意向您發送我的過濾器副本,記錄時間,幀數等。我們可能能夠一起尋找解決這個問題的好方法。

UPDATE

通過寫一個最簡單的變換分析過濾器,我可以(一個簡單的拷貝輸入IMediaSample到輸出的負面形象),我已經能夠重現這種行爲相當一致。每五或六次重新開始一次包含Camera-> Filter-> Renderer的圖形,前幾個採樣的負幀時間會在流時間之後傳遞,並且永遠不會趕上。 (也就是說,流時間永遠在樣本的展示時間之前)。再次,這從來沒有發生過其他相機,也沒有舊的羅技驅動程序。

以下是有趣的部分:如果我在過濾器的Run方法中添加一些延遲(在覆蓋CTransformFilter :: Run之後),問題就消失了。代碼如下:

STDMETHODIMP DLPassThrough::Run(REFERENCE_TIME tStart) 
{ 
    Sleep(10); 

    return CTransformFilter::Run(tStart); 
} 

我可以通過註釋或恢復「睡眠(10)」調用來解決問題。我所能猜到的只是相機代碼是多線程的,需要一段時間,在總是處於「運行」呼叫之前的「暫停」呼叫和接下來的「運行」呼叫之間需要一段時間,以清理它正在做的事情。根據我對MSDN文檔的理解,圖形管理器將在渲染器,過濾器和攝像機上調用「暫停」,然後返回並在渲染器,過濾器和攝像機上調用「運行」。我相信每個調用都是同步的,但是如果攝像機代碼是多線程的,那麼當它的「運行」方法被調用時,它可能仍然在處理來自圖形管理器的最近的「暫停」調用。通過在我的過濾器的「運行」方法中添加一個延遲,最近一次對相機的「暫停」呼叫和下一次對相機的「運行」呼叫之間有較長的延遲。

還在等待/希望聽到羅技對此的迴應。同時,我編寫了一個多線程就地轉換過濾器,它簡單地添加了對其最新樣本的引用,用當前流時間替換了其呈現時間,並將其保存爲下一個過濾器,以便在下一次下游時使用過濾器準備好接收它,然後返回等待下一個進入的樣本。 (如果在下游過濾器取下一個之前有多個樣品進入,則先前的樣品將被釋放,並替換爲最新的樣品。)目前爲止似乎正在工作。

更新2

這裏是羅技的回答是:

我想告訴你,該設備是由主要爲視頻流IM應用程序,而不是對軟件開發主題工作或過濾器。

3

負面時間不是什麼大不了的事。從本質上講,這意味着「媒體樣本應該在不久前提出」。那麼你可能會認爲媒體樣本可能會被丟棄?有時候這是真實的,有時候不是這樣:設想一系列時間壓縮的視頻幀,其中有一個關鍵幀,後面跟着10個三角形幀。你希望演示從第5幀開始,你怎麼做到的?您必須從關鍵幀中穿過,以便解碼器可以從拼接點有效地進行解碼,否則它不能以delta幀開始。無論幀是否遲到,解碼器都可能傳送輸出幀,這就是這些幀最終到達你的方式。

導致負面時間的另一種情況是由線程的競爭狀態,流和控制引起的。捕捉線程可能正在啓動其操作,但沒有基礎的「開始時間」。

+0

我會明白,如果重新啓動的圖上的流時間沒有重新開始在零。每次停止並開始圖形時,流時間從零開始。但是,大約12次中的一次,捕捉過濾器(當它是羅技相機時)在此之前大幅啓動(-15,000,000或更多REFERENCE_TIME單位)。如果沒有別的,我希望捕獲過濾器對其呈現時間和圖形的流時間之間的關係保持一致。 – 2012-04-11 16:56:05

+0

-15M是-1.5秒 - 相當多但仍然屬於上面的第二段。 – 2012-04-11 17:23:08

+0

有什麼我可以做的,以糾正這一點?我試圖將演示時間與流時間進行比較,以便決定是否放棄樣本而不是在我的變換過濾器中處理它。當捕獲過濾器以負值開始時,它始終保持在流組的後面,讓我無法(我知道)決定該樣本是否遠遠落後於我應該放棄的流時間它。 – 2012-04-11 17:43:38