Ticket #4130: broken.patch.14764

File broken.patch.14764, 16.4 KB (added by Tony Lill <ajlill@…>, 13 years ago)
Line 
1Index: libs/libmythtv/jobqueue.cpp
2===================================================================
3--- libs/libmythtv/jobqueue.cpp (revision 14764)
4+++ libs/libmythtv/jobqueue.cpp (working copy)
5@@ -475,8 +475,6 @@
6     if (pinfo->chancommfree)
7         jobTypes &= (~JOB_COMMFLAG);
8 
9-    if (jobTypes != JOB_NONE)
10-    {
11         QString jobHost = "";
12 
13         if (gContext->GetNumSetting("JobsRunOnRecordHost", 0))
14@@ -484,9 +482,6 @@
15 
16         return JobQueue::QueueJobs(jobTypes, pinfo->chanid, pinfo->recstartts,
17                                    "", "", jobHost);
18-    }
19-    else
20-        return false;
21 
22     return true;
23 }
24@@ -581,11 +576,15 @@
25             QueueJob(JOB_TRANSCODE, chanid, starttime, args, comment, host);
26         if (jobTypes & JOB_COMMFLAG)
27             QueueJob(JOB_COMMFLAG, chanid, starttime, args, comment, host);
28+       else
29+         QueueJob(JOB_COMMFLAG, chanid, starttime, args + " --onlycheckbroken", comment, host);
30     }
31     else
32     {
33         if (jobTypes & JOB_COMMFLAG)
34             QueueJob(JOB_COMMFLAG, chanid, starttime, args, comment, host);
35+       else
36+         QueueJob(JOB_COMMFLAG, chanid, starttime, args + " --onlycheckbroken", comment, host);
37         if (jobTypes & JOB_TRANSCODE)
38         {
39             QDateTime schedruntime = QDateTime::currentDateTime();
40@@ -2125,8 +2124,9 @@
41     if (runningJobCommands[key] == "mythcommflag")
42     {
43         path = gContext->GetInstallPrefix() + "/bin/mythcommflag";
44-        command = QString("%1 -j %2 -V %3")
45-                          .arg(path).arg(jobID).arg(print_verbose_messages);
46+        command = QString("%1 -j %2 -V %3 %4")
47+                          .arg(path).arg(jobID).arg(print_verbose_messages)
48+         .arg(GetJobArgs(jobID));
49     }
50     else
51     {
52@@ -2247,7 +2247,7 @@
53     VERBOSE(VB_JOBQUEUE, LOC + QString("Running command: '%1'")
54                                        .arg(runningJobCommands[key]));
55 
56-    int result = myth_system(runningJobCommands[key]);
57+    int result = myth_system(runningJobCommands[key]+GetJobArgs(jobID));
58 
59     if ((result == MYTHSYSTEM__EXIT__EXECL_ERROR) ||
60         (result == MYTHSYSTEM__EXIT__CMD_NOT_FOUND))
61Index: libs/libmythtv/NuppelVideoRecorder.h
62===================================================================
63--- libs/libmythtv/NuppelVideoRecorder.h        (revision 14764)
64+++ libs/libmythtv/NuppelVideoRecorder.h        (working copy)
65@@ -162,7 +162,8 @@
66     int usebttv;
67     float video_aspect;
68 
69-    bool transcoding;
70+    bool transcoding;          /* disables AC3/DTS passthru in
71+                                  decoder if true */
72 
73     int mp3quality;
74     char *mp3buf;
75Index: libs/libmythtv/tv_rec.cpp
76===================================================================
77--- libs/libmythtv/tv_rec.cpp   (revision 14764)
78+++ libs/libmythtv/tv_rec.cpp   (working copy)
79@@ -956,8 +956,7 @@
80                     JobQueue::RemoveJobsFromMask(JOB_TRANSCODE, autoRunJobs);
81                 }
82 
83-                if (autoRunJobs)
84-                    JobQueue::QueueRecordingJobs(curRecording, autoRunJobs);
85+               JobQueue::QueueRecordingJobs(curRecording, autoRunJobs);
86             }
87         }
88 
89@@ -1283,9 +1282,8 @@
90                             autoRunJobs);
91                     }
92 
93-                    if (autoRunJobs)
94-                        JobQueue::QueueRecordingJobs(curRecording,
95-                            autoRunJobs);
96+                   JobQueue::QueueRecordingJobs(curRecording,
97+                       autoRunJobs);
98                 }
99 
100                 SetPseudoLiveTVRecording(NULL);
101@@ -3840,8 +3838,7 @@
102                 JobQueue::RemoveJobsFromMask(JOB_TRANSCODE, autoRunJobs);
103             }
104 
105-            if (autoRunJobs)
106-                JobQueue::QueueRecordingJobs(curRecording, autoRunJobs);
107+           JobQueue::QueueRecordingJobs(curRecording, autoRunJobs);
108         }
109     }
110 
111Index: programs/mythfrontend/globalsettings.cpp
112===================================================================
113--- programs/mythfrontend/globalsettings.cpp    (revision 14764)
114+++ programs/mythfrontend/globalsettings.cpp    (working copy)
115@@ -548,6 +548,40 @@
116     return bs;
117 }
118 
119+static GlobalSpinBox *MaxBlankRun()
120+{
121+    GlobalSpinBox *bs = new GlobalSpinBox("MaxBlankRun", 0, 3600, 1);
122+    bs->setLabel(QObject::tr("Maximum blank gap (in minutes)"));
123+    bs->setHelpText(QObject::tr("If set, MythTV will consider a recording to be "
124+                               "damaged or incomplete if if finds a run of "
125+                               "blank frames longer that this, and try to "
126+                               "re-record it."));
127+    bs->setValue(0);
128+    return bs;
129+}
130+
131+
132+static GlobalSpinBox *MaxBlankPercent()
133+{
134+    GlobalSpinBox *bs = new GlobalSpinBox("MaxBlankPercent", 0, 100, 1);
135+    bs->setLabel(QObject::tr("Maximum percentage of blank frames"));
136+    bs->setHelpText(QObject::tr("If set, MythTV will consider a recording to be damaged if "
137+                               "it has greater than this percentage of blank frames and try to re-record it."));
138+    bs->setValue(0);
139+    return bs;
140+}
141+
142+static GlobalSpinBox *ShortThreshold()
143+{
144+    GlobalSpinBox *bs = new GlobalSpinBox("ShortThreshold", 120, 3600, 1);
145+    bs->setLabel(QObject::tr("Maximum percentage of blank frames"));
146+    bs->setHelpText(QObject::tr("If set, MythTV will consider a recording to be damaged if "
147+                               "it has greater than this percentage of blank frames and try to re-record it."));
148+    bs->setValue(0);
149+    return bs;
150+}
151+
152+
153 static GlobalSpinBox *AutoExpireExtraSpace()
154 {
155     GlobalSpinBox *bs = new GlobalSpinBox("AutoExpireExtraSpace", 0, 200, 1);
156@@ -4560,6 +4594,13 @@
157 
158     addChild(jobs);
159 
160+    VerticalConfigurationGroup* bork = new VerticalConfigurationGroup(false);
161+    bork->setLabel(QObject::tr("Broken Recording Detection"));
162+    bork->addChild(MaxBlankRun());
163+    bork->addChild(MaxBlankPercent());
164+    bork->addChild(ShortThreshold());
165+    addChild(bork);
166+
167     VerticalConfigurationGroup* general2 = new VerticalConfigurationGroup(false);
168     general2->setLabel(QObject::tr("General (Advanced)"));
169     general2->addChild(RecordPreRoll());
170Index: programs/mythcommflag/BlankFrameDetector.h
171===================================================================
172--- programs/mythcommflag/BlankFrameDetector.h  (revision 14764)
173+++ programs/mythcommflag/BlankFrameDetector.h  (working copy)
174@@ -32,9 +32,9 @@
175     /* BlankFrameDetector interface. */
176     bool getSkipCommBlanks(void) const { return skipcommblanks; }
177     const FrameAnalyzer::FrameMap *getBlanks(void) const { return &blankMap; }
178-    int computeForLogoSurplus(const TemplateMatcher *tm);
179+    int computeForLogoSurplus(const TemplateMatcher *tm, long long nframes);
180     int computeForLogoDeficit(const TemplateMatcher *tm);
181-    int computeBreaks(FrameMap *breaks);
182+    int computeBreaks(FrameMap *breaks, long long nframes);
183 
184 private:
185     HistogramAnalyzer       *histogramAnalyzer;
186Index: programs/mythcommflag/main.cpp
187===================================================================
188--- programs/mythcommflag/main.cpp      (revision 14764)
189+++ programs/mythcommflag/main.cpp      (working copy)
190@@ -34,6 +34,7 @@
191 
192 bool quiet = false;
193 bool force = false;
194+bool broken = false;
195 
196 bool showPercentage = true;
197 bool fullSpeed = true;
198@@ -445,6 +446,17 @@
199         if (!dontSubmitCommbreakListToDB)
200             program_info->SetCommFlagged(COMM_FLAG_NOT_FLAGGED);
201     }
202+   
203+    // Figure out how long the recording is, and compare it to what it should be
204+    {
205+      long recordedTime = nvp->GetTotalFrameCount()/nvp->GetFrameRate();
206+      long expectedTime = program_info->endts.toTime_t() - program_info->startts.toTime_t();
207+      long shortThresh = gContext->GetNumSetting("ShortThreshold",120);
208+      if( recordedTime < ( expectedTime - shortThresh) ) {
209+       VERBOSE(VB_COMMFLAG, QString("Short recording: length %1s expected %2s").arg(recordedTime).arg(expectedTime));
210+       broken = true;
211+      }
212+    }
213 
214     delete commDetector;
215 
216@@ -619,6 +631,12 @@
217     breaksFound = DoFlagCommercials(showPercentage, fullSpeed, inJobQueue,
218                                     nvp, commDetectMethod);
219 
220+    if( broken ) {
221+      VERBOSE(VB_COMMFLAG,
222+             QString("Possibly broken recording, reactivating"));
223+      program_info->ForgetHistory();
224+    }
225+
226     if (fakeJobID >= 0)
227     {
228         jobID = -1;
229@@ -792,6 +810,11 @@
230         {
231             onlyDumpDBCommercialBreakList = true;
232         }
233+        else if (!strcmp(a.argv()[argpos], "--onlycheckbroken"))
234+        {
235+            dontSubmitCommbreakListToDB = true;
236+            commDetectMethod = COMM_DETECT_BLANKS;
237+        }
238         else if (!strcmp(a.argv()[argpos], "--outputfile"))
239         {
240             if (a.argc() > argpos)
241@@ -879,6 +902,7 @@
242                     "-c OR --chanid chanid        Flag recording with given channel ID\n"
243                     "-s OR --starttime starttime  Flag recording with given starttime\n"
244                     "-f OR --file filename        Flag recording with specific filename\n"
245+                   "--onlycheckbroken            Don't flag, just check for possibly botched recordings\n"
246                     "--video filename             Rebuild the seektable for a video (non-recording) file\n"
247                     "--sleep                      Give up some CPU time after processing each frame\n"
248                     "--nopercentage               Don't print percentage done\n"
249Index: programs/mythcommflag/BlankFrameDetector.cpp
250===================================================================
251--- programs/mythcommflag/BlankFrameDetector.cpp        (revision 14764)
252+++ programs/mythcommflag/BlankFrameDetector.cpp        (working copy)
253@@ -11,6 +11,7 @@
254 #include "BlankFrameDetector.h"
255 #include "TemplateMatcher.h"
256 
257+extern bool broken;
258 using namespace commDetector2;
259 using namespace frameAnalyzer;
260 
261@@ -198,6 +199,47 @@
262 }
263 
264 void
265+checkForBrokenRecording(const FrameAnalyzer::FrameMap *blankMap, long long nframes, float fps)
266+{
267+  long long totalblank = 0;
268+
269+  /*
270+   * First check for individual blank intervals over a certain length. This catches,
271+   * for example, when an STB gets reset.
272+   * TODO: ignore blank frames in pre/post roll time, in case it's the first/last program of the day
273+   * also, maybe care more if the blank is at the end of the program?
274+   */
275+  int maxrun = gContext->GetNumSetting("MaxBlankRun",0);
276+  for (FrameAnalyzer::FrameMap::const_iterator iiblank = blankMap->begin();
277+       iiblank != blankMap->end();
278+       ++iiblank)
279+    {
280+      long long brkb = iiblank.key();
281+      long long iilen = iiblank.data();
282+      totalblank += iilen;
283+     
284+      /* If the length of the blank interval is over some threshold
285+        then mark this recording for re-recording */
286+      if( maxrun > 0 && iilen > (maxrun * 60 * fps) ) {
287+       if( !broken ) {
288+         VERBOSE( VB_COMMFLAG, QString("BlankFrameDetector::checkForBrokenRecording: Found long blank run at frame %1").arg(brkb));
289+         broken = true;
290+       }
291+      }
292+    }
293+
294+  /*
295+   * Sometime, if there's problems, the picture comes and goes. So check if the total
296+   * blank time is over a theshold.
297+   */
298+  int maxtot = gContext->GetNumSetting("MaxBlankPercent",0);
299+  if( maxtot && totalblank && ( (totalblank * 100)/nframes > maxtot ) ) {
300+    VERBOSE( VB_COMMFLAG, QString("BlankFrameDetector::checkForBrokenRecording: Total blank frames over threshold"));
301+    broken = true;
302+  }
303+}
304+
305+void
306 computeBreakMap(FrameAnalyzer::FrameMap *breakMap,
307         const FrameAnalyzer::FrameMap *blankMap, float fps, bool skipcommblanks,
308         int debugLevel)
309@@ -443,8 +485,8 @@
310 }
311 
312 int
313-BlankFrameDetector::computeForLogoSurplus(
314-        const TemplateMatcher *templateMatcher)
315+BlankFrameDetector::computeForLogoSurplus(const TemplateMatcher *templateMatcher,
316+                                         long long nframes)
317 {
318     /*
319      * See TemplateMatcher::templateCoverage; some commercial breaks have
320@@ -572,6 +614,11 @@
321     computeBreakMap(&breakMap, &blankMap, fps, skipcommblanks, debugLevel);
322 
323     /*
324+     * Look for evidence the recording is broken
325+     */
326+    checkForBrokenRecording(&blankMap, nframes, fps);
327+
328+    /*
329      * Expand blank-frame breaks to fully include overlapping logo breaks.
330      * Fully include logo breaks that don't include any blank-frame breaks.
331      */
332@@ -638,12 +685,13 @@
333 }
334 
335 int
336-BlankFrameDetector::computeBreaks(FrameAnalyzer::FrameMap *breaks)
337+BlankFrameDetector::computeBreaks(FrameAnalyzer::FrameMap *breaks, long long nframes)
338 {
339     if (breakMap.empty())
340     {
341         /* Compute breaks (breakMap). */
342         computeBreakMap(&breakMap, &blankMap, fps, skipcommblanks, debugLevel);
343+       checkForBrokenRecording(&blankMap,nframes,fps);
344         frameAnalyzerReportMap(&breakMap, fps, "BF Break");
345     }
346 
347Index: programs/mythcommflag/ClassicCommDetector.h
348===================================================================
349--- programs/mythcommflag/ClassicCommDetector.h (revision 14764)
350+++ programs/mythcommflag/ClassicCommDetector.h (working copy)
351@@ -83,6 +83,7 @@
352         void ConvertShowMapToCommMap(QMap<long long, int>&map);
353         void CleanupFrameInfo(void);
354         void GetLogoCommBreakMap(QMap<long long, int> &map);
355+       void CheckForBrokenRecording(void);
356 
357         enum SkipTypes commDetectMethod;
358         bool showProgress;
359Index: programs/mythcommflag/CommDetector2.cpp
360===================================================================
361--- programs/mythcommflag/CommDetector2.cpp     (revision 14764)
362+++ programs/mythcommflag/CommDetector2.cpp     (working copy)
363@@ -498,13 +498,13 @@
364         else
365         {
366             if (cmp > 0 &&
367-                    blankFrameDetector->computeForLogoSurplus(matcher))
368+               blankFrameDetector->computeForLogoSurplus(matcher,nframes))
369                 return -1;
370             else if (cmp < 0 &&
371                     blankFrameDetector->computeForLogoDeficit(matcher))
372                 return -1;
373 
374-            if (blankFrameDetector->computeBreaks(&breaks))
375+            if (blankFrameDetector->computeBreaks(&breaks,nframes))
376                 return -1;
377         }
378     }
379@@ -515,7 +515,7 @@
380     }
381     else if (blankFrameDetector)
382     {
383-        if (blankFrameDetector->computeBreaks(&breaks))
384+      if (blankFrameDetector->computeBreaks(&breaks,nframes))
385             return -1;
386     }
387 
388Index: programs/mythcommflag/ClassicCommDetector.cpp
389===================================================================
390--- programs/mythcommflag/ClassicCommDetector.cpp       (revision 14764)
391+++ programs/mythcommflag/ClassicCommDetector.cpp       (working copy)
392@@ -14,6 +14,8 @@
393 
394 //#include "commercial_debug.h"
395 
396+extern bool broken;
397+
398 enum frameMaskValues {
399     COMM_FRAME_SKIPPED       = 0x0001,
400     COMM_FRAME_BLANK         = 0x0002,
401@@ -550,6 +552,7 @@
402                      break;
403     }
404 
405+    CheckForBrokenRecording();
406     VERBOSE(VB_COMMFLAG, "Final Commercial Break Map" );
407 }
408 
409@@ -1714,6 +1717,59 @@
410 }
411 
412 
413+void ClassicCommDetector::CheckForBrokenRecording(void)
414+{
415+  long long totalblank = 0;
416+  long long lastblankframe = 0;
417+  long long blankrun = 0;
418+  long long i;
419+  QMap<long long, int>::Iterator it;
420
421+  /*
422+   * First check for individual blank intervals over a certain length. This catches,
423+   * for example, when an STB gets reset.
424+   * TODO: ignore blank frames in pre/post roll time, in case it's the first/last program of the day
425+   * also, maybe care more if the blank is at the end of the program?
426+   */
427+  int maxrun = gContext->GetNumSetting("MaxBlankRun",0);
428+  /*
429+   * blankFrameMap is simply a list of blank frames. Go through it and find long runs
430+   * and a total count
431+   */
432+  for (it = blankFrameMap.begin(); it != blankFrameMap.end(); ++it) {
433+    if( lastblankframe == ( it.key() - 1 ) ) {
434+      blankrun++;
435+    } else {
436+      if( maxrun > 0 && blankrun > (60 * maxrun * fps) ) {
437+       if( !broken ) {
438+         VERBOSE( VB_COMMFLAG, QString("ClassicCommDetector::CheckForBrokenRecording: Found long blank run at frame %1").arg(it.key()));
439+         broken = true;
440+       }
441+      }
442+      blankrun = 0;
443+    }
444+    totalblank++;
445+    lastblankframe = it.key();
446+  }
447+  /* Check again in case the recording ended blank */
448+  if( maxrun > 0 && blankrun > (60 * maxrun * fps) ) {
449+    if( !broken ) {
450+      VERBOSE( VB_COMMFLAG, QString("ClassicCommDetector::CheckForBrokenRecording: Found long blank run at frame %1").arg(it.key()));
451+      broken = true;
452+    }
453+  }
454+  /*
455+   * Sometime, if there's problems, the picture comes and goes. So check if the total
456+   * blank time is over a theshold.
457+   */
458+  int maxtot = gContext->GetNumSetting("MaxBlankPercent",0);
459+  if( maxtot && totalblank && ( (totalblank * 100)/framesProcessed > maxtot ) ) {
460+    VERBOSE( VB_COMMFLAG, QString("ClassicCommDetector::CheckForBrokenRecording: Total blank frames over threshold"));
461+    broken = true;
462+  }
463+
464+}
465+
466 void ClassicCommDetector::BuildBlankFrameCommList(void)
467 {
468     VERBOSE(VB_COMMFLAG, "CommDetect::BuildBlankFrameCommList()");
469