shaka-player 3.1.4 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/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/AUTHORS +6 -5
- package/CHANGELOG.md +363 -0
- package/CONTRIBUTORS +4 -2
- package/README.md +4 -4
- package/build/types/core +3 -0
- package/build/types/offline +1 -0
- package/build/types/polyfill +2 -0
- package/build/types/ui +2 -0
- package/demo/common/asset.js +9 -7
- package/demo/common/assets.js +28 -1
- package/demo/common/message_ids.js +15 -2
- package/demo/config.js +35 -2
- package/demo/index.html +1 -1
- package/demo/locales/en.json +14 -1
- package/demo/locales/source.json +56 -4
- package/demo/main.js +2 -1
- package/dist/controls.css +26 -2
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +24 -21
- package/dist/demo.compiled.debug.map +3 -3
- package/dist/demo.compiled.js +24 -21
- package/dist/demo.compiled.map +3 -3
- package/dist/deps.js +33 -25
- package/dist/locales.js +31 -29
- package/dist/receiver.compiled.debug.js +14 -12
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +14 -12
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.d.ts +258 -20
- package/dist/shaka-player.compiled.debug.d.ts +258 -20
- package/dist/shaka-player.compiled.debug.externs.js +1005 -695
- package/dist/shaka-player.compiled.debug.js +720 -640
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +1005 -695
- package/dist/shaka-player.compiled.js +850 -817
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +274 -21
- package/dist/shaka-player.ui.debug.d.ts +274 -21
- package/dist/shaka-player.ui.debug.externs.js +766 -429
- package/dist/shaka-player.ui.debug.js +863 -765
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +766 -429
- package/dist/shaka-player.ui.js +1042 -996
- 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/aria.js +6 -0
- package/externs/ima.js +3 -0
- package/externs/shaka/ads.js +29 -1
- package/externs/shaka/manifest.js +18 -2
- package/externs/shaka/manifest_parser.js +10 -1
- package/externs/shaka/net.js +20 -4
- package/externs/shaka/offline.js +36 -2
- package/externs/shaka/player.js +182 -13
- package/externs/shaka/text.js +24 -10
- package/externs/texttrack.js +3 -0
- package/externs/webcrypto.js +18 -0
- 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 +16 -15
- package/lib/ads/client_side_ad.js +8 -0
- package/lib/ads/client_side_ad_manager.js +14 -6
- package/lib/ads/server_side_ad.js +7 -0
- package/lib/ads/server_side_ad_manager.js +19 -2
- package/lib/cast/cast_proxy.js +8 -0
- package/lib/cast/cast_utils.js +7 -1
- package/lib/cea/cea608_data_channel.js +56 -56
- package/lib/cea/cea608_memory.js +33 -33
- package/lib/cea/cea708_service.js +43 -43
- package/lib/cea/cea708_window.js +38 -38
- package/lib/cea/cea_decoder.js +13 -14
- package/lib/cea/cea_utils.js +23 -23
- package/lib/cea/dtvcc_packet_builder.js +7 -7
- package/lib/cea/i_caption_decoder.js +2 -3
- package/lib/cea/i_cea_parser.js +2 -2
- package/lib/cea/mp4_cea_parser.js +6 -6
- package/lib/dash/dash_parser.js +53 -14
- 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 +210 -30
- package/lib/media/closed_caption_parser.js +1 -2
- package/lib/media/drm_engine.js +162 -192
- package/lib/media/quality_observer.js +291 -0
- package/lib/media/segment_index.js +9 -1
- package/lib/media/segment_reference.js +37 -5
- package/lib/media/streaming_engine.js +48 -10
- 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 +82 -18
- package/lib/offline/download_info.js +68 -0
- package/lib/offline/download_manager.js +14 -7
- package/lib/offline/indexeddb/base_storage_cell.js +35 -0
- package/lib/offline/indexeddb/storage_mechanism.js +1 -1
- package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
- package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
- package/lib/offline/indexeddb/v5_storage_cell.js +5 -0
- package/lib/offline/manifest_converter.js +3 -1
- package/lib/offline/storage.js +404 -297
- package/lib/offline/stored_content_utils.js +2 -0
- package/lib/player.js +622 -153
- package/lib/polyfill/aria.js +82 -0
- package/lib/polyfill/random_uuid.js +52 -0
- package/lib/routing/walker.js +2 -3
- package/lib/text/cue.js +12 -0
- package/lib/text/srt_text_parser.js +4 -4
- package/lib/text/text_engine.js +2 -2
- package/lib/text/ttml_text_parser.js +25 -2
- package/lib/text/ui_text_displayer.js +2 -2
- package/lib/text/vtt_text_parser.js +2 -2
- package/lib/text/web_vtt_generator.js +55 -12
- package/lib/util/cmcd_manager.js +826 -0
- package/lib/util/error.js +12 -0
- package/lib/util/language_utils.js +12 -0
- package/lib/util/manifest_parser_utils.js +1 -0
- package/lib/util/mp4_box_parsers.js +20 -20
- package/lib/util/multi_map.js +8 -0
- package/lib/util/mutex.js +52 -0
- package/lib/util/periods.js +98 -64
- package/lib/util/player_configuration.js +31 -1
- package/lib/util/stream_utils.js +140 -85
- package/lib/util/xml_utils.js +31 -12
- package/package.json +1 -1
- package/roadmap.md +24 -22
- package/shaka-player.uncompiled.js +4 -0
- package/test/cast/cast_utils_unit.js +1 -0
- package/test/cea/cea608_memory_unit.js +1 -1
- package/test/cea/cea708_service_unit.js +8 -8
- package/test/cea/cea708_window_unit.js +6 -6
- package/test/cea/cea_decoder_unit.js +1 -1
- package/test/cea/dtvcc_packet_builder_unit.js +2 -2
- package/test/dash/dash_parser_content_protection_unit.js +2 -0
- package/test/dash/dash_parser_live_unit.js +101 -1
- package/test/dash/dash_parser_manifest_unit.js +78 -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 +252 -0
- package/test/media/drm_engine_integration.js +86 -12
- package/test/media/drm_engine_unit.js +310 -450
- package/test/media/quality_observer_unit.js +139 -0
- package/test/media/segment_reference_unit.js +16 -1
- package/test/media/streaming_engine_integration.js +2 -1
- package/test/media/streaming_engine_unit.js +2 -0
- package/test/net/http_plugin_unit.js +20 -15
- package/test/offline/manifest_convert_unit.js +2 -0
- package/test/offline/storage_integration.js +117 -23
- package/test/player_integration.js +151 -0
- package/test/player_src_equals_integration.js +52 -0
- package/test/player_unit.js +11 -33
- package/test/test/assets/chapters.srt +11 -0
- package/test/test/assets/chapters.vtt +10 -0
- package/test/test/util/cea_utils.js +12 -12
- package/test/test/util/dash_parser_util.js +4 -0
- package/test/test/util/fake_ad.js +7 -0
- package/test/test/util/fake_ad_manager.js +7 -0
- package/test/test/util/fake_drm_engine.js +9 -2
- package/test/test/util/manifest_generator.js +5 -2
- package/test/test/util/manifest_parser_util.js +3 -1
- package/test/test/util/test_scheme.js +14 -1
- package/test/text/ttml_text_parser_unit.js +47 -0
- package/test/text/web_vtt_generator_unit.js +81 -7
- package/test/ui/ui_unit.js +250 -0
- package/test/util/cmcd_manager_unit.js +277 -0
- package/test/util/stream_utils_unit.js +118 -10
- package/ui/airplay_button.js +2 -1
- package/ui/audio_language_selection.js +9 -5
- package/ui/cast_button.js +5 -6
- package/ui/constants.js +0 -3
- package/ui/context_menu.js +109 -0
- package/ui/controls.js +41 -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 +16 -8
- package/ui/fullscreen_button.js +2 -3
- package/ui/language_utils.js +1 -1
- 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/loop_button.js +6 -3
- package/ui/mute_button.js +3 -4
- package/ui/overflow_menu.js +7 -28
- package/ui/pip_button.js +10 -7
- package/ui/play_button.js +2 -2
- package/ui/playback_rate_selection.js +11 -15
- package/ui/presentation_time.js +1 -3
- package/ui/resolution_selection.js +11 -7
- package/ui/rewind_button.js +17 -9
- package/ui/seek_bar.js +6 -6
- package/ui/settings_menu.js +36 -4
- package/ui/small_play_button.js +1 -0
- package/ui/spacer.js +1 -1
- package/ui/statistics_button.js +253 -0
- package/ui/text_selection.js +19 -15
- package/ui/ui.js +30 -0
- package/ui/ui_utils.js +1 -1
- package/ui/volume_bar.js +2 -4
|
@@ -24,10 +24,12 @@ shaka.net.HttpXHRPlugin = class {
|
|
|
24
24
|
* @param {shaka.net.NetworkingEngine.RequestType} requestType
|
|
25
25
|
* @param {shaka.extern.ProgressUpdated} progressUpdated Called when a
|
|
26
26
|
* progress event happened.
|
|
27
|
+
* @param {shaka.extern.HeadersReceived} headersReceived Called when the
|
|
28
|
+
* headers for the download are received, but before the body is.
|
|
27
29
|
* @return {!shaka.extern.IAbortableOperation.<shaka.extern.Response>}
|
|
28
30
|
* @export
|
|
29
31
|
*/
|
|
30
|
-
static parse(uri, request, requestType, progressUpdated) {
|
|
32
|
+
static parse(uri, request, requestType, progressUpdated, headersReceived) {
|
|
31
33
|
const xhr = new shaka.net.HttpXHRPlugin.Xhr_();
|
|
32
34
|
|
|
33
35
|
// Last time stamp when we got a progress event.
|
|
@@ -48,23 +50,25 @@ shaka.net.HttpXHRPlugin = class {
|
|
|
48
50
|
shaka.util.Error.Code.OPERATION_ABORTED,
|
|
49
51
|
uri, requestType));
|
|
50
52
|
};
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
/** @type {!Array.<string>} */
|
|
60
|
-
const parts = header.split(': ');
|
|
61
|
-
headers[parts[0].toLowerCase()] = parts.slice(1).join(': ');
|
|
53
|
+
let calledHeadersReceived = false;
|
|
54
|
+
xhr.onreadystatechange = (event) => {
|
|
55
|
+
// See if the readyState is 2 ("HEADERS_RECEIVED").
|
|
56
|
+
if (xhr.readyState == 2 && !calledHeadersReceived) {
|
|
57
|
+
const headers = shaka.net.HttpXHRPlugin.headersToGenericObject_(xhr);
|
|
58
|
+
headersReceived(headers);
|
|
59
|
+
// Don't send out this event twice.
|
|
60
|
+
calledHeadersReceived = true;
|
|
62
61
|
}
|
|
62
|
+
};
|
|
63
|
+
xhr.onload = (event) => {
|
|
64
|
+
const headers = shaka.net.HttpXHRPlugin.headersToGenericObject_(xhr);
|
|
65
|
+
goog.asserts.assert(xhr.response instanceof ArrayBuffer,
|
|
66
|
+
'XHR should have a response by now!');
|
|
67
|
+
const xhrResponse = xhr.response;
|
|
63
68
|
|
|
64
69
|
try {
|
|
65
70
|
const response = shaka.net.HttpPluginUtils.makeResponse(headers,
|
|
66
|
-
|
|
67
|
-
requestType);
|
|
71
|
+
xhrResponse, xhr.status, uri, xhr.responseURL, requestType);
|
|
68
72
|
resolve(response);
|
|
69
73
|
} catch (error) {
|
|
70
74
|
goog.asserts.assert(error instanceof shaka.util.Error,
|
|
@@ -116,6 +120,24 @@ shaka.net.HttpXHRPlugin = class {
|
|
|
116
120
|
return Promise.resolve();
|
|
117
121
|
});
|
|
118
122
|
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @param {!XMLHttpRequest} xhr
|
|
126
|
+
* @return {!Object.<string, string>}
|
|
127
|
+
* @private
|
|
128
|
+
*/
|
|
129
|
+
static headersToGenericObject_(xhr) {
|
|
130
|
+
// Since Edge incorrectly return the header with a leading new
|
|
131
|
+
// line character ('\n'), we trim the header here.
|
|
132
|
+
const headerLines = xhr.getAllResponseHeaders().trim().split('\r\n');
|
|
133
|
+
const headers = {};
|
|
134
|
+
for (const header of headerLines) {
|
|
135
|
+
/** @type {!Array.<string>} */
|
|
136
|
+
const parts = header.split(': ');
|
|
137
|
+
headers[parts[0].toLowerCase()] = parts.slice(1).join(': ');
|
|
138
|
+
}
|
|
139
|
+
return headers;
|
|
140
|
+
}
|
|
119
141
|
};
|
|
120
142
|
|
|
121
143
|
|
|
@@ -136,4 +158,8 @@ shaka.net.NetworkingEngine.registerScheme(
|
|
|
136
158
|
'https', shaka.net.HttpXHRPlugin.parse,
|
|
137
159
|
shaka.net.NetworkingEngine.PluginPriority.FALLBACK,
|
|
138
160
|
/* progressSupport= */ true);
|
|
161
|
+
shaka.net.NetworkingEngine.registerScheme(
|
|
162
|
+
'blob', shaka.net.HttpXHRPlugin.parse,
|
|
163
|
+
shaka.net.NetworkingEngine.PluginPriority.FALLBACK,
|
|
164
|
+
/* progressSupport= */ true);
|
|
139
165
|
|
|
@@ -48,8 +48,12 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
|
|
|
48
48
|
* @param {function(number, number)=} onProgressUpdated Called when a progress
|
|
49
49
|
* event is triggered. Passed the duration, in milliseconds, that the
|
|
50
50
|
* request took, and the number of bytes transferred.
|
|
51
|
+
* @param {shaka.net.NetworkingEngine.OnHeadersReceived=} onHeadersReceived
|
|
52
|
+
* Called when the headers are received for a download.
|
|
53
|
+
* @param {shaka.net.NetworkingEngine.OnDownloadFailed=} onDownloadFailed
|
|
54
|
+
* Called when a download fails, for any reason.
|
|
51
55
|
*/
|
|
52
|
-
constructor(onProgressUpdated) {
|
|
56
|
+
constructor(onProgressUpdated, onHeadersReceived, onDownloadFailed) {
|
|
53
57
|
super();
|
|
54
58
|
|
|
55
59
|
/** @private {boolean} */
|
|
@@ -67,6 +71,12 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
|
|
|
67
71
|
/** @private {?function(number, number)} */
|
|
68
72
|
this.onProgressUpdated_ = onProgressUpdated || null;
|
|
69
73
|
|
|
74
|
+
/** @private {?shaka.net.NetworkingEngine.OnHeadersReceived} */
|
|
75
|
+
this.onHeadersReceived_ = onHeadersReceived || null;
|
|
76
|
+
|
|
77
|
+
/** @private {?shaka.net.NetworkingEngine.OnDownloadFailed} */
|
|
78
|
+
this.onDownloadFailed_ = onDownloadFailed || null;
|
|
79
|
+
|
|
70
80
|
/** @private {boolean} */
|
|
71
81
|
this.forceHTTPS_ = false;
|
|
72
82
|
}
|
|
@@ -447,6 +457,8 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
|
|
|
447
457
|
|
|
448
458
|
let aborted = false;
|
|
449
459
|
|
|
460
|
+
let headersReceivedCalled = false;
|
|
461
|
+
|
|
450
462
|
let startTimeMs;
|
|
451
463
|
const sendOperation = backoffOperation.chain(() => {
|
|
452
464
|
if (this.destroyed_) {
|
|
@@ -456,23 +468,27 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
|
|
|
456
468
|
startTimeMs = Date.now();
|
|
457
469
|
const segment = shaka.net.NetworkingEngine.RequestType.SEGMENT;
|
|
458
470
|
|
|
459
|
-
const
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
471
|
+
const progressUpdated = (time, bytes, numBytesRemaining) => {
|
|
472
|
+
if (connectionTimer) {
|
|
473
|
+
connectionTimer.stop();
|
|
474
|
+
}
|
|
475
|
+
if (stallTimer) {
|
|
476
|
+
stallTimer.tickAfter(stallTimeoutMs / 1000);
|
|
477
|
+
}
|
|
478
|
+
if (this.onProgressUpdated_ && type == segment) {
|
|
479
|
+
this.onProgressUpdated_(time, bytes);
|
|
480
|
+
gotProgress = true;
|
|
481
|
+
numBytesRemainingObj.setBytes(numBytesRemaining);
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
const headersReceived = (headers) => {
|
|
485
|
+
if (this.onHeadersReceived_) {
|
|
486
|
+
this.onHeadersReceived_(headers, request, type);
|
|
487
|
+
}
|
|
488
|
+
headersReceivedCalled = true;
|
|
489
|
+
};
|
|
490
|
+
const requestPlugin = plugin(
|
|
491
|
+
request.uris[index], request, type, progressUpdated, headersReceived);
|
|
476
492
|
|
|
477
493
|
if (!progressSupport) {
|
|
478
494
|
return requestPlugin;
|
|
@@ -511,6 +527,13 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
|
|
|
511
527
|
response: response,
|
|
512
528
|
gotProgress: gotProgress,
|
|
513
529
|
};
|
|
530
|
+
if (!headersReceivedCalled) {
|
|
531
|
+
// The plugin did not call headersReceived, perhaps because it is not
|
|
532
|
+
// able to track that information. So, fire the event manually.
|
|
533
|
+
if (this.onHeadersReceived_) {
|
|
534
|
+
this.onHeadersReceived_(response.headers, request, type);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
514
537
|
|
|
515
538
|
return responseAndGotProgress;
|
|
516
539
|
}, (error) => {
|
|
@@ -520,6 +543,17 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
|
|
|
520
543
|
if (stallTimer) {
|
|
521
544
|
stallTimer.stop();
|
|
522
545
|
}
|
|
546
|
+
if (this.onDownloadFailed_) {
|
|
547
|
+
let shakaError = null;
|
|
548
|
+
let httpResponseCode = 0;
|
|
549
|
+
if (error instanceof shaka.util.Error) {
|
|
550
|
+
shakaError = error;
|
|
551
|
+
if (error.code == shaka.util.Error.Code.BAD_HTTP_STATUS) {
|
|
552
|
+
httpResponseCode = /** @type {number} */ (error.data[1]);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
this.onDownloadFailed_(request, shakaError, httpResponseCode, aborted);
|
|
556
|
+
}
|
|
523
557
|
if (this.destroyed_) {
|
|
524
558
|
return shaka.util.AbortableOperation.aborted();
|
|
525
559
|
}
|
|
@@ -707,6 +741,7 @@ shaka.net.NetworkingEngine.RequestType = {
|
|
|
707
741
|
'LICENSE': 2,
|
|
708
742
|
'APP': 3,
|
|
709
743
|
'TIMING': 4,
|
|
744
|
+
'SERVER_CERTIFICATE': 5,
|
|
710
745
|
};
|
|
711
746
|
|
|
712
747
|
|
|
@@ -763,3 +798,32 @@ shaka.net.NetworkingEngine.schemes_ = {};
|
|
|
763
798
|
* @private
|
|
764
799
|
*/
|
|
765
800
|
shaka.net.NetworkingEngine.ResponseAndGotProgress;
|
|
801
|
+
|
|
802
|
+
|
|
803
|
+
/**
|
|
804
|
+
* @typedef {function(
|
|
805
|
+
* !Object.<string, string>,
|
|
806
|
+
* !shaka.extern.Request,
|
|
807
|
+
* !shaka.net.NetworkingEngine.RequestType)}
|
|
808
|
+
*
|
|
809
|
+
* @description
|
|
810
|
+
* A callback function that passes the shaka.extern.HeadersReceived along to
|
|
811
|
+
* the player, plus some extra data.
|
|
812
|
+
* @export
|
|
813
|
+
*/
|
|
814
|
+
shaka.net.NetworkingEngine.OnHeadersReceived;
|
|
815
|
+
|
|
816
|
+
|
|
817
|
+
/**
|
|
818
|
+
* @typedef {function(
|
|
819
|
+
* !shaka.extern.Request,
|
|
820
|
+
* ?shaka.util.Error,
|
|
821
|
+
* number,
|
|
822
|
+
* boolean)}
|
|
823
|
+
*
|
|
824
|
+
* @description
|
|
825
|
+
* A callback function that notifies the player when a download fails, for any
|
|
826
|
+
* reason (e.g. even if the download was aborted).
|
|
827
|
+
* @export
|
|
828
|
+
*/
|
|
829
|
+
shaka.net.NetworkingEngine.OnDownloadFailed;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/*! @license
|
|
2
|
+
* Shaka Player
|
|
3
|
+
* Copyright 2016 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
goog.provide('shaka.offline.DownloadInfo');
|
|
8
|
+
|
|
9
|
+
goog.require('shaka.util.Networking');
|
|
10
|
+
goog.requireType('shaka.media.InitSegmentReference');
|
|
11
|
+
goog.requireType('shaka.media.SegmentReference');
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* An object that represents a single segment, that the storage system will soon
|
|
16
|
+
* download, but has not yet started downloading.
|
|
17
|
+
*/
|
|
18
|
+
shaka.offline.DownloadInfo = class {
|
|
19
|
+
/**
|
|
20
|
+
* @param {shaka.media.SegmentReference|shaka.media.InitSegmentReference} ref
|
|
21
|
+
* @param {number} estimateId
|
|
22
|
+
* @param {number} groupId
|
|
23
|
+
* @param {boolean} isInitSegment
|
|
24
|
+
*/
|
|
25
|
+
constructor(ref, estimateId, groupId, isInitSegment) {
|
|
26
|
+
/** @type {shaka.media.SegmentReference|shaka.media.InitSegmentReference} */
|
|
27
|
+
this.ref = ref;
|
|
28
|
+
|
|
29
|
+
/** @type {number} */
|
|
30
|
+
this.estimateId = estimateId;
|
|
31
|
+
|
|
32
|
+
/** @type {number} */
|
|
33
|
+
this.groupId = groupId;
|
|
34
|
+
|
|
35
|
+
/** @type {boolean} */
|
|
36
|
+
this.isInitSegment = isInitSegment;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Creates an ID that encapsulates all important information in the ref, which
|
|
41
|
+
* can then be used to check for equality.
|
|
42
|
+
* @param {shaka.media.SegmentReference|shaka.media.InitSegmentReference} ref
|
|
43
|
+
* @return {string}
|
|
44
|
+
*/
|
|
45
|
+
static idForSegmentRef(ref) {
|
|
46
|
+
// Escape the URIs using encodeURI, to make sure that a weirdly formed URI
|
|
47
|
+
// cannot cause two unrelated refs to be considered equivalent.
|
|
48
|
+
return ref.getUris().map((uri) => '{' + encodeURI(uri) + '}').join('') +
|
|
49
|
+
':' + ref.startByte + ':' + ref.endByte;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** @return {string} */
|
|
53
|
+
getRefId() {
|
|
54
|
+
return shaka.offline.DownloadInfo.idForSegmentRef(this.ref);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @param {shaka.extern.PlayerConfiguration} config
|
|
59
|
+
* @return {!shaka.extern.Request}
|
|
60
|
+
*/
|
|
61
|
+
makeSegmentRequest(config) {
|
|
62
|
+
return shaka.util.Networking.createSegmentRequest(
|
|
63
|
+
this.ref.getUris(),
|
|
64
|
+
this.ref.startByte,
|
|
65
|
+
this.ref.endByte,
|
|
66
|
+
config.streaming.retryParameters);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
@@ -44,9 +44,8 @@ shaka.offline.DownloadManager = class {
|
|
|
44
44
|
|
|
45
45
|
/** @private {!shaka.util.Destroyer} */
|
|
46
46
|
this.destroyer_ = new shaka.util.Destroyer(() => {
|
|
47
|
-
const promises = Array.from(this.groups_.values());
|
|
48
47
|
// Add a "catch" block to stop errors from being returned.
|
|
49
|
-
return
|
|
48
|
+
return this.abortAll().catch(() => {});
|
|
50
49
|
});
|
|
51
50
|
|
|
52
51
|
/**
|
|
@@ -103,6 +102,16 @@ shaka.offline.DownloadManager = class {
|
|
|
103
102
|
return Promise.all(promises);
|
|
104
103
|
}
|
|
105
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Adds a byte length to the download estimate.
|
|
107
|
+
*
|
|
108
|
+
* @param {number} estimatedByteLength
|
|
109
|
+
* @return {number} estimateId
|
|
110
|
+
*/
|
|
111
|
+
addDownloadEstimate(estimatedByteLength) {
|
|
112
|
+
return this.estimator_.open(estimatedByteLength);
|
|
113
|
+
}
|
|
114
|
+
|
|
106
115
|
/**
|
|
107
116
|
* Add a request to be downloaded as part of a group.
|
|
108
117
|
*
|
|
@@ -110,18 +119,16 @@ shaka.offline.DownloadManager = class {
|
|
|
110
119
|
* The group to add this segment to. If the group does not exist, a new
|
|
111
120
|
* group will be created.
|
|
112
121
|
* @param {shaka.extern.Request} request
|
|
113
|
-
* @param {number}
|
|
122
|
+
* @param {number} estimateId
|
|
114
123
|
* @param {boolean} isInitSegment
|
|
115
124
|
* @param {function(BufferSource):!Promise} onDownloaded
|
|
116
125
|
* The callback for when this request has been downloaded. Downloading for
|
|
117
126
|
* |group| will pause until the promise returned by |onDownloaded| resolves.
|
|
118
127
|
* @return {!Promise} Resolved when this request is complete.
|
|
119
128
|
*/
|
|
120
|
-
queue(groupId, request,
|
|
129
|
+
queue(groupId, request, estimateId, isInitSegment, onDownloaded) {
|
|
121
130
|
this.destroyer_.ensureNotDestroyed();
|
|
122
131
|
|
|
123
|
-
const id = this.estimator_.open(estimatedByteLength);
|
|
124
|
-
|
|
125
132
|
const group = this.groups_.get(groupId) || Promise.resolve();
|
|
126
133
|
|
|
127
134
|
// Add another download to the group.
|
|
@@ -149,7 +156,7 @@ shaka.offline.DownloadManager = class {
|
|
|
149
156
|
}
|
|
150
157
|
|
|
151
158
|
// Update all our internal stats.
|
|
152
|
-
this.estimator_.close(
|
|
159
|
+
this.estimator_.close(estimateId, response.byteLength);
|
|
153
160
|
this.onProgress_(
|
|
154
161
|
this.estimator_.getEstimatedProgress(),
|
|
155
162
|
this.estimator_.getTotalDownloaded());
|
|
@@ -68,6 +68,28 @@ shaka.offline.indexeddb.BaseStorageCell = class {
|
|
|
68
68
|
return this.rejectAdd(this.manifestStore_);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
/** @override */
|
|
72
|
+
updateManifest(key, manifest) {
|
|
73
|
+
// By default, reject all updates.
|
|
74
|
+
return this.rejectUpdate(this.manifestStore_);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @param {number} key
|
|
79
|
+
* @param {!shaka.extern.ManifestDB} manifest
|
|
80
|
+
* @return {!Promise}
|
|
81
|
+
* @protected
|
|
82
|
+
*/
|
|
83
|
+
updateManifestImplementation(key, manifest) {
|
|
84
|
+
const op = this.connection_.startReadWriteOperation(this.manifestStore_);
|
|
85
|
+
const store = op.store();
|
|
86
|
+
store.get(key).onsuccess = (e) => {
|
|
87
|
+
store.put(manifest, key);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
return op.promise();
|
|
91
|
+
}
|
|
92
|
+
|
|
71
93
|
/** @override */
|
|
72
94
|
updateManifestExpiration(key, newExpiration) {
|
|
73
95
|
const op = this.connection_.startReadWriteOperation(this.manifestStore_);
|
|
@@ -145,6 +167,19 @@ shaka.offline.indexeddb.BaseStorageCell = class {
|
|
|
145
167
|
'Cannot add new value to ' + storeName));
|
|
146
168
|
}
|
|
147
169
|
|
|
170
|
+
/**
|
|
171
|
+
* @param {string} storeName
|
|
172
|
+
* @return {!Promise}
|
|
173
|
+
* @protected
|
|
174
|
+
*/
|
|
175
|
+
rejectUpdate(storeName) {
|
|
176
|
+
return Promise.reject(new shaka.util.Error(
|
|
177
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
178
|
+
shaka.util.Error.Category.STORAGE,
|
|
179
|
+
shaka.util.Error.Code.MODIFY_OPERATION_NOT_SUPPORTED,
|
|
180
|
+
'Cannot modify values in ' + storeName));
|
|
181
|
+
}
|
|
182
|
+
|
|
148
183
|
/**
|
|
149
184
|
* @param {string} storeName
|
|
150
185
|
* @param {!Array.<T>} values
|
|
@@ -315,7 +315,7 @@ shaka.offline.indexeddb.StorageMechanism = class {
|
|
|
315
315
|
|
|
316
316
|
const del = window.indexedDB.deleteDatabase(name);
|
|
317
317
|
del.onblocked = (event) => {
|
|
318
|
-
shaka.log.warning('Deleting', name, 'is being blocked');
|
|
318
|
+
shaka.log.warning('Deleting', name, 'is being blocked', event);
|
|
319
319
|
};
|
|
320
320
|
del.onsuccess = (event) => {
|
|
321
321
|
p.resolve();
|
|
@@ -33,6 +33,11 @@ shaka.offline.indexeddb.V5StorageCell = class
|
|
|
33
33
|
return this.add(this.manifestStore_, manifests);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
/** @override */
|
|
37
|
+
updateManifest(key, manifest) {
|
|
38
|
+
return this.updateManifestImplementation(key, manifest);
|
|
39
|
+
}
|
|
40
|
+
|
|
36
41
|
/** @override */
|
|
37
42
|
convertManifest(old) {
|
|
38
43
|
// JSON serialization turns Infinity into null, so turn it back now.
|
|
@@ -229,7 +229,9 @@ shaka.offline.ManifestConverter = class {
|
|
|
229
229
|
initSegmentReference,
|
|
230
230
|
segmentDB.timestampOffset,
|
|
231
231
|
segmentDB.appendWindowStart,
|
|
232
|
-
segmentDB.appendWindowEnd
|
|
232
|
+
segmentDB.appendWindowEnd,
|
|
233
|
+
/* partialReferences= */ [],
|
|
234
|
+
segmentDB.tilesLayout || '');
|
|
233
235
|
}
|
|
234
236
|
|
|
235
237
|
/**
|