chrome.bluetoothSocket: clean-up Listen functions
[chromium-blink-merge.git] / content / renderer / pepper / pepper_media_stream_audio_track_host.cc
blobd972c2c061e2882eb1257d92fc9981e18a296ba5
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
3 // found in the LICENSE file.
5 #include "content/renderer/pepper/pepper_media_stream_audio_track_host.h"
7 #include <algorithm>
9 #include "base/bind.h"
10 #include "base/location.h"
11 #include "base/logging.h"
12 #include "base/macros.h"
13 #include "base/message_loop/message_loop_proxy.h"
14 #include "base/numerics/safe_math.h"
15 #include "ppapi/c/pp_errors.h"
16 #include "ppapi/c/ppb_audio_buffer.h"
17 #include "ppapi/host/dispatch_host_message.h"
18 #include "ppapi/host/host_message_context.h"
19 #include "ppapi/proxy/ppapi_messages.h"
20 #include "ppapi/shared_impl/media_stream_audio_track_shared.h"
21 #include "ppapi/shared_impl/media_stream_buffer.h"
23 using media::AudioParameters;
24 using ppapi::host::HostMessageContext;
25 using ppapi::MediaStreamAudioTrackShared;
27 namespace {
29 // Max audio buffer duration in milliseconds.
30 const uint32_t kMaxDuration = 10;
32 const int32_t kDefaultNumberOfBuffers = 4;
33 const int32_t kMaxNumberOfBuffers = 1000; // 10 sec
35 // Returns true if the |sample_rate| is supported in
36 // |PP_AudioBuffer_SampleRate|, otherwise false.
37 PP_AudioBuffer_SampleRate GetPPSampleRate(int sample_rate) {
38 switch (sample_rate) {
39 case 8000:
40 return PP_AUDIOBUFFER_SAMPLERATE_8000;
41 case 16000:
42 return PP_AUDIOBUFFER_SAMPLERATE_16000;
43 case 22050:
44 return PP_AUDIOBUFFER_SAMPLERATE_22050;
45 case 32000:
46 return PP_AUDIOBUFFER_SAMPLERATE_32000;
47 case 44100:
48 return PP_AUDIOBUFFER_SAMPLERATE_44100;
49 case 48000:
50 return PP_AUDIOBUFFER_SAMPLERATE_48000;
51 case 96000:
52 return PP_AUDIOBUFFER_SAMPLERATE_96000;
53 case 192000:
54 return PP_AUDIOBUFFER_SAMPLERATE_192000;
55 default:
56 return PP_AUDIOBUFFER_SAMPLERATE_UNKNOWN;
60 } // namespace
62 namespace content {
64 PepperMediaStreamAudioTrackHost::AudioSink::AudioSink(
65 PepperMediaStreamAudioTrackHost* host)
66 : host_(host),
67 buffer_data_size_(0),
68 main_message_loop_proxy_(base::MessageLoopProxy::current()),
69 weak_factory_(this),
70 number_of_buffers_(kDefaultNumberOfBuffers),
71 bytes_per_second_(0) {}
73 PepperMediaStreamAudioTrackHost::AudioSink::~AudioSink() {
74 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current());
77 void PepperMediaStreamAudioTrackHost::AudioSink::EnqueueBuffer(int32_t index) {
78 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current());
79 DCHECK_GE(index, 0);
80 DCHECK_LT(index, host_->buffer_manager()->number_of_buffers());
81 base::AutoLock lock(lock_);
82 buffers_.push_back(index);
85 void PepperMediaStreamAudioTrackHost::AudioSink::Configure(
86 int32_t number_of_buffers) {
87 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current());
88 bool changed = false;
89 if (number_of_buffers != number_of_buffers_)
90 changed = true;
91 number_of_buffers_ = number_of_buffers;
93 // Initialize later in OnSetFormat if bytes_per_second_ is not know yet.
94 if (changed && bytes_per_second_ > 0)
95 InitBuffers();
98 void PepperMediaStreamAudioTrackHost::AudioSink::SetFormatOnMainThread(
99 int bytes_per_second) {
100 bytes_per_second_ = bytes_per_second;
101 InitBuffers();
104 void PepperMediaStreamAudioTrackHost::AudioSink::InitBuffers() {
105 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current());
106 // The size is slightly bigger than necessary, because 8 extra bytes are
107 // added into the struct. Also see |MediaStreamBuffer|.
108 base::CheckedNumeric<int32_t> buffer_size = bytes_per_second_;
109 buffer_size *= kMaxDuration;
110 buffer_size /= base::Time::kMillisecondsPerSecond;
111 buffer_size += sizeof(ppapi::MediaStreamBuffer::Audio);
112 bool result = host_->InitBuffers(number_of_buffers_,
113 buffer_size.ValueOrDie(),
114 kRead);
115 // TODO(penghuang): Send PP_ERROR_NOMEMORY to plugin.
116 CHECK(result);
117 base::AutoLock lock(lock_);
118 buffers_.clear();
119 for (int32_t i = 0; i < number_of_buffers_; ++i) {
120 int32_t index = host_->buffer_manager()->DequeueBuffer();
121 DCHECK_GE(index, 0);
122 buffers_.push_back(index);
126 void PepperMediaStreamAudioTrackHost::AudioSink::
127 SendEnqueueBufferMessageOnMainThread(int32_t index) {
128 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current());
129 host_->SendEnqueueBufferMessageToPlugin(index);
132 void PepperMediaStreamAudioTrackHost::AudioSink::OnData(const int16* audio_data,
133 int sample_rate,
134 int number_of_channels,
135 int number_of_frames) {
136 DCHECK(audio_thread_checker_.CalledOnValidThread());
137 DCHECK(audio_data);
138 DCHECK_EQ(sample_rate, audio_params_.sample_rate());
139 DCHECK_EQ(number_of_channels, audio_params_.channels());
140 DCHECK_EQ(number_of_frames, audio_params_.frames_per_buffer());
141 int32_t index = -1;
143 base::AutoLock lock(lock_);
144 if (!buffers_.empty()) {
145 index = buffers_.front();
146 buffers_.pop_front();
150 if (index != -1) {
151 // TODO(penghuang): support re-sampling, etc.
152 ppapi::MediaStreamBuffer::Audio* buffer =
153 &(host_->buffer_manager()->GetBufferPointer(index)->audio);
154 buffer->header.size = host_->buffer_manager()->buffer_size();
155 buffer->header.type = ppapi::MediaStreamBuffer::TYPE_AUDIO;
156 buffer->timestamp = timestamp_.InMillisecondsF();
157 buffer->sample_rate = static_cast<PP_AudioBuffer_SampleRate>(sample_rate);
158 buffer->number_of_channels = number_of_channels;
159 buffer->number_of_samples = number_of_channels * number_of_frames;
160 buffer->data_size = buffer_data_size_;
161 memcpy(buffer->data, audio_data, buffer_data_size_);
163 main_message_loop_proxy_->PostTask(
164 FROM_HERE,
165 base::Bind(&AudioSink::SendEnqueueBufferMessageOnMainThread,
166 weak_factory_.GetWeakPtr(),
167 index));
169 timestamp_ += buffer_duration_;
172 void PepperMediaStreamAudioTrackHost::AudioSink::OnSetFormat(
173 const AudioParameters& params) {
174 DCHECK(params.IsValid());
175 DCHECK_LE(params.GetBufferDuration().InMilliseconds(), kMaxDuration);
176 DCHECK_EQ(params.bits_per_sample(), 16);
177 DCHECK_NE(GetPPSampleRate(params.sample_rate()),
178 PP_AUDIOBUFFER_SAMPLERATE_UNKNOWN);
180 audio_params_ = params;
182 // TODO(penghuang): support setting format more than once.
183 buffer_duration_ = params.GetBufferDuration();
184 buffer_data_size_ = params.GetBytesPerBuffer();
186 if (original_audio_params_.IsValid()) {
187 DCHECK_EQ(params.sample_rate(), original_audio_params_.sample_rate());
188 DCHECK_EQ(params.bits_per_sample(),
189 original_audio_params_.bits_per_sample());
190 DCHECK_EQ(params.channels(), original_audio_params_.channels());
191 } else {
192 audio_thread_checker_.DetachFromThread();
193 original_audio_params_ = params;
195 main_message_loop_proxy_->PostTask(
196 FROM_HERE,
197 base::Bind(&AudioSink::SetFormatOnMainThread,
198 weak_factory_.GetWeakPtr(),
199 params.GetBytesPerSecond()));
203 PepperMediaStreamAudioTrackHost::PepperMediaStreamAudioTrackHost(
204 RendererPpapiHost* host,
205 PP_Instance instance,
206 PP_Resource resource,
207 const blink::WebMediaStreamTrack& track)
208 : PepperMediaStreamTrackHostBase(host, instance, resource),
209 track_(track),
210 connected_(false),
211 audio_sink_(this) {
212 DCHECK(!track_.isNull());
215 PepperMediaStreamAudioTrackHost::~PepperMediaStreamAudioTrackHost() {
216 OnClose();
219 int32_t PepperMediaStreamAudioTrackHost::OnResourceMessageReceived(
220 const IPC::Message& msg,
221 HostMessageContext* context) {
222 PPAPI_BEGIN_MESSAGE_MAP(PepperMediaStreamAudioTrackHost, msg)
223 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
224 PpapiHostMsg_MediaStreamAudioTrack_Configure, OnHostMsgConfigure)
225 PPAPI_END_MESSAGE_MAP()
226 return PepperMediaStreamTrackHostBase::OnResourceMessageReceived(msg,
227 context);
230 int32_t PepperMediaStreamAudioTrackHost::OnHostMsgConfigure(
231 HostMessageContext* context,
232 const MediaStreamAudioTrackShared::Attributes& attributes) {
233 if (!MediaStreamAudioTrackShared::VerifyAttributes(attributes))
234 return PP_ERROR_BADARGUMENT;
236 int32_t buffers = attributes.buffers
237 ? std::min(kMaxNumberOfBuffers, attributes.buffers)
238 : kDefaultNumberOfBuffers;
239 audio_sink_.Configure(buffers);
241 context->reply_msg = PpapiPluginMsg_MediaStreamAudioTrack_ConfigureReply();
242 return PP_OK;
245 void PepperMediaStreamAudioTrackHost::OnClose() {
246 if (connected_) {
247 MediaStreamAudioSink::RemoveFromAudioTrack(&audio_sink_, track_);
248 connected_ = false;
252 void PepperMediaStreamAudioTrackHost::OnNewBufferEnqueued() {
253 int32_t index = buffer_manager()->DequeueBuffer();
254 DCHECK_GE(index, 0);
255 audio_sink_.EnqueueBuffer(index);
258 void PepperMediaStreamAudioTrackHost::DidConnectPendingHostToResource() {
259 if (!connected_) {
260 MediaStreamAudioSink::AddToAudioTrack(&audio_sink_, track_);
261 connected_ = true;
265 } // namespace content