Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(156)

Side by Side Diff: media/base/audio_buffer.cc

Issue 2466463005: Support (E)AC3 passthrough
Patch Set: Improve CastMediaClient::IsSupportedPassthroughAudio() Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698