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

Side by Side Diff: media/renderers/audio_renderer_impl.cc

Issue 2072843002: Freeze media time and audio rendering when the system suspends. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add observer on |task_runner_|. Created 4 years, 6 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 "media/renderers/audio_renderer_impl.h" 5 #include "media/renderers/audio_renderer_impl.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <algorithm> 9 #include <algorithm>
10 #include <utility> 10 #include <utility>
11 11
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/callback.h" 13 #include "base/callback.h"
14 #include "base/callback_helpers.h" 14 #include "base/callback_helpers.h"
15 #include "base/command_line.h" 15 #include "base/command_line.h"
16 #include "base/logging.h" 16 #include "base/logging.h"
17 #include "base/power_monitor/power_monitor.h"
17 #include "base/single_thread_task_runner.h" 18 #include "base/single_thread_task_runner.h"
18 #include "base/time/default_tick_clock.h" 19 #include "base/time/default_tick_clock.h"
19 #include "build/build_config.h" 20 #include "build/build_config.h"
20 #include "media/base/audio_buffer.h" 21 #include "media/base/audio_buffer.h"
21 #include "media/base/audio_buffer_converter.h" 22 #include "media/base/audio_buffer_converter.h"
22 #include "media/base/audio_hardware_config.h" 23 #include "media/base/audio_hardware_config.h"
23 #include "media/base/audio_splicer.h" 24 #include "media/base/audio_splicer.h"
24 #include "media/base/bind_to_current_loop.h" 25 #include "media/base/bind_to_current_loop.h"
25 #include "media/base/demuxer_stream.h" 26 #include "media/base/demuxer_stream.h"
26 #include "media/base/media_log.h" 27 #include "media/base/media_log.h"
(...skipping 21 matching lines...) Expand all
48 last_audio_memory_usage_(0), 49 last_audio_memory_usage_(0),
49 last_decoded_sample_rate_(0), 50 last_decoded_sample_rate_(0),
50 playback_rate_(0.0), 51 playback_rate_(0.0),
51 state_(kUninitialized), 52 state_(kUninitialized),
52 buffering_state_(BUFFERING_HAVE_NOTHING), 53 buffering_state_(BUFFERING_HAVE_NOTHING),
53 rendering_(false), 54 rendering_(false),
54 sink_playing_(false), 55 sink_playing_(false),
55 pending_read_(false), 56 pending_read_(false),
56 received_end_of_stream_(false), 57 received_end_of_stream_(false),
57 rendered_end_of_stream_(false), 58 rendered_end_of_stream_(false),
59 is_suspending_(false),
58 weak_factory_(this) { 60 weak_factory_(this) {
59 audio_buffer_stream_->set_splice_observer(base::Bind( 61 audio_buffer_stream_->set_splice_observer(base::Bind(
60 &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr())); 62 &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr()));
61 audio_buffer_stream_->set_config_change_observer(base::Bind( 63 audio_buffer_stream_->set_config_change_observer(base::Bind(
62 &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr())); 64 &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr()));
65
66 // Tests may not have a power monitor.
67 base::PowerMonitor* monitor = base::PowerMonitor::Get();
68 if (!monitor)
69 return;
70
71 // PowerObserver's must be added and removed from the same thread, but we
72 // won't remove the observer until we're destructed on |task_runner_| so we
73 // must post it here if we're on the wrong thread.
74 if (task_runner_->BelongsToCurrentThread()) {
75 monitor->AddObserver(this);
76 } else {
77 // Safe to post this without a WeakPtr because this class must be destructed
78 // on the same thread and construction has not completed yet.
79 task_runner_->PostTask(FROM_HERE,
80 base::Bind(&base::PowerMonitor::AddObserver,
81 base::Unretained(monitor), this));
82 }
83 // Do not add anything below this line since the above actions are only safe
84 // as the last lines of the constructor.
63 } 85 }
64 86
65 AudioRendererImpl::~AudioRendererImpl() { 87 AudioRendererImpl::~AudioRendererImpl() {
66 DVLOG(1) << __FUNCTION__; 88 DVLOG(1) << __FUNCTION__;
67 DCHECK(task_runner_->BelongsToCurrentThread()); 89 DCHECK(task_runner_->BelongsToCurrentThread());
90 if (base::PowerMonitor::Get())
91 base::PowerMonitor::Get()->RemoveObserver(this);
68 92
69 // If Render() is in progress, this call will wait for Render() to finish. 93 // If Render() is in progress, this call will wait for Render() to finish.
70 // After this call, the |sink_| will not call back into |this| anymore. 94 // After this call, the |sink_| will not call back into |this| anymore.
71 sink_->Stop(); 95 sink_->Stop();
72 96
73 if (!init_cb_.is_null()) 97 if (!init_cb_.is_null())
74 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); 98 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT);
75 } 99 }
76 100
77 void AudioRendererImpl::StartTicking() { 101 void AudioRendererImpl::StartTicking() {
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 bool AudioRendererImpl::GetWallClockTimes( 206 bool AudioRendererImpl::GetWallClockTimes(
183 const std::vector<base::TimeDelta>& media_timestamps, 207 const std::vector<base::TimeDelta>& media_timestamps,
184 std::vector<base::TimeTicks>* wall_clock_times) { 208 std::vector<base::TimeTicks>* wall_clock_times) {
185 base::AutoLock auto_lock(lock_); 209 base::AutoLock auto_lock(lock_);
186 DCHECK(wall_clock_times->empty()); 210 DCHECK(wall_clock_times->empty());
187 211
188 // When playback is paused (rate is zero), assume a rate of 1.0. 212 // When playback is paused (rate is zero), assume a rate of 1.0.
189 const double playback_rate = playback_rate_ ? playback_rate_ : 1.0; 213 const double playback_rate = playback_rate_ ? playback_rate_ : 1.0;
190 const bool is_time_moving = sink_playing_ && playback_rate_ && 214 const bool is_time_moving = sink_playing_ && playback_rate_ &&
191 !last_render_time_.is_null() && 215 !last_render_time_.is_null() &&
192 stop_rendering_time_.is_null(); 216 stop_rendering_time_.is_null() && !is_suspending_;
193 217
194 // Pre-compute the time until playback of the audio buffer extents, since 218 // Pre-compute the time until playback of the audio buffer extents, since
195 // these values are frequently used below. 219 // these values are frequently used below.
196 const base::TimeDelta time_until_front = 220 const base::TimeDelta time_until_front =
197 audio_clock_->TimeUntilPlayback(audio_clock_->front_timestamp()); 221 audio_clock_->TimeUntilPlayback(audio_clock_->front_timestamp());
198 const base::TimeDelta time_until_back = 222 const base::TimeDelta time_until_back =
199 audio_clock_->TimeUntilPlayback(audio_clock_->back_timestamp()); 223 audio_clock_->TimeUntilPlayback(audio_clock_->back_timestamp());
200 224
201 if (media_timestamps.empty()) { 225 if (media_timestamps.empty()) {
202 // Return the current media time as a wall clock time while accounting for 226 // Return the current media time as a wall clock time while accounting for
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
494 DCHECK(task_runner_->BelongsToCurrentThread()); 518 DCHECK(task_runner_->BelongsToCurrentThread());
495 client_->OnWaitingForDecryptionKey(); 519 client_->OnWaitingForDecryptionKey();
496 } 520 }
497 521
498 void AudioRendererImpl::SetVolume(float volume) { 522 void AudioRendererImpl::SetVolume(float volume) {
499 DCHECK(task_runner_->BelongsToCurrentThread()); 523 DCHECK(task_runner_->BelongsToCurrentThread());
500 DCHECK(sink_.get()); 524 DCHECK(sink_.get());
501 sink_->SetVolume(volume); 525 sink_->SetVolume(volume);
502 } 526 }
503 527
528 void AudioRendererImpl::OnSuspend() {
529 base::AutoLock auto_lock(lock_);
530 is_suspending_ = true;
531 }
532
533 void AudioRendererImpl::OnResume() {
534 base::AutoLock auto_lock(lock_);
535 is_suspending_ = false;
536 }
537
504 void AudioRendererImpl::DecodedAudioReady( 538 void AudioRendererImpl::DecodedAudioReady(
505 AudioBufferStream::Status status, 539 AudioBufferStream::Status status,
506 const scoped_refptr<AudioBuffer>& buffer) { 540 const scoped_refptr<AudioBuffer>& buffer) {
507 DVLOG(2) << __FUNCTION__ << "(" << status << ")"; 541 DVLOG(2) << __FUNCTION__ << "(" << status << ")";
508 DCHECK(task_runner_->BelongsToCurrentThread()); 542 DCHECK(task_runner_->BelongsToCurrentThread());
509 543
510 base::AutoLock auto_lock(lock_); 544 base::AutoLock auto_lock(lock_);
511 DCHECK(state_ != kUninitialized); 545 DCHECK(state_ != kUninitialized);
512 546
513 CHECK(pending_read_); 547 CHECK(pending_read_);
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
744 stop_rendering_time_ = base::TimeTicks(); 778 stop_rendering_time_ = base::TimeTicks();
745 } 779 }
746 780
747 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread. 781 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread.
748 if (!algorithm_) { 782 if (!algorithm_) {
749 audio_clock_->WroteAudio(0, frames_requested, frames_delayed, 783 audio_clock_->WroteAudio(0, frames_requested, frames_delayed,
750 playback_rate_); 784 playback_rate_);
751 return 0; 785 return 0;
752 } 786 }
753 787
754 if (playback_rate_ == 0) { 788 if (playback_rate_ == 0 || is_suspending_) {
755 audio_clock_->WroteAudio(0, frames_requested, frames_delayed, 789 audio_clock_->WroteAudio(0, frames_requested, frames_delayed,
756 playback_rate_); 790 playback_rate_);
757 return 0; 791 return 0;
758 } 792 }
759 793
760 // Mute audio by returning 0 when not playing. 794 // Mute audio by returning 0 when not playing.
761 if (state_ != kPlaying) { 795 if (state_ != kPlaying) {
762 audio_clock_->WroteAudio(0, frames_requested, frames_delayed, 796 audio_clock_->WroteAudio(0, frames_requested, frames_delayed,
763 playback_rate_); 797 playback_rate_);
764 return 0; 798 return 0;
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
925 DCHECK_NE(buffering_state_, buffering_state); 959 DCHECK_NE(buffering_state_, buffering_state);
926 lock_.AssertAcquired(); 960 lock_.AssertAcquired();
927 buffering_state_ = buffering_state; 961 buffering_state_ = buffering_state;
928 962
929 task_runner_->PostTask( 963 task_runner_->PostTask(
930 FROM_HERE, base::Bind(&AudioRendererImpl::OnBufferingStateChange, 964 FROM_HERE, base::Bind(&AudioRendererImpl::OnBufferingStateChange,
931 weak_factory_.GetWeakPtr(), buffering_state_)); 965 weak_factory_.GetWeakPtr(), buffering_state_));
932 } 966 }
933 967
934 } // namespace media 968 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698