diff options
Diffstat (limited to 'src/Subtitles/RTS.cpp')
-rw-r--r-- | src/Subtitles/RTS.cpp | 243 |
1 files changed, 136 insertions, 107 deletions
diff --git a/src/Subtitles/RTS.cpp b/src/Subtitles/RTS.cpp index d52d80ea6..c61f4ad58 100644 --- a/src/Subtitles/RTS.cpp +++ b/src/Subtitles/RTS.cpp @@ -1,6 +1,6 @@ /*
* (C) 2003-2006 Gabest
- * (C) 2006-2016 see Authors.txt
+ * (C) 2006-2017 see Authors.txt
*
* This file is part of MPC-HC.
*
@@ -38,6 +38,15 @@ static long revcolor(long c) //////////////////////////////////////////////////////////////////////////////////////////////
+void alpha_mask_deleter::operator()(CAlphaMask* ptr) const noexcept
+{
+ m_alphaMaskPool.emplace_front(std::move(*ptr));
+ std::default_delete<CAlphaMask>()(ptr);
+ if (m_alphaMaskPool.size() > 10) {
+ m_alphaMaskPool.pop_back();
+ }
+}
+
// CMyFont
CMyFont::CMyFont(const STSStyle& style)
@@ -786,25 +795,30 @@ CClipper::CClipper(CStringW str, const CSize& size, double scalex, double scaley , m_inverse(inverse)
, m_cpOffset(cpOffset)
, m_pAlphaMask(nullptr)
+ , m_effectType(-1)
{
- if (m_size.cx <= 0 || m_size.cy <= 0) {
- return;
+}
+
+CAlphaMaskSharedPtr CClipper::GetAlphaMask(const std::shared_ptr<CClipper>& clipper)
+{
+ if (m_pAlphaMask) {
+ return m_pAlphaMask;
}
- const size_t alphaMaskSize = size_t(m_size.cx) * m_size.cy;
+ ASSERT(this == clipper.get());
+ if (m_size.cx <= 0 || m_size.cy <= 0) {
+ return nullptr;
+ }
- try {
- m_pAlphaMask = DEBUG_NEW BYTE[alphaMaskSize];
- } catch (CMemoryException* e) {
- e->Delete();
- return;
+ CClipperKey key(clipper);
+ if (m_renderingCaches.alphaMaskCache.Lookup(key, m_pAlphaMask)) {
+ return m_pAlphaMask;
}
- memset(m_pAlphaMask, (m_inverse ? 0x40 : 0), alphaMaskSize);
Paint(CPoint(0, 0), CPoint(0, 0));
if (!m_pOverlayData) {
- return;
+ return nullptr;
}
int w = m_pOverlayData->mOverlayWidth, h = m_pOverlayData->mOverlayHeight;
@@ -830,17 +844,31 @@ CClipper::CClipper(CStringW str, const CSize& size, double scalex, double scaley }
if (w <= 0 || h <= 0) {
- return;
+ return nullptr;
+ }
+
+ const size_t alphaMaskSize = size_t(m_size.cx) * m_size.cy;
+
+ try {
+ m_pAlphaMask = CAlphaMask::Alloc(m_renderingCaches.alphaMaskPool, alphaMaskSize);
+ } catch (CMemoryException* e) {
+ e->Delete();
+ m_pAlphaMask = nullptr;
+ return nullptr;
}
+ BYTE* pAlphaMask = m_pAlphaMask->get();
+
const BYTE* src = m_pOverlayData->mpOverlayBufferBody + m_pOverlayData->mOverlayPitch * yo + xo;
- BYTE* dst = m_pAlphaMask + m_size.cx * y + x;
+ BYTE* dst = pAlphaMask + m_size.cx * y + x;
+ memset(pAlphaMask, (m_inverse ? 0x40 : 0), m_size.cx * y + x);
if (m_inverse) {
for (ptrdiff_t i = 0; i < h; ++i) {
for (ptrdiff_t wt = 0; wt < w; ++wt) {
dst[wt] = 0x40 - src[wt];
}
+ memset(dst + w, 0x40, m_size.cx - w);
src += m_pOverlayData->mOverlayPitch;
dst += m_size.cx;
@@ -848,15 +876,94 @@ CClipper::CClipper(CStringW str, const CSize& size, double scalex, double scaley } else {
for (ptrdiff_t i = 0; i < h; ++i) {
memcpy(dst, src, w * sizeof(BYTE));
+ memset(dst + w, 0, m_size.cx - w);
src += m_pOverlayData->mOverlayPitch;
dst += m_size.cx;
}
}
-}
+ memset(dst, (m_inverse ? 0x40 : 0), alphaMaskSize - (dst - pAlphaMask));
-CClipper::~CClipper()
-{
- SAFE_DELETE_ARRAY(m_pAlphaMask);
+ if (m_effectType == EF_SCROLL) {
+ int height = m_effect.param[4];
+ int spd_w = m_size.cx, spd_h = m_size.cy;
+ int da = (64 << 8) / height;
+ int a = 0;
+ int k = m_effect.param[0] >> 3;
+ int l = k + height;
+ if (k < 0) {
+ a += -k * da;
+ k = 0;
+ }
+ if (l > spd_h) {
+ l = spd_h;
+ }
+
+ if (k < spd_h) {
+ BYTE* am = &pAlphaMask[k * spd_w];
+
+ ZeroMemory(pAlphaMask, am - pAlphaMask);
+
+ for (ptrdiff_t j = k; j < l; j++, a += da) {
+ for (ptrdiff_t i = 0; i < spd_w; i++, am++) {
+ *am = BYTE(((*am) * a) >> 14);
+ }
+ }
+ }
+
+ da = -(64 << 8) / height;
+ a = 0x40 << 8;
+ l = m_effect.param[1] >> 3;
+ k = l - height;
+ if (k < 0) {
+ a += -k * da;
+ k = 0;
+ }
+ if (l > spd_h) {
+ l = spd_h;
+ }
+
+ if (k < spd_h) {
+ BYTE* am = &pAlphaMask[k * spd_w];
+
+ int j = k;
+ for (; j < l; j++, a += da) {
+ for (ptrdiff_t i = 0; i < spd_w; i++, am++) {
+ *am = BYTE(((*am) * a) >> 14);
+ }
+ }
+
+ ZeroMemory(am, (spd_h - j)*spd_w);
+ }
+ } else if (m_effectType == EF_BANNER) {
+ int width = m_effect.param[2];
+ int spd_w = m_size.cx, spd_h = m_size.cy;
+ int da = (64 << 8) / width;
+ BYTE* am = pAlphaMask;
+
+ for (ptrdiff_t j = 0; j < spd_h; j++, am += spd_w) {
+ int a = 0;
+ int k = std::min(width, spd_w);
+
+ for (ptrdiff_t i = 0; i < k; i++, a += da) {
+ am[i] = BYTE((am[i] * a) >> 14);
+ }
+
+ a = 0x40 << 8;
+ k = spd_w - width;
+
+ if (k < 0) {
+ a -= -k * da;
+ k = 0;
+ }
+
+ for (ptrdiff_t i = k; i < spd_w; i++, a -= da) {
+ am[i] = BYTE((am[i] * a) >> 14);
+ }
+ }
+
+ }
+ m_renderingCaches.alphaMaskCache.SetAt(key, m_pAlphaMask);
+ return m_pAlphaMask;
}
CWord* CClipper::Copy()
@@ -1142,7 +1249,7 @@ void CSubtitle::Empty() EmptyEffects();
- SAFE_DELETE(m_pClipper);
+ m_pClipper.reset();
}
void CSubtitle::EmptyEffects()
@@ -1312,10 +1419,7 @@ void CSubtitle::CreateClippers(CSize size) 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);
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);
- }
+ m_pClipper = std::make_shared<CClipper>(str, size, 1.0, 1.0, false, CPoint(0, 0), m_renderingCaches);
} catch (CMemoryException* e) {
e->Delete();
}
@@ -1327,87 +1431,12 @@ void CSubtitle::CreateClippers(CSize size) 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;
-
- for (ptrdiff_t j = 0; j < h; j++, am += w) {
- int a = 0;
- int k = std::min(width, w);
-
- for (ptrdiff_t i = 0; i < k; i++, a += da) {
- am[i] = BYTE((am[i] * a) >> 14);
- }
-
- a = 0x40 << 8;
- k = w - width;
-
- if (k < 0) {
- a -= -k * da;
- k = 0;
- }
-
- for (ptrdiff_t i = k; i < w; i++, a -= da) {
- am[i] = BYTE((am[i] * a) >> 14);
- }
- }
+ m_pClipper->SetEffect(*m_effects[EF_BANNER], EF_BANNER);
} else if (m_effects[EF_SCROLL] && m_effects[EF_SCROLL]->param[4]) {
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;
- int l = k + height;
- if (k < 0) {
- a += -k * da;
- k = 0;
- }
- if (l > h) {
- l = h;
- }
-
- if (k < h) {
- BYTE* am = &m_pClipper->m_pAlphaMask[k * w];
-
- ZeroMemory(m_pClipper->m_pAlphaMask, am - m_pClipper->m_pAlphaMask);
-
- for (ptrdiff_t j = k; j < l; j++, a += da) {
- for (ptrdiff_t i = 0; i < w; i++, am++) {
- *am = BYTE(((*am) * a) >> 14);
- }
- }
- }
-
- da = -(64 << 8) / height;
- a = 0x40 << 8;
- l = m_effects[EF_SCROLL]->param[1] >> 3;
- k = l - height;
- if (k < 0) {
- a += -k * da;
- k = 0;
- }
- if (l > h) {
- l = h;
- }
-
- if (k < h) {
- BYTE* am = &m_pClipper->m_pAlphaMask[k * w];
-
- int j = k;
- for (; j < l; j++, a += da) {
- for (ptrdiff_t i = 0; i < w; i++, am++) {
- *am = BYTE(((*am) * a) >> 14);
- }
- }
-
- ZeroMemory(am, (h - j)*w);
- }
+ m_pClipper->SetEffect(*m_effects[EF_SCROLL], EF_SCROLL);
}
}
@@ -2169,18 +2198,18 @@ bool CRenderedTextSubtitle::CreateSubFromSSATag(CSubtitle* sub, const SSATagsLis size_t nParamsInt = tag.paramsInt.GetCount();
if (nParams == 1 && nParamsInt == 0 && !sub->m_pClipper) {
- sub->m_pClipper = DEBUG_NEW CClipper(tag.params[0], CSize(m_size.cx >> 3, m_size.cy >> 3), sub->m_scalex, sub->m_scaley,
- invert, (sub->m_relativeTo == STSStyle::VIDEO) ? CPoint(m_vidrect.left, m_vidrect.top) : CPoint(0, 0),
- m_renderingCaches);
+ sub->m_pClipper = std::make_shared<CClipper>(tag.params[0], CSize(m_size.cx >> 3, m_size.cy >> 3), sub->m_scalex, sub->m_scaley,
+ invert, (sub->m_relativeTo == STSStyle::VIDEO) ? CPoint(m_vidrect.left, m_vidrect.top) : CPoint(0, 0),
+ m_renderingCaches);
} else if (nParams == 1 && nParamsInt == 1 && !sub->m_pClipper) {
long scale = tag.paramsInt[0];
if (scale < 1) {
scale = 1;
}
- sub->m_pClipper = DEBUG_NEW CClipper(tag.params[0], CSize(m_size.cx >> 3, m_size.cy >> 3),
- sub->m_scalex / (1 << (scale - 1)), sub->m_scaley / (1 << (scale - 1)), invert,
- (sub->m_relativeTo == STSStyle::VIDEO) ? CPoint(m_vidrect.left, m_vidrect.top) : CPoint(0, 0),
- m_renderingCaches);
+ sub->m_pClipper = std::make_shared<CClipper>(tag.params[0], CSize(m_size.cx >> 3, m_size.cy >> 3),
+ sub->m_scalex / (1 << (scale - 1)), sub->m_scaley / (1 << (scale - 1)), invert,
+ (sub->m_relativeTo == STSStyle::VIDEO) ? CPoint(m_vidrect.left, m_vidrect.top) : CPoint(0, 0),
+ m_renderingCaches);
} else if (nParamsInt == 4) {
sub->m_clipInverse = invert;
@@ -2993,7 +3022,7 @@ STDMETHODIMP CRenderedTextSubtitle::Render(SubPicDesc& spd, REFERENCE_TIME rt, d CPoint org2;
- BYTE* pAlphaMask = s->m_pClipper ? s->m_pClipper->m_pAlphaMask : nullptr;
+ BYTE* pAlphaMask = s->m_pClipper ? s->m_pClipper->GetAlphaMask(s->m_pClipper)->get() : nullptr;
for (int k = 0; k < EF_NUMBEROFEFFECTS; k++) {
if (!s->m_effects[k]) {
|