Permalink
Browse files

Add method to immediately interrupt HLS read or seek.

HLSRingBuffer::Read and HLSRingBuffer::Seek always wait for sufficient data to be buffered before returning. Add two new methods: HLSRingBuffer::Interrupt() and HLSRingBuffer::Continue() to stop any wait.

Ref #10934
  • Loading branch information...
1 parent fa54d5d commit 4f6c08bfbfe8a933aefce7e270bd3443a308ccba @jyavenard jyavenard committed Jul 30, 2012
@@ -1455,7 +1455,8 @@ HLSRingBuffer::HLSRingBuffer(const QString &lfilename) :
m_playback(new HLSPlayback()),
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_streamworker(NULL), m_playlistworker(NULL), m_fd(NULL),
+ m_interrupted(false)
{
startreadahead = false;
OpenFile(lfilename);
@@ -2532,7 +2533,7 @@ void HLSRingBuffer::WaitUntilBuffered(void)
m_streamworker->Wakeup();
m_streamworker->Lock();
int retries = 0;
- while (!m_error &&
+ while (!m_error && !m_interrupted &&
(m_streamworker->CurrentPlaybackBuffer(false) < 2) &&
(live || (!live && !m_streamworker->IsAtEnd())))
{
@@ -2550,6 +2551,13 @@ int HLSRingBuffer::safe_read(void *data, uint sz)
int used = 0;
int i_read = sz;
+ WaitUntilBuffered();
+ if (m_interrupted)
+ {
+ LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("interrupted"));
+ return 0;
+ }
+
do
{
int segnum = m_playback->Segment();
@@ -2605,9 +2613,10 @@ int HLSRingBuffer::safe_read(void *data, uint sz)
i_read -= len;
segment->Unlock();
}
- while (i_read > 0);
+ while (i_read > 0 && !m_interrupted);
- WaitUntilBuffered();
+ if (m_interrupted)
+ LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("interrupted"));
m_playback->AddOffset(used);
return used;
@@ -2738,14 +2747,17 @@ long long HLSRingBuffer::Seek(long long pos, int whence, bool has_lock)
// see if we've already got the segment, and at least 2 buffered after
// then no need to wait for streamworker
- while (!m_error &&
+ while (!m_error && !m_interrupted &&
(!m_streamworker->GotBufferedSegments(segnum, 2) &&
(m_streamworker->CurrentPlaybackBuffer(false) < 2) &&
!m_streamworker->IsAtEnd()))
{
- m_streamworker->WaitForSignal(); //1000);
+ m_streamworker->WaitForSignal(1000);
retries++;
}
+ if (m_interrupted)
+ LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("interrupted"));
+
m_streamworker->Unlock();
// now seek within found segment
@@ -2780,3 +2792,21 @@ bool HLSRingBuffer::IsOpen(void) const
{
return !m_error && !m_streams.isEmpty() && NumSegments() > 0;
}
+
+void HLSRingBuffer::Interrupt(void)
+{
+ QMutexLocker lock(&m_lock);
+
+ // segment didn't get downloaded (timeout?)
+ LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("requesting interrupt"));
+ m_interrupted = true;
+}
+
+void HLSRingBuffer::Continue(void)
+{
+ QMutexLocker lock(&m_lock);
+
+ // segment didn't get downloaded (timeout?)
+ LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("requesting restart"));
+ m_interrupted = false;
+}
@@ -60,6 +60,8 @@ class HLSRingBuffer : public RingBuffer
bool SaveToDisk(QString filename, int segstart = 0, int segend = -1);
int NumStreams(void) const;
int Read(void *data, uint i_read) { return safe_read(data, i_read); }
+ void Interrupt(void);
+ void Continue(void);
protected:
virtual int safe_read(void *data, uint i_read);
@@ -126,6 +128,7 @@ class HLSRingBuffer : public RingBuffer
friend class PlaylistWorker;
PlaylistWorker *m_playlistworker;
FILE *m_fd;
+ bool m_interrupted;
};
#endif
@@ -72,12 +72,19 @@ void IPTVFeederHLS::Run(void)
m_interrupted = false;
m_lock.unlock();
+ m_hls->Continue();
while (!m_interrupted)
{
if (m_hls == NULL)
break;
m_lock.lock();
uint size = m_hls->Read((void *)m_buffer, BUFFER_SIZE);
+ if (size < 0)
+ {
+ m_lock.unlock();
+ break;
+ }
+
if (m_buffer[0] != 0x47)
{
LOG(VB_RECORD, LOG_INFO, LOC +
@@ -103,8 +110,12 @@ void IPTVFeederHLS::Stop(void)
{
LOG(VB_RECORD, LOG_INFO, LOC + "Stop() -- begin");
QMutexLocker locker(&m_lock);
+
m_interrupted = true;
+ if (m_hls)
+ m_hls->Interrupt();
+
while (m_running)
m_waitcond.wait(&m_lock, 500);

0 comments on commit 4f6c08b

Please sign in to comment.