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

Unified Diff: media/base/android/media_codec_player.cc

Issue 1341883003: Prepare MediaDrmBridge to work with MediaCodecPlayer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@bug526755
Patch Set: Created 5 years, 3 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 side-by-side diff with in-line comments
Download patch
Index: media/base/android/media_codec_player.cc
diff --git a/media/base/android/media_codec_player.cc b/media/base/android/media_codec_player.cc
index 4e1e8ff4fb9a52269e0eb4037f2d5bba5938883d..b7538875b31933fa188c3a6c52622dec15a7e085 100644
--- a/media/base/android/media_codec_player.cc
+++ b/media/base/android/media_codec_player.cc
@@ -12,6 +12,8 @@
#include "base/threading/thread.h"
#include "media/base/android/media_codec_audio_decoder.h"
#include "media/base/android/media_codec_video_decoder.h"
+#include "media/base/android/media_drm_bridge.h"
+#include "media/base/android/media_drm_proxy.h"
#include "media/base/android/media_player_manager.h"
#include "media/base/timestamp_constants.h"
@@ -62,6 +64,10 @@ MediaCodecPlayer::MediaCodecPlayer(
interpolator_(&default_tick_clock_),
pending_start_(false),
pending_seek_(kNoTimestamp()),
+ drm_bridge_(nullptr),
+ cdm_registration_id_(0),
+ key_is_required_(false),
+ key_is_added_(false),
media_weak_factory_(this) {
DCHECK(ui_task_runner_->BelongsToCurrentThread());
@@ -104,6 +110,11 @@ MediaCodecPlayer::~MediaCodecPlayer()
video_decoder_->ReleaseDecoderResources();
if (audio_decoder_)
audio_decoder_->ReleaseDecoderResources();
+
+ if (drm_bridge_) {
+ DCHECK(cdm_registration_id_);
+ drm_bridge_->UnregisterPlayer(cdm_registration_id_);
+ }
}
void MediaCodecPlayer::Initialize() {
@@ -223,6 +234,8 @@ void MediaCodecPlayer::Start() {
case kStatePrefetching:
case kStatePlaying:
case kStateWaitingForSurface:
+ case kStateWaitingForKey:
+ case kStateWaitingForCrypto:
case kStateError:
break; // Ignore
default:
@@ -242,6 +255,8 @@ void MediaCodecPlayer::Pause(bool is_media_related_action) {
case kStateWaitingForConfig:
case kStatePrefetching:
case kStateWaitingForSurface:
+ case kStateWaitingForKey:
+ case kStateWaitingForCrypto:
SetState(kStatePaused);
StopDecoders();
break;
@@ -273,6 +288,8 @@ void MediaCodecPlayer::SeekTo(base::TimeDelta timestamp) {
case kStateWaitingForConfig:
case kStatePrefetching:
case kStateWaitingForSurface:
+ case kStateWaitingForKey:
+ case kStateWaitingForCrypto:
SetState(kStateWaitingForSeek);
StopDecoders();
SetPendingStart(true);
@@ -313,6 +330,10 @@ void MediaCodecPlayer::Release() {
if (state_ != kStateWaitingForSeek)
SetState(kStatePaused);
+ // Crear encryption key related flags.
+ key_is_required_ = false;
+ key_is_added_ = false;
+
base::TimeDelta pending_seek_time = GetPendingSeek();
if (pending_seek_time != kNoTimestamp()) {
SetPendingSeek(kNoTimestamp());
@@ -382,8 +403,42 @@ bool MediaCodecPlayer::IsPlayerReady() {
}
void MediaCodecPlayer::SetCdm(BrowserCdm* cdm) {
- DCHECK(ui_task_runner_->BelongsToCurrentThread());
- NOTIMPLEMENTED();
+ RUN_ON_MEDIA_THREAD(SetCdm, cdm);
+
+ DVLOG(1) << __FUNCTION__;
+
+ // Currently we don't support DRM change during the middle of playback, even
+ // if the player is paused. There is no current plan to support it, see
+ // http://crbug.com/253792.
+ if (state_ != kStatePaused || GetInterpolatedTime() > base::TimeDelta()) {
+ VLOG(0) << "Setting DRM bridge after playback has started is not supported";
+ return;
+ }
+
+ if (drm_bridge_) {
+ NOTREACHED() << "Currently we do not support resetting CDM.";
+ return;
+ }
+
+ DCHECK(cdm);
+ MediaDrmProxy* drm_proxy = static_cast<MediaDrmProxy*>(cdm);
+ drm_bridge_ = drm_proxy->GetDrmBridge();
+
+ DCHECK(drm_bridge_);
+
+ DCHECK(audio_decoder_);
+ DCHECK(video_decoder_);
+ audio_decoder_->SetDrmBridge(drm_bridge_);
+ video_decoder_->SetDrmBridge(drm_bridge_);
+
+ cdm_registration_id_ = drm_bridge_->RegisterPlayer(
+ base::Bind(&MediaCodecPlayer::OnKeyAdded, media_weak_this_),
+ base::Bind(&MediaCodecPlayer::OnCdmUnset, media_weak_this_));
+
+ // If the crypto is ready by this time, OnMediaCryptoReady will be posted
+ // immediately, otherwise it will be posted when the crypro is ready.
+ drm_bridge_->SetMediaCryptoReadyCB(
+ base::Bind(&MediaCodecPlayer::OnMediaCryptoReady, media_weak_this_));
}
// Callbacks from Demuxer.
@@ -604,6 +659,11 @@ void MediaCodecPlayer::OnPrefetchDone() {
return;
}
+ if (key_is_required_ && !key_is_added_) {
+ SetState(kStateWaitingForKey);
+ return;
+ }
+
SetState(kStatePlaying);
StartPlaybackOrBrowserSeek();
}
@@ -717,6 +777,20 @@ void MediaCodecPlayer::OnStopDone(DemuxerStream::Type type) {
ui_task_runner_->PostTask(FROM_HERE, completion_cb_);
}
+void MediaCodecPlayer::OnKeyRequired(DemuxerStream::Type type) {
+ DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
+ DVLOG(1) << __FUNCTION__ << " " << type;
+
+ // Request stop and restart to pick up the key.
+ key_is_required_ = true;
+
+ if (state_ == kStatePlaying) {
+ SetState(kStateStopping);
+ RequestToStopDecoders();
+ SetPendingStart(true);
+ }
+}
+
void MediaCodecPlayer::OnError() {
DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__;
@@ -800,6 +874,57 @@ void MediaCodecPlayer::OnVideoResolutionChanged(const gfx::Size& size) {
FROM_HERE, base::Bind(metadata_changed_cb_, kNoTimestamp(), size));
}
+// Callbacks from DRM
+
+void MediaCodecPlayer::OnMediaCryptoReady() {
+ DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
+ DVLOG(1) << __FUNCTION__;
+
+ DCHECK(drm_bridge_);
+ DCHECK(!drm_bridge_->GetMediaCrypto().is_null());
+ drm_bridge_->SetMediaCryptoReadyCB(base::Closure());
+
+ if (state_ == kStateWaitingForCrypto) {
+ // Resume decoders creation.
+ SetState(kStatePlaying);
+ StartPlaybackOrBrowserSeek();
+ }
+
+ DVLOG(1) << __FUNCTION__ << " end";
+}
+
+void MediaCodecPlayer::OnKeyAdded() {
+ DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
+ DVLOG(1) << __FUNCTION__;
+
+ key_is_added_ = true;
+
+ if (state_ == kStateWaitingForKey) {
+ SetState(kStatePlaying);
+ StartPlaybackOrBrowserSeek();
+ }
+}
+
+void MediaCodecPlayer::OnCdmUnset() {
+ DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
+ DVLOG(1) << __FUNCTION__;
+
+ // This comment is copied from MediaSourcePlayer::OnCdmUnset().
+ // TODO(xhwang): Currently this is only called during teardown. Support full
+ // detachment of CDM during playback. This will be needed when we start to
+ // support setMediaKeys(0) (see http://crbug.com/330324), or when we release
+ // MediaDrm when the video is paused, or when the device goes to sleep (see
+ // http://crbug.com/272421).
+
+ if (audio_decoder_)
+ audio_decoder_->SetDrmBridge(nullptr);
+ if (video_decoder_)
+ video_decoder_->SetDrmBridge(nullptr);
+
+ cdm_registration_id_ = 0;
+ drm_bridge_ = nullptr;
+}
+
// State machine operations, called on Media thread
void MediaCodecPlayer::SetState(PlayerState new_state) {
@@ -899,6 +1024,10 @@ void MediaCodecPlayer::StartPlaybackOrBrowserSeek() {
// TODO(timav): consider replacing this method with posting a
// browser seek task (i.e. generate an event) from StartPlaybackDecoders().
+ // Clear encryption key related flags.
+ key_is_required_ = false;
+ key_is_added_ = false;
+
StartStatus status = StartPlaybackDecoders();
switch (status) {
@@ -909,6 +1038,9 @@ void MediaCodecPlayer::StartPlaybackOrBrowserSeek() {
StopDecoders();
RequestDemuxerSeek(GetInterpolatedTime(), true);
break;
+ case kStartCryptoRequired:
+ SetState(kStateWaitingForCrypto);
+ break;
case kStartFailed:
GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_);
break;
@@ -946,29 +1078,26 @@ MediaCodecPlayer::StartStatus MediaCodecPlayer::ConfigureDecoders() {
// prefetch state and never call this method.
DCHECK(do_audio || do_video);
- // Start with video: if browser seek is required it would
- // not make sense to configure audio.
+ // Start with video: if browser seek is required it would not make sense to
+ // configure audio.
- if (do_video) {
- MediaCodecDecoder::ConfigStatus status = video_decoder_->Configure();
- switch (status) {
- case MediaCodecDecoder::kConfigOk:
- break;
- case MediaCodecDecoder::kConfigKeyFrameRequired:
- // TODO(timav): post a task or return the status?
- return kStartBrowserSeekRequired;
- case MediaCodecDecoder::kConfigFailure:
- return kStartFailed;
- }
- }
+ MediaCodecDecoder::ConfigStatus status = MediaCodecDecoder::kConfigOk;
+ if (do_video)
+ status = video_decoder_->Configure();
+
+ if (status == MediaCodecDecoder::kConfigOk && do_audio)
+ status = audio_decoder_->Configure();
- if (do_audio) {
- MediaCodecDecoder::ConfigStatus status = audio_decoder_->Configure();
- if (status != MediaCodecDecoder::kConfigOk) {
+ switch (status) {
+ case MediaCodecDecoder::kConfigOk:
+ break;
+ case MediaCodecDecoder::kConfigKeyFrameRequired:
+ return kStartBrowserSeekRequired;
+ case MediaCodecDecoder::kConfigNoCrypto:
+ return kStartCryptoRequired;
+ case MediaCodecDecoder::kConfigFailure:
return kStartFailed;
- }
}
-
return kStartOk;
}
@@ -1127,6 +1256,8 @@ void MediaCodecPlayer::CreateDecoders() {
DemuxerStream::AUDIO),
base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_,
DemuxerStream::AUDIO),
+ base::Bind(&MediaCodecPlayer::OnKeyRequired, media_weak_this_,
+ DemuxerStream::AUDIO),
internal_error_cb_,
base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_,
DemuxerStream::AUDIO)));
@@ -1140,6 +1271,8 @@ void MediaCodecPlayer::CreateDecoders() {
DemuxerStream::VIDEO),
base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_,
DemuxerStream::VIDEO),
+ base::Bind(&MediaCodecPlayer::OnKeyRequired, media_weak_this_,
+ DemuxerStream::VIDEO),
internal_error_cb_,
base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_,
DemuxerStream::VIDEO),
@@ -1175,6 +1308,8 @@ const char* MediaCodecPlayer::AsString(PlayerState state) {
RETURN_STRING(kStatePlaying);
RETURN_STRING(kStateStopping);
RETURN_STRING(kStateWaitingForSurface);
+ RETURN_STRING(kStateWaitingForKey);
+ RETURN_STRING(kStateWaitingForCrypto);
RETURN_STRING(kStateWaitingForSeek);
RETURN_STRING(kStateError);
}

Powered by Google App Engine
This is Rietveld 408576698