MythTV  master
DeviceReadBuffer.cpp
Go to the documentation of this file.
1 #include <algorithm>
2 
3 #include "libmythbase/compat.h"
4 #include "libmythbase/mthread.h"
8 
9 #include "DeviceReadBuffer.h"
10 #include "mpeg/tspacket.h"
11 
12 #ifndef _WIN32
13 #include <sys/poll.h>
14 #endif
15 
17 #define REPORT_RING_STATS 0 // NOLINT(cppcoreguidelines-macro-usage)
18 
19 #define LOC QString("DevRdB(%1): ").arg(m_videoDevice)
20 
22  DeviceReaderCB *cb, bool use_poll, bool error_exit_on_poll_timeout)
23  : MThread("DeviceReadBuffer"),
24  m_readerCB(cb),
25  m_usingPoll(use_poll),
26  m_pollTimeoutIsError(error_exit_on_poll_timeout)
27 {
28 #ifdef USING_MINGW
29 #warning mingw DeviceReadBuffer::Poll
30  if (m_usingPoll)
31  {
32  LOG(VB_GENERAL, LOG_WARNING, LOC +
33  "mingw DeviceReadBuffer::Poll is not implemented");
34  m_usingPoll = false;
35  }
36 #endif
37 }
38 
40 {
41  Stop();
42  if (m_buffer)
43  {
44  delete[] m_buffer;
45  m_buffer = nullptr;
46  }
47 }
48 
49 bool DeviceReadBuffer::Setup(const QString &streamName, int streamfd,
50  uint readQuanta, uint deviceBufferSize,
51  uint deviceBufferCount)
52 {
53  QMutexLocker locker(&m_lock);
54 
55  delete[] m_buffer;
56 
57  m_videoDevice = streamName;
58  m_videoDevice = m_videoDevice.isNull() ? "" : m_videoDevice;
59  m_streamFd = streamfd;
60 
61  // Setup device ringbuffer
62  m_eof = false;
63  m_error = false;
64  m_requestPause = false;
65  m_paused = false;
66 
67  m_readQuanta = (readQuanta) ? readQuanta : m_readQuanta;
68  m_devBufferCount = deviceBufferCount;
70  "HDRingbufferSize", static_cast<int>(50 * m_readQuanta)) * 1024_UZ;
71  m_used = 0;
72  m_devReadSize = m_readQuanta * (m_usingPoll ? 256 : 48);
73  m_devReadSize = (deviceBufferSize) ?
74  std::min(m_devReadSize, (size_t)deviceBufferSize) : m_devReadSize;
76 
77  m_buffer = new (std::nothrow) unsigned char[m_size + m_devReadSize];
80 
81  // Initialize buffer, if it exists
82  if (!m_buffer)
83  {
84  m_endPtr = nullptr;
85  LOG(VB_GENERAL, LOG_ERR, LOC +
86  QString("Failed to allocate buffer of size %1 = %2 + %3")
87  .arg(m_size+m_devReadSize).arg(m_size).arg(m_devReadSize));
88  return false;
89  }
91  memset(m_buffer, 0xFF, m_size + m_readQuanta);
92 
93  // Initialize statistics
94  m_maxUsed = 0;
95  m_avgUsed = 0;
96  m_avgBufWriteCnt = 0;
97  m_avgBufReadCnt = 0;
98  m_avgBufSleepCnt = 0;
100 
101  LOG(VB_RECORD, LOG_INFO, LOC + QString("buffer size %1 KB").arg(m_size/1024));
102 
103  return true;
104 }
105 
107 {
108  LOG(VB_RECORD, LOG_INFO, LOC + "Start() -- begin");
109 
110  QMutexLocker locker(&m_lock);
111  if (isRunning() || m_doRun)
112  {
113  m_doRun = false;
114  locker.unlock();
115  WakePoll();
116  wait();
117  locker.relock();
118  }
119 
120  m_doRun = true;
121  m_error = false;
122  m_eof = false;
123 
124  start();
125 
126  LOG(VB_RECORD, LOG_INFO, LOC + "Start() -- middle");
127 
128  while (m_doRun && !isRunning())
129  m_runWait.wait(locker.mutex(), 100);
130 
131  LOG(VB_RECORD, LOG_INFO, LOC + "Start() -- end");
132 }
133 
134 void DeviceReadBuffer::Reset(const QString &streamName, int streamfd)
135 {
136  QMutexLocker locker(&m_lock);
137 
138  m_videoDevice = streamName;
139  m_videoDevice = m_videoDevice.isNull() ? "" : m_videoDevice;
140  m_streamFd = streamfd;
141 
142  m_used = 0;
145 
146  m_error = false;
147 }
148 
150 {
151  LOG(VB_RECORD, LOG_INFO, LOC + "Stop() -- begin");
152  QMutexLocker locker(&m_lock);
153  if (isRunning() || m_doRun)
154  {
155  m_doRun = false;
156  locker.unlock();
157  WakePoll();
158  wait();
159  }
160  LOG(VB_RECORD, LOG_INFO, LOC + "Stop() -- end");
161 }
162 
164 {
165  QMutexLocker locker(&m_lock);
166  m_requestPause = req;
167  WakePoll();
168 }
169 
171 {
172  QMutexLocker locker(&m_lock);
173  m_paused = val;
174  if (val)
175  m_pauseWait.wakeAll();
176  else
177  m_unpauseWait.wakeAll();
178 }
179 
180 // The WakePoll code is copied from MythSocketThread::WakeReadyReadThread()
182 {
183  std::string buf(1,'\0');
184  ssize_t wret = 0;
185  while (isRunning() && (wret <= 0) && (m_wakePipe[1] >= 0))
186  {
187  wret = ::write(m_wakePipe[1], buf.data(), buf.size());
188  if ((wret < 0) && (EAGAIN != errno) && (EINTR != errno))
189  {
190  LOG(VB_GENERAL, LOG_ERR, LOC + "WakePoll failed.");
191  ClosePipes();
192  break;
193  }
194  }
195 }
196 
198 {
199  for (uint i = 0; i < 2; i++)
200  {
201  if (m_wakePipe[i] >= 0)
202  {
203  ::close(m_wakePipe[i]);
204  m_wakePipe[i] = -1;
205  m_wakePipeFlags[i] = 0;
206  }
207  }
208 }
209 
211 {
212  QMutexLocker locker(&m_lock);
213  return m_paused;
214 }
215 
217 {
218  QMutexLocker locker(&m_lock);
219 
220  if (!m_paused)
221  m_pauseWait.wait(&m_lock, timeout);
222 
223  return m_paused;
224 }
225 
227 {
228  QMutexLocker locker(&m_lock);
229 
230  if (m_paused)
231  m_unpauseWait.wait(&m_lock, timeout);
232 
233  return m_paused;
234 }
235 
237 {
238  QMutexLocker locker(&m_lock);
239  return m_requestPause;
240 }
241 
243 {
244  QMutexLocker locker(&m_lock);
245  return m_error;
246 }
247 
248 bool DeviceReadBuffer::IsEOF(void) const
249 {
250  QMutexLocker locker(&m_lock);
251  return m_eof;
252 }
253 
255 {
256  QMutexLocker locker(&m_lock);
257  return isRunning();
258 }
259 
261 {
262  QMutexLocker locker(&m_lock);
263  return m_size - m_used;
264 }
265 
267 {
268  QMutexLocker locker(&m_lock);
269  return m_used;
270 }
271 
273 {
274  QMutexLocker locker(&m_lock);
275  return m_endPtr - m_writePtr;
276 }
277 
279 {
280  QMutexLocker locker(&m_lock);
281  m_used += len;
282  m_writePtr += len;
284 #if REPORT_RING_STATS
285  m_maxUsed = std::max(m_used, m_maxUsed);
288 #endif
289  m_dataWait.wakeAll();
290 }
291 
293 {
294  QMutexLocker locker(&m_lock);
295  m_used -= len;
296  m_readPtr += len;
298 #if REPORT_RING_STATS
299  ++m_avgBufReadCnt;
300 #endif
301 }
302 
304 {
305  RunProlog();
306 
307  uint errcnt = 0;
308  uint cnt = 0;
309  ssize_t read_len = 0;
310  size_t total = 0;
311  size_t throttle = m_devReadSize * m_devBufferCount / 2;
312 
313  m_lock.lock();
314  m_runWait.wakeAll();
315  m_lock.unlock();
316 
317  if (m_usingPoll)
319 
320  while (m_doRun)
321  {
322  if (!HandlePausing())
323  continue;
324 
325  if (!IsOpen())
326  {
327  usleep(5ms);
328  continue;
329  }
330 
331  if (m_usingPoll && !Poll())
332  continue;
333 
334  {
335  QMutexLocker locker(&m_lock);
336  if (m_error)
337  {
338  LOG(VB_RECORD, LOG_ERR, LOC + "fill_ringbuffer: error state");
339  break;
340  }
341  }
342 
343  /* Some device drivers segment their buffer into small pieces,
344  * So allow for the reading of multiple buffers */
345  for (cnt = 0, read_len = 0, total = 0;
346  m_doRun && read_len >= 0 && cnt < m_devBufferCount; ++cnt)
347  {
348  // Limit read size for faster return from read
349  auto unused = static_cast<size_t>(WaitForUnused(m_readQuanta));
350  size_t read_size = std::min(m_devReadSize, unused);
351 
352  // if read_size > 0 do the read...
353  if (read_size)
354  {
355  read_len = read(m_streamFd, m_writePtr, read_size);
356  if (!CheckForErrors(read_len, read_size, errcnt))
357  break;
358  errcnt = 0;
359 
360  // if we wrote past the official end of the buffer,
361  // copy to start
362  if (m_writePtr + read_len > m_endPtr)
363  memcpy(m_buffer, m_endPtr, m_writePtr + read_len - m_endPtr);
364  IncrWritePointer(read_len);
365  total += read_len;
366  }
367  }
368  if (errcnt > 5)
369  break;
370 
371  // Slow down reading if not under load
372  if (errcnt == 0 && total < throttle)
373  usleep(1ms);
374  }
375 
376  ClosePipes();
377 
378  m_lock.lock();
379  m_eof = true;
380  m_runWait.wakeAll();
381  m_dataWait.wakeAll();
382  m_pauseWait.wakeAll();
383  m_unpauseWait.wakeAll();
384  m_lock.unlock();
385 
386  RunEpilog();
387 }
388 
390 {
391  if (IsPauseRequested())
392  {
393  SetPaused(true);
394 
395  if (m_readerCB)
397 
398  usleep(5ms);
399  return false;
400  }
401  if (IsPaused())
402  {
404  SetPaused(false);
405  }
406  return true;
407 }
408 
409 bool DeviceReadBuffer::Poll(void) const
410 {
411 #ifdef _WIN32
412 # ifdef _MSC_VER
413 # pragma message( "mingw DeviceReadBuffer::Poll" )
414 # else
415 # warning mingw DeviceReadBuffer::Poll
416 # endif
417  LOG(VB_GENERAL, LOG_ERR, LOC +
418  "mingw DeviceReadBuffer::Poll is not implemented");
419  return false;
420 #else
421  bool retval = true;
422  MythTimer timer;
423  timer.start();
424 
425  int poll_cnt = 1;
426  std::array<struct pollfd,2> polls {};
427 
428  polls[0].fd = m_streamFd;
429  polls[0].events = POLLIN | POLLPRI;
430  polls[0].revents = 0;
431 
432  if (m_wakePipe[0] >= 0)
433  {
434  poll_cnt = 2;
435  polls[1].fd = m_wakePipe[0];
436  polls[1].events = POLLIN;
437  polls[1].revents = 0;
438  }
439 
440  while (true)
441  {
442  polls[0].revents = 0;
443  polls[1].revents = 0;
444  poll_cnt = (m_wakePipe[0] >= 0) ? poll_cnt : 1;
445 
446  std::chrono::milliseconds timeout = m_maxPollWait;
447  if (1 == poll_cnt)
448  timeout = 10ms;
449  else if (m_pollTimeoutIsError)
450  // subtract a bit to allow processing time.
451  timeout = std::max(m_maxPollWait - timer.elapsed() - 15ms, 10ms);
452 
453  int ret = poll(polls.data(), poll_cnt, timeout.count());
454 
455  if (polls[0].revents & POLLHUP)
456  {
457  LOG(VB_GENERAL, LOG_ERR, LOC + "poll eof (POLLHUP)");
458  break;
459  }
460  if (polls[0].revents & POLLNVAL)
461  {
462  LOG(VB_GENERAL, LOG_ERR, LOC + "poll error" + ENO);
463  m_error = true;
464  return true;
465  }
466 
467  if (!m_doRun || !IsOpen() || IsPauseRequested())
468  {
469  retval = false;
470  break; // are we supposed to pause, stop, etc.
471  }
472 
473  if (polls[0].revents & POLLPRI)
474  {
475  m_readerCB->PriorityEvent(polls[0].fd);
476  }
477 
478  if (polls[0].revents & POLLIN)
479  {
480  if (ret > 0)
481  break; // we have data to read :)
482  if (ret < 0)
483  {
484  if ((EOVERFLOW == errno))
485  break; // we have an error to handle
486 
487  if ((EAGAIN == errno) || (EINTR == errno))
488  continue; // errors that tell you to try again
489 
490  usleep(2.5ms);
491  }
492  else // ret == 0
493  {
494  if (m_pollTimeoutIsError &&
495  (timer.elapsed() >= m_maxPollWait))
496  {
497  LOG(VB_GENERAL, LOG_ERR, LOC + "Poll giving up 1");
498  QMutexLocker locker(&m_lock);
499  m_error = true;
500  return true;
501  }
502  }
503  }
504 
505  // Clear out any pending pipe reads
506  if ((poll_cnt > 1) && (polls[1].revents & POLLIN))
507  {
508  std::array<char,128> dummy {};
509  int cnt = (m_wakePipeFlags[0] & O_NONBLOCK) ? 128 : 1;
510  ::read(m_wakePipe[0], dummy.data(), cnt);
511  }
512 
513  if (m_pollTimeoutIsError && (timer.elapsed() >= m_maxPollWait))
514  {
515  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Poll giving up after %1ms")
516  .arg(m_maxPollWait.count()));
517  QMutexLocker locker(&m_lock);
518  m_error = true;
519  return true;
520  }
521  }
522 
523  std::chrono::milliseconds e = timer.elapsed();
524  if (e > m_maxPollWait)
525  {
526  LOG(VB_GENERAL, LOG_WARNING, LOC +
527  QString("Poll took an unusually long time %1 ms")
528  .arg(timer.elapsed().count()));
529  }
530 
531  return retval;
532 #endif
533 }
534 
536  ssize_t len, size_t requested_len, uint &errcnt)
537 {
538  if (len > (ssize_t)requested_len)
539  {
540  LOG(VB_GENERAL, LOG_ERR, LOC +
541  "Driver is returning bogus values on read");
542  if (++errcnt > 5)
543  {
544  LOG(VB_RECORD, LOG_ERR, LOC + "Too many errors.");
545  QMutexLocker locker(&m_lock);
546  m_error = true;
547  }
548  return false;
549  }
550 
551 #ifdef _WIN32
552 # ifdef _MSC_VER
553 # pragma message( "mingw DeviceReadBuffer::CheckForErrors" )
554 # else
555 # warning mingw DeviceReadBuffer::CheckForErrors
556 # endif
557  LOG(VB_GENERAL, LOG_ERR, LOC +
558  "mingw DeviceReadBuffer::CheckForErrors is not implemented");
559  return false;
560 #else
561  if (len < 0)
562  {
563  if (EINTR == errno)
564  return false;
565  if (EAGAIN == errno)
566  {
567  usleep(2.5ms);
568  return false;
569  }
570  if (EOVERFLOW == errno)
571  {
572  LOG(VB_GENERAL, LOG_ERR, LOC + "Driver buffers overflowed");
573  return false;
574  }
575 
576  LOG(VB_GENERAL, LOG_ERR, LOC +
577  QString("Problem reading fd(%1)").arg(m_streamFd) + ENO);
578 
579  if (++errcnt > 5)
580  {
581  LOG(VB_RECORD, LOG_ERR, LOC + "Too many errors.");
582  QMutexLocker locker(&m_lock);
583  m_error = true;
584  return false;
585  }
586 
587  usleep(500ms);
588  return false;
589  }
590  if (len == 0)
591  {
592  if (++errcnt > 5)
593  {
594  LOG(VB_GENERAL, LOG_ERR, LOC +
595  QString("End-Of-File? fd(%1)").arg(m_streamFd));
596 
597  m_lock.lock();
598  m_eof = true;
599  m_lock.unlock();
600 
601  return false;
602  }
603  usleep(500ms);
604  return false;
605  }
606  return true;
607 #endif
608 }
609 
616 uint DeviceReadBuffer::Read(unsigned char *buf, const uint count)
617 {
618  uint avail = WaitForUsed(std::min(count, (uint)m_readThreshold), 20ms);
619  size_t cnt = std::min(count, avail);
620 
621  if (!cnt)
622  return 0;
623 
624  if (m_readPtr + cnt > m_endPtr)
625  {
626  // Process as two pieces
627  size_t len = m_endPtr - m_readPtr;
628  if (len)
629  {
630  memcpy(buf, m_readPtr, len);
631  buf += len;
632  IncrReadPointer(len);
633  }
634  if (cnt > len)
635  {
636  len = cnt - len;
637  memcpy(buf, m_readPtr, len);
638  IncrReadPointer(len);
639  }
640  }
641  else
642  {
643  memcpy(buf, m_readPtr, cnt);
644  IncrReadPointer(cnt);
645  }
646 
647 #if REPORT_RING_STATS
648  ReportStats();
649 #endif
650 
651  return cnt;
652 }
653 
659 {
660  size_t unused = GetUnused();
661 
662  if (unused > m_readQuanta)
663  {
664  while (unused < needed)
665  {
666  unused = GetUnused();
667  if (IsPauseRequested() || !IsOpen() || !m_doRun)
668  return 0;
669  usleep(5ms);
670  }
671  if (IsPauseRequested() || !IsOpen() || !m_doRun)
672  return 0;
673  unused = GetUnused();
674  }
675 
676  return unused;
677 }
678 
684 uint DeviceReadBuffer::WaitForUsed(uint needed, std::chrono::milliseconds max_wait) const
685 {
686  MythTimer timer;
687  timer.start();
688 
689  QMutexLocker locker(&m_lock);
690  size_t avail = m_used;
691  while ((needed > avail) && isRunning() &&
692  !m_requestPause && !m_error && !m_eof &&
693  (timer.elapsed() < max_wait))
694  {
695  m_dataWait.wait(locker.mutex(), 10);
696  avail = m_used;
697  }
698  return avail;
699 }
700 
702 {
703 #if REPORT_RING_STATS
704  static constexpr std::chrono::seconds secs { 20s }; // msg every 20 seconds
705  static constexpr double d1_s = 1.0 / secs.count();
706  if (m_lastReport.elapsed() > duration_cast<std::chrono::milliseconds>(secs))
707  {
708  QMutexLocker locker(&m_lock);
709  double rsize = 100.0 / m_size;
710  QString msg = QString("fill avg(%1%) ").arg(m_avgUsed*rsize,5,'f',2);
711  msg += QString("fill max(%1%) ").arg(m_maxUsed*rsize,5,'f',2);
712  msg += QString("writes/sec(%1) ").arg(m_avgBufWriteCnt*d1_s);
713  msg += QString("reads/sec(%1) ").arg(m_avgBufReadCnt*d1_s);
714  msg += QString("sleeps/sec(%1)").arg(m_avgBufSleepCnt*d1_s);
715 
716  m_avgUsed = 0;
717  m_avgBufWriteCnt = 0;
718  m_avgBufReadCnt = 0;
719  m_avgBufSleepCnt = 0;
720  m_maxUsed = 0;
722 
723  LOG(VB_GENERAL, LOG_INFO, LOC + msg);
724  }
725 #endif
726 }
727 
728 /*
729  * vim:ts=4:sw=4:ai:et:si:sts=4
730  */
MythTimer::elapsed
std::chrono::milliseconds elapsed(void)
Returns milliseconds elapsed since last start() or restart()
Definition: mythtimer.cpp:91
O_NONBLOCK
#define O_NONBLOCK
Definition: compat.h:337
DeviceReadBuffer::m_streamFd
int m_streamFd
Definition: DeviceReadBuffer.h:88
DeviceReadBuffer::m_devReadSize
size_t m_devReadSize
Definition: DeviceReadBuffer.h:109
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:283
ENO
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:73
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:103
DeviceReadBuffer::m_readPtr
unsigned char * m_readPtr
Definition: DeviceReadBuffer.h:112
DeviceReadBuffer::m_pauseWait
QWaitCondition m_pauseWait
Definition: DeviceReadBuffer.h:118
DeviceReadBuffer::m_maxUsed
size_t m_maxUsed
Definition: DeviceReadBuffer.h:122
DeviceReadBuffer::Start
void Start(void)
Definition: DeviceReadBuffer.cpp:106
DeviceReadBuffer::m_used
size_t m_used
Definition: DeviceReadBuffer.h:106
DeviceReadBuffer::WakePoll
void WakePoll(void) const
Definition: DeviceReadBuffer.cpp:181
DeviceReadBuffer::Setup
bool Setup(const QString &streamName, int streamfd, uint readQuanta=sizeof(TSPacket), uint deviceBufferSize=0, uint deviceBufferCount=1)
Definition: DeviceReadBuffer.cpp:49
DeviceReadBuffer::m_wakePipeFlags
pipe_flag_array m_wakePipeFlags
Definition: DeviceReadBuffer.h:90
DeviceReadBuffer::m_devBufferCount
size_t m_devBufferCount
Definition: DeviceReadBuffer.h:108
MythTimer
A QElapsedTimer based timer to replace use of QTime as a timer.
Definition: mythtimer.h:13
DeviceReadBuffer::IsPaused
bool IsPaused(void) const
Definition: DeviceReadBuffer.cpp:210
MThread::wait
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:300
DeviceReadBuffer::WaitForPaused
bool WaitForPaused(unsigned long timeout)
Definition: DeviceReadBuffer.cpp:216
discid.disc.read
def read(device=None, features=[])
Definition: disc.py:35
MThread::usleep
static void usleep(std::chrono::microseconds time)
Definition: mthread.cpp:335
mythburn.write
def write(text, progress=True)
Definition: mythburn.py:308
DeviceReadBuffer::m_runWait
QWaitCondition m_runWait
Definition: DeviceReadBuffer.h:117
DeviceReadBuffer::WaitForUsed
uint WaitForUsed(uint needed, std::chrono::milliseconds max_wait) const
Definition: DeviceReadBuffer.cpp:684
DeviceReadBuffer::Read
uint Read(unsigned char *buf, uint count)
Try to Read count bytes from into buffer.
Definition: DeviceReadBuffer.cpp:616
DeviceReadBuffer::m_avgBufWriteCnt
size_t m_avgBufWriteCnt
Definition: DeviceReadBuffer.h:124
MythTimer::start
void start(void)
starts measuring elapsed time.
Definition: mythtimer.cpp:47
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MThread::RunProlog
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:196
DeviceReadBuffer::m_wakePipe
pipe_fd_array m_wakePipe
Definition: DeviceReadBuffer.h:89
DeviceReadBuffer::IsPauseRequested
bool IsPauseRequested(void) const
Definition: DeviceReadBuffer.cpp:236
DeviceReadBuffer::WaitForUnpause
bool WaitForUnpause(unsigned long timeout)
Definition: DeviceReadBuffer.cpp:226
DeviceReaderCB
Definition: DeviceReadBuffer.h:19
DeviceReadBuffer::GetContiguousUnused
uint GetContiguousUnused(void) const
Definition: DeviceReadBuffer.cpp:272
DeviceReadBuffer::m_requestPause
bool m_requestPause
Definition: DeviceReadBuffer.h:99
close
#define close
Definition: compat.h:43
DeviceReaderCB::ReaderPaused
virtual void ReaderPaused(int fd)=0
DeviceReadBuffer::m_eof
bool m_eof
Definition: DeviceReadBuffer.h:97
DeviceReadBuffer::WaitForUnused
uint WaitForUnused(uint needed) const
Definition: DeviceReadBuffer.cpp:658
DeviceReadBuffer::CheckForErrors
bool CheckForErrors(ssize_t read_len, size_t requested_len, uint &errcnt)
Definition: DeviceReadBuffer.cpp:535
DeviceReadBuffer::m_pollTimeoutIsError
bool m_pollTimeoutIsError
Definition: DeviceReadBuffer.h:102
DeviceReadBuffer::m_doRun
volatile bool m_doRun
Definition: DeviceReadBuffer.h:96
mythlogging.h
setup_pipe
static void setup_pipe(pipe_fd_array &, pipe_flag_array &)
Definition: mythbaseutil.h:20
DeviceReadBuffer::m_readerCB
DeviceReaderCB * m_readerCB
Definition: DeviceReadBuffer.h:92
DeviceReadBuffer::m_readQuanta
size_t m_readQuanta
Definition: DeviceReadBuffer.h:107
compat.h
DeviceReadBuffer::m_videoDevice
QString m_videoDevice
Definition: DeviceReadBuffer.h:87
DeviceReadBuffer::IsRunning
bool IsRunning(void) const
Definition: DeviceReadBuffer.cpp:254
DeviceReadBuffer::m_usingPoll
bool m_usingPoll
Definition: DeviceReadBuffer.h:101
MThread::RunEpilog
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:209
tspacket.h
DeviceReadBuffer::m_buffer
unsigned char * m_buffer
Definition: DeviceReadBuffer.h:111
DeviceReadBuffer::IsOpen
bool IsOpen(void) const
Definition: DeviceReadBuffer.h:79
DeviceReadBuffer::Stop
void Stop(void)
Definition: DeviceReadBuffer.cpp:149
DeviceReadBuffer::m_unpauseWait
QWaitCondition m_unpauseWait
Definition: DeviceReadBuffer.h:119
sizetliteral.h
DeviceReadBuffer::m_readThreshold
size_t m_readThreshold
Definition: DeviceReadBuffer.h:110
uint
unsigned int uint
Definition: compat.h:79
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:54
DeviceReadBuffer::ClosePipes
void ClosePipes(void) const
Definition: DeviceReadBuffer.cpp:197
DeviceReaderCB::PriorityEvent
virtual void PriorityEvent(int fd)=0
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:910
DeviceReadBuffer::m_lock
QMutex m_lock
Definition: DeviceReadBuffer.h:95
DeviceReadBuffer::m_size
size_t m_size
Definition: DeviceReadBuffer.h:105
DeviceReadBuffer::m_avgUsed
size_t m_avgUsed
Definition: DeviceReadBuffer.h:123
DeviceReadBuffer::GetUnused
uint GetUnused(void) const
Definition: DeviceReadBuffer.cpp:260
DeviceReadBuffer::~DeviceReadBuffer
~DeviceReadBuffer() override
Definition: DeviceReadBuffer.cpp:39
DeviceReadBuffer::ReportStats
void ReportStats(void)
Definition: DeviceReadBuffer.cpp:701
mythcorecontext.h
DeviceReadBuffer::SetPaused
void SetPaused(bool val)
Definition: DeviceReadBuffer.cpp:170
DeviceReadBuffer::m_maxPollWait
std::chrono::milliseconds m_maxPollWait
Definition: DeviceReadBuffer.h:103
DeviceReadBuffer::m_writePtr
unsigned char * m_writePtr
Definition: DeviceReadBuffer.h:113
DeviceReadBuffer::Poll
bool Poll(void) const
Definition: DeviceReadBuffer.cpp:409
DeviceReadBuffer::HandlePausing
bool HandlePausing(void)
Definition: DeviceReadBuffer.cpp:389
DeviceReadBuffer::DeviceReadBuffer
DeviceReadBuffer(DeviceReaderCB *cb, bool use_poll=true, bool error_exit_on_poll_timeout=true)
Definition: DeviceReadBuffer.cpp:21
MThread
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:48
DeviceReadBuffer::m_avgBufSleepCnt
size_t m_avgBufSleepCnt
Definition: DeviceReadBuffer.h:126
mthread.h
DeviceReadBuffer::m_error
bool m_error
Definition: DeviceReadBuffer.h:98
MThread::isRunning
bool isRunning(void) const
Definition: mthread.cpp:263
DeviceReadBuffer::IsErrored
bool IsErrored(void) const
Definition: DeviceReadBuffer.cpp:242
DeviceReadBuffer::run
void run(void) override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: DeviceReadBuffer.cpp:303
DeviceReadBuffer::IncrWritePointer
void IncrWritePointer(uint len)
Definition: DeviceReadBuffer.cpp:278
DeviceReadBuffer::m_avgBufReadCnt
size_t m_avgBufReadCnt
Definition: DeviceReadBuffer.h:125
DeviceReadBuffer::IsEOF
bool IsEOF(void) const
Definition: DeviceReadBuffer.cpp:248
DeviceReadBuffer::m_paused
bool m_paused
Definition: DeviceReadBuffer.h:100
DeviceReadBuffer::SetRequestPause
void SetRequestPause(bool request)
Definition: DeviceReadBuffer.cpp:163
LOC
#define LOC
Definition: DeviceReadBuffer.cpp:19
DeviceReadBuffer::m_dataWait
QWaitCondition m_dataWait
Definition: DeviceReadBuffer.h:116
DeviceReadBuffer.h
DeviceReadBuffer::m_lastReport
MythTimer m_lastReport
Definition: DeviceReadBuffer.h:127
DeviceReadBuffer::IncrReadPointer
void IncrReadPointer(uint len)
Definition: DeviceReadBuffer.cpp:292
DeviceReadBuffer::m_endPtr
unsigned char * m_endPtr
Definition: DeviceReadBuffer.h:114
DeviceReadBuffer::Reset
void Reset(const QString &streamName, int streamfd)
Definition: DeviceReadBuffer.cpp:134
DeviceReadBuffer::GetUsed
uint GetUsed(void) const
Definition: DeviceReadBuffer.cpp:266