diff options
| author | Jochen Dolze <vdr@dolze.de> | 2010-03-30 18:49:58 +0200 |
|---|---|---|
| committer | Jochen Dolze <vdr@dolze.de> | 2010-03-30 18:49:58 +0200 |
| commit | 74cdd9ffa1d0e5f74942051e7e22e07542929c03 (patch) | |
| tree | e59472547b1ed3543b8e2d1d0e2a7c52fcb24c04 /markad-standalone.cpp | |
| parent | 6446f24dce1b30fa341b7de078ca4385d1378457 (diff) | |
| download | vdr-plugin-markad-74cdd9ffa1d0e5f74942051e7e22e07542929c03.tar.gz vdr-plugin-markad-74cdd9ffa1d0e5f74942051e7e22e07542929c03.tar.bz2 | |
Changed directory structure, added Makefiles
Diffstat (limited to 'markad-standalone.cpp')
| -rw-r--r-- | markad-standalone.cpp | 1632 |
1 files changed, 0 insertions, 1632 deletions
diff --git a/markad-standalone.cpp b/markad-standalone.cpp deleted file mode 100644 index 9d4cb82..0000000 --- a/markad-standalone.cpp +++ /dev/null @@ -1,1632 +0,0 @@ -/* - * markad-standalone.cpp: A program for the Video Disk Recorder - * - * See the README file for copyright information and how to reach the author. - * - */ - -#include "markad-standalone.h" - -bool SYSLOG=false; -cMarkAdStandalone *cmasta=NULL; -int SysLogLevel=2; - -void syslog_with_tid(int priority, const char *format, ...) -{ - va_list ap; - if (SYSLOG) - { - char fmt[255]; - snprintf(fmt, sizeof(fmt), "[%d] %s", getpid(), format); - va_start(ap, format); - vsyslog(priority, fmt, ap); - va_end(ap); - } - else - { - char fmt[255]; - snprintf(fmt, sizeof(fmt), "markad: [%d] %s", getpid(), format); - va_start(ap, format); - vprintf(fmt,ap); - va_end(ap); - printf("\n"); - fflush(stdout); - } -} - -void cMarkAdStandalone::AddStartMark() -{ - char *buf; - if (asprintf(&buf,"start of recording (0)")!=-1) - { - marks.Add(MT_COMMON,0,buf); - isyslog(buf); - free(buf); - } -} - -bool cMarkAdStandalone::CheckFirstMark() -{ - if (marksAligned) return true; - - // Check the second mark - clMark *second=marks.GetNext(0); - if (!second) return false; - - if ((second->type==MT_LOGOSTART) || (second->type==MT_BORDERSTART) || - (second->type==MT_CHANNELSTART)) - { - clMark *first=marks.Get(0); - if (first) marks.Del(first); - marksAligned=true; - } - - if ((second->type==MT_LOGOSTOP) || (second->type==MT_BORDERSTOP) || - (second->type==MT_CHANNELSTOP)) - { - marksAligned=true; - } - - // If we have an aspectchange, check the next aspectchange mark - // and the difference between - if ((second->type==MT_ASPECTCHANGE) && (macontext.Video.Info.FramesPerSecond>0)) - { - clMark *next=marks.GetNext(second->position,MT_ASPECTCHANGE); - if (next) - { - int MAXPOSDIFF=(int) (macontext.Video.Info.FramesPerSecond*60*13); - if ((next->position-second->position)>MAXPOSDIFF) - { - clMark *first=marks.Get(0); - if (first) marks.Del(first); - marksAligned=true; - } - } - } - return marksAligned; -} - -void cMarkAdStandalone::AddMark(MarkAdMark *Mark) -{ - if (!Mark) return; - if (!Mark->Type) return; - - if (Mark->Type==MT_LOGOSTART) - { - // check if last mark is an aspectratio change - clMark *prev=marks.GetLast(); - if ((prev) && (prev->type==MT_ASPECTCHANGE)) - { - if ((Mark->Position-prev->position)<20) - { - if (Mark->Comment) isyslog(Mark->Comment); - isyslog("aspectratio change in short distance, moving mark (%i->%i)",Mark->Position,prev->position); - marks.Add(MT_MOVED,prev->position,Mark->Comment); - return; - } - } - } - - if (((Mark->Type & 0xF0)==MT_LOGOCHANGE) && (macontext.Video.Info.FramesPerSecond>0)) - { - // check if the distance to the last mark is large enough! - clMark *prev=marks.GetLast(); - if ((prev) && ((prev->type & 0xF0)==MT_LOGOCHANGE)) - { - int MINMARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*60*2); - if ((Mark->Position-prev->position)<MINMARKDIFF) - { - if (Mark->Comment) isyslog(Mark->Comment); - isyslog("logo distance too short, deleting (%i,%i)",prev->position,Mark->Position); - marks.Del(prev); - return; - } - } - } - - if (((Mark->Type & 0xF0)==MT_BORDERCHANGE) && (Mark->Position>25000) && - (!macontext.Video.Options.IgnoreLogoDetection)) - { - isyslog("border change detected. logo detection disabled"); - macontext.Video.Options.IgnoreLogoDetection=true; - marks.Del(MT_LOGOSTART); - marks.Del(MT_LOGOSTOP); - } - - if ((((Mark->Type & 0xF0)==MT_CHANNELCHANGE) || (Mark->Type==MT_ASPECTCHANGE)) && - (Mark->Position>25000) && (bDecodeVideo)) - { - bool TurnOff=true; - if (Mark->Type==MT_ASPECTCHANGE) - { - if (marks.Count(MT_ASPECTCHANGE)<3) - { - TurnOff=false; - } - } - - if (Mark->Type==MT_CHANNELCHANGE) - { - if ((marks.Count(MT_CHANNELSTART)+marks.Count(MT_CHANNELSTOP))<3) - { - TurnOff=false; - } - } - - if (TurnOff) - { - isyslog("%s change detected. logo/border detection disabled", - Mark->Type==MT_ASPECTCHANGE ? "aspectratio" : "audio channel"); - - bDecodeVideo=false; - macontext.Video.Data.Valid=false; - marks.Del(MT_LOGOSTART); - marks.Del(MT_LOGOSTOP); - marks.Del(MT_BORDERSTART); - marks.Del(MT_BORDERSTOP); - } - } - CheckFirstMark(); - clMark *old=marks.Get(Mark->Position); - if (old) - { - // Aspect- / Channelchange wins over Logo/Border - if (((old->type & 0xF0)!=MT_ASPECTCHANGE) && ((old->type & 0xF0)!=MT_CHANNELCHANGE)) - { - if (Mark->Comment) isyslog(Mark->Comment); - marks.Add(Mark->Type,Mark->Position,Mark->Comment); - } - } - else - { - if (Mark->Comment) isyslog(Mark->Comment); - marks.Add(Mark->Type,Mark->Position,Mark->Comment); - } -} - -void cMarkAdStandalone::RateMarks() -{ - if (macontext.Info.Length) - { - if ((marks.Count()>3) && (macontext.Info.Length>30)) - { - int logomarks=marks.Count(MT_LOGOSTART) + marks.Count(MT_LOGOSTOP); - int audiomarks=marks.Count(MT_CHANNELSTART) + marks.Count(MT_CHANNELSTOP); - - // If we have logomarks or audiomarks get rid of the aspect changes, - // cause if we have a recording with (>=3) aspect changes the - // logomarks were already deleted in AddMark - if ((logomarks) || (audiomarks)) - { - marks.Del(MT_ASPECTCHANGE); - } - } - } - - // Check the first mark again - CheckFirstMark(); - - // TODO: more checks -} - -void cMarkAdStandalone::SaveFrame(int frame) -{ - if (!macontext.Video.Info.Width) return; - if (!macontext.Video.Data.Valid) return; - - FILE *pFile; - char szFilename[256]; - - // Open file - sprintf(szFilename, "/tmp/frame%06d.pgm", frame); - pFile=fopen(szFilename, "wb"); - if (pFile==NULL) - return; - - // Write header - fprintf(pFile, "P5\n%d %d\n255\n", macontext.Video.Data.PlaneLinesize[0], - macontext.Video.Info.Height); - - // Write pixel data - fwrite(macontext.Video.Data.Plane[0],1, - macontext.Video.Data.PlaneLinesize[0]*macontext.Video.Info.Height,pFile); - // Close file - fclose(pFile); -} - -void cMarkAdStandalone::CheckIndex(const char *Directory) -{ - // Here we check if the index is more - // advanced than our framecounter. - // If not we wait. If we wait too much, - // we discard this check... - -#define WAITTIME 10 - - if (!indexFile) return; - if (sleepcnt>=2) return; // we already slept too much - - bool notenough=true; - do - { - struct stat statbuf; - if (stat(indexFile,&statbuf)==-1) return; - - int maxframes=statbuf.st_size/8; - if (maxframes<(framecnt+200)) - { - if ((difftime(time(NULL),statbuf.st_mtime))>=10) return; // "old" file - marks.Save(Directory,macontext.Video.Info.FramesPerSecond,isTS); - sleep(WAITTIME); // now we sleep and hopefully the index will grow - waittime+=WAITTIME; - if (errno==EINTR) return; - sleepcnt++; - if (sleepcnt>=2) - { - esyslog("no new data after %i seconds, skipping wait!", - sleepcnt*WAITTIME); - notenough=false; // something went wrong? - } - } - else - { - sleepcnt=0; - notenough=false; - } - } - while (notenough); -} - -bool cMarkAdStandalone::ProcessFile(const char *Directory, int Number) -{ - if (!Directory) return false; - if (!Number) return false; - - CheckIndex(Directory); - if (abort) return false; - - const int datalen=385024; - uchar data[datalen]; - - char *fbuf; - if (isTS) - { - if (asprintf(&fbuf,"%s/%05i.ts",Directory,Number)==-1) return false; - } - else - { - if (asprintf(&fbuf,"%s/%03i.vdr",Directory,Number)==-1) return false; - } - - int f=open(fbuf,O_RDONLY); - free(fbuf); - if (f==-1) return false; - - int dataread; - dsyslog("processing file %05i",Number); - - while ((dataread=read(f,data,datalen))>0) - { - if (abort) break; - MarkAdMark *mark=NULL; - - if ((video_demux) && (video) && (streaminfo)) - { - uchar *pkt; - int pktlen; - - uchar *tspkt = data; - int tslen = dataread; - - while (tslen>0) - { - int len=video_demux->Process(macontext.Info.VPid,tspkt,tslen,&pkt,&pktlen); - if (len<0) - { - break; - } - else - { - if (pkt) - { - if (streaminfo->FindVideoInfos(&macontext,pkt,pktlen)) - { - if (!framecnt) - { - isyslog("%s %i%c",(macontext.Video.Info.Height>576) ? "HDTV" : "SDTV", - macontext.Video.Info.Height, - macontext.Video.Info.Interlaced ? 'i' : 'p'); - AddStartMark(); - } - //printf("%05i( %c )\n",framecnt,frametypes[macontext.Video.Info.Pict_Type]); - framecnt++; - if (macontext.Video.Info.Pict_Type==MA_I_TYPE) - { - lastiframe=iframe; - iframe=framecnt-1; - } - } - - bool dRes=true; - if ((decoder) && (bDecodeVideo)) dRes=decoder->DecodeVideo(&macontext,pkt,pktlen); - if (dRes) - { - if ((framecnt-iframe)<=3) - { - mark=video->Process(lastiframe); - AddMark(mark); - //SaveFrame(lastiframe); // TODO: JUST FOR DEBUGGING! - } - } - } - tspkt+=len; - tslen-=len; - } - } - } - - if ((ac3_demux) && (streaminfo) && (audio)) - { - uchar *pkt; - int pktlen; - - uchar *tspkt = data; - int tslen = dataread; - - while (tslen>0) - { - int len=ac3_demux->Process(macontext.Info.DPid,tspkt,tslen,&pkt,&pktlen); - if (len<0) - { - break; - } - else - { - if (pkt) - { - if (streaminfo->FindAC3AudioInfos(&macontext,pkt,pktlen)) - { - if ((!isTS) && (!noticeVDR_AC3)) - { - dsyslog("found AC3"); - if (mp2_demux) - { - delete mp2_demux; - mp2_demux=NULL; - } - noticeVDR_AC3=true; - } - mark=audio->Process(lastiframe); - AddMark(mark); - } - } - tspkt+=len; - tslen-=len; - } - } - } - - if ((mp2_demux) && (decoder) && (audio) && (bDecodeAudio)) - { - uchar *pkt; - int pktlen; - - uchar *tspkt = data; - int tslen = dataread; - - while (tslen>0) - { - int len=mp2_demux->Process(macontext.Info.APid,tspkt,tslen,&pkt,&pktlen); - if (len<0) - { - break; - } - else - { - if (pkt) - { - if (decoder->DecodeMP2(&macontext,pkt,pktlen)) - { - if ((!isTS) && (!noticeVDR_MP2)) - { - dsyslog("found MP2"); - noticeVDR_MP2=true; - } - mark=audio->Process(lastiframe); - AddMark(mark); - } - } - tspkt+=len; - tslen-=len; - } - } - } - - CheckIndex(Directory); - if (abort) - { - if (f!=-1) close(f); - return false; - } - } - close(f); - return true; -} - -void cMarkAdStandalone::Process(const char *Directory) -{ - if (abort) return; - - struct timeval tv1,tv2; - struct timezone tz; - - gettimeofday(&tv1,&tz); - - if (bBackupMarks) marks.Backup(Directory,isTS); - - for (int i=1; i<=MaxFiles; i++) - { - if (abort) break; - if (!ProcessFile(Directory,i)) - { - break; - } - } - if (abort) - { - isyslog("aborted"); - } - else - { - if (lastiframe) - { - MarkAdMark tempmark; - tempmark.Type=MT_COMMON; - tempmark.Position=lastiframe; - char *buf; - - if (asprintf(&buf,"stop of recording (%i)",lastiframe)!=-1) - { - tempmark.Comment=buf; - AddMark(&tempmark); - free(buf); - } - } - - gettimeofday(&tv2,&tz); - time_t sec; - suseconds_t usec; - sec=tv2.tv_sec-tv1.tv_sec; - usec=tv2.tv_usec-tv1.tv_usec; - if (usec<0) - { - usec+=1000000; - sec--; - } - RateMarks(); - if (marks.Save(Directory,macontext.Video.Info.FramesPerSecond,isTS)) - { - bool bIndexError=false; - if (marks.CheckIndex(Directory,isTS,&bIndexError)) - { - if (bIndexError) - { - if ((macontext.Info.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264) && (!isTS)) - { - esyslog("index doesn't match marks, sorry you're lost"); - } - else - { - esyslog("index doesn't match marks%s", - isTS ? ", please recreate it" : ", please run genindex"); - } - } - } - } - - double etime,ftime=0,ptime=0; - etime=sec+((double) usec/1000000)-waittime; - if (etime>0) ftime=framecnt/etime; - if (macontext.Video.Info.FramesPerSecond>0) - ptime=ftime/macontext.Video.Info.FramesPerSecond; - isyslog("processed time %.2fs, %i frames, %.1f fps, %.1f pps", - etime,framecnt,ftime,ptime); - - } -} - -bool cMarkAdStandalone::LoadInfo(const char *Directory) -{ - char *buf; - if (isTS) - { - if (asprintf(&buf,"%s/info",Directory)==-1) return false; - } - else - { - if (asprintf(&buf,"%s/info.vdr",Directory)==-1) return false; - } - - FILE *f; - f=fopen(buf,"r"); - if (!f) - { - free(buf); - return false; - } - - char *line=NULL; - size_t length; - while (getline(&line,&length,f)!=-1) - { - if (line[0]=='C') - { - int ntok=0; - char *str=line,*tok; - while ((tok=strtok(str," "))) - { - if (ntok==1) macontext.Info.ChannelID=strdup(tok); - ntok++; - str=NULL; - } - if (macontext.Info.ChannelID) - { - for (int i=0; i<(int) strlen(macontext.Info.ChannelID); i++) - { - if (macontext.Info.ChannelID[i]=='.') macontext.Info.ChannelID[i]='_'; - } - } - } - if (line[0]=='E') - { - int result=sscanf(line,"%*c %*i %*i %i %*i %*x",&macontext.Info.Length); - if (result==1) - { - macontext.Info.Length/=60; - } - else - { - macontext.Info.Length=0; - } - if ((bIgnoreAudioInfo) && (bIgnoreVideoInfo)) break; - } - if (line[0]=='X') - { - int stream=0,type=0; - char descr[256]=""; - int result=sscanf(line,"%*c %i %i %250c",&stream,&type,(char *) &descr); - if ((result!=0) && (result!=EOF)) - { - if ((stream==1) && (!bIgnoreVideoInfo)) - { - if ((type!=1) && (type!=5)) - { - // we dont have 4:3, so ignore AspectRatio-Changes - macontext.Video.Options.IgnoreAspectRatio=true; - isyslog("broadcasts aspectratio is not 4:3, disabling aspect ratio"); - } - } - - if ((stream==2) && (!bIgnoreAudioInfo)) - { - if (type==5) - { - // if we have DolbyDigital 2.0 disable AC3 - if (strchr(descr,'2')) - { - macontext.Info.DPid.Num=0; - isyslog("broadcast with DolbyDigital2.0, disabling AC3 decoding"); - } - // if we have DolbyDigital 5.1 disable video decoding - if (strchr(descr,'5')) - { - bDecodeVideo=false; - isyslog("broadcast with DolbyDigital5.1, disabling video decoding"); - } - - } - } - } - } - } - if (line) free(line); - - fclose(f); - free(buf); - if (!macontext.Info.ChannelID) - { - return false; - } - else - { - return true; - } -} - -bool cMarkAdStandalone::CheckTS(const char *Directory) -{ - MaxFiles=0; - isTS=false; - if (!Directory) return false; - char *buf; - if (asprintf(&buf,"%s/00001.ts",Directory)==-1) return false; - struct stat statbuf; - if (stat(buf,&statbuf)==-1) - { - if (errno!=ENOENT) - { - free(buf); - return false; - } - free(buf); - if (asprintf(&buf,"%s/001.vdr",Directory)==-1) return false; - if (stat(buf,&statbuf)==-1) - { - free(buf); - return false; - } - free(buf); - // .VDR detected - isTS=false; - MaxFiles=999; - return true; - } - free(buf); - // .TS detected - isTS=true; - MaxFiles=65535; - return true; -} - -bool cMarkAdStandalone::CheckVDRHD(const char *Directory) -{ - char *buf; - if (asprintf(&buf,"%s/001.vdr",Directory)==-1) return false; - - int fd=open(buf,O_RDONLY); - free(buf); - if (fd==-1) return false; - - uchar pes_buf[32]; - if (read(fd,pes_buf,sizeof(pes_buf))!=sizeof(pes_buf)) - { - close(fd); - return false; - } - close(fd); - - if ((pes_buf[0]==0) && (pes_buf[1]==0) && (pes_buf[2]==1) && ((pes_buf[3] & 0xF0)==0xE0)) - { - int payloadstart=9+pes_buf[8]; - if (payloadstart>23) return false; - uchar *start=&pes_buf[payloadstart]; - if ((start[0]==0) && (start[1]==0) && (start[2]==1) && (start[5]==0) && (start[6]==0) - && (start[7]==0) && (start[8]==1)) - { - return true; - } - } - return false; -} - -bool cMarkAdStandalone::CheckPATPMT(const char *Directory) -{ - char *buf; - if (asprintf(&buf,"%s/00001.ts",Directory)==-1) return false; - - int fd=open(buf,O_RDONLY); - free(buf); - if (fd==-1) return false; - - uchar patpmt_buf[564]; - uchar *patpmt; - - if (read(fd,patpmt_buf,sizeof(patpmt_buf))!=sizeof(patpmt_buf)) - { - close(fd); - return false; - } - close(fd); - patpmt=patpmt_buf; - - if ((patpmt[0]==0x47) && ((patpmt[1] & 0x5F)==0x40) && (patpmt[2]==0x11) && - ((patpmt[3] & 0x10)==0x10)) patpmt+=188; // skip SDT - - // some checks - if ((patpmt[0]!=0x47) || (patpmt[188]!=0x47)) return false; // no TS-Sync - if (((patpmt[1] & 0x5F)!=0x40) && (patpmt[2]!=0)) return false; // no PAT - if ((patpmt[3] & 0x10)!=0x10) return false; // PAT not without AFC - if ((patpmt[191] & 0x10)!=0x10) return false; // PMT not without AFC - struct PAT *pat = (struct PAT *) &patpmt[5]; - - // more checks - if (pat->reserved1!=3) return false; // is always 11 - if (pat->reserved3!=7) return false; // is always 111 - - int pid=pat->pid_L+(pat->pid_H<<8); - int pmtpid=((patpmt[189] & 0x1f)<<8)+patpmt[190]; - if (pid!=pmtpid) return false; // pid in PAT differs from pid in PMT - - struct PMT *pmt = (struct PMT *) &patpmt[193]; - - // still more checks - if (pmt->reserved1!=3) return false; // is always 11 - if (pmt->reserved2!=3) return false; // is always 11 - if (pmt->reserved3!=7) return false; // is always 111 - if (pmt->reserved4!=15) return false; // is always 1111 - - if ((pmt->program_number_H!=pat->program_number_H) || - (pmt->program_number_L!=pat->program_number_L)) return false; - - int desc_len=(pmt->program_info_length_H<<8)+pmt->program_info_length_L; - if (desc_len>166) return false; // beyond patpmt buffer - - int section_end = 196+(pmt->section_length_H<<8)+pmt->section_length_L; - section_end-=4; // we don't care about the CRC32 - if (section_end>376) return false; //beyond patpmt buffer - - int i=205+desc_len; - - while (i<section_end) - { - struct ES_DESCRIPTOR *es=NULL; - struct STREAMINFO *si = (struct STREAMINFO *) &patpmt[i]; - int esinfo_len=(si->ES_info_length_H<<8)+si->ES_info_length_L; - if (esinfo_len) - { - es = (struct ES_DESCRIPTOR *) &patpmt[i+sizeof(struct STREAMINFO)]; - } - - // oh no -> more checks! - if (si->reserved1!=7) return false; - if (si->reserved2!=15) return false; - - int pid=(si->PID_H<<8)+si->PID_L; - - switch (si->stream_type) - { - case 0x1: - case 0x2: - macontext.Info.VPid.Type=MARKAD_PIDTYPE_VIDEO_H262; - // just use the first pid - if (!macontext.Info.VPid.Num) macontext.Info.VPid.Num=pid; - break; - - case 0x3: - case 0x4: - // just use the first pid - if (!macontext.Info.APid.Num) macontext.Info.APid.Num=pid; - break; - - case 0x6: - if (es) - { - if (es->Descriptor_Tag==0x6A) macontext.Info.DPid.Num=pid; - } - break; - - case 0x1b: - macontext.Info.VPid.Type=MARKAD_PIDTYPE_VIDEO_H264; - // just use the first pid - if (!macontext.Info.VPid.Num) macontext.Info.VPid.Num=pid; - break; - } - - i+=(sizeof(struct STREAMINFO)+esinfo_len); - } - - return true; -} - -bool cMarkAdStandalone::CreatePidfile(const char *Directory) -{ - char *buf; - if (asprintf(&buf,"%s/markad.pid",Directory)==-1) return false; - - // check for other running markad process - FILE *oldpid=fopen(buf,"r"); - if (oldpid) - { - // found old pidfile, check if it's still running - int pid; - if (fscanf(oldpid,"%i\n",&pid)==1) - { - char procname[256]=""; - snprintf(procname,sizeof(procname),"/proc/%i",pid); - struct stat statbuf; - if (stat(procname,&statbuf)!=-1) - { - // found another, running markad - isyslog("another instance is running on this recording"); - abort=duplicate=true; - } - } - fclose(oldpid); - } - if (duplicate) return false; - - FILE *pidfile=fopen(buf,"w+"); - - if (getuid()==0 || geteuid()!=0) - { - // if we are root, set fileowner to owner of 001.vdr/00001.ts file - char *spath=NULL; - if (asprintf(&spath,"%s/%s",Directory,isTS ? "00001.ts" : "001.vdr")!=-1) - { - struct stat statbuf; - if (!stat(spath,&statbuf)) - { - chown(buf,statbuf.st_uid, statbuf.st_gid); - } - free(spath); - } - } - - free(buf); - if (!pidfile) return false; - fprintf(pidfile,"%i\n",(int) getpid()); - fflush(pidfile); - fclose(pidfile); - return true; -} - -void cMarkAdStandalone::RemovePidfile(const char *Directory) -{ - char *buf; - if (asprintf(&buf,"%s/markad.pid",Directory)!=-1) - { - unlink(buf); - free(buf); - } -} - -const char cMarkAdStandalone::frametypes[8]={'?','I','P','B','D','S','s','b'}; - -cMarkAdStandalone::cMarkAdStandalone(const char *Directory, bool BackupMarks, int LogoExtraction, - int LogoWidth, int LogoHeight, bool DecodeVideo, - bool DecodeAudio, bool IgnoreVideoInfo, bool IgnoreAudioInfo, - const char *LogoDir, const char *MarkFileName, bool ASD, - bool noPid) -{ - directory=Directory; - abort=false; - - noticeVDR_MP2=false; - noticeVDR_AC3=false; - - sleepcnt=0; - waittime=0; - duplicate=false; - marksAligned=false; - - memset(&macontext,0,sizeof(macontext)); - macontext.LogoDir=(char *) LogoDir; - macontext.Options.LogoExtraction=LogoExtraction; - macontext.Options.LogoWidth=LogoWidth; - macontext.Options.LogoHeight=LogoHeight; - macontext.Audio.Options.AudioSilenceDetection=ASD; - - bDecodeVideo=DecodeVideo; - bDecodeAudio=DecodeAudio; - bIgnoreAudioInfo=IgnoreAudioInfo; - bIgnoreVideoInfo=IgnoreVideoInfo; - - bBackupMarks=BackupMarks; - - macontext.Info.DPid.Type=MARKAD_PIDTYPE_AUDIO_AC3; - macontext.Info.APid.Type=MARKAD_PIDTYPE_AUDIO_MP2; - - isyslog("starting v%s",VERSION); - isyslog("on %s",Directory); - - if (!bDecodeAudio) - { - isyslog("audio decoding disabled by user"); - } - if (!bDecodeVideo) - { - isyslog("video decoding disabled by user"); - } - if (bIgnoreAudioInfo) - { - isyslog("audio info usage disabled by user"); - } - if (bIgnoreVideoInfo) - { - isyslog("video info usage disabled by user"); - } - - if (LogoExtraction!=-1) - { - // just to be sure extraction works - bDecodeVideo=true; - bIgnoreAudioInfo=true; - bIgnoreVideoInfo=true; - } - - if (!CheckTS(Directory)) - { - video_demux=NULL; - ac3_demux=NULL; - mp2_demux=NULL; - decoder=NULL; - video=NULL; - audio=NULL; - return; - } - - if (!noPid) - { - CreatePidfile(Directory); - if (abort) - { - video_demux=NULL; - ac3_demux=NULL; - mp2_demux=NULL; - decoder=NULL; - video=NULL; - audio=NULL; - return; - } - } - - if (isTS) - { - if (!CheckPATPMT(Directory)) - { - esyslog("no PAT/PMT found -> nothing to process"); - abort=true; - } - if (!macontext.Audio.Options.AudioSilenceDetection) - { - macontext.Info.APid.Num=0; - } - if (asprintf(&indexFile,"%s/index",Directory)==-1) indexFile=NULL; - } - else - { - if (macontext.Audio.Options.AudioSilenceDetection) - { - macontext.Info.APid.Num=-1; - } - macontext.Info.DPid.Num=-1; - macontext.Info.VPid.Num=-1; - - if (CheckVDRHD(Directory)) - { - macontext.Info.VPid.Type=MARKAD_PIDTYPE_VIDEO_H264; - } - else - { - macontext.Info.VPid.Type=MARKAD_PIDTYPE_VIDEO_H262; - } - if (asprintf(&indexFile,"%s/index.vdr",Directory)==-1) indexFile=NULL; - } - - if (!LoadInfo(Directory)) - { - if (bDecodeVideo) - { - esyslog("failed loading info - logo %s disabled", - (LogoExtraction!=-1) ? "extraction" : "detection"); - } - } - - if (MarkFileName[0]) marks.SetFileName(MarkFileName); - - if (macontext.Info.VPid.Num) - { - if (isTS) - { - dsyslog("using %s-video (0x%04x)", - macontext.Info.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264 ? "H264": "H262", - macontext.Info.VPid.Num); - } - else - { - dsyslog("using %s-video", - macontext.Info.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264 ? "H264": "H262"); - } - video_demux = new cMarkAdDemux(); - } - else - { - video_demux=NULL; - } - - if (macontext.Info.APid.Num) - { - if (macontext.Info.APid.Num!=-1) - dsyslog("using MP2 (0x%04x)",macontext.Info.APid.Num); - mp2_demux = new cMarkAdDemux(); - } - else - { - mp2_demux=NULL; - } - - if (macontext.Info.DPid.Num) - { - if (macontext.Info.DPid.Num!=-1) - dsyslog("using AC3 (0x%04x)",macontext.Info.DPid.Num); - ac3_demux = new cMarkAdDemux(); - } - else - { - ac3_demux=NULL; - } - - if (!abort) - { - decoder = new cMarkAdDecoder(macontext.Info.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264, - macontext.Info.APid.Num!=0,macontext.Info.DPid.Num!=0); - video = new cMarkAdVideo(&macontext); - audio = new cMarkAdAudio(&macontext); - streaminfo = new cMarkAdStreamInfo; - if (macontext.Info.ChannelID) - dsyslog("channel %s",macontext.Info.ChannelID); - } - else - { - decoder=NULL; - video=NULL; - audio=NULL; - streaminfo=NULL; - } - - framecnt=0; - lastiframe=0; - iframe=0; -} - -cMarkAdStandalone::~cMarkAdStandalone() -{ - if (macontext.Info.ChannelID) free(macontext.Info.ChannelID); - if (indexFile) free(indexFile); - - 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 (streaminfo) delete streaminfo; - - if ((directory) && (!duplicate)) RemovePidfile(directory); -} - -bool isnumber(const char *s) -{ - while (*s) - { - if (!isdigit(*s)) - return false; - s++; - } - return true; -} - -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" - "-d --disable=<option>\n" - " <option> 1 = disable video 2 = disable audio\n" - " 3 = disable video and audio\n" - "-i --ignoreinfo=<info>\n" - " ignores hints from info(.vdr) file\n" - " <info> 1 = ignore audio info 2 = ignore video info\n" - " 3 = ignore video and audio info\n" - "-l --logocachedir\n" - " directory where logos stored, default /var/lib/markad\n" - "-p, --priority level=<priority>\n" - " priority-level of markad when running in background\n" - " <-20...19> default 19\n" - "-v, --verbose\n" - " increments loglevel by one, can be given multiple times\n" - "-B --backupmarks\n" - " make a backup of existing marks\n" - "-L --extractlogo=<direction>[,width[,height]]\n" - " extracts logo to /tmp as pgm files (must be renamed)\n" - " <direction> 0 = top left, 1 = top right\n" - " 2 = bottom left, 3 = bottom right\n" - " [width] range from 50 to %3i, default %3i (SD)\n" - " default %3i (HD)\n" - " [height] range from 20 to %3i, default %3i\n" - "-O, --OSD\n" - " markad sends an OSD-Message for start and end\n" - "-V --version\n" - " print version-info and exit\n" - " --asd\n" - " enable audio silence detecion\n" - " --markfile=<markfilename>\n" - " set a different markfile-name\n" - " --online[=1|2] (default is 1)\n" - " start markad immediately when called with \"before\" as cmd\n" - " if online is 1, markad starts online for live-recordings\n" - " only, online=2 starts markad online for every recording\n" - " live-recordings are identified by having a '@' in the\n" - " filename so the entry 'Mark instant recording' in the menu\n" - " 'Setup - Recording' of the vdr should be set to 'yes'\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", - LOGO_MAXWIDTH,LOGO_DEFWIDTH,LOGO_DEFHDWIDTH, - LOGO_MAXHEIGHT,LOGO_DEFHEIGHT - ); - return -1; -} - -void signal_handler(int sig) -{ - if (sig==SIGUSR1) - { - // TODO: what we are supposed to do? - } - else - { - if (cmasta) - { - cmasta->SetAbort(); - } - } -} - -int main(int argc, char *argv[]) -{ - int c; - bool bAfter=false,bBefore=false,bEdited=false; - bool bFork=false,bNice=false,bImmediateCall=false; - bool bASD=false; - int niceLevel = 19; - char *recDir=NULL; - char *tok,*str; - int ntok; - int logoExtraction=-1; - int logoWidth=-1; - int logoHeight=-1; - bool bBackupMarks=false,bNoPid=false; - char markFileName[1024]=""; - char logoDirectory[1024]=""; - bool bDecodeVideo=true; - bool bDecodeAudio=true; - bool bIgnoreAudioInfo=false; - bool bIgnoreVideoInfo=false; - int online=1; - - strcpy(logoDirectory,"/var/lib/markad"); - - while (1) - { - int option_index = 0; - static struct option long_options[] = - { - {"ac3",0,0,'a' - }, - {"background", 0, 0, 'b'}, - {"comments", 0, 0, 'c'}, - {"disable", 1, 0, 'd'}, - {"ignoreinfo", 1, 0, 'i' }, - {"jumplogo",0,0,'j'}, - {"logocachedir", 1, 0, 'l'}, - {"nelonen",0,0,'n'}, - {"overlap",0,0,'o' }, - {"priority",1,0,'p'}, - {"statisticfile",1,0,'s'}, - {"verbose", 0, 0, 'v'}, - - {"asd",0,0,6}, - {"loglevel",1,0,2}, - {"markfile",1,0,1}, - {"nopid",0,0,5}, - {"online",2,0,4}, - {"pass3only",0,0,7}, - {"testmode",0,0,3}, - - {"backupmarks", 0, 0, 'B'}, - {"scenechangedetection", 0, 0, 'C'}, - {"extractlogo", 1, 0, 'L'}, - {"OSD",0,0,'O' }, - {"savelogo", 0, 0, 'S'}, - {"version", 0, 0, 'V'}, - - {0, 0, 0, 0} - }; - - c = getopt_long (argc, argv, "abcd:i:jl:nop:s:vBCL:O:SV", - long_options, &option_index); - if (c == -1) - break; - - switch (c) - { - - case 'a': - // --ac3 - break; - - case 'b': - // --background - bFork = SYSLOG = true; - break; - - case 'c': - // --comments - break; - - case 'd': - // --disable - switch (atoi(optarg)) - { - case 1: - bDecodeVideo=false; - break; - case 2: - bDecodeAudio=false; - break; - case 3: - bDecodeVideo=false; - bDecodeAudio=false; - break; - default: - fprintf(stderr, "markad: invalid disable option: %s\n", optarg); - return 2; - break; - } - break; - - case 'i': - // --ignoreinfo - switch (atoi(optarg)) - { - case 1: - bIgnoreAudioInfo=true; - break; - case 2: - bIgnoreVideoInfo=true; - break; - case 3: - bIgnoreVideoInfo=true; - bIgnoreAudioInfo=true; - break; - default: - fprintf(stderr, "markad: invalid ignoreinfo option: %s\n", optarg); - return 2; - break; - } - break; - - case 'j': - // --jumplogo - break; - - case 'l': - strncpy(logoDirectory,optarg,1024); - logoDirectory[1023]=0; - break; - - case 'n': - // --nelonen - break; - - case 'o': - // --overlap - break; - - case 'p': - // --priority - if (isnumber(optarg) || *optarg=='-') - niceLevel = atoi(optarg); - else - { - fprintf(stderr, "markad: invalid priority level: %s\n", optarg); - return 2; - } - bNice = true; - break; - - case 's': - // --statisticfile - break; - - case 'v': - // --verbose - SysLogLevel++; - if (SysLogLevel>10) SysLogLevel=10; - break; - - case 'B': - // --backupmarks - bBackupMarks=true; - break; - - case 'C': - // --scenechangedetection - break; - - case 'L': - // --extractlogo - str=optarg; - ntok=0; - while (tok=strtok(str,",")) - { - switch (ntok) - { - case 0: - logoExtraction=atoi(tok); - if ((logoExtraction<0) || (logoExtraction>3)) - { - fprintf(stderr, "markad: invalid extractlogo value: %s\n", tok); - return 2; - } - break; - - case 1: - logoWidth=atoi(tok); - if ((logoWidth<50) || (logoWidth>LOGO_MAXWIDTH)) - { - fprintf(stderr, "markad: invalid width value: %s\n", tok); - return 2; - } - break; - - case 2: - logoHeight=atoi(tok); - if ((logoHeight<20) || (logoHeight>LOGO_MAXHEIGHT)) - { - fprintf(stderr, "markad: invalid height value: %s\n", tok); - return 2; - } - break; - - default: - break; - } - str=NULL; - ntok++; - } - break; - - case 'O': - // --OSD - break; - - case 'S': - // --savelogo - 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 - strncpy(markFileName,optarg,1024); - markFileName[1023]=0; - break; - - case 2: // --loglevel - SysLogLevel=atoi(optarg); - if (SysLogLevel>10) SysLogLevel=10; - if (SysLogLevel<0) SysLogLevel=2; - break; - - case 3: // --testmode - break; - - case 4: // --online - online=atoi(optarg); - if ((online!=1) && (online!=2)) - { - fprintf(stderr, "markad: invalid online value: %s\n", optarg); - return 2; - } - break; - - case 5: // --nopid - bNoPid=true; - break; - - case 6: // --asd - bASD=true; - 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 = SYSLOG = true; - } - else if (strcmp(argv[optind], "before" ) == 0 ) - { - bBefore = bFork = bNice = SYSLOG = 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 ) - { - bImmediateCall = true; - } - else - { - if ( strstr(argv[optind],".rec") != NULL ) - recDir = argv[optind]; - } - optind++; - } - } - - // do nothing if called from vdr before/after the video is cutted - if ((bAfter) && (online)) return 0; - if (bBefore) - { - if (!online) return 0; - if ((online==1) && (!strchr(recDir,'@'))) return 0; - } - if (bEdited) return 0; - - // we can run, if one of bImmediateCall, bAfter, bBefore or bNice is true - // and recDir is given - if ( (bImmediateCall || bBefore || 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) - { - char *err=strerror(errno); - fprintf(stderr, "%s\n",err); - esyslog("fork ERROR: %s",err); - return 2; - } - if (pid != 0) - { - isyslog("forked to pid %d",pid); - return 0; // initial program immediately returns - } - } - if ( bFork ) - { - isyslog("(forked) pid %d", getpid()); - if (chdir("/")==-1) - { - perror("chdir"); - exit(EXIT_FAILURE); - } - 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); - } - - 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 - - // should we renice ? - if ( bNice ) - { - if (setpriority(PRIO_PROCESS,0,niceLevel)==-1) - { - esyslog("failed to set nice to %d",niceLevel); - } - } - - if (bBefore) sleep(10); - - // 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; - } - - cmasta = new cMarkAdStandalone(recDir,bBackupMarks, logoExtraction, logoWidth, logoHeight, - bDecodeVideo,bDecodeAudio,bIgnoreVideoInfo,bIgnoreAudioInfo, - logoDirectory,markFileName,bASD,bNoPid); - if (!cmasta) return -1; - - // ignore some signals - signal(SIGHUP, SIG_IGN); - - // catch some signals - signal(SIGINT, signal_handler); - signal(SIGTERM, signal_handler); - signal(SIGUSR1, signal_handler); - - cmasta->Process(recDir); - delete cmasta; - return 0; - } - - return usage(); -} |
