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

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

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

Powered by Google App Engine
This is Rietveld 408576698