@startuml autonumber box "Container" #LightGreen participant Cobalt participant Starboard participant ocdmProxy participant rialtoClient end box box "Platform" #LightBlue participant rialtoServer participant Ocdm end box Cobalt -> Starboard: SbDrmGenerateSessionUpdateRequest(media_keys_handle,\n\t\tticket, init_data_type, iv) Starboard -> ocdmProxy: opencdm_construct_session(media_keys_handle, init_data_type, iv) ocdmProxy -> rialtoClient: createKeySession(media_keys_handle, sessionType=TEMPORARY, client, isLDL=false) rialtoClient -> rialtoServer: createKeySession(media_keys_handle, type, isLDL) rialtoServer -> rialtoServer: generate unique key_session_id and create local key session object rialtoServer --> rialtoClient: status, key_session_id rialtoClient --> ocdmProxy: status, key_session_id ocdmProxy -> rialtoClient: generateRequest(key_session_id, init_data_type, init_data) rialtoClient -> rialtoServer: generateRequest(key_session_id, init_data_type, init_data) activate rialtoServer opt ocdm_session not yet created for this key session rialtoServer -> Ocdm: opencdm_construct_session(media_key_system, Temporary, iv, CDMData=NULL) Ocdm --> rialtoServer: status, ocdm_key_session end rialtoServer --> rialtoClient: status rialtoClient --> ocdmProxy: status ocdmProxy --> Starboard: status, session_handle Starboard --> Cobalt: opt media_keys.key_system == "com.netflix.playready" && no errors note over rialtoServer, Ocdm: For Netflix process_challenge_callback() won't be received, Rialto must call\nopencdm_session_get_challenge_data() to get the challenge then call\nonLicenseRequest() with it rialtoServer -> Ocdm: opencdm_session_get_challenge_data(ocdm_session, is_LDL) Ocdm --> rialtoServer: challenge rialtoServer -/ rialtoClient: onLicenseRequest(key_session_id, challenge, url="") deactivate rialtoServer rialtoClient -/ ocdmProxy: onLicenseRequest(key_session_id, challenge, url) else media_keys.key_system != "com.netflix.playready" && no errors Ocdm -/ rialtoServer: process_challenge_callback(ocdm_key_session, url, challenge) note left: Callback automatically occurs after opencdm_construct_session() for non-Netflix key system rialtoServer -/ rialtoClient: onLicenseRequest(key_session_id, challenge, url) rialtoClient -/ ocdmProxy: onLicenseRequest(key_session_id, challenge, url) ocdmProxy -/ Starboard: process_challenge_callback(session_handle, url, challenge) Starboard -/ Cobalt: SbDrmSessionUpdateRequestFunc(media_keys_handle, context,\n\t\tticket, kSbDrmStatusSuccess,\n\t\tkSbDrmSessionRequestTypeLicenseRequest,\n\t\tNULL, session_id, challenge, url) else If generateRequest() fails at any point ensure error callback is made (not showing all cases to keep diagram simple) opt Server error rialtoServer --> rialtoClient: status!=OK end rialtoClient --> ocdmProxy: status!=OK ocdmProxy -/ Starboard: process_challenge_callback(session_handle, url, NULL) Starboard -/ Cobalt: SbDrmSessionUpdateRequestFunc(ticket,\n\t\tUnknownError, RequestTypeLicenseRequest) end note across: Rialto API follows EME/libNova APIs which put IV in generateRequest which doesn't map directly to OCDM/Fusion so some complexity in here but as this model is proven retain it @enduml |
@startuml autonumber box "Container" #LightGreen participant Netflix participant DPI participant rialtoClient end box box "Platform" #LightBlue participant rialtoServer end box Netflix -> DPI: createDrmSession(media_keys, content_id, license_type, drm_header) DPI -> DPI: Create DPI session object DPI -> DPI: Store content_id, license_type &\ndrm_header in session object DPI --> Netflix: session_handle Netflix -> DPI: getChallengeData(is_LDL) DPI -> rialtoClient: createKeySession(media_keys_handle, session_type=TEMPORARY, is_LDL) rialtoClient -> rialtoServer: createKeySession(media_keys_handle, session_type, is_LDL) note over rialtoServer: As createKeySession() in Cobalt diagram above rialtoServer --> rialtoClient: status, key_session_id rialtoClient --> DPI: status, key_session_id DPI -> rialtoClient: generateRequest(key_session_id, init_data_type=DRMHEADER, init_data=drm_header) rialtoClient -> rialtoServer: generateRequest(key_session_id, init_data_type, init_data) note over rialtoServer:As generateRequest() in Cobalt diagram above,\nsee note that opendm_session_get_challenge_data() rialtoServer --> rialtoClient: status rialtoClient --> DPI: status note over DPI: getChallengeData() must block until onLicenseRequest() callback received rialtoServer -/ rialtoClient: onLicenseRequest(key_session_id, challenge, url) rialtoClient -/ DPI: onLicenseRequest(key_session_id, challenge, url) DPI --> Netflix: status, challenge @enduml |
@startuml autonumber box "Container" #LightGreen participant Cobalt participant Starboard participant ocdmProxy participant rialtoClient end box box "Platform" #LightBlue participant rialtoServer participant Ocdm end box Cobalt -> Starboard: SbDrmUpdateSession(media_keys_handle, ticket, key, session_id) Starboard -> ocdmProxy: opencdm_session_update(session_id, key) ocdmProxy -> ocdmProxy: Lookup MediaKeys object for session_id ocdmProxy -> rialtoClient: updateKeySession(media_keys_handle, session_id, key) rialtoClient -> rialtoServer: updateKeySession(media_keys_handle, session_id, key) opt media_keys.key_system == "com.netflix.playready" rialtoServer -> Ocdm: opencdm_session_store_license_data(session_id, license_data=key) Ocdm --> rialtoServer: status, secure_stop_id note left: Secure stop ID ignored as\nnot supported by Rialto else rialtoServer -> Ocdm: opencdm_session_update(session_id, key) Ocdm --> rialtoServer: status end rialtoServer --> rialtoClient: status rialtoClient --> ocdmProxy: status opt update successful ocdmProxy --> Starboard: status=OK Starboard --> Cobalt: status=OK loop For each key updated Ocdm -/ rialtoServer: OnKeyUpdated(session_id, key_id) rialtoServer -> rialtoServer: Store updated key_id end Ocdm -/ rialtoServer: OnAllKeysUpdated(session_id) rialtoServer -/ rialtoClient: onKeyStatusesChanged(session_id, key_statuses) rialtoClient -/ ocdmProxy: onKeyStatusesChanged(session_id, key_statuses) loop For each key updated ocdmProxy -/ Starboard: OnKeyUpdated(session_id, key_id) end ocdmProxy -/ Starboard: OnAllKeysUpdated(session_id) Starboard -/ Cobalt: SbDrmSessionUpdatedFunc(media_keys_handle, context, ticket, kSbDrmStatusSuccess, nullptr, session_id); Starboard -/ Cobalt: SbDrmSessionKeyStatusesChangedFunc(media_keys_handle, context, session_id, key_ids, key_statuses); else update failed ocdmProxy --> Starboard: status=NOK Starboard -/ Cobalt: SbDrmSessionUpdatedFunc(media_keys_handle, context, ticket, kSbDrmStatusUnknownError, nullptr, session_id); Starboard --> Cobalt: status=NOK end @enduml |
@startuml autonumber box "Container" #LightGreen participant Netflix participant DPI participant rialtoClient end box box "Platform" #LightBlue participant rialtoServer participant Ocdm end box Netflix -> DPI: storeLicenseData(session_id, license_data) DPI -> DPI: Lookup MediaKeys object for session_id DPI -> rialtoClient: updateKeySession(media_keys_handle, session_id, license_data) rialtoClient -> rialtoServer: updateKeySession(media_keys_handle, session_id, license_data) note over rialtoServer, Ocdm: As shown for updateKeySession in previous diagram rialtoServer --> rialtoClient: status rialtoClient --> DPI: status DPI --> Netflix: status note across: Key update messages will be generated as shown in previous diagram @enduml |
@startuml autonumber box "Container" #LightGreen participant Cobalt participant Starboard participant ocdmProxy participant rialtoClient end box box "Platform" #LightBlue participant rialtoServer participant Ocdm end box Ocdm -/ rialtoServer: process_challenge_callback(session_id, user_data, license_renewal_message, url) rialtoServer -/ rialtoClient: onLicenseRenewal(session_id, license_renewal_message) rialtoClient -/ ocdmProxy: onLicenseRenewal(session_id, license_renewal_message) ocdmProxy -/ Starboard: process_challenge_callback(session_id, user_data, license_renewal_message, url="") Starboard -/ Starboard: Extract request_type & request_content from license_renewal_message note left: Use user_data to determine media_keys etc Starboard -/ Cobalt: SbDrmSessionUpdateRequestFunc(media_keys, request_status=kSbDrmStatusSuccess, request_type, session_id, request_content, url) note across: App then should fetch the updated license and call SbDrmUpdateSession() in the same way as for the initial license @enduml |
@startuml autonumber box "Container" #LightGreen participant Client participant rialtoClient end box box "Platform" #LightBlue participant rialtoServer participant Ocdm end box Ocdm -/ rialtoServer: process_challenge_callback(session_id, user_data, license_renewal_message, url) rialtoServer -/ rialtoClient: onLicenseRenewal(session_id, license_renewal_message) rialtoClient -/ Client: onLicenseRenewal(session_id, license_renewal_message) note across: App then should fetch the updated license and call updateKeySession() in the same way as for the initial license @enduml |
Not supported in avbus-poc or libNova - not required? If need, it follows a same pattern as License Renewal above and we would need to add onError() method in IMediaKeysClient interface.
@startuml autonumber box "Container" #LightGreen participant Netflix participant DPI participant rialtoClient end box Netflix -> DPI: initDecryptContextByKid(session_id, key_id) DPI -> DPI: Lookup MediaKeys object for session_id DPI -> rialtoClient: selectKeyId(media_keys_handle, session_id, key_id) rialtoClient -> rialtoClient: Store session_id & key_id note right The key_id should be stored with the associated session_id in a map/vector. This key_id will be retrieved later and stored in the metadata when the client calls addSegment() call. When a key session is destroyed the relevant entry in the map should be removed. See Netflix to Rialto Client diagram. end note rialtoClient --> DPI: status DPI --> Netflix: status @enduml |
@startuml autonumber box "Container" #LightGreen participant Netflix participant DPI participant rialtoClient end box box "Platform" #LightBlue participant rialtoServer participant Ocdm end box Netflix -> DPI: hasLicense(session_id, key_id) DPI -> DPI: Lookup MediaKeys object for session_id DPI -> rialtoClient: containsKey(media_keys_handle, session_id, key_id) rialtoClient -> rialtoServer: containsKey(media_keys_handle, session_id, key_id) rialtoServer -> Ocdm: opencdm_session_has_key_id(session, key_id) Ocdm --> rialtoServer: result rialtoServer --> rialtoClient: result rialtoClient --> DPI: result DPI --> Netflix: result @enduml |
Note that Remove is not required by Cobalt so we do not yet need to implement this API.
@startuml autonumber box "Container" #LightGreen participant Client participant ocdmProxy participant rialtoClient end box box "Platform" #LightBlue participant rialtoServer participant Ocdm end box Client -> ocdmProxy: opencdm_session_remove(session_id) ocdmProxy -> ocdmProxy: Lookup MediaKeys object for session_id ocdmProxy -> rialtoClient: removeKeySession(media_keys_handle, session_id) rialtoClient -> rialtoServer: removeKeySession(media_keys_handle, session_id) rialtoServer -> Ocdm: opencdm_session_remove(session_id) Ocdm --> rialtoServer: status rialtoServer --> rialtoClient: status rialtoClient --> ocdmProxy: status ocdmProxy --> Client: status @enduml |
Note that Load is not required by Cobalt so we do not yet need to implement this API.
@startuml autonumber box "Container" #LightGreen participant Client participant ocdmProxy participant rialtoClient end box box "Platform" #LightBlue participant rialtoServer participant Ocdm end box Client -> ocdmProxy: opencdm_session_load(session_id) ocdmProxy -> ocdmProxy: Lookup MediaKeys object for session_id ocdmProxy -> rialtoClient: loadKeySession(media_keys_handle, session_id) rialtoClient -> rialtoServer: loadKeySession(media_keys_handle, session_id) rialtoServer -> Ocdm: opencdm_session_load(session_id) Ocdm --> rialtoServer: status rialtoServer --> rialtoClient: status rialtoClient --> ocdmProxy: status ocdmProxy --> Client: status @enduml |
@startuml autonumber box "Container" #LightGreen participant Cobalt participant Starboard participant ocdmProxy participant rialtoClient end box box "Platform" #LightBlue participant rialtoServer participant Ocdm end box Cobalt -> Starboard: SbDrmCloseSession(media_keys_handle, session_id) Starboard -> ocdmProxy: opencdm_session_close(session_id) ocdmProxy -> ocdmProxy: Lookup MediaKeys object for session_id ocdmProxy -> rialtoClient: closeKeySession(media_keys_handle, session_id) rialtoClient -> rialtoServer: closeKeySession(media_keys_handle, session_id) opt media_keys.key_system == "com.netflix.playready" rialtoServer -> Ocdm: opencdm_session_cancel_challenge_data(session_id) Ocdm --> rialtoServer: status rialtoServer -> Ocdm: opencdm_session_clean_decrypt_context(session_id) Ocdm --> rialtoServer: status else !Netflix rialtoServer -> Ocdm: opencdm_session_close(session_id) note right: TODO: Current code only calls for !Netflix\nbut maybe should we always call it? Ocdm --> rialtoServer: status end rialtoServer -> Ocdm: opencdm_destruct_session(session_id) Ocdm --> rialtoServer: status rialtoServer --> rialtoClient: status rialtoClient --> ocdmProxy: status ocdmProxy --> Starboard: status Starboard -/ Cobalt: SbDrmSessionClosedFunc(media_keys_handle, context, session_id) Starboard --> Cobalt: status @enduml |
@startuml autonumber box "Container" #LightGreen participant Netflix participant DPI participant rialtoClient end box box "Platform" #LightBlue participant rialtoServer participant Ocdm end box Netflix -> DPI: ~IDrmSession() DPI -> DPI: Lookup MediaKeys object for session_id DPI -> rialtoClient: closeKeySession(media_keys_handle, session_id) rialtoClient -> rialtoServer: closeKeySession(media_keys_handle, session_id) note over rialtoServer, Ocdm: Same sequence as closeKeySession above rialtoServer --> rialtoClient: status rialtoClient --> DPI: status DPI --> Netflix: @enduml |