Skip to content

Commit 2ddae7b

Browse files
committed
settings.xml: add whole-number repeat mode
New TVs most support 120Hz, so add a new whole-number repeat option for 24/30Hz to 120Hz. This allow judder free playback for 24/30Hz on 120Hz.
1 parent 17c37e7 commit 2ddae7b

3 files changed

Lines changed: 125 additions & 40 deletions

File tree

addons/resource.language.en_gb/resources/strings.po

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8592,6 +8592,11 @@ msgstr ""
85928592

85938593
#: system/settings/settings.xml
85948594
msgctxt "#14128"
8595+
msgid "Allow whole-number frame repeat"
8596+
msgstr ""
8597+
8598+
#: system/settings/settings.xml
8599+
msgctxt "#14129"
85958600
msgid "Allow double refresh rates"
85968601
msgstr ""
85978602

@@ -21948,6 +21953,12 @@ msgstr ""
2194821953
#. Description of setting with label #14128 "Whitelist"
2194921954
#: system/settings/settings.xml
2195021955
msgctxt "#36445"
21956+
msgid "Select this option to allow using whole-number repeat rate (playing 24 FPS video on a 120 Hz monitor or playing 30 FPS video on a 120 Hz monitor)."
21957+
msgstr ""
21958+
21959+
#. Description of setting with label #14129 "Whitelist"
21960+
#: system/settings/settings.xml
21961+
msgctxt "#36446"
2195121962
msgid "Select this option to allow using double refresh rates (playing 29.97 FPS video on a 59.94 Hz monitor or playing 30 FPS video on a 60 Hz monitor). You may want to use this option if your monitor doesn't have a 29.97 Hz or 30 Hz mode."
2195221963
msgstr ""
2195321964

system/settings/settings.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3257,7 +3257,12 @@
32573257
<default>true</default>
32583258
<control type="toggle" />
32593259
</setting>
3260-
<setting id="videoscreen.whitelistdoublerefreshrate" type="boolean" label="14128" help="36445">
3260+
<setting id="videoscreen.whitelistwholenumber" type="boolean" label="14128" help="36445">
3261+
<level>3</level>
3262+
<default>true</default>
3263+
<control type="toggle" />
3264+
</setting>
3265+
<setting id="videoscreen.whitelistdoublerefreshrate" type="boolean" label="14129" help="36446">
32613266
<level>3</level>
32623267
<default>true</default>
32633268
<control type="toggle" />

xbmc/windowing/Resolution.cpp

Lines changed: 108 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ namespace
2626
{
2727

2828
const char* SETTING_VIDEOSCREEN_WHITELIST_PULLDOWN{"videoscreen.whitelistpulldown"};
29+
const char* SETTING_VIDEOSCREEN_WHITELIST_WHOLENUMBER{"videoscreen.whitelistwholenumber"};
2930
const char* SETTING_VIDEOSCREEN_WHITELIST_DOUBLEREFRESHRATE{
3031
"videoscreen.whitelistdoublerefreshrate"};
3132

@@ -133,41 +134,10 @@ void CResolutionUtils::FindResolutionFromWhitelist(float fps, int width, int hei
133134
}
134135
}
135136

136-
CLog::Log(LOGDEBUG, "[WHITELIST] Searching for an exact resolution with an exact refresh rate");
137-
138137
unsigned int penalty = std::numeric_limits<unsigned int>::max();
139138
bool found = false;
140139

