王小根,趙海武,李國平,滕國偉,王國中
(上海大學通信與信息工程學院,上海 200072)
視頻編碼中每一幀的編碼數據通常是不一樣的,特別是在利用視頻序列的時域相關性進行壓縮編碼時,采用幀內模式編碼的幀和采用幀間模式編碼的幀的編碼數據量會差別很大。而信道的數據傳輸率經常是穩定而有限的,或者說從傳輸的角度,希望視頻編碼數據的速率越穩定越好,最好是恒定碼率。因此,利用緩沖區對視頻編碼數據的速率進行平滑是必須的。在 MPEG-2[1]和 AVS[2]等標準中,都規定了碼流緩沖區校驗模型,來規范碼流的緩沖。
緩沖區的本質是用延遲來換取碼率的穩定,因為緩沖必然會帶來延遲。緩沖的數據越多,碼率越穩定,延遲也越大。然而,在電視廣播等應用中延遲是不能太大的,當然,在其他應用中延遲可以很大,但也是有限制的。在延遲有限,也即緩沖區有限的情況下,就需要對每一幀的編碼數據量進行控制,以達到碼率穩定的目的。因此,緩沖和延遲最終需要用碼率控制來實現[3]。
本文對MPEG-2和AVS的碼流緩沖模型進行了比較詳細的分析。
首先,討論解碼器何時開始解碼的問題。解碼器開始解碼的時刻和碼流中的bbv_delay,bbv_buffer_size以及low_delay等3個信息相關。
當bbv_delay!=0xFFFF時,某一幀(包括開始解碼的第一幀)的解碼時刻等于該幀的編碼數據進入緩沖區的時刻加上該幀的bbv_delay(bbv_delay出現在每一幀的頭部),這是最常見的情況。
當bbv_delay==0xFFFF時,第一幀的解碼時刻是緩沖區被充滿的時刻。緩沖區被充滿的時間由bbv_buffer_size和bit_rate共同確定。事實上,緩沖區被充滿的時間等于二者的商。顯然,這種情況下,從第一幀的編碼數據開始進入緩沖區到第一幀被解碼的延遲是不確定的,它和第一幀以及后續若干幀的編碼數據量有關。編碼器要控制每一幀的編碼數據量,以保證開始解碼后緩沖區不會發生上溢或下溢。
當low_delay==1時(此時bbv_delay不應等于0xFFFF),在每一幀的頭部會包含緩沖區檢測次數信息bbv_check_times。解碼器會按照規定的時間間隔檢測緩沖區,檢測bbv_check_times+1次后解碼器開始解碼。通常bbv_check_times的值是0,即解碼器只檢查緩沖區1次,這和low_delay==0時是一樣的。
其次,討論開始解碼后每一幀的解碼時刻,也就是解碼時間間隔。
解碼時間間隔和解碼器的輸出是密切相關的。解碼器一旦開始輸出解碼圖像,就必須連續輸出解碼圖像,直到解碼過程結束。要想做到連續不間斷地輸出解碼圖像,就必須在輸出一個解碼圖像的同時解碼下一個圖像。因此,解碼器輸出圖像的時間間隔就是解碼圖像的時間間隔。假設第n幀圖像的解碼時刻是tn,輸出(或者說回放)第n幀圖像的時間是in,那么第n+1幀圖像的解碼時刻

通常情況下,輸出一幀的時間就是幀速率的倒數,也稱幀時間間隔。輸出一場的時間就是場速率的倒數,也稱場時間間隔。但是,由于存在3∶2下拉等幀速率的轉換,使得輸出一幀圖像(這里指的是碼流中的一幀,以幀頭開始,到下一幀的幀頭結束)的時間顯得有些復雜。
在AVS標準和MPEG-2標準中,圖像輸出顯示的時間和序列頭中的progressive_sequence(PSeq),progressive_frame(PF)以及幀頭中的 picture_structure(PStr),top_field_first(TFF),repeat_first_field(RFF)等幾個參數有關。為了讀者參考方便,本文將它們之間的關系整理如表1所示。其中NA表示不起作用,第一列是progressive_sequence和progressive_frame兩個參數的所有可能組合,最后一列是圖像的輸出情況。輸出一幀所需的時間是幀時間間隔,在數值上等于幀速率的倒數,輸出一場所需的時間是場時間間隔,在數值上等于場速率倒數。

