Parsing Transport stream PAT and PMT

//TSStructs.h

#ifndef __TSSTRUCTS_H_LUCKYLIU_H__
#define __TSSTRUCTS_H_LUCKYLIU_H__

#include <list>

#define WW_PATPID  (0x0000)
#define WW_PATTABLEID (0x00)
#define WW_PMTTABLEID (0x02)
#define WW_TSPACKET_LEN (188)
#define WW_TSSYNCBYTE (0x47)

//TSPACKET
//One ts packet is contained by TSPacketHeader, adaption field, payload data.
//If there is adaption filed, adaption field length is specified by the first byte after TSPacketHeader.
//Payload bytes length is the remained bytes.

typedef struct WW_TSPACKETHEAD_ //4 BYTES
{
 unsigned char ucSyncByte;       // First byte
 unsigned char PID_hibits : 5;      // Second byte - Notice the reverse declaration
 unsigned char  transport_priority : 1;
 unsigned char  payload_unit_start_indicator : 1;
 unsigned char transport_error_indicator : 1;
 unsigned char PID_lobits;       // Third byte
 unsigned char continuity_counter : 4;    // Fourth byte
 unsigned char _payload_present_flag : 1;
 unsigned char _adaptation_field_present_flag : 1;
 unsigned char transport_scrambling_control : 2;
} WW_TSPACKETHEAD, *PWW_TSPACKETHEAD;

//PAT
typedef struct WW_PATSECTIONHEAD_ //8 BYTES
{
 unsigned char table_id;
 unsigned char section_length_highbits : 4;
 unsigned char reserved_twobits : 2;
 unsigned char must_be_zero : 1;
 unsigned char section_syntax_indicator : 1;
 unsigned char section_length_lowbits;
 unsigned char transport_stream_id_hi;
 unsigned char transport_stream_id_lo;
 unsigned char current_next_indicator : 1;
 unsigned char version_number : 5;
 unsigned char reserved_twobits_2 : 2;
 unsigned char section_number;
 unsigned char last_section_number;
} WW_PATSECTIONHEAD, *PWW_PATSECTIONHEAD;

typedef struct WW_PATSECTIONPROTRAMMAP_// 4 BYTES
{
 unsigned char program_number_hi;
 unsigned char program_number_lo;
 unsigned char program_map_PID_highbits : 5;
 unsigned char reserved : 3;
 unsigned char program_map_PID_lo;
} WW_PATSECTIONPROTRAMMAP, *PWW_PATSECTIONPROTRAMMAP;
typedef std::list<WW_PATSECTIONPROTRAMMAP> WW_PATSECTIONPROTRAMMAPLIST;

//PMT
typedef struct WW_PMTSECTIONHEAD_ //12 BYTES
{
 unsigned char table_id;
 unsigned char section_length_highbits : 4;
 unsigned char reserved_twobits : 2;
 unsigned char must_be_zero : 1;
 unsigned char section_syntax_indicator : 1;
 unsigned char section_length_lowbits;
 unsigned char program_number_hi;
 unsigned char program_number_lo;
 unsigned char current_next_indicator : 1;
 unsigned char version_number : 5;
 unsigned char reserved_twobits_2 : 2;
 unsigned char section_number;
 unsigned char last_section_number;
 unsigned char PCR_PID_highbits : 5;
 unsigned char reserved_threebits : 3;
 unsigned char PCR_PID_lo;
 unsigned char program_info_length_highbits : 4;
 unsigned char reserved_fourbits : 4;
 unsigned char program_info_length_lo;
}WW_PMTSECTIONHEAD, *PWW_PMTSECTIONHEAD;

typedef struct WW_PMTSECTIONSTREAMMAP_ //5 BYTES
{
 unsigned char stream_type; //0x01 mpeg1 video; 0x02 mpeg2 video; 0x03 mpeg1 audio; 0x04 mpeg2 audio;
 unsigned char elementary_PID_highbits : 5;
 unsigned char reserved : 3;
 unsigned char elementary_PID_lo;
 unsigned char ES_info_length_hibits : 4;
 unsigned char reserved2 : 4;
 unsigned char ES_info_length_lo;
}WW_PMTSECTIONSTREAMMAP, *PWW_PMTSECTIONSTREAMMAP;
typedef std::list<WW_PMTSECTIONSTREAMMAP> WW_PMTSECTIONSTREAMMAPLIST;

