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