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 AudioBuffer::AudioBuffer(SampleFormat sample_format, | 22 AudioBuffer::AudioBuffer(SampleFormat sample_format, |
| 23 ChannelLayout channel_layout, | 23 ChannelLayout channel_layout, |
| 24 int channel_count, | 24 int channel_count, |
| 25 int sample_rate, | 25 int sample_rate, |
| 26 int frame_count, | 26 int frame_count, |
| 27 bool create_buffer, | 27 bool create_buffer, |
| 28 const uint8_t* const* data, | 28 const uint8_t* const* data, |
| 29 size_t data_size, | |
| 29 const base::TimeDelta timestamp) | 30 const base::TimeDelta timestamp) |
| 30 : sample_format_(sample_format), | 31 : sample_format_(sample_format), |
| 31 channel_layout_(channel_layout), | 32 channel_layout_(channel_layout), |
| 32 channel_count_(channel_count), | 33 channel_count_(channel_count), |
| 33 sample_rate_(sample_rate), | 34 sample_rate_(sample_rate), |
| 34 adjusted_frame_count_(frame_count), | 35 adjusted_frame_count_(frame_count), |
| 35 end_of_stream_(!create_buffer && data == NULL && frame_count == 0), | 36 end_of_stream_(!create_buffer && data == NULL && frame_count == 0), |
| 36 timestamp_(timestamp), | 37 timestamp_(timestamp), |
| 37 duration_(end_of_stream_ | 38 duration_(end_of_stream_ |
| 38 ? base::TimeDelta() | 39 ? base::TimeDelta() |
| 39 : CalculateDuration(adjusted_frame_count_, sample_rate_)), | 40 : CalculateDuration(adjusted_frame_count_, sample_rate_)), |
| 40 data_size_(0) { | 41 data_size_(data_size) { |
| 41 CHECK_GE(channel_count_, 0); | 42 CHECK_GE(channel_count_, 0); |
| 42 CHECK_LE(channel_count_, limits::kMaxChannels); | 43 CHECK_LE(channel_count_, limits::kMaxChannels); |
| 43 CHECK_GE(frame_count, 0); | 44 CHECK_GE(frame_count, 0); |
| 44 DCHECK(channel_layout == CHANNEL_LAYOUT_DISCRETE || | 45 DCHECK(channel_layout == CHANNEL_LAYOUT_DISCRETE || |
| 45 ChannelLayoutToChannelCount(channel_layout) == channel_count); | 46 ChannelLayoutToChannelCount(channel_layout) == channel_count); |
| 46 | 47 |
| 47 int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format); | 48 int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format); |
| 48 DCHECK_LE(bytes_per_channel, kChannelAlignment); | 49 DCHECK_LE(bytes_per_channel, kChannelAlignment); |
| 49 | 50 |
| 50 // Empty buffer? | 51 // Empty buffer? |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 72 if (data) | 73 if (data) |
| 73 memcpy(channel_data_[i], data[i], data_size_per_channel); | 74 memcpy(channel_data_[i], data[i], data_size_per_channel); |
| 74 } | 75 } |
| 75 return; | 76 return; |
| 76 } | 77 } |
| 77 | 78 |
| 78 // Remaining formats are interleaved data. | 79 // Remaining formats are interleaved data. |
| 79 DCHECK(IsInterleaved(sample_format)) << sample_format_; | 80 DCHECK(IsInterleaved(sample_format)) << sample_format_; |
| 80 // Allocate our own buffer and copy the supplied data into it. Buffer must | 81 // Allocate our own buffer and copy the supplied data into it. Buffer must |
| 81 // contain the data for all channels. | 82 // contain the data for all channels. |
| 82 data_size_ = data_size_per_channel * channel_count_; | 83 if (!IsBitstream(sample_format)) |
|
chcunningham
2016/12/16 22:03:14
I feel like the interleaved code path is the only
AndyWu
2017/05/02 23:41:03
I do make (E)AC3 as interleaved formats:
https://c
| |
| 84 data_size_ = data_size_per_channel * channel_count_; | |
| 83 data_.reset( | 85 data_.reset( |
| 84 static_cast<uint8_t*>(base::AlignedAlloc(data_size_, kChannelAlignment))); | 86 static_cast<uint8_t*>(base::AlignedAlloc(data_size_, kChannelAlignment))); |
| 85 channel_data_.reserve(1); | 87 channel_data_.reserve(1); |
| 86 channel_data_.push_back(data_.get()); | 88 channel_data_.push_back(data_.get()); |
| 87 if (data) | 89 if (data) |
| 88 memcpy(data_.get(), data[0], data_size_); | 90 memcpy(data_.get(), data[0], data_size_); |
| 89 } | 91 } |
| 90 | 92 |
| 91 AudioBuffer::~AudioBuffer() {} | 93 AudioBuffer::~AudioBuffer() {} |
| 92 | 94 |
| 93 // static | 95 // static |
| 94 scoped_refptr<AudioBuffer> AudioBuffer::CopyFrom( | 96 scoped_refptr<AudioBuffer> AudioBuffer::CopyFrom( |
| 95 SampleFormat sample_format, | 97 SampleFormat sample_format, |
| 96 ChannelLayout channel_layout, | 98 ChannelLayout channel_layout, |
| 97 int channel_count, | 99 int channel_count, |
| 98 int sample_rate, | 100 int sample_rate, |
| 99 int frame_count, | 101 int frame_count, |
| 100 const uint8_t* const* data, | 102 const uint8_t* const* data, |
| 101 const base::TimeDelta timestamp) { | 103 const base::TimeDelta timestamp) { |
| 102 // If you hit this CHECK you likely have a bug in a demuxer. Go fix it. | 104 // 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. | 105 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer. |
| 104 CHECK(data[0]); | 106 CHECK(data[0]); |
| 105 return make_scoped_refptr(new AudioBuffer(sample_format, | 107 return make_scoped_refptr( |
| 106 channel_layout, | 108 new AudioBuffer(sample_format, channel_layout, channel_count, sample_rate, |
| 107 channel_count, | 109 frame_count, true, data, 0, timestamp)); |
| 108 sample_rate, | |
| 109 frame_count, | |
| 110 true, | |
| 111 data, | |
| 112 timestamp)); | |
| 113 } | 110 } |
| 114 | 111 |
| 115 // static | 112 // static |
| 113 scoped_refptr<AudioBuffer> AudioBuffer::CopyBitstreamFrom( | |
| 114 SampleFormat sample_format, | |
| 115 ChannelLayout channel_layout, | |
| 116 int channel_count, | |
| 117 int sample_rate, | |
| 118 int frame_count, | |
| 119 const uint8_t* const* data, | |
| 120 const size_t data_size, | |
| 121 const base::TimeDelta timestamp) { | |
| 122 // If you hit this CHECK you likely have a bug in a demuxer. Go fix it. | |
| 123 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer. | |
| 124 CHECK(data[0]); | |
|
chcunningham
2016/12/16 22:03:14
Are we confident that data[0] would never return 0
AndyWu
2017/05/02 23:41:03
data[0] is a pointer; null pointer is unexpected.
| |
| 125 return make_scoped_refptr( | |
| 126 new AudioBuffer(sample_format, channel_layout, channel_count, sample_rate, | |
| 127 frame_count, true, data, data_size, timestamp)); | |
| 128 } | |
| 129 | |
| 130 // static | |
| 116 scoped_refptr<AudioBuffer> AudioBuffer::CreateBuffer( | 131 scoped_refptr<AudioBuffer> AudioBuffer::CreateBuffer( |
| 117 SampleFormat sample_format, | 132 SampleFormat sample_format, |
| 118 ChannelLayout channel_layout, | 133 ChannelLayout channel_layout, |
| 119 int channel_count, | 134 int channel_count, |
| 120 int sample_rate, | 135 int sample_rate, |
| 121 int frame_count) { | 136 int frame_count) { |
| 122 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer. | 137 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer. |
| 123 return make_scoped_refptr( | 138 return make_scoped_refptr( |
| 124 new AudioBuffer(sample_format, channel_layout, channel_count, sample_rate, | 139 new AudioBuffer(sample_format, channel_layout, channel_count, sample_rate, |
| 125 frame_count, true, NULL, kNoTimestamp)); | 140 frame_count, true, NULL, 0, kNoTimestamp)); |
| 126 } | 141 } |
| 127 | 142 |
| 128 // static | 143 // static |
| 144 scoped_refptr<AudioBuffer> AudioBuffer::CreateBitstreamBuffer( | |
| 145 SampleFormat sample_format, | |
| 146 ChannelLayout channel_layout, | |
| 147 int channel_count, | |
| 148 int sample_rate, | |
| 149 int frame_count, | |
| 150 size_t data_size) { | |
| 151 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer. | |
| 152 return make_scoped_refptr( | |
| 153 new AudioBuffer(sample_format, channel_layout, channel_count, sample_rate, | |
| 154 frame_count, true, NULL, data_size, kNoTimestamp)); | |
| 155 } | |
| 156 | |
| 157 // static | |
| 129 scoped_refptr<AudioBuffer> AudioBuffer::CreateEmptyBuffer( | 158 scoped_refptr<AudioBuffer> AudioBuffer::CreateEmptyBuffer( |
| 130 ChannelLayout channel_layout, | 159 ChannelLayout channel_layout, |
| 131 int channel_count, | 160 int channel_count, |
| 132 int sample_rate, | 161 int sample_rate, |
| 133 int frame_count, | 162 int frame_count, |
| 134 const base::TimeDelta timestamp) { | 163 const base::TimeDelta timestamp) { |
| 135 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer. | 164 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer. |
| 136 // Since data == NULL, format doesn't matter. | 165 // Since data == NULL, format doesn't matter. |
| 137 return make_scoped_refptr(new AudioBuffer(kSampleFormatF32, | 166 return make_scoped_refptr( |
| 138 channel_layout, | 167 new AudioBuffer(kSampleFormatF32, channel_layout, channel_count, |
| 139 channel_count, | 168 sample_rate, frame_count, false, NULL, 0, timestamp)); |
| 140 sample_rate, | |
| 141 frame_count, | |
| 142 false, | |
| 143 NULL, | |
| 144 timestamp)); | |
| 145 } | 169 } |
| 146 | 170 |
| 147 // static | 171 // static |
| 148 scoped_refptr<AudioBuffer> AudioBuffer::CreateEOSBuffer() { | 172 scoped_refptr<AudioBuffer> AudioBuffer::CreateEOSBuffer() { |
| 149 return make_scoped_refptr(new AudioBuffer(kUnknownSampleFormat, | 173 return make_scoped_refptr(new AudioBuffer(kUnknownSampleFormat, |
| 150 CHANNEL_LAYOUT_NONE, 0, 0, 0, false, | 174 CHANNEL_LAYOUT_NONE, 0, 0, 0, false, |
| 151 NULL, kNoTimestamp)); | 175 NULL, 0, kNoTimestamp)); |
| 152 } | 176 } |
| 153 | 177 |
| 154 // Convert int16_t values in the range [INT16_MIN, INT16_MAX] to [-1.0, 1.0]. | 178 // Convert int16_t values in the range [INT16_MIN, INT16_MAX] to [-1.0, 1.0]. |
| 155 inline float ConvertSample(int16_t value) { | 179 inline float ConvertSample(int16_t value) { |
| 156 return value * (value < 0 ? -1.0f / std::numeric_limits<int16_t>::min() | 180 return value * (value < 0 ? -1.0f / std::numeric_limits<int16_t>::min() |
| 157 : 1.0f / std::numeric_limits<int16_t>::max()); | 181 : 1.0f / std::numeric_limits<int16_t>::max()); |
| 158 } | 182 } |
| 159 | 183 |
| 160 void AudioBuffer::AdjustSampleRate(int sample_rate) { | 184 void AudioBuffer::AdjustSampleRate(int sample_rate) { |
| 161 DCHECK(!end_of_stream_); | 185 DCHECK(!end_of_stream_); |
| 162 sample_rate_ = sample_rate; | 186 sample_rate_ = sample_rate; |
| 163 duration_ = CalculateDuration(adjusted_frame_count_, sample_rate_); | 187 duration_ = CalculateDuration(adjusted_frame_count_, sample_rate_); |
| 164 } | 188 } |
| 165 | 189 |
| 166 void AudioBuffer::ReadFrames(int frames_to_copy, | 190 void AudioBuffer::ReadFrames(int frames_to_copy, |
| 167 int source_frame_offset, | 191 int source_frame_offset, |
| 168 int dest_frame_offset, | 192 int dest_frame_offset, |
| 169 AudioBus* dest) { | 193 AudioBus* dest) { |
| 170 // Deinterleave each channel (if necessary) and convert to 32bit | 194 // Deinterleave each channel (if necessary) and convert to 32bit |
| 171 // floating-point with nominal range -1.0 -> +1.0 (if necessary). | 195 // floating-point with nominal range -1.0 -> +1.0 (if necessary). |
| 172 | 196 |
| 173 // |dest| must have the same number of channels, and the number of frames | 197 // |dest| must have the same number of channels, and the number of frames |
| 174 // specified must be in range. | 198 // specified must be in range. |
| 175 DCHECK(!end_of_stream()); | 199 DCHECK(!end_of_stream()); |
| 176 DCHECK_EQ(dest->channels(), channel_count_); | 200 DCHECK_EQ(dest->channels(), channel_count_); |
| 177 DCHECK_LE(source_frame_offset + frames_to_copy, adjusted_frame_count_); | 201 DCHECK_LE(source_frame_offset + frames_to_copy, adjusted_frame_count_); |
| 202 | |
| 203 const bool is_bitstream_format = IsBitstream(sample_format_); | |
| 204 | |
| 205 if (is_bitstream_format) { | |
| 206 // TODO(tsunghung): Implement it along with AudioBus changes. | |
| 207 NOTREACHED() << "Invalid sample format!"; | |
| 208 } | |
| 209 | |
| 178 DCHECK_LE(dest_frame_offset + frames_to_copy, dest->frames()); | 210 DCHECK_LE(dest_frame_offset + frames_to_copy, dest->frames()); |
| 179 | 211 |
| 180 if (!data_) { | 212 if (!data_) { |
| 181 // Special case for an empty buffer. | 213 // Special case for an empty buffer. |
| 182 dest->ZeroFramesPartial(dest_frame_offset, frames_to_copy); | 214 dest->ZeroFramesPartial(dest_frame_offset, frames_to_copy); |
| 183 return; | 215 return; |
| 184 } | 216 } |
| 185 | 217 |
| 186 if (sample_format_ == kSampleFormatPlanarF32) { | 218 if (sample_format_ == kSampleFormatPlanarF32) { |
| 187 // Format is planar float32. Copy the data from each channel as a block. | 219 // Format is planar float32. Copy the data from each channel as a block. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 233 int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format_); | 265 int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format_); |
| 234 int frame_size = channel_count_ * bytes_per_channel; | 266 int frame_size = channel_count_ * bytes_per_channel; |
| 235 const uint8_t* source_data = data_.get() + source_frame_offset * frame_size; | 267 const uint8_t* source_data = data_.get() + source_frame_offset * frame_size; |
| 236 dest->FromInterleavedPartial( | 268 dest->FromInterleavedPartial( |
| 237 source_data, dest_frame_offset, frames_to_copy, bytes_per_channel); | 269 source_data, dest_frame_offset, frames_to_copy, bytes_per_channel); |
| 238 } | 270 } |
| 239 | 271 |
| 240 void AudioBuffer::TrimStart(int frames_to_trim) { | 272 void AudioBuffer::TrimStart(int frames_to_trim) { |
| 241 CHECK_GE(frames_to_trim, 0); | 273 CHECK_GE(frames_to_trim, 0); |
| 242 CHECK_LE(frames_to_trim, adjusted_frame_count_); | 274 CHECK_LE(frames_to_trim, adjusted_frame_count_); |
| 275 DCHECK(!IsBitstream(sample_format_)); | |
| 243 | 276 |
| 244 TrimRange(0, frames_to_trim); | 277 TrimRange(0, frames_to_trim); |
| 245 } | 278 } |
| 246 | 279 |
| 247 void AudioBuffer::TrimEnd(int frames_to_trim) { | 280 void AudioBuffer::TrimEnd(int frames_to_trim) { |
| 248 CHECK_GE(frames_to_trim, 0); | 281 CHECK_GE(frames_to_trim, 0); |
| 249 CHECK_LE(frames_to_trim, adjusted_frame_count_); | 282 CHECK_LE(frames_to_trim, adjusted_frame_count_); |
| 283 DCHECK(!IsBitstream(sample_format_)); | |
| 250 | 284 |
| 251 // Adjust the number of frames and duration for this buffer. | 285 // Adjust the number of frames and duration for this buffer. |
| 252 adjusted_frame_count_ -= frames_to_trim; | 286 adjusted_frame_count_ -= frames_to_trim; |
| 253 duration_ = CalculateDuration(adjusted_frame_count_, sample_rate_); | 287 duration_ = CalculateDuration(adjusted_frame_count_, sample_rate_); |
| 254 } | 288 } |
| 255 | 289 |
| 256 void AudioBuffer::TrimRange(int start, int end) { | 290 void AudioBuffer::TrimRange(int start, int end) { |
| 257 CHECK_GE(start, 0); | 291 CHECK_GE(start, 0); |
| 258 CHECK_LE(end, adjusted_frame_count_); | 292 CHECK_LE(end, adjusted_frame_count_); |
| 293 DCHECK(!IsBitstream(sample_format_)); | |
| 259 | 294 |
| 260 const int frames_to_trim = end - start; | 295 const int frames_to_trim = end - start; |
| 261 CHECK_GE(frames_to_trim, 0); | 296 CHECK_GE(frames_to_trim, 0); |
| 262 CHECK_LE(frames_to_trim, adjusted_frame_count_); | 297 CHECK_LE(frames_to_trim, adjusted_frame_count_); |
| 263 | 298 |
| 264 const int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format_); | 299 const int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format_); |
| 265 const int frames_to_copy = adjusted_frame_count_ - end; | 300 const int frames_to_copy = adjusted_frame_count_ - end; |
| 266 if (frames_to_copy > 0) { | 301 if (frames_to_copy > 0) { |
| 267 switch (sample_format_) { | 302 switch (sample_format_) { |
| 268 case kSampleFormatPlanarS16: | 303 case kSampleFormatPlanarS16: |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 294 } | 329 } |
| 295 } else { | 330 } else { |
| 296 CHECK_EQ(frames_to_copy, 0); | 331 CHECK_EQ(frames_to_copy, 0); |
| 297 } | 332 } |
| 298 | 333 |
| 299 // Trim the leftover data off the end of the buffer and update duration. | 334 // Trim the leftover data off the end of the buffer and update duration. |
| 300 TrimEnd(frames_to_trim); | 335 TrimEnd(frames_to_trim); |
| 301 } | 336 } |
| 302 | 337 |
| 303 } // namespace media | 338 } // namespace media |
| OLD | NEW |