OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "media/base/android/media_drm_proxy.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/thread_task_runner_handle.h" |
| 9 |
| 10 #include "media/base/android/media_codec_player.h" // for GetMediaTaskRunner() |
| 11 #include "media/base/android/media_drm_bridge.h" |
| 12 #include "media/base/cdm_key_information.h" |
| 13 |
| 14 #include "third_party/widevine/cdm/widevine_cdm_common.h" |
| 15 |
| 16 #define RUN_ON_MEDIA_THREAD(METHOD, ...) \ |
| 17 do { \ |
| 18 if (!GetMediaTaskRunner()->BelongsToCurrentThread()) { \ |
| 19 /*DCHECK(ui_task_runner_->BelongsToCurrentThread());*/ \ |
| 20 GetMediaTaskRunner()->PostTask( \ |
| 21 FROM_HERE, base::Bind(&MediaDrmProxy::METHOD, media_weak_this_, \ |
| 22 ##__VA_ARGS__)); \ |
| 23 return; \ |
| 24 } \ |
| 25 } while (0) |
| 26 |
| 27 namespace media { |
| 28 |
| 29 // static |
| 30 scoped_ptr<MediaDrmProxy, BrowserCdmDeleter> MediaDrmProxy::Create( |
| 31 const std::string& key_system, |
| 32 MediaDrmBridge::SecurityLevel widevine_security_level, |
| 33 const SessionMessageCB& session_message_cb, |
| 34 const SessionClosedCB& session_closed_cb, |
| 35 const LegacySessionErrorCB& legacy_session_error_cb, |
| 36 const SessionKeysChangeCB& session_keys_change_cb, |
| 37 const SessionExpirationUpdateCB& session_expiration_update_cb) { |
| 38 scoped_ptr<MediaDrmProxy, BrowserCdmDeleter> media_drm_proxy; |
| 39 |
| 40 // Perform as many checks as we can on the UI thread before we do |
| 41 // the creation asynchronously on Media thread. |
| 42 if (!MediaDrmBridge::CanCreate(key_system, widevine_security_level)) |
| 43 return media_drm_proxy.Pass(); |
| 44 |
| 45 media_drm_proxy.reset( |
| 46 new MediaDrmProxy(key_system, widevine_security_level, session_message_cb, |
| 47 session_closed_cb, legacy_session_error_cb, |
| 48 session_keys_change_cb, session_expiration_update_cb)); |
| 49 |
| 50 // The actual work is done on the Media thread and there the creation |
| 51 // might fail, but we are still passing a valid pointer. |
| 52 return media_drm_proxy.Pass(); |
| 53 } |
| 54 |
| 55 MediaDrmProxy::MediaDrmProxy( |
| 56 const std::string& key_system, |
| 57 MediaDrmBridge::SecurityLevel widevine_security_level, |
| 58 const SessionMessageCB& session_message_cb, |
| 59 const SessionClosedCB& session_closed_cb, |
| 60 const LegacySessionErrorCB& legacy_session_error_cb, |
| 61 const SessionKeysChangeCB& session_keys_change_cb, |
| 62 const SessionExpirationUpdateCB& session_expiration_update_cb) |
| 63 : ui_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 64 key_system_(key_system), |
| 65 widevine_security_level_(widevine_security_level), |
| 66 session_message_cb_(session_message_cb), |
| 67 session_closed_cb_(session_closed_cb), |
| 68 legacy_session_error_cb_(legacy_session_error_cb), |
| 69 session_keys_change_cb_(session_keys_change_cb), |
| 70 session_expiration_update_cb_(session_expiration_update_cb), |
| 71 media_weak_factory_(this) { |
| 72 media_weak_this_ = media_weak_factory_.GetWeakPtr(); |
| 73 |
| 74 /* |
| 75 internal_session_message_cb_ = |
| 76 base::Bind(&MediaDrmProxy::OnSessionMessage, media_weak_this_); |
| 77 internal_session_closed_cb_ = |
| 78 base::Bind(&MediaDrmProxy::OnSessionClosed, media_weak_this_); |
| 79 internal_legacy_session_error_cb_ = |
| 80 base::Bind(&MediaDrmProxy::OnLegacySessionError, media_weak_this_); |
| 81 internal_session_keys_change_cb_ = |
| 82 base::Bind(&MediaDrmProxy::OnSessionKeysChange, media_weak_this_); |
| 83 internal_session_expiration_update_cb_ = |
| 84 base::Bind(&MediaDrmProxy::OnSessionExpirationUpdate, media_weak_this_); |
| 85 */ |
| 86 |
| 87 // Perform MediaDrmBridge creation on the Media thread. |
| 88 GetMediaTaskRunner()->PostTask( |
| 89 FROM_HERE, base::Bind(&MediaDrmProxy::Initialize, media_weak_this_)); |
| 90 } |
| 91 |
| 92 MediaDrmProxy::~MediaDrmProxy() { |
| 93 DVLOG(1) << "MediaDrmProxy::" << __FUNCTION__; |
| 94 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 95 } |
| 96 |
| 97 void MediaDrmProxy::DeleteOnCorrectThread() { |
| 98 DVLOG(1) << "MediaDrmProxy::" << __FUNCTION__; |
| 99 |
| 100 // Post deletion onto Media thread |
| 101 GetMediaTaskRunner()->DeleteSoon(FROM_HERE, this); |
| 102 } |
| 103 |
| 104 void MediaDrmProxy::Initialize() { |
| 105 DVLOG(1) << "MediaDrmProxy::" << __FUNCTION__; |
| 106 |
| 107 /* |
| 108 media_drm_bridge_ = scoped_ptr<MediaDrmBridge, BrowserCdmDeleter>( |
| 109 MediaDrmBridge::Create(key_system_, |
| 110 widevine_security_level_, |
| 111 internal_session_message_cb_, |
| 112 internal_session_closed_cb_, |
| 113 internal_legacy_session_error_cb_, |
| 114 internal_session_keys_change_cb_, |
| 115 internal_session_expiration_update_cb_)); |
| 116 */ |
| 117 |
| 118 // Pass the origibal callbacks, those that should be called on UI thread. |
| 119 media_drm_bridge_ = |
| 120 scoped_ptr<MediaDrmBridge, BrowserCdmDeleter>(MediaDrmBridge::Create( |
| 121 key_system_, widevine_security_level_, session_message_cb_, |
| 122 session_closed_cb_, legacy_session_error_cb_, session_keys_change_cb_, |
| 123 session_expiration_update_cb_)); |
| 124 |
| 125 if (!media_drm_bridge_) |
| 126 DVLOG(1) << __FUNCTION__ << ": MediaDrmBridge::Create() failed"; |
| 127 } |
| 128 |
| 129 void MediaDrmProxy::SetServerCertificate( |
| 130 const std::vector<uint8_t>& certificate, |
| 131 scoped_ptr<media::SimpleCdmPromise> promise) { |
| 132 RUN_ON_MEDIA_THREAD(SetServerCertificate, certificate, |
| 133 base::Passed(&promise)); |
| 134 |
| 135 DVLOG(1) << "MediaDrmProxy::" << __FUNCTION__; |
| 136 |
| 137 media_drm_bridge_->SetServerCertificate(certificate, promise.Pass()); |
| 138 } |
| 139 |
| 140 void MediaDrmProxy::CreateSessionAndGenerateRequest( |
| 141 SessionType session_type, |
| 142 media::EmeInitDataType init_data_type, |
| 143 const std::vector<uint8_t>& init_data, |
| 144 scoped_ptr<media::NewSessionCdmPromise> promise) { |
| 145 RUN_ON_MEDIA_THREAD(CreateSessionAndGenerateRequest, session_type, |
| 146 init_data_type, init_data, base::Passed(&promise)); |
| 147 |
| 148 DVLOG(1) << "MediaDrmProxy::" << __FUNCTION__; |
| 149 |
| 150 media_drm_bridge_->CreateSessionAndGenerateRequest( |
| 151 session_type, init_data_type, init_data, promise.Pass()); |
| 152 } |
| 153 |
| 154 void MediaDrmProxy::LoadSession( |
| 155 SessionType session_type, |
| 156 const std::string& session_id, |
| 157 scoped_ptr<media::NewSessionCdmPromise> promise) { |
| 158 RUN_ON_MEDIA_THREAD(LoadSession, session_type, session_id, |
| 159 base::Passed(&promise)); |
| 160 |
| 161 DVLOG(1) << "MediaDrmProxy::" << __FUNCTION__; |
| 162 |
| 163 media_drm_bridge_->LoadSession(session_type, session_id, promise.Pass()); |
| 164 } |
| 165 |
| 166 void MediaDrmProxy::UpdateSession(const std::string& session_id, |
| 167 const std::vector<uint8_t>& response, |
| 168 scoped_ptr<media::SimpleCdmPromise> promise) { |
| 169 RUN_ON_MEDIA_THREAD(UpdateSession, session_id, response, |
| 170 base::Passed(&promise)); |
| 171 |
| 172 DVLOG(1) << "MediaDrmProxy::" << __FUNCTION__; |
| 173 |
| 174 media_drm_bridge_->UpdateSession(session_id, response, promise.Pass()); |
| 175 } |
| 176 |
| 177 void MediaDrmProxy::CloseSession(const std::string& session_id, |
| 178 scoped_ptr<media::SimpleCdmPromise> promise) { |
| 179 RUN_ON_MEDIA_THREAD(CloseSession, session_id, base::Passed(&promise)); |
| 180 |
| 181 DVLOG(1) << "MediaDrmProxy::" << __FUNCTION__; |
| 182 |
| 183 media_drm_bridge_->CloseSession(session_id, promise.Pass()); |
| 184 } |
| 185 |
| 186 void MediaDrmProxy::RemoveSession(const std::string& session_id, |
| 187 scoped_ptr<media::SimpleCdmPromise> promise) { |
| 188 RUN_ON_MEDIA_THREAD(RemoveSession, session_id, base::Passed(&promise)); |
| 189 |
| 190 DVLOG(1) << "MediaDrmProxy::" << __FUNCTION__; |
| 191 |
| 192 media_drm_bridge_->RemoveSession(session_id, promise.Pass()); |
| 193 } |
| 194 |
| 195 CdmContext* MediaDrmProxy::GetCdmContext() { |
| 196 NOTREACHED(); |
| 197 return nullptr; |
| 198 } |
| 199 |
| 200 int MediaDrmProxy::RegisterPlayer(const base::Closure& new_key_cb, |
| 201 const base::Closure& cdm_unset_cb) { |
| 202 // Synchronous? |
| 203 DVLOG(1) << "MediaDrmProxy::" << __FUNCTION__; |
| 204 return media_drm_bridge_->RegisterPlayer(new_key_cb, cdm_unset_cb); |
| 205 } |
| 206 |
| 207 void MediaDrmProxy::UnregisterPlayer(int registration_id) { |
| 208 // Synchronous? |
| 209 DVLOG(1) << "MediaDrmProxy::" << __FUNCTION__; |
| 210 media_drm_bridge_->UnregisterPlayer(registration_id); |
| 211 } |
| 212 |
| 213 MediaDrmBridge* MediaDrmProxy::GetDrmBridge() { |
| 214 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 215 |
| 216 return media_drm_bridge_.get(); |
| 217 } |
| 218 |
| 219 /* |
| 220 // Internal callbacks |
| 221 |
| 222 void MediaDrmProxy::OnSessionMessage(const std::string& session_id, |
| 223 MediaKeys::MessageType message_type, |
| 224 const std::vector<uint8>& message, |
| 225 const GURL& legacy_destination_url) { |
| 226 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 227 |
| 228 ui_task_runner_->PostTask( |
| 229 FROM_HERE, base::Bind(session_message_cb_, session_id, message_type, |
| 230 message, legacy_destination_url)); |
| 231 } |
| 232 |
| 233 void MediaDrmProxy::OnSessionClosed(const std::string& session_id) { |
| 234 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 235 |
| 236 ui_task_runner_->PostTask( |
| 237 FROM_HERE, base::Bind(session_closed_cb_, session_id)); |
| 238 } |
| 239 |
| 240 void MediaDrmProxy::OnLegacySessionError(const std::string& session_id, |
| 241 MediaKeys::Exception exception_code, |
| 242 uint32 system_code, |
| 243 const std::string& error_message) { |
| 244 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 245 |
| 246 ui_task_runner_->PostTask( |
| 247 FROM_HERE, base::Bind(legacy_session_error_cb_, session_id, |
| 248 exception_code, system_code, error_message)); |
| 249 } |
| 250 |
| 251 void MediaDrmProxy::OnSessionKeysChange(const std::string& session_id, |
| 252 bool has_additional_usable_key, |
| 253 CdmKeysInfo keys_info) { |
| 254 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 255 |
| 256 ui_task_runner_->PostTask( |
| 257 FROM_HERE, base::Bind(session_keys_change_cb_, session_id, |
| 258 has_additional_usable_key, |
| 259 base::Passed(&keys_info))); |
| 260 } |
| 261 |
| 262 void MediaDrmProxy::OnSessionExpirationUpdate( |
| 263 const std::string& session_id, const base::Time& new_expiry_time) { |
| 264 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 265 |
| 266 ui_task_runner_->PostTask( |
| 267 FROM_HERE, base::Bind(session_expiration_update_cb_, session_id, |
| 268 new_expiry_time)); |
| 269 } |
| 270 */ |
| 271 |
| 272 } // namespace media |
OLD | NEW |