typedef struct WW_TSPROGRAMSTREAMMAP_
{
 WORD wProgramNumber;
 WW_PMTSECTIONSTREAMMAPLIST lstStreamMap;
}WW_TSPROGRAMSTREAMMAP, *PWW_TSPROGRAMSTREAMMAP;
typedef std::list<WW_TSPROGRAMSTREAMMAP> WW_TSPROGRAMSTREAMMAPLIST;

typedef struct struWWTSVIDEO_
{
 WORD    wPID;
 WORD    wStreamID;
 //FORMAT_MPEG2Video videoFmt;
 char    szFmt[32];
}WWTSVIDEO, *PWWTSVIDEO;
typedef std::list<WWTSVIDEO> WWTSVIDEOLIST;

typedef struct struWWTSAUDIO_
{
 WORD    wPID;
 WORD    wStreamID;
 //FORMAT_WaveFormatEx audioFmt;
 char    szFmt[32];
}WWTSAUDIO, *PWWTSAUDIO;
typedef std::list<WWTSAUDIO> WWTSAUDIOLIST;

typedef struct WWTSPROGRAM_
{
 WORD wProgramNumber;
 WWTSVIDEOLIST lstVideo;
 WWTSAUDIOLIST lstAudio;
}WWTSPROGRAM, *PWWTSPROGRAM;
typedef std::list<WWTSPROGRAM> WWTSPROGRAMLIST;

#endif

#ifndef __WWTSPACKET_H_LUCKYLIU_H__
#define __WWTSPACKET_H_LUCKYLIU_H__

#include "TSStructs.h"

class WWTSPacket
{
public:
 WWTSPacket(void);
 virtual ~WWTSPacket(void);

public:
 BOOL  Load(BYTE* pBuffer, int nLen);
 virtual void Dump();
 WORD  GetPID();
 BYTE  GetTransportPriority();
 BYTE  GetPayloadUnitStartIndicator();
 BYTE  GetTransportErrorIndicator();
 BYTE  GetContinuityCounter();
 BOOL  HasPayload();
 BOOL  HasAdaptationField();
 BYTE  GetTransportScramblingControl();
 PBYTE GetPayload(WORD *pwLen);
 PBYTE GetAdaptationField(WORD *pwLen);

protected:
 PBYTE m_pTSPacket;

};

#endif

#include "StdAfx.h"
#include "./wwtspacket.h"

WWTSPacket::WWTSPacket(void)
{
 m_pTSPacket = new BYTE[WW_TSPACKET_LEN];
}

WWTSPacket::~WWTSPacket(void)
{
 delete[] m_pTSPacket;
}


BOOL  WWTSPacket::Load(BYTE* pBuffer, int nLen)
{
 if( nLen<WW_TSPACKET_LEN )
 {
  return FALSE;
 }

 if( *pBuffer!=WW_TSSYNCBYTE )
 {
  return FALSE;
 }

 memcpy(m_pTSPacket, pBuffer, WW_TSPACKET_LEN);
 return TRUE;
}

WORD WWTSPacket::GetPID()
{
 PWW_TSPACKETHEAD pTsHeader = (PWW_TSPACKETHEAD)m_pTSPacket;

 return MAKEWORD( pTsHeader->PID_lobits, pTsHeader->PID_hibits );
}

BYTE  WWTSPacket::GetTransportPriority()
{
 PWW_TSPACKETHEAD pTsHeader = (PWW_TSPACKETHEAD)m_pTSPacket;

 return pTsHeader->transport_priority;
}

BYTE  WWTSPacket::GetPayloadUnitStartIndicator()
{
 PWW_TSPACKETHEAD pTsHeader = (PWW_TSPACKETHEAD)m_pTSPacket;

 return pTsHeader->payload_unit_start_indicator;
}

BYTE  WWTSPacket::GetTransportErrorIndicator()
{
 PWW_TSPACKETHEAD pTsHeader = (PWW_TSPACKETHEAD)m_pTSPacket;

 return pTsHeader->transport_error_indicator;
}

BYTE  WWTSPacket::GetContinuityCounter()
{
 PWW_TSPACKETHEAD pTsHeader = (PWW_TSPACKETHEAD)m_pTSPacket;

 return pTsHeader->continuity_counter;
}

