1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef MEDIA_FILTERS_FRAME_BUFFER_POOL_H_
6 #define MEDIA_FILTERS_FRAME_BUFFER_POOL_H_
12 #include "base/functional/callback_forward.h"
13 #include "base/memory/raw_ptr.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/synchronization/lock.h"
16 #include "base/time/default_tick_clock.h"
17 #include "base/trace_event/memory_dump_provider.h"
18 #include "media/base/media_export.h"
21 class SequencedTaskRunner;
26 // FrameBufferPool is a pool of simple CPU memory. This class needs to be ref-
27 // counted since frames created using this memory may live beyond the lifetime
28 // of the caller to this class.
30 // This class is thread-safe, with the exception that it must be constructed on
31 // the same thread that `Shutdown()` is called on. Destruction may happen on
32 // any thread after `Shutdown()` returns. All other methods may be called on any
33 // thread safely, unless noted.
34 class MEDIA_EXPORT FrameBufferPool
35 : public base::RefCountedThreadSafe<FrameBufferPool>,
36 public base::trace_event::MemoryDumpProvider {
38 // Must be called on the same thread that `Shutdown()` is called on. If
39 // `zero_initialize_memory` is true, then initial allocations will be
40 // cleared. This does not affect reused buffers, which are never cleared.
41 explicit FrameBufferPool(bool zero_initialize_memory = false);
43 FrameBufferPool(const FrameBufferPool&) = delete;
44 FrameBufferPool& operator=(const FrameBufferPool&) = delete;
46 // Called when a frame buffer allocation is needed. Upon return |fb_priv| will
47 // be set to a private value used to identify the buffer in future calls and a
48 // buffer of at least |min_size| will be returned.
49 uint8_t* GetFrameBuffer(size_t min_size, void** fb_priv);
51 // Called when a frame buffer allocation is no longer needed.
52 void ReleaseFrameBuffer(void* fb_priv);
54 // Allocates (or reuses) room for an alpha plane on a given frame buffer.
55 // |fb_priv| must be a value previously returned by GetFrameBuffer().
56 uint8_t* AllocateAlphaPlaneForFrameBuffer(size_t min_size, void* fb_priv);
58 // Generates a "no_longer_needed" closure that holds a reference to this pool;
59 // |fb_priv| must be a value previously returned by GetFrameBuffer(). The
60 // callback may be called on any thread.
61 base::OnceClosure CreateFrameCallback(void* fb_priv);
63 size_t get_pool_size_for_testing() const {
64 base::AutoLock lock(lock_);
65 return frame_buffers_.size();
68 void set_tick_clock_for_testing(const base::TickClock* tick_clock) {
69 base::AutoLock lock(lock_);
70 tick_clock_ = tick_clock;
73 void force_allocation_error_for_testing() {
74 base::AutoLock lock(lock_);
75 force_allocation_error_ = true;
78 // Called when no more GetFrameBuffer() calls are expected. All unused memory
79 // is released at this time. As frames are returned their memory is released.
80 // This should not be called until anything that might call GetFrameBuffer()
81 // has been destroyed. Must be called on the same thread as the ctor.
84 enum { kStaleFrameLimitSecs = 10 };
87 friend class base::RefCountedThreadSafe<FrameBufferPool>;
88 ~FrameBufferPool() override;
90 // Internal structure holding memory for decoding.
93 // base::MemoryDumpProvider.
94 // Will always be called on `task_runner_`, though it is actually thread-safe.
95 bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
96 base::trace_event::ProcessMemoryDump* pmd) override;
98 // Not safe to concurrent modifications to `buf`. While the method is static,
99 // it's expected, but unchecked, that the caller holds `locked_` to prevent
100 // any modifications to `buf` during this call.
101 static bool IsUsedLocked(const FrameBuffer* buf);
103 // Drop all entries in |frame_buffers_| that report !IsUsedLocked(). Must be
104 // called with `lock_` held.
105 void EraseUnusedResourcesLocked();
107 // Method that gets called when a VideoFrame that references this pool gets
109 void OnVideoFrameDestroyed(FrameBuffer* frame_buffer);
111 // Should we allocate memory and clear it, or just allocate it? Note that
112 // memory is never cleared when reusing a previously returned buffer; only
113 // the initial allocation is affected.
114 const bool zero_initialize_memory_ = false;
116 // Here at the framebuffer cafe, all our dining philosophers share one fork.
117 mutable base::Lock lock_;
119 // Allocated frame buffers.
120 std::vector<std::unique_ptr<FrameBuffer>> frame_buffers_ GUARDED_BY(lock_);
122 bool in_shutdown_ GUARDED_BY(lock_) = false;
124 bool registered_dump_provider_ GUARDED_BY(lock_) = false;
126 bool force_allocation_error_ GUARDED_BY(lock_) = false;
128 // |tick_clock_| is always a DefaultTickClock outside of testing.
129 raw_ptr<const base::TickClock> tick_clock_ GUARDED_BY(lock_);
131 // Task runner that we tell the `MemoryDumpManager` about. It is the task
132 // runner on which we'll be asked to provide a memory dump, and the one on
133 // which `Shutdown()` should be called. It is set during construction.
134 const scoped_refptr<base::SequencedTaskRunner> task_runner_;
139 #endif // MEDIA_FILTERS_FRAME_BUFFER_POOL_H_