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

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

Issue 6822019: Fix erratic HTML5 audio playback (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: more fixup Created 9 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/base/pipeline_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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/compiler_specific.h" 7 #include "base/compiler_specific.h"
8 #include "base/message_loop.h" 8 #include "base/message_loop.h"
9 #include "base/time.h"
9 #include "media/audio/audio_io.h" 10 #include "media/audio/audio_io.h"
10 11
11 AudioOutputDispatcher::AudioOutputDispatcher( 12 AudioOutputDispatcher::AudioOutputDispatcher(
12 AudioManager* audio_manager, const AudioParameters& params, 13 AudioManager* audio_manager, const AudioParameters& params,
13 int close_delay_ms) 14 int close_delay_ms)
14 : audio_manager_(audio_manager), 15 : audio_manager_(audio_manager),
15 message_loop_(audio_manager->GetMessageLoop()), 16 message_loop_(audio_manager->GetMessageLoop()),
16 params_(params), 17 params_(params),
18 pause_delay_milliseconds_(2 * params.samples_per_packet *
19 base::Time::kMillisecondsPerSecond / params.sample_rate),
17 paused_proxies_(0), 20 paused_proxies_(0),
18 ALLOW_THIS_IN_INITIALIZER_LIST(close_timer_( 21 ALLOW_THIS_IN_INITIALIZER_LIST(close_timer_(
19 base::TimeDelta::FromMilliseconds(close_delay_ms), 22 base::TimeDelta::FromMilliseconds(close_delay_ms),
20 this, &AudioOutputDispatcher::ClosePendingStreams)) { 23 this, &AudioOutputDispatcher::ClosePendingStreams)) {
21 } 24 }
22 25
23 AudioOutputDispatcher::~AudioOutputDispatcher() { 26 AudioOutputDispatcher::~AudioOutputDispatcher() {
27 while (!pausing_streams_.empty()) {
28 pausing_streams_.back()->Close();
29 pausing_streams_.pop_back();
30 }
24 } 31 }
25 32
26 bool AudioOutputDispatcher::StreamOpened() { 33 bool AudioOutputDispatcher::StreamOpened() {
27 DCHECK_EQ(MessageLoop::current(), message_loop_); 34 DCHECK_EQ(MessageLoop::current(), message_loop_);
28 paused_proxies_++; 35 paused_proxies_++;
29 36
30 // Ensure that there is at least one open stream. 37 // Ensure that there is at least one open stream.
31 if (streams_.empty() && !CreateAndOpenStream()) { 38 if (idle_streams_.empty() && !CreateAndOpenStream()) {
32 return false; 39 return false;
33 } 40 }
34 41
35 close_timer_.Reset(); 42 close_timer_.Reset();
36 43
37 return true; 44 return true;
38 } 45 }
39 46
40 AudioOutputStream* AudioOutputDispatcher::StreamStarted() { 47 AudioOutputStream* AudioOutputDispatcher::StreamStarted() {
41 DCHECK_EQ(MessageLoop::current(), message_loop_); 48 DCHECK_EQ(MessageLoop::current(), message_loop_);
42 49
43 if (streams_.empty() && !CreateAndOpenStream()) { 50 if (idle_streams_.empty() && !CreateAndOpenStream()) {
44 return NULL; 51 return NULL;
45 } 52 }
46 53
47 AudioOutputStream* stream = streams_.back(); 54 AudioOutputStream* stream = idle_streams_.back();
48 streams_.pop_back(); 55 idle_streams_.pop_back();
49 56
50 DCHECK_GT(paused_proxies_, 0u); 57 DCHECK_GT(paused_proxies_, 0u);
51 paused_proxies_--; 58 paused_proxies_--;
52 59
53 close_timer_.Reset(); 60 close_timer_.Reset();
54 61
55 // Schedule task to allocate streams for other proxies if we need to. 62 // Schedule task to allocate streams for other proxies if we need to.
56 message_loop_->PostTask(FROM_HERE, NewRunnableMethod( 63 message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
57 this, &AudioOutputDispatcher::OpenTask)); 64 this, &AudioOutputDispatcher::OpenTask));
58 65
59 return stream; 66 return stream;
60 } 67 }
61 68
62 void AudioOutputDispatcher::StreamStopped(AudioOutputStream* stream) { 69 void AudioOutputDispatcher::StreamStopped(AudioOutputStream* stream) {
63 DCHECK_EQ(MessageLoop::current(), message_loop_); 70 DCHECK_EQ(MessageLoop::current(), message_loop_);
71
64 paused_proxies_++; 72 paused_proxies_++;
65 streams_.push_back(stream); 73
74 pausing_streams_.push_front(stream);
66 close_timer_.Reset(); 75 close_timer_.Reset();
76
77 // Don't recycle stream until two buffers worth of time has elapsed
Sergey Ulanov 2011/04/13 02:02:54 nit: period at the end of the sentence.
78 message_loop_->PostDelayedTask(
79 FROM_HERE,
80 NewRunnableMethod(this, &AudioOutputDispatcher::StopStreamTask),
81 pause_delay_milliseconds_);
82 }
83
84 void AudioOutputDispatcher::StopStreamTask() {
85 if (pausing_streams_.empty())
86 return;
87 AudioOutputStream* stream = pausing_streams_.back();
88 pausing_streams_.pop_back();
89 idle_streams_.push_back(stream);
67 } 90 }
68 91
69 void AudioOutputDispatcher::StreamClosed() { 92 void AudioOutputDispatcher::StreamClosed() {
70 DCHECK_EQ(MessageLoop::current(), message_loop_); 93 DCHECK_EQ(MessageLoop::current(), message_loop_);
71 94
72 DCHECK_GT(paused_proxies_, 0u); 95 DCHECK_GT(paused_proxies_, 0u);
73 paused_proxies_--; 96 paused_proxies_--;
74 97
75 while (streams_.size() > paused_proxies_) { 98 while (idle_streams_.size() > paused_proxies_) {
76 streams_.back()->Close(); 99 idle_streams_.back()->Close();
77 streams_.pop_back(); 100 idle_streams_.pop_back();
78 } 101 }
79 } 102 }
80 103
81 MessageLoop* AudioOutputDispatcher::message_loop() { 104 MessageLoop* AudioOutputDispatcher::message_loop() {
82 return message_loop_; 105 return message_loop_;
83 } 106 }
84 107
85 bool AudioOutputDispatcher::CreateAndOpenStream() { 108 bool AudioOutputDispatcher::CreateAndOpenStream() {
86 AudioOutputStream* stream = 109 AudioOutputStream* stream =
87 audio_manager_->MakeAudioOutputStream(params_); 110 audio_manager_->MakeAudioOutputStream(params_);
88 if (!stream) { 111 if (!stream) {
89 return false; 112 return false;
90 } 113 }
91 if (!stream->Open()) { 114 if (!stream->Open()) {
92 stream->Close(); 115 stream->Close();
93 return false; 116 return false;
94 } 117 }
95 streams_.push_back(stream); 118 idle_streams_.push_back(stream);
96 return true; 119 return true;
97 } 120 }
98 121
99 void AudioOutputDispatcher::OpenTask() { 122 void AudioOutputDispatcher::OpenTask() {
100 // Make sure that we have at least one stream allocated if there 123 // Make sure that we have at least one stream allocated if there
101 // are paused streams. 124 // are paused streams.
102 if (paused_proxies_ > 0 && streams_.empty()) { 125 if (paused_proxies_ > 0 && idle_streams_.empty()) {
103 CreateAndOpenStream(); 126 CreateAndOpenStream();
104 } 127 }
105 128
106 close_timer_.Reset(); 129 close_timer_.Reset();
107 } 130 }
108 131
109 // This method is called by |close_timer_|. 132 // This method is called by |close_timer_|.
110 void AudioOutputDispatcher::ClosePendingStreams() { 133 void AudioOutputDispatcher::ClosePendingStreams() {
111 while (!streams_.empty()) { 134 while (!idle_streams_.empty()) {
112 streams_.back()->Close(); 135 idle_streams_.back()->Close();
113 streams_.pop_back(); 136 idle_streams_.pop_back();
114 } 137 }
115 } 138 }
OLDNEW
« no previous file with comments | « media/audio/audio_output_dispatcher.h ('k') | media/base/pipeline_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698