shaka-player 4.2.4 → 4.3.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/sync-labels.yaml +1 -1
- package/.github/workflows/update-issues.yaml +1 -1
- package/AUTHORS +4 -0
- package/CHANGELOG.md +85 -54
- package/CONTRIBUTORS +4 -0
- package/README.md +14 -0
- package/demo/common/assets.js +58 -0
- package/demo/common/message_ids.js +22 -1
- package/demo/config.js +89 -5
- package/demo/demo.less +7 -1
- package/demo/index.html +8 -1
- package/demo/locales/en.json +21 -1
- package/demo/locales/source.json +82 -2
- package/demo/main.js +57 -1
- package/demo/search.js +2 -0
- package/demo/visualizer.js +337 -0
- package/demo/visualizer_button.js +103 -0
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +83 -58
- package/dist/demo.compiled.debug.map +4 -4
- package/dist/demo.compiled.js +83 -58
- package/dist/demo.compiled.map +4 -4
- package/dist/demo.css +1 -1
- package/dist/demo.css.map +1 -1
- package/dist/deps.js +16 -9
- package/dist/locales.js +32 -32
- package/dist/receiver.compiled.debug.js +23 -19
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +23 -19
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.d.ts +173 -26
- package/dist/shaka-player.compiled.debug.d.ts +173 -26
- package/dist/shaka-player.compiled.debug.externs.js +161 -31
- package/dist/shaka-player.compiled.debug.js +464 -401
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +161 -31
- package/dist/shaka-player.compiled.js +897 -862
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +173 -26
- package/dist/shaka-player.ui.debug.d.ts +173 -26
- package/dist/shaka-player.ui.debug.externs.js +161 -31
- package/dist/shaka-player.ui.debug.js +488 -422
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +161 -31
- package/dist/shaka-player.ui.js +1053 -1018
- package/dist/shaka-player.ui.map +4 -4
- package/docs/design/lcevc-architecture.png +0 -0
- package/docs/design/lcevc-demo.png +0 -0
- package/docs/design/lcevc-integration.md +72 -0
- package/docs/tutorials/fairplay.md +7 -0
- package/docs/tutorials/faq.md +1 -1
- package/docs/tutorials/ui.md +7 -7
- package/docs/tutorials/upgrade.md +6 -0
- package/externs/ima.js +13 -1
- package/externs/lcevc.js +81 -0
- package/externs/mux.js +1 -42
- package/externs/shaka/ads.js +11 -1
- package/externs/shaka/manifest_parser.js +5 -1
- package/externs/shaka/player.js +178 -15
- package/lib/abr/simple_abr_manager.js +7 -0
- package/lib/ads/ad_manager.js +0 -8
- package/lib/ads/client_side_ad.js +15 -0
- package/lib/ads/client_side_ad_manager.js +21 -8
- package/lib/ads/server_side_ad.js +15 -0
- package/lib/ads/server_side_ad_manager.js +3 -3
- package/lib/cast/cast_utils.js +2 -0
- package/lib/cea/dummy_cea_parser.js +28 -0
- package/lib/cea/i_cea_parser.js +14 -2
- package/lib/cea/mp4_cea_parser.js +87 -5
- package/lib/config/auto_show_text.js +33 -0
- package/lib/dash/dash_parser.js +1 -1
- package/lib/hls/hls_parser.js +790 -374
- package/lib/lcevc/lcevc_dil.js +152 -0
- package/lib/media/closed_caption_parser.js +9 -6
- package/lib/media/drm_engine.js +14 -6
- package/lib/media/media_source_engine.js +106 -26
- package/lib/media/presentation_timeline.js +26 -11
- package/lib/media/segment_reference.js +49 -1
- package/lib/media/streaming_engine.js +142 -12
- package/lib/media/transmuxer.js +73 -18
- package/lib/offline/storage.js +1 -0
- package/lib/player.js +454 -75
- package/lib/polyfill/patchedmediakeys_apple.js +55 -1
- package/lib/text/ui_text_displayer.js +5 -5
- package/lib/text/vtt_text_parser.js +35 -1
- package/lib/util/dom_utils.js +0 -1
- package/lib/util/error.js +17 -0
- package/lib/util/fake_event.js +2 -0
- package/lib/util/id3_utils.js +300 -0
- package/lib/util/mime_utils.js +3 -6
- package/lib/util/mp4_box_parsers.js +15 -5
- package/lib/util/platform.js +9 -1
- package/lib/util/player_configuration.js +23 -1
- package/lib/util/ts_parser.js +499 -0
- package/maintained-branches.md +2 -2
- package/package.json +4 -1
- package/roadmap.md +5 -3
- package/test/ads/ad_manager_unit.js +180 -29
- package/test/cast/cast_utils_unit.js +3 -1
- package/test/dash/dash_parser_content_protection_unit.js +1 -0
- package/test/dash/dash_parser_live_unit.js +1 -0
- package/test/dash/dash_parser_manifest_unit.js +93 -1
- package/test/dash/dash_parser_segment_base_unit.js +1 -0
- package/test/dash/dash_parser_segment_list_unit.js +1 -0
- package/test/dash/dash_parser_segment_template_unit.js +1 -0
- package/test/demo/demo_unit.js +2 -1
- package/test/hls/hls_live_unit.js +253 -19
- package/test/hls/hls_parser_unit.js +500 -12
- package/test/media/closed_caption_parser_unit.js +2 -1
- package/test/media/drm_engine_integration.js +3 -1
- package/test/media/media_source_engine_integration.js +71 -6
- package/test/media/media_source_engine_unit.js +10 -5
- package/test/media/streaming_engine_integration.js +4 -1
- package/test/media/streaming_engine_unit.js +144 -1
- package/test/media/transmuxer_integration.js +21 -10
- package/test/player_integration.js +224 -82
- package/test/player_unit.js +5 -2
- package/test/polyfill/patchedmediakeys_apple_unit.js +124 -0
- package/test/test/assets/id3-metadata.aac +0 -0
- package/test/test/assets/id3-metadata.ts +0 -0
- package/test/test/assets/thumbnails-sprites.vtt +10 -0
- package/test/test/assets/thumbnails.vtt +10 -0
- package/test/test/util/dash_parser_util.js +2 -0
- package/test/test/util/fake_ad.js +21 -0
- package/test/test/util/fake_media_source_engine.js +7 -0
- package/test/test/util/id3_generator.js +100 -0
- package/test/test/util/manifest_generator.js +3 -6
- package/test/test/util/simple_fakes.js +4 -0
- package/test/test/util/stream_generator.js +38 -0
- package/test/test/util/test_scheme.js +43 -14
- package/test/text/vtt_text_parser_unit.js +11 -0
- package/test/ui/text_displayer_layout_unit.js +14 -0
- package/test/util/id3_utils_unit.js +116 -0
- package/test/util/ts_parser_unit.js +77 -0
- package/ui/less/containers.less +7 -0
- package/ui/ui.js +43 -4
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/*! @license
|
|
2
|
+
* Shaka Player
|
|
3
|
+
* Copyright 2016 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
goog.provide('shaka.lcevc.Dil');
|
|
8
|
+
goog.require('shaka.log');
|
|
9
|
+
goog.require('shaka.util.IReleasable');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @summary
|
|
13
|
+
* lcevcDil - (MPEG-5 Part 2 LCEVC - Decoder Integration Layer) provides
|
|
14
|
+
* all the operations related to the enhancement and rendering
|
|
15
|
+
* of LCEVC enabled streams and on to a canvas.
|
|
16
|
+
* @implements {shaka.util.IReleasable}
|
|
17
|
+
* @export
|
|
18
|
+
*/
|
|
19
|
+
shaka.lcevc.Dil = class {
|
|
20
|
+
/**
|
|
21
|
+
* @param {HTMLVideoElement} media The video element that will be attached to
|
|
22
|
+
* LCEVC Dil for input.
|
|
23
|
+
* @param {HTMLCanvasElement} canvas The canvas element that will be attached
|
|
24
|
+
* to LCEVC Dil to render the enhanced frames.
|
|
25
|
+
* @param {shaka.extern.LcevcConfiguration} dilConfig The LCEVC DIL
|
|
26
|
+
* config object to initialize the LCEVC DIL.
|
|
27
|
+
*/
|
|
28
|
+
constructor(media, canvas, dilConfig) {
|
|
29
|
+
/** @private {?LcevcDil.LcevcDIL} */
|
|
30
|
+
this.dil_ = null;
|
|
31
|
+
|
|
32
|
+
/** @private {number} */
|
|
33
|
+
this.variantId_ = -1;
|
|
34
|
+
|
|
35
|
+
/** @private {HTMLVideoElement} */
|
|
36
|
+
this.media_ = media;
|
|
37
|
+
|
|
38
|
+
/** @private {HTMLCanvasElement} */
|
|
39
|
+
this.canvas_ = canvas;
|
|
40
|
+
|
|
41
|
+
/** @private {shaka.extern.LcevcConfiguration} */
|
|
42
|
+
this.dilConfig_ = dilConfig;
|
|
43
|
+
|
|
44
|
+
this.create_();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Append data to the LCEVC Dil.
|
|
49
|
+
* @param {BufferSource} data
|
|
50
|
+
*/
|
|
51
|
+
appendBuffer(data) {
|
|
52
|
+
if (this.dil_) {
|
|
53
|
+
this.dil_.appendBuffer(data, 'video', this.variantId_);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Hide the canvas specifically in the case of a DRM Content
|
|
59
|
+
*/
|
|
60
|
+
hideCanvas() {
|
|
61
|
+
if (this.dil_) {
|
|
62
|
+
this.canvas_.classList.add('shaka-hidden');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Create LCEVC Dil.
|
|
68
|
+
* @private
|
|
69
|
+
*/
|
|
70
|
+
create_() {
|
|
71
|
+
if (this.isSupported_() && !this.dil_) {
|
|
72
|
+
if (LcevcDil.SupportObject.webGLSupport(this.canvas_)) {
|
|
73
|
+
// Make sure the canvas is not hidden from a previous playback session.
|
|
74
|
+
this.canvas_.classList.remove('shaka-hidden');
|
|
75
|
+
this.dil_ = new LcevcDil.LcevcDil(
|
|
76
|
+
this.media_,
|
|
77
|
+
this.canvas_,
|
|
78
|
+
this.dilConfig_);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Close LCEVC Dil.
|
|
85
|
+
* @override
|
|
86
|
+
* @export
|
|
87
|
+
*/
|
|
88
|
+
release() {
|
|
89
|
+
if (this.dil_) {
|
|
90
|
+
this.dil_.close();
|
|
91
|
+
this.dil_ = null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Check if the LCEVC Dil lib is present and is supported by the browser.
|
|
97
|
+
* @return {boolean}
|
|
98
|
+
* @private
|
|
99
|
+
*/
|
|
100
|
+
isSupported_() {
|
|
101
|
+
if (typeof libDPIModule === 'undefined') {
|
|
102
|
+
shaka.log.alwaysWarn(
|
|
103
|
+
'Could not Find LCEVC Library dependencies on this page');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (typeof LcevcDil === 'undefined') {
|
|
107
|
+
shaka.log.alwaysWarn('Could not Find LCEVC Library on this page');
|
|
108
|
+
} else {
|
|
109
|
+
if (!LcevcDil.SupportObject.SupportStatus) {
|
|
110
|
+
shaka.log.alwaysWarn(LcevcDil.SupportObject.SupportError);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return typeof LcevcDil !== 'undefined' &&
|
|
115
|
+
typeof libDPIModule !== 'undefined' &&
|
|
116
|
+
this.canvas_ instanceof HTMLCanvasElement &&
|
|
117
|
+
LcevcDil.SupportObject.SupportStatus;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Update current active variant
|
|
122
|
+
* @param {shaka.extern.Track} track
|
|
123
|
+
*/
|
|
124
|
+
updateVariant(track) {
|
|
125
|
+
let containerFormat = shaka.lcevc.Dil.ContainerFormat.MPEG2_TS;
|
|
126
|
+
switch (track.mimeType) {
|
|
127
|
+
case 'video/webm': {
|
|
128
|
+
containerFormat = shaka.lcevc.Dil.ContainerFormat.WEBM;
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
case 'video/mp4': {
|
|
132
|
+
containerFormat = shaka.lcevc.Dil.ContainerFormat.MP4;
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (this.dil_) {
|
|
137
|
+
this.variantId_ = track.id;
|
|
138
|
+
this.dil_.setLevelSwitching(track.id, true);
|
|
139
|
+
this.dil_.setContainerFormat(containerFormat);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Container Formats.
|
|
146
|
+
* @const @enum {number}
|
|
147
|
+
*/
|
|
148
|
+
shaka.lcevc.Dil.ContainerFormat = {
|
|
149
|
+
MPEG2_TS: 0,
|
|
150
|
+
WEBM: 1,
|
|
151
|
+
MP4: 2,
|
|
152
|
+
};
|
|
@@ -8,6 +8,7 @@ goog.provide('shaka.media.ClosedCaptionParser');
|
|
|
8
8
|
goog.provide('shaka.media.IClosedCaptionParser');
|
|
9
9
|
|
|
10
10
|
goog.require('shaka.cea.CeaDecoder');
|
|
11
|
+
goog.require('shaka.cea.DummyCeaParser');
|
|
11
12
|
goog.require('shaka.cea.Mp4CeaParser');
|
|
12
13
|
goog.require('shaka.util.BufferUtils');
|
|
13
14
|
goog.requireType('shaka.cea.ICaptionDecoder');
|
|
@@ -54,12 +55,14 @@ shaka.media.IClosedCaptionParser = class {
|
|
|
54
55
|
*/
|
|
55
56
|
shaka.media.ClosedCaptionParser = class {
|
|
56
57
|
/** */
|
|
57
|
-
constructor() {
|
|
58
|
-
/**
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
constructor(mimeType) {
|
|
59
|
+
/** @private {!shaka.cea.ICeaParser} */
|
|
60
|
+
this.ceaParser_ = new shaka.cea.DummyCeaParser();
|
|
61
|
+
|
|
62
|
+
if (mimeType.includes('video/mp4')) {
|
|
63
|
+
// MP4 Parser to extract closed caption packets from H.264 video.
|
|
64
|
+
this.ceaParser_ = new shaka.cea.Mp4CeaParser();
|
|
65
|
+
}
|
|
63
66
|
|
|
64
67
|
/**
|
|
65
68
|
* Decoder for decoding CEA-X08 data from closed caption packets.
|
package/lib/media/drm_engine.js
CHANGED
|
@@ -845,7 +845,7 @@ shaka.media.DrmEngine = class {
|
|
|
845
845
|
if (shaka.media.Transmuxer.isSupported(realMimeType)) {
|
|
846
846
|
// This will be handled by the Transmuxer, so use the MIME type that the
|
|
847
847
|
// Transmuxer will produce.
|
|
848
|
-
return shaka.media.Transmuxer.
|
|
848
|
+
return shaka.media.Transmuxer.convertCodecs(stream.type, realMimeType);
|
|
849
849
|
}
|
|
850
850
|
return realMimeType;
|
|
851
851
|
}
|
|
@@ -1113,13 +1113,21 @@ shaka.media.DrmEngine = class {
|
|
|
1113
1113
|
const keys = [];
|
|
1114
1114
|
const keyIds = [];
|
|
1115
1115
|
|
|
1116
|
-
clearKeys.forEach((
|
|
1117
|
-
|
|
1118
|
-
|
|
1116
|
+
clearKeys.forEach((key, keyId) => {
|
|
1117
|
+
let kid = keyId;
|
|
1118
|
+
if (kid.length != 22) {
|
|
1119
|
+
kid = Uint8ArrayUtils.toBase64(
|
|
1120
|
+
Uint8ArrayUtils.fromHex(keyId), false);
|
|
1121
|
+
}
|
|
1122
|
+
let k = key;
|
|
1123
|
+
if (k.length != 22) {
|
|
1124
|
+
k = Uint8ArrayUtils.toBase64(
|
|
1125
|
+
Uint8ArrayUtils.fromHex(key), false);
|
|
1126
|
+
}
|
|
1119
1127
|
const keyObj = {
|
|
1120
1128
|
kty: 'oct',
|
|
1121
|
-
kid:
|
|
1122
|
-
k:
|
|
1129
|
+
kid: kid,
|
|
1130
|
+
k: k,
|
|
1123
1131
|
};
|
|
1124
1132
|
|
|
1125
1133
|
keys.push(keyObj);
|
|
@@ -9,20 +9,25 @@ goog.provide('shaka.media.MediaSourceEngine');
|
|
|
9
9
|
goog.require('goog.asserts');
|
|
10
10
|
goog.require('shaka.log');
|
|
11
11
|
goog.require('shaka.media.ContentWorkarounds');
|
|
12
|
+
goog.require('shaka.media.ClosedCaptionParser');
|
|
12
13
|
goog.require('shaka.media.IClosedCaptionParser');
|
|
13
14
|
goog.require('shaka.media.SegmentReference');
|
|
14
15
|
goog.require('shaka.media.TimeRangesUtils');
|
|
15
16
|
goog.require('shaka.media.Transmuxer');
|
|
16
17
|
goog.require('shaka.text.TextEngine');
|
|
18
|
+
goog.require('shaka.util.BufferUtils');
|
|
17
19
|
goog.require('shaka.util.Destroyer');
|
|
18
20
|
goog.require('shaka.util.Error');
|
|
19
21
|
goog.require('shaka.util.EventManager');
|
|
20
22
|
goog.require('shaka.util.Functional');
|
|
21
23
|
goog.require('shaka.util.IDestroyable');
|
|
24
|
+
goog.require('shaka.util.Id3Utils');
|
|
22
25
|
goog.require('shaka.util.ManifestParserUtils');
|
|
23
26
|
goog.require('shaka.util.MimeUtils');
|
|
24
27
|
goog.require('shaka.util.Platform');
|
|
25
28
|
goog.require('shaka.util.PublicPromise');
|
|
29
|
+
goog.require('shaka.util.TsParser');
|
|
30
|
+
goog.require('shaka.lcevc.Dil');
|
|
26
31
|
|
|
27
32
|
|
|
28
33
|
/**
|
|
@@ -38,21 +43,22 @@ shaka.media.MediaSourceEngine = class {
|
|
|
38
43
|
/**
|
|
39
44
|
* @param {HTMLMediaElement} video The video element, whose source is tied to
|
|
40
45
|
* MediaSource during the lifetime of the MediaSourceEngine.
|
|
41
|
-
* @param {!shaka.media.IClosedCaptionParser} closedCaptionParser
|
|
42
|
-
* The closed caption parser that should be used to parser closed captions
|
|
43
|
-
* from the video stream. MediaSourceEngine takes ownership of the parser.
|
|
44
|
-
* When MediaSourceEngine is destroyed, it will destroy the parser.
|
|
45
46
|
* @param {!shaka.extern.TextDisplayer} textDisplayer
|
|
46
47
|
* The text displayer that will be used with the text engine.
|
|
47
48
|
* MediaSourceEngine takes ownership of the displayer. When
|
|
48
49
|
* MediaSourceEngine is destroyed, it will destroy the displayer.
|
|
49
50
|
* @param {!function(!Array.<shaka.extern.ID3Metadata>, number, ?number)=}
|
|
50
51
|
* onMetadata
|
|
52
|
+
* @param {?shaka.lcevc.Dil} [lcevcDil] Optional - LCEVC Dil Object
|
|
53
|
+
*
|
|
51
54
|
*/
|
|
52
|
-
constructor(video,
|
|
55
|
+
constructor(video, textDisplayer, onMetadata, lcevcDil) {
|
|
53
56
|
/** @private {HTMLMediaElement} */
|
|
54
57
|
this.video_ = video;
|
|
55
58
|
|
|
59
|
+
/** @private {?shaka.extern.MediaSourceConfiguration} */
|
|
60
|
+
this.config_ = null;
|
|
61
|
+
|
|
56
62
|
/** @private {shaka.extern.TextDisplayer} */
|
|
57
63
|
this.textDisplayer_ = textDisplayer;
|
|
58
64
|
|
|
@@ -81,6 +87,9 @@ shaka.media.MediaSourceEngine = class {
|
|
|
81
87
|
number, ?number)} */
|
|
82
88
|
this.onMetadata_ = onMetadata || onMetadataNoOp;
|
|
83
89
|
|
|
90
|
+
/** @private {?shaka.lcevc.Dil} */
|
|
91
|
+
this.lcevcDil_ = lcevcDil || null;
|
|
92
|
+
|
|
84
93
|
/**
|
|
85
94
|
* @private {!Object.<string,
|
|
86
95
|
* !Array.<shaka.media.MediaSourceEngine.Operation>>}
|
|
@@ -93,8 +102,8 @@ shaka.media.MediaSourceEngine = class {
|
|
|
93
102
|
/** @private {!Object.<string, !shaka.media.Transmuxer>} */
|
|
94
103
|
this.transmuxers_ = {};
|
|
95
104
|
|
|
96
|
-
/** @private {shaka.media.IClosedCaptionParser} */
|
|
97
|
-
this.captionParser_ =
|
|
105
|
+
/** @private {?shaka.media.IClosedCaptionParser} */
|
|
106
|
+
this.captionParser_ = null;
|
|
98
107
|
|
|
99
108
|
/** @private {!shaka.util.PublicPromise} */
|
|
100
109
|
this.mediaSourceOpen_ = new shaka.util.PublicPromise();
|
|
@@ -291,6 +300,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
291
300
|
this.video_ = null;
|
|
292
301
|
}
|
|
293
302
|
|
|
303
|
+
this.config_ = null;
|
|
294
304
|
this.mediaSource_ = null;
|
|
295
305
|
this.textEngine_ = null;
|
|
296
306
|
this.textDisplayer_ = null;
|
|
@@ -305,6 +315,9 @@ shaka.media.MediaSourceEngine = class {
|
|
|
305
315
|
}
|
|
306
316
|
}
|
|
307
317
|
this.queues_ = {};
|
|
318
|
+
|
|
319
|
+
// This object is owned by Player
|
|
320
|
+
this.lcevcDil_ = null;
|
|
308
321
|
}
|
|
309
322
|
|
|
310
323
|
/**
|
|
@@ -325,15 +338,16 @@ shaka.media.MediaSourceEngine = class {
|
|
|
325
338
|
* shaka.extern.Stream>} streamsByType
|
|
326
339
|
* A map of content types to streams. All streams must be supported
|
|
327
340
|
* according to MediaSourceEngine.isStreamSupported.
|
|
328
|
-
* @param {boolean}
|
|
329
|
-
* If true, this will transmux TS content even if it is natively
|
|
341
|
+
* @param {boolean} forceTransmux
|
|
342
|
+
* If true, this will transmux AAC and TS content even if it is natively
|
|
343
|
+
* supported.
|
|
330
344
|
* @param {boolean=} sequenceMode
|
|
331
345
|
* If true, the media segments are appended to the SourceBuffer in strict
|
|
332
346
|
* sequence.
|
|
333
347
|
*
|
|
334
348
|
* @return {!Promise}
|
|
335
349
|
*/
|
|
336
|
-
async init(streamsByType,
|
|
350
|
+
async init(streamsByType, forceTransmux, sequenceMode=false) {
|
|
337
351
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
338
352
|
|
|
339
353
|
await this.mediaSourceOpen_;
|
|
@@ -351,14 +365,15 @@ shaka.media.MediaSourceEngine = class {
|
|
|
351
365
|
if (contentType == ContentType.TEXT) {
|
|
352
366
|
this.reinitText(mimeType, sequenceMode);
|
|
353
367
|
} else {
|
|
354
|
-
if ((
|
|
368
|
+
if ((forceTransmux || !MediaSource.isTypeSupported(mimeType)) &&
|
|
355
369
|
shaka.media.Transmuxer.isSupported(mimeType, contentType)) {
|
|
356
|
-
this.transmuxers_[contentType] =
|
|
370
|
+
this.transmuxers_[contentType] =
|
|
371
|
+
new shaka.media.Transmuxer(mimeType);
|
|
357
372
|
mimeType =
|
|
358
|
-
shaka.media.Transmuxer.
|
|
373
|
+
shaka.media.Transmuxer.convertCodecs(contentType, mimeType);
|
|
359
374
|
}
|
|
360
|
-
|
|
361
|
-
const sourceBuffer = this.mediaSource_.addSourceBuffer(
|
|
375
|
+
const type = mimeType + this.config_.sourceBufferExtraFeatures;
|
|
376
|
+
const sourceBuffer = this.mediaSource_.addSourceBuffer(type);
|
|
362
377
|
|
|
363
378
|
this.eventManager_.listen(
|
|
364
379
|
sourceBuffer, 'error',
|
|
@@ -374,6 +389,16 @@ shaka.media.MediaSourceEngine = class {
|
|
|
374
389
|
}
|
|
375
390
|
}
|
|
376
391
|
|
|
392
|
+
/**
|
|
393
|
+
* Called by the Player to provide an updated configuration any time it
|
|
394
|
+
* changes. Must be called at least once before init().
|
|
395
|
+
*
|
|
396
|
+
* @param {shaka.extern.MediaSourceConfiguration} config
|
|
397
|
+
*/
|
|
398
|
+
configure(config) {
|
|
399
|
+
this.config_ = config;
|
|
400
|
+
}
|
|
401
|
+
|
|
377
402
|
/**
|
|
378
403
|
* Reinitialize the TextEngine for a new text type.
|
|
379
404
|
* @param {string} mimeType
|
|
@@ -509,6 +534,17 @@ shaka.media.MediaSourceEngine = class {
|
|
|
509
534
|
}
|
|
510
535
|
}
|
|
511
536
|
|
|
537
|
+
/**
|
|
538
|
+
* Create a new closed caption parser. This will ONLY be replaced by tests as
|
|
539
|
+
* a way to inject fake closed caption parser instances.
|
|
540
|
+
*
|
|
541
|
+
* @param {string} mimeType
|
|
542
|
+
* @return {!shaka.media.IClosedCaptionParser}
|
|
543
|
+
*/
|
|
544
|
+
getCaptionParser(mimeType) {
|
|
545
|
+
return new shaka.media.ClosedCaptionParser(mimeType);
|
|
546
|
+
}
|
|
547
|
+
|
|
512
548
|
/**
|
|
513
549
|
* Enqueue an operation to append data to the SourceBuffer.
|
|
514
550
|
* Start and end times are needed for TextEngine, but not for MediaSource.
|
|
@@ -544,6 +580,37 @@ shaka.media.MediaSourceEngine = class {
|
|
|
544
580
|
return;
|
|
545
581
|
}
|
|
546
582
|
|
|
583
|
+
const uint8ArrayData = shaka.util.BufferUtils.toUint8(data);
|
|
584
|
+
let mimeType = this.sourceBufferTypes_[contentType];
|
|
585
|
+
if (this.transmuxers_[contentType]) {
|
|
586
|
+
mimeType = this.transmuxers_[contentType].getOrginalMimeType();
|
|
587
|
+
}
|
|
588
|
+
if (shaka.util.TsParser.probe(uint8ArrayData)) {
|
|
589
|
+
const metadata = new shaka.util.TsParser().parse(uint8ArrayData)
|
|
590
|
+
.getMetadata();
|
|
591
|
+
if (metadata.length) {
|
|
592
|
+
const timestampOffset =
|
|
593
|
+
this.sourceBuffers_[contentType].timestampOffset;
|
|
594
|
+
this.onMetadata_(metadata, timestampOffset,
|
|
595
|
+
reference ? reference.endTime : null);
|
|
596
|
+
}
|
|
597
|
+
} else {
|
|
598
|
+
if (shaka.media.MediaSourceEngine.RAW_FORMATS.includes(mimeType)) {
|
|
599
|
+
const frames = shaka.util.Id3Utils.getID3Frames(uint8ArrayData);
|
|
600
|
+
if (frames.length && reference) {
|
|
601
|
+
/** @private {shaka.extern.ID3Metadata} */
|
|
602
|
+
const metadata = {
|
|
603
|
+
cueTime: reference.startTime,
|
|
604
|
+
data: uint8ArrayData,
|
|
605
|
+
frames: frames,
|
|
606
|
+
dts: reference.startTime,
|
|
607
|
+
pts: reference.startTime,
|
|
608
|
+
};
|
|
609
|
+
this.onMetadata_([metadata], /* offset= */ 0, reference.endTime);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
547
614
|
if (this.transmuxers_[contentType]) {
|
|
548
615
|
// When seeked we should reset the transmuxer captionstreams
|
|
549
616
|
// so it does not ignores the captions from previous segments
|
|
@@ -558,15 +625,6 @@ shaka.media.MediaSourceEngine = class {
|
|
|
558
625
|
if (!this.textEngine_) {
|
|
559
626
|
this.reinitText('text/vtt', this.sequenceMode_);
|
|
560
627
|
}
|
|
561
|
-
|
|
562
|
-
if (transmuxedData.metadata) {
|
|
563
|
-
const timestampOffset =
|
|
564
|
-
this.sourceBuffers_[contentType].timestampOffset;
|
|
565
|
-
this.onMetadata_(
|
|
566
|
-
transmuxedData.metadata,
|
|
567
|
-
timestampOffset,
|
|
568
|
-
reference ? reference.endTime : null);
|
|
569
|
-
}
|
|
570
628
|
// This doesn't work for native TS support (ex. Edge/Chromecast),
|
|
571
629
|
// since no transmuxing is needed for native TS.
|
|
572
630
|
if (transmuxedData.captions && transmuxedData.captions.length) {
|
|
@@ -582,10 +640,13 @@ shaka.media.MediaSourceEngine = class {
|
|
|
582
640
|
}
|
|
583
641
|
|
|
584
642
|
data = transmuxedData.data;
|
|
585
|
-
} else if (hasClosedCaptions) {
|
|
643
|
+
} else if (hasClosedCaptions && contentType == ContentType.VIDEO) {
|
|
586
644
|
if (!this.textEngine_) {
|
|
587
645
|
this.reinitText('text/vtt', this.sequenceMode_);
|
|
588
646
|
}
|
|
647
|
+
if (!this.captionParser_) {
|
|
648
|
+
this.captionParser_ = this.getCaptionParser(mimeType);
|
|
649
|
+
}
|
|
589
650
|
// If it is the init segment for closed captions, initialize the closed
|
|
590
651
|
// caption parser.
|
|
591
652
|
if (!reference) {
|
|
@@ -779,7 +840,9 @@ shaka.media.MediaSourceEngine = class {
|
|
|
779
840
|
* Fully reset the state of the caption parser owned by MediaSourceEngine.
|
|
780
841
|
*/
|
|
781
842
|
resetCaptionParser() {
|
|
782
|
-
this.captionParser_
|
|
843
|
+
if (this.captionParser_) {
|
|
844
|
+
this.captionParser_.reset();
|
|
845
|
+
}
|
|
783
846
|
}
|
|
784
847
|
|
|
785
848
|
/**
|
|
@@ -918,6 +981,15 @@ shaka.media.MediaSourceEngine = class {
|
|
|
918
981
|
* @private
|
|
919
982
|
*/
|
|
920
983
|
append_(contentType, data) {
|
|
984
|
+
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
985
|
+
|
|
986
|
+
// Append only video data to the LCEVC Dil.
|
|
987
|
+
if (contentType == ContentType.VIDEO && this.lcevcDil_) {
|
|
988
|
+
// Append video buffers to the LCEVC Dil for parsing and storing
|
|
989
|
+
// of LCEVC data.
|
|
990
|
+
this.lcevcDil_.appendBuffer(data);
|
|
991
|
+
}
|
|
992
|
+
|
|
921
993
|
// This will trigger an 'updateend' event.
|
|
922
994
|
this.sourceBuffers_[contentType].appendBuffer(data);
|
|
923
995
|
}
|
|
@@ -1283,6 +1355,14 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1283
1355
|
|
|
1284
1356
|
return segment;
|
|
1285
1357
|
}
|
|
1358
|
+
|
|
1359
|
+
/**
|
|
1360
|
+
* Update LCEVC DIL object when ready for LCEVC Decodes
|
|
1361
|
+
* @param {?shaka.lcevc.Dil} lcevcDil
|
|
1362
|
+
*/
|
|
1363
|
+
updateLcevcDil(lcevcDil) {
|
|
1364
|
+
this.lcevcDil_ = lcevcDil;
|
|
1365
|
+
}
|
|
1286
1366
|
};
|
|
1287
1367
|
|
|
1288
1368
|
|
|
@@ -118,6 +118,20 @@ shaka.media.PresentationTimeline = class {
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
|
|
121
|
+
/**
|
|
122
|
+
* Sets the presentation's start time.
|
|
123
|
+
*
|
|
124
|
+
* @param {number} presentationStartTime The wall-clock time, in seconds,
|
|
125
|
+
* when the presentation started or will start. Only required for live.
|
|
126
|
+
* @export
|
|
127
|
+
*/
|
|
128
|
+
setPresentationStartTime(presentationStartTime) {
|
|
129
|
+
goog.asserts.assert(presentationStartTime >= 0,
|
|
130
|
+
'presentationStartTime must be >= 0');
|
|
131
|
+
this.presentationStartTime_ = presentationStartTime;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
|
|
121
135
|
/**
|
|
122
136
|
* Sets the presentation's duration.
|
|
123
137
|
*
|
|
@@ -207,10 +221,10 @@ shaka.media.PresentationTimeline = class {
|
|
|
207
221
|
|
|
208
222
|
|
|
209
223
|
/**
|
|
210
|
-
* Gives PresentationTimeline
|
|
224
|
+
* Gives PresentationTimeline an array of segments so it can size and position
|
|
211
225
|
* the segment availability window, and account for missing segment
|
|
212
|
-
* information.
|
|
213
|
-
*
|
|
226
|
+
* information. These segments do not necessarily need to all be from the
|
|
227
|
+
* same stream.
|
|
214
228
|
*
|
|
215
229
|
* @param {!Array.<!shaka.media.SegmentReference>} references
|
|
216
230
|
* @export
|
|
@@ -220,15 +234,16 @@ shaka.media.PresentationTimeline = class {
|
|
|
220
234
|
return;
|
|
221
235
|
}
|
|
222
236
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
237
|
+
let firstReferenceStartTime = references[0].startTime;
|
|
238
|
+
let lastReferenceEndTime = references[0].endTime;
|
|
239
|
+
for (const reference of references) {
|
|
240
|
+
firstReferenceStartTime = Math.min(
|
|
241
|
+
firstReferenceStartTime, reference.startTime);
|
|
242
|
+
lastReferenceEndTime = Math.max(lastReferenceEndTime, reference.endTime);
|
|
243
|
+
this.maxSegmentDuration_ = Math.max(
|
|
244
|
+
this.maxSegmentDuration_, reference.endTime - reference.startTime);
|
|
245
|
+
}
|
|
226
246
|
this.notifyMinSegmentStartTime(firstReferenceStartTime);
|
|
227
|
-
|
|
228
|
-
this.maxSegmentDuration_ = references.reduce(
|
|
229
|
-
(max, r) => { return Math.max(max, r.endTime - r.startTime); },
|
|
230
|
-
this.maxSegmentDuration_);
|
|
231
|
-
|
|
232
247
|
this.maxSegmentEndTime_ =
|
|
233
248
|
Math.max(this.maxSegmentEndTime_, lastReferenceEndTime);
|
|
234
249
|
|
|
@@ -28,8 +28,9 @@ shaka.media.InitSegmentReference = class {
|
|
|
28
28
|
* segment extends to the end of the resource.
|
|
29
29
|
* @param {null|shaka.extern.MediaQualityInfo=} mediaQuality Information about
|
|
30
30
|
* the quality of the media associated with this init segment.
|
|
31
|
+
* @param {number=} timescale
|
|
31
32
|
*/
|
|
32
|
-
constructor(uris, startByte, endByte, mediaQuality = null) {
|
|
33
|
+
constructor(uris, startByte, endByte, mediaQuality = null, timescale) {
|
|
33
34
|
/** @type {function():!Array.<string>} */
|
|
34
35
|
this.getUris = uris;
|
|
35
36
|
|
|
@@ -41,6 +42,9 @@ shaka.media.InitSegmentReference = class {
|
|
|
41
42
|
|
|
42
43
|
/** @const {shaka.extern.MediaQualityInfo|null} */
|
|
43
44
|
this.mediaQuality = mediaQuality;
|
|
45
|
+
|
|
46
|
+
/** @type {number|undefined} */
|
|
47
|
+
this.timescale = timescale;
|
|
44
48
|
}
|
|
45
49
|
|
|
46
50
|
/**
|
|
@@ -239,6 +243,9 @@ shaka.media.SegmentReference = class {
|
|
|
239
243
|
|
|
240
244
|
/** @type {?shaka.extern.HlsAes128Key} */
|
|
241
245
|
this.hlsAes128Key = hlsAes128Key;
|
|
246
|
+
|
|
247
|
+
/** @type {?shaka.media.SegmentReference.ThumbnailSprite} */
|
|
248
|
+
this.thumbnailSprite = null;
|
|
242
249
|
}
|
|
243
250
|
|
|
244
251
|
/**
|
|
@@ -353,6 +360,26 @@ shaka.media.SegmentReference = class {
|
|
|
353
360
|
markAsUnavailable() {
|
|
354
361
|
this.status = shaka.media.SegmentReference.Status.UNAVAILABLE;
|
|
355
362
|
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Set the segment's thumbnail sprite.
|
|
366
|
+
*
|
|
367
|
+
* @param {shaka.media.SegmentReference.ThumbnailSprite} thumbnailSprite
|
|
368
|
+
* @export
|
|
369
|
+
*/
|
|
370
|
+
setThumbnailSprite(thumbnailSprite) {
|
|
371
|
+
this.thumbnailSprite = thumbnailSprite;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Returns the segment's thumbnail sprite.
|
|
376
|
+
*
|
|
377
|
+
* @return {?shaka.media.SegmentReference.ThumbnailSprite}
|
|
378
|
+
* @export
|
|
379
|
+
*/
|
|
380
|
+
getThumbnailSprite() {
|
|
381
|
+
return this.thumbnailSprite;
|
|
382
|
+
}
|
|
356
383
|
};
|
|
357
384
|
|
|
358
385
|
|
|
@@ -376,3 +403,24 @@ shaka.media.SegmentReference.Status = {
|
|
|
376
403
|
* @typedef {shaka.media.InitSegmentReference|shaka.media.SegmentReference}
|
|
377
404
|
*/
|
|
378
405
|
shaka.media.AnySegmentReference;
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* @typedef {{
|
|
410
|
+
* height: number,
|
|
411
|
+
* positionX: number,
|
|
412
|
+
* positionY: number,
|
|
413
|
+
* width: number
|
|
414
|
+
* }}
|
|
415
|
+
*
|
|
416
|
+
* @property {number} height
|
|
417
|
+
* The thumbnail height in px.
|
|
418
|
+
* @property {number} positionX
|
|
419
|
+
* The thumbnail left position in px.
|
|
420
|
+
* @property {number} positionY
|
|
421
|
+
* The thumbnail top position in px.
|
|
422
|
+
* @property {number} width
|
|
423
|
+
* The thumbnail width in px.
|
|
424
|
+
* @export
|
|
425
|
+
*/
|
|
426
|
+
shaka.media.SegmentReference.ThumbnailSprite;
|