Skip to content

Commit ed407a0

Browse files
RDK-58069: Dynamic management of HDR settings
Reason for change: Manage High Dynamic Range settings for webkit Test Procedure: See Jira ticket Priority: P1 Risks: Medim - webapps video playback Signed-off-by: Andrzej Surdej <[email protected]>
1 parent 8fbfbb2 commit ed407a0

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:
@@ -333,6 +342,7 @@ namespace Plugin {
333342
, ICECandidateFilteringEnabled()
334343
, GstQuirks()
335344
, GstHolePunchQuirk()
345+
, HDRRefreshDelay(1000) // Default to 1 second for HDR refresh delay
336346
{
337347
Add(_T("useragent"), &UserAgent);
338348
Add(_T("url"), &URL);
@@ -404,6 +414,7 @@ namespace Plugin {
404414
Add(_T("icecandidatefiltering"), &ICECandidateFilteringEnabled);
405415
Add(_T("gstquirks"), &GstQuirks);
406416
Add(_T("gstholepunchquirk"), &GstHolePunchQuirk);
417+
Add(_T("hdrrefreshDelay"), &HDRRefreshDelay);
407418
}
408419
~Config()
409420
{
@@ -480,6 +491,7 @@ namespace Plugin {
480491
Core::JSON::Boolean ICECandidateFilteringEnabled;
481492
Core::JSON::String GstQuirks;
482493
Core::JSON::String GstHolePunchQuirk;
494+
Core::JSON::DecUInt16 HDRRefreshDelay; // Delay in miliseconds to refresh HDR support
483495
};
484496

485497
class HangDetector
@@ -619,6 +631,11 @@ namespace Plugin {
619631
, _unresponsiveReplyNum(0)
620632
, _frameCount(0)
621633
, _lastDumpTime(g_get_monotonic_time())
634+
#if HAS_SCREEN_HDR_API
635+
,_displayInfoPlugin(nullptr)
636+
,_displayConnectionProps(nullptr)
637+
,_hdrSupported(false)
638+
#endif // HAS_SCREEN_HDR_API
622639
{
623640
// Register an @Exit, in case we are killed, with an incorrect ref count !!
624641
if (atexit(CloseDown) != 0) {
@@ -649,6 +666,10 @@ namespace Plugin {
649666
TRACE(Trace::Information, (_T("Bailed out before the end of the WPE main app was reached. %d"), 6000));
650667
}
651668

669+
#if HAS_SCREEN_HDR_API
670+
UnsubscribeHDRCapabilities();
671+
#endif
672+
652673
implementation = nullptr;
653674
}
654675

@@ -1927,6 +1948,7 @@ namespace Plugin {
19271948
_config.Bundle.Config(key,value);
19281949
return (value);
19291950
}
1951+
19301952
BEGIN_INTERFACE_MAP(WebKitImplementation)
19311953
INTERFACE_ENTRY(Exchange::IWebBrowser)
19321954
INTERFACE_ENTRY(Exchange::IBrowser)
@@ -1936,6 +1958,9 @@ namespace Plugin {
19361958
INTERFACE_ENTRY (Exchange::IBrowserCookieJar)
19371959
#endif
19381960
INTERFACE_ENTRY(PluginHost::IStateControl)
1961+
#if HAS_SCREEN_HDR_API
1962+
INTERFACE_ENTRY(Exchange::IConnectionProperties::INotification)
1963+
#endif
19391964
END_INTERFACE_MAP
19401965

19411966
private:
@@ -2490,6 +2515,13 @@ namespace Plugin {
24902515
// webaudio support
24912516
webkit_settings_set_enable_webaudio(preferences, _config.WebAudioEnabled.Value());
24922517

2518+
#if HAS_SCREEN_HDR_API
2519+
SubscribeHDRCapabilities();
2520+
// Query the current HDR capabilities before we start the browser
2521+
RefreshHDRSupport();
2522+
UpdateHDRSettings(preferences);
2523+
#endif
2524+
24932525
// Allow mixed content.
24942526
bool enableWebSecurity = _config.Secure.Value();
24952527
#if WEBKIT_CHECK_VERSION(2, 38, 0)
@@ -2655,6 +2687,181 @@ namespace Plugin {
26552687
}
26562688
}
26572689

2690+
#if HAS_SCREEN_HDR_API
2691+
WPEFramework::PluginHost::IPlugin* QueryDisplayInfoPlugin()
2692+
{
2693+
if (_displayInfoPlugin) {
2694+
return _displayInfoPlugin;
2695+
}
2696+
if (!_service) {
2697+
return nullptr;
2698+
}
2699+
_displayInfoPlugin = _service->QueryInterfaceByCallsign<WPEFramework::PluginHost::IPlugin>(_T("DisplayInfo"));
2700+
if (!_displayInfoPlugin) {
2701+
SYSLOG(Logging::Error, (_T("Failed to query DisplayInfo plugin.")));
2702+
return nullptr;
2703+
}
2704+
return _displayInfoPlugin;
2705+
}
2706+
2707+
bool SubscribeHDRCapabilities()
2708+
{
2709+
auto* displayInfoPlugin = QueryDisplayInfoPlugin();
2710+
if (!displayInfoPlugin || _displayConnectionProps) {
2711+
return false;
2712+
}
2713+
_displayConnectionProps = displayInfoPlugin->QueryInterface<Exchange::IConnectionProperties>();
2714+
if (!_displayConnectionProps) {
2715+
SYSLOG(Logging::Error, (_T("Failed to query IConnectionProperties interface from DisplayInfo plugin.")));
2716+
return false;
2717+
}
2718+
_displayConnectionProps->Register(this);
2719+
SYSLOG(Logging::Notification, (_T("Subscribed to HDR capabilities updates from DisplayInfo plugin.")));
2720+
return true;
2721+
}
2722+
2723+
void UnsubscribeHDRCapabilities()
2724+
{
2725+
if (_displayConnectionProps) {
2726+
_displayConnectionProps->Unregister(this);
2727+
_displayConnectionProps->Release();
2728+
_displayConnectionProps = nullptr;
2729+
}
2730+
_adminLock.Lock();
2731+
if (_hdrRefreshJob.IsValid()) {
2732+
Core::WorkerPool::Instance().Revoke(_hdrRefreshJob);
2733+
_hdrRefreshJob.Release();
2734+
}
2735+
_adminLock.Unlock();
2736+
if (_displayInfoPlugin) {
2737+
_displayInfoPlugin->Release();
2738+
_displayInfoPlugin = nullptr;
2739+
}
2740+
SYSLOG(Logging::Notification, (_T("Unsubscribed from HDR capabilities updates from DisplayInfo plugin.")));
2741+
}
2742+
2743+
void RefreshHDRSupport()
2744+
{
2745+
// HDR support will be set to false in case of any failure
2746+
bool isHDRSupported = false;
2747+
struct ScopeExit {
2748+
bool& isHDRSupported;
2749+
WebKitImplementation& browser;
2750+
~ScopeExit() {
2751+
browser._adminLock.Lock();
2752+
bool wasSupported = browser._hdrSupported;
2753+
browser._hdrSupported = isHDRSupported;
2754+
browser._adminLock.Unlock();
2755+
if (wasSupported != isHDRSupported) {
2756+
SYSLOG(Logging::Notification, (_T("HDR support changed to %s"), isHDRSupported ? "true" : "false"));
2757+
}
2758+
}
2759+
} scope_exit{isHDRSupported, *this};
2760+
2761+
auto displayInfoPlugin = QueryDisplayInfoPlugin();
2762+
if (!displayInfoPlugin) {
2763+
return;
2764+
}
2765+
Exchange::IHDRProperties* hdrPropIface = displayInfoPlugin->QueryInterface<Exchange::IHDRProperties>();
2766+
if (!hdrPropIface) {
2767+
SYSLOG(Logging::Error, (_T("Failed to query IHDRProperties interface from DisplayInfo plugin.")));
2768+
return;
2769+
}
2770+
uint32_t rc = Core::ERROR_NONE;
2771+
Exchange::IHDRProperties::IHDRIterator* iter = nullptr;
2772+
if ((rc = hdrPropIface->STBCapabilities(iter)) != Core::ERROR_NONE) {
2773+
SYSLOG(Logging::Error, (_T("Failed to get STB HDR capabilities, error code: %u"), rc));
2774+
hdrPropIface->Release();
2775+
return;
2776+
}
2777+
2778+
std::vector<Exchange::IHDRProperties::HDRType> stbCaps;
2779+
Exchange::IHDRProperties::HDRType value;
2780+
while (iter->Next(value)) {
2781+
stbCaps.push_back(value);
2782+
}
2783+
iter->Release();
2784+
iter = nullptr;
2785+
2786+
if ((rc = hdrPropIface->TVCapabilities(iter)) != Core::ERROR_NONE) {
2787+
SYSLOG(Logging::Error, (_T("Failed to get TV HDR capabilities, error code: %u"), rc));
2788+
hdrPropIface->Release();
2789+
return;
2790+
}
2791+
2792+
std::vector<Exchange::IHDRProperties::HDRType> commonCaps;
2793+
while (iter->Next(value)) {
2794+
if (std::find(stbCaps.begin(), stbCaps.end(), value) != stbCaps.end()) {
2795+
commonCaps.push_back(value);
2796+
}
2797+
}
2798+
iter->Release();
2799+
hdrPropIface->Release();
2800+
2801+
for (const auto& cap : commonCaps) {
2802+
if (cap > Exchange::IHDRProperties::HDRType::HDR_OFF) {
2803+
isHDRSupported = true;
2804+
break;
2805+
}
2806+
}
2807+
// _hdrSupported will be update in the scope exit handler
2808+
}
2809+
2810+
void UpdateHDRSettings(WebKitSettings* settings)
2811+
{
2812+
ASSERT(settings != nullptr);
2813+
_adminLock.Lock();
2814+
bool isHDRSupported = _hdrSupported;
2815+
_adminLock.Unlock();
2816+
if (webkit_settings_get_screen_supports_hdr(settings) != isHDRSupported) {
2817+
SYSLOG(Logging::Notification, (_T("Updating HDR support setting to %s"), isHDRSupported ? "true" : "false"));
2818+
webkit_settings_set_screen_supports_hdr(settings, isHDRSupported);
2819+
}
2820+
}
2821+
2822+
class HDRRefreshJob : public Core::IDispatch {
2823+
public:
2824+
HDRRefreshJob(WebKitImplementation& browser)
2825+
: _browser(browser)
2826+
{
2827+
}
2828+
~HDRRefreshJob() override = default;
2829+
void Dispatch() override
2830+
{
2831+
_browser.RefreshHDRSupport();
2832+
g_main_context_invoke(
2833+
_browser._context,
2834+
[](gpointer user_data) -> gboolean {
2835+
WebKitImplementation* browser = static_cast<WebKitImplementation*>(user_data);
2836+
WebKitSettings* settings = webkit_web_view_get_settings(browser->_view);
2837+
browser->UpdateHDRSettings(settings);
2838+
return G_SOURCE_REMOVE;
2839+
},
2840+
&_browser);
2841+
}
2842+
private:
2843+
WebKitImplementation& _browser;
2844+
};
2845+
2846+
// Exchange::IConnectionProperties::INotification implementation
2847+
// This method is called on the main thread of the plugin
2848+
// when the display connection properties are updated.
2849+
void Updated(const Exchange::IConnectionProperties::INotification::Source event) override
2850+
{
2851+
SYSLOG(Logging::Notification, (_T("Display connection properties updated, event: %s"),
2852+
Core::EnumerateType<Exchange::IConnectionProperties::INotification::Source>(event).Data()));
2853+
_adminLock.Lock();
2854+
if (!_hdrRefreshJob.IsValid()) {
2855+
_hdrRefreshJob = Core::ProxyType<HDRRefreshJob>::Create(*this);
2856+
// If a refresh is already scheduled, do nothing
2857+
}
2858+
// Delay the refresh to avoid too frequent updates
2859+
// and to allow the display connection properties to stabilize.
2860+
Core::WorkerPool::Instance().Reschedule(Core::Time::Now().Add(_config.HDRRefreshDelay.Value()), _hdrRefreshJob);
2861+
_adminLock.Unlock();
2862+
}
2863+
#endif // HAS_SCREEN_HDR_API
2864+
26582865
void CheckWebProcess()
26592866
{
26602867
if ( _webProcessCheckInProgress )
@@ -2790,6 +2997,13 @@ namespace Plugin {
27902997
uint32_t _unresponsiveReplyNum;
27912998
unsigned _frameCount;
27922999
gint64 _lastDumpTime;
3000+
3001+
#if HAS_SCREEN_HDR_API
3002+
PluginHost::IPlugin* _displayInfoPlugin;
3003+
Exchange::IConnectionProperties* _displayConnectionProps;
3004+
Core::ProxyType<Core::IDispatch> _hdrRefreshJob;
3005+
bool _hdrSupported;
3006+
#endif // HAS_SCREEN_HDR_API
27933007
};
27943008

27953009
SERVICE_REGISTRATION(WebKitImplementation, 1, 0);

0 commit comments

Comments
 (0)