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