Provides definitions that enable DRM support, which are common between Player
and Decoder interfaces.

## Macros

### kSbDrmSystemInvalid

An invalid SbDrmSystem.

### kSbDrmTicketInvalid

A ticket for callback invocations initiated by the DRM system.

## Enums

### SbDrmEncryptionScheme

Encryption scheme of the input sample, as defined in ISO/IEC 23001 part 7.

#### Values

- `kSbDrmEncryptionSchemeAesCtr`
- `kSbDrmEncryptionSchemeAesCbc`

### SbDrmKeyStatus

Status of a particular media key. <https://www.w3.org/TR/encrypted-media/#idl-def-mediakeystatus>

#### Values

- `kSbDrmKeyStatusUsable`
- `kSbDrmKeyStatusExpired`
- `kSbDrmKeyStatusReleased`
- `kSbDrmKeyStatusRestricted`
- `kSbDrmKeyStatusDownscaled`
- `kSbDrmKeyStatusPending`
- `kSbDrmKeyStatusError`

### SbDrmSessionRequestType

The type of the session request. <https://www.w3.org/TR/encrypted-media/#idl-def-mediakeymessagetype>

#### Values

- `kSbDrmSessionRequestTypeLicenseRequest`
- `kSbDrmSessionRequestTypeLicenseRenewal`
- `kSbDrmSessionRequestTypeLicenseRelease`
- `kSbDrmSessionRequestTypeIndividualizationRequest`

### SbDrmStatus

The status of session related operations. Used by
`SbDrmSessionUpdateRequestFunc`, `SbDrmSessionUpdatedFunc`, and
`SbDrmServerCertificateUpdatedFunc` to indicate the status of the operation. <https://w3c.github.io/encrypted-media/#error-names>

#### Values

- `kSbDrmStatusSuccess`
- `kSbDrmStatusTypeError`
- `kSbDrmStatusNotSupportedError`
- `kSbDrmStatusInvalidStateError`
- `kSbDrmStatusQuotaExceededError`
- `kSbDrmStatusUnknownError`

  Use `kSbDrmStatusUnknownError` when the error status cannot map to other
  errors. Add new error codes before `kSbDrmStatusUnknownError` if needed.

## Typedefs

### SbDrmServerCertificateUpdatedFunc

A callback that notifies the caller of `SbDrmUpdateServerCertificate()` whether
the server certificate update succeeded.

#### Definition

    typedef void(* SbDrmServerCertificateUpdatedFunc) (SbDrmSystem drm_system, void *context, int ticket, SbDrmStatus status, const char *error_message)

### SbDrmSessionClosedFunc

A callback that signals when the `SbDrmSystem` closes a session.

#### Definition

    typedef void(* SbDrmSessionClosedFunc) (SbDrmSystem drm_system, void *context, const void *session_id, int session_id_size)

### SbDrmSessionKeyStatusesChangedFunc

A callback that notifies when the status of one or more keys in a session
changes. An array of all session keys (`key_ids`) and their new statuses are
passed. Any keys not in the list are considered deleted.

`number_of_keys` is the number of keys.

`key_ids` is a pointer to an array of keys.

`key_statuses` points to a vector containing the status of each key.

#### Definition

    typedef void(* SbDrmSessionKeyStatusesChangedFunc) (SbDrmSystem drm_system, void *context, const void *session_id, int session_id_size, int number_of_keys, const SbDrmKeyId *key_ids, const SbDrmKeyStatus *key_statuses)

### SbDrmSessionUpdateRequestFunc

A callback that receives a generated session update request from a
`SbDrmSystem`. The `drm_system` parameter is the DRM system on which
`SbDrmGenerateSessionUpdateRequest()` was called. The `context` parameter
matches the context passed to `SbDrmCreateSystem()`.

`status` is the status of the session request.

`type` is the status of the session request.

