Import Cobalt 22.lts.1.305559
diff --git a/src/.pylintrc b/src/.pylintrc
index e167680..239c66f 100644
--- a/src/.pylintrc
+++ b/src/.pylintrc
@@ -118,6 +118,7 @@
         old-raise-syntax,
         parameter-unpacking,
         print-statement,
+        raise-missing-from,
         raising-string,
         range-builtin-not-iterating,
         raw_input-builtin,
@@ -129,6 +130,7 @@
         setslice-method,
         signature-differs,
         standarderror-builtin,
+        super-with-arguments,
         suppressed-message,
         sys-max-int,
         too-few-public-methods,
@@ -147,6 +149,8 @@
         unicode-builtin,
         unnecessary-pass,
         unpacking-in-except,
+        unspecified-encoding,
+        use-maxsplit-arg,
         useless-else-on-loop,
         useless-object-inheritance,
         useless-suppression,
diff --git a/src/build/toolchain/gcc_toolchain.gni b/src/build/toolchain/gcc_toolchain.gni
index 09af53d..42e2b80 100644
--- a/src/build/toolchain/gcc_toolchain.gni
+++ b/src/build/toolchain/gcc_toolchain.gni
@@ -665,7 +665,7 @@
     ld = cxx
     readelf = "${toolprefix}readelf"
     ar = "${prefix}/llvm-ar"
-    nm = "${prefix}/llvm-nm"
+    nm = "nm"
 
     forward_variables_from(invoker,
                            [
diff --git a/src/cobalt/browser/browser.gyp b/src/cobalt/browser/browser.gyp
index 65444e2..6eb6f23 100644
--- a/src/cobalt/browser/browser.gyp
+++ b/src/cobalt/browser/browser.gyp
@@ -37,8 +37,6 @@
         'memory_settings/checker.cc',
         'memory_settings/checker.h',
         'memory_settings/constants.h',
-        'memory_settings/constrainer.cc',
-        'memory_settings/constrainer.h',
         'memory_settings/scaling_function.cc',
         'memory_settings/scaling_function.h',
         'memory_settings/memory_settings.cc',
@@ -209,7 +207,6 @@
         'memory_settings/auto_mem_test.cc',
         'memory_settings/auto_mem_settings_test.cc',
         'memory_settings/calculations_test.cc',
-        'memory_settings/constrainer_test.cc',
         'memory_settings/memory_settings_test.cc',
         'memory_settings/pretty_print_test.cc',
         'memory_settings/table_printer_test.cc',
diff --git a/src/cobalt/browser/browser_module.cc b/src/cobalt/browser/browser_module.cc
index f66ed8b..44fc15e 100644
--- a/src/cobalt/browser/browser_module.cc
+++ b/src/cobalt/browser/browser_module.cc
@@ -1641,7 +1641,7 @@
 void BrowserModule::InitializeSystemWindow() {
   TRACE_EVENT0("cobalt::browser", "BrowserModule::InitializeSystemWindow()");
   DCHECK(!system_window_);
-  if (media_module_) {
+  if (media_module_ && !window_size_.IsEmpty()) {
     system_window_.reset(
         new system_window::SystemWindow(event_dispatcher_, window_size_));
   } else {
diff --git a/src/cobalt/browser/memory_settings/auto_mem.cc b/src/cobalt/browser/memory_settings/auto_mem.cc
index 30a040f..02e7140 100644
--- a/src/cobalt/browser/memory_settings/auto_mem.cc
+++ b/src/cobalt/browser/memory_settings/auto_mem.cc
@@ -20,6 +20,7 @@
 #include <cmath>
 #include <memory>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/optional.h"
@@ -31,7 +32,6 @@
 #include "cobalt/browser/memory_settings/auto_mem_settings.h"
 #include "cobalt/browser/memory_settings/calculations.h"
 #include "cobalt/browser/memory_settings/constants.h"
-#include "cobalt/browser/memory_settings/constrainer.h"
 #include "cobalt/browser/memory_settings/memory_settings.h"
 #include "cobalt/browser/memory_settings/pretty_print.h"
 #include "cobalt/browser/memory_settings/scaling_function.h"
@@ -230,44 +230,6 @@
          "monotonically decreasing values as input goes from 1.0 -> 0.0";
 }
 
-int64_t GenerateTargetMemoryBytes(int64_t max_memory_bytes,
-                                  int64_t current_memory_bytes,
-                                  base::Optional<int64_t> reduce_memory_bytes) {
-  // Make sure values are sanitized.
-  max_memory_bytes = std::max<int64_t>(0, max_memory_bytes);
-  current_memory_bytes = std::max<int64_t>(0, current_memory_bytes);
-
-  // If reduce_memory_bytes is valid and it's a zero or positive value then
-  // this is a signal that the calculation should be based off of this setting.
-  bool use_reduce_memory_input =
-      (reduce_memory_bytes && (-1 < *reduce_memory_bytes));
-
-  if (use_reduce_memory_input) {
-    // If reducing_memory_bytes is set exactly to 0, then this
-    // this will disable max_memory_bytes setting. current_memory_bytes
-    // will be returned as the target memory consumption,
-    // which will prevent memory constraining.
-    if (*reduce_memory_bytes == 0) {
-      return current_memory_bytes;
-    } else {
-      // Reduce memory bytes will subtract from the current memory
-      // consumption.
-      const int64_t target_value = current_memory_bytes - *reduce_memory_bytes;
-      return math::Clamp<int64_t>(target_value, 0, std::abs(target_value));
-    }
-  } else {  // reduce_memory_bytes is not used. Use max_memory_bytes instead.
-    // max_memory_bytes == 0 is special, and signals that no constraining
-    // should happen.
-    if (max_memory_bytes == 0) {
-      return current_memory_bytes;
-    } else {
-      // A non-zero value means that max_memory_bytes is valid and should
-      // be used as the target value.
-      return max_memory_bytes;
-    }
-  }
-}
-
 }  // namespace
 
 AutoMem::AutoMem(const math::Size& ui_resolution,
@@ -276,28 +238,11 @@
   TRACE_EVENT0("cobalt::browser", "AutoMem::AutoMem()");
   ConstructSettings(ui_resolution, command_line_settings, build_settings);
 
-  const int64_t target_cpu_memory = GenerateTargetMemoryBytes(
-      max_cpu_bytes_->value(), SumAllMemoryOfType(MemorySetting::kCPU),
-      base::Optional<int64_t>(0));
-  const int64_t target_gpu_memory = GenerateTargetMemoryBytes(
-      max_gpu_bytes_->value(), SumAllMemoryOfType(MemorySetting::kGPU),
-      reduced_gpu_bytes_->optional_value());
-
   std::vector<MemorySetting*> memory_settings = AllMemorySettingsMutable();
-  ConstrainToMemoryLimits(target_cpu_memory, target_gpu_memory,
-                          &memory_settings, &error_msgs_);
 }
 
 AutoMem::~AutoMem() {}
 
-const IntSetting* AutoMem::misc_cobalt_cpu_size_in_bytes() const {
-  return misc_cobalt_cpu_size_in_bytes_.get();
-}
-
-const IntSetting* AutoMem::misc_cobalt_gpu_size_in_bytes() const {
-  return misc_cobalt_gpu_size_in_bytes_.get();
-}
-
 const IntSetting* AutoMem::remote_typeface_cache_size_in_bytes() const {
   return remote_typeface_cache_size_in_bytes_.get();
 }
@@ -350,8 +295,6 @@
   // Keep these in alphabetical order.
   all_settings.push_back(encoded_image_cache_size_in_bytes_.get());
   all_settings.push_back(image_cache_size_in_bytes_.get());
-  all_settings.push_back(misc_cobalt_cpu_size_in_bytes_.get());
-  all_settings.push_back(misc_cobalt_gpu_size_in_bytes_.get());
   all_settings.push_back(offscreen_target_cache_size_in_bytes_.get());
   all_settings.push_back(remote_typeface_cache_size_in_bytes_.get());
   all_settings.push_back(skia_atlas_texture_dimensions_.get());
@@ -421,15 +364,6 @@
   max_cpu_bytes_ = CreateCpuSetting(command_line_settings, build_settings);
   max_gpu_bytes_ = CreateGpuSetting(command_line_settings, build_settings);
 
-  reduced_gpu_bytes_ = CreateSystemMemorySetting(
-      switches::kReduceGpuMemoryBy, MemorySetting::kGPU,
-      command_line_settings.reduce_gpu_memory_by,
-      build_settings.reduce_gpu_memory_by, -1);
-  if (reduced_gpu_bytes_->value() == -1) {
-    // This effectively disables the value from being used in the constrainer.
-    reduced_gpu_bytes_->set_value(MemorySetting::kUnset, 0);
-  }
-
   // Set the encoded image cache capacity
   encoded_image_cache_size_in_bytes_ = CreateMemorySetting<IntSetting, int64_t>(
       switches::kEncodedImageCacheSizeInBytes,
@@ -454,19 +388,6 @@
   image_cache_size_in_bytes_->set_memory_scaling_function(
       MakeLinearMemoryScaler(.75, 1.0));
 
-  // Set the misc cobalt size to a specific size.
-  misc_cobalt_cpu_size_in_bytes_.reset(
-      new IntSetting("misc_cobalt_cpu_size_in_bytes"));
-  misc_cobalt_cpu_size_in_bytes_->set_value(MemorySetting::kAutoSet,
-                                            kMiscCobaltCpuSizeInBytes);
-
-  // Set the misc cobalt size to a specific size.
-  misc_cobalt_gpu_size_in_bytes_.reset(
-      new IntSetting("misc_cobalt_gpu_size_in_bytes"));
-  misc_cobalt_gpu_size_in_bytes_->set_memory_type(MemorySetting::kGPU);
-  misc_cobalt_gpu_size_in_bytes_->set_value(
-      MemorySetting::kAutoSet, CalculateMiscCobaltGpuSize(ui_resolution));
-
   // Set remote_type_face_cache size.
   remote_typeface_cache_size_in_bytes_ =
       CreateMemorySetting<IntSetting, int64_t>(
diff --git a/src/cobalt/browser/memory_settings/auto_mem.h b/src/cobalt/browser/memory_settings/auto_mem.h
index fd78576..6aa2b76 100644
--- a/src/cobalt/browser/memory_settings/auto_mem.h
+++ b/src/cobalt/browser/memory_settings/auto_mem.h
@@ -44,11 +44,8 @@
 
   const IntSetting* encoded_image_cache_size_in_bytes() const;
   const IntSetting* image_cache_size_in_bytes() const;
-  const IntSetting* javascript_gc_threshold_in_bytes() const;
   // This setting represents all others cpu-memory consuming systems within
   // the engine. This value has been hard coded.
-  const IntSetting* misc_cobalt_cpu_size_in_bytes() const;
-  const IntSetting* misc_cobalt_gpu_size_in_bytes() const;
   const IntSetting* remote_typeface_cache_size_in_bytes() const;
   const DimensionSetting* skia_atlas_texture_dimensions() const;
   const IntSetting* skia_cache_size_in_bytes() const;
@@ -82,9 +79,6 @@
   // All of the following are included in AllMemorySettings().
   std::unique_ptr<IntSetting> encoded_image_cache_size_in_bytes_;
   std::unique_ptr<IntSetting> image_cache_size_in_bytes_;
-  std::unique_ptr<IntSetting> javascript_gc_threshold_in_bytes_;
-  std::unique_ptr<IntSetting> misc_cobalt_cpu_size_in_bytes_;
-  std::unique_ptr<IntSetting> misc_cobalt_gpu_size_in_bytes_;
   std::unique_ptr<IntSetting> remote_typeface_cache_size_in_bytes_;
   std::unique_ptr<DimensionSetting> skia_atlas_texture_dimensions_;
   std::unique_ptr<IntSetting> skia_cache_size_in_bytes_;
@@ -95,18 +89,12 @@
   // in AllMemorySettings().
   std::unique_ptr<IntSetting> max_cpu_bytes_;
   std::unique_ptr<IntSetting> max_gpu_bytes_;
-  std::unique_ptr<IntSetting>
-      reduced_cpu_bytes_;  // Forces CPU memory reduction.
-  std::unique_ptr<IntSetting>
-      reduced_gpu_bytes_;  // Forces GPU memory reduction.
 
   std::vector<std::string> error_msgs_;
 
   FRIEND_TEST(AutoMem, AllMemorySettingsAreOrderedByName);
   FRIEND_TEST(AutoMem, ConstrainedCPUEnvironment);
   FRIEND_TEST(AutoMem, ConstrainedGPUEnvironment);
-  FRIEND_TEST(AutoMem, ExplicitReducedCPUMemoryConsumption);
-  FRIEND_TEST(AutoMem, ExplicitReducedGPUMemoryConsumption);
   FRIEND_TEST(AutoMem, MaxCpuIsIgnoredDuringExplicitMemoryReduction);
 };
 
diff --git a/src/cobalt/browser/memory_settings/auto_mem_settings.cc b/src/cobalt/browser/memory_settings/auto_mem_settings.cc
index 98ef408..1a089e9 100644
--- a/src/cobalt/browser/memory_settings/auto_mem_settings.cc
+++ b/src/cobalt/browser/memory_settings/auto_mem_settings.cc
@@ -264,8 +264,6 @@
       switches::kOffscreenTargetCacheSizeInBytes);
   Set(command_line, &settings.max_cpu_in_bytes, switches::kMaxCobaltCpuUsage);
   Set(command_line, &settings.max_gpu_in_bytes, switches::kMaxCobaltGpuUsage);
-  Set(command_line, &settings.reduce_gpu_memory_by,
-      switches::kReduceGpuMemoryBy);
 
   return settings;
 }
diff --git a/src/cobalt/browser/memory_settings/auto_mem_settings_test.cc b/src/cobalt/browser/memory_settings/auto_mem_settings_test.cc
index 5f2a555..3c710ca 100644
--- a/src/cobalt/browser/memory_settings/auto_mem_settings_test.cc
+++ b/src/cobalt/browser/memory_settings/auto_mem_settings_test.cc
@@ -81,8 +81,6 @@
                  max_cpu_in_bytes);
   TEST_PARSE_INT(expected, value, switches::kMaxCobaltGpuUsage,
                  max_gpu_in_bytes);
-  TEST_PARSE_INT(expected, value, switches::kReduceGpuMemoryBy,
-                 reduce_gpu_memory_by);
 #undef TEST_PARSE_INT
 }
 
@@ -122,7 +120,6 @@
   EXPECT_FALSE(settings.offscreen_target_cache_size_in_bytes);
   EXPECT_FALSE(settings.max_cpu_in_bytes);
   EXPECT_FALSE(settings.max_gpu_in_bytes);
-  EXPECT_FALSE(settings.reduce_gpu_memory_by);
 
   AutoMemSettings build_settings(AutoMemSettings::kTypeBuild);
   EXPECT_EQ(AutoMemSettings::kTypeBuild, build_settings.type);
diff --git a/src/cobalt/browser/memory_settings/auto_mem_test.cc b/src/cobalt/browser/memory_settings/auto_mem_test.cc
index 0891d87..64f76d3 100644
--- a/src/cobalt/browser/memory_settings/auto_mem_test.cc
+++ b/src/cobalt/browser/memory_settings/auto_mem_test.cc
@@ -37,12 +37,6 @@
 
 const math::Size kResolution1080p(1920, 1080);
 
-// Represents what the cobalt engine can scale down to under a default
-// environment.
-const int64_t kSmallEngineCpuMemorySize = 130 * 1024 * 1024;
-
-const int64_t kSmallEngineGpuMemorySize = 68 * 1024 * 1024;
-
 #define EXPECT_MEMORY_SETTING(SETTING, SOURCE, MEMORY_TYPE, VALUE)          \
   EXPECT_EQ(VALUE, SETTING->value()) << " failure for " << SETTING->name(); \
   EXPECT_EQ(MEMORY_TYPE, SETTING->memory_type())                            \
@@ -54,13 +48,6 @@
   return AutoMemSettings(AutoMemSettings::kTypeCommandLine);
 }
 
-std::unique_ptr<AutoMem> CreateDefaultAutoMem() {
-  AutoMemSettings build_settings(AutoMemSettings::kTypeBuild);
-  std::unique_ptr<AutoMem> auto_mem(
-      new AutoMem(kResolution1080p, EmptyCommandLine(), build_settings));
-  return auto_mem;
-}
-
 }  // namespace.
 
 // Tests the expectation that the command-line overrides will be applied.
@@ -230,156 +217,6 @@
   }
 }
 
-// Tests the expectation that constraining the CPU memory to kSmallEngineSize
-// will result in AutoMem reducing to the expected memory footprint.
-TEST(AutoMem, ConstrainedCPUEnvironment) {
-  AutoMemSettings build_settings(AutoMemSettings::kTypeBuild);
-  build_settings.max_cpu_in_bytes = kSmallEngineCpuMemorySize;
-
-  AutoMem auto_mem(kResolution1080p, EmptyCommandLine(), build_settings);
-
-  const int64_t cpu_memory_consumption =
-      auto_mem.SumAllMemoryOfType(MemorySetting::kCPU);
-  EXPECT_LE(cpu_memory_consumption, kSmallEngineCpuMemorySize);
-}
-
-// Tests the expectation that constraining the GPU memory will result
-// in AutoMem reducing the the memory footprint.
-TEST(AutoMem, ConstrainedGPUEnvironment) {
-  AutoMemSettings build_settings(AutoMemSettings::kTypeBuild);
-  build_settings.max_gpu_in_bytes = 57 * 1024 * 1024;
-  AutoMem auto_mem(kResolution1080p, EmptyCommandLine(), build_settings);
-
-  std::vector<const MemorySetting*> settings = auto_mem.AllMemorySettings();
-  const int64_t gpu_memory_consumption =
-      SumMemoryConsumption(MemorySetting::kGPU, settings);
-  EXPECT_LE(gpu_memory_consumption, *build_settings.max_gpu_in_bytes);
-}
-
-// Tests the expectation that constraining the CPU memory to 40MB will result
-// in AutoMem reducing the the memory footprint.
-TEST(AutoMem, ExplicitReducedGPUMemoryConsumption) {
-  // STEP ONE: Get the "natural" size of the engine at the default test
-  // settings.
-  std::unique_ptr<AutoMem> default_auto_mem = CreateDefaultAutoMem();
-
-  AutoMemSettings command_line_settings(AutoMemSettings::kTypeCommandLine);
-  command_line_settings.reduce_gpu_memory_by = 5 * 1024 * 1024;
-  AutoMemSettings build_settings(AutoMemSettings::kTypeBuild);
-  AutoMem reduced_gpu_memory_auto_mem(kResolution1080p, command_line_settings,
-                                      build_settings);
-  EXPECT_EQ(5 * 1024 * 1024,
-            reduced_gpu_memory_auto_mem.reduced_gpu_bytes_->value());
-
-  const int64_t original_memory_consumption =
-      default_auto_mem->SumAllMemoryOfType(MemorySetting::kGPU);
-  const int64_t reduced_memory_consumption =
-      reduced_gpu_memory_auto_mem.SumAllMemoryOfType(MemorySetting::kGPU);
-
-  EXPECT_LE(5 * 1024 * 1024,
-            original_memory_consumption - reduced_memory_consumption);
-}
-
-// Tests the expectation that the constrainer will not run on cpu memory if
-// --reduce_cpu_memory_by is set to 0.
-TEST(AutoMem, MaxCpuIsIgnoredWithZeroValueReduceCPUCommand) {
-  // STEP ONE: Get the "natural" size of the engine at the default test
-  // settings.
-  std::unique_ptr<AutoMem> default_auto_mem = CreateDefaultAutoMem();
-
-  AutoMemSettings command_line_settings(AutoMemSettings::kTypeCommandLine);
-  AutoMemSettings build_settings(AutoMemSettings::kTypeBuild);
-
-  // Max memory is 1-byte. We expect that the kReduceCpuMemoryBy = "0" will
-  // override the max_cpu_in_bytes setting.
-  build_settings.max_cpu_in_bytes = 1;
-  command_line_settings.reduce_cpu_memory_by = 0;
-
-  AutoMem auto_mem_no_reduce_cpu(kResolution1080p, command_line_settings,
-                                 build_settings);
-
-  const int64_t original_memory_consumption =
-      default_auto_mem->SumAllMemoryOfType(MemorySetting::kCPU);
-  const int64_t new_memory_consumption =
-      auto_mem_no_reduce_cpu.SumAllMemoryOfType(MemorySetting::kCPU);
-
-  // Max_cpu_in_bytes specifies one byte of memory, but reduce must override
-  // this for this test to pass.
-  EXPECT_EQ(original_memory_consumption, new_memory_consumption);
-}
-
-// Tests the expectation that the constrainer will not run on gpu memory if
-// --reduce_gpu_memory_by is set to 0.
-TEST(AutoMem, MaxCpuIsIgnoredWithZeroValueReduceGPUCommand) {
-  // STEP ONE: Get the "natural" size of the engine at the default test
-  // settings.
-  std::unique_ptr<AutoMem> default_auto_mem = CreateDefaultAutoMem();
-
-  AutoMemSettings command_line_settings(AutoMemSettings::kTypeCommandLine);
-  AutoMemSettings build_settings(AutoMemSettings::kTypeBuild);
-
-  // Max memory is 1-byte. We expect that the kReduceCpuMemoryBy = "0" will
-  // override the max_cpu_in_bytes setting.
-  build_settings.max_gpu_in_bytes = 1;
-  command_line_settings.reduce_gpu_memory_by = 0;
-
-  AutoMem auto_mem_no_reduce_cpu(kResolution1080p, command_line_settings,
-                                 build_settings);
-
-  const int64_t original_memory_consumption =
-      default_auto_mem->SumAllMemoryOfType(MemorySetting::kGPU);
-  const int64_t new_memory_consumption =
-      auto_mem_no_reduce_cpu.SumAllMemoryOfType(MemorySetting::kGPU);
-
-  // Max_gpu_in_bytes specifies one byte of memory, but reduce must override
-  // this for this test to pass.
-  EXPECT_EQ(original_memory_consumption, new_memory_consumption);
-}
-
-// Tests the expectation that if --reduce_cpu_memory_by is set to -1 that it
-// will be effectively disabled and --max_cpu_bytes be used as the memory
-// reduction means.
-TEST(AutoMem, MaxCpuIsEnabledWhenReduceCpuMemoryIsExplicitlyDisabled) {
-  AutoMemSettings command_line_settings(AutoMemSettings::kTypeCommandLine);
-  AutoMemSettings build_settings(AutoMemSettings::kTypeBuild);
-
-  // Max memory is 1-byte. We expect that the kReduceCpuMemoryBy = "-1"
-  // passed to the command line will cause max_cpu_in_bytes to be the
-  // dominating memory reduction mechanism.
-  build_settings.max_cpu_in_bytes = kSmallEngineGpuMemorySize;
-  command_line_settings.reduce_cpu_memory_by = -1;
-
-  AutoMem auto_mem_no_reduce_cpu(kResolution1080p, command_line_settings,
-                                 build_settings);
-  const int64_t memory_consumption =
-      auto_mem_no_reduce_cpu.SumAllMemoryOfType(MemorySetting::kCPU);
-  // Max_cpu_in_bytes specifies one byte of memory, but reduce must override
-  // this for this test to pass.
-  EXPECT_LE(memory_consumption, kSmallEngineCpuMemorySize);
-}
-
-// Tests the expectation that if --reduce_gpu_memory_by is set to -1 that it
-// will be effectively disabled and --max_gpu_bytes be used as the memory
-// reduction means.
-TEST(AutoMem, MaxGpuIsEnabledWhenReduceCpuMemoryIsExplicitlyDisabled) {
-  AutoMemSettings command_line_settings(AutoMemSettings::kTypeCommandLine);
-  AutoMemSettings build_settings(AutoMemSettings::kTypeBuild);
-
-  // Max memory is 1-byte. We expect that the kReduceCpuMemoryBy = "-1"
-  // passed to the command line will cause max_cpu_in_bytes to be the
-  // dominating memory reduction mechanism.
-  build_settings.max_gpu_in_bytes = kSmallEngineGpuMemorySize;
-  command_line_settings.reduce_gpu_memory_by = -1;
-
-  AutoMem auto_mem_no_reduce_cpu(kResolution1080p, command_line_settings,
-                                 build_settings);
-  const int64_t memory_consumption =
-      auto_mem_no_reduce_cpu.SumAllMemoryOfType(MemorySetting::kGPU);
-  // Max_cpu_in_bytes specifies one byte of memory, but reduce must override
-  // this for this test to pass.
-  EXPECT_LE(memory_consumption, kSmallEngineGpuMemorySize);
-}
-
 // Tests that if the gpu memory could not be queried then the resulting
 // max_gpu_bytes will not be valid.
 TEST(AutoMem, NoDefaultGpuMemory) {
diff --git a/src/cobalt/browser/memory_settings/calculations.cc b/src/cobalt/browser/memory_settings/calculations.cc
index 7b5a35f..0bf7d5c 100644
--- a/src/cobalt/browser/memory_settings/calculations.cc
+++ b/src/cobalt/browser/memory_settings/calculations.cc
@@ -182,16 +182,6 @@
   return std::max<int64_t>(output, kMinSkiaCacheSize);
 }
 
-int64_t CalculateMiscCobaltGpuSize(const math::Size& ui_resolution) {
-  // LinearRemap defines a mapping function which will map the number
-  // of ui_resolution pixels to the misc memory of the GPU. This mapping
-  // is linear such that:
-  // 1080p (1920x1080) => maps to => 24MB
-  LinearRemap remap(0, 1920 * 1080, 0, 24 * 1024 * 1024);
-
-  return static_cast<int64_t>(remap.Map(ui_resolution.GetArea()));
-}
-
 }  // namespace memory_settings
 }  // namespace browser
 }  // namespace cobalt
diff --git a/src/cobalt/browser/memory_settings/calculations.h b/src/cobalt/browser/memory_settings/calculations.h
index d034fa1..0f4b035 100644
--- a/src/cobalt/browser/memory_settings/calculations.h
+++ b/src/cobalt/browser/memory_settings/calculations.h
@@ -63,10 +63,6 @@
 // to be 4MB @ 1080p and scales accordingly.
 int64_t CalculateSkiaCacheSize(const math::Size& ui_resolution);
 
-// Calculates the GPU usage of the app to un-accounted systems. Scales linearly
-// with ui_resolution.
-int64_t CalculateMiscCobaltGpuSize(const math::Size& ui_resolution);
-
 }  // namespace memory_settings
 }  // namespace browser
 }  // namespace cobalt
diff --git a/src/cobalt/browser/memory_settings/calculations_test.cc b/src/cobalt/browser/memory_settings/calculations_test.cc
index c19359a..53e67a2 100644
--- a/src/cobalt/browser/memory_settings/calculations_test.cc
+++ b/src/cobalt/browser/memory_settings/calculations_test.cc
@@ -177,11 +177,6 @@
             CalculateSoftwareSurfaceCacheSizeInBytes(ui_resolution));
 }
 
-TEST(MemoryCalculations, CalculateMiscCobaltGpuSize) {
-  math::Size ui_resolution = GetDimensions(k1080p);
-  EXPECT_EQ(24 * 1024 * 1024, CalculateMiscCobaltGpuSize(ui_resolution));
-}
-
 }  // namespace memory_settings
 }  // namespace browser
 }  // namespace cobalt
diff --git a/src/cobalt/browser/memory_settings/constrainer.cc b/src/cobalt/browser/memory_settings/constrainer.cc
deleted file mode 100644
index 5be827e..0000000
--- a/src/cobalt/browser/memory_settings/constrainer.cc
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright 2017 The Cobalt Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "cobalt/browser/memory_settings/constrainer.h"
-
-#include <algorithm>
-#include <iterator>
-#include <vector>
-
-#include "base/logging.h"
-#include "cobalt/browser/memory_settings/memory_settings.h"
-#include "cobalt/browser/memory_settings/pretty_print.h"
-#include "starboard/configuration.h"
-
-namespace cobalt {
-namespace browser {
-namespace memory_settings {
-namespace {
-
-// Any memory setting that matches the MemoryType and is an AutoSet type is
-// passed to the output.
-std::vector<MemorySetting*> FilterSettings(
-    MemorySetting::MemoryType memory_type,
-    const std::vector<MemorySetting*>& settings) {
-  std::vector<MemorySetting*> output;
-  for (size_t i = 0; i < settings.size(); ++i) {
-    MemorySetting* setting = settings[i];
-    if (setting->memory_type() == memory_type) {
-      output.push_back(setting);
-    }
-  }
-  return output;
-}
-
-// Sums the memory consumption at the given global_constraining_value. The
-// settings variable is read buy not modified (despite the non-const
-// declaration). If constrained_values_out is non-null, then the computed
-// constraining values are stored in this vector.
-// Returns: The amount of memory in bytes that the memory settings vector will
-//          consume at the given global_constraining_factor.
-int64_t SumMemoryConsumption(double global_constraining_factor,
-                             const std::vector<MemorySetting*>& memory_settings,
-                             std::vector<double>* constrained_values_out) {
-  if (constrained_values_out) {
-    constrained_values_out->clear();
-  }
-
-  int64_t sum = 0;
-
-  // Iterates through the MemorySettings and determines the total memory
-  // consumption at the current global_constraining_value.
-  for (size_t i = 0; i < memory_settings.size(); ++i) {
-    const MemorySetting* setting = memory_settings[i];
-
-    const int64_t requested_consumption = setting->MemoryConsumption();
-    double local_constraining_value = 1.0;
-    if (setting->source_type() == MemorySetting::kAutoSet) {
-      local_constraining_value =
-          setting->ComputeAbsoluteMemoryScale(global_constraining_factor);
-    }
-
-    const int64_t new_consumption_value =
-        static_cast<int64_t>(local_constraining_value * requested_consumption);
-
-    if (constrained_values_out) {
-      constrained_values_out->push_back(local_constraining_value);
-    }
-
-    sum += new_consumption_value;
-  }
-
-  return sum;
-}
-
-void CheckMemoryChange(const std::string& setting_name,
-                       int64_t old_memory_consumption,
-                       int64_t new_memory_consumption,
-                       double constraining_value) {
-  if (old_memory_consumption == 0) {
-    // If the system is already using no memory, then it can't use any less.
-    return;
-  }
-
-  // Represents 1% allowed difference.
-  static const double kErrorThreshold = 0.01;
-
-  const double actual_constraining_value =
-      static_cast<double>(new_memory_consumption) /
-      static_cast<double>(old_memory_consumption);
-
-  double diff = constraining_value - actual_constraining_value;
-  if (diff < 0.0) {
-    diff = -diff;
-  }
-
-  DCHECK_LE(diff, kErrorThreshold)
-      << "MemorySetting " << setting_name << " did not change it's memory by "
-      << "the expected value.\n"
-      << "  Expected Change: " << (constraining_value * 100) << "%\n"
-      << "  Actual Change: " << (diff * 100) << "%\n"
-      << "  Original memory consumption (bytes): " << old_memory_consumption
-      << "  New memory consumption (bytes):      " << new_memory_consumption
-      << "\n";
-}
-
-void ConstrainToMemoryLimit(int64_t memory_limit,
-                            std::vector<MemorySetting*>* memory_settings) {
-  if (memory_settings->empty()) {
-    return;
-  }
-
-  // If the memory consumed is already under the memory limit then no further
-  // work needs to be done.
-  if (SumMemoryConsumption(1.0, *memory_settings, NULL) <= memory_limit) {
-    return;
-  }
-
-  // Iterate by small steps the constraining value from 1.0 (100%) toward
-  // 0.0.
-  static const double kStep = 0.0001;  // .01% change per iteration.
-  std::vector<double> constrained_sizes;
-  // 1-1 mapping.
-  constrained_sizes.resize(memory_settings->size());
-  for (double global_constraining_factor = 1.0;
-       global_constraining_factor >= 0.0; global_constraining_factor -= kStep) {
-    global_constraining_factor = std::max(0.0, global_constraining_factor);
-    const int64_t new_global_memory_consumption = SumMemoryConsumption(
-        global_constraining_factor, *memory_settings, &constrained_sizes);
-
-    const bool finished = (global_constraining_factor == 0.0) ||
-                          (new_global_memory_consumption <= memory_limit);
-
-    if (finished) {
-      break;
-    }
-  }
-  DCHECK_EQ(memory_settings->size(), constrained_sizes.size());
-  for (size_t i = 0; i < memory_settings->size(); ++i) {
-    const double local_constraining_factor = constrained_sizes[i];
-    MemorySetting* setting = memory_settings->at(i);
-    if (local_constraining_factor != 1.0) {
-      const int64_t old_memory_consumption = setting->MemoryConsumption();
-      DCHECK_EQ(setting->source_type(), MemorySetting::kAutoSet);
-      setting->ScaleMemory(local_constraining_factor);
-      const int64_t new_memory_consumption = setting->MemoryConsumption();
-
-      // If the memory doesn't actually change as predicted by the constraining
-      // value then this check will catch it here.
-      CheckMemoryChange(setting->name(), old_memory_consumption,
-                        new_memory_consumption, local_constraining_factor);
-    }
-  }
-}
-
-void ConstrainMemoryType(MemorySetting::MemoryType memory_type,
-                         int64_t max_memory,
-                         std::vector<MemorySetting*>* memory_settings,
-                         std::vector<std::string>* error_msgs) {
-  if (max_memory == 0) {
-    return;
-  }
-  DCHECK_NE(MemorySetting::kNotApplicable, memory_type);
-  const char* memory_type_str = "UNKNOWN";
-  switch (memory_type) {
-    case MemorySetting::kCPU: {
-      memory_type_str = "CPU";
-      break;
-    }
-    case MemorySetting::kGPU: {
-      memory_type_str = "GPU";
-      break;
-    }
-    case MemorySetting::kNotApplicable: {
-      memory_type_str = "ERROR";
-      break;
-    }
-  }
-
-  std::vector<MemorySetting*> filtered_settings =
-      FilterSettings(memory_type, *memory_settings);
-
-  const int64_t current_consumption =
-      SumMemoryConsumption(memory_type, *memory_settings);
-
-  if (current_consumption < max_memory) {
-    return;
-  }
-
-  ConstrainToMemoryLimit(max_memory, &filtered_settings);
-
-  const int64_t new_memory_size =
-      SumMemoryConsumption(memory_type, *memory_settings);
-
-  if (new_memory_size > max_memory) {
-    std::stringstream ss;
-    ss << "WARNING - ATTEMPTED TO CONSTRAIN " << memory_type_str
-       << " MEMORY FROM " << ToMegabyteString(current_consumption, 2) << " TO "
-       << ToMegabyteString(max_memory, 2) << ".\nBUT STOPPED"
-       << " AT " << ToMegabyteString(new_memory_size, 2) << " because"
-       << " there was nothing left to\n"
-       << "constrain (settings refused to reduce any more memory). Try\n"
-       << "setting more memory setting(s) to -1 to allow autoset.\n"
-       << "Example: --image_cache_size_in_bytes=-1";
-    error_msgs->push_back(ss.str());
-  }
-}
-
-}  // namespace.
-
-void ConstrainToMemoryLimits(int64_t max_cpu_memory, int64_t max_gpu_memory,
-                             std::vector<MemorySetting*>* memory_settings,
-                             std::vector<std::string>* error_msgs) {
-  // Constrain cpu memory.
-  ConstrainMemoryType(MemorySetting::kCPU, max_cpu_memory, memory_settings,
-                      error_msgs);
-  // Constrain gpu memory.
-  ConstrainMemoryType(MemorySetting::kGPU, max_gpu_memory, memory_settings,
-                      error_msgs);
-}
-
-}  // namespace memory_settings
-}  // namespace browser
-}  // namespace cobalt
diff --git a/src/cobalt/browser/memory_settings/constrainer.h b/src/cobalt/browser/memory_settings/constrainer.h
deleted file mode 100644
index 97d4e04..0000000
--- a/src/cobalt/browser/memory_settings/constrainer.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2017 The Cobalt Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef COBALT_BROWSER_MEMORY_SETTINGS_CONSTRAINER_H_
-#define COBALT_BROWSER_MEMORY_SETTINGS_CONSTRAINER_H_
-
-#include <string>
-#include <vector>
-
-#include "base/optional.h"
-#include "cobalt/browser/memory_settings/memory_settings.h"
-#include "starboard/types.h"
-
-namespace cobalt {
-namespace browser {
-namespace memory_settings {
-
-// Constrains the memory in the memory_settings vector so that the target is
-// such that the sum of memory consumption is below max_cpu_memory and
-// max_gpu_memory.
-//
-// How the memory settings will reduce their memory usage is dependent on
-// the ConstrainerFunction they contain. It's possible that the memory
-// settings won't be able to match the target memory.
-//
-// The output variable error_msgs will be populated with any error messages
-// that result from this function call.
-void ConstrainToMemoryLimits(int64_t max_cpu_memory, int64_t max_gpu_memory,
-                             std::vector<MemorySetting*>* memory_settings,
-                             std::vector<std::string>* error_msgs);
-}  // namespace memory_settings
-}  // namespace browser
-}  // namespace cobalt
-
-#endif  // COBALT_BROWSER_MEMORY_SETTINGS_CONSTRAINER_H_
diff --git a/src/cobalt/browser/memory_settings/constrainer_test.cc b/src/cobalt/browser/memory_settings/constrainer_test.cc
deleted file mode 100644
index 1047d10..0000000
--- a/src/cobalt/browser/memory_settings/constrainer_test.cc
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright 2017 The Cobalt Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "cobalt/browser/memory_settings/constrainer.h"
-#include "base/bind.h"
-#include "base/callback.h"
-#include "cobalt/browser/memory_settings/memory_settings.h"
-#include "cobalt/browser/memory_settings/test_common.h"
-#include "starboard/configuration.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace cobalt {
-namespace browser {
-namespace memory_settings {
-namespace {
-const int64_t kOneMegabyte = 1 * 1024 * 1024;
-const int64_t kTwoMegabytes = 2 * 1024 * 1024;
-const int64_t kFiveMegabytes = 5 * 1024 * 1024;
-const int64_t kNoGpuMemory = 0;
-
-ScalingFunction MakeLinearConstrainer() {
-  // Linearly scale, but clamp between 0 and 1.
-  return MakeLinearMemoryScaler(0.0, 1.0);
-}
-
-}  // namespace.
-
-// Tests the expectation that given one IntSetting which occupies 2MB of
-// the available memory, and max_cpu_setting of 1MB, that
-// ConstrainToMemoryLimits() function will reduce the memory setting
-// down 1MB.
-TEST(ConstrainToMemoryLimits, ConstrainCpuMemoryWithOneSetting) {
-  IntSetting int_setting("dummy_cpu_setting");
-  int_setting.set_memory_type(MemorySetting::kCPU);
-  int_setting.set_value(MemorySetting::kAutoSet, kTwoMegabytes);
-
-  ScalingFunction constrainer(MakeLinearConstrainer());
-
-  int_setting.set_memory_scaling_function(constrainer);
-
-  std::vector<MemorySetting*> settings;
-  settings.push_back(&int_setting);
-
-  std::vector<std::string> error_msgs;
-
-  // Will reduce the memory usage of the IntSetting.
-  ConstrainToMemoryLimits(kOneMegabyte, kNoGpuMemory, &settings, &error_msgs);
-  EXPECT_EQ(kOneMegabyte, int_setting.MemoryConsumption());
-  EXPECT_TRUE(error_msgs.empty());
-}
-
-// Tests the expectation that given two IntSettings, one that was AutoSet and
-// one that was set by the command line and one set by the build system, that
-// only the AutoSet IntSetting will be constrained.
-TEST(ConstrainToMemoryLimits, ConstrainerIgnoresNonAutosetVariables) {
-  IntSetting int_setting_autoset("autoset_cpu_setting");
-  int_setting_autoset.set_memory_type(MemorySetting::kCPU);
-  int_setting_autoset.set_value(MemorySetting::kAutoSet, kTwoMegabytes);
-  int_setting_autoset.set_memory_scaling_function(MakeLinearConstrainer());
-
-  IntSetting int_setting_cmdline("cmdline_cpu_setting");
-  int_setting_cmdline.set_memory_type(MemorySetting::kCPU);
-  int_setting_cmdline.set_value(MemorySetting::kCmdLine, kTwoMegabytes);
-  int_setting_cmdline.set_memory_scaling_function(MakeLinearConstrainer());
-
-  IntSetting int_setting_builtin("builtin_cpu_setting");
-  int_setting_builtin.set_memory_type(MemorySetting::kCPU);
-  int_setting_builtin.set_value(MemorySetting::kBuildSetting, kTwoMegabytes);
-  int_setting_builtin.set_memory_scaling_function(MakeLinearConstrainer());
-
-  std::vector<MemorySetting*> settings;
-  settings.push_back(&int_setting_autoset);
-  settings.push_back(&int_setting_cmdline);
-  settings.push_back(&int_setting_builtin);
-
-  std::vector<std::string> error_msgs;
-
-  // Right now we need to shave off 1MB, but this can only come from the
-  // MemorySetting that was autoset.
-  ConstrainToMemoryLimits(kFiveMegabytes, kNoGpuMemory, &settings, &error_msgs);
-
-  EXPECT_EQ(kOneMegabyte, int_setting_autoset.MemoryConsumption());
-  EXPECT_EQ(kTwoMegabytes, int_setting_cmdline.MemoryConsumption());
-  EXPECT_EQ(kTwoMegabytes, int_setting_builtin.MemoryConsumption());
-
-  EXPECT_TRUE(error_msgs.empty());
-}
-
-}  // namespace memory_settings
-}  // namespace browser
-}  // namespace cobalt
diff --git a/src/cobalt/browser/memory_settings/pretty_print.h b/src/cobalt/browser/memory_settings/pretty_print.h
index 868330c..bf049c3 100644
--- a/src/cobalt/browser/memory_settings/pretty_print.h
+++ b/src/cobalt/browser/memory_settings/pretty_print.h
@@ -28,27 +28,17 @@
 namespace memory_settings {
 
 // Generates a table, ie:
-//
-//   NAME                                   VALUE                   TYPE   SOURCE
-//   _______________________________________________________________________________
-//  |                                      |             |         |      |         |
-//  | image_cache_size_in_bytes            |    33554432 | 32.0 MB |  GPU | AutoSet |
-//  |______________________________________|_____________|_________|______|_________|
-//  |                                      |             |         |      |         |
-//  | javascript_gc_threshold_in_bytes     |     8388608 |  8.0 MB |  CPU |   Build |
-//  |______________________________________|_____________|_________|______|_________|
-//  |                                      |             |         |      |         |
-//  | misc_cobalt_engine_size_in_bytes     |    33554432 | 32.0 MB |  CPU |   Build |
-//  |______________________________________|_____________|_________|______|_________|
-//  |                                      |             |         |      |         |
-//  | skia_atlas_texture_dimensions        | 4096x8192x2 | 64.0 MB |  GPU |   Build |
-//  |______________________________________|_____________|_________|______|_________|
-//  |                                      |             |         |      |         |
-//  | skia_cache_size_in_bytes             |     4194304 |  4.0 MB |  GPU |   Build |
-//  |______________________________________|_____________|_________|______|_________|
-//  |                                      |             |         |      |         |
-//  | software_surface_cache_size_in_bytes |         N/A |     N/A |  N/A |     N/A |
-//  |______________________________________|_____________|_________|______|_________|
+//  _______________________________________________________________________________
+// |SETTING NAME                          |VALUE        |         |TYPE  |SOURCE   |
+// | encoded_image_cache_size_in_bytes    |     1048576 |  1.0 MB |  CPU |   Build |
+// | image_cache_size_in_bytes            |    10485760 | 10.0 MB |  GPU | AutoSet |
+// | offscreen_target_cache_size_in_bytes |     2097152 |  2.0 MB |  GPU | AutoSet |
+// | remote_typeface_cache_size_in_bytes  |     4194304 |  4.0 MB |  CPU |   Build |
+// | skia_atlas_texture_dimensions        | 2048x2048x2 |  8.0 MB |  GPU | AutoSet |
+// | skia_cache_size_in_bytes             |     4194304 |  4.0 MB |  GPU |   Build |
+// | software_surface_cache_size_in_bytes |         N/A |     N/A |  N/A |     N/A |
+// |______________________________________|_____________|_________|______|_________|
+
 std::string GeneratePrettyPrintTable(
     bool use_color_ascii,
     const std::vector<const MemorySetting*>& memory_settings);
diff --git a/src/cobalt/browser/switches.cc b/src/cobalt/browser/switches.cc
index 439de72..4241402 100644
--- a/src/cobalt/browser/switches.cc
+++ b/src/cobalt/browser/switches.cc
@@ -337,11 +337,6 @@
     " and the number of locations can be overwritten by specifying it as the "
     " value of the command line parameter, like '--qr_code_overlay=6'.";
 
-const char kReduceGpuMemoryBy[] = "reduce_gpu_memory_by";
-const char kReduceGpuMemoryByHelp[] =
-    "Reduces the gpu-memory of the system by this amount. This causes AutoMem "
-    "to reduce the runtime size of the GPU-Memory caches.";
-
 const char kRemoteTypefaceCacheSizeInBytes[] =
     "remote_typeface_cache_size_in_bytes";
 const char kRemoteTypefaceCacheSizeInBytesHelp[] =
@@ -488,7 +483,6 @@
         {kOmitDeviceAuthenticationQueryParameters,
          kOmitDeviceAuthenticationQueryParametersHelp},
         {kProxy, kProxyHelp}, {kQrCodeOverlay, kQrCodeOverlayHelp},
-        {kReduceGpuMemoryBy, kReduceGpuMemoryByHelp},
         {kRemoteTypefaceCacheSizeInBytes, kRemoteTypefaceCacheSizeInBytesHelp},
         {kRetainRemoteTypefaceCacheDuringSuspend,
          kRetainRemoteTypefaceCacheDuringSuspendHelp},
diff --git a/src/cobalt/browser/switches.h b/src/cobalt/browser/switches.h
index 0a95017..d07aa1e 100644
--- a/src/cobalt/browser/switches.h
+++ b/src/cobalt/browser/switches.h
@@ -133,8 +133,6 @@
 extern const char kProxyHelp[];
 extern const char kQrCodeOverlay[];
 extern const char kQrCodeOverlayHelp[];
-extern const char kReduceGpuMemoryBy[];
-extern const char kReduceGpuMemoryByHelp[];
 extern const char kRemoteTypefaceCacheSizeInBytes[];
 extern const char kRemoteTypefaceCacheSizeInBytesHelp[];
 extern const char kRetainRemoteTypefaceCacheDuringSuspend[];
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index ce625a1..52c4c5d 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-304997
\ No newline at end of file
+305559
\ No newline at end of file
diff --git a/src/cobalt/configuration/configuration.h b/src/cobalt/configuration/configuration.h
index 6913ea1..0acaec1 100644
--- a/src/cobalt/configuration/configuration.h
+++ b/src/cobalt/configuration/configuration.h
@@ -53,7 +53,6 @@
   float CobaltImageCacheCapacityMultiplierWhenPlayingVideo();
   int CobaltSkiaGlyphAtlasWidth();
   int CobaltSkiaGlyphAtlasHeight();
-  int CobaltJsGarbageCollectionThresholdInBytes();
   int CobaltReduceCpuMemoryBy();
   int CobaltReduceGpuMemoryBy();
   bool CobaltGcZeal();
diff --git a/src/cobalt/doc/memory_tuning.md b/src/cobalt/doc/memory_tuning.md
index da5f972..8f65ee8 100644
--- a/src/cobalt/doc/memory_tuning.md
+++ b/src/cobalt/doc/memory_tuning.md
@@ -7,12 +7,6 @@
 the memory allocations that will be assigned to the various subsystems in
 cobalt.
 
-As an example, at the cost of performance you can reduce CPU memory on your
-platform by 5MB and GPU memory usage on your platform by 10MB using these
-command line flags:
-
-`cobalt --reduce_cpu_memory_by=5MB --reduce_gpu_memory_by=10MB`
-
 Some settings will be "fixed" while others will be "flexible" so that their
 memory consumption will scale down for memory constrained platforms.
 
@@ -20,8 +14,7 @@
 
 **IMPORTANT**
 *Setting `--max_cobalt_cpu_usage` and `--max_cobalt_gpu_usage` on the
-command line is a beta feature. When reducing memory, please use
-`--reduce_cpu_memory_by` and `--reduce_gpu_memory_by`.*
+command line is a beta feature.*
 
 ### Memory Settings Table ###
 
@@ -29,33 +22,16 @@
 
 ~~~
 AutoMem:
-
- SETTING NAME                           VALUE                    TYPE   SOURCE
- ________________________________________________________________________________
-|                                      |             |          |      |         |
-| image_cache_size_in_bytes            |    33554432 |  32.0 MB |  GPU | AutoSet |
-|______________________________________|_____________|__________|______|_________|
-|                                      |             |          |      |         |
-| javascript_gc_threshold_in_bytes     |     8388608 |   8.0 MB |  CPU |   Build |
-|______________________________________|_____________|__________|______|_________|
-|                                      |             |          |      |         |
-| misc_cobalt_cpu_size_in_bytes        |   124780544 | 119.0 MB |  CPU | AutoSet |
-|______________________________________|_____________|__________|______|_________|
-|                                      |             |          |      |         |
-| misc_cobalt_gpu_size_in_bytes        |    25165824 |  24.0 MB |  GPU | AutoSet |
-|______________________________________|_____________|__________|______|_________|
-|                                      |             |          |      |         |
-| remote_typeface_cache_size_in_bytes  |     4194304 |   4.0 MB |  CPU |   Build |
-|______________________________________|_____________|__________|______|_________|
-|                                      |             |          |      |         |
-| skia_atlas_texture_dimensions        | 4096x8192x2 |  64.0 MB |  GPU |   Build |
-|______________________________________|_____________|__________|______|_________|
-|                                      |             |          |      |         |
-| skia_cache_size_in_bytes             |     4194304 |   4.0 MB |  GPU |   Build |
-|______________________________________|_____________|__________|______|_________|
-|                                      |             |          |      |         |
-| software_surface_cache_size_in_bytes |         N/A |      N/A |  N/A |     N/A |
-|______________________________________|_____________|__________|______|_________|
+ _______________________________________________________________________________
+|SETTING NAME                          |VALUE        |         |TYPE  |SOURCE   |
+| encoded_image_cache_size_in_bytes    |     1048576 |  1.0 MB |  CPU |   Build |
+| image_cache_size_in_bytes            |    10485760 | 10.0 MB |  GPU | AutoSet |
+| offscreen_target_cache_size_in_bytes |     2097152 |  2.0 MB |  GPU | AutoSet |
+| remote_typeface_cache_size_in_bytes  |     4194304 |  4.0 MB |  CPU |   Build |
+| skia_atlas_texture_dimensions        | 2048x2048x2 |  8.0 MB |  GPU | AutoSet |
+| skia_cache_size_in_bytes             |     4194304 |  4.0 MB |  GPU |   Build |
+| software_surface_cache_size_in_bytes |         N/A |     N/A |  N/A |     N/A |
+|______________________________________|_____________|_________|______|_________|
 
 ~~~
 This table shows the breakdown of how much memory is being allocated to each
@@ -101,8 +77,6 @@
     * `AutoSet (Constrained)`
       * This value was AutoSet to a default value, but then was reduced in
       response to `max_cobalt_cpu_usage` or `max_cobalt_gpu_usage being` set too low.
-      This will also trigger in response to `reduce_cpu_memory_by` or
-      `reduce_cpu_memory_by` being set. See "Memory Scaling" section below.
 
 ### Maximum Memory Table ###
 
@@ -183,18 +157,6 @@
 **TOTAL** value. The memory settings will be scaled down until their consumption is
 less than or equal the maximum allowed value **TOTAL**. See also **SETTINGS CONSUME**.
 
-Another way to scale down the memory size is by passing the flags
-`--reduce_cpu_memory_by=XX` and `--reduce_gpu_memory_by=XX` which will:
-1) Ignore the `--max_cobalt_cpu_usage` and `--max_cobalt_gpu_usage`.
-2) Use the current memory consumption of the settings and then reduce that by
-   the amount.
-
-For example, if cobalt uses 160MB of CPU memory then passing in
-`--reduce_cpu_memory_by=10MB` to the command line will attempt to reduce the
-footprint of cobalt by 10MB to 150MB. Note that this reduction is an an attempt,
-and it's possible this attempt will fail if the memory reduction is too aggressive
-or if memory settings have been explicitly set via the build or command line.
-
 *Forcing a Memory Setting to be flexible*
 
 If a memory setting is set via a build setting, then it's possible to make it
@@ -265,16 +227,6 @@
     * Note that `SbSystemGetTotalGPUMemory()` is optional. If no value exists
       for `max_cobalt_gpu_usage` in build/commandline/starboard settings then no
       GPU memory checking is performed.
-  * `reduce_cpu_memory_by`
-    * This setting will trigger CPU memory consumption to be reduced by the amount
-      specified. *This overrides the memory scaling behavior of `max_cobalt_cpu_usage`*.
-      But this will not affect memory checking of `max_cobalt_cpu_usage` otherwise.
-    * Set via command line or else the platform gyp build file.
-  * `reduce_cpu_memory_by`
-    * This setting will trigger GPU memory consumption to be reduced by the amount
-      specified. *This overrides the memory scaling behavior of `max_cobalt_gpu_usage`*.
-      But this will not affect memory checking of `max_cobalt_gpu_usage` otherwise.
-    * Set via command line or else the platform gyp build file.
 
 #### Memory Setting API ####
 
@@ -282,10 +234,6 @@
     * See documentation *Image cache capacity* in `performance_tuning.md` for what
       this setting does.
     * Set via command line, or else build system, or else automatically by Cobalt.
-  * `javascript_gc_threshold_in_bytes`
-    * See documentation *Garbage collection trigger threshold* in `performance_tuning.md`
-      for what this setting does.
-    * Set via command line, or else build system, or else automatically by Cobalt.
   * `remote_typeface_cache_size_in_bytes`
     * Determines the capacity of the remote typefaces cache which manages all typefaces
       downloaded from a web page.
diff --git a/src/cobalt/dom/event_target.h b/src/cobalt/dom/event_target.h
index 66b4a3f..7aca7e7 100644
--- a/src/cobalt/dom/event_target.h
+++ b/src/cobalt/dom/event_target.h
@@ -400,6 +400,20 @@
     SetAttributeEventListener(base::Tokens::beforeunload(), event_listener);
   }
 
+  const EventListenerScriptValue* onoffline() {
+    return GetAttributeEventListener(base::Tokens::offline());
+  }
+  void set_onoffline(const EventListenerScriptValue& event_listener) {
+    SetAttributeEventListener(base::Tokens::offline(), event_listener);
+  }
+
+  const EventListenerScriptValue* ononline() {
+    return GetAttributeEventListener(base::Tokens::online());
+  }
+  void set_ononline(const EventListenerScriptValue& event_listener) {
+    SetAttributeEventListener(base::Tokens::online(), event_listener);
+  }
+
   const EventListenerScriptValue* ontransitionend() {
     return GetAttributeEventListener(base::Tokens::transitionend());
   }
diff --git a/src/cobalt/dom/performance.cc b/src/cobalt/dom/performance.cc
index 390fc55..d1298ce 100644
--- a/src/cobalt/dom/performance.cc
+++ b/src/cobalt/dom/performance.cc
@@ -16,8 +16,8 @@
 
 #include <string>
 
-#include "base/time/time.h"
 #include "base/time/default_clock.h"
+#include "base/time/time.h"
 #include "cobalt/browser/stack_size_constants.h"
 #include "cobalt/dom/dom_exception.h"
 #include "cobalt/dom/memory_info.h"
@@ -67,14 +67,16 @@
   return 0.0;
 }
 
-}  //namespace
+}  // namespace
 
 Performance::Performance(script::EnvironmentSettings* settings,
                          const scoped_refptr<base::BasicClock>& clock)
     : EventTarget(settings),
       time_origin_(base::TimeTicks::Now()),
       tick_clock_(base::DefaultTickClock::GetInstance()),
-      timing_(new PerformanceTiming(clock, time_origin_)),
+      timing_(new PerformanceTiming(
+          clock,
+          (time_origin_ - base::TimeTicks::UnixEpoch()).InMilliseconds())),
       memory_(new MemoryInfo()),
       resource_timing_buffer_size_limit_(
           Performance::kMaxResourceTimingBufferSize),
@@ -83,8 +85,8 @@
       resource_timing_secondary_buffer_current_size_(0),
       performance_observer_task_queued_flag_(false),
       add_to_performance_entry_buffer_flag_(false) {
-  unix_at_zero_monotonic_ = GetUnixAtZeroMonotonic(
-      base::DefaultClock::GetInstance(), tick_clock_);
+  unix_at_zero_monotonic_ =
+      GetUnixAtZeroMonotonic(base::DefaultClock::GetInstance(), tick_clock_);
   lifecycle_timing_ = base::MakeRefCounted<PerformanceLifecycleTiming>(
       "lifecycle timing", time_origin());
   // Queue lifecycle timing.
@@ -95,15 +97,15 @@
 
 // static
 DOMHighResTimeStamp Performance::MonotonicTimeToDOMHighResTimeStamp(
-      base::TimeTicks time_origin,
-      base::TimeTicks monotonic_time) {
-  if (monotonic_time.is_null() || time_origin.is_null())
-    return 0.0;
+    base::TimeTicks time_origin, base::TimeTicks monotonic_time) {
+  if (monotonic_time.is_null() || time_origin.is_null()) return 0.0;
   DOMHighResTimeStamp clamped_time =
-      ClampTimeStampMinimumResolution(monotonic_time,
-      Performance::kPerformanceTimerMinResolutionInMicroseconds) -
-      ClampTimeStampMinimumResolution(time_origin,
-      Performance::kPerformanceTimerMinResolutionInMicroseconds);
+      ClampTimeStampMinimumResolution(
+          monotonic_time,
+          Performance::kPerformanceTimerMinResolutionInMicroseconds) -
+      ClampTimeStampMinimumResolution(
+          time_origin,
+          Performance::kPerformanceTimerMinResolutionInMicroseconds);
 
   return clamped_time;
 }
@@ -140,8 +142,7 @@
 
   // Return the sum of t1 and t2.
   return ClampTimeStampMinimumResolution(
-      t1 + t2,
-      Performance::kPerformanceTimerMinResolutionInMicroseconds);
+      t1 + t2, Performance::kPerformanceTimerMinResolutionInMicroseconds);
 }
 
 void Performance::Mark(const std::string& mark_name,
@@ -382,8 +383,9 @@
   // entry buffer.
   PerformanceEntryList performance_entry_buffer;
   for (const auto& entry : performance_entry_buffer_) {
-    bool should_be_removed = PerformanceEntry::ToEntryTypeEnum(
-        entry->entry_type()) == PerformanceEntry::kResource;
+    bool should_be_removed =
+        PerformanceEntry::ToEntryTypeEnum(entry->entry_type()) ==
+        PerformanceEntry::kResource;
     if (!should_be_removed) {
       performance_entry_buffer.push_back(entry);
     }
@@ -606,8 +608,8 @@
   // 2.Setup the resource timing entry for entry, given initiatorType,
   // requestedURL, timingInfo, and cacheMode.
   scoped_refptr<PerformanceResourceTiming> resource_timing(
-      new PerformanceResourceTiming(timing_info, initiator_type,
-                                    requested_url, this, time_origin_));
+      new PerformanceResourceTiming(timing_info, initiator_type, requested_url,
+                                    this, time_origin_));
   // 2. Queue entry.
   QueuePerformanceEntry(resource_timing);
   // 3. Add entry to global's performance entry buffer.
@@ -621,8 +623,8 @@
 
 void Performance::SetApplicationStartOrPreloadTimestamp(
     bool is_preload, SbTimeMonotonic timestamp) {
-  lifecycle_timing_->SetApplicationStartOrPreloadTimestamp(
-      is_preload, timestamp);
+  lifecycle_timing_->SetApplicationStartOrPreloadTimestamp(is_preload,
+                                                           timestamp);
 }
 
 void Performance::SetDeepLinkTimestamp(SbTimeMonotonic timestamp) {
diff --git a/src/cobalt/dom/performance_test.cc b/src/cobalt/dom/performance_test.cc
index be1e776..f0a28ed 100644
--- a/src/cobalt/dom/performance_test.cc
+++ b/src/cobalt/dom/performance_test.cc
@@ -25,7 +25,8 @@
       new base::SystemMonotonicClock());
 
   testing::StubEnvironmentSettings environment_settings;
-  scoped_refptr<Performance> performance(new Performance(&environment_settings, clock));
+  scoped_refptr<Performance> performance(
+      new Performance(&environment_settings, clock));
 
   // Test that now returns a result that is within a correct range for the
   // current time.
@@ -46,10 +47,11 @@
       new base::SystemMonotonicClock());
 
   testing::StubEnvironmentSettings environment_settings;
-  scoped_refptr<Performance> performance(new Performance(&environment_settings, clock));
+  scoped_refptr<Performance> performance(
+      new Performance(&environment_settings, clock));
 
   base::TimeTicks current_time_ticks = base::TimeTicks::Now();
-  DOMHighResTimeStamp  current_time = ClampTimeStampMinimumResolution(
+  DOMHighResTimeStamp current_time = ClampTimeStampMinimumResolution(
       current_time_ticks,
       Performance::kPerformanceTimerMinResolutionInMicroseconds);
   DOMHighResTimeStamp current_time_respect_to_time_origin =
@@ -70,17 +72,19 @@
   // the object will be created at the beginning of a new navigation.
   scoped_refptr<base::SystemMonotonicClock> clock(
       new base::SystemMonotonicClock());
-  base::TimeTicks lower_limit = base::TimeTicks::Now();
 
-  scoped_refptr<PerformanceTiming> performance_timing(
-      new PerformanceTiming(clock, base::TimeTicks::Now()));
+  uint64 lower_limit =
+      (base::TimeTicks::Now() - base::TimeTicks::UnixEpoch()).InMilliseconds();
 
-  base::TimeTicks upper_limit = base::TimeTicks::Now();
+  testing::StubEnvironmentSettings environment_settings;
+  scoped_refptr<Performance> performance(
+      new Performance(&environment_settings, clock));
 
-  DCHECK_GE(performance_timing->navigation_start(),
-            static_cast<uint64>((lower_limit.ToInternalValue())));
-  DCHECK_LE(performance_timing->navigation_start(),
-            static_cast<uint64>((upper_limit.ToInternalValue())));
+  uint64 upper_limit =
+      (base::TimeTicks::Now() - base::TimeTicks::UnixEpoch()).InMilliseconds();
+
+  DCHECK_GE(performance->timing()->navigation_start(), lower_limit);
+  DCHECK_LE(performance->timing()->navigation_start(), upper_limit);
 }
 
 }  // namespace dom
diff --git a/src/cobalt/dom/performance_timing.cc b/src/cobalt/dom/performance_timing.cc
index 910eb03..c0cf211 100644
--- a/src/cobalt/dom/performance_timing.cc
+++ b/src/cobalt/dom/performance_timing.cc
@@ -18,16 +18,13 @@
 namespace dom {
 
 PerformanceTiming::PerformanceTiming(
-    const scoped_refptr<base::BasicClock>& clock,
-    base::TimeTicks time_origin)
-    : navigation_start_(time_origin),
+    const scoped_refptr<base::BasicClock>& clock, uint64 navigation_start)
+    : navigation_start_(navigation_start),
       navigation_start_clock_(new base::OffsetClock(clock, clock->Now())) {}
 
 PerformanceTiming::~PerformanceTiming() {}
 
-uint64 PerformanceTiming::navigation_start() const {
-  return static_cast<uint64>(navigation_start_.ToInternalValue());
-}
+uint64 PerformanceTiming::navigation_start() const { return navigation_start_; }
 
 scoped_refptr<base::OffsetClock> PerformanceTiming::GetNavigationStartClock() {
   return navigation_start_clock_;
diff --git a/src/cobalt/dom/performance_timing.h b/src/cobalt/dom/performance_timing.h
index 184d92d..a0a761c 100644
--- a/src/cobalt/dom/performance_timing.h
+++ b/src/cobalt/dom/performance_timing.h
@@ -29,7 +29,7 @@
   // Performance::Mark and Performance::Measure.
  public:
   explicit PerformanceTiming(const scoped_refptr<base::BasicClock>& clock,
-                             base::TimeTicks time_origin);
+                             uint64 navigation_start);
 
   // This attribute must return the time immediately after the user agent
   // finishes prompting to unload the previous document. If there is no previous
@@ -50,7 +50,7 @@
   ~PerformanceTiming();
 
   // The navigation start time relative to January 1, 1970.
-  base::TimeTicks navigation_start_;
+  uint64 navigation_start_;
   scoped_refptr<base::OffsetClock> navigation_start_clock_;
 
   DISALLOW_COPY_AND_ASSIGN(PerformanceTiming);
diff --git a/src/cobalt/dom/window_event_handlers.idl b/src/cobalt/dom/window_event_handlers.idl
index 186e1ad..ba91797 100644
--- a/src/cobalt/dom/window_event_handlers.idl
+++ b/src/cobalt/dom/window_event_handlers.idl
@@ -18,4 +18,6 @@
 interface WindowEventHandlers {
   attribute EventHandler onunload;
   attribute EventHandler onbeforeunload;
+  attribute EventHandler onoffline;
+  attribute EventHandler ononline;
 };
diff --git a/src/cobalt/extension/extension_test.cc b/src/cobalt/extension/extension_test.cc
index ef159a7..43b4925 100644
--- a/src/cobalt/extension/extension_test.cc
+++ b/src/cobalt/extension/extension_test.cc
@@ -22,6 +22,7 @@
 #include "cobalt/extension/installation_manager.h"
 #include "cobalt/extension/javascript_cache.h"
 #include "cobalt/extension/media_session.h"
+#include "cobalt/extension/memory_mapped_file.h"
 #include "cobalt/extension/platform_service.h"
 #include "cobalt/extension/updater_notification.h"
 #include "cobalt/extension/url_fetcher_observer.h"
@@ -328,5 +329,25 @@
       << "Extension struct should be a singleton";
 }
 
+TEST(ExtensionTest, MemoryMappedFile) {
+  typedef CobaltExtensionMemoryMappedFileApi ExtensionApi;
+  const char* kExtensionName = kCobaltExtensionMemoryMappedFileName;
+
+  const ExtensionApi* extension_api =
+      static_cast<const ExtensionApi*>(SbSystemGetExtension(kExtensionName));
+  if (!extension_api) {
+    return;
+  }
+
+  EXPECT_STREQ(extension_api->name, kExtensionName);
+  EXPECT_EQ(extension_api->version, 1u);
+  EXPECT_NE(extension_api->MemoryMapFile, nullptr);
+
+  const ExtensionApi* second_extension_api =
+      static_cast<const ExtensionApi*>(SbSystemGetExtension(kExtensionName));
+  EXPECT_EQ(second_extension_api, extension_api)
+      << "Extension struct should be a singleton";
+}
+
 }  // namespace extension
 }  // namespace cobalt
diff --git a/src/cobalt/extension/memory_mapped_file.h b/src/cobalt/extension/memory_mapped_file.h
new file mode 100644
index 0000000..7c1c4bb
--- /dev/null
+++ b/src/cobalt/extension/memory_mapped_file.h
@@ -0,0 +1,58 @@
+// Copyright 2021 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+
+#ifndef COBALT_EXTENSION_MEMORY_MAPPED_FILE_H_
+#define COBALT_EXTENSION_MEMORY_MAPPED_FILE_H_
+
+#include <stdint.h>
+
+#include "starboard/memory.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define kCobaltExtensionMemoryMappedFileName \
+  "dev.cobalt.extension.MemoryMappedFile"
+
+typedef struct CobaltExtensionMemoryMappedFileApi {
+  // Name should be the string |kCobaltExtensionMemoryMappedFileName|.
+  // This helps to validate that the extension API is correct.
+  const char* name;
+
+  // This specifies the version of the API that is implemented.
+  uint32_t version;
+
+  // The fields below this point were added in version 1 or later.
+
+  // Memory maps a file at the specified |address| starting at |file_offset|
+  // and  mapping |size| bytes. The |address| argument can be NULL in which
+  // case new memory buffer will be allocated. If a non NULL |address| is
+  // passed the memory should be resreved in advance through |SbMemoryMap|.
+  // To release the memory call |SbMemoryUnmap|.
+  // The |file_offset| must be a multiple of |kSbMemoryPageSize|.
+  // Returns NULL or error.
+  void* (*MemoryMapFile)(void* address, const char* path,
+                         SbMemoryMapFlags flags, int64_t file_offset,
+                         int64_t size);
+
+} CobaltExtensionMemoryMappedFileApi;
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // COBALT_EXTENSION_MEMORY_MAPPED_FILE_H_
diff --git a/src/cobalt/h5vcc/dial/dial_http_response.cc b/src/cobalt/h5vcc/dial/dial_http_response.cc
index 6531a3e..3fcd329 100644
--- a/src/cobalt/h5vcc/dial/dial_http_response.cc
+++ b/src/cobalt/h5vcc/dial/dial_http_response.cc
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 #include <memory>
+#include <utility>
 
 #include "cobalt/h5vcc/dial/dial_http_response.h"
 
@@ -24,7 +25,7 @@
 namespace dial {
 DialHttpResponse::DialHttpResponse(const std::string& path,
                                    const std::string& method)
-    : path_(path), method_(method), response_code_(0) {}
+    : path_(path), method_(method), response_code_(500) {}
 
 void DialHttpResponse::AddHeader(const std::string& header,
                                  const std::string& value) {
diff --git a/src/cobalt/media/base/playback_statistics.cc b/src/cobalt/media/base/playback_statistics.cc
index b5001ec..30527b1 100644
--- a/src/cobalt/media/base/playback_statistics.cc
+++ b/src/cobalt/media/base/playback_statistics.cc
@@ -128,13 +128,16 @@
                      "", "The error message of the media pipeline error.") {}
 
 PlaybackStatistics::~PlaybackStatistics() {
-  SbAtomicNoBarrier_Increment(&s_active_instances, -1);
+  if (has_active_instance_) {
+    DCHECK(SbAtomicAcquire_Load(&s_active_instances) > 0);
+    SbAtomicNoBarrier_Increment(&s_active_instances, -1);
+  }
 }
 
 void PlaybackStatistics::UpdateVideoConfig(
     const VideoDecoderConfig& video_config) {
-  if (is_initial_config_) {
-    is_initial_config_ = false;
+  if (!has_active_instance_) {
+    has_active_instance_ = true;
 
     SbAtomicNoBarrier_Increment(&s_active_instances, 1);
 
diff --git a/src/cobalt/media/base/playback_statistics.h b/src/cobalt/media/base/playback_statistics.h
index 78808b3..7507b31 100644
--- a/src/cobalt/media/base/playback_statistics.h
+++ b/src/cobalt/media/base/playback_statistics.h
@@ -54,7 +54,7 @@
   base::CVal<bool> is_video_eos_written_;
   base::CVal<PipelineStatus> pipeline_status_;
   base::CVal<std::string> error_message_;
-  bool is_initial_config_ = true;
+  bool has_active_instance_ = false;
   bool is_first_audio_buffer_written_ = false;
   bool is_first_video_buffer_written_ = false;
 };
diff --git a/src/cobalt/media/base/sbplayer_pipeline.cc b/src/cobalt/media/base/sbplayer_pipeline.cc
index 5a9b541..3fa6b43 100644
--- a/src/cobalt/media/base/sbplayer_pipeline.cc
+++ b/src/cobalt/media/base/sbplayer_pipeline.cc
@@ -904,7 +904,7 @@
   // TODO:  Check |suspended_| here as the pipeline can be suspended before the
   // player is created.  In this case we should delay creating the player as the
   // creation of player may fail.
-
+  std::string error_message;
   {
     base::AutoLock auto_lock(lock_);
     LOG(INFO) << "Creating StarboardPlayer with url: " << source_url;
@@ -916,6 +916,7 @@
       SetPlaybackRateTask(playback_rate_);
       SetVolumeTask(volume_);
     } else {
+      error_message = player_->GetPlayerCreationErrorMessage();
       player_.reset();
       LOG(INFO) << "Failed to create a valid StarboardPlayer.";
     }
@@ -933,8 +934,9 @@
   }
 
   CallSeekCB(DECODER_ERROR_NOT_SUPPORTED,
-             "SbPlayerPipeline::CreateUrlPlayer failed: "
-             "player_->IsValid() is false.");
+             "SbPlayerPipeline::CreateUrlPlayer failed to create a valid "
+             "StarboardPlayer:" +
+                 (error_message.empty() ? "" : " Error: " + error_message));
 }
 
 void SbPlayerPipeline::SetDrmSystem(SbDrmSystem drm_system) {
@@ -990,6 +992,7 @@
         video_stream_->video_decoder_config());
   }
 
+  std::string error_message;
   {
     base::AutoLock auto_lock(lock_);
     SB_DCHECK(!player_);
@@ -1008,6 +1011,7 @@
       SetPlaybackRateTask(playback_rate_);
       SetVolumeTask(volume_);
     } else {
+      error_message = player_->GetPlayerCreationErrorMessage();
       player_.reset();
       LOG(INFO) << "Failed to create a valid StarboardPlayer.";
     }
@@ -1032,8 +1036,9 @@
   }
 
   CallSeekCB(DECODER_ERROR_NOT_SUPPORTED,
-             "SbPlayerPipeline::CreatePlayer failed: "
-             "player_->IsValid() is false.");
+             "SbPlayerPipeline::CreatePlayer failed to create a valid "
+             "StarboardPlayer:" +
+                 (error_message.empty() ? "" : " Error: " + error_message));
 }
 
 void SbPlayerPipeline::OnDemuxerInitialized(PipelineStatus status) {
diff --git a/src/cobalt/media/base/starboard_player.cc b/src/cobalt/media/base/starboard_player.cc
index 7d19612..47ad52b 100644
--- a/src/cobalt/media/base/starboard_player.cc
+++ b/src/cobalt/media/base/starboard_player.cc
@@ -554,6 +554,8 @@
 
   bool has_audio = audio_codec != kSbMediaAudioCodecNone;
 
+  is_creating_player_ = true;
+
 #if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
 
   SbPlayerCreationParam creation_param = {};
@@ -592,6 +594,8 @@
 
 #endif  // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
 
+  is_creating_player_ = false;
+
   if (!SbPlayerIsValid(player_)) {
     return;
   }
@@ -856,6 +860,19 @@
   }
 }
 
+bool StarboardPlayer::TryToSetPlayerCreationErrorMessage(
+    const std::string& message) {
+  DCHECK(task_runner_->BelongsToCurrentThread());
+  if (is_creating_player_) {
+    player_creation_error_message_ = message;
+    return true;
+  }
+  LOG(INFO) << "TryToSetPlayerCreationErrorMessage() "
+               "is called when |is_creating_player_| "
+               "is false. Error message is ignored.";
+  return false;
+}
+
 // static
 void StarboardPlayer::DecoderStatusCB(SbPlayer player, void* context,
                                       SbMediaType type,
@@ -880,6 +897,13 @@
 void StarboardPlayer::PlayerErrorCB(SbPlayer player, void* context,
                                     SbPlayerError error, const char* message) {
   StarboardPlayer* helper = static_cast<StarboardPlayer*>(context);
+  if (player == kSbPlayerInvalid) {
+    // TODO: Simplify by combining the functionality of
+    // TryToSetPlayerCreationErrorMessage() with OnPlayerError().
+    if (helper->TryToSetPlayerCreationErrorMessage(message)) {
+      return;
+    }
+  }
   helper->task_runner_->PostTask(
       FROM_HERE, base::Bind(&StarboardPlayer::CallbackHelper::OnPlayerError,
                             helper->callback_helper_, player, error,
diff --git a/src/cobalt/media/base/starboard_player.h b/src/cobalt/media/base/starboard_player.h
index 588ca42..6e40ac4 100644
--- a/src/cobalt/media/base/starboard_player.h
+++ b/src/cobalt/media/base/starboard_player.h
@@ -118,6 +118,15 @@
   //       Need to be removed with media refactor.
   void Resume(SbWindow window);
 
+  // These functions help the pipeline report an error message on a player
+  // creation error. TryToSetPlayerCreationErrorMessage() will set
+  // |player_creation_error_message_| and return true when called while
+  // |is_creating_player_| is true, else it will do nothing and return false.
+  bool TryToSetPlayerCreationErrorMessage(const std::string& message);
+  std::string GetPlayerCreationErrorMessage() const {
+    return player_creation_error_message_;
+  }
+
   SbDecodeTarget GetCurrentSbDecodeTarget();
   SbPlayerOutputMode GetSbPlayerOutputMode();
 
@@ -256,6 +265,10 @@
   // A string of video maximum capabilities.
   std::string max_video_capabilities_;
 
+  // Keep track of errors during player creation.
+  bool is_creating_player_ = false;
+  std::string player_creation_error_message_;
+
 #if SB_HAS(PLAYER_WITH_URL)
   const bool is_url_based_;
 #endif  // SB_HAS(PLAYER_WITH_URL)
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontConfigParser_cobalt.cc b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontConfigParser_cobalt.cc
index 4890e72..67fe50a 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontConfigParser_cobalt.cc
+++ b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontConfigParser_cobalt.cc
@@ -324,6 +324,10 @@
         LOG(ERROR) << "---- Invalid fallback priority [" << value << "]";
         NOTREACHED();
       }
+    } else if (name_len == 15 &&
+               strncmp("disable_caching", name, name_len) == 0) {
+      family->disable_caching =
+          strcmp("true", value) == 0 || strcmp("1", value) == 0;
     } else {
       LOG(ERROR) << "---- Unsupported family attribute [" << name << "]";
       NOTREACHED();
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontStyleSet_cobalt.cc b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontStyleSet_cobalt.cc
index 8d92c16..6862a5e 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontStyleSet_cobalt.cc
+++ b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontStyleSet_cobalt.cc
@@ -91,6 +91,7 @@
   }
 
   character_map_ = base::MakeRefCounted<font_character_map::CharacterMap>();
+  disable_character_map_ = family_info.disable_caching;
 
   family_name_ = family_info.names[0];
   SkTHashMap<SkString, int> styles_index_map;
@@ -392,10 +393,12 @@
               << "(" << style_entry->font_style.weight() << ", "
               << style_entry->font_style.width() << ", "
               << style_entry->font_style.slant() << ")";
+    scoped_refptr<font_character_map::CharacterMap> map =
+        disable_character_map_ ? NULL : character_map_;
     style_entry->typeface.reset(new SkTypeface_CobaltStreamProvider(
         stream_provider, style_entry->face_index, style_entry->font_style,
         style_entry->face_is_fixed_pitch, family_name_,
-        style_entry->disable_synthetic_bolding, character_map_));
+        style_entry->disable_synthetic_bolding, map));
   } else {
     LOG(ERROR) << "Failed to scan font: "
                << style_entry->font_file_path.c_str();
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontStyleSet_cobalt.h b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontStyleSet_cobalt.h
index 33ec970..774a90f 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontStyleSet_cobalt.h
+++ b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontStyleSet_cobalt.h
@@ -135,6 +135,9 @@
   SkLanguage language_;
   font_character_map::PageRanges page_ranges_;
 
+  // Used when the styles in the styleset have different character mappings.
+  bool disable_character_map_;
+
   // NOTE: The following characters require locking when being accessed.
   bool is_character_map_generated_;
   scoped_refptr<font_character_map::CharacterMap> character_map_;
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontUtil_cobalt.h b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontUtil_cobalt.h
index 422276c..6314e5a 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontUtil_cobalt.h
+++ b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontUtil_cobalt.h
@@ -164,7 +164,8 @@
 // determine that a family cannot support a character, without needing to
 // generate a full mapping of the family's characters.
 struct FontFamilyInfo {
-  FontFamilyInfo() : is_fallback_family(true), fallback_priority(0) {}
+  FontFamilyInfo()
+      : is_fallback_family(true), fallback_priority(0), disable_caching(0) {}
 
   SkTArray<SkString> names;
   SkTArray<FontFileInfo> fonts;
@@ -172,6 +173,7 @@
   bool is_fallback_family;
   int fallback_priority;
   font_character_map::PageRanges page_ranges;
+  bool disable_caching;
 };
 
 #endif  // COBALT_RENDERER_RASTERIZER_SKIA_SKIA_SRC_PORTS_SKFONTUTIL_COBALT_H_
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkTypeface_cobalt.cc b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkTypeface_cobalt.cc
index 8f9cce8..a116c2c 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkTypeface_cobalt.cc
+++ b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkTypeface_cobalt.cc
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 #include <memory>
+#include <utility>
 
 #include "cobalt/renderer/rasterizer/skia/skia/src/ports/SkTypeface_cobalt.h"
 
@@ -44,16 +45,18 @@
 
 SkGlyphID SkTypeface_Cobalt::characterMapGetGlyphIdForCharacter(
     SkUnichar character) const {
-  CHECK(character_map_);
-
-  // Check whether the character is cached in the character map.
-  font_character_map::Character c = character_map_->Find(character);
-  if (c.is_set) return c.id;
+  if (character_map_) {
+    // Check whether the character is cached in the character map.
+    font_character_map::Character c = character_map_->Find(character);
+    if (c.is_set) return c.id;
+  }
 
   // If the character isn't there, look it up with FreeType, then cache it.
   SkGlyphID glyphs[1] = {0};
   SkTypeface_FreeType::onCharsToGlyphs(&character, 1, glyphs);
-  character_map_->Insert(character, glyphs[0]);
+  if (character_map_) {
+    character_map_->Insert(character, glyphs[0]);
+  }
   return glyphs[0];
 }
 
@@ -119,7 +122,6 @@
   *face_index = face_index_;
   return std::unique_ptr<SkFileMemoryChunkStream>(
       stream_provider_->OpenStream());
-  ;
 }
 
 size_t SkTypeface_CobaltStreamProvider::GetStreamLength() const {
diff --git a/src/cobalt/site/docs/codelabs/cobalt_extensions/codelab.md b/src/cobalt/site/docs/codelabs/cobalt_extensions/codelab.md
new file mode 100644
index 0000000..8fc180c
--- /dev/null
+++ b/src/cobalt/site/docs/codelabs/cobalt_extensions/codelab.md
@@ -0,0 +1,793 @@
+---
+layout: doc
+title: "Cobalt Extensions codelab"
+---
+
+The Cobalt Extension framework provides a way to add optional, platform-specific
+features to the Cobalt application. A Cobalt Extension is an optional interface
+that porters can implement for their platforms if, and as, they wish.
+
+This tutorial uses coding exercises to guide you through the process of creating
+a simple example of a Cobalt Extension. By the end you should have a firm
+understanding of what Cobalt Extensions are, when to use them instead of
+alternatives, how to write them, and how to work with the Cobalt team to
+contribute them to the repository.
+
+## Prerequisites
+
+Because it's helpful to build and run Cobalt during the exercises, you'll first
+want to set up your environment and make sure you can build Cobalt. You can
+follow <a href="/development/setup-linux.html">Set up your environment -
+Linux</a> to do this if you're a Linux user. Please note that the exercise
+solutions assume you're using Linux but should be comparable to implementations
+for other platforms.
+
+Also note that while this codelab doesn't require it, you'll need to
+<a href="/starboard/porting.html">Port Cobalt to your platform</a> before you
+can actually use a Cobalt Extension to customize it for your platform.
+
+Finally, the exercises assume the ability to program in C and C++.
+
+### Exercise 0: Run Cobalt and inspect logs
+
+Assuming you've already built Cobalt, please now run Cobalt and pay special
+attention to a message it logs when it starts up. This message will be the focus
+of subsequent exercises.
+
+```
+$ out/linux-x64x11_debug/cobalt 2>/dev/null | grep "Starting application"
+```
+
+## Background
+
+Situated below Cobalt is Starboard. Starboard, which is a porting layer and OS
+abstraction, contains a minimal set of APIs to encapsulate the platform-specific
+functionalities that Cobalt uses. Each Starboard module (memory, socket, thread,
+etc.) defines functions that must be implemented on a porter's platform,
+imposing an implementation and maintenance cost on all porters. With this cost
+in mind the Cobalt team tries to keep the Starboard APIs stable and only adds a
+new API **when some functionality is required by Cobalt but the implementation
+depends on the platform**.
+
+A Starboard API can be made optional, though, by the introduction of an
+accompanying API that asks platforms whether they support the underlying feature
+and enables Cobalt to check for the answer at runtime. For example,
+`SbWindowOnScreenKeyboardIsSupported` is used so that only platforms that
+support an on screen keyboard need implement the related functions in
+`starboard/window.h`. To spare porters uninterested in the functionality, the
+Cobalt team chooses to make a Starboard API optional **when some Cobalt
+functionality is optional and the implementation is platform-dependent**.
+
+Finally, a nonobvious point explains why even an optional Starboard API may
+sometimes be too cumbersome: other applications beyond Cobalt are able to be run
+on top of Starboard. If a feature is needed by Cobalt but not by all Starboard-
+based applications or by Starboard itself, adding a Starboard API for it may add
+unnecessary size and complexity to the porting layer. **And here we arrive at
+the sweet spot for Cobalt Extensions: when the desired functionality is
+Cobalt-specific, optional in Cobalt, and has platform-dependent
+implementation.** Also, because Cobalt Extensions are lightweight and, as you'll
+see below, added without any changes to the Starboard layer, they're the
+preferred way for porters to add new, custom features to Cobalt.
+
+To summarize:
+
+<table>
+  <tr>
+    <th colspan="1">Tool</th>
+    <th colspan="1">Use case</th>
+    <th colspan="1">Ecosystem cost</th>
+  </tr>
+  <tr>
+    <td>Starboard API</td>
+    <td>Feature is <strong>required</strong> but implementation is
+    platform-dependent</td>
+    <td>High</td>
+  </tr>
+  <tr>
+    <td>Optional Starboard API</td>
+    <td>Feature is <strong>optional</strong> and implementation is
+    platform-dependent</td>
+    <td>Medium</td>
+  </tr>
+  <tr>
+    <td>Cobalt Extension</td>
+    <td>Feature is <strong>optional and specific to Cobalt</strong> and
+    implementation is platform-dependent</td>
+    <td>Low</td>
+  </tr>
+</table>
+
+As a caveat, please note that for all three of these abstractions the interface
+is in Cobalt's open-source repository and therefore visible to other porters.
+The implementation, on the other hand, is written and built by porters and so
+may be kept private.
+
+Finally, in addition to the alternatives mentioned, porters have in some cases
+made local changes to Cobalt, above the Starboard layer, to achieve some
+customization or optimization. This has been discouraged by the Cobalt team
+because it makes rebasing to future versions of Cobalt more difficult but has
+been possible because porters have historically built **both** Cobalt and
+Starboard. However, Cobalt is moving toward Evergreen
+(<a href="https://cobalt.googlesource.com/cobalt/+/refs/heads/master/src/starboard/doc/evergreen/cobalt_evergreen_overview.md">overview</a>),
+an architecture that enables automatic Cobalt updates on devices by separating a
+Google-built, Cobalt core shared library from the partner-built Starboard layer
+and Cobalt loader app. Because Cobalt core code is built by Google, custom
+changes to it are no longer possible for partners using Evergreen.
+
+## Anatomy of a Cobalt Extension
+
+### Extension structures
+
+Cobalt uses a structure to describe the interface for an extension and organizes
+the structures in headers under `cobalt/extension/`. The header for a "foo"
+extension should be named `foo.h` and the first version of it should contain the
+following content, as well as any additional members that provide the "foo"
+functionality.
+
+```
+#ifndef COBALT_EXTENSION_FOO_H_
+#define COBALT_EXTENSION_FOO_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define kCobaltExtensionFooName "dev.cobalt.extension.Foo"
+
+typedef struct CobaltExtensionFooApi {
+  // Name should be the string |kCobaltExtensionFooName|.
+  // This helps to validate that the extension API is correct.
+  const char* name;
+
+  // This specifies the version of the API that is implemented.
+  uint32_t version;
+
+  // The fields below this point were added in version 1 or later.
+
+} CobaltExtensionFooApi;
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // COBALT_EXTENSION_FOO_H_
+```
+
+Please note a few important points about this structure:
+
+*   The first two members must be, in order:
+    *   A `const char* |name|`, storing the extension's name.
+    *   A `uint32_t |version|`, storing the version number of the extension.
+        Extension versioning is discussed later on in this codelab.
+*   The following members can be any C types (including custom structures) that
+    are useful. Often, these are function pointers.
+
+### Extension access in Cobalt
+
+The `SbSystemGetExtension` function from Starboard's `system` module allows
+Cobalt to query for an extension by name. It returns a pointer to the constant,
+global instance of the structure implementing the extension with the given name
+if it exists, otherwise `NULL`. This function is the only mechanism Cobalt has
+to get an extension; the Starboard interface intentionally doesn't have any
+functions related to the specific extensions.
+
+The caller in Cobalt must static cast the `const void*` returned by
+`SbSystemGetExtension` to a `const CobaltExtensionFooApi*`, or pointer of
+whatever type the extension structure type happens to be, before using it. Since
+the caller can't be sure whether a platform implements the extension or, if it
+does, implements it correctly, it's good defensive programming to check that the
+resulting pointer is not `NULL` and that the `name` member in the pointed-to
+structure has the same value as `kCobaltExtensionFooName`.
+
+### Extension implementation
+
+Because Cobalt Extensions are platform-dependent, the implementations of an
+extension belong in Starboard ports. A Starboard port implements an extension by
+defining a constant, global instance of the structure and implementing the
+`SbSystemGetExtension` function to return a pointer to it. For our "foo"
+extension, an implementation for `custom_platform`'s Starboard port could look
+as follows.
+
+`starboard/custom_platform/foo.h` declares a `GetFooApi` accessor for the
+structure instance.
+
+```
+#ifndef STARBOARD_CUSTOM_PLATFORM_FOO_H_
+#define STARBOARD_CUSTOM_PLATFORM_FOO_H_
+
+namespace starboard {
+namespace custom_platform {
+
+const void* GetFooApi();
+
+}  // namespace custom_platform
+}  // namespace starboard
+
+#endif  // STARBOARD_CUSTOM_PLATFORM_FOO_H_
+```
+
+`starboard/custom_platform/foo.cc`, then, defines `GetFooApi`.
+
+```
+#include "starboard/custom_platform/foo.h"
+
+#include "cobalt/extension/foo.h"
+
+namespace starboard {
+namespace custom_platform {
+
+namespace {
+
+// Definitions of any functions included as components in the extension
+// are added here.
+
+const CobaltExtensionFooApi kFooApi = {
+    kCobaltExtensionFooName,
+    1,  // API version that's implemented.
+    // Any additional members are initialized here.
+};
+
+}  // namespace
+
+const void* GetFooApi() {
+  return &kFooApi;
+}
+
+}  // namespace custom_platform
+}  // namespace starboard
+```
+
+Finally, `starboard/custom_platform/system_get_extension.cc` defines
+`SbSystemGetExtension` to wire up the extensions for the platform.
+
+```
+#include "starboard/system.h"
+
+#include "cobalt/extension/foo.h"
+#include "starboard/common/string.h"
+#include "starboard/custom_platform/foo.h"
+
+const void* SbSystemGetExtension(const char* name) {
+  if (strcmp(name, kCobaltExtensionFooName) == 0) {
+    return starboard::custom_platform::GetFooApi();
+  }
+  // Other conditions here should handle other implemented extensions.
+
+  return NULL;
+}
+```
+
+Please feel free to browse existing extension implementations in the repository.
+For example, the reference Raspberry Pi port implements the `Graphics` extension
+across the following files.
+
+*   `starboard/raspi/shared/graphics.h`
+*   `starboard/raspi/shared/graphics.cc`
+*   `starboard/raspi/shared/system_get_extensions.cc`
+
+### Exercise 1: Write and use your first extension
+
+Now that you've seen the anatomy of a Cobalt Extension it's your turn to write
+one of your own. In Exercise 0 we saw that Cobalt logs "Starting application"
+when it's started. Please write a `Pleasantry` Cobalt Extension that has a
+member of type `const char*` and name `greeting` and make any necessary changes
+in `cobalt/browser/main.cc` so that the extension can be used to log a custom
+greeting directly after the plain "Starting application." Implement the
+extension for Linux, or whichever other platform you'd like, and confirm that
+the greeting is logged.
+
+#### Solution to Exercise 1
+
+Click the items below to expand parts of a solution. The `git diff`s are between
+the solution and the `master` branch.
+
+<details>
+    <summary style="display:list-item">Contents of new
+    `cobalt/extension/pleasantry.h` file.</summary>
+
+```
+#ifndef COBALT_EXTENSION_PLEASANTRY_H_
+#define COBALT_EXTENSION_PLEASANTRY_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define kCobaltExtensionPleasantryName "dev.cobalt.extension.Pleasantry"
+
+typedef struct CobaltExtensionPleasantryApi {
+  // Name should be the string |kCobaltExtensionPleasantryName|.
+  // This helps to validate that the extension API is correct.
+  const char* name;
+
+  // This specifies the version of the API that is implemented.
+  uint32_t version;
+
+  // The fields below this point were added in version 1 or later.
+  const char* greeting;
+
+} CobaltExtensionPleasantryApi;
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // COBALT_EXTENSION_PLEASANTRY_H_
+```
+
+</details>
+
+<details>
+    <summary style="display:list-item">Contents of new
+    `starboard/linux/shared/pleasantry.h` file.</summary>
+
+```
+#ifndef STARBOARD_LINUX_SHARED_PLEASANTRY_H_
+#define STARBOARD_LINUX_SHARED_PLEASANTRY_H_
+
+namespace starboard {
+namespace shared {
+
+const void* GetPleasantryApi();
+
+}  // namespace shared
+}  // namespace starboard
+
+#endif  // STARBOARD_LINUX_SHARED_PLEASANTRY_H_
+```
+
+</details>
+
+<details>
+    <summary style="display:list-item">Contents of new
+    `starboard/linux/shared/pleasantry.cc` file.</summary>
+
+```
+#include "starboard/linux/shared/pleasantry.h"
+
+#include "cobalt/extension/pleasantry.h"
+
+namespace starboard {
+namespace shared {
+
+namespace {
+
+const char *kGreeting = "Happy debugging!";
+
+const CobaltExtensionPleasantryApi kPleasantryApi = {
+    kCobaltExtensionPleasantryName,
+    1,
+    kGreeting,
+};
+
+}  // namespace
+
+const void* GetPleasantryApi() {
+  return &kPleasantryApi;
+}
+
+}  // namespace shared
+}  // namespace starboard
+```
+
+</details>
+
+<details>
+    <summary style="display:list-item">`git diff
+    starboard/linux/shared/starboard_platform.gypi`</summary>
+
+```
+@@ -38,6 +38,8 @@
+       '<(DEPTH)/starboard/linux/shared/netlink.cc',
+       '<(DEPTH)/starboard/linux/shared/netlink.h',
+       '<(DEPTH)/starboard/linux/shared/player_components_factory.cc',
++      '<(DEPTH)/starboard/linux/shared/pleasantry.cc',
++      '<(DEPTH)/starboard/linux/shared/pleasantry.h',
+       '<(DEPTH)/starboard/linux/shared/routes.cc',
+       '<(DEPTH)/starboard/linux/shared/routes.h',
+       '<(DEPTH)/starboard/linux/shared/system_get_connection_type.cc',
+```
+
+</details>
+
+<details>
+    <summary style="display:list-item">`git diff
+    starboard/linux/shared/system_get_extensions.cc`</summary>
+
+```
+@@ -16,12 +16,14 @@
+
+ #include "cobalt/extension/configuration.h"
+ #include "cobalt/extension/crash_handler.h"
++#include "cobalt/extension/pleasantry.h"
+ #include "starboard/common/string.h"
+ #include "starboard/shared/starboard/crash_handler.h"
+ #if SB_IS(EVERGREEN_COMPATIBLE)
+ #include "starboard/elf_loader/evergreen_config.h"
+ #endif
+ #include "starboard/linux/shared/configuration.h"
++#include "starboard/linux/shared/pleasantry.h"
+
+ const void* SbSystemGetExtension(const char* name) {
+ #if SB_IS(EVERGREEN_COMPATIBLE)
+@@ -41,5 +43,8 @@ const void* SbSystemGetExtension(const char* name) {
+   if (strcmp(name, kCobaltExtensionCrashHandlerName) == 0) {
+     return starboard::common::GetCrashHandlerApi();
+   }
++  if (strcmp(name, kCobaltExtensionPleasantryName) == 0) {
++    return starboard::shared::GetPleasantryApi();
++  }
+   return NULL;
+ }
+```
+
+</details>
+
+<details>
+    <summary style="display:list-item">`git diff cobalt/browser/main.cc`
+    </summary>
+
+```
+@@ -18,7 +18,9 @@
+ #include "cobalt/base/wrap_main.h"
+ #include "cobalt/browser/application.h"
+ #include "cobalt/browser/switches.h"
++#include "cobalt/extension/pleasantry.h"
+ #include "cobalt/version.h"
++#include "starboard/system.h"
+
+ namespace {
+
+@@ -77,6 +79,14 @@ void StartApplication(int argc, char** argv, const char* link,
+     return;
+   }
+   LOG(INFO) << "Starting application.";
++  const CobaltExtensionPleasantryApi* pleasantry_extension =
++      static_cast<const CobaltExtensionPleasantryApi*>(
++          SbSystemGetExtension(kCobaltExtensionPleasantryName));
++  if (pleasantry_extension &&
++      strcmp(pleasantry_extension->name, kCobaltExtensionPleasantryName) == 0 &&
++      pleasantry_extension->version >= 1) {
++    LOG(INFO) << pleasantry_extension->greeting;
++  }
+ #if SB_API_VERSION >= 13
+   DCHECK(!g_application);
+   g_application = new cobalt::browser::Application(quit_closure,
+```
+
+</details>
+
+## Extension versioning
+
+Cobalt Extensions are themselves extensible, but care must be taken to ensure
+that the extension interface in Cobalt and implementation in a platform's port,
+which may be built separately, are consistent.
+
+The `version` member, which is always the second member in an extension
+structure, indicates which version of the interface the structure describes. In
+other words, a `version` of the extension structure corresponds to a specific,
+invariant list of members. By convention, the first version of a Cobalt
+Extension is version `1` (i.e., one-based indexing, not zero-based).
+
+A new version of the extension can be introduced in the structure declaration by
+adding additional members to the end of the declaration and adding a comment to
+delineate, e.g., "The fields below this point were added in version 2 or later."
+To maintain compatibility and enable Cobalt to correctly index into instances of
+the structure, it's important that members are always added at the end of the
+structure declaration and that members are never removed. If a member is
+deprecated in a later version, this fact should simply be noted with a comment
+in the structure declaration.
+
+To implement a new version of the extension, a platform's port should then set
+the `version` member to the appropriate value when creating the instance of the
+structure, and also initialize all members required for the version.
+
+Finally, any code in Cobalt that uses the extension should guard references to
+members with version checks.
+
+### Exercise 2: Version your extension
+
+Add a second version of the `Pleasantry` extension that enables porters to also
+log a polite farewell message when the Cobalt application is stopped. To allow
+platforms more flexibility, add the new `farewell` member as a pointer to a
+function that takes no parameters and returns a `const char*`. Update
+`cobalt/browser/main.cc` so that Cobalt, if the platform implements version 2 of
+this extension, replaces the "Stopping application." message with a polite
+farewell provided by the platform.
+
+To keep things interesting, have the platform's implementation pseudo-randomly
+return one of several messages. And, once you've made the changes, build Cobalt
+and run it a few times to confirm that the feature behaves as expected.
+
+#### Solution to Exercise 2
+
+Click the items below to expand parts of a solution. The `git diff` is between
+the solution and the `master` branch.
+
+<details>
+    <summary style="display:list-item">Updated contents of
+    `cobalt/extension/pleasantry.h`.</summary>
+
+```
+#ifndef COBALT_EXTENSION_PLEASANTRY_H_
+#define COBALT_EXTENSION_PLEASANTRY_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define kCobaltExtensionPleasantryName "dev.cobalt.extension.Pleasantry"
+
+typedef struct CobaltExtensionPleasantryApi {
+  // Name should be the string |kCobaltExtensionPleasantryName|.
+  // This helps to validate that the extension API is correct.
+  const char* name;
+
+  // This specifies the version of the API that is implemented.
+  uint32_t version;
+
+  // The fields below this point were added in version 1 or later.
+  const char* greeting;
+
+  // The fields below this point were added in version 2 or later.
+  const char* (*GetFarewell)();
+
+} CobaltExtensionPleasantryApi;
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // COBALT_EXTENSION_PLEASANTRY_H_
+```
+
+</details>
+
+<details>
+    <summary style="display:list-item">Updated contents of
+    `starboard/linux/shared/pleasantry.cc`.</summary>
+
+```
+#include "starboard/linux/shared/pleasantry.h"
+
+#include <stdlib.h>
+
+#include "cobalt/extension/pleasantry.h"
+#include "starboard/system.h"
+#include "starboard/time.h"
+
+namespace starboard {
+namespace shared {
+
+namespace {
+
+const char* kGreeting = "Happy debugging!";
+
+const char* kFarewells[] = {
+  "Farewell",
+  "Take care",
+  "Thanks for running Cobalt",
+};
+
+const char* GetFarewell() {
+  srand (SbTimeGetNow());
+  int pseudo_random_index = rand() % SB_ARRAY_SIZE_INT(kFarewells);
+  return kFarewells[pseudo_random_index];
+}
+
+const CobaltExtensionPleasantryApi kPleasantryApi = {
+  kCobaltExtensionPleasantryName,
+  2,
+  kGreeting,
+  &GetFarewell,
+};
+
+}  // namespace
+
+const void* GetPleasantryApi() {
+  return &kPleasantryApi;
+}
+
+}  // namespace shared
+}  // namespace starboard
+```
+
+</details>
+
+<details>
+    <summary style="display:list-item">`git diff cobalt/browser/main.cc`
+    </summary>
+
+```
+@@ -18,7 +18,9 @@
+ #include "cobalt/base/wrap_main.h"
+ #include "cobalt/browser/application.h"
+ #include "cobalt/browser/switches.h"
++#include "cobalt/extension/pleasantry.h"
+ #include "cobalt/version.h"
++#include "starboard/system.h"
+
+ namespace {
+
+@@ -54,6 +56,14 @@ bool CheckForAndExecuteStartupSwitches() {
+   return g_is_startup_switch_set;
+ }
+
++// Get the Pleasantry extension if it's implemented.
++const CobaltExtensionPleasantryApi* GetPleasantryApi() {
++  static const CobaltExtensionPleasantryApi* pleasantry_extension =
++      static_cast<const CobaltExtensionPleasantryApi*>(
++          SbSystemGetExtension(kCobaltExtensionPleasantryName));
++  return pleasantry_extension;
++}
++
+ void PreloadApplication(int argc, char** argv, const char* link,
+                         const base::Closure& quit_closure,
+                         SbTimeMonotonic timestamp) {
+@@ -77,6 +87,12 @@ void StartApplication(int argc, char** argv, const char* link,
+     return;
+   }
+   LOG(INFO) << "Starting application.";
++  const CobaltExtensionPleasantryApi* pleasantry_extension = GetPleasantryApi();
++  if (pleasantry_extension &&
++      strcmp(pleasantry_extension->name, kCobaltExtensionPleasantryName) == 0 &&
++      pleasantry_extension->version >= 1) {
++    LOG(INFO) << pleasantry_extension->greeting;
++  }
+ #if SB_API_VERSION >= 13
+   DCHECK(!g_application);
+   g_application = new cobalt::browser::Application(quit_closure,
+@@ -96,7 +112,14 @@ void StartApplication(int argc, char** argv, const char* link,
+ }
+
+ void StopApplication() {
+-  LOG(INFO) << "Stopping application.";
++  const CobaltExtensionPleasantryApi* pleasantry_extension = GetPleasantryApi();
++  if (pleasantry_extension &&
++      strcmp(pleasantry_extension->name, kCobaltExtensionPleasantryName) == 0 &&
++      pleasantry_extension->version >= 2) {
++    LOG(INFO) << pleasantry_extension->GetFarewell();
++  } else {
++    LOG(INFO) << "Stopping application.";
++  }
+   delete g_application;
+   g_application = NULL;
+ }
+```
+
+</details>
+
+`starboard/linux/shared/pleasantry.h`,
+`starboard/linux/shared/starboard_platform.gypi`, and
+`starboard/linux/shared/system_get_extensions.cc` should be unchanged from the
+Exercise 1 solution.
+
+## Extension testing
+
+Each Cobalt Extension has a test in `cobalt/extension/extension_test.cc` that
+tests whether the extension is wired up correctly for the platform Cobalt
+happens to be built for.
+
+Since some platforms may not implement a particular extension, these tests begin
+by checking whether `SbSystemGetExtension` simply returns `NULL` for the
+extension's name. For our `foo` extension, the first few lines may contain the
+following.
+
+```
+TEST(ExtensionTest, Foo) {
+  typedef CobaltExtensionFooApi ExtensionApi;
+  const char* kExtensionName = kCobaltExtensionFooName;
+
+  const ExtensionApi* extension_api =
+      static_cast<const ExtensionApi*>(SbSystemGetExtension(kExtensionName));
+  if (!extension_api) {
+    return;
+  }
+
+  // Verifications about the global structure instance, if implemented.
+}
+```
+
+If `SbSystemGetExtension` does not return `NULL`, meaning the platform does
+implement the extension, the tests generally verify a few details about the
+structure:
+
+*   It has the expected name.
+*   Its version is in the range of possible versions for the extension.
+*   For whichever version is implemented, any members required for that version
+    are present.
+*   It's a singleton.
+
+### Exercise 3: Test your extension
+
+You guessed it! Add a test for your new extension to
+`cobalt/extension/extension_test.cc`.
+
+Once you've written your test you can execute it to confirm that it passes.
+`cobalt/extension/extension.gyp` configures an `extension_test` target to be
+built from our `extension_test.cc` source file. We can build that target for our
+platform and then run the executable to run the tests.
+
+```
+$ cobalt/build/gyp_cobalt linux-x64x11
+```
+
+```
+$ ninja -C out/linux-x64x11_devel all
+```
+
+```
+$ out/linux-x64x11_devel/extension_test
+```
+
+Tip: because the `extension_test` has type `<(gtest_target_type)`, we can use
+`--gtest_filter` to filter the tests that are run. For example, you can run just
+your newly added test with `--gtest_filter=ExtensionTest.Pleasantry`.
+
+#### Solution to Exercise 3
+
+<details>
+    <summary style="display:list-item">Click here to see a solution for the new
+    test.</summary>
+
+```
+TEST(ExtensionTest, Pleasantry) {
+  typedef CobaltExtensionPleasantryApi ExtensionApi;
+  const char* kExtensionName = kCobaltExtensionPleasantryName;
+
+  const ExtensionApi* extension_api =
+      static_cast<const ExtensionApi*>(SbSystemGetExtension(kExtensionName));
+  if (!extension_api) {
+    return;
+  }
+
+  EXPECT_STREQ(extension_api->name, kExtensionName);
+  EXPECT_GE(extension_api->version, 1u);
+  EXPECT_LE(extension_api->version, 2u);
+
+  EXPECT_NE(extension_api->greeting, nullptr);
+
+  if (extension_api->version >= 2) {
+    EXPECT_NE(extension_api->GetFarewell, nullptr);
+  }
+
+  const ExtensionApi* second_extension_api =
+      static_cast<const ExtensionApi*>(SbSystemGetExtension(kExtensionName));
+  EXPECT_EQ(second_extension_api, extension_api)
+      << "Extension struct should be a singleton";
+}
+```
+
+</details>
+
+You'll also want to include the header for the extension, i.e., `#include
+"cobalt/extension/pleasantry.h"`.
+
+## Contributing a Cobalt Extension
+
+Thanks for taking the time to complete the codelab!
+
+**If you'd like to contribute an actual Cobalt Extension to Cobalt in order to
+add some useful functionality for your platform, we encourage you to start a
+discussion with the Cobalt team before you begin coding.** To do so, please
+[file a feature request](https://issuetracker.google.com/issues/new?component=181120)
+for the extension and include the following information:
+
+*   The name of the Cobalt Extension.
+*   A description of the extension.
+*   Why a Cobalt Extension is the right tool, instead of some alternative.
+*   The fact that you'd like to contribute the extension (i.e., write the code)
+    rather than rely on the Cobalt team to prioritize, plan, and implement it.
+
+Please file this feature request with the appropriate priority and the Cobalt
+team will review the proposal accordingly. If the Cobalt team approves of the
+use case and design then a member of the team will assign the feature request
+back to you for implementation. At this point, please follow the
+<a href="/contributors/index.html">Contributing to Cobalt</a> guide to ensure
+your code is compliant and can be reviewed and submitted.
diff --git a/src/cobalt/site/docs/development/setup-linux.md b/src/cobalt/site/docs/development/setup-linux.md
index 9e40a3e..014394d 100644
--- a/src/cobalt/site/docs/development/setup-linux.md
+++ b/src/cobalt/site/docs/development/setup-linux.md
@@ -63,8 +63,8 @@
 
 ```
 $ cd cobalt
-$ git mv src/* ./
-$ git mv src/.* ./
+$ mv src/* ./
+$ mv src/.* ./
 ```
 
 Once you do that, you'll be able to follow the following two steps to have C++
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/branching.md b/src/cobalt/site/docs/gen/cobalt/doc/branching.md
new file mode 100644
index 0000000..c3b9cd9
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/branching.md
@@ -0,0 +1,98 @@
+---
+layout: doc
+title: "Cobalt Branching"
+---
+# Cobalt Branching
+
+*(This document assumes you are already familiar
+with [Cobalt Versioning][versioning] practices.)*
+
+The Cobalt project uses git branches for two main purposes:
+
+  1. To solidify a release as it is hardened for production.
+  2. To isolate `master` branch developers from risky or disruptive work.
+
+
+## Release Branches
+
+A "Cobalt release" is an official, tested version of Cobalt that is intended to
+be deployable to production. We branch for releases to allow development to
+continue on the `master` branch while stabilizing and finalizing a set of sources
+for release.
+
+
+### Release Timeline
+
+  1. Feature work is done in the `master` branch.
+
+  2. Once all feature work is completed, a release branch is created. The branch
+     will be named "[[Feature Year](versioning.md#Feature-Year)].[[Purpose](versioning.md#Purpose)].[[Update Number](versioning.md#Update-Number)]+".
+     Note that while very similar to the structure of the Cobalt
+     [version](versioning.md), it features a `+` symbol at the end, indicating
+     that the branch may eventually contain multiple release updates,
+     all greater than or equal to the specified update number.  In particular, a
+     single branch may host multiple releases/updates. Should another release
+     branch be cut from master with a pre-existing (feature year, purpose)
+     pair, the new branch will have an update number equivalent to the most
+     recently released update number, plus one.  Note that we expect it to be
+     rare that we will need a branch other than the `1+` branch.
+
+     An example release branch name is `19.lts.1+`.
+
+     An RC announcement will be made to
+     [cobalt-dev@googlegroups.com][cobalt-dev].
+
+     Note that a release branch implies that code on that branch is being
+     stabilized, not that it is ready for release.  Versions of Cobalt that
+     are ready for release will have a dedicated `*.stable` branch pointing to
+     them, and will be discussed later.
+
+  3. As bugs are discovered and feedback received from partners, fixes will be
+     cherry-picked into the release candidate branch. These cherry-picks should
+     not be considered stable again until the `*.stable` branch is updated.
+
+  4. As time goes on, the number of cherry-picks will decrease in number and
+     scope.
+
+  5. Once a commit on the branch is deemed to be feature-complete and stable, it
+     will be tagged with the current [version](versioning.md) for that branch,
+     and the version will be incremented for all subsequent commits.  A special
+     branch that acts more like a "moving tag" named "[[Feature Year](versioning.md#Feature-Year)].[[Purpose](versioning.md#Purpose)].stable"
+     will be created to point to the newly released version.  Should a
+     subsequent update be made for the given feature year and purpose, the
+     `*.stable` branch will be updated to point to the newest update.
+
+     An example stable branch name is `19.lts.stable`.
+
+     Some example release tags are:
+      - `19.lts.1`
+      - `19.lts.2`
+      - `20.lts.1`
+
+     A release announcement will be made
+     to [cobalt-dev@googlegroups.com][cobalt-dev].
+
+
+## Work Branches
+
+If a set of work is deemed to be particularly risky or disruptive, or if a
+serious contributor wants a sandbox to prepare an extensive patch, a work branch
+may be created to facilitate such development.
+
+Work branch names are of the form `work_<topic>`, where `<topic>` is the purpose
+for which the branch was created. Work branches are generally in use by a
+specific and limited set of people, and may disappear at any time.
+
+
+## Older branching schemes
+
+Older branches have been following different branch naming schemes, and for
+a description of those schemes, the version of this branching.md file within
+those branches should be consulted.
+
+## Other Reading
+
+  * [Cobalt Versioning][versioning]
+
+[cobalt-dev]: https://groups.google.com/forum/#!forum/cobalt-dev "cobalt-dev@googlegroups.com"
+[versioning]: versioning.md "Cobalt Versioning"
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/clients_performance_guide.md b/src/cobalt/site/docs/gen/cobalt/doc/clients_performance_guide.md
new file mode 100644
index 0000000..29c3984
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/clients_performance_guide.md
@@ -0,0 +1,172 @@
+---
+layout: doc
+title: "Cobalt Clients Performance Guide"
+---
+# Cobalt Clients Performance Guide
+
+This document contains a list of hints and tricks for using web technologies
+that when employed will result in improved performance of Cobalt client apps.
+
+[TOC]
+
+## Avoid large opacity animations of DOM subtrees.
+
+Be careful when applying the CSS opacity property to DOM subtrees.  When
+applying opacity to a DOM leaf node, the renderer can usually easily render the
+single element the way it normally would, except with an opacity parameter set.
+When rendering a non-trivial multi-subnode DOM subtree though, in order for
+the results to appear correct, the renderer has no choice but to create an
+offscreen surface, render to that surface *without* opacity, and then finally
+render the offscreen surface onto the onscreen surface *with* the set opacity
+applied.
+
+For some examples, suppose we have the following CSS:
+
+```
+<head>
+  <style>
+    .rectangle {
+      position: absolute;
+      width: 100px;
+      height: 100px;
+    }
+    .red {
+      background-color: red;
+    }
+    .green {
+      background-color: green;
+      transform: translate(25px, 25px);
+    }
+    .blue {
+      background-color: blue;
+      transform: translate(50px, 50px);
+    }
+    .half-opacity {
+      opacity: 0.5;
+    }
+  </style>
+</head>
+```
+
+Then when applying opacity to a subtree of 3 cascading rectangles,
+```
+<body>
+  <div class="half-opacity">
+    <div class="rectangle red"></div>
+    <div class="rectangle green"></div>
+    <div class="rectangle blue"></div>
+  </div>
+</body>
+```
+the results will look like this:
+
+![Opacity applied to subtree](resources/clients_performance_guide/opacity_on_subtree.png)
+
+which requires the browser to produce an offscreen surface the size of all three
+rectangles, which can be expensive for performance and memory.
+
+For comparison, when opacity is applied to leaf nodes individually,
+```
+<body>
+  <div>
+    <div class="rectangle red half-opacity"></div>
+    <div class="rectangle green half-opacity"></div>
+    <div class="rectangle blue half-opacity"></div>
+  </div>
+</body>
+```
+the results will look like this:
+
+![Opacity to each element of subtree](resources/clients_performance_guide/opacity_on_individuals.png)
+
+which is less expensive because each rectangle can be rendered directly with
+the specified opacity value.
+
+The problem in the first case where opacity is applied to the subtree is that
+switching render targets to and from an offscreen surface is time consuming
+for both the CPU and GPU, and can on some platforms noticeably slow down
+performance, likely manifesting as a lower framerate in animations.  While it is
+possible that Cobalt may cache the result, it is not guaranteed, and may not be
+possible if the subtree is being animated.  Additionally, the offscreen surface
+will of course consume memory that wouldn't have been required otherwise.
+
+### Similar situations
+
+While opacity tends to be the most common instigator of the behavior described
+above, there are other situations that can trigger offscreen surface usage.
+They are:
+
+ - Setting `overflow: hidden` on a rotated subtree parent element (e.g. via
+   `transform: rotate(...)`)
+ - Setting `overflow: hidden` on a subtree parent element with rounded corners.
+
+## Explicitly set Image src attributes to '' when finished with them.
+
+Cobalt maintains an image cache with a preset capacity (e.g. default of 32MB on
+platforms with 1080p UIs, but it can be customized).  When an image goes out
+of scope and is no longer needed, instead of leaving it up to the garbage
+collector to decide when an image should be destroyed and its resources
+released, it is recommended that Image objects have their `src` attribute
+explicitly cleared (i.e. set to `''`) when they are no longer needed, so
+that Cobalt can reclaim the image resources as soon as possible.
+
+## Be conservative with usage of the border-radius CSS property.
+
+While Cobalt has significant optimizations in place for handling the rendering
+of rounded corners, it still requires significantly more sophistication and
+processing than rendering a normal rectangle.  This applies to a number of
+different scenarios, such as using rounded corners on elements with either
+background-color or background-image.  Particularly expensive however would
+be to apply rounded corners on a parent node which has `overflow: hidden` set
+(as mentioned above), since this requires the creation of an offscreen surface.
+
+## Avoid large (e.g. fullscreen) divs
+
+The more screen area that is covered by DOM elements, the more work the GPU has
+to do, and so the lower the framerate will be.  For example, if a background
+is desired, instead of creating a new fullscreen `<div>`, set the
+desired background color or image on the `<body>` element which will cover the
+display anyway.  Otherwise, the `<body>` element will render its background, and
+then the `<div>` element will render over top of it (Cobalt is not smart enough
+to know if an element completely coveres another element), resulting in more
+pixels being touched than is necessary.
+
+This type of optimization is related to the concept of "overdraw" from computer
+graphics.  A good definition for overdraw can be found at
+[https://developer.android.com/topic/performance/rendering/overdraw](https://developer.android.com/topic/performance/rendering/overdraw):
+
+> "Overdraw refers to the system's drawing a pixel on the screen multiple times
+>  in a single frame of rendering. For example, if we have a bunch of stacked
+>  UI cards, each card hides a portion of the one below it... It manifests
+>  itself as a performance problem by wasting GPU time to render pixels that
+>  don't contribute to what the user sees on the screen."
+
+The `<body>` element will always result in the display being filled with a
+color, which is `rgba(0, 0, 0, 0)` by default.  Since `<body>` already
+guarantees a full screen draw, the most optimal way of specifying a
+background is to modify `<body>`'s background properties instead of adding
+a layer on top of it.
+
+## Blitter optimizations
+
+If the platform's user agent string contains "blitter", then the platform uses
+the Blitter API for rendering. This device is much more limited in what it can
+render natively, and many complex geometry will require software rendering.
+This means the CPU creates a texture and calculates the color of each pixel in
+that texture. The following things trigger the software rendering path (i.e.
+uses extra memory and is slow) on platforms using the Blitter API:
+
+ - Text.
+ - Rounded corners.
+ - Borders of different sizes. If borders are to be used, then all borders
+   should have the same properties. (And avoid rounded corners.)
+ - Linear gradients which are not exactly vertical or horizontal (i.e. gradients
+   at an angle).
+ - Radial gradients.
+ - Shadows.
+ - Multi-plane images. JPEG images tend to decode into multi-plane images.
+   Prefer using PNG images instead -- these tend to be decoded into RGBA which
+   blitter can handle natively.
+ - Using part of a background image. For example, using background-position may
+   result in extra memory usage, or using a background image inside an
+   `overflow: hidden` element that is shifted or has rounded corners.
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/device_authentication.md b/src/cobalt/site/docs/gen/cobalt/doc/device_authentication.md
new file mode 100644
index 0000000..f1513a9
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/device_authentication.md
@@ -0,0 +1,51 @@
+---
+layout: doc
+title: "Device Authentication"
+---
+# Device Authentication
+
+Starting in Cobalt 20, initial URL requests will now have query parameters
+appended to them signed by the platform's secret key.  The key is provided during
+the certification process.  The key must be stored in secure storage on the
+device.
+
+## Message
+
+When constructing the URL for the initial browse request, according to the
+logic in
+[cobalt/browser/device_authentication.cc](../browser/device_authentication.cc),
+it will fetch from the platform a "certification scope" string provided to
+the device during certification.  The certification scope will be queried
+by a call to `SbSystemGetProperty(kSbSystemPropertyCertificationScope, ...)`,
+which the platform is expected to implement.  Along with the current system
+time, this forms the message that must be signed by the device's secret key.
+
+## Signing
+
+The message defined above must be signed with the HMAC-SHA256 algorithm. The
+resulting digest (encoded as base64), alongside the unencrypted message
+contents, will be appended to the initial URL.
+
+Two choices exists for how platforms can expose the secret key to Cobalt.
+Cobalt will first attempt to have the platform sign the message, and if that
+functionality is not implemented Cobalt will query the platform for the secret
+key and sign the message itself.  If neither choice is implemented, then Cobalt
+will log a warning and not append anything to the URL.
+
+### Platform signing
+
+Cobalt will first attempt to use the `SbSystemSignWithCertificationSecretKey()`
+function to sign the message using the secret key.  This method is preferred
+since it enables implementations where the key exists only in secure hardware
+and never enters the system's main memory.  A reference implementation, which
+depends on BoringSSL exists at
+[starboard/linux/x64x11/internal/system_sign_with_certification_secret_key.cc](../../starboard/linux/x64x11/internal/system_sign_with_certification_secret_key.cc).
+
+### Cobalt signing
+
+If the function `SbSystemSignWithCertificationSecretKey()` is unimplemented (e.g. it returns `false`, as is done in
+[starboard/shared/stub/system_sign_with_certification_secret_key.cc](../../starboard/shared/stub/system_sign_with_certification_secret_key.cc)),
+then Cobalt will instead attempt to retrieve the secret key from the system by
+a call to
+`SbSystemGetProperty(kSbSystemPropertyBase64EncodedCertificationSecret, ...)`,
+and use it to produce the HMAC-SHA256 digest of the message itself.
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/docker_build.md b/src/cobalt/site/docs/gen/cobalt/doc/docker_build.md
new file mode 100644
index 0000000..450693f
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/docker_build.md
@@ -0,0 +1,70 @@
+---
+layout: doc
+title: "Cobalt Docker builds"
+---
+# Cobalt Docker builds
+
+Cobalt includes [Docker image][docker.com](https://www.docker.com/)
+definitions for simplifying managing build environments.
+
+The instructions below assume Docker is installed and is able to run basic
+[`hello-world` verification](https://docs.docker.com/get-started/#test-docker-installation).
+`docker-compose` command is expected to be available as well.
+
+## Usage
+
+The simplest usage is:
+
+  `docker-compose run <platform>`
+
+By default, a debug build will be built, with `cobalt` as a target.
+You can override this with an environment variable, e.g.
+
+  `docker-compose run -e CONFIG=devel -e TARGET=nplb <platform>`
+
+where config is one of the four optimization levels, debug, devel, qa and gold,
+and target is the build target passed to `ninja`
+
+See [Cobalt README](../../README.md#build-types)
+for full details.
+
+Builds will be available in your `${COBALT_SRC}/out` directory.
+
+NB! Note that Docker runs processes as root user by default, hence output
+files in `src/out/<platform>` directory have `root` as file owner.
+
+## Customization
+
+To parametrize base operating system images used for the build, pass BASE_OS
+as an argument to docker-compose as follows:
+
+  `docker-compose build --build-arg BASE_OS="ubuntu:bionic" base`
+
+This parameter is defined in `docker/linux/base/Dockerfile` and is passed to
+Docker `FROM ...` statement.
+
+Available parameters for customizing container execution are:
+
+ - **BASE_OS**: passed to `base` image at build time to select a Debian-based
+    base os image and version. Defaults to Debian 9. `ubuntu:bionic` and
+    `ubuntu:xenial` are other tested examples.
+ - **PLATFORM**: Cobalt build platform, passed to GYP
+ - **CONFIG**: Cobalt build config, passed to GYP. Defaults to `debug`
+ - **TARGET**: Build target, passed to `ninja`
+
+The `docker-compose.yml` contains the currently defined experimental build
+configurations. Edit or add new `service` entries as needed, to build custom
+configurations.
+
+## Pre-built images
+
+Note: Pre-built images from a public container registry are not yet available.
+
+## Troubleshooting
+
+To debug build issues, enter the shell of the corresponding build container by
+launching the bash shell, i.e.
+
+  `docker-compose run linux-x64x11 /bin/bash`
+
+and try to build cobalt [with the usual `gyp / ninja` flow](../../README.md#building-and-running-the-code).
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/lifecycle.md b/src/cobalt/site/docs/gen/cobalt/doc/lifecycle.md
new file mode 100644
index 0000000..6b22ee0
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/lifecycle.md
@@ -0,0 +1,244 @@
+---
+layout: doc
+title: "Application Lifecycle"
+---
+# Application Lifecycle
+
+In order to meet common needs of applications running on CE devices, Cobalt
+implements a well-defined web application lifecycle, managing resources and
+notifying the application as appropriate.
+
+## Summary of changes in Cobalt 22
+
+The application lifecycle has some changes from Cobalt 22:
+
+### States:
+
+* The *Paused* state is renamed to *Blurred*.
+* The *Suspended* state is replaced by *Concealed* and *Frozen*.
+* The *Preloading* state is removed, and *Concealed* is used instead.
+  Note: The corresponding attribute value 'prerender' for
+  document.visibilityState is also removed.
+
+The new *Concealed* state is used for applications that are not visible but may
+use CPU or network resources. This state is used to both replace the
+*Preloading* state, and as an intermediate state between *Blurred* and
+*Frozen*.
+
+The *Frozen* state most closely resembles the previous *Suspended* state,
+during which applications do not have network access.
+
+### State Changes:
+
+* The *Pause* event is renamed to *Blur*.
+* The *Unpause* event is renamed to *Focus*.
+* The *Suspend* event is replaced by *Conceal* and *Freeze*.
+* The *Resume* event is replaced by *Unfreeze* and *Reveal*.
+
+Most platforms should only need to replace 'Pause' with 'Blur', 'Unpause' with
+'Focus', 'Suspend' with 'Freeze', and 'Resume' with 'Reveal'.
+
+Since there is no longer a special *Preloading* state, applications should no
+longer use the *Start* event when a preloaded application is brought to the
+foreground. Instead, the same event(s) used for backgrounded applications
+(*Concealed* or *Frozen*) should be used.
+
+### Application 'Backgrounding' and 'Foregrounding'.
+
+To signal that the application is being 'backgrounded', the use of *Suspend*
+should be replaced with *Freeze*.
+
+To signal that the application is being 'foregrounded', the use of *Unpause*
+should be replaced with *Focus*.
+
+Note: If a platform is using *Resume* (*Reveal*) to signal that an application
+is being 'foregrounded', then that may result in unexpected application
+behavior, unless a subsequent *Unpause* (*Focus*) is also used when the
+application receives input focus.
+
+More details about lifecycle states and state changes can be found in
+`src/starboard/event.h`.
+
+### Deprecated `SbEventType` values.
+
+The `SbEventType` enum is defined in `src/starboard/event.h`.
+
+* The `kSbEventTypePause` value is renamed to `kSbEventTypeBlur`.
+* The `kSbEventTypeUnpause` value is renamed to `kSbEventTypeFocus`.
+* The `kSbEventTypeSuspend` value is replaced by `kSbEventTypeConceal` and
+  `kSbEventTypeFreeze`.
+* The `kSbEventTypeResume` value is replaced by `kSbEventTypeUnfreeze` and
+  `kSbEventTypeReveal`.
+
+The corresponding helper functions in
+`starboard::shared::starboard::Application` (implemented in
+`starboard/shared/starboard/application.cc`) that inject events with these
+values have been updated correspondingly:
+
+* The `Pause()` method is renamed to `Blur()`.
+* The `Unpause()` method is renamed to `Focus()`.
+* The `Suspend()` method is replaced by `Conceal()` and
+  `Freeze()`.
+* The `Resume()` method is replaced by `Unfreeze()` and
+  `Reveal()`.
+
+Platforms that inject events themselves should be updated to use renamed event
+type values, and platforms that use the helper functions should be updated to
+call the corresponding renamed helper functions.
+
+### Deprecated `SbSystemRequest` functions.
+
+The `SbSytemRequest` functions are declared in `src/starboard/system.h`
+
+* The `SbSystemRequestPause` event is renamed to `SbSystemRequestBlur`
+* The `SbSystemRequestUnpause` event is renamed to `SbSystemRequestFocus`
+* The `SbSystemRequestSuspend` event is replaced by `SbSystemRequestConceal`
+  and `SbSystemRequestFreeze`
+* The `SbSystemRequestResume` event is replaced by `SbSystemRequestUnfreeze`
+  and `SbSystemRequestReveal`
+
+## Application States
+
+Starboard Application State | Page Visibility State | Window Focused
+:-------------------------- | :-------------------- | :-------------
+*Started*                   | visible               | true
+*Blurred*                   | visible               | false
+*Concealed*                 | hidden                | false
+*Frozen*                    | hidden                | false
+
+When transitioning between *Concealed* and *Frozen*, the document.onfreeze and
+document.onresume events from the Page LifeCycle Web API will be dispatched.
+
+### Started
+
+The application is running, visible, and interactive. The normal foreground
+application state. May be the start state, or can be entered from *Blurred*.
+
+May only transition to *Blurred*. In Linux desktop, this happens anytime the
+top-level Cobalt X11 window loses focus. Linux transition back to *Started*
+when the top-level Cobalt X11 window gains focus again.
+
+### Blurred
+
+The application may be fully visible, partially visible, or completely
+obscured, but it has lost input focus, so will receive no input events. It has
+been allowed to retain all its resources for a very quick return to *Started*,
+and the application is still running. May be entered from or transition to
+*Started* or *Concealed* at any time.
+
+### Concealed
+
+The application is not visible and will receive no input, but is running. Can
+be entered as the start state. May be entered from or transition to *Blurred*
+or *Frozen* at any time. The application may be terminated in this state
+without notification.
+
+Upon entering, all graphics resources will be revoked until revealed, so the
+application should expect all images to be lost, and all caches to be cleared.
+
+#### Expectations for the web application
+
+The application should **shut down** playback, releasing resources. On resume,
+all resources need to be reloaded, and playback should be reinitialized where
+it left off, or at the nearest key frame.
+
+### Frozen
+
+The application is not visible and will receive no input, and, once *Frozen*,
+will not run any code. May be entered from or transition to *Concealed* at any
+time. The application may be terminated in this state without notification.
+
+Upon entering, all graphics and media resources will be revoked until resumed,
+so the application should expect all images to be lost, all caches to be
+cleared, and all network requests to be aborted.
+
+#### Expectations for the porter
+
+Currently, Cobalt does not manually stop JavaScript execution when it goes into
+the *Frozen* state. In Linux desktop, it expects that a `SIGSTOP` will be
+raised, causing all the threads not to get any more CPU time until resumed.
+This will be fixed in a future version of Cobalt.
+
+### Application Startup Expectations for the porter
+
+The starboard application lifecycle, with descriptions of the states and the
+state changes can be found in `src/starboard/event.h`.
+
+For applications that can be preloaded, the platform should send
+`kSbEventTypePreload` as the first Starboard event instead of
+`kSbEventTypeStart`. Subclasses of
+`src/starboard/shared/starboard/application.cc` can opt-in to use the already
+implemented support for the `--preload` command-line switch.
+
+If started with `kSbEventTypePreload`, the platform can at any time send
+`kSbEventTypeFocus` when the application brought to the foreground.
+In Linux desktop (linux-x64x11), this can be done by sending a `SIGCONT` to the
+process that is in the *Preloading* state (see
+`starboard/shared/signal/suspend_signals.cc`)
+
+If the platform wants to only give applications a certain amount of time to
+preload, they can send `SbSystemRequestFreeze` to halt preloading and move to
+the *Frozen* state. In Linux desktop, this can be done by sending SIGUSR1 to
+the process that is in the *Preloading* state.
+
+## Implementing the Application Lifecycle (for the porter)
+
+The platform Starboard implementation **must always** send events in the
+prescribed order - meaning, for example, that it should never send a
+`kSbEventTypeConceal` event unless in the *Blurred* state.
+
+Most porters will want to subclass either `starboard::shared::Application` (in
+`src/starboard/shared/starboard/application.cc`) or
+`starboard::shared::QueueApplication` (in
+`src/starboard/shared/starboard/queue_application.cc`), as these are reference
+classes that rigorously implement the Starboard application lifecycle. They are
+optional, and platforms can directly dispatch events to SbEventHandle(), but it
+is then up to them to ensure that events are **always** sent in the correct
+state as specified in the Starboard documentation.
+
+`starboard::shared::Application` (in
+`starboard/shared/starboard/application.cc`) guarantees the correct ordering by
+implementing a small state machine that ignores invalid application state
+transitions, and inserts any necessary transitions to make them valid. For
+example, you can call `starboard::shared::Application::Conceal()`, and if you
+are in *Blurred*, it will just dispatch a `kSbEventTypeConceal` event. But if
+you call `Conceal()` in the *Started* state, it will first dispatch
+`kSbEventTypeBlur`, followed by a `kSbEventTypeConceal` event. If you call
+`Conceal()` in the *Concealed* state, it just does nothing.
+
+This behavior can be ensured by only dispatching events to SbEventHandle()
+using `Application::DispatchAndDelete()` either directly, or indirectly such
+as by using `Application::RunLoop()` with the default implementation of
+`Application::DispatchNextEvent()`.
+
+To control starting up in the *Concealed* state for preloading, `Application`
+subclasses must override two functions:
+
+``` c++
+class MyApplication : public shared::starboard::QueueApplication {
+  // [ ... ]
+  bool IsStartImmediate() override;
+  bool IsPreloadImmediate() override;
+  // [ ... ]
+}
+```
+
+To start up in the *Concealed* state, `IsStartImmediate()` should return
+`false` and `IsPreloadImmediate()` should return `true`.
+
+To start up in the *Starting* state (which is the default), `IsStartImmediate()`
+should return `true` and `IsPreloadImmediate()` will not be called.
+
+To delay starting up until some later event, `IsStartImmediate()` and
+`IsPreloadImmediate()` should both return `false`. No initial event will be
+automatically sent to the application, and it is then up to the porter to
+dispatch a `kSbEventTypeStart` or `kSbEventTypePreload` event as the first
+event. This is useful if you need to wait for an asynchronous system activity to
+complete before starting Cobalt.
+
+To support the `--preload` command-line argument:
+
+``` c++
+  bool IsStartImmediate() override { return !HasPreloadSwitch(); }
+  bool IsPreloadImmediate() override { return HasPreloadSwitch(); }
+```
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/memory_tuning.md b/src/cobalt/site/docs/gen/cobalt/doc/memory_tuning.md
new file mode 100644
index 0000000..a053b40
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/memory_tuning.md
@@ -0,0 +1,329 @@
+---
+layout: doc
+title: ""
+---
+# Memory Tuning #
+
+Cobalt is designed to choose sensible parameters for memory-related options and
+parameters through a system called "AutoMem".
+
+On startup, AutoMem will print a memory table to the output console detailing
+the memory allocations that will be assigned to the various subsystems in
+cobalt.
+
+As an example, at the cost of performance you can reduce CPU memory on your
+platform by 5MB and GPU memory usage on your platform by 10MB using these
+command line flags:
+
+`cobalt --reduce_cpu_memory_by=5MB --reduce_gpu_memory_by=10MB`
+
+Some settings will be "fixed" while others will be "flexible" so that their
+memory consumption will scale down for memory constrained platforms.
+
+Read on for more information.
+
+**IMPORTANT**
+*Setting `--max_cobalt_cpu_usage` and `--max_cobalt_gpu_usage` on the
+command line is a beta feature. When reducing memory, please use
+`--reduce_cpu_memory_by` and `--reduce_gpu_memory_by`.*
+
+### Memory Settings Table ###
+
+A table similar to the one below, will be printed on startup.
+
+~~~
+AutoMem:
+
+ SETTING NAME                           VALUE                    TYPE   SOURCE
+ ________________________________________________________________________________
+|                                      |             |          |      |         |
+| image_cache_size_in_bytes            |    33554432 |  32.0 MB |  GPU | AutoSet |
+|______________________________________|_____________|__________|______|_________|
+|                                      |             |          |      |         |
+| javascript_gc_threshold_in_bytes     |     8388608 |   8.0 MB |  CPU |   Build |
+|______________________________________|_____________|__________|______|_________|
+|                                      |             |          |      |         |
+| misc_cobalt_cpu_size_in_bytes        |   124780544 | 119.0 MB |  CPU | AutoSet |
+|______________________________________|_____________|__________|______|_________|
+|                                      |             |          |      |         |
+| misc_cobalt_gpu_size_in_bytes        |    25165824 |  24.0 MB |  GPU | AutoSet |
+|______________________________________|_____________|__________|______|_________|
+|                                      |             |          |      |         |
+| remote_typeface_cache_size_in_bytes  |     4194304 |   4.0 MB |  CPU |   Build |
+|______________________________________|_____________|__________|______|_________|
+|                                      |             |          |      |         |
+| skia_atlas_texture_dimensions        | 4096x8192x2 |  64.0 MB |  GPU |   Build |
+|______________________________________|_____________|__________|______|_________|
+|                                      |             |          |      |         |
+| skia_cache_size_in_bytes             |     4194304 |   4.0 MB |  GPU |   Build |
+|______________________________________|_____________|__________|______|_________|
+|                                      |             |          |      |         |
+| software_surface_cache_size_in_bytes |         N/A |      N/A |  N/A |     N/A |
+|______________________________________|_____________|__________|______|_________|
+
+~~~
+This table shows the breakdown of how much memory is being allocated to each
+sub-system, the type, and where it came from.
+
+**SETTING NAME:** This is the name of the memory setting. If a setting can be
+manually set through the command line or the build system, then it will be
+accessible by using this name. For example adding the command line argument
+`--image_cache_size_in_bytes=25165824` will manually set the Image Cache Size to
+24 megabytes. Also note that this is also equivalent:
+`--image_cache_size_in_bytes=24MB`. Note that the numerical value can include
+the suffix kb/mb/gb to specify kilo/mega/giga-bytes. The numerical value can
+be a floating point value. For example `--image_cache_size_in_bytes=.1GB` is
+equivalent to `--image_cache_size_in_bytes=100MB`.
+
+**VALUE:** This two column value has a first setting that describes what the
+actual value is, and the second column is the amount of memory that the setting
+consumes. This first setting gives hints on what kind of values the
+setting can be set to via the command line. For example,
+`skia_atlas_texture_dimensions` accepts texture sizes on the command line, such
+as: `--skia_atlas_texture_dimensions=2048x4096x2`
+
+**TYPE:** This specifies whether the setting consumes GPU or CPU memory.
+For example, the Image Cache will decode images to buffers to the GPU memory
+and therefore it is the classified as the GPU memory type.
+
+**SOURCE:** This specifies where the memory setting came from. It will either
+be set from a specific place or automatically generated from Cobalt.
+  * Values for **SOURCE**:
+    * `Starboard API`
+      * The value used was reported by the result of a Starboard API function call.
+      * Example: `SbSystemGetUsedCPUMemory()`
+    * `Build`
+      * Specified by the platform specific `*.gyp(i)` build file.
+      * For example: see `image_cache_size_in_bytes` in [`build/config/base.gypi`](../build/config/base.gypi)
+    * `CmdLine`
+      * Read the memory setting value from the command line.
+      * For example: `cobalt --image_cache_size_in_bytes=24MB`.
+    * `AutoSet`
+      * No value was specified and therefore Cobalt calculated the default value
+	    automatically based on system parameters. For example many caches
+		will be chosen proportionally to the size of the UI resolution.
+    * `AutoSet (Constrained)`
+      * This value was AutoSet to a default value, but then was reduced in
+      response to `max_cobalt_cpu_usage` or `max_cobalt_gpu_usage being` set too low.
+      This will also trigger in response to `reduce_cpu_memory_by` or
+      `reduce_cpu_memory_by` being set. See "Memory Scaling" section below.
+
+### Maximum Memory Table ###
+
+This second table is also printed at startup and details the sum of memory and
+maximum memory limits as reported by cobalt.
+
+~~~
+ MEMORY                 SOURCE          TOTAL      SETTINGS CONSUME
+ ____________________________________________________________________
+|                      |               |          |                  |
+| max_cobalt_cpu_usage | Starboard API | 256.0 MB |         131.0 MB |
+|______________________|_______________|__________|__________________|
+|                      |               |          |                  |
+| max_cobalt_gpu_usage | Starboard API | 768.0 MB |         124.0 MB |
+|______________________|_______________|__________|__________________|
+~~~
+
+This table shows the limits for CPU and GPU memory consumption and also how
+much memory is being consumed for each memory type.
+
+**MEMORY**: This is the name of the memory limit. If you want to change this
+setting manually then use the name on the command line. For example
+`--max_cobalt_cpu_usage=150MB` will set Cobalt to 150MB limit for CPU
+memory. If the sum of CPU memory exceeds this limit then memory settings of the
+same type will reduce their memory usage.
+
+**SOURCE**: This value indicates where the value came from.
+ * `Starboard API`
+   * `max_cobalt_cpu_usage`: This value was found from SbSystemGetTotalCPUMemory().
+   * `max_cobalt_gpu_usage`: This value was found from SbSystemGetTotalGPUMemory().
+ * `CmdLine`
+   * `max_cobalt_cpu_usage`: --max_cobalt_cpu_usage was used as a command argument.
+   * `max_cobalt_gpu_usage`: --max_cobalt_gpu_usage was used as a command argument.
+ * `Build`
+   * `max_cobalt_cpu_usage`: max_cobalt_cpu_usage was specified in a platform gyp file.
+   * `max_cobalt_gpu_usage`: max_cobalt_gpu_usage was specified in a platform gyp file.
+
+**TOTAL**: Represents the maximum available memory for settings. This value
+came from **SOURCE**.
+
+**SETTINGS CONSUME**: This value indicates the consumption of memory for the
+current memory type.
+
+For `max_cobalt_cpu_usage`, `Starboard API` indicates that this value came from
+`SbSystemGetTotalCPUMemory()`  If this source value is `Starboard API` then this
+value came from `SbSystemGetTotalCPUMemory()` (for CPU) or
+`SbSystemGetTotalGPUMemory()` for GPU).
+
+If the available memory for the Cobalt is less than the amount of memory
+consumed by the settings, then any settings that are AutoSet AND adjustable
+will reduce their memory consumption. When this happens, look for the string
+*`AutoSet (Constrained)`* in the first table.
+
+## Setting Maximum Memory Values ##
+
+The max cpu and gpu memory of the system can be set either by command line or
+by modifying the gyp build file.
+
+Command Line:
+  * `--max_cobalt_cpu_usage=160MB`
+  * `--max_cobalt_gpu_usage=160MB`
+
+Build settings:
+  * `starboard/<PLATFORM>/gyp_configuration.gypi`
+    * `max_cobalt_cpu_usage`
+    * `max_cobalt_gpu_usage`
+
+Command Line settings will override build settings.
+
+### Memory Scaling ###
+
+There are two primary ways in which the memory consumption settings will scale down.
+One is by specifying `--max_cobalt_cpu_usage` (or `max_cobalt_gpu_usage`) to a
+particular value (e.g. `--max_cobalt_cpu_usage=160MB`).
+
+`--max_cobalt_cpu_usage` (and `--max_cobalt_gpu_usage`) will trigger the memory
+to scale down whenever the memory settings memory consumption exceed the maximum
+**TOTAL** value. The memory settings will be scaled down until their consumption is
+less than or equal the maximum allowed value **TOTAL**. See also **SETTINGS CONSUME**.
+
+Another way to scale down the memory size is by passing the flags
+`--reduce_cpu_memory_by=XX` and `--reduce_gpu_memory_by=XX` which will:
+1) Ignore the `--max_cobalt_cpu_usage` and `--max_cobalt_gpu_usage`.
+2) Use the current memory consumption of the settings and then reduce that by
+   the amount.
+
+For example, if cobalt uses 160MB of CPU memory then passing in
+`--reduce_cpu_memory_by=10MB` to the command line will attempt to reduce the
+footprint of cobalt by 10MB to 150MB. Note that this reduction is an an attempt,
+and it's possible this attempt will fail if the memory reduction is too aggressive
+or if memory settings have been explicitly set via the build or command line.
+
+*Forcing a Memory Setting to be flexible*
+
+If a memory setting is set via a build setting, then it's possible to make it
+flexible via the command line by setting the value to "autoset". For example,
+ `--image_cache_size_in_bytes=auto` will allow `image_cache_size_in_bytes` to be
+flexible by disabling the value being set by a build setting.
+
+### Memory Warnings ###
+
+Cobalt will periodically check to see if the memory consumed by the application
+is less than the `--max_cobalt_cpu_usage` and `--max_cobalt_gpu_usage` amount.
+If the cpu/gpu exceeds this maximum value then an error message will be logged
+once to stdout for cpu and/or gpu memory systems.
+
+
+### Example 1 - Configuring for a memory restricted platform ###
+
+Let's say that we are configuring platform called "XXX":
+
+We will configure XXX such that:
+  * `image_cache_size_in_bytes` will be set to 32MB in the build settings.
+  * `skia_atlas_texture_dimensions` will be set to `2048x2048x2` in the build settings.
+  * `max_cobalt_cpu_usage` will be set to 160MB on the command line.
+
+**Configuring `image_cache_size_in_bytes` to be 32MB:**
+  * in `starboard\<PLATFORM>\gyp_configuration.gypi`
+    * add `'image_cache_size_in_bytes': 32 * 1024 * 1024,`
+
+**Configuring `skia_atlas_texture_dimensions` to be 2048x2048x2:**
+
+  * in `src\starboard\XXX\gyp_configuration.gypi`
+    * add `'skia_glyph_atlas_width': '2048'`
+    * add `'skia_glyph_atlas_height': '2048'`
+    * (note that the third dimension is assumed)
+
+**Configuring `max_cobalt_cpu_usage` to be 160MB:**
+
+  * `cobalt --max_cobalt_cpu_usage=160MB`
+
+### Example 2 - Configuring for a memory-plentiful platform ###
+
+The following command line will give a lot of memory to image cache and give
+500MB to `max_cobalt_cpu_usage` and `max_cobalt_gpu_usage`.
+
+~~~
+cobalt --max_cobalt_cpu_usage=500MB --max_cobalt_gpu_usage=500MB
+--image_cache_size_in_bytes=80MB
+~~~
+
+## API Reference ##
+
+#### Memory System API ####
+
+  * `max_cobalt_cpu_usage`
+    * This setting will set the maximum cpu memory that the app will consume.
+      CPU Memory settings will scale down their consumption in order to stay under
+      the `max_cobalt_cpu_usage`. If memory consumption exceeds this value during
+      runtime then a memory warning will be printed to stdout.
+    * Set via command line or else build system or else starboard.
+      * starboard value will bind to `SbSystemGetTotalCPUMemory()`.
+  * `max_cobalt_gpu_usage`
+    * This setting will set the maximum gpu memory that the app will consume.
+      GPU Memory settings will scale down their consumption in order to stay under
+      the `max_cobalt_gpu_usage`. If memory consumption exceeds this value during
+      runtime then a memory warning will be printed to stdout.
+    * Set via command line or else build system or else starboard.
+      * starboard value will bind to `SbSystemGetTotalGPUMemory()`.
+    * Note that `SbSystemGetTotalGPUMemory()` is optional. If no value exists
+      for `max_cobalt_gpu_usage` in build/commandline/starboard settings then no
+      GPU memory checking is performed.
+  * `reduce_cpu_memory_by`
+    * This setting will trigger CPU memory consumption to be reduced by the amount
+      specified. *This overrides the memory scaling behavior of `max_cobalt_cpu_usage`*.
+      But this will not affect memory checking of `max_cobalt_cpu_usage` otherwise.
+    * Set via command line or else the platform gyp build file.
+  * `reduce_cpu_memory_by`
+    * This setting will trigger GPU memory consumption to be reduced by the amount
+      specified. *This overrides the memory scaling behavior of `max_cobalt_gpu_usage`*.
+      But this will not affect memory checking of `max_cobalt_gpu_usage` otherwise.
+    * Set via command line or else the platform gyp build file.
+
+#### Memory Setting API ####
+
+  * `image_cache_size_in_bytes`
+    * See documentation *Image cache capacity* in `performance_tuning.md` for what
+      this setting does.
+    * Set via command line, or else build system, or else automatically by Cobalt.
+  * `javascript_gc_threshold_in_bytes`
+    * See documentation *Garbage collection trigger threshold* in `performance_tuning.md`
+      for what this setting does.
+    * Set via command line, or else build system, or else automatically by Cobalt.
+  * `remote_typeface_cache_size_in_bytes`
+    * Determines the capacity of the remote typefaces cache which manages all typefaces
+      downloaded from a web page.
+    * Set via command line, or else build system, or else automatically by Cobalt.
+  * `skia_atlas_texture_dimensions`
+    * Determines the size in pixels of the glyph atlas where rendered glyphs are
+      cached. The resulting memory usage is 2 bytes of GPU memory per pixel.
+      When a value is used that is too small, thrashing may occur that will
+      result in visible stutter. Such thrashing is more likely to occur when CJK
+      language glyphs are rendered and when the size of the glyphs in pixels is
+      larger, such as for higher resolution displays.
+      The negative default values indicates to the Cobalt that these settings
+      should be automatically set.
+    * Set via command line, or else build system, or else automatically by Cobalt.
+    * Note that in the gyp build system, this setting is represented as two values:
+      * `skia_glyph_atlas_width` and
+      * `skia_glyph_atlas_height`
+  * `skia_cache_size_in_bytes`
+    * See documentation *Glyph atlas size* in `performance_tuning.md` for what this
+      setting does.
+    * Set via command line, or else build system or else automatically by Cobalt.
+  * `software_surface_cache_size_in_bytes`
+    * See documentation *Scratch Surface cache capacity* in `performance_tuning.md`
+      for what this setting does.
+    * Set via command line, or else build system, or else automatically by Cobalt.
+
+#### Units for Command Line Settings ####
+
+Memory values passed into Cobalt via command line arguments support units such
+kb, mb, and gb for kilo-byte, megabyte, gigabytes. These units are case insensitive.
+
+For example, these are all equivalent on the command line:
+
+`--image_cache_size_in_bytes=67108864`
+`--image_cache_size_in_bytes=65536kb`
+`--image_cache_size_in_bytes=64mb`
+`--image_cache_size_in_bytes=.0625gb`
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/net_log.md b/src/cobalt/site/docs/gen/cobalt/doc/net_log.md
new file mode 100644
index 0000000..17410f7
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/net_log.md
@@ -0,0 +1,34 @@
+---
+layout: doc
+title: "Cobalt NetLog"
+---
+# Cobalt NetLog

+

+Chromium has a very useful network diagnostic tool called the NetLog and Cobalt

+is hooked up to use it. It's the main tool to track network traffic and debug

+network code.

+

+### Activate the NetLog

+

+The following command line switch will activate the NetLog and store net log

+record to the specified location.

+`./cobalt --net_log=/PATH/TO/YOUR_NETLOG_NAME.json`

+The output json file will be stored at the file location you choose.

+

+

+### Read the NetLog records

+

+The produced json file is not human-friendly, use the

+[NetLog Viewer](https://netlog-viewer.appspot.com/#import)

+

+Cobalt's net_log can not enable some features in the web viewer, but all the

+network traffic is recorded in the event tab.

+

+

+### Add NetLog entries

+

+To Add NetLog entry, get the NetLog instance owned by NetworkModule to where you

+want to add entries and start/end your entry according to the NetLog interface.

+

+A NetLog object is created at each NetworkModule initialization and is passed

+into Chromium net through URLRequestContext.

diff --git a/src/cobalt/site/docs/gen/cobalt/doc/performance_tuning.md b/src/cobalt/site/docs/gen/cobalt/doc/performance_tuning.md
new file mode 100644
index 0000000..72118e7
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/performance_tuning.md
@@ -0,0 +1,393 @@
+---
+layout: doc
+title: "Performance Tuning"
+---
+# Performance Tuning
+
+Cobalt is designed to choose sensible parameters for all performance-related
+options and parameters, however sometimes these need to be explicitly set
+to allow Cobalt to run optimally for a specific platform.  This document
+discusses some of the tweakable parameters in Cobalt that can have an
+affect on performance.
+
+A number of tweaks are listed below in no particular order.  Each item
+has a set of tags keywords to make it easy to search for items related
+to a specific type of performance metric (e.g. "framerate").
+
+Many of the tweaks involve adding a new gyp variable to your platform's
+`gyp_configuration.gypi` file.  The default values for these variables are
+defined in either
+[`base_configuration.gypi`](../../starboard/build/base_configuration.gypi) or
+[`cobalt_configuration.gypi`](../build/cobalt_configuration.gypi).
+
+### Use a Release Build
+
+Cobalt has a number of different build configurations (e.g. "debug", "devel",
+"qa" and "gold" in slowest-to-fastest order), with varying degrees of
+optimizations enabled.  For example, while "devel" has compiler optimizations
+enabled, it does not disable DCHECKS (debug assertions) which can decrease
+Cobalt's performance.  The "qa" build is most similar to "gold", but it still
+has some debug features enabled (such as the debug console which can consume
+memory, and decrease performance while it is visible).  For the best
+performance, build Cobalt in the "gold" configuration.
+
+**Tags:** *framerate, startup, browse-to-watch, cpu memory, input latency.*
+
+
+### Framerate throttling
+
+If you're willing to accept a lower framerate, there is potential that
+JavaScript execution can be made to run faster (which can improve startup
+time, browse-to-watch time, and input latency).  Without any special
+settings in place, the renderer will attempt to render each frame as fast
+as it can, limited only by the display's refresh rate, which is usually 60Hz.
+By artificially throttling this rate to a lower value, like 30Hz, CPU
+resources can be freed to work on other tasks.  You can enable framerate
+throttling by setting a value for `cobalt_minimum_frame_time_in_milliseconds`
+in your platform's `gyp_configuration.gypi` file.  Setting it to 33, for
+example, will throttle Cobalt's renderer to 30 frames per second.
+
+**Tags:** *gyp_configuration.gypi, framerate, startup, browse-to-watch,
+           input latency.*
+
+
+### Image cache capacity
+
+Cobalt's image cache is used to cache decoded image data.  The image data
+in the image cache is stored as a texture, and so it will occupy GPU memory.
+The image cache capacity dictates how long images will be kept resident in
+memory even if they are not currently visible on the web page.  By reducing
+this value, you can lower GPU memory usage, at the cost of having Cobalt
+make more network requests and image decodes for previously seen images.
+Cobalt will automatically set the image cache capacity to a reasonable value,
+but if you wish to override this, you can do so by setting the
+`image_cache_size_in_bytes` variable in your `gyp_configuration.gypi` file.  For
+the YouTube web app, we have found that at 1080p, 32MB will allow around
+5 thumbnail shelves to stay resident at a time, with 720p and 4K resolutions
+using proportionally less and more memory, respectively.
+
+**Tags:** *gyp_configuration.gypi, cpu memory, gpu memory.*
+
+
+### Image cache capacity multiplier during video playback
+
+Cobalt provides a feature where the image cache capacity will be reduced
+as soon as video playback begins.  This can be useful for reducing peak
+GPU memory usage, which usually occurs during video playback.  The
+downside to lowering the image cache during video playback is that it
+may need to evict some images when the capacity changes, and so it is
+more likely that Cobalt will have to re-download and decode images after
+returning from video playback.  Note that this feature is not well tested.
+The feature can be activated by setting
+`image_cache_capacity_multiplier_when_playing_video` to a value between
+`0.0` and `1.0` in your `gyp_configuration.gypi` file.  The image cache
+capacity will be multiplied by this value during video playback.
+
+**Tags:** *gyp_configuration.gypi, gpu memory.*
+
+
+### Scratch Surface cache capacity
+
+This only affects GLES renderers.  While rasterizing a frame, it is
+occasionally necessary to render to a temporary offscreen surface and then
+apply that surface to the original render target.  Offscreen surface
+rendering may also need to be performed multiple times per frame.  The
+scratch surface cache will keep allocated a set of scratch textures that
+will be reused (within and across frames) for offscreen rendering.  Reusing
+offscreen surfaces allows render target allocations, which can be expensive
+on some platforms, to be minimized.  However, it has been found that some
+platforms (especially those with tiled renderers, like the Raspberry Pi's
+Broadcom VideoCore), reading and writing again and again to the same texture
+can result in performance degradation.  Memory may also be potentially saved
+by disabling this cache, since when it is enabled, if the cache is filled, it
+may be occupying memory that it is not currently using.  This setting can
+be adjusted by setting `surface_cache_size_in_bytes` in your
+`gyp_configuration.gypi` file.  A value of `0` will disable the surface cache.
+
+**Tags:** *gyp_configuration.gypi, gpu memory, framerate.*
+
+
+### Glyph atlas size
+
+This only affects GLES renderers.  Skia sets up glyph atlases to which
+it software rasterizes glyphs the first time they are encountered, and
+from which the glyphs are used as textures for hardware accelerated glyph
+rendering to the render target.  Adjusting this value will adjust
+GPU memory usage, but at the cost of performance as text glyphs will be
+less likely to be cached already.  Note that if experimenting with
+modifications to this setting, be sure to test many languages, as some
+are more demanding (e.g. Chinese and Japanese) on the glyph cache than
+others.  This value can be adjusted by changing the values of
+the `skia_glyph_atlas_width` and `skia_glyph_atlas_height` variables in your
+`gyp_configuration.gypi` file.  Note that by default, these will be
+automatically configured by Cobalt to values found to be optimal for
+the application's resolution.
+
+**Tags:** *gyp_configuration.gypi, gpu memory, input latency, framerate.*
+
+
+### Software surface cache capacity
+
+This only affects Starboard Blitter API renderers.  The Starboard Blitter API
+has only limited support for rendering special effects, so often Cobalt will
+have to fallback to a software rasterizer for rendering certain visual
+elements (most notably, text).  In order to avoid expensive software
+renders, the results are cached and re-used across frames.  The software
+surface cache is crucial to achieving an acceptable framerate on Blitter API
+platforms.  The size of this cache is specified by the
+`software_surface_cache_size_in_bytes` variable in `gyp_configuration.gypi`.
+
+**Tags:** *gyp_configuration.gypi, gpu memory, framerate.*
+
+
+### Toggle Just-In-Time JavaScript Compilation
+
+Just-in-time (JIT) compilation of JavaScript is well known to significantly
+improve the speed of JavaScript execution.  However, in the context of Cobalt
+and its web apps (like YouTube's HTML5 TV application), JITting may not be
+the best or fastest thing to do.  Enabling JIT can result in Cobalt using
+more memory (to store compiled code) and can also actually slow down
+JavaScript execution (e.g. time must now be spent compiling code).  It is
+recommended that JIT support be left disabled, but you can experiment with
+it by implementing the CobaltExtensionConfigurationApi method
+`CobaltEnableJit()` to return `true` to enable JIT, or `false` to disable it.
+
+**Tags:** *gyp_configuration.gypi, startup, browse-to-watch, input latency,
+           cpu memory.*
+
+
+### Ensure that you are not requesting Cobalt to render unchanging frames
+
+Some platforms require that the display buffer is swapped frequently, and
+so in these cases Cobalt will render the scene every frame, even if it is
+not changing, which consumes CPU resources.  If the platform needs a new frame
+submitted periodically implement the Cobalt Extension
+"dev.cobalt.extension.Graphics" and report the maximum frame interval via
+`GetMaximumFrameIntervalInMilliseconds`.
+
+See `SbSystemGetExtension` and
+[`CobaltExtensionGraphicsApi`](../extension/graphics.h).
+
+Every `cobalt_minimum_frame_time_in_milliseconds`, this function will be queried
+to determine if a new frame should be presented even if the scene has not
+changed.
+
+**Tags:** *configuration_public.h, startup, browse-to-watch, input latency,
+           framerate.*
+
+
+### Try enabling rendering only to regions that change
+
+If you set the
+[`CobaltConfigurationExtensionApi`](../extension/configuration.h) function
+`CobaltRenderDirtyRegionOnly` to return `true`, then Cobalt will invoke logic
+to detect which part of the frame has been affected by animations and can be
+configured to only render to that region.  However, this feature requires
+support from the driver for GLES platforms.  In particular, `eglChooseConfig()`
+will first be called with `EGL_SWAP_BEHAVIOR_PRESERVED_BIT` set in its
+attribute list.  If this fails, Cobalt will call eglChooseConfig() again
+without `EGL_SWAP_BEHAVIOR_PRESERVED_BIT` set and dirty region rendering will
+be disabled.  By having Cobalt render only small parts of the screen,
+CPU (and GPU) resources can be freed to work on other tasks.  This can
+especially affect startup time since usually only a small part of the
+screen is updating (e.g. displaying an animated spinner).  Thus, if
+possible, ensure that your EGL/GLES driver supports
+`EGL_SWAP_BEHAVIOR_PRESERVED_BIT`.  Note that it is possible (but not
+necessary) that GLES drivers will implement this feature by allocating a new
+offscreen buffer, which can significantly affect GPU memory usage.  If you are
+on a Blitter API platform, enabling this functionality will result in the
+allocation and blit of a fullscreen "intermediate" back buffer target.
+
+**Tags:** *startup, framerate, gpu memory.*
+
+
+### Ensure that thread priorities are respected
+
+Cobalt makes use of thread priorities to ensure that animations remain smooth
+even while JavaScript is being executed, and to ensure that JavaScript is
+processed (e.g. in response to a key press) before images are decoded.  Thus
+having support for priorities can improve the overall performance of the
+application.  To enable thread priority support, you should set the value
+of `kSbHasThreadPrioritySupport` to `true` in your `configuration_constants.h`
+file, and then also ensure that your platform's implementation of
+`SbThreadCreate()` properly forwards the priority parameter down to the
+platform.
+
+**Tags:** *configuration_public.h, framerate, startup, browse-to-watch,
+           input latency.*
+
+
+### Tweak compiler/linker optimization flags
+
+Huge performance improvements can be obtained by ensuring that the right
+optimizations are enabled by your compiler and linker flag settings.  You
+can set these up within `gyp_configuration.gypi` by adjusting the list
+variables `compiler_flags` and `linker_flags`.  See also
+`compiler_flags_gold` and `linker_flags_gold` which describe flags that
+apply only to gold builds where performance is critical.  Note that
+unless you explicitly set this up, it is unlikely that compiler/linker
+flags will carry over from external shell environment settings; they
+must be set explicitly in `gyp_configuration.gypi`.
+
+**Tags:** *framerate, startup, browse-to-watch, input latency*
+
+#### Optimize for size vs speed
+
+For qa and gold configs, different compiler flags can be used for gyp targets
+which should be optimized for size vs speed. This can be used to reduce the
+executable size with minimal impact on performance. On top of the base
+`compiler_flags_qa` and `compiler_flags_gold`, the gyp variables
+`compiler_flags_qa_size`, `compiler_flags_qa_speed`, `compiler_flags_gold_size`,
+and `compiler_flags_gold_speed` will be used. Performance-critical gyp targets
+specify `optimize_target_for_speed`: 1, and these will use compiler flags
+`compiler_flags_<config>` + `compiler_flags_<config>_speed`; other gyp targets
+will use `compiler_flags_<config>` + `compiler_flags_<config>_size`.
+
+**Tags:** *cpu memory, package size*
+
+#### Link Time Optimization (LTO)
+If your toolchain supports it, it is recommended that you enable the LTO
+optimization, as it has been reported to yield significant performance
+improvements in many high profile projects.
+
+**Tags:** *framerate, startup, browse-to-watch, input latency*
+
+
+### Close "Stats for Nerds" when measuring performance
+
+The YouTube web app offers a feature called "Stats for Nerds" that enables
+a stats overlay to appear on the screen during video playback.  Rendering
+this overlay requires a significant amount of processing, so it is
+recommended that all performance evaluation is done without the
+"Stats for Nerds" overlay active.  This can greatly affect browse-to-watch
+time and potentially affect the video frame drop rate.
+
+**Tags:** *browse-to-watch, framerate, youtube.*
+
+
+### Close the debug console when measuring performance
+
+Cobalt provides a debug console in non-gold builds to allow the display
+of variables overlayed on top of the application.  This can be helpful
+for debugging issues and keeping track of things like app lifetime, but
+the debug console consumes significant resources when it is visible in order
+to render it, so it should be hidden when performance is being evaluated.
+
+**Tags:** *framerate, startup, browse-to-watch, input latency.*
+
+
+### Toggle between dlmalloc and system allocator
+
+Cobalt includes dlmalloc and can be configured to use it to handle all
+memory allocations.  It should be carefully evaluated however whether
+dlmalloc performs better or worse than your system allocator, in terms
+of both memory fragmentation efficiency as well as runtime performance.
+To use dlmalloc, you should adjust your starboard_platform.gyp file to
+use the Starboard [`starboard/memory.h`](../../starboard/memory.h) function
+implementations defined in
+[`starboard/shared/dlmalloc/`](../../starboard/shared/dlmalloc).  To use
+your system allocator, you should adjust your starboard_platform.gyp file
+to use the Starboard [`starboard/memory.h`](../../starboard/memory.h) function
+implementations defined in
+[`starboard/shared/iso/`](../../starboard/shared/iso).
+
+**Tags:** *framerate, startup, browse-to-watch, input latency, cpu memory.*
+
+
+### Media buffer allocation strategy
+
+During video playback, memory is reserved by Cobalt to contain the encoded
+media data (separated into video and audio), and we refer to this memory
+as the media buffers.  By default, Cobalt pre-allocates the memory and
+wraps it with a custom allocator, in order to avoid fragmentation of main
+memory.  However, depending on your platform and your system allocator,
+overall memory usage may improve if media buffer allocations were made
+normally via the system allocator instead.  This can be achieved by setting
+`cobalt_media_buffer_initial_capacity` and `cobalt_media_buffer_allocation_unit`
+to 0 in gyp_configuration.gypi.  Note also that if you choose to pre-allocate
+memory, for 1080p video it has been found that 24MB is a good media buffer size.
+The pre-allocated media buffer capacity size can be adjusted by modifying the
+value of `cobalt_media_buffer_initial_capacity` mentioned above.
+
+**Tags:** *configuration_public.h, cpu memory.*
+
+
+### Adjust media buffer size settings
+
+Many of the parameters around media buffer allocation can be adjusted in your
+gyp_configuration.gypi file.  The variables in question are the family of
+`cobalt_media_*` variables, whose default values are specified in
+[`cobalt_configuration.gypi`](../build/cobalt_configuration.gypi).  In
+particular, if your maximum video output resolution is less than 1080, then you
+may lower the budgets for many of the categories according to your maximum
+resolution.
+
+**Tags:** *cpu memory*
+
+
+### Avoid using a the YouTube web app FPS counter (i.e. "?fps=1")
+
+The YouTube web app is able to display a Frames Per Second (FPS) counter in the
+corner when the URL parameter "fps=1" is set.  Unfortunately, activating this
+timer will cause Cobalt to re-layout and re-render the scene frequently in
+order to update the FPS counter.  Instead, we recommend instead to either
+measure the framerate in the GLES driver and periodically printing it, or
+hacking Cobalt to measure the framerate and periodically print it.  In order to
+hack in an FPS counter, you will want to look at the
+`HardwareRasterizer::Impl::Submit()` function in
+[`cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc`](../renderer/rasterizer/skia/hardware_rasterizer.cc).
+The work required to update the counter has the potential to affect many
+aspects of performance.  TODO: Cobalt should add a command line switch to
+enable printing of the framerate in gold builds.
+
+**Tags:** *framerate, startup, browse-to-watch, input latency,*
+
+
+### Implement hardware image decoding
+
+The Starboard header file [`starboard/image.h`](../../starboard/image.h) defines
+functions that allow platforms to implement hardware-accelerated image
+decoding, if available.  In particular, if `SbImageIsDecodeSupported()` returns
+true for the specified mime type and output format, then instead of using the
+software-based libpng or libjpeg libraries, Cobalt will instead call
+`SbImageDecode()`.  `SbImageDecode()` is expected to return a decoded image as
+a `SbDecodeTarget` option, from which Cobalt will extract a GL texture or
+Blitter API surface object when rendering.  If non-CPU hardware is used to
+decode images, it would alleviate the load on the CPU, and possibly also
+increase the speed at which images can be decoded.
+
+**Tags:** *startup, browse-to-watch, input latency.*
+
+
+### Use Chromium's about:tracing tool to debug Cobalt performance
+
+Cobalt has support for generating profiling data that is viewable through
+Chromium's about:tracing tool.  This feature is available in all Cobalt
+configurations except for "gold" ("qa" is the best build to use for performance
+investigations here). There are currently two ways to tell Cobalt
+to generate this data:
+
+1. The command line option, "--timed_trace=XX" will instruct Cobalt to trace
+   upon startup, for XX seconds (e.g. "--timed_trace=25").  When completed,
+   the output will be written to the file `timed_trace.json`.
+2. Using the debug console (hit CTRL+O on a keyboard once or twice), type in
+   the command "h5vcc.traceEvent.start()" and hit enter.  Cobalt will begin a
+   trace.  After some time has passed (and presumably you have performed some
+   actions), you can open the debug console again and type
+   "h5vcc.traceEvent.stop()" again to end the trace.
+   The trace output will be written to the file `h5vcc_trace_event.json`.
+
+The directory the output files will be placed within is the directory that the
+Starboard function `SbSystemGetPath()` returns with a `path_id` of
+`kSbSystemPathDebugOutputDirectory`, so you may need to check your
+implementation of `SbSystemGetPath()` to discover where this is.
+
+Once the trace file is created, it can be opened in Chrome by navigating to
+`about:tracing` or `chrome://tracing`, clicking the "Load" button near the top
+left, and then opening the JSON file created earlier.
+
+Of particular interest in the output view is the `MainWebModule` thread where
+JavaScript and layout are executed, and `Rasterizer` where per-frame rendering
+takes place.
+
+**Tags:** *framerate, startup, browse-to-watch, input latency.*
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/platform_services.md b/src/cobalt/site/docs/gen/cobalt/doc/platform_services.md
new file mode 100644
index 0000000..309b578
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/platform_services.md
@@ -0,0 +1,111 @@
+---
+layout: doc
+title: "Cobalt Platform Services"
+---
+# Cobalt Platform Services
+
+_NOTE: The Cobalt Platform Services API replaces the deprecated Cobalt Custom Web API Extensions_
+
+## Overview
+
+The Cobalt Platform Services API aims to provide Cobalt users the ability to
+extend the web application functionality of Cobalt. This is done using runtime
+extensions provided by the Starboard layer without having to make any
+modifications to the common Cobalt code.
+
+Web applications running on Cobalt may want to implement a feature to have
+direct access to platform-specific services, on platforms where they are
+available.
+
+For example, a Cobalt implementation may want to enable the web application to:
+
+*   Communicate directly with a service that is available on the platform
+*   Surface platform-level status messages
+
+The Cobalt Platform Services API is an RPC interface and makes assumptions that
+communication with the service is in-process and 100% reliable, unlike sockets
+or HTTP. Out-of-process communications can be implemented as a layer on top of
+the interface.
+
+## Interface Definition
+
+The Cobalt Platform Services API is an RPC interface allowing for bidirectional
+communication between the web application and platform service. The interface
+is intentionally minimal, to avoid as much as possible the need to make changes
+to common Cobalt code. There will be two parallel interfaces, one between the
+web app and Cobalt specified via IDL, and another between Cobalt and the
+Starboard implementation specified via a Starboard interface header file.
+
+The interface provides a method of querying for services by name, where a name
+is some arbitrary string (Java naming convention recommended). The platform
+should maintain a registry mapping names to services and return the appropriate
+service for the given name. Once the application has obtained a handle to a
+service, it can send messages to the service using a `send()` function, which
+optionally may return immediate results. In addition, it can receive
+asynchronous incoming messages from the service via a receive callback
+registered when the service is opened. The `send()` function may fail, either
+because the service has already been closed by the application, or because of
+some state of the service and platform. When `send()` fails, it will raise an
+`kInvalidStateErr` exception, which may be caught & handled by the application.
+
+Any functionality in addition to the necessities provided by the interface must
+be implemented within the service’s protocol.  For example, services may push a
+“version” message to the application immediately upon being opened in order to
+implement versioning.
+
+### IDL Interface
+
+The Platform Services extension is exposed to the web app via the following IDL:
+
+*   [src/cobalt/h5vcc/h5vcc\_platform\_service.idl](../h5vcc/h5vcc_platform_service.idl)
+
+The entrypoint for defined Platform Services extensions will be accessible in
+the `H5vccPlatformService` object. Note that ArrayBuffers are chosen to
+represent arbitrary message data in order to leave open the possibility of
+passing binary data.
+
+### Starboard Interface
+
+Implementing the Starboard layer of Platform Service extension support uses the
+following interface in parallel with the IDL interface:
+
+*   [src/cobalt/extension/platform\_service.h](../extension/platform_service.h)
+
+`CobaltExtensionPlatformServiceApi` is the main interface for the Starboard
+layer.
+
+### Naming Conventions for Service Names
+
+In order to guard against namespace pollution, the Java package naming
+convention is used for Platform Services.
+
+For example, some services names could be:
+
+*   `com.google.android.CobaltPlatformService`
+*   `com.<PARTNER>.<PLATFORM>.CobaltPlatformService`
+
+## Using a Cobalt Platforms Service Extension
+
+Assuming that the implementation work is completed for the IDL and
+complimentary Starboard interface, an example usage of an extension from the
+web application could look like the following:
+
+```
+var myCobaltPlatformService = "com.google.android.CobaltPlatformService";
+
+// checks if a platform has the specified service available
+H5vccPlatformService.has(myCobaltPlatformService);
+
+// attempting to open the specified service
+service = H5vccPlatformService.open(myCobaltPlatformService,
+                            (service, data) => { console.log("do something") };
+
+// send some data
+var data = new ArrayBuffer(16);
+var view = new DataView(data);
+view.setInt32(0, 0x01234567);
+service.send(data);
+
+// close the service when we are done
+service.close();
+```
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/resources/clients_performance_guide/opacity_on_individuals.png b/src/cobalt/site/docs/gen/cobalt/doc/resources/clients_performance_guide/opacity_on_individuals.png
new file mode 100644
index 0000000..17116be
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/resources/clients_performance_guide/opacity_on_individuals.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/resources/clients_performance_guide/opacity_on_subtree.png b/src/cobalt/site/docs/gen/cobalt/doc/resources/clients_performance_guide/opacity_on_subtree.png
new file mode 100644
index 0000000..b3b1656
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/resources/clients_performance_guide/opacity_on_subtree.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/resources/devtools-overlay-console-modes.png b/src/cobalt/site/docs/gen/cobalt/doc/resources/devtools-overlay-console-modes.png
new file mode 100644
index 0000000..5103358
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/resources/devtools-overlay-console-modes.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/resources/webapi_extension_example.jpg b/src/cobalt/site/docs/gen/cobalt/doc/resources/webapi_extension_example.jpg
new file mode 100644
index 0000000..e9b43d1
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/resources/webapi_extension_example.jpg
Binary files differ
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/spherical_video.md b/src/cobalt/site/docs/gen/cobalt/doc/spherical_video.md
new file mode 100644
index 0000000..b82de1e
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/spherical_video.md
@@ -0,0 +1,76 @@
+---
+layout: doc
+title: "Enabling Spherical Video in Cobalt"
+---
+# Enabling Spherical Video in Cobalt
+
+Cobalt supports playback of 360 spherical videos.  Cobalt does not expose
+this support to web applications through WebGL (which is currently
+unimplemented in Cobalt), but rather through a custom `map-to-mesh` CSS
+filter and custom [`window.camera3D` Web API](../dom/camera_3d.idl). Support
+for spherical video in Cobalt requires a GLES rasterizer (i.e. it is not
+supported for the Starboard Blitter API), and Starboard platform support for
+the player
+[decode-to-texture output mode](../../starboard/doc/howto_decode_to_texture.md).
+
+## Enabling spherical video support
+
+Spherical video support requires `map-to-mesh` support, which is enabled by
+default. You can explicitly disable it either through the command line switch
+`--disable_map_to_mesh` or by implementing the CobaltExtensionGraphicsApi
+function `IsMapToMeshEnabled()` to return `false`.
+
+When `map-to-mesh` is supported, Cobalt will make the `map-to-mesh` CSS filter
+parseable.  The web app can then detect whether the browser, Cobalt, supports
+spherical video by evaluating the following JavaScript:
+
+```
+function checkForMapToMeshSupport() {
+  return 'CSS' in window && 'supports' in window.CSS &&
+         CSS.supports(
+             'filter',
+             'map-to-mesh(url(p.msh), 100deg 60deg,' +
+                 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1),' +
+                 'monoscopic)');
+}
+```
+
+It is required that your platform provides
+[decode-to-texture support](../../starboard/doc/howto_decode_to_texture.md).
+
+## Input
+
+Cobalt currently supports input mappings from the following keys (defined in [starboard/key.h](../../starboard/key.h)):
+
+ - `kSbKeyLeft`
+ - `kSbKeyUp`
+ - `kSbKeyRight`
+ - `kSbKeyDown`
+ - `kSbKeyGamepadDPadUp`
+ - `kSbKeyGamepadDPadDown`
+ - `kSbKeyGamepadDPadLeft`
+ - `kSbKeyGamepadDPadRight`
+ - `kSbKeyGamepadLeftStickUp`
+ - `kSbKeyGamepadLeftStickDown`
+ - `kSbKeyGamepadLeftStickLeft`
+ - `kSbKeyGamepadLeftStickRight`
+ - `kSbKeyGamepadRightStickUp`
+ - `kSbKeyGamepadRightStickDown`
+ - `kSbKeyGamepadRightStickLeft`
+ - `kSbKeyGamepadRightStickRight`
+
+Additionally, if your platform generates `kSbInputEventTypeMove` (from
+[starboard/input.h](../../starboard/input.h)) events with
+`SbInputData::position` set to values in the range `[-1, 1]`, for the following
+keys,
+
+ - `kSbKeyGamepadLeftStickUp`
+ - `kSbKeyGamepadLeftStickDown`
+ - `kSbKeyGamepadLeftStickLeft`
+ - `kSbKeyGamepadLeftStickRight`
+ - `kSbKeyGamepadRightStickUp`
+ - `kSbKeyGamepadRightStickDown`
+ - `kSbKeyGamepadRightStickLeft`
+ - `kSbKeyGamepadRightStickRight`
+
+then they will be treated as analog inputs when controlling the camera.
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/splash_screen.md b/src/cobalt/site/docs/gen/cobalt/doc/splash_screen.md
new file mode 100644
index 0000000..16651c3
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/splash_screen.md
@@ -0,0 +1,144 @@
+---
+layout: doc
+title: "Cobalt Splash Screen"
+---
+# Cobalt Splash Screen
+
+## Startup splash screen sequence
+
+There can be up to three splash screens shown when launching web applications on
+Cobalt:
+
+  * one from the system
+  * one from Cobalt
+  * one from the web application itself
+
+The system splash screen is often a transition from the application icon
+on the home screen to a static asset dictated by the platform (which is outside
+of Cobalt's control). The Cobalt splash screen is shown as soon as Cobalt can
+render until the web application is loaded. The web application splash screen is
+the HTML content shown immediately upon loading the web application (this may
+resemble a typical splash screen, but it really can be whatever the application
+chooses to show on starting).
+
+## Cobalt splash screen priority order
+
+The Cobalt splash screen must be specified as a URL to a document. The document
+must be either self-contained or all of its references must be local. That means
+the document should not reference any external CSS, JavaScript, or image files,
+for example. This simplifies the caching process so that only a single document
+must be cached without tracing references. All fallback splash screens must
+refer to local documents. This is so the fallback splash screen can be shown
+without latency and even when there is no network available. Specifically, the
+fallback splash screen URL and its references should start with either
+`file:///` or `h5vcc-embedded://`. Additionally `none` can be used to specify
+that no Cobalt splash screen should be constructed; the system splash sequence
+transitions directly into the application splash sequence once the page is
+loaded.
+
+The Cobalt splash screen is one of the following, in order of precedence:
+
+  1. **Web cached splash screen:** If a splash screen specified by a web
+     application is cached from a previous instance of Cobalt, it will be loaded
+     at startup. The key for the cache splash screen is based on host & path of
+     the initial URL with no query or hash. If network connectivity is available
+     at startup, when the initial web application URL is processed, a custom
+     `rel="splashscreen"` attribute of the link element is used to specify and
+     cache the splashscreen URL for future runs.
+
+  2. **Command line fallback splash screen:** This is specified as a command
+     line argument `--fallback_splash_screen_url` via the system and used when
+     cache is unavailable.  This is the case when there is no local cache
+     storage, cache has been cleared, or the application is started for the
+     first time.
+
+  3. **Build-time fallback splash screen:** If a web cached splash screen is
+     unavailable and command line parameters are not passed by the system,
+     a CobaltExtensionConfigurationApi fallback splash screen may be used.
+     Porters should set the `CobaltFallbackSplashScreenUrl` value in
+     `configuration.cc` to the splash screen URL.
+
+  4. **Default splash screen:** If no web cached splash screen is available, and
+     command line and CobaltExtensionConfigurationApi fallbacks are not set, a
+     default splash screen will be used. This is set in
+     `configuration_defaults.cc` to refer to a black splash screen.
+
+## Web-updatability
+
+Since Cobalt parses the link element's `rel="splashscreen"` attribute for the
+splash screen URL in the content fetched from the initial URL, an application
+developer may update the splash screen by changing that attribute in the link
+element. On the next load of the application, the new splash screen will be
+cached, and on the subsequent load of the application, the new cached splash
+screen will be shown.
+
+For example, the document at the initial URL could contain
+```
+<link rel="splashscreen" href="https://www.example.com/self-contained.html">
+```
+where `"https://www.example.com/self-contained.html"` is the address of some
+self-contained splash screen document. The document must not violate the Content
+Security Policy. The splash screen is treated as a script resource by the CSP.
+
+### Caching implementation requirements
+
+In order to cache the application-provided splash screen, Cobalt will attempt
+to create directories and write files into the directory returned from a call to
+`SbSystemGetPath(kSbSystemPathCacheDirectory, ...)`.  Cobalt will expect the
+data that it writes into that directory to persist across process instances.
+Cobalt will also need to read the cached splash screen from the cache directory
+when starting up.
+
+## Topic-specific splash screens
+
+It is possible to specify multiple splash screens for a given Cobalt-based
+application, using a start-up 'topic' to select between the available splash
+screens. This can be useful when an application has multiple entry points that
+require different splash screens. The topic may be specified in the start-up url
+or deeplink as a query parameter. For example,
+`https://www.example.com/path?topic=foo`. If a splash-screen has been specified
+for topic 'foo', it will be used. Otherwise, the topic is ignored. Topic values
+should be URL encoded and limited to alphanumeric characters, hyphens,
+underscores, and percent signs.
+
+There are three ways to specify topic-specific splash screens. These methods mirror
+the types of splash screens listed above, and unless specified, the rules here
+are the same as for non-topic-based splash screens.
+
+  1. **Web cached splash screen:** A custom `rel="<topic>_splashscreen"`
+     attribute on a link element is used to specify a topic-specific splash
+     screen. There can be any number of these elements with different topics, in
+     addition to the topic-neutral `rel="splashscreen"`.
+
+  2. **Command line fallback splash screen:** The command line argument
+     `--fallback_splash_screen_topics` can be used if the cache is unavailable.
+     The argument accepts a list of topic/file parameters. If a file is not a
+     valid URL path, then it will be used as a filename at the path specified by
+     `--fallback_splash_screen_url`. For example,
+     `foo_topic=file:///foo.html&bar=bar.html`.
+
+  3. **Build-time fallback splash screen:** If a web cached splash screen is
+     unavailable and command line parameters are not passed by the system, a
+     CobaltExtensionConfigurationApi fallback splash screen may be used. Porters
+     should set the `CobaltFallbackSplashScreenTopics` value in
+     `configuration.cc` and this value should look like the command line option.
+
+## Application-specific splash screens
+
+On systems that plan to support multiple Cobalt-based applications, an
+application developer may wish to use the command line arguments for the
+fallback splash screen to display different Cobalt splash screens for different
+applications. The logic for passing in these different command line arguments to
+the Cobalt binary must be handled by the system.
+
+Alternatively, an application developer may use the default black splash screen
+whenever a cached splash screen is not available and rely on the web application
+to specify an application-specific cached splash screen otherwise.
+
+## Provided embedded resource splash screens
+For convenience, we currently provide the following splash screens as embedded
+resources:
+
+  * `h5vcc-embedded://black_splash_screen.html` - a black splash screen
+  * `h5vcc-embedded://cobalt_splash_screen.html` - a splash screen showing the
+    Cobalt logo
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/versioning.md b/src/cobalt/site/docs/gen/cobalt/doc/versioning.md
new file mode 100644
index 0000000..020d607
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/versioning.md
@@ -0,0 +1,82 @@
+---
+layout: doc
+title: "Cobalt Versioning"
+---
+# Cobalt Versioning
+
+Cobalt versions, as they appear in the user agent, have the following structure:
+
+**[Feature Year]**.**[Purpose]**.**[Update Number]**.**[Build ID]**
+
+The meansions of these components are described below.
+
+Example Cobalt versions would be:
+
+  * `19.lts.1.40455`
+  * `19.lts.2.53047`
+  * `20.lts.1.64553`
+
+## Feature Year
+
+Cobalt features are tied to a yearly release cycle and this number indicates
+the yearly feature set that this version of Cobalt supports.  It is the last
+two digits of the year of the target feature set.  For example for the 2019
+feature set, this value will be `19`.
+
+## Purpose
+
+The purpose of this build, usually named after the reason that a branch is cut.
+On the master branch it will be `master`, and on LTS branches for example it
+will be `lts`.
+
+## Update Number
+
+The current update revision number (e.g. release number) for a given pair of
+values above.  This will always be `0` on the master branch.  When a release
+branch is cut, will be modified to start at `1`, and be incremented each time a
+release or update is released.  It is possible that multiple updates are
+released off of the same release branch, if new bugs are discovered and fixed.
+
+## Build ID
+
+The Cobalt Build ID represents **fine-grained** information about the state of
+the source tree for a given build. An internal Cobalt build server generates a
+monotonically increasing number for each unique set of sources that it
+sees. When an open-source release is published,
+a [`src/cobalt/build/build.id`](../build/build.id) file is included that
+specifies the build ID of that source release. The Cobalt team can reproduce the
+exact sources for a given Build ID.
+
+Note that since the Build ID always increases with time, it means that the
+latest version of an older Cobalt release can have a higher Build ID than the
+latest version of a new Cobalt release. An example from above: Cobalt `4.16134`
+was produced earlier than Cobalt `3.16138`, thus has a lower Build ID.
+
+## Older Cobalt versioning scheme
+
+A Cobalt version consists of two components: The Release Number and the Build
+ID. Some real historical Cobalt version examples:
+
+  * `2.15147`
+  * `3.16138`
+  * `4.16134`
+  * `6.18971`
+
+You get the idea. The number before the dot is the "Release Number." The number
+after the dot is the "Build ID."
+
+### Release Number
+
+In older Cobalt versioning schemes, a "Cobalt release" is an official, tested
+version of Cobalt that is intended to be deployable to production. The
+"Release Number" is a single counting number, starting at "1" for our first
+release, and increasing by one for every release thereafter. This number is
+checked into [`src/cobalt/version.h`](../version.h), and represents **coarse**
+information about the state of the source tree when we decided to do a release.
+
+It is important to note that there are no point releases, or major or minor
+releases. Each release gets its own unique counting number.
+
+## Other Reading
+
+  * [Cobalt Branching](branching.md)
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/voice_search.md b/src/cobalt/site/docs/gen/cobalt/doc/voice_search.md
new file mode 100644
index 0000000..f5d54a2
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/voice_search.md
@@ -0,0 +1,69 @@
+---
+layout: doc
+title: "Enabling voice search in Cobalt"
+---
+# Enabling voice search in Cobalt
+
+Cobalt enables voice search through either:
+
+1. A subset of the [MediaRecorder Web API](https://www.w3.org/TR/mediastream-recording/#mediarecorder-api).
+2. A subset of the [Speech Recognition Web API](https://w3c.github.io/speech-api/#speechreco-section)
+
+Only one or the other can be used, and we recommend that the MediaRecorder API
+is followed, as we are considering deprecating the Speech Recognition API.
+
+**The Speech Recognition API is deprecated as of Starboard 13.**
+
+In both approaches, in order to check whether to enable voice control or not,
+web apps will call the [MediaDevices.enumerateDevices()](https://www.w3.org/TR/mediacapture-streams/#dom-mediadevices-enumeratedevices%28%29)
+Web API function within which Cobalt will in turn call a subset of the
+[Starboard SbMicrophone API](../../starboard/microphone.h).
+
+## MediaRecorder API
+
+To enable the MediaRecorder API in Cobalt, the complete
+[SbMicrophone API](../../starboard/microphone.h) must be implemented, and
+`SbSpeechRecognizerIsSupported()` must return `false`.
+
+## Speech Recognition API - Deprecated
+
+**The Speech Recognition API is deprecated as of Starboard 13.**
+
+In order to provide support for using this API, platforms must implement the
+[Starboard SbSpeechRecognizer API](../../starboard/speech_recognizer.h) as well
+as a subset of the [SbMicrophone API](../../starboard/microphone.h).
+
+### Specific instructions to enable voice search
+
+1. Implement `SbSpeechRecognizerIsSupported()` to return `true`, and implement
+   the [SbSpeechRecognizer API](../../starboard/speech_recognizer.h).
+2. Implement the following subset of the
+   [SbMicrophone API](../../starboard/microphone.h):
+    - `SbMicrophoneGetAvailable()`
+    - `SbMicrophoneCreate()`
+    - `SbMicrophoneDestroy()`
+
+   In particular, SbMicrophoneCreate() must return a valid microphone.  It is
+   okay to stub out the other functions, e.g. have `SbMicrophoneOpen()`
+   return `false`.
+3. The YouTube app will display the mic icon on the search page when it detects
+   valid microphone input devices using `MediaDevices.enumerateDevices()`.
+4. With `SbSpeechRecognizerIsSupported()` implemented to return `true`, Cobalt
+   will use the platform's
+   [Starboard SbSpeechRecognizer API](../../starboard/speech_recognizer.h)
+   implementation, and it will not actually read directly from the microphone
+   via the [Starboard SbMicrophone API](../../starboard/microphone.h).
+
+### Differences from versions of Cobalt <= 11
+
+In previous versions of Cobalt, there was no way to dynamically disable
+speech support besides modifying common Cobalt code to dynamically stub out the
+Speech Recognition API when the platform does not support microphone input.
+This is no longer necessary, web apps should now rely on
+`MediaDevices.enumerateDevices()` to determine whether voice support is enabled
+or not.
+
+### Speech Recognition API is deprecated in Starboard 13 ###
+
+Web applications are expected to use the MediaRecorder API. This in turn relies
+on the SbMicrophone API as detailed above.
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/web_debugging.md b/src/cobalt/site/docs/gen/cobalt/doc/web_debugging.md
new file mode 100644
index 0000000..eb46b28
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/web_debugging.md
@@ -0,0 +1,292 @@
+---
+layout: doc
+title: "Cobalt Web Debugging"
+---
+# Cobalt Web Debugging
+
+## Overview
+
+Cobalt includes the [Chrome
+DevTools](https://developers.google.com/web/tools/chrome-devtools/) frontend for
+debugging web apps. It's available in the **20.lts.1+** and newer branches of
+Cobalt.
+
+Cobalt only supports a subset of what DevTools can do, but we make a point of
+hiding UI elements that don't work so everything you see in the UI should work.
+As we get more implemented in the backend the respective UI will be enabled in
+the frontend.
+
+The following panels are supported:
+
+*   **Elements** - view the DOM tree and CSS styles
+*   **Console** - JavaScript "command line" and logging output
+*   **Sources** - interactive JavaScript debugging
+*   **Performance** - profile JavaScript execution
+
+## Using DevTools
+
+The DevTools frontend is loaded in Chrome from a small HTTP server built into
+**non-gold** Cobalt. Even though it looks mostly the same as Chrome's inspector
+(it's built from the same source code), Cobalt's DevTools is a separate app,
+and Cobalt is *not* a remote target that you can debug with Chrome's built-in
+debugger.
+
+After building and running Cobalt as usual, use Chrome on your desktop to load
+the start page from port 9222 on the target device where Cobalt is running.
+Click through to the only inspectable page shown on the start page.
+
+> If you have trouble connecting:
+> * Ensure you have an IP route from your desktop to the target device that
+>   allows traffic on the debugging port (default 9222).
+> * If you are running Cobalt locally on your desktop, then use
+>   http://localhost:9222 since the Linux build only listens to the loopback
+>   network interface by default.
+
+If you're not sure what IP address to use, look in the terminal log output for a
+message telling you the URL of Cobalt's DevTools (which you may be able to open
+with a ctrl-click in many terminal programs):
+
+```
+---------------------------------
+ Connect to the web debugger at:
+ http://192.168.1.1:9222
+---------------------------------
+```
+
+### Wait for web debugger
+
+If you're debugging the initial page as it's loading you need use the
+`--wait_for_web_debugger` switch to tell Cobalt to wait until you attach
+DevTools before actually loading the initial URL:
+
+```
+out/linux-x64x11_devel/cobalt --wait_for_web_debugger --url="http://test.example.com"
+```
+
+When this switch is specified, Cobalt will appear to hang with just a black
+window until you load DevTools. In the terminal log output you'll see that
+Cobalt is waiting with message like:
+
+```
+-------------------------------------
+ Waiting for web debugger to connect
+-------------------------------------
+```
+
+If you're debugging a page in a series of redirects, you can specify a number to
+make Cobalt wait before loading the Nth page. If no number is specified with the
+switch, the default value is 1 to wait before the initial page load. For
+example:
+
+```
+out/linux-x64x11_devel/cobalt --wait_for_web_debugger=2 --url="http://test.example.com"
+```
+
+## Panels
+
+### Elements
+
+The Elements panel displays the DOM as a tree with expandable nodes to dig into
+it. The right side bar shows the CSS styles affecting the selected node in the
+DOM. The *Styles* tab shows matching rules, inherited rules, and inline style.
+The *Computed* tab shows the computed style for the selected node. The box model
+properties are shown graphically in both the *Styles* and *Computed* tabs.
+
+> Cobalt currently only supports a read-only view of the DOM and CSS.
+
+Chrome docs:
+
+*   https://developers.google.com/web/tools/chrome-devtools/dom/
+*   https://developers.google.com/web/tools/chrome-devtools/css/
+
+### Console
+
+Cobalt has two types of consoles:
+
+*   Overlay Console: shown at runtime of Cobalt. It has multiple mode that it
+    can cycle between as well:
+    *   HUD
+    *   HUD & Debug Console
+    *   Media Console
+*   Remote Console: shown in a connected devtools session.
+
+Both console UIs show messages logged from JavaScript (with `console.log()`,
+etc.), and have a command line to evaluate arbitrary JavaScript in the context
+of the page being debugged.
+
+#### Overlay Console
+
+The overlay console also shows non-JavaScript logging from Cobalt itself, which
+is mostly interesting to Cobalt developers rather than web app developers.
+
+The various modes of the overlay console are accessed by repeatedly pressing
+"`F1`" or "`Ctrl+O`". They cycle in order between: none, HUD, HUD & Debug, and
+Media. Alternatively, initial console state can be set with the
+`--debug_console=off|hud|debug|media` command-line switch (`--debug_console=on`
+is accepted as a legacy option and maps to "debug" setting).
+
+![Overlay Console mode switching](resources/devtools-overlay-console-flow.png)
+
+##### HUD overlay
+
+This brings up an overlay panel which does not block sending input to the
+underlying Cobalt app. It serves to display real-time statistics (e.g. memory
+usage) and configuration values (e.g. disabled codecs) of the Cobalt app in a
+compact string.
+
+##### Debug Console overlay
+
+This overlay is interactive and it shows messages from Cobalt, along with logs
+from Javacript `console.log()`. While it is active, you cannot interact directly
+with the underlying page.
+
+Additionally, it can act as a JS interpreter that will evaluate arbitrary
+expressions on the page being debugged. The output from these JS commands will
+also be printed to the Debug console.
+
+Finally, it has some special debug commands which can be listed by calling
+`d.help()`. They are provided by a debug helper object and the list of functions
+are invoked by prepending either "`debug`" or "`d`". For example, you can
+disable the vp9 codec manually for all future played videos in this session of
+Cobalt by sending `debug.disable_media_codecs("vp9")` to the console.
+
+Note: you can clear the disabled media codecs by sending
+`debug.disable_media_codecs("")`. The command takes a semicolon separated list
+of codecs as the input list of codecs to disable.
+
+##### Media Console overlay
+
+The media console is a specialized console of the debug overlay system, for
+playback and media related tasks. The current list of implemented features are:
+
+*   Reading the play/pause state of the primary video
+*   Reading the current time and duration of the primary video
+*   Reading the playback rate of the primary video
+*   Reading the currently disabled codecs for the player
+*   Toggling between playing and pausing the primary video
+*   Setting the current playback rate between various presets for the primary
+    video
+*   Toggling the enabled/disabled state of the available codecs
+
+While the media console is shown, it is not possible to interact with the page
+below it directly.
+
+Additionally, the console does not show any meaningful information or
+interactions when no video is currently playing (all the readouts are blank or
+undefined). A status message of “No primary video.” indicates there is no valid
+player element on the current page.
+
+In the case of multiple videos playing (such as picture in picture), only the
+primary (fullscreen) video’s information is shown and the controls are only
+enabled for the primary video.
+
+The list of hotkeys and commands are dynamically generated as they are found to
+be available on app startup.
+
+Basic always-enabled commands are (case-sensitive):
+
+*   "`p`" Toggle the play/pause state
+*   "`]`" Increase the playback rate
+*   "`[`" Decrease the playback rate
+
+The above commands will take effect instantly for the currently playing video.
+They have no effect if there is no video playing.
+
+The following commands are dynamically loaded based on the capability of the
+system:
+
+*   "`CTRL+NUM`" Enable/disable specific video codec
+*   "`ALT+NUM`" Enable/disable specific audio codec
+
+**Important:** Media Console cannot be used to directly select a specific codec for
+playback. See the section below for rough outline of steps to work around this.
+
+The list of available codecs for any video is chosen based on the decoders on
+the platform, and what formats YouTube itself serves. As a result, the only way
+to get a particular codec to play is to disable all the options until the
+desired codec is the one that is picked. Simply do the following procedure:
+
+*   Pick the video you want to play.
+*   Enable “stats for nerds” (See [help page for
+    instructions](https://support.google.com/youtube/answer/7519898)).
+*   Write down the codecs that are chosen when playing the video, without any
+    codecs disabled (one for video, and one for audio).
+*   Disable the default codecs.
+*   Replay the same video from the browse screen.
+*   Repeat until you identify all codecs that are available for the video, until
+    the video is unable to be played.
+*   Use the above knowledge to disable the codecs to force the player into
+    choosing a particular codec, by process of elimination.
+
+**Important:** Disabled codecs only take effect when a video starts playing.
+When you play a video, the current list of disabled codecs is used to select an
+arbitrary enabled format. When you seek in the video, the disabled codecs list
+does not take effect. Only when you exit the player and re-enter by playing a
+video will any toggled codecs be affected.
+
+**Important:** Disabled codecs list is persistent for the app-run. If you
+disable “av01”, then until you re-enable it, “av01” formats will never be
+chosen.
+
+**Important:** If you disable all the available codecs, no video codec can be
+selected and an error dialog will be shown. This means that YouTube does not
+have the video in any other formats, outside of the codecs that are disabled.
+The player reports that it cannot play the video in any of the available formats
+so playback will fail here, which is intended.
+
+#### Remote Console
+
+The console in DevTools is a richer UI that can show evaluated objects with an
+expander so you can dig in to their properties. Logging from JavaScript with
+`console.log()` can show objects and exceptions as well, in contrast to the
+text-only messages shown in the console overlay.
+
+Chrome docs:
+
+*   https://developers.google.com/web/tools/chrome-devtools/console/
+
+### Sources
+
+Source-level JavaScript debugging can be done on the Sources panel. You can
+inspect sources, set breakpoints, see call stacks and scoped variables, add
+watch expressions, and all that good stuff.
+
+> Source debugging only works when Cobalt is built with V8.
+
+Chrome docs:
+
+*   https://developers.google.com/web/tools/chrome-devtools/javascript/
+
+### Performance
+
+The Performance panel allows you to record a profile of sampled call stacks
+while Cobalt is running your JavaScript code. The recorded profile is displayed
+in a flame chart showing the relationship and timing of function calls.
+
+> Performance profiling only works when Cobalt is built with V8, and the
+> platform implements the `SbThreadSampler` Starboard API.
+
+> The profiler can't currently identify which is the main thread, but you can
+> easily see it as the one with the most events.
+
+Chrome docs:
+
+*   https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/
+
+## Tips
+
+*   You can make Cobalt reload the current page by pressing F5 in the Cobalt
+    window, or ctrl-R in the remote DevTools. This may be useful for debugging
+    startup code in the web app. It may also help in case some source file is
+    not appearing in the DevTools Sources panel.
+
+*   The DevTools frontend remembers your breakpoints, so if you need to restart
+    Cobalt completely you can just kill it with ctrl-C in the terminal where you
+    launched it and re-run it. Then click the *Reconnect DevTools* button shown
+    in the DevTools UI or refresh the page to reload the DevTools UI.
+
+*   You can use the `--remote_debugging_port` command line switch to specify a
+    remote debugging port other than the default 9222.
+
+*   You can use the `--dev_servers_listen_ip` command line switch to change
+    which network interface the remote debugging server is listening to.
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/webapi_extension.md b/src/cobalt/site/docs/gen/cobalt/doc/webapi_extension.md
new file mode 100644
index 0000000..f3c7b42
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/webapi_extension.md
@@ -0,0 +1,113 @@
+---
+layout: doc
+title: "Cobalt Web Extension Support"
+---
+# Cobalt Web Extension Support
+
+## Deprecation
+Please note that Web Extension support is deprecated. Please use Platform
+Services (cobalt/doc/platform_services.md) instead. This is an effort to move
+away from injecting compile-time modules into the Cobalt layer in favor of
+using runtime extensions provided by the Starboard layer.
+
+## Overview
+Cobalt provides a facility for extending the JavaScript Web API.  This allows
+custom web apps running on Cobalt to make calls through a custom API to
+C++ Cobalt code defined per Starboard platform.  This can allow for closer
+integration between the web app hosted by Cobalt and the system on which that
+web app is running.
+
+The Cobalt Web Extension support will allow you to attach an instance of a
+custom class to the JavaScript `window` global object so that it can be
+referenced from a web app in JavaScript as in the following example:
+
+```
+window.myInterface.RunMyFunction()
+```
+
+## Build-level modifications
+
+In order to extend the interface, one should add the following lines to the
+`variables` section of `<platform-directory>/cobalt/configuration.gypi` (see
+Starboard's
+[Application Customization](../../starboard/doc/building.md#application-customization)
+for more information):
+
+1. `cobalt_webapi_extension_source_idl_files`
+   This should be a list of [IDL files](https://en.wikipedia.org/wiki/Web_IDL)
+   that define the collection of new interfaces introduced by your extensions.
+   One of these new interfaces can be selected to be injected into the `window`
+   element (see 3. `cobalt_webapi_extension_gyp_target` for information on how
+   to do this).  Each IDL file listed here simultaneously defines a JavaScript
+   and a C++ interface.  For each IDL file, you will be expected to also provide
+   a header file in the same directory that re-declares (in C++) the interface
+   declared in the IDL file, as well as an implementation of all the methods
+   within it (either inline in the header file or in a corresponding source
+   file).
+2. `cobalt_webapi_extension_generated_header_idl_files`
+   This is a list of all files that may result in automatic header file
+   generation that might be referenced from other C++ code.  An example of
+   this is the definition of `enum`s that may then be referenced as types in
+   a file from 1. `cobalt_webapi_extension_source_idl_files`.
+3. `cobalt_webapi_extension_gyp_target`
+   This is the gyp target that will provide the IDL interface implementations,
+   as well as any necessary auxiliary code.  It will be added as a dependency of
+   [browser/cobalt.gyp:cobalt](../browser/cobalt.gyp).  It is expected that
+   this target will implement the interface defined in
+   [browser/webapi_extension.h](../browser/webapi_extension.h), which let you
+   name the injected window property, and provide a function to instantiate it
+   (i.e. to let you select which IDL object is the "entry point").
+
+The first two lists get included by
+[cobalt/browser/browser_bindings_gen.gyp](cobalt/browser/browser_bindings_gen.gyp),
+where you can look to see many examples of existing Cobalt IDL files that define
+the Web API available through Cobalt.  For each of these, you can also
+examine their corresponding `.h` files and in most cases their `.cc` files as
+well.
+
+An example configuration for these variables is available at
+[starboard/shared/test_webapi_extension/test_webapi_extension.gypi](../../starboard/shared/test_webapi_extension/test_webapi_extension.gypi), which
+contains the following variable definitions:
+
+```
+'cobalt_webapi_extension_source_idl_files': [
+  'my_new_interface.idl'
+],
+'cobalt_webapi_extension_generated_header_idl_files': [
+  'my_new_enum.idl'
+],
+'cobalt_webapi_extension_gyp_target':
+  '<(DEPTH)/starboard/shared/test_webapi_extension/webapi_extension.gyp:cobalt_test_webapi_extension',
+```
+
+## Implementing the [webapi_extension.h](../browser/webapi_extension.h) interface
+
+As discussed above in 3. `cobalt_webapi_extension_gyp_target`, you must provide
+an implementation of the two functions declared in
+[browser/webapi_extension.h](../browser/webapi_extension.h).
+
+### `GetWebAPIExtensionObjectPropertyName()`
+You should implement `GetWebAPIExtensionObjectPropertyName()` to return the name
+of the injected `window` property.  For example, in the example from the
+beginning of this document, `window.myInterface.RunMyFunction()`, we would have
+the function return `std::string("myInterface")`.  If you return `nullopt` from
+this function, it is assumed that you do not wish to extend the web interface.
+
+Note that you should NOT name your `window` property the same as your class name
+as described in the IDL file, it will result in a name collision in the
+JavaScript environment.
+
+### `CreateWebAPIExtensionObject()`
+This function should instantiate and return the object to be accessed from
+`window`.  The object must be defined by an IDL file.
+
+## Debugging
+You may find the Cobalt debug console to be particularly useful for debugging
+IDL additions and changes.  In it, you can enter arbitrary JavaScript and then
+hit enter to execute it.  You can toggle it open by hitting either CTRL+O or
+F1, and you may have to hit the key twice to skip past the HUD mode.
+
+Here is an example of an example interface being exercised through the
+debug console:
+
+![Debug console web extension example](resources/webapi_extension_example.jpg)
diff --git a/src/cobalt/site/docs/gen/starboard/build/doc/gn_migrate_stub_to_platform.md b/src/cobalt/site/docs/gen/starboard/build/doc/gn_migrate_stub_to_platform.md
new file mode 100644
index 0000000..f717d32
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/build/doc/gn_migrate_stub_to_platform.md
@@ -0,0 +1,132 @@
+---
+layout: doc
+title: "Stub to Platform GN Migration"
+---
+# Stub to Platform GN Migration
+
+This document outlines a step by step process for converting the stub platform's
+GN files to GN files that will be able to be built for your platform. It assumes
+you have an already working port of Starboard using GYP.
+
+## Steps to Migrate Stub Files to your platform's GN Files
+
+This is **one** way for migrating your platform from GYP to GN. The benefit of
+following this is that you can have regular checkpoints to see if your migration
+is going correctly, rather than trying to do the entire migration at once where
+it's uncertain how much progress is being made. \
+Here are the steps to do your migration:
+
+1.  [Copy stub files over to your platform and build them](#copy-stub-files-over-to-your-platform-and-build-them).
+2.  [Replace stub toolchain with your platform's toolchain](#replace-stub-toolchain-with-your-platforms-toolchain).
+3.  [Replace stub configuration with your platform's configuration](#replace-stub-configuration-with-your-platforms-configuration).
+4.  [Replace stubbed starboard_platform target sources with your platform's
+    sources](#replace-stubbed-starboardplatform-sources-with-your-platforms-sources).
+
+After each step, you should be able to build the starboard_platform target.
+For example, you would build raspi2 starboard_platform target with the following
+commands:
+```
+$gn gen out/raspi-2gn_devel --args='target_platform="raspi-2" build_type="devel"'
+$ninja -C out/raspi-2gn_devel/ starboard
+```
+
+### Copy Stub Files Over to Your Platform and Build Them
+
+Here is a list of steps outlining which files to copy over and how to build
+those files:
+
+1.  Copy over files from the stub implementation to the platform folder. This
+    list gives you an example of which files to copy over for your platform.
+    This is an example for files to be copied over for your platform's port at
+    starboard/YOUR_PLATFORM
+    *   starboard/stub/BUILD.gn > starboard/YOUR_PLATFORM/BUILD.gn
+    *   starboard/stub/platform_configuration/BUILD.gn >
+        starboard/YOUR_PLATFORM/platform_configuration/BUILD.gn
+    *   starboard/stub/platform_configuration/configuration.gni >
+        starboard/YOUR_PLATFORM/platform_configuration/configuration.gni
+    *   starboard/stub/toolchain/BUILD.gn >
+        starboard/YOUR_PLATFORM/toolchain/BUILD.gn
+2.  Add your platform path to starboard/build/platforms.gni as referenced
+    [here](../migrating_gyp_to_gn.md#adding-your-platform-to-starboard)
+3.  Resolve any errors which come up for missing/incorrect file paths. Then, you
+    should be able to build your platform target with the stubbed out files
+    suggested in the above section.
+
+### Replace Stub Toolchain with Your Platform's Toolchain
+
+Follow instructions [here](../migrating_gyp_to_gn.md#migrating-a-toolchain) for
+migrating the toolchain. Resolve errors and build the starboard_platform target
+with the stubbed files.
+
+### Replace Stub Configuration with Your Platform's Configuration
+
+This involves migrating the compiler flags and build variables as referenced
+[here](../migrating_gyp_to_gn.md#migrating-a-platform).
+
+> **Highly recommended** \
+> It’s good to turn off the `treat_warnings_as_errors flag` until you can compile
+> the starboard_platform target with the platform files.
+> If this flag is not disabled you might run into a lot of
+> warnings turned errors and it might take time to solve all those errors.
+> Meanwhile you won't be in a buildable state which might make it uncertain as to
+> how much progress you are actually making.
+> For disabling the flag you can pass that as an argument to gn.
+> Here's an example for disabling the flag for raspi2:
+> ```
+> $gn gen out/raspi-2gn_devel --args='target_platform="raspi-2" build_type="devel" treat_warnings_as_errors=false'
+> ```
+
+Resolve errors and build the starboard_platform target with the stubbed files.
+
+### Replace Stubbed starboard_platform Sources with Your Platform's Sources
+
+This involves adding files for the starboard_platform target as suggested
+[here](../migrating_gyp_to_gn.md#migrating-a-platform).
+
+While building any target, follow the recommendation above of building the
+target with `treat_warnings_as_errors=false`.
+
+Once you can build your platform files, you can remove the
+`treat_warnings_as_errors=false` flag and resolve the warning errors.
+
+## FAQ
+
+1.  **I’m getting a build error! What should I do?** \
+    Some common questions to ask yourself:
+
+    *   Is the same target building with GYP + ninja (as GN + Ninja)?
+
+        > For example if the `nplb` target is not being built by GN, check first
+        > if it can be built with GYP. If GYP cannot build it, this indicates
+        > that some flags are missing in GYP itself so it might be prudent to
+        > solve that first before migrating to GN.
+
+    *   Am I missing a config/dependency to include the missing file?
+
+        > [gn check](https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/reference.md#cmd_check)
+        > can help point out missing dependencies.
+
+    *   Is the same file being included in the build by GYP?
+
+        > Add a preprocessor directive like #error "This file is included" in
+        > that file and see if GYP + Ninja prints out that error message.
+
+    *   Is the same code path being followed by GYP + ninja ?
+
+        > Use the same method as above.
+
+    *   Are the compiler flags for this file the same as in GYP ?
+
+        > To compare flags for GYP vs GN refer
+        > [section](../migrating_gyp_to_gn.md#validating-a-target). To check if
+        > the variables/flags you are compiling have changed since GYP, refer
+        > [page](../migration_changes.md).
+
+    *   Have you passed in the default arguments for your platform correctly?
+
+        > Default variables such as `target_cpu`, `target_os` and others can be
+        > overridden by passing arguments to gn while building. Here's an
+        > example of passing the default argument `target_cpu` for raspi2:
+        > ```
+        > $gn gen out/raspi-2gn_devel --args='target_platform="raspi-2" build_type="devel" target_cpu="arm"'
+        > ```
diff --git a/src/cobalt/site/docs/gen/starboard/build/doc/migrating_gyp_to_gn.md b/src/cobalt/site/docs/gen/starboard/build/doc/migrating_gyp_to_gn.md
new file mode 100644
index 0000000..07b4968
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/build/doc/migrating_gyp_to_gn.md
@@ -0,0 +1,262 @@
+---
+layout: doc
+title: "Migrating GYP to GN"
+---
+# Migrating GYP to GN
+
+Cobalt is currently in the process of migrating from our current build system
+which uses [GYP][gyp_home] to an updated one with
+[Generate Ninja (GN)][gn_home]. This allows us to remove our dependencies on
+Python 2.
+
+## Getting Started with GN
+
+### Getting the Binary
+
+There are a few ways to get a binary. Follow the instructions for whichever way
+you prefer [here][gn_getting_a_binary].
+
+### Read the Docs
+
+Most of the documentation for GN is located [here][gn_doc_home].
+
+*   For a hands-on example with GN, check out the
+    [Quick Start Guide][gn_quick_start] and walk through the example.
+
+*   To learn more about the language and coding in it, read through the
+    [Language page][gn_language] and the [Style Guide][gn_style_guide].
+
+*   For a full reference of the language, run `gn help` or use the
+    [Reference page][gn_reference].
+
+If you're familiar with GYP but not with GN, it may be helpful to read
+Chromium's [GYP->GN Conversion Cookbook][gyp_to_gn_cookbook]. Keep in mind we
+don't want to follow everything that's recommended here—much of the advice is
+specific to Chromium. In particular:
+
+*   Whenever possible, avoid using a `source_set`. Instead, use a
+    `static_library`.
+*   Many of the flags under [Variable Mappings][gyp_to_gn_variable_mappings] do
+    not apply to Cobalt.
+*   Cobalt code is not Chromium code by default, so you can ignore
+    [that section][gyp_to_gn_chromium_code].
+
+### Know the Tools
+
+The flow of GN is fairly similar to that of GYP: you'll configure a build then
+actually build it (using ninja). Here's how to build `nplb` target for
+`stub_debug`:
+
+```
+$ gn gen out/stub_debug --args='target_platform="stub" build_type="debug"'
+$ ninja -C out/stub_debug nplb
+```
+
+You can change the directory argument to `gn gen` (`out/stub_debug`) if you'd
+like; unlike GYP, we can put the build root wherever we want.
+
+There are some additional important tools: `gn format`, which is a code
+formatter for GN, and `gn check`, which checks that build dependencies are
+correctly set. See the documentation for [gn format][gn_format_tool] and
+[gn check][gn_check_tool] for how to use both. The full list of commands GN
+supports can be found on the [reference page][gn_reference].
+
+## Migrating a Single Target
+
+GYP and GN are very similar within the scope of a single target. The GYP->GN
+Conversion Cookbook is a good reference for this, particularly
+[this section][gyp_to_gn_typical_modifications]. The GYP syntax stays very
+similar in general, though configuration will differ: in GN, you should create a
+`config` targets and have your target add that to their list of configs:
+
+```
+config("foo_config") {
+  cflags = ...
+}
+
+static_library("foo") {
+  sources = ...
+  deps = ...
+
+  configs += [ ":foo_config" ]
+}
+```
+
+You also may need to remove default configs. The default configs are listed in
+[BUILDCONFIG.gn](../config/BUILDCONFIG.gn). You remove a config like so:
+
+```
+static_library("foo") {
+  configs -= [ "//full/path/to/config:config_name" ]
+}
+```
+
+## Migrating a Platform
+
+When porting your platform with GYP following
+[the porting guide][cobalt_porting_guide], we expected a few build files to be
+present under your starboard path:
+
+*   `gyp_configuration.py`
+*   `gyp_configuration.gypi`
+*   `starboard_platform.gyp`
+
+These contain your toolchain, your compilation flags, your platform-specific
+build variables, and your definition of the `starboard_platform` target. This
+maps to the GN files needed to port your platform:
+
+*   Your toolchain: `toolchain/BUILD.gn`
+*   Your compilation flags: `platform_configuration/BUILD.gn`
+*   Your platform-specific build variables:
+    `platform_configuration/configuration.gni`
+*   Your definition of the `starboard_platform` target: `BUILD.gn`
+
+Some of these files need to define certain targets:
+
+*   `toolchain/BUILD.gn`
+
+    The toolchain implementation is discussed in more detail
+    [below](#migrating-a-toolchain).
+
+    ```
+    toolchain("host") {
+      ...
+    }
+
+    toolchain("target") {
+      ...
+    }
+    ```
+
+*   `platform_configuration/BUILD.gn`
+
+    ```
+    config("platform_configuration") {
+      # Set the flags that were in gyp_configuration.gypi.
+    }
+    ```
+
+*   `BUILD.gn`
+
+    ```
+    static_library("starboard_platform") {
+      # Largely the same as the current starboard_platform.gyp.
+    }
+    ```
+
+### Adding Your Platform to Starboard
+
+Instead of implicitly searching directories for certain files like GYP did, we
+explicitly enumerate our ports and their locations.
+[platforms.gni](../platforms.gni) contains all of this information, and you'll
+need to add your platform to that list following the same format.
+
+### Migrating a Family of Platforms
+
+Cobalt's reference platforms when implemented in GYP mainly used variables to
+share sources and dependencies. In GN, we prefer putting shared sources and
+dependencies in a static_library that we depend on in the final
+`starboard_platform` `static_library` target. This means that configurations to
+particular files should be in the same `static_library` that files are in.
+
+### Migrating a Toolchain
+
+Cobalt expects you to set a target and a host toolchain for your build like so:
+
+```
+toolchain("host") {
+  ...
+}
+
+toolchain("target") {
+  ...
+}
+```
+
+You may define a toolchain from scratch following the [reference][gn_toolchain],
+or you can use the
+[gcc/clang templates](../../../build/toolchain/gcc_toolchain.gni) provided.
+Almost all of the reference platforms use these templates, so look to those as
+examples for how to use it correctly. Here's the linux-x64x11
+[toolchain/BUILD.gn file](../../linux/x64x11/toolchain/BUILD.gn).
+
+## Checking Your Migration
+
+There are a few different ways to ensure you've migrated a target successfully.
+You'll of course want to make sure you can build things after you've migrated
+them.
+
+### Validating a Target
+
+If you're migrating a single target, it's simple to check: just configure the
+build using the the necessary arguments then build that target with `ninja`,
+i.e.:
+
+```
+static_library("new_target") { ... }
+```
+
+```
+$ gn gen out/stub_debug --args='target_platform="stub" build_type="debug"'
+$ gn check out/stub_debug
+$ ninja -C out/stub_debug new_target
+```
+
+If this was equivalent to a GYP target, you can compare the ninja compilation
+databases by using [format_ninja.py](../../../tools/format_ninja.py) and a
+comparison tool, i.e. [meld](https://meldmerge.org/). This will allow you to see
+any changes in commands, i.e. with flags or otherwise.
+
+The following differences for ninja flags between GYP and GN don't cause any
+issues:
+
+1. The name of the intermediate .o, .d files is different in both cases: Here is
+   an example while compiling the same source file
+   ```
+   starboard/common/new.cc
+   ```
+   GYP generates:
+   ```
+   obj/starboard/common/common.new.cc.o
+   ```
+   GN generates:
+   ```
+   obj/starboard/common/common/new.o
+   ```
+2. The `-x` flag for specifying language is not present in GN migration.
+   For example GYP specifies `-x c` flag while building c language files for
+   certain targets. This flag is not specified while building any GN targets.
+
+### Validating a Platform
+
+Checking that an entire platform has been migrated successfully is slightly more
+involved. It can be easiest to start by copying provided stub implementation and
+continuously migrating it over, checking that it builds as you go along. If you
+don't go this route, you can instead start by building a small target (with few
+dependencies) then work your way up to building the `all` target.
+
+You can use the same comparison method of using `format_ninja.py` as discussed
+[in the section above](#validating-a-target).
+
+### Step by Step Stub to Your Platform Migration Guide
+
+This [document](../gn_migrate_stub_to_platform.md) outlines a step by step
+process for converting the stub platform's GN files to GN files that will be
+able to be built for your platform.
+
+[cobalt_porting_guide]: https://cobalt.dev/starboard/porting.html
+[gn_check_tool]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/reference.md#cmd_check
+[gn_doc_home]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs
+[gn_format_tool]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/reference.md#cmd_format
+[gn_getting_a_binary]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/#getting-a-binary
+[gn_home]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/
+[gn_language]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/language.md
+[gn_reference]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/reference.md
+[gn_style_guide]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/style_guide.md
+[gn_toolchain]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/reference.md#func_toolchain
+[gn_quick_start]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/quick_start.md
+[gyp_home]: https://gyp.gsrc.io/index.md
+[gyp_to_gn_chromium_code]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/cookbook.md#chromium-code
+[gyp_to_gn_cookbook]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/cookbook.md
+[gyp_to_gn_typical_modifications]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/cookbook.md#typical-sources-and-deps-modifications
+[gyp_to_gn_variable_mappings]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/cookbook.md#variable-mappings
diff --git a/src/cobalt/site/docs/gen/starboard/build/doc/migration_changes.md b/src/cobalt/site/docs/gen/starboard/build/doc/migration_changes.md
new file mode 100644
index 0000000..38d8477
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/build/doc/migration_changes.md
@@ -0,0 +1,72 @@
+---
+layout: doc
+title: "GYP to GN Migration Changes"
+---
+# GYP to GN Migration Changes
+
+This file tracks changes to configuration meta build configuration variables in
+the GYP to GN migration. Reference the table below to find the correct GN
+equivalent to a changed variable, deprecated GYP variables not in GN, and added
+variables.
+
+## Variable Changes
+
+*GYP*                                     | *GN*                                                 | *GN import*
+:---------------------------------------- | :--------------------------------------------------- | :----------
+`OS` ("starboard"/other)                  | `is_starboard` (true/false)                          | (global)
+`clang` (0/1)                             | `is_clang` (true/false)                              | (global)
+`has_input_events_filter`                 | `is_internal_build` (true/false)                     | (global)
+`has_drm_system_extension`                | `is_internal_build` (true/false)                     | (global)
+`has_cdm`                                 | `is_internal_build` (true/false)                     | (global)
+`has_private_system_properties`           | `is_internal_build` (true/false)                     | (global)
+`sb_deploy_output_dir`                    | `sb_install_output_dir`                              | `//starboard/build/config/base_configuration.gni`
+`sb_evergreen` (0/1)                      | `sb_is_evergreen` (true/false)                       | `//starboard/build/config/base_configuration.gni`
+`sb_evergreen_compatible` (0/1)           | `sb_is_evergreen_compatible` (true/false)            | `//starboard/build/config/base_configuration.gni`
+`sb_evergreen_compatible_libunwind` (0/1) | `sb_evergreen_compatible_use_libunwind` (true/false) | `//starboard/build/config/base_configuration.gni`
+`sb_evergreen_compatible_lite` (0/1)      | `sb_evergreen_compatible_enable_lite` (true/false)   | `//starboard/build/config/base_configuration.gni`
+`sb_disable_cpp14_audit`                  | (none)                                               |
+`sb_disable_microphone_idl`               | (none)                                               |
+`starboard_path`                          | (none)                                               |
+`tizen_os`                                | (none)                                               |
+`includes_starboard`                      | (none)                                               |
+(none)                                    | `has_platform_tests` (true/false)                    | `//starboard/build/config/base_configuration.gni`
+(none)                                    | `has_platform_targets` (true/false)                  | `//starboard/build/config/base_configuration.gni`
+(none)                                    | `install_target_path` (true/false)                   | `//starboard/build/config/base_configuration.gni`
+
+## Other Changes
+
+*GYP*                           | *GN*                                                  | *Notes* (see below)
+:------------------------------ | :---------------------------------------------------- | :------------------
+`'STARBOARD_IMPLEMENTATION'`    | `"//starboard/build/config:starboard_implementation"` | Starboard Implementation
+`optimize_target_for_speed` (0) | `"//starboard/build/config:size"`                     | Optimizations
+`optimize_target_for_speed` (1) | `"//starboard/build/config:speed"`                    | Optimizations
+`compiler_flags_*_speed`        | `speed_config_path`                                   | Optimizations
+`compiler_flags_*_size`         | `size_config_path`                                    | Optimizations
+`sb_pedantic_warnings`          | `pedantic_warnings_config_path`                       | Compiler Options
+`sb_pedantic_warnings`          | `no_pedantic_warnings_config_path`                    | Compiler Options
+
+Notes:
+
+*   *Starboard Implementation:* If your platform defined
+    `STARBOARD_IMPLENTATION` in its implementation, you would now add the above
+    config with `configs +=
+    ["//starboard/build/config:starboard_implementation"]`.
+
+*   *Optimizations:* Cobalt defaults to building targets to optimize for size.
+    If you need to optimize a target for speed, remove the size config and add
+    the speed config with `configs -= [ "//starboard/build/config:size" ]` and
+    `configs += [ "//starboard/build/config:speed" ]`. You can define these
+    configurations for your platform by creating `config`s and pointing to the
+    correct ones for `speed_config_path` and `size_config_path` in your
+    platform's `platform_configuration/configuration.gni` file.
+
+*   *Compiler Options:* Cobalt compiles some targets with stricter settings
+    than others, depending on the platform. Before these targets would opt into
+    the stricter settings by settings `sb_pedantic_warnings: 1` in their
+    `variables` section. Now they will add the appropriate config like so:
+    `configs += [ "//starboard/build/config:pedantic_warnings" ]` and remove
+    the default: `configs -= [ "//starboard/build/config:no_pedantic_warnings"
+    ]`. The additional config that is used to compile these targets is
+    specified with the `pedantic_warnings_config_path` and
+    `no_pedantic_warnings_config_path` variables in your platform's
+    `platform_configuration/configuration.gni` file.
diff --git a/src/cobalt/site/docs/gen/starboard/doc/abstract-toolchain.md b/src/cobalt/site/docs/gen/starboard/doc/abstract-toolchain.md
new file mode 100644
index 0000000..c60daa1
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/abstract-toolchain.md
@@ -0,0 +1,57 @@
+---
+layout: doc
+title: "Abstract Toolchain"
+---
+# Abstract Toolchain
+
+## Motivation
+
+The aim of implementing an Abstract Toolchain is to allow porters to add
+new toolchains or customize existing ones without the need of modifying
+common code.
+
+Initially all targets were defined in one common shared file,
+`src/tools/gyp/pylib/gyp/generator/ninja.py`.
+Modifications to this file were required for replacing any of the toolchain
+components, adding platform-specific tooling, adding new toolchains, or
+accomodating platform-specific flavor of reference tool. Doing this in a
+shared file does not scale with the number of ports.
+
+## Overview
+
+The solution implemented to solve toolchain abstraction consists of adding two
+new functions to the platform specific `gyp_configuration.py` file found under:
+
+`starboard/<PLATFORM>/gyp_configuration.py`
+
+The functions to implement are:
+
+`GetHostToolchain` and `GetTargetToolchain`
+
+## Example
+
+The simplest complete GCC based toolchain, where a target and host are the same,
+and all tools are in the PATH:
+
+  class ExamplePlatformConfig(starboard.PlatformConfig)
+    # ...
+
+    def GetTargetToolchain(self):
+      return [
+        starboard.toolchains.gnu.CCompiler(),
+        starboard.toolchains.gnu.CPlusPlusCompiler(),
+        starboard.toolchains.gnu.Assembler(),
+        starboard.toolchains.gnu.StaticLinker(),
+        starboard.toolchains.gnu.DynamicLinker(),
+        starboard.toolchains.gnu.Bison(),
+        starboard.toolchains.gnu.Stamp(),
+        starboard.toolchains.gnu.Copy(),
+      ]
+
+    def GetHostToolchain(self):
+      return self.GetTargetToolchain()
+
+You can find real examples of this in the Open Source repo:
+[Linux x8611](https://cobalt.googlesource.com/cobalt/+/refs/heads/21.lts.1+/src/starboard/linux/x64x11/gyp_configuration.py)
+
+[Raspberry Pi 2](https://cobalt.googlesource.com/cobalt/+/refs/heads/21.lts.1+/src/starboard/raspi/shared/gyp_configuration.py)
diff --git a/src/cobalt/site/docs/gen/starboard/doc/api_process.md b/src/cobalt/site/docs/gen/starboard/doc/api_process.md
new file mode 100644
index 0000000..0d699d2
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/api_process.md
@@ -0,0 +1,72 @@
+---
+layout: doc
+title: "Starboard API Review Process"
+---
+# Starboard API Review Process
+
+## Why do we need a process?
+The Starboard API is the contract between Starboard applications and
+implementors of the Starboard API. Changing existing APIs and adding new
+required APIs breaks that contract and increases the cost of implementors
+keeping their Starboard port up-to-date. Pushing a release to the Open Source
+repository signals to Starboard implementors that any non-experimental APIs in
+that version will not change for as long as that version of Starboard is
+supported by the Starboard applications. We cannot change those newly frozen
+APIs without causing a potentially significant disruption to any partners who
+have already implemented them, or are in the process of implementing them.
+
+While having a process may make it harder to add new things to Starboard, it is
+much harder to remove or change things that are already there.
+
+Thus we need to give special focus to changes to the Starboard API to ensure its
+consistency with existing APIs design principles. Unnecessary churn on the
+Starboard API creates more work for Starboard application developers and may
+discourage porters from keeping Starboard applications up-to-date on their
+platforms. This process is intended to save time and effort for both Starboard
+application developers and Starboard implementors in the long run, and
+illustrates the complexity of dealing with a wide variety of platforms
+simultaneously.
+
+## So you want to add a new API?
+Historically, we have done API review as a part of the Code Review process using
+Gerrit. This works well for small-ish changes. For larger changes, consider
+writing a design document up front before defining the new API.
+
+### Who does the review?
+Send a message to the public cobalt-dev group to request a review.
+
+### What is the process?
+Developers are strongly encouraged to create the interface and upload that to
+Gerrit for review before spending time on stubs and tests. Iteration on the
+interface will necessarily result in changes to the stubs and tests, which can
+result in more work for the implementer of a new API.
+
+1. Upload a .h file with Module Overview and (optionally) initial function
+   prototypes
+    * New APIs should be declared in the experimental version, as described in the
+      starboard versioning doc.
+2. Discuss the new API with whoever is performing the review, and address
+   comments.
+3. Iterate.
+    * As a part of the review process, the reviewer will work with you to ensure
+      that the new API adheres to the starboard principles.
+4. Finalize function declarations.
+5. Implement tests and stubs.
+    * Existing platforms on trunk should not break as a result of this change.
+    * At this point, you may submit the interface, tests, and stubs with your
+      reviewer’s +2.
+6. Implement the interface for at least one platform.
+7. Iterate
+8. It may be that implementation of the API reveals things that were overlooked
+   during the earlier stages of the review.
+
+Ideally most major points of feedback will be caught early in the review process
+before much time has been spent on implementation.
+In the case that the platform in (6) is an internal platform, provide a
+reference implementation for at least one external reference platform. This can
+be in a follow-up CL, but must be implemented before the new API is frozen
+(see [versioning.md](versioning.md)).
+
+## How to design a new API
+See [principles.md](principles.md) for a guide on how to design a good Starboard
+API.
diff --git a/src/cobalt/site/docs/gen/starboard/doc/building.md b/src/cobalt/site/docs/gen/starboard/doc/building.md
new file mode 100644
index 0000000..0281e71
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/building.md
@@ -0,0 +1,99 @@
+---
+layout: doc
+title: "Building Starboard"
+---
+# Building Starboard
+
+Starboard currently uses GYP as the basis of its build system, though there is
+already some movement towards GN as a replacement.
+
+While you can integrate Starboard into any build system, there are enough knobs
+and dials that it would be a daunting effort. Instead, Starboard tries to provide a
+functional build framework that an application developer can easily integrate with.
+
+
+## The Flow
+
+The basic flow of how Starboard builds is:
+
+1. `starboard/build/gyp` - Parse command line parameters and pass them into
+   `GypRunner`.
+2. `starboard/build/gyp_runner.py`
+   1. Load the `PlatformConfiguration`.
+   2. Load the `ApplicationConfiguration`.
+   3. Calculate and merge the GYP includes, GYP variables, environment
+      variables, and generator variables, and pass them into GYP.
+3. tools/gyp - Parse all the .gyp and included .gypi files, generate ninja.
+4. ninja - Build all the source files.
+
+
+## The Platform vs. the Application
+
+In this documentation, you will see a lot of discussion about things being
+Platform or Application concerns.
+
+The Platform is more-or-less what you think it is -- Everything you might need
+to build any Starboard Application on a given platform.
+
+It helps to think about an Application as a broader concept than a single
+program. From Starboard's build system's perspective, an Application is a
+*single configuration of build variables per platform*, which may produce many
+build targets beyond a single executable - shared libraries, tests, and so on.
+
+
+## Application Customization
+
+Each Application will probably want to define its own knobs, dials, and defaults
+to be able to be customized per platform, and so Starboard provides a space for
+the Application to do that.
+
+Each Application can provide a platform-specific ApplicationConfiguration
+instance by creating a python module in
+`<platform-directory>/<application-name>/configuration.py`. This module must
+contain a class definition that extends from
+`starboard.build.application_configuration.ApplicationConfiguration`. If the
+class is not found in the platform-specific location, a generic configuration
+will be loaded, as dictated by the `APPLICATIONS` registry in
+`starboard_configuration.py`.
+
+Additionally, the Application can provide a GYPI file to be included at
+`<platform-directory>/<application-name>/configuration.gypi`. This will, by
+default, be included at the end of all other configuration GYPI files, but this
+behavior can be arbitrarily customized by the loaded `ApplicationConfiguration`
+class.
+
+
+## HOWTO: Create a new Application
+
+1. Create your Application's root `.gyp` file. Often called `all.gyp` or
+   something similar.
+
+2. Create a cross-platform `ApplicationConfiguration` python class for your
+   application. Take a look at
+   [`cobalt_configuration.py`](../../cobalt/build/cobalt_configuration.py) as an
+   example.
+
+   Define a subclass of
+   `starboard.build.application_configuration.ApplicationConfiguration` and
+   override any desired methods. In particular, you probably at least want to
+   override the `GetDefaultTargetBuildFile()` method to point at your root
+   `.gyp` file from step 1.
+
+3. Register your Application in your `starboard_configuration.py` file in your
+   source tree root.
+
+   To do this, just add an entry to the `APPLICATIONS` Mapping that maps your
+   canonical Application name to the cross-platform `ApplicationConfiguration`
+   subclass constructor for your application.
+
+       APPLICATIONS = {
+           # ...
+
+           'example_app': example_app.ExampleAppConfiguration
+
+           # ...
+       }
+
+At this point, you should be able to build your application with:
+
+    starboard/build/gyp -a <application-name>
diff --git a/src/cobalt/site/docs/gen/starboard/doc/c99.md b/src/cobalt/site/docs/gen/starboard/doc/c99.md
new file mode 100644
index 0000000..3aed66d
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/c99.md
@@ -0,0 +1,82 @@
+---
+layout: doc
+title: "Starboard and C99"
+---
+# Starboard and C99
+
+## Background
+
+Historically Starboard did not allow usage of standard C symbols in order to
+isolate Cobalt from non-compliant libc implementations and to provide a single,
+consistent behavior at the Starboard API layer.
+
+## C99 Usage Rationale
+1. Inconsistencies in the libc libraries are rare and all third party libraries
+need to be ported to the Starboard API. This can be a significant maintenance
+cost as the dependencies need to be periodically rebased.
+
+2. Even with all the efforts to use POEM headers from the
+[starboard/client_porting](../../starboard/client_porting) directory many
+non-Evergreen platforms still have a lot of direct system dependencies. These
+dependencies do not exist for Evergreen platforms as Cobalt is statically
+linked with the [musl](../../third_party/musl/musl.gyp) libc library.
+
+3. Starting with Starboard 13 a limited set of C99 symbols will be allowed.
+This set will expand gradually while the corresponding Starboard APIs will be
+deprecated and eventually removed.
+
+## List of Allowed C99 Symbols
+### <ctype.h>
+* isalnum
+* isdigit
+* isspace
+* isupper
+* isxdigit
+* tolower
+* toupper
+### <math.h>
+* fabs
+* floor
+* isfinite
+* isnan
+* pow
+* sqrt
+* sqrtf
+### <stdlib.h>
+* abs
+* atoi
+* atol
+* bsearch
+* strtof
+* strtod
+* strtol
+* strtoll
+* strtoul
+* strtoull
+* qsort
+### <string.h>
+* memchr
+* memcmp
+* memcpy
+* memmove
+* memset
+* strcat
+* strchr
+* strcmp
+* strcspn
+* strlen
+* strncmp
+* strncat
+* strrchr
+* strstr
+* strspn
+### <wchar.h>
+* wcscat
+* wcschr
+* wcslen
+* wmemchr
+* wmemcmp
+* wmemcpy
+* wmemmove
+* wmemset
+* wcsncmp
diff --git a/src/cobalt/site/docs/gen/starboard/doc/crash_handlers.md b/src/cobalt/site/docs/gen/starboard/doc/crash_handlers.md
new file mode 100644
index 0000000..2f30683
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/crash_handlers.md
@@ -0,0 +1,56 @@
+---
+layout: doc
+title: "Installing Crash Handlers in Cobalt"
+---
+# Installing Crash Handlers in Cobalt
+
+Partners can install Crashpad's crash handlers to create crash reports in the
+cache directory. This is done by:
+
+1. Adding the following files to the `starboard_platform` target's sources:
+
+```
+'<(DEPTH)/starboard/shared/starboard/crash_handler.cc',
+'<(DEPTH)/starboard/shared/starboard/crash_handler.h',
+```
+
+2. Handling `kCobaltExtensionCrashHandlerName` in the implementation of
+`SbSystemGetExtension`:
+
+```
+#include "starboard/system.h"
+
+#include "cobalt/extension/crash_handler.h"
+#include "starboard/shared/starboard/crash_handler.h"
+
+...
+
+const void* SbSystemGetExtension(const char* name) {
+
+  ...
+
+  if (SbStringCompareAll(name, kCobaltExtensionCrashHandlerName) == 0) {
+    return starboard::common::GetCrashHandlerApi();
+  }
+  return NULL;
+}
+```
+
+3. Calling the `third_party::crashpad::wrapper::InstallCrashpadHandler()` hook
+directly after installing system crash handlers. On linux, for example, this
+could look like:
+
+```
+#include "third_party/crashpad/wrapper/wrapper.h"
+
+int main(int argc, char** argv) {
+  ...
+  starboard::shared::signal::InstallCrashSignalHandlers();
+  starboard::shared::signal::InstallSuspendSignalHandlers();
+
+  third_party::crashpad::wrapper::InstallCrashpadHandler();
+
+  int result = application.Run(argc, argv);
+  ...
+}
+```
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_evergreen_lite.md b/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_evergreen_lite.md
new file mode 100644
index 0000000..93ff983
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_evergreen_lite.md
@@ -0,0 +1,182 @@
+---
+layout: doc
+title: "Evergreen Lite Partner Doc"
+---
+Evergreen Lite Partner Doc
+
+
+## What is Cobalt Evergreen Lite?
+
+Evergreen Lite is a Cobalt configuration similar to Evergreen Full. Evergreen
+Lite takes advantage of the same Evergreen software architecture, but removes
+the need for additional storage and is missing the defining cloud-based Cobalt
+Updater feature used in Evergreen Full.
+
+Evergreen Lite relies on separating the Starboard (platform) and Cobalt (core)
+components of a Cobalt implementation into the following discrete components:
+
+![Evergreen Lite Overvew](resources/evergreen_lite_overview.png)
+
+## Components
+
+Google-built (on Google toolchain)
+
+
+*   Cobalt Core
+    *   Pre-built shared library available for all supported architectures
+*   Cobalt Updater - disabled
+
+Partner-built (on Partner toolchain)
+
+
+
+*   Starboard
+    *   Platform-specific implementation
+    *   Contains system dependencies (e.g. libpthread.so, libEGL.so)
+*   Cobalt Loader (Loader App)
+    *   Loads the Cobalt core shared library
+    *   An ELF loader is used to load the Cobalt core and resolves symbols with
+        Starboard APIs when Cobalt starts up in Evergreen mode
+*   Crash handler
+    *   Uploads crash reports to Google server when crash happens
+
+With this new Cobalt Evergreen platform architecture, less engineering effort is
+ necessary for a full Cobalt integration/deployment.
+
+**The idea here is you should only need to implement Starboard one time (as
+long as the Starboard API version is supported by Cobalt), and any Cobalt
+Core-level binary updates are provided by Google with pre-built
+configurations/symbols via our open-source releases
+([GitHub](https://github.com/youtube/cobalt/releases))**. These pre-built
+Cobalt Core Evergreen binaries should be a direct replacement to update Cobalt
+without any engineering work required. As Cobalt Core binaries are pre-built,
+they should only require platform testing. NOTE that certain new Cobalt
+features may require Starboard changes, so if you want to take advantage of
+some of these new features, Starboard changes may be necessary.
+
+### Benefits compared to non-Evergreen
+
+*   Less engineering work/accelerated timeline for Cobalt
+integration/deployment as Google builds Cobalt core code and partners only need
+to build and maintain the Starboard layer
+*   Performance enhancements as the Cobalt core is built with modern toolchain
+*   Crash reports are uploaded to Google backend and monitored by Google, so
+they can be acted on and addressed more quickly
+
+### New in Evergreen Lite compared to non-Evergreen
+
+*   New `loader_app` and `crashpad_handler` components required to be built
+on platform toolchains
+*   No Cobalt Core customization is allowed because the vanilla Cobalt Core
+binary is provided by Google.
+
+### Differences compared to Evergreen Full
+
+*   The Google-control cloud-based automatic updates are disabled. Instead,
+Cobalt provides the update binary to partners, and partners control the release
+process
+*   No extra storage required comparing to the existing software requirements
+
+## How is Evergreen different from porting Cobalt previously?
+
+Same as the [Evergreen full doc](cobalt_evergreen_overview.md).
+
+## Building Cobalt Evergreen Components
+
+`kSbSystemPathStorageDirectory` is not required to implement. Set both
+`sb_evergreen_compatible` and `sb_evergreen_compatible_lite` to `1`s in the `gyp`
+platform config. The remaining is the same as the Evergreen full doc.
+
+## How does the update work with Evergreen Lite?
+
+Cobalt will release the Cobalt Core binary to partners for each Cobalt LTS
+major and minor release, and partners decide whether to update their devices
+with the latest Cobalt Core code via firmware OTA update. To update, partners
+only need to put the new Cobalt Core binary at the system image location under
+`<kSbSystemPathContentDirectory>/app/cobalt`. More about the system image slot
+is explained below.
+
+## Platform Requirements
+
+Cobalt Evergreen currently supports the following
+
+Target Architectures:
+
+*   `x86_32`
+*   `x86_64`
+*   `armv7 32`
+*   `armv8 64`
+
+Supported Javascript Engines
+
+*   V8
+
+## Building and Running Tests
+
+Same as the Evergreen Full doc -
+[cobalt_evergreen_overview.md](cobalt_evergreen_overview.md).
+
+## System Design
+
+### Cobalt Evergreen Components
+
+Cobalt updater is disabled. The binary will not check for updates by sending
+requests to the Google update server, nor download updates from the Google
+Download server.
+
+### Cobalt Evergreen Interfaces
+
+Same as the Evergreen Full doc -
+[cobalt_evergreen_overview.md](cobalt_evergreen_overview.md).
+
+### System Image Slot
+
+Evergreen Lite will have only one system image slot.  This is stored in the
+directory specified by `kSbSystemPathContentDirectory` under the
+`app/cobalt` subdirectory.
+
+```
+.
+├── content <--(kSbSystemPathContentDirectory)
+│   └── fonts <--(kSbSystemPathFontDirectory, `standard` or `limit` configuration)
+│   └── app
+│       └── cobalt <--(System image, provided by Google)
+│           ├── content <--(relative path defined in kSystemImageContentPath)
+│           │   ├── fonts <--(`empty` configuration)
+│           │   ├── icu
+│           │   ├── licenses
+│           │   ├── ssl
+│           ├── lib
+│           │   └── libcobalt.so
+│           └── manifest.json
+└── loader_app <--(Cobalt loader binary)
+└── crashpad_handler <--(Cobalt crash handler binary)
+```
+
+### Fonts
+
+Same as the Evergreen Full doc -
+[cobalt_evergreen_overview.md](cobalt_evergreen_overview.md).
+
+## How to run Evergreen Lite
+
+Launch Cobalt with the loader app binary with the `evergreen_lite` flag
+
+```
+$ ./loader_app --evergreen_lite
+```
+## FAQ
+
+### What’s the path from Evergreen Lite to Evergreen Full?
+
+*   Provision storage for the installation slots to contain downloaded update
+binaries - `kSbSystemPathStorageDirectory `and configure the slots as instructed
+in the Evergreen full doc
+*   Configure icu table under `kSbSystemPathStorageDirectory` to be shared
+    among slots
+*   Set `sb_evergreen_compatible_lite` to 0
+*   Implement the handling of pending updates
+*   Rebuild and rerun `nplb_evergreen_compat_tests`
+*   Launch Cobalt with loader app without the `evergreen_lite` flag
+
+More details can be found in the Evergreen Full doc.
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_evergreen_overview.md b/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_evergreen_overview.md
new file mode 100644
index 0000000..4e07d8e
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_evergreen_overview.md
@@ -0,0 +1,728 @@
+---
+layout: doc
+title: "Cobalt Evergreen Overview"
+---
+# Cobalt Evergreen Overview
+
+![Cobalt non-Evergreen vs
+Evergreen](resources/cobalt_evergreen_overview_flow.png)
+
+## What is Cobalt Evergreen?
+
+Cobalt Evergreen is an end-to-end framework for cloud-based deployment of Cobalt
+updates without the need for supplemental Cobalt integration work on device
+platforms.
+
+There are two configurations available:
+*   Evergreen-Lite
+    *   Please read this document for general Evergreen details then see
+        Evergreen-Lite specific configuration details in
+        [cobalt_evergreen_lite.md](cobalt_evergreen_lite.md)
+*   Evergreen Full
+    *   Please continue reading below documentation for configuration details
+
+![Cobalt Evergreen Configurations](resources/cobalt_evergreen_configurations.png)
+
+For a bit of background context, as the number of Cobalt devices in the field
+increases there is a growing proliferation of version fragmentation. Many of
+these devices are unable to take advantage of the benefits of Cobalt
+performance, security, and functional improvements as it is costly to integrate
+and port new versions of Cobalt. We recognized this issue, listened to feedback
+from the Cobalt community and as a result developed Cobalt Evergreen as a way to
+make updating Cobalt a much simpler process for everyone involved.
+
+This relies on separating the Starboard(platform) and Cobalt(core) components of
+a Cobalt implementation into the following discrete components:
+
+**Google-built** (on Google toolchain)
+
+*   Cobalt Core
+    *   Pre-built shared library available for all supported architectures
+*   Cobalt Updater
+    *   Part of Cobalt Core and used to query servers to check for and download
+        updated Cobalt Core
+
+**Partner-built** (on Partner toolchain)
+
+*   Starboard
+    *   Platform-specific implementation
+    *   Contains system dependencies (e.g. `libpthread.so`, `libEGL.so`)
+*   Cobalt Loader (Loader App)
+    *   Selects the appropriate Cobalt core for usage
+    *   An ELF loader is used to load the Cobalt core and resolves symbols with
+        Starboard APIs when Cobalt starts up in Evergreen mode
+
+With this new Cobalt platform architecture, less engineering effort is necessary
+for a full Cobalt integration/deployment. The idea here is you should only need
+to implement Starboard one time and any Cobalt-level updates should only require
+platform testing. NOTE that certain new Cobalt features may require Starboard
+changes, so if you want to take advantage of some of these new features,
+Starboard changes may be necessary.
+
+### Main Benefits
+
+*   More stable platform as there is less Cobalt version fragmentation
+*   Little-to-no engineering effort necessary for Cobalt updates
+*   Longer device lifetime due to more Cobalt updates
+*   Less engineering work/accelerated timeline for Cobalt integration/deployment
+    as Google builds the Cobalt components and partners are only responsible for
+    the Starboard, `loader_app`, and `crashpad_handler` portion
+
+### New in Evergreen
+
+*   Larger storage and system permissions requirements in order to update and
+    store multiple Cobalt binaries
+*   Access permissions to download binaries onto a device platform from Google
+    servers
+*   New `loader_app` and `crashpad_handler` components required to be built on
+    platform toolchains
+*   Additional testing/verification required to ensure new Cobalt releases work
+    properly
+
+## How is Evergreen different from porting Cobalt previously?
+
+There are minimal differences in switching to Evergreen as the Cobalt team has
+already done a majority of the work building the necessary components to support
+the Evergreen architecture. You will still be responsible for building the
+Starboard and platform-specific components as usual. Thereafter, switching to
+Evergreen is as simple as building a different configuration. Please see the
+Raspberry Pi 2 Evergreen reference port
+([Instructions](cobalt_evergreen_reference_port_raspi2.md)) for an example.
+
+![Cobalt non-Evergreen vs
+Evergreen](resources/cobalt_evergreen_overview_vs_non_evergreen.png)
+
+### Building Cobalt Evergreen Components
+
+Cobalt Evergreen requires that there are two separate build(`gyp`)
+configurations used due to the separation of the Cobalt core(`libcobalt.so`) and
+the platform-specific Starboard layer(`loader_app`). As a result, you will have
+to initiate a separate gyp process for each. This is required since the Cobalt
+core binary is built with the Google toolchain settings and the
+platform-specific Starboard layer is built with partner toolchain
+configurations.
+
+Cobalt Evergreen is built by a separate gyp platform using the Google toolchain:
+
+```
+$ cobalt/build/gyp_cobalt evergreen-arm-softfp-sbversion-12
+$ ninja -C out/evergreen-arm-softfp-sbversion-12_qa cobalt
+```
+
+Which produces a shared library `libcobalt.so` targeted for specific
+architecture, ABI and Starboard version.
+
+The gyp variable `sb_evergreen` is set to 1 when building `libcobalt.so`.
+
+The partner port of Starboard is built with the partner’s toolchain and is
+linked into the `loader_app` which knows how to dynamically load
+`libcobalt.so`, and the `crashpad_handler` which handles crashes.
+
+```
+$ cobalt/build/gyp_cobalt <partner_port_name>
+$ ninja -C out/<partner_port_name>_qa loader_app crashpad_handler
+```
+
+Partners should set `sb_evergreen_compatible` to 1 in their gyp platform config.
+DO NOT set the `sb_evergreen` to 1 in your platform-specific configuration as it
+is used only by Cobalt when building with the Google toolchain.
+
+Additionally, partners should install crash handlers as instructed in the
+[Installing Crash Handlers for Cobalt guide](../crash_handlers.md).
+
+The following additional Starboard interfaces are necessary to implement for
+Evergreen:
+
+*   `kSbSystemPathStorageDirectory`
+    *   Dedicated location for storing Cobalt Evergreen-related binaries
+    *   This path must be writable and have at least 96MB of reserved space for
+        Evergreen updates. Please see the “Platforms Requirements” section below
+        for more details.
+*   `kSbMemoryMapProtectExec`
+    *   Ensures mapped memory can be executed
+*   `#define SB_CAN_MAP_EXECUTABLE_MEMORY 1`
+    *   Specifies that the platform can map executable memory
+    *   Defined in `configuration_public.h`
+
+Only if necessary, create a customized SABI configuration for your architecture.
+Note, we do not anticipate that you will need to make a new configuration for
+your platform unless it is not one of our supported architectures:
+
+*   x86\_32
+*   x86\_64
+*   arm32
+*   arm64
+
+If your target architecture falls outside the support list above, please reach
+out to us for guidance.
+
+#### Adding Crash Handlers to Evergreen
+
+### What is an example for how this would help me?
+
+Some common versions of Cobalt in the field may show a bug in the implementation
+of the CSS which can cause layout behavior to cause components to overlap and
+give users a poor user experience. A fix for this is identified and pushed to
+Cobalt open source ready for integration and deployment on devices.
+
+#### Without Cobalt Evergreen:
+
+Though a fix for this was made available in the latest Cobalt open source,
+affected devices in the field are not getting updated (e.g. due to engineering
+resources, timing, device end-of-life), users continue to have a poor experience
+and have negative sentiment against a device. In parallel, the web app team
+determines a workaround for this particular situation, but the workaround is
+obtuse and causes app bloat and technical debt from on-going maintenance of
+workarounds for various Cobalt versions.
+
+#### With Cobalt Evergreen:
+
+The Cobalt team can work with you to guide validation and deployment of a shared
+Cobalt library to all affected devices much more quickly without all the
+engineering effort required to deploy a new Cobalt build. With this simpler
+updating capability, device behavior will be more consistent and there is less
+technical debt from workarounds on the web application side. Additionally, users
+can benefit from the latest performance, security, and functional fixes.
+
+## Platform Requirements
+
+Cobalt Evergreen currently supports the following
+
+Target Architectures:
+
+*   x86\_32
+*   x86\_64
+*   armv7 32
+*   armv8 64
+
+Supported Javascript Engines
+
+*   V8
+
+Additional reserved storage (96MB) is required for Evergreen binaries. We expect
+Evergreen implementations to have an initial Cobalt preloaded on the device and
+an additional reserved space for additional Cobalt update storage.
+
+*   Initial Cobalt binary deployment - 64MB
+*   Additional Cobalt update storage - 96MB
+    *   Required for 2 update slots under `kSbSystemPathStorageDirectory`
+
+As Cobalt Evergreen is intended to be updated from Google Cloud architecture
+without the need for device FW updates, it is important that this can be done
+easily and securely on the target platform. There are a set of general minimum
+requirements to do so:
+
+*   Writable access to the file system of a device platform to download Cobalt
+    Evergreen binaries
+*   Enough reserved storage for Cobalt updates
+*   Platform supporting mmap API with writable memory (`PROT_WRITE`,
+    `PROT_EXEC`) for loading in-memory and performing relocations for Cobalt
+    Evergreen binaries
+
+## Building and Running Tests
+
+The `elf_loader_sandbox` binary can be used to run tests in Evergreen mode. This
+is much more lightweight than the `loader_app`, and does not have any knowledge
+about installations or downloading updates.
+
+The `elf_loader_sandbox` is run using two command line switches:
+`--evergreen_library` and `--evergreen_content`. These switches are the path to
+the shared library to be run and the path to that shared library's content.
+These paths should be *relative to the content of the elf_loader_sandbox*.
+
+For example, if we wanted to run the NPLB set of tests and had the following
+directory tree,
+
+```
+.../elf_loader_sandbox
+.../content/app/nplb/lib/libnplb.so
+.../content/app/nplb/content
+```
+
+we would use the following command to run NPLB:
+
+```
+.../elf_loader_sandbox --evergreen_library=app/nplb/lib/libnplb.so
+                       --evergreen_content=app/nplb/content
+```
+
+Building tests is identical to how they are already built except that a
+different platform configuration must be used. The platform configuration should
+be an Evergreen platform configuration, and have a Starboard ABI file that
+matches the file used by the platform configuration used to build the
+`elf_loader_sandbox`.
+
+For example, building these targets for the Raspberry Pi 2 would use the
+`raspi-2` and `evergreen-arm-hardfp` platform configurations.
+
+## Verifying Platform Requirements
+
+In order to verify the platform requirements you should run the
+`nplb_evergreen_compat_tests`. These tests ensure that the platform is
+configured appropriately for Evergreen.
+
+To enable the test, set the `sb_evergreen_compatible gyp` variable to 1 in the
+`gyp_configuration.gypi`. For more details please take a look at the Raspberry
+Pi 2 gyp files.
+
+There is a reference implementation available for Raspberry Pi 2 with
+instructions available [here](cobalt_evergreen_reference_port_raspi2.md).
+
+### Verifying Crashpad Uploads
+
+1. Build the `crashpad_database_util` target and deploy it onto the device.
+```
+$ cobalt/build/gyp_cobalt <partner_port_name>
+$ ninja -C out/<partner_port_name>_qa crashpad_database_util
+```
+2. Remove the existing state for crashpad as it throttles uploads to 1 per hour:
+```
+$ rm -rf <kSbSystemPathCacheDirectory>/crashpad_database/
+
+```
+3. Launch Cobalt.
+4. Trigger crash by sending `abort` signal to the `loader_app` process:
+```
+$ kill -6 <pid>
+```
+5. Verify the crash was uploaded through running `crashpad_database_util` on the device
+pointing it to the cache directory, where the crash data is stored.
+
+```
+$ crashpad_database_util -d <kSbSystemPathCacheDirectory>/crashpad_database/ --show-completed-reports --show-all-report-info
+```
+
+```
+8c3af145-30a0-43c7-a3a5-0952dea230e4:
+  Path: cobalt/cache/crashpad_database/completed/8c3af145-30a0-43c7-a3a5-0952dea230e4.dmp
+  Remote ID: c9b14b489a895093
+  Creation time: 2021-06-01 17:01:19 HDT
+  Uploaded: true
+  Last upload attempt time: 2021-06-01 17:01:19 HDT
+  Upload attempts: 1
+```
+
+In this example the minidump was successfully uploaded because we see `Uploaded: true`.
+
+Reference for [crashpad_database_util](https://chromium.googlesource.com/crashpad/crashpad/+/refs/heads/main/tools/crashpad_database_util.md)
+
+## System Design
+
+![Cobalt Evergreen
+Components](resources/cobalt_evergreen_overview_components.png)
+
+The above diagram is a high-level overview of the components in the Cobalt
+Evergreen architecture.
+
+* **Partner-built** represents components the Partner is responsible for
+  implementing and building.
+
+* **Cobalt-built** represents components the Cobalt team is responsible for
+  implementing and building.
+
+### Cobalt Evergreen Components
+
+#### Cobalt Updater
+
+This is a new component in the Cobalt Shared Library component that is built on
+top of the Starboard API. The purpose of this module is to check the update
+servers if there is a new version of the Cobalt Shared Library available for the
+target device. If a new version is available, the Cobalt updater will download,
+verify, and install the new package on the target platform. The new package can
+be used the next time Cobalt is started or it can be forced to update
+immediately and restart Cobalt as soon as the new package is available and
+verified on the platform. This behavior will take into account the
+suspend/resume logic on the target platform.
+
+Functionally, the Cobalt Updater itself runs as a separate thread within the
+Cobalt process when Cobalt is running. This behavior depends on what the target
+platform allows.
+
+For more detailed information on Cobalt Updater, please take a look
+[here](cobalt_update_framework.md).
+
+#### Google Update (Update Server)
+
+We use Google Update as the infrastructure to manage the Cobalt Evergreen
+package install and update process. This has been heavily used across Google for
+quite some time and has the level of reliability required for Cobalt Evergreen.
+There are also other important features such as:
+
+*   Fine grained device targeting
+*   Rollout and rollback
+*   Multiple update channels (e.g. production, testing, development)
+*   Staged rollouts
+
+For more detailed information on Google Update for Cobalt Evergreen, please take
+a look [here](cobalt_update_framework.md).
+
+#### Google Downloads (Download Server)
+
+We use Google Downloads to manage the downloads available for Cobalt Evergreen.
+The Cobalt Updater will use Google Downloads in order to download available
+packages onto the target platform. We selected Google Downloads for this purpose
+due to its ability to scale across billions of devices as well as the
+flexibility to control download behavior for reliability.
+
+For more detailed information on Google Downloads (Download Server) for Cobalt
+Evergreen, please take a look [here](cobalt_update_framework.md).
+
+### Cobalt Evergreen Interfaces
+
+#### Starboard ABI
+
+The Starboard ABI was introduced to provide a single, consistent method for
+specifying the Starboard API version and the ABI. This specification ensures
+that any two binaries, built with the same Starboard ABI and with arbitrary
+toolchains, are compatible.
+
+Note that Cobalt already provides default SABI files for the following
+architectures:
+
+*   x86\_32
+*   x86\_64
+*   arm v7 (32-bit)
+*   arm v8 (64-bit)
+
+You should not need to make a new SABI file for your target platform unless it
+is not a currently supported architecture. We recommend that you do not make any
+SABI file changes. If you believe it is necessary to create a new SABI file for
+your target platform, please reach out to the Cobalt team to advise.
+
+For more detailed information on the Starboard ABI for Cobalt Evergreen, please
+take a look here.
+
+### Installation Slots
+
+Cobalt Evergreen provides support for maintaining multiple, separate versions of
+the Cobalt binary on a platform. These versions are stored in installation
+slots(i.e. known locations on disk), and are used to significantly improve the
+resilience and reliability of Cobalt updates.
+
+All slot configurations assume the following:
+* 1 System Image Installation Slot (read-only)
+* 2+ Additional Installation Slot(s) (writable)
+
+The number of installation slots available will be determined by the platform
+owner. **3 slots is the default configuration for Evergreen**. There can be `N`
+installation slots configured with the only limitation being available storage.
+
+#### Slot Configuration
+NOTE: 3-slots is the DEFAULT configuration.
+
+The number of installation slots is directly controlled using
+`kMaxNumInstallations`, defined in
+[loader\_app.cc](../../loader_app/loader_app.cc).
+
+It is worth noting that all slot configurations specify that the first
+installation slot (`SLOT_0`) will always be the read-only factory system image.
+This is permanently installed on the platform and is used as a fail-safe option.
+This is stored in the directory specified by `kSbSystemPathContentDirectory`
+under the `app/cobalt` subdirectory.
+
+All of the other installation slots are located within the storage directory
+specified by `kSbSystemPathStorageDirectory`. This will vary depending on the
+platform.
+
+For example, on the Raspberry Pi the `kSbSystemPathStorageDirectory` directory
+is `/home/pi/.cobalt_storage`, and the paths to all existing installation slots
+will be as follows:
+
+```
+/home/pi/<kSbSystemPathContentDirectory>/app/cobalt (system image installation SLOT_0) (read-only)
+/home/pi/.cobalt_storage/installation_1 (SLOT_1)
+/home/pi/.cobalt_storage/installation_2 (SLOT_2)
+...
+/home/pi/.cobalt_storage/installation_N (SLOT_N)
+```
+
+Where the most recent update is stored will alternate between the available
+writable slots. In the above example, this would be `SLOT_1`...`SLOT_N`.
+
+#### Understanding Slot Structure
+Slots are used to manage Cobalt Evergreen binaries with associated app metadata
+to select the appropriate Cobalt Evergreen binaries.
+
+See the below structures for an example 3-slot configuration.
+
+Structure for `kSbSystemPathContentDirectory` used for the read-only System
+Image required for all slot configurations:
+
+```
+.
+├── content <--(kSbSystemPathContentDirectory)
+│   └── fonts <--(kSbSystemPathFontDirectory, `standard` or `limit` configuration, to be explained below)
+│   └── app
+│       └── cobalt <--(SLOT_0)
+│           ├── content <--(relative path defined in kSystemImageContentPath)
+│           │   ├── fonts <--(`empty` configuration)
+│           │   ├── (icu) <--(only present when it needs to be updated by Cobalt Update)
+│           │   ├── licenses
+│           │   ├── ssl
+│           ├── lib
+│           │   └── libcobalt.so <--(System image version of libcobalt.so)
+│           └── manifest.json
+└── loader_app <--(Cobalt launcher binary)
+└── crashpad_handler <--(Cobalt crash handler)
+```
+
+Structure for `kSbSystemPathStorageDirectory` used for future Cobalt Evergreen
+updates in an example 3-slot configuration:
+
+```
+├── .cobalt_storage <--(kSbSystemPathStorageDirectory)
+    ├── cobalt_updater
+    │   └── prefs_<APP_KEY>.json
+    ├── installation_1 <--(SLOT_1 - currently unused)
+    ├── installation_2 <--(SLOT_2 - contains new Cobalt version)
+    │   ├── content
+    │   │   ├── fonts <--(`empty` configuration)
+    │   │   ├── (icu) <--(only present when it needs to be updated by Cobalt Update)
+    │   │   ├── licenses
+    │   │   ├── ssl
+    │   ├── lib
+    │   │   └── libcobalt.so <--(SLOT_2 version of libcobalt.so)
+    │   ├── manifest.fingerprint
+    │   └── manifest.json <-- (Evergreen version information of libcobalt.so under SLOT_2)
+    ├── installation_store_<APP_KEY>.pb
+    └── icu (default location shared by installation slots, to be explained below)
+```
+Note that after the Cobalt binary is loaded by the loader_app, `kSbSystemPathContentDirectory` points to the
+content directory of the running binary, as stated in Starboard Module Reference of system.h.
+
+#### App metadata
+Each Cobalt Evergreen application has a set of unique metadata to track slot
+selection. The following set of files are unique per application via a
+differentiating <APP_KEY> identifier, which is a Base64 hash appended to the
+filename.
+
+```
+<SLOT_#>/installation_store_<APP_KEY>.pb
+<SLOT_#>/cobalt_updater/prefs_<APP_KEY>.json
+```
+
+You should NOT change any of these files and they are highlighted here just for
+reference.
+
+
+### Fonts
+The system font directory `kSbSystemPathFontDirectory` should be configured to
+point to the `standard` (23MB) or the `limited` (3.1MB) cobalt font packages. An
+easy way to do that is to use the `kSbSystemPathContentDirectory` to contain
+the system font directory and setting the `cobalt_font_package` to `standard` or
+`limited` in your port.
+
+Cobalt Evergreen (built by Google), will by default use the `empty` font
+package to minimize storage requirements. A separate
+`cobalt_font_package` variable is set to `empty` in the Evergreen platform.
+
+On Raspberry Pi this is:
+
+`empty` set of fonts under:
+```
+<kSbSystemPathContentDirectory>/app/cobalt/content/fonts
+```
+
+`standard` or `limited` set of fonts under:
+```
+<kSbSystemPathContentDirectory>/fonts
+```
+
+### ICU Tables
+The ICU table should be deployed under the `kSbSystemPathStorageDirectory`. This
+way all Cobalt Evergreen installations would be able to share the same tables.
+The current storage size for the ICU tables is 7MB.
+
+On Raspberry Pi this is:
+
+```
+/home/pi/.cobalt_storage/icu
+```
+The Cobalt Evergreen package will not carry ICU tables by default but may add
+them in the future if needed. When the package has ICU tables they would be
+stored under the content location for the installation:
+
+```
+<SLOT_#>/content/icu
+```
+
+### Handling Pending Updates
+Pending updates will be picked up on the next application start, which means
+that on platforms that support suspending the platform should check
+`loader_app::IsPendingRestart` and call `SbSystemRequestStop` instead of
+ suspending if there is a pending restart.
+
+Please see
+[`suspend_signals.cc`](../../shared/signal/suspend_signals.cc)
+for an example.
+
+### Multi-App Support
+Evergreen can support multiple apps that share a Cobalt binary. This is a very
+common way to save space and keep all your Cobalt apps using the latest version
+of Cobalt. We understand that there are situations where updates are only needed
+for certain apps, so we have provided a way where Cobalt Updater and loader_app
+behavior can be easily configured on a per-app basis with simple command-line flags.
+
+The configurable options for Cobalt Updater configuration are:
+* `--evergreen_lite` *Use the System Image version of Cobalt under Slot_0 and turn
+  off the updater for the specified application.*
+* `--disable_updater_module` *Stay on the current version of Cobalt that might be the
+  system image or an installed update, and turn off the updater for the
+  specified application.*
+
+Each app’s Cobalt Updater will perform an independent, regular check for new
+Cobalt Evergreen updates. Note that all apps will share the same set of slots,
+but each app will maintain metadata about which slots are “good” (working) or
+“bad” (error detected) and use the appropriate slot. Sharing slots allows
+Evergreen to download Cobalt updates a single time and be able to use it across
+all Evergreen-enabled apps.
+
+To illustrate, a simple example:
+
+* Cobalt v5 - latest Cobalt Evergreen version
+
+#### BEFORE COBALT UPDATE
+```
+[APP_1] (currently using SLOT_1, using Cobalt v4)
+[APP_2] (currently using SLOT_0, using Cobalt v3)
+[APP_3] (currently using SLOT_0, using Cobalt v3)
+```
+
+Now remember, apps could share the same Cobalt binary. Let’s say `APP_1` has
+detected an update available and downloads the latest update (Cobalt v5) into
+SLOT_2. The next time `APP_2` runs, it may detect Cobalt v5 as well. It would
+then simply do a `request_roll_forward` operation to switch to SLOT_2 and does
+not have to download a new update since the latest is already available in an
+existing slot. In this case, `APP_1` and `APP_2` are now using the same Cobalt
+binaries in SLOT_2.
+
+If `APP_3` has not been launched, not run through a regular Cobalt Updater
+check, or launched with the `--evergreen_lite`/`--disable_updater_module` flag,
+it stays with its current configuration.
+
+#### AFTER COBALT UPDATE
+```
+[APP_1] (currently using SLOT_2, using Cobalt v5)
+[APP_2] (currently using SLOT_2, using Cobalt v5)
+[APP_3] (currently using SLOT_0, using Cobalt v3)
+```
+
+Now that we have gone through an example scenario, we can cover some examples of
+how to configure Cobalt Updater behavior and `loader_app` configuration.
+
+
+Some example configurations include:
+```
+
+# All Cobalt-based apps get Evergreen Updates
+[APP_1] (Cobalt Updater ENABLED)
+[APP_2] (Cobalt Updater ENABLED)
+[APP_3] (Cobalt Updater ENABLED)
+
+loader_app --url="<YOUR_APP_1_URL>"
+loader_app --url="<YOUR_APP_2_URL>"
+loader_app --url="<YOUR_APP_3_URL>"
+
+
+# Only APP_1 gets Evergreen Updates, APP_2 disables the updater and uses an alternate splash screen, APP_3 uses
+# the system image and disables the updater
+[APP_1] (Cobalt Updater ENABLED)
+[APP_2] (Cobalt Updater DISABLED)
+[APP_3] (System Image loaded, Cobalt Updater DISABLED)
+
+loader_app --url="<YOUR_APP_1_URL>"
+loader_app --url="<YOUR_APP_2_URL>" --disable_updater_module \
+--fallback_splash_screen_url="/<PATH_TO_APP_2>/app_2_splash_screen.html"
+loader_app --url="<YOUR_APP_3_URL>" --evergreen_lite
+
+
+# APP_3 is a local app, wants Cobalt Updater disabled and stays on the system image, and uses an alternate content
+# directory (This configuration is common for System UI apps. APP_3 in this example.)
+[APP_1] (Cobalt Updater ENABLED)
+[APP_2] (Cobalt Updater ENABLED)
+[APP_3] (System Image loaded, Cobalt Updater DISABLED)
+
+loader_app --url="<YOUR_APP_1_URL>"
+loader_app --url="<YOUR_APP_2_URL>"
+loader_app --csp_mode=disable --allow_http --url="file:///<PATH_TO_APP_3>/index.html" --content="/<PATH_TO_APP_3>/content" --evergreen_lite
+```
+
+Please see
+[`loader_app_switches.cc`](../../loader_app/loader_app.cc)
+for full list of available command-line flags.
+
+### Platform Security
+
+As Cobalt binary packages ([CRX
+format](https://docs.google.com/document/d/1pAVB4y5EBhqufLshWMcvbQ5velk0yMGl5ynqiorTCG4/edit#heading=h.ke61kmpkapku))
+are downloaded from the Google Downloads server, the verification of the Cobalt
+update package is critical to the reliability of Cobalt Evergreen. There are
+mechanisms in place to ensure that the binary is verified and a chain of trust
+is formed. The Cobalt Updater is responsible for downloading the available
+Cobalt update package and verifies that the package is authored by Cobalt(and
+not an imposter), before trying to install the downloaded package.
+
+#### Understanding Verification
+
+![Cobalt Evergreen CRX
+Verification](resources/cobalt_evergreen_overview_crx_verification.png)
+
+In the above diagram, the Cobalt Updater downloads the update package if
+available, and parses the CRX header of the package for verification, before
+unpacking the whole package. A copy of the Cobalt public key is contained in the
+CRX header, so the updater retrieves the key and generates the hash of the key
+coming from the header of the package, say _Key_ _hash1_.
+
+At the same time, the updater has the hash of the Cobalt public key hard-coded
+locally, say _Key hash2_.
+
+The updater compares _Key hash1_ with _Key hash2._ If they match, verification
+succeeds.
+
+## **FAQ**
+
+### Can I host the binaries for Cobalt core myself to deploy on my devices?
+
+Not at this time. All Cobalt updates will be deployed through Google
+infrastructure. We believe Google hosting the Cobalt core binaries allows us to
+ensure a high-level of reliability and monitoring in case issues arise.
+
+### What is the performance impact of switching to Cobalt Evergreen?
+
+We expect performance to be similar to a standard non-Evergreen Cobalt port.
+
+### How can I ensure that Cobalt updates work well on our platform?
+
+Google will work closely with device partners to ensure that the appropriate
+testing is in place to prevent regressions.
+
+### Will there be tests provided to verify functionality and detect regression?
+
+Yes, there are tests available to help validate the implementation:
+
+*   NPLB tests to ensure all necessary APIs are implemented
+*   Cobalt Evergreen Test Plan to verify the functionality of all components and
+    use cases
+
+### How can I be sure that Cobalt space requirements will not grow too large for my system resources?
+
+The Cobalt team is focusing a large amount of effort to identify and integrate
+various methods to reduce the size of the Cobalt binary such as compression and
+using less fonts.
+
+### What if something goes wrong in the field? Can we rollback?
+
+Yes, this is one of the benefits of Evergreen. We can initiate an update from
+the server side that addresses problems that were undetected during full
+testing. There are a formal set of guidelines to verify an updated binary
+deployed to the device to ensure that it will work properly with no regressions
+that partners should follow to ensure that there are no regressions. In
+addition, it is also critical to do your own testing to exercise
+platform-specific behavior.
+
+### How can I be sure that Cobalt Evergreen will be optimized for my platform?
+
+Much of the optimization work remains in the Starboard layer and configuration
+so you should still expect good performance using Cobalt Evergreen. That being
+said, the Cobalt Evergreen configuration allows you to customize Cobalt features
+and settings as before.
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_evergreen_reference_port_raspi2.md b/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_evergreen_reference_port_raspi2.md
new file mode 100644
index 0000000..7763cc2
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_evergreen_reference_port_raspi2.md
@@ -0,0 +1,124 @@
+---
+layout: doc
+title: "Cobalt Evergreen Raspi-2 Reference Port"
+---
+# Cobalt Evergreen Raspi-2 Reference Port
+
+## Requirements
+
+*   Raspberry Pi 2 (image configured per
+    [instructions](https://cobalt.dev/development/setup-raspi.html) on
+    cobalt.dev)
+
+## Build instructions
+
+```
+## Clone the repository
+$ git clone https://cobalt.googlesource.com/cobalt
+
+## Build the loader app (new entry point)
+$ cd cobalt/src
+$ cobalt/build/gyp_cobalt -v raspi-2-sbversion-12 -C qa
+$ ninja -C out/raspi-2-sbversion-12_qa loader_app crashpad_handler
+
+## Create package directory for Cobalt Evergreen
+$ export COEG_PATH=coeg
+$ cp out/raspi-2-sbversion-12_qa/loader_app $COEG_PATH
+
+## Create directory structure for the initial installation
+[2-slot configuration]
+$ mkdir -p  ~/.cobalt_storage/installation_0/
+$ cd  ~/.cobalt_storage/installation_0/
+
+[3-slot configuration]
+$ mkdir -p $COEG_PATH/content/app/cobalt
+$ cd $COEG_PATH/content/app/cobalt
+
+## Download package
+$ curl -L https://dl.google.com/cobalt/evergreen/latest/cobalt_arm-hardfp_qa.crx  -o cobalt.zip
+
+## Unpack content package
+$ unzip cobalt.zip
+$ rm cobalt.zip
+$ cd -
+```
+
+The following are the steps to build the Cobalt content that’s contained in the
+crx package. Note you only need to do this if you want to build the Cobalt
+shared library and supplementary components.
+
+```
+## Build Cobalt core locally
+$ cd cobalt/src
+$ cobalt/build/gyp_cobalt -v evergreen-arm-hardfp-sbversion-12 -C qa
+$ ninja -C out/evergreen-arm-hardfp-sbversion-12_qa cobalt
+
+## Copy the generated files to the package directory for Cobalt Evergreen
+$ cp -r out/evergreen-arm-hardfp-sbversion-12_qa/lib   $COEG_PATH/content/app/cobalt/
+$ cp -r out/evergreen-arm-hardfp-sbversion-12_qa/content   $COEG_PATH/content/app/cobalt/
+
+## Create a file named manifest.json with the following content, and put it under $COEG_PATH/content/app/cobalt/
+$ cat > $COEG_PATH/content/app/cobalt/manifest.json <<EOF
+{
+        "manifest_version": 2,
+        "name": "Cobalt",
+        "description": "Cobalt",
+        "version": "1.0.0"
+}
+EOF
+```
+
+## Deployment instructions
+
+Configure your Raspberry Pi 2 with the following steps from your Linux machine.
+
+```
+## Save the address of the device
+$ export RASPI_ADDR=<YOUR_RASPI_ID_ADDR>
+
+## Remove old storage directory
+$ rm -rf /home/pi/.cobalt_storage
+
+## Copy the Evergreen contents to the device
+$ rsync -arvp $COEG_PATH pi@$RASPI_ADDR:/home/pi
+
+## Launch
+$ ssh pi@$RASPI_ADDR  /home/pi/$COEG_PATH/loader_app
+```
+
+## Run instructions
+
+```
+$ ssh pi@$RASPI_ADDR
+$ cd coeg
+$ ./loader_app
+```
+
+Cobalt should load and work as usual, but leveraging Evergreen. That’s it!
+
+## Troubleshooting
+
+### Certificate errors on execution of loader\_app
+
+Certificate issues may occur on certain network environments when launching
+`loader_app` via SSH. In this case, try launching with a keyboard directly
+connected to the device.
+
+### “Failed to load library at <path>” thrown on startup
+
+The loader can’t find the `libcobalt.so` file. Check that the path to
+`libcobalt.so` completely matches the one in Deployment instructions.
+
+### “fatal error: “assert(sk\_file)”” thrown on startup
+
+The loader can’t find the content/data folder or it is malformed. Check that the
+path to this folder completely matches the one in Deployment instructions.
+
+### “Check failed: address. Failed to retrieve the address” thrown on startup
+
+Ensure that `libcobalt.so` being used is the correct version. For a rebuild, you
+may need to remove the old .cobalt\_storage directory on your device.
+
+```
+## Remove old storage directory
+$ rm -rf /home/pi/.cobalt_storage
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_update_framework.md b/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_update_framework.md
new file mode 100644
index 0000000..f1b1cf8
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_update_framework.md
@@ -0,0 +1,104 @@
+---
+layout: doc
+title: "Cobalt Update Framework"
+---
+# Cobalt Update Framework
+
+## Background
+
+The updatability of Cobalt on the field devices enables the deployment of new
+features and crucial bug fixes in a timely manner. It significantly reduces the
+amount of work on partners’ shoulders to update to a newer version of Cobalt.
+This document introduces how Cobalt updates itself and what the system is like
+that supports the update of Cobalt. Note that the Cobalt Update Framework is
+currently used only for Evergreen configurations.
+
+## Goal
+
+*   Enable Cobalt to automatically update itself periodically
+*   Build a framework that hosts and serves the updates reliably
+
+## Overview
+
+![Cobalt Update Overview](resources/cobalt_update_overview.png)
+
+The Cobalt Updater is a module of Cobalt. It is initiated as Cobalt starts. It
+periodically sends requests to Google Update server to check for updates. If an
+update is available, the Update server responds with a downloadable link of the
+update package to the Updater. Then the Updater connects to the link, which is
+hosted on Google Downloads server, to download the update package. If an update
+is not available, the Updater server responds to indicate no update. Then the
+Updater waits until the next scheduled time to check for updates again.
+
+## Implementation
+
+### Google Update
+
+![Cobalt Update Interaction](resources/cobalt_update_interaction.png)
+
+Google Update is an update service that manages updates for Google products
+serving billions of users worldwide. We set up Cobalt updates on Google Update
+in a way that each type of device gets a unique update link (URL). The device
+type is identified by [Starboard
+ABI](../starboard_abi.md)
+(SABI) string. For instance, Raspberry Pi 2 and Linux desktop are two different
+types of devices. They are identified by two different SABI strings, and get two
+different update URLs on Google Update. The request sent by the Cobalt updater
+to Google Update  contains a SABI string. Google Update finds the suitable
+update link that matches the SABI string from the request, and responds to the
+Cobalt updater.
+
+Google Update allows the setup of multiple channels. We set up different
+channels for internal testing, partner testing, production and developers.
+
+Google Update also allows staged rollout and rollback when things go wrong. In
+the case where a problem is detected that requires rollback or fixes, Google
+will work with the partner to find a path to resolution.
+
+### Google Downloads
+
+Google Downloads is a download hosting service for official Google content. We
+generate Cobalt update packages for various types of devices, and upload the
+packages to Google Downloads. Then the links to the packages on Google Downloads
+are served on Google Update.
+
+### Cobalt Updater
+
+The updater checks for updates on Google Downloads, then downloads the update
+package if available. After the download is complete, the updater verifies the
+downloaded package, then unpack the package to a designated installation
+location. The updater runs update checks following a predefined schedule: the
+first check happens after Cobalt starts; the second check runs in a randomized
+number of hours between 1 and 24 hours; the following checks run every 24 hours.
+
+### Update flow
+
+![Cobalt Update Flow](resources/cobalt_update_flow.png)
+
+Above is a chart of the workflow of a complete update cycle. It shows how the
+Updater operates step by step and how it interacts with the Installation Manager
+and the Elf Loader[^1].
+
+The Installation Manager maintains the installation slots and provides a proper
+slot to the Updater. During the update and installation process, the
+Installation Manager keeps track of the status and collects any installation
+error. After the installation is completed, the Installation Manager marks the
+installation as pending, so that next time Cobalt starts, the Elf Loader loads
+the new installation and the update is complete. If the target platform supports
+app exits/suspends on user exiting, Cobalt will exit when an installation is
+pending, so that the new update will be picked up on the next start; otherwise,
+Cobalt is not able to exit by itself, then a manual termination of the app is
+required to pick up the update on restart.
+
+## FAQ
+
+### What happens if an urgent problem is found that requires a rollback or update?
+
+In the case where a problem is detected that requires rollback or fixes, Google
+will work with the partner to find a path to resolution.
+
+<!-- Footnotes themselves at the bottom. -->
+## Footnotes
+
+[^1]: Elf loader - A portable loader that loads the Cobalt binary and resolves
+     symbols with Starboard API when Cobalt starts up in Evergreen mode.
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_configurations.png b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_configurations.png
new file mode 100644
index 0000000..8b3721c
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_configurations.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_components.png b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_components.png
new file mode 100644
index 0000000..073ce92
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_components.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_crx_verification.png b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_crx_verification.png
new file mode 100644
index 0000000..16ec0d9
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_crx_verification.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_flow.png b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_flow.png
new file mode 100644
index 0000000..df0284b
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_flow.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_vs_non_evergreen.png b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_vs_non_evergreen.png
new file mode 100644
index 0000000..cd9cb9f
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_vs_non_evergreen.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_update_flow.png b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_update_flow.png
new file mode 100644
index 0000000..eebe1d3
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_update_flow.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_update_interaction.png b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_update_interaction.png
new file mode 100644
index 0000000..07b710a
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_update_interaction.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_update_overview.png b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_update_overview.png
new file mode 100644
index 0000000..3c8328e
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_update_overview.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/evergreen_lite_overview.png b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/evergreen_lite_overview.png
new file mode 100644
index 0000000..fa338d9
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/evergreen_lite_overview.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/symbolizing_minidumps.md b/src/cobalt/site/docs/gen/starboard/doc/evergreen/symbolizing_minidumps.md
new file mode 100644
index 0000000..df7a502
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/symbolizing_minidumps.md
@@ -0,0 +1,133 @@
+---
+layout: doc
+title: "How to Symbolize Dumps"
+---
+# How to Symbolize Dumps
+
+Evergreen will store the minidumps (`.dmp` files) from the 2 most recent
+crashes on the disk. They are stored under `kSbSystemPathCacheDirectory` in the
+subdirectory `crashpad_database/`. These files can be used along with
+Breakpad's tools to get a full stacktrace of the past crashes. This can help in
+debugging, as these minidumps have the information for the dynamic
+`libcobalt.so` module correctly mapped, which a out-of-the-box dumper could not
+manage.
+
+## Obtaining the Tools to Symbolize Minidumps
+
+Tools for symbolizing these dumps are available through
+[Breakpad](https://chromium.googlesource.com/breakpad/breakpad/). Breakpad is
+an open source crash reporting library that we use to obtain symbol files
+(`.sym`) from unstripped binaries, and to process the symbol files with the
+minidumps to produce human-readable stacktraces.
+
+
+### Building Breakpad
+
+[Breakpad](https://chromium.googlesource.com/breakpad/breakpad/) provides
+instructions for building these tools yourself. The
+[Getting Started with Breakpad](https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/getting_started_with_breakpad.md)
+guide is a good place to start if you want to go through the docs yourself, but
+below is a brief overview of how to get and build the tools.
+
+Download depot_tools:
+```
+$ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
+$ export PATH=/path/to/depot_tools:$PATH
+```
+
+Get breakpad:
+```
+$ mkdir breakpad && cd breakpad
+$ fetch breakpad
+$ cd src
+```
+
+Build breakpad:
+```
+$ ./configure && make
+```
+
+This will build the processor (`src/processor/minidump_stackwalk`), and when
+building on Linux it will also build the `dump_syms` tool
+(`src/tools/linux/dump_syms/dump_syms`).
+
+**IMPORTANT:** Once you have fetched Breakpad, you should remove the path to
+depot_tools from your `$PATH` environment variable, as it can conflict with
+Cobalt's depot_tools.
+
+## Symbolizing Minidumps
+
+Now that you have all the tools you need, we can symbolize the dumps. To be
+able to symbolize Cobalt using Evergreen, you need to be get the unstripped
+`libcobalt.so` binary. These will be available as assets in GitHub releases
+[on Cobalt's public GitHub repo](https://github.com/youtube/cobalt/releases).
+
+libcobalt releases will be labeled by the Evergreen version, the architecture,
+the config, and the ELF build id, for example
+"libcobalt_1.0.10_unstripped_armeabi_softfp_qa_ac3132014007df0e.tgz". Here, we
+have:
+* Evergreen Version: 1.0.10
+* Architecture: armeabi_softfp
+* Config: qa
+* ELF Build Id: ac3132014007df0e
+
+Knowing the architecture and config you want, you'll just have to know which
+version of Evergreen you're on or obtain the build id of the library. If you
+need to obtain the ELF build id, you can do so easily by running
+`readelf -n /path/to/libcobalt.so` and look at the hash displayed after "Build
+ID:".
+
+Now you can get the debug symbols from the library using the tools we
+downloaded previously. Unpack libcobalt and dump its symbols into a file:
+
+```
+$ tar xzf /path/to/libcobalt.tgz
+$ /path/to/dump_syms /path/to/unzipped/libcobalt > libcobalt.so.sym
+$ head -n1 libcobalt.so.sym
+MODULE Linux x86_64 6462A5D44C0843D100000000000000000 libcobalt.so
+```
+
+We run `head` on the symbol file to get the debug identifier, the hash
+displayed above (in this case, it's `6462A5D44C0843D100000000000000000`). Now
+we can create the file structure that `minidump_stackwalker` expects and run
+the stackwalker against the minidump:
+
+```
+$ mkdir -p symbols/libcobalt.so/<debug identifier>/
+$ mv libcobalt.so.sym symbols/libcobalt.so/<debug identifier>/
+$ /path/to/minidump_stackwalk /path/to/your/minidump.dmp symbols/
+```
+
+`minidump_stackwalk` produces verbose output on stderr, and the stacktrace on
+stdout, so you may want to redirect stderr.
+
+### Addendum: Adding Other Symbols
+
+We can use the process above to add symbols for any library or executable you
+use, not just `libcobalt.so`. To do this, all you have to do is run the
+`dump_syms` tools on the binary you want symbolized and put that in the
+"symbols/" folder.
+
+```
+$ /path/to/dump_syms /path/to/<your-binary> > <your-binary>.sym
+$ head -n1 <your-binary.sym>
+MODULE Linux x86_64 <debug-identifier> <your-binary>
+$ mkdir -p symbols/<your-binary>/<debug-identifier>
+$ mv <your-binary>.sym symbols/<your-binary>/<debug-identifier>/
+```
+
+Now, `minidump_stackwalk` should symbolize sections within `<your-binary>`. For
+example, if you decided to symbolize the `loader_app`, it would transform the
+stacktrace output from `minidump_stackwalk` from:
+
+```
+9  loader_app + 0x3a31130
+```
+
+to:
+
+```
+9  loader_app!SbEventHandle [sandbox.cc : 44 + 0x8]
+```
+
+Note that the addresses will vary.
diff --git a/src/cobalt/site/docs/gen/starboard/doc/howto_decode_to_texture.md b/src/cobalt/site/docs/gen/starboard/doc/howto_decode_to_texture.md
new file mode 100644
index 0000000..bd2f7b8
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/howto_decode_to_texture.md
@@ -0,0 +1,140 @@
+---
+layout: doc
+title: "**HOWTO:** Decode to Texture"
+---
+# **HOWTO:** Decode to Texture
+
+Starboard declares the interfaces necessary to allow applications to query for
+video frames from the media player, and have them returned as texture objects
+(e.g. GLES textures).  This is useful if the application would like to apply
+a geometrical transformation to the rendered video, in order to support 360
+spherical video playback for example.  Additionally, if a Starboard platform
+implementation does not support punch-through video playback, then
+applications can choose to use decode-to-texture instead.
+
+## API Overview
+
+Decode-to-texture support involves multiple Starboard API functions spanning
+both the [`starboard/player.h`](../player.h) and
+[`starboard/decode_target.h`](../decode_target.h) Starboard interface header
+files.  Support for decode-to-texture began in version 4 of the Starboard
+API.
+
+In particular, the following function implementations require consideration
+for decode-to-texture support:
+
+From [`starboard/player.h`](../player.h),
+
+* `SbPlayerCreate()`
+* `SbPlayerOutputModeSupported()`
+* `SbPlayerGetCurrentFrame()`
+
+From [`starboard/decode_target.h`](../decode_target.h),
+
+* `SbDecodeTargetRelease()`
+* `SbDecodeTargetGetInfo()`
+
+Note that it is possible that you may not need to use the
+`SbDecodeTargetGraphicsContextProvider` parameter of SbPlayerCreate().  More on
+this later.
+
+## Example Application Usage Pattern
+
+We now describe an example, and typical, sequence of steps that an
+application will take when it wishes to make use of decode-to-texture
+support.
+
+![Decode-to-texture sequence diagram](resources/decode_to_texture_sequence.png)
+
+1. An application with the desire to make use of decode-to-texture will first
+   call `SbPlayerOutputModeSupported()`, passing in
+   `kSbPlayerOutputModeDecodeToTexture` for its `output_mode` parameter.  If
+   the function returns false, the application learns that decode-to-texture
+   is not supported by the platform and it will not continue with a
+   decode-to-texture flow.
+
+2. If `SbPlayerOutputModeSupported()` returns true, the application will call
+   `SbPlayerCreate()`, passing in `kSbPlayerOutputModeDecodeToTexture` for
+   the `output_mode` parameter, and also providing a valid `provider`
+   parameter (more on this later).  At this point, the Starboard platform is
+   expected to have created a player with the decode-to-texture output mode.
+
+3. Once the player is started and playback has begun, the application's
+   renderer thread (this may be a different thread than the one that called
+   `SbPlayerCreate()`) will repeatedly and frequently call
+   `SbPlayerGetCurrentFrame()`.  Since this function will be called from the
+   application's renderer thread, it should be thread-safe.  If the platform
+   uses a GLES renderer, it is guaranteed that this function will be called
+   with the GLES renderer context set as current.  This function is expected
+   to return the video frame that is to be displayed at the time the function
+   is called as a `SbDecodeTarget` object.  The `SbPlayerGetCurrentFrame()`
+   will be called at the renderer's frequency, i.e. the application render
+   loop's frame rate.  If the application's frame rate is higher than the
+   video's frame rate, then the same video frame will sometimes be returned
+   in consecutive calls to `SbPlayerGetCurrentFrame()`.  If the video's frame
+   rate is higher than the application's (this should be rare), then some
+   video frames will never be returned by calls to
+   `SbPlayerGetCurrentFrame()`; in other words, video frames will be
+   dropped.
+
+4. Once the application has acquired a valid SbDecodeTarget object through a
+   call to `SbPlayerGetCurrentFrame()`, it will call
+   `SbDecodeTargetGetInfo()` on it to extract information about the opaque
+   `SbDecodeTarget` object.  The `SbDecodeTargetGetInfo()` function fills
+   out a `SbDecodeTargetInfo` structure which contains information about the
+   decoded frame and, most importantly, a reference to a GLES texture ID on
+   GLES platforms, or a reference to a `SbBlitterSurface` object on
+   Starboard Blitter API platforms.  The application can then use this
+   texture/surface handle to render the video frame as it wishes.
+
+5. When the application is finished using the `SbDecodeTarget` that it has
+   aquired through the `SbPlayerGetCurrentFrame()` function, it will call
+   `SbDecodeTargetRelease()` on it.  The Starboard platform implementation
+   should ensure that the `SbDecodeTarget` object returned by
+   `SbPlayerGetCurrentFrame()` remains valid until the corresponding call to
+   `SbDecodeTargetRelease()` is made.  A call to `SbDecodeTargetRelease()`
+   will be made to match each call to `SbPlayerGetCurrentFrame()`.
+
+## The `SbDecodeTargetGraphicsContextProvider` object
+
+It is completely possible that a platform's Starboard implementation can
+properly implement decode-to-texture support without dealing with the
+`SbDecodeTargetGraphicsContextProvider` object (passed in to
+`SbPlayerCreate()`).  The `SbDecodeTargetGraphicsContextProvider` reference
+gives platforms references to the graphics objects that will later be used to
+render the decoded frames.  For example, on Blitter API platforms, a reference
+to the `SbBlitterDevice` object will be a mamber of
+`SbDecodeTargetGraphicsContextProvider`.  For EGL platforms, a `EGLDisplay` and
+`EGLContext` will be available, but additionally a
+`SbDecodeTargetGlesContextRunner` function pointer will be provided that will
+allow you to run arbitrary code on the renderer thread with the `EGLContext`
+held current.  This may be useful if your `SbDecodeTarget` creation code will
+required making GLES calls (e.g. `glGenTextures()`) in which a `EGLContext` must
+be held current.
+
+## Performance Considerations
+
+The decode-to-texture Starboard API is specifically designed to allow
+Starboard implementations to have the player decode directly to a texture,
+so that the application can then reference and render with that texture
+without at any point performing a pixel copy.  The
+decode-to-texture path can therefore be highly performant.
+
+It is still recommended however that platforms support the punch-through
+player mode if possible.  When using the decode-to-texture player output
+mode, the video may be rendered within the application's render loop, which
+means that non-video-related time complexity in the application's render
+loop can affect video playback's apparent frame rate, potentially resulting in
+dropped frames.  The platform can likely configure punch-through video to
+refresh on its own loop, decoupling it from the application render loop.
+
+## Implementation Strategies
+
+### Working with "push" players
+
+If your player implementation is setup with a "push" framework where
+frames are pushed out as soon as they are decoded, then you will need
+to cache those frames (along with their timestamps) so that they can be
+passed on to the application when `SbPlayerGetCurrentFrame()` is called.
+This same strategy applies if the player pushes frames only when they are meant
+to be rendered.
\ No newline at end of file
diff --git a/src/cobalt/site/docs/gen/starboard/doc/principles.md b/src/cobalt/site/docs/gen/starboard/doc/principles.md
new file mode 100644
index 0000000..880c09c
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/principles.md
@@ -0,0 +1,157 @@
+---
+layout: doc
+title: "Starboard Design Principles"
+---
+# Starboard Design Principles
+
+An overview of the goals and design principles of Starboard with the perspective
+of hindsight.
+
+**Status:** REVIEWED\
+**Created:** 2016-11-12
+
+Starboard is a porting abstraction and a collection of implementation fragments
+used to abstract operating system facilities and platform quirks from C or C++
+applications. It occupies a similar space to SDL, DirectFB, Marmalade, and
+various others.
+
+## Background
+
+Starboard was created as a response to the significant effort it has
+historically taken to port desktop-oriented web browsers to non-traditional
+device platforms like game consoles. Chromium in particular mixes
+platform-specific code with common code throughout the technology stack, making
+it very difficult to know what has to be done for a new platform or how much
+work it is going to be.
+
+## Goals
+
+Here are the main goals of Starboard, stack-ranked from most-to-least important.
+
+  * **G1** Minimize the total time and effort required to port Starboard Client
+    Applications to new platforms.
+  * **G2** Minimize the incremental time and effort required to rebase Starboard
+    Client Applications across platforms.
+  * **G3** Enable third parties to port Starboard to their platform without
+    significant engineering support from the Starboard team.
+  * **G4** Ensure support for low-profile platforms that are not geared towards
+    broad native C/C++ development access.
+  * **G5** Provide an organization framework for platform-specific code, clearly
+    delineating what is common and what is platform-specific, consolidating
+    platform-specific code into a single location, and enumerating all the APIs
+    needed to provide full functionality.
+  * **G6** Encapsulate all platform-provided services needed to build graphical
+    media applications into a single API.
+  * **G7** Reduce the total surface area needed to port to new platforms.
+  * **G8** Improve and encourage sharing of platform-specific implementation
+    components between platforms.
+  * **G9** Maximize the amount of common (platform-independent) code, to avoid
+    variances between platforms, and to increase the leverage of testing,
+    including fuzz testing which must often be done on particular platforms.
+  * **G10** Maintain a loose binding between a Starboard Platform Implementation
+    and a Starboard Client Application, such that they can be updated
+    independently at a source level.
+  * **G11** Avoid the pitfalls of trying to emulate POSIX, including, but not
+    limited to: auto-included headers, global defines of short and common
+    symbols, wrapping misbehaving or misprototyped system APIs, using custom
+    toolchain facilities, and conflicts with platform headers.
+
+## Principles
+
+### Make APIs sufficient for their purpose, but minimally so.
+
+APIs can generally be augmented without serious backwards-compatibility
+consequences, but they can not be changed or pruned so easily, so it is better
+to **err on the side of providing less**.
+
+#### Corollary: Implementation details should be as hidden as possible.
+
+#### Corollary: Anything that could be implemented purely on top of Starboard APIs should be implemented purely on top of Starboard APIs.
+
+#### Exception: If there are good reasons why an API may need to be implemented in a platform-specific manner on one or more platforms, but can be commonly implemented on other platforms, it should be part of the API, with a shared Starboard-based implementation.
+
+#### Exception: For the select few cases where Starboard implementations also need to use it, it should be included in the Starboard API so that can happen without creating circular dependencies.
+
+### Specify public APIs concretely and narrowly.
+
+A broader specification of the behavior of an API function makes life easier for
+the implementor, but more difficult for anyone attempting to use the API. An API
+can be so weakly specified that it is not usable across platforms. It can also
+be so strictly specified that it is not implementable across platforms. **Err on
+the side of narrower specifications**, requiring generality only when
+necessitated by one or more platforms.
+
+#### Corollary: Documentation should be exhaustive and clear.
+
+#### Corollary: Avoid overly-flexible convention-based interfaces.
+
+For example, passing in a set of string-string name-value pairs. This takes the
+compiler out of any kind of validation, and can encourage mismatches of
+understanding between Clients and Platforms.
+
+### Minimize the burden on the porter.
+
+Whenever adding or changing an API, or specifying a contract, consider whether
+this places a large burden on some platform implementers. This burden could be
+because of a wide porting surface, or complex requirements that are difficult to
+implement. It could be caused by a fundamental piece of infrastructure that
+isn't provided by a particular platform.
+
+We can always make APIs that are burdensome to use easier with more common code.
+
+### Be consistent and predictable.
+
+Consistency, not just in formatting, but in semantics, leads to
+predictability. Some people just won't read the documentation, even if it's
+thorough. Perhaps especially if it's thorough. The names of API entities should
+convey the intention as completely as possible.
+
+Yet, overly-verbose naming will make the API difficult to remember, read, and
+use.
+
+### Assume the porter knows nothing.
+
+Engineers from a broad set of backgrounds and environments will end up being
+dropped into porting Starboard. They may not have knowledge of any particular
+technologies, best practices, or design patterns. They may be under an
+aggressive deadline.
+
+### Always consider threading (and document it).
+
+Each function and module should have a strategy for dealing with multiple
+threads. It should make sense for the expected use cases of the interface
+entities in question. As the interface designer, it is most clear to you how the
+API should be used with respect to threads.
+
+Some may be "thread-safe," such that any functions can be called from any thread
+without much concern. Note that this places the burden on the implementer to
+ensure that an implementation meets that specification, and they MAY not know
+how to do that. This can also be more complex than just acquiring a mutex inside
+every function implementation, as there may be inherent race conditions between
+function calls even when using a synchronization mechanism.
+
+The path of least burden to the porter is to say that an interface is not
+thread-safe at all, which means applications will have to take care how the API
+is used. But, sometimes even this requires clarification as to what modes of
+access are dangerous and how to use the API safely.
+
+### Don't expose Informational-Only result codes, but do DLOG them.
+
+"Informational-Only" is defined by a result code that doesn't change the
+behavior of the caller. Many times, why something failed does not matter when
+the product is already in the hands of the user. We often want diagnostic
+logging during development
+
+### Trust but Verify. Whenever possible, write NPLB tests for all contracts declared by the interface.
+
+#### Corollary: For hard-to-test features (like Input) add an example sandbox app for testing.
+
+### We will get it wrong the first time, so plan for some kind of change mechanism.
+
+Starboard has a [versioning mechanism](versioning.md) to manage change.
+
+## References
+  * [Joshua Bloch's presentation about API design](https://www.youtube.com/watch?v=aAb7hSCtvGw)
+  * [Joshua Bloch's bumper sticker API design rules](http://www.infoq.com/articles/API-Design-Joshua-Bloch)
+  * [digithead's collection of API design links (I didn't read them all)](http://digitheadslabnotebook.blogspot.com/2010/07/how-to-design-good-apis.html)
+
diff --git a/src/cobalt/site/docs/gen/starboard/doc/resources/decode_to_texture_sequence.png b/src/cobalt/site/docs/gen/starboard/doc/resources/decode_to_texture_sequence.png
new file mode 100644
index 0000000..b2b4cb4
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/resources/decode_to_texture_sequence.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/starboard/doc/resources/decode_to_texture_sequence.txt b/src/cobalt/site/docs/gen/starboard/doc/resources/decode_to_texture_sequence.txt
new file mode 100644
index 0000000..5118f0b
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/resources/decode_to_texture_sequence.txt
@@ -0,0 +1,14 @@
+participant Application (e.g. Cobalt) as a [fillcolor="#ffd0d0"]
+participant Starboard as s [fillcolor="#d0d0ff"]
+
+a->s: SbPlayerOutputModeSupported(kSbPlayerOutputModeDecodeToTexture, ...)
+s-->a: returns bool
+Note over a: If SbPlayerOutputModeSupported()\nreturns true... [fillcolor="white"]
+a->s: SbPlayerCreate(..., kSbPlayerOutputModeDecodeToTexture, ...)
+Note over a: Start of render loop [fillcolor="#ffffd0"]
+a->s: SbPlayerGetCurrentFrame()
+s-->a: returns SbDecodeTarget
+Note over a: Extracts GLES texture(s) from the\nSbDecodeTarget object and\nrenders a scene with them. [fillcolor="white"]
+a->s: SbDecodeTargetRelease()
+Note over a: Goto: Start of render loop [fillcolor="#ffffd0"]
+
diff --git a/src/cobalt/site/docs/gen/starboard/doc/resources/starboard_abi_overview.png b/src/cobalt/site/docs/gen/starboard/doc/resources/starboard_abi_overview.png
new file mode 100644
index 0000000..8a15c74
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/resources/starboard_abi_overview.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/starboard/doc/starboard_abi.md b/src/cobalt/site/docs/gen/starboard/doc/starboard_abi.md
new file mode 100644
index 0000000..619703c
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/starboard_abi.md
@@ -0,0 +1,123 @@
+---
+layout: doc
+title: "Starboard ABI"
+---
+# Starboard ABI
+
+The Starboard ABI was introduced to provide a single, consistent method for
+specifying the Starboard API version and the ABI. This specification ensures
+that any two binaries, built with the same Starboard ABI and with arbitrary
+toolchains, are compatible.
+
+## Background
+
+The Starboard ABI is the set of features, such as the Starboard API version or
+the sizes of data types, that collectively describes the relationship between
+the Starboard API and ABI of a binary. In the past, each of these features were
+inconsistently and ambiguously defined in a variety of files. This led to
+confusion, and made it difficult to track down the feature values for a
+platform. To simplify how Starboard is configured for a target platform, all of
+these features, and their concrete values, are now listed for each distinct
+target architecture in Starboard ABI files. These files provide a consistent,
+consolidated view of the values for each of these features, decoupling
+platform-specific details from architecture.
+
+## Goals
+
+The overall goal of the Starboard ABI is to provide a way to implement and
+verify binary compatibility on a target platform, and this goal can be broken
+down into the following more concise motivations:
+
+*   Separate platform and architecture into distinct concepts.
+*   Establish a consistent set of values for the various features of each target
+    architecture.
+*   Consolidate this set of features and their values in a consistent,
+    predictable location.
+*   Provide the ability to validate the values of each feature in produced
+    binaries.
+
+## Using Starboard ABI Files
+
+With the Starboard ABI being the source of truth for all things architecture
+related, each platform must now include a Starboard ABI file in its build (see
+[//starboard/sabi](../sabi)
+for examples). Starboard ABI files are JSON, and should all contain identical
+keys with the values being appropriate for the architecture. Each platform must
+override the new
+[GetPathToSabiJsonFile](../build/platform_configuration.py##339)
+method in its platform configuration to return the path to the desired Starboard
+ABI file (e.g.
+[//starboard/linux/shared/gyp\_configuration.py](../linux/shared/gyp_configuration.py)).
+By default, an empty and invalid Starboard ABI file is provided.
+
+Additionally, all platforms must include the
+[sabi.gypi](../sabi/sabi.gypi)
+in their build configuration. This file will consume the specified Starboard ABI
+file, resulting in the creation of a set of GYP variables and preprocessor
+macros. The preprocessor macros are passed directly to the compiler and replace
+the macros you might be familiar with, such as `SB_HAS_32_BIT_LONG`.
+
+The newly defined GYP variables need to be transformed into toolchain specific
+flags; these flags are what actually makes the build result in a binary for the
+desired architecture. These flags will, in most cases, be identical to the flags
+already being used for building.
+
+The process outlined above is shown in the diagram below.
+
+![Starboard ABI Overview](resources/starboard_abi_overview.png)
+
+### Post-Starboard ABI File Cleanup
+
+A number of GYP variables and preprocessor macros should no longer be defined
+directly, and instead the Starboard ABI file will be used to define them. These
+definitions need to be removed.
+
+From `configuration_public.h`:
+
+*   `SB_IS_ARCH_*`
+*   `SB_IS_BIG_ENDIAN`
+*   `SB_IS_32_BIT`
+*   `SB_IS_64_BIT`
+*   `SB_HAS_32_BIT_LONG`
+*   `SB_HAS_64_BIT_LONG`
+*   `SB_HAS_32_BIT_POINTERS`
+*   `SB_HAS_64_BIT_POINTERS`
+
+From `gyp_configuration.gypi`:
+
+*   `target_arch`
+
+## FAQ
+
+### What Starboard ABI files are provided?
+
+The Cobalt team provides, and maintains, Starboard ABI files for the following
+architectures:
+
+*   x86\_32
+*   x86\_64
+*   ARM v7 (32-bit)
+*   ARM v8 (64-bit)
+
+If you find that no valid Starboard ABI file exists for your architecture, or
+that you need to change any values of a provided Starboard ABI file, please
+reach out to the Cobalt team to advise.
+
+### How can I verify that my build is configured correctly?
+
+Similar to the process prior to Starboard ABI files, there are multiple levels
+of verification that occur:
+
+1.  When configuring your build, the Starboard ABI file that was specified will
+    have its values sanity checked against a provided
+    [schema](../sabi/sabi.schema.json).
+1.  When building, a number of static assertions will assert correctness of a
+    number of features generated from the Starboard ABI file against the
+    features of the binary.
+1.  The NPLB test suite has been expanded to include [additional
+    tests](../nplb/sabi/)
+    capable of verifying the remaining features of the binary.
+
+Finally, binaries produced by the Cobalt team for your architecture, including
+NPLB, will be made available to ensure end-to-end correctness of the produced
+binaries.
diff --git a/src/cobalt/site/docs/gen/starboard/doc/starboard_split.md b/src/cobalt/site/docs/gen/starboard/doc/starboard_split.md
new file mode 100644
index 0000000..2e145ae
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/starboard_split.md
@@ -0,0 +1,62 @@
+---
+layout: doc
+title: "Separation of Starboard from Cobalt"
+---
+# Separation of Starboard from Cobalt
+
+### Background
+
+In creating Cobalt Evergreen, we needed to have as few differences in the code
+as we could from one platform to another. Simply put, that means we want to get
+rid of as many platform specific compile time macros as possible. Because of
+the large amount of platform differences we had previously, there were macros
+defined in a variety places, all of which require different cases to convert.
+The below sections go into the differences regarding changes to these macros
+from Cobalt 20 to 21 and from Starboard 11 to 12.
+
+## Optional APIs
+
+In previous versions, there were a few APIs that could optionally defined and
+would only be enabled if certain macros were set. The platform would only have
+to implement the API if it set the macros accordingly. Now, those differences
+have been removed, and all platforms are required to implement these APIs. For
+convenience, we have provided stub functions for all implementations, which a
+platform can use without differences in Cobalt if they did not enable the API
+beforehand.
+
+## Migration from Configuration Macros to External Constants
+
+Starboard configurations have moved from
+[configuration.h](../configuration.h) and platform specific
+`configuration_public.h` files to `configuration_constants.cc` files. They
+have also been changes from macros to `extern const`s. This means that Cobalt
+will be able to evaluate these variables at runtime instead of compile time.
+The declarations for all of these variables are located in
+[configuration_constants.h](../configuration_constants.h), but each platform
+must define each variable individually, i.e. as
+```
+// configuration_constants.cc
+#include "starboard/configuration_constants.h"
+
+const int32_t kSbFileMaxName = 64;
+```
+There are two changes that are a result of this migration:
+
+1. There is no longer any form of inheritance. This means that if there are any
+configuration differences between two platforms, they must have separate
+`configuration_constants.cc` files.
+2. There are no longer default values for any variable. Because we cannot
+inherit values, we would not be able to receive a default value for any one, so
+each platform must have a definition for every configuration variable.
+
+## Migration from GYP Variables to Cobalt Extensions
+
+Cobalt configurations have moved from [cobalt_configuration.gypi](../../cobalt/build/cobalt_configuration.gypi) and platform specific `gyp_configuration.gypi` files to Cobalt extensions, primarily [CobaltExtensionConfigurationApi](../../cobalt/extension/configuration.h), but including the [CobaltExtensionGraphicsApi](../../cobalt/extension/graphics.h).
+
+Some variables were already in the process of being deprecated, sometimes with a replacement. In those cases, that path was followed.
+
+Implementing the Cobalt extension is completely optional, and when calling the functions corresponding to the old GYP variable, there will be a default value that the function will be able to fall back onto if the extension has not been implemented. That being said, if there is a single function the platform needs a custom implementation for, it must completely implement the CobaltExtensionConfigurationApi. For convenience, we have provided default functions to use to define the API if desired.
+
+##### Notes
+
+For migrating from macros, partners will have to treat their use differently! I.e. string literal vs const char* in their implementations. Add an overview of all of the cases of this migration in runtime code.
\ No newline at end of file
diff --git a/src/cobalt/site/docs/gen/starboard/doc/style.md b/src/cobalt/site/docs/gen/starboard/doc/style.md
new file mode 100644
index 0000000..43b3623
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/style.md
@@ -0,0 +1,280 @@
+---
+layout: doc
+title: "Starboard C and C++ Style Guide"
+---
+# Starboard C and C++ Style Guide
+
+A description of the coding conventions for Starboard code and API headers.
+
+**Status:** REVIEWED\
+**Created:** 2016-11-08
+
+Starboard generally tries to follow the coding conventions of Cobalt, which
+itself mostly follows the conventions of Chromium, which mostly follows the
+externally-published Google C++ coding conventions. But, Starboard has some
+special requirements due to its unusual constraints, so it must add a few new
+conventions and loosen some of the existing style prescriptions.
+
+## Background
+
+Before looking at this document, bear in mind that it is not intending to
+completely describe all conventions that apply to Starboard. You probably want
+to take some time to familiarize yourself with these documents first, probably
+in this order:
+
+  * [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html)
+  * [Chromium C++ Style Guide](https://chromium.googlesource.com/chromium/src/+/master/styleguide/c++/c++.md)
+  * [Cobalt Style Guide](http://cobalt.foo/broken)
+
+The main additional constraints that Starboard has to deal with are:
+
+  * The Starboard API is defined in straight-C. It must be able to interface
+    with all possible third-party components, many of which are in C and not
+    C++.
+  * Starboard is a public API. Starboard platform implementations and
+    applications written on top of Starboard will change independently. This
+    means there are intense requirements for API stability, usage
+    predictability, searchability, and documentation.
+  * Note that even though it is presented as a "style guide," the conventions
+    presented here are required to be approved for check-in unless otherwise
+    noted.
+
+
+## Definitions
+
+### snake-case
+
+Words separated with underscores.
+
+    lower_snake_case
+    ALL_CAPS_SNAKE_CASE
+
+### camel-case
+
+Words separated by letter capitalization.
+
+    camelCase
+    CapitalizedCamelCase
+
+## C++ Guidelines
+
+What follows are hereby the guidelines for Starboard C and C++ code. Heretofore
+the guidelines follow thusly as follows.
+
+### API Definitions
+
+  * Starboard API definitions must always be compatible with straight-C99 compilers.
+  * All public API declarations must be specified in headers in
+    `src/starboard/*.h`, not in any subdirectories.
+  * Non-public declarations must NOT be specified in headers in
+    `src/starboard/*.h`.
+  * C++ inline helper definitions may be included inside an `#if
+    defined(__cplusplus)` preprocessor block. They must only provide
+    convenience, and must NOT be required for any API functionality.
+  * All public API functions should be exported symbols with the SB_EXPORT
+    attribute.
+  * No non-const variables shall be exposed as part of the public API.
+  * All APIs should be implemented in C++ source files, not straight-C source files.
+
+### Modules
+
+  * Each module header must be contained with a single header file.
+
+  * The name of the module must be the singular form of the noun being
+    interfaced with by the module, without any "sb" or "starboard".
+      * `file.h`
+      * `directory.h`
+      * `window.h`
+  * Module interfaces should not have circular dependencies.
+
+### File Names
+
+  * Like in the other conventions (e.g. Google, Chromium), file names must be in
+    `lower_snake_case`.
+  * File names must not contain `sb_` or `starboard_`.
+  * The name of a module header file must be the `lower_snake_case` form of the
+    module name.
+      * `SbConditionVariable` âž¡ `starboard/condition_variable.h`
+  * A header that is intended to be an internal implementation detail of one or
+    more platform implementations should have the suffix `_internal.h`, and
+    include the header `starboard/shared/internal_only.h`.
+  * See "Implementations" for conventions about where to place implementation files.
+
+### Types
+
+  * Like in the other conventions, types should be `CapitalizedCamelCase`.
+  * Every public Starboard type must start with `Sb`. There are no namespaces in
+    C, so `Sb` is the Starboard namespace.
+  * Every public Starboard type must be declared by a module, and must have the
+    name of the module following the `Sb`.
+      * `file.h` contains `SbFile`, `SbFileInfo`, `SbFileWhence`, etc...
+  * Every seemingly-allocatable, platform-specific Starboard type should be
+    defined as an opaque handle to a publically undefined struct with the
+    `Private` suffix. Follow this pattern for all such type declarations.
+      * `struct SbFilePrivate` is declared, but not defined in the public header.
+      * `SbFilePrivate` is `typedef`'d to `struct SbFilePrivate`. This is a C
+        thing where types are defined as names with the "`struct`" keyword
+        prepended unless `typedef`'d.
+      * `SbFile` is defined as a `typedef` of `struct SbFilePrivate*`.
+  * C structs may be defined internally to have functions and visibility. It is
+    allowed for such structs to have constructors, destructors, methods,
+    members, and public members.
+  * It is also considered idiomatic to never define the private struct but to
+    just treat it like a handle into some other method of object tracking,
+    casting the handle back and forth to the pointer type.
+  * If a word in the name of a type is redundant with the module name, it is
+    omitted.
+        * A monotonic time type in the Time module is `SbTimeMonotonic`, not
+          ~~`SbMonotonicTime`, `SbTimeMonotonicTime`, or
+          `SbTimeMonotonicSbTime`~~.
+
+### Functions
+
+  * Like in the other conventions, functions should be `CapitalizedCamelCase`.
+  * Every public Starboard function must start with `Sb`. There are no namespaces
+    in C, so `Sb` is the Starboard namespace.
+  * Every public Starboard function must be declared by a module, and must have
+    the name of the module following the `Sb`.
+      * `system.h` contains `SbSystemGetPath()`
+      * `file.h` contains `SbFileOpen()`
+  * After the Starboard and Module prefix, functions should start with an
+    imperative verb indicating what the function does.
+      * The Thread module defines `SbThreadCreateLocalKey()` to create a key for
+        thread local storage.
+  * If a word in the name of a function is redundant with the module name, it is
+    omitted.
+      * The `File` module as the function `SbFileOpen`, not ~~`SbOpenFile`,
+        `SbFileOpenFile` or `SbFileOpenSbFile`~~.
+      * If this gets awkward, it may indicate a need to split into a different
+        module.
+
+### Variables, Parameters, Fields
+
+  * Like in the other conventions, variable, function parameter, and field names
+    must be in `lower_snake_case`.
+  * Private member fields end in an underscore.
+  * Public member fields do not end in an underscore.
+
+### Namespaces
+
+Most Starboard API headers are straight-C compatible, so cannot live inside a
+namespace. Implementations, since they implement straight-C interface functions,
+also cannot live inside a namespace.
+
+But, in all other cases, Starboard C++ code should follow the inherited
+conventions and use a namespace for each directory starting with a "starboard"
+namespace at the starboard repository root.
+
+### Preprocessor Macros
+
+  * Like in the other conventions, variable, function parameter, and field names
+    must be in `ALL_CAPS_SNAKE_CASE`.
+  * Macros may be used as compile-time constants because straight-C does not
+    have a proper facility for typed constants. This is as opposed to macros
+    used primarily at preprocessor-time to filter or modify what gets sent to
+    the compiler. Macros used as compile-time constants and that are not
+    configuration parameters should be explicitly-typed with a c-style cast, and
+    should follow the Constants naming conventions.
+  * Macros must start with `SB_`, and then must further be namespaced with the
+    module name, with the exception of configuration definitions.
+  * Configuration definitions should be namespaced with the module name that
+    they primarily affect, if applicable, or a scope that generally indicates
+    its domain.
+      * `SB_FILE_MAX_NAME`
+      * `SB_MEMORY_PAGE_SIZE`
+  * Always use `#if defined(MACRO)` over `#ifdef MACRO`.
+
+### Constants
+
+  * Constants (including enum entries) are named using the Google constant
+    naming convention, `CapitalizedCamelCase`d, but starting with a lower-case
+    `k`.
+  * After the `k`, all constants have `Sb`, the Starboard namespace.
+      * `kSb`
+  * After `kSb`, all constants then have the module name.
+      * `kSbTime`
+      * `kSbFile`
+  * After `kSb<module>` comes the rest of the name of the constant.
+      * `kSbTimeMillisecond`
+      * `kSbFileInvalid`
+  * Enum entries are prefixed with the full name of the enum.
+      * The enum `SbSystemDeviceType` contains entries like
+        `kSbSystemDeviceTypeBlueRayDiskPlayer`.
+
+### Comments
+
+  * All files must have a license and copyright comment.
+  * It is expected that the straight-C compiler supports C99 single-line
+    comments. Block comments should be avoided whenever possible, even in
+    license and copyright headers.
+  * Each public API module file should have a Module Overview documentation
+    comment below the license explaining what the module is for, and how to use
+    it effectively.
+  * The Module Overview must be separated by a completely blank line from the
+    license comment.
+  * The first line of the Module Overview documentation comment must say
+    "`Module Overview: Starboard <module-name> module`", followed by a blank
+    comment line (i.e. a line that contains a `//`, but nothing else).
+  * The first sentence of a documentation comment describing any entity (module,
+    type, function, variable, etc...) should assume "This module," "This type,"
+    "This function," or "This variable" at the beginning of the sentence, and
+    not include it.
+  * The first sentence of a documentation comment describing any entity should
+    be a single-sentence summary description of the entire entity.
+  * The first paragraph of a documentation comment should describe the overall
+    behavior of the entity.
+  * Paragraphs in comments should be separated by a blank comment line.
+  * All public entities must have documentation comments, including enum
+    entries.
+  * Documentation comments should be formatted with Markdown.
+  * Variables, constants, literals, and expressions should be referenced in
+    comments with pipes around them.
+  * All comments must be full grammatically-correct English sentences with
+    proper punctuation.
+  * Comments in Starboard headers must be written as requirements for the
+    porter, for example: "must not return NULL" or "should not return
+    NULL" rather than "will not return NULL". The choice of "must" vs "should"
+    must follow the guidelines of IETF RFC,
+    https://www.ietf.org/rfc/rfc2119.txt .
+
+### Implementations
+
+  * Each API implementation should attempt to minimize other platform
+    assumptions, and should therefore use Starboard APIs to accomplish
+    platform-specific work unless directly related to the platform functionality
+    being implemented.
+        * For example, `SbFile` can use POSIX file I/O, because that what it is
+          abstracting, but it should use `SbMemoryAllocate` for any memory
+          allocations, because it might be used with a variety of `SbMemory`
+          implementations.
+  * Whenever possible, each shared function implementation should be implemented
+    in an individual file so as to maximize the chances of reuse between
+    implementations.
+  * This does not apply to platform-specific functions that have no chance of
+    being reusable on other platforms.
+  * Implementation files that can conceivably be shared between one or more
+    implementations should be placed in a `starboard/shared/<dependency>/`
+    directory, where `<dependency>` is the primary platform dependency of that
+    implementation. (e.g. `libevent`, `posix`, `c++11`, etc.)
+  * Implementation files that don't have a specific platform dependency, but
+    whether to use them should be a platform decision should be placed in
+    `starboard/shared/starboard/`, and must only have dependencies on other
+    Starboard APIs.
+  * Implementation files that definitely can be common to ALL implementations
+    should be placed in `starboard/common/`.
+
+### Language Features
+
+  * In public headers, particularly in inline functions and macros, only C-Style
+    casts may be used, though they are forbidden everywhere else.
+  * It is expected that the C compiler supports inline functions. They must be
+    declared `static`, and they must use the `SB_C_INLINE` or
+    `SB_C_FORCE_INLINE` attribute. In straight-C code, there is no anonymous
+    namespace, so `static` is allowed and required for inline functions.
+  * No straight-C ISO or POSIX headers should be assumed to exist. Basic C++03
+    headers may be assumed to exist in C++ code. The ISO C standards have grown
+    up over a long period of time and have historically been implemented with
+    quirks, missing pieces, and so on. Support for the core C++ standard library
+    is much more consistent on those platforms that do support it.
+  * It is idiomatic to include thin C++ inline wrappers inside public API
+    headers, gated by an `#if defined(cplusplus__)` check.
diff --git a/src/cobalt/site/docs/gen/starboard/doc/versioning.md b/src/cobalt/site/docs/gen/starboard/doc/versioning.md
new file mode 100644
index 0000000..c3e07f1
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/versioning.md
@@ -0,0 +1,245 @@
+---
+layout: doc
+title: "Starboard Versioning"
+---
+# Starboard Versioning
+
+## Motivation
+
+When a porter implements Starboard for a platform, it is more precise to say
+that they have implemented support for a certain version of Starboard.
+Changes to the Starboard API are associated with Starboard versions. Any usage
+of new Starboard APIs must also be protected by a compile-time check for the
+Starboard version it belongs to. This decoupling of Cobalt and Starboard
+versions ensures that a porter can update to a newer version of Cobalt, but not
+be required to implement new Starboard APIs, if the version of Starboard they
+have implemented is still supported.
+
+## Starboard API version vs. Starboard application version
+
+The Starboard version describes the set of Starboard APIs available to Starboard
+applications. It will be incremented with every open-source release that
+includes changes to the Starboard API. Reasons to increment the Starboard API
+version include:
+
+* New Starboard APIs
+* Removed Starboard APIs
+* Modified semantics to existing APIs
+
+Some notable cases that do not justify incrementing the Starboard version
+include:
+
+* More descriptive or clearer comments for existing APIs that do not change the
+  semantics
+* New utility classes that are built on top of Starboard APIs, such as
+  `starboard::ScopedFile`
+* Changes that affect the upward API to Starboard applications, but not the
+  downward API to porters. For example, defining new upward APIs in terms of
+  existing Starboard APIs.
+
+A particular Starboard application may be versioned independently of the
+Starboard API. A given version of a Starboard application may support a range of
+Starboard versions. It may be the case that some new functionality in a
+Starboard application requires Starboard APIs that were added to a particular
+API version. If a porter wants to use such a feature, they must therefore also
+implement the required version of the Starboard API. For example, Voice Search
+was added to Cobalt version 5 and requires the SbMicrophone APIs which were
+added to Starboard version 2. Platforms that implemented Starboard version 1
+continued to build and run Cobalt 5 correctly, but the Voice Search feature
+would be unavailable.
+
+## Range of supported Starboard versions
+
+The minimum supported API version is defined by the `SB_MINIMUM_API_VERSION`
+macro, which is defined in starboard/configuration.h. Likewise, the
+`SB_MAXIMUM_API_VERSION` macro defines the maximum supported API version. All
+platforms must declare a `SB_API_VERSION` macro in the platform’s
+configuration.h to declare the starboard version the platform has implemented.
+Declaring implementation for an API version outside this range will result in an
+error at compilation time.
+Generally Starboard applications will not support all versions of the Starboard
+API indefinitely. Starboard application owners may increment the minimum
+required Starboard version at their discretion.
+TBD: Timelines and communication around when an upcoming Cobalt release will
+require porters to implement a newer version of Starboard.
+
+## Using new Starboard APIs from Starboard Applications
+
+Usage of a Starboard API that is not available in all supported Starboard API
+versions must be guarded with a check for `SB_API_VERSION`. Starboard
+applications must continue to function correctly and must not disable existing
+functionality if this check evaluates to false, but it’s acceptable to disable
+new functionality in Starboard applications if this evaluates to false.
+
+## Adding and using new Starboard APIs
+
+### The "Experimental" Starboard Version
+
+At any given time, exactly one version of Starboard will be denoted as the
+"experimental" version, as defined by the `SB_EXPERIMENTAL_API_VERSION` macro in
+`starboard/configuration.h`. It is generally not recommended to declare support
+for this version. Any Starboard APIs defined in the experimental version are
+subject to change and API requirements could be added, removed, or changed at
+any time.
+
+### The "Release Candidate" Starboard Version
+
+At any given time, zero or more versions of Starboard will be denoted as the
+"release candidate" version, as defined by the
+`SB_RELEASE_CANDIDATE_API_VERSION` macro in `starboard/configuration.h`. The
+"release candidate" version is a set of API changes that have been considered
+and tested together. It is reasonable to port against this version, it has gone
+through some stabilization and may become frozen as it currently is. But, be
+aware that it is possible that minor incompatible changes may be made to this
+version if an unexpected situation arises. `SB_RELEASE_CANDIDATE_API_VERSION` is
+not defined if there is no "release candidate" version. Every API version
+greater than `SB_RELEASE_CANDIDATE_API_VERSION` but less than `SB_EXPERIMENTAL_API_VERSION` is also considered a release candidate.
+
+### "Frozen" Starboard versions
+
+All Starboard versions that are less than the experimental and release candidate
+versions are considered frozen. Any Starboard APIs in a frozen version MUST not
+change.
+
+### Version Numbers, and how They Interrelate Numerically
+
+```
+frozen < release-candidate < experimental < future
+```
+
+As mentioned previously, a release candidate version may or may not exist at any
+given time.  When there is a release candate version, it follows the invariant
+above.
+
+### Life of a Starboard API
+
+New Starboard APIs should be defined in the experimental version.
+
+When introducing a new Starboard API (or modifying an existing one), a new
+feature version define should be created within the "Experimental Feature
+Defines" section of `starboard/configuration.h`, and set to
+`SB_EXPERIMENTAL_API_VERSION`. A well written comment should be added in front
+of the feature define that describes exactly what is introduced by the feature.
+In the comment, all new/modified/removed symbols should be identified, and all
+modified header files should be named.
+
+For example,
+
+```
+// in starboard/configuration.h
+
+#define SB_EXPERIMENTAL_API_VERSION 7
+
+#undef SB_RELEASE_CANDIDATE_API_VERSION
+
+// --- Experimental Feature Defines ------------------------------------------
+
+...
+
+// Introduce a new API in starboard/screensaver.h, which declares the following
+// functions for managing the platform's screensaver settings:
+//   SbScreensaverDisableScreensaver()
+//   SbScreensaverEnableScreensaver()
+// Additionally, a new event, kSbEventTypeScreensaverStarted, is introduced in
+// starboard/event.h.
+#define SB_SCREENSAVER_FEATURE_API_VERSION SB_EXPERIMENTAL_API_VERSION
+
+// Introduce a new API in starboard/new_functionality.h which declares the
+// function SbNewFunctionality().
+#define SB_MY_NEW_FEATURE_API_VERSION SB_EXPERIMENTAL_API_VERSION
+
+// Introduce another new API in starboard/still_in_development.h which
+// declares the function SbStillInDevelopment().
+#define SB_MY_OTHER_NEW_FEATURE_API_VERSION SB_EXPERIMENTAL_API_VERSION
+```
+
+When declaring the new interface, the following syntax should be used:
+
+```
+// starboard/new_functionality.h
+#if SB_API_VERSION >= SB_MY_NEW_FEATURE_API_VERSION
+void SbNewFunctionality();
+#endif
+```
+
+Starboard application features that use a new API must have a similar check:
+
+```
+// cobalt/new_feature.cc
+#if SB_API_VERSION >= SB_MY_NEW_FEATURE_API_VERSION
+void DoSomethingCool() {
+  SbNewFunctionality();
+}
+#endif
+```
+
+When promoting the experimental API version to be the release candidate API
+version, the previously undefined `SB_RELEASE_CANDIDATE_API_VERSION` is set to
+the current value of `SB_EXPERIMENTAL_API_VERSION`, and
+`SB_EXPERIMENTAL_API_VERSION` is then incremented by one. As a result,
+`SB_RELEASE_CANDIDATE_API_VERSION` on the master branch should always either be
+undefined, or `SB_EXPERIMENTAL_API_VERSION - 1`.
+
+One or more features are then moved from `SB_EXPERIMENTAL_API_VERSION` to
+`SB_RELEASE_CANDIDATE_API_VERSION`, and into the "Release Candidate Feature
+Defines" section of `starboard/configuration.h`. Some features may be left in
+experimental if they are not ready for release. The documentation comments of
+these features should be moved into the (newly created) section for the
+corresponding version in [starboard/CHANGELOG.md](../CHANGELOG.md).
+
+```
+// in starboard/configuration.h
+
+#define SB_EXPERIMENTAL_API_VERSION 8
+
+#define SB_RELEASE_CANDIDATE_API_VERSION 7
+
+// --- Experimental Feature Defines ------------------------------------------
+
+// Introduce another new API in starboard/still_in_development.h which
+// declares the function SbStillInDevelopment().
+#define SB_MY_OTHER_NEW_FEATURE_API_VERSION SB_EXPERIMENTAL_API_VERSION
+
+// --- Release Candidate Features Defines ------------------------------------
+
+#define SB_MY_NEW_FEATURE_API_VERSION SB_RELEASE_CANDIDATE_API_VERSION
+
+```
+
+When a release candidate branch is promoted to a full release, these new
+Starboard APIs will be irrevocably frozen to the value of
+`SB_RELEASE_CANDIDATE_API_VERSION`, and the release candidate version will be
+undefined. Additionally, the feature defines should be removed.
+
+```
+// starboard/new_functionality.h
+#if SB_API_VERSION >= 7
+void SbNewFunctionality();
+#endif
+
+// starboard/other_new_functionality.h
+#if SB_API_VERSION >= SB_MY_OTHER_NEW_FEATURE_API_VERSION
+void SbStillInDevelopment();
+#endif
+
+// starboard/configuration.h
+#define SB_EXPERIMENTAL_API_VERSION 8
+#undef SB_RELEASE_CANDIDATE_API_VERSION
+
+// cobalt/new_feature.cc
+#if SB_API_VERSION >= 7
+void DoSomethingCool() {
+  SbNewFunctionality();
+}
+#endif
+```
+
+Whoever increments the experimental version must ensure that stubs and reference
+platforms declare support for the new experimental version through their
+respective `SB_API_VERSION` macros.
+
+### Communicating Starboard API changes to porters
+
+When a new version of Starboard is released, [starboard/CHANGELOG.md](../CHANGELOG.md) should be
+updated with the feature define comments for all features enabled in that
+version.
diff --git a/src/cobalt/site/docs/gen/starboard/tools/doc/abstract_launcher.md b/src/cobalt/site/docs/gen/starboard/tools/doc/abstract_launcher.md
new file mode 100644
index 0000000..e404ea5
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/tools/doc/abstract_launcher.md
@@ -0,0 +1,41 @@
+---
+layout: doc
+title: "App Launchers"
+---
+# App Launchers
+
+The app launcher framework is used to run an executable on a given platform,
+allowing its output/results to be used by other scripts or tools.
+
+## Making an App Launcher
+
+In order to use this framework for your platform, there must be a method called
+"GetLauncher()" in the PlatformConfig class that your platform's
+"gyp_configuration.py" file refers to.  It should load and return a module
+containing a class called "Launcher."  This class must inherit from the
+AbstractLauncher class in [abstract_launcher.py](../../abstract_launcher.py),
+and must implement at minimum the following abstract methods:
+
+- Run(): Runs the executable, logs its output, and returns its return code.
+         Generally, any app installation work is also done in this method.
+- Kill(): Kills the currently running executable and cleans up any leftover
+          resources such as threads, processes, etc.
+
+Once the above steps are implemented, tools that use this framework, such as
+[Starboard's unit test runner](../../testing/test_runner.py), should work
+properly for your platform.  For an example of a Launcher class, see
+[this Linux implementation](../../../linux/shared/launcher.py).  For an example
+of the corresponding "GetLauncher()" method, see
+[this gyp_configuration.py file](../../../linux/shared/gyp_configuration.py).
+
+## Using an App Launcher
+
+In order to use this framework in a Python tool, it must import
+abstract_launcher.py and call "abstract_launcher.LauncherFactory()."  This
+method returns a Launcher object from the platform specified by its "platform"
+argument.  To run the launcher, call its "Run()" method, and to stop it, call
+its "Kill()" method.  If your tools need to access the Launcher's output while
+the executable is still running, have it start "Run()" in a separate thread;
+this will allow the main thread to easily read from the Launcher's output file.
+For an example of creating and using a Launcher, see
+[this example](../../example/app_launcher_client.py).
\ No newline at end of file
diff --git a/src/cobalt/site/docs/gen/starboard/tools/doc/testing.md b/src/cobalt/site/docs/gen/starboard/tools/doc/testing.md
new file mode 100644
index 0000000..b9edba5
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/tools/doc/testing.md
@@ -0,0 +1,111 @@
+---
+layout: doc
+title: "Test Runner Documentation"
+---
+# Test Runner Documentation
+
+The scripts in this folder comprise a cross-platform unit test runner. The
+components of this runner are as follows:
+
+## Components
+
+### 1.) test_runner.py
+
+This script is used to run unit test binaries on multiple platforms. To see a
+full list of parameters that can be supplied to the script, run:
+
+    python test_runner.py --help
+
+#### Running Tests:
+
+To run all tests for a given platform, execute the `test_runner.py` script and
+provide at minimum the `--platform` and `--config` arguments.
+
+Example:
+
+	python test_runner.py --platform=android-x86 --config=devel
+
+Running this command will run all unit tests for the `devel` build of the
+`android-x86` platform. To specify a device to run the tests on, provide the
+`--device_id` argument, as shown below:
+
+    python test_runner.py --platform=android-x86 --config=devel \
+      --device_id=emulator-4
+
+#### Running a Single Test:
+
+If you would like to run a single unit test binary and view its output, you can
+do so by using the `--target_name` parameter and providing a test binary name,
+as shown below:
+
+    python test_runner.py --platform=android-x86 --config=devel \
+      --device_id=emulator-4 --target_name=audio_test
+
+#### Building Tests:
+
+You can also use this script to build your unit test binaries before running
+them. To do this, provide the `-b` command line flag. If you would like to
+build the tests and then run them, provide the flags `-br`.
+
+### 2.) Master list of test binaries
+
+In your application's `starboard_configuration.py` file, define a variable
+called TEST_TARGETS. It should be a list containing the names of all of the
+test binaries that you want the test runner to run. An example is shown below:
+
+    TEST_TARGETS =[
+        'audio_test',
+        'bindings_test',
+    ]
+
+If your 'starboard_configuration.py' file contains this list, then every
+platform you support in Starboard will try to run these test binaries unless
+they are filtered out as described below.
+
+## Filtering Tests
+
+To filter out tests that you do not want to run for a specific platform,
+implement a method within the platform's `PlatformConfiguration` subclass called
+`GetTestFilters()`. The `PlatformConfiguration` subclass lives in the
+`gyp_configuration.py` file for each platform. If the tests are
+application-specific, you may define `GetTestFilters()` on an optional
+`ApplicationConfiguration` subclass, which will be found in the
+`<platform-directory>/<application-name>/configuration.py` subdirectory. See
+[this Linux implementation](../../linux/x64x11/cobalt/configuration.py) for an
+example.
+
+The `GetTestFilters()` function should return a list of `TestFilter` objects,
+which can be constructed by importing `starboard.tools.testing.test_filter`. To
+make a `TestFilter` object, provide the constructor with the test target name,
+the name of the actual unit test that the target runs, and optionally, the build
+configuration from which the test should be excluded. An example is shown below:
+
+    test_filter.TestFilter('math_test', 'Vector3dTest.IsZero', 'debug')
+
+If a configuration is not provided, then the test will be exluded from all
+configurations.
+
+To filter out all tests for a particular target, provide
+`test_filter.FILTER_ALL` as the test name.
+
+To disable unit testing for all targets and all configurations, return a list
+containing `test_filter.DISABLE_TESTING`.
+
+## Environment Variables
+
+If a platform requires extra environment variables in order to run tests
+properly, implement a method called `GetTestEnvVariables()` in the same
+`PlatformConfiguration` or `ApplicationConfiguration` mentioned above. The
+application-level variables will be merged on top of the platform-level
+variables. There is an example of this method in the provided Linux
+implementation. The method should return a dictionary that maps test binary
+names to dictionaries of environment variables that they need.
+
+Example:
+
+    def GetTestEnvVariables(self):
+      return {
+          'base_unittests': {'ASAN_OPTIONS': 'detect_leaks=0'},
+          'crypto_unittests': {'ASAN_OPTIONS': 'detect_leaks=0'},
+          'net_unittests': {'ASAN_OPTIONS': 'detect_leaks=0'}
+      }
diff --git a/src/cobalt/updater/one_app_only_sandbox.cc b/src/cobalt/updater/one_app_only_sandbox.cc
index 8b31ce4..33e6478 100644
--- a/src/cobalt/updater/one_app_only_sandbox.cc
+++ b/src/cobalt/updater/one_app_only_sandbox.cc
@@ -26,13 +26,17 @@
 #include "cobalt/browser/switches.h"
 #include "cobalt/version.h"
 #include "starboard/event.h"
+#include "starboard/loader_app/app_key.h"
 #include "starboard/system.h"
 
 namespace {
 
+const char kMainAppKey[] = "aHR0cHM6Ly93d3cueW91dHViZS5jb20vdHY=";
+// Use the html instead of url or app key to target the Evergreen cert test
+// page, because there are various urls to launch the test page.
 const char kEvergreenCertTestHtml[] = "evergreen-cert-test.html";
 
-bool is_evergreen_cert_test = false;
+bool is_target_app = false;
 
 cobalt::browser::Application* g_application = NULL;
 bool g_is_startup_switch_set = false;
@@ -75,9 +79,8 @@
   }
   LOG(INFO) << "Concealing application.";
   DCHECK(!g_application);
-  g_application =
-      new cobalt::browser::Application(quit_closure, true /*should_preload*/,
-                                       timestamp);
+  g_application = new cobalt::browser::Application(
+      quit_closure, true /*should_preload*/, timestamp);
   DCHECK(g_application);
 }
 
@@ -91,15 +94,13 @@
   LOG(INFO) << "Starting application.";
 #if SB_API_VERSION >= 13
   DCHECK(!g_application);
-  g_application =
-      new cobalt::browser::Application(quit_closure, false /*not_preload*/,
-                                       timestamp);
+  g_application = new cobalt::browser::Application(
+      quit_closure, false /*not_preload*/, timestamp);
   DCHECK(g_application);
 #else
   if (!g_application) {
-    g_application = new cobalt::browser::Application(quit_closure,
-                                                     false /*should_preload*/,
-                                                     timestamp);
+    g_application = new cobalt::browser::Application(
+        quit_closure, false /*should_preload*/, timestamp);
     DCHECK(g_application);
   } else {
     g_application->Start(timestamp);
@@ -126,7 +127,7 @@
 }  // namespace
 
 void SbEventHandle(const SbEvent* event) {
-  if (is_evergreen_cert_test)
+  if (is_target_app)
     return ::cobalt::wrap_main::BaseEventHandler<
         PreloadApplication, StartApplication, HandleStarboardEvent,
         StopApplication>(event);
@@ -134,19 +135,22 @@
   const SbEventStartData* data = static_cast<SbEventStartData*>(event->data);
   const base::CommandLine command_line(
       data->argument_count, const_cast<const char**>(data->argument_values));
+
   if (command_line.HasSwitch(cobalt::browser::switches::kInitialURL)) {
     std::string url = command_line.GetSwitchValueASCII(
         cobalt::browser::switches::kInitialURL);
-    size_t pos = url.find(kEvergreenCertTestHtml);
-    if (pos != std::string::npos) {
-      // If the url is the Evergreen cert test page, hook up the app lifecycle
-      // functions.
-      is_evergreen_cert_test = true;
-      return ::cobalt::wrap_main::BaseEventHandler<
-          PreloadApplication, StartApplication, HandleStarboardEvent,
-          StopApplication>(event);
+    if (starboard::loader_app::GetAppKey(url) != kMainAppKey &&
+        url.find(kEvergreenCertTestHtml) == std::string::npos) {
+      // If the app is not the main app nor Evergreen cert test page, stop the
+      // app.
+      SbSystemRequestStop(0);
     }
   }
-  // If the url is not the Evergreen cert test page, stop the app.
-  SbSystemRequestStop(0);
+
+  // If the url is the main app or the Evergreen cert test page, hook up the app
+  // lifecycle functions.
+  is_target_app = true;
+  return ::cobalt::wrap_main::BaseEventHandler<
+      PreloadApplication, StartApplication, HandleStarboardEvent,
+      StopApplication>(event);
 }
diff --git a/src/cobalt/updater/one_app_only_sandbox.gyp b/src/cobalt/updater/one_app_only_sandbox.gyp
index f311023..0d99d26 100644
--- a/src/cobalt/updater/one_app_only_sandbox.gyp
+++ b/src/cobalt/updater/one_app_only_sandbox.gyp
@@ -20,6 +20,7 @@
       'dependencies': [
         '<(DEPTH)/cobalt/browser/browser.gyp:browser',
         '<(DEPTH)/net/net.gyp:net',
+        '<(DEPTH)/starboard/loader_app/app_key.gyp:app_key',
         '<(DEPTH)/starboard/starboard.gyp:starboard',
       ],
       'sources': [
diff --git a/src/cobalt/version.h b/src/cobalt/version.h
index 94b0f68..b338e71 100644
--- a/src/cobalt/version.h
+++ b/src/cobalt/version.h
@@ -35,6 +35,6 @@
 //                  release is cut.
 //.
 
-#define COBALT_VERSION "22.lts.1"
+#define COBALT_VERSION "22.lts.2"
 
 #endif  // COBALT_VERSION_H_
diff --git a/src/starboard/BUILD.gn b/src/starboard/BUILD.gn
index b421b3e..b9ab2b6 100644
--- a/src/starboard/BUILD.gn
+++ b/src/starboard/BUILD.gn
@@ -62,6 +62,7 @@
         "//third_party/crashpad/client",
         "//third_party/crashpad/handler",
       ]
+      data_deps = [ "//starboard/loader_app" ]
     }
   }
 }
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/CobaltSystemConfigChangeReceiver.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/CobaltSystemConfigChangeReceiver.java
index 5207655..9f2c5d9 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/CobaltSystemConfigChangeReceiver.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/CobaltSystemConfigChangeReceiver.java
@@ -31,18 +31,39 @@
   CobaltSystemConfigChangeReceiver(Context appContext, Runnable stopRequester) {
     this.isForeground = true;
     this.stopRequester = stopRequester;
-    appContext.registerReceiver(this, new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
+    IntentFilter filter = new IntentFilter();
+    filter.addAction(Intent.ACTION_LOCALE_CHANGED);
+    filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
+    filter.addAction(Intent.ACTION_TIME_CHANGED);
+    filter.addAction(Intent.ACTION_DATE_CHANGED);
+    appContext.registerReceiver(this, filter);
   }
 
   @Override
   public void onReceive(Context context, Intent intent) {
-    if ((!Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) || isForeground) return;
+    if (isForeground) {
+      return;
+    }
 
-    Log.w(TAG, "System locale settings have changed.");
-    stopRequester.run();
+    switch (intent.getAction()) {
+      case Intent.ACTION_TIMEZONE_CHANGED:
+      case Intent.ACTION_TIME_CHANGED:
+      case Intent.ACTION_DATE_CHANGED:
+        Log.w(TAG, "System Date or Time have changed.");
+        nativeDateTimeConfigurationChanged();
+        break;
+      case Intent.ACTION_LOCALE_CHANGED:
+        Log.w(TAG, "System locale settings have changed.");
+        stopRequester.run();
+        break;
+      default:
+        Log.w(TAG, "Unknown intent.");
+    }
   }
 
   public void setForeground(final boolean isForeground) {
     this.isForeground = isForeground;
   }
+
+  private native void nativeDateTimeConfigurationChanged();
 }
diff --git a/src/starboard/android/shared/application_android.cc b/src/starboard/android/shared/application_android.cc
index 598bed7..45a57af 100644
--- a/src/starboard/android/shared/application_android.cc
+++ b/src/starboard/android/shared/application_android.cc
@@ -247,13 +247,13 @@
       if (window_) {
         window_->native_window = native_window_;
       }
+      // Now that we have the window, signal that the Android UI thread can
+      // continue, before we start or resume the Starboard app.
+      android_command_condition_.Signal();
       // Media playback service is tied to UI window being created/destroyed
       // (rather than to the Activity lifecycle), the service should be
       // stopped before native window being created.
       StopMediaPlaybackService();
-      // Now that we have the window, signal that the Android UI thread can
-      // continue, before we start or resume the Starboard app.
-      android_command_condition_.Signal();
     }
       if (state() == kStateUnstarted) {
         // This is the initial launch, so we have to start Cobalt now that we
@@ -261,16 +261,9 @@
         env->CallStarboardVoidMethodOrAbort("beforeStartOrResume", "()V");
 #if SB_API_VERSION >= 13
         DispatchStart(GetAppStartTimestamp());
-#else  // SB_API_VERSION >= 13
+#else   // SB_API_VERSION >= 13
         DispatchStart();
 #endif  // SB_API_VERSION >= 13
-      } else if (state() == kStateConcealed || state() == kStateFrozen) {
-#if SB_API_VERSION >= 13
-        DispatchAndDelete(new Event(kSbEventTypeReveal, SbTimeGetMonotonicNow(),
-                                    NULL, NULL));
-#else  // SB_API_VERSION >= 13
-        DispatchAndDelete(new Event(kSbEventTypeReveal, NULL, NULL));
-#endif  // SB_API_VERSION >= 13
       } else {
         // Now that we got a window back, change the command for the switch
         // below to sync up with the current activity lifecycle.
@@ -282,17 +275,13 @@
       // early in SendAndroidCommand().
       {
         ScopedLock lock(android_command_mutex_);
-        // Media playback service is tied to UI window being created/destroyed
-        // (rather than to the Activity lifecycle). The service should be
-        // started after window being destroyed.
-        StartMediaPlaybackService();
-        // Cobalt can't keep running without a window, even if the Activity
-        // hasn't stopped yet. DispatchAndDelete() will inject events as needed
-        // if we're not already paused.
+// Cobalt can't keep running without a window, even if the Activity
+// hasn't stopped yet. DispatchAndDelete() will inject events as needed
+// if we're not already paused.
 #if SB_API_VERSION >= 13
-        DispatchAndDelete(new Event(kSbEventTypeConceal, SbTimeGetMonotonicNow(),
-                                    NULL, NULL));
-#else  // SB_API_VERSION >= 13
+        DispatchAndDelete(new Event(kSbEventTypeConceal,
+                                    SbTimeGetMonotonicNow(), NULL, NULL));
+#else   // SB_API_VERSION >= 13
         DispatchAndDelete(new Event(kSbEventTypeConceal, NULL, NULL));
 #endif  // SB_API_VERSION >= 13
         if (window_) {
@@ -302,6 +291,10 @@
         // Now that we've suspended the Starboard app, and let go of the window,
         // signal that the Android UI thread can continue.
         android_command_condition_.Signal();
+        // Media playback service is tied to UI window being created/destroyed
+        // (rather than to the Activity lifecycle). The service should be
+        // started after window being destroyed.
+        StartMediaPlaybackService();
       }
       break;
 
@@ -349,9 +342,9 @@
         } else {
           SB_LOG(INFO) << "ApplicationAndroid Inject: kSbEventTypeLink";
 #if SB_API_VERSION >= 13
-          Inject(new Event(kSbEventTypeLink, SbTimeGetMonotonicNow(),
-              deep_link, SbMemoryDeallocate));
-#else  // SB_API_VERSION >= 13
+          Inject(new Event(kSbEventTypeLink, SbTimeGetMonotonicNow(), deep_link,
+                           SbMemoryDeallocate));
+#else   // SB_API_VERSION >= 13
           Inject(new Event(kSbEventTypeLink, deep_link, SbMemoryDeallocate));
 #endif  // SB_API_VERSION >= 13
         }
@@ -359,37 +352,37 @@
       break;
   }
 
-  // If there's a window, sync the app state to the Activity lifecycle, letting
-  // DispatchAndDelete() inject events as needed if we missed a state.
+// If there's a window, sync the app state to the Activity lifecycle, letting
+// DispatchAndDelete() inject events as needed if we missed a state.
 #if SB_API_VERSION >= 13
-if (native_window_) {
+  if (native_window_) {
     switch (sync_state) {
       case AndroidCommand::kStart:
-        DispatchAndDelete(new Event(kSbEventTypeReveal, SbTimeGetMonotonicNow(),
-                                    NULL, NULL));
+        DispatchAndDelete(
+            new Event(kSbEventTypeReveal, SbTimeGetMonotonicNow(), NULL, NULL));
         break;
       case AndroidCommand::kResume:
-        DispatchAndDelete(new Event(kSbEventTypeFocus, SbTimeGetMonotonicNow(),
-                                    NULL, NULL));
+        DispatchAndDelete(
+            new Event(kSbEventTypeFocus, SbTimeGetMonotonicNow(), NULL, NULL));
         break;
       case AndroidCommand::kPause:
-        DispatchAndDelete(new Event(kSbEventTypeBlur, SbTimeGetMonotonicNow(),
-                                    NULL, NULL));
+        DispatchAndDelete(
+            new Event(kSbEventTypeBlur, SbTimeGetMonotonicNow(), NULL, NULL));
         break;
       case AndroidCommand::kStop:
         if (state() != kStateConcealed && state() != kStateFrozen) {
           // We usually conceal when losing the window above, but if the window
           // wasn't destroyed (e.g. when Daydream starts) then we still have to
           // conceal when the Activity is stopped.
-          DispatchAndDelete(new Event(kSbEventTypeConceal, SbTimeGetMonotonicNow(),
-                                      NULL, NULL));
+          DispatchAndDelete(new Event(kSbEventTypeConceal,
+                                      SbTimeGetMonotonicNow(), NULL, NULL));
         }
         break;
       default:
         break;
     }
   }
-#else  // SB_API_VERSION >= 13
+#else   // SB_API_VERSION >= 13
   if (native_window_) {
     switch (sync_state) {
       case AndroidCommand::kStart:
@@ -671,8 +664,7 @@
 SbTimeMonotonic ApplicationAndroid::GetAppStartTimestamp() {
   JniEnvExt* env = JniEnvExt::Get();
   jlong app_start_timestamp =
-      env->CallStarboardLongMethodOrAbort("getAppStartTimestamp",
-                                          "()J");
+      env->CallStarboardLongMethodOrAbort("getAppStartTimestamp", "()J");
   return app_start_timestamp;
 }
 
@@ -684,6 +676,19 @@
   return SbTimeGetMonotonicNow();
 }
 
+void ApplicationAndroid::SendDateTimeConfigurationChangedEvent() {
+  // Set the timezone to allow SbTimeZoneGetName() to return updated timezone.
+  tzset();
+  Inject(new Event(kSbEventDateTimeConfigurationChanged, NULL, NULL));
+}
+
+extern "C" SB_EXPORT_PLATFORM void
+Java_dev_cobalt_coat_CobaltSystemConfigChangeReceiver_nativeDateTimeConfigurationChanged(
+    JNIEnv* env,
+    jobject jcaller) {
+  ApplicationAndroid::Get()->SendDateTimeConfigurationChangedEvent();
+}
+
 }  // namespace shared
 }  // namespace android
 }  // namespace starboard
diff --git a/src/starboard/android/shared/application_android.h b/src/starboard/android/shared/application_android.h
index 1c8dde4..6e5a458 100644
--- a/src/starboard/android/shared/application_android.h
+++ b/src/starboard/android/shared/application_android.h
@@ -94,6 +94,8 @@
   void OsNetworkStatusChange(bool became_online);
   SbTimeMonotonic GetAppStartTimestamp();
 
+  void SendDateTimeConfigurationChangedEvent();
+
  protected:
   // --- Application overrides ---
   void Initialize() override;
diff --git a/src/starboard/android/shared/install_target.gni b/src/starboard/android/shared/install_target.gni
index 4111a06..1442c9f 100644
--- a/src/starboard/android/shared/install_target.gni
+++ b/src/starboard/android/shared/install_target.gni
@@ -89,6 +89,8 @@
       "-P",
       "cobaltProductDir=$root_out_dir",
       "-P",
+      "cobaltLibraryDir=$root_out_dir",
+      "-P",
       "cobaltTarget=$installable_target_name",
       "-P",
       "enableVulkan=$enable_vulkan",
diff --git a/src/starboard/android/shared/launcher.py b/src/starboard/android/shared/launcher.py
index abd2787..2e90983 100644
--- a/src/starboard/android/shared/launcher.py
+++ b/src/starboard/android/shared/launcher.py
@@ -450,3 +450,7 @@
   def GetDeviceIp(self):
     """Gets the device IP. TODO: Implement."""
     return None
+
+  def GetDeviceOutputPath(self):
+    """Writable path where test targets can output files"""
+    return '/data/data/{}/cache/'.format(_APP_PACKAGE_NAME)
diff --git a/src/starboard/android/shared/media_is_video_supported.cc b/src/starboard/android/shared/media_is_video_supported.cc
index 095a698..09895ed 100644
--- a/src/starboard/android/shared/media_is_video_supported.cc
+++ b/src/starboard/android/shared/media_is_video_supported.cc
@@ -42,13 +42,13 @@
     return false;
   }
   JniEnvExt* env = JniEnvExt::Get();
+  ScopedLocalJavaRef<jstring> j_mime(env->NewStringStandardUTFOrAbort(mime));
 
   // An HDR capable VP9 or AV1 decoder is needed to handle HDR at all.
   bool has_hdr_capable_decoder =
       JniEnvExt::Get()->CallStaticBooleanMethodOrAbort(
           "dev/cobalt/media/MediaCodecUtil", "hasHdrCapableVideoDecoder",
-          "(Ljava/lang/String;)Z",
-          env->NewStringStandardUTFOrAbort(mime)) == JNI_TRUE;
+          "(Ljava/lang/String;)Z", j_mime.Get()) == JNI_TRUE;
   if (!has_hdr_capable_decoder) {
     return false;
   }
@@ -98,14 +98,16 @@
   // Check extended parameters for correctness and return false if any invalid
   // invalid params are found.
   MimeType mime_type(content_type);
-  // Allows for enabling tunneled playback. Disabled by default.
-  // https://source.android.com/devices/tv/multimedia-tunneling
-  mime_type.RegisterBoolParameter("tunnelmode");
-  // Override endianness on HDR Info header. Defaults to little.
-  mime_type.RegisterStringParameter("hdrinfoendianness", "big|little");
+  if (strlen(content_type) > 0) {
+    // Allows for enabling tunneled playback. Disabled by default.
+    // https://source.android.com/devices/tv/multimedia-tunneling
+    mime_type.RegisterBoolParameter("tunnelmode");
+    // Override endianness on HDR Info header. Defaults to little.
+    mime_type.RegisterStringParameter("hdrinfoendianness", "big|little");
 
-  if (!mime_type.is_valid()) {
-    return false;
+    if (!mime_type.is_valid()) {
+      return false;
+    }
   }
 
   bool must_support_tunnel_mode =
diff --git a/src/starboard/android/shared/microphone_impl.cc b/src/starboard/android/shared/microphone_impl.cc
index 1972d0e..68c4188 100644
--- a/src/starboard/android/shared/microphone_impl.cc
+++ b/src/starboard/android/shared/microphone_impl.cc
@@ -18,10 +18,12 @@
 #include <SLES/OpenSLES_Android.h>
 
 #include <algorithm>
+#include <cstddef>
 #include <queue>
 
 #include "starboard/android/shared/jni_env_ext.h"
 #include "starboard/common/log.h"
+#include "starboard/common/mutex.h"
 #include "starboard/common/scoped_ptr.h"
 #include "starboard/memory.h"
 #include "starboard/shared/starboard/thread_checker.h"
@@ -83,8 +85,10 @@
   // Keeps track of the microphone's current state.
   State state_;
   // Audio data that has been delivered to the buffer queue.
+  Mutex delivered_queue_mutex_;
   std::queue<int16_t*> delivered_queue_;
   // Audio data that is ready to be read.
+  Mutex ready_queue_mutex_;
   std::queue<int16_t*> ready_queue_;
 };
 
@@ -169,7 +173,10 @@
   for (int i = 0; i < kNumOfOpenSLESBuffers; ++i) {
     int16_t* buffer = new int16_t[kSamplesPerBuffer];
     memset(buffer, 0, kBufferSizeInBytes);
-    delivered_queue_.push(buffer);
+    {
+      ScopedLock lock(delivered_queue_mutex_);
+      delivered_queue_.push(buffer);
+    }
     SLresult result =
         (*buffer_object_)->Enqueue(buffer_object_, buffer, kBufferSizeInBytes);
     if (!CheckReturnValue(result)) {
@@ -245,14 +252,17 @@
 
   int read_bytes = 0;
   scoped_ptr<int16_t> buffer;
-  // Go through the ready queue, reading and sending audio data.
-  while (!ready_queue_.empty() &&
-         audio_data_size - read_bytes >= kBufferSizeInBytes) {
-    buffer.reset(ready_queue_.front());
-    memcpy(static_cast<uint8_t*>(out_audio_data) + read_bytes,
-                 buffer.get(), kBufferSizeInBytes);
-    ready_queue_.pop();
-    read_bytes += kBufferSizeInBytes;
+  {
+    ScopedLock lock(ready_queue_mutex_);
+    // Go through the ready queue, reading and sending audio data.
+    while (!ready_queue_.empty() &&
+           audio_data_size - read_bytes >= kBufferSizeInBytes) {
+      buffer.reset(ready_queue_.front());
+      memcpy(static_cast<uint8_t*>(out_audio_data) + read_bytes, buffer.get(),
+             kBufferSizeInBytes);
+      ready_queue_.pop();
+      read_bytes += kBufferSizeInBytes;
+    }
   }
 
   buffer.reset();
@@ -272,18 +282,29 @@
 }
 
 void SbMicrophoneImpl::SwapAndPublishBuffer() {
-  if (!delivered_queue_.empty()) {
-    // The front item in the delivered queue already has the buffered data, so
-    // move it from the delivered queue to the ready queue for future reads.
-    int16_t* buffer = delivered_queue_.front();
-    delivered_queue_.pop();
+  int16_t* buffer = nullptr;
+  {
+    ScopedLock lock(delivered_queue_mutex_);
+    if (!delivered_queue_.empty()) {
+      // The front item in the delivered queue already has the buffered data, so
+      // move it from the delivered queue to the ready queue for future reads.
+      buffer = delivered_queue_.front();
+      delivered_queue_.pop();
+    }
+  }
+
+  if (buffer != NULL) {
+    ScopedLock lock(ready_queue_mutex_);
     ready_queue_.push(buffer);
   }
 
   if (state_ == kOpened) {
     int16_t* buffer = new int16_t[kSamplesPerBuffer];
     memset(buffer, 0, kBufferSizeInBytes);
-    delivered_queue_.push(buffer);
+    {
+      ScopedLock lock(delivered_queue_mutex_);
+      delivered_queue_.push(buffer);
+    }
     SLresult result =
         (*buffer_object_)->Enqueue(buffer_object_, buffer, kBufferSizeInBytes);
     CheckReturnValue(result);
@@ -437,14 +458,20 @@
     }
   }
 
-  while (!delivered_queue_.empty()) {
-    delete[] delivered_queue_.front();
-    delivered_queue_.pop();
+  {
+    ScopedLock lock(delivered_queue_mutex_);
+    while (!delivered_queue_.empty()) {
+      delete[] delivered_queue_.front();
+      delivered_queue_.pop();
+    }
   }
 
-  while (!ready_queue_.empty()) {
-    delete[] ready_queue_.front();
-    ready_queue_.pop();
+  {
+    ScopedLock lock(ready_queue_mutex_);
+    while (!ready_queue_.empty()) {
+      delete[] ready_queue_.front();
+      ready_queue_.pop();
+    }
   }
 }
 
diff --git a/src/starboard/android/shared/player_create.cc b/src/starboard/android/shared/player_create.cc
index f4c4083..e9e1041 100644
--- a/src/starboard/android/shared/player_create.cc
+++ b/src/starboard/android/shared/player_create.cc
@@ -17,6 +17,8 @@
 #include "starboard/android/shared/video_decoder.h"
 #include "starboard/android/shared/video_window.h"
 #include "starboard/common/log.h"
+#include "starboard/common/media.h"
+#include "starboard/common/string.h"
 #include "starboard/configuration.h"
 #include "starboard/decode_target.h"
 #include "starboard/shared/starboard/player/filter/filter_based_player_worker_handler.h"
@@ -37,8 +39,15 @@
                         SbPlayerErrorFunc player_error_func,
                         void* context,
                         SbDecodeTargetGraphicsContextProvider* provider) {
+  if (!player_error_func) {
+    SB_LOG(ERROR) << "|player_error_func| cannot be null.";
+    return kSbPlayerInvalid;
+  }
+
   if (!creation_param) {
     SB_LOG(ERROR) << "CreationParam cannot be null.";
+    player_error_func(kSbPlayerInvalid, context, kSbPlayerErrorDecode,
+                      "CreationParam cannot be null");
     return kSbPlayerInvalid;
   }
 
@@ -56,15 +65,22 @@
 
   if (!audio_mime) {
     SB_LOG(ERROR) << "creation_param->audio_sample_info.mime cannot be null.";
+    player_error_func(kSbPlayerInvalid, context, kSbPlayerErrorDecode,
+                      "creation_param->audio_sample_info.mime cannot be null");
     return kSbPlayerInvalid;
   }
   if (!video_mime) {
     SB_LOG(ERROR) << "creation_param->video_sample_info.mime cannot be null.";
+    player_error_func(kSbPlayerInvalid, context, kSbPlayerErrorDecode,
+                      "creation_param->video_sample_info.mime cannot be null");
     return kSbPlayerInvalid;
   }
   if (!max_video_capabilities) {
     SB_LOG(ERROR) << "creation_param->video_sample_info.max_video_capabilities"
                   << " cannot be null.";
+    player_error_func(kSbPlayerInvalid, context, kSbPlayerErrorDecode,
+                      "creation_param->video_sample_info.max_video_"
+                      "capabilities cannot be null");
     return kSbPlayerInvalid;
   }
 
@@ -73,8 +89,24 @@
                << "\", and max video capabilities \"" << max_video_capabilities
                << "\".";
 
-  if (!sample_deallocate_func || !decoder_status_func || !player_status_func ||
-      !player_error_func) {
+  if (!sample_deallocate_func) {
+    SB_LOG(ERROR) << "|sample_deallocate_func| cannot be null.";
+    player_error_func(kSbPlayerInvalid, context, kSbPlayerErrorDecode,
+                      "|sample_deallocate_func| cannot be null.");
+    return kSbPlayerInvalid;
+  }
+
+  if (!decoder_status_func) {
+    SB_LOG(ERROR) << "|decoder_status_func| cannot be null.";
+    player_error_func(kSbPlayerInvalid, context, kSbPlayerErrorDecode,
+                      "|decoder_status_func| cannot be null.");
+    return kSbPlayerInvalid;
+  }
+
+  if (!player_status_func) {
+    SB_LOG(ERROR) << "|player_status_func| cannot be null.";
+    player_error_func(kSbPlayerInvalid, context, kSbPlayerErrorDecode,
+                      "|player_status_func| cannot be null.");
     return kSbPlayerInvalid;
   }
 
@@ -86,7 +118,13 @@
       audio_codec != kSbMediaAudioCodecAc3 &&
       audio_codec != kSbMediaAudioCodecEac3 &&
       audio_codec != kSbMediaAudioCodecOpus) {
-    SB_LOG(ERROR) << "Unsupported audio codec " << audio_codec;
+    SB_LOG(ERROR) << "Unsupported audio codec: "
+                  << starboard::GetMediaAudioCodecName(audio_codec) << ".";
+    player_error_func(
+        kSbPlayerInvalid, context, kSbPlayerErrorDecode,
+        starboard::FormatString("Unsupported audio codec: %s",
+                                starboard::GetMediaAudioCodecName(audio_codec))
+            .c_str());
     return kSbPlayerInvalid;
   }
 
@@ -95,7 +133,13 @@
       video_codec != kSbMediaVideoCodecH265 &&
       video_codec != kSbMediaVideoCodecVp9 &&
       video_codec != kSbMediaVideoCodecAv1) {
-    SB_LOG(ERROR) << "Unsupported video codec " << video_codec;
+    SB_LOG(ERROR) << "Unsupported video codec: "
+                  << starboard::GetMediaVideoCodecName(video_codec) << ".";
+    player_error_func(
+        kSbPlayerInvalid, context, kSbPlayerErrorDecode,
+        starboard::FormatString("Unsupported video codec: %s",
+                                starboard::GetMediaVideoCodecName(video_codec))
+            .c_str());
     return kSbPlayerInvalid;
   }
 
@@ -103,20 +147,33 @@
       video_codec == kSbMediaVideoCodecNone) {
     SB_LOG(ERROR) << "SbPlayerCreate() requires at least one audio track or"
                   << " one video track.";
+    player_error_func(kSbPlayerInvalid, context, kSbPlayerErrorDecode,
+                      "SbPlayerCreate() requires at least one audio track or  "
+                      "one video track");
     return kSbPlayerInvalid;
   }
 
+  std::string error_message;
   if (has_audio && creation_param->audio_sample_info.number_of_channels >
                        SbAudioSinkGetMaxChannels()) {
-    SB_LOG(ERROR) << "creation_param->audio_sample_info.number_of_channels"
-                  << " exceeds the maximum number of audio channels supported"
-                  << " by this platform.";
+    error_message = starboard::FormatString(
+        "Number of audio channels (%d) exceeds the maximum number of audio "
+        "channels supported by this platform (%d)",
+        creation_param->audio_sample_info.number_of_channels,
+        SbAudioSinkGetMaxChannels());
+    SB_LOG(ERROR) << error_message << ".";
+    player_error_func(kSbPlayerInvalid, context, kSbPlayerErrorDecode,
+                      error_message.c_str());
     return kSbPlayerInvalid;
   }
 
   auto output_mode = creation_param->output_mode;
   if (SbPlayerGetPreferredOutputMode(creation_param) != output_mode) {
-    SB_LOG(ERROR) << "Unsupported player output mode " << output_mode;
+    error_message = starboard::FormatString(
+        "Unsupported player output mode: %d", output_mode);
+    SB_LOG(ERROR) << error_message << ".";
+    player_error_func(kSbPlayerInvalid, context, kSbPlayerErrorDecode,
+                      error_message.c_str());
     return kSbPlayerInvalid;
   }
 
@@ -127,8 +184,16 @@
     // support one main player on Android, which can be either in punch out mode
     // or decode to target mode.
     const int kMaxNumberOfHardwareDecoders = 1;
-    if (VideoDecoder::number_of_hardware_decoders() >=
-        kMaxNumberOfHardwareDecoders) {
+    auto number_of_hardware_decoders =
+        VideoDecoder::number_of_hardware_decoders();
+    if (number_of_hardware_decoders >= kMaxNumberOfHardwareDecoders) {
+      error_message = starboard::FormatString(
+          "Number of hardware decoders (%d) is equal to or exceeds the max "
+          "number of hardware decoders supported by this platform (%d)",
+          number_of_hardware_decoders, kMaxNumberOfHardwareDecoders);
+      SB_LOG(ERROR) << error_message << ".";
+      player_error_func(kSbPlayerInvalid, context, kSbPlayerErrorDecode,
+                        error_message.c_str());
       return kSbPlayerInvalid;
     }
   }
@@ -143,6 +208,8 @@
     if (!starboard::android::shared::VideoSurfaceHolder::
             IsVideoSurfaceAvailable()) {
       SB_LOG(ERROR) << "Video surface is not available now.";
+      player_error_func(kSbPlayerInvalid, context, kSbPlayerErrorDecode,
+                        "Video surface is not available now");
       return kSbPlayerInvalid;
     }
   }
@@ -161,5 +228,12 @@
     SbPlayerSetBounds(player, 0, 0, 0, 0, 0);
   }
 
+  if (!SbPlayerIsValid(player)) {
+    SB_LOG(ERROR)
+        << "Invalid player returned by SbPlayerPrivate::CreateInstance().";
+    player_error_func(
+        kSbPlayerInvalid, context, kSbPlayerErrorDecode,
+        "Invalid player returned by SbPlayerPrivate::CreateInstance()");
+  }
   return player;
 }
diff --git a/src/starboard/android/shared/window_get_size.cc b/src/starboard/android/shared/window_get_size.cc
index a6182c4..744e233 100644
--- a/src/starboard/android/shared/window_get_size.cc
+++ b/src/starboard/android/shared/window_get_size.cc
@@ -29,6 +29,10 @@
     return false;
   }
 
+  if (window->native_window == NULL) {
+    SB_DLOG(ERROR) << __FUNCTION__ << ": Native window has been destroyed.";
+    return false;
+  }
   size->width = ANativeWindow_getWidth(window->native_window);
   size->height = ANativeWindow_getHeight(window->native_window);
 
diff --git a/src/starboard/android/x86/gyp_configuration.py b/src/starboard/android/x86/gyp_configuration.py
index 80de3ec..0df1f47 100644
--- a/src/starboard/android/x86/gyp_configuration.py
+++ b/src/starboard/android/x86/gyp_configuration.py
@@ -54,16 +54,6 @@
           'AudioDecoderTests/*',
           'VideoDecoderTests/*',
 
-          'PlayerComponentsTests/PlayerComponentsTest.Preroll/*',
-          'PlayerComponentsTests/PlayerComponentsTest.Pause/*',
-
-          'PlayerComponentsTests/PlayerComponentsTest.*/2',
-          'PlayerComponentsTests/PlayerComponentsTest.*/4',
-          'PlayerComponentsTests/PlayerComponentsTest.*/9',
-          'PlayerComponentsTests/PlayerComponentsTest.*/11',
-          'PlayerComponentsTests/PlayerComponentsTest.*/16',
-          'PlayerComponentsTests/PlayerComponentsTest.*/17',
-          'PlayerComponentsTests/PlayerComponentsTest.*/20',
-          'PlayerComponentsTests/PlayerComponentsTest.*/21',
+          'PlayerComponentsTests/*',
       ],
   }
diff --git a/src/starboard/build/collect_deploy_content.gypi b/src/starboard/build/collect_deploy_content.gypi
index 4068e57..65953f5 100644
--- a/src/starboard/build/collect_deploy_content.gypi
+++ b/src/starboard/build/collect_deploy_content.gypi
@@ -51,7 +51,7 @@
         'collect_deploy_content_extra_args': [ '--use_absolute_symlinks' ],
       }
     }],
-    ['cobalt_docker_build == 1 and host_os == "win"', {
+    ['cobalt_docker_build == 1 and host_os == "win" and cobalt_fastbuild != 1', {
       'variables': {
         'collect_deploy_content_extra_args': [ '--copy_override' ],
       }
diff --git a/src/starboard/build/collect_deploy_content.py b/src/starboard/build/collect_deploy_content.py
index 3f03b9d..3b4ce71 100755
--- a/src/starboard/build/collect_deploy_content.py
+++ b/src/starboard/build/collect_deploy_content.py
@@ -12,7 +12,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-"""Builds a symlink farm pointing to specified subdirectories of the input dir."""
+"""Builds a symlink farm pointing to specified subdirs of the input dir."""
 
 import argparse
 import logging
@@ -21,7 +21,7 @@
 import sys
 
 import _env  # pylint: disable=unused-import
-import starboard.tools.port_symlink as port_symlink
+from starboard.tools import port_symlink
 from starboard.tools import log_level
 
 # The name of an environment variable that when set to |'1'|, signals to us that
@@ -60,6 +60,7 @@
     raise RuntimeError('Content is %d levels deep (max allowed is %d): %s' %
                        (depth, max_depth, deepest_file))
 
+
 def _CopyTree(src_path, dst_path):
   """Copy tree with a safeguard for windows long path (>260).
 
@@ -74,6 +75,7 @@
       dst_path = prefix + dst_path
   shutil.copytree(src_path, dst_path)
 
+
 def main(argv):
   parser = argparse.ArgumentParser()
   parser.add_argument(
diff --git a/src/starboard/build/install/install_target.gni b/src/starboard/build/install/install_target.gni
index aa7e715..e072622 100644
--- a/src/starboard/build/install/install_target.gni
+++ b/src/starboard/build/install/install_target.gni
@@ -15,8 +15,10 @@
 template("install_target") {
   if (invoker.type == "executable") {
     install_subdir = "bin"
+    source_name = invoker.installable_target_name
   } else if (invoker.type == "shared_library") {
     install_subdir = "lib"
+    source_name = "lib${invoker.installable_target_name}.so"
   } else {
     assert(false, "You can only install an executable or shared library.")
   }
@@ -29,7 +31,7 @@
                            ])
     deps = [ ":$installable_target_name" ]
 
-    sources = [ "$root_out_dir/$installable_target_name" ]
+    sources = [ "$root_out_dir/$source_name" ]
     outputs = [ "$root_out_dir/install/$install_subdir/{{source_file_part}}" ]
   }
 
diff --git a/src/starboard/doc/evergreen/cobalt_evergreen_overview.md b/src/starboard/doc/evergreen/cobalt_evergreen_overview.md
index 51130f1..001f324 100644
--- a/src/starboard/doc/evergreen/cobalt_evergreen_overview.md
+++ b/src/starboard/doc/evergreen/cobalt_evergreen_overview.md
@@ -503,16 +503,17 @@
 
 ### Fonts
 The system font directory `kSbSystemPathFontDirectory` should be configured to
-point to the `standard` (23MB) or the `limited` (3.1MB) cobalt font packages. An
-easy way to do that is to use the `kSbSystemPathContentDirectory` to contain
-the system font directory and setting the `cobalt_font_package` to `standard` or
-`limited` in your port.
+point to either the system fonts on the device or the Cobalt `standard` (23MB)
+or the Cobalt `limited` (3.1MB) font packages. An easy way to use the Cobalt
+fonts is to set `kSbSystemPathFontDirectory` to point to
+`kSbSystemPathContentDirectory/fonts` and configure `cobalt_font_package` to
+`standard` or `limited` in your port.
 
 Cobalt Evergreen (built by Google), will by default use the `empty` font
 package to minimize storage requirements. A separate
 `cobalt_font_package` variable is set to `empty` in the Evergreen platform.
 
-On Raspberry Pi this is:
+On Raspberry Pi the Cobalt fonts are configured the following way:
 
 `empty` set of fonts under:
 ```
diff --git a/src/starboard/elf_loader/elf_header_test.cc b/src/starboard/elf_loader/elf_header_test.cc
index a00805b..cb03d42 100644
--- a/src/starboard/elf_loader/elf_header_test.cc
+++ b/src/starboard/elf_loader/elf_header_test.cc
@@ -14,6 +14,8 @@
 
 #include "starboard/elf_loader/elf_header.h"
 
+#include <string>
+
 #include "starboard/common/scoped_ptr.h"
 #include "starboard/elf_loader/file.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -30,7 +32,10 @@
  public:
   DummyFile(const char* buffer, int size) : buffer_(buffer), size_(size) {}
 
-  bool Open(const char* name) { return true; }
+  bool Open(const char* name) {
+    name_ = name;
+    return true;
+  }
   bool ReadFromOffset(int64_t offset, char* buffer, int size) {
     SB_LOG(INFO) << "ReadFromOffset";
     if (offset != 0) {
@@ -46,9 +51,12 @@
   }
   void Close() {}
 
+  const std::string& GetName() { return name_; }
+
  private:
   const char* buffer_;
   int size_;
+  std::string name_;
 };
 
 class ElfHeaderTest : public ::testing::Test {
diff --git a/src/starboard/elf_loader/elf_loader_impl.cc b/src/starboard/elf_loader/elf_loader_impl.cc
index 7445332..cf392a9 100644
--- a/src/starboard/elf_loader/elf_loader_impl.cc
+++ b/src/starboard/elf_loader/elf_loader_impl.cc
@@ -34,8 +34,7 @@
   if (s.size() < suffix.size()) {
     return false;
   }
-  return strcmp(s.c_str() + (s.size() - suffix.size()),
-                            suffix.c_str()) == 0;
+  return strcmp(s.c_str() + (s.size() - suffix.size()), suffix.c_str()) == 0;
 }
 
 }  // namespace
@@ -68,7 +67,18 @@
 
   SB_DLOG(INFO) << "Loaded ELF header";
 
-  program_table_.reset(new ProgramTable());
+  const auto* memory_mapped_file_extension =
+      reinterpret_cast<const CobaltExtensionMemoryMappedFileApi*>(
+          SbSystemGetExtension(kCobaltExtensionMemoryMappedFileName));
+  if (memory_mapped_file_extension &&
+      strcmp(memory_mapped_file_extension->name,
+             kCobaltExtensionMemoryMappedFileName) == 0 &&
+      memory_mapped_file_extension->version >= 1) {
+    program_table_.reset(new ProgramTable(memory_mapped_file_extension));
+  } else {
+    program_table_.reset(new ProgramTable(nullptr));
+  }
+
   program_table_->LoadProgramHeader(elf_header_loader_->GetHeader(),
                                     elf_file_.get());
 
diff --git a/src/starboard/elf_loader/file.h b/src/starboard/elf_loader/file.h
index ad9b701..0fd4a3d 100644
--- a/src/starboard/elf_loader/file.h
+++ b/src/starboard/elf_loader/file.h
@@ -15,6 +15,8 @@
 #ifndef STARBOARD_ELF_LOADER_FILE_H_
 #define STARBOARD_ELF_LOADER_FILE_H_
 
+#include <string>
+
 #include "starboard/types.h"
 
 namespace starboard {
@@ -35,6 +37,9 @@
   // Closes the underlying file.
   virtual void Close() = 0;
 
+  // Returns the name of the file.
+  virtual const std::string& GetName() = 0;
+
   virtual ~File() {}
 };
 
diff --git a/src/starboard/elf_loader/file_impl.cc b/src/starboard/elf_loader/file_impl.cc
index 94ee465..951db5f 100644
--- a/src/starboard/elf_loader/file_impl.cc
+++ b/src/starboard/elf_loader/file_impl.cc
@@ -39,6 +39,7 @@
 
 bool FileImpl::Open(const char* name) {
   SB_DLOG(INFO) << "Loading: " << name;
+  name_ = name;
   file_ = SbFileOpen(name, kSbFileOpenOnly | kSbFileRead, NULL, NULL);
   if (!file_) {
     return false;
@@ -72,5 +73,9 @@
   }
 }
 
+const std::string& FileImpl::GetName() {
+  return name_;
+}
+
 }  // namespace elf_loader
 }  // namespace starboard
diff --git a/src/starboard/elf_loader/file_impl.h b/src/starboard/elf_loader/file_impl.h
index ebd1c92..a6a30bd 100644
--- a/src/starboard/elf_loader/file_impl.h
+++ b/src/starboard/elf_loader/file_impl.h
@@ -16,6 +16,9 @@
 #define STARBOARD_ELF_LOADER_FILE_IMPL_H_
 
 #include "starboard/elf_loader/file.h"
+
+#include <string>
+
 #include "starboard/file.h"
 
 namespace starboard {
@@ -29,9 +32,11 @@
   bool Open(const char* name) override;
   bool ReadFromOffset(int64_t offset, char* buffer, int size) override;
   void Close() override;
+  const std::string& GetName() override;
 
  protected:
   SbFile file_;
+  std::string name_;
 
   FileImpl(const FileImpl&) = delete;
   void operator=(const FileImpl&) = delete;
diff --git a/src/starboard/elf_loader/program_table.cc b/src/starboard/elf_loader/program_table.cc
index 2684338..61d823c 100644
--- a/src/starboard/elf_loader/program_table.cc
+++ b/src/starboard/elf_loader/program_table.cc
@@ -35,14 +35,16 @@
 namespace starboard {
 namespace elf_loader {
 
-ProgramTable::ProgramTable()
+ProgramTable::ProgramTable(
+    const CobaltExtensionMemoryMappedFileApi* memory_mapped_file_extension)
     : phdr_num_(0),
       phdr_mmap_(NULL),
       phdr_table_(NULL),
       phdr_size_(0),
       load_start_(NULL),
       load_size_(0),
-      base_memory_address_(0) {}
+      base_memory_address_(0),
+      memory_mapped_file_extension_(memory_mapped_file_extension) {}
 
 bool ProgramTable::LoadProgramHeader(const Ehdr* elf_header, File* elf_file) {
   if (!elf_header) {
@@ -77,39 +79,52 @@
 
   SB_DLOG(INFO) << "page_max - page_min=" << page_max - page_min;
 
-#if SB_API_VERSION >= 12 || SB_HAS(MMAP)
-  phdr_mmap_ =
-      SbMemoryMap(phdr_size_, kSbMemoryMapProtectWrite, "program_header");
-  if (!phdr_mmap_) {
-    SB_LOG(ERROR) << "Failed to allocate memory";
-    return false;
-  }
+  if (memory_mapped_file_extension_) {
+    SB_DLOG(INFO) << "Memory mapped file for the program header";
+    phdr_mmap_ = memory_mapped_file_extension_->MemoryMapFile(
+        NULL, elf_file->GetName().c_str(), kSbMemoryMapProtectRead, page_min,
+        phdr_size_);
+    if (!phdr_mmap_) {
+      SB_LOG(ERROR) << "Failed to memory map the program header";
+      return false;
+    }
 
-  SB_DLOG(INFO) << "Allocated address=" << phdr_mmap_;
-#else
-  SB_CHECK(false);
-#endif
-  if (!elf_file->ReadFromOffset(page_min, reinterpret_cast<char*>(phdr_mmap_),
-                                phdr_size_)) {
-    SB_LOG(ERROR) << "Failed to read program header from file offset: "
-                  << page_min;
-    return false;
-  }
+    SB_DLOG(INFO) << "Allocated address=" << phdr_mmap_;
+  } else {
 #if SB_API_VERSION >= 12 || SB_HAS(MMAP)
-  bool mp_result =
-      SbMemoryProtect(phdr_mmap_, phdr_size_, kSbMemoryMapProtectRead);
-  SB_DLOG(INFO) << "mp_result=" << mp_result;
-  if (!mp_result) {
-    SB_LOG(ERROR) << "Failed to protect program header";
-    return false;
-  }
+    phdr_mmap_ =
+        SbMemoryMap(phdr_size_, kSbMemoryMapProtectWrite, "program_header");
+    if (!phdr_mmap_) {
+      SB_LOG(ERROR) << "Failed to allocate memory";
+      return false;
+    }
+
+    SB_DLOG(INFO) << "Allocated address=" << phdr_mmap_;
 #else
-  SB_CHECK(false);
+    SB_CHECK(false);
 #endif
+    if (!elf_file->ReadFromOffset(page_min, reinterpret_cast<char*>(phdr_mmap_),
+                                  phdr_size_)) {
+      SB_LOG(ERROR) << "Failed to read program header from file offset: "
+                    << page_min;
+      return false;
+    }
+#if SB_API_VERSION >= 12 || SB_HAS(MMAP)
+    bool mp_result =
+        SbMemoryProtect(phdr_mmap_, phdr_size_, kSbMemoryMapProtectRead);
+    SB_DLOG(INFO) << "mp_result=" << mp_result;
+    if (!mp_result) {
+      SB_LOG(ERROR) << "Failed to protect program header";
+      return false;
+    }
+#else
+    SB_CHECK(false);
+#endif
+  }
 
   phdr_table_ = reinterpret_cast<Phdr*>(reinterpret_cast<char*>(phdr_mmap_) +
                                         page_offset);
-
+  SB_DLOG(INFO) << "phdr_table_=" << phdr_table_;
   return true;
 }
 
@@ -186,20 +201,33 @@
       SB_DLOG(INFO) << "segment prot_flags=" << std::hex << prot_flags;
 
       void* seg_addr = reinterpret_cast<void*>(seg_page_start);
-      bool mp_ret =
-          SbMemoryProtect(seg_addr, file_length, kSbMemoryMapProtectWrite);
-      SB_DLOG(INFO) << "segment vaddress=" << seg_addr;
+      bool mp_ret = false;
+      if (memory_mapped_file_extension_) {
+        SB_DLOG(INFO) << "Using Memory Mapped File for Loading the Segment";
+        void* p = memory_mapped_file_extension_->MemoryMapFile(
+            seg_addr, elf_file->GetName().c_str(), kSbMemoryMapProtectRead,
+            file_page_start, file_length);
+        if (!p) {
+          SB_LOG(ERROR) << "Failed to memory map file: " << elf_file->GetName();
+          return false;
+        }
+      } else {
+        SB_DLOG(INFO) << "Not using Memory Mapped Files";
+        mp_ret =
+            SbMemoryProtect(seg_addr, file_length, kSbMemoryMapProtectWrite);
+        SB_DLOG(INFO) << "segment vaddress=" << seg_addr;
 
-      if (!mp_ret) {
-        SB_LOG(ERROR) << "Failed to unprotect segment";
-        return false;
-      }
-      if (!elf_file->ReadFromOffset(file_page_start,
-                                    reinterpret_cast<char*>(seg_addr),
-                                    file_length)) {
-        SB_DLOG(INFO) << "Failed to read segment from file offset: "
-                      << file_page_start;
-        return false;
+        if (!mp_ret) {
+          SB_LOG(ERROR) << "Failed to unprotect segment";
+          return false;
+        }
+        if (!elf_file->ReadFromOffset(file_page_start,
+                                      reinterpret_cast<char*>(seg_addr),
+                                      file_length)) {
+          SB_DLOG(INFO) << "Failed to read segment from file offset: "
+                        << file_page_start;
+          return false;
+        }
       }
       mp_ret = SbMemoryProtect(seg_addr, file_length, prot_flags);
       SB_DLOG(INFO) << "mp_ret=" << mp_ret;
@@ -314,7 +342,7 @@
     SB_DLOG(INFO) << "Reading at vaddr: " << phdr->p_vaddr;
     *dynamic = reinterpret_cast<Dyn*>(base_memory_address_ + phdr->p_vaddr);
     if (dynamic_count) {
-      *dynamic_count = (size_t)(phdr->p_memsz / sizeof(Dyn));
+      *dynamic_count = static_cast<size_t>((phdr->p_memsz / sizeof(Dyn)));
     }
     if (dynamic_flags) {
       *dynamic_flags = phdr->p_flags;
diff --git a/src/starboard/elf_loader/program_table.h b/src/starboard/elf_loader/program_table.h
index 3741002..08f4231 100644
--- a/src/starboard/elf_loader/program_table.h
+++ b/src/starboard/elf_loader/program_table.h
@@ -17,6 +17,7 @@
 
 #include <vector>
 
+#include "cobalt/extension/memory_mapped_file.h"
 #include "starboard/elf_loader/elf.h"
 #include "starboard/elf_loader/file.h"
 
@@ -36,7 +37,8 @@
 
 class ProgramTable {
  public:
-  ProgramTable();
+  explicit ProgramTable(
+      const CobaltExtensionMemoryMappedFileApi* memory_mapped_file_extension);
 
   // Loads the program header.
   bool LoadProgramHeader(const Ehdr* elf_header, File* elf_file);
@@ -90,6 +92,8 @@
   // from the ELF file are offsets from this address.
   Addr base_memory_address_;
 
+  const CobaltExtensionMemoryMappedFileApi* memory_mapped_file_extension_;
+
   ProgramTable(const ProgramTable&) = delete;
   void operator=(const ProgramTable&) = delete;
 };
diff --git a/src/starboard/elf_loader/program_table_test.cc b/src/starboard/elf_loader/program_table_test.cc
index 4e56dd7..3a23711 100644
--- a/src/starboard/elf_loader/program_table_test.cc
+++ b/src/starboard/elf_loader/program_table_test.cc
@@ -14,6 +14,7 @@
 
 #include "starboard/elf_loader/program_table.h"
 
+#include <string>
 #include <vector>
 
 #include "starboard/common/scoped_ptr.h"
@@ -41,7 +42,11 @@
   explicit DummyFile(const std::vector<FileChunk>& file_chunks)
       : file_chunks_(file_chunks), read_index_(0) {}
 
-  bool Open(const char* name) { return true; }
+  bool Open(const char* name) {
+    name_ = name;
+    return true;
+  }
+
   bool ReadFromOffset(int64_t offset, char* buffer, int size) {
     SB_LOG(INFO) << "ReadFromOffset offset=" << offset << " size=" << size
                  << " read_index_=" << read_index_;
@@ -65,17 +70,20 @@
   }
   void Close() {}
 
+  const std::string& GetName() { return name_; }
+
  private:
   int file_offset_;
   const char* buffer_;
   int size_;
   std::vector<FileChunk> file_chunks_;
   int read_index_;
+  std::string name_;
 };
 
 class ProgramTableTest : public ::testing::Test {
  protected:
-  ProgramTableTest() { program_table_.reset(new ProgramTable()); }
+  ProgramTableTest() { program_table_.reset(new ProgramTable(nullptr)); }
   ~ProgramTableTest() {}
 
   void HelperMethod() {}
@@ -136,14 +144,13 @@
 
   char program_table_page[PAGE_SIZE];
   memset(program_table_page, 0, sizeof(program_table_page));
-  memcpy(program_table_page, program_table_data,
-               sizeof(program_table_data));
+  memcpy(program_table_page, program_table_data, sizeof(program_table_data));
 
   char segment_file_data1[2 * PAGE_SIZE];
   char segment_file_data2[3 * PAGE_SIZE];
 
   memcpy(segment_file_data1 + 250, dynamic_table_data,
-               sizeof(dynamic_table_data));
+         sizeof(dynamic_table_data));
 
   std::vector<DummyFile::FileChunk> file_chunks;
   file_chunks.push_back(
diff --git a/src/starboard/evergreen/shared/launcher.py b/src/starboard/evergreen/shared/launcher.py
index 3915278..034d71f 100644
--- a/src/starboard/evergreen/shared/launcher.py
+++ b/src/starboard/evergreen/shared/launcher.py
@@ -236,3 +236,6 @@
 
   def GetDeviceIp(self):
     return self.launcher.GetDeviceIp()
+
+  def GetDeviceOutputPath(self):
+    return self.launcher.GetDeviceOutputPath()
diff --git a/src/starboard/linux/shared/BUILD.gn b/src/starboard/linux/shared/BUILD.gn
index b9d5b3a..c720b16 100644
--- a/src/starboard/linux/shared/BUILD.gn
+++ b/src/starboard/linux/shared/BUILD.gn
@@ -184,6 +184,8 @@
     "//starboard/shared/posix/memory_allocate_aligned_unchecked.cc",
     "//starboard/shared/posix/memory_flush.cc",
     "//starboard/shared/posix/memory_free_aligned.cc",
+    "//starboard/shared/posix/memory_mapped_file.cc",
+    "//starboard/shared/posix/memory_mapped_file.h",
     "//starboard/shared/posix/set_non_blocking_internal.cc",
     "//starboard/shared/posix/socket_accept.cc",
     "//starboard/shared/posix/socket_bind.cc",
@@ -385,6 +387,8 @@
 
   sources += common_player_sources
 
+  sources -= [ "//starboard/shared/starboard/player/player_set_bounds.cc" ]
+
   configs += [
     "//starboard/build/config:starboard_implementation",
     "//third_party/de265_includes",
diff --git a/src/starboard/linux/shared/launcher.py b/src/starboard/linux/shared/launcher.py
index 5cfec50..8888d6d 100644
--- a/src/starboard/linux/shared/launcher.py
+++ b/src/starboard/linux/shared/launcher.py
@@ -197,3 +197,7 @@
   def GetDeviceIp(self):
     """Gets the device IP."""
     return self.device_ip
+
+  def GetDeviceOutputPath(self):
+    """Writable path where test targets can output files"""
+    return "/tmp"
diff --git a/src/starboard/linux/shared/starboard_platform.gypi b/src/starboard/linux/shared/starboard_platform.gypi
index 5387624..fef07e1 100644
--- a/src/starboard/linux/shared/starboard_platform.gypi
+++ b/src/starboard/linux/shared/starboard_platform.gypi
@@ -155,6 +155,8 @@
       '<(DEPTH)/starboard/shared/posix/memory_allocate_aligned_unchecked.cc',
       '<(DEPTH)/starboard/shared/posix/memory_flush.cc',
       '<(DEPTH)/starboard/shared/posix/memory_free_aligned.cc',
+      '<(DEPTH)/starboard/shared/posix/memory_mapped_file.cc',
+      '<(DEPTH)/starboard/shared/posix/memory_mapped_file.h',
       '<(DEPTH)/starboard/shared/posix/set_non_blocking_internal.cc',
       '<(DEPTH)/starboard/shared/posix/socket_accept.cc',
       '<(DEPTH)/starboard/shared/posix/socket_bind.cc',
diff --git a/src/starboard/linux/shared/system_get_extensions.cc b/src/starboard/linux/shared/system_get_extensions.cc
index 5c7ac86..3411d93 100644
--- a/src/starboard/linux/shared/system_get_extensions.cc
+++ b/src/starboard/linux/shared/system_get_extensions.cc
@@ -16,7 +16,9 @@
 
 #include "cobalt/extension/configuration.h"
 #include "cobalt/extension/crash_handler.h"
+#include "cobalt/extension/memory_mapped_file.h"
 #include "starboard/common/string.h"
+#include "starboard/shared/posix/memory_mapped_file.h"
 #include "starboard/shared/starboard/crash_handler.h"
 #if SB_IS(EVERGREEN_COMPATIBLE)
 #include "starboard/elf_loader/evergreen_config.h"
@@ -41,5 +43,8 @@
   if (strcmp(name, kCobaltExtensionCrashHandlerName) == 0) {
     return starboard::common::GetCrashHandlerApi();
   }
+  if (strcmp(name, kCobaltExtensionMemoryMappedFileName) == 0) {
+    return starboard::shared::posix::GetMemoryMappedFileApi();
+  }
   return NULL;
 }
diff --git a/src/starboard/linux/x64x11/BUILD.gn b/src/starboard/linux/x64x11/BUILD.gn
index c443ead..ad6b13a 100644
--- a/src/starboard/linux/x64x11/BUILD.gn
+++ b/src/starboard/linux/x64x11/BUILD.gn
@@ -15,13 +15,7 @@
 static_library("starboard_platform") {
   check_includes = false
 
-  sources = [
-    "//starboard/linux/x64x11/main.cc",
-    "//starboard/shared/starboard/player/video_dmp_common.cc",
-    "//starboard/shared/starboard/player/video_dmp_common.h",
-    "//starboard/shared/starboard/player/video_dmp_writer.cc",
-    "//starboard/shared/starboard/player/video_dmp_writer.h",
-  ]
+  sources = [ "//starboard/linux/x64x11/main.cc" ]
 
   public_deps = [
     "//starboard/linux/x64x11/shared:starboard_platform",
diff --git a/src/starboard/linux/x64x11/egl/BUILD.gn b/src/starboard/linux/x64x11/egl/BUILD.gn
index c443ead..ad6b13a 100644
--- a/src/starboard/linux/x64x11/egl/BUILD.gn
+++ b/src/starboard/linux/x64x11/egl/BUILD.gn
@@ -15,13 +15,7 @@
 static_library("starboard_platform") {
   check_includes = false
 
-  sources = [
-    "//starboard/linux/x64x11/main.cc",
-    "//starboard/shared/starboard/player/video_dmp_common.cc",
-    "//starboard/shared/starboard/player/video_dmp_common.h",
-    "//starboard/shared/starboard/player/video_dmp_writer.cc",
-    "//starboard/shared/starboard/player/video_dmp_writer.h",
-  ]
+  sources = [ "//starboard/linux/x64x11/main.cc" ]
 
   public_deps = [
     "//starboard/linux/x64x11/shared:starboard_platform",
diff --git a/src/starboard/linux/x64x11/skia/BUILD.gn b/src/starboard/linux/x64x11/skia/BUILD.gn
index cf08201..024e560 100644
--- a/src/starboard/linux/x64x11/skia/BUILD.gn
+++ b/src/starboard/linux/x64x11/skia/BUILD.gn
@@ -20,10 +20,6 @@
     "//starboard/linux/x64x11/skia/configuration.cc",
     "//starboard/linux/x64x11/skia/configuration.h",
     "//starboard/linux/x64x11/skia/system_get_extensions.cc",
-    "//starboard/shared/starboard/player/video_dmp_common.cc",
-    "//starboard/shared/starboard/player/video_dmp_common.h",
-    "//starboard/shared/starboard/player/video_dmp_writer.cc",
-    "//starboard/shared/starboard/player/video_dmp_writer.h",
   ]
 
   public_deps = [
diff --git a/src/starboard/loader_app/loader_app.cc b/src/starboard/loader_app/loader_app.cc
index c1834af..2fdce8f 100644
--- a/src/starboard/loader_app/loader_app.cc
+++ b/src/starboard/loader_app/loader_app.cc
@@ -14,6 +14,7 @@
 
 #include <vector>
 
+#include "cobalt/version.h"
 #include "starboard/common/log.h"
 #include "starboard/common/string.h"
 #include "starboard/configuration.h"
@@ -165,10 +166,25 @@
     const starboard::shared::starboard::CommandLine command_line(
         data->argument_count, const_cast<const char**>(data->argument_values));
 
+    if (command_line.HasSwitch(starboard::loader_app::kLoaderAppVersion)) {
+      std::string versiong_msg = "Loader app version: ";
+      versiong_msg += COBALT_VERSION;
+      versiong_msg += "\n";
+      SbLogRaw(versiong_msg.c_str());
+    }
+
     bool is_evergreen_lite =
         command_line.HasSwitch(starboard::loader_app::kEvergreenLite);
     SB_LOG(INFO) << "is_evergreen_lite=" << is_evergreen_lite;
 
+#if SB_API_VERSION >= 12
+    if (command_line.HasSwitch(starboard::loader_app::kShowSABI)) {
+      std::string sabi = "SABI=";
+      sabi += SB_SABI_JSON_ID;
+      SbLogRaw(sabi.c_str());
+    }
+#endif
+
     std::string alternative_content =
         command_line.GetSwitchValue(starboard::loader_app::kContent);
     SB_LOG(INFO) << "alternative_content=" << alternative_content;
diff --git a/src/starboard/loader_app/loader_app_switches.cc b/src/starboard/loader_app/loader_app_switches.cc
index 36b6f8f..7758dea 100644
--- a/src/starboard/loader_app/loader_app_switches.cc
+++ b/src/starboard/loader_app/loader_app_switches.cc
@@ -20,6 +20,8 @@
 const char kContent[] = "content";
 const char kURL[] = "url";
 const char kEvergreenLite[] = "evergreen_lite";
+const char kLoaderAppVersion[] = "loader_app_version";
+const char kShowSABI[] = "show_sabi";
 
 }  // namespace loader_app
 }  // namespace starboard
diff --git a/src/starboard/loader_app/loader_app_switches.h b/src/starboard/loader_app/loader_app_switches.h
index 45cbf01..22030c5 100644
--- a/src/starboard/loader_app/loader_app_switches.h
+++ b/src/starboard/loader_app/loader_app_switches.h
@@ -32,6 +32,12 @@
 // Run Evergreen Lite by loading the system image and disabling the updater.
 extern const char kEvergreenLite[];
 
+// Print the loader_app version on the command line.
+extern const char kLoaderAppVersion[];
+
+// Print the loader_app Starboard ABI string on the command line.
+extern const char kShowSABI[];
+
 }  // namespace loader_app
 }  // namespace starboard
 
diff --git a/src/starboard/nplb/audio_sink_destroy_test.cc b/src/starboard/nplb/audio_sink_destroy_test.cc
index 81adf21..e90a3d1 100644
--- a/src/starboard/nplb/audio_sink_destroy_test.cc
+++ b/src/starboard/nplb/audio_sink_destroy_test.cc
@@ -18,7 +18,7 @@
 namespace starboard {
 namespace nplb {
 
-TEST(SbAudioSinkCreateTest, DestroyInvalidAudioSink) {
+TEST(SbAudioSinkDestroyTest, DestroyInvalidAudioSink) {
   SbAudioSinkDestroy(kSbAudioSinkInvalid);
 }
 
diff --git a/src/starboard/nplb/media_buffer_test.cc b/src/starboard/nplb/media_buffer_test.cc
index 66640dd..10599ce 100644
--- a/src/starboard/nplb/media_buffer_test.cc
+++ b/src/starboard/nplb/media_buffer_test.cc
@@ -12,7 +12,12 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include <cmath>
+#include <random>
+#include <vector>
+
 #include "starboard/media.h"
+#include "starboard/memory.h"
 #include "starboard/nplb/performance_helpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -38,8 +43,7 @@
     kSbMediaVideoCodecNone,
 
     kSbMediaVideoCodecH264,   kSbMediaVideoCodecH265, kSbMediaVideoCodecMpeg2,
-    kSbMediaVideoCodecTheora, kSbMediaVideoCodecVc1,
-    kSbMediaVideoCodecAv1,
+    kSbMediaVideoCodecTheora, kSbMediaVideoCodecVc1,  kSbMediaVideoCodecAv1,
     kSbMediaVideoCodecVp8,    kSbMediaVideoCodecVp9,
 };
 
@@ -47,6 +51,37 @@
     kSbMediaTypeAudio, kSbMediaTypeVideo,
 };
 
+// Minimum audio and video budgets required by the 2020 Youtube Software
+// Requirements.
+constexpr int kMinAudioBudget = 5 * 1024 * 1024;
+constexpr int kMinVideoBudget = 30 * 1024 * 1024;
+
+std::vector<void*> TryToAllocateMemory(int size,
+                                       int allocation_unit,
+                                       int alignment) {
+  int total_allocated = 0;
+  std::vector<void*> allocated_ptrs;
+  if (allocation_unit != 0) {
+    allocated_ptrs.reserve(std::ceil(size / allocation_unit));
+  }
+  while (total_allocated < size) {
+    // When |allocation_unit| == 0, randomly allocate a size between 100k -
+    // 500k.
+    int allocation_increment = allocation_unit != 0
+                                   ? allocation_unit
+                                   : (std::rand() % 500 + 100) * 1024;
+    void* allocated_memory =
+        SbMemoryAllocateAligned(alignment, allocation_increment);
+    EXPECT_NE(allocated_memory, nullptr);
+    if (!allocated_memory) {
+      return allocated_ptrs;
+    }
+    allocated_ptrs.push_back(allocated_memory);
+    total_allocated += allocation_increment;
+  }
+  return allocated_ptrs;
+}
+
 }  // namespace
 
 TEST(SbMediaBufferTest, VideoCodecs) {
@@ -83,28 +118,60 @@
 TEST(SbMediaBufferTest, Alignment) {
   for (auto type : kMediaTypes) {
     int alignment = SbMediaGetBufferAlignment(type);
-    // TODO: This currently accepts 0 or a power of 2. We should disallow 0 here
-    // when we change the default value to be 1 instead of 0.
-    EXPECT_GE(alignment, 0);
+    EXPECT_GE(alignment, 1);
     EXPECT_EQ(alignment & (alignment - 1), 0)
         << "Alignment must always be a power of 2";
   }
 }
 
 TEST(SbMediaBufferTest, AllocationUnit) {
-  // TODO: impose more bounds.
   EXPECT_GE(SbMediaGetBufferAllocationUnit(), 0);
+
+  if (SbMediaGetBufferAllocationUnit() != 0) {
+    EXPECT_GE(SbMediaGetBufferAllocationUnit(), 64 * 1024);
+  }
+
+  int allocation_unit = SbMediaGetBufferAllocationUnit();
+  std::vector<void*> allocated_ptrs;
+  int initial_buffer_capacity = SbMediaGetInitialBufferCapacity();
+  if (initial_buffer_capacity > 0) {
+    allocated_ptrs =
+        TryToAllocateMemory(initial_buffer_capacity, allocation_unit, 1);
+  }
+
+  if (!HasNonfatalFailure()) {
+    for (SbMediaType type : kMediaTypes) {
+      int alignment = SbMediaGetBufferAlignment(type);
+      EXPECT_EQ(alignment & (alignment - 1), 0)
+          << "Alignment must always be a power of 2";
+      if (HasNonfatalFailure()) {
+        break;
+      }
+      int media_budget = type == SbMediaType::kSbMediaTypeAudio
+                             ? kMinAudioBudget
+                             : kMinVideoBudget;
+      std::vector<void*> media_buffer_allocated_memory =
+          TryToAllocateMemory(media_budget, allocation_unit, alignment);
+      allocated_ptrs.insert(allocated_ptrs.end(),
+                            media_buffer_allocated_memory.begin(),
+                            media_buffer_allocated_memory.end());
+      if (HasNonfatalFailure()) {
+        break;
+      }
+    }
+  }
+
+  for (void* ptr : allocated_ptrs) {
+    SbMemoryFreeAligned(ptr);
+  }
 }
 
 TEST(SbMediaBufferTest, AudioBudget) {
-  // TODO: refine this lower bound.
-  const int kMinAudioBudget = 1 * 1024 * 1024;
-  EXPECT_GT(SbMediaGetAudioBufferBudget(), kMinAudioBudget);
+  EXPECT_GE(SbMediaGetAudioBufferBudget(), kMinAudioBudget);
 }
 
 TEST(SbMediaBufferTest, GarbageCollectionDurationThreshold) {
-  // TODO: impose reasonable bounds here.
-  int kMinGarbageCollectionDurationThreshold = 10 * kSbTimeSecond;
+  int kMinGarbageCollectionDurationThreshold = 30 * kSbTimeSecond;
   int kMaxGarbageCollectionDurationThreshold = 240 * kSbTimeSecond;
   int threshold = SbMediaGetBufferGarbageCollectionDurationThreshold();
   EXPECT_GE(threshold, kMinGarbageCollectionDurationThreshold);
@@ -116,7 +183,9 @@
 }
 
 TEST(SbMediaBufferTest, MaxCapacity) {
-  // TODO: set a reasonable upper bound.
+  // TODO: Limit EXPECT statements to only codecs and resolutions that are
+  // supported by the platform. If unsupported, still call
+  // SbMediaGetMaxBufferCapacity() to ensure there isn't a crash.
   for (auto resolution : kVideoResolutions) {
     for (auto bits_per_pixel : kBitsPerPixelValues) {
       for (auto codec : kVideoCodecs) {
@@ -178,12 +247,10 @@
 }
 
 TEST(SbMediaBufferTest, VideoBudget) {
-  // TODO: refine this lower bound.
-  const int kMinVideoBudget = 1 * 1024 * 1024;
   for (auto codec : kVideoCodecs) {
     for (auto resolution : kVideoResolutions) {
       for (auto bits_per_pixel : kBitsPerPixelValues) {
-        EXPECT_GT(SbMediaGetVideoBufferBudget(codec, resolution[0],
+        EXPECT_GE(SbMediaGetVideoBufferBudget(codec, resolution[0],
                                               resolution[1], bits_per_pixel),
                   kMinVideoBudget);
       }
diff --git a/src/starboard/raspi/shared/BUILD.gn b/src/starboard/raspi/shared/BUILD.gn
index 3828973..2cc3d1c 100644
--- a/src/starboard/raspi/shared/BUILD.gn
+++ b/src/starboard/raspi/shared/BUILD.gn
@@ -375,6 +375,17 @@
 
   sources += common_player_sources
 
+  if (sb_api_version == 12) {
+    sources += [
+      "//starboard/shared/stub/speech_recognizer_cancel.cc",
+      "//starboard/shared/stub/speech_recognizer_create.cc",
+      "//starboard/shared/stub/speech_recognizer_destroy.cc",
+      "//starboard/shared/stub/speech_recognizer_is_supported.cc",
+      "//starboard/shared/stub/speech_recognizer_start.cc",
+      "//starboard/shared/stub/speech_recognizer_stop.cc",
+    ]
+  }
+
   configs += [
     "//starboard/build/config:pedantic_warnings",
     "//starboard/build/config:starboard_implementation",
diff --git a/src/starboard/raspi/shared/launcher.py b/src/starboard/raspi/shared/launcher.py
index 14e11e1..4617abc 100644
--- a/src/starboard/raspi/shared/launcher.py
+++ b/src/starboard/raspi/shared/launcher.py
@@ -365,3 +365,7 @@
   def GetDeviceIp(self):
     """Gets the device IP."""
     return self.device_id
+
+  def GetDeviceOutputPath(self):
+    """Writable path where test targets can output files"""
+    return '/tmp'
diff --git a/src/starboard/shared/dlmalloc/page_internal.h b/src/starboard/shared/dlmalloc/page_internal.h
index b4df31f..e72fd75 100644
--- a/src/starboard/shared/dlmalloc/page_internal.h
+++ b/src/starboard/shared/dlmalloc/page_internal.h
@@ -19,6 +19,7 @@
 #ifndef STARBOARD_SHARED_DLMALLOC_PAGE_INTERNAL_H_
 #define STARBOARD_SHARED_DLMALLOC_PAGE_INTERNAL_H_
 
+#include "starboard/memory.h"
 #include "starboard/shared/internal_only.h"
 #include "starboard/types.h"
 
@@ -115,6 +116,17 @@
 // allocated by dlmalloc isn't counted twice.
 void* SbPageMapUntracked(size_t size_bytes, int flags, const char* name);
 
+// Memory maps a file to the specified |addr| starting with |file_offset| and
+// mapping |size| bytes. The |addr| should be reserved before calling. If
+// NULL |addr| is passed a new memory block would be allocated and the address
+// returned. The file_offset must be a multiple of |kSbMemoryPageSize|.
+// On error returns NULL.
+void* SbPageMapFile(void* addr,
+                    const char* path,
+                    SbMemoryMapFlags flags,
+                    int64_t file_offset,
+                    int64_t size);
+
 // Unmap |size_bytes| of physical pages starting from |virtual_address|,
 // returning true on success. After this, [virtual_address, virtual_address +
 // size_bytes) will not be read/writable. SbUnmap() can unmap multiple
diff --git a/src/starboard/shared/libdav1d/dav1d_video_decoder.cc b/src/starboard/shared/libdav1d/dav1d_video_decoder.cc
index ad5ffc5..80ce0d5 100644
--- a/src/starboard/shared/libdav1d/dav1d_video_decoder.cc
+++ b/src/starboard/shared/libdav1d/dav1d_video_decoder.cc
@@ -227,7 +227,7 @@
   Dav1dSettings dav1d_settings{0};
   dav1d_default_settings(&dav1d_settings);
   // TODO: Verify this setting is optimal.
-  dav1d_settings.n_frame_threads = 8;
+  dav1d_settings.n_threads = 8;
 
   Dav1dPicAllocator allocator;
   allocator.cookie = this;  // dav1d refers to context pointers as "cookie".
diff --git a/src/starboard/shared/linux/page_internal.cc b/src/starboard/shared/linux/page_internal.cc
index de2ff6f..e708839 100644
--- a/src/starboard/shared/linux/page_internal.cc
+++ b/src/starboard/shared/linux/page_internal.cc
@@ -17,8 +17,10 @@
 
 #include "starboard/shared/dlmalloc/page_internal.h"
 
+#include <fcntl.h>
 #include <stdio.h>
 #include <sys/mman.h>
+#include <unistd.h>
 
 #include "starboard/atomic.h"
 #include "starboard/common/log.h"
@@ -86,6 +88,38 @@
   return mem;
 }
 
+void* SbPageMapFile(void* addr,
+                    const char* path,
+                    SbMemoryMapFlags flags,
+                    int64_t file_offset,
+                    int64_t size) {
+  int fd = open(path, O_RDONLY);
+  if (fd == -1) {
+    return nullptr;
+  }
+
+  void* p = nullptr;
+  if (addr != nullptr) {
+    p = mmap(addr, size, SbMemoryMapFlagsToMmapProtect(flags),
+             MAP_PRIVATE | MAP_FIXED, fd, file_offset);
+    if (p == MAP_FAILED) {
+      close(fd);
+      return nullptr;
+    }
+  } else {
+    p = mmap(addr, size, SbMemoryMapFlagsToMmapProtect(flags), MAP_PRIVATE, fd,
+             file_offset);
+    if (p == MAP_FAILED) {
+      close(fd);
+      return nullptr;
+    }
+  }
+  // It is OK to close the file descriptor as the memory
+  // mapping keeps the file open.
+  close(fd);
+  return p;
+}
+
 bool SbPageUnmap(void* ptr, size_t size_bytes) {
   SbAtomicNoBarrier_Increment(&s_tracked_page_count, -GetPageCount(size_bytes));
   return SbPageUnmapUntracked(ptr, size_bytes);
diff --git a/src/starboard/shared/posix/memory_mapped_file.cc b/src/starboard/shared/posix/memory_mapped_file.cc
new file mode 100644
index 0000000..d9a3dfb
--- /dev/null
+++ b/src/starboard/shared/posix/memory_mapped_file.cc
@@ -0,0 +1,39 @@
+// Copyright 2021 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/shared/posix/memory_mapped_file.h"
+
+#include "cobalt/extension/memory_mapped_file.h"
+#include "starboard/common/log.h"
+#include "starboard/shared/dlmalloc/page_internal.h"
+
+namespace starboard {
+namespace shared {
+namespace posix {
+
+namespace {
+
+const CobaltExtensionMemoryMappedFileApi kMemoryMappedFileApi = {
+    kCobaltExtensionMemoryMappedFileName, 1, &SbPageMapFile,
+};
+
+}  // namespace
+
+const void* GetMemoryMappedFileApi() {
+  return &kMemoryMappedFileApi;
+}
+
+}  // namespace posix
+}  // namespace shared
+}  // namespace starboard
diff --git a/src/starboard/shared/posix/memory_mapped_file.h b/src/starboard/shared/posix/memory_mapped_file.h
new file mode 100644
index 0000000..46e47fe
--- /dev/null
+++ b/src/starboard/shared/posix/memory_mapped_file.h
@@ -0,0 +1,28 @@
+// Copyright 2021 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_SHARED_POSIX_MEMORY_MAPPED_FILE_H_
+#define STARBOARD_SHARED_POSIX_MEMORY_MAPPED_FILE_H_
+
+namespace starboard {
+namespace shared {
+namespace posix {
+
+const void* GetMemoryMappedFileApi();
+
+}  // namespace posix
+}  // namespace shared
+}  // namespace starboard
+
+#endif  // STARBOARD_SHARED_POSIX_MEMORY_MAPPED_FILE_H_
diff --git a/src/starboard/shared/starboard/media/avc_util.cc b/src/starboard/shared/starboard/media/avc_util.cc
index aaa677e..81e196b 100644
--- a/src/starboard/shared/starboard/media/avc_util.cc
+++ b/src/starboard/shared/starboard/media/avc_util.cc
@@ -38,8 +38,7 @@
   if (annex_b_data_size < sizeof(kAnnexBHeader)) {
     return false;
   }
-  return memcmp(annex_b_data, kAnnexBHeader, sizeof(kAnnexBHeader)) ==
-         0;
+  return memcmp(annex_b_data, kAnnexBHeader, sizeof(kAnnexBHeader)) == 0;
 }
 
 // UInt8Type can be "uint8_t", or "const uint8_t".
@@ -125,6 +124,26 @@
       << "AVC parameter set NALUs not found.";
 }
 
+std::vector<uint8_t> AvcParameterSets::GetAllSpses() const {
+  std::vector<uint8_t> result;
+  for (const auto& parameter_set : parameter_sets_) {
+    if (parameter_set[4] == kSpsStartCode) {
+      result.insert(result.end(), parameter_set.begin(), parameter_set.end());
+    }
+  }
+  return result;
+}
+
+std::vector<uint8_t> AvcParameterSets::GetAllPpses() const {
+  std::vector<uint8_t> result;
+  for (const auto& parameter_set : parameter_sets_) {
+    if (parameter_set[4] == kPpsStartCode) {
+      result.insert(result.end(), parameter_set.begin(), parameter_set.end());
+    }
+  }
+  return result;
+}
+
 AvcParameterSets AvcParameterSets::ConvertTo(Format new_format) const {
   if (format_ == new_format) {
     return *this;
@@ -204,7 +223,7 @@
     avcc_destination[2] = static_cast<uint8_t>((payload_size & 0xff00) >> 8);
     avcc_destination[3] = static_cast<uint8_t>(payload_size & 0xff);
     memcpy(avcc_destination + kAvccLengthInBytes,
-                 last_source + kAnnexBHeaderSizeInBytes, payload_size);
+           last_source + kAnnexBHeaderSizeInBytes, payload_size);
     avcc_destination += annex_b_source - last_source;
     last_source = annex_b_source;
   }
diff --git a/src/starboard/shared/starboard/media/avc_util.h b/src/starboard/shared/starboard/media/avc_util.h
index c9d7931..7def624 100644
--- a/src/starboard/shared/starboard/media/avc_util.h
+++ b/src/starboard/shared/starboard/media/avc_util.h
@@ -83,6 +83,9 @@
   }
   size_t combined_size_in_bytes() const { return combined_size_in_bytes_; }
 
+  std::vector<uint8_t> GetAllSpses() const;
+  std::vector<uint8_t> GetAllPpses() const;
+
   AvcParameterSets ConvertTo(Format new_format) const;
 
   bool operator==(const AvcParameterSets& that) const;
diff --git a/src/starboard/shared/starboard/media/media_util.cc b/src/starboard/shared/starboard/media/media_util.cc
index ab3db04..786e284 100644
--- a/src/starboard/shared/starboard/media/media_util.cc
+++ b/src/starboard/shared/starboard/media/media_util.cc
@@ -221,7 +221,7 @@
   if (audio_specific_config_size > 0) {
     audio_specific_config_storage.resize(audio_specific_config_size);
     memcpy(audio_specific_config_storage.data(), audio_specific_config,
-                 audio_specific_config_size);
+           audio_specific_config_size);
     audio_specific_config = audio_specific_config_storage.data();
   }
 #if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
@@ -310,6 +310,51 @@
   return true;
 }
 
+bool IsSDRVideo(const char* mime) {
+  SB_DCHECK(mime);
+
+  if (!mime) {
+    SB_LOG(WARNING) << mime << " is empty, assuming sdr video.";
+    return true;
+  }
+
+  MimeType mime_type(mime);
+  if (!mime_type.is_valid()) {
+    SB_LOG(WARNING) << mime << " is not a valid mime type, assuming sdr video.";
+    return true;
+  }
+  const std::vector<std::string> codecs = mime_type.GetCodecs();
+  if (codecs.empty()) {
+    SB_LOG(WARNING) << mime << " contains no codecs, assuming sdr video.";
+    return true;
+  }
+  if (codecs.size() > 1) {
+    SB_LOG(WARNING) << mime
+                    << " contains more than one codecs, assuming sdr video.";
+    return true;
+  }
+
+  SbMediaVideoCodec video_codec;
+  int profile = -1;
+  int level = -1;
+  int bit_depth = 8;
+  SbMediaPrimaryId primary_id = kSbMediaPrimaryIdUnspecified;
+  SbMediaTransferId transfer_id = kSbMediaTransferIdUnspecified;
+  SbMediaMatrixId matrix_id = kSbMediaMatrixIdUnspecified;
+
+  if (!ParseVideoCodec(codecs[0].c_str(), &video_codec, &profile, &level,
+                       &bit_depth, &primary_id, &transfer_id, &matrix_id)) {
+    SB_LOG(WARNING) << "ParseVideoCodec() failed on mime: " << mime
+                    << ", assuming sdr video.";
+    return true;
+  }
+
+  SB_DCHECK(video_codec != kSbMediaVideoCodecNone);
+  // TODO: Consider to consolidate the two IsSDRVideo() implementations by
+  //       calling IsSDRVideo(bit_depth, primary_id, transfer_id, matrix_id).
+  return bit_depth == 8;
+}
+
 SbMediaTransferId GetTransferIdFromString(const std::string& transfer_id) {
   if (transfer_id == "bt709") {
     return kSbMediaTransferIdBt709;
@@ -459,8 +504,7 @@
          left.samples_per_second != right.samples_per_second ||
          left.number_of_channels != right.number_of_channels ||
          left.audio_specific_config_size != right.audio_specific_config_size ||
-         memcmp(left.audio_specific_config,
-                right.audio_specific_config,
+         memcmp(left.audio_specific_config, right.audio_specific_config,
                 left.audio_specific_config_size) != 0;
 }
 
@@ -471,8 +515,7 @@
 
 bool operator==(const SbMediaColorMetadata& metadata_1,
                 const SbMediaColorMetadata& metadata_2) {
-  return memcmp(&metadata_1, &metadata_2,
-                sizeof(SbMediaColorMetadata)) == 0;
+  return memcmp(&metadata_1, &metadata_2, sizeof(SbMediaColorMetadata)) == 0;
 }
 
 bool operator==(const SbMediaVideoSampleInfo& sample_info_1,
@@ -489,7 +532,7 @@
     return false;
   }
   if (strcmp(sample_info_1.max_video_capabilities,
-                         sample_info_2.max_video_capabilities) != 0) {
+             sample_info_2.max_video_capabilities) != 0) {
     return false;
   }
 #endif  // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
diff --git a/src/starboard/shared/starboard/media/media_util.h b/src/starboard/shared/starboard/media/media_util.h
index 3f43cd5..a0ee728 100644
--- a/src/starboard/shared/starboard/media/media_util.h
+++ b/src/starboard/shared/starboard/media/media_util.h
@@ -58,6 +58,7 @@
                 SbMediaPrimaryId primary_id,
                 SbMediaTransferId transfer_id,
                 SbMediaMatrixId matrix_id);
+bool IsSDRVideo(const char* mime);
 
 // Turns |eotf| into value of SbMediaTransferId.  If |eotf| isn't recognized the
 // function returns kSbMediaTransferIdReserved0.
diff --git a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
index 64f94ab..6a4b15e 100644
--- a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
+++ b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
@@ -161,7 +161,7 @@
     player_components_ =
         factory->CreateComponents(creation_parameters, error_message);
     if (!player_components_) {
-      SB_LOG(ERROR) << "Failed to create renderer with error: "
+      SB_LOG(ERROR) << "Failed to create player components with error: "
                     << *error_message;
       return false;
     }
@@ -399,8 +399,7 @@
     // only log when the other members of |bounds| have been changed to avoid
     // spamming the log.
     bounds_.z_index = bounds.z_index;
-    bool bounds_changed =
-        memcmp(&bounds_, &bounds, sizeof(bounds_)) != 0;
+    bool bounds_changed = memcmp(&bounds_, &bounds, sizeof(bounds_)) != 0;
     SB_LOG_IF(INFO, bounds_changed)
         << "Set bounds to "
         << "x: " << bounds.x << ", y: " << bounds.y
diff --git a/src/starboard/tools/abstract_launcher.py b/src/starboard/tools/abstract_launcher.py
index 8a72a2e..85963cb 100644
--- a/src/starboard/tools/abstract_launcher.py
+++ b/src/starboard/tools/abstract_launcher.py
@@ -159,6 +159,11 @@
     """Gets the device IP. Must be implemented in subclasses."""
     pass
 
+  @abc.abstractmethod
+  def GetDeviceOutputPath(self):
+    """Writable path where test targets can output files"""
+    pass
+
   def SupportsSuspendResume(self):
     return False
 
diff --git a/src/starboard/tools/app_launcher_packager.py b/src/starboard/tools/app_launcher_packager.py
index 53ff7d1..37a1e80 100644
--- a/src/starboard/tools/app_launcher_packager.py
+++ b/src/starboard/tools/app_launcher_packager.py
@@ -31,19 +31,18 @@
 import _env  # pylint: disable=unused-import
 from paths import REPOSITORY_ROOT
 from paths import THIRD_PARTY_ROOT
+
 sys.path.append(THIRD_PARTY_ROOT)
-# pylint: disable=g-import-not-at-top,g-bad-import-order
+# pylint: disable=g-import-not-at-top,g-bad-import-order,wrong-import-position
 from starboard.tools import command_line
 from starboard.tools import log_level
 from starboard.tools import port_symlink
 import starboard.tools.platform
 
 # Default python directories to app launcher resources.
-_INCLUDE_FILE_PATTERNS = [
-    ('cobalt', '*.py'),
-    ('starboard', '*.py'),
-    ('starboard/tools', 'platform.py.template')
-]
+_INCLUDE_FILE_PATTERNS = [('cobalt', '*.py'), ('starboard', '*.py'),
+                          ('starboard', '*.pfx'),
+                          ('starboard/tools', 'platform.py.template')]
 
 _INCLUDE_BLACK_BOX_TESTS_PATTERNS = [
     # Black box and web platform tests have non-py assets, so everything
@@ -128,11 +127,11 @@
     # Store posix paths even on Windows so MH Linux hosts can use them.
     # The template has code to re-normalize them when used on Windows hosts.
     platforms_map[p] = platform_path.replace('\\', '/')
-  template = string.Template(
-      open(os.path.join(current_dir, 'platform.py.template')).read())
-  with open(os.path.join(dest_dir, 'platform.py'), 'w+') as f:
-    sub = template.substitute(platforms_map=platforms_map)
-    f.write(sub.encode('utf-8'))
+  with open(os.path.join(current_dir, 'platform.py.template')) as c:
+    template = string.Template(c.read())
+    with open(os.path.join(dest_dir, 'platform.py'), 'w+') as f:
+      sub = template.substitute(platforms_map=platforms_map)
+      f.write(sub.encode('utf-8'))
   logging.info('Finished baking in platform info files.')
 
 
diff --git a/src/starboard/tools/net_args.py b/src/starboard/tools/net_args.py
index b77d658..1948633 100644
--- a/src/starboard/tools/net_args.py
+++ b/src/starboard/tools/net_args.py
@@ -12,37 +12,34 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-
 """Example script for getting the Net Args."""
 
 from __future__ import print_function
 
-import pprint
-
 import argparse
 import socket
 import sys
-import thread
 import time
 import threading
 
+
 # Returns |True| if a connection was made and the NetArg payload was delivered.
 # Example:
 #  TryConnectAndSendNetArgs('1.2.3.4', '1234', ['--argument', '--switch=value'])
 def TryConnectAndSendNetArgs(host, port, arg_list):
   arg_string = '\n'.join(arg_list)
-
   try:
-    server_socket = socket.create_connection((host, port), timeout = .5)
-    result = server_socket.sendall(arg_string)
+    server_socket = socket.create_connection((host, port), timeout=.5)
+    server_socket.sendall(arg_string)
     server_socket.close()
     return True
-  except socket.timeout as err:
+  except socket.timeout:
     return False
-  except socket.error as (err_no, err_str):
-    print(err_no, err_str)
+  except socket.error as e:
+    print(e.errno, e.strerror)
     return False
 
+
 class NetArgsThread(threading.Thread):
   """Threaded version of NetArgs"""
 
@@ -71,32 +68,36 @@
       with self.mutex:
         if self.join_called:
           break
-      connected_and_sent = TryConnectAndSendNetArgs(
-          self.host, self.port, self.arg_list)
+      connected_and_sent = TryConnectAndSendNetArgs(self.host, self.port,
+                                                    self.arg_list)
       if connected_and_sent:
         with self.mutex:
           self.args_sent = True
           break
 
+
 def main(argv):
-  parser = argparse.ArgumentParser(description = 'Connects to the weblog.')
-  parser.add_argument('--host', type=str, required = False,
-                      default = 'localhost',
-                      help = "Example localhost or 1.2.3.4")
-  parser.add_argument('--port', type=int, required = False, default = '49355')
-  parser.add_argument('--arg', type=str, required = True)
+  parser = argparse.ArgumentParser(description='Connects to the weblog.')
+  parser.add_argument(
+      '--host',
+      type=str,
+      required=False,
+      default='localhost',
+      help='Example localhost or 1.2.3.4')
+  parser.add_argument('--port', type=int, required=False, default='49355')
+  parser.add_argument('--arg', type=str, required=True)
   args = parser.parse_args(argv)
 
-  net_args_thread = NetArgsThread(
-          args.host, args.port, [args.arg])
+  net_args_thread = NetArgsThread(args.host, args.port, [args.arg])
 
   while not net_args_thread.ArgsSent():
-    print("Waiting to send arg " + args.arg + " to " + str(args.host) +
-          ":" + str(args.port) + "...")
+    print('Waiting to send arg ' + args.arg + ' to ' + str(args.host) + ':' +
+          str(args.port) + '...')
     time.sleep(.5)
 
-  print("Argument", args.arg, "was sent to", \
-        args.host + ":" + str(args.port))
+  print('Argument', args.arg, 'was sent to', \
+        args.host + ':' + str(args.port))
+
 
 if __name__ == '__main__':
   sys.exit(main(sys.argv[1:]))
diff --git a/src/starboard/tools/net_log.py b/src/starboard/tools/net_log.py
index 0b85cfa..aaa9797 100644
--- a/src/starboard/tools/net_log.py
+++ b/src/starboard/tools/net_log.py
@@ -13,24 +13,24 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-
 """Example script for getting the Net log."""
 
 from __future__ import print_function
 
 import argparse
-import pprint
 import select
 import socket
 import sys
 import time
 import threading
 
+
 class NetLog:
   """
   Uses a non-blocking socket to establish a connection with a
   NetLog and then will allow the log to be fetched.
   """
+
   def __init__(self, host, port):
     self.host = host
     self.port = port
@@ -47,9 +47,9 @@
         self.server_socket = None
       else:
         return log
-    except socket.error as (err_no, err_str):
-      print(__file__ + ": Socket error while reading log:" \
-            + str(err_no) + " - " + str(err_str))
+    except socket.error as e:
+      print(__file__ + ': Socket error while reading log:' \
+            + str(e.errno) + ' - ' + str(e.strerror))
       self.server_socket = None
       return None
 
@@ -64,28 +64,31 @@
       if len(result) == 0:
         return None
       return result
-    except socket.error as (err_no, err_str):
-      if err_no == 10035:  # Data not ready yet.
+    except socket.error as e:
+      if e.errno == 10035:  # Data not ready yet.
         return ''
       else:
         raise
 
   def _TryCreateSocketConnection(self):
     try:
-      print("Waiting for connection to " + str(self.host) + ':' + str(self.port))
+      print('Waiting for connection to ' + str(self.host) + ':' +
+            str(self.port))
 
-      server_socket = socket.create_connection((self.host, self.port), timeout = 1)
+      server_socket = socket.create_connection((self.host, self.port),
+                                               timeout=1)
       server_socket.setblocking(0)
       return server_socket
-    except socket.timeout as err:
+    except socket.timeout:
       return None
     except socket.error as err:
-      print("Error while trying to create socket: " + str(err))
+      print('Error while trying to create socket: ' + str(err))
       return None
 
 
 class NetLogThread(threading.Thread):
   """Threaded version of NetLog"""
+
   def __init__(self, host, port):
     super(NetLogThread, self).__init__()
     self.web_log = NetLog(host, port)
@@ -111,8 +114,9 @@
         with self.log_mutex:
           self.log.extend(new_log)
 
+
 def TestNetLog(host, port):
-  print("Started...")
+  print('Started...')
   web_log = NetLog(host, port)
 
   while True:
@@ -123,11 +127,14 @@
 
 
 def main(argv):
-  parser = argparse.ArgumentParser(description = 'Connects to the weblog.')
-  parser.add_argument('--host', type=str, required = False,
-                      default = 'localhost',
-                      help = "Example localhost or 1.2.3.4")
-  parser.add_argument('--port', type=int, required = False, default = '49353')
+  parser = argparse.ArgumentParser(description='Connects to the weblog.')
+  parser.add_argument(
+      '--host',
+      type=str,
+      required=False,
+      default='localhost',
+      help='Example localhost or 1.2.3.4')
+  parser.add_argument('--port', type=int, required=False, default='49353')
   args = parser.parse_args(argv)
 
   thread = NetLogThread(args.host, args.port)
@@ -136,13 +143,14 @@
     while True:
       print(thread.GetLog(), end='')
       time.sleep(.1)
-  except KeyboardInterrupt as ki:
-    print("\nUser canceled.")
+  except KeyboardInterrupt:
+    print('\nUser canceled.')
     pass
 
-  print("Waiting to join...")
+  print('Waiting to join...')
   thread.join()
   return 0
 
+
 if __name__ == '__main__':
   sys.exit(main(sys.argv[1:]))
diff --git a/src/starboard/tools/testing/test_runner.py b/src/starboard/tools/testing/test_runner.py
index 1ae0133..7a08bd2 100755
--- a/src/starboard/tools/testing/test_runner.py
+++ b/src/starboard/tools/testing/test_runner.py
@@ -190,14 +190,12 @@
           self.launcher.target_name))
       traceback.print_exc(file=sys.stderr)
 
-    self.return_code_lock.acquire()
-    self.return_code = return_code
-    self.return_code_lock.release()
+    with self.return_code_lock:
+      self.return_code = return_code
 
   def GetReturnCode(self):
-    self.return_code_lock.acquire()
-    return_code = self.return_code
-    self.return_code_lock.release()
+    with self.return_code_lock:
+      return_code = self.return_code
     return return_code
 
 
@@ -233,7 +231,8 @@
       self.out_directory = paths.BuildOutputDirectory(self.platform,
                                                       self.config)
     self.coverage_directory = os.path.join(self.out_directory, "coverage")
-    if not self.loader_out_directory and self.loader_platform and self.loader_config:
+    if (not self.loader_out_directory and self.loader_platform and
+        self.loader_config):
       self.loader_out_directory = paths.BuildOutputDirectory(
           self.loader_platform, self.loader_config)
 
@@ -272,13 +271,13 @@
       logging.info(msg)
       if output_file:
         with open(output_file, "wb") as out:
-          p = subprocess.Popen(
+          p = subprocess.Popen(  # pylint: disable=consider-using-with
               cmd_list,
               stdout=out,
               universal_newlines=True,
               cwd=self.out_directory)
       else:
-        p = subprocess.Popen(
+        p = subprocess.Popen(  # pylint: disable=consider-using-with
             cmd_list,
             stderr=subprocess.STDOUT,
             universal_newlines=True,
@@ -401,10 +400,32 @@
     if gtest_filter_value:
       test_params.append("--gtest_filter=" + gtest_filter_value)
 
+    def MakeLauncher():
+      return abstract_launcher.LauncherFactory(
+          self.platform,
+          target_name,
+          self.config,
+          device_id=self.device_id,
+          target_params=test_params,
+          output_file=write_pipe,
+          out_directory=self.out_directory,
+          coverage_directory=self.coverage_directory,
+          env_variables=env,
+          loader_platform=self.loader_platform,
+          loader_config=self.loader_config,
+          loader_out_directory=self.loader_out_directory,
+          launcher_args=self.launcher_args)
+
     if self.log_xml_results:
-      # Log the xml results
-      test_params.append("--gtest_output=xml:log")
-      logging.info("Xml results for this test will be logged.")
+      out_path = MakeLauncher().GetDeviceOutputPath()
+      xml_filename = "{}_testoutput.xml".format(target_name)
+      if out_path:
+        xml_path = os.path.join(out_path, xml_filename)
+      else:
+        xml_path = xml_filename
+      test_params.append("--gtest_output=xml:{}".format(xml_path))
+      logging.info(("Xml results for this test will "
+                    "be logged to '%s'."), xml_path)
     elif self.xml_output_dir:
       # Have gtest create and save a test result xml
       xml_output_subdir = os.path.join(self.xml_output_dir, target_name)
@@ -424,20 +445,9 @@
     if self.dry_run:
       test_params.extend(["--gtest_list_tests"])
 
-    launcher = abstract_launcher.LauncherFactory(
-        self.platform,
-        target_name,
-        self.config,
-        device_id=self.device_id,
-        target_params=test_params,
-        output_file=write_pipe,
-        out_directory=self.out_directory,
-        coverage_directory=self.coverage_directory,
-        env_variables=env,
-        loader_platform=self.loader_platform,
-        loader_config=self.loader_config,
-        loader_out_directory=self.loader_out_directory,
-        launcher_args=self.launcher_args)
+    logging.info("Initializing launcher")
+    launcher = MakeLauncher()
+    logging.info("Launcher initialized")
 
     test_reader = TestLineReader(read_pipe)
     test_launcher = TestLauncher(launcher)
diff --git a/src/testing/gtest/src/gtest.cc b/src/testing/gtest/src/gtest.cc
index 50717b7..e561a3c 100644
--- a/src/testing/gtest/src/gtest.cc
+++ b/src/testing/gtest/src/gtest.cc
@@ -3450,6 +3450,19 @@
   GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter);
 };
 
+#if GTEST_OS_STARBOARD
+void WriteOuputFile(const std::string &output_file, const std::string &data) {
+  SbFileError err;
+  starboard::ScopedFile cache_file(
+      output_file.c_str(), kSbFileCreateAlways | kSbFileWrite, NULL, &err);
+  // TODO: Change to SB_DCHECK once all platforms are verified
+  if(err != kSbFileOk) {
+    SB_LOG(ERROR) << "Unable to open file " << output_file << " for XML output";
+  }
+  cache_file.WriteAll(data.c_str(), static_cast<int>(data.size()));
+}
+#endif
+
 // Creates a new XmlUnitTestResultPrinter.
 XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file)
     : output_file_(output_file) {
@@ -3458,6 +3471,10 @@
     fflush(stderr);
     exit(EXIT_FAILURE);
   }
+#if GTEST_OS_STARBOARD
+  // Ensure file contents get reset between runs, to avoid stale results
+  WriteOuputFile(output_file,"");
+#endif
 }
 
 // Called after the unit test ends.
@@ -3466,10 +3483,8 @@
 #if GTEST_OS_STARBOARD
   std::stringstream stream;
   PrintXmlUnitTest(&stream, unit_test);
-  starboard::ScopedFile cache_file(
-      output_file_.c_str(), kSbFileCreateAlways | kSbFileWrite, NULL, NULL);
-  cache_file.WriteAll(StringStreamToString(&stream).c_str(),
-                      static_cast<int>(StringStreamToString(&stream).size()));
+
+  WriteOuputFile(output_file_, StringStreamToString(&stream));
 #else
   FILE* xmlout = NULL;
   FilePath output_file(output_file_);
diff --git a/src/third_party/libdav1d/include/dav1d/common.h b/src/third_party/libdav1d/include/dav1d/common.h
index b55e939..d81775d 100644
--- a/src/third_party/libdav1d/include/dav1d/common.h
+++ b/src/third_party/libdav1d/include/dav1d/common.h
@@ -1,81 +1,81 @@
-/*
- * Copyright © 2018, VideoLAN and dav1d authors
- * Copyright © 2018, Two Orioles, LLC
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef DAV1D_COMMON_H
-#define DAV1D_COMMON_H
-
-#include <errno.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#ifndef DAV1D_API
-    #if defined _WIN32
-      #if defined DAV1D_BUILDING_DLL
-        #define DAV1D_API __declspec(dllexport)
-      #else
-        #define DAV1D_API
-      #endif
-    #else
-      #if __GNUC__ >= 4
-        #define DAV1D_API __attribute__ ((visibility ("default")))
-      #else
-        #define DAV1D_API
-      #endif
-    #endif
-#endif
-
-#if EPERM > 0
-#define DAV1D_ERR(e) (-(e)) ///< Negate POSIX error code.
-#else
-#define DAV1D_ERR(e) (e)
-#endif
-
-/**
- * A reference-counted object wrapper for a user-configurable pointer.
- */
-typedef struct Dav1dUserData {
-    const uint8_t *data; ///< data pointer
-    struct Dav1dRef *ref; ///< allocation origin
-} Dav1dUserData;
-
-/**
- * Input packet metadata which are copied from the input data used to
- * decode each image into the matching structure of the output image
- * returned back to the user. Since these are metadata fields, they
- * can be used for other purposes than the documented ones, they will
- * still be passed from input data to output picture without being
- * used internally.
- */
-typedef struct Dav1dDataProps {
-    int64_t timestamp; ///< container timestamp of input data, INT64_MIN if unknown (default)
-    int64_t duration; ///< container duration of input data, 0 if unknown (default)
-    int64_t offset; ///< stream offset of input data, -1 if unknown (default)
-    size_t size; ///< packet size, default Dav1dData.sz
-    struct Dav1dUserData user_data; ///< user-configurable data, default NULL members
-} Dav1dDataProps;
-
-#endif /* DAV1D_COMMON_H */
+/*

+ * Copyright © 2018, VideoLAN and dav1d authors

+ * Copyright © 2018, Two Orioles, LLC

+ * All rights reserved.

+ *

+ * Redistribution and use in source and binary forms, with or without

+ * modification, are permitted provided that the following conditions are met:

+ *

+ * 1. Redistributions of source code must retain the above copyright notice, this

+ *    list of conditions and the following disclaimer.

+ *

+ * 2. Redistributions in binary form must reproduce the above copyright notice,

+ *    this list of conditions and the following disclaimer in the documentation

+ *    and/or other materials provided with the distribution.

+ *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND

+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED

+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE

+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR

+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;

+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND

+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS

+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ */

+

+#ifndef DAV1D_COMMON_H

+#define DAV1D_COMMON_H

+

+#include <errno.h>

+#include <stddef.h>

+#include <stdint.h>

+

+#ifndef DAV1D_API

+    #if defined _WIN32

+      #if defined DAV1D_BUILDING_DLL

+        #define DAV1D_API __declspec(dllexport)

+      #else

+        #define DAV1D_API

+      #endif

+    #else

+      #if __GNUC__ >= 4

+        #define DAV1D_API __attribute__ ((visibility ("default")))

+      #else

+        #define DAV1D_API

+      #endif

+    #endif

+#endif

+

+#if EPERM > 0

+#define DAV1D_ERR(e) (-(e)) ///< Negate POSIX error code.

+#else

+#define DAV1D_ERR(e) (e)

+#endif

+

+/**

+ * A reference-counted object wrapper for a user-configurable pointer.

+ */

+typedef struct Dav1dUserData {

+    const uint8_t *data; ///< data pointer

+    struct Dav1dRef *ref; ///< allocation origin

+} Dav1dUserData;

+

+/**

+ * Input packet metadata which are copied from the input data used to

+ * decode each image into the matching structure of the output image

+ * returned back to the user. Since these are metadata fields, they

+ * can be used for other purposes than the documented ones, they will

+ * still be passed from input data to output picture without being

+ * used internally.

+ */

+typedef struct Dav1dDataProps {

+    int64_t timestamp; ///< container timestamp of input data, INT64_MIN if unknown (default)

+    int64_t duration; ///< container duration of input data, 0 if unknown (default)

+    int64_t offset; ///< stream offset of input data, -1 if unknown (default)

+    size_t size; ///< packet size, default Dav1dData.sz

+    struct Dav1dUserData user_data; ///< user-configurable data, default NULL members

+} Dav1dDataProps;

+

+#endif /* DAV1D_COMMON_H */

diff --git a/src/third_party/libdav1d/include/dav1d/data.h b/src/third_party/libdav1d/include/dav1d/data.h
index f945a04..b532474 100644
--- a/src/third_party/libdav1d/include/dav1d/data.h
+++ b/src/third_party/libdav1d/include/dav1d/data.h
@@ -1,109 +1,109 @@
-/*
- * Copyright © 2018, VideoLAN and dav1d authors
- * Copyright © 2018, Two Orioles, LLC
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef DAV1D_DATA_H
-#define DAV1D_DATA_H
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "common.h"
-
-typedef struct Dav1dData {
-    const uint8_t *data; ///< data pointer
-    size_t sz; ///< data size
-    struct Dav1dRef *ref; ///< allocation origin
-    Dav1dDataProps m; ///< user provided metadata passed to the output picture
-} Dav1dData;
-
-/**
- * Allocate data.
- *
- * @param data Input context.
- * @param   sz Size of the data that should be allocated.
- *
- * @return Pointer to the allocated buffer on success. NULL on error.
- */
-DAV1D_API uint8_t * dav1d_data_create(Dav1dData *data, size_t sz);
-
-/**
- * Wrap an existing data array.
- *
- * @param          data Input context.
- * @param           buf The data to be wrapped.
- * @param            sz Size of the data.
- * @param free_callback Function to be called when we release our last
- *                      reference to this data. In this callback, $buf will be
- *                      the $buf argument to this function, and $cookie will
- *                      be the $cookie input argument to this function.
- * @param        cookie Opaque parameter passed to free_callback().
- *
- * @return 0 on success. A negative DAV1D_ERR value on error.
- */
-DAV1D_API int dav1d_data_wrap(Dav1dData *data, const uint8_t *buf, size_t sz,
-                              void (*free_callback)(const uint8_t *buf, void *cookie),
-                              void *cookie);
-
-/**
- * Wrap a user-provided data pointer into a reference counted object.
- *
- * data->m.user_data field will initialized to wrap the provided $user_data
- * pointer.
- *
- * $free_callback will be called on the same thread that released the last
- * reference. If frame threading is used, make sure $free_callback is
- * thread-safe.
- *
- * @param          data Input context.
- * @param     user_data The user data to be wrapped.
- * @param free_callback Function to be called when we release our last
- *                      reference to this data. In this callback, $user_data
- *                      will be the $user_data argument to this function, and
- *                      $cookie will be the $cookie input argument to this
- *                      function.
- * @param        cookie Opaque parameter passed to $free_callback.
- *
- * @return 0 on success. A negative DAV1D_ERR value on error.
- */
-DAV1D_API int dav1d_data_wrap_user_data(Dav1dData *data,
-                                        const uint8_t *user_data,
-                                        void (*free_callback)(const uint8_t *user_data,
-                                                              void *cookie),
-                                        void *cookie);
-
-/**
- * Free the data reference.
- *
- * The reference count for data->m.user_data will be decremented (if it has been
- * initialized with dav1d_data_wrap_user_data). The $data object will be memset
- * to 0.
- *
- * @param data Input context.
- */
-DAV1D_API void dav1d_data_unref(Dav1dData *data);
-
-#endif /* DAV1D_DATA_H */
+/*

+ * Copyright © 2018, VideoLAN and dav1d authors

+ * Copyright © 2018, Two Orioles, LLC

+ * All rights reserved.

+ *

+ * Redistribution and use in source and binary forms, with or without

+ * modification, are permitted provided that the following conditions are met:

+ *

+ * 1. Redistributions of source code must retain the above copyright notice, this

+ *    list of conditions and the following disclaimer.

+ *

+ * 2. Redistributions in binary form must reproduce the above copyright notice,

+ *    this list of conditions and the following disclaimer in the documentation

+ *    and/or other materials provided with the distribution.

+ *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND

+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED

+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE

+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR

+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;

+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND

+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS

+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ */

+

+#ifndef DAV1D_DATA_H

+#define DAV1D_DATA_H

+

+#include <stddef.h>

+#include <stdint.h>

+

+#include "common.h"

+

+typedef struct Dav1dData {

+    const uint8_t *data; ///< data pointer

+    size_t sz; ///< data size

+    struct Dav1dRef *ref; ///< allocation origin

+    Dav1dDataProps m; ///< user provided metadata passed to the output picture

+} Dav1dData;

+

+/**

+ * Allocate data.

+ *

+ * @param data Input context.

+ * @param   sz Size of the data that should be allocated.

+ *

+ * @return Pointer to the allocated buffer on success. NULL on error.

+ */

+DAV1D_API uint8_t * dav1d_data_create(Dav1dData *data, size_t sz);

+

+/**

+ * Wrap an existing data array.

+ *

+ * @param          data Input context.

+ * @param           buf The data to be wrapped.

+ * @param            sz Size of the data.

+ * @param free_callback Function to be called when we release our last

+ *                      reference to this data. In this callback, $buf will be

+ *                      the $buf argument to this function, and $cookie will

+ *                      be the $cookie input argument to this function.

+ * @param        cookie Opaque parameter passed to free_callback().

+ *

+ * @return 0 on success. A negative DAV1D_ERR value on error.

+ */

+DAV1D_API int dav1d_data_wrap(Dav1dData *data, const uint8_t *buf, size_t sz,

+                              void (*free_callback)(const uint8_t *buf, void *cookie),

+                              void *cookie);

+

+/**

+ * Wrap a user-provided data pointer into a reference counted object.

+ *

+ * data->m.user_data field will initialized to wrap the provided $user_data

+ * pointer.

+ *

+ * $free_callback will be called on the same thread that released the last

+ * reference. If frame threading is used, make sure $free_callback is

+ * thread-safe.

+ *

+ * @param          data Input context.

+ * @param     user_data The user data to be wrapped.

+ * @param free_callback Function to be called when we release our last

+ *                      reference to this data. In this callback, $user_data

+ *                      will be the $user_data argument to this function, and

+ *                      $cookie will be the $cookie input argument to this

+ *                      function.

+ * @param        cookie Opaque parameter passed to $free_callback.

+ *

+ * @return 0 on success. A negative DAV1D_ERR value on error.

+ */

+DAV1D_API int dav1d_data_wrap_user_data(Dav1dData *data,

+                                        const uint8_t *user_data,

+                                        void (*free_callback)(const uint8_t *user_data,

+                                                              void *cookie),

+                                        void *cookie);

+

+/**

+ * Free the data reference.

+ *

+ * The reference count for data->m.user_data will be decremented (if it has been

+ * initialized with dav1d_data_wrap_user_data). The $data object will be memset

+ * to 0.

+ *

+ * @param data Input context.

+ */

+DAV1D_API void dav1d_data_unref(Dav1dData *data);

+

+#endif /* DAV1D_DATA_H */

diff --git a/src/third_party/libdav1d/include/dav1d/dav1d.h b/src/third_party/libdav1d/include/dav1d/dav1d.h
index 76558cf..8d3d97c 100644
--- a/src/third_party/libdav1d/include/dav1d/dav1d.h
+++ b/src/third_party/libdav1d/include/dav1d/dav1d.h
@@ -1,210 +1,244 @@
-/*
- * Copyright © 2018, VideoLAN and dav1d authors
- * Copyright © 2018, Two Orioles, LLC
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef DAV1D_H
-#define DAV1D_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <errno.h>
-#include <stdarg.h>
-
-#include "common.h"
-#include "picture.h"
-#include "data.h"
-
-#define DAV1D_API_VERSION_MAJOR 3
-#define DAV1D_API_VERSION_MINOR 1
-#define DAV1D_API_VERSION_PATCH 0
-
-typedef struct Dav1dContext Dav1dContext;
-typedef struct Dav1dRef Dav1dRef;
-
-#define DAV1D_MAX_FRAME_THREADS 256
-#define DAV1D_MAX_TILE_THREADS 64
-
-typedef struct Dav1dLogger {
-    void *cookie; ///< Custom data to pass to the callback.
-    /**
-     * Logger callback. Default prints to stderr. May be NULL to disable logging.
-     *
-     * @param cookie Custom pointer passed to all calls.
-     * @param format The vprintf compatible format string.
-     * @param     ap List of arguments referenced by the format string.
-     */
-    void (*callback)(void *cookie, const char *format, va_list ap);
-} Dav1dLogger;
-
-typedef struct Dav1dSettings {
-    int n_frame_threads;
-    int n_tile_threads;
-    int apply_grain;
-    int operating_point; ///< select an operating point for scalable AV1 bitstreams (0 - 31)
-    int all_layers; ///< output all spatial layers of a scalable AV1 biststream
-    unsigned frame_size_limit; ///< maximum frame size, in pixels (0 = unlimited)
-    uint8_t reserved[32]; ///< reserved for future use
-    Dav1dPicAllocator allocator;
-    Dav1dLogger logger;
-} Dav1dSettings;
-
-/**
- * Get library version.
- */
-DAV1D_API const char *dav1d_version(void);
-
-/**
- * Initialize settings to default values.
- *
- * @param s Input settings context.
- */
-DAV1D_API void dav1d_default_settings(Dav1dSettings *s);
-
-/**
- * Allocate and open a decoder instance.
- *
- * @param c_out The decoder instance to open. *c_out will be set to the
- *              allocated context.
- * @param     s Input settings context.
- *
- * @note The context must be freed using dav1d_close() when decoding is
- *       finished.
- *
- * @return 0 on success, or < 0 (a negative DAV1D_ERR code) on error.
- */
-DAV1D_API int dav1d_open(Dav1dContext **c_out, const Dav1dSettings *s);
-
-/**
- * Parse a Sequence Header OBU from bitstream data.
- *
- * @param out Output Sequence Header.
- * @param buf The data to be parser.
- * @param sz  Size of the data.
- *
- * @return 0 on success, or < 0 (a negative DAV1D_ERR code) on error.
- *
- * @note It is safe to feed this function data containing other OBUs than a
- *       Sequence Header, as they will simply be ignored. If there is more than
- *       one Sequence Header OBU present, only the last will be returned.
- */
-DAV1D_API int dav1d_parse_sequence_header(Dav1dSequenceHeader *out,
-                                          const uint8_t *buf, const size_t sz);
-
-/**
- * Feed bitstream data to the decoder.
- *
- * @param   c Input decoder instance.
- * @param  in Input bitstream data. On success, ownership of the reference is
- *            passed to the library.
- *
- * @return
- *         0: Success, and the data was consumed.
- *  DAV1D_ERR(EAGAIN): The data can't be consumed. dav1d_get_picture() should
- *                     be called to get one or more frames before the function
- *                     can consume new data.
- *  other negative DAV1D_ERR codes: Error during decoding or because of invalid
- *                                  passed-in arguments.
- */
-DAV1D_API int dav1d_send_data(Dav1dContext *c, Dav1dData *in);
-
-/**
- * Return a decoded picture.
- *
- * @param   c Input decoder instance.
- * @param out Output frame. The caller assumes ownership of the returned
- *            reference.
- *
- * @return
- *         0: Success, and a frame is returned.
- *  DAV1D_ERR(EAGAIN): Not enough data to output a frame. dav1d_send_data()
- *                     should be called with new input.
- *  other negative DAV1D_ERR codes: Error during decoding or because of invalid
- *                                  passed-in arguments.
- *
- * @note To drain buffered frames from the decoder (i.e. on end of stream),
- *       call this function until it returns DAV1D_ERR(EAGAIN).
- *
- * @code{.c}
- *  Dav1dData data = { 0 };
- *  Dav1dPicture p = { 0 };
- *  int res;
- *
- *  read_data(&data);
- *  do {
- *      res = dav1d_send_data(c, &data);
- *      // Keep going even if the function can't consume the current data
- *         packet. It eventually will after one or more frames have been
- *         returned in this loop.
- *      if (res < 0 && res != DAV1D_ERR(EAGAIN))
- *          free_and_abort();
- *      res = dav1d_get_picture(c, &p);
- *      if (res < 0) {
- *          if (res != DAV1D_ERR(EAGAIN))
- *              free_and_abort();
- *      } else
- *          output_and_unref_picture(&p);
- *  // Stay in the loop as long as there's data to consume.
- *  } while (data.sz || read_data(&data) == SUCCESS);
- *
- *  // Handle EOS by draining all buffered frames.
- *  do {
- *      res = dav1d_get_picture(c, &p);
- *      if (res < 0) {
- *          if (res != DAV1D_ERR(EAGAIN))
- *              free_and_abort();
- *      } else
- *          output_and_unref_picture(&p);
- *  } while (res == 0);
- * @endcode
- */
-DAV1D_API int dav1d_get_picture(Dav1dContext *c, Dav1dPicture *out);
-
-/**
- * Close a decoder instance and free all associated memory.
- *
- * @param c_out The decoder instance to close. *c_out will be set to NULL.
- */
-DAV1D_API void dav1d_close(Dav1dContext **c_out);
-
-/**
- * Flush all delayed frames in decoder and clear internal decoder state,
- * to be used when seeking.
- *
- * @param c Input decoder instance.
- *
- * @note Decoding will start only after a valid sequence header OBU is
- *       delivered to dav1d_send_data().
- *
- */
-DAV1D_API void dav1d_flush(Dav1dContext *c);
-
-# ifdef __cplusplus
-}
-# endif
-
-#endif /* DAV1D_H */
+/*

+ * Copyright © 2018-2021, VideoLAN and dav1d authors

+ * Copyright © 2018, Two Orioles, LLC

+ * All rights reserved.

+ *

+ * Redistribution and use in source and binary forms, with or without

+ * modification, are permitted provided that the following conditions are met:

+ *

+ * 1. Redistributions of source code must retain the above copyright notice, this

+ *    list of conditions and the following disclaimer.

+ *

+ * 2. Redistributions in binary form must reproduce the above copyright notice,

+ *    this list of conditions and the following disclaimer in the documentation

+ *    and/or other materials provided with the distribution.

+ *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND

+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED

+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE

+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR

+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;

+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND

+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS

+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ */

+

+#ifndef DAV1D_H

+#define DAV1D_H

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+#include <errno.h>

+#include <stdarg.h>

+

+#include "common.h"

+#include "picture.h"

+#include "data.h"

+

+#define DAV1D_API_VERSION_MAJOR 3

+#define DAV1D_API_VERSION_MINOR 1

+#define DAV1D_API_VERSION_PATCH 0

+

+typedef struct Dav1dContext Dav1dContext;

+typedef struct Dav1dRef Dav1dRef;

+

+#define DAV1D_MAX_THREADS 256

+#define DAV1D_MAX_FRAME_DELAY 256

+

+typedef struct Dav1dLogger {

+    void *cookie; ///< Custom data to pass to the callback.

+    /**

+     * Logger callback. May be NULL to disable logging.

+     *

+     * @param cookie Custom pointer passed to all calls.

+     * @param format The vprintf compatible format string.

+     * @param     ap List of arguments referenced by the format string.

+     */

+    void (*callback)(void *cookie, const char *format, va_list ap);

+} Dav1dLogger;

+

+typedef struct Dav1dSettings {

+    int n_threads; ///< number of threads (0 = auto)

+    int max_frame_delay; ///< Set to 1 for low-latency decoding (0 = auto)

+    int apply_grain;

+    int operating_point; ///< select an operating point for scalable AV1 bitstreams (0 - 31)

+    int all_layers; ///< output all spatial layers of a scalable AV1 biststream

+    unsigned frame_size_limit; ///< maximum frame size, in pixels (0 = unlimited)

+    Dav1dPicAllocator allocator; ///< Picture allocator callback.

+    Dav1dLogger logger; ///< Logger callback.

+    uint8_t reserved[32]; ///< reserved for future use

+} Dav1dSettings;

+

+/**

+ * Get library version.

+ */

+DAV1D_API const char *dav1d_version(void);

+

+/**

+ * Initialize settings to default values.

+ *

+ * @param s Input settings context.

+ */

+DAV1D_API void dav1d_default_settings(Dav1dSettings *s);

+

+/**

+ * Allocate and open a decoder instance.

+ *

+ * @param c_out The decoder instance to open. *c_out will be set to the

+ *              allocated context.

+ * @param     s Input settings context.

+ *

+ * @note The context must be freed using dav1d_close() when decoding is

+ *       finished.

+ *

+ * @return 0 on success, or < 0 (a negative DAV1D_ERR code) on error.

+ */

+DAV1D_API int dav1d_open(Dav1dContext **c_out, const Dav1dSettings *s);

+

+/**

+ * Parse a Sequence Header OBU from bitstream data.

+ *

+ * @param out Output Sequence Header.

+ * @param buf The data to be parser.

+ * @param sz  Size of the data.

+ *

+ * @return

+ *                  0: Success, and out is filled with the parsed Sequence Header

+ *                     OBU parameters.

+ *  DAV1D_ERR(ENOENT): No Sequence Header OBUs were found in the buffer.

+ *  other negative DAV1D_ERR codes: Invalid data in the buffer, invalid passed-in

+ *                                  arguments, and other errors during parsing.

+ *

+ * @note It is safe to feed this function data containing other OBUs than a

+ *       Sequence Header, as they will simply be ignored. If there is more than

+ *       one Sequence Header OBU present, only the last will be returned.

+ */

+DAV1D_API int dav1d_parse_sequence_header(Dav1dSequenceHeader *out,

+                                          const uint8_t *buf, const size_t sz);

+

+/**

+ * Feed bitstream data to the decoder.

+ *

+ * @param   c Input decoder instance.

+ * @param  in Input bitstream data. On success, ownership of the reference is

+ *            passed to the library.

+ *

+ * @return

+ *         0: Success, and the data was consumed.

+ *  DAV1D_ERR(EAGAIN): The data can't be consumed. dav1d_get_picture() should

+ *                     be called to get one or more frames before the function

+ *                     can consume new data.

+ *  other negative DAV1D_ERR codes: Error during decoding or because of invalid

+ *                                  passed-in arguments.

+ */

+DAV1D_API int dav1d_send_data(Dav1dContext *c, Dav1dData *in);

+

+/**

+ * Return a decoded picture.

+ *

+ * @param   c Input decoder instance.

+ * @param out Output frame. The caller assumes ownership of the returned

+ *            reference.

+ *

+ * @return

+ *         0: Success, and a frame is returned.

+ *  DAV1D_ERR(EAGAIN): Not enough data to output a frame. dav1d_send_data()

+ *                     should be called with new input.

+ *  other negative DAV1D_ERR codes: Error during decoding or because of invalid

+ *                                  passed-in arguments.

+ *

+ * @note To drain buffered frames from the decoder (i.e. on end of stream),

+ *       call this function until it returns DAV1D_ERR(EAGAIN).

+ *

+ * @code{.c}

+ *  Dav1dData data = { 0 };

+ *  Dav1dPicture p = { 0 };

+ *  int res;

+ *

+ *  read_data(&data);

+ *  do {

+ *      res = dav1d_send_data(c, &data);

+ *      // Keep going even if the function can't consume the current data

+ *         packet. It eventually will after one or more frames have been

+ *         returned in this loop.

+ *      if (res < 0 && res != DAV1D_ERR(EAGAIN))

+ *          free_and_abort();

+ *      res = dav1d_get_picture(c, &p);

+ *      if (res < 0) {

+ *          if (res != DAV1D_ERR(EAGAIN))

+ *              free_and_abort();

+ *      } else

+ *          output_and_unref_picture(&p);

+ *  // Stay in the loop as long as there's data to consume.

+ *  } while (data.sz || read_data(&data) == SUCCESS);

+ *

+ *  // Handle EOS by draining all buffered frames.

+ *  do {

+ *      res = dav1d_get_picture(c, &p);

+ *      if (res < 0) {

+ *          if (res != DAV1D_ERR(EAGAIN))

+ *              free_and_abort();

+ *      } else

+ *          output_and_unref_picture(&p);

+ *  } while (res == 0);

+ * @endcode

+ */

+DAV1D_API int dav1d_get_picture(Dav1dContext *c, Dav1dPicture *out);

+

+/**

+ * Close a decoder instance and free all associated memory.

+ *

+ * @param c_out The decoder instance to close. *c_out will be set to NULL.

+ */

+DAV1D_API void dav1d_close(Dav1dContext **c_out);

+

+/**

+ * Flush all delayed frames in decoder and clear internal decoder state,

+ * to be used when seeking.

+ *

+ * @param c Input decoder instance.

+ *

+ * @note Decoding will start only after a valid sequence header OBU is

+ *       delivered to dav1d_send_data().

+ *

+ */

+DAV1D_API void dav1d_flush(Dav1dContext *c);

+

+enum Dav1dEventFlags {

+    /**

+     * The last returned picture contains a reference to a new Sequence Header,

+     * either because it's the start of a new coded sequence, or the decoder was

+     * flushed before it was generated.

+     */

+    DAV1D_EVENT_FLAG_NEW_SEQUENCE =       1 << 0,

+    /**

+     * The last returned picture contains a reference to a Sequence Header with

+     * new operating parameters information for the current coded sequence.

+     */

+    DAV1D_EVENT_FLAG_NEW_OP_PARAMS_INFO = 1 << 1,

+};

+

+/**

+ * Fetch a combination of DAV1D_EVENT_FLAG_* event flags generated by the decoding

+ * process.

+ *

+ * @param c Input decoder instance.

+ * @param flags Where to write the flags.

+ *

+ * @return 0 on success, or < 0 (a negative DAV1D_ERR code) on error.

+ *

+ * @note Calling this function will clear all the event flags currently stored in

+ *       the decoder.

+ *

+ */

+DAV1D_API int dav1d_get_event_flags(Dav1dContext *c, enum Dav1dEventFlags *flags);

+

+# ifdef __cplusplus

+}

+# endif

+

+#endif /* DAV1D_H */

diff --git a/src/third_party/libdav1d/include/dav1d/headers.h b/src/third_party/libdav1d/include/dav1d/headers.h
index 4e3bf9e..7ec6cef 100644
--- a/src/third_party/libdav1d/include/dav1d/headers.h
+++ b/src/third_party/libdav1d/include/dav1d/headers.h
@@ -1,430 +1,435 @@
-/*
- * Copyright © 2018, VideoLAN and dav1d authors
- * Copyright © 2018, Two Orioles, LLC
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef DAV1D_HEADERS_H
-#define DAV1D_HEADERS_H
-
-#include <stddef.h>
-
-// Constants from Section 3. "Symbols and abbreviated terms"
-#define DAV1D_MAX_CDEF_STRENGTHS 8
-#define DAV1D_MAX_OPERATING_POINTS 32
-#define DAV1D_MAX_TILE_COLS 64
-#define DAV1D_MAX_TILE_ROWS 64
-#define DAV1D_MAX_SEGMENTS 8
-#define DAV1D_NUM_REF_FRAMES 8
-#define DAV1D_PRIMARY_REF_NONE 7
-#define DAV1D_REFS_PER_FRAME 7
-#define DAV1D_TOTAL_REFS_PER_FRAME (DAV1D_REFS_PER_FRAME + 1)
-
-enum Dav1dObuType {
-    DAV1D_OBU_SEQ_HDR   = 1,
-    DAV1D_OBU_TD        = 2,
-    DAV1D_OBU_FRAME_HDR = 3,
-    DAV1D_OBU_TILE_GRP  = 4,
-    DAV1D_OBU_METADATA  = 5,
-    DAV1D_OBU_FRAME     = 6,
-    DAV1D_OBU_REDUNDANT_FRAME_HDR = 7,
-    DAV1D_OBU_PADDING   = 15,
-};
-
-enum Dav1dTxfmMode {
-    DAV1D_TX_4X4_ONLY,
-    DAV1D_TX_LARGEST,
-    DAV1D_TX_SWITCHABLE,
-    DAV1D_N_TX_MODES,
-};
-
-enum Dav1dFilterMode {
-    DAV1D_FILTER_8TAP_REGULAR,
-    DAV1D_FILTER_8TAP_SMOOTH,
-    DAV1D_FILTER_8TAP_SHARP,
-    DAV1D_N_SWITCHABLE_FILTERS,
-    DAV1D_FILTER_BILINEAR = DAV1D_N_SWITCHABLE_FILTERS,
-    DAV1D_N_FILTERS,
-    DAV1D_FILTER_SWITCHABLE = DAV1D_N_FILTERS,
-};
-
-enum Dav1dAdaptiveBoolean {
-    DAV1D_OFF = 0,
-    DAV1D_ON = 1,
-    DAV1D_ADAPTIVE = 2,
-};
-
-enum Dav1dRestorationType {
-    DAV1D_RESTORATION_NONE,
-    DAV1D_RESTORATION_SWITCHABLE,
-    DAV1D_RESTORATION_WIENER,
-    DAV1D_RESTORATION_SGRPROJ,
-};
-
-enum Dav1dWarpedMotionType {
-    DAV1D_WM_TYPE_IDENTITY,
-    DAV1D_WM_TYPE_TRANSLATION,
-    DAV1D_WM_TYPE_ROT_ZOOM,
-    DAV1D_WM_TYPE_AFFINE,
-};
-
-typedef struct Dav1dWarpedMotionParams {
-    enum Dav1dWarpedMotionType type;
-    int32_t matrix[6];
-    union {
-        struct {
-            int16_t alpha, beta, gamma, delta;
-        };
-        int16_t abcd[4];
-    };
-} Dav1dWarpedMotionParams;
-
-enum Dav1dPixelLayout {
-    DAV1D_PIXEL_LAYOUT_I400, ///< monochrome
-    DAV1D_PIXEL_LAYOUT_I420, ///< 4:2:0 planar
-    DAV1D_PIXEL_LAYOUT_I422, ///< 4:2:2 planar
-    DAV1D_PIXEL_LAYOUT_I444, ///< 4:4:4 planar
-};
-
-enum Dav1dFrameType {
-    DAV1D_FRAME_TYPE_KEY = 0,    ///< Key Intra frame
-    DAV1D_FRAME_TYPE_INTER = 1,  ///< Inter frame
-    DAV1D_FRAME_TYPE_INTRA = 2,  ///< Non key Intra frame
-    DAV1D_FRAME_TYPE_SWITCH = 3, ///< Switch Inter frame
-};
-
-enum Dav1dColorPrimaries {
-    DAV1D_COLOR_PRI_BT709 = 1,
-    DAV1D_COLOR_PRI_UNKNOWN = 2,
-    DAV1D_COLOR_PRI_BT470M = 4,
-    DAV1D_COLOR_PRI_BT470BG = 5,
-    DAV1D_COLOR_PRI_BT601 = 6,
-    DAV1D_COLOR_PRI_SMPTE240 = 7,
-    DAV1D_COLOR_PRI_FILM = 8,
-    DAV1D_COLOR_PRI_BT2020 = 9,
-    DAV1D_COLOR_PRI_XYZ = 10,
-    DAV1D_COLOR_PRI_SMPTE431 = 11,
-    DAV1D_COLOR_PRI_SMPTE432 = 12,
-    DAV1D_COLOR_PRI_EBU3213 = 22,
-};
-
-enum Dav1dTransferCharacteristics {
-    DAV1D_TRC_BT709 = 1,
-    DAV1D_TRC_UNKNOWN = 2,
-    DAV1D_TRC_BT470M = 4,
-    DAV1D_TRC_BT470BG = 5,
-    DAV1D_TRC_BT601 = 6,
-    DAV1D_TRC_SMPTE240 = 7,
-    DAV1D_TRC_LINEAR = 8,
-    DAV1D_TRC_LOG100 = 9,         ///< logarithmic (100:1 range)
-    DAV1D_TRC_LOG100_SQRT10 = 10, ///< lograithmic (100*sqrt(10):1 range)
-    DAV1D_TRC_IEC61966 = 11,
-    DAV1D_TRC_BT1361 = 12,
-    DAV1D_TRC_SRGB = 13,
-    DAV1D_TRC_BT2020_10BIT = 14,
-    DAV1D_TRC_BT2020_12BIT = 15,
-    DAV1D_TRC_SMPTE2084 = 16,     ///< PQ
-    DAV1D_TRC_SMPTE428 = 17,
-    DAV1D_TRC_HLG = 18,           ///< hybrid log/gamma (BT.2100 / ARIB STD-B67)
-};
-
-enum Dav1dMatrixCoefficients {
-    DAV1D_MC_IDENTITY = 0,
-    DAV1D_MC_BT709 = 1,
-    DAV1D_MC_UNKNOWN = 2,
-    DAV1D_MC_FCC = 4,
-    DAV1D_MC_BT470BG = 5,
-    DAV1D_MC_BT601 = 6,
-    DAV1D_MC_SMPTE240 = 7,
-    DAV1D_MC_SMPTE_YCGCO = 8,
-    DAV1D_MC_BT2020_NCL = 9,
-    DAV1D_MC_BT2020_CL = 10,
-    DAV1D_MC_SMPTE2085 = 11,
-    DAV1D_MC_CHROMAT_NCL = 12, ///< Chromaticity-derived
-    DAV1D_MC_CHROMAT_CL = 13,
-    DAV1D_MC_ICTCP = 14,
-};
-
-enum Dav1dChromaSamplePosition {
-    DAV1D_CHR_UNKNOWN = 0,
-    DAV1D_CHR_VERTICAL = 1,  ///< Horizontally co-located with luma(0, 0)
-                           ///< sample, between two vertical samples
-    DAV1D_CHR_COLOCATED = 2, ///< Co-located with luma(0, 0) sample
-};
-
-typedef struct Dav1dContentLightLevel {
-    int max_content_light_level;
-    int max_frame_average_light_level;
-} Dav1dContentLightLevel;
-
-typedef struct Dav1dMasteringDisplay {
-    ///< 0.16 fixed point
-    uint16_t primaries[3][2];
-    ///< 0.16 fixed point
-    uint16_t white_point[2];
-    ///< 24.8 fixed point
-    uint32_t max_luminance;
-    ///< 18.14 fixed point
-    uint32_t min_luminance;
-} Dav1dMasteringDisplay;
-
-typedef struct Dav1dITUTT35 {
-    uint8_t  country_code;
-    uint8_t  country_code_extension_byte;
-    size_t   payload_size;
-    uint8_t *payload;
-} Dav1dITUTT35;
-
-typedef struct Dav1dSequenceHeader {
-    /**
-     * Stream profile, 0 for 8-10 bits/component 4:2:0 or monochrome;
-     * 1 for 8-10 bits/component 4:4:4; 2 for 4:2:2 at any bits/component,
-     * or 12 bits/component at any chroma subsampling.
-     */
-    int profile;
-    /**
-     * Maximum dimensions for this stream. In non-scalable streams, these
-     * are often the actual dimensions of the stream, although that is not
-     * a normative requirement.
-     */
-    int max_width, max_height;
-    enum Dav1dPixelLayout layout; ///< format of the picture
-    enum Dav1dColorPrimaries pri; ///< color primaries (av1)
-    enum Dav1dTransferCharacteristics trc; ///< transfer characteristics (av1)
-    enum Dav1dMatrixCoefficients mtrx; ///< matrix coefficients (av1)
-    enum Dav1dChromaSamplePosition chr; ///< chroma sample position (av1)
-    /**
-     * 0, 1 and 2 mean 8, 10 or 12 bits/component, respectively. This is not
-     * exactly the same as 'hbd' from the spec; the spec's hbd distinguishes
-     * between 8 (0) and 10-12 (1) bits/component, and another element
-     * (twelve_bit) to distinguish between 10 and 12 bits/component. To get
-     * the spec's hbd, use !!our_hbd, and to get twelve_bit, use hbd == 2.
-     */
-    int hbd;
-    /**
-     * Pixel data uses JPEG pixel range ([0,255] for 8bits) instead of
-     * MPEG pixel range ([16,235] for 8bits luma, [16,240] for 8bits chroma).
-     */
-    int color_range;
-
-    int num_operating_points;
-    struct Dav1dSequenceHeaderOperatingPoint {
-        int major_level, minor_level;
-        int initial_display_delay;
-        int idc;
-        int tier;
-        int decoder_model_param_present;
-        int display_model_param_present;
-    } operating_points[DAV1D_MAX_OPERATING_POINTS];
-
-    int still_picture;
-    int reduced_still_picture_header;
-    int timing_info_present;
-    int num_units_in_tick;
-    int time_scale;
-    int equal_picture_interval;
-    unsigned num_ticks_per_picture;
-    int decoder_model_info_present;
-    int encoder_decoder_buffer_delay_length;
-    int num_units_in_decoding_tick;
-    int buffer_removal_delay_length;
-    int frame_presentation_delay_length;
-    int display_model_info_present;
-    int width_n_bits, height_n_bits;
-    int frame_id_numbers_present;
-    int delta_frame_id_n_bits;
-    int frame_id_n_bits;
-    int sb128;
-    int filter_intra;
-    int intra_edge_filter;
-    int inter_intra;
-    int masked_compound;
-    int warped_motion;
-    int dual_filter;
-    int order_hint;
-    int jnt_comp;
-    int ref_frame_mvs;
-    enum Dav1dAdaptiveBoolean screen_content_tools;
-    enum Dav1dAdaptiveBoolean force_integer_mv;
-    int order_hint_n_bits;
-    int super_res;
-    int cdef;
-    int restoration;
-    int ss_hor, ss_ver, monochrome;
-    int color_description_present;
-    int separate_uv_delta_q;
-    int film_grain_present;
-
-    // Dav1dSequenceHeaders of the same sequence are required to be
-    // bit-identical until this offset. See 7.5 "Ordering of OBUs":
-    //   Within a particular coded video sequence, the contents of
-    //   sequence_header_obu must be bit-identical each time the
-    //   sequence header appears except for the contents of
-    //   operating_parameters_info.
-    struct Dav1dSequenceHeaderOperatingParameterInfo {
-        int decoder_buffer_delay;
-        int encoder_buffer_delay;
-        int low_delay_mode;
-    } operating_parameter_info[DAV1D_MAX_OPERATING_POINTS];
-} Dav1dSequenceHeader;
-
-typedef struct Dav1dSegmentationData {
-    int delta_q;
-    int delta_lf_y_v, delta_lf_y_h, delta_lf_u, delta_lf_v;
-    int ref;
-    int skip;
-    int globalmv;
-} Dav1dSegmentationData;
-
-typedef struct Dav1dSegmentationDataSet {
-    Dav1dSegmentationData d[DAV1D_MAX_SEGMENTS];
-    int preskip;
-    int last_active_segid;
-} Dav1dSegmentationDataSet;
-
-typedef struct Dav1dLoopfilterModeRefDeltas {
-    int mode_delta[2 /* is_zeromv */];
-    int ref_delta[DAV1D_TOTAL_REFS_PER_FRAME];
-} Dav1dLoopfilterModeRefDeltas;
-
-typedef struct Dav1dFilmGrainData {
-    unsigned seed;
-    int num_y_points;
-    uint8_t y_points[14][2 /* value, scaling */];
-    int chroma_scaling_from_luma;
-    int num_uv_points[2];
-    uint8_t uv_points[2][10][2 /* value, scaling */];
-    int scaling_shift;
-    int ar_coeff_lag;
-    int8_t ar_coeffs_y[24];
-    int8_t ar_coeffs_uv[2][25];
-    int ar_coeff_shift;
-    int grain_scale_shift;
-    int uv_mult[2];
-    int uv_luma_mult[2];
-    int uv_offset[2];
-    int overlap_flag;
-    int clip_to_restricted_range;
-} Dav1dFilmGrainData;
-
-typedef struct Dav1dFrameHeader {
-    enum Dav1dFrameType frame_type; ///< type of the picture
-    int width[2 /* { coded_width, superresolution_upscaled_width } */], height;
-    int frame_offset; ///< frame number
-    struct {
-        int present, update;
-        Dav1dFilmGrainData data;
-    } film_grain; ///< film grain parameters
-    int temporal_id, spatial_id; ///< spatial and temporal id of the frame for SVC
-
-    int show_existing_frame;
-    int existing_frame_idx;
-    int frame_id;
-    int frame_presentation_delay;
-    int show_frame;
-    int showable_frame;
-    int error_resilient_mode;
-    int disable_cdf_update;
-    int allow_screen_content_tools;
-    int force_integer_mv;
-    int frame_size_override;
-    int primary_ref_frame;
-    int buffer_removal_time_present;
-    struct Dav1dFrameHeaderOperatingPoint {
-        int buffer_removal_time;
-    } operating_points[DAV1D_MAX_OPERATING_POINTS];
-    int refresh_frame_flags;
-    int render_width, render_height;
-    struct {
-        int width_scale_denominator;
-        int enabled;
-    } super_res;
-    int have_render_size;
-    int allow_intrabc;
-    int frame_ref_short_signaling;
-    int refidx[DAV1D_REFS_PER_FRAME];
-    int hp;
-    enum Dav1dFilterMode subpel_filter_mode;
-    int switchable_motion_mode;
-    int use_ref_frame_mvs;
-    int refresh_context;
-    struct {
-        int uniform;
-        unsigned n_bytes;
-        int min_log2_cols, max_log2_cols, log2_cols, cols;
-        int min_log2_rows, max_log2_rows, log2_rows, rows;
-        uint16_t col_start_sb[DAV1D_MAX_TILE_COLS + 1];
-        uint16_t row_start_sb[DAV1D_MAX_TILE_ROWS + 1];
-        int update;
-    } tiling;
-    struct {
-        int yac;
-        int ydc_delta;
-        int udc_delta, uac_delta, vdc_delta, vac_delta;
-        int qm, qm_y, qm_u, qm_v;
-    } quant;
-    struct {
-        int enabled, update_map, temporal, update_data;
-        Dav1dSegmentationDataSet seg_data;
-        int lossless[DAV1D_MAX_SEGMENTS], qidx[DAV1D_MAX_SEGMENTS];
-    } segmentation;
-    struct {
-        struct {
-            int present;
-            int res_log2;
-        } q;
-        struct {
-            int present;
-            int res_log2;
-            int multi;
-        } lf;
-    } delta;
-    int all_lossless;
-    struct {
-        int level_y[2 /* dir */];
-        int level_u, level_v;
-        int mode_ref_delta_enabled;
-        int mode_ref_delta_update;
-        Dav1dLoopfilterModeRefDeltas mode_ref_deltas;
-        int sharpness;
-    } loopfilter;
-    struct {
-        int damping;
-        int n_bits;
-        int y_strength[DAV1D_MAX_CDEF_STRENGTHS];
-        int uv_strength[DAV1D_MAX_CDEF_STRENGTHS];
-    } cdef;
-    struct {
-        enum Dav1dRestorationType type[3 /* plane */];
-        int unit_size[2 /* y, uv */];
-    } restoration;
-    enum Dav1dTxfmMode txfm_mode;
-    int switchable_comp_refs;
-    int skip_mode_allowed, skip_mode_enabled, skip_mode_refs[2];
-    int warp_motion;
-    int reduced_txtp_set;
-    Dav1dWarpedMotionParams gmv[DAV1D_REFS_PER_FRAME];
-} Dav1dFrameHeader;
-
-#endif /* DAV1D_HEADERS_H */
+/*

+ * Copyright © 2018-2020, VideoLAN and dav1d authors

+ * Copyright © 2018, Two Orioles, LLC

+ * All rights reserved.

+ *

+ * Redistribution and use in source and binary forms, with or without

+ * modification, are permitted provided that the following conditions are met:

+ *

+ * 1. Redistributions of source code must retain the above copyright notice, this

+ *    list of conditions and the following disclaimer.

+ *

+ * 2. Redistributions in binary form must reproduce the above copyright notice,

+ *    this list of conditions and the following disclaimer in the documentation

+ *    and/or other materials provided with the distribution.

+ *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND

+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED

+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE

+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR

+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;

+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND

+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS

+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ */

+

+#ifndef DAV1D_HEADERS_H

+#define DAV1D_HEADERS_H

+

+#include <stdint.h>

+#include <stddef.h>

+

+// Constants from Section 3. "Symbols and abbreviated terms"

+#define DAV1D_MAX_CDEF_STRENGTHS 8

+#define DAV1D_MAX_OPERATING_POINTS 32

+#define DAV1D_MAX_TILE_COLS 64

+#define DAV1D_MAX_TILE_ROWS 64

+#define DAV1D_MAX_SEGMENTS 8

+#define DAV1D_NUM_REF_FRAMES 8

+#define DAV1D_PRIMARY_REF_NONE 7

+#define DAV1D_REFS_PER_FRAME 7

+#define DAV1D_TOTAL_REFS_PER_FRAME (DAV1D_REFS_PER_FRAME + 1)

+

+enum Dav1dObuType {

+    DAV1D_OBU_SEQ_HDR   = 1,

+    DAV1D_OBU_TD        = 2,

+    DAV1D_OBU_FRAME_HDR = 3,

+    DAV1D_OBU_TILE_GRP  = 4,

+    DAV1D_OBU_METADATA  = 5,

+    DAV1D_OBU_FRAME     = 6,

+    DAV1D_OBU_REDUNDANT_FRAME_HDR = 7,

+    DAV1D_OBU_PADDING   = 15,

+};

+

+enum Dav1dTxfmMode {

+    DAV1D_TX_4X4_ONLY,

+    DAV1D_TX_LARGEST,

+    DAV1D_TX_SWITCHABLE,

+    DAV1D_N_TX_MODES,

+};

+

+enum Dav1dFilterMode {

+    DAV1D_FILTER_8TAP_REGULAR,

+    DAV1D_FILTER_8TAP_SMOOTH,

+    DAV1D_FILTER_8TAP_SHARP,

+    DAV1D_N_SWITCHABLE_FILTERS,

+    DAV1D_FILTER_BILINEAR = DAV1D_N_SWITCHABLE_FILTERS,

+    DAV1D_N_FILTERS,

+    DAV1D_FILTER_SWITCHABLE = DAV1D_N_FILTERS,

+};

+

+enum Dav1dAdaptiveBoolean {

+    DAV1D_OFF = 0,

+    DAV1D_ON = 1,

+    DAV1D_ADAPTIVE = 2,

+};

+

+enum Dav1dRestorationType {

+    DAV1D_RESTORATION_NONE,

+    DAV1D_RESTORATION_SWITCHABLE,

+    DAV1D_RESTORATION_WIENER,

+    DAV1D_RESTORATION_SGRPROJ,

+};

+

+enum Dav1dWarpedMotionType {

+    DAV1D_WM_TYPE_IDENTITY,

+    DAV1D_WM_TYPE_TRANSLATION,

+    DAV1D_WM_TYPE_ROT_ZOOM,

+    DAV1D_WM_TYPE_AFFINE,

+};

+

+typedef struct Dav1dWarpedMotionParams {

+    enum Dav1dWarpedMotionType type;

+    int32_t matrix[6];

+    union {

+        struct {

+            int16_t alpha, beta, gamma, delta;

+        } p;

+        int16_t abcd[4];

+    } u;

+} Dav1dWarpedMotionParams;

+

+enum Dav1dPixelLayout {

+    DAV1D_PIXEL_LAYOUT_I400, ///< monochrome

+    DAV1D_PIXEL_LAYOUT_I420, ///< 4:2:0 planar

+    DAV1D_PIXEL_LAYOUT_I422, ///< 4:2:2 planar

+    DAV1D_PIXEL_LAYOUT_I444, ///< 4:4:4 planar

+};

+

+enum Dav1dFrameType {

+    DAV1D_FRAME_TYPE_KEY = 0,    ///< Key Intra frame

+    DAV1D_FRAME_TYPE_INTER = 1,  ///< Inter frame

+    DAV1D_FRAME_TYPE_INTRA = 2,  ///< Non key Intra frame

+    DAV1D_FRAME_TYPE_SWITCH = 3, ///< Switch Inter frame

+};

+

+enum Dav1dColorPrimaries {

+    DAV1D_COLOR_PRI_BT709 = 1,

+    DAV1D_COLOR_PRI_UNKNOWN = 2,

+    DAV1D_COLOR_PRI_BT470M = 4,

+    DAV1D_COLOR_PRI_BT470BG = 5,

+    DAV1D_COLOR_PRI_BT601 = 6,

+    DAV1D_COLOR_PRI_SMPTE240 = 7,

+    DAV1D_COLOR_PRI_FILM = 8,

+    DAV1D_COLOR_PRI_BT2020 = 9,

+    DAV1D_COLOR_PRI_XYZ = 10,

+    DAV1D_COLOR_PRI_SMPTE431 = 11,

+    DAV1D_COLOR_PRI_SMPTE432 = 12,

+    DAV1D_COLOR_PRI_EBU3213 = 22,

+    DAV1D_COLOR_PRI_RESERVED = 255,

+};

+

+enum Dav1dTransferCharacteristics {

+    DAV1D_TRC_BT709 = 1,

+    DAV1D_TRC_UNKNOWN = 2,

+    DAV1D_TRC_BT470M = 4,

+    DAV1D_TRC_BT470BG = 5,

+    DAV1D_TRC_BT601 = 6,

+    DAV1D_TRC_SMPTE240 = 7,

+    DAV1D_TRC_LINEAR = 8,

+    DAV1D_TRC_LOG100 = 9,         ///< logarithmic (100:1 range)

+    DAV1D_TRC_LOG100_SQRT10 = 10, ///< lograithmic (100*sqrt(10):1 range)

+    DAV1D_TRC_IEC61966 = 11,

+    DAV1D_TRC_BT1361 = 12,

+    DAV1D_TRC_SRGB = 13,

+    DAV1D_TRC_BT2020_10BIT = 14,

+    DAV1D_TRC_BT2020_12BIT = 15,

+    DAV1D_TRC_SMPTE2084 = 16,     ///< PQ

+    DAV1D_TRC_SMPTE428 = 17,

+    DAV1D_TRC_HLG = 18,           ///< hybrid log/gamma (BT.2100 / ARIB STD-B67)

+    DAV1D_TRC_RESERVED = 255,

+};

+

+enum Dav1dMatrixCoefficients {

+    DAV1D_MC_IDENTITY = 0,

+    DAV1D_MC_BT709 = 1,

+    DAV1D_MC_UNKNOWN = 2,

+    DAV1D_MC_FCC = 4,

+    DAV1D_MC_BT470BG = 5,

+    DAV1D_MC_BT601 = 6,

+    DAV1D_MC_SMPTE240 = 7,

+    DAV1D_MC_SMPTE_YCGCO = 8,

+    DAV1D_MC_BT2020_NCL = 9,

+    DAV1D_MC_BT2020_CL = 10,

+    DAV1D_MC_SMPTE2085 = 11,

+    DAV1D_MC_CHROMAT_NCL = 12, ///< Chromaticity-derived

+    DAV1D_MC_CHROMAT_CL = 13,

+    DAV1D_MC_ICTCP = 14,

+    DAV1D_MC_RESERVED = 255,

+};

+

+enum Dav1dChromaSamplePosition {

+    DAV1D_CHR_UNKNOWN = 0,

+    DAV1D_CHR_VERTICAL = 1,  ///< Horizontally co-located with luma(0, 0)

+                           ///< sample, between two vertical samples

+    DAV1D_CHR_COLOCATED = 2, ///< Co-located with luma(0, 0) sample

+};

+

+typedef struct Dav1dContentLightLevel {

+    int max_content_light_level;

+    int max_frame_average_light_level;

+} Dav1dContentLightLevel;

+

+typedef struct Dav1dMasteringDisplay {

+    ///< 0.16 fixed point

+    uint16_t primaries[3][2];

+    ///< 0.16 fixed point

+    uint16_t white_point[2];

+    ///< 24.8 fixed point

+    uint32_t max_luminance;

+    ///< 18.14 fixed point

+    uint32_t min_luminance;

+} Dav1dMasteringDisplay;

+

+typedef struct Dav1dITUTT35 {

+    uint8_t  country_code;

+    uint8_t  country_code_extension_byte;

+    size_t   payload_size;

+    uint8_t *payload;

+} Dav1dITUTT35;

+

+typedef struct Dav1dSequenceHeader {

+    /**

+     * Stream profile, 0 for 8-10 bits/component 4:2:0 or monochrome;

+     * 1 for 8-10 bits/component 4:4:4; 2 for 4:2:2 at any bits/component,

+     * or 12 bits/component at any chroma subsampling.

+     */

+    int profile;

+    /**

+     * Maximum dimensions for this stream. In non-scalable streams, these

+     * are often the actual dimensions of the stream, although that is not

+     * a normative requirement.

+     */

+    int max_width, max_height;

+    enum Dav1dPixelLayout layout; ///< format of the picture

+    enum Dav1dColorPrimaries pri; ///< color primaries (av1)

+    enum Dav1dTransferCharacteristics trc; ///< transfer characteristics (av1)

+    enum Dav1dMatrixCoefficients mtrx; ///< matrix coefficients (av1)

+    enum Dav1dChromaSamplePosition chr; ///< chroma sample position (av1)

+    /**

+     * 0, 1 and 2 mean 8, 10 or 12 bits/component, respectively. This is not

+     * exactly the same as 'hbd' from the spec; the spec's hbd distinguishes

+     * between 8 (0) and 10-12 (1) bits/component, and another element

+     * (twelve_bit) to distinguish between 10 and 12 bits/component. To get

+     * the spec's hbd, use !!our_hbd, and to get twelve_bit, use hbd == 2.

+     */

+    int hbd;

+    /**

+     * Pixel data uses JPEG pixel range ([0,255] for 8bits) instead of

+     * MPEG pixel range ([16,235] for 8bits luma, [16,240] for 8bits chroma).

+     */

+    int color_range;

+

+    int num_operating_points;

+    struct Dav1dSequenceHeaderOperatingPoint {

+        int major_level, minor_level;

+        int initial_display_delay;

+        int idc;

+        int tier;

+        int decoder_model_param_present;

+        int display_model_param_present;

+    } operating_points[DAV1D_MAX_OPERATING_POINTS];

+

+    int still_picture;

+    int reduced_still_picture_header;

+    int timing_info_present;

+    int num_units_in_tick;

+    int time_scale;

+    int equal_picture_interval;

+    unsigned num_ticks_per_picture;

+    int decoder_model_info_present;

+    int encoder_decoder_buffer_delay_length;

+    int num_units_in_decoding_tick;

+    int buffer_removal_delay_length;

+    int frame_presentation_delay_length;

+    int display_model_info_present;

+    int width_n_bits, height_n_bits;

+    int frame_id_numbers_present;

+    int delta_frame_id_n_bits;

+    int frame_id_n_bits;

+    int sb128;

+    int filter_intra;

+    int intra_edge_filter;

+    int inter_intra;

+    int masked_compound;

+    int warped_motion;

+    int dual_filter;

+    int order_hint;

+    int jnt_comp;

+    int ref_frame_mvs;

+    enum Dav1dAdaptiveBoolean screen_content_tools;

+    enum Dav1dAdaptiveBoolean force_integer_mv;

+    int order_hint_n_bits;

+    int super_res;

+    int cdef;

+    int restoration;

+    int ss_hor, ss_ver, monochrome;

+    int color_description_present;

+    int separate_uv_delta_q;

+    int film_grain_present;

+

+    // Dav1dSequenceHeaders of the same sequence are required to be

+    // bit-identical until this offset. See 7.5 "Ordering of OBUs":

+    //   Within a particular coded video sequence, the contents of

+    //   sequence_header_obu must be bit-identical each time the

+    //   sequence header appears except for the contents of

+    //   operating_parameters_info.

+    struct Dav1dSequenceHeaderOperatingParameterInfo {

+        int decoder_buffer_delay;

+        int encoder_buffer_delay;

+        int low_delay_mode;

+    } operating_parameter_info[DAV1D_MAX_OPERATING_POINTS];

+} Dav1dSequenceHeader;

+

+typedef struct Dav1dSegmentationData {

+    int delta_q;

+    int delta_lf_y_v, delta_lf_y_h, delta_lf_u, delta_lf_v;

+    int ref;

+    int skip;

+    int globalmv;

+} Dav1dSegmentationData;

+

+typedef struct Dav1dSegmentationDataSet {

+    Dav1dSegmentationData d[DAV1D_MAX_SEGMENTS];

+    int preskip;

+    int last_active_segid;

+} Dav1dSegmentationDataSet;

+

+typedef struct Dav1dLoopfilterModeRefDeltas {

+    int mode_delta[2 /* is_zeromv */];

+    int ref_delta[DAV1D_TOTAL_REFS_PER_FRAME];

+} Dav1dLoopfilterModeRefDeltas;

+

+typedef struct Dav1dFilmGrainData {

+    unsigned seed;

+    int num_y_points;

+    uint8_t y_points[14][2 /* value, scaling */];

+    int chroma_scaling_from_luma;

+    int num_uv_points[2];

+    uint8_t uv_points[2][10][2 /* value, scaling */];

+    int scaling_shift;

+    int ar_coeff_lag;

+    int8_t ar_coeffs_y[24];

+    int8_t ar_coeffs_uv[2][25 + 3 /* padding for alignment purposes */];

+    uint64_t ar_coeff_shift;

+    int grain_scale_shift;

+    int uv_mult[2];

+    int uv_luma_mult[2];

+    int uv_offset[2];

+    int overlap_flag;

+    int clip_to_restricted_range;

+} Dav1dFilmGrainData;

+

+typedef struct Dav1dFrameHeader {

+    struct {

+        Dav1dFilmGrainData data;

+        int present, update;

+    } film_grain; ///< film grain parameters

+    enum Dav1dFrameType frame_type; ///< type of the picture

+    int width[2 /* { coded_width, superresolution_upscaled_width } */], height;

+    int frame_offset; ///< frame number

+    int temporal_id; ///< temporal id of the frame for SVC

+    int spatial_id; ///< spatial id of the frame for SVC

+

+    int show_existing_frame;

+    int existing_frame_idx;

+    int frame_id;

+    int frame_presentation_delay;

+    int show_frame;

+    int showable_frame;

+    int error_resilient_mode;

+    int disable_cdf_update;

+    int allow_screen_content_tools;

+    int force_integer_mv;

+    int frame_size_override;

+    int primary_ref_frame;

+    int buffer_removal_time_present;

+    struct Dav1dFrameHeaderOperatingPoint {

+        int buffer_removal_time;

+    } operating_points[DAV1D_MAX_OPERATING_POINTS];

+    int refresh_frame_flags;

+    int render_width, render_height;

+    struct {

+        int width_scale_denominator;

+        int enabled;

+    } super_res;

+    int have_render_size;

+    int allow_intrabc;

+    int frame_ref_short_signaling;

+    int refidx[DAV1D_REFS_PER_FRAME];

+    int hp;

+    enum Dav1dFilterMode subpel_filter_mode;

+    int switchable_motion_mode;

+    int use_ref_frame_mvs;

+    int refresh_context;

+    struct {

+        int uniform;

+        unsigned n_bytes;

+        int min_log2_cols, max_log2_cols, log2_cols, cols;

+        int min_log2_rows, max_log2_rows, log2_rows, rows;

+        uint16_t col_start_sb[DAV1D_MAX_TILE_COLS + 1];

+        uint16_t row_start_sb[DAV1D_MAX_TILE_ROWS + 1];

+        int update;

+    } tiling;

+    struct {

+        int yac;

+        int ydc_delta;

+        int udc_delta, uac_delta, vdc_delta, vac_delta;

+        int qm, qm_y, qm_u, qm_v;

+    } quant;

+    struct {

+        int enabled, update_map, temporal, update_data;

+        Dav1dSegmentationDataSet seg_data;

+        int lossless[DAV1D_MAX_SEGMENTS], qidx[DAV1D_MAX_SEGMENTS];

+    } segmentation;

+    struct {

+        struct {

+            int present;

+            int res_log2;

+        } q;

+        struct {

+            int present;

+            int res_log2;

+            int multi;

+        } lf;

+    } delta;

+    int all_lossless;

+    struct {

+        int level_y[2 /* dir */];

+        int level_u, level_v;

+        int mode_ref_delta_enabled;

+        int mode_ref_delta_update;

+        Dav1dLoopfilterModeRefDeltas mode_ref_deltas;

+        int sharpness;

+    } loopfilter;

+    struct {

+        int damping;

+        int n_bits;

+        int y_strength[DAV1D_MAX_CDEF_STRENGTHS];

+        int uv_strength[DAV1D_MAX_CDEF_STRENGTHS];

+    } cdef;

+    struct {

+        enum Dav1dRestorationType type[3 /* plane */];

+        int unit_size[2 /* y, uv */];

+    } restoration;

+    enum Dav1dTxfmMode txfm_mode;

+    int switchable_comp_refs;

+    int skip_mode_allowed, skip_mode_enabled, skip_mode_refs[2];

+    int warp_motion;

+    int reduced_txtp_set;

+    Dav1dWarpedMotionParams gmv[DAV1D_REFS_PER_FRAME];

+} Dav1dFrameHeader;

+

+#endif /* DAV1D_HEADERS_H */

diff --git a/src/third_party/libdav1d/include/dav1d/picture.h b/src/third_party/libdav1d/include/dav1d/picture.h
index 08746f3..68ef6d5 100644
--- a/src/third_party/libdav1d/include/dav1d/picture.h
+++ b/src/third_party/libdav1d/include/dav1d/picture.h
@@ -1,141 +1,144 @@
-/*
- * Copyright © 2018, VideoLAN and dav1d authors
- * Copyright © 2018, Two Orioles, LLC
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef DAV1D_PICTURE_H
-#define DAV1D_PICTURE_H
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "common.h"
-#include "headers.h"
-
-/* Number of bytes to align AND pad picture memory buffers by, so that SIMD
- * implementations can over-read by a few bytes, and use aligned read/write
- * instructions. */
-#define DAV1D_PICTURE_ALIGNMENT 64
-
-typedef struct Dav1dPictureParameters {
-    int w; ///< width (in pixels)
-    int h; ///< height (in pixels)
-    enum Dav1dPixelLayout layout; ///< format of the picture
-    int bpc; ///< bits per pixel component (8 or 10)
-} Dav1dPictureParameters;
-
-typedef struct Dav1dPicture {
-    Dav1dSequenceHeader *seq_hdr;
-    Dav1dFrameHeader *frame_hdr;
-
-    /**
-     * Pointers to planar image data (Y is [0], U is [1], V is [2]). The data
-     * should be bytes (for 8 bpc) or words (for 10 bpc). In case of words
-     * containing 10 bpc image data, the pixels should be located in the LSB
-     * bits, so that values range between [0, 1023]; the upper bits should be
-     * zero'ed out.
-     */
-    void *data[3];
-
-    /**
-     * Number of bytes between 2 lines in data[] for luma [0] or chroma [1].
-     */
-    ptrdiff_t stride[2];
-
-    Dav1dPictureParameters p;
-    Dav1dDataProps m;
-
-    /**
-     * High Dynamic Range Content Light Level metadata applying to this picture,
-     * as defined in section 5.8.3 and 6.7.3
-     */
-    Dav1dContentLightLevel *content_light;
-    /**
-     * High Dynamic Range Mastering Display Color Volume metadata applying to
-     * this picture, as defined in section 5.8.4 and 6.7.4
-     */
-    Dav1dMasteringDisplay *mastering_display;
-    /**
-     * ITU-T T.35 metadata as defined in section 5.8.2 and 6.7.2
-     */
-    Dav1dITUTT35 *itut_t35;
-
-    uintptr_t reserved[4]; ///< reserved for future use
-
-    struct Dav1dRef *frame_hdr_ref, *seq_hdr_ref; ///< Frame parameter allocation origins
-    struct Dav1dRef *content_light_ref, *mastering_display_ref, *itut_t35_ref; ///< Metadata allocation origins
-    uintptr_t reserved_ref[4]; ///< reserved for future use
-    struct Dav1dRef *ref; ///< Frame data allocation origin
-
-    void *allocator_data; ///< pointer managed by the allocator
-} Dav1dPicture;
-
-typedef struct Dav1dPicAllocator {
-    void *cookie; ///< custom data to pass to the allocator callbacks.
-    /**
-     * Allocate the picture buffer based on the Dav1dPictureParameters.
-     *
-     * The data[0], data[1] and data[2] must be DAV1D_PICTURE_ALIGNMENT byte
-     * aligned and with a pixel width/height multiple of 128 pixels. Any
-     * allocated memory area should also be padded by DAV1D_PICTURE_ALIGNMENT
-     * bytes.
-     * data[1] and data[2] must share the same stride[1].
-     *
-     * This function will be called on the main thread (the thread which calls
-     * dav1d_get_picture()).
-     *
-     * @param  pic The picture to allocate the buffer for. The callback needs to
-     *             fill the picture data[0], data[1], data[2], stride[0] and
-     *             stride[1].
-     *             The allocator can fill the pic allocator_data pointer with
-     *             a custom pointer that will be passed to
-     *             release_picture_callback().
-     * @param cookie Custom pointer passed to all calls.
-     *
-     * @note No fields other than data, stride and allocator_data must be filled
-     *       by this callback.
-     * @return 0 on success. A negative DAV1D_ERR value on error.
-     */
-    int (*alloc_picture_callback)(Dav1dPicture *pic, void *cookie);
-    /**
-     * Release the picture buffer.
-     *
-     * If frame threading is used, this function may be called by the main
-     * thread (the thread which calls dav1d_get_picture()) or any of the frame
-     * threads and thus must be thread-safe. If frame threading is not used,
-     * this function will only be called on the main thread.
-     *
-     * @param pic    The picture that was filled by alloc_picture_callback().
-     * @param cookie Custom pointer passed to all calls.
-     */
-    void (*release_picture_callback)(Dav1dPicture *pic, void *cookie);
-} Dav1dPicAllocator;
-
-/**
- * Release reference to a picture.
- */
-DAV1D_API void dav1d_picture_unref(Dav1dPicture *p);
-
-#endif /* DAV1D_PICTURE_H */
+/*

+ * Copyright © 2018-2020, VideoLAN and dav1d authors

+ * Copyright © 2018, Two Orioles, LLC

+ * All rights reserved.

+ *

+ * Redistribution and use in source and binary forms, with or without

+ * modification, are permitted provided that the following conditions are met:

+ *

+ * 1. Redistributions of source code must retain the above copyright notice, this

+ *    list of conditions and the following disclaimer.

+ *

+ * 2. Redistributions in binary form must reproduce the above copyright notice,

+ *    this list of conditions and the following disclaimer in the documentation

+ *    and/or other materials provided with the distribution.

+ *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND

+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED

+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE

+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR

+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;

+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND

+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS

+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ */

+

+#ifndef DAV1D_PICTURE_H

+#define DAV1D_PICTURE_H

+

+#include <stddef.h>

+#include <stdint.h>

+

+#include "common.h"

+#include "headers.h"

+

+/* Number of bytes to align AND pad picture memory buffers by, so that SIMD

+ * implementations can over-read by a few bytes, and use aligned read/write

+ * instructions. */

+#define DAV1D_PICTURE_ALIGNMENT 64

+

+typedef struct Dav1dPictureParameters {

+    int w; ///< width (in pixels)

+    int h; ///< height (in pixels)

+    enum Dav1dPixelLayout layout; ///< format of the picture

+    int bpc; ///< bits per pixel component (8 or 10)

+} Dav1dPictureParameters;

+

+typedef struct Dav1dPicture {

+    Dav1dSequenceHeader *seq_hdr;

+    Dav1dFrameHeader *frame_hdr;

+

+    /**

+     * Pointers to planar image data (Y is [0], U is [1], V is [2]). The data

+     * should be bytes (for 8 bpc) or words (for 10 bpc). In case of words

+     * containing 10 bpc image data, the pixels should be located in the LSB

+     * bits, so that values range between [0, 1023]; the upper bits should be

+     * zero'ed out.

+     */

+    void *data[3];

+

+    /**

+     * Number of bytes between 2 lines in data[] for luma [0] or chroma [1].

+     */

+    ptrdiff_t stride[2];

+

+    Dav1dPictureParameters p;

+    Dav1dDataProps m;

+

+    /**

+     * High Dynamic Range Content Light Level metadata applying to this picture,

+     * as defined in section 5.8.3 and 6.7.3

+     */

+    Dav1dContentLightLevel *content_light;

+    /**

+     * High Dynamic Range Mastering Display Color Volume metadata applying to

+     * this picture, as defined in section 5.8.4 and 6.7.4

+     */

+    Dav1dMasteringDisplay *mastering_display;

+    /**

+     * ITU-T T.35 metadata as defined in section 5.8.2 and 6.7.2

+     */

+    Dav1dITUTT35 *itut_t35;

+

+    uintptr_t reserved[4]; ///< reserved for future use

+

+    struct Dav1dRef *frame_hdr_ref; ///< Dav1dFrameHeader allocation origin

+    struct Dav1dRef *seq_hdr_ref; ///< Dav1dSequenceHeader allocation origin

+    struct Dav1dRef *content_light_ref; ///< Dav1dContentLightLevel allocation origin

+    struct Dav1dRef *mastering_display_ref; ///< Dav1dMasteringDisplay allocation origin

+    struct Dav1dRef *itut_t35_ref; ///< Dav1dITUTT35 allocation origin

+    uintptr_t reserved_ref[4]; ///< reserved for future use

+    struct Dav1dRef *ref; ///< Frame data allocation origin

+

+    void *allocator_data; ///< pointer managed by the allocator

+} Dav1dPicture;

+

+typedef struct Dav1dPicAllocator {

+    void *cookie; ///< custom data to pass to the allocator callbacks.

+    /**

+     * Allocate the picture buffer based on the Dav1dPictureParameters.

+     *

+     * The data[0], data[1] and data[2] must be DAV1D_PICTURE_ALIGNMENT byte

+     * aligned and with a pixel width/height multiple of 128 pixels. Any

+     * allocated memory area should also be padded by DAV1D_PICTURE_ALIGNMENT

+     * bytes.

+     * data[1] and data[2] must share the same stride[1].

+     *

+     * This function will be called on the main thread (the thread which calls

+     * dav1d_get_picture()).

+     *

+     * @param  pic The picture to allocate the buffer for. The callback needs to

+     *             fill the picture data[0], data[1], data[2], stride[0] and

+     *             stride[1].

+     *             The allocator can fill the pic allocator_data pointer with

+     *             a custom pointer that will be passed to

+     *             release_picture_callback().

+     * @param cookie Custom pointer passed to all calls.

+     *

+     * @note No fields other than data, stride and allocator_data must be filled

+     *       by this callback.

+     * @return 0 on success. A negative DAV1D_ERR value on error.

+     */

+    int (*alloc_picture_callback)(Dav1dPicture *pic, void *cookie);

+    /**

+     * Release the picture buffer.

+     *

+     * If frame threading is used, this function may be called by the main

+     * thread (the thread which calls dav1d_get_picture()) or any of the frame

+     * threads and thus must be thread-safe. If frame threading is not used,

+     * this function will only be called on the main thread.

+     *

+     * @param pic    The picture that was filled by alloc_picture_callback().

+     * @param cookie Custom pointer passed to all calls.

+     */

+    void (*release_picture_callback)(Dav1dPicture *pic, void *cookie);

+} Dav1dPicAllocator;

+

+/**

+ * Release reference to a picture.

+ */

+DAV1D_API void dav1d_picture_unref(Dav1dPicture *p);

+

+#endif /* DAV1D_PICTURE_H */

diff --git a/src/third_party/libdav1d/platforms/linux-x64/libdav1d.a b/src/third_party/libdav1d/platforms/linux-x64/libdav1d.a
index bb3473f..5189375 100644
--- a/src/third_party/libdav1d/platforms/linux-x64/libdav1d.a
+++ b/src/third_party/libdav1d/platforms/linux-x64/libdav1d.a
Binary files differ
diff --git a/src/tools/download_from_gcs.py b/src/tools/download_from_gcs.py
index 9c79dfb..4a49502 100755
--- a/src/tools/download_from_gcs.py
+++ b/src/tools/download_from_gcs.py
@@ -57,11 +57,13 @@
   context = create_default_context()
 
   try:
-    res = urllib.urlopen(url, context=context) if context else urllib.urlopen(url)
+    res = urllib.urlopen(
+        url, context=context) if context else urllib.urlopen(url)
   except urllib.URLError:
-    from ssl import _create_unverified_context
+    from ssl import _create_unverified_context  # pylint:disable=import-outside-toplevel
     context = _create_unverified_context()
-    res = urllib.urlopen(url, context=context) if context else urllib.urlopen(url)
+    res = urllib.urlopen(
+        url, context=context) if context else urllib.urlopen(url)
 
   if not res:
     logging.error('Could not reach %s', url)
diff --git a/src/tools/download_from_gcs_test.py b/src/tools/download_from_gcs_test.py
index 6c5b4b8..65a0eaf 100755
--- a/src/tools/download_from_gcs_test.py
+++ b/src/tools/download_from_gcs_test.py
@@ -18,7 +18,7 @@
 import tempfile
 import unittest
 
-import tools.download_from_gcs as download_from_gcs
+from tools import download_from_gcs
 
 _BUCKET = 'chromium-clang-format'
 _HASH_FILE_EXT = '.sha1'
@@ -52,7 +52,7 @@
 
   def setUp(self):
     self.test_file = os.path.join(_TEST_PATH, _TEST_FILE)
-    self.output_directory = tempfile.TemporaryDirectory()
+    self.output_directory = tempfile.TemporaryDirectory()  # pylint:disable=consider-using-with
     self.output_file = os.path.join(self.output_directory.name, 'output')
     self.bucket = _BUCKET
 
@@ -74,7 +74,7 @@
 
   def setUp(self):
     self.test_directory = os.path.join(_TEST_PATH, _TEST_DIRECTORY)
-    self.output_directory = tempfile.TemporaryDirectory()
+    self.output_directory = tempfile.TemporaryDirectory()  # pylint:disable=consider-using-with
     self.bucket = _BUCKET
 
   def tearDown(self):
diff --git a/src/tools/gyp/pylib/gyp/msvs_emulation.py b/src/tools/gyp/pylib/gyp/msvs_emulation.py
index 84f4ff6..ba2812c 100755
--- a/src/tools/gyp/pylib/gyp/msvs_emulation.py
+++ b/src/tools/gyp/pylib/gyp/msvs_emulation.py
@@ -747,7 +747,8 @@
       'cell_.*',
       'sn_.*',
       'sce_.*',
-      'is_docker', # TODO(agmenon): needed for ninja to invoke docker-specific logic
+      'is_docker', # needed for ninja to invoke docker-specific logic
+      'is_ci',     # needed for ninja to exlcude some logic on GKE
   )
   env = {}
   for line in output_of_set.splitlines():