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> |
| 8 |
7 #include "base/bind.h" | 9 #include "base/bind.h" |
8 #include "base/location.h" | 10 #include "base/location.h" |
9 #include "base/logging.h" | 11 #include "base/logging.h" |
10 #include "base/macros.h" | 12 #include "base/macros.h" |
11 #include "base/message_loop/message_loop_proxy.h" | 13 #include "base/message_loop/message_loop_proxy.h" |
| 14 #include "base/numerics/safe_math.h" |
12 #include "ppapi/c/pp_errors.h" | 15 #include "ppapi/c/pp_errors.h" |
13 #include "ppapi/c/ppb_audio_buffer.h" | 16 #include "ppapi/c/ppb_audio_buffer.h" |
| 17 #include "ppapi/host/dispatch_host_message.h" |
| 18 #include "ppapi/host/host_message_context.h" |
| 19 #include "ppapi/proxy/ppapi_messages.h" |
| 20 #include "ppapi/shared_impl/media_stream_audio_track_shared.h" |
14 #include "ppapi/shared_impl/media_stream_buffer.h" | 21 #include "ppapi/shared_impl/media_stream_buffer.h" |
15 | 22 |
16 using media::AudioParameters; | 23 using media::AudioParameters; |
| 24 using ppapi::host::HostMessageContext; |
| 25 using ppapi::MediaStreamAudioTrackShared; |
17 | 26 |
18 namespace { | 27 namespace { |
19 | 28 |
20 // Max audio buffer duration in milliseconds. | 29 // Max audio buffer duration in milliseconds. |
21 const uint32_t kMaxDuration = 10; | 30 const uint32_t kMaxDuration = 10; |
22 | 31 |
23 // TODO(penghuang): make this configurable. | 32 const int32_t kDefaultNumberOfBuffers = 4; |
24 const int32_t kNumberOfBuffers = 4; | 33 const int32_t kMaxNumberOfBuffers = 1000; // 10 sec |
25 | 34 |
26 // Returns true if the |sample_rate| is supported in | 35 // Returns true if the |sample_rate| is supported in |
27 // |PP_AudioBuffer_SampleRate|, otherwise false. | 36 // |PP_AudioBuffer_SampleRate|, otherwise false. |
28 PP_AudioBuffer_SampleRate GetPPSampleRate(int sample_rate) { | 37 PP_AudioBuffer_SampleRate GetPPSampleRate(int sample_rate) { |
29 switch (sample_rate) { | 38 switch (sample_rate) { |
30 case 8000: | 39 case 8000: |
31 return PP_AUDIOBUFFER_SAMPLERATE_8000; | 40 return PP_AUDIOBUFFER_SAMPLERATE_8000; |
32 case 16000: | 41 case 16000: |
33 return PP_AUDIOBUFFER_SAMPLERATE_16000; | 42 return PP_AUDIOBUFFER_SAMPLERATE_16000; |
34 case 22050: | 43 case 22050: |
(...skipping 15 matching lines...) Expand all Loading... |
50 | 59 |
51 } // namespace | 60 } // namespace |
52 | 61 |
53 namespace content { | 62 namespace content { |
54 | 63 |
55 PepperMediaStreamAudioTrackHost::AudioSink::AudioSink( | 64 PepperMediaStreamAudioTrackHost::AudioSink::AudioSink( |
56 PepperMediaStreamAudioTrackHost* host) | 65 PepperMediaStreamAudioTrackHost* host) |
57 : host_(host), | 66 : host_(host), |
58 buffer_data_size_(0), | 67 buffer_data_size_(0), |
59 main_message_loop_proxy_(base::MessageLoopProxy::current()), | 68 main_message_loop_proxy_(base::MessageLoopProxy::current()), |
60 weak_factory_(this) {} | 69 weak_factory_(this), |
| 70 number_of_buffers_(kDefaultNumberOfBuffers), |
| 71 bytes_per_second_(0) {} |
61 | 72 |
62 PepperMediaStreamAudioTrackHost::AudioSink::~AudioSink() { | 73 PepperMediaStreamAudioTrackHost::AudioSink::~AudioSink() { |
63 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | 74 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
64 } | 75 } |
65 | 76 |
66 void PepperMediaStreamAudioTrackHost::AudioSink::EnqueueBuffer(int32_t index) { | 77 void PepperMediaStreamAudioTrackHost::AudioSink::EnqueueBuffer(int32_t index) { |
67 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | 78 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
68 DCHECK_GE(index, 0); | 79 DCHECK_GE(index, 0); |
69 DCHECK_LT(index, host_->buffer_manager()->number_of_buffers()); | 80 DCHECK_LT(index, host_->buffer_manager()->number_of_buffers()); |
70 base::AutoLock lock(lock_); | 81 base::AutoLock lock(lock_); |
71 buffers_.push_back(index); | 82 buffers_.push_back(index); |
72 } | 83 } |
73 | 84 |
74 void PepperMediaStreamAudioTrackHost::AudioSink::InitBuffersOnMainThread( | 85 void PepperMediaStreamAudioTrackHost::AudioSink::Configure( |
75 int32_t number_of_buffers, | 86 int32_t number_of_buffers) { |
76 int32_t buffer_size) { | |
77 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | 87 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
78 bool result = host_->InitBuffers(number_of_buffers, buffer_size, kRead); | 88 bool changed = false; |
| 89 if (number_of_buffers != number_of_buffers_) |
| 90 changed = true; |
| 91 number_of_buffers_ = number_of_buffers; |
| 92 |
| 93 // Initialize later in OnSetFormat if bytes_per_second_ is not know yet. |
| 94 if (changed && bytes_per_second_ > 0) |
| 95 InitBuffers(); |
| 96 } |
| 97 |
| 98 void PepperMediaStreamAudioTrackHost::AudioSink::SetFormatOnMainThread( |
| 99 int bytes_per_second) { |
| 100 bytes_per_second_ = bytes_per_second; |
| 101 InitBuffers(); |
| 102 } |
| 103 |
| 104 void PepperMediaStreamAudioTrackHost::AudioSink::InitBuffers() { |
| 105 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
| 106 // The size is slightly bigger than necessary, because 8 extra bytes are |
| 107 // added into the struct. Also see |MediaStreamBuffer|. |
| 108 base::CheckedNumeric<int32_t> buffer_size = bytes_per_second_; |
| 109 buffer_size *= kMaxDuration; |
| 110 buffer_size /= base::Time::kMillisecondsPerSecond; |
| 111 buffer_size += sizeof(ppapi::MediaStreamBuffer::Audio); |
| 112 bool result = host_->InitBuffers(number_of_buffers_, |
| 113 buffer_size.ValueOrDie(), |
| 114 kRead); |
79 // TODO(penghuang): Send PP_ERROR_NOMEMORY to plugin. | 115 // TODO(penghuang): Send PP_ERROR_NOMEMORY to plugin. |
80 CHECK(result); | 116 CHECK(result); |
81 base::AutoLock lock(lock_); | 117 base::AutoLock lock(lock_); |
82 for (int32_t i = 0; i < number_of_buffers; ++i) { | 118 buffers_.clear(); |
| 119 for (int32_t i = 0; i < number_of_buffers_; ++i) { |
83 int32_t index = host_->buffer_manager()->DequeueBuffer(); | 120 int32_t index = host_->buffer_manager()->DequeueBuffer(); |
84 DCHECK_GE(index, 0); | 121 DCHECK_GE(index, 0); |
85 buffers_.push_back(index); | 122 buffers_.push_back(index); |
86 } | 123 } |
87 } | 124 } |
88 | 125 |
89 void PepperMediaStreamAudioTrackHost::AudioSink:: | 126 void PepperMediaStreamAudioTrackHost::AudioSink:: |
90 SendEnqueueBufferMessageOnMainThread(int32_t index) { | 127 SendEnqueueBufferMessageOnMainThread(int32_t index) { |
91 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | 128 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
92 host_->SendEnqueueBufferMessageToPlugin(index); | 129 host_->SendEnqueueBufferMessageToPlugin(index); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 buffer_data_size_ = params.GetBytesPerBuffer(); | 184 buffer_data_size_ = params.GetBytesPerBuffer(); |
148 | 185 |
149 if (original_audio_params_.IsValid()) { | 186 if (original_audio_params_.IsValid()) { |
150 DCHECK_EQ(params.sample_rate(), original_audio_params_.sample_rate()); | 187 DCHECK_EQ(params.sample_rate(), original_audio_params_.sample_rate()); |
151 DCHECK_EQ(params.bits_per_sample(), | 188 DCHECK_EQ(params.bits_per_sample(), |
152 original_audio_params_.bits_per_sample()); | 189 original_audio_params_.bits_per_sample()); |
153 DCHECK_EQ(params.channels(), original_audio_params_.channels()); | 190 DCHECK_EQ(params.channels(), original_audio_params_.channels()); |
154 } else { | 191 } else { |
155 audio_thread_checker_.DetachFromThread(); | 192 audio_thread_checker_.DetachFromThread(); |
156 original_audio_params_ = params; | 193 original_audio_params_ = params; |
157 // The size is slightly bigger than necessary, because 8 extra bytes are | |
158 // added into the struct. Also see |MediaStreamBuffer|. | |
159 size_t max_data_size = params.sample_rate() * params.bits_per_sample() / 8 * | |
160 params.channels() * kMaxDuration / 1000; | |
161 size_t size = sizeof(ppapi::MediaStreamBuffer::Audio) + max_data_size; | |
162 | 194 |
163 main_message_loop_proxy_->PostTask( | 195 main_message_loop_proxy_->PostTask( |
164 FROM_HERE, | 196 FROM_HERE, |
165 base::Bind(&AudioSink::InitBuffersOnMainThread, | 197 base::Bind(&AudioSink::SetFormatOnMainThread, |
166 weak_factory_.GetWeakPtr(), | 198 weak_factory_.GetWeakPtr(), |
167 kNumberOfBuffers, | 199 params.GetBytesPerSecond())); |
168 static_cast<int32_t>(size))); | |
169 } | 200 } |
170 } | 201 } |
171 | 202 |
172 PepperMediaStreamAudioTrackHost::PepperMediaStreamAudioTrackHost( | 203 PepperMediaStreamAudioTrackHost::PepperMediaStreamAudioTrackHost( |
173 RendererPpapiHost* host, | 204 RendererPpapiHost* host, |
174 PP_Instance instance, | 205 PP_Instance instance, |
175 PP_Resource resource, | 206 PP_Resource resource, |
176 const blink::WebMediaStreamTrack& track) | 207 const blink::WebMediaStreamTrack& track) |
177 : PepperMediaStreamTrackHostBase(host, instance, resource), | 208 : PepperMediaStreamTrackHostBase(host, instance, resource), |
178 track_(track), | 209 track_(track), |
179 connected_(false), | 210 connected_(false), |
180 audio_sink_(this) { | 211 audio_sink_(this) { |
181 DCHECK(!track_.isNull()); | 212 DCHECK(!track_.isNull()); |
182 } | 213 } |
183 | 214 |
184 PepperMediaStreamAudioTrackHost::~PepperMediaStreamAudioTrackHost() { | 215 PepperMediaStreamAudioTrackHost::~PepperMediaStreamAudioTrackHost() { |
185 OnClose(); | 216 OnClose(); |
186 } | 217 } |
187 | 218 |
| 219 int32_t PepperMediaStreamAudioTrackHost::OnResourceMessageReceived( |
| 220 const IPC::Message& msg, |
| 221 HostMessageContext* context) { |
| 222 PPAPI_BEGIN_MESSAGE_MAP(PepperMediaStreamAudioTrackHost, msg) |
| 223 PPAPI_DISPATCH_HOST_RESOURCE_CALL( |
| 224 PpapiHostMsg_MediaStreamAudioTrack_Configure, OnHostMsgConfigure) |
| 225 PPAPI_END_MESSAGE_MAP() |
| 226 return PepperMediaStreamTrackHostBase::OnResourceMessageReceived(msg, |
| 227 context); |
| 228 } |
| 229 |
| 230 int32_t PepperMediaStreamAudioTrackHost::OnHostMsgConfigure( |
| 231 HostMessageContext* context, |
| 232 const MediaStreamAudioTrackShared::Attributes& attributes) { |
| 233 if (!MediaStreamAudioTrackShared::VerifyAttributes(attributes)) |
| 234 return PP_ERROR_BADARGUMENT; |
| 235 |
| 236 int32_t buffers = attributes.buffers |
| 237 ? std::min(kMaxNumberOfBuffers, attributes.buffers) |
| 238 : kDefaultNumberOfBuffers; |
| 239 audio_sink_.Configure(buffers); |
| 240 |
| 241 context->reply_msg = PpapiPluginMsg_MediaStreamAudioTrack_ConfigureReply(); |
| 242 return PP_OK; |
| 243 } |
| 244 |
188 void PepperMediaStreamAudioTrackHost::OnClose() { | 245 void PepperMediaStreamAudioTrackHost::OnClose() { |
189 if (connected_) { | 246 if (connected_) { |
190 MediaStreamAudioSink::RemoveFromAudioTrack(&audio_sink_, track_); | 247 MediaStreamAudioSink::RemoveFromAudioTrack(&audio_sink_, track_); |
191 connected_ = false; | 248 connected_ = false; |
192 } | 249 } |
193 } | 250 } |
194 | 251 |
195 void PepperMediaStreamAudioTrackHost::OnNewBufferEnqueued() { | 252 void PepperMediaStreamAudioTrackHost::OnNewBufferEnqueued() { |
196 int32_t index = buffer_manager()->DequeueBuffer(); | 253 int32_t index = buffer_manager()->DequeueBuffer(); |
197 DCHECK_GE(index, 0); | 254 DCHECK_GE(index, 0); |
198 audio_sink_.EnqueueBuffer(index); | 255 audio_sink_.EnqueueBuffer(index); |
199 } | 256 } |
200 | 257 |
201 void PepperMediaStreamAudioTrackHost::DidConnectPendingHostToResource() { | 258 void PepperMediaStreamAudioTrackHost::DidConnectPendingHostToResource() { |
202 if (!connected_) { | 259 if (!connected_) { |
203 MediaStreamAudioSink::AddToAudioTrack(&audio_sink_, track_); | 260 MediaStreamAudioSink::AddToAudioTrack(&audio_sink_, track_); |
204 connected_ = true; | 261 connected_ = true; |
205 } | 262 } |
206 } | 263 } |
207 | 264 |
208 } // namespace content | 265 } // namespace content |
OLD | NEW |