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");
711 LOG(VB_COMMFLAG, LOG_INFO,
712 QString(
"CommDetect::SetVideoParams called with aspect = %1")
716 if (fabs(aspect - 1.333333F) < 0.1F)
721 LOG(VB_COMMFLAG, LOG_INFO,
722 QString(
"Aspect Ratio changed from %1 to %2 at frame %3")
736 LOG(VB_COMMFLAG, LOG_ERR,
737 QString(
"Unable to keep track of Aspect ratio change because "
738 "frameInfo for frame number %1 does not exist.")
746 long long frame_number)
750 int blankPixelsChecked = 0;
751 long long totBrightness = 0;
752 auto *rowMax =
new unsigned char[
m_height];
753 auto *colMax =
new unsigned char[
m_width];
754 memset(rowMax, 0,
sizeof(*rowMax)*
m_height);
755 memset(colMax, 0,
sizeof(*colMax)*
m_width);
762 if (!frame || !(frame->
m_buffer) || frame_number == -1 ||
765 LOG(VB_COMMFLAG, LOG_ERR,
"CommDetect: Invalid video frame or codec, "
766 "unable to process frame.");
774 LOG(VB_COMMFLAG, LOG_ERR,
"CommDetect: Width or Height is 0, "
775 "unable to process frame.");
782 unsigned char* framePtr = frame->
m_buffer;
785 fInfo.minBrightness = -1;
786 fInfo.maxBrightness = -1;
787 fInfo.avgBrightness = -1;
788 fInfo.sceneChangePercent = -1;
831 uchar
pixel = framePtr[y * bytesPerLine + x];
835 bool checkPixel =
false;
845 blankPixelsChecked++;
846 totBrightness +=
pixel;
854 if (
pixel > rowMax[y])
857 if (
pixel > colMax[x])
907 (leftDarkCol < (
m_width * .20)) &&
909 (rightDarkCol > (
m_width * .80)))
914 int avg = totBrightness / blankPixelsChecked;
949 (CheckRatingSymbol()))
975 LOG(VB_COMMFLAG, LOG_DEBUG, QString(
"Frame: %1 -> %2 %3 %4 %5 %6 %7 %8")
986 #ifdef SHOW_DEBUG_WIN
987 comm_debug_show(frame->buf);
998 LOG(VB_COMMFLAG, LOG_INFO,
"CommDetect::ClearAllMaps()");
1011 LOG(VB_COMMFLAG, LOG_INFO,
"CommDetect::GetBlankCommMap()");
1021 LOG(VB_COMMFLAG, LOG_INFO,
"CommDetect::GetBlankCommBreakMap()");
1030 int64_t start_frame)
1032 LOG(VB_COMMFLAG, LOG_INFO,
"CommDetect::GetSceneChangeMap()");
1034 frm_dir_map_t::iterator it;
1036 if (start_frame == -1)
1040 if ((start_frame == -1) || ((int64_t)it.key() >= start_frame))
1041 scenes[it.key()] = *it;
1047 LOG(VB_COMMFLAG, LOG_INFO,
"CommDetect::BuildMasterCommList()");
1053 frm_dir_map_t::const_iterator it = a.begin();
1054 for (; it != a.end(); ++it)
1055 newMap[it.key()] = *it;
1058 if ((a.size() > 1) &&
1062 frm_dir_map_t::const_iterator it_a;
1063 frm_dir_map_t::const_iterator it_b;
1068 if ((it_b.key() < 2) && (it_a.key() > 2))
1070 newMap.remove(it_a.key());
1076 frm_dir_map_t::const_iterator it;
1081 for (; it != a.end(); ++it)
1088 for (; it != b.end(); ++it)
1097 newMap.remove(max_a);
1102 if ((a.size() > 3) &&
1105 frm_dir_map_t::const_iterator it_a;
1106 frm_dir_map_t::const_iterator it_b;
1112 while (it_b != a.end())
1114 uint64_t fdiff = it_b.key() - it_a.key();
1115 bool allTrue =
false;
1117 if (fdiff < (62 *
m_fps))
1119 uint64_t f = it_a.key() + 1;
1129 newMap.remove(it_a.key());
1130 newMap.remove(it_b.key());
1135 if (it_b != a.end())
1145 int format,
int aspect)
1160 if (finfo.
format == format)
1163 if (finfo.
aspect == aspect)
1169 LOG(VB_COMMFLAG, LOG_INFO,
"CommDetect::BuildAllMethodsCommList()");
1172 uint64_t lastStart = 0;
1173 uint64_t lastEnd = 0;
1174 int64_t firstLogoFrame = -1;
1178 std::array<uint64_t,COMM_FORMAT_MAX> formatCounts {};
1180 frm_dir_map_t::iterator it;
1187 uint64_t curFrame = 1;
1200 bool lastFrameWasBlank =
true;
1204 uint64_t aspectFrames = 0;
1221 formatCounts.fill(0);
1232 uint64_t formatFrames = 0;
1235 if (formatCounts[i] > formatFrames)
1238 formatFrames = formatCounts[i];
1254 if (!nextFrameIsBlank || !lastFrameWasBlank)
1258 fbp->
end = curFrame;
1267 fbp = &fblock[curBlock];
1276 fbp->
start = curFrame;
1279 lastFrameWasBlank =
true;
1283 lastFrameWasBlank =
false;
1289 (firstLogoFrame == -1))
1290 firstLogoFrame = curFrame;
1295 fbp->
end = curFrame;
1302 int maxBlock = curBlock;
1306 LOG(VB_COMMFLAG, LOG_INFO,
"Initial Block pass");
1307 LOG(VB_COMMFLAG, LOG_DEBUG,
1308 "Block StTime StFrm EndFrm Frames Secs "
1309 "Bf Lg Cnt RT Cnt SC Cnt SC Rt FmtMch AspMch Score");
1310 LOG(VB_COMMFLAG, LOG_INFO,
1311 "----- ------ ------ ------ ------ ------- "
1312 "--- ------ ------ ------ ----- ------ ------ -----");
1313 while (curBlock <= maxBlock)
1315 fbp = &fblock[curBlock];
1318 LOG(VB_COMMFLAG, LOG_DEBUG, msg);
1323 LOG(VB_COMMFLAG, LOG_DEBUG,
1324 QString(
" FRAMES > %1").arg(
m_fps));
1329 LOG(VB_COMMFLAG, LOG_DEBUG,
1330 " length > max comm length, +20");
1337 LOG(VB_COMMFLAG, LOG_DEBUG,
1338 " length > max comm break length, +20");
1348 LOG(VB_COMMFLAG, LOG_DEBUG,
1349 " length > 4 && logoCount > frames * 0.60 && "
1350 "bfCount < frames * .10");
1355 LOG(VB_COMMFLAG, LOG_DEBUG,
1356 " length > max comm break length, +20");
1362 LOG(VB_COMMFLAG, LOG_DEBUG,
1363 " length <= max comm break length, +10");
1373 LOG(VB_COMMFLAG, LOG_DEBUG,
1374 " logoInfoAvailable && logoCount < frames * .50, "
1383 LOG(VB_COMMFLAG, LOG_DEBUG,
1384 " rating symbol present > 5% of time, +20");
1388 if ((fbp->
scRate > 1.0) &&
1392 LOG(VB_COMMFLAG, LOG_DEBUG,
" scRate > 1.0, -10");
1398 LOG(VB_COMMFLAG, LOG_DEBUG,
" scRate > 2.0, -10");
1408 LOG(VB_COMMFLAG, LOG_DEBUG,
1409 " < 10% of frames match show letter/pillar-box "
1415 if ((abs((
int)(fbp->
frames - (15 *
m_fps))) < 5 ) ||
1420 LOG(VB_COMMFLAG, LOG_DEBUG,
1421 " block appears to be standard comm length, -10");
1428 LOG(VB_COMMFLAG, LOG_DEBUG,
1429 QString(
" FRAMES <= %1").arg(
m_fps));
1432 (fbp->
start >= firstLogoFrame) &&
1436 LOG(VB_COMMFLAG, LOG_DEBUG,
1437 " logoInfoAvailable && logoCount == 0, -10");
1446 LOG(VB_COMMFLAG, LOG_DEBUG,
1447 " < 10% of frames match show letter/pillar-box "
1456 LOG(VB_COMMFLAG, LOG_DEBUG,
1457 " rating symbol present > 25% of time, +10");
1466 LOG(VB_COMMFLAG, LOG_DEBUG,
1467 " < 10% of frames match show aspect, -20");
1472 LOG(VB_COMMFLAG, LOG_DEBUG, msg);
1481 LOG(VB_COMMFLAG, LOG_DEBUG,
"============================================");
1482 LOG(VB_COMMFLAG, LOG_INFO,
"Second Block pass");
1483 LOG(VB_COMMFLAG, LOG_DEBUG,
1484 "Block StTime StFrm EndFrm Frames Secs "
1485 "Bf Lg Cnt RT Cnt SC Cnt SC Rt FmtMch AspMch Score");
1486 LOG(VB_COMMFLAG, LOG_DEBUG,
1487 "----- ------ ------ ------ ------ ------- "
1488 "--- ------ ------ ------ ----- ------ ------ -----");
1489 while (curBlock <= maxBlock)
1491 fbp = &fblock[curBlock];
1494 LOG(VB_COMMFLAG, LOG_DEBUG, msg);
1496 if ((curBlock > 0) && (curBlock < maxBlock))
1498 int nextScore = fblock[curBlock + 1].score;
1500 if ((lastScore < 0) && (nextScore < 0) && (fbp->
length < 35))
1504 LOG(VB_COMMFLAG, LOG_DEBUG,
1505 " lastScore < 0 && nextScore < 0 "
1506 "&& length < 35, setting -10");
1513 (lastScore < 0 && nextScore < 0))
1517 LOG(VB_COMMFLAG, LOG_DEBUG,
1518 " blanks > frames * 0.95 && frames < 2*m_fps && "
1519 "lastScore < 0 && nextScore < 0, setting -10");
1527 (fbp->
score < 20) &&
1532 LOG(VB_COMMFLAG, LOG_DEBUG,
1533 " frames < 120 * m_fps && (-20 < lastScore < 0) && "
1534 "thisScore > 0 && nextScore < 0, setting score = -10");
1542 (fbp->
score > -20) &&
1547 LOG(VB_COMMFLAG, LOG_DEBUG,
1548 " frames < 30 * m_fps && (0 < lastScore < 20) && "
1549 "thisScore < 0 && nextScore > 0, setting score = 10");
1555 if ((fbp->
score == 0) && (lastScore > 30))
1558 while(((curBlock + offset) <= maxBlock) &&
1559 (fblock[curBlock + offset].frames < (2 *
m_fps)) &&
1560 (fblock[curBlock + offset].score == 0))
1563 if ((curBlock + offset) <= maxBlock)
1566 if (fblock[curBlock + offset + 1].score > 0)
1568 for (; offset >= 0; offset--)
1570 fblock[curBlock + offset].score += 10;
1573 LOG(VB_COMMFLAG, LOG_DEBUG,
1574 QString(
" Setting block %1 score +10")
1575 .arg(curBlock+offset));
1579 else if (fblock[curBlock + offset + 1].score < 0)
1581 for (; offset >= 0; offset--)
1583 fblock[curBlock + offset].score -= 10;
1586 LOG(VB_COMMFLAG, LOG_DEBUG,
1587 QString(
" Setting block %1 score -10")
1588 .arg(curBlock+offset));
1596 LOG(VB_COMMFLAG, LOG_DEBUG, msg);
1598 lastScore = fbp->
score;
1602 LOG(VB_COMMFLAG, LOG_DEBUG,
"============================================");
1603 LOG(VB_COMMFLAG, LOG_INFO,
"FINAL Block stats");
1604 LOG(VB_COMMFLAG, LOG_DEBUG,
1605 "Block StTime StFrm EndFrm Frames Secs "
1606 "Bf Lg Cnt RT Cnt SC Cnt SC Rt FmtMch AspMch Score");
1607 LOG(VB_COMMFLAG, LOG_DEBUG,
1608 "----- ------ ------ ------ ------ ------- "
1609 "--- ------ ------ ------ ----- ------ ------ -----");
1612 int64_t breakStart = -1;
1613 while (curBlock <= maxBlock)
1615 fbp = &fblock[curBlock];
1616 int thisScore = fbp->
score;
1618 if ((breakStart >= 0) &&
1621 if (((fbp->
start - breakStart) >
1627 LOG(VB_COMMFLAG, LOG_DEBUG,
1628 QString(
"Closing commercial block at start of "
1629 "frame block %1 with length %2, frame "
1630 "block length of %3 frames would put comm "
1631 "block length over max of %4 seconds.")
1632 .arg(curBlock).arg(fbp->
start - breakStart)
1639 lastStart = breakStart;
1640 lastEnd = fbp->
start;
1647 LOG(VB_COMMFLAG, LOG_DEBUG,
1648 QString(
"Ignoring what appears to be commercial"
1649 " block at frame %1 with length %2, "
1650 "length of %3 frames would put comm "
1651 "block length under min of %4 seconds.")
1653 .arg(fbp->
start - breakStart)
1662 thisScore = lastScore;
1664 else if (thisScore < 0)
1666 if ((lastScore > 0) || (curBlock == 0))
1672 breakStart = lastStart;
1678 LOG(VB_COMMFLAG, LOG_DEBUG,
1679 QString(
"ReOpening commercial block at "
1680 "frame %1 because show less than "
1687 LOG(VB_COMMFLAG, LOG_DEBUG,
1688 "Opening initial commercial block "
1689 "at start of recording, block 0.");
1695 breakStart = fbp->
start;
1699 LOG(VB_COMMFLAG, LOG_DEBUG,
1700 QString(
"Starting new commercial block at "
1701 "frame %1 from start of frame block %2")
1702 .arg(fbp->
start).arg(curBlock));
1706 else if (curBlock == maxBlock)
1708 if ((fbp->
end - breakStart) >
1716 LOG(VB_COMMFLAG, LOG_DEBUG,
1717 QString(
"Closing final commercial block at "
1718 "frame %1").arg(fbp->
end));
1723 lastStart = breakStart;
1732 LOG(VB_COMMFLAG, LOG_DEBUG,
1733 QString(
"Ignoring what appears to be commercial"
1734 " block at frame %1 with length %2, "
1735 "length of %3 frames would put comm "
1736 "block length under min of %4 seconds.")
1738 .arg(fbp->
start - breakStart)
1747 else if ((lastScore < 0) &&
1750 if (((fbp->
start - breakStart) >
1756 lastStart = breakStart;
1757 lastEnd = fbp->
start;
1761 LOG(VB_COMMFLAG, LOG_DEBUG,
1762 QString(
"Closing commercial block at frame %1")
1770 LOG(VB_COMMFLAG, LOG_DEBUG,
1771 QString(
"Ignoring what appears to be commercial "
1772 "block at frame %1 with length %2, "
1773 "length of %3 frames would put comm block "
1774 "length under min of %4 seconds.")
1776 .arg(fbp->
start - breakStart)
1785 LOG(VB_COMMFLAG, LOG_DEBUG, msg);
1787 lastScore = thisScore;
1791 if ((breakStart != -1) &&
1796 LOG(VB_COMMFLAG, LOG_DEBUG,
1797 QString(
"Closing final commercial block started at "
1798 "block %1 and going to end of program. length "
1816 LOG(VB_COMMFLAG, LOG_DEBUG,
1817 "Adjusting start/end marks according to blanks.");
1818 for (it = tmpCommMap.begin(); it != tmpCommMap.end(); ++it)
1822 uint64_t lastStartLower = it.key();
1823 uint64_t lastStartUpper = it.key();
1824 while ((lastStartLower > 0) &&
1830 uint64_t adj = (lastStartUpper - lastStartLower) / 2;
1833 lastStart = lastStartLower + adj;
1836 LOG(VB_COMMFLAG, LOG_DEBUG, QString(
"Start Mark: %1 -> %2")
1837 .arg(it.key()).arg(lastStart));
1843 uint64_t lastEndLower = it.key();
1844 uint64_t lastEndUpper = it.key();
1848 while ((lastEndLower > 0) &&
1851 uint64_t adj = (lastEndUpper - lastEndLower) / 2;
1854 lastEnd = lastEndUpper - adj;
1857 LOG(VB_COMMFLAG, LOG_DEBUG, QString(
"End Mark : %1 -> %2")
1858 .arg(it.key()).arg(lastEnd));
1870 LOG(VB_COMMFLAG, LOG_INFO,
"CommDetect::BuildBlankFrameCommList()");
1879 int commercials = 0;
1884 bframes[frames++] = it.key();
1889 for(
int i = 0; i < frames; i++ )
1891 for(
int x=i+1; x < frames; x++ )
1896 int gap_length = bframes[x] - bframes[i];
1898 ((abs((
int)(gap_length - (5 *
m_fps))) < 5 ) ||
1899 (abs((
int)(gap_length - (10 *
m_fps))) < 7 ) ||
1900 (abs((
int)(gap_length - (15 *
m_fps))) < 10 ) ||
1901 (abs((
int)(gap_length - (20 *
m_fps))) < 11 ) ||
1902 (abs((
int)(gap_length - (30 *
m_fps))) < 12 ) ||
1903 (abs((
int)(gap_length - (40 *
m_fps))) < 1 ) ||
1904 (abs((
int)(gap_length - (45 *
m_fps))) < 1 ) ||
1905 (abs((
int)(gap_length - (60 *
m_fps))) < 15 ) ||
1906 (abs((
int)(gap_length - (90 *
m_fps))) < 10 ) ||
1907 (abs((
int)(gap_length - (120 *
m_fps))) < 10 ))) ||
1909 ((abs((
int)(gap_length - (5 *
m_fps))) < 11 ) ||
1910 (abs((
int)(gap_length - (10 *
m_fps))) < 13 ) ||
1911 (abs((
int)(gap_length - (15 *
m_fps))) < 16 ) ||
1912 (abs((
int)(gap_length - (20 *
m_fps))) < 17 ) ||
1913 (abs((
int)(gap_length - (30 *
m_fps))) < 18 ) ||
1914 (abs((
int)(gap_length - (40 *
m_fps))) < 3 ) ||
1915 (abs((
int)(gap_length - (45 *
m_fps))) < 3 ) ||
1916 (abs((
int)(gap_length - (60 *
m_fps))) < 20 ) ||
1917 (abs((
int)(gap_length - (90 *
m_fps))) < 20 ) ||
1918 (abs((
int)(gap_length - (120 *
m_fps))) < 20 ))))
1920 c_start[commercials] = bframes[i];
1921 c_end[commercials] = bframes[x] - 1;
1928 ((abs((
int)(gap_length - (30 *
m_fps))) < (
int)(
m_fps * 0.85)) ||
1929 (abs((
int)(gap_length - (60 *
m_fps))) < (
int)(
m_fps * 0.95)) ||
1930 (abs((
int)(gap_length - (90 *
m_fps))) < (
int)(
m_fps * 1.05)) ||
1931 (abs((
int)(gap_length - (120 *
m_fps))) < (
int)(
m_fps * 1.15))) &&
1932 ((x + 2) < frames) &&
1933 ((i + 2) < frames) &&
1934 ((bframes[i] + 1) == bframes[i+1]) &&
1935 ((bframes[x] + 1) == bframes[x+1]))
1937 c_start[commercials] = bframes[i];
1938 c_end[commercials] = bframes[x];
1950 if ((commercials > 1) &&
1951 (c_end[0] < (33 *
m_fps)) &&
1952 (c_start[1] > (c_end[0] + 40 *
m_fps)))
1956 bool first_comm =
true;
1957 for(; i < (commercials-1); i++)
1959 long long r = c_start[i];
1960 long long adjustment = 0;
1962 if ((r < (30 *
m_fps)) &&
1969 if ( i < (commercials-1))
1972 for(x = 0; x < (frames-1); x++)
1973 if (bframes[x] == r)
1975 while((x < (frames-1)) &&
1976 ((bframes[x] + 1 ) == bframes[x+1]) &&
1977 (bframes[x+1] < c_start[i+1]))
1984 (c_start[i+1] != (r+1)))
2014 LOG(VB_COMMFLAG, LOG_INFO,
"Blank-Frame Commercial Map" );
2016 LOG(VB_COMMFLAG, LOG_INFO, QString(
" %1:%2")
2017 .arg(it.key()).arg(*it));
2021 LOG(VB_COMMFLAG, LOG_INFO,
"Merged Blank-Frame Commercial Break Map" );
2023 LOG(VB_COMMFLAG, LOG_INFO, QString(
" %1:%2")
2024 .arg(it.key()).arg(*it));
2030 int section_start = -1;
2032 int *sc_histogram =
new int[seconds+1];
2036 memset(sc_histogram, 0, (seconds+1)*
sizeof(
int));
2040 sc_histogram[(uint64_t)(f /
m_fps)]++;
2043 for(
long long s = 0; s < (seconds + 1); s++)
2045 if (sc_histogram[s] > 2)
2047 if (section_start == -1)
2050 for(
int i = 0; i <
m_fps; i++, f++)
2055 i = (int)(
m_fps) + 1;
2063 if ((section_start >= 0) &&
2064 (s > (section_start + 32)))
2066 auto f = (
long long)(section_start *
m_fps);
2067 bool found_end =
false;
2069 for(
int i = 0; i <
m_fps; i++, f++)
2078 i = (int)(
m_fps) + 1;
2091 delete[] sc_histogram;
2093 if (section_start >= 0)
2098 frm_dir_map_t::iterator prev = it;
2105 (it.key() - prev.key()) < (30 *
m_fps))
2115 frm_dir_map_t::iterator dit;
2116 for (dit = deleteMap.begin(); dit != deleteMap.end(); ++dit)
2120 LOG(VB_COMMFLAG, LOG_INFO,
"Scene-Change Commercial Break Map" );
2123 LOG(VB_COMMFLAG, LOG_INFO, QString(
" %1:%2")
2124 .arg(it.key()).arg(*it));
2136 frm_dir_map_t::iterator it;
2137 LOG(VB_COMMFLAG, LOG_INFO,
"Logo Commercial Break Map" );
2139 LOG(VB_COMMFLAG, LOG_INFO, QString(
" %1:%2")
2140 .arg(it.key()).arg(*it));
2145 frm_dir_map_t::iterator it;
2146 frm_dir_map_t::iterator prev;
2147 QMap<long long, long long> tmpMap;
2148 QMap<long long, long long>::Iterator tmpMap_it;
2149 QMap<long long, long long>::Iterator tmpMap_prev;
2168 if ((((prev.key() + 1) == it.key()) ||
2169 ((prev.key() + (15 *
m_fps)) > it.key())) &&
2183 tmpMap[prev.key()] = it.key();
2188 tmpMap[prev.key()] = it.key();
2191 tmpMap_it = tmpMap.begin();
2192 tmpMap_prev = tmpMap_it;
2194 for(; tmpMap_it != tmpMap.end(); ++tmpMap_it, ++tmpMap_prev)
2198 if (((*tmpMap_prev + (35 *
m_fps)) > tmpMap_it.key()) &&
2199 ((*tmpMap_prev - tmpMap_prev.key()) > (35 *
m_fps)) &&
2200 ((*tmpMap_it - tmpMap_it.key()) > (35 *
m_fps)))
2213 if (breakMap.contains(i))
2215 int type = breakMap[i];
2225 for (uint64_t i = (f + 1); i-- > 0; )
2227 if (breakMap.contains(i))
2229 int type = breakMap[i];
2242 frm_dir_map_t::iterator it;
2245 LOG(VB_COMMFLAG, LOG_INFO,
2246 "---------------------------------------------------");
2247 for (it = map.begin(); it != map.end(); ++it)
2249 long long frame = it.key();
2251 int my_fps = (int)ceil(
m_fps);
2252 long long hour = (frame / my_fps) / 60 / 60;
2253 long long min = (frame / my_fps) / 60 - (hour * 60);
2254 long long sec = (frame / my_fps) - (min * 60) - (hour * 60 * 60);
2255 long long frm = frame - ((sec * my_fps) + (min * 60 * my_fps) +
2256 (hour * 60 * 60 * my_fps));
2257 int my_sec = (int)(frame / my_fps);
2258 msg = QString(
"%1 : %2 (%3:%4:%5.%6) (%7)")
2259 .arg(frame, 7).arg(flag).arg(hour, 2, 10, QChar(
'0')).arg(min, 2, 10, QChar(
'0'))
2260 .arg(sec, 2, 10, QChar(
'0')).arg(frm, 2, 10, QChar(
'0')).arg(my_sec);
2261 LOG(VB_COMMFLAG, LOG_INFO, msg);
2263 LOG(VB_COMMFLAG, LOG_INFO,
2264 "---------------------------------------------------");
2270 show_map_t::iterator it;
2271 show_map_t::iterator prev;
2274 if (map.size() <= 2)
2278 LOG(VB_COMMFLAG, LOG_INFO,
"Commercial Map Before condense:" );
2279 for (it = map.begin(); it != map.end(); ++it)
2281 LOG(VB_COMMFLAG, LOG_INFO, QString(
" %1:%2")
2282 .arg(it.key()).arg(*it));
2283 tmpMap[it.key()] = *it;
2286 prev = tmpMap.begin();
2289 while (it != tmpMap.end())
2293 ((it.key() - prev.key()) < (uint64_t)spacing))
2295 map.remove(prev.key());
2296 map.remove(it.key());
2307 for (it = map.begin(); it != map.end(); ++it)
2308 tmpMap[it.key()] = *it;
2310 prev = tmpMap.begin();
2313 while (it != tmpMap.end())
2317 ((it.key() - prev.key()) < (uint64_t)length))
2319 map.remove(prev.key());
2320 map.remove(it.key());
2326 LOG(VB_COMMFLAG, LOG_INFO,
"Commercial Map After condense:" );
2327 for (it = map.begin(); it != map.end(); ++it)
2328 LOG(VB_COMMFLAG, LOG_INFO, QString(
" %1:%2")
2329 .arg(it.key()).arg(*it));
2339 show_map_t::const_iterator sit;
2340 for (sit = in.begin(); sit != in.end(); ++sit)
2348 frm_dir_map_t::iterator it = out.begin();
2349 if (it == out.end())
2352 switch (out[it.key()])
2375 LOG(VB_COMMFLAG, LOG_INFO,
"CommDetect::CleanupFrameInfo()");
2381 std::array<int,256> avgHistogram {};
2383 int newThreshold = -1;
2385 LOG(VB_COMMFLAG, LOG_INFO,
2386 QString(
"ClassicCommDetect: Only found %1 blank frames but "
2387 "wanted at least %2, rechecking data using higher "
2394 avgHistogram.fill(0);
2397 avgHistogram[std::clamp(
m_frameInfo[i].avgBrightness, 0, 255)] += 1;
2399 for (
int i = 1; i <= 255 && minAvg == -1; i++)
2403 newThreshold = minAvg + 3;
2404 LOG(VB_COMMFLAG, LOG_INFO,
2405 QString(
"Minimum Average Brightness on a frame "
2406 "was %1, will use %2 as new threshold")
2407 .arg(minAvg).arg(newThreshold));
2423 LOG(VB_COMMFLAG, LOG_INFO,
2424 QString(
"Found %1 blank frames using new value")
2435 for (
int offset = 1; offset <= 10; offset++)
2440 for (
int offset = 1; offset <= 10; offset++)
2450 if ((before < 4) && (after < 4))
2455 if ((before > 6) && (after > 6))
2463 LOG(VB_COMMFLAG, LOG_INFO,
"CommDetect::GetLogoCommBreakMap()");
2467 bool PrevFrameLogo =
false;
2471 bool CurrentFrameLogo =
2474 if (!PrevFrameLogo && CurrentFrameLogo)
2476 else if (PrevFrameLogo && !CurrentFrameLogo)
2479 PrevFrameLogo = CurrentFrameLogo;
2494 out <<
tmp.constData() <<
" mark" << std::endl;
2499 QMap<long long, FrameInfoEntry>::const_iterator it =
m_frameInfo.find(i);
2503 QByteArray atmp = (*it).toString(i,
verbose).toLatin1();
2504 out << atmp.constData() <<
" ";
2507 frm_dir_map_t::const_iterator mit = comm_breaks->find(i);
2508 if (mit != comm_breaks->end())
2512 atmp =
tmp.toLatin1();
2514 out << atmp.constData();