1. 程式人生 > >rtmp流轉Hls流 與 flv轉mpegts

rtmp流轉Hls流 與 flv轉mpegts

rtmp協議是adobe出的一種流媒體格式協議。是目前較為流行的協議的一種。

HLS協議是蘋果推出的一種流媒體協議,由於IOS系統不支援RTMP協議,如實現RTMP協議的流媒體需要自己實現RTMP的客戶端,這使得移動手機端使用RTMP的流媒體增加了一些開發成本。

HLS協議的詳情可以參考APPLE的網站,內容主要由M3U8和MPEGTS這兩大檔案組成,本文詳解的是MPEGTS檔案。

MPEG2-TS(Transport Stream“傳輸流”;又稱 MTS、TS)是一種傳輸和儲存包含音效、影象與通訊協議各種資料的標準格式,用於數字電視廣播系統,如 DVB、ATSC、IPTV 等等。

MPEG2-TS 定義於 MPEG-2 第一部份,系統(即原來之 ISO/IEC 標準 13818-1 或 ITU-T Rec. H.222.0)。

SMPLAYER、VLC多媒體播放器 等軟體可以直接播放 MPEG-TS 檔案。

MPEG2-TS傳輸流編碼層允許一個或多個節目組合成單一流。來自每個基本流的資料同節目內允許該基本流同步顯示的資訊一起多路複用。

傳輸流由一個或多個節目組成。音訊和視訊基本流(ES)由存取單元(AU,一般常說的NALU)組成。

基本流資料(ES element stream ,  比如H264裸流)在PES 包中承載。PES 包由PES 包頭及後隨的包資料組成。PES 包插入到傳輸流包中。每個PES 包頭的首位元組定位於傳輸流包的第一個有效載荷位。

本文主要的參考為:ISO-13818-1,Adobe Flash Video File Format Specification  Version 10.1,ISO-14496-3,ISO-14486-15

本文所述內容與標準有一定的差異,這種差異並非指存在違背標準的內容,而是本文由於篇幅所限,對於某些約束,只取與符號標準的一項,而不是相容標準所有的規範。

1.2結構

傳輸流類似OSI network 協議堆疊:

1.TS

2. PES

3.Elementarystream (ES) — audio or video (the below is for video only)

4.編碼層..

1.3傳輸流資料包(transport stream packets)

TransportStream packets -> PES -> ES

TransportStream packets 是傳輸流(transport stream)內資料的最基本單位,包含了一個同步位元組(sync byte)值為 0x47,它存在一個4bytes的固定包頭,32bits 接著它的是可變包頭區域。 Packets 有固定的188 bytes 的長度。

表1-1 Transport Stream packets結構

欄位

Value

bits

sync_byte

0x47

8

bslbf

transport_error_indicator

如果這個流中包含了一個無法修復的錯誤,由解調器設定,以告訴多路解調器,該包存在一個無法糾正的錯誤

1

bslbf

payload_unit_start_indicator

1 表示是 PES 資料或 PSI資料的開始部分,否則為零.

1

bslbf

transport_priority

1 意思是在相同 PID 的資料包中含有更高的優先權.

1

bslbf

PID

PID 為13 位元欄位,指示包有效載荷中儲存的資料型別,也就是包的標識號。

13

uimsbf

transport_scrambling_control

此2 位元欄位指示傳輸流包有效載荷的加擾方式。

2

bslbf

adaptation_field_control

此2 位元欄位指示此傳輸流包頭是否後隨自適應欄位和/或有效載荷

2

bslbf

continuity_counter

continuity_counter 為4 位元欄位,隨著具有相同PID 的每個傳輸流包而增加

4

uimsbf

這裡最主要關係的是payload_unit_start_indicator,PID,adaptation_field_control,continuity_counter

payload_unit_start_indicator

這個位標誌為1,指的是一個包的啟示,因為ts包只有188個位元組,對於一個PES包的話往往大於188位元組,因此一個PES包往往要拆成多個TS包,為了識別收到的TS包屬於另一個PES包,起始位表示新的一個PES包或者PSI包等到來了。

PID program id

節目標示符,一個13位的無符號整數。作用如下表描述。一般來說,參考FFMPEG,PMT表使用PID 4096,VIDEOSTREAM 採用256,AUDIOSTREAM採用257。



adaptation_field_contro

當adaptation_field_control的值為10,接下來的是自適應欄位adaptation_field,當adaptation_field_control的值如下表描述



continuity_counter

這個是當前節目的一個計數器,獨立於PID,也就是說各個PID分開計算。

接下來的就是有效的負載內容,具體的負載內容必須是來自PES 包(參閱2.4.3.6)、PSI 分段(參閱2.4.4)以及PSI 分段後的包填充位元組資料的相連貫的資料位元組,或者不在這些結構中的專用資料,如PID 所指示的。在具有PID 值0x1FFF 的空包情況中,data_bytes 可以指派為任何值。data_bytes 數N 通過184 減去 adaptation_field() 中的位元組數來確定。

