Chromium Code Reviews| 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/audio_encoder_shim.h" | |
| 10 #include "content/renderer/pepper/host_globals.h" | |
| 11 #include "content/renderer/pepper/pepper_audio_encoder_host.h" | |
| 12 #include "content/renderer/render_thread_impl.h" | |
| 13 #include "media/base/bind_to_current_loop.h" | |
| 14 #include "ppapi/c/pp_codecs.h" | |
| 15 #include "ppapi/c/pp_errors.h" | |
| 16 #include "ppapi/host/dispatch_host_message.h" | |
| 17 #include "ppapi/host/ppapi_host.h" | |
| 18 #include "ppapi/proxy/ppapi_messages.h" | |
| 19 #include "ppapi/shared_impl/media_stream_buffer.h" | |
| 20 | |
| 21 using ppapi::proxy::SerializedHandle; | |
| 22 | |
| 23 namespace content { | |
| 24 | |
| 25 namespace { | |
| 26 | |
| 27 // Number of input audio buffers (150ms at 10ms per frame). | |
| 28 const uint32_t kDefaultNumberOfAudioFrames = 15; | |
| 29 | |
| 30 // Number of bitstream buffers. | |
| 31 const uint32_t kDefaultNumberOfBitstreamBuffers = 8; | |
| 32 | |
| 33 // Default bitstream buffers size. | |
| 34 // TODO(llandwerlin): Would having this a multiple of the audio frame | |
| 35 // size would make more sense? | |
| 36 const size_t kDefaultBitstreamBufferSize = 100000; | |
| 37 | |
| 38 bool PP_HardwareAccelerationCompatible(bool accelerated, | |
| 39 PP_HardwareAcceleration requested) { | |
| 40 switch (requested) { | |
| 41 case PP_HARDWAREACCELERATION_ONLY: | |
| 42 return accelerated; | |
| 43 case PP_HARDWAREACCELERATION_NONE: | |
| 44 return !accelerated; | |
| 45 case PP_HARDWAREACCELERATION_WITHFALLBACK: | |
| 46 return true; | |
| 47 // No default case, to catch unhandled PP_HardwareAcceleration values. | |
| 48 } | |
| 49 return false; | |
| 50 } | |
| 51 | |
| 52 } // namespace | |
| 53 | |
| 54 class PepperAudioEncoderHost::BufferManager | |
| 55 : public base::RefCountedThreadSafe<BufferManager> { | |
| 56 public: | |
| 57 uint32_t number_of_buffers() const { return number_of_buffers_; } | |
| 58 size_t buffer_size() const { return buffer_size_; } | |
| 59 | |
| 60 virtual bool Initialize(uint32_t number_of_buffers, size_t buffer_size) { | |
| 61 number_of_buffers_ = number_of_buffers; | |
| 62 buffer_size_ = buffer_size; | |
| 63 return true; | |
| 64 } | |
| 65 | |
| 66 virtual uint8_t* GetBuffer(uint32_t id) = 0; | |
| 67 virtual base::SharedMemory* GetSharedMemory() = 0; | |
| 68 | |
| 69 uint32_t DequeueBuffer() { | |
| 70 DCHECK(!enqueued_buffers_.empty()); | |
| 71 uint32_t id = enqueued_buffers_.front(); | |
| 72 enqueued_buffers_.pop_front(); | |
| 73 buffers_.erase(id); | |
| 74 return id; | |
| 75 } | |
| 76 void EnqueueBuffer(uint32_t id) { | |
| 77 DCHECK(!IsBufferQueued(id)); | |
| 78 enqueued_buffers_.push_back(id); | |
| 79 buffers_.insert(id); | |
| 80 } | |
| 81 bool HasAvailableBuffer() { return !enqueued_buffers_.empty(); } | |
| 82 bool IsBufferQueued(uint32_t id) { | |
| 83 return buffers_.find(id) != buffers_.end(); | |
| 84 } | |
| 85 | |
| 86 protected: | |
| 87 friend class base::RefCountedThreadSafe<BufferManager>; | |
| 88 BufferManager() : number_of_buffers_(0), buffer_size_(0) {} | |
| 89 virtual ~BufferManager() {} | |
| 90 | |
| 91 private: | |
| 92 uint32_t number_of_buffers_; | |
| 93 size_t buffer_size_; | |
| 94 std::deque<uint32_t> enqueued_buffers_; | |
| 95 std::set<uint32_t> buffers_; | |
| 96 | |
| 97 DISALLOW_COPY_AND_ASSIGN(BufferManager); | |
| 98 }; | |
| 99 | |
| 100 class PepperAudioEncoderHost::PcmBufferManager : public BufferManager { | |
| 101 public: | |
| 102 PcmBufferManager(const ppapi::proxy::PPB_AudioEncodeParameters& parameters, | |
| 103 uint32_t number_of_samples) | |
| 104 : encode_parameters_(parameters), | |
| 105 number_of_samples_(number_of_samples), | |
| 106 total_buffer_size_(0) {} | |
| 107 | |
| 108 private: | |
| 109 ~PcmBufferManager() override {} | |
| 110 | |
| 111 // PepperAudioEncoderHost::BufferManager: | |
| 112 bool Initialize(uint32_t number_of_buffers, size_t buffer_size) override { | |
| 113 base::CheckedNumeric<size_t> total_buffer_size = | |
| 114 buffer_size + sizeof(ppapi::MediaStreamBuffer::Audio); | |
| 115 total_buffer_size_ = total_buffer_size.ValueOrDie(); | |
| 116 base::CheckedNumeric<size_t> total_memory_size = total_buffer_size_; | |
| 117 total_memory_size *= number_of_buffers; | |
| 118 shm_ = RenderThreadImpl::current() | |
|
Tom Sepez
2015/10/05 16:54:16
you might want to call IsValid() and return false
llandwerlin-old
2015/10/05 17:16:31
Done.
| |
| 119 ->HostAllocateSharedMemoryBuffer(total_memory_size.ValueOrDie()) | |
| 120 .Pass(); | |
| 121 if (!shm_ || !shm_->Map(total_memory_size.ValueOrDie())) | |
| 122 return false; | |
| 123 | |
| 124 for (uint32_t i = 0; i < number_of_buffers; ++i) { | |
| 125 uint8_t* mem = | |
| 126 static_cast<uint8_t*>(shm_->memory()) + total_buffer_size_ * i; | |
| 127 ppapi::MediaStreamBuffer::Audio* buffer = | |
| 128 reinterpret_cast<ppapi::MediaStreamBuffer::Audio*>(mem); | |
| 129 buffer->header.size = total_buffer_size_; | |
| 130 buffer->header.type = ppapi::MediaStreamBuffer::TYPE_AUDIO; | |
| 131 buffer->sample_rate = static_cast<PP_AudioBuffer_SampleRate>( | |
| 132 encode_parameters_.input_sample_rate); | |
| 133 buffer->number_of_channels = encode_parameters_.channels; | |
| 134 buffer->number_of_samples = number_of_samples_; | |
| 135 buffer->data_size = buffer_size; | |
| 136 } | |
| 137 | |
| 138 return BufferManager::Initialize(number_of_buffers, buffer_size); | |
| 139 } | |
| 140 uint8_t* GetBuffer(uint32_t id) override { | |
| 141 if (id >= number_of_buffers()) | |
| 142 return nullptr; | |
| 143 uint8_t* mem = | |
| 144 static_cast<uint8_t*>(shm_->memory()) + total_buffer_size_ * id; | |
| 145 return static_cast<uint8_t*>( | |
| 146 reinterpret_cast<ppapi::MediaStreamBuffer::Audio*>(mem)->data); | |
| 147 } | |
| 148 base::SharedMemory* GetSharedMemory() override { return shm_.get(); } | |
| 149 | |
| 150 scoped_ptr<base::SharedMemory> shm_; | |
| 151 ppapi::proxy::PPB_AudioEncodeParameters encode_parameters_; | |
| 152 uint32_t number_of_samples_; | |
| 153 size_t total_buffer_size_; | |
| 154 }; | |
| 155 | |
| 156 class PepperAudioEncoderHost::BitstreamBufferManager : public BufferManager { | |
| 157 public: | |
| 158 BitstreamBufferManager() {} | |
| 159 | |
| 160 private: | |
| 161 ~BitstreamBufferManager() override {} | |
| 162 | |
| 163 // PepperAudioEncoderHost::BufferManager: | |
| 164 bool Initialize(uint32_t number_of_buffers, size_t buffer_size) override { | |
| 165 base::CheckedNumeric<size_t> total_size = number_of_buffers * buffer_size; | |
|
Tom Sepez
2015/10/05 16:54:16
need to assign first, then multiply as you did abo
llandwerlin-old
2015/10/05 17:16:31
Sorry, missed this one.
| |
| 166 shm_ = RenderThreadImpl::current() | |
| 167 ->HostAllocateSharedMemoryBuffer(total_size.ValueOrDie()) | |
| 168 .Pass(); | |
| 169 if (!shm_ || !shm_->Map(total_size.ValueOrDie())) | |
| 170 return false; | |
| 171 | |
| 172 for (uint32_t i = 0; i < number_of_buffers; ++i) | |
| 173 EnqueueBuffer(i); | |
| 174 | |
| 175 return BufferManager::Initialize(number_of_buffers, buffer_size); | |
| 176 } | |
| 177 uint8_t* GetBuffer(uint32_t id) override { | |
| 178 if (id >= number_of_buffers()) | |
| 179 return nullptr; | |
| 180 return static_cast<uint8_t*>(shm_->memory()) + (id * buffer_size()); | |
| 181 } | |
| 182 base::SharedMemory* GetSharedMemory() override { return shm_.get(); } | |
| 183 | |
| 184 scoped_ptr<base::SharedMemory> shm_; | |
| 185 }; | |
| 186 | |
| 187 class PepperAudioEncoderHost::AudioData : public AudioEncoderShim::AudioData { | |
| 188 public: | |
| 189 AudioData(int32_t id, const scoped_refptr<BufferManager>& buffer_manager) | |
| 190 : id_(id), buffer_manager_(buffer_manager) {} | |
| 191 | |
| 192 int32_t id() const { return id_; } | |
| 193 | |
| 194 private: | |
| 195 ~AudioData() override {} | |
| 196 | |
| 197 // AudioEncoderShim::AudioData: | |
| 198 uint8_t* GetData() override { return buffer_manager_->GetBuffer(id_); } | |
| 199 size_t GetSize() override { return buffer_manager_->buffer_size(); } | |
| 200 | |
| 201 int32_t id_; | |
| 202 scoped_refptr<BufferManager> buffer_manager_; | |
| 203 | |
| 204 DISALLOW_COPY_AND_ASSIGN(AudioData); | |
| 205 }; | |
| 206 | |
| 207 PepperAudioEncoderHost::PepperAudioEncoderHost(RendererPpapiHost* host, | |
| 208 PP_Instance instance, | |
| 209 PP_Resource resource) | |
| 210 : ResourceHost(host->GetPpapiHost(), instance, resource), | |
| 211 renderer_ppapi_host_(host), | |
| 212 initialized_(false), | |
| 213 encoder_last_error_(PP_ERROR_FAILED), | |
| 214 weak_ptr_factory_(this) {} | |
| 215 | |
| 216 PepperAudioEncoderHost::~PepperAudioEncoderHost() { | |
| 217 Close(); | |
| 218 } | |
| 219 | |
| 220 int32_t PepperAudioEncoderHost::OnResourceMessageReceived( | |
| 221 const IPC::Message& msg, | |
| 222 ppapi::host::HostMessageContext* context) { | |
| 223 PPAPI_BEGIN_MESSAGE_MAP(PepperAudioEncoderHost, msg) | |
| 224 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0( | |
| 225 PpapiHostMsg_AudioEncoder_GetSupportedProfiles, | |
| 226 OnHostMsgGetSupportedProfiles) | |
| 227 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_AudioEncoder_Initialize, | |
| 228 OnHostMsgInitialize) | |
| 229 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0( | |
| 230 PpapiHostMsg_AudioEncoder_GetAudioFrames, OnHostMsgGetAudioFrames) | |
| 231 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_AudioEncoder_Encode, | |
| 232 OnHostMsgEncode) | |
| 233 PPAPI_DISPATCH_HOST_RESOURCE_CALL( | |
| 234 PpapiHostMsg_AudioEncoder_RecycleBitstreamBuffer, | |
| 235 OnHostMsgRecycleBitstreamBuffer) | |
| 236 PPAPI_DISPATCH_HOST_RESOURCE_CALL( | |
| 237 PpapiHostMsg_AudioEncoder_RequestBitrateChange, | |
| 238 OnHostMsgRequestBitrateChange) | |
| 239 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_AudioEncoder_Close, | |
| 240 OnHostMsgClose) | |
| 241 PPAPI_END_MESSAGE_MAP() | |
| 242 return PP_ERROR_FAILED; | |
| 243 } | |
| 244 | |
| 245 int32_t PepperAudioEncoderHost::OnHostMsgGetSupportedProfiles( | |
| 246 ppapi::host::HostMessageContext* context) { | |
| 247 std::vector<PP_AudioProfileDescription> profiles; | |
| 248 GetSupportedProfiles(&profiles); | |
| 249 | |
| 250 host()->SendReply( | |
| 251 context->MakeReplyMessageContext(), | |
| 252 PpapiPluginMsg_AudioEncoder_GetSupportedProfilesReply(profiles)); | |
| 253 | |
| 254 return PP_OK_COMPLETIONPENDING; | |
| 255 } | |
| 256 | |
| 257 int32_t PepperAudioEncoderHost::OnHostMsgInitialize( | |
| 258 ppapi::host::HostMessageContext* context, | |
| 259 const ppapi::proxy::PPB_AudioEncodeParameters& parameters) { | |
| 260 if (initialized_) | |
| 261 return PP_ERROR_FAILED; | |
| 262 | |
| 263 if (!IsInitializationValid(parameters)) | |
| 264 return PP_ERROR_NOTSUPPORTED; | |
| 265 | |
| 266 encode_parameters_ = parameters; | |
| 267 initialize_reply_context_ = context->MakeReplyMessageContext(); | |
| 268 | |
| 269 int32_t error = PP_ERROR_FAILED; | |
| 270 if (parameters.acceleration == PP_HARDWAREACCELERATION_NONE || | |
| 271 parameters.acceleration == PP_HARDWAREACCELERATION_WITHFALLBACK) { | |
| 272 encoder_.reset(new AudioEncoderShim); | |
| 273 if (encoder_->Initialize(parameters)) { | |
| 274 if (AllocateBitstreamBuffers(kDefaultBitstreamBufferSize)) { | |
| 275 encoder_last_error_ = PP_OK; | |
| 276 return PP_OK_COMPLETIONPENDING; | |
| 277 } | |
| 278 error = PP_ERROR_NOMEMORY; | |
| 279 } else | |
| 280 error = PP_ERROR_FAILED; | |
| 281 } | |
| 282 | |
| 283 initialize_reply_context_ = ppapi::host::ReplyMessageContext(); | |
| 284 encoder_ = nullptr; | |
| 285 | |
| 286 return error; | |
| 287 } | |
| 288 | |
| 289 int32_t PepperAudioEncoderHost::OnHostMsgGetAudioFrames( | |
| 290 ppapi::host::HostMessageContext* context) { | |
| 291 if (encoder_last_error_) | |
| 292 return encoder_last_error_; | |
| 293 | |
| 294 get_audio_frames_reply_context_ = context->MakeReplyMessageContext(); | |
| 295 if (!AllocateAudioFrames(encoder_->GetNumberOfSamplesPerFrame())) | |
| 296 return PP_ERROR_NOMEMORY; | |
| 297 | |
| 298 return PP_OK_COMPLETIONPENDING; | |
| 299 } | |
| 300 | |
| 301 int32_t PepperAudioEncoderHost::OnHostMsgEncode( | |
| 302 ppapi::host::HostMessageContext* context, | |
| 303 uint32_t buffer_id) { | |
| 304 if (encoder_last_error_) | |
| 305 return encoder_last_error_; | |
| 306 | |
| 307 if (buffer_id >= audio_buffer_manager_->number_of_buffers() || | |
| 308 audio_buffer_manager_->IsBufferQueued(buffer_id)) | |
| 309 return PP_ERROR_BADARGUMENT; | |
| 310 | |
| 311 audio_buffer_manager_->EnqueueBuffer(buffer_id); | |
| 312 | |
| 313 DoEncode(); | |
| 314 | |
| 315 return PP_OK_COMPLETIONPENDING; | |
| 316 } | |
| 317 | |
| 318 int32_t PepperAudioEncoderHost::OnHostMsgRecycleBitstreamBuffer( | |
| 319 ppapi::host::HostMessageContext* context, | |
| 320 uint32_t buffer_id) { | |
| 321 if (encoder_last_error_) | |
| 322 return encoder_last_error_; | |
| 323 | |
| 324 if (buffer_id >= bitstream_buffer_manager_->number_of_buffers() || | |
| 325 bitstream_buffer_manager_->IsBufferQueued(buffer_id)) | |
| 326 return PP_ERROR_BADARGUMENT; | |
| 327 | |
| 328 bitstream_buffer_manager_->EnqueueBuffer(buffer_id); | |
| 329 | |
| 330 DoEncode(); | |
| 331 | |
| 332 return PP_OK; | |
| 333 } | |
| 334 | |
| 335 int32_t PepperAudioEncoderHost::OnHostMsgRequestBitrateChange( | |
| 336 ppapi::host::HostMessageContext* context, | |
| 337 uint32_t bitrate) { | |
| 338 if (encoder_last_error_) | |
| 339 return encoder_last_error_; | |
| 340 | |
| 341 encoder_->RequestBitrateChange(bitrate); | |
| 342 | |
| 343 return PP_OK; | |
| 344 } | |
| 345 | |
| 346 int32_t PepperAudioEncoderHost::OnHostMsgClose( | |
| 347 ppapi::host::HostMessageContext* context) { | |
| 348 encoder_last_error_ = PP_ERROR_FAILED; | |
| 349 Close(); | |
| 350 | |
| 351 return PP_OK; | |
| 352 } | |
| 353 | |
| 354 void PepperAudioEncoderHost::GetSupportedProfiles( | |
| 355 std::vector<PP_AudioProfileDescription>* profiles) { | |
| 356 DCHECK(RenderThreadImpl::current()); | |
| 357 | |
| 358 AudioEncoderShim software_encoder; | |
| 359 *profiles = software_encoder.GetSupportedProfiles(); | |
| 360 } | |
| 361 | |
| 362 bool PepperAudioEncoderHost::IsInitializationValid( | |
| 363 const ppapi::proxy::PPB_AudioEncodeParameters& parameters) { | |
| 364 DCHECK(RenderThreadImpl::current()); | |
| 365 | |
| 366 std::vector<PP_AudioProfileDescription> profiles; | |
| 367 GetSupportedProfiles(&profiles); | |
| 368 | |
| 369 for (const PP_AudioProfileDescription& profile : profiles) { | |
| 370 if (parameters.output_profile == profile.profile && | |
| 371 parameters.input_sample_size == profile.sample_size && | |
| 372 parameters.input_sample_rate == profile.sample_rate && | |
| 373 parameters.channels <= profile.max_channels && | |
| 374 PP_HardwareAccelerationCompatible( | |
| 375 profile.hardware_accelerated == PP_TRUE ? true : false, | |
| 376 parameters.acceleration)) | |
| 377 return true; | |
| 378 } | |
| 379 | |
| 380 return false; | |
| 381 } | |
| 382 | |
| 383 bool PepperAudioEncoderHost::AllocateAudioFrames(uint32_t number_of_samples) { | |
| 384 DCHECK(RenderThreadImpl::current()); | |
| 385 DCHECK(initialized_); | |
| 386 DCHECK(get_audio_frames_reply_context_.is_valid()); | |
| 387 | |
| 388 // Frames have already been allocated. | |
| 389 if (audio_buffer_manager_) | |
| 390 return false; | |
| 391 | |
| 392 scoped_refptr<BufferManager> buffer_manager( | |
| 393 new PcmBufferManager(encode_parameters_, number_of_samples)); | |
| 394 base::CheckedNumeric<size_t> buffer_size = number_of_samples; | |
| 395 buffer_size *= | |
| 396 encode_parameters_.channels * encode_parameters_.input_sample_size; | |
|
Tom Sepez
2015/10/05 16:54:16
again, you need to do the multplications one at a
llandwerlin-old
2015/10/05 17:16:31
Ok, left this one because the encode_parameters_ a
| |
| 397 if (!buffer_manager->Initialize(kDefaultNumberOfAudioFrames, | |
| 398 buffer_size.ValueOrDie())) { | |
| 399 get_audio_frames_reply_context_ = ppapi::host::ReplyMessageContext(); | |
| 400 return false; | |
| 401 } | |
| 402 | |
| 403 get_audio_frames_reply_context_.params.AppendHandle( | |
| 404 SerializedHandle(renderer_ppapi_host_->ShareSharedMemoryHandleWithRemote( | |
| 405 buffer_manager->GetSharedMemory()->handle()), | |
| 406 buffer_manager->GetSharedMemory()->mapped_size())); | |
| 407 | |
| 408 host()->SendReply( | |
| 409 get_audio_frames_reply_context_, | |
| 410 PpapiPluginMsg_AudioEncoder_GetAudioFramesReply( | |
| 411 buffer_manager->number_of_buffers(), buffer_manager->buffer_size())); | |
| 412 | |
| 413 audio_buffer_manager_ = buffer_manager; | |
| 414 get_audio_frames_reply_context_ = ppapi::host::ReplyMessageContext(); | |
| 415 | |
| 416 return true; | |
| 417 } | |
| 418 | |
| 419 bool PepperAudioEncoderHost::AllocateBitstreamBuffers(size_t buffer_size) { | |
| 420 DCHECK(RenderThreadImpl::current()); | |
| 421 // We assume RequireBitstreamBuffers is only called once. | |
| 422 DCHECK(!initialized_); | |
| 423 DCHECK(initialize_reply_context_.is_valid()); | |
| 424 | |
| 425 scoped_refptr<BufferManager> buffer_manager(new BitstreamBufferManager); | |
| 426 if (!buffer_manager->Initialize(kDefaultNumberOfBitstreamBuffers, | |
| 427 buffer_size)) { | |
| 428 initialize_reply_context_ = ppapi::host::ReplyMessageContext(); | |
| 429 return false; | |
| 430 } | |
| 431 | |
| 432 initialize_reply_context_.params.AppendHandle( | |
| 433 SerializedHandle(renderer_ppapi_host_->ShareSharedMemoryHandleWithRemote( | |
| 434 buffer_manager->GetSharedMemory()->handle()), | |
| 435 buffer_manager->GetSharedMemory()->mapped_size())); | |
| 436 | |
| 437 host()->SendReply( | |
| 438 initialize_reply_context_, | |
| 439 PpapiPluginMsg_AudioEncoder_InitializeReply( | |
| 440 encoder_->GetNumberOfSamplesPerFrame(), | |
| 441 buffer_manager->number_of_buffers(), buffer_manager->buffer_size())); | |
| 442 | |
| 443 bitstream_buffer_manager_ = buffer_manager; | |
| 444 initialize_reply_context_ = ppapi::host::ReplyMessageContext(); | |
| 445 | |
| 446 return true; | |
| 447 } | |
| 448 | |
| 449 scoped_refptr<PepperAudioEncoderHost::AudioData> | |
| 450 PepperAudioEncoderHost::GetAudioData( | |
| 451 const scoped_refptr<BufferManager>& buffer_manager) { | |
| 452 if (!buffer_manager->HasAvailableBuffer()) | |
| 453 return scoped_refptr<AudioData>(); | |
| 454 return make_scoped_refptr( | |
| 455 new AudioData(buffer_manager->DequeueBuffer(), buffer_manager)); | |
| 456 } | |
| 457 | |
| 458 void PepperAudioEncoderHost::DoEncode() { | |
| 459 if (!audio_buffer_manager_->HasAvailableBuffer() || | |
| 460 !bitstream_buffer_manager_->HasAvailableBuffer()) | |
| 461 return; | |
| 462 | |
| 463 scoped_refptr<AudioData> input(GetAudioData(audio_buffer_manager_)); | |
| 464 encoder_->Encode(input, GetAudioData(bitstream_buffer_manager_), | |
| 465 base::Bind(&PepperAudioEncoderHost::BitstreamBufferReady, | |
| 466 weak_ptr_factory_.GetWeakPtr(), input->id())); | |
| 467 } | |
| 468 | |
| 469 void PepperAudioEncoderHost::BitstreamBufferReady( | |
| 470 uint32_t audio_buffer_id, | |
| 471 const scoped_refptr<AudioEncoderShim::AudioData>& output, | |
| 472 size_t size) { | |
| 473 DCHECK(RenderThreadImpl::current()); | |
| 474 | |
| 475 if (encoder_last_error_) | |
| 476 return; | |
| 477 | |
| 478 host()->SendUnsolicitedReply( | |
| 479 pp_resource(), PpapiPluginMsg_AudioEncoder_EncodeReply(audio_buffer_id)); | |
| 480 | |
| 481 if (size < 0) { | |
| 482 NotifyPepperError(PP_ERROR_FAILED); | |
| 483 return; | |
| 484 } | |
| 485 | |
| 486 host()->SendUnsolicitedReply( | |
| 487 pp_resource(), PpapiPluginMsg_AudioEncoder_BitstreamBufferReady( | |
| 488 static_cast<AudioData*>(output.get())->id(), size)); | |
| 489 } | |
| 490 | |
| 491 void PepperAudioEncoderHost::NotifyPepperError(int32_t error) { | |
| 492 DCHECK(RenderThreadImpl::current()); | |
| 493 | |
| 494 encoder_last_error_ = error; | |
| 495 Close(); | |
| 496 host()->SendUnsolicitedReply( | |
| 497 pp_resource(), | |
| 498 PpapiPluginMsg_AudioEncoder_NotifyError(encoder_last_error_)); | |
| 499 } | |
| 500 | |
| 501 void PepperAudioEncoderHost::Close() { | |
| 502 DCHECK(RenderThreadImpl::current()); | |
| 503 | |
| 504 encoder_ = nullptr; | |
| 505 audio_buffer_manager_ = nullptr; | |
| 506 bitstream_buffer_manager_ = nullptr; | |
| 507 } | |
| 508 | |
| 509 } // namespace content | |
| OLD | NEW |