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/host/ppapi_host.h" |
19 #include "ppapi/proxy/ppapi_messages.h" | 20 #include "ppapi/proxy/ppapi_messages.h" |
20 #include "ppapi/shared_impl/media_stream_audio_track_shared.h" | 21 #include "ppapi/shared_impl/media_stream_audio_track_shared.h" |
21 #include "ppapi/shared_impl/media_stream_buffer.h" | 22 #include "ppapi/shared_impl/media_stream_buffer.h" |
22 | 23 |
23 using media::AudioParameters; | 24 using media::AudioParameters; |
24 using ppapi::host::HostMessageContext; | 25 using ppapi::host::HostMessageContext; |
25 using ppapi::MediaStreamAudioTrackShared; | 26 using ppapi::MediaStreamAudioTrackShared; |
26 | 27 |
27 namespace { | 28 namespace { |
28 | 29 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 } | 82 } |
82 | 83 |
83 void PepperMediaStreamAudioTrackHost::AudioSink::EnqueueBuffer(int32_t index) { | 84 void PepperMediaStreamAudioTrackHost::AudioSink::EnqueueBuffer(int32_t index) { |
84 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | 85 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
85 DCHECK_GE(index, 0); | 86 DCHECK_GE(index, 0); |
86 DCHECK_LT(index, host_->buffer_manager()->number_of_buffers()); | 87 DCHECK_LT(index, host_->buffer_manager()->number_of_buffers()); |
87 base::AutoLock lock(lock_); | 88 base::AutoLock lock(lock_); |
88 buffers_.push_back(index); | 89 buffers_.push_back(index); |
89 } | 90 } |
90 | 91 |
91 void PepperMediaStreamAudioTrackHost::AudioSink::Configure( | 92 int32_t PepperMediaStreamAudioTrackHost::AudioSink::Configure( |
92 int32_t number_of_buffers, int32_t duration) { | 93 int32_t number_of_buffers, int32_t duration, |
| 94 const ppapi::host::ReplyMessageContext& context) { |
93 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | 95 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
| 96 |
| 97 if (pending_configure_reply_.is_valid()) { |
| 98 return PP_ERROR_INPROGRESS; |
| 99 } |
| 100 pending_configure_reply_ = context; |
| 101 |
94 bool changed = false; | 102 bool changed = false; |
95 if (number_of_buffers != number_of_buffers_) | 103 if (number_of_buffers != number_of_buffers_) |
96 changed = true; | 104 changed = true; |
97 if (duration != 0 && duration != user_buffer_duration_) { | 105 if (duration != 0 && duration != user_buffer_duration_) { |
98 user_buffer_duration_ = duration; | 106 user_buffer_duration_ = duration; |
99 changed = true; | 107 changed = true; |
100 } | 108 } |
101 number_of_buffers_ = number_of_buffers; | 109 number_of_buffers_ = number_of_buffers; |
102 | 110 |
103 // Initialize later in OnSetFormat if bytes_per_second_ is not know yet. | 111 if (changed) { |
104 if (changed && bytes_per_second_ > 0 && bytes_per_frame_ > 0) | 112 // Initialize later in OnSetFormat if bytes_per_second_ is not known yet. |
105 InitBuffers(); | 113 if (bytes_per_second_ > 0 && bytes_per_frame_ > 0) |
| 114 InitBuffers(); |
| 115 } else { |
| 116 SendConfigureReply(PP_OK); |
| 117 } |
| 118 return PP_OK_COMPLETIONPENDING; |
| 119 } |
| 120 |
| 121 void PepperMediaStreamAudioTrackHost::AudioSink::SendConfigureReply( |
| 122 int32_t result) { |
| 123 if (pending_configure_reply_.is_valid()) { |
| 124 pending_configure_reply_.params.set_result(result); |
| 125 host_->host()->SendReply( |
| 126 pending_configure_reply_, |
| 127 PpapiPluginMsg_MediaStreamAudioTrack_ConfigureReply()); |
| 128 pending_configure_reply_ = ppapi::host::ReplyMessageContext(); |
| 129 } |
106 } | 130 } |
107 | 131 |
108 void PepperMediaStreamAudioTrackHost::AudioSink::SetFormatOnMainThread( | 132 void PepperMediaStreamAudioTrackHost::AudioSink::SetFormatOnMainThread( |
109 int bytes_per_second, int bytes_per_frame) { | 133 int bytes_per_second, int bytes_per_frame) { |
110 bytes_per_second_ = bytes_per_second; | 134 bytes_per_second_ = bytes_per_second; |
111 bytes_per_frame_ = bytes_per_frame; | 135 bytes_per_frame_ = bytes_per_frame; |
112 InitBuffers(); | 136 InitBuffers(); |
113 } | 137 } |
114 | 138 |
115 void PepperMediaStreamAudioTrackHost::AudioSink::InitBuffers() { | 139 void PepperMediaStreamAudioTrackHost::AudioSink::InitBuffers() { |
(...skipping 17 matching lines...) Expand all Loading... |
133 base::CheckedNumeric<int32_t> buffer_size = buffer_audio_size; | 157 base::CheckedNumeric<int32_t> buffer_size = buffer_audio_size; |
134 buffer_size += sizeof(ppapi::MediaStreamBuffer::Audio); | 158 buffer_size += sizeof(ppapi::MediaStreamBuffer::Audio); |
135 DCHECK_GT(buffer_size.ValueOrDie(), 0); | 159 DCHECK_GT(buffer_size.ValueOrDie(), 0); |
136 | 160 |
137 // We don't need to hold |lock_| during |host->InitBuffers()| call, because | 161 // We don't need to hold |lock_| during |host->InitBuffers()| call, because |
138 // we just cleared |buffers_| , so the audio thread will drop all incoming | 162 // we just cleared |buffers_| , so the audio thread will drop all incoming |
139 // audio data, and not use buffers in |host_|. | 163 // audio data, and not use buffers in |host_|. |
140 bool result = host_->InitBuffers(number_of_buffers_, | 164 bool result = host_->InitBuffers(number_of_buffers_, |
141 buffer_size.ValueOrDie(), | 165 buffer_size.ValueOrDie(), |
142 kRead); | 166 kRead); |
143 // TODO(penghuang): Send PP_ERROR_NOMEMORY to plugin. | 167 if (!result) { |
144 CHECK(result); | 168 SendConfigureReply(PP_ERROR_NOMEMORY); |
| 169 return; |
| 170 } |
145 | 171 |
146 // Fill the |buffers_|, so the audio thread can continue receiving audio data. | 172 // Fill the |buffers_|, so the audio thread can continue receiving audio data. |
147 base::AutoLock lock(lock_); | 173 base::AutoLock lock(lock_); |
148 output_buffer_size_ = buffer_audio_size.ValueOrDie(); | 174 output_buffer_size_ = buffer_audio_size.ValueOrDie(); |
149 for (int32_t i = 0; i < number_of_buffers_; ++i) { | 175 for (int32_t i = 0; i < number_of_buffers_; ++i) { |
150 int32_t index = host_->buffer_manager()->DequeueBuffer(); | 176 int32_t index = host_->buffer_manager()->DequeueBuffer(); |
151 DCHECK_GE(index, 0); | 177 DCHECK_GE(index, 0); |
152 buffers_.push_back(index); | 178 buffers_.push_back(index); |
153 } | 179 } |
| 180 |
| 181 SendConfigureReply(PP_OK); |
154 } | 182 } |
155 | 183 |
156 void PepperMediaStreamAudioTrackHost::AudioSink:: | 184 void PepperMediaStreamAudioTrackHost::AudioSink:: |
157 SendEnqueueBufferMessageOnMainThread(int32_t index, | 185 SendEnqueueBufferMessageOnMainThread(int32_t index, |
158 int32_t buffers_generation) { | 186 int32_t buffers_generation) { |
159 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | 187 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
160 // If |InitBuffers()| is called after this task being posted from the audio | 188 // If |InitBuffers()| is called after this task being posted from the audio |
161 // thread, the buffer should become invalid already. We should ignore it. | 189 // thread, the buffer should become invalid already. We should ignore it. |
162 // And because only the main thread modifies the |buffers_generation_|, | 190 // And because only the main thread modifies the |buffers_generation_|, |
163 // so we don't need to lock |lock_| here (main thread). | 191 // so we don't need to lock |lock_| here (main thread). |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 | 341 |
314 int32_t PepperMediaStreamAudioTrackHost::OnHostMsgConfigure( | 342 int32_t PepperMediaStreamAudioTrackHost::OnHostMsgConfigure( |
315 HostMessageContext* context, | 343 HostMessageContext* context, |
316 const MediaStreamAudioTrackShared::Attributes& attributes) { | 344 const MediaStreamAudioTrackShared::Attributes& attributes) { |
317 if (!MediaStreamAudioTrackShared::VerifyAttributes(attributes)) | 345 if (!MediaStreamAudioTrackShared::VerifyAttributes(attributes)) |
318 return PP_ERROR_BADARGUMENT; | 346 return PP_ERROR_BADARGUMENT; |
319 | 347 |
320 int32_t buffers = attributes.buffers | 348 int32_t buffers = attributes.buffers |
321 ? std::min(kMaxNumberOfBuffers, attributes.buffers) | 349 ? std::min(kMaxNumberOfBuffers, attributes.buffers) |
322 : kDefaultNumberOfBuffers; | 350 : kDefaultNumberOfBuffers; |
323 audio_sink_.Configure(buffers, attributes.duration); | 351 return audio_sink_.Configure(buffers, attributes.duration, |
324 | 352 context->MakeReplyMessageContext()); |
325 context->reply_msg = PpapiPluginMsg_MediaStreamAudioTrack_ConfigureReply(); | |
326 return PP_OK; | |
327 } | 353 } |
328 | 354 |
329 void PepperMediaStreamAudioTrackHost::OnClose() { | 355 void PepperMediaStreamAudioTrackHost::OnClose() { |
330 if (connected_) { | 356 if (connected_) { |
331 MediaStreamAudioSink::RemoveFromAudioTrack(&audio_sink_, track_); | 357 MediaStreamAudioSink::RemoveFromAudioTrack(&audio_sink_, track_); |
332 connected_ = false; | 358 connected_ = false; |
333 } | 359 } |
| 360 audio_sink_.SendConfigureReply(PP_ERROR_ABORTED); |
334 } | 361 } |
335 | 362 |
336 void PepperMediaStreamAudioTrackHost::OnNewBufferEnqueued() { | 363 void PepperMediaStreamAudioTrackHost::OnNewBufferEnqueued() { |
337 int32_t index = buffer_manager()->DequeueBuffer(); | 364 int32_t index = buffer_manager()->DequeueBuffer(); |
338 DCHECK_GE(index, 0); | 365 DCHECK_GE(index, 0); |
339 audio_sink_.EnqueueBuffer(index); | 366 audio_sink_.EnqueueBuffer(index); |
340 } | 367 } |
341 | 368 |
342 void PepperMediaStreamAudioTrackHost::DidConnectPendingHostToResource() { | 369 void PepperMediaStreamAudioTrackHost::DidConnectPendingHostToResource() { |
343 if (!connected_) { | 370 if (!connected_) { |
344 MediaStreamAudioSink::AddToAudioTrack(&audio_sink_, track_); | 371 MediaStreamAudioSink::AddToAudioTrack(&audio_sink_, track_); |
345 connected_ = true; | 372 connected_ = true; |
346 } | 373 } |
347 } | 374 } |
348 | 375 |
349 } // namespace content | 376 } // namespace content |
OLD | NEW |