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> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/macros.h" | 12 #include "base/macros.h" |
| 13 #include "base/message_loop/message_loop_proxy.h" | 13 #include "base/message_loop/message_loop_proxy.h" |
| 14 #include "base/numerics/safe_math.h" | 14 #include "base/numerics/safe_math.h" |
| 15 #include "ppapi/c/pp_errors.h" | 15 #include "ppapi/c/pp_errors.h" |
| 16 #include "ppapi/c/ppb_audio_buffer.h" | 16 #include "ppapi/c/ppb_audio_buffer.h" |
| 17 #include "ppapi/host/dispatch_host_message.h" | 17 #include "ppapi/host/dispatch_host_message.h" |
| 18 #include "ppapi/host/host_message_context.h" | 18 #include "ppapi/host/host_message_context.h" |
| 19 #include "ppapi/proxy/ppapi_messages.h" | 19 #include "ppapi/proxy/ppapi_messages.h" |
| 20 #include "ppapi/shared_impl/media_stream_audio_track_shared.h" | 20 #include "ppapi/shared_impl/media_stream_audio_track_shared.h" |
| 21 #include "ppapi/shared_impl/media_stream_buffer.h" | 21 #include "ppapi/shared_impl/media_stream_buffer.h" |
| 22 | 22 |
| 23 using media::AudioParameters; | 23 using media::AudioParameters; |
| 24 using ppapi::host::HostMessageContext; | 24 using ppapi::host::HostMessageContext; |
| 25 using ppapi::MediaStreamAudioTrackShared; | 25 using ppapi::MediaStreamAudioTrackShared; |
| 26 | 26 |
| 27 namespace { | 27 namespace { |
| 28 | 28 |
| 29 // Max audio buffer duration in milliseconds. | 29 // Audio buffer durations in milliseconds. |
| 30 const uint32_t kMaxDuration = 10; | 30 const uint32_t kMinDuration = 10; |
| 31 const uint32_t kDefaultDuration = 123; | |
|
dmichael (off chromium)
2014/07/23 20:08:41
This seems like a weird default... did you benchm
Anand Mistry (off Chromium)
2014/07/24 01:28:28
Oops. A hold over from testing. It should be 10, w
| |
| 31 | 32 |
| 32 const int32_t kDefaultNumberOfBuffers = 4; | 33 const int32_t kDefaultNumberOfBuffers = 4; |
| 33 const int32_t kMaxNumberOfBuffers = 1000; // 10 sec | 34 const int32_t kMaxNumberOfBuffers = 1000; // 10 sec |
| 34 | 35 |
| 35 // Returns true if the |sample_rate| is supported in | 36 // Returns true if the |sample_rate| is supported in |
| 36 // |PP_AudioBuffer_SampleRate|, otherwise false. | 37 // |PP_AudioBuffer_SampleRate|, otherwise false. |
| 37 PP_AudioBuffer_SampleRate GetPPSampleRate(int sample_rate) { | 38 PP_AudioBuffer_SampleRate GetPPSampleRate(int sample_rate) { |
| 38 switch (sample_rate) { | 39 switch (sample_rate) { |
| 39 case 8000: | 40 case 8000: |
| 40 return PP_AUDIOBUFFER_SAMPLERATE_8000; | 41 return PP_AUDIOBUFFER_SAMPLERATE_8000; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 58 } | 59 } |
| 59 | 60 |
| 60 } // namespace | 61 } // namespace |
| 61 | 62 |
| 62 namespace content { | 63 namespace content { |
| 63 | 64 |
| 64 PepperMediaStreamAudioTrackHost::AudioSink::AudioSink( | 65 PepperMediaStreamAudioTrackHost::AudioSink::AudioSink( |
| 65 PepperMediaStreamAudioTrackHost* host) | 66 PepperMediaStreamAudioTrackHost* host) |
| 66 : host_(host), | 67 : host_(host), |
| 67 buffer_data_size_(0), | 68 buffer_data_size_(0), |
| 69 active_buffer_index_(-1), | |
| 70 active_buffer_offset_(0), | |
| 68 main_message_loop_proxy_(base::MessageLoopProxy::current()), | 71 main_message_loop_proxy_(base::MessageLoopProxy::current()), |
| 69 weak_factory_(this), | 72 weak_factory_(this), |
| 70 number_of_buffers_(kDefaultNumberOfBuffers), | 73 number_of_buffers_(kDefaultNumberOfBuffers), |
| 71 bytes_per_second_(0) {} | 74 bytes_per_second_(0), |
| 75 user_buffer_duration_(kDefaultDuration) {} | |
| 72 | 76 |
| 73 PepperMediaStreamAudioTrackHost::AudioSink::~AudioSink() { | 77 PepperMediaStreamAudioTrackHost::AudioSink::~AudioSink() { |
| 74 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | 78 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
| 75 } | 79 } |
| 76 | 80 |
| 77 void PepperMediaStreamAudioTrackHost::AudioSink::EnqueueBuffer(int32_t index) { | 81 void PepperMediaStreamAudioTrackHost::AudioSink::EnqueueBuffer(int32_t index) { |
| 78 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | 82 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
| 79 DCHECK_GE(index, 0); | 83 DCHECK_GE(index, 0); |
| 80 DCHECK_LT(index, host_->buffer_manager()->number_of_buffers()); | 84 DCHECK_LT(index, host_->buffer_manager()->number_of_buffers()); |
| 81 base::AutoLock lock(lock_); | 85 base::AutoLock lock(lock_); |
| 82 buffers_.push_back(index); | 86 buffers_.push_back(index); |
| 83 } | 87 } |
| 84 | 88 |
| 85 void PepperMediaStreamAudioTrackHost::AudioSink::Configure( | 89 void PepperMediaStreamAudioTrackHost::AudioSink::Configure( |
| 86 int32_t number_of_buffers) { | 90 int32_t number_of_buffers, int32_t duration) { |
| 87 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | 91 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
| 88 bool changed = false; | 92 bool changed = false; |
| 89 if (number_of_buffers != number_of_buffers_) | 93 if (number_of_buffers != number_of_buffers_) |
| 90 changed = true; | 94 changed = true; |
| 95 if (duration != 0 && duration != user_buffer_duration_) { | |
| 96 user_buffer_duration_ = duration; | |
| 97 changed = true; | |
| 98 } | |
| 91 number_of_buffers_ = number_of_buffers; | 99 number_of_buffers_ = number_of_buffers; |
| 92 | 100 |
| 93 // Initialize later in OnSetFormat if bytes_per_second_ is not know yet. | 101 // Initialize later in OnSetFormat if bytes_per_second_ is not know yet. |
| 94 if (changed && bytes_per_second_ > 0) | 102 if (changed && bytes_per_second_ > 0 && bytes_per_frame_ > 0) |
| 95 InitBuffers(); | 103 InitBuffers(); |
| 96 } | 104 } |
| 97 | 105 |
| 98 void PepperMediaStreamAudioTrackHost::AudioSink::SetFormatOnMainThread( | 106 void PepperMediaStreamAudioTrackHost::AudioSink::SetFormatOnMainThread( |
| 99 int bytes_per_second) { | 107 int bytes_per_second, int bytes_per_frame) { |
| 100 bytes_per_second_ = bytes_per_second; | 108 bytes_per_second_ = bytes_per_second; |
| 109 bytes_per_frame_ = bytes_per_frame; | |
| 101 InitBuffers(); | 110 InitBuffers(); |
| 102 } | 111 } |
| 103 | 112 |
| 104 void PepperMediaStreamAudioTrackHost::AudioSink::InitBuffers() { | 113 void PepperMediaStreamAudioTrackHost::AudioSink::InitBuffers() { |
| 105 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | 114 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
| 115 int32_t frame_rate = bytes_per_second_ / bytes_per_frame_; | |
| 116 int32_t frames_per_buffer = (user_buffer_duration_ * frame_rate) / | |
| 117 base::Time::kMillisecondsPerSecond; | |
|
dmichael (off chromium)
2014/07/23 20:08:41
Please use CheckedNumeric from base/numerics/safe_
Anand Mistry (off Chromium)
2014/07/24 01:28:28
Done.
| |
| 118 int32_t buffer_audio_size = frames_per_buffer * bytes_per_frame_; | |
| 106 // The size is slightly bigger than necessary, because 8 extra bytes are | 119 // The size is slightly bigger than necessary, because 8 extra bytes are |
| 107 // added into the struct. Also see |MediaStreamBuffer|. | 120 // added into the struct. Also see |MediaStreamBuffer|. Also, the size of the |
| 108 base::CheckedNumeric<int32_t> buffer_size = bytes_per_second_; | 121 // buffer may be larger than requested, since the size of each buffer will be |
| 109 buffer_size *= kMaxDuration; | 122 // 4-byte aligned. |
| 110 buffer_size /= base::Time::kMillisecondsPerSecond; | 123 base::CheckedNumeric<int32_t> buffer_size = buffer_audio_size; |
| 111 buffer_size += sizeof(ppapi::MediaStreamBuffer::Audio); | 124 buffer_size += sizeof(ppapi::MediaStreamBuffer::Audio); |
| 125 // Re-initialising buffers will unmap the existing buffers. If the audio | |
| 126 // thread is writing to one, then it will SEGV. | |
| 127 // TODO(amistry): Fix me! | |
|
dmichael (off chromium)
2014/07/23 20:08:41
Good catch! File a bug to reference here, please.
Peng
2014/07/23 20:40:31
I has a CL[1] to fix this issue. With the CL [1],
Anand Mistry (off Chromium)
2014/07/24 01:28:28
Applied that CL to this.
| |
| 112 bool result = host_->InitBuffers(number_of_buffers_, | 128 bool result = host_->InitBuffers(number_of_buffers_, |
| 113 buffer_size.ValueOrDie(), | 129 buffer_size.ValueOrDie(), |
| 114 kRead); | 130 kRead); |
| 115 // TODO(penghuang): Send PP_ERROR_NOMEMORY to plugin. | 131 // TODO(penghuang): Send PP_ERROR_NOMEMORY to plugin. |
| 116 CHECK(result); | 132 CHECK(result); |
| 117 base::AutoLock lock(lock_); | 133 base::AutoLock lock(lock_); |
| 134 output_buffer_size_ = buffer_audio_size; | |
| 118 buffers_.clear(); | 135 buffers_.clear(); |
| 119 for (int32_t i = 0; i < number_of_buffers_; ++i) { | 136 for (int32_t i = 0; i < number_of_buffers_; ++i) { |
| 120 int32_t index = host_->buffer_manager()->DequeueBuffer(); | 137 int32_t index = host_->buffer_manager()->DequeueBuffer(); |
| 121 DCHECK_GE(index, 0); | 138 DCHECK_GE(index, 0); |
| 122 buffers_.push_back(index); | 139 buffers_.push_back(index); |
| 123 } | 140 } |
| 124 } | 141 } |
| 125 | 142 |
| 126 void PepperMediaStreamAudioTrackHost::AudioSink:: | 143 void PepperMediaStreamAudioTrackHost::AudioSink:: |
| 127 SendEnqueueBufferMessageOnMainThread(int32_t index) { | 144 SendEnqueueBufferMessageOnMainThread(int32_t index) { |
| 128 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | 145 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
| 129 host_->SendEnqueueBufferMessageToPlugin(index); | 146 host_->SendEnqueueBufferMessageToPlugin(index); |
| 130 } | 147 } |
| 131 | 148 |
| 132 void PepperMediaStreamAudioTrackHost::AudioSink::OnData(const int16* audio_data, | 149 void PepperMediaStreamAudioTrackHost::AudioSink::OnData(const int16* audio_data, |
| 133 int sample_rate, | 150 int sample_rate, |
| 134 int number_of_channels, | 151 int number_of_channels, |
| 135 int number_of_frames) { | 152 int number_of_frames) { |
| 136 DCHECK(audio_thread_checker_.CalledOnValidThread()); | 153 DCHECK(audio_thread_checker_.CalledOnValidThread()); |
| 137 DCHECK(audio_data); | 154 DCHECK(audio_data); |
| 138 DCHECK_EQ(sample_rate, audio_params_.sample_rate()); | 155 DCHECK_EQ(sample_rate, audio_params_.sample_rate()); |
| 139 DCHECK_EQ(number_of_channels, audio_params_.channels()); | 156 DCHECK_EQ(number_of_channels, audio_params_.channels()); |
| 140 DCHECK_EQ(number_of_frames, audio_params_.frames_per_buffer()); | 157 DCHECK_EQ(number_of_frames, audio_params_.frames_per_buffer()); |
|
dmichael (off chromium)
2014/07/23 20:08:41
Given this ^^^ Why do you need the new code to all
Anand Mistry (off Chromium)
2014/07/24 01:28:28
More like this DCHECK is irrelevant because this c
dmichael (off chromium)
2014/07/29 16:41:24
So if we're guaranteed to have this property, can'
Anand Mistry (off Chromium)
2014/07/30 00:22:05
The reason this code is complex is to handle cases
dmichael (off chromium)
2014/07/30 23:09:22
So audio_params_.frames_per_buffer() might not ref
Anand Mistry (off Chromium)
2014/07/31 00:41:21
Done.
| |
| 141 int32_t index = -1; | 158 |
| 142 { | 159 const uint32_t bytes_per_frame = number_of_channels * |
| 143 base::AutoLock lock(lock_); | 160 audio_params_.bits_per_sample() / 8; |
| 144 if (!buffers_.empty()) { | 161 |
| 145 index = buffers_.front(); | 162 int frames_remaining = number_of_frames; |
| 146 buffers_.pop_front(); | 163 base::TimeDelta timestamp_offset; |
| 164 while (frames_remaining) { | |
| 165 uint32_t output_buffer_size = 0; | |
| 166 if (active_buffer_index_ == -1) { | |
| 167 active_buffer_offset_ = 0; | |
| 168 active_buffer_ptr_ = NULL; | |
| 169 base::AutoLock lock(lock_); | |
| 170 output_buffer_size = output_buffer_size_; | |
| 171 if (!buffers_.empty()) { | |
| 172 active_buffer_index_ = buffers_.front(); | |
| 173 buffers_.pop_front(); | |
| 174 } | |
| 147 } | 175 } |
| 148 } | 176 if (active_buffer_index_ == -1) { |
| 177 // Eek! We're dropping frames. Bad, bad, bad! | |
| 178 break; | |
| 179 } | |
| 149 | 180 |
| 150 if (index != -1) { | |
| 151 // TODO(penghuang): support re-sampling, etc. | 181 // TODO(penghuang): support re-sampling, etc. |
| 182 // TODO(amistry): NOT SAFE! | |
|
dmichael (off chromium)
2014/07/23 20:08:42
Can you elaborate?
Anand Mistry (off Chromium)
2014/07/24 01:28:28
It was to do with the thread safety of the buffer
| |
| 152 ppapi::MediaStreamBuffer::Audio* buffer = | 183 ppapi::MediaStreamBuffer::Audio* buffer = |
| 153 &(host_->buffer_manager()->GetBufferPointer(index)->audio); | 184 &(host_->buffer_manager()->GetBufferPointer(active_buffer_index_) |
| 154 buffer->header.size = host_->buffer_manager()->buffer_size(); | 185 ->audio); |
| 155 buffer->header.type = ppapi::MediaStreamBuffer::TYPE_AUDIO; | 186 if (active_buffer_offset_ == 0) { |
| 156 buffer->timestamp = timestamp_.InMillisecondsF(); | 187 // Next buffer. Not using an active buffer. |
| 157 buffer->sample_rate = static_cast<PP_AudioBuffer_SampleRate>(sample_rate); | 188 active_buffer_ptr_ = buffer; |
| 158 buffer->number_of_channels = number_of_channels; | 189 buffer->header.size = host_->buffer_manager()->buffer_size(); |
| 159 buffer->number_of_samples = number_of_channels * number_of_frames; | 190 buffer->header.type = ppapi::MediaStreamBuffer::TYPE_AUDIO; |
| 160 buffer->data_size = buffer_data_size_; | 191 buffer->timestamp = (timestamp_ + timestamp_offset).InMillisecondsF(); |
| 161 memcpy(buffer->data, audio_data, buffer_data_size_); | 192 buffer->sample_rate = static_cast<PP_AudioBuffer_SampleRate>(sample_rate); |
| 193 DCHECK_NE(output_buffer_size, 0U); | |
| 194 buffer->data_size = output_buffer_size; | |
| 195 buffer->number_of_channels = number_of_channels; | |
| 196 buffer->number_of_samples = buffer->data_size / bytes_per_frame; | |
| 197 } else if (buffer != active_buffer_ptr_ || buffer->data_size == 0) { | |
| 198 // Buffer no longer valid. | |
| 199 active_buffer_index_ = -1; | |
| 200 continue; | |
| 201 } | |
| 202 uint32_t buffer_bytes_remaining = | |
| 203 buffer->data_size - active_buffer_offset_; | |
| 204 DCHECK_EQ(buffer_bytes_remaining % bytes_per_frame, 0U); | |
| 205 uint32_t incoming_bytes_remaining = frames_remaining * bytes_per_frame; | |
| 206 uint32_t bytes_to_copy = std::min(buffer_bytes_remaining, | |
| 207 incoming_bytes_remaining); | |
| 208 uint32_t frames_to_copy = bytes_to_copy / bytes_per_frame; | |
| 209 DCHECK_EQ(bytes_to_copy % bytes_per_frame, 0U); | |
| 210 memcpy(buffer->data + active_buffer_offset_, | |
| 211 audio_data, bytes_to_copy); | |
| 212 active_buffer_offset_ += bytes_to_copy; | |
| 213 audio_data += bytes_to_copy / 2; | |
| 214 frames_remaining -= frames_to_copy; | |
| 215 timestamp_offset += base::TimeDelta::FromMilliseconds( | |
| 216 frames_to_copy * base::Time::kMillisecondsPerSecond / sample_rate); | |
| 162 | 217 |
| 163 main_message_loop_proxy_->PostTask( | 218 DCHECK_LE(active_buffer_offset_, buffer->data_size); |
| 164 FROM_HERE, | 219 if (active_buffer_offset_ == buffer->data_size) { |
| 165 base::Bind(&AudioSink::SendEnqueueBufferMessageOnMainThread, | 220 main_message_loop_proxy_->PostTask( |
| 166 weak_factory_.GetWeakPtr(), | 221 FROM_HERE, |
| 167 index)); | 222 base::Bind(&AudioSink::SendEnqueueBufferMessageOnMainThread, |
| 223 weak_factory_.GetWeakPtr(), | |
| 224 active_buffer_index_)); | |
| 225 active_buffer_index_ = -1; | |
| 226 } | |
| 168 } | 227 } |
| 169 timestamp_ += buffer_duration_; | 228 timestamp_ += buffer_duration_; |
| 170 } | 229 } |
| 171 | 230 |
| 172 void PepperMediaStreamAudioTrackHost::AudioSink::OnSetFormat( | 231 void PepperMediaStreamAudioTrackHost::AudioSink::OnSetFormat( |
| 173 const AudioParameters& params) { | 232 const AudioParameters& params) { |
| 174 DCHECK(params.IsValid()); | 233 DCHECK(params.IsValid()); |
| 175 DCHECK_LE(params.GetBufferDuration().InMilliseconds(), kMaxDuration); | 234 // TODO(amistry): How do you handle the case where the user configures a |
| 235 // duration that's shorter than the received buffer duration? One option is to | |
| 236 // double buffer, where the size of the intermediate ring buffer is at least | |
| 237 // max(user requested duration, received buffer duration). There are other | |
| 238 // ways of dealing with it, but which one is "correct"? | |
| 239 DCHECK_LE(params.GetBufferDuration().InMilliseconds(), kMinDuration); | |
| 176 DCHECK_EQ(params.bits_per_sample(), 16); | 240 DCHECK_EQ(params.bits_per_sample(), 16); |
| 177 DCHECK_NE(GetPPSampleRate(params.sample_rate()), | 241 DCHECK_NE(GetPPSampleRate(params.sample_rate()), |
| 178 PP_AUDIOBUFFER_SAMPLERATE_UNKNOWN); | 242 PP_AUDIOBUFFER_SAMPLERATE_UNKNOWN); |
| 179 | 243 |
| 180 audio_params_ = params; | 244 audio_params_ = params; |
| 181 | 245 |
| 182 // TODO(penghuang): support setting format more than once. | 246 // TODO(penghuang): support setting format more than once. |
| 183 buffer_duration_ = params.GetBufferDuration(); | 247 buffer_duration_ = params.GetBufferDuration(); |
| 184 buffer_data_size_ = params.GetBytesPerBuffer(); | 248 buffer_data_size_ = params.GetBytesPerBuffer(); |
| 185 | 249 |
| 186 if (original_audio_params_.IsValid()) { | 250 if (original_audio_params_.IsValid()) { |
| 187 DCHECK_EQ(params.sample_rate(), original_audio_params_.sample_rate()); | 251 DCHECK_EQ(params.sample_rate(), original_audio_params_.sample_rate()); |
| 188 DCHECK_EQ(params.bits_per_sample(), | 252 DCHECK_EQ(params.bits_per_sample(), |
| 189 original_audio_params_.bits_per_sample()); | 253 original_audio_params_.bits_per_sample()); |
| 190 DCHECK_EQ(params.channels(), original_audio_params_.channels()); | 254 DCHECK_EQ(params.channels(), original_audio_params_.channels()); |
| 191 } else { | 255 } else { |
| 192 audio_thread_checker_.DetachFromThread(); | 256 audio_thread_checker_.DetachFromThread(); |
| 193 original_audio_params_ = params; | 257 original_audio_params_ = params; |
| 194 | 258 |
| 259 int bytes_per_frame = params.channels() * params.bits_per_sample() / 8; | |
| 195 main_message_loop_proxy_->PostTask( | 260 main_message_loop_proxy_->PostTask( |
| 196 FROM_HERE, | 261 FROM_HERE, |
| 197 base::Bind(&AudioSink::SetFormatOnMainThread, | 262 base::Bind(&AudioSink::SetFormatOnMainThread, |
| 198 weak_factory_.GetWeakPtr(), | 263 weak_factory_.GetWeakPtr(), |
| 199 params.GetBytesPerSecond())); | 264 params.GetBytesPerSecond(), |
| 265 bytes_per_frame)); | |
| 200 } | 266 } |
| 201 } | 267 } |
| 202 | 268 |
| 203 PepperMediaStreamAudioTrackHost::PepperMediaStreamAudioTrackHost( | 269 PepperMediaStreamAudioTrackHost::PepperMediaStreamAudioTrackHost( |
| 204 RendererPpapiHost* host, | 270 RendererPpapiHost* host, |
| 205 PP_Instance instance, | 271 PP_Instance instance, |
| 206 PP_Resource resource, | 272 PP_Resource resource, |
| 207 const blink::WebMediaStreamTrack& track) | 273 const blink::WebMediaStreamTrack& track) |
| 208 : PepperMediaStreamTrackHostBase(host, instance, resource), | 274 : PepperMediaStreamTrackHostBase(host, instance, resource), |
| 209 track_(track), | 275 track_(track), |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 229 | 295 |
| 230 int32_t PepperMediaStreamAudioTrackHost::OnHostMsgConfigure( | 296 int32_t PepperMediaStreamAudioTrackHost::OnHostMsgConfigure( |
| 231 HostMessageContext* context, | 297 HostMessageContext* context, |
| 232 const MediaStreamAudioTrackShared::Attributes& attributes) { | 298 const MediaStreamAudioTrackShared::Attributes& attributes) { |
| 233 if (!MediaStreamAudioTrackShared::VerifyAttributes(attributes)) | 299 if (!MediaStreamAudioTrackShared::VerifyAttributes(attributes)) |
| 234 return PP_ERROR_BADARGUMENT; | 300 return PP_ERROR_BADARGUMENT; |
| 235 | 301 |
| 236 int32_t buffers = attributes.buffers | 302 int32_t buffers = attributes.buffers |
| 237 ? std::min(kMaxNumberOfBuffers, attributes.buffers) | 303 ? std::min(kMaxNumberOfBuffers, attributes.buffers) |
| 238 : kDefaultNumberOfBuffers; | 304 : kDefaultNumberOfBuffers; |
| 239 audio_sink_.Configure(buffers); | 305 audio_sink_.Configure(buffers, attributes.duration); |
| 240 | 306 |
| 241 context->reply_msg = PpapiPluginMsg_MediaStreamAudioTrack_ConfigureReply(); | 307 context->reply_msg = PpapiPluginMsg_MediaStreamAudioTrack_ConfigureReply(); |
| 242 return PP_OK; | 308 return PP_OK; |
| 243 } | 309 } |
| 244 | 310 |
| 245 void PepperMediaStreamAudioTrackHost::OnClose() { | 311 void PepperMediaStreamAudioTrackHost::OnClose() { |
| 246 if (connected_) { | 312 if (connected_) { |
| 247 MediaStreamAudioSink::RemoveFromAudioTrack(&audio_sink_, track_); | 313 MediaStreamAudioSink::RemoveFromAudioTrack(&audio_sink_, track_); |
| 248 connected_ = false; | 314 connected_ = false; |
| 249 } | 315 } |
| 250 } | 316 } |
| 251 | 317 |
| 252 void PepperMediaStreamAudioTrackHost::OnNewBufferEnqueued() { | 318 void PepperMediaStreamAudioTrackHost::OnNewBufferEnqueued() { |
| 253 int32_t index = buffer_manager()->DequeueBuffer(); | 319 int32_t index = buffer_manager()->DequeueBuffer(); |
| 254 DCHECK_GE(index, 0); | 320 DCHECK_GE(index, 0); |
| 255 audio_sink_.EnqueueBuffer(index); | 321 audio_sink_.EnqueueBuffer(index); |
| 256 } | 322 } |
| 257 | 323 |
| 258 void PepperMediaStreamAudioTrackHost::DidConnectPendingHostToResource() { | 324 void PepperMediaStreamAudioTrackHost::DidConnectPendingHostToResource() { |
| 259 if (!connected_) { | 325 if (!connected_) { |
| 260 MediaStreamAudioSink::AddToAudioTrack(&audio_sink_, track_); | 326 MediaStreamAudioSink::AddToAudioTrack(&audio_sink_, track_); |
| 261 connected_ = true; | 327 connected_ = true; |
| 262 } | 328 } |
| 263 } | 329 } |
| 264 | 330 |
| 265 } // namespace content | 331 } // namespace content |
| OLD | NEW |