2013-01-18 117 views
2

我一直在做一些關於機器間編碼/解碼和流媒體視頻的研究,我覺得好像我已經很好地把握了從文件到流的管道。我可以打開容器,解碼和抓取單個幀和音頻塊,我想象通過網絡移動這些幀就像發送字節數據一樣簡單(儘管是原始的和低效率的)。我不明白的是它的實際效果。只需將幀寫入某個圖像框並將聲音數據從聲卡緩衝區中刪除,實際上效果不佳。任何人都可以向我解釋在vlc播放器或Windows媒體播放器等程序中發生了什麼,它們允許它們將所有這些幀數據發送到屏幕而不破壞CPU和內存?只是一般的想法或一些高水平的文件將是偉大的。我甚至不知道從哪裏開始......視頻播放器如何將幀數據寫入屏幕?

謝謝!

+0

VLC是開源的不是嗎?你可以檢查:) –

+1

我只記得我們是如何用袖珍電腦上的mpeg lib做到的。就像你描述的那樣。我們使用了一個2D庫,打開了一個表面,將框架位複製到表面並將其翻轉到屏幕上。當然你可以提前緩衝幾幀,或者在幀之間進行內插等整齊的操作。但我不認爲在這一點上有更多的魔力,而不僅僅是將像素帶到屏幕上。 – dowhilefor

+0

繪製圖像並將音頻數據與音頻 - 視頻時間同步。 – 9dan

回答

1

如果您使用OpenGL,您可以創建紋理並不斷用新的幀數據替換它。這不是一個非常昂貴的操作。然後,你畫一個帶紋理的矩形到你的窗口。 glOrtho這裏是有用的投影。

在Windows中,如果您使用DirectX或Direct3D,同樣的事情將適用。你甚至可以獲得良好的性能blitting DIB部分(GDI):Fastest method for blitting from a pixel buffer into a device context

無論你如何繪製像素,你設置更新計時器,就這麼簡單。

爲了平穩運行,您需要在繪圖之前進行緩衝,以便磁盤(或網絡)和解碼延遲不會影響實時繪圖。即使視頻中最輕微的動作也能被人類感知。在定時器啓動時,您需要將圖像解碼到圖像緩衝區中並準備繪製。

+1

+1,但Windows中的bitblt會受到一個不幸的副作用,稱爲[撕裂](http://stackoverflow.com/questions/2448831/how-to-eliminate-tearing-from-animation)每當圖像更新被刷新。不幸的是,你必須使用Direct ...或更新的API來避免撕裂。 – MusiGenesis

+0

是的,我記得當我在切割牙齒時,在386 = =的程序集上編寫blit例程時撕掉了=)我認爲等待VSync的oldschool方法不適用...感謝您的評論。 – paddy

+0

不久前,我在寫一個玩家時遇到了這個問題。我提出了一個奇怪的解決方法,其中涉及使用DirectX來計時v-sync事件(DirectX公開)。您只需註冊一些事件即可獲得v-syncs的時序,因爲它們以接近完美的規律發生。在動畫引擎中,只要確保在任何一邊同步幾毫秒內都不渲染任何幀;相反,你會延遲到之後。它可以工作,但它非常愚蠢,因爲如果你要使用DirectX,你可能只需使用DirectX – MusiGenesis

1

我已經寫了許多播放器應用程序(適用於Windows),它們結合了視頻和音頻,並且需要兩者之間的精確同步。在Windows音頻中,您基本上準備緩衝區(它們只是音頻採樣值的數組),並將它們排隊到音頻子系統進行播放;子系統會在每個緩衝區完成回放時對您的應用程序進行回調,並且您的應用程序會使用每個回調來1)將下一幀渲染到屏幕,以及2)準備將下一個音頻塊排入音頻子系統。例如,假設您想要以每秒50幀的速度在內存中播放一些視頻幀,並與單聲道音頻,每個樣本2個字節和每秒44,100個樣本同步播放。這意味着您的音頻緩衝區需要882個樣本(44,100/50 = 882),因此每個緩衝區只是一個包含882個元素的短整型數組(2字節)。您至少需要兩個緩衝區,但在實踐中更多更好(與緩衝區的折衷是更多的緩衝區意味着以更長的啓動延遲和更大的內存佔用爲代價的更平滑的回放)。

視頻的幀需要以相同的方式「緩衝」,以便至少有一幀始終準備好進行渲染;將單個圖像傳輸到PC屏幕非常快,以至於它實際上是瞬間的,而不是您需要擔心的事情。唯一的問題是用任何方法提取或組成幀。這些方法需要至少足夠快以跟上播放速度,或者需要在播放之前進行緩衝,這也會導致較長的啓動延遲和較大的內存佔用量(這些問題對於視頻而言要差得多它們是用於音頻的,具有任何合理的分辨率)。

當應用程序開始播放時,它會將所有帶有音頻的緩衝區預加載並排隊等待播放;然後,它同時開始播放並將第一幀渲染到屏幕上。用戶看到第一幀並聽到音頻的前20 ms(20 ms = 1/50秒)。此時音頻子系統將回放從第一個緩衝區切換到第二個緩衝區,並對應用程序進行回調。然後,應用程序將第二幀渲染到屏幕上,並使用下一個可用的音頻塊填充第一個緩衝區,然後將第一個緩衝區再次排隊到音頻子系統。

只要應用程序有音頻和視頻數據可用來保持填充緩衝區和幀,此過程將繼續,並且您可以看到/聽到視頻。