diff --git a/mythtv/libs/libmythbase/mythversion.h b/mythtv/libs/libmythbase/mythversion.h index 84dd4602ff9..5eec821e520 100644 --- a/mythtv/libs/libmythbase/mythversion.h +++ b/mythtv/libs/libmythbase/mythversion.h @@ -12,7 +12,7 @@ /// Update this whenever the plug-in API changes. /// Including changes in the libmythbase, libmyth, libmythtv, libmythav* and /// libmythui class methods used by plug-ins. -#define MYTH_BINARY_VERSION "0.27.20121231-1" +#define MYTH_BINARY_VERSION "0.27.20130102-1" /** \brief Increment this whenever the MythTV network protocol changes. * diff --git a/mythtv/libs/libmythtv/decoderbase.cpp b/mythtv/libs/libmythtv/decoderbase.cpp index b5daa57d071..e77a3c7e94e 100644 --- a/mythtv/libs/libmythtv/decoderbase.cpp +++ b/mythtv/libs/libmythtv/decoderbase.cpp @@ -425,6 +425,10 @@ bool DecoderBase::SyncPositionMap(void) .arg(totframes).arg(length).arg(new_posmap_size)); } recordingHasPositionMap |= (0 != new_posmap_size); + { + QMutexLocker locker(&m_positionMapLock); + m_lastPositionMapUpdate = QDateTime::currentDateTime(); + } return ret_val; } @@ -1265,9 +1269,25 @@ uint64_t DecoderBase::TranslatePosition(const frm_pos_map_t &map, uint64_t DecoderBase::TranslatePositionFrameToMs(uint64_t position, float fallback_framerate, const frm_dir_map_t &cutlist) - const { QMutexLocker locker(&m_positionMapLock); + // Accurate calculation of duration requires an up-to-date + // duration map. However, the last frame (total duration) will + // almost always appear to be past the end of the duration map, so + // we limit duration map syncing to once every 3 seconds (a + // somewhat arbitrary value). + if (!m_frameToDurMap.empty()) + { + frm_pos_map_t::const_iterator it = m_frameToDurMap.end(); + --it; + if (position > it.key()) + { + if (!m_lastPositionMapUpdate.isValid() || + (QDateTime::currentDateTime() > + m_lastPositionMapUpdate.addSecs(3))) + SyncPositionMap(); + } + } return TranslatePositionAbsToRel(cutlist, position, m_frameToDurMap, 1000 / fallback_framerate); } @@ -1277,7 +1297,6 @@ uint64_t DecoderBase::TranslatePositionFrameToMs(uint64_t position, uint64_t DecoderBase::TranslatePositionMsToFrame(uint64_t dur_ms, float fallback_framerate, const frm_dir_map_t &cutlist) - const { QMutexLocker locker(&m_positionMapLock); // Convert relative position in milliseconds (cutlist-adjusted) to diff --git a/mythtv/libs/libmythtv/decoderbase.h b/mythtv/libs/libmythtv/decoderbase.h index 4ac2c63834a..4f8a01a272d 100644 --- a/mythtv/libs/libmythtv/decoderbase.h +++ b/mythtv/libs/libmythtv/decoderbase.h @@ -156,10 +156,10 @@ class DecoderBase float fallback_ratio); uint64_t TranslatePositionFrameToMs(uint64_t position, float fallback_framerate, - const frm_dir_map_t &cutlist) const; + const frm_dir_map_t &cutlist); uint64_t TranslatePositionMsToFrame(uint64_t dur_ms, float fallback_framerate, - const frm_dir_map_t &cutlist) const; + const frm_dir_map_t &cutlist); float GetVideoAspect(void) const { return current_aspect; } @@ -297,6 +297,7 @@ class DecoderBase frm_pos_map_t m_frameToDurMap; // guarded by m_positionMapLock frm_pos_map_t m_durToFrameMap; // guarded by m_positionMapLock bool dontSyncPositionMap; + mutable QDateTime m_lastPositionMapUpdate; // guarded by m_positionMapLock uint64_t seeksnap; bool livetv; diff --git a/mythtv/libs/libmythtv/mythplayer.cpp b/mythtv/libs/libmythtv/mythplayer.cpp index ca2a7847a0f..a34bd31733c 100644 --- a/mythtv/libs/libmythtv/mythplayer.cpp +++ b/mythtv/libs/libmythtv/mythplayer.cpp @@ -4711,7 +4711,7 @@ void MythPlayer::calcSliderPos(osdInfo &info, bool paddedFields) } else if (IsWatchingInprogress()) { - total_frames = player_ctx->recorder->GetFramesWritten(); + total_frames = -1; islive = true; } else @@ -4814,6 +4814,24 @@ void MythPlayer::calcSliderPos(osdInfo &info, bool paddedFields) } } +// If position == -1, it signifies that we are computing the current +// duration of an in-progress recording. In this case, we fetch the +// current frame rate and frame count from the recorder. +uint64_t MythPlayer::TranslatePositionFrameToMs(uint64_t position, + bool use_cutlist) const +{ + float frameRate = GetFrameRate(); + if (position == -1) + { + float recorderFrameRate = player_ctx->recorder->GetFrameRate(); + if (recorderFrameRate > 0) + frameRate = recorderFrameRate; + position = player_ctx->recorder->GetFramesWritten(); + } + return deleteMap.TranslatePositionFrameToMs(position, frameRate, + use_cutlist); +} + int MythPlayer::GetNumChapters() { if (decoder) diff --git a/mythtv/libs/libmythtv/mythplayer.h b/mythtv/libs/libmythtv/mythplayer.h index 5f3cb3c9b50..bf27f482b06 100644 --- a/mythtv/libs/libmythtv/mythplayer.h +++ b/mythtv/libs/libmythtv/mythplayer.h @@ -393,11 +393,7 @@ class MTV_PUBLIC MythPlayer long long CalcRWTime(long long rw) const; virtual void calcSliderPos(osdInfo &info, bool paddedFields = false); uint64_t TranslatePositionFrameToMs(uint64_t position, - bool use_cutlist) const { - return deleteMap.TranslatePositionFrameToMs(position, - GetFrameRate(), - use_cutlist); - } + bool use_cutlist) const; uint64_t TranslatePositionMsToFrame(uint64_t position, bool use_cutlist) const { return deleteMap.TranslatePositionMsToFrame(position, diff --git a/mythtv/libs/libmythtv/recorders/recorderbase.h b/mythtv/libs/libmythtv/recorders/recorderbase.h index 972eced58c2..981e74ca048 100644 --- a/mythtv/libs/libmythtv/recorders/recorderbase.h +++ b/mythtv/libs/libmythtv/recorders/recorderbase.h @@ -189,13 +189,9 @@ class MTV_PUBLIC RecorderBase : public QRunnable virtual bool IsPaused(bool holding_lock = false) const; virtual bool WaitForPause(int timeout = 1000); - /** \brief Returns an approximation of the frame rate. - * - * \bug This can be off by at least half, our non-frame grabber based - * recorders do not not try to approximate the frame rate. So - * a 720p recording at 60fps will report a frame-rate of 25fps. + /** \brief Returns the latest frame rate. */ - double GetFrameRate(void) { return video_frame_rate; } + double GetFrameRate(void) { return m_frameRate / 1000; } /** \brief If requested, switch to new RingBuffer/ProgramInfo objects */