8#include <QCoreApplication>
37 return (isrecording && (frameno % 100) == 0) || (frameno % 500) == 0;
42 return ((showprogress || isrecording) && (frameno % 100) == 0) ||
46void waitForBuffer(std::chrono::microseconds framestart,
int minlag,
int flaglag,
47 float fps,
bool fullspeed)
49 auto usperframe =
floatusecs(1000000.0F / fps);
51 auto now = nowAsDuration<std::chrono::microseconds>();
52 auto elapsed = (now - framestart);
55 auto sleepus = usperframe - duration_cast<floatusecs>(elapsed);
66 else if (flaglag < minlag)
69 sleepus = sleepus * 3 / 2;
71 std::this_thread::sleep_for(sleepus);
80 auto it = pass.begin();
81 while (it != pass.end())
84 (*it)->MythPlayerInited(player, nframes);
93 finishedAnalyzers.push_back(*it);
98 deadAnalyzers.push_back(*it);
103 LOG(VB_GENERAL, LOG_ERR,
104 QString(
"Unexpected return value from %1::MythPlayerInited: %2")
105 .arg((*it)->name()).arg(ares));
119 long long nextFrame = 0;
122 auto it = pass.begin();
123 while (it != pass.end())
126 (*it)->analyzeFrame(frame, frameno, &nextFrame);
131 minNextFrame = std::min(minNextFrame, nextFrame);
136 finishedAnalyzers.push_back(*it);
143 LOG(VB_GENERAL, LOG_ERR,
144 QString(
"Unexpected return value from %1::analyzeFrame: %2")
145 .arg((*it)->name()).arg(ares));
148 deadAnalyzers.push_back(*it);
157 minNextFrame = frameno + 1;
164 for (
auto & pas : pass)
165 (void)pas->finished(nframes,
final);
172 for (
auto *pas : pass)
173 (void)pas->reportTime();
183 auto it =
std::find(pass.cbegin(), pass.cend(), tf);
184 return it != pass.end();
197 query.
prepare(
"SELECT basename"
199 " WHERE chanid = :CHANID"
200 " AND starttime = :STARTTIME"
203 query.
bindValue(
":STARTTIME", recstartts);
216 if (!pburl.startsWith(
"/"))
219 QString basename(query.
value(0).toString());
220 QString m_debugdir = pburl.section(
'/',0,-2) +
"/" + basename +
"-debug";
230 LOG(VB_COMMFLAG, LOG_INFO, QString(
"%1 using debug directory \"%2\"")
231 .arg(comment, dirname));
235 if (qdir.mkdir(dirname))
237 LOG(VB_COMMFLAG, LOG_INFO,
238 QString(
"%1 created debug directory \"%1\"")
239 .arg(comment, dirname));
243 LOG(VB_COMMFLAG, LOG_INFO, QString(
"%1 failed to create \"%2\": %3")
244 .arg(comment, dirname, strerror(errno)));
252 auto secs = std::chrono::ceil<std::chrono::seconds>(ms);
265 auto msecs = duration_cast<std::chrono::milliseconds>(usecs);
275 bool showProgress_in,
279 QDateTime startts_in,
281 QDateTime recstartts_in,
282 QDateTime recendts_in,
285 m_showProgress(showProgress_in), m_fullSpeed(fullSpeed_in),
287 m_startts(
std::move(startts_in)), m_endts(
std::move(endts_in)),
288 m_recstartts(
std::move(recstartts_in)), m_recendts(
std::move(recendts_in)),
298 std::shared_ptr<PGMConverter> pgmConverter =
299 std::make_shared<PGMConverter>();
300 std::shared_ptr<BorderDetector> borderDetector =
301 std::make_shared<BorderDetector>();
302 std::shared_ptr<HistogramAnalyzer> histogramAnalyzer =
303 std::make_shared<HistogramAnalyzer>(pgmConverter, borderDetector,
342 std::shared_ptr<CannyEdgeDetector> cannyEdgeDetector =
343 std::make_shared<CannyEdgeDetector>();
370 long long nframes,
unsigned int passno,
unsigned int npasses)
372 float fps = elapsedms ? (float)frameno * 1000 / elapsedms : 0;
373 static int s_prevpercent = -1;
376 int percentage = (passno == 0 || npasses == 1 || nframes == 0) ? 0 :
377 ((passno - 1) * 100 / (npasses - 1)) +
378 std::min((
long long)100, (frameno * 100 / nframes) / (npasses - 1));
385 tmp = QString(
"\r%1%/ %2fps").arg(percentage,3).arg(fps,6,
'f',2);
387 tmp = QString(
"\r%1/ %2fps").arg(frameno,6).arg(fps,6,
'f',2);
389 QByteArray tmp2 =
tmp.toLocal8Bit();
390 std::cerr << tmp2.constData() <<
" \r";
396 emit
statusUpdate(QCoreApplication::translate(
"(mythcommflag)",
397 "%1% Completed @ %2 fps.").arg(percentage).arg(fps));
401 emit
statusUpdate(QCoreApplication::translate(
"(mythcommflag)",
402 "%1 Frames Completed @ %2 fps.").arg(frameno).arg(fps));
405 if (percentage % 10 == 0 && s_prevpercent != percentage)
407 s_prevpercent = percentage;
408 LOG(VB_GENERAL, LOG_INFO, QString(
"%1%% Completed @ %2 fps.")
409 .arg(percentage) .arg(fps));
472 LOG(VB_GENERAL, LOG_ERR,
473 "NVP: Unable to initialize video for FlagCommercials.");
477 QElapsedTimer totalFlagTime;
478 totalFlagTime.start();
490 std::cerr <<
" 0%/ ";
497 unsigned int passno = 0;
505 LOG(VB_COMMFLAG, LOG_INFO,
506 QString(
"CommDetector2::go pass %1 of %2 (%3 frames, %4 fps)")
507 .arg(passno + 1).arg(npasses)
518 long long nextFrame = -1;
521 QElapsedTimer passTime;
523 std::chrono::microseconds getframetime {0us};
528 emit
statusUpdate(QCoreApplication::translate(
"(mythcommflag)",
529 "Performing Logo Identification"));
535 auto start = nowAsDuration<std::chrono::microseconds>();
541 auto end = nowAsDuration<std::chrono::microseconds>();
542 getframetime += (end - start);
544 if (nextFrame != -1 && nextFrame == lastFrameNumber + 1 &&
551 LOG(VB_COMMFLAG, LOG_INFO,
552 QString(
"Jumped from frame %1 to frame %2")
569 std::this_thread::sleep_for(1s);
577 nframes, passno, npasses);
585 (((nextFrame * 10) / nframes) !=
587 (nextFrame >= nframes))
590 int elapsed = clock.restart();
591 LOG(VB_COMMFLAG, LOG_INFO,
592 QString(
"processFrame %1 of %2 (%3%) - %4 fps")
595 .arg((nframes == 0) ? 0 :
598 (elapsed ? elapsed : 1)));
612 std::this_thread::sleep_for(10ms);
621 auto ii = breakMap.cbegin();
622 auto jj = lastBreakMap.cbegin();
623 while (ii != breakMap.cend() && jj != lastBreakMap.cend())
625 if (ii.key() != jj.key())
632 bool same = ii == breakMap.cend() && jj == lastBreakMap.cend();
633 lastBreakMap = breakMap;
646 if (passno + 1 == npasses)
659 LOG(VB_COMMFLAG, LOG_INFO, QString(
"NVP Time: GetRawVideoFrame=%1s")
668 std::cerr <<
"\b\b\b\b\b\b \b\b\b\b\b\b";
670 std::cerr <<
"\b\b\b\b\b\b\b\b\b\b\b\b\b "
671 "\b\b\b\b\b\b\b\b\b\b\b\b\b";
702 long long breakframes = 0;
705 long long segb = bb.key();
706 long long seglen = *bb;
707 long long sege = segb + seglen - 1;
714 breakframes += seglen;
720 for (
auto iimark = marks.cbegin(); iimark != marks.cend(); ++iimark)
723 long long markstart = iimark.key() + 1;
725 if (iimark == marks.cend())
727 long long markend = iimark.key() + 1;
729 LOG(VB_COMMFLAG, LOG_INFO, QString(
"Break: frame %1-%2 (%3-%4, %5)")
730 .arg(markstart, 6).arg(markend, 6)
737 LOG(VB_COMMFLAG, LOG_INFO,
738 QString(
"Flagged %1 of %2 frames (%3 of %4), %5% commercials (%6)")
750 LOG(VB_COMMFLAG, LOG_INFO,
751 QString(
"CommDetector2::recordingFinished: %1 bytes")
752 .arg(totalFileSize));
759 LOG(VB_COMMFLAG, LOG_INFO,
"Ignoring request for commBreakMapUpdate; "
760 "still doing logo detection");
764 LOG(VB_COMMFLAG, LOG_INFO,
765 QString(
"commBreakMapUpdate requested at frame %1")
774 FrameAnalyzer::FrameMap::const_iterator it = frameMap.begin();
775 for (; it != frameMap.end(); ++it)
782 long long bb = it.key() + 1;
783 long long ee = (*it) ? (bb + *it) : 1;
784 QString
tmp = QString(
"%1: %2").arg(bb, 10).arg(ee - 1, 10);
786 out << qPrintable(
tmp) <<
"\n";
810 out <<
"Logo Break Map" << std::endl;
812 out <<
"Blank Break Map" << std::endl;
814 out <<
"Blank Map" << std::endl;
816 out <<
"Scene Break Map" << std::endl;
static void PrintReportMap(std::ostream &out, const FrameAnalyzer::FrameMap &frameMap)
std::vector< FrameAnalyzer * > FrameAnalyzerItem
int computeBreaks(FrameMap *breaks)
int computeForLogoSurplus(const TemplateMatcher *templateMatcher)
static int computeForLogoDeficit(const TemplateMatcher *templateMatcher)
FrameMap GetMap(unsigned int index) const override
void reportState(int elapsedms, long long frameno, long long nframes, unsigned int passno, unsigned int npasses)
TemplateFinder * m_logoFinder
FrameAnalyzerList m_frameAnalyzers
FrameAnalyzerItem m_finishedAnalyzers
void recordingFinished(long long totalFileSize) override
bool m_breakMapUpdateRequested
SkipType m_commDetectMethod
FrameAnalyzerList::iterator m_currentPass
MythCommFlagPlayer * m_player
BlankFrameDetector * m_blankFrameDetector
bool m_sendBreakMapUpdates
void requestCommBreakMapUpdate(void) override
void PrintFullMap(std::ostream &out, const frm_dir_map_t *comm_breaks, bool verbose) const override
void GetCommercialBreakList(frm_dir_map_t &marks) override
TemplateMatcher * m_logoMatcher
int computeBreaks(long long nframes)
FrameAnalyzer::FrameMap m_breaks
CommDetector2(SkipType commDetectMethod, bool showProgress, bool fullSpeed, MythCommFlagPlayer *player, int chanid, QDateTime startts, QDateTime endts, QDateTime recstartts, QDateTime recendts, bool useDB)
SceneChangeDetector * m_sceneChangeDetector
long long m_currentFrameNumber
virtual void recordingFinished(long long totalFileSize)
void statusUpdate(const QString &a)
void gotNewCommercialBreakList()
static const long long kNextFrame
static const long long kAnyFrame
QMap< long long, long long > FrameMap
QSqlQuery wrapper that fetches a DB connection from the connection pool.
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
QVariant value(int i) const
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
MythVideoFrame * GetRawVideoFrame(long long FrameNumber=-1)
Returns a specific frame from the video.
static void DBError(const QString &where, const MSqlQuery &query)
void SaveTotalDuration(void)
uint64_t GetTotalFrameCount(void) const
virtual int OpenFile(int Retries=4)
void ResetTotalDuration(void)
EofState GetEof(void) const
float GetFrameRate(void) const
void DiscardVideoFrame(MythVideoFrame *buffer)
Places frame in the available frames queue.
virtual bool InitVideo(void)
Holds information on recordings and videos.
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
QString GetPlaybackURL(bool checkMaster=false, bool forceCheckLocal=false)
Returns filename or URL to be used to play back this recording.
FrameMap GetMap(unsigned int) const override
FrameMap GetMap(unsigned int) const override
const struct AVFrame * getTemplate(int *prow, int *pcol, int *pwidth, int *pheight) const
int computeBreaks(FrameMap *breaks)
int templateCoverage(long long nframes, bool final) const
int adjustForBlanks(const BlankFrameDetector *blankFrameDetector, long long nframes)
static pid_list_t::iterator find(const PIDInfoMap &map, pid_list_t &list, pid_list_t::iterator begin, pid_list_t::iterator end, bool find_open)
std::enable_if_t< std::is_floating_point_v< T >, std::chrono::milliseconds > millisecondsFromFloat(T value)
Helper function for convert a floating point number to a duration.
std::chrono::duration< double, std::micro > floatusecs
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
QString formatTime(std::chrono::milliseconds msecs, QString fmt)
Format a milliseconds time value.
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
bool needToReportState(bool showprogress, bool isrecording, long long frameno)
bool stopForBreath(bool isrecording, long long frameno)
bool MythPlayerInited(FrameAnalyzerItem &pass, FrameAnalyzerItem &finishedAnalyzers, FrameAnalyzerItem &deadAnalyzers, MythPlayer *player, long long nframes)
long long processFrame(FrameAnalyzerItem &pass, FrameAnalyzerItem &finishedAnalyzers, FrameAnalyzerItem &deadAnalyzers, const MythVideoFrame *frame, long long frameno)
int passFinished(FrameAnalyzerItem &pass, long long nframes, bool final)
bool searchingForLogo(TemplateFinder *tf, const FrameAnalyzerItem &pass)
int passReportTime(const FrameAnalyzerItem &pass)
void waitForBuffer(std::chrono::microseconds framestart, int minlag, int flaglag, float fps, bool fullspeed)
QString frameToTimestamp(long long frameno, float fps)
void createDebugDirectory(const QString &dirname, const QString &comment)
QString frameToTimestampms(long long frameno, float fps)
QString strftimeval(std::chrono::microseconds usecs)
QString debugDirectory(int chanid, const QDateTime &recstartts)
SkipType
This is used as a bitmask.
QMap< uint64_t, MarkTypes > frm_dir_map_t
Frame # -> Mark map.