From 52cd041405849817c72d272bee0e6798f57b66c4 Mon Sep 17 00:00:00 2001 From: Jochen Dolze Date: Fri, 2 Oct 2009 17:36:58 +0200 Subject: Rewrote packet handling code, now it uses queues --- Makefile | 4 +- decoder.cpp | 3 +- demux.cpp | 187 ++++++++++++++-------------- demux.h | 23 ++-- global.h | 1 - markad-standalone.cpp | 49 +++----- pes2audioes.cpp | 273 ----------------------------------------- pes2audioes.h | 132 -------------------- pes2es.cpp | 95 ++++++++++++++ pes2es.h | 79 ++++++++++++ recv.cpp | 36 +++--- tools.cpp | 333 ++++++++++++++++++++++++++++++++++++++++++++++++++ tools.h | 143 ++++++++++++++++++++++ ts2pkt.cpp | 333 ++++++++++---------------------------------------- ts2pkt.h | 57 +-------- vdr2pkt.cpp | 30 +++++ vdr2pkt.h | 29 +++++ 17 files changed, 924 insertions(+), 883 deletions(-) delete mode 100644 pes2audioes.cpp delete mode 100644 pes2audioes.h create mode 100644 pes2es.cpp create mode 100644 pes2es.h create mode 100644 tools.cpp create mode 100644 tools.h create mode 100644 vdr2pkt.cpp create mode 100644 vdr2pkt.h 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 (tssizeProcess(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 (tssizeProcess(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()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 - -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; iSync1==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/pes2audioes.h b/pes2audioes.h deleted file mode 100644 index 13ebcc2..0000000 --- a/pes2audioes.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * pes2audioes.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 uchar -typedef unsigned char uchar; -#endif - -#include -#include -#include - -class cMarkAdPES2AudioES -{ -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: - 8; -unsigned Protection: - 1; -unsigned Layer: - 2; -unsigned MpegID: - 2; -unsigned Sync2: - 3; -unsigned Private: - 1; -unsigned Padding: - 1; -unsigned SampleRateIndex: - 2; -unsigned BitRateIndex: - 4; -unsigned Emphasis: - 2; -unsigned Original: - 1; -unsigned Copyright: - 1; -unsigned ModeExt: - 2; -unsigned Mode: - 2; - }; - -#pragma pack(1) - struct AC3HDR - { -unsigned Sync1: - 8; -unsigned Sync2: - 8; -unsigned CRC1: - 8; -unsigned CRC2: - 8; -unsigned FrameSizeIndex: - 6; -unsigned SampleRateIndex: - 2; - }; -#pragma pack() - - uchar *esdatalast; - uchar *esdata; - int essize; - bool data_left; - - int FindAudioHeader(uchar *PESData, int PESSize); - bool IsValidAudioHeader(uchar *Data, int *FrameSize); - void Reset(); -public: - cMarkAdPES2AudioES(); - ~cMarkAdPES2AudioES(); - int Process(uchar *PESData, int PESSize, uchar **ESData, int *ESSize); -}; - - -#endif 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 +#include +#include + +#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=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; iSampleRateIndex==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/tools.h b/tools.h new file mode 100644 index 0000000..4a182cb --- /dev/null +++ b/tools.h @@ -0,0 +1,143 @@ +/* + * tools.h: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id$ + */ + +#ifndef __tools_h_ +#define __tools_h_ + +#include // needed for (d/e/i)syslog + +#ifndef uchar +typedef unsigned char uchar; +#endif + +#include + +class cMarkAdPaketQueue +{ + struct MP2HDR + { +unsigned Sync1: + 8; +unsigned Protection: + 1; +unsigned Layer: + 2; +unsigned MpegID: + 2; +unsigned Sync2: + 3; +unsigned Private: + 1; +unsigned Padding: + 1; +unsigned SampleRateIndex: + 2; +unsigned BitRateIndex: + 4; +unsigned Emphasis: + 2; +unsigned Original: + 1; +unsigned Copyright: + 1; +unsigned ModeExt: + 2; +unsigned Mode: + 2; + }; + +#pragma pack(1) + struct AC3HDR + { +unsigned Sync1: + 8; +unsigned Sync2: + 8; +unsigned CRC1: + 8; +unsigned CRC2: + 8; +unsigned FrameSizeIndex: + 6; +unsigned SampleRateIndex: + 2; + }; +#pragma pack() + +#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; + + 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: + 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=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)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 (TSSizePidH << 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; iPidH << 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 (sizePut(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 #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 -- cgit v1.2.3