Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/content_decryptor_delegate.h" | 5 #include "content/renderer/pepper/content_decryptor_delegate.h" |
| 6 | 6 |
| 7 #include "base/callback_helpers.h" | 7 #include "base/callback_helpers.h" |
| 8 #include "base/debug/trace_event.h" | 8 #include "base/debug/trace_event.h" |
| 9 #include "base/message_loop/message_loop_proxy.h" | 9 #include "base/message_loop/message_loop_proxy.h" |
| 10 #include "base/safe_numerics.h" | 10 #include "base/safe_numerics.h" |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 243 } // namespace | 243 } // namespace |
| 244 | 244 |
| 245 ContentDecryptorDelegate::ContentDecryptorDelegate( | 245 ContentDecryptorDelegate::ContentDecryptorDelegate( |
| 246 PP_Instance pp_instance, | 246 PP_Instance pp_instance, |
| 247 const PPP_ContentDecryptor_Private* plugin_decryption_interface) | 247 const PPP_ContentDecryptor_Private* plugin_decryption_interface) |
| 248 : pp_instance_(pp_instance), | 248 : pp_instance_(pp_instance), |
| 249 plugin_decryption_interface_(plugin_decryption_interface), | 249 plugin_decryption_interface_(plugin_decryption_interface), |
| 250 next_decryption_request_id_(1), | 250 next_decryption_request_id_(1), |
| 251 audio_samples_per_second_(0), | 251 audio_samples_per_second_(0), |
| 252 audio_channel_count_(0), | 252 audio_channel_count_(0), |
| 253 weak_ptr_factory_(this) { | 253 weak_ptr_factory_(this), |
| 254 is_valid_(true) { | |
| 254 weak_this_ = weak_ptr_factory_.GetWeakPtr(); | 255 weak_this_ = weak_ptr_factory_.GetWeakPtr(); |
| 255 } | 256 } |
| 256 | 257 |
| 257 ContentDecryptorDelegate::~ContentDecryptorDelegate() { | 258 ContentDecryptorDelegate::~ContentDecryptorDelegate() { |
| 259 CancelAllPendingCallbacks(); | |
| 258 } | 260 } |
| 259 | 261 |
| 260 void ContentDecryptorDelegate::Initialize(const std::string& key_system) { | 262 void ContentDecryptorDelegate::Initialize(const std::string& key_system) { |
| 261 DCHECK(!key_system.empty()); | 263 DCHECK(!key_system.empty()); |
| 262 DCHECK(key_system_.empty()); | 264 DCHECK(key_system_.empty()); |
| 263 key_system_ = key_system; | 265 key_system_ = key_system; |
| 264 | 266 |
| 265 plugin_decryption_interface_->Initialize( | 267 plugin_decryption_interface_->Initialize( |
| 266 pp_instance_, | 268 pp_instance_, |
| 267 StringVar::StringToPPVar(key_system_)); | 269 StringVar::StringToPPVar(key_system_)); |
| 268 } | 270 } |
| 269 | 271 |
| 270 void ContentDecryptorDelegate::SetSessionEventCallbacks( | 272 void ContentDecryptorDelegate::SetSessionEventCallbacks( |
| 271 const media::SessionCreatedCB& session_created_cb, | 273 const media::SessionCreatedCB& session_created_cb, |
| 272 const media::SessionMessageCB& session_message_cb, | 274 const media::SessionMessageCB& session_message_cb, |
| 273 const media::SessionReadyCB& session_ready_cb, | 275 const media::SessionReadyCB& session_ready_cb, |
| 274 const media::SessionClosedCB& session_closed_cb, | 276 const media::SessionClosedCB& session_closed_cb, |
| 275 const media::SessionErrorCB& session_error_cb) { | 277 const media::SessionErrorCB& session_error_cb) { |
| 276 session_created_cb_ = session_created_cb; | 278 session_created_cb_ = session_created_cb; |
| 277 session_message_cb_ = session_message_cb; | 279 session_message_cb_ = session_message_cb; |
| 278 session_ready_cb_ = session_ready_cb; | 280 session_ready_cb_ = session_ready_cb; |
| 279 session_closed_cb_ = session_closed_cb; | 281 session_closed_cb_ = session_closed_cb; |
| 280 session_error_cb_ = session_error_cb; | 282 session_error_cb_ = session_error_cb; |
| 281 } | 283 } |
| 282 | 284 |
| 285 void ContentDecryptorDelegate::InstanceCrashed() { | |
| 286 CancelAllPendingCallbacks(); | |
| 287 is_valid_ = false; | |
| 288 } | |
| 289 | |
| 283 bool ContentDecryptorDelegate::CreateSession(uint32 session_id, | 290 bool ContentDecryptorDelegate::CreateSession(uint32 session_id, |
| 284 const std::string& type, | 291 const std::string& type, |
| 285 const uint8* init_data, | 292 const uint8* init_data, |
| 286 int init_data_length) { | 293 int init_data_length) { |
| 294 if (!is_valid_) | |
| 295 return false; | |
| 296 | |
| 287 PP_Var init_data_array = | 297 PP_Var init_data_array = |
| 288 PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( | 298 PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( |
| 289 init_data_length, init_data); | 299 init_data_length, init_data); |
| 290 | 300 |
| 291 plugin_decryption_interface_->CreateSession(pp_instance_, | 301 plugin_decryption_interface_->CreateSession(pp_instance_, |
| 292 session_id, | 302 session_id, |
| 293 StringVar::StringToPPVar(type), | 303 StringVar::StringToPPVar(type), |
| 294 init_data_array); | 304 init_data_array); |
| 295 return true; | 305 return true; |
| 296 } | 306 } |
| 297 | 307 |
| 298 bool ContentDecryptorDelegate::UpdateSession(uint32 session_id, | 308 bool ContentDecryptorDelegate::UpdateSession(uint32 session_id, |
| 299 const uint8* response, | 309 const uint8* response, |
| 300 int response_length) { | 310 int response_length) { |
| 311 if (!is_valid_) | |
| 312 return false; | |
| 313 | |
| 301 PP_Var response_array = | 314 PP_Var response_array = |
| 302 PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( | 315 PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( |
| 303 response_length, response); | 316 response_length, response); |
| 304 plugin_decryption_interface_->UpdateSession( | 317 plugin_decryption_interface_->UpdateSession( |
| 305 pp_instance_, session_id, response_array); | 318 pp_instance_, session_id, response_array); |
| 306 return true; | 319 return true; |
| 307 } | 320 } |
| 308 | 321 |
| 309 bool ContentDecryptorDelegate::ReleaseSession(uint32 session_id) { | 322 bool ContentDecryptorDelegate::ReleaseSession(uint32 session_id) { |
| 323 if (!is_valid_) | |
| 324 return false; | |
| 325 | |
| 310 plugin_decryption_interface_->ReleaseSession(pp_instance_, session_id); | 326 plugin_decryption_interface_->ReleaseSession(pp_instance_, session_id); |
| 311 return true; | 327 return true; |
| 312 } | 328 } |
| 313 | 329 |
| 314 // TODO(xhwang): Remove duplication of code in Decrypt(), | 330 // TODO(xhwang): Remove duplication of code in Decrypt(), |
| 315 // DecryptAndDecodeAudio() and DecryptAndDecodeVideo(). | 331 // DecryptAndDecodeAudio() and DecryptAndDecodeVideo(). |
| 316 bool ContentDecryptorDelegate::Decrypt( | 332 bool ContentDecryptorDelegate::Decrypt( |
| 317 Decryptor::StreamType stream_type, | 333 Decryptor::StreamType stream_type, |
| 318 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, | 334 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, |
| 319 const Decryptor::DecryptCB& decrypt_cb) { | 335 const Decryptor::DecryptCB& decrypt_cb) { |
| 320 DVLOG(3) << "Decrypt() - stream_type: " << stream_type; | 336 DVLOG(3) << "Decrypt() - stream_type: " << stream_type; |
| 337 | |
| 338 if (!is_valid_) | |
| 339 return false; | |
| 340 | |
| 321 // |{audio|video}_input_resource_| is not being used by the plugin | 341 // |{audio|video}_input_resource_| is not being used by the plugin |
| 322 // now because there is only one pending audio/video decrypt request at any | 342 // now because there is only one pending audio/video decrypt request at any |
| 323 // time. This is enforced by the media pipeline. | 343 // time. This is enforced by the media pipeline. |
| 324 scoped_refptr<PPB_Buffer_Impl> encrypted_resource; | 344 scoped_refptr<PPB_Buffer_Impl> encrypted_resource; |
| 325 if (!MakeMediaBufferResource( | 345 if (!MakeMediaBufferResource( |
| 326 stream_type, encrypted_buffer, &encrypted_resource) || | 346 stream_type, encrypted_buffer, &encrypted_resource) || |
| 327 !encrypted_resource.get()) { | 347 !encrypted_resource.get()) { |
| 328 return false; | 348 return false; |
| 329 } | 349 } |
| 330 ScopedPPResource pp_resource(encrypted_resource.get()); | 350 ScopedPPResource pp_resource(encrypted_resource.get()); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 357 plugin_decryption_interface_->Decrypt(pp_instance_, | 377 plugin_decryption_interface_->Decrypt(pp_instance_, |
| 358 pp_resource, | 378 pp_resource, |
| 359 &block_info); | 379 &block_info); |
| 360 return true; | 380 return true; |
| 361 } | 381 } |
| 362 | 382 |
| 363 bool ContentDecryptorDelegate::CancelDecrypt( | 383 bool ContentDecryptorDelegate::CancelDecrypt( |
| 364 Decryptor::StreamType stream_type) { | 384 Decryptor::StreamType stream_type) { |
| 365 DVLOG(3) << "CancelDecrypt() - stream_type: " << stream_type; | 385 DVLOG(3) << "CancelDecrypt() - stream_type: " << stream_type; |
| 366 | 386 |
| 387 if (!is_valid_) | |
| 388 return false; | |
| 389 | |
| 367 Decryptor::DecryptCB decrypt_cb; | 390 Decryptor::DecryptCB decrypt_cb; |
| 368 switch (stream_type) { | 391 switch (stream_type) { |
| 369 case Decryptor::kAudio: | 392 case Decryptor::kAudio: |
| 370 // Release the shared memory as it can still be in use by the plugin. | 393 // Release the shared memory as it can still be in use by the plugin. |
| 371 // The next Decrypt() call will need to allocate a new shared memory | 394 // The next Decrypt() call will need to allocate a new shared memory |
| 372 // buffer. | 395 // buffer. |
| 373 audio_input_resource_ = NULL; | 396 audio_input_resource_ = NULL; |
| 374 decrypt_cb = audio_decrypt_cb_.ResetAndReturn(); | 397 decrypt_cb = audio_decrypt_cb_.ResetAndReturn(); |
| 375 break; | 398 break; |
| 376 case Decryptor::kVideo: | 399 case Decryptor::kVideo: |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 387 | 410 |
| 388 if (!decrypt_cb.is_null()) | 411 if (!decrypt_cb.is_null()) |
| 389 decrypt_cb.Run(Decryptor::kSuccess, NULL); | 412 decrypt_cb.Run(Decryptor::kSuccess, NULL); |
| 390 | 413 |
| 391 return true; | 414 return true; |
| 392 } | 415 } |
| 393 | 416 |
| 394 bool ContentDecryptorDelegate::InitializeAudioDecoder( | 417 bool ContentDecryptorDelegate::InitializeAudioDecoder( |
| 395 const media::AudioDecoderConfig& decoder_config, | 418 const media::AudioDecoderConfig& decoder_config, |
| 396 const Decryptor::DecoderInitCB& init_cb) { | 419 const Decryptor::DecoderInitCB& init_cb) { |
| 420 if (!is_valid_) | |
| 421 return false; | |
| 422 | |
| 397 PP_AudioDecoderConfig pp_decoder_config; | 423 PP_AudioDecoderConfig pp_decoder_config; |
| 398 pp_decoder_config.codec = | 424 pp_decoder_config.codec = |
| 399 MediaAudioCodecToPpAudioCodec(decoder_config.codec()); | 425 MediaAudioCodecToPpAudioCodec(decoder_config.codec()); |
| 400 pp_decoder_config.channel_count = | 426 pp_decoder_config.channel_count = |
| 401 media::ChannelLayoutToChannelCount(decoder_config.channel_layout()); | 427 media::ChannelLayoutToChannelCount(decoder_config.channel_layout()); |
| 402 pp_decoder_config.bits_per_channel = decoder_config.bits_per_channel(); | 428 pp_decoder_config.bits_per_channel = decoder_config.bits_per_channel(); |
| 403 pp_decoder_config.samples_per_second = decoder_config.samples_per_second(); | 429 pp_decoder_config.samples_per_second = decoder_config.samples_per_second(); |
| 404 pp_decoder_config.request_id = next_decryption_request_id_++; | 430 pp_decoder_config.request_id = next_decryption_request_id_++; |
| 405 | 431 |
| 406 audio_samples_per_second_ = pp_decoder_config.samples_per_second; | 432 audio_samples_per_second_ = pp_decoder_config.samples_per_second; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 418 audio_decoder_init_cb_.Set(pp_decoder_config.request_id, init_cb); | 444 audio_decoder_init_cb_.Set(pp_decoder_config.request_id, init_cb); |
| 419 plugin_decryption_interface_->InitializeAudioDecoder(pp_instance_, | 445 plugin_decryption_interface_->InitializeAudioDecoder(pp_instance_, |
| 420 &pp_decoder_config, | 446 &pp_decoder_config, |
| 421 pp_resource); | 447 pp_resource); |
| 422 return true; | 448 return true; |
| 423 } | 449 } |
| 424 | 450 |
| 425 bool ContentDecryptorDelegate::InitializeVideoDecoder( | 451 bool ContentDecryptorDelegate::InitializeVideoDecoder( |
| 426 const media::VideoDecoderConfig& decoder_config, | 452 const media::VideoDecoderConfig& decoder_config, |
| 427 const Decryptor::DecoderInitCB& init_cb) { | 453 const Decryptor::DecoderInitCB& init_cb) { |
| 454 if (!is_valid_) | |
| 455 return false; | |
| 456 | |
| 428 PP_VideoDecoderConfig pp_decoder_config; | 457 PP_VideoDecoderConfig pp_decoder_config; |
| 429 pp_decoder_config.codec = | 458 pp_decoder_config.codec = |
| 430 MediaVideoCodecToPpVideoCodec(decoder_config.codec()); | 459 MediaVideoCodecToPpVideoCodec(decoder_config.codec()); |
| 431 pp_decoder_config.profile = | 460 pp_decoder_config.profile = |
| 432 MediaVideoCodecProfileToPpVideoCodecProfile(decoder_config.profile()); | 461 MediaVideoCodecProfileToPpVideoCodecProfile(decoder_config.profile()); |
| 433 pp_decoder_config.format = | 462 pp_decoder_config.format = |
| 434 MediaVideoFormatToPpDecryptedFrameFormat(decoder_config.format()); | 463 MediaVideoFormatToPpDecryptedFrameFormat(decoder_config.format()); |
| 435 pp_decoder_config.width = decoder_config.coded_size().width(); | 464 pp_decoder_config.width = decoder_config.coded_size().width(); |
| 436 pp_decoder_config.height = decoder_config.coded_size().height(); | 465 pp_decoder_config.height = decoder_config.coded_size().height(); |
| 437 pp_decoder_config.request_id = next_decryption_request_id_++; | 466 pp_decoder_config.request_id = next_decryption_request_id_++; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 449 natural_size_ = decoder_config.natural_size(); | 478 natural_size_ = decoder_config.natural_size(); |
| 450 | 479 |
| 451 plugin_decryption_interface_->InitializeVideoDecoder(pp_instance_, | 480 plugin_decryption_interface_->InitializeVideoDecoder(pp_instance_, |
| 452 &pp_decoder_config, | 481 &pp_decoder_config, |
| 453 pp_resource); | 482 pp_resource); |
| 454 return true; | 483 return true; |
| 455 } | 484 } |
| 456 | 485 |
| 457 bool ContentDecryptorDelegate::DeinitializeDecoder( | 486 bool ContentDecryptorDelegate::DeinitializeDecoder( |
| 458 Decryptor::StreamType stream_type) { | 487 Decryptor::StreamType stream_type) { |
| 488 if (!is_valid_) | |
| 489 return false; | |
| 490 | |
| 459 CancelDecode(stream_type); | 491 CancelDecode(stream_type); |
| 460 | 492 |
| 461 natural_size_ = gfx::Size(); | 493 natural_size_ = gfx::Size(); |
| 462 | 494 |
| 463 // TODO(tomfinegan): Add decoder deinitialize request tracking, and get | 495 // TODO(tomfinegan): Add decoder deinitialize request tracking, and get |
| 464 // stream type from media stack. | 496 // stream type from media stack. |
| 465 plugin_decryption_interface_->DeinitializeDecoder( | 497 plugin_decryption_interface_->DeinitializeDecoder( |
| 466 pp_instance_, MediaDecryptorStreamTypeToPpStreamType(stream_type), 0); | 498 pp_instance_, MediaDecryptorStreamTypeToPpStreamType(stream_type), 0); |
| 467 return true; | 499 return true; |
| 468 } | 500 } |
| 469 | 501 |
| 470 bool ContentDecryptorDelegate::ResetDecoder(Decryptor::StreamType stream_type) { | 502 bool ContentDecryptorDelegate::ResetDecoder(Decryptor::StreamType stream_type) { |
| 503 if (!is_valid_) | |
| 504 return false; | |
| 505 | |
| 471 CancelDecode(stream_type); | 506 CancelDecode(stream_type); |
| 472 | 507 |
| 473 // TODO(tomfinegan): Add decoder reset request tracking. | 508 // TODO(tomfinegan): Add decoder reset request tracking. |
| 474 plugin_decryption_interface_->ResetDecoder( | 509 plugin_decryption_interface_->ResetDecoder( |
| 475 pp_instance_, MediaDecryptorStreamTypeToPpStreamType(stream_type), 0); | 510 pp_instance_, MediaDecryptorStreamTypeToPpStreamType(stream_type), 0); |
| 476 return true; | 511 return true; |
| 477 } | 512 } |
| 478 | 513 |
| 479 bool ContentDecryptorDelegate::DecryptAndDecodeAudio( | 514 bool ContentDecryptorDelegate::DecryptAndDecodeAudio( |
| 480 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, | 515 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, |
| 481 const Decryptor::AudioDecodeCB& audio_decode_cb) { | 516 const Decryptor::AudioDecodeCB& audio_decode_cb) { |
| 517 if (!is_valid_) | |
| 518 return false; | |
| 519 | |
| 482 // |audio_input_resource_| is not being used by the plugin now | 520 // |audio_input_resource_| is not being used by the plugin now |
| 483 // because there is only one pending audio decode request at any time. | 521 // because there is only one pending audio decode request at any time. |
| 484 // This is enforced by the media pipeline. | 522 // This is enforced by the media pipeline. |
| 485 scoped_refptr<PPB_Buffer_Impl> encrypted_resource; | 523 scoped_refptr<PPB_Buffer_Impl> encrypted_resource; |
| 486 if (!MakeMediaBufferResource( | 524 if (!MakeMediaBufferResource( |
| 487 Decryptor::kAudio, encrypted_buffer, &encrypted_resource)) { | 525 Decryptor::kAudio, encrypted_buffer, &encrypted_resource)) { |
| 488 return false; | 526 return false; |
| 489 } | 527 } |
| 490 | 528 |
| 491 // The resource should not be NULL for non-EOS buffer. | 529 // The resource should not be NULL for non-EOS buffer. |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 512 plugin_decryption_interface_->DecryptAndDecode(pp_instance_, | 550 plugin_decryption_interface_->DecryptAndDecode(pp_instance_, |
| 513 PP_DECRYPTORSTREAMTYPE_AUDIO, | 551 PP_DECRYPTORSTREAMTYPE_AUDIO, |
| 514 pp_resource, | 552 pp_resource, |
| 515 &block_info); | 553 &block_info); |
| 516 return true; | 554 return true; |
| 517 } | 555 } |
| 518 | 556 |
| 519 bool ContentDecryptorDelegate::DecryptAndDecodeVideo( | 557 bool ContentDecryptorDelegate::DecryptAndDecodeVideo( |
| 520 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, | 558 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, |
| 521 const Decryptor::VideoDecodeCB& video_decode_cb) { | 559 const Decryptor::VideoDecodeCB& video_decode_cb) { |
| 560 if (!is_valid_) | |
| 561 return false; | |
| 562 | |
| 522 // |video_input_resource_| is not being used by the plugin now | 563 // |video_input_resource_| is not being used by the plugin now |
| 523 // because there is only one pending video decode request at any time. | 564 // because there is only one pending video decode request at any time. |
| 524 // This is enforced by the media pipeline. | 565 // This is enforced by the media pipeline. |
| 525 scoped_refptr<PPB_Buffer_Impl> encrypted_resource; | 566 scoped_refptr<PPB_Buffer_Impl> encrypted_resource; |
| 526 if (!MakeMediaBufferResource( | 567 if (!MakeMediaBufferResource( |
| 527 Decryptor::kVideo, encrypted_buffer, &encrypted_resource)) { | 568 Decryptor::kVideo, encrypted_buffer, &encrypted_resource)) { |
| 528 return false; | 569 return false; |
| 529 } | 570 } |
| 530 | 571 |
| 531 // The resource should not be 0 for non-EOS buffer. | 572 // The resource should not be 0 for non-EOS buffer. |
| (...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1014 frame_count)); | 1055 frame_count)); |
| 1015 frames->push_back(frame); | 1056 frames->push_back(frame); |
| 1016 | 1057 |
| 1017 cur += frame_size; | 1058 cur += frame_size; |
| 1018 bytes_left -= frame_size; | 1059 bytes_left -= frame_size; |
| 1019 } while (bytes_left > 0); | 1060 } while (bytes_left > 0); |
| 1020 | 1061 |
| 1021 return true; | 1062 return true; |
| 1022 } | 1063 } |
| 1023 | 1064 |
| 1065 void ContentDecryptorDelegate::CancelAllPendingCallbacks() { | |
|
dmichael (off chromium)
2014/01/08 20:15:59
The meaning here is a little different from what I
xhwang
2014/01/08 23:19:14
Done.
| |
| 1066 if (!audio_decoder_init_cb_.is_null()) | |
| 1067 audio_decoder_init_cb_.ResetAndReturn().Run(false); | |
| 1068 | |
| 1069 if (!video_decoder_init_cb_.is_null()) | |
| 1070 video_decoder_init_cb_.ResetAndReturn().Run(false); | |
| 1071 | |
| 1072 audio_input_resource_ = NULL; | |
| 1073 video_input_resource_ = NULL; | |
| 1074 | |
| 1075 if (!audio_decrypt_cb_.is_null()) | |
| 1076 audio_decrypt_cb_.ResetAndReturn().Run(media::Decryptor::kError, NULL); | |
| 1077 | |
| 1078 if (!video_decrypt_cb_.is_null()) | |
| 1079 video_decrypt_cb_.ResetAndReturn().Run(media::Decryptor::kError, NULL); | |
| 1080 | |
| 1081 if (!audio_decode_cb_.is_null()) { | |
| 1082 const media::Decryptor::AudioBuffers empty_frames; | |
| 1083 audio_decode_cb_.ResetAndReturn().Run(media::Decryptor::kError, | |
| 1084 empty_frames); | |
| 1085 } | |
| 1086 | |
| 1087 if (!video_decode_cb_.is_null()) | |
| 1088 video_decode_cb_.ResetAndReturn().Run(media::Decryptor::kError, NULL); | |
| 1089 } | |
| 1090 | |
| 1024 } // namespace content | 1091 } // namespace content |
| OLD | NEW |