MythTV  master
mythdvdbuffer.cpp
Go to the documentation of this file.
1 // Qt
2 #include <QCoreApplication>
3 
4 // MythTV
5 #include "mythconfig.h"
6 #include "mythcontext.h"
7 #include "mythmediamonitor.h"
8 #include "iso639.h"
9 #include "mythdvdplayer.h"
10 #include "compat.h"
11 #include "mythlogging.h"
12 #include "mythmainwindow.h"
13 #include "mythuiactions.h"
14 #include "tv_actions.h"
15 #include "mythdvdbuffer.h"
16 
17 // Std
18 #include <thread>
19 #include <algorithm>
20 
21 #define LOC QString("DVDRB: ")
22 
23 #define IncrementButtonVersion if (++m_buttonVersion > 1024) m_buttonVersion = 1;
24 #define DVD_DRIVE_SPEED 1
25 
26 static const std::array<const std::string,8> DVDMenuTable
27 {
28  "",
29  "",
30  QT_TRANSLATE_NOOP("(DVD menu)", "Title Menu"),
31  QT_TRANSLATE_NOOP("(DVD menu)", "Root Menu"),
32  QT_TRANSLATE_NOOP("(DVD menu)", "Subpicture Menu"),
33  QT_TRANSLATE_NOOP("(DVD menu)", "Audio Menu"),
34  QT_TRANSLATE_NOOP("(DVD menu)", "Angle Menu"),
35  //: DVD part/chapter menu
36  QT_TRANSLATE_NOOP("(DVD menu)", "Part Menu")
37 };
38 
39 const QMap<int, int> MythDVDBuffer::kSeekSpeedMap =
40 { { 3, 1 }, { 5, 2 }, { 10, 4 }, { 20, 8 },
41  { 30, 10 }, { 60, 15 }, { 120, 20 }, { 180, 60 } };
42 
43 MythDVDBuffer::MythDVDBuffer(const QString &Filename)
45 {
46  MythDVDBuffer::OpenFile(Filename);
47 }
48 
50 {
52 
53  CloseDVD();
54  m_menuBtnLock.lock();
56  m_menuBtnLock.unlock();
58 }
59 
61 {
62  QMutexLocker contextLocker(&m_contextLock);
63  m_rwLock.lockForWrite();
64  if (m_dvdnav)
65  {
66  SetDVDSpeed(-1);
67  dvdnav_close(m_dvdnav);
68  m_dvdnav = nullptr;
69  }
70 
71  if (m_context)
72  {
73  m_context->DecrRef();
74  m_context = nullptr;
75  }
76 
77  m_gotStop = false;
78  m_audioStreamsChanged = true;
79  m_rwLock.unlock();
80 }
81 
83 {
84  m_rwLock.lockForWrite();
85  for (QList<std::chrono::seconds> chapters : qAsConst(m_chapterMap))
86  chapters.clear();
87  m_chapterMap.clear();
88  m_rwLock.unlock();
89 }
90 
91 long long MythDVDBuffer::SeekInternal(long long Position, int Whence)
92 {
93  long long ret = -1;
94 
95  m_posLock.lockForWrite();
96 
97  // Optimize no-op seeks
98  if (m_readAheadRunning &&
99  ((Whence == SEEK_SET && Position == m_readPos) || (Whence == SEEK_CUR && Position == 0)))
100  {
101  ret = m_readPos;
102  m_posLock.unlock();
103  return ret;
104  }
105 
106  // only valid for SEEK_SET & SEEK_CUR
107  long long new_pos = (SEEK_SET==Whence) ? Position : m_readPos + Position;
108 
109  // Here we perform a normal seek. When successful we
110  // need to call ResetReadAhead(). A reset means we will
111  // need to refill the buffer, which takes some time.
112  if ((SEEK_END == Whence) || ((SEEK_CUR == Whence) && new_pos != 0))
113  {
114  errno = EINVAL;
115  ret = -1;
116  }
117  else
118  {
119  NormalSeek(new_pos);
120  ret = new_pos;
121  }
122 
123  if (ret >= 0)
124  {
125  m_readPos = ret;
126  m_ignoreReadPos = -1;
127  if (m_readAheadRunning)
129  m_readAdjust = 0;
130  }
131  else
132  {
133  QString cmd = QString("Seek(%1, %2)").arg(Position)
134  .arg((Whence == SEEK_SET) ? "SEEK_SET" :
135  ((Whence == SEEK_CUR) ? "SEEK_CUR" : "SEEK_END"));
136  LOG(VB_GENERAL, LOG_ERR, LOC + cmd + " Failed" + ENO);
137  }
138 
139  m_posLock.unlock();
140  m_generalWait.wakeAll();
141  return ret;
142 }
143 
144 long long MythDVDBuffer::NormalSeek(long long Time)
145 {
146  QMutexLocker locker(&m_seekLock);
147  return Seek(Time);
148 }
149 
150 bool MythDVDBuffer::SectorSeek(uint64_t Sector)
151 {
152  dvdnav_status_t dvdRet = DVDNAV_STATUS_OK;
153 
154  QMutexLocker lock(&m_seekLock);
155 
156  dvdRet = dvdnav_sector_search(m_dvdnav, static_cast<int64_t>(Sector), SEEK_SET);
157 
158  if (dvdRet == DVDNAV_STATUS_ERR)
159  {
160  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString("SectorSeek() to sector %1 failed").arg(Sector));
161  return false;
162  }
163  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("DVD Playback SectorSeek() sector: %1").arg(Sector));
164  return true;
165 }
166 
167 long long MythDVDBuffer::Seek(long long Time)
168 {
169  dvdnav_status_t dvdRet = DVDNAV_STATUS_OK;
170 
171  int seekSpeed = 0;
172  int ffrewSkip = 1;
173  if (m_parent)
174  ffrewSkip = m_parent->GetFFRewSkip();
175 
176  if (ffrewSkip != 1 && ffrewSkip != 0 && Time != 0)
177  {
178  auto it = kSeekSpeedMap.lowerBound(static_cast<int>(std::abs(Time)));
179  if (it == kSeekSpeedMap.end())
180  seekSpeed = kSeekSpeedMap.last();
181  else
182  seekSpeed = *it;
183  if (Time < 0)
184  seekSpeed = -seekSpeed;
185  dvdRet = dvdnav_relative_time_search(m_dvdnav, seekSpeed);
186  }
187  else
188  {
190  dvdRet = dvdnav_absolute_time_search(m_dvdnav, m_seektime.count(), 0);
191  }
192 
193  LOG(VB_PLAYBACK, LOG_DEBUG, QString("DVD Playback Seek() time: %1; seekSpeed: %2")
194  .arg(Time).arg(seekSpeed));
195 
196  if (dvdRet == DVDNAV_STATUS_ERR)
197  {
198  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString("Seek() to time %1 failed").arg(Time));
199  return -1;
200  }
201 
202  if (!m_inMenu)
203  {
204  m_gotStop = false;
205  if (Time > 0 && ffrewSkip == 1)
206  m_seeking = true;
207  }
208 
209  return m_currentpos;
210 }
211 
212 bool MythDVDBuffer::IsOpen(void) const
213 {
214  return m_dvdnav;
215 }
216 
218 {
219  return GetTotalTimeOfTitle() >= 2min;
220 }
221 
223 {
224  return m_still > 0s;
225 }
226 
228 {
229  // Don't allow seeking when the ringbuffer is
230  // waiting for the player to flush its buffers
231  // or waiting for the decoder.
232  return ((m_dvdEvent != DVDNAV_WAIT) &&
233  (m_dvdEvent != DVDNAV_HOP_CHANNEL) &&
235 }
236 
237 void MythDVDBuffer::GetDescForPos(QString &Description) const
238 {
239  if (m_inMenu)
240  {
241  if ((m_part <= DVD_MENU_MAX) && !DVDMenuTable[m_part].empty())
242  Description = QCoreApplication::translate("(DVD menu)", DVDMenuTable[m_part].c_str());
243  }
244  else
245  {
246  Description = tr("Title %1 chapter %2").arg(m_title).arg(m_part);
247  }
248 }
249 
256 bool MythDVDBuffer::OpenFile(const QString &Filename, std::chrono::milliseconds /*Retry*/)
257 {
258  QMutexLocker contextLocker(&m_contextLock);
259  m_rwLock.lockForWrite();
260 
261  if (m_dvdnav)
262  {
263  m_rwLock.unlock();
264  CloseDVD();
265  m_rwLock.lockForWrite();
266  }
267 
268  m_safeFilename = Filename;
269  m_filename = Filename;
270  dvdnav_status_t res = dvdnav_open(&m_dvdnav, m_filename.toLocal8Bit().constData());
271  if (res == DVDNAV_STATUS_ERR)
272  {
273  m_lastError = tr("Failed to open DVD device at %1").arg(m_filename);
274  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to open DVD device at '%1'").arg(m_filename));
275  m_rwLock.unlock();
276  return false;
277  }
278 
279  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Opened DVD device at '%1'").arg(m_filename));
280 
281  if (m_context)
282  {
283  m_context->DecrRef();
284  m_context = nullptr;
285  }
286 
287  // Set preferred languages
288  QString lang = gCoreContext->GetSetting("Language").section('_', 0, 0);
289 
290  dvdnav_menu_language_select(m_dvdnav, lang.toLatin1().data());
291  dvdnav_audio_language_select(m_dvdnav, lang.toLatin1().data());
292  dvdnav_spu_language_select(m_dvdnav, lang.toLatin1().data());
293 
294  dvdnav_set_readahead_flag(m_dvdnav, 0);
295  dvdnav_set_PGC_positioning_flag(m_dvdnav, 1);
296 
297  // Check we aren't starting in a still frame (which will probably fail as
298  // ffmpeg will be unable to create a decoder)
299  if (dvdnav_get_next_still_flag(m_dvdnav))
300  {
301  LOG(VB_GENERAL, LOG_NOTICE,
302  LOC + "The selected title is a still frame. "
303  "Playback is likely to fail - please raise a bug report at "
304  "http://code.mythtv.org/trac");
305  }
306 
308 
309  SetDVDSpeed();
310  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("DVD Serial Number %1").arg(m_discSerialNumber));
312  m_setSwitchToNext = false;
313  m_ateof = false;
314  m_commsError = false;
315  m_numFailures = 0;
316  m_rawBitrate = 8000;
318 
319  m_rwLock.unlock();
320 
321  return true;
322 }
323 
325 {
326  LOG(VB_GENERAL, LOG_INFO, LOC + "Resetting DVD device.");
327 
328  // if a DVDNAV_STOP event has been emitted, dvdnav_reset does not
329  // seem to restore the state, hence we need to re-create
330  if (m_gotStop)
331  {
332  LOG(VB_GENERAL, LOG_ERR, LOC +
333  "DVD errored after initial scan - trying again");
334  CloseDVD();
336  if (!m_dvdnav)
337  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to re-open DVD.");
338  }
339 
340  if (m_dvdnav)
341  {
342  // Set preferred languages
343  QString lang = gCoreContext->GetSetting("Language").section('_', 0, 0);
344  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Setting DVD languages to %1")
345  .arg(lang));
346 
347  QMutexLocker lock(&m_seekLock);
348  dvdnav_reset(m_dvdnav);
349  dvdnav_menu_language_select(m_dvdnav, lang.toLatin1().data());
350  dvdnav_audio_language_select(m_dvdnav, lang.toLatin1().data());
351  dvdnav_spu_language_select(m_dvdnav, lang.toLatin1().data());
352  m_audioStreamsChanged = true;
353  }
354 
355  m_endPts = 0;
356  m_timeDiff = 0;
357 
358  QMutexLocker contextLocker(&m_contextLock);
359  if (m_context)
360  {
361  m_context->DecrRef();
362  m_context = nullptr;
363  }
364 
365  return m_dvdnav;
366 }
367 
368 void MythDVDBuffer::GetChapterTimes(QList<std::chrono::seconds> &Times)
369 {
370  if (!m_chapterMap.contains(m_title))
372  if (!m_chapterMap.contains(m_title))
373  return;
374  const QList<std::chrono::seconds>& chapters = m_chapterMap.value(m_title);
375  std::copy(chapters.cbegin(), chapters.cend(), std::back_inserter(Times));
376 }
377 
378 static constexpr mpeg::chrono::pts HALFSECOND { 45000_pts };
379 std::chrono::seconds MythDVDBuffer::GetChapterTimes(int Title)
380 {
381  if (!m_dvdnav)
382  return 0s;
383 
384  uint64_t duration = 0;
385  uint64_t *times = nullptr;
386  uint32_t num = dvdnav_describe_title_chapters(m_dvdnav, Title, &times, &duration);
387 
388  if (num < 1)
389  {
390  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to retrieve chapter data");
391  return 0s;
392  }
393 
394  QList<std::chrono::seconds> chapters;
395  // add the start
396  chapters.append(0s);
397  // don't add the last 'chapter' - which is the title end
398  if (num > 1)
399  for (uint i = 0; i < num - 1; i++)
400  chapters.append(duration_cast<std::chrono::seconds>(mpeg::chrono::pts(times[i]) + HALFSECOND));
401 
402  // Assigned via calloc, must be free'd not deleted
403  if (times)
404  free(times);
405  m_chapterMap.insert(Title, chapters);
406  return duration_cast<std::chrono::seconds>(mpeg::chrono::pts(duration) + HALFSECOND);
407 }
408 
411 long long MythDVDBuffer::GetReadPosition(void) const
412 {
413  uint32_t pos = 0;
414  uint32_t length = 1;
415  if (m_dvdnav)
416  {
417  if (dvdnav_get_position(m_dvdnav, &pos, &length) == DVDNAV_STATUS_ERR)
418  {
419  // try one more time
420  dvdnav_get_position(m_dvdnav, &pos, &length);
421  }
422  }
423  return pos * DVD_BLOCK_SIZE;
424 }
425 
426 int MythDVDBuffer::GetTitle(void) const
427 {
428  return m_title;
429 }
430 
432 {
433  return m_playerWait;
434 }
435 
436 int MythDVDBuffer::GetPart(void) const
437 {
438  return m_part;
439 }
440 
442 {
443  return m_currentAngle;
444 }
445 
447 {
449 }
450 
452 {
453  return m_titleLength;
454 }
455 
456 std::chrono::seconds MythDVDBuffer::GetChapterLength(void) const
457 {
458  return duration_cast<std::chrono::seconds>(m_pgLength);
459 }
460 
461 void MythDVDBuffer::GetPartAndTitle(int &Part, int &Title) const
462 {
463  Part = m_part;
464  Title = m_title;
465 }
466 
467 uint32_t MythDVDBuffer::AdjustTimestamp(uint32_t Timestamp) const
468 {
469  uint32_t newTimestamp = Timestamp;
470  if (newTimestamp >= m_timeDiff)
471  newTimestamp -= m_timeDiff;
472  return newTimestamp;
473 }
474 
475 int64_t MythDVDBuffer::AdjustTimestamp(int64_t Timestamp) const
476 {
477  int64_t newTimestamp = Timestamp;
478  if ((newTimestamp != AV_NOPTS_VALUE) && (newTimestamp >= m_timeDiff))
479  newTimestamp -= m_timeDiff;
480  return newTimestamp;
481 }
482 
484 {
485  QMutexLocker contextLocker(&m_contextLock);
486  if (m_context)
487  m_context->IncrRef();
488  return m_context;
489 }
490 
492 {
493  return m_dvdEvent;
494 }
495 
497 {
498  if (!m_skipstillorwait)
499  {
500  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Waiting for player's buffers to drain");
501  m_playerWait = true;
502  int count = 0;
503  while (m_playerWait && count++ < 200)
504  {
505  m_rwLock.unlock();
506  std::this_thread::sleep_for(10ms);
507  m_rwLock.lockForWrite();
508  }
509 
510  if (m_playerWait)
511  {
512  LOG(VB_GENERAL, LOG_ERR, LOC + "Player wait state was not cleared");
513  m_playerWait = false;
514  }
515  }
516 }
517 
519 {
520  uint8_t* blockBuf = nullptr;
521  uint tot = 0;
522  int needed = static_cast<int>(Size);
523  char* dest = static_cast<char*>(Buffer);
524  int offset = 0;
525  bool reprocessing { false };
526  bool waiting = false;
527 
528  if (m_gotStop)
529  {
530  LOG(VB_GENERAL, LOG_ERR, LOC + "safe_read: called after DVDNAV_STOP");
531  errno = EBADF;
532  return -1;
533  }
534 
535  if (m_readAheadRunning)
536  LOG(VB_GENERAL, LOG_ERR, LOC + "read ahead thread running.");
537 
538  while ((m_processState != PROCESS_WAIT) && needed)
539  {
540  blockBuf = m_dvdBlockWriteBuf.data();
541 
543  {
545  reprocessing = true;
546  }
547  else
548  {
549  m_dvdStat = dvdnav_get_next_cache_block(m_dvdnav, &blockBuf, &m_dvdEvent, &m_dvdEventSize);
550  reprocessing = false;
551  }
552 
553  if (m_dvdStat == DVDNAV_STATUS_ERR)
554  {
555  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to read block: %1")
556  .arg(dvdnav_err_to_string(m_dvdnav)));
557  errno = EIO;
558  return -1;
559  }
560 
561  switch (m_dvdEvent)
562  {
563  // Standard packet for decoding
564  case DVDNAV_BLOCK_OK:
565  {
566  // copy block
567  if (!m_seeking)
568  {
569  memcpy(dest + offset, blockBuf, DVD_BLOCK_SIZE);
570  tot += DVD_BLOCK_SIZE;
571  }
572 
573  // release buffer
574  if (blockBuf != m_dvdBlockWriteBuf.data())
575  dvdnav_free_cache_block(m_dvdnav, blockBuf);
576 
577  // debug
578  LOG(VB_PLAYBACK|VB_FILE, LOG_DEBUG, LOC + "DVDNAV_BLOCK_OK");
579  }
580  break;
581 
582  // cell change
583  case DVDNAV_CELL_CHANGE:
584  {
585  // get event details
586  auto *cell_event = reinterpret_cast<dvdnav_cell_change_event_t*>(blockBuf);
587 
588  // update information for the current cell
589  m_cellChanged = true;
590  if (m_pgcLength != mpeg::chrono::pts(cell_event->pgc_length))
591  m_pgcLengthChanged = true;
592  m_pgLength = mpeg::chrono::pts(cell_event->pg_length);
593  m_pgcLength = mpeg::chrono::pts(cell_event->pgc_length);
594  m_cellStart = mpeg::chrono::pts(cell_event->cell_start);
595  m_pgStart = cell_event->pg_start;
596 
597  // update title/part/still/menu information
599  m_lastPart = m_part;
601  uint32_t pos = 0;
602  uint32_t length = 0;
603  uint32_t stillTimer = dvdnav_get_next_still_flag(m_dvdnav);
604  m_still = 0s;
605  m_titleParts = 0;
606  dvdnav_current_title_info(m_dvdnav, &m_title, &m_part);
607  dvdnav_get_number_of_parts(m_dvdnav, m_title, &m_titleParts);
608  dvdnav_get_position(m_dvdnav, &pos, &length);
609  dvdnav_get_angle_info(m_dvdnav, &m_currentAngle, &m_currentTitleAngleCount);
610 
611  if (m_title != m_lastTitle)
612  {
613  // Populate the chapter list for this title, used in the OSD menu
615  }
616 
617  m_titleLength = length * DVD_BLOCK_SIZE;
618  if (!m_seeking)
620 
621  // debug
622  LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
623  QString("---- DVDNAV_CELL_CHANGE - Cell #%1 Menu %2 Length %3")
624  .arg(cell_event->cellN).arg(m_inMenu ? "Yes" : "No")
625  .arg(static_cast<double>(cell_event->cell_length) / 90000.0, 0, 'f', 1));
626  QString still = stillTimer ? ((stillTimer < 0xff) ?
627  QString("Stillframe: %1 seconds").arg(stillTimer) :
628  QString("Infinite stillframe")) :
629  QString("Length: %1 seconds")
630  .arg(duration_cast<std::chrono::seconds>(m_pgcLength).count());
631  if (m_title == 0)
632  {
633  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Menu #%1 %2")
634  .arg(m_part).arg(still));
635  }
636  else
637  {
638  LOG(VB_PLAYBACK, LOG_INFO,
639  LOC + QString("Title #%1: %2 Part %3 of %4")
640  .arg(m_title).arg(still).arg(m_part).arg(m_titleParts));
641  }
642 
643  // wait unless it is a transition from one normal video cell to
644  // another or the same menu id
645  if ((m_title != m_lastTitle) &&
646  !((m_title == 0 && m_lastTitle == 0) && (m_part == m_lastPart)))
647  {
648  WaitForPlayer();
649  }
650 
651  // Make sure the still frame timer is reset.
652  if (m_parent)
654 
655  // clear menus/still frame selections
659  m_buttonSelected = false;
660  m_vobid = m_cellid = 0;
661  m_cellRepeated = false;
662  m_buttonSeenInCell = false;
663 
665 
666  // release buffer
667  if (blockBuf != m_dvdBlockWriteBuf.data())
668  dvdnav_free_cache_block(m_dvdnav, blockBuf);
669  }
670  break;
671 
672  // new colour lookup table for subtitles/menu buttons
673  case DVDNAV_SPU_CLUT_CHANGE:
674  {
675  // debug
676  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "DVDNAV_SPU_CLUT_CHANGE");
677 
678  // store the new clut
679  // m_clut = std::to_array(blockBuf); // C++20
680  std::copy(blockBuf, blockBuf + 16 * sizeof(uint32_t),
681  reinterpret_cast<uint8_t*>(m_clut.data()));
682  // release buffer
683  if (blockBuf != m_dvdBlockWriteBuf.data())
684  dvdnav_free_cache_block(m_dvdnav, blockBuf);
685  }
686  break;
687 
688  // new Sub-picture Unit stream (subtitles/menu buttons)
689  case DVDNAV_SPU_STREAM_CHANGE:
690  {
691  // get event details
692  auto* spu = reinterpret_cast<dvdnav_spu_stream_change_event_t*>(blockBuf);
693 
694  // clear any existing subs/buttons
696 
697  // not sure
699  m_curSubtitleTrack = dvdnav_get_active_spu_stream(m_dvdnav);
700 
701  // debug
702  LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
703  QString("DVDNAV_SPU_STREAM_CHANGE: "
704  "physicalwide %1, physicalletterbox %2, "
705  "physicalpanscan %3, currenttrack %4")
706  .arg(spu->physical_wide).arg(spu->physical_letterbox)
707  .arg(spu->physical_pan_scan).arg(m_curSubtitleTrack));
708 
709  // release buffer
710  if (blockBuf != m_dvdBlockWriteBuf.data())
711  dvdnav_free_cache_block(m_dvdnav, blockBuf);
712  }
713  break;
714 
715  // the audio stream changed
716  case DVDNAV_AUDIO_STREAM_CHANGE:
717  {
718  // get event details
719  auto* audio = reinterpret_cast<dvdnav_audio_stream_change_event_t*>(blockBuf);
720 
721  // retrieve the new track
722  int new_track = GetAudioTrackNum(static_cast<uint>(audio->physical));
723 
724  // debug
725  LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
726  QString("DVDNAV_AUDIO_STREAM_CHANGE: old %1 new %2, physical %3, logical %4")
727  .arg(m_curAudioTrack).arg(new_track)
728  .arg(audio->physical).arg(audio->logical));
729 
730  // tell the decoder to reset the audio streams if necessary
731  if (new_track != m_curAudioTrack)
732  {
733  m_curAudioTrack = new_track;
734  m_audioStreamsChanged = true;
735  }
736 
737  // release buffer
738  if (blockBuf != m_dvdBlockWriteBuf.data())
739  dvdnav_free_cache_block(m_dvdnav, blockBuf);
740  }
741  break;
742 
743  // navigation packet
744  case DVDNAV_NAV_PACKET:
745  {
746  QMutexLocker lock(&m_seekLock);
747  bool lastInMenu = m_inMenu;
748 
749  // retrieve the latest Presentation Control and
750  // Data Search Information structures
751  pci_t *pci = dvdnav_get_current_nav_pci(m_dvdnav);
752  dsi_t *dsi = dvdnav_get_current_nav_dsi(m_dvdnav);
753 
754  if (pci == nullptr || dsi == nullptr)
755  {
756  // Something has gone horribly wrong if this happens
757  LOG(VB_GENERAL, LOG_ERR, LOC + QString("DVDNAV_NAV_PACKET - Error retrieving DVD data structures - dsi 0x%1, pci 0x%2")
758  .arg(reinterpret_cast<uint64_t>(dsi), 0, 16)
759  .arg(reinterpret_cast<uint64_t>(pci), 0, 16));
760  }
761  else
762  {
763  // If the start PTS of this block is not the
764  // same as the end PTS of the last block,
765  // we've got a timestamp discontinuity
766  int64_t diff = static_cast<int64_t>(pci->pci_gi.vobu_s_ptm) - m_endPts;
767  if (diff != 0)
768  {
769  if (!reprocessing && !m_skipstillorwait)
770  {
771  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("PTS discontinuity - waiting for decoder: this %1, last %2, diff %3")
772  .arg(pci->pci_gi.vobu_s_ptm).arg(m_endPts).arg(diff));
774  break;
775  }
776 
777  m_timeDiff += diff;
778  }
779 
780  m_endPts = pci->pci_gi.vobu_e_ptm;
781  m_inMenu = (pci->hli.hl_gi.btn_ns > 0);
782 
783  if (m_inMenu && m_seeking && (dsi->synci.sp_synca[0] & 0x80000000) &&
785  {
786  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("Jumped into middle of menu: lba %1, dest %2")
787  .arg(pci->pci_gi.nv_pck_lbn)
788  .arg(pci->pci_gi.nv_pck_lbn - (dsi->synci.sp_synca[0] & 0x7fffffff)));
789 
790  // We're in a menu, the subpicture packets are somewhere behind us
791  // and we've not decoded any subpicture.
792  // That probably means we've jumped into the middle of a menu.
793  // We'd better jump back to get the subpicture packet(s) otherwise
794  // there's no menu highlight to show.
795  m_seeking = false;
796  dvdnav_sector_search(m_dvdnav, pci->pci_gi.nv_pck_lbn - (dsi->synci.sp_synca[0] & 0x7fffffff), SEEK_SET);
797  }
798  else
799  {
800  pci_t pci_copy = *pci;
801 
802  pci_copy.pci_gi.vobu_s_ptm = AdjustTimestamp(pci->pci_gi.vobu_s_ptm);
803  pci_copy.pci_gi.vobu_e_ptm = AdjustTimestamp(pci->pci_gi.vobu_e_ptm);
804 
805  if (pci->pci_gi.vobu_se_e_ptm != 0)
806  pci_copy.pci_gi.vobu_se_e_ptm = AdjustTimestamp(pci->pci_gi.vobu_se_e_ptm);
807 
808  QMutexLocker contextLocker(&m_contextLock);
809  if (m_context)
810  m_context->DecrRef();
811 
812  m_context = new MythDVDContext(*dsi, pci_copy);
813 
814  if (m_inMenu != lastInMenu)
815  {
816  if (m_inMenu)
817  {
818  m_autoselectsubtitle = true;
820  }
821  else
822  {
824  }
825  }
826 
827  // if we are in a looping menu, we don't want to reset the
828  // selected button when we restart
829  m_vobid = dsi->dsi_gi.vobu_vob_idn;
830  m_cellid = dsi->dsi_gi.vobu_c_idn;
831  if ((m_lastvobid == m_vobid) && (m_lastcellid == m_cellid)
833  {
834  m_cellRepeated = true;
835  }
836 
837  // update our status
838  m_currentTime = mpeg::chrono::pts(dvdnav_get_current_time(m_dvdnav));
840 
841  if (m_seeking)
842  {
843  auto relativetime = duration_cast<std::chrono::seconds>(m_seektime - m_currentTime);
844  if (abs(relativetime) <= 1s)
845  {
846  m_seeking = false;
847  m_seektime = 0_pts;
848  }
849  else
850  {
851  dvdnav_relative_time_search(m_dvdnav, relativetime.count() * 2);
852  }
853  }
854 
855  // update the button stream number if this is the
856  // first NAV pack containing button information
857  if ( (pci->hli.hl_gi.hli_ss & 0x03) == 0x01 )
858  {
859  m_buttonStreamID = 32;
860  int aspect = dvdnav_get_video_aspect(m_dvdnav);
861 
862  // workaround where dvd menu is
863  // present in VTS_DOMAIN. dvdnav adds 0x80 to stream id
864  // proper fix should be put in dvdnav sometime
865  int8_t spustream = dvdnav_get_active_spu_stream(m_dvdnav) & 0x7f;
866 
867  if (aspect != 0 && spustream > 0)
868  m_buttonStreamID += spustream;
869 
870  m_buttonSeenInCell = true;
871  }
872 
873  // debug
874  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("DVDNAV_NAV_PACKET - time:%1, lba:%2, vob:%3, cell:%4, seeking:%5, seektime:%6")
875  .arg(m_context->GetStartPTS())
876  .arg(m_context->GetLBA())
877  .arg(m_vobid)
878  .arg(m_cellid)
879  .arg(m_seeking)
880  .arg(m_seektime.count()));
881 
882  if (!m_seeking)
883  {
884  memcpy(dest + offset, blockBuf, DVD_BLOCK_SIZE);
885  tot += DVD_BLOCK_SIZE;
886  }
887  }
888  }
889  // release buffer
890  if (blockBuf != m_dvdBlockWriteBuf.data())
891  dvdnav_free_cache_block(m_dvdnav, blockBuf);
892  }
893  break;
894 
895  case DVDNAV_HOP_CHANNEL:
896  {
897  if (!reprocessing && !m_skipstillorwait)
898  {
899  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "DVDNAV_HOP_CHANNEL - waiting");
901  break;
902  }
903 
904  // debug
905  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "DVDNAV_HOP_CHANNEL");
906  WaitForPlayer();
907  }
908  break;
909 
910  // no op
911  case DVDNAV_NOP:
912  break;
913 
914  // new Video Title Set - aspect ratio/letterboxing
915  case DVDNAV_VTS_CHANGE:
916  {
917  // retrieve event details
918  auto* vts = reinterpret_cast<dvdnav_vts_change_event_t*>(blockBuf);
919 
920  // update player
921  int aspect = dvdnav_get_video_aspect(m_dvdnav);
922  if (aspect == 2) // 4:3
923  m_forcedAspect = 4.0F / 3.0F;
924  else if (aspect == 3) // 16:9
925  m_forcedAspect = 16.0F / 9.0F;
926  else
927  m_forcedAspect = -1;
928  int permission = dvdnav_get_video_scale_permission(m_dvdnav);
929 
930  // debug
931  LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
932  QString("DVDNAV_VTS_CHANGE: old_vtsN %1, new_vtsN %2, "
933  "aspect %3, perm %4")
934  .arg(vts->old_vtsN).arg(vts->new_vtsN)
935  .arg(aspect).arg(permission));
936 
937  // trigger a rescan of the audio streams
938  if ((vts->old_vtsN != vts->new_vtsN) ||(vts->old_domain != vts->new_domain))
939  m_audioStreamsChanged = true;
940 
941  // Make sure we know we're not staying in the
942  // same cell (same vobid/cellid values can
943  // occur in every VTS)
944  m_lastvobid = m_vobid = 0;
945  m_lastcellid = m_cellid = 0;
946 
947  // release buffer
948  if (blockBuf != m_dvdBlockWriteBuf.data())
949  dvdnav_free_cache_block(m_dvdnav, blockBuf);
950  }
951  break;
952 
953  // menu button
954  case DVDNAV_HIGHLIGHT:
955  {
956  // retrieve details
957  auto* highlight = reinterpret_cast<dvdnav_highlight_event_t*>(blockBuf);
958 
959  // update the current button
960  m_menuBtnLock.lock();
961  DVDButtonUpdate(false);
963  m_menuBtnLock.unlock();
964 
965  // debug
966  LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
967  QString("DVDNAV_HIGHLIGHT: display %1, palette %2, "
968  "sx %3, sy %4, ex %5, ey %6, pts %7, buttonN %8")
969  .arg(highlight->display).arg(highlight->palette)
970  .arg(highlight->sx).arg(highlight->sy)
971  .arg(highlight->ex).arg(highlight->ey)
972  .arg(highlight->pts).arg(highlight->buttonN));
973 
974  // release buffer
975  if (blockBuf != m_dvdBlockWriteBuf.data())
976  dvdnav_free_cache_block(m_dvdnav, blockBuf);
977  }
978  break;
979 
980  // dvd still frame
981  case DVDNAV_STILL_FRAME:
982  {
983  // retrieve still frame details (length)
984  auto* still = reinterpret_cast<dvdnav_still_event_t*>(blockBuf);
985 
986  if (!reprocessing && !m_skipstillorwait)
987  {
988  if (m_still != std::chrono::seconds(still->length))
989  {
990  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("DVDNAV_STILL_FRAME (%1) - waiting")
991  .arg(still->length));
992  }
993 
995  }
996  else
997  {
998  // pause a little as the dvdnav VM will continue to return
999  // this event until it has been skipped
1000  m_rwLock.unlock();
1001  std::this_thread::sleep_for(10ms);
1002  m_rwLock.lockForWrite();
1003 
1004  // when scanning the file or exiting playback, skip immediately
1005  // otherwise update the timeout in the player
1006  if (m_skipstillorwait)
1007  {
1008  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("Skipping DVDNAV_STILL_FRAME (%1)")
1009  .arg(still->length));
1010  SkipStillFrame();
1011  }
1012  else if (m_parent)
1013  {
1014  // debug
1015  if (m_still != std::chrono::seconds(still->length))
1016  {
1017  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("DVDNAV_STILL_FRAME (%1)")
1018  .arg(still->length));
1019  }
1020 
1021  m_still = std::chrono::seconds(still->length);
1022  Size = tot;
1024  }
1025 
1026  // release buffer
1027  if (blockBuf != m_dvdBlockWriteBuf.data())
1028  dvdnav_free_cache_block(m_dvdnav, blockBuf);
1029  }
1030  }
1031  break;
1032 
1033  // wait for the player
1034  case DVDNAV_WAIT:
1035  {
1036  if (!reprocessing && !m_skipstillorwait && !waiting)
1037  {
1038  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "DVDNAV_WAIT - waiting");
1040  }
1041  else
1042  {
1043  waiting = true;
1044 
1045  //debug
1046  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "DVDNAV_WAIT");
1047 
1048  // skip if required, otherwise wait (and loop)
1049  if (m_skipstillorwait)
1050  {
1051  WaitSkip();
1052  }
1053  else
1054  {
1055  m_dvdWaiting = true;
1056  m_rwLock.unlock();
1057  std::this_thread::sleep_for(10ms);
1058  m_rwLock.lockForWrite();
1059  }
1060 
1061  // release buffer
1062  if (blockBuf != m_dvdBlockWriteBuf.data())
1063  dvdnav_free_cache_block(m_dvdnav, blockBuf);
1064  }
1065  }
1066  break;
1067 
1068  // exit playback
1069  case DVDNAV_STOP:
1070  {
1071  LOG(VB_GENERAL, LOG_INFO, LOC + "DVDNAV_STOP");
1072  Size = tot;
1073  m_gotStop = true;
1074 
1075  // release buffer
1076  if (blockBuf != m_dvdBlockWriteBuf.data())
1077  dvdnav_free_cache_block(m_dvdnav, blockBuf);
1078  }
1079  break;
1080 
1081  // this shouldn't happen
1082  default:
1083  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Unknown DVD event: %1").arg(m_dvdEvent));
1084  break;
1085  }
1086 
1087  needed = static_cast<int>(Size - tot);
1088  offset = static_cast<int>(tot);
1089  }
1090 
1092  {
1093  errno = EAGAIN;
1094  return 0;
1095  }
1096  return static_cast<int>(tot);
1097 }
1098 
1100 {
1101  QMutexLocker lock(&m_seekLock);
1102  if (Track < 1)
1103  Seek(0);
1104  else if (Track < m_titleParts)
1105  dvdnav_part_play(m_dvdnav, m_title, Track);
1106  else
1107  return false;
1108  m_gotStop = false;
1109  return true;
1110 }
1111 
1113 {
1114  int newPart = m_part + 1;
1115 
1116  QMutexLocker lock(&m_seekLock);
1117  if (newPart < m_titleParts)
1118  {
1119  dvdnav_part_play(m_dvdnav, m_title, newPart);
1120  m_gotStop = false;
1121  return true;
1122  }
1123  return false;
1124 }
1125 
1127 {
1128  int newPart = m_part - 1;
1129 
1130  QMutexLocker lock(&m_seekLock);
1131  if (newPart > 0)
1132  dvdnav_part_play(m_dvdnav, m_title, newPart);
1133  else
1134  Seek(0);
1135  m_gotStop = false;
1136 }
1137 
1141 std::chrono::seconds MythDVDBuffer::GetTotalTimeOfTitle(void) const
1142 {
1143  return duration_cast<std::chrono::seconds>(m_pgcLength);
1144 }
1145 
1147 {
1148  return m_forcedAspect;
1149 }
1150 
1153 std::chrono::seconds MythDVDBuffer::GetCellStart(void) const
1154 {
1155  return duration_cast<std::chrono::seconds>(m_cellStart);
1156 }
1157 
1161 {
1162  bool ret = m_cellChanged;
1163  m_cellChanged = false;
1164  return ret;
1165 }
1166 
1168 {
1169  return dvdnav_get_next_still_flag(m_dvdnav) > 0;
1170 }
1171 
1173 {
1174  return m_audioStreamsChanged;
1175 }
1176 
1178 {
1179  return m_dvdWaiting;
1180 }
1181 
1183 {
1184  return m_titleParts;
1185 }
1186 
1190 {
1191  bool ret = m_pgcLengthChanged;
1192  m_pgcLengthChanged = false;
1193  return ret;
1194 }
1195 
1197 {
1198  QMutexLocker locker(&m_seekLock);
1199  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Skipping still frame.");
1200 
1201  m_still = 0s;
1202  dvdnav_still_skip(m_dvdnav);
1203 
1204  // Make sure the still frame timer is disabled.
1205  if (m_parent)
1207 }
1208 
1210 {
1211  QMutexLocker locker(&m_seekLock);
1212  dvdnav_wait_skip(m_dvdnav);
1213  m_dvdWaiting = false;
1214  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Exiting DVDNAV_WAIT status");
1215 }
1216 
1218 {
1219  m_playerWait = false;
1220 }
1221 
1223 {
1225 }
1226 
1228 {
1229  return m_processState == PROCESS_WAIT;
1230 }
1231 
1234 bool MythDVDBuffer::GoToMenu(const QString &str)
1235 {
1236  DVDMenuID_t menuid = DVD_MENU_Escape;
1237  QMutexLocker locker(&m_seekLock);
1238 
1239  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("DVDRingBuf: GoToMenu %1").arg(str));
1240 
1241  if (str.compare("chapter") == 0)
1242  menuid = DVD_MENU_Part;
1243  else if (str.compare("root") == 0)
1244  menuid = DVD_MENU_Root;
1245  else if (str.compare("title") == 0)
1246  menuid = DVD_MENU_Title;
1247  else
1248  return false;
1249 
1250  dvdnav_status_t ret = dvdnav_menu_call(m_dvdnav, menuid);
1251  return ret == DVDNAV_STATUS_OK;
1252 }
1253 
1259 {
1260  bool success = false;
1261  QString target;
1262 
1263  QMutexLocker locker(&m_seekLock);
1264 
1265  if (dvdnav_is_domain_vts(m_dvdnav) && !m_inMenu)
1266  {
1267  if (dvdnav_go_up(m_dvdnav) == DVDNAV_STATUS_OK)
1268  {
1269  target = "GoUp";
1270  success = true;
1271  }
1272  else if (dvdnav_menu_call(m_dvdnav, DVD_MENU_Root) == DVDNAV_STATUS_OK)
1273  {
1274  target = "Root";
1275  success = true;
1276  }
1277  else if (dvdnav_menu_call(m_dvdnav, DVD_MENU_Title) == DVDNAV_STATUS_OK)
1278  {
1279  target = "Title";
1280  success = true;
1281  }
1282  else
1283  {
1284  target = "Nothing available";
1285  }
1286  }
1287  else
1288  {
1289  target = QString("No jump, %1 menu").arg(m_inMenu ? "in" : "not in");
1290  }
1291 
1292  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("DVDRingBuf: GoBack - %1").arg(target));
1293  return success;
1294 }
1295 
1297 {
1298  QMutexLocker locker(&m_seekLock);
1299  // This conditional appears to be unnecessary, and might have come
1300  // from a mistake in a libdvdnav resync.
1301  //if (!dvdnav_is_domain_vts(m_dvdnav))
1302  dvdnav_next_pg_search(m_dvdnav);
1303 }
1304 
1306 {
1307  QMutexLocker locker(&m_seekLock);
1308  // This conditional appears to be unnecessary, and might have come
1309  // from a mistake in a libdvdnav resync.
1310  //if (!dvdnav_is_domain_vts(m_dvdnav))
1311  dvdnav_prev_pg_search(m_dvdnav);
1312 }
1313 
1314 bool MythDVDBuffer::HandleAction(const QStringList &Actions, mpeg::chrono::pts /*Pts*/)
1315 {
1316  if (!NumMenuButtons())
1317  return false;
1318 
1319  if (Actions.contains(ACTION_UP) || Actions.contains(ACTION_CHANNELUP))
1320  MoveButtonUp();
1321  else if (Actions.contains(ACTION_DOWN) || Actions.contains(ACTION_CHANNELDOWN))
1322  MoveButtonDown();
1323  else if (Actions.contains(ACTION_LEFT) || Actions.contains(ACTION_SEEKRWND))
1324  MoveButtonLeft();
1325  else if (Actions.contains(ACTION_RIGHT) || Actions.contains(ACTION_SEEKFFWD))
1326  MoveButtonRight();
1327  else if (Actions.contains(ACTION_SELECT))
1328  ActivateButton();
1329  else
1330  return false;
1331 
1332  return true;
1333 }
1334 
1336 {
1337  m_skipstillorwait = Ignore;
1338 }
1339 
1341 {
1342  if (NumMenuButtons() > 1)
1343  {
1344  pci_t *pci = dvdnav_get_current_nav_pci(m_dvdnav);
1345  dvdnav_left_button_select(m_dvdnav, pci);
1346  }
1347 }
1348 
1350 {
1351  if (NumMenuButtons() > 1)
1352  {
1353  pci_t *pci = dvdnav_get_current_nav_pci(m_dvdnav);
1354  dvdnav_right_button_select(m_dvdnav, pci);
1355  }
1356 }
1357 
1359 {
1360  if (NumMenuButtons() > 1)
1361  {
1362  pci_t *pci = dvdnav_get_current_nav_pci(m_dvdnav);
1363  dvdnav_upper_button_select(m_dvdnav, pci);
1364  }
1365 }
1366 
1368 {
1369  if (NumMenuButtons() > 1)
1370  {
1371  pci_t *pci = dvdnav_get_current_nav_pci(m_dvdnav);
1372  dvdnav_lower_button_select(m_dvdnav, pci);
1373  }
1374 }
1375 
1378 {
1379  if (NumMenuButtons() > 0)
1380  {
1382  pci_t *pci = dvdnav_get_current_nav_pci(m_dvdnav);
1383  dvdnav_button_activate(m_dvdnav, pci);
1384  }
1385 }
1386 
1388 void MythDVDBuffer::GetMenuSPUPkt(uint8_t *Buffer, int Size, int StreamID, uint32_t StartTime)
1389 {
1390  if (Size < 4)
1391  return;
1392 
1393  if (m_buttonStreamID != StreamID)
1394  return;
1395 
1396  QMutexLocker lock(&m_menuBtnLock);
1397 
1399  auto *spu_pkt = reinterpret_cast<uint8_t*>(av_malloc(static_cast<size_t>(Size)));
1400  memcpy(spu_pkt, Buffer, static_cast<size_t>(Size));
1401  m_menuSpuPkt = spu_pkt;
1402  m_menuBuflength = Size;
1403  if (!m_buttonSelected)
1404  {
1406  m_buttonSelected = true;
1407  }
1408 
1409  if (DVDButtonUpdate(false))
1410  {
1411  int32_t gotbutton = 0;
1413  m_menuSpuPkt, m_menuBuflength, StartTime);
1414  }
1415 }
1416 
1419 {
1420  // this is unlocked by ReleaseMenuButton
1421  m_menuBtnLock.lock();
1422 
1423  if ((m_menuBuflength > 4) && m_buttonExists && (NumMenuButtons() > 0))
1424  {
1425  Version = m_buttonVersion;
1426  return &(m_dvdMenuButton);
1427  }
1428 
1429  return nullptr;
1430 }
1431 
1432 
1434 {
1435  m_menuBtnLock.unlock();
1436 }
1437 
1441 {
1442  QRect rect(0,0,0,0);
1443  if (!m_buttonExists)
1444  return rect;
1445  rect.setRect(m_hlButton.x(), m_hlButton.y(), m_hlButton.width(), m_hlButton.height());
1446  return rect;
1447 }
1448 
1452 bool MythDVDBuffer::DecodeSubtitles(AVSubtitle *Subtitle, int *GotSubtitles,
1453  const uint8_t *SpuPkt, int BufSize, uint32_t StartTime)
1454 {
1455  #define GETBE16(p) (((p)[0] << 8) | (p)[1])
1456 
1457  AlphaArray alpha {0, 0, 0, 0};
1458  PaletteArray palette {0, 0, 0, 0};
1459 
1460  if (!SpuPkt)
1461  return false;
1462 
1463  if (BufSize < 4)
1464  return false;
1465 
1466  bool force_subtitle_display = false;
1467  Subtitle->rects = nullptr;
1468  Subtitle->num_rects = 0;
1469  Subtitle->start_display_time = StartTime;
1470  Subtitle->end_display_time = StartTime;
1471 
1472  int cmd_pos = GETBE16(SpuPkt + 2);
1473  while ((cmd_pos + 4) < BufSize)
1474  {
1475  int offset1 = -1;
1476  int offset2 = -1;
1477  int date = GETBE16(SpuPkt + cmd_pos);
1478  int next_cmd_pos = GETBE16(SpuPkt + cmd_pos + 2);
1479  int pos = cmd_pos + 4;
1480  int x1 = 0;
1481  int x2 = 0;
1482  int y1 = 0;
1483  int y2 = 0;
1484  while (pos < BufSize)
1485  {
1486  int cmd = SpuPkt[pos++];
1487  switch(cmd)
1488  {
1489  case 0x00:
1490  force_subtitle_display = true;
1491  break;
1492  case 0x01:
1493  Subtitle->start_display_time = ((static_cast<uint>(date) << 10) / 90) + StartTime;
1494  break;
1495  case 0x02:
1496  Subtitle->end_display_time = ((static_cast<uint>(date) << 10) / 90) + StartTime;
1497  break;
1498  case 0x03:
1499  {
1500  if ((BufSize - pos) < 2)
1501  goto fail;
1502 
1503  palette[3] = SpuPkt[pos] >> 4;
1504  palette[2] = SpuPkt[pos] & 0x0f;
1505  palette[1] = SpuPkt[pos + 1] >> 4;
1506  palette[0] = SpuPkt[pos + 1] & 0x0f;
1507  pos +=2;
1508  }
1509  break;
1510  case 0x04:
1511  {
1512  if ((BufSize - pos) < 2)
1513  goto fail;
1514  alpha[3] = SpuPkt[pos] >> 4;
1515  alpha[2] = SpuPkt[pos] & 0x0f;
1516  alpha[1] = SpuPkt[pos + 1] >> 4;
1517  alpha[0] = SpuPkt[pos + 1] & 0x0f;
1518  pos +=2;
1519  }
1520  break;
1521  case 0x05:
1522  {
1523  if ((BufSize - pos) < 6)
1524  goto fail;
1525  x1 = (SpuPkt[pos] << 4) | (SpuPkt[pos + 1] >> 4);
1526  x2 = ((SpuPkt[pos + 1] & 0x0f) << 8) | SpuPkt[pos + 2];
1527  y1 = (SpuPkt[pos + 3] << 4) | (SpuPkt[pos + 4] >> 4);
1528  y2 = ((SpuPkt[pos + 4] & 0x0f) << 8) | SpuPkt[pos + 5];
1529  pos +=6;
1530  }
1531  break;
1532  case 0x06:
1533  {
1534  if ((BufSize - pos) < 4)
1535  goto fail;
1536  offset1 = GETBE16(SpuPkt + pos);
1537  offset2 = GETBE16(SpuPkt + pos + 2);
1538  pos +=4;
1539  }
1540  break;
1541  case 0x07:
1542  {
1543  if ((BufSize - pos) < 2)
1544  goto fail;
1545 
1546  pos += GETBE16(SpuPkt + pos);
1547  }
1548  break;
1549  case 0xff:
1550  default:
1551  goto the_end;
1552  }
1553  }
1554  the_end:
1555  if (offset1 >= 0)
1556  {
1557  int width = x2 - x1 + 1;
1558  if (width < 0)
1559  width = 0;
1560  int height = y2 - y1 + 1;
1561  if (height < 0)
1562  height = 0;
1563  if (width > 0 && height > 0)
1564  {
1565  if (Subtitle->rects != nullptr)
1566  {
1567  for (uint i = 0; i < Subtitle->num_rects; i++)
1568  {
1569  av_free(Subtitle->rects[i]->data[0]);
1570  av_free(Subtitle->rects[i]->data[1]);
1571  av_freep(&Subtitle->rects[i]);
1572  }
1573  av_freep(&Subtitle->rects);
1574  Subtitle->num_rects = 0;
1575  }
1576 
1577  auto *bitmap = static_cast<uint8_t*>(av_malloc(static_cast<size_t>(width * height)));
1578  Subtitle->num_rects = (NumMenuButtons() > 0) ? 2 : 1;
1579  Subtitle->rects = static_cast<AVSubtitleRect**>(av_mallocz(sizeof(AVSubtitleRect*) * Subtitle->num_rects));
1580  for (uint i = 0; i < Subtitle->num_rects; i++)
1581  Subtitle->rects[i] = static_cast<AVSubtitleRect*>(av_mallocz(sizeof(AVSubtitleRect)));
1582  Subtitle->rects[0]->data[1] = static_cast<uint8_t*>(av_mallocz(4 * 4));
1583  DecodeRLE(bitmap, width * 2, width, (height + 1) / 2,
1584  SpuPkt, offset1 * 2, BufSize);
1585  DecodeRLE(bitmap + width, width * 2, width, height / 2,
1586  SpuPkt, offset2 * 2, BufSize);
1587  GuessPalette(reinterpret_cast<uint32_t*>(Subtitle->rects[0]->data[1]), palette, alpha);
1588  Subtitle->rects[0]->data[0] = bitmap;
1589  Subtitle->rects[0]->x = x1;
1590  Subtitle->rects[0]->y = y1;
1591  Subtitle->rects[0]->w = width;
1592  Subtitle->rects[0]->h = height;
1593  Subtitle->rects[0]->type = SUBTITLE_BITMAP;
1594  Subtitle->rects[0]->nb_colors = 4;
1595  Subtitle->rects[0]->linesize[0] = width;
1596  if (NumMenuButtons() > 0)
1597  {
1598  Subtitle->rects[1]->type = SUBTITLE_BITMAP;
1599  Subtitle->rects[1]->data[1] = static_cast<uint8_t*>(av_malloc(4 *4));
1600  GuessPalette(reinterpret_cast<uint32_t*>(Subtitle->rects[1]->data[1]),
1602  }
1603  else
1605  *GotSubtitles = 1;
1606  }
1607  }
1608  if (next_cmd_pos == cmd_pos)
1609  break;
1610  cmd_pos = next_cmd_pos;
1611  }
1612  if (Subtitle->num_rects > 0)
1613  {
1614  if (force_subtitle_display)
1615  {
1616  Subtitle->forced = 1;
1617  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Decoded forced subtitle");
1618  }
1619  return true;
1620  }
1621 fail:
1622  return false;
1623 }
1624 
1628 bool MythDVDBuffer::DVDButtonUpdate(bool ButtonMode)
1629 {
1630  if (!m_parent)
1631  return false;
1632 
1633  QSize videodispdim = m_parent->GetVideoSize();
1634  int videoheight = videodispdim.height();
1635  int videowidth = videodispdim.width();
1636 
1637  int32_t button = 0;
1638  dvdnav_highlight_area_t highlight;
1639  dvdnav_get_current_highlight(m_dvdnav, &button);
1640  pci_t *pci = dvdnav_get_current_nav_pci(m_dvdnav);
1641  dvdnav_status_t dvdRet =
1642  dvdnav_get_highlight_area_from_group(pci, DVD_BTN_GRP_Wide, button,
1643  static_cast<int32_t>(ButtonMode), &highlight);
1644 
1645  if (dvdRet == DVDNAV_STATUS_ERR)
1646  return false;
1647 
1648  for (uint i = 0 ; i < 4 ; i++)
1649  {
1650  m_buttonAlpha[i] = 0xf & (highlight.palette >> (4 * i));
1651  m_buttonColor[i] = 0xf & (highlight.palette >> (16 + 4 * i));
1652  }
1653 
1654  // If the button overlay has already been decoded, make sure
1655  // the correct palette for the current highlight is set
1656  if (m_dvdMenuButton.rects && (m_dvdMenuButton.num_rects > 1))
1657  {
1658  GuessPalette(reinterpret_cast<uint32_t*>(m_dvdMenuButton.rects[1]->data[1]),
1660  }
1661 
1662  m_hlButton.setCoords(highlight.sx, highlight.sy, highlight.ex, highlight.ey);
1663  return ((highlight.sx + highlight.sy) > 0) &&
1664  (highlight.sx < videowidth && highlight.sy < videoheight);
1665 }
1666 
1670 {
1671  if (m_buttonExists || m_dvdMenuButton.rects)
1672  {
1673  for (uint i = 0; i < m_dvdMenuButton.num_rects; i++)
1674  {
1675  AVSubtitleRect* rect = m_dvdMenuButton.rects[i];
1676  av_free(rect->data[0]);
1677  av_free(rect->data[1]);
1678  av_free(rect);
1679  }
1680  av_free(m_dvdMenuButton.rects);
1681  m_dvdMenuButton.rects = nullptr;
1682  m_dvdMenuButton.num_rects = 0;
1683  m_buttonExists = false;
1684  }
1685 }
1686 
1691 {
1692  if (m_menuBuflength == 0)
1693  return;
1694 
1695  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Clearing Menu SPU Packet" );
1696 
1697  ClearMenuButton();
1698 
1699  av_free(m_menuSpuPkt);
1700  m_menuBuflength = 0;
1701  m_hlButton.setRect(0, 0, 0, 0);
1702 }
1703 
1705 {
1706  pci_t *pci = dvdnav_get_current_nav_pci(m_dvdnav);
1707  int numButtons = pci->hli.hl_gi.btn_ns;
1708  if (numButtons > 0 && numButtons < 36)
1709  return numButtons;
1710  return 0;
1711 }
1712 
1716 {
1717  uint audioLang = 0;
1718  int8_t physicalStreamId = dvdnav_get_audio_logical_stream(m_dvdnav, static_cast<uint8_t>(Index));
1719 
1720  if (physicalStreamId >= 0)
1721  {
1722  uint16_t lang = dvdnav_audio_stream_to_lang(m_dvdnav, static_cast<uint8_t>(physicalStreamId));
1723  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Audio StreamID: %1; lang: %2").arg(Index).arg(lang));
1724  audioLang = ConvertLangCode(lang);
1725  }
1726  else
1727  {
1728  LOG(VB_PLAYBACK, LOG_WARNING, LOC + QString("Audio StreamID: %1 - not found!").arg(Index));
1729  }
1730 
1731  return audioLang;
1732 }
1733 
1740 {
1741  const uint AC3_OFFSET = 0x0080;
1742  const uint DTS_OFFSET = 0x0088;
1743  const uint LPCM_OFFSET = 0x00A0;
1744  const uint MP2_OFFSET = 0x01C0;
1745 
1746  if (StreamId >= MP2_OFFSET)
1747  StreamId -= MP2_OFFSET;
1748  else if (StreamId >= LPCM_OFFSET)
1749  StreamId -= LPCM_OFFSET;
1750  else if (StreamId >= DTS_OFFSET)
1751  StreamId -= DTS_OFFSET;
1752  else if (StreamId >= AC3_OFFSET)
1753  StreamId -= AC3_OFFSET;
1754 
1755  int logical = -1;
1756  for (uint8_t i = 0; i < 8; i++)
1757  {
1758  // Get the physical stream number at the given index
1759  // of the logical mapping table (function name is wrong!)
1760  int8_t phys = dvdnav_get_audio_logical_stream(m_dvdnav, i);
1761  if (static_cast<uint>(phys) == StreamId)
1762  {
1763  logical = i;
1764  break;
1765  }
1766  }
1767 
1768  return logical;
1769 }
1770 
1772 {
1773  int ret = -1;
1774  int8_t physicalStreamId = dvdnav_get_audio_logical_stream(m_dvdnav, static_cast<uint8_t>(Index));
1775  if (physicalStreamId < 0)
1776  return ret;
1777 
1778  audio_attr_t attributes;
1779  if (dvdnav_get_audio_attr(m_dvdnav, static_cast<uint8_t>(physicalStreamId), &attributes) == DVDNAV_STATUS_OK)
1780  {
1781  LOG(VB_AUDIO, LOG_INFO, QString("DVD Audio Track #%1 Language Extension Code - %2")
1782  .arg(Index).arg(attributes.code_extension));
1783  return attributes.code_extension;
1784  }
1785 
1786  return ret;
1787 }
1788 
1791 {
1792  uint16_t lang = dvdnav_spu_stream_to_lang(m_dvdnav, static_cast<uint8_t>(Id));
1793  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("StreamID: %1; lang: %2").arg(Id).arg(lang));
1794  return ConvertLangCode(lang);
1795 }
1796 
1801 {
1802  int8_t logstream = -1;
1803 
1804  // VM always sets stream_id to zero if we're not in the VTS
1805  // domain and always returns 0 (instead of -1) if nothing has
1806  // been found, so only try to retrieve the logical stream if
1807  // we *are* in the VTS domain or we *are* trying to map stream 0.
1808  if (dvdnav_is_domain_vts(m_dvdnav) || (StreamId == 0))
1809  logstream = dvdnav_get_spu_logical_stream(m_dvdnav, static_cast<uint8_t>(StreamId));
1810 
1811  return logstream;
1812 }
1813 
1816 {
1817  if (Code == 0)
1818  return 0;
1819 
1820  std::array<QChar,2> str2 { QChar(Code >> 8), QChar(Code & 0xff) };
1821  QString str3 = iso639_str2_to_str3(QString(str2.data(), str2.size()));
1822 
1823  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("code: %1; iso639: %2").arg(Code).arg(str3));
1824 
1825  if (!str3.isEmpty())
1826  return static_cast<uint>(iso639_str3_to_key(str3));
1827  return 0;
1828 }
1829 
1834 {
1835  pci_t *pci = dvdnav_get_current_nav_pci(m_dvdnav);
1836  int32_t button = pci->hli.hl_gi.fosl_btnn;
1837  if (button > 0 && !m_cellRepeated)
1838  {
1839  dvdnav_button_select(m_dvdnav,pci,button);
1840  return;
1841  }
1842  dvdnav_get_current_highlight(m_dvdnav,&button);
1843  if (button > 0 && button <= NumMenuButtons())
1844  dvdnav_button_select(m_dvdnav,pci,button);
1845  else
1846  dvdnav_button_select(m_dvdnav,pci,1);
1847 }
1848 
1853 void MythDVDBuffer::SetTrack(uint Type, int TrackNo)
1854 {
1855  if (Type == kTrackTypeSubtitle)
1856  {
1857  m_curSubtitleTrack = static_cast<int8_t>(TrackNo);
1858  m_autoselectsubtitle = TrackNo < 0;
1859  }
1860  else if (Type == kTrackTypeAudio)
1861  {
1862  m_curAudioTrack = TrackNo;
1863  dvdnav_set_active_audio_stream(m_dvdnav, static_cast<int8_t>(TrackNo));
1864  }
1865 }
1866 
1873 {
1874  if (Type == kTrackTypeSubtitle)
1875  return m_curSubtitleTrack;
1876  if (Type == kTrackTypeAudio)
1877  return m_curAudioTrack;
1878  return 0;
1879 }
1880 
1882 {
1883  int8_t physical = dvdnav_get_audio_logical_stream(m_dvdnav, static_cast<uint8_t>(Index));
1884  if (physical >= 0)
1885  {
1886  uint16_t channels = dvdnav_audio_stream_channels(m_dvdnav, static_cast<uint8_t>(physical));
1887  if (channels != 0xFFFf)
1888  return channels;
1889  }
1890  return 0;
1891 }
1892 
1894 {
1895  m_audioStreamsChanged = Change;
1896 }
1897 
1900 bool MythDVDBuffer::GetNameAndSerialNum(QString& Name, QString& SerialNumber)
1901 {
1902  Name = m_discName;
1903  SerialNumber = m_discSerialNumber;
1904  return !(Name.isEmpty() && SerialNumber.isEmpty());
1905 }
1906 
1910 {
1911  State.clear();
1912  char* dvdstate = dvdnav_get_state(m_dvdnav);
1913 
1914  if (dvdstate)
1915  {
1916  State = dvdstate;
1917  free(dvdstate);
1918  }
1919 
1920  return (!State.isEmpty());
1921 }
1922 
1926 {
1927  QByteArray state = State.toUtf8();
1928  return (dvdnav_set_state(m_dvdnav, state.constData()) == DVDNAV_STATUS_OK);
1929 }
1930 
1937 {
1938  int format = dvdnav_get_video_format(m_dvdnav);
1939  double dvdfps = (format == 1) ? 25.00 : 29.97;
1940  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("DVD Frame Rate %1").arg(dvdfps));
1941  return dvdfps;
1942 }
1943 
1945 {
1946  return m_part == 0;
1947 }
1948 
1950 {
1951  return ((m_titleParts == 0) || (m_part == (m_titleParts - 1)) || (m_titleParts == 1));
1952 }
1953 
1954 void MythDVDBuffer::PlayTitleAndPart(int Title, int Part)
1955 {
1956  dvdnav_part_play(m_dvdnav, Title, Part);
1957 }
1958 
1961 {
1962  QMutexLocker lock(&m_seekLock);
1964 }
1965 
1968 {
1969  if (m_filename.startsWith("/"))
1970  MediaMonitor::SetCDSpeed(m_filename.toLocal8Bit().constData(), Speed);
1971 }
1972 
1974 std::chrono::seconds MythDVDBuffer::TitleTimeLeft(void) const
1975 {
1976  return GetTotalTimeOfTitle() - GetCurrentTime();
1977 }
1978 
1979 std::chrono::seconds MythDVDBuffer::GetCurrentTime(void) const
1980 {
1981  return duration_cast<std::chrono::seconds>(m_currentTime);
1982 }
1983 
1985 void MythDVDBuffer::GuessPalette(uint32_t *RGBAPalette, const PaletteArray Palette, const AlphaArray Alpha)
1986 {
1987  memset(RGBAPalette, 0, 16);
1988  for (int i = 0 ; i < 4 ; i++)
1989  {
1990  uint32_t yuv = m_clut[Palette[i]];
1991  uint y = (yuv >> 16) & 0xff;
1992  uint cr = (yuv >> 8) & 0xff;
1993  uint cb = (yuv >> 0) & 0xff;
1994  uint r = qBound(0U, uint(y + 1.4022 * (cr - 128)), 0xFFU);
1995  uint b = qBound(0U, uint(y + 1.7710 * (cb - 128)), 0xFFU);
1996  uint g = qBound(0U, uint(1.7047 * y - (0.1952 * b) - (0.5647 * r)), 0xFFU);
1997  RGBAPalette[i] = ((Alpha[i] * 17U) << 24) | (r << 16 )| (g << 8) | b;
1998  }
1999 }
2000 
2004 int MythDVDBuffer::DecodeRLE(uint8_t *Bitmap, int Linesize, int Width, int Height,
2005  const uint8_t *Buffer, int NibbleOffset, int BufferSize)
2006 {
2007  int nibbleEnd = BufferSize * 2;
2008  int x = 0;
2009  int y = 0;
2010  uint8_t *data = Bitmap;
2011  for(;;)
2012  {
2013  if (NibbleOffset >= nibbleEnd)
2014  return -1;
2015  uint v = GetNibble(Buffer, NibbleOffset++);
2016  if (v < 0x4)
2017  {
2018  v = (v << 4) | GetNibble(Buffer, NibbleOffset++);
2019  if (v < 0x10)
2020  {
2021  v = (v << 4) | GetNibble(Buffer, NibbleOffset++);
2022  if (v < 0x040)
2023  {
2024  v = (v << 4) | GetNibble(Buffer, NibbleOffset++);
2025  if (v < 4)
2026  v |= static_cast<uint>(Width - x) << 2;
2027  }
2028  }
2029  }
2030  int len = v >> 2;
2031  if (len > (Width - x))
2032  len = Width - x;
2033  int color = v & 0x03;
2034  memset(data + x, color, static_cast<size_t>(len));
2035  x += len;
2036  if (x >= Width)
2037  {
2038  y++;
2039  if (y >= Height)
2040  break;
2041  data += Linesize;
2042  x = 0;
2043  NibbleOffset += (NibbleOffset & 1);
2044  }
2045  }
2046  return 0;
2047 }
2048 
2051 uint MythDVDBuffer::GetNibble(const uint8_t *Buffer, int NibbleOffset)
2052 {
2053  return (Buffer[NibbleOffset >> 1] >> ((1 - (NibbleOffset & 1)) << 2)) & 0xf;
2054 }
2055 
2060 int MythDVDBuffer::IsTransparent(const uint8_t *Buffer, int Pitch, int Num, const ColorArray& Colors)
2061 {
2062  for (int i = 0; i < Num; i++)
2063  {
2064  if (!Colors[*Buffer])
2065  return 0;
2066  Buffer += Pitch;
2067  }
2068  return 1;
2069 }
2070 
2076 {
2077  ColorArray colors {};
2078 
2079  if (Subtitle->num_rects == 0 || Subtitle->rects == nullptr ||
2080  Subtitle->rects[0]->w <= 0 || Subtitle->rects[0]->h <= 0)
2081  {
2082  return 0;
2083  }
2084 
2085  for (int i = 0; i < Subtitle->rects[0]->nb_colors; i++)
2086  if (((reinterpret_cast<uint32_t*>(Subtitle->rects[0]->data[1])[i] >> 24)) == 0)
2087  colors[i] = 1;
2088 
2089  int bottom = 0;
2090  while (bottom < Subtitle->rects[0]->h &&
2091  IsTransparent(Subtitle->rects[0]->data[0] + bottom * Subtitle->rects[0]->linesize[0],
2092  1, Subtitle->rects[0]->w, colors))
2093  {
2094  bottom++;
2095  }
2096 
2097  if (bottom == Subtitle->rects[0]->h)
2098  {
2099  av_freep(&Subtitle->rects[0]->data[0]);
2100  Subtitle->rects[0]->w = Subtitle->rects[0]->h = 0;
2101  return 0;
2102  }
2103 
2104  int top = Subtitle->rects[0]->h - 1;
2105  while (top > 0 &&
2106  IsTransparent(Subtitle->rects[0]->data[0] + top * Subtitle->rects[0]->linesize[0], 1,
2107  Subtitle->rects[0]->w, colors))
2108  {
2109  top--;
2110  }
2111 
2112  int left = 0;
2113  while (left < (Subtitle->rects[0]->w - 1) &&
2114  IsTransparent(Subtitle->rects[0]->data[0] + left, Subtitle->rects[0]->linesize[0],
2115  Subtitle->rects[0]->h, colors))
2116  {
2117  left++;
2118  }
2119 
2120  int right = Subtitle->rects[0]->w - 1;
2121  while (right > 0 &&
2122  IsTransparent(Subtitle->rects[0]->data[0] + right, Subtitle->rects[0]->linesize[0],
2123  Subtitle->rects[0]->h, colors))
2124  {
2125  right--;
2126  }
2127 
2128  int width = right - left + 1;
2129  int height = top - bottom + 1;
2130  auto *bitmap = static_cast<uint8_t*>(av_malloc(static_cast<size_t>(width * height)));
2131  if (!bitmap)
2132  return 1;
2133 
2134  for (int y = 0; y < height; y++)
2135  {
2136  memcpy(bitmap + width * y, Subtitle->rects[0]->data[0] + left +
2137  (bottom + y) * Subtitle->rects[0]->linesize[0], static_cast<size_t>(width));
2138  }
2139 
2140  av_freep(&Subtitle->rects[0]->data[0]);
2141  Subtitle->rects[0]->data[0] = bitmap;
2142  Subtitle->rects[0]->linesize[0] = width;
2143  Subtitle->rects[0]->w = width;
2144  Subtitle->rects[0]->h = height;
2145  Subtitle->rects[0]->x += left;
2146  Subtitle->rects[0]->y += bottom;
2147  return 1;
2148 }
2149 
2151 {
2152  if (!m_dvdnav)
2153  return false;
2154 
2155  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Switching to Angle %1...").arg(Angle));
2156  dvdnav_status_t status = dvdnav_angle_change(m_dvdnav, static_cast<int32_t>(Angle));
2157  if (status == DVDNAV_STATUS_OK)
2158  {
2159  m_currentAngle = Angle;
2160  return true;
2161  }
2162  return false;
2163 }
2164 
2166 {
2167  m_parent = Parent;
2168 }
MythDVDBuffer::m_context
MythDVDContext * m_context
Definition: mythdvdbuffer.h:207
MythDVDBuffer::m_dvdnav
dvdnav_t * m_dvdnav
Definition: mythdvdbuffer.h:154
MythDVDBuffer::ClearMenuSPUParameters
void ClearMenuSPUParameters(void)
clears the menu SPU pkt and parameters.
Definition: mythdvdbuffer.cpp:1690
MythDVDBuffer::PlayTrack
bool PlayTrack(int Track)
Definition: mythdvdbuffer.cpp:1099
MythDVDBuffer::GetCurrentTime
std::chrono::seconds GetCurrentTime(void) const
Definition: mythdvdbuffer.cpp:1979
ACTION_UP
#define ACTION_UP
Definition: mythuiactions.h:16
MythDVDBuffer::IsOpen
bool IsOpen(void) const override
Definition: mythdvdbuffer.cpp:212
MythDVDBuffer::m_lastvobid
int m_lastvobid
Definition: mythdvdbuffer.h:190
MythDVDBuffer::m_lastStill
std::chrono::seconds m_lastStill
Definition: mythdvdbuffer.h:177
MythDVDBuffer::~MythDVDBuffer
~MythDVDBuffer() override
Definition: mythdvdbuffer.cpp:49
MythDVDContext::GetLBA
uint32_t GetLBA(void) const
Definition: mythdvdcontext.cpp:29
build_compdb.dest
dest
Definition: build_compdb.py:9
MythDVDBuffer::GetTrack
int GetTrack(uint Type) const
get the track the dvd should be playing.
Definition: mythdvdbuffer.cpp:1872
AlphaArray
std::array< uint8_t, 4 > AlphaArray
Definition: mythdvdbuffer.h:34
MythDVDBuffer::m_cellRepeated
bool m_cellRepeated
Definition: mythdvdbuffer.h:191
MythDVDBuffer::m_vobid
int m_vobid
Definition: mythdvdbuffer.h:189
MythDVDBuffer::TitleTimeLeft
std::chrono::seconds TitleTimeLeft(void) const
returns seconds left in the title
Definition: mythdvdbuffer.cpp:1974
ENO
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:72
MythDVDBuffer::m_buttonAlpha
PaletteArray m_buttonAlpha
Definition: mythdvdbuffer.h:215
MythDVDBuffer::m_lastPart
int32_t m_lastPart
Definition: mythdvdbuffer.h:167
copy
long long copy(QFile &dst, QFile &src, uint block_size)
Copies src file to dst file.
Definition: mythmiscutil.cpp:311
MythDVDBuffer::CloseDVD
void CloseDVD(void)
Definition: mythdvdbuffer.cpp:60
ReferenceCounter::DecrRef
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
Definition: referencecounter.cpp:125
MythDVDBuffer::m_still
std::chrono::seconds m_still
Definition: mythdvdbuffer.h:176
MythDVDBuffer::GetAspectOverride
float GetAspectOverride(void) const
Definition: mythdvdbuffer.cpp:1146
MythDVDBuffer::RestoreDVDStateSnapshot
bool RestoreDVDStateSnapshot(QString &State)
Restore a DVD VM from a snapshot.
Definition: mythdvdbuffer.cpp:1925
MythDVDBuffer::SkipStillFrame
void SkipStillFrame(void)
Definition: mythdvdbuffer.cpp:1196
MythDVDBuffer::m_buttonStreamID
int m_buttonStreamID
Definition: mythdvdbuffer.h:212
MythDVDBuffer::m_lastcellid
int m_lastcellid
Definition: mythdvdbuffer.h:188
MythDVDBuffer::m_dvdBlockWriteBuf
DvdBuffer m_dvdBlockWriteBuf
Definition: mythdvdbuffer.h:155
MythMediaBuffer::m_readAdjust
long long m_readAdjust
Definition: mythmediabuffer.h:219
MythDVDBuffer::DVDButtonUpdate
bool DVDButtonUpdate(bool ButtonMode)
update the dvd menu button parameters when a user changes the dvd menu button position
Definition: mythdvdbuffer.cpp:1628
ACTION_DOWN
#define ACTION_DOWN
Definition: mythuiactions.h:17
MythDVDBuffer::m_menuBuflength
int m_menuBuflength
Definition: mythdvdbuffer.h:218
MythDVDBuffer::m_skipstillorwait
bool m_skipstillorwait
Definition: mythdvdbuffer.h:181
HALFSECOND
static constexpr mpeg::chrono::pts HALFSECOND
Definition: mythdvdbuffer.cpp:378
MythDVDBuffer::IsInStillFrame
bool IsInStillFrame(void) const override
Definition: mythdvdbuffer.cpp:222
MythDVDBuffer::m_pgLength
mpeg::chrono::pts m_pgLength
Definition: mythdvdbuffer.h:159
MythDVDBuffer::ClearMenuButton
void ClearMenuButton(void)
clears the dvd menu button structures
Definition: mythdvdbuffer.cpp:1669
MythDVDBuffer::GetPartAndTitle
void GetPartAndTitle(int &Part, int &Title) const
Definition: mythdvdbuffer.cpp:461
MythMediaBuffer::m_commsError
bool m_commsError
Definition: mythmediabuffer.h:215
x2
static int x2
Definition: mythsocket.cpp:58
MythDVDBuffer::SetTrack
void SetTrack(uint Type, int TrackNo)
set the dvd subtitle/audio track used
Definition: mythdvdbuffer.cpp:1853
MythDVDBuffer::m_dvdEvent
int32_t m_dvdEvent
Definition: mythdvdbuffer.h:209
MythDVDBuffer::m_cellStart
mpeg::chrono::pts m_cellStart
Definition: mythdvdbuffer.h:161
kMythBufferDVD
@ kMythBufferDVD
Definition: mythmediabuffer.h:43
MythDVDBuffer::DecodeSubtitles
bool DecodeSubtitles(AVSubtitle *Subtitle, int *GotSubtitles, const uint8_t *SpuPkt, int BufSize, uint32_t StartTime)
generate dvd subtitle bitmap or dvd menu bitmap.
Definition: mythdvdbuffer.cpp:1452
MythMediaBuffer::m_safeFilename
QString m_safeFilename
Definition: mythmediabuffer.h:181
MythDVDBuffer::m_menuBtnLock
QMutex m_menuBtnLock
Definition: mythdvdbuffer.h:220
MythDVDBuffer::StartOfTitle
bool StartOfTitle(void) const
Definition: mythdvdbuffer.cpp:1944
MythDVDBuffer::GetDVDContext
MythDVDContext * GetDVDContext(void)
Definition: mythdvdbuffer.cpp:483
MythMediaBuffer::CalcReadAheadThresh
void CalcReadAheadThresh(void)
Calculates m_fillMin, m_fillThreshold, and m_readBlockSize from the estimated effective bitrate of th...
Definition: mythmediabuffer.cpp:344
mythdvdbuffer.h
MythDVDBuffer::IsBookmarkAllowed
bool IsBookmarkAllowed(void) override
Definition: mythdvdbuffer.cpp:217
MythMainWindow::RestoreScreensaver
static void RestoreScreensaver()
Definition: mythmainwindow.cpp:576
mythmediamonitor.h
MythDVDBuffer::m_forcedAspect
float m_forcedAspect
Definition: mythdvdbuffer.h:201
MythDVDBuffer::m_timeDiff
int64_t m_timeDiff
Definition: mythdvdbuffer.h:175
IncrementButtonVersion
#define IncrementButtonVersion
Definition: mythdvdbuffer.cpp:23
MythDVDBuffer::SelectDefaultButton
void SelectDefaultButton(void)
determines the default dvd menu button to show when you initially access the dvd menu.
Definition: mythdvdbuffer.cpp:1833
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythMediaBuffer::m_lastError
QString m_lastError
Definition: mythmediabuffer.h:186
MythMediaBuffer::m_generalWait
QWaitCondition m_generalWait
Condition to signal that the read ahead thread is running.
Definition: mythmediabuffer.h:237
MythDVDBuffer::m_dvdMenuButton
AVSubtitle m_dvdMenuButton
Definition: mythdvdbuffer.h:219
MythDVDBuffer::GoToMenu
bool GoToMenu(const QString &str)
jump to a dvd root or chapter menu
Definition: mythdvdbuffer.cpp:1234
MythDVDBuffer::m_pgStart
long long m_pgStart
Definition: mythdvdbuffer.h:164
MythDVDBuffer::GetTitle
int GetTitle(void) const
Definition: mythdvdbuffer.cpp:426
MythDVDBuffer::m_currentTime
mpeg::chrono::pts m_currentTime
Definition: mythdvdbuffer.h:197
Bitmap
Definition: polygon.h:7
MythDVDBuffer::GetFrameRate
double GetFrameRate(void)
used by DecoderBase for the total frame number calculation for position map support and ffw/rew.
Definition: mythdvdbuffer.cpp:1936
MythOpticalBuffer::PROCESS_WAIT
@ PROCESS_WAIT
Definition: mythopticalbuffer.h:21
MythDVDBuffer::GetLastEvent
int32_t GetLastEvent(void) const
Definition: mythdvdbuffer.cpp:491
MythDVDBuffer::SkipDVDWaitingForPlayer
void SkipDVDWaitingForPlayer(void)
Definition: mythdvdbuffer.cpp:1217
MythDVDBuffer::IsTransparent
static int IsTransparent(const uint8_t *Buffer, int Pitch, int Num, const ColorArray &Colors)
Obtained from ffmpeg dvdsubdec.c Used to find smallest bounded rectangle.
Definition: mythdvdbuffer.cpp:2060
MythDVDBuffer::CellChanged
bool CellChanged(void)
check if dvd cell has changed
Definition: mythdvdbuffer.cpp:1160
MythDVDBuffer::GetTotalTimeOfTitle
std::chrono::seconds GetTotalTimeOfTitle(void) const
get the total time of the title in seconds 90000 ticks = 1 sec
Definition: mythdvdbuffer.cpp:1141
MythDVDBuffer::m_currentTitleAngleCount
int m_currentTitleAngleCount
Definition: mythdvdbuffer.h:173
MediaMonitor::SetCDSpeed
static void SetCDSpeed(const char *device, int speed)
Definition: mythmediamonitor.cpp:101
MythDVDBuffer::MoveButtonRight
void MoveButtonRight(void)
Definition: mythdvdbuffer.cpp:1349
MythDVDBuffer::m_hlButton
QRect m_hlButton
Definition: mythdvdbuffer.h:216
MythDVDBuffer::m_seektime
mpeg::chrono::pts m_seektime
Definition: mythdvdbuffer.h:196
MythDVDBuffer::m_menuSpuPkt
uint8_t * m_menuSpuPkt
Definition: mythdvdbuffer.h:217
MythDVDBuffer::SetParent
void SetParent(MythDVDPlayer *Parent)
Definition: mythdvdbuffer.cpp:2165
MythDVDBuffer::IsReadingBlocked
bool IsReadingBlocked(void)
Definition: mythdvdbuffer.cpp:1227
MythDVDBuffer::m_audioStreamsChanged
bool m_audioStreamsChanged
Definition: mythdvdbuffer.h:178
MythOpticalBuffer::m_discSerialNumber
QString m_discSerialNumber
Definition: mythopticalbuffer.h:28
MythMediaBuffer::m_rawBitrate
uint m_rawBitrate
Definition: mythmediabuffer.h:208
MythDVDBuffer::DVDWaitingForPlayer
bool DVDWaitingForPlayer(void) const
Definition: mythdvdbuffer.cpp:431
MythMainWindow::DisableScreensaver
static void DisableScreensaver()
Definition: mythmainwindow.cpp:582
StreamID
Contains listing of PMT Stream ID's for various A/V Stream types.
Definition: mpegtables.h:109
x4
static int x4
Definition: mythsocket.cpp:60
MythDVDBuffer::m_title
int32_t m_title
Definition: mythdvdbuffer.h:168
MythDVDBuffer::OpenFile
bool OpenFile(const QString &Filename, std::chrono::milliseconds Retry=kDefaultOpenTimeout) override
Opens a dvd device for reading.
Definition: mythdvdbuffer.cpp:256
MythDVDBuffer::GetCurrentAngle
int GetCurrentAngle(void) const
Definition: mythdvdbuffer.cpp:441
ColorArray
std::array< uint8_t, 256 > ColorArray
Definition: mythdvdbuffer.h:36
MythDVDBuffer::IsSeekingAllowed
bool IsSeekingAllowed(void) override
Definition: mythdvdbuffer.cpp:227
MythMediaBuffer::m_readPos
long long m_readPos
Definition: mythmediabuffer.h:165
MythDVDBuffer::GetNibble
static uint GetNibble(const uint8_t *Buffer, int NibbleOffset)
copied from ffmpeg's dvdsubdec.c
Definition: mythdvdbuffer.cpp:2051
MythDVDBuffer::IgnoreWaitStates
void IgnoreWaitStates(bool Ignore) override
Definition: mythdvdbuffer.cpp:1335
MythDVDBuffer::m_currentpos
long long m_currentpos
Definition: mythdvdbuffer.h:165
mythlogging.h
MythDVDBuffer::PlayTitleAndPart
void PlayTitleAndPart(int Title, int Part)
Definition: mythdvdbuffer.cpp:1954
MythDVDBuffer::GetButtonCoords
QRect GetButtonCoords(void)
get coordinates of highlighted button
Definition: mythdvdbuffer.cpp:1440
MythDVDBuffer::m_titleParts
int32_t m_titleParts
Definition: mythdvdbuffer.h:171
tv_actions.h
MythDVDBuffer::m_pgcLengthChanged
bool m_pgcLengthChanged
Definition: mythdvdbuffer.h:163
ACTION_RIGHT
#define ACTION_RIGHT
Definition: mythuiactions.h:19
MythDVDBuffer::m_part
int32_t m_part
Definition: mythdvdbuffer.h:166
mythdvdplayer.h
MythDVDBuffer::GetAudioTrackType
int GetAudioTrackType(uint Index)
Definition: mythdvdbuffer.cpp:1771
MythDVDBuffer::EndOfTitle
bool EndOfTitle(void) const
Definition: mythdvdbuffer.cpp:1949
compat.h
MythDVDBuffer::GetAudioTrackNum
int GetAudioTrackNum(uint StreamId)
get the logical track index (into PGC_AST_CTL) of the element that maps the given physical stream id.
Definition: mythdvdbuffer.cpp:1739
MythDVDBuffer::GoBack
bool GoBack(void)
Attempts to back-up by trying to jump to the 'Go up' PGC, the root menu or the title menu in turn.
Definition: mythdvdbuffer.cpp:1258
MythDVDBuffer::m_contextLock
QRecursiveMutex m_contextLock
Definition: mythdvdbuffer.h:205
MythDVDPlayer
Definition: mythdvdplayer.h:10
MythDVDBuffer::GetDescForPos
void GetDescForPos(QString &Description) const
Definition: mythdvdbuffer.cpp:237
x1
static int x1
Definition: mythsocket.cpp:57
MythDVDBuffer::StartFromBeginning
bool StartFromBeginning(void) override
Definition: mythdvdbuffer.cpp:324
MythDVDBuffer::m_dvdEventSize
int32_t m_dvdEventSize
Definition: mythdvdbuffer.h:210
State
State
Definition: zmserver.h:68
MythMediaBuffer::m_readBlockSize
int m_readBlockSize
Definition: mythmediabuffer.h:212
GETBE16
#define GETBE16(p)
MythDVDContext::GetStartPTS
int64_t GetStartPTS(void) const
Definition: mythdvdcontext.cpp:14
LOC
#define LOC
Definition: mythdvdbuffer.cpp:21
MythDVDContext
Encapsulates playback context at any given moment.
Definition: mythdvdcontext.h:16
MythDVDBuffer::PGCLengthChanged
bool PGCLengthChanged(void)
check if pgc length has changed
Definition: mythdvdbuffer.cpp:1189
MythDVDBuffer::m_chapterMap
QMap< int, QList< std::chrono::seconds > > m_chapterMap
Definition: mythdvdbuffer.h:199
MythMediaBuffer::m_setSwitchToNext
bool m_setSwitchToNext
Definition: mythmediabuffer.h:207
ACTION_SELECT
#define ACTION_SELECT
Definition: mythuiactions.h:15
ACTION_SEEKRWND
#define ACTION_SEEKRWND
Definition: tv_actions.h:42
MythDVDBuffer::GetAudioLanguage
uint GetAudioLanguage(int Index)
get the audio language from the dvd
Definition: mythdvdbuffer.cpp:1715
MythDVDBuffer::AudioStreamsChanged
bool AudioStreamsChanged(void) const
Definition: mythdvdbuffer.cpp:1172
MythDVDBuffer::m_playerWait
bool m_playerWait
Definition: mythdvdbuffer.h:170
MythMediaBuffer::m_numFailures
int m_numFailures
Definition: mythmediabuffer.h:214
kTrackTypeAudio
@ kTrackTypeAudio
Definition: decoderbase.h:29
MythDVDBuffer::m_titleLength
long long m_titleLength
Definition: mythdvdbuffer.h:180
MythDVDBuffer::MoveButtonLeft
void MoveButtonLeft(void)
Definition: mythdvdbuffer.cpp:1340
uint
unsigned int uint
Definition: compat.h:140
MythDVDBuffer::ReleaseMenuButton
void ReleaseMenuButton(void)
Definition: mythdvdbuffer.cpp:1433
MythDVDBuffer::NumPartsInTitle
int NumPartsInTitle(void) const
Definition: mythdvdbuffer.cpp:1182
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:60
MythDVDBuffer::IsWaiting
bool IsWaiting(void) const
Definition: mythdvdbuffer.cpp:1177
MythMediaBuffer::m_filename
QString m_filename
Definition: mythmediabuffer.h:184
MythDVDBuffer::kSeekSpeedMap
static const QMap< int, int > kSeekSpeedMap
Definition: mythdvdbuffer.h:198
MythDVDBuffer::WaitForPlayer
void WaitForPlayer(void)
Definition: mythdvdbuffer.cpp:496
MythDVDBuffer::NormalSeek
long long NormalSeek(long long Time)
Definition: mythdvdbuffer.cpp:144
kTrackTypeSubtitle
@ kTrackTypeSubtitle
Definition: decoderbase.h:31
DVDMenuTable
static const std::array< const std::string, 8 > DVDMenuTable
Definition: mythdvdbuffer.cpp:27
MythDVDBuffer::m_seeking
bool m_seeking
Definition: mythdvdbuffer.h:195
DVD_DRIVE_SPEED
#define DVD_DRIVE_SPEED
Definition: mythdvdbuffer.cpp:24
MythDVDBuffer::m_pgcLength
mpeg::chrono::pts m_pgcLength
Definition: mythdvdbuffer.h:160
MythDVDBuffer::GetChapterTimes
void GetChapterTimes(QList< std::chrono::seconds > &Times)
Definition: mythdvdbuffer.cpp:368
MythDVDBuffer::m_lastButtonSeenInCell
bool m_lastButtonSeenInCell
Definition: mythdvdbuffer.h:186
MythDVDBuffer::AdjustTimestamp
uint32_t AdjustTimestamp(uint32_t Timestamp) const
Definition: mythdvdbuffer.cpp:467
MythOpticalBuffer::m_inMenu
bool m_inMenu
Definition: mythopticalbuffer.h:26
MythDVDBuffer::GetMenuSubtitle
AVSubtitle * GetMenuSubtitle(uint &Version)
returns dvd menu button information if available.
Definition: mythdvdbuffer.cpp:1418
MythDVDBuffer::Seek
long long Seek(long long Time)
Definition: mythdvdbuffer.cpp:167
MythDVDBuffer::m_lastTitle
int32_t m_lastTitle
Definition: mythdvdbuffer.h:169
MythDVDBuffer::SetDVDSpeed
void SetDVDSpeed(void)
set dvd speed. uses the constant DVD_DRIVE_SPEED table
Definition: mythdvdbuffer.cpp:1960
DVD_MENU_MAX
#define DVD_MENU_MAX
Definition: mythdvdbuffer.h:29
MythMediaBuffer::KillReadAheadThread
void KillReadAheadThread(void)
Stops the read-ahead thread, and waits for it to stop.
Definition: mythmediabuffer.cpp:646
MythDVDBuffer::GoToNextProgram
void GoToNextProgram(void)
Definition: mythdvdbuffer.cpp:1296
Buffer
Definition: MythExternControl.h:36
MythOpticalBuffer::m_currentAngle
int m_currentAngle
Definition: mythopticalbuffer.h:25
MythDVDBuffer::GetCellStart
std::chrono::seconds GetCellStart(void) const
get the start of the cell in seconds
Definition: mythdvdbuffer.cpp:1153
MythDVDBuffer::GetNumAngles
int GetNumAngles(void) const
Definition: mythdvdbuffer.cpp:446
MythDVDBuffer::m_parent
MythDVDPlayer * m_parent
Definition: mythdvdbuffer.h:200
MythDVDBuffer::m_curSubtitleTrack
int8_t m_curSubtitleTrack
Definition: mythdvdbuffer.h:193
MythOpticalBuffer::m_discName
QString m_discName
Definition: mythopticalbuffer.h:27
MythMediaBuffer::ResetReadAhead
void ResetReadAhead(long long NewInternal)
Restart the read-ahead thread at the 'newinternal' position.
Definition: mythmediabuffer.cpp:568
hardwareprofile.devicelist.pci
pci
Definition: devicelist.py:109
MythDVDBuffer::PrevTrack
void PrevTrack(void)
Definition: mythdvdbuffer.cpp:1126
Name
Definition: channelsettings.cpp:46
MythDVDBuffer::ActivateButton
void ActivateButton(void)
Action taken when a dvd menu button is selected.
Definition: mythdvdbuffer.cpp:1377
MythDVDBuffer::GetNameAndSerialNum
bool GetNameAndSerialNum(QString &Name, QString &SerialNumber) override
Get the dvd title and serial num.
Definition: mythdvdbuffer.cpp:1900
MythDVDBuffer::m_cellstartPos
long long m_cellstartPos
Definition: mythdvdbuffer.h:182
MythPlayer::GetVideoSize
QSize GetVideoSize(void) const
Definition: mythplayer.h:134
MythDVDBuffer::m_buttonColor
AlphaArray m_buttonColor
Definition: mythdvdbuffer.h:214
MythDVDBuffer::GetPart
int GetPart(void) const
Definition: mythdvdbuffer.cpp:436
MythDVDBuffer::m_gotStop
bool m_gotStop
Definition: mythdvdbuffer.h:172
MythDVDBuffer::m_endPts
int64_t m_endPts
Definition: mythdvdbuffer.h:174
MythDVDBuffer::SeekInternal
long long SeekInternal(long long Position, int Whence) override
Definition: mythdvdbuffer.cpp:91
MythDVDBuffer::m_autoselectsubtitle
bool m_autoselectsubtitle
Definition: mythdvdbuffer.h:194
MythDVDInfo::GetNameAndSerialNum
bool GetNameAndSerialNum(QString &Name, QString &SerialNumber)
Definition: mythdvdinfo.cpp:109
mythcontext.h
MythDVDBuffer::FindSmallestBoundingRectangle
static int FindSmallestBoundingRectangle(AVSubtitle *Subtitle)
Obtained from ffmpeg dvdsubdec.c Used to find smallest bounded rect and helps prevent jerky picture d...
Definition: mythdvdbuffer.cpp:2075
MythOpticalBuffer
Definition: mythopticalbuffer.h:7
MythDVDBuffer::m_dvdWaiting
bool m_dvdWaiting
Definition: mythdvdbuffer.h:179
MythDVDBuffer::m_buttonSelected
bool m_buttonSelected
Definition: mythdvdbuffer.h:183
MythDVDBuffer::IsStillFramePending
bool IsStillFramePending(void) const
Definition: mythdvdbuffer.cpp:1167
ACTION_LEFT
#define ACTION_LEFT
Definition: mythuiactions.h:18
MythDVDBuffer::NumMenuButtons
int NumMenuButtons(void) const
Definition: mythdvdbuffer.cpp:1704
MythDVDBuffer::UnblockReading
void UnblockReading(void)
Definition: mythdvdbuffer.cpp:1222
DVD_BLOCK_SIZE
#define DVD_BLOCK_SIZE
Definition: mythdvdinfo.h:16
iso639_str2_to_str3
QString iso639_str2_to_str3(const QString &str2)
Definition: iso639.cpp:68
mpeg::chrono::pts
std::chrono::duration< CHRONO_TYPE, std::ratio< 1, 90000 > > pts
Definition: mythchrono.h:55
MythDVDBuffer::GetSubtitleTrackNum
int8_t GetSubtitleTrackNum(uint StreamId)
get the logical subtitle track/stream number from the dvd
Definition: mythdvdbuffer.cpp:1800
MythDVDBuffer::GetNumAudioChannels
uint16_t GetNumAudioChannels(int Index)
Definition: mythdvdbuffer.cpp:1881
MythDVDBuffer::MythDVDBuffer
MythDVDBuffer(const QString &Filename)
Definition: mythdvdbuffer.cpp:43
iso639.h
ISO 639-1 and ISO 639-2 support functions.
MythDVDBuffer::SectorSeek
bool SectorSeek(uint64_t Sector)
Definition: mythdvdbuffer.cpp:150
MythDVDBuffer::WaitSkip
void WaitSkip(void)
Definition: mythdvdbuffer.cpp:1209
MythDVDBuffer::GetTotalReadPosition
long long GetTotalReadPosition(void) const
Definition: mythdvdbuffer.cpp:451
mythuiactions.h
uint16_t
unsigned short uint16_t
Definition: iso6937tables.h:3
MythDVDBuffer::m_curAudioTrack
int m_curAudioTrack
Definition: mythdvdbuffer.h:192
MythMediaBuffer::m_posLock
QReadWriteLock m_posLock
Definition: mythmediabuffer.h:164
MythDVDBuffer::MoveButtonDown
void MoveButtonDown(void)
Definition: mythdvdbuffer.cpp:1367
MythDVDBuffer::NextTrack
bool NextTrack(void)
Definition: mythdvdbuffer.cpp:1112
MythDVDBuffer::GetChapterLength
std::chrono::seconds GetChapterLength(void) const
Definition: mythdvdbuffer.cpp:456
MythDVDBuffer::m_cellChanged
bool m_cellChanged
Definition: mythdvdbuffer.h:162
MythOpticalBuffer::m_processState
MythOpticalState m_processState
Definition: mythopticalbuffer.h:24
MythDVDBuffer::GetSubtitleLanguage
uint GetSubtitleLanguage(int Id)
Get the subtitle language from the dvd.
Definition: mythdvdbuffer.cpp:1790
MythDVDBuffer::m_buttonVersion
uint m_buttonVersion
Definition: mythdvdbuffer.h:211
ACTION_CHANNELUP
#define ACTION_CHANNELUP
Definition: tv_actions.h:16
ACTION_CHANNELDOWN
#define ACTION_CHANNELDOWN
Definition: tv_actions.h:17
MythMediaBuffer::m_rwLock
QReadWriteLock m_rwLock
Definition: mythmediabuffer.h:183
MythDVDBuffer::m_cellid
int m_cellid
Definition: mythdvdbuffer.h:187
MythDVDBuffer::m_buttonSeenInCell
bool m_buttonSeenInCell
Definition: mythdvdbuffer.h:185
iso639_str3_to_key
static int iso639_str3_to_key(const unsigned char *iso639_2)
Definition: iso639.h:59
MythDVDPlayer::SetStillFrameTimeout
void SetStillFrameTimeout(std::chrono::seconds Length)
Definition: mythdvdplayer.cpp:693
MythDVDBuffer::HandleAction
bool HandleAction(const QStringList &Actions, mpeg::chrono::pts Pts) override
Definition: mythdvdbuffer.cpp:1314
MythDVDBuffer::m_buttonExists
bool m_buttonExists
Definition: mythdvdbuffer.h:184
ReferenceCounter::IncrRef
virtual int IncrRef(void)
Increments reference count.
Definition: referencecounter.cpp:101
MythDVDBuffer::GoToPreviousProgram
void GoToPreviousProgram(void)
Definition: mythdvdbuffer.cpp:1305
MythOpticalBuffer::PROCESS_REPROCESS
@ PROCESS_REPROCESS
Definition: mythopticalbuffer.h:20
MythMediaBuffer::m_ateof
bool m_ateof
Definition: mythmediabuffer.h:201
MythOpticalBuffer::PROCESS_NORMAL
@ PROCESS_NORMAL
Definition: mythopticalbuffer.h:19
MythDVDBuffer::MoveButtonUp
void MoveButtonUp(void)
Definition: mythdvdbuffer.cpp:1358
mythmainwindow.h
MythDVDBuffer::m_clut
CLUTArray m_clut
Definition: mythdvdbuffer.h:213
MythDVDBuffer::GetMenuSPUPkt
void GetMenuSPUPkt(uint8_t *Buffer, int Size, int StreamID, uint32_t StartTime)
Get SPU pkt from dvd menu subtitle stream.
Definition: mythdvdbuffer.cpp:1388
PaletteArray
std::array< uint8_t, 4 > PaletteArray
Definition: mythdvdbuffer.h:35
MythDVDBuffer::GetReadPosition
long long GetReadPosition(void) const override
returns current position in the PGC.
Definition: mythdvdbuffer.cpp:411
MythDVDBuffer::SwitchAngle
bool SwitchAngle(int Angle)
Definition: mythdvdbuffer.cpp:2150
ACTION_SEEKFFWD
#define ACTION_SEEKFFWD
Definition: tv_actions.h:43
MythPlayer::GetFFRewSkip
int GetFFRewSkip(void) const
Definition: mythplayer.h:140
MythDVDBuffer::m_seekLock
QMutex m_seekLock
Definition: mythdvdbuffer.h:221
MythDVDBuffer::SafeRead
int SafeRead(void *Buffer, uint Size) override
Definition: mythdvdbuffer.cpp:518
MythDVDBuffer::DecodeRLE
static int DecodeRLE(uint8_t *Bitmap, int Linesize, int Width, int Height, const uint8_t *Buffer, int NibbleOffset, int BufferSize)
decodes the bitmap from the subtitle packet.
Definition: mythdvdbuffer.cpp:2004
MythMediaBuffer::m_ignoreReadPos
long long m_ignoreReadPos
Definition: mythmediabuffer.h:168
MythDVDBuffer::m_dvdStat
dvdnav_status_t m_dvdStat
Definition: mythdvdbuffer.h:208
MythMediaBuffer::m_readAheadRunning
bool m_readAheadRunning
Definition: mythmediabuffer.h:197
MythDVDBuffer::ClearChapterCache
void ClearChapterCache(void)
Definition: mythdvdbuffer.cpp:82
MythDVDBuffer::ConvertLangCode
static uint ConvertLangCode(uint16_t Code)
converts the subtitle/audio lang code to iso639.
Definition: mythdvdbuffer.cpp:1815
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:922
MythDVDBuffer::GetDVDStateSnapshot
bool GetDVDStateSnapshot(QString &State)
Get a snapshot of the current DVD VM state.
Definition: mythdvdbuffer.cpp:1909
MythDVDBuffer::GuessPalette
void GuessPalette(uint32_t *RGBAPalette, PaletteArray Palette, AlphaArray Alpha)
converts palette values from YUV to RGB
Definition: mythdvdbuffer.cpp:1985