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
diff options
context:
space:
mode:
Diffstat (limited to 'src/Subtitles/RTS.cpp')
-rw-r--r--src/Subtitles/RTS.cpp313
1 files changed, 186 insertions, 127 deletions
diff --git a/src/Subtitles/RTS.cpp b/src/Subtitles/RTS.cpp
index ec158b73d..d52d80ea6 100644
--- a/src/Subtitles/RTS.cpp
+++ b/src/Subtitles/RTS.cpp
@@ -1,6 +1,6 @@
/*
* (C) 2003-2006 Gabest
- * (C) 2006-2014 see Authors.txt
+ * (C) 2006-2016 see Authors.txt
*
* This file is part of MPC-HC.
*
@@ -20,11 +20,12 @@
*/
#include "stdafx.h"
-#include <math.h>
+#include <cmath>
#include <intrin.h>
#include <algorithm>
+#include "ColorConvTable.h"
#include "RTS.h"
-#include "../DSUtil/WinAPIUtils.h"
+#include "../DSUtil/PathUtils.h"
// WARNING: this isn't very thread safe, use only one RTS a time. We should use TLS in future.
static HDC g_hDC;
@@ -39,7 +40,7 @@ static long revcolor(long c)
// CMyFont
-CMyFont::CMyFont(STSStyle& style)
+CMyFont::CMyFont(const STSStyle& style)
{
LOGFONT lf;
ZeroMemory(&lf, sizeof(lf));
@@ -65,24 +66,24 @@ CMyFont::CMyFont(STSStyle& style)
// CWord
-CWord::CWord(STSStyle& style, CStringW str, int ktype, int kstart, int kend, double scalex, double scaley,
+CWord::CWord(const STSStyle& style, CStringW str, int ktype, int kstart, int kend, double scalex, double scaley,
RenderingCaches& renderingCaches)
- : m_style(style)
+ : m_fDrawn(false)
+ , m_p(INT_MAX, INT_MAX)
+ , m_renderingCaches(renderingCaches)
+ , m_scalex(scalex)
+ , m_scaley(scaley)
, m_str(str)
- , m_width(0)
- , m_ascent(0)
- , m_descent(0)
+ , m_fWhiteSpaceChar(false)
+ , m_fLineBreak(false)
+ , m_style(style)
+ , m_pOpaqueBox(nullptr)
, m_ktype(ktype)
, m_kstart(kstart)
, m_kend(kend)
- , m_fDrawn(false)
- , m_p(INT_MAX, INT_MAX)
- , m_fLineBreak(false)
- , m_fWhiteSpaceChar(false)
- , m_pOpaqueBox(nullptr)
- , m_scalex(scalex)
- , m_scaley(scaley)
- , m_renderingCaches(renderingCaches)
+ , m_width(0)
+ , m_ascent(0)
+ , m_descent(0)
{
if (str.IsEmpty()) {
m_fWhiteSpaceChar = m_fLineBreak = true;
@@ -123,17 +124,13 @@ void CWord::Paint(const CPoint& p, const CPoint& org)
if (m_renderingCaches.overlayCache.Lookup(overlayKey, m_pOverlayData)) {
m_fDrawn = m_renderingCaches.outlineCache.Lookup(overlayKey, m_pOutlineData);
if (m_style.borderStyle == 1) {
- if (!CreateOpaqueBox()) {
- return;
- }
+ VERIFY(CreateOpaqueBox());
}
} else {
if (!m_fDrawn) {
if (m_renderingCaches.outlineCache.Lookup(overlayKey, m_pOutlineData)) {
if (m_style.borderStyle == 1) {
- if (!CreateOpaqueBox()) {
- return;
- }
+ VERIFY(CreateOpaqueBox());
}
} else {
if (!CreatePath()) {
@@ -163,9 +160,7 @@ void CWord::Paint(const CPoint& p, const CPoint& org)
return;
}
} else if (m_style.borderStyle == 1) {
- if (!CreateOpaqueBox()) {
- return;
- }
+ VERIFY(CreateOpaqueBox());
}
m_renderingCaches.outlineCache.SetAt(overlayKey, m_pOutlineData);
@@ -192,10 +187,13 @@ void CWord::Paint(const CPoint& p, const CPoint& org)
void CWord::Transform(CPoint org)
{
- if (m_bUseSSE2) { // SSE code
- Transform_SSE2(org);
- } else { // C-code
+#if defined(_M_IX86_FP) && _M_IX86_FP < 2
+ if (!m_bUseSSE2) {
Transform_C(org);
+ } else
+#endif
+ {
+ Transform_SSE2(org);
}
}
@@ -207,12 +205,14 @@ bool CWord::CreateOpaqueBox()
STSStyle style = m_style;
style.borderStyle = 0;
- style.outlineWidthX = style.outlineWidthY = 0;
+ // We don't want to apply the outline and the scaling twice
+ style.outlineWidthX = style.outlineWidthY = 0.0;
+ style.fontScaleX = style.fontScaleY = 100.0;
style.colors[0] = m_style.colors[2];
style.alpha[0] = m_style.alpha[2];
- int w = (int)(m_style.outlineWidthX + 0.5);
- int h = (int)(m_style.outlineWidthY + 0.5);
+ int w = std::lround(m_style.outlineWidthX);
+ int h = std::lround(m_style.outlineWidthY);
// Convert to pixels rounding to nearest
CStringW str;
@@ -222,7 +222,12 @@ bool CWord::CreateOpaqueBox()
(m_width + w + 4) / 8, (m_ascent + m_descent + h + 4) / 8,
-(w + 4) / 8, (m_ascent + m_descent + h + 4) / 8);
- m_pOpaqueBox = DEBUG_NEW CPolygon(style, str, 0, 0, 0, 1.0, 1.0, 0, m_renderingCaches);
+ try {
+ m_pOpaqueBox = DEBUG_NEW CPolygon(style, str, 0, 0, 0, 1.0, 1.0, 0, m_renderingCaches);
+ } catch (CMemoryException* e) {
+ e->Delete();
+ m_pOpaqueBox = nullptr;
+ }
return !!m_pOpaqueBox;
}
@@ -417,7 +422,7 @@ void CWord::Transform_SSE2(const CPoint& org)
// CText
-CText::CText(STSStyle& style, CStringW str, int ktype, int kstart, int kend, double scalex, double scaley,
+CText::CText(const STSStyle& style, CStringW str, int ktype, int kstart, int kend, double scalex, double scaley,
RenderingCaches& renderingCaches)
: CWord(style, str, ktype, kstart, kend, scalex, scaley, renderingCaches)
{
@@ -528,7 +533,7 @@ bool CText::CreatePath()
// CPolygon
-CPolygon::CPolygon(STSStyle& style, CStringW str, int ktype, int kstart, int kend, double scalex, double scaley, int baseline,
+CPolygon::CPolygon(const STSStyle& style, CStringW str, int ktype, int kstart, int kend, double scalex, double scaley, int baseline,
RenderingCaches& renderingCaches)
: CWord(style, str, ktype, kstart, kend, scalex, scaley, renderingCaches)
, m_baseline(baseline)
@@ -604,14 +609,16 @@ bool CPolygon::ParseStr()
};
for (LPCWSTR str = m_str; *str;) {
- // Trim left whitespace
- while (CStringW::StrTraits::IsSpace(*str)) {
+ // Trim any leading invalid characters and whitespace
+ while (*str && !isValidAction(*str)) {
str++;
}
const WCHAR c = *str;
- do {
- str++;
- } while (isValidAction(*str));
+ if (*str) {
+ do {
+ str++;
+ } while (isValidAction(*str));
+ }
switch (c) {
case L'm':
if (!bFoundMove) {
@@ -792,9 +799,14 @@ CClipper::CClipper(CStringW str, const CSize& size, double scalex, double scaley
e->Delete();
return;
}
+ memset(m_pAlphaMask, (m_inverse ? 0x40 : 0), alphaMaskSize);
Paint(CPoint(0, 0), CPoint(0, 0));
+ if (!m_pOverlayData) {
+ return;
+ }
+
int w = m_pOverlayData->mOverlayWidth, h = m_pOverlayData->mOverlayHeight;
int x = (m_pOverlayData->mOffsetX + m_cpOffset.x + 4) >> 3, y = (m_pOverlayData->mOffsetY + m_cpOffset.y + 4) >> 3;
@@ -821,8 +833,6 @@ CClipper::CClipper(CStringW str, const CSize& size, double scalex, double scaley
return;
}
- memset(m_pAlphaMask, (m_inverse ? 0x40 : 0), alphaMaskSize);
-
const BYTE* src = m_pOverlayData->mpOverlayBufferBody + m_pOverlayData->mOverlayPitch * yo + xo;
BYTE* dst = m_pAlphaMask + m_size.cx * y + x;
@@ -957,6 +967,7 @@ CRect CLine::PaintShadow(SubPicDesc& spd, CRect& clipRect, BYTE* pAlphaMask, CPo
}
COLORREF shadow = revcolor(w->m_style.colors[3]) | (a << 24);
DWORD sw[6] = {shadow, DWORD_MAX};
+ sw[0] = ColorConvTable::ColorCorrection(sw[0]);
w->Paint(CPoint(x, y), org);
@@ -987,7 +998,7 @@ CRect CLine::PaintOutline(SubPicDesc& spd, CRect& clipRect, BYTE* pAlphaMask, CP
return bbox; // should not happen since this class is just a line of text without any breaks
}
- if (w->m_style.outlineWidthX + w->m_style.outlineWidthY > 0 && !(w->m_ktype == 2 && time < w->m_kstart)) {
+ if ((w->m_style.outlineWidthX + w->m_style.outlineWidthY > 0 || w->m_style.borderStyle == 1) && !(w->m_ktype == 2 && time < w->m_kstart)) {
int x = p.x;
int y = p.y + m_ascent - w->m_ascent;
DWORD aoutline = w->m_style.alpha[2];
@@ -996,6 +1007,7 @@ CRect CLine::PaintOutline(SubPicDesc& spd, CRect& clipRect, BYTE* pAlphaMask, CP
}
COLORREF outline = revcolor(w->m_style.colors[2]) | ((0xff - aoutline) << 24);
DWORD sw[6] = {outline, DWORD_MAX};
+ sw[0] = ColorConvTable::ColorCorrection(sw[0]);
w->Paint(CPoint(x, y), org);
@@ -1075,14 +1087,14 @@ CRect CLine::PaintBody(SubPicDesc& spd, CRect& clipRect, BYTE* pAlphaMask, CPoin
if (w->m_style.fBlur) {
bluradjust += 8;
}
- double tx = w->m_style.fontAngleZ;
- UNREFERENCED_PARAMETER(tx);
- sw[4] = sw[2];
- sw[5] = 0x00ffffff;
w->Paint(CPoint(x, y), org);
+ sw[0] = ColorConvTable::ColorCorrection(sw[0]);
+ sw[2] = ColorConvTable::ColorCorrection(sw[2]);
sw[3] = (int)(w->m_style.outlineWidthX + t * w->getOverlayWidth() + t * bluradjust) >> 3;
+ sw[4] = sw[2];
+ sw[5] = 0x00ffffff;
bbox |= w->Draw(spd, clipRect, pAlphaMask, x, y, sw, true, false);
p.x += w->m_width;
@@ -1096,19 +1108,19 @@ CRect CLine::PaintBody(SubPicDesc& spd, CRect& clipRect, BYTE* pAlphaMask, CPoin
CSubtitle::CSubtitle(RenderingCaches& renderingCaches)
: m_renderingCaches(renderingCaches)
- , m_pClipper(nullptr)
- , m_clipInverse(false)
- , m_scalex(1.0)
- , m_scaley(1.0)
, m_scrAlignment(0)
, m_wrapStyle(0)
, m_fAnimated(false)
- , m_relativeTo(STSStyle::AUTO)
+ , m_bIsAnimated(false)
+ , m_relativeTo(STSStyle::VIDEO)
+ , m_pClipper(nullptr)
, m_topborder(0)
, m_bottomborder(0)
+ , m_clipInverse(false)
+ , m_scalex(1.0)
+ , m_scaley(1.0)
{
ZeroMemory(m_effects, sizeof(Effect*)*EF_NUMBEROFEFFECTS);
- m_bIsAnimated = false;
}
CSubtitle::~CSubtitle()
@@ -1294,22 +1306,30 @@ void CSubtitle::CreateClippers(CSize size)
size.cx >>= 3;
size.cy >>= 3;
- if (m_effects[EF_BANNER] && m_effects[EF_BANNER]->param[2]) {
- int width = m_effects[EF_BANNER]->param[2];
-
- int w = size.cx, h = size.cy;
+ auto createClipper = [this](const CSize & size) {
+ ASSERT(!m_pClipper);
+ CStringW str;
+ str.Format(L"m %d %d l %d %d %d %d %d %d", 0, 0, size.cx, 0, size.cx, size.cy, 0, size.cy);
- if (!m_pClipper) {
- CStringW str;
- str.Format(L"m %d %d l %d %d %d %d %d %d", 0, 0, w, 0, w, h, 0, h);
- try {
- m_pClipper = DEBUG_NEW CClipper(str, size, 1, 1, false, CPoint(0, 0), m_renderingCaches);
- } catch (CMemoryException* e) {
- e->Delete();
- return;
+ try {
+ m_pClipper = DEBUG_NEW CClipper(str, size, 1.0, 1.0, false, CPoint(0, 0), m_renderingCaches);
+ if (!m_pClipper->m_pAlphaMask) {
+ SAFE_DELETE(m_pClipper);
}
+ } catch (CMemoryException* e) {
+ e->Delete();
}
+ return !!m_pClipper;
+ };
+
+ if (m_effects[EF_BANNER] && m_effects[EF_BANNER]->param[2]) {
+ if (!m_pClipper && !createClipper(size)) {
+ return;
+ }
+
+ int width = m_effects[EF_BANNER]->param[2];
+ int w = size.cx, h = size.cy;
int da = (64 << 8) / width;
BYTE* am = m_pClipper->m_pAlphaMask;
@@ -1318,7 +1338,7 @@ void CSubtitle::CreateClippers(CSize size)
int k = std::min(width, w);
for (ptrdiff_t i = 0; i < k; i++, a += da) {
- am[i] = (am[i] * a) >> 14;
+ am[i] = BYTE((am[i] * a) >> 14);
}
a = 0x40 << 8;
@@ -1330,26 +1350,16 @@ void CSubtitle::CreateClippers(CSize size)
}
for (ptrdiff_t i = k; i < w; i++, a -= da) {
- am[i] = (am[i] * a) >> 14;
+ am[i] = BYTE((am[i] * a) >> 14);
}
}
} else if (m_effects[EF_SCROLL] && m_effects[EF_SCROLL]->param[4]) {
- int height = m_effects[EF_SCROLL]->param[4];
-
- int w = size.cx, h = size.cy;
-
- if (!m_pClipper) {
- CStringW str;
- str.Format(L"m %d %d l %d %d %d %d %d %d", 0, 0, w, 0, w, h, 0, h);
- try {
- m_pClipper = DEBUG_NEW CClipper(str, size, 1, 1, false, CPoint(0, 0),
- m_renderingCaches);
- } catch (CMemoryException* e) {
- e->Delete();
- return;
- }
+ if (!m_pClipper && !createClipper(size)) {
+ return;
}
+ int height = m_effects[EF_SCROLL]->param[4];
+ int w = size.cx, h = size.cy;
int da = (64 << 8) / height;
int a = 0;
int k = m_effects[EF_SCROLL]->param[0] >> 3;
@@ -1369,7 +1379,7 @@ void CSubtitle::CreateClippers(CSize size)
for (ptrdiff_t j = k; j < l; j++, a += da) {
for (ptrdiff_t i = 0; i < w; i++, am++) {
- *am = ((*am) * a) >> 14;
+ *am = BYTE(((*am) * a) >> 14);
}
}
}
@@ -1392,7 +1402,7 @@ void CSubtitle::CreateClippers(CSize size)
int j = k;
for (; j < l; j++, a += da) {
for (ptrdiff_t i = 0; i < w; i++, am++) {
- *am = ((*am) * a) >> 14;
+ *am = BYTE(((*am) * a) >> 14);
}
}
@@ -1530,9 +1540,6 @@ CAtlMap<CStringW, SSATagCmd, CStringElementTraits<CStringW>> CRenderedTextSubtit
CRenderedTextSubtitle::CRenderedTextSubtitle(CCritSec* pLock)
: CSubPicProviderImpl(pLock)
- , m_bOverrideStyle(false)
- , m_bOverridePlacement(false)
- , m_overridePlacement(50, 90)
, m_time(0)
, m_delay(0)
, m_animStart(0)
@@ -1543,6 +1550,9 @@ CRenderedTextSubtitle::CRenderedTextSubtitle(CCritSec* pLock)
, m_kend(0)
, m_nPolygon(0)
, m_polygonBaselineOffset(0)
+ , m_bOverrideStyle(false)
+ , m_bOverridePlacement(false)
+ , m_overridePlacement(50, 90)
{
m_size = CSize(0, 0);
@@ -1961,8 +1971,8 @@ bool CRenderedTextSubtitle::ParseSSATag(SSATagsList& tagsList, const CStringW& s
tag.paramsInt.Add(wcstol(tag.params[0], nullptr, 10));
tag.params.RemoveAt(0);
} else if (nParams == 4) {
- for (size_t i = 0; i < nParams; i++) {
- tag.paramsInt.Add(wcstol(tag.params[i], nullptr, 10));
+ for (size_t n = 0; n < nParams; n++) {
+ tag.paramsInt.Add(wcstol(tag.params[n], nullptr, 10));
}
tag.params.RemoveAll();
}
@@ -1971,8 +1981,8 @@ bool CRenderedTextSubtitle::ParseSSATag(SSATagsList& tagsList, const CStringW& s
case SSA_fade: {
size_t nParams = tag.params.GetCount();
if (nParams == 7 || nParams == 2) {
- for (size_t i = 0; i < nParams; i++) {
- tag.paramsInt.Add(wcstol(tag.params[i], nullptr, 10));
+ for (size_t n = 0; n < nParams; n++) {
+ tag.paramsInt.Add(wcstol(tag.params[n], nullptr, 10));
}
tag.params.RemoveAll();
}
@@ -1981,11 +1991,11 @@ bool CRenderedTextSubtitle::ParseSSATag(SSATagsList& tagsList, const CStringW& s
case SSA_move: {
size_t nParams = tag.params.GetCount();
if (nParams == 4 || nParams == 6) {
- for (size_t i = 0; i < 4; i++) {
- tag.paramsReal.Add(wcstod(tag.params[i], nullptr));
+ for (size_t n = 0; n < 4; n++) {
+ tag.paramsReal.Add(wcstod(tag.params[n], nullptr));
}
- for (size_t i = 4; i < nParams; i++) {
- tag.paramsInt.Add(wcstol(tag.params[i], nullptr, 10));
+ for (size_t n = 4; n < nParams; n++) {
+ tag.paramsInt.Add(wcstol(tag.params[n], nullptr, 10));
}
tag.params.RemoveAll();
}
@@ -1995,8 +2005,8 @@ bool CRenderedTextSubtitle::ParseSSATag(SSATagsList& tagsList, const CStringW& s
case SSA_pos: {
size_t nParams = tag.params.GetCount();
if (nParams == 2) {
- for (size_t i = 0; i < nParams; i++) {
- tag.paramsReal.Add(wcstod(tag.params[i], nullptr));
+ for (size_t n = 0; n < nParams; n++) {
+ tag.paramsReal.Add(wcstod(tag.params[n], nullptr));
}
tag.params.RemoveAll();
}
@@ -2062,7 +2072,7 @@ bool CRenderedTextSubtitle::ParseSSATag(SSATagsList& tagsList, const CStringW& s
}
bool CRenderedTextSubtitle::CreateSubFromSSATag(CSubtitle* sub, const SSATagsList& tagsList,
- STSStyle& style, STSStyle& org, bool fAnimate /*= false*/)
+ STSStyle& style, STSStyle& org, bool fAnimate /*= false*/)
{
if (!sub || !tagsList) {
return false;
@@ -2844,18 +2854,20 @@ 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;
}
- return GetNext((POSITION)iSegment);
+ __assume((INT_PTR)iSegment >= INT_MIN && (INT_PTR)iSegment <= INT_MAX);
+ return GetNext((POSITION)(INT_PTR)iSegment);
}
STDMETHODIMP_(POSITION) CRenderedTextSubtitle::GetNext(POSITION pos)
{
- int iSegment = (int)pos;
+ __assume((INT_PTR)pos >= INT_MIN && (INT_PTR)pos <= INT_MAX);
+ int iSegment = (int)(INT_PTR)pos;
const STSSegment* stss = GetSegment(iSegment);
while (stss && stss->subs.IsEmpty()) {
@@ -2863,22 +2875,25 @@ STDMETHODIMP_(POSITION) CRenderedTextSubtitle::GetNext(POSITION pos)
stss = GetSegment(iSegment);
}
- return (stss ? (POSITION)(iSegment + 1) : nullptr);
+ return (stss ? (POSITION)(INT_PTR)(iSegment + 1) : nullptr);
}
STDMETHODIMP_(REFERENCE_TIME) CRenderedTextSubtitle::GetStart(POSITION pos, double fps)
{
- return (10000i64 * TranslateSegmentStart((int)pos - 1, fps));
+ __assume((INT_PTR)pos - 1 >= INT_MIN && (INT_PTR)pos <= INT_MAX);
+ return TranslateSegmentStart((int)(INT_PTR)pos - 1, fps);
}
STDMETHODIMP_(REFERENCE_TIME) CRenderedTextSubtitle::GetStop(POSITION pos, double fps)
{
- return (10000i64 * TranslateSegmentEnd((int)pos - 1, fps));
+ __assume((INT_PTR)pos - 1 >= INT_MIN && (INT_PTR)pos <= INT_MAX);
+ return TranslateSegmentEnd((int)(INT_PTR)pos - 1, fps);
}
STDMETHODIMP_(bool) CRenderedTextSubtitle::IsAnimated(POSITION pos)
{
- int iSegment = (int)pos - 1;
+ __assume((INT_PTR)pos - 1 >= INT_MIN && (INT_PTR)pos <= INT_MAX);
+ int iSegment = (int)(INT_PTR)pos - 1;
const STSSegment* stss = GetSegment(iSegment);
if (stss) {
@@ -2914,10 +2929,8 @@ STDMETHODIMP CRenderedTextSubtitle::Render(SubPicDesc& spd, REFERENCE_TIME rt, d
Init(CSize(spd.w, spd.h), spd.vidrect);
}
- int t = (int)(rt / 10000);
-
int segment;
- const STSSegment* stss = SearchSubs(t, fps, &segment);
+ const STSSegment* stss = SearchSubs(rt, fps, &segment);
if (!stss) {
return S_FALSE;
}
@@ -2931,7 +2944,7 @@ STDMETHODIMP CRenderedTextSubtitle::Render(SubPicDesc& spd, REFERENCE_TIME rt, d
m_subtitleCache.GetNextAssoc(pos, entry, pSub);
STSEntry& stse = GetAt(entry);
- if (stse.end < t) {
+ if (stse.end < rt) {
delete pSub;
m_subtitleCache.RemoveKey(entry);
}
@@ -2958,9 +2971,9 @@ STDMETHODIMP CRenderedTextSubtitle::Render(SubPicDesc& spd, REFERENCE_TIME rt, d
STSEntry stse = GetAt(entry);
{
- int start = TranslateStart(entry, fps);
- m_time = t - 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);
@@ -2996,9 +3009,7 @@ STDMETHODIMP CRenderedTextSubtitle::Render(SubPicDesc& spd, REFERENCE_TIME rt, d
int t2 = s->m_effects[k]->t[1];
if (t2 < t1) {
- int t = t1;
- t1 = t2;
- t2 = t;
+ std::swap(t1, t2);
}
if (t1 <= 0 && t2 <= 0) {
@@ -3207,26 +3218,35 @@ STDMETHODIMP_(int) CRenderedTextSubtitle::GetStreamCount()
STDMETHODIMP CRenderedTextSubtitle::GetStreamInfo(int iStream, WCHAR** ppName, LCID* pLCID)
{
+ CheckPointer(ppName, E_POINTER);
if (iStream != 0) {
return E_INVALIDARG;
}
- if (ppName) {
- *ppName = (WCHAR*)CoTaskMemAlloc((m_name.GetLength() + 1) * sizeof(WCHAR));
- if (!(*ppName)) {
- return E_OUTOFMEMORY;
- }
+ if (pLCID) {
+ *pLCID = m_lcid;
+ }
- wcscpy_s(*ppName, m_name.GetLength() + 1, CStringW(m_name));
+ CString strLanguage;
+ if (m_lcid && m_lcid != LCID(-1)) {
+ int len = GetLocaleInfo(m_lcid, LOCALE_SENGLANGUAGE, strLanguage.GetBuffer(64), 64);
+ strLanguage.ReleaseBufferSetLength(std::max(len - 1, 0));
+ }
- if (pLCID) {
- *pLCID = ISO6391ToLcid(CW2A(*ppName));
- if (*pLCID == 0) {
- *pLCID = ISO6392ToLcid(CW2A(*ppName));
- }
- }
+ if (!strLanguage.IsEmpty() && m_eHearingImpaired == Subtitle::HI_YES) {
+ strLanguage = '[' + strLanguage + ']';
+ }
+ CStringW strName;
+ if (!m_provider.IsEmpty()) {
+ strName.Format(L"[%s] %s\t%s", m_provider, m_name, strLanguage);
+ } else {
+ strName.Format(L"%s\t%s", m_name, strLanguage);
}
+ *ppName = (WCHAR*)CoTaskMemAlloc((strName.GetLength() + 1) * sizeof(WCHAR));
+ CheckPointer(*ppName, E_OUTOFMEMORY);
+ wcscpy_s(*ppName, strName.GetLength() + 1, strName);
+
return S_OK;
}
@@ -3242,8 +3262,47 @@ STDMETHODIMP CRenderedTextSubtitle::SetStream(int iStream)
STDMETHODIMP CRenderedTextSubtitle::Reload()
{
- if (!FileExists(m_path)) {
+ if (!PathUtils::Exists(m_path)) {
return E_FAIL;
}
return !m_path.IsEmpty() && Open(m_path, DEFAULT_CHARSET, m_name) ? S_OK : E_FAIL;
}
+
+STDMETHODIMP CRenderedTextSubtitle::SetSourceTargetInfo(CString yuvVideoMatrix, int targetBlackLevel, int targetWhiteLevel)
+{
+ bool bIsVSFilter = !!yuvVideoMatrix.Replace(_T(".VSFilter"), _T(""));
+ ColorConvTable::YuvMatrixType yuvMatrix = ColorConvTable::BT601;
+ ColorConvTable::YuvRangeType yuvRange = ColorConvTable::RANGE_TV;
+
+ auto parseMatrixString = [&](const CString & sYuvMatrix) {
+ int nPos = 0;
+ CString range = sYuvMatrix.Tokenize(_T("."), nPos);
+ CString matrix = sYuvMatrix.Mid(nPos);
+
+ yuvRange = ColorConvTable::RANGE_TV;
+ if (range == _T("PC")) {
+ yuvRange = ColorConvTable::RANGE_PC;
+ }
+
+ if (matrix == _T("709")) {
+ yuvMatrix = ColorConvTable::BT709;
+ } else if (matrix == _T("240M")) {
+ yuvMatrix = ColorConvTable::BT709;
+ } else if (matrix == _T("601")) {
+ yuvMatrix = ColorConvTable::BT601;
+ } else {
+ yuvMatrix = ColorConvTable::NONE;
+ }
+ };
+
+ if (!m_sYCbCrMatrix.IsEmpty()) {
+ parseMatrixString(m_sYCbCrMatrix);
+ } else {
+ parseMatrixString(yuvVideoMatrix);
+ }
+
+ bool bTransformColors = !bIsVSFilter && !m_sYCbCrMatrix.IsEmpty();
+ ColorConvTable::SetDefaultConvType(yuvMatrix, yuvRange, (targetWhiteLevel < 245), bTransformColors);
+
+ return S_OK;
+}