Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: media/base/audio_buffer.h

Issue 2788483003: Introduce AudioBufferMemoryPool to avoid thrashing on audio buffers. (Closed)
Patch Set: Lock yo' pools! Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef MEDIA_BASE_AUDIO_BUFFER_H_ 5 #ifndef MEDIA_BASE_AUDIO_BUFFER_H_
6 #define MEDIA_BASE_AUDIO_BUFFER_H_ 6 #define MEDIA_BASE_AUDIO_BUFFER_H_
7 7
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <stdint.h> 9 #include <stdint.h>
10 10
11 #include <list>
11 #include <memory> 12 #include <memory>
12 #include <vector> 13 #include <vector>
13 14
14 #include "base/macros.h" 15 #include "base/macros.h"
15 #include "base/memory/aligned_memory.h" 16 #include "base/memory/aligned_memory.h"
16 #include "base/memory/ref_counted.h" 17 #include "base/memory/ref_counted.h"
18 #include "base/synchronization/lock.h"
17 #include "base/time/time.h" 19 #include "base/time/time.h"
18 #include "media/base/channel_layout.h" 20 #include "media/base/channel_layout.h"
19 #include "media/base/media_export.h" 21 #include "media/base/media_export.h"
20 #include "media/base/sample_format.h" 22 #include "media/base/sample_format.h"
21 23
22 namespace mojo { 24 namespace mojo {
23 template <typename T, typename U> 25 template <typename T, typename U>
24 struct TypeConverter; 26 struct TypeConverter;
25 template <typename T> 27 template <typename T>
26 class StructPtr; 28 class StructPtr;
27 }; 29 };
28 30
29 namespace media { 31 namespace media {
30 class AudioBus; 32 class AudioBus;
33 class AudioBufferMemoryPool;
31 34
32 namespace mojom { 35 namespace mojom {
33 class AudioBuffer; 36 class AudioBuffer;
34 } 37 }
35 38
36 // An audio buffer that takes a copy of the data passed to it, holds it, and 39 // An audio buffer that takes a copy of the data passed to it, holds it, and
37 // copies it into an AudioBus when needed. Also supports an end of stream 40 // copies it into an AudioBus when needed. Also supports an end of stream
38 // marker. 41 // marker.
39 class MEDIA_EXPORT AudioBuffer 42 class MEDIA_EXPORT AudioBuffer
40 : public base::RefCountedThreadSafe<AudioBuffer> { 43 : public base::RefCountedThreadSafe<AudioBuffer> {
41 public: 44 public:
42 // Alignment of each channel's data; this must match what ffmpeg expects 45 // Alignment of each channel's data; this must match what ffmpeg expects
43 // (which may be 0, 16, or 32, depending on the processor). Selecting 32 in 46 // (which may be 0, 16, or 32, depending on the processor). Selecting 32 in
44 // order to work on all processors. 47 // order to work on all processors.
45 enum { kChannelAlignment = 32 }; 48 enum { kChannelAlignment = 32 };
46 49
47 // Create an AudioBuffer whose channel data is copied from |data|. For 50 // Create an AudioBuffer whose channel data is copied from |data|. For
48 // interleaved data, only the first buffer is used. For planar data, the 51 // interleaved data, only the first buffer is used. For planar data, the
49 // number of buffers must be equal to |channel_count|. |frame_count| is the 52 // number of buffers must be equal to |channel_count|. |frame_count| is the
50 // number of frames in each buffer. |data| must not be null and |frame_count| 53 // number of frames in each buffer. |data| must not be null and |frame_count|
51 // must be >= 0. 54 // must be >= 0. For optimal efficiency when many buffers are being created, a
52 static scoped_refptr<AudioBuffer> CopyFrom(SampleFormat sample_format, 55 // AudioBufferMemoryPool can be provided to avoid thrashing memory.
53 ChannelLayout channel_layout, 56 static scoped_refptr<AudioBuffer> CopyFrom(
54 int channel_count, 57 SampleFormat sample_format,
55 int sample_rate, 58 ChannelLayout channel_layout,
56 int frame_count, 59 int channel_count,
57 const uint8_t* const* data, 60 int sample_rate,
58 const base::TimeDelta timestamp); 61 int frame_count,
62 const uint8_t* const* data,
63 const base::TimeDelta timestamp,
64 scoped_refptr<AudioBufferMemoryPool> pool = nullptr);
59 65
60 // Create an AudioBuffer with |frame_count| frames. Buffer is allocated, but 66 // Create an AudioBuffer with |frame_count| frames. Buffer is allocated, but
61 // not initialized. Timestamp and duration are set to kNoTimestamp. 67 // not initialized. Timestamp and duration are set to kNoTimestamp. For
62 static scoped_refptr<AudioBuffer> CreateBuffer(SampleFormat sample_format, 68 // optimal efficiency when many buffers are being created, a
63 ChannelLayout channel_layout, 69 // AudioBufferMemoryPool can be provided to avoid thrashing memory.
64 int channel_count, 70 static scoped_refptr<AudioBuffer> CreateBuffer(
65 int sample_rate, 71 SampleFormat sample_format,
66 int frame_count); 72 ChannelLayout channel_layout,
73 int channel_count,
74 int sample_rate,
75 int frame_count,
76 scoped_refptr<AudioBufferMemoryPool> pool = nullptr);
67 77
68 // Create an empty AudioBuffer with |frame_count| frames. 78 // Create an empty AudioBuffer with |frame_count| frames.
69 static scoped_refptr<AudioBuffer> CreateEmptyBuffer( 79 static scoped_refptr<AudioBuffer> CreateEmptyBuffer(
70 ChannelLayout channel_layout, 80 ChannelLayout channel_layout,
71 int channel_count, 81 int channel_count,
72 int sample_rate, 82 int sample_rate,
73 int frame_count, 83 int frame_count,
74 const base::TimeDelta timestamp); 84 const base::TimeDelta timestamp);
75 85
76 // Create a AudioBuffer indicating we've reached end of stream. 86 // Create a AudioBuffer indicating we've reached end of stream.
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 // [data,data+data_size) to the allocated buffer(s). If |data| is null, no 160 // [data,data+data_size) to the allocated buffer(s). If |data| is null, no
151 // data is copied. If |create_buffer| is false, no data buffer is created (or 161 // data is copied. If |create_buffer| is false, no data buffer is created (or
152 // copied to). 162 // copied to).
153 AudioBuffer(SampleFormat sample_format, 163 AudioBuffer(SampleFormat sample_format,
154 ChannelLayout channel_layout, 164 ChannelLayout channel_layout,
155 int channel_count, 165 int channel_count,
156 int sample_rate, 166 int sample_rate,
157 int frame_count, 167 int frame_count,
158 bool create_buffer, 168 bool create_buffer,
159 const uint8_t* const* data, 169 const uint8_t* const* data,
160 const base::TimeDelta timestamp); 170 const base::TimeDelta timestamp,
171 scoped_refptr<AudioBufferMemoryPool> pool);
161 172
162 virtual ~AudioBuffer(); 173 virtual ~AudioBuffer();
163 174
164 const SampleFormat sample_format_; 175 const SampleFormat sample_format_;
165 const ChannelLayout channel_layout_; 176 const ChannelLayout channel_layout_;
166 const int channel_count_; 177 const int channel_count_;
167 int sample_rate_; 178 int sample_rate_;
168 int adjusted_frame_count_; 179 int adjusted_frame_count_;
169 const bool end_of_stream_; 180 const bool end_of_stream_;
170 base::TimeDelta timestamp_; 181 base::TimeDelta timestamp_;
171 base::TimeDelta duration_; 182 base::TimeDelta duration_;
172 183
173 // Contiguous block of channel data. 184 // Contiguous block of channel data.
174 std::unique_ptr<uint8_t, base::AlignedFreeDeleter> data_; 185 std::unique_ptr<uint8_t, base::AlignedFreeDeleter> data_;
175 size_t data_size_; 186 size_t data_size_;
176 187
177 // For planar data, points to each channels data. 188 // For planar data, points to each channels data.
178 std::vector<uint8_t*> channel_data_; 189 std::vector<uint8_t*> channel_data_;
179 190
191 // Allows recycling of memory data to avoid repeated allocations.
192 scoped_refptr<AudioBufferMemoryPool> pool_;
193
180 DISALLOW_IMPLICIT_CONSTRUCTORS(AudioBuffer); 194 DISALLOW_IMPLICIT_CONSTRUCTORS(AudioBuffer);
181 }; 195 };
182 196
197 // Basic memory pool for reusing AudioBuffer internal memory to avoid thrashing.
198 class MEDIA_EXPORT AudioBufferMemoryPool
199 : public base::RefCountedThreadSafe<AudioBufferMemoryPool> {
200 public:
201 AudioBufferMemoryPool();
202
203 using AudioMemory = std::unique_ptr<uint8_t, base::AlignedFreeDeleter>;
204 AudioMemory CreateBuffer(size_t size);
205 void ReturnBuffer(AudioMemory memory, size_t size);
206
207 size_t get_pool_size_for_testing() const { return entries_.size(); }
208
209 private:
210 friend class base::RefCountedThreadSafe<AudioBufferMemoryPool>;
211 ~AudioBufferMemoryPool();
212
213 struct MemoryEntry {
214 MemoryEntry(AudioMemory, size_t data_size);
215 ~MemoryEntry();
216 AudioMemory data;
217 size_t size;
218 };
219
220 base::Lock entry_lock_;
221 std::list<MemoryEntry> entries_;
222 DISALLOW_COPY_AND_ASSIGN(AudioBufferMemoryPool);
223 };
224
183 } // namespace media 225 } // namespace media
184 226
185 #endif // MEDIA_BASE_AUDIO_BUFFER_H_ 227 #endif // MEDIA_BASE_AUDIO_BUFFER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698