MythTV  master
mythbdbuffer.cpp
Go to the documentation of this file.
1 // Std
2 #include <thread>
3 #include <fcntl.h>
4 
5 // Qt
6 #include <QDir>
7 #include <QCoreApplication>
8 
9 // MythTV
10 #include "libmythbase/iso639.h"
11 #include "libmythbase/mythcdrom.h"
13 #include "libmythbase/mythdate.h"
14 #include "libmythbase/mythdirs.h"
15 #include "libmythbase/mythevent.h"
16 #include "libmythbase/mythlocale.h"
18 #include "libmythbase/stringutil.h"
22 
23 #include "io/mythiowrapper.h"
24 #include "libbluray/bluray.h"
25 #include "tv_actions.h"
26 #include "Bluray/mythbdiowrapper.h"
27 #include "Bluray/mythbdinfo.h"
28 #include "Bluray/mythbdbuffer.h"
29 
30 // BluRay
31 #ifdef HAVE_LIBBLURAY
32 #include <libbluray/log_control.h>
33 #include <libbluray/meta_data.h>
34 #include <libbluray/overlay.h>
35 #include <libbluray/keys.h>
36 #else
37 #include "util/log_control.h"
38 #include "libbluray/bdnav/meta_data.h"
39 #include "libbluray/decoders/overlay.h"
40 #include "libbluray/keys.h"
41 #endif
42 
43 #define LOC QString("BDBuffer: ")
44 
45 static void HandleOverlayCallback(void *Data, const bd_overlay_s *const Overlay)
46 {
47  auto *bdrb = static_cast<MythBDBuffer*>(Data);
48  if (bdrb)
49  bdrb->SubmitOverlay(Overlay);
50 }
51 
52 static void HandleARGBOverlayCallback(void *Data, const bd_argb_overlay_s *const Overlay)
53 {
54  auto *bdrb = static_cast<MythBDBuffer*>(Data);
55  if (bdrb)
56  bdrb->SubmitARGBOverlay(Overlay);
57 }
58 
59 static void FileOpenedCallback(void* Data)
60 {
61  auto *obj = static_cast<MythBDBuffer*>(Data);
62  if (obj)
63  obj->ProgressUpdate();
64 }
65 
66 static void BDLogger(const char* Message)
67 {
68  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString(Message).trimmed());
69 }
70 
71 static int BDRead(void *Handle, void *Buf, int LBA, int NumBlocks)
72 {
73  if (MythFileSeek(*(static_cast<int*>(Handle)), LBA * 2048LL, SEEK_SET) != -1)
74  return static_cast<int>(MythFileRead(*(static_cast<int*>(Handle)), Buf,
75  static_cast<size_t>(NumBlocks) * 2048) / 2048);
76  return -1;
77 }
78 
79 MythBDBuffer::MythBDBuffer(const QString &Filename)
81  m_overlayPlanes(2, nullptr)
82 {
83  m_tryHDMVNavigation = qEnvironmentVariableIsSet("MYTHTV_HDMV");
84  m_mainThread = QThread::currentThread();
85  MythBDBuffer::OpenFile(Filename);
86 }
87 
89 {
91  Close();
92 }
93 
95 {
96  if (m_bdnav)
97  {
98  m_infoLock.lock();
99  for (auto it = m_cachedTitleInfo.begin(); it !=m_cachedTitleInfo.end(); ++it)
100  bd_free_title_info(it.value());
101  m_cachedTitleInfo.clear();
102  for (auto it = m_cachedPlaylistInfo.begin(); it !=m_cachedPlaylistInfo.end(); ++it)
103  bd_free_title_info(it.value());
104  m_cachedPlaylistInfo.clear();
105  m_infoLock.unlock();
106  bd_close(m_bdnav);
107  m_bdnav = nullptr;
108  }
109 
110  if (m_imgHandle > 0)
111  {
113  m_imgHandle = -1;
114  }
115 
116  ClearOverlays();
117 }
118 
119 long long MythBDBuffer::SeekInternal(long long Position, int Whence)
120 {
121  long long ret = -1;
122 
123  m_posLock.lockForWrite();
124 
125  // Optimize no-op seeks
126  if (m_readAheadRunning &&
127  ((Whence == SEEK_SET && Position == m_readPos) || (Whence == SEEK_CUR && Position == 0)))
128  {
129  ret = m_readPos;
130  m_posLock.unlock();
131  return ret;
132  }
133 
134  // only valid for SEEK_SET & SEEK_CUR
135  long long newposition = (SEEK_SET == Whence) ? Position : m_readPos + Position;
136 
137  // Here we perform a normal seek. When successful we
138  // need to call ResetReadAhead(). A reset means we will
139  // need to refill the buffer, which takes some time.
140  if ((SEEK_END == Whence) || ((SEEK_CUR == Whence) && newposition != 0))
141  {
142  errno = EINVAL;
143  ret = -1;
144  }
145  else
146  {
147  SeekInternal(static_cast<uint64_t>(newposition));
148  m_currentTime = mpeg::chrono::pts(bd_tell_time(m_bdnav));
149  ret = newposition;
150  }
151 
152  if (ret >= 0)
153  {
154  m_readPos = ret;
155  m_ignoreReadPos = -1;
156  if (m_readAheadRunning)
158  m_readAdjust = 0;
159  }
160  else
161  {
162  QString cmd = QString("Seek(%1, %2)").arg(Position)
163  .arg((Whence == SEEK_SET) ? "SEEK_SET" :
164  ((Whence == SEEK_CUR) ?"SEEK_CUR" : "SEEK_END"));
165  LOG(VB_GENERAL, LOG_ERR, LOC + cmd + " Failed" + ENO);
166  }
167 
168  m_posLock.unlock();
169  m_generalWait.wakeAll();
170  return ret;
171 }
172 
173 uint64_t MythBDBuffer::SeekInternal(uint64_t Position)
174 {
175  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Seeking to '%1'").arg(Position));
177  if (m_bdnav)
178  return static_cast<uint64_t>(bd_seek_time(m_bdnav, Position));
179  return 0;
180 }
181 
182 void MythBDBuffer::GetDescForPos(QString &Desc)
183 {
184  if (!m_infoLock.tryLock())
185  return;
186  Desc = tr("Title %1 chapter %2").arg(m_currentTitle).arg(m_currentTitleInfo->chapters->idx);
187  m_infoLock.unlock();
188 }
189 
190 bool MythBDBuffer::HandleAction(const QStringList &Actions, mpeg::chrono::pts Pts)
191 {
192  if (!m_isHDMVNavigation)
193  return false;
194 
195  if (Actions.contains(ACTION_MENUTEXT))
196  {
197  PressButton(BD_VK_POPUP, Pts);
198  return true;
199  }
200 
201  if (!IsInMenu())
202  return false;
203 
204  bool handled = true;
205  if (Actions.contains(ACTION_UP) || Actions.contains(ACTION_CHANNELUP))
206  PressButton(BD_VK_UP, Pts);
207  else if (Actions.contains(ACTION_DOWN) || Actions.contains(ACTION_CHANNELDOWN))
208  PressButton(BD_VK_DOWN, Pts);
209  else if (Actions.contains(ACTION_LEFT) || Actions.contains(ACTION_SEEKRWND))
210  PressButton(BD_VK_LEFT, Pts);
211  else if (Actions.contains(ACTION_RIGHT) || Actions.contains(ACTION_SEEKFFWD))
212  PressButton(BD_VK_RIGHT, Pts);
213  else if (Actions.contains(ACTION_0))
214  PressButton(BD_VK_0, Pts);
215  else if (Actions.contains(ACTION_1))
216  PressButton(BD_VK_1, Pts);
217  else if (Actions.contains(ACTION_2))
218  PressButton(BD_VK_2, Pts);
219  else if (Actions.contains(ACTION_3))
220  PressButton(BD_VK_3, Pts);
221  else if (Actions.contains(ACTION_4))
222  PressButton(BD_VK_4, Pts);
223  else if (Actions.contains(ACTION_5))
224  PressButton(BD_VK_5, Pts);
225  else if (Actions.contains(ACTION_6))
226  PressButton(BD_VK_6, Pts);
227  else if (Actions.contains(ACTION_7))
228  PressButton(BD_VK_7, Pts);
229  else if (Actions.contains(ACTION_8))
230  PressButton(BD_VK_8, Pts);
231  else if (Actions.contains(ACTION_9))
232  PressButton(BD_VK_9, Pts);
233  else if (Actions.contains(ACTION_SELECT))
234  PressButton(BD_VK_ENTER, Pts);
235  else
236  handled = false;
237 
238  return handled;
239 }
240 
242 {
243  // This thread check is probably unnecessary as processEvents should
244  // only handle events in the calling thread - and not all threads
246  return;
247 
248  qApp->postEvent(GetMythMainWindow(),
250  qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
251 }
252 
254 {
255  return m_playerWait;
256 }
257 
259 {
260  m_playerWait = false;
261 }
262 
271 bool MythBDBuffer::OpenFile(const QString &Filename, std::chrono::milliseconds /*Retry*/)
272 {
273  m_safeFilename = Filename;
274  m_filename = Filename;
275 
276  // clean path filename
277  QString filename = QDir(QDir::cleanPath(Filename)).canonicalPath();
278  if (filename.isEmpty())
279  {
280  LOG(VB_GENERAL, LOG_ERR, LOC + QString("%1 nonexistent").arg(Filename));
281  filename = Filename;
282  }
284 
285  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Opened MythBDBuffer device at %1")
286  .arg(filename));
287 
288  // Make sure log messages from the Bluray library appear in our logs
289  bd_set_debug_handler(BDLogger);
290  bd_set_debug_mask(DBG_CRIT | DBG_NAV | DBG_BLURAY);
291 
292  // Use our own wrappers for file and directory access
294 
295  // Ask mythiowrapper to update this object on file open progress. Opening
296  // a bluray disc can involve opening several hundred files which can take
297  // several minutes when the disc structure is remote. The callback allows
298  // us to 'kick' the main UI - as the 'please wait' widget is still visible
299  // at this stage
300  MythFileOpenRegisterCallback(filename.toLocal8Bit().data(), this, FileOpenedCallback);
301 
302  QMutexLocker locker(&m_infoLock);
303  m_rwLock.lockForWrite();
304 
305  if (m_bdnav)
306  Close();
307 
308  QString keyfile = QString("%1/KEYDB.cfg").arg(GetConfDir());
309 
310  if (filename.startsWith("myth:") && MythCDROM::inspectImage(filename) != MythCDROM::kUnknown)
311  {
312  // Use streaming for remote images.
313  // Streaming encrypted images causes a SIGSEGV in aacs code when
314  // using the makemkv libraries due to the missing "device" name.
315  // Since a local device (which is likely to be encrypted) can be
316  // opened directly, only use streaming for remote images, which
317  // presumably won't be encrypted.
318  m_imgHandle = MythFileOpen(filename.toLocal8Bit().data(), O_RDONLY);
319  if (m_imgHandle >= 0)
320  {
321  m_bdnav = bd_init();
322  if (m_bdnav)
323  bd_open_stream(m_bdnav, &m_imgHandle, BDRead);
324  }
325  }
326  else
327  {
328  m_bdnav = bd_open(filename.toLocal8Bit().data(), qPrintable(keyfile));
329  }
330 
331  if (!m_bdnav)
332  {
333  m_lastError = tr("Could not open Blu-ray device: %1").arg(filename);
334  m_rwLock.unlock();
335  MythFileOpenRegisterCallback(filename.toLocal8Bit().data(), this, nullptr);
336  return false;
337  }
338 
339  const meta_dl *metaDiscLibrary = bd_get_meta(m_bdnav);
340 
341  if (metaDiscLibrary)
342  {
343  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Disc Title: %1 (%2)")
344  .arg(metaDiscLibrary->di_name, metaDiscLibrary->language_code));
345  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Alternative Title: %1")
346  .arg(metaDiscLibrary->di_alternative));
347  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Disc Number: %1 of %2")
348  .arg(metaDiscLibrary->di_set_number).arg(metaDiscLibrary->di_num_sets));
349  }
350 
352 
353  // Check disc to see encryption status, menu and navigation types.
354  m_topMenuSupported = false;
355  m_firstPlaySupported = false;
356  const BLURAY_DISC_INFO *discinfo = bd_get_disc_info(m_bdnav);
357  if (!discinfo)
358  {
359  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to retrieve disc info");
360  bd_close(m_bdnav);
361  m_bdnav = nullptr;
362  m_lastError = tr("Could not open Blu-ray device: %1").arg(filename);
363  m_rwLock.unlock();
364  MythFileOpenRegisterCallback(filename.toLocal8Bit().data(), this, nullptr);
365  return false;
366  }
367 
368  if ((discinfo->aacs_detected && !discinfo->aacs_handled) ||
369  (discinfo->bdplus_detected && !discinfo->bdplus_handled))
370  {
371  // couldn't decrypt bluray
372  bd_close(m_bdnav);
373  m_bdnav = nullptr;
374  m_lastError = tr("Could not open Blu-ray device %1, failed to decrypt").arg(filename);
375  m_rwLock.unlock();
376  MythFileOpenRegisterCallback(filename.toLocal8Bit().data(), this, nullptr);
377  return false;
378  }
379 
380  // The following settings affect HDMV navigation
381  // (default audio track selection, parental controls, menu language, etc.)
382  // They are not yet used.
383 
384  // Set parental level "age" to 99 for now. TODO: Add support for FE level
385  bd_set_player_setting(m_bdnav, BLURAY_PLAYER_SETTING_PARENTAL, 99);
386 
387  // Set preferred language to FE guide language
388  std::string langpref = gCoreContext->GetSetting("ISO639Language0", "eng").toLatin1().data();
389  QString QScountry = gCoreContext->GetLocale()->GetCountryCode().toLower();
390  std::string country = QScountry.toLatin1().data();
391  bd_set_player_setting_str(m_bdnav, BLURAY_PLAYER_SETTING_AUDIO_LANG, langpref.c_str());
392  // Set preferred presentation graphics language to the FE guide language
393  bd_set_player_setting_str(m_bdnav, BLURAY_PLAYER_SETTING_PG_LANG, langpref.c_str());
394  // Set preferred menu language to the FE guide language
395  bd_set_player_setting_str(m_bdnav, BLURAY_PLAYER_SETTING_MENU_LANG, langpref.c_str());
396  // Set player country code via MythLocale. (not a region setting)
397  bd_set_player_setting_str(m_bdnav, BLURAY_PLAYER_SETTING_COUNTRY_CODE, country.c_str());
398 
399  uint32_t regioncode = static_cast<uint32_t>(gCoreContext->GetNumSetting("BlurayRegionCode"));
400  if (regioncode > 0)
401  bd_set_player_setting(m_bdnav, BLURAY_PLAYER_SETTING_REGION_CODE, regioncode);
402 
403  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Using %1 as keyfile...").arg(keyfile));
404 
405  // Return an index of relevant titles (excludes dupe clips + titles)
406  LOG(VB_GENERAL, LOG_INFO, LOC + "Retrieving title list (please wait).");
407  m_numTitles = bd_get_titles(m_bdnav, TITLES_RELEVANT, 30);
408  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Found %1 titles.").arg(m_numTitles));
409  if (!m_numTitles)
410  {
411  // no title, no point trying any longer
412  bd_close(m_bdnav);
413  m_bdnav = nullptr;
414  m_lastError = tr("Unable to find any Blu-ray compatible titles");
415  m_rwLock.unlock();
416  MythFileOpenRegisterCallback(filename.toLocal8Bit().data(), this, nullptr);
417  return false;
418  }
419 
420  m_topMenuSupported = (discinfo->top_menu_supported != 0U);
421  m_firstPlaySupported = (discinfo->first_play_supported != 0U);
422 
423  LOG(VB_PLAYBACK, LOG_INFO, LOC + "*** Blu-ray Disc Information ***");
424  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("First Play Supported: %1")
425  .arg(discinfo->first_play_supported ? "yes" : "no"));
426  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Top Menu Supported: %1")
427  .arg(discinfo->top_menu_supported ? "yes" : "no"));
428  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Number of HDMV Titles: %1")
429  .arg(discinfo->num_hdmv_titles));
430  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Number of BD-J Titles: %1")
431  .arg(discinfo->num_bdj_titles));
432  if (discinfo->num_bdj_titles && discinfo->bdj_detected)
433  {
434  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("BD-J Supported: %1")
435  .arg(discinfo->bdj_handled ? "yes" : "no"));
436  }
437  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Number of Unsupported Titles: %1")
438  .arg(discinfo->num_unsupported_titles));
439  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("AACS present on disc: %1")
440  .arg(discinfo->aacs_detected ? "yes" : "no"));
441  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("libaacs used: %1")
442  .arg(discinfo->libaacs_detected ? "yes" : "no"));
443  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("AACS handled: %1")
444  .arg(discinfo->aacs_handled ? "yes" : "no"));
445  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("BD+ present on disc: %1")
446  .arg(discinfo->bdplus_detected ? "yes" : "no"));
447  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("libbdplus used: %1")
448  .arg(discinfo->libbdplus_detected ? "yes" : "no"));
449  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("BD+ handled: %1")
450  .arg(discinfo->bdplus_handled ? "yes" : "no"));
451 
452  m_mainTitle = 0;
453  m_currentTitleLength = 0_pts;
454  m_titlesize = 0;
455  m_currentTime = 0_pts;
456  m_currentTitleInfo = nullptr;
459  m_lastEvent.event = BD_EVENT_NONE;
460  m_lastEvent.param = 0;
461 
462  // Mostly event-driven values below
463  m_currentAngle = 0;
464  m_currentTitle = -1;
465  m_currentPlaylist = 0;
466  m_currentPlayitem = 0;
467  m_currentChapter = 0;
469  m_currentIGStream = 0;
473  m_pgTextSTEnabled = false;
474  m_secondaryAudioEnabled = false;
475  m_secondaryVideoEnabled = false;
477  m_stillMode = BLURAY_STILL_NONE;
478  m_stillTime = 0s;
479  m_timeDiff = 0;
480  m_inMenu = false;
481 
482  // First, attempt to initialize the disc in HDMV navigation mode.
483  // If this fails, fall back to the traditional built-in title switching
484  // mode.
486  {
487  LOG(VB_GENERAL, LOG_INFO, LOC + "Using HDMV navigation mode.");
488  m_isHDMVNavigation = true;
489 
490  // Register the Menu Overlay Callback
491  bd_register_overlay_proc(m_bdnav, this, HandleOverlayCallback);
492  bd_register_argb_overlay_proc(m_bdnav, this, HandleARGBOverlayCallback, nullptr);
493  }
494  else
495  {
496  LOG(VB_GENERAL, LOG_INFO, LOC + "Using title navigation mode.");
497 
498  // Loop through the relevant titles and find the longest
499  uint64_t titleLength = 0;
500  BLURAY_TITLE_INFO *titleInfo = nullptr;
501  bool found = false;
502  for(uint32_t i = 0; i < m_numTitles; ++i)
503  {
504  titleInfo = GetTitleInfo(i);
505  if (!titleInfo)
506  continue;
507  if (titleLength == 0 || (titleInfo->duration > titleLength))
508  {
509  m_mainTitle = titleInfo->idx;
510  titleLength = titleInfo->duration;
511  found = true;
512  }
513  }
514 
515  if (!found)
516  {
517  // no title, no point trying any longer
518  bd_close(m_bdnav);
519  m_bdnav = nullptr;
520  m_lastError = tr("Unable to find any usable Blu-ray titles");
521  m_rwLock.unlock();
522  MythFileOpenRegisterCallback(filename.toLocal8Bit().data(), this, nullptr);
523  return false;
524  }
526  }
527 
529  m_setSwitchToNext = false;
530  m_ateof = false;
531  m_commsError = false;
532  m_numFailures = 0;
533  m_rawBitrate = 8000;
535  m_rwLock.unlock();
536  MythFileOpenRegisterCallback(filename.toLocal8Bit().data(), this, nullptr);
537  return true;
538 }
539 
540 long long MythBDBuffer::GetReadPosition(void) const
541 {
542  if (m_bdnav)
543  return static_cast<long long>(bd_tell(m_bdnav));
544  return 0;
545 }
546 
547 bool MythBDBuffer::IsOpen(void) const
548 {
549  return m_bdnav;
550 }
551 
553 {
554  QMutexLocker locker(&m_infoLock);
555  if (m_currentTitleInfo)
556  return m_currentTitleInfo->chapter_count - 1;
557  return 0;
558 }
559 
561 {
562  if (m_bdnav)
563  return bd_get_current_chapter(m_bdnav);
564  return 0;
565 }
566 
567 std::chrono::milliseconds MythBDBuffer::GetChapterStartTimeMs(uint32_t Chapter)
568 {
569  if (Chapter >= GetNumChapters())
570  return 0ms;
571  QMutexLocker locker(&m_infoLock);
572  auto start = mpeg::chrono::pts(m_currentTitleInfo->chapters[Chapter].start);
573  return duration_cast<std::chrono::milliseconds>(start);
574 }
575 
576 std::chrono::seconds MythBDBuffer::GetChapterStartTime(uint32_t Chapter)
577 {
578  if (Chapter >= GetNumChapters())
579  return 0s;
580  QMutexLocker locker(&m_infoLock);
581  auto start = mpeg::chrono::pts(m_currentTitleInfo->chapters[Chapter].start);
582  return duration_cast<std::chrono::seconds>(start);
583 }
584 
585 uint64_t MythBDBuffer::GetChapterStartFrame(uint32_t Chapter)
586 {
587  if (Chapter >= GetNumChapters())
588  return 0;
589  QMutexLocker locker(&m_infoLock);
590  return static_cast<uint64_t>((m_currentTitleInfo->chapters[Chapter].start * GetFrameRate()) / 90000.0);
591 }
592 
593 uint32_t MythBDBuffer::GetNumTitles(void) const
594 {
595  return m_numTitles;
596 }
597 
599 {
600  QMutexLocker locker(&m_infoLock);
601  return m_currentTitle;
602 }
603 
604 uint64_t MythBDBuffer::GetCurrentAngle(void) const
605 {
606  return static_cast<uint64_t>(m_currentAngle);
607 }
608 
609 std::chrono::seconds MythBDBuffer::GetTitleDuration(int Title)
610 {
611  QMutexLocker locker(&m_infoLock);
612  auto numTitles = GetNumTitles();
613  if (numTitles <= 0 || Title < 0 || Title >= static_cast<int>(numTitles))
614  return 0s;
615 
616  BLURAY_TITLE_INFO *info = GetTitleInfo(static_cast<uint32_t>(Title));
617  if (!info)
618  return 0s;
619 
620  return duration_cast<std::chrono::seconds>(mpeg::chrono::pts(info->duration));
621 }
622 
623 uint64_t MythBDBuffer::GetTitleSize(void) const
624 {
625  return m_titlesize;
626 }
627 
628 std::chrono::seconds MythBDBuffer::GetTotalTimeOfTitle(void) const
629 {
630  return duration_cast<std::chrono::seconds>(m_currentTitleLength);
631 }
632 
633 std::chrono::seconds MythBDBuffer::GetCurrentTime(void) const
634 {
635  return duration_cast<std::chrono::seconds>(m_currentTime);
636 }
637 
638 bool MythBDBuffer::SwitchTitle(uint32_t Index)
639 {
640  if (!m_bdnav)
641  return false;
642 
643  m_infoLock.lock();
645  m_infoLock.unlock();
646  bd_select_title(m_bdnav, Index);
647 
648  return UpdateTitleInfo();
649 }
650 
651 bool MythBDBuffer::SwitchPlaylist(uint32_t Index)
652 {
653  if (!m_bdnav)
654  return false;
655 
656  LOG(VB_PLAYBACK, LOG_INFO, LOC + "SwitchPlaylist - start");
657 
658  m_infoLock.lock();
660  m_currentTitle = static_cast<int>(bd_get_current_title(m_bdnav));
661  m_infoLock.unlock();
662  bool result = UpdateTitleInfo();
663 
664  LOG(VB_PLAYBACK, LOG_INFO, LOC + "SwitchPlaylist - end");
665  return result;
666 }
667 
668 BLURAY_TITLE_INFO* MythBDBuffer::GetTitleInfo(uint32_t Index)
669 {
670  if (!m_bdnav)
671  return nullptr;
672 
673  QMutexLocker locker(&m_infoLock);
674  if (m_cachedTitleInfo.contains(Index))
675  return m_cachedTitleInfo.value(Index);
676 
677  if (Index > m_numTitles)
678  return nullptr;
679 
680  BLURAY_TITLE_INFO* result = bd_get_title_info(m_bdnav, Index, 0);
681  if (result)
682  {
683  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Found title %1 info").arg(Index));
684  m_cachedTitleInfo.insert(Index,result);
685  return result;
686  }
687  return nullptr;
688 }
689 
690 BLURAY_TITLE_INFO* MythBDBuffer::GetPlaylistInfo(uint32_t Index)
691 {
692  if (!m_bdnav)
693  return nullptr;
694 
695  QMutexLocker locker(&m_infoLock);
696  if (m_cachedPlaylistInfo.contains(Index))
697  return m_cachedPlaylistInfo.value(Index);
698 
699  BLURAY_TITLE_INFO* result = bd_get_playlist_info(m_bdnav, Index, 0);
700  if (result)
701  {
702  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Found playlist %1 info").arg(Index));
703  m_cachedPlaylistInfo.insert(Index,result);
704  return result;
705  }
706  return nullptr;
707 }
708 
710 {
711  QMutexLocker locker(&m_infoLock);
712  if (!m_currentTitleInfo)
713  return false;
714 
715  m_titleChanged = true;
718  m_currentAngle = 0;
719  m_currentPlayitem = 0;
720  m_timeDiff = 0;
721  m_titlesize = bd_get_title_size(m_bdnav);
722  uint32_t chapter_count = GetNumChapters();
723  auto total_msecs = duration_cast<std::chrono::milliseconds>(m_currentTitleLength);
724  auto duration = MythDate::formatTime(total_msecs, "HH:mm:ss.z");
725  LOG(VB_GENERAL, LOG_INFO, LOC + QString("New title info: Index %1 Playlist: %2 Duration: %3 ""Chapters: %5")
726  .arg(m_currentTitle).arg(m_currentTitleInfo->playlist).arg(duration).arg(chapter_count));
727  LOG(VB_GENERAL, LOG_INFO, LOC + QString("New title info: Clips: %1 Angles: %2 Title Size: %3 Frame Rate %4")
728  .arg(m_currentTitleInfo->clip_count).arg(m_currentTitleAngleCount).arg(m_titlesize)
729  .arg(GetFrameRate()));
730 
731  for (uint i = 0; i < chapter_count; i++)
732  {
733  uint64_t framenum = GetChapterStartFrame(i);
734  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Chapter %1 found @ [%2]->%3")
735  .arg(StringUtil::intToPaddedString(i + 1),
736  MythDate::formatTime(GetChapterStartTimeMs(i), "HH:mm:ss.zzz"),
737  QString::number(framenum)));
738  }
739 
740  int still = BLURAY_STILL_NONE;
741  std::chrono::seconds time = 0s;
742  if (m_currentTitleInfo->clip_count)
743  {
744  for (uint i = 0; i < m_currentTitleInfo->clip_count; i++)
745  {
746  LOG(VB_PLAYBACK, LOG_INFO, LOC +
747  QString("Clip %1 stillmode %2 stilltime %3 videostreams %4 audiostreams %5 igstreams %6")
748  .arg(i).arg(m_currentTitleInfo->clips[i].still_mode)
749  .arg(m_currentTitleInfo->clips[i].still_time)
750  .arg(m_currentTitleInfo->clips[i].video_stream_count)
751  .arg(m_currentTitleInfo->clips[i].audio_stream_count)
752  .arg(m_currentTitleInfo->clips[i].ig_stream_count));
753  still |= m_currentTitleInfo->clips[i].still_mode;
754  time = std::chrono::seconds(m_currentTitleInfo->clips[i].still_time);
755  }
756  }
757 
758  if (m_currentTitleInfo->clip_count > 1 && still != BLURAY_STILL_NONE)
759  {
760  LOG(VB_GENERAL, LOG_WARNING, LOC + "Warning: more than 1 clip, following still "
761  "frame analysis may be wrong");
762  }
763 
764  if (still == BLURAY_STILL_TIME)
765  {
766  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Entering still frame (%1 seconds) UNSUPPORTED").arg(time.count()));
767  bd_read_skip_still(m_bdnav);
768  }
769  else if (still == BLURAY_STILL_INFINITE)
770  {
771  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Entering infinite still frame.");
772  }
773 
774  m_stillMode = still;
775  m_stillTime = time;
776  return true;
777 }
778 
780 {
781  bool ret = m_titleChanged;
782  m_titleChanged = false;
783  return ret;
784 }
785 
787 {
788  if (!m_bdnav)
789  return false;
790 
791  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Switching to Angle '%1'").arg(Angle));
792  bd_seamless_angle_change(m_bdnav, Angle);
793  m_currentAngle = static_cast<int>(Angle);
794  return true;
795 }
796 
797 uint64_t MythBDBuffer::GetNumAngles(void) const
798 {
800 }
801 
803 {
804  if (m_bdnav)
805  return bd_get_title_size(m_bdnav);
806  return 0;
807 }
808 
809 int64_t MythBDBuffer::AdjustTimestamp(int64_t Timestamp) const
810 {
811  int64_t newTimestamp = Timestamp;
812  if ((newTimestamp != AV_NOPTS_VALUE) && (newTimestamp >= m_timeDiff))
813  newTimestamp -= m_timeDiff;
814  return newTimestamp;
815 }
816 
818 {
819  int result = 0;
820  if (m_isHDMVNavigation)
821  {
822  result = HandleBDEvents() ? 0 : -1;
823  while (result == 0)
824  {
825  BD_EVENT event;
826  result = bd_read_ext(m_bdnav, static_cast<unsigned char*>(Buffer),
827  static_cast<int>(Size), &event);
828  if (result == 0)
829  {
830  HandleBDEvent(event);
831  result = HandleBDEvents() ? 0 : -1;
832  }
833  }
834  }
835  else
836  {
838  {
839  MythOpticalState lastState = m_processState;
840 
842  result = bd_read(m_bdnav, static_cast<unsigned char*>(Buffer), static_cast<int>(Size));
843 
844  HandleBDEvents();
845 
846  if (m_processState == PROCESS_WAIT && lastState == PROCESS_NORMAL)
847  {
848  // We're waiting for the decoder to drain its buffers
849  // so don't give it any more data just yet.
850  m_pendingData = QByteArray(static_cast<const char*>(Buffer), result);
851  result = 0;
852  }
853  else
854  if (m_processState == PROCESS_NORMAL && lastState == PROCESS_REPROCESS)
855  {
856  // The decoder has finished draining its buffers so give
857  // it that last block of data we read
858  result = m_pendingData.size();
859  memcpy(Buffer, m_pendingData.constData(), static_cast<size_t>(result));
860  m_pendingData.clear();
861  }
862  }
863  }
864 
865  if (result < 0)
866  StopReads();
867 
868  m_currentTime = mpeg::chrono::pts(bd_tell_time(m_bdnav));
869  return result;
870 }
871 
873 {
874  QMutexLocker locker(&m_infoLock);
876  {
877  switch (m_currentTitleInfo->clips->video_streams->rate)
878  {
879  case BLURAY_VIDEO_RATE_24000_1001: return 23.97;
880  case BLURAY_VIDEO_RATE_24: return 24.00;
881  case BLURAY_VIDEO_RATE_25: return 25.00;
882  case BLURAY_VIDEO_RATE_30000_1001: return 29.97;
883  case BLURAY_VIDEO_RATE_50: return 50.00;
884  case BLURAY_VIDEO_RATE_60000_1001: return 59.94;
885  default: break;
886  }
887  }
888  return 0;
889 }
890 
892 {
893  QMutexLocker locker(&m_infoLock);
894 
895  int code = iso639_str3_to_key("und");
896 
897  if (m_currentTitleInfo && m_currentTitleInfo->clip_count > 0)
898  {
899  bd_clip& clip = m_currentTitleInfo->clips[0];
900  const BLURAY_STREAM_INFO* stream = FindStream(StreamID, clip.audio_streams, clip.audio_stream_count);
901  if (stream)
902  {
903  const uint8_t* lang = stream->lang;
904  code = iso639_key_to_canonical_key((lang[0] << 16) | (lang[1] << 8) | lang[2]);
905  }
906  }
907 
908  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Audio Lang: 0x%1 Code: %2")
909  .arg(code, 3, 16).arg(iso639_key_to_str3(code)));
910  return code;
911 }
912 
914 {
915  QMutexLocker locker(&m_infoLock);
916  int code = iso639_str3_to_key("und");
917  if (m_currentTitleInfo && m_currentTitleInfo->clip_count > 0)
918  {
919  bd_clip& clip = m_currentTitleInfo->clips[0];
920  const BLURAY_STREAM_INFO* stream = FindStream(StreamID, clip.pg_streams, clip.pg_stream_count);
921  if (stream)
922  {
923  const uint8_t* lang = stream->lang;
924  code = iso639_key_to_canonical_key((lang[0]<<16)|(lang[1]<<8)|lang[2]);
925  }
926  }
927 
928  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Subtitle Lang: 0x%1 Code: %2")
929  .arg(code, 3, 16).arg(iso639_key_to_str3(code)));
930  return code;
931 }
932 
934 {
935  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Key %1 (pts %2)").arg(Key).arg(Pts.count()));
936  // HACK for still frame menu navigation
937  Pts = 1_pts;
938  if (!m_bdnav || /*Pts <= 0 ||*/ Key < 0)
939  return;
940  bd_user_input(m_bdnav, Pts.count(), static_cast<uint32_t>(Key));
941 }
942 
944 {
945  if (!m_bdnav)
946  return;
947  if (Pts <= 0 || X == 0 || Y == 0)
948  return;
949  bd_mouse_select(m_bdnav, Pts, X, Y);
950 }
951 
954 bool MythBDBuffer::GoToMenu(const QString &Menu, mpeg::chrono::pts Pts)
955 {
956  if (!m_isHDMVNavigation || Pts < 0_pts)
957  return false;
958 
959  if (!m_topMenuSupported)
960  {
961  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Top Menu not supported");
962  return false;
963  }
964 
965  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("GoToMenu %1").arg(Menu));
966 
967  if (Menu.compare("root") == 0)
968  {
969  if (bd_menu_call(m_bdnav, Pts.count()))
970  {
971  LOG(VB_PLAYBACK, LOG_INFO, LOC +QString("Invoked Top Menu (pts %1)").arg(Pts.count()));
972  return true;
973  }
974  }
975  else if (Menu.compare("popup") == 0)
976  {
977  PressButton(BD_VK_POPUP, Pts);
978  return true;
979  }
980 
981  return false;
982 }
983 
985 {
987  {
989  {
991  // HandleBDEvent will change the process state
992  // if it needs to so don't do it here.
993  }
994 
995  while (m_processState == PROCESS_NORMAL && bd_get_event(m_bdnav, &m_lastEvent))
996  {
998  if (m_lastEvent.event == BD_EVENT_NONE || m_lastEvent.event == BD_EVENT_ERROR)
999  return false;
1000  }
1001  }
1002  return true;
1003 }
1004 
1006 {
1007  switch (Event.event) {
1008  case BD_EVENT_NONE:
1009  break;
1010  case BD_EVENT_ERROR:
1011  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_ERROR %1").arg(Event.param));
1012  break;
1013  case BD_EVENT_ENCRYPTED:
1014  LOG(VB_GENERAL, LOG_ERR, LOC + "EVENT_ENCRYPTED, playback will fail.");
1015  break;
1016 
1017  /* current playback position */
1018 
1019  case BD_EVENT_ANGLE:
1020  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_ANGLE %1").arg(Event.param));
1021  m_currentAngle = static_cast<int>(Event.param);
1022  break;
1023  case BD_EVENT_TITLE:
1024  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_TITLE %1 (old %2)")
1025  .arg(Event.param).arg(m_currentTitle));
1026  m_currentTitle = static_cast<int>(Event.param);
1027  break;
1028  case BD_EVENT_END_OF_TITLE:
1029  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_END_OF_TITLE %1").arg(m_currentTitle));
1030  WaitForPlayer();
1031  break;
1032  case BD_EVENT_PLAYLIST:
1033  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_PLAYLIST %1 (old %2)")
1034  .arg(Event.param).arg(m_currentPlaylist));
1035  m_currentPlaylist = static_cast<int>(Event.param);
1036  m_timeDiff = 0;
1037  m_currentPlayitem = 0;
1038  SwitchPlaylist(static_cast<uint32_t>(m_currentPlaylist));
1039  break;
1040  case BD_EVENT_PLAYITEM:
1041  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_PLAYITEM %1").arg(Event.param));
1042  {
1043  if (m_currentPlayitem != static_cast<int>(Event.param))
1044  {
1045  auto out = static_cast<int64_t>(m_currentTitleInfo->clips[m_currentPlayitem].out_time);
1046  auto in = static_cast<int64_t>(m_currentTitleInfo->clips[Event.param].in_time);
1047  int64_t diff = in - out;
1048  if (diff != 0 && m_processState == PROCESS_NORMAL)
1049  {
1050  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("PTS discontinuity - waiting for decoder: this %1, last %2, diff %3")
1051  .arg(in).arg(out).arg(diff));
1053  break;
1054  }
1055 
1056  m_timeDiff += diff;
1058  m_currentPlayitem = static_cast<int>(Event.param);
1059  }
1060  }
1061  break;
1062  case BD_EVENT_CHAPTER:
1063  // N.B. event chapter numbering 1...N, chapter seeks etc 0...
1064  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_CHAPTER %1").arg(Event.param));
1065  m_currentChapter = static_cast<int>(Event.param);
1066  break;
1067  case BD_EVENT_PLAYMARK:
1068  /* playmark reached */
1069  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_PLAYMARK"));
1070  break;
1071 
1072  /* playback control */
1073  case BD_EVENT_PLAYLIST_STOP:
1074  /* HDMV VM or JVM stopped playlist playback. Flush all buffers. */
1075  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ToDo EVENT_PLAYLIST_STOP %1")
1076  .arg(Event.param));
1077  break;
1078 
1079  case BD_EVENT_STILL:
1080  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_STILL %1").arg(Event.param));
1081  break;
1082  case BD_EVENT_STILL_TIME:
1083  // we use the clip information to determine the still frame status
1084  // sleep a little
1085  std::this_thread::sleep_for(10ms);
1086  break;
1087  case BD_EVENT_SEEK:
1088  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_SEEK"));
1089  break;
1090 
1091  /* stream selection */
1092 
1093  case BD_EVENT_AUDIO_STREAM:
1094  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_AUDIO_STREAM %1").arg(Event.param));
1095  m_currentAudioStream = static_cast<int>(Event.param);
1096  break;
1097  case BD_EVENT_IG_STREAM:
1098  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_IG_STREAM %1").arg(Event.param));
1099  m_currentIGStream = static_cast<int>(Event.param);
1100  break;
1101  case BD_EVENT_PG_TEXTST_STREAM:
1102  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_PG_TEXTST_STREAM %1").arg(Event.param));
1103  m_currentPGTextSTStream = static_cast<int>(Event.param);
1104  break;
1105  case BD_EVENT_SECONDARY_AUDIO_STREAM:
1106  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_SECONDARY_AUDIO_STREAM %1").arg(Event.param));
1107  m_currentSecondaryAudioStream = static_cast<int>(Event.param);
1108  break;
1109  case BD_EVENT_SECONDARY_VIDEO_STREAM:
1110  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_SECONDARY_VIDEO_STREAM %1").arg(Event.param));
1111  m_currentSecondaryVideoStream = static_cast<int>(Event.param);
1112  break;
1113 
1114  case BD_EVENT_PG_TEXTST:
1115  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_PG_TEXTST %1")
1116  .arg(Event.param ? "enable" : "disable"));
1117  m_pgTextSTEnabled = (Event.param != 0U);
1118  break;
1119  case BD_EVENT_SECONDARY_AUDIO:
1120  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_SECONDARY_AUDIO %1")
1121  .arg(Event.param ? "enable" : "disable"));
1122  m_secondaryAudioEnabled = (Event.param != 0U);
1123  break;
1124  case BD_EVENT_SECONDARY_VIDEO:
1125  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_SECONDARY_VIDEO %1")
1126  .arg(Event.param ? "enable" : "disable"));
1127  m_secondaryVideoEnabled = (Event.param != 0U);
1128  break;
1129  case BD_EVENT_SECONDARY_VIDEO_SIZE:
1130  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_SECONDARY_VIDEO_SIZE %1")
1131  .arg(Event.param==0 ? "PIP" : "fullscreen"));
1132  m_secondaryVideoIsFullscreen = (Event.param != 0U);
1133  break;
1134 
1135  /* status */
1136  case BD_EVENT_IDLE:
1137  /* Nothing to do. Playlist is not playing, but title applet is running.
1138  * Application should not call bd_read*() immediately again to avoid busy loop. */
1139  std::this_thread::sleep_for(40ms);
1140  break;
1141 
1142  case BD_EVENT_MENU:
1143  /* Interactive menu visible */
1144  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_MENU %1")
1145  .arg(Event.param==0 ? "no" : "yes"));
1146  m_inMenu = (Event.param == 1);
1147  break;
1148 
1149  case BD_EVENT_KEY_INTEREST_TABLE:
1150  /* BD-J key interest table changed */
1151  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ToDo EVENT_KEY_INTEREST_TABLE %1")
1152  .arg(Event.param));
1153  break;
1154 
1155  case BD_EVENT_UO_MASK_CHANGED:
1156  /* User operations mask was changed */
1157  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ToDo EVENT_UO_MASK_CHANGED %1")
1158  .arg(Event.param));
1159  break;
1160 
1161  default:
1162  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString("Unknown Event! %1 %2")
1163  .arg(Event.event).arg(Event.param));
1164  break;
1165  }
1166 }
1167 
1169 {
1170  return m_stillTime > 0s && m_stillMode != BLURAY_STILL_NONE;
1171 }
1172 
1180 const BLURAY_STREAM_INFO* MythBDBuffer::FindStream(uint StreamID,
1181  BLURAY_STREAM_INFO* Streams,
1182  int StreamCount)
1183 {
1184  const BLURAY_STREAM_INFO* stream = nullptr;
1185  for (int i = 0; i < StreamCount && !stream; i++)
1186  if (Streams[i].pid == StreamID)
1187  stream = &Streams[i];
1188  return stream;
1189 }
1190 
1192 {
1193  if (m_currentTitleInfo && m_currentTitleInfo->clip_count > 0)
1194  {
1195  bd_clip& clip = m_currentTitleInfo->clips[0];
1196  if (FindStream(StreamId, clip.audio_streams, clip.audio_stream_count) ||
1197  FindStream(StreamId, clip.video_streams, clip.video_stream_count) ||
1198  FindStream(StreamId, clip.ig_streams, clip.ig_stream_count) ||
1199  FindStream(StreamId, clip.pg_streams, clip.pg_stream_count) ||
1200  FindStream(StreamId, clip.sec_audio_streams, clip.sec_audio_stream_count) ||
1201  FindStream(StreamId, clip.sec_video_streams, clip.sec_video_stream_count))
1202  {
1203  return true;
1204  }
1205  }
1206 
1207  return false;
1208 }
1209 
1211 {
1213 }
1214 
1216 {
1217  return m_processState == PROCESS_WAIT;
1218 }
1219 
1221 {
1222  return m_isHDMVNavigation;
1223 }
1224 
1226 {
1227  if (m_ignorePlayerWait)
1228  return;
1229 
1230  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Waiting for player's buffers to drain");
1231  m_playerWait = true;
1232  int count = 0;
1233  while (m_playerWait && count++ < 200)
1234  std::this_thread::sleep_for(10ms);
1235  if (m_playerWait)
1236  {
1237  LOG(VB_GENERAL, LOG_ERR, LOC + "Player wait state was not cleared");
1238  m_playerWait = false;
1239  }
1240 }
1241 
1243 {
1244  m_ignorePlayerWait = Ignore;
1245 }
1246 
1248 {
1249  if (m_bdnav && m_isHDMVNavigation)
1250  {
1251  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Starting from beginning...");
1252  return true; //bd_play(m_bdnav);
1253  }
1254  return true;
1255 }
1256 
1257 bool MythBDBuffer::GetNameAndSerialNum(QString &Name, QString &SerialNum)
1258 {
1259  if (!m_bdnav)
1260  return false;
1261  Name = m_discName;
1262  SerialNum = m_discSerialNumber;
1263  return !SerialNum.isEmpty();
1264 }
1265 
1269 {
1270  int title = GetCurrentTitle();
1272  uint64_t angle = GetCurrentAngle();
1273  if (title >= 0)
1274  State = QString("title:%1,time:%2,angle:%3").arg(title).arg(time.count()).arg(angle);
1275  else
1276  State.clear();
1277  return !State.isEmpty();
1278 }
1279 
1283 {
1284 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
1285  QStringList states = State.split(",", QString::SkipEmptyParts);
1286 #else
1287  QStringList states = State.split(",", Qt::SkipEmptyParts);
1288 #endif
1289  QHash<QString, uint64_t> settings;
1290 
1291  for (const QString& state : states)
1292  {
1293 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
1294  QStringList keyvalue = state.split(":", QString::SkipEmptyParts);
1295 #else
1296  QStringList keyvalue = state.split(":", Qt::SkipEmptyParts);
1297 #endif
1298  if (keyvalue.length() != 2)
1299  {
1300  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString("Invalid BD state: %1 (%2)")
1301  .arg(state, State));
1302  }
1303  else
1304  {
1305  settings[keyvalue[0]] = keyvalue[1].toULongLong();
1306  //LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString( "%1 = %2" ).arg(keyvalue[0]).arg(keyvalue[1]));
1307  }
1308  }
1309 
1310  if (settings.contains("title") && settings.contains("time"))
1311  {
1312  uint32_t title = static_cast<uint32_t>(settings["title"]);
1313  uint64_t time = settings["time"];
1314  uint64_t angle = 0;
1315 
1316  if (settings.contains("angle"))
1317  angle = settings["angle"];
1318 
1319  if (title != static_cast<uint32_t>(m_currentTitle))
1320  SwitchTitle(title);
1321 
1322  SeekInternal(static_cast<long long>(time), SEEK_SET);
1323  SwitchAngle(static_cast<uint>(angle));
1324  return true;
1325  }
1326 
1327  return false;
1328 }
1329 
1330 
1332 {
1333  QMutexLocker lock(&m_overlayLock);
1334 
1335  while (!m_overlayImages.isEmpty())
1336  {
1337  MythBDOverlay *overlay = m_overlayImages.takeFirst();
1338  delete overlay;
1339  overlay = nullptr;
1340  }
1341 
1342  // NOLINTNEXTLINE(modernize-loop-convert)
1343  for (int i = 0; i < m_overlayPlanes.size(); i++)
1344  {
1345  MythBDOverlay*& osd = m_overlayPlanes[i];
1346 
1347  if (osd)
1348  {
1349  delete osd;
1350  osd = nullptr;
1351  }
1352  }
1353 }
1354 
1356 {
1357  QMutexLocker lock(&m_overlayLock);
1358  if (!m_overlayImages.isEmpty())
1359  return m_overlayImages.takeFirst();
1360  return nullptr;
1361 }
1362 
1363 void MythBDBuffer::SubmitOverlay(const bd_overlay_s* const Overlay)
1364 {
1365  if (!Overlay || (Overlay->plane > m_overlayPlanes.size()))
1366  return;
1367 
1368  LOG(VB_PLAYBACK, LOG_DEBUG, QString("--------------------"));
1369  LOG(VB_PLAYBACK, LOG_DEBUG, QString("overlay->cmd = %1, %2")
1370  .arg(Overlay->cmd).arg(Overlay->plane));
1371  LOG(VB_PLAYBACK, LOG_DEBUG, QString("overlay rect = (%1,%2,%3,%4)")
1372  .arg(Overlay->x).arg(Overlay->y).arg(Overlay->w).arg(Overlay->h));
1373  LOG(VB_PLAYBACK, LOG_DEBUG, QString("overlay->pts = %1")
1374  .arg(Overlay->pts));
1375  LOG(VB_PLAYBACK, LOG_DEBUG, QString("update palette = %1")
1376  .arg(Overlay->palette_update_flag ? "yes":"no"));
1377 
1378  MythBDOverlay*& osd = m_overlayPlanes[Overlay->plane];
1379 
1380  switch(Overlay->cmd)
1381  {
1382  case BD_OVERLAY_INIT:
1383  // init overlay plane. Size and position of plane in x,y,w,h
1384  // init overlay plane. Size of plane in w,h
1385  delete osd;
1386  osd = new MythBDOverlay(Overlay);
1387  break;
1388  case BD_OVERLAY_CLOSE:
1389  // close overlay
1390  {
1391  if (osd)
1392  {
1393  delete osd;
1394  osd = nullptr;
1395  }
1396  QMutexLocker lock(&m_overlayLock);
1397  m_overlayImages.append(new MythBDOverlay());
1398  }
1399  break;
1400  /* following events can be processed immediately, but changes
1401  * should not be flushed to display before next FLUSH event
1402  */
1403  case BD_OVERLAY_HIDE: /* overlay is empty and can be hidden */
1404  case BD_OVERLAY_CLEAR: /* clear plane */
1405  if (osd)
1406  osd->Wipe();
1407  break;
1408  case BD_OVERLAY_WIPE: /* clear area (x,y,w,h) */
1409  if (osd)
1410  osd->Wipe(Overlay->x, Overlay->y, Overlay->w, Overlay->h);
1411  break;
1412  case BD_OVERLAY_DRAW: /* draw bitmap (x,y,w,h,img,palette,crop) */
1413  if (osd)
1414  {
1415  const BD_PG_RLE_ELEM *rlep = Overlay->img;
1416  int actual = Overlay->w * Overlay->h;
1417  uint8_t *data = osd->m_image.bits();
1418  data = &data[(Overlay->y * osd->m_image.bytesPerLine()) + Overlay->x];
1419  for (int i = 0; i < actual; i += rlep->len, rlep++)
1420  {
1421  int dst_y = (i / Overlay->w) * osd->m_image.bytesPerLine();
1422  int dst_x = (i % Overlay->w);
1423  memset(data + dst_y + dst_x, rlep->color, rlep->len);
1424  }
1425  osd->SetPalette(Overlay->palette);
1426  }
1427  break;
1428 
1429  case BD_OVERLAY_FLUSH: /* all changes have been done, flush overlay to display at given pts */
1430  if (osd)
1431  {
1432  auto* newOverlay = new MythBDOverlay(*osd);
1433  newOverlay->m_image = osd->m_image.convertToFormat(QImage::Format_ARGB32);
1434  newOverlay->m_pts = Overlay->pts;
1435  QMutexLocker lock(&m_overlayLock);
1436  m_overlayImages.append(newOverlay);
1437  }
1438  break;
1439  default: break;
1440  }
1441 }
1442 
1443 void MythBDBuffer::SubmitARGBOverlay(const bd_argb_overlay_s * const Overlay)
1444 {
1445  if (!Overlay || (Overlay->plane > m_overlayPlanes.size()))
1446  return;
1447 
1448  LOG(VB_PLAYBACK, LOG_DEBUG, QString("--------------------"));
1449  LOG(VB_PLAYBACK, LOG_DEBUG, QString("overlay->cmd,plane = %1, %2")
1450  .arg(Overlay->cmd).arg(Overlay->plane));
1451  LOG(VB_PLAYBACK, LOG_DEBUG, QString("overlay->(x,y,w,h) = %1,%2,%3x%4 - %5")
1452  .arg(Overlay->x).arg(Overlay->y).arg(Overlay->w).arg(Overlay->h).arg(Overlay->stride));
1453  LOG(VB_PLAYBACK, LOG_DEBUG, QString("overlay->pts = %1").arg(Overlay->pts));
1454 
1455  MythBDOverlay*& osd = m_overlayPlanes[Overlay->plane];
1456  switch(Overlay->cmd)
1457  {
1458  case BD_ARGB_OVERLAY_INIT:
1459  /* init overlay plane. Size of plane in w,h */
1460  delete osd;
1461  osd = new MythBDOverlay(Overlay);
1462  break;
1463  case BD_ARGB_OVERLAY_CLOSE:
1464  /* close overlay */
1465  {
1466  if (osd)
1467  {
1468  delete osd;
1469  osd = nullptr;
1470  }
1471  QMutexLocker lock(&m_overlayLock);
1472  m_overlayImages.append(new MythBDOverlay());
1473  }
1474  break;
1475  /* following events can be processed immediately, but changes
1476  * should not be flushed to display before next FLUSH event
1477  */
1478  case BD_ARGB_OVERLAY_DRAW:
1479  if (osd)
1480  {
1481  /* draw image */
1482  uint8_t* data = osd->m_image.bits();
1483  int32_t srcOffset = 0;
1484  int32_t dstOffset = (Overlay->y * osd->m_image.bytesPerLine()) + (Overlay->x * 4);
1485  for (uint16_t y = 0; y < Overlay->h; y++)
1486  {
1487  memcpy(&data[dstOffset], &Overlay->argb[srcOffset], Overlay->w * 4_UZ);
1488  dstOffset += osd->m_image.bytesPerLine();
1489  srcOffset += Overlay->stride;
1490  }
1491  }
1492  break;
1493  case BD_ARGB_OVERLAY_FLUSH:
1494  /* all changes have been done, flush overlay to display at given pts */
1495  if (osd)
1496  {
1497  QMutexLocker lock(&m_overlayLock);
1498  auto* newOverlay = new MythBDOverlay(*osd);
1499  newOverlay->m_pts = Overlay->pts;
1500  m_overlayImages.append(newOverlay);
1501  }
1502  break;
1503  default:
1504  LOG(VB_PLAYBACK, LOG_ERR, QString("Unknown ARGB overlay - %1").arg(Overlay->cmd));
1505  break;
1506  }
1507 }
BD_BLOCK_SIZE
static constexpr int32_t BD_BLOCK_SIZE
Definition: mythbdbuffer.h:14
MythBDBuffer::GetAudioLanguage
int GetAudioLanguage(uint StreamID)
Definition: mythbdbuffer.cpp:891
MythBDBuffer::GetPlaylistInfo
BLURAY_TITLE_INFO * GetPlaylistInfo(uint32_t Index)
Definition: mythbdbuffer.cpp:690
MythBDBuffer::SubmitARGBOverlay
void SubmitARGBOverlay(const bd_argb_overlay_s *Overlay)
Definition: mythbdbuffer.cpp:1443
MythBDBuffer::GetFrameRate
double GetFrameRate(void)
Definition: mythbdbuffer.cpp:872
mythevent.h
iso639_key_to_canonical_key
int iso639_key_to_canonical_key(int iso639_2)
Definition: iso639.cpp:118
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:283
ENO
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:73
ACTION_DOWN
static constexpr const char * ACTION_DOWN
Definition: mythuiactions.h:17
MythBDBuffer::GetReadPosition
long long GetReadPosition(void) const override
Definition: mythbdbuffer.cpp:540
MythBDBuffer::IsHDMVNavigation
bool IsHDMVNavigation(void) const
Definition: mythbdbuffer.cpp:1220
MythBDBuffer::m_firstPlaySupported
bool m_firstPlaySupported
Definition: mythbdbuffer.h:100
MythMediaBuffer::m_readAdjust
long long m_readAdjust
Definition: mythmediabuffer.h:219
MythBDOverlay::m_image
QImage m_image
Definition: mythbdoverlay.h:27
MythBDBuffer::m_cachedTitleInfo
QHash< uint32_t, BLURAY_TITLE_INFO * > m_cachedTitleInfo
Definition: mythbdbuffer.h:133
MythBDBuffer::m_currentPlayitem
int m_currentPlayitem
Definition: mythbdbuffer.h:111
MythOpticalBuffer::MythOpticalState
MythOpticalState
Definition: mythopticalbuffer.h:17
MythBDBuffer::TitleChanged
bool TitleChanged(void)
Definition: mythbdbuffer.cpp:779
MythBDBuffer::GetTotalReadPosition
uint64_t GetTotalReadPosition(void)
Definition: mythbdbuffer.cpp:802
MythBDBuffer::m_tryHDMVNavigation
bool m_tryHDMVNavigation
Definition: mythbdbuffer.h:98
MythOpticalBuffer::IsInMenu
bool IsInMenu(void) const override
Definition: mythopticalbuffer.cpp:9
MythCDROM::kUnknown
@ kUnknown
Definition: mythcdrom.h:28
MythBDBuffer::m_currentTitle
int m_currentTitle
Definition: mythbdbuffer.h:109
MythMediaBuffer::StopReads
void StopReads(void)
Definition: mythmediabuffer.cpp:663
MythBDBuffer::m_timeDiff
int64_t m_timeDiff
Definition: mythbdbuffer.h:132
MythBDBuffer::m_imgHandle
int m_imgHandle
Definition: mythbdbuffer.h:108
MythCoreContext::GetLocale
MythLocale * GetLocale(void) const
Definition: mythcorecontext.cpp:1761
MythBDBuffer::GetOverlay
MythBDOverlay * GetOverlay(void)
Definition: mythbdbuffer.cpp:1355
MythMediaBuffer::m_commsError
bool m_commsError
Definition: mythmediabuffer.h:215
MythBDBuffer::ClickButton
void ClickButton(int64_t Pts, uint16_t X, uint16_t Y)
Definition: mythbdbuffer.cpp:943
mythcdrom.h
MythBDBuffer::m_currentPlaylist
int m_currentPlaylist
Definition: mythbdbuffer.h:110
MythMediaBuffer::m_safeFilename
QString m_safeFilename
Definition: mythmediabuffer.h:181
MythEvent
This class is used as a container for messages.
Definition: mythevent.h:16
BDRead
static int BDRead(void *Handle, void *Buf, int LBA, int NumBlocks)
Definition: mythbdbuffer.cpp:71
MythBDBuffer::m_currentAudioStream
int m_currentAudioStream
Definition: mythbdbuffer.h:113
MythBDBuffer::m_secondaryVideoIsFullscreen
bool m_secondaryVideoIsFullscreen
Definition: mythbdbuffer.h:121
MythBDOverlay::SetPalette
void SetPalette(const BD_PG_PALETTE_ENTRY *Palette)
Definition: mythbdoverlay.cpp:24
MythMediaBuffer::CalcReadAheadThresh
void CalcReadAheadThresh(void)
Calculates m_fillMin, m_fillThreshold, and m_readBlockSize from the estimated effective bitrate of th...
Definition: mythmediabuffer.cpp:345
HandleARGBOverlayCallback
static void HandleARGBOverlayCallback(void *Data, const bd_argb_overlay_s *const Overlay)
Definition: mythbdbuffer.cpp:52
MythBDBuffer::IsInStillFrame
bool IsInStillFrame(void) const override
Definition: mythbdbuffer.cpp:1168
ACTION_0
static constexpr const char * ACTION_0
Definition: mythuiactions.h:4
kMythBufferBD
@ kMythBufferBD
Definition: mythmediabuffer.h:44
MythBDBuffer::m_ignorePlayerWait
bool m_ignorePlayerWait
Definition: mythbdbuffer.h:124
MythBDBuffer::m_stillTime
std::chrono::seconds m_stillTime
Definition: mythbdbuffer.h:128
MythfileClose
int MythfileClose(int FileID)
Definition: mythiowrapper.cpp:205
ACTION_LEFT
static constexpr const char * ACTION_LEFT
Definition: mythuiactions.h:18
MythDate::formatTime
QString formatTime(std::chrono::milliseconds msecs, QString fmt)
Format a milliseconds time value.
Definition: mythdate.cpp:233
MythBDBuffer::GetNumAngles
uint64_t GetNumAngles(void) const
Definition: mythbdbuffer.cpp:797
MythBDBuffer::m_currentSecondaryVideoStream
int m_currentSecondaryVideoStream
Definition: mythbdbuffer.h:117
MythBDOverlay
Definition: mythbdoverlay.h:16
MythBDBuffer::IsReadingBlocked
bool IsReadingBlocked(void)
Definition: mythbdbuffer.cpp:1215
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythMediaBuffer::m_lastError
QString m_lastError
Definition: mythmediabuffer.h:186
is_current_thread
bool is_current_thread(MThread *thread)
Use this to determine if you are in the named thread.
Definition: mthread.cpp:40
MythBDBuffer::GetNumTitles
uint32_t GetNumTitles(void) const
Definition: mythbdbuffer.cpp:593
MythMediaBuffer::m_generalWait
QWaitCondition m_generalWait
Condition to signal that the read ahead thread is running.
Definition: mythmediabuffer.h:237
MythFileOpenRegisterCallback
void MythFileOpenRegisterCallback(const char *Pathname, void *Object, callback_t Func)
Definition: mythiowrapper.cpp:81
MythBDBuffer::Close
void Close(void)
Definition: mythbdbuffer.cpp:94
MythFileRead
ssize_t MythFileRead(int FileID, void *Buffer, size_t Count)
Definition: mythiowrapper.cpp:285
mythdirs.h
mythbdiowrapper.h
MythOpticalBuffer::PROCESS_WAIT
@ PROCESS_WAIT
Definition: mythopticalbuffer.h:21
ACTION_SELECT
static constexpr const char * ACTION_SELECT
Definition: mythuiactions.h:15
ACTION_9
static constexpr const char * ACTION_9
Definition: mythuiactions.h:13
MythBDBuffer::GetNameAndSerialNum
bool GetNameAndSerialNum(QString &Name, QString &SerialNum) override
Definition: mythbdbuffer.cpp:1257
HandleOverlayCallback
static void HandleOverlayCallback(void *Data, const bd_overlay_s *const Overlay)
Definition: mythbdbuffer.cpp:45
MythBDBuffer::m_mainThread
QThread * m_mainThread
Definition: mythbdbuffer.h:140
MythBDBuffer::m_topMenuSupported
bool m_topMenuSupported
Definition: mythbdbuffer.h:99
MythBDBuffer::IsOpen
bool IsOpen(void) const override
Definition: mythbdbuffer.cpp:547
MythBDBuffer::~MythBDBuffer
~MythBDBuffer() override
Definition: mythbdbuffer.cpp:88
LOC
#define LOC
Definition: mythbdbuffer.cpp:43
MythOpticalBuffer::m_discSerialNumber
QString m_discSerialNumber
Definition: mythopticalbuffer.h:28
MythMediaBuffer::m_rawBitrate
uint m_rawBitrate
Definition: mythmediabuffer.h:208
StreamID
Contains listing of PMT Stream ID's for various A/V Stream types.
Definition: mpegtables.h:109
MythBDBuffer::OpenFile
bool OpenFile(const QString &Filename, std::chrono::milliseconds Retry=kDefaultOpenTimeout) override
Opens a bluray device for reading.
Definition: mythbdbuffer.cpp:271
MythBDBuffer::HandleBDEvent
void HandleBDEvent(BD_EVENT &Event)
Definition: mythbdbuffer.cpp:1005
MythBDBuffer::m_isHDMVNavigation
bool m_isHDMVNavigation
Definition: mythbdbuffer.h:97
mythdate.h
MythMediaBuffer::m_readPos
long long m_readPos
Definition: mythmediabuffer.h:165
mythlogging.h
MythLocale::GetCountryCode
QString GetCountryCode() const
Definition: mythlocale.cpp:57
GetConfDir
QString GetConfDir(void)
Definition: mythdirs.cpp:256
ACTION_1
static constexpr const char * ACTION_1
Definition: mythuiactions.h:5
MythBDBuffer::GetChapterStartFrame
uint64_t GetChapterStartFrame(uint32_t Chapter)
Definition: mythbdbuffer.cpp:585
tv_actions.h
Event
Event details.
Definition: zmdefines.h:26
MythBDBuffer::m_currentIGStream
int m_currentIGStream
Definition: mythbdbuffer.h:114
MythBDBuffer::m_currentTitleAngleCount
uint64_t m_currentTitleAngleCount
Definition: mythbdbuffer.h:106
MythBDBuffer::GetChapterStartTimeMs
std::chrono::milliseconds GetChapterStartTimeMs(uint32_t Chapter)
Definition: mythbdbuffer.cpp:567
State
State
Definition: zmserver.h:68
MythMediaBuffer::m_readBlockSize
int m_readBlockSize
Definition: mythmediabuffer.h:212
stringutil.h
MythBDBuffer::m_secondaryAudioEnabled
bool m_secondaryAudioEnabled
Definition: mythbdbuffer.h:119
MythEvent::kUpdateTvProgressEventType
static const Type kUpdateTvProgressEventType
Definition: mythevent.h:81
MythBDBuffer
Definition: mythbdbuffer.h:19
MythBDBuffer::StartFromBeginning
bool StartFromBeginning(void) override
Definition: mythbdbuffer.cpp:1247
MythBDBuffer::UnblockReading
void UnblockReading(void)
Definition: mythbdbuffer.cpp:1210
MythMediaBuffer::m_setSwitchToNext
bool m_setSwitchToNext
Definition: mythmediabuffer.h:207
MythBDBuffer::m_currentPGTextSTStream
int m_currentPGTextSTStream
Definition: mythbdbuffer.h:115
ACTION_SEEKRWND
#define ACTION_SEEKRWND
Definition: tv_actions.h:42
ACTION_8
static constexpr const char * ACTION_8
Definition: mythuiactions.h:12
MythBDInfo::GetNameAndSerialNum
bool GetNameAndSerialNum(QString &Name, QString &SerialNum)
Definition: mythbdinfo.cpp:163
StringUtil::intToPaddedString
QString intToPaddedString(int n, int width=2)
Creates a zero padded string representation of an integer.
Definition: stringutil.h:24
mythlocale.h
MythMediaBuffer::m_numFailures
int m_numFailures
Definition: mythmediabuffer.h:214
sizetliteral.h
MythBDBuffer::m_overlayLock
QMutex m_overlayLock
Definition: mythbdbuffer.h:125
MythBDBuffer::SwitchAngle
bool SwitchAngle(uint Angle)
Definition: mythbdbuffer.cpp:786
iso639_key_to_str3
static QString iso639_key_to_str3(int code)
Definition: iso639.h:44
MythBDBuffer::GetTitleDuration
std::chrono::seconds GetTitleDuration(int Title)
Definition: mythbdbuffer.cpp:609
uint
unsigned int uint
Definition: compat.h:81
ACTION_7
static constexpr const char * ACTION_7
Definition: mythuiactions.h:11
MythBDBuffer::HandleAction
bool HandleAction(const QStringList &Actions, mpeg::chrono::pts Pts) override
Definition: mythbdbuffer.cpp:190
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
MythBDBuffer::BDWaitingForPlayer
bool BDWaitingForPlayer(void) const
Definition: mythbdbuffer.cpp:253
MythBDBuffer::m_playerWait
bool m_playerWait
Definition: mythbdbuffer.h:123
MythBDBuffer::GetNumChapters
uint32_t GetNumChapters(void)
Definition: mythbdbuffer.cpp:552
MythMediaBuffer::m_filename
QString m_filename
Definition: mythmediabuffer.h:184
MythBDBuffer::SkipBDWaitingForPlayer
void SkipBDWaitingForPlayer(void)
Definition: mythbdbuffer.cpp:258
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:911
MythBDBuffer::m_currentTitleLength
mpeg::chrono::pts m_currentTitleLength
Definition: mythbdbuffer.h:103
ACTION_MENUTEXT
#define ACTION_MENUTEXT
Definition: tv_actions.h:82
ACTION_UP
static constexpr const char * ACTION_UP
Definition: mythuiactions.h:16
MythOpticalBuffer::m_inMenu
bool m_inMenu
Definition: mythopticalbuffer.h:26
MythBDBuffer::GetChapterStartTime
std::chrono::seconds GetChapterStartTime(uint32_t Chapter)
Definition: mythbdbuffer.cpp:576
MythCDROM::inspectImage
static ImageType inspectImage(const QString &path)
Definition: mythcdrom.cpp:188
MythBDBuffer::m_currentSecondaryAudioStream
int m_currentSecondaryAudioStream
Definition: mythbdbuffer.h:116
MythBDBuffer::GetTitleInfo
BLURAY_TITLE_INFO * GetTitleInfo(uint32_t Index)
Definition: mythbdbuffer.cpp:668
mythbdbuffer.h
MythBDBuffer::m_titleChanged
bool m_titleChanged
Definition: mythbdbuffer.h:122
MythMediaBuffer::KillReadAheadThread
void KillReadAheadThread(void)
Stops the read-ahead thread, and waits for it to stop.
Definition: mythmediabuffer.cpp:647
MythBDBuffer::UpdateTitleInfo
bool UpdateTitleInfo(void)
Definition: mythbdbuffer.cpp:709
ACTION_4
static constexpr const char * ACTION_4
Definition: mythuiactions.h:8
Buffer
Definition: MythExternControl.h:36
MythOpticalBuffer::m_currentAngle
int m_currentAngle
Definition: mythopticalbuffer.h:25
MythBDBuffer::m_stillMode
int m_stillMode
Definition: mythbdbuffer.h:129
MythBDBuffer::m_currentChapter
int m_currentChapter
Definition: mythbdbuffer.h:112
MythBDBuffer::m_infoLock
QRecursiveMutex m_infoLock
Definition: mythbdbuffer.h:138
ACTION_3
static constexpr const char * ACTION_3
Definition: mythuiactions.h:7
MythBDBuffer::ClearOverlays
void ClearOverlays(void)
Definition: mythbdbuffer.cpp:1331
MythBDBuffer::m_cachedPlaylistInfo
QHash< uint32_t, BLURAY_TITLE_INFO * > m_cachedPlaylistInfo
Definition: mythbdbuffer.h:134
MythOpticalBuffer::m_discName
QString m_discName
Definition: mythopticalbuffer.h:27
ACTION_RIGHT
static constexpr const char * ACTION_RIGHT
Definition: mythuiactions.h:19
MythMediaBuffer::ResetReadAhead
void ResetReadAhead(long long NewInternal)
Restart the read-ahead thread at the 'newinternal' position.
Definition: mythmediabuffer.cpp:569
MythBDBuffer::GetCurrentChapter
uint32_t GetCurrentChapter(void)
Definition: mythbdbuffer.cpp:560
mythcorecontext.h
MythBDBuffer::m_currentTitleInfo
BLURAY_TITLE_INFO * m_currentTitleInfo
Definition: mythbdbuffer.h:104
MythBDBuffer::GetCurrentTime
std::chrono::seconds GetCurrentTime(void) const
Definition: mythbdbuffer.cpp:633
MythBDBuffer::m_secondaryVideoEnabled
bool m_secondaryVideoEnabled
Definition: mythbdbuffer.h:120
Name
Definition: channelsettings.cpp:71
MythBDBuffer::GetDescForPos
void GetDescForPos(QString &Desc)
Definition: mythbdbuffer.cpp:182
MythBDBuffer::GoToMenu
bool GoToMenu(const QString &Menu, mpeg::chrono::pts Pts)
jump to a Blu-ray root or popup menu
Definition: mythbdbuffer.cpp:954
MythBDBuffer::m_pgTextSTEnabled
bool m_pgTextSTEnabled
Definition: mythbdbuffer.h:118
MythBDBuffer::PressButton
void PressButton(int32_t Key, mpeg::chrono::pts Pts)
Definition: mythbdbuffer.cpp:933
ACTION_5
static constexpr const char * ACTION_5
Definition: mythuiactions.h:9
MythBDBuffer::GetSubtitleLanguage
int GetSubtitleLanguage(uint StreamID)
Definition: mythbdbuffer.cpp:913
MythFileOpen
int MythFileOpen(const char *Pathname, int Flags)
Definition: mythiowrapper.cpp:115
BDLogger
static void BDLogger(const char *Message)
Definition: mythbdbuffer.cpp:66
MythBDBuffer::GetCurrentAngle
uint64_t GetCurrentAngle(void) const
Definition: mythbdbuffer.cpp:604
MythBDBuffer::m_numTitles
uint32_t m_numTitles
Definition: mythbdbuffer.h:101
MythOpticalBuffer
Definition: mythopticalbuffer.h:7
GetMythMainWindow
MythMainWindow * GetMythMainWindow(void)
Definition: mythmainwindow.cpp:104
MythBDBuffer::m_currentTime
mpeg::chrono::pts m_currentTime
Definition: mythbdbuffer.h:107
Buf
IFSPoint * Buf
Definition: ifs.cpp:105
mpeg::chrono::pts
std::chrono::duration< CHRONO_TYPE, std::ratio< 1, 90000 > > pts
Definition: mythchrono.h:55
MythBDBuffer::m_mainTitle
uint32_t m_mainTitle
Definition: mythbdbuffer.h:102
MythBDBuffer::GetTitleSize
uint64_t GetTitleSize(void) const
Definition: mythbdbuffer.cpp:623
iso639.h
ISO 639-1 and ISO 639-2 support functions.
MythBDBuffer::m_lastEvent
BD_EVENT m_lastEvent
Definition: mythbdbuffer.h:130
MythBDBuffer::HandleBDEvents
bool HandleBDEvents(void)
Definition: mythbdbuffer.cpp:984
mythuiactions.h
uint16_t
unsigned short uint16_t
Definition: iso6937tables.h:3
MythBDBuffer::IgnoreWaitStates
void IgnoreWaitStates(bool Ignore) override
Definition: mythbdbuffer.cpp:1242
MythBDBuffer::SwitchPlaylist
bool SwitchPlaylist(uint32_t Index)
Definition: mythbdbuffer.cpp:651
MythBDBuffer::m_overlayImages
QList< MythBDOverlay * > m_overlayImages
Definition: mythbdbuffer.h:126
MythMediaBuffer::m_posLock
QReadWriteLock m_posLock
Definition: mythmediabuffer.h:164
MythBDBuffer::SeekInternal
long long SeekInternal(long long Position, int Whence) override
Definition: mythbdbuffer.cpp:119
MythBDBuffer::IsValidStream
bool IsValidStream(uint StreamId)
Definition: mythbdbuffer.cpp:1191
MythBDBuffer::MythBDBuffer
MythBDBuffer(const QString &Filename)
Definition: mythbdbuffer.cpp:79
MythBDBuffer::m_bdnav
BLURAY * m_bdnav
Definition: mythbdbuffer.h:96
MythBDBuffer::SwitchTitle
bool SwitchTitle(uint32_t Index)
Definition: mythbdbuffer.cpp:638
ACTION_2
static constexpr const char * ACTION_2
Definition: mythuiactions.h:6
MythOpticalBuffer::m_processState
MythOpticalState m_processState
Definition: mythopticalbuffer.h:24
ACTION_CHANNELUP
#define ACTION_CHANNELUP
Definition: tv_actions.h:16
MythBDBuffer::GetCurrentTitle
int GetCurrentTitle(void)
Definition: mythbdbuffer.cpp:598
ACTION_CHANNELDOWN
#define ACTION_CHANNELDOWN
Definition: tv_actions.h:17
MythMediaBuffer::m_rwLock
QReadWriteLock m_rwLock
Definition: mythmediabuffer.h:183
MythBDBuffer::WaitForPlayer
void WaitForPlayer(void)
Definition: mythbdbuffer.cpp:1225
MythBDBuffer::m_pendingData
QByteArray m_pendingData
Definition: mythbdbuffer.h:131
FileOpenedCallback
static void FileOpenedCallback(void *Data)
Definition: mythbdbuffer.cpp:59
MythBDBuffer::SafeRead
int SafeRead(void *Buffer, uint Size) override
Definition: mythbdbuffer.cpp:817
iso639_str3_to_key
static int iso639_str3_to_key(const unsigned char *iso639_2)
Definition: iso639.h:59
MythOpticalBuffer::PROCESS_REPROCESS
@ PROCESS_REPROCESS
Definition: mythopticalbuffer.h:20
build_compdb.filename
filename
Definition: build_compdb.py:21
MythMediaBuffer::m_ateof
bool m_ateof
Definition: mythmediabuffer.h:201
MythOpticalBuffer::PROCESS_NORMAL
@ PROCESS_NORMAL
Definition: mythopticalbuffer.h:19
mythmainwindow.h
MythBDBuffer::GetBDStateSnapshot
bool GetBDStateSnapshot(QString &State)
Get a snapshot of the current BD state.
Definition: mythbdbuffer.cpp:1268
MythBDBuffer::GetTotalTimeOfTitle
std::chrono::seconds GetTotalTimeOfTitle(void) const
Definition: mythbdbuffer.cpp:628
MythBDBuffer::RestoreBDStateSnapshot
bool RestoreBDStateSnapshot(const QString &State)
Restore a BD snapshot.
Definition: mythbdbuffer.cpp:1282
MythBDBuffer::m_overlayPlanes
QVector< MythBDOverlay * > m_overlayPlanes
Definition: mythbdbuffer.h:127
MythBDIORedirect
void MythBDIORedirect(void)
Definition: mythbdiowrapper.cpp:144
ACTION_6
static constexpr const char * ACTION_6
Definition: mythuiactions.h:10
MythBDOverlay::Wipe
void Wipe(void)
Definition: mythbdoverlay.cpp:44
MythBDBuffer::SubmitOverlay
void SubmitOverlay(const bd_overlay_s *Overlay)
Definition: mythbdbuffer.cpp:1363
MythFileSeek
off_t MythFileSeek(int FileID, off_t Offset, int Whence)
Definition: mythiowrapper.cpp:243
ACTION_SEEKFFWD
#define ACTION_SEEKFFWD
Definition: tv_actions.h:43
MythBDBuffer::AdjustTimestamp
int64_t AdjustTimestamp(int64_t Timestamp) const
Definition: mythbdbuffer.cpp:809
MythBDBuffer::ProgressUpdate
void ProgressUpdate(void)
Definition: mythbdbuffer.cpp:241
mythbdinfo.h
MythMediaBuffer::m_ignoreReadPos
long long m_ignoreReadPos
Definition: mythmediabuffer.h:168
MythMediaBuffer::m_readAheadRunning
bool m_readAheadRunning
Definition: mythmediabuffer.h:197
MythBDBuffer::FindStream
static const BLURAY_STREAM_INFO * FindStream(uint StreamID, BLURAY_STREAM_INFO *Streams, int StreamCount)
Find the stream with the given ID from an array of streams.
Definition: mythbdbuffer.cpp:1180
MythBDBuffer::m_titlesize
uint64_t m_titlesize
Definition: mythbdbuffer.h:105
mythiowrapper.h
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:897