Commit 9a647fd4 authored by xhwang@chromium.org's avatar xhwang@chromium.org

Add PlayerTracker and BrowserCdm interfaces.

- PlayerTracker interface can be used by any CDM that needs to track media
  players. It can notify media players of new abailable key (to resume playback)
  or the destruction of the CDM.
- PlayerTrackerImpl is a simple implementation of PlayerTracker that can help
  any CDM to implement PlayerTracker interface.
- BrowserCdm is a common CDM interface for browser side CDMs.
- CdmFactory is renamed to BrowserCdmFactory.
- Now BrowserMediaPlayer only needs to call SetCdm() on the player and do not
  need to track CDM <-> player mapping.

TBR=damienv@chromium.org
BUG=373327
TEST=Existing test pages still work.

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@274470 0039d316-1c4b-4281-b951-d872f2087c98
parent bf10dc22
......@@ -28,9 +28,11 @@
#include "content/public/common/content_switches.h"
#include "media/base/android/media_player_bridge.h"
#include "media/base/android/media_source_player.h"
#include "media/base/cdm_factory.h"
#include "media/base/browser_cdm.h"
#include "media/base/browser_cdm_factory.h"
#include "media/base/media_switches.h"
using media::BrowserCdm;
using media::MediaKeys;
using media::MediaPlayerAndroid;
using media::MediaPlayerBridge;
......@@ -317,7 +319,7 @@ MediaPlayerAndroid* BrowserMediaPlayerManager::GetPlayer(int player_id) {
return NULL;
}
MediaKeys* BrowserMediaPlayerManager::GetCdm(int cdm_id) {
BrowserCdm* BrowserMediaPlayerManager::GetCdm(int cdm_id) {
CdmMap::const_iterator iter = cdm_map_.find(cdm_id);
return (iter == cdm_map_.end()) ? NULL : iter->second;
}
......@@ -376,11 +378,10 @@ void BrowserMediaPlayerManager::OnSessionClosed(int cdm_id, uint32 session_id) {
Send(new CdmMsg_SessionClosed(RoutingID(), cdm_id, session_id));
}
void BrowserMediaPlayerManager::OnSessionError(
int cdm_id,
uint32 session_id,
media::MediaKeys::KeyError error_code,
uint32 system_code) {
void BrowserMediaPlayerManager::OnSessionError(int cdm_id,
uint32 session_id,
MediaKeys::KeyError error_code,
uint32 system_code) {
Send(new CdmMsg_SessionError(
RoutingID(), cdm_id, session_id, error_code, system_code));
}
......@@ -576,7 +577,7 @@ void BrowserMediaPlayerManager::OnCreateSession(
if (init_data.size() > kMaxInitDataLength) {
LOG(WARNING) << "InitData for ID: " << cdm_id
<< " too long: " << init_data.size();
OnSessionError(cdm_id, session_id, media::MediaKeys::kUnknownError, 0);
OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
return;
}
......@@ -603,10 +604,10 @@ void BrowserMediaPlayerManager::OnCreateSession(
return;
}
MediaKeys* cdm = GetCdm(cdm_id);
BrowserCdm* cdm = GetCdm(cdm_id);
if (!cdm) {
DLOG(WARNING) << "No CDM for ID " << cdm_id << " found";
OnSessionError(cdm_id, session_id, media::MediaKeys::kUnknownError, 0);
OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
return;
}
......@@ -617,7 +618,7 @@ void BrowserMediaPlayerManager::OnCreateSession(
cdm_security_origin_map_.find(cdm_id);
if (iter == cdm_security_origin_map_.end()) {
NOTREACHED();
OnSessionError(cdm_id, session_id, media::MediaKeys::kUnknownError, 0);
OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
return;
}
......@@ -637,38 +638,29 @@ void BrowserMediaPlayerManager::OnUpdateSession(
int cdm_id,
uint32 session_id,
const std::vector<uint8>& response) {
MediaKeys* cdm = GetCdm(cdm_id);
BrowserCdm* cdm = GetCdm(cdm_id);
if (!cdm) {
DLOG(WARNING) << "No CDM for ID " << cdm_id << " found";
OnSessionError(cdm_id, session_id, media::MediaKeys::kUnknownError, 0);
OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
return;
}
if (response.size() > kMaxSessionResponseLength) {
LOG(WARNING) << "Response for ID " << cdm_id
<< " is too long: " << response.size();
OnSessionError(cdm_id, session_id, media::MediaKeys::kUnknownError, 0);
OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
return;
}
cdm->UpdateSession(session_id, &response[0], response.size());
CdmToPlayerMap::const_iterator iter = cdm_to_player_map_.find(cdm_id);
if (iter == cdm_to_player_map_.end())
return;
int player_id = iter->second;
MediaPlayerAndroid* player = GetPlayer(player_id);
if (player)
player->OnKeyAdded();
}
void BrowserMediaPlayerManager::OnReleaseSession(int cdm_id,
uint32 session_id) {
MediaKeys* cdm = GetCdm(cdm_id);
BrowserCdm* cdm = GetCdm(cdm_id);
if (!cdm) {
DLOG(WARNING) << "No CDM for ID " << cdm_id << " found";
OnSessionError(cdm_id, session_id, media::MediaKeys::kUnknownError, 0);
OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
return;
}
......@@ -676,7 +668,7 @@ void BrowserMediaPlayerManager::OnReleaseSession(int cdm_id,
}
void BrowserMediaPlayerManager::OnDestroyCdm(int cdm_id) {
MediaKeys* cdm = GetCdm(cdm_id);
BrowserCdm* cdm = GetCdm(cdm_id);
if (!cdm)
return;
......@@ -711,15 +703,6 @@ void BrowserMediaPlayerManager::RemovePlayer(int player_id) {
break;
}
}
for (CdmToPlayerMap::iterator it = cdm_to_player_map_.begin();
it != cdm_to_player_map_.end();
++it) {
if (it->second == player_id) {
cdm_to_player_map_.erase(it);
break;
}
}
}
scoped_ptr<media::MediaPlayerAndroid> BrowserMediaPlayerManager::SwapPlayer(
......@@ -744,18 +727,14 @@ void BrowserMediaPlayerManager::AddCdm(int cdm_id,
base::WeakPtr<BrowserMediaPlayerManager> weak_this =
weak_ptr_factory_.GetWeakPtr();
scoped_ptr<MediaKeys> cdm(media::CreateBrowserCdm(
int id = cdm_id;
scoped_ptr<BrowserCdm> cdm(media::CreateBrowserCdm(
key_system,
base::Bind(
&BrowserMediaPlayerManager::OnSessionCreated, weak_this, cdm_id),
base::Bind(
&BrowserMediaPlayerManager::OnSessionMessage, weak_this, cdm_id),
base::Bind(
&BrowserMediaPlayerManager::OnSessionReady, weak_this, cdm_id),
base::Bind(
&BrowserMediaPlayerManager::OnSessionClosed, weak_this, cdm_id),
base::Bind(
&BrowserMediaPlayerManager::OnSessionError, weak_this, cdm_id)));
base::Bind(&BrowserMediaPlayerManager::OnSessionCreated, weak_this, id),
base::Bind(&BrowserMediaPlayerManager::OnSessionMessage, weak_this, id),
base::Bind(&BrowserMediaPlayerManager::OnSessionReady, weak_this, id),
base::Bind(&BrowserMediaPlayerManager::OnSessionClosed, weak_this, id),
base::Bind(&BrowserMediaPlayerManager::OnSessionError, weak_this, id)));
if (!cdm) {
// This failure will be discovered and reported by OnCreateSession()
......@@ -778,29 +757,21 @@ void BrowserMediaPlayerManager::RemoveCdm(int cdm_id) {
delete iter->second;
cdm_map_.erase(iter);
}
cdm_to_player_map_.erase(cdm_id);
cdm_security_origin_map_.erase(cdm_id);
}
void BrowserMediaPlayerManager::OnSetCdm(int player_id, int cdm_id) {
MediaPlayerAndroid* player = GetPlayer(player_id);
MediaKeys* cdm = GetCdm(cdm_id);
BrowserCdm* cdm = GetCdm(cdm_id);
// Currently we do not support detaching CDM from a player.
if (!cdm || !player) {
DVLOG(1) << "Cannot set CDM on the specified player.";
NOTREACHED() << "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->SetCdm(cdm);
// Do now support setting one CDM on multiple players.
if (ContainsKey(cdm_to_player_map_, cdm_id)) {
DVLOG(1) << "CDM is already set on another player.";
return;
}
cdm_to_player_map_[cdm_id] = player_id;
}
int BrowserMediaPlayerManager::RoutingID() {
......@@ -818,14 +789,14 @@ void BrowserMediaPlayerManager::CreateSessionIfPermitted(
const std::vector<uint8>& init_data,
bool permitted) {
if (!permitted) {
OnSessionError(cdm_id, session_id, media::MediaKeys::kUnknownError, 0);
OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
return;
}
MediaKeys* cdm = GetCdm(cdm_id);
BrowserCdm* cdm = GetCdm(cdm_id);
if (!cdm) {
DLOG(WARNING) << "No CDM for ID: " << cdm_id << " found";
OnSessionError(cdm_id, session_id, media::MediaKeys::kUnknownError, 0);
OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
return;
}
......
......@@ -26,8 +26,8 @@
#include "url/gurl.h"
namespace media {
class BrowserCdm;
class DemuxerAndroid;
class MediaKeys;
}
namespace content {
......@@ -91,7 +91,7 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
virtual media::MediaResourceGetter* GetMediaResourceGetter() OVERRIDE;
virtual media::MediaPlayerAndroid* GetFullscreenPlayer() OVERRIDE;
virtual media::MediaPlayerAndroid* GetPlayer(int player_id) OVERRIDE;
virtual media::MediaKeys* GetCdm(int cdm_id) OVERRIDE;
virtual media::BrowserCdm* GetCdm(int cdm_id) OVERRIDE;
virtual void DestroyAllMediaPlayers() OVERRIDE;
virtual void RequestFullScreen(int player_id) OVERRIDE;
virtual void OnSessionCreated(int cdm_id,
......@@ -229,16 +229,9 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
ScopedVector<media::MediaPlayerAndroid> players_;
// A map from CDM IDs to managed CDMs.
typedef std::map<int, media::MediaKeys*> CdmMap;
typedef std::map<int, media::BrowserCdm*> CdmMap;
CdmMap cdm_map_;
// Map from CDM ID to MediaPlayerAndroid player ID to indicate that
// the CDM is set on the MediaPlayerAndroid object.
// TODO(xhwang): Register a callback in the CDM to resume playback so that we
// can remove this map. See http://crbug.com/373327
typedef std::map<int, int> CdmToPlayerMap;
CdmToPlayerMap cdm_to_player_map_;
// Map from CDM ID to CDM's security origin.
std::map<int, GURL> cdm_security_origin_map_;
......
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/base/cdm_factory.h"
#include "media/base/browser_cdm_factory.h"
#include "base/command_line.h"
#include "base/logging.h"
......@@ -12,7 +12,7 @@
namespace media {
scoped_ptr<MediaKeys> CreateBrowserCdm(
scoped_ptr<BrowserCdm> CreateBrowserCdm(
const std::string& key_system,
const SessionCreatedCB& session_created_cb,
const SessionMessageCB& session_message_cb,
......@@ -21,7 +21,7 @@ scoped_ptr<MediaKeys> CreateBrowserCdm(
const SessionErrorCB& session_error_cb) {
if (!MediaDrmBridge::IsKeySystemSupported(key_system)) {
NOTREACHED() << "Unsupported key system: " << key_system;
return scoped_ptr<MediaKeys>();
return scoped_ptr<BrowserCdm>();
}
scoped_ptr<MediaDrmBridge> cdm(MediaDrmBridge::Create(key_system,
......@@ -32,7 +32,7 @@ scoped_ptr<MediaKeys> CreateBrowserCdm(
session_error_cb));
if (!cdm) {
NOTREACHED() << "MediaDrmBridge cannot be created for " << key_system;
return scoped_ptr<MediaKeys>();
return scoped_ptr<BrowserCdm>();
}
// TODO(xhwang/ddorwin): Pass the security level from key system.
......@@ -44,10 +44,10 @@ scoped_ptr<MediaKeys> CreateBrowserCdm(
}
if (!cdm->SetSecurityLevel(security_level)) {
DVLOG(1) << "failed to set security level " << security_level;
return scoped_ptr<MediaKeys>();
return scoped_ptr<BrowserCdm>();
}
return cdm.PassAs<MediaKeys>();
return cdm.PassAs<BrowserCdm>();
}
} // namespace media
......@@ -311,6 +311,7 @@ MediaDrmBridge::MediaDrmBridge(const std::vector<uint8>& scheme_uuid,
MediaDrmBridge::~MediaDrmBridge() {
JNIEnv* env = AttachCurrentThread();
player_tracker_.NotifyCdmUnset();
if (!j_media_drm_.is_null())
Java_MediaDrmBridge_release(env, j_media_drm_.obj());
}
......@@ -422,6 +423,10 @@ void MediaDrmBridge::UpdateSession(uint32 session_id,
base::android::ToJavaByteArray(env, response, response_length);
Java_MediaDrmBridge_updateSession(
env, j_media_drm_.obj(), session_id, j_response.obj());
// TODO(xhwang/jrummell): Move this when usableKeyIds/keyschange are
// implemented.
player_tracker_.NotifyNewKey();
}
void MediaDrmBridge::ReleaseSession(uint32 session_id) {
......@@ -434,6 +439,15 @@ void MediaDrmBridge::ReleaseSession(uint32 session_id) {
Java_MediaDrmBridge_releaseSession(env, j_media_drm_.obj(), session_id);
}
int MediaDrmBridge::RegisterPlayer(const base::Closure& new_key_cb,
const base::Closure& cdm_unset_cb) {
return player_tracker_.RegisterPlayer(new_key_cb, cdm_unset_cb);
}
void MediaDrmBridge::UnregisterPlayer(int registration_id) {
player_tracker_.UnregisterPlayer(registration_id);
}
void MediaDrmBridge::SetMediaCryptoReadyCB(const base::Closure& closure) {
if (closure.is_null()) {
media_crypto_ready_cb_.Reset();
......
......@@ -12,8 +12,9 @@
#include "base/android/scoped_java_ref.h"
#include "base/callback.h"
#include "base/memory/scoped_ptr.h"
#include "media/base/browser_cdm.h"
#include "media/base/media_export.h"
#include "media/base/media_keys.h"
#include "media/cdm/player_tracker_impl.h"
#include "url/gurl.h"
class GURL;
......@@ -24,7 +25,7 @@ class MediaPlayerManager;
// This class provides DRM services for android EME implementation.
// TODO(qinmin): implement all the functions in this class.
class MEDIA_EXPORT MediaDrmBridge : public MediaKeys {
class MEDIA_EXPORT MediaDrmBridge : public BrowserCdm {
public:
enum SecurityLevel {
SECURITY_LEVEL_NONE = 0,
......@@ -88,7 +89,7 @@ class MEDIA_EXPORT MediaDrmBridge : public MediaKeys {
// object. Calling this function multiples times may cause errors.
bool SetSecurityLevel(SecurityLevel security_level);
// MediaKeys implementations.
// BrowserCdm implementations.
virtual bool CreateSession(uint32 session_id,
const std::string& content_type,
const uint8* init_data,
......@@ -99,6 +100,9 @@ class MEDIA_EXPORT MediaDrmBridge : public MediaKeys {
const uint8* response,
int response_length) OVERRIDE;
virtual void ReleaseSession(uint32 session_id) OVERRIDE;
virtual int RegisterPlayer(const base::Closure& new_key_cb,
const base::Closure& cdm_unset_cb) OVERRIDE;
virtual void UnregisterPlayer(int registration_id) OVERRIDE;
// Returns a MediaCrypto object if it's already created. Returns a null object
// otherwise.
......@@ -163,6 +167,8 @@ class MEDIA_EXPORT MediaDrmBridge : public MediaKeys {
ResetCredentialsCB reset_credentials_cb_;
PlayerTrackerImpl player_tracker_;
DISALLOW_COPY_AND_ASSIGN(MediaDrmBridge);
};
......
......@@ -6,7 +6,6 @@
#include "base/logging.h"
#include "media/base/android/media_player_manager.h"
#include "media/base/media_keys.h"
namespace media {
......@@ -31,13 +30,9 @@ GURL MediaPlayerAndroid::GetFirstPartyForCookies() {
return GURL();
}
void MediaPlayerAndroid::SetCdm(MediaKeys* cdm) {
// Not all players support CDMs. Do nothing by default.
return;
}
void MediaPlayerAndroid::OnKeyAdded() {
// Not all players care about the decryption key. Do nothing by default.
void MediaPlayerAndroid::SetCdm(BrowserCdm* /* cdm */) {
// Players that support EME should override this.
NOTREACHED() << "EME not supported on base MediaPlayerAndroid class.";
return;
}
......
......@@ -16,7 +16,7 @@
namespace media {
class MediaKeys;
class BrowserCdm;
class MediaPlayerManager;
// This class serves as the base class for different media player
......@@ -74,11 +74,7 @@ class MEDIA_EXPORT MediaPlayerAndroid {
virtual GURL GetFirstPartyForCookies();
// Associates the |cdm| with this player.
virtual void SetCdm(MediaKeys* cdm);
// Notifies the player that a decryption key has been added. The player
// may want to start/resume playback if it is waiting for a key.
virtual void OnKeyAdded();
virtual void SetCdm(BrowserCdm* cdm);
// Check whether the player still uses the current surface.
virtual bool IsSurfaceInUse() const = 0;
......
......@@ -19,7 +19,7 @@ class GURL;
namespace media {
class MediaKeys;
class BrowserCdm;
class MediaPlayerAndroid;
class MediaResourceGetter;
......@@ -75,7 +75,7 @@ class MEDIA_EXPORT MediaPlayerManager {
virtual void DestroyAllMediaPlayers() = 0;
// Get the CDM for the given CDM ID.
virtual MediaKeys* GetCdm(int cdm_id) = 0;
virtual BrowserCdm* GetCdm(int cdm_id) = 0;
// Called by the player to get a hardware protected surface.
virtual void RequestFullScreen(int player_id) = 0;
......@@ -105,7 +105,7 @@ class MEDIA_EXPORT MediaPlayerManager {
// Called when CDM wants to send an Error event.
virtual void OnSessionError(int cdm_id,
uint32 session_id,
media::MediaKeys::KeyError error_code,
MediaKeys::KeyError error_code,
uint32 system_code) = 0;
};
......
......@@ -54,16 +54,23 @@ MediaSourcePlayer::MediaSourcePlayer(
reconfig_audio_decoder_(false),
reconfig_video_decoder_(false),
drm_bridge_(NULL),
cdm_registration_id_(0),
is_waiting_for_key_(false),
has_pending_audio_data_request_(false),
has_pending_video_data_request_(false),
weak_factory_(this) {
demuxer_->Initialize(this);
clock_.SetMaxTime(base::TimeDelta());
weak_this_ = weak_factory_.GetWeakPtr();
}
MediaSourcePlayer::~MediaSourcePlayer() {
Release();
DCHECK_EQ(!drm_bridge_, !cdm_registration_id_);
if (drm_bridge_) {
drm_bridge_->UnregisterPlayer(cdm_registration_id_);
cdm_registration_id_ = 0;
}
}
void MediaSourcePlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) {
......@@ -239,16 +246,6 @@ void MediaSourcePlayer::SetVolume(double volume) {
SetVolumeInternal();
}
void MediaSourcePlayer::OnKeyAdded() {
DVLOG(1) << __FUNCTION__;
if (!is_waiting_for_key_)
return;
is_waiting_for_key_ = false;
if (playing_)
StartInternal();
}
bool MediaSourcePlayer::IsSurfaceInUse() const {
return is_surface_in_use_;
}
......@@ -355,7 +352,7 @@ void MediaSourcePlayer::OnMediaCryptoReady() {
StartInternal();
}
void MediaSourcePlayer::SetCdm(MediaKeys* cdm) {
void MediaSourcePlayer::SetCdm(BrowserCdm* cdm) {
// Currently we don't support DRM change during the middle of playback, even
// if the player is paused.
// TODO(qinmin): support DRM change after playback has started.
......@@ -365,12 +362,21 @@ void MediaSourcePlayer::SetCdm(MediaKeys* cdm) {
<< "This is not well supported!";
}
if (drm_bridge_) {
NOTREACHED() << "Currently we do not support resetting CDM.";
return;
}
// Only MediaDrmBridge will be set on MediaSourcePlayer.
drm_bridge_ = static_cast<MediaDrmBridge*>(cdm);
cdm_registration_id_ = drm_bridge_->RegisterPlayer(
base::Bind(&MediaSourcePlayer::OnKeyAdded, weak_this_),
base::Bind(&MediaSourcePlayer::OnCdmUnset, weak_this_));
if (drm_bridge_->GetMediaCrypto().is_null()) {
drm_bridge_->SetMediaCryptoReadyCB(base::Bind(
&MediaSourcePlayer::OnMediaCryptoReady, weak_factory_.GetWeakPtr()));
drm_bridge_->SetMediaCryptoReadyCB(
base::Bind(&MediaSourcePlayer::OnMediaCryptoReady, weak_this_));
return;
}
......@@ -524,10 +530,8 @@ void MediaSourcePlayer::ProcessPendingEvents() {
return;
SetPendingEvent(PREFETCH_DONE_EVENT_PENDING);
base::Closure barrier =
BarrierClosure(count,
base::Bind(&MediaSourcePlayer::OnPrefetchDone,
weak_factory_.GetWeakPtr()));
base::Closure barrier = BarrierClosure(
count, base::Bind(&MediaSourcePlayer::OnPrefetchDone, weak_this_));
if (!AudioFinished())
audio_decoder_job_->Prefetch(barrier);
......@@ -655,9 +659,7 @@ void MediaSourcePlayer::DecodeMoreAudio() {
scoped_ptr<DemuxerConfigs> configs(audio_decoder_job_->Decode(
start_time_ticks_,
start_presentation_timestamp_,
base::Bind(&MediaSourcePlayer::MediaDecoderCallback,
weak_factory_.GetWeakPtr(),
true)));
base::Bind(&MediaSourcePlayer::MediaDecoderCallback, weak_this_, true)));
if (!configs) {
TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreAudio",
audio_decoder_job_.get());
......@@ -687,9 +689,7 @@ void MediaSourcePlayer::DecodeMoreVideo() {
scoped_ptr<DemuxerConfigs> configs(video_decoder_job_->Decode(
start_time_ticks_,
start_presentation_timestamp_,
base::Bind(&MediaSourcePlayer::MediaDecoderCallback,
weak_factory_.GetWeakPtr(),
false)));
base::Bind(&MediaSourcePlayer::MediaDecoderCallback, weak_this_, false)));
if (!configs) {
TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreVideo",
video_decoder_job_.get());
......@@ -914,8 +914,8 @@ void MediaSourcePlayer::StartStarvationCallback(
timeout = std::max(timeout, kMinStarvationTimeout);
decoder_starvation_callback_.Reset(base::Bind(
&MediaSourcePlayer::OnDecoderStarved, weak_factory_.GetWeakPtr()));
decoder_starvation_callback_.Reset(
base::Bind(&MediaSourcePlayer::OnDecoderStarved, weak_this_));
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE, decoder_starvation_callback_.callback(), timeout);
}
......@@ -1022,4 +1022,23 @@ void MediaSourcePlayer::SetDemuxerConfigs(const DemuxerConfigs& configs,
}
}
void MediaSourcePlayer::OnKeyAdded() {
DVLOG(1) << __FUNCTION__;
if (!is_waiting_for_key_)
return;
is_waiting_for_key_ = false;
if (playing_)
StartInternal();
}
void MediaSourcePlayer::OnCdmUnset() {
DVLOG(1) << __FUNCTION__;
DCHECK(drm_bridge_);
// TODO(xhwang): Support detachment of CDM. This will be needed when we start
// to support setMediaKeys(0), or when we release MediaDrm when the video is
// paused, or when the device goes to sleep. See http://crbug.com/272421
DVLOG(1) << "CDM detachment not supported.";
}
} // namespace media
......@@ -61,8 +61,7 @@ class MEDIA_EXPORT MediaSourcePlayer : public MediaPlayerAndroid,
virtual bool CanSeekForward() OVERRIDE;
virtual bool CanSeekBackward() OVERRIDE;
virtual bool IsPlayerReady() OVERRIDE;
virtual void SetCdm(MediaKeys* cdm) OVERRIDE;
virtual void OnKeyAdded() OVERRIDE;
virtual void SetCdm(BrowserCdm* cdm) OVERRIDE;
virtual bool IsSurfaceInUse() const OVERRIDE;
// DemuxerAndroidClient implementation.
......@@ -171,6 +170,12 @@ class MEDIA_EXPORT MediaSourcePlayer : public MediaPlayerAndroid,
// Sets the demuxer configs for audio or video stream.
void SetDemuxerConfigs(const DemuxerConfigs& configs, bool is_audio);
// Called when new decryption key becomes available.
void OnKeyAdded();
// Called when the CDM is detached.
void OnCdmUnset();
// Test-only method to setup hook for the completion of the next decode cycle.
// This callback state is cleared when it is next run.
// Prevent usage creep by only calling this from the
......@@ -273,6 +278,7 @@ class MEDIA_EXPORT MediaSourcePlayer : public MediaPlayerAndroid,
base::CancelableClosure decoder_starvation_callback_;
MediaDrmBridge* drm_bridge_;
int cdm_registration_id_;
// No decryption key available to decrypt the encrypted buffer. In this case,
// the player should pause. When a new key is added (OnKeyAdded()), we should
......@@ -292,6 +298,7 @@ class MEDIA_EXPORT MediaSourcePlayer : public MediaPlayerAndroid,
// Weak pointer passed to media decoder jobs for callbacks.
// NOTE: Weak pointers must be invalidated before all other member variables.
base::WeakPtrFactory<MediaSourcePlayer> weak_factory_;
base::WeakPtr<MediaSourcePlayer> weak_this_;
DISALLOW_COPY_AND_ASSIGN(MediaSourcePlayer);
};
......
......@@ -72,7 +72,7 @@ class MockMediaPlayerManager : public MediaPlayerManager {
virtual MediaPlayerAndroid* GetFullscreenPlayer() OVERRIDE { return NULL; }
virtual MediaPlayerAndroid* GetPlayer(int player_id) OVERRIDE { return NULL; }
virtual void DestroyAllMediaPlayers() OVERRIDE {}
virtual MediaKeys* GetCdm(int cdm_id) OVERRIDE { return NULL; }
virtual BrowserCdm* GetCdm(int cdm_id) OVERRIDE { return NULL; }
virtual void RequestFullScreen(int player_id) OVERRIDE {}
virtual void OnSessionCreated(int cdm_id,
uint32 session_id,
......@@ -85,7 +85,7 @@ class MockMediaPlayerManager : public MediaPlayerManager {
virtual void OnSessionClosed(int cdm_id, uint32 session_id) OVERRIDE {}
virtual void OnSessionError(int cdm_id,
uint32 session_id,
media::MediaKeys::KeyError error_code,
MediaKeys::KeyError error_code,
uint32 system_code) OVERRIDE {}
bool playback_completed() const {
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/base/browser_cdm.h"
namespace media {
BrowserCdm::BrowserCdm() {
}
BrowserCdm::~BrowserCdm() {
}
} // namespace media
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_BASE_BROWSER_CDM_H_
#define MEDIA_BASE_BROWSER_CDM_H_
#include "media/base/media_keys.h"
#include "media/base/player_tracker.h"
namespace media {
// Interface for browser side CDMs.
class BrowserCdm : public MediaKeys, public PlayerTracker {
public:
virtual ~BrowserCdm();
// MediaKeys implementation.
virtual bool CreateSession(uint32 session_id,
const std::string& content_type,
const uint8* init_data,
int init_data_length) = 0;
virtual void LoadSession(uint32 session_id,
const std::string& web_session_id) = 0;
virtual void UpdateSession(uint32 session_id,
const uint8* response,
int response_length) = 0;
virtual void ReleaseSession(uint32 session_id) = 0;
// PlayerTracker implementation.
virtual int RegisterPlayer(const base::Closure& new_key_cb,
const base::Closure& cdm_unset_cb) = 0;
virtual void UnregisterPlayer(int registration_id) = 0;
protected:
BrowserCdm();
private:
DISALLOW_COPY_AND_ASSIGN(BrowserCdm);
};
} // namespace media
#endif // MEDIA_BASE_BROWSER_CDM_H_
......@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_BASE_CDM_FACTORY_H_
#define MEDIA_BASE_CDM_FACTORY_H_
#ifndef MEDIA_BASE_BROWSER_CDM_FACTORY_H_
#define MEDIA_BASE_BROWSER_CDM_FACTORY_H_
#include <string>
......@@ -13,9 +13,12 @@
namespace media {
// Creates a CDM for |key_system|. Returns NULL if the CDM cannot be created.
class BrowserCdm;
// Creates a BrowserCdm for |key_system|. Returns NULL if the CDM cannot be
// created.
// TODO(xhwang): Add ifdef for IPC based CDM.
scoped_ptr<MediaKeys> MEDIA_EXPORT
scoped_ptr<BrowserCdm> MEDIA_EXPORT
CreateBrowserCdm(const std::string& key_system,
const SessionCreatedCB& session_created_cb,
const SessionMessageCB& session_message_cb,
......@@ -25,4 +28,4 @@ scoped_ptr<MediaKeys> MEDIA_EXPORT
} // namespace media
#endif // MEDIA_BASE_CDM_FACTORY_H_
#endif // MEDIA_BASE_BROWSER_CDM_FACTORY_H_
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/base/player_tracker.h"
namespace media {
PlayerTracker::PlayerTracker() {
}
PlayerTracker::~PlayerTracker() {
}
} // namespace media
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_BASE_PLAYER_TRACKER_H_
#define MEDIA_BASE_PLAYER_TRACKER_H_
#include "base/basictypes.h"
#include "base/callback.h"
#include "media/base/media_export.h"
namespace media {
// An interface for players to register to be notified when a new decryption key
// becomes available or when the CDM is unset.
class MEDIA_EXPORT PlayerTracker {
public:
virtual ~PlayerTracker();
// Registers player callbacks with the CDM.
// - |new_key_cb| is fired when a new decryption key becomes available.
// - |cdm_unset_cb| is fired when the CDM is detached from the player.
// Returns a registration ID which can be used to unregister a player.
virtual int RegisterPlayer(const base::Closure& new_key_cb,
const base::Closure& cdm_unset_cb) = 0;
// Unregisters a previously registered player. This should be called when
// the CDM is detached from the player (e.g. setMediaKeys(0)), or when the
// player is destroyed.
virtual void UnregisterPlayer(int registration_id) = 0;
protected:
PlayerTracker();
private:
DISALLOW_COPY_AND_ASSIGN(PlayerTracker);
};
} // namespace media
#endif // MEDIA_BASE_PLAYER_TRACKER_H_
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/cdm/player_tracker_impl.h"
#include <utility>
#include "base/stl_util.h"
namespace media {
PlayerTrackerImpl::PlayerCallbacks::PlayerCallbacks(
base::Closure new_key_cb,
base::Closure cdm_unset_cb)
: new_key_cb(new_key_cb), cdm_unset_cb(cdm_unset_cb) {
}
PlayerTrackerImpl::PlayerCallbacks::~PlayerCallbacks() {
}
PlayerTrackerImpl::PlayerTrackerImpl() : next_registration_id_(1) {}
PlayerTrackerImpl::~PlayerTrackerImpl() {}
int PlayerTrackerImpl::RegisterPlayer(const base::Closure& new_key_cb,
const base::Closure& cdm_unset_cb) {
DCHECK(thread_checker_.CalledOnValidThread());
int registration_id = next_registration_id_++;
DCHECK(!ContainsKey(player_callbacks_map_, registration_id));
player_callbacks_map_.insert(std::make_pair(
registration_id, PlayerCallbacks(new_key_cb, cdm_unset_cb)));
return registration_id;
}
void PlayerTrackerImpl::UnregisterPlayer(int registration_id) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(ContainsKey(player_callbacks_map_, registration_id))
<< registration_id;
player_callbacks_map_.erase(registration_id);
}
void PlayerTrackerImpl::NotifyNewKey() {
DCHECK(thread_checker_.CalledOnValidThread());
std::map<int, PlayerCallbacks>::iterator iter = player_callbacks_map_.begin();
for (; iter != player_callbacks_map_.end(); ++iter)
iter->second.new_key_cb.Run();
}
void PlayerTrackerImpl::NotifyCdmUnset() {
DCHECK(thread_checker_.CalledOnValidThread());
std::map<int, PlayerCallbacks>::iterator iter = player_callbacks_map_.begin();
for (; iter != player_callbacks_map_.end(); ++iter)
iter->second.cdm_unset_cb.Run();
}
} // namespace media
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_CDM_PLAYER_TRACKER_IMPL_H_
#define MEDIA_CDM_PLAYER_TRACKER_IMPL_H_
#include <map>
#include "base/basictypes.h"
#include "base/callback.h"
#include "base/threading/thread_checker.h"
#include "media/base/media_export.h"
#include "media/base/player_tracker.h"
namespace media {
// A common implementation that can be shared by different PlayerTracker
// implementations. This class is not thread safe and should only be called
// on one thread.
class MEDIA_EXPORT PlayerTrackerImpl : public PlayerTracker {
public:
PlayerTrackerImpl();
virtual ~PlayerTrackerImpl();
// PlayerTracker implementation.
virtual int RegisterPlayer(const base::Closure& new_key_cb,
const base::Closure& cdm_unset_cb) OVERRIDE;
virtual void UnregisterPlayer(int registration_id) OVERRIDE;
// Helpers methods to fire registered callbacks.
void NotifyNewKey();
void NotifyCdmUnset();
private:
struct PlayerCallbacks {
PlayerCallbacks(base::Closure new_key_cb, base::Closure cdm_unset_cb);
~PlayerCallbacks();
base::Closure new_key_cb;
base::Closure cdm_unset_cb;
};
int next_registration_id_;
std::map<int, PlayerCallbacks> player_callbacks_map_;
base::ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(PlayerTrackerImpl);
};
} // namespace media
#endif // MEDIA_CDM_PLAYER_TRACKER_IMPL_H_
......@@ -298,6 +298,8 @@
'base/pipeline.cc',
'base/pipeline.h',
'base/pipeline_status.h',
'base/player_tracker.cc',
'base/player_tracker.h',
'base/ranges.cc',
'base/ranges.h',
'base/sample_format.cc',
......@@ -355,6 +357,8 @@
'cdm/json_web_key.h',
'cdm/key_system_names.cc',
'cdm/key_system_names.h',
'cdm/player_tracker_impl.cc',
'cdm/player_tracker_impl.h',
'ffmpeg/ffmpeg_common.cc',
'ffmpeg/ffmpeg_common.h',
'ffmpeg/ffmpeg_deleters.h',
......@@ -1570,7 +1574,7 @@
'sources': [
'base/android/audio_decoder_job.cc',
'base/android/audio_decoder_job.h',
'base/android/cdm_factory_android.cc',
'base/android/browser_cdm_factory_android.cc',
'base/android/media_codec_bridge.cc',
'base/android/media_codec_bridge.h',
'base/android/media_decoder_job.cc',
......@@ -1592,7 +1596,9 @@
'base/android/webaudio_media_codec_bridge.cc',
'base/android/webaudio_media_codec_bridge.h',
'base/android/webaudio_media_codec_info.h',
'base/cdm_factory.h',
'base/browser_cdm.cc',
'base/browser_cdm.h',
'base/browser_cdm_factory.h',
],
'dependencies': [
'../base/base.gyp:base',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment