TS Stream 詳解

<什麼是TS>
    TS(transport stream) , TS流文件,是一種DVD的文件格式,TS格式的特色就是要求從視頻流的任一片斷開始都是能夠獨立解碼的,這種特性就決定了TS流文件主要用來實時傳送的節目,好比實時廣播的電視節目。與之相互對應的是PS(Program Stream),PS主要應用於存儲的具備固定時長的節目,如DVD電影,將DVD上的VOB文件的前面一截剪掉(或者乾脆就是數據損壞),那麼就會致使整個文件沒法解碼。
 
<TS碼流數據封裝格式>
    網絡上常見的TS碼流結構圖:
    由上圖可知,TS流主要由header 和 payload 組成,其中header 部分相對來講比較簡單一些,payload部分紅分比較複雜,其中payload 能夠是PSI(其中包括PAT , PMT),能夠是PES(從攝像頭採集的數據通過壓縮算法後的數據被成爲ES , 通常是在一幀的ES數據前加上點頭信息,其中最主要的是PTS和DTS信息,就造成了PES),能夠是一些自適應數據(沒一包TS碼流長度是固定的188字節,視頻數據不夠188個字節,使用0xFF填充)。
➤TS header
     TS header 的結構:
    
TS header結構圖如圖所示, 各個部分的含義以下:
sync_byte:同步字節,固定爲0x47 ,表示後面的是一個TS分組。
transport_error_indicator錯誤標誌位,佔位1bit,置爲1表示此分組中至少有一個不可糾正的錯誤
payload_unit_start_indicator負載開始標誌位,針對不一樣的負載,有不一樣的含義
●PES:
    置爲1,標識TS包的有效淨荷以PES包的第一個字節開始,即此TS包爲PES包的起始包,且此TS分組中有且只有一個PES包的起始字段;置爲0,表示TS包不是PES包的起始包,是後面的數據包。
●PSI:
    置爲1,表示TS包中帶有PSI數據分段的第一個字節,即這個TS包是PSI Section的起始包,則此TS包的負載(payload)的第一個字節帶有pointer_field,用來指示PSI數據的在payload 中的位置;置爲0,表示TS包不帶有PSI Section的第一個字節,即此TS包不是PSI的起始包,即在有效負載中沒有point_field,有效負載的開始就是PSI的數據內容。point_field的定義將在下面的PSI節中進行介紹;對於空包的包,payload_unit_start_indicator應該置爲0

    例如:若TS包載荷爲PAT,則當接收到的TS包的payload_unit_start_indicator1時,代表這個TS包包含了PAT頭信息,從這個包裏面解析出section_lengthcontinuity_counter,而後繼續收集後面的payload_unit_start_indicator = 0TS包,並判斷continuity_counter的連續性,不斷讀出TS包中的淨載荷(也就是PAT數據),用section_length做爲收集TS包結束條件。web

transport_priority發送優先級,置1則表示此包比其餘相同PID0的包有高的優先級
 PID指示有效負載中的數據類型
0x0000表明PAT
0x0001表明CAT
0x0002-0x000F保留
0x1FFF表示空包
 transport_scrambling_control有效負載加密模式標誌,佔位2bit,00表示未加密
 adaption_field_control調整字段標誌,表示此TS首部是否跟隨調整字段仍是負載數據,佔位2bit,其中00位保留,01表示無調整字段,只有有效負載數據,10表示只有調整字段,無有效負載,11表示有調整字段,且其後跟有有效負載;空分組此字段應爲01;
●總結

若是adaptation_field_control == 1x,表示後面跟有自適應字段;算法

若是adaptation_field_control == x1,表示後面跟有沒有自適應字段;網絡

 continuity_counter連續性計數,隨每個相同PID的TS分組增長,達到最大值後又歸爲0;佔位4bit,若是adaptation_field_control值爲00或01,此值不該增長;若調整字段的標誌位discontinuity_indicator值爲1,則此值也不連續。
 
➤自適應調整字段
調整字段,通常在如下兩種狀況會在TS流中添加自適應段,而且此時的TS header 中的 adaptation_field_control == 1x時,如下字段纔會存在 
    (1) 封裝TS數據的時候,視頻或者音頻數據不夠184個字節的時候,使用該段來指明調整字段0xFF的長度,此時的自適應的區的PCR_flag 標誌爲0;
    (2)對於每一幀視頻數據進行封裝的開始,須要而且是必須在TS header 以後添加自適應區間,此時,自適應區間中最重要的部分是PCR相關數據,PCR主要用來實現解碼端的時鐘同步,具備很重要的意義。此時的自適應區的PCT_flag 標誌爲1;
 

  adaptation_field_length調整字段長度標示,標示此字節後面調整字段的長度,佔位8bit;值爲0時,表示在TS分組中插入一個調整字節,後面沒有調整字段,緊跟着的是有效負載;adaptation_field_control == ‘11’時,此值在0~182之間,adaptation_field_control == ‘10’時,此值爲183,若字段沒這麼長則填充0xFF字段;後面的字段都是在adaptation_field_length>0的時候纔會出現,順序以下:less

 discontinuity_indicator:不連續狀態指示符,佔位1bit,置位1時表示此TS分組的不連續狀態爲真;
 random_access_indicator:隨機訪問指示符,佔位1bit;
 elementary_stream_priority_indicator:原始流數據優先級指示符,佔位1bit,置位1表示此原始流數據比相同PID的TS包中的其餘原始流優先級高;