表1 圖像輸出顯示的時間和序列頭中參數關系
當low_delay==1時,解碼時間間隔更加復雜一些,因為碼流中可能存在大圖像。所謂大圖像,就是圖像頭中的bbv_check_times不是0的圖像。大圖像的檢測緩沖區時間間隔是幀速率的倒數,其他圖像的解碼時間間隔和low_delay==0時一樣。所謂的“檢測緩沖區”,實際上就是“嘗試解碼”。
當解碼時刻到來時,被解碼圖像的所有編碼數據是瞬時移出碼流緩沖區的。一幀圖像的編碼數據包含的內容,在AVS和MPEG-2標準中有明確的定義,這里不再贅述。第n幀圖像的編碼數據量用fn來表示。
顯然,對于一個視頻序列,每一幀的編碼數據是按照編碼順序進入緩沖區的。第n幀的編碼數據進入緩沖區的時間記為en。解碼器把收到第n幀開始碼后第一個比特的時刻記錄為en,它和編碼器把第n幀開始碼后第一個比特寫入碼流的時刻間隔一個固定的時間,這個時間是碼流通過信道產生的延遲。假設碼流通過信道產生的延遲是固定的,以此實現編碼器和解碼器的同步。
為方便起見,把第n幀頭部的bbv_delay所表示的時間記為dn。解碼器根據en和dn確定第一幀的解碼時刻,即

因為解碼器可能從碼流的中間某些位置開始解碼,所以上式中的序號仍然用n,而不是1。當bbv_delay==0xFFFF時,第一幀的解碼時刻是碼流緩沖區充滿的時刻,這時(2)可以表示為

式中:S是碼流緩沖區的容量,R是碼率,這兩個參數都是編碼器在序列頭中設定的。
第一幀的解碼時刻確定以后,根據式(1)確定后續各幀的解碼時刻,再根據各幀的解碼時刻,和各幀的延遲dn,倒推出各幀數據進入緩沖區的時刻,即

這是確定編碼數據進入緩沖區的時刻的過程。之所以這么復雜,是因為編碼數據進入緩沖區的速率是可變的。即不總是以序列頭中設置的速率R進入緩沖區。所以,無法根據fn和R來遞推每一幀的編碼數據進入緩沖區的時刻。
式(3)適用于解碼器。對于編碼器,具有一定的靈活性,即編碼器可以在滿足式(3)的前提下,調整dn和en。編碼器調整dn和en,是通過調整第n-1幀的編碼數據進入緩沖區的速率來實現的。第n-1幀的編碼數據進入緩沖區的速率高,就會早一些結束,從而第n幀的編碼數據就可以早一些開始,反之亦然。所以,這里有一個假設,即第n-1幀數據結束進入緩沖區的時刻就是第n幀數據開始進入緩沖區的時刻。即

式中:τn-1是第 n-1 幀進入緩沖區所需的時間。
當某一幀的解碼時刻到來時,如果該幀的編碼數據沒有完全進入緩沖區,則緩沖區發生下溢;如果在某個時刻,緩沖區沒有足夠的空間存放需要進入緩沖區的編碼數據,則緩沖區發生上溢。
通常情況下,編碼器必須保證緩沖區不發生下溢和上溢。當bbv_delay==0xFFFF時,緩沖區不存在上溢,因為緩沖區被充滿以后,編碼數據可以等待,暫時不進入緩沖區。當low_delay==1時,如果某一幀的編碼數據量太大,造成該幀的編碼數據無法在按照式(1)遞推的解碼時刻完全進入緩沖區,則編碼器可以將其設置成大圖像,其實就是讓解碼器進行額外的等待,以保證緩沖區不發生下溢。即使如此,緩沖區還是可能發生下溢,例如當某一幀的編碼數據量超過緩沖區的容量時,無論等待多少時間,緩沖區都會發生下溢。雖然當low_delay==1時,緩沖區下溢是允許的,但是會給解碼帶來很大的麻煩,而且標準中沒有規定緩沖區發生下溢時解碼器的處理方法,編碼器也就不知道解碼器會如何處理。因此,本文建議編碼器還是要避免緩沖區發生下溢。
編碼器可以通過控制每一幀的編碼數據量、控制每一幀的編碼數據進入緩沖區的時刻和設置合適的延遲來保證緩沖區不發生溢出。
首先考慮最常見的情況,即bbv_delay的值不是0xFFFF且low_delay的值不是1。如圖1所示(此時可能存在幀率轉換,可能是CBR,也可能是VBR)。

