📄 dvbdata.c
字号:
// dvbdata.c: implementation of the dvbdata class.
//
//////////////////////////////////////////////////////////////////////
#include "dvbdata.h"
#include "stdio.h"
#include"secdb.h"
#include"PrMem.h"
#include"string.h"
#include"FavGroup.h"
#define VERIFIED_BYTES 0x82101215
static TSDATA*streams=NULL;
static SECTIONDB*bouquetDB=NULL;//业务群链表
static SECTIONDB*networkDB=NULL;//NIT链表
static SIInternalCMP(UCHAR*sec1,UCHAR*sec2)
{
UINT id1,id2;
USHORT eid1,eid2;
UCHAR tid1,tid2,sno1,sno2;
tid1=GetTableID(sec1);eid1=GetExtTableID(sec1);sno1=GetSectionNo(sec1);
tid2=GetTableID(sec2);eid2=GetExtTableID(sec2);sno2=GetSectionNo(sec2);
if((tid1==0x00)||(tid1==0x02)||(tid1>=0x3B&&tid1<=0x3E)||(tid1==0x4A)){
//PAT,PMT,BAT,DSMCC
id1=(tid1<<24)|(eid1<<8)|sno1;
id2=(tid2<<24)|(eid2<<8)|sno2;
return id1-id2;
}else if((tid1==0x40)||(tid1==0x41)||(tid1==0x42)||
(tid1==0x46)||(tid1>=0x4E&&tid1<=0x6F)){//NIT,SDT,EIT
id1=(tid1<<24)|(eid1<<8)|sno1;//不比较TableID
id2=(tid2<<24)|(eid2<<8)|sno2;
return id1-id2;
}else if(tid1==0x01||(tid1>=0x80&&tid1<=0x8F)){//CAT CMT
return tid1-tid2;
}else if((tid1>=0x70)&&(tid1<=0x73)){//TDT RST ST TOT
return tid1-tid2;
}else{
printf("SectionCompare Wrong section tableID=0x%02X\n",tid2);
}
return 0;
}
int CreateSystemDB(void){
networkDB=CreateSectionDB(SIInternalCMP,NULL);
bouquetDB=CreateSectionDB(SIInternalCMP,NULL);
return 2;
}
int ResetSystemDB(void)
{
FreeDBSections(networkDB);
FreeDBSections(bouquetDB);
}
int DestroySystemDB(void)
{
TSDATA*ts=streams;
DestroySectionDB(networkDB);
DestroySectionDB(bouquetDB);
FreeAllTS();
networkDB=NULL;
bouquetDB=NULL;
streams=NULL;
}
TSDATA*CreateTS(USHORT netId,USHORT tsId)
{
TSDATA*newts,*ts=streams;
newts=(TSDATA*)PrMalloc(sizeof(TSDATA));
memset(newts,0,sizeof(TSDATA));
newts->netId=netId;
newts->tsId=tsId;
newts->lock=PrMutexCreate();
newts->pat=CreateSectionDB(SIInternalCMP,newts->lock);
newts->pmt=CreateSectionDB(SIInternalCMP,newts->lock);
newts->sdt=CreateSectionDB(SIInternalCMP,newts->lock);
memset(newts->States,16,MAX_TSPROGRAM*2);
if(streams==NULL)
streams=newts;
else{
ts=streams;
while(ts){
if(ts->next==NULL){
ts->next=newts;
break;
}
ts=ts->next;
}
}
return newts;
}
TSDATA*FindTS(USHORT netId,USHORT tsId)//查找一个TS
{
TSDATA*ts=streams;
while(ts){
if(ts->tsId==tsId)
return ts;
ts=ts->next;
}
return NULL;
}
TSDATA*FindTSByFrequency(UINT32 freq)
{
TSDATA*ts=streams;
while(ts){
if(ts->tunerParams.frequency ==freq)
return ts;
ts=ts->next;
}
return NULL;
}
TSDATA*GetFirstTS(void)
{
return streams;
}
void FreeTSData(TSDATA*ts)//释放TS结构的所有内存但不包括TS结构本身
{
SECTIONDATA*sd;
sd=ts->pat->sections;
while(sd){
SERVICELOCATOR s;
INT16 i,pc=GetPatProgramCount(sd->Data);
s.netId=ts->netId;
s.tsId=GetPatStreamID(sd->Data);
for(i=0;i<pc;i++){
DVBProgram prg;
GetPatProgram(sd->Data,&prg,i);
s.serviceId=prg.program_number;
if(s.serviceId)
DeleteServiceFromFavGroup(NULL,&s);
}
sd=sd->next;
}
sd=ts->sdt->sections;
while(sd){
SERVICELOCATOR s;
INT16 i,sc=GetSdtServiceCount(sd->Data);
s.netId=GetSdtNetID(sd->Data);
s.tsId=GetSdtStreamID(sd->Data);
for(i=0;i<sc;i++){
DVBService svr;
GetSdtService(sd->Data,&svr,i);
s.serviceId=svr.service_id;
DeleteServiceFromFavGroup(NULL,&s);
}
sd=sd->next;
}
FreeDBSections(ts->pat);
FreeDBSections(ts->pmt);
FreeDBSections(ts->sdt);
}
void FreeAllTS(void)//释放所有TS的数据包括TS本身
{
TSDATA*ts=GetFirstTS();
while(ts){
TSDATA*t=ts->next;
FreeTSData(ts);
PrFree(ts);
ts=t;
}
streams=NULL;
}
static int FindServiceInTS(TSDATA*ts,USHORT serviceID,DVBService*service)
{//
if(ts==NULL)
return -1;
if(ts->sdt){
SECTIONDATA*sd=ts->sdt->sections;
while(sd){
int i,sCount=GetSdtServiceCount(sd->Data);
for(i=0;i<sCount;i++){
DVBService svr;
GetSdtService(sd->Data,&svr,i);
if(svr.service_id==serviceID){
if(service!=NULL)
*service=svr;
return 0x2000|i;
}
}
sd=sd->next;
}
}else if(ts->pat&&ts->pmt){
int i=0;
SECTIONDATA*sd=ts->pmt->sections;
while(sd){
if(GetPmtServiceID(sd->Data)==serviceID)
return 0x1000|i;
sd=sd->next;
}
}
return -1;
}
int GetServiceInfo(const SERVICELOCATOR*sloc,DVBService*service)//
{
int rc;
if(sloc){
TSDATA*ts=FindTS(sloc->netId,sloc->tsId);
rc=FindServiceInTS(ts,sloc->serviceId,service);
if(rc==-1)return 0;
else if(rc&0x2000)return 2;
else return 1;
}
return 0;
}
int GetServiceType(SERVICELOCATOR*service)
{
DVBService svr;
int rc=GetServiceInfo(service,&svr);
if(rc==2){
UCHAR*p=FindDescriptor(svr.descriptors,svr.descriptor_loop_length,SERVICE_DESCRIPTOR_TAG);
if(p)
return p[2];
}
return 0;
}
int GetNvodTimeShiftService(SERVICELOCATOR*refService,SERVICELOCATOR*timeShifts)
{
DVBService svr;
int rc=GetServiceInfo(refService,&svr);
if(rc==2){
int i,count;
UCHAR*p=FindDescriptor(svr.descriptors,svr.descriptor_loop_length,NVOD_REFERENCE_DESCRIPTOR_TAG);
if(p==NULL)
return 0;
count=p[1]/6;
if(timeShifts){
p+=2;
for(i=0;i<count;i++,p+=6){
timeShifts[i].tsId=(p[0]<<8)|p[1];
timeShifts[i].netId=(p[2]<<8)|p[3];
timeShifts[i].serviceId=(p[4]<<8)|p[5];
}
}
return count;
}
return 0;
}
int GetServiceName(SERVICELOCATOR*sloc,char*provider,char*sname,UCHAR*lan)
{
DVBService svr;
int rc=GetServiceInfo(sloc,&svr);
switch(rc){
case 0:
if(sname)sname[0]=0;
if(provider)provider[0]=0;
break;
case 1:
if(sname)
sprintf(sname,"DTV%d",sloc->serviceId);
break;
case 2:GetSdtServiceName(&svr,(UCHAR*)provider,(UCHAR*)sname,lan);
}
return rc;
}
int GetServiceParams(const SERVICELOCATOR*sloc,UINT*pids)
{
TSDATA*ts=FindTS(sloc->netId,sloc->tsId);
if(ts){
SECTIONDATA*sd=ts->pmt->sections;
while(sd){
unsigned sid=GetPmtServiceID(sd->Data);
if(sid==sloc->serviceId){
int i,ec=GetPmtElementCount(sd->Data);
for(i=0;i<ec;i++){
ProgElement p;
GetPmtElement(sd->Data,&p,i);
if(pids)
pids[i]=(p.stream_type<<16)|p.elementary_PID;
}
if(pids)pids[ec]=GetPmtPCRPID(sd->Data);
return ec+1;
}
sd=sd->next;
}
}
return 0;
}
int GetServicePIDS(const SERVICELOCATOR*sloc,USHORT*pcrPID,
USHORT*vID,USHORT*aIDs)
{
UINT pids[64],count,i,ac,rc;
count=GetServiceParams(sloc,pids);
if(count==0)
return 0;
*pcrPID=pids[count-1];
ac=0;rc=0;
for(i=0;i<count-1;i++){
switch(pids[i]>>16){
case 1:
case 2:*vID=pids[i]&0x1FFF;rc++;break;
case 3:
case 4:aIDs[ac++]=pids[i]&0x1FFF;rc++;break;
}
}
return rc+1;
}
USHORT GetServiceState(SERVICELOCATOR*sloc,USHORT mask)
{
TSDATA*ts=FindTS(sloc->netId,sloc->tsId);
int i=FindServiceInTS(ts,sloc->serviceId,NULL);
if(i==-1)
return 0;
i&=0xFF;
return ts->States[i]&mask;
}
USHORT SetServiceState(SERVICELOCATOR*sloc,USHORT mask)
{
TSDATA*ts=FindTS(sloc->netId,sloc->tsId);
int i=FindServiceInTS(ts,sloc->serviceId,NULL);
if(i==-1)
return 0;
i&=0xFF;
ts->States[i]|=mask;
return 1;
}
USHORT GetServicePmtPID(SERVICELOCATOR*sloc)
{
TSDATA*ts=FindTS(sloc->netId,sloc->tsId);
if(ts&&ts->pat&&ts->pat->sections){
return GetPmtPID(ts->pat->sections->Data,sloc->serviceId);
}
return 0;
}
SECTIONDB*GetBouquetDB(void)
{
return bouquetDB;
}
int GetBouquetName(USHORT bouquetId,char*name,char*lan)
{
SECTIONDATA*sd;
if(bouquetDB){
PrMutexLock(bouquetDB->lock,-1);
sd=bouquetDB->sections;
while(sd){
if(GetBatBouquetID(sd->Data)==bouquetId)
return GetBatBouquetName(sd->Data,(UCHAR*)name,(UCHAR*)lan);
sd=sd->next;
}
PrMutexUnlock(bouquetDB->lock);
}
return 0;
}
SECTIONDB*GetNetworkDB(void)
{
return networkDB;
}
int LoadDVBData(UCHAR*data)
{
UCHAR*p=data;
short i,Count;
UINT verifyBytes,seclen;
#ifdef _WIN32
FILE*f=fopen("fav.dat","rb");
data=(UCHAR*)PrMalloc(1024*64);
fread(data,1024*64,1,f);
p=data;
#endif
memcpy(&verifyBytes,p,4);p+=4;
if(verifyBytes!=VERIFIED_BYTES)
return 0;
memcpy(&Count,p,2); p+=2;//获取TS流数据总数
for(i=0;i<Count;i++){
TSDATA t,*ts;
memcpy(&t,p,sizeof(TSDATA)); p+=sizeof(TSDATA);
ts=CreateTS(t.netId,t.tsId);
ts->tunerParams=t.tunerParams;
//ts->pat=ts->pmt=ts->sdt=NULL;
memcpy(&seclen,p,4);p+=4;
while(seclen>0){
int slen=GetSectionLength(p)+3;
switch(p[0]){
case 0x00:AddSection(ts->pat,p);break;
case 0x02:AddSection(ts->pmt,p);break;
case 0x42:
case 0x46:AddSection(ts->sdt,p);break;
}
seclen-=slen; p+=slen;
}
}
memcpy(&Count,p,2);p+=2;//获取GROUP总数
for(i=0;i<Count;i++){
FAVGROUP grp,*fav;
int j;
memcpy(&grp,p,sizeof(FAVGROUP));p+=sizeof(FAVGROUP);
fav=CreateFavGroup(grp.name,grp.FavId);
AddFavGroup(fav);
for(j=0;j<grp.serviceCount;j++){
SERVICELOCATOR s;
memcpy(&s,p,sizeof(SERVICELOCATOR));p+=sizeof(SERVICELOCATOR);
if(GetServiceInfo(&s,NULL))
AddServiceToFavGroup(fav,&s);
}
}
memcpy(&seclen,p,4);p+=4;//读取NIT BAT section数据的长度
while(seclen){
int slen=GetSectionLength(p)+3;
if(p[0]==0x40||p[0]==0x41){
AddSection(networkDB,p);
}else if(p[0]==0x4A){
AddSection(networkDB,p);
}else
break;
seclen-=slen; p+=slen;
}
#ifdef _WIN32
PrFree(data);
fclose(f);
#endif
return p-data;
}
static int WriteSection(UCHAR*data,SECTIONDB*secdb)
{
UCHAR*p=data;
SECTIONDATA*sd;
if(secdb){
sd=secdb->sections;
while(sd){
int slen=GetSectionLength(sd->Data)+3;
memcpy(p,sd->Data,slen);
p+=slen;
sd=sd->next;
}
}
return p-data;
}
int SaveDVBData(UCHAR*data)
{
short Count=0;
FAVGROUP*grp=GetFirstFavGroup();//favGroups;
TSDATA*ts=streams;
UINT verifyBytes=VERIFIED_BYTES;
UCHAR*p=data;
while(ts){
Count++;
ts=ts->next;
}
memcpy(p,&verifyBytes,4);p+=4;
memcpy(p,&Count,2);p+=2;//写入TS总数 2 字节
ts=streams;
while(ts){
UCHAR*pseclen;
UINT secslen;
memcpy(p,ts,sizeof(TSDATA)); p+=sizeof(TSDATA);
pseclen=p;p+=4;
p+=WriteSection(p,ts->pat);
p+=WriteSection(p,ts->pmt);
p+=WriteSection(p,ts->sdt);
secslen=p-pseclen-4;
memcpy(pseclen,&secslen,4);
ts=ts->next;
}
Count=0;
while(grp){
Count++;
grp=grp->next;
}
memcpy(p,&Count,2); p+=2;//写入Group总数
grp=GetFirstFavGroup();//favGroups;
while(grp){
int slen;
memcpy(p,grp,sizeof(FAVGROUP));p+=sizeof(FAVGROUP);
slen=grp->serviceCount*sizeof(SERVICELOCATOR);
memcpy(p,grp->Services,slen); p+=slen;
grp=grp->next;
}
{
UCHAR*pseclen;
UINT secslen;
pseclen=p;p+=4;
if(networkDB)
p+=WriteSection(p,networkDB);
if(bouquetDB)
p+=WriteSection(p,bouquetDB);
secslen=p-pseclen-4;
memcpy(pseclen,&secslen,4);
}
return p-data;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -