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