TS包結構圖


1.4 自適應欄位 (adaptation_field)

自適應欄位我們主要關注的是第一個adaptation  field length和PCR,這裡重點講解他們的主要用處:

    adaptationfield length指的是自適應欄位的長度,也就是,從discontinuity indicator 到adaptation field最後的長度,也就是從第6位元組(包含第6位元組)開始算到最後。

PCR

這個值是系統的時間戳,在PES層時間戳是PTS與DTS,這裡要注意與PCR,PTS,DTS的概念,可能會讓人模糊。PCR是TS層的時間戳,PTS與DTS是PES的時間戳,PCR在PES層相當於DTS,TS不需要考慮PTS。為啥不需要,這裡就要講下,PTS的具體概念。詳細的在ISO-13818-1上有,詳細到可以看到你吐。其實實際中不需要考慮這麼多。我簡單的講吧。在ES流中,依次組成影象幀序為I1P4B2B3P7B5B6I10B8B9的,這裡,I、P、B分別指I幀,P幀,B幀。具體意義可以參考H264的相關基本概念,對於I、P幀而言,PES的影象幀序為I1P4B2B3P7B5B6I10B8B9,應該P4比B2、B3在先,但顯示時P4一定 要比B2、B3在後,這就必須重新排序。在PTS/DTS時間標誌指引下,將P4提前插入資料流,經過快取器重新排序,重建視訊幀序 I1B2B3P4B5B6P7B8B9I10。顯然,PTS/DTS是表明確定事件或確定資訊,並以專用時標形態確定事件或資訊的開始時刻。說到這裡,PTS,與DTS的概念應該明白了。但是為啥TS層不需要呢,因為TS層只是負責傳輸,你知道解碼的時間在什麼位置,確保傳輸的TS包不是延遲太久就可以了,具體的顯示細節交給PES層去做。

2.1 PES包

PES將ES流打包,打包的依據我沒有發現有硬性規定,但是一般會將ES流中的一個frame打包成一個PES,在H264的ES流中的NALU流如果分段的話,會由3個NALU組成一個frame,一般來說,都沒有分段的選項。所以,我們可以簡單的認為一個NALU就是一個frame。

   在ffmpeg中,H264的SPS與PPS一起打包在頭一個NALU中,

PES包的欄位沒什麼好講的,

streamID , 這裡視訊H264填寫0xe0 ,AAC音訊填寫OXCO

PES PACKET LENGTH 是從OPTIONAL FIELD 到包最後一個位元組的長度,不算前面的4位元組,和自身2位元組,一般來說就是3+10+NALUSIZE,這裡10是指VIDEOFRAME的,如果是AUDIOFRAME則是5.

PTS,和DTS的計算。如果是根據ES流計算怎麼算,我還沒想到容易的方法。但是如果根據FLV格式轉換,PTS就是(flvTagHeader.timestamp +videoTagHeader.CompositionTime) * 90 , 為啥是90呢?flv裡面的時間戳的單位都是毫秒的,1/1000秒。mpegts的系統時鐘為27MHZ,這裡要除以300(規定的除以300,參考ISO-13818-1)。也就是90000hz,一秒鐘90000個週期,所以,PTS代表的週期flv的時間戳*90000/1000 ,90也就是這麼來的。

TS層裡的PCR可以直接採用DTS。

/

以下是擷取的一個TS包,紅色部分為SPS,PPS,藍色部分為es 流中的startcode ,紫色部分為H.264 video access units must use Access Unit Delimiter NALs

  1. 47 41 00 30 07 50 00 00 00 00 7E 00 00 00 01 E0  
  2. 50 A5 80 C0 0A 31 00 01 5D 85 11 00 01 00 01 00  
  3. 00 00 01 09 F0 00 00 00 01 67 64 00 15 AC C8 60  
  4. 20 09 6C 04 40 00 00 03 00 40 00 00 07 A3 C5 8B  
  5. 67 80 00 00 00 01 68 E9 BB 2C 8B 00 00 00 01 65  
  6. 88 84 00 7F 4D 32 19 FF 2D 02 C7 FE E6 51 22 40  
  7. 3D AA 71 9A 11 60 AE 24 4B BB 66 66 4E 71 C9 E0  
  8. E4 EB 4C D1 FE D4 B7 3B 8F 1D 36 2C 76 5B B9 12  
  9. 70 23 B6 F4 C0 EB 58 CD 66 AB 0D C5 2A 91 59 C6  
  10. 31 7F 7B A0 5A 76 AD 3F BD 01 88 6A 35 84 BE 58  
  11. 06 A0 1C 99 93 72 BC CE 61 6D 22 CB 89 E1 AD 56  
  12. 26 C0 48 66 78 2C 2C EF 38 F8 84 CF  


