shaka-player 4.7.12 → 4.7.13
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/dist/deps.js +3 -3
- package/dist/locales.js +32 -32
- package/dist/shaka-player.compiled.d.ts +2 -2
- package/dist/shaka-player.compiled.debug.d.ts +2 -2
- package/dist/shaka-player.compiled.debug.js +224 -220
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.js +1148 -1140
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +2 -2
- package/dist/shaka-player.ui.debug.d.ts +2 -2
- package/dist/shaka-player.ui.debug.js +355 -350
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.js +1304 -1296
- package/dist/shaka-player.ui.map +4 -4
- package/externs/shaka/manifest.js +11 -1
- package/externs/shaka/offline.js +7 -1
- package/lib/dash/dash_parser.js +10 -3
- package/lib/dash/segment_base.js +8 -1
- package/lib/dash/segment_list.js +24 -18
- package/lib/dash/segment_template.js +21 -2
- package/lib/hls/hls_parser.js +18 -1
- package/lib/media/media_source_engine.js +74 -24
- package/lib/media/playhead.js +3 -3
- package/lib/media/segment_index.js +21 -20
- package/lib/media/streaming_engine.js +2 -14
- package/lib/mss/mss_parser.js +4 -0
- package/lib/offline/indexeddb/v1_storage_cell.js +2 -0
- package/lib/offline/indexeddb/v2_storage_cell.js +2 -0
- package/lib/offline/manifest_converter.js +10 -3
- package/lib/offline/storage.js +2 -0
- package/lib/player.js +16 -3
- package/lib/util/mime_utils.js +10 -5
- package/lib/util/periods.js +5 -37
- package/lib/util/stream_utils.js +334 -271
- package/package.json +1 -1
|
@@ -400,7 +400,8 @@ shaka.extern.FetchCryptoKeysFunction;
|
|
|
400
400
|
* undefined),
|
|
401
401
|
* mssPrivateData: (shaka.extern.MssPrivateData|undefined),
|
|
402
402
|
* external: boolean,
|
|
403
|
-
* fastSwitching: boolean
|
|
403
|
+
* fastSwitching: boolean,
|
|
404
|
+
* fullMimeTypes: !Set.<string>
|
|
404
405
|
* }}
|
|
405
406
|
*
|
|
406
407
|
* @description
|
|
@@ -430,10 +431,14 @@ shaka.extern.FetchCryptoKeysFunction;
|
|
|
430
431
|
* @property {string} mimeType
|
|
431
432
|
* <i>Required.</i> <br>
|
|
432
433
|
* The Stream's MIME type, e.g., 'audio/mp4', 'video/webm', or 'text/vtt'.
|
|
434
|
+
* In the case of a stream that adapts between different periods with
|
|
435
|
+
* different MIME types, this represents only the first period.
|
|
433
436
|
* @property {string} codecs
|
|
434
437
|
* <i>Defaults to '' (i.e., unknown / not needed).</i> <br>
|
|
435
438
|
* The Stream's codecs, e.g., 'avc1.4d4015' or 'vp9', which must be
|
|
436
439
|
* compatible with the Stream's MIME type. <br>
|
|
440
|
+
* In the case of a stream that adapts between different periods with
|
|
441
|
+
* different codecs, this represents only the first period.
|
|
437
442
|
* See {@link https://tools.ietf.org/html/rfc6381}
|
|
438
443
|
* @property {(number|undefined)} frameRate
|
|
439
444
|
* <i>Video streams only.</i> <br>
|
|
@@ -535,6 +540,11 @@ shaka.extern.FetchCryptoKeysFunction;
|
|
|
535
540
|
* Eg: external text tracks.
|
|
536
541
|
* @property {boolean} fastSwitching
|
|
537
542
|
* Indicate if the stream should be used for fast switching.
|
|
543
|
+
* @property {!Set.<string>} fullMimeTypes
|
|
544
|
+
* A set of full MIME types (e.g. MIME types plus codecs information), that
|
|
545
|
+
* represents the types used in each period of the original manifest.
|
|
546
|
+
* Meant for being used by compatibility checking, such as with
|
|
547
|
+
* MediaSource.isTypeSupported.
|
|
538
548
|
*
|
|
539
549
|
* @exportDoc
|
|
540
550
|
*/
|
package/externs/shaka/offline.js
CHANGED
|
@@ -230,7 +230,9 @@ shaka.extern.StreamDB;
|
|
|
230
230
|
* tilesLayout: ?string,
|
|
231
231
|
* pendingSegmentRefId: (string|undefined),
|
|
232
232
|
* pendingInitSegmentRefId: (string|undefined),
|
|
233
|
-
* dataKey: number
|
|
233
|
+
* dataKey: number,
|
|
234
|
+
* mimeType: ?string,
|
|
235
|
+
* codecs: ?string
|
|
234
236
|
* }}
|
|
235
237
|
*
|
|
236
238
|
* @property {?number} initSegmentKey
|
|
@@ -263,6 +265,10 @@ shaka.extern.StreamDB;
|
|
|
263
265
|
* downloaded.
|
|
264
266
|
* @property {number} dataKey
|
|
265
267
|
* The key to the data in storage.
|
|
268
|
+
* @property {?string} mimeType
|
|
269
|
+
* The mimeType of the segment.
|
|
270
|
+
* @property {?string} codecs
|
|
271
|
+
* The codecs of the segment.
|
|
266
272
|
*/
|
|
267
273
|
shaka.extern.SegmentDB;
|
|
268
274
|
|
package/lib/dash/dash_parser.js
CHANGED
|
@@ -1485,8 +1485,13 @@ shaka.dash.DashParser = class {
|
|
|
1485
1485
|
const getBaseUris = context.representation.getBaseUris;
|
|
1486
1486
|
streamInfo = {
|
|
1487
1487
|
generateSegmentIndex: () => {
|
|
1488
|
-
|
|
1489
|
-
periodStart, duration, getBaseUris())
|
|
1488
|
+
const segmentIndex = shaka.media.SegmentIndex.forSingleSegment(
|
|
1489
|
+
periodStart, duration, getBaseUris());
|
|
1490
|
+
segmentIndex.forEachTopLevelReference((ref) => {
|
|
1491
|
+
ref.mimeType = context.representation.mimeType;
|
|
1492
|
+
ref.codecs = context.representation.codecs;
|
|
1493
|
+
});
|
|
1494
|
+
return Promise.resolve(segmentIndex);
|
|
1490
1495
|
},
|
|
1491
1496
|
};
|
|
1492
1497
|
}
|
|
@@ -1585,7 +1590,7 @@ shaka.dash.DashParser = class {
|
|
|
1585
1590
|
},
|
|
1586
1591
|
segmentIndex: null,
|
|
1587
1592
|
mimeType: context.representation.mimeType,
|
|
1588
|
-
codecs
|
|
1593
|
+
codecs,
|
|
1589
1594
|
frameRate: context.representation.frameRate,
|
|
1590
1595
|
pixelAspectRatio: context.representation.pixelAspectRatio,
|
|
1591
1596
|
bandwidth: context.bandwidth,
|
|
@@ -1615,6 +1620,8 @@ shaka.dash.DashParser = class {
|
|
|
1615
1620
|
accessibilityPurpose,
|
|
1616
1621
|
external: false,
|
|
1617
1622
|
fastSwitching: false,
|
|
1623
|
+
fullMimeTypes: new Set([shaka.util.MimeUtils.getFullType(
|
|
1624
|
+
context.representation.mimeType, context.representation.codecs)]),
|
|
1618
1625
|
};
|
|
1619
1626
|
}
|
|
1620
1627
|
|
package/lib/dash/segment_base.js
CHANGED
|
@@ -62,7 +62,7 @@ shaka.dash.SegmentBase = class {
|
|
|
62
62
|
|
|
63
63
|
const getUris = () => resolvedUris;
|
|
64
64
|
const qualityInfo = shaka.dash.SegmentBase.createQualityInfo(context);
|
|
65
|
-
|
|
65
|
+
const ref = new shaka.media.InitSegmentReference(
|
|
66
66
|
getUris,
|
|
67
67
|
startByte,
|
|
68
68
|
endByte,
|
|
@@ -70,6 +70,9 @@ shaka.dash.SegmentBase = class {
|
|
|
70
70
|
/* timescale= */ null,
|
|
71
71
|
/* segmentData= */ null,
|
|
72
72
|
aes128Key);
|
|
73
|
+
ref.codecs = context.representation.codecs;
|
|
74
|
+
ref.mimeType = context.representation.mimeType;
|
|
75
|
+
return ref;
|
|
73
76
|
}
|
|
74
77
|
|
|
75
78
|
/**
|
|
@@ -184,6 +187,10 @@ shaka.dash.SegmentBase = class {
|
|
|
184
187
|
indexData, initData, uris, initSegmentReference, timestampOffset,
|
|
185
188
|
appendWindowStart, appendWindowEnd);
|
|
186
189
|
}
|
|
190
|
+
for (const ref of references) {
|
|
191
|
+
ref.codecs = context.representation.codecs;
|
|
192
|
+
ref.mimeType = context.representation.mimeType;
|
|
193
|
+
}
|
|
187
194
|
|
|
188
195
|
presentationTimeline.notifySegments(references);
|
|
189
196
|
|
package/lib/dash/segment_list.js
CHANGED
|
@@ -60,7 +60,8 @@ shaka.dash.SegmentList = class {
|
|
|
60
60
|
const references = SegmentList.createSegmentReferences_(
|
|
61
61
|
context.periodInfo.start, context.periodInfo.duration,
|
|
62
62
|
info.startNumber, context.representation.getBaseUris, info,
|
|
63
|
-
initSegmentReference, aes128Key
|
|
63
|
+
initSegmentReference, aes128Key, context.representation.mimeType,
|
|
64
|
+
context.representation.codecs);
|
|
64
65
|
|
|
65
66
|
const isNew = !segmentIndex;
|
|
66
67
|
if (segmentIndex) {
|
|
@@ -199,12 +200,14 @@ shaka.dash.SegmentList = class {
|
|
|
199
200
|
* @param {shaka.dash.SegmentList.SegmentListInfo} info
|
|
200
201
|
* @param {shaka.media.InitSegmentReference} initSegmentReference
|
|
201
202
|
* @param {shaka.extern.aes128Key|undefined} aes128Key
|
|
203
|
+
* @param {string} mimeType
|
|
204
|
+
* @param {string} codecs
|
|
202
205
|
* @return {!Array.<!shaka.media.SegmentReference>}
|
|
203
206
|
* @private
|
|
204
207
|
*/
|
|
205
208
|
static createSegmentReferences_(
|
|
206
209
|
periodStart, periodDuration, startNumber, getBaseUris, info,
|
|
207
|
-
initSegmentReference, aes128Key) {
|
|
210
|
+
initSegmentReference, aes128Key, mimeType, codecs) {
|
|
208
211
|
const ManifestParserUtils = shaka.util.ManifestParserUtils;
|
|
209
212
|
|
|
210
213
|
let max = info.mediaSegments.length;
|
|
@@ -251,22 +254,25 @@ shaka.dash.SegmentList = class {
|
|
|
251
254
|
}
|
|
252
255
|
return uris;
|
|
253
256
|
};
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
257
|
+
|
|
258
|
+
const ref = new shaka.media.SegmentReference(
|
|
259
|
+
periodStart + startTime,
|
|
260
|
+
periodStart + endTime,
|
|
261
|
+
getUris,
|
|
262
|
+
segment.start,
|
|
263
|
+
segment.end,
|
|
264
|
+
initSegmentReference,
|
|
265
|
+
timestampOffset,
|
|
266
|
+
appendWindowStart, appendWindowEnd,
|
|
267
|
+
/* partialReferences= */ [],
|
|
268
|
+
/* tilesLayout= */ '',
|
|
269
|
+
/* tileDuration= */ null,
|
|
270
|
+
/* syncTime= */ null,
|
|
271
|
+
shaka.media.SegmentReference.Status.AVAILABLE,
|
|
272
|
+
aes128Key);
|
|
273
|
+
ref.codecs = codecs;
|
|
274
|
+
ref.mimeType = mimeType;
|
|
275
|
+
references.push(ref);
|
|
270
276
|
prevEndTime = endTime;
|
|
271
277
|
}
|
|
272
278
|
|
|
@@ -213,6 +213,8 @@ shaka.dash.SegmentTemplate = class {
|
|
|
213
213
|
timeline: segmentInfo.timeline,
|
|
214
214
|
mediaTemplate: media,
|
|
215
215
|
indexTemplate: index,
|
|
216
|
+
mimeType: context.representation.mimeType,
|
|
217
|
+
codecs: context.representation.codecs,
|
|
216
218
|
};
|
|
217
219
|
}
|
|
218
220
|
|
|
@@ -463,6 +465,8 @@ shaka.dash.SegmentTemplate = class {
|
|
|
463
465
|
/* syncTime= */ null,
|
|
464
466
|
shaka.media.SegmentReference.Status.AVAILABLE,
|
|
465
467
|
aes128Key);
|
|
468
|
+
ref.codecs = context.representation.codecs;
|
|
469
|
+
ref.mimeType = context.representation.mimeType;
|
|
466
470
|
// This is necessary information for thumbnail streams:
|
|
467
471
|
ref.trueEndTime = trueSegmentEnd;
|
|
468
472
|
return ref;
|
|
@@ -552,7 +556,7 @@ shaka.dash.SegmentTemplate = class {
|
|
|
552
556
|
return resolvedUris;
|
|
553
557
|
};
|
|
554
558
|
const qualityInfo = shaka.dash.SegmentBase.createQualityInfo(context);
|
|
555
|
-
|
|
559
|
+
const ref = new shaka.media.InitSegmentReference(
|
|
556
560
|
getUris,
|
|
557
561
|
/* startByte= */ 0,
|
|
558
562
|
/* endByte= */ null,
|
|
@@ -560,6 +564,9 @@ shaka.dash.SegmentTemplate = class {
|
|
|
560
564
|
/* timescale= */ null,
|
|
561
565
|
/* segmentData= */ null,
|
|
562
566
|
aes128Key);
|
|
567
|
+
ref.codecs = context.representation.codecs;
|
|
568
|
+
ref.mimeType = context.representation.mimeType;
|
|
569
|
+
return ref;
|
|
563
570
|
}
|
|
564
571
|
};
|
|
565
572
|
|
|
@@ -835,6 +842,8 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
835
842
|
this.periodEnd_ !== Infinity) {
|
|
836
843
|
segmentEnd = this.periodEnd_;
|
|
837
844
|
}
|
|
845
|
+
const codecs = this.templateInfo_.codecs;
|
|
846
|
+
const mimeType = this.templateInfo_.mimeType;
|
|
838
847
|
|
|
839
848
|
const partialSegmentRefs = [];
|
|
840
849
|
|
|
@@ -877,6 +886,8 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
877
886
|
/* syncTime= */ null,
|
|
878
887
|
shaka.media.SegmentReference.Status.AVAILABLE,
|
|
879
888
|
this.aes128Key_);
|
|
889
|
+
partial.codecs = codecs;
|
|
890
|
+
partial.mimeType = mimeType;
|
|
880
891
|
if (this.segmentSequenceCadence_ == 0) {
|
|
881
892
|
if (i > 0) {
|
|
882
893
|
partial.markAsNonIndependent();
|
|
@@ -920,6 +931,8 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
920
931
|
shaka.media.SegmentReference.Status.AVAILABLE,
|
|
921
932
|
this.aes128Key_,
|
|
922
933
|
/* allPartialSegments= */ range.partialSegments > 0);
|
|
934
|
+
ref.codecs = codecs;
|
|
935
|
+
ref.mimeType = mimeType;
|
|
923
936
|
ref.trueEndTime = trueSegmentEnd;
|
|
924
937
|
this.references[correctedPosition] = ref;
|
|
925
938
|
}
|
|
@@ -955,7 +968,9 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
955
968
|
* unscaledPresentationTimeOffset: number,
|
|
956
969
|
* timeline: Array.<shaka.media.PresentationTimeline.TimeRange>,
|
|
957
970
|
* mediaTemplate: ?string,
|
|
958
|
-
* indexTemplate: ?string
|
|
971
|
+
* indexTemplate: ?string,
|
|
972
|
+
* mimeType: string,
|
|
973
|
+
* codecs: string
|
|
959
974
|
* }}
|
|
960
975
|
*
|
|
961
976
|
* @description
|
|
@@ -977,5 +992,9 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
977
992
|
* The media URI template, if given.
|
|
978
993
|
* @property {?string} indexTemplate
|
|
979
994
|
* The index URI template, if given.
|
|
995
|
+
* @property {string} mimeType
|
|
996
|
+
* The mimeType.
|
|
997
|
+
* @property {string} codecs
|
|
998
|
+
* The codecs.
|
|
980
999
|
*/
|
|
981
1000
|
shaka.dash.SegmentTemplate.SegmentTemplateInfo;
|
package/lib/hls/hls_parser.js
CHANGED
|
@@ -1224,6 +1224,7 @@ shaka.hls.HlsParser = class {
|
|
|
1224
1224
|
textStreamInfo.stream.mimeType =
|
|
1225
1225
|
this.guessMimeTypeBeforeLoading_(type, codecs) ||
|
|
1226
1226
|
this.guessMimeTypeFallback_(type);
|
|
1227
|
+
this.setFullTypeForStream_(textStreamInfo.stream);
|
|
1227
1228
|
}
|
|
1228
1229
|
}
|
|
1229
1230
|
}
|
|
@@ -1233,6 +1234,15 @@ shaka.hls.HlsParser = class {
|
|
|
1233
1234
|
return textStreams.filter((s) => s);
|
|
1234
1235
|
}
|
|
1235
1236
|
|
|
1237
|
+
/**
|
|
1238
|
+
* @param {!shaka.extern.Stream} stream
|
|
1239
|
+
* @private
|
|
1240
|
+
*/
|
|
1241
|
+
setFullTypeForStream_(stream) {
|
|
1242
|
+
stream.fullMimeTypes = new Set([shaka.util.MimeUtils.getFullType(
|
|
1243
|
+
stream.mimeType, stream.codecs)]);
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1236
1246
|
/**
|
|
1237
1247
|
* @param {!Array.<!shaka.hls.Tag>} imageTags from the playlist.
|
|
1238
1248
|
* @param {!Array.<!shaka.hls.Tag>} iFrameTags from the playlist.
|
|
@@ -2266,6 +2276,7 @@ shaka.hls.HlsParser = class {
|
|
|
2266
2276
|
stream.mimeType = realStream.mimeType;
|
|
2267
2277
|
stream.bandwidth = stream.bandwidth || realStream.bandwidth;
|
|
2268
2278
|
stream.codecs = stream.codecs || realStream.codecs;
|
|
2279
|
+
this.setFullTypeForStream_(stream);
|
|
2269
2280
|
|
|
2270
2281
|
// Since we lazy-loaded this content, the player may need to create new
|
|
2271
2282
|
// sessions for the DRM info in this stream.
|
|
@@ -2280,6 +2291,7 @@ shaka.hls.HlsParser = class {
|
|
|
2280
2291
|
// To aid manifest filtering, assume before loading that all video
|
|
2281
2292
|
// renditions have the same MIME type. (And likewise for audio.)
|
|
2282
2293
|
otherStreamInfo.stream.mimeType = realStream.mimeType;
|
|
2294
|
+
this.setFullTypeForStream_(otherStreamInfo.stream);
|
|
2283
2295
|
}
|
|
2284
2296
|
}
|
|
2285
2297
|
}
|
|
@@ -2288,6 +2300,7 @@ shaka.hls.HlsParser = class {
|
|
|
2288
2300
|
const firstSegment = realStream.segmentIndex.get(0);
|
|
2289
2301
|
if (firstSegment && firstSegment.initSegmentReference) {
|
|
2290
2302
|
stream.mimeType = 'application/mp4';
|
|
2303
|
+
this.setFullTypeForStream_(stream);
|
|
2291
2304
|
}
|
|
2292
2305
|
}
|
|
2293
2306
|
|
|
@@ -2537,6 +2550,7 @@ shaka.hls.HlsParser = class {
|
|
|
2537
2550
|
stream.drmInfos = drmInfos;
|
|
2538
2551
|
stream.keyIds = keyIds;
|
|
2539
2552
|
stream.mimeType = mimeType;
|
|
2553
|
+
this.setFullTypeForStream_(stream);
|
|
2540
2554
|
|
|
2541
2555
|
const mediaSequenceToStartTime = this.isLive_() ?
|
|
2542
2556
|
this.mediaSequenceToStartTimeByType_.get(type) : new Map();
|
|
@@ -2692,7 +2706,7 @@ shaka.hls.HlsParser = class {
|
|
|
2692
2706
|
roles.push(shaka.util.ManifestParserUtils.TextStreamKind.SUBTITLE);
|
|
2693
2707
|
}
|
|
2694
2708
|
|
|
2695
|
-
|
|
2709
|
+
const stream = {
|
|
2696
2710
|
id: this.globalId_++,
|
|
2697
2711
|
originalId: name,
|
|
2698
2712
|
groupId: null,
|
|
@@ -2730,7 +2744,10 @@ shaka.hls.HlsParser = class {
|
|
|
2730
2744
|
accessibilityPurpose: accessibilityPurpose,
|
|
2731
2745
|
external: false,
|
|
2732
2746
|
fastSwitching: false,
|
|
2747
|
+
fullMimeTypes: new Set(),
|
|
2733
2748
|
};
|
|
2749
|
+
this.setFullTypeForStream_(stream);
|
|
2750
|
+
return stream;
|
|
2734
2751
|
}
|
|
2735
2752
|
|
|
2736
2753
|
/**
|
|
@@ -31,6 +31,7 @@ goog.require('shaka.util.Mp4BoxParsers');
|
|
|
31
31
|
goog.require('shaka.util.Mp4Parser');
|
|
32
32
|
goog.require('shaka.util.Platform');
|
|
33
33
|
goog.require('shaka.util.PublicPromise');
|
|
34
|
+
goog.require('shaka.util.StreamUtils');
|
|
34
35
|
goog.require('shaka.util.TsParser');
|
|
35
36
|
goog.require('shaka.lcevc.Dec');
|
|
36
37
|
|
|
@@ -237,18 +238,61 @@ shaka.media.MediaSourceEngine = class {
|
|
|
237
238
|
* Checks if a certain type is supported.
|
|
238
239
|
*
|
|
239
240
|
* @param {shaka.extern.Stream} stream
|
|
240
|
-
* @
|
|
241
|
+
* @param {shaka.util.ManifestParserUtils.ContentType} contentType
|
|
242
|
+
* @return {!Promise.<boolean>}
|
|
241
243
|
*/
|
|
242
|
-
static isStreamSupported(stream) {
|
|
244
|
+
static async isStreamSupported(stream, contentType) {
|
|
245
|
+
if (stream.createSegmentIndex) {
|
|
246
|
+
await stream.createSegmentIndex();
|
|
247
|
+
}
|
|
248
|
+
if (!stream.segmentIndex) {
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
if (stream.segmentIndex.isEmpty()) {
|
|
252
|
+
return true;
|
|
253
|
+
}
|
|
243
254
|
const MimeUtils = shaka.util.MimeUtils;
|
|
244
|
-
const fullMimeType = MimeUtils.getFullType(stream.mimeType, stream.codecs);
|
|
245
|
-
const extendedMimeType = MimeUtils.getExtendedType(stream);
|
|
246
|
-
const fullMimeTypeWithAllCodecs = MimeUtils.getFullTypeWithAllCodecs(
|
|
247
|
-
stream.mimeType, stream.codecs);
|
|
248
255
|
const TransmuxerEngine = shaka.transmuxer.TransmuxerEngine;
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
256
|
+
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
257
|
+
const StreamUtils = shaka.util.StreamUtils;
|
|
258
|
+
const seenCombos = new Set();
|
|
259
|
+
// Check each combination of mimeType and codecs within the segment index.
|
|
260
|
+
// Unfortunately we cannot use fullMimeTypes, as we ALSO need to check the
|
|
261
|
+
// getFullTypeWithAllCodecs (for the sake of the transmuxer) and we have no
|
|
262
|
+
// way of going from a full mimeType to a full mimeType with all codecs.
|
|
263
|
+
// As this function is only called in debug mode, a little inefficiency is
|
|
264
|
+
// acceptable.
|
|
265
|
+
for (const ref of stream.segmentIndex) {
|
|
266
|
+
const mimeType = ref.mimeType || stream.mimeType || '';
|
|
267
|
+
let codecs = ref.codecs || stream.codecs || '';
|
|
268
|
+
// Don't check the same combination of mimetype + codecs twice.
|
|
269
|
+
const combo = mimeType + ':' + codecs;
|
|
270
|
+
if (seenCombos.has(combo)) {
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
seenCombos.add(combo);
|
|
274
|
+
if (contentType == ContentType.TEXT) {
|
|
275
|
+
const fullMimeType = MimeUtils.getFullType(mimeType, codecs);
|
|
276
|
+
if (!shaka.text.TextEngine.isTypeSupported(fullMimeType)) {
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
} else {
|
|
280
|
+
if (contentType == ContentType.VIDEO) {
|
|
281
|
+
codecs = StreamUtils.getCorrectVideoCodecs(codecs);
|
|
282
|
+
} else if (contentType == ContentType.AUDIO) {
|
|
283
|
+
codecs = StreamUtils.getCorrectAudioCodecs(codecs);
|
|
284
|
+
}
|
|
285
|
+
const extendedMimeType = MimeUtils.getExtendedType(
|
|
286
|
+
stream, mimeType, codecs);
|
|
287
|
+
const fullMimeType = MimeUtils.getFullTypeWithAllCodecs(
|
|
288
|
+
mimeType, codecs);
|
|
289
|
+
if (!shaka.media.Capabilities.isTypeSupported(extendedMimeType) &&
|
|
290
|
+
!TransmuxerEngine.isSupported(fullMimeType, stream.type)) {
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
return true;
|
|
252
296
|
}
|
|
253
297
|
|
|
254
298
|
/**
|
|
@@ -451,7 +495,8 @@ shaka.media.MediaSourceEngine = class {
|
|
|
451
495
|
|
|
452
496
|
for (const contentType of streamsByType.keys()) {
|
|
453
497
|
const stream = streamsByType.get(contentType);
|
|
454
|
-
|
|
498
|
+
// eslint-disable-next-line no-await-in-loop
|
|
499
|
+
await this.initSourceBuffer_(contentType, stream, stream.codecs);
|
|
455
500
|
if (this.needSplitMuxedContent_) {
|
|
456
501
|
this.queues_[ContentType.AUDIO] = [];
|
|
457
502
|
this.queues_[ContentType.VIDEO] = [];
|
|
@@ -467,13 +512,15 @@ shaka.media.MediaSourceEngine = class {
|
|
|
467
512
|
* @param {shaka.util.ManifestParserUtils.ContentType} contentType
|
|
468
513
|
* @param {shaka.extern.Stream} stream
|
|
469
514
|
* @param {string} codecs
|
|
515
|
+
* @return {!Promise}
|
|
470
516
|
* @private
|
|
471
517
|
*/
|
|
472
|
-
initSourceBuffer_(contentType, stream, codecs) {
|
|
518
|
+
async initSourceBuffer_(contentType, stream, codecs) {
|
|
473
519
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
474
520
|
|
|
475
521
|
goog.asserts.assert(
|
|
476
|
-
shaka.media.MediaSourceEngine.isStreamSupported(
|
|
522
|
+
await shaka.media.MediaSourceEngine.isStreamSupported(
|
|
523
|
+
stream, contentType),
|
|
477
524
|
'Type negotiation should happen before MediaSourceEngine.init!');
|
|
478
525
|
|
|
479
526
|
let mimeType = shaka.util.MimeUtils.getFullType(
|
|
@@ -490,7 +537,6 @@ shaka.media.MediaSourceEngine = class {
|
|
|
490
537
|
const mimeTypeWithAllCodecs =
|
|
491
538
|
shaka.util.MimeUtils.getFullTypeWithAllCodecs(
|
|
492
539
|
stream.mimeType, codecs);
|
|
493
|
-
const TransmuxerEngine = shaka.transmuxer.TransmuxerEngine;
|
|
494
540
|
if (needTransmux) {
|
|
495
541
|
const audioCodec = shaka.util.ManifestParserUtils.guessCodecsSafe(
|
|
496
542
|
ContentType.AUDIO, (codecs || '').split(','));
|
|
@@ -498,12 +544,12 @@ shaka.media.MediaSourceEngine = class {
|
|
|
498
544
|
ContentType.VIDEO, (codecs || '').split(','));
|
|
499
545
|
if (audioCodec && videoCodec) {
|
|
500
546
|
this.needSplitMuxedContent_ = true;
|
|
501
|
-
this.initSourceBuffer_(ContentType.AUDIO, stream, audioCodec);
|
|
502
|
-
this.initSourceBuffer_(ContentType.VIDEO, stream, videoCodec);
|
|
547
|
+
await this.initSourceBuffer_(ContentType.AUDIO, stream, audioCodec);
|
|
548
|
+
await this.initSourceBuffer_(ContentType.VIDEO, stream, videoCodec);
|
|
503
549
|
return;
|
|
504
550
|
}
|
|
505
|
-
const transmuxerPlugin =
|
|
506
|
-
|
|
551
|
+
const transmuxerPlugin = shaka.transmuxer.TransmuxerEngine
|
|
552
|
+
.findTransmuxer(mimeTypeWithAllCodecs);
|
|
507
553
|
if (transmuxerPlugin) {
|
|
508
554
|
const transmuxer = transmuxerPlugin();
|
|
509
555
|
this.transmuxers_[contentType] = transmuxer;
|
|
@@ -1802,7 +1848,8 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1802
1848
|
|
|
1803
1849
|
for (const contentType of streamsByType.keys()) {
|
|
1804
1850
|
const stream = streamsByType.get(contentType);
|
|
1805
|
-
|
|
1851
|
+
// eslint-disable-next-line no-await-in-loop
|
|
1852
|
+
await this.initSourceBuffer_(contentType, stream, stream.codecs);
|
|
1806
1853
|
if (this.needSplitMuxedContent_) {
|
|
1807
1854
|
this.queues_[ContentType.AUDIO] = [];
|
|
1808
1855
|
this.queues_[ContentType.VIDEO] = [];
|
|
@@ -1935,10 +1982,12 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1935
1982
|
*
|
|
1936
1983
|
* @param {shaka.util.ManifestParserUtils.ContentType} contentType
|
|
1937
1984
|
* @param {shaka.extern.Stream} stream
|
|
1985
|
+
* @param {string} refMimeType
|
|
1986
|
+
* @param {string} refCodecs
|
|
1938
1987
|
* @return {boolean}
|
|
1939
1988
|
* @private
|
|
1940
1989
|
*/
|
|
1941
|
-
isCodecSwitchNecessary_(contentType, stream) {
|
|
1990
|
+
isCodecSwitchNecessary_(contentType, stream, refMimeType, refCodecs) {
|
|
1942
1991
|
if (contentType == shaka.util.ManifestParserUtils.ContentType.TEXT) {
|
|
1943
1992
|
return false;
|
|
1944
1993
|
}
|
|
@@ -1948,8 +1997,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1948
1997
|
const currentBasicType = MimeUtils.getBasicType(
|
|
1949
1998
|
this.sourceBufferTypes_[contentType]);
|
|
1950
1999
|
|
|
1951
|
-
let newMimeType = shaka.util.MimeUtils.getFullType(
|
|
1952
|
-
stream.mimeType, stream.codecs);
|
|
2000
|
+
let newMimeType = shaka.util.MimeUtils.getFullType(refMimeType, refCodecs);
|
|
1953
2001
|
let needTransmux = this.config_.forceTransmux;
|
|
1954
2002
|
if (!shaka.media.Capabilities.isTypeSupported(newMimeType) ||
|
|
1955
2003
|
(!this.sequenceMode_ &&
|
|
@@ -1958,7 +2006,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1958
2006
|
}
|
|
1959
2007
|
const newMimeTypeWithAllCodecs =
|
|
1960
2008
|
shaka.util.MimeUtils.getFullTypeWithAllCodecs(
|
|
1961
|
-
|
|
2009
|
+
refMimeType, refCodecs);
|
|
1962
2010
|
const TransmuxerEngine = shaka.transmuxer.TransmuxerEngine;
|
|
1963
2011
|
if (needTransmux) {
|
|
1964
2012
|
const transmuxerPlugin =
|
|
@@ -1984,10 +2032,12 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1984
2032
|
*
|
|
1985
2033
|
* @param {shaka.util.ManifestParserUtils.ContentType} contentType
|
|
1986
2034
|
* @param {shaka.extern.Stream} stream
|
|
2035
|
+
* @param {string} mimeType
|
|
2036
|
+
* @param {string} codecs
|
|
1987
2037
|
* @return {boolean}
|
|
1988
2038
|
*/
|
|
1989
|
-
isResetMediaSourceNecessary(contentType, stream) {
|
|
1990
|
-
if (!this.isCodecSwitchNecessary_(contentType, stream)) {
|
|
2039
|
+
isResetMediaSourceNecessary(contentType, stream, mimeType, codecs) {
|
|
2040
|
+
if (!this.isCodecSwitchNecessary_(contentType, stream, mimeType, codecs)) {
|
|
1991
2041
|
return false;
|
|
1992
2042
|
}
|
|
1993
2043
|
|
package/lib/media/playhead.js
CHANGED
|
@@ -382,10 +382,10 @@ shaka.media.MediaSourcePlayhead = class {
|
|
|
382
382
|
seekStart = seekEnd - this.minSeekRange_;
|
|
383
383
|
}
|
|
384
384
|
|
|
385
|
-
if (currentTime < seekStart) {
|
|
386
|
-
//
|
|
385
|
+
if (currentTime < seekStart || currentTime > seekEnd) {
|
|
386
|
+
// playhead is outside of the seekrange. Move playhead to catch up.
|
|
387
387
|
const targetTime = this.reposition_(currentTime);
|
|
388
|
-
shaka.log.info('Jumping
|
|
388
|
+
shaka.log.info('Jumping by ' + (targetTime - currentTime) +
|
|
389
389
|
' seconds to catch up with the seek range.');
|
|
390
390
|
this.mediaElement_.currentTime = targetTime;
|
|
391
391
|
}
|
|
@@ -363,26 +363,27 @@ shaka.media.SegmentIndex = class {
|
|
|
363
363
|
|
|
364
364
|
// Adjust the last SegmentReference.
|
|
365
365
|
const lastReference = this.references[this.references.length - 1];
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
366
|
+
const newReference = new shaka.media.SegmentReference(
|
|
367
|
+
lastReference.startTime,
|
|
368
|
+
/* endTime= */ windowEnd,
|
|
369
|
+
lastReference.getUrisInner,
|
|
370
|
+
lastReference.startByte,
|
|
371
|
+
lastReference.endByte,
|
|
372
|
+
lastReference.initSegmentReference,
|
|
373
|
+
lastReference.timestampOffset,
|
|
374
|
+
lastReference.appendWindowStart,
|
|
375
|
+
lastReference.appendWindowEnd,
|
|
376
|
+
lastReference.partialReferences,
|
|
377
|
+
lastReference.tilesLayout,
|
|
378
|
+
lastReference.tileDuration,
|
|
379
|
+
lastReference.syncTime,
|
|
380
|
+
lastReference.status,
|
|
381
|
+
lastReference.aes128Key,
|
|
382
|
+
);
|
|
383
|
+
newReference.mimeType = lastReference.mimeType;
|
|
384
|
+
newReference.codecs = lastReference.codecs;
|
|
385
|
+
newReference.discontinuitySequence = lastReference.discontinuitySequence;
|
|
386
|
+
this.references[this.references.length - 1] = newReference;
|
|
386
387
|
}
|
|
387
388
|
|
|
388
389
|
|
|
@@ -881,7 +881,6 @@ shaka.media.StreamingEngine = class {
|
|
|
881
881
|
// The playhead might be seeking on startup, if a start time is set, so
|
|
882
882
|
// start "seeked" as true.
|
|
883
883
|
seeked: true,
|
|
884
|
-
needsResync: false,
|
|
885
884
|
recovering: false,
|
|
886
885
|
hasError: false,
|
|
887
886
|
operation: null,
|
|
@@ -1248,11 +1247,6 @@ shaka.media.StreamingEngine = class {
|
|
|
1248
1247
|
shaka.log.v1(
|
|
1249
1248
|
logPrefix, 'looking up segment from new stream endTime:', time);
|
|
1250
1249
|
|
|
1251
|
-
// Using a new iterator means we need to resync the stream in sequence
|
|
1252
|
-
// mode. The buffered range might not align perfectly with the last
|
|
1253
|
-
// segment end time, so we may end up repeating a segment. Resyncing
|
|
1254
|
-
// makes this safe to do.
|
|
1255
|
-
mediaState.needsResync = true;
|
|
1256
1250
|
mediaState.segmentIterator =
|
|
1257
1251
|
mediaState.stream.segmentIndex.getIteratorForTime(time);
|
|
1258
1252
|
const ref = mediaState.segmentIterator &&
|
|
@@ -1730,7 +1724,7 @@ shaka.media.StreamingEngine = class {
|
|
|
1730
1724
|
const isResetMediaSourceNecessary =
|
|
1731
1725
|
mediaState.lastCodecs && mediaState.lastMimeType &&
|
|
1732
1726
|
this.playerInterface_.mediaSourceEngine.isResetMediaSourceNecessary(
|
|
1733
|
-
mediaState.type, mediaState.stream);
|
|
1727
|
+
mediaState.type, mediaState.stream, mimeType, codecs);
|
|
1734
1728
|
if (isResetMediaSourceNecessary) {
|
|
1735
1729
|
let otherState = null;
|
|
1736
1730
|
if (mediaState.type === ContentType.VIDEO) {
|
|
@@ -1879,9 +1873,7 @@ shaka.media.StreamingEngine = class {
|
|
|
1879
1873
|
// Across discontinuity bounds, we should resync timestamps for
|
|
1880
1874
|
// sequence mode playbacks. The next segment appended should
|
|
1881
1875
|
// land at its theoretical timestamp from the segment index.
|
|
1882
|
-
if (reference.discontinuitySequence != lastDiscontinuitySequence
|
|
1883
|
-
mediaState.needsResync) {
|
|
1884
|
-
mediaState.needsResync = false;
|
|
1876
|
+
if (reference.discontinuitySequence != lastDiscontinuitySequence) {
|
|
1885
1877
|
operations.push(this.playerInterface_.mediaSourceEngine.resync(
|
|
1886
1878
|
mediaState.type, reference.startTime));
|
|
1887
1879
|
}
|
|
@@ -2591,7 +2583,6 @@ shaka.media.StreamingEngine.PlayerInterface;
|
|
|
2591
2583
|
* clearBufferSafeMargin: number,
|
|
2592
2584
|
* clearingBuffer: boolean,
|
|
2593
2585
|
* seeked: boolean,
|
|
2594
|
-
* needsResync: boolean,
|
|
2595
2586
|
* adaptation: boolean,
|
|
2596
2587
|
* recovering: boolean,
|
|
2597
2588
|
* hasError: boolean,
|
|
@@ -2646,9 +2637,6 @@ shaka.media.StreamingEngine.PlayerInterface;
|
|
|
2646
2637
|
* True indicates that the presentation just seeked.
|
|
2647
2638
|
* @property {boolean} adaptation
|
|
2648
2639
|
* True indicates that the presentation just automatically switched variants.
|
|
2649
|
-
* @property {boolean} needsResync
|
|
2650
|
-
* True indicates that the stream needs to be resynced in sequence mode,
|
|
2651
|
-
* regardless of discontinuity sequence.
|
|
2652
2640
|
* @property {boolean} recovering
|
|
2653
2641
|
* True indicates that the last segment was not appended because it could not
|
|
2654
2642
|
* fit in the buffer.
|