Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(107)

Side by Side Diff: content/renderer/media/crypto/ppapi_decryptor.cc

Issue 697203003: Resume playback of EME stream only on SessionKeysChange event. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rename Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/renderer/media/crypto/ppapi_decryptor.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/media/crypto/ppapi_decryptor.h" 5 #include "content/renderer/media/crypto/ppapi_decryptor.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/callback_helpers.h"
12 #include "base/location.h"
13 #include "base/logging.h" 10 #include "base/logging.h"
14 #include "base/message_loop/message_loop.h" 11 #include "base/message_loop/message_loop.h"
15 #include "base/message_loop/message_loop_proxy.h" 12 #include "base/message_loop/message_loop_proxy.h"
16 #include "content/renderer/media/crypto/key_systems.h" 13 #include "content/renderer/media/crypto/key_systems.h"
17 #include "content/renderer/pepper/content_decryptor_delegate.h" 14 #include "content/renderer/pepper/content_decryptor_delegate.h"
18 #include "content/renderer/pepper/pepper_plugin_instance_impl.h" 15 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
19 #include "media/base/audio_decoder_config.h" 16 #include "media/base/audio_decoder_config.h"
20 #include "media/base/cdm_promise.h"
21 #include "media/base/data_buffer.h" 17 #include "media/base/data_buffer.h"
22 #include "media/base/decoder_buffer.h" 18 #include "media/base/decoder_buffer.h"
23 #include "media/base/video_decoder_config.h" 19 #include "media/base/video_decoder_config.h"
24 #include "media/base/video_frame.h" 20 #include "media/base/video_frame.h"
25 21
26 namespace content { 22 namespace content {
27 23
28 // This class is needed so that resolving an Update() promise triggers playback
29 // of the stream. It intercepts the resolve() call to invoke an additional
30 // callback.
31 class SessionUpdatedPromise : public media::CdmPromiseTemplate<> {
32 public:
33 SessionUpdatedPromise(scoped_ptr<media::SimpleCdmPromise> caller_promise,
34 const base::Closure& additional_resolve_cb)
35 : caller_promise_(caller_promise.Pass()),
36 additional_resolve_cb_(additional_resolve_cb) {}
37
38 void resolve() override {
39 MarkPromiseSettled();
40 additional_resolve_cb_.Run();
41 caller_promise_->resolve();
42 }
43
44 void reject(media::MediaKeys::Exception exception_code,
45 uint32 system_code,
46 const std::string& error_message) override {
47 MarkPromiseSettled();
48 caller_promise_->reject(exception_code, system_code, error_message);
49 }
50
51 protected:
52 scoped_ptr<media::SimpleCdmPromise> caller_promise_;
53 base::Closure additional_resolve_cb_;
54 };
55
56 // This class is needed so that resolving a SessionLoaded() promise triggers
57 // playback of the stream. It intercepts the resolve() call to invoke an
58 // additional callback. This is only needed until KeysChange event gets passed
59 // through Pepper.
60 class SessionLoadedPromise : public media::CdmPromiseTemplate<std::string> {
61 public:
62 SessionLoadedPromise(scoped_ptr<media::NewSessionCdmPromise> caller_promise,
63 const base::Closure& additional_resolve_cb)
64 : caller_promise_(caller_promise.Pass()),
65 additional_resolve_cb_(additional_resolve_cb) {}
66
67 void resolve(const std::string& web_session_id) override {
68 MarkPromiseSettled();
69 additional_resolve_cb_.Run();
70 caller_promise_->resolve(web_session_id);
71 }
72
73 void reject(media::MediaKeys::Exception exception_code,
74 uint32 system_code,
75 const std::string& error_message) override {
76 MarkPromiseSettled();
77 caller_promise_->reject(exception_code, system_code, error_message);
78 }
79
80 protected:
81 scoped_ptr<media::NewSessionCdmPromise> caller_promise_;
82 base::Closure additional_resolve_cb_;
83 };
84
85 scoped_ptr<PpapiDecryptor> PpapiDecryptor::Create( 24 scoped_ptr<PpapiDecryptor> PpapiDecryptor::Create(
86 const std::string& key_system, 25 const std::string& key_system,
87 const GURL& security_origin, 26 const GURL& security_origin,
88 const CreatePepperCdmCB& create_pepper_cdm_cb, 27 const CreatePepperCdmCB& create_pepper_cdm_cb,
89 const media::SessionMessageCB& session_message_cb, 28 const media::SessionMessageCB& session_message_cb,
90 const media::SessionReadyCB& session_ready_cb, 29 const media::SessionReadyCB& session_ready_cb,
91 const media::SessionClosedCB& session_closed_cb, 30 const media::SessionClosedCB& session_closed_cb,
92 const media::SessionErrorCB& session_error_cb, 31 const media::SessionErrorCB& session_error_cb,
93 const media::SessionKeysChangeCB& session_keys_change_cb, 32 const media::SessionKeysChangeCB& session_keys_change_cb,
94 const media::SessionExpirationUpdateCB& session_expiration_update_cb) { 33 const media::SessionExpirationUpdateCB& session_expiration_update_cb) {
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 void PpapiDecryptor::LoadSession( 133 void PpapiDecryptor::LoadSession(
195 const std::string& web_session_id, 134 const std::string& web_session_id,
196 scoped_ptr<media::NewSessionCdmPromise> promise) { 135 scoped_ptr<media::NewSessionCdmPromise> promise) {
197 DVLOG(2) << __FUNCTION__; 136 DVLOG(2) << __FUNCTION__;
198 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); 137 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
199 138
200 if (!CdmDelegate()) { 139 if (!CdmDelegate()) {
201 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist."); 140 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist.");
202 return; 141 return;
203 } 142 }
204 143 CdmDelegate()->LoadSession(web_session_id, promise.Pass());
205 // TODO(jrummell): Intercepting the promise should not be necessary once
206 // OnSessionKeysChange() is called in all cases. http://crbug.com/413413.
207 scoped_ptr<SessionLoadedPromise> session_loaded_promise(
208 new SessionLoadedPromise(promise.Pass(),
209 base::Bind(&PpapiDecryptor::ResumePlayback,
210 weak_ptr_factory_.GetWeakPtr())));
211
212 CdmDelegate()->LoadSession(web_session_id, session_loaded_promise.Pass());
213 } 144 }
214 145
215 void PpapiDecryptor::UpdateSession( 146 void PpapiDecryptor::UpdateSession(
216 const std::string& web_session_id, 147 const std::string& web_session_id,
217 const uint8* response, 148 const uint8* response,
218 int response_length, 149 int response_length,
219 scoped_ptr<media::SimpleCdmPromise> promise) { 150 scoped_ptr<media::SimpleCdmPromise> promise) {
220 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); 151 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
221 152
222 if (!CdmDelegate()) { 153 if (!CdmDelegate()) {
223 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist."); 154 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist.");
224 return; 155 return;
225 } 156 }
226 157 CdmDelegate()->UpdateSession(web_session_id, response, response_length,
227 // TODO(jrummell): Intercepting the promise should not be necessary once 158 promise.Pass());
228 // OnSessionKeysChange() is called in all cases. http://crbug.com/413413.
229 scoped_ptr<SessionUpdatedPromise> session_updated_promise(
230 new SessionUpdatedPromise(promise.Pass(),
231 base::Bind(&PpapiDecryptor::ResumePlayback,
232 weak_ptr_factory_.GetWeakPtr())));
233 CdmDelegate()->UpdateSession(web_session_id,
234 response,
235 response_length,
236 session_updated_promise.Pass());
237 } 159 }
238 160
239 void PpapiDecryptor::CloseSession(const std::string& web_session_id, 161 void PpapiDecryptor::CloseSession(const std::string& web_session_id,
240 scoped_ptr<media::SimpleCdmPromise> promise) { 162 scoped_ptr<media::SimpleCdmPromise> promise) {
241 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); 163 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
242 164
243 if (!CdmDelegate()) { 165 if (!CdmDelegate()) {
244 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist."); 166 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist.");
245 return; 167 return;
246 } 168 }
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 session_message_cb_.Run(web_session_id, message, destination_url); 407 session_message_cb_.Run(web_session_id, message, destination_url);
486 } 408 }
487 409
488 void PpapiDecryptor::OnSessionKeysChange(const std::string& web_session_id, 410 void PpapiDecryptor::OnSessionKeysChange(const std::string& web_session_id,
489 bool has_additional_usable_key) { 411 bool has_additional_usable_key) {
490 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); 412 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
491 413
492 // TODO(jrummell): Handling resume playback should be done in the media 414 // TODO(jrummell): Handling resume playback should be done in the media
493 // player, not in the Decryptors. http://crbug.com/413413. 415 // player, not in the Decryptors. http://crbug.com/413413.
494 if (has_additional_usable_key) 416 if (has_additional_usable_key)
495 ResumePlayback(); 417 AttemptToResumePlayback();
496 418
497 session_keys_change_cb_.Run(web_session_id, has_additional_usable_key); 419 session_keys_change_cb_.Run(web_session_id, has_additional_usable_key);
498 } 420 }
499 421
500 void PpapiDecryptor::OnSessionExpirationUpdate( 422 void PpapiDecryptor::OnSessionExpirationUpdate(
501 const std::string& web_session_id, 423 const std::string& web_session_id,
502 const base::Time& new_expiry_time) { 424 const base::Time& new_expiry_time) {
503 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); 425 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
504 session_expiration_update_cb_.Run(web_session_id, new_expiry_time); 426 session_expiration_update_cb_.Run(web_session_id, new_expiry_time);
505 } 427 }
506 428
507 void PpapiDecryptor::OnSessionReady(const std::string& web_session_id) { 429 void PpapiDecryptor::OnSessionReady(const std::string& web_session_id) {
508 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); 430 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
509
510 // TODO(jrummell): Calling ResumePlayback() here should not be necessary once
511 // OnSessionKeysChange() is called in all cases. http://crbug.com/413413.
512 ResumePlayback();
513 session_ready_cb_.Run(web_session_id); 431 session_ready_cb_.Run(web_session_id);
514 } 432 }
515 433
516 void PpapiDecryptor::OnSessionClosed(const std::string& web_session_id) { 434 void PpapiDecryptor::OnSessionClosed(const std::string& web_session_id) {
517 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); 435 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
518 session_closed_cb_.Run(web_session_id); 436 session_closed_cb_.Run(web_session_id);
519 } 437 }
520 438
521 void PpapiDecryptor::OnSessionError(const std::string& web_session_id, 439 void PpapiDecryptor::OnSessionError(const std::string& web_session_id,
522 MediaKeys::Exception exception_code, 440 MediaKeys::Exception exception_code,
523 uint32 system_code, 441 uint32 system_code,
524 const std::string& error_description) { 442 const std::string& error_description) {
525 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); 443 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
526 session_error_cb_.Run( 444 session_error_cb_.Run(
527 web_session_id, exception_code, system_code, error_description); 445 web_session_id, exception_code, system_code, error_description);
528 } 446 }
529 447
530 void PpapiDecryptor::ResumePlayback() { 448 void PpapiDecryptor::AttemptToResumePlayback() {
531 // Based on the spec, we need to resume playback when update() completes
532 // successfully, or when a session is successfully loaded (triggered by
533 // OnSessionReady()). So we choose to call the NewKeyCBs here.
534 if (!new_audio_key_cb_.is_null()) 449 if (!new_audio_key_cb_.is_null())
535 new_audio_key_cb_.Run(); 450 new_audio_key_cb_.Run();
536 451
537 if (!new_video_key_cb_.is_null()) 452 if (!new_video_key_cb_.is_null())
538 new_video_key_cb_.Run(); 453 new_video_key_cb_.Run();
539 } 454 }
540 455
541 void PpapiDecryptor::OnFatalPluginError() { 456 void PpapiDecryptor::OnFatalPluginError() {
542 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); 457 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
543 pepper_cdm_wrapper_.reset(); 458 pepper_cdm_wrapper_.reset();
544 } 459 }
545 460
546 ContentDecryptorDelegate* PpapiDecryptor::CdmDelegate() { 461 ContentDecryptorDelegate* PpapiDecryptor::CdmDelegate() {
547 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); 462 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
548 return (pepper_cdm_wrapper_) ? pepper_cdm_wrapper_->GetCdmDelegate() : NULL; 463 return (pepper_cdm_wrapper_) ? pepper_cdm_wrapper_->GetCdmDelegate() : NULL;
549 } 464 }
550 465
551 } // namespace content 466 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/media/crypto/ppapi_decryptor.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698