diff options
author | Jochen Dolze <vdr@dolze.de> | 2010-03-16 19:46:20 +0100 |
---|---|---|
committer | Jochen Dolze <vdr@dolze.de> | 2010-03-16 19:46:20 +0100 |
commit | 8c15ec9bc01a96e707daeef2f0955bdc97867201 (patch) | |
tree | 0ffb3dc724a629fa9f1e35ef8171b14ce7d3dd6f | |
parent | 6d7569aec72f444763474efb420ae403f90e36ae (diff) | |
download | vdr-plugin-markad-8c15ec9bc01a96e707daeef2f0955bdc97867201.tar.gz vdr-plugin-markad-8c15ec9bc01a96e707daeef2f0955bdc97867201.tar.bz2 |
Added creation of mark filesv0.0.6
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | global.h | 3 | ||||
-rw-r--r-- | markad-standalone.cpp | 154 | ||||
-rw-r--r-- | markad-standalone.h | 20 | ||||
-rw-r--r-- | marks.cpp | 341 | ||||
-rw-r--r-- | marks.h | 109 | ||||
-rw-r--r-- | version.h | 2 |
7 files changed, 584 insertions, 47 deletions
@@ -55,7 +55,7 @@ LIBS-CMD += $(shell $(PKG-CONFIG) --libs $(PKG-LIBS)) ### The object files (add further files here): -OBJS-CMD = markad-standalone.o decoder.o +OBJS-CMD = markad-standalone.o decoder.o marks.o OBJS-COMMON = streaminfo.o video.o audio.o demux.o queue.o vdr2pkt.o ts2pkt.o pes2es.o OBJS = $(PLUGIN).o recv.o status.o $(OBJS-COMMON) @@ -17,11 +17,10 @@ typedef unsigned char uchar; #define MA_I_TYPE 1 #define MA_P_TYPE 2 #define MA_B_TYPE 3 -#define MA_S_TYPE 4 +#define MA_D_TYPE 4 #define MA_SI_TYPE 5 #define MA_SP_TYPE 6 #define MA_BI_TYPE 7 -#define MA_D_TYPE 80 typedef struct MarkAdMark { diff --git a/markad-standalone.cpp b/markad-standalone.cpp index 95a6bf4..7929738 100644 --- a/markad-standalone.cpp +++ b/markad-standalone.cpp @@ -3,23 +3,12 @@ * * See the README file for copyright information and how to reach the author. * - * $Id$ */ #include "markad-standalone.h" cMarkAdStandalone *cmasta=NULL; int SysLogLevel=2; -char markFileName[1024]=""; -char logoDirectory[1024]=""; -int logoExtraction=-1; -int logoWidth=-1; -int logoHeight=-1; -bool bDecodeVideo=true; -bool bDecodeAudio=true; -bool bBackupMarks=false; -bool bIgnoreAudioInfo=false; -bool bIgnoreVideoInfo=false; void syslog_with_tid(int priority, const char *format, ...) { @@ -38,35 +27,53 @@ void syslog_with_tid(int priority, const char *format, ...) #endif } -char *cMarkAdStandalone::IndexToHMSF(int Index) +void cMarkAdStandalone::AddStartMark() { - if (macontext.Video.Info.FramesPerSecond==0.0) return NULL; - char *buf; - double Seconds; - int f = int(modf((Index+0.5)/macontext.Video.Info.FramesPerSecond,&Seconds)* - macontext.Video.Info.FramesPerSecond+1); - int s = int(Seconds); - int m = s / 60 % 60; - int h = s / 3600; - s %= 60; - if (asprintf(&buf,"%d:%02d:%02d.%02d",h,m,s,f)==-1) return NULL; - return buf; + if (!marks.Count()) + { + char *buf; + if (asprintf(&buf,"start of recording (0)")!=-1) + { + marks.Add(0,buf); + isyslog("markad [%i]: %s",recvnumber,buf); + free(buf); + } + } + else + { + marksAligned=true; + } } void cMarkAdStandalone::AddMark(MarkAdMark *Mark) { if (!Mark) return; + if (Mark->Position<1) return; - if (Mark->Comment) + marks.Add(Mark->Position,Mark->Comment); + + if (!marksAligned) { - char *buf=IndexToHMSF(Mark->Position); - if (buf) + clMark *prevmark=marks.GetPrev(Mark->Position); + if (!prevmark) return; + if (prevmark->position==0) return; + + int MAXPOSDIFF = (int) (macontext.Video.Info.FramesPerSecond*60*13); // = 13 min + + if (abs(Mark->Position-prevmark->position)>MAXPOSDIFF) { - fprintf(stderr,"%s %s\n",buf,Mark->Comment); - free(buf); + clMark *firstmark=marks.Get(0); + if (firstmark) + { + marks.Del(firstmark); + marksAligned=true; + } + } + else + { + marksAligned=true; } } -// TODO: Implement creating marks/marks.vdr! } @@ -117,7 +124,7 @@ bool cMarkAdStandalone::ProcessFile(const char *Directory, int Number) free(fbuf); if (f==-1) return false; - int dataread,lastiframe=0; + int dataread; dsyslog("markad [%i]: processing file %05i",recvnumber,Number); while ((dataread=read(f,data,datalen))>0) @@ -146,7 +153,18 @@ bool cMarkAdStandalone::ProcessFile(const char *Directory, int Number) { if (streaminfo->FindVideoInfos(&macontext,pkt,pktlen)) { - //printf("%05i( %s )\n",framecnt,(macontext.Video.Info.Pict_Type==MA_I_TYPE) ? "I" : "-"); + if (!framecnt) + { + if (!marks.Load(Directory,macontext.Video.Info.FramesPerSecond,isTS)) + { + AddStartMark(); + } + else + { + marksAligned=true; + } + } + //printf("%05i( %c )\n",framecnt,frametypes[macontext.Video.Info.Pict_Type]); framecnt++; } @@ -281,6 +299,21 @@ void cMarkAdStandalone::Process(const char *Directory) } else { + if (lastiframe) + { + MarkAdMark tempmark; + tempmark.Position=lastiframe; + char *buf; + + if (asprintf(&buf,"stop of recording (%i)",lastiframe)!=-1) + { + tempmark.Comment=buf; + AddMark(&tempmark); + isyslog("markad [%i]: %s",recvnumber,buf); + free(buf); + } + } + gettimeofday(&tv2,&tz); long sec,usec; sec=tv2.tv_sec-tv1.tv_sec; @@ -290,6 +323,17 @@ void cMarkAdStandalone::Process(const char *Directory) usec+=1000000; sec--; } + + bool bIndexError; + if (marks.Save(Directory,macontext.Video.Info.FramesPerSecond,isTS,bBackupMarks,&bIndexError)) + { + if (bIndexError) + { + esyslog("markad [%i]: index doesn't match marks%s",recvnumber, + isTS ? ", please report this" : ", please run genindex"); + } + } + double etime,ftime=0,ptime=0; etime=sec+((double) usec/1000000); if (etime>0) ftime=framecnt/etime; @@ -297,6 +341,7 @@ void cMarkAdStandalone::Process(const char *Directory) ptime=ftime/macontext.Video.Info.FramesPerSecond; isyslog("markad [%i]: elapsed time %.2fs, %i frames, %.1f fps, %.1f pps",recvnumber, etime,framecnt,ftime,ptime); + } } @@ -565,8 +610,13 @@ bool cMarkAdStandalone::CheckPATPMT(const char *Directory) return true; } -cMarkAdStandalone::cMarkAdStandalone(const char *Directory) +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) { + const char frametypes[8]={'?','I','P','B','D','S','s','b'}; + recvnumber=255; abort=false; @@ -574,12 +624,19 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory) noticeVDR_AC3=false; memset(&macontext,0,sizeof(macontext)); - macontext.LogoDir=logoDirectory; - macontext.StandAlone.LogoExtraction=logoExtraction; - macontext.StandAlone.LogoWidth=logoWidth; - macontext.StandAlone.LogoHeight=logoHeight; + macontext.LogoDir=(char *) LogoDir; + macontext.StandAlone.LogoExtraction=LogoExtraction; + macontext.StandAlone.LogoWidth=LogoWidth; + macontext.StandAlone.LogoHeight=LogoHeight; + + bDecodeVideo=DecodeVideo; + bDecodeAudio=DecodeAudio; + bIgnoreAudioInfo=IgnoreAudioInfo; + bIgnoreVideoInfo=IgnoreVideoInfo; + + bBackupMarks=BackupMarks; - if (logoExtraction!=-1) + if (LogoExtraction!=-1) { // just to be sure extraction works bDecodeVideo=true; @@ -628,7 +685,6 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory) abort=true; } macontext.General.APid.Num=0; - if (!markFileName[0]) strcpy(markFileName,"marks"); } else { @@ -644,8 +700,6 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory) { macontext.General.VPid.Type=MARKAD_PIDTYPE_VIDEO_H262; } - - if (!markFileName[0]) strcpy(markFileName,"marks.vdr"); } if (!LoadInfo(Directory)) @@ -653,6 +707,8 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory) if (bDecodeVideo) esyslog("markad [%i]: failed loading info - logo detection impossible",recvnumber); } + if (MarkFileName[0]) marks.SetFileName(MarkFileName); + if (macontext.General.VPid.Num) { if (isTS) @@ -711,7 +767,9 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory) streaminfo=NULL; } + marksAligned=false; framecnt=0; + lastiframe=0; } cMarkAdStandalone::~cMarkAdStandalone() @@ -760,7 +818,7 @@ int usage() "-v, --verbose\n" " increments loglevel by one, can be given multiple times\n" "-B --backupmarks\n" - " make a backup of the existing marks\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" @@ -810,6 +868,16 @@ int main(int argc, char *argv[]) char *recDir=NULL; char *tok,*str; int ntok; + int logoExtraction=-1; + int logoWidth=-1; + int logoHeight=-1; + bool bBackupMarks=false; + char markFileName[1024]=""; + char logoDirectory[1024]=""; + bool bDecodeVideo=true; + bool bDecodeAudio=true; + bool bIgnoreAudioInfo=false; + bool bIgnoreVideoInfo=false; strcpy(logoDirectory,"/var/lib/markad"); @@ -1212,7 +1280,9 @@ int main(int argc, char *argv[]) return -1; } - cmasta = new cMarkAdStandalone(recDir); + cmasta = new cMarkAdStandalone(recDir,bBackupMarks, logoExtraction, logoWidth, logoHeight, + bDecodeVideo,bDecodeAudio,bIgnoreVideoInfo,bIgnoreAudioInfo, + logoDirectory,markFileName); if (!cmasta) return -1; // ignore some signals diff --git a/markad-standalone.h b/markad-standalone.h index 25f8fc9..f84ec38 100644 --- a/markad-standalone.h +++ b/markad-standalone.h @@ -25,6 +25,7 @@ #include "audio.h" #include "streaminfo.h" #include "version.h" +#include "marks.h" class cMarkAdStandalone { @@ -140,6 +141,8 @@ unsigned Descriptor_Length: 8; }; + static const char frametypes[8]; + cMarkAdDemux *video_demux; cMarkAdDemux *ac3_demux; cMarkAdDemux *mp2_demux; @@ -153,14 +156,25 @@ unsigned Descriptor_Length: bool isTS; int MaxFiles; + int lastiframe; int framecnt; bool abort; bool noticeVDR_MP2; bool noticeVDR_AC3; + bool bDecodeVideo; + bool bDecodeAudio; + bool bIgnoreAudioInfo; + bool bIgnoreVideoInfo; + void SaveFrame(int Frame); + + bool marksAligned; + bool bBackupMarks; + clMarks marks; char *IndexToHMSF(int Index); + void AddStartMark(); void AddMark(MarkAdMark *Mark); bool CheckVDRHD(const char *Directory); @@ -175,7 +189,11 @@ public: abort=true; } void Process(const char *Directory); - cMarkAdStandalone(const char *Directory); + 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); + ~cMarkAdStandalone(); }; diff --git a/marks.cpp b/marks.cpp new file mode 100644 index 0000000..4de8c0e --- /dev/null +++ b/marks.cpp @@ -0,0 +1,341 @@ +/* + * marks.cpp: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + */ + +#include "marks.h" + +clMark::clMark(int Position, const char *Comment) +{ + position=Position; + if (Comment) + { + comment=strdup(Comment); + } + else + { + comment=NULL; + } + prev=NULL; + next=NULL; +} + +clMark::~clMark() +{ + if (comment) free(comment); +} + +// -------------------------------------------------------------------------- + +clMarks::~clMarks() +{ + clMark *next,*mark=first; + while (mark) + { + next=mark->Next(); + Del(mark); + mark=next; + } + +} + +void clMarks::Del(clMark *Mark) +{ + if (!Mark) return; + if (Mark->Next()) + { + if (Mark->Prev()) + { + // there is a next and prev object + Mark->Prev()->SetNext(Mark->Next()); + Mark->Next()->SetPrev(Mark->Prev()); + } + else + { + // just a next, so we are number 1 + Mark->Next()->SetPrev(NULL); + first=Mark->Next(); + } + } + else + { + // we are the last + first=NULL; + } + delete Mark; + count--; +} + +clMark *clMarks::Get(int Position) +{ + if (!first) return NULL; // no elements yet + + clMark *mark=first; + while (mark) + { + if (Position==mark->position) break; + mark=mark->Next(); + } + return mark; +} + +clMark *clMarks::GetPrev(int Position) +{ + if (!first) return NULL; // no elements yet + + clMark *mark=first; + while (mark) + { + if (mark->position>=Position) break; + mark=mark->Next(); + } + return mark->Prev(); +} + +clMark *clMarks::GetNext(int Position) +{ + if (!first) return NULL; // no elements yet + + clMark *mark=first; + while (mark) + { + if (Position>mark->position) break; + mark=mark->Next(); + } + return mark->Next(); +} + +clMark *clMarks::Add(int Position,const char *Comment) +{ + clMark *newmark; + if ((newmark=Get(Position))) + { + if ((newmark->comment) && (Comment)) + { + free(newmark->comment); + newmark->comment=strdup(Comment); + } + return newmark; + } + + newmark=new clMark(Position,Comment); + if (!newmark) return NULL; + + if (!first) + { + //first element + first=newmark; + count++; + return newmark; + } + else + { + clMark *mark=first; + while (mark) + { + if (!mark->Next()) + { + if (Position>mark->position) + { + // add as last element + newmark->Set(mark,NULL); + mark->SetNext(newmark); + break; + } + else + { + // add before + if (!mark->Prev()) + { + // add as first element + newmark->Set(NULL,mark); + mark->SetPrev(newmark); + first=newmark; + break; + } + else + { + newmark->Set(mark->Prev(),mark); + mark->SetPrev(newmark); + break; + } + } + } + else + { + if ((Position>mark->position) && (Position<mark->Next()->position)) + { + // add after mark + newmark->Set(mark,mark->Next()); + mark->SetNext(newmark); + break; + } + } + mark=mark->Next(); + } + if (!mark)return NULL; + count++; + return newmark; + } + return NULL; +} + +bool clMarks::Load(const char *Directory,double FrameRate, bool isTS) +{ + char *fpath=NULL; + if (asprintf(&fpath,"%s/%s%s",Directory,filename,isTS ? "" : ".vdr")==-1) return false; + + FILE *mf; + mf=fopen(fpath,"r"); + free(fpath); + if (!mf) return false; + + char *line=NULL; + size_t length; + int h, m, s, f; + + while (getline(&line,&length,mf)!=-1) + { + char descr[256]=""; + f=1; + int n=sscanf(line,"%d:%d:%d.%d %80c",&h, &m, &s, &f,(char *) &descr); + if (n==1) + { + Add(h); + } + if (n>=3) + { + int pos=int(round((h*3600+m*60+s)*FrameRate))+f-1; + if (n<=4) + { + Add(pos); + } + else + { + char *lf=strchr(descr,10); + if (lf) *lf=0; + char *cr=strchr(descr,13); + if (cr) *cr=0; + Add(pos,descr); + } + } + } + if (line) free(line); + fclose(mf); + + return true; +} + +char *clMarks::IndexToHMSF(int Index, double FramesPerSecond) +{ + if (FramesPerSecond==0.0) return NULL; + char *buf=NULL; + double Seconds; + int f = int(modf((Index+0.5)/FramesPerSecond,&Seconds)*FramesPerSecond+1); + int s = int(Seconds); + int m = s / 60 % 60; + int h = s / 3600; + s %= 60; + if (asprintf(&buf,"%d:%02d:%02d.%02d",h,m,s,f)==-1) return NULL; + return buf; +} + +bool clMarks::CheckIndex(int FileDescriptor, int Index, bool isTS) +{ + // return true on error + if (FileDescriptor==-1) return true; + if (Index<0) return true; + + if (isTS) + { + off_t offset = Index * sizeof(struct tIndexTS); + if (lseek(FileDescriptor,offset,SEEK_SET)!=offset) return true; + struct tIndexTS IndexTS; + if (read(FileDescriptor,&IndexTS,sizeof(IndexTS))!=sizeof(IndexTS)) return true; + if (IndexTS.independent) return false; + } + else + { + off_t offset = Index * sizeof(struct tIndexVDR); + if (lseek(FileDescriptor,offset,SEEK_SET)!=offset) return true; + struct tIndexVDR IndexVDR; + if (read(FileDescriptor,&IndexVDR,sizeof(IndexVDR))!=sizeof(IndexVDR)) return true; + if (IndexVDR.type==1) return false; + } + return true; +} + +bool clMarks::Save(const char *Directory, double FrameRate, bool isTS, bool Backup, bool *IndexError) +{ + if (IndexError) *IndexError=false; + if (!first) return false; + + char *fpath=NULL; + if (asprintf(&fpath,"%s/%s%s",Directory,filename,isTS ? "" : ".vdr")==-1) return false; + + char *ipath=NULL; + if (asprintf(&ipath,"%s/index%s",Directory,isTS ? "" : ".vdr")==-1) ipath=NULL; + + if (Backup) + { + // make backup of old marks, filename convention taken from noad + char *bpath=NULL; + if (asprintf(&bpath,"%s/%s0%s",Directory,filename,isTS ? "" : ".vdr")!=-1) + { + rename(fpath,bpath); + free(bpath); + } + } + + FILE *mf; + mf=fopen(fpath,"w+"); + + if (!mf) + { + free(fpath); + if (ipath) free(ipath); + return false; + } + + int fd=-1; + if (ipath) fd=open(ipath,O_RDONLY); + + clMark *mark=first; + while (mark) + { + char *buf=IndexToHMSF(mark->position,FrameRate); + if (buf) + { + fprintf(mf,"%s %s\n",buf,mark->comment ? mark->comment : ""); + free(buf); + if ((IndexError) && (fd!=-1)) + { + *IndexError=CheckIndex(fd,mark->position,isTS); + } + } + mark=mark->Next(); + } + fclose(mf); + free(ipath); + + if (fd!=-1) close(fd); + + 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(fpath,statbuf.st_uid, statbuf.st_gid); + } + free(spath); + } + } + free(fpath); + return true; +} @@ -0,0 +1,109 @@ +/* + * marks.h: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + */ + +#ifndef __marks_h_ +#define __marks_h_ + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <math.h> +#include <unistd.h> +#include <sys/stat.h> +#include <stdint.h> +#include <fcntl.h> + +class clMark +{ +private: + clMark *next; + clMark *prev; +public: + int position; + char *comment; + clMark(int Position = 0, const char *Comment = NULL); + ~clMark(); + clMark *Next() + { + return next; + }; + clMark *Prev() + { + return prev; + }; + void Set(clMark *Prev, clMark *Next) + { + prev=Prev; + next=Next; + } + void SetNext(clMark *Next) + { + next=Next; + } + void SetPrev(clMark *Prev) + { + prev=Prev; + } +}; + +class clMarks +{ +private: + struct tIndexVDR + { + int offset; + unsigned char type; + unsigned char number; + short reserved; + }; + + struct tIndexTS + { +uint64_t offset: + 40; +int reserved: + 7; +int independent: + 1; +uint16_t number: + 16; + }; + + char filename[1024]; + clMark *first; + char *IndexToHMSF(int Index, double FramesPerSecond); + bool CheckIndex(int FileDescriptor, int Index, bool isTS); + int count; +public: + ~clMarks(); + int Count() + { + return count; + } + clMarks() + { + strcpy(filename,"marks"); + first=NULL; + }; + void SetFileName(const char *FileName) + { + if (FileName) + { + strncpy(filename,FileName,sizeof(filename)-1); + filename[sizeof(filename)-1]=0; + } + } + clMark *Add(int Position, const char *Comment = NULL); + void Del(clMark *Mark); + clMark *Get(int Position); + clMark *GetPrev(int Position); + clMark *GetNext(int Position); + bool Load(const char *Directory, double FrameRate, bool isTS); + bool Save(const char *Directory, double FrameRate, bool isTS, bool Backup, bool *IndexError); +}; + +#endif @@ -8,6 +8,6 @@ #ifndef __version_h_ #define __version_h_ -static const char *VERSION = "0.0.5"; +static const char *VERSION = "0.0.6"; #endif |