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

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

Issue 2788483003: Introduce AudioBufferMemoryPool to avoid thrashing on audio buffers. (Closed)
Patch Set: Privatize methods. Remove cruft. 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 #include "media/base/audio_buffer.h" 5 #include "media/base/audio_buffer.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "media/base/audio_bus.h" 10 #include "media/base/audio_bus.h"
11 #include "media/base/limits.h" 11 #include "media/base/limits.h"
12 #include "media/base/timestamp_constants.h" 12 #include "media/base/timestamp_constants.h"
13 13
14 namespace media { 14 namespace media {
15 15
16 static base::TimeDelta CalculateDuration(int frames, double sample_rate) { 16 static base::TimeDelta CalculateDuration(int frames, double sample_rate) {
17 DCHECK_GT(sample_rate, 0); 17 DCHECK_GT(sample_rate, 0);
18 return base::TimeDelta::FromMicroseconds( 18 return base::TimeDelta::FromMicroseconds(
19 frames * base::Time::kMicrosecondsPerSecond / sample_rate); 19 frames * base::Time::kMicrosecondsPerSecond / sample_rate);
20 } 20 }
21 21
22 AudioBufferMemoryPool::AudioBufferMemoryPool() {}
23 AudioBufferMemoryPool::~AudioBufferMemoryPool() {}
24
25 AudioBufferMemoryPool::AudioMemory AudioBufferMemoryPool::CreateBuffer(
xhwang 2017/04/01 00:05:26 Could you please add comments summarizing the allo
DaleCurtis 2017/04/01 01:00:01 Done.
26 size_t size) {
27 base::AutoLock al(entry_lock_);
28 while (!entries_.empty()) {
29 MemoryEntry& front = entries_.front();
30 MemoryEntry entry(std::move(front.first), front.second);
31 entries_.pop_front();
32 if (entry.second == size)
33 return std::move(entry.first);
34 }
35
36 return AudioMemory(static_cast<uint8_t*>(
37 base::AlignedAlloc(size, AudioBuffer::kChannelAlignment)));
38 }
39
40 void AudioBufferMemoryPool::ReturnBuffer(AudioMemory memory, size_t size) {
41 base::AutoLock al(entry_lock_);
42 entries_.emplace_back(std::move(memory), size);
43 }
44
22 AudioBuffer::AudioBuffer(SampleFormat sample_format, 45 AudioBuffer::AudioBuffer(SampleFormat sample_format,
23 ChannelLayout channel_layout, 46 ChannelLayout channel_layout,
24 int channel_count, 47 int channel_count,
25 int sample_rate, 48 int sample_rate,
26 int frame_count, 49 int frame_count,
27 bool create_buffer, 50 bool create_buffer,
28 const uint8_t* const* data, 51 const uint8_t* const* data,
29 const base::TimeDelta timestamp) 52 const base::TimeDelta timestamp,
53 scoped_refptr<AudioBufferMemoryPool> pool)
30 : sample_format_(sample_format), 54 : sample_format_(sample_format),
31 channel_layout_(channel_layout), 55 channel_layout_(channel_layout),
32 channel_count_(channel_count), 56 channel_count_(channel_count),
33 sample_rate_(sample_rate), 57 sample_rate_(sample_rate),
34 adjusted_frame_count_(frame_count), 58 adjusted_frame_count_(frame_count),
35 end_of_stream_(!create_buffer && data == NULL && frame_count == 0), 59 end_of_stream_(!create_buffer && !data && !frame_count),
36 timestamp_(timestamp), 60 timestamp_(timestamp),
37 duration_(end_of_stream_ 61 duration_(end_of_stream_
38 ? base::TimeDelta() 62 ? base::TimeDelta()
39 : CalculateDuration(adjusted_frame_count_, sample_rate_)), 63 : CalculateDuration(adjusted_frame_count_, sample_rate_)),
40 data_size_(0) { 64 data_size_(0),
65 pool_(std::move(pool)) {
41 CHECK_GE(channel_count_, 0); 66 CHECK_GE(channel_count_, 0);
42 CHECK_LE(channel_count_, limits::kMaxChannels); 67 CHECK_LE(channel_count_, limits::kMaxChannels);
43 CHECK_GE(frame_count, 0); 68 CHECK_GE(frame_count, 0);
44 DCHECK(channel_layout == CHANNEL_LAYOUT_DISCRETE || 69 DCHECK(channel_layout == CHANNEL_LAYOUT_DISCRETE ||
45 ChannelLayoutToChannelCount(channel_layout) == channel_count); 70 ChannelLayoutToChannelCount(channel_layout) == channel_count);
46 71
47 int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format); 72 int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format);
48 DCHECK_LE(bytes_per_channel, kChannelAlignment); 73 DCHECK_LE(bytes_per_channel, kChannelAlignment);
49 74
50 // Empty buffer? 75 // Empty buffer?
(...skipping 22 matching lines...) Expand all
73 memcpy(channel_data_[i], data[i], data_size_per_channel); 98 memcpy(channel_data_[i], data[i], data_size_per_channel);
74 } 99 }
75 return; 100 return;
76 } 101 }
77 102
78 // Remaining formats are interleaved data. 103 // Remaining formats are interleaved data.
79 DCHECK(IsInterleaved(sample_format)) << sample_format_; 104 DCHECK(IsInterleaved(sample_format)) << sample_format_;
80 // Allocate our own buffer and copy the supplied data into it. Buffer must 105 // Allocate our own buffer and copy the supplied data into it. Buffer must
81 // contain the data for all channels. 106 // contain the data for all channels.
82 data_size_ = data_size_per_channel * channel_count_; 107 data_size_ = data_size_per_channel * channel_count_;
83 data_.reset( 108
84 static_cast<uint8_t*>(base::AlignedAlloc(data_size_, kChannelAlignment))); 109 if (pool_) {
110 data_ = pool_->CreateBuffer(data_size_);
111 } else {
112 data_.reset(static_cast<uint8_t*>(
113 base::AlignedAlloc(data_size_, kChannelAlignment)));
114 }
115
85 channel_data_.reserve(1); 116 channel_data_.reserve(1);
86 channel_data_.push_back(data_.get()); 117 channel_data_.push_back(data_.get());
87 if (data) 118 if (data)
88 memcpy(data_.get(), data[0], data_size_); 119 memcpy(data_.get(), data[0], data_size_);
89 } 120 }
90 121
91 AudioBuffer::~AudioBuffer() {} 122 AudioBuffer::~AudioBuffer() {
123 if (pool_)
124 pool_->ReturnBuffer(std::move(data_), data_size_);
125 }
92 126
93 // static 127 // static
94 scoped_refptr<AudioBuffer> AudioBuffer::CopyFrom( 128 scoped_refptr<AudioBuffer> AudioBuffer::CopyFrom(
95 SampleFormat sample_format, 129 SampleFormat sample_format,
96 ChannelLayout channel_layout, 130 ChannelLayout channel_layout,
97 int channel_count, 131 int channel_count,
98 int sample_rate, 132 int sample_rate,
99 int frame_count, 133 int frame_count,
100 const uint8_t* const* data, 134 const uint8_t* const* data,
101 const base::TimeDelta timestamp) { 135 const base::TimeDelta timestamp,
136 scoped_refptr<AudioBufferMemoryPool> pool) {
102 // If you hit this CHECK you likely have a bug in a demuxer. Go fix it. 137 // If you hit this CHECK you likely have a bug in a demuxer. Go fix it.
103 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer. 138 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer.
104 CHECK(data[0]); 139 CHECK(data[0]);
105 return make_scoped_refptr(new AudioBuffer(sample_format, 140 return make_scoped_refptr(
106 channel_layout, 141 new AudioBuffer(sample_format, channel_layout, channel_count, sample_rate,
107 channel_count, 142 frame_count, true, data, timestamp, std::move(pool)));
108 sample_rate,
109 frame_count,
110 true,
111 data,
112 timestamp));
113 } 143 }
114 144
115 // static 145 // static
116 scoped_refptr<AudioBuffer> AudioBuffer::CreateBuffer( 146 scoped_refptr<AudioBuffer> AudioBuffer::CreateBuffer(
117 SampleFormat sample_format, 147 SampleFormat sample_format,
118 ChannelLayout channel_layout, 148 ChannelLayout channel_layout,
119 int channel_count, 149 int channel_count,
120 int sample_rate, 150 int sample_rate,
121 int frame_count) { 151 int frame_count,
152 scoped_refptr<AudioBufferMemoryPool> pool) {
122 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer. 153 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer.
123 return make_scoped_refptr( 154 return make_scoped_refptr(new AudioBuffer(
124 new AudioBuffer(sample_format, channel_layout, channel_count, sample_rate, 155 sample_format, channel_layout, channel_count, sample_rate, frame_count,
125 frame_count, true, NULL, kNoTimestamp)); 156 true, nullptr, kNoTimestamp, std::move(pool)));
126 } 157 }
127 158
128 // static 159 // static
129 scoped_refptr<AudioBuffer> AudioBuffer::CreateEmptyBuffer( 160 scoped_refptr<AudioBuffer> AudioBuffer::CreateEmptyBuffer(
130 ChannelLayout channel_layout, 161 ChannelLayout channel_layout,
131 int channel_count, 162 int channel_count,
132 int sample_rate, 163 int sample_rate,
133 int frame_count, 164 int frame_count,
134 const base::TimeDelta timestamp) { 165 const base::TimeDelta timestamp) {
135 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer. 166 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer.
136 // Since data == NULL, format doesn't matter. 167 // Since data == nullptr, format doesn't matter.
137 return make_scoped_refptr(new AudioBuffer(kSampleFormatF32, 168 return make_scoped_refptr(new AudioBuffer(
138 channel_layout, 169 kSampleFormatF32, channel_layout, channel_count, sample_rate, frame_count,
139 channel_count, 170 false, nullptr, timestamp, nullptr));
140 sample_rate,
141 frame_count,
142 false,
143 NULL,
144 timestamp));
145 } 171 }
146 172
147 // static 173 // static
148 scoped_refptr<AudioBuffer> AudioBuffer::CreateEOSBuffer() { 174 scoped_refptr<AudioBuffer> AudioBuffer::CreateEOSBuffer() {
149 return make_scoped_refptr(new AudioBuffer(kUnknownSampleFormat, 175 return make_scoped_refptr(new AudioBuffer(kUnknownSampleFormat,
150 CHANNEL_LAYOUT_NONE, 0, 0, 0, false, 176 CHANNEL_LAYOUT_NONE, 0, 0, 0, false,
151 NULL, kNoTimestamp)); 177 nullptr, kNoTimestamp, nullptr));
152 } 178 }
153 179
154 // Convert int16_t values in the range [INT16_MIN, INT16_MAX] to [-1.0, 1.0]. 180 // Convert int16_t values in the range [INT16_MIN, INT16_MAX] to [-1.0, 1.0].
155 inline float ConvertSample(int16_t value) { 181 inline float ConvertSample(int16_t value) {
156 return value * (value < 0 ? -1.0f / std::numeric_limits<int16_t>::min() 182 return value * (value < 0 ? -1.0f / std::numeric_limits<int16_t>::min()
157 : 1.0f / std::numeric_limits<int16_t>::max()); 183 : 1.0f / std::numeric_limits<int16_t>::max());
158 } 184 }
159 185
160 void AudioBuffer::AdjustSampleRate(int sample_rate) { 186 void AudioBuffer::AdjustSampleRate(int sample_rate) {
161 DCHECK(!end_of_stream_); 187 DCHECK(!end_of_stream_);
(...skipping 20 matching lines...) Expand all
182 dest->ZeroFramesPartial(dest_frame_offset, frames_to_copy); 208 dest->ZeroFramesPartial(dest_frame_offset, frames_to_copy);
183 return; 209 return;
184 } 210 }
185 211
186 if (sample_format_ == kSampleFormatPlanarF32) { 212 if (sample_format_ == kSampleFormatPlanarF32) {
187 // Format is planar float32. Copy the data from each channel as a block. 213 // Format is planar float32. Copy the data from each channel as a block.
188 for (int ch = 0; ch < channel_count_; ++ch) { 214 for (int ch = 0; ch < channel_count_; ++ch) {
189 const float* source_data = 215 const float* source_data =
190 reinterpret_cast<const float*>(channel_data_[ch]) + 216 reinterpret_cast<const float*>(channel_data_[ch]) +
191 source_frame_offset; 217 source_frame_offset;
192 memcpy(dest->channel(ch) + dest_frame_offset, 218 memcpy(dest->channel(ch) + dest_frame_offset, source_data,
193 source_data,
194 sizeof(float) * frames_to_copy); 219 sizeof(float) * frames_to_copy);
195 } 220 }
196 return; 221 return;
197 } 222 }
198 223
199 if (sample_format_ == kSampleFormatPlanarS16) { 224 if (sample_format_ == kSampleFormatPlanarS16) {
200 // Format is planar signed16. Convert each value into float and insert into 225 // Format is planar signed16. Convert each value into float and insert into
201 // output channel data. 226 // output channel data.
202 for (int ch = 0; ch < channel_count_; ++ch) { 227 for (int ch = 0; ch < channel_count_; ++ch) {
203 const int16_t* source_data = 228 const int16_t* source_data =
(...skipping 22 matching lines...) Expand all
226 } 251 }
227 252
228 // Remaining formats are integer interleaved data. Use the deinterleaving code 253 // Remaining formats are integer interleaved data. Use the deinterleaving code
229 // in AudioBus to copy the data. 254 // in AudioBus to copy the data.
230 DCHECK( 255 DCHECK(
231 sample_format_ == kSampleFormatU8 || sample_format_ == kSampleFormatS16 || 256 sample_format_ == kSampleFormatU8 || sample_format_ == kSampleFormatS16 ||
232 sample_format_ == kSampleFormatS24 || sample_format_ == kSampleFormatS32); 257 sample_format_ == kSampleFormatS24 || sample_format_ == kSampleFormatS32);
233 int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format_); 258 int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format_);
234 int frame_size = channel_count_ * bytes_per_channel; 259 int frame_size = channel_count_ * bytes_per_channel;
235 const uint8_t* source_data = data_.get() + source_frame_offset * frame_size; 260 const uint8_t* source_data = data_.get() + source_frame_offset * frame_size;
236 dest->FromInterleavedPartial( 261 dest->FromInterleavedPartial(source_data, dest_frame_offset, frames_to_copy,
237 source_data, dest_frame_offset, frames_to_copy, bytes_per_channel); 262 bytes_per_channel);
238 } 263 }
239 264
240 void AudioBuffer::TrimStart(int frames_to_trim) { 265 void AudioBuffer::TrimStart(int frames_to_trim) {
241 CHECK_GE(frames_to_trim, 0); 266 CHECK_GE(frames_to_trim, 0);
242 CHECK_LE(frames_to_trim, adjusted_frame_count_); 267 CHECK_LE(frames_to_trim, adjusted_frame_count_);
243 268
244 TrimRange(0, frames_to_trim); 269 TrimRange(0, frames_to_trim);
245 } 270 }
246 271
247 void AudioBuffer::TrimEnd(int frames_to_trim) { 272 void AudioBuffer::TrimEnd(int frames_to_trim) {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 } 319 }
295 } else { 320 } else {
296 CHECK_EQ(frames_to_copy, 0); 321 CHECK_EQ(frames_to_copy, 0);
297 } 322 }
298 323
299 // Trim the leftover data off the end of the buffer and update duration. 324 // Trim the leftover data off the end of the buffer and update duration.
300 TrimEnd(frames_to_trim); 325 TrimEnd(frames_to_trim);
301 } 326 }
302 327
303 } // namespace media 328 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698