141-
for (const auto& mode : indexList)
142-
{
143-
auto i = CDisplaySettings::GetInstance().GetResFromString(mode.asString());
144-
const RESOLUTION_INFO info = CServiceBroker::GetWinSystem()->GetGfxContext().GetResInfo(i);
145-
146-
// allow resolutions that are exact and have the correct refresh rate
147-
// allow hardware decoder surface padding due to codec block alignment and GPU requirements
148-
// note: height has greater tolerance due to 32/64px boundaries e.g. 1080→1088 or 2160→2176
149-
if (((height == info.iScreenHeight && width <= info.iScreenWidth + 8) ||
150-
(width == info.iScreenWidth && height <= info.iScreenHeight + 32)) &&
151-
(info.dwFlags & dwFlags) == dwFlags &&
152-
MathUtils::FloatEquals(info.fRefreshRate, fps, 0.01f))
153-
{
154-
CLog::Log(LOGDEBUG,
155-
"[WHITELIST] Matched an exact resolution with an exact refresh rate {}, 0x{:x} ({})",
156-
info.strMode, info.dwFlags, i);
157-
unsigned int pen = abs(info.iScreenHeight - height) + abs(info.iScreenWidth - width);
158-
if (pen < penalty)
159-
{
160-
resolution = i;
161-
found = true;
162-
penalty = pen;
163-
}
164-
}
165-
}
166-
167-
if (!found)
168-
CLog::Log(LOGDEBUG, "[WHITELIST] No match for an exact resolution with an exact refresh rate");
169-
170-
if (noWhiteList || CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
140+
if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
171141
SETTING_VIDEOSCREEN_WHITELIST_DOUBLEREFRESHRATE))
172142
{
173143
CLog::Log(LOGDEBUG,
@@ -204,10 +174,79 @@ void CResolutionUtils::FindResolutionFromWhitelist(float fps, int width, int hei
204174
CLog::Log(LOGDEBUG,
205175
"[WHITELIST] No match for an exact resolution with double the refresh rate");
206176
}
207-
else if (found)
177+
178+
if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
179+
SETTING_VIDEOSCREEN_WHITELIST_WHOLENUMBER))
180+
{
181+
CLog::Log(LOGDEBUG,
182+
"[WHITELIST] Searching for an exact resolution with a whole-number repeat refresh rate");
183+
184+
for (const auto& mode : indexList)
185+
{
186+
auto i = CDisplaySettings::GetInstance().GetResFromString(mode.asString());
187+
const RESOLUTION_INFO info = CServiceBroker::GetWinSystem()->GetGfxContext().GetResInfo(i);
188+
189+
// allow resolutions that are exact and have 5 times the refresh rate
190+
// allow hardware decoder surface padding due to codec block alignment and GPU requirements
191+
if (((height == info.iScreenHeight && width <= info.iScreenWidth + 8) ||
192+
(width == info.iScreenWidth && height <= info.iScreenHeight + 32)) &&
193+
(info.dwFlags & dwFlags) == dwFlags &&
194+
(MathUtils::FloatEquals(info.fRefreshRate, fps * 4.0f, 0.01f) ||
195+
MathUtils::FloatEquals(info.fRefreshRate, fps * 5.0f, 0.01f)))
196+
{
197+
CLog::Log(
198+
LOGDEBUG,
199+
"[WHITELIST] Matched an exact resolution with a whole-number repeat refresh rate {} ({})",
200+
info.strMode, i);
201+
unsigned int pen = abs(info.iScreenHeight - height) + abs(info.iScreenWidth - width);
202+
if (pen < penalty)
203+
{
204+
resolution = i;
205+
found = true;
206+
penalty = pen;
207+
}
208+
}
209+
}
210+
if (found)
211+
return;
212+
213+
CLog::Log(LOGDEBUG, "[WHITELIST] No match for a resolution with a whole-number repeat refresh rate");
214+
}
215+
216+
CLog::Log(LOGDEBUG, "[WHITELIST] Searching for an exact resolution with an exact refresh rate");
217+
218+
for (const auto& mode : indexList)
219+
{
220+
auto i = CDisplaySettings::GetInstance().GetResFromString(mode.asString());
221+
const RESOLUTION_INFO info = CServiceBroker::GetWinSystem()->GetGfxContext().GetResInfo(i);
222+
223+
// allow resolutions that are exact and have the correct refresh rate
224+
// allow hardware decoder surface padding due to codec block alignment and GPU requirements
225+
// note: height has greater tolerance due to 32/64px boundaries e.g. 1080→1088 or 2160→2176
226+
if (((height == info.iScreenHeight && width <= info.iScreenWidth + 8) ||
227+
(width == info.iScreenWidth && height <= info.iScreenHeight + 32)) &&
228+
(info.dwFlags & dwFlags) == dwFlags &&
229+
MathUtils::FloatEquals(info.fRefreshRate, fps, 0.01f))
230+
{
231+
CLog::Log(LOGDEBUG,
232+
"[WHITELIST] Matched an exact resolution with an exact refresh rate {}, 0x{:x} ({})",
233+
info.strMode, info.dwFlags, i);
234+
unsigned int pen = abs(info.iScreenHeight - height) + abs(info.iScreenWidth - width);
235+
if (pen < penalty)
236+
{
237+
resolution = i;
238+
found = true;
239+
penalty = pen;
240+
}
241+
}
242+
}
243+
244+
if (!found)
245+
CLog::Log(LOGDEBUG, "[WHITELIST] No match for an exact resolution with an exact refresh rate");
246+
else
208247
return;
209248