2.2 PAT

節目相關表:

這個表主要是節目相關資訊的表。這個表在轉換的時候,可以採取一種暴力的方法,就是寫死。

這裡CRC校驗的演算法,最後會說,計算的位元組是隻計算PSI+PXT的內容,TS頭部的內容不考慮。

PAT specific data repeated until end of section length

Name

Number
of bits

Description

Program num

16

Relates to the Table ID extension in the associated PMT. A value of 0 is reserved for a NIT packet identifier.

Reserved bits

3

Set to 0x07 (all bits on)

Program map PID

13

The packet identifier that contains the associated PMT

  1. //TS
  2.    0x47,0x40,0x00,0x10,0x00,  
  3. //PSI,table id 00
  4.    0x00,0xb0,0x0d,0x00,0x01,0xc1,0x00,0x00,  
  5. //PAT
  6.    0x00,0x01,0xf0,0x01,  
  7. //crc
  8.    0x2e,0x70,0x19,0x05,  
  9. // stuffing 167 bytes
  10.    0xff,0xff,0xff,0xff,0xff,0xff,0xff,  
  11.    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,  
  12.    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,  


2.3 PMT

PMT(Program map specific data)

PMT specific data

Name

Number
of bits

Description

Reserved bits

3

Set to 0x07 (all bits on)

PCR PID

13

The packet identifier that contains the program clock reference used to improve the random access accuracy of the stream's timing that is derived from the program timestamp. If this is unused. then it is set to 0x1FFF (all bits on).

Reserved bits

4

Set to 0x0f (all bits on)

Program info length unused bits

2

Set to 0 (all bits off)

Program info length

10

The number of bytes that follow for the program descriptors.

Program descriptors

N*8

When the program info length is non-zero, this is the program info length number of program descriptor bytes.

Elementary stream info data

N*8

The streams used in this program map.

Elementary stream specific data repeated until end of section length

Name

Number
of bits

Description

stream type

8

This defines the structure of the data contained within the elementary packet identifier.

Reserved bits

3

Set to 0x07 (all bits on)

Elementary PID

13

The packet identifier that contains the stream type data.

Reserved bits

4

Set to 0x0f (all bits on)

ES Info length unused bits

2

Set to 0 (all bits off)

ES Info length length

10

The number of bytes that follow for the elementary stream descriptors.

Elementary stream descriptors

N*8

When the ES info length is non-zero, this is the ES info length number of elementary stream descriptor bytes.

  1. //ts
  2.    0x47,0x50,0x01,0x10,0x00,  
  3. //PSI
  4.    0x02,0xb0,0x17,0x00,0x01,0xc1,0x00,0x00,  
  5. //PMT ,no pcr
  6.    0xe1,0x00,  
  7.    0xf0,0x00,  
  8.    0x1b,0xe1,0x00,0xf0,0x00,  
  9.    0x0f,0xe1,0x01,0xf0,0x00,  
  10. //crc
  11.    0x2f,0x44,0xb9,0x9b,  
  12. // stuffing 157 bytes
  13.    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,  
  14.    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,  
  15.    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,  

3.FLV檔案分析

FLV檔案的結構,可以在網上找個flv parse的工具幫助分析。

可以看到,FLV的檔案形式由FLV HEADER + pre Tag Size + Tag 組成


首先每個TAG中的前面有個11位元組的頭部,這個描述了該tag中的內容的型別。後續接著的是相關型別的TAG內容。



3.1 視訊

對於VIDEO TAG來講,首部會有個5位元組的VIDEO TAG HEADER,




這裡如果AVCPACKET TYPE為0,則表示AVC SEQUENCE HEADER,這裡包含著很重要的資訊,也就是H264 ES流中解碼的關鍵資訊--SPS ,PPS的內容

AVC SEQUENCE HEADER的具體內容可參考, ISO-14496-15AVC file format。這裡簡化如下表所示。 AVC SEQUENCEHEADER一般情況只出現一次,並出現在FLV檔案的第一個VIDEO TAG。這裡引用一張別人的圖,出處我忘了不好意思,因為專案是一年前做的。


從AVC PACKET TYPE 看出每個VIDEO TAG至少包含一個完整的FRAME。在FLV中的NALU,需要加上00 00 00 01這樣的NALU頭,並在前面再加上 00 00 00 01 09 f0,具體的原因應該是規範。視訊的PTS的時間戳由TAG裡的TIMESTAMP + COMPOSITIONTIME構成。DTS可直接由TIMESTAMP。這裡FLV裡的是毫秒,需要*90向MPEGTS的時鐘週期進行轉換

3.2音訊

