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