diff options
author | Jochen Dolze <vdr@dolze.de> | 2009-09-25 21:25:30 +0200 |
---|---|---|
committer | Jochen Dolze <vdr@dolze.de> | 2009-09-25 21:25:30 +0200 |
commit | 404b1e87e9d1f8854cbbd5a438ec4791b6ed296b (patch) | |
tree | c533dfc3b656f2afe92560c94caaf50105504272 | |
parent | 8f9594678c4e0d94e546cd2e94f898bf796c86c6 (diff) | |
download | vdr-plugin-markad-404b1e87e9d1f8854cbbd5a438ec4791b6ed296b.tar.gz vdr-plugin-markad-404b1e87e9d1f8854cbbd5a438ec4791b6ed296b.tar.bz2 |
Updated demux, ts2pkt
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | demux.cpp | 67 | ||||
-rw-r--r-- | demux.h | 21 | ||||
-rw-r--r-- | markad-standalone.cpp | 60 | ||||
-rw-r--r-- | recv.cpp | 12 | ||||
-rw-r--r-- | ts2pes.cpp | 269 | ||||
-rw-r--r-- | ts2pkt.cpp | 323 | ||||
-rw-r--r-- | ts2pkt.h (renamed from ts2pes.h) | 48 |
8 files changed, 469 insertions, 333 deletions
@@ -64,7 +64,7 @@ endif ### The object files (add further files here): OBJS-CMD = markad-standalone.o -OBJS-COMMON = demux.o video.o audio.o decoder.o common.o ts2pes.o pes2audioes.o +OBJS-COMMON = demux.o video.o audio.o decoder.o common.o ts2pkt.o pes2audioes.o OBJS = $(PLUGIN).o recv.o status.o $(OBJS-COMMON) ### The main target: @@ -8,38 +8,67 @@ #include "demux.h" -cMarkAdDemux::cMarkAdDemux() +cMarkAdDemux::cMarkAdDemux(int RecvNumber) { - ts2pes=new cMarkAdTS2PES(); + ts2pkt=new cMarkAdTS2Pkt(RecvNumber); pes2audioes=NULL; - pespkt=NULL; + pkt=NULL; pesptr=NULL; - peslen=0; + pktlen=0; + tsdata=tsptr=NULL; + tssize=0; } cMarkAdDemux::~cMarkAdDemux() { - if (ts2pes) delete ts2pes; + if (ts2pkt) delete ts2pkt; if (pes2audioes) delete pes2audioes; + if (tsdata) free(tsdata); } int cMarkAdDemux::Process(MarkAdPid Pid, uchar *Data, int Count, uchar **Pkt, int *PktLen) { - if ((!Data) && (!Count) && (!ts2pes) && (!pes2audioes) || + if ((!Data) && (!Count) && (!ts2pkt) && (!pes2audioes) || (!Pkt) || (!PktLen) || (!Pid.Num)) return -1; *Pkt=NULL; *PktLen=0; int len=-1; // we don't want loops - if (!peslen) + if (!pktlen) { - len=ts2pes->Process(Pid,Data,Count,&pespkt,&peslen); + if (tssize<TS_SIZE) + { + tsdata=(uchar *) realloc(tsdata,tssize+Count); + if (!tsdata) return -1; + memcpy(tsdata+tssize,Data,Count); + tssize+=Count; + tsptr=tsdata; + if (tssize<TS_SIZE) return Count; + } + len=ts2pkt->Process(Pid,tsdata,tssize,&pkt,&pktlen); + + int bufleftsize=tssize-len; + uchar *ptr=(uchar *) malloc(bufleftsize); + if (!ptr) return -1; + memcpy(ptr,tsdata+len,bufleftsize); + + free(tsdata); + tsdata=ptr; + tssize=bufleftsize; + if (tssize<TS_SIZE) + { + len=Count; + } + else + { + len=0; + } } - if (pespkt) + if (pkt) { - if ((((pespkt[3]>=0xc0) && (pespkt[3]<=0xDF)) || (pespkt[3]==0xBD)) + if ((((pkt[3]>=0xc0) && (pkt[3]<=0xDF)) || (pkt[3]==0xBD)) && (!pesptr)) { if (!pes2audioes) @@ -48,7 +77,7 @@ int cMarkAdDemux::Process(MarkAdPid Pid, uchar *Data, int Count, uchar **Pkt, in } if (pes2audioes) { - pesptr=pespkt; + pesptr=pkt; } else { @@ -61,9 +90,9 @@ int cMarkAdDemux::Process(MarkAdPid Pid, uchar *Data, int Count, uchar **Pkt, in if (len==-1) len=0; uchar *esdata; int essize; - while (peslen>0) + while (pktlen>0) { - int len2=pes2audioes->Process(pesptr,peslen,&esdata,&essize); + int len2=pes2audioes->Process(pesptr,pktlen,&esdata,&essize); if (len2<0) { break; @@ -76,8 +105,8 @@ int cMarkAdDemux::Process(MarkAdPid Pid, uchar *Data, int Count, uchar **Pkt, in *PktLen=essize; } pesptr+=len2; - peslen-=len2; - if (!peslen) pesptr=NULL; + pktlen-=len2; + if (!pktlen) pesptr=NULL; break; } } @@ -85,10 +114,10 @@ int cMarkAdDemux::Process(MarkAdPid Pid, uchar *Data, int Count, uchar **Pkt, in } else { - *Pkt=pespkt; - *PktLen=peslen; - pespkt=pesptr=NULL; - peslen=0; + *Pkt=pkt; + *PktLen=pktlen; + pkt=pesptr=NULL; + pktlen=0; } } return len; @@ -9,20 +9,29 @@ #ifndef __demux_h_ #define __demux_h_ +#ifndef TS_SIZE +#define TS_SIZE 188 +#endif + #include "global.h" -#include "ts2pes.h" +#include "ts2pkt.h" #include "pes2audioes.h" class cMarkAdDemux { private: - cMarkAdTS2PES *ts2pes; + cMarkAdTS2Pkt *ts2pkt; cMarkAdPES2AudioES *pes2audioes; - uchar *pespkt; - uchar *pesptr; // pointer into pespkt - int peslen; + uchar *pkt; + uchar *pesptr; // pointer into pkt + + uchar *tsdata; + int tssize; + uchar *tsptr; + + int pktlen; public: - cMarkAdDemux(); + cMarkAdDemux(int RecvNumber); ~cMarkAdDemux(); int Process(MarkAdPid Pid, uchar *Data, int Count, uchar **Pkt, int *PktLen); }; diff --git a/markad-standalone.cpp b/markad-standalone.cpp index ed57ceb..3e6e8d1 100644 --- a/markad-standalone.cpp +++ b/markad-standalone.cpp @@ -125,16 +125,23 @@ bool cMarkAdStandalone::ProcessFile(int Number) if (!dir) return false; if (!Number) return false; - uchar data[2048]; + uchar *data; int datalen; + int dataread; char *fbuf; if (index->isTS()) { + datalen=70688; // multiple of 188 + data=(uchar *) malloc(datalen); + if (!data) return false; asprintf(&fbuf,"%s/%05i.ts",dir,Number); } else { + datalen=69632; // VDR paket size + data=(uchar *) malloc(datalen); + if (!data)return false; asprintf(&fbuf,"%s/%03i.vdr",dir,Number); } if (!fbuf) return false; @@ -144,10 +151,10 @@ bool cMarkAdStandalone::ProcessFile(int Number) if (f==-1) return false; int lastiframe; - while ((datalen=read(f,&data,sizeof(data))>0)) + while ((dataread=read(f,data,datalen))>0) { - lastiframe=LastIFrame(Number,lseek(f,0,SEEK_CUR)-datalen); + lastiframe=LastIFrame(Number,lseek(f,0,SEEK_CUR)-dataread); MarkAdMark *mark; if (common) @@ -162,7 +169,7 @@ bool cMarkAdStandalone::ProcessFile(int Number) int pktlen; uchar *tspkt = data; - int tslen = datalen; + int tslen = dataread; while (tslen>0) { @@ -180,7 +187,6 @@ bool cMarkAdStandalone::ProcessFile(int Number) { mark=video->Process(lastiframe); AddMark(mark); - } } tspkt+=len; @@ -195,7 +201,7 @@ bool cMarkAdStandalone::ProcessFile(int Number) int pktlen; uchar *tspkt = data; - int tslen = datalen; + int tslen = dataread; while (tslen>0) { @@ -226,7 +232,7 @@ bool cMarkAdStandalone::ProcessFile(int Number) int pktlen; uchar *tspkt = data; - int tslen = datalen; + int tslen = dataread; while (tslen>0) { @@ -250,8 +256,9 @@ bool cMarkAdStandalone::ProcessFile(int Number) tslen-=len; } } - } + } } + free(data); close(f); return true; } @@ -279,30 +286,47 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory) { dir=strdup(Directory); + index = new cMarkAdIndex(Directory); + if (!index) + { + video_demux=ac3_demux=mp2_demux=NULL; + decoder=NULL; + video=NULL; + audio=NULL; + common=NULL; + return; + } + memset(&macontext,0,sizeof(macontext)); macontext.General.StartTime=0; macontext.General.EndTime=time(NULL)+(7*86400); macontext.General.DPid.Type=MARKAD_PIDTYPE_AUDIO_AC3; macontext.General.APid.Type=MARKAD_PIDTYPE_AUDIO_MP2; - macontext.General.VPid.Type=MARKAD_PIDTYPE_VIDEO_H262; + if (index->isTS()) + { + macontext.General.VPid.Type=MARKAD_PIDTYPE_VIDEO_H264; + } + else + { + macontext.General.VPid.Type=MARKAD_PIDTYPE_VIDEO_H262; + } - macontext.General.VPid.Num=0x100; - macontext.General.DPid.Num=0x102; - macontext.General.APid.Num=0x101; + macontext.General.VPid.Num=0x3ff; +// macontext.General.DPid.Num=0x403; + macontext.General.APid.Num=0x0; - video_demux = new cMarkAdDemux(); + video_demux = new cMarkAdDemux(255); -// mp2_demux = new cMarkAdDemux(); +// mp2_demux = new cMarkAdDemux(255); mp2_demux=NULL; - ac3_demux = new cMarkAdDemux(); - decoder = new cMarkAdDecoder(255,false,false); + ac3_demux = new cMarkAdDemux(255); + decoder = new cMarkAdDecoder(255,index->isTS(), + macontext.General.DPid.Num!=0); video = new cMarkAdVideo(255,&macontext); audio = new cMarkAdAudio(255,&macontext); common = new cMarkAdCommon(255,&macontext); - - index = new cMarkAdIndex(Directory); } cMarkAdStandalone::~cMarkAdStandalone() @@ -55,7 +55,7 @@ cMarkAdReceiver::cMarkAdReceiver(int RecvNumber, const char *Filename, cTimer *T } // macontext.General.APid.Pid=Timer->Channel()->Apid(0); // TODO ... better solution? -// macontext.General.DPid.Type=MARKAD_PIDTYPE_AUDIO_MP2; +// macontext.General.APid.Type=MARKAD_PIDTYPE_AUDIO_MP2; macontext.General.DPid.Num=Timer->Channel()->Dpid(0); // TODO ... better solution? macontext.General.DPid.Type=MARKAD_PIDTYPE_AUDIO_AC3; @@ -64,9 +64,9 @@ cMarkAdReceiver::cMarkAdReceiver(int RecvNumber, const char *Filename, cTimer *T if (macontext.General.VPid.Num) { - dsyslog("markad [%i]: using video",recvnumber); + dsyslog("markad [%i]: using %s-video",recvnumber,useH264 ? "H262": "H264"); video=new cMarkAdVideo(RecvNumber,&macontext); - video_demux = new cMarkAdDemux(); + video_demux = new cMarkAdDemux(RecvNumber); } else { @@ -77,7 +77,7 @@ cMarkAdReceiver::cMarkAdReceiver(int RecvNumber, const char *Filename, cTimer *T if (macontext.General.APid.Num) { dsyslog("markad [%i]: using mp2",recvnumber); - mp2_demux = new cMarkAdDemux(); + mp2_demux = new cMarkAdDemux(RecvNumber); } else { @@ -87,7 +87,7 @@ cMarkAdReceiver::cMarkAdReceiver(int RecvNumber, const char *Filename, cTimer *T if (macontext.General.DPid.Num) { dsyslog("markad [%i]: using ac3",recvnumber); - ac3_demux = new cMarkAdDemux(); + ac3_demux = new cMarkAdDemux(RecvNumber); } else { @@ -274,7 +274,7 @@ void cMarkAdReceiver::Action() } if (t.Elapsed()>100) { - isyslog("markad [%i]: 100ms exceeded -> %Li", + isyslog("markad [%i]: 100ms exceeded -> %Lims", recvnumber,t.Elapsed()); } } diff --git a/ts2pes.cpp b/ts2pes.cpp deleted file mode 100644 index 702fff8..0000000 --- a/ts2pes.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/* - * ts2pes.cpp: A plugin for the Video Disk Recorder - * - * See the README file for copyright information and how to reach the author. - * - * $Id$ - */ - -#include "ts2pes.h" - -#include <stdio.h> - -cMarkAdTS2PES::cMarkAdTS2PES() -{ - pesdata=NULL; - pesdatalast=NULL; - Reset(); -} - -cMarkAdTS2PES::~cMarkAdTS2PES() -{ - if (pesdata) free(pesdata); - if (pesdatalast) free(pesdatalast); -} - -void cMarkAdTS2PES::Reset() -{ - if (pesdata) free(pesdata); - pesdata=NULL; - pessize=0; - data_left=false; - counter=-1; - sync=false; -} - -int cMarkAdTS2PES::FindPESHeader(uchar *TSData, int TSSize, int *StreamSize, - int *HeaderSize) -{ - if ((!TSData) || (!TSSize)) return -1; -#define PESHDRSIZE 6 - if (StreamSize) (*StreamSize)=0; - if (HeaderSize) (*HeaderSize)=3; - //unsigned long scanner=0xFFFFFFFF; - int i=0; -long scanner=-1; - - for (i=0; i<TSSize; i++) - { - scanner<<=8; - if (scanner==(long) 0x00000100L) - { - break; - } - scanner|=TSData[i]; - } - if (i!=TSSize) - { - if ((StreamSize) && ((i+2)<TSSize)) - { - if (TSData[i]>=0xBC) - { - (*StreamSize)=(TSData[i+1]<<8)+TSData[i+2]; - if (*StreamSize) (*StreamSize)+=6; // 6 Byte PES-Header - } - } - if ((HeaderSize) && ((i+6)<TSSize)) - { - struct PESHDROPT *peshdropt=(struct PESHDROPT *) &TSData[i+3]; - if (peshdropt->MarkerBits==0x2) - { - (*HeaderSize)=PESHDRSIZE+sizeof(struct PESHDROPT)+ - peshdropt->Length; - } - else - { - (*HeaderSize)=PESHDRSIZE; - } - } - return i-3; - } - return -1; -} - -int cMarkAdTS2PES::Process(MarkAdPid Pid, uchar *TSData, int TSSize, uchar **PESData, int *PESSize) -{ - if ((!PESData) || (!PESSize) || (!TSData) || (!TSSize)) return -1; - *PESData=NULL; - *PESSize=0; - - int buflen=TS_SIZE+1; - uchar *buf=NULL; - - int bytes_processed; - - if (!data_left) - { - // search for TS packet sync - int i; - for (i=0; i<TSSize; i++) - { - if (TSData[i]==0x47) break; - } - if (i==TSSize) - { - Reset(); - return TSSize; - } - TSData+=i; - TSSize-=i; - - struct TSHDR *tshdr = (struct TSHDR *) TSData; - - int pid = (tshdr->PidH << 8) | tshdr->PidL; - if (Pid.Num!=pid) - { - return TS_SIZE; // not for us - } - - if ((tshdr->PayloadStart==0) && (!sync)) - { - return TS_SIZE; - } - else - { - sync=true; - } - - if ((counter!=-1) && (((counter+1) & 0xF)!=tshdr->Counter)) - { - // sequence error - Reset(); - return TS_SIZE; - } - counter=tshdr->Counter; - - if ((tshdr->AFC<=0) || (tshdr->AFC>3)) - { - Reset(); - return TS_SIZE; - } - - // we just ignore the infos in the adaption field (e.g. OPCR/PCR) - if ((tshdr->AFC!=1) && (tshdr->AFC!=3)) - { - return TS_SIZE; - } - - if (tshdr->AFC==1) - { - // payload only - buflen=TS_SIZE-sizeof(struct TSHDR); - buf=&TSData[sizeof(struct TSHDR)]; - } - - if (tshdr->AFC==3) - { - // adaption field + payload - struct TSADAPT *tsadapt = (struct TSADAPT *) &TSData[4]; - int alen=tsadapt->Len+1; - buflen=TS_SIZE-(sizeof(struct TSHDR)+alen); - buf=&TSData[sizeof(struct TSHDR)+alen]; - } - - if (buflen>TS_SIZE) - { - // size to large - Reset(); - return TS_SIZE; - } - if (buflen<0) - { - // error in size - Reset(); - return TS_SIZE; - } - - bytes_processed=TS_SIZE-buflen; - - pesdata=(uchar *) realloc(pesdata,pessize+buflen); - if (!pesdata) - { - pessize=0; - return -1; - } - memcpy(pesdata+pessize,buf,buflen); - pessize+=buflen; - bytes_processed+=buflen; - } - else - { - bytes_processed=pessize; - data_left=false; - } - - int streamsize=0; - int peshdrsize=3; // size of sync (just as start) - int peshdr=FindPESHeader(pesdata, pessize, &streamsize, &peshdrsize); - - if (peshdr==0) - { - if (!streamsize) - { - peshdr=FindPESHeader(pesdata+peshdrsize,pessize-peshdrsize,NULL,NULL); - if (peshdr>=0) - { - peshdr+=peshdrsize; - } - } - else - { - if (pessize>streamsize) - { - int size=pessize-streamsize; - uchar *pesptr=pesdata; - *PESData=pesdata; - *PESSize=streamsize; - if (pesdatalast) free(pesdatalast); - pesdatalast=pesdata; - pesdata=NULL; - pessize=0; - - void *ptr=malloc(size); - if (!ptr) return -1; - memcpy(ptr,pesptr+streamsize,size); - bytes_processed-=size; - pessize=size; - pesdata=(uchar *) ptr; - data_left=true; - } - } - } - - if (peshdr>0) - { - // start of next PES paket found - if (pesdata) - { - if ((pesdata[0]==0) && (pesdata[1]==0) && (pesdata[2]==1)) - { - // return old data - uchar *pesptr=pesdata; - *PESData=pesdata; - *PESSize=peshdr; - if (pesdatalast) free(pesdatalast); - pesdatalast=pesdata; - int size=pessize-peshdr; - pesdata=NULL; - pessize=0; - - if (size>0) - { - void *ptr=malloc(size); - if (!ptr) return -1; - memcpy(ptr,pesptr+peshdr,size); - bytes_processed-=size; - pessize=size; - pesdata=(uchar *) ptr; - data_left=true; - } - else - { - // TODO: not sure if this is ok - bytes_processed-=size; - } - } - } - } - return bytes_processed; -} diff --git a/ts2pkt.cpp b/ts2pkt.cpp new file mode 100644 index 0000000..08139b6 --- /dev/null +++ b/ts2pkt.cpp @@ -0,0 +1,323 @@ +/* + * ts2pkt.cpp: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id$ + */ + +#include "ts2pkt.h" + +cMarkAdTS2Pkt::cMarkAdTS2Pkt(int RecvNumber) +{ + recvnumber=RecvNumber; + pktdata=NULL; + pktdatalast=NULL; + Reset(); +} + +cMarkAdTS2Pkt::~cMarkAdTS2Pkt() +{ + if (pktdata) free(pktdata); + if (pktdatalast) free(pktdatalast); +} + +void cMarkAdTS2Pkt::Reset(int ErrIndex) +{ + switch (ErrIndex) + { + case MA_ERR_TOSMALL: + dsyslog("markad [%i]: input to small",recvnumber); + break; + case MA_ERR_NOSYNC: + dsyslog("markad [%i]: found no sync",recvnumber); + break; + case MA_ERR_SEQ: + dsyslog("markad [%i]: sequence error",recvnumber); + break; + case MA_ERR_AFC: + dsyslog("markad [%i]: wrong AFC value",recvnumber); + break; + case MA_ERR_TOBIG: + dsyslog("markad [%i]: buflen > 188",recvnumber); + break; + case MA_ERR_NEG: + dsyslog("markad [%i]: buflen < 0",recvnumber); + break; + case MA_ERR_MEM: + dsyslog("markad [%i]: out of memory",recvnumber); + break; + } + + if (pktdata) free(pktdata); + pktdata=NULL; + pktsize=0; + dataleft=false; + counter=-1; + pktinfo.pkthdr=-1; + isPES=false; +} + +bool cMarkAdTS2Pkt::CheckStreamID(MarkAdPid Pid, uchar *Data, int Size) +{ + if ((!Data) || (!Size)) return false; + if (Size<3) return false; + int streamid=Data[3]; + + switch (Pid.Type) + { + case MARKAD_PIDTYPE_AUDIO_AC3: + if (streamid!=0xBD) return false; + return true; + break; + case MARKAD_PIDTYPE_AUDIO_MP2: + if ((streamid & 0xF0)!=0xC0) return false; + return true; + break; + case MARKAD_PIDTYPE_VIDEO_H262: + case MARKAD_PIDTYPE_VIDEO_H264: + if ((streamid>=0xBC) && (streamid<0xE0)) return false; + if (streamid>0xEF) return false; + return true; + break; + default: + return false; + } + return false; +} + +int cMarkAdTS2Pkt::FindPktHeader(uchar *Data, int Size, int *StreamSize, + int *HeaderSize) +{ +#define PESHDRSIZE 6 + if ((!Data) || (!Size)) return -1; + if (StreamSize) (*StreamSize)=0; + if (HeaderSize) (*HeaderSize)=3; + + unsigned long scanner=0xFFFFFFFF; + int i; + + for (i=0; i<Size; i++) + { + scanner<<=8; + if (scanner==0x00000100L) + { + break; + } + scanner|=Data[i]; + } + if (i!=Size) + { + if ((StreamSize) && ((i+2)<Size)) + { + if (Data[i]>=0xBC) // do we have a PES packet? + { + (*StreamSize)=(Data[i+1]<<8)+Data[i+2]; + if (*StreamSize) (*StreamSize)+=PESHDRSIZE; // 6 Byte PES-Header + + if ((HeaderSize) && ((i+PESHDRSIZE)<Size)) + { + struct PESHDROPT *peshdropt=(struct PESHDROPT *) &Data[i+3]; + if (peshdropt->MarkerBits==0x2) + { + (*HeaderSize)=PESHDRSIZE+sizeof(struct PESHDROPT)+ + peshdropt->Length; + } + else + { + (*HeaderSize)=PESHDRSIZE; + } + } + } + } + return i-3; + } + return -1; +} + +int cMarkAdTS2Pkt::Process(MarkAdPid Pid, uchar *TSData, int TSSize, uchar **PktData, int *PktSize) +{ + if ((!PktData) || (!PktSize) || (!TSData) || (!TSSize)) return -1; + *PktData=NULL; + *PktSize=0; + + int buflen=TS_SIZE+1; + uchar *buf=NULL; + + int bytes_processed; // pointer in TSData + + if (!dataleft) + { + if (TSSize<TS_SIZE) + { + Reset(MA_ERR_TOSMALL); + return TSSize; // we need a full packet + } + + if ((TSData[0]==0) && (TSData[1]==0) && (TSData[2]==1)) + { + isPES=true; + } + + if (isPES) + { + buf=TSData; + buflen=TSSize; + } + else + { + // search for TS packet sync + int i; + for (i=0; i<TSSize; i++) + { + if (TSData[i]==0x47) break; + } + if (i==TSSize) + { + Reset(MA_ERR_NOSYNC); + return TSSize; + } + TSData+=i; + TSSize-=i; + + struct TSHDR *tshdr = (struct TSHDR *) TSData; + + int pid = (tshdr->PidH << 8) | tshdr->PidL; + if (Pid.Num!=pid) + { + return TS_SIZE; // not for us + } + + if ((counter!=-1) && (((counter+1) & 0xF)!=tshdr->Counter)) + { + // sequence error + Reset(MA_ERR_SEQ); + return TS_SIZE; + } + counter=tshdr->Counter; + + if ((tshdr->AFC<=0) || (tshdr->AFC>3)) + { + Reset(MA_ERR_AFC); + return TS_SIZE; + } + + // we just ignore the infos in the adaption field (e.g. OPCR/PCR) + if ((tshdr->AFC!=1) && (tshdr->AFC!=3)) + { + return TS_SIZE; + } + + if (tshdr->AFC==1) + { + // payload only + buflen=TS_SIZE-sizeof(struct TSHDR); + buf=&TSData[sizeof(struct TSHDR)]; + } + + if (tshdr->AFC==3) + { + // adaption field + payload + struct TSADAPT *tsadapt = (struct TSADAPT *) &TSData[4]; + int alen=tsadapt->Len+1; + buflen=TS_SIZE-(sizeof(struct TSHDR)+alen); + buf=&TSData[sizeof(struct TSHDR)+alen]; + } + + if (buflen>TS_SIZE) + { + // size to large + Reset(MA_ERR_TOBIG); + return TS_SIZE; + } + if (buflen<0) + { + // error in size + Reset(MA_ERR_NEG); + return TS_SIZE; + } + + } + pktdata=(uchar *) realloc(pktdata,pktsize+buflen); + if (!pktdata) + { + Reset(MA_ERR_MEM); + return -1; + } + memcpy(pktdata+pktsize,buf,buflen); + pktsize+=buflen; + if (isPES) + { + bytes_processed=buflen; + } + else + { + bytes_processed=TS_SIZE; + } + } + else + { + bytes_processed=pktsize; + dataleft=false; + } + + if (pktinfo.pkthdr==-1) + { + pktinfo.pkthdr=FindPktHeader(pktdata, pktsize, &pktinfo.streamsize, &pktinfo.pkthdrsize); + if (pktinfo.pkthdr==-1) + { + return bytes_processed; // not found any header -> next paket + } + } + + int streamsize=0; + int pkthdrsize; + int pkthdr=FindPktHeader(pktdata+pktinfo.pkthdr+pktinfo.pkthdrsize, + pktsize-(pktinfo.pkthdr+pktinfo.pkthdrsize),&streamsize,&pkthdrsize); + + if (pkthdr==-1) + { + return bytes_processed; // no next header -> next packet + } + + pkthdr+=(pktinfo.pkthdrsize+pktinfo.pkthdr); + + // found paket between pktinfo.pkthdr and pkthdr + int size = pkthdr-pktinfo.pkthdr; + if (size<pktinfo.streamsize) size=pktinfo.streamsize; + + if (pktsize<size) return bytes_processed; // we need more data! + + (*PktData)=pktdata+pktinfo.pkthdr; + (*PktSize)=size; + if (isPES) + { + if (!CheckStreamID(Pid,*PktData,*PktSize)) + { + (*PktData)=NULL; + (*PktSize)=0; + } + } + if (pktdatalast) free(pktdatalast); + pktdatalast=pktdata; + + int bufleftsize=pktsize-(pktinfo.pkthdr+size); + + uchar *bufleft=(uchar *) malloc(bufleftsize); + if (!bufleft) + { + Reset(MA_ERR_MEM); + return bytes_processed; + } + memcpy(bufleft,pktdata+pktinfo.pkthdr+size,bufleftsize); + pktinfo.pkthdr=-1; + pktdata=bufleft; + pktsize=bufleftsize; + + bytes_processed-=bufleftsize; + if (bytes_processed<0) bytes_processed=0; // just to be safe + + dataleft=true; + + return bytes_processed; +} @@ -1,13 +1,15 @@ /* - * ts2pes.h: A plugin for the Video Disk Recorder + * ts2pkt.h: A plugin for the Video Disk Recorder * * See the README file for copyright information and how to reach the author. * * $Id$ */ -#ifndef __ts2pes_h_ -#define __ts2pes_h_ +#ifndef __ts2pkt_h_ +#define __ts2pkt_h_ + +#include <vdr/tools.h> #ifndef TS_SIZE #define TS_SIZE 188 @@ -22,7 +24,7 @@ typedef unsigned char uchar; #include "global.h" -class cMarkAdTS2PES +class cMarkAdTS2Pkt { private: struct TSHDR @@ -89,19 +91,37 @@ unsigned Length: }; #pragma pack() - uchar *pesdatalast; - uchar *pesdata; - int pessize; - bool data_left; + struct pktinfo + { + int pkthdr; + int pkthdrsize; + int streamsize; + } pktinfo; + + int recvnumber; + + bool isPES; + uchar *pktdatalast; + uchar *pktdata; + int pktsize; + bool dataleft; int counter; - bool sync; - void Reset(); - int FindPESHeader(uchar *TSData, int TSSize, int *StreamSize, int *HeaderSize); +#define MA_ERR_STARTUP 0 +#define MA_ERR_TOSMALL 1 +#define MA_ERR_NOSYNC 2 +#define MA_ERR_SEQ 3 +#define MA_ERR_AFC 4 +#define MA_ERR_TOBIG 5 +#define MA_ERR_NEG 6 +#define MA_ERR_MEM 7 + void Reset(int ErrIndex=MA_ERR_STARTUP); + int FindPktHeader(uchar *TSData, int TSSize, int *StreamSize, int *HeaderSize); + bool CheckStreamID(MarkAdPid Pid, uchar *Data, int Size); public: - cMarkAdTS2PES(); - ~cMarkAdTS2PES(); - int Process(MarkAdPid Pid,uchar *TSData, int TSSize, uchar **PESData, int *PESSize); + cMarkAdTS2Pkt(int RecvNumber); + ~cMarkAdTS2Pkt(); + int Process(MarkAdPid Pid,uchar *TSData, int TSSize, uchar **PktData, int *PktSize); }; #endif |