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

Side by Side Diff: content/browser/media/android/browser_media_player_manager.cc

Issue 315733003: Separate BrowserCdmManager from BrowserMediaPlayerManager. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: minor fix after rebase Created 6 years, 6 months 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 | Annotate | Revision Log
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/browser/media/android/browser_media_player_manager.h" 5 #include "content/browser/media/android/browser_media_player_manager.h"
6 6
7 #include "base/android/scoped_java_ref.h" 7 #include "base/android/scoped_java_ref.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/stl_util.h"
10 #include "content/browser/android/content_view_core_impl.h" 9 #include "content/browser/android/content_view_core_impl.h"
11 #include "content/browser/media/android/browser_demuxer_android.h" 10 #include "content/browser/media/android/browser_demuxer_android.h"
12 #include "content/browser/media/android/media_resource_getter_impl.h" 11 #include "content/browser/media/android/media_resource_getter_impl.h"
13 #include "content/browser/renderer_host/render_view_host_impl.h" 12 #include "content/browser/renderer_host/render_view_host_impl.h"
14 #include "content/browser/web_contents/web_contents_view_android.h" 13 #include "content/browser/web_contents/web_contents_view_android.h"
15 #include "content/common/media/cdm_messages.h"
16 #include "content/common/media/media_player_messages_android.h" 14 #include "content/common/media/media_player_messages_android.h"
17 #include "content/public/browser/android/content_view_core.h" 15 #include "content/public/browser/android/content_view_core.h"
18 #include "content/public/browser/android/external_video_surface_container.h" 16 #include "content/public/browser/android/external_video_surface_container.h"
19 #include "content/public/browser/browser_context.h" 17 #include "content/public/browser/browser_context.h"
20 #include "content/public/browser/content_browser_client.h" 18 #include "content/public/browser/content_browser_client.h"
21 #include "content/public/browser/render_frame_host.h" 19 #include "content/public/browser/render_frame_host.h"
22 #include "content/public/browser/render_process_host.h" 20 #include "content/public/browser/render_process_host.h"
23 #include "content/public/browser/render_view_host.h" 21 #include "content/public/browser/render_view_host.h"
24 #include "content/public/browser/storage_partition.h" 22 #include "content/public/browser/storage_partition.h"
25 #include "content/public/browser/web_contents.h" 23 #include "content/public/browser/web_contents.h"
26 #include "content/public/browser/web_contents_delegate.h" 24 #include "content/public/browser/web_contents_delegate.h"
27 #include "content/public/common/content_client.h" 25 #include "content/public/common/content_client.h"
28 #include "content/public/common/content_switches.h" 26 #include "content/public/common/content_switches.h"
29 #include "media/base/android/media_player_bridge.h" 27 #include "media/base/android/media_player_bridge.h"
30 #include "media/base/android/media_source_player.h" 28 #include "media/base/android/media_source_player.h"
31 #include "media/base/browser_cdm.h"
32 #include "media/base/browser_cdm_factory.h"
33 #include "media/base/media_switches.h" 29 #include "media/base/media_switches.h"
34 30
35 using media::BrowserCdm;
36 using media::MediaKeys;
37 using media::MediaPlayerAndroid; 31 using media::MediaPlayerAndroid;
38 using media::MediaPlayerBridge; 32 using media::MediaPlayerBridge;
39 using media::MediaPlayerManager; 33 using media::MediaPlayerManager;
40 using media::MediaSourcePlayer; 34 using media::MediaSourcePlayer;
41 35
42 namespace content { 36 namespace content {
43 37
44 // Threshold on the number of media players per renderer before we start 38 // Threshold on the number of media players per renderer before we start
45 // attempting to release inactive media players. 39 // attempting to release inactive media players.
46 const int kMediaPlayerThreshold = 1; 40 const int kMediaPlayerThreshold = 1;
47 41
48 // Maximum lengths for various EME API parameters. These are checks to
49 // prevent unnecessarily large parameters from being passed around, and the
50 // lengths are somewhat arbitrary as the EME spec doesn't specify any limits.
51 const size_t kMaxInitDataLength = 64 * 1024; // 64 KB
52 const size_t kMaxSessionResponseLength = 64 * 1024; // 64 KB
53 const size_t kMaxKeySystemLength = 256;
54
55 static BrowserMediaPlayerManager::Factory g_factory = NULL; 42 static BrowserMediaPlayerManager::Factory g_factory = NULL;
56 43
57 // static 44 // static
58 void BrowserMediaPlayerManager::RegisterFactory(Factory factory) { 45 void BrowserMediaPlayerManager::RegisterFactory(Factory factory) {
59 g_factory = factory; 46 g_factory = factory;
60 } 47 }
61 48
62 // static 49 // static
63 BrowserMediaPlayerManager* BrowserMediaPlayerManager::Create( 50 BrowserMediaPlayerManager* BrowserMediaPlayerManager::Create(
64 RenderFrameHost* rfh) { 51 RenderFrameHost* rfh) {
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 299
313 MediaPlayerAndroid* BrowserMediaPlayerManager::GetPlayer(int player_id) { 300 MediaPlayerAndroid* BrowserMediaPlayerManager::GetPlayer(int player_id) {
314 for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin(); 301 for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
315 it != players_.end(); ++it) { 302 it != players_.end(); ++it) {
316 if ((*it)->player_id() == player_id) 303 if ((*it)->player_id() == player_id)
317 return *it; 304 return *it;
318 } 305 }
319 return NULL; 306 return NULL;
320 } 307 }
321 308
322 BrowserCdm* BrowserMediaPlayerManager::GetCdm(int cdm_id) {
323 CdmMap::const_iterator iter = cdm_map_.find(cdm_id);
324 return (iter == cdm_map_.end()) ? NULL : iter->second;
325 }
326
327 void BrowserMediaPlayerManager::DestroyAllMediaPlayers() { 309 void BrowserMediaPlayerManager::DestroyAllMediaPlayers() {
328 players_.clear(); 310 players_.clear();
329 STLDeleteValues(&cdm_map_);
330 if (fullscreen_player_id_ != -1) { 311 if (fullscreen_player_id_ != -1) {
331 video_view_.reset(); 312 video_view_.reset();
332 fullscreen_player_id_ = -1; 313 fullscreen_player_id_ = -1;
333 } 314 }
334 } 315 }
335 316
336 void BrowserMediaPlayerManager::RequestFullScreen(int player_id) { 317 void BrowserMediaPlayerManager::RequestFullScreen(int player_id) {
337 if (fullscreen_player_id_ == player_id) 318 if (fullscreen_player_id_ == player_id)
338 return; 319 return;
339 320
340 if (fullscreen_player_id_ != -1) { 321 if (fullscreen_player_id_ != -1) {
341 // TODO(qinmin): Determine the correct error code we should report to WMPA. 322 // TODO(qinmin): Determine the correct error code we should report to WMPA.
342 OnError(player_id, MediaPlayerAndroid::MEDIA_ERROR_DECODE); 323 OnError(player_id, MediaPlayerAndroid::MEDIA_ERROR_DECODE);
343 return; 324 return;
344 } 325 }
345 } 326 }
346 327
347 // The following 5 functions are EME MediaKeySession events.
348
349 void BrowserMediaPlayerManager::OnSessionCreated(
350 int cdm_id,
351 uint32 session_id,
352 const std::string& web_session_id) {
353 Send(new CdmMsg_SessionCreated(
354 RoutingID(), cdm_id, session_id, web_session_id));
355 }
356
357 void BrowserMediaPlayerManager::OnSessionMessage(
358 int cdm_id,
359 uint32 session_id,
360 const std::vector<uint8>& message,
361 const GURL& destination_url) {
362 GURL verified_gurl = destination_url;
363 if (!verified_gurl.is_valid() && !verified_gurl.is_empty()) {
364 DLOG(WARNING) << "SessionMessage destination_url is invalid : "
365 << destination_url.possibly_invalid_spec();
366 verified_gurl = GURL::EmptyGURL(); // Replace invalid destination_url.
367 }
368
369 Send(new CdmMsg_SessionMessage(
370 RoutingID(), cdm_id, session_id, message, verified_gurl));
371 }
372
373 void BrowserMediaPlayerManager::OnSessionReady(int cdm_id, uint32 session_id) {
374 Send(new CdmMsg_SessionReady(RoutingID(), cdm_id, session_id));
375 }
376
377 void BrowserMediaPlayerManager::OnSessionClosed(int cdm_id, uint32 session_id) {
378 Send(new CdmMsg_SessionClosed(RoutingID(), cdm_id, session_id));
379 }
380
381 void BrowserMediaPlayerManager::OnSessionError(int cdm_id,
382 uint32 session_id,
383 MediaKeys::KeyError error_code,
384 uint32 system_code) {
385 Send(new CdmMsg_SessionError(
386 RoutingID(), cdm_id, session_id, error_code, system_code));
387 }
388
389 #if defined(VIDEO_HOLE) 328 #if defined(VIDEO_HOLE)
390 void BrowserMediaPlayerManager::AttachExternalVideoSurface(int player_id, 329 void BrowserMediaPlayerManager::AttachExternalVideoSurface(int player_id,
391 jobject surface) { 330 jobject surface) {
392 MediaPlayerAndroid* player = GetPlayer(player_id); 331 MediaPlayerAndroid* player = GetPlayer(player_id);
393 if (player) { 332 if (player) {
394 player->SetVideoSurface( 333 player->SetVideoSurface(
395 gfx::ScopedJavaSurface::AcquireExternalSurface(surface)); 334 gfx::ScopedJavaSurface::AcquireExternalSurface(surface));
396 } 335 }
397 } 336 }
398 337
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 if (player_id == fullscreen_player_id_) 488 if (player_id == fullscreen_player_id_)
550 fullscreen_player_is_released_ = true; 489 fullscreen_player_is_released_ = true;
551 } 490 }
552 491
553 void BrowserMediaPlayerManager::OnDestroyPlayer(int player_id) { 492 void BrowserMediaPlayerManager::OnDestroyPlayer(int player_id) {
554 RemovePlayer(player_id); 493 RemovePlayer(player_id);
555 if (fullscreen_player_id_ == player_id) 494 if (fullscreen_player_id_ == player_id)
556 fullscreen_player_id_ = -1; 495 fullscreen_player_id_ = -1;
557 } 496 }
558 497
559 void BrowserMediaPlayerManager::OnInitializeCdm(int cdm_id,
560 const std::string& key_system,
561 const GURL& security_origin) {
562 if (key_system.size() > kMaxKeySystemLength) {
563 // This failure will be discovered and reported by OnCreateSession()
564 // as GetCdm() will return null.
565 NOTREACHED() << "Invalid key system: " << key_system;
566 return;
567 }
568
569 AddCdm(cdm_id, key_system, security_origin);
570 }
571
572 void BrowserMediaPlayerManager::OnCreateSession(
573 int cdm_id,
574 uint32 session_id,
575 CdmHostMsg_CreateSession_ContentType content_type,
576 const std::vector<uint8>& init_data) {
577 if (init_data.size() > kMaxInitDataLength) {
578 LOG(WARNING) << "InitData for ID: " << cdm_id
579 << " too long: " << init_data.size();
580 OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
581 return;
582 }
583
584 // Convert the session content type into a MIME type. "audio" and "video"
585 // don't matter, so using "video" for the MIME type.
586 // Ref:
587 // https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypte d-media.html#dom-createsession
588 std::string mime_type;
589 switch (content_type) {
590 case CREATE_SESSION_TYPE_WEBM:
591 mime_type = "video/webm";
592 break;
593 case CREATE_SESSION_TYPE_MP4:
594 mime_type = "video/mp4";
595 break;
596 default:
597 NOTREACHED();
598 return;
599 }
600
601 if (CommandLine::ForCurrentProcess()
602 ->HasSwitch(switches::kDisableInfobarForProtectedMediaIdentifier)) {
603 CreateSessionIfPermitted(cdm_id, session_id, mime_type, init_data, true);
604 return;
605 }
606
607 BrowserCdm* cdm = GetCdm(cdm_id);
608 if (!cdm) {
609 DLOG(WARNING) << "No CDM for ID " << cdm_id << " found";
610 OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
611 return;
612 }
613
614 BrowserContext* context =
615 web_contents()->GetRenderProcessHost()->GetBrowserContext();
616
617 std::map<int, GURL>::const_iterator iter =
618 cdm_security_origin_map_.find(cdm_id);
619 if (iter == cdm_security_origin_map_.end()) {
620 NOTREACHED();
621 OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
622 return;
623 }
624
625 context->RequestProtectedMediaIdentifierPermission(
626 web_contents()->GetRenderProcessHost()->GetID(),
627 web_contents()->GetRenderViewHost()->GetRoutingID(),
628 iter->second,
629 base::Bind(&BrowserMediaPlayerManager::CreateSessionIfPermitted,
630 weak_ptr_factory_.GetWeakPtr(),
631 cdm_id,
632 session_id,
633 mime_type,
634 init_data));
635 }
636
637 void BrowserMediaPlayerManager::OnUpdateSession(
638 int cdm_id,
639 uint32 session_id,
640 const std::vector<uint8>& response) {
641 BrowserCdm* cdm = GetCdm(cdm_id);
642 if (!cdm) {
643 DLOG(WARNING) << "No CDM for ID " << cdm_id << " found";
644 OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
645 return;
646 }
647
648 if (response.size() > kMaxSessionResponseLength) {
649 LOG(WARNING) << "Response for ID " << cdm_id
650 << " is too long: " << response.size();
651 OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
652 return;
653 }
654
655 cdm->UpdateSession(session_id, &response[0], response.size());
656 }
657
658 void BrowserMediaPlayerManager::OnReleaseSession(int cdm_id,
659 uint32 session_id) {
660 BrowserCdm* cdm = GetCdm(cdm_id);
661 if (!cdm) {
662 DLOG(WARNING) << "No CDM for ID " << cdm_id << " found";
663 OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
664 return;
665 }
666
667 cdm->ReleaseSession(session_id);
668 }
669
670 void BrowserMediaPlayerManager::OnDestroyCdm(int cdm_id) {
671 BrowserCdm* cdm = GetCdm(cdm_id);
672 if (!cdm)
673 return;
674
675 CancelAllPendingSessionCreations(cdm_id);
676 RemoveCdm(cdm_id);
677 }
678
679 void BrowserMediaPlayerManager::CancelAllPendingSessionCreations(int cdm_id) {
680 BrowserContext* context =
681 web_contents()->GetRenderProcessHost()->GetBrowserContext();
682 std::map<int, GURL>::const_iterator iter =
683 cdm_security_origin_map_.find(cdm_id);
684 if (iter == cdm_security_origin_map_.end())
685 return;
686 context->CancelProtectedMediaIdentifierPermissionRequests(
687 web_contents()->GetRenderProcessHost()->GetID(),
688 web_contents()->GetRenderViewHost()->GetRoutingID(),
689 iter->second);
690 }
691
692 void BrowserMediaPlayerManager::AddPlayer(MediaPlayerAndroid* player) { 498 void BrowserMediaPlayerManager::AddPlayer(MediaPlayerAndroid* player) {
693 DCHECK(!GetPlayer(player->player_id())); 499 DCHECK(!GetPlayer(player->player_id()));
694 players_.push_back(player); 500 players_.push_back(player);
695 } 501 }
696 502
697 void BrowserMediaPlayerManager::RemovePlayer(int player_id) { 503 void BrowserMediaPlayerManager::RemovePlayer(int player_id) {
698 for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin(); 504 for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
699 it != players_.end(); ++it) { 505 it != players_.end(); ++it) {
700 MediaPlayerAndroid* player = *it; 506 MediaPlayerAndroid* player = *it;
701 if (player->player_id() == player_id) { 507 if (player->player_id() == player_id) {
(...skipping 11 matching lines...) Expand all
713 if ((*it)->player_id() == player_id) { 519 if ((*it)->player_id() == player_id) {
714 previous_player = *it; 520 previous_player = *it;
715 players_.weak_erase(it); 521 players_.weak_erase(it);
716 players_.push_back(player); 522 players_.push_back(player);
717 break; 523 break;
718 } 524 }
719 } 525 }
720 return scoped_ptr<media::MediaPlayerAndroid>(previous_player); 526 return scoped_ptr<media::MediaPlayerAndroid>(previous_player);
721 } 527 }
722 528
723 void BrowserMediaPlayerManager::AddCdm(int cdm_id,
724 const std::string& key_system,
725 const GURL& security_origin) {
726 DCHECK(!GetCdm(cdm_id));
727 base::WeakPtr<BrowserMediaPlayerManager> weak_this =
728 weak_ptr_factory_.GetWeakPtr();
729
730 int id = cdm_id;
731 scoped_ptr<BrowserCdm> cdm(media::CreateBrowserCdm(
732 key_system,
733 base::Bind(&BrowserMediaPlayerManager::OnSessionCreated, weak_this, id),
734 base::Bind(&BrowserMediaPlayerManager::OnSessionMessage, weak_this, id),
735 base::Bind(&BrowserMediaPlayerManager::OnSessionReady, weak_this, id),
736 base::Bind(&BrowserMediaPlayerManager::OnSessionClosed, weak_this, id),
737 base::Bind(&BrowserMediaPlayerManager::OnSessionError, weak_this, id)));
738
739 if (!cdm) {
740 // This failure will be discovered and reported by OnCreateSession()
741 // as GetCdm() will return null.
742 DVLOG(1) << "failed to create CDM.";
743 return;
744 }
745
746 cdm_map_[cdm_id] = cdm.release();
747 cdm_security_origin_map_[cdm_id] = security_origin;
748 }
749
750 void BrowserMediaPlayerManager::RemoveCdm(int cdm_id) {
751 // TODO(xhwang): Detach CDM from the player it's set to. In prefixed
752 // EME implementation the current code is fine because we always destroy the
753 // player before we destroy the DrmBridge. This will not always be the case
754 // in unprefixed EME implementation.
755 CdmMap::iterator iter = cdm_map_.find(cdm_id);
756 if (iter != cdm_map_.end()) {
757 delete iter->second;
758 cdm_map_.erase(iter);
759 }
760 cdm_security_origin_map_.erase(cdm_id);
761 }
762
763 void BrowserMediaPlayerManager::OnSetCdm(int player_id, int cdm_id) {
764 MediaPlayerAndroid* player = GetPlayer(player_id);
765 BrowserCdm* cdm = GetCdm(cdm_id);
766 // Currently we do not support detaching CDM from a player.
767 if (!cdm || !player) {
768 NOTREACHED() << "Cannot set CDM on the specified player.";
769 return;
770 }
771
772 // TODO(qinmin): add the logic to decide whether we should create the
773 // fullscreen surface for EME lv1.
774 player->SetCdm(cdm);
775 }
776
777 int BrowserMediaPlayerManager::RoutingID() { 529 int BrowserMediaPlayerManager::RoutingID() {
778 return render_frame_host_->GetRoutingID(); 530 return render_frame_host_->GetRoutingID();
779 } 531 }
780 532
781 bool BrowserMediaPlayerManager::Send(IPC::Message* msg) { 533 bool BrowserMediaPlayerManager::Send(IPC::Message* msg) {
782 return render_frame_host_->Send(msg); 534 return render_frame_host_->Send(msg);
783 } 535 }
784 536
785 void BrowserMediaPlayerManager::CreateSessionIfPermitted(
786 int cdm_id,
787 uint32 session_id,
788 const std::string& content_type,
789 const std::vector<uint8>& init_data,
790 bool permitted) {
791 if (!permitted) {
792 OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
793 return;
794 }
795
796 BrowserCdm* cdm = GetCdm(cdm_id);
797 if (!cdm) {
798 DLOG(WARNING) << "No CDM for ID: " << cdm_id << " found";
799 OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
800 return;
801 }
802
803 // This could fail, in which case a SessionError will be fired.
804 cdm->CreateSession(session_id, content_type, &init_data[0], init_data.size());
805 }
806
807 void BrowserMediaPlayerManager::ReleaseFullscreenPlayer( 537 void BrowserMediaPlayerManager::ReleaseFullscreenPlayer(
808 MediaPlayerAndroid* player) { 538 MediaPlayerAndroid* player) {
809 player->Release(); 539 player->Release();
810 } 540 }
811 541
812 void BrowserMediaPlayerManager::OnMediaResourcesRequested(int player_id) { 542 void BrowserMediaPlayerManager::OnMediaResourcesRequested(int player_id) {
813 int num_active_player = 0; 543 int num_active_player = 0;
814 ScopedVector<MediaPlayerAndroid>::iterator it; 544 ScopedVector<MediaPlayerAndroid>::iterator it;
815 for (it = players_.begin(); it != players_.end(); ++it) { 545 for (it = players_.begin(); it != players_.end(); ++it) {
816 if (!(*it)->IsPlayerReady()) 546 if (!(*it)->IsPlayerReady())
(...skipping 24 matching lines...) Expand all
841 #if defined(VIDEO_HOLE) 571 #if defined(VIDEO_HOLE)
842 MediaPlayerAndroid* player = GetPlayer(player_id); 572 MediaPlayerAndroid* player = GetPlayer(player_id);
843 if (player && player->IsSurfaceInUse()) 573 if (player && player->IsSurfaceInUse())
844 return; 574 return;
845 if (external_video_surface_container_) 575 if (external_video_surface_container_)
846 external_video_surface_container_->ReleaseExternalVideoSurface(player_id); 576 external_video_surface_container_->ReleaseExternalVideoSurface(player_id);
847 #endif // defined(VIDEO_HOLE) 577 #endif // defined(VIDEO_HOLE)
848 } 578 }
849 579
850 } // namespace content 580 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698