16 #define LOC QString("Dec: ") 19 : m_parent(parent), m_playbackinfo(new
ProgramInfo(pginfo)),
20 m_audio(m_parent->GetAudio()), ringBuffer(nullptr),
22 current_width(640), current_height(480),
23 current_aspect(1.33333), fps(29.97),
24 fpsMultiplier(1), fpsSkip(0),
27 framesPlayed(0), framesRead(0),
29 lastKey(0), keyframedist(-1), indexOffset(0),
30 trackTotalDuration(
false),
34 hasFullPositionMap(
false), recordingHasPositionMap(
false),
37 m_positionMapLock(QMutex::Recursive),
38 dontSyncPositionMap(
false),
40 seeksnap(UINT64_MAX), livetv(
false), watchingrecording(
false),
42 hasKeyFrameAdjustTable(
false),
44 errored(
false), waitingForChange(
false), readAdjust(0),
45 justAfterChange(
false),
46 video_inverted(
false),
47 decodeAllSubtitles(
false),
74 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
75 QString(
"Reset: Video %1, Seek %2, File %3")
76 .arg(reset_video_data).arg(seek_reset).arg(reset_file));
131 if (fps < 26 && fps > 24)
141 if (fps < 26 && fps > 24)
146 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
147 QString(
"%1 TotalTimeOfTitle() in ticks, %2 TotalReadPosition() " 148 "in bytes, %3 is fps")
172 if (fps < 26 && fps > 24)
204 for (frm_pos_map_t::const_iterator it = posMap.begin();
205 it != posMap.end(); ++it)
216 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
217 QString(
"Position map filled from DB to: %1")
222 for (frm_pos_map_t::const_iterator it = durMap.begin();
223 it != durMap.end(); ++it)
232 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
233 QString(
"Duration map filled from DB to: %1").arg(
last));
252 unsigned long long start = 0;
268 long long last_index = 0;
271 for (frm_pos_map_t::const_iterator it = posMap.begin();
272 it != posMap.end(); ++it)
274 if (it.key() <= last_index)
286 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
287 QString(
"Position map filled from Encoder to: %1")
296 last_index = it.key();
298 for (frm_pos_map_t::const_iterator it = durMap.begin();
299 it != durMap.end(); ++it)
301 if (!isEmpty && it.key() <= last_index)
311 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
312 QString(
"Duration map filled from Encoder to: %1").arg(it.key()));
348 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
349 QString(
"Resyncing position map. posmapStarted = %1" 350 " livetv(%2) watchingRec(%3)")
357 unsigned long new_posmap_size = old_posmap_size;
366 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
367 QString(
"SyncPositionMap watchingrecording, from DB: " 368 "%1 entries") .arg(new_posmap_size));
373 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
374 QString(
"SyncPositionMap watchingrecording no entries " 375 "from encoder, try DB"));
380 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
381 QString(
"SyncPositionMap watchingrecording total: %1 entries")
382 .arg(new_posmap_size));
392 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
393 QString(
"SyncPositionMap prerecorded, from DB: %1 entries")
394 .arg(new_posmap_size));
398 bool ret_val = new_posmap_size > old_posmap_size;
402 long long totframes = 0;
422 length = (int)((totframes * 1.0) /
fps);
429 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
430 QString(
"SyncPositionMap, new totframes: %1, new length: %2, " 432 .arg(totframes).arg(length).arg(new_posmap_size));
445 int &lower_bound,
int &upper_bound)
450 long long lower = -1;
451 long long upper = size;
456 while (upper - 1 > lower)
458 long long i = (upper + lower) / 2;
464 if (value == desired_value)
470 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
471 QString(
"FindPosition(%1, search%2 adjusted)")
472 .arg(desired_value).arg((search_adjusted) ?
"" :
" not") +
473 QString(
" --> [%1:%2(%3)]")
479 else if (value > desired_value)
488 while (lower >= 0 &&
m_positionMap[lower].adjFrame > desired_value)
490 while (upper < size &&
m_positionMap[upper].adjFrame < desired_value)
498 while (upper < size &&
503 lower = max(lower, 0LL);
504 upper = min(upper, size - 1LL);
510 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
511 QString(
"FindPosition(%1, search%3 adjusted)")
512 .arg(desired_value).arg((search_adjusted) ?
"" :
" not") +
513 QString(
" --> \n\t\t\t[%1:%2(%3),%4:%5(%6)]")
553 if (it.key() < first)
557 durMap[it.key()] = it.value();
567 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
568 QString(
"Saving position map [%1,%2] w/%3 keyframes, " 569 "took (%4,%5,%6) ms")
570 .arg(first).arg(
last).arg(saved)
580 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
581 QString(
"DoRewind(%1 (%2), %3 discard frames)")
583 .arg((discardFrames) ?
"do" :
"don't"));
596 normalframes = max(normalframes, 0);
618 LOG(VB_GENERAL, LOG_ERR,
LOC +
"PosMap is empty, can't seek");
624 LOG(VB_GENERAL, LOG_ERR,
LOC +
"No ringBuffer yet, can't seek");
629 int pre_idx, post_idx;
637 int pos_idx = pre_idx;
641 GetKey(e_post) - desiredFrame <= desiredFrame -
GetKey(e_pre))
680 long long last_frame = 0;
693 if (desiredFrame < 0)
698 if (desiredFrame < last_frame)
701 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
702 "ConditionallyUpdatePosMap: Not enough info in positionMap," +
703 QString(
"\n\t\t\twe need frame %1 but highest we have is %2.")
704 .arg(desiredFrame).arg(last_frame));
710 if (desiredFrame > last_frame)
712 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
713 "ConditionallyUpdatePosMap: Still not " 714 "enough info in positionMap after sync, " +
715 QString(
"\n\t\t\twe need frame %1 but highest we have " 716 "is %2. Will attempt to seek frame-by-frame")
717 .arg(desiredFrame).arg(last_frame));
734 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
735 QString(
"DoFastForward(%1 (%2), %3 discard frames)")
737 .arg((discardFrames) ?
"do" :
"don't"));
741 LOG(VB_GENERAL, LOG_ERR,
LOC +
"No ringBuffer yet, can't fast forward");
757 return DoRewind(desiredFrame, discardFrames);
771 bool needflush =
false;
772 if (desiredFrame > last_frame)
774 LOG(VB_GENERAL, LOG_NOTICE,
LOC +
775 QString(
"DoFastForward(): desiredFrame(%1) > last_frame(%2)")
776 .arg(desiredFrame).arg(last_frame));
778 if (desiredFrame - last_frame > 32)
780 LOG(VB_GENERAL, LOG_ERR,
LOC +
"DoFastForward(): " 781 "Desired frame is way past the end of the keyframe map!" 782 "\n\t\t\tSeeking to last keyframe instead.");
783 desiredFrame = last_frame;
792 while ((desiredFrame > last_frame) && !
ateof)
825 normalframes = max(normalframes, 0);
855 LOG(VB_GENERAL, LOG_ERR,
LOC +
856 "No ringBuffer yet, can't fast forward seek");
860 int pre_idx, post_idx;
874 GetKey(e_post) - desiredFrame < desiredFrame -
GetKey(e_pre)))
956 int hnum = trackNo + 1;
961 return type_msg + QString(
" %1").arg(hnum);
965 return type_msg + QString(
" %1: %2").arg(hnum).arg(lang_msg);
1052 int selTrack = (1 == numStreams) ? 0 : -1;
1054 if ((selTrack < 0) &&
1057 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Trying to reselect track");
1063 for (
uint i = 0; i < numStreams; i++)
1082 LOG(VB_PLAYBACK, LOG_INFO,
1083 LOC +
"Trying to select track (w/lang & forced)");
1084 const int kForcedWeight = (1 << 20);
1085 const int kLanguageWeight = (1 << 10);
1086 const int kPositionWeight = (1 << 0);
1089 for (
uint i = 0; i < numStreams; i++)
1094 int position = numStreams - i;
1102 int score = kForcedWeight * forced
1103 + kLanguageWeight * language
1104 + kPositionWeight * position;
1105 if (score > bestScore)
1122 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1123 QString(
"Selected track #%1 (type %2) in the %3 language(%4)")
1136 QString str = QObject::tr(
"Track");
1139 str = QObject::tr(
"Audio track");
1141 str = QObject::tr(
"Video track");
1143 str = QObject::tr(
"Subtitle track");
1145 str = QObject::tr(
"CC",
"EIA-608 closed captions");
1147 str = QObject::tr(
"ATSC CC",
"EIA-708 closed captions");
1149 str = QObject::tr(
"TT CC",
"Teletext closed captions");
1151 str = QObject::tr(
"TT Menu",
"Teletext Menu");
1153 str = QObject::tr(
"Text",
"Text stream");
1155 str = QObject::tr(
"TXT File",
"Text File");
1163 if (str.startsWith(
"AUDIO"))
1165 else if (str.startsWith(
"VIDEO"))
1167 else if (str.startsWith(
"SUBTITLE"))
1169 else if (str.startsWith(
"CC608"))
1171 else if (str.startsWith(
"CC708"))
1173 else if (str.startsWith(
"TTC"))
1175 else if (str.startsWith(
"TTM"))
1177 else if (str.startsWith(
"TFL"))
1179 else if (str.startsWith(
"RAWTEXT"))
1191 str = QObject::tr(
"Audio Description",
1192 "On-screen events described for the visually impaired");
1195 str = QObject::tr(
"Clean Effects",
1196 "No dialog, background audio only");
1199 str = QObject::tr(
"Hearing Impaired",
1200 "Clear dialog for the hearing impaired");
1203 str = QObject::tr(
"Spoken Subtitles",
1204 "Subtitles are read out for the visually impaired");
1207 str = QObject::tr(
"Commentary",
"Director/Cast commentary track");
1211 str = QObject::tr(
"Normal",
"Ordinary audio track");
1239 float fallback_ratio)
1241 uint64_t key1, key2;
1242 uint64_t val1, val2;
1244 frm_pos_map_t::const_iterator lower = map.lowerBound(key);
1247 if (lower != map.begin() && (lower == map.end() || lower.key() > key))
1249 if (lower == map.end() || lower.key() > key)
1253 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
1254 QString(
"TranslatePosition(key=%1): extrapolating to (0,0)")
1260 val1 = lower.value();
1264 frm_pos_map_t::const_iterator upper = map.lowerBound(key);
1265 if (upper == map.end())
1269 val2 = llroundf(val1 + fallback_ratio * (key2 - key1));
1270 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
1271 QString(
"TranslatePosition(key=%1, ratio=%2): " 1272 "extrapolating to (%3,%4)")
1273 .arg(key).arg(fallback_ratio).arg(key2).arg(val2));
1279 val2 = upper.value();
1284 return llround(val1 + (
double) (key - key1) * (val2 - val1) / (key2 - key1));
1290 float fallback_framerate,
1303 if (position > it.key())
1306 (QDateTime::currentDateTime() >
1312 1000 / fallback_framerate);
1318 float fallback_framerate,
1325 1000 / fallback_framerate);
1342 uint64_t absPosition,
1344 float fallback_ratio)
1346 uint64_t subtraction = 0;
1347 uint64_t startOfCutRegion = 0;
1348 bool withinCut =
false;
1350 for (frm_dir_map_t::const_iterator i = deleteMap.begin();
1351 i != deleteMap.end(); ++i)
1356 if (i.key() > absPosition)
1362 startOfCutRegion = mappedKey;
1367 subtraction += (mappedKey - startOfCutRegion);
1372 subtraction += (mappedPos - startOfCutRegion);
1373 return mappedPos - subtraction;
1391 uint64_t relPosition,
1393 float fallback_ratio)
1395 uint64_t addition = 0;
1396 uint64_t startOfCutRegion = 0;
1397 bool withinCut =
false;
1399 for (frm_dir_map_t::const_iterator i = deleteMap.begin();
1400 i != deleteMap.end(); ++i)
1409 startOfCutRegion = mappedKey;
1410 if (relPosition + addition <= startOfCutRegion)
1416 addition += (mappedKey - startOfCutRegion);
1419 return relPosition + addition;
virtual bool DoFastForward(long long desiredFrame, bool doflush=true)
Skips ahead or rewinds to desiredFrame.
vector< int > languagePreference
language preferences for auto-selection of streams
bool ForcedSubtitlesFavored(void) const
void SetKeyframeDistance(int keyframedistance)
virtual bool DoRewind(long long desiredFrame, bool doflush=true)
ISO 639-1 and ISO 639-2 support functions.
void SaveTotalFrames(void)
void TracksChanged(uint trackType)
This tries to re-enable captions/subtitles if the user wants them and one of the captions/subtitles t...
A QElapsedTimer based timer to replace use of QTime as a timer.
long long GetLastFrameInPosMap(void) const
virtual void SetEofState(EofState eof)
const DVDRingBuffer * DVD(void) const
virtual void SeekReset(long long newkey, uint skipFrames, bool doFlush, bool discardFrames)
virtual bool IsInDiscMenuOrStillFrame(void) const
virtual bool GetFrame(DecodeType)=0
Demux, preprocess and possibly decode a frame of video/audio.
int to_track_type(const QString &str)
uint GetTotalTimeOfTitle(void)
get the total time of the title in seconds 90000 ticks = 1 sec
bool hasKeyFrameAdjustTable
QString iso639_key_toName(int iso639_2)
Converts a canonical key to language name in English.
MarkTypes positionMapType
uint64_t SavePositionMapDelta(long long first_frame, long long last_frame)
QString toString(TrackType type)
int currentTrack[kTrackTypeCount]
void SaveTotalDuration(void)
ProgramInfo * m_playbackinfo
uint64_t GetTotalReadPosition(void)
DecoderBase(MythPlayer *parent, const ProgramInfo &pginfo)
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)
QMap< uint64_t, MarkTypes > frm_dir_map_t
Frame # -> Mark map.
QDateTime m_lastPositionMapUpdate
void SaveTotalFrames(int64_t frames)
Store the Total Frames at frame 0 in the recordedmarkup table.
void SetFramesPlayed(uint64_t played)
void SetWaitForChange(void)
bool recordingHasPositionMap
void SetFileLength(int total, int frames)
Holds information on recordings and videos.
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)
virtual bool FindPosition(long long desired_value, bool search_adjusted, int &lower_bound, int &upper_bound)
StreamInfo wantedTrack[kTrackTypeCount]
frm_pos_map_t m_frameToDurMap
bool GetWaitForChange(void) const
uint TitleTimeLeft(void)
returns seconds left in the title
virtual bool InsertTrack(uint type, const StreamInfo &)
void FileChangedCallback()
virtual bool DoRewindSeek(long long desiredFrame)
enum TrackTypes TrackType
Track types.
virtual QString GetTrackDesc(uint type, uint trackNo) const
virtual void ResetPosMap(void)
virtual bool PosMapFromEnc(void)
Queries encoder for position map data that has not been committed to the DB yet.
double GetFrameRate(void)
long long GetTotalReadPosition(void)
sinfo_vec_t tracks[kTrackTypeCount]
virtual void UpdateFramesPlayed(void)
uint64_t TranslatePositionMsToFrame(uint64_t dur_ms, float fallback_framerate, const frm_dir_map_t &cutlist)
double GetFrameRate(void)
used by DecoderBase for the total frame number calculation for position map support and ffw/rew.
long long GetKey(const PosMapEntry &entry) const
void SetProgramInfo(const ProgramInfo &pginfo)
StreamInfo selectedTrack[(uint) kTrackTypeCount]
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...
unsigned long GetPositionMapSize(void) const
static uint64_t TranslatePosition(const frm_pos_map_t &map, long long key, float fallback_ratio)
int elapsed(void) const
Returns milliseconds elapsed since last start() or restart()
virtual bool SyncPositionMap(void)
Updates the position map used for skipping frames.
#define LOG(_MASK_, _LEVEL_, _STRING_)
vector< int > iso639_get_language_key_list(void)
frm_pos_map_t m_durToFrameMap
virtual void SetWatchingRecording(bool mode)
void SetReadAdjust(long long adjust)
StreamInfo GetTrackInfo(uint type, uint trackNo) const
vector< PosMapEntry > m_positionMap
QMutex * avcodeclock
This global variable is used to makes certain calls to avlib threadsafe.
virtual bool PosMapFromDb(void)
uint64_t TranslatePositionFrameToMs(long long position, float fallback_framerate, const frm_dir_map_t &cutlist)
virtual int SetTrack(uint type, int trackNo)
virtual int AutoSelectTrack(uint type)
Select best track.
QMap< long long, long long > frm_pos_map_t
Frame # -> File offset map.
void QueryPositionMap(frm_pos_map_t &, MarkTypes type) const
long long Seek(long long pos, int whence, bool has_lock=false)
Seeks to a particular position in the file.
const BDRingBuffer * BD(void) const
void start(void)
starts measuring elapsed time.
virtual void Reset(bool reset_video_data, bool seek_reset, bool reset_file)
bool PosMapFromEnc(uint64_t start, frm_pos_map_t &posMap, frm_pos_map_t &durMap)
uint64_t GetTotalTimeOfTitle(void) const
virtual QStringList GetTracks(uint type) const
int language
ISO639 canonical language key.
void SaveTotalDuration(int64_t duration)
Store the Total Duration at frame 0 in the recordedmarkup table.
AVRational AVRationalInit(int num, int den=1)
long long ConditionallyUpdatePosMap(long long desiredFrame)
void SavePositionMapDelta(frm_pos_map_t &, MarkTypes type) const
virtual int GetTrackLanguageIndex(uint type, uint trackNo) const