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