1. 程式人生 > >音視訊同步之系統中的快取

音視訊同步之系統中的快取

前言

這幾天做錄屏軟體,生成的h264檔案,用vlc播放是音視訊同步的,但是用自己寫的播放器,總是差那麼一點點。從感知上來看大概0.2s~0.4s之間。
原始視訊是音視訊同步的。
就是當人快速說話的時候,口型跟聲音是對上的。

音視訊同步的兩種方式

前提:音訊幀和視訊幀都必須有自己的時間戳。
沒有時間戳:
如果沒有這個前提。音訊還好說,設定好音訊播放參數之後持續的播就是了。
視訊幀就麻煩了,要麼以固定幀率播放,要麼就播放的忽快忽慢。
沒有時間戳的不考慮,這是初學者的做法。

以音訊的時間戳為基準

也就是將視訊同步到音訊上。這種方式聲音是流暢播放的。
應用場景:絕大部分視訊播放器。

以視訊的時間戳為基準

視訊幀以自己的節奏播放(緩衝區中未播放的幀多了就播放的快些,反之就播慢點;或者是固定幀率);
缺點是:為了音視訊同步,聲音會卡頓。
應用場景:直播類接收端播放器。

以外部時鐘為基準

選擇一個外部時鐘為基準,視訊和音訊的播放速度都以該時鐘為標準。

音視訊同步的標準

從感知上來看(這是我的感知,不是標準的)。
先約定一些資料:
Tv0:當前顯示視訊幀的時間戳;
Ta0:當前顯示的視訊幀應當播放的音訊幀的時間戳;
Ta1:當前顯示的視訊幀實際播放的音訊幀的時間戳;
如果 |Ta0-Ta1| < 0.1s,可以認為是同步的。
如果 |Ta0-Ta1| >= 0.3s,對話的時候就感覺很明顯對不上了。

寫到這裡感覺跑題了,這篇blog主題不是寫音視訊同步,而是寫音視訊同步一個被忽視的地方

音視訊同步,網上文章很多。自己找,不解釋。

下面這張圖片是聲音在系統中的播放
這裡寫圖片描述
幾個名詞的描述:
T0:當前正在播放的聲音的時刻
T1-T0:當前系統快取中還未播放的音訊資料所需的時間
T2-T1:每次音訊回撥函式讀取的資料播放的時間
Buf0: 系統中還未播放的資料
Buf1: 每次音訊回撥函式讀取的資料

當播放器將Buf0播放完了,而Buf1還沒有讀進來。那麼現在就沒聲了。
Buf1的大小,應該是按系統來的。我用Qt在win下,每次讀取16384個byte。
16383個位元組:
如果是11025hz,雙聲道,16bit,那麼聲音持續時間大概是0.371519s。
如果是44100hz,雙聲道,16bit,那麼聲音持續時間大概是0.0928798s。

一般情況下Buf0的大小<=BUf1。但是沒有絕對的。也許它就是想多讀取一點資料。

在我修改了播放的取樣率之後,QAudioOutput::bufferSize()也跟著改變了,但是我沒感覺出來這裡改變有什麼影響。
在我修改了播放的取樣率之後,每次讀取的位元組數16384沒有改變。

其實我一直想改變Buf1的大小,但是沒找到方法。

總結

這個地方的細節很容易忽略掉。之前寫播放器,沒注意掉這麼一點差距;當自己編碼也要處理的時候,這個問題就冒出來了。
其實我是不想用44100的取樣率的,因為資料量是11025的4倍。
但是因為這裡音視訊同步的時間差,不得不採用了44100的取樣率。