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