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 <fcntl.h>
26 
27 // BluRay
28 #if CONFIG_LIBBLURAY_EXTERNAL
29 #include "libbluray/log_control.h"
30 #include "libbluray/meta_data.h"
31 #include "libbluray/overlay.h"
32 #else
33 #include "util/log_control.h"
34 #include "libbluray/bdnav/meta_data.h"
35 #include "libbluray/decoders/overlay.h"
36 #endif
37 #include "libbluray/keys.h"
38 
39 #define LOC QString("BDBuffer: ")
40 
41 static void HandleOverlayCallback(void *Data, const bd_overlay_s *const Overlay)
42 {
43  auto *bdrb = static_cast<MythBDBuffer*>(Data);
44  if (bdrb)
45  bdrb->SubmitOverlay(Overlay);
46 }
47 
48 static void HandleARGBOverlayCallback(void *Data, const bd_argb_overlay_s *const Overlay)
49 {
50  auto *bdrb = static_cast<MythBDBuffer*>(Data);
51  if (bdrb)
52  bdrb->SubmitARGBOverlay(Overlay);
53 }
54 
55 static void FileOpenedCallback(void* Data)
56 {
57  auto *obj = static_cast<MythBDBuffer*>(Data);
58  if (obj)
59  obj->ProgressUpdate();
60 }
61 
62 static void BDLogger(const char* Message)
63 {
64  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString(Message).trimmed());
65 }
66 
67 static int BDRead(void *Handle, void *Buf, int LBA, int NumBlocks)
68 {
69  if (MythFileSeek(*(static_cast<int*>(Handle)), LBA * 2048LL, SEEK_SET) != -1)
70  return static_cast<int>(MythFileRead(*(static_cast<int*>(Handle)), Buf,
71  static_cast<size_t>(NumBlocks * 2048)) / 2048);
72  return -1;
73 }
74 
75 MythBDBuffer::MythBDBuffer(const QString &Filename)
77  m_overlayPlanes(2, nullptr)
78 {
79  m_tryHDMVNavigation = nullptr != getenv("MYTHTV_HDMV");
80  m_mainThread = QThread::currentThread();
81  MythBDBuffer::OpenFile(Filename);
82 }
83 
85 {
87  Close();
88 }
89 
91 {
92  if (m_bdnav)
93  {
94  m_infoLock.lock();
95  for (auto it = m_cachedTitleInfo.begin(); it !=m_cachedTitleInfo.end(); ++it)
96  bd_free_title_info(it.value());
97  m_cachedTitleInfo.clear();
98  for (auto it = m_cachedPlaylistInfo.begin(); it !=m_cachedPlaylistInfo.end(); ++it)
99  bd_free_title_info(it.value());
100  m_cachedPlaylistInfo.clear();
101  m_infoLock.unlock();
102  bd_close(m_bdnav);
103  m_bdnav = nullptr;
104  }
105 
106  if (m_imgHandle > 0)
107  {
109  m_imgHandle = -1;
110  }
111 
112  ClearOverlays();
113 }
114 
115 long long MythBDBuffer::SeekInternal(long long Position, int Whence)
116 {
117  long long ret = -1;
118 
119  m_posLock.lockForWrite();
120 
121  // Optimize no-op seeks
122  if (m_readAheadRunning &&
123  ((Whence == SEEK_SET && Position == m_readPos) || (Whence == SEEK_CUR && Position == 0)))
124  {
125  ret = m_readPos;
126  m_posLock.unlock();
127  return ret;
128  }
129 
130  // only valid for SEEK_SET & SEEK_CUR
131  long long newposition = (SEEK_SET == Whence) ? Position : m_readPos + Position;
132 
133  // Here we perform a normal seek. When successful we
134  // need to call ResetReadAhead(). A reset means we will
135  // need to refill the buffer, which takes some time.
136  if ((SEEK_END == Whence) || ((SEEK_CUR == Whence) && newposition != 0))
137  {
138  errno = EINVAL;
139  ret = -1;
140  }
141  else
142  {
143  SeekInternal(static_cast<uint64_t>(newposition));
144  m_currentTime = bd_tell_time(m_bdnav);
145  ret = newposition;
146  }
147 
148  if (ret >= 0)
149  {
150  m_readPos = ret;
151  m_ignoreReadPos = -1;
152  if (m_readAheadRunning)
154  m_readAdjust = 0;
155  }
156  else
157  {
158  QString cmd = QString("Seek(%1, %2)").arg(Position)
159  .arg((Whence == SEEK_SET) ? "SEEK_SET" :
160  ((Whence == SEEK_CUR) ?"SEEK_CUR" : "SEEK_END"));
161  LOG(VB_GENERAL, LOG_ERR, LOC + cmd + " Failed" + ENO);
162  }
163 
164  m_posLock.unlock();
165  m_generalWait.wakeAll();
166  return ret;
167 }
168 
169 uint64_t MythBDBuffer::SeekInternal(uint64_t Position)
170 {
171  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Seeking to '%1'").arg(Position));
173  if (m_bdnav)
174  return static_cast<uint64_t>(bd_seek_time(m_bdnav, Position));
175  return 0;
176 }
177 
178 void MythBDBuffer::GetDescForPos(QString &Desc)
179 {
180  if (!m_infoLock.tryLock())
181  return;
182  Desc = tr("Title %1 chapter %2").arg(m_currentTitle).arg(m_currentTitleInfo->chapters->idx);
183  m_infoLock.unlock();
184 }
185 
186 bool MythBDBuffer::HandleAction(const QStringList &Actions, int64_t Pts)
187 {
188  if (!m_isHDMVNavigation)
189  return false;
190 
191  if (Actions.contains(ACTION_MENUTEXT))
192  {
193  PressButton(BD_VK_POPUP, Pts);
194  return true;
195  }
196 
197  if (!IsInMenu())
198  return false;
199 
200  bool handled = true;
201  if (Actions.contains(ACTION_UP) || Actions.contains(ACTION_CHANNELUP))
202  PressButton(BD_VK_UP, Pts);
203  else if (Actions.contains(ACTION_DOWN) || Actions.contains(ACTION_CHANNELDOWN))
204  PressButton(BD_VK_DOWN, Pts);
205  else if (Actions.contains(ACTION_LEFT) || Actions.contains(ACTION_SEEKRWND))
206  PressButton(BD_VK_LEFT, Pts);
207  else if (Actions.contains(ACTION_RIGHT) || Actions.contains(ACTION_SEEKFFWD))
208  PressButton(BD_VK_RIGHT, Pts);
209  else if (Actions.contains(ACTION_0))
210  PressButton(BD_VK_0, Pts);
211  else if (Actions.contains(ACTION_1))
212  PressButton(BD_VK_1, Pts);
213  else if (Actions.contains(ACTION_2))
214  PressButton(BD_VK_2, Pts);
215  else if (Actions.contains(ACTION_3))
216  PressButton(BD_VK_3, Pts);
217  else if (Actions.contains(ACTION_4))
218  PressButton(BD_VK_4, Pts);
219  else if (Actions.contains(ACTION_5))
220  PressButton(BD_VK_5, Pts);
221  else if (Actions.contains(ACTION_6))
222  PressButton(BD_VK_6, Pts);
223  else if (Actions.contains(ACTION_7))
224  PressButton(BD_VK_7, Pts);
225  else if (Actions.contains(ACTION_8))
226  PressButton(BD_VK_8, Pts);
227  else if (Actions.contains(ACTION_9))
228  PressButton(BD_VK_9, Pts);
229  else if (Actions.contains(ACTION_SELECT))
230  PressButton(BD_VK_ENTER, Pts);
231  else
232  handled = false;
233 
234  return handled;
235 }
236 
238 {
239  // This thread check is probably unnecessary as processEvents should
240  // only handle events in the calling thread - and not all threads
242  return;
243 
244  qApp->postEvent(GetMythMainWindow(),
246  qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
247 }
248 
250 {
251  return m_playerWait;
252 }
253 
255 {
256  m_playerWait = false;
257 }
258 
267 bool MythBDBuffer::OpenFile(const QString &Filename, uint /*Retry*/)
268 {
269  m_safeFilename = Filename;
270  m_filename = Filename;
271 
272  // clean path filename
273  QString filename = QDir(QDir::cleanPath(Filename)).canonicalPath();
274  if (filename.isEmpty())
275  {
276  LOG(VB_GENERAL, LOG_ERR, LOC + QString("%1 nonexistent").arg(Filename));
277  filename = Filename;
278  }
280 
281  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Opened MythBDBuffer device at %1")
282  .arg(filename));
283 
284  // Make sure log messages from the Bluray library appear in our logs
285  bd_set_debug_handler(BDLogger);
286  bd_set_debug_mask(DBG_CRIT | DBG_NAV | DBG_BLURAY);
287 
288  // Use our own wrappers for file and directory access
290 
291  // Ask mythiowrapper to update this object on file open progress. Opening
292  // a bluray disc can involve opening several hundred files which can take
293  // several minutes when the disc structure is remote. The callback allows
294  // us to 'kick' the main UI - as the 'please wait' widget is still visible
295  // at this stage
296  MythFileOpenRegisterCallback(filename.toLocal8Bit().data(), this, FileOpenedCallback);
297 
298  QMutexLocker locker(&m_infoLock);
299  m_rwLock.lockForWrite();
300 
301  if (m_bdnav)
302  Close();
303 
304  QString keyfile = QString("%1/KEYDB.cfg").arg(GetConfDir());
305  const char *keyfilepath = keyfile.toLatin1().data();
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(), keyfilepath);
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).arg(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  const char *langpref = gCoreContext->GetSetting("ISO639Language0", "eng").toLatin1().data();
386  QString QScountry = gCoreContext->GetLocale()->GetCountryCode().toLower();
387  const char *country = QScountry.toLatin1().data();
388  bd_set_player_setting_str(m_bdnav, BLURAY_PLAYER_SETTING_AUDIO_LANG, langpref);
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);
391  // Set preferred menu language to the FE guide language
392  bd_set_player_setting_str(m_bdnav, BLURAY_PLAYER_SETTING_MENU_LANG, langpref);
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);
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(QString(keyfilepath)));
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;
451  m_titlesize = 0;
452  m_currentTime = 0;
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 = 0;
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 uint64_t MythBDBuffer::GetChapterStartTimeMs(uint32_t Chapter)
565 {
566  if (Chapter >= GetNumChapters())
567  return 0;
568  QMutexLocker locker(&m_infoLock);
569  return m_currentTitleInfo->chapters[Chapter].start / 90;
570 }
571 
572 uint64_t MythBDBuffer::GetChapterStartTime(uint32_t Chapter)
573 {
574  if (Chapter >= GetNumChapters())
575  return 0;
576  QMutexLocker locker(&m_infoLock);
577  return static_cast<uint64_t>(static_cast<double>(m_currentTitleInfo->chapters[Chapter].start) / 90000.0);
578 }
579 
580 uint64_t MythBDBuffer::GetChapterStartFrame(uint32_t Chapter)
581 {
582  if (Chapter >= GetNumChapters())
583  return 0;
584  QMutexLocker locker(&m_infoLock);
585  return static_cast<uint64_t>((m_currentTitleInfo->chapters[Chapter].start * GetFrameRate()) / 90000.0);
586 }
587 
588 uint32_t MythBDBuffer::GetNumTitles(void) const
589 {
590  return m_numTitles;
591 }
592 
594 {
595  QMutexLocker locker(&m_infoLock);
596  return m_currentTitle;
597 }
598 
599 uint64_t MythBDBuffer::GetCurrentAngle(void) const
600 {
601  return static_cast<uint64_t>(m_currentAngle);
602 }
603 
605 {
606  QMutexLocker locker(&m_infoLock);
607  auto numTitles = GetNumTitles();
608  if (!(numTitles > 0 && Title >= 0 && Title < static_cast<int>(numTitles)))
609  return 0;
610 
611  BLURAY_TITLE_INFO *info = GetTitleInfo(static_cast<uint32_t>(Title));
612  if (!info)
613  return 0;
614 
615  return static_cast<int>(static_cast<double>(info->duration) / 90000.0);
616 }
617 
618 uint64_t MythBDBuffer::GetTitleSize(void) const
619 {
620  return m_titlesize;
621 }
622 
624 {
625  return m_currentTitleLength / 90000;
626 }
627 
628 uint64_t MythBDBuffer::GetCurrentTime(void) const
629 {
630  return m_currentTime / 90000;
631 }
632 
633 bool MythBDBuffer::SwitchTitle(uint32_t Index)
634 {
635  if (!m_bdnav)
636  return false;
637 
638  m_infoLock.lock();
640  m_infoLock.unlock();
641  bd_select_title(m_bdnav, Index);
642 
643  return UpdateTitleInfo();
644 }
645 
646 bool MythBDBuffer::SwitchPlaylist(uint32_t Index)
647 {
648  if (!m_bdnav)
649  return false;
650 
651  LOG(VB_PLAYBACK, LOG_INFO, LOC + "SwitchPlaylist - start");
652 
653  m_infoLock.lock();
655  m_currentTitle = static_cast<int>(bd_get_current_title(m_bdnav));
656  m_infoLock.unlock();
657  bool result = UpdateTitleInfo();
658 
659  LOG(VB_PLAYBACK, LOG_INFO, LOC + "SwitchPlaylist - end");
660  return result;
661 }
662 
663 BLURAY_TITLE_INFO* MythBDBuffer::GetTitleInfo(uint32_t Index)
664 {
665  if (!m_bdnav)
666  return nullptr;
667 
668  QMutexLocker locker(&m_infoLock);
669  if (m_cachedTitleInfo.contains(Index))
670  return m_cachedTitleInfo.value(Index);
671 
672  if (Index > m_numTitles)
673  return nullptr;
674 
675  BLURAY_TITLE_INFO* result = bd_get_title_info(m_bdnav, Index, 0);
676  if (result)
677  {
678  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Found title %1 info").arg(Index));
679  m_cachedTitleInfo.insert(Index,result);
680  return result;
681  }
682  return nullptr;
683 }
684 
685 BLURAY_TITLE_INFO* MythBDBuffer::GetPlaylistInfo(uint32_t Index)
686 {
687  if (!m_bdnav)
688  return nullptr;
689 
690  QMutexLocker locker(&m_infoLock);
691  if (m_cachedPlaylistInfo.contains(Index))
692  return m_cachedPlaylistInfo.value(Index);
693 
694  BLURAY_TITLE_INFO* result = bd_get_playlist_info(m_bdnav, Index, 0);
695  if (result)
696  {
697  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Found playlist %1 info").arg(Index));
698  m_cachedPlaylistInfo.insert(Index,result);
699  return result;
700  }
701  return nullptr;
702 }
703 
705 {
706  QMutexLocker locker(&m_infoLock);
707  if (!m_currentTitleInfo)
708  return false;
709 
710  m_titleChanged = true;
713  m_currentAngle = 0;
714  m_currentPlayitem = 0;
715  m_timeDiff = 0;
716  m_titlesize = bd_get_title_size(m_bdnav);
717  uint32_t chapter_count = GetNumChapters();
718  uint64_t total_msecs = m_currentTitleLength / 90;
719  QString duration = MythFormatTimeMs(total_msecs, "HH:mm:ss.zzz");
720  duration.chop(2); // Chop 2 to show tenths
721  LOG(VB_GENERAL, LOG_INFO, LOC + QString("New title info: Index %1 Playlist: %2 Duration: %3 ""Chapters: %5")
722  .arg(m_currentTitle).arg(m_currentTitleInfo->playlist).arg(duration).arg(chapter_count));
723  LOG(VB_GENERAL, LOG_INFO, LOC + QString("New title info: Clips: %1 Angles: %2 Title Size: %3 Frame Rate %4")
725  .arg(GetFrameRate()));
726 
727  for (uint i = 0; i < chapter_count; i++)
728  {
729  uint64_t framenum = GetChapterStartFrame(i);
730  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Chapter %1 found @ [%2]->%3")
731  .arg(i + 1, 2, 10, QChar('0'))
732  .arg(MythFormatTimeMs(GetChapterStartTimeMs(i), "HH:mm:ss.zzz"))
733  .arg(framenum));
734  }
735 
736  int still = BLURAY_STILL_NONE;
737  int time = 0;
738  if (m_currentTitleInfo->clip_count)
739  {
740  for (uint i = 0; i < m_currentTitleInfo->clip_count; i++)
741  {
742  LOG(VB_PLAYBACK, LOG_INFO, LOC +
743  QString("Clip %1 stillmode %2 stilltime %3 videostreams %4 audiostreams %5 igstreams %6")
744  .arg(i).arg(m_currentTitleInfo->clips[i].still_mode)
745  .arg(m_currentTitleInfo->clips[i].still_time)
746  .arg(m_currentTitleInfo->clips[i].video_stream_count)
747  .arg(m_currentTitleInfo->clips[i].audio_stream_count)
748  .arg(m_currentTitleInfo->clips[i].ig_stream_count));
749  still |= m_currentTitleInfo->clips[i].still_mode;
750  time = m_currentTitleInfo->clips[i].still_time;
751  }
752  }
753 
754  if (m_currentTitleInfo->clip_count > 1 && still != BLURAY_STILL_NONE)
755  {
756  LOG(VB_GENERAL, LOG_WARNING, LOC + "Warning: more than 1 clip, following still "
757  "frame analysis may be wrong");
758  }
759 
760  if (still == BLURAY_STILL_TIME)
761  {
762  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Entering still frame (%1 seconds) UNSUPPORTED").arg(time));
763  bd_read_skip_still(m_bdnav);
764  }
765  else if (still == BLURAY_STILL_INFINITE)
766  {
767  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Entering infinite still frame.");
768  }
769 
770  m_stillMode = still;
771  m_stillTime = time;
772  return true;
773 }
774 
776 {
777  bool ret = m_titleChanged;
778  m_titleChanged = false;
779  return ret;
780 }
781 
783 {
784  if (!m_bdnav)
785  return false;
786 
787  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Switching to Angle '%1'").arg(Angle));
788  bd_seamless_angle_change(m_bdnav, Angle);
789  m_currentAngle = static_cast<int>(Angle);
790  return true;
791 }
792 
793 uint64_t MythBDBuffer::GetNumAngles(void) const
794 {
796 }
797 
799 {
800  if (m_bdnav)
801  return bd_get_title_size(m_bdnav);
802  return 0;
803 }
804 
805 int64_t MythBDBuffer::AdjustTimestamp(int64_t Timestamp) const
806 {
807  int64_t newTimestamp = Timestamp;
808  if ((newTimestamp != AV_NOPTS_VALUE) && (newTimestamp >= m_timeDiff))
809  newTimestamp -= m_timeDiff;
810  return newTimestamp;
811 }
812 
814 {
815  int result = 0;
816  if (m_isHDMVNavigation)
817  {
818  result = HandleBDEvents() ? 0 : -1;
819  while (result == 0)
820  {
821  BD_EVENT event;
822  result = bd_read_ext(m_bdnav, static_cast<unsigned char*>(Buffer),
823  static_cast<int>(Size), &event);
824  if (result == 0)
825  {
826  HandleBDEvent(event);
827  result = HandleBDEvents() ? 0 : -1;
828  }
829  }
830  }
831  else
832  {
834  {
835  MythOpticalState lastState = m_processState;
836 
838  result = bd_read(m_bdnav, static_cast<unsigned char*>(Buffer), static_cast<int>(Size));
839 
840  HandleBDEvents();
841 
842  if (m_processState == PROCESS_WAIT && lastState == PROCESS_NORMAL)
843  {
844  // We're waiting for the decoder to drain its buffers
845  // so don't give it any more data just yet.
846  m_pendingData = QByteArray(static_cast<const char*>(Buffer), result);
847  result = 0;
848  }
849  else
850  if (m_processState == PROCESS_NORMAL && lastState == PROCESS_REPROCESS)
851  {
852  // The decoder has finished draining its buffers so give
853  // it that last block of data we read
854  result = m_pendingData.size();
855  memcpy(Buffer, m_pendingData.constData(), static_cast<size_t>(result));
856  m_pendingData.clear();
857  }
858  }
859  }
860 
861  if (result < 0)
862  StopReads();
863 
864  m_currentTime = bd_tell_time(m_bdnav);
865  return result;
866 }
867 
869 {
870  QMutexLocker locker(&m_infoLock);
872  {
873  switch (m_currentTitleInfo->clips->video_streams->rate)
874  {
875  case BLURAY_VIDEO_RATE_24000_1001: return 23.97;
876  case BLURAY_VIDEO_RATE_24: return 24.00;
877  case BLURAY_VIDEO_RATE_25: return 25.00;
878  case BLURAY_VIDEO_RATE_30000_1001: return 29.97;
879  case BLURAY_VIDEO_RATE_50: return 50.00;
880  case BLURAY_VIDEO_RATE_60000_1001: return 59.94;
881  default: break;
882  }
883  }
884  return 0;
885 }
886 
888 {
889  QMutexLocker locker(&m_infoLock);
890 
891  int code = iso639_str3_to_key("und");
892 
893  if (m_currentTitleInfo && m_currentTitleInfo->clip_count > 0)
894  {
895  bd_clip& clip = m_currentTitleInfo->clips[0];
896  const BLURAY_STREAM_INFO* stream = FindStream(StreamID, clip.audio_streams, clip.audio_stream_count);
897  if (stream)
898  {
899  const uint8_t* lang = stream->lang;
900  code = iso639_key_to_canonical_key((lang[0] << 16) | (lang[1] << 8) | lang[2]);
901  }
902  }
903 
904  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Audio Lang: 0x%1 Code: %2")
905  .arg(code, 3, 16).arg(iso639_key_to_str3(code)));
906  return code;
907 }
908 
910 {
911  QMutexLocker locker(&m_infoLock);
912  int code = iso639_str3_to_key("und");
913  if (m_currentTitleInfo && m_currentTitleInfo->clip_count > 0)
914  {
915  bd_clip& clip = m_currentTitleInfo->clips[0];
916  const BLURAY_STREAM_INFO* stream = FindStream(StreamID, clip.pg_streams, clip.pg_stream_count);
917  if (stream)
918  {
919  const uint8_t* lang = stream->lang;
920  code = iso639_key_to_canonical_key((lang[0]<<16)|(lang[1]<<8)|lang[2]);
921  }
922  }
923 
924  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Subtitle Lang: 0x%1 Code: %2")
925  .arg(code, 3, 16).arg(iso639_key_to_str3(code)));
926  return code;
927 }
928 
929 void MythBDBuffer::PressButton(int32_t Key, int64_t Pts)
930 {
931  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Key %1 (pts %2)").arg(Key).arg(Pts));
932  // HACK for still frame menu navigation
933  Pts = 1;
934  if (!m_bdnav || Pts <= 0 || Key < 0)
935  return;
936  bd_user_input(m_bdnav, Pts, static_cast<uint32_t>(Key));
937 }
938 
940 {
941  if (!m_bdnav)
942  return;
943  if (Pts <= 0 || X == 0 || Y == 0)
944  return;
945  bd_mouse_select(m_bdnav, Pts, X, Y);
946 }
947 
950 bool MythBDBuffer::GoToMenu(const QString &Menu, int64_t Pts)
951 {
952  if (!m_isHDMVNavigation || Pts < 0)
953  return false;
954 
955  if (!m_topMenuSupported)
956  {
957  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Top Menu not supported");
958  return false;
959  }
960 
961  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("GoToMenu %1").arg(Menu));
962 
963  if (Menu.compare("root") == 0)
964  {
965  if (bd_menu_call(m_bdnav, Pts))
966  {
967  LOG(VB_PLAYBACK, LOG_INFO, LOC +QString("Invoked Top Menu (pts %1)").arg(Pts));
968  return true;
969  }
970  }
971  else if (Menu.compare("popup") == 0)
972  {
973  PressButton(BD_VK_POPUP, Pts);
974  return true;
975  }
976 
977  return false;
978 }
979 
981 {
983  {
985  {
987  // HandleBDEvent will change the process state
988  // if it needs to so don't do it here.
989  }
990 
991  while (m_processState == PROCESS_NORMAL && bd_get_event(m_bdnav, &m_lastEvent))
992  {
994  if (m_lastEvent.event == BD_EVENT_NONE || m_lastEvent.event == BD_EVENT_ERROR)
995  return false;
996  }
997  }
998  return true;
999 }
1000 
1002 {
1003  switch (Event.event) {
1004  case BD_EVENT_NONE:
1005  break;
1006  case BD_EVENT_ERROR:
1007  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_ERROR %1").arg(Event.param));
1008  break;
1009  case BD_EVENT_ENCRYPTED:
1010  LOG(VB_GENERAL, LOG_ERR, LOC + "EVENT_ENCRYPTED, playback will fail.");
1011  break;
1012 
1013  /* current playback position */
1014 
1015  case BD_EVENT_ANGLE:
1016  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_ANGLE %1").arg(Event.param));
1017  m_currentAngle = static_cast<int>(Event.param);
1018  break;
1019  case BD_EVENT_TITLE:
1020  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_TITLE %1 (old %2)")
1021  .arg(Event.param).arg(m_currentTitle));
1022  m_currentTitle = static_cast<int>(Event.param);
1023  break;
1024  case BD_EVENT_END_OF_TITLE:
1025  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_END_OF_TITLE %1").arg(m_currentTitle));
1026  WaitForPlayer();
1027  break;
1028  case BD_EVENT_PLAYLIST:
1029  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_PLAYLIST %1 (old %2)")
1030  .arg(Event.param).arg(m_currentPlaylist));
1031  m_currentPlaylist = static_cast<int>(Event.param);
1032  m_timeDiff = 0;
1033  m_currentPlayitem = 0;
1034  SwitchPlaylist(static_cast<uint32_t>(m_currentPlaylist));
1035  break;
1036  case BD_EVENT_PLAYITEM:
1037  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_PLAYITEM %1").arg(Event.param));
1038  {
1039  if (m_currentPlayitem != static_cast<int>(Event.param))
1040  {
1041  auto out = static_cast<int64_t>(m_currentTitleInfo->clips[m_currentPlayitem].out_time);
1042  auto in = static_cast<int64_t>(m_currentTitleInfo->clips[Event.param].in_time);
1043  int64_t diff = in - out;
1044  if (diff != 0 && m_processState == PROCESS_NORMAL)
1045  {
1046  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("PTS discontinuity - waiting for decoder: this %1, last %2, diff %3")
1047  .arg(in).arg(out).arg(diff));
1049  break;
1050  }
1051 
1052  m_timeDiff += diff;
1054  m_currentPlayitem = static_cast<int>(Event.param);
1055  }
1056  }
1057  break;
1058  case BD_EVENT_CHAPTER:
1059  // N.B. event chapter numbering 1...N, chapter seeks etc 0...
1060  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_CHAPTER %1").arg(Event.param));
1061  m_currentChapter = static_cast<int>(Event.param);
1062  break;
1063  case BD_EVENT_PLAYMARK:
1064  /* playmark reached */
1065  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_PLAYMARK"));
1066  break;
1067 
1068  /* playback control */
1069  case BD_EVENT_PLAYLIST_STOP:
1070  /* HDMV VM or JVM stopped playlist playback. Flush all buffers. */
1071  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ToDo EVENT_PLAYLIST_STOP %1")
1072  .arg(Event.param));
1073  break;
1074 
1075  case BD_EVENT_STILL:
1076  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_STILL %1").arg(Event.param));
1077  break;
1078  case BD_EVENT_STILL_TIME:
1079  // we use the clip information to determine the still frame status
1080  // sleep a little
1081  usleep(10000);
1082  break;
1083  case BD_EVENT_SEEK:
1084  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_SEEK"));
1085  break;
1086 
1087  /* stream selection */
1088 
1089  case BD_EVENT_AUDIO_STREAM:
1090  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_AUDIO_STREAM %1").arg(Event.param));
1091  m_currentAudioStream = static_cast<int>(Event.param);
1092  break;
1093  case BD_EVENT_IG_STREAM:
1094  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_IG_STREAM %1").arg(Event.param));
1095  m_currentIGStream = static_cast<int>(Event.param);
1096  break;
1097  case BD_EVENT_PG_TEXTST_STREAM:
1098  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_PG_TEXTST_STREAM %1").arg(Event.param));
1099  m_currentPGTextSTStream = static_cast<int>(Event.param);
1100  break;
1101  case BD_EVENT_SECONDARY_AUDIO_STREAM:
1102  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_SECONDARY_AUDIO_STREAM %1").arg(Event.param));
1103  m_currentSecondaryAudioStream = static_cast<int>(Event.param);
1104  break;
1105  case BD_EVENT_SECONDARY_VIDEO_STREAM:
1106  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_SECONDARY_VIDEO_STREAM %1").arg(Event.param));
1107  m_currentSecondaryVideoStream = static_cast<int>(Event.param);
1108  break;
1109 
1110  case BD_EVENT_PG_TEXTST:
1111  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_PG_TEXTST %1")
1112  .arg(Event.param ? "enable" : "disable"));
1113  m_pgTextSTEnabled = (Event.param != 0U);
1114  break;
1115  case BD_EVENT_SECONDARY_AUDIO:
1116  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_SECONDARY_AUDIO %1")
1117  .arg(Event.param ? "enable" : "disable"));
1118  m_secondaryAudioEnabled = (Event.param != 0U);
1119  break;
1120  case BD_EVENT_SECONDARY_VIDEO:
1121  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_SECONDARY_VIDEO %1")
1122  .arg(Event.param ? "enable" : "disable"));
1123  m_secondaryVideoEnabled = (Event.param != 0U);
1124  break;
1125  case BD_EVENT_SECONDARY_VIDEO_SIZE:
1126  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_SECONDARY_VIDEO_SIZE %1")
1127  .arg(Event.param==0 ? "PIP" : "fullscreen"));
1128  m_secondaryVideoIsFullscreen = (Event.param != 0U);
1129  break;
1130 
1131  /* status */
1132  case BD_EVENT_IDLE:
1133  /* Nothing to do. Playlist is not playing, but title applet is running.
1134  * Application should not call bd_read*() immediately again to avoid busy loop. */
1135  usleep(40000);
1136  break;
1137 
1138  case BD_EVENT_MENU:
1139  /* Interactive menu visible */
1140  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("EVENT_MENU %1")
1141  .arg(Event.param==0 ? "no" : "yes"));
1142  m_inMenu = (Event.param == 1);
1143  break;
1144 
1145  case BD_EVENT_KEY_INTEREST_TABLE:
1146  /* BD-J key interest table changed */
1147  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ToDo EVENT_KEY_INTEREST_TABLE %1")
1148  .arg(Event.param));
1149  break;
1150 
1151  case BD_EVENT_UO_MASK_CHANGED:
1152  /* User operations mask was changed */
1153  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ToDo EVENT_UO_MASK_CHANGED %1")
1154  .arg(Event.param));
1155  break;
1156 
1157  default:
1158  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString("Unknown Event! %1 %2")
1159  .arg(Event.event).arg(Event.param));
1160  break;
1161  }
1162 }
1163 
1165 {
1166  return m_stillTime > 0 && m_stillMode != BLURAY_STILL_NONE;
1167 }
1168 
1176 const BLURAY_STREAM_INFO* MythBDBuffer::FindStream(uint StreamID,
1177  BLURAY_STREAM_INFO* Streams,
1178  int StreamCount)
1179 {
1180  const BLURAY_STREAM_INFO* stream = nullptr;
1181  for (int i = 0; i < StreamCount && !stream; i++)
1182  if (Streams[i].pid == StreamID)
1183  stream = &Streams[i];
1184  return stream;
1185 }
1186 
1188 {
1189  if (m_currentTitleInfo && m_currentTitleInfo->clip_count > 0)
1190  {
1191  bd_clip& clip = m_currentTitleInfo->clips[0];
1192  if (FindStream(StreamId, clip.audio_streams, clip.audio_stream_count) ||
1193  FindStream(StreamId, clip.video_streams, clip.video_stream_count) ||
1194  FindStream(StreamId, clip.ig_streams, clip.ig_stream_count) ||
1195  FindStream(StreamId, clip.pg_streams, clip.pg_stream_count) ||
1196  FindStream(StreamId, clip.sec_audio_streams, clip.sec_audio_stream_count) ||
1197  FindStream(StreamId, clip.sec_video_streams, clip.sec_video_stream_count))
1198  {
1199  return true;
1200  }
1201  }
1202 
1203  return false;
1204 }
1205 
1207 {
1209 }
1210 
1212 {
1213  return m_processState == PROCESS_WAIT;
1214 }
1215 
1217 {
1218  return m_isHDMVNavigation;
1219 }
1220 
1222 {
1223  if (m_ignorePlayerWait)
1224  return;
1225 
1226  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Waiting for player's buffers to drain");
1227  m_playerWait = true;
1228  int count = 0;
1229  while (m_playerWait && count++ < 200)
1230  usleep(10000);
1231  if (m_playerWait)
1232  {
1233  LOG(VB_GENERAL, LOG_ERR, LOC + "Player wait state was not cleared");
1234  m_playerWait = false;
1235  }
1236 }
1237 
1239 {
1240  m_ignorePlayerWait = Ignore;
1241 }
1242 
1244 {
1245  if (m_bdnav && m_isHDMVNavigation)
1246  {
1247  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Starting from beginning...");
1248  return true; //bd_play(m_bdnav);
1249  }
1250  return true;
1251 }
1252 
1253 bool MythBDBuffer::GetNameAndSerialNum(QString &Name, QString &SerialNum)
1254 {
1255  if (!m_bdnav)
1256  return false;
1257  Name = m_discName;
1258  SerialNum = m_discSerialNumber;
1259  return !SerialNum.isEmpty();
1260 }
1261 
1265 {
1266  int title = GetCurrentTitle();
1267  uint64_t time = m_currentTime;
1268  uint64_t angle = GetCurrentAngle();
1269  if (title >= 0)
1270  State = QString("title:%1,time:%2,angle:%3").arg(title).arg(time).arg(angle);
1271  else
1272  State.clear();
1273  return !State.isEmpty();
1274 }
1275 
1279 {
1280 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
1281  QStringList states = State.split(",", QString::SkipEmptyParts);
1282 #else
1283  QStringList states = State.split(",", Qt::SkipEmptyParts);
1284 #endif
1285  QHash<QString, uint64_t> settings;
1286 
1287  for (const QString& state : states)
1288  {
1289 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
1290  QStringList keyvalue = state.split(":", QString::SkipEmptyParts);
1291 #else
1292  QStringList keyvalue = state.split(":", Qt::SkipEmptyParts);
1293 #endif
1294  if (keyvalue.length() != 2)
1295  {
1296  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString("Invalid BD state: %1 (%2)")
1297  .arg(state).arg(State));
1298  }
1299  else
1300  {
1301  settings[keyvalue[0]] = keyvalue[1].toULongLong();
1302  //LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString( "%1 = %2" ).arg(keyvalue[0]).arg(keyvalue[1]));
1303  }
1304  }
1305 
1306  if (settings.contains("title") && settings.contains("time"))
1307  {
1308  uint32_t title = static_cast<uint32_t>(settings["title"]);
1309  uint64_t time = settings["time"];
1310  uint64_t angle = 0;
1311 
1312  if (settings.contains("angle"))
1313  angle = settings["angle"];
1314 
1315  if (title != static_cast<uint32_t>(m_currentTitle))
1316  SwitchTitle(title);
1317 
1318  SeekInternal(static_cast<long long>(time), SEEK_SET);
1319  SwitchAngle(static_cast<uint>(angle));
1320  return true;
1321  }
1322 
1323  return false;
1324 }
1325 
1326 
1328 {
1329  QMutexLocker lock(&m_overlayLock);
1330 
1331  while (!m_overlayImages.isEmpty())
1332  {
1333  MythBDOverlay *overlay = m_overlayImages.takeFirst();
1334  delete overlay;
1335  overlay = nullptr;
1336  }
1337 
1338  // NOLINTNEXTLINE(modernize-loop-convert)
1339  for (int i = 0; i < m_overlayPlanes.size(); i++)
1340  {
1341  MythBDOverlay*& osd = m_overlayPlanes[i];
1342 
1343  if (osd)
1344  {
1345  delete osd;
1346  osd = nullptr;
1347  }
1348  }
1349 }
1350 
1352 {
1353  QMutexLocker lock(&m_overlayLock);
1354  if (!m_overlayImages.isEmpty())
1355  return m_overlayImages.takeFirst();
1356  return nullptr;
1357 }
1358 
1359 void MythBDBuffer::SubmitOverlay(const bd_overlay_s* const Overlay)
1360 {
1361  if (!Overlay || (Overlay && (Overlay->plane > m_overlayPlanes.size())))
1362  return;
1363 
1364  LOG(VB_PLAYBACK, LOG_DEBUG, QString("--------------------"));
1365  LOG(VB_PLAYBACK, LOG_DEBUG, QString("overlay->cmd = %1, %2")
1366  .arg(Overlay->cmd).arg(Overlay->plane));
1367  LOG(VB_PLAYBACK, LOG_DEBUG, QString("overlay rect = (%1,%2,%3,%4)")
1368  .arg(Overlay->x).arg(Overlay->y).arg(Overlay->w).arg(Overlay->h));
1369  LOG(VB_PLAYBACK, LOG_DEBUG, QString("overlay->pts = %1")
1370  .arg(Overlay->pts));
1371  LOG(VB_PLAYBACK, LOG_DEBUG, QString("update palette = %1")
1372  .arg(Overlay->palette_update_flag ? "yes":"no"));
1373 
1374  MythBDOverlay*& osd = m_overlayPlanes[Overlay->plane];
1375 
1376  switch(Overlay->cmd)
1377  {
1378  case BD_OVERLAY_INIT:
1379  // init overlay plane. Size and position of plane in x,y,w,h
1380  // init overlay plane. Size of plane in w,h
1381  delete osd;
1382  osd = new MythBDOverlay(Overlay);
1383  break;
1384  case BD_OVERLAY_CLOSE:
1385  // close overlay
1386  {
1387  if (osd)
1388  {
1389  delete osd;
1390  osd = nullptr;
1391  }
1392  QMutexLocker lock(&m_overlayLock);
1393  m_overlayImages.append(new MythBDOverlay());
1394  }
1395  break;
1396  /* following events can be processed immediately, but changes
1397  * should not be flushed to display before next FLUSH event
1398  */
1399  case BD_OVERLAY_HIDE: /* overlay is empty and can be hidden */
1400  case BD_OVERLAY_CLEAR: /* clear plane */
1401  if (osd)
1402  osd->Wipe();
1403  break;
1404  case BD_OVERLAY_WIPE: /* clear area (x,y,w,h) */
1405  if (osd)
1406  osd->Wipe(Overlay->x, Overlay->y, Overlay->w, Overlay->h);
1407  break;
1408  case BD_OVERLAY_DRAW: /* draw bitmap (x,y,w,h,img,palette,crop) */
1409  if (osd)
1410  {
1411  const BD_PG_RLE_ELEM *rlep = Overlay->img;
1412  int actual = Overlay->w * Overlay->h;
1413  uint8_t *data = osd->m_image.bits();
1414  data = &data[(Overlay->y * osd->m_image.bytesPerLine()) + Overlay->x];
1415  for (int i = 0; i < actual; i += rlep->len, rlep++)
1416  {
1417  int dst_y = (i / Overlay->w) * osd->m_image.bytesPerLine();
1418  int dst_x = (i % Overlay->w);
1419  memset(data + dst_y + dst_x, rlep->color, rlep->len);
1420  }
1421  osd->SetPalette(Overlay->palette);
1422  }
1423  break;
1424 
1425  case BD_OVERLAY_FLUSH: /* all changes have been done, flush overlay to display at given pts */
1426  if (osd)
1427  {
1428  auto* newOverlay = new MythBDOverlay(*osd);
1429  newOverlay->m_image = osd->m_image.convertToFormat(QImage::Format_ARGB32);
1430  newOverlay->m_pts = Overlay->pts;
1431  QMutexLocker lock(&m_overlayLock);
1432  m_overlayImages.append(newOverlay);
1433  }
1434  break;
1435  default: break;
1436  }
1437 }
1438 
1439 void MythBDBuffer::SubmitARGBOverlay(const bd_argb_overlay_s * const Overlay)
1440 {
1441  if (!Overlay || (Overlay && (Overlay->plane > m_overlayPlanes.size())))
1442  return;
1443 
1444  LOG(VB_PLAYBACK, LOG_DEBUG, QString("--------------------"));
1445  LOG(VB_PLAYBACK, LOG_DEBUG, QString("overlay->cmd,plane = %1, %2")
1446  .arg(Overlay->cmd).arg(Overlay->plane));
1447  LOG(VB_PLAYBACK, LOG_DEBUG, QString("overlay->(x,y,w,h) = %1,%2,%3x%4 - %5")
1448  .arg(Overlay->x).arg(Overlay->y).arg(Overlay->w).arg(Overlay->h).arg(Overlay->stride));
1449  LOG(VB_PLAYBACK, LOG_DEBUG, QString("overlay->pts = %1").arg(Overlay->pts));
1450 
1451  MythBDOverlay*& osd = m_overlayPlanes[Overlay->plane];
1452  switch(Overlay->cmd)
1453  {
1454  case BD_ARGB_OVERLAY_INIT:
1455  /* init overlay plane. Size of plane in w,h */
1456  delete osd;
1457  osd = new MythBDOverlay(Overlay);
1458  break;
1459  case BD_ARGB_OVERLAY_CLOSE:
1460  /* close overlay */
1461  {
1462  if (osd)
1463  {
1464  delete osd;
1465  osd = nullptr;
1466  }
1467  QMutexLocker lock(&m_overlayLock);
1468  m_overlayImages.append(new MythBDOverlay());
1469  }
1470  break;
1471  /* following events can be processed immediately, but changes
1472  * should not be flushed to display before next FLUSH event
1473  */
1474  case BD_ARGB_OVERLAY_DRAW:
1475  if (osd)
1476  {
1477  /* draw image */
1478  uint8_t* data = osd->m_image.bits();
1479  int32_t srcOffset = 0;
1480  int32_t dstOffset = (Overlay->y * osd->m_image.bytesPerLine()) + (Overlay->x * 4);
1481  for (uint16_t y = 0; y < Overlay->h; y++)
1482  {
1483  memcpy(&data[dstOffset], &Overlay->argb[srcOffset], Overlay->w * 4);
1484  dstOffset += osd->m_image.bytesPerLine();
1485  srcOffset += Overlay->stride;
1486  }
1487  }
1488  break;
1489  case BD_ARGB_OVERLAY_FLUSH:
1490  /* all changes have been done, flush overlay to display at given pts */
1491  if (osd)
1492  {
1493  QMutexLocker lock(&m_overlayLock);
1494  auto* newOverlay = new MythBDOverlay(*osd);
1495  newOverlay->m_pts = Overlay->pts;
1496  m_overlayImages.append(newOverlay);
1497  }
1498  break;
1499  default:
1500  LOG(VB_PLAYBACK, LOG_ERR, QString("Unknown ARGB overlay - %1").arg(Overlay->cmd));
1501  break;
1502  }
1503 }
MythFormatTimeMs
QString MythFormatTimeMs(int msecs, const QString &fmt)
Format a milliseconds time value.
Definition: mythmiscutil.cpp:1232
MythBDBuffer::GetAudioLanguage
int GetAudioLanguage(uint StreamID)
Definition: mythbdbuffer.cpp:887
MythBDBuffer::GetPlaylistInfo
BLURAY_TITLE_INFO * GetPlaylistInfo(uint32_t Index)
Definition: mythbdbuffer.cpp:685
MythBDBuffer::SubmitARGBOverlay
void SubmitARGBOverlay(const bd_argb_overlay_s *Overlay)
Definition: mythbdbuffer.cpp:1439
ACTION_UP
#define ACTION_UP
Definition: mythuiactions.h:16
MythBDBuffer::GetFrameRate
double GetFrameRate(void)
Definition: mythbdbuffer.cpp:868
mythevent.h
iso639_key_to_canonical_key
int iso639_key_to_canonical_key(int iso639_2)
Definition: iso639.cpp:121
ACTION_3
#define ACTION_3
Definition: mythuiactions.h:7
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:1216
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:217
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:18
MythBDBuffer::TitleChanged
bool TitleChanged(void)
Definition: mythbdbuffer.cpp:775
MythBDBuffer::GetTotalReadPosition
uint64_t GetTotalReadPosition(void)
Definition: mythbdbuffer.cpp:798
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::GetChapterStartTime
uint64_t GetChapterStartTime(uint32_t Chapter)
Definition: mythbdbuffer.cpp:572
MythBDBuffer::m_currentTitle
int m_currentTitle
Definition: mythbdbuffer.h:110
title
QString title
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:633
MythMediaBuffer::StopReads
void StopReads(void)
Definition: mythmediabuffer.cpp:686
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:1772
MythBDBuffer::GetOverlay
MythBDOverlay * GetOverlay(void)
Definition: mythbdbuffer.cpp:1351
MythBDBuffer::m_stillTime
int m_stillTime
Definition: mythbdbuffer.h:129
MythMediaBuffer::m_commsError
bool m_commsError
Definition: mythmediabuffer.h:213
MythBDBuffer::ClickButton
void ClickButton(int64_t Pts, uint16_t X, uint16_t Y)
Definition: mythbdbuffer.cpp:939
mythcdrom.h
MythBDBuffer::m_currentPlaylist
int m_currentPlaylist
Definition: mythbdbuffer.h:111
MythMediaBuffer::m_safeFilename
QString m_safeFilename
Definition: mythmediabuffer.h:179
MythEvent
This class is used as a container for messages.
Definition: mythevent.h:17
BDRead
static int BDRead(void *Handle, void *Buf, int LBA, int NumBlocks)
Definition: mythbdbuffer.cpp:67
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:368
HandleARGBOverlayCallback
static void HandleARGBOverlayCallback(void *Data, const bd_argb_overlay_s *const Overlay)
Definition: mythbdbuffer.cpp:48
MythBDBuffer::IsInStillFrame
bool IsInStillFrame(void) const override
Definition: mythbdbuffer.cpp:1164
kMythBufferBD
@ kMythBufferBD
Definition: mythmediabuffer.h:43
MythBDBuffer::m_ignorePlayerWait
bool m_ignorePlayerWait
Definition: mythbdbuffer.h:125
arg
arg(title).arg(filename).arg(doDelete))
MythfileClose
int MythfileClose(int FileID)
Definition: mythiowrapper.cpp:202
ACTION_2
#define ACTION_2
Definition: mythuiactions.h:6
MythBDBuffer::GetNumAngles
uint64_t GetNumAngles(void) const
Definition: mythbdbuffer.cpp:793
MythBDBuffer::m_currentSecondaryVideoStream
int m_currentSecondaryVideoStream
Definition: mythbdbuffer.h:118
MythBDOverlay
Definition: mythbdoverlay.h:19
MythBDBuffer::GoToMenu
bool GoToMenu(const QString &Menu, int64_t Pts)
jump to a Blu-ray root or popup menu
Definition: mythbdbuffer.cpp:950
MythBDBuffer::IsReadingBlocked
bool IsReadingBlocked(void)
Definition: mythbdbuffer.cpp:1211
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythMediaBuffer::m_lastError
QString m_lastError
Definition: mythmediabuffer.h:184
is_current_thread
bool is_current_thread(MThread *thread)
Use this to determine if you are in the named thread.
Definition: mthread.cpp:41
MythBDBuffer::GetNumTitles
uint32_t GetNumTitles(void) const
Definition: mythbdbuffer.cpp:588
MythMediaBuffer::m_generalWait
QWaitCondition m_generalWait
Condition to signal that the read ahead thread is running.
Definition: mythmediabuffer.h:235
MythFileOpenRegisterCallback
void MythFileOpenRegisterCallback(const char *Pathname, void *Object, callback_t Func)
Definition: mythiowrapper.cpp:78
MythBDBuffer::Close
void Close(void)
Definition: mythbdbuffer.cpp:90
MythFileRead
ssize_t MythFileRead(int FileID, void *Buffer, size_t Count)
Definition: mythiowrapper.cpp:282
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:1253
HandleOverlayCallback
static void HandleOverlayCallback(void *Data, const bd_overlay_s *const Overlay)
Definition: mythbdbuffer.cpp:41
MythBDBuffer::m_mainThread
QThread * m_mainThread
Definition: mythbdbuffer.h:137
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:84
LOC
#define LOC
Definition: mythbdbuffer.cpp:39
MythOpticalBuffer::m_discSerialNumber
QString m_discSerialNumber
Definition: mythopticalbuffer.h:28
MythMediaBuffer::m_rawBitrate
uint m_rawBitrate
Definition: mythmediabuffer.h:206
StreamID
Contains listing of PMT Stream ID's for various A/V Stream types.
Definition: mpegtables.h:110
MythBDBuffer::HandleBDEvent
void HandleBDEvent(BD_EVENT &Event)
Definition: mythbdbuffer.cpp:1001
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:163
mythlogging.h
MythLocale::GetCountryCode
QString GetCountryCode() const
Definition: mythlocale.cpp:58
GetConfDir
QString GetConfDir(void)
Definition: mythdirs.cpp:224
MythBDBuffer::GetChapterStartFrame
uint64_t GetChapterStartFrame(uint32_t Chapter)
Definition: mythbdbuffer.cpp:580
tv_actions.h
ACTION_RIGHT
#define ACTION_RIGHT
Definition: mythuiactions.h:19
Event
Event details.
Definition: zmdefines.h:27
MythBDBuffer::m_currentIGStream
int m_currentIGStream
Definition: mythbdbuffer.h:115
MythBDBuffer::m_currentTitleAngleCount
uint64_t m_currentTitleAngleCount
Definition: mythbdbuffer.h:107
MythBDBuffer::GetChapterStartTimeMs
uint64_t GetChapterStartTimeMs(uint32_t Chapter)
Definition: mythbdbuffer.cpp:564
State
State
Definition: zmserver.h:63
MythMediaBuffer::m_readBlockSize
int m_readBlockSize
Definition: mythmediabuffer.h:210
MythBDBuffer::m_secondaryAudioEnabled
bool m_secondaryAudioEnabled
Definition: mythbdbuffer.h:120
MythBDBuffer
Definition: mythbdbuffer.h:21
MythBDBuffer::StartFromBeginning
bool StartFromBeginning(void) override
Definition: mythbdbuffer.cpp:1243
MythBDBuffer::UnblockReading
void UnblockReading(void)
Definition: mythbdbuffer.cpp:1206
filename
QString filename
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:634
MythMediaBuffer::m_setSwitchToNext
bool m_setSwitchToNext
Definition: mythmediabuffer.h:205
ACTION_SELECT
#define ACTION_SELECT
Definition: mythuiactions.h:15
MythEvent::kUpdateTvProgressEventType
static Type kUpdateTvProgressEventType
Definition: mythevent.h:75
MythBDBuffer::m_currentTitleLength
uint64_t m_currentTitleLength
Definition: mythbdbuffer.h:104
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
MythBDBuffer::GetTitleDuration
int GetTitleDuration(int Title)
Definition: mythbdbuffer.cpp:604
MythMediaBuffer::m_numFailures
int m_numFailures
Definition: mythmediabuffer.h:212
MythBDBuffer::m_overlayLock
QMutex m_overlayLock
Definition: mythbdbuffer.h:126
MythBDBuffer::SwitchAngle
bool SwitchAngle(uint Angle)
Definition: mythbdbuffer.cpp:782
iso639_key_to_str3
static QString iso639_key_to_str3(int code)
Definition: iso639.h:46
uint
unsigned int uint
Definition: compat.h:140
ACTION_9
#define ACTION_9
Definition: mythuiactions.h:13
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:249
MythBDBuffer::m_playerWait
bool m_playerWait
Definition: mythbdbuffer.h:124
MythBDBuffer::GetNumChapters
uint32_t GetNumChapters(void)
Definition: mythbdbuffer.cpp:549
MythBDBuffer::PressButton
void PressButton(int32_t Key, int64_t Pts)
Definition: mythbdbuffer.cpp:929
MythMediaBuffer::m_filename
QString m_filename
Definition: mythmediabuffer.h:182
ACTION_4
#define ACTION_4
Definition: mythuiactions.h:8
MythBDBuffer::SkipBDWaitingForPlayer
void SkipBDWaitingForPlayer(void)
Definition: mythbdbuffer.cpp:254
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:930
ACTION_1
#define ACTION_1
Definition: mythuiactions.h:5
states
states
Definition: mythmiscutil.cpp:1245
ACTION_MENUTEXT
#define ACTION_MENUTEXT
Definition: tv_actions.h:82
MythOpticalBuffer::m_inMenu
bool m_inMenu
Definition: mythopticalbuffer.h:26
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:663
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:670
MythBDBuffer::UpdateTitleInfo
bool UpdateTitleInfo(void)
Definition: mythbdbuffer.cpp:704
Buffer
Definition: MythExternControl.h:37
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::ClearOverlays
void ClearOverlays(void)
Definition: mythbdbuffer.cpp:1327
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:592
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::HandleAction
bool HandleAction(const QStringList &Actions, int64_t Pts) override
Definition: mythbdbuffer.cpp:186
MythBDBuffer::m_secondaryVideoEnabled
bool m_secondaryVideoEnabled
Definition: mythbdbuffer.h:121
Name
Definition: channelsettings.cpp:47
MythBDBuffer::GetDescForPos
void GetDescForPos(QString &Desc)
Definition: mythbdbuffer.cpp:178
MythBDBuffer::m_pgTextSTEnabled
bool m_pgTextSTEnabled
Definition: mythbdbuffer.h:119
MythBDBuffer::GetSubtitleLanguage
int GetSubtitleLanguage(uint StreamID)
Definition: mythbdbuffer.cpp:909
MythFileOpen
int MythFileOpen(const char *Pathname, int Flags)
Definition: mythiowrapper.cpp:112
BDLogger
static void BDLogger(const char *Message)
Definition: mythbdbuffer.cpp:62
MythBDBuffer::GetCurrentAngle
uint64_t GetCurrentAngle(void) const
Definition: mythbdbuffer.cpp:599
MythBDBuffer::m_numTitles
uint32_t m_numTitles
Definition: mythbdbuffer.h:102
MythOpticalBuffer
Definition: mythopticalbuffer.h:8
GetMythMainWindow
MythMainWindow * GetMythMainWindow(void)
Definition: mythmainwindow.cpp:107
ACTION_LEFT
#define ACTION_LEFT
Definition: mythuiactions.h:18
MythBDBuffer::OpenFile
bool OpenFile(const QString &Filename, uint Retry=static_cast< uint >(kDefaultOpenTimeout)) override
Opens a bluray device for reading.
Definition: mythbdbuffer.cpp:267
Buf
IFSPoint * Buf
Definition: ifs.cpp:145
MythBDBuffer::m_mainTitle
uint32_t m_mainTitle
Definition: mythbdbuffer.h:103
MythBDBuffer::GetTitleSize
uint64_t GetTitleSize(void) const
Definition: mythbdbuffer.cpp:618
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:980
mythuiactions.h
uint16_t
unsigned short uint16_t
Definition: iso6937tables.h:1
MythBDBuffer::IgnoreWaitStates
void IgnoreWaitStates(bool Ignore) override
Definition: mythbdbuffer.cpp:1238
MythBDBuffer::SwitchPlaylist
bool SwitchPlaylist(uint32_t Index)
Definition: mythbdbuffer.cpp:646
MythBDBuffer::m_overlayImages
QList< MythBDOverlay * > m_overlayImages
Definition: mythbdbuffer.h:127
MythMediaBuffer::m_posLock
QReadWriteLock m_posLock
Definition: mythmediabuffer.h:162
MythBDBuffer::SeekInternal
long long SeekInternal(long long Position, int Whence) override
Definition: mythbdbuffer.cpp:115
MythBDBuffer::IsValidStream
bool IsValidStream(uint StreamId)
Definition: mythbdbuffer.cpp:1187
MythBDBuffer::m_infoLock
QMutex m_infoLock
Definition: mythbdbuffer.h:136
MythBDBuffer::MythBDBuffer
MythBDBuffer(const QString &Filename)
Definition: mythbdbuffer.cpp:75
MythBDBuffer::m_bdnav
BLURAY * m_bdnav
Definition: mythbdbuffer.h:97
MythBDBuffer::SwitchTitle
bool SwitchTitle(uint32_t Index)
Definition: mythbdbuffer.cpp:633
MythBDBuffer::GetTotalTimeOfTitle
uint64_t GetTotalTimeOfTitle(void) const
Definition: mythbdbuffer.cpp:623
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:593
ACTION_CHANNELDOWN
#define ACTION_CHANNELDOWN
Definition: tv_actions.h:17
MythMediaBuffer::m_rwLock
QReadWriteLock m_rwLock
Definition: mythmediabuffer.h:181
MythBDBuffer::WaitForPlayer
void WaitForPlayer(void)
Definition: mythbdbuffer.cpp:1221
MythBDBuffer::m_pendingData
QByteArray m_pendingData
Definition: mythbdbuffer.h:132
FileOpenedCallback
static void FileOpenedCallback(void *Data)
Definition: mythbdbuffer.cpp:55
MythBDBuffer::SafeRead
int SafeRead(void *Buffer, uint Size) override
Definition: mythbdbuffer.cpp:813
iso639_str3_to_key
static int iso639_str3_to_key(const unsigned char *iso639_2)
Definition: iso639.h:63
MythOpticalBuffer::PROCESS_REPROCESS
@ PROCESS_REPROCESS
Definition: mythopticalbuffer.h:20
MythMediaBuffer::m_ateof
bool m_ateof
Definition: mythmediabuffer.h:199
MythOpticalBuffer::PROCESS_NORMAL
@ PROCESS_NORMAL
Definition: mythopticalbuffer.h:19
mythmainwindow.h
MythBDBuffer::GetCurrentTime
uint64_t GetCurrentTime(void) const
Definition: mythbdbuffer.cpp:628
MythBDBuffer::GetBDStateSnapshot
bool GetBDStateSnapshot(QString &State)
Get a snapshot of the current BD state.
Definition: mythbdbuffer.cpp:1264
MythBDBuffer::RestoreBDStateSnapshot
bool RestoreBDStateSnapshot(const QString &State)
Restore a BD snapshot.
Definition: mythbdbuffer.cpp:1278
MythBDBuffer::m_overlayPlanes
QVector< MythBDOverlay * > m_overlayPlanes
Definition: mythbdbuffer.h:128
for
for(int x=0;x< dirList.count() - 1;x++)
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:1172
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:1359
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:240
ACTION_SEEKFFWD
#define ACTION_SEEKFFWD
Definition: tv_actions.h:43
MThread::usleep
static void usleep(unsigned long time)
Definition: mthread.cpp:346
MythBDBuffer::AdjustTimestamp
int64_t AdjustTimestamp(int64_t Timestamp) const
Definition: mythbdbuffer.cpp:805
MythBDBuffer::ProgressUpdate
void ProgressUpdate(void)
Definition: mythbdbuffer.cpp:237
mythbdinfo.h
MythMediaBuffer::m_ignoreReadPos
long long m_ignoreReadPos
Definition: mythmediabuffer.h:166
MythMediaBuffer::m_readAheadRunning
bool m_readAheadRunning
Definition: mythmediabuffer.h:195
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:1176
MythBDBuffer::m_titlesize
uint64_t m_titlesize
Definition: mythbdbuffer.h:106
MythBDBuffer::m_currentTime
uint64_t m_currentTime
Definition: mythbdbuffer.h:108
mythiowrapper.h
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:916