shaka-player 4.6.13 → 4.6.15
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/shaka-bot-commands/lib.sh +37 -12
- package/.github/workflows/shaka-bot-commands/main.sh +4 -2
- package/.github/workflows/talk-to-shaka-bot.yaml +1 -0
- package/AUTHORS +1 -0
- package/CHANGELOG.md +26 -0
- package/CONTRIBUTORS +1 -0
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/deps.js +1 -1
- package/dist/locales.js +29 -29
- package/dist/shaka-player.compiled.debug.js +91 -89
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.js +348 -349
- package/dist/shaka-player.compiled.map +3 -3
- package/dist/shaka-player.ui.debug.js +105 -103
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.js +433 -434
- package/dist/shaka-player.ui.map +3 -3
- package/lib/ads/ad_manager.js +1 -1
- package/lib/dash/segment_template.js +18 -13
- package/lib/deprecate/deprecate.js +1 -1
- package/lib/hls/hls_parser.js +24 -5
- package/lib/media/manifest_parser.js +3 -2
- package/lib/media/segment_reference.js +4 -1
- package/lib/media/streaming_engine.js +2 -2
- package/lib/player.js +3 -3
- package/lib/polyfill/mediasource.js +5 -36
- package/lib/text/vtt_text_parser.js +2 -1
- package/lib/util/error.js +1 -0
- package/lib/util/periods.js +23 -1
- package/lib/util/stream_utils.js +1 -1
- package/lib/util/ts_parser.js +2 -2
- package/package.json +3 -3
- package/test/dash/dash_parser_segment_template_unit.js +1 -1
- package/test/hls/hls_parser_unit.js +28 -0
- package/test/media/buffering_observer_unit.js +13 -0
- package/test/player_integration.js +9 -1
- package/test/player_load_graph_integration.js +13 -10
- package/test/player_src_equals_integration.js +2 -2
- package/test/player_unit.js +9 -3
- package/test/test/assets/hls-ts-h265/index.m3u8 +2 -0
- package/test/test/assets/hls-ts-muxed-aac-h265/media.m3u8 +5 -1
- package/test/test/util/waiter.js +5 -0
- package/test/text/vtt_text_parser_unit.js +31 -0
- package/test/transmuxer/transmuxer_integration.js +22 -53
- package/test/util/periods_unit.js +64 -0
- package/ui/less/containers.less +1 -0
package/lib/ads/ad_manager.js
CHANGED
|
@@ -656,7 +656,7 @@ shaka.ads.AdManager = class extends shaka.util.FakeEventTarget {
|
|
|
656
656
|
*/
|
|
657
657
|
getServerSideCuePoints() {
|
|
658
658
|
shaka.Deprecate.deprecateFeature(5,
|
|
659
|
-
'AdManager',
|
|
659
|
+
'AdManager.getServerSideCuePoints',
|
|
660
660
|
'Please use getCuePoints function.');
|
|
661
661
|
return this.getCuePoints();
|
|
662
662
|
}
|
|
@@ -755,16 +755,10 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
755
755
|
|
|
756
756
|
this.evict(this.periodStart_);
|
|
757
757
|
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
if (this.periodEnd_ !== Infinity) {
|
|
763
|
-
// Adjust the last timeline entry to match the period end
|
|
764
|
-
const lastTimePeriod = timeline[timeline.length - 1];
|
|
765
|
-
// NOTE: end should be relative to period start
|
|
766
|
-
lastTimePeriod.end = this.periodEnd_ - this.periodStart_;
|
|
767
|
-
}
|
|
758
|
+
// Do NOT adjust last range to match period end! With high precision
|
|
759
|
+
// timestamps several recalculations may give wrong results on less precise
|
|
760
|
+
// platforms. To mitigate that, we're using cached |periodEnd_| value in
|
|
761
|
+
// find/get() methods whenever possible.
|
|
768
762
|
}
|
|
769
763
|
|
|
770
764
|
/**
|
|
@@ -784,7 +778,7 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
784
778
|
const timeline = this.templateInfo_.timeline;
|
|
785
779
|
|
|
786
780
|
// Early exit if the time isn't within this period
|
|
787
|
-
if (time < this.periodStart_ || time
|
|
781
|
+
if (time < this.periodStart_ || time >= this.periodEnd_) {
|
|
788
782
|
return null;
|
|
789
783
|
}
|
|
790
784
|
|
|
@@ -797,10 +791,14 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
797
791
|
// the references by a fraction of a second. To account for this, we use
|
|
798
792
|
// the start of the next segment as /end/, unless this is the last
|
|
799
793
|
// reference, in which case we use the period end as the /end/
|
|
800
|
-
let end
|
|
794
|
+
let end;
|
|
801
795
|
|
|
802
796
|
if (i < lastIndex) {
|
|
803
797
|
end = timeline[i + 1].start + this.periodStart_;
|
|
798
|
+
} else if (this.periodEnd_ === Infinity) {
|
|
799
|
+
end = range.end + this.periodStart_;
|
|
800
|
+
} else {
|
|
801
|
+
end = this.periodEnd_;
|
|
804
802
|
}
|
|
805
803
|
|
|
806
804
|
if ((time >= start) && (time < end)) {
|
|
@@ -831,6 +829,12 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
831
829
|
.unscaledPresentationTimeOffset + range.unscaledStart;
|
|
832
830
|
const timestampOffset = this.periodStart_ -
|
|
833
831
|
this.templateInfo_.scaledPresentationTimeOffset;
|
|
832
|
+
const trueSegmentEnd = this.periodStart_ + range.end;
|
|
833
|
+
let segmentEnd = trueSegmentEnd;
|
|
834
|
+
if (correctedPosition === this.getNumReferences() - 1 &&
|
|
835
|
+
this.periodEnd_ !== Infinity) {
|
|
836
|
+
segmentEnd = this.periodEnd_;
|
|
837
|
+
}
|
|
834
838
|
|
|
835
839
|
const partialSegmentRefs = [];
|
|
836
840
|
|
|
@@ -901,7 +905,7 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
901
905
|
|
|
902
906
|
ref = new shaka.media.SegmentReference(
|
|
903
907
|
this.periodStart_ + range.start,
|
|
904
|
-
|
|
908
|
+
segmentEnd,
|
|
905
909
|
createUrisCb,
|
|
906
910
|
/* startByte= */ 0,
|
|
907
911
|
/* endByte= */ null,
|
|
@@ -916,6 +920,7 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
916
920
|
shaka.media.SegmentReference.Status.AVAILABLE,
|
|
917
921
|
this.aes128Key_,
|
|
918
922
|
/* allPartialSegments= */ range.partialSegments > 0);
|
|
923
|
+
ref.trueEndTime = trueSegmentEnd;
|
|
919
924
|
this.references[correctedPosition] = ref;
|
|
920
925
|
}
|
|
921
926
|
|
package/lib/hls/hls_parser.js
CHANGED
|
@@ -32,6 +32,7 @@ goog.require('shaka.util.FakeEvent');
|
|
|
32
32
|
goog.require('shaka.util.LanguageUtils');
|
|
33
33
|
goog.require('shaka.util.ManifestParserUtils');
|
|
34
34
|
goog.require('shaka.util.MimeUtils');
|
|
35
|
+
goog.require('shaka.util.Networking');
|
|
35
36
|
goog.require('shaka.util.OperationManager');
|
|
36
37
|
goog.require('shaka.util.Pssh');
|
|
37
38
|
goog.require('shaka.media.SegmentUtils');
|
|
@@ -908,8 +909,11 @@ shaka.hls.HlsParser = class {
|
|
|
908
909
|
playlist, middleSegment.tags, getUris);
|
|
909
910
|
this.mapTagToInitSegmentRefMap_.clear();
|
|
910
911
|
if (initSegmentRef) {
|
|
911
|
-
const initSegmentRequest = shaka.
|
|
912
|
-
initSegmentRef.getUris(),
|
|
912
|
+
const initSegmentRequest = shaka.util.Networking.createSegmentRequest(
|
|
913
|
+
initSegmentRef.getUris(),
|
|
914
|
+
initSegmentRef.getStartByte(),
|
|
915
|
+
initSegmentRef.getEndByte(),
|
|
916
|
+
this.config_.retryParameters);
|
|
913
917
|
const initType =
|
|
914
918
|
shaka.net.NetworkingEngine.AdvancedRequestType.INIT_SEGMENT;
|
|
915
919
|
const initResponse = await this.makeNetworkRequest_(
|
|
@@ -2831,12 +2835,12 @@ shaka.hls.HlsParser = class {
|
|
|
2831
2835
|
// Don't download the key object until the segment is parsed, to avoid a
|
|
2832
2836
|
// startup delay for long manifests with lots of keys.
|
|
2833
2837
|
keyInfo.fetchKey = async () => {
|
|
2834
|
-
const
|
|
2838
|
+
const keyUris = shaka.hls.Utils.constructSegmentUris(
|
|
2835
2839
|
getUris(), drmTag.getRequiredAttrValue('URI'), variables);
|
|
2836
2840
|
|
|
2837
2841
|
const requestType = shaka.net.NetworkingEngine.RequestType.KEY;
|
|
2838
2842
|
const request = shaka.net.NetworkingEngine.makeRequest(
|
|
2839
|
-
|
|
2843
|
+
keyUris, this.config_.retryParameters);
|
|
2840
2844
|
const keyResponse = await this.makeNetworkRequest_(request, requestType);
|
|
2841
2845
|
|
|
2842
2846
|
// keyResponse.status is undefined when URI is "data:text/plain;base64,"
|
|
@@ -4122,7 +4126,22 @@ shaka.hls.HlsParser = class {
|
|
|
4122
4126
|
* @return {?shaka.extern.DrmInfo}
|
|
4123
4127
|
* @private
|
|
4124
4128
|
*/
|
|
4125
|
-
static identityDrmParser_(drmTag) {
|
|
4129
|
+
static identityDrmParser_(drmTag, mimeType) {
|
|
4130
|
+
if (mimeType == 'video/mp2t') {
|
|
4131
|
+
throw new shaka.util.Error(
|
|
4132
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
4133
|
+
shaka.util.Error.Category.MANIFEST,
|
|
4134
|
+
shaka.util.Error.Code.HLS_MSE_ENCRYPTED_MP2T_NOT_SUPPORTED);
|
|
4135
|
+
}
|
|
4136
|
+
|
|
4137
|
+
if (shaka.util.Platform.isMediaKeysPolyfilled()) {
|
|
4138
|
+
throw new shaka.util.Error(
|
|
4139
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
4140
|
+
shaka.util.Error.Category.MANIFEST,
|
|
4141
|
+
shaka.util.Error.Code
|
|
4142
|
+
.HLS_MSE_ENCRYPTED_LEGACY_APPLE_MEDIA_KEYS_NOT_SUPPORTED);
|
|
4143
|
+
}
|
|
4144
|
+
|
|
4126
4145
|
const method = drmTag.getRequiredAttrValue('METHOD');
|
|
4127
4146
|
const VALID_METHODS = ['SAMPLE-AES', 'SAMPLE-AES-CTR'];
|
|
4128
4147
|
if (!VALID_METHODS.includes(method)) {
|
|
@@ -28,7 +28,7 @@ shaka.media.ManifestParser = class {
|
|
|
28
28
|
*/
|
|
29
29
|
static registerParserByExtension(extension, parserFactory) {
|
|
30
30
|
shaka.Deprecate.deprecateFeature(5,
|
|
31
|
-
'ManifestParser',
|
|
31
|
+
'ManifestParser.registerParserByExtension',
|
|
32
32
|
'Please use an ManifestParser with registerParserByMime function.');
|
|
33
33
|
}
|
|
34
34
|
|
|
@@ -125,7 +125,8 @@ shaka.media.ManifestParser = class {
|
|
|
125
125
|
shaka.util.Error.Severity.CRITICAL,
|
|
126
126
|
shaka.util.Error.Category.MANIFEST,
|
|
127
127
|
shaka.util.Error.Code.UNABLE_TO_GUESS_MANIFEST_TYPE,
|
|
128
|
-
uri
|
|
128
|
+
uri,
|
|
129
|
+
mimeType);
|
|
129
130
|
}
|
|
130
131
|
|
|
131
132
|
|
|
@@ -123,7 +123,10 @@ shaka.media.InitSegmentReference = class {
|
|
|
123
123
|
static equal(reference1, reference2) {
|
|
124
124
|
const ArrayUtils = shaka.util.ArrayUtils;
|
|
125
125
|
const BufferUtils = shaka.util.BufferUtils;
|
|
126
|
-
|
|
126
|
+
|
|
127
|
+
if (reference1 === reference2) {
|
|
128
|
+
return true;
|
|
129
|
+
} else if (!reference1 || !reference2) {
|
|
127
130
|
return reference1 == reference2;
|
|
128
131
|
} else {
|
|
129
132
|
return reference1.getStartByte() == reference2.getStartByte() &&
|
|
@@ -2153,8 +2153,8 @@ shaka.media.StreamingEngine = class {
|
|
|
2153
2153
|
const bufferedBehind = presentationTime - startTime;
|
|
2154
2154
|
|
|
2155
2155
|
const overflow = bufferedBehind - bufferBehind;
|
|
2156
|
-
// See: https://github.com/shaka-project/shaka-player/issues/
|
|
2157
|
-
if (overflow <=
|
|
2156
|
+
// See: https://github.com/shaka-project/shaka-player/issues/6240
|
|
2157
|
+
if (overflow <= 1) {
|
|
2158
2158
|
shaka.log.v2(logPrefix,
|
|
2159
2159
|
'buffer behind okay:',
|
|
2160
2160
|
'presentationTime=' + presentationTime,
|
package/lib/player.js
CHANGED
|
@@ -734,7 +734,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
734
734
|
// player having been initialized.
|
|
735
735
|
if (mediaElement) {
|
|
736
736
|
shaka.Deprecate.deprecateFeature(5,
|
|
737
|
-
'Player',
|
|
737
|
+
'Player w/ mediaElement',
|
|
738
738
|
'Please migrate from initializing Player with a mediaElement; ' +
|
|
739
739
|
'use the attach method instead.');
|
|
740
740
|
this.attach(mediaElement, /* initializeMediaSource= */ true);
|
|
@@ -1842,7 +1842,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
1842
1842
|
this.abrManager_ = abrFactory();
|
|
1843
1843
|
if (typeof this.abrManager_.setMediaElement != 'function') {
|
|
1844
1844
|
shaka.Deprecate.deprecateFeature(5,
|
|
1845
|
-
'AbrManager',
|
|
1845
|
+
'AbrManager w/o setMediaElement',
|
|
1846
1846
|
'Please use an AbrManager with setMediaElement function.');
|
|
1847
1847
|
this.abrManager_.setMediaElement = () => {};
|
|
1848
1848
|
}
|
|
@@ -6837,7 +6837,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
|
|
|
6837
6837
|
* @export
|
|
6838
6838
|
*/
|
|
6839
6839
|
// eslint-disable-next-line no-useless-concat
|
|
6840
|
-
shaka.Player.version = 'v4.6.
|
|
6840
|
+
shaka.Player.version = 'v4.6.15' + '-uncompiled'; // x-release-please-version
|
|
6841
6841
|
|
|
6842
6842
|
// Initialize the deprecation system using the version string we just set
|
|
6843
6843
|
// on the player.
|
|
@@ -32,11 +32,12 @@ shaka.polyfill.MediaSource = class {
|
|
|
32
32
|
|
|
33
33
|
if (!window.MediaSource) {
|
|
34
34
|
shaka.log.info('No MSE implementation available.');
|
|
35
|
-
} else if (
|
|
36
|
-
cast.__platform__.canDisplayType) {
|
|
35
|
+
} else if (shaka.util.Platform.isChromecast()) {
|
|
37
36
|
shaka.log.info('Patching Chromecast MSE bugs.');
|
|
38
|
-
// Chromecast
|
|
39
|
-
|
|
37
|
+
// Chromecast fails on some TS content, even though it is supposed to
|
|
38
|
+
// support it. Better to transmux.
|
|
39
|
+
// See https://github.com/shaka-project/shaka-player/issues/5278
|
|
40
|
+
shaka.polyfill.MediaSource.rejectContainer_('mp2t');
|
|
40
41
|
} else if (safariVersion) {
|
|
41
42
|
// NOTE: shaka.Player.isBrowserSupported() has its own restrictions on
|
|
42
43
|
// Safari version.
|
|
@@ -182,38 +183,6 @@ shaka.polyfill.MediaSource = class {
|
|
|
182
183
|
};
|
|
183
184
|
}
|
|
184
185
|
|
|
185
|
-
/**
|
|
186
|
-
* Patch isTypeSupported() to chain to a private API on the Chromecast which
|
|
187
|
-
* can query for support of detailed content parameters.
|
|
188
|
-
*
|
|
189
|
-
* @private
|
|
190
|
-
*/
|
|
191
|
-
static patchCastIsTypeSupported_() {
|
|
192
|
-
const originalIsTypeSupported = MediaSource.isTypeSupported;
|
|
193
|
-
|
|
194
|
-
MediaSource.isTypeSupported = (mimeType) => {
|
|
195
|
-
// Parse the basic MIME type from its parameters.
|
|
196
|
-
const pieces = mimeType.split(/ *; */);
|
|
197
|
-
pieces.shift(); // Remove basic MIME type from pieces.
|
|
198
|
-
|
|
199
|
-
const hasCodecs = pieces.some((piece) => piece.startsWith('codecs='));
|
|
200
|
-
if (!hasCodecs) {
|
|
201
|
-
// Though the original reason for this special case was not documented,
|
|
202
|
-
// it is presumed to be because the platform won't accept a MIME type
|
|
203
|
-
// without codecs in canDisplayType. It is valid, however, in
|
|
204
|
-
// isTypeSupported.
|
|
205
|
-
return originalIsTypeSupported(mimeType);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// Only canDisplayType can check extended MIME type parameters on this
|
|
209
|
-
// platform (such as frame rate, resolution, etc).
|
|
210
|
-
// In previous versions of this polyfill, the MIME type parameters were
|
|
211
|
-
// manipulated, filtered, or extended. This is no longer true, so we pass
|
|
212
|
-
// the full MIME type to the platform as we received it.
|
|
213
|
-
return cast.__platform__.canDisplayType(mimeType);
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
|
|
217
186
|
/**
|
|
218
187
|
* Patch isTypeSupported() to translate vp09 codec strings into vp9, to allow
|
|
219
188
|
* such content to play on older smart TVs.
|
|
@@ -687,6 +687,8 @@ shaka.text.VttTextParser = class {
|
|
|
687
687
|
refCue.fontFamily, cue.fontFamily);
|
|
688
688
|
cue.fontSize = VttTextParser.getOrDefault_(
|
|
689
689
|
refCue.fontSize, cue.fontSize);
|
|
690
|
+
cue.textShadow = VttTextParser.getOrDefault_(
|
|
691
|
+
refCue.textShadow, cue.textShadow);
|
|
690
692
|
|
|
691
693
|
// Overwrite with new values as unable to determine
|
|
692
694
|
// if new value is set or not
|
|
@@ -695,7 +697,6 @@ shaka.text.VttTextParser = class {
|
|
|
695
697
|
cue.opacity = refCue.opacity;
|
|
696
698
|
cue.rubyTag = refCue.rubyTag;
|
|
697
699
|
cue.textCombineUpright = refCue.textCombineUpright;
|
|
698
|
-
cue.textShadow = refCue.textShadow;
|
|
699
700
|
cue.wrapLine = refCue.wrapLine;
|
|
700
701
|
}
|
|
701
702
|
|
package/lib/util/error.js
CHANGED
|
@@ -527,6 +527,7 @@ shaka.util.Error.Code = {
|
|
|
527
527
|
* <li>Configure the server to accept a HEAD request for the manifest.
|
|
528
528
|
* </ul>
|
|
529
529
|
* <br> error.data[0] is the manifest URI.
|
|
530
|
+
* <br> error.data[1] is the detected or specified MIME type.
|
|
530
531
|
*/
|
|
531
532
|
'UNABLE_TO_GUESS_MANIFEST_TYPE': 4000,
|
|
532
533
|
|
package/lib/util/periods.js
CHANGED
|
@@ -1180,7 +1180,18 @@ shaka.util.PeriodCombiner = class {
|
|
|
1180
1180
|
return false;
|
|
1181
1181
|
}
|
|
1182
1182
|
|
|
1183
|
-
// If language-based differences haven't decided this, look at
|
|
1183
|
+
// If language-based differences haven't decided this, look at labels.
|
|
1184
|
+
// If available options differ, look does any matches with output stream.
|
|
1185
|
+
if (best.label !== candidate.label) {
|
|
1186
|
+
if (outputStream.label === best.label) {
|
|
1187
|
+
return false;
|
|
1188
|
+
}
|
|
1189
|
+
if (outputStream.label === candidate.label) {
|
|
1190
|
+
return true;
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
// If label-based differences haven't decided this, look at roles. If
|
|
1184
1195
|
// the candidate has more roles in common with the output, upgrade to the
|
|
1185
1196
|
// candidate.
|
|
1186
1197
|
if (outputStream.roles.length) {
|
|
@@ -1383,6 +1394,17 @@ shaka.util.PeriodCombiner = class {
|
|
|
1383
1394
|
return false;
|
|
1384
1395
|
}
|
|
1385
1396
|
|
|
1397
|
+
// If language-based differences haven't decided this, look at labels.
|
|
1398
|
+
// If available options differ, look does any matches with output stream.
|
|
1399
|
+
if (best.label !== candidate.label) {
|
|
1400
|
+
if (outputStream.label === best.label) {
|
|
1401
|
+
return false;
|
|
1402
|
+
}
|
|
1403
|
+
if (outputStream.label === candidate.label) {
|
|
1404
|
+
return true;
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1386
1408
|
// If the candidate has more roles in common with the output, upgrade to the
|
|
1387
1409
|
// candidate.
|
|
1388
1410
|
if (outputStream.roles.length) {
|
package/lib/util/stream_utils.js
CHANGED
|
@@ -839,7 +839,7 @@ shaka.util.StreamUtils = class {
|
|
|
839
839
|
// currently don't support 'fLaC', while 'flac' is supported by most
|
|
840
840
|
// major browsers.
|
|
841
841
|
// See https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
|
|
842
|
-
if (codecs === 'fLaC') {
|
|
842
|
+
if (codecs === 'fLaC' && !shaka.util.Platform.isSafari()) {
|
|
843
843
|
return 'flac';
|
|
844
844
|
}
|
|
845
845
|
|
package/lib/util/ts_parser.js
CHANGED
|
@@ -433,7 +433,7 @@ shaka.util.TsParser = class {
|
|
|
433
433
|
*/
|
|
434
434
|
parseAvcNalus(pes, nextPes) {
|
|
435
435
|
shaka.Deprecate.deprecateFeature(5,
|
|
436
|
-
'TsParser',
|
|
436
|
+
'TsParser.parseAvcNalus',
|
|
437
437
|
'Please use parseNalus function instead.');
|
|
438
438
|
return this.parseNalus(pes);
|
|
439
439
|
}
|
|
@@ -769,7 +769,7 @@ shaka.util.TsParser = class {
|
|
|
769
769
|
*/
|
|
770
770
|
getVideoResolution() {
|
|
771
771
|
shaka.Deprecate.deprecateFeature(5,
|
|
772
|
-
'TsParser',
|
|
772
|
+
'TsParser.getVideoResolution',
|
|
773
773
|
'Please use getVideoInfo function instead.');
|
|
774
774
|
const videoInfo = this.getVideoInfo();
|
|
775
775
|
return {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shaka-player",
|
|
3
3
|
"description": "DASH/EME video player library",
|
|
4
|
-
"version": "4.6.
|
|
4
|
+
"version": "4.6.15",
|
|
5
5
|
"homepage": "https://github.com/shaka-project/shaka-player",
|
|
6
6
|
"author": "Google",
|
|
7
7
|
"maintainers": [
|
|
@@ -43,13 +43,13 @@
|
|
|
43
43
|
"karma-coverage": "^2.2.0",
|
|
44
44
|
"karma-jasmine": "^4.0.1",
|
|
45
45
|
"karma-jasmine-ajax": "^0.1.13",
|
|
46
|
-
"karma-local-wd-launcher": "^1.6.
|
|
46
|
+
"karma-local-wd-launcher": "^1.6.7",
|
|
47
47
|
"karma-opera-launcher": "^1.0.0",
|
|
48
48
|
"karma-sourcemap-loader": "^0.3.8",
|
|
49
49
|
"karma-spec-reporter": "^0.0.34",
|
|
50
50
|
"karma-webdriver-launcher": "^1.0.8",
|
|
51
51
|
"lcevc_dec.js": "^1.0.1",
|
|
52
|
-
"less": "
|
|
52
|
+
"less": "^4.2.0",
|
|
53
53
|
"less-plugin-clean-css": "github:austingardner/less-plugin-clean-css#4e9e77bf",
|
|
54
54
|
"material-design-lite": "^1.3.0",
|
|
55
55
|
"open-sans-fonts": "^1.6.2",
|
|
@@ -786,7 +786,7 @@ describe('DashParser SegmentTemplate', () => {
|
|
|
786
786
|
const newTemplateInfo = makeTemplateInfo(newRanges);
|
|
787
787
|
|
|
788
788
|
const newEnd = newRanges[newRanges.length - 1].end;
|
|
789
|
-
index.appendTemplateInfo(newTemplateInfo, newEnd);
|
|
789
|
+
index.appendTemplateInfo(newTemplateInfo, /* periodStart= */ 0, newEnd);
|
|
790
790
|
expect(index.find(newStart)).toBe(10);
|
|
791
791
|
expect(index.find(newEnd - 1.0)).toBe(19);
|
|
792
792
|
});
|
|
@@ -4074,6 +4074,34 @@ describe('HlsParser', () => {
|
|
|
4074
4074
|
await verifyError(master, media, error, /* onCreateSegmentIndex= */ true);
|
|
4075
4075
|
});
|
|
4076
4076
|
|
|
4077
|
+
it('if SAMPLE-AES encryption with MSE and mp2t content', async () => {
|
|
4078
|
+
const master = [
|
|
4079
|
+
'#EXTM3U\n',
|
|
4080
|
+
'#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1",',
|
|
4081
|
+
'RESOLUTION=960x540,FRAME-RATE=60\n',
|
|
4082
|
+
'video\n',
|
|
4083
|
+
].join('');
|
|
4084
|
+
|
|
4085
|
+
const media = [
|
|
4086
|
+
'#EXTM3U\n',
|
|
4087
|
+
'#EXT-X-TARGETDURATION:6\n',
|
|
4088
|
+
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
4089
|
+
'#EXT-X-KEY:METHOD=SAMPLE-AES,',
|
|
4090
|
+
'URI="fake",\n',
|
|
4091
|
+
'#EXTINF:5,\n',
|
|
4092
|
+
'#EXT-X-BYTERANGE:121090@616\n',
|
|
4093
|
+
'main.ts',
|
|
4094
|
+
].join('');
|
|
4095
|
+
|
|
4096
|
+
const error = new shaka.util.Error(
|
|
4097
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
4098
|
+
shaka.util.Error.Category.MANIFEST,
|
|
4099
|
+
Code.HLS_MSE_ENCRYPTED_MP2T_NOT_SUPPORTED);
|
|
4100
|
+
|
|
4101
|
+
await verifyError(master, media, error, /* onCreateSegmentIndex= */ true);
|
|
4102
|
+
});
|
|
4103
|
+
|
|
4104
|
+
|
|
4077
4105
|
describe('if required tags are missing', () => {
|
|
4078
4106
|
/**
|
|
4079
4107
|
* @param {string} master
|
|
@@ -11,15 +11,28 @@ describe('BufferingObserver', () => {
|
|
|
11
11
|
const thresholdAfterStarving = 5;
|
|
12
12
|
const thresholdAfterSatisfied = 2;
|
|
13
13
|
|
|
14
|
+
const originalDateNow = Date.now;
|
|
15
|
+
|
|
16
|
+
/** @type {!Date} */
|
|
17
|
+
let baseTime;
|
|
18
|
+
|
|
14
19
|
/** @type {!shaka.media.BufferingObserver} */
|
|
15
20
|
let controller;
|
|
16
21
|
|
|
17
22
|
beforeEach(() => {
|
|
23
|
+
// Any test using Date needs to have Date mocked to avoid flake.
|
|
24
|
+
baseTime = new Date(2015, 11, 30);
|
|
25
|
+
Date.now = () => baseTime.getTime();
|
|
26
|
+
|
|
18
27
|
controller = new BufferingObserver(
|
|
19
28
|
thresholdAfterStarving,
|
|
20
29
|
thresholdAfterSatisfied);
|
|
21
30
|
});
|
|
22
31
|
|
|
32
|
+
afterEach(() => {
|
|
33
|
+
Date.now = originalDateNow;
|
|
34
|
+
});
|
|
35
|
+
|
|
23
36
|
describe('when satisfied', () => {
|
|
24
37
|
beforeEach(() => {
|
|
25
38
|
controller.setState(State.SATISFIED);
|
|
@@ -1208,13 +1208,21 @@ describe('Player', () => {
|
|
|
1208
1208
|
'com.widevine.alpha': bogusUrl,
|
|
1209
1209
|
'com.microsoft.playready': bogusUrl,
|
|
1210
1210
|
});
|
|
1211
|
-
|
|
1211
|
+
|
|
1212
|
+
// This load may be interrupted, so ignore errors and don't wait.
|
|
1213
|
+
const loadPromise =
|
|
1214
|
+
player.load('test:sintel-enc_compiled').catch(() => {});
|
|
1212
1215
|
|
|
1213
1216
|
await errorPromise;
|
|
1214
1217
|
expect(unloadPromise).not.toBeNull();
|
|
1218
|
+
|
|
1215
1219
|
if (unloadPromise) {
|
|
1216
1220
|
await unloadPromise;
|
|
1217
1221
|
}
|
|
1222
|
+
|
|
1223
|
+
// This should be done, and errors ignored. But don't leave any Promise
|
|
1224
|
+
// unresolved.
|
|
1225
|
+
await loadPromise;
|
|
1218
1226
|
});
|
|
1219
1227
|
}); // describe('unloading')
|
|
1220
1228
|
|
|
@@ -373,11 +373,11 @@ describe('Player Load Graph', () => {
|
|
|
373
373
|
|
|
374
374
|
// Make the two requests one-after-another so that we don't have any idle
|
|
375
375
|
// time between them.
|
|
376
|
-
const
|
|
377
|
-
const
|
|
376
|
+
const attach = player.attach(video);
|
|
377
|
+
const load = player.load('test:sintel');
|
|
378
378
|
|
|
379
|
-
await
|
|
380
|
-
await expectAsync(
|
|
379
|
+
await attach;
|
|
380
|
+
await expectAsync(load).toBeRejected();
|
|
381
381
|
|
|
382
382
|
// Wait a couple interrupter cycles to allow the player to enter idle
|
|
383
383
|
// state.
|
|
@@ -420,22 +420,23 @@ describe('Player Load Graph', () => {
|
|
|
420
420
|
// Normally the player would initialize media source after attaching to
|
|
421
421
|
// the media element, however since we don't support media source, it
|
|
422
422
|
// should stop at the attach state.
|
|
423
|
-
player.attach(video, /* initMediaSource= */ true);
|
|
423
|
+
const attach = player.attach(video, /* initMediaSource= */ true);
|
|
424
424
|
|
|
425
425
|
await shaka.test.Util.delay(/* seconds= */ 0.25);
|
|
426
426
|
expect(lastStateChange).toBe('attach');
|
|
427
|
+
|
|
428
|
+
await attach;
|
|
427
429
|
});
|
|
428
430
|
|
|
429
431
|
it('loading ignores media source path', async () => {
|
|
430
432
|
await player.attach(video, /* initMediaSource= */ false);
|
|
431
433
|
|
|
432
|
-
|
|
433
|
-
// path, but since we don't have media source support, it should use the
|
|
434
|
-
// src= path.
|
|
435
|
-
player.load(SMALL_MP4_CONTENT_URI);
|
|
434
|
+
const load = player.load(SMALL_MP4_CONTENT_URI);
|
|
436
435
|
|
|
437
436
|
await shaka.test.Util.delay(/* seconds= */ 0.25);
|
|
438
437
|
expect(lastStateChange).toBe('src-equals');
|
|
438
|
+
|
|
439
|
+
await load;
|
|
439
440
|
});
|
|
440
441
|
|
|
441
442
|
it('unloading ignores init media source flag', async () => {
|
|
@@ -445,10 +446,12 @@ describe('Player Load Graph', () => {
|
|
|
445
446
|
// Normally the player would try to go to the media source state because
|
|
446
447
|
// we are saying to initialize media source after unloading, but since we
|
|
447
448
|
// don't have media source, it should stop at the attach state.
|
|
448
|
-
player.unload(/* initMediaSource= */ true);
|
|
449
|
+
const unload = player.unload(/* initMediaSource= */ true);
|
|
449
450
|
|
|
450
451
|
await shaka.test.Util.delay(/* seconds= */ 0.25);
|
|
451
452
|
expect(lastStateChange).toBe('unload');
|
|
453
|
+
|
|
454
|
+
await unload;
|
|
452
455
|
});
|
|
453
456
|
});
|
|
454
457
|
|
|
@@ -115,8 +115,8 @@ describe('Player Src Equals', () => {
|
|
|
115
115
|
expect(video.currentTime).toBeLessThan(2.0);
|
|
116
116
|
|
|
117
117
|
// Trigger a seek and then wait for the seek to take effect.
|
|
118
|
-
// This seek target is very close to the duration of the video.
|
|
119
|
-
video.currentTime =
|
|
118
|
+
// This seek target is very close to the duration of the video (10.01s).
|
|
119
|
+
video.currentTime = 9.5;
|
|
120
120
|
await waiter.waitForMovementOrFailOnTimeout(video, /* timeout= */10);
|
|
121
121
|
|
|
122
122
|
// Make sure the playhead is roughly where we expect it to be after
|
package/test/player_unit.js
CHANGED
|
@@ -667,15 +667,21 @@ describe('Player', () => {
|
|
|
667
667
|
});
|
|
668
668
|
|
|
669
669
|
describe('when config.streaming.preferNativeHls is set to true', () => {
|
|
670
|
-
|
|
670
|
+
beforeAll(() => {
|
|
671
671
|
shaka.media.ManifestParser.registerParserByMime(
|
|
672
672
|
'application/x-mpegurl',
|
|
673
673
|
() => new shaka.test.FakeManifestParser(manifest));
|
|
674
674
|
});
|
|
675
675
|
|
|
676
|
+
afterAll(() => {
|
|
677
|
+
// IMPORTANT: restore the ORIGINAL parser. DO NOT just unregister the
|
|
678
|
+
// fake!
|
|
679
|
+
shaka.media.ManifestParser.registerParserByMime(
|
|
680
|
+
'application/x-mpegurl',
|
|
681
|
+
() => new shaka.hls.HlsParser());
|
|
682
|
+
});
|
|
683
|
+
|
|
676
684
|
afterEach(() => {
|
|
677
|
-
shaka.media.ManifestParser.unregisterParserByMime(
|
|
678
|
-
'application/x-mpegurl');
|
|
679
685
|
video.canPlayType.calls.reset();
|
|
680
686
|
});
|
|
681
687
|
|
package/test/test/util/waiter.js
CHANGED
|
@@ -184,6 +184,7 @@ shaka.test.Waiter = class {
|
|
|
184
184
|
}
|
|
185
185
|
this.eventManager_.unlisten(mediaElement, 'timeupdate');
|
|
186
186
|
this.eventManager_.unlisten(mediaElement, 'ended');
|
|
187
|
+
this.eventManager_.unlisten(mediaElement, 'durationchange');
|
|
187
188
|
};
|
|
188
189
|
|
|
189
190
|
const p = new Promise((resolve) => {
|
|
@@ -202,6 +203,10 @@ shaka.test.Waiter = class {
|
|
|
202
203
|
timer.tickEvery(/* seconds= */ 1);
|
|
203
204
|
this.eventManager_.listen(mediaElement, 'timeupdate', check);
|
|
204
205
|
this.eventManager_.listen(mediaElement, 'ended', check);
|
|
206
|
+
// Some tests on Safari expose a condition where the ended flag can be
|
|
207
|
+
// found in the desired state in a brief window during a durationchange
|
|
208
|
+
// event.
|
|
209
|
+
this.eventManager_.listen(mediaElement, 'durationchange', check);
|
|
205
210
|
});
|
|
206
211
|
|
|
207
212
|
return this.waitUntilGeneric_(goalName, p, cleanup, mediaElement);
|