OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |