Skip to content

Commit

Permalink
Add method to immediately interrupt HLS read or seek.
Browse files Browse the repository at this point in the history
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
jyavenard committed Jul 30, 2012
1 parent fa54d5d commit 4f6c08b
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 6 deletions.
42 changes: 36 additions & 6 deletions mythtv/libs/libmythtv/HLS/httplivestreambuffer.cpp
Expand Up @@ -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);
Expand Down Expand Up @@ -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())))
{
Expand All @@ -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();
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
3 changes: 3 additions & 0 deletions mythtv/libs/libmythtv/HLS/httplivestreambuffer.h
Expand Up @@ -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);
Expand Down Expand Up @@ -126,6 +128,7 @@ class HLSRingBuffer : public RingBuffer
friend class PlaylistWorker;
PlaylistWorker *m_playlistworker;
FILE *m_fd;
bool m_interrupted;
};

#endif
11 changes: 11 additions & 0 deletions mythtv/libs/libmythtv/iptv/iptvfeederhls.cpp
Expand Up @@ -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 +
Expand All @@ -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);

Expand Down

0 comments on commit 4f6c08b

Please sign in to comment.