幀邊界識别簡介
H.264 将構成一幀圖像所有nalu 的集合稱為一個AU,幀邊界識别實際上就是識别AU。因為H.264 取消幀級文法,是以無法簡單地從碼流中擷取AU。解碼器隻有在解碼的過
程中,通過某些文法元素的組合才能判斷一幀圖像是否結束。一般來說,解碼器必須在完成一幀新圖像的第一個slice_header 文法解碼之後,才能知道前一幀圖像已經結束。
是以,最嚴謹的AU 識别步驟如下:
步驟 1 對碼流實施“去03 處理”。
步驟 2 解析nalu 文法。
步驟 3 解析slice_header 文法。
步驟 4 綜合判斷前後兩個nalu 以及對應的slice_header 中的若幹個文法元素,看是否發生變化。
如果發生變化,則說明這兩個nalu 屬于不同的幀,否則說明這兩個nalu 屬于同一幀。
----結束
顯然,在解碼前完成上述的AU 識别消耗許多CPU 資源,是以不推薦使用AU 方式解碼
為了提供一種簡單的AU 識别方案,H.264 規定一種類型為09 的nalu,即編碼器在每次完成一個AU 編碼後,在碼流中插入一個類型為09 的nalu,在這個前提下,解碼器隻需要從碼流中搜尋類型為09 的nalu 即可獲得一個AU。
H.264 并不強制要求編碼器插入類型為09 的nalu,是以并非所有的碼流都具備這種特征。對于編碼器和解碼器協同工作的應用場景,建議讓編碼器插入類型為09 的nalu,這樣可以降低解碼器識别AU 的代價。
為了降低解碼器在解碼前識别AU 的代價,本文提出一種高效的AU 識别方法,其主要思路是利用一幀圖像的第一個slice_header 中的文法元素first_mb_in_slice 一般等于0 這
個特征(對于包含ASO 或者FMO 特性的碼流,這個條件不一定成立)。
- typedef struct ParseContext{
- unsigned int FrameStartFound;
- unsigned int iFrameLength;
- } ParseContext;
- signed int DecLoadAU(unsigned char* pStream, unsigned int iStreamLen, ParseContext *pc)
- {
- unsigned int i;
- unsigned int state = 0xffffffff;
- if( NULL == pStream )
- {
- return -1;
- }
- for( i = 0; i < iStreamLen; i++)
- {
- if( (state & 0xFFFFFF1F) == 0x101 || (state & 0xFFFFFF1F) == 0x105 )
- {
- if (i >= iStreamLen)
- {
- break;
- }if( pStream[i] & 0x80)
- {
- if(pc->FrameStartFound)
- {
- pc->iFrameLength = i - 4;
- pc->FrameStartFound = 0;
- state = 0xffffffff;
- return 0;
- }
- else
- {
- pc->FrameStartFound = 1;
- }
- }
- }
- if (i < iStreamLen)
- {
- state = (state << 8) | pStream[i];
- }
- }
- pc->FrameStartFound = 0;
- return -1;
- }