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

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

Issue 9691001: Audio software mixer. (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Created 8 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « media/audio/audio_output_dispatcher.h ('k') | media/audio/audio_output_dispatcher_impl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/audio/audio_output_dispatcher.h" 5 #include "media/audio/audio_output_dispatcher.h"
6 6
7 #include "base/bind.h"
8 #include "base/compiler_specific.h"
9 #include "base/message_loop.h" 7 #include "base/message_loop.h"
10 #include "base/time.h"
11 #include "media/audio/audio_io.h"
12 8
13 namespace media { 9 namespace media {
14 10
15 AudioOutputDispatcher::AudioOutputDispatcher( 11 AudioOutputDispatcher::AudioOutputDispatcher(
16 AudioManager* audio_manager, const AudioParameters& params, 12 AudioManager* audio_manager,
17 base::TimeDelta close_delay) 13 const AudioParameters& params)
18 : audio_manager_(audio_manager), 14 : audio_manager_(audio_manager),
19 message_loop_(MessageLoop::current()), 15 message_loop_(MessageLoop::current()),
20 params_(params), 16 params_(params) {
21 pause_delay_(base::TimeDelta::FromMilliseconds(
22 2 * params.frames_per_buffer() *
23 base::Time::kMillisecondsPerSecond / params.sample_rate())),
24 paused_proxies_(0),
25 ALLOW_THIS_IN_INITIALIZER_LIST(weak_this_(this)),
26 close_timer_(FROM_HERE,
27 close_delay,
28 weak_this_.GetWeakPtr(),
29 &AudioOutputDispatcher::ClosePendingStreams) {
30 // We expect to be instantiated on the audio thread. Otherwise the 17 // We expect to be instantiated on the audio thread. Otherwise the
31 // message_loop_ member will point to the wrong message loop! 18 // message_loop_ member will point to the wrong message loop!
32 DCHECK(audio_manager->GetMessageLoop()->BelongsToCurrentThread()); 19 DCHECK(audio_manager->GetMessageLoop()->BelongsToCurrentThread());
33 } 20 }
34 21
35 AudioOutputDispatcher::~AudioOutputDispatcher() { 22 AudioOutputDispatcher::~AudioOutputDispatcher() {
36 DCHECK_EQ(MessageLoop::current(), message_loop_); 23 DCHECK_EQ(MessageLoop::current(), message_loop_);
37 } 24 }
38 25
39 bool AudioOutputDispatcher::StreamOpened() {
40 DCHECK_EQ(MessageLoop::current(), message_loop_);
41 paused_proxies_++;
42
43 // Ensure that there is at least one open stream.
44 if (idle_streams_.empty() && !CreateAndOpenStream()) {
45 return false;
46 }
47
48 close_timer_.Reset();
49
50 return true;
51 }
52
53 AudioOutputStream* AudioOutputDispatcher::StreamStarted() {
54 DCHECK_EQ(MessageLoop::current(), message_loop_);
55
56 if (idle_streams_.empty() && !CreateAndOpenStream()) {
57 return NULL;
58 }
59
60 AudioOutputStream* stream = idle_streams_.back();
61 idle_streams_.pop_back();
62
63 DCHECK_GT(paused_proxies_, 0u);
64 paused_proxies_--;
65
66 close_timer_.Reset();
67
68 // Schedule task to allocate streams for other proxies if we need to.
69 message_loop_->PostTask(FROM_HERE, base::Bind(
70 &AudioOutputDispatcher::OpenTask, weak_this_.GetWeakPtr()));
71
72 return stream;
73 }
74
75 void AudioOutputDispatcher::StreamStopped(AudioOutputStream* stream) {
76 DCHECK_EQ(MessageLoop::current(), message_loop_);
77
78 paused_proxies_++;
79
80 pausing_streams_.push_front(stream);
81
82 // Don't recycle stream until two buffers worth of time has elapsed.
83 message_loop_->PostDelayedTask(
84 FROM_HERE,
85 base::Bind(&AudioOutputDispatcher::StopStreamTask,
86 weak_this_.GetWeakPtr()),
87 pause_delay_);
88 }
89
90 void AudioOutputDispatcher::StopStreamTask() {
91 DCHECK_EQ(MessageLoop::current(), message_loop_);
92
93 if (pausing_streams_.empty())
94 return;
95
96 AudioOutputStream* stream = pausing_streams_.back();
97 pausing_streams_.pop_back();
98 idle_streams_.push_back(stream);
99 close_timer_.Reset();
100 }
101
102 void AudioOutputDispatcher::StreamClosed() {
103 DCHECK_EQ(MessageLoop::current(), message_loop_);
104
105 while (!pausing_streams_.empty()) {
106 idle_streams_.push_back(pausing_streams_.back());
107 pausing_streams_.pop_back();
108 }
109
110 DCHECK_GT(paused_proxies_, 0u);
111 paused_proxies_--;
112
113 while (idle_streams_.size() > paused_proxies_) {
114 idle_streams_.back()->Close();
115 idle_streams_.pop_back();
116 }
117 }
118
119 void AudioOutputDispatcher::Shutdown() {
120 DCHECK_EQ(MessageLoop::current(), message_loop_);
121
122 // Cancel any pending tasks to close paused streams or create new ones.
123 weak_this_.InvalidateWeakPtrs();
124
125 // No AudioOutputProxy objects should hold a reference to us when we get
126 // to this stage.
127 DCHECK(HasOneRef()) << "Only the AudioManager should hold a reference";
128
129 AudioOutputStreamList::iterator it = idle_streams_.begin();
130 for (; it != idle_streams_.end(); ++it)
131 (*it)->Close();
132 idle_streams_.clear();
133
134 it = pausing_streams_.begin();
135 for (; it != pausing_streams_.end(); ++it)
136 (*it)->Close();
137 pausing_streams_.clear();
138 }
139
140 bool AudioOutputDispatcher::CreateAndOpenStream() {
141 AudioOutputStream* stream = audio_manager_->MakeAudioOutputStream(params_);
142 if (!stream)
143 return false;
144
145 if (!stream->Open()) {
146 stream->Close();
147 return false;
148 }
149 idle_streams_.push_back(stream);
150 return true;
151 }
152
153 void AudioOutputDispatcher::OpenTask() {
154 // Make sure that we have at least one stream allocated if there
155 // are paused streams.
156 if (paused_proxies_ > 0 && idle_streams_.empty() &&
157 pausing_streams_.empty()) {
158 CreateAndOpenStream();
159 }
160
161 close_timer_.Reset();
162 }
163
164 // This method is called by |close_timer_|.
165 void AudioOutputDispatcher::ClosePendingStreams() {
166 DCHECK_EQ(MessageLoop::current(), message_loop_);
167
168 while (!idle_streams_.empty()) {
169 idle_streams_.back()->Close();
170 idle_streams_.pop_back();
171 }
172 }
173
174 } // namespace media 26 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/audio_output_dispatcher.h ('k') | media/audio/audio_output_dispatcher_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698