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 |
74 void PepperMediaStreamAudioTrackHost::AudioSink::InitBuffersOnMainThread( | 84 void PepperMediaStreamAudioTrackHost::AudioSink::Configure( |
75 int32_t number_of_buffers, | 85 int32_t number_of_buffers) { |
76 int32_t buffer_size) { | |
77 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | 86 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
78 bool result = host_->InitBuffers(number_of_buffers, buffer_size, kRead); | 87 bool changed; |
88 if (number_of_buffers != number_of_buffers_) | |
89 changed = true; | |
90 number_of_buffers_ = number_of_buffers; | |
91 | |
92 // Initialize later in OnSetFormat if bytes_per_second_ is not know yet. | |
93 if (changed && bytes_per_second_ > 0) | |
94 InitBuffers(); | |
95 } | |
96 | |
97 void PepperMediaStreamAudioTrackHost::AudioSink::SetFormatOnMainThread( | |
98 int bytes_per_second) { | |
99 bytes_per_second_ = bytes_per_second; | |
100 InitBuffers(); | |
101 } | |
102 | |
103 void PepperMediaStreamAudioTrackHost::AudioSink::InitBuffers() { | |
104 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | |
105 // The size is slightly bigger than necessary, because 8 extra bytes are | |
106 // added into the struct. Also see |MediaStreamBuffer|. | |
107 size_t buffer_size = sizeof(ppapi::MediaStreamBuffer::Audio) + | |
108 bytes_per_second_ * kMaxDuration / base::Time::kMillisecondsPerSecond; | |
109 bool result = host_->InitBuffers(number_of_buffers_, | |
110 static_cast<int32_t>(buffer_size), | |
dcheng
2014/05/28 15:55:44
Will we need to be concerned about overflow in the
thembrown
2014/05/28 17:13:11
Hm - with audio @192kHz, 16Bit, 10ch bytes_per_sec
dcheng
2014/05/28 17:21:06
We use bytes per second though, not bits.
So it's
thembrown
2014/05/28 19:09:54
I was concerned about the intermediate result of (
| |
111 kRead); | |
79 // TODO(penghuang): Send PP_ERROR_NOMEMORY to plugin. | 112 // TODO(penghuang): Send PP_ERROR_NOMEMORY to plugin. |
80 CHECK(result); | 113 CHECK(result); |
81 base::AutoLock lock(lock_); | 114 base::AutoLock lock(lock_); |
82 for (int32_t i = 0; i < number_of_buffers; ++i) { | 115 buffers_.clear(); |
116 for (int32_t i = 0; i < number_of_buffers_; ++i) { | |
83 int32_t index = host_->buffer_manager()->DequeueBuffer(); | 117 int32_t index = host_->buffer_manager()->DequeueBuffer(); |
84 DCHECK_GE(index, 0); | 118 DCHECK_GE(index, 0); |
85 buffers_.push_back(index); | 119 buffers_.push_back(index); |
86 } | 120 } |
87 } | 121 } |
88 | 122 |
89 void PepperMediaStreamAudioTrackHost::AudioSink:: | 123 void PepperMediaStreamAudioTrackHost::AudioSink:: |
90 SendEnqueueBufferMessageOnMainThread(int32_t index) { | 124 SendEnqueueBufferMessageOnMainThread(int32_t index) { |
91 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | 125 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
92 host_->SendEnqueueBufferMessageToPlugin(index); | 126 host_->SendEnqueueBufferMessageToPlugin(index); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
147 buffer_data_size_ = params.GetBytesPerBuffer(); | 181 buffer_data_size_ = params.GetBytesPerBuffer(); |
148 | 182 |
149 if (original_audio_params_.IsValid()) { | 183 if (original_audio_params_.IsValid()) { |
150 DCHECK_EQ(params.sample_rate(), original_audio_params_.sample_rate()); | 184 DCHECK_EQ(params.sample_rate(), original_audio_params_.sample_rate()); |
151 DCHECK_EQ(params.bits_per_sample(), | 185 DCHECK_EQ(params.bits_per_sample(), |
152 original_audio_params_.bits_per_sample()); | 186 original_audio_params_.bits_per_sample()); |
153 DCHECK_EQ(params.channels(), original_audio_params_.channels()); | 187 DCHECK_EQ(params.channels(), original_audio_params_.channels()); |
154 } else { | 188 } else { |
155 audio_thread_checker_.DetachFromThread(); | 189 audio_thread_checker_.DetachFromThread(); |
156 original_audio_params_ = params; | 190 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 | 191 |
163 main_message_loop_proxy_->PostTask( | 192 main_message_loop_proxy_->PostTask( |
164 FROM_HERE, | 193 FROM_HERE, |
165 base::Bind(&AudioSink::InitBuffersOnMainThread, | 194 base::Bind(&AudioSink::SetFormatOnMainThread, |
166 weak_factory_.GetWeakPtr(), | 195 weak_factory_.GetWeakPtr(), |
167 kNumberOfBuffers, | 196 params.GetBytesPerSecond())); |
168 static_cast<int32_t>(size))); | |
169 } | 197 } |
170 } | 198 } |
171 | 199 |
172 PepperMediaStreamAudioTrackHost::PepperMediaStreamAudioTrackHost( | 200 PepperMediaStreamAudioTrackHost::PepperMediaStreamAudioTrackHost( |
173 RendererPpapiHost* host, | 201 RendererPpapiHost* host, |
174 PP_Instance instance, | 202 PP_Instance instance, |
175 PP_Resource resource, | 203 PP_Resource resource, |
176 const blink::WebMediaStreamTrack& track) | 204 const blink::WebMediaStreamTrack& track) |
177 : PepperMediaStreamTrackHostBase(host, instance, resource), | 205 : PepperMediaStreamTrackHostBase(host, instance, resource), |
178 track_(track), | 206 track_(track), |
179 connected_(false), | 207 connected_(false), |
180 audio_sink_(this) { | 208 audio_sink_(this) { |
181 DCHECK(!track_.isNull()); | 209 DCHECK(!track_.isNull()); |
182 } | 210 } |
183 | 211 |
184 PepperMediaStreamAudioTrackHost::~PepperMediaStreamAudioTrackHost() { | 212 PepperMediaStreamAudioTrackHost::~PepperMediaStreamAudioTrackHost() { |
185 OnClose(); | 213 OnClose(); |
186 } | 214 } |
187 | 215 |
216 int32_t PepperMediaStreamAudioTrackHost::OnResourceMessageReceived( | |
217 const IPC::Message& msg, | |
218 HostMessageContext* context) { | |
219 PPAPI_BEGIN_MESSAGE_MAP(PepperMediaStreamAudioTrackHost, msg) | |
220 PPAPI_DISPATCH_HOST_RESOURCE_CALL( | |
221 PpapiHostMsg_MediaStreamAudioTrack_Configure, OnHostMsgConfigure) | |
222 PPAPI_END_MESSAGE_MAP() | |
223 return PepperMediaStreamTrackHostBase::OnResourceMessageReceived(msg, | |
224 context); | |
225 } | |
226 | |
227 int32_t PepperMediaStreamAudioTrackHost::OnHostMsgConfigure( | |
228 HostMessageContext* context, | |
229 const MediaStreamAudioTrackShared::Attributes& attributes) { | |
230 if (!MediaStreamAudioTrackShared::VerifyAttributes(attributes)) | |
231 return PP_ERROR_BADARGUMENT; | |
232 | |
233 int32_t buffers = attributes.buffers | |
234 ? std::min(kMaxNumberOfBuffers, attributes.buffers) | |
235 : kDefaultNumberOfBuffers; | |
236 audio_sink_.Configure(buffers); | |
237 | |
238 context->reply_msg = PpapiPluginMsg_MediaStreamAudioTrack_ConfigureReply(); | |
239 return PP_OK; | |
240 } | |
241 | |
188 void PepperMediaStreamAudioTrackHost::OnClose() { | 242 void PepperMediaStreamAudioTrackHost::OnClose() { |
189 if (connected_) { | 243 if (connected_) { |
190 MediaStreamAudioSink::RemoveFromAudioTrack(&audio_sink_, track_); | 244 MediaStreamAudioSink::RemoveFromAudioTrack(&audio_sink_, track_); |
191 connected_ = false; | 245 connected_ = false; |
192 } | 246 } |
193 } | 247 } |
194 | 248 |
195 void PepperMediaStreamAudioTrackHost::OnNewBufferEnqueued() { | 249 void PepperMediaStreamAudioTrackHost::OnNewBufferEnqueued() { |
196 int32_t index = buffer_manager()->DequeueBuffer(); | 250 int32_t index = buffer_manager()->DequeueBuffer(); |
197 DCHECK_GE(index, 0); | 251 DCHECK_GE(index, 0); |
198 audio_sink_.EnqueueBuffer(index); | 252 audio_sink_.EnqueueBuffer(index); |
199 } | 253 } |
200 | 254 |
201 void PepperMediaStreamAudioTrackHost::DidConnectPendingHostToResource() { | 255 void PepperMediaStreamAudioTrackHost::DidConnectPendingHostToResource() { |
202 if (!connected_) { | 256 if (!connected_) { |
203 MediaStreamAudioSink::AddToAudioTrack(&audio_sink_, track_); | 257 MediaStreamAudioSink::AddToAudioTrack(&audio_sink_, track_); |
204 connected_ = true; | 258 connected_ = true; |
205 } | 259 } |
206 } | 260 } |
207 | 261 |
208 } // namespace content | 262 } // namespace content |
OLD | NEW |