00001 #include <math.h>
00002 #include <qdir.h>
00003 #include <qfileinfo.h>
00004 #include <unistd.h>
00005
00006 #include "NuppelVideoPlayer.h"
00007 #include "compat.h"
00008
00009 #include "CommDetector.h"
00010 #include "CommDetector2.h"
00011 #include "CannyEdgeDetector.h"
00012 #include "FrameAnalyzer.h"
00013 #include "PGMConverter.h"
00014 #include "BorderDetector.h"
00015 #include "HistogramAnalyzer.h"
00016 #include "BlankFrameDetector.h"
00017 #include "SceneChangeDetector.h"
00018 #include "TemplateFinder.h"
00019 #include "TemplateMatcher.h"
00020
00021 namespace {
00022
00023 bool stopForBreath(bool isrecording, long long frameno)
00024 {
00025 return (isrecording && (frameno % 100) == 0) || (frameno % 500) == 0;
00026 }
00027
00028 bool needToReportState(bool showprogress, bool isrecording, long long frameno)
00029 {
00030 return ((showprogress || isrecording) && (frameno % 100) == 0) ||
00031 (frameno % 500) == 0;
00032 }
00033
00034 void waitForBuffer(const struct timeval *framestart, int minlag, int flaglag,
00035 float fps, bool fullspeed)
00036 {
00037 long usperframe = (long)(1000000.0 / fps);
00038 struct timeval now, elapsed;
00039 long sleepus;
00040
00041 (void)gettimeofday(&now, NULL);
00042 timersub(&now, framestart, &elapsed);
00043
00044
00045 sleepus = usperframe - elapsed.tv_sec * 1000000 - elapsed.tv_usec;
00046 if (sleepus <= 0)
00047 return;
00048
00049 if (flaglag > minlag)
00050 {
00051
00052 if (fullspeed)
00053 return;
00054 sleepus /= 4;
00055 }
00056 else if (flaglag < minlag)
00057 {
00058
00059 sleepus = sleepus * 3 / 2;
00060 }
00061 usleep(sleepus);
00062 }
00063
00064 int nuppelVideoPlayerInited(QPtrList<FrameAnalyzer> *pass,
00065 QPtrList<FrameAnalyzer> *finishedAnalyzers,
00066 QPtrList<FrameAnalyzer> *deadAnalyzers,
00067 NuppelVideoPlayer *nvp, long long nframes)
00068 {
00069 QPtrListIterator<FrameAnalyzer> iifa(*pass);
00070 FrameAnalyzer *fa;
00071 FrameAnalyzer::analyzeFrameResult ares;
00072
00073 for (QPtrListIterator<FrameAnalyzer> jjfa = iifa;
00074 (fa = iifa.current()); iifa = jjfa)
00075 {
00076 ++jjfa;
00077
00078 ares = fa->nuppelVideoPlayerInited(nvp, nframes);
00079
00080 if (ares == FrameAnalyzer::ANALYZE_OK ||
00081 ares == FrameAnalyzer::ANALYZE_ERROR)
00082 {
00083 continue;
00084 }
00085
00086 if (ares == FrameAnalyzer::ANALYZE_FINISHED)
00087 {
00088 pass->remove(fa);
00089 finishedAnalyzers->append(fa);
00090 continue;
00091 }
00092
00093 if (ares == FrameAnalyzer::ANALYZE_FATAL)
00094 {
00095 pass->remove(fa);
00096 deadAnalyzers->append(fa);
00097 continue;
00098 }
00099
00100 VERBOSE(VB_IMPORTANT, QString("Unexpected return value from"
00101 " %1::nuppelVideoPlayerInited: %2")
00102 .arg(fa->name()).arg(ares));
00103 return -1;
00104 }
00105
00106 return 0;
00107 }
00108
00109 long long processFrame(QPtrList<FrameAnalyzer> *pass,
00110 QPtrList<FrameAnalyzer> *finishedAnalyzers,
00111 QPtrList<FrameAnalyzer> *deadAnalyzers,
00112 const VideoFrame *frame, long long frameno)
00113 {
00114 QPtrListIterator<FrameAnalyzer> iifa(*pass);
00115 FrameAnalyzer *fa;
00116 FrameAnalyzer::analyzeFrameResult ares;
00117 long long nextFrame, minNextFrame;
00118
00119 minNextFrame = FrameAnalyzer::ANYFRAME;
00120 for (QPtrListIterator<FrameAnalyzer> jjfa = iifa;
00121 (fa = iifa.current()); iifa = jjfa)
00122 {
00123 ++jjfa;
00124
00125 ares = fa->analyzeFrame(frame, frameno, &nextFrame);
00126
00127 if (ares == FrameAnalyzer::ANALYZE_OK ||
00128 ares == FrameAnalyzer::ANALYZE_ERROR)
00129 {
00130 if (minNextFrame > nextFrame)
00131 minNextFrame = nextFrame;
00132 continue;
00133 }
00134
00135 if (ares == FrameAnalyzer::ANALYZE_FINISHED)
00136 {
00137 pass->remove(fa);
00138 finishedAnalyzers->append(fa);
00139 continue;
00140 }
00141
00142 if (ares == FrameAnalyzer::ANALYZE_FATAL)
00143 {
00144 pass->remove(fa);
00145 deadAnalyzers->append(fa);
00146 continue;
00147 }
00148
00149 VERBOSE(VB_IMPORTANT, QString("Unexpected return value from"
00150 " %1::analyzeFrame: %2")
00151 .arg(fa->name()).arg(ares));
00152 pass->remove(fa);
00153 deadAnalyzers->append(fa);
00154 }
00155
00156 if (minNextFrame == FrameAnalyzer::ANYFRAME)
00157 minNextFrame = FrameAnalyzer::NEXTFRAME;
00158
00159 if (minNextFrame == FrameAnalyzer::NEXTFRAME)
00160 minNextFrame = frameno + 1;
00161
00162 return minNextFrame;
00163 }
00164
00165 int passFinished(QPtrList<FrameAnalyzer> *pass, long long nframes, bool final)
00166 {
00167 FrameAnalyzer *fa;
00168
00169 for (QPtrListIterator<FrameAnalyzer> iifa(*pass);
00170 (fa = iifa.current()); ++iifa)
00171 (void)fa->finished(nframes, final);
00172
00173 return 0;
00174 }
00175
00176 int passReportTime(QPtrList<FrameAnalyzer> *pass)
00177 {
00178 FrameAnalyzer *fa;
00179
00180 for (QPtrListIterator<FrameAnalyzer> iifa(*pass);
00181 (fa = iifa.current()); ++iifa)
00182 (void)fa->reportTime();
00183
00184 return 0;
00185 }
00186
00187 bool searchingForLogo(TemplateFinder *tf, QPtrList<FrameAnalyzer> *pass)
00188 {
00189 return tf && pass->find(tf) != -1;
00190 }
00191
00192 };
00193
00194 namespace commDetector2 {
00195
00196 QString debugDirectory(int chanid, const QDateTime& recstartts)
00197 {
00198
00199
00200
00201 MSqlQuery query(MSqlQuery::InitCon());
00202 query.prepare("SELECT basename"
00203 " FROM recorded"
00204 " WHERE chanid = :CHANID"
00205 " AND starttime = :STARTTIME"
00206 ";");
00207 query.bindValue(":CHANID", chanid);
00208 query.bindValue(":STARTTIME", recstartts);
00209 query.exec();
00210 if (query.size() <= 0 || !query.next())
00211 {
00212 MythContext::DBError("Error in CommDetector2::CommDetector2",
00213 query);
00214 return "";
00215 }
00216
00217 ProgramInfo *pginfo = ProgramInfo::GetProgramFromRecorded(
00218 QString::number(chanid), recstartts);
00219
00220 if (!pginfo)
00221 return "";
00222
00223 QString pburl = pginfo->GetPlaybackURL(true);
00224 if (pburl.left(1) != "/")
00225 return "";
00226
00227 QString basename(query.value(0).toString());
00228 QString debugdir = pburl.section('/',0,-2) + "/" + basename + "-debug";
00229
00230 return debugdir;
00231 }
00232
00233 void createDebugDirectory(QString dirname, QString comment)
00234 {
00235 QDir qdir(dirname);
00236 if (qdir.exists())
00237 {
00238 VERBOSE(VB_COMMFLAG, QString("%1 using debug directory \"%2\"")
00239 .arg(comment).arg(dirname));
00240 }
00241 else
00242 {
00243 if (qdir.mkdir(dirname))
00244 {
00245 VERBOSE(VB_COMMFLAG, QString("%1 created debug directory \"%1\"")
00246 .arg(comment).arg(dirname));
00247 }
00248 else
00249 {
00250 VERBOSE(VB_COMMFLAG, QString("%1 failed to create \"%2\": %3")
00251 .arg(comment).arg(dirname).arg(strerror(errno)));
00252 }
00253 }
00254 }
00255
00256 QString frameToTimestamp(long long frameno, float fps)
00257 {
00258 int ms, ss, mm, hh;
00259 QString ts;
00260
00261 ms = (int)roundf(frameno / fps * 1000);
00262
00263 ss = ms / 1000;
00264 ms %= 1000;
00265 if (ms >= 500)
00266 ss++;
00267
00268 mm = ss / 60;
00269 ss %= 60;
00270
00271 hh = mm / 60;
00272 mm %= 60;
00273
00274 return ts.sprintf("%d:%02d:%02d", hh, mm, ss);
00275 }
00276
00277 QString frameToTimestampms(long long frameno, float fps)
00278 {
00279 int ms, ss, mm;
00280 QString ts;
00281
00282 ms = (int)roundf(frameno / fps * 1000);
00283
00284 ss = ms / 1000;
00285 ms %= 1000;
00286
00287 mm = ss / 60;
00288 ss %= 60;
00289
00290 return ts.sprintf("%d:%02d.%03d", mm, ss, ms);
00291 }
00292
00293 QString strftimeval(const struct timeval *tv)
00294 {
00295 QString str;
00296 return str.sprintf("%ld.%06ld", tv->tv_sec, tv->tv_usec);
00297 }
00298
00299 };
00300
00301 using namespace commDetector2;
00302
00303 CommDetector2::CommDetector2(enum SkipTypes commDetectMethod_in,
00304 bool showProgress_in, bool fullSpeed_in, NuppelVideoPlayer* nvp_in,
00305 int chanid, const QDateTime& startts_in, const QDateTime& endts_in,
00306 const QDateTime& recstartts_in, const QDateTime& recendts_in)
00307 : commDetectMethod((enum SkipTypes)(commDetectMethod_in & ~COMM_DETECT_2))
00308 , showProgress(showProgress_in)
00309 , fullSpeed(fullSpeed_in)
00310 , nvp(nvp_in)
00311 , startts(startts_in)
00312 , endts(endts_in)
00313 , recstartts(recstartts_in)
00314 , recendts(recendts_in)
00315 , isRecording(QDateTime::currentDateTime() < recendts)
00316 , sendBreakMapUpdates(false)
00317 , breakMapUpdateRequested(false)
00318 , finished(false)
00319 , logoFinder(NULL)
00320 , logoMatcher(NULL)
00321 , blankFrameDetector(NULL)
00322 , sceneChangeDetector(NULL)
00323 , debugdir("")
00324 {
00325 QPtrList<FrameAnalyzer> pass0, pass1;
00326 PGMConverter *pgmConverter = NULL;
00327 BorderDetector *borderDetector = NULL;
00328 HistogramAnalyzer *histogramAnalyzer = NULL;
00329
00330 debugdir = debugDirectory(chanid, recstartts);
00331
00332
00333
00334
00335
00336 if ((commDetectMethod & COMM_DETECT_2_BLANK))
00337 {
00338 if (!pgmConverter)
00339 pgmConverter = new PGMConverter();
00340
00341 if (!borderDetector)
00342 borderDetector = new BorderDetector();
00343
00344 if (!histogramAnalyzer)
00345 {
00346 histogramAnalyzer = new HistogramAnalyzer(pgmConverter,
00347 borderDetector, debugdir);
00348 }
00349
00350 if (!blankFrameDetector)
00351 {
00352 blankFrameDetector = new BlankFrameDetector(histogramAnalyzer,
00353 debugdir);
00354 pass1.append(blankFrameDetector);
00355 }
00356 }
00357
00358 #ifdef LATER
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 if ((commDetectMethod & COMM_DETECT_2_SCENE))
00370 {
00371 if (!pgmConverter)
00372 pgmConverter = new PGMConverter();
00373
00374 if (!borderDetector)
00375 borderDetector = new BorderDetector();
00376
00377 if (!histogramAnalyzer)
00378 {
00379 histogramAnalyzer = new HistogramAnalyzer(pgmConverter,
00380 borderDetector, debugdir);
00381 }
00382
00383 if (!sceneChangeDetector)
00384 {
00385 sceneChangeDetector = new SceneChangeDetector(histogramAnalyzer,
00386 debugdir);
00387 pass1.append(sceneChangeDetector);
00388 }
00389 }
00390 #endif
00391
00392
00393
00394
00395
00396
00397
00398 if ((commDetectMethod & COMM_DETECT_2_LOGO))
00399 {
00400 CannyEdgeDetector *cannyEdgeDetector = NULL;
00401
00402 if (!pgmConverter)
00403 pgmConverter = new PGMConverter();
00404
00405 if (!borderDetector)
00406 borderDetector = new BorderDetector();
00407
00408 if (!cannyEdgeDetector)
00409 cannyEdgeDetector = new CannyEdgeDetector();
00410
00411 if (!logoFinder)
00412 {
00413 logoFinder = new TemplateFinder(pgmConverter, borderDetector,
00414 cannyEdgeDetector, nvp, recstartts.secsTo(recendts),
00415 debugdir);
00416 pass0.append(logoFinder);
00417 }
00418
00419 if (!logoMatcher)
00420 {
00421 logoMatcher = new TemplateMatcher(pgmConverter, cannyEdgeDetector,
00422 logoFinder, debugdir);
00423 pass1.append(logoMatcher);
00424 }
00425 }
00426
00427 if (histogramAnalyzer && logoFinder)
00428 histogramAnalyzer->setLogoState(logoFinder);
00429
00430
00431 frameAnalyzers.append(pass0);
00432 frameAnalyzers.append(pass1);
00433 }
00434
00435 void CommDetector2::reportState(int elapsedms, long long frameno,
00436 long long nframes, unsigned int passno, unsigned int npasses)
00437 {
00438 float fps = elapsedms ? (float)frameno * 1000 / elapsedms : 0;
00439
00440
00441 int percentage = passno == 0 ? 0 :
00442 (passno - 1) * 100 / (npasses - 1) +
00443 min((long long)100, (frameno * 100 / nframes) / (npasses - 1));
00444
00445 if (showProgress)
00446 {
00447 if (nframes)
00448 {
00449 cerr << "\b\b\b\b\b\b\b\b\b\b\b"
00450 << QString::number(percentage).rightJustify(3, ' ')
00451 << "%/"
00452 << QString::number((int)fps).rightJustify(3, ' ')
00453 << "fps";
00454 }
00455 else
00456 {
00457 cerr << "\b\b\b\b\b\b\b\b\b\b\b\b\b"
00458 << QString::number(frameno).rightJustify(6, ' ')
00459 << "/"
00460 << QString::number((int)fps).rightJustify(3, ' ')
00461 << "fps";
00462 }
00463 cerr.flush();
00464 }
00465
00466 if (nframes)
00467 {
00468 emit statusUpdate(QObject::tr("%1% Completed @ %2 fps.")
00469 .arg(percentage).arg(fps));
00470 }
00471 else
00472 {
00473 emit statusUpdate(QObject::tr("%1 Frames Completed @ %2 fps.")
00474 .arg(frameno).arg(fps));
00475 }
00476 }
00477
00478 int CommDetector2::computeBreaks(long long nframes)
00479 {
00480 int trow, tcol, twidth, theight;
00481 TemplateMatcher *matcher;
00482
00483 breaks.clear();
00484
00485 matcher = logoFinder &&
00486 logoFinder->getTemplate(&trow, &tcol, &twidth, &theight) ? logoMatcher :
00487 NULL;
00488
00489 if (matcher && blankFrameDetector)
00490 {
00491 int cmp;
00492 if (!(cmp = matcher->templateCoverage(nframes, finished)))
00493 {
00494 if (matcher->adjustForBlanks(blankFrameDetector, nframes))
00495 return -1;
00496 if (matcher->computeBreaks(&breaks))
00497 return -1;
00498 }
00499 else
00500 {
00501 if (cmp > 0 &&
00502 blankFrameDetector->computeForLogoSurplus(matcher))
00503 return -1;
00504 else if (cmp < 0 &&
00505 blankFrameDetector->computeForLogoDeficit(matcher))
00506 return -1;
00507
00508 if (blankFrameDetector->computeBreaks(&breaks))
00509 return -1;
00510 }
00511 }
00512 else if (matcher)
00513 {
00514 if (matcher->computeBreaks(&breaks))
00515 return -1;
00516 }
00517 else if (blankFrameDetector)
00518 {
00519 if (blankFrameDetector->computeBreaks(&breaks))
00520 return -1;
00521 }
00522
00523 return 0;
00524 }
00525
00526 bool CommDetector2::go(void)
00527 {
00528 int minlag = 7;
00529
00530 nvp->SetNullVideo();
00531
00532 if (nvp->OpenFile() < 0)
00533 return false;
00534
00535 if (!nvp->InitVideo())
00536 {
00537 VERBOSE(VB_IMPORTANT,
00538 "NVP: Unable to initialize video for FlagCommercials.");
00539 return false;
00540 }
00541
00542 nvp->SetCaptionsEnabled(false);
00543
00544 QTime totalFlagTime;
00545 totalFlagTime.start();
00546
00547
00548 long long nframes = isRecording ?
00549 (long long)roundf((recstartts.secsTo(recendts) + 5) *
00550 nvp->GetFrameRate()) :
00551 nvp->GetTotalFrameCount();
00552 bool postprocessing = !isRecording;
00553
00554 if (showProgress)
00555 {
00556 if (nframes)
00557 cerr << " 0%/ ";
00558 else
00559 cerr << " 0/ ";
00560 cerr.flush();
00561 }
00562
00563 QMap<long long, int> lastBreakMap;
00564 unsigned int passno = 0;
00565 unsigned int npasses = frameAnalyzers.count();
00566 for (currentPass = frameAnalyzers.begin();
00567 currentPass != frameAnalyzers.end();
00568 ++currentPass, passno++)
00569 {
00570 QPtrList<FrameAnalyzer> deadAnalyzers;
00571
00572 VERBOSE(VB_COMMFLAG, QString(
00573 "CommDetector2::go pass %1 of %2 (%3 frames, %4 fps)")
00574 .arg(passno + 1).arg(npasses)
00575 .arg(nvp->GetTotalFrameCount())
00576 .arg(nvp->GetFrameRate(), 0, 'f', 2));
00577
00578 if (nuppelVideoPlayerInited(&(*currentPass), &finishedAnalyzers,
00579 &deadAnalyzers, nvp, nframes))
00580 return false;
00581
00582 nvp->DiscardVideoFrame(nvp->GetRawVideoFrame(0));
00583 long long nextFrame = -1;
00584 currentFrameNumber = 0;
00585 long long lastLoggedFrame = currentFrameNumber;
00586 QTime passTime, clock;
00587 struct timeval getframetime;
00588
00589 if (searchingForLogo(logoFinder, &(*currentPass)))
00590 emit statusUpdate("Performing Logo Identification");
00591
00592 clock.start();
00593 passTime.start();
00594 memset(&getframetime, 0, sizeof(getframetime));
00595 while (!(*currentPass).isEmpty() && !nvp->GetEof())
00596 {
00597 struct timeval start, end, elapsedtv;
00598
00599 (void)gettimeofday(&start, NULL);
00600 VideoFrame *currentFrame = nvp->GetRawVideoFrame(nextFrame);
00601 long long lastFrameNumber = currentFrameNumber;
00602 currentFrameNumber = currentFrame->frameNumber;
00603 (void)gettimeofday(&end, NULL);
00604 timersub(&end, &start, &elapsedtv);
00605 timeradd(&getframetime, &elapsedtv, &getframetime);
00606
00607 if (nextFrame != -1 && nextFrame == lastFrameNumber + 1 &&
00608 currentFrameNumber != nextFrame)
00609 {
00610
00611
00612
00613
00614 VERBOSE(VB_COMMFLAG, QString("Jumped from frame %1 to frame %2")
00615 .arg(lastFrameNumber).arg(currentFrameNumber));
00616 }
00617
00618 if (stopForBreath(isRecording, currentFrameNumber))
00619 {
00620 emit breathe();
00621 if (m_bStop)
00622 {
00623 nvp->DiscardVideoFrame(currentFrame);
00624 return false;
00625 }
00626 }
00627
00628 while (m_bPaused)
00629 {
00630 emit breathe();
00631 sleep(1);
00632 }
00633
00634 if (!searchingForLogo(logoFinder, &(*currentPass)) &&
00635 needToReportState(showProgress, isRecording,
00636 currentFrameNumber))
00637 {
00638 reportState(passTime.elapsed(), currentFrameNumber,
00639 nframes, passno, npasses);
00640 }
00641
00642 nextFrame = processFrame(&(*currentPass), &finishedAnalyzers,
00643 &deadAnalyzers, currentFrame, currentFrameNumber);
00644
00645 if (currentFrameNumber >= 1 &&
00646 nextFrame * 10 / nframes !=
00647 currentFrameNumber * 10 / nframes ||
00648 nextFrame >= nframes)
00649 {
00650
00651 int elapsed = clock.restart();
00652 VERBOSE(VB_COMMFLAG, QString(
00653 "processFrame %1 of %2 (%3%) - %4 fps")
00654 .arg(currentFrameNumber)
00655 .arg(nframes)
00656 .arg((int)roundf(currentFrameNumber * 100.0 / nframes))
00657 .arg((currentFrameNumber - lastLoggedFrame) * 1000 /
00658 elapsed));
00659 lastLoggedFrame = currentFrameNumber;
00660 }
00661
00662 if (isRecording)
00663 {
00664 waitForBuffer(&start, minlag,
00665 recstartts.secsTo(QDateTime::currentDateTime()) -
00666 totalFlagTime.elapsed() / 1000, nvp->GetFrameRate(),
00667 fullSpeed);
00668 }
00669
00670
00671 if (!fullSpeed && !isRecording)
00672 usleep(10000);
00673
00674 if (sendBreakMapUpdates && (breakMapUpdateRequested ||
00675 !(currentFrameNumber % 500)))
00676 {
00677 QMap<long long, int> breakMap;
00678
00679 getCommercialBreakList(breakMap);
00680
00681 QMap<long long, int>::const_iterator ii, jj;
00682 ii = breakMap.begin();
00683 jj = lastBreakMap.begin();
00684 while (ii != breakMap.end() && jj != breakMap.end())
00685 {
00686 if (ii.key() != jj.key())
00687 break;
00688 if (ii.data() != jj.data())
00689 break;
00690 ++ii;
00691 ++jj;
00692 }
00693 bool same = ii == breakMap.end() && jj == lastBreakMap.end();
00694 lastBreakMap = breakMap;
00695
00696 if (breakMapUpdateRequested || !same)
00697 emit gotNewCommercialBreakList();
00698
00699 breakMapUpdateRequested = false;
00700 }
00701
00702 nvp->DiscardVideoFrame(currentFrame);
00703 }
00704
00705 QPtrListIterator<FrameAnalyzer> iifa(finishedAnalyzers);
00706 FrameAnalyzer *fa;
00707 while ((fa = iifa.current()))
00708 {
00709 finishedAnalyzers.remove(fa);
00710 (*currentPass).append(fa);
00711 }
00712
00713 if (postprocessing)
00714 currentFrameNumber = nvp->GetTotalFrameCount() - 1;
00715 if (passFinished(&(*currentPass), currentFrameNumber + 1, true))
00716 return false;
00717
00718 VERBOSE(VB_COMMFLAG, QString("NVP Time: GetRawVideoFrame=%1s")
00719 .arg(strftimeval(&getframetime)));
00720 if (passReportTime(&(*currentPass)))
00721 return false;
00722 }
00723
00724 if (showProgress)
00725 {
00726 if (nframes)
00727 cerr << "\b\b\b\b\b\b \b\b\b\b\b\b";
00728 else
00729 cerr << "\b\b\b\b\b\b\b\b\b\b\b\b\b "
00730 "\b\b\b\b\b\b\b\b\b\b\b\b\b";
00731 cerr.flush();
00732 }
00733
00734 finished = true;
00735 return true;
00736 }
00737
00738 void CommDetector2::getCommercialBreakList(QMap<long long, int> &marks)
00739 {
00740 if (!finished)
00741 {
00742 for (frameAnalyzerList::iterator pass = frameAnalyzers.begin();
00743 pass != frameAnalyzers.end();
00744 ++pass)
00745 {
00746 if (*pass == *currentPass && passFinished(&finishedAnalyzers,
00747 currentFrameNumber + 1, false))
00748 return;
00749 if (passFinished(&(*pass), currentFrameNumber + 1, false))
00750 return;
00751 }
00752 }
00753
00754 if (computeBreaks(currentFrameNumber + 1))
00755 return;
00756
00757 marks.clear();
00758
00759
00760 long long breakframes = 0;
00761 for (FrameAnalyzer::FrameMap::Iterator bb = breaks.begin();
00762 bb != breaks.end();
00763 ++bb)
00764 {
00765 long long segb = bb.key();
00766 long long seglen = bb.data();
00767 long long sege = segb + seglen - 1;
00768
00769 if (segb < sege)
00770 {
00771 marks[segb] = MARK_COMM_START;
00772 marks[sege] = MARK_COMM_END;
00773
00774 breakframes += seglen;
00775 }
00776 }
00777
00778
00779 const float fps = nvp->GetFrameRate();
00780 for (QMap<long long, int>::const_iterator iimark = marks.begin();
00781 iimark != marks.end();
00782 ++iimark)
00783 {
00784 long long markstart, markend;
00785
00786
00787 markstart = iimark.key() + 1;
00788 ++iimark;
00789 markend = iimark.key() + 1;
00790
00791 VERBOSE(VB_COMMFLAG, QString("Break: frame %1-%2 (%3-%4, %5)")
00792 .arg(markstart, 6).arg(markend, 6)
00793 .arg(frameToTimestamp(markstart, fps))
00794 .arg(frameToTimestamp(markend, fps))
00795 .arg(frameToTimestamp(markend - markstart + 1, fps)));
00796 }
00797
00798 const long long nframes = nvp->GetTotalFrameCount();
00799 VERBOSE(VB_COMMFLAG, QString("Flagged %1 of %2 frames (%3 of %4),"
00800 " %5% commercials (%6)")
00801 .arg(currentFrameNumber + 1).arg(nframes)
00802 .arg(frameToTimestamp(currentFrameNumber + 1, fps))
00803 .arg(frameToTimestamp(nframes, fps))
00804 .arg(breakframes * 100 / currentFrameNumber)
00805 .arg(frameToTimestamp(breakframes, fps)));
00806 }
00807
00808 void CommDetector2::recordingFinished(long long totalFileSize)
00809 {
00810 CommDetectorBase::recordingFinished(totalFileSize);
00811 isRecording = false;
00812 VERBOSE(VB_COMMFLAG, QString("CommDetector2::recordingFinished: %1 bytes")
00813 .arg(totalFileSize));
00814 }
00815
00816 void CommDetector2::requestCommBreakMapUpdate(void)
00817 {
00818 if (searchingForLogo(logoFinder, &(*currentPass)))
00819 {
00820 VERBOSE(VB_COMMFLAG, "Ignoring request for commBreakMapUpdate;"
00821 " still doing logo detection");
00822 return;
00823 }
00824
00825 VERBOSE(VB_COMMFLAG, QString("commBreakMapUpdate requested at frame %1")
00826 .arg(currentFrameNumber + 1));
00827 sendBreakMapUpdates = true;
00828 breakMapUpdateRequested = true;
00829 }
00830
00831