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( | |
| 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 |