shaka-player 4.3.9 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/build-and-test.yaml +11 -18
- package/.github/workflows/compute-incremental-coverage.py +3 -0
- package/.github/workflows/release-please.yaml +7 -0
- package/.github/workflows/selenium-lab-tests.yaml +45 -10
- package/AUTHORS +9 -0
- package/CHANGELOG.md +295 -190
- package/CONTRIBUTORS +8 -0
- package/LICENSE +32 -0
- package/README.md +63 -10
- package/demo/autoTemplate.txt +40 -5
- package/demo/close_button.js +11 -0
- package/demo/common/asset.js +13 -1
- package/demo/common/assets.js +112 -28
- package/demo/common/message_ids.js +25 -1
- package/demo/config.js +69 -10
- package/demo/customWarning.txt +2 -2
- package/demo/index.html +3 -1
- package/demo/locales/en.json +26 -2
- package/demo/locales/source.json +105 -9
- package/demo/main.js +57 -9
- package/demo/search.js +3 -1
- package/demo/service_worker.js +3 -0
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +132 -118
- package/dist/demo.compiled.debug.map +3 -3
- package/dist/demo.compiled.js +132 -118
- package/dist/demo.compiled.map +3 -3
- package/dist/deps.js +46 -28
- package/dist/locales.js +31 -31
- package/dist/receiver.compiled.debug.js +60 -52
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +60 -52
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.d.ts +676 -391
- package/dist/shaka-player.compiled.debug.d.ts +676 -391
- package/dist/shaka-player.compiled.debug.externs.js +1188 -616
- package/dist/shaka-player.compiled.debug.js +1046 -700
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +1188 -616
- package/dist/shaka-player.compiled.js +1094 -933
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +677 -392
- package/dist/shaka-player.ui.debug.d.ts +677 -392
- package/dist/shaka-player.ui.debug.externs.js +1023 -451
- package/dist/shaka-player.ui.debug.js +1101 -738
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +1023 -451
- package/dist/shaka-player.ui.js +1244 -1071
- package/dist/shaka-player.ui.map +4 -4
- package/docs/tutorials/ad_monetization.md +15 -1
- package/docs/tutorials/application-level-redirects.md +1 -1
- package/docs/tutorials/config.md +9 -5
- package/docs/tutorials/drm-config.md +61 -0
- package/docs/tutorials/fairplay.md +19 -4
- package/docs/tutorials/license-server-auth.md +4 -4
- package/docs/tutorials/license-wrapping.md +2 -2
- package/docs/tutorials/ui-customization.md +7 -3
- package/docs/tutorials/ui.md +7 -7
- package/docs/tutorials/upgrade.md +3 -0
- package/externs/ima.js +123 -2
- package/externs/isoboxer.js +217 -0
- package/externs/mediakeys.js +18 -0
- package/externs/mux.js +1 -105
- package/externs/pictureinpicture.js +48 -0
- package/externs/shaka/ads.js +61 -1
- package/externs/shaka/cea.js +110 -0
- package/externs/shaka/codecs.js +32 -0
- package/externs/shaka/manifest.js +101 -1
- package/externs/shaka/manifest_parser.js +0 -10
- package/externs/shaka/net.js +36 -7
- package/externs/shaka/offline.js +8 -1
- package/externs/shaka/player.js +220 -21
- package/externs/shaka/text.js +1 -382
- package/externs/shaka/transmuxer.js +59 -0
- package/karma.conf.js +15 -0
- package/lib/abr/simple_abr_manager.js +6 -3
- package/lib/ads/ad_manager.js +60 -2
- package/lib/ads/client_side_ad.js +86 -0
- package/lib/ads/client_side_ad_manager.js +93 -5
- package/lib/ads/server_side_ad.js +86 -0
- package/lib/ads/server_side_ad_manager.js +13 -0
- package/lib/cast/cast_utils.js +1 -0
- package/lib/cea/cea608_data_channel.js +24 -14
- package/lib/cea/cea608_memory.js +5 -2
- package/lib/cea/cea708_service.js +8 -9
- package/lib/cea/cea708_window.js +1 -2
- package/lib/cea/cea_decoder.js +23 -6
- package/lib/cea/cea_utils.js +25 -2
- package/lib/cea/dummy_caption_decoder.js +21 -0
- package/lib/cea/dummy_cea_parser.js +1 -3
- package/lib/cea/mp4_cea_parser.js +15 -10
- package/lib/cea/ts_cea_parser.js +69 -0
- package/lib/dash/content_protection.js +32 -2
- package/lib/dash/dash_parser.js +93 -31
- package/lib/dash/mpd_utils.js +6 -25
- package/lib/dash/segment_base.js +12 -14
- package/lib/dash/segment_list.js +10 -6
- package/lib/dash/segment_template.js +349 -32
- package/lib/dependencies/all.js +8 -0
- package/lib/hls/hls_classes.js +33 -8
- package/lib/hls/hls_parser.js +805 -191
- package/lib/hls/manifest_text_parser.js +4 -14
- package/lib/media/adaptation_set_criteria.js +43 -3
- package/lib/media/closed_caption_parser.js +74 -12
- package/lib/media/drm_engine.js +189 -49
- package/lib/media/gap_jumping_controller.js +1 -1
- package/lib/media/manifest_parser.js +34 -0
- package/lib/media/media_source_capabilities.js +10 -0
- package/lib/media/media_source_engine.js +475 -231
- package/lib/media/playhead.js +1 -1
- package/lib/media/presentation_timeline.js +62 -0
- package/lib/media/segment_index.js +50 -14
- package/lib/media/segment_prefetch.js +277 -0
- package/lib/media/segment_reference.js +70 -4
- package/lib/media/streaming_engine.js +258 -81
- package/lib/media/video_wrapper.js +15 -7
- package/lib/mss/content_protection.js +353 -0
- package/lib/mss/mss_parser.js +1081 -0
- package/lib/net/networking_engine.js +60 -10
- package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
- package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
- package/lib/offline/manifest_converter.js +6 -0
- package/lib/offline/storage.js +2 -4
- package/lib/player.js +309 -105
- package/lib/polyfill/media_capabilities.js +43 -3
- package/lib/polyfill/patchedmediakeys_apple.js +5 -0
- package/lib/polyfill/patchedmediakeys_nop.js +5 -0
- package/lib/polyfill/patchedmediakeys_webkit.js +5 -0
- package/lib/text/cue.js +208 -130
- package/lib/text/lrc_text_parser.js +2 -2
- package/lib/text/mp4_vtt_parser.js +2 -2
- package/lib/text/sbv_text_parser.js +1 -1
- package/lib/text/simple_text_displayer.js +2 -1
- package/lib/text/srt_text_parser.js +9 -1
- package/lib/text/ssa_text_parser.js +2 -2
- package/lib/text/text_engine.js +3 -21
- package/lib/text/text_utils.js +71 -20
- package/lib/text/ui_text_displayer.js +14 -14
- package/lib/text/vtt_text_parser.js +22 -14
- package/lib/transmuxer/aac_transmuxer.js +224 -0
- package/lib/transmuxer/ac3.js +142 -0
- package/lib/transmuxer/ac3_transmuxer.js +212 -0
- package/lib/transmuxer/adts.js +232 -0
- package/lib/transmuxer/ec3.js +103 -0
- package/lib/transmuxer/ec3_transmuxer.js +212 -0
- package/lib/transmuxer/h264.js +324 -0
- package/lib/transmuxer/mp3_transmuxer.js +204 -0
- package/lib/transmuxer/mpeg_audio.js +196 -0
- package/lib/transmuxer/mpeg_ts_transmuxer.js +182 -0
- package/lib/transmuxer/mss_transmuxer.js +389 -0
- package/lib/{media/transmuxer.js → transmuxer/muxjs_transmuxer.js} +34 -80
- package/lib/transmuxer/transmuxer_engine.js +161 -0
- package/lib/transmuxer/ts_transmuxer.js +738 -0
- package/lib/util/cmcd_manager.js +131 -71
- package/lib/util/error.js +62 -26
- package/lib/util/exp_golomb.js +220 -0
- package/lib/util/fairplay_utils.js +64 -13
- package/lib/util/id3_utils.js +56 -3
- package/lib/util/language_utils.js +11 -8
- package/lib/util/manifest_parser_utils.js +3 -0
- package/lib/util/mime_utils.js +44 -7
- package/lib/util/mp4_box_parsers.js +233 -5
- package/lib/util/mp4_generator.js +1381 -0
- package/lib/util/periods.js +40 -34
- package/lib/util/platform.js +25 -3
- package/lib/util/player_configuration.js +38 -1
- package/lib/util/stream_utils.js +138 -27
- package/lib/util/text_parser.js +1 -1
- package/lib/util/ts_parser.js +470 -47
- package/lib/util/xml_utils.js +16 -3
- package/maintained-branches.md +2 -2
- package/package.json +4 -2
- package/roadmap.md +21 -6
- package/shaka-player.uncompiled.js +18 -0
- package/test/abr/simple_abr_manager_unit.js +32 -4
- package/test/ads/ad_manager_unit.js +18 -2
- package/test/cast/cast_utils_unit.js +7 -2
- package/test/cea/cea608_memory_unit.js +24 -0
- package/test/cea/cea_decoder_unit.js +33 -0
- package/test/dash/dash_parser_content_protection_unit.js +93 -3
- package/test/dash/dash_parser_live_unit.js +56 -13
- package/test/dash/dash_parser_manifest_unit.js +70 -2
- package/test/dash/dash_parser_segment_base_unit.js +14 -9
- package/test/dash/dash_parser_segment_template_unit.js +286 -6
- package/test/demo/demo_unit.js +5 -1
- package/test/hls/hls_live_unit.js +188 -28
- package/test/hls/hls_parser_unit.js +250 -109
- package/test/hls/manifest_text_parser_unit.js +18 -13
- package/test/media/adaptation_set_criteria_unit.js +46 -14
- package/test/media/adaptation_set_unit.js +2 -0
- package/test/media/drm_engine_integration.js +11 -8
- package/test/media/drm_engine_unit.js +220 -7
- package/test/media/media_source_engine_integration.js +122 -38
- package/test/media/media_source_engine_unit.js +133 -153
- package/test/media/playhead_unit.js +3 -0
- package/test/media/presentation_timeline_unit.js +51 -0
- package/test/media/segment_index_unit.js +52 -0
- package/test/media/segment_prefetch_unit.js +243 -0
- package/test/media/streaming_engine_integration.js +9 -3
- package/test/media/streaming_engine_unit.js +440 -59
- package/test/mss/mss_parser_content_protection_unit.js +49 -0
- package/test/mss/mss_parser_unit.js +472 -0
- package/test/mss/mss_player_integration.js +123 -0
- package/test/offline/manifest_convert_unit.js +9 -0
- package/test/offline/storage_integration.js +6 -1
- package/test/player_integration.js +4 -1
- package/test/player_unit.js +386 -133
- package/test/polyfill/media_capabilities_unit.js +18 -0
- package/test/test/assets/hls-raw-aac/fileSequence0.aac +0 -0
- package/test/test/assets/hls-raw-aac/fileSequence1.aac +0 -0
- package/test/test/assets/hls-raw-aac/fileSequence2.aac +0 -0
- package/test/test/assets/hls-raw-aac/fileSequence3.aac +0 -0
- package/test/test/assets/hls-raw-aac/manifest.m3u8 +4 -0
- package/test/test/assets/hls-raw-aac/stream.m4a.m3u8 +14 -0
- package/test/test/assets/hls-raw-ac3/fileSequence0.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/fileSequence1.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/fileSequence2.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/fileSequence3.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/fileSequence4.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/fileSequence5.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/fileSequence6.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/fileSequence7.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/prog_index.m3u8 +31 -0
- package/test/test/assets/hls-raw-ec3/fileSequence0.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/fileSequence1.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/fileSequence2.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/fileSequence3.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/fileSequence4.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/fileSequence5.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/fileSequence6.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/fileSequence7.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/prog_index.m3u8 +31 -0
- package/test/test/assets/hls-raw-mp3/chunklist_w905519204.m3u8 +13 -0
- package/test/test/assets/hls-raw-mp3/media_w905519204_0.mp3 +0 -0
- package/test/test/assets/hls-raw-mp3/media_w905519204_1.mp3 +0 -0
- package/test/test/assets/hls-raw-mp3/media_w905519204_2.mp3 +0 -0
- package/test/test/assets/hls-raw-mp3/media_w905519204_3.mp3 +0 -0
- package/test/test/assets/hls-raw-mp3/playlist.m3u8 +4 -0
- package/test/test/assets/hls-ts-aac/playlist.m3u8 +23 -0
- package/test/test/assets/hls-ts-aac/segment_0.ts +0 -0
- package/test/test/assets/hls-ts-aac/segment_1.ts +0 -0
- package/test/test/assets/hls-ts-aac/segment_2.ts +0 -0
- package/test/test/assets/hls-ts-aac/segment_3.ts +0 -0
- package/test/test/assets/hls-ts-aac/segment_4.ts +0 -0
- package/test/test/assets/hls-ts-aac/segment_5.ts +0 -0
- package/test/test/assets/hls-ts-aac/segment_6.ts +0 -0
- package/test/test/assets/hls-ts-aac/segment_7.ts +0 -0
- package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0000.ts +0 -0
- package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0001.ts +0 -0
- package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0002.ts +0 -0
- package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0003.ts +0 -0
- package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0004.ts +0 -0
- package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0005.ts +0 -0
- package/test/test/assets/hls-ts-ac3/prog_index.m3u8 +19 -0
- package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0000.ts +0 -0
- package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0001.ts +0 -0
- package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0002.ts +0 -0
- package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0003.ts +0 -0
- package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0004.ts +0 -0
- package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0005.ts +0 -0
- package/test/test/assets/hls-ts-ec3/prog_index.m3u8 +19 -0
- package/test/test/assets/hls-ts-h264/fileSequence0.ts +0 -0
- package/test/test/assets/hls-ts-h264/fileSequence1.ts +0 -0
- package/test/test/assets/hls-ts-h264/fileSequence2.ts +0 -0
- package/test/test/assets/hls-ts-h264/fileSequence3.ts +0 -0
- package/test/test/assets/hls-ts-h264/fileSequence4.ts +0 -0
- package/test/test/assets/hls-ts-h264/fileSequence5.ts +0 -0
- package/test/test/assets/hls-ts-h264/prog_index.m3u8 +25 -0
- package/test/test/assets/hls-ts-mp3/manifest.m3u8 +13 -0
- package/test/test/assets/hls-ts-mp3/media_w239891843_0.ts +0 -0
- package/test/test/assets/hls-ts-mp3/media_w239891843_1.ts +0 -0
- package/test/test/assets/hls-ts-mp3/media_w239891843_2.ts +0 -0
- package/test/test/assets/hls-ts-mp3/media_w239891843_3.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/chunk.m3u8 +17 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/n_0_0_0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/n_1_0_0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/n_2_0_0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/n_3_0_0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/n_4_0_0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/n_5_0_0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/playlist.m3u8 +4 -0
- package/test/test/boot.js +7 -2
- package/test/test/util/fake_ad.js +99 -0
- package/test/test/util/fake_ad_manager.js +7 -1
- package/test/test/util/fake_networking_engine.js +41 -14
- package/test/test/util/fake_segment_prefetch.js +81 -0
- package/test/test/util/manifest_generator.js +19 -5
- package/test/test/util/mss_parser_util.js +115 -0
- package/test/test/util/offline_utils.js +1 -0
- package/test/test/util/simple_fakes.js +12 -3
- package/test/test/util/streaming_engine_util.js +14 -4
- package/test/test/util/ttml_utils.js +2 -2
- package/test/test/util/ui_utils.js +5 -1
- package/test/text/cue_integration.js +1 -1
- package/test/text/srt_text_parser_unit.js +78 -0
- package/test/text/text_engine_unit.js +17 -8
- package/test/text/ui_text_displayer_unit.js +4 -4
- package/test/text/vtt_text_parser_unit.js +59 -40
- package/test/text/web_vtt_generator_unit.js +9 -3
- package/test/{media/transmuxer_integration.js → transmuxer/muxjs_transmuxer_integration.js} +30 -33
- package/test/transmuxer/transmuxer_engine_integration.js +60 -0
- package/test/transmuxer/transmuxer_integration.js +296 -0
- package/test/util/cmcd_manager_unit.js +162 -13
- package/test/util/language_utils_unit.js +9 -2
- package/test/util/mp4_box_parsers_unit.js +39 -4
- package/test/util/periods_unit.js +34 -26
- package/test/util/stream_utils_unit.js +60 -107
- package/ui/controls.js +19 -1
- package/ui/controls.less +1 -0
- package/ui/externs/ui.js +13 -3
- package/ui/language_utils.js +15 -0
- package/ui/less/thumbnails.less +26 -0
- package/ui/locales/oc.json +42 -0
- package/ui/pip_button.js +83 -2
- package/ui/range_element.js +15 -0
- package/ui/resolution_selection.js +9 -2
- package/ui/seek_bar.js +230 -1
- package/ui/ui.js +5 -0
- package/lib/cea/i_caption_decoder.js +0 -51
- package/lib/cea/i_cea_parser.js +0 -68
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
/*! @license
|
|
2
|
+
* Shaka Player
|
|
3
|
+
* Copyright 2016 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
goog.provide('shaka.mss.ContentProtection');
|
|
8
|
+
|
|
9
|
+
goog.require('shaka.log');
|
|
10
|
+
goog.require('shaka.util.BufferUtils');
|
|
11
|
+
goog.require('shaka.util.ManifestParserUtils');
|
|
12
|
+
goog.require('shaka.util.Pssh');
|
|
13
|
+
goog.require('shaka.util.StringUtils');
|
|
14
|
+
goog.require('shaka.util.Uint8ArrayUtils');
|
|
15
|
+
goog.require('shaka.util.XmlUtils');
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @summary A set of functions for parsing and interpreting Protection
|
|
20
|
+
* elements.
|
|
21
|
+
*/
|
|
22
|
+
shaka.mss.ContentProtection = class {
|
|
23
|
+
/**
|
|
24
|
+
* Parses info from the Protection elements.
|
|
25
|
+
*
|
|
26
|
+
* @param {!Array.<!Element>} elems
|
|
27
|
+
* @param {!Object.<string, string>} keySystemsBySystemId
|
|
28
|
+
* @return {!Array.<shaka.extern.DrmInfo>}
|
|
29
|
+
*/
|
|
30
|
+
static parseFromProtection(elems, keySystemsBySystemId) {
|
|
31
|
+
const ContentProtection = shaka.mss.ContentProtection;
|
|
32
|
+
const XmlUtils = shaka.util.XmlUtils;
|
|
33
|
+
|
|
34
|
+
/** @type {!Array.<!Element>} */
|
|
35
|
+
let protectionHeader = [];
|
|
36
|
+
for (const elem of elems) {
|
|
37
|
+
protectionHeader = protectionHeader.concat(
|
|
38
|
+
XmlUtils.findChildren(elem, 'ProtectionHeader'));
|
|
39
|
+
}
|
|
40
|
+
if (!protectionHeader.length) {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
return ContentProtection.convertElements_(
|
|
44
|
+
protectionHeader, keySystemsBySystemId);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Parses an Array buffer starting at byteOffset for PlayReady Object Records.
|
|
49
|
+
* Each PRO Record is preceded by its PlayReady Record type and length in
|
|
50
|
+
* bytes.
|
|
51
|
+
*
|
|
52
|
+
* PlayReady Object Record format: https://goo.gl/FTcu46
|
|
53
|
+
*
|
|
54
|
+
* @param {!DataView} view
|
|
55
|
+
* @param {number} byteOffset
|
|
56
|
+
* @return {!Array.<shaka.mss.ContentProtection.PlayReadyRecord>}
|
|
57
|
+
* @private
|
|
58
|
+
*/
|
|
59
|
+
static parseMsProRecords_(view, byteOffset) {
|
|
60
|
+
const records = [];
|
|
61
|
+
|
|
62
|
+
while (byteOffset < view.byteLength - 1) {
|
|
63
|
+
const type = view.getUint16(byteOffset, true);
|
|
64
|
+
byteOffset += 2;
|
|
65
|
+
|
|
66
|
+
const byteLength = view.getUint16(byteOffset, true);
|
|
67
|
+
byteOffset += 2;
|
|
68
|
+
|
|
69
|
+
if ((byteLength & 1) != 0 || byteLength + byteOffset > view.byteLength) {
|
|
70
|
+
shaka.log.warning('Malformed MS PRO object');
|
|
71
|
+
return [];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const recordValue = shaka.util.BufferUtils.toUint8(
|
|
75
|
+
view, byteOffset, byteLength);
|
|
76
|
+
records.push({
|
|
77
|
+
type: type,
|
|
78
|
+
value: recordValue,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
byteOffset += byteLength;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return records;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Parses a buffer for PlayReady Objects. The data
|
|
89
|
+
* should contain a 32-bit integer indicating the length of
|
|
90
|
+
* the PRO in bytes. Following that, a 16-bit integer for
|
|
91
|
+
* the number of PlayReady Object Records in the PRO. Lastly,
|
|
92
|
+
* a byte array of the PRO Records themselves.
|
|
93
|
+
*
|
|
94
|
+
* PlayReady Object format: https://goo.gl/W8yAN4
|
|
95
|
+
*
|
|
96
|
+
* @param {BufferSource} data
|
|
97
|
+
* @return {!Array.<shaka.mss.ContentProtection.PlayReadyRecord>}
|
|
98
|
+
* @private
|
|
99
|
+
*/
|
|
100
|
+
static parseMsPro_(data) {
|
|
101
|
+
let byteOffset = 0;
|
|
102
|
+
const view = shaka.util.BufferUtils.toDataView(data);
|
|
103
|
+
|
|
104
|
+
// First 4 bytes is the PRO length (DWORD)
|
|
105
|
+
const byteLength = view.getUint32(byteOffset, /* littleEndian= */ true);
|
|
106
|
+
byteOffset += 4;
|
|
107
|
+
|
|
108
|
+
if (byteLength != data.byteLength) {
|
|
109
|
+
// Malformed PRO
|
|
110
|
+
shaka.log.warning('PlayReady Object with invalid length encountered.');
|
|
111
|
+
return [];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Skip PRO Record count (WORD)
|
|
115
|
+
byteOffset += 2;
|
|
116
|
+
|
|
117
|
+
// Rest of the data contains the PRO Records
|
|
118
|
+
const ContentProtection = shaka.mss.ContentProtection;
|
|
119
|
+
return ContentProtection.parseMsProRecords_(view, byteOffset);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Parse a PlayReady Header format: https://goo.gl/dBzxNA
|
|
124
|
+
* a try to find the LA_URL value.
|
|
125
|
+
*
|
|
126
|
+
* @param {!Element} xml
|
|
127
|
+
* @return {string}
|
|
128
|
+
* @private
|
|
129
|
+
*/
|
|
130
|
+
static getLaurl_(xml) {
|
|
131
|
+
// LA_URL element is optional and no more than one is
|
|
132
|
+
// allowed inside the DATA element. Only absolute URLs are allowed.
|
|
133
|
+
// If the LA_URL element exists, it must not be empty.
|
|
134
|
+
for (const elem of xml.getElementsByTagName('DATA')) {
|
|
135
|
+
const laUrl = shaka.util.XmlUtils.findChild(elem, 'LA_URL');
|
|
136
|
+
if (laUrl) {
|
|
137
|
+
return laUrl.textContent;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Not found
|
|
142
|
+
// We return a empty string instead null because is the default value for
|
|
143
|
+
// a License in our model.
|
|
144
|
+
return '';
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Gets a PlayReady license URL from a protection element
|
|
149
|
+
* containing a PlayReady Header Object
|
|
150
|
+
*
|
|
151
|
+
* @param {!Element} element
|
|
152
|
+
* @return {string}
|
|
153
|
+
*/
|
|
154
|
+
static getPlayReadyLicenseUrl(element) {
|
|
155
|
+
const ContentProtection = shaka.mss.ContentProtection;
|
|
156
|
+
const rootElement = ContentProtection.getPlayReadyHeaderObject_(element);
|
|
157
|
+
if (!rootElement) {
|
|
158
|
+
return '';
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return ContentProtection.getLaurl_(rootElement);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Parse a PlayReady Header format: https://goo.gl/dBzxNA
|
|
166
|
+
* a try to find the KID value.
|
|
167
|
+
*
|
|
168
|
+
* @param {!Element} xml
|
|
169
|
+
* @return {?string}
|
|
170
|
+
* @private
|
|
171
|
+
*/
|
|
172
|
+
static getKID_(xml) {
|
|
173
|
+
// KID element is optional and no more than one is
|
|
174
|
+
// allowed inside the DATA element.
|
|
175
|
+
for (const elem of xml.getElementsByTagName('DATA')) {
|
|
176
|
+
const kid = shaka.util.XmlUtils.findChild(elem, 'KID');
|
|
177
|
+
if (kid) {
|
|
178
|
+
// GUID: [DWORD, WORD, WORD, 8-BYTE]
|
|
179
|
+
const guidBytes =
|
|
180
|
+
shaka.util.Uint8ArrayUtils.fromBase64(kid.textContent);
|
|
181
|
+
// Reverse byte order from little-endian to big-endian
|
|
182
|
+
const kidBytes = new Uint8Array([
|
|
183
|
+
guidBytes[3], guidBytes[2], guidBytes[1], guidBytes[0],
|
|
184
|
+
guidBytes[5], guidBytes[4],
|
|
185
|
+
guidBytes[7], guidBytes[6],
|
|
186
|
+
...guidBytes.slice(8),
|
|
187
|
+
]);
|
|
188
|
+
return shaka.util.Uint8ArrayUtils.toHex(kidBytes);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Not found
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Gets a PlayReady KID from a protection element
|
|
198
|
+
* containing a PlayReady Header Object
|
|
199
|
+
*
|
|
200
|
+
* @param {!Element} element
|
|
201
|
+
* @return {?string}
|
|
202
|
+
* @private
|
|
203
|
+
*/
|
|
204
|
+
static getPlayReadyKID_(element) {
|
|
205
|
+
const ContentProtection = shaka.mss.ContentProtection;
|
|
206
|
+
const rootElement = ContentProtection.getPlayReadyHeaderObject_(element);
|
|
207
|
+
if (!rootElement) {
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return ContentProtection.getKID_(rootElement);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Gets a PlayReady Header Object from a protection element
|
|
216
|
+
*
|
|
217
|
+
* @param {!Element} element
|
|
218
|
+
* @return {?Element}
|
|
219
|
+
* @private
|
|
220
|
+
*/
|
|
221
|
+
static getPlayReadyHeaderObject_(element) {
|
|
222
|
+
const ContentProtection = shaka.mss.ContentProtection;
|
|
223
|
+
const PLAYREADY_RECORD_TYPES = ContentProtection.PLAYREADY_RECORD_TYPES;
|
|
224
|
+
|
|
225
|
+
const bytes = shaka.util.Uint8ArrayUtils.fromBase64(element.textContent);
|
|
226
|
+
const records = ContentProtection.parseMsPro_(bytes);
|
|
227
|
+
const record = records.filter((record) => {
|
|
228
|
+
return record.type === PLAYREADY_RECORD_TYPES.RIGHTS_MANAGEMENT;
|
|
229
|
+
})[0];
|
|
230
|
+
|
|
231
|
+
if (!record) {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const xml = shaka.util.StringUtils.fromUTF16(record.value, true);
|
|
236
|
+
const rootElement = shaka.util.XmlUtils.parseXmlString(xml, 'WRMHEADER');
|
|
237
|
+
if (!rootElement) {
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
return rootElement;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Gets a initData from a protection element.
|
|
245
|
+
*
|
|
246
|
+
* @param {!Element} element
|
|
247
|
+
* @param {string} systemID
|
|
248
|
+
* @param {?string} keyId
|
|
249
|
+
* @return {?Array.<shaka.extern.InitDataOverride>}
|
|
250
|
+
* @private
|
|
251
|
+
*/
|
|
252
|
+
static getInitDataFromPro_(element, systemID, keyId) {
|
|
253
|
+
const Uint8ArrayUtils = shaka.util.Uint8ArrayUtils;
|
|
254
|
+
const data = Uint8ArrayUtils.fromBase64(element.textContent);
|
|
255
|
+
const systemId = Uint8ArrayUtils.fromHex(systemID.replace(/-/g, ''));
|
|
256
|
+
const keyIds = new Set();
|
|
257
|
+
const psshVersion = 0;
|
|
258
|
+
const pssh =
|
|
259
|
+
shaka.util.Pssh.createPssh(data, systemId, keyIds, psshVersion);
|
|
260
|
+
return [
|
|
261
|
+
{
|
|
262
|
+
initData: pssh,
|
|
263
|
+
initDataType: 'cenc',
|
|
264
|
+
keyId: keyId,
|
|
265
|
+
},
|
|
266
|
+
];
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Creates DrmInfo objects from an array of elements.
|
|
271
|
+
*
|
|
272
|
+
* @param {!Array.<!Element>} elements
|
|
273
|
+
* @param {!Object.<string, string>} keySystemsBySystemId
|
|
274
|
+
* @return {!Array.<shaka.extern.DrmInfo>}
|
|
275
|
+
* @private
|
|
276
|
+
*/
|
|
277
|
+
static convertElements_(elements, keySystemsBySystemId) {
|
|
278
|
+
const ContentProtection = shaka.mss.ContentProtection;
|
|
279
|
+
const ManifestParserUtils = shaka.util.ManifestParserUtils;
|
|
280
|
+
const licenseUrlParsers = ContentProtection.licenseUrlParsers_;
|
|
281
|
+
|
|
282
|
+
/** @type {!Array.<shaka.extern.DrmInfo>} */
|
|
283
|
+
const out = [];
|
|
284
|
+
|
|
285
|
+
for (let i = 0; i < elements.length; i++) {
|
|
286
|
+
const element = elements[i];
|
|
287
|
+
const systemID = element.getAttribute('SystemID').toLowerCase();
|
|
288
|
+
const keySystem = keySystemsBySystemId[systemID];
|
|
289
|
+
if (keySystem) {
|
|
290
|
+
const KID = ContentProtection.getPlayReadyKID_(element);
|
|
291
|
+
const initData = ContentProtection.getInitDataFromPro_(
|
|
292
|
+
element, systemID, KID);
|
|
293
|
+
|
|
294
|
+
const info = ManifestParserUtils.createDrmInfo(keySystem, initData);
|
|
295
|
+
if (KID) {
|
|
296
|
+
info.keyIds.add(KID);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const licenseParser = licenseUrlParsers.get(keySystem);
|
|
300
|
+
if (licenseParser) {
|
|
301
|
+
info.licenseServerUri = licenseParser(element);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
out.push(info);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return out;
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* @typedef {{
|
|
314
|
+
* type: number,
|
|
315
|
+
* value: !Uint8Array
|
|
316
|
+
* }}
|
|
317
|
+
*
|
|
318
|
+
* @description
|
|
319
|
+
* The parsed result of a PlayReady object record.
|
|
320
|
+
*
|
|
321
|
+
* @property {number} type
|
|
322
|
+
* Type of data stored in the record.
|
|
323
|
+
* @property {!Uint8Array} value
|
|
324
|
+
* Record content.
|
|
325
|
+
*/
|
|
326
|
+
shaka.mss.ContentProtection.PlayReadyRecord;
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Enum for PlayReady record types.
|
|
330
|
+
* @enum {number}
|
|
331
|
+
*/
|
|
332
|
+
shaka.mss.ContentProtection.PLAYREADY_RECORD_TYPES = {
|
|
333
|
+
RIGHTS_MANAGEMENT: 0x001,
|
|
334
|
+
RESERVED: 0x002,
|
|
335
|
+
EMBEDDED_LICENSE: 0x003,
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* A map of key system name to license server url parser.
|
|
340
|
+
*
|
|
341
|
+
* @const {!Map.<string, function(!Element)>}
|
|
342
|
+
* @private
|
|
343
|
+
*/
|
|
344
|
+
shaka.mss.ContentProtection.licenseUrlParsers_ = new Map()
|
|
345
|
+
.set('com.microsoft.playready',
|
|
346
|
+
shaka.mss.ContentProtection.getPlayReadyLicenseUrl)
|
|
347
|
+
.set('com.microsoft.playready.recommendation',
|
|
348
|
+
shaka.mss.ContentProtection.getPlayReadyLicenseUrl)
|
|
349
|
+
.set('com.microsoft.playready.software',
|
|
350
|
+
shaka.mss.ContentProtection.getPlayReadyLicenseUrl)
|
|
351
|
+
.set('com.microsoft.playready.hardware',
|
|
352
|
+
shaka.mss.ContentProtection.getPlayReadyLicenseUrl);
|
|
353
|
+
|