數字電視節目碼流的PMT表分析

節目映射表提供節目號與組成它們的所有原始碼流之間的映射,其PID由所在TS中的PAT表指定,PMT以program_map_section的形式進行TS打包。
    我們知道,單路節目的TS是由具有相同時間基點的PES流複用而成的,典型情況下包含一路視頻PES流、多路音頻PES
流,還有teletext、subtitle等PES,各路PES的PID就在這張表中指定。因此,解析這張表就可以知道一路節目是由哪些PES組成的,其PID是多少?這樣有利於解碼器根據找出相應的PID,進行音視頻解碼。

    PMT section的header部分爲8個字節,由表標識符(以區別於其他table)、section長度、節目號、版本號、section號、最後一個section號組成。緊接着會提供本節目進行收發同步參考的PCR PID,節目信息長度及其描述符(描述符會單獨分析),節目所含的基本流信息。

 

語法結構

  (略) 

表中:
Table id:8bit域,在TS流中Program map section將置爲0x02。
Section syntax indicator:1bit域,對於PMT表,設置爲1。
Zero:1bit域,設置爲0。
Reserved:2bit域,預留爲11(0x3)。
Section length:12bit域,首先兩位bit置爲00,它指示段的byte數,由段長度域開始,包含CRC字段4個字節,因此在寫解析代碼時需要注意。
Program number:16bit域,它指出該節目對應於可應用的Program map PID。一個節目定義僅含一個TS流的Progrmn
 map section。這意味着一個節目的定義不超過1016Byte。
Reserved:2bit域,預留爲11(0x3)。
Version number:5bit域,指出TS流中Program map section的版本號。當段中有關信息發生變化,版本號將以32爲
模加1。版本號是關於一個節目的定義,因此版本號是關於單一段的定義,該字段用於service中各組成部分的信息發生更新,例如當視頻PID變化。
Current next indicator:1bit域,當該位置1時,當前傳送的Program map section可用;當該位置0時,指示當前
傳送的Program map section不可用,下一個TS流的Program map section有效。
Section number:8bit域,總是置爲0x00(因爲PMT表裏表示一個service的信息,一個section的長度足夠)。
Last section number:8bit域,該域的值總是0x000。
Reserved:3bit域,預留爲111(0x7)。
PCR PID:13bit域,指明TS包的PID值,該TS包含有PCR域,該PCR值對應於由節目號指定的對應節目。如果對於私有
數據流的節目定義與PCR無關,這個域的值將爲0×1FFF。
Reserved:4bit域,預留爲1111(0xF)。
Program info length:12bit域,前兩位bit爲00。該域指出跟隨其後對節目信息的描述的byte數。
Stream type:8bit域,指示特定PID的節目元素包的類型。該處PID由elementary PID指定。該域值爲0×2時,指示
ITU-TRECH262|ISO/IEC13818-2video或ISO/IEC11172-2constrained parameter video stream。

 

【碼流示例】

  Program_number爲0x65的TS包以及PMT如下:

數字電視節目碼流中的PMT表分析
 

上面的數據解析如下圖:

 
數字電視節目碼流中的PMT表分析
 
 
下面一段代碼用來取得PMT表的頭信息,如下:

ErrorCode_t ParsePMTHead(U8* pSectionData, PMT_HEAD *pHead)
{
    ErrorCode_t err = NO_ERROR;
 
    if(NULL == pSectionData || NULL == pHead)
   {
      err = ERROR_FAME;
   }
   else
   {
      pHead->m_uTableID = pSectionData[0];  /*恆爲0x02*/
      pHead->m_uSectLen = SECTION_LENGTH(pSectionData[1], pSectionData 

          [2]); /*PMT section的長度*/
      pHead->m_uServiceId= USHORT_LENGTH(pSectionData[3], pSectionData

          [4]); /*節目號,program_number*/
      pHead->m_uVersion = (pSectionData[5] & 0x3E) >> 1; 

      pHead->m_PCRPID = PID_LENGTH(pSectionData[8] , pSectionData

          [9]); /*PCR PID*/

     //描述符長度,循環
     pHead->m_uProgLen = SECTION_LENGTH(pSectionData[10], pSectionData

          [11]); /*節目信息的長度*/
     pHead->m_pProgData = pSectionData + 12;  /*節目信息循環開始地址*/

    //流信息長度,循環
     pHead->m_uStreamInfoLen = (pHead->m_uSectLen) - (pHead-

         >m_uProgLen) - 13; /*流描述信息長度*/

     /*流描述數據開始地址*/
     pHead->m_pStreamData = (pHead->m_pProgData) + pHead->m_uProgLen;   
    
 err = NO_ERROR;
   }
  return err; 
}

    在取得PMT表頭信息後,接下來的代碼主要用於獲取該節目各組成部分信息,對兩處描述符的解析等等,注意要隨時與中間件部分的節目管理和頻道管理模塊聯繫起來。
    PMT中會包含多種描述符,如CA_descriptor、stream_identifier_descriptor等,至於具體有哪些描述符,往往需要分析實際的碼流才能決定。
    此外,需要注意的是,在後一個循環對基本流的描述部分,有時候對於一個視頻可能對應幾個音頻流,這就需要在應用層做相應的處理;此外如果包含CA_descriptor,其中的CA_PID是ECM表的PID。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章