8 #include <QCoreApplication>
58 msg = msg.left(msg.length() - 1);
87 return (
verbose) ?
"normal" :
" N ";
89 return (
verbose) ?
"letter" :
" L ";
91 return (
verbose) ?
"pillar" :
" P ";
93 return (
verbose) ?
"letter,pillar" :
"L,P";
95 return (
verbose) ?
" max " :
" M ";
98 return (
verbose) ?
"unknown" :
" U ";
103 return {
" frame min/max/avg scene aspect format flags"};
109 "%1: %2/%3/%4 %5% %6 %7 %8")
121 bool showProgress_in,
124 QDateTime startedAt_in,
125 QDateTime stopsAt_in,
126 QDateTime recordingStartedAt_in,
127 QDateTime recordingStopsAt_in) :
130 m_commDetectMethod(commDetectMethod_in),
132 m_startedAt(
std::move(startedAt_in)),
133 m_stopsAt(
std::move(stopsAt_in)),
134 m_recordingStartedAt(
std::move(recordingStartedAt_in)),
135 m_recordingStopsAt(
std::move(recordingStopsAt_in)),
137 m_fullSpeed(fullSpeed_in),
138 m_showProgress(showProgress_in)
166 m_width = video_disp_dim.width();
185 #ifdef SHOW_DEBUG_WIN
195 LOG(VB_COMMFLAG, LOG_INFO,
196 QString(
"Commercial Detection initialized: "
197 "width = %1, height = %2, fps = %3, method = %4")
227 LOG(VB_COMMFLAG, LOG_INFO,
228 QString(
"Using Sample Spacing of %1 horizontal & %2 vertical pixels.")
263 LOG(VB_COMMFLAG, LOG_DEBUG,
264 " Fr # Min Max Avg Scn F A Mask");
265 LOG(VB_COMMFLAG, LOG_DEBUG,
266 " ------ --- --- --- --- - - ----");
278 CommDetectorBase::deleteLater();
284 int requiredBuffer = 30;
285 int requiredHeadStart = requiredBuffer;
288 emit
statusUpdate(QCoreApplication::translate(
"(mythcommflag)",
289 "Building Head Start Buffer"));
297 std::this_thread::sleep_for(2s);
317 int logoDetectBorder =
322 requiredHeadStart += std::max(
326 emit
statusUpdate(QCoreApplication::translate(
"(mythcommflag)",
327 "Building Logo Detection Buffer"));
335 std::this_thread::sleep_for(2s);
341 if ((wereRecording) && (!
m_stillRecording) && (secsSince < requiredHeadStart))
349 LOG(VB_GENERAL, LOG_ERR,
350 "NVP: Unable to initialize video for FlagCommercials.");
356 emit
statusUpdate(QCoreApplication::translate(
"(mythcommflag)",
357 "Searching for Logo"));
361 std::cerr <<
"Finding Logo";
364 LOG(VB_GENERAL, LOG_INFO,
"Finding Logo");
371 LOG(VB_COMMFLAG, LOG_WARNING,
"No logo found, abort flagging.");
378 std::cerr <<
"\b\b\b\b\b\b\b\b\b\b\b\b "
379 "\b\b\b\b\b\b\b\b\b\b\b\b";
388 QElapsedTimer flagTime;
391 long long myTotalFrames = 0;
401 std::cerr <<
"\r 0%/ \r" << std::flush;
403 std::cerr <<
"\r 0/ \r" << std::flush;
408 int prevpercent = -1;
418 std::chrono::microseconds startTime {0us};
420 startTime = nowAsDuration<std::chrono::microseconds>();
429 float newAspect = currentFrame->
m_aspect;
430 if (newAspect != aspect)
436 if (((currentFrameNumber % 500) == 0) ||
437 (((currentFrameNumber % 100) == 0) &&
450 ((currentFrameNumber % 500) == 0)))
453 frm_dir_map_t::iterator it;
454 frm_dir_map_t::iterator lastIt;
455 bool mapsAreIdentical =
false;
459 if ((commBreakMap.empty()) &&
462 mapsAreIdentical =
true;
467 mapsAreIdentical =
true;
468 for (it = commBreakMap.begin();
469 it != commBreakMap.end() && mapsAreIdentical; ++it)
474 mapsAreIdentical =
false;
491 std::this_thread::sleep_for(1s);
496 std::this_thread::sleep_for(10ms);
498 if (((currentFrameNumber % 500) == 0) ||
500 ((currentFrameNumber % 100) == 0)))
502 float flagFPS { 0.0 };
503 float elapsed = flagTime.elapsed() / 1000.0;
506 flagFPS = currentFrameNumber / elapsed;
512 percentage = currentFrameNumber * 100 / myTotalFrames;
514 if (percentage > 100)
521 QString
tmp = QString(
"\r%1%/%2fps \r")
522 .arg(percentage, 3).arg((
int)flagFPS, 4);
523 std::cerr << qPrintable(
tmp) << std::flush;
527 QString
tmp = QString(
"\r%1/%2fps \r")
528 .arg(currentFrameNumber, 6).arg((
int)flagFPS, 4);
529 std::cerr << qPrintable(
tmp) << std::flush;
535 emit
statusUpdate(QCoreApplication::translate(
"(mythcommflag)",
536 "%1% Completed @ %2 fps.")
537 .arg(percentage).arg(flagFPS));
541 emit
statusUpdate(QCoreApplication::translate(
"(mythcommflag)",
542 "%1 Frames Completed @ %2 fps.")
543 .arg(currentFrameNumber).arg(flagFPS));
546 if (percentage % 10 == 0 && prevpercent != percentage)
548 prevpercent = percentage;
549 LOG(VB_GENERAL, LOG_INFO, QString(
"%1%% Completed @ %2 fps.")
550 .arg(percentage) .arg(flagFPS));
558 int secondsRecorded =
561 int secondsBehind = secondsRecorded - secondsFlagged;
564 auto endTime = nowAsDuration<std::chrono::microseconds>();
566 floatusecs usecSleep = usecPerFrame - (endTime - startTime);
568 if (secondsBehind > requiredBuffer)
573 usecSleep = usecSleep * 0.25;
575 else if (secondsBehind < requiredBuffer)
576 usecSleep = usecPerFrame * 1.5;
579 std::this_thread::sleep_for(usecSleep);
588 float elapsed = flagTime.elapsed() / 1000.0;
591 flagFPS = currentFrameNumber / elapsed;
597 std::cerr <<
"\b\b\b\b\b\b \b\b\b\b\b\b";
599 std::cerr <<
"\b\b\b\b\b\b\b\b\b\b\b\b\b "
600 "\b\b\b\b\b\b\b\b\b\b\b\b\b";
608 unsigned int framenum,
bool isSceneChange,
float debugValue)
621 m_frameInfo[framenum].sceneChangePercent = (int) (debugValue*100);
627 LOG(VB_COMMFLAG, LOG_INFO,
"CommDetect::GetCommBreakMap()");
640 if (!blank && !scene && !logo)
642 LOG(VB_COMMFLAG, LOG_ERR, QString(
"Unexpected commDetectMethod: 0x%1")
647 if (blank && scene && logo)
651 LOG(VB_COMMFLAG, LOG_INFO,
"Final Commercial Break Map");
673 int cnt = ((blank) ? 1 : 0) + ((scene) ? 1 : 0) + ((logo) ? 1 : 0);
681 else if (blank && logo)
686 else if (scene && logo)
693 LOG(VB_COMMFLAG, LOG_INFO,
"Final Commercial Break Map");
713 LOG(VB_COMMFLAG, LOG_INFO,
714 QString(
"CommDetect::SetVideoParams called with aspect = %1")
718 if (fabs(aspect - 1.333333F) < 0.1F)
723 LOG(VB_COMMFLAG, LOG_INFO,
724 QString(
"Aspect Ratio changed from %1 to %2 at frame %3")
738 LOG(VB_COMMFLAG, LOG_ERR,
739 QString(
"Unable to keep track of Aspect ratio change because "
740 "frameInfo for frame number %1 does not exist.")
748 long long frame_number)
752 int blankPixelsChecked = 0;
753 long long totBrightness = 0;
754 auto *rowMax =
new unsigned char[
m_height];
755 auto *colMax =
new unsigned char[
m_width];
756 memset(rowMax, 0,
sizeof(*rowMax)*
m_height);
757 memset(colMax, 0,
sizeof(*colMax)*
m_width);
764 if (!frame || !(frame->
m_buffer) || frame_number == -1 ||
767 LOG(VB_COMMFLAG, LOG_ERR,
"CommDetect: Invalid video frame or codec, "
768 "unable to process frame.");
776 LOG(VB_COMMFLAG, LOG_ERR,
"CommDetect: Width or Height is 0, "
777 "unable to process frame.");
784 unsigned char* framePtr = frame->
m_buffer;
787 fInfo.minBrightness = -1;
788 fInfo.maxBrightness = -1;
789 fInfo.avgBrightness = -1;
790 fInfo.sceneChangePercent = -1;
833 uchar
pixel = framePtr[y * bytesPerLine + x];
837 bool checkPixel =
false;
847 blankPixelsChecked++;
848 totBrightness +=
pixel;
856 if (
pixel > rowMax[y])
859 if (
pixel > colMax[x])
909 (leftDarkCol < (
m_width * .20)) &&
911 (rightDarkCol > (
m_width * .80)))
916 int avg = totBrightness / blankPixelsChecked;
951 (CheckRatingSymbol()))
977 LOG(VB_COMMFLAG, LOG_DEBUG, QString(
"Frame: %1 -> %2 %3 %4 %5 %6 %7 %8")
988 #ifdef SHOW_DEBUG_WIN
989 comm_debug_show(frame->buf);
1000 LOG(VB_COMMFLAG, LOG_INFO,
"CommDetect::ClearAllMaps()");
1013 LOG(VB_COMMFLAG, LOG_INFO,
"CommDetect::GetBlankCommMap()");
1023 LOG(VB_COMMFLAG, LOG_INFO,
"CommDetect::GetBlankCommBreakMap()");
1032 int64_t start_frame)
1034 LOG(VB_COMMFLAG, LOG_INFO,
"CommDetect::GetSceneChangeMap()");
1036 frm_dir_map_t::iterator it;
1038 if (start_frame == -1)
1042 if ((start_frame == -1) || ((int64_t)it.key() >= start_frame))
1043 scenes[it.key()] = *it;
1049 LOG(VB_COMMFLAG, LOG_INFO,
"CommDetect::BuildMasterCommList()");
1055 frm_dir_map_t::const_iterator it = a.begin();
1056 for (; it != a.end(); ++it)
1057 newMap[it.key()] = *it;
1060 if ((a.size() > 1) &&
1064 frm_dir_map_t::const_iterator it_a;
1065 frm_dir_map_t::const_iterator it_b;
1070 if ((it_b.key() < 2) && (it_a.key() > 2))
1072 newMap.remove(it_a.key());
1078 frm_dir_map_t::const_iterator it;
1083 for (; it != a.end(); ++it)
1090 for (; it != b.end(); ++it)
1099 newMap.remove(max_a);
1104 if ((a.size() > 3) &&
1107 frm_dir_map_t::const_iterator it_a;
1108 frm_dir_map_t::const_iterator it_b;
1114 while (it_b != a.end())
1116 uint64_t fdiff = it_b.key() - it_a.key();
1117 bool allTrue =
false;
1119 if (fdiff < (62 *
m_fps))
1121 uint64_t f = it_a.key() + 1;
1131 newMap.remove(it_a.key());
1132 newMap.remove(it_b.key());
1137 if (it_b != a.end())
1147 int format,
int aspect)
1162 if (finfo.
format == format)
1165 if (finfo.
aspect == aspect)
1171 LOG(VB_COMMFLAG, LOG_INFO,
"CommDetect::BuildAllMethodsCommList()");
1174 uint64_t lastStart = 0;
1175 uint64_t lastEnd = 0;
1176 int64_t firstLogoFrame = -1;
1180 std::array<uint64_t,COMM_FORMAT_MAX> formatCounts {};
1182 frm_dir_map_t::iterator it;
1189 uint64_t curFrame = 1;
1202 bool lastFrameWasBlank =
true;
1206 uint64_t aspectFrames = 0;
1223 formatCounts.fill(0);
1234 uint64_t formatFrames = 0;
1237 if (formatCounts[i] > formatFrames)
1240 formatFrames = formatCounts[i];
1256 if (!nextFrameIsBlank || !lastFrameWasBlank)
1260 fbp->
end = curFrame;
1269 fbp = &fblock[curBlock];
1278 fbp->
start = curFrame;
1281 lastFrameWasBlank =
true;
1285 lastFrameWasBlank =
false;
1291 (firstLogoFrame == -1))
1292 firstLogoFrame = curFrame;
1297 fbp->
end = curFrame;
1304 int maxBlock = curBlock;
1308 LOG(VB_COMMFLAG, LOG_INFO,
"Initial Block pass");
1309 LOG(VB_COMMFLAG, LOG_DEBUG,
1310 "Block StTime StFrm EndFrm Frames Secs "
1311 "Bf Lg Cnt RT Cnt SC Cnt SC Rt FmtMch AspMch Score");
1312 LOG(VB_COMMFLAG, LOG_INFO,
1313 "----- ------ ------ ------ ------ ------- "
1314 "--- ------ ------ ------ ----- ------ ------ -----");
1315 while (curBlock <= maxBlock)
1317 fbp = &fblock[curBlock];
1320 LOG(VB_COMMFLAG, LOG_DEBUG, msg);
1325 LOG(VB_COMMFLAG, LOG_DEBUG,
1326 QString(
" FRAMES > %1").arg(
m_fps));
1331 LOG(VB_COMMFLAG, LOG_DEBUG,
1332 " length > max comm length, +20");
1339 LOG(VB_COMMFLAG, LOG_DEBUG,
1340 " length > max comm break length, +20");
1350 LOG(VB_COMMFLAG, LOG_DEBUG,
1351 " length > 4 && logoCount > frames * 0.60 && "
1352 "bfCount < frames * .10");
1357 LOG(VB_COMMFLAG, LOG_DEBUG,
1358 " length > max comm break length, +20");
1364 LOG(VB_COMMFLAG, LOG_DEBUG,
1365 " length <= max comm break length, +10");
1375 LOG(VB_COMMFLAG, LOG_DEBUG,
1376 " logoInfoAvailable && logoCount < frames * .50, "
1385 LOG(VB_COMMFLAG, LOG_DEBUG,
1386 " rating symbol present > 5% of time, +20");
1390 if ((fbp->
scRate > 1.0) &&
1394 LOG(VB_COMMFLAG, LOG_DEBUG,
" scRate > 1.0, -10");
1400 LOG(VB_COMMFLAG, LOG_DEBUG,
" scRate > 2.0, -10");
1410 LOG(VB_COMMFLAG, LOG_DEBUG,
1411 " < 10% of frames match show letter/pillar-box "
1417 if ((abs((
int)(fbp->
frames - (15 *
m_fps))) < 5 ) ||
1422 LOG(VB_COMMFLAG, LOG_DEBUG,
1423 " block appears to be standard comm length, -10");
1430 LOG(VB_COMMFLAG, LOG_DEBUG,
1431 QString(
" FRAMES <= %1").arg(
m_fps));
1434 (fbp->
start >= firstLogoFrame) &&
1438 LOG(VB_COMMFLAG, LOG_DEBUG,
1439 " logoInfoAvailable && logoCount == 0, -10");
1448 LOG(VB_COMMFLAG, LOG_DEBUG,
1449 " < 10% of frames match show letter/pillar-box "
1458 LOG(VB_COMMFLAG, LOG_DEBUG,
1459 " rating symbol present > 25% of time, +10");
1468 LOG(VB_COMMFLAG, LOG_DEBUG,
1469 " < 10% of frames match show aspect, -20");
1474 LOG(VB_COMMFLAG, LOG_DEBUG, msg);
1483 LOG(VB_COMMFLAG, LOG_DEBUG,
"============================================");
1484 LOG(VB_COMMFLAG, LOG_INFO,
"Second Block pass");
1485 LOG(VB_COMMFLAG, LOG_DEBUG,
1486 "Block StTime StFrm EndFrm Frames Secs "
1487 "Bf Lg Cnt RT Cnt SC Cnt SC Rt FmtMch AspMch Score");
1488 LOG(VB_COMMFLAG, LOG_DEBUG,
1489 "----- ------ ------ ------ ------ ------- "
1490 "--- ------ ------ ------ ----- ------ ------ -----");
1491 while (curBlock <= maxBlock)
1493 fbp = &fblock[curBlock];
1496 LOG(VB_COMMFLAG, LOG_DEBUG, msg);
1498 if ((curBlock > 0) && (curBlock < maxBlock))
1500 int nextScore = fblock[curBlock + 1].score;
1502 if ((lastScore < 0) && (nextScore < 0) && (fbp->
length < 35))
1506 LOG(VB_COMMFLAG, LOG_DEBUG,
1507 " lastScore < 0 && nextScore < 0 "
1508 "&& length < 35, setting -10");
1515 (lastScore < 0 && nextScore < 0))
1519 LOG(VB_COMMFLAG, LOG_DEBUG,
1520 " blanks > frames * 0.95 && frames < 2*m_fps && "
1521 "lastScore < 0 && nextScore < 0, setting -10");
1529 (fbp->
score < 20) &&
1534 LOG(VB_COMMFLAG, LOG_DEBUG,
1535 " frames < 120 * m_fps && (-20 < lastScore < 0) && "
1536 "thisScore > 0 && nextScore < 0, setting score = -10");
1544 (fbp->
score > -20) &&
1549 LOG(VB_COMMFLAG, LOG_DEBUG,
1550 " frames < 30 * m_fps && (0 < lastScore < 20) && "
1551 "thisScore < 0 && nextScore > 0, setting score = 10");
1557 if ((fbp->
score == 0) && (lastScore > 30))
1560 while(((curBlock + offset) <= maxBlock) &&
1561 (fblock[curBlock + offset].frames < (2 *
m_fps)) &&
1562 (fblock[curBlock + offset].score == 0))
1565 if ((curBlock + offset) <= maxBlock)
1568 if (fblock[curBlock + offset + 1].score > 0)
1570 for (; offset >= 0; offset--)
1572 fblock[curBlock + offset].score += 10;
1575 LOG(VB_COMMFLAG, LOG_DEBUG,
1576 QString(
" Setting block %1 score +10")
1577 .arg(curBlock+offset));
1581 else if (fblock[curBlock + offset + 1].score < 0)
1583 for (; offset >= 0; offset--)
1585 fblock[curBlock + offset].score -= 10;
1588 LOG(VB_COMMFLAG, LOG_DEBUG,
1589 QString(
" Setting block %1 score -10")
1590 .arg(curBlock+offset));
1598 LOG(VB_COMMFLAG, LOG_DEBUG, msg);
1600 lastScore = fbp->
score;
1604 LOG(VB_COMMFLAG, LOG_DEBUG,
"============================================");
1605 LOG(VB_COMMFLAG, LOG_INFO,
"FINAL Block stats");
1606 LOG(VB_COMMFLAG, LOG_DEBUG,
1607 "Block StTime StFrm EndFrm Frames Secs "
1608 "Bf Lg Cnt RT Cnt SC Cnt SC Rt FmtMch AspMch Score");
1609 LOG(VB_COMMFLAG, LOG_DEBUG,
1610 "----- ------ ------ ------ ------ ------- "
1611 "--- ------ ------ ------ ----- ------ ------ -----");
1614 int64_t breakStart = -1;
1615 while (curBlock <= maxBlock)
1617 fbp = &fblock[curBlock];
1618 int thisScore = fbp->
score;
1620 if ((breakStart >= 0) &&
1623 if (((fbp->
start - breakStart) >
1629 LOG(VB_COMMFLAG, LOG_DEBUG,
1630 QString(
"Closing commercial block at start of "
1631 "frame block %1 with length %2, frame "
1632 "block length of %3 frames would put comm "
1633 "block length over max of %4 seconds.")
1634 .arg(curBlock).arg(fbp->
start - breakStart)
1641 lastStart = breakStart;
1642 lastEnd = fbp->
start;
1649 LOG(VB_COMMFLAG, LOG_DEBUG,
1650 QString(
"Ignoring what appears to be commercial"
1651 " block at frame %1 with length %2, "
1652 "length of %3 frames would put comm "
1653 "block length under min of %4 seconds.")
1655 .arg(fbp->
start - breakStart)
1664 thisScore = lastScore;
1666 else if (thisScore < 0)
1668 if ((lastScore > 0) || (curBlock == 0))
1674 breakStart = lastStart;
1680 LOG(VB_COMMFLAG, LOG_DEBUG,
1681 QString(
"ReOpening commercial block at "
1682 "frame %1 because show less than "
1689 LOG(VB_COMMFLAG, LOG_DEBUG,
1690 "Opening initial commercial block "
1691 "at start of recording, block 0.");
1697 breakStart = fbp->
start;
1701 LOG(VB_COMMFLAG, LOG_DEBUG,
1702 QString(
"Starting new commercial block at "
1703 "frame %1 from start of frame block %2")
1704 .arg(fbp->
start).arg(curBlock));
1708 else if (curBlock == maxBlock)
1710 if ((fbp->
end - breakStart) >
1718 LOG(VB_COMMFLAG, LOG_DEBUG,
1719 QString(
"Closing final commercial block at "
1720 "frame %1").arg(fbp->
end));
1725 lastStart = breakStart;
1734 LOG(VB_COMMFLAG, LOG_DEBUG,
1735 QString(
"Ignoring what appears to be commercial"
1736 " block at frame %1 with length %2, "
1737 "length of %3 frames would put comm "
1738 "block length under min of %4 seconds.")
1740 .arg(fbp->
start - breakStart)
1749 else if ((lastScore < 0) &&
1752 if (((fbp->
start - breakStart) >
1758 lastStart = breakStart;
1759 lastEnd = fbp->
start;
1763 LOG(VB_COMMFLAG, LOG_DEBUG,
1764 QString(
"Closing commercial block at frame %1")
1772 LOG(VB_COMMFLAG, LOG_DEBUG,
1773 QString(
"Ignoring what appears to be commercial "
1774 "block at frame %1 with length %2, "
1775 "length of %3 frames would put comm block "
1776 "length under min of %4 seconds.")
1778 .arg(fbp->
start - breakStart)
1787 LOG(VB_COMMFLAG, LOG_DEBUG, msg);
1789 lastScore = thisScore;
1793 if ((breakStart != -1) &&
1798 LOG(VB_COMMFLAG, LOG_DEBUG,
1799 QString(
"Closing final commercial block started at "
1800 "block %1 and going to end of program. length "
1818 LOG(VB_COMMFLAG, LOG_DEBUG,
1819 "Adjusting start/end marks according to blanks.");
1820 for (it = tmpCommMap.begin(); it != tmpCommMap.end(); ++it)
1824 uint64_t lastStartLower = it.key();
1825 uint64_t lastStartUpper = it.key();
1826 while ((lastStartLower > 0) &&
1832 uint64_t adj = (lastStartUpper - lastStartLower) / 2;
1835 lastStart = lastStartLower + adj;
1838 LOG(VB_COMMFLAG, LOG_DEBUG, QString(
"Start Mark: %1 -> %2")
1839 .arg(it.key()).arg(lastStart));
1845 uint64_t lastEndLower = it.key();
1846 uint64_t lastEndUpper = it.key();
1850 while ((lastEndLower > 0) &&
1853 uint64_t adj = (lastEndUpper - lastEndLower) / 2;
1856 lastEnd = lastEndUpper - adj;
1859 LOG(VB_COMMFLAG, LOG_DEBUG, QString(
"End Mark : %1 -> %2")
1860 .arg(it.key()).arg(lastEnd));
1872 LOG(VB_COMMFLAG, LOG_INFO,
"CommDetect::BuildBlankFrameCommList()");
1881 int commercials = 0;
1886 bframes[frames++] = it.key();
1891 for(
int i = 0; i < frames; i++ )
1893 for(
int x=i+1; x < frames; x++ )
1898 int gap_length = bframes[x] - bframes[i];
1900 ((abs((
int)(gap_length - (5 *
m_fps))) < 5 ) ||
1901 (abs((
int)(gap_length - (10 *
m_fps))) < 7 ) ||
1902 (abs((
int)(gap_length - (15 *
m_fps))) < 10 ) ||
1903 (abs((
int)(gap_length - (20 *
m_fps))) < 11 ) ||
1904 (abs((
int)(gap_length - (30 *
m_fps))) < 12 ) ||
1905 (abs((
int)(gap_length - (40 *
m_fps))) < 1 ) ||
1906 (abs((
int)(gap_length - (45 *
m_fps))) < 1 ) ||
1907 (abs((
int)(gap_length - (60 *
m_fps))) < 15 ) ||
1908 (abs((
int)(gap_length - (90 *
m_fps))) < 10 ) ||
1909 (abs((
int)(gap_length - (120 *
m_fps))) < 10 ))) ||
1911 ((abs((
int)(gap_length - (5 *
m_fps))) < 11 ) ||
1912 (abs((
int)(gap_length - (10 *
m_fps))) < 13 ) ||
1913 (abs((
int)(gap_length - (15 *
m_fps))) < 16 ) ||
1914 (abs((
int)(gap_length - (20 *
m_fps))) < 17 ) ||
1915 (abs((
int)(gap_length - (30 *
m_fps))) < 18 ) ||
1916 (abs((
int)(gap_length - (40 *
m_fps))) < 3 ) ||
1917 (abs((
int)(gap_length - (45 *
m_fps))) < 3 ) ||
1918 (abs((
int)(gap_length - (60 *
m_fps))) < 20 ) ||
1919 (abs((
int)(gap_length - (90 *
m_fps))) < 20 ) ||
1920 (abs((
int)(gap_length - (120 *
m_fps))) < 20 ))))
1922 c_start[commercials] = bframes[i];
1923 c_end[commercials] = bframes[x] - 1;
1930 ((abs((
int)(gap_length - (30 *
m_fps))) < (
int)(
m_fps * 0.85)) ||
1931 (abs((
int)(gap_length - (60 *
m_fps))) < (
int)(
m_fps * 0.95)) ||
1932 (abs((
int)(gap_length - (90 *
m_fps))) < (
int)(
m_fps * 1.05)) ||
1933 (abs((
int)(gap_length - (120 *
m_fps))) < (
int)(
m_fps * 1.15))) &&
1934 ((x + 2) < frames) &&
1935 ((i + 2) < frames) &&
1936 ((bframes[i] + 1) == bframes[i+1]) &&
1937 ((bframes[x] + 1) == bframes[x+1]))
1939 c_start[commercials] = bframes[i];
1940 c_end[commercials] = bframes[x];
1952 if ((commercials > 1) &&
1953 (c_end[0] < (33 *
m_fps)) &&
1954 (c_start[1] > (c_end[0] + 40 *
m_fps)))
1958 bool first_comm =
true;
1959 for(; i < (commercials-1); i++)
1961 long long r = c_start[i];
1962 long long adjustment = 0;
1964 if ((r < (30 *
m_fps)) &&
1971 if ( i < (commercials-1))
1974 for(x = 0; x < (frames-1); x++)
1975 if (bframes[x] == r)
1977 while((x < (frames-1)) &&
1978 ((bframes[x] + 1 ) == bframes[x+1]) &&
1979 (bframes[x+1] < c_start[i+1]))
1986 (c_start[i+1] != (r+1)))
2016 LOG(VB_COMMFLAG, LOG_INFO,
"Blank-Frame Commercial Map" );
2018 LOG(VB_COMMFLAG, LOG_INFO, QString(
" %1:%2")
2019 .arg(it.key()).arg(*it));
2023 LOG(VB_COMMFLAG, LOG_INFO,
"Merged Blank-Frame Commercial Break Map" );
2025 LOG(VB_COMMFLAG, LOG_INFO, QString(
" %1:%2")
2026 .arg(it.key()).arg(*it));
2032 int section_start = -1;
2034 int *sc_histogram =
new int[seconds+1];
2038 memset(sc_histogram, 0, (seconds+1)*
sizeof(
int));
2042 sc_histogram[(uint64_t)(f /
m_fps)]++;
2045 for(
long long s = 0; s < (seconds + 1); s++)
2047 if (sc_histogram[s] > 2)
2049 if (section_start == -1)
2052 for(
int i = 0; i <
m_fps; i++, f++)
2057 i = (int)(
m_fps) + 1;
2065 if ((section_start >= 0) &&
2066 (s > (section_start + 32)))
2068 auto f = (
long long)(section_start *
m_fps);
2069 bool found_end =
false;
2071 for(
int i = 0; i <
m_fps; i++, f++)
2080 i = (int)(
m_fps) + 1;
2093 delete[] sc_histogram;
2095 if (section_start >= 0)
2100 frm_dir_map_t::iterator prev = it;
2107 (it.key() - prev.key()) < (30 *
m_fps))
2117 frm_dir_map_t::iterator dit;
2118 for (dit = deleteMap.begin(); dit != deleteMap.end(); ++dit)
2122 LOG(VB_COMMFLAG, LOG_INFO,
"Scene-Change Commercial Break Map" );
2125 LOG(VB_COMMFLAG, LOG_INFO, QString(
" %1:%2")
2126 .arg(it.key()).arg(*it));
2138 frm_dir_map_t::iterator it;
2139 LOG(VB_COMMFLAG, LOG_INFO,
"Logo Commercial Break Map" );
2141 LOG(VB_COMMFLAG, LOG_INFO, QString(
" %1:%2")
2142 .arg(it.key()).arg(*it));
2147 frm_dir_map_t::iterator it;
2148 frm_dir_map_t::iterator prev;
2149 QMap<long long, long long> tmpMap;
2150 QMap<long long, long long>::Iterator tmpMap_it;
2151 QMap<long long, long long>::Iterator tmpMap_prev;
2170 if ((((prev.key() + 1) == it.key()) ||
2171 ((prev.key() + (15 *
m_fps)) > it.key())) &&
2185 tmpMap[prev.key()] = it.key();
2190 tmpMap[prev.key()] = it.key();
2193 tmpMap_it = tmpMap.begin();
2194 tmpMap_prev = tmpMap_it;
2196 for(; tmpMap_it != tmpMap.end(); ++tmpMap_it, ++tmpMap_prev)
2200 if (((*tmpMap_prev + (35 *
m_fps)) > tmpMap_it.key()) &&
2201 ((*tmpMap_prev - tmpMap_prev.key()) > (35 *
m_fps)) &&
2202 ((*tmpMap_it - tmpMap_it.key()) > (35 *
m_fps)))
2215 if (breakMap.contains(i))
2217 int type = breakMap[i];
2227 for (uint64_t i = (f + 1); i-- > 0; )
2229 if (breakMap.contains(i))
2231 int type = breakMap[i];
2244 frm_dir_map_t::iterator it;
2247 LOG(VB_COMMFLAG, LOG_INFO,
2248 "---------------------------------------------------");
2249 for (it = map.begin(); it != map.end(); ++it)
2251 long long frame = it.key();
2253 int my_fps = (int)ceil(
m_fps);
2254 long long hour = (frame / my_fps) / 60 / 60;
2255 long long min = (frame / my_fps) / 60 - (hour * 60);
2256 long long sec = (frame / my_fps) - (min * 60) - (hour * 60 * 60);
2257 long long frm = frame - ((sec * my_fps) + (min * 60 * my_fps) +
2258 (hour * 60 * 60 * my_fps));
2259 int my_sec = (int)(frame / my_fps);
2260 msg = QString(
"%1 : %2 (%3:%4:%5.%6) (%7)")
2261 .arg(frame, 7).arg(flag).arg(hour, 2, 10, QChar(
'0')).arg(min, 2, 10, QChar(
'0'))
2262 .arg(sec, 2, 10, QChar(
'0')).arg(frm, 2, 10, QChar(
'0')).arg(my_sec);
2263 LOG(VB_COMMFLAG, LOG_INFO, msg);
2265 LOG(VB_COMMFLAG, LOG_INFO,
2266 "---------------------------------------------------");
2272 show_map_t::iterator it;
2273 show_map_t::iterator prev;
2276 if (map.size() <= 2)
2280 LOG(VB_COMMFLAG, LOG_INFO,
"Commercial Map Before condense:" );
2281 for (it = map.begin(); it != map.end(); ++it)
2283 LOG(VB_COMMFLAG, LOG_INFO, QString(
" %1:%2")
2284 .arg(it.key()).arg(*it));
2285 tmpMap[it.key()] = *it;
2288 prev = tmpMap.begin();
2291 while (it != tmpMap.end())
2295 ((it.key() - prev.key()) < (uint64_t)spacing))
2297 map.remove(prev.key());
2298 map.remove(it.key());
2309 for (it = map.begin(); it != map.end(); ++it)
2310 tmpMap[it.key()] = *it;
2312 prev = tmpMap.begin();
2315 while (it != tmpMap.end())
2319 ((it.key() - prev.key()) < (uint64_t)length))
2321 map.remove(prev.key());
2322 map.remove(it.key());
2328 LOG(VB_COMMFLAG, LOG_INFO,
"Commercial Map After condense:" );
2329 for (it = map.begin(); it != map.end(); ++it)
2330 LOG(VB_COMMFLAG, LOG_INFO, QString(
" %1:%2")
2331 .arg(it.key()).arg(*it));
2341 show_map_t::const_iterator sit;
2342 for (sit = in.begin(); sit != in.end(); ++sit)
2350 frm_dir_map_t::iterator it = out.begin();
2351 if (it == out.end())
2354 switch (out[it.key()])
2377 LOG(VB_COMMFLAG, LOG_INFO,
"CommDetect::CleanupFrameInfo()");
2383 std::array<int,256> avgHistogram {};
2385 int newThreshold = -1;
2387 LOG(VB_COMMFLAG, LOG_INFO,
2388 QString(
"ClassicCommDetect: Only found %1 blank frames but "
2389 "wanted at least %2, rechecking data using higher "
2396 avgHistogram.fill(0);
2399 avgHistogram[std::clamp(
m_frameInfo[i].avgBrightness, 0, 255)] += 1;
2401 for (
int i = 1; i <= 255 && minAvg == -1; i++)
2405 newThreshold = minAvg + 3;
2406 LOG(VB_COMMFLAG, LOG_INFO,
2407 QString(
"Minimum Average Brightness on a frame "
2408 "was %1, will use %2 as new threshold")
2409 .arg(minAvg).arg(newThreshold));
2425 LOG(VB_COMMFLAG, LOG_INFO,
2426 QString(
"Found %1 blank frames using new value")
2437 for (
int offset = 1; offset <= 10; offset++)
2442 for (
int offset = 1; offset <= 10; offset++)
2452 if ((before < 4) && (after < 4))
2457 if ((before > 6) && (after > 6))
2465 LOG(VB_COMMFLAG, LOG_INFO,
"CommDetect::GetLogoCommBreakMap()");
2469 bool PrevFrameLogo =
false;
2473 bool CurrentFrameLogo =
2476 if (!PrevFrameLogo && CurrentFrameLogo)
2478 else if (PrevFrameLogo && !CurrentFrameLogo)
2481 PrevFrameLogo = CurrentFrameLogo;
2496 out <<
tmp.constData() <<
" mark" << std::endl;
2501 QMap<long long, FrameInfoEntry>::const_iterator it =
m_frameInfo.find(i);
2505 QByteArray atmp = (*it).toString(i,
verbose).toLatin1();
2506 out << atmp.constData() <<
" ";
2509 frm_dir_map_t::const_iterator mit = comm_breaks->find(i);
2510 if (mit != comm_breaks->end())
2514 atmp =
tmp.toLatin1();
2516 out << atmp.constData();