summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJochen Dolze <vdr@dolze.de>2009-09-25 21:25:30 +0200
committerJochen Dolze <vdr@dolze.de>2009-09-25 21:25:30 +0200
commit404b1e87e9d1f8854cbbd5a438ec4791b6ed296b (patch)
treec533dfc3b656f2afe92560c94caaf50105504272
parent8f9594678c4e0d94e546cd2e94f898bf796c86c6 (diff)
downloadvdr-plugin-markad-404b1e87e9d1f8854cbbd5a438ec4791b6ed296b.tar.gz
vdr-plugin-markad-404b1e87e9d1f8854cbbd5a438ec4791b6ed296b.tar.bz2
Updated demux, ts2pkt
-rw-r--r--Makefile2
-rw-r--r--demux.cpp67
-rw-r--r--demux.h21
-rw-r--r--markad-standalone.cpp60
-rw-r--r--recv.cpp12
-rw-r--r--ts2pes.cpp269
-rw-r--r--ts2pkt.cpp323
-rw-r--r--ts2pkt.h (renamed from ts2pes.h)48
8 files changed, 469 insertions, 333 deletions
diff --git a/Makefile b/Makefile
index a55426c..4c17bcd 100644
--- a/Makefile
+++ b/Makefile
@@ -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:
diff --git a/demux.cpp b/demux.cpp
index 96748a2..a0aec72 100644
--- a/demux.cpp
+++ b/demux.cpp
@@ -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;
diff --git a/demux.h b/demux.h
index 00e8727..d0b8265 100644
--- a/demux.h
+++ b/demux.h
@@ -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()
diff --git a/recv.cpp b/recv.cpp
index 447d82a..f105aa4 100644
--- a/recv.cpp
+++ b/recv.cpp
@@ -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;
+}
diff --git a/ts2pes.h b/ts2pkt.h
index 2511eb3..e610050 100644
--- a/ts2pes.h
+++ b/ts2pkt.h
@@ -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