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

Side by Side Diff: chromecast/media/cma/backend/alsa/audio_decoder_alsa.cc

Issue 2557513002: [Chromecast] Add support for different playback rates to ALSA backend (Closed)
Patch Set: Created 4 years 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "chromecast/media/cma/backend/alsa/audio_decoder_alsa.h" 5 #include "chromecast/media/cma/backend/alsa/audio_decoder_alsa.h"
6 6
7 #include <time.h> 7 #include <time.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <limits> 10 #include <limits>
11 11
12 #include "base/callback_helpers.h" 12 #include "base/callback_helpers.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/macros.h" 14 #include "base/macros.h"
15 #include "base/trace_event/trace_event.h" 15 #include "base/trace_event/trace_event.h"
16 #include "chromecast/base/task_runner_impl.h" 16 #include "chromecast/base/task_runner_impl.h"
17 #include "chromecast/media/cma/backend/alsa/media_pipeline_backend_alsa.h" 17 #include "chromecast/media/cma/backend/alsa/media_pipeline_backend_alsa.h"
18 #include "chromecast/media/cma/base/decoder_buffer_adapter.h"
18 #include "chromecast/media/cma/base/decoder_buffer_base.h" 19 #include "chromecast/media/cma/base/decoder_buffer_base.h"
19 #include "chromecast/public/media/cast_decoder_buffer.h" 20 #include "chromecast/public/media/cast_decoder_buffer.h"
21 #include "media/base/audio_buffer.h"
22 #include "media/base/audio_bus.h"
23 #include "media/base/channel_layout.h"
24 #include "media/base/decoder_buffer.h"
25 #include "media/base/sample_format.h"
26 #include "media/filters/audio_renderer_algorithm.h"
20 27
21 #define TRACE_FUNCTION_ENTRY0() TRACE_EVENT0("cma", __FUNCTION__) 28 #define TRACE_FUNCTION_ENTRY0() TRACE_EVENT0("cma", __FUNCTION__)
22 29
23 #define TRACE_FUNCTION_ENTRY1(arg1) \ 30 #define TRACE_FUNCTION_ENTRY1(arg1) \
24 TRACE_EVENT1("cma", __FUNCTION__, #arg1, arg1) 31 TRACE_EVENT1("cma", __FUNCTION__, #arg1, arg1)
25 32
26 #define TRACE_FUNCTION_ENTRY2(arg1, arg2) \ 33 #define TRACE_FUNCTION_ENTRY2(arg1, arg2) \
27 TRACE_EVENT2("cma", __FUNCTION__, #arg1, arg1, #arg2, arg2) 34 TRACE_EVENT2("cma", __FUNCTION__, #arg1, arg1, #arg2, arg2)
28 35
29 namespace chromecast { 36 namespace chromecast {
30 namespace media { 37 namespace media {
31 38
32 namespace { 39 namespace {
33 40
41 const int kBitsPerSample = 32;
42 const int kDefaultFramesPerBuffer = 1024;
43 const int kSilenceBufferFrames = 2048;
44 const int kMaxOutputMs = 20;
45
46 const double kPlaybackRateEpsilon = 0.001;
47
34 const CastAudioDecoder::OutputFormat kDecoderSampleFormat = 48 const CastAudioDecoder::OutputFormat kDecoderSampleFormat =
35 CastAudioDecoder::kOutputPlanarFloat; 49 CastAudioDecoder::kOutputPlanarFloat;
36 50
37 const int64_t kInvalidDelayTimestamp = std::numeric_limits<int64_t>::min(); 51 const int64_t kInvalidTimestamp = std::numeric_limits<int64_t>::min();
38
39 AudioDecoderAlsa::RenderingDelay kInvalidRenderingDelay() {
40 AudioDecoderAlsa::RenderingDelay delay;
41 delay.timestamp_microseconds = kInvalidDelayTimestamp;
42 delay.delay_microseconds = 0;
43 return delay;
44 }
45 52
46 } // namespace 53 } // namespace
47 54
55 AudioDecoderAlsa::RateShifterInfo::RateShifterInfo(float playback_rate)
56 : rate(playback_rate), input_frames(0), output_frames(0) {}
57
48 AudioDecoderAlsa::AudioDecoderAlsa(MediaPipelineBackendAlsa* backend) 58 AudioDecoderAlsa::AudioDecoderAlsa(MediaPipelineBackendAlsa* backend)
49 : backend_(backend), 59 : backend_(backend),
50 task_runner_(backend->GetTaskRunner()), 60 task_runner_(backend->GetTaskRunner()),
51 delegate_(nullptr), 61 delegate_(nullptr),
52 is_eos_(false), 62 pending_write_pcm_(false),
63 pending_buffer_complete_(false),
64 got_eos_(false),
65 pushed_eos_(false),
53 error_(false), 66 error_(false),
67 rate_shifter_output_(
68 ::media::AudioBus::Create(2, kDefaultFramesPerBuffer)),
slan 2016/12/07 00:22:27 nit: Can we do "2 /* num_channels */" or kNumChann
kmackay 2016/12/07 22:59:57 Done.
69 current_pts_(kInvalidTimestamp),
70 pending_output_frames_(0),
54 volume_multiplier_(1.0f), 71 volume_multiplier_(1.0f),
55 weak_factory_(this) { 72 weak_factory_(this) {
56 TRACE_FUNCTION_ENTRY0(); 73 TRACE_FUNCTION_ENTRY0();
57 DCHECK(backend_); 74 DCHECK(backend_);
58 DCHECK(task_runner_.get()); 75 DCHECK(task_runner_.get());
59 DCHECK(task_runner_->BelongsToCurrentThread()); 76 DCHECK(task_runner_->BelongsToCurrentThread());
77 rate_shifter_info_.push_back(RateShifterInfo(1.0f));
slan 2016/12/07 00:22:27 Why do we need this call? The queue is cleared whe
kmackay 2016/12/07 22:59:57 We don't; removed
60 } 78 }
61 79
62 AudioDecoderAlsa::~AudioDecoderAlsa() { 80 AudioDecoderAlsa::~AudioDecoderAlsa() {
63 TRACE_FUNCTION_ENTRY0(); 81 TRACE_FUNCTION_ENTRY0();
64 DCHECK(task_runner_->BelongsToCurrentThread()); 82 DCHECK(task_runner_->BelongsToCurrentThread());
65 } 83 }
66 84
67 void AudioDecoderAlsa::SetDelegate( 85 void AudioDecoderAlsa::SetDelegate(
68 MediaPipelineBackend::Decoder::Delegate* delegate) { 86 MediaPipelineBackend::Decoder::Delegate* delegate) {
69 DCHECK(delegate); 87 DCHECK(delegate);
70 delegate_ = delegate; 88 delegate_ = delegate;
71 } 89 }
72 90
73 void AudioDecoderAlsa::Initialize() { 91 void AudioDecoderAlsa::Initialize() {
74 TRACE_FUNCTION_ENTRY0(); 92 TRACE_FUNCTION_ENTRY0();
75 DCHECK(delegate_); 93 DCHECK(delegate_);
76 stats_ = Statistics(); 94 stats_ = Statistics();
77 is_eos_ = false; 95 pending_write_pcm_ = false;
78 last_buffer_pts_ = std::numeric_limits<int64_t>::min(); 96 pending_buffer_complete_ = false;
97 got_eos_ = false;
98 pushed_eos_ = false;
99 current_pts_ = kInvalidTimestamp;
100 pending_output_frames_ = 0;
79 101
80 last_known_delay_.timestamp_microseconds = kInvalidDelayTimestamp; 102 last_known_delay_.timestamp_microseconds = kInvalidTimestamp;
81 last_known_delay_.delay_microseconds = 0; 103 last_known_delay_.delay_microseconds = 0;
82 } 104 }
83 105
84 bool AudioDecoderAlsa::Start(int64_t start_pts) { 106 bool AudioDecoderAlsa::Start(int64_t start_pts) {
85 TRACE_FUNCTION_ENTRY0(); 107 TRACE_FUNCTION_ENTRY0();
86 current_pts_ = start_pts; 108 current_pts_ = start_pts;
87 DCHECK(IsValidConfig(config_)); 109 DCHECK(IsValidConfig(config_));
88 mixer_input_.reset(new StreamMixerAlsaInput( 110 mixer_input_.reset(new StreamMixerAlsaInput(
89 this, config_.samples_per_second, backend_->Primary())); 111 this, config_.samples_per_second, backend_->Primary()));
90 mixer_input_->SetVolumeMultiplier(volume_multiplier_); 112 mixer_input_->SetVolumeMultiplier(volume_multiplier_);
91 // Create decoder_ if necessary. This can happen if Stop() was called, and 113 // Create decoder_ if necessary. This can happen if Stop() was called, and
92 // SetConfig() was not called since then. 114 // SetConfig() was not called since then.
93 if (!decoder_) 115 if (!decoder_) {
94 CreateDecoder(); 116 CreateDecoder();
117 }
118 if (!rate_shifter_) {
119 CreateRateShifter(config_.samples_per_second);
120 }
95 return true; 121 return true;
96 } 122 }
97 123
98 void AudioDecoderAlsa::Stop() { 124 void AudioDecoderAlsa::Stop() {
99 TRACE_FUNCTION_ENTRY0(); 125 TRACE_FUNCTION_ENTRY0();
100 decoder_.reset(); 126 decoder_.reset();
101 mixer_input_.reset(); 127 mixer_input_.reset();
128 rate_shifter_.reset();
129 weak_factory_.InvalidateWeakPtrs();
102 130
103 Initialize(); 131 Initialize();
104 } 132 }
105 133
106 bool AudioDecoderAlsa::Pause() { 134 bool AudioDecoderAlsa::Pause() {
107 TRACE_FUNCTION_ENTRY0(); 135 TRACE_FUNCTION_ENTRY0();
108 DCHECK(mixer_input_); 136 DCHECK(mixer_input_);
109 mixer_input_->SetPaused(true); 137 mixer_input_->SetPaused(true);
110 return true; 138 return true;
111 } 139 }
112 140
113 bool AudioDecoderAlsa::Resume() { 141 bool AudioDecoderAlsa::Resume() {
114 TRACE_FUNCTION_ENTRY0(); 142 TRACE_FUNCTION_ENTRY0();
115 DCHECK(mixer_input_); 143 DCHECK(mixer_input_);
116 mixer_input_->SetPaused(false); 144 mixer_input_->SetPaused(false);
117 return true; 145 return true;
118 } 146 }
119 147
148 bool AudioDecoderAlsa::SetPlaybackRate(float rate) {
149 if (std::abs(rate - 1.0) < kPlaybackRateEpsilon) {
slan 2016/12/07 00:22:27 Why this check? Are we worried about apps setting
kmackay 2016/12/07 22:59:57 AudioRendererAlgorithm treats values close to 1 as
150 rate = 1.0f;
151 }
152 LOG(INFO) << "SetPlaybackRate to " << rate;
153
154 while (!rate_shifter_info_.empty() &&
155 rate_shifter_info_.back().input_frames == 0) {
156 rate_shifter_info_.pop_back();
157 }
158 rate_shifter_info_.push_back(RateShifterInfo(rate));
159 return true;
160 }
161
120 AudioDecoderAlsa::BufferStatus AudioDecoderAlsa::PushBuffer( 162 AudioDecoderAlsa::BufferStatus AudioDecoderAlsa::PushBuffer(
121 CastDecoderBuffer* buffer) { 163 CastDecoderBuffer* buffer) {
122 TRACE_FUNCTION_ENTRY0(); 164 TRACE_FUNCTION_ENTRY0();
123 DCHECK(task_runner_->BelongsToCurrentThread()); 165 DCHECK(task_runner_->BelongsToCurrentThread());
124 DCHECK(buffer); 166 DCHECK(buffer);
125 DCHECK(!is_eos_); 167 DCHECK(!got_eos_);
126 DCHECK(!error_); 168 DCHECK(!error_);
169 DCHECK(!pending_buffer_complete_);
127 170
128 uint64_t input_bytes = buffer->end_of_stream() ? 0 : buffer->data_size(); 171 uint64_t input_bytes = buffer->end_of_stream() ? 0 : buffer->data_size();
129 scoped_refptr<DecoderBufferBase> buffer_base( 172 scoped_refptr<DecoderBufferBase> buffer_base(
130 static_cast<DecoderBufferBase*>(buffer)); 173 static_cast<DecoderBufferBase*>(buffer));
131 if (!buffer->end_of_stream()) { 174 if (!buffer->end_of_stream()) {
132 last_buffer_pts_ = buffer->timestamp(); 175 current_pts_ = buffer->timestamp();
133 current_pts_ = std::min(current_pts_, last_buffer_pts_);
134 } 176 }
135 177
136 // If the buffer is already decoded, do not attempt to decode. Call 178 // If the buffer is already decoded, do not attempt to decode. Call
137 // OnBufferDecoded asynchronously on the main thread. 179 // OnBufferDecoded asynchronously on the main thread.
138 if (BypassDecoder()) { 180 if (BypassDecoder()) {
139 DCHECK(!decoder_); 181 DCHECK(!decoder_);
140 task_runner_->PostTask( 182 task_runner_->PostTask(
141 FROM_HERE, 183 FROM_HERE,
142 base::Bind(&AudioDecoderAlsa::OnBufferDecoded, 184 base::Bind(&AudioDecoderAlsa::OnBufferDecoded,
143 weak_factory_.GetWeakPtr(), input_bytes, 185 weak_factory_.GetWeakPtr(), input_bytes,
(...skipping 23 matching lines...) Expand all
167 } 209 }
168 210
169 bool AudioDecoderAlsa::SetConfig(const AudioConfig& config) { 211 bool AudioDecoderAlsa::SetConfig(const AudioConfig& config) {
170 TRACE_FUNCTION_ENTRY0(); 212 TRACE_FUNCTION_ENTRY0();
171 DCHECK(task_runner_->BelongsToCurrentThread()); 213 DCHECK(task_runner_->BelongsToCurrentThread());
172 if (!IsValidConfig(config)) { 214 if (!IsValidConfig(config)) {
173 LOG(ERROR) << "Invalid audio config passed to SetConfig"; 215 LOG(ERROR) << "Invalid audio config passed to SetConfig";
174 return false; 216 return false;
175 } 217 }
176 218
219 if (!rate_shifter_ ||
220 config.samples_per_second != config_.samples_per_second) {
221 CreateRateShifter(config.samples_per_second);
222 }
223
177 if (mixer_input_ && config.samples_per_second != config_.samples_per_second) { 224 if (mixer_input_ && config.samples_per_second != config_.samples_per_second) {
178 // Destroy the old input first to ensure that the mixer output sample rate 225 // Destroy the old input first to ensure that the mixer output sample rate
179 // is updated. 226 // is updated.
180 mixer_input_.reset(); 227 mixer_input_.reset();
181 mixer_input_.reset(new StreamMixerAlsaInput( 228 mixer_input_.reset(new StreamMixerAlsaInput(
182 this, config.samples_per_second, backend_->Primary())); 229 this, config.samples_per_second, backend_->Primary()));
183 mixer_input_->SetVolumeMultiplier(volume_multiplier_); 230 mixer_input_->SetVolumeMultiplier(volume_multiplier_);
231 pending_write_pcm_ = false;
232 pending_output_frames_ = 0;
184 } 233 }
185 234
186 config_ = config; 235 config_ = config;
187 decoder_.reset(); 236 decoder_.reset();
188 CreateDecoder(); 237 CreateDecoder();
238
239 if (pending_buffer_complete_ && !rate_shifter_->IsQueueFull()) {
slan 2016/12/07 00:22:27 Why do we need to check the rate_shifter queue her
kmackay 2016/12/07 22:59:57 We need to have flow control, so the app doesn't p
slan 2016/12/09 00:05:31 Acknowledged.
240 pending_buffer_complete_ = false;
241 delegate_->OnPushBufferComplete(MediaPipelineBackendAlsa::kBufferSuccess);
242 }
189 return true; 243 return true;
190 } 244 }
191 245
192 void AudioDecoderAlsa::CreateDecoder() { 246 void AudioDecoderAlsa::CreateDecoder() {
193 DCHECK(!decoder_); 247 DCHECK(!decoder_);
194 DCHECK(IsValidConfig(config_)); 248 DCHECK(IsValidConfig(config_));
195 249
196 // No need to create a decoder if the samples are already decoded. 250 // No need to create a decoder if the samples are already decoded.
197 if (BypassDecoder()) { 251 if (BypassDecoder()) {
198 LOG(INFO) << "Data is not coded. Decoder will not be used."; 252 LOG(INFO) << "Data is not coded. Decoder will not be used.";
199 return; 253 return;
200 } 254 }
201 255
202 // Create a decoder. 256 // Create a decoder.
203 decoder_ = CastAudioDecoder::Create( 257 decoder_ = CastAudioDecoder::Create(
204 task_runner_, 258 task_runner_,
205 config_, 259 config_,
206 kDecoderSampleFormat, 260 kDecoderSampleFormat,
207 base::Bind(&AudioDecoderAlsa::OnDecoderInitialized, 261 base::Bind(&AudioDecoderAlsa::OnDecoderInitialized,
208 weak_factory_.GetWeakPtr())); 262 weak_factory_.GetWeakPtr()));
209 } 263 }
210 264
265 void AudioDecoderAlsa::CreateRateShifter(int samples_per_second) {
slan 2016/12/07 00:22:27 Do we want to DCHECK that rate_shifter_ is flushed
kmackay 2016/12/07 22:59:58 No; it might not be in some cases (eg, sample rate
slan 2016/12/09 00:05:31 In that case, wouldn't we want to play out the aud
kmackay 2016/12/09 00:21:16 Ideally yes, but we're already resetting the mixer
266 rate_shifter_info_.clear();
267 rate_shifter_info_.push_back(RateShifterInfo(1.0f));
268
269 rate_shifter_.reset(new ::media::AudioRendererAlgorithm());
270 rate_shifter_->Initialize(::media::AudioParameters(
271 ::media::AudioParameters::AUDIO_PCM_LINEAR,
272 ::media::CHANNEL_LAYOUT_STEREO, samples_per_second, kBitsPerSample,
273 kDefaultFramesPerBuffer));
274 }
275
211 bool AudioDecoderAlsa::SetVolume(float multiplier) { 276 bool AudioDecoderAlsa::SetVolume(float multiplier) {
212 TRACE_FUNCTION_ENTRY1(multiplier); 277 TRACE_FUNCTION_ENTRY1(multiplier);
213 DCHECK(task_runner_->BelongsToCurrentThread()); 278 DCHECK(task_runner_->BelongsToCurrentThread());
214 volume_multiplier_ = multiplier; 279 volume_multiplier_ = multiplier;
215 if (mixer_input_) 280 if (mixer_input_)
216 mixer_input_->SetVolumeMultiplier(volume_multiplier_); 281 mixer_input_->SetVolumeMultiplier(volume_multiplier_);
217 return true; 282 return true;
218 } 283 }
219 284
220 AudioDecoderAlsa::RenderingDelay AudioDecoderAlsa::GetRenderingDelay() { 285 AudioDecoderAlsa::RenderingDelay AudioDecoderAlsa::GetRenderingDelay() {
221 TRACE_FUNCTION_ENTRY0(); 286 TRACE_FUNCTION_ENTRY0();
222 return last_known_delay_; 287 AudioDecoderAlsa::RenderingDelay delay = last_known_delay_;
288 if (delay.timestamp_microseconds != kInvalidTimestamp) {
289 double usec_per_sample = 1000000.0 / config_.samples_per_second;
290 for (const RateShifterInfo& info : rate_shifter_info_) {
slan 2016/12/07 00:22:27 This is dense. Could you put a simple comment insi
kmackay 2016/12/07 22:59:58 Added comments. The last_known_delay_ is the last
slan 2016/12/09 00:05:31 OK, I get it now.
291 double queued_output_frames =
292 (info.input_frames / info.rate) - info.output_frames;
293 delay.delay_microseconds += queued_output_frames * usec_per_sample;
294 }
295
296 delay.delay_microseconds += pending_output_frames_ * usec_per_sample;
297 }
298
299 return delay;
223 } 300 }
224 301
225 void AudioDecoderAlsa::OnDecoderInitialized(bool success) { 302 void AudioDecoderAlsa::OnDecoderInitialized(bool success) {
226 TRACE_FUNCTION_ENTRY0(); 303 TRACE_FUNCTION_ENTRY0();
227 DCHECK(task_runner_->BelongsToCurrentThread()); 304 DCHECK(task_runner_->BelongsToCurrentThread());
228 LOG(INFO) << "Decoder initialization was " 305 LOG(INFO) << "Decoder initialization was "
229 << (success ? "successful" : "unsuccessful"); 306 << (success ? "successful" : "unsuccessful");
230 if (!success) 307 if (!success)
231 delegate_->OnDecoderError(); 308 delegate_->OnDecoderError();
232 } 309 }
233 310
234 void AudioDecoderAlsa::OnBufferDecoded( 311 void AudioDecoderAlsa::OnBufferDecoded(
235 uint64_t input_bytes, 312 uint64_t input_bytes,
236 CastAudioDecoder::Status status, 313 CastAudioDecoder::Status status,
237 const scoped_refptr<DecoderBufferBase>& decoded) { 314 const scoped_refptr<DecoderBufferBase>& decoded) {
238 TRACE_FUNCTION_ENTRY0(); 315 TRACE_FUNCTION_ENTRY0();
239 DCHECK(task_runner_->BelongsToCurrentThread()); 316 DCHECK(task_runner_->BelongsToCurrentThread());
240 DCHECK(!is_eos_); 317 DCHECK(!got_eos_);
241 318 DCHECK(!pending_buffer_complete_);
242 Statistics delta = Statistics(); 319 DCHECK(rate_shifter_);
243 320
244 if (status == CastAudioDecoder::Status::kDecodeError) { 321 if (status == CastAudioDecoder::Status::kDecodeError) {
245 LOG(ERROR) << "Decode error"; 322 LOG(ERROR) << "Decode error";
246 task_runner_->PostTask(FROM_HERE, 323 delegate_->OnPushBufferComplete(MediaPipelineBackendAlsa::kBufferFailed);
247 base::Bind(&AudioDecoderAlsa::OnWritePcmCompletion, 324 return;
248 weak_factory_.GetWeakPtr(), 325 }
249 MediaPipelineBackendAlsa::kBufferFailed, 326 if (error_) {
slan 2016/12/07 00:22:27 Can we rename this variable to mixer_error_? This
kmackay 2016/12/07 22:59:58 Done.
250 kInvalidRenderingDelay())); 327 delegate_->OnPushBufferComplete(MediaPipelineBackendAlsa::kBufferFailed);
251 UpdateStatistics(delta);
252 return; 328 return;
253 } 329 }
254 330
331 Statistics delta;
255 delta.decoded_bytes = input_bytes; 332 delta.decoded_bytes = input_bytes;
256 UpdateStatistics(delta); 333 UpdateStatistics(delta);
257 334
258 if (decoded->end_of_stream()) 335 if (decoded->end_of_stream()) {
259 is_eos_ = true; 336 got_eos_ = true;
337 } else {
338 int input_frames = decoded->data_size() / (2 * sizeof(float));
slan 2016/12/07 00:22:27 nit: kNumChannels
kmackay 2016/12/07 22:59:57 Done.
260 339
340 RateShifterInfo* rate_info = &rate_shifter_info_.front();
341 // Bypass rate shifter if the rate is 1.0.
342 if (rate_info->rate == 1.0 && rate_shifter_->frames_buffered() == 0 &&
343 !pending_write_pcm_) {
344 DCHECK_EQ(rate_info->output_frames, rate_info->input_frames);
345 pending_buffer_complete_ = true;
346 pending_write_pcm_ = true;
347 pending_output_frames_ = input_frames;
348 if (got_eos_) {
halliwell 2016/12/06 17:27:59 I don't think this branch can be hit? DCHECK(!got
slan 2016/12/07 00:22:27 got_eos_ can mutate above (line 336) meganit, tho
kmackay 2016/12/07 22:59:57 I prefer to set the state variables before calling
slan 2016/12/09 00:05:31 Yes, I suppose that's fair...
349 DCHECK(!pushed_eos_);
350 pushed_eos_ = true;
351 }
352 mixer_input_->WritePcm(decoded);
353 return;
354 }
355
356 const uint8_t* channels[2] = {
slan 2016/12/07 00:22:27 Add comment: // Otherwise, if the rate is not 1.0
kmackay 2016/12/07 22:59:57 Done.
357 decoded->data(), decoded->data() + input_frames * sizeof(float)};
358 scoped_refptr<::media::AudioBuffer> buffer = ::media::AudioBuffer::CopyFrom(
359 ::media::kSampleFormatPlanarF32, ::media::CHANNEL_LAYOUT_STEREO, 2,
360 config_.samples_per_second, input_frames, channels, base::TimeDelta());
361 rate_shifter_->EnqueueBuffer(buffer);
362 rate_shifter_info_.back().input_frames += input_frames;
363 }
364
365 PushRateShifted();
366 if (decoded->end_of_stream() || (!rate_shifter_->IsQueueFull() &&
slan 2016/12/07 00:22:27 Why not check got_eos_?
kmackay 2016/12/07 22:59:57 Added comment.
367 rate_shifter_info_.front().rate != 1.0)) {
368 delegate_->OnPushBufferComplete(MediaPipelineBackendAlsa::kBufferSuccess);
369 } else {
370 pending_buffer_complete_ = true;
371 }
372 }
373
374 void AudioDecoderAlsa::PushRateShifted() {
261 DCHECK(mixer_input_); 375 DCHECK(mixer_input_);
262 mixer_input_->WritePcm(decoded); 376
377 if (pending_write_pcm_) {
378 return;
379 }
380
381 if (got_eos_) {
382 // Push some silence into the rate shifter so we can get out any remaining
383 // rate-shifted data.
slan 2016/12/07 00:22:27 Perhaps make this an anonymous function that takes
kmackay 2016/12/07 22:59:57 Done.
384 scoped_refptr<::media::AudioBuffer> silence_buffer =
385 ::media::AudioBuffer::CreateBuffer(
386 ::media::kSampleFormatPlanarF32, ::media::CHANNEL_LAYOUT_STEREO, 2,
387 config_.samples_per_second, kSilenceBufferFrames);
388 for (uint8_t* channel : silence_buffer->channel_data()) {
389 float* real_channel = reinterpret_cast<float*>(channel);
390 std::fill_n(real_channel, kSilenceBufferFrames, 0.0f);
391 }
392
393 rate_shifter_->EnqueueBuffer(silence_buffer);
394 }
395
396 RateShifterInfo* rate_info = &rate_shifter_info_.front();
slan 2016/12/07 00:22:27 It seems to be an implicit assumption everywhere t
kmackay 2016/12/07 22:59:57 Done.
397 int64_t possible_output_frames = rate_info->input_frames / rate_info->rate;
398 DCHECK_GE(possible_output_frames, rate_info->output_frames);
399
400 int desired_output_frames = possible_output_frames - rate_info->output_frames;
401 if (desired_output_frames == 0) {
402 if (got_eos_) {
403 DCHECK(!pushed_eos_);
404 pending_write_pcm_ = true;
405 pushed_eos_ = true;
406
407 scoped_refptr<DecoderBufferBase> eos_buffer(
408 new DecoderBufferAdapter(::media::DecoderBuffer::CreateEOSBuffer()));
409 mixer_input_->WritePcm(eos_buffer);
410 }
411 return;
412 }
413 // Don't push too many frames at a time.
414 desired_output_frames = std::min(
415 desired_output_frames, config_.samples_per_second * kMaxOutputMs / 1000);
slan 2016/12/07 00:22:27 base::kMillisecondsPerSecond
kmackay 2016/12/07 22:59:57 Added constant.
416
417 if (desired_output_frames > rate_shifter_output_->frames()) {
418 rate_shifter_output_ = ::media::AudioBus::Create(2, desired_output_frames);
slan 2016/12/07 00:22:27 Is seems inefficient for rate_shifter_ouptut_ to b
kmackay 2016/12/07 22:59:57 It already does that? It only reallocates if it ne
slan 2016/12/09 00:05:31 Yuuuupppp, lgtm
419 }
420
421 int out_frames = rate_shifter_->FillBuffer(
422 rate_shifter_output_.get(), 0, desired_output_frames, rate_info->rate);
423 if (out_frames <= 0) {
424 return;
425 }
426
427 rate_info->output_frames += out_frames;
428 DCHECK_GE(possible_output_frames, rate_info->output_frames);
429
430 int channel_data_size = out_frames * sizeof(float);
slan 2016/12/07 00:22:27 Do we have a more conventional way of going from A
kmackay 2016/12/07 22:59:57 No, we don't. Usually we convert from ::media::Dec
slan 2016/12/09 00:05:31 Acknowledged.
431 scoped_refptr<DecoderBufferBase> output_buffer(new DecoderBufferAdapter(
432 new ::media::DecoderBuffer(channel_data_size * 2)));
433 for (int c = 0; c < 2; ++c) {
434 memcpy(output_buffer->writable_data() + c * channel_data_size,
435 rate_shifter_output_->channel(c), channel_data_size);
436 }
437 pending_write_pcm_ = true;
438 pending_output_frames_ = out_frames;
439 mixer_input_->WritePcm(output_buffer);
440
441 if (rate_shifter_info_.size() > 1 &&
442 possible_output_frames == rate_info->output_frames) {
443 double remaining_input_frames =
444 rate_info->input_frames - (rate_info->output_frames * rate_info->rate);
445 rate_shifter_info_.pop_front();
446
447 rate_info = &rate_shifter_info_.front();
448 LOG(INFO) << "New playback rate in effect: " << rate_info->rate;
449 rate_info->input_frames += remaining_input_frames;
450 DCHECK_EQ(0, rate_info->output_frames);
451
452 // If new playback rate is 1.0, clear out 'extra' data in the rate shifter.
453 if (rate_info->rate == 1.0) {
454 int extra_frames = rate_shifter_->frames_buffered() -
455 static_cast<int>(rate_info->input_frames);
456 if (extra_frames > 0) {
slan 2016/12/07 00:22:27 When this condition hits, what has happened? Shoul
kmackay 2016/12/07 22:59:57 They already were. I added more comments.
457 // Clear out extra buffered data.
458 std::unique_ptr<::media::AudioBus> dropped =
459 ::media::AudioBus::Create(2, extra_frames);
460 int cleared_frames =
461 rate_shifter_->FillBuffer(dropped.get(), 0, extra_frames, 1.0f);
462 DCHECK_EQ(extra_frames, cleared_frames);
463 }
464 rate_info->input_frames = rate_shifter_->frames_buffered();
465 }
466 }
263 } 467 }
264 468
265 bool AudioDecoderAlsa::BypassDecoder() const { 469 bool AudioDecoderAlsa::BypassDecoder() const {
266 DCHECK(task_runner_->BelongsToCurrentThread()); 470 DCHECK(task_runner_->BelongsToCurrentThread());
267 // The mixer input requires planar float PCM data. 471 // The mixer input requires planar float PCM data.
268 return (config_.codec == kCodecPCM && 472 return (config_.codec == kCodecPCM &&
269 config_.sample_format == kSampleFormatPlanarF32); 473 config_.sample_format == kSampleFormatPlanarF32);
270 } 474 }
271 475
272 void AudioDecoderAlsa::OnWritePcmCompletion(BufferStatus status, 476 void AudioDecoderAlsa::OnWritePcmCompletion(BufferStatus status,
slan 2016/12/07 00:22:27 Is it OK to ignore |status| here?
kmackay 2016/12/07 22:59:57 Added DCHECK
273 const RenderingDelay& delay) { 477 const RenderingDelay& delay) {
274 TRACE_FUNCTION_ENTRY0(); 478 TRACE_FUNCTION_ENTRY0();
275 DCHECK(task_runner_->BelongsToCurrentThread()); 479 DCHECK(task_runner_->BelongsToCurrentThread());
276 if (status == MediaPipelineBackendAlsa::kBufferSuccess && !is_eos_) 480 pending_write_pcm_ = false;
277 current_pts_ = last_buffer_pts_; 481 pending_output_frames_ = 0;
278 if (delay.timestamp_microseconds != kInvalidDelayTimestamp) 482 last_known_delay_ = delay;
279 last_known_delay_ = delay; 483
280 delegate_->OnPushBufferComplete(status); 484 if (pushed_eos_) {
281 if (is_eos_) 485 if (pending_buffer_complete_) {
486 pending_buffer_complete_ = false;
487 delegate_->OnPushBufferComplete(MediaPipelineBackendAlsa::kBufferSuccess);
488 }
282 delegate_->OnEndOfStream(); 489 delegate_->OnEndOfStream();
490 } else {
491 task_runner_->PostTask(FROM_HERE, base::Bind(&AudioDecoderAlsa::PushMorePcm,
492 weak_factory_.GetWeakPtr()));
493 }
494 }
495
496 void AudioDecoderAlsa::PushMorePcm() {
497 PushRateShifted();
498
499 double rate = rate_shifter_info_.front().rate;
slan 2016/12/07 00:22:27 nit: Move inside if (pending_buffer_complete_), an
kmackay 2016/12/07 22:59:58 Done.
500 if (pending_buffer_complete_ &&
501 ((rate == 1.0 && !pending_write_pcm_) ||
502 (rate != 1.0 && !rate_shifter_->IsQueueFull()))) {
503 pending_buffer_complete_ = false;
504 delegate_->OnPushBufferComplete(MediaPipelineBackendAlsa::kBufferSuccess);
505 }
283 } 506 }
284 507
285 void AudioDecoderAlsa::OnMixerError(MixerError error) { 508 void AudioDecoderAlsa::OnMixerError(MixerError error) {
286 TRACE_FUNCTION_ENTRY0(); 509 TRACE_FUNCTION_ENTRY0();
287 DCHECK(task_runner_->BelongsToCurrentThread()); 510 DCHECK(task_runner_->BelongsToCurrentThread());
288 if (error != MixerError::kInputIgnored) 511 if (error != MixerError::kInputIgnored)
289 LOG(ERROR) << "Mixer error occurred."; 512 LOG(ERROR) << "Mixer error occurred.";
290 error_ = true; 513 error_ = true;
291 delegate_->OnDecoderError(); 514 delegate_->OnDecoderError();
292 } 515 }
293 516
294 } // namespace media 517 } // namespace media
295 } // namespace chromecast 518 } // namespace chromecast
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698