210-
if (noWhiteList || CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
249+
if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
211250
SETTING_VIDEOSCREEN_WHITELIST_PULLDOWN))
212251
{
213252
CLog::Log(LOGDEBUG,
@@ -270,8 +309,10 @@ void CResolutionUtils::FindResolutionFromWhitelist(float fps, int width, int hei
270309
}
271310
if (!found)
272311
CLog::Log(LOGDEBUG, "[WHITELIST] No match for a closest resolution with an exact refresh rate");
312+
else
313+
return;
273314

274-
if (noWhiteList || CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
315+
if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
275316
SETTING_VIDEOSCREEN_WHITELIST_DOUBLEREFRESHRATE))
276317
{
277318
CLog::Log(LOGDEBUG, "[WHITELIST] Searching for a closest resolution with double refresh rate");
@@ -302,8 +343,6 @@ void CResolutionUtils::FindResolutionFromWhitelist(float fps, int width, int hei
302343

303344
CLog::Log(LOGDEBUG, "[WHITELIST] No match for a closest resolution with double refresh rate");
304345
}
305-
else if (found)
306-
return;
307346

308347
CLog::Log(LOGDEBUG, "[WHITELIST] Searching for a desktop resolution with an exact refresh rate");
309348

@@ -327,7 +366,7 @@ void CResolutionUtils::FindResolutionFromWhitelist(float fps, int width, int hei
327366

328367
CLog::Log(LOGDEBUG, "[WHITELIST] No match for a desktop resolution with an exact refresh rate");
329368

330-
if (noWhiteList || CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
369+
if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
331370
SETTING_VIDEOSCREEN_WHITELIST_DOUBLEREFRESHRATE))
332371
{
333372
CLog::Log(LOGDEBUG,
@@ -355,7 +394,7 @@ void CResolutionUtils::FindResolutionFromWhitelist(float fps, int width, int hei
355394
"[WHITELIST] No match for a desktop resolution with double the refresh rate");
356395
}
357396

358-
if (noWhiteList || CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
397+
if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
359398
SETTING_VIDEOSCREEN_WHITELIST_PULLDOWN))
360399
{
361400
CLog::Log(LOGDEBUG,
@@ -384,6 +423,36 @@ void CResolutionUtils::FindResolutionFromWhitelist(float fps, int width, int hei
384423
"[WHITELIST] No match for a desktop resolution with a 3:2 pulldown refresh rate");
385424
}
386425

426+
if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
427+
SETTING_VIDEOSCREEN_WHITELIST_WHOLENUMBER))
428+
{
429+
CLog::Log(LOGDEBUG,
430+
"[WHITELIST] Searching for a desktop resolution with a whole-number repeat refresh rate");
431+
432+
for (const auto& mode : indexList)
433+
{
434+
auto i = CDisplaySettings::GetInstance().GetResFromString(mode.asString());
435+
const RESOLUTION_INFO info = CServiceBroker::GetWinSystem()->GetGfxContext().GetResInfo(i);
436+
437+
// allow resolutions that are desktop resolution but have whole-number refresh rate
438+
if (info.iScreenWidth == desktop_info.iScreenWidth &&
439+
(info.dwFlags & dwFlags) == dwFlags &&
440+
(MathUtils::FloatEquals(info.fRefreshRate, fps * 4.0f, 0.01f) ||
441+
MathUtils::FloatEquals(info.fRefreshRate, fps * 5.0f, 0.01f)))
442+
{
443+
CLog::Log(
444+
LOGDEBUG,
445+
"[WHITELIST] Matched a desktop resolution with a whole-number repeat refresh rate {} ({})",
446+
info.strMode, i);
447+
resolution = i;
448+
return;
449+
}
450+
}
451+
452+
CLog::Log(LOGDEBUG,
453+
"[WHITELIST] No match for a desktop resolution with a whole-number repeat refresh rate");
454+
}
455+
387456
if (is3D && curr.fRefreshRate > 30)
388457
{
389458
CLog::Log(LOGDEBUG, "[WHITELIST] No resolution matched but refresh rate is {:0.3f}", curr.fRefreshRate);

0 commit comments

Comments
 (0)