diff options
author | Jochen Dolze <vdr@dolze.de> | 2009-09-22 09:29:03 +0200 |
---|---|---|
committer | Jochen Dolze <vdr@dolze.de> | 2009-09-22 09:29:03 +0200 |
commit | 8f9594678c4e0d94e546cd2e94f898bf796c86c6 (patch) | |
tree | db70bb896f08b831485f9d97a53b134708b9c5a6 | |
parent | 27b768a40f33b229ee832d22f24696565b812f98 (diff) | |
download | vdr-plugin-markad-8f9594678c4e0d94e546cd2e94f898bf796c86c6.tar.gz vdr-plugin-markad-8f9594678c4e0d94e546cd2e94f898bf796c86c6.tar.bz2 |
Updated various things
-rw-r--r-- | ChangeLog | 0 | ||||
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | NEWS | 0 | ||||
-rw-r--r-- | README | 4 | ||||
-rw-r--r-- | TODO | 0 | ||||
-rw-r--r-- | common.cpp | 1 | ||||
-rw-r--r-- | decoder.cpp | 30 | ||||
-rw-r--r-- | demux.cpp | 4 | ||||
-rw-r--r-- | demux.h | 2 | ||||
-rw-r--r-- | global.h | 17 | ||||
-rw-r--r-- | markad-standalone.cpp | 669 | ||||
-rw-r--r-- | markad-standalone.h | 63 | ||||
-rw-r--r-- | markad.h | 4 | ||||
-rw-r--r-- | pes2audioes.cpp | 2 | ||||
-rw-r--r-- | recv.cpp | 52 | ||||
-rw-r--r-- | ts2pes.cpp | 112 | ||||
-rw-r--r-- | ts2pes.h | 41 | ||||
-rw-r--r-- | version.h | 14 | ||||
-rw-r--r-- | video.cpp | 1 |
19 files changed, 887 insertions, 133 deletions
diff --git a/ChangeLog b/ChangeLog deleted file mode 100644 index e69de29..0000000 --- a/ChangeLog +++ /dev/null @@ -53,12 +53,14 @@ PKG-INCLUDES += libavcodec INCLUDES += -I$(VDRDIR)/include DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' +DEFINES += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE ifeq ($(AVCODEC),1) -DEFINES += DHAVE_AVCODEC +DEFINES += -DHAVE_AVCODEC INCLUDES += $(shell $(PKG-CONFIG) --cflags $(PKG-INCLUDES)) LIBS += $(shell $(PKG-CONFIG) --libs $(PKG-LIBS)) endif + ### The object files (add further files here): OBJS-CMD = markad-standalone.o @@ -2,9 +2,9 @@ This is a "plugin" for the Video Disk Recorder (VDR). Written by: Jochen Dolze <vdr@dolze.de> -Project's homepage: vdr-portal +Project's homepage: http://projects.vdr-developer.org/projects/show/plg-markad -Latest version available at: vdr-portal +Latest version available at: http://projects.vdr-developer.org/projects/list_files/plg-markad This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -55,6 +55,7 @@ bool cMarkAdCommon::AddMark(int Position, const char *Comment) void cMarkAdCommon::SetTimerMarks(int LastIFrame) { if (!macontext) return; + if (!LastIFrame) return; if ((time(NULL)>macontext->General.StartTime) && (!macontext->State.ContentStarted)) { diff --git a/decoder.cpp b/decoder.cpp index 0cbaa9a..56192c1 100644 --- a/decoder.cpp +++ b/decoder.cpp @@ -222,6 +222,8 @@ cMarkAdDecoder::cMarkAdDecoder(int RecvNumber, bool useH264, bool hasAC3) cpucount=CPU_COUNT(&cpumask); } + isyslog("markad [%i]: using %i threads",recvnumber,cpucount); + CodecID mp2_codecid=CODEC_ID_MP2; AVCodec *mp2_codec= avcodec_find_decoder(mp2_codecid); if (mp2_codec) @@ -232,19 +234,19 @@ cMarkAdDecoder::cMarkAdDecoder(int RecvNumber, bool useH264, bool hasAC3) mp2_context->thread_count=cpucount; if (avcodec_open(mp2_context, mp2_codec) < 0) { - esyslog("noad [%i]: could not open codec 0x%05x",recvnumber,mp2_codecid); + esyslog("markad [%i]: could not open codec 0x%05x",recvnumber,mp2_codecid); av_free(mp2_context); mp2_context=NULL; } } else { - esyslog("noad [%i]: could not allocate mp2 context",recvnumber); + esyslog("markad [%i]: could not allocate mp2 context",recvnumber); } } else { - esyslog("noad [%i]: codec 0x%05x not found",recvnumber,mp2_codecid); + esyslog("markad [%i]: codec 0x%05x not found",recvnumber,mp2_codecid); mp2_context=NULL; } @@ -260,19 +262,19 @@ cMarkAdDecoder::cMarkAdDecoder(int RecvNumber, bool useH264, bool hasAC3) ac3_context->thread_count=cpucount; if (avcodec_open(ac3_context, ac3_codec) < 0) { - esyslog("noad [%i]: could not open codec 0x%05x",recvnumber,ac3_codecid); + esyslog("markad [%i]: could not open codec 0x%05x",recvnumber,ac3_codecid); av_free(ac3_context); ac3_context=NULL; } } else { - esyslog("noad [%i]: could not allocate ac3 context",recvnumber); + esyslog("markad [%i]: could not allocate ac3 context",recvnumber); } } else { - esyslog("noad [%i]: codec 0x%05x not found",recvnumber,ac3_codecid); + esyslog("markad [%i]: codec 0x%05x not found",recvnumber,ac3_codecid); ac3_context=NULL; } } @@ -308,7 +310,7 @@ cMarkAdDecoder::cMarkAdDecoder(int RecvNumber, bool useH264, bool hasAC3) if (avcodec_open(video_context, video_codec) < 0) { - esyslog("noad [%i]: could not open codec 0x%05x",recvnumber,video_codecid); + esyslog("markad [%i]: could not open codec 0x%05x",recvnumber,video_codecid); av_free(video_context); video_context=NULL; } @@ -317,7 +319,7 @@ cMarkAdDecoder::cMarkAdDecoder(int RecvNumber, bool useH264, bool hasAC3) video_frame = avcodec_alloc_frame(); if (!video_frame) { - esyslog("noad [%i]: could not allocate frame",recvnumber); + esyslog("markad [%i]: could not allocate frame",recvnumber); avcodec_close(video_context); av_free(video_context); video_context=NULL; @@ -326,12 +328,12 @@ cMarkAdDecoder::cMarkAdDecoder(int RecvNumber, bool useH264, bool hasAC3) } else { - esyslog("noad [%i]: could not allocate video context",recvnumber); + esyslog("markad [%i]: could not allocate video context",recvnumber); } } else { - esyslog("noad [%i]: codec 0x%05x not found",recvnumber,video_codecid); + esyslog("markad [%i]: codec 0x%05x not found",recvnumber,video_codecid); video_context=NULL; } memset(temp_pictureplane,0,sizeof(temp_pictureplane)); @@ -391,7 +393,7 @@ bool cMarkAdDecoder::DecodeMP2(MarkAdContext *maContext, uchar *espkt, int eslen #endif if (len<0) { - esyslog("noad [%i]: error decoding mp2",recvnumber); + esyslog("markad [%i]: error decoding mp2",recvnumber); break; } else @@ -446,12 +448,12 @@ bool cMarkAdDecoder::DecodeAC3(MarkAdContext *maContext, uchar *espkt, int eslen #endif if (len<0) { - esyslog("noad [%i]: error decoding ac3",recvnumber); + esyslog("markad [%i]: error decoding ac3",recvnumber); break; } else { - SetAudioInfos(maContext,ac3_context,); + SetAudioInfos(maContext,ac3_context); ret=true; avpkt.size-=len; avpkt.data+=len; @@ -563,7 +565,7 @@ bool cMarkAdDecoder::DecodeVideo(MarkAdContext *maContext,uchar *pespkt, int pes #endif if (len<0) { - esyslog("noad [%i]: error decoding video",recvnumber); + esyslog("markad [%i]: error decoding video",recvnumber); break; } else @@ -23,10 +23,10 @@ cMarkAdDemux::~cMarkAdDemux() if (pes2audioes) delete pes2audioes; } -int cMarkAdDemux::Process(int Pid, uchar *Data, int Count, uchar **Pkt, int *PktLen) +int cMarkAdDemux::Process(MarkAdPid Pid, uchar *Data, int Count, uchar **Pkt, int *PktLen) { if ((!Data) && (!Count) && (!ts2pes) && (!pes2audioes) || - (!Pkt) || (!PktLen) || (!Pid)) return -1; + (!Pkt) || (!PktLen) || (!Pid.Num)) return -1; *Pkt=NULL; *PktLen=0; @@ -24,7 +24,7 @@ private: public: cMarkAdDemux(); ~cMarkAdDemux(); - int Process(int Pid, uchar *Data, int Count, uchar **Pkt, int *PktLen); + int Process(MarkAdPid Pid, uchar *Data, int Count, uchar **Pkt, int *PktLen); }; #endif @@ -36,6 +36,17 @@ typedef struct MarkAdAspectRatio int Den; } MarkAdAspectRatio; +#define MARKAD_PIDTYPE_VIDEO_H262 0x10 +#define MARKAD_PIDTYPE_VIDEO_H264 0x11 +#define MARKAD_PIDTYPE_AUDIO_AC3 0x20 +#define MARKAD_PIDTYPE_AUDIO_MP2 0x21 + +typedef struct MarkAdPid +{ + int Num; + int Type; +} MarkAdPid; + typedef struct MarkAdContext { struct General @@ -44,9 +55,9 @@ typedef struct MarkAdContext time_t EndTime; bool ManualRecording; bool H264; - int VPid; - int APid; - int DPid; + MarkAdPid VPid; + MarkAdPid APid; + MarkAdPid DPid; } General; struct State diff --git a/markad-standalone.cpp b/markad-standalone.cpp index 6837807..ed57ceb 100644 --- a/markad-standalone.cpp +++ b/markad-standalone.cpp @@ -8,87 +8,658 @@ #include "markad-standalone.h" -#define MAXSYSLOGBUF 255 void syslog_with_tid(int priority, const char *format, ...) { va_list ap; - char fmt[MAXSYSLOGBUF]; +#ifdef SYSLOG + char fmt[255]; snprintf(fmt, sizeof(fmt), "[%d] %s", getpid(), format); va_start(ap, format); vsyslog(priority, fmt, ap); va_end(ap); +#else + va_start(ap, format); + vprintf(format,ap); + va_end(ap); + printf("\n"); +#endif } -int main(int argc, char *argv[]) +int cMarkAdIndex::GetNext(off_t Offset) { - uchar data[35344]; + if (index_fd==-1) return 0; + + struct tIndexPes + { + uint32_t offset; + uchar type; + uchar number; + uint16_t reserved; + }; + + struct tIndexTs + { +uint64_t offset: + 40; +unsigned reserved: + 7; +unsigned independent: + 1; +uint16_t number: + 16; + }; + + if (offset>Offset) return iframe; + if (ts) + { + struct tIndexTs its; + if (read(index_fd,&its,sizeof(its))==-1) return 0; + offset=(off_t) its.offset; + if (its.independent==1) iframe=index; + } + else + { + struct tIndexPes ipes; + if (read(index_fd,&ipes,sizeof(ipes))==-1) return 0; + offset=ipes.offset; + if (ipes.type==1) iframe=index; + } + index++; + return iframe; +} + +bool cMarkAdIndex::Open(const char *Directory) +{ + if (!Directory) return false; + char *ibuf; + asprintf(&ibuf,"%s/index.vdr",Directory); + if (!ibuf) return false; + index_fd = open(ibuf,O_RDONLY); + free(ibuf); + maxfiles=999; + if (index_fd==-1) + { + // second try just index -> ts format + asprintf(&ibuf,"%s/index",Directory); + if (!ibuf) return false; + index_fd = open(ibuf,O_RDONLY); + free(ibuf); + if (index_fd==-1) + { + fprintf(stderr,"Cannot open index file in %s\n",Directory); + return false; + } + ts=true; + maxfiles=65535; + } + return true; +} + +void cMarkAdIndex::Close() +{ + if (index_fd!=-1) close(index_fd); +} + +cMarkAdIndex::cMarkAdIndex(const char *Directory) +{ + if (!Directory) return; + iframe=0; + offset=0; + index=0; + ts=false; + Open(Directory); +} + +cMarkAdIndex::~cMarkAdIndex() +{ + Close(); +} + +void cMarkAdStandalone::AddMark(MarkAdMark *Mark) +{ +// TODO: Implement this! +} + +bool cMarkAdStandalone::ProcessFile(int Number) +{ + if (!dir) return false; + if (!Number) return false; + + uchar data[2048]; int datalen; - //int f=open("/var/lib/video/031.ts",O_RDWR); - //int f=open("/root/frames_515.dat",O_RDWR); - //int f=open("/root/VDR/PLUGINS/markad/test/ANIXEHD-Spiderman3-h.264.ts",O_RDWR); - int f=open("/tmp/input0.ts",O_RDWR); - if (f==-1) return -1; + char *fbuf; + if (index->isTS()) + { + asprintf(&fbuf,"%s/%05i.ts",dir,Number); + } + else + { + asprintf(&fbuf,"%s/%03i.vdr",dir,Number); + } + if (!fbuf) return false; - MarkAdContext macontext; - memset(&macontext,0,sizeof(macontext)); + int f=open(fbuf,O_RDONLY); + free(fbuf); + if (f==-1) return false; + + int lastiframe; + while ((datalen=read(f,&data,sizeof(data))>0)) + { + + lastiframe=LastIFrame(Number,lseek(f,0,SEEK_CUR)-datalen); + MarkAdMark *mark; + + if (common) + { + mark=common->Process(lastiframe); + AddMark(mark); + } + + if ((video_demux) && (decoder) && (video)) + { + uchar *pkt; + int pktlen; + + uchar *tspkt = data; + int tslen = datalen; + + while (tslen>0) + { + int len=video_demux->Process(macontext.General.VPid,tspkt,tslen,&pkt,&pktlen); + if (len<0) + { + break; + } + else + { + if (pkt) + { + decoder->FindH262VideoInfos(&macontext,pkt,pktlen); + if (decoder->DecodeVideo(&macontext,pkt,pktlen)) + { + mark=video->Process(lastiframe); + AddMark(mark); + + } + } + tspkt+=len; + tslen-=len; + } + } + } + if ((mp2_demux) && (decoder) && (audio)) + { + uchar *pkt; + int pktlen; + + uchar *tspkt = data; + int tslen = datalen; + + while (tslen>0) + { + int len=mp2_demux->Process(macontext.General.APid,tspkt,tslen,&pkt,&pktlen); + if (len<0) + { + break; + } + else + { + if (pkt) + { + if (decoder->DecodeMP2(&macontext,pkt,pktlen)) + { + mark=audio->Process(lastiframe); + AddMark(mark); + } + } + tspkt+=len; + tslen-=len; + } + } + } + + if ((ac3_demux) && (decoder) && (audio)) + { + uchar *pkt; + int pktlen; + + uchar *tspkt = data; + int tslen = datalen; + + while (tslen>0) + { + int len=ac3_demux->Process(macontext.General.DPid,tspkt,tslen,&pkt,&pktlen); + if (len<0) + { + break; + } + else + { + if (pkt) + { + decoder->FindAC3AudioInfos(&macontext,pkt,pktlen); + if (decoder->DecodeAC3(&macontext,pkt,pktlen)) + { + mark=audio->Process(lastiframe); + AddMark(mark); + } + } + tspkt+=len; + tslen-=len; + } + } + } + } + close(f); + return true; +} + +int cMarkAdStandalone::LastIFrame(int Number, off_t Offset) +{ + return index->GetNext(Offset); +} + + +void cMarkAdStandalone::Process() +{ + if (!index) return; + + for (int i=1; i<=index->MaxFiles(); i++) + { + if (!ProcessFile(i)) + { + break; + } + } +} + +cMarkAdStandalone::cMarkAdStandalone(const char *Directory) +{ + dir=strdup(Directory); + + memset(&macontext,0,sizeof(macontext)); macontext.General.StartTime=0; - macontext.General.EndTime=0xFFFFFFFF; - macontext.General.VPid=0x100; - //macontext.General.DPid=0x403; -// macontext.General.DPid=0x203; - //macontext.General.APid=0x101; - - cMarkAdDemux *demux = new cMarkAdDemux(); - cMarkAdDecoder *decoder = new cMarkAdDecoder(255,false,false); - cMarkAdVideo *video = new cMarkAdVideo(255,&macontext); - MarkAdMark *mark; - - int lastiframe=1; - while (datalen=read(f,&data,sizeof(data))) + macontext.General.EndTime=time(NULL)+(7*86400); + macontext.General.DPid.Type=MARKAD_PIDTYPE_AUDIO_AC3; + macontext.General.APid.Type=MARKAD_PIDTYPE_AUDIO_MP2; + + macontext.General.VPid.Type=MARKAD_PIDTYPE_VIDEO_H262; + + macontext.General.VPid.Num=0x100; + macontext.General.DPid.Num=0x102; + macontext.General.APid.Num=0x101; + + video_demux = new cMarkAdDemux(); + +// mp2_demux = new cMarkAdDemux(); + mp2_demux=NULL; + + ac3_demux = new cMarkAdDemux(); + decoder = new cMarkAdDecoder(255,false,false); + video = new cMarkAdVideo(255,&macontext); + audio = new cMarkAdAudio(255,&macontext); + common = new cMarkAdCommon(255,&macontext); + + index = new cMarkAdIndex(Directory); +} + +cMarkAdStandalone::~cMarkAdStandalone() +{ + if (video_demux) delete video_demux; + if (ac3_demux) delete ac3_demux; + if (mp2_demux) delete mp2_demux; + if (decoder) delete decoder; + if (video) delete video; + if (audio) delete audio; + if (common) delete common; + if (index) delete index; + + if (dir) free(dir); +} + +bool isnumber(const char *s) +{ + while (*s) { - uchar *pkt; - int pktlen; + if (!isdigit(*s)) + return false; + s++; + } + return true; +} - uchar *tspkt = data; - int tslen = datalen; +int usage() +{ + // nothing done, give the user some help + printf("Usage: markad [options] cmd <record>\n" + "options:\n" + "-b --background\n" + " markad runs as a background-process\n" + " this will be automatically set if called with \"after\"\n" + "-p, --priority\n" + " priority-level of markad when running in background\n" + " [19...-19] default 19\n" + "-v, --verbose\n" + " increments loglevel by one, can be given multiple times\n" + "-B --backupmarks\n" + " make a backup of the existing marks\n" + "-O, --OSD\n" + " markad sends an OSD-Message for start and end\n" + "-V --version\n" + " print version-info and exit\n" + "--markfile=<markfilename>\n" + " set a different markfile-name\n" + "\ncmd: one of\n" + "- dummy-parameter if called directly\n" + "after markad starts to analyze the recording\n" + "before markad exits immediately if called with \"before\"\n" + "edited markad exits immediately if called with \"edited\"\n" + "nice runs markad with nice(19)\n" + "\n<record> is the name of the directory where the recording\n" + " is stored\n\n" + ); + return -1; +} - while (tslen>0) +int main(int argc, char *argv[]) +{ + int c; + bool bAfter=false,bBefore=false,bEdited=false,bFork=false,bNice=false,bImmediateCall=false; + int niceLevel = 19; + char *recDir=NULL; + + while (1) + { + int option_index = 0; + static struct option long_options[] = + { + {"statisticfile",1,0,'s' + }, + {"logocachedir", 1, 0, 'l'}, + {"verbose", 0, 0, 'v'}, + {"background", 0, 0, 'b'}, + {"priority",1,0,'p'}, + {"comments", 0, 0, 'c'}, + {"jumplogo",0,0,'j'}, + {"overlap",0,0,'o' }, + {"ac3",0,0,'a' }, + {"OSD",0,0,'O' }, + {"savelogo", 0, 0, 'S'}, + {"backupmarks", 0, 0, 'B'}, + {"scenechangedetection", 0, 0, 'C'}, + {"version", 0, 0, 'V'}, + {"nelonen",0,0,'n'}, + {"markfile",1,0,1}, + {"loglevel",1,0,2}, + {"testmode",0,0,3}, + {"online",2,0,4}, + {"nopid",0,0,5}, + {"asd",0,0,6}, + {"pass3only",0,0,7}, + {0, 0, 0, 0} + }; + + c = getopt_long (argc, argv, "s:l:vbp:cjoaOSBCV", + long_options, &option_index); + if (c == -1) + break; + + switch (c) { - int len=demux->Process(macontext.General.VPid,tspkt,tslen,&pkt,&pktlen); - if (len<0) + + case 'v': + SysLogLevel++; + if (SysLogLevel>10) SysLogLevel=10; + break; + + case 'b': + bFork = true; + break; + + case 'p': + if (isnumber(optarg) || *optarg=='-') + niceLevel = atoi(optarg); + else + { + fprintf(stderr, "markad: invalid priority level: %s\n", optarg); + return 2; + } + bNice = true; + break; + + case 'O': +// osdMsg = 1; + break; + + case 's': + case 'l': + case 'c': + case 'j': + case 'o': + case 'a': + case 'S': + case 'B': + case 'n': + case 'C': + break; + + case 'V': + printf("markad %s - marks advertisements in VDR recordings\n",VERSION); + return 0; + + case '?': + printf("unknow option ?\n"); + break; + + case 0: + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + break; + + case 1: // --markfile + //setMarkfileName(optarg); // TODO: implement this + break; + + case 2: // --verbose + //if (isnumber(optarg)) + // verbosity = atoi(optarg); + break; + + case 3: // --testmode + break; + + case 4: // --online + break; + + case 5: // --nopid + break; + + case 6: // --asd + break; + + case 7: // --pass3only + break; + + default: + printf ("? getopt returned character code 0%o ? (option_index %d)\n", c,option_index); + } + } + + if (optind < argc) + { + while (optind < argc) + { + if (strcmp(argv[optind], "after" ) == 0 ) + { + bAfter = bFork = bNice = true; + } + else if (strcmp(argv[optind], "before" ) == 0 ) + { + bBefore = true; + } + else if (strcmp(argv[optind], "edited" ) == 0 ) + { + bEdited = true; + } + else if (strcmp(argv[optind], "nice" ) == 0 ) + { + bNice = true; + } + else if (strcmp(argv[optind], "-" ) == 0 ) { - break; + bImmediateCall = true; } else { + if ( strstr(argv[optind],".rec") != NULL ) + recDir = argv[optind]; + } + optind++; + } + } - if (pkt) - { + // do nothing if called from vdr before/after the video is cutted + if (bBefore) return 0; + if (bEdited) return 0; - decoder->FindH262VideoInfos(&macontext,pkt,pktlen); - if (decoder->DecodeVideo(&macontext,pkt,pktlen)) - { - mark=video->Process(lastiframe++); - // AddMark(mark); + // we can run, if one of bImmediateCall, bAfter, bBefore or bNice is true + // and recDir is given + if ( (bImmediateCall || bAfter || bNice) && recDir ) + { + // if bFork is given go in background + if ( bFork ) + { + (void)umask((mode_t)0011); + //close_files(); + pid_t pid = fork(); + if (pid < 0) + { + fprintf(stderr, "%m\n"); + esyslog("fork ERROR: %m"); + return 2; + } + if (pid != 0) + { + isyslog("markad forked to pid %d",pid); + return 0; // initial program immediately returns + } + } + if ( bFork ) + { + isyslog("markad (forked) pid: %d", getpid()); + chdir("/"); + if (setsid() == (pid_t)(-1)) + { + perror("setsid"); + exit(EXIT_FAILURE); + } + if (signal(SIGHUP, SIG_IGN) == SIG_ERR) + { + perror("signal(SIGHUP, SIG_IGN)"); + errno = 0; + } + int f; - } + f = open("/dev/null", O_RDONLY); + if (f == -1) + { + perror("/dev/null"); + errno = 0; + } + else + { + if (dup2(f, fileno(stdin)) == -1) + { + perror("dup2"); + errno = 0; + } + (void)close(f); + } - printf("Pktlen=%i\n", pktlen); + f = open("/dev/null", O_WRONLY); + if (f == -1) + { + perror("/dev/null"); + errno = 0; + } + else + { + if (dup2(f, fileno(stdout)) == -1) + { + perror("dup2"); + errno = 0; } + if (dup2(f, fileno(stderr)) == -1) + { + perror("dup2"); + errno = 0; + } + (void)close(f); + } + } + + int MaxPossibleFileDescriptors = getdtablesize(); + for (int i = STDERR_FILENO + 1; i < MaxPossibleFileDescriptors; i++) + close(i); //close all dup'ed filedescriptors - tspkt+=len; - tslen-=len; + // should we renice ? + if ( bNice ) + { + int niceErr = nice(niceLevel); + int oldErrno = errno; + if ( errno == EPERM || errno == EACCES ) + { + esyslog("ERROR: nice %d: no super-user rights",niceLevel); + errno = oldErrno; + fprintf(stderr, "nice %d: no super-user rights\n",niceLevel); + } + else if ( niceErr != niceLevel ) + { + esyslog("nice ERROR(%d,%d): %m",niceLevel,niceErr); + errno = oldErrno; + fprintf(stderr, "%d %d %m\n",niceErr,errno); } } - } - delete demux; - delete decoder; - delete video; - close(f); + // catch some signals + /* + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); + signal(SIGABRT, signal_handler); + signal(SIGSEGV, signal_handler); + signal(SIGUSR1, signal_handler); + */ - return 0; + // do cleanup at exit... +// atexit(cleanUp); + + // now do the work... + struct stat statbuf; + if (stat(recDir,&statbuf)==-1) + { + fprintf(stderr,"%s not found\n",recDir); + return -1; + } + + if (!S_ISDIR(statbuf.st_mode)) + { + fprintf(stderr,"%s is not a directory\n",recDir); + return -1; + } + + cMarkAdStandalone *cmasta = new cMarkAdStandalone(recDir); + if (cmasta) + { + cmasta->Process(); + delete cmasta; + } + + return 0; + } + return usage(); } diff --git a/markad-standalone.h b/markad-standalone.h index 1f39d39..cd4a023 100644 --- a/markad-standalone.h +++ b/markad-standalone.h @@ -14,12 +14,71 @@ #include <stdarg.h> #include <unistd.h> #include <fcntl.h> +#include <getopt.h> +#include <signal.h> +#include <ctype.h> #include "demux.h" #include "global.h" #include "decoder.h" #include "video.h" +#include "audio.h" +#include "common.h" +#include "version.h" -int SysLogLevel=3; +int SysLogLevel=2; -#endif
\ No newline at end of file +class cMarkAdIndex +{ +private: + int index_fd; // index file descriptor + int maxfiles; + bool ts; + + int index; + int iframe; + off_t offset; + + bool Open(const char *Directory); + void Close(); +public: + bool isTS() + { + return ts; + } + int MaxFiles() + { + return maxfiles; + } + int GetNext(off_t Offset); + cMarkAdIndex(const char *Directory); + ~cMarkAdIndex(); +}; + +class cMarkAdStandalone +{ +private: + cMarkAdDemux *video_demux; + cMarkAdDemux *ac3_demux; + cMarkAdDemux *mp2_demux; + cMarkAdDecoder *decoder; + cMarkAdVideo *video; + cMarkAdAudio *audio; + cMarkAdCommon *common; + + MarkAdContext macontext; + char *dir; + + cMarkAdIndex *index; + + void AddMark(MarkAdMark *Mark); + int LastIFrame(int Number, off_t Offset); + bool ProcessFile(int Number); + +public: + void Process(); + cMarkAdStandalone(const char *Directory); + ~cMarkAdStandalone(); +}; + +#endif @@ -1,4 +1,3 @@ - /* * markad.h: A plugin for the Video Disk Recorder * @@ -10,9 +9,10 @@ #ifndef __markad_h_ #define __markad_h_ +#include "version.h" #include "status.h" -static const char *VERSION = "0.0.3"; +extern const char *VERSION; static const char *DESCRIPTION = trNOOP("Mark advertisements"); class cPluginMarkAd : public cPlugin { diff --git a/pes2audioes.cpp b/pes2audioes.cpp index 7614cd0..e8cdde4 100644 --- a/pes2audioes.cpp +++ b/pes2audioes.cpp @@ -254,7 +254,7 @@ int cMarkAdPES2AudioES::Process(uchar *PESData, int PESSize, uchar **ESData, int esdata=NULL; essize=0; - if (size) + if (size>0) { void *ptr=malloc(size); if (!ptr) return -1; @@ -44,14 +44,27 @@ cMarkAdReceiver::cMarkAdReceiver(int RecvNumber, const char *Filename, cTimer *T macontext.General.ManualRecording=true; } - macontext.General.VPid=Timer->Channel()->Vpid(); -// macontext.General.APid=Timer->Channel()->Apid(0); // TODO ... better solution? - macontext.General.DPid=Timer->Channel()->Dpid(0); // TODO ... better solution? + macontext.General.VPid.Num=Timer->Channel()->Vpid(); + if (useH264) + { + macontext.General.VPid.Type=MARKAD_PIDTYPE_VIDEO_H264; + } + else + { + macontext.General.VPid.Type=MARKAD_PIDTYPE_VIDEO_H262; + } + +// macontext.General.APid.Pid=Timer->Channel()->Apid(0); // TODO ... better solution? +// macontext.General.DPid.Type=MARKAD_PIDTYPE_AUDIO_MP2; + + 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) + if (macontext.General.VPid.Num) { + dsyslog("markad [%i]: using video",recvnumber); video=new cMarkAdVideo(RecvNumber,&macontext); video_demux = new cMarkAdDemux(); } @@ -61,8 +74,9 @@ cMarkAdReceiver::cMarkAdReceiver(int RecvNumber, const char *Filename, cTimer *T video_demux=NULL; } - if (macontext.General.APid) + if (macontext.General.APid.Num) { + dsyslog("markad [%i]: using mp2",recvnumber); mp2_demux = new cMarkAdDemux(); } else @@ -70,8 +84,9 @@ cMarkAdReceiver::cMarkAdReceiver(int RecvNumber, const char *Filename, cTimer *T mp2_demux = NULL; } - if (macontext.General.DPid) + if (macontext.General.DPid.Num) { + dsyslog("markad [%i]: using ac3",recvnumber); ac3_demux = new cMarkAdDemux(); } else @@ -79,7 +94,7 @@ cMarkAdReceiver::cMarkAdReceiver(int RecvNumber, const char *Filename, cTimer *T ac3_demux=NULL; } - if ((macontext.General.APid) || (macontext.General.DPid)) + if ((macontext.General.APid.Num) || (macontext.General.DPid.Num)) { audio=new cMarkAdAudio(RecvNumber,&macontext); } @@ -88,7 +103,7 @@ cMarkAdReceiver::cMarkAdReceiver(int RecvNumber, const char *Filename, cTimer *T audio=NULL; } - decoder=new cMarkAdDecoder(RecvNumber,useH264,macontext.General.DPid!=0); + decoder=new cMarkAdDecoder(RecvNumber,useH264,macontext.General.DPid.Num!=0); common=new cMarkAdCommon(RecvNumber,&macontext); marks.Load(Filename); @@ -111,10 +126,16 @@ cMarkAdReceiver::~cMarkAdReceiver() { MarkAdMark tempmark; tempmark.Position=lastiframe; - tempmark.Comment=strdup("stop of content (user)"); - AddMark(&tempmark); - isyslog("markad [%i]: stop of content (user)",recvnumber); - free(tempmark.Comment); + + char *buf; + asprintf(&buf,"stop of user content (%i)",lastiframe); + if (buf) + { + tempmark.Comment=buf; + AddMark(&tempmark); + isyslog("markad [%i]: %s",recvnumber,buf); + free(buf); + } } if (video_demux) delete video_demux; @@ -135,14 +156,14 @@ int cMarkAdReceiver::LastIFrame() if (!Index) { esyslog("markad [%i]: ERROR can't allocate index",recvnumber); - return -1; + return 0; } else if (!Index->Ok()) { // index file is not ready till now, try it later delete Index; Index=NULL; - return -1; + return 0; } } return Index->GetNextIFrame(Index->Last(),false,NULL,NULL,NULL,true); @@ -299,7 +320,7 @@ void cMarkAdReceiver::Action() while (tslen>0) { - int len=ac3_demux->Process(macontext.General.APid,tspkt,tslen,&pkt,&pktlen); + int len=ac3_demux->Process(macontext.General.DPid,tspkt,tslen,&pkt,&pktlen); if (len<0) { break; @@ -312,6 +333,7 @@ void cMarkAdReceiver::Action() if (decoder->DecodeAC3(&macontext,pkt,pktlen)) { mark=audio->Process(lastiframe); + AddMark(mark); } } tspkt+=len; @@ -29,19 +29,25 @@ void cMarkAdTS2PES::Reset() pesdata=NULL; pessize=0; data_left=false; - streamsize=0; counter=-1; sync=false; } -int cMarkAdTS2PES::FindPESHeader(uchar *TSData, int TSSize, int *StreamSize) +int cMarkAdTS2PES::FindPESHeader(uchar *TSData, int TSSize, int *StreamSize, + int *HeaderSize) { - unsigned long scanner=0xFFFFFFFF; - int i; + if ((!TSData) || (!TSSize)) return -1; +#define PESHDRSIZE 6 + if (StreamSize) (*StreamSize)=0; + if (HeaderSize) (*HeaderSize)=3; + //unsigned long scanner=0xFFFFFFFF; + int i=0; +long scanner=-1; + for (i=0; i<TSSize; i++) { scanner<<=8; - if (scanner==0x00000100) + if (scanner==(long) 0x00000100L) { break; } @@ -49,22 +55,35 @@ int cMarkAdTS2PES::FindPESHeader(uchar *TSData, int TSSize, int *StreamSize) } if (i!=TSSize) { - if (StreamSize) + if ((StreamSize) && ((i+2)<TSSize)) { if (TSData[i]>=0xBC) { - *StreamSize=(TSData[i+1]<<8)+TSData[i+2]; + (*StreamSize)=(TSData[i+1]<<8)+TSData[i+2]; if (*StreamSize) (*StreamSize)+=6; // 6 Byte PES-Header } } + if ((HeaderSize) && ((i+6)<TSSize)) + { + struct PESHDROPT *peshdropt=(struct PESHDROPT *) &TSData[i+3]; + if (peshdropt->MarkerBits==0x2) + { + (*HeaderSize)=PESHDRSIZE+sizeof(struct PESHDROPT)+ + peshdropt->Length; + } + else + { + (*HeaderSize)=PESHDRSIZE; + } + } return i-3; } return -1; } -int cMarkAdTS2PES::Process(int Pid, uchar *TSData, int TSSize, uchar **PESData, int *PESSize) +int cMarkAdTS2PES::Process(MarkAdPid Pid, uchar *TSData, int TSSize, uchar **PESData, int *PESSize) { - if ((!PESData) || (!PESSize)) return -1; + if ((!PESData) || (!PESSize) || (!TSData) || (!TSSize)) return -1; *PESData=NULL; *PESSize=0; @@ -92,7 +111,7 @@ int cMarkAdTS2PES::Process(int Pid, uchar *TSData, int TSSize, uchar **PESData, struct TSHDR *tshdr = (struct TSHDR *) TSData; int pid = (tshdr->PidH << 8) | tshdr->PidL; - if (Pid!=pid) + if (Pid.Num!=pid) { return TS_SIZE; // not for us } @@ -148,6 +167,13 @@ int cMarkAdTS2PES::Process(int Pid, uchar *TSData, int TSSize, uchar **PESData, Reset(); return TS_SIZE; } + if (buflen<0) + { + // error in size + Reset(); + return TS_SIZE; + } + bytes_processed=TS_SIZE-buflen; pesdata=(uchar *) realloc(pesdata,pessize+buflen); @@ -166,20 +192,26 @@ int cMarkAdTS2PES::Process(int Pid, uchar *TSData, int TSSize, uchar **PESData, data_left=false; } - int peshdr=FindPESHeader(pesdata, pessize, &streamsize); + int streamsize=0; + int peshdrsize=3; // size of sync (just as start) + int peshdr=FindPESHeader(pesdata, pessize, &streamsize, &peshdrsize); + if (peshdr==0) { if (!streamsize) { - peshdr=FindPESHeader(pesdata+3,pessize-3,NULL); - if (peshdr>0) peshdr+=3; + peshdr=FindPESHeader(pesdata+peshdrsize,pessize-peshdrsize,NULL,NULL); + if (peshdr>=0) + { + peshdr+=peshdrsize; + } } else { if (pessize>streamsize) { int size=pessize-streamsize; - + uchar *pesptr=pesdata; *PESData=pesdata; *PESSize=streamsize; if (pesdatalast) free(pesdatalast); @@ -189,43 +221,47 @@ int cMarkAdTS2PES::Process(int Pid, uchar *TSData, int TSSize, uchar **PESData, void *ptr=malloc(size); if (!ptr) return -1; - memcpy(ptr,(*PESData)+streamsize,size); + memcpy(ptr,pesptr+streamsize,size); bytes_processed-=size; pessize=size; pesdata=(uchar *) ptr; data_left=true; - streamsize=0; } } } + if (peshdr>0) { // start of next PES paket found if (pesdata) { - // return old data - *PESData=pesdata; - *PESSize=peshdr; - if (pesdatalast) free(pesdatalast); - pesdatalast=pesdata; - int size=pessize-peshdr; - pesdata=NULL; - pessize=0; - - if (size>0) - { - void *ptr=malloc(size); - if (!ptr) return -1; - memcpy(ptr,(*PESData)+peshdr,size); - bytes_processed-=size; - pessize=size; - pesdata=(uchar *) ptr; - data_left=true; - } - else + if ((pesdata[0]==0) && (pesdata[1]==0) && (pesdata[2]==1)) { - // TODO: not sure if this is ok - bytes_processed-=size; + // return old data + uchar *pesptr=pesdata; + *PESData=pesdata; + *PESSize=peshdr; + if (pesdatalast) free(pesdatalast); + pesdatalast=pesdata; + int size=pessize-peshdr; + pesdata=NULL; + pessize=0; + + if (size>0) + { + void *ptr=malloc(size); + if (!ptr) return -1; + memcpy(ptr,pesptr+peshdr,size); + bytes_processed-=size; + pessize=size; + pesdata=(uchar *) ptr; + data_left=true; + } + else + { + // TODO: not sure if this is ok + bytes_processed-=size; + } } } } @@ -20,6 +20,8 @@ typedef unsigned char uchar; #include <stdlib.h> #include <string.h> +#include "global.h" + class cMarkAdTS2PES { private: @@ -53,20 +55,53 @@ 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() + uchar *pesdatalast; uchar *pesdata; int pessize; - int streamsize; bool data_left; int counter; bool sync; void Reset(); - int FindPESHeader(uchar *TSData, int TSSize, int *StreamSize); + int FindPESHeader(uchar *TSData, int TSSize, int *StreamSize, int *HeaderSize); public: cMarkAdTS2PES(); ~cMarkAdTS2PES(); - int Process(int Pid,uchar *TSData, int TSSize, uchar **PESData, int *PESSize); + int Process(MarkAdPid Pid,uchar *TSData, int TSSize, uchar **PESData, int *PESSize); }; #endif diff --git a/version.h b/version.h new file mode 100644 index 0000000..aa37a4a --- /dev/null +++ b/version.h @@ -0,0 +1,14 @@ +/* + * version.h: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id$ + */ + +#ifndef __version_h_ +#define __version_h_ + +static const char *VERSION = "0.0.3"; + +#endif
\ No newline at end of file @@ -50,6 +50,7 @@ int cMarkAdBlackBordersHoriz::Process(int LastIFrame, int *BorderIFrame) #define BRIGHTNESS 20 if (!macontext) return 0; if (!macontext->Video.Data.Valid) return 0; +return 0; *BorderIFrame=borderiframe; |