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

Side by Side Diff: content/renderer/pepper/pepper_media_stream_audio_track_host.cc

Issue 417753002: Fix a race condition in MediaStreamAudioTrackHost. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Upload Created 6 years, 5 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "content/renderer/pepper/pepper_media_stream_audio_track_host.h" 5 #include "content/renderer/pepper/pepper_media_stream_audio_track_host.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/location.h" 10 #include "base/location.h"
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 } 58 }
59 59
60 } // namespace 60 } // namespace
61 61
62 namespace content { 62 namespace content {
63 63
64 PepperMediaStreamAudioTrackHost::AudioSink::AudioSink( 64 PepperMediaStreamAudioTrackHost::AudioSink::AudioSink(
65 PepperMediaStreamAudioTrackHost* host) 65 PepperMediaStreamAudioTrackHost* host)
66 : host_(host), 66 : host_(host),
67 buffer_data_size_(0), 67 buffer_data_size_(0),
68 init_buffers_count_(0),
68 main_message_loop_proxy_(base::MessageLoopProxy::current()), 69 main_message_loop_proxy_(base::MessageLoopProxy::current()),
69 weak_factory_(this), 70 weak_factory_(this),
70 number_of_buffers_(kDefaultNumberOfBuffers), 71 number_of_buffers_(kDefaultNumberOfBuffers),
71 bytes_per_second_(0) {} 72 bytes_per_second_(0) {}
72 73
73 PepperMediaStreamAudioTrackHost::AudioSink::~AudioSink() { 74 PepperMediaStreamAudioTrackHost::AudioSink::~AudioSink() {
74 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); 75 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current());
75 } 76 }
76 77
77 void PepperMediaStreamAudioTrackHost::AudioSink::EnqueueBuffer(int32_t index) { 78 void PepperMediaStreamAudioTrackHost::AudioSink::EnqueueBuffer(int32_t index) {
(...skipping 18 matching lines...) Expand all
96 } 97 }
97 98
98 void PepperMediaStreamAudioTrackHost::AudioSink::SetFormatOnMainThread( 99 void PepperMediaStreamAudioTrackHost::AudioSink::SetFormatOnMainThread(
99 int bytes_per_second) { 100 int bytes_per_second) {
100 bytes_per_second_ = bytes_per_second; 101 bytes_per_second_ = bytes_per_second;
101 InitBuffers(); 102 InitBuffers();
102 } 103 }
103 104
104 void PepperMediaStreamAudioTrackHost::AudioSink::InitBuffers() { 105 void PepperMediaStreamAudioTrackHost::AudioSink::InitBuffers() {
105 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); 106 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current());
107 {
108 base::AutoLock lock(lock_);
109 // Clear |buffers_|, so the audio thread will drop all incoming audio data.
110 buffers_.clear();
111 init_buffers_count_++;
112 }
106 // The size is slightly bigger than necessary, because 8 extra bytes are 113 // The size is slightly bigger than necessary, because 8 extra bytes are
107 // added into the struct. Also see |MediaStreamBuffer|. 114 // added into the struct. Also see |MediaStreamBuffer|.
108 base::CheckedNumeric<int32_t> buffer_size = bytes_per_second_; 115 base::CheckedNumeric<int32_t> buffer_size = bytes_per_second_;
109 buffer_size *= kMaxDuration; 116 buffer_size *= kMaxDuration;
110 buffer_size /= base::Time::kMillisecondsPerSecond; 117 buffer_size /= base::Time::kMillisecondsPerSecond;
111 buffer_size += sizeof(ppapi::MediaStreamBuffer::Audio); 118 buffer_size += sizeof(ppapi::MediaStreamBuffer::Audio);
119
120 // We don't need hold |lock_| during |host->InitBuffers()| call, because
dmichael (off chromium) 2014/07/24 16:42:56 need +to+ hold
Peng 2014/07/25 15:25:31 Done.
121 // we just cleared |buffers_| , so the audio thread will drop all incoming
122 // audio data, and not use buffers in |host_|.
112 bool result = host_->InitBuffers(number_of_buffers_, 123 bool result = host_->InitBuffers(number_of_buffers_,
113 buffer_size.ValueOrDie(), 124 buffer_size.ValueOrDie(),
114 kRead); 125 kRead);
115 // TODO(penghuang): Send PP_ERROR_NOMEMORY to plugin. 126 // TODO(penghuang): Send PP_ERROR_NOMEMORY to plugin.
116 CHECK(result); 127 CHECK(result);
128
129 // Fill the |buffers_|, so the audio thread can continue receiving audio data.
117 base::AutoLock lock(lock_); 130 base::AutoLock lock(lock_);
118 buffers_.clear();
119 for (int32_t i = 0; i < number_of_buffers_; ++i) { 131 for (int32_t i = 0; i < number_of_buffers_; ++i) {
120 int32_t index = host_->buffer_manager()->DequeueBuffer(); 132 int32_t index = host_->buffer_manager()->DequeueBuffer();
121 DCHECK_GE(index, 0); 133 DCHECK_GE(index, 0);
122 buffers_.push_back(index); 134 buffers_.push_back(index);
123 } 135 }
124 } 136 }
125 137
126 void PepperMediaStreamAudioTrackHost::AudioSink:: 138 void PepperMediaStreamAudioTrackHost::AudioSink::
127 SendEnqueueBufferMessageOnMainThread(int32_t index) { 139 SendEnqueueBufferMessageOnMainThread(int32_t index,
140 int32_t init_buffers_count) {
128 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); 141 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current());
129 host_->SendEnqueueBufferMessageToPlugin(index); 142 // If |InitBuffers()| is called after this task being posted from the audio
143 // thread, the buffer should become invalid already. We should ignore it.
144 // And because only the main thread modifies the |init_buffers_count_|,
145 // so we don't need lock |lock_| here (main thread).
Anand Mistry (off Chromium) 2014/07/25 00:42:54 Although I'll agree this is a benign read, I think
Peng 2014/07/25 15:25:31 I think rwlock is better for this case, but I can
dmichael (off chromium) 2014/07/28 19:30:43 I don't think TSAN will flag it; I think it's fine
146 if (init_buffers_count == init_buffers_count_)
147 host_->SendEnqueueBufferMessageToPlugin(index);
130 } 148 }
131 149
132 void PepperMediaStreamAudioTrackHost::AudioSink::OnData(const int16* audio_data, 150 void PepperMediaStreamAudioTrackHost::AudioSink::OnData(const int16* audio_data,
133 int sample_rate, 151 int sample_rate,
134 int number_of_channels, 152 int number_of_channels,
135 int number_of_frames) { 153 int number_of_frames) {
136 DCHECK(audio_thread_checker_.CalledOnValidThread()); 154 DCHECK(audio_thread_checker_.CalledOnValidThread());
137 DCHECK(audio_data); 155 DCHECK(audio_data);
138 DCHECK_EQ(sample_rate, audio_params_.sample_rate()); 156 DCHECK_EQ(sample_rate, audio_params_.sample_rate());
139 DCHECK_EQ(number_of_channels, audio_params_.channels()); 157 DCHECK_EQ(number_of_channels, audio_params_.channels());
140 DCHECK_EQ(number_of_frames, audio_params_.frames_per_buffer()); 158 DCHECK_EQ(number_of_frames, audio_params_.frames_per_buffer());
141 int32_t index = -1;
142 {
143 base::AutoLock lock(lock_);
144 if (!buffers_.empty()) {
145 index = buffers_.front();
146 buffers_.pop_front();
147 }
148 }
149 159
150 if (index != -1) { 160 base::AutoLock lock(lock_);
161 if (!buffers_.empty()) {
162 int index = buffers_.front();
163 buffers_.pop_front();
151 // TODO(penghuang): support re-sampling, etc. 164 // TODO(penghuang): support re-sampling, etc.
152 ppapi::MediaStreamBuffer::Audio* buffer = 165 ppapi::MediaStreamBuffer::Audio* buffer =
153 &(host_->buffer_manager()->GetBufferPointer(index)->audio); 166 &(host_->buffer_manager()->GetBufferPointer(index)->audio);
154 buffer->header.size = host_->buffer_manager()->buffer_size(); 167 buffer->header.size = host_->buffer_manager()->buffer_size();
155 buffer->header.type = ppapi::MediaStreamBuffer::TYPE_AUDIO; 168 buffer->header.type = ppapi::MediaStreamBuffer::TYPE_AUDIO;
156 buffer->timestamp = timestamp_.InMillisecondsF(); 169 buffer->timestamp = timestamp_.InMillisecondsF();
157 buffer->sample_rate = static_cast<PP_AudioBuffer_SampleRate>(sample_rate); 170 buffer->sample_rate = static_cast<PP_AudioBuffer_SampleRate>(sample_rate);
158 buffer->number_of_channels = number_of_channels; 171 buffer->number_of_channels = number_of_channels;
159 buffer->number_of_samples = number_of_channels * number_of_frames; 172 buffer->number_of_samples = number_of_channels * number_of_frames;
160 buffer->data_size = buffer_data_size_; 173 buffer->data_size = buffer_data_size_;
161 memcpy(buffer->data, audio_data, buffer_data_size_); 174 memcpy(buffer->data, audio_data, buffer_data_size_);
162 175
163 main_message_loop_proxy_->PostTask( 176 main_message_loop_proxy_->PostTask(
164 FROM_HERE, 177 FROM_HERE,
165 base::Bind(&AudioSink::SendEnqueueBufferMessageOnMainThread, 178 base::Bind(&AudioSink::SendEnqueueBufferMessageOnMainThread,
166 weak_factory_.GetWeakPtr(), 179 weak_factory_.GetWeakPtr(),
167 index)); 180 index,
181 init_buffers_count_));
168 } 182 }
169 timestamp_ += buffer_duration_; 183 timestamp_ += buffer_duration_;
170 } 184 }
171 185
172 void PepperMediaStreamAudioTrackHost::AudioSink::OnSetFormat( 186 void PepperMediaStreamAudioTrackHost::AudioSink::OnSetFormat(
173 const AudioParameters& params) { 187 const AudioParameters& params) {
174 DCHECK(params.IsValid()); 188 DCHECK(params.IsValid());
175 DCHECK_LE(params.GetBufferDuration().InMilliseconds(), kMaxDuration); 189 DCHECK_LE(params.GetBufferDuration().InMilliseconds(), kMaxDuration);
176 DCHECK_EQ(params.bits_per_sample(), 16); 190 DCHECK_EQ(params.bits_per_sample(), 16);
177 DCHECK_NE(GetPPSampleRate(params.sample_rate()), 191 DCHECK_NE(GetPPSampleRate(params.sample_rate()),
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 } 270 }
257 271
258 void PepperMediaStreamAudioTrackHost::DidConnectPendingHostToResource() { 272 void PepperMediaStreamAudioTrackHost::DidConnectPendingHostToResource() {
259 if (!connected_) { 273 if (!connected_) {
260 MediaStreamAudioSink::AddToAudioTrack(&audio_sink_, track_); 274 MediaStreamAudioSink::AddToAudioTrack(&audio_sink_, track_);
261 connected_ = true; 275 connected_ = true;
262 } 276 }
263 } 277 }
264 278
265 } // namespace content 279 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698