OLD | NEW |
---|---|
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" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/macros.h" | 12 #include "base/macros.h" |
13 #include "base/message_loop/message_loop_proxy.h" | 13 #include "base/message_loop/message_loop_proxy.h" |
14 #include "base/numerics/safe_math.h" | 14 #include "base/numerics/safe_math.h" |
15 #include "ppapi/c/pp_errors.h" | 15 #include "ppapi/c/pp_errors.h" |
16 #include "ppapi/c/ppb_audio_buffer.h" | 16 #include "ppapi/c/ppb_audio_buffer.h" |
17 #include "ppapi/host/dispatch_host_message.h" | 17 #include "ppapi/host/dispatch_host_message.h" |
18 #include "ppapi/host/host_message_context.h" | 18 #include "ppapi/host/host_message_context.h" |
19 #include "ppapi/proxy/ppapi_messages.h" | 19 #include "ppapi/proxy/ppapi_messages.h" |
20 #include "ppapi/shared_impl/media_stream_audio_track_shared.h" | 20 #include "ppapi/shared_impl/media_stream_audio_track_shared.h" |
21 #include "ppapi/shared_impl/media_stream_buffer.h" | 21 #include "ppapi/shared_impl/media_stream_buffer.h" |
22 | 22 |
23 using media::AudioParameters; | 23 using media::AudioParameters; |
24 using ppapi::host::HostMessageContext; | 24 using ppapi::host::HostMessageContext; |
25 using ppapi::MediaStreamAudioTrackShared; | 25 using ppapi::MediaStreamAudioTrackShared; |
26 | 26 |
27 namespace { | 27 namespace { |
28 | 28 |
29 // Max audio buffer duration in milliseconds. | 29 // Audio buffer durations in milliseconds. |
30 const uint32_t kMaxDuration = 10; | 30 const uint32_t kMinDuration = 10; |
31 const uint32_t kDefaultDuration = 10; | |
31 | 32 |
32 const int32_t kDefaultNumberOfBuffers = 4; | 33 const int32_t kDefaultNumberOfBuffers = 4; |
33 const int32_t kMaxNumberOfBuffers = 1000; // 10 sec | 34 const int32_t kMaxNumberOfBuffers = 1000; // 10 sec |
34 | 35 |
35 // Returns true if the |sample_rate| is supported in | 36 // Returns true if the |sample_rate| is supported in |
36 // |PP_AudioBuffer_SampleRate|, otherwise false. | 37 // |PP_AudioBuffer_SampleRate|, otherwise false. |
37 PP_AudioBuffer_SampleRate GetPPSampleRate(int sample_rate) { | 38 PP_AudioBuffer_SampleRate GetPPSampleRate(int sample_rate) { |
38 switch (sample_rate) { | 39 switch (sample_rate) { |
39 case 8000: | 40 case 8000: |
40 return PP_AUDIOBUFFER_SAMPLERATE_8000; | 41 return PP_AUDIOBUFFER_SAMPLERATE_8000; |
(...skipping 17 matching lines...) Expand all Loading... | |
58 } | 59 } |
59 | 60 |
60 } // namespace | 61 } // namespace |
61 | 62 |
62 namespace content { | 63 namespace content { |
63 | 64 |
64 PepperMediaStreamAudioTrackHost::AudioSink::AudioSink( | 65 PepperMediaStreamAudioTrackHost::AudioSink::AudioSink( |
65 PepperMediaStreamAudioTrackHost* host) | 66 PepperMediaStreamAudioTrackHost* host) |
66 : host_(host), | 67 : host_(host), |
67 buffer_data_size_(0), | 68 buffer_data_size_(0), |
69 active_buffer_index_(-1), | |
70 active_buffers_generation_(0), | |
71 active_buffer_offset_(0), | |
68 buffers_generation_(0), | 72 buffers_generation_(0), |
69 main_message_loop_proxy_(base::MessageLoopProxy::current()), | 73 main_message_loop_proxy_(base::MessageLoopProxy::current()), |
70 weak_factory_(this), | 74 weak_factory_(this), |
71 number_of_buffers_(kDefaultNumberOfBuffers), | 75 number_of_buffers_(kDefaultNumberOfBuffers), |
72 bytes_per_second_(0) {} | 76 bytes_per_second_(0), |
77 user_buffer_duration_(kDefaultDuration) {} | |
73 | 78 |
74 PepperMediaStreamAudioTrackHost::AudioSink::~AudioSink() { | 79 PepperMediaStreamAudioTrackHost::AudioSink::~AudioSink() { |
75 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | 80 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
76 } | 81 } |
77 | 82 |
78 void PepperMediaStreamAudioTrackHost::AudioSink::EnqueueBuffer(int32_t index) { | 83 void PepperMediaStreamAudioTrackHost::AudioSink::EnqueueBuffer(int32_t index) { |
79 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | 84 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
80 DCHECK_GE(index, 0); | 85 DCHECK_GE(index, 0); |
81 DCHECK_LT(index, host_->buffer_manager()->number_of_buffers()); | 86 DCHECK_LT(index, host_->buffer_manager()->number_of_buffers()); |
82 base::AutoLock lock(lock_); | 87 base::AutoLock lock(lock_); |
83 buffers_.push_back(index); | 88 buffers_.push_back(index); |
84 } | 89 } |
85 | 90 |
86 void PepperMediaStreamAudioTrackHost::AudioSink::Configure( | 91 void PepperMediaStreamAudioTrackHost::AudioSink::Configure( |
87 int32_t number_of_buffers) { | 92 int32_t number_of_buffers, int32_t duration) { |
88 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | 93 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
89 bool changed = false; | 94 bool changed = false; |
90 if (number_of_buffers != number_of_buffers_) | 95 if (number_of_buffers != number_of_buffers_) |
91 changed = true; | 96 changed = true; |
97 if (duration != 0 && duration != user_buffer_duration_) { | |
98 user_buffer_duration_ = duration; | |
99 changed = true; | |
100 } | |
92 number_of_buffers_ = number_of_buffers; | 101 number_of_buffers_ = number_of_buffers; |
93 | 102 |
94 // Initialize later in OnSetFormat if bytes_per_second_ is not know yet. | 103 // Initialize later in OnSetFormat if bytes_per_second_ is not know yet. |
95 if (changed && bytes_per_second_ > 0) | 104 if (changed && bytes_per_second_ > 0 && bytes_per_frame_ > 0) |
96 InitBuffers(); | 105 InitBuffers(); |
97 } | 106 } |
98 | 107 |
99 void PepperMediaStreamAudioTrackHost::AudioSink::SetFormatOnMainThread( | 108 void PepperMediaStreamAudioTrackHost::AudioSink::SetFormatOnMainThread( |
100 int bytes_per_second) { | 109 int bytes_per_second, int bytes_per_frame) { |
101 bytes_per_second_ = bytes_per_second; | 110 bytes_per_second_ = bytes_per_second; |
111 bytes_per_frame_ = bytes_per_frame; | |
102 InitBuffers(); | 112 InitBuffers(); |
103 } | 113 } |
104 | 114 |
105 void PepperMediaStreamAudioTrackHost::AudioSink::InitBuffers() { | 115 void PepperMediaStreamAudioTrackHost::AudioSink::InitBuffers() { |
106 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | 116 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
107 { | 117 { |
108 base::AutoLock lock(lock_); | 118 base::AutoLock lock(lock_); |
109 // Clear |buffers_|, so the audio thread will drop all incoming audio data. | 119 // Clear |buffers_|, so the audio thread will drop all incoming audio data. |
110 buffers_.clear(); | 120 buffers_.clear(); |
111 buffers_generation_++; | 121 buffers_generation_++; |
112 } | 122 } |
123 int32_t frame_rate = bytes_per_second_ / bytes_per_frame_; | |
124 base::CheckedNumeric<int32_t> frames_per_buffer = user_buffer_duration_; | |
125 frames_per_buffer *= frame_rate; | |
126 frames_per_buffer /= base::Time::kMillisecondsPerSecond; | |
127 base::CheckedNumeric<int32_t> buffer_audio_size = | |
128 frames_per_buffer * bytes_per_frame_; | |
113 // The size is slightly bigger than necessary, because 8 extra bytes are | 129 // The size is slightly bigger than necessary, because 8 extra bytes are |
114 // added into the struct. Also see |MediaStreamBuffer|. | 130 // added into the struct. Also see |MediaStreamBuffer|. Also, the size of the |
115 base::CheckedNumeric<int32_t> buffer_size = bytes_per_second_; | 131 // buffer may be larger than requested, since the size of each buffer will be |
116 buffer_size *= kMaxDuration; | 132 // 4-byte aligned. |
117 buffer_size /= base::Time::kMillisecondsPerSecond; | 133 base::CheckedNumeric<int32_t> buffer_size = buffer_audio_size; |
118 buffer_size += sizeof(ppapi::MediaStreamBuffer::Audio); | 134 buffer_size += sizeof(ppapi::MediaStreamBuffer::Audio); |
135 DCHECK_GT(buffer_size.ValueOrDie(), 0); | |
119 | 136 |
120 // We don't need to hold |lock_| during |host->InitBuffers()| call, because | 137 // We don't need to hold |lock_| during |host->InitBuffers()| call, because |
121 // we just cleared |buffers_| , so the audio thread will drop all incoming | 138 // we just cleared |buffers_| , so the audio thread will drop all incoming |
122 // audio data, and not use buffers in |host_|. | 139 // audio data, and not use buffers in |host_|. |
123 bool result = host_->InitBuffers(number_of_buffers_, | 140 bool result = host_->InitBuffers(number_of_buffers_, |
124 buffer_size.ValueOrDie(), | 141 buffer_size.ValueOrDie(), |
125 kRead); | 142 kRead); |
126 // TODO(penghuang): Send PP_ERROR_NOMEMORY to plugin. | 143 // TODO(penghuang): Send PP_ERROR_NOMEMORY to plugin. |
127 CHECK(result); | 144 CHECK(result); |
128 | 145 |
129 // Fill the |buffers_|, so the audio thread can continue receiving audio data. | 146 // Fill the |buffers_|, so the audio thread can continue receiving audio data. |
130 base::AutoLock lock(lock_); | 147 base::AutoLock lock(lock_); |
148 output_buffer_size_ = buffer_audio_size.ValueOrDie(); | |
131 for (int32_t i = 0; i < number_of_buffers_; ++i) { | 149 for (int32_t i = 0; i < number_of_buffers_; ++i) { |
132 int32_t index = host_->buffer_manager()->DequeueBuffer(); | 150 int32_t index = host_->buffer_manager()->DequeueBuffer(); |
133 DCHECK_GE(index, 0); | 151 DCHECK_GE(index, 0); |
134 buffers_.push_back(index); | 152 buffers_.push_back(index); |
135 } | 153 } |
136 } | 154 } |
137 | 155 |
138 void PepperMediaStreamAudioTrackHost::AudioSink:: | 156 void PepperMediaStreamAudioTrackHost::AudioSink:: |
139 SendEnqueueBufferMessageOnMainThread(int32_t index, | 157 SendEnqueueBufferMessageOnMainThread(int32_t index, |
140 int32_t buffers_generation) { | 158 int32_t buffers_generation) { |
141 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | 159 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
142 // If |InitBuffers()| is called after this task being posted from the audio | 160 // If |InitBuffers()| is called after this task being posted from the audio |
143 // thread, the buffer should become invalid already. We should ignore it. | 161 // thread, the buffer should become invalid already. We should ignore it. |
144 // And because only the main thread modifies the |buffers_generation_|, | 162 // And because only the main thread modifies the |buffers_generation_|, |
145 // so we don't need to lock |lock_| here (main thread). | 163 // so we don't need to lock |lock_| here (main thread). |
146 if (buffers_generation == buffers_generation_) | 164 if (buffers_generation == buffers_generation_) |
147 host_->SendEnqueueBufferMessageToPlugin(index); | 165 host_->SendEnqueueBufferMessageToPlugin(index); |
148 } | 166 } |
149 | 167 |
150 void PepperMediaStreamAudioTrackHost::AudioSink::OnData(const int16* audio_data, | 168 void PepperMediaStreamAudioTrackHost::AudioSink::OnData(const int16* audio_data, |
151 int sample_rate, | 169 int sample_rate, |
152 int number_of_channels, | 170 int number_of_channels, |
153 int number_of_frames) { | 171 int number_of_frames) { |
154 DCHECK(audio_thread_checker_.CalledOnValidThread()); | 172 DCHECK(audio_thread_checker_.CalledOnValidThread()); |
155 DCHECK(audio_data); | 173 DCHECK(audio_data); |
156 DCHECK_EQ(sample_rate, audio_params_.sample_rate()); | 174 DCHECK_EQ(sample_rate, audio_params_.sample_rate()); |
157 DCHECK_EQ(number_of_channels, audio_params_.channels()); | 175 DCHECK_EQ(number_of_channels, audio_params_.channels()); |
158 DCHECK_EQ(number_of_frames, audio_params_.frames_per_buffer()); | 176 DCHECK_EQ(number_of_frames, audio_params_.frames_per_buffer()); |
159 | 177 |
178 const uint32_t bytes_per_frame = number_of_channels * | |
179 audio_params_.bits_per_sample() / 8; | |
180 | |
181 int frames_remaining = number_of_frames; | |
182 base::TimeDelta timestamp_offset; | |
183 | |
160 base::AutoLock lock(lock_); | 184 base::AutoLock lock(lock_); |
161 if (!buffers_.empty()) { | 185 while (frames_remaining) { |
162 int index = buffers_.front(); | 186 if (active_buffers_generation_ != buffers_generation_) { |
163 buffers_.pop_front(); | 187 // Buffers have changed, so drop the active buffer. |
188 active_buffer_index_ = -1; | |
189 } | |
190 if (active_buffer_index_ == -1 && !buffers_.empty()) { | |
191 active_buffers_generation_ = buffers_generation_; | |
192 active_buffer_offset_ = 0; | |
193 active_buffer_index_ = buffers_.front(); | |
194 buffers_.pop_front(); | |
195 } | |
196 if (active_buffer_index_ == -1) { | |
197 // Eek! We're dropping frames. Bad, bad, bad! | |
198 break; | |
199 } | |
200 | |
164 // TODO(penghuang): support re-sampling, etc. | 201 // TODO(penghuang): support re-sampling, etc. |
165 ppapi::MediaStreamBuffer::Audio* buffer = | 202 ppapi::MediaStreamBuffer::Audio* buffer = |
166 &(host_->buffer_manager()->GetBufferPointer(index)->audio); | 203 &(host_->buffer_manager()->GetBufferPointer(active_buffer_index_) |
167 buffer->header.size = host_->buffer_manager()->buffer_size(); | 204 ->audio); |
168 buffer->header.type = ppapi::MediaStreamBuffer::TYPE_AUDIO; | 205 if (active_buffer_offset_ == 0) { |
169 buffer->timestamp = timestamp_.InMillisecondsF(); | 206 // The active buffer is new, so initialise the header and metadata fields. |
170 buffer->sample_rate = static_cast<PP_AudioBuffer_SampleRate>(sample_rate); | 207 buffer->header.size = host_->buffer_manager()->buffer_size(); |
171 buffer->number_of_channels = number_of_channels; | 208 buffer->header.type = ppapi::MediaStreamBuffer::TYPE_AUDIO; |
172 buffer->number_of_samples = number_of_channels * number_of_frames; | 209 buffer->timestamp = (timestamp_ + timestamp_offset).InMillisecondsF(); |
173 buffer->data_size = buffer_data_size_; | 210 buffer->sample_rate = static_cast<PP_AudioBuffer_SampleRate>(sample_rate); |
174 memcpy(buffer->data, audio_data, buffer_data_size_); | 211 buffer->data_size = output_buffer_size_; |
212 buffer->number_of_channels = number_of_channels; | |
213 buffer->number_of_samples = buffer->data_size / bytes_per_frame; | |
214 } | |
215 uint32_t buffer_bytes_remaining = | |
216 buffer->data_size - active_buffer_offset_; | |
217 DCHECK_EQ(buffer_bytes_remaining % bytes_per_frame, 0U); | |
218 uint32_t incoming_bytes_remaining = frames_remaining * bytes_per_frame; | |
219 uint32_t bytes_to_copy = std::min(buffer_bytes_remaining, | |
220 incoming_bytes_remaining); | |
221 uint32_t frames_to_copy = bytes_to_copy / bytes_per_frame; | |
222 DCHECK_EQ(bytes_to_copy % bytes_per_frame, 0U); | |
223 memcpy(buffer->data + active_buffer_offset_, | |
224 audio_data, bytes_to_copy); | |
225 active_buffer_offset_ += bytes_to_copy; | |
226 audio_data += bytes_to_copy / sizeof(*audio_data); | |
227 frames_remaining -= frames_to_copy; | |
228 timestamp_offset += base::TimeDelta::FromMilliseconds( | |
229 frames_to_copy * base::Time::kMillisecondsPerSecond / sample_rate); | |
175 | 230 |
176 main_message_loop_proxy_->PostTask( | 231 DCHECK_LE(active_buffer_offset_, buffer->data_size); |
177 FROM_HERE, | 232 if (active_buffer_offset_ == buffer->data_size) { |
178 base::Bind(&AudioSink::SendEnqueueBufferMessageOnMainThread, | 233 main_message_loop_proxy_->PostTask( |
179 weak_factory_.GetWeakPtr(), | 234 FROM_HERE, |
180 index, | 235 base::Bind(&AudioSink::SendEnqueueBufferMessageOnMainThread, |
181 buffers_generation_)); | 236 weak_factory_.GetWeakPtr(), |
237 active_buffer_index_, | |
238 buffers_generation_)); | |
239 active_buffer_index_ = -1; | |
240 } | |
182 } | 241 } |
183 timestamp_ += buffer_duration_; | 242 timestamp_ += buffer_duration_; |
184 } | 243 } |
185 | 244 |
186 void PepperMediaStreamAudioTrackHost::AudioSink::OnSetFormat( | 245 void PepperMediaStreamAudioTrackHost::AudioSink::OnSetFormat( |
187 const AudioParameters& params) { | 246 const AudioParameters& params) { |
188 DCHECK(params.IsValid()); | 247 DCHECK(params.IsValid()); |
189 DCHECK_LE(params.GetBufferDuration().InMilliseconds(), kMaxDuration); | 248 // TODO(amistry): How do you handle the case where the user configures a |
249 // duration that's shorter than the received buffer duration? One option is to | |
250 // double buffer, where the size of the intermediate ring buffer is at least | |
251 // max(user requested duration, received buffer duration). There are other | |
252 // ways of dealing with it, but which one is "correct"? | |
253 DCHECK_LE(params.GetBufferDuration().InMilliseconds(), kMinDuration); | |
dmichael (off chromium)
2014/07/30 23:09:22
Did you mean DCHECK_GE?
(Does the fact that this
Anand Mistry (off Chromium)
2014/07/31 00:41:21
I meant LE. The case I'm catching is where the aud
| |
190 DCHECK_EQ(params.bits_per_sample(), 16); | 254 DCHECK_EQ(params.bits_per_sample(), 16); |
191 DCHECK_NE(GetPPSampleRate(params.sample_rate()), | 255 DCHECK_NE(GetPPSampleRate(params.sample_rate()), |
192 PP_AUDIOBUFFER_SAMPLERATE_UNKNOWN); | 256 PP_AUDIOBUFFER_SAMPLERATE_UNKNOWN); |
193 | 257 |
194 audio_params_ = params; | 258 audio_params_ = params; |
195 | 259 |
196 // TODO(penghuang): support setting format more than once. | 260 // TODO(penghuang): support setting format more than once. |
197 buffer_duration_ = params.GetBufferDuration(); | 261 buffer_duration_ = params.GetBufferDuration(); |
198 buffer_data_size_ = params.GetBytesPerBuffer(); | 262 buffer_data_size_ = params.GetBytesPerBuffer(); |
199 | 263 |
200 if (original_audio_params_.IsValid()) { | 264 if (original_audio_params_.IsValid()) { |
201 DCHECK_EQ(params.sample_rate(), original_audio_params_.sample_rate()); | 265 DCHECK_EQ(params.sample_rate(), original_audio_params_.sample_rate()); |
202 DCHECK_EQ(params.bits_per_sample(), | 266 DCHECK_EQ(params.bits_per_sample(), |
203 original_audio_params_.bits_per_sample()); | 267 original_audio_params_.bits_per_sample()); |
204 DCHECK_EQ(params.channels(), original_audio_params_.channels()); | 268 DCHECK_EQ(params.channels(), original_audio_params_.channels()); |
205 } else { | 269 } else { |
206 audio_thread_checker_.DetachFromThread(); | 270 audio_thread_checker_.DetachFromThread(); |
207 original_audio_params_ = params; | 271 original_audio_params_ = params; |
208 | 272 |
273 int bytes_per_frame = params.channels() * params.bits_per_sample() / 8; | |
209 main_message_loop_proxy_->PostTask( | 274 main_message_loop_proxy_->PostTask( |
210 FROM_HERE, | 275 FROM_HERE, |
211 base::Bind(&AudioSink::SetFormatOnMainThread, | 276 base::Bind(&AudioSink::SetFormatOnMainThread, |
212 weak_factory_.GetWeakPtr(), | 277 weak_factory_.GetWeakPtr(), |
213 params.GetBytesPerSecond())); | 278 params.GetBytesPerSecond(), |
279 bytes_per_frame)); | |
214 } | 280 } |
215 } | 281 } |
216 | 282 |
217 PepperMediaStreamAudioTrackHost::PepperMediaStreamAudioTrackHost( | 283 PepperMediaStreamAudioTrackHost::PepperMediaStreamAudioTrackHost( |
218 RendererPpapiHost* host, | 284 RendererPpapiHost* host, |
219 PP_Instance instance, | 285 PP_Instance instance, |
220 PP_Resource resource, | 286 PP_Resource resource, |
221 const blink::WebMediaStreamTrack& track) | 287 const blink::WebMediaStreamTrack& track) |
222 : PepperMediaStreamTrackHostBase(host, instance, resource), | 288 : PepperMediaStreamTrackHostBase(host, instance, resource), |
223 track_(track), | 289 track_(track), |
(...skipping 19 matching lines...) Expand all Loading... | |
243 | 309 |
244 int32_t PepperMediaStreamAudioTrackHost::OnHostMsgConfigure( | 310 int32_t PepperMediaStreamAudioTrackHost::OnHostMsgConfigure( |
245 HostMessageContext* context, | 311 HostMessageContext* context, |
246 const MediaStreamAudioTrackShared::Attributes& attributes) { | 312 const MediaStreamAudioTrackShared::Attributes& attributes) { |
247 if (!MediaStreamAudioTrackShared::VerifyAttributes(attributes)) | 313 if (!MediaStreamAudioTrackShared::VerifyAttributes(attributes)) |
248 return PP_ERROR_BADARGUMENT; | 314 return PP_ERROR_BADARGUMENT; |
249 | 315 |
250 int32_t buffers = attributes.buffers | 316 int32_t buffers = attributes.buffers |
251 ? std::min(kMaxNumberOfBuffers, attributes.buffers) | 317 ? std::min(kMaxNumberOfBuffers, attributes.buffers) |
252 : kDefaultNumberOfBuffers; | 318 : kDefaultNumberOfBuffers; |
253 audio_sink_.Configure(buffers); | 319 audio_sink_.Configure(buffers, attributes.duration); |
254 | 320 |
255 context->reply_msg = PpapiPluginMsg_MediaStreamAudioTrack_ConfigureReply(); | 321 context->reply_msg = PpapiPluginMsg_MediaStreamAudioTrack_ConfigureReply(); |
256 return PP_OK; | 322 return PP_OK; |
257 } | 323 } |
258 | 324 |
259 void PepperMediaStreamAudioTrackHost::OnClose() { | 325 void PepperMediaStreamAudioTrackHost::OnClose() { |
260 if (connected_) { | 326 if (connected_) { |
261 MediaStreamAudioSink::RemoveFromAudioTrack(&audio_sink_, track_); | 327 MediaStreamAudioSink::RemoveFromAudioTrack(&audio_sink_, track_); |
262 connected_ = false; | 328 connected_ = false; |
263 } | 329 } |
264 } | 330 } |
265 | 331 |
266 void PepperMediaStreamAudioTrackHost::OnNewBufferEnqueued() { | 332 void PepperMediaStreamAudioTrackHost::OnNewBufferEnqueued() { |
267 int32_t index = buffer_manager()->DequeueBuffer(); | 333 int32_t index = buffer_manager()->DequeueBuffer(); |
268 DCHECK_GE(index, 0); | 334 DCHECK_GE(index, 0); |
269 audio_sink_.EnqueueBuffer(index); | 335 audio_sink_.EnqueueBuffer(index); |
270 } | 336 } |
271 | 337 |
272 void PepperMediaStreamAudioTrackHost::DidConnectPendingHostToResource() { | 338 void PepperMediaStreamAudioTrackHost::DidConnectPendingHostToResource() { |
273 if (!connected_) { | 339 if (!connected_) { |
274 MediaStreamAudioSink::AddToAudioTrack(&audio_sink_, track_); | 340 MediaStreamAudioSink::AddToAudioTrack(&audio_sink_, track_); |
275 connected_ = true; | 341 connected_ = true; |
276 } | 342 } |
277 } | 343 } |
278 | 344 |
279 } // namespace content | 345 } // namespace content |
OLD | NEW |