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 "mythuihelper.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  for (uint64_t chapter : m_chapterMap.value(m_title))
374  Times.push_back(static_cast<long long>(chapter));
375 }
376 
378 {
379  if (!m_dvdnav)
380  return 0;
381 
382  uint64_t duration = 0;
383  uint64_t *times = nullptr;
384  uint32_t num = dvdnav_describe_title_chapters(m_dvdnav, Title, &times, &duration);
385 
386  if (num < 1)
387  {
388  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to retrieve chapter data");
389  return 0;
390  }
391 
392  QList<uint64_t> chapters;
393  // add the start
394  chapters.append(0);
395  // don't add the last 'chapter' - which is the title end
396  if (num > 1)
397  for (uint i = 0; i < num - 1; i++)
398  chapters.append((times[i] + 45000) / 90000);
399 
400  // Assigned via calloc, must be free'd not deleted
401  if (times)
402  free(times);
403  m_chapterMap.insert(Title, chapters);
404  return (duration + 45000) / 90000;
405 }
406 
409 long long MythDVDBuffer::GetReadPosition(void) const
410 {
411  uint32_t pos = 0;
412  uint32_t length = 1;
413  if (m_dvdnav)
414  {
415  if (dvdnav_get_position(m_dvdnav, &pos, &length) == DVDNAV_STATUS_ERR)
416  {
417  // try one more time
418  dvdnav_get_position(m_dvdnav, &pos, &length);
419  }
420  }
421  return pos * DVD_BLOCK_SIZE;
422 }
423 
424 int MythDVDBuffer::GetTitle(void) const
425 {
426  return m_title;
427 }
428 
430 {
431  return m_playerWait;
432 }
433 
434 int MythDVDBuffer::GetPart(void) const
435 {
436  return m_part;
437 }
438 
440 {
441  return m_currentAngle;
442 }
443 
445 {
447 }
448 
450 {
451  return m_titleLength;
452 }
453 
455 {
456  return static_cast<uint>(m_pgLength / 90000);
457 }
458 
459 void MythDVDBuffer::GetPartAndTitle(int &Part, int &Title) const
460 {
461  Part = m_part;
462  Title = m_title;
463 }
464 
465 uint32_t MythDVDBuffer::AdjustTimestamp(uint32_t Timestamp) const
466 {
467  uint32_t newTimestamp = Timestamp;
468  if (newTimestamp >= m_timeDiff)
469  newTimestamp -= m_timeDiff;
470  return newTimestamp;
471 }
472 
473 int64_t MythDVDBuffer::AdjustTimestamp(int64_t Timestamp) const
474 {
475  int64_t newTimestamp = Timestamp;
476  if ((newTimestamp != AV_NOPTS_VALUE) && (newTimestamp >= m_timeDiff))
477  newTimestamp -= m_timeDiff;
478  return newTimestamp;
479 }
480 
482 {
483  QMutexLocker contextLocker(&m_contextLock);
484  if (m_context)
485  m_context->IncrRef();
486  return m_context;
487 }
488 
490 {
491  return m_dvdEvent;
492 }
493 
495 {
496  if (!m_skipstillorwait)
497  {
498  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Waiting for player's buffers to drain");
499  m_playerWait = true;
500  int count = 0;
501  while (m_playerWait && count++ < 200)
502  {
503  m_rwLock.unlock();
504  usleep(10000);
505  m_rwLock.lockForWrite();
506  }
507 
508  if (m_playerWait)
509  {
510  LOG(VB_GENERAL, LOG_ERR, LOC + "Player wait state was not cleared");
511  m_playerWait = false;
512  }
513  }
514 }
515 
517 {
518  uint8_t* blockBuf = nullptr;
519  uint tot = 0;
520  int needed = static_cast<int>(Size);
521  char *dest = static_cast<char*>(Buffer);
522  int offset = 0;
523  bool reprocessing = false;
524  bool waiting = false;
525 
526  if (m_gotStop)
527  {
528  LOG(VB_GENERAL, LOG_ERR, LOC + "safe_read: called after DVDNAV_STOP");
529  errno = EBADF;
530  return -1;
531  }
532 
533  if (m_readAheadRunning)
534  LOG(VB_GENERAL, LOG_ERR, LOC + "read ahead thread running.");
535 
536  while ((m_processState != PROCESS_WAIT) && needed)
537  {
538  blockBuf = m_dvdBlockWriteBuf.data();
539 
541  {
543  reprocessing = true;
544  }
545  else
546  {
547  m_dvdStat = dvdnav_get_next_cache_block(m_dvdnav, &blockBuf, &m_dvdEvent, &m_dvdEventSize);
548  reprocessing = false;
549  }
550 
551  if (m_dvdStat == DVDNAV_STATUS_ERR)
552  {
553  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to read block: %1")
554  .arg(dvdnav_err_to_string(m_dvdnav)));
555  errno = EIO;
556  return -1;
557  }
558 
559  switch (m_dvdEvent)
560  {
561  // Standard packet for decoding
562  case DVDNAV_BLOCK_OK:
563  {
564  // copy block
565  if (!m_seeking)
566  {
567  memcpy(dest + offset, blockBuf, DVD_BLOCK_SIZE);
568  tot += DVD_BLOCK_SIZE;
569  }
570 
571  // release buffer
572  if (blockBuf != m_dvdBlockWriteBuf.data())
573  dvdnav_free_cache_block(m_dvdnav, blockBuf);
574 
575  // debug
576  LOG(VB_PLAYBACK|VB_FILE, LOG_DEBUG, LOC + "DVDNAV_BLOCK_OK");
577  }
578  break;
579 
580  // cell change
581  case DVDNAV_CELL_CHANGE:
582  {
583  // get event details
584  auto *cell_event = reinterpret_cast<dvdnav_cell_change_event_t*>(blockBuf);
585 
586  // update information for the current cell
587  m_cellChanged = true;
588  if (m_pgcLength != cell_event->pgc_length)
589  m_pgcLengthChanged = true;
590  m_pgLength = cell_event->pg_length;
591  m_pgcLength = cell_event->pgc_length;
592  m_cellStart = cell_event->cell_start;
593  m_pgStart = cell_event->pg_start;
594 
595  // update title/part/still/menu information
597  m_lastPart = m_part;
599  uint32_t pos = 0;
600  uint32_t length = 0;
601  uint32_t stillTimer = dvdnav_get_next_still_flag(m_dvdnav);
602  m_still = 0;
603  m_titleParts = 0;
604  dvdnav_current_title_info(m_dvdnav, &m_title, &m_part);
605  dvdnav_get_number_of_parts(m_dvdnav, m_title, &m_titleParts);
606  dvdnav_get_position(m_dvdnav, &pos, &length);
607  dvdnav_get_angle_info(m_dvdnav, &m_currentAngle, &m_currentTitleAngleCount);
608 
609  if (m_title != m_lastTitle)
610  {
611  // Populate the chapter list for this title, used in the OSD menu
613  }
614 
615  m_titleLength = length * DVD_BLOCK_SIZE;
616  if (!m_seeking)
618 
619  // debug
620  LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
621  QString("---- DVDNAV_CELL_CHANGE - Cell #%1 Menu %2 Length %3")
622  .arg(cell_event->cellN).arg(m_inMenu ? "Yes" : "No")
623  .arg(static_cast<double>(cell_event->cell_length) / 90000.0, 0, 'f', 1));
624  QString still = stillTimer ? ((stillTimer < 0xff) ?
625  QString("Stillframe: %1 seconds").arg(stillTimer) :
626  QString("Infinite stillframe")) :
627  QString("Length: %1 seconds")
628  .arg(static_cast<double>(m_pgcLength) / 90000.0, 0, 'f', 1);
629  if (m_title == 0)
630  {
631  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Menu #%1 %2")
632  .arg(m_part).arg(still));
633  }
634  else
635  {
636  LOG(VB_PLAYBACK, LOG_INFO,
637  LOC + QString("Title #%1: %2 Part %3 of %4")
638  .arg(m_title).arg(still).arg(m_part).arg(m_titleParts));
639  }
640 
641  // wait unless it is a transition from one normal video cell to
642  // another or the same menu id
643  if ((m_title != m_lastTitle) &&
644  !((m_title == 0 && m_lastTitle == 0) && (m_part == m_lastPart)))
645  {
646  WaitForPlayer();
647  }
648 
649  // Make sure the still frame timer is reset.
650  if (m_parent)
652 
653  // clear menus/still frame selections
657  m_buttonSelected = false;
658  m_vobid = m_cellid = 0;
659  m_cellRepeated = false;
660  m_buttonSeenInCell = false;
661 
663 
664  // release buffer
665  if (blockBuf != m_dvdBlockWriteBuf.data())
666  dvdnav_free_cache_block(m_dvdnav, blockBuf);
667  }
668  break;
669 
670  // new colour lookup table for subtitles/menu buttons
671  case DVDNAV_SPU_CLUT_CHANGE:
672  {
673  // debug
674  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "DVDNAV_SPU_CLUT_CHANGE");
675 
676  // store the new clut
677  // m_clut = std::to_array(blockBuf); // C++20
678  std::copy(blockBuf, blockBuf + 16 * sizeof(uint32_t),
679  reinterpret_cast<uint8_t*>(m_clut.data()));
680  // release buffer
681  if (blockBuf != m_dvdBlockWriteBuf.data())
682  dvdnav_free_cache_block(m_dvdnav, blockBuf);
683  }
684  break;
685 
686  // new Sub-picture Unit stream (subtitles/menu buttons)
687  case DVDNAV_SPU_STREAM_CHANGE:
688  {
689  // get event details
690  auto* spu = reinterpret_cast<dvdnav_spu_stream_change_event_t*>(blockBuf);
691 
692  // clear any existing subs/buttons
694 
695  // not sure
697  m_curSubtitleTrack = dvdnav_get_active_spu_stream(m_dvdnav);
698 
699  // debug
700  LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
701  QString("DVDNAV_SPU_STREAM_CHANGE: "
702  "physicalwide %1, physicalletterbox %2, "
703  "physicalpanscan %3, currenttrack %4")
704  .arg(spu->physical_wide).arg(spu->physical_letterbox)
705  .arg(spu->physical_pan_scan).arg(m_curSubtitleTrack));
706 
707  // release buffer
708  if (blockBuf != m_dvdBlockWriteBuf.data())
709  dvdnav_free_cache_block(m_dvdnav, blockBuf);
710  }
711  break;
712 
713  // the audio stream changed
714  case DVDNAV_AUDIO_STREAM_CHANGE:
715  {
716  // get event details
717  auto* audio = reinterpret_cast<dvdnav_audio_stream_change_event_t*>(blockBuf);
718 
719  // retrieve the new track
720  int new_track = GetAudioTrackNum(static_cast<uint>(audio->physical));
721 
722  // debug
723  LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
724  QString("DVDNAV_AUDIO_STREAM_CHANGE: old %1 new %2, physical %3, logical %4")
725  .arg(m_curAudioTrack).arg(new_track)
726  .arg(audio->physical).arg(audio->logical));
727 
728  // tell the decoder to reset the audio streams if necessary
729  if (new_track != m_curAudioTrack)
730  {
731  m_curAudioTrack = new_track;
732  m_audioStreamsChanged = true;
733  }
734 
735  // release buffer
736  if (blockBuf != m_dvdBlockWriteBuf.data())
737  dvdnav_free_cache_block(m_dvdnav, blockBuf);
738  }
739  break;
740 
741  // navigation packet
742  case DVDNAV_NAV_PACKET:
743  {
744  QMutexLocker lock(&m_seekLock);
745  bool lastInMenu = m_inMenu;
746 
747  // retrieve the latest Presentation Control and
748  // Data Search Information structures
749  pci_t *pci = dvdnav_get_current_nav_pci(m_dvdnav);
750  dsi_t *dsi = dvdnav_get_current_nav_dsi(m_dvdnav);
751 
752  if (pci == nullptr || dsi == nullptr)
753  {
754  // Something has gone horribly wrong if this happens
755  LOG(VB_GENERAL, LOG_ERR, LOC + QString("DVDNAV_NAV_PACKET - Error retrieving DVD data structures - dsi 0x%1, pci 0x%2")
756  .arg(reinterpret_cast<uint64_t>(dsi), 0, 16)
757  .arg(reinterpret_cast<uint64_t>(pci), 0, 16));
758  }
759  else
760  {
761  // If the start PTS of this block is not the
762  // same as the end PTS of the last block,
763  // we've got a timestamp discontinuity
764  int64_t diff = static_cast<int64_t>(pci->pci_gi.vobu_s_ptm) - m_endPts;
765  if (diff != 0)
766  {
767  if (!reprocessing && !m_skipstillorwait)
768  {
769  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("PTS discontinuity - waiting for decoder: this %1, last %2, diff %3")
770  .arg(pci->pci_gi.vobu_s_ptm).arg(m_endPts).arg(diff));
772  break;
773  }
774 
775  m_timeDiff += diff;
776  }
777 
778  m_endPts = pci->pci_gi.vobu_e_ptm;
779  m_inMenu = (pci->hli.hl_gi.btn_ns > 0);
780 
781  if (m_inMenu && m_seeking && (dsi->synci.sp_synca[0] & 0x80000000) &&
783  {
784  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("Jumped into middle of menu: lba %1, dest %2")
785  .arg(pci->pci_gi.nv_pck_lbn)
786  .arg(pci->pci_gi.nv_pck_lbn - (dsi->synci.sp_synca[0] & 0x7fffffff)));
787 
788  // We're in a menu, the subpicture packets are somewhere behind us
789  // and we've not decoded any subpicture.
790  // That probably means we've jumped into the middle of a menu.
791  // We'd better jump back to get the subpicture packet(s) otherwise
792  // there's no menu highlight to show.
793  m_seeking = false;
794  dvdnav_sector_search(m_dvdnav, pci->pci_gi.nv_pck_lbn - (dsi->synci.sp_synca[0] & 0x7fffffff), SEEK_SET);
795  }
796  else
797  {
798  pci_t pci_copy = *pci;
799 
800  pci_copy.pci_gi.vobu_s_ptm = AdjustTimestamp(pci->pci_gi.vobu_s_ptm);
801  pci_copy.pci_gi.vobu_e_ptm = AdjustTimestamp(pci->pci_gi.vobu_e_ptm);
802 
803  if (pci->pci_gi.vobu_se_e_ptm != 0)
804  pci_copy.pci_gi.vobu_se_e_ptm = AdjustTimestamp(pci->pci_gi.vobu_se_e_ptm);
805 
806  QMutexLocker contextLocker(&m_contextLock);
807  if (m_context)
808  m_context->DecrRef();
809 
810  m_context = new MythDVDContext(*dsi, pci_copy);
811 
812  if (m_inMenu != lastInMenu)
813  {
814  if (m_inMenu)
815  {
816  m_autoselectsubtitle = true;
818  }
819  else
820  {
822  }
823  }
824 
825  // if we are in a looping menu, we don't want to reset the
826  // selected button when we restart
827  m_vobid = dsi->dsi_gi.vobu_vob_idn;
828  m_cellid = dsi->dsi_gi.vobu_c_idn;
829  if ((m_lastvobid == m_vobid) && (m_lastcellid == m_cellid)
831  {
832  m_cellRepeated = true;
833  }
834 
835  // update our status
836  m_currentTime = dvdnav_get_current_time(m_dvdnav);
838 
839  if (m_seeking)
840  {
841  int relativetime = static_cast<int>((m_seektime - m_currentTime) / 90000);
842  if (abs(relativetime) <= 1)
843  {
844  m_seeking = false;
845  m_seektime = 0;
846  }
847  else
848  {
849  dvdnav_relative_time_search(m_dvdnav, relativetime * 2);
850  }
851  }
852 
853  // update the button stream number if this is the
854  // first NAV pack containing button information
855  if ( (pci->hli.hl_gi.hli_ss & 0x03) == 0x01 )
856  {
857  m_buttonStreamID = 32;
858  int aspect = dvdnav_get_video_aspect(m_dvdnav);
859 
860  // workaround where dvd menu is
861  // present in VTS_DOMAIN. dvdnav adds 0x80 to stream id
862  // proper fix should be put in dvdnav sometime
863  int8_t spustream = dvdnav_get_active_spu_stream(m_dvdnav) & 0x7f;
864 
865  if (aspect != 0 && spustream > 0)
866  m_buttonStreamID += spustream;
867 
868  m_buttonSeenInCell = true;
869  }
870 
871  // debug
872  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("DVDNAV_NAV_PACKET - time:%1, lba:%2, vob:%3, cell:%4, seeking:%5, seektime:%6")
874  .arg(m_context->GetLBA())
875  .arg(m_vobid)
876  .arg(m_cellid)
877  .arg(m_seeking)
878  .arg(m_seektime));
879 
880  if (!m_seeking)
881  {
882  memcpy(dest + offset, blockBuf, DVD_BLOCK_SIZE);
883  tot += DVD_BLOCK_SIZE;
884  }
885  }
886  }
887  // release buffer
888  if (blockBuf != m_dvdBlockWriteBuf.data())
889  dvdnav_free_cache_block(m_dvdnav, blockBuf);
890  }
891  break;
892 
893  case DVDNAV_HOP_CHANNEL:
894  {
895  if (!reprocessing && !m_skipstillorwait)
896  {
897  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "DVDNAV_HOP_CHANNEL - waiting");
899  break;
900  }
901 
902  // debug
903  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "DVDNAV_HOP_CHANNEL");
904  WaitForPlayer();
905  }
906  break;
907 
908  // no op
909  case DVDNAV_NOP:
910  break;
911 
912  // new Video Title Set - aspect ratio/letterboxing
913  case DVDNAV_VTS_CHANGE:
914  {
915  // retrieve event details
916  auto* vts = reinterpret_cast<dvdnav_vts_change_event_t*>(blockBuf);
917 
918  // update player
919  int aspect = dvdnav_get_video_aspect(m_dvdnav);
920  if (aspect == 2) // 4:3
921  m_forcedAspect = 4.0F / 3.0F;
922  else if (aspect == 3) // 16:9
923  m_forcedAspect = 16.0F / 9.0F;
924  else
925  m_forcedAspect = -1;
926  int permission = dvdnav_get_video_scale_permission(m_dvdnav);
927 
928  // debug
929  LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
930  QString("DVDNAV_VTS_CHANGE: old_vtsN %1, new_vtsN %2, "
931  "aspect %3, perm %4")
932  .arg(vts->old_vtsN).arg(vts->new_vtsN)
933  .arg(aspect).arg(permission));
934 
935  // trigger a rescan of the audio streams
936  if ((vts->old_vtsN != vts->new_vtsN) ||(vts->old_domain != vts->new_domain))
937  m_audioStreamsChanged = true;
938 
939  // Make sure we know we're not staying in the
940  // same cell (same vobid/cellid values can
941  // occur in every VTS)
942  m_lastvobid = m_vobid = 0;
943  m_lastcellid = m_cellid = 0;
944 
945  // release buffer
946  if (blockBuf != m_dvdBlockWriteBuf.data())
947  dvdnav_free_cache_block(m_dvdnav, blockBuf);
948  }
949  break;
950 
951  // menu button
952  case DVDNAV_HIGHLIGHT:
953  {
954  // retrieve details
955  auto* highlight = reinterpret_cast<dvdnav_highlight_event_t*>(blockBuf);
956 
957  // update the current button
958  m_menuBtnLock.lock();
959  DVDButtonUpdate(false);
961  m_menuBtnLock.unlock();
962 
963  // debug
964  LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
965  QString("DVDNAV_HIGHLIGHT: display %1, palette %2, "
966  "sx %3, sy %4, ex %5, ey %6, pts %7, buttonN %8")
967  .arg(highlight->display).arg(highlight->palette)
968  .arg(highlight->sx).arg(highlight->sy)
969  .arg(highlight->ex).arg(highlight->ey)
970  .arg(highlight->pts).arg(highlight->buttonN));
971 
972  // release buffer
973  if (blockBuf != m_dvdBlockWriteBuf.data())
974  dvdnav_free_cache_block(m_dvdnav, blockBuf);
975  }
976  break;
977 
978  // dvd still frame
979  case DVDNAV_STILL_FRAME:
980  {
981  // retrieve still frame details (length)
982  auto* still = reinterpret_cast<dvdnav_still_event_t*>(blockBuf);
983 
984  if (!reprocessing && !m_skipstillorwait)
985  {
986  if (m_still != still->length)
987  {
988  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("DVDNAV_STILL_FRAME (%1) - waiting")
989  .arg(still->length));
990  }
991 
993  }
994  else
995  {
996  // pause a little as the dvdnav VM will continue to return
997  // this event until it has been skipped
998  m_rwLock.unlock();
999  usleep(10000);
1000  m_rwLock.lockForWrite();
1001 
1002  // when scanning the file or exiting playback, skip immediately
1003  // otherwise update the timeout in the player
1004  if (m_skipstillorwait)
1005  {
1006  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("Skipping DVDNAV_STILL_FRAME (%1)")
1007  .arg(still->length));
1008  SkipStillFrame();
1009  }
1010  else if (m_parent)
1011  {
1012  // debug
1013  if (m_still != still->length)
1014  {
1015  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("DVDNAV_STILL_FRAME (%1)")
1016  .arg(still->length));
1017  }
1018 
1019  m_still = still->length;
1020  Size = tot;
1022  }
1023 
1024  // release buffer
1025  if (blockBuf != m_dvdBlockWriteBuf.data())
1026  dvdnav_free_cache_block(m_dvdnav, blockBuf);
1027  }
1028  }
1029  break;
1030 
1031  // wait for the player
1032  case DVDNAV_WAIT:
1033  {
1034  if (!reprocessing && !m_skipstillorwait && !waiting)
1035  {
1036  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "DVDNAV_WAIT - waiting");
1038  }
1039  else
1040  {
1041  waiting = true;
1042 
1043  //debug
1044  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "DVDNAV_WAIT");
1045 
1046  // skip if required, otherwise wait (and loop)
1047  if (m_skipstillorwait)
1048  {
1049  WaitSkip();
1050  }
1051  else
1052  {
1053  m_dvdWaiting = true;
1054  m_rwLock.unlock();
1055  usleep(10000);
1056  m_rwLock.lockForWrite();
1057  }
1058 
1059  // release buffer
1060  if (blockBuf != m_dvdBlockWriteBuf.data())
1061  dvdnav_free_cache_block(m_dvdnav, blockBuf);
1062  }
1063  }
1064  break;
1065 
1066  // exit playback
1067  case DVDNAV_STOP:
1068  {
1069  LOG(VB_GENERAL, LOG_INFO, LOC + "DVDNAV_STOP");
1070  Size = tot;
1071  m_gotStop = true;
1072 
1073  // release buffer
1074  if (blockBuf != m_dvdBlockWriteBuf.data())
1075  dvdnav_free_cache_block(m_dvdnav, blockBuf);
1076  }
1077  break;
1078 
1079  // this shouldn't happen
1080  default:
1081  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Unknown DVD event: %1").arg(m_dvdEvent));
1082  break;
1083  }
1084 
1085  needed = static_cast<int>(Size - tot);
1086  offset = static_cast<int>(tot);
1087  }
1088 
1090  {
1091  errno = EAGAIN;
1092  return 0;
1093  }
1094  return static_cast<int>(tot);
1095 }
1096 
1098 {
1099  QMutexLocker lock(&m_seekLock);
1100  if (Track < 1)
1101  Seek(0);
1102  else if (Track < m_titleParts)
1103  dvdnav_part_play(m_dvdnav, m_title, Track);
1104  else
1105  return false;
1106  m_gotStop = false;
1107  return true;
1108 }
1109 
1111 {
1112  int newPart = m_part + 1;
1113 
1114  QMutexLocker lock(&m_seekLock);
1115  if (newPart < m_titleParts)
1116  {
1117  dvdnav_part_play(m_dvdnav, m_title, newPart);
1118  m_gotStop = false;
1119  return true;
1120  }
1121  return false;
1122 }
1123 
1125 {
1126  int newPart = m_part - 1;
1127 
1128  QMutexLocker lock(&m_seekLock);
1129  if (newPart > 0)
1130  dvdnav_part_play(m_dvdnav, m_title, newPart);
1131  else
1132  Seek(0);
1133  m_gotStop = false;
1134 }
1135 
1140 {
1141  return static_cast<uint>(lround(m_pgcLength / 90000.0F));
1142 }
1143 
1145 {
1146  return m_forcedAspect;
1147 }
1148 
1152 {
1153  return static_cast<uint>(m_cellStart / 900000.F);
1154 }
1155 
1159 {
1160  bool ret = m_cellChanged;
1161  m_cellChanged = false;
1162  return ret;
1163 }
1164 
1166 {
1167  return dvdnav_get_next_still_flag(m_dvdnav) > 0;
1168 }
1169 
1171 {
1172  return m_audioStreamsChanged;
1173 }
1174 
1176 {
1177  return m_dvdWaiting;
1178 }
1179 
1181 {
1182  return m_titleParts;
1183 }
1184 
1188 {
1189  bool ret = m_pgcLengthChanged;
1190  m_pgcLengthChanged = false;
1191  return ret;
1192 }
1193 
1195 {
1196  QMutexLocker locker(&m_seekLock);
1197  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Skipping still frame.");
1198 
1199  m_still = 0;
1200  dvdnav_still_skip(m_dvdnav);
1201 
1202  // Make sure the still frame timer is disabled.
1203  if (m_parent)
1205 }
1206 
1208 {
1209  QMutexLocker locker(&m_seekLock);
1210  dvdnav_wait_skip(m_dvdnav);
1211  m_dvdWaiting = false;
1212  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Exiting DVDNAV_WAIT status");
1213 }
1214 
1216 {
1217  m_playerWait = false;
1218 }
1219 
1221 {
1223 }
1224 
1226 {
1227  return m_processState == PROCESS_WAIT;
1228 }
1229 
1232 bool MythDVDBuffer::GoToMenu(const QString &str)
1233 {
1234  DVDMenuID_t menuid = DVD_MENU_Escape;
1235  QMutexLocker locker(&m_seekLock);
1236 
1237  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("DVDRingBuf: GoToMenu %1").arg(str));
1238 
1239  if (str.compare("chapter") == 0)
1240  menuid = DVD_MENU_Part;
1241  else if (str.compare("root") == 0)
1242  menuid = DVD_MENU_Root;
1243  else if (str.compare("title") == 0)
1244  menuid = DVD_MENU_Title;
1245  else
1246  return false;
1247 
1248  dvdnav_status_t ret = dvdnav_menu_call(m_dvdnav, menuid);
1249  return ret == DVDNAV_STATUS_OK;
1250 }
1251 
1257 {
1258  bool success = false;
1259  QString target;
1260 
1261  QMutexLocker locker(&m_seekLock);
1262 
1263  if (dvdnav_is_domain_vts(m_dvdnav) && !m_inMenu)
1264  {
1265  if (dvdnav_go_up(m_dvdnav) == DVDNAV_STATUS_OK)
1266  {
1267  target = "GoUp";
1268  success = true;
1269  }
1270  else if (dvdnav_menu_call(m_dvdnav, DVD_MENU_Root) == DVDNAV_STATUS_OK)
1271  {
1272  target = "Root";
1273  success = true;
1274  }
1275  else if (dvdnav_menu_call(m_dvdnav, DVD_MENU_Title) == DVDNAV_STATUS_OK)
1276  {
1277  target = "Title";
1278  success = true;
1279  }
1280  else
1281  {
1282  target = "Nothing available";
1283  }
1284  }
1285  else
1286  {
1287  target = QString("No jump, %1 menu").arg(m_inMenu ? "in" : "not in");
1288  }
1289 
1290  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("DVDRingBuf: GoBack - %1").arg(target));
1291  return success;
1292 }
1293 
1295 {
1296  QMutexLocker locker(&m_seekLock);
1297  // This conditional appears to be unnecessary, and might have come
1298  // from a mistake in a libdvdnav resync.
1299  //if (!dvdnav_is_domain_vts(m_dvdnav))
1300  dvdnav_next_pg_search(m_dvdnav);
1301 }
1302 
1304 {
1305  QMutexLocker locker(&m_seekLock);
1306  // This conditional appears to be unnecessary, and might have come
1307  // from a mistake in a libdvdnav resync.
1308  //if (!dvdnav_is_domain_vts(m_dvdnav))
1309  dvdnav_prev_pg_search(m_dvdnav);
1310 }
1311 
1312 bool MythDVDBuffer::HandleAction(const QStringList &Actions, int64_t /*Pts*/)
1313 {
1314  if (!NumMenuButtons())
1315  return false;
1316 
1317  if (Actions.contains(ACTION_UP) || Actions.contains(ACTION_CHANNELUP))
1318  MoveButtonUp();
1319  else if (Actions.contains(ACTION_DOWN) || Actions.contains(ACTION_CHANNELDOWN))
1320  MoveButtonDown();
1321  else if (Actions.contains(ACTION_LEFT) || Actions.contains(ACTION_SEEKRWND))
1322  MoveButtonLeft();
1323  else if (Actions.contains(ACTION_RIGHT) || Actions.contains(ACTION_SEEKFFWD))
1324  MoveButtonRight();
1325  else if (Actions.contains(ACTION_SELECT))
1326  ActivateButton();
1327  else
1328  return false;
1329 
1330  return true;
1331 }
1332 
1334 {
1335  m_skipstillorwait = Ignore;
1336 }
1337 
1339 {
1340  if (NumMenuButtons() > 1)
1341  {
1342  pci_t *pci = dvdnav_get_current_nav_pci(m_dvdnav);
1343  dvdnav_left_button_select(m_dvdnav, pci);
1344  }
1345 }
1346 
1348 {
1349  if (NumMenuButtons() > 1)
1350  {
1351  pci_t *pci = dvdnav_get_current_nav_pci(m_dvdnav);
1352  dvdnav_right_button_select(m_dvdnav, pci);
1353  }
1354 }
1355 
1357 {
1358  if (NumMenuButtons() > 1)
1359  {
1360  pci_t *pci = dvdnav_get_current_nav_pci(m_dvdnav);
1361  dvdnav_upper_button_select(m_dvdnav, pci);
1362  }
1363 }
1364 
1366 {
1367  if (NumMenuButtons() > 1)
1368  {
1369  pci_t *pci = dvdnav_get_current_nav_pci(m_dvdnav);
1370  dvdnav_lower_button_select(m_dvdnav, pci);
1371  }
1372 }
1373 
1376 {
1377  if (NumMenuButtons() > 0)
1378  {
1380  pci_t *pci = dvdnav_get_current_nav_pci(m_dvdnav);
1381  dvdnav_button_activate(m_dvdnav, pci);
1382  }
1383 }
1384 
1386 void MythDVDBuffer::GetMenuSPUPkt(uint8_t *Buffer, int Size, int StreamID, uint32_t StartTime)
1387 {
1388  if (Size < 4)
1389  return;
1390 
1391  if (m_buttonStreamID != StreamID)
1392  return;
1393 
1394  QMutexLocker lock(&m_menuBtnLock);
1395 
1397  auto *spu_pkt = reinterpret_cast<uint8_t*>(av_malloc(static_cast<size_t>(Size)));
1398  memcpy(spu_pkt, Buffer, static_cast<size_t>(Size));
1399  m_menuSpuPkt = spu_pkt;
1400  m_menuBuflength = Size;
1401  if (!m_buttonSelected)
1402  {
1404  m_buttonSelected = true;
1405  }
1406 
1407  if (DVDButtonUpdate(false))
1408  {
1409  int32_t gotbutton = 0;
1411  m_menuSpuPkt, m_menuBuflength, StartTime);
1412  }
1413 }
1414 
1417 {
1418  // this is unlocked by ReleaseMenuButton
1419  m_menuBtnLock.lock();
1420 
1421  if ((m_menuBuflength > 4) && m_buttonExists && (NumMenuButtons() > 0))
1422  {
1423  Version = m_buttonVersion;
1424  return &(m_dvdMenuButton);
1425  }
1426 
1427  return nullptr;
1428 }
1429 
1430 
1432 {
1433  m_menuBtnLock.unlock();
1434 }
1435 
1439 {
1440  QRect rect(0,0,0,0);
1441  if (!m_buttonExists)
1442  return rect;
1443  rect.setRect(m_hlButton.x(), m_hlButton.y(), m_hlButton.width(), m_hlButton.height());
1444  return rect;
1445 }
1446 
1450 bool MythDVDBuffer::DecodeSubtitles(AVSubtitle *Subtitle, int *GotSubtitles,
1451  const uint8_t *SpuPkt, int BufSize, uint32_t StartTime)
1452 {
1453  #define GETBE16(p) (((p)[0] << 8) | (p)[1])
1454 
1455  AlphaArray alpha {0, 0, 0, 0};
1456  PaletteArray palette {0, 0, 0, 0};
1457 
1458  if (!SpuPkt)
1459  return false;
1460 
1461  if (BufSize < 4)
1462  return false;
1463 
1464  bool force_subtitle_display = false;
1465  Subtitle->rects = nullptr;
1466  Subtitle->num_rects = 0;
1467  Subtitle->start_display_time = StartTime;
1468  Subtitle->end_display_time = StartTime;
1469 
1470  int cmd_pos = GETBE16(SpuPkt + 2);
1471  while ((cmd_pos + 4) < BufSize)
1472  {
1473  int offset1 = -1;
1474  int offset2 = -1;
1475  int date = GETBE16(SpuPkt + cmd_pos);
1476  int next_cmd_pos = GETBE16(SpuPkt + cmd_pos + 2);
1477  int pos = cmd_pos + 4;
1478  int x1 = 0;
1479  int x2 = 0;
1480  int y1 = 0;
1481  int y2 = 0;
1482  while (pos < BufSize)
1483  {
1484  int cmd = SpuPkt[pos++];
1485  switch(cmd)
1486  {
1487  case 0x00:
1488  force_subtitle_display = true;
1489  break;
1490  case 0x01:
1491  Subtitle->start_display_time = ((static_cast<uint>(date) << 10) / 90) + StartTime;
1492  break;
1493  case 0x02:
1494  Subtitle->end_display_time = ((static_cast<uint>(date) << 10) / 90) + StartTime;
1495  break;
1496  case 0x03:
1497  {
1498  if ((BufSize - pos) < 2)
1499  goto fail;
1500 
1501  palette[3] = SpuPkt[pos] >> 4;
1502  palette[2] = SpuPkt[pos] & 0x0f;
1503  palette[1] = SpuPkt[pos + 1] >> 4;
1504  palette[0] = SpuPkt[pos + 1] & 0x0f;
1505  pos +=2;
1506  }
1507  break;
1508  case 0x04:
1509  {
1510  if ((BufSize - pos) < 2)
1511  goto fail;
1512  alpha[3] = SpuPkt[pos] >> 4;
1513  alpha[2] = SpuPkt[pos] & 0x0f;
1514  alpha[1] = SpuPkt[pos + 1] >> 4;
1515  alpha[0] = SpuPkt[pos + 1] & 0x0f;
1516  pos +=2;
1517  }
1518  break;
1519  case 0x05:
1520  {
1521  if ((BufSize - pos) < 6)
1522  goto fail;
1523  x1 = (SpuPkt[pos] << 4) | (SpuPkt[pos + 1] >> 4);
1524  x2 = ((SpuPkt[pos + 1] & 0x0f) << 8) | SpuPkt[pos + 2];
1525  y1 = (SpuPkt[pos + 3] << 4) | (SpuPkt[pos + 4] >> 4);
1526  y2 = ((SpuPkt[pos + 4] & 0x0f) << 8) | SpuPkt[pos + 5];
1527  pos +=6;
1528  }
1529  break;
1530  case 0x06:
1531  {
1532  if ((BufSize - pos) < 4)
1533  goto fail;
1534  offset1 = GETBE16(SpuPkt + pos);
1535  offset2 = GETBE16(SpuPkt + pos + 2);
1536  pos +=4;
1537  }
1538  break;
1539  case 0x07:
1540  {
1541  if ((BufSize - pos) < 2)
1542  goto fail;
1543 
1544  pos += GETBE16(SpuPkt + pos);
1545  }
1546  break;
1547  case 0xff:
1548  default:
1549  goto the_end;
1550  }
1551  }
1552  the_end:
1553  if (offset1 >= 0)
1554  {
1555  int width = x2 - x1 + 1;
1556  if (width < 0)
1557  width = 0;
1558  int height = y2 - y1 + 1;
1559  if (height < 0)
1560  height = 0;
1561  if (width > 0 && height > 0)
1562  {
1563  if (Subtitle->rects != nullptr)
1564  {
1565  for (uint i = 0; i < Subtitle->num_rects; i++)
1566  {
1567  av_free(Subtitle->rects[i]->data[0]);
1568  av_free(Subtitle->rects[i]->data[1]);
1569  av_freep(&Subtitle->rects[i]);
1570  }
1571  av_freep(&Subtitle->rects);
1572  Subtitle->num_rects = 0;
1573  }
1574 
1575  auto *bitmap = static_cast<uint8_t*>(av_malloc(static_cast<size_t>(width * height)));
1576  Subtitle->num_rects = (NumMenuButtons() > 0) ? 2 : 1;
1577  Subtitle->rects = static_cast<AVSubtitleRect**>(av_mallocz(sizeof(AVSubtitleRect*) * Subtitle->num_rects));
1578  for (uint i = 0; i < Subtitle->num_rects; i++)
1579  Subtitle->rects[i] = static_cast<AVSubtitleRect*>(av_mallocz(sizeof(AVSubtitleRect)));
1580  Subtitle->rects[0]->data[1] = static_cast<uint8_t*>(av_mallocz(4 * 4));
1581  DecodeRLE(bitmap, width * 2, width, (height + 1) / 2,
1582  SpuPkt, offset1 * 2, BufSize);
1583  DecodeRLE(bitmap + width, width * 2, width, height / 2,
1584  SpuPkt, offset2 * 2, BufSize);
1585  GuessPalette(reinterpret_cast<uint32_t*>(Subtitle->rects[0]->data[1]), palette, alpha);
1586  Subtitle->rects[0]->data[0] = bitmap;
1587  Subtitle->rects[0]->x = x1;
1588  Subtitle->rects[0]->y = y1;
1589  Subtitle->rects[0]->w = width;
1590  Subtitle->rects[0]->h = height;
1591  Subtitle->rects[0]->type = SUBTITLE_BITMAP;
1592  Subtitle->rects[0]->nb_colors = 4;
1593  Subtitle->rects[0]->linesize[0] = width;
1594  if (NumMenuButtons() > 0)
1595  {
1596  Subtitle->rects[1]->type = SUBTITLE_BITMAP;
1597  Subtitle->rects[1]->data[1] = static_cast<uint8_t*>(av_malloc(4 *4));
1598  GuessPalette(reinterpret_cast<uint32_t*>(Subtitle->rects[1]->data[1]),
1600  }
1601  else
1603  *GotSubtitles = 1;
1604  }
1605  }
1606  if (next_cmd_pos == cmd_pos)
1607  break;
1608  cmd_pos = next_cmd_pos;
1609  }
1610  if (Subtitle->num_rects > 0)
1611  {
1612  if (force_subtitle_display)
1613  {
1614  Subtitle->forced = 1;
1615  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Decoded forced subtitle");
1616  }
1617  return true;
1618  }
1619 fail:
1620  return false;
1621 }
1622 
1626 bool MythDVDBuffer::DVDButtonUpdate(bool ButtonMode)
1627 {
1628  if (!m_parent)
1629  return false;
1630 
1631  QSize videodispdim = m_parent->GetVideoSize();
1632  int videoheight = videodispdim.height();
1633  int videowidth = videodispdim.width();
1634 
1635  int32_t button = 0;
1636  dvdnav_highlight_area_t highlight;
1637  dvdnav_get_current_highlight(m_dvdnav, &button);
1638  pci_t *pci = dvdnav_get_current_nav_pci(m_dvdnav);
1639  dvdnav_status_t dvdRet =
1640  dvdnav_get_highlight_area_from_group(pci, DVD_BTN_GRP_Wide, button,
1641  static_cast<int32_t>(ButtonMode), &highlight);
1642 
1643  if (dvdRet == DVDNAV_STATUS_ERR)
1644  return false;
1645 
1646  for (uint i = 0 ; i < 4 ; i++)
1647  {
1648  m_buttonAlpha[i] = 0xf & (highlight.palette >> (4 * i));
1649  m_buttonColor[i] = 0xf & (highlight.palette >> (16 + 4 * i));
1650  }
1651 
1652  // If the button overlay has already been decoded, make sure
1653  // the correct palette for the current highlight is set
1654  if (m_dvdMenuButton.rects && (m_dvdMenuButton.num_rects > 1))
1655  {
1656  GuessPalette(reinterpret_cast<uint32_t*>(m_dvdMenuButton.rects[1]->data[1]),
1658  }
1659 
1660  m_hlButton.setCoords(highlight.sx, highlight.sy, highlight.ex, highlight.ey);
1661  return ((highlight.sx + highlight.sy) > 0) &&
1662  (highlight.sx < videowidth && highlight.sy < videoheight);
1663 }
1664 
1668 {
1669  if (m_buttonExists || m_dvdMenuButton.rects)
1670  {
1671  for (uint i = 0; i < m_dvdMenuButton.num_rects; i++)
1672  {
1673  AVSubtitleRect* rect = m_dvdMenuButton.rects[i];
1674  av_free(rect->data[0]);
1675  av_free(rect->data[1]);
1676  av_free(rect);
1677  }
1678  av_free(m_dvdMenuButton.rects);
1679  m_dvdMenuButton.rects = nullptr;
1680  m_dvdMenuButton.num_rects = 0;
1681  m_buttonExists = false;
1682  }
1683 }
1684 
1689 {
1690  if (m_menuBuflength == 0)
1691  return;
1692 
1693  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Clearing Menu SPU Packet" );
1694 
1695  ClearMenuButton();
1696 
1697  av_free(m_menuSpuPkt);
1698  m_menuBuflength = 0;
1699  m_hlButton.setRect(0, 0, 0, 0);
1700 }
1701 
1703 {
1704  pci_t *pci = dvdnav_get_current_nav_pci(m_dvdnav);
1705  int numButtons = pci->hli.hl_gi.btn_ns;
1706  if (numButtons > 0 && numButtons < 36)
1707  return numButtons;
1708  return 0;
1709 }
1710 
1714 {
1715  uint audioLang = 0;
1716  int8_t physicalStreamId = dvdnav_get_audio_logical_stream(m_dvdnav, static_cast<uint8_t>(Index));
1717 
1718  if (physicalStreamId >= 0)
1719  {
1720  uint16_t lang = dvdnav_audio_stream_to_lang(m_dvdnav, static_cast<uint8_t>(physicalStreamId));
1721  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Audio StreamID: %1; lang: %2").arg(Index).arg(lang));
1722  audioLang = ConvertLangCode(lang);
1723  }
1724  else
1725  {
1726  LOG(VB_PLAYBACK, LOG_WARNING, LOC + QString("Audio StreamID: %1 - not found!").arg(Index));
1727  }
1728 
1729  return audioLang;
1730 }
1731 
1738 {
1739  const uint AC3_OFFSET = 0x0080;
1740  const uint DTS_OFFSET = 0x0088;
1741  const uint LPCM_OFFSET = 0x00A0;
1742  const uint MP2_OFFSET = 0x01C0;
1743 
1744  if (StreamId >= MP2_OFFSET)
1745  StreamId -= MP2_OFFSET;
1746  else if (StreamId >= LPCM_OFFSET)
1747  StreamId -= LPCM_OFFSET;
1748  else if (StreamId >= DTS_OFFSET)
1749  StreamId -= DTS_OFFSET;
1750  else if (StreamId >= AC3_OFFSET)
1751  StreamId -= AC3_OFFSET;
1752 
1753  int logical = -1;
1754  for (uint8_t i = 0; i < 8; i++)
1755  {
1756  // Get the physical stream number at the given index
1757  // of the logical mapping table (function name is wrong!)
1758  int8_t phys = dvdnav_get_audio_logical_stream(m_dvdnav, i);
1759  if (static_cast<uint>(phys) == StreamId)
1760  {
1761  logical = i;
1762  break;
1763  }
1764  }
1765 
1766  return logical;
1767 }
1768 
1770 {
1771  int ret = -1;
1772  int8_t physicalStreamId = dvdnav_get_audio_logical_stream(m_dvdnav, static_cast<uint8_t>(Index));
1773  if (physicalStreamId < 0)
1774  return ret;
1775 
1776  audio_attr_t attributes;
1777  if (dvdnav_get_audio_attr(m_dvdnav, static_cast<uint8_t>(physicalStreamId), &attributes) == DVDNAV_STATUS_OK)
1778  {
1779  LOG(VB_AUDIO, LOG_INFO, QString("DVD Audio Track #%1 Language Extension Code - %2")
1780  .arg(Index).arg(attributes.code_extension));
1781  return attributes.code_extension;
1782  }
1783 
1784  return ret;
1785 }
1786 
1789 {
1790  uint16_t lang = dvdnav_spu_stream_to_lang(m_dvdnav, static_cast<uint8_t>(Id));
1791  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("StreamID: %1; lang: %2").arg(Id).arg(lang));
1792  return ConvertLangCode(lang);
1793 }
1794 
1799 {
1800  int8_t logstream = -1;
1801 
1802  // VM always sets stream_id to zero if we're not in the VTS
1803  // domain and always returns 0 (instead of -1) if nothing has
1804  // been found, so only try to retrieve the logical stream if
1805  // we *are* in the VTS domain or we *are* trying to map stream 0.
1806  if (dvdnav_is_domain_vts(m_dvdnav) || (StreamId == 0))
1807  logstream = dvdnav_get_spu_logical_stream(m_dvdnav, static_cast<uint8_t>(StreamId));
1808 
1809  return logstream;
1810 }
1811 
1814 {
1815  if (Code == 0)
1816  return 0;
1817 
1818  std::array<QChar,2> str2 { Code >> 8, Code & 0xff };
1819  QString str3 = iso639_str2_to_str3(QString(str2.data(), str2.size()));
1820 
1821  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("code: %1; iso639: %2").arg(Code).arg(str3));
1822 
1823  if (!str3.isEmpty())
1824  return static_cast<uint>(iso639_str3_to_key(str3));
1825  return 0;
1826 }
1827 
1832 {
1833  pci_t *pci = dvdnav_get_current_nav_pci(m_dvdnav);
1834  int32_t button = pci->hli.hl_gi.fosl_btnn;
1835  if (button > 0 && !m_cellRepeated)
1836  {
1837  dvdnav_button_select(m_dvdnav,pci,button);
1838  return;
1839  }
1840  dvdnav_get_current_highlight(m_dvdnav,&button);
1841  if (button > 0 && button <= NumMenuButtons())
1842  dvdnav_button_select(m_dvdnav,pci,button);
1843  else
1844  dvdnav_button_select(m_dvdnav,pci,1);
1845 }
1846 
1852 {
1853  if (Type == kTrackTypeSubtitle)
1854  {
1855  m_curSubtitleTrack = static_cast<int8_t>(TrackNo);
1856  m_autoselectsubtitle = TrackNo < 0;
1857  }
1858  else if (Type == kTrackTypeAudio)
1859  {
1860  m_curAudioTrack = TrackNo;
1861  dvdnav_set_active_audio_stream(m_dvdnav, static_cast<int8_t>(TrackNo));
1862  }
1863 }
1864 
1871 {
1872  if (Type == kTrackTypeSubtitle)
1873  return m_curSubtitleTrack;
1874  if (Type == kTrackTypeAudio)
1875  return m_curAudioTrack;
1876  return 0;
1877 }
1878 
1880 {
1881  int8_t physical = dvdnav_get_audio_logical_stream(m_dvdnav, static_cast<uint8_t>(Index));
1882  if (physical >= 0)
1883  {
1884  uint16_t channels = dvdnav_audio_stream_channels(m_dvdnav, static_cast<uint8_t>(physical));
1885  if (channels != 0xFFFf)
1886  return channels;
1887  }
1888  return 0;
1889 }
1890 
1892 {
1893  m_audioStreamsChanged = Change;
1894 }
1895 
1898 bool MythDVDBuffer::GetNameAndSerialNum(QString& Name, QString& SerialNumber)
1899 {
1900  Name = m_discName;
1901  SerialNumber = m_discSerialNumber;
1902  return !(Name.isEmpty() && SerialNumber.isEmpty());
1903 }
1904 
1908 {
1909  State.clear();
1910  char* dvdstate = dvdnav_get_state(m_dvdnav);
1911 
1912  if (dvdstate)
1913  {
1914  State = dvdstate;
1915  free(dvdstate);
1916  }
1917 
1918  return (!State.isEmpty());
1919 }
1920 
1924 {
1925  QByteArray state = State.toUtf8();
1926  return (dvdnav_set_state(m_dvdnav, state.constData()) == DVDNAV_STATUS_OK);
1927 }
1928 
1935 {
1936  int format = dvdnav_get_video_format(m_dvdnav);
1937  double dvdfps = (format == 1) ? 25.00 : 29.97;
1938  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("DVD Frame Rate %1").arg(dvdfps));
1939  return dvdfps;
1940 }
1941 
1943 {
1944  return m_part == 0;
1945 }
1946 
1948 {
1949  return ((m_titleParts == 0) || (m_part == (m_titleParts - 1)) || (m_titleParts == 1));
1950 }
1951 
1952 void MythDVDBuffer::PlayTitleAndPart(int Title, int Part)
1953 {
1954  dvdnav_part_play(m_dvdnav, Title, Part);
1955 }
1956 
1959 {
1960  QMutexLocker lock(&m_seekLock);
1962 }
1963 
1966 {
1967  if (m_filename.startsWith("/"))
1968  MediaMonitor::SetCDSpeed(m_filename.toLocal8Bit().constData(), Speed);
1969 }
1970 
1973 {
1974  return static_cast<uint>(GetTotalTimeOfTitle() - GetCurrentTime());
1975 }
1976 
1978 {
1979  return (m_currentTime / 90000);
1980 }
1981 
1983 void MythDVDBuffer::GuessPalette(uint32_t *RGBAPalette, const PaletteArray& Palette, const AlphaArray& Alpha)
1984 {
1985  memset(RGBAPalette, 0, 16);
1986  for (int i = 0 ; i < 4 ; i++)
1987  {
1988  uint32_t yuv = m_clut[Palette[i]];
1989  uint y = (yuv >> 16) & 0xff;
1990  uint cr = (yuv >> 8) & 0xff;
1991  uint cb = (yuv >> 0) & 0xff;
1992  uint r = qBound(0U, uint(y + 1.4022 * (cr - 128)), 0xFFU);
1993  uint b = qBound(0U, uint(y + 1.7710 * (cb - 128)), 0xFFU);
1994  uint g = qBound(0U, uint(1.7047 * y - (0.1952 * b) - (0.5647 * r)), 0xFFU);
1995  RGBAPalette[i] = ((Alpha[i] * 17U) << 24) | (r << 16 )| (g << 8) | b;
1996  }
1997 }
1998 
2002 int MythDVDBuffer::DecodeRLE(uint8_t *Bitmap, int Linesize, int Width, int Height,
2003  const uint8_t *Buffer, int NibbleOffset, int BufferSize)
2004 {
2005  int nibbleEnd = BufferSize * 2;
2006  int x = 0;
2007  int y = 0;
2008  uint8_t *data = Bitmap;
2009  for(;;)
2010  {
2011  if (NibbleOffset >= nibbleEnd)
2012  return -1;
2013  uint v = GetNibble(Buffer, NibbleOffset++);
2014  if (v < 0x4)
2015  {
2016  v = (v << 4) | GetNibble(Buffer, NibbleOffset++);
2017  if (v < 0x10)
2018  {
2019  v = (v << 4) | GetNibble(Buffer, NibbleOffset++);
2020  if (v < 0x040)
2021  {
2022  v = (v << 4) | GetNibble(Buffer, NibbleOffset++);
2023  if (v < 4)
2024  v |= static_cast<uint>(Width - x) << 2;
2025  }
2026  }
2027  }
2028  int len = v >> 2;
2029  if (len > (Width - x))
2030  len = Width - x;
2031  int color = v & 0x03;
2032  memset(data + x, color, static_cast<size_t>(len));
2033  x += len;
2034  if (x >= Width)
2035  {
2036  y++;
2037  if (y >= Height)
2038  break;
2039  data += Linesize;
2040  x = 0;
2041  NibbleOffset += (NibbleOffset & 1);
2042  }
2043  }
2044  return 0;
2045 }
2046 
2049 uint MythDVDBuffer::GetNibble(const uint8_t *Buffer, int NibbleOffset)
2050 {
2051  return (Buffer[NibbleOffset >> 1] >> ((1 - (NibbleOffset & 1)) << 2)) & 0xf;
2052 }
2053 
2058 int MythDVDBuffer::IsTransparent(const uint8_t *Buffer, int Pitch, int Num, const ColorArray& Colors)
2059 {
2060  for (int i = 0; i < Num; i++)
2061  {
2062  if (!Colors[*Buffer])
2063  return 0;
2064  Buffer += Pitch;
2065  }
2066  return 1;
2067 }
2068 
2074 {
2075  ColorArray colors {};
2076 
2077  if (Subtitle->num_rects == 0 || Subtitle->rects == nullptr ||
2078  Subtitle->rects[0]->w <= 0 || Subtitle->rects[0]->h <= 0)
2079  {
2080  return 0;
2081  }
2082 
2083  for (int i = 0; i < Subtitle->rects[0]->nb_colors; i++)
2084  if (((reinterpret_cast<uint32_t*>(Subtitle->rects[0]->data[1])[i] >> 24)) == 0)
2085  colors[i] = 1;
2086 
2087  int bottom = 0;
2088  while (bottom < Subtitle->rects[0]->h &&
2089  IsTransparent(Subtitle->rects[0]->data[0] + bottom * Subtitle->rects[0]->linesize[0],
2090  1, Subtitle->rects[0]->w, colors))
2091  {
2092  bottom++;
2093  }
2094 
2095  if (bottom == Subtitle->rects[0]->h)
2096  {
2097  av_freep(&Subtitle->rects[0]->data[0]);
2098  Subtitle->rects[0]->w = Subtitle->rects[0]->h = 0;
2099  return 0;
2100  }
2101 
2102  int top = Subtitle->rects[0]->h - 1;
2103  while (top > 0 &&
2104  IsTransparent(Subtitle->rects[0]->data[0] + top * Subtitle->rects[0]->linesize[0], 1,
2105  Subtitle->rects[0]->w, colors))
2106  {
2107  top--;
2108  }
2109 
2110  int left = 0;
2111  while (left < (Subtitle->rects[0]->w - 1) &&
2112  IsTransparent(Subtitle->rects[0]->data[0] + left, Subtitle->rects[0]->linesize[0],
2113  Subtitle->rects[0]->h, colors))
2114  {
2115  left++;
2116  }
2117 
2118  int right = Subtitle->rects[0]->w - 1;
2119  while (right > 0 &&
2120  IsTransparent(Subtitle->rects[0]->data[0] + right, Subtitle->rects[0]->linesize[0],
2121  Subtitle->rects[0]->h, colors))
2122  {
2123  right--;
2124  }
2125 
2126  int width = right - left + 1;
2127  int height = top - bottom + 1;
2128  auto *bitmap = static_cast<uint8_t*>(av_malloc(static_cast<size_t>(width * height)));
2129  if (!bitmap)
2130  return 1;
2131 
2132  for (int y = 0; y < height; y++)
2133  {
2134  memcpy(bitmap + width * y, Subtitle->rects[0]->data[0] + left +
2135  (bottom + y) * Subtitle->rects[0]->linesize[0], static_cast<size_t>(width));
2136  }
2137 
2138  av_freep(&Subtitle->rects[0]->data[0]);
2139  Subtitle->rects[0]->data[0] = bitmap;
2140  Subtitle->rects[0]->linesize[0] = width;
2141  Subtitle->rects[0]->w = width;
2142  Subtitle->rects[0]->h = height;
2143  Subtitle->rects[0]->x += left;
2144  Subtitle->rects[0]->y += bottom;
2145  return 1;
2146 }
2147 
2149 {
2150  if (!m_dvdnav)
2151  return false;
2152 
2153  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Switching to Angle %1...").arg(Angle));
2154  dvdnav_status_t status = dvdnav_angle_change(m_dvdnav, static_cast<int32_t>(Angle));
2155  if (status == DVDNAV_STATUS_OK)
2156  {
2157  m_currentAngle = Angle;
2158  return true;
2159  }
2160  return false;
2161 }
2162 
2164 {
2165  m_parent = Parent;
2166 }
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:1688
MythDVDBuffer::PlayTrack
bool PlayTrack(int Track)
Definition: mythdvdbuffer.cpp:1097
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:1870
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:307
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:1144
MythDVDPlayer::SetStillFrameTimeout
void SetStillFrameTimeout(int Length)
Definition: mythdvdplayer.cpp:728
MythDVDBuffer::RestoreDVDStateSnapshot
bool RestoreDVDStateSnapshot(QString &State)
Restore a DVD VM from a snapshot.
Definition: mythdvdbuffer.cpp:1923
MythDVDBuffer::SkipStillFrame
void SkipStillFrame(void)
Definition: mythdvdbuffer.cpp:1194
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:1626
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:1667
MythDVDBuffer::GetPartAndTitle
void GetPartAndTitle(int &Part, int &Title) const
Definition: mythdvdbuffer.cpp:459
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:1851
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:1450
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:1942
MythDVDBuffer::GetDVDContext
MythDVDContext * GetDVDContext(void)
Definition: mythdvdbuffer.cpp:481
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))
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:1831
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:1232
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:1972
MythDVDBuffer::GetTitle
int GetTitle(void) const
Definition: mythdvdbuffer.cpp:424
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:1934
MythOpticalBuffer::PROCESS_WAIT
@ PROCESS_WAIT
Definition: mythopticalbuffer.h:21
MythDVDBuffer::GetChapterLength
uint GetChapterLength(void) const
Definition: mythdvdbuffer.cpp:454
MythDVDBuffer::GetLastEvent
int32_t GetLastEvent(void) const
Definition: mythdvdbuffer.cpp:489
MythDVDBuffer::SkipDVDWaitingForPlayer
void SkipDVDWaitingForPlayer(void)
Definition: mythdvdbuffer.cpp:1215
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:2058
MythDVDBuffer::CellChanged
bool CellChanged(void)
check if dvd cell has changed
Definition: mythdvdbuffer.cpp:1158
MythDVDBuffer::m_currentTitleAngleCount
int m_currentTitleAngleCount
Definition: mythdvdbuffer.h:170
MediaMonitor::SetCDSpeed
static void SetCDSpeed(const char *device, int speed)
Definition: mythmediamonitor.cpp:102
MythDVDBuffer::MoveButtonRight
void MoveButtonRight(void)
Definition: mythdvdbuffer.cpp:1347
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:2163
MythDVDBuffer::IsReadingBlocked
bool IsReadingBlocked(void)
Definition: mythdvdbuffer.cpp:1225
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:429
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:439
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:2049
MythDVDBuffer::IgnoreWaitStates
void IgnoreWaitStates(bool Ignore) override
Definition: mythdvdbuffer.cpp:1333
MythDVDBuffer::m_currentpos
long long m_currentpos
Definition: mythdvdbuffer.h:162
mythlogging.h
MythDVDBuffer::PlayTitleAndPart
void PlayTitleAndPart(int Title, int Part)
Definition: mythdvdbuffer.cpp:1952
MythDVDBuffer::GetButtonCoords
QRect GetButtonCoords(void)
get coordinates of highlighted button
Definition: mythdvdbuffer.cpp:1438
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:1769
MythDVDBuffer::EndOfTitle
bool EndOfTitle(void) const
Definition: mythdvdbuffer.cpp:1947
MythDVDBuffer::HandleAction
bool HandleAction(const QStringList &Actions, int64_t Pts) override
Definition: mythdvdbuffer.cpp:1312
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:1737
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:1256
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:67
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:1187
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:1713
MythDVDBuffer::AudioStreamsChanged
bool AudioStreamsChanged(void) const
Definition: mythdvdbuffer.cpp:1170
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:30
MythDVDBuffer::m_titleLength
long long m_titleLength
Definition: mythdvdbuffer.h:177
MythDVDBuffer::MoveButtonLeft
void MoveButtonLeft(void)
Definition: mythdvdbuffer.cpp:1338
uint
unsigned int uint
Definition: compat.h:140
MythDVDBuffer::ReleaseMenuButton
void ReleaseMenuButton(void)
Definition: mythdvdbuffer.cpp:1431
MythDVDBuffer::NumPartsInTitle
int NumPartsInTitle(void) const
Definition: mythdvdbuffer.cpp:1180
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:57
MythDVDBuffer::IsWaiting
bool IsWaiting(void) const
Definition: mythdvdbuffer.cpp:1175
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:494
MythDVDBuffer::NormalSeek
long long NormalSeek(long long Time)
Definition: mythdvdbuffer.cpp:143
MythOpenGLInterop::Type
Type
Definition: mythopenglinterop.h:30
kTrackTypeSubtitle
@ kTrackTypeSubtitle
Definition: decoderbase.h:32
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:465
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:1416
mythuihelper.h
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:1958
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:1294
Buffer
Definition: MythExternControl.h:37
MythOpticalBuffer::m_currentAngle
int m_currentAngle
Definition: mythopticalbuffer.h:25
MythDVDBuffer::GetNumAngles
int GetNumAngles(void) const
Definition: mythdvdbuffer.cpp:444
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:1124
Name
Definition: channelsettings.cpp:47
MythDVDBuffer::ActivateButton
void ActivateButton(void)
Action taken when a dvd menu button is selected.
Definition: mythdvdbuffer.cpp:1375
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:1898
MythDVDBuffer::m_cellstartPos
long long m_cellstartPos
Definition: mythdvdbuffer.h:179
MythPlayer::GetVideoSize
QSize GetVideoSize(void) const
Definition: mythplayer.h:205
MythDVDBuffer::m_buttonColor
AlphaArray m_buttonColor
Definition: mythdvdbuffer.h:207
MythDVDBuffer::GetPart
int GetPart(void) const
Definition: mythdvdbuffer.cpp:434
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:1139
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:1977
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:2073
MythOpticalBuffer
Definition: mythopticalbuffer.h:8
MythDVDBuffer::GetCellStart
uint GetCellStart(void) const
get the start of the cell in seconds
Definition: mythdvdbuffer.cpp:1151
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:1165
ACTION_LEFT
#define ACTION_LEFT
Definition: mythuiactions.h:18
MythDVDBuffer::NumMenuButtons
int NumMenuButtons(void) const
Definition: mythdvdbuffer.cpp:1702
MythDVDBuffer::UnblockReading
void UnblockReading(void)
Definition: mythdvdbuffer.cpp:1220
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:70
MythDVDBuffer::GetSubtitleTrackNum
int8_t GetSubtitleTrackNum(uint StreamId)
get the logical subtitle track/stream number from the dvd
Definition: mythdvdbuffer.cpp:1798
MythDVDBuffer::GetNumAudioChannels
uint16_t GetNumAudioChannels(int Index)
Definition: mythdvdbuffer.cpp:1879
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:1207
MythDVDBuffer::GetTotalReadPosition
long long GetTotalReadPosition(void) const
Definition: mythdvdbuffer.cpp:449
mythuiactions.h
MythUIHelper::DisableScreensaver
static void DisableScreensaver(void)
Definition: mythuihelper.cpp:1354
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:1365
MythDVDBuffer::NextTrack
bool NextTrack(void)
Definition: mythdvdbuffer.cpp:1110
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:1788
MythDVDBuffer::m_buttonVersion
uint m_buttonVersion
Definition: mythdvdbuffer.h:204
ACTION_CHANNELUP
#define ACTION_CHANNELUP
Definition: tv_actions.h:16
MythDVDBuffer::GuessPalette
void GuessPalette(uint32_t *RGBAPalette, const PaletteArray &Palette, const AlphaArray &Alpha)
converts palette values from YUV to RGB
Definition: mythdvdbuffer.cpp:1983
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:1303
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:1356
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:1386
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:409
MythDVDBuffer::SwitchAngle
bool SwitchAngle(int Angle)
Definition: mythdvdbuffer.cpp:2148
MythUIHelper::RestoreScreensaver
static void RestoreScreensaver(void)
Definition: mythuihelper.cpp:1364
ACTION_SEEKFFWD
#define ACTION_SEEKFFWD
Definition: tv_actions.h:43
MythPlayer::GetFFRewSkip
int GetFFRewSkip(void) const
Definition: mythplayer.h:217
MythDVDBuffer::m_seekLock
QMutex m_seekLock
Definition: mythdvdbuffer.h:214
MThread::usleep
static void usleep(unsigned long time)
Definition: mthread.cpp:343
MythDVDBuffer::SafeRead
int SafeRead(void *Buffer, uint Size) override
Definition: mythdvdbuffer.cpp:516
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:2002
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:1813
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:916
MythDVDBuffer::GetDVDStateSnapshot
bool GetDVDStateSnapshot(QString &State)
Get a snapshot of the current DVD VM state.
Definition: mythdvdbuffer.cpp:1907