2 * Copyright (C) 2013-2019 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
11 * \file media\hwdecoder\DecoderFilterManager.cpp
12 * \brief Implements CDecoderFilterManager class.
16 #include "DecoderFilterManager.h"
19 #include "cores/VideoPlayer/DVDStreamInfo.h"
20 #include "filesystem/File.h"
21 #include "utils/XBMCTinyXML2.h"
22 #include "utils/XMLUtils.h"
23 #include "utils/log.h"
27 static const char* TAG_ROOT
= "decoderfilter";
28 static const char* TAG_FILTER
= "filter";
29 static const char* TAG_NAME
= "name";
30 static const char* TAG_GENERAL
= "allowed";
31 static const char* TAG_STILLS
= "stills-allowed";
32 static const char* TAG_DVD
= "dvd-allowed";
33 static const char* TAG_MINHEIGHT
= "min-height";
34 static const char* HWDFFileName
= "special://masterprofile/decoderfilter.xml";
36 CDecoderFilter::CDecoderFilter(const std::string
& name
, uint32_t flags
, int minHeight
)
39 , m_minHeight(minHeight
)
43 bool CDecoderFilter::isValid(const CDVDStreamInfo
& streamInfo
) const
45 uint32_t flags
= FLAG_GENERAL_ALLOWED
;
47 if (streamInfo
.stills
)
48 flags
|= FLAG_STILLS_ALLOWED
;
51 flags
|= FLAG_DVD_ALLOWED
;
53 if ((flags
& m_flags
) != flags
)
56 // remove codec pitch for comparison
57 if (m_minHeight
&& (streamInfo
.height
& ~31) < m_minHeight
)
63 bool CDecoderFilter::Load(const tinyxml2::XMLNode
* node
)
65 bool flagBool
= false;
67 XMLUtils::GetString(node
, TAG_NAME
, m_name
);
68 XMLUtils::GetBoolean(node
, TAG_GENERAL
, flagBool
);
70 m_flags
|= FLAG_GENERAL_ALLOWED
;
73 XMLUtils::GetBoolean(node
, TAG_STILLS
, flagBool
);
75 m_flags
|= FLAG_STILLS_ALLOWED
;
78 XMLUtils::GetBoolean(node
, TAG_DVD
, flagBool
);
80 m_flags
|= FLAG_DVD_ALLOWED
;
82 XMLUtils::GetInt(node
, TAG_MINHEIGHT
, m_minHeight
);
87 bool CDecoderFilter::Save(tinyxml2::XMLNode
* node
) const
89 // Now write each of the pieces of information we need...
90 XMLUtils::SetString(node
, TAG_NAME
, m_name
);
91 XMLUtils::SetBoolean(node
, TAG_GENERAL
, (m_flags
& FLAG_GENERAL_ALLOWED
) != 0);
92 XMLUtils::SetBoolean(node
, TAG_STILLS
, (m_flags
& FLAG_STILLS_ALLOWED
) != 0);
93 XMLUtils::SetBoolean(node
, TAG_DVD
, (m_flags
& FLAG_DVD_ALLOWED
) != 0);
94 XMLUtils::SetInt(node
, TAG_MINHEIGHT
, m_minHeight
);
99 /****************************************/
101 bool CDecoderFilterManager::isValid(const std::string
& name
, const CDVDStreamInfo
& streamInfo
)
103 std::unique_lock
<CCriticalSection
> lock(m_critical
);
104 std::set
<CDecoderFilter
>::const_iterator
filter(m_filters
.find(name
));
105 return filter
!= m_filters
.end() ? filter
->isValid(streamInfo
) : m_filters
.empty();
108 void CDecoderFilterManager::add(const CDecoderFilter
& filter
)
110 std::unique_lock
<CCriticalSection
> lock(m_critical
);
111 std::pair
<std::set
<CDecoderFilter
>::iterator
, bool> res
= m_filters
.insert(filter
);
112 m_dirty
= m_dirty
|| res
.second
;
115 bool CDecoderFilterManager::Load()
117 std::unique_lock
<CCriticalSection
> lock(m_critical
);
121 std::string fileName
= CUtil::TranslateSpecialSource(HWDFFileName
);
122 if (!XFILE::CFile::Exists(fileName
))
125 CLog::LogF(LOGINFO
, "loading filters from {}", fileName
);
127 CXBMCTinyXML2 xmlDoc
;
128 if (!xmlDoc
.LoadFile(fileName
))
130 CLog::LogF(LOGERROR
, "error loading: line {}, {}", xmlDoc
.ErrorLineNum(), xmlDoc
.ErrorStr());
134 const auto* rootElement
= xmlDoc
.RootElement();
135 if (rootElement
== nullptr || !StringUtils::EqualsNoCase(rootElement
->Value(), TAG_ROOT
))
137 CLog::LogF(LOGERROR
, "invalid root element ({})", rootElement
? rootElement
->Value() : "");
141 const auto* tagFilter
= rootElement
->FirstChildElement(TAG_FILTER
);
142 while (tagFilter
!= nullptr)
144 CDecoderFilter
filter("");
145 if (filter
.Load(tagFilter
))
146 m_filters
.insert(filter
);
147 tagFilter
= tagFilter
->NextSiblingElement(TAG_FILTER
);
152 bool CDecoderFilterManager::Save() const
154 std::unique_lock
<CCriticalSection
> lock(m_critical
);
155 if (!m_dirty
|| m_filters
.empty())
159 auto* xmlRootElement
= doc
.NewElement(TAG_ROOT
);
160 if (xmlRootElement
== nullptr)
163 auto* root
= doc
.InsertEndChild(xmlRootElement
);
167 for (const CDecoderFilter
& filter
: m_filters
)
169 // Write the resolution tag
170 auto* filterElem
= doc
.NewElement(TAG_FILTER
);
171 if (filterElem
== nullptr)
174 auto* node
= root
->InsertEndChild(filterElem
);
180 std::string fileName
= CUtil::TranslateSpecialSource(HWDFFileName
);
181 return doc
.SaveFile(fileName
);