From 9dacccd1940abd5fa0c6dc5007aecdd5ffb114b5 Mon Sep 17 00:00:00 2001 From: enen92 <92enen@gmail.com> Date: Mon, 24 Jun 2024 14:34:22 +0100 Subject: [EDL] Use std::chrono --- xbmc/cores/DataCacheCore.cpp | 9 +- xbmc/cores/DataCacheCore.h | 20 ++-- xbmc/cores/EdlEdit.h | 6 +- xbmc/cores/VideoPlayer/Edl.cpp | 154 ++++++++++++++++------------ xbmc/cores/VideoPlayer/Edl.h | 35 ++++--- xbmc/cores/VideoPlayer/VideoPlayer.cpp | 90 +++++++++------- xbmc/cores/VideoPlayer/test/edl/TestEdl.cpp | 123 ++++++++++++---------- xbmc/guilib/guiinfo/PlayerGUIInfo.cpp | 13 +-- xbmc/pvr/PVREdl.cpp | 6 +- 9 files changed, 259 insertions(+), 197 deletions(-) diff --git a/xbmc/cores/DataCacheCore.cpp b/xbmc/cores/DataCacheCore.cpp index 8eb961733b..4a01f8fbb9 100644 --- a/xbmc/cores/DataCacheCore.cpp +++ b/xbmc/cores/DataCacheCore.cpp @@ -11,6 +11,7 @@ #include "ServiceBroker.h" #include "cores/EdlEdit.h" +#include #include #include @@ -271,25 +272,25 @@ const std::vector& CDataCacheCore::GetEditList() const return m_contentInfo.GetEditList(); } -void CDataCacheCore::SetCuts(const std::vector& cuts) +void CDataCacheCore::SetCuts(const std::vector& cuts) { std::unique_lock lock(m_contentSection); m_contentInfo.SetCuts(cuts); } -const std::vector& CDataCacheCore::GetCuts() const +const std::vector& CDataCacheCore::GetCuts() const { std::unique_lock lock(m_contentSection); return m_contentInfo.GetCuts(); } -void CDataCacheCore::SetSceneMarkers(const std::vector& sceneMarkers) +void CDataCacheCore::SetSceneMarkers(const std::vector& sceneMarkers) { std::unique_lock lock(m_contentSection); m_contentInfo.SetSceneMarkers(sceneMarkers); } -const std::vector& CDataCacheCore::GetSceneMarkers() const +const std::vector& CDataCacheCore::GetSceneMarkers() const { std::unique_lock lock(m_contentSection); return m_contentInfo.GetSceneMarkers(); diff --git a/xbmc/cores/DataCacheCore.h b/xbmc/cores/DataCacheCore.h index c09d7fcf10..5a4b1509e9 100644 --- a/xbmc/cores/DataCacheCore.h +++ b/xbmc/cores/DataCacheCore.h @@ -86,25 +86,25 @@ public: * @brief Set the list of cut markers in cache. * @return The list of cuts or an empty list if no cuts exist */ - void SetCuts(const std::vector& cuts); + void SetCuts(const std::vector& cuts); /*! * @brief Get the list of cut markers from cache. * @return The list of cut markers or an empty vector if no cuts exist. */ - const std::vector& GetCuts() const; + const std::vector& GetCuts() const; /*! * @brief Set the list of scene markers in cache. * @return The list of scene markers or an empty list if no scene markers exist */ - void SetSceneMarkers(const std::vector& sceneMarkers); + void SetSceneMarkers(const std::vector& sceneMarkers); /*! * @brief Get the list of scene markers markers from cache. * @return The list of scene markers or an empty vector if no scene exist. */ - const std::vector& GetSceneMarkers() const; + const std::vector& GetSceneMarkers() const; void SetChapters(const std::vector>& chapters); @@ -242,19 +242,19 @@ protected: * @brief Save the list of cut markers in cache. * @param cuts the list of cut markers to store in cache */ - void SetCuts(const std::vector& cuts) { m_cuts = cuts; } + void SetCuts(const std::vector& cuts) { m_cuts = cuts; } /*! * @brief Get the list of cut markers in cache. * @return the list of cut markers in cache */ - const std::vector& GetCuts() const { return m_cuts; } + const std::vector& GetCuts() const { return m_cuts; } /*! * @brief Save the list of scene markers in cache. * @param sceneMarkers the list of scene markers to store in cache */ - void SetSceneMarkers(const std::vector& sceneMarkers) + void SetSceneMarkers(const std::vector& sceneMarkers) { m_sceneMarkers = sceneMarkers; } @@ -263,7 +263,7 @@ protected: * @brief Get the list of scene markers in cache. * @return the list of scene markers in cache */ - const std::vector& GetSceneMarkers() const { return m_sceneMarkers; } + const std::vector& GetSceneMarkers() const { return m_sceneMarkers; } /*! * @brief Save the chapter list in cache. @@ -297,9 +297,9 @@ protected: /*!< name and position for chapters */ std::vector> m_chapters; /*!< position for EDL cuts */ - std::vector m_cuts; + std::vector m_cuts; /*!< position for EDL scene markers */ - std::vector m_sceneMarkers; + std::vector m_sceneMarkers; } m_contentInfo; CCriticalSection m_renderSection; diff --git a/xbmc/cores/EdlEdit.h b/xbmc/cores/EdlEdit.h index a06ed1572a..74ad3521be 100644 --- a/xbmc/cores/EdlEdit.h +++ b/xbmc/cores/EdlEdit.h @@ -8,6 +8,8 @@ #pragma once +#include + namespace EDL { @@ -23,8 +25,8 @@ enum class Action struct Edit { - int start = 0; // ms - int end = 0; // ms + std::chrono::milliseconds start{0}; + std::chrono::milliseconds end{0}; Action action = Action::CUT; }; diff --git a/xbmc/cores/VideoPlayer/Edl.cpp b/xbmc/cores/VideoPlayer/Edl.cpp index 0252611442..68cd40bf63 100644 --- a/xbmc/cores/VideoPlayer/Edl.cpp +++ b/xbmc/cores/VideoPlayer/Edl.cpp @@ -20,6 +20,8 @@ #include "utils/XBMCTinyXML2.h" #include "utils/log.h" +#include + #include "PlatformDefs.h" #define COMSKIP_HEADER "FILE PROCESSING COMPLETE" @@ -27,6 +29,7 @@ #define VIDEOREDO_TAG_CUT "" #define VIDEOREDO_TAG_SCENE " fieldParts = StringUtils::Split(strFields[i], '.'); if (fieldParts.size() == 1) // No ms { - editStartEnd[i] = StringUtils::TimeStringToSeconds(fieldParts[0]) * - static_cast(1000); // seconds to ms + editStartEnd[i] = std::chrono::duration_cast( + std::chrono::seconds(StringUtils::TimeStringToSeconds(fieldParts[0]))); } else if (fieldParts.size() == 2) // Has ms. Everything after the dot (.) is ms { @@ -179,9 +182,12 @@ bool CEdl::ReadEdl(const std::string& mediaFilePath, float fps) { fieldParts[1] = fieldParts[1].substr(0, 3); } - editStartEnd[i] = - static_cast(StringUtils::TimeStringToSeconds(fieldParts[0])) * 1000 + - std::atoi(fieldParts[1].c_str()); // seconds to ms + int additionalMs{0}; + editStartEnd[i] = std::chrono::duration_cast( + std::chrono::seconds(StringUtils::TimeStringToSeconds(fieldParts[0]))); + std::from_chars(fieldParts[1].data(), fieldParts[1].data() + fieldParts[1].size(), + additionalMs); + editStartEnd[i] += std::chrono::milliseconds(additionalMs); } else { @@ -193,8 +199,10 @@ bool CEdl::ReadEdl(const std::string& mediaFilePath, float fps) { if (fps > 0.0f) { - editStartEnd[i] = static_cast(std::atol(strFields[i].substr(1).c_str()) / fps * - 1000); // frame number to ms + std::chrono::duration> durationInSeconds{ + std::atol(strFields[i].substr(1).c_str()) / fps}; + editStartEnd[i] = + std::chrono::duration_cast(durationInSeconds); } else { @@ -207,7 +215,8 @@ bool CEdl::ReadEdl(const std::string& mediaFilePath, float fps) } else // Plain old seconds in float format, e.g. 123.45 { - editStartEnd[i] = std::lround(std::atof(strFields[i].c_str()) * 1000); // seconds to ms + editStartEnd[i] = + std::chrono::milliseconds{std::lround(std::atof(strFields[i].c_str()) * 1000)}; } } @@ -344,8 +353,13 @@ bool CEdl::ReadComskip(const std::string& mediaFilePath, float fps) if (sscanf(szBuffer, "%lf %lf", &dStartFrame, &dEndFrame) == 2) { Edit edit; - edit.start = std::lround(dStartFrame / static_cast(fFrameRate) * 1000.0); - edit.end = std::lround(dEndFrame / static_cast(fFrameRate) * 1000.0); + edit.start = std::chrono::duration_cast( + std::chrono::duration>{dStartFrame / + static_cast(fFrameRate)}); + edit.end = std::chrono::duration_cast( + std::chrono::duration_cast( + std::chrono::duration>{dEndFrame / + static_cast(fFrameRate)})); edit.action = Action::COMM_BREAK; bValid = AddEdit(edit); } @@ -427,8 +441,8 @@ bool CEdl::ReadVideoReDo(const std::string& mediaFilePath) * Times need adjusting by 1/10,000 to get ms. */ Edit edit; - edit.start = std::lround(dStart / 10000); - edit.end = std::lround(dEnd / 10000); + edit.start = std::chrono::milliseconds(std::lround(dStart / 10000)); + edit.end = std::chrono::milliseconds(std::lround(dEnd / 10000)); edit.action = Action::CUT; bValid = AddEdit(edit); } @@ -440,8 +454,8 @@ bool CEdl::ReadVideoReDo(const std::string& mediaFilePath) int iScene; double dSceneMarker; if (sscanf(szBuffer + strlen(VIDEOREDO_TAG_SCENE), " %i>%lf", &iScene, &dSceneMarker) == 2) - bValid = AddSceneMarker( - std::lround(dSceneMarker / 10000)); // Times need adjusting by 1/10,000 to get ms. + bValid = AddSceneMarker(std::chrono::milliseconds( + std::lround(dSceneMarker / 10000))); // Times need adjusting by 1/10,000 to get ms. else bValid = false; } @@ -528,8 +542,10 @@ bool CEdl::ReadBeyondTV(const std::string& mediaFilePath) * atof() returns 0 if there were any problems and will subsequently be rejected in AddEdit(). */ Edit edit; - edit.start = std::lround((std::atof(start->FirstChild()->Value()) / 10000)); - edit.end = std::lround((std::atof(end->FirstChild()->Value()) / 10000)); + edit.start = + std::chrono::milliseconds(std::lround((std::atof(start->FirstChild()->Value()) / 10000))); + edit.end = + std::chrono::milliseconds(std::lround((std::atof(end->FirstChild()->Value()) / 10000))); edit.action = Action::COMM_BREAK; valid = AddEdit(edit); } @@ -616,7 +632,7 @@ bool CEdl::AddEdit(const Edit& newEdit) return false; } - if (edit.start < 0) + if (edit.start < 0ms) { CLog::Log(LOGERROR, "{} - Before start! [{} - {}], {}", __FUNCTION__, MillisecondsToTimeString(edit.start), MillisecondsToTimeString(edit.end), @@ -658,20 +674,24 @@ bool CEdl::AddEdit(const Edit& newEdit) * the start (autowait) and automatically rewind by a bit (autowind) at the end of the commercial * break. */ - int autowait = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_iEdlCommBreakAutowait * 1000; // seconds -> ms - int autowind = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_iEdlCommBreakAutowind * 1000; // seconds -> ms - - if (edit.start > 0) // Only autowait if not at the start. + auto autowait = std::chrono::duration_cast(std::chrono::seconds( + CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_iEdlCommBreakAutowait)); + std::chrono::milliseconds autowind = std::chrono::duration_cast( + std::chrono::seconds(CServiceBroker::GetSettingsComponent() + ->GetAdvancedSettings() + ->m_iEdlCommBreakAutowind)); + + if (edit.start > 0ms) // Only autowait if not at the start. { /* get the edit length so we don't start skipping after the end */ - int editLength = edit.end - edit.start; + std::chrono::milliseconds editLength = edit.end - edit.start; /* add the lesser of the edit length or the autowait to the start */ edit.start += autowait > editLength ? editLength : autowait; } if (edit.end > edit.start) // Only autowind if there is any edit time remaining. { /* get the remaining edit length so we don't rewind to before the start */ - int editLength = edit.end - edit.start; + std::chrono::milliseconds editLength = edit.end - edit.start; /* subtract the lesser of the edit length or the autowind from the end */ edit.end -= autowind > editLength ? editLength : autowind; } @@ -709,7 +729,7 @@ bool CEdl::AddEdit(const Edit& newEdit) return true; } -bool CEdl::AddSceneMarker(int iSceneMarker) +bool CEdl::AddSceneMarker(std::chrono::milliseconds iSceneMarker) { const auto edit = InEdit(iSceneMarker); if (edit && edit.value()->action == Action::CUT) // Only works for current cuts. @@ -729,10 +749,10 @@ bool CEdl::HasEdits() const bool CEdl::HasCuts() const { - return m_totalCutTime > 0; + return m_totalCutTime > 0ms; } -int CEdl::GetTotalCutTime() const +std::chrono::milliseconds CEdl::GetTotalCutTime() const { return m_totalCutTime; // ms } @@ -741,7 +761,7 @@ const std::vector CEdl::GetEditList() const { // the sum of cut durations while we iterate over them // note: edits are ordered by start time - int surpassedSumOfCutDurations{0}; + std::chrono::milliseconds surpassedSumOfCutDurations{0ms}; std::vector editList; // @note we should not modify the original edits since @@ -757,7 +777,7 @@ const std::vector CEdl::GetEditList() const continue; } - // substract the duration of already surpassed cuts + // subtract the duration of already surpassed cuts edit.start -= surpassedSumOfCutDurations; edit.end -= surpassedSumOfCutDurations; editList.emplace_back(edit); @@ -766,10 +786,10 @@ const std::vector CEdl::GetEditList() const return editList; } -const std::vector CEdl::GetCutMarkers() const +const std::vector CEdl::GetCutMarkers() const { - int surpassedSumOfCutDurations{0}; - std::vector cutList; + std::chrono::milliseconds surpassedSumOfCutDurations{0}; + std::vector cutList; for (const EDL::Edit& edit : m_vecEdits) { if (edit.action != Action::CUT) @@ -781,23 +801,23 @@ const std::vector CEdl::GetCutMarkers() const return cutList; } -const std::vector CEdl::GetSceneMarkers() const +const std::vector CEdl::GetSceneMarkers() const { - std::vector sceneMarkers; + std::vector sceneMarkers; sceneMarkers.reserve(m_vecSceneMarkers.size()); - for (const int& scene : m_vecSceneMarkers) + for (const std::chrono::milliseconds& scene : m_vecSceneMarkers) { sceneMarkers.emplace_back(GetTimeWithoutCuts(scene)); } return sceneMarkers; } -int CEdl::GetTimeWithoutCuts(int seek) const +std::chrono::milliseconds CEdl::GetTimeWithoutCuts(std::chrono::milliseconds seek) const { if (!HasCuts()) return seek; - int cutTime = 0; + std::chrono::milliseconds cutTime = 0ms; for (const EDL::Edit& edit : m_vecEdits) { if (edit.action != Action::CUT) @@ -806,8 +826,8 @@ int CEdl::GetTimeWithoutCuts(int seek) const // inside cut if (seek >= edit.start && seek <= edit.end) { - // decrease cut lenght by 1 ms to jump over the end boundary. - cutTime += seek - edit.start - 1; + // decrease cut length by 1 ms to jump over the end boundary. + cutTime += seek - edit.start - 1ms; } // cut has already been passed over else if (seek >= edit.start) @@ -818,16 +838,16 @@ int CEdl::GetTimeWithoutCuts(int seek) const return seek - cutTime; } -double CEdl::GetTimeAfterRestoringCuts(double seek) const +std::chrono::milliseconds CEdl::GetTimeAfterRestoringCuts(std::chrono::milliseconds seek) const { if (!HasCuts()) return seek; for (const EDL::Edit& edit : m_vecEdits) { - double cutDuration = static_cast(edit.end - edit.start); + std::chrono::milliseconds cutDuration = edit.end - edit.start; // add 1 ms to jump over the start boundary - if (edit.action == Action::CUT && seek > edit.start + 1) + if (edit.action == Action::CUT && seek > edit.start + 1ms) { seek += cutDuration; } @@ -840,7 +860,7 @@ bool CEdl::HasSceneMarker() const return !m_vecSceneMarkers.empty(); } -std::optional> CEdl::InEdit(const int seekTime) +std::optional> CEdl::InEdit(std::chrono::milliseconds seekTime) { for (size_t i = 0; i < m_vecEdits.size(); ++i) { @@ -854,19 +874,19 @@ std::optional> CEdl::InEdit(const int seekTime) return std::nullopt; } -int CEdl::GetLastEditTime() const +std::optional CEdl::GetLastEditTime() const { return m_lastEditTime; } -void CEdl::SetLastEditTime(int editTime) +void CEdl::SetLastEditTime(std::chrono::milliseconds editTime) { m_lastEditTime = editTime; } void CEdl::ResetLastEditTime() { - m_lastEditTime = -1; + m_lastEditTime = std::nullopt; } void CEdl::SetLastEditActionType(EDL::Action action) @@ -879,15 +899,17 @@ EDL::Action CEdl::GetLastEditActionType() const return m_lastEditActionType; } -std::optional CEdl::GetNextSceneMarker(Direction direction, int clock) +std::optional CEdl::GetNextSceneMarker(Direction direction, + std::chrono::milliseconds clock) { if (!HasSceneMarker()) return std::nullopt; - std::optional sceneMarker; - const int seekTime = GetTimeAfterRestoringCuts(clock); + std::optional sceneMarker; + const std::chrono::milliseconds seekTime = GetTimeAfterRestoringCuts(clock); - int diff = 10 * 60 * 60 * 1000; // 10 hours to ms. + std::chrono::milliseconds diff = + std::chrono::milliseconds(10 * 60 * 60 * 1000); // 10 hours to ms. if (direction == Direction::FORWARD) // Find closest scene forwards { @@ -928,11 +950,11 @@ std::optional CEdl::GetNextSceneMarker(Direction direction, int clock) return sceneMarker; } -std::string CEdl::MillisecondsToTimeString(int milliSeconds) +std::string CEdl::MillisecondsToTimeString(std::chrono::milliseconds milliSeconds) { std::string strTimeString = StringUtils::SecondsToTimeString( - static_cast(milliSeconds / 1000), TIME_FORMAT_HH_MM_SS); // milliseconds to seconds - strTimeString += StringUtils::Format(".{:03}", milliSeconds % 1000); + std::chrono::duration_cast(milliSeconds).count(), TIME_FORMAT_HH_MM_SS); + strTimeString += StringUtils::Format(".{:03}", milliSeconds.count() % 1000); return strTimeString; } @@ -945,7 +967,7 @@ void CEdl::MergeShortCommBreaks() * the algorithms below. */ if (!m_vecEdits.empty() && m_vecEdits[0].action == Action::COMM_BREAK && - (m_vecEdits[0].end - m_vecEdits[0].start) < 5 * 1000) // 5 seconds + (m_vecEdits[0].end - m_vecEdits[0].start) < 5s) { CLog::Log(LOGDEBUG, "{} - Removing short commercial break at start [{} - {}]. <5 seconds", __FUNCTION__, MillisecondsToTimeString(m_vecEdits[0].start), @@ -961,9 +983,11 @@ void CEdl::MergeShortCommBreaks() if ((m_vecEdits[i].action == Action::COMM_BREAK && m_vecEdits[i + 1].action == Action::COMM_BREAK) && (m_vecEdits[i + 1].end - m_vecEdits[i].start < - advancedSettings->m_iEdlMaxCommBreakLength * 1000) // s to ms - && (m_vecEdits[i + 1].start - m_vecEdits[i].end < - advancedSettings->m_iEdlMaxCommBreakGap * 1000)) // s to ms + std::chrono::duration_cast( + std::chrono::seconds(advancedSettings->m_iEdlMaxCommBreakLength))) && + (m_vecEdits[i + 1].start - m_vecEdits[i].end < + std::chrono::duration_cast( + std::chrono::seconds(advancedSettings->m_iEdlMaxCommBreakGap)))) { Edit commBreak; commBreak.action = Action::COMM_BREAK; @@ -995,12 +1019,13 @@ void CEdl::MergeShortCommBreaks() * the maximum commercial break length being triggered. */ if (!m_vecEdits.empty() && m_vecEdits[0].action == Action::COMM_BREAK && - m_vecEdits[0].start < advancedSettings->m_iEdlMaxStartGap * 1000) + m_vecEdits[0].start < std::chrono::duration_cast( + std::chrono::seconds(advancedSettings->m_iEdlMaxStartGap))) { CLog::Log(LOGDEBUG, "{} - Expanding first commercial break back to start [{} - {}].", __FUNCTION__, MillisecondsToTimeString(m_vecEdits[0].start), MillisecondsToTimeString(m_vecEdits[0].end)); - m_vecEdits[0].start = 0; + m_vecEdits[0].start = 0ms; } /* @@ -1008,9 +1033,10 @@ void CEdl::MergeShortCommBreaks() */ for (size_t i = 0; i < m_vecEdits.size(); ++i) { - if (m_vecEdits[i].action == Action::COMM_BREAK && m_vecEdits[i].start > 0 && + if (m_vecEdits[i].action == Action::COMM_BREAK && m_vecEdits[i].start > 0ms && (m_vecEdits[i].end - m_vecEdits[i].start) < - advancedSettings->m_iEdlMinCommBreakLength * 1000) + std::chrono::duration_cast( + std::chrono::seconds(advancedSettings->m_iEdlMinCommBreakLength))) { CLog::Log(LOGDEBUG, "{} - Removing short commercial break [{} - {}]. Minimum length: {} seconds", @@ -1033,7 +1059,7 @@ void CEdl::AddSceneMarkersAtStartAndEndOfEdits() if (edit.action == Action::COMM_BREAK) { // Don't add a scene marker at the start. - if (edit.start > 0) + if (edit.start > 0ms) AddSceneMarker(edit.start); AddSceneMarker(edit.end); } diff --git a/xbmc/cores/VideoPlayer/Edl.h b/xbmc/cores/VideoPlayer/Edl.h index 01abf3a3db..eaf5e295d1 100644 --- a/xbmc/cores/VideoPlayer/Edl.h +++ b/xbmc/cores/VideoPlayer/Edl.h @@ -45,7 +45,7 @@ public: * because of EDL cuts * @return the total cut time */ - int GetTotalCutTime() const; + std::chrono::milliseconds GetTotalCutTime() const; /*! * @brief Providing a given seek time, return the actual time without @@ -55,7 +55,7 @@ public: * @param seek the desired seek time * @return the seek time without considering EDL cut blocks */ - int GetTimeWithoutCuts(int seek) const; + std::chrono::milliseconds GetTimeWithoutCuts(std::chrono::milliseconds seekTime) const; /*! * @brief Provided a given seek time, return the time after correction with @@ -66,7 +66,7 @@ public: * @return the seek time after applying the cut blocks already surpassed by the * provided seek time */ - double GetTimeAfterRestoringCuts(double seek) const; + std::chrono::milliseconds GetTimeAfterRestoringCuts(std::chrono::milliseconds seekTime) const; /*! * @brief Get the raw EDL edit list. @@ -90,7 +90,7 @@ public: * has multiple cuts, the positions of subsquent cuts are automatically corrected by * substracting the previous cut durations. */ - const std::vector GetCutMarkers() const; + const std::vector GetCutMarkers() const; /*! * @brief Get the list of EDL scene markers. @@ -99,7 +99,7 @@ public: * has multiple cuts, the positions of scene markers are automatically corrected by * substracting the surpassed cut durations until the scene marker point. */ - const std::vector GetSceneMarkers() const; + const std::vector GetSceneMarkers() const; /*! * @brief Check if for the provided seek time is contained within an EDL @@ -109,24 +109,24 @@ public: * @param seekTime The seek time (on the original timeline) * @return a pointer to the edit struct if seekTime is within an edit, nullopt otherwise */ - std::optional> InEdit(int seekTime); + std::optional> InEdit(std::chrono::milliseconds seekTime); /*! * @brief Get the last processed edit time (set during playback when a given * edit is surpassed) - * @return The last processed edit time (ms) or -1 if not any + * @return The last processed edit time or nullopt if not any */ - int GetLastEditTime() const; + std::optional GetLastEditTime() const; /*! * @brief Set the last processed edit time (set during playback when a given * edit is surpassed) - * @param editTime The last processed EDL edit time (ms) + * @param editTime The last processed EDL edit time */ - void SetLastEditTime(int editTime); + void SetLastEditTime(std::chrono::milliseconds editTime); /*! - * @brief Reset the last recorded edit time (-1) + * @brief Reset the last recorded edit time (nullopt) */ void ResetLastEditTime(); @@ -149,20 +149,21 @@ public: * @param clock the current position of the clock * @return the position of the scenemarker (nullopt if none) */ - std::optional GetNextSceneMarker(Direction direction, int clock); + std::optional GetNextSceneMarker(Direction direction, + std::chrono::milliseconds clockTime); - static std::string MillisecondsToTimeString(int milliSeconds); + static std::string MillisecondsToTimeString(std::chrono::milliseconds milliSeconds); private: // total cut time (edl cuts) in ms - int m_totalCutTime; + std::chrono::milliseconds m_totalCutTime; std::vector m_vecEdits; - std::vector m_vecSceneMarkers; + std::vector m_vecSceneMarkers; /*! * @brief Last processed EDL edit time (ms) */ - int m_lastEditTime; + std::optional m_lastEditTime; /*! * @brief Last processed EDL edit action type @@ -182,7 +183,7 @@ private: */ bool AddEdit(const EDL::Edit& newEdit); - bool AddSceneMarker(int sceneMarker); + bool AddSceneMarker(std::chrono::milliseconds sceneMarker); void MergeShortCommBreaks(); diff --git a/xbmc/cores/VideoPlayer/VideoPlayer.cpp b/xbmc/cores/VideoPlayer/VideoPlayer.cpp index 77b15e6eeb..1deb7d2ba7 100644 --- a/xbmc/cores/VideoPlayer/VideoPlayer.cpp +++ b/xbmc/cores/VideoPlayer/VideoPlayer.cpp @@ -65,6 +65,7 @@ #include "video/VideoInfoTag.h" #include "windowing/WinSystem.h" +#include #include #include #include @@ -1281,22 +1282,24 @@ void CVideoPlayer::Prepare() * if there was a start time specified as part of the "Start from where last stopped" (aka * auto-resume) feature or if there is an EDL cut or commercial break that starts at time 0. */ - int starttime = 0; + std::chrono::milliseconds starttime = 0ms; if (m_playerOptions.starttime > 0 || m_playerOptions.startpercent > 0) { if (m_playerOptions.startpercent > 0 && m_pDemuxer) { - int playerStartTime = static_cast((static_cast( - m_pDemuxer->GetStreamLength() * (m_playerOptions.startpercent / 100.0)))); + std::chrono::milliseconds playerStartTime = + std::chrono::milliseconds(static_cast((static_cast( + m_pDemuxer->GetStreamLength() * (m_playerOptions.startpercent / 100.0))))); starttime = m_Edl.GetTimeAfterRestoringCuts(playerStartTime); } else { - starttime = m_Edl.GetTimeAfterRestoringCuts( - static_cast(m_playerOptions.starttime * 1000)); // s to ms + starttime = + m_Edl.GetTimeAfterRestoringCuts(std::chrono::duration_cast( + std::chrono::seconds(static_cast(m_playerOptions.starttime)))); } CLog::Log(LOGDEBUG, "{} - Start position set to last stopped position: {}", __FUNCTION__, - starttime); + starttime.count()); } else { @@ -1312,7 +1315,7 @@ void CVideoPlayer::Prepare() { starttime = edit->end; CLog::Log(LOGDEBUG, "{} - Start position set to end of first cut: {}", __FUNCTION__, - starttime); + starttime.count()); } else if (edit->action == EDL::Action::COMM_BREAK) { @@ -1320,7 +1323,7 @@ void CVideoPlayer::Prepare() { starttime = edit->end; CLog::Log(LOGDEBUG, "{} - Start position set to end of first commercial break: {}", - __FUNCTION__, starttime); + __FUNCTION__, starttime.count()); } const std::shared_ptr advancedSettings = @@ -1328,37 +1331,39 @@ void CVideoPlayer::Prepare() if (advancedSettings && advancedSettings->m_EdlDisplayCommbreakNotifications) { const std::string timeString = - StringUtils::SecondsToTimeString(edit->end / 1000, TIME_FORMAT_MM_SS); + StringUtils::SecondsToTimeString(edit->end.count(), TIME_FORMAT_MM_SS); CGUIDialogKaiToast::QueueNotification(g_localizeStrings.Get(25011), timeString); } } } } - if (starttime > 0) + if (starttime > 0ms) { double startpts = DVD_NOPTS_VALUE; if (m_pDemuxer) { - if (m_pDemuxer->SeekTime(starttime, true, &startpts)) + if (m_pDemuxer->SeekTime(starttime.count(), true, &startpts)) { - FlushBuffers(starttime / 1000 * AV_TIME_BASE, true, true); - CLog::Log(LOGDEBUG, "{} - starting demuxer from: {}", __FUNCTION__, starttime); + FlushBuffers(starttime.count() / 1000 * AV_TIME_BASE, true, true); + CLog::Log(LOGDEBUG, "{} - starting demuxer from: {}", __FUNCTION__, starttime.count()); } else - CLog::Log(LOGDEBUG, "{} - failed to start demuxing from: {}", __FUNCTION__, starttime); + CLog::Log(LOGDEBUG, "{} - failed to start demuxing from: {}", __FUNCTION__, + starttime.count()); } if (m_pSubtitleDemuxer) { - if(m_pSubtitleDemuxer->SeekTime(starttime, true, &startpts)) - CLog::Log(LOGDEBUG, "{} - starting subtitle demuxer from: {}", __FUNCTION__, starttime); + if (m_pSubtitleDemuxer->SeekTime(starttime.count(), true, &startpts)) + CLog::Log(LOGDEBUG, "{} - starting subtitle demuxer from: {}", __FUNCTION__, + starttime.count()); else CLog::Log(LOGDEBUG, "{} - failed to start subtitle demuxing from: {}", __FUNCTION__, - starttime); + starttime.count()); } - m_clock.Discontinuity(DVD_MSEC_TO_TIME(starttime)); + m_clock.Discontinuity(DVD_MSEC_TO_TIME(starttime.count())); } UpdatePlayState(0); @@ -1712,7 +1717,8 @@ void CVideoPlayer::ProcessAudioData(CDemuxStream* pStream, DemuxPacket* pPacket) } else { - const auto hasEdit = m_Edl.InEdit(DVD_TIME_TO_MSEC(m_CurrentAudio.dts + m_offset_pts)); + const auto hasEdit = m_Edl.InEdit( + std::chrono::milliseconds(DVD_TIME_TO_MSEC(m_CurrentAudio.dts + m_offset_pts))); if (hasEdit && hasEdit.value()->action == EDL::Action::MUTE) drop = true; } @@ -2391,7 +2397,8 @@ bool CVideoPlayer::CheckSceneSkip(const CCurrentStream& current) if(current.inited == false) return false; - const auto hasEdit = m_Edl.InEdit(DVD_TIME_TO_MSEC(current.dts + m_offset_pts)); + const auto hasEdit = + m_Edl.InEdit(std::chrono::milliseconds(std::lround(current.dts + m_offset_pts))); return hasEdit && hasEdit.value()->action == EDL::Action::CUT; } @@ -2411,9 +2418,9 @@ void CVideoPlayer::CheckAutoSceneSkip() m_CurrentVideo.inited == false) return; - const int64_t clock = GetTime(); + const std::chrono::milliseconds clock{GetTime()}; - const double correctClock = m_Edl.GetTimeAfterRestoringCuts(clock); + const std::chrono::milliseconds correctClock = m_Edl.GetTimeAfterRestoringCuts(clock); const auto hasEdit = m_Edl.InEdit(correctClock); if (!hasEdit) { @@ -2429,19 +2436,19 @@ void CVideoPlayer::CheckAutoSceneSkip() const auto& edit = hasEdit.value(); if (edit->action == EDL::Action::CUT) { - if ((m_playSpeed > 0 && correctClock < (edit->start + 1000)) || - (m_playSpeed < 0 && correctClock < (edit->end - 1000))) + if ((m_playSpeed > 0 && correctClock < (edit->start + 1s)) || + (m_playSpeed < 0 && correctClock < (edit->end - 1s))) { CLog::Log(LOGDEBUG, "{} - Clock in EDL cut [{} - {}]: {}. Automatically skipping over.", __FUNCTION__, CEdl::MillisecondsToTimeString(edit->start), CEdl::MillisecondsToTimeString(edit->end), CEdl::MillisecondsToTimeString(clock)); // Seeking either goes to the start or the end of the cut depending on the play direction. - int seek = m_playSpeed >= 0 ? edit->end : edit->start; + std::chrono::milliseconds seek = m_playSpeed >= 0 ? edit->end : edit->start; if (m_Edl.GetLastEditTime() != seek) { CDVDMsgPlayerSeek::CMode mode; - mode.time = seek; + mode.time = seek.count(); mode.backward = true; mode.accurate = true; mode.restore = false; @@ -2457,14 +2464,15 @@ void CVideoPlayer::CheckAutoSceneSkip() else if (edit->action == EDL::Action::COMM_BREAK) { // marker for commbreak may be inaccurate. allow user to skip into break from the back - if (m_playSpeed >= 0 && m_Edl.GetLastEditTime() != edit->start && clock < edit->end - 1000) + if (m_playSpeed >= 0 && m_Edl.GetLastEditTime() != edit->start && clock < edit->end - 1s) { const std::shared_ptr advancedSettings = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings(); if (advancedSettings && advancedSettings->m_EdlDisplayCommbreakNotifications) { - const std::string timeString = - StringUtils::SecondsToTimeString((edit->end - edit->start) / 1000, TIME_FORMAT_MM_SS); + const std::string timeString = StringUtils::SecondsToTimeString( + std::chrono::duration_cast(edit->end - edit->start).count(), + TIME_FORMAT_MM_SS); CGUIDialogKaiToast::QueueNotification(g_localizeStrings.Get(25011), timeString); } @@ -2480,7 +2488,7 @@ void CVideoPlayer::CheckAutoSceneSkip() CEdl::MillisecondsToTimeString(edit->end), CEdl::MillisecondsToTimeString(clock)); CDVDMsgPlayerSeek::CMode mode; - mode.time = edit->end; + mode.time = edit->end.count(); mode.backward = true; mode.accurate = true; mode.restore = false; @@ -2700,7 +2708,10 @@ void CVideoPlayer::HandleMessages() if (msg.GetRelative()) time = (m_clock.GetClock() + m_State.time_offset) / 1000l + time; - time = msg.GetRestore() ? m_Edl.GetTimeAfterRestoringCuts(time) : time; + time = msg.GetRestore() + ? m_Edl.GetTimeAfterRestoringCuts(std::chrono::milliseconds(std::lround(time))) + .count() + : time; // if input stream doesn't support ISeekTime, convert back to pts //! @todo @@ -3268,19 +3279,19 @@ bool CVideoPlayer::SeekScene(Direction seekDirection) * There is a 5 second grace period applied when seeking for scenes backwards. If there is no * grace period applied it is impossible to go backwards past a scene marker. */ - int64_t clock = GetTime(); - if (seekDirection == Direction::BACKWARD && clock > 5 * 1000) // 5 seconds - clock -= 5 * 1000; + auto clock = std::chrono::milliseconds(GetTime()); + if (seekDirection == Direction::BACKWARD && clock > 5s) // 5 seconds + clock -= 5s; - const std::optional sceneMarker = - m_Edl.GetNextSceneMarker(seekDirection, static_cast(clock)); + const std::optional sceneMarker = + m_Edl.GetNextSceneMarker(seekDirection, clock); if (sceneMarker) { /* * Seeking is flushed and inaccurate, just like Seek() */ CDVDMsgPlayerSeek::CMode mode; - mode.time = sceneMarker.value(); + mode.time = sceneMarker.value().count(); mode.backward = seekDirection == Direction::BACKWARD; mode.accurate = false; mode.restore = false; @@ -4940,8 +4951,9 @@ void CVideoPlayer::UpdatePlayState(double timeout) if (m_Edl.HasCuts()) { - state.time = static_cast(m_Edl.GetTimeWithoutCuts(state.time)); - state.timeMax = state.timeMax - static_cast(m_Edl.GetTotalCutTime()); + state.time = static_cast( + m_Edl.GetTimeWithoutCuts(std::chrono::milliseconds(std::lround(state.time))).count()); + state.timeMax = state.timeMax - static_cast(m_Edl.GetTotalCutTime().count()); } if (m_caching > CACHESTATE_DONE && m_caching < CACHESTATE_PLAY) diff --git a/xbmc/cores/VideoPlayer/test/edl/TestEdl.cpp b/xbmc/cores/VideoPlayer/test/edl/TestEdl.cpp index a8072ca868..4d36958f87 100644 --- a/xbmc/cores/VideoPlayer/test/edl/TestEdl.cpp +++ b/xbmc/cores/VideoPlayer/test/edl/TestEdl.cpp @@ -13,10 +13,12 @@ #include "settings/SettingsComponent.h" #include "test/TestUtils.h" +#include #include #include +using namespace std::chrono_literals; using namespace EDL; @@ -49,16 +51,16 @@ TEST_F(TestEdl, TestParsingMplayerTimeBasedEDL) // file has only 1 cut starting at 5.3 secs and ending at 7.1 secs // so total cut time should be 1.8 seconds (1800 msec) EXPECT_EQ(edl.HasCuts(), true); - EXPECT_EQ(edl.GetTotalCutTime(), 1.8 * 1000); + EXPECT_EQ(edl.GetTotalCutTime(), 1800ms); EXPECT_EQ(edl.GetCutMarkers().size(), 1); - EXPECT_EQ(edl.GetCutMarkers().at(0), 5.3 * 1000); // 5.3 secs + EXPECT_EQ(edl.GetCutMarkers().at(0), 5300ms); // When removing or restoring cuts, EDL adds (or removes) 1 msec to jump over the start or end boundary of the edit EXPECT_EQ(edl.GetTimeWithoutCuts(edl.GetRawEditList().at(0).start), - edl.GetRawEditList().at(0).start + 1); + edl.GetRawEditList().at(0).start + 1ms); EXPECT_EQ(edl.GetTimeAfterRestoringCuts(edl.GetRawEditList().at(0).start), edl.GetRawEditList().at(0).start); - EXPECT_EQ(edl.GetTimeAfterRestoringCuts(edl.GetRawEditList().at(0).start + 2), - edl.GetRawEditList().at(0).end + 2); + EXPECT_EQ(edl.GetTimeAfterRestoringCuts(edl.GetRawEditList().at(0).start + 2ms), + edl.GetRawEditList().at(0).end + 2ms); // the first edit (note editlist does not contain cuts) is a mute section starting at 15 seconds // of the real file this should correspond to 13.2 secs on the kodi VideoPlayer timeline (start - cuttime) @@ -75,32 +77,36 @@ TEST_F(TestEdl, TestParsingMplayerTimeBasedEDL) // scene markers // one of the scenemarkers (the first) have start and end times defined, kodi should assume the marker at the END position (255.3 secs) - EXPECT_EQ(edl.GetSceneMarkers().at(0), edl.GetTimeWithoutCuts(255.3 * 1000)); + EXPECT_EQ(edl.GetSceneMarkers().at(0), + edl.GetTimeWithoutCuts(duration_cast(255.3s))); // one of them only has start defined, at 720.1 secs - EXPECT_EQ(edl.GetSceneMarkers().at(1), edl.GetTimeWithoutCuts(720.1 * 1000)); + EXPECT_EQ(edl.GetSceneMarkers().at(1), + edl.GetTimeWithoutCuts(duration_cast(720.1s))); // commbreaks // the second edit on the file is a commbreak const auto commbreak = edl.GetEditList().at(1); EXPECT_EQ(commbreak.action, Action::COMM_BREAK); // We should have a scenemarker at the commbreak start and another on commbreak end - std::optional time = edl.GetNextSceneMarker(Direction::FORWARD, commbreak.start - 1); + std::optional time = + edl.GetNextSceneMarker(Direction::FORWARD, commbreak.start - 1ms); // lets cycle to the next scenemarker if starting from 1 msec before the start (or end) of the commbreak EXPECT_NE(time, std::nullopt); EXPECT_EQ(edl.GetTimeWithoutCuts(time.value()), commbreak.start); - time = edl.GetNextSceneMarker(Direction::FORWARD, commbreak.end - 1); + time = edl.GetNextSceneMarker(Direction::FORWARD, commbreak.end - 1ms); EXPECT_NE(time, std::nullopt); EXPECT_EQ(edl.GetTimeWithoutCuts(time.value()), commbreak.end); // same if we cycle backwards - time = edl.GetNextSceneMarker(Direction::BACKWARD, commbreak.start + 1); + time = edl.GetNextSceneMarker(Direction::BACKWARD, commbreak.start + 1ms); EXPECT_NE(time, std::nullopt); EXPECT_EQ(edl.GetTimeWithoutCuts(time.value()), commbreak.start); - time = edl.GetNextSceneMarker(Direction::BACKWARD, commbreak.end + 1); + time = edl.GetNextSceneMarker(Direction::BACKWARD, commbreak.end + 1ms); EXPECT_NE(time, std::nullopt); EXPECT_EQ(edl.GetTimeWithoutCuts(time.value()), commbreak.end); // We should be in an edit if we are in the middle of a commbreak... // lets check and confirm the edits match (after restoring cuts) - const int middleOfCommbreak = commbreak.start + (commbreak.end - commbreak.start) / 2; + const std::chrono::milliseconds middleOfCommbreak = + commbreak.start + (commbreak.end - commbreak.start) / 2; const auto hasEdit = edl.InEdit(edl.GetTimeWithoutCuts(middleOfCommbreak)); EXPECT_NE(hasEdit, std::nullopt); const auto& edit = hasEdit.value(); @@ -126,9 +132,9 @@ TEST_F(TestEdl, TestParsingMplayerTimeBasedInterleavedCutsEDL) EXPECT_EQ(edl.HasEdits(), true); EXPECT_EQ(edl.GetCutMarkers().size(), 2); // lets check the total cut time matches the sum of the two cut durations defined in the file - EXPECT_EQ(edl.GetTotalCutTime(), ((7.1 - 5.3) + (19 - 18)) * 1000); + EXPECT_EQ(edl.GetTotalCutTime(), 2800ms); // (7.1s - 5.3s) + (19s - 18s) // the first edit is after the first cut, so lets check the start time was adjusted exactly by the cut duration - EXPECT_EQ(edl.GetEditList().at(0).start, edl.GetRawEditList().at(1).start - ((7.1 - 5.3) * 1000)); + EXPECT_EQ(edl.GetEditList().at(0).start, edl.GetRawEditList().at(1).start - (7.1s - 5.3s)); EXPECT_EQ(edl.GetEditList().at(0).start, edl.GetTimeWithoutCuts(edl.GetRawEditList().at(1).start)); EXPECT_EQ(edl.GetEditList().at(1).start, @@ -157,9 +163,13 @@ TEST_F(TestEdl, TestParsingMplayerFrameBasedEDL) EXPECT_EQ(edl.GetEditList().size(), 2); // check edit times are correctly calculated provided the fps EXPECT_EQ(edl.GetEditList().at(0).start, - static_cast((360 / fps) * 1000) - edl.GetTotalCutTime()); + std::chrono::duration_cast( + std::chrono::duration>{360 / fps}) - + edl.GetTotalCutTime()); EXPECT_EQ(edl.GetSceneMarkers().at(0), - static_cast((6127 / fps) * 1000) - edl.GetTotalCutTime()); + std::chrono::duration_cast( + std::chrono::duration>{6127 / fps}) - + edl.GetTotalCutTime()); } TEST_F(TestEdl, TestParsingMplayerTimeBasedMixedEDL) @@ -182,7 +192,7 @@ TEST_F(TestEdl, TestParsingMplayerTimeBasedMixedEDL) // check we have correctly parsed the scene with 12:00.1 start point for (const auto& scene : edl.GetSceneMarkers()) { - if (scene == (12 * 60 + 0.1) * 1000 - edl.GetTotalCutTime()) + if (scene == (12 * 60s + 0.1s) - edl.GetTotalCutTime()) { sceneFound = true; break; @@ -190,7 +200,7 @@ TEST_F(TestEdl, TestParsingMplayerTimeBasedMixedEDL) } EXPECT_EQ(sceneFound, true); // check that the first ordered edit starts at 15 secs - EXPECT_EQ(edl.GetEditList().front().start, (15 * 1000) - edl.GetTotalCutTime()); + EXPECT_EQ(edl.GetEditList().front().start, 15s - edl.GetTotalCutTime()); } TEST_F(TestEdl, TestParsingVideoRedoEDL) @@ -213,7 +223,7 @@ TEST_F(TestEdl, TestParsingVideoRedoEDL) EXPECT_EQ(edl.GetCutMarkers().size(), 3); // in videoredo time processing is ms * 10000 // first cut in the file is at 4235230000 - let's confirm this corresponds to second 423.523 - EXPECT_EQ(edl.GetCutMarkers().front(), 423.523 * 1000); + EXPECT_EQ(edl.GetCutMarkers().front(), 423.523s); } TEST_F(TestEdl, TestSnapStreamEDL) @@ -233,8 +243,8 @@ TEST_F(TestEdl, TestSnapStreamEDL) EXPECT_EQ(edl.GetSceneMarkers().size(), 3 * 2); // start and end of each commbreak // snapstream beyond tv uses ms * 10000 // check if first commbreak (4235230000 - 5936600000) is 423.523 sec - 593.660 sec - EXPECT_EQ(edl.GetEditList().front().start, std::lround(423.523 * 1000)); - EXPECT_EQ(edl.GetEditList().front().end, std::lround(593.660 * 1000)); + EXPECT_EQ(edl.GetEditList().front().start, 423.523s); + EXPECT_EQ(edl.GetEditList().front().end, 593.660s); } TEST_F(TestEdl, TestComSkipVersion1EDL) @@ -257,8 +267,12 @@ TEST_F(TestEdl, TestComSkipVersion1EDL) EXPECT_EQ(edl.GetCutMarkers().empty(), true); EXPECT_EQ(edl.GetEditList().size(), 3); EXPECT_EQ(edl.GetSceneMarkers().size(), 3 * 2); // start and end of each commbreak - EXPECT_EQ(edl.GetEditList().front().start, std::lround(12693 / fps * 1000)); - EXPECT_EQ(edl.GetEditList().front().end, std::lround(17792 / fps * 1000)); + EXPECT_EQ(edl.GetEditList().front().start, + std::chrono::duration_cast( + std::chrono::duration>{12693 / fps})); + EXPECT_EQ(edl.GetEditList().front().end, + std::chrono::duration_cast( + std::chrono::duration>{17792 / fps})); } TEST_F(TestEdl, TestComSkipVersion2EDL) @@ -274,23 +288,27 @@ TEST_F(TestEdl, TestComSkipVersion2EDL) EXPECT_EQ(found, true); // fps is obtained from the file as it always takes precedence (note we supplied 0 above), // the EDL file has the value of 2500 for fps. kodi converts this to 25 fps by dividing by a factor of 100 - const float fpsInEdlFile = 2500 / 100; + const double fpsInEdlFile = 2500 / 100; // this format only supports commbreak types EXPECT_EQ(edl.HasEdits(), true); EXPECT_EQ(edl.GetCutMarkers().empty(), true); EXPECT_EQ(edl.GetEditList().size(), 3); EXPECT_EQ(edl.GetSceneMarkers().size(), 3 * 2); // start and end of each commbreak - EXPECT_EQ(edl.GetEditList().front().start, std::lround(12693 / fpsInEdlFile * 1000)); - EXPECT_EQ(edl.GetEditList().front().end, std::lround(17792 / fpsInEdlFile * 1000)); + EXPECT_EQ(edl.GetEditList().front().start, + std::chrono::duration_cast( + std::chrono::duration>{12693 / fpsInEdlFile})); + EXPECT_EQ(edl.GetEditList().front().end, + std::chrono::duration_cast( + std::chrono::duration>{17792 / fpsInEdlFile})); } TEST_F(TestEdl, TestRuntimeSetEDL) { // this is a simple test for SetLastEditTime, SetLastEditActionType and corresponding getters CEdl edl; - edl.SetLastEditTime(1000); + edl.SetLastEditTime(1000ms); edl.SetLastEditActionType(Action::COMM_BREAK); - EXPECT_EQ(edl.GetLastEditTime(), 1000); + EXPECT_EQ(edl.GetLastEditTime(), 1000ms); EXPECT_EQ(edl.GetLastEditActionType(), Action::COMM_BREAK); } @@ -325,17 +343,17 @@ TEST_F(TestEdl, TestCommBreakAdvancedSettings) EXPECT_EQ(found, true); // confirm the start and end times of all the commbreaks match EXPECT_EQ(edl.GetEditList().size(), 5); - EXPECT_EQ(edl.GetEditList().at(0).start, 10 * 1000); - EXPECT_EQ(edl.GetEditList().at(0).end, 22 * 1000); - EXPECT_EQ(edl.GetEditList().at(1).start, 30 * 1000); - EXPECT_EQ(edl.GetEditList().at(1).end, 32 * 1000); - EXPECT_EQ(edl.GetEditList().at(2).start, 37 * 1000); - EXPECT_EQ(edl.GetEditList().at(2).end, 50 * 1000); - EXPECT_EQ(edl.GetEditList().at(3).start, 52 * 1000); - EXPECT_EQ(edl.GetEditList().at(3).end, 60 * 1000); - EXPECT_EQ(edl.GetEditList().at(4).start, 62 * 1000); - EXPECT_EQ(edl.GetEditList().at(4).end, std::lround(65.1 * 1000)); - // now lets change autowait and autowind and check the edits are correcly adjusted + EXPECT_EQ(edl.GetEditList().at(0).start, 10s); + EXPECT_EQ(edl.GetEditList().at(0).end, 22s); + EXPECT_EQ(edl.GetEditList().at(1).start, 30s); + EXPECT_EQ(edl.GetEditList().at(1).end, 32s); + EXPECT_EQ(edl.GetEditList().at(2).start, 37s); + EXPECT_EQ(edl.GetEditList().at(2).end, 50s); + EXPECT_EQ(edl.GetEditList().at(3).start, 52s); + EXPECT_EQ(edl.GetEditList().at(3).end, 60s); + EXPECT_EQ(edl.GetEditList().at(4).start, 62s); + EXPECT_EQ(edl.GetEditList().at(4).end, 65100ms); + // now lets change autowait and autowind and check the edits are correctly adjusted edl.Clear(); advancedSettings->m_iEdlCommBreakAutowait = 3; // secs advancedSettings->m_iEdlCommBreakAutowind = 3; // secs @@ -345,23 +363,23 @@ TEST_F(TestEdl, TestCommBreakAdvancedSettings) EXPECT_EQ(edl.GetEditList().size(), 5); // the second edit has a duration smaller than the autowait // this moves the start time to the end of the edit - EXPECT_EQ(edl.GetEditList().at(1).start, 32 * 1000); + EXPECT_EQ(edl.GetEditList().at(1).start, 32s); EXPECT_EQ(edl.GetEditList().at(1).end, edl.GetEditList().at(1).start); // the others should be adjusted + 3 secs at the start and -3 secs at the end // due to the provided values for autowait and autowind. - EXPECT_EQ(edl.GetEditList().at(0).start, (10 + 3) * 1000); - EXPECT_EQ(edl.GetEditList().at(0).end, (22 - 3) * 1000); - EXPECT_EQ(edl.GetEditList().at(2).start, (37 + 3) * 1000); - EXPECT_EQ(edl.GetEditList().at(2).end, (50 - 3) * 1000); - EXPECT_EQ(edl.GetEditList().at(3).start, (52 + 3) * 1000); - EXPECT_EQ(edl.GetEditList().at(3).end, (60 - 3) * 1000); + EXPECT_EQ(edl.GetEditList().at(0).start, 10s + 3s); + EXPECT_EQ(edl.GetEditList().at(0).end, 22s - 3s); + EXPECT_EQ(edl.GetEditList().at(2).start, 37s + 3s); + EXPECT_EQ(edl.GetEditList().at(2).end, 50s - 3s); + EXPECT_EQ(edl.GetEditList().at(3).start, 52s + 3s); + EXPECT_EQ(edl.GetEditList().at(3).end, 60s - 3s); // since we adjust the start to second 65 and the autowind is 3 seconds kodi should // shift the end time not by 3 seconds but by the "excess" time (in this case 0.1 sec) // this means start and end will be exactly the same. The commbreak would be removed if // mergeshortcommbreaks was active and advancedsetting m_iEdlMinCommBreakLength // was set to a reasonable threshold. - EXPECT_EQ(edl.GetEditList().at(4).start, (62 + 3) * 1000); - EXPECT_EQ(edl.GetEditList().at(4).end, (65.1 - 0.1) * 1000); + EXPECT_EQ(edl.GetEditList().at(4).start, 62s + 3s); + EXPECT_EQ(edl.GetEditList().at(4).end, 65.1s - 0.1s); EXPECT_EQ(edl.GetEditList().at(4).start, edl.GetEditList().at(4).end); } @@ -425,8 +443,8 @@ TEST_F(TestEdl, TestMergeSmallCommbreaks) // kodi should merge all commbreaks into a single one starting at the first point (0) // and ending at the last edit time EXPECT_EQ(edl.GetEditList().size(), 1); - EXPECT_EQ(edl.GetEditList().at(0).start, 0); - EXPECT_EQ(edl.GetEditList().at(0).end, std::lround(65.1 * 1000)); + EXPECT_EQ(edl.GetEditList().at(0).start, 0ms); + EXPECT_EQ(edl.GetEditList().at(0).end, 65100ms); } TEST_F(TestEdl, TestMergeSmallCommbreaksAdvanced) @@ -458,8 +476,7 @@ TEST_F(TestEdl, TestMergeSmallCommbreaksAdvanced) // kodi should merge all commbreaks into two EXPECT_EQ(edl.GetEditList().size(), 2); // second edit of the original file + third one - EXPECT_EQ(edl.GetEditList().at(0).end - edl.GetEditList().at(0).start, (32 - 10) * 1000); + EXPECT_EQ(edl.GetEditList().at(0).end - edl.GetEditList().at(0).start, 32s - 10s); // 4th, 5th and 6th commbreaks joined - EXPECT_EQ(edl.GetEditList().at(1).end - edl.GetEditList().at(1).start, - std::lround((65.1 - 37) * 1000)); + EXPECT_EQ(edl.GetEditList().at(1).end - edl.GetEditList().at(1).start, 65100ms - 37s); } diff --git a/xbmc/guilib/guiinfo/PlayerGUIInfo.cpp b/xbmc/guilib/guiinfo/PlayerGUIInfo.cpp index 62e620dc41..790264c21f 100644 --- a/xbmc/guilib/guiinfo/PlayerGUIInfo.cpp +++ b/xbmc/guilib/guiinfo/PlayerGUIInfo.cpp @@ -32,6 +32,7 @@ #include "utils/log.h" #include +#include #include #include @@ -672,8 +673,8 @@ std::vector> CPlayerGUIInfo::GetEditList(const CDataCach const std::vector& edits = data.GetEditList(); for (const auto& edit : edits) { - float editStart = edit.start * 100.0f / duration; - float editEnd = edit.end * 100.0f / duration; + float editStart = edit.start.count() * 100.0f / duration; + float editEnd = edit.end.count() * 100.0f / duration; ranges.emplace_back(editStart, editEnd); } return ranges; @@ -684,11 +685,11 @@ std::vector> CPlayerGUIInfo::GetCuts(const CDataCacheCor { std::vector> ranges; - const std::vector& cuts = data.GetCuts(); + const std::vector& cuts = data.GetCuts(); float lastMarker = 0.0f; for (const auto& cut : cuts) { - float marker = cut * 100.0f / duration; + float marker = cut.count() * 100.0f / duration; if (marker != 0) ranges.emplace_back(lastMarker, marker); @@ -702,11 +703,11 @@ std::vector> CPlayerGUIInfo::GetSceneMarkers(const CData { std::vector> ranges; - const std::vector& scenes = data.GetSceneMarkers(); + const std::vector& scenes = data.GetSceneMarkers(); float lastMarker = 0.0f; for (const auto& scene : scenes) { - float marker = scene * 100.0f / duration; + float marker = scene.count() * 100.0f / duration; if (marker != 0) ranges.emplace_back(lastMarker, marker); diff --git a/xbmc/pvr/PVREdl.cpp b/xbmc/pvr/PVREdl.cpp index 72a3ee46fd..aa47cbed27 100644 --- a/xbmc/pvr/PVREdl.cpp +++ b/xbmc/pvr/PVREdl.cpp @@ -15,6 +15,8 @@ #include "pvr/recordings/PVRRecording.h" #include "utils/log.h" +#include + namespace PVR { @@ -38,8 +40,8 @@ std::vector CPVREdl::GetEdits(const CFileItem& item) for (const auto& entry : edl) { EDL::Edit edit; - edit.start = entry.start; - edit.end = entry.end; + edit.start = std::chrono::milliseconds(entry.start); + edit.end = std::chrono::milliseconds(entry.end); switch (entry.type) { -- cgit v1.2.3