summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJochen Dolze <vdr@dolze.de>2009-09-22 09:29:03 +0200
committerJochen Dolze <vdr@dolze.de>2009-09-22 09:29:03 +0200
commit8f9594678c4e0d94e546cd2e94f898bf796c86c6 (patch)
treedb70bb896f08b831485f9d97a53b134708b9c5a6
parent27b768a40f33b229ee832d22f24696565b812f98 (diff)
downloadvdr-plugin-markad-8f9594678c4e0d94e546cd2e94f898bf796c86c6.tar.gz
vdr-plugin-markad-8f9594678c4e0d94e546cd2e94f898bf796c86c6.tar.bz2
Updated various things
-rw-r--r--ChangeLog0
-rw-r--r--Makefile4
-rw-r--r--NEWS0
-rw-r--r--README4
-rw-r--r--TODO0
-rw-r--r--common.cpp1
-rw-r--r--decoder.cpp30
-rw-r--r--demux.cpp4
-rw-r--r--demux.h2
-rw-r--r--global.h17
-rw-r--r--markad-standalone.cpp669
-rw-r--r--markad-standalone.h63
-rw-r--r--markad.h4
-rw-r--r--pes2audioes.cpp2
-rw-r--r--recv.cpp52
-rw-r--r--ts2pes.cpp112
-rw-r--r--ts2pes.h41
-rw-r--r--version.h14
-rw-r--r--video.cpp1
19 files changed, 887 insertions, 133 deletions
diff --git a/ChangeLog b/ChangeLog
deleted file mode 100644
index e69de29..0000000
--- a/ChangeLog
+++ /dev/null
diff --git a/Makefile b/Makefile
index 5530737..a55426c 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/NEWS b/NEWS
deleted file mode 100644
index e69de29..0000000
--- a/NEWS
+++ /dev/null
diff --git a/README b/README
index f58695c..4ed4247 100644
--- a/README
+++ b/README
@@ -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
diff --git a/TODO b/TODO
deleted file mode 100644
index e69de29..0000000
--- a/TODO
+++ /dev/null
diff --git a/common.cpp b/common.cpp
index dcddfd9..8869265 100644
--- a/common.cpp
+++ b/common.cpp
@@ -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
diff --git a/demux.cpp b/demux.cpp
index 792618b..96748a2 100644
--- a/demux.cpp
+++ b/demux.cpp
@@ -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;
diff --git a/demux.h b/demux.h
index 11e0b91..00e8727 100644
--- a/demux.h
+++ b/demux.h
@@ -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
diff --git a/global.h b/global.h
index 7762a83..79a612c 100644
--- a/global.h
+++ b/global.h
@@ -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
diff --git a/markad.h b/markad.h
index f1b40e8..de7316a 100644
--- a/markad.h
+++ b/markad.h
@@ -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;
diff --git a/recv.cpp b/recv.cpp
index b66cf93..447d82a 100644
--- a/recv.cpp
+++ b/recv.cpp
@@ -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;
diff --git a/ts2pes.cpp b/ts2pes.cpp
index c75b672..702fff8 100644
--- a/ts2pes.cpp
+++ b/ts2pes.cpp
@@ -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;
+ }
}
}
}
diff --git a/ts2pes.h b/ts2pes.h
index a3596be..2511eb3 100644
--- a/ts2pes.h
+++ b/ts2pes.h
@@ -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
diff --git a/video.cpp b/video.cpp
index fb956fd..ab2f285 100644
--- a/video.cpp
+++ b/video.cpp
@@ -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;