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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: media/audio/audio_output_dispatcher.cc
diff --git a/media/audio/audio_output_dispatcher.cc b/media/audio/audio_output_dispatcher.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c861d559c5821720980e554faaa9f04b9497e948
--- /dev/null
+++ b/media/audio/audio_output_dispatcher.cc
@@ -0,0 +1,181 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/audio/audio_output_dispatcher.h"
+
+#include "base/message_loop.h"
+#include "media/audio/audio_io.h"
+
+namespace {
+// 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.
+// audio device is closed.
+const int kStreamCloseDelayMs = 5000;
+} // namespace
+
+AudioOutputDispatcher::AudioOutputDispatcher(
+ AudioManager* audio_manager, const AudioParameters& params)
+ : audio_manager_(audio_manager),
+ message_loop_(audio_manager->GetMessageLoop()),
+ params_(params),
+ close_delay_(base::TimeDelta::FromMilliseconds(
+ kStreamCloseDelayMs)),
+ paused_proxies_(0),
+ last_activity_time_(base::Time::Now()),
+ close_task_scheduled_(false) {
+}
+
+AudioOutputDispatcher::~AudioOutputDispatcher() {
+}
+
+bool AudioOutputDispatcher::StreamOpened() {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ 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.
+ last_activity_time_ = base::Time::Now();
+
+ // 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
+ if (streams_.size() == 0) {
+ AudioOutputStream* stream = CreateAndOpenStream();
+ if (!stream) {
+ return false;
+ }
+ streams_.push_back(stream);
+ }
+
+ // Schedule close task so that the stream is closed later if it is
+ // not used.
+ ScheduleCloseTask();
+
+ return true;
+}
+
+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
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ AudioOutputStream* stream;
+ if (streams_.size() == 0) {
+ 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!
+ if (!stream) {
+ return NULL;
+ }
+ } else {
+ stream = streams_.back();
+ streams_.pop_back();
+ }
+
+ paused_proxies_--;
+ DCHECK_GE(paused_proxies_, 0);
+
+ last_activity_time_ = base::Time::Now();
+
+ // Schedule task to allocate streams for other proxies if we need to.
+ message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &AudioOutputDispatcher::OpenTask));
+
+ return stream;
+}
+
+void AudioOutputDispatcher::StreamStopped(AudioOutputStream* stream) {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ paused_proxies_++;
+ streams_.push_back(stream);
+ last_activity_time_ = base::Time::Now();
+ ScheduleCloseTask();
+}
+
+void AudioOutputDispatcher::StreamClosed() {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ paused_proxies_--;
+ DCHECK_GE(paused_proxies_, 0);
+ ClosePendingStreams();
+}
+
+MessageLoop* AudioOutputDispatcher::message_loop() {
+ return message_loop_;
+}
+
+AudioOutputStream* AudioOutputDispatcher::CreateAndOpenStream() {
+ AudioOutputStream* stream =
+ audio_manager_->MakeAudioOutputStream(params_);
+ if (!stream) {
+ return NULL;
+ }
+ if (!stream->Open()) {
+ stream->Close();
+ return NULL;;
+ }
+ return stream;
+}
+
+void AudioOutputDispatcher::OpenTask() {
+ base::TimeDelta last_activity_delay =
+ base::Time::Now() - last_activity_time_;
+
+ if (last_activity_delay < close_delay_) {
+ // Make sure that we have at least one stream allocated if there
+ // are paused streams.
+ if (paused_proxies_ > 0 && streams_.size() == 0) {
+ AudioOutputStream* stream = CreateAndOpenStream();
+ if (stream) {
+ streams_.push_back(stream);
+ }
+ }
+ }
+
+ // Schedule close task, so that the stream is closed if it is not
+ // used.
+ ScheduleCloseTask();
+}
+
+void AudioOutputDispatcher::CloseTask() {
+ close_task_scheduled_ = false;
+ ClosePendingStreams();
+}
+
+void AudioOutputDispatcher::ClosePendingStreams() {
+ bool delay_expired = (base::Time::Now() - last_activity_time_) >=
+ close_delay_;
+
+ // We never need to have more than |paused_proxies_| streams.
+ 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.
+
+ if (delay_expired) {
+ // Enough time has expired since the last activity. Close all
+ // pending streams.
+ max_pending_streams = 0;
+ }
+
+ // Close streams we don't need anymore.
+ while (static_cast<int>(streams_.size()) > max_pending_streams) {
+ streams_.back()->Close();
+ streams_.pop_back();
+ }
+
+ if (!delay_expired && streams_.size() > 0) {
+ ScheduleCloseTask();
+ }
+}
+
+void AudioOutputDispatcher::ScheduleCloseTask() {
+ 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.
+ // There is a pending task. Don't schedule another one.
+ return;
+ }
+
+ base::TimeDelta last_activity_delay =
+ base::Time::Now() - last_activity_time_;
+ int64 next_task_delay_ms =
+ (close_delay_ - last_activity_delay).InMillisecondsRoundedUp();
+ if (next_task_delay_ms <= 0)
+ next_task_delay_ms = 0;
+
+ message_loop_->PostDelayedTask(
+ FROM_HERE,
+ NewRunnableMethod(this, &AudioOutputDispatcher::CloseTask),
+ next_task_delay_ms);
+
+ close_task_scheduled_ = true;
+}
+
+void AudioOutputDispatcher::set_close_delay(base::TimeDelta delay) {
+ close_delay_ = delay;
+}

Powered by Google App Engine
This is Rietveld 408576698