forked from youtube/cobalt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
drm.h
411 lines (369 loc) · 18.2 KB
/
drm.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
// Copyright 2016 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Module Overview: Starboard DRM module
//
// Provides definitions that allow for DRM support, which are common
// between Player and Decoder interfaces.
#ifndef STARBOARD_DRM_H_
#define STARBOARD_DRM_H_
#include "starboard/export.h"
#include "starboard/types.h"
#ifdef __cplusplus
extern "C" {
#endif
// --- Types -----------------------------------------------------------------
// The type of the session request.
// https://www.w3.org/TR/encrypted-media/#idl-def-mediakeymessagetype
typedef enum SbDrmSessionRequestType {
kSbDrmSessionRequestTypeLicenseRequest,
kSbDrmSessionRequestTypeLicenseRenewal,
kSbDrmSessionRequestTypeLicenseRelease,
kSbDrmSessionRequestTypeIndividualizationRequest,
} SbDrmSessionRequestType;
// 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
typedef enum SbDrmStatus {
kSbDrmStatusSuccess,
kSbDrmStatusTypeError,
kSbDrmStatusNotSupportedError,
kSbDrmStatusInvalidStateError,
kSbDrmStatusQuotaExceededError,
// The following error can be used when the error status cannot be mapped to
// one of the above errors.
kSbDrmStatusUnknownError,
} SbDrmStatus;
// Status of a particular media key.
// https://w3c.github.io/encrypted-media/#idl-def-MediaKeyStatus
typedef enum SbDrmKeyStatus {
kSbDrmKeyStatusUsable,
kSbDrmKeyStatusExpired,
kSbDrmKeyStatusReleased,
kSbDrmKeyStatusRestricted,
kSbDrmKeyStatusDownscaled,
kSbDrmKeyStatusPending,
kSbDrmKeyStatusError,
} SbDrmKeyStatus;
// A mapping of clear and encrypted bytes for a single subsample. All subsamples
// within a sample must be encrypted with the same encryption parameters. The
// clear bytes always appear first in the sample.
typedef struct SbDrmSubSampleMapping {
// How many bytes of the corresponding subsample are not encrypted
int32_t clear_byte_count;
// How many bytes of the corresponding subsample are encrypted.
int32_t encrypted_byte_count;
} SbDrmSubSampleMapping;
typedef struct SbDrmKeyId {
// 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.
uint8_t identifier[16];
int identifier_size;
} SbDrmKeyId;
// Encryption scheme of the input sample, as defined in ISO/IEC 23001 part 7.
typedef enum SbDrmEncryptionScheme {
kSbDrmEncryptionSchemeAesCtr,
kSbDrmEncryptionSchemeAesCbc,
} SbDrmEncryptionScheme;
// Encryption pattern of the input sample, as defined in ISO/IEC 23001 part 7.
typedef struct SbDrmEncryptionPattern {
uint32_t crypt_byte_block;
uint32_t skip_byte_block;
} SbDrmEncryptionPattern;
// All the optional information needed per sample for encrypted samples.
typedef struct SbDrmSampleInfo {
// The encryption scheme of this sample.
SbDrmEncryptionScheme encryption_scheme;
// The encryption pattern of this sample.
SbDrmEncryptionPattern encryption_pattern;
// The Initialization Vector needed to decrypt this sample.
uint8_t initialization_vector[16];
int initialization_vector_size;
// 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.
uint8_t identifier[16];
int identifier_size;
// The number of subsamples in this sample, must be at least 1.
int32_t subsample_count;
// The clear/encrypted mapping of each subsample in this sample. This must be
// an array of |subsample_count| mappings.
const SbDrmSubSampleMapping* subsample_mapping;
} SbDrmSampleInfo;
// A handle to a DRM system which can be used with either an SbDecoder or an
// SbPlayer.
typedef struct SbDrmSystemPrivate* SbDrmSystem;
// A callback that will receive generated session update request when requested
// from a SbDrmSystem. |drm_system| will be the DRM system that
// SbDrmGenerateSessionUpdateRequest() was called on. |context| will be the same
// context that was passed into the call to SbDrmCreateSystem().
//
// |status| is the status of the session request.
//
// |type| is the status of the session request.
//
// |error_message| may contain an optional error message when |status| isn't
// |kSbDrmStatusSuccess| to provide more details about the error. It may be
// NULL if |status| is |kSbDrmStatusSuccess| or if no error message can be
// provided.
// |ticket| will be the same ticket that was passed to
// SbDrmGenerateSessionUpdateRequest() or |kSbDrmTicketInvalid| if the update
// request was generated by the DRM system.
//
// |session_id| cannot be NULL when |ticket| is |kSbDrmTicketInvalid|, even when
// there was an error generating the request. This allows Cobalt to find and
// reject the correct Promise corresponding to the associated
// SbDrmGenerateSessionUpdateRequest().
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);
// A callback for notifications that a session has been added, and subsequent
// encrypted samples are actively 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.
//
// |error_message| may contain an optional error message when |status| isn't
// |kSbDrmStatusSuccess| to provide more details about the error. It may be
// NULL if |status| is |kSbDrmStatusSuccess| or if no error message can be
// provided.
// |succeeded| is whether the session was successfully updated or not.
typedef void (*SbDrmSessionUpdatedFunc)(SbDrmSystem drm_system,
void* context,
int ticket,
SbDrmStatus status,
const char* error_message,
const void* session_id,
int session_id_size);
// A callback for notifications that the status of one or more keys in a session
// has been changed. All keys of the session and their new status will be
// passed along. Any keys not in the list is considered as deleted.
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);
// A callback for signalling that a session has been closed by the SbDrmSystem
typedef void (*SbDrmSessionClosedFunc)(SbDrmSystem drm_system,
void* context,
const void* session_id,
int session_id_size);
// A callback to notify the caller of SbDrmUpdateServerCertificate() whether the
// update has been successfully updated or not.
typedef void (*SbDrmServerCertificateUpdatedFunc)(SbDrmSystem drm_system,
void* context,
int ticket,
SbDrmStatus status,
const char* error_message);
// --- Constants -------------------------------------------------------------
// An invalid SbDrmSystem.
#define kSbDrmSystemInvalid ((SbDrmSystem)NULL)
// A ticket for callback invocations initiated by the DRM system.
#define kSbDrmTicketInvalid kSbInvalidInt
// --- Functions -------------------------------------------------------------
// Indicates whether |drm_system| is a valid SbDrmSystem.
static SB_C_FORCE_INLINE bool SbDrmSystemIsValid(SbDrmSystem drm) {
return drm != kSbDrmSystemInvalid;
}
// Indicates whether |ticket| is a valid ticket.
static SB_C_FORCE_INLINE bool SbDrmTicketIsValid(int ticket) {
return ticket != kSbDrmTicketInvalid;
}
// Creates a new DRM system that can be used when constructing an SbPlayer or an
// 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" as suggested by
// https://w3c.github.io/encrypted-media/#key-system. All letters in the value
// should be lowercase and will be matched exactly with known DRM key systems of
// the platform.
// |context|: A value passed when any of this function's callback parameters are
// called.
// |update_request_callback|: A function that is called every time after
// SbDrmGenerateSessionUpdateRequest() is called.
// |session_updated_callback|: A function that is called every time after
// SbDrmUpdateSession() is called.
// |key_statuses_changed_callback|: A function that can be called to indicate
// that key statuses have changed.
// |server_certificate_updated_callback|: A function that is called to report
// whether the server certificate has been successfully updated. It is called
// once and only once. It is possible that the callback is called before the
// function returns.
// |session_closed_callback|: A function that can be called to indicate that a
// session has closed.
// 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.
SB_EXPORT 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);
// Asynchronously generates a session update request payload for
// |initialization_data|, of |initialization_data_size|, in case sensitive
// |type|, extracted from the media stream, in |drm_system|'s key system.
//
// This function calls |drm_system|'s |update_request_callback| function,
// which is defined when the DRM system is created by SbDrmCreateSystem. When
// calling that function, this function either sends |context| (also from
// |SbDrmCreateSystem|) and a populated request, or it sends 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 allows to distinguish callbacks from multiple
// concurrent calls to SbDrmGenerateSessionUpdateRequest(), which will be passed
// to |update_request_callback| as-is. It is the responsibility of the caller to
// establish 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.
SB_EXPORT void SbDrmGenerateSessionUpdateRequest(
SbDrmSystem drm_system,
int ticket,
const char* type,
const void* initialization_data,
int initialization_data_size);
// Update session with |key|, in |drm_system|'s key system, from the license
// server response. Calls |session_updated_callback| with |context| and whether
// the update succeeded. |context| may be used to route callbacks back to an
// object instance. The |key| must not be NULL.
//
// |drm_system| must not be |kSbDrmSystemInvalid|.
// |ticket| is the opaque ID that allows to distinguish callbacks from multiple
// concurrent calls to SbDrmUpdateSession(), which will be passed to
// |session_updated_callback| as-is. It is the responsibility of the caller to
// establish ticket uniqueness, issuing multiple calls with the same ticket may
// result in undefined behavior.
//
// Once the session is successfully updated, an SbPlayer or SbDecoder associated
// with that DRM key system will be able to decrypt encrypted samples.
//
// |drm_system|'s |session_updated_callback| may called either from the current
// thread before this function returns or from another thread.
// The |session_id| must not be NULL.
SB_EXPORT void SbDrmUpdateSession(SbDrmSystem drm_system,
int ticket,
const void* key,
int key_size,
const void* session_id,
int session_id_size);
// Clear any internal states/resources related to the specified |session_id|.
//
// |drm_system| must not be |kSbDrmSystemInvalid|.
// |session_id| must not be NULL.
SB_EXPORT void SbDrmCloseSession(SbDrmSystem drm_system,
const void* session_id,
int session_id_size);
// Returns true if server certificate of |drm_system| can be updated via
// SbDrmUpdateServerCertificate(). The return value should remain the same
// during the life time of |drm_system|.
//
// |drm_system|: The DRM system to check if its server certificate is updatable.
// Must not be |kSbDrmSystemInvalid|.
SB_EXPORT bool SbDrmIsServerCertificateUpdatable(SbDrmSystem drm_system);
// Update the server certificate of |drm_system|. The function can be called
// multiple times. It is possible that a call to it happens before the callback
// of a previous call is called.
// Note that this function should only be called after
// |SbDrmIsServerCertificateUpdatable| is called first and returned true.
//
// |drm_system|: The DRM system whose server certificate is being updated. Must
// not be |kSbDrmSystemInvalid|.
// |ticket|: The opaque ID that allows to distinguish callbacks from multiple
// concurrent calls to SbDrmUpdateServerCertificate(), which will be passed to
// |server_certificate_updated_callback| as-is. It is the responsibility of
// the caller to establish 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.
SB_EXPORT void SbDrmUpdateServerCertificate(SbDrmSystem drm_system,
int ticket,
const void* certificate,
int certificate_size);
// Get the metrics of the underlying drm system.
//
// When it is called on an implementation that supports drm system metrics, it
// should return a pointer containing the metrics as a blob, encoded using url
// safe base64 without padding and line wrapping, with the size of the encoded
// result in |size| on return. 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.
//
// It should return NULL when there is no metrics support in the underlying drm
// system, or when the drm system implementation fails to retrieve the metrics.
//
// |drm_system| must not be |kSbDrmSystemInvalid|.
// |size| must not be NULL.
SB_EXPORT const void* SbDrmGetMetrics(SbDrmSystem drm_system, int* size);
// Destroys |drm_system|, which implicitly removes all keys installed in it and
// invalidates all outstanding session update requests. A DRM system cannot be
// destroyed unless any associated SbPlayer or SbDecoder has first been
// destroyed.
//
// 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|.
SB_EXPORT void SbDrmDestroySystem(SbDrmSystem drm_system);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // STARBOARD_DRM_H_