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