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" |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 42 entries_.emplace_back(std::move(memory), size); | 42 entries_.emplace_back(std::move(memory), size); |
| 43 } | 43 } |
| 44 | 44 |
| 45 AudioBuffer::AudioBuffer(SampleFormat sample_format, | 45 AudioBuffer::AudioBuffer(SampleFormat sample_format, |
| 46 ChannelLayout channel_layout, | 46 ChannelLayout channel_layout, |
| 47 int channel_count, | 47 int channel_count, |
| 48 int sample_rate, | 48 int sample_rate, |
| 49 int frame_count, | 49 int frame_count, |
| 50 bool create_buffer, | 50 bool create_buffer, |
| 51 const uint8_t* const* data, | 51 const uint8_t* const* data, |
| 52 const size_t data_size, | |
| 52 const base::TimeDelta timestamp, | 53 const base::TimeDelta timestamp, |
| 53 scoped_refptr<AudioBufferMemoryPool> pool) | 54 scoped_refptr<AudioBufferMemoryPool> pool) |
| 54 : sample_format_(sample_format), | 55 : sample_format_(sample_format), |
| 55 channel_layout_(channel_layout), | 56 channel_layout_(channel_layout), |
| 56 channel_count_(channel_count), | 57 channel_count_(channel_count), |
| 57 sample_rate_(sample_rate), | 58 sample_rate_(sample_rate), |
| 58 adjusted_frame_count_(frame_count), | 59 adjusted_frame_count_(frame_count), |
| 59 end_of_stream_(!create_buffer && !data && !frame_count), | 60 end_of_stream_(!create_buffer && !data && !frame_count), |
| 60 timestamp_(timestamp), | 61 timestamp_(timestamp), |
| 61 duration_(end_of_stream_ | 62 duration_(end_of_stream_ |
| 62 ? base::TimeDelta() | 63 ? base::TimeDelta() |
| 63 : CalculateDuration(adjusted_frame_count_, sample_rate_)), | 64 : CalculateDuration(adjusted_frame_count_, sample_rate_)), |
| 64 data_size_(0), | 65 data_size_(data_size), |
| 65 pool_(std::move(pool)) { | 66 pool_(std::move(pool)) { |
| 66 CHECK_GE(channel_count_, 0); | 67 CHECK_GE(channel_count_, 0); |
| 67 CHECK_LE(channel_count_, limits::kMaxChannels); | 68 CHECK_LE(channel_count_, limits::kMaxChannels); |
| 68 CHECK_GE(frame_count, 0); | 69 CHECK_GE(frame_count, 0); |
| 69 DCHECK(channel_layout == CHANNEL_LAYOUT_DISCRETE || | 70 DCHECK(channel_layout == CHANNEL_LAYOUT_DISCRETE || |
| 70 ChannelLayoutToChannelCount(channel_layout) == channel_count); | 71 ChannelLayoutToChannelCount(channel_layout) == channel_count); |
| 71 | 72 |
| 72 int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format); | 73 int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format); |
| 73 DCHECK_LE(bytes_per_channel, kChannelAlignment); | 74 DCHECK_LE(bytes_per_channel, kChannelAlignment); |
| 74 | 75 |
| 75 // Empty buffer? | 76 // Empty buffer? |
| 76 if (!create_buffer) | 77 if (!create_buffer) |
| 77 return; | 78 return; |
| 78 | 79 |
| 79 int data_size_per_channel = frame_count * bytes_per_channel; | 80 int data_size_per_channel = frame_count * bytes_per_channel; |
| 80 if (IsPlanar(sample_format)) { | 81 if (IsPlanar(sample_format)) { |
| 81 // Planar data, so need to allocate buffer for each channel. | 82 // Planar data, so need to allocate buffer for each channel. |
|
chcunningham
2017/05/05 01:14:12
DCHECK(!IsBitstreamFormat(...))
AndyWu
2017/05/06 01:46:48
Done.
| |
| 82 // Determine per channel data size, taking into account alignment. | 83 // Determine per channel data size, taking into account alignment. |
| 83 int block_size_per_channel = | 84 int block_size_per_channel = |
| 84 (data_size_per_channel + kChannelAlignment - 1) & | 85 (data_size_per_channel + kChannelAlignment - 1) & |
| 85 ~(kChannelAlignment - 1); | 86 ~(kChannelAlignment - 1); |
| 86 DCHECK_GE(block_size_per_channel, data_size_per_channel); | 87 DCHECK_GE(block_size_per_channel, data_size_per_channel); |
| 87 | 88 |
| 88 // Allocate a contiguous buffer for all the channel data. | 89 // Allocate a contiguous buffer for all the channel data. |
| 89 data_size_ = channel_count_ * block_size_per_channel; | 90 data_size_ = channel_count_ * block_size_per_channel; |
| 90 if (pool_) { | 91 if (pool_) { |
| 91 data_ = pool_->CreateBuffer(data_size_); | 92 data_ = pool_->CreateBuffer(data_size_); |
| 92 } else { | 93 } else { |
| 93 data_.reset(static_cast<uint8_t*>( | 94 data_.reset(static_cast<uint8_t*>( |
| 94 base::AlignedAlloc(data_size_, kChannelAlignment))); | 95 base::AlignedAlloc(data_size_, kChannelAlignment))); |
| 95 } | 96 } |
| 96 channel_data_.reserve(channel_count_); | 97 channel_data_.reserve(channel_count_); |
| 97 | 98 |
| 98 // Copy each channel's data into the appropriate spot. | 99 // Copy each channel's data into the appropriate spot. |
| 99 for (int i = 0; i < channel_count_; ++i) { | 100 for (int i = 0; i < channel_count_; ++i) { |
| 100 channel_data_.push_back(data_.get() + i * block_size_per_channel); | 101 channel_data_.push_back(data_.get() + i * block_size_per_channel); |
| 101 if (data) | 102 if (data) |
| 102 memcpy(channel_data_[i], data[i], data_size_per_channel); | 103 memcpy(channel_data_[i], data[i], data_size_per_channel); |
| 103 } | 104 } |
| 104 return; | 105 return; |
| 105 } | 106 } |
| 106 | 107 |
| 107 // Remaining formats are interleaved data. | 108 // Remaining formats are interleaved data. |
| 108 DCHECK(IsInterleaved(sample_format)) << sample_format_; | 109 DCHECK(IsInterleaved(sample_format)) << sample_format_; |
| 109 // Allocate our own buffer and copy the supplied data into it. Buffer must | 110 // Allocate our own buffer and copy the supplied data into it. Buffer must |
| 110 // contain the data for all channels. | 111 // contain the data for all channels. |
| 111 data_size_ = data_size_per_channel * channel_count_; | 112 if (!IsBitstream(sample_format)) |
| 113 data_size_ = data_size_per_channel * channel_count_; | |
|
chcunningham
2017/05/05 01:14:12
else DCHECK(data_size_ > 0)?
AndyWu
2017/05/06 01:46:48
Done.
| |
| 112 | 114 |
| 113 if (pool_) { | 115 if (pool_) { |
| 114 data_ = pool_->CreateBuffer(data_size_); | 116 data_ = pool_->CreateBuffer(data_size_); |
| 115 } else { | 117 } else { |
| 116 data_.reset(static_cast<uint8_t*>( | 118 data_.reset(static_cast<uint8_t*>( |
| 117 base::AlignedAlloc(data_size_, kChannelAlignment))); | 119 base::AlignedAlloc(data_size_, kChannelAlignment))); |
| 118 } | 120 } |
| 119 | 121 |
| 120 channel_data_.reserve(1); | 122 channel_data_.reserve(1); |
| 121 channel_data_.push_back(data_.get()); | 123 channel_data_.push_back(data_.get()); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 136 int sample_rate, | 138 int sample_rate, |
| 137 int frame_count, | 139 int frame_count, |
| 138 const uint8_t* const* data, | 140 const uint8_t* const* data, |
| 139 const base::TimeDelta timestamp, | 141 const base::TimeDelta timestamp, |
| 140 scoped_refptr<AudioBufferMemoryPool> pool) { | 142 scoped_refptr<AudioBufferMemoryPool> pool) { |
| 141 // If you hit this CHECK you likely have a bug in a demuxer. Go fix it. | 143 // If you hit this CHECK you likely have a bug in a demuxer. Go fix it. |
| 142 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer. | 144 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer. |
| 143 CHECK(data[0]); | 145 CHECK(data[0]); |
| 144 return make_scoped_refptr( | 146 return make_scoped_refptr( |
| 145 new AudioBuffer(sample_format, channel_layout, channel_count, sample_rate, | 147 new AudioBuffer(sample_format, channel_layout, channel_count, sample_rate, |
| 146 frame_count, true, data, timestamp, std::move(pool))); | 148 frame_count, true, data, 0, timestamp, std::move(pool))); |
| 147 } | 149 } |
| 148 | 150 |
| 149 // static | 151 // static |
| 152 scoped_refptr<AudioBuffer> AudioBuffer::CopyBitstreamFrom( | |
| 153 SampleFormat sample_format, | |
| 154 ChannelLayout channel_layout, | |
| 155 int channel_count, | |
| 156 int sample_rate, | |
| 157 int frame_count, | |
| 158 const uint8_t* const* data, | |
| 159 const size_t data_size, | |
| 160 const base::TimeDelta timestamp, | |
| 161 scoped_refptr<AudioBufferMemoryPool> pool) { | |
| 162 // If you hit this CHECK you likely have a bug in a demuxer. Go fix it. | |
| 163 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer. | |
| 164 CHECK(data[0]); | |
| 165 return make_scoped_refptr(new AudioBuffer( | |
| 166 sample_format, channel_layout, channel_count, sample_rate, frame_count, | |
| 167 true, data, data_size, timestamp, std::move(pool))); | |
| 168 } | |
| 169 | |
| 170 // static | |
| 150 scoped_refptr<AudioBuffer> AudioBuffer::CreateBuffer( | 171 scoped_refptr<AudioBuffer> AudioBuffer::CreateBuffer( |
| 151 SampleFormat sample_format, | 172 SampleFormat sample_format, |
| 152 ChannelLayout channel_layout, | 173 ChannelLayout channel_layout, |
| 153 int channel_count, | 174 int channel_count, |
| 154 int sample_rate, | 175 int sample_rate, |
| 155 int frame_count, | 176 int frame_count, |
| 156 scoped_refptr<AudioBufferMemoryPool> pool) { | 177 scoped_refptr<AudioBufferMemoryPool> pool) { |
| 157 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer. | 178 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer. |
| 158 return make_scoped_refptr(new AudioBuffer( | 179 return make_scoped_refptr(new AudioBuffer( |
| 159 sample_format, channel_layout, channel_count, sample_rate, frame_count, | 180 sample_format, channel_layout, channel_count, sample_rate, frame_count, |
| 160 true, nullptr, kNoTimestamp, std::move(pool))); | 181 true, nullptr, 0, kNoTimestamp, std::move(pool))); |
| 161 } | 182 } |
| 162 | 183 |
| 163 // static | 184 // static |
| 185 scoped_refptr<AudioBuffer> AudioBuffer::CreateBitstreamBuffer( | |
| 186 SampleFormat sample_format, | |
| 187 ChannelLayout channel_layout, | |
| 188 int channel_count, | |
| 189 int sample_rate, | |
| 190 int frame_count, | |
| 191 size_t data_size, | |
| 192 scoped_refptr<AudioBufferMemoryPool> pool) { | |
| 193 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer. | |
| 194 return make_scoped_refptr(new AudioBuffer( | |
| 195 sample_format, channel_layout, channel_count, sample_rate, frame_count, | |
| 196 true, nullptr, data_size, kNoTimestamp, std::move(pool))); | |
| 197 } | |
| 198 | |
| 199 // static | |
| 164 scoped_refptr<AudioBuffer> AudioBuffer::CreateEmptyBuffer( | 200 scoped_refptr<AudioBuffer> AudioBuffer::CreateEmptyBuffer( |
| 165 ChannelLayout channel_layout, | 201 ChannelLayout channel_layout, |
| 166 int channel_count, | 202 int channel_count, |
| 167 int sample_rate, | 203 int sample_rate, |
| 168 int frame_count, | 204 int frame_count, |
| 169 const base::TimeDelta timestamp) { | 205 const base::TimeDelta timestamp) { |
| 170 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer. | 206 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer. |
| 171 // Since data == nullptr, format doesn't matter. | 207 // Since data == nullptr, format doesn't matter. |
| 172 return make_scoped_refptr(new AudioBuffer( | 208 return make_scoped_refptr(new AudioBuffer( |
| 173 kSampleFormatF32, channel_layout, channel_count, sample_rate, frame_count, | 209 kSampleFormatF32, channel_layout, channel_count, sample_rate, frame_count, |
| 174 false, nullptr, timestamp, nullptr)); | 210 false, nullptr, 0, timestamp, nullptr)); |
| 175 } | 211 } |
| 176 | 212 |
| 177 // static | 213 // static |
| 178 scoped_refptr<AudioBuffer> AudioBuffer::CreateEOSBuffer() { | 214 scoped_refptr<AudioBuffer> AudioBuffer::CreateEOSBuffer() { |
| 179 return make_scoped_refptr(new AudioBuffer(kUnknownSampleFormat, | 215 return make_scoped_refptr(new AudioBuffer(kUnknownSampleFormat, |
| 180 CHANNEL_LAYOUT_NONE, 0, 0, 0, false, | 216 CHANNEL_LAYOUT_NONE, 0, 0, 0, false, |
| 181 nullptr, kNoTimestamp, nullptr)); | 217 nullptr, 0, kNoTimestamp, nullptr)); |
| 182 } | 218 } |
| 183 | 219 |
| 184 // Convert int16_t values in the range [INT16_MIN, INT16_MAX] to [-1.0, 1.0]. | 220 // Convert int16_t values in the range [INT16_MIN, INT16_MAX] to [-1.0, 1.0]. |
| 185 inline float ConvertSample(int16_t value) { | 221 inline float ConvertSample(int16_t value) { |
| 186 return value * (value < 0 ? -1.0f / std::numeric_limits<int16_t>::min() | 222 return value * (value < 0 ? -1.0f / std::numeric_limits<int16_t>::min() |
| 187 : 1.0f / std::numeric_limits<int16_t>::max()); | 223 : 1.0f / std::numeric_limits<int16_t>::max()); |
| 188 } | 224 } |
| 189 | 225 |
| 190 void AudioBuffer::AdjustSampleRate(int sample_rate) { | 226 void AudioBuffer::AdjustSampleRate(int sample_rate) { |
| 191 DCHECK(!end_of_stream_); | 227 DCHECK(!end_of_stream_); |
| 192 sample_rate_ = sample_rate; | 228 sample_rate_ = sample_rate; |
| 193 duration_ = CalculateDuration(adjusted_frame_count_, sample_rate_); | 229 duration_ = CalculateDuration(adjusted_frame_count_, sample_rate_); |
| 194 } | 230 } |
| 195 | 231 |
| 196 void AudioBuffer::ReadFrames(int frames_to_copy, | 232 void AudioBuffer::ReadFrames(int frames_to_copy, |
| 197 int source_frame_offset, | 233 int source_frame_offset, |
| 198 int dest_frame_offset, | 234 int dest_frame_offset, |
| 199 AudioBus* dest) { | 235 AudioBus* dest) { |
| 200 // Deinterleave each channel (if necessary) and convert to 32bit | 236 // Deinterleave each channel (if necessary) and convert to 32bit |
| 201 // floating-point with nominal range -1.0 -> +1.0 (if necessary). | 237 // floating-point with nominal range -1.0 -> +1.0 (if necessary). |
| 202 | 238 |
| 203 // |dest| must have the same number of channels, and the number of frames | 239 // |dest| must have the same number of channels, and the number of frames |
| 204 // specified must be in range. | 240 // specified must be in range. |
| 205 DCHECK(!end_of_stream()); | 241 DCHECK(!end_of_stream()); |
| 206 DCHECK_EQ(dest->channels(), channel_count_); | 242 DCHECK_EQ(dest->channels(), channel_count_); |
| 207 DCHECK_LE(source_frame_offset + frames_to_copy, adjusted_frame_count_); | 243 DCHECK_LE(source_frame_offset + frames_to_copy, adjusted_frame_count_); |
| 244 | |
| 245 bool is_compressed_format = IsBitstream(sample_format_); | |
| 246 dest->set_is_compressed_format(is_compressed_format); | |
|
chcunningham
2017/05/05 01:14:11
is_compressed_format is slightly different name fr
AndyWu
2017/05/06 01:46:48
Sorry, this change should not be included in this
| |
| 247 | |
| 248 if (is_compressed_format) { | |
| 249 DCHECK(!source_frame_offset); | |
| 250 uint8_t* dest_data = | |
| 251 reinterpret_cast<uint8_t*>(dest->channel(0)) + dest->data_size(); | |
| 252 | |
| 253 memcpy(dest_data, channel_data_[0], data_size()); | |
| 254 dest->set_data_size(dest_frame_offset + data_size()); | |
| 255 dest->set_frames(dest->frames() + frame_count()); | |
| 256 return; | |
| 257 } | |
| 258 | |
| 208 DCHECK_LE(dest_frame_offset + frames_to_copy, dest->frames()); | 259 DCHECK_LE(dest_frame_offset + frames_to_copy, dest->frames()); |
| 209 | 260 |
| 210 if (!data_) { | 261 if (!data_) { |
| 211 // Special case for an empty buffer. | 262 // Special case for an empty buffer. |
| 212 dest->ZeroFramesPartial(dest_frame_offset, frames_to_copy); | 263 dest->ZeroFramesPartial(dest_frame_offset, frames_to_copy); |
| 213 return; | 264 return; |
| 214 } | 265 } |
| 215 | 266 |
| 216 if (sample_format_ == kSampleFormatPlanarF32) { | 267 if (sample_format_ == kSampleFormatPlanarF32) { |
| 217 // Format is planar float32. Copy the data from each channel as a block. | 268 // Format is planar float32. Copy the data from each channel as a block. |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 262 int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format_); | 313 int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format_); |
| 263 int frame_size = channel_count_ * bytes_per_channel; | 314 int frame_size = channel_count_ * bytes_per_channel; |
| 264 const uint8_t* source_data = data_.get() + source_frame_offset * frame_size; | 315 const uint8_t* source_data = data_.get() + source_frame_offset * frame_size; |
| 265 dest->FromInterleavedPartial(source_data, dest_frame_offset, frames_to_copy, | 316 dest->FromInterleavedPartial(source_data, dest_frame_offset, frames_to_copy, |
| 266 bytes_per_channel); | 317 bytes_per_channel); |
| 267 } | 318 } |
| 268 | 319 |
| 269 void AudioBuffer::TrimStart(int frames_to_trim) { | 320 void AudioBuffer::TrimStart(int frames_to_trim) { |
| 270 CHECK_GE(frames_to_trim, 0); | 321 CHECK_GE(frames_to_trim, 0); |
| 271 CHECK_LE(frames_to_trim, adjusted_frame_count_); | 322 CHECK_LE(frames_to_trim, adjusted_frame_count_); |
| 323 DCHECK(!IsBitstream(sample_format_)); | |
|
chcunningham
2017/05/05 01:14:11
These methods are called in frame_processor as par
AndyWu
2017/05/06 01:46:48
Done. However, we really should prevent trimming c
chcunningham
2017/05/08 20:01:02
They current MediaSource API doesn't really afford
| |
| 272 | 324 |
| 273 TrimRange(0, frames_to_trim); | 325 TrimRange(0, frames_to_trim); |
| 274 } | 326 } |
| 275 | 327 |
| 276 void AudioBuffer::TrimEnd(int frames_to_trim) { | 328 void AudioBuffer::TrimEnd(int frames_to_trim) { |
| 277 CHECK_GE(frames_to_trim, 0); | 329 CHECK_GE(frames_to_trim, 0); |
| 278 CHECK_LE(frames_to_trim, adjusted_frame_count_); | 330 CHECK_LE(frames_to_trim, adjusted_frame_count_); |
| 331 DCHECK(!IsBitstream(sample_format_)); | |
| 279 | 332 |
| 280 // Adjust the number of frames and duration for this buffer. | 333 // Adjust the number of frames and duration for this buffer. |
| 281 adjusted_frame_count_ -= frames_to_trim; | 334 adjusted_frame_count_ -= frames_to_trim; |
| 282 duration_ = CalculateDuration(adjusted_frame_count_, sample_rate_); | 335 duration_ = CalculateDuration(adjusted_frame_count_, sample_rate_); |
| 283 } | 336 } |
| 284 | 337 |
| 285 void AudioBuffer::TrimRange(int start, int end) { | 338 void AudioBuffer::TrimRange(int start, int end) { |
| 286 CHECK_GE(start, 0); | 339 CHECK_GE(start, 0); |
| 287 CHECK_LE(end, adjusted_frame_count_); | 340 CHECK_LE(end, adjusted_frame_count_); |
| 341 DCHECK(!IsBitstream(sample_format_)); | |
| 288 | 342 |
| 289 const int frames_to_trim = end - start; | 343 const int frames_to_trim = end - start; |
| 290 CHECK_GE(frames_to_trim, 0); | 344 CHECK_GE(frames_to_trim, 0); |
| 291 CHECK_LE(frames_to_trim, adjusted_frame_count_); | 345 CHECK_LE(frames_to_trim, adjusted_frame_count_); |
| 292 | 346 |
| 293 const int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format_); | 347 const int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format_); |
| 294 const int frames_to_copy = adjusted_frame_count_ - end; | 348 const int frames_to_copy = adjusted_frame_count_ - end; |
| 295 if (frames_to_copy > 0) { | 349 if (frames_to_copy > 0) { |
| 296 switch (sample_format_) { | 350 switch (sample_format_) { |
| 297 case kSampleFormatPlanarS16: | 351 case kSampleFormatPlanarS16: |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 323 } | 377 } |
| 324 } else { | 378 } else { |
| 325 CHECK_EQ(frames_to_copy, 0); | 379 CHECK_EQ(frames_to_copy, 0); |
| 326 } | 380 } |
| 327 | 381 |
| 328 // Trim the leftover data off the end of the buffer and update duration. | 382 // Trim the leftover data off the end of the buffer and update duration. |
| 329 TrimEnd(frames_to_trim); | 383 TrimEnd(frames_to_trim); |
| 330 } | 384 } |
| 331 | 385 |
| 332 } // namespace media | 386 } // namespace media |
| OLD | NEW |