<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    TS數據結構分析

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    1.TS包得數據結構

    RFID設備管理軟件

    2.

    // Transport packet header
    typedef struct TS_packet_header
    {
        unsigned sync_byte                                         :    8;    //同步字節,固定為0x47 ,表示后面的是一個TS分組,當然,后面包中的數據是不會出現0x47的
        unsigned transport_error_indicator              :    1;      //傳輸錯誤標志位,一般傳輸錯誤的話就不會處理這個包了
        unsigned payload_unit_start_indicator        :     1;      //有效負載的開始標志,根據后面有效負載的內容不同功能也不同
        unsigned transport_priority                             :     1;      //傳輸優先級位,1表示高優先級
        unsigned PID                                                     :     13;     //有效負載數據的類型
        unsigned transport_scrambling_control      :     2;      //加密標志位,00表示未加密
        unsigned adaption_field_control                   :     2;      //調整字段控制,。01僅含有效負載,10僅含調整字段,11含有調整字段和有效負載。為00的話解碼器不進行處理。
        unsigned continuity_counter                           :    4;    //一個4bit的計數器,范圍0-15
    } TS_packet_header; 

     

     

    TS包頭定義:

    typedef struct TS_packet_header
    {
        unsigned sync_byte                        : 8; //同步字節, 固定為0x47,表示后面的是一個TS分組
        unsigned transport_error_indicator        : 1; //傳輸誤碼指示符
        unsigned payload_unit_start_indicator    : 1; //有效荷載單元起始指示符
       
        unsigned transport_priority              : 1; //傳輸優先, 1表示高優先級,傳輸機制可能用到,解碼用不著
        unsigned PID                            : 13; //PID
        unsigned transport_scrambling_control    : 2; //傳輸加擾控制 
        unsigned adaption_field_control            : 2; //自適應控制 01僅含有效負載,10僅含調整字段,11含有調整字段和有效負載。為00解碼器不進行處理
        unsigned continuity_counter                : 4; //連續計數器 一個4bit的計數器,范圍0-15
    } TS_packet_header;

     

    TS包頭解析代碼:

    HRESULT CTS_Stream_Parse::adjust_TS_packet_header( TS_packet_header* TS_header )
    {
     unsigned char buf[4]; 
     
        memcpy(buf, TS_header, 4);
        TS_header->transport_error_indicator        = buf[1] >> 7;
        TS_header->payload_unit_start_indicator    = buf[1] >> 6 & 0x01;
        TS_header->transport_priority                = buf[1] >> 5 & 0x01;
        TS_header->PID                            = (buf[1] & 0x1F) << 8 | buf[2];
        TS_header->transport_scrambling_control    = buf[3] >> 6;
        TS_header->adaption_field_control            = buf[3] >> 4 & 0x03;
        TS_header->continuity_counter                = buf[3] & 0x0F; // 四位數據,應為0x0F xyy 09.03.18

     return 0;
    }

     

    3.PSI

    全稱Program Specific Information,意為節目專用信息。傳輸流中是多路節目復用的,那么,怎么知道這些節目在傳輸流中的位置,區分屬于不同節目呢?所以就還需要一些附加信息,這就是PSI。PSI也是插入到TS分組中的,它們的PID是特定值。MPEG-2中規定了4個PSI,包括PAT(節目關聯表),CAT(條件訪問表),PMT(節目映射表),NIT(網絡信息表),這些PSI包含了進行多路解調和顯示節目的必要的和足夠的信息.PSI的PID是特定的,含PSI的數據包必須周期性的出現在傳輸流中。

    PMT (Program Map Table )節目映射表PMT所在分組的PID由PAT指定,所以要先解出PAT,再解PMT。PMT中包含了屬于同一節目的視頻、音頻和數據原始流的PID。找到了PMT,解多路復用器就可找到一道節目對應的每個原始流的PID,再根據原始流PID,去獲取原始流。

    PAT (Program Association Table )節目關聯表PAT所在分組的PID=0 PAT中列出了傳輸流中存在的節目流PAT指定了傳輸流中每個節目對應PMT所在分組的PIDPAT的第一條數據指定了NIT所在分組的PID ,其他數據指定了PMT所在分組的PID,一個節目包含多少個節目就含有多少PMT。

    CAT (Conditional Access Table )條件訪問表CAT所在分組的PID=1CAT中列出了條件控制信息(ECM)和條件管理信息(EMM)所在分組的PID。CAT用于節目的加密和解密 NIT( Network Information Table)網絡信息表

    NIT所在分組的PID由PAT指定NIT提供一組傳輸流的相關信息,以及于網絡自身特性相關的信息,比如網絡名稱,傳輸參數(如頻率,調制方式等)。NIT一般是解碼器內部使用的數據,當然也可以做為EPG的一個顯示數據提供給用戶做為參考。

    幾種PSI之間的關系,如下圖所示:首先PAT中指定了傳輸流中所存在的節目,及每個節目對應的PMT的PID號。 比如Program 1對應的PMT 的PID=22,然后找到PID=22的TS分組,解出PMT,得到這個節目中包含的原始流的PID,再根據原始流的PID去找相應的TS分組,獲取原始流的數據,然后就可以送入解碼器解碼了。

     

    PSI由四張表構成:PAT,PMT,CAT和NIT,這四張表分別描述了一個TS所包括的所有ES流的傳輸結構。首先的一個概念是,TS是以包形式傳播,在編解碼端都需要以一定的包ID來標識TS流里承載的內容,比如,PAT表會存在于一個或多個TS包里,所以要用一個特別的包ID來表示,另外,不同的ES流也需要不同的包ID來標識。我們有了PAT和PMT這兩種表,解碼器就可以根據 PID,將TS上從不同ES來的TS包區分出來進行解碼。

    TS的解碼分兩步進行,其一,是從PID為0 的TS包里,解析出PAT表,然后從PAT表里找到各個節目源的PID,一般此類節目源都由若干個ES流組成,并描述在PMT表里面,然后通過節目源的 PID,就可以在PMT表里檢索到各個ES的PID。其二,解碼器根據PMT表里的ES流的PID,將TS流上的包進行區分,并按不同的ES流進行解碼。所以,TS是經過節目復用和傳輸復用兩層完成的,即在節目復用時,加入了PMT,在傳輸復用時,加入了PAT。同樣在節目解復用時,可以得到PMT,在傳輸解復用時,可以得到PAT。

    RFID設備管理軟件

    4.PAT表數據結構

    RFID設備管理軟件

     

    數據結構PAT Table

    //PAT Table
    program_association_section() {
           table_id                      : 8;    //固定為0x00 ,標志是該表是PAT
       section_syntax_indicator           : 1;    //段語法標志位,固定為1    
       '0'                                : 1;    //0
       reserved                           : 2;    //保留
       section_length                     : 12;    //表示這個字節后面有用的字節數,包括CRC32。假如后面的字節加上前面的字節數少于188,后面會用0XFF填充。假如這個數值比較大,則PAT會分成幾部分來傳輸


       transport_stream_id                : 16    //該傳輸流的ID,區別于一個網絡中其它多路復用的流。
       reserved                           : 2    //保留
       version_number                     : 5    //范圍0-31表示PAT的版本號,標注當前節目的版本這是個非常有用的參數,當檢測到這個字段改變時,說明TS流中的節目已經變化了,程序必須重新搜索節目.
       current_next_indicator             : 1    //表示發送的PAT是當前有效還是下一個PAT有效。
       section_number                     : 8    //分段的號碼。PAT可能分為多段傳輸,第一段為00,以后每個分段加1,最多可能有256個分段
       last_section_number                : 8    //最后一個分段的號碼
       for (i=0; i<N;i++) {
           program_number                 : 16    //節目號
           reserved                       : 3    //保留
         if(program_number == '0') {
             network_PID                  : 13    //網絡信息表(NIT)的PID,網絡信息表提供了該物理網絡的一些信息,和電視臺相關的。節目號為0時對應的PID為network_PID
           }
         else {
            program_map_PID               : 13    //節目映射表的PID,節目號大于0時對應的PID,每個節目對應一個
          }
      }
     CRC_32                               : 32
    }

     

    //PAT表結構體
    typedef struct TS_PAT
    {
        unsigned table_id                        : 8; //固定為0x00 ,標志是該表是PAT
        unsigned section_syntax_indicator        : 1; //段語法標志位,固定為1
        unsigned zero                            : 1; //0
        unsigned reserved_1                        : 2; // 保留位
        unsigned section_length                    : 12; //表示這個字節后面有用的字節數,包括CRC32
        unsigned transport_stream_id            : 16; //該傳輸流的ID,區別于一個網絡中其它多路復用的流
        unsigned reserved_2                        : 2;// 保留位
        unsigned version_number                    : 5; //范圍0-31,表示PAT的版本號
        unsigned current_next_indicator            : 1; //發送的PAT是當前有效還是下一個PAT有效
        unsigned section_number                    : 8; //分段的號碼。PAT可能分為多段傳輸,第一段為00,以后每個分段加1,最多可能有256個分段
        unsigned last_section_number            : 8;  //最后一個分段的號碼
     
     std::vector<TS_PAT_Program> program;
        unsigned reserved_3                        : 3; // 保留位
        unsigned network_PID                    : 13; //網絡信息表(NIT)的PID,節目號為0時對應的PID為network_PID

        unsigned CRC_32                            : 32;  //CRC32校驗碼
    } TS_PAT;

     

     

    HRESULT CTS_Stream_Parse::adjust_PAT_table( TS_PAT * packet, unsigned char * buffer)
    {
        packet->table_id                    = buffer[0];
        packet->section_syntax_indicator    = buffer[1] >> 7;
        packet->zero                        = buffer[1] >> 6 & 0x1;
        packet->reserved_1                    = buffer[1] >> 4 & 0x3;
        packet->section_length                = (buffer[1] & 0x0F) << 8 | buffer[2]; 
     
        packet->transport_stream_id            = buffer[3] << 8 | buffer[4];
     
        packet->reserved_2                    = buffer[5] >> 6;
        packet->version_number                = buffer[5] >> 1 &  0x1F;
        packet->current_next_indicator        = (buffer[5] << 7) >> 7;
        packet->section_number                = buffer[6];
        packet->last_section_number            = buffer[7];

        int len = 0;
        len = 3 + packet->section_length;
        packet->CRC_32                        = (buffer[len-4] & 0x000000FF) << 24
      | (buffer[len-3] & 0x000000FF) << 16
      | (buffer[len-2] & 0x000000FF) << 8 
      | (buffer[len-1] & 0x000000FF); 
     
      
     int n = 0;
        for ( n = 0; n < packet->section_length - 12; n += 4 )
        {
      unsigned  program_num = buffer[8 + n ] << 8 | buffer[9 + n ];  
            packet->reserved_3                = buffer[10 + n ] >> 5; 
      
      packet->network_PID = 0x00;
      if ( program_num == 0x00)
      {  
                packet->network_PID = (buffer[10 + n ] & 0x1F) << 8 | buffer[11 + n ];

       TS_network_Pid = packet->network_PID; //記錄該TS流的網絡PID

       TRACE(" packet->network_PID %0x /n/n", packet->network_PID );
      }
            else
            {
       TS_PAT_Program PAT_program;
       PAT_program.program_map_PID = (buffer[10 + n] & 0x1F) << 8 | buffer[11 + n];
       PAT_program.program_number = program_num;
       packet->program.push_back( PAT_program );
       
       TS_program.push_back( PAT_program );//向全局PAT節目數組中添加PAT節目信息     
            }         
        }
     return 0;
    }

     

    //PMT Table

    TS_program_map_section(){ 
        table_id : 8;                //固定為0x02 ,標志是該表是PMT。
        section_syntax_indicator :  1;        //段語法標志位,固定為1    
         '0' : 1;                //0
        reserved : 2;                //保留
        section_length : 12;            //表示這個字節后面有用的字節數,
        program_number : 16;            //節目號,表示該PMT對應的節目
        reserved : 2;                //保留
        version_number : 5;
        current_next_indicator :1;        
        section_number : 8;
        last_section_number : 8;
        reserved : 3;     
        PCR_PID : 13                 //PCR(節目時鐘參考)所在TS分組的PID,根據PID可以去搜索相應的TS分組,解出PCR信息。
        reserved : 4;
        program_info_length:  12;        //該節目的信息長度
        for (i=0; i<N; i++) { 
            descriptor() 
        } 
        for (i=0;i<N1;i++) { 
            stream_type : 8;         //指示了PID為elementary_PID的PES分組中原始流的類型,比如視頻流,音頻流等,見后面的表
            reserved : 3;            
            elementary_PID : 13;        //該節目中包括的視頻流,音頻流等對應的TS分組的PID
            reserved : 4; 
            ES_info_length : 12;        //該節目相關原始流的描述符的信息長度
            for (i=0; i<N2; i++) { 
                descriptor() 
            } 
        } 
        CRC_32 : 32 
    }

     

     

    PMT結構定義:


    typedef struct TS_PMT_Stream
    {
     unsigned stream_type                    : 8; //指示特定PID的節目元素包的類型。該處PID由elementary PID指定
     unsigned elementary_PID                    : 13; //該域指示TS包的PID值。這些TS包含有相關的節目元素
     unsigned ES_info_length                    : 12; //前兩位bit為00。該域指示跟隨其后的描述相關節目元素的byte數
     unsigned descriptor;
    }TS_PMT_Stream;

    //PMT 表結構體
    typedef struct TS_PMT
    {
        unsigned table_id                        : 8; //固定為0x02, 表示PMT表
        unsigned section_syntax_indicator        : 1; //固定為0x01
        unsigned zero                            : 1; //0x01
        unsigned reserved_1                      : 2; //0x03
        unsigned section_length                  : 12;//首先兩位bit置為00,它指示段的byte數,由段長度域開始,包含CRC。
        unsigned program_number                    : 16;// 指出該節目對應于可應用的Program map PID
        unsigned reserved_2                        : 2; //0x03
        unsigned version_number                    : 5; //指出TS流中Program map section的版本號
        unsigned current_next_indicator            : 1; //當該位置1時,當前傳送的Program map section可用;
       //當該位置0時,指示當前傳送的Program map section不可用,下一個TS流的Program map section有效。
        unsigned section_number                    : 8; //固定為0x00
        unsigned last_section_number            : 8; //固定為0x00
        unsigned reserved_3                        : 3; //0x07
        unsigned PCR_PID                        : 13; //指明TS包的PID值,該TS包含有PCR域,
                //該PCR值對應于由節目號指定的對應節目。
                //如果對于私有數據流的節目定義與PCR無關,這個域的值將為0x1FFF。
        unsigned reserved_4                        : 4; //預留為0x0F
        unsigned program_info_length            : 12; //前兩位bit為00。該域指出跟隨其后對節目信息的描述的byte數。
        
     std::vector<TS_PMT_Stream> PMT_Stream;  //每個元素包含8位, 指示特定PID的節目元素包的類型。該處PID由elementary PID指定
        unsigned reserved_5                        : 3; //0x07
        unsigned reserved_6                        : 4; //0x0F
        unsigned CRC_32                            : 32; 
    } TS_PMT;

     

    解析代碼為:

    HRESULT CTS_Stream_Parse::adjust_PMT_table ( TS_PMT * packet, unsigned char * buffer )

        packet->table_id                            = buffer[0];
        packet->section_syntax_indicator            = buffer[1] >> 7;
        packet->zero                                = buffer[1] >> 6 & 0x01; 
        packet->reserved_1                            = buffer[1] >> 4 & 0x03;
        packet->section_length                        = (buffer[1] & 0x0F) << 8 | buffer[2];    
        packet->program_number                        = buffer[3] << 8 | buffer[4];
        packet->reserved_2                            = buffer[5] >> 6;
        packet->version_number                        = buffer[5] >> 1 & 0x1F;
        packet->current_next_indicator                = (buffer[5] << 7) >> 7;
        packet->section_number                        = buffer[6];
        packet->last_section_number                    = buffer[7];
        packet->reserved_3                            = buffer[8] >> 5;
        packet->PCR_PID                                = ((buffer[8] << 8) | buffer[9]) & 0x1FFF;

     PCRID = packet->PCR_PID;

        packet->reserved_4                            = buffer[10] >> 4;
        packet->program_info_length                    = (buffer[10] & 0x0F) << 8 | buffer[11]; 
        // Get CRC_32
     int len = 0;
        len = packet->section_length + 3;    
        packet->CRC_32                = (buffer[len-4] & 0x000000FF) << 24
      | (buffer[len-3] & 0x000000FF) << 16
      | (buffer[len-2] & 0x000000FF) << 8
      | (buffer[len-1] & 0x000000FF);

     int pos = 12;
        // program info descriptor
        if ( packet->program_info_length != 0 )
            pos += packet->program_info_length;    
        // Get stream type and PID    
        for ( ; pos <= (packet->section_length + 2 ) -  4; )
        {
      TS_PMT_Stream pmt_stream;
      pmt_stream.stream_type =  buffer[pos];
      packet->reserved_5  =   buffer[pos+1] >> 5;
      pmt_stream.elementary_PID =  ((buffer[pos+1] << 8) | buffer[pos+2]) & 0x1FFF;
      packet->reserved_6     =   buffer[pos+3] >> 4;
      pmt_stream.ES_info_length =   (buffer[pos+3] & 0x0F) << 8 | buffer[pos+4];
      
      pmt_stream.descriptor = 0x00;
      if (pmt_stream.ES_info_length != 0)
      {
       pmt_stream.descriptor = buffer[pos + 5];
       
       for( int len = 2; len <= pmt_stream.ES_info_length; len ++ )
       {
        pmt_stream.descriptor = pmt_stream.descriptor<< 8 | buffer[pos + 4 + len];
       }
       pos += pmt_stream.ES_info_length;
      }
      pos += 5;
      packet->PMT_Stream.push_back( pmt_stream );
      TS_Stream_type.push_back( pmt_stream );
        }
     return 0;
    }

     

    //CheckOut 數據宏

    從byteVar的某位,獲取獲取指定的位值

    #define GET1BIT(byteVar, fromBit) ((byteVar >> (8 - (fromBit))) & 0x01)
    #define GET2BIT(byteVar, fromBit) ((byteVar >> (7 - (fromBit))) & 0x03)
    #define GET3BIT(byteVar, fromBit) ((byteVar >> (6 - (fromBit))) & 0x07)
    #define GET4BIT(byteVar, fromBit) ((byteVar >> (5 - (fromBit))) & 0x0F)
    #define GET5BIT(byteVar, fromBit) ((byteVar>>  (4 - (fromBit))) & 0x1F)
    #define GET6BIT(byteVar, fromBit) ((byteVar >> (3 - (fromBit))) & 0x3F)
    #define GET7BIT(byteVar, fromBit) ((byteVar >> (2 - (fromBit))) & 0x7F)
    #define GET8BIT(byteVar, fromBit) ((byteVar >> (1 - (fromBit))) & 0xFF)

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全