diff options
Diffstat (limited to 'chromium/media/cdm/ppapi/cdm_wrapper.h')
-rw-r--r-- | chromium/media/cdm/ppapi/cdm_wrapper.h | 431 |
1 files changed, 162 insertions, 269 deletions
diff --git a/chromium/media/cdm/ppapi/cdm_wrapper.h b/chromium/media/cdm/ppapi/cdm_wrapper.h index d827336a8c6..665b6b68dad 100644 --- a/chromium/media/cdm/ppapi/cdm_wrapper.h +++ b/chromium/media/cdm/ppapi/cdm_wrapper.h @@ -35,16 +35,6 @@ namespace media { // (just a shim layer in most cases), everything is done in this header file. class CdmWrapper { public: - // CDM_1 and CDM_2 methods AddKey() and CancelKeyRequest() may require - // callbacks to fire. Use this enum to indicate the additional calls required. - // TODO(jrummell): Remove return value once CDM_1 and CDM_2 are no longer - // supported. - enum Result { - NO_ACTION, - CALL_KEY_ADDED, - CALL_KEY_ERROR - }; - static CdmWrapper* Create(const char* key_system, uint32_t key_system_size, GetCdmHostFunc get_cdm_host_func, @@ -52,15 +42,23 @@ class CdmWrapper { virtual ~CdmWrapper() {}; - virtual void CreateSession(uint32_t session_id, - const char* type, - uint32_t type_size, + virtual void CreateSession(uint32_t promise_id, + const char* init_data_type, + uint32_t init_data_type_size, const uint8_t* init_data, - uint32_t init_data_size) = 0; - virtual Result UpdateSession(uint32_t session_id, - const uint8_t* response, - uint32_t response_size) = 0; - virtual Result ReleaseSession(uint32_t session_id) = 0; + uint32_t init_data_size, + cdm::SessionType session_type) = 0; + virtual void LoadSession(uint32_t promise_id, + const char* web_session_id, + uint32_t web_session_id_size) = 0; + virtual void UpdateSession(uint32_t promise_id, + const char* web_session_id, + uint32_t web_session_id_size, + const uint8_t* response, + uint32_t response_size) = 0; + virtual void ReleaseSession(uint32_t promise_id, + const char* web_session_id, + uint32_t web_session_id_size) = 0; virtual void TimerExpired(void* context) = 0; virtual cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer, cdm::DecryptedBlock* decrypted_buffer) = 0; @@ -82,42 +80,23 @@ class CdmWrapper { uint32_t link_mask, uint32_t output_protection_mask) = 0; - // ContentDecryptionModule_1 and ContentDecryptionModule_2 interface methods - // AddKey() and CancelKeyRequest() (older versions of UpdateSession() and - // ReleaseSession(), respectively) pass in the web_session_id rather than the - // session_id. As well, Host_1 and Host_2 callbacks SendKeyMessage() and - // SendKeyError() include the web_session_id, but the actual callbacks need - // session_id. - // - // The following functions maintain the session_id <-> web_session_id mapping. - // These can be removed once _1 and _2 interfaces are no longer supported. - - // Determine the corresponding session_id for |web_session_id|. - virtual uint32_t LookupSessionId(const std::string& web_session_id) = 0; - - // Determine the corresponding session_id for |session_id|. - virtual const std::string LookupWebSessionId(uint32_t session_id) = 0; - - // Map between session_id and web_session_id. - // TODO(jrummell): The following can be removed once CDM_1 and CDM_2 are - // no longer supported. - typedef std::map<uint32_t, std::string> SessionMap; - SessionMap session_map_; - - static const uint32_t kInvalidSessionId = 0; - - // As the response from PrefixedGenerateKeyRequest() may be synchronous or - // asynchronous, keep track of the current request during the call to handle - // synchronous responses or errors. If no response received, add this request - // to a queue and assume that the subsequent responses come back in the order - // issued. - // TODO(jrummell): Remove once all supported CDM host interfaces support - // session_id. - uint32_t current_key_request_session_id_; - std::queue<uint32_t> pending_key_request_session_ids_; + // Helper function for the cdm::Host_4 methods. Calls to CreateSession(), + // LoadSession(), UpdateSession(), and ReleaseSession() pass in promise ids, + // but the CDM interface needs session ids. For create and load, we need to + // create a new session_id to pass to the CDM. For update and release, we need + // to look up |web_session_id| and convert it into the existing |session_id|. + // Since the callbacks don't come through this interface, cdm_adapter needs to + // create the mapping (and delete it on release). + // TODO(jrummell): Remove these once Host_4 interface is removed. + virtual uint32_t LookupPromiseId(uint32_t session_id) = 0; + virtual void AssignWebSessionId(uint32_t session_id, + const char* web_session_id, + uint32_t web_session_id_size) = 0; + virtual std::string LookupWebSessionId(uint32_t session_id) = 0; + virtual void DropWebSessionId(std::string web_session_id) = 0; protected: - CdmWrapper() : current_key_request_session_id_(kInvalidSessionId) {} + CdmWrapper() {} private: DISALLOW_COPY_AND_ASSIGN(CdmWrapper); @@ -147,24 +126,42 @@ class CdmWrapperImpl : public CdmWrapper { cdm_->Destroy(); } - virtual void CreateSession(uint32_t session_id, - const char* type, - uint32_t type_size, + virtual void CreateSession(uint32_t promise_id, + const char* init_data_type, + uint32_t init_data_type_size, const uint8_t* init_data, - uint32_t init_data_size) OVERRIDE { - cdm_->CreateSession(session_id, type, type_size, init_data, init_data_size); + uint32_t init_data_size, + cdm::SessionType session_type) OVERRIDE { + cdm_->CreateSession(promise_id, + init_data_type, + init_data_type_size, + init_data, + init_data_size, + session_type); + } + + virtual void LoadSession(uint32_t promise_id, + const char* web_session_id, + uint32_t web_session_id_size) OVERRIDE { + cdm_->LoadSession(promise_id, web_session_id, web_session_id_size); } - virtual Result UpdateSession(uint32_t session_id, - const uint8_t* response, - uint32_t response_size) OVERRIDE { - cdm_->UpdateSession(session_id, response, response_size); - return NO_ACTION; + virtual void UpdateSession(uint32_t promise_id, + const char* web_session_id, + uint32_t web_session_id_size, + const uint8_t* response, + uint32_t response_size) OVERRIDE { + cdm_->UpdateSession(promise_id, + web_session_id, + web_session_id_size, + response, + response_size); } - virtual Result ReleaseSession(uint32_t session_id) OVERRIDE { - cdm_->ReleaseSession(session_id); - return NO_ACTION; + virtual void ReleaseSession(uint32_t promise_id, + const char* web_session_id, + uint32_t web_session_id_size) OVERRIDE { + cdm_->ReleaseSession(promise_id, web_session_id, web_session_id_size); } virtual void TimerExpired(void* context) OVERRIDE { @@ -217,223 +214,125 @@ class CdmWrapperImpl : public CdmWrapper { cdm_->OnQueryOutputProtectionStatus(link_mask, output_protection_mask); } - uint32_t LookupSessionId(const std::string& web_session_id) { - for (SessionMap::iterator it = session_map_.begin(); - it != session_map_.end(); - ++it) { - if (it->second == web_session_id) - return it->first; - } - - // There is no entry in the map; assume it came from the current - // PrefixedGenerateKeyRequest() call (if possible). If no current request, - // assume it came from the oldest PrefixedGenerateKeyRequest() call. - uint32_t session_id = current_key_request_session_id_; - if (current_key_request_session_id_) { - // Only 1 response is allowed for the current - // PrefixedGenerateKeyRequest(). - current_key_request_session_id_ = kInvalidSessionId; - } else { - PP_DCHECK(!pending_key_request_session_ids_.empty()); - session_id = pending_key_request_session_ids_.front(); - pending_key_request_session_ids_.pop(); - } - - // If this is a valid |session_id|, add it to the list. Otherwise, avoid - // adding empty string as a mapping to prevent future calls with an empty - // string from using the wrong session_id. - if (!web_session_id.empty()) { - PP_DCHECK(session_map_.find(session_id) == session_map_.end()); - session_map_[session_id] = web_session_id; - } - - return session_id; + uint32_t CreateSessionId() { + return next_session_id_++; } - const std::string LookupWebSessionId(uint32_t session_id) { - // Session may not exist if error happens during CreateSession(). - SessionMap::iterator it = session_map_.find(session_id); - return (it != session_map_.end()) ? it->second : std::string(); + void RegisterPromise(uint32_t session_id, uint32_t promise_id) { + PP_DCHECK(promise_to_session_id_map_.find(session_id) == + promise_to_session_id_map_.end()); + promise_to_session_id_map_.insert(std::make_pair(session_id, promise_id)); } - private: - CdmWrapperImpl(CdmInterface* cdm) : cdm_(cdm) { - PP_DCHECK(cdm_); + virtual uint32_t LookupPromiseId(uint32_t session_id) { + std::map<uint32_t, uint32_t>::iterator it = + promise_to_session_id_map_.find(session_id); + if (it == promise_to_session_id_map_.end()) + return 0; + uint32_t promise_id = it->second; + promise_to_session_id_map_.erase(it); + return promise_id; } - CdmInterface* cdm_; - - DISALLOW_COPY_AND_ASSIGN(CdmWrapperImpl); -}; - -// For ContentDecryptionModule_1 and ContentDecryptionModule_2, -// CreateSession(), UpdateSession(), and ReleaseSession() call methods -// are incompatible with ContentDecryptionModule_3. Use the following -// templated functions to handle this. - -template <class CdmInterface> -void PrefixedGenerateKeyRequest(CdmWrapper* wrapper, - CdmInterface* cdm, - uint32_t session_id, - const char* type, - uint32_t type_size, - const uint8_t* init_data, - uint32_t init_data_size) { - // As it is possible for CDMs to reply synchronously during the call to - // GenerateKeyRequest(), keep track of |session_id|. - wrapper->current_key_request_session_id_ = session_id; - - cdm::Status status = - cdm->GenerateKeyRequest(type, type_size, init_data, init_data_size); - PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError); - if (status != cdm::kSuccess) { - // If GenerateKeyRequest() failed, no subsequent asynchronous replies - // will be sent. Verify that a response was sent synchronously. - PP_DCHECK(wrapper->current_key_request_session_id_ == - CdmWrapper::kInvalidSessionId); - wrapper->current_key_request_session_id_ = CdmWrapper::kInvalidSessionId; - return; + virtual void AssignWebSessionId(uint32_t session_id, + const char* web_session_id, + uint32_t web_session_id_size) { + web_session_to_session_id_map_.insert(std::make_pair( + std::string(web_session_id, web_session_id_size), session_id)); } - if (wrapper->current_key_request_session_id_) { - // If this request is still pending (SendKeyMessage() or SendKeyError() - // not called synchronously), add |session_id| to the end of the queue. - // Without CDM support, it is impossible to match SendKeyMessage() - // (or SendKeyError()) responses to the |session_id|. Doing the best - // we can by keeping track of this in a queue, and assuming the responses - // come back in order. - wrapper->pending_key_request_session_ids_.push(session_id); - wrapper->current_key_request_session_id_ = CdmWrapper::kInvalidSessionId; + uint32_t LookupSessionId(std::string web_session_id) { + return web_session_to_session_id_map_.find(web_session_id)->second; } -} -template <class CdmInterface> -CdmWrapper::Result PrefixedAddKey(CdmWrapper* wrapper, - CdmInterface* cdm, - uint32_t session_id, - const uint8_t* response, - uint32_t response_size) { - const std::string web_session_id = wrapper->LookupWebSessionId(session_id); - if (web_session_id.empty()) { - // Possible if UpdateSession() called before CreateSession(). - return CdmWrapper::CALL_KEY_ERROR; + virtual std::string LookupWebSessionId(uint32_t session_id) { + std::map<std::string, uint32_t>::iterator it; + for (it = web_session_to_session_id_map_.begin(); + it != web_session_to_session_id_map_.end(); + ++it) { + if (it->second == session_id) + return it->first; + } + PP_NOTREACHED(); + return std::string(); } - // CDM_1 and CDM_2 accept initdata, which is no longer needed. - // In it's place pass in NULL. - cdm::Status status = cdm->AddKey(web_session_id.data(), web_session_id.size(), - response, response_size, - NULL, 0); - PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError); - if (status != cdm::kSuccess) { - // Some CDMs using Host_1/2 don't call keyerror, so send one. - return CdmWrapper::CALL_KEY_ERROR; + virtual void DropWebSessionId(std::string web_session_id) { + web_session_to_session_id_map_.erase(web_session_id); } - return CdmWrapper::CALL_KEY_ADDED; -} - -template <class CdmInterface> -CdmWrapper::Result PrefixedCancelKeyRequest(CdmWrapper* wrapper, - CdmInterface* cdm, - uint32_t session_id) { - const std::string web_session_id = wrapper->LookupWebSessionId(session_id); - if (web_session_id.empty()) { - // Possible if ReleaseSession() called before CreateSession(). - return CdmWrapper::CALL_KEY_ERROR; + private: + CdmWrapperImpl(CdmInterface* cdm) : cdm_(cdm), next_session_id_(100) { + PP_DCHECK(cdm_); } - wrapper->session_map_.erase(session_id); - cdm::Status status = - cdm->CancelKeyRequest(web_session_id.data(), web_session_id.size()); + CdmInterface* cdm_; - PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError); - if (status != cdm::kSuccess) { - // Some CDMs using Host_1/2 don't call keyerror, so send one. - return CdmWrapper::CALL_KEY_ERROR; - } + std::map<uint32_t, uint32_t> promise_to_session_id_map_; + uint32_t next_session_id_; + std::map<std::string, uint32_t> web_session_to_session_id_map_; - return CdmWrapper::NO_ACTION; -} + DISALLOW_COPY_AND_ASSIGN(CdmWrapperImpl); +}; -// Specializations for ContentDecryptionModule_1. +// Overrides for the cdm::Host_4 methods. Calls to CreateSession(), +// LoadSession(), UpdateSession(), and ReleaseSession() pass in promise ids, +// but the CDM interface needs session ids. For create and load, we need to +// create a new session_id to pass to the CDM. For update and release, we need +// to look up |web_session_id| and convert it into the existing |session_id|. +// Since the callbacks don't come through this interface, cdm_adapter needs to +// create the mapping (and delete it on release). +// TODO(jrummell): Remove these once Host_4 interface is removed. template <> -void CdmWrapperImpl<cdm::ContentDecryptionModule_1>::CreateSession( - uint32_t session_id, - const char* type, - uint32_t type_size, +void CdmWrapperImpl<cdm::ContentDecryptionModule_4>::CreateSession( + uint32_t promise_id, + const char* init_data_type, + uint32_t init_data_type_size, const uint8_t* init_data, - uint32_t init_data_size) { - PrefixedGenerateKeyRequest( - this, cdm_, session_id, type, type_size, init_data, init_data_size); + uint32_t init_data_size, + cdm::SessionType session_type) { + uint32_t session_id = CreateSessionId(); + RegisterPromise(session_id, promise_id); + cdm_->CreateSession(session_id, + init_data_type, + init_data_type_size, + init_data, + init_data_size); } template <> -CdmWrapper::Result CdmWrapperImpl< - cdm::ContentDecryptionModule_1>::UpdateSession(uint32_t session_id, - const uint8_t* response, - uint32_t response_size) { - return PrefixedAddKey(this, cdm_, session_id, response, response_size); +void CdmWrapperImpl<cdm::ContentDecryptionModule_4>::LoadSession( + uint32_t promise_id, + const char* web_session_id, + uint32_t web_session_id_size) { + uint32_t session_id = CreateSessionId(); + RegisterPromise(session_id, promise_id); + cdm_->LoadSession(session_id, web_session_id, web_session_id_size); } template <> -CdmWrapper::Result CdmWrapperImpl< - cdm::ContentDecryptionModule_1>::ReleaseSession(uint32_t session_id) { - return PrefixedCancelKeyRequest(this, cdm_, session_id); -} - -template <> void CdmWrapperImpl<cdm::ContentDecryptionModule_1>:: - OnPlatformChallengeResponse( - const cdm::PlatformChallengeResponse& response) { - PP_NOTREACHED(); -} - -template <> void CdmWrapperImpl<cdm::ContentDecryptionModule_1>:: - OnQueryOutputProtectionStatus(uint32_t link_mask, - uint32_t output_protection_mask) { - PP_NOTREACHED(); -} - -template <> cdm::Status CdmWrapperImpl<cdm::ContentDecryptionModule_1>:: - DecryptAndDecodeSamples(const cdm::InputBuffer& encrypted_buffer, - cdm::AudioFrames* audio_frames) { - AudioFramesImpl audio_frames_1; - cdm::Status status = - cdm_->DecryptAndDecodeSamples(encrypted_buffer, &audio_frames_1); - if (status != cdm::kSuccess) - return status; - - audio_frames->SetFrameBuffer(audio_frames_1.PassFrameBuffer()); - audio_frames->SetFormat(cdm::kAudioFormatS16); - return cdm::kSuccess; +void CdmWrapperImpl<cdm::ContentDecryptionModule_4>::UpdateSession( + uint32_t promise_id, + const char* web_session_id, + uint32_t web_session_id_size, + const uint8_t* response, + uint32_t response_size) { + std::string web_session_str(web_session_id, web_session_id_size); + uint32_t session_id = LookupSessionId(web_session_str); + RegisterPromise(session_id, promise_id); + cdm_->UpdateSession(session_id, response, response_size); } -// Specializations for ContentDecryptionModule_2. - template <> -void CdmWrapperImpl<cdm::ContentDecryptionModule_2>::CreateSession( - uint32_t session_id, - const char* type, - uint32_t type_size, - const uint8_t* init_data, - uint32_t init_data_size) { - PrefixedGenerateKeyRequest( - this, cdm_, session_id, type, type_size, init_data, init_data_size); -} - -template <> -CdmWrapper::Result CdmWrapperImpl< - cdm::ContentDecryptionModule_2>::UpdateSession(uint32_t session_id, - const uint8_t* response, - uint32_t response_size) { - return PrefixedAddKey(this, cdm_, session_id, response, response_size); -} - -template <> -CdmWrapper::Result CdmWrapperImpl< - cdm::ContentDecryptionModule_2>::ReleaseSession(uint32_t session_id) { - return PrefixedCancelKeyRequest(this, cdm_, session_id); +void CdmWrapperImpl<cdm::ContentDecryptionModule_4>::ReleaseSession( + uint32_t promise_id, + const char* web_session_id, + uint32_t web_session_id_size) { + std::string web_session_str(web_session_id, web_session_id_size); + uint32_t session_id = LookupSessionId(web_session_str); + RegisterPromise(session_id, promise_id); + cdm_->ReleaseSession(session_id); } CdmWrapper* CdmWrapper::Create(const char* key_system, @@ -441,23 +340,21 @@ CdmWrapper* CdmWrapper::Create(const char* key_system, GetCdmHostFunc get_cdm_host_func, void* user_data) { COMPILE_ASSERT(cdm::ContentDecryptionModule::kVersion == - cdm::ContentDecryptionModule_3::kVersion, + cdm::ContentDecryptionModule_5::kVersion, update_code_below); - // Ensure IsSupportedCdmInterfaceVersion matches this implementation. + // Ensure IsSupportedCdmInterfaceVersion() matches this implementation. // Always update this DCHECK when updating this function. // If this check fails, update this function and DCHECK or update - // IsSupportedCdmInterfaceVersion. + // IsSupportedCdmInterfaceVersion(). PP_DCHECK( - !IsSupportedCdmInterfaceVersion( - cdm::ContentDecryptionModule::kVersion + 1) && + !IsSupportedCdmInterfaceVersion(cdm::ContentDecryptionModule::kVersion + + 1) && IsSupportedCdmInterfaceVersion(cdm::ContentDecryptionModule::kVersion) && IsSupportedCdmInterfaceVersion( - cdm::ContentDecryptionModule_2::kVersion) && - IsSupportedCdmInterfaceVersion( - cdm::ContentDecryptionModule_1::kVersion) && - !IsSupportedCdmInterfaceVersion( - cdm::ContentDecryptionModule_1::kVersion - 1)); + cdm::ContentDecryptionModule_4::kVersion) && + !IsSupportedCdmInterfaceVersion(cdm::ContentDecryptionModule_4::kVersion - + 1)); // Try to create the CDM using the latest CDM interface version. CdmWrapper* cdm_wrapper = @@ -466,13 +363,9 @@ CdmWrapper* CdmWrapper::Create(const char* key_system, if (cdm_wrapper) return cdm_wrapper; - // Try to see if the CDM supports older version(s) of the CDM interface. - cdm_wrapper = CdmWrapperImpl<cdm::ContentDecryptionModule_2>::Create( - key_system, key_system_size, get_cdm_host_func, user_data); - if (cdm_wrapper) - return cdm_wrapper; - - cdm_wrapper = CdmWrapperImpl<cdm::ContentDecryptionModule_1>::Create( + // If |cdm_wrapper| is NULL, try to create the CDM using older supported + // versions of the CDM interface. + cdm_wrapper = CdmWrapperImpl<cdm::ContentDecryptionModule_4>::Create( key_system, key_system_size, get_cdm_host_func, user_data); return cdm_wrapper; } @@ -482,7 +375,7 @@ CdmWrapper* CdmWrapper::Create(const char* key_system, // does not have. // Also update supported_cdm_versions.h. COMPILE_ASSERT(cdm::ContentDecryptionModule::kVersion == - cdm::ContentDecryptionModule_3::kVersion, + cdm::ContentDecryptionModule_5::kVersion, ensure_cdm_wrapper_templates_have_old_version_support); } // namespace media |