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

Side by Side Diff: content/renderer/media/track_audio_renderer.cc

Issue 1666363005: Switching audio clients to using RestartableAudioRendererSink interface as a sink. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 4 years, 10 months 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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "content/renderer/media/track_audio_renderer.h" 5 #include "content/renderer/media/track_audio_renderer.h"
6 6
7 #include "base/location.h" 7 #include "base/location.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/metrics/histogram.h" 9 #include "base/metrics/histogram.h"
10 #include "base/synchronization/lock.h" 10 #include "base/synchronization/lock.h"
11 #include "base/thread_task_runner_handle.h" 11 #include "base/thread_task_runner_handle.h"
12 #include "base/trace_event/trace_event.h" 12 #include "base/trace_event/trace_event.h"
13 #include "content/renderer/media/audio_device_factory.h" 13 #include "content/renderer/media/audio_device_factory.h"
14 #include "content/renderer/media/media_stream_audio_track.h" 14 #include "content/renderer/media/media_stream_audio_track.h"
15 #include "media/audio/audio_output_device.h"
16 #include "media/base/audio_bus.h" 15 #include "media/base/audio_bus.h"
17 #include "media/base/audio_shifter.h" 16 #include "media/base/audio_shifter.h"
18 17
19 namespace content { 18 namespace content {
20 19
21 namespace { 20 namespace {
22 21
23 enum LocalRendererSinkStates { 22 enum LocalRendererSinkStates {
24 kSinkStarted = 0, 23 kSinkStarted = 0,
25 kSinkNeverStarted, 24 kSinkNeverStarted,
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 143
145 void TrackAudioRenderer::Start() { 144 void TrackAudioRenderer::Start() {
146 DVLOG(1) << "TrackAudioRenderer::Start()"; 145 DVLOG(1) << "TrackAudioRenderer::Start()";
147 DCHECK(task_runner_->BelongsToCurrentThread()); 146 DCHECK(task_runner_->BelongsToCurrentThread());
148 DCHECK_EQ(playing_, false); 147 DCHECK_EQ(playing_, false);
149 148
150 // We get audio data from |audio_track_|... 149 // We get audio data from |audio_track_|...
151 MediaStreamAudioSink::AddToAudioTrack(this, audio_track_); 150 MediaStreamAudioSink::AddToAudioTrack(this, audio_track_);
152 // ...and |sink_| will get audio data from us. 151 // ...and |sink_| will get audio data from us.
153 DCHECK(!sink_.get()); 152 DCHECK(!sink_.get());
154 sink_ = 153 sink_ = AudioDeviceFactory::NewAudioRendererSink(
155 AudioDeviceFactory::NewOutputDevice(playout_render_frame_id_, session_id_, 154 AudioDeviceFactory::kSourceNonRtcAudioTrack, playout_render_frame_id_,
156 output_device_id_, security_origin_); 155 session_id_, output_device_id_, security_origin_);
157 156
158 base::AutoLock auto_lock(thread_lock_); 157 base::AutoLock auto_lock(thread_lock_);
159 prior_elapsed_render_time_ = base::TimeDelta(); 158 prior_elapsed_render_time_ = base::TimeDelta();
160 num_samples_rendered_ = 0; 159 num_samples_rendered_ = 0;
161 } 160 }
162 161
163 void TrackAudioRenderer::Stop() { 162 void TrackAudioRenderer::Stop() {
164 DVLOG(1) << "TrackAudioRenderer::Stop()"; 163 DVLOG(1) << "TrackAudioRenderer::Stop()";
165 DCHECK(task_runner_->BelongsToCurrentThread()); 164 DCHECK(task_runner_->BelongsToCurrentThread());
166 165
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 const url::Origin& security_origin, 245 const url::Origin& security_origin,
247 const media::SwitchOutputDeviceCB& callback) { 246 const media::SwitchOutputDeviceCB& callback) {
248 DVLOG(1) << "TrackAudioRenderer::SwitchOutputDevice()"; 247 DVLOG(1) << "TrackAudioRenderer::SwitchOutputDevice()";
249 DCHECK(task_runner_->BelongsToCurrentThread()); 248 DCHECK(task_runner_->BelongsToCurrentThread());
250 249
251 { 250 {
252 base::AutoLock auto_lock(thread_lock_); 251 base::AutoLock auto_lock(thread_lock_);
253 HaltAudioFlowWhileLockHeld(); 252 HaltAudioFlowWhileLockHeld();
254 } 253 }
255 254
256 scoped_refptr<media::AudioOutputDevice> new_sink = 255 scoped_refptr<media::AudioRendererSink> new_sink =
257 AudioDeviceFactory::NewOutputDevice(playout_render_frame_id_, session_id_, 256 AudioDeviceFactory::NewAudioRendererSink(
258 device_id, security_origin); 257 AudioDeviceFactory::kSourceNonRtcAudioTrack, playout_render_frame_id_,
259 if (new_sink->GetDeviceStatus() != media::OUTPUT_DEVICE_STATUS_OK) { 258 session_id_, device_id, security_origin);
260 callback.Run(new_sink->GetDeviceStatus()); 259 media::OutputDeviceStatus new_sink_status =
260 new_sink->GetOutputDevice()->GetDeviceStatus();
261 if (new_sink_status != media::OUTPUT_DEVICE_STATUS_OK) {
262 callback.Run(new_sink_status);
261 return; 263 return;
262 } 264 }
263 265
264 output_device_id_ = device_id; 266 output_device_id_ = device_id;
265 security_origin_ = security_origin; 267 security_origin_ = security_origin;
266 bool was_sink_started = sink_started_; 268 bool was_sink_started = sink_started_;
267 269
268 if (sink_.get()) 270 if (sink_.get())
269 sink_->Stop(); 271 sink_->Stop();
270 272
271 sink_started_ = false; 273 sink_started_ = false;
272 sink_ = new_sink; 274 sink_ = new_sink;
273 if (was_sink_started) 275 if (was_sink_started)
274 MaybeStartSink(); 276 MaybeStartSink();
275 277
276 callback.Run(media::OUTPUT_DEVICE_STATUS_OK); 278 callback.Run(media::OUTPUT_DEVICE_STATUS_OK);
277 } 279 }
278 280
279 media::AudioParameters TrackAudioRenderer::GetOutputParameters() { 281 media::AudioParameters TrackAudioRenderer::GetOutputParameters() {
280 DCHECK(task_runner_->BelongsToCurrentThread()); 282 DCHECK(task_runner_->BelongsToCurrentThread());
281 if (!sink_ || !source_params_.IsValid()) 283 if (!sink_ || !source_params_.IsValid())
282 return media::AudioParameters(); 284 return media::AudioParameters();
283 285
284 // Output parameters consist of the same channel layout and sample rate as the 286 // Output parameters consist of the same channel layout and sample rate as the
285 // source, but having the buffer duration preferred by the hardware. 287 // source, but having the buffer duration preferred by the hardware.
286 const media::AudioParameters& preferred_params = sink_->GetOutputParameters(); 288 const media::AudioParameters& preferred_params =
289 sink_->GetOutputDevice()->GetOutputParameters();
287 return media::AudioParameters( 290 return media::AudioParameters(
288 preferred_params.format(), source_params_.channel_layout(), 291 preferred_params.format(), source_params_.channel_layout(),
289 source_params_.sample_rate(), source_params_.bits_per_sample(), 292 source_params_.sample_rate(), source_params_.bits_per_sample(),
290 preferred_params.frames_per_buffer() * source_params_.sample_rate() / 293 preferred_params.frames_per_buffer() * source_params_.sample_rate() /
291 preferred_params.sample_rate()); 294 preferred_params.sample_rate());
292 } 295 }
293 296
294 media::OutputDeviceStatus TrackAudioRenderer::GetDeviceStatus() { 297 media::OutputDeviceStatus TrackAudioRenderer::GetDeviceStatus() {
295 DCHECK(task_runner_->BelongsToCurrentThread()); 298 DCHECK(task_runner_->BelongsToCurrentThread());
296 if (!sink_.get()) 299 if (!sink_.get())
297 return media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL; 300 return media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL;
298 301
299 return sink_->GetDeviceStatus(); 302 return sink_->GetOutputDevice()->GetDeviceStatus();
300 } 303 }
301 304
302 void TrackAudioRenderer::MaybeStartSink() { 305 void TrackAudioRenderer::MaybeStartSink() {
303 DCHECK(task_runner_->BelongsToCurrentThread()); 306 DCHECK(task_runner_->BelongsToCurrentThread());
304 DVLOG(1) << "TrackAudioRenderer::MaybeStartSink()"; 307 DVLOG(1) << "TrackAudioRenderer::MaybeStartSink()";
305 308
306 if (!sink_.get() || !source_params_.IsValid() || !playing_) 309 if (!sink_.get() || !source_params_.IsValid() || !playing_)
307 return; 310 return;
308 311
309 // Re-create the AudioShifter to drop old audio data and reset to a starting 312 // Re-create the AudioShifter to drop old audio data and reset to a starting
310 // state. MaybeStartSink() is always called in a situation where either the 313 // state. MaybeStartSink() is always called in a situation where either the
311 // source or sink has changed somehow and so all of AudioShifter's internal 314 // source or sink has changed somehow and so all of AudioShifter's internal
312 // time-sync state is invalid. 315 // time-sync state is invalid.
313 CreateAudioShifter(); 316 CreateAudioShifter();
314 317
315 if (sink_started_ || 318 if (sink_started_ ||
316 sink_->GetDeviceStatus() != media::OUTPUT_DEVICE_STATUS_OK) { 319 sink_->GetOutputDevice()->GetDeviceStatus() !=
320 media::OUTPUT_DEVICE_STATUS_OK) {
317 return; 321 return;
318 } 322 }
319 323
320 DVLOG(1) << ("TrackAudioRenderer::MaybeStartSink() -- Starting sink. " 324 DVLOG(1) << ("TrackAudioRenderer::MaybeStartSink() -- Starting sink. "
321 "source_params_={") 325 "source_params_={")
322 << source_params_.AsHumanReadableString() << "}, sink parameters={" 326 << source_params_.AsHumanReadableString() << "}, sink parameters={"
323 << GetOutputParameters().AsHumanReadableString() << '}'; 327 << GetOutputParameters().AsHumanReadableString() << '}';
324 sink_->Initialize(GetOutputParameters(), this); 328 sink_->Initialize(GetOutputParameters(), this);
325 sink_->Start(); 329 sink_->Start();
326 sink_->SetVolume(volume_); 330 sink_->SetVolume(volume_);
331 sink_->Play(); // Not all the sinks play on start.
Henrik Grunell 2016/02/15 12:21:17 Ahh, the fact that sinks behave differently is hor
o1ka 2016/02/17 17:40:44 Acknowledged.
327 sink_started_ = true; 332 sink_started_ = true;
328 if (IsLocalRenderer()) { 333 if (IsLocalRenderer()) {
329 UMA_HISTOGRAM_ENUMERATION("Media.LocalRendererSinkStates", kSinkStarted, 334 UMA_HISTOGRAM_ENUMERATION("Media.LocalRendererSinkStates", kSinkStarted,
330 kSinkStatesMax); 335 kSinkStatesMax);
331 } 336 }
332 } 337 }
333 338
334 void TrackAudioRenderer::ReconfigureSink(const media::AudioParameters& params) { 339 void TrackAudioRenderer::ReconfigureSink(const media::AudioParameters& params) {
335 DCHECK(task_runner_->BelongsToCurrentThread()); 340 DCHECK(task_runner_->BelongsToCurrentThread());
336 341
337 DVLOG(1) << "TrackAudioRenderer::ReconfigureSink()"; 342 DVLOG(1) << "TrackAudioRenderer::ReconfigureSink()";
338 343
339 if (source_params_.Equals(params)) 344 if (source_params_.Equals(params))
340 return; 345 return;
341 source_params_ = params; 346 source_params_ = params;
342 347
343 if (!sink_.get()) 348 if (!sink_.get())
344 return; // TrackAudioRenderer has not yet been started. 349 return; // TrackAudioRenderer has not yet been started.
345 350
346 // Stop |sink_| and re-create a new one to be initialized with different audio 351 // Stop |sink_| and re-create a new one to be initialized with different audio
347 // parameters. Then, invoke MaybeStartSink() to restart everything again. 352 // parameters. Then, invoke MaybeStartSink() to restart everything again.
348 sink_->Stop(); 353 sink_->Stop();
349 sink_started_ = false; 354 sink_started_ = false;
350 sink_ = 355 sink_ = AudioDeviceFactory::NewAudioRendererSink(
351 AudioDeviceFactory::NewOutputDevice(playout_render_frame_id_, session_id_, 356 AudioDeviceFactory::kSourceNonRtcAudioTrack, playout_render_frame_id_,
352 output_device_id_, security_origin_); 357 session_id_, output_device_id_, security_origin_);
353 MaybeStartSink(); 358 MaybeStartSink();
354 } 359 }
355 360
356 void TrackAudioRenderer::CreateAudioShifter() { 361 void TrackAudioRenderer::CreateAudioShifter() {
357 DCHECK(task_runner_->BelongsToCurrentThread()); 362 DCHECK(task_runner_->BelongsToCurrentThread());
358 363
359 // Note 1: The max buffer is fairly large to cover the case where 364 // Note 1: The max buffer is fairly large to cover the case where
360 // remotely-sourced audio is delivered well ahead of its scheduled playout 365 // remotely-sourced audio is delivered well ahead of its scheduled playout
361 // time (e.g., content streaming with a very large end-to-end 366 // time (e.g., content streaming with a very large end-to-end
362 // latency). However, there is no penalty for making it large in the 367 // latency). However, there is no penalty for making it large in the
(...skipping 20 matching lines...) Expand all
383 if (source_params_.IsValid()) { 388 if (source_params_.IsValid()) {
384 prior_elapsed_render_time_ = 389 prior_elapsed_render_time_ =
385 ComputeTotalElapsedRenderTime(prior_elapsed_render_time_, 390 ComputeTotalElapsedRenderTime(prior_elapsed_render_time_,
386 num_samples_rendered_, 391 num_samples_rendered_,
387 source_params_.sample_rate()); 392 source_params_.sample_rate());
388 num_samples_rendered_ = 0; 393 num_samples_rendered_ = 0;
389 } 394 }
390 } 395 }
391 396
392 } // namespace content 397 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698