圖1 緩沖區模型示意圖
本節的目的是導出保證緩沖區不發生溢出的條件。
當第n-1幀編碼結束時,根據解碼時刻的遞推關系,可以確定第n幀的解碼時刻tn,即tn是已知的。根據編碼數據進入緩沖區的假設式(4),第n幀編碼數據開始進入緩沖區的時刻en也是已知的。根據(2)和(3),第n幀的延遲dn也是已知的。
由圖1可知,第n幀編碼數據在其解碼時刻到來之前全部進入緩沖區(即緩沖區不下溢)的充分必要條件是

對于解碼器,式(5)中的所有量都是已知的,可以通過上式檢驗緩沖區是否發生下溢。
緩沖區不上溢的條件是,在第n幀(n為任意值)的編碼數據被移出緩沖區之前,進入緩沖區的數據總量不超過緩沖區的容量S。從第n幀數據進入緩沖區到移出緩沖區的時間是dn,在這段時間之內,可能有若干幀數據進入緩沖區。然而,在編碼第n幀的時候,編碼器無法知道后續尚未編碼的幀的數據量。但是,編碼器知道后續各幀數據進入緩沖區的速率都小于等于R。所以,編碼器只需保證以下條件即可

但是,如前所述,當第n-1幀編碼結束時,dn已經確定了,假設編碼器在編碼第n-1幀時已經保證了dn<D,編碼第n幀需要做的,是保證dn+1<D。

當dn和D比較接近時,式(8)的右邊是一個正值,這就要求傳送第n幀數據的時間不能太短。
在CBR時,編碼器必須保證第n幀的數據量

在VBR時,編碼器可以通過降低第n幀數據進入緩沖區的速率來使式(8)成立,也可以像CBR時那樣通過控制fn來使式(8)成立。如圖2所示。其中rn表示第n幀數據進入緩沖區的速率。

圖2 VBR時為防止緩沖區上溢所做的處理
需要注意的是,在CBR時,式(8)或(9)是緩沖區不上溢的充分必要條件,在VBR時,式(8)是充分但非必要條件。如果式(8)不成立,編碼器可以通過降低后續各幀編碼數據進入緩沖區的速率使緩沖區不上溢。但是,既然總數據量不大于S,編碼器總是可以將這些數據放在長度不超過D的時間區間上傳送(即強制第n幀數據延后至tn-D時再進入緩沖區),以保證式(8)成立。
當bbv_delay==0xFFFF時,AVS標準規定:如果BBV緩沖區沒有充滿,數據以速率R輸入緩沖區;如果BBV緩沖區充滿,則數據不能進入該緩沖區直到緩沖區中的部分數據被移出。因此,當bbv_delay==0xFFFF時,緩沖區不存在上溢的問題。
當bbv_delay==0xFFFF時,視頻序列的第1幀圖像的起始碼前的所有數據和這個起始碼輸入BBV緩沖區后,數據繼續輸入BBV緩沖區直到緩沖區充滿,并在這個時間開始解碼處理。此時,第1幀的延遲可以看成是D=S/R,這是延遲的最大值,不妨把這種緩沖模型稱為“高延遲模型”。后續各幀的解碼時間依然按照式(1)來確定。
在高延遲模型中,只需保證緩沖區不發生下溢。緩沖區下溢是有可能發生的,比如某一幀的編碼數據量大于緩沖區的容量,當該幀的解碼時刻到來時,其數據不可能完全進入緩沖區,就會發生下溢。即使每一幀的編碼數據量都小于緩沖區的容量,也可能發生緩沖區下溢,比如出現連續兩幀的編碼數據量都很大(大到接近緩沖區的容量)的時候。當前一幀的數據被移出緩沖區時,后一幀的數據只有一小部分進入了緩沖區,其余部分在兩幀的解碼時間間隔內無法全部進入緩沖區。
準確的說,保證第n幀編碼數據能夠及時全部進入緩沖區的充分必要條件是

