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

Side by Side Diff: media/audio/audio_output_dispatcher.cc

Issue 5158003: Implement AudioOutputProxy. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: - Created 10 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/audio/audio_output_dispatcher.h"
6
7 #include "base/message_loop.h"
8 #include "media/audio/audio_io.h"
9
10 namespace {
11 // Delay in milliseconds after since the stream is paused untill the
scherkus (not reviewing) 2010/11/22 06:43:15 untill -> until
Sergey Ulanov 2010/11/23 19:51:46 Done.
12 // audio device is closed.
13 const int kStreamCloseDelayMs = 5000;
14 } // namespace
15
16 AudioOutputDispatcher::AudioOutputDispatcher(
17 AudioManager* audio_manager, const AudioParameters& params)
18 : audio_manager_(audio_manager),
19 message_loop_(audio_manager->GetMessageLoop()),
20 params_(params),
21 close_delay_(base::TimeDelta::FromMilliseconds(
22 kStreamCloseDelayMs)),
23 paused_proxies_(0),
24 last_activity_time_(base::Time::Now()),
25 close_task_scheduled_(false) {
26 }
27
28 AudioOutputDispatcher::~AudioOutputDispatcher() {
29 }
30
31 bool AudioOutputDispatcher::StreamOpened() {
32 DCHECK_EQ(MessageLoop::current(), message_loop_);
33 paused_proxies_++;
scherkus (not reviewing) 2010/11/22 06:43:15 I'm not really sure what this variable is tracking
Sergey Ulanov 2010/11/23 19:51:46 Number of streams that are currently paused.
34 last_activity_time_ = base::Time::Now();
35
36 // Ensure that there is at least one open stream.
scherkus (not reviewing) 2010/11/22 06:43:15 out of curiosity do we need to have an open stream
Sergey Ulanov 2010/11/23 19:51:46 It is just so that a page that created media eleme
37 if (streams_.size() == 0) {
38 AudioOutputStream* stream = CreateAndOpenStream();
39 if (!stream) {
40 return false;
41 }
42 streams_.push_back(stream);
43 }
44
45 // Schedule close task so that the stream is closed later if it is
46 // not used.
47 ScheduleCloseTask();
48
49 return true;
50 }
51
52 AudioOutputStream* AudioOutputDispatcher::StreamStarted() {
scherkus (not reviewing) 2010/11/22 06:43:15 so to help me understand... ownership is passed ba
Sergey Ulanov 2010/11/23 19:51:46 Yes. Added more comments about it in .h
53 DCHECK_EQ(MessageLoop::current(), message_loop_);
54 AudioOutputStream* stream;
55 if (streams_.size() == 0) {
56 stream = CreateAndOpenStream();
scherkus (not reviewing) 2010/11/22 06:43:15 you might be able to de-duplicate this + StreamOpe
Sergey Ulanov 2010/11/23 19:51:46 Good catch. Fixed!
57 if (!stream) {
58 return NULL;
59 }
60 } else {
61 stream = streams_.back();
62 streams_.pop_back();
63 }
64
65 paused_proxies_--;
66 DCHECK_GE(paused_proxies_, 0);
67
68 last_activity_time_ = base::Time::Now();
69
70 // Schedule task to allocate streams for other proxies if we need to.
71 message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
72 this, &AudioOutputDispatcher::OpenTask));
73
74 return stream;
75 }
76
77 void AudioOutputDispatcher::StreamStopped(AudioOutputStream* stream) {
78 DCHECK_EQ(MessageLoop::current(), message_loop_);
79 paused_proxies_++;
80 streams_.push_back(stream);
81 last_activity_time_ = base::Time::Now();
82 ScheduleCloseTask();
83 }
84
85 void AudioOutputDispatcher::StreamClosed() {
86 DCHECK_EQ(MessageLoop::current(), message_loop_);
87 paused_proxies_--;
88 DCHECK_GE(paused_proxies_, 0);
89 ClosePendingStreams();
90 }
91
92 MessageLoop* AudioOutputDispatcher::message_loop() {
93 return message_loop_;
94 }
95
96 AudioOutputStream* AudioOutputDispatcher::CreateAndOpenStream() {
97 AudioOutputStream* stream =
98 audio_manager_->MakeAudioOutputStream(params_);
99 if (!stream) {
100 return NULL;
101 }
102 if (!stream->Open()) {
103 stream->Close();
104 return NULL;;
105 }
106 return stream;
107 }
108
109 void AudioOutputDispatcher::OpenTask() {
110 base::TimeDelta last_activity_delay =
111 base::Time::Now() - last_activity_time_;
112
113 if (last_activity_delay < close_delay_) {
114 // Make sure that we have at least one stream allocated if there
115 // are paused streams.
116 if (paused_proxies_ > 0 && streams_.size() == 0) {
117 AudioOutputStream* stream = CreateAndOpenStream();
118 if (stream) {
119 streams_.push_back(stream);
120 }
121 }
122 }
123
124 // Schedule close task, so that the stream is closed if it is not
125 // used.
126 ScheduleCloseTask();
127 }
128
129 void AudioOutputDispatcher::CloseTask() {
130 close_task_scheduled_ = false;
131 ClosePendingStreams();
132 }
133
134 void AudioOutputDispatcher::ClosePendingStreams() {
135 bool delay_expired = (base::Time::Now() - last_activity_time_) >=
136 close_delay_;
137
138 // We never need to have more than |paused_proxies_| streams.
139 int max_pending_streams = paused_proxies_;
scherkus (not reviewing) 2010/11/22 06:43:15 nit: remove one space between = and paused_proxies
Sergey Ulanov 2010/11/23 19:51:46 Done.
140
141 if (delay_expired) {
142 // Enough time has expired since the last activity. Close all
143 // pending streams.
144 max_pending_streams = 0;
145 }
146
147 // Close streams we don't need anymore.
148 while (static_cast<int>(streams_.size()) > max_pending_streams) {
149 streams_.back()->Close();
150 streams_.pop_back();
151 }
152
153 if (!delay_expired && streams_.size() > 0) {
154 ScheduleCloseTask();
155 }
156 }
157
158 void AudioOutputDispatcher::ScheduleCloseTask() {
159 if (close_task_scheduled_) {
scherkus (not reviewing) 2010/11/22 06:43:15 nit: DCHECK for the message loop
Sergey Ulanov 2010/11/23 19:51:46 Done.
160 // There is a pending task. Don't schedule another one.
161 return;
162 }
163
164 base::TimeDelta last_activity_delay =
165 base::Time::Now() - last_activity_time_;
166 int64 next_task_delay_ms =
167 (close_delay_ - last_activity_delay).InMillisecondsRoundedUp();
168 if (next_task_delay_ms <= 0)
169 next_task_delay_ms = 0;
170
171 message_loop_->PostDelayedTask(
172 FROM_HERE,
173 NewRunnableMethod(this, &AudioOutputDispatcher::CloseTask),
174 next_task_delay_ms);
175
176 close_task_scheduled_ = true;
177 }
178
179 void AudioOutputDispatcher::set_close_delay(base::TimeDelta delay) {
180 close_delay_ = delay;
181 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698