summaryrefslogtreecommitdiff
path: root/markad-standalone.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'markad-standalone.cpp')
-rw-r--r--markad-standalone.cpp669
1 files changed, 620 insertions, 49 deletions
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();
}