Merge "Workaround crash on deactivation." into 24.lts.dev
diff --git a/src/third_party/starboard/rdk/shared/application_rdk.cc b/src/third_party/starboard/rdk/shared/application_rdk.cc
index 34dbf2b..cbfa0f7 100644
--- a/src/third_party/starboard/rdk/shared/application_rdk.cc
+++ b/src/third_party/starboard/rdk/shared/application_rdk.cc
@@ -45,6 +45,7 @@
 #include <sys/eventfd.h>
 #include <sys/timerfd.h>
 #include <unistd.h>
+#include <malloc.h>
 
 namespace third_party {
 namespace starboard {
@@ -139,6 +140,8 @@
   using ::starboard::shared::starboard::media::MimeSupportabilityCache;
   MimeSupportabilityCache::GetInstance()->SetCacheEnabled(true);
   KeySystemSupportabilityCache::GetInstance()->SetCacheEnabled(true);
+
+  ScheduleMemoryUsageCheck();
 }
 
 void Application::Teardown() {
@@ -388,6 +391,48 @@
   }, nullptr, 0);
 }
 
+void Application::ReleaseMemory() {
+  Inject(new Event(kSbEventTypeLowMemory, NULL, [](void*) {
+    malloc_trim(0);
+  }));
+}
+
+void Application::ScheduleMemoryUsageCheck(SbTime delay) {
+  SbEventSchedule([](void* data) {
+    SbTime back_off_timeout = Application::Get()->CheckMemoryUsage();
+    if (back_off_timeout && back_off_timeout != kSbTimeMax)
+      Application::Get()->ScheduleMemoryUsageCheck(back_off_timeout);
+  }, nullptr, delay);
+}
+
+SbTime Application::CheckMemoryUsage() {
+  static const int64_t kCPUMemoryPressureLimit = ([]() -> int64_t {
+    const char* env = std::getenv("COBALT_CPU_MEM_PRESSURE_IN_MB");
+    int64_t limit_in_mb = SB_INT64_C(400);
+    if( env ) {
+      int64_t t = strtol(env, nullptr, 0);
+      if ( t >= 0 )
+        limit_in_mb = t;
+    }
+    int64_t total_in_bytes = SbSystemGetTotalCPUMemory();
+    return std::min(total_in_bytes, limit_in_mb * 1024 * 1024);
+  })();
+
+  if (!kCPUMemoryPressureLimit)
+    return kSbTimeMax;
+
+  int64_t usage_in_bytes = SbSystemGetUsedCPUMemory();
+  if (kCPUMemoryPressureLimit < usage_in_bytes) {
+    SB_LOG(INFO) << "Triggering memory pressure event. Current CPU mem. usage: "
+                 << uint64_t(usage_in_bytes / 1024) << " kb, pressure limit: "
+                 << uint64_t(kCPUMemoryPressureLimit / 1024) << " kb.";
+    ReleaseMemory();
+    return 5 * kSbTimeSecond;
+  }
+
+  return kSbTimeSecond;
+}
+
 }  // namespace shared
 }  // namespace rdk
 }  // namespace starboard
diff --git a/src/third_party/starboard/rdk/shared/application_rdk.h b/src/third_party/starboard/rdk/shared/application_rdk.h
index d88180a..1bd3dda 100644
--- a/src/third_party/starboard/rdk/shared/application_rdk.h
+++ b/src/third_party/starboard/rdk/shared/application_rdk.h
@@ -104,6 +104,10 @@
   void BuildEssosContext();
   void FatalError();
 
+  void ScheduleMemoryUsageCheck(SbTime delay = kSbTimeSecond);
+  SbTime CheckMemoryUsage();
+  void ReleaseMemory();
+
   static EssTerminateListener terminateListener;
   static EssKeyListener keyListener;
   static EssSettingsListener settingsListener;
diff --git a/src/third_party/starboard/rdk/shared/media/media_get_buffer_garbage_collection_duration_threshold.cc b/src/third_party/starboard/rdk/shared/media/media_get_buffer_garbage_collection_duration_threshold.cc
index 4aa55ea..e8f872e 100644
--- a/src/third_party/starboard/rdk/shared/media/media_get_buffer_garbage_collection_duration_threshold.cc
+++ b/src/third_party/starboard/rdk/shared/media/media_get_buffer_garbage_collection_duration_threshold.cc
@@ -34,5 +34,5 @@
 #include "starboard/common/log.h"
 
 SbTime SbMediaGetBufferGarbageCollectionDurationThreshold() {
-  return 170 * kSbTimeSecond;
+  return 40 * kSbTimeSecond;
 }
diff --git a/src/third_party/starboard/rdk/shared/player/player_internal.cc b/src/third_party/starboard/rdk/shared/player/player_internal.cc
index 0236174..1f884b9 100644
--- a/src/third_party/starboard/rdk/shared/player/player_internal.cc
+++ b/src/third_party/starboard/rdk/shared/player/player_internal.cc
@@ -416,6 +416,7 @@
   gst_app_src_set_emit_signals(GST_APP_SRC(appsrc), FALSE);
   gst_app_src_set_callbacks(GST_APP_SRC(appsrc), callbacks, user_data, nullptr);
   gst_app_src_set_max_bytes(GST_APP_SRC(appsrc), max_bytes);
+  gst_base_src_set_format(GST_BASE_SRC(appsrc), GST_FORMAT_TIME);
 
   GstCobaltSrc* src = GST_COBALT_SRC(element);
   gchar* name = g_strdup_printf("src_%u", src->priv->pad_number);
diff --git a/src/third_party/starboard/rdk/shared/system/system_has_capability.cc b/src/third_party/starboard/rdk/shared/system/system_has_capability.cc
index e09e260..c514cb0 100644
--- a/src/third_party/starboard/rdk/shared/system/system_has_capability.cc
+++ b/src/third_party/starboard/rdk/shared/system/system_has_capability.cc
@@ -14,13 +14,15 @@
 #include "starboard/system.h"
 
 #include "starboard/common/log.h"
+#include "starboard/file.h"
 
 bool SbSystemHasCapability(SbSystemCapabilityId capability_id) {
   switch (capability_id) {
     case kSbSystemCapabilityReversedEnterAndBack:
       return false;
     case kSbSystemCapabilityCanQueryGPUMemoryStats:
-      return true;
+      static bool gpu_stats_exists_cached = SbFileExists("/sys/fs/cgroup/gpu/gpu.usage_in_bytes");
+      return gpu_stats_exists_cached;
   }
 
   SB_DLOG(WARNING) << "Unrecognized capability: " << capability_id;