The `error_message` parameter provides additional details if `status` is not
`kSbDrmStatusSuccess`. It can be `NULL` if `status` is `kSbDrmStatusSuccess` or
if no error message is available.

The `ticket` parameter matches the ticket passed to
`SbDrmGenerateSessionUpdateRequest()`, or is `kSbDrmTicketInvalid` if the update
request was generated by the DRM system.

The `session_id` parameter must not be `NULL` when `ticket` is
`kSbDrmTicketInvalid`, even if an error occurred during generation. This allows
Cobalt to locate and reject the Promise associated with the
`SbDrmGenerateSessionUpdateRequest()` call.

#### Definition

    typedef void(* SbDrmSessionUpdateRequestFunc) (SbDrmSystem drm_system, void *context, int ticket, SbDrmStatus status, SbDrmSessionRequestType type, const char *error_message, const void *session_id, int session_id_size, const void *content, int content_size, const char *url)

### SbDrmSessionUpdatedFunc

A callback for notifications that indicate that a session has been added, and
subsequent encrypted samples are ready to be decoded. `drm_system` will be the
DRM system that SbDrmUpdateSession() was called on. `context` will be the same
context passed into that call to SbDrmCreateSystem().

`ticket` will be the same ticket that was passed to SbDrmUpdateSession().

`status` is the status of the session request.

The `error_message` parameter provides additional details if `status` is not
`kSbDrmStatusSuccess`. It can be `NULL` if `status` is `kSbDrmStatusSuccess` or
if no error message is available. `succeeded` is whether the session was
successfully updated or not.

#### Definition

    typedef void(* SbDrmSessionUpdatedFunc) (SbDrmSystem drm_system, void *context, int ticket, SbDrmStatus status, const char *error_message, const void *session_id, int session_id_size)

### SbDrmSystem

A handle to a DRM system used with `SbDecoder` or `SbPlayer`.

#### Definition

    typedef struct SbDrmSystemPrivate* SbDrmSystem

## Structs

### SbDrmEncryptionPattern

Encryption pattern of the input sample, as defined in ISO/IEC 23001 part 7.

#### Members

- `uint32_t crypt_byte_block`
- `uint32_t skip_byte_block`

### SbDrmKeyId

#### Members

- `uint8_t identifier`

  The ID of the license (or key) required to decrypt this sample. For
  PlayReady, this is the license GUID in packed little-endian binary form.
- `int identifier_size`

### SbDrmSampleInfo

Per-sample metadata for encrypted samples.

#### Members

- `SbDrmEncryptionScheme encryption_scheme`

  The encryption scheme of this sample.
- `SbDrmEncryptionPattern encryption_pattern`

  The encryption pattern of this sample.
- `uint8_t initialization_vector`

  The Initialization Vector needed to decrypt this sample.
- `int initialization_vector_size`

- `uint8_t identifier`

  The ID of the license (or key) required to decrypt this sample. For
  PlayReady, this is the license GUID in packed little-endian binary form.
- `int identifier_size`

- `int32_t subsample_count`

  The number of subsamples in this sample (must be at least 1).
- `const SbDrmSubSampleMapping* subsample_mapping`

  The clear/encrypted mapping of each subsample in this sample. This must be
  an array of `subsample_count` mappings.

### SbDrmSubSampleMapping

Maps the clear and encrypted bytes for a single subsample. All subsamples within
a sample must use the same encryption parameters. Clear bytes always precede
encrypted bytes in the sample.

#### Members

- `int32_t clear_byte_count`

  The number of clear (unencrypted) bytes in the subsample.
- `int32_t encrypted_byte_count`

  The number of encrypted bytes in the subsample.

## Functions

### SbDrmCloseSession

Clear any internal states/resources related to the specified `session_id`.

`drm_system` must not be `kSbDrmSystemInvalid`. `session_id` must not be NULL.

#### Declaration

    void SbDrmCloseSession(SbDrmSystem drm_system, const void *session_id, int session_id_size)

### SbDrmCreateSystem

