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_stream(nullptr), m_parent(parent)
17 {
18  startreadahead = true;
19  OpenFile(url);
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(&rwlock);
71 
72  safefilename = url;
73  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  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  poslock.lockForWrite();
103 
104  long long ret;
105 
106  // Optimize no-op seeks
107  if (readaheadrunning &&
108  ((whence == SEEK_SET && pos == readpos) ||
109  (whence == SEEK_CUR && pos == 0)))
110  {
111  ret = readpos;
112 
113  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  readpos = ret;
138 
139  ignorereadpos = -1;
140 
141  if (readaheadrunning)
143 
144  readAdjust = 0;
145  }
146 
147 err:
148  poslock.unlock();
149 
150  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) : (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:768
qlonglong GetSize() const
Definition: netstream.cpp:608
NetStream * m_stream
Definition: icringbuffer.h:36
unsigned int uint
Definition: compat.h:140
bool IsOpen(void) const override
Returns true if open for either reading or writing.
QReadWriteLock rwlock
int safe_read(void *data, unsigned size, unsigned millisecs=0)
Definition: netstream.cpp:548
void CalcReadAheadThresh(void)
Calculates fill_min, fill_threshold, and readblocksize from the estimated effective bitrate of the st...
Definition: ringbuffer.cpp:402
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)
QReadWriteLock poslock
long long GetReadPosition(void) const override
Returns how far into the file we have read.
bool IsOpen() const
Definition: netstream.cpp:517
void KillReadAheadThread(void)
Stops the read-ahead thread, and waits for it to stop.
Definition: ringbuffer.cpp:729
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:782
RingBuffer * Take()
RingBuffer * m_parent
Definition: icringbuffer.h:37
QWaitCondition generalWait
Condition to signal that the read ahead thread is running.
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:300
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:645
Implements a file/stream reader/writer.
int safe_read(void *data, uint sz) override