//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);
}
}
}