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