📄 dvbepg.c
字号:
// Epg.cpp: implementation of the Epg class.
//
//////////////////////////////////////////////////////////////////////
#include "dvbepg.h"
#include "string.h"
#include "PrVideo.h"
#include "PrAudio.h"
#include "PrTuner.h"
#include"prmem.h"
#ifdef WIN32
#define PLAY_PRIORITY 120
#define SEARCH_PRIORITY 120
#else
#define PLAY_PRIORITY 220
#define SEARCH_PRIORITY 220
#endif
#define MAX_TS_SERVICE 40
#define USE_PSI_MONITOR 1
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
static PRThread schThread=NULL;
static PRThread playThread=NULL;
static PRMsgQ msgQEPG=NULL;
static PRMsgQ msgQPlay=NULL;
static PRPartition memPool;
static PRMutex epgMutex=NULL;
static UINT epgInited=0;
static void SearchProc(void*params);//EPG接收任务
static void PlayProc(void*params);//A/V播出任务
typedef struct{
PRSem sem;
UCHAR buf[4096];
}FILTERCONTEXT;
typedef struct{
USHORT netid;
USHORT tsid;
USHORT serviceId;
int version;
PRMutex lock;
SECTIONDB*secDB;
}SCHEDULE;
typedef struct{
UINT msgID;
UINT wParam;
UINT lParam;
}EPGREQUEST;
static SECTIONDB*SchedulePF;
static PRMpgFilt fltEit;
static PRMpgFilt fltTDT;
static PRMpgFilt fltSDT;
static PRMpgFilt fltNIT;
static PRMpgFilt fltPAT;
static PRMpgFilt fltPMT;
static SERVICELOCATOR CurrentService;
static SCHEDULE Schedules[MAX_TS_SERVICE];
static SCHEDULE*GetScheduleSlot(USHORT netid,USHORT tsid,USHORT sid,int alloc);
extern BroadcastMessage(UINT,UINT,UINT);
extern SECTIONDATA*GetFirstNIT();
static int EITCMPPF(unsigned char*sec1,unsigned char*sec2)
{
unsigned int id1,id2;
unsigned short tsid1,tsid2,eid1,eid2;
unsigned char sno1,sno2;
tsid1=GetEitStreamID(sec1);tsid2=GetEitStreamID(sec2);
eid1=GetEitServiceID(sec1);sno1=GetSectionNo(sec1);
eid2=GetEitServiceID(sec2);sno2=GetSectionNo(sec2);
//EIT不比较TableID
if(tsid1!=tsid2)
return tsid1-tsid2;
id1=(eid1<<8)|sno1;
id2=(eid2<<8)|sno2;
return id1-id2;
}
static int EITCMPSCH(unsigned char*sec1,unsigned char*sec2)
{
unsigned int id1,id2;
id1=((UINT)GetTableID(sec1)<<24)|((UINT)GetEitServiceID(sec1)<<8)|GetSectionNo(sec1);
id2=((UINT)GetTableID(sec2)<<24)|((UINT)GetEitServiceID(sec2)<<8)|GetSectionNo(sec2);
//只比较sectionNo 和TableID就可以了.
return id1-id2;
}
static void EitCBK(PRMpgFilt filt, void *userData, UCHAR*section,UINT length)
{
SERVICELOCATOR s;
SCHEDULE*ch;
UCHAR tableID=GetTableID(section);
if((tableID<0x4E)||(tableID>0x6F)){
TRACE("EIT TableID [%02X] Error\r\n",tableID);
return ;
}
if(tableID<0x50){
s.netId=GetEitNetID(section);
s.tsId=GetEitStreamID(section);
s.serviceId=GetEitServiceID(section);
AddSection(SchedulePF,section);
if(SchedulePF->Count>512)
TRACE("SchedulePF::Count=%d %d.%d.%d TBID=%X\r\n",SchedulePF->Count,
s.netId,s.tsId,s.serviceId,tableID);
return ;
}else{
static int cnt=0;
UCHAR sno=GetSectionNo(section);
s.netId=GetEitNetID(section);
s.tsId=GetEitStreamID(section);
s.serviceId=GetEitServiceID(section);
ch=GetScheduleSlot(s.netId,s.tsId,s.serviceId,((tableID&0x50)==0x50));
if(ch){
AddSection(ch->secDB,section);
if((cnt++%200==0))
TRACE("RECV EIT %d.%d.%d CNT=%d\r\n",s.netId,s.tsId,s.serviceId,ch->secDB->Count);
}else if( (tableID&0x50)==0x50){
int i;
TRACE("Actural Service %d.%d.%d no Cahed!!!\r\n",s.netId,s.tsId,s.serviceId);
}
}
}
static int GetTSFrequency(USHORT netId,USHORT tsId,PRTunerParams*tun)
{
SECTIONDB*db=GetNetworkDB();
SECTIONDATA*sec;
int rc=0;
//PrMutexLock(db->lock,-1);
sec=db->sections;
while(sec&&(rc==0)){
int i,cnt=GetNitTSCount(sec->Data);
for(i=0;i<cnt;i++){
DVBStream stm;
GetNitTSStream(sec->Data,&stm,i);
if(stm.original_network_id==netId&&stm.transport_stream_id==tsId){
GetDeliveryTuneInfo(&stm,tun);
//TRACE("TS %d.%d Freq=%d\r\n",stm.original_network_id,stm.transport_stream_id,tun->frequency);
rc=1;
break;
}
}
sec=sec->next;
}
if(db->Count>40)
TRACE("!!!!!NIT has %d sections\r\n",db->Count);
//PrMutexUnlock(db->lock);
return rc;
}
static void SDTCBK(PRMpgFilt filt, void *userData, UCHAR*section,UINT length)
{
USHORT netid=GetSdtNetID(section);
USHORT tsid=GetSdtStreamID(section);
TSDATA*ts;
static int cc=0;
UCHAR tableId=GetTableID(section);
if(tableId==0x4A){
SECTIONDB*db=GetBouquetDB();
AddSection(db,section);
return;
}else if(tableId==0x42){
//ts=FindTSByFrequency(PrGetLastFrequency());
ts=FindTS(netid,tsid);
if(ts==NULL)ts=CreateTS(netid,tsid);
ts->netId=netid;ts->tsId=tsid;
}else if(tableId==0x46){
ts=FindTS(netid,tsid);
if(ts==NULL)ts=CreateTS(netid,tsid);
}else{
TRACE("SDT/BAT TableID[%02X]ERROR\r\n",tableId);
return ;
}
if(ts->tunerParams.frequency==0){
GetTSFrequency(netid,tsid,&ts->tunerParams);
//ts->tunerParams.frequency=PrGetLastFrequency();
}
AddSection(ts->sdt,section);
if(ts->sdt->Count>10||(cc++%20==0)){
TSDATA*t=GetFirstTS();
int tc=0;
while(t){
t=t->next;
tc++;
}
TRACE("!!!ts %d.%d has %d sdt sections TSCount=%d\r\n",ts->netId,ts->tsId,
ts->sdt->Count,tc);
}
}
static void NITCBK(PRMpgFilt filt, void *userData, UCHAR*section,UINT length)
{
SECTIONDB*db;
static unsigned int version=0xFFFFFFFF;
db=GetNetworkDB();
if((section[0]&0xFE)!=0x40){
TRACE("NIT TableID[%02X]Error\r\n",section[0]);
return ;
}
AddSection(db,section);
if(version!=db->version){
USHORT nid=GetNitNetID(section);
int i,cnt=GetNitTSCount(section);
TRACE("**RECV NIT NETID=%d SEC %d COUNT=%d\r\n",nid,GetSectionNo(section),db->Count);
for(i=0;i<cnt;i++){
DVBStream stm;
TSDATA*ts=GetFirstTS();
GetNitTSStream(section,&stm,i);
while(ts){
if(ts->netId==stm.original_network_id
&&ts->tsId==stm.transport_stream_id){
GetDeliveryTuneInfo(&stm,&ts->tunerParams);
TRACE("TS %d.%d Freq=%d\r\n",ts->netId,ts->tsId,ts->tunerParams.frequency);
break;
}
ts=ts->next;
}
}
version=db->version;
}
}
extern UINT UTCTime2SecondsFrom1970(INT mjd,UINT utc);
static void TDTCBK(PRMpgFilt filt, void *userData, UCHAR*section,UINT length)
{
USHORT mjd;
UINT utc,secondsFrom1970;
if(section[0]==0x70){//TDT
USHORT y,m,d,h,min,sec;
GetUTCTime(section,&mjd,&utc);
GetYMDFromMJD(mjd,&y,&m,&d);
GetHMSFromUTC(utc,&h,&min,&sec);
secondsFrom1970=UTCTime2SecondsFrom1970(mjd,utc);
PrTimeSetTime(secondsFrom1970);
TRACE("RECV TDT %d/%02d/%02d %02d:%02d:%02d\r\n",y+1900,m,d,h,min,sec);
}else{//0x73 TOT
USHORT y,m,d,h,min,sec;
TIMEOFFSETINFO tos[16];
INT cnt,i;
GetTOTTime(section,&mjd,&utc);
GetYMDFromMJD(mjd,&y,&m,&d);
GetHMSFromUTC(utc,&h,&min,&sec);
cnt=GetTOTOffsetInfo(section,tos);
for(i=0;i<cnt;i++){
TIMEOFFSETINFO*t=tos+i;
TRACE("%s, Region=%d Offset=%04X Change=%04X %06X Next=%04X\r\n",
t->CountryCode,t->CountryRegionId,t->LocalTimeOffset,
t->TimeOfChangeMJD,t->TimeOfChangeUTC,t->NextTimeOffset);
}
}
}
static void PATCBK(PRMpgFilt filt, void *userData, UCHAR*section,UINT length)
{
SERVICELOCATOR svc;
USHORT tsid=GetPatStreamID(section);
GetCurrentService(&svc);
if(section[0]!=0){
TRACE("PAT TabelID[%02X] Error\r\n",section[0]);
return ;
}
if(svc.tsId==tsid){
TSDATA*ts=FindTS(svc.netId,tsid);
if(ts){
static int cc=0;
AddSection(ts->pat,section);
if(cc++%50==0)TRACE("recv PAT %d.%d\r\n",svc.netId,tsid);
}
}
}
static void PMTCBK(PRMpgFilt filt, void *userData, UCHAR*section,UINT length)
{
SERVICELOCATOR svc;
USHORT sid=GetPmtServiceID(section);
GetCurrentService(&svc);
if(section[0]!=2){
TRACE("PMT TabelID[%02X] Error\r\n",section[0]);
return ;
}
if((svc.serviceId==sid)){
TSDATA*ts=FindTS(svc.netId,svc.tsId);
if(ts){
static int cc=0;
AddSection(ts->pmt,section);
if(cc++%50==0)TRACE("recv PMT %d.%d.%d\r\n",svc.netId,svc.tsId,sid);
}
}
}
int EpgInit(int memsize)
{
int i;
UCHAR mask,data;
if(playThread!=NULL)
return 0;
SchedulePF=CreateSectionDB(EITCMPPF,NULL);
CreateSystemDB();
epgMutex=PrMutexCreate();
epgInited=1;
if((msgQEPG=PrMsgQCreate(64,sizeof(EPGREQUEST)))==NULL)
return 1;
if((msgQPlay=PrMsgQCreate(16,sizeof(SERVICELOCATOR)))==NULL)
return 1;
playThread=PrThreadCreate(8192,PLAY_PRIORITY,PlayProc,NULL);
if(playThread==NULL)
return 1;
schThread=PrThreadCreate(8192,SEARCH_PRIORITY,SearchProc,NULL);
if(schThread==NULL)
return 1;
memPool=PrPartitionCreate(memsize);
if(memPool==NULL)
return 1;
for(i=0;i<MAX_TS_SERVICE;i++){
PRMutex schLock;
memset(&Schedules[i],0,sizeof(SCHEDULE));
Schedules[i].lock=schLock=PrMutexCreate();
Schedules[i].lock=schLock;
Schedules[i].secDB=CreateSectionDB(EITCMPSCH,schLock);
}
fltEit=FilterCreate(0,MPGFILT_SECTION); //// EIT
FilterSetPID(fltEit,0x12);
mask=0xC0;data=0x4E;
FilterSetMask(fltEit,&mask,&data,1);
FilterSetCrcMode(fltEit,1);
FilterSetNotify(fltEit,EitCBK,0);
FilterStart(fltEit);
fltTDT=FilterCreate(0,MPGFILT_SECTION); //// TDT TOT
FilterSetPID(fltTDT,0x14);
mask=0xF0;data=0x70;
FilterSetMask(fltTDT,&mask,&data,1);
FilterSetNotify(fltTDT,TDTCBK,0);
FilterStart(fltTDT);
fltSDT=FilterCreate(0,MPGFILT_SECTION); //// SDT Actual/Other and BAT
FilterSetPID(fltSDT,0x11);
mask=0xF3;data=0x42;
FilterSetMask(fltSDT,&mask,&data,1);
FilterSetNotify(fltSDT,SDTCBK,0);
FilterStart(fltSDT);
fltNIT=FilterCreate(0,MPGFILT_SECTION); //// NIT
FilterSetPID(fltNIT,0x10);
mask=0xFE;data=0x40;
FilterSetMask(fltNIT,&mask,&data,1);
FilterSetNotify(fltNIT,NITCBK,0);
FilterStart(fltNIT);
#ifdef USE_PSI_MONITOR
fltPAT=FilterCreate(0,MPGFILT_SECTION);
FilterSetPID(fltPAT,0x0);
mask=0xFD;data=0x00;
FilterSetMask(fltPAT,&mask,&data,1);
FilterSetNotify(fltPAT,PATCBK,0);
FilterStart(fltPAT);
fltPMT=FilterCreate(0,MPGFILT_SECTION);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -