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#ifdef __cpp_lib_ranges_contains
184 return std::ranges::contains(pass, tf);
200 query.
prepare(
"SELECT basename"
202 " WHERE chanid = :CHANID"
203 " AND starttime = :STARTTIME"
206 query.
bindValue(
":STARTTIME", recstartts);
219 if (!pburl.startsWith(
"/"))
222 QString basename(query.
value(0).toString());
223 QString m_debugdir = pburl.section(
'/',0,-2) +
"/" + basename +
"-debug";
233 LOG(VB_COMMFLAG, LOG_INFO, QString(
"%1 using debug directory \"%2\"")
234 .arg(comment, dirname));
238 if (qdir.mkdir(dirname))
240 LOG(VB_COMMFLAG, LOG_INFO,
241 QString(
"%1 created debug directory \"%1\"")
242 .arg(comment, dirname));
246 LOG(VB_COMMFLAG, LOG_INFO, QString(
"%1 failed to create \"%2\": %3")
247 .arg(comment, dirname, strerror(errno)));
255 auto secs = std::chrono::ceil<std::chrono::seconds>(ms);
268 auto msecs = duration_cast<std::chrono::milliseconds>(usecs);
278 bool showProgress_in,
282 QDateTime startts_in,
284 QDateTime recstartts_in,
285 QDateTime recendts_in,
288 m_showProgress(showProgress_in), m_fullSpeed(fullSpeed_in),
290 m_startts(std::move(startts_in)), m_endts(std::move(endts_in)),
291 m_recstartts(std::move(recstartts_in)), m_recendts(std::move(recendts_in)),
301 std::shared_ptr<PGMConverter> pgmConverter =
302 std::make_shared<PGMConverter>();
303 std::shared_ptr<BorderDetector> borderDetector =
304 std::make_shared<BorderDetector>();
305 std::shared_ptr<HistogramAnalyzer> histogramAnalyzer =
306 std::make_shared<HistogramAnalyzer>(pgmConverter, borderDetector,
345 std::shared_ptr<CannyEdgeDetector> cannyEdgeDetector =
346 std::make_shared<CannyEdgeDetector>();
373 long long nframes,
unsigned int passno,
unsigned int npasses)
375 float fps = elapsedms ? (float)frameno * 1000 / elapsedms : 0;
376 static int s_prevpercent = -1;
379 int percentage = (passno == 0 || npasses == 1 || nframes == 0) ? 0 :
380 ((passno - 1) * 100 / (npasses - 1)) +
381 std::min((
long long)100, (frameno * 100 / nframes) / (npasses - 1));
388 tmp = QString(
"\r%1%/ %2fps").arg(percentage,3).arg(fps,6,
'f',2);
390 tmp = QString(
"\r%1/ %2fps").arg(frameno,6).arg(fps,6,
'f',2);
392 QByteArray tmp2 = tmp.toLocal8Bit();
393 std::cerr << tmp2.constData() <<
" \r";
399 emit
statusUpdate(QCoreApplication::translate(
"(mythcommflag)",
400 "%1% Completed @ %2 fps.").arg(percentage).arg(fps));
404 emit
statusUpdate(QCoreApplication::translate(
"(mythcommflag)",
405 "%1 Frames Completed @ %2 fps.").arg(frameno).arg(fps));
408 if (percentage % 10 == 0 && s_prevpercent != percentage)
410 s_prevpercent = percentage;
411 LOG(VB_GENERAL, LOG_INFO, QString(
"%1% Completed @ %2 fps.")
412 .arg(percentage) .arg(fps));
475 LOG(VB_GENERAL, LOG_ERR,
476 "NVP: Unable to initialize video for FlagCommercials.");
480 QElapsedTimer totalFlagTime;
481 totalFlagTime.start();
493 std::cerr <<
" 0%/ ";
500 unsigned int passno = 0;
508 LOG(VB_COMMFLAG, LOG_INFO,
509 QString(
"CommDetector2::go pass %1 of %2 (%3 frames, %4 fps)")
510 .arg(passno + 1).arg(npasses)
521 long long nextFrame = -1;
524 QElapsedTimer passTime;
526 std::chrono::microseconds getframetime {0us};
531 emit
statusUpdate(QCoreApplication::translate(
"(mythcommflag)",
532 "Performing Logo Identification"));
538 auto start = nowAsDuration<std::chrono::microseconds>();
544 auto end = nowAsDuration<std::chrono::microseconds>();
545 getframetime += (end - start);
547 if (nextFrame != -1 && nextFrame == lastFrameNumber + 1 &&
554 LOG(VB_COMMFLAG, LOG_INFO,
555 QString(
"Jumped from frame %1 to frame %2")
572 std::this_thread::sleep_for(1s);
580 nframes, passno, npasses);
588 (((nextFrame * 10) / nframes) !=
590 (nextFrame >= nframes))
593 int elapsed = clock.restart();
594 LOG(VB_COMMFLAG, LOG_INFO,
595 QString(
"processFrame %1 of %2 (%3%) - %4 fps")
598 .arg((nframes == 0) ? 0 :
601 (elapsed ? elapsed : 1)));
615 std::this_thread::sleep_for(10ms);
624 auto ii = breakMap.cbegin();
625 auto jj = lastBreakMap.cbegin();
626 while (ii != breakMap.cend() && jj != lastBreakMap.cend())
628 if (ii.key() != jj.key())
635 bool same = ii == breakMap.cend() && jj == lastBreakMap.cend();
636 lastBreakMap = breakMap;
649 if (passno + 1 == npasses)
662 LOG(VB_COMMFLAG, LOG_INFO, QString(
"NVP Time: GetRawVideoFrame=%1s")
671 std::cerr <<
"\b\b\b\b\b\b \b\b\b\b\b\b";
673 std::cerr <<
"\b\b\b\b\b\b\b\b\b\b\b\b\b "
674 "\b\b\b\b\b\b\b\b\b\b\b\b\b";
705 long long breakframes = 0;
708 long long segb = bb.key();
709 long long seglen = *bb;
710 long long sege = segb + seglen - 1;
717 breakframes += seglen;
723 for (
auto iimark = marks.cbegin(); iimark != marks.cend(); ++iimark)
726 long long markstart = iimark.key() + 1;
728 if (iimark == marks.cend())
730 long long markend = iimark.key() + 1;
732 LOG(VB_COMMFLAG, LOG_INFO, QString(
"Break: frame %1-%2 (%3-%4, %5)")
733 .arg(markstart, 6).arg(markend, 6)
740 LOG(VB_COMMFLAG, LOG_INFO,
741 QString(
"Flagged %1 of %2 frames (%3 of %4), %5% commercials (%6)")
753 LOG(VB_COMMFLAG, LOG_INFO,
754 QString(
"CommDetector2::recordingFinished: %1 bytes")
755 .arg(totalFileSize));
762 LOG(VB_COMMFLAG, LOG_INFO,
"Ignoring request for commBreakMapUpdate; "
763 "still doing logo detection");
767 LOG(VB_COMMFLAG, LOG_INFO,
768 QString(
"commBreakMapUpdate requested at frame %1")
777 FrameAnalyzer::FrameMap::const_iterator it = frameMap.begin();
778 for (; it != frameMap.end(); ++it)
785 long long bb = it.key() + 1;
786 long long ee = (*it) ? (bb + *it) : 1;
787 QString tmp = QString(
"%1: %2").arg(bb, 10).arg(ee - 1, 10);
789 out << qPrintable(tmp) <<
"\n";
813 out <<
"Logo Break Map\n";
815 out <<
"Blank Break Map\n";
817 out <<
"Blank Map\n";
819 out <<
"Scene Break Map\n";
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::chrono::duration< double, std::micro > floatusecs
std::chrono::milliseconds millisecondsFromFloat(T value)
Helper function for convert a floating point number to a duration.
#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.