h264和aac封裝flv


flv格式解析

FLV是一個二進制文件,簡單來說,其是由一個文件頭(FLV header)和很多tag組成(FLV body)。tag又可以分成三類:audio,video,script,分別代表音頻流(0x8),視頻流(0x9),腳本流(0x12),而每個tag又由tag header和tag data組成。

flv官方標准文檔

分析之前推薦一個flv分析工具:flv分析工具
工具的使用說明和出處:使用說明

以一個具體的flv文件為例具體分析:

文件頭由9bytes組成:

image.png

前3個bytes是文件類型,總是“FLV”,也就是(0x46 0x4C 0x56)。第4btye是版本號,目前一般是0x01。第5byte是流的信息,倒數第一bit是1表示有視頻(0x01),倒數第三bit是1表示有音頻(0x4),有視頻又有音頻就是0x01 | 0x04(0x05),其他都應該是0。最后4bytes表示FLV 頭的長度,3+1+1+4 = 9。

FLV header后面就是FLV body,FLV body中包含很多個FLV tag,tag的分類有三種:0x08音頻、0x09視頻、0x12腳本。

每個tag中包含tag頭和tag體。

每個tag前面還有一個previous size包 記錄這上一個tag的數據的長度。先簡單說一下tag head:
image.png

1byte Tag類型,3bytes數據長度記錄,3bytes時間戳,一個擴展時間戳bype,3bytes StreamID

每一個tag第一部分是tag header,tag header長度為11bytes,但是每個tag header前面有4bytes記錄着上一個tag的長度。tag header的第1個byte為記錄着tag的類型,音頻(0x8),視頻(0x9),腳本(0x12);第2到4bytes是數據區的長度,也就是tag data的長度;再后面3個bytes是時間戳,單位是毫秒,類型為0x12則時間戳為0,時間戳控制着文件播放的速度,可以根據音視頻的幀率類設置;時間戳后面一個byte是擴展時間戳,時間戳不夠長的時候用;最后3bytes是streamID,但是總為0,再后面就是數據區了(tag data),也即是h264的裸流,tag header 長度為1+3+3+1+3=11。

image.png

0x12腳本數據(Script Tag Data)

跟在FLV header后面的第一個tag就是腳本數據,Script Tag Data,該類型Tag又通常被稱為Metadata(元數據) Tag,會放一些關於FLV視頻和音頻的參數信息,如duration、width、height等。通常該類型Tag會跟在File Header后面作為第一個Tag出現,而且只有一個。一般來說,該Tag Data結構包含兩個AMF包。AMF(Action Message Format)是Adobe設計的一種通用數據封裝格式,在Adobe的很多產品中應用,簡單來說,AMF將不同類型的數據用統一的格式來描述。第一個 AMF包封裝字符串類型數據,用來裝入一個“onMetaData”標志,這個標志與Adobe的一些API調用有,在此不細述。第二個AMF包封裝一個數組類型,這個數組中包含了音視頻信息項的名稱和值。具體說明如下,大家可以參照圖片上的數據進行理解。

第一個AMF包:

第1個字節表示AMF包類型,一般總是0x02,表示字符串,其他值表示意義請查閱文檔。

第2-3個字節為UI16類型值,表示字符串的長度,一般總是0x000A(“onMetaData”長度)。

后面字節為字符串數據,一般總為“onMetaData”。

第二個AMF包:

第1個字節表示AMF包類型,一般總是0x08,表示數組。

第2-5個字節為UI32類型值,表示數組元素的個數。

后面即為各數組元素的封裝,數組元素為元素名稱和值組成的對。表示方法如下:

第1-2個字節表示元素名稱的長度,假設為L。

后面跟着為長度為L的字符串。

第L+3個字節表示元素值的類型。

后面跟着為對應值,占用字節數取決於值的類型。

image.png

0x12前面的00 00 00 00 就是剛剛說的記錄着上一個tag的長度的4bytes,這里因為前面沒有tag,所以為0。

0x09視頻數據

H264 的NALU 封裝成FLV有三種不同的形式:

(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中:

image.png

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

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中封裝 如下:

image.png

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 0xEDNALU data

+PreviousTag Size

另外補充:

VideoHeader第一個字節是video info。前4bit表示視頻數據幀的類型,后4bit表示編碼器的類型。如果是H264的視頻,則VideoHeader還要多4個字節。包含1個字節的

avc_packet_type和3個字節的composition_time。

avc_packet_type:0x0表示avc sequence header,0x01表示NALU。VideoData需要完整的一幀的數據,而在RTP傳輸中,由於一幀數據太大,不利於傳輸,在傳輸時會對一幀進行分片。所以在這里需要將接收到的FU_A的NALU轉換成原始的NALU,然后將多個NALU組成完成的一幀視頻數據,存入VideoData中。至此VideoTagData就封裝完成了。

0x09視頻數據

AudioHeader第一個字節是audio info。前4bit是音頻格式,第5-6bit是采樣率,第7bit是采樣精度,第8bit是聲道數。如果音頻格式是AAC的則還要多一個字節的aac_packt_type。

aac_packt_type:0x0表示AAC Sequence Header,0x01表示AAC Raw。AAC一幀數據通常較小,在RTP傳輸中,每次都是一個包一幀數據,不像H264視頻需要分開。所以取出RTP中的音頻數據,加上ADTS頭就可以直接放入AudioData。至此AudioTagData就封裝完成了。

image.png

前4bits表示音頻格式(全部格式請看官方文檔):

·0 -- 未壓縮

·1 -- ADPCM

·2 -- MP3

·4 -- Nellymoser 16-kHz mono

·5 -- Nellymoser 8-kHz mono

·10 -- AAC

下面兩個bits表示samplerate:

·0 -- 5.5KHz

·1 -- 11kHz

·2 -- 22kHz

·3 -- 44kHz

下面1bit表示采樣長度:

·0 -- snd8Bit

·1 -- snd16Bit

下面1bit表示類型:

·0 -- sndMomo

·1 -- sndStereo

之后是數據。

更多參考:

【音視頻技術】H264流媒體封裝FLV文件


打包H264碼流到FLV文件


打包AAC碼流到FLV文件


FLV視頻封裝格式詳解


flv封裝H264+AAC[附完整代碼]


h264 aac 封裝 flv


h264和aac 封裝成flv

https://www.optbbs.com/thread-4712999-1-1.html

https://www.cnblogs.com/chef/archive/2012/07/18/2597279.html

http://www.360doc.com/content/16/1013/17/474846_598171645.shtml


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM