Skip to content

Commit

Permalink
Encrypted Media: Implement IPC based SetCdm().
Browse files Browse the repository at this point in the history
BUG=338910

Review URL: https://codereview.chromium.org/193523002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@260592 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
xhwang@chromium.org committed Mar 31, 2014
1 parent 9364154 commit 0727f76
Show file tree
Hide file tree
Showing 19 changed files with 157 additions and 39 deletions.
19 changes: 11 additions & 8 deletions content/browser/media/android/browser_media_player_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ bool BrowserMediaPlayerManager::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyMediaPlayer, OnDestroyPlayer)
IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyAllMediaPlayers,
DestroyAllMediaPlayers)
IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_SetCdm, OnSetCdm)
IPC_MESSAGE_HANDLER(CdmHostMsg_InitializeCdm, OnInitializeCdm)
IPC_MESSAGE_HANDLER(CdmHostMsg_CreateSession, OnCreateSession)
IPC_MESSAGE_HANDLER(CdmHostMsg_UpdateSession, OnUpdateSession)
Expand Down Expand Up @@ -522,10 +523,14 @@ void BrowserMediaPlayerManager::OnInitialize(

RenderProcessHostImpl* host = static_cast<RenderProcessHostImpl*>(
web_contents()->GetRenderProcessHost());
AddPlayer(CreateMediaPlayer(
MediaPlayerAndroid* player = CreateMediaPlayer(
type, player_id, url, first_party_for_cookies, demuxer_client_id,
host->GetBrowserContext()->IsOffTheRecord(), this,
host->browser_demuxer_android()));
host->browser_demuxer_android());
if (!player)
return;

AddPlayer(player);
}

void BrowserMediaPlayerManager::OnStart(int player_id) {
Expand Down Expand Up @@ -590,9 +595,6 @@ void BrowserMediaPlayerManager::OnInitializeCdm(int cdm_id,
}

AddDrmBridge(cdm_id, key_system, frame_url);
// In EME v0.1b MediaKeys lives in the media element. So the |cdm_id|
// is the same as the |player_id|.
OnSetMediaKeys(cdm_id, cdm_id);
}

void BrowserMediaPlayerManager::OnCreateSession(
Expand Down Expand Up @@ -781,13 +783,14 @@ void BrowserMediaPlayerManager::RemoveDrmBridge(int cdm_id) {
}
}

void BrowserMediaPlayerManager::OnSetMediaKeys(int player_id, int cdm_id) {
void BrowserMediaPlayerManager::OnSetCdm(int player_id, int cdm_id) {
MediaPlayerAndroid* player = GetPlayer(player_id);
MediaDrmBridge* drm_bridge = GetDrmBridge(cdm_id);
if (!player || !drm_bridge) {
DVLOG(1) << "OnSetMediaKeys(): Player and MediaKeys must be present.";
if (!drm_bridge || !player) {
DVLOG(1) << "Cannot set CDM on the specified player.";
return;
}

// TODO(qinmin): add the logic to decide whether we should create the
// fullscreen surface for EME lv1.
player->SetDrmBridge(drm_bridge);
Expand Down
5 changes: 2 additions & 3 deletions content/browser/media/android/browser_media_player_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#ifndef CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_MEDIA_PLAYER_MANAGER_H_
#define CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_MEDIA_PLAYER_MANAGER_H_

#include <map>
#include <set>
#include <string>
#include <vector>
Expand Down Expand Up @@ -147,7 +146,7 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
uint32 session_id,
const std::vector<uint8>& response);
void OnReleaseSession(int cdm_id, uint32 session_id);
void OnSetMediaKeys(int player_id, int cdm_id);
void OnSetCdm(int player_id, int cdm_id);
void OnDestroyCdm(int cdm_id);

// Cancels all pending session creations associated with |cdm_id|.
Expand Down Expand Up @@ -220,7 +219,7 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
// An array of managed media DRM bridges.
ScopedVector<media::MediaDrmBridge> drm_bridges_;

// a set of media keys IDs that are pending approval or approved to access
// A set of media keys IDs that are pending approval or approved to access
// device DRM credentials.
// These 2 sets does not cover all the EME videos. If a video only streams
// clear data, it will not be included in either set.
Expand Down
5 changes: 5 additions & 0 deletions content/common/media/media_player_messages_android.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,11 @@ IPC_MESSAGE_ROUTED1(MediaPlayerHostMsg_EnterFullscreen, int /* player_id */)
// Requests the player to exit fullscreen.
IPC_MESSAGE_ROUTED1(MediaPlayerHostMsg_ExitFullscreen, int /* player_id */)

// Requests the player with |player_id| to use the CDM with |cdm_id|.
IPC_MESSAGE_ROUTED2(MediaPlayerHostMsg_SetCdm,
int /* player_id */,
int /* cdm_id */);

// Sent after the renderer demuxer has seeked.
IPC_MESSAGE_CONTROL2(MediaPlayerHostMsg_DemuxerSeekDone,
int /* demuxer_client_id */,
Expand Down
10 changes: 8 additions & 2 deletions content/renderer/media/android/proxy_media_keys.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,18 @@

namespace content {

int ProxyMediaKeys::next_cdm_id_ =
RendererMediaPlayerManager::kInvalidCdmId + 1;

ProxyMediaKeys::ProxyMediaKeys(
RendererMediaPlayerManager* manager,
int cdm_id,
const media::SessionCreatedCB& session_created_cb,
const media::SessionMessageCB& session_message_cb,
const media::SessionReadyCB& session_ready_cb,
const media::SessionClosedCB& session_closed_cb,
const media::SessionErrorCB& session_error_cb)
: manager_(manager),
cdm_id_(cdm_id),
cdm_id_(next_cdm_id_++),
session_created_cb_(session_created_cb),
session_message_cb_(session_message_cb),
session_ready_cb_(session_ready_cb),
Expand Down Expand Up @@ -111,4 +113,8 @@ void ProxyMediaKeys::OnSessionError(uint32 session_id,
session_error_cb_.Run(session_id, error_code, system_code);
}

int ProxyMediaKeys::GetCdmId() const {
return cdm_id_;
}

} // namespace content
7 changes: 6 additions & 1 deletion content/renderer/media/android/proxy_media_keys.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ class RendererMediaPlayerManager;
class ProxyMediaKeys : public media::MediaKeys {
public:
ProxyMediaKeys(RendererMediaPlayerManager* proxy,
int cdm_id,
const media::SessionCreatedCB& session_created_cb,
const media::SessionMessageCB& session_message_cb,
const media::SessionReadyCB& session_ready_cb,
Expand Down Expand Up @@ -54,7 +53,13 @@ class ProxyMediaKeys : public media::MediaKeys {
media::MediaKeys::KeyError error_code,
uint32 system_code);

int GetCdmId() const;

private:
// CDM ID should be unique per renderer process.
// TODO(xhwang): Use uint32 to prevent undefined overflow behavior.
static int next_cdm_id_;

RendererMediaPlayerManager* manager_;
int cdm_id_;
media::SessionCreatedCB session_created_cb_;
Expand Down
11 changes: 11 additions & 0 deletions content/renderer/media/android/renderer_media_player_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -240,10 +240,17 @@ void RendererMediaPlayerManager::ExitFullscreen(int player_id) {
Send(new MediaPlayerHostMsg_ExitFullscreen(routing_id(), player_id));
}

void RendererMediaPlayerManager::SetCdm(int player_id, int cdm_id) {
if (cdm_id == kInvalidCdmId)
return;
Send(new MediaPlayerHostMsg_SetCdm(routing_id(), player_id, cdm_id));
}

void RendererMediaPlayerManager::InitializeCdm(int cdm_id,
ProxyMediaKeys* media_keys,
const std::string& key_system,
const GURL& frame_url) {
DCHECK_NE(cdm_id, kInvalidCdmId);
RegisterMediaKeys(cdm_id, media_keys);
Send(new CdmHostMsg_InitializeCdm(
routing_id(), cdm_id, key_system, frame_url));
Expand All @@ -254,6 +261,7 @@ void RendererMediaPlayerManager::CreateSession(
uint32 session_id,
CdmHostMsg_CreateSession_ContentType content_type,
const std::vector<uint8>& init_data) {
DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered.";
Send(new CdmHostMsg_CreateSession(
routing_id(), cdm_id, session_id, content_type, init_data));
}
Expand All @@ -262,15 +270,18 @@ void RendererMediaPlayerManager::UpdateSession(
int cdm_id,
uint32 session_id,
const std::vector<uint8>& response) {
DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered.";
Send(
new CdmHostMsg_UpdateSession(routing_id(), cdm_id, session_id, response));
}

void RendererMediaPlayerManager::ReleaseSession(int cdm_id, uint32 session_id) {
DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered.";
Send(new CdmHostMsg_ReleaseSession(routing_id(), cdm_id, session_id));
}

void RendererMediaPlayerManager::DestroyCdm(int cdm_id) {
DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered.";
Send(new CdmHostMsg_DestroyCdm(routing_id(), cdm_id));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ class WebMediaPlayerAndroid;
// RenderView.
class RendererMediaPlayerManager : public RenderViewObserver {
public:
static const int kInvalidCdmId = 0;

// Constructs a RendererMediaPlayerManager object for the |render_view|.
RendererMediaPlayerManager(RenderView* render_view);
virtual ~RendererMediaPlayerManager();
Expand Down Expand Up @@ -80,6 +82,11 @@ class RendererMediaPlayerManager : public RenderViewObserver {
// Requests the player to exit fullscreen.
void ExitFullscreen(int player_id);

// Requests the player with |player_id| to use the CDM with |cdm_id|.
// Does nothing if |cdm_id| is kInvalidCdmId.
// TODO(xhwang): Update this when we implement setCdm(0).
void SetCdm(int player_id, int cdm_id);

#if defined(VIDEO_HOLE)
// Requests an external surface for out-of-band compositing.
void RequestExternalSurface(int player_id, const gfx::RectF& geometry);
Expand Down
37 changes: 31 additions & 6 deletions content/renderer/media/android/webmediaplayer_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
#include "cc/layers/video_layer.h"
#include "content/public/common/content_client.h"
#include "content/public/renderer/render_frame.h"
#include "content/renderer/media/android/proxy_media_keys.h"
#include "content/renderer/media/android/renderer_demuxer_android.h"
#include "content/renderer/media/android/renderer_media_player_manager.h"
#include "content/renderer/media/crypto/key_systems.h"
#include "content/renderer/media/webcontentdecryptionmodule_impl.h"
#include "content/renderer/media/webmediaplayer_delegate.h"
#include "content/renderer/media/webmediaplayer_util.h"
#include "content/renderer/render_frame_impl.h"
Expand All @@ -31,6 +31,8 @@
#include "gpu/command_buffer/common/mailbox_holder.h"
#include "media/base/android/media_player_android.h"
#include "media/base/bind_to_current_loop.h"
// TODO(xhwang): Remove when we remove prefixed EME implementation.
#include "media/base/media_keys.h"
#include "media/base/media_switches.h"
#include "media/base/video_frame.h"
#include "net/base/mime_util.h"
Expand Down Expand Up @@ -106,6 +108,7 @@ WebMediaPlayerAndroid::WebMediaPlayerAndroid(
current_time_(0),
is_remote_(false),
media_log_(media_log),
web_cdm_(NULL),
weak_factory_(this) {
DCHECK(manager_);

Expand Down Expand Up @@ -1268,8 +1271,6 @@ WebMediaPlayerAndroid::GenerateKeyRequestInternal(
frame_,
#else
manager_,
player_id_, // TODO(xhwang): Use cdm_id when MediaKeys are
// separated from WebMediaPlayer.
#endif // defined(ENABLE_PEPPER_CDMS)
base::Bind(&WebMediaPlayerAndroid::OnKeyAdded,
weak_factory_.GetWeakPtr()),
Expand All @@ -1284,11 +1285,12 @@ WebMediaPlayerAndroid::GenerateKeyRequestInternal(
return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
}

if (proxy_decryptor_ && !decryptor_ready_cb_.is_null()) {
if (!decryptor_ready_cb_.is_null()) {
base::ResetAndReturn(&decryptor_ready_cb_)
.Run(proxy_decryptor_->GetDecryptor());
}

manager_->SetCdm(player_id_, proxy_decryptor_->GetCdmId());
current_key_system_ = key_system;
} else if (key_system != current_key_system_) {
return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
Expand Down Expand Up @@ -1388,6 +1390,24 @@ WebMediaPlayerAndroid::CancelKeyRequestInternal(const std::string& key_system,
return WebMediaPlayer::MediaKeyExceptionNoError;
}

void WebMediaPlayerAndroid::setContentDecryptionModule(
blink::WebContentDecryptionModule* cdm) {
DCHECK(main_thread_checker_.CalledOnValidThread());

// TODO(xhwang): Support setMediaKeys(0) if necessary: http://crbug.com/330324
if (!cdm)
return;

web_cdm_ = ToWebContentDecryptionModuleImpl(cdm);
if (!web_cdm_)
return;

if (!decryptor_ready_cb_.is_null())
base::ResetAndReturn(&decryptor_ready_cb_).Run(web_cdm_->GetDecryptor());

manager_->SetCdm(player_id_, web_cdm_->GetCdmId());
}

void WebMediaPlayerAndroid::OnKeyAdded(const std::string& session_id) {
EmeUMAHistogramCounts(current_key_system_, "KeyAdded", 1);

Expand Down Expand Up @@ -1476,13 +1496,18 @@ void WebMediaPlayerAndroid::SetDecryptorReadyCB(
// detail.
DCHECK(decryptor_ready_cb_.is_null());

// Mixed use of prefixed and unprefixed EME APIs is disallowed by Blink.
DCHECK(!proxy_decryptor_ || !web_cdm_);

if (proxy_decryptor_) {
decryptor_ready_cb.Run(proxy_decryptor_->GetDecryptor());
return;
}

// TODO(xhwang): Also notify |web_cdm_| when we implement
// setContentDecryptionModule(). See: http://crbug.com/224786
if (web_cdm_) {
decryptor_ready_cb.Run(web_cdm_->GetDecryptor());
return;
}

decryptor_ready_cb_ = decryptor_ready_cb;
}
Expand Down
18 changes: 15 additions & 3 deletions content/renderer/media/android/webmediaplayer_android.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class MessageLoopProxy;
}

namespace blink {
class WebContentDecryptionModule;
class WebFrame;
class WebURL;
}
Expand All @@ -53,8 +54,9 @@ class WebLayerImpl;
}

namespace content {
class WebMediaPlayerDelegate;
class RendererMediaPlayerManager;
class WebContentDecryptionModuleImpl;
class WebMediaPlayerDelegate;

// This class implements blink::WebMediaPlayer by keeping the android
// media player in the browser process. It listens to all the status changes
Expand Down Expand Up @@ -214,6 +216,8 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
virtual MediaKeyException cancelKeyRequest(
const blink::WebString& key_system,
const blink::WebString& session_id);
virtual void setContentDecryptionModule(
blink::WebContentDecryptionModule* cdm);

void OnKeyAdded(const std::string& session_id);
void OnKeyError(const std::string& session_id,
Expand Down Expand Up @@ -427,11 +431,19 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
// through GenerateKeyRequest() directly from WebKit.
std::string init_data_type_;

media::DecryptorReadyCB decryptor_ready_cb_;

// Manages decryption keys and decrypts encrypted frames.
scoped_ptr<ProxyDecryptor> proxy_decryptor_;

// Non-owned pointer to the CDM. Updated via calls to
// setContentDecryptionModule().
WebContentDecryptionModuleImpl* web_cdm_;

// This is only Used by Clear Key key system implementation, where a renderer
// side CDM will be used. This is similar to WebMediaPlayerImpl. For other key
// systems, a browser side CDM will be used and we set CDM by calling
// manager_->SetCdm() directly.
media::DecryptorReadyCB decryptor_ready_cb_;

// NOTE: Weak pointers must be invalidated before all other member variables.
base::WeakPtrFactory<WebMediaPlayerAndroid> weak_factory_;

Expand Down
Loading

0 comments on commit 0727f76

Please sign in to comment.