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 (frm_pos_map_t::const_iterator it = posMap.begin();
178  it != posMap.end(); ++it)
179  {
180  PosMapEntry e = {it.key(), it.key() * m_keyframeDist, *it};
181  m_positionMap.push_back(e);
182  }
183 
184  if (!m_positionMap.empty() && !(m_ringBuffer && m_ringBuffer->IsDisc()))
185  m_indexOffset = m_positionMap[0].index;
186 
187  if (!m_positionMap.empty())
188  {
189  LOG(VB_PLAYBACK, LOG_INFO, LOC +
190  QString("Position map filled from DB to: %1")
191  .arg(m_positionMap.back().index));
192  }
193 
194  uint64_t last = 0;
195  for (frm_pos_map_t::const_iterator it = durMap.begin();
196  it != durMap.end(); ++it)
197  {
198  m_frameToDurMap[it.key()] = it.value();
199  m_durToFrameMap[it.value()] = it.key();
200  last = it.key();
201  }
202 
203  if (!m_durToFrameMap.empty())
204  {
205  LOG(VB_PLAYBACK, LOG_INFO, LOC +
206  QString("Duration map filled from DB to: %1").arg(last));
207  }
208 
209  return true;
210 }
211 
221 {
222  if (!m_parent || m_keyframeDist < 1)
223  return false;
224 
225  unsigned long long start = 0;
226  {
227  QMutexLocker locker(&m_positionMapLock);
228  if (!m_positionMap.empty())
229  start = m_positionMap.back().index + 1;
230  }
231 
232  frm_pos_map_t posMap;
233  frm_pos_map_t durMap;
234  if (!m_parent->PosMapFromEnc(start, posMap, durMap))
235  return false;
236 
237  QMutexLocker locker(&m_positionMapLock);
238 
239  // append this new position map to class's
240  m_positionMap.reserve(m_positionMap.size() + posMap.size());
241 
242  long long last_index = 0;
243  if (!m_positionMap.empty())
244  last_index = m_positionMap.back().index;
245  for (frm_pos_map_t::const_iterator it = posMap.begin();
246  it != posMap.end(); ++it)
247  {
248  if (it.key() <= last_index)
249  continue;
250 
251  PosMapEntry e = {it.key(), it.key() * m_keyframeDist, *it};
252  m_positionMap.push_back(e);
253  }
254 
255  if (!m_positionMap.empty() && !(m_ringBuffer && m_ringBuffer->IsDisc()))
256  m_indexOffset = m_positionMap[0].index;
257 
258  if (!m_positionMap.empty())
259  {
260  LOG(VB_PLAYBACK, LOG_INFO, LOC +
261  QString("Position map filled from Encoder to: %1")
262  .arg(m_positionMap.back().index));
263  }
264 
265  bool isEmpty = m_frameToDurMap.empty();
266  if (!isEmpty)
267  {
268  frm_pos_map_t::const_iterator it = m_frameToDurMap.end();
269  --it;
270  last_index = it.key();
271  }
272  for (frm_pos_map_t::const_iterator it = durMap.begin();
273  it != durMap.end(); ++it)
274  {
275  if (!isEmpty && it.key() <= last_index)
276  continue; // we released the m_positionMapLock for a few ms...
277  m_frameToDurMap[it.key()] = it.value();
278  m_durToFrameMap[it.value()] = it.key();
279  }
280 
281  if (!m_frameToDurMap.empty())
282  {
283  frm_pos_map_t::const_iterator it = m_frameToDurMap.end();
284  --it;
285  LOG(VB_PLAYBACK, LOG_INFO, LOC +
286  QString("Duration map filled from Encoder to: %1").arg(it.key()));
287  }
288 
289  return true;
290 }
291 
292 unsigned long DecoderBase::GetPositionMapSize(void) const
293 {
294  QMutexLocker locker(&m_positionMapLock);
295  return m_positionMap.size();
296 }
297 
321 {
322  LOG(VB_PLAYBACK, LOG_INFO, LOC +
323  QString("Resyncing position map. posmapStarted = %1"
324  " livetv(%2) watchingRec(%3)")
326 
328  return false;
329 
330  unsigned long old_posmap_size = GetPositionMapSize();
331  unsigned long new_posmap_size = old_posmap_size;
332 
334  {
335  if (!m_posmapStarted)
336  {
337  // starting up -- try first from database
338  PosMapFromDb();
339  new_posmap_size = GetPositionMapSize();
340  LOG(VB_PLAYBACK, LOG_INFO, LOC +
341  QString("SyncPositionMap watchingrecording, from DB: "
342  "%1 entries") .arg(new_posmap_size));
343  }
344  // always try to get more from encoder
345  if (!PosMapFromEnc())
346  {
347  LOG(VB_PLAYBACK, LOG_INFO, LOC +
348  QString("SyncPositionMap watchingrecording no entries "
349  "from encoder, try DB"));
350  PosMapFromDb(); // try again from db
351  }
352 
353  new_posmap_size = GetPositionMapSize();
354  LOG(VB_PLAYBACK, LOG_INFO, LOC +
355  QString("SyncPositionMap watchingrecording total: %1 entries")
356  .arg(new_posmap_size));
357  }
358  else
359  {
360  // watching prerecorded ... just get from db
361  if (!m_posmapStarted)
362  {
363  PosMapFromDb();
364 
365  new_posmap_size = GetPositionMapSize();
366  LOG(VB_PLAYBACK, LOG_INFO, LOC +
367  QString("SyncPositionMap prerecorded, from DB: %1 entries")
368  .arg(new_posmap_size));
369  }
370  }
371 
372  bool ret_val = new_posmap_size > old_posmap_size;
373 
374  if (ret_val && m_keyframeDist > 0)
375  {
376  long long totframes = 0;
377  int length = 0;
378 
379  if (m_ringBuffer && m_ringBuffer->IsDVD())
380  {
381  length = m_ringBuffer->DVD()->GetTotalTimeOfTitle();
382  QMutexLocker locker(&m_positionMapLock);
383  totframes = m_positionMap.back().index;
384  }
385  else if (m_ringBuffer && m_ringBuffer->IsBD())
386  {
387  length = m_ringBuffer->BD()->GetTotalTimeOfTitle();
388  QMutexLocker locker(&m_positionMapLock);
389  totframes = m_positionMap.back().index;
390  }
391  else
392  {
393  QMutexLocker locker(&m_positionMapLock);
394  totframes = m_positionMap.back().index * m_keyframeDist;
395  if (m_fps != 0.0)
396  length = (int)((totframes * 1.0) / m_fps);
397  }
398 
399  m_parent->SetFileLength(length, totframes);
401  m_posmapStarted = true;
402 
403  LOG(VB_PLAYBACK, LOG_INFO, LOC +
404  QString("SyncPositionMap, new totframes: %1, new length: %2, "
405  "posMap size: %3")
406  .arg(totframes).arg(length).arg(new_posmap_size));
407  }
408  m_recordingHasPositionMap |= (0 != new_posmap_size);
409  {
410  QMutexLocker locker(&m_positionMapLock);
411  m_lastPositionMapUpdate = QDateTime::currentDateTime();
412  }
413  return ret_val;
414 }
415 
416 // returns true iff found exactly
417 // searches position if search_pos, index otherwise
418 bool DecoderBase::FindPosition(long long desired_value, bool search_adjusted,
419  int &lower_bound, int &upper_bound)
420 {
421  QMutexLocker locker(&m_positionMapLock);
422  // Binary search
423  auto size = (long long) m_positionMap.size();
424  long long lower = -1;
425  long long upper = size;
426 
427  if (!search_adjusted && m_keyframeDist > 0)
428  desired_value /= m_keyframeDist;
429 
430  while (upper - 1 > lower)
431  {
432  long long i = (upper + lower) / 2;
433  long long value = 0;
434  if (search_adjusted)
435  value = m_positionMap[i].adjFrame;
436  else
437  value = m_positionMap[i].index - m_indexOffset;
438  if (value == desired_value)
439  {
440  // found it
441  upper_bound = i;
442  lower_bound = i;
443 
444  LOG(VB_PLAYBACK, LOG_INFO, LOC +
445  QString("FindPosition(%1, search%2 adjusted)")
446  .arg(desired_value).arg((search_adjusted) ? "" : " not") +
447  QString(" --> [%1:%2(%3)]")
448  .arg(i).arg(GetKey(m_positionMap[i]))
449  .arg(m_positionMap[i].pos));
450 
451  return true;
452  }
453  if (value > desired_value)
454  upper = i;
455  else
456  lower = i;
457  }
458  // Did not find it exactly -- return bounds
459 
460  if (search_adjusted)
461  {
462  while (lower >= 0 && m_positionMap[lower].adjFrame > desired_value)
463  lower--;
464  while (upper < size && m_positionMap[upper].adjFrame < desired_value)
465  upper++;
466  }
467  else
468  {
469  while (lower >= 0 &&
470  (m_positionMap[lower].index - m_indexOffset) > desired_value)
471  lower--;
472  while (upper < size &&
473  (m_positionMap[upper].index - m_indexOffset) < desired_value)
474  upper++;
475  }
476  // keep in bounds
477  lower = max(lower, 0LL);
478  upper = min(upper, size - 1LL);
479 
480  upper_bound = upper;
481  lower_bound = lower;
482  bool empty = m_positionMap.empty();
483 
484  LOG(VB_PLAYBACK, LOG_INFO, LOC +
485  QString("FindPosition(%1, search%3 adjusted)")
486  .arg(desired_value).arg((search_adjusted) ? "" : " not") +
487  QString(" --> \n\t\t\t[%1:%2(%3),%4:%5(%6)]")
488  .arg(lower_bound)
489  .arg(empty ? -1 : GetKey(m_positionMap[lower_bound]))
490  .arg(empty ? -1 : m_positionMap[lower_bound].pos)
491  .arg(upper_bound)
492  .arg(empty ? -1 : GetKey(m_positionMap[upper_bound]))
493  .arg(empty ? -1 : m_positionMap[upper_bound].pos));
494 
495  return false;
496 }
497 
498 uint64_t DecoderBase::SavePositionMapDelta(long long first, long long last)
499 {
500  MythTimer ttm;
501  MythTimer ctm;
502  MythTimer stm;
503  ttm.start();
504 
505  QMutexLocker locker(&m_positionMapLock);
507  uint64_t saved = 0;
508 
510  return saved;
511 
512  ctm.start();
513  frm_pos_map_t posMap;
514  for (auto & entry : m_positionMap)
515  {
516  if (entry.index < first)
517  continue;
518  if (entry.index > last)
519  break;
520 
521  posMap[entry.index] = entry.pos;
522  saved++;
523  }
524 
525  frm_pos_map_t durMap;
526  for (frm_pos_map_t::const_iterator it = m_frameToDurMap.begin();
527  it != m_frameToDurMap.end(); ++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 = 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() < 5)
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 = max(desiredFrame, m_framesPlayed);
736 
737  // Save rawframe state, for later restoration...
738  bool oldrawstate = m_getRawFrames;
739  m_getRawFrames = false;
740 
741  ConditionallyUpdatePosMap(desiredFrame);
742 
743  // Fetch last keyframe in position map
744  long long last_frame = GetLastFrameInPosMap();
745 
746  // If the desiredFrame is past the end of the position map,
747  // do some frame-by-frame seeking until we get to it.
748  bool needflush = false;
749  if (desiredFrame > last_frame)
750  {
751  LOG(VB_GENERAL, LOG_NOTICE, LOC +
752  QString("DoFastForward(): desiredFrame(%1) > last_frame(%2)")
753  .arg(desiredFrame).arg(last_frame));
754 
755  if (desiredFrame - last_frame > 32)
756  {
757  LOG(VB_GENERAL, LOG_ERR, LOC + "DoFastForward(): "
758  "Desired frame is way past the end of the keyframe map!"
759  "\n\t\t\tSeeking to last keyframe instead.");
760  desiredFrame = last_frame;
761  }
762 
763  needflush = true;
764 
765  // Handle non-frame-by-frame seeking
766  DoFastForwardSeek(last_frame, needflush);
767 
768  m_exitAfterDecoded = true; // don't actualy get a frame
769  while ((desiredFrame > last_frame) && !m_atEof)
770  {
771  bool retry = false;
772  GetFrame(kDecodeNothing, retry); // don't need to return frame...
773  SyncPositionMap();
774  last_frame = GetLastFrameInPosMap();
775  }
776  m_exitAfterDecoded = false; // allow frames to be returned again
777 
778  if (m_atEof)
779  {
780  // Re-enable rawframe state if it was enabled before FF
781  m_getRawFrames = oldrawstate;
782  return false;
783  }
784  }
785 
786  {
787  QMutexLocker locker(&m_positionMapLock);
788  if (m_positionMap.empty())
789  {
790  // Re-enable rawframe state if it was enabled before FF
791  m_getRawFrames = oldrawstate;
792  return false;
793  }
794  }
795 
796  // Handle non-frame-by-frame seeking
797  DoFastForwardSeek(desiredFrame, needflush);
798 
799  // Do any Extra frame-by-frame seeking for exactseeks mode
800  // And flush pre-seek frame if we are allowed to and need to..
801  int normalframes = (uint64_t)(desiredFrame - (m_framesPlayed - 1)) > m_seekSnap
802  ? desiredFrame - m_framesPlayed : 0;
803  normalframes = max(normalframes, 0);
804  SeekReset(m_lastKey, normalframes, needflush, discardFrames);
805 
806  if (discardFrames || m_transcoding)
808 
809  // Re-enable rawframe state if it was enabled before FF
810  m_getRawFrames = oldrawstate;
811 
812  return true;
813 }
814 
829 void DecoderBase::DoFastForwardSeek(long long desiredFrame, bool &needflush)
830 {
831  if (!m_ringBuffer)
832  {
833  LOG(VB_GENERAL, LOG_ERR, LOC +
834  "No ringBuffer yet, can't fast forward seek");
835  return;
836  }
837 
838  int pre_idx = 0;
839  int post_idx = 0;
840  FindPosition(desiredFrame, m_hasKeyFrameAdjustTable, pre_idx, post_idx);
841 
842  // if exactseeks, use keyframe <= desiredFrame
843 
844  PosMapEntry e {};
845  PosMapEntry e_pre {};
846  PosMapEntry e_post {};
847  {
848  QMutexLocker locker(&m_positionMapLock);
849  e_pre = m_positionMap[pre_idx];
850  e_post = m_positionMap[post_idx];
851  }
852  e = e_pre;
853  if (((uint64_t) (GetKey(e_post) - desiredFrame)) <= m_seekSnap &&
854  (m_framesPlayed - 1 >= GetKey(e_pre) ||
855  GetKey(e_post) - desiredFrame < desiredFrame - GetKey(e_pre)))
856  {
857  // Snap to the right if e_post is within snap distance and is
858  // a closer snap than e_pre. Take into account that if
859  // framesPlayed has already reached e_pre, we should only snap
860  // to the right.
861  e = e_post;
862  }
863  m_lastKey = GetKey(e);
864 
866  {
867  m_ringBuffer->Seek(e.pos, SEEK_SET);
868  needflush = true;
870  m_fpsSkip = 0;
872  }
873 }
874 
876 {
878 }
879 
881 {
882  ResetPosMap();
883  m_framesPlayed = 0;
884  m_framesRead = 0;
886 
887  m_waitingForChange = false;
888  m_justAfterChange = true;
889 
891 }
892 
893 void DecoderBase::SetReadAdjust(long long adjust)
894 {
895  m_readAdjust = adjust;
896 }
897 
899 {
900  m_waitingForChange = true;
901 }
902 
904 {
905  return m_waitingForChange;
906 }
907 
909 {
910  QMutexLocker locker(&m_trackLock);
911  return static_cast<uint>(m_tracks[Type].size());
912 }
913 
915 {
916  m_trackLock.lock();
917  m_decodeAllSubtitles = DecodeAll;
918  m_trackLock.unlock();
919 }
920 
921 QStringList DecoderBase::GetTracks(uint Type)
922 {
923  QMutexLocker locker(&m_trackLock);
924  QStringList list;
925  for (size_t i = 0; i < m_tracks[Type].size(); i++)
926  list += GetTrackDesc(Type, static_cast<uint>(i));
927  return list;
928 }
929 
931 {
932  QMutexLocker locker(&m_trackLock);
933  if (TrackNo >= m_tracks[Type].size())
934  return 0;
935  return static_cast<int>(m_tracks[Type][TrackNo].m_language_index);
936 }
937 
938 QString DecoderBase::GetTrackDesc(uint Type, uint TrackNo)
939 {
940  QMutexLocker locker(&m_trackLock);
941  if (TrackNo >= m_tracks[Type].size())
942  return "";
943 
944  QString type_msg = toString(static_cast<TrackType>(Type));
945  int lang = m_tracks[Type][TrackNo].m_language;
946  int hnum = static_cast<int>(TrackNo + 1);
947  if (kTrackTypeCC608 == Type)
948  hnum = m_tracks[Type][TrackNo].m_stream_id;
949 
950  if (!lang)
951  return type_msg + QString(" %1").arg(hnum);
952  QString lang_msg = iso639_key_toName(lang);
953  return type_msg + QString(" %1: %2").arg(hnum).arg(lang_msg);
954 }
955 
957 {
958  QMutexLocker locker(&m_trackLock);
959  return m_currentTrack[Type];
960 }
961 
962 int DecoderBase::SetTrack(uint Type, int TrackNo)
963 {
964  QMutexLocker locker(&m_trackLock);
965  if (TrackNo >= static_cast<int>(m_tracks[Type].size()))
966  return -1;
967 
968  m_currentTrack[Type] = max(-1, TrackNo);
969  if (m_currentTrack[Type] < 0)
970  {
972  }
973  else
974  {
975  m_wantedTrack[Type] = m_tracks[Type][static_cast<size_t>(m_currentTrack[Type])];
976  m_selectedTrack[Type] = m_tracks[Type][static_cast<size_t>(m_currentTrack[Type])];
977  }
978 
979  return m_currentTrack[Type];
980 }
981 
983 {
984  QMutexLocker locker(&m_trackLock);
985  if (TrackNo >= m_tracks[Type].size())
986  {
987  StreamInfo si;
988  return si;
989  }
990  return m_tracks[Type][TrackNo];
991 }
992 
993 int DecoderBase::ChangeTrack(uint Type, int Dir)
994 {
995  QMutexLocker locker(&m_trackLock);
996 
997  int next_track = -1;
998  int size = static_cast<int>(m_tracks[Type].size());
999  if (size)
1000  {
1001  if (Dir > 0)
1002  next_track = (max(-1, m_currentTrack[Type]) + 1) % size;
1003  else
1004  next_track = (max(+0, m_currentTrack[Type]) + size - 1) % size;
1005  }
1006  return SetTrack(Type, next_track);
1007 }
1008 
1010 {
1011  QMutexLocker locker(&m_trackLock);
1012 
1013  int next_track = -1;
1014  int size = static_cast<int>(m_tracks[Type].size());
1015  if (size)
1016  next_track = (max(0, m_currentTrack[Type]) + 1) % size;
1017  return next_track;
1018 }
1019 
1021 {
1022  QMutexLocker locker(&m_trackLock);
1023 
1024  for (auto & i : m_tracks[Type])
1025  if (Info.m_stream_id == i.m_stream_id)
1026  return false;
1027 
1028  m_tracks[Type].push_back(Info);
1029 
1030  if (m_parent)
1031  m_parent->TracksChanged(Type);
1032 
1033  return true;
1034 }
1035 
1052 {
1053  QMutexLocker locker(&m_trackLock);
1054 
1055  uint numStreams = static_cast<uint>(m_tracks[Type].size());
1056 
1057  if ((m_currentTrack[Type] >= 0) && (m_currentTrack[Type] < static_cast<int>(numStreams)))
1058  return m_currentTrack[Type]; // track already selected
1059 
1060  if (!numStreams)
1061  {
1062  m_currentTrack[Type] = -1;
1064  return -1;
1065  }
1066 
1067  int selTrack = (1 == numStreams) ? 0 : -1;
1068 
1069  if ((selTrack < 0) && m_wantedTrack[Type].m_language>=-1)
1070  {
1071  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Trying to reselect track");
1072  // Try to reselect user selected track stream.
1073  // This should find the stream after a commercial
1074  // break and in some cases after a channel change.
1075  int wlang = m_wantedTrack[Type].m_language;
1076  uint windx = m_wantedTrack[Type].m_language_index;
1077  for (uint i = 0; i < numStreams; i++)
1078  {
1079  if (wlang == m_tracks[Type][i].m_language)
1080  {
1081  selTrack = static_cast<int>(i);
1082  if (windx == m_tracks[Type][i].m_language_index)
1083  break;
1084  }
1085  }
1086  }
1087 
1088  if (selTrack < 0)
1089  {
1090  // Select the best track. Primary attribute is to favor a
1091  // forced track. Secondary attribute is language preference,
1092  // in order of most preferred to least preferred language.
1093  // Third attribute is track order, preferring the earliest
1094  // track.
1095  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Trying to select track (w/lang & forced)");
1096  const int kForcedWeight = (1 << 20);
1097  const int kLanguageWeight = (1 << 10);
1098  const int kPositionWeight = (1 << 0);
1099  int bestScore = -1;
1100  selTrack = 0;
1101  for (uint i = 0; i < numStreams; i++)
1102  {
1103  bool forced = (Type == kTrackTypeSubtitle &&
1104  m_tracks[Type][i].m_forced &&
1106  int position = static_cast<int>(numStreams) - static_cast<int>(i);
1107  int language = 0;
1108  for (uint j = 0; (language == 0) && (j < m_languagePreference.size()); ++j)
1109  {
1110  if (m_tracks[Type][i].m_language == m_languagePreference[j])
1111  language = static_cast<int>(m_languagePreference.size()) - static_cast<int>(j);
1112  }
1113  int score = (kForcedWeight * static_cast<int>(forced)) +
1114  (kLanguageWeight * language) +
1115  (kPositionWeight * position);
1116  if (score > bestScore)
1117  {
1118  bestScore = score;
1119  selTrack = static_cast<int>(i);
1120  }
1121  }
1122  }
1123 
1124  int oldTrack = m_currentTrack[Type];
1125  m_currentTrack[Type] = selTrack;
1126  StreamInfo tmp = m_tracks[Type][static_cast<size_t>(m_currentTrack[Type])];
1127  m_selectedTrack[Type] = tmp;
1128 
1129  if (m_wantedTrack[Type].m_av_stream_index < 0)
1130  m_wantedTrack[Type] = tmp;
1131 
1132  int lang = m_tracks[Type][static_cast<size_t>(m_currentTrack[Type])].m_language;
1133  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Selected track #%1 (type %2) in the %3 language(%4)")
1134  .arg(m_currentTrack[Type]+1).arg(Type).arg(iso639_key_toName(lang)).arg(lang));
1135 
1136  if (m_parent && (oldTrack != m_currentTrack[Type]))
1137  m_parent->TracksChanged(Type);
1138 
1139  return selTrack;
1140 }
1141 
1143 {
1144  for (uint i = 0; i < kTrackTypeCount; i++)
1145  AutoSelectTrack(i);
1146 }
1147 
1149 {
1150  QMutexLocker locker(&m_trackLock);
1151  for (int & i : m_currentTrack)
1152  i = -1;
1153 }
1154 
1156 {
1157  QString str = QObject::tr("Track");
1158 
1159  if (kTrackTypeAudio == type)
1160  str = QObject::tr("Audio track");
1161  else if (kTrackTypeVideo == type)
1162  str = QObject::tr("Video track");
1163  else if (kTrackTypeSubtitle == type)
1164  str = QObject::tr("Subtitle track");
1165  else if (kTrackTypeCC608 == type)
1166  str = QObject::tr("CC", "EIA-608 closed captions");
1167  else if (kTrackTypeCC708 == type)
1168  str = QObject::tr("ATSC CC", "EIA-708 closed captions");
1169  else if (kTrackTypeTeletextCaptions == type)
1170  str = QObject::tr("TT CC", "Teletext closed captions");
1171  else if (kTrackTypeTeletextMenu == type)
1172  str = QObject::tr("TT Menu", "Teletext Menu");
1173  else if (kTrackTypeRawText == type)
1174  str = QObject::tr("Text", "Text stream");
1175  else if (kTrackTypeTextSubtitle == type)
1176  str = QObject::tr("TXT File", "Text File");
1177  return str;
1178 }
1179 
1180 int to_track_type(const QString &str)
1181 {
1182  int ret = -1;
1183 
1184  if (str.startsWith("AUDIO"))
1185  ret = kTrackTypeAudio;
1186  else if (str.startsWith("VIDEO"))
1187  ret = kTrackTypeVideo;
1188  else if (str.startsWith("SUBTITLE"))
1189  ret = kTrackTypeSubtitle;
1190  else if (str.startsWith("CC608"))
1191  ret = kTrackTypeCC608;
1192  else if (str.startsWith("CC708"))
1193  ret = kTrackTypeCC708;
1194  else if (str.startsWith("TTC"))
1196  else if (str.startsWith("TTM"))
1197  ret = kTrackTypeTeletextMenu;
1198  else if (str.startsWith("TFL"))
1199  ret = kTrackTypeTextSubtitle;
1200  else if (str.startsWith("RAWTEXT"))
1201  ret = kTrackTypeRawText;
1202  return ret;
1203 }
1204 
1206 {
1207  QString str;
1208 
1209  switch (type)
1210  {
1212  str = QObject::tr("Audio Description",
1213  "On-screen events described for the visually impaired");
1214  break;
1215  case kAudioTypeCleanEffects :
1216  str = QObject::tr("Clean Effects",
1217  "No dialog, background audio only");
1218  break;
1220  str = QObject::tr("Hearing Impaired",
1221  "Clear dialog for the hearing impaired");
1222  break;
1223  case kAudioTypeSpokenSubs :
1224  str = QObject::tr("Spoken Subtitles",
1225  "Subtitles are read out for the visually impaired");
1226  break;
1227  case kAudioTypeCommentary :
1228  str = QObject::tr("Commentary", "Director/Cast commentary track");
1229  break;
1230  case kAudioTypeNormal :
1231  default:
1232  str = QObject::tr("Normal", "Ordinary audio track");
1233  break;
1234  }
1235 
1236  return str;
1237 }
1238 
1240 {
1241  if (!m_playbackInfo || av_q2d(m_totalDuration) == 0)
1242  return;
1243 
1244  m_playbackInfo->SaveTotalDuration(1000000 * av_q2d(m_totalDuration));
1245 }
1246 
1248 {
1249  if (!m_playbackInfo || !m_framesRead)
1250  return;
1251 
1253 }
1254 
1255 // Linearly interpolate the value for a given key in the map. If the
1256 // key is outside the range of keys in the map, linearly extrapolate
1257 // using the fallback ratio.
1259  long long key,
1260  float fallback_ratio)
1261 {
1262  uint64_t key1 = 0;
1263  uint64_t key2 = 0;
1264  uint64_t val1 = 0;
1265  uint64_t val2 = 0;
1266 
1267  frm_pos_map_t::const_iterator lower = map.lowerBound(key);
1268  // QMap::lowerBound() finds a key >= the given key. We want one
1269  // <= the given key, so back up one element upon > condition.
1270  if (lower != map.begin() && (lower == map.end() || lower.key() > key))
1271  --lower;
1272  if (lower == map.end() || lower.key() > key)
1273  {
1274  key1 = 0;
1275  val1 = 0;
1276  LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
1277  QString("TranslatePosition(key=%1): extrapolating to (0,0)")
1278  .arg(key));
1279  }
1280  else
1281  {
1282  key1 = lower.key();
1283  val1 = lower.value();
1284  }
1285  // Find the next key >= the given key. QMap::lowerBound() is
1286  // precisely correct in this case.
1287  frm_pos_map_t::const_iterator upper = map.lowerBound(key);
1288  if (upper == map.end())
1289  {
1290  // Extrapolate from (key1,val1) based on fallback_ratio
1291  key2 = key;
1292  val2 = llroundf(val1 + fallback_ratio * (key2 - key1));
1293  LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
1294  QString("TranslatePosition(key=%1, ratio=%2): "
1295  "extrapolating to (%3,%4)")
1296  .arg(key).arg(fallback_ratio).arg(key2).arg(val2));
1297  return val2;
1298  }
1299  key2 = upper.key();
1300  val2 = upper.value();
1301  if (key1 == key2) // this happens for an exact keyframe match
1302  return val2; // can also set key2 = key1 + 1 avoid dividing by zero
1303 
1304  return llround(val1 + (double) (key - key1) * (val2 - val1) / (key2 - key1));
1305 }
1306 
1307 // Convert from an absolute frame number (not cutlist adjusted) to its
1308 // cutlist-adjusted position in milliseconds.
1309 uint64_t DecoderBase::TranslatePositionFrameToMs(long long position,
1310  float fallback_framerate,
1311  const frm_dir_map_t &cutlist)
1312 {
1313  QMutexLocker locker(&m_positionMapLock);
1314  // Accurate calculation of duration requires an up-to-date
1315  // duration map. However, the last frame (total duration) will
1316  // almost always appear to be past the end of the duration map, so
1317  // we limit duration map syncing to once every 3 seconds (a
1318  // somewhat arbitrary value).
1319  if (!m_frameToDurMap.empty())
1320  {
1321  frm_pos_map_t::const_iterator it = m_frameToDurMap.end();
1322  --it;
1323  if (position > it.key())
1324  {
1325  if (!m_lastPositionMapUpdate.isValid() ||
1326  (QDateTime::currentDateTime() >
1327  m_lastPositionMapUpdate.addSecs(3)))
1328  SyncPositionMap();
1329  }
1330  }
1331  return TranslatePositionAbsToRel(cutlist, position, m_frameToDurMap,
1332  1000 / fallback_framerate);
1333 }
1334 
1335 // Convert from a cutlist-adjusted position in milliseconds to its
1336 // absolute frame number (not cutlist-adjusted).
1338  float fallback_framerate,
1339  const frm_dir_map_t &cutlist)
1340 {
1341  QMutexLocker locker(&m_positionMapLock);
1342  // Convert relative position in milliseconds (cutlist-adjusted) to
1343  // its absolute position in milliseconds (not cutlist-adjusted).
1344  uint64_t ms = TranslatePositionRelToAbs(cutlist, dur_ms, m_frameToDurMap,
1345  1000 / fallback_framerate);
1346  // Convert absolute position in milliseconds to its absolute frame
1347  // number.
1348  return TranslatePosition(m_durToFrameMap, ms, fallback_framerate / 1000);
1349 }
1350 
1351 // Convert from an "absolute" (not cutlist-adjusted) value to its
1352 // "relative" (cutlist-adjusted) mapped value. Usually the position
1353 // argument is a frame number, the map argument maps frames to
1354 // milliseconds, the fallback_ratio is 1000/framerate_fps, and the
1355 // return value is in milliseconds.
1356 //
1357 // If the map and fallback_ratio arguments are omitted, it simply
1358 // converts from an absolute frame number to a relative
1359 // (cutlist-adjusted) frame number.
1360 uint64_t
1362  uint64_t absPosition, // frames
1363  const frm_pos_map_t &map, // frame->ms
1364  float fallback_ratio)
1365 {
1366  uint64_t subtraction = 0;
1367  uint64_t startOfCutRegion = 0;
1368  bool withinCut = false;
1369  bool first = true;
1370  for (frm_dir_map_t::const_iterator i = deleteMap.begin();
1371  i != deleteMap.end(); ++i)
1372  {
1373  if (first)
1374  withinCut = (i.value() == MARK_CUT_END);
1375  first = false;
1376  if (i.key() > absPosition)
1377  break;
1378  uint64_t mappedKey = TranslatePosition(map, i.key(), fallback_ratio);
1379  if (i.value() == MARK_CUT_START && !withinCut)
1380  {
1381  withinCut = true;
1382  startOfCutRegion = mappedKey;
1383  }
1384  else if (i.value() == MARK_CUT_END && withinCut)
1385  {
1386  withinCut = false;
1387  subtraction += (mappedKey - startOfCutRegion);
1388  }
1389  }
1390  uint64_t mappedPos = TranslatePosition(map, absPosition, fallback_ratio);
1391  if (withinCut)
1392  subtraction += (mappedPos - startOfCutRegion);
1393  return mappedPos - subtraction;
1394 }
1395 
1396 // Convert from a "relative" (cutlist-adjusted) value to its
1397 // "absolute" (not cutlist-adjusted) mapped value. Usually the
1398 // position argument is in milliseconds, the map argument maps frames
1399 // to milliseconds, the fallback_ratio is 1000/framerate_fps, and the
1400 // return value is also in milliseconds. Upon return, if necessary,
1401 // the result may need a separate, non-cutlist adjusted conversion
1402 // from milliseconds to frame number, using the inverse
1403 // millisecond-to-frame map and the inverse fallback_ratio; see for
1404 // example TranslatePositionMsToFrame().
1405 //
1406 // If the map and fallback_ratio arguments are omitted, it simply
1407 // converts from a relatve (cutlist-adjusted) frame number to an
1408 // absolute frame number.
1409 uint64_t
1411  uint64_t relPosition, // ms
1412  const frm_pos_map_t &map, // frame->ms
1413  float fallback_ratio)
1414 {
1415  uint64_t addition = 0;
1416  uint64_t startOfCutRegion = 0;
1417  bool withinCut = false;
1418  bool first = true;
1419  for (frm_dir_map_t::const_iterator i = deleteMap.begin();
1420  i != deleteMap.end(); ++i)
1421  {
1422  if (first)
1423  withinCut = (i.value() == MARK_CUT_END);
1424  first = false;
1425  uint64_t mappedKey = TranslatePosition(map, i.key(), fallback_ratio);
1426  if (i.value() == MARK_CUT_START && !withinCut)
1427  {
1428  withinCut = true;
1429  startOfCutRegion = mappedKey;
1430  if (relPosition + addition <= startOfCutRegion)
1431  break;
1432  }
1433  else if (i.value() == MARK_CUT_END && withinCut)
1434  {
1435  withinCut = false;
1436  addition += (mappedKey - startOfCutRegion);
1437  }
1438  }
1439  return relPosition + addition;
1440 }
1441 
1446 AVPixelFormat DecoderBase::GetBestVideoFormat(AVPixelFormat* Formats)
1447 {
1448  if (m_parent)
1449  {
1451  for (AVPixelFormat *format = Formats; *format != AV_PIX_FMT_NONE; format++)
1452  {
1453  for (VideoFrameType* mythfmt = mythfmts; *mythfmt != FMT_NONE; mythfmt++)
1454  if (FrameTypeToPixelFormat(*mythfmt) == *format)
1455  return *format;
1456  }
1457  }
1458  return AV_PIX_FMT_NONE;
1459 }
1460 
1461 /* vim: set expandtab tabstop=4 shiftwidth=4: */
AVRationalInit
AVRational AVRationalInit(int num, int den=1)
Definition: decoderbase.h:112
MythMediaBuffer::BD
const MythBDBuffer * BD(void) const
Definition: mythmediabuffer.cpp:1854
DecoderBase::DoFastForward
virtual bool DoFastForward(long long desiredFrame, bool discardFrames=true)
Skips ahead or rewinds to desiredFrame.
Definition: decoderbase.cpp:709
kAudioTypeHearingImpaired
@ kAudioTypeHearingImpaired
Definition: decoderbase.h:59
MythBDBuffer::GetFrameRate
double GetFrameRate(void)
Definition: mythbdbuffer.cpp:868
e
QDomElement e
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:1417
MARK_KEYFRAME
@ MARK_KEYFRAME
Definition: programtypes.h:62
DecoderBase::SetTrack
virtual int SetTrack(uint Type, int TrackNo)
Definition: decoderbase.cpp:962
DecoderBase::m_readAdjust
long long m_readAdjust
Definition: decoderbase.h:345
DecoderBase::m_trackLock
QMutex m_trackLock
Definition: decoderbase.h:349
DecoderBase::GetTrack
int GetTrack(uint Type)
Definition: decoderbase.cpp:956
DecoderBase::NextTrack
int NextTrack(uint Type)
Definition: decoderbase.cpp:1009
DecoderBase::m_seekSnap
uint64_t m_seekSnap
Definition: decoderbase.h:331
AudioTrackType
AudioTrackType
Definition: decoderbase.h:54
kTrackTypeTextSubtitle
@ kTrackTypeTextSubtitle
Definition: decoderbase.h:41
DecoderBase::m_ringBuffer
MythMediaBuffer * m_ringBuffer
Definition: decoderbase.h:290
StreamInfo::m_language_index
uint m_language_index
Definition: decoderbase.h:97
DecoderBase::PosMapEntry
Definition: decoderbase.h:279
ProgramInfo::QueryPositionMap
void QueryPositionMap(frm_pos_map_t &posMap, MarkTypes type) const
Definition: programinfo.cpp:3590
kEofStateNone
@ kEofStateNone
Definition: decoderbase.h:68
kTrackTypeCount
@ kTrackTypeCount
Definition: decoderbase.h:37
DecoderBase::m_fps
double m_fps
Definition: decoderbase.h:292
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:306
DecoderBase::m_lastPositionMapUpdate
QDateTime m_lastPositionMapUpdate
Definition: decoderbase.h:329
to_track_type
int to_track_type(const QString &str)
Definition: decoderbase.cpp:1180
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:496
ProgramInfo::SavePositionMapDelta
void SavePositionMapDelta(frm_pos_map_t &posMap, MarkTypes type) const
Definition: programinfo.cpp:3818
DecoderBase::m_hasKeyFrameAdjustTable
bool m_hasKeyFrameAdjustTable
Definition: decoderbase.h:336
StreamInfo::m_av_stream_index
int m_av_stream_index
Definition: decoderbase.h:93
ProgramInfo::SaveTotalFrames
void SaveTotalFrames(int64_t frames)
Store the Total Frames at frame 0 in the recordedmarkup table.
Definition: programinfo.cpp:4167
MythPlayer::DirectRenderFormats
VideoFrameType * DirectRenderFormats(void)
Return a list of frame types that can be rendered directly.
Definition: mythplayer.cpp:949
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:1051
DecoderBase::m_atEof
EofState m_atEof
Definition: decoderbase.h:310
DecoderBase::m_parent
MythPlayer * m_parent
Definition: decoderbase.h:287
DecoderBase::SavePositionMapDelta
uint64_t SavePositionMapDelta(long long first_frame, long long last_frame)
Definition: decoderbase.cpp:498
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:98
kTrackTypeTeletextMenu
@ kTrackTypeTeletextMenu
Definition: decoderbase.h:34
DecoderBase::m_frameCounter
unsigned long long m_frameCounter
Definition: decoderbase.h:302
DecoderBase::DecoderBase
DecoderBase(MythPlayer *parent, const ProgramInfo &pginfo)
Definition: decoderbase.cpp:18
mythdvdbuffer.h
DecoderBase::m_livetv
bool m_livetv
Definition: decoderbase.h:333
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:1148
MythMediaBuffer::IsDVD
bool IsDVD(void) const
Definition: mythmediabuffer.cpp:1839
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:993
TrackType
TrackType
Track types.
Definition: decoderbase.h:25
kAudioTypeCleanEffects
@ kAudioTypeCleanEffects
Definition: decoderbase.h:58
mythplayer.h
DecoderBase::m_positionMapType
MarkTypes m_positionMapType
Definition: decoderbase.h:323
MythDVDBuffer::TitleTimeLeft
uint TitleTimeLeft(void) const
returns seconds left in the title
Definition: mythdvdbuffer.cpp:1970
MythPlayer
Definition: mythplayer.h:164
MythMediaBuffer::IsBD
bool IsBD(void) const
Definition: mythmediabuffer.cpp:1844
MythPlayer::ForcedSubtitlesFavored
bool ForcedSubtitlesFavored(void) const
Definition: mythplayer.h:338
DecoderBase::m_currentTrack
int m_currentTrack[kTrackTypeCount]
Definition: decoderbase.h:351
DecoderBase::m_posmapStarted
bool m_posmapStarted
Definition: decoderbase.h:322
MythDVDBuffer::GetFrameRate
double GetFrameRate(void)
used by DecoderBase for the total frame number calculation for position map support and ffw/rew.
Definition: mythdvdbuffer.cpp:1932
DecoderBase::m_exitAfterDecoded
bool m_exitAfterDecoded
Definition: decoderbase.h:317
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:327
DecoderBase::GetWaitForChange
bool GetWaitForChange(void) const
Definition: decoderbase.cpp:903
DecoderBase::SetWaitForChange
void SetWaitForChange(void)
Definition: decoderbase.cpp:898
tmp
static guint32 * tmp
Definition: goom_core.cpp:30
DecoderBase::m_dontSyncPositionMap
bool m_dontSyncPositionMap
Definition: decoderbase.h:332
FMT_NONE
@ FMT_NONE
Definition: mythframe.h:26
kAudioTypeAudioDescription
@ kAudioTypeAudioDescription
Definition: decoderbase.h:57
kAudioTypeNormal
@ kAudioTypeNormal
Definition: decoderbase.h:56
toString
QString toString(TrackType type)
Definition: decoderbase.cpp:1155
DecoderBase::GetTrackDesc
virtual QString GetTrackDesc(uint Type, uint TrackNo)
Definition: decoderbase.cpp:938
DecoderBase::SaveTotalDuration
void SaveTotalDuration(void)
Definition: decoderbase.cpp:1239
DecoderBase::GetTrackCount
virtual uint GetTrackCount(uint Type)
Definition: decoderbase.cpp:908
DecoderBase::FindPosition
virtual bool FindPosition(long long desired_value, bool search_adjusted, int &lower_bound, int &upper_bound)
Definition: decoderbase.cpp:418
DecoderBase::m_selectedTrack
StreamInfo m_selectedTrack[kTrackTypeCount]
Definition: decoderbase.h:354
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:1361
programinfo.h
DecoderBase::m_keyframeDist
int m_keyframeDist
Definition: decoderbase.h:304
DecoderBase::m_getRawFrames
bool m_getRawFrames
Definition: decoderbase.h:338
mythlogging.h
DecoderBase::GetTrackInfo
StreamInfo GetTrackInfo(uint Type, uint TrackNo)
Definition: decoderbase.cpp:982
StreamInfo
Definition: decoderbase.h:73
DecoderBase::DoRewindSeek
virtual bool DoRewindSeek(long long desiredFrame)
Definition: decoderbase.cpp:588
DecoderBase::m_languagePreference
vector< int > m_languagePreference
language preferences for auto-selection of streams
Definition: decoderbase.h:357
MythMediaBuffer::IsInDiscMenuOrStillFrame
virtual bool IsInDiscMenuOrStillFrame(void) const
Definition: mythmediabuffer.h:131
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:1410
LOC
#define LOC
Definition: decoderbase.cpp:16
DecoderBase::m_positionMapLock
QMutex m_positionMapLock
Definition: decoderbase.h:325
kTrackTypeTeletextCaptions
@ kTrackTypeTeletextCaptions
Definition: decoderbase.h:33
hardwareprofile.smolt.long
long
Definition: smolt.py:76
DecoderBase::m_durToFrameMap
frm_pos_map_t m_durToFrameMap
Definition: decoderbase.h:328
DecoderBase::ResetPosMap
virtual void ResetPosMap(void)
Definition: decoderbase.cpp:646
DecoderBase::SetReadAdjust
void SetReadAdjust(long long adjust)
Definition: decoderbase.cpp:893
DecoderBase::m_playbackInfo
ProgramInfo * m_playbackInfo
Definition: decoderbase.h:288
DecoderBase::m_totalDuration
AVRational m_totalDuration
Definition: decoderbase.h:303
MythPlayer::PosMapFromEnc
bool PosMapFromEnc(uint64_t start, frm_pos_map_t &posMap, frm_pos_map_t &durMap)
Definition: mythplayer.cpp:5378
kTrackTypeAudio
@ kTrackTypeAudio
Definition: decoderbase.h:28
kTrackTypeCC708
@ kTrackTypeCC708
Definition: decoderbase.h:32
DecoderBase::GetPositionMapSize
unsigned long GetPositionMapSize(void) const
Definition: decoderbase.cpp:292
uint
unsigned int uint
Definition: compat.h:140
DecoderBase::AutoSelectTracks
void AutoSelectTracks(void)
Definition: decoderbase.cpp:1142
DecoderBase::FileChanged
void FileChanged(void)
Definition: decoderbase.cpp:880
DecoderBase::m_transcoding
bool m_transcoding
Definition: decoderbase.h:318
DecoderBase::m_waitingForChange
bool m_waitingForChange
Definition: decoderbase.h:343
kTrackTypeSubtitle
@ kTrackTypeSubtitle
Definition: decoderbase.h:30
DecoderBase::m_justAfterChange
bool m_justAfterChange
Definition: decoderbase.h:344
DecoderBase::SyncPositionMap
virtual bool SyncPositionMap(void)
Updates the position map used for skipping frames.
Definition: decoderbase.cpp:320
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:48
DecoderBase::SetProgramInfo
void SetProgramInfo(const ProgramInfo &pginfo)
Definition: decoderbase.cpp:37
DecoderBase::GetKey
long long GetKey(const PosMapEntry &entry) const
Definition: decoderbase.cpp:581
DecoderBase::m_tracks
vector< StreamInfo > m_tracks[kTrackTypeCount]
Definition: decoderbase.h:352
DecoderBase::PosMapFromEnc
virtual bool PosMapFromEnc(void)
Queries encoder for position map data that has not been committed to the DB yet.
Definition: decoderbase.cpp:220
DecoderBase::SetWatchingRecording
virtual void SetWatchingRecording(bool mode)
Definition: decoderbase.cpp:77
MythPlayer::SetFileLength
void SetFileLength(int total, int frames)
Definition: mythplayer.cpp:743
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:829
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:31
MythPlayer::SetKeyframeDistance
void SetKeyframeDistance(int keyframedistance)
Definition: mythplayer.cpp:521
DecoderBase::UpdateFramesPlayed
virtual void UpdateFramesPlayed(void)
Definition: decoderbase.cpp:875
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:67
DecoderBase::SetDecodeAllSubtitles
void SetDecodeAllSubtitles(bool DecodeAll)
Definition: decoderbase.cpp:914
ProgramInfo::SaveTotalDuration
void SaveTotalDuration(int64_t duration)
Store the Total Duration at frame 0 in the recordedmarkup table.
Definition: programinfo.cpp:4135
DecoderBase::m_framesPlayed
long long m_framesPlayed
Definition: decoderbase.h:300
DecoderBase::TranslatePositionMsToFrame
uint64_t TranslatePositionMsToFrame(uint64_t dur_ms, float fallback_framerate, const frm_dir_map_t &cutlist)
Definition: decoderbase.cpp:1337
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:1408
MythPlayer::SetFramesPlayed
void SetFramesPlayed(uint64_t played)
Definition: mythplayer.cpp:931
MythPlayer::FileChangedCallback
void FileChangedCallback()
Definition: mythplayer.cpp:2558
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:1309
DecoderBase::m_decodeAllSubtitles
bool m_decodeAllSubtitles
Definition: decoderbase.h:350
MarkTypes
MarkTypes
Definition: programtypes.h:48
StreamInfo::m_language
int m_language
ISO639 canonical language key.
Definition: decoderbase.h:96
DecoderBase::m_watchingRecording
bool m_watchingRecording
Definition: decoderbase.h:334
DecoderBase::m_wantedTrack
StreamInfo m_wantedTrack[kTrackTypeCount]
Definition: decoderbase.h:353
MythDVDBuffer::GetTotalTimeOfTitle
uint GetTotalTimeOfTitle(void) const
get the total time of the title in seconds 90000 ticks = 1 sec
Definition: mythdvdbuffer.cpp:1135
DecoderBase::GetBestVideoFormat
AVPixelFormat GetBestVideoFormat(AVPixelFormat *Formats)
Find a suitable frame format that is mutually acceptable to the decoder and render device.
Definition: decoderbase.cpp:1446
MythMediaBuffer::IsDisc
bool IsDisc(void) const
Definition: mythmediabuffer.cpp:1834
DecoderBase::TranslatePosition
static uint64_t TranslatePosition(const frm_pos_map_t &map, long long key, float fallback_ratio)
Definition: decoderbase.cpp:1258
decoderbase.h
DecoderBase::PosMapFromDb
virtual bool PosMapFromDb(void)
Definition: decoderbase.cpp:90
kTrackTypeRawText
@ kTrackTypeRawText
Definition: decoderbase.h:35
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:305
MythDVDBuffer::GetTotalReadPosition
long long GetTotalReadPosition(void) const
Definition: mythdvdbuffer.cpp:447
MythMediaBuffer::DVD
const MythDVDBuffer * DVD(void) const
Definition: mythmediabuffer.cpp:1849
VideoFrameType
VideoFrameType
Definition: mythframe.h:24
kTrackTypeVideo
@ kTrackTypeVideo
Definition: decoderbase.h:29
DecoderBase::m_positionMap
vector< PosMapEntry > m_positionMap
Definition: decoderbase.h:326
DecoderBase::m_framesRead
long long m_framesRead
Definition: decoderbase.h:301
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:921
DecoderBase::m_fpsSkip
int m_fpsSkip
Definition: decoderbase.h:294
kAudioTypeSpokenSubs
@ kAudioTypeSpokenSubs
Definition: decoderbase.h:60
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:1020
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:554
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:321
DecoderBase::GetTrackLanguageIndex
virtual int GetTrackLanguageIndex(uint Type, uint TrackNo)
Definition: decoderbase.cpp:930
DecoderBase::SaveTotalFrames
void SaveTotalFrames(void)
Definition: decoderbase.cpp:1247
kAudioTypeCommentary
@ kAudioTypeCommentary
Definition: decoderbase.h:61