MythTV  master
HLSPlaylistWorker.cpp
Go to the documentation of this file.
1 #include "HLSPlaylistWorker.h"
2 #include "HLSReader.h"
3 
4 const int PLAYLIST_FAILURE = 20; // number of consecutive failures after which
5  // an error will be propagated.
6 
7 #define LOC QString("%1 playlist: ").arg(m_parent->StreamURL().isEmpty() ? "Worker" : m_parent->StreamURL())
8 
10  : MThread("HLSPlaylist"), m_parent(parent)
11 {
12  LOG(VB_RECORD, LOG_DEBUG, LOC + "ctor");
13 }
14 
16 {
17  LOG(VB_RECORD, LOG_DEBUG, LOC + "dtor");
18 }
19 
21 {
22  LOG(VB_RECORD, LOG_INFO, LOC + "Cancel -- begin");
23  m_lock.lock();
24  m_cancel = true;
25  m_waitcond.wakeAll();
26  m_lock.unlock();
27  wait();
28  LOG(VB_RECORD, LOG_INFO, LOC + "Cancel -- end");
29 }
30 
32 {
33  int64_t wakeup = 1000;
34  double delay = 0;
35 
36  LOG(VB_RECORD, LOG_INFO, LOC + "run -- begin");
37 
38  RunProlog();
39 
40  auto *downloader = new MythSingleDownload;
41 
42  while (!m_cancel)
43  {
44  m_lock.lock();
45  if (!m_wokenup)
46  {
47  unsigned long waittime = wakeup < 1000 ? 1000 : wakeup;
48  LOG(VB_RECORD, (waittime > 12000 ? LOG_INFO : LOG_DEBUG), LOC +
49  QString("refreshing in %2s")
50  .arg(waittime / 1000.0));
51  m_waitcond.wait(&m_lock, waittime);
52  }
53  m_wokenup = false;
54  m_lock.unlock();
55 
56  if (m_parent->FatalError())
57  {
58  LOG(VB_GENERAL, LOG_CRIT, LOC + "Fatal error detected");
59  break;
60  }
61  if (m_cancel)
62  {
63  LOG(VB_RECORD, LOG_INFO, LOC + "canceled");
64  break;
65  }
66 
67  if (m_parent->LoadMetaPlaylists(*downloader))
68  {
69  if (m_parent->PlaylistRetryCount() > 0)
70  {
71  LOG(VB_RECORD, LOG_INFO, LOC +
72  QString("Playlist successfully downloaded. Buffered: %1%")
74  }
76  delay = 0.5;
77  }
78  else
79  {
81  LOG(VB_RECORD, LOG_WARNING, LOC +
82  QString("Playlist download failed -- Retry #%1, "
83  "Buffered: %2%")
85  .arg((m_parent->PercentBuffered())));
86 
87  if (m_parent->PlaylistRetryCount() > 1)
88  {
89  // Asking QNetworkAccessManager to redownload after a
90  // failure seems to result in another failure, even if the
91  // playlist is now available. So, create a new instance.
92  delete downloader;
93  downloader = new MythSingleDownload;
94 
95  if (m_parent->PlaylistRetryCount() == 3)
97  if (m_parent->PlaylistRetryCount() < 4)
100  {
101  LOG(VB_RECORD, LOG_ERR, LOC + "Loading playlist failed. "
102  "Perform a complete reset.");
104  }
105  }
106 
107  if (m_parent->PercentBuffered() > 85)
108  {
109  // Don't wait, we need more segments to work on.
110  if (m_parent->PlaylistRetryCount() == 1)
111  continue; // restart immediately if it's the first try
112  delay = 0.5;
113  }
114  else if (m_parent->PlaylistRetryCount() == 1)
115  delay = 0.5;
116  else if (m_parent->PlaylistRetryCount() == 2)
117  delay = 1;
118  else
119  delay = 2;
120  }
121 
122  // When should the playlist be reloaded
123  wakeup = m_parent->TargetDuration() > 0 ?
124  m_parent->TargetDuration() : 10;
125  wakeup *= (delay * (int64_t)1000);
126  if (wakeup > 60000)
127  wakeup = 60000;
128  }
129 
130  if (downloader)
131  {
132  downloader->Cancel();
133  delete downloader;
134  }
135 
136  RunEpilog();
137 
138  LOG(VB_RECORD, LOG_INFO, LOC + "run -- end");
139 }
HLSReader::FatalError
bool FatalError(void) const
Definition: HLSReader.h:53
HLSPlaylistWorker::m_parent
HLSReader * m_parent
Definition: HLSPlaylistWorker.h:24
HLSPlaylistWorker.h
HLSReader::PlaylistRetryCount
int PlaylistRetryCount(void) const
Definition: HLSReader.cpp:1026
arg
arg(title).arg(filename).arg(doDelete))
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MThread::RunProlog
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:199
HLSPlaylistWorker::m_waitcond
QWaitCondition m_waitcond
Definition: HLSPlaylistWorker.h:28
HLSPlaylistWorker::m_wokenup
bool m_wokenup
Definition: HLSPlaylistWorker.h:26
HLSReader::LoadMetaPlaylists
bool LoadMetaPlaylists(MythSingleDownload &downloader)
Definition: HLSReader.cpp:630
HLSReader::EnableDebugging
void EnableDebugging(void)
Definition: HLSReader.cpp:1034
HLSReader::PercentBuffered
uint PercentBuffered(void) const
Definition: HLSReader.cpp:875
HLSPlaylistWorker::~HLSPlaylistWorker
~HLSPlaylistWorker(void) override
Definition: HLSPlaylistWorker.cpp:15
MThread::RunEpilog
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:212
HLSPlaylistWorker::m_cancel
bool m_cancel
Definition: HLSPlaylistWorker.h:25
PLAYLIST_FAILURE
const int PLAYLIST_FAILURE
Definition: HLSPlaylistWorker.cpp:4
HLSReader::AllowPlaylistSwitch
void AllowPlaylistSwitch(void)
Definition: HLSReader.h:78
HLSReader
Definition: HLSReader.h:35
HLSReader::PlaylistRetrying
void PlaylistRetrying(void)
Definition: HLSReader.cpp:1019
HLSReader::TargetDuration
int TargetDuration(void) const
Definition: HLSReader.h:75
MythSingleDownload
Definition: mythsingledownload.h:24
HLSPlaylistWorker::Cancel
void Cancel(void)
Definition: HLSPlaylistWorker.cpp:20
MThread
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:49
HLSPlaylistWorker::HLSPlaylistWorker
HLSPlaylistWorker(HLSReader *parent)
Definition: HLSPlaylistWorker.cpp:9
HLSReader::ResetStream
void ResetStream(void)
Definition: HLSReader.h:56
LOC
#define LOC
Definition: HLSPlaylistWorker.cpp:7
HLSPlaylistWorker::run
void run() override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: HLSPlaylistWorker.cpp:31
MThread::wait
bool wait(unsigned long time=ULONG_MAX)
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:306
HLSReader::PlaylistGood
void PlaylistGood(void)
Definition: HLSReader.cpp:1012
HLSPlaylistWorker::m_lock
QMutex m_lock
Definition: HLSPlaylistWorker.h:29
HLSReader.h