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