dom

後面是5flags,對應的flag 若是被置1 , 就在flags字段追加相應的數據
 PCR_flag:PCR標誌位,佔位1bit,置位1表示調整字段中包含PCR字段,置位0則沒有PCR字段;

PCR字段:當PCR_flag == 1時,此字段才存在,佔位48bit,依次順序爲:ide

●program_clock_reference_base字段:         佔位33bit;ui

●reserved字段:                                                佔位6bit;編碼

●program_clock_reference_extension字段:佔位9bit;加密

 OPCR_flag :OPCR標誌位,佔位1bit,置位1表示調整字段中包含OPCR字段,置位0則沒有OPCR字段;

OPCR字段:當OPCR_flag == 1時,此字段才存在,佔位48bit,依次順序爲:spa

original_program_clock_reference_base字段:         佔位33bit;

reserved字段:                                                               佔位6bit;

original_program_clock_reference_extension字段:佔位9bit;

 splicing_point_flag :splice_countdown標誌位,佔位1bit,置位1表示調整字段中包含splice_countdown字段,置位0則沒有splice_countdown字段;
 splice_countdown字段:當splicing_point_flag == 1時此字段存在,佔位8bit;
 transport_private_data_flag :transport_private_data標誌位,佔位1bit,置位1時表示調整字段中含有1個或者多個私有數據字節,置位0則無此字節;

transport_private_data字段:私有數據字段,當transport_private_data_flag == 1時此字段存在,佔位N*8bit,字節順序爲:

transport_private_data_length:代表私有數據的字節長度,佔位8bit;

private_data_byte:私有數據,長度由前面的長度字段肯定;

 adaptation_field_extension_flag:調整字段擴展標誌位,佔位1bit,置位1表示含有調整字段擴展字段,置位0則無擴展字段;

adaptation_field_extension字段:調整字段擴展字段,佔用長度不肯定,當adaptation_field_extension_flag == 1時此字段存在,字段中也有3個標誌位,來肯定一些字段存不存在,其具體字節順序以下:

adaptation_field_extension_length:調整字段擴展字段的長度,佔位8bit;

ltw_flag:ltw字段標誌位,置位1時表示此字段存在,佔位1bit;

piecewise_rate_flag:piecewise_rate字段標誌位,置位1時此字段存在,佔位1bit;

seamless_splice_flag:seamless_splice標誌位,置位1時此字段存在,佔位1bit;

Reserved:保留字段,佔位5bit;

Ltw字段:當ltw_flag == 1時此字段存在,佔位16bit,其由如下兩個字段組成

ltw_valid_flag:佔位1bit,當ltw_valid_flag == 1時,ltw_offset纔有效;

ltw_offset:佔位15bit;

piecewise_rate字段:當piecewise_rate_flag == 1時此字段存在,佔位24bit,其字節順序以下:

reserved字段:保留字段,佔位2bit;

piecewise_rate字段:佔位22bit;此字段只有在當ltw_flag == 1和ltw_valid_flag == 1時纔有定義,有定義時此字段是一個正整數;

seamless_splice字段:當seamless_splice_flag == 1時此字段存在,佔位40bit;字節順序依次爲:

splice_type字段:佔位4bit;標識delay和rate值;

DTS_next_AU[32..30]:佔位3bit;

marker_bit字段:佔位1bit;

DTS_next_AU[29..15]字段:佔位15bit;

marker_bit:佔位1bit;

DTS_next_AU[14..0]:佔位15bit;

marker_bit:佔位1bit;

stuffing_byte:填充字段,固定爲0xFF

Payload_bytes:有效負載字段,字節來自PES包,PSI部分等;

 

