Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/mpc-hc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorslydiman <slydiman@mail.ru>2015-12-08 23:10:13 +0300
committerKacper Michajłow <kasper93@gmail.com>2015-12-22 23:13:52 +0300
commit04f914f92c894b43fdead49f7ce50c023826b43b (patch)
tree83ca65e8bba5dcfb275372f75bbf9a3a04d55448 /src
parent768298db1ad597c38f195922c874ed37b93c93d6 (diff)
Changed the Subtitles library timestamp to REFERENCE_TIME.
Resolves #157.
Diffstat (limited to 'src')
-rw-r--r--src/Subtitles/RTS.cpp18
-rw-r--r--src/Subtitles/STS.cpp95
-rw-r--r--src/Subtitles/STS.h24
-rw-r--r--src/Subtitles/SubtitleHelpers.h6
-rw-r--r--src/Subtitles/SubtitleInputPin.cpp10
-rw-r--r--src/filters/transform/VSFilter/Copy.cpp10
-rw-r--r--src/filters/transform/VSFilter/DirectVobSub.cpp8
-rw-r--r--src/filters/transform/VSFilter/DirectVobSub.h5
-rw-r--r--src/filters/transform/VSFilter/DirectVobSubFilter.cpp2
-rw-r--r--src/mpc-hc/PlayerSubresyncBar.cpp78
-rw-r--r--src/mpc-hc/PlayerSubresyncBar.h16
11 files changed, 143 insertions, 129 deletions
diff --git a/src/Subtitles/RTS.cpp b/src/Subtitles/RTS.cpp
index ecce8ec72..4d125267a 100644
--- a/src/Subtitles/RTS.cpp
+++ b/src/Subtitles/RTS.cpp
@@ -2854,7 +2854,7 @@ STDMETHODIMP CRenderedTextSubtitle::NonDelegatingQueryInterface(REFIID riid, voi
STDMETHODIMP_(POSITION) CRenderedTextSubtitle::GetStartPosition(REFERENCE_TIME rt, double fps)
{
int iSegment = -1;
- SearchSubs((int)(rt / 10000), fps, &iSegment, nullptr);
+ SearchSubs(rt, fps, &iSegment, nullptr);
if (iSegment < 0) {
iSegment = 0;
@@ -2878,12 +2878,12 @@ STDMETHODIMP_(POSITION) CRenderedTextSubtitle::GetNext(POSITION pos)
STDMETHODIMP_(REFERENCE_TIME) CRenderedTextSubtitle::GetStart(POSITION pos, double fps)
{
- return (10000i64 * TranslateSegmentStart((int)pos - 1, fps));
+ return TranslateSegmentStart((int)pos - 1, fps);
}
STDMETHODIMP_(REFERENCE_TIME) CRenderedTextSubtitle::GetStop(POSITION pos, double fps)
{
- return (10000i64 * TranslateSegmentEnd((int)pos - 1, fps));
+ return TranslateSegmentEnd((int)pos - 1, fps);
}
STDMETHODIMP_(bool) CRenderedTextSubtitle::IsAnimated(POSITION pos)
@@ -2924,10 +2924,8 @@ STDMETHODIMP CRenderedTextSubtitle::Render(SubPicDesc& spd, REFERENCE_TIME rt, d
Init(CSize(spd.w, spd.h), spd.vidrect);
}
- int time = (int)(rt / 10000);
-
int segment;
- const STSSegment* stss = SearchSubs(time, fps, &segment);
+ const STSSegment* stss = SearchSubs(rt, fps, &segment);
if (!stss) {
return S_FALSE;
}
@@ -2941,7 +2939,7 @@ STDMETHODIMP CRenderedTextSubtitle::Render(SubPicDesc& spd, REFERENCE_TIME rt, d
m_subtitleCache.GetNextAssoc(pos, entry, pSub);
STSEntry& stse = GetAt(entry);
- if (stse.end < time) {
+ if (stse.end < rt) {
delete pSub;
m_subtitleCache.RemoveKey(entry);
}
@@ -2968,9 +2966,9 @@ STDMETHODIMP CRenderedTextSubtitle::Render(SubPicDesc& spd, REFERENCE_TIME rt, d
STSEntry stse = GetAt(entry);
{
- int start = TranslateStart(entry, fps);
- m_time = time - start;
- m_delay = TranslateEnd(entry, fps) - start;
+ REFERENCE_TIME start = TranslateStart(entry, fps);
+ m_time = (int)RT2MS(rt - start);
+ m_delay = (int)RT2MS(TranslateEnd(entry, fps) - start);
}
CSubtitle* s = GetSubtitle(entry);
diff --git a/src/Subtitles/STS.cpp b/src/Subtitles/STS.cpp
index 701a51535..80e0289ee 100644
--- a/src/Subtitles/STS.cpp
+++ b/src/Subtitles/STS.cpp
@@ -519,8 +519,8 @@ static bool OpenSubRipper(CTextFile* file, CSimpleTextSubtitle& ret, int CharSet
ret.Add(SubRipper2SSA(str, CharSet),
file->IsUnicode(),
- (((hh1 * 60 + mm1) * 60) + ss1) * 1000 + ms1,
- (((hh2 * 60 + mm2) * 60) + ss2) * 1000 + ms2);
+ MS2RT((((hh1 * 60i64 + mm1) * 60i64) + ss1) * 1000i64 + ms1),
+ MS2RT((((hh2 * 60i64 + mm2) * 60i64) + ss2) * 1000i64 + ms2));
} else {
return false;
}
@@ -555,8 +555,8 @@ static bool OpenOldSubRipper(CTextFile* file, CSimpleTextSubtitle& ret, int Char
ret.Add(
buff.Mid(buff.Find('}', buff.Find('}') + 1) + 1),
file->IsUnicode(),
- (((hh1 * 60 + mm1) * 60) + ss1) * 1000,
- (((hh2 * 60 + mm2) * 60) + ss2) * 1000);
+ MS2RT((((hh1 * 60i64 + mm1) * 60i64) + ss1) * 1000i64),
+ MS2RT((((hh2 * 60i64 + mm2) * 60i64) + ss2) * 1000i64));
} else if (c != EOF) { // might be another format
return false;
}
@@ -665,8 +665,8 @@ static bool OpenSubViewer(CTextFile* file, CSimpleTextSubtitle& ret, int CharSet
ret.Add(str,
file->IsUnicode(),
- (((hh1 * 60 + mm1) * 60) + ss1) * 1000 + hs1 * 10,
- (((hh2 * 60 + mm2) * 60) + ss2) * 1000 + hs2 * 10);
+ MS2RT((((hh1 * 60i64 + mm1) * 60i64) + ss1) * 1000i64 + hs1 * 10i64),
+ MS2RT((((hh2 * 60i64 + mm2) * 60i64) + ss2) * 1000i64 + hs2 * 10i64));
} else if (c != EOF) { // might be another format
return false;
}
@@ -942,14 +942,14 @@ static bool OpenMicroDVD(CTextFile* file, CSimpleTextSubtitle& ret, int CharSet)
if (c == 2) {
if (fCheck2 && ret.GetCount()) {
STSEntry& stse = ret[ret.GetCount() - 1];
- stse.end = std::min(stse.end, start);
+ stse.end = std::min(stse.end, MS2RT(start));
fCheck2 = false;
}
ret.Add(
MicroDVD2SSA(buff.Mid(buff.Find('}', buff.Find('}') + 1) + 1), file->IsUnicode(), CharSet),
file->IsUnicode(),
- start, end,
+ MS2RT(start), MS2RT(end),
style);
if (fCheck) {
@@ -1123,7 +1123,7 @@ static bool OpenSami(CTextFile* file, CSimpleTextSubtitle& ret, int CharSet)
ret.Add(
SMI2SSA(caption, CharSet),
file->IsUnicode(),
- start_time, time);
+ MS2RT(start_time), MS2RT(time));
start_time = time;
caption.Empty();
@@ -1140,7 +1140,7 @@ static bool OpenSami(CTextFile* file, CSimpleTextSubtitle& ret, int CharSet)
ret.Add(
SMI2SSA(caption, CharSet),
file->IsUnicode(),
- start_time, MAXLONG);
+ MS2RT(start_time), LONGLONG_MAX);
return true;
}
@@ -1168,8 +1168,8 @@ static bool OpenVPlayer(CTextFile* file, CSimpleTextSubtitle& ret, int CharSet)
CStringW str = buff.Mid(buff.Find(':', buff.Find(':', buff.Find(':') + 1) + 1) + 1);
ret.Add(str,
file->IsUnicode(),
- (((hh * 60 + mm) * 60) + ss) * 1000,
- (((hh * 60 + mm) * 60) + ss) * 1000 + 1000 + 50 * str.GetLength());
+ MS2RT((((hh * 60i64 + mm) * 60i64) + ss) * 1000i64),
+ MS2RT((((hh * 60i64 + mm) * 60i64) + ss) * 1000i64 + 1000i64 + 50i64 * str.GetLength()));
} else if (c != EOF) { // might be another format
return false;
}
@@ -1429,8 +1429,8 @@ static bool OpenSubStationAlpha(CTextFile* file, CSimpleTextSubtitle& ret, int C
ret.Add(pszBuff,
file->IsUnicode(),
- (((hh1 * 60 + mm1) * 60) + ss1) * 1000 + ms1_div10 * 10,
- (((hh2 * 60 + mm2) * 60) + ss2) * 1000 + ms2_div10 * 10,
+ MS2RT((((hh1 * 60i64 + mm1) * 60i64) + ss1) * 1000i64 + ms1_div10 * 10i64),
+ MS2RT((((hh2 * 60i64 + mm2) * 60i64) + ss2) * 1000i64 + ms2_div10 * 10i64),
style, actor, effect,
marginRect,
layer);
@@ -1715,8 +1715,8 @@ static bool OpenXombieSub(CTextFile* file, CSimpleTextSubtitle& ret, int CharSet
ret.Add(pszBuff,
file->IsUnicode(),
- (((hh1 * 60 + mm1) * 60) + ss1) * 1000 + ms1,
- (((hh2 * 60 + mm2) * 60) + ss2) * 1000 + ms2,
+ MS2RT((((hh1 * 60i64 + mm1) * 60i64) + ss1) * 1000i64 + ms1),
+ MS2RT((((hh2 * 60i64 + mm2) * 60i64) + ss2) * 1000i64 + ms2),
style, actor, _T(""),
marginRect,
layer);
@@ -1775,7 +1775,8 @@ static bool OpenMPL2(CTextFile* file, CSimpleTextSubtitle& ret, int CharSet)
ret.Add(
MPL22SSA(buff.Mid(buff.Find(']', buff.Find(']') + 1) + 1), file->IsUnicode(), CharSet),
file->IsUnicode(),
- start * 100, end * 100);
+ MS2RT(start * 100i64),
+ MS2RT(end * 100i64));
} else if (c != EOF) { // might be another format
return false;
}
@@ -1866,7 +1867,7 @@ void CSimpleTextSubtitle::Copy(CSimpleTextSubtitle& sts)
}
}
-void CSimpleTextSubtitle::Append(CSimpleTextSubtitle& sts, int timeoff)
+void CSimpleTextSubtitle::Append(CSimpleTextSubtitle& sts, REFERENCE_TIME timeoff)
{
if (timeoff < 0) {
timeoff = !IsEmpty() ? GetAt(GetCount() - 1).end : 0;
@@ -1938,12 +1939,12 @@ void CSimpleTextSubtitle::Empty()
RemoveAll();
}
-static bool SegmentCompStart(const STSSegment& segment, int start)
+static bool SegmentCompStart(const STSSegment& segment, REFERENCE_TIME start)
{
return (segment.start < start);
}
-void CSimpleTextSubtitle::Add(CStringW str, bool fUnicode, int start, int end, CString style, CString actor, CString effect, const CRect& marginRect, int layer, int readorder)
+void CSimpleTextSubtitle::Add(CStringW str, bool fUnicode, REFERENCE_TIME start, REFERENCE_TIME end, CString style, CString actor, CString effect, const CRect& marginRect, int layer, int readorder)
{
FastTrim(str);
if (str.IsEmpty() || start > end) {
@@ -2008,7 +2009,7 @@ void CSimpleTextSubtitle::Add(CStringW str, bool fUnicode, int start, int end, C
i++;
}
- int lastEnd = INT_MAX;
+ REFERENCE_TIME lastEnd = _I64_MAX;
for (; i < m_segments.GetCount() && m_segments[i].start < end; i++) {
STSSegment& s = m_segments[i];
@@ -2186,8 +2187,8 @@ void CSimpleTextSubtitle::ConvertToTimeBased(double fps)
for (size_t i = 0, j = GetCount(); i < j; i++) {
STSEntry& stse = (*this)[i];
- stse.start = (int)(stse.start * 1000.0 / fps + 0.5);
- stse.end = (int)(stse.end * 1000.0 / fps + 0.5);
+ stse.start = std::llround(stse.start * UNITS_FLOAT / fps);
+ stse.end = std::llround(stse.end * UNITS_FLOAT / fps);
}
m_mode = TIME;
@@ -2203,8 +2204,8 @@ void CSimpleTextSubtitle::ConvertToFrameBased(double fps)
for (size_t i = 0, j = GetCount(); i < j; i++) {
STSEntry& stse = (*this)[i];
- stse.start = (int)(stse.start * fps / 1000 + 0.5);
- stse.end = (int)(stse.end * fps / 1000 + 0.5);
+ stse.start = std::llround(stse.start * fps / UNITS);
+ stse.end = std::llround(stse.end * fps / UNITS);
}
m_mode = FRAME;
@@ -2212,7 +2213,7 @@ void CSimpleTextSubtitle::ConvertToFrameBased(double fps)
CreateSegments();
}
-int CSimpleTextSubtitle::SearchSub(int t, double fps)
+int CSimpleTextSubtitle::SearchSub(REFERENCE_TIME t, double fps)
{
int i = 0, j = (int)GetCount() - 1, ret = -1;
@@ -2223,7 +2224,7 @@ int CSimpleTextSubtitle::SearchSub(int t, double fps)
while (i < j) {
int mid = (i + j) >> 1;
- int midt = TranslateStart(mid, fps);
+ REFERENCE_TIME midt = TranslateStart(mid, fps);
if (t == midt) {
while (mid > 0 && t == TranslateStart(mid - 1, fps)) {
@@ -2249,7 +2250,7 @@ int CSimpleTextSubtitle::SearchSub(int t, double fps)
return ret;
}
-const STSSegment* CSimpleTextSubtitle::SearchSubs(int t, double fps, /*[out]*/ int* iSegment, int* nSegments)
+const STSSegment* CSimpleTextSubtitle::SearchSubs(REFERENCE_TIME t, double fps, /*[out]*/ int* iSegment, int* nSegments)
{
int i = 0, j = (int)m_segments.GetCount() - 1, ret = -1;
@@ -2284,7 +2285,7 @@ const STSSegment* CSimpleTextSubtitle::SearchSubs(int t, double fps, /*[out]*/ i
while (i < j) {
int mid = (i + j) >> 1;
- int midt = TranslateSegmentStart(mid, fps);
+ REFERENCE_TIME midt = TranslateSegmentStart(mid, fps);
if (t == midt) {
ret = mid;
@@ -2319,35 +2320,35 @@ const STSSegment* CSimpleTextSubtitle::SearchSubs(int t, double fps, /*[out]*/ i
return nullptr;
}
-int CSimpleTextSubtitle::TranslateStart(int i, double fps)
+REFERENCE_TIME CSimpleTextSubtitle::TranslateStart(int i, double fps)
{
return (i < 0 || GetCount() <= (size_t)i ? -1 :
m_mode == TIME ? GetAt(i).start :
- m_mode == FRAME ? (int)(GetAt(i).start * 1000 / fps) :
+ m_mode == FRAME ? std::llround(GetAt(i).start * UNITS_FLOAT / fps) :
0);
}
-int CSimpleTextSubtitle::TranslateEnd(int i, double fps)
+REFERENCE_TIME CSimpleTextSubtitle::TranslateEnd(int i, double fps)
{
return (i < 0 || GetCount() <= (size_t)i ? -1 :
m_mode == TIME ? GetAt(i).end :
- m_mode == FRAME ? (int)(GetAt(i).end * 1000 / fps) :
+ m_mode == FRAME ? std::llround(GetAt(i).end * UNITS_FLOAT / fps) :
0);
}
-int CSimpleTextSubtitle::TranslateSegmentStart(int i, double fps)
+REFERENCE_TIME CSimpleTextSubtitle::TranslateSegmentStart(int i, double fps)
{
return (i < 0 || m_segments.GetCount() <= (size_t)i ? -1 :
m_mode == TIME ? m_segments[i].start :
- m_mode == FRAME ? (int)(m_segments[i].start * 1000 / fps) :
+ m_mode == FRAME ? std::llround(m_segments[i].start * UNITS_FLOAT / fps) :
0);
}
-int CSimpleTextSubtitle::TranslateSegmentEnd(int i, double fps)
+REFERENCE_TIME CSimpleTextSubtitle::TranslateSegmentEnd(int i, double fps)
{
return (i < 0 || m_segments.GetCount() <= (size_t)i ? -1 :
m_mode == TIME ? m_segments[i].end :
- m_mode == FRAME ? (int)(m_segments[i].end * 1000 / fps) :
+ m_mode == FRAME ? std::llround(m_segments[i].end * UNITS_FLOAT / fps) :
0);
}
@@ -2518,7 +2519,7 @@ void CSimpleTextSubtitle::SetStr(int i, CStringW str, bool fUnicode)
static int comp1(const void* a, const void* b)
{
- int ret = ((STSEntry*)a)->start - ((STSEntry*)b)->start;
+ int ret = SGN(((STSEntry*)a)->start - ((STSEntry*)b)->start);
if (ret == 0) {
ret = ((STSEntry*)a)->layer - ((STSEntry*)b)->layer;
}
@@ -2540,10 +2541,10 @@ void CSimpleTextSubtitle::Sort(bool fRestoreReadorder)
}
struct Breakpoint {
- int t;
+ REFERENCE_TIME t;
bool isStart;
- Breakpoint(int t, bool isStart) : t(t), isStart(isStart) {};
+ Breakpoint(REFERENCE_TIME t, bool isStart) : t(t), isStart(isStart) {};
};
static int BreakpointComp(const void* e1, const void* e2)
@@ -2551,7 +2552,7 @@ static int BreakpointComp(const void* e1, const void* e2)
const Breakpoint* bp1 = (const Breakpoint*)e1;
const Breakpoint* bp2 = (const Breakpoint*)e2;
- return (bp1->t - bp2->t);
+ return SGN(bp1->t - bp2->t);
}
void CSimpleTextSubtitle::CreateSegments()
@@ -2713,7 +2714,7 @@ bool CSimpleTextSubtitle::Open(BYTE* data, int len, int CharSet, CString name)
}
bool CSimpleTextSubtitle::SaveAs(CString fn, Subtitle::SubType type,
- double fps /*= -1*/, int delay /*= 0*/,
+ double fps /*= -1*/, LONGLONG delay /*= 0*/,
CTextFile::enc e /*= CTextFile::DEFAULT_ENCODING*/, bool bCreateExternalStyleFile /*= true*/)
{
LPCTSTR ext = Subtitle::GetSubtitleFileExt(type);
@@ -2840,19 +2841,19 @@ bool CSimpleTextSubtitle::SaveAs(CString fn, Subtitle::SubType type,
// Sort(true);
if (m_mode == FRAME) {
- delay = int(delay * fps / 1000);
+ delay = std::lround(delay * fps / 1000.0);
}
for (int i = 0, j = (int)GetCount(), k = 0; i < j; i++) {
STSEntry& stse = GetAt(i);
- int t1 = TranslateStart(i, fps) + delay;
+ int t1 = (int)(RT2MS(TranslateStart(i, fps)) + delay);
if (t1 < 0) {
k++;
continue;
}
- int t2 = TranslateEnd(i, fps) + delay;
+ int t2 = (int)(RT2MS(TranslateEnd(i, fps)) + delay);
int hh1 = (t1 / 60 / 60 / 1000);
int mm1 = (t1 / 60 / 1000) % 60;
@@ -3163,8 +3164,8 @@ static bool OpenRealText(CTextFile* file, CSimpleTextSubtitle& ret, int CharSet)
ret.Add(
SubRipper2SSA(i->second.c_str(), CharSet),
file->IsUnicode(),
- i->first.first,
- i->first.second);
+ MS2RT(i->first.first),
+ MS2RT(i->first.second));
}
return !ret.IsEmpty();
diff --git a/src/Subtitles/STS.h b/src/Subtitles/STS.h
index b927b7052..b5fab63f0 100644
--- a/src/Subtitles/STS.h
+++ b/src/Subtitles/STS.h
@@ -93,20 +93,20 @@ struct STSEntry {
CString style, actor, effect;
CRect marginRect;
int layer;
- int start, end;
+ REFERENCE_TIME start, end;
int readorder;
};
class STSSegment
{
public:
- int start, end;
+ REFERENCE_TIME start, end;
CAtlArray<int> subs;
STSSegment()
: start(0)
, end(0) {}
- STSSegment(int s, int e) {
+ STSSegment(REFERENCE_TIME s, REFERENCE_TIME e) {
start = s;
end = e;
}
@@ -170,14 +170,14 @@ public:
void Sort(bool fRestoreReadorder = false);
void CreateSegments();
- void Append(CSimpleTextSubtitle& sts, int timeoff = -1);
+ void Append(CSimpleTextSubtitle& sts, REFERENCE_TIME timeoff = -1);
bool Open(CString fn, int CharSet, CString name = _T(""), CString videoName = _T(""));
bool Open(CTextFile* f, int CharSet, CString name);
bool Open(BYTE* data, int len, int CharSet, CString name);
- bool SaveAs(CString fn, Subtitle::SubType type, double fps = -1, int delay = 0, CTextFile::enc e = CTextFile::DEFAULT_ENCODING, bool bCreateExternalStyleFile = true);
+ bool SaveAs(CString fn, Subtitle::SubType type, double fps = -1, LONGLONG delay = 0, CTextFile::enc e = CTextFile::DEFAULT_ENCODING, bool bCreateExternalStyleFile = true);
- void Add(CStringW str, bool fUnicode, int start, int end, CString style = _T("Default"), CString actor = _T(""), CString effect = _T(""), const CRect& marginRect = CRect(0, 0, 0, 0), int layer = 0, int readorder = -1);
+ void Add(CStringW str, bool fUnicode, REFERENCE_TIME start, REFERENCE_TIME end, CString style = _T("Default"), CString actor = _T(""), CString effect = _T(""), const CRect& marginRect = CRect(0, 0, 0, 0), int layer = 0, int readorder = -1);
STSStyle* CreateDefaultStyle(int CharSet);
void ChangeUnknownStylesToDefault();
void AddStyle(CString name, STSStyle* style); // style will be stored and freed in Empty() later
@@ -189,13 +189,13 @@ public:
void ConvertToTimeBased(double fps);
void ConvertToFrameBased(double fps);
- int TranslateStart(int i, double fps);
- int TranslateEnd(int i, double fps);
- int SearchSub(int t, double fps);
+ REFERENCE_TIME TranslateStart(int i, double fps);
+ REFERENCE_TIME TranslateEnd(int i, double fps);
+ int SearchSub(REFERENCE_TIME t, double fps);
- int TranslateSegmentStart(int i, double fps);
- int TranslateSegmentEnd(int i, double fps);
- const STSSegment* SearchSubs(int t, double fps, /*[out]*/ int* iSegment = nullptr, int* nSegments = nullptr);
+ REFERENCE_TIME TranslateSegmentStart(int i, double fps);
+ REFERENCE_TIME TranslateSegmentEnd(int i, double fps);
+ const STSSegment* SearchSubs(REFERENCE_TIME t, double fps, /*[out]*/ int* iSegment = nullptr, int* nSegments = nullptr);
const STSSegment* GetSegment(int iSegment) {
return iSegment >= 0 && iSegment < (int)m_segments.GetCount() ? &m_segments[iSegment] : nullptr;
}
diff --git a/src/Subtitles/SubtitleHelpers.h b/src/Subtitles/SubtitleHelpers.h
index d004cae67..cf691e5fb 100644
--- a/src/Subtitles/SubtitleHelpers.h
+++ b/src/Subtitles/SubtitleHelpers.h
@@ -1,6 +1,6 @@
/*
* (C) 2003-2006 Gabest
- * (C) 2006-2014 see Authors.txt
+ * (C) 2006-2015 see Authors.txt
*
* This file is part of MPC-HC.
*
@@ -24,6 +24,10 @@
#include <afx.h>
#include <atlcoll.h>
+#define MS2RT(t) (10000i64 * (t))
+#define RT2MS(t) ((t) / 10000)
+#define UNITS_FLOAT (10000000.0)
+
namespace Subtitle
{
enum SubType {
diff --git a/src/Subtitles/SubtitleInputPin.cpp b/src/Subtitles/SubtitleInputPin.cpp
index a7cf216ec..0d4272cc7 100644
--- a/src/Subtitles/SubtitleInputPin.cpp
+++ b/src/Subtitles/SubtitleInputPin.cpp
@@ -379,12 +379,12 @@ REFERENCE_TIME CSubtitleInputPin::DecodeSample(const std::unique_ptr<SubtitleSam
if (tag == __GAB1_LANGUAGE__) {
pRTS->m_name = CString(ptr);
} else if (tag == __GAB1_ENTRY__) {
- pRTS->Add(AToW(&ptr[8]), false, *(int*)ptr, *(int*)(ptr + 4));
+ pRTS->Add(AToW(&ptr[8]), false, MS2RT(*(int*)ptr), MS2RT(*(int*)(ptr + 4)));
bInvalidate = true;
} else if (tag == __GAB1_LANGUAGE_UNICODE__) {
pRTS->m_name = (WCHAR*)ptr;
} else if (tag == __GAB1_ENTRY_UNICODE__) {
- pRTS->Add((WCHAR*)(ptr + 8), true, *(int*)ptr, *(int*)(ptr + 4));
+ pRTS->Add((WCHAR*)(ptr + 8), true, MS2RT(*(int*)ptr), MS2RT(*(int*)(ptr + 4)));
bInvalidate = true;
}
@@ -416,7 +416,7 @@ REFERENCE_TIME CSubtitleInputPin::DecodeSample(const std::unique_ptr<SubtitleSam
str.Trim();
if (!str.IsEmpty()) {
- pRTS->Add(AToW(str), false, (int)(pSample->rtStart / 10000), (int)(pSample->rtStop / 10000));
+ pRTS->Add(AToW(str), false, pSample->rtStart, pSample->rtStop);
bInvalidate = true;
}
}
@@ -426,7 +426,7 @@ REFERENCE_TIME CSubtitleInputPin::DecodeSample(const std::unique_ptr<SubtitleSam
CStringW str = UTF8To16(CStringA((LPCSTR)pSample->data.data(), (int)pSample->data.size())).Trim();
if (!str.IsEmpty()) {
- pRTS->Add(str, true, (int)(pSample->rtStart / 10000), (int)(pSample->rtStop / 10000));
+ pRTS->Add(str, true, pSample->rtStart, pSample->rtStop);
bInvalidate = true;
}
} else if (m_mt.subtype == MEDIASUBTYPE_SSA || m_mt.subtype == MEDIASUBTYPE_ASS || m_mt.subtype == MEDIASUBTYPE_ASS2) {
@@ -456,7 +456,7 @@ REFERENCE_TIME CSubtitleInputPin::DecodeSample(const std::unique_ptr<SubtitleSam
}
if (!stse.str.IsEmpty()) {
- pRTS->Add(stse.str, true, (int)(pSample->rtStart / 10000), (int)(pSample->rtStop / 10000),
+ pRTS->Add(stse.str, true, pSample->rtStart, pSample->rtStop,
stse.style, stse.actor, stse.effect, stse.marginRect, stse.layer, stse.readorder);
bInvalidate = true;
}
diff --git a/src/filters/transform/VSFilter/Copy.cpp b/src/filters/transform/VSFilter/Copy.cpp
index b6c65e0d8..70c761abb 100644
--- a/src/filters/transform/VSFilter/Copy.cpp
+++ b/src/filters/transform/VSFilter/Copy.cpp
@@ -184,10 +184,10 @@ void CDirectVobSubFilter::PrintMessages(BYTE* pOut)
bihOut.biWidth, bihOut.biHeight,
Subtype2String(m_pOutput->CurrentMediaType().subtype));
- msg.AppendFormat(_T("real fps: %.3f, current fps: %.3f\nmedia time: %d, subtitle time: %I64d [ms]\nframe number: %d (calculated)\nrate: %.4lf\n"),
+ msg.AppendFormat(_T("real fps: %.3f, current fps: %.3f\nmedia time: %I64d, subtitle time: %I64d [ms]\nframe number: %I64d (calculated)\nrate: %.4lf\n"),
m_fps, m_fMediaFPSEnabled ? m_MediaFPS : fabs(m_fps),
- m_tPrev.Millisecs(), CalcCurrentTime() / 10000,
- (int)(m_tPrev.m_time * m_fps / 10000000),
+ RT2MS(m_tPrev.GetUnits()), RT2MS(CalcCurrentTime()),
+ std::llround(m_tPrev.m_time * m_fps / UNITS_FLOAT),
m_pInput->CurrentRate());
CAutoLock cAutoLock(&m_csQueueLock);
@@ -196,11 +196,11 @@ void CDirectVobSubFilter::PrintMessages(BYTE* pOut)
int nSubPics = -1;
REFERENCE_TIME rtNow = -1, rtStart = -1, rtStop = -1;
m_pSubPicQueue->GetStats(nSubPics, rtNow, rtStart, rtStop);
- msg.AppendFormat(_T("queue stats: %I64d - %I64d [ms]\n"), rtStart / 10000, rtStop / 10000);
+ msg.AppendFormat(_T("queue stats: %I64d - %I64d [ms]\n"), RT2MS(rtStart), RT2MS(rtStop));
for (int i = 0; i < nSubPics; i++) {
m_pSubPicQueue->GetStats(i, rtStart, rtStop);
- msg.AppendFormat(_T("%d: %I64d - %I64d [ms]\n"), i, rtStart / 10000, rtStop / 10000);
+ msg.AppendFormat(_T("%d: %I64d - %I64d [ms]\n"), i, RT2MS(rtStart), RT2MS(rtStop));
}
}
diff --git a/src/filters/transform/VSFilter/DirectVobSub.cpp b/src/filters/transform/VSFilter/DirectVobSub.cpp
index f8cdc9b1c..e264644a2 100644
--- a/src/filters/transform/VSFilter/DirectVobSub.cpp
+++ b/src/filters/transform/VSFilter/DirectVobSub.cpp
@@ -55,6 +55,10 @@ CDirectVobSub::CDirectVobSub()
m_fMediaFPSEnabled = !!theApp.GetProfileInt(ResStr(IDS_R_TIMING), ResStr(IDS_RTM_MEDIAFPSENABLED), FALSE);
m_ePARCompensationType = static_cast<CSimpleTextSubtitle::EPARCompensationType>(theApp.GetProfileInt(ResStr(IDS_R_TEXT), ResStr(IDS_RT_AUTOPARCOMPENSATION), 0));
+ int gcd = GCD(m_SubtitleSpeedMul, m_SubtitleSpeedDiv);
+ m_SubtitleSpeedNormalizedMul = m_SubtitleSpeedMul / gcd;
+ m_SubtitleSpeedNormalizedDiv = m_SubtitleSpeedDiv / gcd;
+
BYTE* pData = nullptr;
UINT nSize;
if (theApp.GetProfileBinary(ResStr(IDS_R_TIMING), ResStr(IDS_RTM_MEDIAFPS), &pData, &nSize) && pData) {
@@ -459,6 +463,10 @@ STDMETHODIMP CDirectVobSub::put_SubtitleTiming(int delay, int speedmul, int spee
m_SubtitleSpeedDiv = speeddiv;
}
+ int gcd = GCD(m_SubtitleSpeedMul, m_SubtitleSpeedDiv);
+ m_SubtitleSpeedNormalizedMul = m_SubtitleSpeedMul / gcd;
+ m_SubtitleSpeedNormalizedDiv = m_SubtitleSpeedDiv / gcd;
+
return S_OK;
}
diff --git a/src/filters/transform/VSFilter/DirectVobSub.h b/src/filters/transform/VSFilter/DirectVobSub.h
index 6282020c3..9321f6ae9 100644
--- a/src/filters/transform/VSFilter/DirectVobSub.h
+++ b/src/filters/transform/VSFilter/DirectVobSub.h
@@ -1,6 +1,6 @@
/*
* (C) 2003-2006 Gabest
- * (C) 2006-2014 see Authors.txt
+ * (C) 2006-2015 see Authors.txt
*
* This file is part of MPC-HC.
*
@@ -49,6 +49,9 @@ protected:
bool m_fOSD;
int m_nReloaderDisableCount;
int m_SubtitleDelay, m_SubtitleSpeedMul, m_SubtitleSpeedDiv;
+ // User could specify any values for m_SubtitleSpeedMul and m_SubtitleSpeedDiv.
+ // We want to normalize the user input to minimize the chance of overflow later when we do calculations.
+ int m_SubtitleSpeedNormalizedMul, m_SubtitleSpeedNormalizedDiv;
bool m_fMediaFPSEnabled;
double m_MediaFPS;
bool m_fSaveFullPath;
diff --git a/src/filters/transform/VSFilter/DirectVobSubFilter.cpp b/src/filters/transform/VSFilter/DirectVobSubFilter.cpp
index beefbdeac..b049e2498 100644
--- a/src/filters/transform/VSFilter/DirectVobSubFilter.cpp
+++ b/src/filters/transform/VSFilter/DirectVobSubFilter.cpp
@@ -518,7 +518,7 @@ HRESULT CDirectVobSubFilter::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tS
REFERENCE_TIME CDirectVobSubFilter::CalcCurrentTime()
{
REFERENCE_TIME rt = m_pSubClock ? m_pSubClock->GetTime() : m_tPrev;
- return (rt - 10000i64 * m_SubtitleDelay) * m_SubtitleSpeedMul / m_SubtitleSpeedDiv; // no, it won't overflow if we use normal parameters (__int64 is enough for about 2000 hours if we multiply it by the max: 65536 as m_SubtitleSpeedMul)
+ return (rt - 10000i64 * m_SubtitleDelay) * m_SubtitleSpeedNormalizedMul / m_SubtitleSpeedNormalizedDiv; // no, it won't overflow if we use normal parameters (__int64 is enough for about 2000 hours if we multiply it by the max: 65536 as m_SubtitleSpeedMul)
}
void CDirectVobSubFilter::InitSubPicQueue()
diff --git a/src/mpc-hc/PlayerSubresyncBar.cpp b/src/mpc-hc/PlayerSubresyncBar.cpp
index 52f18d5c7..ac1ef2b4f 100644
--- a/src/mpc-hc/PlayerSubresyncBar.cpp
+++ b/src/mpc-hc/PlayerSubresyncBar.cpp
@@ -139,7 +139,7 @@ void CPlayerSubresyncBar::SetTime(REFERENCE_TIME rt)
m_rt = rt;
int curSegment;
- if (!m_sts.SearchSubs((int)(rt / 10000), 25, &curSegment)) {
+ if (!m_sts.SearchSubs(rt, 25, &curSegment)) {
curSegment = -1;
}
@@ -258,7 +258,7 @@ void CPlayerSubresyncBar::ResetSubtitle()
m_list.DeleteAllItems();
if (m_mode == VOBSUB || m_mode == TEXTSUB) {
- int prevstart = INT_MIN;
+ REFERENCE_TIME prevstart = INT64_MIN;
size_t nCount = m_sts.GetCount();
m_displayData.resize(nCount);
@@ -386,7 +386,7 @@ void CPlayerSubresyncBar::UpdatePreview()
}
} else if (schk.GetCount() == 1) {
int k = schk[0];
- int dt = m_subtimes[k].newStart - m_subtimes[k].orgStart;
+ REFERENCE_TIME dt = m_subtimes[k].newStart - m_subtimes[k].orgStart;
for (; start < end; start++) {
m_sts[start].start = m_subtimes[start].orgStart + dt;
m_sts[start].end = (m_displayData[start].flags & TEMOD)
@@ -396,8 +396,8 @@ void CPlayerSubresyncBar::UpdatePreview()
} else if (schk.GetCount() >= 2) {
int i0 = 0;
int i1 = 0;
- int ti0 = 0;
- int ds = 0;
+ REFERENCE_TIME ti0 = 0;
+ REFERENCE_TIME ds = 0;
double m = 0;
int k, l;
@@ -443,11 +443,11 @@ void CPlayerSubresyncBar::UpdatePreview()
}
}
-void CPlayerSubresyncBar::SetSTS0(int& start, int end, int ti0)
+void CPlayerSubresyncBar::SetSTS0(int& start, int end, REFERENCE_TIME ti0)
{
for (; start < end; start++) {
m_sts[start].start = ti0;
- int endpos;
+ REFERENCE_TIME endpos;
if (m_displayData[start].flags & TEMOD) {
endpos = m_subtimes[start].newEnd;
} else {
@@ -457,19 +457,19 @@ void CPlayerSubresyncBar::SetSTS0(int& start, int end, int ti0)
}
}
-void CPlayerSubresyncBar::SetSTS1(int& start, int end, int ti0, double m, int i0)
+void CPlayerSubresyncBar::SetSTS1(int& start, int end, REFERENCE_TIME ti0, double m, int i0)
{
for (; start < end; start++) {
- m_sts[start].start = int((m_subtimes[start].orgStart - ti0) * m + m_subtimes[i0].newStart);
- int endpos;
+ m_sts[start].start = REFERENCE_TIME((m_subtimes[start].orgStart - ti0) * m + m_subtimes[i0].newStart);
+ REFERENCE_TIME endpos;
if (m_displayData[start].flags & TEMOD) {
endpos = m_subtimes[start].newEnd;
} else {
- int diff = m_subtimes[start].orgEnd - m_subtimes[start].orgStart;
+ REFERENCE_TIME diff = m_subtimes[start].orgEnd - m_subtimes[start].orgStart;
if (m_mode == VOBSUB) {
endpos = m_sts[start].start + diff;
} else {
- endpos = m_sts[start].start + int(diff * m);
+ endpos = m_sts[start].start + REFERENCE_TIME(diff * m);
}
}
m_sts[start].end = endpos;
@@ -511,7 +511,7 @@ void CPlayerSubresyncBar::SetCheck(int iItem, bool bStart, bool bEnd)
}
}
-bool CPlayerSubresyncBar::ModStart(int iItem, int t, bool bReset)
+bool CPlayerSubresyncBar::ModStart(int iItem, REFERENCE_TIME t, bool bReset)
{
bool bRet = false;
bool bStartMod, bEndMod, bStartAdj, bEndAdj;
@@ -539,7 +539,7 @@ bool CPlayerSubresyncBar::ModStart(int iItem, int t, bool bReset)
return bRet;
}
-bool CPlayerSubresyncBar::ModEnd(int iItem, int t, bool bReset)
+bool CPlayerSubresyncBar::ModEnd(int iItem, REFERENCE_TIME t, bool bReset)
{
bool bRet = false;
bool bStartMod, bEndMod, bStartAdj, bEndAdj;
@@ -605,14 +605,17 @@ void CPlayerSubresyncBar::OnGetDisplayInfo(NMHDR* pNMHDR, LRESULT* pResult)
}
if (pItem->mask & LVIF_TEXT) {
- auto formatTime = [](int t, TCHAR * buff, size_t buffLen) {
+ auto formatTime = [](REFERENCE_TIME t, TCHAR * buff, size_t buffLen) {
+ int ms = int(RT2MS(abs(t)));
+ int s = ms / 1000;
+ int m = s / 60;
_stprintf_s(buff, buffLen, t >= 0
? _T("%02d:%02d:%02d.%03d")
: _T("-%02d:%02d:%02d.%03d"),
- abs(t) / 60 / 60 / 1000,
- (abs(t) / 60 / 1000) % 60,
- (abs(t) / 1000) % 60,
- abs(t) % 1000);
+ m / 60,
+ m % 60,
+ s % 60,
+ ms % 1000);
};
switch (pItem->iSubItem) {
@@ -703,7 +706,7 @@ void CPlayerSubresyncBar::OnGetDisplayInfoVobSub(LV_ITEM* pItem)
}
}
-static bool ParseTime(CString str, int& ret, bool bWarn = true)
+static bool ParseTime(CString str, REFERENCE_TIME& ret, bool bWarn = true)
{
int sign = 1, h, m, s, ms;
TCHAR c;
@@ -722,7 +725,7 @@ static bool ParseTime(CString str, int& ret, bool bWarn = true)
&& 0 <= m && m < 60
&& 0 <= s && s < 60
&& 0 <= ms && ms < 1000) {
- ret = sign * (h * 60 * 60 * 1000 + m * 60 * 1000 + s * 1000 + ms);
+ ret = MS2RT(sign * (h * 60 * 60 * 1000 + m * 60 * 1000 + s * 1000 + ms));
return true;
}
@@ -790,7 +793,7 @@ void CPlayerSubresyncBar::OnEndlabeleditList(NMHDR* pNMHDR, LRESULT* pResult)
switch (pItem->iSubItem) {
case COL_START: {
- int t;
+ REFERENCE_TIME t;
if (ParseTime(pItem->pszText, t)) {
bNeedsUpdate = ModStart(pItem->iItem, t);
@@ -800,7 +803,7 @@ void CPlayerSubresyncBar::OnEndlabeleditList(NMHDR* pNMHDR, LRESULT* pResult)
break;
case COL_END:
if (m_mode == TEXTSUB) {
- int t;
+ REFERENCE_TIME t;
if (ParseTime(pItem->pszText, t)) {
bNeedsUpdate = ModEnd(pItem->iItem, t);
@@ -1107,7 +1110,7 @@ void CPlayerSubresyncBar::OnRclickList(NMHDR* pNMHDR, LRESULT* pResult)
bNeedsUpdate = true;
break;
case SETCS:
- ModStart(iItem, (int)(m_rt / 10000));
+ ModStart(iItem, m_rt);
bNeedsUpdate = true;
break;
case RESETE:
@@ -1119,7 +1122,7 @@ void CPlayerSubresyncBar::OnRclickList(NMHDR* pNMHDR, LRESULT* pResult)
bNeedsUpdate = true;
break;
case SETCE:
- ModEnd(iItem, (int)(m_rt / 10000));
+ ModEnd(iItem, m_rt);
bNeedsUpdate = true;
break;
default:
@@ -1205,13 +1208,10 @@ void CPlayerSubresyncBar::OnNMDblclkList(NMHDR* pNMHDR, LRESULT* pResult)
if (lpnmlv->iItem >= 0 && lpnmlv->iSubItem >= 0 && (m_mode == VOBSUB || m_mode == TEXTSUB)) {
if (CMainFrame* pMainFrame = AfxGetMainFrame()) {
- int t = 0;
- if (lpnmlv->iSubItem > COL_PREVEND || !ParseTime(m_list.GetItemText(lpnmlv->iItem, lpnmlv->iSubItem), t, false)) {
- t = m_sts[lpnmlv->iItem].start;
+ REFERENCE_TIME rt;
+ if (lpnmlv->iSubItem > COL_PREVEND || !ParseTime(m_list.GetItemText(lpnmlv->iItem, lpnmlv->iSubItem), rt, false)) {
+ rt = m_sts[lpnmlv->iItem].start;
}
-
- REFERENCE_TIME rt = (REFERENCE_TIME)t * 10000;
-
pMainFrame->SeekTo(rt);
}
}
@@ -1270,7 +1270,7 @@ void CPlayerSubresyncBar::OnCustomdrawList(NMHDR* pNMHDR, LRESULT* pResult)
// if (m_totalGroups > 0)
clrTextBk -= ((m_itemGroups[pLVCD->nmcd.dwItemSpec] & 1) ? 0x100010 : 0x200020);
- if (m_sts[pLVCD->nmcd.dwItemSpec].start <= m_rt / 10000 && m_rt / 10000 < m_sts[pLVCD->nmcd.dwItemSpec].end) {
+ if (m_sts[pLVCD->nmcd.dwItemSpec].start <= m_rt && m_rt < m_sts[pLVCD->nmcd.dwItemSpec].end) {
clrText |= 0xFF;
}
@@ -1367,7 +1367,7 @@ bool CPlayerSubresyncBar::HandleShortCuts(const MSG* pMsg)
bHandled = true;
break;
case VK_F5:
- ModStart(iItem, (int)(m_rt / 10000));
+ ModStart(iItem, m_rt);
bHandled = true;
break;
case VK_F2:
@@ -1379,7 +1379,7 @@ bool CPlayerSubresyncBar::HandleShortCuts(const MSG* pMsg)
bHandled = true;
break;
case VK_F6:
- ModEnd(iItem, (int)(m_rt / 10000));
+ ModEnd(iItem, m_rt);
bHandled = bStep = true;
break;
}
@@ -1419,21 +1419,21 @@ int CPlayerSubresyncBar::FindNearestSub(REFERENCE_TIME& rtPos, bool bForward)
return -2;
}
- int lCurTime = int(rtPos / 10000) + (bForward ? 1 : -1);
+ REFERENCE_TIME lCurTime = rtPos + (bForward ? 1 : -1);
if (lCurTime < m_newStartsIndex.begin()->first) {
size_t i = m_newStartsIndex.begin()->second;
- rtPos = m_subtimes[i].newStart * 10000i64;
+ rtPos = m_subtimes[i].newStart;
return bForward ? int(i) : -1;
} else if (lCurTime > m_newStartsIndex.rbegin()->first) {
size_t i = m_newStartsIndex.rbegin()->second;
- rtPos = m_subtimes[i].newStart * 10000i64;
+ rtPos = m_subtimes[i].newStart;
return bForward ? -1 : int(i);
}
for (auto it = m_newStartsIndex.begin(), itPrec = it++; it != m_newStartsIndex.end(); it++, itPrec++) {
if (lCurTime >= itPrec->first && lCurTime < it->first) {
- rtPos = bForward ? it->first * 10000i64 : itPrec->first * 10000i64;
+ rtPos = bForward ? it->first : itPrec->first;
return int(bForward ? it->second : itPrec->second);
}
}
@@ -1455,7 +1455,7 @@ bool CPlayerSubresyncBar::ShiftSubtitle(int nItem, long lValue, REFERENCE_TIME&
UpdatePreview();
SaveSubtitle();
bRet = true;
- rtPos = (REFERENCE_TIME)m_subtimes[nItem].newStart * 10000;
+ rtPos = m_subtimes[nItem].newStart;
}
return bRet;
}
diff --git a/src/mpc-hc/PlayerSubresyncBar.h b/src/mpc-hc/PlayerSubresyncBar.h
index 5aa9446fc..069368a69 100644
--- a/src/mpc-hc/PlayerSubresyncBar.h
+++ b/src/mpc-hc/PlayerSubresyncBar.h
@@ -88,10 +88,10 @@ private:
};
MODE m_mode;
- std::multimap<int, size_t> m_newStartsIndex;
+ std::multimap<REFERENCE_TIME, size_t> m_newStartsIndex;
struct SubTime {
- int orgStart, newStart, orgEnd, newEnd;
- std::multimap<int, size_t>::iterator itIndex;
+ REFERENCE_TIME orgStart, newStart, orgEnd, newEnd;
+ std::multimap<REFERENCE_TIME, size_t>::iterator itIndex;
};
std::vector<SubTime> m_subtimes;
@@ -99,7 +99,7 @@ private:
CAtlArray<CVobSubFile::SubPos> m_vobSub;
struct DisplayData {
- int tStart, tPrevStart, tEnd, tPrevEnd;
+ REFERENCE_TIME tStart, tPrevStart, tEnd, tPrevEnd;
int flags;
};
std::vector<DisplayData> m_displayData;
@@ -115,14 +115,14 @@ private:
TSEP = 0x80000000
};
- void SetSTS0(int& start, int end, int ti0);
- void SetSTS1(int& start, int end, int ti0, double m, int i0);
+ void SetSTS0(int& start, int end, REFERENCE_TIME ti0);
+ void SetSTS1(int& start, int end, REFERENCE_TIME ti0, double m, int i0);
void GetCheck(int iItem, bool& fStartMod, bool& fEndMod, bool& fStartAdj, bool& fEndAdj) const;
void SetCheck(int iItem, bool fStart, bool fEnd);
- bool ModStart(int iItem, int t, bool fReset = false);
- bool ModEnd(int iItem, int t, bool fReset = false);
+ bool ModStart(int iItem, REFERENCE_TIME t, bool fReset = false);
+ bool ModEnd(int iItem, REFERENCE_TIME t, bool fReset = false);
void OnGetDisplayInfoTextSub(LV_ITEM* pItem);
void OnGetDisplayInfoVobSub(LV_ITEM* pItem);