aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xbmc/cores/DataCacheCore.cpp9
-rw-r--r--xbmc/cores/DataCacheCore.h20
-rw-r--r--xbmc/cores/EdlEdit.h6
-rw-r--r--xbmc/cores/VideoPlayer/Edl.cpp154
-rw-r--r--xbmc/cores/VideoPlayer/Edl.h35
-rw-r--r--xbmc/cores/VideoPlayer/VideoPlayer.cpp90
-rw-r--r--xbmc/cores/VideoPlayer/test/edl/TestEdl.cpp123
-rw-r--r--xbmc/guilib/guiinfo/PlayerGUIInfo.cpp13
-rw-r--r--xbmc/pvr/PVREdl.cpp6
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 <chrono>
#include <mutex>
#include <utility>
@@ -271,25 +272,25 @@ const std::vector<EDL::Edit>& CDataCacheCore::GetEditList() const
return m_contentInfo.GetEditList();
}
-void CDataCacheCore::SetCuts(const std::vector<int64_t>& cuts)
+void CDataCacheCore::SetCuts(const std::vector<std::chrono::milliseconds>& cuts)
{
std::unique_lock<CCriticalSection> lock(m_contentSection);
m_contentInfo.SetCuts(cuts);
}
-const std::vector<int64_t>& CDataCacheCore::GetCuts() const
+const std::vector<std::chrono::milliseconds>& CDataCacheCore::GetCuts() const
{
std::unique_lock<CCriticalSection> lock(m_contentSection);
return m_contentInfo.GetCuts();
}
-void CDataCacheCore::SetSceneMarkers(const std::vector<int64_t>& sceneMarkers)
+void CDataCacheCore::SetSceneMarkers(const std::vector<std::chrono::milliseconds>& sceneMarkers)
{
std::unique_lock<CCriticalSection> lock(m_contentSection);
m_contentInfo.SetSceneMarkers(sceneMarkers);
}
-const std::vector<int64_t>& CDataCacheCore::GetSceneMarkers() const
+const std::vector<std::chrono::milliseconds>& CDataCacheCore::GetSceneMarkers() const
{
std::unique_lock<CCriticalSection> 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<int64_t>& cuts);
+ void SetCuts(const std::vector<std::chrono::milliseconds>& 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<int64_t>& GetCuts() const;
+ const std::vector<std::chrono::milliseconds>& 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<int64_t>& sceneMarkers);
+ void SetSceneMarkers(const std::vector<std::chrono::milliseconds>& 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<int64_t>& GetSceneMarkers() const;
+ const std::vector<std::chrono::milliseconds>& GetSceneMarkers() const;
void SetChapters(const std::vector<std::pair<std::string, int64_t>>& 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<int64_t>& cuts) { m_cuts = cuts; }
+ void SetCuts(const std::vector<std::chrono::milliseconds>& cuts) { m_cuts = cuts; }
/*!
* @brief Get the list of cut markers in cache.
* @return the list of cut markers in cache
*/
- const std::vector<int64_t>& GetCuts() const { return m_cuts; }
+ const std::vector<std::chrono::milliseconds>& 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<int64_t>& sceneMarkers)
+ void SetSceneMarkers(const std::vector<std::chrono::milliseconds>& 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<int64_t>& GetSceneMarkers() const { return m_sceneMarkers; }
+ const std::vector<std::chrono::milliseconds>& GetSceneMarkers() const { return m_sceneMarkers; }
/*!
* @brief Save the chapter list in cache.
@@ -297,9 +297,9 @@ protected:
/*!< name and position for chapters */
std::vector<std::pair<std::string, int64_t>> m_chapters;
/*!< position for EDL cuts */
- std::vector<int64_t> m_cuts;
+ std::vector<std::chrono::milliseconds> m_cuts;
/*!< position for EDL scene markers */
- std::vector<int64_t> m_sceneMarkers;
+ std::vector<std::chrono::milliseconds> 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 <chrono>
+
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 <charconv>
+
#include "PlatformDefs.h"
#define COMSKIP_HEADER "FILE PROCESSING COMPLETE"
@@ -27,6 +29,7 @@
#define VIDEOREDO_TAG_CUT "<Cut>"
#define VIDEOREDO_TAG_SCENE "<SceneMarker "
+using namespace std::chrono_literals;
using namespace EDL;
using namespace XFILE;
@@ -39,8 +42,8 @@ void CEdl::Clear()
{
m_vecEdits.clear();
m_vecSceneMarkers.clear();
- m_totalCutTime = 0;
- m_lastEditTime = -1;
+ m_totalCutTime = 0ms;
+ m_lastEditTime = std::nullopt;
}
bool CEdl::ReadEditDecisionLists(const CFileItem& fileItem, float fps)
@@ -151,7 +154,7 @@ bool CEdl::ReadEdl(const std::string& mediaFilePath, float fps)
* For each of the first two fields read, parse based on whether it is a time string
* (HH:MM:SS.sss), frame marker (#12345), or normal seconds string (123.45).
*/
- int64_t editStartEnd[2];
+ std::chrono::milliseconds editStartEnd[2];
for (int i = 0; i < 2; i++)
{
if (strFields[i].find(':') != std::string::npos) // HH:MM:SS.sss format
@@ -159,8 +162,8 @@ bool CEdl::ReadEdl(const std::string& mediaFilePath, float fps)
std::vector<std::string> fieldParts = StringUtils::Split(strFields[i], '.');
if (fieldParts.size() == 1) // No ms
{
- editStartEnd[i] = StringUtils::TimeStringToSeconds(fieldParts[0]) *
- static_cast<int64_t>(1000); // seconds to ms
+ editStartEnd[i] = std::chrono::duration_cast<std::chrono::milliseconds>(
+ 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<int64_t>(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::milliseconds>(
+ 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<int64_t>(std::atol(strFields[i].substr(1).c_str()) / fps *
- 1000); // frame number to ms
+ std::chrono::duration<double, std::ratio<1>> durationInSeconds{
+ std::atol(strFields[i].substr(1).c_str()) / fps};
+ editStartEnd[i] =
+ std::chrono::duration_cast<std::chrono::milliseconds>(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<double>(fFrameRate) * 1000.0);
- edit.end = std::lround(dEndFrame / static_cast<double>(fFrameRate) * 1000.0);
+ edit.start = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::duration<double, std::ratio<1>>{dStartFrame /
+ static_cast<double>(fFrameRate)});
+ edit.end = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::duration<double, std::ratio<1>>{dEndFrame /
+ static_cast<double>(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::milliseconds>(std::chrono::seconds(
+ CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_iEdlCommBreakAutowait));
+ std::chrono::milliseconds autowind = std::chrono::duration_cast<std::chrono::milliseconds>(
+ 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<EDL::Edit> 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<EDL::Edit> editList;
// @note we should not modify the original edits since
@@ -757,7 +777,7 @@ const std::vector<EDL::Edit> 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<EDL::Edit> CEdl::GetEditList() const
return editList;
}
-const std::vector<int64_t> CEdl::GetCutMarkers() const
+const std::vector<std::chrono::milliseconds> CEdl::GetCutMarkers() const
{
- int surpassedSumOfCutDurations{0};
- std::vector<int64_t> cutList;
+ std::chrono::milliseconds surpassedSumOfCutDurations{0};
+ std::vector<std::chrono::milliseconds> cutList;
for (const EDL::Edit& edit : m_vecEdits)
{
if (edit.action != Action::CUT)
@@ -781,23 +801,23 @@ const std::vector<int64_t> CEdl::GetCutMarkers() const
return cutList;
}
-const std::vector<int64_t> CEdl::GetSceneMarkers() const
+const std::vector<std::chrono::milliseconds> CEdl::GetSceneMarkers() const
{
- std::vector<int64_t> sceneMarkers;
+ std::vector<std::chrono::milliseconds> 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<double>(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<std::unique_ptr<EDL::Edit>> CEdl::InEdit(const int seekTime)
+std::optional<std::unique_ptr<EDL::Edit>> CEdl::InEdit(std::chrono::milliseconds seekTime)
{
for (size_t i = 0; i < m_vecEdits.size(); ++i)
{
@@ -854,19 +874,19 @@ std::optional<std::unique_ptr<EDL::Edit>> CEdl::InEdit(const int seekTime)
return std::nullopt;
}
-int CEdl::GetLastEditTime() const
+std::optional<std::chrono::milliseconds> 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<int> CEdl::GetNextSceneMarker(Direction direction, int clock)
+std::optional<std::chrono::milliseconds> CEdl::GetNextSceneMarker(Direction direction,
+ std::chrono::milliseconds clock)
{
if (!HasSceneMarker())
return std::nullopt;
- std::optional<int> sceneMarker;
- const int seekTime = GetTimeAfterRestoringCuts(clock);
+ std::optional<std::chrono::milliseconds> 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<int> 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<long>(milliSeconds / 1000), TIME_FORMAT_HH_MM_SS); // milliseconds to seconds
- strTimeString += StringUtils::Format(".{:03}", milliSeconds % 1000);
+ std::chrono::duration_cast<std::chrono::seconds>(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::milliseconds>(
+ std::chrono::seconds(advancedSettings->m_iEdlMaxCommBreakLength))) &&
+ (m_vecEdits[i + 1].start - m_vecEdits[i].end <
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ 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::milliseconds>(
+ 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::milliseconds>(
+ 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<int64_t> GetCutMarkers() const;
+ const std::vector<std::chrono::milliseconds> 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<int64_t> GetSceneMarkers() const;
+ const std::vector<std::chrono::milliseconds> 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<std::unique_ptr<EDL::Edit>> InEdit(int seekTime);
+ std::optional<std::unique_ptr<EDL::Edit>> 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<std::chrono::milliseconds> 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<int> GetNextSceneMarker(Direction direction, int clock);
+ std::optional<std::chrono::milliseconds> 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<EDL::Edit> m_vecEdits;
- std::vector<int> m_vecSceneMarkers;
+ std::vector<std::chrono::milliseconds> m_vecSceneMarkers;
/*!
* @brief Last processed EDL edit time (ms)
*/
- int m_lastEditTime;
+ std::optional<std::chrono::milliseconds> 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 <chrono>
#include <iterator>
#include <memory>
#include <mutex>
@@ -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<int>((static_cast<double>(
- m_pDemuxer->GetStreamLength() * (m_playerOptions.startpercent / 100.0))));
+ std::chrono::milliseconds playerStartTime =
+ std::chrono::milliseconds(static_cast<int>((static_cast<double>(
+ m_pDemuxer->GetStreamLength() * (m_playerOptions.startpercent / 100.0)))));
starttime = m_Edl.GetTimeAfterRestoringCuts(playerStartTime);
}
else
{
- starttime = m_Edl.GetTimeAfterRestoringCuts(
- static_cast<int>(m_playerOptions.starttime * 1000)); // s to ms
+ starttime =
+ m_Edl.GetTimeAfterRestoringCuts(std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::seconds(static_cast<int>(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<CAdvancedSettings> 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<CAdvancedSettings> 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<std::chrono::seconds>(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<int> sceneMarker =
- m_Edl.GetNextSceneMarker(seekDirection, static_cast<int>(clock));
+ const std::optional<std::chrono::milliseconds> 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<double>(m_Edl.GetTimeWithoutCuts(state.time));
- state.timeMax = state.timeMax - static_cast<double>(m_Edl.GetTotalCutTime());
+ state.time = static_cast<double>(
+ m_Edl.GetTimeWithoutCuts(std::chrono::milliseconds(std::lround(state.time))).count());
+ state.timeMax = state.timeMax - static_cast<double>(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 <chrono>
#include <cmath>
#include <gtest/gtest.h>
+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<std::chrono::milliseconds>(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<std::chrono::milliseconds>(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<int> time = edl.GetNextSceneMarker(Direction::FORWARD, commbreak.start - 1);
+ std::optional<std::chrono::milliseconds> 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<int64_t>((360 / fps) * 1000) - edl.GetTotalCutTime());
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::duration<double, std::ratio<1>>{360 / fps}) -
+ edl.GetTotalCutTime());
EXPECT_EQ(edl.GetSceneMarkers().at(0),
- static_cast<int64_t>((6127 / fps) * 1000) - edl.GetTotalCutTime());
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::duration<double, std::ratio<1>>{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::milliseconds>(
+ std::chrono::duration<double, std::ratio<1>>{12693 / fps}));
+ EXPECT_EQ(edl.GetEditList().front().end,
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::duration<double, std::ratio<1>>{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::milliseconds>(
+ std::chrono::duration<double, std::ratio<1>>{12693 / fpsInEdlFile}));
+ EXPECT_EQ(edl.GetEditList().front().end,
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::duration<double, std::ratio<1>>{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 <charconv>
+#include <chrono>
#include <cmath>
#include <memory>
@@ -672,8 +673,8 @@ std::vector<std::pair<float, float>> CPlayerGUIInfo::GetEditList(const CDataCach
const std::vector<EDL::Edit>& 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<std::pair<float, float>> CPlayerGUIInfo::GetCuts(const CDataCacheCor
{
std::vector<std::pair<float, float>> ranges;
- const std::vector<int64_t>& cuts = data.GetCuts();
+ const std::vector<std::chrono::milliseconds>& 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<std::pair<float, float>> CPlayerGUIInfo::GetSceneMarkers(const CData
{
std::vector<std::pair<float, float>> ranges;
- const std::vector<int64_t>& scenes = data.GetSceneMarkers();
+ const std::vector<std::chrono::milliseconds>& 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 <chrono>
+
namespace PVR
{
@@ -38,8 +40,8 @@ std::vector<EDL::Edit> 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)
{