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 |
dmichael (off chromium)
2014/05/27 20:22:33
I'm slightly surprised that this isn't part of the
thembrown
2014/05/28 10:55:59
Hm, adding it to Attributes::VerifyAttributes woul
dmichael (off chromium)
2014/05/28 15:27:43
Makes sense, thanks.
| |
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; | |
dmichael (off chromium)
2014/05/27 20:22:33
I think it would be good to have the same DCHECK_E
thembrown
2014/05/28 10:55:59
Done.
| |
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() { | |
dmichael (off chromium)
2014/05/27 20:22:33
These two names (InitBuffers and InitBuffersOnMain
thembrown
2014/05/28 10:55:59
Agreed. Changed to SetFormatOnMainThread.
| |
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; | |
dmichael (off chromium)
2014/05/27 20:22:33
The way I'm reading this, you're now dividing by 1
thembrown
2014/05/28 10:55:59
Changed. I guess it was too late for me yesterday.
| |
108 bool result = host_->InitBuffers(number_of_buffers_, | |
109 static_cast<int32_t>(buffer_size), | |
110 kRead); | |
dmichael (off chromium)
2014/05/27 20:22:33
nit: indentation is off. It looks like they all wi
thembrown
2014/05/28 10:55:59
Done.
| |
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)); | |
dmichael (off chromium)
2014/05/27 20:22:33
I don't think we should CHECK here. We're crashing
thembrown
2014/05/28 10:55:59
Agreed. How about PP_ERROR_BADARGUMENT like in Med
dmichael (off chromium)
2014/05/28 15:27:43
That's fine.
| |
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 |