rfc3984
Standards Track [Page 2] RFC 3984 RTP Payload Format for H.264 Video February 2005 1.
按照RFC3984協議實現H264視頻流媒體
nalu單元 包起始 0x 00 00 00 01
H.264 NAL格式及分析器
http://hi.baidu.com/zsw%5Fdavy/b ... c409cc7cd92ace.html http://hi.baidu.com/zsw_davy/blo ... 081312c8fc7acc.html ----------------------------------比特流信息----------------------------------------------
①NALU(Network Abstract Layer Unit):兩標準中的比特流都是以NAL為單位,每個NAL單元包含一個RBSP,NALU的頭信息定義了RBSP所屬類型。類型一般包括序列參數集(SPS)、圖像參數集(PPS)、增強信息(SEI)、條帶(Slice)等,其中,SPS和PPS屬于參數集,兩標準采用參數集機制是為了將一些主要的序列、圖像參數(解碼圖像尺寸、片組數、參考幀數、量化和濾波參數標記等)與其他參數分離,通過解碼器先解碼出來。此外,為了增強圖像的清晰度,AVS-M添加了圖像頭(Picture head)信息。讀取NALU流程中,每個NALU前有一個起始碼0x000001,為防止 內部0x000001序列競爭,H.264編碼器在最后一字節前插入一個新的字節——0x03,所以解碼器檢測到該序列時,需將0x03刪掉,而AVS-M只需識別出起始碼0x000001。
②讀取宏塊類型(mb type)和宏塊編碼模板(cbp):編解碼圖像以宏塊劃分,一個宏塊由一個16*16亮度塊和相應的一個8*8cb和一個8*8cr色度塊組成。
(a) 兩標準的幀內、幀間預測時宏塊的劃分是有區別的。H.264中,I_slice亮度塊有Intra_4*4和Intra_16*16兩種模式,色度塊只有8*8模式;P_slice宏塊分為16*16、16*8、8*16、8*8、8*4、4*8、4*4共7種模式。而AVS-M中,I_slice亮度塊有I_4*4和I_Direct兩模式,P_slice時宏塊的劃分和H.264中的劃分一致。
(b) 兩標準的宏塊cbp值計算也不相同。H.264中,Intra_16*16宏塊的亮度(色度)cbp直接通過讀mb type得到;非Intra_16*16宏塊的亮度cbp=coded_block_pattern%16,色度cbp=coded_block_pattern/16 。其中,亮度cbp最低4位有效,每位決定對應宏塊的殘差系數能不能為0;色度cbp為0時,對應殘差系數為0,cbp為1時,DC殘差系數不為0,AC系數為0,cbp為2時,DC、AC殘差系數都不為0。AVS-M中,當宏塊類型不是P_skip時,直接從碼流中得到cbp的索引值,并以此索引值查表得到codenum值,再以codenum查表分別得到幀內/幀間cbp。此cbp為6位,每位代表宏塊按8*8劃分時能不能包含非零系數,當變換系數不為0時,需進一步讀cbp_4*4中每位值來判斷一個8*8塊中4個4*4塊的系數能不能為0。
---------------------------------------------------------------------------------------------
總的來說H264的碼流的打包方式有兩種,一種為
annex-b byte stream format的格式,這個是絕大部分編碼器的默認輸出格式,就是每個幀的開頭的3~4個字節是H264的start_code,0x00000001或者0x000001。
另一種是原始的NAL打包格式,就是開始的若干字節(1,2,4字節)是NAL的長度,而不是start_code,此時必須借助某個全局的數據來獲得編碼器的profile,level,PPS,SPS等信息才可以解碼。
----------------------------------------------------------------------------
AVC vs. H.264
AVC and H.264 are synonymous. The standard is known by the full names "ISO/IEC 14496-10" and "ITU-T Recommendation H.264". In addition, a number of alternate names are used (or have been) in reference to this standard. These include:
- MPEG-4 part 10
- MPEG-4 AVC
- AVC
- MPEG-4 (in the broadcasting world MPEG4 part 2 is ignored)
- H.264
- JVT (Joint Video Team, nowadays rarely used referring to actual spec)
- H.26L (early drafts went by this name)
All of the above (and those I've missed) include the
Annex B byte-stream format. Unlike earlier MPEG1/2/4 and H.26x codecs, the H.264 specification proper does not define a full bit-stream syntax. It describes a number of NAL (Network Abstraction Layer) units, a sequence of which can be decoded into video frames. These NAL units have no boundary markers, and rely on some unspecified format to provide framing.
Annex B of of the document specifies one such format, which wraps NAL units in a format resembling a traditional MPEG video elementary stream, thus making it suitable for use with containers like MPEG PS/TS unable to provide the required framing. Other formats, such as ISO base media based formats, are able to properly separate the NAL units and do not need the Annex B wrapping.
The H.264 spec suffers from a deficiency. It defines several header-type NAL units (SPS and PPS) without specifying how to pack them into the single codec data field available in most containers. Fortunately, most containers seem to have adopted the packing used by the ISO format known as MP4.
1. H.264起始碼
?? 在網絡傳輸h264數據時,一個UDP包就是一個NALU,解碼器可以很方便的檢測出NAL分界和解碼。但是如果編碼數據存儲為一個文件,原來的解碼器將無法從數據流中分別出每個NAL的起始位置和終止位置,為此h.264用起始碼來解決這一問題。
?? H.264編碼時,在每個NAL前添加起始碼 0x000001,解碼器在碼流中檢測到起始碼,當前NAL結束。為了防止NAL內部出現0x000001的數據,h.264又提出'防止競爭 emulation prevention"機制,在編碼完一個NAL時,如果檢測出有連續兩個0x00字節,就在后面插入一個0x03。當解碼器在NAL內部檢測到0x000003的數據,就把0x03拋棄,恢復原始數據。
0x000000?? >>>>>>?? 0x00000300
0x000001?? >>>>>>?? 0x00000301
0x000002?? >>>>>>?? 0x00000302
0x000003?? >>>>>>?? 0x00000303
附上h.264解碼nalu中檢測起始碼的算法流程??
for(;;)
{
if next 24 bits are 0x000001
{
?? ??? startCodeFound = true
?? ??? break;
}
else
{
?? ??? flush 8 bits??
}
}// for(;;)
if(true == startCodeFound)
{
??? //startcode found
??? // Flush the start code found
??? flush 24 bits??
??? //Now navigate up to next start code and put the in between stuff
??? // in the nal structure.
??? for(;;)
??? {
?? ?? get next 24 bits & check if it equals to 0x000001
?? ?? if(false == (next 24 bits == 000001))
?? ?? {
?? ?? ?? // search for pattern 0x000000
?? ?? ?? check if next 24 bits are 0x000000
?? ?? ?? if(false == result)
?? ?? ?? {
?? ?? ?? ?? ??? // copy the byte into the buffer
?? ?? ?? ?? ??? copy one byte to the Nal unit ?? ?? ?? ???
?? ?? ?? }
?? ?? ?? else
?? ?? ?? {
?? ?? ?? ?? ??? break;
?? ?? ?? }
?? ?? }
?? ?? else
?? ?? {
?? ?? ?? ??? break;
?? ?? }
?? }//for(;;)
}
?? 2. MPEG4起始碼
?? ??? MPEG4的特色是VOP,沒有NALU的概念,仍使用startcode對每幀進行分界。MPEG4的起始碼是0x000001. 另外MPEG4中很多起始碼也很有用,比如video_object_sequence_start_code 0x000001B0 表示一個視頻對象序列的開始,VO_start_code 0x000001B6 表示一個VOP的開始. 0x000001B6之后的兩位,是00表示 I frame, 01 表示 P frame, 10 表示 B frame.