Skip to content

Commit 7a29841

Browse files
authored
Merge pull request rdkcentral#6326 from asurdej-comcast/hdr_settings_2
RDK-58069: Dynamic management of HDR settings
2 parents feddce4 + fbece25 commit 7a29841

File tree

1 file changed

+215
-1
lines changed

1 file changed

+215
-1
lines changed

WebKitBrowser/WebKitImplementation.cpp

Lines changed: 215 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@
4646

4747
#define HAS_MEMORY_PRESSURE_SETTINGS_API WEBKIT_CHECK_VERSION(2, 38, 0)
4848

49+
#define HAS_SCREEN_HDR_API WEBKIT_CHECK_VERSION(2, 46, 0)
50+
#if HAS_SCREEN_HDR_API
51+
#include <interfaces/IDisplayInfo.h>
52+
#endif
53+
4954
#ifdef ENABLE_TESTING
5055
#include <testrunner.h>
5156
#endif // ENABLE_TESTING
@@ -78,7 +83,11 @@ namespace Plugin {
7883
#if defined(ENABLE_CLOUD_COOKIE_JAR)
7984
public Exchange::IBrowserCookieJar,
8085
#endif
81-
public PluginHost::IStateControl {
86+
public PluginHost::IStateControl
87+
#if HAS_SCREEN_HDR_API
88+
, public Exchange::IConnectionProperties::INotification
89+
#endif
90+
{
8291
public:
8392
class BundleConfig : public Core::JSON::Container {
8493
private:
@@ -334,6 +343,7 @@ namespace Plugin {
334343
, ICECandidateFilteringEnabled()
335344
, GstQuirks()
336345
, GstHolePunchQuirk()
346+
, HDRRefreshDelay(1000) // Default to 1 second for HDR refresh delay
337347
{
338348
Add(_T("useragent"), &UserAgent);
339349
Add(_T("url"), &URL);
@@ -406,6 +416,7 @@ namespace Plugin {
406416
Add(_T("icecandidatefiltering"), &ICECandidateFilteringEnabled);
407417
Add(_T("gstquirks"), &GstQuirks);
408418
Add(_T("gstholepunchquirk"), &GstHolePunchQuirk);
419+
Add(_T("hdrrefreshDelay"), &HDRRefreshDelay);
409420
}
410421
~Config()
411422
{
@@ -483,6 +494,7 @@ namespace Plugin {
483494
Core::JSON::Boolean ICECandidateFilteringEnabled;
484495
Core::JSON::String GstQuirks;
485496
Core::JSON::String GstHolePunchQuirk;
497+
Core::JSON::DecUInt16 HDRRefreshDelay; // Delay in miliseconds to refresh HDR support
486498
};
487499

488500
class HangDetector
@@ -622,6 +634,11 @@ namespace Plugin {
622634
, _unresponsiveReplyNum(0)
623635
, _frameCount(0)
624636
, _lastDumpTime(g_get_monotonic_time())
637+
#if HAS_SCREEN_HDR_API
638+
,_displayInfoPlugin(nullptr)
639+
,_displayConnectionProps(nullptr)
640+
,_hdrSupported(false)
641+
#endif // HAS_SCREEN_HDR_API
625642
{
626643
// Register an @Exit, in case we are killed, with an incorrect ref count !!
627644
if (atexit(CloseDown) != 0) {
@@ -652,6 +669,10 @@ namespace Plugin {
652669
TRACE(Trace::Information, (_T("Bailed out before the end of the WPE main app was reached. %d"), 6000));
653670
}
654671

672+
#if HAS_SCREEN_HDR_API
673+
UnsubscribeHDRCapabilities();
674+
#endif
675+
655676
implementation = nullptr;
656677
}
657678

@@ -1935,6 +1956,7 @@ namespace Plugin {
19351956
_config.Bundle.Config(key,value);
19361957
return (value);
19371958
}
1959+
19381960
BEGIN_INTERFACE_MAP(WebKitImplementation)
19391961
INTERFACE_ENTRY(Exchange::IWebBrowser)
19401962
INTERFACE_ENTRY(Exchange::IBrowser)
@@ -1944,6 +1966,9 @@ namespace Plugin {
19441966
INTERFACE_ENTRY (Exchange::IBrowserCookieJar)
19451967
#endif
19461968
INTERFACE_ENTRY(PluginHost::IStateControl)
1969+
#if HAS_SCREEN_HDR_API
1970+
INTERFACE_ENTRY(Exchange::IConnectionProperties::INotification)
1971+
#endif
19471972
END_INTERFACE_MAP
19481973

19491974
private:
@@ -2523,6 +2548,13 @@ namespace Plugin {
25232548
// webaudio support
25242549
webkit_settings_set_enable_webaudio(preferences, _config.WebAudioEnabled.Value());
25252550

2551+
#if HAS_SCREEN_HDR_API
2552+
SubscribeHDRCapabilities();
2553+
// Query the current HDR capabilities before we start the browser
2554+
RefreshHDRSupport();
2555+
UpdateHDRSettings(preferences);
2556+
#endif
2557+
25262558
// Allow mixed content.
25272559
bool enableWebSecurity = _config.Secure.Value();
25282560
#if WEBKIT_CHECK_VERSION(2, 38, 0)
@@ -2688,6 +2720,181 @@ namespace Plugin {
26882720
}
26892721
}
26902722

2723+
#if HAS_SCREEN_HDR_API
2724+
WPEFramework::PluginHost::IPlugin* QueryDisplayInfoPlugin()
2725+
{
2726+
if (_displayInfoPlugin) {
2727+
return _displayInfoPlugin;
2728+
}
2729+
if (!_service) {
2730+
return nullptr;
2731+
}
2732+
_displayInfoPlugin = _service->QueryInterfaceByCallsign<WPEFramework::PluginHost::IPlugin>(_T("DisplayInfo"));
2733+
if (!_displayInfoPlugin) {
2734+
SYSLOG(Logging::Error, (_T("Failed to query DisplayInfo plugin.")));
2735+
return nullptr;
2736+
}
2737+
return _displayInfoPlugin;
2738+
}
2739+
2740+
bool SubscribeHDRCapabilities()
2741+
{
2742+
auto* displayInfoPlugin = QueryDisplayInfoPlugin();
2743+
if (!displayInfoPlugin || _displayConnectionProps) {
2744+
return false;
2745+
}
2746+
_displayConnectionProps = displayInfoPlugin->QueryInterface<Exchange::IConnectionProperties>();
2747+
if (!_displayConnectionProps) {
2748+
SYSLOG(Logging::Error, (_T("Failed to query IConnectionProperties interface from DisplayInfo plugin.")));
2749+
return false;
2750+
}
2751+
_displayConnectionProps->Register(this);
2752+
SYSLOG(Logging::Notification, (_T("Subscribed to HDR capabilities updates from DisplayInfo plugin.")));
2753+
return true;
2754+
}
2755+
2756+
void UnsubscribeHDRCapabilities()
2757+
{
2758+
if (_displayConnectionProps) {
2759+
_displayConnectionProps->Unregister(this);
2760+
_displayConnectionProps->Release();
2761+
_displayConnectionProps = nullptr;
2762+
}
2763+
_adminLock.Lock();
2764+
if (_hdrRefreshJob.IsValid()) {
2765+
Core::WorkerPool::Instance().Revoke(_hdrRefreshJob);
2766+
_hdrRefreshJob.Release();
2767+
}
2768+
_adminLock.Unlock();
2769+
if (_displayInfoPlugin) {
2770+
_displayInfoPlugin->Release();
2771+
_displayInfoPlugin = nullptr;
2772+
}
2773+
SYSLOG(Logging::Notification, (_T("Unsubscribed from HDR capabilities updates from DisplayInfo plugin.")));
2774+
}
2775+
2776+
void RefreshHDRSupport()
2777+
{
2778+
// HDR support will be set to false in case of any failure
2779+
bool isHDRSupported = false;
2780+
struct ScopeExit {
2781+
bool& isHDRSupported;
2782+
WebKitImplementation& browser;
2783+
~ScopeExit() {
2784+
browser._adminLock.Lock();
2785+
bool wasSupported = browser._hdrSupported;
2786+
browser._hdrSupported = isHDRSupported;
2787+
browser._adminLock.Unlock();
2788+
if (wasSupported != isHDRSupported) {
2789+
SYSLOG(Logging::Notification, (_T("HDR support changed to %s"), isHDRSupported ? "true" : "false"));
2790+
}
2791+
}
2792+
} scope_exit{isHDRSupported, *this};
2793+
2794+
auto displayInfoPlugin = QueryDisplayInfoPlugin();
2795+
if (!displayInfoPlugin) {
2796+
return;
2797+
}
2798+
Exchange::IHDRProperties* hdrPropIface = displayInfoPlugin->QueryInterface<Exchange::IHDRProperties>();
2799+
if (!hdrPropIface) {
2800+
SYSLOG(Logging::Error, (_T("Failed to query IHDRProperties interface from DisplayInfo plugin.")));
2801+
return;
2802+
}
2803+
uint32_t rc = Core::ERROR_NONE;
2804+
Exchange::IHDRProperties::IHDRIterator* iter = nullptr;
2805+
if ((rc = hdrPropIface->STBCapabilities(iter)) != Core::ERROR_NONE) {
2806+
SYSLOG(Logging::Error, (_T("Failed to get STB HDR capabilities, error code: %u"), rc));
2807+
hdrPropIface->Release();
2808+
return;
2809+
}
2810+
2811+
std::vector<Exchange::IHDRProperties::HDRType> stbCaps;
2812+
Exchange::IHDRProperties::HDRType value;
2813+
while (iter->Next(value)) {
2814+
stbCaps.push_back(value);
2815+
}
2816+
iter->Release();
2817+
iter = nullptr;
2818+
2819+
if ((rc = hdrPropIface->TVCapabilities(iter)) != Core::ERROR_NONE) {
2820+
SYSLOG(Logging::Error, (_T("Failed to get TV HDR capabilities, error code: %u"), rc));
2821+
hdrPropIface->Release();
2822+
return;
2823+
}
2824+
2825+
std::vector<Exchange::IHDRProperties::HDRType> commonCaps;
2826+
while (iter->Next(value)) {
2827+
if (std::find(stbCaps.begin(), stbCaps.end(), value) != stbCaps.end()) {
2828+
commonCaps.push_back(value);
2829+
}
2830+
}
2831+
iter->Release();
2832+
hdrPropIface->Release();
2833+
2834+
for (const auto& cap : commonCaps) {
2835+
if (cap > Exchange::IHDRProperties::HDRType::HDR_OFF) {
2836+
isHDRSupported = true;
2837+
break;
2838+
}
2839+
}
2840+
// _hdrSupported will be update in the scope exit handler
2841+
}
2842+
2843+
void UpdateHDRSettings(WebKitSettings* settings)
2844+
{
2845+
ASSERT(settings != nullptr);
2846+
_adminLock.Lock();
2847+
bool isHDRSupported = _hdrSupported;
2848+
_adminLock.Unlock();
2849+
if (webkit_settings_get_screen_supports_hdr(settings) != isHDRSupported) {
2850+
SYSLOG(Logging::Notification, (_T("Updating HDR support setting to %s"), isHDRSupported ? "true" : "false"));
2851+
webkit_settings_set_screen_supports_hdr(settings, isHDRSupported);
2852+
}
2853+
}
2854+
2855+
class HDRRefreshJob : public Core::IDispatch {
2856+
public:
2857+
HDRRefreshJob(WebKitImplementation& browser)
2858+
: _browser(browser)
2859+
{
2860+
}
2861+
~HDRRefreshJob() override = default;
2862+
void Dispatch() override
2863+
{
2864+
_browser.RefreshHDRSupport();
2865+
g_main_context_invoke(
2866+
_browser._context,
2867+
[](gpointer user_data) -> gboolean {
2868+
WebKitImplementation* browser = static_cast<WebKitImplementation*>(user_data);
2869+
WebKitSettings* settings = webkit_web_view_get_settings(browser->_view);
2870+
browser->UpdateHDRSettings(settings);
2871+
return G_SOURCE_REMOVE;
2872+
},
2873+
&_browser);
2874+
}
2875+
private:
2876+
WebKitImplementation& _browser;
2877+
};
2878+
2879+
// Exchange::IConnectionProperties::INotification implementation
2880+
// This method is called on the main thread of the plugin
2881+
// when the display connection properties are updated.
2882+
void Updated(const Exchange::IConnectionProperties::INotification::Source event) override
2883+
{
2884+
SYSLOG(Logging::Notification, (_T("Display connection properties updated, event: %s"),
2885+
Core::EnumerateType<Exchange::IConnectionProperties::INotification::Source>(event).Data()));
2886+
_adminLock.Lock();
2887+
if (!_hdrRefreshJob.IsValid()) {
2888+
_hdrRefreshJob = Core::ProxyType<HDRRefreshJob>::Create(*this);
2889+
// If a refresh is already scheduled, do nothing
2890+
}
2891+
// Delay the refresh to avoid too frequent updates
2892+
// and to allow the display connection properties to stabilize.
2893+
Core::WorkerPool::Instance().Reschedule(Core::Time::Now().Add(_config.HDRRefreshDelay.Value()), _hdrRefreshJob);
2894+
_adminLock.Unlock();
2895+
}
2896+
#endif // HAS_SCREEN_HDR_API
2897+
26912898
void CheckWebProcess()
26922899
{
26932900
if ( _webProcessCheckInProgress )
@@ -2823,6 +3030,13 @@ namespace Plugin {
28233030
uint32_t _unresponsiveReplyNum;
28243031
unsigned _frameCount;
28253032
gint64 _lastDumpTime;
3033+
3034+
#if HAS_SCREEN_HDR_API
3035+
PluginHost::IPlugin* _displayInfoPlugin;
3036+
Exchange::IConnectionProperties* _displayConnectionProps;
3037+
Core::ProxyType<Core::IDispatch> _hdrRefreshJob;
3038+
bool _hdrSupported;
3039+
#endif // HAS_SCREEN_HDR_API
28263040
};
28273041

28283042
SERVICE_REGISTRATION(WebKitImplementation, 1, 0);

0 commit comments

Comments
 (0)