helens mcf fixes
From: Mark Spieth <mspieth@digivation.com.au>
---
.../programs/mythcommflag/ClassicCommDetector.cpp | 58 +++++++++++++-------
.../programs/mythcommflag/ClassicLogoDetector.cpp | 21 ++++++-
2 files changed, 54 insertions(+), 25 deletions(-)
diff --git a/mythtv/programs/mythcommflag/ClassicCommDetector.cpp b/mythtv/programs/mythcommflag/ClassicCommDetector.cpp
index 9d0d4d7..c545039 100644
a
|
b
|
typedef enum frameAspects { |
31 | 31 | } FrameAspects; |
32 | 32 | |
33 | 33 | typedef enum frameFormats { |
34 | | COMM_FORMAT_NORMAL = 0, |
35 | | COMM_FORMAT_LETTERBOX, |
36 | | COMM_FORMAT_PILLARBOX, |
37 | | COMM_FORMAT_MAX |
| 34 | COMM_FORMAT_NORMAL = 0, |
| 35 | COMM_FORMAT_LETTERBOX = 1, |
| 36 | COMM_FORMAT_PILLARBOX = 2, |
| 37 | COMM_FORMAT_MAX = 4, |
38 | 38 | } FrameFormats; |
39 | 39 | |
40 | 40 | static QString toStringFrameMaskValues(int mask, bool verbose) |
… |
… |
static QString toStringFrameFormats(int format, bool verbose) |
87 | 87 | switch (format) |
88 | 88 | { |
89 | 89 | case COMM_FORMAT_NORMAL: |
90 | | return (verbose) ? "normal" : "N"; |
| 90 | return (verbose) ? "normal" : " N "; |
91 | 91 | case COMM_FORMAT_LETTERBOX: |
92 | | return (verbose) ? "letter" : "L"; |
| 92 | return (verbose) ? "letter" : " L "; |
93 | 93 | case COMM_FORMAT_PILLARBOX: |
94 | | return (verbose) ? "pillar" : "P"; |
| 94 | return (verbose) ? "pillar" : " P "; |
| 95 | case COMM_FORMAT_LETTERBOX | COMM_FORMAT_PILLARBOX: |
| 96 | return (verbose) ? "letter,pillar" : "L,P"; |
95 | 97 | case COMM_FORMAT_MAX: |
96 | | return (verbose) ? " max " : "M"; |
| 98 | return (verbose) ? " max " : " M "; |
97 | 99 | } |
98 | 100 | |
99 | | return (verbose) ? " null " : "n"; |
| 101 | return (verbose) ? "unknown" : " U "; |
100 | 102 | } |
101 | 103 | |
102 | 104 | QString FrameInfoEntry::GetHeader(void) |
… |
… |
ClassicCommDetector::ClassicCommDetector(SkipType commDetectMethod_in, |
152 | 154 | fps(0.0), framesProcessed(0), |
153 | 155 | preRoll(0), postRoll(0) |
154 | 156 | { |
155 | | commDetectBorder = |
156 | | gCoreContext->GetNumSetting("CommDetectBorder", 20); |
157 | 157 | commDetectBlankFrameMaxDiff = |
158 | 158 | gCoreContext->GetNumSetting("CommDetectBlankFrameMaxDiff", 25); |
159 | 159 | commDetectDarkBrightness = |
… |
… |
void ClassicCommDetector::Init() |
189 | 189 | postRoll = (long long)( |
190 | 190 | max(int64_t(0), int64_t(stopsAt.secsTo(recordingStopsAt))) * fps); |
191 | 191 | |
| 192 | // CommDetectBorder's default value of 20 predates the change to use |
| 193 | // ffmpeg's lowres decoding capability by 5 years. |
| 194 | // I believe it should be adjusted based on the height of the lowres video |
| 195 | // CommDetectBorder * height / 720 seems to produce reasonable results. |
| 196 | // source height = 480 gives border = 20 * 480 / 4 / 720 = 2 |
| 197 | // source height = 720 gives border = 20 * 720 / 4 / 720 = 5 |
| 198 | // source height = 1080 gives border = 20 * 1080 / 4 / 720 = 7 |
| 199 | commDetectBorder = |
| 200 | gCoreContext->GetNumSetting("CommDetectBorder", 20) * height / 720; |
| 201 | |
192 | 202 | #ifdef SHOW_DEBUG_WIN |
193 | 203 | comm_debug_init(width, height); |
194 | 204 | #endif |
… |
… |
bool ClassicCommDetector::go() |
316 | 326 | |
317 | 327 | if (commDetectMethod & COMM_DETECT_LOGO) |
318 | 328 | { |
| 329 | // Use a different border for logo detection. |
| 330 | // If we try to detect logos in letterboxed areas, |
| 331 | // chances are we won't detect the logo. |
| 332 | // Generally speaking, SD video is likely to be letter boxed |
| 333 | // and HD video is not likely to be letter boxed. |
| 334 | // To detect logos, try to exclude letterboxed area from SD video |
| 335 | // but exclude too much from HD video and you'll miss the logo. |
| 336 | // Using the same border for both with no scaling seems to be |
| 337 | // a good compromise. |
| 338 | int logoDetectBorder = |
| 339 | gCoreContext->GetNumSetting("CommDetectLogoBorder", 16); |
319 | 340 | logoDetector = new ClassicLogoDetector(this, width, height, |
320 | | commDetectBorder, horizSpacing, vertSpacing); |
| 341 | logoDetectBorder, horizSpacing, vertSpacing); |
321 | 342 | |
322 | 343 | requiredHeadStart += max( |
323 | 344 | int64_t(0), int64_t(recordingStartedAt.secsTo(startedAt))); |
… |
… |
void ClassicCommDetector::ProcessFrame(VideoFrame *frame, |
897 | 918 | delete[] colMax; |
898 | 919 | colMax = 0; |
899 | 920 | |
| 921 | frameInfo[curFrameNumber].format = COMM_FORMAT_NORMAL; |
900 | 922 | if ((topDarkRow > commDetectBorder) && |
901 | 923 | (topDarkRow < (height * .20)) && |
902 | 924 | (bottomDarkRow < (height - commDetectBorder)) && |
903 | 925 | (bottomDarkRow > (height * .80))) |
904 | 926 | { |
905 | | frameInfo[curFrameNumber].format = COMM_FORMAT_LETTERBOX; |
| 927 | frameInfo[curFrameNumber].format |= COMM_FORMAT_LETTERBOX; |
906 | 928 | } |
907 | | else if ((leftDarkCol > commDetectBorder) && |
| 929 | if ((leftDarkCol > commDetectBorder) && |
908 | 930 | (leftDarkCol < (width * .20)) && |
909 | 931 | (rightDarkCol < (width - commDetectBorder)) && |
910 | 932 | (rightDarkCol > (width * .80))) |
911 | 933 | { |
912 | | frameInfo[curFrameNumber].format = COMM_FORMAT_PILLARBOX; |
913 | | } |
914 | | else |
915 | | { |
916 | | frameInfo[curFrameNumber].format = COMM_FORMAT_NORMAL; |
| 934 | frameInfo[curFrameNumber].format |= COMM_FORMAT_PILLARBOX; |
917 | 935 | } |
918 | 936 | |
919 | 937 | avg = totBrightness / blankPixelsChecked; |
… |
… |
void ClassicCommDetector::BuildAllMethodsCommList(void) |
1364 | 1382 | } |
1365 | 1383 | |
1366 | 1384 | if ((fbp->length > 4) && |
1367 | | (fbp->logoCount > (fbp->frames * 0.60)) && |
| 1385 | (!logoInfoAvailable || fbp->logoCount > (fbp->frames * 0.60)) && |
1368 | 1386 | (fbp->bfCount < (fbp->frames * 0.10))) |
1369 | 1387 | { |
1370 | 1388 | if (verboseDebugging) |
diff --git a/mythtv/programs/mythcommflag/ClassicLogoDetector.cpp b/mythtv/programs/mythcommflag/ClassicLogoDetector.cpp
index 0cdc680..ccf1545 100644
a
|
b
|
bool ClassicLogoDetector::searchForLogo(MythPlayer* player) |
100 | 100 | |
101 | 101 | edgeCounts = new EdgeMaskEntry[width * height]; |
102 | 102 | |
| 103 | // Back in 2005, a threshold of 50 minimum pixelsInMask was established. |
| 104 | // I don't know whether that was tested against SD or HD resolutions. |
| 105 | // I do know that in 2010, mythcommflag was changed to use ffmpeg's |
| 106 | // lowres support, effectively dividing the video area by 16. |
| 107 | // But the 50 pixel minimum was not adjusted accordingly. |
| 108 | // I believe the minimum threshold should vary with the video's area. |
| 109 | // I am using 1280x720 (for 720p) video as the baseline. |
| 110 | // This should improve logo detection for SD video. |
| 111 | int minPixelsInMask = 50 * (width*height) / (1280*720 / 16); |
| 112 | |
103 | 113 | for (i = 0; edgeDiffs[i] != 0 && !logoInfoAvailable; i++) |
104 | 114 | { |
105 | 115 | int pixelsInMask = 0; |
106 | 116 | |
107 | | LOG(VB_COMMFLAG, LOG_INFO, QString("Trying with edgeDiff == %1") |
108 | | .arg(edgeDiffs[i])); |
| 117 | LOG(VB_COMMFLAG, LOG_INFO, QString("Trying with edgeDiff == %1, minPixelsInMask=%2") |
| 118 | .arg(edgeDiffs[i]).arg(minPixelsInMask)); |
109 | 119 | |
110 | 120 | memset(edgeCounts, 0, sizeof(EdgeMaskEntry) * width * height); |
111 | 121 | memset(edgeMask, 0, sizeof(EdgeMaskEntry) * width * height); |
… |
… |
bool ClassicLogoDetector::searchForLogo(MythPlayer* player) |
237 | 247 | #endif |
238 | 248 | if (((logoMaxX - logoMinX) < (width / 4)) && |
239 | 249 | ((logoMaxY - logoMinY) < (height / 4)) && |
240 | | (pixelsInMask > 50)) |
| 250 | (pixelsInMask > minPixelsInMask)) |
241 | 251 | { |
242 | 252 | logoInfoAvailable = true; |
243 | 253 | logoEdgeDiff = edgeDiffs[i]; |
244 | 254 | |
245 | 255 | LOG(VB_COMMFLAG, LOG_INFO, |
246 | 256 | QString("Using Logo area: topleft (%1,%2), " |
247 | | "bottomright (%3,%4)") |
| 257 | "bottomright (%3,%4), pixelsInMask (%5).") |
248 | 258 | .arg(logoMinX).arg(logoMinY) |
249 | | .arg(logoMaxX).arg(logoMaxY)); |
| 259 | .arg(logoMaxX).arg(logoMaxY) |
| 260 | .arg(pixelsInMask)); |
250 | 261 | } |
251 | 262 | else |
252 | 263 | { |