Chromium Code Reviews| 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) { | |
|
Peng
2014/05/26 14:48:49
{} is not necessary.
thembrown
2014/05/27 10:36:02
Done.
| |
| 93 InitBuffers(); | |
| 94 } | |
| 95 } | |
| 96 | |
| 74 void PepperMediaStreamAudioTrackHost::AudioSink::InitBuffersOnMainThread( | 97 void PepperMediaStreamAudioTrackHost::AudioSink::InitBuffersOnMainThread( |
| 75 int32_t number_of_buffers, | 98 int bytes_per_second) { |
| 76 int32_t buffer_size) { | 99 bytes_per_second_ = bytes_per_second; |
| 100 InitBuffers(); | |
| 101 } | |
| 102 | |
| 103 void PepperMediaStreamAudioTrackHost::AudioSink::InitBuffers() { | |
| 77 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | 104 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
| 78 bool result = host_->InitBuffers(number_of_buffers, buffer_size, kRead); | 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; | |
|
Peng
2014/05/26 14:48:49
kMaxDuration is in milliseconds. See comment of kM
thembrown
2014/05/27 10:36:02
Done.
| |
| 109 bool result = host_->InitBuffers(number_of_buffers_, | |
| 110 static_cast<int32_t>(buffer_size), | |
| 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 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 |
| 122 | |
|
Peng
2014/05/26 14:48:49
remove the extra blank line
thembrown
2014/05/27 10:36:02
Done.
| |
| 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); |
| 93 } | 127 } |
| 94 | 128 |
| 95 void PepperMediaStreamAudioTrackHost::AudioSink::OnData(const int16* audio_data, | 129 void PepperMediaStreamAudioTrackHost::AudioSink::OnData(const int16* audio_data, |
| 96 int sample_rate, | 130 int sample_rate, |
| 97 int number_of_channels, | 131 int number_of_channels, |
| 98 int number_of_frames) { | 132 int number_of_frames) { |
| (...skipping 48 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::InitBuffersOnMainThread, |
| 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 CHECK(MediaStreamAudioTrackShared::VerifyAttributes(attributes)); | |
| 231 | |
| 232 int32_t buffers = attributes.buffers | |
| 233 ? std::min(kMaxNumberOfBuffers, attributes.buffers) | |
| 234 : kDefaultNumberOfBuffers; | |
| 235 audio_sink_.Configure(buffers); | |
| 236 | |
| 237 context->reply_msg = PpapiPluginMsg_MediaStreamAudioTrack_ConfigureReply(); | |
| 238 return PP_OK; | |
| 239 } | |
| 240 | |
| 188 void PepperMediaStreamAudioTrackHost::OnClose() { | 241 void PepperMediaStreamAudioTrackHost::OnClose() { |
| 189 if (connected_) { | 242 if (connected_) { |
| 190 MediaStreamAudioSink::RemoveFromAudioTrack(&audio_sink_, track_); | 243 MediaStreamAudioSink::RemoveFromAudioTrack(&audio_sink_, track_); |
| 191 connected_ = false; | 244 connected_ = false; |
| 192 } | 245 } |
| 193 } | 246 } |
| 194 | 247 |
| 195 void PepperMediaStreamAudioTrackHost::OnNewBufferEnqueued() { | 248 void PepperMediaStreamAudioTrackHost::OnNewBufferEnqueued() { |
| 196 int32_t index = buffer_manager()->DequeueBuffer(); | 249 int32_t index = buffer_manager()->DequeueBuffer(); |
| 197 DCHECK_GE(index, 0); | 250 DCHECK_GE(index, 0); |
| 198 audio_sink_.EnqueueBuffer(index); | 251 audio_sink_.EnqueueBuffer(index); |
| 199 } | 252 } |
| 200 | 253 |
| 201 void PepperMediaStreamAudioTrackHost::DidConnectPendingHostToResource() { | 254 void PepperMediaStreamAudioTrackHost::DidConnectPendingHostToResource() { |
| 202 if (!connected_) { | 255 if (!connected_) { |
| 203 MediaStreamAudioSink::AddToAudioTrack(&audio_sink_, track_); | 256 MediaStreamAudioSink::AddToAudioTrack(&audio_sink_, track_); |
| 204 connected_ = true; | 257 connected_ = true; |
| 205 } | 258 } |
| 206 } | 259 } |
| 207 | 260 |
| 208 } // namespace content | 261 } // namespace content |
| OLD | NEW |