summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJochen Dolze <vdr@dolze.de>2009-10-02 17:36:58 +0200
committerJochen Dolze <vdr@dolze.de>2009-10-02 17:36:58 +0200
commit52cd041405849817c72d272bee0e6798f57b66c4 (patch)
tree994709d9e41ae0a367ba4b0bf5254911a4f38558
parenta21c3bf58621446068b054326eec83dae1e744a0 (diff)
downloadvdr-plugin-markad-52cd041405849817c72d272bee0e6798f57b66c4.tar.gz
vdr-plugin-markad-52cd041405849817c72d272bee0e6798f57b66c4.tar.bz2
Rewrote packet handling code, now it uses queues
-rw-r--r--Makefile4
-rw-r--r--decoder.cpp3
-rw-r--r--demux.cpp187
-rw-r--r--demux.h23
-rw-r--r--global.h1
-rw-r--r--markad-standalone.cpp49
-rw-r--r--pes2audioes.cpp273
-rw-r--r--pes2es.cpp95
-rw-r--r--pes2es.h79
-rw-r--r--recv.cpp36
-rw-r--r--tools.cpp333
-rw-r--r--tools.h (renamed from pes2audioes.h)135
-rw-r--r--ts2pkt.cpp333
-rw-r--r--ts2pkt.h57
-rw-r--r--vdr2pkt.cpp30
-rw-r--r--vdr2pkt.h29
16 files changed, 854 insertions, 813 deletions
diff --git a/Makefile b/Makefile
index db3eac3..143985b 100644
--- a/Makefile
+++ b/Makefile
@@ -63,8 +63,8 @@ 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 ts2pkt.o pes2audioes.o
+OBJS-CMD = markad-standalone.o
+OBJS-COMMON = demux.o video.o audio.o decoder.o common.o tools.o vdr2pkt.o ts2pkt.o pes2es.o
OBJS = $(PLUGIN).o recv.o status.o $(OBJS-COMMON)
### The main target:
diff --git a/decoder.cpp b/decoder.cpp
index 12ac059..ef34fb8 100644
--- a/decoder.cpp
+++ b/decoder.cpp
@@ -94,8 +94,9 @@ unsigned AcMod:
void cMarkAdDecoder::FindVideoInfos(MarkAdContext *maContext, uchar *pkt, int len)
{
if ((!maContext) || (!pkt) || (!len)) return;
+ if (!maContext->General.VPid.Type) return;
- if (maContext->General.H264)
+ if (maContext->General.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264)
{
FindH264VideoInfos(maContext, pkt, len);
}
diff --git a/demux.cpp b/demux.cpp
index a0aec72..c36508f 100644
--- a/demux.cpp
+++ b/demux.cpp
@@ -10,116 +10,119 @@
cMarkAdDemux::cMarkAdDemux(int RecvNumber)
{
- ts2pkt=new cMarkAdTS2Pkt(RecvNumber);
+ recvnumber=RecvNumber;
+ ts2pkt=NULL;
+ vdr2pkt=NULL;
pes2audioes=NULL;
- pkt=NULL;
- pesptr=NULL;
- pktlen=0;
- tsdata=tsptr=NULL;
- tssize=0;
+ pes2videoes=NULL;
+ queue = new cMarkAdPaketQueue(RecvNumber,"Demux");
}
cMarkAdDemux::~cMarkAdDemux()
{
if (ts2pkt) delete ts2pkt;
+ if (vdr2pkt) delete vdr2pkt;
if (pes2audioes) delete pes2audioes;
- if (tsdata) free(tsdata);
+ if (pes2videoes) delete pes2videoes;
+ if (queue) delete queue;
}
-int cMarkAdDemux::Process(MarkAdPid Pid, uchar *Data, int Count, uchar **Pkt, int *PktLen)
+void cMarkAdDemux::ProcessVDR(MarkAdPid Pid, uchar *Data, int Count, uchar **Pkt, int *PktLen)
{
- if ((!Data) && (!Count) && (!ts2pkt) && (!pes2audioes) ||
- (!Pkt) || (!PktLen) || (!Pid.Num)) return -1;
+ if ((!Pkt) || (!PktLen)) return;
*Pkt=NULL;
*PktLen=0;
- int len=-1; // we don't want loops
+ uchar *pkt;
+ int pktlen;
+
+ if (!vdr2pkt) vdr2pkt= new cMarkAdVDR2Pkt(recvnumber);
+ if (!vdr2pkt) return;
+
+ vdr2pkt->Process(Pid,Data,Count,&pkt,&pktlen);
- if (!pktlen)
+ if ((Pid.Type==MARKAD_PIDTYPE_AUDIO_AC3) || (Pid.Type==MARKAD_PIDTYPE_AUDIO_MP2))
{
- 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 (!pes2audioes) pes2audioes=new cMarkAdPES2ES(recvnumber,"PES2ES audio");
+ if (!pes2audioes) return;
+ pes2audioes->Process(Pid,pkt,pktlen,Pkt,PktLen);
+ return;
}
- if (pkt)
+
+ if ((Pid.Type==MARKAD_PIDTYPE_VIDEO_H262) || (Pid.Type==MARKAD_PIDTYPE_VIDEO_H264))
{
+ if (!pes2videoes) pes2videoes=new cMarkAdPES2ES(recvnumber,"PES2ES video",262144);
+ if (!pes2videoes) return;
+ pes2videoes->Process(Pid,pkt,pktlen,Pkt,PktLen);
+ return;
+ }
+ return;
+}
- if ((((pkt[3]>=0xc0) && (pkt[3]<=0xDF)) || (pkt[3]==0xBD))
- && (!pesptr))
- {
- if (!pes2audioes)
- {
- pes2audioes=new cMarkAdPES2AudioES();
- }
- if (pes2audioes)
- {
- pesptr=pkt;
- }
- else
- {
- pesptr=NULL;
- }
- }
- if (pesptr)
- {
-
- if (len==-1) len=0;
- uchar *esdata;
- int essize;
- while (pktlen>0)
- {
- int len2=pes2audioes->Process(pesptr,pktlen,&esdata,&essize);
- if (len2<0)
- {
- break;
- }
- else
- {
- if (esdata)
- {
- *Pkt=esdata;
- *PktLen=essize;
- }
- pesptr+=len2;
- pktlen-=len2;
- if (!pktlen) pesptr=NULL;
- break;
- }
- }
-
- }
- else
- {
- *Pkt=pkt;
- *PktLen=pktlen;
- pkt=pesptr=NULL;
- pktlen=0;
- }
+void cMarkAdDemux::ProcessTS(MarkAdPid Pid, uchar *Data, int Count, uchar **Pkt, int *PktLen)
+{
+ if ((!Pkt) || (!PktLen) || (!Data)) return;
+ *Pkt=NULL;
+ *PktLen=0;
+
+ uchar *pkt;
+ int pktlen;
+
+ if (!ts2pkt) ts2pkt=new cMarkAdTS2Pkt(recvnumber);
+ if (!ts2pkt) return;
+
+ ts2pkt->Process(Pid,Data,Count,&pkt,&pktlen);
+
+ if ((Pid.Type==MARKAD_PIDTYPE_AUDIO_AC3) || (Pid.Type==MARKAD_PIDTYPE_AUDIO_MP2))
+ {
+ if (!pes2audioes) pes2audioes=new cMarkAdPES2ES(recvnumber,"PES2ES audio");
+ if (!pes2audioes) return;
+ pes2audioes->Process(Pid,pkt,pktlen,Pkt,PktLen);
+ return;
+ }
+
+ if (pkt)
+ {
+ *Pkt=pkt;
+ *PktLen=pktlen;
}
- return len;
+ return;
}
+int cMarkAdDemux::Process(MarkAdPid Pid, uchar *Data, int Count, uchar **Pkt, int *PktLen)
+{
+ if ((!Data) && (!Count) && (!Pkt) || (!PktLen)) return -1;
+
+ *Pkt=NULL;
+ *PktLen=0;
+
+ int retval;
+ int min_needed=TS_SIZE;
+
+ int needed=min_needed-queue->Length();
+ if (Count>needed)
+ {
+ queue->Put(Data,needed);
+ retval=needed;
+ }
+ else
+ {
+ queue->Put(Data,Count);
+ retval=Count;
+ }
+ if (queue->Length()<min_needed) return Count;
+
+ uchar *in;
+ int inlen=TS_SIZE;
+ in=queue->Get(&inlen);
+
+ if (Pid.Num>=0)
+ {
+ ProcessTS(Pid, in, inlen, Pkt, PktLen);
+ }
+ else
+ {
+ ProcessVDR(Pid, in, inlen, Pkt, PktLen);
+ }
+ return retval;
+}
diff --git a/demux.h b/demux.h
index d0b8265..ed11e6c 100644
--- a/demux.h
+++ b/demux.h
@@ -13,23 +13,28 @@
#define TS_SIZE 188
#endif
+#ifndef VDR_SIZE
+#define VDR_SIZE 2048
+#endif
+
#include "global.h"
+#include "tools.h"
+#include "vdr2pkt.h"
#include "ts2pkt.h"
-#include "pes2audioes.h"
+#include "pes2es.h"
class cMarkAdDemux
{
private:
+ int recvnumber;
+ cMarkAdVDR2Pkt *vdr2pkt;
cMarkAdTS2Pkt *ts2pkt;
- cMarkAdPES2AudioES *pes2audioes;
- uchar *pkt;
- uchar *pesptr; // pointer into pkt
-
- uchar *tsdata;
- int tssize;
- uchar *tsptr;
+ cMarkAdPES2ES *pes2audioes;
+ cMarkAdPES2ES *pes2videoes;
+ cMarkAdPaketQueue *queue;
- int pktlen;
+ void ProcessTS(MarkAdPid Pid, uchar *Data, int Count, uchar **Pkt, int *PktLen);
+ void ProcessVDR(MarkAdPid Pid, uchar *Data, int Count, uchar **Pkt, int *PktLen);
public:
cMarkAdDemux(int RecvNumber);
~cMarkAdDemux();
diff --git a/global.h b/global.h
index 79a612c..ff55afe 100644
--- a/global.h
+++ b/global.h
@@ -54,7 +54,6 @@ typedef struct MarkAdContext
time_t StartTime;
time_t EndTime;
bool ManualRecording;
- bool H264;
MarkAdPid VPid;
MarkAdPid APid;
MarkAdPid DPid;
diff --git a/markad-standalone.cpp b/markad-standalone.cpp
index e6d1b20..2a8001e 100644
--- a/markad-standalone.cpp
+++ b/markad-standalone.cpp
@@ -35,43 +35,26 @@ bool cMarkAdStandalone::ProcessFile(const char *Directory, int Number)
if (!Directory) return false;
if (!Number) return false;
- uchar *data;
- int datalen;
- int dataread;
+ int datalen=385024;
+ uchar data[datalen];
char *fbuf;
if (isTS)
{
- datalen=70688; // multiple of 188
- data=(uchar *) malloc(datalen);
- if (!data) return false;
- if (asprintf(&fbuf,"%s/%05i.ts",Directory,Number)==-1)
- {
- free(data);
- return false;
- }
+ if (asprintf(&fbuf,"%s/%05i.ts",Directory,Number)==-1) return false;
}
else
{
- datalen=69632; // VDR paket size
- data=(uchar *) malloc(datalen);
- if (!data) return false;
- if (asprintf(&fbuf,"%s/%03i.vdr",Directory,Number)==-1)
- {
- free(data);
- return false;
- }
+ if (asprintf(&fbuf,"%s/%03i.vdr",Directory,Number)==-1) return false;
}
int f=open(fbuf,O_RDONLY);
free(fbuf);
- if (f==-1)
- {
- free(data);
- return false;
- }
+ if (f==-1) return false;
+
+ int dataread,lastiframe=0;
+ dsyslog("markad [%i]: processing file %05i",recvnumber,Number);
- int lastiframe=0;
while ((dataread=read(f,data,datalen))>0)
{
@@ -183,7 +166,6 @@ bool cMarkAdStandalone::ProcessFile(const char *Directory, int Number)
}
}
}
- free(data);
close(f);
return true;
}
@@ -222,13 +204,13 @@ bool cMarkAdStandalone::CheckTS(const char *Directory)
return false;
}
free(buf);
- // VDR detected
+ // .VDR detected
isTS=false;
MaxFiles=999;
return true;
}
free(buf);
- // TS detected
+ // .TS detected
isTS=true;
MaxFiles=65535;
return true;
@@ -332,7 +314,6 @@ void cMarkAdStandalone::CheckPATPMT(const char *Directory)
case 0x1b:
macontext.General.VPid.Type=MARKAD_PIDTYPE_VIDEO_H264;
- macontext.General.H264=true;
// just use the first pid
if (!macontext.General.VPid.Num) macontext.General.VPid.Num=pid;
break;
@@ -372,14 +353,15 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory)
}
else
{
- // TODO: get infos from VDR PES
+ //macontext.General.APid.Num=-1;
+ macontext.General.DPid.Num=-1;
+ macontext.General.VPid.Num=-1;
macontext.General.VPid.Type=MARKAD_PIDTYPE_VIDEO_H262;
- macontext.General.H264=false;
}
if (macontext.General.VPid.Num)
{
- dsyslog("markad [%i]: using %s-video (0x%04x)",recvnumber,macontext.General.H264 ? "H264": "H262",
+ dsyslog("markad [%i]: using %s-video (0x%04x)",recvnumber,macontext.General.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264 ? "H264": "H262",
macontext.General.VPid.Num);
video_demux = new cMarkAdDemux(recvnumber);
}
@@ -747,9 +729,6 @@ int main(int argc, char *argv[])
signal(SIGUSR1, signal_handler);
*/
- // do cleanup at exit...
-// atexit(cleanUp);
-
// now do the work...
struct stat statbuf;
if (stat(recDir,&statbuf)==-1)
diff --git a/pes2audioes.cpp b/pes2audioes.cpp
deleted file mode 100644
index e8cdde4..0000000
--- a/pes2audioes.cpp
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * pes2audioes.cpp: A plugin for the Video Disk Recorder
- *
- * See the README file for copyright information and how to reach the author.
- *
- * $Id$
- */
-
-#include "pes2audioes.h"
-
-#include <stdio.h>
-
-cMarkAdPES2AudioES::cMarkAdPES2AudioES()
-{
- esdata=NULL;
- esdatalast=NULL;
- essize=0;
- data_left=false;
-}
-
-cMarkAdPES2AudioES::~cMarkAdPES2AudioES()
-{
- if (esdata) free(esdata);
- if (esdatalast) free(esdatalast);
-}
-
-void cMarkAdPES2AudioES::Reset()
-{
- if (esdata) free(esdata);
- esdata=NULL;
- essize=0;
- data_left=false;
-}
-
-int cMarkAdPES2AudioES::FindAudioHeader(uchar *ESData, int ESSize)
-{
- unsigned short scanner=0x0;
- int i;
- for (i=0; i<ESSize; i++)
- {
- scanner|=ESData[i];
- if ((scanner==0x0B77) || ((scanner & 0xFFE0)==0xFFE0))
- {
- break;
- }
- scanner<<=8;
-
- }
- if (i!=ESSize)
- {
- return i-1;
- }
- return -1;
-}
-
-
-bool cMarkAdPES2AudioES::IsValidAudioHeader(uchar *Data,int *FrameSize)
-{
- struct MP2HDR *mp2hdr = (struct MP2HDR *) Data;
- struct AC3HDR *ac3hdr = (struct AC3HDR *) Data;
-
- if ((ac3hdr->Sync1==0x0b) && (ac3hdr->Sync2==0x77))
- {
- if (ac3hdr->SampleRateIndex==3) return false; // reserved
- if (ac3hdr->FrameSizeIndex>=38) return false; // reserved
-
- if (FrameSize)
- {
- int bitRatesAC3[3][38] = // all values are specified as kbits/s
- {
- { 64, 64, 80, 80, 96, 96, 112, 112, 128, 128, 160, 160, 192, 192,
- 224, 224, 256, 256, 320, 320, 384, 384, 448, 448, 512, 512,
- 640, 640, 768, 768, 896, 896, 1024, 1024, 1152, 1152, 1280, 1280 }, // 48kHz
-
- { 69, 70, 87, 88, 104, 105, 121, 122, 139, 140, 174, 175, 208, 209,
- 243, 244, 278, 279, 348, 349, 417, 418, 487, 488, 557, 558,
- 696, 697, 835, 836, 975, 976, 1114, 1115, 1253, 1254, 1393, 1394 }, // 44.1kHz
-
- { 96, 96, 120, 120, 144, 144, 168, 168, 192, 192, 240, 240, 288,
- 288, 336, 336, 384, 384, 480, 480, 576, 576, 672, 672, 768,
- 768, 960, 960, 1152, 1152, 1344, 1344, 1536, 1536, 1728, 1728, 1920,1920 } // 32kHz
- };
-
- *FrameSize=2*bitRatesAC3[ac3hdr->SampleRateIndex][ac3hdr->FrameSizeIndex];
- }
-
- }
- else if ((mp2hdr->Sync1==0xFF) && (mp2hdr->Sync2==7))
- {
- if (mp2hdr->MpegID==1) return false; // reserved
- if (mp2hdr->Layer==0) return false; // reserved
- if (mp2hdr->BitRateIndex==0xF) return false; // forbidden
- if (mp2hdr->SampleRateIndex==3) return false; //reserved
- if (mp2hdr->Emphasis==2) return false; // reserved
-
- if (FrameSize)
- {
- int bitRates[3][3][16] = // all values are specified as kbits/s
- {
- {
- { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -1 }, // M1, L1
- { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, -1 }, // M1, L2
- { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1 } // M1, L3
- },
- {
- { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, -1 }, // M2, L1
- { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 }, // M2, L2
- { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 } // M2, L3
- },
- {
- { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, -1 }, // M2.5, L1
- { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 }, // M2.5, L2
- { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 } // M2.5, L3
- }
- };
-
- int samplingFrequencies[3][4] = // all values are specified in Hz
- {
- { 44100, 48000, 32000, -1 }, // MPEG 1
- { 22050, 24000, 16000, -1 }, // MPEG 2
- { 32000, 16000, 8000, -1 } // MPEG 2.5
- };
-
-
- int slots_per_frame[3][3] =
- {
- { 12, 144, 144 }, // MPEG 1, Layer I, II, III
- { 12, 144, 72 }, // MPEG 2, Layer I, II, III
- { 12, 144, 72 } // MPEG 2.5, Layer I, II, III
- };
-
- int mpegIndex;
- switch (mp2hdr->MpegID)
- {
- case 0:
- mpegIndex=2;
- break;
- case 2:
- mpegIndex=1;
- break;
- case 3:
- mpegIndex=0;
- break;
- default:
- mpegIndex=0; // just to get rid of compiler warnings ;)
- }
- int layerIndex = 3 - mp2hdr->Layer;
-
- // Layer I (i. e., layerIndex == 0) has a larger slot size
- int slotSize = (layerIndex == 0) ? 4 : 1; // bytes
- int sf = samplingFrequencies[mpegIndex][mp2hdr->SampleRateIndex];
-
- if (mp2hdr->BitRateIndex == 0)
- *FrameSize = 0; // "free" Bitrate -> we don't support this!
- else
- {
- int br = 1000 * bitRates[mpegIndex][layerIndex][mp2hdr->BitRateIndex]; // bits/s
- int N = slots_per_frame[mpegIndex][layerIndex] * br / sf; // slots
-
- *FrameSize = (N + mp2hdr->Padding) * slotSize; // bytes
- }
- }
- }
- else
- {
- return false;
- }
- return true;
-}
-
-int cMarkAdPES2AudioES::Process(uchar *PESData, int PESSize, uchar **ESData, int *ESSize)
-{
- if ((!ESData) || (!ESSize)) return -1;
- *ESData=NULL;
- *ESSize=0;
-
- int bytes_processed;
-
- if (!data_left)
- {
- struct PESHDR *peshdr=(struct PESHDR *) PESData;
-
- // first check some simple things
- if ((peshdr->Sync1!=0) && (peshdr->Sync2!=0) && (peshdr->Sync3!=1))
- {
- Reset();
- return PESSize;
- }
-
- if ((peshdr->StreamID<0xC0) && (peshdr->StreamID>0xDF))
- {
- if (peshdr->StreamID!=0xBD) return PESSize; // no audio
- }
-
- int Length=(peshdr->LenH<<8)+peshdr->LenL;
- if (Length>PESSize)
- {
- Reset();
- return PESSize;
- }
-
- struct PESHDROPT *peshdropt=(struct PESHDROPT *) &PESData[sizeof(struct PESHDR)];
-
- uchar *buf;
- int buflen;
-
- if (peshdropt->MarkerBits==0x2)
- {
- // we have an optional PES header
- int bpos=sizeof(struct PESHDR)+sizeof(struct PESHDROPT)+
- peshdropt->Length;
- buf=&PESData[bpos];
- buflen=PESSize-bpos;
- bytes_processed=bpos;
- }
- else
- {
- int bpos=sizeof(struct PESHDR);
- buf=&PESData[bpos];
- buflen=PESSize-bpos;
- bytes_processed=bpos;
- }
- esdata=(uchar *) realloc(esdata,essize+buflen);
- if (!esdata)
- {
- return -1;
- essize=0;
- }
- memcpy(esdata+essize,buf,buflen);
- essize+=buflen;
- bytes_processed+=buflen;
- }
- else
- {
- bytes_processed=essize;
- data_left=false;
- }
-
- int audiohdr=FindAudioHeader(esdata,essize);
- if (audiohdr!=-1)
- {
- int framesize;
- if (IsValidAudioHeader(&esdata[audiohdr],&framesize))
- {
- if ((essize-audiohdr)>=framesize)
- {
- *ESData=&esdata[audiohdr];
- *ESSize=framesize;
- if (esdatalast) free(esdatalast);
- esdatalast=esdata;
-
- int size=(essize-framesize-audiohdr);
-
- esdata=NULL;
- essize=0;
-
- if (size>0)
- {
- void *ptr=malloc(size);
- if (!ptr) return -1;
-
- memcpy(ptr,(*ESData)+framesize,size);
- bytes_processed-=size;
-
- esdata=(uchar *) ptr;
- essize=size;
- data_left=true;
- }
- }
- }
- }
- return bytes_processed;
-}
diff --git a/pes2es.cpp b/pes2es.cpp
new file mode 100644
index 0000000..8d09e45
--- /dev/null
+++ b/pes2es.cpp
@@ -0,0 +1,95 @@
+/*
+ * pes2es.cpp: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id$
+ */
+
+#include "pes2es.h"
+
+cMarkAdPES2ES::cMarkAdPES2ES(int RecvNumber, const char *QueueName, int QueueSize)
+{
+ queue = new cMarkAdPaketQueue(RecvNumber,QueueName,QueueSize);
+ type=0;
+}
+
+cMarkAdPES2ES::~cMarkAdPES2ES()
+{
+ if (queue) delete queue;
+}
+
+void cMarkAdPES2ES::Reset()
+{
+ queue->Clear();
+}
+
+void cMarkAdPES2ES::Process(MarkAdPid Pid, uchar *PESData, int PESSize, uchar **ESData, int *ESSize)
+{
+ if ((!ESData) || (!ESSize) || (!queue)) return;
+ *ESData=NULL;
+ *ESSize=0;
+
+ if (PESData)
+ {
+ struct PESHDR *peshdr=(struct PESHDR *) PESData;
+
+ // first check some simple things
+ if ((peshdr->Sync1!=0) && (peshdr->Sync2!=0) && (peshdr->Sync3!=1))
+ {
+ Reset();
+ return;
+ }
+
+ int Length=(peshdr->LenH<<8)+peshdr->LenL+sizeof(PESHDR);
+ if (Length!=PESSize)
+ {
+ Reset();
+ return;
+ }
+
+ switch (Pid.Type)
+ {
+ case MARKAD_PIDTYPE_VIDEO_H262:
+ case MARKAD_PIDTYPE_VIDEO_H264:
+ if ((peshdr->StreamID & 0xF0)!=0xE0) return;
+ type=MA_PACKET_PKT;
+ break;
+ case MARKAD_PIDTYPE_AUDIO_AC3:
+ if (peshdr->StreamID!=0xBD) return;
+ type=MA_PACKET_AC3;
+ break;
+ case MARKAD_PIDTYPE_AUDIO_MP2:
+ if ((peshdr->StreamID<0xC0) || (peshdr->StreamID>0xDF)) return;
+ type=MA_PACKET_MP2;
+ break;
+ default:
+ Reset();
+ return;
+ }
+
+ struct PESHDROPT *peshdropt=(struct PESHDROPT *) &PESData[sizeof(struct PESHDR)];
+
+ uchar *buf;
+ int buflen;
+
+ if (peshdropt->MarkerBits==0x2)
+ {
+ // we have an optional PES header
+ int bpos=sizeof(struct PESHDR)+sizeof(struct PESHDROPT)+
+ peshdropt->Length;
+ buf=&PESData[bpos];
+ buflen=PESSize-bpos;
+ }
+ else
+ {
+ int bpos=sizeof(struct PESHDR);
+ buf=&PESData[bpos];
+ buflen=PESSize-bpos;
+ }
+
+ queue->Put(buf,buflen);
+ }
+ if (type) *ESData=queue->GetPacket(ESSize,type);
+ return;
+}
diff --git a/pes2es.h b/pes2es.h
new file mode 100644
index 0000000..5b74e43
--- /dev/null
+++ b/pes2es.h
@@ -0,0 +1,79 @@
+/*
+ * pes2es.h: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id$
+ */
+
+#ifndef __pes2es_h_
+#define __pes2es_h_
+
+#ifndef uchar
+typedef unsigned char uchar;
+#endif
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "global.h"
+#include "tools.h"
+
+class cMarkAdPES2ES
+{
+private:
+ struct PESHDR
+ {
+ uchar Sync1;
+ uchar Sync2;
+ uchar Sync3;
+ uchar StreamID;
+ uchar LenH;
+ uchar LenL;
+ };
+
+#pragma pack(1)
+ struct PESHDROPT
+ {
+unsigned OOC:
+ 1;
+unsigned CY:
+ 1;
+unsigned DAI:
+ 1;
+unsigned PESP:
+ 1;
+unsigned PESSC:
+ 2;
+unsigned MarkerBits:
+ 2;
+unsigned EXT:
+ 1;
+unsigned CRC:
+ 1;
+unsigned ACI:
+ 1;
+unsigned TM:
+ 1;
+unsigned RATE:
+ 1;
+unsigned ESCR:
+ 1;
+unsigned TSF:
+ 2;
+unsigned Length:
+ 8;
+ };
+#pragma pack()
+
+ cMarkAdPaketQueue *queue;
+ int type;
+ void Reset();
+public:
+ cMarkAdPES2ES(int RecvNumber, const char *QueueName="PES2ES", int QueueSize=32768);
+ ~cMarkAdPES2ES();
+ void Process(MarkAdPid Pid, uchar *PESData, int PESSize, uchar **ESData, int *ESSize);
+};
+
+#endif
diff --git a/recv.cpp b/recv.cpp
index 7be6d62..48dbd35 100644
--- a/recv.cpp
+++ b/recv.cpp
@@ -60,8 +60,6 @@ cMarkAdReceiver::cMarkAdReceiver(int RecvNumber, const char *Filename, cTimer *T
macontext.General.DPid.Num=Timer->Channel()->Dpid(0); // TODO ... better solution?
macontext.General.DPid.Type=MARKAD_PIDTYPE_AUDIO_AC3;
- macontext.General.H264=useH264;
-
if (macontext.General.VPid.Num)
{
dsyslog("markad [%i]: using %s-video",recvnumber,useH264 ? "H264": "H262");
@@ -122,21 +120,6 @@ cMarkAdReceiver::~cMarkAdReceiver()
}
buffer.Clear();
- if ((!macontext.State.ContentStopped) && (lastiframe))
- {
- MarkAdMark tempmark;
- tempmark.Position=lastiframe;
-
- char *buf;
- if (asprintf(&buf,"stop of user content (%i)",lastiframe)!=-1)
- {
- tempmark.Comment=buf;
- AddMark(&tempmark,0);
- isyslog("markad [%i]: %s",recvnumber,buf);
- free(buf);
- }
- }
-
if (video_demux) delete video_demux;
if (mp2_demux) delete mp2_demux;
if (ac3_demux) delete ac3_demux;
@@ -170,6 +153,7 @@ int cMarkAdReceiver::LastIFrame()
{
if (!Index)
{
+ if (!filename) return 0;
Index = new cIndexFile(filename,false);
if (!Index)
{
@@ -207,7 +191,21 @@ void cMarkAdReceiver::Activate(bool On)
}
else if (running)
{
- marks.Save();
+ if ((!macontext.State.ContentStopped) && (lastiframe))
+ {
+ MarkAdMark tempmark;
+ tempmark.Position=lastiframe;
+
+ char *buf;
+ if (asprintf(&buf,"stop of user content (%i)",lastiframe)!=-1)
+ {
+ tempmark.Comment=buf;
+ AddMark(&tempmark,0);
+ isyslog("markad [%i]: %s",recvnumber,buf);
+ free(buf);
+ }
+ }
+
if (Index) delete Index;
running = false;
buffer.Signal();
@@ -254,7 +252,7 @@ void cMarkAdReceiver::AddMark(MarkAdMark *mark, int Priority)
}
marks.Save();
-#define MAXPOSDIFF 10500 // = 7 min
+#define MAXPOSDIFF (25*60*9) // = 9 min
cMark *prevmark=marks.GetPrev(mark->Position);
if (!prevmark) return;
diff --git a/tools.cpp b/tools.cpp
new file mode 100644
index 0000000..04d7e2c
--- /dev/null
+++ b/tools.cpp
@@ -0,0 +1,333 @@
+/*
+ * tools.cpp: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id$
+ */
+
+#include "tools.h"
+
+cMarkAdPaketQueue::cMarkAdPaketQueue(int RecvNumber, const char *Name, int Size)
+{
+ recvnumber=RecvNumber;
+ inptr=0;
+ outptr=0;
+ pktinfo.pkthdr=-1;
+ maxqueue=Size;
+ name=strdup(Name);
+ buffer=(uchar *) malloc(Size+1);
+ if (!buffer) maxqueue=0;
+}
+
+cMarkAdPaketQueue::~cMarkAdPaketQueue()
+{
+ if (name) free(name);
+ if (buffer) free(buffer);
+}
+
+bool cMarkAdPaketQueue::Put(uchar *Data, int Size)
+{
+ if (!buffer) return false;
+ if ((inptr) && (inptr==outptr)) inptr=outptr=0;
+
+ if (((inptr+Size)>maxqueue) && (name))
+ {
+ esyslog("markad [%i]: buffer %s full",recvnumber,name);
+ inptr=outptr=0;
+ }
+
+ memcpy(&buffer[inptr],Data,Size);
+ inptr+=Size;
+
+ if ((inptr>(0.9*maxqueue)) && (name))
+ {
+ dsyslog("markad [%i]: buffer %s usage: %3.f%%",recvnumber,
+ name,((double) inptr/(double) maxqueue)*100);
+ }
+
+ return true;
+}
+
+uchar *cMarkAdPaketQueue::Get(int *Size)
+{
+ if (!buffer) return NULL;
+ if (!Size) return NULL;
+ if (Length()<*Size)
+ {
+ *Size=0;
+ return NULL;
+ }
+ uchar *ret=&buffer[outptr];
+ outptr+=*Size;
+ return ret;
+}
+
+int cMarkAdPaketQueue::FindPktHeader(int Start, int *StreamSize,int *HeaderSize)
+{
+ if ((!StreamSize) || (!HeaderSize)) return -1;
+ if (!Start) Start=outptr;
+ if (Start>inptr) return -1;
+ *StreamSize=0;
+ *HeaderSize=4; // 0x0 0x0 0x1 0xNN
+ unsigned long scanner=0xFFFFFFFF;
+ int i;
+
+ for (i=Start; i<inptr; i++)
+ {
+ scanner<<=8;
+ if (scanner==0x00000100L)
+ {
+ break;
+ }
+ scanner|=buffer[i];
+ }
+
+ if (i==inptr) return -1;
+
+ if (buffer[i]>=0xBC)// do we have a PES packet?
+ {
+#define PESHDRSIZE 6
+ if ((i+PESHDRSIZE)>inptr)
+ {
+ return -1; // we need more data (for streamsize and headersize)
+ }
+
+ *StreamSize=(buffer[i+1]<<8)+buffer[i+2];
+ if (*StreamSize) (*StreamSize)+=PESHDRSIZE; // 6 Byte PES-Header
+
+ struct PESHDROPT *peshdropt=(struct PESHDROPT *) &buffer[i+3];
+ if (peshdropt->MarkerBits==0x2)
+ {
+ *HeaderSize=PESHDRSIZE+sizeof(struct PESHDROPT)+
+ peshdropt->Length;
+ }
+ else
+ {
+ *HeaderSize=PESHDRSIZE;
+ }
+ }
+ return i-3;
+}
+
+int cMarkAdPaketQueue::FindAudioHeader(int Start, int *FrameSize, int *HeaderSize, bool AC3)
+{
+ if (!Start) Start=outptr;
+ if (Start>inptr) return -1;
+ if (FrameSize) (*FrameSize)=0;
+ if (HeaderSize) (*HeaderSize)=4;
+ unsigned short scanner=0x0;
+ int i;
+ for (i=Start; i<inptr; i++)
+ {
+ scanner|=buffer[i];
+ if (AC3)
+ {
+ if (scanner==0x0B77) break;
+ }
+ else
+ {
+ if ((scanner & 0xFFE0)==0xFFE0) break;
+ }
+ scanner<<=8;
+ }
+ if (i==inptr) return -1;
+ i--;
+
+ if (AC3)
+ {
+ struct AC3HDR *ac3hdr = (struct AC3HDR *) &buffer[i];
+
+ if (ac3hdr->SampleRateIndex==3) return -1; // reserved
+ if (ac3hdr->FrameSizeIndex>=38) return -1; // reserved
+ if (HeaderSize) (*HeaderSize)=sizeof(struct AC3HDR);
+
+ if (FrameSize)
+ {
+ int bitRatesAC3[3][38] = // all values are specified as kbits/s
+ {
+ { 64, 64, 80, 80, 96, 96, 112, 112, 128, 128, 160, 160, 192, 192,
+ 224, 224, 256, 256, 320, 320, 384, 384, 448, 448, 512, 512,
+ 640, 640, 768, 768, 896, 896, 1024, 1024, 1152, 1152, 1280, 1280 }, // 48kHz
+
+ { 69, 70, 87, 88, 104, 105, 121, 122, 139, 140, 174, 175, 208, 209,
+ 243, 244, 278, 279, 348, 349, 417, 418, 487, 488, 557, 558,
+ 696, 697, 835, 836, 975, 976, 1114, 1115, 1253, 1254, 1393, 1394 }, // 44.1kHz
+
+ { 96, 96, 120, 120, 144, 144, 168, 168, 192, 192, 240, 240, 288,
+ 288, 336, 336, 384, 384, 480, 480, 576, 576, 672, 672, 768,
+ 768, 960, 960, 1152, 1152, 1344, 1344, 1536, 1536, 1728, 1728, 1920,1920 } // 32kHz
+ };
+
+ *FrameSize=2*bitRatesAC3[ac3hdr->SampleRateIndex][ac3hdr->FrameSizeIndex];
+ }
+ return i;
+ }
+ else
+ {
+ struct MP2HDR *mp2hdr = (struct MP2HDR *) &buffer[i];
+ if (mp2hdr->MpegID==1) return -1; // reserved
+ if (mp2hdr->Layer==0) return -1; // reserved
+ if (mp2hdr->BitRateIndex==0xF) return -1; // forbidden
+ if (mp2hdr->SampleRateIndex==3) return -1; //reserved
+ if (mp2hdr->Emphasis==2) return -1; // reserved
+
+ if (HeaderSize) (*HeaderSize)=sizeof(struct MP2HDR);
+
+ if (FrameSize)
+ {
+ int bitRates[3][3][16] = // all values are specified as kbits/s
+ {
+ {
+ { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -1 }, // M1, L1
+ { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, -1 }, // M1, L2
+ { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1 } // M1, L3
+ },
+ {
+ { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, -1 }, // M2, L1
+ { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 }, // M2, L2
+ { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 } // M2, L3
+ },
+ {
+ { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, -1 }, // M2.5, L1
+ { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 }, // M2.5, L2
+ { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 } // M2.5, L3
+ }
+ };
+
+ int samplingFrequencies[3][4] = // all values are specified in Hz
+ {
+ { 44100, 48000, 32000, -1 }, // MPEG 1
+ { 22050, 24000, 16000, -1 }, // MPEG 2
+ { 32000, 16000, 8000, -1 } // MPEG 2.5
+ };
+
+
+ int slots_per_frame[3][3] =
+ {
+ { 12, 144, 144 }, // MPEG 1, Layer I, II, III
+ { 12, 144, 72 }, // MPEG 2, Layer I, II, III
+ { 12, 144, 72 } // MPEG 2.5, Layer I, II, III
+ };
+
+ int mpegIndex;
+ switch (mp2hdr->MpegID)
+ {
+ case 0:
+ mpegIndex=2;
+ break;
+ case 2:
+ mpegIndex=1;
+ break;
+ case 3:
+ mpegIndex=0;
+ break;
+ default:
+ mpegIndex=0; // just to get rid of compiler warnings ;)
+ }
+ int layerIndex = 3 - mp2hdr->Layer;
+
+ // Layer I (i. e., layerIndex == 0) has a larger slot size
+ int slotSize = (layerIndex == 0) ? 4 : 1; // bytes
+ int sf = samplingFrequencies[mpegIndex][mp2hdr->SampleRateIndex];
+
+ if (mp2hdr->BitRateIndex == 0)
+ *FrameSize = 0; // "free" Bitrate -> we don't support this!
+ else
+ {
+ int br = 1000 * bitRates[mpegIndex][layerIndex][mp2hdr->BitRateIndex]; // bits/s
+ int N = slots_per_frame[mpegIndex][layerIndex] * br / sf; // slots
+
+ *FrameSize = (N + mp2hdr->Padding) * slotSize; // bytes
+ }
+ }
+ return i;
+ }
+}
+
+uchar *cMarkAdPaketQueue::GetPacket(int *Size, int Type)
+{
+ if (!Size) return NULL;
+ *Size=0;
+ if (!Length()) return NULL;
+
+ if (pktinfo.pkthdr==-1)
+ {
+
+ switch (Type)
+ {
+ case MA_PACKET_AC3:
+ pktinfo.pkthdr=FindAudioHeader(0,&pktinfo.streamsize,&pktinfo.pkthdrsize, true);
+ break;
+ case MA_PACKET_MP2:
+ pktinfo.pkthdr=FindAudioHeader(0,&pktinfo.streamsize,&pktinfo.pkthdrsize, false);
+ break;
+ default:
+ pktinfo.pkthdr=FindPktHeader(0,&pktinfo.streamsize,&pktinfo.pkthdrsize);
+ }
+
+ if (pktinfo.pkthdr==-1)
+ {
+ return NULL;
+ }
+ }
+
+ int start,streamsize,pkthdrsize,pkthdr=-1;
+
+ if (pktinfo.streamsize)
+ {
+ if ((pktinfo.pkthdr+pktinfo.streamsize)>inptr)
+ {
+ return NULL; // need more data
+ }
+ else
+ {
+ start=pktinfo.pkthdr+pktinfo.streamsize;
+ }
+ }
+ else
+ {
+ start=pktinfo.pkthdr+pktinfo.pkthdrsize;
+ }
+
+ switch (Type)
+ {
+ case MA_PACKET_AC3:
+ pkthdr=FindAudioHeader(start,&streamsize,&pkthdrsize, true);
+ break;
+ case MA_PACKET_MP2:
+ pkthdr=FindAudioHeader(start,&streamsize,&pkthdrsize, false);
+ break;
+ default:
+ pkthdr=FindPktHeader(start,&streamsize,&pkthdrsize);
+ }
+
+ if (pkthdr==-1) return NULL;
+
+ uchar *ptr=&buffer[pktinfo.pkthdr];
+
+ if (pktinfo.streamsize)
+ {
+ *Size=pktinfo.streamsize;
+ }
+ else
+ {
+ *Size=pkthdr-pktinfo.pkthdr;
+ }
+ outptr=pkthdr;
+
+ int bytesleft=inptr-outptr;
+ if (pktinfo.pkthdr>(8192+bytesleft))
+ {
+ memcpy(buffer,&buffer[pkthdr],bytesleft);
+ inptr=bytesleft;
+ outptr=0;
+ pkthdr=0;
+ }
+
+ pktinfo.pkthdr=pkthdr;
+ pktinfo.streamsize=streamsize;
+ pktinfo.pkthdrsize=pkthdrsize;
+
+ return ptr;
+}
diff --git a/pes2audioes.h b/tools.h
index 13ebcc2..4a182cb 100644
--- a/pes2audioes.h
+++ b/tools.h
@@ -1,69 +1,24 @@
/*
- * pes2audioes.h: A plugin for the Video Disk Recorder
+ * tools.h: A plugin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
* $Id$
*/
-#ifndef __pes2audioes_h_
-#define __pes2audioes_h_
+#ifndef __tools_h_
+#define __tools_h_
+
+#include <vdr/tools.h> // needed for (d/e/i)syslog
#ifndef uchar
typedef unsigned char uchar;
#endif
-#include <inttypes.h>
-#include <stdlib.h>
#include <string.h>
-class cMarkAdPES2AudioES
+class cMarkAdPaketQueue
{
-private:
- struct PESHDR
- {
- uchar Sync1;
- uchar Sync2;
- uchar Sync3;
- uchar StreamID;
- uchar LenH;
- uchar LenL;
- };
-
-#pragma pack(1)
- struct PESHDROPT
- {
-unsigned OOC:
- 1;
-unsigned CY:
- 1;
-unsigned DAI:
- 1;
-unsigned PESP:
- 1;
-unsigned PESSC:
- 2;
-unsigned MarkerBits:
- 2;
-unsigned EXT:
- 1;
-unsigned CRC:
- 1;
-unsigned ACI:
- 1;
-unsigned TM:
- 1;
-unsigned RATE:
- 1;
-unsigned ESCR:
- 1;
-unsigned TSF:
- 2;
-unsigned Length:
- 8;
- };
-#pragma pack()
-
struct MP2HDR
{
unsigned Sync1:
@@ -114,19 +69,75 @@ unsigned SampleRateIndex:
};
#pragma pack()
- uchar *esdatalast;
- uchar *esdata;
- int essize;
- bool data_left;
+#pragma pack(1)
+ struct PESHDROPT
+ {
+unsigned OOC:
+ 1;
+unsigned CY:
+ 1;
+unsigned DAI:
+ 1;
+unsigned PESP:
+ 1;
+unsigned PESSC:
+ 2;
+unsigned MarkerBits:
+ 2;
+unsigned EXT:
+ 1;
+unsigned CRC:
+ 1;
+unsigned ACI:
+ 1;
+unsigned TM:
+ 1;
+unsigned RATE:
+ 1;
+unsigned ESCR:
+ 1;
+unsigned TSF:
+ 2;
+unsigned Length:
+ 8;
+ };
+#pragma pack()
+
+private:
+ char *name;
+ int recvnumber;
+ struct pktinfo
+ {
+ int pkthdr;
+ int pkthdrsize;
+ int streamsize;
+ } pktinfo;
- int FindAudioHeader(uchar *PESData, int PESSize);
- bool IsValidAudioHeader(uchar *Data, int *FrameSize);
- void Reset();
+ uchar *buffer;
+ int maxqueue;
+ int inptr;
+ int outptr;
+ int FindPktHeader(int Start, int *StreamSize,int *HeaderSize);
+ int FindAudioHeader(int Start, int *FrameSize, int *HeaderSize, bool AC3);
public:
- cMarkAdPES2AudioES();
- ~cMarkAdPES2AudioES();
- int Process(uchar *PESData, int PESSize, uchar **ESData, int *ESSize);
-};
+ cMarkAdPaketQueue(int RecvNumber, const char *Name, int Size=32768);
+ ~cMarkAdPaketQueue();
+ int Length()
+ {
+ return inptr-outptr;
+ }
+ void Clear()
+ {
+ inptr=outptr=0;
+ }
+ bool Put(uchar *Data, int Size);
+ uchar *Get(int *Size);
+#define MA_PACKET_PKT 1
+#define MA_PACKET_AC3 2
+#define MA_PACKET_MP2 3
+
+ uchar *GetPacket(int *Size, int Type);
+};
#endif
diff --git a/ts2pkt.cpp b/ts2pkt.cpp
index 049d8e4..ad26ebe 100644
--- a/ts2pkt.cpp
+++ b/ts2pkt.cpp
@@ -8,18 +8,16 @@
#include "ts2pkt.h"
-cMarkAdTS2Pkt::cMarkAdTS2Pkt(int RecvNumber)
+cMarkAdTS2Pkt::cMarkAdTS2Pkt(int RecvNumber, const char *QueueName, int QueueSize)
{
recvnumber=RecvNumber;
- pktdata=NULL;
- pktdatalast=NULL;
+ queue=new cMarkAdPaketQueue(RecvNumber,QueueName,QueueSize);
Reset();
}
cMarkAdTS2Pkt::~cMarkAdTS2Pkt()
{
- if (pktdata) free(pktdata);
- if (pktdatalast) free(pktdatalast);
+ if (queue) delete queue;
}
void cMarkAdTS2Pkt::Reset(int ErrIndex)
@@ -44,303 +42,104 @@ void cMarkAdTS2Pkt::Reset(int ErrIndex)
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;
+ if (queue) queue->Clear();
}
-int cMarkAdTS2Pkt::FindPktHeader(uchar *Data, int Size, int *StreamSize,
- int *HeaderSize)
+void cMarkAdTS2Pkt::Process(MarkAdPid Pid, uchar *TSData, int TSSize, uchar **PktData, int *PktSize)
{
-#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;
+ if ((!PktData) || (!PktSize) || (!queue)) return;
*PktData=NULL;
*PktSize=0;
- int buflen=TS_SIZE+1;
- uchar *buf=NULL;
-
- int bytes_processed; // pointer in TSData
-
- if (!dataleft)
+ if (TSData)
{
- if (TSSize<TS_SIZE)
+ if (TSSize!=TS_SIZE)
{
Reset(MA_ERR_TOSMALL);
- return TSSize; // we need a full packet
+ return; // we need a full packet
}
- if ((TSData[0]==0) && (TSData[1]==0) && (TSData[2]==1))
+ // check TS packet sync
+ if (TSData[0]!=0x47)
{
- isPES=true;
+ Reset(MA_ERR_NOSYNC);
+ return;
}
- if (isPES)
+ struct TSHDR *tshdr = (struct TSHDR *) TSData;
+
+ int pid = (tshdr->PidH << 8) | tshdr->PidL;
+ if (Pid.Num!=pid)
{
- buf=TSData;
- buflen=TSSize;
+ return; // not for us
}
- 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))
- {
- if (counter==tshdr->Counter)
- {
- // duplicate paket -> just ignore
- return TS_SIZE;
- }
- // sequence error
- Reset(MA_ERR_SEQ);
- return TS_SIZE;
- }
- counter=tshdr->Counter;
-
- if ((tshdr->AFC<=0) || (tshdr->AFC>3))
+ if ((counter!=-1) && (((counter+1) & 0xF)!=tshdr->Counter))
+ {
+ if (counter==tshdr->Counter)
{
- Reset(MA_ERR_AFC);
- return TS_SIZE;
+ // duplicate paket -> just ignore
+ return;
}
+ // sequence error
+ Reset(MA_ERR_SEQ);
+ return;
+ }
+ counter=tshdr->Counter;
- // 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<=0) || (tshdr->AFC>3))
+ {
+ Reset(MA_ERR_AFC);
+ return;
+ }
- if (tshdr->AFC==1)
- {
- // payload only
- buflen=TS_SIZE-sizeof(struct TSHDR);
- buf=&TSData[sizeof(struct TSHDR)];
- }
+ // we just ignore the infos in the adaption field (e.g. OPCR/PCR)
+ if ((tshdr->AFC!=1) && (tshdr->AFC!=3))
+ {
+ return;
+ }
- 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];
- }
+ int buflen=TS_SIZE+1;
+ uchar *buf=NULL;
- 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;
- }
- if (buflen==0)
- {
- // no data?
- return TS_SIZE;
- }
- }
- pktdata=(uchar *) realloc(pktdata,pktsize+buflen);
- if (!pktdata)
+ if (tshdr->AFC==1)
{
- Reset(MA_ERR_MEM);
- return -1;
+ // payload only
+ buflen=TS_SIZE-sizeof(struct TSHDR);
+ buf=&TSData[sizeof(struct TSHDR)];
}
- memcpy(pktdata+pktsize,buf,buflen);
- pktsize+=buflen;
- if (isPES)
+
+ if (tshdr->AFC==3)
{
- bytes_processed=buflen;
+ // 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];
}
- else
+
+ if (buflen>TS_SIZE)
{
- bytes_processed=TS_SIZE;
+ // size to large
+ Reset(MA_ERR_TOBIG);
+ return;
}
- }
- else
- {
- bytes_processed=pktsize;
- dataleft=false;
- }
-
- if (pktinfo.pkthdr==-1)
- {
- pktinfo.pkthdr=FindPktHeader(pktdata, pktsize, &pktinfo.streamsize, &pktinfo.pkthdrsize);
- if (pktinfo.pkthdr==-1)
+ if (buflen<0)
{
- return bytes_processed; // not found any header -> next paket
+ // error in size
+ Reset(MA_ERR_NEG);
+ return;
}
- }
-
- 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))
+ if (buflen==0)
{
- (*PktData)=NULL;
- (*PktSize)=0;
+ // no data?
+ return;
}
- }
- if (pktdatalast) free(pktdatalast);
- pktdatalast=pktdata;
-
- int bufleftsize=pktsize-(pktinfo.pkthdr+size);
- if (bufleftsize<0)
- {
- pktdata=NULL;
- Reset(MA_ERR_NEG);
- return bytes_processed;
- }
- if (bufleftsize==0)
- {
- pktinfo.pkthdr=-1;
- pktdata=NULL;
- pktsize=0;
- return bytes_processed;
+ queue->Put(buf,buflen);
}
-
- 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;
+ *PktData=queue->GetPacket(PktSize,MA_PACKET_PKT);
+ return;
}
diff --git a/ts2pkt.h b/ts2pkt.h
index 927e03b..cd8d19d 100644
--- a/ts2pkt.h
+++ b/ts2pkt.h
@@ -23,6 +23,7 @@ typedef unsigned char uchar;
#include <string.h>
#include "global.h"
+#include "tools.h"
class cMarkAdTS2Pkt
{
@@ -57,56 +58,11 @@ unsigned Flags:
8;
};
-#pragma pack(1)
- struct PESHDROPT
- {
-unsigned OOC:
- 1;
-unsigned CY:
- 1;
-unsigned DAI:
- 1;
-unsigned PESP:
- 1;
-unsigned PESSC:
- 2;
-unsigned MarkerBits:
- 2;
-unsigned EXT:
- 1;
-unsigned CRC:
- 1;
-unsigned ACI:
- 1;
-unsigned TM:
- 1;
-unsigned RATE:
- 1;
-unsigned ESCR:
- 1;
-unsigned TSF:
- 2;
-unsigned Length:
- 8;
- };
-#pragma pack()
-
- struct pktinfo
- {
- int pkthdr;
- int pkthdrsize;
- int streamsize;
- } pktinfo;
-
int recvnumber;
-
- bool isPES;
- uchar *pktdatalast;
- uchar *pktdata;
- int pktsize;
- bool dataleft;
int counter;
+ cMarkAdPaketQueue *queue;
+
#define MA_ERR_STARTUP 0
#define MA_ERR_TOSMALL 1
#define MA_ERR_NOSYNC 2
@@ -114,14 +70,11 @@ unsigned Length:
#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:
- cMarkAdTS2Pkt(int RecvNumber);
+ cMarkAdTS2Pkt(int RecvNumber, const char *QueueName="TS2Pkt", int QueueSize=262144);
~cMarkAdTS2Pkt();
- int Process(MarkAdPid Pid,uchar *TSData, int TSSize, uchar **PktData, int *PktSize);
+ void Process(MarkAdPid Pid,uchar *TSData, int TSSize, uchar **PktData, int *PktSize);
};
#endif
diff --git a/vdr2pkt.cpp b/vdr2pkt.cpp
new file mode 100644
index 0000000..1a42fd7
--- /dev/null
+++ b/vdr2pkt.cpp
@@ -0,0 +1,30 @@
+/*
+ * vdr2pkt.cpp: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id$
+ */
+
+#include "vdr2pkt.h"
+
+cMarkAdVDR2Pkt::cMarkAdVDR2Pkt(int RecvNumber, const char *QueueName, int QueueSize)
+{
+ queue = new cMarkAdPaketQueue(RecvNumber,QueueName,QueueSize);
+}
+
+cMarkAdVDR2Pkt::~cMarkAdVDR2Pkt()
+{
+if (queue) delete queue;
+}
+
+void cMarkAdVDR2Pkt::Process(MarkAdPid Pid, uchar *VDRData, int VDRSize, uchar **PktData, int *PktSize)
+{
+ if ((!PktData) || (!PktSize) || (!queue)) return;
+ *PktData=NULL;
+ *PktSize=0;
+
+ if (VDRData) queue->Put(VDRData,VDRSize);
+ *PktData=queue->GetPacket(PktSize,MA_PACKET_PKT);
+ return;
+}
diff --git a/vdr2pkt.h b/vdr2pkt.h
new file mode 100644
index 0000000..1820fbf
--- /dev/null
+++ b/vdr2pkt.h
@@ -0,0 +1,29 @@
+/*
+ * vdr2pkt.h: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id$
+ */
+
+#ifndef __vdr2pkt_h_
+#define __vdr2pkt_h_
+
+#ifndef uchar
+typedef unsigned char uchar;
+#endif
+
+#include "global.h"
+#include "tools.h"
+
+class cMarkAdVDR2Pkt
+{
+private:
+ cMarkAdPaketQueue *queue;
+public:
+ cMarkAdVDR2Pkt(int RecvNumber, const char *QueueName="VDR2PKT", int QueueSize=32768);
+ ~cMarkAdVDR2Pkt();
+ void Process(MarkAdPid Pid,uchar *VDRData, int VDRSize, uchar **PktData, int *PktSize);
+};
+
+#endif