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