| 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" |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 } | 58 } |
| 59 | 59 |
| 60 } // namespace | 60 } // namespace |
| 61 | 61 |
| 62 namespace content { | 62 namespace content { |
| 63 | 63 |
| 64 PepperMediaStreamAudioTrackHost::AudioSink::AudioSink( | 64 PepperMediaStreamAudioTrackHost::AudioSink::AudioSink( |
| 65 PepperMediaStreamAudioTrackHost* host) | 65 PepperMediaStreamAudioTrackHost* host) |
| 66 : host_(host), | 66 : host_(host), |
| 67 buffer_data_size_(0), | 67 buffer_data_size_(0), |
| 68 buffers_generation_(0), |
| 68 main_message_loop_proxy_(base::MessageLoopProxy::current()), | 69 main_message_loop_proxy_(base::MessageLoopProxy::current()), |
| 69 weak_factory_(this), | 70 weak_factory_(this), |
| 70 number_of_buffers_(kDefaultNumberOfBuffers), | 71 number_of_buffers_(kDefaultNumberOfBuffers), |
| 71 bytes_per_second_(0) {} | 72 bytes_per_second_(0) {} |
| 72 | 73 |
| 73 PepperMediaStreamAudioTrackHost::AudioSink::~AudioSink() { | 74 PepperMediaStreamAudioTrackHost::AudioSink::~AudioSink() { |
| 74 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | 75 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
| 75 } | 76 } |
| 76 | 77 |
| 77 void PepperMediaStreamAudioTrackHost::AudioSink::EnqueueBuffer(int32_t index) { | 78 void PepperMediaStreamAudioTrackHost::AudioSink::EnqueueBuffer(int32_t index) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 96 } | 97 } |
| 97 | 98 |
| 98 void PepperMediaStreamAudioTrackHost::AudioSink::SetFormatOnMainThread( | 99 void PepperMediaStreamAudioTrackHost::AudioSink::SetFormatOnMainThread( |
| 99 int bytes_per_second) { | 100 int bytes_per_second) { |
| 100 bytes_per_second_ = bytes_per_second; | 101 bytes_per_second_ = bytes_per_second; |
| 101 InitBuffers(); | 102 InitBuffers(); |
| 102 } | 103 } |
| 103 | 104 |
| 104 void PepperMediaStreamAudioTrackHost::AudioSink::InitBuffers() { | 105 void PepperMediaStreamAudioTrackHost::AudioSink::InitBuffers() { |
| 105 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | 106 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
| 107 { |
| 108 base::AutoLock lock(lock_); |
| 109 // Clear |buffers_|, so the audio thread will drop all incoming audio data. |
| 110 buffers_.clear(); |
| 111 buffers_generation_++; |
| 112 } |
| 106 // The size is slightly bigger than necessary, because 8 extra bytes are | 113 // The size is slightly bigger than necessary, because 8 extra bytes are |
| 107 // added into the struct. Also see |MediaStreamBuffer|. | 114 // added into the struct. Also see |MediaStreamBuffer|. |
| 108 base::CheckedNumeric<int32_t> buffer_size = bytes_per_second_; | 115 base::CheckedNumeric<int32_t> buffer_size = bytes_per_second_; |
| 109 buffer_size *= kMaxDuration; | 116 buffer_size *= kMaxDuration; |
| 110 buffer_size /= base::Time::kMillisecondsPerSecond; | 117 buffer_size /= base::Time::kMillisecondsPerSecond; |
| 111 buffer_size += sizeof(ppapi::MediaStreamBuffer::Audio); | 118 buffer_size += sizeof(ppapi::MediaStreamBuffer::Audio); |
| 119 |
| 120 // We don't need to hold |lock_| during |host->InitBuffers()| call, because |
| 121 // we just cleared |buffers_| , so the audio thread will drop all incoming |
| 122 // audio data, and not use buffers in |host_|. |
| 112 bool result = host_->InitBuffers(number_of_buffers_, | 123 bool result = host_->InitBuffers(number_of_buffers_, |
| 113 buffer_size.ValueOrDie(), | 124 buffer_size.ValueOrDie(), |
| 114 kRead); | 125 kRead); |
| 115 // TODO(penghuang): Send PP_ERROR_NOMEMORY to plugin. | 126 // TODO(penghuang): Send PP_ERROR_NOMEMORY to plugin. |
| 116 CHECK(result); | 127 CHECK(result); |
| 128 |
| 129 // Fill the |buffers_|, so the audio thread can continue receiving audio data. |
| 117 base::AutoLock lock(lock_); | 130 base::AutoLock lock(lock_); |
| 118 buffers_.clear(); | |
| 119 for (int32_t i = 0; i < number_of_buffers_; ++i) { | 131 for (int32_t i = 0; i < number_of_buffers_; ++i) { |
| 120 int32_t index = host_->buffer_manager()->DequeueBuffer(); | 132 int32_t index = host_->buffer_manager()->DequeueBuffer(); |
| 121 DCHECK_GE(index, 0); | 133 DCHECK_GE(index, 0); |
| 122 buffers_.push_back(index); | 134 buffers_.push_back(index); |
| 123 } | 135 } |
| 124 } | 136 } |
| 125 | 137 |
| 126 void PepperMediaStreamAudioTrackHost::AudioSink:: | 138 void PepperMediaStreamAudioTrackHost::AudioSink:: |
| 127 SendEnqueueBufferMessageOnMainThread(int32_t index) { | 139 SendEnqueueBufferMessageOnMainThread(int32_t index, |
| 140 int32_t buffers_generation) { |
| 128 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); | 141 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current()); |
| 129 host_->SendEnqueueBufferMessageToPlugin(index); | 142 // If |InitBuffers()| is called after this task being posted from the audio |
| 143 // thread, the buffer should become invalid already. We should ignore it. |
| 144 // And because only the main thread modifies the |buffers_generation_|, |
| 145 // so we don't need to lock |lock_| here (main thread). |
| 146 if (buffers_generation == buffers_generation_) |
| 147 host_->SendEnqueueBufferMessageToPlugin(index); |
| 130 } | 148 } |
| 131 | 149 |
| 132 void PepperMediaStreamAudioTrackHost::AudioSink::OnData(const int16* audio_data, | 150 void PepperMediaStreamAudioTrackHost::AudioSink::OnData(const int16* audio_data, |
| 133 int sample_rate, | 151 int sample_rate, |
| 134 int number_of_channels, | 152 int number_of_channels, |
| 135 int number_of_frames) { | 153 int number_of_frames) { |
| 136 DCHECK(audio_thread_checker_.CalledOnValidThread()); | 154 DCHECK(audio_thread_checker_.CalledOnValidThread()); |
| 137 DCHECK(audio_data); | 155 DCHECK(audio_data); |
| 138 DCHECK_EQ(sample_rate, audio_params_.sample_rate()); | 156 DCHECK_EQ(sample_rate, audio_params_.sample_rate()); |
| 139 DCHECK_EQ(number_of_channels, audio_params_.channels()); | 157 DCHECK_EQ(number_of_channels, audio_params_.channels()); |
| 140 DCHECK_EQ(number_of_frames, audio_params_.frames_per_buffer()); | 158 DCHECK_EQ(number_of_frames, audio_params_.frames_per_buffer()); |
| 141 int32_t index = -1; | |
| 142 { | |
| 143 base::AutoLock lock(lock_); | |
| 144 if (!buffers_.empty()) { | |
| 145 index = buffers_.front(); | |
| 146 buffers_.pop_front(); | |
| 147 } | |
| 148 } | |
| 149 | 159 |
| 150 if (index != -1) { | 160 base::AutoLock lock(lock_); |
| 161 if (!buffers_.empty()) { |
| 162 int index = buffers_.front(); |
| 163 buffers_.pop_front(); |
| 151 // TODO(penghuang): support re-sampling, etc. | 164 // TODO(penghuang): support re-sampling, etc. |
| 152 ppapi::MediaStreamBuffer::Audio* buffer = | 165 ppapi::MediaStreamBuffer::Audio* buffer = |
| 153 &(host_->buffer_manager()->GetBufferPointer(index)->audio); | 166 &(host_->buffer_manager()->GetBufferPointer(index)->audio); |
| 154 buffer->header.size = host_->buffer_manager()->buffer_size(); | 167 buffer->header.size = host_->buffer_manager()->buffer_size(); |
| 155 buffer->header.type = ppapi::MediaStreamBuffer::TYPE_AUDIO; | 168 buffer->header.type = ppapi::MediaStreamBuffer::TYPE_AUDIO; |
| 156 buffer->timestamp = timestamp_.InMillisecondsF(); | 169 buffer->timestamp = timestamp_.InMillisecondsF(); |
| 157 buffer->sample_rate = static_cast<PP_AudioBuffer_SampleRate>(sample_rate); | 170 buffer->sample_rate = static_cast<PP_AudioBuffer_SampleRate>(sample_rate); |
| 158 buffer->number_of_channels = number_of_channels; | 171 buffer->number_of_channels = number_of_channels; |
| 159 buffer->number_of_samples = number_of_channels * number_of_frames; | 172 buffer->number_of_samples = number_of_channels * number_of_frames; |
| 160 buffer->data_size = buffer_data_size_; | 173 buffer->data_size = buffer_data_size_; |
| 161 memcpy(buffer->data, audio_data, buffer_data_size_); | 174 memcpy(buffer->data, audio_data, buffer_data_size_); |
| 162 | 175 |
| 163 main_message_loop_proxy_->PostTask( | 176 main_message_loop_proxy_->PostTask( |
| 164 FROM_HERE, | 177 FROM_HERE, |
| 165 base::Bind(&AudioSink::SendEnqueueBufferMessageOnMainThread, | 178 base::Bind(&AudioSink::SendEnqueueBufferMessageOnMainThread, |
| 166 weak_factory_.GetWeakPtr(), | 179 weak_factory_.GetWeakPtr(), |
| 167 index)); | 180 index, |
| 181 buffers_generation_)); |
| 168 } | 182 } |
| 169 timestamp_ += buffer_duration_; | 183 timestamp_ += buffer_duration_; |
| 170 } | 184 } |
| 171 | 185 |
| 172 void PepperMediaStreamAudioTrackHost::AudioSink::OnSetFormat( | 186 void PepperMediaStreamAudioTrackHost::AudioSink::OnSetFormat( |
| 173 const AudioParameters& params) { | 187 const AudioParameters& params) { |
| 174 DCHECK(params.IsValid()); | 188 DCHECK(params.IsValid()); |
| 175 DCHECK_LE(params.GetBufferDuration().InMilliseconds(), kMaxDuration); | 189 DCHECK_LE(params.GetBufferDuration().InMilliseconds(), kMaxDuration); |
| 176 DCHECK_EQ(params.bits_per_sample(), 16); | 190 DCHECK_EQ(params.bits_per_sample(), 16); |
| 177 DCHECK_NE(GetPPSampleRate(params.sample_rate()), | 191 DCHECK_NE(GetPPSampleRate(params.sample_rate()), |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 } | 270 } |
| 257 | 271 |
| 258 void PepperMediaStreamAudioTrackHost::DidConnectPendingHostToResource() { | 272 void PepperMediaStreamAudioTrackHost::DidConnectPendingHostToResource() { |
| 259 if (!connected_) { | 273 if (!connected_) { |
| 260 MediaStreamAudioSink::AddToAudioTrack(&audio_sink_, track_); | 274 MediaStreamAudioSink::AddToAudioTrack(&audio_sink_, track_); |
| 261 connected_ = true; | 275 connected_ = true; |
| 262 } | 276 } |
| 263 } | 277 } |
| 264 | 278 |
| 265 } // namespace content | 279 } // namespace content |
| OLD | NEW |