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 class ThreadedFileWriter;
29 class DVDRingBuffer;
30 class BDRingBuffer;
31 class LiveTVChain;
32 class RemoteFile;
33 
35 {
43 };
44 
45 class MTV_PUBLIC RingBuffer : protected MThread
46 {
47  friend class ICRingBuffer;
48 
49  public:
50  static RingBuffer *Create(const QString &xfilename, bool write,
51  bool usereadahead = true,
52  int timeout_ms = kDefaultOpenTimeout,
53  bool stream_only = false);
54  virtual ~RingBuffer() = 0;
55 
56  // Sets
57  void SetWriteBufferSize(int newSize);
58  void SetWriteBufferMinWriteSize(int newMinSize);
59  void SetOldFile(bool is_old);
60  void UpdateRawBitrate(uint raw_bitrate);
61  void UpdatePlaySpeed(float play_speed);
62  void EnableBitrateMonitor(bool enable) { bitrateMonitorEnabled = enable; }
63  void SetBufferSizeFactors(bool estbitrate, bool matroska);
64  void SetWaitForWrite(void) { waitforwrite = true; }
65 
66  // Gets
67  QString GetSafeFilename(void) { return safefilename; }
68  QString GetFilename(void) const;
69  QString GetSubtitleFilename(void) const;
70  QString GetLastError(void) const;
71  bool GetCommsError(void) const { return commserror; }
72  void ResetCommsError(void) { commserror = 0; }
73 
76  bool GetStopReads(void) const { return stopreads; }
77  bool isPaused(void) const;
79  virtual long long GetReadPosition(void) const = 0;
80  QString GetDecoderRate(void);
81  QString GetStorageRate(void);
82  QString GetAvailableBuffer(void);
83  uint GetBufferSize(void) { return bufferSize; }
84  long long GetWritePosition(void) const;
87  long long GetRealFileSize(void) const;
88  bool IsNearEnd(double fps, uint vvf) const;
90  virtual bool IsOpen(void) const = 0;
91  virtual bool IsStreamed(void) { return LiveMode(); }
92  virtual bool IsSeekingAllowed(void) { return true; }
93  virtual bool IsBookmarkAllowed(void) { return true; }
94  virtual int BestBufferSize(void) { return 32768; }
95  static QString BitrateToString(uint64_t rate, bool hz = false);
96  RingBufferType GetType() const { return type; }
97 
98  // LiveTV used utilities
99  int GetReadBufAvail() const;
100  bool SetReadInternalMode(bool mode);
101  bool IsReadInternalMode(void) { return readInternalMode; }
102 
103  // DVD and bluray methods
104  bool IsDisc(void) const { return IsDVD() || IsBD(); }
105  bool IsDVD(void) const { return type == kRingBuffer_DVD; }
106  bool IsBD(void) const { return type == kRingBuffer_BD; }
107  const DVDRingBuffer *DVD(void) const;
108  const BDRingBuffer *BD(void) const;
109  DVDRingBuffer *DVD(void);
110  BDRingBuffer *BD(void);
111  virtual bool StartFromBeginning(void) { return true; }
112  virtual void IgnoreWaitStates(bool /*ignore*/) { }
113  virtual bool IsInMenu(void) const { return false; }
114  virtual bool IsInStillFrame(void) const { return false; }
115  virtual bool IsInDiscMenuOrStillFrame(void) const { return IsInMenu() || IsInStillFrame(); }
116  virtual bool HandleAction(const QStringList &, int64_t) { return false; }
117 
118  // General Commands
119 
126  virtual bool OpenFile(const QString &lfilename,
127  uint retry_ms = kDefaultOpenTimeout) = 0;
128  virtual bool ReOpen(QString /*newFilename*/ = "") { return false; }
129 
130  int Read(void *buf, int count);
131  int Peek(void *buf, int count); // only works with readahead
132 
133  void Reset(bool full = false,
134  bool toAdjust = false,
135  bool resetInternal = false);
136 
138  long long Seek(long long pos, int whence, bool has_lock = false);
139 
140  // Pause commands
141  void Pause(void);
142  void Unpause(void);
143  void WaitForPause(void);
144 
145  // Start/Stop commands
146  void Start(void);
147  void StopReads(void);
148  void StartReads(void);
149 
150  // LiveTVChain support
151  bool LiveMode(void) const;
152  void SetLiveMode(LiveTVChain *chain);
153  void IgnoreLiveEOF(bool ignore);
154 
155  // ThreadedFileWriter proxies
156  int Write(const void *buf, uint count);
157  bool IsIOBound(void) const;
158  void WriterFlush(void);
159  void Sync(void);
160  long long WriterSeek(long long pos, int whence, bool has_lock = false);
161  bool WriterSetBlocking(bool lock = true);
162 
163  long long SetAdjustFilesize(void);
164 
165  static const int kDefaultOpenTimeout;
166  static const int kLiveTVOpenTimeout;
167 
168  static void AVFormatInitNetwork(void);
169 
170  protected:
171  explicit RingBuffer(RingBufferType rbtype);
172 
173  void run(void) override; // MThread
174  void CreateReadAheadBuffer(void);
175  void CalcReadAheadThresh(void);
176  bool PauseAndWait(void);
177  virtual int safe_read(void *data, uint sz) = 0;
178 
179  int ReadPriv(void *buf, int count, bool peek);
180  int ReadDirect(void *buf, int count, bool peek);
181  bool WaitForReadsAllowed(void);
182  int WaitForAvail(int count, int timeout);
183  virtual long long GetRealFileSizeInternal(void) const { return -1; }
184  virtual long long SeekInternal(long long pos, int whence) = 0;
185 
186  int ReadBufFree(void) const;
187  int ReadBufAvail(void) const;
188 
189  void ResetReadAhead(long long newinternal);
190  void KillReadAheadThread(void);
191 
192  uint64_t UpdateDecoderRate(uint64_t latest = 0);
193  uint64_t UpdateStorageRate(uint64_t latest = 0);
194 
195  protected:
197  mutable QReadWriteLock poslock;
198  long long readpos; // protected by poslock
199  long long writepos; // protected by poslock
200  long long internalreadpos; // protected by poslock
201  long long ignorereadpos; // protected by poslock
202  mutable QReadWriteLock rbrlock;
203  int rbrpos; // protected by rbrlock
204  mutable QReadWriteLock rbwlock;
205  int rbwpos; // protected by rbwlock
206 
207  // note should not go under rwlock..
208  // this is used to break out of read_safe where rwlock is held
209  volatile bool stopreads;
210 
211  mutable QReadWriteLock rwlock;
212 
213  QString safefilename; // unprotected (for debugging)
214  QString filename; // protected by rwlock
215  QString subtitlefilename; // protected by rwlock
216  QString lastError; // protected by rwlock
217 
218  ThreadedFileWriter *tfw; // protected by rwlock
219  int fd2; // protected by rwlock
220 
221  bool writemode; // protected by rwlock
222 
223  RemoteFile *remotefile; // protected by rwlock
224 
225  uint bufferSize; // protected by rwlock
226  bool low_buffers; // protected by rwlock
227  bool fileismatroska; // protected by rwlock
228  bool unknownbitrate; // protected by rwlock
229  bool startreadahead; // protected by rwlock
230  char *readAheadBuffer; // protected by rwlock
231  bool readaheadrunning; // protected by rwlock
232  bool reallyrunning; // protected by rwlock
233  bool request_pause; // protected by rwlock
234  bool paused; // protected by rwlock
235  bool ateof; // protected by rwlock
236  bool waitforwrite; // protected by rwlock
237  bool beingwritten; // protected by rwlock
238  bool readsallowed; // protected by rwlock
239  bool readsdesired; // protected by rwlock
240  volatile bool recentseek;
241  bool setswitchtonext; // protected by rwlock
242  uint rawbitrate; // protected by rwlock
243  float playspeed; // protected by rwlock
244  int fill_threshold; // protected by rwlock
245  int fill_min; // protected by rwlock
246  int readblocksize; // protected by rwlock
247  int wanttoread; // protected by rwlock
248  int numfailures; // protected by rwlock (see note 1)
249  bool commserror; // protected by rwlock
250 
251  bool oldfile; // protected by rwlock
252 
253  LiveTVChain *livetvchain; // protected by rwlock
254  bool ignoreliveeof; // protected by rwlock
255 
256  long long readAdjust; // protected by rwlock
257 
258  // Internal RingBuffer Method
259  int readOffset; // protected by rwlock
260  bool readInternalMode; // protected by rwlock
261 
262  // bitrate monitors
265  QMap<qint64, uint64_t> decoderReads;
267  QMap<qint64, uint64_t> storageReads;
268 
269  // note 1: numfailures is modified with only a read lock in the
270  // read ahead thread, but this is safe since all other places
271  // that use it are protected by a write lock. But this is a
272  // fragile state of affairs and care must be taken when modifying
273  // code or locking around this variable.
274 
276  QWaitCondition generalWait; // protected by rwlock
277 
278  public:
279  static QMutex subExtLock;
280  static QStringList subExt;
281  static QStringList subExtNoCheck;
282 
283  private:
286 };
287 
288 #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:768
const DVDRingBuffer * DVD(void) const
virtual int BestBufferSize(void)
int GetReadBufAvail() const
Returns number of bytes available for reading from buffer.
Definition: ringbuffer.cpp:525
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:319
QString GetLastError(void) const
QString GetSafeFilename(void)
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:757
uint64_t UpdateDecoderRate(uint64_t latest=0)
QString GetFilename(void) const
Returns name of file used by this RingBuffer.
volatile bool recentseek
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:112
bool IsOpen(void) const override
Returns true if open for either reading or writing.
QReadWriteLock rwlock
QString GetDecoderRate(void)
QString GetStorageRate(void)
volatile bool stopreads
void CalcReadAheadThresh(void)
Calculates fill_min, fill_threshold, and readblocksize from the estimated effective bitrate of the st...
Definition: ringbuffer.cpp:402
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:386
QReadWriteLock rbrlock
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).
virtual bool IsInMenu(void) const
bool PauseAndWait(void)
Definition: ringbuffer.cpp:824
static bool gAVformat_net_initialised
QReadWriteLock poslock
QString GetAvailableBuffer(void)
#define MTV_PUBLIC
Definition: mythtvexp.h:15
virtual bool IsInStillFrame(void) const
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:729
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:281
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:514
bool IsBD(void) const
int Peek(void *buf, int count)
bool IsIOBound(void) const
void Start(void)
Starts the read-ahead thread.
Definition: ringbuffer.cpp:688
void WaitForPause(void)
Waits for Pause(void) to take effect.
Definition: ringbuffer.cpp:805
void StopReads(void)
????
Definition: ringbuffer.cpp:746
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 subExtNoCheck
void Unpause(void)
Unpauses the read-ahead thread.
Definition: ringbuffer.cpp:782
LiveTVChain * livetvchain
bool IsDisc(void) const
bool WaitForReadsAllowed(void)
ThreadedFileWriter * tfw
QString GetSubtitleFilename(void) const
static QMutex subExtLock
QWaitCondition generalWait
Condition to signal that the read ahead thread is running.
QMap< qint64, uint64_t > storageReads
long long GetRealFileSize(void) const
Returns the size of the file we are reading/writing, or -1 if the query fails.
Definition: ringbuffer.cpp:532
virtual bool IsSeekingAllowed(void)
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
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:593
bool IsNearEnd(double fps, uint vvf) const
Definition: ringbuffer.cpp:472
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:645
Implements a file/stream reader/writer.
QReadWriteLock rbwlock
virtual void IgnoreWaitStates(bool)
static QStringList subExt
void UpdateRawBitrate(uint raw_bitrate)
Set the raw bit rate, to allow RingBuffer adjust effective bitrate.
Definition: ringbuffer.cpp:342
QMap< qint64, uint64_t > decoderReads
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:545
const BDRingBuffer * BD(void) const
void UpdatePlaySpeed(float play_speed)
Set the play speed, to allow RingBuffer adjust effective bitrate.
Definition: ringbuffer.cpp:373
Keeps track of recordings in a current LiveTV instance.
Definition: livetvchain.h:31
virtual long long GetRealFileSizeInternal(void) const
int WaitForAvail(int count, int timeout)
virtual bool ReOpen(QString="")
void CreateReadAheadBuffer(void)
Definition: ringbuffer.cpp:867
bool isPaused(void) const
Returns false iff read-ahead is not running and read-ahead is not paused.
Definition: ringbuffer.cpp:794
RingBuffer(RingBufferType rbtype)
Definition: ringbuffer.cpp:220
int ReadBufAvail(void) const
Returns number of bytes available for reading from buffer.
Definition: ringbuffer.cpp:624
virtual bool HandleAction(const QStringList &, int64_t)