MythTV  master
icringbuffer.cpp
Go to the documentation of this file.
1 #include "icringbuffer.h"
2 
3 #include <cstdio> // SEEK_SET
4 
5 #include <QScopedPointer>
6 #include <QWriteLocker>
7 
8 #include "netstream.h"
9 #include "mythlogging.h"
10 
11 
12 #define LOC QString("ICRingBuf ")
13 
14 
15 ICRingBuffer::ICRingBuffer(const QString &url, RingBuffer *parent)
16  : RingBuffer(kRingBufferType), m_parent(parent)
17 {
18  m_startReadAhead = true;
20 }
21 
23 {
25 
26  delete m_stream;
27  m_stream = nullptr;
28 
29  delete m_parent;
30  m_parent = nullptr;
31 }
32 
33 bool ICRingBuffer::IsOpen(void) const
34 {
35  return m_stream ? m_stream->IsOpen() : false;
36 }
37 
46 bool ICRingBuffer::OpenFile(const QString &url, uint /*retry_ms*/)
47 {
48  if (!NetStream::IsSupported(url))
49  {
50  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Unsupported URL %1").arg(url) );
51  return false;
52  }
53 
54  QScopedPointer<NetStream> stream(new NetStream(url, NetStream::kNeverCache));
55  if (!stream || !stream->IsOpen())
56  {
57  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to open %1").arg(url) );
58  return false;
59  }
60 
61  if (!stream->WaitTillReady(30000))
62  {
63  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Stream not ready%1").arg(url) );
64  return false;
65  }
66 
67  if (m_parent)
68  m_parent->Pause();
69 
70  QWriteLocker locker(&m_rwLock);
71 
72  m_safeFilename = url;
73  m_filename = url;
74 
75  delete m_stream;
76  m_stream = stream.take();
77 
78  // The initial bitrate needs to be set with consideration for low bit rate
79  // streams (e.g. radio @ 64Kbps) such that fill_min bytes are received
80  // in a reasonable time period to enable decoders to peek the first few KB
81  // to determine type & settings.
82  m_rawBitrate = 128; // remotefile
84 
85  locker.unlock();
86  Reset(true, false, true);
87 
88  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Opened %1").arg(url));
89  return true;
90 }
91 
92 long long ICRingBuffer::GetReadPosition(void) const
93 {
94  return m_stream ? m_stream->GetReadPosition() : 0;
95 }
96 
97 long long ICRingBuffer::SeekInternal(long long pos, int whence)
98 {
99  if (!m_stream)
100  return -1;
101 
102  m_posLock.lockForWrite();
103 
104  long long ret;
105 
106  // Optimize no-op seeks
107  if (m_readAheadRunning &&
108  ((whence == SEEK_SET && pos == m_readPos) ||
109  (whence == SEEK_CUR && pos == 0)))
110  {
111  ret = m_readPos;
112 
113  m_posLock.unlock();
114 
115  return ret;
116  }
117 
118  switch (whence)
119  {
120  case SEEK_SET:
121  break;
122  case SEEK_CUR:
123  pos += m_stream->GetReadPosition();
124  break;
125  case SEEK_END:
126  pos += m_stream->GetSize();
127  break;
128  default:
129  errno = EINVAL;
130  ret = -1;
131  goto err;
132  }
133 
134  ret = m_stream->Seek(pos);
135  if (ret >= 0)
136  {
137  m_readPos = ret;
138 
139  m_ignoreReadPos = -1;
140 
141  if (m_readAheadRunning)
143 
144  m_readAdjust = 0;
145  }
146 
147 err:
148  m_posLock.unlock();
149 
150  m_generalWait.wakeAll();
151 
152  return ret;
153 }
154 
155 int ICRingBuffer::safe_read(void *data, uint sz)
156 {
157  return m_stream ? m_stream->safe_read(data, sz, 1000) : (m_ateof = true, 0);
158 }
159 
161 {
162  return m_stream ? m_stream->GetSize() : -1;
163 }
164 
165 // Take ownership of parent RingBuffer
167 {
168  RingBuffer *parent = m_parent;
169  if (parent && IsOpen())
170  parent->Unpause();
171  m_parent = nullptr;
172  return parent;
173 }
174 
175 // End of file
#define LOC
virtual ~ICRingBuffer()
void Pause(void)
Pauses the read-ahead thread.
Definition: ringbuffer.cpp:733
qlonglong GetSize() const
Definition: netstream.cpp:608
NetStream * m_stream
Definition: icringbuffer.h:36
QReadWriteLock m_rwLock
unsigned int uint
Definition: compat.h:140
bool IsOpen(void) const override
Returns true if open for either reading or writing.
void CalcReadAheadThresh(void)
Calculates m_fillMin, m_fillThreshold, and m_readBlockSize from the estimated effective bitrate of th...
Definition: ringbuffer.cpp:367
qlonglong GetReadPosition() const
Definition: netstream.cpp:601
bool OpenFile(const QString &url, uint retry_ms=kDefaultOpenTimeout) override
Opens a BBC NetStream for reading.
ICRingBuffer(const QString &url, RingBuffer *parent=nullptr)
long long GetReadPosition(void) const override
Returns how far into the file we have read.
bool IsOpen() const
Definition: netstream.cpp:517
int safe_read(void *data, unsigned sz, unsigned millisecs=0)
Definition: netstream.cpp:548
void KillReadAheadThread(void)
Stops the read-ahead thread, and waits for it to stop.
Definition: ringbuffer.cpp:694
QReadWriteLock m_posLock
static bool IsSupported(const QUrl &)
RingBuffer interface.
Definition: netstream.cpp:509
long long GetRealFileSizeInternal(void) const override
long long SeekInternal(long long pos, int whence) override
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
void Unpause(void)
Unpauses the read-ahead thread.
Definition: ringbuffer.cpp:747
QWaitCondition m_generalWait
Condition to signal that the read ahead thread is running.
RingBuffer * Take()
RingBuffer * m_parent
Definition: icringbuffer.h:37
void Reset(bool full=false, bool toAdjust=false, bool resetInternal=false)
Resets the read-ahead thread and our position in the file.
Definition: ringbuffer.cpp:265
Stream content from a URI.
Definition: netstream.h:30
qlonglong Seek(qlonglong)
Definition: netstream.cpp:580
void ResetReadAhead(long long newinternal)
Restart the read-ahead thread at the 'newinternal' position.
Definition: ringbuffer.cpp:610
Implements a file/stream reader/writer.
int safe_read(void *data, uint sz) override