MythTV  master
commbreakmap.cpp
Go to the documentation of this file.
1 
2 #include "commbreakmap.h"
3 
4 #include "mythcontext.h"
5 #include "mythmiscutil.h"
6 #include "programinfo.h"
7 
8 #define LOC QString("CommBreakMap: ")
9 
11  : m_commBreakIter(m_commBreakMap.end())
12 {
13  m_commrewindamount = gCoreContext->GetNumSetting("CommRewindAmount",0);
14  m_commnotifyamount = gCoreContext->GetNumSetting("CommNotifyAmount",0);
17  gCoreContext->GetNumSetting("AutoCommercialSkip", kCommSkipOff);
18  m_maxskip = gCoreContext->GetNumSetting("MaximumCommercialSkip", 3600);
19  m_maxShortMerge = gCoreContext->GetNumSetting("MergeShortCommBreaks", 0);
20 }
21 
23 {
24  QMutexLocker locker(&m_commBreakMapLock);
25  return m_autocommercialskip;
26 }
27 
29 {
30  m_lastSkipTime = time(nullptr);
31 }
32 
33 void CommBreakMap::SetAutoCommercialSkip(CommSkipMode autoskip, uint64_t framesplayed)
34 {
35  QMutexLocker locker(&m_commBreakMapLock);
36  SetTracker(framesplayed);
37  uint next = (kCommSkipIncr == autoskip) ?
38  (uint) m_autocommercialskip + 1 : (uint) autoskip;
40 }
41 
42 void CommBreakMap::SkipCommercials(int direction)
43 {
44  m_commBreakMapLock.lock();
45  if ((m_skipcommercials == 0 && direction != 0) ||
46  (m_skipcommercials != 0 && direction == 0))
47  m_skipcommercials = direction;
48  m_commBreakMapLock.unlock();
49 }
50 
51 void CommBreakMap::LoadMap(PlayerContext *player_ctx, uint64_t framesPlayed)
52 {
53  if (!player_ctx)
54  return;
55 
56  QMutexLocker locker(&m_commBreakMapLock);
57  player_ctx->LockPlayingInfo(__FILE__, __LINE__);
58  if (player_ctx->m_playingInfo)
59  {
60  m_commBreakMap.clear();
63  SetTracker(framesPlayed);
64  }
65  player_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
66 }
67 
68 void CommBreakMap::SetTracker(uint64_t framesPlayed)
69 {
70  QMutexLocker locker(&m_commBreakMapLock);
72  return;
73 
75  while (m_commBreakIter != m_commBreakMap.end())
76  {
77  if (framesPlayed <= m_commBreakIter.key())
78  break;
79 
81  }
82 
83  if (m_commBreakIter != m_commBreakMap.end())
84  {
85  LOG(VB_COMMFLAG, LOG_INFO, LOC +
86  QString("new commBreakIter = %1 @ frame %2, framesPlayed = %3")
87  .arg(*m_commBreakIter).arg(m_commBreakIter.key())
88  .arg(framesPlayed));
89  }
90 }
91 
93 {
94  QMutexLocker locker(&m_commBreakMapLock);
95  map.clear();
96  map = m_commBreakMap;
97 }
98 
99 bool CommBreakMap::IsInCommBreak(uint64_t frameNumber) const
100 {
101  QMutexLocker locker(&m_commBreakMapLock);
102  if (m_commBreakMap.isEmpty())
103  return false;
104 
105  frm_dir_map_t::const_iterator it = m_commBreakMap.find(frameNumber);
106  if (it != m_commBreakMap.end())
107  return true;
108 
109  int lastType = MARK_UNSET;
110  for (it = m_commBreakMap.begin(); it != m_commBreakMap.end(); ++it)
111  {
112  if (it.key() > frameNumber)
113  {
114  int type = *it;
115 
116  if (((type == MARK_COMM_END) ||
117  (type == MARK_CUT_END)) &&
118  ((lastType == MARK_COMM_START) ||
119  (lastType == MARK_CUT_START)))
120  return true;
121 
122  if ((type == MARK_COMM_START) ||
123  (type == MARK_CUT_START))
124  return false;
125  }
126 
127  lastType = *it;
128  }
129  return false;
130 }
131 
132 void CommBreakMap::SetMap(const frm_dir_map_t &newMap, uint64_t framesPlayed)
133 {
134  QMutexLocker locker(&m_commBreakMapLock);
135  LOG(VB_COMMFLAG, LOG_INFO, LOC +
136  QString("Setting New Commercial Break List, old size %1, new %2")
137  .arg(m_commBreakMap.size()).arg(newMap.size()));
138 
139  m_commBreakMap.clear();
140  m_commBreakMap = newMap;
141  m_hascommbreaktable = !m_commBreakMap.isEmpty();
142  SetTracker(framesPlayed);
143 }
144 
145 bool CommBreakMap::AutoCommercialSkip(uint64_t &jumpToFrame,
146  uint64_t framesPlayed,
147  double video_frame_rate,
148  uint64_t totalFrames,
149  QString &comm_msg)
150 {
151  QMutexLocker locker(&m_commBreakMapLock);
152  if (!m_hascommbreaktable)
153  return false;
154 
155  if (((time(nullptr) - m_lastSkipTime) <= 3) ||
156  ((time(nullptr) - m_lastCommSkipTime) <= 3))
157  {
158  SetTracker(framesPlayed);
159  return false;
160  }
161 
162  if (m_commBreakIter == m_commBreakMap.end())
163  return false;
164 
166  m_commBreakIter++;
167 
168  if (m_commBreakIter == m_commBreakMap.end())
169  return false;
170 
171  if (!((*m_commBreakIter == MARK_COMM_START) &&
173  (framesPlayed >= m_commBreakIter.key())) ||
175  (framesPlayed + m_commnotifyamount * video_frame_rate >=
176  m_commBreakIter.key())))))
177  {
178  return false;
179  }
180 
181  LOG(VB_COMMFLAG, LOG_INFO, LOC +
182  QString("AutoCommercialSkip(), current framesPlayed %1, commBreakIter "
183  "frame %2, incrementing commBreakIter")
184  .arg(framesPlayed).arg(m_commBreakIter.key()));
185 
186  ++m_commBreakIter;
187 
188  MergeShortCommercials(video_frame_rate);
189 
190  if (m_commBreakIter == m_commBreakMap.end())
191  {
192  LOG(VB_COMMFLAG, LOG_INFO, LOC + "AutoCommercialSkip(), at end of "
193  "commercial break list, will not skip.");
194  return false;
195  }
196 
198  {
199  LOG(VB_COMMFLAG, LOG_INFO, LOC + "AutoCommercialSkip(), new "
200  "commBreakIter mark is another start, "
201  "will not skip.");
202  return false;
203  }
204 
205  if (totalFrames &&
206  ((m_commBreakIter.key() + (10 * video_frame_rate)) > totalFrames))
207  {
208  LOG(VB_COMMFLAG, LOG_INFO, LOC + "AutoCommercialSkip(), skipping would "
209  "take us to the end of the file, will "
210  "not skip.");
211  return false;
212  }
213 
214  LOG(VB_COMMFLAG, LOG_INFO, LOC +
215  QString("AutoCommercialSkip(), new commBreakIter frame %1")
216  .arg(m_commBreakIter.key()));
217 
218  int skipped_seconds = (int)((m_commBreakIter.key() -
219  framesPlayed) / video_frame_rate);
220  QString skipTime = MythFormatTime(skipped_seconds, "m:ss");
222  {
223  //: %1 is the skip time
224  comm_msg = tr("Skip %1").arg(skipTime);
225  }
226  else
227  {
228  //: %1 is the skip time
229  comm_msg = tr("Commercial: %1").arg(skipTime);
230  }
231 
233  {
234  LOG(VB_COMMFLAG, LOG_INFO, LOC +
235  QString("AutoCommercialSkip(), auto-skipping to frame %1")
236  .arg(m_commBreakIter.key() -
237  (int)(m_commrewindamount * video_frame_rate)));
238 
240  m_lastCommSkipStart = framesPlayed;
241  m_lastCommSkipTime = time(nullptr);
242 
243  jumpToFrame = m_commBreakIter.key() -
244  (int)(m_commrewindamount * video_frame_rate);
245  return true;
246  }
247  ++m_commBreakIter;
248  return false;
249 }
250 
251 bool CommBreakMap::DoSkipCommercials(uint64_t &jumpToFrame,
252  uint64_t framesPlayed,
253  double video_frame_rate,
254  uint64_t totalFrames, QString &comm_msg)
255 {
256  QMutexLocker locker(&m_commBreakMapLock);
258  ((time(nullptr) - m_lastCommSkipTime) <= 5))
259  {
260  comm_msg = tr("Skipping Back.");
261 
262  if (m_lastCommSkipStart > (2.0 * video_frame_rate))
263  m_lastCommSkipStart -= (long long) (2.0 * video_frame_rate);
265  m_lastCommSkipTime = time(nullptr);
266  jumpToFrame = m_lastCommSkipStart;
267  return true;
268  }
270  m_lastCommSkipStart = framesPlayed;
271  m_lastCommSkipTime = time(nullptr);
272 
273  SetTracker(framesPlayed);
274 
275  if ((m_commBreakIter == m_commBreakMap.begin()) &&
276  (m_skipcommercials < 0))
277  {
278  comm_msg = tr("Start of program.");
279  jumpToFrame = 0;
280  return true;
281  }
282 
283  if ((m_skipcommercials > 0) &&
284  ((m_commBreakIter == m_commBreakMap.end()) ||
285  (((totalFrames) != 0U) &&
286  ((m_commBreakIter.key() + (10 * video_frame_rate)) > totalFrames))))
287  {
288  comm_msg = tr("At End, cannot Skip.");
289  return false;
290  }
291 
292  if (m_skipcommercials < 0)
293  {
294  m_commBreakIter--;
295 
296  int skipped_seconds = (int)(((int64_t)(m_commBreakIter.key()) -
297  (int64_t)framesPlayed) / video_frame_rate);
298 
299  // special case when hitting 'skip backwards' <3 seconds after break
300  if (skipped_seconds > -3)
301  {
302  if (m_commBreakIter == m_commBreakMap.begin())
303  {
304  comm_msg = tr("Start of program.");
305  jumpToFrame = 0;
306  return true;
307  }
308  m_commBreakIter--;
309  }
310  }
311  else
312  {
313  int skipped_seconds = (int)(((int64_t)(m_commBreakIter.key()) -
314  (int64_t)framesPlayed) / video_frame_rate);
315 
316  // special case when hitting 'skip' within 20 seconds of the break
317  // start or within commrewindamount of the break end
318  // Even though commrewindamount has a max of 10 per the settings UI,
319  // check for MARK_COMM_END to make the code generic
321  if (((type == MARK_COMM_START) && (skipped_seconds < 20)) ||
322  ((type == MARK_COMM_END) && (skipped_seconds < m_commrewindamount)))
323  {
324  m_commBreakIter++;
325 
326  if ((m_commBreakIter == m_commBreakMap.end()) ||
327  (((totalFrames) != 0U) &&
328  ((m_commBreakIter.key() + (10 * video_frame_rate)) >
329  totalFrames)))
330  {
331  comm_msg = tr("At End, cannot Skip.");
332  return false;
333  }
334  }
335  }
336 
337  if (m_skipcommercials > 0)
338  MergeShortCommercials(video_frame_rate);
339  int skipped_seconds = (int)(((int64_t)(m_commBreakIter.key()) -
340  (int64_t)framesPlayed) / video_frame_rate);
341  QString skipTime = MythFormatTime(skipped_seconds, "m:ss");
342 
343  if ((m_lastIgnoredManualSkip.secsTo(MythDate::current()) > 3) &&
344  (abs(skipped_seconds) >= m_maxskip))
345  {
346  //: %1 is the skip time
347  comm_msg = tr("Too Far %1").arg(skipTime);
349  return false;
350  }
351 
352  //: %1 is the skip time
353  comm_msg = tr("Skip %1").arg(skipTime);
354 
355  uint64_t jumpto = (m_skipcommercials > 0) ?
356  m_commBreakIter.key() - (long long)(m_commrewindamount * video_frame_rate):
357  m_commBreakIter.key();
358  m_commBreakIter++;
359  jumpToFrame = jumpto;
360  return true;
361 }
362 
363 void CommBreakMap::MergeShortCommercials(double video_frame_rate)
364 {
365  double maxMerge = m_maxShortMerge * video_frame_rate;
366  if (maxMerge <= 0.0 || (m_commBreakIter == m_commBreakMap.end()))
367  return;
368 
369  long long lastFrame = m_commBreakIter.key();
370  ++m_commBreakIter;
371  while ((m_commBreakIter != m_commBreakMap.end()) &&
372  (m_commBreakIter.key() - lastFrame < maxMerge))
373  {
374  ++m_commBreakIter;
375  }
376  --m_commBreakIter;
377 }
CommBreakMap::m_skipcommercials
int m_skipcommercials
Definition: commbreakmap.h:50
CommSkipMode
CommSkipMode
Definition: tv.h:131
CommBreakMap::m_lastSkipTime
time_t m_lastSkipTime
Definition: commbreakmap.h:57
MARK_COMM_END
@ MARK_COMM_END
Definition: programtypes.h:60
commbreakmap.h
PlayerContext::UnlockPlayingInfo
void UnlockPlayingInfo(const char *file, int line) const
Definition: playercontext.cpp:248
CommBreakMap::DoSkipCommercials
bool DoSkipCommercials(uint64_t &jumpToFrame, uint64_t framesPlayed, double video_frame_rate, uint64_t totalFrames, QString &comm_msg)
Definition: commbreakmap.cpp:251
MARK_CUT_END
@ MARK_CUT_END
Definition: programtypes.h:55
CommBreakMap::SetTracker
void SetTracker(uint64_t framesPlayed)
Definition: commbreakmap.cpp:68
CommBreakMap::MergeShortCommercials
void MergeShortCommercials(double video_frame_rate)
Definition: commbreakmap.cpp:363
arg
arg(title).arg(filename).arg(doDelete))
frm_dir_map_t
QMap< uint64_t, MarkTypes > frm_dir_map_t
Frame # -> Mark map.
Definition: programtypes.h:82
kCommSkipOn
@ kCommSkipOn
Definition: tv.h:133
CommBreakMap::m_autocommercialskip
CommSkipMode m_autocommercialskip
Definition: commbreakmap.h:51
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
CommBreakMap::GetMap
void GetMap(frm_dir_map_t &map) const
Definition: commbreakmap.cpp:92
CommBreakMap::m_commnotifyamount
int m_commnotifyamount
Definition: commbreakmap.h:53
CommBreakMap::SetMap
void SetMap(const frm_dir_map_t &newMap, uint64_t framesPlayed)
Definition: commbreakmap.cpp:132
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
kCommSkipCount
@ kCommSkipCount
Definition: tv.h:135
CommBreakMap::m_lastCommSkipStart
uint64_t m_lastCommSkipStart
Definition: commbreakmap.h:56
kCommSkipNotify
@ kCommSkipNotify
Definition: tv.h:134
programinfo.h
CommBreakMap::ResetLastSkip
void ResetLastSkip(void)
Definition: commbreakmap.cpp:28
CommBreakMap::m_commBreakIter
frm_dir_map_t::Iterator m_commBreakIter
Definition: commbreakmap.h:63
PlayerContext::m_playingInfo
ProgramInfo * m_playingInfo
Currently playing info.
Definition: playercontext.h:116
CommBreakMap::SetAutoCommercialSkip
void SetAutoCommercialSkip(CommSkipMode autoskip, uint64_t framesPlayed)
Definition: commbreakmap.cpp:33
PlayerContext::LockPlayingInfo
void LockPlayingInfo(const char *file, int line) const
Definition: playercontext.cpp:236
MythFormatTime
QString MythFormatTime(int secs, const QString &fmt)
Format a seconds time value.
Definition: mythmiscutil.cpp:1238
CommBreakMap::m_maxShortMerge
int m_maxShortMerge
Definition: commbreakmap.h:61
CommBreakMap::LoadMap
void LoadMap(PlayerContext *player_ctx, uint64_t framesPlayed)
Definition: commbreakmap.cpp:51
CommBreakMap::m_lastIgnoredManualSkip
QDateTime m_lastIgnoredManualSkip
Definition: commbreakmap.h:59
hardwareprofile.smolt.long
long
Definition: smolt.py:76
CommBreakMap::IsInCommBreak
bool IsInCommBreak(uint64_t frameNumber) const
Definition: commbreakmap.cpp:99
CommBreakMap::m_commrewindamount
int m_commrewindamount
Definition: commbreakmap.h:52
uint
unsigned int uint
Definition: compat.h:141
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:60
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:933
CommBreakMap::m_lastCommSkipDirection
int m_lastCommSkipDirection
Definition: commbreakmap.h:54
LOC
#define LOC
Definition: commbreakmap.cpp:8
CommBreakMap::m_lastCommSkipTime
time_t m_lastCommSkipTime
Definition: commbreakmap.h:55
CommBreakMap::GetAutoCommercialSkip
CommSkipMode GetAutoCommercialSkip(void) const
Definition: commbreakmap.cpp:22
MARK_CUT_START
@ MARK_CUT_START
Definition: programtypes.h:56
mythmiscutil.h
CommBreakMap::AutoCommercialSkip
bool AutoCommercialSkip(uint64_t &jumpToFrame, uint64_t framesPlayed, double video_frame_rate, uint64_t totalFrames, QString &comm_msg)
Definition: commbreakmap.cpp:145
MarkTypes
MarkTypes
Definition: programtypes.h:48
CommBreakMap::m_commBreakMap
frm_dir_map_t m_commBreakMap
Definition: commbreakmap.h:62
kCommSkipIncr
@ kCommSkipIncr
Definition: tv.h:136
mythcontext.h
CommBreakMap::CommBreakMap
CommBreakMap(void)
Definition: commbreakmap.cpp:10
CommBreakMap::m_commBreakMapLock
QMutex m_commBreakMapLock
Definition: commbreakmap.h:49
PlayerContext
Definition: playercontext.h:49
CommBreakMap::m_hascommbreaktable
bool m_hascommbreaktable
Definition: commbreakmap.h:58
MARK_UNSET
@ MARK_UNSET
Definition: programtypes.h:50
ProgramInfo::QueryCommBreakList
void QueryCommBreakList(frm_dir_map_t &frames) const
Definition: programinfo.cpp:3380
kCommSkipOff
@ kCommSkipOff
Definition: tv.h:132
CommBreakMap::m_maxskip
int m_maxskip
Definition: commbreakmap.h:60
MARK_COMM_START
@ MARK_COMM_START
Definition: programtypes.h:59
CommBreakMap::SkipCommercials
void SkipCommercials(int direction)
Definition: commbreakmap.cpp:42