MythTV  master
mythmediabuffer.cpp
Go to the documentation of this file.
1 // Qt
2 #include <QFile>
3 #include <QDateTime>
4 #include <QReadLocker>
5 
6 // MythTV
7 #include "threadedfilewriter.h"
8 #include "io/mythfilebuffer.h"
10 #include "mythmiscutil.h"
11 #include "livetvchain.h"
12 #include "mythcontext.h"
13 #include "mythconfig.h"
14 #include "remotefile.h"
15 #include "compat.h"
16 #include "mythdate.h"
17 #include "mythtimer.h"
18 #include "mythlogging.h"
19 #include "DVD/mythdvdbuffer.h"
20 #include "DVD/mythdvdstream.h"
21 #include "Bluray/mythbdbuffer.h"
23 #include "mythcdrom.h"
24 #include "io/mythmediabuffer.h"
25 
26 // Std
27 #include <cmath>
28 #include <cstdio>
29 #include <cstdlib>
30 #include <cerrno>
31 #include <chrono>
32 #include <thread>
33 #include <sys/types.h>
34 #include <sys/time.h>
35 #include <unistd.h>
36 #include <fcntl.h>
37 
38 // FFmpeg
39 extern "C" {
40 #include "libavformat/avformat.h"
41 }
42 
43 const int MythMediaBuffer::kDefaultOpenTimeout = 2000; // ms
44 const int MythMediaBuffer::kLiveTVOpenTimeout = 10000;
45 
46 #define LOC QString("RingBuf(%1): ").arg(m_filename)
47 
48 
49 /*
50  Locking relations:
51  rwlock->poslock->rbrlock->rbwlock
52 
53  A child should never lock any of the parents without locking
54  the parent lock before the child lock.
55  void MythMediaBuffer::Example1()
56  {
57  poslock.lockForWrite();
58  rwlock.lockForRead(); // error!
59  blah(); // <- does not implicitly acquire any locks
60  rwlock.unlock();
61  poslock.unlock();
62  }
63  void MythMediaBuffer::Example2()
64  {
65  rwlock.lockForRead();
66  rbrlock.lockForWrite(); // ok!
67  blah(); // <- does not implicitly acquire any locks
68  rbrlock.unlock();
69  rwlock.unlock();
70  }
71 */
72 
100 MythMediaBuffer *MythMediaBuffer::Create(const QString &Filename, bool Write,
101  bool UseReadAhead, int Timeout, bool StreamOnly)
102 {
103  QString filename = Filename;
104  QString lower = filename.toLower();
105 
106  if (Write)
107  return new MythFileBuffer(filename, Write, UseReadAhead, Timeout);
108 
109  bool dvddir = false;
110  bool bddir = false;
111  bool httpurl = lower.startsWith("http://") || lower.startsWith("https://");
112  bool iptvurl = lower.startsWith("rtp://") || lower.startsWith("tcp://") ||
113  lower.startsWith("udp://");
114  bool mythurl = lower.startsWith("myth://");
115  bool bdurl = lower.startsWith("bd:");
116  bool dvdurl = lower.startsWith("dvd:");
117  bool imgext = lower.endsWith(".img") || lower.endsWith(".iso");
118 
119  if (imgext)
120  {
122  {
123  case MythCDROM::kBluray:
124  bdurl = true;
125  break;
126  case MythCDROM::kDVD:
127  dvdurl = true;
128  break;
129  default: break;
130  }
131  }
132 
133  if (httpurl || iptvurl)
134  {
136  return new HLSRingBuffer(filename);
137  return new MythStreamingBuffer(filename);
138  }
139  if (!StreamOnly && mythurl)
140  {
141  struct stat fileInfo {};
143  (S_ISDIR(fileInfo.st_mode)))
144  {
145  if (RemoteFile::Exists(filename + "/VIDEO_TS"))
146  dvddir = true;
147  else if (RemoteFile::Exists(filename + "/BDMV"))
148  bddir = true;
149  }
150  }
151  else if (!StreamOnly && !mythurl)
152  {
153  if (QFile::exists(filename + "/VIDEO_TS"))
154  dvddir = true;
155  else if (QFile::exists(filename + "/BDMV"))
156  bddir = true;
157  }
158 
159  if (!StreamOnly && (dvdurl || dvddir))
160  {
161  if (filename.startsWith("dvd:")) // URI "dvd:" + path
162  filename.remove(0,4); // e.g. "dvd:/dev/dvd"
163 
164  if (!(mythurl || QFile::exists(filename)))
165  filename = "/dev/dvd";
166  LOG(VB_PLAYBACK, LOG_INFO, "Trying DVD at " + filename);
167  return new MythDVDBuffer(filename);
168  }
169 
170  if (!StreamOnly && (bdurl || bddir))
171  {
172  if (filename.startsWith("bd:")) // URI "bd:" + path
173  filename.remove(0,3); // e.g. "bd:/videos/ET"
174 
175  if (!(mythurl || QFile::exists(filename)))
176  filename = "/dev/dvd";
177  LOG(VB_PLAYBACK, LOG_INFO, "Trying BD at " + filename);
178  return new MythBDBuffer(filename);
179  }
180 
181  if (!mythurl && imgext && filename.startsWith("dvd:"))
182  {
183  LOG(VB_PLAYBACK, LOG_INFO, "DVD image at " + filename);
184  return new MythDVDStream(filename);
185  }
186 
187  if (!mythurl && lower.endsWith(".vob") && filename.contains("/VIDEO_TS/"))
188  {
189  LOG(VB_PLAYBACK, LOG_INFO, "DVD VOB at " + filename);
190  auto *dvdstream = new MythDVDStream(filename);
191  if (dvdstream && dvdstream->IsOpen())
192  return dvdstream;
193  delete dvdstream;
194  }
195 
196  return new MythFileBuffer(filename, Write, UseReadAhead, Timeout);
197 }
198 
200  : MThread("RingBuffer"),
201  m_type(Type)
202 {
203 }
204 
206 {
207  return m_type;
208 }
209 
210 #undef NDEBUG
211 #include <cassert>
212 
221 {
222  assert(!isRunning());
223  wait();
224 
225  delete [] m_readAheadBuffer;
226  m_readAheadBuffer = nullptr;
227 
228  if (m_tfw)
229  {
230  m_tfw->Flush();
231  delete m_tfw;
232  m_tfw = nullptr;
233  }
234 }
235 
239 void MythMediaBuffer::Reset(bool Full, bool ToAdjust, bool ResetInternal)
240 {
241  LOG(VB_FILE, LOG_INFO, LOC + QString("Reset(%1,%2,%3)")
242  .arg(Full).arg(ToAdjust).arg(ResetInternal));
243 
244  m_rwLock.lockForWrite();
245  m_posLock.lockForWrite();
246 
247  m_numFailures = 0;
248  m_commsError = false;
249  m_setSwitchToNext = false;
250 
251  m_writePos = 0;
252  m_readPos = (ToAdjust) ? (m_readPos - m_readAdjust) : 0;
253 
254  if (m_readPos != 0)
255  {
256  LOG(VB_GENERAL, LOG_ERR, LOC +
257  QString("MythMediaBuffer::Reset() nonzero readpos. toAdjust: %1 "
258  "readpos: %2 readAdjust: %3")
259  .arg(ToAdjust).arg(m_readPos).arg(m_readAdjust));
260  }
261 
262  m_readAdjust = 0;
263  m_readPos = (m_readPos < 0) ? 0 : m_readPos;
264 
265  if (Full)
267 
268  if (ResetInternal)
270 
271  m_generalWait.wakeAll();
272  m_posLock.unlock();
273  m_rwLock.unlock();
274 }
275 
281 {
282  LOG(VB_FILE, LOG_INFO, LOC + QString("UpdateRawBitrate(%1Kb)").arg(RawBitrate));
283 
284  // an audio only stream could be as low as 64Kb (DVB radio) and
285  // an MHEG only stream is likely to be reported as 0Kb
286  if (RawBitrate < 64)
287  {
288  LOG(VB_FILE, LOG_INFO, LOC + QString("Bitrate too low - setting to 64Kb"));
289  RawBitrate = 64;
290  }
291  else if (RawBitrate > 100000)
292  {
293  LOG(VB_FILE, LOG_INFO, LOC + QString("Bitrate too high - setting to 100Mb"));
294  RawBitrate = 100000;
295  }
296 
297  m_rwLock.lockForWrite();
298  m_rawBitrate = RawBitrate;
300  m_bitrateInitialized = true;
301  m_rwLock.unlock();
302 }
303 
308 void MythMediaBuffer::UpdatePlaySpeed(float PlaySpeed)
309 {
310  m_rwLock.lockForWrite();
311  m_playSpeed = PlaySpeed;
313  m_rwLock.unlock();
314 }
315 
317 {
318  m_bitrateMonitorEnabled = Enable;
319 }
320 
322 {
323  m_waitForWrite = true;
324 }
325 
331 void MythMediaBuffer::SetBufferSizeFactors(bool EstBitrate, bool Matroska)
332 {
333  m_rwLock.lockForWrite();
334  m_unknownBitrate = EstBitrate;
335  m_fileIsMatroska = Matroska;
336  m_rwLock.unlock();
338 }
339 
348 {
349  uint estbitrate = 0;
350 
351  m_readsAllowed = false;
352  m_readsDesired = false;
353 
354  // loop without sleeping if the buffered data is less than this
355  m_fillThreshold = 7 * m_bufferSize / 8;
356 
357  const uint KB2 = 2*1024;
358  const uint KB4 = 4*1024;
359  const uint KB8 = 8*1024;
360  const uint KB16 = 16*1024;
361  const uint KB32 = 32*1024;
362  const uint KB64 = 64*1024;
363  const uint KB128 = 128*1024;
364  const uint KB256 = 256*1024;
365  const uint KB512 = 512*1024;
366 
367  estbitrate = static_cast<uint>(std::max(abs(m_rawBitrate * m_playSpeed), 0.5F * m_rawBitrate));
368  estbitrate = std::min(m_rawBitrate * 3, estbitrate);
369  int const rbs = (estbitrate > 18000) ? KB512 :
370  (estbitrate > 9000) ? KB256 :
371  (estbitrate > 5000) ? KB128 :
372  (estbitrate > 2500) ? KB64 :
373  (estbitrate > 1250) ? KB32 :
374  (estbitrate >= 500) ? KB16 :
375  (estbitrate > 250) ? KB8 :
376  (estbitrate > 125) ? KB4 : KB2;
377  if (rbs < DEFAULT_CHUNK_SIZE)
378  m_readBlockSize = rbs;
379  else
380  m_readBlockSize = m_bitrateInitialized ? std::max(rbs, m_readBlockSize) : rbs;
381 
382  // minimum seconds of buffering before allowing read
383  float secs_min = 0.3F;
384  // set the minimum buffering before allowing ffmpeg read
385  m_fillMin = static_cast<int>((estbitrate * 1000 * secs_min) * 0.125F);
386  // make this a multiple of ffmpeg block size..
388  {
389  if (m_lowBuffers)
390  LOG(VB_GENERAL, LOG_INFO, LOC + "Buffering optimisations disabled.");
391  m_lowBuffers = false;
393  m_fillMin = std::min(m_fillMin, static_cast<int>(m_bufferSize / 2));
394  }
395  else
396  {
397  m_lowBuffers = true;
398  LOG(VB_GENERAL, LOG_WARNING, "Enabling buffering optimisations for low bitrate stream.");
399  }
400 
401  LOG(VB_FILE, LOG_INFO, LOC +
402  QString("CalcReadAheadThresh(%1 Kb)\n\t\t\t -> "
403  "threshold(%2 KB) min read(%3 KB) blk size(%4 KB)")
404  .arg(estbitrate).arg(m_fillThreshold/1024)
405  .arg(m_fillMin/1024).arg(m_readBlockSize/1024));
406 }
407 
408 bool MythMediaBuffer::IsNearEnd(double /*Framerate*/, uint Frames) const
409 {
410  QReadLocker lock(&m_rwLock);
411 
412  // file is still being read, so can't be finished
413  if (!m_ateof && !m_setSwitchToNext)
414  return false;
415 
416  m_posLock.lockForRead();
417  long long readpos = m_readPos;
418  long long size = m_internalReadPos - m_readPos;
419  m_posLock.unlock();
420 
421  // telecom kilobytes (i.e. 1000 per k not 1024)
422  uint tmp = static_cast<uint>(std::max(abs(m_rawBitrate * m_playSpeed), 0.5F * m_rawBitrate));
423  uint kbitspersec = std::min(m_rawBitrate * 3, tmp);
424  if (kbitspersec == 0)
425  return false;
426 
427  double readahead_time = size / (kbitspersec * (1000.0 / 8.0));
428 
429  bool near_end = readahead_time <= 1.5;
430  LOG(VB_PLAYBACK, LOG_INFO, LOC + "IsReallyNearEnd()" +
431  QString(" br(%1KB)").arg(kbitspersec/8) +
432  QString(" sz(%1KB)").arg(size / 1000LL) +
433  QString(" vfl(%1)").arg(Frames) +
434  QString(" time(%1)").arg(readahead_time) +
435  QString(" rawbitrate(%1)").arg(m_rawBitrate) +
436  QString(" avail(%1)").arg(size) +
437  QString(" internal_size(%1)").arg(m_internalReadPos) +
438  QString(" readposition(%1)").arg(readpos) +
439  QString(" stopreads(%1)").arg(m_stopReads) +
440  QString(" paused(%1)").arg(m_paused) +
441  QString(" ne:%1").arg(near_end));
442  return near_end;
443 }
444 
448 {
449  m_rbrLock.lockForRead();
450  m_rbwLock.lockForRead();
451  int ret = ((m_rbwPos >= m_rbrPos) ? m_rbrPos + static_cast<int>(m_bufferSize) : m_rbrPos) - m_rbwPos - 1;
452  m_rbwLock.unlock();
453  m_rbrLock.unlock();
454  return ret;
455 }
456 
459 {
460  QReadLocker lock(&m_rwLock);
461  return ReadBufAvail();
462 }
463 
464 long long MythMediaBuffer::GetRealFileSize(void) const
465 {
466  {
467  QReadLocker lock(&m_rwLock);
468  if (m_readInternalMode)
469  return ReadBufAvail();
470  }
471 
472  return GetRealFileSizeInternal();
473 }
474 
475 long long MythMediaBuffer::Seek(long long Position, int Whence, bool HasLock)
476 {
477  LOG(VB_FILE, LOG_INFO, LOC + QString("Seek: Position:%1 Type: %2 Locked: %3)")
478  .arg(Position)
479  .arg((SEEK_SET == Whence) ? "SEEK_SET" : ((SEEK_CUR == Whence) ? "SEEK_CUR" : "SEEK_END"))
480  .arg(HasLock?"locked":"unlocked"));
481 
482  if (!HasLock)
483  m_rwLock.lockForWrite();
484 
485  long long ret = 0;
486 
487  if (m_readInternalMode)
488  {
489  m_posLock.lockForWrite();
490  // only valid for SEEK_SET & SEEK_CUR
491  switch (Whence)
492  {
493  case SEEK_SET:
494  m_readPos = Position;
495  break;
496  case SEEK_CUR:
497  m_readPos += Position;
498  break;
499  case SEEK_END:
500  m_readPos = ReadBufAvail() - Position;
501  break;
502  }
503  m_readOffset = static_cast<int>(m_readPos);
504  m_posLock.unlock();
505  ret = m_readPos;
506  }
507  else
508  {
509  ret = SeekInternal(Position, Whence);
510  }
511 
512  m_generalWait.wakeAll();
513 
514  if (!HasLock)
515  m_rwLock.unlock();
516  return ret;
517 }
518 
520 {
521  QWriteLocker lock(&m_rwLock);
522  bool old = m_readInternalMode;
523 
524  if (Mode == old)
525  return old;
526 
527  m_readInternalMode = Mode;
528 
529  if (!Mode)
530  {
531  // adjust real read position in ringbuffer
532  m_rbrLock.lockForWrite();
533  m_rbrPos = (m_rbrPos + m_readOffset) % static_cast<int>(m_bufferSize);
534  m_generalWait.wakeAll();
535  m_rbrLock.unlock();
536  // reset the read offset as we are exiting the internal read mode
537  m_readOffset = 0;
538  }
539 
540  LOG(VB_FILE, LOG_DEBUG, LOC + QString("SetReadInternalMode: %1").arg(Mode ? "on" : "off"));
541  return old;
542 }
543 
545 {
546  return m_readInternalMode;
547 }
548 
552 {
553  m_rbrLock.lockForRead();
554  m_rbwLock.lockForRead();
555  int ret = (m_rbwPos >= m_rbrPos) ? m_rbwPos - m_rbrPos : static_cast<int>(m_bufferSize) - m_rbrPos + m_rbwPos;
556  m_rbwLock.unlock();
557  m_rbrLock.unlock();
558  return ret;
559 }
560 
571 void MythMediaBuffer::ResetReadAhead(long long NewInternal)
572 {
573  LOG(VB_FILE, LOG_INFO, LOC + QString("ResetReadAhead(internalreadpos = %1->%2)")
574  .arg(m_internalReadPos).arg(NewInternal));
575 
576  m_readInternalMode = false;
577  m_readOffset = 0;
578 
579  m_rbrLock.lockForWrite();
580  m_rbwLock.lockForWrite();
581 
583 
584  m_rbrPos = 0;
585  m_rbwPos = 0;
586  m_internalReadPos = NewInternal;
587  m_ateof = false;
588  m_readsAllowed = false;
589  m_readsDesired = false;
590  m_recentSeek = true;
591  m_setSwitchToNext = false;
592 
593  m_generalWait.wakeAll();
594 
595  m_rbwLock.unlock();
596  m_rbrLock.unlock();
597 }
598 
614 {
615  bool dostart = true;
616 
617  m_rwLock.lockForWrite();
618  if (!m_startReadAhead)
619  {
620  dostart = false;
621  }
622  else if (m_writeMode)
623  {
624  LOG(VB_GENERAL, LOG_WARNING, LOC + "Not starting read ahead thread - write only RingBuffer");
625  dostart = false;
626  }
627  else if (m_readAheadRunning)
628  {
629  LOG(VB_GENERAL, LOG_WARNING, LOC + "Not starting read ahead thread - already running");
630  dostart = false;
631  }
632 
633  if (!dostart)
634  {
635  m_rwLock.unlock();
636  return;
637  }
638 
639  StartReads();
640  MThread::start();
642  m_generalWait.wait(&m_rwLock);
643  m_rwLock.unlock();
644 }
645 
650 {
651  while (isRunning())
652  {
653  m_rwLock.lockForWrite();
654  m_readAheadRunning = false;
655  StopReads();
656  m_generalWait.wakeAll();
657  m_rwLock.unlock();
658  MThread::wait(5000);
659  }
660 }
661 
666 {
667  LOG(VB_FILE, LOG_INFO, LOC + "StopReads()");
668  m_stopReads = true;
669  m_generalWait.wakeAll();
670 }
671 
676 {
677  LOG(VB_FILE, LOG_INFO, LOC + "StartReads()");
678  m_stopReads = false;
679  m_generalWait.wakeAll();
680 }
681 
687 {
688  LOG(VB_FILE, LOG_INFO, LOC + "Pausing read ahead thread");
689  StopReads();
690 
691  m_rwLock.lockForWrite();
692  m_requestPause = true;
693  m_rwLock.unlock();
694 }
695 
701 {
702  LOG(VB_FILE, LOG_INFO, LOC + "Unpausing readahead thread");
703  StartReads();
704 
705  m_rwLock.lockForWrite();
706  m_requestPause = false;
707  m_generalWait.wakeAll();
708  m_rwLock.unlock();
709 }
710 
715 {
716  MythTimer t;
717  t.start();
718 
719  m_rwLock.lockForRead();
721  {
722  m_generalWait.wait(&m_rwLock, 1000);
723  if (m_readAheadRunning && !m_paused && m_requestPause && t.elapsed() > 1000)
724  LOG(VB_GENERAL, LOG_WARNING, LOC + QString("Waited %1 ms for ringbuffer pause").arg(t.elapsed()));
725  }
726  m_rwLock.unlock();
727 }
728 
730 {
731  const uint timeout = 500; // ms
732 
733  if (m_requestPause)
734  {
735  if (!m_paused)
736  {
737  m_rwLock.unlock();
738  m_rwLock.lockForWrite();
739 
740  if (m_requestPause)
741  {
742  m_paused = true;
743  m_generalWait.wakeAll();
744  }
745 
746  m_rwLock.unlock();
747  m_rwLock.lockForRead();
748  }
749 
752  }
753 
754  if (!m_requestPause && m_paused)
755  {
756  m_rwLock.unlock();
757  m_rwLock.lockForWrite();
758 
759  if (!m_requestPause)
760  {
761  m_paused = false;
762  m_generalWait.wakeAll();
763  }
764 
765  m_rwLock.unlock();
766  m_rwLock.lockForRead();
767  }
768 
769  return m_requestPause || m_paused;
770 }
771 
773 {
774  m_rwLock.lockForWrite();
775  m_posLock.lockForWrite();
776 
777  uint oldsize = m_bufferSize;
778  uint newsize = BUFFER_SIZE_MINIMUM;
779  if (m_remotefile)
780  {
781  newsize *= BUFFER_FACTOR_NETWORK;
782  if (m_fileIsMatroska)
783  newsize *= BUFFER_FACTOR_MATROSKA;
784  if (m_unknownBitrate)
785  newsize *= BUFFER_FACTOR_BITRATE;
786  }
787 
788  // N.B. Don't try and make it smaller - bad things happen...
789  if (m_readAheadBuffer && (oldsize >= newsize))
790  {
791  m_posLock.unlock();
792  m_rwLock.unlock();
793  return;
794  }
795 
796  m_bufferSize = newsize;
797  if (m_readAheadBuffer)
798  {
799  char* newbuffer = new char[m_bufferSize + 1024];
800  memcpy(newbuffer, m_readAheadBuffer + m_rbwPos, oldsize - static_cast<uint>(m_rbwPos));
801  memcpy(newbuffer + (oldsize - static_cast<uint>(m_rbwPos)), m_readAheadBuffer, static_cast<uint>(m_rbwPos));
802  delete [] m_readAheadBuffer;
803  m_readAheadBuffer = newbuffer;
805  (m_rbrPos + static_cast<int>(oldsize) - m_rbwPos);
806  m_rbwPos = static_cast<int>(oldsize);
807  }
808  else
809  {
810  m_readAheadBuffer = new char[m_bufferSize + 1024];
811  }
813  m_posLock.unlock();
814  m_rwLock.unlock();
815 
816  LOG(VB_FILE, LOG_INFO, LOC + QString("Created readAheadBuffer: %1Mb")
817  .arg(newsize >> 20));
818 }
819 
821 {
822  RunProlog();
823 
824  // These variables are used to adjust the read block size
825  struct timeval lastread {};
826  struct timeval now {};
827  long readTimeAvg = 300;
828  bool ignoreForReadTiming = true;
829  int eofreads = 0;
830 
831  gettimeofday(&lastread, nullptr); // this is just to keep gcc happy
832 
834  m_rwLock.lockForWrite();
835  m_posLock.lockForWrite();
836  m_requestPause = false;
837  ResetReadAhead(0);
838  m_readAheadRunning = true;
839  m_reallyRunning = true;
840  m_generalWait.wakeAll();
841  m_posLock.unlock();
842  m_rwLock.unlock();
843 
844  // NOTE: this must loop at some point hold only
845  // a read lock on rwlock, so that other functions
846  // such as reset and seek can take priority.
847 
848  m_rwLock.lockForRead();
849 
850  LOG(VB_FILE, LOG_INFO, LOC + QString("Initial readblocksize %1K fillMin %2K")
851  .arg(m_readBlockSize/1024).arg(m_fillMin/1024));
852 
853  while (m_readAheadRunning)
854  {
855  m_rwLock.unlock();
856  bool isopened = IsOpen();
857  m_rwLock.lockForRead();
858 
859  if (!isopened)
860  {
861  LOG(VB_FILE, LOG_WARNING, LOC + QString("File not opened, terminating readahead thread"));
862  m_posLock.lockForWrite();
863  m_readAheadRunning = false;
864  m_generalWait.wakeAll();
865  m_posLock.unlock();
866  break;
867  }
868  if (PauseAndWait())
869  {
870  ignoreForReadTiming = true;
871  LOG(VB_FILE, LOG_DEBUG, LOC + "run: PauseAndWait Not reading continuing");
872  continue;
873  }
874 
875  long long totfree = ReadBufFree();
876 
877  const uint KB32 = 32*1024;
878  const int KB512 = 512*1024;
879  // These are conditions where we don't want to go through
880  // the loop if they are true.
881  if (((totfree < KB32) && m_readsAllowed) ||
883  {
884  ignoreForReadTiming |= (m_ignoreReadPos >= 0) || m_commsError || m_stopReads;
885  m_generalWait.wait(&m_rwLock, (m_stopReads) ? 50 : 1000);
886  LOG(VB_FILE, LOG_DEBUG, LOC +
887  QString("run: Not reading continuing: totfree(%1) "
888  "readsallowed(%2) ignorereadpos(%3) commserror(%4) "
889  "stopreads(%5)")
892  continue;
893  }
894 
895  // These are conditions where we want to sleep to allow
896  // other threads to do stuff.
898  {
899  ignoreForReadTiming = true;
900  m_generalWait.wait(&m_rwLock, 1000);
901  totfree = ReadBufFree();
902  }
903 
904  int readResult = -1;
905  if (totfree >= KB32 && !m_commsError && !m_ateof && !m_setSwitchToNext)
906  {
907  // limit the read size
908  if (m_readBlockSize > totfree)
909  totfree = (totfree / KB32) * KB32; // must be multiple of 32KB
910  else
911  totfree = m_readBlockSize;
912 
913  // adapt blocksize
914  gettimeofday(&now, nullptr);
915  if (!ignoreForReadTiming)
916  {
917  long readinterval = (now.tv_sec - lastread.tv_sec ) * 1000 +
918  (now.tv_usec - lastread.tv_usec) / 1000;
919  readTimeAvg = (readTimeAvg * 9 + readinterval) / 10;
920 
921  if (readTimeAvg < 150 &&
922  static_cast<uint>(m_readBlockSize) < (BUFFER_SIZE_MINIMUM >>2) &&
923  m_readBlockSize >= DEFAULT_CHUNK_SIZE /* low_buffers */ &&
924  m_readBlockSize <= KB512)
925  {
926  int old_block_size = m_readBlockSize;
929  if (m_readBlockSize > KB512)
930  m_readBlockSize = KB512;
931  LOG(VB_FILE, LOG_INFO, LOC + QString("Avg read interval was %1 msec. "
932  "%2K -> %3K block size")
933  .arg(readTimeAvg).arg(old_block_size/1024).arg(m_readBlockSize/1024));
934  readTimeAvg = 225;
935  }
936  else if (readTimeAvg > 300 && m_readBlockSize > DEFAULT_CHUNK_SIZE)
937  {
939  LOG(VB_FILE, LOG_INFO, LOC +
940  QString("Avg read interval was %1 msec. %2K -> %3K block size")
941  .arg(readTimeAvg)
943  .arg(m_readBlockSize/1024));
944  readTimeAvg = 225;
945  }
946  }
947  lastread = now;
948 
949  m_rbwLock.lockForRead();
950  if (m_rbwPos + totfree > m_bufferSize)
951  {
952  totfree = m_bufferSize - static_cast<uint>(m_rbwPos);
953  LOG(VB_FILE, LOG_DEBUG, LOC + "Shrinking read, near end of buffer");
954  }
955 
956  if (m_internalReadPos == 0)
957  {
958  totfree = std::max(m_fillMin, m_readBlockSize);
959  LOG(VB_FILE, LOG_DEBUG, LOC + "Reading enough data to start playback");
960  }
961 
962  LOG(VB_FILE, LOG_DEBUG, LOC + QString("safe_read(...@%1, %2) -- begin")
963  .arg(m_rbwPos).arg(totfree));
964 
965  MythTimer sr_timer;
966  sr_timer.start();
967 
968  int rbwposcopy = m_rbwPos;
969 
970  // MythFileBuffer::SafeRead(RemoteFile*...) acquires poslock;
971  // so we need to unlock this here to preserve locking order.
972  m_rbwLock.unlock();
973 
974  readResult = SafeRead(m_readAheadBuffer + rbwposcopy, static_cast<uint>(totfree));
975 
976  int sr_elapsed = sr_timer.elapsed();
977  uint64_t bps = !sr_elapsed ? 1000000001 :
978  static_cast<uint64_t>((readResult * 8000.0) / static_cast<double>(sr_elapsed));
979  LOG(VB_FILE, LOG_DEBUG, LOC +
980  QString("safe_read(...@%1, %2) -> %3, took %4 ms %5 avg %6 ms")
981  .arg(rbwposcopy).arg(totfree).arg(readResult).arg(sr_elapsed)
982  .arg(QString("(%1Mbps)").arg(static_cast<double>(bps) / 1000000.0))
983  .arg(readTimeAvg));
984  UpdateStorageRate(bps);
985 
986  if (readResult >= 0)
987  {
988  m_posLock.lockForWrite();
989  m_rbwLock.lockForWrite();
990 
991  if (rbwposcopy == m_rbwPos)
992  {
993  m_internalReadPos += readResult;
994  m_rbwPos = (m_rbwPos + readResult) % static_cast<int>(m_bufferSize);
995  LOG(VB_FILE, LOG_DEBUG, LOC + QString("rbwpos += %1K requested %2K in read")
996  .arg(readResult/1024,3).arg(totfree/1024,3));
997  }
998  m_numFailures = 0;
999 
1000  m_rbwLock.unlock();
1001  m_posLock.unlock();
1002 
1003  LOG(VB_FILE, LOG_DEBUG, LOC + QString("total read so far: %1 bytes")
1005  }
1006  }
1007  else
1008  {
1009  LOG(VB_FILE, LOG_DEBUG, LOC +
1010  QString("We are not reading anything (totfree: %1 commserror:%2 ateof:%3 setswitchtonext:%4")
1012  }
1013 
1014  int used = static_cast<int>(m_bufferSize) - ReadBufFree();
1015  bool readsWereAllowed = m_readsAllowed;
1016 
1017  ignoreForReadTiming = (totfree < m_readBlockSize) || (readResult < totfree);
1018 
1019  if ((0 == readResult) || (m_numFailures > 5) ||
1020  (m_readsAllowed != (used >= 1 || m_ateof || m_setSwitchToNext || m_commsError)) ||
1022  {
1023  // If readpos changes while the lock is released
1024  // we should not handle the 0 read_return now.
1025  long long oldreadposition = m_readPos;
1026 
1027  m_rwLock.unlock();
1028  m_rwLock.lockForWrite();
1029 
1030  m_commsError |= (m_numFailures > 5);
1031 
1034 
1035  if ((0 == readResult) && (oldreadposition == m_readPos))
1036  {
1037  eofreads++;
1038  if (eofreads >= 3 && m_readBlockSize >= KB512)
1039  {
1040  // not reading anything
1043  }
1044 
1045  if (m_liveTVChain)
1046  {
1048  {
1049  // we receive new livetv chain element event
1050  // before we receive file closed for writing event
1051  // so don't need to test if file is closed for writing
1052  m_liveTVChain->SwitchToNext(true);
1053  m_setSwitchToNext = true;
1054  }
1056  {
1057  LOG(VB_FILE, LOG_DEBUG, LOC +
1058  QString("EOF encountered, but %1 still being written to")
1059  .arg(m_filename));
1060  // We reached EOF, but file still open for writing and
1061  // no next program in livetvchain
1062  // wait a little bit (60ms same wait as typical safe_read)
1063  m_generalWait.wait(&m_rwLock, 60);
1064  }
1065  }
1067  {
1068  LOG(VB_FILE, LOG_DEBUG, LOC +
1069  QString("EOF encountered, but %1 still being written to")
1070  .arg(m_filename));
1071  // We reached EOF, but file still open for writing,
1072  // typically active in-progress recording
1073  // wait a little bit (60ms same wait as typical safe_read)
1074  m_generalWait.wait(&m_rwLock, 60);
1075  m_beingWritten = true;
1076  }
1077  else
1078  {
1080  {
1081  LOG(VB_FILE, LOG_DEBUG, LOC + "Waiting for file to grow large enough to process.");
1082  m_generalWait.wait(&m_rwLock, 300);
1083  }
1084  else
1085  {
1086  LOG(VB_FILE, LOG_DEBUG, LOC + "setting ateof (readResult == 0)");
1087  m_ateof = true;
1088  }
1089  }
1090  }
1091 
1092  m_rwLock.unlock();
1093  m_rwLock.lockForRead();
1094  used = static_cast<int>(m_bufferSize) - ReadBufFree();
1095  }
1096  else
1097  {
1098  eofreads = 0;
1099  }
1100 
1101  LOG(VB_FILE, LOG_DEBUG, LOC + "@ end of read ahead loop");
1102 
1104  (m_wantToRead <= used && m_wantToRead > 0))
1105  {
1106  // To give other threads a good chance to handle these
1107  // conditions, even if they are only requesting a read lock
1108  // like us, yield (currently implemented with short usleep).
1109  m_generalWait.wakeAll();
1110  m_rwLock.unlock();
1111  std::this_thread::sleep_for(std::chrono::milliseconds(5));
1112  m_rwLock.lockForRead();
1113  }
1114  else
1115  {
1116  // yield if we have nothing to do...
1117  if (!m_requestPause && readsWereAllowed &&
1118  (used >= m_fillThreshold || m_ateof || m_setSwitchToNext))
1119  {
1120  m_generalWait.wait(&m_rwLock, 50);
1121  }
1122  else if (m_readsAllowed)
1123  {
1124  // if reads are allowed release the lock and yield so the
1125  // reader gets a chance to read before the buffer is full.
1126  m_generalWait.wakeAll();
1127  m_rwLock.unlock();
1128  std::this_thread::sleep_for(std::chrono::milliseconds(5));
1129  m_rwLock.lockForRead();
1130  }
1131  }
1132  }
1133 
1134  m_rwLock.unlock();
1135 
1136  m_rwLock.lockForWrite();
1137  m_rbrLock.lockForWrite();
1138  m_rbwLock.lockForWrite();
1139 
1140  delete [] m_readAheadBuffer;
1141 
1142  m_readAheadBuffer = nullptr;
1143  m_rbrPos = 0;
1144  m_rbwPos = 0;
1145  m_reallyRunning = false;
1146  m_readsAllowed = false;
1147  m_readsDesired = false;
1148 
1149  m_rbwLock.unlock();
1150  m_rbrLock.unlock();
1151  m_rwLock.unlock();
1152 
1153  LOG(VB_FILE, LOG_INFO, LOC + QString("Exiting readahead thread"));
1154 
1155  RunEpilog();
1156 }
1157 
1159 {
1160  m_rwLock.lockForWrite();
1161  m_posLock.lockForRead();
1163  long long readadjust = m_readAdjust;
1164  m_posLock.unlock();
1165  m_rwLock.unlock();
1166  return readadjust;
1167 }
1168 
1170 int MythMediaBuffer::Peek(void *Buffer, int Count)
1171 {
1172  int result = ReadPriv(Buffer, Count, true);
1173  if (result != Count)
1174  {
1175  LOG(VB_GENERAL, LOG_WARNING, LOC + QString("Peek requested %1 bytes but only have %2")
1176  .arg(Count).arg(result));
1177  }
1178  return result;
1179 }
1180 
1181 int MythMediaBuffer::Peek(std::vector<char>& Buffer)
1182 {
1183  return Peek(Buffer.data(), Buffer.size());
1184 };
1185 
1187 {
1188  // Wait up to 30000 ms for reads allowed (or readsdesired if post seek/open)
1190  m_recentSeek = false;
1191  int timeoutms = 30000;
1192  int count = 0;
1193  MythTimer timer;
1194  timer.start();
1195 
1196  while ((timer.elapsed() < timeoutms) && !check && !m_stopReads &&
1198  {
1199  m_generalWait.wait(&m_rwLock, static_cast<unsigned long>(clamp(timeoutms - timer.elapsed(), 10, 100)));
1200  if (!check && timer.elapsed() > 1000 && (count % 100) == 0)
1201  LOG(VB_GENERAL, LOG_WARNING, LOC + "Taking too long to be allowed to read..");
1202  count++;
1203  }
1204 
1205  if (timer.elapsed() >= timeoutms)
1206  {
1207  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Took more than %1 seconds to be allowed to read, aborting.")
1208  .arg(timeoutms / 1000));
1209  return false;
1210  }
1211  return check;
1212 }
1213 
1214 int MythMediaBuffer::WaitForAvail(int Count, int Timeout)
1215 {
1216  int available = ReadBufAvail();
1217  if (available >= Count)
1218  return available;
1219 
1220  Count = (m_ateof && available < Count) ? available : Count;
1221 
1222  if (m_liveTVChain && m_setSwitchToNext && (available < Count))
1223  return available;
1224 
1225  // Make sure that if the read ahead thread is sleeping and
1226  // it should be reading that we start reading right away.
1227  if ((available < Count) && !m_stopReads && !m_requestPause && !m_commsError && m_readAheadRunning)
1228  m_generalWait.wakeAll();
1229 
1230  MythTimer timer;
1231  timer.start();
1232  while ((available < Count) && !m_stopReads && !m_requestPause && !m_commsError && m_readAheadRunning)
1233  {
1234  m_wantToRead = Count;
1235  m_generalWait.wait(&m_rwLock, static_cast<unsigned long>(clamp(Timeout - timer.elapsed(), 10, 250)));
1236  available = ReadBufAvail();
1237  if (m_ateof)
1238  break;
1239  if (m_lowBuffers && available >= m_fillMin)
1240  break;
1241  if (timer.elapsed() > Timeout)
1242  break;
1243  }
1244 
1245  m_wantToRead = 0;
1246  return available;
1247 }
1248 
1249 int MythMediaBuffer::ReadDirect(void *Buffer, int Count, bool Peek)
1250 {
1251  long long oldposition = 0;
1252  if (Peek)
1253  {
1254  m_posLock.lockForRead();
1255  oldposition = (m_ignoreReadPos >= 0) ? m_ignoreReadPos : m_readPos;
1256  m_posLock.unlock();
1257  }
1258 
1259  MythTimer timer;
1260  timer.start();
1261  int result = SafeRead(Buffer, static_cast<uint>(Count));
1262  int elapsed = timer.elapsed();
1263  uint64_t bps = !elapsed ? 1000000001 : static_cast<uint64_t>((result * 8000.0) / static_cast<double>(elapsed));
1264  UpdateStorageRate(bps);
1265 
1266  m_posLock.lockForWrite();
1267  if (m_ignoreReadPos >= 0 && result > 0)
1268  {
1269  if (Peek)
1270  {
1271  // seek should always succeed since we were at this position
1272  long long cur_pos = -1;
1273  if (m_remotefile)
1274  cur_pos = m_remotefile->Seek(oldposition, SEEK_SET);
1275  else if (m_fd2 >= 0)
1276  cur_pos = lseek64(m_fd2, oldposition, SEEK_SET);
1277  if (cur_pos < 0)
1278  {
1279  LOG(VB_FILE, LOG_ERR, LOC + "Seek failed repositioning to previous position");
1280  }
1281  }
1282  else
1283  {
1284  m_ignoreReadPos += result;
1285  }
1286  m_posLock.unlock();
1287  return result;
1288  }
1289  m_posLock.unlock();
1290 
1291  if (Peek && (result > 0))
1292  {
1293  if ((IsDVD() || IsBD()) && oldposition != 0)
1294  {
1295  LOG(VB_GENERAL, LOG_ERR, LOC +
1296  "DVD and Blu-Ray do not support arbitrary "
1297  "peeks except when read-ahead is enabled."
1298  "\n\t\t\tWill seek to beginning of video.");
1299  oldposition = 0;
1300  }
1301 
1302  long long newposition = Seek(oldposition, SEEK_SET, true);
1303 
1304  if (newposition != oldposition)
1305  {
1306  LOG(VB_GENERAL, LOG_ERR, LOC +
1307  QString("Peek() Failed to return from new position %1 to old position %2, now "
1308  "at position %3")
1309  .arg(oldposition - result).arg(oldposition).arg(newposition));
1310  }
1311  }
1312 
1313  return result;
1314 }
1315 
1324 int MythMediaBuffer::ReadPriv(void *Buffer, int Count, bool Peek)
1325 {
1326  QString desc = QString("ReadPriv(..%1, %2)").arg(Count).arg(Peek ? "peek" : "normal");
1327  LOG(VB_FILE, LOG_DEBUG, LOC + desc + QString(" @%1 -- begin").arg(m_rbrPos));
1328 
1329  m_rwLock.lockForRead();
1330  if (m_writeMode)
1331  {
1332  LOG(VB_GENERAL, LOG_ERR, LOC + desc + ": Attempt to read from a write only file");
1333  errno = EBADF;
1334  m_rwLock.unlock();
1335  return -1;
1336  }
1337 
1339  {
1340  m_rwLock.unlock();
1341  m_rwLock.lockForWrite();
1342  // we need a write lock so the read-ahead thread
1343  // can't start mucking with the read position.
1344  // If the read ahead thread was started while we
1345  // didn't hold the lock, we proceed with a normal
1346  // read from the buffer, otherwise we read directly.
1348  {
1349  int result = ReadDirect(Buffer, Count, Peek);
1350  LOG(VB_FILE, LOG_DEBUG, LOC + desc + QString(": ReadDirect checksum %1")
1351  .arg(qChecksum(reinterpret_cast<char*>(Buffer), static_cast<uint>(Count))));
1352  m_rwLock.unlock();
1353  return result;
1354  }
1355  m_rwLock.unlock();
1356  m_rwLock.lockForRead();
1357  }
1358 
1359  if (!WaitForReadsAllowed())
1360  {
1361  LOG(VB_FILE, LOG_NOTICE, LOC + desc + ": !WaitForReadsAllowed()");
1362  m_rwLock.unlock();
1363  m_stopReads = true; // this needs to be outside the lock
1364  m_rwLock.lockForWrite();
1365  m_wantToRead = 0;
1366  m_rwLock.unlock();
1367  return 0;
1368  }
1369 
1370  int available = ReadBufAvail();
1372 
1373  // Wait up to 10000 ms for any data
1374  int timeout_ms = 10000;
1375  while (!m_readInternalMode && !m_ateof && (timer.elapsed() < timeout_ms) && m_readAheadRunning &&
1377  {
1378  available = WaitForAvail(Count, std::min(timeout_ms - timer.elapsed(), 100));
1379  if (m_liveTVChain && m_setSwitchToNext && available < Count)
1380  {
1381  LOG(VB_GENERAL, LOG_INFO, LOC + "Checking to see if there's a new livetv program to switch to..");
1383  break;
1384  }
1385  if (available > 0)
1386  break;
1387  }
1388  if (timer.elapsed() > 6000)
1389  {
1390  LOG(VB_GENERAL, LOG_WARNING, LOC + desc + QString(" -- waited %1 ms for avail(%2) > count(%3)")
1391  .arg(timer.elapsed()).arg(available).arg(Count));
1392  }
1393 
1394  if (m_readInternalMode)
1395  {
1396  LOG(VB_FILE, LOG_DEBUG, LOC + QString("ReadPriv: %1 bytes available, %2 left")
1397  .arg(available).arg(available-m_readOffset));
1398  }
1399  Count = std::min(available - m_readOffset, Count);
1400 
1401  if ((Count <= 0) && (m_ateof || m_readInternalMode))
1402  {
1403  // If we're at the end of file return 0 bytes
1404  m_rwLock.unlock();
1405  return Count;
1406  }
1407 
1408  if (Count <= 0)
1409  {
1410  // If we're not at the end of file but have no data
1411  // at this point time out and shutdown read ahead.
1412  LOG(VB_GENERAL, LOG_ERR, LOC + desc + QString(" -- timed out waiting for data (%1 ms)")
1413  .arg(timer.elapsed()));
1414 
1415  m_rwLock.unlock();
1416  m_stopReads = true; // this needs to be outside the lock
1417  m_rwLock.lockForWrite();
1418  m_ateof = true;
1419  m_wantToRead = 0;
1420  m_generalWait.wakeAll();
1421  m_rwLock.unlock();
1422  return Count;
1423  }
1424 
1425  if (Peek || m_readInternalMode)
1426  m_rbrLock.lockForRead();
1427  else
1428  m_rbrLock.lockForWrite();
1429 
1430  LOG(VB_FILE, LOG_DEBUG, LOC + desc + ": Copying data");
1431 
1432  int readposition = 0;
1433  if (m_rbrPos + m_readOffset > static_cast<int>(m_bufferSize))
1434  readposition = (m_rbrPos + m_readOffset) - static_cast<int>(m_bufferSize);
1435  else
1436  readposition = m_rbrPos + m_readOffset;
1437 
1438  if (readposition + Count > static_cast<int>(m_bufferSize))
1439  {
1440  int firstsize = static_cast<int>(m_bufferSize) - readposition;
1441  int secondsize = Count - firstsize;
1442 
1443  memcpy(Buffer, m_readAheadBuffer + readposition, static_cast<size_t>(firstsize));
1444  memcpy(reinterpret_cast<char*>(Buffer) + firstsize, m_readAheadBuffer, static_cast<size_t>(secondsize));
1445  }
1446  else
1447  {
1448  memcpy(Buffer, m_readAheadBuffer + readposition, static_cast<uint>(Count));
1449  }
1450  LOG(VB_FILE, LOG_DEBUG, LOC + desc + QString(": Checksum %1")
1451  .arg(qChecksum(reinterpret_cast<char*>(Buffer), static_cast<uint>(Count))));
1452 
1453  if (!Peek)
1454  {
1455  if (m_readInternalMode)
1456  {
1457  m_readOffset += Count;
1458  }
1459  else
1460  {
1461  m_rbrPos = (m_rbrPos + Count) % static_cast<int>(m_bufferSize);
1462  m_generalWait.wakeAll();
1463  }
1464  }
1465  m_rbrLock.unlock();
1466  m_rwLock.unlock();
1467 
1468  return Count;
1469 }
1470 
1479 int MythMediaBuffer::Read(void *Buffer, int Count)
1480 {
1481  int ret = ReadPriv(Buffer, Count, false);
1482  if (ret > 0)
1483  {
1484  m_posLock.lockForWrite();
1485  m_readPos += ret;
1486  m_posLock.unlock();
1487  UpdateDecoderRate(static_cast<uint64_t>(ret));
1488  }
1489 
1490  return ret;
1491 }
1492 
1493 QString MythMediaBuffer::BitrateToString(uint64_t Rate, bool Hz)
1494 {
1495  if (Rate < 1)
1496  return "-";
1497 
1498  if (Rate > 1000000000)
1499  return QObject::tr(">1Gbps");
1500 
1501  QString msg;
1502  auto bitrate = static_cast<double>(NAN);
1503  auto rate = static_cast<double>(Rate);
1504  int range = 0;
1505 
1506  if (Rate >= 1000000)
1507  {
1508  msg = Hz ? QObject::tr("%1MHz") : QObject::tr("%1Mbps");
1509  bitrate = rate / 1000000.0;
1510  range = Hz ? 3 : 1;
1511  }
1512  else if (Rate >= 1000)
1513  {
1514  msg = Hz ? QObject::tr("%1kHz") : QObject::tr("%1kbps");
1515  bitrate = rate / 1000.0;
1516  range = Hz ? 1 : 0;
1517  }
1518  else
1519  {
1520  msg = Hz ? QObject::tr("%1Hz") : QObject::tr("%1bps");
1521  bitrate = rate;
1522  }
1523  return msg.arg(bitrate, 0, 'f', range);
1524 }
1525 
1527 {
1529 }
1530 
1532 {
1534 }
1535 
1537 {
1539  return "N/A";
1540 
1541  int avail = (m_rbwPos >= m_rbrPos) ? m_rbwPos - m_rbrPos
1542  : static_cast<int>(m_bufferSize) - m_rbrPos + m_rbwPos;
1543  return QString("%1%").arg(lroundf((static_cast<float>(avail) / static_cast<float>(m_bufferSize) * 100.0F)));
1544 }
1545 
1547 {
1548  return m_bufferSize;
1549 }
1550 
1551 uint64_t MythMediaBuffer::UpdateDecoderRate(uint64_t Latest)
1552 {
1554  return 0;
1555 
1556  qint64 current = QDateTime::currentDateTime().toMSecsSinceEpoch();
1557  qint64 expire = current - 1000;
1558 
1559  m_decoderReadLock.lock();
1560  if (Latest)
1561  m_decoderReads.insert(current, Latest);
1562  uint64_t total = 0;
1563  QMutableMapIterator<qint64,uint64_t> it(m_decoderReads);
1564  while (it.hasNext())
1565  {
1566  it.next();
1567  if (it.key() < expire || it.key() > current)
1568  it.remove();
1569  else
1570  total += it.value();
1571  }
1572 
1573  int size = m_decoderReads.size();
1574  m_decoderReadLock.unlock();
1575 
1576  auto average = static_cast<uint64_t>(static_cast<double>(total) * 8.0);
1577  LOG(VB_FILE, LOG_INFO, LOC + QString("Decoder read speed: %1 %2")
1578  .arg(average).arg(size));
1579  return average;
1580 }
1581 
1582 uint64_t MythMediaBuffer::UpdateStorageRate(uint64_t Latest)
1583 {
1585  return 0;
1586 
1587  qint64 current = QDateTime::currentDateTime().toMSecsSinceEpoch();
1588  qint64 expire = current - 1000;
1589 
1590  m_storageReadLock.lock();
1591  if (Latest)
1592  m_storageReads.insert(current, Latest);
1593  uint64_t total = 0;
1594  QMutableMapIterator<qint64,uint64_t> it(m_storageReads);
1595  while (it.hasNext())
1596  {
1597  it.next();
1598  if (it.key() < expire || it.key() > current)
1599  it.remove();
1600  else
1601  total += it.value();
1602  }
1603 
1604  int size = m_storageReads.size();
1605  m_storageReadLock.unlock();
1606 
1607  uint64_t average = size ? static_cast<uint64_t>(static_cast<double>(total) / size) : 0;
1608  LOG(VB_FILE, LOG_INFO, LOC + QString("Average storage read speed: %1 (Reads %2")
1609  .arg(average).arg(m_storageReads.size()));
1610  return average;
1611 }
1612 
1617 int MythMediaBuffer::Write(const void *Buffer, uint Count)
1618 {
1619  m_rwLock.lockForRead();
1620  int result = -1;
1621 
1622  if (!m_writeMode)
1623  {
1624  LOG(VB_GENERAL, LOG_ERR, LOC + "Tried to write to a read only file.");
1625  m_rwLock.unlock();
1626  return result;
1627  }
1628 
1629  if (!m_tfw && !m_remotefile)
1630  {
1631  m_rwLock.unlock();
1632  return result;
1633  }
1634 
1635  if (m_tfw)
1636  result = m_tfw->Write(Buffer, Count);
1637  else
1638  result = m_remotefile->Write(Buffer, static_cast<int>(Count));
1639 
1640  if (result > 0)
1641  {
1642  m_posLock.lockForWrite();
1643  m_writePos += result;
1644  m_posLock.unlock();
1645  }
1646 
1647  m_rwLock.unlock();
1648  return result;
1649 }
1650 
1655 {
1656  m_rwLock.lockForRead();
1657  if (m_tfw)
1658  m_tfw->Sync();
1659  m_rwLock.unlock();
1660 }
1661 
1664 long long MythMediaBuffer::WriterSeek(long long Position, int Whence, bool HasLock)
1665 {
1666  long long result = -1;
1667 
1668  if (!HasLock)
1669  m_rwLock.lockForRead();
1670 
1671  m_posLock.lockForWrite();
1672 
1673  if (m_tfw)
1674  {
1675  result = m_tfw->Seek(Position, Whence);
1676  m_writePos = result;
1677  }
1678 
1679  m_posLock.unlock();
1680 
1681  if (!HasLock)
1682  m_rwLock.unlock();
1683 
1684  return result;
1685 }
1686 
1691 {
1692  m_rwLock.lockForRead();
1693  if (m_tfw)
1694  m_tfw->Flush();
1695  m_rwLock.unlock();
1696 }
1697 
1702 {
1703  QReadLocker lock(&m_rwLock);
1704  if (m_tfw)
1705  return m_tfw->SetBlocking(Lock);
1706  return false;
1707 }
1708 
1725 {
1726  LOG(VB_FILE, LOG_INFO, LOC + QString("SetOldFile: %1)").arg(Old));
1727  m_rwLock.lockForWrite();
1728  m_oldfile = Old;
1729  m_rwLock.unlock();
1730 }
1731 
1732 QString MythMediaBuffer::GetFilename(void) const
1733 {
1734  m_rwLock.lockForRead();
1735  QString tmp = m_filename;
1736  m_rwLock.unlock();
1737  return tmp;
1738 }
1739 
1741 {
1742  return m_safeFilename;
1743 }
1744 
1746 {
1747  m_rwLock.lockForRead();
1748  QString tmp = m_subtitleFilename;
1749  m_rwLock.unlock();
1750  return tmp;
1751 }
1752 
1754 {
1755  m_rwLock.lockForRead();
1756  QString tmp = m_lastError;
1757  m_rwLock.unlock();
1758  return tmp;
1759 }
1760 
1762 {
1763  return m_commsError;
1764 }
1765 
1767 {
1768  m_commsError = false;
1769 }
1770 
1772 {
1773  return m_stopReads;
1774 }
1775 
1780 {
1781  m_posLock.lockForRead();
1782  long long ret = m_writePos;
1783  m_posLock.unlock();
1784  return ret;
1785 }
1786 
1792 {
1793  m_rwLock.lockForRead();
1794  bool ret = (m_liveTVChain);
1795  m_rwLock.unlock();
1796  return ret;
1797 }
1798 
1804 {
1805  m_rwLock.lockForWrite();
1806  m_liveTVChain = Chain;
1807  m_rwLock.unlock();
1808 }
1809 
1812 {
1813  m_rwLock.lockForWrite();
1814  m_ignoreLiveEOF = Ignore;
1815  m_rwLock.unlock();
1816 }
1817 
1818 bool MythMediaBuffer::IsDisc(void) const
1819 {
1820  return IsDVD() || IsBD();
1821 }
1822 
1823 bool MythMediaBuffer::IsDVD(void) const
1824 {
1825  return m_type == kMythBufferDVD;
1826 }
1827 
1828 bool MythMediaBuffer::IsBD(void) const
1829 {
1830  return m_type == kMythBufferBD;
1831 }
1832 
1834 {
1835  return dynamic_cast<const MythDVDBuffer*>(this);
1836 }
1837 
1839 {
1840  return dynamic_cast<const MythBDBuffer*>(this);
1841 }
1842 
1844 {
1845  return dynamic_cast<MythDVDBuffer*>(this);
1846 }
1847 
1849 {
1850  return dynamic_cast<MythBDBuffer*>(this);
1851 }
1852 
1854 {
1855  static QMutex s_avnetworkLock(QMutex::Recursive);
1856  static bool s_avnetworkInitialised = false;
1857  QMutexLocker lock(&s_avnetworkLock);
1858  if (!s_avnetworkInitialised)
1859  {
1860  avformat_network_init();
1861  s_avnetworkInitialised = true;
1862  }
1863 }
mythdvdstream.h
MythMediaBuffer::BD
const MythBDBuffer * BD(void) const
Definition: mythmediabuffer.cpp:1838
BUFFER_SIZE_MINIMUM
#define BUFFER_SIZE_MINIMUM
Definition: mythmediabuffer.h:25
fileInfo
QFileInfo fileInfo(filename)
MythMediaBuffer::SafeRead
virtual int SafeRead(void *Buffer, uint Size)=0
ThreadedFileWriter::Seek
long long Seek(long long pos, int whence)
Seek to a position within stream; May be unsafe.
Definition: threadedfilewriter.cpp:297
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:288
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:103
MythMediaBuffer::m_tfw
ThreadedFileWriter * m_tfw
Definition: mythmediabuffer.h:186
MythMediaBuffer::SetBufferSizeFactors
void SetBufferSizeFactors(bool EstBitrate, bool Matroska)
Tells RingBuffer that the raw bitrate may be inaccurate and the underlying container is matroska,...
Definition: mythmediabuffer.cpp:331
MythMediaBuffer::PauseAndWait
bool PauseAndWait(void)
Definition: mythmediabuffer.cpp:729
ThreadedFileWriter::Sync
void Sync(void) const
Flush data written to the file descriptor to disk.
Definition: threadedfilewriter.cpp:355
MythMediaBuffer::m_rbrPos
int m_rbrPos
Definition: mythmediabuffer.h:170
MythMediaBuffer::m_readAdjust
long long m_readAdjust
Definition: mythmediabuffer.h:218
MythTimer
A QElapsedTimer based timer to replace use of QTime as a timer.
Definition: mythtimer.h:14
LiveTVChain::HasNext
bool HasNext(void) const
Definition: livetvchain.cpp:405
MythMediaBuffer::m_startReadAhead
bool m_startReadAhead
Definition: mythmediabuffer.h:194
HLSRingBuffer::TestForHTTPLiveStreaming
static bool TestForHTTPLiveStreaming(const QString &filename)
Definition: httplivestreambuffer.cpp:1718
MythMediaBuffer::Seek
long long Seek(long long Position, int Whence, bool HasLock=false)
Definition: mythmediabuffer.cpp:475
MythCDROM::kBluray
@ kBluray
Definition: mythcdrom.h:29
RemoteFile::Exists
static bool Exists(const QString &url, struct stat *fileinfo)
Definition: remotefile.cpp:461
MythMediaBuffer::StopReads
void StopReads(void)
Definition: mythmediabuffer.cpp:665
MythMediaBuffer::UpdatePlaySpeed
void UpdatePlaySpeed(float PlaySpeed)
Set the play speed, to allow RingBuffer adjust effective bitrate.
Definition: mythmediabuffer.cpp:308
MythMediaBuffer::m_commsError
bool m_commsError
Definition: mythmediabuffer.h:214
MythMediaBuffer::m_oldfile
bool m_oldfile
Definition: mythmediabuffer.h:215
MythMediaBuffer::Create
static MythMediaBuffer * Create(const QString &Filename, bool Write, bool UseReadAhead=true, int Timeout=kDefaultOpenTimeout, bool StreamOnly=false)
Creates a RingBuffer instance.
Definition: mythmediabuffer.cpp:100
MythMediaBuffer::EnableBitrateMonitor
void EnableBitrateMonitor(bool Enable)
Definition: mythmediabuffer.cpp:316
mythcdrom.h
kMythBufferDVD
@ kMythBufferDVD
Definition: mythmediabuffer.h:42
MythMediaBuffer::WriterSetBlocking
bool WriterSetBlocking(bool Lock=true)
Calls ThreadedFileWriter::SetBlocking(bool)
Definition: mythmediabuffer.cpp:1701
MythMediaBuffer::GetWritePosition
long long GetWritePosition(void) const
Returns how far into a ThreadedFileWriter file we have written.
Definition: mythmediabuffer.cpp:1779
MythMediaBuffer::m_storageReads
QMap< qint64, uint64_t > m_storageReads
Definition: mythmediabuffer.h:227
MythMediaBuffer::m_fd2
int m_fd2
Definition: mythmediabuffer.h:187
MythMediaBuffer::m_safeFilename
QString m_safeFilename
Definition: mythmediabuffer.h:180
MythMediaBuffer::GetDecoderRate
QString GetDecoderRate(void)
Definition: mythmediabuffer.cpp:1526
MythMediaBuffer::CalcReadAheadThresh
void CalcReadAheadThresh(void)
Calculates m_fillMin, m_fillThreshold, and m_readBlockSize from the estimated effective bitrate of th...
Definition: mythmediabuffer.cpp:347
mythdvdbuffer.h
MythMediaBuffer::m_type
MythBufferType m_type
Definition: mythmediabuffer.h:161
kMythBufferBD
@ kMythBufferBD
Definition: mythmediabuffer.h:43
arg
arg(title).arg(filename).arg(doDelete))
MythMediaBuffer::ReadDirect
int ReadDirect(void *Buffer, int Count, bool Peek)
Definition: mythmediabuffer.cpp:1249
MythMediaBuffer::Write
int Write(const void *Buffer, uint Count)
Writes buffer to ThreadedFileWriter::Write(const void*,uint)
Definition: mythmediabuffer.cpp:1617
MythMediaBuffer::m_readOffset
int m_readOffset
Definition: mythmediabuffer.h:219
ThreadedFileWriter::Flush
void Flush(void)
Allow DiskLoop() to flush buffer completely ignoring low watermark.
Definition: threadedfilewriter.cpp:318
MythMediaBuffer
Definition: mythmediabuffer.h:50
MythMediaBuffer::IsDVD
bool IsDVD(void) const
Definition: mythmediabuffer.cpp:1823
MythTimer::start
void start(void)
starts measuring elapsed time.
Definition: mythtimer.cpp:47
MythMediaBuffer::Unpause
void Unpause(void)
Unpauses the read-ahead thread.
Definition: mythmediabuffer.cpp:700
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
MythMediaBuffer::GetSafeFilename
QString GetSafeFilename(void)
Definition: mythmediabuffer.cpp:1740
MythMediaBuffer::GetReadBufAvail
int GetReadBufAvail(void) const
Returns number of bytes available for reading from buffer.
Definition: mythmediabuffer.cpp:458
MythMediaBuffer::m_lastError
QString m_lastError
Definition: mythmediabuffer.h:185
MythMediaBuffer::m_generalWait
QWaitCondition m_generalWait
Condition to signal that the read ahead thread is running.
Definition: mythmediabuffer.h:236
MythMediaBuffer::kDefaultOpenTimeout
static const int kDefaultOpenTimeout
Definition: mythmediabuffer.h:61
RemoteFile::Write
int Write(const void *data, int size)
Definition: remotefile.cpp:834
MythMediaBuffer::ReadBufFree
int ReadBufFree(void) const
Returns number of bytes available for reading into buffer.
Definition: mythmediabuffer.cpp:447
MythMediaBuffer::IsBD
bool IsBD(void) const
Definition: mythmediabuffer.cpp:1828
MythMediaBuffer::SetAdjustFilesize
long long SetAdjustFilesize(void)
Definition: mythmediabuffer.cpp:1158
MythBufferType
MythBufferType
Definition: mythmediabuffer.h:39
MythMediaBuffer::WaitForReadsAllowed
bool WaitForReadsAllowed(void)
Definition: mythmediabuffer.cpp:1186
BUFFER_FACTOR_BITRATE
#define BUFFER_FACTOR_BITRATE
Definition: mythmediabuffer.h:27
MythMediaBuffer::UpdateRawBitrate
void UpdateRawBitrate(uint RawBitrate)
Set the raw bit rate, to allow RingBuffer adjust effective bitrate.
Definition: mythmediabuffer.cpp:280
BUFFER_FACTOR_MATROSKA
#define BUFFER_FACTOR_MATROSKA
Definition: mythmediabuffer.h:28
LOC
#define LOC
Definition: mythmediabuffer.cpp:46
MythMediaBuffer::BitrateToString
static QString BitrateToString(uint64_t Rate, bool Hz=false)
Definition: mythmediabuffer.cpp:1493
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
MythMediaBuffer::m_paused
bool m_paused
Definition: mythmediabuffer.h:199
MythMediaBuffer::m_decoderReadLock
QMutex m_decoderReadLock
Definition: mythmediabuffer.h:224
MythMediaBuffer::m_readsAllowed
bool m_readsAllowed
Definition: mythmediabuffer.h:203
MythMediaBuffer::GetStopReads
bool GetStopReads(void) const
Definition: mythmediabuffer.cpp:1771
tmp
static guint32 * tmp
Definition: goom_core.cpp:31
MythMediaBuffer::GetBufferSize
uint GetBufferSize(void) const
Definition: mythmediabuffer.cpp:1546
MythMediaBuffer::m_rawBitrate
uint m_rawBitrate
Definition: mythmediabuffer.h:207
MythMediaBuffer::ReadPriv
int ReadPriv(void *Buffer, int Count, bool Peek)
When possible reads from the read-ahead buffer, otherwise reads directly from the device.
Definition: mythmediabuffer.cpp:1324
MythMediaBuffer::m_liveTVChain
LiveTVChain * m_liveTVChain
Definition: mythmediabuffer.h:216
MythCoreContext::IsRegisteredFileForWrite
bool IsRegisteredFileForWrite(const QString &file)
Definition: mythcorecontext.cpp:2138
MythMediaBuffer::GetFilename
QString GetFilename(void) const
Definition: mythmediabuffer.cpp:1732
MythMediaBuffer::GetRealFileSize
long long GetRealFileSize(void) const
Definition: mythmediabuffer.cpp:464
MythMediaBuffer::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: mythmediabuffer.cpp:820
threadedfilewriter.h
mythdate.h
MythCDROM::kDVD
@ kDVD
Definition: mythcdrom.h:30
MythMediaBuffer::SetOldFile
void SetOldFile(bool Old)
Tell RingBuffer if this is an old file or not.
Definition: mythmediabuffer.cpp:1724
MythMediaBuffer::m_readPos
long long m_readPos
Definition: mythmediabuffer.h:164
MythMediaBuffer::m_beingWritten
bool m_beingWritten
Definition: mythmediabuffer.h:202
MythDVDStream
Definition: mythdvdstream.h:20
mythlogging.h
MythMediaBuffer::SeekInternal
virtual long long SeekInternal(long long Position, int Whence)=0
RemoteFile::Seek
long long Seek(long long pos, int whence, long long curpos=-1)
Definition: remotefile.cpp:759
MythMediaBuffer::WaitForPause
void WaitForPause(void)
Waits for Pause(void) to take effect.
Definition: mythmediabuffer.cpp:714
remotefile.h
MythMediaBuffer::WriterSeek
long long WriterSeek(long long Position, int Whence, bool HasLock=false)
Calls ThreadedFileWriter::Seek(long long,int).
Definition: mythmediabuffer.cpp:1664
MythMediaBuffer::m_requestPause
bool m_requestPause
Definition: mythmediabuffer.h:198
hardwareprofile.i18n.t
t
Definition: i18n.py:36
MythMediaBuffer::m_readInternalMode
bool m_readInternalMode
Definition: mythmediabuffer.h:220
compat.h
MythMediaBuffer::~MythMediaBuffer
~MythMediaBuffer() override=0
Deletes.
Definition: mythmediabuffer.cpp:220
BUFFER_FACTOR_NETWORK
#define BUFFER_FACTOR_NETWORK
Definition: mythmediabuffer.h:26
MythMediaBuffer::GetSubtitleFilename
QString GetSubtitleFilename(void) const
Definition: mythmediabuffer.cpp:1745
MythMediaBuffer::m_remotefile
RemoteFile * m_remotefile
Definition: mythmediabuffer.h:189
MythMediaBuffer::UpdateStorageRate
uint64_t UpdateStorageRate(uint64_t Latest=0)
Definition: mythmediabuffer.cpp:1582
MythMediaBuffer::ResetCommsError
void ResetCommsError(void)
Definition: mythmediabuffer.cpp:1766
HLSRingBuffer
Definition: httplivestreambuffer.h:44
MythMediaBuffer::m_writePos
long long m_writePos
Definition: mythmediabuffer.h:165
MythMediaBuffer::m_readBlockSize
int m_readBlockSize
Definition: mythmediabuffer.h:211
MythMediaBuffer::m_rbwLock
QReadWriteLock m_rbwLock
Definition: mythmediabuffer.h:172
clamp
float clamp(float val, float minimum, float maximum)
Definition: mythmiscutil.h:59
MythMediaBuffer::GetCommsError
bool GetCommsError(void) const
Definition: mythmediabuffer.cpp:1761
MythMediaBuffer::m_waitForWrite
bool m_waitForWrite
Definition: mythmediabuffer.h:201
MythBDBuffer
A class to allow a MythMediaBuffer to read from BDs.
Definition: mythbdbuffer.h:21
filename
QString filename
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:637
MythMediaBuffer::m_setSwitchToNext
bool m_setSwitchToNext
Definition: mythmediabuffer.h:206
DEFAULT_CHUNK_SIZE
#define DEFAULT_CHUNK_SIZE
Definition: mythmediabuffer.h:30
MThread::RunEpilog
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:211
MythMediaBuffer::m_readAheadBuffer
char * m_readAheadBuffer
Definition: mythmediabuffer.h:195
LiveTVChain::ReloadAll
void ReloadAll(const QStringList &data=QStringList())
Definition: livetvchain.cpp:209
MythMediaBuffer::m_numFailures
int m_numFailures
Definition: mythmediabuffer.h:213
MythMediaBuffer::m_bufferSize
uint m_bufferSize
Definition: mythmediabuffer.h:190
MythMediaBuffer::LiveMode
bool LiveMode(void) const
Returns true if this RingBuffer has been assigned a LiveTVChain.
Definition: mythmediabuffer.cpp:1791
MythMediaBuffer::m_lowBuffers
bool m_lowBuffers
Definition: mythmediabuffer.h:191
MythMediaBuffer::m_fillThreshold
int m_fillThreshold
Definition: mythmediabuffer.h:209
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
MythMediaBuffer::m_filename
QString m_filename
Definition: mythmediabuffer.h:183
MythMediaBuffer::CreateReadAheadBuffer
void CreateReadAheadBuffer(void)
Definition: mythmediabuffer.cpp:772
mythmediabuffer.h
MythFileBuffer
Definition: mythfilebuffer.h:8
MythMediaBuffer::IgnoreLiveEOF
void IgnoreLiveEOF(bool Ignore)
Tells RingBuffer whether to ignore the end-of-file.
Definition: mythmediabuffer.cpp:1811
ThreadedFileWriter::Write
int Write(const void *data, uint count)
Writes data to the end of the write buffer.
Definition: threadedfilewriter.cpp:190
MythMediaBuffer::Read
int Read(void *Buffer, int Count)
This is the public method for reading from a file, it calls the appropriate read method if the file i...
Definition: mythmediabuffer.cpp:1479
MythCDROM::inspectImage
static ImageType inspectImage(const QString &path)
Definition: mythcdrom.cpp:179
MythMediaBuffer::IsReadInternalMode
bool IsReadInternalMode(void) const
Definition: mythmediabuffer.cpp:544
MythMediaBuffer::m_rbrLock
QReadWriteLock m_rbrLock
Definition: mythmediabuffer.h:169
MythMediaBuffer::m_readsDesired
bool m_readsDesired
Definition: mythmediabuffer.h:204
MythTimer::elapsed
int elapsed(void)
Returns milliseconds elapsed since last start() or restart()
Definition: mythtimer.cpp:90
MythMediaBuffer::WriterFlush
void WriterFlush(void)
Calls ThreadedFileWriter::Flush(void)
Definition: mythmediabuffer.cpp:1690
mythbdbuffer.h
MythMediaBuffer::KillReadAheadThread
void KillReadAheadThread(void)
Stops the read-ahead thread, and waits for it to stop.
Definition: mythmediabuffer.cpp:649
MythMediaBuffer::AVFormatInitNetwork
static void AVFormatInitNetwork(void)
Definition: mythmediabuffer.cpp:1853
livetvchain.h
MythMediaBuffer::m_playSpeed
float m_playSpeed
Definition: mythmediabuffer.h:208
Buffer
Definition: MythExternControl.h:37
MythMediaBuffer::m_recentSeek
volatile bool m_recentSeek
Definition: mythmediabuffer.h:205
MythMediaBuffer::m_ignoreLiveEOF
bool m_ignoreLiveEOF
Definition: mythmediabuffer.h:217
MythTimer::kStartRunning
@ kStartRunning
Definition: mythtimer.h:17
MythMediaBuffer::m_storageReadLock
QMutex m_storageReadLock
Definition: mythmediabuffer.h:226
assert
#define assert(x)
Definition: audiooutputalsa.cpp:18
mythmiscutil.h
MythMediaBuffer::m_unknownBitrate
bool m_unknownBitrate
Definition: mythmediabuffer.h:193
MythMediaBuffer::ResetReadAhead
void ResetReadAhead(long long NewInternal)
Restart the read-ahead thread at the 'newinternal' position.
Definition: mythmediabuffer.cpp:571
MythMediaBuffer::MythMediaBuffer
MythMediaBuffer(MythBufferType Type)
Definition: mythmediabuffer.cpp:199
MythMediaBuffer::SetReadInternalMode
bool SetReadInternalMode(bool Mode)
Definition: mythmediabuffer.cpp:519
LiveTVChain::SwitchToNext
void SwitchToNext(bool up)
Sets the recording to switch to.
Definition: livetvchain.cpp:591
httplivestreambuffer.h
MythMediaBuffer::m_fileIsMatroska
bool m_fileIsMatroska
Definition: mythmediabuffer.h:192
MythStreamingBuffer
Definition: mythstreamingbuffer.h:14
MythMediaBuffer::m_wantToRead
int m_wantToRead
Definition: mythmediabuffer.h:212
MythMediaBuffer::GetRealFileSizeInternal
virtual long long GetRealFileSizeInternal(void) const
Definition: mythmediabuffer.h:156
MythMediaBuffer::IsDisc
bool IsDisc(void) const
Definition: mythmediabuffer.cpp:1818
MythMediaBuffer::Start
void Start(void)
Starts the read-ahead thread.
Definition: mythmediabuffer.cpp:613
mythcontext.h
MThread
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:49
MythMediaBuffer::GetAvailableBuffer
QString GetAvailableBuffer(void)
Definition: mythmediabuffer.cpp:1536
MythMediaBuffer::kLiveTVOpenTimeout
static const int kLiveTVOpenTimeout
Definition: mythmediabuffer.h:62
MThread::isRunning
bool isRunning(void) const
Definition: mthread.cpp:268
MythMediaBuffer::ReadBufAvail
int ReadBufAvail(void) const
Returns number of bytes available for reading from buffer.
Definition: mythmediabuffer.cpp:551
MythMediaBuffer::m_bitrateInitialized
bool m_bitrateInitialized
Definition: mythmediabuffer.h:239
MythMediaBuffer::GetLastError
QString GetLastError(void) const
Definition: mythmediabuffer.cpp:1753
MythMediaBuffer::m_decoderReads
QMap< qint64, uint64_t > m_decoderReads
Definition: mythmediabuffer.h:225
MythMediaBuffer::m_reallyRunning
bool m_reallyRunning
Definition: mythmediabuffer.h:197
MythMediaBuffer::SetLiveMode
void SetLiveMode(LiveTVChain *Chain)
Assigns a LiveTVChain to this RingBuffer.
Definition: mythmediabuffer.cpp:1803
mythtimer.h
MythMediaBuffer::m_subtitleFilename
QString m_subtitleFilename
Definition: mythmediabuffer.h:184
mythfilebuffer.h
MythMediaBuffer::m_writeMode
bool m_writeMode
Definition: mythmediabuffer.h:188
MythMediaBuffer::DVD
const MythDVDBuffer * DVD(void) const
Definition: mythmediabuffer.cpp:1833
MythMediaBuffer::m_posLock
QReadWriteLock m_posLock
Definition: mythmediabuffer.h:163
mythstreamingbuffer.h
MythMediaBuffer::m_bitrateMonitorEnabled
bool m_bitrateMonitorEnabled
Definition: mythmediabuffer.h:223
MythMediaBuffer::Peek
int Peek(void *Buffer, int Count)
Definition: mythmediabuffer.cpp:1170
MythMediaBuffer::m_stopReads
volatile bool m_stopReads
Definition: mythmediabuffer.h:177
ThreadedFileWriter::SetBlocking
bool SetBlocking(bool block=true)
Set write blocking mode While in blocking mode, ThreadedFileWriter::Write will wait for buffers to be...
Definition: threadedfilewriter.cpp:613
MThread::wait
bool wait(unsigned long time=ULONG_MAX)
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:305
MythMediaBuffer::IsNearEnd
bool IsNearEnd(double Framerate, uint Frames) const
Definition: mythmediabuffer.cpp:408
MythMediaBuffer::m_rwLock
QReadWriteLock m_rwLock
Definition: mythmediabuffer.h:182
MythMediaBuffer::StartReads
void StartReads(void)
Definition: mythmediabuffer.cpp:675
MythDVDBuffer
Definition: mythdvdbuffer.h:36
MythMediaBuffer::m_ateof
bool m_ateof
Definition: mythmediabuffer.h:200
MythMediaBuffer::GetStorageRate
QString GetStorageRate(void)
Definition: mythmediabuffer.cpp:1531
MythMediaBuffer::UpdateDecoderRate
uint64_t UpdateDecoderRate(uint64_t Latest=0)
Definition: mythmediabuffer.cpp:1551
MythMediaBuffer::m_internalReadPos
long long m_internalReadPos
Definition: mythmediabuffer.h:166
MythMediaBuffer::WaitForAvail
int WaitForAvail(int Count, int Timeout)
Definition: mythmediabuffer.cpp:1214
MythMediaBuffer::Pause
void Pause(void)
Pauses the read-ahead thread.
Definition: mythmediabuffer.cpp:686
MythMediaBuffer::Sync
void Sync(void)
Calls ThreadedFileWriter::Sync(void)
Definition: mythmediabuffer.cpp:1654
MythMediaBuffer::m_rbwPos
int m_rbwPos
Definition: mythmediabuffer.h:173
MythMediaBuffer::m_ignoreReadPos
long long m_ignoreReadPos
Definition: mythmediabuffer.h:167
MythMediaBuffer::m_readAheadRunning
bool m_readAheadRunning
Definition: mythmediabuffer.h:196
MythMediaBuffer::Reset
void Reset(bool Full=false, bool ToAdjust=false, bool ResetInternal=false)
Resets the read-ahead thread and our position in the file.
Definition: mythmediabuffer.cpp:239
MythMediaBuffer::IsOpen
virtual bool IsOpen(void) const =0
MythMediaBuffer::GetType
MythBufferType GetType() const
Definition: mythmediabuffer.cpp:205
MythMediaBuffer::m_fillMin
int m_fillMin
Definition: mythmediabuffer.h:210
LiveTVChain
Keeps track of recordings in a current LiveTV instance.
Definition: livetvchain.h:32
MythMediaBuffer::SetWaitForWrite
void SetWaitForWrite(void)
Definition: mythmediabuffer.cpp:321