BOOL  WWTSPacket::HasPayload()
{
 PWW_TSPACKETHEAD pTsHeader = (PWW_TSPACKETHEAD)m_pTSPacket;

 return pTsHeader->_payload_present_flag;
}

BOOL  WWTSPacket::HasAdaptationField()
{
 PWW_TSPACKETHEAD pTsHeader = (PWW_TSPACKETHEAD)m_pTSPacket;

 return pTsHeader->_adaptation_field_present_flag;
}

BYTE  WWTSPacket::GetTransportScramblingControl()
{
 PWW_TSPACKETHEAD pTsHeader = (PWW_TSPACKETHEAD)m_pTSPacket;

 return pTsHeader->transport_scrambling_control;
}

PBYTE WWTSPacket::GetPayload(WORD *pwLen)
{
 PBYTE pBuffer = 0;
 *pwLen = 0;
 PBYTE pAdaptation = 0;
 WORD wLenAdaptation = 0;

 PWW_TSPACKETHEAD pTsHeader = (PWW_TSPACKETHEAD)m_pTSPacket;
 if( pTsHeader->_payload_present_flag )
 {
  pAdaptation = GetAdaptationField(&wLenAdaptation);
  if( pAdaptation )
  {
   *pwLen = WW_TSPACKET_LEN - sizeof(WW_TSPACKETHEAD) - 1 - wLenAdaptation;
   pBuffer = m_pTSPacket + sizeof(WW_TSPACKETHEAD) + 1 + wLenAdaptation;
   if( *pwLen==0 )
   {
    pBuffer = 0;
   }
  }
  else
  {
   pBuffer = m_pTSPacket + sizeof(WW_TSPACKETHEAD);
   *pwLen = WW_TSPACKET_LEN - sizeof(WW_TSPACKETHEAD);
  }
 }

 return pBuffer;
}

PBYTE WWTSPacket::GetAdaptationField(WORD *pwLen)
{
 PBYTE pBuffer = 0;
 *pwLen = 0;

 PWW_TSPACKETHEAD pTsHeader = (PWW_TSPACKETHEAD)m_pTSPacket;
 if( pTsHeader->_adaptation_field_present_flag )
 {
  *pwLen = ( WORD )(* (m_pTSPacket + sizeof(WW_TSPACKETHEAD)) );
  pBuffer = m_pTSPacket + 1;

  if( *pwLen> WW_TSPACKET_LEN-sizeof(WW_TSPACKETHEAD)-1 )
  {
   *pwLen = WW_TSPACKET_LEN-sizeof(WW_TSPACKETHEAD)-1;
  }
 }

 return pBuffer;
}

void WWTSPacket::Dump()
{
}

#ifndef __WWPATPACKET_H_LUCKYLIU__
#define __WWPATPACKET_H_LUCKYLIU__

#include "wwtspacket.h"

class WWPatPacket :
 public WWTSPacket
{
public:
 WWPatPacket(void);
 virtual ~WWPatPacket(void);

public:
 BOOL Load(BYTE* pBuffer, int nLen);
 void GetProgramMapList(WW_PATSECTIONPROTRAMMAPLIST* pLstProgramMap);
 virtual void Dump();

protected:
 WW_PATSECTIONPROTRAMMAPLIST m_lstProgramMap;
 PWW_PATSECTIONHEAD   m_pSectionHeader;
};

#endif
#include "StdAfx.h"
#include "./wwpatpacket.h"

WWPatPacket::WWPatPacket(void):
m_pSectionHeader(0),
WWTSPacket()
{
}

WWPatPacket::~WWPatPacket(void)
{
}

