MythTV  master
libs/libmythtv/ringbuffer.h
Go to the documentation of this file.
1 // -*- Mode: c++ -*-
2 
3 #ifndef _RINGBUFFER_H_
4 #define _RINGBUFFER_H_
5 
6 #include <QReadWriteLock>
7 #include <QWaitCondition>
8 #include <QString>
9 #include <QMutex>
10 #include <QMap>
11 
12 #include "mythconfig.h"
13 #include "mthread.h"
14 
15 extern "C" {
16 #include "libavcodec/avcodec.h"
17 }
18 
19 #include "mythtvexp.h"
20 
21 #define PNG_MIN_SIZE 20 /* header plus one empty chunk */
22 #define NUV_MIN_SIZE 204 /* header size? */
23 #define MPEG_MIN_SIZE 376 /* 2 TS packets */
24 
25 /* should be minimum of the above test sizes */
26 #define kReadTestSize PNG_MIN_SIZE
27 
28 // about one second at 35mbit
29 #define BUFFER_SIZE_MINIMUM (4 * 1024 * 1024)
30 #define BUFFER_FACTOR_NETWORK 2
31 #define BUFFER_FACTOR_BITRATE 2
32 #define BUFFER_FACTOR_MATROSKA 2
33 
34 #define CHUNK 32768 /* readblocksize increments */
35 
36 class ThreadedFileWriter;
37 class DVDRingBuffer;
38 class BDRingBuffer;
39 class LiveTVChain;
40 class RemoteFile;
41 
43 {
51 };
52 
53 class MTV_PUBLIC RingBuffer : protected MThread
54 {
55  friend class ICRingBuffer;
56 
57  public:
58  static RingBuffer *Create(const QString &xfilename, bool write,
59  bool usereadahead = true,
60  int timeout_ms = kDefaultOpenTimeout,
61  bool stream_only = false);
62  ~RingBuffer() override = 0;
63 
64  // Sets
65  void SetWriteBufferSize(int newSize);
66  void SetWriteBufferMinWriteSize(int newMinSize);
67  void SetOldFile(bool is_old);
68  void UpdateRawBitrate(uint raw_bitrate);
69  void UpdatePlaySpeed(float play_speed);
70  void EnableBitrateMonitor(bool enable) { m_bitrateMonitorEnabled = enable; }
71  void SetBufferSizeFactors(bool estbitrate, bool matroska);
72  void SetWaitForWrite(void) { m_waitForWrite = true; }
73 
74  // Gets
75  QString GetSafeFilename(void) { return m_safeFilename; }
76  QString GetFilename(void) const;
77  QString GetSubtitleFilename(void) const;
78  QString GetLastError(void) const;
79  bool GetCommsError(void) const { return m_commsError; }
80  void ResetCommsError(void) { m_commsError = false; }
81 
84  bool GetStopReads(void) const { return m_stopReads; }
85  bool isPaused(void) const;
87  virtual long long GetReadPosition(void) const = 0;
88  QString GetDecoderRate(void);
89  QString GetStorageRate(void);
90  QString GetAvailableBuffer(void);
91  uint GetBufferSize(void) { return m_bufferSize; }
92  long long GetWritePosition(void) const;
95  long long GetRealFileSize(void) const;
96  bool IsNearEnd(double fps, uint vvf) const;
98  virtual bool IsOpen(void) const = 0;
99  virtual bool IsStreamed(void) { return LiveMode(); }
100  virtual bool IsSeekingAllowed(void) { return true; }
101  virtual bool IsBookmarkAllowed(void) { return true; }
102  virtual int BestBufferSize(void) { return 32768; }
103  static QString BitrateToString(uint64_t rate, bool hz = false);
104  RingBufferType GetType() const { return m_type; }
105 
106  // LiveTV used utilities
107  int GetReadBufAvail() const;
108  bool SetReadInternalMode(bool mode);
109  bool IsReadInternalMode(void) { return m_readInternalMode; }
110 
111  // DVD and bluray methods
112  bool IsDisc(void) const { return IsDVD() || IsBD(); }
113  bool IsDVD(void) const { return m_type == kRingBuffer_DVD; }
114  bool IsBD(void) const { return m_type == kRingBuffer_BD; }
115  const DVDRingBuffer *DVD(void) const;
116  const BDRingBuffer *BD(void) const;
117  DVDRingBuffer *DVD(void);
118  BDRingBuffer *BD(void);
119  virtual bool StartFromBeginning(void) { return true; }
120  virtual void IgnoreWaitStates(bool /*ignore*/) { }
121  virtual bool IsInMenu(void) const { return false; }
122  virtual bool IsInStillFrame(void) const { return false; }
123  virtual bool IsInDiscMenuOrStillFrame(void) const { return IsInMenu() || IsInStillFrame(); }
124  virtual bool HandleAction(const QStringList &/*action*/, int64_t /*frane*/) { return false; }
125 
126  // General Commands
127 
134  virtual bool OpenFile(const QString &lfilename,
135  uint retry_ms = kDefaultOpenTimeout) = 0;
136  virtual bool ReOpen(const QString& /*newFilename*/ = "") { return false; }
137 
138  int Read(void *buf, int count);
139  int Peek(void *buf, int count); // only works with readahead
140 
141  void Reset(bool full = false,
142  bool toAdjust = false,
143  bool resetInternal = false);
144 
146  long long Seek(long long pos, int whence, bool has_lock = false);
147 
148  // Pause commands
149  void Pause(void);
150  void Unpause(void);
151  void WaitForPause(void);
152 
153  // Start/Stop commands
154  void Start(void);
155  void StopReads(void);
156  void StartReads(void);
157 
158  // LiveTVChain support
159  bool LiveMode(void) const;
160  void SetLiveMode(LiveTVChain *chain);
161  void IgnoreLiveEOF(bool ignore);
162 
163  // ThreadedFileWriter proxies
164  int Write(const void *buf, uint count);
165  bool IsIOBound(void) const;
166  void WriterFlush(void);
167  void Sync(void);
168  long long WriterSeek(long long pos, int whence, bool has_lock = false);
169  bool WriterSetBlocking(bool lock = true);
170 
171  long long SetAdjustFilesize(void);
172 
173  static const int kDefaultOpenTimeout;
174  static const int kLiveTVOpenTimeout;
175 
176  static void AVFormatInitNetwork(void);
177 
178  protected:
179  explicit RingBuffer(RingBufferType rbtype);
180 
181  void run(void) override; // MThread
182  void CreateReadAheadBuffer(void);
183  void CalcReadAheadThresh(void);
184  bool PauseAndWait(void);
185  virtual int safe_read(void *data, uint sz) = 0;
186 
187  int ReadPriv(void *buf, int count, bool peek);
188  int ReadDirect(void *buf, int count, bool peek);
189  bool WaitForReadsAllowed(void);
190  int WaitForAvail(int count, int timeout);
191  virtual long long GetRealFileSizeInternal(void) const { return -1; }
192  virtual long long SeekInternal(long long pos, int whence) = 0;
193 
194  int ReadBufFree(void) const;
195  int ReadBufAvail(void) const;
196 
197  void ResetReadAhead(long long newinternal);
198  void KillReadAheadThread(void);
199 
200  uint64_t UpdateDecoderRate(uint64_t latest = 0);
201  uint64_t UpdateStorageRate(uint64_t latest = 0);
202 
203  protected:
205 
206  //
207  // The following are protected by posLock
208  //
209  mutable QReadWriteLock m_posLock;
210  long long m_readPos {0};
211  long long m_writePos {0};
212  long long m_internalReadPos {0};
213  long long m_ignoreReadPos {-1};
214 
215  //
216  // The following are protected by rbrLock
217  //
218  mutable QReadWriteLock m_rbrLock;
219  int m_rbrPos {0};
220 
221  //
222  // The following are protected by rbwLock
223  //
224  mutable QReadWriteLock m_rbwLock;
225  int m_rbwPos {0};
226 
227  // note should not go under rwLock..
228  // this is used to break out of read_safe where rwLock is held
229  volatile bool m_stopReads {false};
230 
231  //
232  // unprotected (for debugging)
233  //
234  QString m_safeFilename;
235 
236  //
237  // The following are protected by rwLock
238  //
239  mutable QReadWriteLock m_rwLock;
240  QString m_filename;
242  QString m_lastError;
243 
245  int m_fd2 {-1};
246 
247  bool m_writeMode {false};
248 
250 
252  bool m_lowBuffers {false};
253  bool m_fileIsMatroska {false};
254  bool m_unknownBitrate {false};
255  bool m_startReadAhead {false};
256  char *m_readAheadBuffer {nullptr};
257  bool m_readAheadRunning {false};
258  bool m_reallyRunning {false};
259  bool m_requestPause {false};
260  bool m_paused {false};
261  bool m_ateof {false};
262  bool m_waitForWrite {false};
263  bool m_beingWritten {false};
264  bool m_readsAllowed {false};
265  bool m_readsDesired {false};
266  volatile bool m_recentSeek {true}; // not protected by rwLock
267  bool m_setSwitchToNext {false};
269  float m_playSpeed {1.0F};
270  int m_fillThreshold {65536};
271  int m_fillMin {-1};
273  int m_wantToRead {0};
274  int m_numFailures {0}; // (see note 1)
275  bool m_commsError {false};
276 
277  bool m_oldfile {false};
278 
280  bool m_ignoreLiveEOF {false};
281 
282  long long m_readAdjust {0};
283 
284  // Internal RingBuffer Method
285  int m_readOffset {0};
286  bool m_readInternalMode {false};
287  //
288  // End of section protected by rwLock
289  //
290 
291  // bitrate monitors
294  QMap<qint64, uint64_t> m_decoderReads;
296  QMap<qint64, uint64_t> m_storageReads;
297 
298  // note 1: numfailures is modified with only a read lock in the
299  // read ahead thread, but this is safe since all other places
300  // that use it are protected by a write lock. But this is a
301  // fragile state of affairs and care must be taken when modifying
302  // code or locking around this variable.
303 
305  QWaitCondition m_generalWait; // protected by rwLock
306 
307  public:
308  static QMutex s_subExtLock;
309  static QStringList s_subExt;
310  static QStringList s_subExtNoCheck;
311 
312  private:
314  bool m_bitrateInitialized {false};
315 };
316 
317 #endif // _RINGBUFFER_H_
static const int kDefaultOpenTimeout
void EnableBitrateMonitor(bool enable)
def write(text, progress=True)
Definition: mythburn.py:279
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:46
void Pause(void)
Pauses the read-ahead thread.
Definition: ringbuffer.cpp:733
LiveTVChain * m_liveTVChain
const DVDRingBuffer * DVD(void) const
virtual int BestBufferSize(void)
int GetReadBufAvail() const
Returns number of bytes available for reading from buffer.
Definition: ringbuffer.cpp:490
static QString BitrateToString(uint64_t rate, bool hz=false)
virtual bool IsInDiscMenuOrStillFrame(void) const
bool IsReadInternalMode(void)
bool LiveMode(void) const
Returns true if this RingBuffer has been assigned a LiveTVChain.
void WriterFlush(void)
Calls ThreadedFileWriter::Flush(void)
virtual void run(void)
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: mthread.cpp:318
QString GetLastError(void) const
QString GetSafeFilename(void)
#define BUFFER_SIZE_MINIMUM
bool WriterSetBlocking(bool lock=true)
Calls ThreadedFileWriter::SetBlocking(bool)
uint64_t UpdateStorageRate(uint64_t latest=0)
void SetLiveMode(LiveTVChain *chain)
Assigns a LiveTVChain to this RingBuffer.
void StartReads(void)
????
Definition: ringbuffer.cpp:722
uint64_t UpdateDecoderRate(uint64_t latest=0)
QReadWriteLock m_rwLock
QString GetFilename(void) const
Returns name of file used by this RingBuffer.
static RingBuffer * Create(const QString &xfilename, bool write, bool usereadahead=true, int timeout_ms=kDefaultOpenTimeout, bool stream_only=false)
Creates a RingBuffer instance.
Definition: ringbuffer.cpp:104
bool IsOpen(void) const override
Returns true if open for either reading or writing.
QString GetDecoderRate(void)
QString GetStorageRate(void)
void CalcReadAheadThresh(void)
Calculates m_fillMin, m_fillThreshold, and m_readBlockSize from the estimated effective bitrate of th...
Definition: ringbuffer.cpp:367
long long SetAdjustFilesize(void)
static ssize_t safe_read(int filedes, void *buffer, size_t size)
Definition: dvbci.cpp:83
void SetBufferSizeFactors(bool estbitrate, bool matroska)
Tells RingBuffer that the raw bitrate may be innacurate and the underlying container is matroska,...
Definition: ringbuffer.cpp:351
~RingBuffer() override=0
Deletes.
Definition: ringbuffer.cpp:246
int ReadPriv(void *buf, int count, bool peek)
When possible reads from the read-ahead buffer, otherwise reads directly from the device.
bool GetStopReads(void) const
Returns value of stopreads.
void SetWriteBufferSize(int newSize)
bool OpenFile(const QString &url, uint retry_ms=kDefaultOpenTimeout) override
Opens a BBC NetStream for reading.
bool IsDVD(void) const
void SetWaitForWrite(void)
long long WriterSeek(long long pos, int whence, bool has_lock=false)
Calls ThreadedFileWriter::Seek(long long,int).
QMap< qint64, uint64_t > m_decoderReads
virtual bool IsInMenu(void) const
bool PauseAndWait(void)
Definition: ringbuffer.cpp:789
static bool gAVformat_net_initialised
QReadWriteLock m_rbwLock
QString GetAvailableBuffer(void)
#define MTV_PUBLIC
Definition: mythtvexp.h:15
virtual bool IsInStillFrame(void) const
QReadWriteLock m_rbrLock
long long GetReadPosition(void) const override
Returns how far into the file we have read.
static void AVFormatInitNetwork(void)
void Sync(void)
Calls ThreadedFileWriter::Sync(void)
void KillReadAheadThread(void)
Stops the read-ahead thread, and waits for it to stop.
Definition: ringbuffer.cpp:694
QReadWriteLock m_posLock
int ReadDirect(void *buf, int count, bool peek)
virtual bool IsStreamed(void)
void IgnoreLiveEOF(bool ignore)
Tells RingBuffer whether to ignore the end-of-file.
bool GetCommsError(void) const
void SetOldFile(bool is_old)
Tell RingBuffer if this is an old file or not.
static const int kLiveTVOpenTimeout
unsigned int uint
Definition: compat.h:140
RingBufferType GetType() const
virtual bool IsBookmarkAllowed(void)
int ReadBufFree(void) const
Returns number of bytes available for reading into buffer.
Definition: ringbuffer.cpp:479
bool IsBD(void) const
int Peek(void *buf, int count)
bool IsIOBound(void) const
volatile bool m_stopReads
void Start(void)
Starts the read-ahead thread.
Definition: ringbuffer.cpp:653
ThreadedFileWriter * m_tfw
RingBufferType m_type
void WaitForPause(void)
Waits for Pause(void) to take effect.
Definition: ringbuffer.cpp:770
void StopReads(void)
????
Definition: ringbuffer.cpp:711
virtual bool StartFromBeginning(void)
long long GetWritePosition(void) const
Returns how far into a ThreadedFileWriter file we have written.
long long SeekInternal(long long pos, int whence) override
static QStringList s_subExt
void Unpause(void)
Unpauses the read-ahead thread.
Definition: ringbuffer.cpp:747
bool IsDisc(void) const
QWaitCondition m_generalWait
Condition to signal that the read ahead thread is running.
bool WaitForReadsAllowed(void)
QString GetSubtitleFilename(void) const
long long GetRealFileSize(void) const
Returns the size of the file we are reading/writing, or -1 if the query fails.
Definition: ringbuffer.cpp:497
virtual bool IsSeekingAllowed(void)
static QMutex s_subExtLock
RemoteFile * m_remotefile
virtual bool ReOpen(const QString &="")
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
int Read(void *buf, int count)
This is the public method for reading from a file, it calls the appropriate read method if the file i...
This class supports the writing of recordings to disk.
bool SetReadInternalMode(bool mode)
Definition: ringbuffer.cpp:558
bool IsNearEnd(double fps, uint vvf) const
Definition: ringbuffer.cpp:437
int Write(const void *buf, uint count)
Writes buffer to ThreadedFileWriter::Write(const void*,uint)
void SetWriteBufferMinWriteSize(int newMinSize)
Calls ThreadedFileWriter::SetWriteBufferMinWriteSize(int)
void ResetReadAhead(long long newinternal)
Restart the read-ahead thread at the 'newinternal' position.
Definition: ringbuffer.cpp:610
QMap< qint64, uint64_t > m_storageReads
Implements a file/stream reader/writer.
virtual void IgnoreWaitStates(bool)
static QStringList s_subExtNoCheck
void UpdateRawBitrate(uint raw_bitrate)
Set the raw bit rate, to allow RingBuffer adjust effective bitrate.
Definition: ringbuffer.cpp:307
void ResetCommsError(void)
long long Seek(long long pos, int whence, bool has_lock=false)
Seeks to a particular position in the file.
Definition: ringbuffer.cpp:510
const BDRingBuffer * BD(void) const
void UpdatePlaySpeed(float play_speed)
Set the play speed, to allow RingBuffer adjust effective bitrate.
Definition: ringbuffer.cpp:338
Keeps track of recordings in a current LiveTV instance.
Definition: livetvchain.h:31
#define CHUNK
virtual long long GetRealFileSizeInternal(void) const
int WaitForAvail(int count, int timeout)
void CreateReadAheadBuffer(void)
Definition: ringbuffer.cpp:832
bool isPaused(void) const
Returns false iff read-ahead is not running and read-ahead is not paused.
Definition: ringbuffer.cpp:759
RingBuffer(RingBufferType rbtype)
Definition: ringbuffer.cpp:212
int ReadBufAvail(void) const
Returns number of bytes available for reading from buffer.
Definition: ringbuffer.cpp:589
virtual bool HandleAction(const QStringList &, int64_t)
volatile bool m_recentSeek