diff options
author | Jochen Dolze <vdr@dolze.de> | 2010-11-09 20:38:56 +0100 |
---|---|---|
committer | Jochen Dolze <vdr@dolze.de> | 2010-11-09 20:38:56 +0100 |
commit | 7716b8b9d7c869265607b6c7ced4ddbd1625ffe9 (patch) | |
tree | 97abe288fb1d5b15e2d420ec28a22ebb41962970 | |
parent | d48a56868074ae2cb71bb6be45fa62aa9f5c2076 (diff) | |
download | vdr-plugin-markad-7716b8b9d7c869265607b6c7ced4ddbd1625ffe9.tar.gz vdr-plugin-markad-7716b8b9d7c869265607b6c7ced4ddbd1625ffe9.tar.bz2 |
Added handling for interrupted recordings
-rw-r--r-- | command/global.h | 1 | ||||
-rw-r--r-- | command/markad-standalone.cpp | 318 | ||||
-rw-r--r-- | command/markad-standalone.h | 5 | ||||
-rw-r--r-- | command/streaminfo.cpp | 31 |
4 files changed, 222 insertions, 133 deletions
diff --git a/command/global.h b/command/global.h index d9f2e12..52764ee 100644 --- a/command/global.h +++ b/command/global.h @@ -125,7 +125,6 @@ typedef struct MarkAdContext struct Info { - int Length; // in seconds int Channels; char *ChannelName; MarkAdAspectRatio AspectRatio; diff --git a/command/markad-standalone.cpp b/command/markad-standalone.cpp index 7d882f5..bf10fdf 100644 --- a/command/markad-standalone.cpp +++ b/command/markad-standalone.cpp @@ -180,10 +180,10 @@ int cOSDMessage::Send(const char *format, ...) void cMarkAdStandalone::CalculateStopPosition(int startframe, int delta) { - if (!macontext.Info.Length) return; + if (!length) return; if (!macontext.Video.Info.FramesPerSecond) return; - int len_in_frames=macontext.Info.Length*macontext.Video.Info.FramesPerSecond; + int len_in_frames=length*macontext.Video.Info.FramesPerSecond; if (startframe) { @@ -480,12 +480,12 @@ void cMarkAdStandalone::CheckFirstMark() // If we have an aspectchange, check the next aspectchange mark // and the difference between - if ((second->type==MT_ASPECTCHANGE) && (macontext.Info.Length)) + if ((second->type==MT_ASPECTCHANGE) && (length)) { clMark *next=marks.GetNext(second->position,MT_ASPECTCHANGE); if (next) { - int maxlen=macontext.Info.Length*(13*60)/(90*60); // max 13 minutes ads on 90 minutes program + int maxlen=length*(13*60)/(90*60); // max 13 minutes ads on 90 minutes program if (maxlen>(13*60)) maxlen=(13*60); // maximum ad block = 13 minutes int MAXPOSDIFF=(int) (macontext.Video.Info.FramesPerSecond*maxlen); if ((next->position-second->position)>MAXPOSDIFF) @@ -685,7 +685,7 @@ void cMarkAdStandalone::AddMark(MarkAdMark *Mark) } } - if (macontext.Info.Length>0) + if (length>0) { if ((Mark->Type==MT_BORDERSTART) && (Mark->Position>chkLEFT) && (Mark->Position<chkRIGHT) && (!macontext.Video.Options.IgnoreLogoDetection)) @@ -813,15 +813,15 @@ void cMarkAdStandalone::SaveFrame(int frame) void cMarkAdStandalone::CheckBroadcastLength() { - if (macontext.Info.Length) return; + if (length) return; if (!macontext.Video.Info.FramesPerSecond) return; /* get broadcastlength from length of indexFile */ int tframecnt=1; int iIndexError; marks.CheckIndex(directory,isTS,&tframecnt,&iIndexError); if (iIndexError!=0) return; - macontext.Info.Length=tframecnt/macontext.Video.Info.FramesPerSecond; - isyslog("got broadcast length of %im from index",macontext.Info.Length/60); + length=tframecnt/macontext.Video.Info.FramesPerSecond; + isyslog("got broadcast length of %im from index",length/60); reprocess=true; } @@ -846,7 +846,31 @@ bool cMarkAdStandalone::CheckIndexGrowing() int maxframes=statbuf.st_size/8; if (maxframes<(framecnt+200)) { - if ((difftime(time(NULL),statbuf.st_mtime))>=10) return false; // "old" file + if ((difftime(time(NULL),statbuf.st_mtime))>=10) + { + if (length && startTime) + { + if (time(NULL)>(startTime+(time_t) length)) + { + return false; + } + else + { + sleepcnt=0; + iwaittime_msg+=WAITTIME; + iwaittime+=WAITTIME; + if (iwaittime_msg>=120) + { + esyslog("recording interrupted %is, still waiting...",iwaittime); + iwaittime_msg=0; + } + } + } + else + { + return false; // "old" file + } + } marks.Save(directory,macontext.Video.Info.FramesPerSecond,isTS); sleep(WAITTIME); // now we sleep and hopefully the index will grow waittime+=WAITTIME; @@ -854,13 +878,18 @@ bool cMarkAdStandalone::CheckIndexGrowing() sleepcnt++; if (sleepcnt>=2) { - esyslog("no new data after %i seconds, skipping wait!", - sleepcnt*WAITTIME); + esyslog("no new data after %is, skipping wait!", + waittime); notenough=false; // something went wrong? } } else { + if (iwaittime) + { + esyslog("resuming after %is of interrupted recording, marks can be wrong now!",iwaittime); + } + iwaittime=iwaittime_msg=0; sleepcnt=0; notenough=false; } @@ -1065,7 +1094,7 @@ bool cMarkAdStandalone::ProcessFile2ndPass(clMark **Mark1, clMark **Mark2,int Nu if (abs(audiotime-lastiframetime)<DELTATIME) { - if (decoder->DecodeMP2(&macontext,apkt.Data,apkt.Length)) + if (decoder->DecodeMP2(&macontext,apkt.Data,apkt.length)) { pos=audio->Process2ndPass(iframe); if (pos) ChangeMarks(Mark1,NULL,pos); @@ -1102,10 +1131,13 @@ void cMarkAdStandalone::Process2ndPass() if (abort) return; if (duplicate) return; if (!decoder) return; + if (!length) return; + if (!startTime) return; + if (time(NULL)<(startTime+(time_t) length)) return; if (!macontext.Video.Info.FramesPerSecond) { - // TODO: Get Framerate from info + isyslog("WARNING: assuming fps of 25"); macontext.Video.Info.FramesPerSecond=25; } @@ -1269,6 +1301,12 @@ bool cMarkAdStandalone::ProcessFile(int Number) dRes=true; } } + if (macontext.Video.Info.FramesPerSecond<0) + { + macontext.Video.Info.FramesPerSecond*=-1; + if (!setFrameRate) isyslog("framerate in info wrong, setting to %.f",macontext.Video.Info.FramesPerSecond); + setFrameRate=true; + } if ((decoder) && (bDecodeVideo)) dRes=decoder->DecodeVideo(&macontext,vpkt.Data,vpkt.Length); @@ -1483,60 +1521,71 @@ void cMarkAdStandalone::Process() ProcessFile(); if (CheckDolbyDigital51()) ProcessFile(); + marks.CloseIndex(directory,isTS); if (!abort) { - marks.CloseIndex(directory,isTS); if (marks.Save(directory,macontext.Video.Info.FramesPerSecond,isTS)) { - int iIndexError=false; - int tframecnt=macontext.Config->GenIndex ? framecnt : 0; - if (marks.CheckIndex(directory,isTS,&tframecnt,&iIndexError)) + if (length && startTime) { - if (iIndexError) + if (time(NULL)>(startTime+(time_t) length)) { - if (macontext.Config->GenIndex) + int iIndexError=false; + int tframecnt=macontext.Config->GenIndex ? framecnt : 0; + if (marks.CheckIndex(directory,isTS,&tframecnt,&iIndexError)) { - switch (iIndexError) - { - case IERR_NOTFOUND: - isyslog("no index found"); - break; - case IERR_TOOSHORT: - isyslog("index too short"); - break; - default: - isyslog("index contains errors"); - break; - } - if (RegenerateIndex()) + if (iIndexError) { - isyslog("recreated index"); - } - else - { - esyslog("failed to recreate index"); + if (macontext.Config->GenIndex) + { + switch (iIndexError) + { + case IERR_NOTFOUND: + isyslog("no index found"); + break; + case IERR_TOOSHORT: + isyslog("index too short"); + break; + default: + isyslog("index contains errors"); + break; + } + if (RegenerateIndex()) + { + isyslog("recreated index"); + } + else + { + esyslog("failed to recreate index"); + } + } + else + { + esyslog("index doesn't match marks%s", + ((isTS) || ((macontext.Info.VPid.Type== + MARKAD_PIDTYPE_VIDEO_H264) && (!isTS))) ? + ", sorry you're lost" : + ", please run genindex"); + } } } - else - { - esyslog("index doesn't match marks%s", - ((isTS) || ((macontext.Info.VPid.Type== - MARKAD_PIDTYPE_VIDEO_H264) && (!isTS))) ? - ", sorry you're lost" : - ", please run genindex"); - } + if ((!bIgnoreAudioInfo) && (!bIgnoreVideoInfo)) SaveInfo(); + } + else + { + // this shouldn't be reached + esyslog("ALERT: stopping before end of broadcast"); } } } - if (macontext.Config->GenIndex) marks.RemoveGeneratedIndex(directory,isTS); - - if ((!bIgnoreAudioInfo) && (!bIgnoreVideoInfo) && (macontext.Info.Length)) SaveInfo(); } + if (macontext.Config->GenIndex) marks.RemoveGeneratedIndex(directory,isTS); } bool cMarkAdStandalone::SaveInfo() { - if ((!setVideo43) && (!setVideo169) && (!setAudio20) && (!setAudio51) && (!setVideo43LB)) return true; + if ((!setVideo43) && (!setVideo169) && (!setAudio20) && (!setAudio51) && (!setVideo43LB) && + (!setFrameRate)) return true; char *src,*dst; if (asprintf(&src,"%s/info%s",directory,isTS ? "" : ".vdr")==-1) return false; @@ -1567,90 +1616,97 @@ bool cMarkAdStandalone::SaveInfo() bool setVideo169_done=false; bool setAudio20_done=false; bool setAudio51_done=false; + bool setFrameRate_done=false; char lang[4]=""; bool err=false; while (getline(&line,&length,r)!=-1) { - if (line[0]=='X') + if ((line[0]=='F') && (setFrameRate)) { - int stream=0,type=0; - char descr[256]=""; - - int result=sscanf(line,"%*c %i %i %3c %250c",&stream,&type,(char *) &lang, (char *) &descr); - if ((result!=0) && (result!=EOF)) + if (fprintf(w,"F %i\n",(int) macontext.Video.Info.FramesPerSecond)<=0) err=true; + setFrameRate_done=true; + } + else + if (line[0]=='X') { - switch (stream) + int stream=0,type=0; + char descr[256]=""; + + int result=sscanf(line,"%*c %i %i %3c %250c",&stream,&type,(char *) &lang, (char *) &descr); + if ((result!=0) && (result!=EOF)) { - case 1: - if ( (((type==1) || (type==5)) && ((setVideo169) || (setVideo43LB))) || - (((type==2) || (type==3) || (type==6) || (type==7)) && - ((setVideo43) || (setVideo43LB)))) + switch (stream) { - if (setVideo43) - { - if (fprintf(w,"X 1 01 %s 4:3\n",lang)<=0) err=true; - setVideo43_done=true; - } - if (setVideo43LB) + case 1: + if ( (((type==1) || (type==5)) && ((setVideo169) || (setVideo43LB))) || + (((type==2) || (type==3) || (type==6) || (type==7)) && + ((setVideo43) || (setVideo43LB)))) { - if (fprintf(w,"X 1 01 %s 4:3 LetterBox\n",lang)<=0) err=true; - setVideo43LB_done=true; + if (setVideo43) + { + if (fprintf(w,"X 1 01 %s 4:3\n",lang)<=0) err=true; + setVideo43_done=true; + } + if (setVideo43LB) + { + if (fprintf(w,"X 1 01 %s 4:3 LetterBox\n",lang)<=0) err=true; + setVideo43LB_done=true; + } + if (setVideo169) + { + if (fprintf(w,"X 1 03 %s 16:9\n",lang)<=0) err=true; + setVideo169_done=true; + } } - if (setVideo169) + else { - if (fprintf(w,"X 1 03 %s 16:9\n",lang)<=0) err=true; - setVideo169_done=true; + if (fprintf(w,"%s",line)<=0) err=true; } - } - else - { - if (fprintf(w,"%s",line)<=0) err=true; - } - break; - case 2: - if ((type==5) && ((setAudio51) || (setAudio20))) - { - if (setAudio51) + break; + case 2: + if ((type==5) && ((setAudio51) || (setAudio20))) { - if (fprintf(w,"X 2 05 %s Dolby Digital 5.1\n",lang)<=0) err=true; - setAudio51_done=true; + if (setAudio51) + { + if (fprintf(w,"X 2 05 %s Dolby Digital 5.1\n",lang)<=0) err=true; + setAudio51_done=true; + } + if (setAudio20) + { + if (fprintf(w,"X 2 05 %s Dolby Digital 2.0\n",lang)<=0) err=true; + setAudio20_done=true; + } } - if (setAudio20) + else { - if (fprintf(w,"X 2 05 %s Dolby Digital 2.0\n",lang)<=0) err=true; - setAudio20_done=true; + if (fprintf(w,"%s",line)<=0) err=true; } - } - else - { + break; + default: if (fprintf(w,"%s",line)<=0) err=true; + break; } - break; - default: - if (fprintf(w,"%s",line)<=0) err=true; - break; } } - } - else - { - if (line[0]!='@') - { - if (fprintf(w,"%s",line)<=0) err=true; - } else { - if (lline) + if (line[0]!='@') { - free(lline); - err=true; - esyslog("multiple @lines in info file, please report this!"); + if (fprintf(w,"%s",line)<=0) err=true; + } + else + { + if (lline) + { + free(lline); + err=true; + esyslog("multiple @lines in info file, please report this!"); + } + lline=strdup(line); } - lline=strdup(line); } - } if (err) break; } if (line) free(line); @@ -1678,6 +1734,10 @@ bool cMarkAdStandalone::SaveInfo() { if (fprintf(w,"X 2 05 %s Dolby Digital 5.1\n",lang)<=0) err=true; } + if ((setFrameRate) && (!setFrameRate_done) && (!err)) + { + if (fprintf(w,"F %i\n",(int) macontext.Video.Info.FramesPerSecond)<=0) err=true; + } if (line) { if (fprintf(w,"%s",line)<=0) err=true; @@ -1803,10 +1863,10 @@ bool cMarkAdStandalone::LoadInfo() free(buf); if (!f) return false; - time_t start=0; char *line=NULL; - size_t length; - while (getline(&line,&length,f)!=-1) + size_t linelen; + setFrameRate=true; + while (getline(&line,&linelen,f)!=-1) { if (line[0]=='C') { @@ -1828,11 +1888,11 @@ bool cMarkAdStandalone::LoadInfo() } if (line[0]=='E') { - int result=sscanf(line,"%*c %*i %li %i %*i %*x",&start,&macontext.Info.Length); + int result=sscanf(line,"%*c %*i %li %i %*i %*x",&startTime,&length); if (result!=2) { - start=0; - macontext.Info.Length=0; + startTime=0; + length=0; } } if (line[0]=='T') @@ -1850,6 +1910,20 @@ bool cMarkAdStandalone::LoadInfo() if (cr) *cr=0; } } + if (line[0]=='F') + { + int fps; + int result=sscanf(line,"%*c %i",&fps); + if ((result==0) || (result==EOF)) + { + macontext.Video.Info.FramesPerSecond=0; + } + else + { + macontext.Video.Info.FramesPerSecond=fps; + setFrameRate=false; + } + } if (line[0]=='X') { int stream=0,type=0; @@ -1921,23 +1995,24 @@ bool cMarkAdStandalone::LoadInfo() } if (line) free(line); - if ((macontext.Info.Length) && (!bIgnoreTimerInfo) && (start)) + if ((length) && (!bIgnoreTimerInfo) && (startTime)) { - time_t rStart=GetBroadcastStart(start,fileno(f)); + time_t rStart=GetBroadcastStart(startTime,fileno(f)); if (rStart) { - if (rStart>start+macontext.Info.Length) + if (rStart>startTime+(time_t) length) { rStart=GetBroadcastStartPES(); } - tStart=(int) (start-rStart); + tStart=(int) (startTime-rStart); if (tStart<0) { - if (macontext.Info.Length+tStart>0) + if (length+tStart>0) { isyslog("broadcast start truncated by %im, length will be corrected",-tStart/60); - macontext.Info.Length+=tStart; + startTime=rStart; + length+=tStart; tStart=1; } else @@ -1958,7 +2033,7 @@ bool cMarkAdStandalone::LoadInfo() } fclose(f); - if (!macontext.Info.Length) + if (!length) { esyslog("cannot read broadcast length from info, marks can be wrong!"); macontext.Info.AspectRatio.Num=0; @@ -2279,8 +2354,9 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory, const MarkAdConfig * noticeVDR_AC3=false; noticeHEADER=false; + sleepcnt=0; - waittime=0; + waittime=iwaittime=iwaittime_msg=0; duplicate=false; marksAligned=false; title[0]=0; @@ -2404,7 +2480,7 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory, const MarkAdConfig * } if (tStart>1) isyslog("pre-timer %im",tStart/60); - if (macontext.Info.Length) isyslog("broadcast length %im",macontext.Info.Length/60); + if (length) isyslog("broadcast length %im",length/60); if (title[0]) { diff --git a/command/markad-standalone.h b/command/markad-standalone.h index adb718a..f7b2966 100644 --- a/command/markad-standalone.h +++ b/command/markad-standalone.h @@ -191,6 +191,8 @@ unsigned Descriptor_Length: bool gotendmark; bool reprocess; int waittime; + int iwaittime; + int iwaittime_msg; struct timeval tv1,tv2; struct timezone tz; @@ -204,6 +206,8 @@ unsigned Descriptor_Length: bool bIgnoreVideoInfo; bool bIgnoreTimerInfo; + time_t startTime; // StartTime of broadcast + int length; // Length in seconds int tStart; // pretimer in seconds int iStart; // pretimer as index value int iStartCheck; // check position for iStart @@ -215,6 +219,7 @@ unsigned Descriptor_Length: bool setVideo43; // set video to 4:3 in info bool setVideo43LB; // set video to 4:3 letterbox in info bool setVideo169; // set video to 16:9 in info + bool setFrameRate; // set framerate in info int chkLEFT; int chkRIGHT; diff --git a/command/streaminfo.cpp b/command/streaminfo.cpp index f12a6b8..4de2665 100644 --- a/command/streaminfo.cpp +++ b/command/streaminfo.cpp @@ -252,7 +252,6 @@ bool cMarkAdStreamInfo::FindH264VideoInfos(MarkAdContext *maContext, uchar *pkt, if (num_units_in_tick > 0) { frame_rate = time_scale / (2*num_units_in_tick); - //if (frame_mbs_only_flag) frame_rate/=2; } bs.skipBit(); // fixed_frame_rate_flag } @@ -314,7 +313,10 @@ bool cMarkAdStreamInfo::FindH264VideoInfos(MarkAdContext *maContext, uchar *pkt, { // set values maContext->Video.Info.Interlaced=!frame_mbs_only_flag; - maContext->Video.Info.FramesPerSecond=frame_rate; + if (frame_rate!=maContext->Video.Info.FramesPerSecond) + { + maContext->Video.Info.FramesPerSecond=-frame_rate; + } maContext->Video.Info.Width=width; maContext->Video.Info.Height=height; @@ -564,42 +566,49 @@ unsigned BitRateExtL: break; } + double fps=0; switch (seqhdr->FrameRateIndex) { case 1: - maContext->Video.Info.FramesPerSecond=24000/1001; // 23.976 fps NTSC encapsulated + fps=24000/1001; // 23.976 fps NTSC encapsulated break; case 2: - maContext->Video.Info.FramesPerSecond=24.0; // Standard international cinema film rate + fps=24.0; // Standard international cinema film rate break; case 3: - maContext->Video.Info.FramesPerSecond=25.0; // PAL (625/50) video frame rate + fps=25.0; // PAL (625/50) video frame rate break; case 4: - maContext->Video.Info.FramesPerSecond=30000/1001; // 29.97 NTSC video frame rate + fps=30000/1001; // 29.97 NTSC video frame rate break; case 5: - maContext->Video.Info.FramesPerSecond=30.0; // NTSC drop frame (525/60) video frame rate + fps=30.0; // NTSC drop frame (525/60) video frame rate break; case 6: - maContext->Video.Info.FramesPerSecond=50.0; // double frame rate/progressive PAL + fps=50.0; // double frame rate/progressive PAL break; case 7: - maContext->Video.Info.FramesPerSecond=60000/1001; // double frame rate NTSC + fps=60000/1001; // double frame rate NTSC break; case 8: - maContext->Video.Info.FramesPerSecond=60.0; // double frame rate drop-frame NTSC + fps=60.0; // double frame rate drop-frame NTSC break; default: break; } - + if (fps) + { + if (fps!=maContext->Video.Info.FramesPerSecond) + { + maContext->Video.Info.FramesPerSecond=-fps; + } + } } return false; } |