BOOL WWPatPacket::Load(BYTE* pBuffer, int nLen)
{
 //load tspacket.
 if( !WWTSPacket::Load(pBuffer, nLen) )
 {
  return FALSE;
 }

 //check if this pid is pat id.
 if( WWTSPacket::GetPID()!=WW_PATPID )
 {
  return FALSE;
 }

 PBYTE pPayload = 0;
 PBYTE pPatPayload = 0;
 WORD  wPayload = 0;
 WORD  wPatPayload = 0;
 WORD  wDiff = 0;

 //get pat payload buffer pointer and pat payload bytes number.
 if( !WWTSPacket::HasPayload() )
 {
  return FALSE;
 }
 pPayload = WWTSPacket::GetPayload(&wPayload);
 if( pPayload==0 || wPayload==0 )
 {
  return FALSE;
 }
 wDiff = (WORD)(*pPayload) + 1;//pointer_field
 if( wDiff>=wPayload )
 {
  return FALSE;
 }
 pPatPayload = pPayload + wDiff;
 wPatPayload = wPayload - wDiff;
 int nPatPayload = wPatPayload;

 //parse every pat section.
 m_lstProgramMap.clear();
 m_pSectionHeader = (PWW_PATSECTIONHEAD)(pPatPayload);
 while( nPatPayload>=sizeof(WW_PATSECTIONHEAD)+4 )
 {
  PWW_PATSECTIONHEAD pPatHead = (PWW_PATSECTIONHEAD)(pPatPayload);
  if( pPatHead->table_id!=0x00 ||
   pPatHead->section_syntax_indicator!=0x01 ||
   pPatHead->must_be_zero!=0x00 ||
   //pPatHead->reserved_twobits!=0x00 ||
   //pPatHead->reserved_twobits_2!=0x00 ||
   pPatHead->current_next_indicator!=0x01)
  {
   break;
  }
  WORD wSecLen = MAKEWORD(pPatHead->section_length_lowbits, pPatHead->section_length_highbits);
  if( wSecLen+3 > nPatPayload )
  {
   break;
  }
  WORD wPMapCount = (wSecLen - 5 - 4)/sizeof(WW_PATSECTIONPROTRAMMAP);
  for( WORD wIndex = 0; wIndex<wPMapCount; wIndex++ )
  {
   PWW_PATSECTIONPROTRAMMAP pPMap = (PWW_PATSECTIONPROTRAMMAP)(pPatPayload+sizeof(WW_PATSECTIONHEAD)+wIndex*sizeof(WW_PATSECTIONPROTRAMMAP));
   m_lstProgramMap.push_back(*pPMap);
  }

  pPatPayload += (wSecLen + 3);
  nPatPayload -= (wSecLen + 3);
 }

 for( WW_PATSECTIONPROTRAMMAPLIST::iterator it = m_lstProgramMap.begin(); it!=m_lstProgramMap.end(); )
 {
  if( MAKEWORD(it->program_number_lo, it->program_number_hi)==0 )
  {
   WW_PATSECTIONPROTRAMMAPLIST::iterator itDel = it;
   it++;
   m_lstProgramMap.erase(itDel);
  }
  else
  {
   it++;
  }
 }

 return TRUE;
}

void WWPatPacket::GetProgramMapList(WW_PATSECTIONPROTRAMMAPLIST* pLstProgramMap)
{
 pLstProgramMap->clear();
 *pLstProgramMap = m_lstProgramMap;
}

void WWPatPacket::Dump()
{
 printf("PAT packet(PID=0x%.4x)/n", WWTSPacket::GetPID());
 for( WW_PATSECTIONPROTRAMMAPLIST::iterator it = m_lstProgramMap.begin(); it!=m_lstProgramMap.end(); it++ )
 {
  printf("    Program Number: 0x%.4x, PMT PID: 0x%.4x/n", MAKEWORD(it->program_number_lo, it->program_number_hi),
   MAKEWORD(it->program_map_PID_lo, it->program_map_PID_highbits) );
 }
}

#ifndef __WWPMTPACKET_H_LUCKYLIU__
#define __WWPMTPACKET_H_LUCKYLIU__

#include "wwtspacket.h"

class WWPmtPacket :
 public WWTSPacket
{
public:
 WWPmtPacket(void);
 virtual ~WWPmtPacket(void);

public:
 BOOL Load(BYTE* pBuffer, int nLen);
 void GetProgramStreamMap(WW_TSPROGRAMSTREAMMAPLIST* pProgramStreamMapList);
 virtual void Dump();

protected:
 WW_TSPROGRAMSTREAMMAPLIST m_lstProgramStreamMap;

};

#endif
#include "StdAfx.h"
#include "./wwpmtpacket.h"

WWPmtPacket::WWPmtPacket(void):
WWTSPacket()
{
}

WWPmtPacket::~WWPmtPacket(void)
{
}

