shaka-player 3.2.2 → 3.3.2
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/ISSUE_TEMPLATE/bug_report.md +1 -1
- package/.github/ISSUE_TEMPLATE/feature_request.md +1 -1
- package/.github/ISSUE_TEMPLATE/question.md +1 -1
- package/.github/workflows/build_and_test.yaml +73 -0
- package/.github/workflows/release.yaml +53 -0
- package/AUTHORS +6 -5
- package/CHANGELOG.md +314 -1
- package/CONTRIBUTORS +4 -2
- package/build/checkversion.py +1 -1
- package/build/conformance.textproto +183 -169
- package/build/test.py +6 -0
- package/build/types/core +3 -0
- package/build/types/offline +1 -0
- package/build/types/polyfill +1 -0
- package/build/types/ui +2 -0
- package/demo/common/assets.js +18 -0
- package/demo/common/message_ids.js +13 -1
- package/demo/config.js +31 -1
- package/demo/index.html +1 -1
- package/demo/locales/en.json +12 -0
- package/demo/locales/source.json +48 -0
- package/dist/controls.css +26 -2
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +19 -16
- package/dist/demo.compiled.debug.map +3 -3
- package/dist/demo.compiled.js +19 -16
- package/dist/demo.compiled.map +3 -3
- package/dist/deps.js +21 -14
- package/dist/locales.js +31 -29
- package/dist/receiver.compiled.debug.js +11 -9
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +11 -9
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.d.ts +232 -18
- package/dist/shaka-player.compiled.debug.d.ts +232 -18
- package/dist/shaka-player.compiled.debug.externs.js +293 -17
- package/dist/shaka-player.compiled.debug.js +481 -422
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +293 -17
- package/dist/shaka-player.compiled.js +846 -817
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +250 -30
- package/dist/shaka-player.ui.debug.d.ts +250 -30
- package/dist/shaka-player.ui.debug.externs.js +322 -28
- package/dist/shaka-player.ui.debug.js +630 -553
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +322 -28
- package/dist/shaka-player.ui.js +1048 -1006
- package/dist/shaka-player.ui.map +4 -4
- package/docs/design/bg-fetch-after.gv +29 -0
- package/docs/design/bg-fetch-after.gv.png +0 -0
- package/docs/design/bg-fetch-before.gv +18 -0
- package/docs/design/bg-fetch-before.gv.png +0 -0
- package/docs/design/bg-fetch.md +134 -0
- package/docs/tutorials/blob-url.md +15 -0
- package/docs/tutorials/index.json +1 -0
- package/docs/tutorials/ui-customization.md +66 -0
- package/docs/tutorials/ui.md +5 -5
- package/externs/cmcd.js +186 -0
- package/externs/ima.js +3 -0
- package/externs/shaka/ads.js +5 -0
- package/externs/shaka/manifest.js +12 -1
- package/externs/shaka/manifest_parser.js +10 -1
- package/externs/shaka/net.js +20 -4
- package/externs/shaka/offline.js +31 -2
- package/externs/shaka/player.js +138 -5
- package/externs/shaka/text.js +24 -0
- package/externs/webcrypto.js +18 -0
- package/karma.conf.js +19 -15
- package/lib/abr/ewma.js +14 -0
- package/lib/abr/ewma_bandwidth_estimator.js +16 -2
- package/lib/abr/simple_abr_manager.js +6 -0
- package/lib/ads/ad_manager.js +1 -0
- package/lib/ads/client_side_ad.js +8 -0
- package/lib/ads/client_side_ad_manager.js +8 -4
- package/lib/ads/server_side_ad.js +7 -0
- package/lib/cast/cast_proxy.js +3 -0
- package/lib/cast/cast_receiver.js +3 -0
- package/lib/cast/cast_utils.js +1 -0
- package/lib/dash/dash_parser.js +79 -33
- package/lib/dash/segment_base.js +25 -1
- package/lib/dash/segment_list.js +18 -9
- package/lib/dash/segment_template.js +23 -10
- package/lib/hls/hls_parser.js +116 -23
- package/lib/hls/manifest_text_parser.js +1 -0
- package/lib/media/quality_observer.js +274 -0
- package/lib/media/region_observer.js +39 -33
- package/lib/media/region_timeline.js +17 -19
- package/lib/media/segment_index.js +8 -1
- package/lib/media/segment_reference.js +37 -4
- package/lib/media/streaming_engine.js +47 -6
- package/lib/net/http_fetch_plugin.js +31 -11
- package/lib/net/http_plugin_utils.js +1 -0
- package/lib/net/http_xhr_plugin.js +40 -14
- package/lib/net/networking_engine.js +85 -18
- package/lib/offline/download_info.js +68 -0
- package/lib/offline/download_manager.js +13 -5
- package/lib/offline/indexeddb/base_storage_cell.js +35 -0
- package/lib/offline/indexeddb/storage_mechanism.js +1 -1
- package/lib/offline/indexeddb/v5_storage_cell.js +5 -0
- package/lib/offline/storage.js +401 -293
- package/lib/offline/stored_content_utils.js +2 -0
- package/lib/player.js +254 -27
- package/lib/polyfill/media_capabilities.js +30 -15
- package/lib/polyfill/random_uuid.js +52 -0
- package/lib/text/cue.js +18 -0
- package/lib/text/ttml_text_parser.js +109 -60
- package/lib/text/ui_text_displayer.js +19 -13
- package/lib/util/cmcd_manager.js +672 -0
- package/lib/util/error.js +6 -0
- package/lib/util/fake_event_target.js +21 -1
- package/lib/util/language_utils.js +12 -0
- package/lib/util/mutex.js +52 -0
- package/lib/util/periods.js +98 -64
- package/lib/util/player_configuration.js +18 -0
- package/lib/util/stream_utils.js +86 -10
- package/lib/util/xml_utils.js +19 -0
- package/package.json +3 -6
- package/shaka-player.uncompiled.js +3 -0
- package/test/dash/dash_parser_content_protection_unit.js +2 -0
- package/test/dash/dash_parser_live_unit.js +144 -1
- package/test/dash/dash_parser_manifest_unit.js +37 -2
- package/test/dash/dash_parser_segment_base_unit.js +2 -0
- package/test/dash/dash_parser_segment_list_unit.js +2 -1
- package/test/dash/dash_parser_segment_template_unit.js +2 -1
- package/test/hls/hls_live_unit.js +2 -0
- package/test/hls/hls_parser_unit.js +76 -0
- package/test/media/drm_engine_unit.js +3 -3
- package/test/media/quality_observer_unit.js +142 -0
- package/test/media/region_observer_unit.js +40 -5
- package/test/media/region_timeline_unit.js +40 -22
- package/test/media/segment_reference_unit.js +16 -1
- package/test/media/streaming_engine_integration.js +4 -2
- package/test/media/streaming_engine_unit.js +147 -0
- package/test/net/http_plugin_unit.js +20 -15
- package/test/offline/storage_integration.js +108 -4
- package/test/player_integration.js +140 -8
- package/test/player_src_equals_integration.js +41 -8
- package/test/player_unit.js +19 -9
- package/test/test/assets/chapters.vtt +2 -2
- package/test/test/assets/chapters2.vtt +10 -0
- package/test/test/util/dash_parser_util.js +4 -0
- package/test/test/util/fake_ad.js +7 -0
- package/test/test/util/fake_drm_engine.js +9 -2
- package/test/test/util/manifest_generator.js +3 -2
- package/test/test/util/test_scheme.js +14 -1
- package/test/test/util/ttml_utils.js +81 -0
- package/test/test/util/util.js +10 -7
- package/test/text/mp4_ttml_parser_unit.js +11 -18
- package/test/text/ttml_text_parser_unit.js +544 -228
- package/test/ui/text_displayer_layout_unit.js +8 -7
- package/test/ui/ui_unit.js +250 -0
- package/test/util/cmcd_manager_unit.js +291 -0
- package/test/util/stream_utils_unit.js +36 -30
- package/third_party/closure-uri/uri.js +21 -0
- package/ui/airplay_button.js +1 -0
- package/ui/audio_language_selection.js +7 -0
- package/ui/cast_button.js +1 -0
- package/ui/context_menu.js +109 -0
- package/ui/controls.js +44 -7
- package/ui/controls.less +1 -0
- package/ui/enums.js +4 -0
- package/ui/externs/ui.js +28 -1
- package/ui/fast_forward_button.js +14 -5
- package/ui/fullscreen_button.js +1 -0
- package/ui/less/buttons.less +0 -4
- package/ui/less/containers.less +74 -0
- package/ui/less/overflow_menu.less +0 -10
- package/ui/less/tooltip.less +97 -0
- package/ui/locales/en.json +1 -0
- package/ui/locales/source.json +4 -0
- package/ui/localization.js +12 -36
- package/ui/loop_button.js +5 -0
- package/ui/mute_button.js +2 -1
- package/ui/overflow_menu.js +5 -25
- package/ui/pip_button.js +5 -0
- package/ui/play_button.js +2 -2
- package/ui/playback_rate_selection.js +8 -9
- package/ui/resolution_selection.js +7 -0
- package/ui/rewind_button.js +15 -6
- package/ui/seek_bar.js +4 -2
- package/ui/settings_menu.js +36 -4
- package/ui/small_play_button.js +1 -0
- package/ui/statistics_button.js +253 -0
- package/ui/text_selection.js +12 -4
- package/ui/ui.js +30 -0
- package/ui/volume_bar.js +1 -1
- package/externs/media_capabilities.js +0 -16
package/lib/dash/dash_parser.js
CHANGED
|
@@ -19,6 +19,7 @@ goog.require('shaka.media.PresentationTimeline');
|
|
|
19
19
|
goog.require('shaka.media.SegmentIndex');
|
|
20
20
|
goog.require('shaka.net.NetworkingEngine');
|
|
21
21
|
goog.require('shaka.text.TextEngine');
|
|
22
|
+
goog.require('shaka.util.CmcdManager');
|
|
22
23
|
goog.require('shaka.util.Error');
|
|
23
24
|
goog.require('shaka.util.Functional');
|
|
24
25
|
goog.require('shaka.util.Iterables');
|
|
@@ -58,12 +59,12 @@ shaka.dash.DashParser = class {
|
|
|
58
59
|
this.globalId_ = 1;
|
|
59
60
|
|
|
60
61
|
/**
|
|
61
|
-
* A map of IDs to
|
|
62
|
+
* A map of IDs to Stream objects.
|
|
62
63
|
* ID: Period@id,AdaptationSet@id,@Representation@id
|
|
63
64
|
* e.g.: '1,5,23'
|
|
64
|
-
* @private {!Object.<string, !shaka.
|
|
65
|
+
* @private {!Object.<string, !shaka.extern.Stream>}
|
|
65
66
|
*/
|
|
66
|
-
this.
|
|
67
|
+
this.streamMap_ = {};
|
|
67
68
|
|
|
68
69
|
/**
|
|
69
70
|
* A map of period ids to their durations
|
|
@@ -164,8 +165,10 @@ shaka.dash.DashParser = class {
|
|
|
164
165
|
stop() {
|
|
165
166
|
// When the parser stops, release all segment indexes, which stops their
|
|
166
167
|
// timers, as well.
|
|
167
|
-
for (const
|
|
168
|
-
segmentIndex
|
|
168
|
+
for (const stream of Object.values(this.streamMap_)) {
|
|
169
|
+
if (stream.segmentIndex) {
|
|
170
|
+
stream.segmentIndex.release();
|
|
171
|
+
}
|
|
169
172
|
}
|
|
170
173
|
|
|
171
174
|
if (this.periodCombiner_) {
|
|
@@ -176,7 +179,7 @@ shaka.dash.DashParser = class {
|
|
|
176
179
|
this.config_ = null;
|
|
177
180
|
this.manifestUris_ = [];
|
|
178
181
|
this.manifest_ = null;
|
|
179
|
-
this.
|
|
182
|
+
this.streamMap_ = {};
|
|
180
183
|
this.periodCombiner_ = null;
|
|
181
184
|
|
|
182
185
|
if (this.updateTimer_ != null) {
|
|
@@ -224,6 +227,9 @@ shaka.dash.DashParser = class {
|
|
|
224
227
|
this.manifestUris_, this.config_.retryParameters);
|
|
225
228
|
const networkingEngine = this.playerInterface_.networkingEngine;
|
|
226
229
|
|
|
230
|
+
const format = shaka.util.CmcdManager.StreamingFormat.DASH;
|
|
231
|
+
this.playerInterface_.modifyManifestRequest(request, {format: format});
|
|
232
|
+
|
|
227
233
|
const startTime = Date.now();
|
|
228
234
|
const operation = networkingEngine.request(requestType, request);
|
|
229
235
|
this.operationManager_.manage(operation);
|
|
@@ -378,8 +384,11 @@ shaka.dash.DashParser = class {
|
|
|
378
384
|
// that the complex logic of multi-Period eviction and period-flattening
|
|
379
385
|
// is correct. See also:
|
|
380
386
|
// https://github.com/google/shaka-player/issues/3169#issuecomment-823580634
|
|
381
|
-
for (const
|
|
382
|
-
|
|
387
|
+
for (const stream of Object.values(this.streamMap_)) {
|
|
388
|
+
if (stream.segmentIndex) {
|
|
389
|
+
stream.segmentIndex.evict(
|
|
390
|
+
presentationTimeline.getSegmentAvailabilityStart());
|
|
391
|
+
}
|
|
383
392
|
}
|
|
384
393
|
} else {
|
|
385
394
|
// DASH IOP v3.0 suggests using a default delay between minBufferTime
|
|
@@ -401,6 +410,24 @@ shaka.dash.DashParser = class {
|
|
|
401
410
|
this.config_.dash.autoCorrectDrift);
|
|
402
411
|
}
|
|
403
412
|
|
|
413
|
+
presentationTimeline.setStatic(mpdType == 'static');
|
|
414
|
+
|
|
415
|
+
const isLive = presentationTimeline.isLive();
|
|
416
|
+
|
|
417
|
+
// If it's live, we check for an override.
|
|
418
|
+
if (isLive && !isNaN(this.config_.availabilityWindowOverride)) {
|
|
419
|
+
segmentAvailabilityDuration = this.config_.availabilityWindowOverride;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// If it's null, that means segments are always available. This is always
|
|
423
|
+
// the case for VOD, and sometimes the case for live.
|
|
424
|
+
if (segmentAvailabilityDuration == null) {
|
|
425
|
+
segmentAvailabilityDuration = Infinity;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
presentationTimeline.setSegmentAvailabilityDuration(
|
|
429
|
+
segmentAvailabilityDuration);
|
|
430
|
+
|
|
404
431
|
const profiles = mpd.getAttribute('profiles') || '';
|
|
405
432
|
|
|
406
433
|
/** @type {shaka.dash.DashParser.Context} */
|
|
@@ -423,7 +450,6 @@ shaka.dash.DashParser = class {
|
|
|
423
450
|
const duration = periodsAndDuration.duration;
|
|
424
451
|
const periods = periodsAndDuration.periods;
|
|
425
452
|
|
|
426
|
-
presentationTimeline.setStatic(mpdType == 'static');
|
|
427
453
|
if (mpdType == 'static' ||
|
|
428
454
|
!periodsAndDuration.durationDerivedFromPeriods) {
|
|
429
455
|
// Ignore duration calculated from Period lengths if this is dynamic.
|
|
@@ -442,6 +468,7 @@ shaka.dash.DashParser = class {
|
|
|
442
468
|
this.lowLatencyMode_ = this.playerInterface_.isLowLatencyMode();
|
|
443
469
|
}
|
|
444
470
|
}
|
|
471
|
+
|
|
445
472
|
if (this.lowLatencyMode_) {
|
|
446
473
|
presentationTimeline.setAvailabilityTimeOffset(
|
|
447
474
|
this.minTotalAvailabilityTimeOffset_);
|
|
@@ -455,22 +482,6 @@ shaka.dash.DashParser = class {
|
|
|
455
482
|
'https://bit.ly/3clctcj for details.');
|
|
456
483
|
}
|
|
457
484
|
|
|
458
|
-
const isLive = presentationTimeline.isLive();
|
|
459
|
-
|
|
460
|
-
// If it's live, we check for an override.
|
|
461
|
-
if (isLive && !isNaN(this.config_.availabilityWindowOverride)) {
|
|
462
|
-
segmentAvailabilityDuration = this.config_.availabilityWindowOverride;
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
// If it's null, that means segments are always available. This is always
|
|
466
|
-
// the case for VOD, and sometimes the case for live.
|
|
467
|
-
if (segmentAvailabilityDuration == null) {
|
|
468
|
-
segmentAvailabilityDuration = Infinity;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
presentationTimeline.setSegmentAvailabilityDuration(
|
|
472
|
-
segmentAvailabilityDuration);
|
|
473
|
-
|
|
474
485
|
// Use @maxSegmentDuration to override smaller, derived values.
|
|
475
486
|
presentationTimeline.notifyMaxSegmentDuration(maxSegmentDuration || 1);
|
|
476
487
|
if (goog.DEBUG) {
|
|
@@ -705,8 +716,12 @@ shaka.dash.DashParser = class {
|
|
|
705
716
|
|
|
706
717
|
const eventStreamNodes =
|
|
707
718
|
XmlUtils.findChildren(periodInfo.node, 'EventStream');
|
|
719
|
+
const availabilityStart =
|
|
720
|
+
context.presentationTimeline.getSegmentAvailabilityStart();
|
|
721
|
+
|
|
708
722
|
for (const node of eventStreamNodes) {
|
|
709
|
-
this.parseEventStream_(
|
|
723
|
+
this.parseEventStream_(
|
|
724
|
+
periodInfo.start, periodInfo.duration, node, availabilityStart);
|
|
710
725
|
}
|
|
711
726
|
|
|
712
727
|
const adaptationSetNodes =
|
|
@@ -1163,11 +1178,12 @@ shaka.dash.DashParser = class {
|
|
|
1163
1178
|
context, requestInitSegment);
|
|
1164
1179
|
} else if (context.representation.segmentList) {
|
|
1165
1180
|
streamInfo = shaka.dash.SegmentList.createStreamInfo(
|
|
1166
|
-
context, this.
|
|
1181
|
+
context, this.streamMap_);
|
|
1167
1182
|
} else if (context.representation.segmentTemplate) {
|
|
1168
1183
|
const hasManifest = !!this.manifest_;
|
|
1184
|
+
|
|
1169
1185
|
streamInfo = shaka.dash.SegmentTemplate.createStreamInfo(
|
|
1170
|
-
context, requestInitSegment, this.
|
|
1186
|
+
context, requestInitSegment, this.streamMap_, hasManifest,
|
|
1171
1187
|
this.config_.dash.initialSegmentLimit, this.periodDurations_);
|
|
1172
1188
|
} else {
|
|
1173
1189
|
goog.asserts.assert(isText,
|
|
@@ -1220,8 +1236,10 @@ shaka.dash.DashParser = class {
|
|
|
1220
1236
|
|
|
1221
1237
|
let forced = false;
|
|
1222
1238
|
if (isText) {
|
|
1223
|
-
// See: https://github.com/google/shaka-player/issues/2122
|
|
1224
|
-
|
|
1239
|
+
// See: https://github.com/google/shaka-player/issues/2122 and
|
|
1240
|
+
// https://github.com/Dash-Industry-Forum/DASH-IF-IOP/issues/165
|
|
1241
|
+
forced = roles.includes('forced_subtitle') ||
|
|
1242
|
+
roles.includes('forced-subtitle');
|
|
1225
1243
|
}
|
|
1226
1244
|
|
|
1227
1245
|
let tilesLayout;
|
|
@@ -1254,13 +1272,29 @@ shaka.dash.DashParser = class {
|
|
|
1254
1272
|
hdr = 'PQ';
|
|
1255
1273
|
}
|
|
1256
1274
|
|
|
1275
|
+
const contextId = context.representation.id ?
|
|
1276
|
+
context.period.id + ',' + context.representation.id : '';
|
|
1277
|
+
|
|
1257
1278
|
/** @type {shaka.extern.Stream} */
|
|
1258
1279
|
const stream = {
|
|
1259
1280
|
id: this.globalId_++,
|
|
1260
1281
|
originalId: context.representation.id,
|
|
1261
1282
|
createSegmentIndex: async () => {
|
|
1262
|
-
|
|
1263
|
-
|
|
1283
|
+
// If we have a stream with the same context id stored in the map
|
|
1284
|
+
// that has no segmentIndex, we should set the segmentIndex for it.
|
|
1285
|
+
const storedInMap = contextId && context.dynamic &&
|
|
1286
|
+
this.streamMap_[contextId];
|
|
1287
|
+
|
|
1288
|
+
const currentStream = storedInMap ? this.streamMap_[contextId] : stream;
|
|
1289
|
+
if (!currentStream.segmentIndex) {
|
|
1290
|
+
currentStream.segmentIndex = await streamInfo.generateSegmentIndex();
|
|
1291
|
+
}
|
|
1292
|
+
},
|
|
1293
|
+
|
|
1294
|
+
closeSegmentIndex: () => {
|
|
1295
|
+
if (stream.segmentIndex) {
|
|
1296
|
+
stream.segmentIndex.release();
|
|
1297
|
+
stream.segmentIndex = null;
|
|
1264
1298
|
}
|
|
1265
1299
|
},
|
|
1266
1300
|
segmentIndex: null,
|
|
@@ -1290,7 +1324,13 @@ shaka.dash.DashParser = class {
|
|
|
1290
1324
|
closedCaptions,
|
|
1291
1325
|
hdr,
|
|
1292
1326
|
tilesLayout,
|
|
1327
|
+
matchedStreams: [],
|
|
1293
1328
|
};
|
|
1329
|
+
|
|
1330
|
+
if (contextId && context.dynamic && !this.streamMap_[contextId]) {
|
|
1331
|
+
this.streamMap_[contextId] = stream;
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1294
1334
|
return stream;
|
|
1295
1335
|
}
|
|
1296
1336
|
|
|
@@ -1735,9 +1775,10 @@ shaka.dash.DashParser = class {
|
|
|
1735
1775
|
* @param {number} periodStart
|
|
1736
1776
|
* @param {?number} periodDuration
|
|
1737
1777
|
* @param {!Element} elem
|
|
1778
|
+
* @param {number} availabilityStart
|
|
1738
1779
|
* @private
|
|
1739
1780
|
*/
|
|
1740
|
-
parseEventStream_(periodStart, periodDuration, elem) {
|
|
1781
|
+
parseEventStream_(periodStart, periodDuration, elem, availabilityStart) {
|
|
1741
1782
|
const XmlUtils = shaka.util.XmlUtils;
|
|
1742
1783
|
const parseNumber = XmlUtils.parseNonNegativeInt;
|
|
1743
1784
|
|
|
@@ -1760,6 +1801,11 @@ shaka.dash.DashParser = class {
|
|
|
1760
1801
|
endTime = Math.min(endTime, periodStart + periodDuration);
|
|
1761
1802
|
}
|
|
1762
1803
|
|
|
1804
|
+
// Don't add unavailable regions to the timeline.
|
|
1805
|
+
if (endTime < availabilityStart) {
|
|
1806
|
+
continue;
|
|
1807
|
+
}
|
|
1808
|
+
|
|
1763
1809
|
/** @type {shaka.extern.TimelineRegionInfo} */
|
|
1764
1810
|
const region = {
|
|
1765
1811
|
schemeIdUri: schemeIdUri,
|
package/lib/dash/segment_base.js
CHANGED
|
@@ -61,7 +61,9 @@ shaka.dash.SegmentBase = class {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
const getUris = () => resolvedUris;
|
|
64
|
-
|
|
64
|
+
const qualityInfo = shaka.dash.SegmentBase.createQualityInfo(context);
|
|
65
|
+
return new shaka.media.InitSegmentReference(
|
|
66
|
+
getUris, startByte, endByte, qualityInfo);
|
|
65
67
|
}
|
|
66
68
|
|
|
67
69
|
/**
|
|
@@ -346,4 +348,26 @@ shaka.dash.SegmentBase = class {
|
|
|
346
348
|
indexRange.start, indexRange.end,
|
|
347
349
|
scaledPresentationTimeOffset);
|
|
348
350
|
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Create a MediaQualityInfo object from a Context object.
|
|
354
|
+
*
|
|
355
|
+
* @param {!shaka.dash.DashParser.Context} context
|
|
356
|
+
* @return {!shaka.extern.MediaQualityInfo}
|
|
357
|
+
*/
|
|
358
|
+
static createQualityInfo(context) {
|
|
359
|
+
const representation = context.representation;
|
|
360
|
+
return {
|
|
361
|
+
bandwidth: context.bandwidth,
|
|
362
|
+
audioSamplingRate: representation.audioSamplingRate,
|
|
363
|
+
codecs: representation.codecs,
|
|
364
|
+
contentType: representation.contentType,
|
|
365
|
+
frameRate: representation.frameRate || null,
|
|
366
|
+
height: representation.height || null,
|
|
367
|
+
mimeType: representation.mimeType,
|
|
368
|
+
channelsCount: representation.numChannels,
|
|
369
|
+
pixelAspectRatio: representation.pixelAspectRatio || null,
|
|
370
|
+
width: representation.width || null,
|
|
371
|
+
};
|
|
372
|
+
}
|
|
349
373
|
};
|
package/lib/dash/segment_list.js
CHANGED
|
@@ -30,10 +30,10 @@ shaka.dash.SegmentList = class {
|
|
|
30
30
|
* Updates the existing SegmentIndex, if any.
|
|
31
31
|
*
|
|
32
32
|
* @param {shaka.dash.DashParser.Context} context
|
|
33
|
-
* @param {!Object.<string, !shaka.
|
|
33
|
+
* @param {!Object.<string, !shaka.extern.Stream>} streamMap
|
|
34
34
|
* @return {shaka.dash.DashParser.StreamInfo}
|
|
35
35
|
*/
|
|
36
|
-
static createStreamInfo(context,
|
|
36
|
+
static createStreamInfo(context, streamMap) {
|
|
37
37
|
goog.asserts.assert(context.representation.segmentList,
|
|
38
38
|
'Should only be called with SegmentList');
|
|
39
39
|
const SegmentList = shaka.dash.SegmentList;
|
|
@@ -46,11 +46,14 @@ shaka.dash.SegmentList = class {
|
|
|
46
46
|
|
|
47
47
|
/** @type {shaka.media.SegmentIndex} */
|
|
48
48
|
let segmentIndex = null;
|
|
49
|
-
let
|
|
49
|
+
let stream = null;
|
|
50
50
|
if (context.period.id && context.representation.id) {
|
|
51
51
|
// Only check/store the index if period and representation IDs are set.
|
|
52
|
-
id = context.period.id + ',' + context.representation.id;
|
|
53
|
-
|
|
52
|
+
const id = context.period.id + ',' + context.representation.id;
|
|
53
|
+
stream = streamMap[id];
|
|
54
|
+
if (stream) {
|
|
55
|
+
segmentIndex = stream.segmentIndex;
|
|
56
|
+
}
|
|
54
57
|
}
|
|
55
58
|
|
|
56
59
|
const references = SegmentList.createSegmentReferences_(
|
|
@@ -64,9 +67,6 @@ shaka.dash.SegmentList = class {
|
|
|
64
67
|
segmentIndex.mergeAndEvict(references, start);
|
|
65
68
|
} else {
|
|
66
69
|
segmentIndex = new shaka.media.SegmentIndex(references);
|
|
67
|
-
if (id && context.dynamic) {
|
|
68
|
-
segmentIndexMap[id] = segmentIndex;
|
|
69
|
-
}
|
|
70
70
|
}
|
|
71
71
|
context.presentationTimeline.notifySegments(references);
|
|
72
72
|
|
|
@@ -77,8 +77,17 @@ shaka.dash.SegmentList = class {
|
|
|
77
77
|
segmentIndex.fit(periodStart, periodEnd, isNew);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
if (stream) {
|
|
81
|
+
stream.segmentIndex = segmentIndex;
|
|
82
|
+
}
|
|
83
|
+
|
|
80
84
|
return {
|
|
81
|
-
generateSegmentIndex: () =>
|
|
85
|
+
generateSegmentIndex: () => {
|
|
86
|
+
if (!segmentIndex || segmentIndex.isEmpty()) {
|
|
87
|
+
segmentIndex.merge(references);
|
|
88
|
+
}
|
|
89
|
+
return Promise.resolve(segmentIndex);
|
|
90
|
+
},
|
|
82
91
|
};
|
|
83
92
|
}
|
|
84
93
|
|
|
@@ -31,7 +31,7 @@ shaka.dash.SegmentTemplate = class {
|
|
|
31
31
|
* @param {shaka.dash.DashParser.Context} context
|
|
32
32
|
* @param {shaka.dash.DashParser.RequestInitSegmentCallback}
|
|
33
33
|
* requestInitSegment
|
|
34
|
-
* @param {!Object.<string, !shaka.
|
|
34
|
+
* @param {!Object.<string, !shaka.extern.Stream>} streamMap
|
|
35
35
|
* @param {boolean} isUpdate True if the manifest is being updated.
|
|
36
36
|
* @param {number} segmentLimit The maximum number of segments to generate for
|
|
37
37
|
* a SegmentTemplate with fixed duration.
|
|
@@ -39,8 +39,8 @@ shaka.dash.SegmentTemplate = class {
|
|
|
39
39
|
* @return {shaka.dash.DashParser.StreamInfo}
|
|
40
40
|
*/
|
|
41
41
|
static createStreamInfo(
|
|
42
|
-
context, requestInitSegment,
|
|
43
|
-
|
|
42
|
+
context, requestInitSegment, streamMap, isUpdate, segmentLimit,
|
|
43
|
+
periodDurationMap) {
|
|
44
44
|
goog.asserts.assert(context.representation.segmentTemplate,
|
|
45
45
|
'Should only be called with SegmentTemplate');
|
|
46
46
|
const SegmentTemplate = shaka.dash.SegmentTemplate;
|
|
@@ -86,10 +86,14 @@ shaka.dash.SegmentTemplate = class {
|
|
|
86
86
|
/** @type {shaka.media.SegmentIndex} */
|
|
87
87
|
let segmentIndex = null;
|
|
88
88
|
let id = null;
|
|
89
|
+
let stream = null;
|
|
89
90
|
if (context.period.id && context.representation.id) {
|
|
90
91
|
// Only check/store the index if period and representation IDs are set.
|
|
91
92
|
id = context.period.id + ',' + context.representation.id;
|
|
92
|
-
|
|
93
|
+
stream = streamMap[id];
|
|
94
|
+
if (stream) {
|
|
95
|
+
segmentIndex = stream.segmentIndex;
|
|
96
|
+
}
|
|
93
97
|
}
|
|
94
98
|
|
|
95
99
|
const references = SegmentTemplate.createFromTimeline_(
|
|
@@ -117,9 +121,6 @@ shaka.dash.SegmentTemplate = class {
|
|
|
117
121
|
context.presentationTimeline.getSegmentAvailabilityStart());
|
|
118
122
|
} else {
|
|
119
123
|
segmentIndex = new shaka.media.SegmentIndex(references);
|
|
120
|
-
if (id && context.dynamic) {
|
|
121
|
-
segmentIndexMap[id] = segmentIndex;
|
|
122
|
-
}
|
|
123
124
|
}
|
|
124
125
|
context.presentationTimeline.notifySegments(references);
|
|
125
126
|
|
|
@@ -127,8 +128,20 @@ shaka.dash.SegmentTemplate = class {
|
|
|
127
128
|
segmentIndex.fit(periodStart, periodEnd);
|
|
128
129
|
}
|
|
129
130
|
|
|
131
|
+
if (stream && context.dynamic) {
|
|
132
|
+
stream.segmentIndex = segmentIndex;
|
|
133
|
+
}
|
|
134
|
+
|
|
130
135
|
return {
|
|
131
|
-
generateSegmentIndex: () =>
|
|
136
|
+
generateSegmentIndex: () => {
|
|
137
|
+
// If segmentIndex is deleted, or segmentIndex's references are
|
|
138
|
+
// released by closeSegmentIndex(), we should set the value of
|
|
139
|
+
// segmentIndex again.
|
|
140
|
+
if (!segmentIndex || segmentIndex.isEmpty()) {
|
|
141
|
+
segmentIndex.merge(references);
|
|
142
|
+
}
|
|
143
|
+
return Promise.resolve(segmentIndex);
|
|
144
|
+
},
|
|
132
145
|
};
|
|
133
146
|
}
|
|
134
147
|
}
|
|
@@ -569,8 +582,8 @@ shaka.dash.SegmentTemplate = class {
|
|
|
569
582
|
baseUris, [filledTemplate]);
|
|
570
583
|
return resolvedUris;
|
|
571
584
|
};
|
|
572
|
-
|
|
573
|
-
return new shaka.media.InitSegmentReference(getUris, 0, null);
|
|
585
|
+
const qualityInfo = shaka.dash.SegmentBase.createQualityInfo(context);
|
|
586
|
+
return new shaka.media.InitSegmentReference(getUris, 0, null, qualityInfo);
|
|
574
587
|
}
|
|
575
588
|
};
|
|
576
589
|
|