Chromium Code Reviews| 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 |