1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_RECLAIMABLE_CODEC_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_RECLAIMABLE_CODEC_H_
#include <memory>
#include "base/feature_list.h"
#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/heap/prefinalizer.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h"
#include "third_party/blink/renderer/platform/timer.h"
namespace base {
class TickClock;
} // namespace base
namespace blink {
class CodecPressureManager;
class DOMException;
class ExecutionContext;
class MODULES_EXPORT ReclaimableCodec
: public ExecutionContextLifecycleObserver {
USING_PRE_FINALIZER(ReclaimableCodec, Dispose);
public:
// Use 1.5 minutes since some RDP clients are only ticking at 1 FPM.
static constexpr base::TimeDelta kInactivityReclamationThreshold =
base::Seconds(90);
enum class CodecType {
kDecoder,
kEncoder,
};
ReclaimableCodec(CodecType, ExecutionContext*);
~ReclaimableCodec() override = default;
// GarbageCollectedMixin override.
void Trace(Visitor*) const override;
// Apply or release pressure, if this codec is holding on to constrained
// resources.
void ApplyCodecPressure();
void ReleaseCodecPressure();
// Pre-finalizer.
void Dispose();
// Called by PressureManger() when we cross the pressure threshold at which
// we should start/stop reclamation attempts.
void SetGlobalPressureExceededFlag(bool global_pressure_exceeded);
// Notified when throttling state is changed. May be called consecutively
// with the same value.
void OnLifecycleStateChanged(scheduler::SchedulingLifecycleState);
bool is_applying_codec_pressure() const { return is_applying_pressure_; }
// Test support.
void SimulateCodecReclaimedForTesting();
void SimulateActivityTimerFiredForTesting();
void SimulateLifecycleStateForTesting(scheduler::SchedulingLifecycleState);
bool IsReclamationTimerActiveForTesting() {
return activity_timer_.IsActive();
}
bool is_backgrounded_for_testing() { return is_backgrounded_; }
void set_tick_clock_for_testing(const base::TickClock* clock) {
tick_clock_ = clock;
}
protected:
// Pushes back the time at which |this| can be reclaimed due to inactivity.
void MarkCodecActive();
virtual void OnCodecReclaimed(DOMException*) = 0;
CodecPressureManager* get_manager_for_testing() { return PressureManager(); }
base::TimeTicks last_activity_for_testing() const { return last_activity_; }
bool global_pressure_exceeded_for_testing() const {
return global_pressure_exceeded_;
}
private:
CodecPressureManager* PressureManager();
// Starts the idle reclamation timer if all preconditions are met, or stops it
// otherwise. Called when any of the following criteria change:
// - Global codec pressure exceeds a threshold or falls back under it.
// - |this| applies/releases codec pressure.
// - |this|'s background status changes.
void OnReclamationPreconditionsUpdated();
bool AreReclamationPreconditionsMet();
void StartIdleReclamationTimer();
void StopIdleReclamationTimer();
void OnActivityTimerFired(TimerBase*);
// This is used to make sure that there are two consecutive ticks of the
// timer, before we reclaim for inactivity. This prevents immediately
// reclaiming otherwise active codecs, right after a page suspended/resumed.
bool last_tick_was_inactive_ = false;
// Used to distinguish between encoder and decoder pressure.
CodecType codec_type_;
// Whether this codec is holding on to platform resources.
bool is_applying_pressure_ = false;
raw_ptr<const base::TickClock> tick_clock_;
// Period of time after which a codec is considered to be inactive.
base::TimeDelta inactivity_threshold_;
base::TimeTicks last_activity_;
HeapTaskRunnerTimer<ReclaimableCodec> activity_timer_;
// Flag indicating if there are too many codecs according to PressureManger(),
// and whether we should attempt to reclaim codecs.
bool global_pressure_exceeded_ = false;
// True iff document.visibilityState of the associated page is "hidden".
// This includes being in bg of tab strip, minimized, or (depending on OS)
// covered by other windows.
bool is_backgrounded_ = false;
// Handle to unhook from FrameOrWorkerScheduler upon destruction.
std::unique_ptr<FrameOrWorkerScheduler::LifecycleObserverHandle>
observer_handle_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_RECLAIMABLE_CODEC_H_
|