OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 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. | |
4 | |
5 #include "base/bind.h" | |
6 #include "base/memory/shared_memory.h" | |
7 #include "base/numerics/safe_math.h" | |
8 #include "content/public/renderer/renderer_ppapi_host.h" | |
9 #include "content/renderer/pepper/host_globals.h" | |
10 #include "content/renderer/pepper/pepper_audio_encoder_host.h" | |
11 #include "content/renderer/render_thread_impl.h" | |
12 #include "media/base/bind_to_current_loop.h" | |
13 #include "ppapi/c/pp_codecs.h" | |
14 #include "ppapi/c/pp_errors.h" | |
15 #include "ppapi/host/dispatch_host_message.h" | |
16 #include "ppapi/host/ppapi_host.h" | |
17 #include "ppapi/proxy/ppapi_messages.h" | |
18 #include "ppapi/shared_impl/media_stream_buffer.h" | |
19 #include "third_party/opus/src/include/opus.h" | |
20 | |
21 using ppapi::proxy::SerializedHandle; | |
22 | |
23 namespace content { | |
24 | |
25 namespace { | |
26 | |
27 // Buffer up to 150ms (15 x 10ms per frame). | |
28 const uint32_t kDefaultNumberOfAudioBuffers = 15; | |
29 | |
30 // Class used to pass audio data between the different threads. | |
bbudge
2015/11/04 00:59:59
nit: s/the different//
llandwerlin-old
2015/11/04 14:44:27
Done.
| |
31 class AudioData { | |
32 public: | |
33 AudioData(const AudioData& other) : data(other.data), size(other.size) {} | |
34 AudioData(uint8_t* data, size_t size) : data(data), size(size) {} | |
35 ~AudioData() {} | |
36 | |
37 uint8_t* data; | |
38 size_t size; | |
39 }; | |
40 | |
41 using BitstreamBufferReadyCB = base::Callback<void(int32_t size)>; | |
42 | |
43 bool PP_HardwareAccelerationCompatible(bool accelerated, | |
44 PP_HardwareAcceleration requested) { | |
45 switch (requested) { | |
46 case PP_HARDWAREACCELERATION_ONLY: | |
47 return accelerated; | |
48 case PP_HARDWAREACCELERATION_NONE: | |
49 return !accelerated; | |
50 case PP_HARDWAREACCELERATION_WITHFALLBACK: | |
51 return true; | |
52 // No default case, to catch unhandled PP_HardwareAcceleration values. | |
53 } | |
54 return false; | |
55 } | |
56 | |
57 base::CheckedNumeric<size_t> GetAudioBufferSize( | |
58 const ppapi::proxy::PPB_AudioEncodeParameters& audio_parameters, | |
59 uint32_t number_of_samples) { | |
60 base::CheckedNumeric<size_t> buffer_size = number_of_samples; | |
61 buffer_size *= audio_parameters.channels; | |
62 buffer_size *= audio_parameters.input_sample_size; | |
63 | |
64 return buffer_size; | |
65 } | |
66 | |
67 AudioData GetAudioDataFromAudioBufferManager( | |
68 ppapi::MediaStreamBufferManager* buffer_manager, | |
69 uint32_t* buffer_id) { | |
70 DCHECK(buffer_manager->HasAvailableBuffer()); | |
71 int32_t id = buffer_manager->DequeueBuffer(); | |
72 ppapi::MediaStreamBuffer* buffer = buffer_manager->GetBufferPointer(id); | |
73 *buffer_id = id; | |
74 return AudioData(static_cast<uint8_t*>(buffer->audio.data), | |
75 buffer->audio.data_size); | |
76 } | |
77 | |
78 AudioData GetBitstreamDataFromAudioBufferManager( | |
bbudge
2015/11/04 00:59:59
s/GetBitstreamDataFromAudioBufferManager/GetBitstr
llandwerlin-old
2015/11/04 14:44:27
Done.
| |
79 ppapi::MediaStreamBufferManager* buffer_manager, | |
80 uint32_t* buffer_id) { | |
81 DCHECK(buffer_manager->HasAvailableBuffer()); | |
82 int32_t id = buffer_manager->DequeueBuffer(); | |
83 uint8_t* buffer = | |
84 reinterpret_cast<uint8_t*>(buffer_manager->GetBufferPointer(id)); | |
85 *buffer_id = id; | |
86 return AudioData(buffer, buffer_manager->buffer_size()); | |
87 } | |
88 | |
89 } // namespace | |
90 | |
91 // This class should be constructed, used, and destructed on the main | |
92 // (renderer) thread. | |
93 class PepperAudioEncoderHost::AudioEncoderImpl { | |
94 public: | |
95 // Callback used to signal encoded data. If |size| is negative, an error | |
96 // occured. | |
97 | |
98 AudioEncoderImpl(); | |
99 ~AudioEncoderImpl(); | |
100 | |
101 std::vector<PP_AudioProfileDescription> GetSupportedProfiles(); | |
102 bool Initialize(const ppapi::proxy::PPB_AudioEncodeParameters& parameters); | |
103 int32_t GetNumberOfSamplesPerFrame(); | |
104 void Encode(const AudioData& input, | |
105 const AudioData& output, | |
106 BitstreamBufferReadyCB callback); | |
107 void RequestBitrateChange(uint32_t bitrate); | |
108 | |
109 private: | |
110 void DoEncode(const AudioData& input, | |
111 const AudioData& output, | |
112 BitstreamBufferReadyCB callback); | |
113 void DoRequestBitrateChange(uint32_t bitrate); | |
114 void OnEncodeDone(BitstreamBufferReadyCB callback, int32_t output_size); | |
115 void Stop(base::WaitableEvent* event); | |
116 | |
117 // Task calling from/into PepperAudioEncoderHost. | |
118 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; | |
119 | |
120 // Task doing the encoding. | |
121 scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_; | |
122 | |
123 // Initialization parameters. | |
124 ppapi::proxy::PPB_AudioEncodeParameters parameters_; | |
125 | |
126 scoped_ptr<uint8[]> encoder_memory_; | |
127 OpusEncoder* opus_encoder_; | |
128 | |
129 DISALLOW_COPY_AND_ASSIGN(AudioEncoderImpl); | |
130 }; | |
131 | |
132 PepperAudioEncoderHost::AudioEncoderImpl::AudioEncoderImpl() | |
133 : main_task_runner_(base::ThreadTaskRunnerHandle::Get()), | |
134 media_task_runner_(RenderThreadImpl::current() | |
135 ->GetMediaThreadTaskRunner()) {} | |
136 | |
137 PepperAudioEncoderHost::AudioEncoderImpl::~AudioEncoderImpl() { | |
138 if (encoder_memory_) { | |
139 base::WaitableEvent event(false, false); | |
140 media_task_runner_->PostTask( | |
141 FROM_HERE, | |
142 base::Bind(&AudioEncoderImpl::Stop, base::Unretained(this), &event)); | |
143 event.Wait(); | |
144 } | |
145 } | |
146 | |
147 std::vector<PP_AudioProfileDescription> | |
148 PepperAudioEncoderHost::AudioEncoderImpl::GetSupportedProfiles() { | |
149 std::vector<PP_AudioProfileDescription> profiles; | |
150 static const uint32_t sampling_rates[] = {8000, 12000, 16000, 24000, 48000}; | |
151 | |
152 for (uint32_t i = 0; i < arraysize(sampling_rates); ++i) { | |
153 PP_AudioProfileDescription profile; | |
154 profile.profile = PP_AUDIOPROFILE_OPUS; | |
155 profile.max_channels = 2; | |
156 profile.sample_size = PP_AUDIOBUFFER_SAMPLESIZE_16_BITS; | |
157 profile.sample_rate = sampling_rates[i]; | |
158 profile.hardware_accelerated = PP_FALSE; | |
159 profiles.push_back(profile); | |
160 } | |
161 return profiles; | |
162 } | |
163 | |
164 bool PepperAudioEncoderHost::AudioEncoderImpl::Initialize( | |
165 const ppapi::proxy::PPB_AudioEncodeParameters& parameters) { | |
166 if (parameters.output_profile != PP_AUDIOPROFILE_OPUS) | |
167 return false; | |
168 | |
169 DCHECK(!encoder_memory_); | |
170 | |
171 int32_t encoder_size = opus_encoder_get_size(parameters.channels); | |
172 if (encoder_size < 1) | |
173 return false; | |
174 | |
175 encoder_memory_.reset(new uint8[encoder_size]); | |
176 opus_encoder_ = reinterpret_cast<OpusEncoder*>(encoder_memory_.get()); | |
177 | |
178 if (opus_encoder_init(opus_encoder_, parameters.input_sample_rate, | |
179 parameters.channels, OPUS_APPLICATION_AUDIO) != OPUS_OK) | |
180 return false; | |
181 | |
182 if (opus_encoder_ctl(opus_encoder_, | |
183 OPUS_SET_BITRATE(parameters.initial_bitrate <= 0 | |
184 ? OPUS_AUTO | |
185 : parameters.initial_bitrate)) != | |
186 OPUS_OK) | |
187 return false; | |
188 | |
189 parameters_ = parameters; | |
190 | |
191 return true; | |
192 } | |
193 | |
194 int32_t PepperAudioEncoderHost::AudioEncoderImpl::GetNumberOfSamplesPerFrame() { | |
195 // Opus supports 2.5, 5, 10, 20, 40 or 60ms audio frames. We take | |
196 // 10ms by default. | |
197 return parameters_.input_sample_rate / 100; | |
198 } | |
199 | |
200 void PepperAudioEncoderHost::AudioEncoderImpl::Encode( | |
201 const AudioData& input, | |
202 const AudioData& output, | |
203 BitstreamBufferReadyCB callback) { | |
204 media_task_runner_->PostTask( | |
205 FROM_HERE, | |
206 base::Bind(&AudioEncoderImpl::DoEncode, base::Unretained(this), input, | |
207 output, base::Bind(&AudioEncoderImpl::OnEncodeDone, | |
208 base::Unretained(this), callback))); | |
209 } | |
210 | |
211 void PepperAudioEncoderHost::AudioEncoderImpl::DoEncode( | |
212 const AudioData& input, | |
213 const AudioData& output, | |
214 BitstreamBufferReadyCB callback) { | |
215 int32_t result = opus_encode( | |
216 opus_encoder_, reinterpret_cast<opus_int16*>(input.data), | |
217 (input.size / parameters_.channels) / parameters_.input_sample_size, | |
218 output.data, output.size); | |
219 main_task_runner_->PostTask( | |
220 FROM_HERE, base::Bind(&AudioEncoderImpl::OnEncodeDone, | |
221 base::Unretained(this), callback, result)); | |
222 } | |
223 | |
224 void PepperAudioEncoderHost::AudioEncoderImpl::RequestBitrateChange( | |
225 uint32_t bitrate) { | |
226 media_task_runner_->PostTask( | |
227 FROM_HERE, base::Bind(&AudioEncoderImpl::RequestBitrateChange, | |
228 base::Unretained(this), bitrate)); | |
229 } | |
230 | |
231 void PepperAudioEncoderHost::AudioEncoderImpl::DoRequestBitrateChange( | |
232 uint32_t bitrate) { | |
233 opus_encoder_ctl(opus_encoder_, OPUS_SET_BITRATE(bitrate)); | |
234 } | |
235 | |
236 void PepperAudioEncoderHost::AudioEncoderImpl::OnEncodeDone( | |
237 BitstreamBufferReadyCB callback, | |
238 int32_t size) { | |
239 callback.Run(size); | |
240 } | |
241 | |
242 void PepperAudioEncoderHost::AudioEncoderImpl::Stop( | |
243 base::WaitableEvent* event) { | |
244 event->Signal(); | |
245 } | |
246 | |
247 PepperAudioEncoderHost::PepperAudioEncoderHost(RendererPpapiHost* host, | |
248 PP_Instance instance, | |
249 PP_Resource resource) | |
250 : ResourceHost(host->GetPpapiHost(), instance, resource), | |
251 renderer_ppapi_host_(host), | |
252 initialized_(false), | |
253 encoder_last_error_(PP_ERROR_FAILED), | |
254 audio_buffer_manager_(this), | |
255 bitstream_buffer_manager_(this) {} | |
256 | |
257 PepperAudioEncoderHost::~PepperAudioEncoderHost() { | |
258 Close(); | |
259 } | |
260 | |
261 int32_t PepperAudioEncoderHost::OnResourceMessageReceived( | |
262 const IPC::Message& msg, | |
263 ppapi::host::HostMessageContext* context) { | |
264 PPAPI_BEGIN_MESSAGE_MAP(PepperAudioEncoderHost, msg) | |
265 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0( | |
266 PpapiHostMsg_AudioEncoder_GetSupportedProfiles, | |
267 OnHostMsgGetSupportedProfiles) | |
268 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_AudioEncoder_Initialize, | |
269 OnHostMsgInitialize) | |
270 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0( | |
271 PpapiHostMsg_AudioEncoder_GetAudioBuffers, OnHostMsgGetAudioBuffers) | |
272 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_AudioEncoder_Encode, | |
273 OnHostMsgEncode) | |
274 PPAPI_DISPATCH_HOST_RESOURCE_CALL( | |
275 PpapiHostMsg_AudioEncoder_RecycleBitstreamBuffer, | |
276 OnHostMsgRecycleBitstreamBuffer) | |
277 PPAPI_DISPATCH_HOST_RESOURCE_CALL( | |
278 PpapiHostMsg_AudioEncoder_RequestBitrateChange, | |
279 OnHostMsgRequestBitrateChange) | |
280 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_AudioEncoder_Close, | |
281 OnHostMsgClose) | |
282 PPAPI_END_MESSAGE_MAP() | |
283 return PP_ERROR_FAILED; | |
284 } | |
285 | |
286 int32_t PepperAudioEncoderHost::OnHostMsgGetSupportedProfiles( | |
287 ppapi::host::HostMessageContext* context) { | |
288 std::vector<PP_AudioProfileDescription> profiles; | |
289 GetSupportedProfiles(&profiles); | |
290 | |
291 host()->SendReply( | |
292 context->MakeReplyMessageContext(), | |
293 PpapiPluginMsg_AudioEncoder_GetSupportedProfilesReply(profiles)); | |
294 | |
295 return PP_OK_COMPLETIONPENDING; | |
296 } | |
297 | |
298 int32_t PepperAudioEncoderHost::OnHostMsgInitialize( | |
299 ppapi::host::HostMessageContext* context, | |
300 const ppapi::proxy::PPB_AudioEncodeParameters& parameters) { | |
301 if (initialized_) | |
302 return PP_ERROR_FAILED; | |
303 | |
304 if (!IsInitializationValid(parameters)) | |
305 return PP_ERROR_NOTSUPPORTED; | |
306 | |
307 encode_parameters_ = parameters; | |
308 | |
309 int32_t error = PP_ERROR_FAILED; | |
310 if (parameters.acceleration == PP_HARDWAREACCELERATION_NONE || | |
311 parameters.acceleration == PP_HARDWAREACCELERATION_WITHFALLBACK) { | |
312 encoder_.reset(new AudioEncoderImpl); | |
313 if (encoder_->Initialize(parameters)) { | |
bbudge
2015/11/04 00:59:59
It's unfortunate that you validate 'parameters' af
llandwerlin-old
2015/11/04 14:44:27
The parameters are validated above line 304, those
bbudge
2015/11/10 00:08:25
OK, I missed that the parameters have to match a s
| |
314 base::CheckedNumeric<size_t> bitstream_buffer_size = GetAudioBufferSize( | |
315 parameters, encoder_->GetNumberOfSamplesPerFrame()); | |
316 bitstream_buffer_size *= 2; | |
317 if (bitstream_buffer_size.IsValid() && | |
318 AllocateBitstreamBuffers(bitstream_buffer_size.ValueOrDie())) { | |
319 initialized_ = true; | |
320 encoder_last_error_ = PP_OK; | |
321 | |
322 ppapi::host::ReplyMessageContext reply_context = | |
323 context->MakeReplyMessageContext(); | |
324 reply_context.params.AppendHandle(SerializedHandle( | |
325 renderer_ppapi_host_->ShareSharedMemoryHandleWithRemote( | |
326 bitstream_buffer_manager_.shm()->handle()), | |
327 bitstream_buffer_manager_.shm()->mapped_size())); | |
328 host()->SendReply(reply_context, | |
329 PpapiPluginMsg_AudioEncoder_InitializeReply( | |
330 encoder_->GetNumberOfSamplesPerFrame(), | |
331 bitstream_buffer_manager_.number_of_buffers(), | |
332 bitstream_buffer_manager_.buffer_size())); | |
333 | |
334 return PP_OK_COMPLETIONPENDING; | |
335 } | |
336 error = PP_ERROR_NOMEMORY; | |
337 } else | |
338 error = PP_ERROR_FAILED; | |
339 } | |
340 | |
341 encoder_ = nullptr; | |
342 | |
343 return error; | |
344 } | |
345 | |
346 int32_t PepperAudioEncoderHost::OnHostMsgGetAudioBuffers( | |
347 ppapi::host::HostMessageContext* context) { | |
348 if (encoder_last_error_) | |
349 return encoder_last_error_; | |
350 | |
bbudge
2015/11/04 00:59:59
You should probably detect when this has been call
llandwerlin-old
2015/11/04 14:44:27
Done.
| |
351 if (!AllocateAudioBuffers(encoder_->GetNumberOfSamplesPerFrame())) | |
352 return PP_ERROR_NOMEMORY; | |
353 | |
354 ppapi::host::ReplyMessageContext reply_context = | |
355 context->MakeReplyMessageContext(); | |
356 reply_context.params.AppendHandle( | |
357 SerializedHandle(renderer_ppapi_host_->ShareSharedMemoryHandleWithRemote( | |
358 audio_buffer_manager_.shm()->handle()), | |
359 audio_buffer_manager_.shm()->mapped_size())); | |
360 | |
361 host()->SendReply(reply_context, | |
362 PpapiPluginMsg_AudioEncoder_GetAudioBuffersReply( | |
363 audio_buffer_manager_.number_of_buffers(), | |
364 audio_buffer_manager_.buffer_size())); | |
365 | |
366 return PP_OK_COMPLETIONPENDING; | |
367 } | |
368 | |
369 int32_t PepperAudioEncoderHost::OnHostMsgEncode( | |
370 ppapi::host::HostMessageContext* context, | |
371 uint32_t buffer_id) { | |
372 if (encoder_last_error_) | |
373 return encoder_last_error_; | |
374 | |
375 if (buffer_id >= | |
376 static_cast<uint32_t>(audio_buffer_manager_.number_of_buffers())) | |
377 return PP_ERROR_BADARGUMENT; | |
378 | |
379 audio_buffer_manager_.EnqueueBuffer(buffer_id); | |
380 | |
381 DoEncode(); | |
382 | |
383 return PP_OK_COMPLETIONPENDING; | |
384 } | |
385 | |
386 int32_t PepperAudioEncoderHost::OnHostMsgRecycleBitstreamBuffer( | |
387 ppapi::host::HostMessageContext* context, | |
388 uint32_t buffer_id) { | |
389 if (encoder_last_error_) | |
390 return encoder_last_error_; | |
391 | |
392 if (buffer_id >= | |
393 static_cast<uint32_t>(bitstream_buffer_manager_.number_of_buffers())) | |
394 return PP_ERROR_BADARGUMENT; | |
395 | |
396 bitstream_buffer_manager_.EnqueueBuffer(buffer_id); | |
397 | |
398 DoEncode(); | |
399 | |
400 return PP_OK; | |
401 } | |
402 | |
403 int32_t PepperAudioEncoderHost::OnHostMsgRequestBitrateChange( | |
404 ppapi::host::HostMessageContext* context, | |
405 uint32_t bitrate) { | |
406 if (encoder_last_error_) | |
407 return encoder_last_error_; | |
408 | |
409 encoder_->RequestBitrateChange(bitrate); | |
410 | |
411 return PP_OK; | |
412 } | |
413 | |
414 int32_t PepperAudioEncoderHost::OnHostMsgClose( | |
415 ppapi::host::HostMessageContext* context) { | |
416 encoder_last_error_ = PP_ERROR_FAILED; | |
417 Close(); | |
418 | |
419 return PP_OK; | |
420 } | |
421 | |
422 void PepperAudioEncoderHost::GetSupportedProfiles( | |
423 std::vector<PP_AudioProfileDescription>* profiles) { | |
424 DCHECK(RenderThreadImpl::current()); | |
425 | |
426 AudioEncoderImpl software_encoder; | |
427 *profiles = software_encoder.GetSupportedProfiles(); | |
428 } | |
429 | |
430 bool PepperAudioEncoderHost::IsInitializationValid( | |
431 const ppapi::proxy::PPB_AudioEncodeParameters& parameters) { | |
432 DCHECK(RenderThreadImpl::current()); | |
433 | |
434 std::vector<PP_AudioProfileDescription> profiles; | |
435 GetSupportedProfiles(&profiles); | |
436 | |
437 for (const PP_AudioProfileDescription& profile : profiles) { | |
438 if (parameters.output_profile == profile.profile && | |
439 parameters.input_sample_size == profile.sample_size && | |
440 parameters.input_sample_rate == profile.sample_rate && | |
441 parameters.channels <= profile.max_channels && | |
442 PP_HardwareAccelerationCompatible( | |
443 profile.hardware_accelerated == PP_TRUE ? true : false, | |
444 parameters.acceleration)) | |
445 return true; | |
446 } | |
447 | |
448 return false; | |
449 } | |
450 | |
451 bool PepperAudioEncoderHost::AllocateAudioBuffers(uint32_t number_of_samples) { | |
452 DCHECK(RenderThreadImpl::current()); | |
453 DCHECK(initialized_); | |
454 | |
455 // Buffers have already been allocated. | |
456 if (audio_buffer_manager_.number_of_buffers() > 0) | |
457 return false; | |
bbudge
2015/11/04 00:59:59
remove this check (see comment at call site above.
llandwerlin-old
2015/11/04 14:44:27
Done.
| |
458 | |
459 base::CheckedNumeric<size_t> buffer_size = | |
460 GetAudioBufferSize(encode_parameters_, number_of_samples); | |
461 if (!buffer_size.IsValid()) | |
462 return false; | |
463 | |
464 base::CheckedNumeric<size_t> total_buffer_size = buffer_size.ValueOrDie(); | |
465 total_buffer_size += sizeof(ppapi::MediaStreamBuffer::Audio); | |
466 if (!total_buffer_size.IsValid()) | |
467 return false; | |
468 | |
469 base::CheckedNumeric<size_t> total_memory_size = | |
470 total_buffer_size.ValueOrDie(); | |
471 total_memory_size *= kDefaultNumberOfAudioBuffers; | |
472 if (!total_memory_size.IsValid()) | |
473 return false; | |
474 | |
475 if (!audio_buffer_manager_.SetBuffers( | |
476 kDefaultNumberOfAudioBuffers, total_buffer_size.ValueOrDie(), | |
477 RenderThreadImpl::current() | |
478 ->HostAllocateSharedMemoryBuffer(total_memory_size.ValueOrDie()) | |
479 .Pass(), | |
480 false)) | |
481 return false; | |
482 | |
483 for (int32_t i = 0; i < audio_buffer_manager_.number_of_buffers(); ++i) { | |
484 ppapi::MediaStreamBuffer::Audio* buffer = | |
485 &(audio_buffer_manager_.GetBufferPointer(i)->audio); | |
486 buffer->header.size = total_buffer_size.ValueOrDie(); | |
487 buffer->header.type = ppapi::MediaStreamBuffer::TYPE_AUDIO; | |
488 buffer->sample_rate = static_cast<PP_AudioBuffer_SampleRate>( | |
489 encode_parameters_.input_sample_rate); | |
490 buffer->number_of_channels = encode_parameters_.channels; | |
491 buffer->number_of_samples = number_of_samples; | |
492 buffer->data_size = buffer_size.ValueOrDie(); | |
493 } | |
494 | |
495 return true; | |
496 } | |
497 | |
498 bool PepperAudioEncoderHost::AllocateBitstreamBuffers(size_t buffer_size) { | |
bbudge
2015/11/04 00:59:59
If you follow some of my other suggestions for the
| |
499 DCHECK(RenderThreadImpl::current()); | |
500 // We assume AllocateBitstreamBuffers is only called once. | |
501 DCHECK(!initialized_); | |
502 | |
503 // Buffers have already been allocated. | |
504 if (bitstream_buffer_manager_.number_of_buffers() > 0) | |
505 return false; | |
506 | |
507 base::CheckedNumeric<size_t> total_size = buffer_size; | |
508 total_size *= kDefaultNumberOfAudioBuffers; | |
509 if (!total_size.IsValid()) | |
510 return false; | |
511 | |
512 if (!bitstream_buffer_manager_.SetBuffers( | |
513 kDefaultNumberOfAudioBuffers, buffer_size, | |
514 RenderThreadImpl::current() | |
515 ->HostAllocateSharedMemoryBuffer(total_size.ValueOrDie()) | |
516 .Pass(), | |
517 true)) | |
518 return false; | |
519 | |
520 return true; | |
521 } | |
522 | |
523 void PepperAudioEncoderHost::DoEncode() { | |
524 if (!audio_buffer_manager_.HasAvailableBuffer() || | |
525 !bitstream_buffer_manager_.HasAvailableBuffer()) | |
526 return; | |
527 | |
528 uint32_t audio_buffer_id, bitstream_buffer_id; | |
529 AudioData input(GetAudioDataFromAudioBufferManager(&audio_buffer_manager_, | |
530 &audio_buffer_id)); | |
531 AudioData output(GetBitstreamDataFromAudioBufferManager( | |
532 &bitstream_buffer_manager_, &bitstream_buffer_id)); | |
533 encoder_->Encode( | |
534 input, output, | |
535 base::Bind(&PepperAudioEncoderHost::BitstreamBufferReady, | |
536 base::Unretained(this), audio_buffer_id, bitstream_buffer_id)); | |
537 } | |
538 | |
539 void PepperAudioEncoderHost::BitstreamBufferReady(uint32_t audio_buffer_id, | |
540 uint32_t bitstream_buffer_id, | |
541 int32_t size) { | |
542 DCHECK(RenderThreadImpl::current()); | |
543 | |
544 if (encoder_last_error_) | |
545 return; | |
546 | |
547 host()->SendUnsolicitedReply( | |
548 pp_resource(), PpapiPluginMsg_AudioEncoder_EncodeReply(audio_buffer_id)); | |
549 | |
550 if (size < 0) { | |
551 NotifyPepperError(PP_ERROR_FAILED); | |
552 return; | |
553 } | |
554 | |
555 host()->SendUnsolicitedReply( | |
556 pp_resource(), PpapiPluginMsg_AudioEncoder_BitstreamBufferReady( | |
557 bitstream_buffer_id, static_cast<uint32_t>(size))); | |
558 } | |
559 | |
560 void PepperAudioEncoderHost::NotifyPepperError(int32_t error) { | |
561 DCHECK(RenderThreadImpl::current()); | |
562 | |
563 encoder_last_error_ = error; | |
564 Close(); | |
565 host()->SendUnsolicitedReply( | |
566 pp_resource(), | |
567 PpapiPluginMsg_AudioEncoder_NotifyError(encoder_last_error_)); | |
568 } | |
569 | |
570 void PepperAudioEncoderHost::Close() { | |
571 DCHECK(RenderThreadImpl::current()); | |
572 | |
573 encoder_ = nullptr; | |
574 } | |
575 | |
576 } // namespace content | |
OLD | NEW |