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  virtual ~RingBuffer() = 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 = 0; }
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 &, int64_t) { return false; }
125 
126  // General Commands
127 
134  virtual bool OpenFile(const QString &lfilename,
135  uint retry_ms = kDefaultOpenTimeout) = 0;
136  virtual bool ReOpen(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.
unsigned int uint
Definition: compat.h:140
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
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.
virtual ~RingBuffer()=0
Deletes.
Definition: ringbuffer.cpp:246
bool GetCommsError(void) const
void SetOldFile(bool is_old)
Tell RingBuffer if this is an old file or not.
static const int kLiveTVOpenTimeout
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
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)
virtual bool ReOpen(QString="")
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