MythTV master
DeviceReadBuffer.h
Go to the documentation of this file.
1// -*- Mode: c++ -*-
2/* Device Buffer written by John Poet */
3
4#ifndef DEVICEREADBUFFER_H
5#define DEVICEREADBUFFER_H
6
7#include <array>
8#include <unistd.h>
9
10#include <QMutex>
11#include <QWaitCondition>
12#include <QString>
13
14#include "libmythbase/mthread.h"
16
17#include "mpeg/tspacket.h"
18
20{
21 protected:
22 virtual ~DeviceReaderCB() = default;
23 public:
24 virtual void ReaderPaused(int fd) = 0;
25 virtual void PriorityEvent(int fd) = 0;
26};
27
35class DeviceReadBuffer : protected MThread
36{
37 public:
39 bool use_poll = true,
40 bool error_exit_on_poll_timeout = true);
41 ~DeviceReadBuffer() override;
42
43 bool Setup(const QString &streamName,
44 int streamfd,
45 uint readQuanta = sizeof(TSPacket),
46 uint deviceBufferSize = 0,
47 uint deviceBufferCount = 1);
48
49 void Start(void);
50 void Reset(const QString &streamName, int streamfd);
51 void Stop(void);
52
53 void SetRequestPause(bool request);
54 bool IsPaused(void) const;
55 bool WaitForUnpause(unsigned long timeout);
56 bool WaitForPaused(unsigned long timeout);
57
58 bool IsErrored(void) const;
59 bool IsEOF(void) const;
60 bool IsRunning(void) const;
61
62 uint Read(unsigned char *buf, uint count);
63 uint GetUsed(void) const;
64
65 private:
66 void run(void) override; // MThread
67
68 void SetPaused(bool val);
69 void IncrWritePointer(uint len);
70 void IncrReadPointer(uint len);
71
72 bool HandlePausing(void);
73 bool Poll(void) const;
74 void WakePoll(void) const;
75 uint WaitForUnused(uint needed) const;
76 uint WaitForUsed (uint needed, std::chrono::milliseconds max_wait) const;
77
78 bool IsPauseRequested(void) const;
79 bool IsOpen(void) const { return m_streamFd >= 0; }
80 void ClosePipes(void) const;
81 uint GetUnused(void) const;
82 uint GetContiguousUnused(void) const;
83
84 bool CheckForErrors(ssize_t read_len, size_t requested_len, uint &errcnt);
85 void ReportStats(void);
86
87 using pipe_fd_array = std::array<int,2>;
88 using pipe_flag_array = std::array<long,2>;
89 static void setup_pipe(pipe_fd_array& mypipe, pipe_flag_array& myflags);
90
92 int m_streamFd {-1};
93 mutable pipe_fd_array m_wakePipe {-1,-1};
95
97
98 // Data for managing the device ringbuffer
99 mutable QMutex m_lock;
100 volatile bool m_doRun {false};
101 bool m_eof {false};
102 mutable bool m_error {false};
103 bool m_requestPause {false};
104 bool m_paused {false};
105 bool m_usingPoll {true};
107 std::chrono::milliseconds m_maxPollWait {2500ms};
108
109 size_t m_size {0};
110 size_t m_used {0};
111 size_t m_readQuanta {0};
113 size_t m_devReadSize {0};
114 size_t m_readThreshold {0};
115 unsigned char *m_buffer {nullptr};
116 unsigned char *m_readPtr {nullptr};
117 unsigned char *m_writePtr {nullptr};
118 unsigned char *m_endPtr {nullptr};
119
120 mutable QWaitCondition m_dataWait;
121 QWaitCondition m_runWait;
122 QWaitCondition m_pauseWait;
123 QWaitCondition m_unpauseWait;
124
125 // statistics
126 size_t m_maxUsed {0};
127 size_t m_avgUsed {0};
129 size_t m_avgBufReadCnt {0};
132};
133
134#endif // DEVICEREADBUFFER_H
135
136/*
137 * vim:ts=4:sw=4:ai:et:si:sts=4
138 */
Buffers reads from device files.
void ClosePipes(void) const
bool IsRunning(void) const
uint GetUsed(void) const
bool WaitForUnpause(unsigned long timeout)
std::array< long, 2 > pipe_flag_array
unsigned char * m_writePtr
DeviceReadBuffer(DeviceReaderCB *cb, bool use_poll=true, bool error_exit_on_poll_timeout=true)
bool IsPauseRequested(void) const
volatile bool m_doRun
unsigned char * m_readPtr
QWaitCondition m_pauseWait
QWaitCondition m_runWait
unsigned char * m_endPtr
bool Setup(const QString &streamName, int streamfd, uint readQuanta=sizeof(TSPacket), uint deviceBufferSize=0, uint deviceBufferCount=1)
void SetRequestPause(bool request)
uint WaitForUnused(uint needed) const
bool IsOpen(void) const
std::chrono::milliseconds m_maxPollWait
uint Read(unsigned char *buf, uint count)
Try to Read count bytes from into buffer.
std::array< int, 2 > pipe_fd_array
~DeviceReadBuffer() override
static void setup_pipe(pipe_fd_array &mypipe, pipe_flag_array &myflags)
bool IsPaused(void) const
void IncrWritePointer(uint len)
pipe_flag_array m_wakePipeFlags
QWaitCondition m_dataWait
QWaitCondition m_unpauseWait
bool Poll(void) const
bool IsErrored(void) const
bool IsEOF(void) const
unsigned char * m_buffer
void WakePoll(void) const
DeviceReaderCB * m_readerCB
void Reset(const QString &streamName, int streamfd)
bool CheckForErrors(ssize_t read_len, size_t requested_len, uint &errcnt)
uint GetUnused(void) const
uint GetContiguousUnused(void) const
uint WaitForUsed(uint needed, std::chrono::milliseconds max_wait) const
void SetPaused(bool val)
pipe_fd_array m_wakePipe
bool WaitForPaused(unsigned long timeout)
void run(void) override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
void IncrReadPointer(uint len)
virtual void PriorityEvent(int fd)=0
virtual ~DeviceReaderCB()=default
virtual void ReaderPaused(int fd)=0
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:49
A QElapsedTimer based timer to replace use of QTime as a timer.
Definition: mythtimer.h:14
Used to access the data of a Transport Stream packet.
Definition: tspacket.h:208
unsigned int uint
Definition: freesurround.h:24