MythTV  0.26-pre
ringbuffer.h
Go to the documentation of this file.
00001 // -*- Mode: c++ -*-
00002 
00003 #ifndef _RINGBUFFER_H_
00004 #define _RINGBUFFER_H_
00005 
00006 #include <QReadWriteLock>
00007 #include <QWaitCondition>
00008 #include <QString>
00009 #include <QMutex>
00010 #include <QMap>
00011 
00012 #include "mythconfig.h"
00013 #include "mthread.h"
00014 
00015 extern "C" {
00016 #include "libavcodec/avcodec.h"
00017 }
00018 
00019 #include "mythtvexp.h"
00020 
00021 #define PNG_MIN_SIZE   20 /* header plus one empty chunk */
00022 #define NUV_MIN_SIZE  204 /* header size? */
00023 #define MPEG_MIN_SIZE 376 /* 2 TS packets */
00024 
00025 /* should be minimum of the above test sizes */
00026 #define kReadTestSize PNG_MIN_SIZE
00027 
00028 class ThreadedFileWriter;
00029 class DVDRingBuffer;
00030 class BDRingBuffer;
00031 class LiveTVChain;
00032 class RemoteFile;
00033 
00034 enum RingBufferType
00035 {
00036     kRingBuffer_Unknown = 0,
00037     kRingBuffer_File,
00038     kRingBuffer_DVD,
00039     kRingBuffer_BD,
00040     kRingBuffer_HTTP,
00041     kRingBuffer_HLS,
00042 };
00043 
00044 class MTV_PUBLIC RingBuffer : protected MThread
00045 {
00046   public:
00047     static RingBuffer *Create(const QString &lfilename, bool write,
00048                               bool usereadahead = true,
00049                               int timeout_ms = kDefaultOpenTimeout,
00050                               bool stream_only = false);
00051     virtual ~RingBuffer();
00052 
00053     // Sets
00054     void SetWriteBufferSize(int newSize);
00055     void SetWriteBufferMinWriteSize(int newMinSize);
00056     void SetOldFile(bool is_old);
00057     void UpdateRawBitrate(uint rawbitrate);
00058     void UpdatePlaySpeed(float playspeed);
00059     void EnableBitrateMonitor(bool enable) { bitrateMonitorEnabled = enable; }
00060     void SetBufferSizeFactors(bool estbitrate, bool matroska);
00061 
00062     // Gets
00063     QString   GetSafeFilename(void) { return safefilename; }
00064     QString   GetFilename(void)      const;
00065     QString   GetSubtitleFilename(void) const;
00068     bool      GetStopReads(void)     const { return stopreads; }
00069     bool      isPaused(void)         const;
00071     virtual long long GetReadPosition(void)  const = 0;
00072     QString GetDecoderRate(void);
00073     QString GetStorageRate(void);
00074     QString GetAvailableBuffer(void);
00075     uint    GetBufferSize(void) { return bufferSize; }
00076     long long GetWritePosition(void) const;
00079     virtual long long GetRealFileSize(void)  const { return -1; }
00080     bool      IsNearEnd(double fps, uint vvf) const;
00082     virtual bool IsOpen(void) const = 0;
00083     virtual bool IsStreamed(void)       { return LiveMode(); }
00084     virtual bool IsSeekingAllowed(void) { return true;  }
00085     virtual bool IsBookmarkAllowed(void) { return true; }
00086     virtual int  BestBufferSize(void)   { return 32768; }
00087     static QString BitrateToString(uint64_t rate, bool hz = false);
00088 
00089     // DVD and bluray methods
00090     bool IsDisc(void) const { return IsDVD() || IsBD(); }
00091     bool IsDVD(void)  const { return type == kRingBuffer_DVD; }
00092     bool IsBD(void)   const { return type == kRingBuffer_BD;  }
00093     const DVDRingBuffer *DVD(void) const;
00094     const BDRingBuffer  *BD(void)  const;
00095     DVDRingBuffer *DVD(void);
00096     BDRingBuffer  *BD(void);
00097     virtual bool StartFromBeginning(void)                   { return true;  }
00098     virtual void IgnoreWaitStates(bool ignore)              { }
00099     virtual bool IsInDiscMenuOrStillFrame(void) const       { return false; }
00100     virtual bool HandleAction(const QStringList &, int64_t) { return false; }
00101 
00102     // General Commands
00103 
00110     virtual bool OpenFile(const QString &lfilename,
00111                           uint retry_ms = kDefaultOpenTimeout) = 0;
00112     virtual bool ReOpen(QString newFilename = "") { return false; }
00113 
00114     int  Read(void *buf, int count);
00115     int  Peek(void *buf, int count); // only works with readahead
00116 
00117     void Reset(bool full          = false,
00118                bool toAdjust      = false,
00119                bool resetInternal = false);
00120 
00122     virtual long long Seek(
00123         long long pos, int whence, bool has_lock = false) = 0;
00124 
00125     // Pause commands
00126     void Pause(void);
00127     void Unpause(void);
00128     void WaitForPause(void);
00129 
00130     // Start/Stop commands
00131     void Start(void);
00132     void StopReads(void);
00133     void StartReads(void);
00134 
00135     // LiveTVChain support
00136     bool LiveMode(void) const;
00137     void SetLiveMode(LiveTVChain *chain);
00138     void IgnoreLiveEOF(bool ignore);
00139 
00140     // ThreadedFileWriter proxies
00141     int  Write(const void *buf, uint count);
00142     bool IsIOBound(void) const;
00143     void WriterFlush(void);
00144     void Sync(void);
00145     long long WriterSeek(long long pos, int whence, bool has_lock = false);
00146 
00147     long long SetAdjustFilesize(void);
00148 
00150     void SetTimeout(bool is_old) MDEPRECATED { SetOldFile(is_old); }
00151 
00152     static const int kDefaultOpenTimeout;
00153     static const int kLiveTVOpenTimeout;
00154 
00155   protected:
00156     RingBuffer(RingBufferType rbtype);
00157 
00158     void run(void); // MThread
00159     void CreateReadAheadBuffer(void);
00160     void CalcReadAheadThresh(void);
00161     bool PauseAndWait(void);
00162     virtual int safe_read(void *data, uint sz) = 0;
00163 
00164     int ReadPriv(void *buf, int count, bool peek);
00165     int ReadDirect(void *buf, int count, bool peek);
00166     bool WaitForReadsAllowed(void);
00167     bool WaitForAvail(int count);
00168 
00169     int ReadBufFree(void) const;
00170     int ReadBufAvail(void) const;
00171 
00172     void ResetReadAhead(long long newinternal);
00173     void KillReadAheadThread(void);
00174 
00175     uint64_t UpdateDecoderRate(uint64_t latest = 0);
00176     uint64_t UpdateStorageRate(uint64_t latest = 0);
00177 
00178   protected:
00179     RingBufferType type;
00180     mutable QReadWriteLock poslock;
00181     long long readpos;            // protected by poslock
00182     long long writepos;           // protected by poslock
00183     long long internalreadpos;    // protected by poslock
00184     long long ignorereadpos;      // protected by poslock
00185     mutable QReadWriteLock rbrlock;
00186     int       rbrpos;             // protected by rbrlock
00187     mutable QReadWriteLock rbwlock;
00188     int       rbwpos;             // protected by rbwlock
00189 
00190     // note should not go under rwlock..
00191     // this is used to break out of read_safe where rwlock is held
00192     volatile bool stopreads;
00193 
00194     mutable QReadWriteLock rwlock;
00195 
00196     QString safefilename;         // unprotected (for debugging)
00197     QString filename;             // protected by rwlock
00198     QString subtitlefilename;     // protected by rwlock
00199 
00200     ThreadedFileWriter *tfw;      // protected by rwlock
00201     int fd2;                      // protected by rwlock
00202 
00203     bool writemode;               // protected by rwlock
00204 
00205     RemoteFile *remotefile;       // protected by rwlock
00206 
00207     uint      bufferSize;         // protected by rwlock
00208     bool      low_buffers;        // protected by rwlock
00209     bool      fileismatroska;     // protected by rwlock
00210     bool      unknownbitrate;     // protected by rwlock
00211     bool      startreadahead;     // protected by rwlock
00212     char     *readAheadBuffer;    // protected by rwlock
00213     bool      readaheadrunning;   // protected by rwlock
00214     bool      reallyrunning;      // protected by rwlock
00215     bool      request_pause;      // protected by rwlock
00216     bool      paused;             // protected by rwlock
00217     bool      ateof;              // protected by rwlock
00218     bool      readsallowed;       // protected by rwlock
00219     bool      setswitchtonext;    // protected by rwlock
00220     uint      rawbitrate;         // protected by rwlock
00221     float     playspeed;          // protected by rwlock
00222     int       fill_threshold;     // protected by rwlock
00223     int       fill_min;           // protected by rwlock
00224     int       readblocksize;      // protected by rwlock
00225     int       wanttoread;         // protected by rwlock
00226     int       numfailures;        // protected by rwlock (see note 1)
00227     bool      commserror;         // protected by rwlock
00228 
00229     bool oldfile;                 // protected by rwlock
00230 
00231     LiveTVChain *livetvchain;     // protected by rwlock
00232     bool ignoreliveeof;           // protected by rwlock
00233 
00234     long long readAdjust;         // protected by rwlock
00235 
00236     // bitrate monitors
00237     bool              bitrateMonitorEnabled;
00238     QMutex            decoderReadLock;
00239     QMap<qint64, uint64_t> decoderReads;
00240     QMutex            storageReadLock;
00241     QMap<qint64, uint64_t> storageReads;
00242 
00243     // note 1: numfailures is modified with only a read lock in the
00244     // read ahead thread, but this is safe since all other places
00245     // that use it are protected by a write lock. But this is a
00246     // fragile state of affairs and care must be taken when modifying
00247     // code or locking around this variable.
00248 
00250     QWaitCondition generalWait;         // protected by rwlock
00251 
00252   public:
00253     static QMutex subExtLock;
00254     static QStringList subExt;
00255     static QStringList subExtNoCheck;
00256 };
00257 
00258 #endif // _RINGBUFFER_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends