shaka-player 4.6.3 → 4.6.5
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/CHANGELOG.md +21 -0
- package/demo/common/asset.js +0 -1
- package/demo/common/assets.js +0 -1
- package/dist/demo.compiled.debug.map +1 -1
- package/dist/demo.compiled.map +1 -1
- package/dist/deps.js +5 -5
- package/dist/locales.js +33 -33
- package/dist/receiver.compiled.debug.map +1 -1
- package/dist/receiver.compiled.map +1 -1
- package/dist/shaka-player.compiled.d.ts +1 -1
- package/dist/shaka-player.compiled.debug.d.ts +1 -1
- package/dist/shaka-player.compiled.debug.externs.js +5 -2
- package/dist/shaka-player.compiled.debug.js +172 -171
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.externs.js +5 -2
- package/dist/shaka-player.compiled.js +227 -224
- package/dist/shaka-player.compiled.map +3 -3
- package/dist/shaka-player.ui.d.ts +1 -1
- package/dist/shaka-player.ui.debug.d.ts +1 -1
- package/dist/shaka-player.ui.debug.externs.js +5 -2
- package/dist/shaka-player.ui.debug.js +196 -195
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.externs.js +5 -2
- package/dist/shaka-player.ui.js +223 -220
- package/dist/shaka-player.ui.map +3 -3
- package/docs/tutorials/ui.md +3 -1
- package/lib/ads/client_side_ad_manager.js +4 -0
- package/lib/ads/media_tailor_ad_manager.js +5 -0
- package/lib/ads/server_side_ad_manager.js +4 -0
- package/lib/hls/hls_parser.js +17 -5
- package/lib/media/drm_engine.js +0 -3
- package/lib/media/media_source_engine.js +1 -1
- package/lib/media/streaming_engine.js +3 -2
- package/lib/media/video_wrapper.js +4 -3
- package/lib/net/networking_utils.js +12 -3
- package/lib/player.js +5 -7
- package/lib/text/simple_text_displayer.js +8 -7
- package/lib/text/text_utils.js +39 -13
- package/lib/text/ui_text_displayer.js +20 -11
- package/lib/text/web_vtt_generator.js +1 -1
- package/lib/util/ts_parser.js +12 -8
- package/package.json +1 -1
- package/test/media/drm_engine_unit.js +27 -0
- package/test/player_unit.js +31 -0
- package/test/test/util/layout_tests.js +2 -1
- package/test/text/simple_text_displayer_unit.js +1 -1
- package/test/text/web_vtt_generator_unit.js +3 -3
- package/test/transmuxer/transmuxer_integration.js +3 -3
- package/ui/volume_bar.js +10 -6
package/docs/tutorials/ui.md
CHANGED
|
@@ -204,11 +204,13 @@ constructor.
|
|
|
204
204
|
// "local" because it is for local playback only, as opposed to the player proxy
|
|
205
205
|
// object, which will route your calls to the ChromeCast receiver as necessary.
|
|
206
206
|
const localPlayer = new shaka.Player();
|
|
207
|
-
await localPlayer.attach(videoElement);
|
|
208
207
|
// "Overlay" because the UI will add DOM elements inside the container,
|
|
209
208
|
// to visually overlay the video element
|
|
210
209
|
const ui = new shaka.ui.Overlay(localPlayer, videoContainerElement,
|
|
211
210
|
videoElement);
|
|
211
|
+
// Now that the player has been configured to be part of a UI, attach it to the
|
|
212
|
+
// video.
|
|
213
|
+
await localPlayer.attach(videoElement);
|
|
212
214
|
|
|
213
215
|
// As with DOM-based setup, get access to the UI controls and player from the
|
|
214
216
|
// UI.
|
|
@@ -13,6 +13,10 @@ goog.provide('shaka.ads.ClientSideAdManager');
|
|
|
13
13
|
|
|
14
14
|
goog.require('goog.asserts');
|
|
15
15
|
goog.require('shaka.ads.ClientSideAd');
|
|
16
|
+
goog.require('shaka.log');
|
|
17
|
+
goog.require('shaka.util.Dom');
|
|
18
|
+
goog.require('shaka.util.EventManager');
|
|
19
|
+
goog.require('shaka.util.FakeEvent');
|
|
16
20
|
goog.require('shaka.util.IReleasable');
|
|
17
21
|
|
|
18
22
|
/**
|
|
@@ -15,7 +15,12 @@ goog.require('goog.asserts');
|
|
|
15
15
|
goog.require('shaka.ads.MediaTailorAd');
|
|
16
16
|
goog.require('shaka.log');
|
|
17
17
|
goog.require('shaka.net.NetworkingEngine');
|
|
18
|
+
goog.require('goog.Uri');
|
|
19
|
+
goog.require('shaka.util.EventManager');
|
|
20
|
+
goog.require('shaka.util.Error');
|
|
21
|
+
goog.require('shaka.util.FakeEvent');
|
|
18
22
|
goog.require('shaka.util.IReleasable');
|
|
23
|
+
goog.require('shaka.util.PublicPromise');
|
|
19
24
|
goog.require('shaka.util.StringUtils');
|
|
20
25
|
|
|
21
26
|
|
|
@@ -14,7 +14,11 @@ goog.provide('shaka.ads.ServerSideAdManager');
|
|
|
14
14
|
goog.require('goog.asserts');
|
|
15
15
|
goog.require('shaka.ads.ServerSideAd');
|
|
16
16
|
goog.require('shaka.log');
|
|
17
|
+
goog.require('shaka.util.EventManager');
|
|
18
|
+
goog.require('shaka.util.Error');
|
|
19
|
+
goog.require('shaka.util.FakeEvent');
|
|
17
20
|
goog.require('shaka.util.IReleasable');
|
|
21
|
+
goog.require('shaka.util.PublicPromise');
|
|
18
22
|
|
|
19
23
|
|
|
20
24
|
/**
|
package/lib/hls/hls_parser.js
CHANGED
|
@@ -3753,14 +3753,26 @@ shaka.hls.HlsParser = class {
|
|
|
3753
3753
|
|
|
3754
3754
|
// If unable to guess mime type, request a segment and try getting it
|
|
3755
3755
|
// from the response.
|
|
3756
|
+
let contentMimeType;
|
|
3757
|
+
const type = shaka.net.NetworkingEngine.AdvancedRequestType.MEDIA_SEGMENT;
|
|
3756
3758
|
const headRequest = shaka.net.NetworkingEngine.makeRequest(
|
|
3757
3759
|
middleSegmentUris, this.config_.retryParameters);
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3760
|
+
try {
|
|
3761
|
+
headRequest.method = 'HEAD';
|
|
3762
|
+
const response = await this.makeNetworkRequest_(
|
|
3763
|
+
headRequest, requestType, {type});
|
|
3764
|
+
|
|
3765
|
+
contentMimeType = response.headers['content-type'];
|
|
3766
|
+
} catch (error) {
|
|
3767
|
+
if (error && error.code == shaka.util.Error.Code.HTTP_ERROR) {
|
|
3768
|
+
headRequest.method = 'GET';
|
|
3769
|
+
const response = await this.makeNetworkRequest_(
|
|
3770
|
+
headRequest, requestType, {type});
|
|
3771
|
+
|
|
3772
|
+
contentMimeType = response.headers['content-type'];
|
|
3773
|
+
}
|
|
3774
|
+
}
|
|
3762
3775
|
|
|
3763
|
-
const contentMimeType = response.headers['content-type'];
|
|
3764
3776
|
if (contentMimeType) {
|
|
3765
3777
|
// Split the MIME type in case the server sent additional parameters.
|
|
3766
3778
|
return contentMimeType.split(';')[0];
|
package/lib/media/drm_engine.js
CHANGED
|
@@ -2038,9 +2038,6 @@ shaka.media.DrmEngine = class {
|
|
|
2038
2038
|
|
|
2039
2039
|
for (const drm1 of drms1) {
|
|
2040
2040
|
for (const drm2 of drms2) {
|
|
2041
|
-
// This method is only called to compare drmInfos of a video and an
|
|
2042
|
-
// audio adaptations, so we shouldn't have to worry about checking
|
|
2043
|
-
// robustness.
|
|
2044
2041
|
if (drm1.keySystem == drm2.keySystem) {
|
|
2045
2042
|
const initDataMap = new Map();
|
|
2046
2043
|
const bothInitDatas = (drm1.initData || [])
|
|
@@ -864,7 +864,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
864
864
|
const calculatedTimestampOffset = reference.startTime - timestamp;
|
|
865
865
|
const timestampOffsetDifference =
|
|
866
866
|
Math.abs(timestampOffset - calculatedTimestampOffset);
|
|
867
|
-
if ((timestampOffsetDifference >= 0.
|
|
867
|
+
if ((timestampOffsetDifference >= 0.001 || seeked || adaptation) &&
|
|
868
868
|
(!isChunkedData || calculatedTimestampOffset > 0 ||
|
|
869
869
|
!timestampOffset)) {
|
|
870
870
|
timestampOffset = calculatedTimestampOffset;
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* @fileoverview
|
|
9
|
-
* @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed
|
|
10
9
|
*/
|
|
11
10
|
|
|
12
11
|
goog.provide('shaka.media.StreamingEngine');
|
|
@@ -14,12 +13,14 @@ goog.provide('shaka.media.StreamingEngine');
|
|
|
14
13
|
goog.require('goog.asserts');
|
|
15
14
|
goog.require('shaka.log');
|
|
16
15
|
goog.require('shaka.media.InitSegmentReference');
|
|
16
|
+
goog.require('shaka.media.ManifestParser');
|
|
17
17
|
goog.require('shaka.media.MediaSourceEngine');
|
|
18
18
|
goog.require('shaka.media.SegmentIterator');
|
|
19
19
|
goog.require('shaka.media.SegmentReference');
|
|
20
20
|
goog.require('shaka.media.SegmentPrefetch');
|
|
21
21
|
goog.require('shaka.net.Backoff');
|
|
22
22
|
goog.require('shaka.net.NetworkingEngine');
|
|
23
|
+
goog.require('shaka.util.BufferUtils');
|
|
23
24
|
goog.require('shaka.util.DelayedTick');
|
|
24
25
|
goog.require('shaka.util.Destroyer');
|
|
25
26
|
goog.require('shaka.util.Error');
|
|
@@ -28,6 +29,7 @@ goog.require('shaka.util.IDestroyable');
|
|
|
28
29
|
goog.require('shaka.util.Id3Utils');
|
|
29
30
|
goog.require('shaka.util.ManifestParserUtils');
|
|
30
31
|
goog.require('shaka.util.MimeUtils');
|
|
32
|
+
goog.require('shaka.util.Mp4BoxParsers');
|
|
31
33
|
goog.require('shaka.util.Mp4Parser');
|
|
32
34
|
goog.require('shaka.util.Networking');
|
|
33
35
|
|
|
@@ -2203,7 +2205,6 @@ shaka.media.StreamingEngine = class {
|
|
|
2203
2205
|
*
|
|
2204
2206
|
* @return {!Promise.<BufferSource>}
|
|
2205
2207
|
* @private
|
|
2206
|
-
* @suppress {strictMissingProperties}
|
|
2207
2208
|
*/
|
|
2208
2209
|
async fetch_(mediaState, reference, streamDataCallback) {
|
|
2209
2210
|
if (reference instanceof shaka.media.InitSegmentReference) {
|
|
@@ -183,8 +183,8 @@ shaka.media.VideoWrapper = class {
|
|
|
183
183
|
|
|
184
184
|
/**
|
|
185
185
|
* A class used to move the playhead away from its current time. Sometimes,
|
|
186
|
-
* Edge ignores re-seeks. After changing the current time, check every
|
|
187
|
-
* retrying if the change was not accepted.
|
|
186
|
+
* legacy Edge ignores re-seeks. After changing the current time, check every
|
|
187
|
+
* 100ms, retrying if the change was not accepted.
|
|
188
188
|
*
|
|
189
189
|
* Delay stats over 100 runs of a re-seeking integration test:
|
|
190
190
|
* Edge - 0ms - 2%
|
|
@@ -194,7 +194,8 @@ shaka.media.VideoWrapper = class {
|
|
|
194
194
|
* Edge - 400ms - 2%
|
|
195
195
|
* Chrome - 0ms - 100%
|
|
196
196
|
*
|
|
197
|
-
*
|
|
197
|
+
* Unfortunately, legacy Edge is not receiving updates anymore, but it still
|
|
198
|
+
* must be supported as it is used for web browsers on XBox.
|
|
198
199
|
*
|
|
199
200
|
* @implements {shaka.util.IReleasable}
|
|
200
201
|
* @final
|
|
@@ -8,6 +8,7 @@ goog.provide('shaka.net.NetworkingUtils');
|
|
|
8
8
|
|
|
9
9
|
goog.require('goog.Uri');
|
|
10
10
|
goog.require('shaka.net.NetworkingEngine');
|
|
11
|
+
goog.require('shaka.util.Error');
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -30,13 +31,21 @@ shaka.net.NetworkingUtils = class {
|
|
|
30
31
|
const type = shaka.net.NetworkingEngine.RequestType.MANIFEST;
|
|
31
32
|
|
|
32
33
|
const request = shaka.net.NetworkingEngine.makeRequest([uri], retryParams);
|
|
33
|
-
request.method = 'HEAD';
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
try {
|
|
36
|
+
request.method = 'HEAD';
|
|
37
|
+
const response = await netEngine.request(type, request).promise;
|
|
38
|
+
mimeType = response.headers['content-type'];
|
|
39
|
+
} catch (error) {
|
|
40
|
+
if (error && error.code == shaka.util.Error.Code.HTTP_ERROR) {
|
|
41
|
+
request.method = 'GET';
|
|
42
|
+
const response = await netEngine.request(type, request).promise;
|
|
43
|
+
mimeType = response.headers['content-type'];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
36
46
|
|
|
37
47
|
// https://bit.ly/2K9s9kf says this header should always be available,
|
|
38
48
|
// but just to be safe:
|
|
39
|
-
mimeType = response.headers['content-type'];
|
|
40
49
|
return mimeType ? mimeType.toLowerCase().split(';').shift() : '';
|
|
41
50
|
}
|
|
42
51
|
|
package/lib/player.js
CHANGED
|
@@ -4525,7 +4525,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
4525
4525
|
|
|
4526
4526
|
if (this.isLive()) {
|
|
4527
4527
|
const now = this.getPresentationStartTimeAsDate().valueOf() +
|
|
4528
|
-
|
|
4528
|
+
element.currentTime * 1000;
|
|
4529
4529
|
const latency = (Date.now() - now) / 1000;
|
|
4530
4530
|
this.stats_.setLiveLatency(latency);
|
|
4531
4531
|
}
|
|
@@ -5144,7 +5144,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5144
5144
|
} else {
|
|
5145
5145
|
// eslint-disable-next-line no-restricted-syntax
|
|
5146
5146
|
if (HTMLMediaElement.prototype.addTextTrack) {
|
|
5147
|
-
return new shaka.text.SimpleTextDisplayer(
|
|
5147
|
+
return new shaka.text.SimpleTextDisplayer(
|
|
5148
|
+
this.video_, shaka.Player.TextTrackLabel);
|
|
5148
5149
|
} else {
|
|
5149
5150
|
shaka.log.warning('Text tracks are not supported by the ' +
|
|
5150
5151
|
'browser, disabling.');
|
|
@@ -6386,6 +6387,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
6386
6387
|
} // if (keyIds.size)
|
|
6387
6388
|
|
|
6388
6389
|
if (tracksChanged) {
|
|
6390
|
+
this.onTracksChanged_();
|
|
6389
6391
|
const variantsUpdated = this.updateAbrManagerVariants_();
|
|
6390
6392
|
if (!variantsUpdated) {
|
|
6391
6393
|
return;
|
|
@@ -6397,10 +6399,6 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
6397
6399
|
shaka.log.debug('Choosing new streams after key status changed');
|
|
6398
6400
|
this.chooseVariantAndSwitch_();
|
|
6399
6401
|
}
|
|
6400
|
-
|
|
6401
|
-
if (tracksChanged) {
|
|
6402
|
-
this.onTracksChanged_();
|
|
6403
|
-
}
|
|
6404
6402
|
}
|
|
6405
6403
|
|
|
6406
6404
|
/**
|
|
@@ -6781,7 +6779,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
|
|
|
6781
6779
|
* @export
|
|
6782
6780
|
*/
|
|
6783
6781
|
// eslint-disable-next-line no-useless-concat
|
|
6784
|
-
shaka.Player.version = 'v4.6.
|
|
6782
|
+
shaka.Player.version = 'v4.6.5' + '-uncompiled'; // x-release-please-version
|
|
6785
6783
|
|
|
6786
6784
|
// Initialize the deprecation system using the version string we just set
|
|
6787
6785
|
// on the player.
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* @fileoverview
|
|
9
|
-
* @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed
|
|
10
9
|
*/
|
|
11
10
|
|
|
12
11
|
goog.provide('shaka.text.SimpleTextDisplayer');
|
|
@@ -24,8 +23,11 @@ goog.require('shaka.text.Utils');
|
|
|
24
23
|
* @export
|
|
25
24
|
*/
|
|
26
25
|
shaka.text.SimpleTextDisplayer = class {
|
|
27
|
-
/**
|
|
28
|
-
|
|
26
|
+
/**
|
|
27
|
+
* @param {HTMLMediaElement} video
|
|
28
|
+
* @param {string} label
|
|
29
|
+
*/
|
|
30
|
+
constructor(video, label) {
|
|
29
31
|
/** @private {TextTrack} */
|
|
30
32
|
this.textTrack_ = null;
|
|
31
33
|
|
|
@@ -39,7 +41,7 @@ shaka.text.SimpleTextDisplayer = class {
|
|
|
39
41
|
// element.
|
|
40
42
|
track.mode = 'disabled';
|
|
41
43
|
|
|
42
|
-
if (track.label ==
|
|
44
|
+
if (track.label == label) {
|
|
43
45
|
this.textTrack_ = track;
|
|
44
46
|
}
|
|
45
47
|
}
|
|
@@ -49,8 +51,7 @@ shaka.text.SimpleTextDisplayer = class {
|
|
|
49
51
|
// kind to 'subtitles' or 'captions' when creating the TextTrack object.
|
|
50
52
|
// The individual text tracks from the manifest will still have their own
|
|
51
53
|
// kinds which can be displayed in the app's UI.
|
|
52
|
-
this.textTrack_ = video.addTextTrack(
|
|
53
|
-
'subtitles', shaka.Player.TextTrackLabel);
|
|
54
|
+
this.textTrack_ = video.addTextTrack('subtitles', label);
|
|
54
55
|
}
|
|
55
56
|
this.textTrack_.mode = 'hidden';
|
|
56
57
|
}
|
|
@@ -80,7 +81,7 @@ shaka.text.SimpleTextDisplayer = class {
|
|
|
80
81
|
* @export
|
|
81
82
|
*/
|
|
82
83
|
append(cues) {
|
|
83
|
-
const flattenedCues = shaka.text.Utils.getCuesToFlatten(cues
|
|
84
|
+
const flattenedCues = shaka.text.Utils.getCuesToFlatten(cues);
|
|
84
85
|
|
|
85
86
|
// Convert cues.
|
|
86
87
|
const textTrackCues = [];
|
package/lib/text/text_utils.js
CHANGED
|
@@ -15,16 +15,19 @@ shaka.text.Utils = class {
|
|
|
15
15
|
* their contents should be combined and replace the payload of the parent.
|
|
16
16
|
*
|
|
17
17
|
* @param {!shaka.text.Cue} cue
|
|
18
|
+
* @param {?shaka.text.Cue=} parentCue
|
|
18
19
|
* @return {string}
|
|
19
20
|
* @private
|
|
20
21
|
*/
|
|
21
|
-
static flattenPayload_(cue) {
|
|
22
|
+
static flattenPayload_(cue, parentCue) {
|
|
22
23
|
if (cue.lineBreak) {
|
|
23
24
|
// This is a vertical lineBreak, so insert a newline.
|
|
24
25
|
return '\n';
|
|
25
26
|
}
|
|
26
27
|
if (cue.nestedCues.length) {
|
|
27
|
-
return cue.nestedCues.map(
|
|
28
|
+
return cue.nestedCues.map((nested) => {
|
|
29
|
+
return shaka.text.Utils.flattenPayload_(nested, cue);
|
|
30
|
+
}).join('');
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
// Handle bold, italics and underline
|
|
@@ -43,14 +46,22 @@ shaka.text.Utils = class {
|
|
|
43
46
|
openStyleTags.push(['u']);
|
|
44
47
|
}
|
|
45
48
|
// Handle color classes, if the value consists of letters
|
|
49
|
+
let color = cue.color;
|
|
50
|
+
if (color == '' && parentCue) {
|
|
51
|
+
color = parentCue.color;
|
|
52
|
+
}
|
|
46
53
|
let classes = '';
|
|
47
|
-
const
|
|
48
|
-
if (
|
|
49
|
-
classes += `.${
|
|
54
|
+
const colorName = shaka.text.Utils.getColorName_(color);
|
|
55
|
+
if (colorName) {
|
|
56
|
+
classes += `.${colorName}`;
|
|
57
|
+
}
|
|
58
|
+
let bgColor = cue.backgroundColor;
|
|
59
|
+
if (bgColor == '' && parentCue) {
|
|
60
|
+
bgColor = parentCue.backgroundColor;
|
|
50
61
|
}
|
|
51
|
-
const
|
|
52
|
-
if (
|
|
53
|
-
classes += `.bg_${
|
|
62
|
+
const bgColorName = shaka.text.Utils.getColorName_(bgColor);
|
|
63
|
+
if (bgColorName) {
|
|
64
|
+
classes += `.bg_${bgColorName}`;
|
|
54
65
|
}
|
|
55
66
|
if (classes) {
|
|
56
67
|
openStyleTags.push(['c', classes]);
|
|
@@ -69,7 +80,20 @@ shaka.text.Utils = class {
|
|
|
69
80
|
* @private
|
|
70
81
|
*/
|
|
71
82
|
static getColorName_(string) {
|
|
72
|
-
|
|
83
|
+
let colorString = string.toLowerCase();
|
|
84
|
+
const rgb = colorString.replace(/\s/g, '')
|
|
85
|
+
.match(/^rgba?\((\d+),(\d+),(\d+),?([^,\s)]+)?/i);
|
|
86
|
+
if (rgb) {
|
|
87
|
+
colorString = '#' +
|
|
88
|
+
(parseInt(rgb[1], 10) | (1 << 8)).toString(16).slice(1) +
|
|
89
|
+
(parseInt(rgb[2], 10) | (1 << 8)).toString(16).slice(1) +
|
|
90
|
+
(parseInt(rgb[3], 10) | (1 << 8)).toString(16).slice(1);
|
|
91
|
+
} else if (colorString.startsWith('#') && colorString.length > 7) {
|
|
92
|
+
// With this we lose the alpha of the color, but it is better than having
|
|
93
|
+
// no color.
|
|
94
|
+
colorString = colorString.slice(0, 7);
|
|
95
|
+
}
|
|
96
|
+
switch (colorString) {
|
|
73
97
|
case 'white':
|
|
74
98
|
case '#fff':
|
|
75
99
|
case '#ffffff':
|
|
@@ -92,6 +116,7 @@ shaka.text.Utils = class {
|
|
|
92
116
|
return 'yellow';
|
|
93
117
|
case 'magenta':
|
|
94
118
|
case '#f0f':
|
|
119
|
+
case '#ff00ff':
|
|
95
120
|
return 'magenta';
|
|
96
121
|
case 'blue':
|
|
97
122
|
case '#00f':
|
|
@@ -118,19 +143,20 @@ shaka.text.Utils = class {
|
|
|
118
143
|
* isContainer = false.
|
|
119
144
|
*
|
|
120
145
|
* @param {!Array.<!shaka.text.Cue>} cues
|
|
121
|
-
* @param {
|
|
146
|
+
* @param {?shaka.text.Cue=} parentCue
|
|
122
147
|
* @return {!Array.<!shaka.text.Cue>}
|
|
123
148
|
*/
|
|
124
|
-
static getCuesToFlatten(cues,
|
|
149
|
+
static getCuesToFlatten(cues, parentCue) {
|
|
150
|
+
const result = [];
|
|
125
151
|
for (const cue of cues) {
|
|
126
152
|
if (cue.isContainer) {
|
|
127
153
|
// Recurse to find the actual text payload cues.
|
|
128
|
-
shaka.text.Utils.getCuesToFlatten(cue.nestedCues,
|
|
154
|
+
result.push(...shaka.text.Utils.getCuesToFlatten(cue.nestedCues, cue));
|
|
129
155
|
} else {
|
|
130
156
|
// Flatten the payload.
|
|
131
157
|
const flatCue = cue.clone();
|
|
132
158
|
flatCue.nestedCues = [];
|
|
133
|
-
flatCue.payload = shaka.text.Utils.flattenPayload_(cue);
|
|
159
|
+
flatCue.payload = shaka.text.Utils.flattenPayload_(cue, parentCue);
|
|
134
160
|
result.push(flatCue);
|
|
135
161
|
}
|
|
136
162
|
}
|
|
@@ -707,37 +707,46 @@ shaka.text.UITextDisplayer = class {
|
|
|
707
707
|
// (for vertical growing left) is aligned at the line.
|
|
708
708
|
// TODO: Implement line alignment with line number.
|
|
709
709
|
// TODO: Implement lineAlignment of 'CENTER'.
|
|
710
|
-
|
|
710
|
+
let line = cue.line;
|
|
711
|
+
if (line != null) {
|
|
711
712
|
let lineInterpretation = cue.lineInterpretation;
|
|
712
713
|
// HACK: the current implementation of UITextDisplayer only handled
|
|
713
|
-
// PERCENTAGE,
|
|
714
|
-
|
|
715
|
-
if (cue.line == 0 &&
|
|
716
|
-
lineInterpretation == Cue.lineInterpretation.LINE_NUMBER) {
|
|
714
|
+
// PERCENTAGE, so we need convert LINE_NUMBER to PERCENTAGE
|
|
715
|
+
if (lineInterpretation == Cue.lineInterpretation.LINE_NUMBER) {
|
|
717
716
|
lineInterpretation = Cue.lineInterpretation.PERCENTAGE;
|
|
717
|
+
let maxLines = 16;
|
|
718
|
+
// The maximum number of lines is different if it is a vertical video.
|
|
719
|
+
if (this.aspectRatio_ && this.aspectRatio_ < 1) {
|
|
720
|
+
maxLines = 32;
|
|
721
|
+
}
|
|
722
|
+
if (line < 0) {
|
|
723
|
+
line = 100 + line / maxLines * 100;
|
|
724
|
+
} else {
|
|
725
|
+
line = line / maxLines * 100;
|
|
726
|
+
}
|
|
718
727
|
}
|
|
719
728
|
if (lineInterpretation == Cue.lineInterpretation.PERCENTAGE) {
|
|
720
729
|
style.position = 'absolute';
|
|
721
730
|
if (cue.writingMode == Cue.writingMode.HORIZONTAL_TOP_TO_BOTTOM) {
|
|
722
731
|
style.width = '100%';
|
|
723
732
|
if (cue.lineAlign == Cue.lineAlign.START) {
|
|
724
|
-
style.top =
|
|
733
|
+
style.top = line + '%';
|
|
725
734
|
} else if (cue.lineAlign == Cue.lineAlign.END) {
|
|
726
|
-
style.bottom = (100 -
|
|
735
|
+
style.bottom = (100 - line) + '%';
|
|
727
736
|
}
|
|
728
737
|
} else if (cue.writingMode == Cue.writingMode.VERTICAL_LEFT_TO_RIGHT) {
|
|
729
738
|
style.height = '100%';
|
|
730
739
|
if (cue.lineAlign == Cue.lineAlign.START) {
|
|
731
|
-
style.left =
|
|
740
|
+
style.left = line + '%';
|
|
732
741
|
} else if (cue.lineAlign == Cue.lineAlign.END) {
|
|
733
|
-
style.right = (100 -
|
|
742
|
+
style.right = (100 - line) + '%';
|
|
734
743
|
}
|
|
735
744
|
} else {
|
|
736
745
|
style.height = '100%';
|
|
737
746
|
if (cue.lineAlign == Cue.lineAlign.START) {
|
|
738
|
-
style.right =
|
|
747
|
+
style.right = line + '%';
|
|
739
748
|
} else if (cue.lineAlign == Cue.lineAlign.END) {
|
|
740
|
-
style.left = (100 -
|
|
749
|
+
style.left = (100 - line) + '%';
|
|
741
750
|
}
|
|
742
751
|
}
|
|
743
752
|
}
|
|
@@ -40,7 +40,7 @@ shaka.text.WebVttGenerator = class {
|
|
|
40
40
|
milliseconds;
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
-
const flattenedCues = shaka.text.Utils.getCuesToFlatten(cues
|
|
43
|
+
const flattenedCues = shaka.text.Utils.getCuesToFlatten(cues);
|
|
44
44
|
|
|
45
45
|
let webvttString = 'WEBVTT\n\n';
|
|
46
46
|
for (const cue of flattenedCues) {
|
package/lib/util/ts_parser.js
CHANGED
|
@@ -614,9 +614,11 @@ shaka.util.TsParser = class {
|
|
|
614
614
|
let sort = false;
|
|
615
615
|
for (const audioData of this.audioData_) {
|
|
616
616
|
const pes = this.parsePES_(audioData);
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
617
|
+
let previousPes = this.audioPes_.length ?
|
|
618
|
+
this.audioPes_[this.audioPes_.length - 1] : null;
|
|
619
|
+
if (pes && pes.pts != null && pes.dts != null && (!previousPes ||
|
|
620
|
+
(previousPes.pts != pes.pts && previousPes.dts != pes.dts))) {
|
|
621
|
+
if (this.audioPes_.length && pes.dts < (previousPes.dts || 0)) {
|
|
620
622
|
sort = true;
|
|
621
623
|
}
|
|
622
624
|
this.audioPes_.push(pes);
|
|
@@ -625,7 +627,7 @@ shaka.util.TsParser = class {
|
|
|
625
627
|
if (!data) {
|
|
626
628
|
continue;
|
|
627
629
|
}
|
|
628
|
-
|
|
630
|
+
previousPes = this.audioPes_.pop();
|
|
629
631
|
previousPes.data =
|
|
630
632
|
shaka.util.Uint8ArrayUtils.concat(previousPes.data, data);
|
|
631
633
|
this.audioPes_.push(previousPes);
|
|
@@ -654,9 +656,11 @@ shaka.util.TsParser = class {
|
|
|
654
656
|
let sort = false;
|
|
655
657
|
for (const videoData of this.videoData_) {
|
|
656
658
|
const pes = this.parsePES_(videoData);
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
659
|
+
let previousPes = this.videoPes_.length ?
|
|
660
|
+
this.videoPes_[this.videoPes_.length - 1] : null;
|
|
661
|
+
if (pes && pes.pts != null && pes.dts != null && (!previousPes ||
|
|
662
|
+
(previousPes.pts != pes.pts && previousPes.dts != pes.dts))) {
|
|
663
|
+
if (this.videoPes_.length && pes.dts < (previousPes.dts || 0)) {
|
|
660
664
|
sort = true;
|
|
661
665
|
}
|
|
662
666
|
this.videoPes_.push(pes);
|
|
@@ -665,7 +669,7 @@ shaka.util.TsParser = class {
|
|
|
665
669
|
if (!data) {
|
|
666
670
|
continue;
|
|
667
671
|
}
|
|
668
|
-
|
|
672
|
+
previousPes = this.videoPes_.pop();
|
|
669
673
|
previousPes.data =
|
|
670
674
|
shaka.util.Uint8ArrayUtils.concat(previousPes.data, data);
|
|
671
675
|
this.videoPes_.push(previousPes);
|
package/package.json
CHANGED
|
@@ -2390,6 +2390,33 @@ describe('DrmEngine', () => {
|
|
|
2390
2390
|
[drmInfoAudio]);
|
|
2391
2391
|
expect(returned).toEqual([drmInfoDesired]);
|
|
2392
2392
|
});
|
|
2393
|
+
|
|
2394
|
+
it('does not match incompatible drmInfos', () => {
|
|
2395
|
+
// Different key systems do not match.
|
|
2396
|
+
const drmInfo1 = {
|
|
2397
|
+
keySystem: 'drm.abc',
|
|
2398
|
+
licenseServerUri: undefined,
|
|
2399
|
+
distinctiveIdentifierRequired: false,
|
|
2400
|
+
persistentStateRequired: false,
|
|
2401
|
+
serverCertificate: undefined,
|
|
2402
|
+
serverCertificateUri: '',
|
|
2403
|
+
initData: [],
|
|
2404
|
+
keyIds: new Set(),
|
|
2405
|
+
};
|
|
2406
|
+
const drmInfo2 = {
|
|
2407
|
+
keySystem: 'drm.foobar',
|
|
2408
|
+
licenseServerUri: undefined,
|
|
2409
|
+
distinctiveIdentifierRequired: false,
|
|
2410
|
+
persistentStateRequired: false,
|
|
2411
|
+
serverCertificate: undefined,
|
|
2412
|
+
serverCertificateUri: '',
|
|
2413
|
+
initData: [],
|
|
2414
|
+
keyIds: new Set(),
|
|
2415
|
+
};
|
|
2416
|
+
const returned1 = shaka.media.DrmEngine.getCommonDrmInfos(
|
|
2417
|
+
[drmInfo1], [drmInfo2]);
|
|
2418
|
+
expect(returned1).toEqual([]);
|
|
2419
|
+
});
|
|
2393
2420
|
}); // describe('getCommonDrmInfos')
|
|
2394
2421
|
|
|
2395
2422
|
describe('configure', () => {
|
package/test/player_unit.js
CHANGED
|
@@ -3484,6 +3484,37 @@ describe('Player', () => {
|
|
|
3484
3484
|
expect(tracks[0].id).toBe(2);
|
|
3485
3485
|
});
|
|
3486
3486
|
|
|
3487
|
+
it('removes based on frameRate', async () => {
|
|
3488
|
+
manifest = shaka.test.ManifestGenerator.generate((manifest) => {
|
|
3489
|
+
manifest.addVariant(0, (variant) => {
|
|
3490
|
+
variant.addVideo(1, (stream) => {
|
|
3491
|
+
stream.frameRate = 15;
|
|
3492
|
+
});
|
|
3493
|
+
});
|
|
3494
|
+
|
|
3495
|
+
manifest.addVariant(1, (variant) => {
|
|
3496
|
+
variant.addVideo(2, (stream) => {
|
|
3497
|
+
stream.frameRate = 30;
|
|
3498
|
+
});
|
|
3499
|
+
});
|
|
3500
|
+
|
|
3501
|
+
manifest.addVariant(2, (variant) => {
|
|
3502
|
+
variant.addVideo(3, (stream) => {
|
|
3503
|
+
stream.frameRate = 60;
|
|
3504
|
+
});
|
|
3505
|
+
});
|
|
3506
|
+
});
|
|
3507
|
+
|
|
3508
|
+
await player.load(fakeManifestUri, 0, fakeMimeType);
|
|
3509
|
+
expect(player.getVariantTracks().length).toBe(3);
|
|
3510
|
+
|
|
3511
|
+
player.configure({restrictions: {minFrameRate: 20, maxFrameRate: 40}});
|
|
3512
|
+
|
|
3513
|
+
const tracks = player.getVariantTracks();
|
|
3514
|
+
expect(tracks.length).toBe(1);
|
|
3515
|
+
expect(tracks[0].id).toBe(1);
|
|
3516
|
+
});
|
|
3517
|
+
|
|
3487
3518
|
it('removes the whole variant if one stream is restricted', async () => {
|
|
3488
3519
|
manifest = shaka.test.ManifestGenerator.generate((manifest) => {
|
|
3489
3520
|
manifest.addVariant(0, (variant) => {
|
|
@@ -377,7 +377,8 @@ shaka.test.NativeTextLayoutTests = class extends shaka.test.TextLayoutTests {
|
|
|
377
377
|
|
|
378
378
|
/** @override */
|
|
379
379
|
recreateTextDisplayer() {
|
|
380
|
-
this.textDisplayer = new shaka.text.SimpleTextDisplayer(
|
|
380
|
+
this.textDisplayer = new shaka.text.SimpleTextDisplayer(
|
|
381
|
+
this.video, shaka.Player.TextTrackLabel);
|
|
381
382
|
this.textDisplayer.setTextVisibility(true);
|
|
382
383
|
}
|
|
383
384
|
|
|
@@ -18,7 +18,7 @@ describe('SimpleTextDisplayer', () => {
|
|
|
18
18
|
|
|
19
19
|
beforeEach(() => {
|
|
20
20
|
video = new shaka.test.FakeVideo();
|
|
21
|
-
displayer = new SimpleTextDisplayer(video);
|
|
21
|
+
displayer = new SimpleTextDisplayer(video, shaka.Player.TextTrackLabel);
|
|
22
22
|
|
|
23
23
|
expect(video.textTracks.length).toBe(1);
|
|
24
24
|
mockTrack = /** @type {!shaka.test.FakeTextTrack} */ (video.textTracks[0]);
|
|
@@ -18,11 +18,11 @@ describe('WebVttGenerator', () => {
|
|
|
18
18
|
const shakaCue2 = new shaka.text.Cue(40, 50, 'Test2');
|
|
19
19
|
shakaCue2.textAlign = shaka.text.Cue.textAlign.RIGHT;
|
|
20
20
|
shakaCue2.writingMode = shaka.text.Cue.writingMode.VERTICAL_RIGHT_TO_LEFT;
|
|
21
|
-
shakaCue2.color = '#
|
|
22
|
-
shakaCue2.backgroundColor = '
|
|
21
|
+
shakaCue2.color = '#00ff00ff';
|
|
22
|
+
shakaCue2.backgroundColor = 'rgba(0,255,0,1)';
|
|
23
23
|
const shakaCue3 = new shaka.text.Cue(50, 51, 'Test3');
|
|
24
24
|
shakaCue3.textAlign = shaka.text.Cue.textAlign.CENTER;
|
|
25
|
-
shakaCue3.color = '
|
|
25
|
+
shakaCue3.color = 'rgb(255,255,0)';
|
|
26
26
|
shakaCue3.backgroundColor = '#00ffff';
|
|
27
27
|
const shakaCue4 = new shaka.text.Cue(52, 53, 'Test4');
|
|
28
28
|
shakaCue4.textAlign = shaka.text.Cue.textAlign.START;
|