blob: 01481677387c682ed573fc0c66a0f021faacc3a3 [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/base/android/media_drm_bridge_factory.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "media/base/cdm_config.h"
#include "media/base/content_decryption_module.h"
#include "media/base/key_system_names.h"
#include "media/cdm/clear_key_cdm_common.h"
#include "third_party/widevine/cdm/widevine_cdm_common.h"
namespace media {
MediaDrmBridgeFactory::MediaDrmBridgeFactory(CreateFetcherCB create_fetcher_cb,
CreateStorageCB create_storage_cb)
: create_fetcher_cb_(std::move(create_fetcher_cb)),
create_storage_cb_(std::move(create_storage_cb)) {
DCHECK(create_fetcher_cb_);
DCHECK(create_storage_cb_);
}
MediaDrmBridgeFactory::~MediaDrmBridgeFactory() {
if (cdm_created_cb_)
std::move(cdm_created_cb_).Run(nullptr, "CDM creation aborted");
}
void MediaDrmBridgeFactory::Create(
const CdmConfig& cdm_config,
const SessionMessageCB& session_message_cb,
const SessionClosedCB& session_closed_cb,
const SessionKeysChangeCB& session_keys_change_cb,
const SessionExpirationUpdateCB& session_expiration_update_cb,
CdmCreatedCB cdm_created_cb) {
DCHECK(MediaDrmBridge::IsKeySystemSupported(cdm_config.key_system));
DCHECK(scheme_uuid_.empty()) << "This factory can only be used once.";
scheme_uuid_ = MediaDrmBridge::GetUUID(cdm_config.key_system);
DCHECK(!scheme_uuid_.empty());
// Set security level.
if (cdm_config.key_system == kWidevineKeySystem) {
security_level_ = cdm_config.use_hw_secure_codecs
? MediaDrmBridge::SECURITY_LEVEL_1
: MediaDrmBridge::SECURITY_LEVEL_3;
} else if (media::IsExternalClearKey(cdm_config.key_system)) {
security_level_ = MediaDrmBridge::SECURITY_LEVEL_DEFAULT;
} else if (!cdm_config.use_hw_secure_codecs) {
// Assume other key systems require hardware-secure codecs and thus do not
// support full compositing.
auto error_message =
cdm_config.key_system +
" may require use_video_overlay_for_embedded_encrypted_video";
NOTREACHED() << error_message;
std::move(cdm_created_cb).Run(nullptr, error_message);
return;
}
session_message_cb_ = session_message_cb;
session_closed_cb_ = session_closed_cb;
session_keys_change_cb_ = session_keys_change_cb;
session_expiration_update_cb_ = session_expiration_update_cb;
cdm_created_cb_ = std::move(cdm_created_cb);
if (media::IsExternalClearKey(cdm_config.key_system)) {
// We don't use storage in ClearKey so we return before creation, and
// initialize the Media Drm Bridge with an empty string.
CreateMediaDrmBridge("");
return;
}
// MediaDrmStorage may be lazy created in MediaDrmStorageBridge.
storage_ = std::make_unique<MediaDrmStorageBridge>();
storage_->Initialize(
create_storage_cb_,
base::BindOnce(&MediaDrmBridgeFactory::OnStorageInitialized,
weak_factory_.GetWeakPtr()));
}
void MediaDrmBridgeFactory::OnStorageInitialized(bool success) {
DCHECK(storage_);
DVLOG(2) << __func__ << ": success = " << success
<< ", origin_id = " << storage_->origin_id();
// MediaDrmStorageBridge should only be created on a successful Initialize().
if (!success) {
std::move(cdm_created_cb_).Run(nullptr, "Cannot fetch origin ID");
return;
}
CreateMediaDrmBridge(storage_->origin_id());
}
void MediaDrmBridgeFactory::CreateMediaDrmBridge(const std::string& origin_id) {
DCHECK(!media_drm_bridge_);
// Requires MediaCrypto so that it can be used by MediaCodec-based decoders.
const bool requires_media_crypto = true;
media_drm_bridge_ = MediaDrmBridge::CreateInternal(
scheme_uuid_, origin_id, security_level_, requires_media_crypto,
std::move(storage_), create_fetcher_cb_, session_message_cb_,
session_closed_cb_, session_keys_change_cb_,
session_expiration_update_cb_);
if (!media_drm_bridge_) {
std::move(cdm_created_cb_).Run(nullptr, "MediaDrmBridge creation failed");
return;
}
media_drm_bridge_->SetMediaCryptoReadyCB(base::BindOnce(
&MediaDrmBridgeFactory::OnMediaCryptoReady, weak_factory_.GetWeakPtr()));
}
void MediaDrmBridgeFactory::OnMediaCryptoReady(
JavaObjectPtr media_crypto,
bool requires_secure_video_codec) {
DCHECK(media_crypto);
if (media_crypto->is_null()) {
media_drm_bridge_ = nullptr;
std::move(cdm_created_cb_).Run(nullptr, "MediaCrypto not available");
return;
}
std::move(cdm_created_cb_).Run(media_drm_bridge_, "");
}
} // namespace media