➤PES頭
    PES流是對原始ES流進行的第一層封裝,PES流的基本單位是PES包,由包頭和payload組成,ES流即音視頻裸流,是從編碼器裏面出來的原始視頻音頻流;ES流只包含一種內容,裏面是視頻或者音頻;封裝時不對其進行改變,只在前面添加頭部,如私有頭,解碼時,將私有頭剝掉,將原始ES碼流送進解碼器解碼,這也是解碼通用性,如果修改了,則其餘解碼器就無法解碼了;PES和ES同樣,都是單一原始碼流,通常我遇到的是一幀數據放在一個PES包裏面,可是一個PES包的最大長度爲65535字節,所以一幀數據有可能被分爲多個PES;其包頭格式以下。

    能夠看出,PES包是由固定包頭,可選包頭和負載三部分組成,其中固定包頭固定6個字節;PES包長度字段佔位16bit,最大值爲65536,故一幀可能會分爲多個PES包下面依次介紹其每一個字段的含義:

Packet start code prefix:包頭起始碼,固定爲0x000001,佔位24bit

Stream id(UI)PES包中的負載流類型,通常視頻爲0xe0,音頻爲0xc0,佔位8bit

PES packet length(UI)PES包長度,包括此字節後的可選包頭和負載的長度,佔位16bit

 Optional PES Header,順序依次爲:

 

➣'10'字段:佔位2bit

PES scrambling control:加密模式,佔2bit00未加密,011011由用戶定義;

PES priority:有效負載的優先級,佔位1bit;值爲1比值爲0的負載優先級高;

Data alignment indicator:數據定位指示器,佔位1bit

Copyright:版權信息,1爲有版權,0無版權,佔位1bit

Original or copy:原始或備份,1爲原始,0爲備份,佔位1bit

後面是7flags,對應的flag 若是被置1 , 就在PES header data length字段後追加相應的數據(通常咱們關注的就是PTS DTS的標誌位)

PTS_DTS_flagsPTSDTS標誌位,佔位2bit10表示首部有PTS字段,11表示有PTSDTS字段,00表示都沒有,01被禁止,不會出現此種狀況;

 

      PTS/DTS字段:顯示時間戳/解碼時間戳,佔位40bit,當PTS_DTS_flags == 1x時此字段存在;時間佔用33bitPTSDTS的內容是在這40bit中取33位,方式相同;

   PTS(presentation time stamp)顯示時間戳和DTS(Decoding Time Stamp)解碼時間戳,是用來音視頻同步的,是打在PES包的包頭裏面的,PTS/DTS是相對SCR(系統參考)的時間戳,是以90000爲單位的,PTS/DTS到ms的轉換公式是PTS/90,系統時鐘頻率(H264採樣頻率?)爲90Khz,因此轉換到秒爲PTS/90000,因此若是是以ms爲單位的播放器,PTS/DTS是要使用公式ms=pts/90來轉換才行的,而若是是以時鐘頻率爲單位的話,則直接將PTS/DTS送進去解碼便可;若是沒有B幀,PTS和DTS的順序應該是一致的,若是有B幀,則須要先解碼P幀,才能解出來B幀,因此須要PTS和DTS來控制解碼時間和顯示時間;

字節順序依次:

start_code:起始碼,佔位4bit;若PTS_DTS_flags == ‘10’,則說明只有PTS,起始碼爲0010;若PTS_DTS_flags == ‘11’,則PTSDTS都存在,PTS的起始碼爲0011DTS的起始碼爲0001(PTS的起始碼後2bitflag相同)

PTS[32..30]:佔位3bit

marker_bit佔位1bit

PTS[29..15]:佔位15bit

marker_bit:佔位1bit

PTS[14..0]:佔位15bit

marker_bit:佔位1bit

PTS/DTS  = PTS1 & 0x0e) << 29 + (PTS2 & 0xfffe) << 14 + (PTS3 & 0xfffe ) >> 1;

 


ESCR_flagESCR標誌,佔位1bit1表示首部有ESCR字段,0則無此字段

 

ESCR字段:此字段佔位48bit,由33bitESCR_base字段和9bitESCR_extension字段組成,ESCR_flag == 1時此字段存在;數據依次順序:

Reserved保留字段,佔位2bit

ESCR_base[32..30]:佔位3bit

marker_bit佔位1bit

ESCR_base[29..15]:佔位15bit

marker_bit佔位1bit

ESCR_base[14..0]:佔位15bit

marker_bit:佔位1bit

ESCR_extension(UI)佔位9bit;週期數,取值範圍0~299;循環一次,base+1

marker_bit:佔位1bit


ES_rate_flagES_rate字段,佔位1bit1表示首部有此字段,0無此字段;

 

ES rate字段:目標解碼器接收PES分組字節速率,禁止爲0佔位24bitES_rate_flag == 1時此字段存在;數據順序爲:

marker_bit:佔位1bit

ES_rate佔位22bit

marker_bit佔位1bit


