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