#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#define TSPACKETLEN 188
#define PAT_Pid 0x00
#define PMT_MAX 8
#define PES_MAX 0x10
#define cnCRC32Size 4
#define VID 4
#define AUD 5
#define PIDINT_LIST_START_SIZE 5
#define PIDINT_LIST_INCREMENT 10
#define EVALUATE(d, s) TransData(&d, s, sizeof(d)); s += sizeof(d)
#define INIT_STRUCT(_STRUCT, _STREAM) _STRUCT; \
TransData(&_STRUCT, _STREAM, sizeof(_STRUCT)); \
_STREAM += sizeof(_STRUCT)
typedef enum bool{
false,true
}bool;
//typedef uint8_t byte;
typedef unsigned char byte;
//typedef long long __int64;
#define __int64 long long int
#define __int32 int
struct TS_header_tag
{
unsigned char sync_byte;
unsigned char transport_error_indicator;
unsigned char payload_unit_start_indicator;
unsigned char transport_priority;
unsigned int PID;
unsigned char transport_scrambling_control;
unsigned char adaptation_field_control;
unsigned char continuity_counter;
} ;
//struct TS_header_tag TS_header;
struct TS_packet_header//defined in reverse order
{
unsigned int continuity_counter :4 ;
unsigned int adaptation_field_control :2 ;
unsigned int transport_scrambling_control :2 ;
unsigned int PID :13 ;
unsigned int transport_priority :1 ;
unsigned int payload_unit_start_indicator :1 ;
unsigned int transport_error_indicator :1 ;
unsigned int sync_byte :8 ;
};
typedef struct TS_packet_header TS_packet_header;
//struct TS_packet_header TS_header;
FILE *ip_file;
int sync_bytes[10];
unsigned char ts_package[TSPACKETLEN];
unsigned int adaption_field_length;
unsigned int pointer_field_length;
struct pmt_pid_st
{
int *number;
int *pid;
int length;
int size;
};
struct pmt_pid_st pmt_pid;
struct pes_pid_st
{
int *stream_type;
int *pid;
int *payload_start;
int *continuity_counter_before;
int length;
int size;
};
struct pes_pid_st pes_pid;
void pat_parser();
void pmt_parser();
void vid_parser(int n);
void program_association_section(unsigned char *buff, int leng);
void program_map_section(byte* buff, int leng);
void transport_packet(unsigned char *buff);
unsigned short descriptor(byte *p_descriptor);
void pes_packet(byte* buff, int leng,TS_packet_header *p_header);
int init_pmt_list(struct pmt_pid_st *list);
int init_pes_list(struct pes_pid_st *list);
int add_pmt_list(struct pmt_pid_st *list, int pid, int program);
int add_pes_list(struct pes_pid_st *list,int stream_type, int pid);
void free_pmt_list(struct pmt_pid_st *list);
void free_pes_list(struct pes_pid_st *list);
void report_pmt_list(struct pmt_pid_st *list);
void report_pes_list(struct pes_pid_st *list);
/*
void TS_header_decode()
{
// current_header_add = ftell(ip_file);
// fread(&TS_raw_header, sizeof(TS_raw_header), 1, ip_file); // read the header
TS_header.sync_byte = ts_package[0];
TS_header.transport_error_indicator = (ts_package[1] & 0x80) >> 7;
TS_header.payload_unit_start_indicator = (ts_package[1] & 0x40) >> 6;
TS_header.transport_priority = (ts_package[1] & 0x20) >> 5;
TS_header.PID = ((ts_package[1] & 31) << 8) | ts_package[2];
TS_header.transport_scrambling_control = (ts_package[3] & 0xC0);
TS_header.adaptation_field_control = (ts_package[3] & 0x30) >> 4;
TS_header.continuity_counter = (ts_package[3] & 0xF);
}
*/
void TS_header_decode(TS_packet_header *p_header,byte* buff)
{
*(byte *)p_header = *(buff+3);
*((byte *)(p_header)+1) = *(buff+2);
*((byte *)(p_header)+2) = *(buff+1);
*((byte *)(p_header)+3) = *(buff);
}
bool TransData(void * pTarget, const unsigned char * pStream, int nBytes)
{
int i;
if (nBytes <= 0)
{
return false;
}
if (nBytes == 1 || nBytes == 2 || (nBytes % 4) == 0)
{
for (i = 0; i < nBytes; i ++)
{
*((unsigned char*)(pTarget) + i) = *(pStream + (nBytes - i - 1));
}
return true;
}
else
{
return false;
}
}
bool find_TS_sync_byte(void)
{ // scan file looking for sync_bytes
int sync_data = 0; // storage for data read from file
int occurance = 0; // keep track of how many sync_bytes have been found
long int current_file_pos = 0; // where are we?
while ( !feof(ip_file) && occurance < 6)
{
current_file_pos = ftell(ip_file);
sync_data = 0;
fread(&sync_data, 1, 1, ip_file);
switch (sync_data)
{ // if sync_byte is found then remember it in sync_bytes[]
case 0x47 :
sync_bytes[occurance] = current_file_pos;
occurance++;
fseek(ip_file,187,1); // look for next one
break;
default : // if byte is not equal to 0x47
occurance = 0;
}
}
if ( occurance < 6 )
{ // report error if 5 cannot be found
return false;
}
return true;
}
int main(int argc, char *argv[])
{
char fileName[255];
bool sync_find=false;
int rsize;
long long circle_num;
int err;
if (argc != 2)
{
printf("Usage:%s TSfile\n", argv[0]);
return -1;
}
memset(fileName,0,255);
strcpy(fileName, argv[1]);
unsigned int i=0;
err = init_pes_list(&pes_pid);
if(err)
return 1;
err = init_pmt_list(&pmt_pid);
if(err)
return 1;
ip_file = fopen(fileName, "rb");
if(ip_file <= 0)
{
printf("File %s can't be opened\n", fileName);
exit(2);
}
sync_find = find_TS_sync_byte();
if(sync_find==false)
return 0;
circle_num =0;
fseek(ip_file, sync_bytes[1], 0);
while(1)
{
rsize = fread(&ts_package, sizeof(ts_package), 1, ip_file); // read the header
if(feof(ip_file)||(rsize <1))
{
fclose(ip_file);
printf("Finished! \n");
break;
}
circle_num++;
transport_packet(ts_package);
}
report_pmt_list(&pmt_pid);
report_pes_list(&pes_pid);
free_pmt_list(&pmt_pid);
free_pes_list(&pes_pid);
return 0;
}
int adaptation_field(unsigned char *pField)
{
struct _adaptation_field_data
{//defined in reverse order
byte adaptation_field_extension_flag :1;
byte transport_private_data_flag :1;
byte splicing_poing_flag :1;
byte OPCR_flag :1;
byte PCR_flag :1;
byte elementary_stream_priority_indicator :1;
byte random_access_indicator :1;
byte discontinuity_indicator :1;
byte adaptation_field_length;
}INIT_STRUCT(adaptation_field_data, pField);
return adaptation_field_data.adaptation_field_length + 1;
}
bool ispmt(unsigned int pid)
{
int i;
for(i=0;i<pmt_pid.length;i++)
{
if(pid == pmt_pid.pid[i])
return true;
}
return false;
}
bool ispes(unsigned int pid)
{
int i;
for(i=0;i<pes_pid.length;i++)
{
if(pid == pes_pid.pid[i])
return true;
}
return false;
}
void transport_packet(unsigned char *buff)
{
int leng = TSPACKETLEN, size;
TS_packet_header transport_packet_header;
// EVALUATE(transport_packet_header, buff);
TS_header_decode(&transport_packet_header, buff);
buff +=4;
leng -= sizeof(transport_packet_header);
if (transport_packet_header.transport_error_indicator
|| transport_packet_header.transport_scrambling_control)
{
return;
}