DSM_trick_mode_flag:佔位1bit1表示有8位的DSM_trick_mode_flag字段,0無此字段;

 

Trick mode control字段:表示哪一種trick mode被應用於相應的視頻流,佔位8bitDSM_ trick_mode_flag == 1時此字段存在;其中trick_mode_control佔前3bit,根據其值後面有5bit的不一樣內容;

若是trick_mode_control == ‘000’,依次字節順序爲:

field_id:佔位2bit

intra_slice_refresh 佔位1bit

frequency_truncation:佔位2bit

若是trick_mode_control == ‘001’,依次字節順序爲:

rep_cntrl:佔位5bit

若是trick_mode_control == ‘010’,依次字節順序爲:

field_id:佔位2bit

Reserved:佔位3bit

若是trick_mode_control == ‘011’,依次字節順序爲:

field_id:佔位2bit

intra_slice_refresh:佔位1bit

frequency_truncation:佔位2bit

若是trick_mode_control== ‘100’,依次字節順序爲:

rep_cntrl:佔位5bit

其餘狀況,字節順序爲:

reserved :佔位5bit; 

 


Additional_copy_info_flag:佔位1bit1表示首部有此字段,0表示無此字段;

 

Additional copy info字段8bitAdditional_copy_info_flag == 1時此字段存在;數據順序爲:

marker_bit:佔位1bit

copy info字段:佔位7bit;表示和版權相關的私有數據;


PES_CRC_flag:佔位1bit;置1表示PES分組有CRC字段,0無此字段;

 

Previous PES CRC字段:佔位16bit字段,包含CRC值,PES_CRC_flag == 1時此字段存在;


PES_extension_flag:佔位1bit;擴展標誌位,置1表示有擴展字段,0無此字段

 

PES exten sion字段PES擴展字段,PES_extension_flag == 1時此字段存在;內容以下,字節順序依次爲

 

PES_private_data_flag:佔位1bit,置1表示有私有數據,0則無;

PES_private_data字段:私有數據內容,佔位128bitPES_private_data_flag == 1時此字段存在;

 

 

Pack_header_field_flag:佔位1bit1表示有Pack_header_field字段,0則無

Pack_header_field字段Pack_header_field_flag == 1時此字段存在;字段組成順序以下:

 

Pack_field_length字段(UI)指定後面的field的長度,佔位8bit

pack_header_field()長度爲Pack_field_length指定;

 

 

Program_packet_sequence_counter_flag佔位1bit,置1表示有此字段,0則無;

Program_packet_sequence_counter字段:計數器字段,16bit;當flag字段Program_packet_sequence_counter_flag == 1時此字段存在;字節順序依次爲:

 

marker_bit:佔位1bit

 

packet_sequence_counter字段(UI)佔位7bit

 

marker_bit佔位1bit

 

MPEG1_MPEG2_identifier佔位1bit;置位1表示此PES包的負載來自MPEG1流,置位0表示此PES包的負載來自PS流;

 

original_stuff_length(UI)佔位6bit;表示PES頭部填充字節長度; 

 

 

P-STD_buffer_flag:佔位1bit,置1表示有P-STD_buffer字段,0則無此字段;

P-STD_buffer字段:表示P-STD_buffer內容,佔位16bitP-STD_buffer_flag == '1'時此字段存在;字節順序依次爲:

 

’01’字段:佔位2bit

 

P-STD_buffer_scale:佔位1bit;表示用來解釋後面P-STD_buffer_size字段的比例因子;若是以前的stream_id表示音頻流,則此值應爲0,若以前的stream_id表示視頻流,則此值應爲1,對於其餘stream類型,此值能夠01

 

P-STD_buffer_size佔位13bit;無符號整數;大於或等於全部P-STD輸入緩衝區大小BSn的最大值;若P-STD_buffer_scale == 0,則P-STD_buffer_size128字節爲單位;若P-STD_buffer_scale == 1,則P-STD_buffer_size1024字節爲單位;

 

 

Reserved字段3bit

 

PES_extension_flag_2:佔位1bit,置1表示有擴展字段,0則無此字段;

PES_extension2字段:擴展字段的擴展字段;佔用N*8bitPES_extension_flag_2 == '1'時此字段存在;字節順序依次爲:

 

marker_bit佔位1bit

 

PES_extension_field_length:佔位7bit,表示擴展區域的長度;

 

Reserved字段:佔位8*PES_extension_field_lengthbit

 

Stuffing bytes:填充字段,固定爲0xFF;不能超過32個字節;

 

PES_packet_data_bytePES包負載中的數據,即ES原始流數據

PES header data length(UI)PES首部中可選字段和填充字段的長度;佔位8bit;可選字段的內容由上面7flags來進行控制;

相關文章
相關標籤/搜索