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:
authorKacper Michajłow <kasper93@gmail.com>2017-08-13 04:02:21 +0300
committerKacper Michajłow <kasper93@gmail.com>2017-08-13 23:24:42 +0300
commit701ceec81e37de1d9f89ce82ced9bab7735a2eae (patch)
tree377ecbd3230ac5711e3c7d2f8bcfe14d62ae80a0
parentf1bfa3c353f0f0929237f14c01f538a91589d9e0 (diff)
Subtitles: Add cache for alpha mask.
-rw-r--r--docs/Changelog.txt1
-rw-r--r--src/Subtitles/RTS.cpp243
-rw-r--r--src/Subtitles/RTS.h125
-rw-r--r--src/Subtitles/RenderingCache.cpp28
-rw-r--r--src/Subtitles/RenderingCache.h19
5 files changed, 292 insertions, 124 deletions
diff --git a/docs/Changelog.txt b/docs/Changelog.txt
index c63ad5815..1beb78b1a 100644
--- a/docs/Changelog.txt
+++ b/docs/Changelog.txt
@@ -20,6 +20,7 @@ next version - not released yet
* Updated Unrar to v5.5.7
* Split internal MPEG source filter option into a PS and TS variant
* End of support for Windows XP
+* SSA/ASS subtitles: Add cache for alpha mask
! Fixed text subtitle rendering in Avisynth
! Fixed DPI scaling of non-client areas in main window
! Prevent crash for ASS subtitles with invalid (too high) blur values
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]) {
diff --git a/src/Subtitles/RTS.h b/src/Subtitles/RTS.h
index 0e29b97d2..ad275c60d 100644
--- a/src/Subtitles/RTS.h
+++ b/src/Subtitles/RTS.h
@@ -1,6 +1,6 @@
/*
* (C) 2003-2006 Gabest
- * (C) 2006-2015 see Authors.txt
+ * (C) 2006-2015, 2017 see Authors.txt
*
* This file is part of MPC-HC.
*
@@ -21,21 +21,63 @@
#pragma once
+#include <list>
#include <memory>
#include "STS.h"
#include "Rasterizer.h"
#include "../SubPic/SubPicProviderImpl.h"
#include "RenderingCache.h"
+class Effect;
struct CTextDims;
struct CPolygonPath {
CAtlArray<BYTE> typesOrg;
CAtlArray<CPoint> pointsOrg;
CSize size;
};
+
+struct CAlphaMask;
+
+struct alpha_mask_deleter {
+ explicit alpha_mask_deleter(std::list<CAlphaMask>& alphaMaskPool)
+ : m_alphaMaskPool(alphaMaskPool) {
+ }
+
+ void operator()(CAlphaMask* ptr) const noexcept;
+
+ std::list<CAlphaMask>& m_alphaMaskPool;
+};
+
+struct CAlphaMask final : std::unique_ptr<BYTE[]> {
+ CAlphaMask() = delete;
+ CAlphaMask(CAlphaMask&&) = default;
+ CAlphaMask(const CAlphaMask&) = delete;
+ CAlphaMask& operator=(const CAlphaMask&) = delete;
+
+ size_t m_size;
+
+ explicit CAlphaMask(size_t size)
+ : std::unique_ptr<BYTE[]>(std::make_unique<BYTE[]>(size))
+ , m_size(size) {
+ }
+
+ static std::shared_ptr<CAlphaMask> Alloc(std::list<CAlphaMask>& alphaMaskPool, size_t size) {
+ for (auto it = alphaMaskPool.begin(); it != alphaMaskPool.end(); ++it) {
+ auto& am = *it;
+ if (am.m_size >= size) {
+ auto ret = std::shared_ptr<CAlphaMask>(DEBUG_NEW CAlphaMask(std::move(am)), alpha_mask_deleter(alphaMaskPool));
+ alphaMaskPool.erase(it);
+ return std::move(ret);
+ }
+ }
+ return std::shared_ptr<CAlphaMask>(DEBUG_NEW CAlphaMask(size), alpha_mask_deleter(alphaMaskPool));
+ }
+};
+
typedef std::shared_ptr<CPolygonPath> CPolygonPathSharedPtr;
struct SSATag;
typedef std::shared_ptr<CAtlList<SSATag>> SSATagsList;
+typedef std::shared_ptr<CAlphaMask> CAlphaMaskSharedPtr;
typedef CRenderingCache<CTextDimsKey, CTextDims, CKeyTraits<CTextDimsKey>> CTextDimsCache;
typedef CRenderingCache<CPolygonPathKey, CPolygonPathSharedPtr, CKeyTraits<CPolygonPathKey>> CPolygonCache;
@@ -43,6 +85,7 @@ typedef CRenderingCache<CStringW, SSATagsList, CStringElementTraits<CStringW>> C
typedef CRenderingCache<CEllipseKey, CEllipseSharedPtr, CKeyTraits<CEllipseKey>> CEllipseCache;
typedef CRenderingCache<COutlineKey, COutlineDataSharedPtr, CKeyTraits<COutlineKey>> COutlineCache;
typedef CRenderingCache<COverlayKey, COverlayDataSharedPtr, CKeyTraits<COverlayKey>> COverlayCache;
+typedef CRenderingCache<CClipperKey, CAlphaMaskSharedPtr, CKeyTraits<CClipperKey>> CAlphaMaskCache;
struct RenderingCaches {
CTextDimsCache textDimsCache;
@@ -51,6 +94,9 @@ struct RenderingCaches {
CEllipseCache ellipseCache;
COutlineCache outlineCache;
COverlayCache overlayCache;
+ // Be careful about the order alphaMaskCache need to be destroyed before alphaMaskPool.
+ std::list<CAlphaMask> alphaMaskPool;
+ CAlphaMaskCache alphaMaskCache;
RenderingCaches()
: textDimsCache(2048)
@@ -58,7 +104,8 @@ struct RenderingCaches {
, SSATagsCache(2048)
, ellipseCache(64)
, outlineCache(128)
- , overlayCache(128) {}
+ , overlayCache(128)
+ , alphaMaskCache(128) {}
};
class CMyFont : public CFont
@@ -154,6 +201,20 @@ public:
virtual bool Append(CWord* w);
};
+class Effect
+{
+public:
+ enum eftype type;
+ int param[9];
+ int t[4];
+
+ bool operator==(const Effect& rhs) const {
+ return type == rhs.type
+ && !memcmp(param, rhs.param, sizeof(param))
+ && !memcmp(t, rhs.t, sizeof(t));
+ }
+};
+
class CClipper : public CPolygon
{
private:
@@ -163,14 +224,60 @@ private:
public:
CClipper(CStringW str, const CSize& size, double scalex, double scaley, bool inverse, const CPoint& cpOffset,
RenderingCaches& renderingCaches);
- virtual ~CClipper();
+ void CClipper::SetEffect(const Effect& effect, int effectType) {
+ m_effectType = effectType;
+ m_effect = effect;
+ }
+
+ CAlphaMaskSharedPtr GetAlphaMask(const std::shared_ptr<CClipper>& clipper);
+
+ ULONG Hash() const {
+ ULONG hash = CStringElementTraits<CString>::Hash(m_str);
+ hash += hash << 5;
+ hash += m_inverse;
+ hash += hash << 5;
+ hash += m_effectType;
+ hash += hash << 5;
+ hash += m_size.cx;
+ hash += hash << 5;
+ hash += m_size.cy;
+ hash += hash << 5;
+ hash += int(m_scalex * 1e6);
+ hash += hash << 5;
+ hash += int(m_scaley * 1e6);
+ for (const auto& param : m_effect.t) {
+ hash += hash << 5;
+ hash += param;
+ }
+ for (const auto& type : m_effect.t) {
+ hash += hash << 5;
+ hash += type;
+ }
+ return hash;
+ }
+
+ bool operator==(const CClipper& rhs) const {
+ return m_str == rhs.m_str
+ && std::abs(m_scalex - rhs.m_scalex) < 1e-6
+ && std::abs(m_scaley - rhs.m_scaley) < 1e-6
+ && m_size == rhs.m_size
+ && m_inverse == rhs.m_inverse
+ && m_effectType == rhs.m_effectType
+ && m_effect == rhs.m_effect;
+ }
+
+private:
const CSize m_size;
const bool m_inverse;
const CPoint m_cpOffset;
- BYTE* m_pAlphaMask;
+ CAlphaMaskSharedPtr m_pAlphaMask;
+ Effect m_effect;
+ int m_effectType;
};
+using CClipperSharedPtr = std::shared_ptr<CClipper>;
+
class CLine : public CAtlList<CWord*>
{
public:
@@ -278,14 +385,6 @@ enum eftype {
#define EF_NUMBEROFEFFECTS 5
-class Effect
-{
-public:
- enum eftype type;
- int param[9];
- int t[4];
-};
-
class CSubtitle : public CAtlList<CLine*>
{
RenderingCaches& m_renderingCaches;
@@ -306,7 +405,7 @@ public:
CAtlList<CWord*> m_words;
- CClipper* m_pClipper;
+ CClipperSharedPtr m_pClipper;
CRect m_rect, m_clip;
int m_topborder, m_bottomborder;
diff --git a/src/Subtitles/RenderingCache.cpp b/src/Subtitles/RenderingCache.cpp
index 53b27e3bc..7a8bdd585 100644
--- a/src/Subtitles/RenderingCache.cpp
+++ b/src/Subtitles/RenderingCache.cpp
@@ -1,5 +1,5 @@
/*
- * (C) 2013-2014, 2016 see Authors.txt
+ * (C) 2013-2014, 2016-2017 see Authors.txt
*
* This file is part of MPC-HC.
*
@@ -125,9 +125,9 @@ void COutlineKey::UpdateHash()
// CreatePath
m_hash = __super::GetHash();
m_hash += m_hash << 5;
- m_hash += int(m_scalex);
+ m_hash += int(m_scalex * 1e6);
m_hash += m_hash << 5;
- m_hash += int(m_scaley);
+ m_hash += int(m_scaley * 1e6);
m_hash += m_hash << 5;
// Transform
m_hash += int(m_style->fontScaleX);
@@ -206,3 +206,25 @@ bool COverlayKey::operator==(const COverlayKey& overlayKey) const
&& m_style->fBlur == overlayKey.m_style->fBlur
&& IsNearlyEqual(m_style->fGaussianBlur, overlayKey.m_style->fGaussianBlur, 1e-6);
}
+
+CClipperKey::CClipperKey(const std::shared_ptr<CClipper>& clipper)
+ : m_clipper(clipper)
+{
+ UpdateHash();
+}
+
+void CClipperKey::UpdateHash()
+{
+ m_hash = m_clipper->Hash();
+}
+
+bool CClipperKey::operator==(const CClipperKey& clipperKey) const
+{
+ if (m_clipper == clipperKey.m_clipper) {
+ return true;
+ }
+ if (m_clipper && clipperKey.m_clipper) {
+ return *m_clipper == *clipperKey.m_clipper;
+ }
+ return false;
+}
diff --git a/src/Subtitles/RenderingCache.h b/src/Subtitles/RenderingCache.h
index 218da59da..5981708f4 100644
--- a/src/Subtitles/RenderingCache.h
+++ b/src/Subtitles/RenderingCache.h
@@ -1,5 +1,5 @@
/*
- * (C) 2013-2014 see Authors.txt
+ * (C) 2013-2014, 2017 see Authors.txt
*
* This file is part of MPC-HC.
*
@@ -191,3 +191,20 @@ public:
bool operator==(const COverlayKey& overlayKey) const;
};
+
+class CClipper;
+
+class CClipperKey
+{
+ ULONG m_hash;
+ std::shared_ptr<CClipper> m_clipper;
+
+public:
+ CClipperKey(const std::shared_ptr<CClipper>& clipper);
+
+ ULONG GetHash() const { return m_hash; };
+
+ void UpdateHash();
+
+ bool operator==(const CClipperKey& clipperKey) const;
+};