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