#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "iconv.h"
#include "stdafx.h"
#include "Demux.h"
#include "crc.h"
#include "mjd.h"
#define MAX_PMT_NUM 204
#define MAX_EITS_NUM 255
#define BCDTODEC(bcd) ((bcd) = ((bcd) & 15) + ((bcd)>>4) * 10)//将BCD码转换为十进制数
uint16_t service_id=0;
unsigned char *service_name=NULL;
uint16_t video_pid=0;
uint16_t audio_pid=0;
uint16_t pmt_pid=0;
uint16_t transport_stream_id=0;
int dr = 188;
typedef struct
{
unsigned char *pat_buf;//存储pat表相关信息
unsigned char *pmt_buf;//存储pmt表相关信息
unsigned char *sdt_buf;//存储sdt表相关信息
unsigned int pat_buf_size;
unsigned int pmt_buf_size;
unsigned int sdt_buf_size;
void *pat_filter; //过滤pat表
void *pmt_filter[MAX_PMT_NUM];
void *sdt_filter;
unsigned char pmt_number;
unsigned int bufsize;
unsigned char *buf;
void *demux;
unsigned char aflag;//标记pat表中预定信息是否在TS流中
unsigned char mflag;
unsigned char sflag;
}Ts;
Ts *ts;
int pat_num=0;
int sdt_num=0;
int pmt_num=0;
/*初始化定义的结构体*/
void Initialize();
/*pat回调函数*/
int pat_filter( void* demux, void* filter, unsigned char *buf, int32_t size, uint32_t lParam );
/*sdt回调函数*/
int sdt_filter( void* demux, void* filter, unsigned char *buf, int32_t size, uint32_t lParam );
/*pmt回调函数*/
int pmt_filter( void* demux, void* filter, unsigned char *buf, int32_t size, uint32_t lParam );
/*提取PAT数据*/
int get_PAT_info();
/*提取SDT数据*/
int get_SDT_info(uint16_t serv_id,uint16_t tranport_s_id);
/*提取PMT数据*/
int get_PMT_info(uint16_t serv_id);
/*打印结果*/
void print();
int main()
{
int i, size;
FILE *fp;
unsigned char file_name[255];
ts = (Ts *)malloc( sizeof( Ts ) );
Initialize();//用来初始化结构体
ts->buf = (unsigned char*)malloc( ts->bufsize );//为ts流缓存申请空间
printf("**************************************\n\n");
printf("\n请输入要搜索的TS文件的目录:");
scanf("%s",file_name);
printf("\n");
fp=fopen(file_name,"rb");//从TS文件中读取信息 备用:gehua_634、387_0604_195948
if (fp==NULL)
{
printf("File open error!!!\n");
printf("File is not exist!!!\n");
return ;
}
ts->demux=Demux_Create();
ts->pat_filter=Demux_CreateFilterEx(ts->demux,0x0000,0x00,0xff,0,0,1024,pat_filter,(uint32_t)ts);
ts->sdt_filter=Demux_CreateFilterEx(ts->demux,0x0011,0x42,0xff,0,0,1024,sdt_filter,(uint32_t)ts);
/* 扫描文件,寻找PAT*/
while(!feof(fp))
{
size = fread(ts->buf,1,ts->bufsize,fp);
if( size <= 0 )
{
break;
}
Demux_OnData(ts->demux, ts->buf, size ,dr);
if (ts->aflag==1&&ts->sflag==1&&ts->mflag==1)
{
break;
}
}
/*关闭filter*/
Demux_DestroyFilter( ts->demux, ts->pat_filter );
Demux_DestroyFilter( ts->demux, ts->sdt_filter );
for (i=0;i<ts->pmt_number;i++)
Demux_DestroyFilter( ts->demux, ts->pmt_filter[i] );
/*关闭demux*/
Demux_Destroy( ts->demux );
printf("**************************************\n\n");
printf("在TS文件中搜索到的节目信息如下:\n");
printf("**************************************\n\n");
get_PAT_info();
fclose(fp);
free(ts->buf);
ts->buf=NULL;
free(ts->pat_buf);
ts->pat_buf=NULL;
free(ts->sdt_buf);
ts->sdt_buf=NULL;
free(ts->eit_buf);
ts->pmt_buf=NULL;
free(ts);
ts=NULL;
return 0;
}
/*初始化定义的结构体*/
void Initialize()
{ int i;
ts->pat_buf=NULL;//存放pat表信息
ts->pmt_buf=NULL;
ts->sdt_buf=NULL;
ts->pat_buf_size=0;
ts->pmt_buf_size=0;
ts->sdt_buf_size=0;
ts->pat_filter=NULL;//pat表的section的过滤器
ts->sdt_filter=NULL;
for(i=0;i<MAX_PMT_NUM;i++)
{
ts->pmt_filter[i]=NULL;//各个pmt表的section的过滤器
}
ts->pmt_number=0;
ts->bufsize =16*1024*204;
ts->buf=NULL;
ts->demux=NULL;
ts->aflag=0;//判断是否搜集完pat表所有信息的标识符(为1时表示搜集完)
ts->mflag=0;
ts->sflag=0;
}
/*pat回调函数*/
int pat_filter( void* demux, void* filter, unsigned char *buf, int32_t size, uint32_t lParam )
{
Ts *ts=(Ts *)lParam;
unsigned char *tmp,*_tmp;
uint16_t service_id;
uint16_t pmt_pid;
uint32_t crc32,cValue,i=0;
unsigned char section_number,last_section_number;
uint16_t section_length;
if (1024<size||filter!=ts->pat_filter)
{
return 1;
}
/* CRC校验 */
if(dr==188)
{
crc32 = GetCrc32( buf, size-4 );
memcpy( &cValue, buf+size-4, 4 );
if( cValue != htonl(crc32) )
{
printf("CRC校验错误!!!");
return 0;
}
}
section_number=buf[6];
last_section_number=buf[7];
section_length=(buf[1]&0x0f)<<8|buf[2];
if (last_section_number<section_number)
{
return 1;
}
if (ts->pat_buf==NULL)
{
ts->pat_buf_size=(last_section_number+1)*1024;
ts->pat_buf=(unsigned char*)malloc(ts->pat_buf_size);
if (ts->pat_buf==NULL)
{ printf("pat_buf指向内存申请失败.\n");
return 1;
}
memset(ts->pat_buf,0xff,ts->pat_buf_size);
}
tmp=ts->pat_buf;
//ts->pat_buf用于存放pat表的各个section
//ts->pat_buf的空间被初始化时赋为0xff
//pat表中的section的首字节是0x00;
//在ts->pat_buf中查找空闲空间用于存放pat表当前的section
while ((*tmp)!=0xff&&tmp<(ts->pat_buf+ts->pat_buf_size))
{
if (tmp[6]==section_number)
{
ts->aflag=1;
return 1;
}
tmp+=3+ ((tmp[1]&0xf)<<8)+tmp[2];//移动section个长度
}
if (ts->pat_buf+ts->pat_buf_size<tmp+size)
{
return 1;
}
memcpy(tmp,buf,size);
tmp=ts->pat_buf;
_tmp=tmp;
tmp+=8;
if(ts->pmt_number==0)
{ while(tmp+3<=_tmp+3+section_length-4)
{ service_id=(tmp[0]<<8)|tmp[1];
if (service_id!=0)
{
ts->pmt_number++;//计算该TS流中有多少pmt表
}
tmp+=4;
}
}
//检测pat表的所有section是否都收到。
pat_num++;
if (pat_num == last_section_number + 1)
{
ts->aflag=1;
}
tmp=_tmp;
tmp+=8;
i=0;
//为pat表的当前section中标记的pmt表建立过滤器
while(tmp+3<=_tmp+3+section_length-4)
{
service_id=(tmp[0]<<8)|tmp[1];
tmp+=2;
if (service_id!=0)
{
pmt_pid=((tmp[0]&0x1f)<<8)|tmp[1];
/*过滤PMT*/
ts->pmt_filter[i]=Demux_CreateFilterEx(ts->demux,pmt_pid,0x02,0xff,0,0,1024,pmt_filter,(uint32_t)ts);
i++;
}
tmp+=2;
}
return 0;
}
/*sdt回调函数*/
int sdt_filter( void* demux, void* filter, unsigned char *buf, int32_t size, uint32_t lParam )
{
Ts *ts=(Ts *)lParam;
unsigned char *tmp;
uint32_t crc32,cValue,i=0;
unsigned char section_number,last_section_number;
if (1024<size||filter!=ts->sdt_filter)
{
return 1;
}
/* CRC校验 */
if(dr==188)
{
crc32 = GetCrc32( buf, size-4 );
memcpy( &cValue, buf+size-4, 4 );
if( cValue != htonl(crc32) )
{
printf("CRC校验错误!!!");
return 0;
}
}
section_number=buf[6];
last_section_number=buf[7];
if (last_section_number<section_number)
{
return 1;
}
if (ts->sdt_buf==NULL)
{
ts->sdt_buf_size=(last_section_number+1)*1024;
ts->sdt_buf=(unsigned char*)malloc(ts->sdt_buf_size);
if (ts->sdt_buf==NULL)
{
printf("sdt_buf指向内存申请失败.\n");
return 1;
}
memset(ts->sdt_buf,0xff,ts->sdt_buf_size);
}
tmp=ts->sdt_buf;
//sdt表的section的首字节是table_id = 0x42;
//在ts->sdt_buf中查找未使用空间用于存放sdt表当前的section
while ((*tmp)!=0xff&&tmp<(ts->sdt_buf+ts->sdt_buf_size))
{
/* 如果SECTION已经存在,则不必再次处理 */
if (tmp[6]==section_number)
{
return 1;
}
tmp+=3+((tmp[1]&0xf)<<8)+tmp[2];
}
if (ts->sdt_buf+ts->sdt_buf_size<tmp+size)
{
return 1;
}
memcpy(tmp,buf,size);
sdt_num++;
//检测sdt表中的section是否已经收集完
if (sdt_num==(ts->sdt_buf)[7])