MythTV master
FrameAnalyzer.cpp
Go to the documentation of this file.
2#include "CommDetector2.h"
3#include "FrameAnalyzer.h"
4
5using namespace commDetector2;
6
7namespace frameAnalyzer {
8
9bool
10rrccinrect(int rr, int cc, int rrow, int rcol, int rwidth, int rheight)
11{
12 return rr >= rrow && cc >= rcol &&
13 rr < rrow + rheight && cc < rcol + rwidth;
14}
15
16void
18 const char *comment)
19{
20 for (FrameAnalyzer::FrameMap::const_iterator ii = frameMap->begin();
21 ii != frameMap->end();
22 ++ii)
23 {
24 /*
25 * QMap'd as 0-based index, but display as 1-based index to match "Edit
26 * Recording" OSD.
27 */
28 long long bb = ii.key() + 1;
29 if (*ii)
30 {
31 long long ee = bb + *ii;
32 long long len = ee - bb;
33
34 LOG(VB_COMMFLAG, LOG_INFO, QString("%1: %2-%3 (%4-%5, %6)")
35 .arg(comment,
36 QString::number(bb, 6),
37 QString::number(ee - 1, 6),
38 frameToTimestamp(bb, fps),
39 frameToTimestamp(ee - 1, fps),
40 frameToTimestamp(len, fps)));
41 }
42 else
43 {
44 LOG(VB_COMMFLAG, LOG_INFO, QString("%1: %2 (%3)")
45 .arg(comment,
46 QString::number(bb, 6),
47 frameToTimestamp(bb, fps)));
48 }
49 }
50}
51
52void
54 const char *comment)
55{
56 for (FrameAnalyzer::FrameMap::const_iterator ii = frameMap->begin();
57 ii != frameMap->end();
58 ++ii)
59 {
60 /*
61 * QMap'd as 0-based index, but display as 1-based index to match "Edit
62 * Recording" OSD.
63 */
64 long long bb = ii.key() + 1;
65 if (*ii)
66 {
67 long long ee = bb + *ii;
68 long long len = ee - bb;
69
70 LOG(VB_COMMFLAG, LOG_INFO, QString("%1: %2-%3 (%4-%5, %6)")
71 .arg(comment,
72 QString::number(bb, 6),
73 QString::number(ee - 1, 6),
74 frameToTimestamp(bb, fps),
75 frameToTimestamp(ee - 1, fps),
76 frameToTimestampms(len, fps)));
77 }
78 else
79 {
80 LOG(VB_COMMFLAG, LOG_INFO, QString("%1: %2 (%3)")
81 .arg(comment,
82 QString::number(bb, 6),
83 frameToTimestamp(bb, fps)));
84 }
85 }
86}
87
88long long
90{
91 return std::accumulate(frameMap->cbegin(), frameMap->cend(),
92 static_cast<long long>(0));
93}
94
95bool
96removeShortBreaks(FrameAnalyzer::FrameMap *breakMap, float fps, int minbreaklen,
97 bool verbose)
98{
99 /*
100 * Remove any breaks that are less than "minbreaklen" units long.
101 *
102 * Return whether or not any breaks were actually removed.
103 */
104 FrameAnalyzer::FrameMap::Iterator bb;
105
106 bool removed = false;
107
108 /* Don't remove the initial commercial break, no matter how short. */
109 bb = breakMap->begin();
110 if (bb != breakMap->end() && bb.key() == 0)
111 ++bb;
112 while (bb != breakMap->end())
113 {
114 if (*bb >= minbreaklen)
115 {
116 ++bb;
117 continue;
118 }
119
120 /* Don't remove the final commercial break, no matter how short. */
121 FrameAnalyzer::FrameMap::Iterator bbNext = bb;
122 ++bbNext;
123 if (bbNext == breakMap->end())
124 break;
125
126 if (verbose)
127 {
128 long long start = bb.key();
129 long long end = start + *bb - 1;
130 LOG(VB_COMMFLAG, LOG_INFO, QString("Removing break %1-%2 (%3-%4)")
131 .arg(frameToTimestamp(start, fps),
132 frameToTimestamp(end, fps))
133 .arg(start + 1).arg(end + 1));
134 }
135 bb = breakMap->erase(bb);
136 removed = true;
137 }
138
139 return removed;
140}
141
142bool
143removeShortSegments(FrameAnalyzer::FrameMap *breakMap, long long nframes,
144 float fps, int minseglen, bool verbose)
145{
146 /*
147 * Remove any segments that are less than "minseglen" units long.
148 *
149 * Return whether or not any segments were actually removed.
150 */
151 FrameAnalyzer::FrameMap::Iterator bb;
152 FrameAnalyzer::FrameMap::Iterator bbnext;
153
154 bool removed = false;
155
156 for (bb = breakMap->begin(); bb != breakMap->end(); bb = bbnext)
157 {
158 /* Never remove initial segment (beginning at frame 0). */
159 if (bb == breakMap->begin() && bb != breakMap->end() &&
160 bb.key() != 0 && bb.key() < minseglen)
161 ++bb;
162
163 bbnext = bb;
164 ++bbnext;
165 long long brkb = bb.key();
166 long long segb = brkb + *bb;
167 long long sege = bbnext == breakMap->end() ? nframes : bbnext.key();
168 long long seglen = sege - segb;
169 if (seglen >= minseglen)
170 continue;
171
172 /* Merge break with next break. */
173 if (bbnext == breakMap->end())
174 {
175 if (segb != nframes)
176 {
177 /* Extend break "bb" to end of recording. */
178 if (verbose)
179 {
180 long long old1 = brkb;
181 long long old2 = segb - 1;
182 long long new1 = brkb;
183 long long new2 = nframes - 1;
184 LOG(VB_COMMFLAG, LOG_INFO,
185 QString("Removing segment %1-%2 (%3-%4)")
186 .arg(frameToTimestamp(segb + 1, fps),
187 frameToTimestamp(sege + 1, fps))
188 .arg(segb + 1).arg(sege + 1));
189 LOG(VB_COMMFLAG, LOG_INFO,
190 QString("Replacing break %1-%2 (%3-%4)"
191 " with %5-%6 (%7-%8, EOF)")
192 .arg(frameToTimestamp(old1 + 1, fps),
193 frameToTimestamp(old2 + 1, fps))
194 .arg(old1 + 1).arg(old2 + 1)
195 .arg(frameToTimestamp(new1 + 1, fps),
196 frameToTimestamp(new2 + 1, fps))
197 .arg(new1 + 1).arg(new2 + 1));
198 }
199 breakMap->remove(brkb);
200 breakMap->insert(brkb, nframes - brkb);
201 removed = true;
202 }
203 }
204 else
205 {
206 /* Extend break "bb" to cover "bbnext"; delete "bbnext". */
207 if (verbose)
208 {
209 long long old1 = brkb;
210 long long old2 = segb - 1;
211 long long new1 = brkb;
212 long long new2 = bbnext.key() + *bbnext - 1;
213 LOG(VB_COMMFLAG, LOG_INFO,
214 QString("Removing segment %1-%2 (%3-%4)")
215 .arg(frameToTimestamp(segb + 1, fps),
216 frameToTimestamp(sege + 1, fps))
217 .arg(segb + 1).arg(sege + 1));
218 LOG(VB_COMMFLAG, LOG_INFO,
219 QString("Replacing break %1-%2 (%3-%4)"
220 " with %5-%6 (%7-%8)")
221 .arg(frameToTimestamp(old1 + 1, fps),
222 frameToTimestamp(old2 + 1, fps))
223 .arg(old1 + 1).arg(old2 + 1)
224 .arg(frameToTimestamp(new1 + 1, fps),
225 frameToTimestamp(new2 + 1, fps))
226 .arg(new1 + 1).arg(new2 + 1));
227 }
228 breakMap->remove(brkb);
229 breakMap->insert(brkb, bbnext.key() + *bbnext - brkb);
230
231 bb = bbnext;
232 ++bbnext;
233 if (verbose)
234 {
235 long long start = bb.key();
236 long long end = start + *bb - 1;
237 LOG(VB_COMMFLAG, LOG_INFO,
238 QString("Removing break %1-%2 (%3-%4)")
239 .arg(frameToTimestamp(start + 1, fps),
240 frameToTimestamp(end + 1, fps))
241 .arg(start + 1).arg(end + 1));
242 }
243 breakMap->erase(bb);
244
245 removed = true;
246 }
247 }
248
249 return removed;
250}
251
252FrameAnalyzer::FrameMap::const_iterator
253frameMapSearchForwards(const FrameAnalyzer::FrameMap *frameMap, long long mark,
254 long long markend)
255{
256 /*
257 * Search forwards to find the earliest block "block" such that
258 *
259 * mark <= blockbegin < markend
260 *
261 * Return frameMap->constEnd() if there is no such block.
262 */
263 FrameAnalyzer::FrameMap::const_iterator block = frameMap->constBegin();
264
265 for (; block != frameMap->constEnd(); ++block)
266 {
267 const long long bb = block.key();
268 const long long ee = bb + *block;
269 if (mark < ee)
270 {
271 if (mark <= bb && bb < markend)
272 return block;
273 break;
274 }
275 }
276 return frameMap->constEnd();
277}
278
279FrameAnalyzer::FrameMap::const_iterator
281 long long markbegin, long long mark)
282{
283 /*
284 * Search backards to find the latest block "block" such that
285 *
286 * markbegin < blockend <= mark
287 *
288 * Return frameMap->constEnd() if there is no such block.
289 */
290 FrameAnalyzer::FrameMap::const_iterator block = frameMap->constEnd();
291 for (--block; block != frameMap->constBegin(); --block)
292 {
293 const long long bb = block.key();
294 const long long ee = bb + *block;
295 if (bb < mark)
296 {
297 if (markbegin < ee && ee <= mark)
298 return block;
299 break;
300 }
301 }
302 return frameMap->constEnd();
303}
304
305}; /* namespace */
306
307/* vim: set expandtab tabstop=4 shiftwidth=4: */
QMap< long long, long long > FrameMap
Definition: FrameAnalyzer.h:45
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
QString frameToTimestamp(long long frameno, float fps)
QString frameToTimestampms(long long frameno, float fps)
long long frameAnalyzerMapSum(const FrameAnalyzer::FrameMap *frameMap)
void frameAnalyzerReportMapms(const FrameAnalyzer::FrameMap *frameMap, float fps, const char *comment)
FrameAnalyzer::FrameMap::const_iterator frameMapSearchForwards(const FrameAnalyzer::FrameMap *frameMap, long long mark, long long markend)
bool removeShortSegments(FrameAnalyzer::FrameMap *breakMap, long long nframes, float fps, int minseglen, bool verbose)
bool rrccinrect(int rr, int cc, int rrow, int rcol, int rwidth, int rheight)
void frameAnalyzerReportMap(const FrameAnalyzer::FrameMap *frameMap, float fps, const char *comment)
FrameAnalyzer::FrameMap::const_iterator frameMapSearchBackwards(const FrameAnalyzer::FrameMap *frameMap, long long markbegin, long long mark)
bool removeShortBreaks(FrameAnalyzer::FrameMap *breakMap, float fps, int minbreaklen, bool verbose)