Skip to content

Commit

Permalink
MythPlayer: Add support for InteractiveTV streams
Browse files Browse the repository at this point in the history
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
Lawrence Rust authored and stuartm committed Oct 7, 2012
1 parent c885805 commit 98b1a77
Show file tree
Hide file tree
Showing 9 changed files with 1,451 additions and 11 deletions.
3 changes: 3 additions & 0 deletions mythtv/libs/libmythtv/avformatdecoder.cpp
Expand Up @@ -2203,6 +2203,9 @@ int AvFormatDecoder::ScanStreams(bool novideo)
}
}

if ((uint)ic->bit_rate > bitrate)
bitrate = (uint)ic->bit_rate;

if (bitrate > 0)
{
bitrate = (bitrate + 999) / 1000;
Expand Down
172 changes: 172 additions & 0 deletions mythtv/libs/libmythtv/icringbuffer.cpp
@@ -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
40 changes: 40 additions & 0 deletions mythtv/libs/libmythtv/icringbuffer.h
@@ -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
6 changes: 6 additions & 0 deletions mythtv/libs/libmythtv/libmythtv.pro
Expand Up @@ -123,6 +123,7 @@ HEADERS += mythsystemevent.h
HEADERS += avfringbuffer.h ThreadedFileWriter.h
HEADERS += ringbuffer.h fileringbuffer.h
HEADERS += streamingringbuffer.h metadataimagehelper.h
HEADERS += icringbuffer.h

SOURCES += recordinginfo.cpp
SOURCES += dbcheck.cpp
Expand Down Expand Up @@ -150,6 +151,7 @@ SOURCES += mythsystemevent.cpp
SOURCES += avfringbuffer.cpp ThreadedFileWriter.cpp
SOURCES += ringbuffer.cpp fileringBuffer.cpp
SOURCES += streamingringbuffer.cpp metadataimagehelper.cpp
SOURCES += icringbuffer.cpp

# DiSEqC
HEADERS += diseqc.h diseqcsettings.h
Expand Down Expand Up @@ -420,6 +422,10 @@ using_frontend {
SOURCES += dsmcc.cpp dsmcccache.cpp
SOURCES += dsmccbiop.cpp dsmccobjcarousel.cpp

# MHEG interaction channel
HEADERS += netstream.h
SOURCES += netstream.cpp

# MHEG/MHI stuff
HEADERS += interactivetv.h mhi.h
SOURCES += interactivetv.cpp mhi.cpp
Expand Down

0 comments on commit 98b1a77

Please sign in to comment.