diff options
author | Jochen Dolze <vdr@dolze.de> | 2009-10-02 17:36:58 +0200 |
---|---|---|
committer | Jochen Dolze <vdr@dolze.de> | 2009-10-02 17:36:58 +0200 |
commit | 52cd041405849817c72d272bee0e6798f57b66c4 (patch) | |
tree | 994709d9e41ae0a367ba4b0bf5254911a4f38558 | |
parent | a21c3bf58621446068b054326eec83dae1e744a0 (diff) | |
download | vdr-plugin-markad-52cd041405849817c72d272bee0e6798f57b66c4.tar.gz vdr-plugin-markad-52cd041405849817c72d272bee0e6798f57b66c4.tar.bz2 |
Rewrote packet handling code, now it uses queues
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | decoder.cpp | 3 | ||||
-rw-r--r-- | demux.cpp | 187 | ||||
-rw-r--r-- | demux.h | 23 | ||||
-rw-r--r-- | global.h | 1 | ||||
-rw-r--r-- | markad-standalone.cpp | 49 | ||||
-rw-r--r-- | pes2audioes.cpp | 273 | ||||
-rw-r--r-- | pes2es.cpp | 95 | ||||
-rw-r--r-- | pes2es.h | 79 | ||||
-rw-r--r-- | recv.cpp | 36 | ||||
-rw-r--r-- | tools.cpp | 333 | ||||
-rw-r--r-- | tools.h (renamed from pes2audioes.h) | 135 | ||||
-rw-r--r-- | ts2pkt.cpp | 333 | ||||
-rw-r--r-- | ts2pkt.h | 57 | ||||
-rw-r--r-- | vdr2pkt.cpp | 30 | ||||
-rw-r--r-- | vdr2pkt.h | 29 |
16 files changed, 854 insertions, 813 deletions
@@ -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); } @@ -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; +} @@ -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(); @@ -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 @@ -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; +} @@ -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 @@ -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; } @@ -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 |