Creates a new DRM system used when constructing an `SbPlayer` or `SbDecoder`.

This function returns `kSbDrmSystemInvalid` if `key_system` is unsupported.

Also see the documentation of SbDrmGenerateSessionUpdateRequest() and
SbDrmUpdateSession() for more details.

- `key_system`: The DRM key system to be created. The value should be in the
  form of "com.example.somesystem". All letters in the value should be
  lowercase and will be matched exactly with known DRM key systems of the
  platform. Note the key system will be matched case sensitive. For more
  details, refer to <https://w3c.github.io/encrypted-media/#dfn-key-system-s>

- `context`: An opaque value passed to the callbacks.

- `update_request_callback`: A callback invoked after calling
  `SbDrmGenerateSessionUpdateRequest()`.

- `session_updated_callback`: A callback invoked after calling
  `SbDrmUpdateSession()`.

- `key_statuses_changed_callback`: A callback invoked when key statuses
  change.

- `server_certificate_updated_callback`: A callback invoked once to report
  whether the server certificate updated successfully. This callback may be
  invoked before the function returns.

- `session_closed_callback`: A callback invoked when a session closes. If
  `NULL` is passed for any of the callbacks (`update_request_callback`,
  `session_updated_callback`, `key_statuses_changed_callback`,
  `server_certificate_updated_callback`, or `session_closed_callback`), then
  `kSbDrmSystemInvalid` must be returned.

#### Declaration

    SbDrmSystem SbDrmCreateSystem(const char *key_system, void *context, SbDrmSessionUpdateRequestFunc update_request_callback, SbDrmSessionUpdatedFunc session_updated_callback, SbDrmSessionKeyStatusesChangedFunc key_statuses_changed_callback, SbDrmServerCertificateUpdatedFunc server_certificate_updated_callback, SbDrmSessionClosedFunc session_closed_callback)

### SbDrmDestroySystem

Destroys `drm_system`, implicitly removing its installed keys and invalidating
outstanding session update requests. You must destroy any associated `SbPlayer`
or `SbDecoder` before destroying the DRM system.

All callbacks are guaranteed to be finished when this function returns. As a
result, if this function is called from a callback that is passed to
SbDrmCreateSystem(), a deadlock will occur.

- `drm_system`: The DRM system to be destroyed. Must not be `kSbDrmSystemInvalid`.

#### Declaration

    void SbDrmDestroySystem(SbDrmSystem drm_system)

### SbDrmGenerateSessionUpdateRequest

Asynchronously generates a session update request payload for the specified
`initialization_data` and `type` (case-sensitive) extracted from the media
stream, using the key system of `drm_system`.

This function invokes the `update_request_callback` defined during
`SbDrmCreateSystem()`. It passes the `context` and a populated request, or a
`NULL` `session_id` if an error occurred.

`drm_system`'s `context` may be used to route callbacks back to an object
instance.

Callbacks may be called either from the current thread before this function
returns or from another thread.

- `drm_system`: The DRM system that defines the key system used for the
  session update request payload as well as the callback function that is
  called as a result of the function being called. Must not be
  `kSbDrmSystemInvalid`.

- `ticket`: The opaque ID that distinguishes callbacks from multiple
  concurrent calls to SbDrmGenerateSessionUpdateRequest(), which will be
  passed to `update_request_callback` as-is. The caller must ensure ticket
  uniqueness; issuing multiple requests with the same ticket may result in
  undefined behavior. The value `kSbDrmTicketInvalid` must not be used.

- `type`: The case-sensitive type of the session update request payload. Must
  not be NULL.

- `initialization_data`: The data for which the session update request payload
  is created. Must not be NULL.

- `initialization_data_size`: The size of the session update request payload.

#### Declaration

    void SbDrmGenerateSessionUpdateRequest(SbDrmSystem drm_system, int ticket, const char *type, const void *initialization_data, int initialization_data_size)