音訊的TAG如下圖所示,值得注意的是AAC SEQUENCE HEADER,這裡和視訊頭部一樣,其實質內容是AudioSpecificConfig ,定義在14496-3中。包含了AAC解碼的關鍵內容,ADTS HEADER的內容。ADTS 的內容定義在13818-7中。這些定義在標準裡面寫的看起來很複雜,實際上內容倒也沒什麼。AAC ES流中要求每個音訊frame前面要加上ADTS HEADER 的內容。我們根據首個音訊TAG中提取2位元組的AUDIO SPECIFIC CONFIG,轉換成7位元組的ADTS HEADER,程式碼可參考FFMPEG等,很多有提供。這裡注意,很容易出錯。



RTMP媒體流中,第一個音訊包裡保護的一定是AAC header.

如:af 00 13 90。包長4個位元組,解釋如下,

1)第一個位元組af,a就是10代表的意思是AAC,

Format of SoundData. The following values are defined:

0 = Linear PCM, platform endian

1 = ADPCM

2 = MP3

3 = Linear PCM, little endian

4 = Nellymoser 16 kHz mono

5 = Nellymoser 8 kHz mono

6 = Nellymoser

7 = G.711 A-law logarithmic PCM

8 = G.711 mu-law logarithmic PCM

9 = reserved

10 = AAC

11 = Speex

14 = MP3 8 kHz

15 = Device-specific sound

Formats 7, 8, 14, and 15 are reserved.

AAC is supported in Flash Player 9,0,115,0 and higher.

Speex is supported in Flash Player 10 and higher.

2)第一個位元組中的後四位f代表如下

前2個bit的含義 抽樣頻率,這裡是二進位制11,代表44kHZ

Sampling rate. The following values are defined:

0 = 5.5 kHz

1 = 11 kHz

2 = 22 kHz

3 = 44 kHz

第3個bit,代表 音訊用16位的

Size of each audio sample. This parameter only pertains to

uncompressed formats. Compressed formats always decode

to 16 bits internally.

0 = 8-bit samples

1 = 16-bit samples

第4個bit代表聲道

Mono or stereo sound

0 = Mono sound

1 = Stereo sound

3)第2個位元組

AACPacketType,這個欄位來表示AACAUDIODATA的型別:0 = AAC sequence header,1 = AAC raw。第一個音訊包用0,後面的都用1

4)第3,4個位元組內容AudioSpecificConfig如下

AAC sequence header存放的是AudioSpecificConfig結構,該結構則在“ISO-14496-3 Audio”中描述。AudioSpecificConfig結構的描述非常複雜,這裡我做一下簡化,事先設定要將要編碼的音訊格式,其中,選擇"AAC-LC"為音訊編碼,音訊取樣率為44100,於是AudioSpecificConfig簡化為下表:


0x13 0x90(1001110010000) 表示 ObjectProfile=2, AAC-LC,SamplingFrequencyIndex=7,ChannelConfiguration=聲道2

AudioSpecificConfig,即為ObjectProfile,SamplingFrequencyIndex,ChannelConfiguration,TFSpecificConfig。

其中,ObjectProfile (AAC main ~1, AAC lc ~2, AAC ssr ~3);

SamplingFrequencyIndex (0 ~ 96000, 1~88200, 2~64000, 3~48000, 4~44100, 5~32000, 6~24000, 7~ 22050, 8~16000...),通常aac固定選中44100,即應該對應為4,但是試驗結果表明,當音訊取樣率小於等於44100時,應該選擇3,而當音訊取樣率為48000時,應該選擇2;

ChannelConfiguration對應的是音訊的頻道數目。單聲道對應1,雙聲道對應2,依次類推。

TFSpecificConfig的說明見標準14496-3中(1.2 T/F Audio Specific Configuration)的講解,這裡恆定的設定為0;

索引值如下含義:

There are 13 supported frequencies:

0: 96000 Hz

1: 88200 Hz

2: 64000 Hz

3: 48000 Hz

4: 44100 Hz

5: 32000 Hz

6: 24000 Hz

7: 22050 Hz

8: 16000 Hz

9: 12000 Hz

10: 11025 Hz

11: 8000 Hz

12: 7350 Hz

13: Reserved

14: Reserved

15: frequency is written explictly

channel_configuration: 表示聲道數

0: Defined in AOT Specifc Config

1: 1 channel: front-center

2: 2 channels: front-left, front-right

3: 3 channels: front-center, front-left, front-right

4: 4 channels: front-center, front-left, front-right, back-center

5: 5 channels: front-center, front-left, front-right, back-left,back-right

6: 6 channels: front-center, front-left, front-right, back-left,back-right, LFE-channel

7: 8 channels: front-center, front-left, front-right, side-left,side-right, back-left, back-right, LFE-channel

8-15: Reserved