當low_delay=1時,是低延遲模式。此時每一幀的編碼數據頭部存在BbvCheckTimes,在從緩沖區移出該幀數據解碼之前,解碼器要檢查緩沖區BbvCheckTimes+1次。通常BbvCheckTimes=0,即解碼器只需檢查緩沖區1次,這和low_delay==0時是一樣的,如果所有幀都是只需檢查緩沖區1次,那整個碼流就和low_delay==0時是一樣的。這里所說的“檢查緩沖區”的意思是“嘗試解碼”,檢查緩沖區的時刻就是解碼時刻,檢查緩沖區的時間間隔就是解碼時間間隔。
緩沖區下溢通常是由于大圖像的編碼數據量太大造成的。然而,并非某一幀的編碼數據量大了就一定會發生下溢,根據fn<R×dn,可知是否下溢和該幀的延遲有關。而延遲又是由該幀的解碼時刻和該幀數據進入緩沖區的時刻共同確定的,該幀編碼數據進入緩沖區的時刻無法提前,因為在保證緩沖區不上溢的前提下,已經是盡量早的進入緩沖區了。所以,發生緩沖區下溢的原因是該幀的解碼時刻過早,而該幀的解碼時刻是按照tn+1=tn+in遞推出來的,各幀的顯示時間是確定的,最終決定該幀的解碼時刻的是第1幀的解碼時刻。
實際上,解碼的第一幀在碼流中是隨機的。在低延遲模式下,編碼器會將每一幀的延遲時間盡量設得短,以達到讓解碼器盡早解碼,降低延遲的目的。這正是低延遲模式的含義。
當按照通常的設置(BbvCheckTimes=0)緩沖區發生下溢時,編碼器通過將發生下溢的幀設置成大圖像,告知解碼器等待一段時間再解碼。但是,額外的等待時間不一定能夠保證不發生下溢,如果大圖像的數據量太大,超過緩沖區的容量,或者需等待的時間超過某種上限,則只能放棄大圖像。這時,編碼器設置的等待時間不足以讓大圖像的全部數據到達。解碼器在檢測緩沖區指定的次數之后強行移出大圖像。AVS標準沒有詳細規定在緩沖區發生下溢時的處理方法。編碼器可以將大圖像數據全部寫入碼流,也可以只寫入一部分。解碼器可以不解碼大圖像,也可以強行解碼并輸出不完整的解碼圖像。建議編碼器避免緩沖區發生下溢,以避免解碼器出現不可控的輸出。
這里有兩個問題需要解決:1)等待大圖像解碼的這段時間解碼器如何輸出?2)大圖像解碼后解碼器如何輸出?AVS標準并未明確回答這兩個問題。但是,有一點是肯定的,即解碼器必須按照指定的速率持續輸出解碼圖像。根據這個原則,等待大圖像解碼的時候解碼器應當有輸出,大圖像解碼后,輸出的速率不能提高。為了保持同步,編碼器應當丟棄若干幀,否則會造成不同步。
上述3種緩沖模型對應著不同的應用。bbv_delay值不是0xFFFF且low_delay值不是1的模型是最常見的,主要應用于數字電視廣播等。這種應用的特點是各方面的要求比較均衡。需要注意的是,這種應用可以用CBR編碼,也可以用VBR編碼。
bbv_delay==0xFFFF時是高延遲模型,主要應用于存儲媒體。這種應用的特點是對延遲不敏感,信道可靠性好,能提供的數據傳輸率很高,但是存儲容量有限,因此通常采用VBR編碼。
低延遲模式通常用于可視電話、視頻會議等對延遲要求很高的應用。同時,信道能夠提供的數據傳輸率也是有限的。這就給碼率控制帶來了很大的難度,可能會出現某些幀數據量太大的情況。
前文列舉的基本概念對理解碼流緩沖模型是非常重要的,特別是解碼時刻的確定方式。
另外,就是關于CBR和VBR。根據前文的敘述,可知CBR,VBR和bbv_delay,low_delay的值沒有必然的聯系。
編碼器和解碼器使用同樣的碼流緩沖區模型,但是任務是不同的。解碼器是被動的,它首先要判斷自己是否有足夠的資源完成解碼,然后按照碼流中的設置實現對緩沖區的操作。解碼器還必須處理意外情況和標準中沒有明確規定的部分。
編碼器首先要把用戶的設置翻譯成合適的緩沖區參數,然后采取合適的方法控制編碼過程,使緩沖區不發生溢出。編碼器通過控制緩沖區來控制解碼器的行為。
本文從編碼器的角度,針對3種不同的緩沖模式,給出了保證緩沖區不溢出的可操作的條件。其中,低延遲模式保證緩沖區不上溢的條件和常用的緩沖模式是一樣的。
[1] ISO/EC 13818-2,Generic coding of moving pictures and associated audio:Video[S].1996.
[2]GB/T 20090.2—2006,信息技術 先進音視頻編碼 第2部分:視頻[S].2006.
[3]楊其彤,諸巍杰,張兆揚,等.基于運動復雜度的AVS幀級碼率控制算法[J]. 電視技術,2009,33(1):21-23.