BOOL WWPmtPacket::Load(BYTE* pBuffer, int nLen)
{
 m_lstProgramStreamMap.clear();
 if( !WWTSPacket::Load(pBuffer, nLen) )
 {
  return FALSE;
 }

 if( !WWTSPacket::HasPayload() )
 {
  return FALSE;
 }

 PBYTE pPayload = 0, pPmtPayload = 0;
 WORD  wPayload = 0, wPmtPayload = 0, wDiff = 0;

 pPayload = WWTSPacket::GetPayload(&wPayload);
 if( pPayload==NULL || wPayload==0 )
 {
  return FALSE;
 }
 wDiff = (WORD)(*pPayload) + 1;
 if( wDiff>=wPayload )
 {
  return FALSE;
 }

 pPmtPayload = pPayload + wDiff;
 wPmtPayload = wPayload - wDiff;
 int nPmtPayload = wPmtPayload;
 BOOL bSuccessful = TRUE;

 while( nPmtPayload >= 12+4 && bSuccessful)//sizeof(WW_PMTSECTIONHEAD)
 {
  PWW_PMTSECTIONHEAD pHeader = (PWW_PMTSECTIONHEAD)pPmtPayload;
  if( pHeader->table_id!=0x02 ||
   pHeader->section_syntax_indicator!=0x01 ||
   pHeader->must_be_zero!=0x00 ||
   pHeader->current_next_indicator!=0x01 )
  {
   break;
  }

  WORD wSecLen = MAKEWORD( pHeader->section_length_lowbits, pHeader->section_length_highbits);
  WORD wProLen = MAKEWORD( pHeader->program_info_length_lo, pHeader->program_info_length_highbits);
  if( wSecLen+3>nPmtPayload )
  {
   break;
  }
  if( wProLen+9+4>wSecLen )
  {
   break;
  }

  WW_TSPROGRAMSTREAMMAP mapProStrm;
  mapProStrm.wProgramNumber = MAKEWORD( pHeader->program_number_lo, pHeader->program_number_hi);
  WORD wStreamMapLen = wSecLen - 9 -4 - wProLen;
  PBYTE pMap = pPmtPayload + 12 + wProLen;//sizeof(PWW_PMTSECTIONHEAD)
  while( wStreamMapLen>=5 )
  {
   PWW_PMTSECTIONSTREAMMAP pStreamMap = (PWW_PMTSECTIONSTREAMMAP)pMap;
   WORD wInfoLen = MAKEWORD( pStreamMap->ES_info_length_lo, pStreamMap->ES_info_length_hibits);
   if( wInfoLen+5>wStreamMapLen )
   {
    bSuccessful = FALSE;
    break;
   }
   mapProStrm.lstStreamMap.push_back( *pStreamMap );
   wStreamMapLen = wStreamMapLen - 5 - wInfoLen;
   pMap = pMap + 5 + wInfoLen;
  }

  if( bSuccessful )
  {
   m_lstProgramStreamMap.push_back( mapProStrm );
   pPmtPayload = pPmtPayload + 3 + wSecLen;
   nPmtPayload = nPmtPayload - (3 + wSecLen);
  }
  else
  {
   break;
  }
 }

 return TRUE;

}

void WWPmtPacket::GetProgramStreamMap(WW_TSPROGRAMSTREAMMAPLIST* pProgramStreamMapList)
{
 pProgramStreamMapList->clear();
 *pProgramStreamMapList = m_lstProgramStreamMap;
}

void WWPmtPacket::Dump()
{
 printf("PMT packet(PID=0x%.4x)/n", WWTSPacket::GetPID());
 for( WW_TSPROGRAMSTREAMMAPLIST::iterator it = m_lstProgramStreamMap.begin(); it!=m_lstProgramStreamMap.end(); it++ )
 { 
  printf("    Program number: 0x%.4x/n", it->wProgramNumber);
  for( WW_PMTSECTIONSTREAMMAPLIST::iterator itt = it->lstStreamMap.begin(); itt!=it->lstStreamMap.end(); itt++ )
  {
   printf("    PID: 0x%.4x, Stream Type: 0x%.4x/n", MAKEWORD(itt->elementary_PID_lo, itt->elementary_PID_highbits),
                itt->stream_type);
  }
 }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值