MythTV  master
decoderbase.cpp
Go to the documentation of this file.
1 
2 #include <algorithm>
3 
4 #include "libmythbase/iso639.h"
5 #include "libmythbase/mythconfig.h"
8 
9 #include "Bluray/mythbdbuffer.h"
10 #include "DVD/mythdvdbuffer.h"
11 #include "decoderbase.h"
12 #include "mythcodeccontext.h"
13 #include "mythplayer.h"
14 
15 #define LOC QString("Dec: ")
16 
18  : m_parent(parent), m_playbackInfo(new ProgramInfo(pginfo)),
19  m_audio(m_parent->GetAudio()),
20 
21  // language preference
22  m_languagePreference(iso639_get_language_key_list())
23 {
24  ResetTracks();
25  m_tracks[kTrackTypeAudio].emplace_back(0, 0, 0, 0, kAudioTypeNormal);
26  m_tracks[kTrackTypeCC608].emplace_back(0, 1);
27  m_tracks[kTrackTypeCC608].emplace_back(0, 3);
28 }
29 
31 {
32  delete m_playbackInfo;
33 }
34 
36 {
37  if (RenderFormats != nullptr)
38  m_renderFormats = RenderFormats;
39 }
40 
42 {
43  delete m_playbackInfo;
44  m_playbackInfo = new ProgramInfo(pginfo);
45 }
46 
47 void DecoderBase::Reset(bool reset_video_data, bool seek_reset, bool reset_file)
48 {
49  LOG(VB_PLAYBACK, LOG_INFO, LOC +
50  QString("Reset: Video %1, Seek %2, File %3")
51  .arg(reset_video_data).arg(seek_reset).arg(reset_file));
52 
53  if (seek_reset)
54  SeekReset(0, 0, true, true);
55 
56  if (reset_video_data)
57  {
58  ResetPosMap();
59  m_framesPlayed = 0;
60  m_frameCounter += 100;
61  m_fpsSkip = 0;
62  m_framesRead = 0;
64  m_dontSyncPositionMap = false;
65  }
66 
67  if (reset_file)
68  {
69  m_waitingForChange = false;
71  }
72 }
73 
74 void DecoderBase::SeekReset(long long /*newkey*/, uint /*skipFrames*/,
75  bool /*doFlush*/, bool /*discardFrames*/)
76 {
77  m_readAdjust = 0;
78  m_frameCounter += 100; // NB don't just set to 0
79 }
80 
82 {
83  bool wereWatchingRecording = m_watchingRecording;
84 
85  // When we switch from WatchingRecording to WatchingPreRecorded,
86  // re-get the positionmap
87  m_posmapStarted = false;
88  m_watchingRecording = mode;
89 
90  if (wereWatchingRecording && !m_watchingRecording)
92 }
93 
95 {
96  if (!m_playbackInfo)
97  return false;
98 
99  // Overwrites current positionmap with entire contents of database
100  frm_pos_map_t posMap;
101  frm_pos_map_t durMap;
102 
103  if (m_ringBuffer && m_ringBuffer->IsDVD())
104  {
105  m_keyframeDist = 15;
107  if (m_fps < 26 && m_fps > 24)
108  m_keyframeDist = 12;
109  auto totframes =
110  (long long)(m_ringBuffer->DVD()->GetTotalTimeOfTitle().count() * m_fps);
111  posMap[totframes] = m_ringBuffer->DVD()->GetTotalReadPosition();
112  }
113  else if (m_ringBuffer && m_ringBuffer->IsBD())
114  {
115  m_keyframeDist = 15;
117  if (m_fps < 26 && m_fps > 24)
118  m_keyframeDist = 12;
119  auto totframes =
120  (long long)(m_ringBuffer->BD()->GetTotalTimeOfTitle().count() * m_fps);
121  posMap[totframes] = m_ringBuffer->BD()->GetTotalReadPosition();
122 #if 0
123  LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
124  QString("%1 TotalTimeOfTitle() in ticks, %2 TotalReadPosition() "
125  "in bytes, %3 is fps")
127  .arg(m_ringBuffer->BD()->GetTotalReadPosition()).arg(m_fps));
128 #endif
129  }
130  else if ((m_positionMapType == MARK_UNSET) ||
131  (m_keyframeDist == -1))
132  {
134  if (!posMap.empty())
135  {
137  if (m_keyframeDist == -1)
138  m_keyframeDist = 1;
139  }
140  else
141  {
143  if (!posMap.empty())
144  {
146  if (m_keyframeDist == -1)
147  {
148  m_keyframeDist = 15;
149  if (m_fps < 26 && m_fps > 24)
150  m_keyframeDist = 12;
151  }
152  }
153  else
154  {
156  if (!posMap.empty())
157  {
158  // keyframedist should be set in the fileheader so no
159  // need to try to determine it in this case
161  }
162  }
163  }
164  }
165  else
166  {
168  }
169 
170  if (posMap.empty())
171  return false; // no position map in recording
172 
174 
175  QMutexLocker locker(&m_positionMapLock);
176  m_positionMap.clear();
177  m_positionMap.reserve(posMap.size());
178  m_frameToDurMap.clear();
179  m_durToFrameMap.clear();
180 
181  for (auto it = posMap.cbegin(); it != posMap.cend(); ++it)
182  {
183  PosMapEntry e = {it.key(), it.key() * m_keyframeDist, *it};
184  m_positionMap.push_back(e);
185  }
186 
187  if (!m_positionMap.empty() && !(m_ringBuffer && m_ringBuffer->IsDisc()))
188  m_indexOffset = m_positionMap[0].index;
189 
190  if (!m_positionMap.empty())
191  {
192  LOG(VB_PLAYBACK, LOG_INFO, LOC +
193  QString("Position map filled from DB to: %1")
194  .arg(m_positionMap.back().index));
195  }
196 
197  uint64_t last = 0;
198  for (auto it = durMap.cbegin(); it != durMap.cend(); ++it)
199  {
200  m_frameToDurMap[it.key()] = it.value();
201  m_durToFrameMap[it.value()] = it.key();
202  last = it.key();
203  }
204 
205  if (!m_durToFrameMap.empty())
206  {
207  LOG(VB_PLAYBACK, LOG_INFO, LOC +
208  QString("Duration map filled from DB to: %1").arg(last));
209  }
210 
211  return true;
212 }
213 
223 {
224  if (!m_parent || m_keyframeDist < 1)
225  return false;
226 
227  unsigned long long start = 0;
228  {
229  QMutexLocker locker(&m_positionMapLock);
230  if (!m_positionMap.empty())
231  start = m_positionMap.back().index + 1;
232  }
233 
234  frm_pos_map_t posMap;
235  frm_pos_map_t durMap;
236  if (!m_parent->PosMapFromEnc(start, posMap, durMap))
237  return false;
238 
239  QMutexLocker locker(&m_positionMapLock);
240 
241  // append this new position map to class's
242  m_positionMap.reserve(m_positionMap.size() + posMap.size());
243 
244  long long last_index = 0;
245  if (!m_positionMap.empty())
246  last_index = m_positionMap.back().index;
247  for (auto it = posMap.cbegin(); it != posMap.cend(); ++it)
248  {
249  if (it.key() <= last_index)
250  continue;
251 
252  PosMapEntry e = {it.key(), it.key() * m_keyframeDist, *it};
253  m_positionMap.push_back(e);
254  }
255 
256  if (!m_positionMap.empty() && !(m_ringBuffer && m_ringBuffer->IsDisc()))
257  m_indexOffset = m_positionMap[0].index;
258 
259  if (!m_positionMap.empty())
260  {
261  LOG(VB_PLAYBACK, LOG_INFO, LOC +
262  QString("Position map filled from Encoder to: %1")
263  .arg(m_positionMap.back().index));
264  }
265 
266  bool isEmpty = m_frameToDurMap.empty();
267  if (!isEmpty)
268  {
269  frm_pos_map_t::const_iterator it = m_frameToDurMap.cend();
270  --it;
271  last_index = it.key();
272  }
273  for (frm_pos_map_t::const_iterator it = durMap.cbegin();
274  it != durMap.cend(); ++it)
275  {
276  if (!isEmpty && it.key() <= last_index)
277  continue; // we released the m_positionMapLock for a few ms...
278  m_frameToDurMap[it.key()] = it.value();
279  m_durToFrameMap[it.value()] = it.key();
280  }
281 
282  if (!m_frameToDurMap.empty())
283  {
284  frm_pos_map_t::const_iterator it = m_frameToDurMap.cend();
285  --it;
286  LOG(VB_PLAYBACK, LOG_INFO, LOC +
287  QString("Duration map filled from Encoder to: %1").arg(it.key()));
288  }
289 
290  return true;
291 }
292 
293 unsigned long DecoderBase::GetPositionMapSize(void) const
294 {
295  QMutexLocker locker(&m_positionMapLock);
296  return m_positionMap.size();
297 }
298 
322 {
323  LOG(VB_PLAYBACK, LOG_INFO, LOC +
324  QString("Resyncing position map. posmapStarted = %1"
325  " livetv(%2) watchingRec(%3)")
326  .arg((int) m_posmapStarted).arg(m_livetv).arg(m_watchingRecording));
327 
329  return false;
330 
331  unsigned long old_posmap_size = GetPositionMapSize();
332  unsigned long new_posmap_size = old_posmap_size;
333 
335  {
336  if (!m_posmapStarted)
337  {
338  // starting up -- try first from database
339  PosMapFromDb();
340  new_posmap_size = GetPositionMapSize();
341  LOG(VB_PLAYBACK, LOG_INFO, LOC +
342  QString("SyncPositionMap watchingrecording, from DB: "
343  "%1 entries") .arg(new_posmap_size));
344  }
345  // always try to get more from encoder
346  if (!PosMapFromEnc())
347  {
348  LOG(VB_PLAYBACK, LOG_INFO, LOC +
349  QString("SyncPositionMap watchingrecording no entries "
350  "from encoder, try DB"));
351  PosMapFromDb(); // try again from db
352  }
353 
354  new_posmap_size = GetPositionMapSize();
355  LOG(VB_PLAYBACK, LOG_INFO, LOC +
356  QString("SyncPositionMap watchingrecording total: %1 entries")
357  .arg(new_posmap_size));
358  }
359  else
360  {
361  // watching prerecorded ... just get from db
362  if (!m_posmapStarted)
363  {
364  PosMapFromDb();
365 
366  new_posmap_size = GetPositionMapSize();
367  LOG(VB_PLAYBACK, LOG_INFO, LOC +
368  QString("SyncPositionMap prerecorded, from DB: %1 entries")
369  .arg(new_posmap_size));
370  }
371  }
372 
373  bool ret_val = new_posmap_size > old_posmap_size;
374 
375  if (ret_val && m_keyframeDist > 0)
376  {
377  long long totframes = 0;
378  std::chrono::seconds length = 0s;
379 
380  if (m_ringBuffer && m_ringBuffer->IsDVD())
381  {
382  length = m_ringBuffer->DVD()->GetTotalTimeOfTitle();
383  QMutexLocker locker(&m_positionMapLock);
384  totframes = m_positionMap.back().index;
385  }
386  else if (m_ringBuffer && m_ringBuffer->IsBD())
387  {
388  length = m_ringBuffer->BD()->GetTotalTimeOfTitle();
389  QMutexLocker locker(&m_positionMapLock);
390  totframes = m_positionMap.back().index;
391  }
392  else
393  {
394  QMutexLocker locker(&m_positionMapLock);
395  totframes = m_positionMap.back().index * m_keyframeDist;
396  if (m_fps != 0.0)
397  length = secondsFromFloat((totframes * 1.0) / m_fps);
398  }
399 
400  m_parent->SetFileLength(length, totframes);
402  m_posmapStarted = true;
403 
404  LOG(VB_PLAYBACK, LOG_INFO, LOC +
405  QString("SyncPositionMap, new totframes: %1, new length: %2, "
406  "posMap size: %3")
407  .arg(totframes).arg(length.count()).arg(new_posmap_size));
408  }
409  m_recordingHasPositionMap |= (0 != new_posmap_size);
410  {
411  QMutexLocker locker(&m_positionMapLock);
412  m_lastPositionMapUpdate = QDateTime::currentDateTime();
413  }
414  return ret_val;
415 }
416 
417 // returns true iff found exactly
418 // searches position if search_pos, index otherwise
419 bool DecoderBase::FindPosition(long long desired_value, bool search_adjusted,
420  int &lower_bound, int &upper_bound)
421 {
422  QMutexLocker locker(&m_positionMapLock);
423  // Binary search
424  auto size = (long long) m_positionMap.size();
425  long long lower = -1;
426  long long upper = size;
427 
428  if (!search_adjusted && m_keyframeDist > 0)
429  desired_value /= m_keyframeDist;
430 
431  while (upper - 1 > lower)
432  {
433  long long i = (upper + lower) / 2;
434  long long value = 0;
435  if (search_adjusted)
436  value = m_positionMap[i].adjFrame;
437  else
438  value = m_positionMap[i].index - m_indexOffset;
439  if (value == desired_value)
440  {
441  // found it
442  upper_bound = i;
443  lower_bound = i;
444 
445  LOG(VB_PLAYBACK, LOG_INFO, LOC +
446  QString("FindPosition(%1, search%2 adjusted)")
447  .arg(desired_value).arg((search_adjusted) ? "" : " not") +
448  QString(" --> [%1:%2(%3)]")
449  .arg(i).arg(GetKey(m_positionMap[i]))
450  .arg(m_positionMap[i].pos));
451 
452  return true;
453  }
454  if (value > desired_value)
455  upper = i;
456  else
457  lower = i;
458  }
459  // Did not find it exactly -- return bounds
460 
461  if (search_adjusted)
462  {
463  while (lower >= 0 && m_positionMap[lower].adjFrame > desired_value)
464  lower--;
465  while (upper < size && m_positionMap[upper].adjFrame < desired_value)
466  upper++;
467  }
468  else
469  {
470  while (lower >= 0 &&
471  (m_positionMap[lower].index - m_indexOffset) > desired_value)
472  lower--;
473  while (upper < size &&
474  (m_positionMap[upper].index - m_indexOffset) < desired_value)
475  upper++;
476  }
477  // keep in bounds
478  lower = std::max(lower, 0LL);
479  upper = std::min(upper, size - 1LL);
480 
481  upper_bound = upper;
482  lower_bound = lower;
483  bool empty = m_positionMap.empty();
484 
485  LOG(VB_PLAYBACK, LOG_INFO, LOC +
486  QString("FindPosition(%1, search%3 adjusted)")
487  .arg(desired_value).arg((search_adjusted) ? "" : " not") +
488  QString(" --> \n\t\t\t[%1:%2(%3),%4:%5(%6)]")
489  .arg(lower_bound)
490  .arg(empty ? -1 : GetKey(m_positionMap[lower_bound]))
491  .arg(empty ? -1 : m_positionMap[lower_bound].pos)
492  .arg(upper_bound)
493  .arg(empty ? -1 : GetKey(m_positionMap[upper_bound]))
494  .arg(empty ? -1 : m_positionMap[upper_bound].pos));
495 
496  return false;
497 }
498 
499 uint64_t DecoderBase::SavePositionMapDelta(long long first, long long last)
500 {
501  MythTimer ttm;
502  MythTimer ctm;
503  MythTimer stm;
504  ttm.start();
505 
506  QMutexLocker locker(&m_positionMapLock);
508  uint64_t saved = 0;
509 
511  return saved;
512 
513  ctm.start();
514  frm_pos_map_t posMap;
515  for (auto & entry : m_positionMap)
516  {
517  if (entry.index < first)
518  continue;
519  if (entry.index > last)
520  break;
521 
522  posMap[entry.index] = entry.pos;
523  saved++;
524  }
525 
526  frm_pos_map_t durMap;
527  for (auto it = m_frameToDurMap.cbegin(); it != m_frameToDurMap.cend(); ++it)
528  {
529  if (it.key() < first)
530  continue;
531  if (it.key() > last)
532  break;
533  durMap[it.key()] = it.value();
534  }
535 
536  locker.unlock();
537 
538  stm.start();
541 
542 #if 0
543  LOG(VB_GENERAL, LOG_DEBUG, LOC +
544  QString("Saving position map [%1,%2] w/%3 keyframes, "
545  "took (%4,%5,%6) ms")
546  .arg(first).arg(last).arg(saved)
547  .arg(ttm.elapsed())
548  .arg(ctm.elapsed()-stm.elapsed()).arg(stm.elapsed()));
549 #endif
550 
551  return saved;
552 }
553 
554 bool DecoderBase::DoRewind(long long desiredFrame, bool discardFrames)
555 {
556  LOG(VB_PLAYBACK, LOG_INFO, LOC +
557  QString("DoRewind(%1 (%2), %3 discard frames)")
558  .arg(desiredFrame).arg(m_framesPlayed)
559  .arg((discardFrames) ? "do" : "don't"));
560 
561  if (!DoRewindSeek(desiredFrame))
562  return false;
563 
565  m_fpsSkip = 0;
567 
568  // Do any Extra frame-by-frame seeking for exactseeks mode
569  // And flush pre-seek frame if we are allowed to and need to..
570  int normalframes = (uint64_t)(desiredFrame - (m_framesPlayed - 1)) > m_seekSnap
571  ? desiredFrame - m_framesPlayed : 0;
572  normalframes = std::max(normalframes, 0);
573  SeekReset(m_lastKey, normalframes, true, discardFrames);
574 
575  if (discardFrames || (m_ringBuffer && m_ringBuffer->IsDisc()))
577 
578  return true;
579 }
580 
581 long long DecoderBase::GetKey(const PosMapEntry &e) const
582 {
583  long long kf = (m_ringBuffer && m_ringBuffer->IsDisc()) ?
584  1LL : m_keyframeDist;
585  return (m_hasKeyFrameAdjustTable) ? e.adjFrame :(e.index - m_indexOffset) * kf;
586 }
587 
588 bool DecoderBase::DoRewindSeek(long long desiredFrame)
589 {
590  ConditionallyUpdatePosMap(desiredFrame);
591 
592  if (!GetPositionMapSize())
593  {
594  LOG(VB_GENERAL, LOG_ERR, LOC + "PosMap is empty, can't seek");
595  return false;
596  }
597 
598  if (!m_ringBuffer)
599  {
600  LOG(VB_GENERAL, LOG_ERR, LOC + "No ringBuffer yet, can't seek");
601  return false;
602  }
603 
604  // Find keyframe <= desiredFrame, store in lastKey (frames)
605  int pre_idx = 0;
606  int post_idx = 0;
607  FindPosition(desiredFrame, m_hasKeyFrameAdjustTable, pre_idx, post_idx);
608 
609  PosMapEntry e {};
610  {
611  QMutexLocker locker(&m_positionMapLock);
612  PosMapEntry e_pre = m_positionMap[pre_idx];
613  PosMapEntry e_post = m_positionMap[post_idx];
614  int pos_idx = pre_idx;
615  e = e_pre;
616  if (((uint64_t) (GetKey(e_post) - desiredFrame)) <= m_seekSnap &&
617  m_framesPlayed - 1 > GetKey(e_post) &&
618  GetKey(e_post) - desiredFrame <= desiredFrame - GetKey(e_pre))
619  {
620  // Snap to the right if e_post is within snap distance and
621  // is at least as close a snap as e_pre. Take into
622  // account that if framesPlayed has already reached
623  // e_post, we should only snap to the left.
624  pos_idx = post_idx;
625  e = e_post;
626  }
627  m_lastKey = GetKey(e);
628 
629  // ??? Don't rewind past the beginning of the file
630  while (e.pos < 0)
631  {
632  pos_idx++;
633  if (pos_idx >= (int)m_positionMap.size())
634  return false;
635 
636  e = m_positionMap[pos_idx];
637  m_lastKey = GetKey(e);
638  }
639  }
640 
641  m_ringBuffer->Seek(e.pos, SEEK_SET);
642 
643  return true;
644 }
645 
647 {
648  QMutexLocker locker(&m_positionMapLock);
649  m_posmapStarted = false;
650  m_positionMap.clear();
651  m_frameToDurMap.clear();
652  m_durToFrameMap.clear();
653 }
654 
656 {
657  long long last_frame = 0;
658 
659  QMutexLocker locker(&m_positionMapLock);
660  if (!m_positionMap.empty())
661  last_frame = GetKey(m_positionMap.back());
662 
663  return last_frame;
664 }
665 
666 long long DecoderBase::ConditionallyUpdatePosMap(long long desiredFrame)
667 {
668  long long last_frame = GetLastFrameInPosMap();
669 
670  if (desiredFrame < 0)
671  return last_frame;
672 
673  // Resync keyframe map if we are trying to seek to a frame
674  // not yet equalled or exceeded in the seek map.
675  if (desiredFrame < last_frame)
676  return last_frame;
677 
678  LOG(VB_PLAYBACK, LOG_INFO, LOC +
679  "ConditionallyUpdatePosMap: Not enough info in positionMap," +
680  QString("\n\t\t\twe need frame %1 but highest we have is %2.")
681  .arg(desiredFrame).arg(last_frame));
682 
683  SyncPositionMap();
684 
685  last_frame = GetLastFrameInPosMap();
686 
687  if (desiredFrame > last_frame)
688  {
689  LOG(VB_PLAYBACK, LOG_INFO, LOC +
690  "ConditionallyUpdatePosMap: Still not "
691  "enough info in positionMap after sync, " +
692  QString("\n\t\t\twe need frame %1 but highest we have "
693  "is %2. Will attempt to seek frame-by-frame")
694  .arg(desiredFrame).arg(last_frame));
695  }
696 
697  return last_frame;
698 }
699 
709 bool DecoderBase::DoFastForward(long long desiredFrame, bool discardFrames)
710 {
711  LOG(VB_PLAYBACK, LOG_INFO, LOC +
712  QString("DoFastForward(%1 (%2), %3 discard frames)")
713  .arg(desiredFrame).arg(m_framesPlayed)
714  .arg((discardFrames) ? "do" : "don't"));
715 
716  if (!m_ringBuffer)
717  {
718  LOG(VB_GENERAL, LOG_ERR, LOC + "No ringBuffer yet, can't fast forward");
719  return false;
720  }
721 
722  if (m_ringBuffer->IsDVD() &&
724  m_ringBuffer->DVD()->TitleTimeLeft() < 5s)
725  {
726  return false;
727  }
728  // Rewind if we have already played the desiredFrame. The +1 is for
729  // MPEG4 NUV files, which need to decode an extra frame sometimes.
730  // This shouldn't effect how this works in general because this is
731  // only triggered on the first keyframe/frame skip when paused. At
732  // that point the decoding is more than one frame ahead of display.
733  if (desiredFrame+1 < m_framesPlayed)
734  return DoRewind(desiredFrame, discardFrames);
735  desiredFrame = std::max(desiredFrame, m_framesPlayed);
736 
737  ConditionallyUpdatePosMap(desiredFrame);
738 
739  // Fetch last keyframe in position map
740  long long last_frame = GetLastFrameInPosMap();
741 
742  // If the desiredFrame is past the end of the position map,
743  // do some frame-by-frame seeking until we get to it.
744  bool needflush = false;
745  if (desiredFrame > last_frame)
746  {
747  LOG(VB_GENERAL, LOG_NOTICE, LOC +
748  QString("DoFastForward(): desiredFrame(%1) > last_frame(%2)")
749  .arg(desiredFrame).arg(last_frame));
750 
751  if (desiredFrame - last_frame > 32)
752  {
753  LOG(VB_GENERAL, LOG_ERR, LOC + "DoFastForward(): "
754  "Desired frame is way past the end of the keyframe map!"
755  "\n\t\t\tSeeking to last keyframe instead.");
756  desiredFrame = last_frame;
757  }
758 
759  needflush = true;
760 
761  // Handle non-frame-by-frame seeking
762  DoFastForwardSeek(last_frame, needflush);
763 
764  m_exitAfterDecoded = true; // don't actualy get a frame
765  while ((desiredFrame > last_frame) && !m_atEof)
766  {
767  bool retry = false;
768  GetFrame(kDecodeNothing, retry); // don't need to return frame...
769  SyncPositionMap();
770  last_frame = GetLastFrameInPosMap();
771  }
772  m_exitAfterDecoded = false; // allow frames to be returned again
773 
774  if (m_atEof)
775  {
776  return false;
777  }
778  }
779 
780  {
781  QMutexLocker locker(&m_positionMapLock);
782  if (m_positionMap.empty())
783  {
784  return false;
785  }
786  }
787 
788  // Handle non-frame-by-frame seeking
789  DoFastForwardSeek(desiredFrame, needflush);
790 
791  // Do any Extra frame-by-frame seeking for exactseeks mode
792  // And flush pre-seek frame if we are allowed to and need to..
793  int normalframes = (uint64_t)(desiredFrame - (m_framesPlayed - 1)) > m_seekSnap
794  ? desiredFrame - m_framesPlayed : 0;
795  normalframes = std::max(normalframes, 0);
796  SeekReset(m_lastKey, normalframes, needflush, discardFrames);
797 
798  if (discardFrames || m_transcoding)
800 
801  return true;
802 }
803 
818 void DecoderBase::DoFastForwardSeek(long long desiredFrame, bool &needflush)
819 {
820  if (!m_ringBuffer)
821  {
822  LOG(VB_GENERAL, LOG_ERR, LOC +
823  "No ringBuffer yet, can't fast forward seek");
824  return;
825  }
826 
827  int pre_idx = 0;
828  int post_idx = 0;
829  FindPosition(desiredFrame, m_hasKeyFrameAdjustTable, pre_idx, post_idx);
830 
831  // if exactseeks, use keyframe <= desiredFrame
832 
833  PosMapEntry e {};
834  PosMapEntry e_pre {};
835  PosMapEntry e_post {};
836  {
837  QMutexLocker locker(&m_positionMapLock);
838  e_pre = m_positionMap[pre_idx];
839  e_post = m_positionMap[post_idx];
840  }
841  e = e_pre;
842  if (((uint64_t) (GetKey(e_post) - desiredFrame)) <= m_seekSnap &&
843  (m_framesPlayed - 1 >= GetKey(e_pre) ||
844  GetKey(e_post) - desiredFrame < desiredFrame - GetKey(e_pre)))
845  {
846  // Snap to the right if e_post is within snap distance and is
847  // a closer snap than e_pre. Take into account that if
848  // framesPlayed has already reached e_pre, we should only snap
849  // to the right.
850  e = e_post;
851  }
852  m_lastKey = GetKey(e);
853 
855  {
856  m_ringBuffer->Seek(e.pos, SEEK_SET);
857  needflush = true;
859  m_fpsSkip = 0;
861  }
862 }
863 
865 {
867 }
868 
870 {
871  ResetPosMap();
872  m_framesPlayed = 0;
873  m_framesRead = 0;
875 
876  m_waitingForChange = false;
877  m_justAfterChange = true;
878 
880 }
881 
882 void DecoderBase::SetReadAdjust(long long adjust)
883 {
884  m_readAdjust = adjust;
885 }
886 
888 {
889  m_waitingForChange = true;
890 }
891 
893 {
894  return m_waitingForChange;
895 }
896 
898 {
899  QMutexLocker locker(&m_trackLock);
900  return static_cast<uint>(m_tracks[Type].size());
901 }
902 
904 {
905  m_trackLock.lock();
906  m_decodeAllSubtitles = DecodeAll;
907  m_trackLock.unlock();
908 }
909 
910 QStringList DecoderBase::GetTracks(uint Type)
911 {
912  QMutexLocker locker(&m_trackLock);
913  QStringList list;
914  for (size_t i = 0; i < m_tracks[Type].size(); i++)
915  list += GetTrackDesc(Type, static_cast<uint>(i));
916  return list;
917 }
918 
920 {
921  QMutexLocker locker(&m_trackLock);
922  if (TrackNo >= m_tracks[Type].size())
923  return 0;
924  return static_cast<int>(m_tracks[Type][TrackNo].m_language_index);
925 }
926 
927 QString DecoderBase::GetTrackDesc(uint Type, uint TrackNo)
928 {
929  QMutexLocker locker(&m_trackLock);
930  if (TrackNo >= m_tracks[Type].size())
931  return "";
932 
933  QString type_msg = toString(static_cast<TrackType>(Type));
934  int lang = m_tracks[Type][TrackNo].m_language;
935  int hnum = static_cast<int>(TrackNo + 1);
936  if (kTrackTypeCC608 == Type)
937  hnum = m_tracks[Type][TrackNo].m_stream_id;
938 
939  if (!lang)
940  return type_msg + QString(" %1").arg(hnum);
941  QString lang_msg = iso639_key_toName(lang);
942  return type_msg + QString(" %1: %2").arg(hnum).arg(lang_msg);
943 }
944 
946 {
947  QMutexLocker locker(&m_trackLock);
948  return m_currentTrack[Type];
949 }
950 
951 int DecoderBase::SetTrack(uint Type, int TrackNo)
952 {
953  QMutexLocker locker(&m_trackLock);
954  if (TrackNo >= static_cast<int>(m_tracks[Type].size()))
955  return -1;
956 
957  m_currentTrack[Type] = std::max(-1, TrackNo);
958  if (m_currentTrack[Type] < 0)
959  {
960  m_selectedTrack[Type].m_av_stream_index = -1;
961  }
962  else
963  {
964  m_wantedTrack[Type] = m_tracks[Type][static_cast<size_t>(m_currentTrack[Type])];
965  m_selectedTrack[Type] = m_tracks[Type][static_cast<size_t>(m_currentTrack[Type])];
966  if (Type == kTrackTypeSubtitle)
967  {
968  // Rechoose the associated forced track, preferring the same language
969  int forcedTrackIndex = BestTrack(Type, true, m_selectedTrack[Type].m_language);
970  if (m_tracks[Type][forcedTrackIndex].m_forced)
971  m_selectedForcedTrack[Type] = m_tracks[Type][forcedTrackIndex];
972  }
973  }
974 
975  return m_currentTrack[Type];
976 }
977 
979 {
980  QMutexLocker locker(&m_trackLock);
981  if (TrackNo >= m_tracks[Type].size())
982  {
983  StreamInfo si;
984  return si;
985  }
986  return m_tracks[Type][TrackNo];
987 }
988 
989 int DecoderBase::ChangeTrack(uint Type, int Dir)
990 {
991  QMutexLocker locker(&m_trackLock);
992 
993  int next_track = -1;
994  int size = static_cast<int>(m_tracks[Type].size());
995  if (size)
996  {
997  if (Dir > 0)
998  next_track = (std::max(-1, m_currentTrack[Type]) + 1) % size;
999  else
1000  next_track = (std::max(+0, m_currentTrack[Type]) + size - 1) % size;
1001  }
1002  return SetTrack(Type, next_track);
1003 }
1004 
1006 {
1007  QMutexLocker locker(&m_trackLock);
1008 
1009  int next_track = -1;
1010  int size = static_cast<int>(m_tracks[Type].size());
1011  if (size)
1012  next_track = (std::max(0, m_currentTrack[Type]) + 1) % size;
1013  return next_track;
1014 }
1015 
1017 {
1018  QMutexLocker locker(&m_trackLock);
1019 
1020  if (std::any_of(m_tracks[Type].cbegin(), m_tracks[Type].cend(),
1021  [&](const StreamInfo& Si) { return Si.m_stream_id == Info.m_stream_id; } ))
1022  {
1023  return false;
1024  }
1025 
1026  m_tracks[Type].push_back(Info);
1027 
1028  if (m_parent)
1029  emit m_parent->SignalTracksChanged(Type);
1030 
1031  return true;
1032 }
1033 
1052 int DecoderBase::BestTrack(uint Type, bool forcedPreferred, int preferredLanguage)
1053 {
1054  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Trying to select track (w/lang & %1forced)")
1055  .arg(forcedPreferred ? "" : "!"));
1056  const int kForcedWeight = forcedPreferred ? (1 << 20) : -(1 << 20);
1057  const int kLanguageWeight = (1 << 10);
1058  const int kPositionWeight = (1 << 0);
1059  int bestScore = -1;
1060  int selTrack = -1;
1061  uint numStreams = static_cast<uint>(m_tracks[Type].size());
1062 
1063  for (uint i = 0; i < numStreams; i++)
1064  {
1065  bool forced = (Type == kTrackTypeSubtitle &&
1066  m_tracks[Type][i].m_forced);
1067  int position = static_cast<int>(numStreams) - static_cast<int>(i);
1068  int language = 0;
1069  if (preferredLanguage != 0 && m_tracks[Type][i].m_language == preferredLanguage)
1070  {
1071  language = static_cast<int>(m_languagePreference.size()) + 1;
1072  }
1073  for (uint j = 0; (language == 0) && (j < m_languagePreference.size()); ++j)
1074  {
1075  if (m_tracks[Type][i].m_language == m_languagePreference[j])
1076  language = static_cast<int>(m_languagePreference.size()) - static_cast<int>(j);
1077  }
1078  int score = (1 << 20) +
1079  (kForcedWeight * static_cast<int>(forced)) +
1080  (kLanguageWeight * language) +
1081  (kPositionWeight * position);
1082  if (score > bestScore)
1083  {
1084  bestScore = score;
1085  selTrack = static_cast<int>(i);
1086  }
1087  }
1088 
1089  return selTrack;
1090 }
1091 
1108 {
1109  QMutexLocker locker(&m_trackLock);
1110 
1111  uint numStreams = static_cast<uint>(m_tracks[Type].size());
1112 
1113  if ((m_currentTrack[Type] >= 0) && (m_currentTrack[Type] < static_cast<int>(numStreams)))
1114  return m_currentTrack[Type]; // track already selected
1115 
1116  if (!numStreams)
1117  {
1118  m_currentTrack[Type] = -1;
1119  m_selectedTrack[Type].m_av_stream_index = -1;
1120  return -1;
1121  }
1122 
1123  int selTrack = (1 == numStreams) ? 0 : -1;
1124 
1125  if ((selTrack < 0) && m_wantedTrack[Type].m_language>=-1)
1126  {
1127  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Trying to reselect track");
1128  // Try to reselect user selected track stream.
1129  // This should find the stream after a commercial
1130  // break and in some cases after a channel change.
1131  int wlang = m_wantedTrack[Type].m_language;
1132  uint windx = m_wantedTrack[Type].m_language_index;
1133  for (uint i = 0; i < numStreams; i++)
1134  {
1135  if (wlang == m_tracks[Type][i].m_language)
1136  {
1137  selTrack = static_cast<int>(i);
1138  if (windx == m_tracks[Type][i].m_language_index)
1139  break;
1140  }
1141  }
1142  }
1143 
1144  if (selTrack < 0)
1145  {
1146  // Find best track favoring forced.
1147  selTrack = BestTrack(Type, true);
1148 
1149  if (Type == kTrackTypeSubtitle)
1150  {
1151  if (m_tracks[Type][selTrack].m_forced)
1152  {
1153  // A forced AV Subtitle tracks is handled without the user
1154  // explicitly enabling subtitles. Try to find a good non-forced
1155  // track that can be swapped to in the case the user does
1156  // explicitly enable subtitles.
1157  int nonForcedTrack = BestTrack(Type, false);
1158 
1159  if (!m_tracks[Type][nonForcedTrack].m_forced)
1160  {
1161  m_selectedForcedTrack[Type] = m_tracks[Type][selTrack];
1162  selTrack = nonForcedTrack;
1163  }
1164  }
1165  }
1166  }
1167 
1168  int oldTrack = m_currentTrack[Type];
1169  m_currentTrack[Type] = selTrack;
1170  StreamInfo tmp = m_tracks[Type][static_cast<size_t>(m_currentTrack[Type])];
1171  m_selectedTrack[Type] = tmp;
1172 
1173  if (m_wantedTrack[Type].m_av_stream_index < 0)
1174  m_wantedTrack[Type] = tmp;
1175 
1176  int lang = m_tracks[Type][static_cast<size_t>(m_currentTrack[Type])].m_language;
1177  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Selected track #%1 (type %2) in the %3 language(%4)")
1178  .arg(m_currentTrack[Type]+1).arg(Type).arg(iso639_key_toName(lang)).arg(lang));
1179 
1180  if (m_parent && (oldTrack != m_currentTrack[Type]))
1181  emit m_parent->SignalTracksChanged(Type);
1182 
1183  return selTrack;
1184 }
1185 
1187 {
1188  for (uint i = 0; i < kTrackTypeCount; i++)
1189  AutoSelectTrack(i);
1190 }
1191 
1193 {
1194  QMutexLocker locker(&m_trackLock);
1195  std::fill(m_currentTrack.begin(), m_currentTrack.end(), -1);
1196 }
1197 
1199 {
1200  QString str = QObject::tr("Track");
1201 
1202  if (kTrackTypeAudio == type)
1203  str = QObject::tr("Audio track");
1204  else if (kTrackTypeVideo == type)
1205  str = QObject::tr("Video track");
1206  else if (kTrackTypeSubtitle == type)
1207  str = QObject::tr("Subtitle track");
1208  else if (kTrackTypeCC608 == type)
1209  str = QObject::tr("CC", "EIA-608 closed captions");
1210  else if (kTrackTypeCC708 == type)
1211  str = QObject::tr("ATSC CC", "EIA-708 closed captions");
1212  else if (kTrackTypeTeletextCaptions == type)
1213  str = QObject::tr("TT CC", "Teletext closed captions");
1214  else if (kTrackTypeTeletextMenu == type)
1215  str = QObject::tr("TT Menu", "Teletext Menu");
1216  else if (kTrackTypeRawText == type)
1217  str = QObject::tr("Text", "Text stream");
1218  else if (kTrackTypeTextSubtitle == type)
1219  str = QObject::tr("TXT File", "Text File");
1220  return str;
1221 }
1222 
1223 int to_track_type(const QString &str)
1224 {
1225  int ret = -1;
1226 
1227  if (str.startsWith("AUDIO"))
1228  ret = kTrackTypeAudio;
1229  else if (str.startsWith("VIDEO"))
1230  ret = kTrackTypeVideo;
1231  else if (str.startsWith("SUBTITLE"))
1232  ret = kTrackTypeSubtitle;
1233  else if (str.startsWith("CC608"))
1234  ret = kTrackTypeCC608;
1235  else if (str.startsWith("CC708"))
1236  ret = kTrackTypeCC708;
1237  else if (str.startsWith("TTC"))
1239  else if (str.startsWith("TTM"))
1240  ret = kTrackTypeTeletextMenu;
1241  else if (str.startsWith("TFL"))
1242  ret = kTrackTypeTextSubtitle;
1243  else if (str.startsWith("RAWTEXT"))
1244  ret = kTrackTypeRawText;
1245  return ret;
1246 }
1247 
1249 {
1250  QString str;
1251 
1252  switch (type)
1253  {
1255  str = QObject::tr("Audio Description",
1256  "On-screen events described for the visually impaired");
1257  break;
1258  case kAudioTypeCleanEffects :
1259  str = QObject::tr("Clean Effects",
1260  "No dialog, background audio only");
1261  break;
1263  str = QObject::tr("Hearing Impaired",
1264  "Clear dialog for the hearing impaired");
1265  break;
1266  case kAudioTypeSpokenSubs :
1267  str = QObject::tr("Spoken Subtitles",
1268  "Subtitles are read out for the visually impaired");
1269  break;
1270  case kAudioTypeCommentary :
1271  str = QObject::tr("Commentary", "Director/Cast commentary track");
1272  break;
1273  case kAudioTypeNormal :
1274  default:
1275  str = QObject::tr("Normal", "Ordinary audio track");
1276  break;
1277  }
1278 
1279  return str;
1280 }
1281 
1283 {
1285  return;
1286 
1287  m_playbackInfo->SaveTotalDuration(std::chrono::milliseconds{m_totalDuration.toFixed(1000)});
1288 }
1289 
1291 {
1292  if (!m_playbackInfo || !m_framesRead)
1293  return;
1294 
1296 }
1297 
1298 // Linearly interpolate the value for a given key in the map. If the
1299 // key is outside the range of keys in the map, linearly extrapolate
1300 // using the fallback ratio.
1302  long long key,
1303  float fallback_ratio)
1304 {
1305  uint64_t key1 = 0;
1306  uint64_t key2 = 0;
1307  uint64_t val1 = 0;
1308  uint64_t val2 = 0;
1309 
1310  frm_pos_map_t::const_iterator lower = map.lowerBound(key);
1311  // QMap::lowerBound() finds a key >= the given key. We want one
1312  // <= the given key, so back up one element upon > condition.
1313  if (lower != map.begin() && (lower == map.end() || lower.key() > key))
1314  --lower;
1315  if (lower == map.end() || lower.key() > key)
1316  {
1317  key1 = 0;
1318  val1 = 0;
1319  LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
1320  QString("TranslatePosition(key=%1): extrapolating to (0,0)")
1321  .arg(key));
1322  }
1323  else
1324  {
1325  key1 = lower.key();
1326  val1 = lower.value();
1327  }
1328  // Find the next key >= the given key. QMap::lowerBound() is
1329  // precisely correct in this case.
1330  frm_pos_map_t::const_iterator upper = map.lowerBound(key);
1331  if (upper == map.end())
1332  {
1333  // Extrapolate from (key1,val1) based on fallback_ratio
1334  key2 = key;
1335  val2 = llroundf(val1 + (fallback_ratio * (key2 - key1)));
1336  LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
1337  QString("TranslatePosition(key=%1, ratio=%2): "
1338  "extrapolating to (%3,%4)")
1339  .arg(key).arg(fallback_ratio).arg(key2).arg(val2));
1340  return val2;
1341  }
1342  key2 = upper.key();
1343  val2 = upper.value();
1344  if (key1 == key2) // this happens for an exact keyframe match
1345  return val2; // can also set key2 = key1 + 1 avoid dividing by zero
1346 
1347  return llround(val1 + ((double) (key - key1) * (val2 - val1) / (key2 - key1)));
1348 }
1349 
1350 // Convert from an absolute frame number (not cutlist adjusted) to its
1351 // cutlist-adjusted position in milliseconds.
1352 std::chrono::milliseconds DecoderBase::TranslatePositionFrameToMs(long long position,
1353  float fallback_framerate,
1354  const frm_dir_map_t &cutlist)
1355 {
1356  QMutexLocker locker(&m_positionMapLock);
1357  // Accurate calculation of duration requires an up-to-date
1358  // duration map. However, the last frame (total duration) will
1359  // almost always appear to be past the end of the duration map, so
1360  // we limit duration map syncing to once every 3 seconds (a
1361  // somewhat arbitrary value).
1362  if (!m_frameToDurMap.empty())
1363  {
1364  frm_pos_map_t::const_iterator it = m_frameToDurMap.cend();
1365  --it;
1366  if (position > it.key())
1367  {
1368  if (!m_lastPositionMapUpdate.isValid() ||
1369  (QDateTime::currentDateTime() >
1370  m_lastPositionMapUpdate.addSecs(3)))
1371  SyncPositionMap();
1372  }
1373  }
1374  return std::chrono::milliseconds(TranslatePositionAbsToRel(cutlist, position, m_frameToDurMap,
1375  1000 / fallback_framerate));
1376 }
1377 
1378 // Convert from a cutlist-adjusted position in milliseconds to its
1379 // absolute frame number (not cutlist-adjusted).
1380 uint64_t DecoderBase::TranslatePositionMsToFrame(std::chrono::milliseconds dur_ms,
1381  float fallback_framerate,
1382  const frm_dir_map_t &cutlist)
1383 {
1384  QMutexLocker locker(&m_positionMapLock);
1385  // Convert relative position in milliseconds (cutlist-adjusted) to
1386  // its absolute position in milliseconds (not cutlist-adjusted).
1387  uint64_t ms = TranslatePositionRelToAbs(cutlist, dur_ms.count(), m_frameToDurMap,
1388  1000 / fallback_framerate);
1389  // Convert absolute position in milliseconds to its absolute frame
1390  // number.
1391  return TranslatePosition(m_durToFrameMap, ms, fallback_framerate / 1000);
1392 }
1393 
1394 // Convert from an "absolute" (not cutlist-adjusted) value to its
1395 // "relative" (cutlist-adjusted) mapped value. Usually the position
1396 // argument is a frame number, the map argument maps frames to
1397 // milliseconds, the fallback_ratio is 1000/framerate_fps, and the
1398 // return value is in milliseconds.
1399 //
1400 // If the map and fallback_ratio arguments are omitted, it simply
1401 // converts from an absolute frame number to a relative
1402 // (cutlist-adjusted) frame number.
1403 uint64_t
1405  uint64_t absPosition, // frames
1406  const frm_pos_map_t &map, // frame->ms
1407  float fallback_ratio)
1408 {
1409  uint64_t subtraction = 0;
1410  uint64_t startOfCutRegion = 0;
1411  bool withinCut = false;
1412  bool first = true;
1413  for (frm_dir_map_t::const_iterator i = deleteMap.begin();
1414  i != deleteMap.end(); ++i)
1415  {
1416  if (first)
1417  withinCut = (i.value() == MARK_CUT_END);
1418  first = false;
1419  if (i.key() > absPosition)
1420  break;
1421  uint64_t mappedKey = TranslatePosition(map, i.key(), fallback_ratio);
1422  if (i.value() == MARK_CUT_START && !withinCut)
1423  {
1424  withinCut = true;
1425  startOfCutRegion = mappedKey;
1426  }
1427  else if (i.value() == MARK_CUT_END && withinCut)
1428  {
1429  withinCut = false;
1430  subtraction += (mappedKey - startOfCutRegion);
1431  }
1432  }
1433  uint64_t mappedPos = TranslatePosition(map, absPosition, fallback_ratio);
1434  if (withinCut)
1435  subtraction += (mappedPos - startOfCutRegion);
1436  return mappedPos - subtraction;
1437 }
1438 
1439 // Convert from a "relative" (cutlist-adjusted) value to its
1440 // "absolute" (not cutlist-adjusted) mapped value. Usually the
1441 // position argument is in milliseconds, the map argument maps frames
1442 // to milliseconds, the fallback_ratio is 1000/framerate_fps, and the
1443 // return value is also in milliseconds. Upon return, if necessary,
1444 // the result may need a separate, non-cutlist adjusted conversion
1445 // from milliseconds to frame number, using the inverse
1446 // millisecond-to-frame map and the inverse fallback_ratio; see for
1447 // example TranslatePositionMsToFrame().
1448 //
1449 // If the map and fallback_ratio arguments are omitted, it simply
1450 // converts from a relatve (cutlist-adjusted) frame number to an
1451 // absolute frame number.
1452 uint64_t
1454  uint64_t relPosition, // ms
1455  const frm_pos_map_t &map, // frame->ms
1456  float fallback_ratio)
1457 {
1458  uint64_t addition = 0;
1459  uint64_t startOfCutRegion = 0;
1460  bool withinCut = false;
1461  bool first = true;
1462  for (frm_dir_map_t::const_iterator i = deleteMap.begin();
1463  i != deleteMap.end(); ++i)
1464  {
1465  if (first)
1466  withinCut = (i.value() == MARK_CUT_END);
1467  first = false;
1468  uint64_t mappedKey = TranslatePosition(map, i.key(), fallback_ratio);
1469  if (i.value() == MARK_CUT_START && !withinCut)
1470  {
1471  withinCut = true;
1472  startOfCutRegion = mappedKey;
1473  if (relPosition + addition <= startOfCutRegion)
1474  break;
1475  }
1476  else if (i.value() == MARK_CUT_END && withinCut)
1477  {
1478  withinCut = false;
1479  addition += (mappedKey - startOfCutRegion);
1480  }
1481  }
1482  return relPosition + addition;
1483 }
1484 
1489 AVPixelFormat DecoderBase::GetBestVideoFormat(AVPixelFormat* Formats, const VideoFrameTypes* RenderFormats)
1490 {
1491  for (AVPixelFormat *format = Formats; *format != AV_PIX_FMT_NONE; format++)
1492  {
1493  for (auto fmt : *RenderFormats)
1494  if (MythAVUtil::FrameTypeToPixelFormat(fmt) == *format)
1495  return *format;
1496  }
1497  return AV_PIX_FMT_NONE;
1498 }
1499 
1500 /* vim: set expandtab tabstop=4 shiftwidth=4: */
MythMediaBuffer::BD
const MythBDBuffer * BD(void) const
Definition: mythmediabuffer.cpp:1855
DecoderBase::DoFastForward
virtual bool DoFastForward(long long desiredFrame, bool discardFrames=true)
Skips ahead or rewinds to desiredFrame.
Definition: decoderbase.cpp:709
MythBDBuffer::GetFrameRate
double GetFrameRate(void)
Definition: mythbdbuffer.cpp:871
secondsFromFloat
std::enable_if_t< std::is_floating_point_v< T >, std::chrono::seconds > secondsFromFloat(T value)
Helper function for convert a floating point number to a duration.
Definition: mythchrono.h:80
MythTimer::elapsed
std::chrono::milliseconds elapsed(void)
Returns milliseconds elapsed since last start() or restart()
Definition: mythtimer.cpp:91
kTrackTypeCC708
@ kTrackTypeCC708
Definition: decoderbase.h:34
DecoderBase::SetTrack
virtual int SetTrack(uint Type, int TrackNo)
Definition: decoderbase.cpp:951
DecoderBase::m_readAdjust
long long m_readAdjust
Definition: decoderbase.h:334
DecoderBase::GetTrack
int GetTrack(uint Type)
Definition: decoderbase.cpp:945
DecoderBase::NextTrack
int NextTrack(uint Type)
Definition: decoderbase.cpp:1005
MythDVDBuffer::TitleTimeLeft
std::chrono::seconds TitleTimeLeft(void) const
returns seconds left in the title
Definition: mythdvdbuffer.cpp:1991
MARK_KEYFRAME
@ MARK_KEYFRAME
Definition: programtypes.h:61
kAudioTypeNormal
@ kAudioTypeNormal
Definition: decoderbase.h:58
DecoderBase::PosMapEntry::adjFrame
long long adjFrame
Definition: decoderbase.h:274
MythPlayer::SetFileLength
void SetFileLength(std::chrono::seconds total, int frames)
Definition: mythplayer.cpp:387
DecoderBase::m_seekSnap
uint64_t m_seekSnap
Definition: decoderbase.h:323
DecoderBase::m_selectedTrack
std::array< StreamInfo, kTrackTypeCount > m_selectedTrack
Definition: decoderbase.h:344
DecoderBase::m_ringBuffer
MythMediaBuffer * m_ringBuffer
Definition: decoderbase.h:282
DecoderBase::m_renderFormats
const VideoFrameTypes * m_renderFormats
Definition: decoderbase.h:351
DecoderBase::PosMapEntry
Definition: decoderbase.h:271
kTrackTypeSubtitle
@ kTrackTypeSubtitle
Definition: decoderbase.h:32
ProgramInfo::QueryPositionMap
void QueryPositionMap(frm_pos_map_t &posMap, MarkTypes type) const
Definition: programinfo.cpp:3784
MARK_GOP_START
@ MARK_GOP_START
Definition: programtypes.h:60
DecoderBase::m_fps
double m_fps
Definition: decoderbase.h:284
MythTimer
A QElapsedTimer based timer to replace use of QTime as a timer.
Definition: mythtimer.h:13
DecoderBase::m_indexOffset
long long m_indexOffset
Definition: decoderbase.h:298
DecoderBase::m_lastPositionMapUpdate
QDateTime m_lastPositionMapUpdate
Definition: decoderbase.h:321
to_track_type
int to_track_type(const QString &str)
Definition: decoderbase.cpp:1223
MythBDBuffer::GetTotalReadPosition
uint64_t GetTotalReadPosition(void)
Definition: mythbdbuffer.cpp:801
MythMediaBuffer::Seek
long long Seek(long long Position, int Whence, bool HasLock=false)
Definition: mythmediabuffer.cpp:479
ProgramInfo::SavePositionMapDelta
void SavePositionMapDelta(frm_pos_map_t &posMap, MarkTypes type) const
Definition: programinfo.cpp:4012
DecoderBase::m_hasKeyFrameAdjustTable
bool m_hasKeyFrameAdjustTable
Definition: decoderbase.h:328
ProgramInfo::SaveTotalFrames
void SaveTotalFrames(int64_t frames)
Store the Total Frames at frame 0 in the recordedmarkup table.
Definition: programinfo.cpp:4422
DecoderBase::ConditionallyUpdatePosMap
long long ConditionallyUpdatePosMap(long long desiredFrame)
Definition: decoderbase.cpp:666
DecoderBase::AutoSelectTrack
virtual int AutoSelectTrack(uint Type)
Select best track.
Definition: decoderbase.cpp:1107
DecoderBase::m_atEof
EofState m_atEof
Definition: decoderbase.h:302
DecoderBase::m_parent
MythPlayer * m_parent
Definition: decoderbase.h:279
DecoderBase::SavePositionMapDelta
uint64_t SavePositionMapDelta(long long first_frame, long long last_frame)
Definition: decoderbase.cpp:499
MarkTypes
MarkTypes
Definition: programtypes.h:46
StreamInfo::m_stream_id
int m_stream_id
Definition: decoderbase.h:105
DecoderBase::DecoderBase
DecoderBase(MythPlayer *parent, const ProgramInfo &pginfo)
Definition: decoderbase.cpp:17
mythdvdbuffer.h
kDecodeNothing
@ kDecodeNothing
Definition: decoderbase.h:50
DecoderBase::m_livetv
bool m_livetv
Definition: decoderbase.h:325
frm_dir_map_t
QMap< uint64_t, MarkTypes > frm_dir_map_t
Frame # -> Mark map.
Definition: programtypes.h:117
DecoderBase::ResetTracks
void ResetTracks(void)
Definition: decoderbase.cpp:1192
MythMediaBuffer::IsDVD
bool IsDVD(void) const
Definition: mythmediabuffer.cpp:1840
MythTimer::start
void start(void)
starts measuring elapsed time.
Definition: mythtimer.cpp:47
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
DecoderBase::ChangeTrack
int ChangeTrack(uint Type, int Dir)
Definition: decoderbase.cpp:989
DecoderBase::m_trackLock
QRecursiveMutex m_trackLock
Definition: decoderbase.h:339
mythplayer.h
DecoderBase::m_positionMapType
MarkTypes m_positionMapType
Definition: decoderbase.h:315
MythPlayer
Definition: mythplayer.h:83
MythMediaBuffer::IsBD
bool IsBD(void) const
Definition: mythmediabuffer.cpp:1845
DecoderBase::m_posmapStarted
bool m_posmapStarted
Definition: decoderbase.h:314
kAudioTypeCommentary
@ kAudioTypeCommentary
Definition: decoderbase.h:63
MythDVDBuffer::GetFrameRate
double GetFrameRate(void)
used by DecoderBase for the total frame number calculation for position map support and ffw/rew.
Definition: mythdvdbuffer.cpp:1953
DecoderBase::m_exitAfterDecoded
bool m_exitAfterDecoded
Definition: decoderbase.h:309
iso639_key_toName
QString iso639_key_toName(int iso639_2)
Converts a canonical key to language name in English.
Definition: iso639.cpp:109
iso639_get_language_key_list
std::vector< int > iso639_get_language_key_list(void)
Definition: iso639.cpp:56
DecoderBase::m_frameToDurMap
frm_pos_map_t m_frameToDurMap
Definition: decoderbase.h:319
DecoderBase::GetWaitForChange
bool GetWaitForChange(void) const
Definition: decoderbase.cpp:892
DecoderBase::SetWaitForChange
void SetWaitForChange(void)
Definition: decoderbase.cpp:887
DecoderBase::m_currentTrack
std::array< int, kTrackTypeCount > m_currentTrack
Definition: decoderbase.h:341
MythDVDBuffer::GetTotalTimeOfTitle
std::chrono::seconds GetTotalTimeOfTitle(void) const
get the total time of the title in seconds 90000 ticks = 1 sec
Definition: mythdvdbuffer.cpp:1157
tmp
static guint32 * tmp
Definition: goom_core.cpp:26
DecoderBase::m_dontSyncPositionMap
bool m_dontSyncPositionMap
Definition: decoderbase.h:324
DecoderBase::TranslatePositionMsToFrame
uint64_t TranslatePositionMsToFrame(std::chrono::milliseconds dur_ms, float fallback_framerate, const frm_dir_map_t &cutlist)
Definition: decoderbase.cpp:1380
DecoderBase::m_tracks
std::array< sinfo_vec_t, kTrackTypeCount > m_tracks
Definition: decoderbase.h:342
toString
QString toString(TrackType type)
Definition: decoderbase.cpp:1198
DecoderBase::GetTrackDesc
virtual QString GetTrackDesc(uint Type, uint TrackNo)
Definition: decoderbase.cpp:927
DecoderBase::SaveTotalDuration
void SaveTotalDuration(void)
Definition: decoderbase.cpp:1282
DecoderBase::GetTrackCount
virtual uint GetTrackCount(uint Type)
Definition: decoderbase.cpp:897
DecoderBase::FindPosition
virtual bool FindPosition(long long desired_value, bool search_adjusted, int &lower_bound, int &upper_bound)
Definition: decoderbase.cpp:419
kEofStateNone
@ kEofStateNone
Definition: decoderbase.h:70
DecoderBase::TranslatePositionAbsToRel
static uint64_t TranslatePositionAbsToRel(const frm_dir_map_t &deleteMap, uint64_t absPosition, const frm_pos_map_t &map=frm_pos_map_t(), float fallback_ratio=1.0)
Definition: decoderbase.cpp:1404
programinfo.h
DecoderBase::m_keyframeDist
int m_keyframeDist
Definition: decoderbase.h:296
mythlogging.h
DecoderBase::GetTrackInfo
StreamInfo GetTrackInfo(uint Type, uint TrackNo)
Definition: decoderbase.cpp:978
StreamInfo
Definition: decoderbase.h:75
DecoderBase::m_languagePreference
std::vector< int > m_languagePreference
language preferences for auto-selection of streams
Definition: decoderbase.h:348
DecoderBase::DoRewindSeek
virtual bool DoRewindSeek(long long desiredFrame)
Definition: decoderbase.cpp:588
MythMediaBuffer::IsInDiscMenuOrStillFrame
virtual bool IsInDiscMenuOrStillFrame(void) const
Definition: mythmediabuffer.h:142
DecoderBase::m_totalDuration
MythAVRational m_totalDuration
Definition: decoderbase.h:295
DecoderBase::~DecoderBase
virtual ~DecoderBase()
Definition: decoderbase.cpp:30
VideoFrameTypes
std::vector< VideoFrameType > VideoFrameTypes
Definition: mythframe.h:82
kTrackTypeTextSubtitle
@ kTrackTypeTextSubtitle
Definition: decoderbase.h:43
DecoderBase::TranslatePositionRelToAbs
static uint64_t TranslatePositionRelToAbs(const frm_dir_map_t &deleteMap, uint64_t relPosition, const frm_pos_map_t &map=frm_pos_map_t(), float fallback_ratio=1.0)
Definition: decoderbase.cpp:1453
DecoderBase::m_positionMap
std::vector< PosMapEntry > m_positionMap
Definition: decoderbase.h:318
LOC
#define LOC
Definition: decoderbase.cpp:15
AudioTrackType
AudioTrackType
Definition: decoderbase.h:56
kTrackTypeTeletextMenu
@ kTrackTypeTeletextMenu
Definition: decoderbase.h:36
ProgramInfo::SaveTotalDuration
void SaveTotalDuration(std::chrono::milliseconds duration)
Store the Total Duration at frame 0 in the recordedmarkup table.
Definition: programinfo.cpp:4406
DecoderBase::TranslatePositionFrameToMs
std::chrono::milliseconds TranslatePositionFrameToMs(long long position, float fallback_framerate, const frm_dir_map_t &cutlist)
Definition: decoderbase.cpp:1352
MARK_CUT_START
@ MARK_CUT_START
Definition: programtypes.h:55
kTrackTypeCC608
@ kTrackTypeCC608
Definition: decoderbase.h:33
hardwareprofile.smolt.long
long
Definition: smolt.py:75
DecoderBase::m_durToFrameMap
frm_pos_map_t m_durToFrameMap
Definition: decoderbase.h:320
DecoderBase::ResetPosMap
virtual void ResetPosMap(void)
Definition: decoderbase.cpp:646
DecoderBase::SetReadAdjust
void SetReadAdjust(long long adjust)
Definition: decoderbase.cpp:882
DecoderBase::m_playbackInfo
ProgramInfo * m_playbackInfo
Definition: decoderbase.h:280
MythPlayer::PosMapFromEnc
bool PosMapFromEnc(uint64_t start, frm_pos_map_t &posMap, frm_pos_map_t &durMap)
Definition: mythplayer.cpp:1898
DecoderBase::PosMapEntry::index
long long index
Definition: decoderbase.h:273
DecoderBase::GetPositionMapSize
unsigned long GetPositionMapSize(void) const
Definition: decoderbase.cpp:293
MythAVRational::isNonzero
bool isNonzero() const
Definition: mythavrational.h:42
DecoderBase::AutoSelectTracks
void AutoSelectTracks(void)
Definition: decoderbase.cpp:1186
kAudioTypeCleanEffects
@ kAudioTypeCleanEffects
Definition: decoderbase.h:60
DecoderBase::FileChanged
void FileChanged(void)
Definition: decoderbase.cpp:869
DecoderBase::m_wantedTrack
std::array< StreamInfo, kTrackTypeCount > m_wantedTrack
Definition: decoderbase.h:343
DecoderBase::m_transcoding
bool m_transcoding
Definition: decoderbase.h:310
DecoderBase::m_waitingForChange
bool m_waitingForChange
Definition: decoderbase.h:332
kAudioTypeHearingImpaired
@ kAudioTypeHearingImpaired
Definition: decoderbase.h:61
MARK_UNSET
@ MARK_UNSET
Definition: programtypes.h:49
DecoderBase::m_justAfterChange
bool m_justAfterChange
Definition: decoderbase.h:333
DecoderBase::SyncPositionMap
virtual bool SyncPositionMap(void)
Updates the position map used for skipping frames.
Definition: decoderbase.cpp:321
MARK_GOP_BYFRAME
@ MARK_GOP_BYFRAME
Definition: programtypes.h:63
frm_pos_map_t
QMap< long long, long long > frm_pos_map_t
Frame # -> File offset map.
Definition: programtypes.h:44
DecoderBase::SetProgramInfo
void SetProgramInfo(const ProgramInfo &pginfo)
Definition: decoderbase.cpp:41
MythAVRational::isValid
bool isValid() const
Definition: mythavrational.h:44
DecoderBase::GetKey
long long GetKey(const PosMapEntry &entry) const
Definition: decoderbase.cpp:581
DecoderBase::PosMapFromEnc
virtual bool PosMapFromEnc(void)
Queries encoder for position map data that has not been committed to the DB yet.
Definition: decoderbase.cpp:222
DecoderBase::SetWatchingRecording
virtual void SetWatchingRecording(bool mode)
Definition: decoderbase.cpp:81
DecoderBase::m_selectedForcedTrack
std::array< StreamInfo, kTrackTypeCount > m_selectedForcedTrack
Definition: decoderbase.h:345
DecoderBase::GetFrame
virtual bool GetFrame(DecodeType Type, bool &Retry)=0
Demux, preprocess and possibly decode a frame of video/audio.
DecoderBase::DoFastForwardSeek
virtual void DoFastForwardSeek(long long desiredFrame, bool &needflush)
Seeks to the keyframe just before the desiredFrame if exact seeks is enabled, or the frame just after...
Definition: decoderbase.cpp:818
MARK_DURATION_MS
@ MARK_DURATION_MS
Definition: programtypes.h:73
mythbdbuffer.h
MythPlayer::SetKeyframeDistance
void SetKeyframeDistance(int keyframedistance)
Definition: mythplayer.cpp:319
kTrackTypeCount
@ kTrackTypeCount
Definition: decoderbase.h:39
DecoderBase::UpdateFramesPlayed
virtual void UpdateFramesPlayed(void)
Definition: decoderbase.cpp:864
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:67
DecoderBase::SetDecodeAllSubtitles
void SetDecodeAllSubtitles(bool DecodeAll)
Definition: decoderbase.cpp:903
DecoderBase::m_framesPlayed
long long m_framesPlayed
Definition: decoderbase.h:292
MARK_CUT_END
@ MARK_CUT_END
Definition: programtypes.h:54
MythPlayer::SetFramesPlayed
void SetFramesPlayed(uint64_t played)
Definition: mythplayer.cpp:562
MythPlayer::FileChangedCallback
void FileChangedCallback()
Definition: mythplayer.cpp:938
DecoderBase::m_positionMapLock
QRecursiveMutex m_positionMapLock
Definition: decoderbase.h:317
DecoderBase::SetRenderFormats
void SetRenderFormats(const VideoFrameTypes *RenderFormats)
Definition: decoderbase.cpp:35
kTrackTypeVideo
@ kTrackTypeVideo
Definition: decoderbase.h:31
DecoderBase::m_decodeAllSubtitles
bool m_decodeAllSubtitles
Definition: decoderbase.h:340
DecoderBase::m_watchingRecording
bool m_watchingRecording
Definition: decoderbase.h:326
MythAVUtil::FrameTypeToPixelFormat
static AVPixelFormat FrameTypeToPixelFormat(VideoFrameType Type)
Definition: mythavutil.cpp:28
DecoderBase::BestTrack
int BestTrack(uint Type, bool forcedPreferred, int preferredLanguage=0)
Determine the best track according to weights.
Definition: decoderbase.cpp:1052
kTrackTypeTeletextCaptions
@ kTrackTypeTeletextCaptions
Definition: decoderbase.h:35
MythMediaBuffer::IsDisc
bool IsDisc(void) const
Definition: mythmediabuffer.cpp:1835
DecoderBase::TranslatePosition
static uint64_t TranslatePosition(const frm_pos_map_t &map, long long key, float fallback_ratio)
Definition: decoderbase.cpp:1301
decoderbase.h
DecoderBase::PosMapFromDb
virtual bool PosMapFromDb(void)
Definition: decoderbase.cpp:94
DecoderBase::GetBestVideoFormat
static AVPixelFormat GetBestVideoFormat(AVPixelFormat *Formats, const VideoFrameTypes *RenderFormats)
Find a suitable frame format that is mutually acceptable to the decoder and render device.
Definition: decoderbase.cpp:1489
iso639.h
ISO 639-1 and ISO 639-2 support functions.
kTrackTypeAudio
@ kTrackTypeAudio
Definition: decoderbase.h:30
MythAVRational
C++ wrapper for FFmpeg libavutil AVRational.
Definition: mythavrational.h:14
mythcodeccontext.h
DecoderBase::m_lastKey
long long m_lastKey
Definition: decoderbase.h:297
kTrackTypeRawText
@ kTrackTypeRawText
Definition: decoderbase.h:37
MythDVDBuffer::GetTotalReadPosition
long long GetTotalReadPosition(void) const
Definition: mythdvdbuffer.cpp:454
MythMediaBuffer::DVD
const MythDVDBuffer * DVD(void) const
Definition: mythmediabuffer.cpp:1850
kAudioTypeSpokenSubs
@ kAudioTypeSpokenSubs
Definition: decoderbase.h:62
MythPlayer::SignalTracksChanged
void SignalTracksChanged(uint Type)
DecoderBase::m_framesRead
long long m_framesRead
Definition: decoderbase.h:293
TrackType
TrackType
Track types.
Definition: decoderbase.h:27
DecoderBase::Reset
virtual void Reset(bool reset_video_data, bool seek_reset, bool reset_file)
Definition: decoderbase.cpp:47
kAudioTypeAudioDescription
@ kAudioTypeAudioDescription
Definition: decoderbase.h:59
DecoderBase::GetTracks
virtual QStringList GetTracks(uint Type)
Definition: decoderbase.cpp:910
DecoderBase::m_fpsSkip
int m_fpsSkip
Definition: decoderbase.h:286
DecoderBase::GetLastFrameInPosMap
long long GetLastFrameInPosMap(void) const
Definition: decoderbase.cpp:655
DecoderBase::SetEofState
virtual void SetEofState(EofState eof)
Definition: decoderbase.h:132
DecoderBase::InsertTrack
virtual bool InsertTrack(uint Type, const StreamInfo &Info)
Definition: decoderbase.cpp:1016
MythBDBuffer::GetTotalTimeOfTitle
std::chrono::seconds GetTotalTimeOfTitle(void) const
Definition: mythbdbuffer.cpp:627
DecoderBase::SeekReset
virtual void SeekReset(long long newkey, uint skipFrames, bool doFlush, bool discardFrames)
Definition: decoderbase.cpp:74
DecoderBase::DoRewind
virtual bool DoRewind(long long desiredFrame, bool discardFrames=true)
Definition: decoderbase.cpp:554
MythAVRational::toFixed
long long toFixed(long long base) const
Convert the rational number to fixed point.
Definition: mythavrational.h:32
DecoderBase::m_recordingHasPositionMap
bool m_recordingHasPositionMap
Definition: decoderbase.h:313
DecoderBase::GetTrackLanguageIndex
virtual int GetTrackLanguageIndex(uint Type, uint TrackNo)
Definition: decoderbase.cpp:919
uint
unsigned int uint
Definition: freesurround.h:24
DecoderBase::SaveTotalFrames
void SaveTotalFrames(void)
Definition: decoderbase.cpp:1290
DecoderBase::m_frameCounter
uint64_t m_frameCounter
Definition: decoderbase.h:294