最近再封裝H264文件,本來想想用ffmpeg,可惜設備端沒有足夠的空間放ffmpeg的庫了,無奈只好開始擼協議自己封裝了~
首先至少得了解以下知識點:
好了,開擼。
FLV的封裝格式就不說了,這篇博客着重說一下 H264中的NALU如何封裝成 FLV中的video tag ,關於FLVheader 及FLV其他結構有不清楚的可以上網查其他資料或者看我寫的這篇【音視頻技術】FLV封裝格式博客。
-------------------------------------------------------------------------------------------------------------
H264 的NALU 封裝成FLV有三種不同的形式:
(H264 NALU 不清楚的【音視頻技術】AVC H264的一些基本概念和知識點)
(1)H264 NALU type SPS +PPS;
(2)H264 NALU type SEI;
(3)H264 NALU type Slice 也就是 type值爲(1-5);
--------------------------------------------------------------------------------------------------------------
(1)H264 NALU type SPS +PPS 封裝成 FLV video tag:
在H264的碼流中 SPS 和 PPS是成對出現的,先是SPS然後是PPS,SPS對於H264來說就是編碼後的第一幀、PPS是編碼後的第二幀這兩針攜帶的數據主要是編碼器的一些屬性,比如寬高 profile level deblock濾波器等等。
在封裝FLV中這兩幀數據被合併到一個video TAG中:
FLV tag header Bytes value
1)Tag type // 0 0x09
2)Data Size // 1-3 0x00 0x00 0x24
3)TimeStamp // 4-6 0x00 0x00 0x00 (First frame)
4)TimeStampExtend // 7 0x00
5)StreamID // 8-10 0x00 0x00 0x00 (always zero)
AVC Video tag header
1)FrameType | CodecID //11 0x17
2)AVCPacketType //12 0x00
3)Composition Time //13-15 0x00 0x00 0x00
AVCDecoderConfigurationRecord
1)Configuration VerSion //16 0x01
2)AVC Profile SPS[1] //17 0x42
3)profile_compatibility SPS[2] //18 0x00
4)AVC Level SPS[3] //19 0x2A
5)lengthSizeMinusOne //20 0xFF
6)numOfSequenceParameterSets //21 0xE1
SPS
1)SPS0 Length //22-23 0x0010
2)SPS0 Data
3)SPS(n) length /btyes 如果存在多個循環存放最多31個SPS
4)SPS(n) Data
PPS
PPS count //1byte 0x01
PPS0 Length //2bytes 0x00 0x04
PPS0 Data
PPS(n) Length
PPS(n) Data
+PreviousTag Size
--------------------------------------------------------------------------------------------------------
(2)H264 NALU type Sei 封裝成 FLV video tag:
SEI NALU 是沒有圖像數據的,它的主要作用是對圖像數據或者視頻流的補充,有些內容可能對解碼有幫助。在封裝FLV文件中含義SEI的videoTAG其中包含色SEI數據還有SEI幀後緊跟着的一個IDR數據,其編碼結構如下;
FLV tag header Bytes value
1)Tag type // 0 0x09
2)Data Size // 1-3 0x00 0x00 0x24
3)TimeStamp // 4-6 0x00 0x00 0x00 (First frame)
4)TimeStampExtend // 7 0x00
5)StreamID // 8-10 0x00 0x00 0x00 (always zero)
AVC Video tag header
1)FrameType | CodecID //11 0x27
2)AVCPacketType //12 0x01
3)Composition Time //13-15 0x00 0x00 0x00
SEI
1)SEI length //16-19 0x00 0x00 0x00 0x05
2)SEI Data // 20-N 0x06 E5 01 81 80
3)IDR NALU Length //4Bytes 0x00 0x00 0x1F 0xF4
4)IDR NALU Data
+PreviousTag Size
----------------------------------------------------------------------------------------------------
(3)H264 NALU type Slice 封裝成 FLV video tag:
Slice Type NALU (1-5) 就是H264 中一片一片的數據了,在FLV video tag中封裝 如下:
FLV tag header Bytes value
1)Tag type // 0 0x09
2)Data Size // 1-3 0x00 0x95 0xF6
3)TimeStamp // 4-6 0x00 0x00 0x00 (First frame)
4)TimeStampExtend // 7 0x00
5)StreamID // 8-10 0x00 0x00 0x00 (always zero)
AVC Video tag header
1)FrameType | CodecID //11 0x27 or 0x17
2)AVCPacketType //12 0x01
3)Composition Time //13-15 0x00 0x00 0x00
NALU
NALU Length // 4bytes 0x00 0x00 0x95 0xED
NALU data
+PreviousTag Size
OK,上述就是H264在封裝成FLV文件時的3中video tag。再說點調試時的經驗吧。封裝FLV我總共花了3天,第一天瞭解FLV協議,AMF協議,結合着flv的媒體文件來對照協議,理解各個字段的意思。大家可以使用UEdit這個工具來看二進制文件,也可以使用這個flv解析工具來直接解析flv文件 (還算挺好用的吧)。封裝過程中有些大端小端的一定要注意,還有擴展時間戳位(不知道搞協議的人怎麼想的搞出這個東西來)。第二天,再網上搞了一套代碼,看懂後改了改 ,可以封裝H264了 但是 生產出來的flv文件播放有馬賽克。後來用ffmpeg封裝對比前後的文件慢慢找出的端倪。錯在SEI type的nalu 我處理的不對又改了改,大功告成。源代碼的話我就不放了,如果按照我這個按部就班的做應該沒問題的,我就是這麼搞出來的。
整個工作過程這篇博客給我的幫助是最大的,內容也是最正確的,其他看了好多感覺都有寫的不對的地方(感謝感謝):