Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MythPlayer: Add support for InteractiveTV streams
This patch adds functionality to MythPlayer to enable interactive TV content to select altenative streamed media for display. NB this patch needs to be applied together with that for InteractionChannel streaming. Refs #10019 Signed-off-by: Lawrence Rust <lvr@softsystem.co.uk> Signed-off-by: Stuart Morgan <smorgan@mythtv.org>
- Loading branch information
Showing
9 changed files
with
1,451 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
#include "icringbuffer.h" | ||
|
||
#include <stdio.h> // SEEK_SET | ||
|
||
#include <QScopedPointer> | ||
#include <QWriteLocker> | ||
|
||
#include "netstream.h" | ||
#include "mythlogging.h" | ||
|
||
|
||
#define LOC QString("ICRingBuf ") | ||
|
||
|
||
ICRingBuffer::ICRingBuffer(const QString &url, RingBuffer *parent) | ||
: RingBuffer(kRingBufferType), m_stream(0), m_parent(parent) | ||
{ | ||
startreadahead = true; | ||
OpenFile(url); | ||
} | ||
|
||
ICRingBuffer::~ICRingBuffer() | ||
{ | ||
delete m_stream; | ||
delete m_parent; | ||
} | ||
|
||
bool ICRingBuffer::IsOpen(void) const | ||
{ | ||
return m_stream ? m_stream->IsOpen() : false; | ||
} | ||
|
||
bool ICRingBuffer::OpenFile(const QString &url, uint retry_ms) | ||
{ | ||
if (!NetStream::IsSupported(url)) | ||
{ | ||
LOG(VB_GENERAL, LOG_ERR, LOC + QString("Unsupported URL %1").arg(url) ); | ||
return false; | ||
} | ||
|
||
QScopedPointer<NetStream> stream(new NetStream(url, NetStream::kNeverCache)); | ||
if (!stream || !stream->IsOpen()) | ||
{ | ||
LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to open %1").arg(url) ); | ||
return false; | ||
} | ||
|
||
if (!stream->WaitTillReady(30000)) | ||
{ | ||
LOG(VB_GENERAL, LOG_ERR, LOC + QString("Stream not ready%1").arg(url) ); | ||
return false; | ||
} | ||
|
||
if (m_parent) | ||
m_parent->Pause(); | ||
|
||
QWriteLocker locker(&rwlock); | ||
|
||
safefilename = url; | ||
filename = url; | ||
|
||
delete m_stream; | ||
m_stream = stream.take(); | ||
|
||
// The initial bitrate needs to be set with consideration for low bit rate | ||
// streams (e.g. radio @ 64Kbps) such that fill_min bytes are received | ||
// in a reasonable time period to enable decoders to peek the first few KB | ||
// to determine type & settings. | ||
rawbitrate = 128; // remotefile | ||
CalcReadAheadThresh(); | ||
|
||
locker.unlock(); | ||
Reset(true, false, true); | ||
|
||
LOG(VB_GENERAL, LOG_INFO, LOC + QString("Opened %1").arg(url)); | ||
return true; | ||
} | ||
|
||
long long ICRingBuffer::GetReadPosition(void) const | ||
{ | ||
return m_stream ? m_stream->GetReadPosition() : 0; | ||
} | ||
|
||
long long ICRingBuffer::Seek(long long pos, int whence, bool has_lock) | ||
{ | ||
if (!m_stream) | ||
return -1; | ||
|
||
// lockForWrite takes priority over lockForRead, so this will | ||
// take priority over the lockForRead in the read ahead thread. | ||
if (!has_lock) | ||
rwlock.lockForWrite(); | ||
|
||
poslock.lockForWrite(); | ||
|
||
long long ret; | ||
|
||
// Optimize no-op seeks | ||
if (readaheadrunning && | ||
((whence == SEEK_SET && pos == readpos) || | ||
(whence == SEEK_CUR && pos == 0))) | ||
{ | ||
ret = readpos; | ||
|
||
poslock.unlock(); | ||
if (!has_lock) | ||
rwlock.unlock(); | ||
|
||
return ret; | ||
} | ||
|
||
switch (whence) | ||
{ | ||
case SEEK_SET: | ||
break; | ||
case SEEK_CUR: | ||
pos += m_stream->GetReadPosition(); | ||
break; | ||
case SEEK_END: | ||
pos += m_stream->GetSize(); | ||
break; | ||
default: | ||
errno = EINVAL; | ||
ret = -1; | ||
goto err; | ||
} | ||
|
||
ret = m_stream->Seek(pos); | ||
if (ret >= 0) | ||
{ | ||
readpos = ret; | ||
|
||
ignorereadpos = -1; | ||
|
||
if (readaheadrunning) | ||
ResetReadAhead(readpos); | ||
|
||
readAdjust = 0; | ||
} | ||
|
||
err: | ||
poslock.unlock(); | ||
|
||
generalWait.wakeAll(); | ||
|
||
if (!has_lock) | ||
rwlock.unlock(); | ||
|
||
return ret; | ||
} | ||
|
||
int ICRingBuffer::safe_read(void *data, uint sz) | ||
{ | ||
return m_stream ? m_stream->safe_read(data, sz, 1000) : (ateof = true, 0); | ||
} | ||
|
||
long long ICRingBuffer::GetRealFileSize(void) const | ||
{ | ||
return m_stream ? m_stream->GetSize() : -1; | ||
} | ||
|
||
// Take ownership of parent RingBuffer | ||
RingBuffer *ICRingBuffer::Take() | ||
{ | ||
RingBuffer *parent = m_parent; | ||
if (parent && IsOpen()) | ||
parent->Unpause(); | ||
m_parent = 0; | ||
return parent; | ||
} | ||
|
||
// End of file |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
#ifndef ICRINGBUFFER_H | ||
#define ICRINGBUFFER_H | ||
|
||
#include "ringbuffer.h" | ||
|
||
class NetStream; | ||
|
||
class ICRingBuffer : public RingBuffer | ||
{ | ||
public: | ||
static enum RingBufferType const kRingBufferType = kRingBuffer_MHEG; | ||
|
||
ICRingBuffer(const QString &url, RingBuffer *parent = 0); | ||
virtual ~ICRingBuffer(); | ||
|
||
// RingBuffer implementation | ||
virtual bool IsOpen(void) const; | ||
virtual long long GetReadPosition(void) const; | ||
virtual bool OpenFile(const QString &url, | ||
uint retry_ms = kDefaultOpenTimeout); | ||
virtual long long Seek(long long pos, int whence, bool has_lock); | ||
virtual long long GetRealFileSize(void) const; | ||
virtual bool IsStreamed(void) { return false; } | ||
virtual bool IsSeekingAllowed(void) { return true; } | ||
virtual bool IsBookmarkAllowed(void) { return false; } | ||
|
||
protected: | ||
virtual int safe_read(void *data, uint sz); | ||
|
||
// Operations | ||
public: | ||
// Take ownership of parent RingBuffer | ||
RingBuffer *Take(); | ||
|
||
private: | ||
NetStream *m_stream; | ||
RingBuffer *m_parent; // parent RingBuffer | ||
}; | ||
|
||
#endif // ICRINGBUFFER_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.