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? |
| 51 if (!create_buffer) | 52 if (!create_buffer) |
| 52 return; | 53 return; |
| 53 | 54 |
| 55 if (sample_format == kSampleFormatRaw) { | |
|
AndyWu
2016/11/04 18:04:24
I refactored the code a little to avoid code dupli
| |
| 56 if (data_size_) { | |
| 57 data_.reset(static_cast<uint8_t*>( | |
| 58 base::AlignedAlloc(data_size_, kChannelAlignment))); | |
|
DaleCurtis
2016/11/01 23:05:13
AlignedAlloc shouldn't be necessary in this case.
AndyWu
2016/11/04 18:04:24
|data_| is defined as:
std::unique_ptr<uint8_t, ba
| |
| 59 channel_data_.reserve(1); | |
|
DaleCurtis
2016/11/01 23:05:13
Just channel_data_ = std::vector(1, data_.get()) ?
AndyWu
2016/11/04 18:04:24
Yes, it should work. It's better in terms of line
| |
| 60 channel_data_.push_back(data_.get()); | |
| 61 if (data) | |
|
DaleCurtis
2016/11/01 23:05:13
This should never be null now right?
AndyWu
2016/11/04 18:04:24
In current use cases, yes. But I would prefer to k
| |
| 62 memcpy(data_.get(), data[0], data_size_); | |
| 63 } | |
| 64 return; | |
| 65 } | |
| 66 | |
| 54 int data_size_per_channel = frame_count * bytes_per_channel; | 67 int data_size_per_channel = frame_count * bytes_per_channel; |
| 55 if (IsPlanar(sample_format)) { | 68 if (IsPlanar(sample_format)) { |
| 56 // Planar data, so need to allocate buffer for each channel. | 69 // Planar data, so need to allocate buffer for each channel. |
| 57 // Determine per channel data size, taking into account alignment. | 70 // Determine per channel data size, taking into account alignment. |
| 58 int block_size_per_channel = | 71 int block_size_per_channel = |
| 59 (data_size_per_channel + kChannelAlignment - 1) & | 72 (data_size_per_channel + kChannelAlignment - 1) & |
| 60 ~(kChannelAlignment - 1); | 73 ~(kChannelAlignment - 1); |
| 61 DCHECK_GE(block_size_per_channel, data_size_per_channel); | 74 DCHECK_GE(block_size_per_channel, data_size_per_channel); |
| 62 | 75 |
| 63 // Allocate a contiguous buffer for all the channel data. | 76 // Allocate a contiguous buffer for all the channel data. |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 91 AudioBuffer::~AudioBuffer() {} | 104 AudioBuffer::~AudioBuffer() {} |
| 92 | 105 |
| 93 // static | 106 // static |
| 94 scoped_refptr<AudioBuffer> AudioBuffer::CopyFrom( | 107 scoped_refptr<AudioBuffer> AudioBuffer::CopyFrom( |
| 95 SampleFormat sample_format, | 108 SampleFormat sample_format, |
| 96 ChannelLayout channel_layout, | 109 ChannelLayout channel_layout, |
| 97 int channel_count, | 110 int channel_count, |
| 98 int sample_rate, | 111 int sample_rate, |
| 99 int frame_count, | 112 int frame_count, |
| 100 const uint8_t* const* data, | 113 const uint8_t* const* data, |
| 101 const base::TimeDelta timestamp) { | 114 const base::TimeDelta timestamp, |
| 115 const size_t data_size) { | |
|
DaleCurtis
2016/11/01 23:05:13
Instead of adding this, if you specify the appropr
AndyWu
2016/11/04 18:04:24
I see your point, but it would also introduce anot
DaleCurtis
2016/11/04 19:48:29
Hmm, I guess you're saying that we don't always en
DaleCurtis
2016/11/04 21:17:33
Actually, why can't you just define these sample f
AndyWu
2016/11/08 00:04:21
The |data_size_| calculation is based on
https://c
| |
| 102 // If you hit this CHECK you likely have a bug in a demuxer. Go fix it. | 116 // 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. | 117 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer. |
| 104 CHECK(data[0]); | 118 CHECK(data[0]); |
| 105 return make_scoped_refptr(new AudioBuffer(sample_format, | 119 return make_scoped_refptr( |
| 106 channel_layout, | 120 new AudioBuffer(sample_format, channel_layout, channel_count, sample_rate, |
| 107 channel_count, | 121 frame_count, true, data, data_size, timestamp)); |
| 108 sample_rate, | |
| 109 frame_count, | |
| 110 true, | |
| 111 data, | |
| 112 timestamp)); | |
| 113 } | 122 } |
| 114 | 123 |
| 115 // static | 124 // static |
| 116 scoped_refptr<AudioBuffer> AudioBuffer::CreateBuffer( | 125 scoped_refptr<AudioBuffer> AudioBuffer::CreateBuffer( |
| 117 SampleFormat sample_format, | 126 SampleFormat sample_format, |
| 118 ChannelLayout channel_layout, | 127 ChannelLayout channel_layout, |
| 119 int channel_count, | 128 int channel_count, |
| 120 int sample_rate, | 129 int sample_rate, |
| 121 int frame_count) { | 130 int frame_count, |
| 131 size_t data_size) { | |
| 122 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer. | 132 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer. |
| 123 return make_scoped_refptr( | 133 return make_scoped_refptr( |
| 124 new AudioBuffer(sample_format, channel_layout, channel_count, sample_rate, | 134 new AudioBuffer(sample_format, channel_layout, channel_count, sample_rate, |
| 125 frame_count, true, NULL, kNoTimestamp)); | 135 frame_count, true, NULL, data_size, kNoTimestamp)); |
| 126 } | 136 } |
| 127 | 137 |
| 128 // static | 138 // static |
| 129 scoped_refptr<AudioBuffer> AudioBuffer::CreateEmptyBuffer( | 139 scoped_refptr<AudioBuffer> AudioBuffer::CreateEmptyBuffer( |
| 130 ChannelLayout channel_layout, | 140 ChannelLayout channel_layout, |
| 131 int channel_count, | 141 int channel_count, |
| 132 int sample_rate, | 142 int sample_rate, |
| 133 int frame_count, | 143 int frame_count, |
| 134 const base::TimeDelta timestamp) { | 144 const base::TimeDelta timestamp) { |
| 135 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer. | 145 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer. |
| 136 // Since data == NULL, format doesn't matter. | 146 // Since data == NULL, format doesn't matter. |
| 137 return make_scoped_refptr(new AudioBuffer(kSampleFormatF32, | 147 return make_scoped_refptr( |
| 138 channel_layout, | 148 new AudioBuffer(kSampleFormatF32, channel_layout, channel_count, |
| 139 channel_count, | 149 sample_rate, frame_count, false, NULL, 0, timestamp)); |
| 140 sample_rate, | |
| 141 frame_count, | |
| 142 false, | |
| 143 NULL, | |
| 144 timestamp)); | |
| 145 } | 150 } |
| 146 | 151 |
| 147 // static | 152 // static |
| 148 scoped_refptr<AudioBuffer> AudioBuffer::CreateEOSBuffer() { | 153 scoped_refptr<AudioBuffer> AudioBuffer::CreateEOSBuffer() { |
| 149 return make_scoped_refptr(new AudioBuffer(kUnknownSampleFormat, | 154 return make_scoped_refptr(new AudioBuffer(kUnknownSampleFormat, |
| 150 CHANNEL_LAYOUT_NONE, 0, 0, 0, false, | 155 CHANNEL_LAYOUT_NONE, 0, 0, 0, false, |
| 151 NULL, kNoTimestamp)); | 156 NULL, 0, kNoTimestamp)); |
| 152 } | 157 } |
| 153 | 158 |
| 154 // Convert int16_t values in the range [INT16_MIN, INT16_MAX] to [-1.0, 1.0]. | 159 // Convert int16_t values in the range [INT16_MIN, INT16_MAX] to [-1.0, 1.0]. |
| 155 inline float ConvertSample(int16_t value) { | 160 inline float ConvertSample(int16_t value) { |
| 156 return value * (value < 0 ? -1.0f / std::numeric_limits<int16_t>::min() | 161 return value * (value < 0 ? -1.0f / std::numeric_limits<int16_t>::min() |
| 157 : 1.0f / std::numeric_limits<int16_t>::max()); | 162 : 1.0f / std::numeric_limits<int16_t>::max()); |
| 158 } | 163 } |
| 159 | 164 |
| 160 void AudioBuffer::AdjustSampleRate(int sample_rate) { | 165 void AudioBuffer::AdjustSampleRate(int sample_rate) { |
| 161 DCHECK(!end_of_stream_); | 166 DCHECK(!end_of_stream_); |
| 162 sample_rate_ = sample_rate; | 167 sample_rate_ = sample_rate; |
| 163 duration_ = CalculateDuration(adjusted_frame_count_, sample_rate_); | 168 duration_ = CalculateDuration(adjusted_frame_count_, sample_rate_); |
| 164 } | 169 } |
| 165 | 170 |
| 166 void AudioBuffer::ReadFrames(int frames_to_copy, | 171 void AudioBuffer::ReadFrames(int frames_to_copy, |
| 167 int source_frame_offset, | 172 int source_frame_offset, |
| 168 int dest_frame_offset, | 173 int dest_frame_offset, |
| 169 AudioBus* dest) { | 174 AudioBus* dest) { |
| 170 // Deinterleave each channel (if necessary) and convert to 32bit | 175 // Deinterleave each channel (if necessary) and convert to 32bit |
| 171 // floating-point with nominal range -1.0 -> +1.0 (if necessary). | 176 // floating-point with nominal range -1.0 -> +1.0 (if necessary). |
| 172 | 177 |
| 173 // |dest| must have the same number of channels, and the number of frames | 178 // |dest| must have the same number of channels, and the number of frames |
| 174 // specified must be in range. | 179 // specified must be in range. |
| 175 DCHECK(!end_of_stream()); | 180 DCHECK(!end_of_stream()); |
| 176 DCHECK_EQ(dest->channels(), channel_count_); | 181 DCHECK_EQ(dest->channels(), channel_count_); |
| 177 DCHECK_LE(source_frame_offset + frames_to_copy, adjusted_frame_count_); | 182 DCHECK_LE(source_frame_offset + frames_to_copy, adjusted_frame_count_); |
| 183 | |
| 184 bool is_raw_format = (sample_format_ == kSampleFormatRaw); | |
| 185 dest->set_is_raw_format(is_raw_format); | |
| 186 | |
| 187 if (is_raw_format) { | |
| 188 DCHECK(!source_frame_offset); | |
| 189 uint8_t* dest_data = | |
| 190 reinterpret_cast<uint8_t*>(dest->channel(0)) + dest->data_size(); | |
| 191 | |
| 192 memcpy(dest_data, channel_data_[0], data_size()); | |
| 193 dest->set_data_size(dest_frame_offset + data_size()); | |
| 194 dest->set_frames(dest->frames() + frame_count()); | |
| 195 return; | |
| 196 } | |
| 197 | |
| 178 DCHECK_LE(dest_frame_offset + frames_to_copy, dest->frames()); | 198 DCHECK_LE(dest_frame_offset + frames_to_copy, dest->frames()); |
| 179 | 199 |
| 180 if (!data_) { | 200 if (!data_) { |
| 181 // Special case for an empty buffer. | 201 // Special case for an empty buffer. |
| 182 dest->ZeroFramesPartial(dest_frame_offset, frames_to_copy); | 202 dest->ZeroFramesPartial(dest_frame_offset, frames_to_copy); |
| 183 return; | 203 return; |
| 184 } | 204 } |
| 185 | 205 |
| 186 if (sample_format_ == kSampleFormatPlanarF32) { | 206 if (sample_format_ == kSampleFormatPlanarF32) { |
| 187 // Format is planar float32. Copy the data from each channel as a block. | 207 // Format is planar float32. Copy the data from each channel as a block. |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 280 case kSampleFormatS24: | 300 case kSampleFormatS24: |
| 281 case kSampleFormatS32: | 301 case kSampleFormatS32: |
| 282 case kSampleFormatF32: { | 302 case kSampleFormatF32: { |
| 283 // Interleaved data can be shifted all at once. | 303 // Interleaved data can be shifted all at once. |
| 284 const int frame_size = channel_count_ * bytes_per_channel; | 304 const int frame_size = channel_count_ * bytes_per_channel; |
| 285 memmove(channel_data_[0] + start * frame_size, | 305 memmove(channel_data_[0] + start * frame_size, |
| 286 channel_data_[0] + end * frame_size, | 306 channel_data_[0] + end * frame_size, |
| 287 frame_size * frames_to_copy); | 307 frame_size * frames_to_copy); |
| 288 break; | 308 break; |
| 289 } | 309 } |
| 310 case kSampleFormatRaw: | |
| 290 case kUnknownSampleFormat: | 311 case kUnknownSampleFormat: |
| 291 NOTREACHED() << "Invalid sample format!"; | 312 NOTREACHED() << "Invalid sample format!"; |
| 292 } | 313 } |
| 293 } else { | 314 } else { |
| 294 CHECK_EQ(frames_to_copy, 0); | 315 CHECK_EQ(frames_to_copy, 0); |
| 295 } | 316 } |
| 296 | 317 |
| 297 // Trim the leftover data off the end of the buffer and update duration. | 318 // Trim the leftover data off the end of the buffer and update duration. |
| 298 TrimEnd(frames_to_trim); | 319 TrimEnd(frames_to_trim); |
| 299 } | 320 } |
| 300 | 321 |
| 301 } // namespace media | 322 } // namespace media |
| OLD | NEW |