UNPKG

shaka-player

Version:
118 lines (105 loc) 3.79 kB
/** * @license * Copyright 2016 Google Inc. * * 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. */ goog.provide('shaka.util.FairPlayUtils'); goog.require('goog.Uri'); goog.require('goog.asserts'); /** * @summary A set of FairPlay utility functions. * @exportInterface */ shaka.util.FairPlayUtils = class { /** * Using the default method, extract a content ID from the init data. This is * based on the FairPlay example documentation. * * @param {!BufferSource} initData * @return {string} * @export */ static defaultGetContentId(initData) { const uriString = shaka.util.StringUtils.fromBytesAutoDetect(initData); // The domain of that URI is the content ID according to Apple's FPS // sample. const uri = new goog.Uri(uriString); return uri.getDomain(); } /** * Transforms the init data buffer using the given data. The format is: * * <pre> * [4 bytes] initDataSize * [initDataSize bytes] initData * [4 bytes] contentIdSize * [contentIdSize bytes] contentId * [4 bytes] certSize * [certSize bytes] cert * </pre> * * @param {!BufferSource} initData * @param {!BufferSource|string} contentId * @param {?BufferSource} cert The server certificate; this will throw if not * provided. * @return {!Uint8Array} * @export */ static initDataTransform(initData, contentId, cert) { if (!cert || !cert.byteLength) { throw new shaka.util.Error( shaka.util.Error.Severity.CRITICAL, shaka.util.Error.Category.DRM, shaka.util.Error.Code.SERVER_CERTIFICATE_REQUIRED); } // From that, we build a new init data to use in the session. This is // composed of several parts. First, the init data as a UTF-16 sdk:// URL. // Second, a 4-byte LE length followed by the content ID in UTF-16-LE. // Third, a 4-byte LE length followed by the certificate. /** @type {!Uint8Array} */ let contentIdArray; if (typeof contentId == 'string') { contentIdArray = new Uint8Array( shaka.util.StringUtils.toUTF16(contentId, /* littleEndian= */ true)); } else { contentIdArray = new Uint8Array(contentId); } // The init data we get is a UTF-8 string; convert that to a UTF-16 string. const sdkUri = shaka.util.StringUtils.fromBytesAutoDetect(initData); const utf16 = shaka.util.StringUtils.toUTF16(sdkUri, /* littleEndian= */ true); const rebuiltInitData = new Uint8Array( 12 + utf16.byteLength + contentIdArray.byteLength + cert.byteLength); let offset = 0; /** @param {!Uint8Array} array */ const append = (array) => { rebuiltInitData.set(array, offset); offset += array.byteLength; }; /** @param {!Uint8Array} array */ const appendWithLength = (array) => { const view = new DataView(rebuiltInitData.buffer); const value = array.byteLength; view.setUint32(offset, value, /* littleEndian= */ true); offset += 4; append(array); }; appendWithLength(new Uint8Array(utf16)); appendWithLength(contentIdArray); appendWithLength(new Uint8Array(cert)); goog.asserts.assert( offset == rebuiltInitData.length, 'Inconsistent init data length'); return rebuiltInitData; } };