Permalink
Browse files

Interrupt ongoing downloads in HLSRingBuffer destructor

IPTVRecorder::Close() is expected to return quickly, so the event thread isn't blocked which would cause the frontend client to disconnect prematurely (it timeout after only 7s)

Speed-up HLSRingBuffer destructor by interrupting any ongoing downloads (interrupt both segments download and playlist refresh)

Fixes #10987
  • Loading branch information...
1 parent f8b772b commit a52ec1d107caed0ee56ae1ebd926cf35f20bfa75 @jyavenard jyavenard committed Aug 10, 2012
@@ -81,6 +81,12 @@ static bool downloadURL(QString url, QByteArray *buffer)
return mdm->download(url, buffer);
}
+static void cancelURL(QString url)
+{
+ MythDownloadManager *mdm = GetMythDownloadManager();
+ mdm->cancelDownload(url);
+}
+
/* segment container */
class HLSSegment
@@ -99,6 +105,7 @@ class HLSSegment
m_keyloaded = false;
m_psz_key_path = current_key_path;
#endif
+ m_downloading = false;
}
HLSSegment(const HLSSegment &rhs)
@@ -127,6 +134,7 @@ class HLSSegment
memcpy(&m_aeskey, &(rhs.m_aeskey), sizeof(m_aeskey));
m_keyloaded = rhs.m_keyloaded;
#endif
+ m_downloading = rhs.m_downloading;
return *this;
}
@@ -163,7 +171,9 @@ class HLSSegment
int Download(void)
{
// must own lock
+ m_downloading = true;
bool ret = downloadURL(m_url, &m_data);
+ m_downloading = false;
// didn't succeed, clear buffer
if (!ret)
{
@@ -173,6 +183,16 @@ class HLSSegment
return RET_OK;
}
+ void CancelDownload(void)
+ {
+ if (m_downloading)
+ {
+ cancelURL(m_url);
+ QMutexLocker lock(&m_lock);
+ m_downloading = false;
+ }
+ }
+
QString Url(void)
{
return m_url;
@@ -337,6 +357,7 @@ class HLSSegment
QByteArray m_data; // raw data
int32_t m_played; // bytes counter of data already read from segment
QMutex m_lock;
+ bool m_downloading;
};
/* stream class */
@@ -790,6 +811,20 @@ class HLSStream
{
m_keypath = x;
}
+
+ void Cancel(void)
+ {
+ QMutexLocker lock(&m_lock);
+ QList<HLSSegment*>::iterator it = m_segments.begin();
+ for (; it != m_segments.end(); ++it)
+ {
+ if (*it)
+ {
+ (*it)->CancelDownload();
+ }
+ }
+ }
+
private:
QString m_keypath; // URL path of the encrypted key
bool m_ivloaded;
@@ -880,6 +915,18 @@ class StreamWorker : public MThread
{
m_interrupted = true;
Wakeup();
+ m_lock.lock();
+ // Interrupt on-going downloads of all segments
+ int streams = m_parent->NumStreams();
+ for (int i = 0; i < streams; i++)
+ {
+ HLSStream *hls = m_parent->GetStream(i);
+ if (hls)
+ {
+ hls->Cancel();
+ }
+ }
+ m_lock.unlock();
wait();
}
int CurrentStream(void)
@@ -1187,6 +1234,18 @@ class PlaylistWorker : public MThread
{
m_interrupted = true;
Wakeup();
+ m_lock.lock();
+ // Interrupt on-going downloads of all stream playlists
+ int streams = m_parent->NumStreams();
+ for (int i = 0; i < streams; i++)
+ {
+ HLSStream *hls = m_parent->GetStream(i);
+ if (hls)
+ {
+ cancelURL(hls->Url());
+ }
+ }
+ m_lock.unlock();
wait();
}
@@ -1425,7 +1484,7 @@ class PlaylistWorker : public MThread
int err = RET_ERROR;
/* Duplicate HLS stream META information */
- for (int i = 0; i < m_parent->m_streams.size(); i++)
+ for (int i = 0; i < m_parent->m_streams.size() && !m_interrupted; i++)
{
HLSStream *src, *dst;
src = m_parent->GetStream(i);
@@ -1437,7 +1496,7 @@ class PlaylistWorker : public MThread
/* Download playlist file from server */
QByteArray buffer;
- if (!downloadURL(dst->Url(), &buffer))
+ if (!downloadURL(dst->Url(), &buffer) || m_interrupted)
{
return RET_ERROR;
}
@@ -1464,7 +1523,7 @@ HLSRingBuffer::HLSRingBuffer(const QString &lfilename) :
m_meta(false), m_error(false), m_aesmsg(false),
m_startup(0), m_bitrate(0), m_seektoend(false),
m_streamworker(NULL), m_playlistworker(NULL), m_fd(NULL),
- m_interrupted(false)
+ m_interrupted(false), m_killed(false)
{
startreadahead = false;
OpenFile(lfilename);
@@ -1476,7 +1535,7 @@ HLSRingBuffer::HLSRingBuffer(const QString &lfilename, bool open) :
m_meta(false), m_error(false), m_aesmsg(false),
m_startup(0), m_bitrate(0), m_seektoend(false),
m_streamworker(NULL), m_playlistworker(NULL), m_fd(NULL),
- m_interrupted(false)
+ m_interrupted(false), m_killed(false)
{
startreadahead = false;
if (open)
@@ -1489,6 +1548,8 @@ HLSRingBuffer::~HLSRingBuffer()
{
QWriteLocker lock(&rwlock);
+ m_killed = true;
+
if (m_playlistworker)
{
m_playlistworker->Cancel();
@@ -2077,7 +2138,7 @@ int HLSRingBuffer::ParseM3U8(const QByteArray *buffer, StreamsList *streams)
/* M3U8 Meta Index file */
stream.seek(0); // rewind
- while (true)
+ while (!m_killed)
{
line = stream.readLine();
if (line.isNull())
@@ -2107,7 +2168,7 @@ int HLSRingBuffer::ParseM3U8(const QByteArray *buffer, StreamsList *streams)
/* Download playlist file from server */
QByteArray buf;
bool ret = downloadURL(hls->Url(), &buf);
- if (!ret)
+ if (!ret || m_killed)
{
err = RET_ERROR;
break;
@@ -2210,7 +2271,7 @@ int HLSRingBuffer::Prefetch(int count)
.arg(count));
m_streamworker->Lock();
m_streamworker->Wakeup();
- while (!m_error && !m_interrupted && (retries < 20) &&
+ while (!m_error && !m_killed && (retries < 20) &&
(m_streamworker->CurrentPlaybackBuffer(false) < count) &&
!m_streamworker->IsAtEnd())
{
@@ -130,6 +130,7 @@ class HLSRingBuffer : public RingBuffer
PlaylistWorker *m_playlistworker;
FILE *m_fd;
bool m_interrupted;
+ bool m_killed;
};
#endif

0 comments on commit a52ec1d

Please sign in to comment.