### SbDrmGetMetrics

Gets the metrics of the underlying DRM system.

On implementations supporting DRM system metrics, this function returns a
pointer to the metrics as a blob. The blob is encoded using URL-safe base64
without padding or line wrapping. The size of the encoded result is written to
`size`. For example, on Android API level 28 or later, it should return the
result of `MediaDrm.getPropertyByteArray("metrics")`, encoded using url safe
base64 without padding and line wrapping. On systems using Widevine CE CDM with
oemcrypto 16 or later, it should return the metrics retrieved via
`Cdm::getMetrics()`, encoded using url safe base64 without padding and line
wrapping. The returned pointer should remain valid and its content should remain
unmodified until the next time this function is called on the associated
`drm_system` or the `drm_system` is destroyed.

When the metrics is empty on supported system, it should return a non-null
pointer with `size` set to 0.

Returns `NULL` if the underlying DRM system does not support metrics, or if the
implementation fails to retrieve them.

`drm_system` must not be `kSbDrmSystemInvalid`. `size` must not be NULL.

#### Declaration

    const void * SbDrmGetMetrics(SbDrmSystem drm_system, int *size)

### SbDrmIsServerCertificateUpdatable

Returns `true` if the server certificate of `drm_system` can be updated via
`SbDrmUpdateServerCertificate()`. This return value must remain constant for the
lifetime of `drm_system`.

- `drm_system`: The DRM system to check if its server certificate is updatable. Must not be `kSbDrmSystemInvalid`.

#### Declaration

    bool SbDrmIsServerCertificateUpdatable(SbDrmSystem drm_system)

### SbDrmSystemIsValid

Indicates whether `drm_system` is a valid SbDrmSystem.

#### Declaration

    bool SbDrmSystemIsValid(SbDrmSystem drm)

### SbDrmTicketIsValid

Indicates whether `ticket` is a valid ticket.

#### Declaration

    bool SbDrmTicketIsValid(int ticket)

### SbDrmUpdateServerCertificate

Updates the server certificate of `drm_system`. This function can be called
multiple times. A subsequent call may occur before the callback of a previous
call invokes. Call this function only if `SbDrmIsServerCertificateUpdatable()`
returns `true`.

- `drm_system`: The DRM system whose server certificate is being updated. Must
  not be `kSbDrmSystemInvalid`.

- `ticket`: The opaque ID that distinguishes callbacks from multiple
  concurrent calls to SbDrmUpdateServerCertificate(), which will be passed to
  `server_certificate_updated_callback` as-is. The caller must ensure ticket
  uniqueness; issuing multiple requests with the same ticket may result in
  undefined behavior. The value `kSbDrmTicketInvalid` must not be used.

- `certificate`: Pointer to the server certificate data. Must not be NULL.

- `certificate_size`: Size of the server certificate data.

#### Declaration

    void SbDrmUpdateServerCertificate(SbDrmSystem drm_system, int ticket, const void *certificate, int certificate_size)

### SbDrmUpdateSession

Updates the session with `key` from the license server response, using the key
system of `drm_system`. This function invokes `session_updated_callback` with
`context` and the status. The `key` parameter must not be `NULL`.

`drm_system` must not be `kSbDrmSystemInvalid`. `ticket` is the opaque ID that
distinguishes callbacks from multiple concurrent calls to `SbDrmUpdateSession()`, which will be passed to `session_updated_callback`
as-is. The caller must ensure ticket uniqueness; issuing multiple calls with the
same ticket may result in undefined behavior.

Once the session updates successfully, an `SbPlayer` or `SbDecoder` associated
with that DRM key system can decrypt encrypted samples.

The `session_updated_callback` may be invoked from the current thread before
this function returns, or from another thread. The `session_id` parameter must
not be `NULL`.

#### Declaration

    void SbDrmUpdateSession(SbDrmSystem drm_system, int ticket, const void *key, int key_size, const void *session_id, int session_id_size)