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
|
@@ -9,23 +9,45 @@ goog.require('shaka.text.WebVttGenerator');
|
|
|
9
9
|
|
|
10
10
|
describe('WebVttGenerator', () => {
|
|
11
11
|
it('supports no cues', () => {
|
|
12
|
-
verifyHelper([], 'WEBVTT\n\n');
|
|
12
|
+
verifyHelper([], [], 'WEBVTT\n\n');
|
|
13
13
|
});
|
|
14
14
|
|
|
15
15
|
it('convert cues to WebVTT', () => {
|
|
16
16
|
const shakaCue1 = new shaka.text.Cue(20, 40, 'Test');
|
|
17
|
+
shakaCue1.textAlign = shaka.text.Cue.textAlign.LEFT;
|
|
18
|
+
shakaCue1.writingMode = shaka.text.Cue.writingMode.VERTICAL_LEFT_TO_RIGHT;
|
|
17
19
|
const shakaCue2 = new shaka.text.Cue(40, 50, 'Test2');
|
|
20
|
+
shakaCue2.textAlign = shaka.text.Cue.textAlign.RIGHT;
|
|
21
|
+
shakaCue2.writingMode = shaka.text.Cue.writingMode.VERTICAL_RIGHT_TO_LEFT;
|
|
22
|
+
const shakaCue3 = new shaka.text.Cue(50, 51, 'Test3');
|
|
23
|
+
shakaCue3.textAlign = shaka.text.Cue.textAlign.CENTER;
|
|
24
|
+
const shakaCue4 = new shaka.text.Cue(52, 53, 'Test4');
|
|
25
|
+
shakaCue4.textAlign = shaka.text.Cue.textAlign.START;
|
|
26
|
+
const shakaCue5 = new shaka.text.Cue(53, 54, 'Test5');
|
|
27
|
+
shakaCue5.textAlign = shaka.text.Cue.textAlign.END;
|
|
28
|
+
|
|
29
|
+
const adCuePoints = [];
|
|
18
30
|
|
|
19
31
|
verifyHelper(
|
|
20
32
|
[
|
|
21
33
|
shakaCue1,
|
|
22
34
|
shakaCue2,
|
|
35
|
+
shakaCue3,
|
|
36
|
+
shakaCue4,
|
|
37
|
+
shakaCue5,
|
|
23
38
|
],
|
|
39
|
+
adCuePoints,
|
|
24
40
|
'WEBVTT\n\n' +
|
|
25
|
-
'00:00:20.000 --> 00:00:40.000\n' +
|
|
41
|
+
'00:00:20.000 --> 00:00:40.000 align:left vertical:lr\n' +
|
|
26
42
|
'Test\n\n' +
|
|
27
|
-
'00:00:40.000 --> 00:00:50.000\n' +
|
|
28
|
-
'Test2\n\n'
|
|
43
|
+
'00:00:40.000 --> 00:00:50.000 align:right vertical:rl\n' +
|
|
44
|
+
'Test2\n\n' +
|
|
45
|
+
'00:00:50.000 --> 00:00:51.000 align:middle\n' +
|
|
46
|
+
'Test3\n\n' +
|
|
47
|
+
'00:00:52.000 --> 00:00:53.000 align:start\n' +
|
|
48
|
+
'Test4\n\n' +
|
|
49
|
+
'00:00:53.000 --> 00:00:54.000 align:end\n' +
|
|
50
|
+
'Test5\n\n');
|
|
29
51
|
});
|
|
30
52
|
|
|
31
53
|
it('creates style tags for cues with underline/italics/bold', () => {
|
|
@@ -49,19 +71,71 @@ describe('WebVttGenerator', () => {
|
|
|
49
71
|
nestedCue4.textDecoration.push(shaka.text.Cue.textDecoration.UNDERLINE);
|
|
50
72
|
|
|
51
73
|
shakaCue.nestedCues = [nestedCue1, nestedCue2, nestedCue3, nestedCue4];
|
|
74
|
+
|
|
75
|
+
const adCuePoints = [];
|
|
76
|
+
|
|
52
77
|
verifyHelper(
|
|
53
78
|
[shakaCue],
|
|
79
|
+
adCuePoints,
|
|
54
80
|
'WEBVTT\n\n' +
|
|
55
|
-
'00:00:10.000 --> 00:00:20.000\n' +
|
|
81
|
+
'00:00:10.000 --> 00:00:20.000 align:middle\n' +
|
|
56
82
|
'<i><u>Test1</u></i><b><i>Test2</i></b>Test3<u>Test4</u>\n\n');
|
|
57
83
|
});
|
|
58
84
|
|
|
85
|
+
it('computes the time with ad cue points', () => {
|
|
86
|
+
const shakaCue1 = new shaka.text.Cue(20, 30, 'Test');
|
|
87
|
+
shakaCue1.textAlign = shaka.text.Cue.textAlign.LEFT;
|
|
88
|
+
shakaCue1.writingMode = shaka.text.Cue.writingMode.VERTICAL_LEFT_TO_RIGHT;
|
|
89
|
+
const shakaCue2 = new shaka.text.Cue(40, 50, 'Test2');
|
|
90
|
+
shakaCue2.textAlign = shaka.text.Cue.textAlign.RIGHT;
|
|
91
|
+
shakaCue2.writingMode = shaka.text.Cue.writingMode.VERTICAL_RIGHT_TO_LEFT;
|
|
92
|
+
const shakaCue3 = new shaka.text.Cue(50, 51, 'Test3');
|
|
93
|
+
shakaCue3.textAlign = shaka.text.Cue.textAlign.CENTER;
|
|
94
|
+
const shakaCue4 = new shaka.text.Cue(52, 53, 'Test4');
|
|
95
|
+
shakaCue4.textAlign = shaka.text.Cue.textAlign.START;
|
|
96
|
+
const shakaCue5 = new shaka.text.Cue(53, 54, 'Test5');
|
|
97
|
+
shakaCue5.textAlign = shaka.text.Cue.textAlign.END;
|
|
98
|
+
|
|
99
|
+
const adCuePoints = [
|
|
100
|
+
{
|
|
101
|
+
start: 0,
|
|
102
|
+
end: 10,
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
start: 35,
|
|
106
|
+
end: 45,
|
|
107
|
+
},
|
|
108
|
+
];
|
|
109
|
+
|
|
110
|
+
verifyHelper(
|
|
111
|
+
[
|
|
112
|
+
shakaCue1,
|
|
113
|
+
shakaCue2,
|
|
114
|
+
shakaCue3,
|
|
115
|
+
shakaCue4,
|
|
116
|
+
shakaCue5,
|
|
117
|
+
],
|
|
118
|
+
adCuePoints,
|
|
119
|
+
'WEBVTT\n\n' +
|
|
120
|
+
'00:00:30.000 --> 00:00:40.000 align:left vertical:lr\n' +
|
|
121
|
+
'Test\n\n' +
|
|
122
|
+
'00:01:00.000 --> 00:01:10.000 align:right vertical:rl\n' +
|
|
123
|
+
'Test2\n\n' +
|
|
124
|
+
'00:01:10.000 --> 00:01:11.000 align:middle\n' +
|
|
125
|
+
'Test3\n\n' +
|
|
126
|
+
'00:01:12.000 --> 00:01:13.000 align:start\n' +
|
|
127
|
+
'Test4\n\n' +
|
|
128
|
+
'00:01:13.000 --> 00:01:14.000 align:end\n' +
|
|
129
|
+
'Test5\n\n');
|
|
130
|
+
});
|
|
131
|
+
|
|
59
132
|
/**
|
|
60
133
|
* @param {!Array} cues
|
|
134
|
+
* @param {!Array} adCuePoints
|
|
61
135
|
* @param {string} text
|
|
62
136
|
*/
|
|
63
|
-
function verifyHelper(cues, text) {
|
|
64
|
-
const result = shaka.text.WebVttGenerator.convert(cues);
|
|
137
|
+
function verifyHelper(cues, adCuePoints, text) {
|
|
138
|
+
const result = shaka.text.WebVttGenerator.convert(cues, adCuePoints);
|
|
65
139
|
expect(text).toBe(result);
|
|
66
140
|
}
|
|
67
141
|
});
|
package/test/ui/ui_unit.js
CHANGED
|
@@ -409,6 +409,80 @@ describe('UI', () => {
|
|
|
409
409
|
});
|
|
410
410
|
});
|
|
411
411
|
|
|
412
|
+
describe('control panel buttons with submenus', () => {
|
|
413
|
+
/** @type {!HTMLElement} */
|
|
414
|
+
let resolutionMenu;
|
|
415
|
+
/** @type {!Element} */
|
|
416
|
+
let resolutionMenuButton;
|
|
417
|
+
/** @type {!HTMLElement} */
|
|
418
|
+
let languageMenu;
|
|
419
|
+
/** @type {!Element} */
|
|
420
|
+
let languageMenuButton;
|
|
421
|
+
|
|
422
|
+
beforeEach(() => {
|
|
423
|
+
const config = {
|
|
424
|
+
controlPanelElements: [
|
|
425
|
+
'quality',
|
|
426
|
+
'language',
|
|
427
|
+
],
|
|
428
|
+
};
|
|
429
|
+
const ui = UiUtils.createUIThroughAPI(videoContainer, video, config);
|
|
430
|
+
player = ui.getControls().getLocalPlayer();
|
|
431
|
+
|
|
432
|
+
const resolutionsMenus =
|
|
433
|
+
videoContainer.getElementsByClassName('shaka-resolutions');
|
|
434
|
+
expect(resolutionsMenus.length).toBe(1);
|
|
435
|
+
resolutionMenu = /** @type {!HTMLElement} */ (resolutionsMenus[0]);
|
|
436
|
+
|
|
437
|
+
const resolutionMenuButtons =
|
|
438
|
+
videoContainer.getElementsByClassName('shaka-resolution-button');
|
|
439
|
+
expect(resolutionMenuButtons.length).toBe(1);
|
|
440
|
+
resolutionMenuButton = resolutionMenuButtons[0];
|
|
441
|
+
|
|
442
|
+
const languageMenus =
|
|
443
|
+
videoContainer.getElementsByClassName('shaka-audio-languages');
|
|
444
|
+
expect(languageMenus.length).toBe(1);
|
|
445
|
+
languageMenu = /** @type {!HTMLElement} */ (languageMenus[0]);
|
|
446
|
+
|
|
447
|
+
const languageMenuButtons =
|
|
448
|
+
videoContainer.getElementsByClassName('shaka-language-button');
|
|
449
|
+
expect(languageMenuButtons.length).toBe(1);
|
|
450
|
+
languageMenuButton = languageMenuButtons[0];
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
it('menus are initially hidden', () => {
|
|
454
|
+
expect(resolutionMenu.classList.contains('shaka-hidden')).toBe(true);
|
|
455
|
+
expect(languageMenu.classList.contains('shaka-hidden')).toBe(true);
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
it('a menu becomes visible if the button is clicked', () => {
|
|
459
|
+
resolutionMenuButton.click();
|
|
460
|
+
|
|
461
|
+
expect(resolutionMenu.classList.contains('shaka-hidden')).toBe(false);
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
it('a menu becomes hidden if the "close" button is clicked', () => {
|
|
465
|
+
resolutionMenuButton.click();
|
|
466
|
+
|
|
467
|
+
const backToOverflowButtons =
|
|
468
|
+
videoContainer.getElementsByClassName('shaka-back-to-overflow-button');
|
|
469
|
+
expect(backToOverflowButtons.length).toBe(2);
|
|
470
|
+
const backToOverflowButton =
|
|
471
|
+
/** @type {!HTMLElement} */ (backToOverflowButtons[0]);
|
|
472
|
+
backToOverflowButton.click();
|
|
473
|
+
|
|
474
|
+
expect(resolutionMenu.classList.contains('shaka-hidden')).toBe(true);
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
it('a menu becomes hidden if another one is opened', () => {
|
|
478
|
+
resolutionMenuButton.click();
|
|
479
|
+
languageMenuButton.click();
|
|
480
|
+
|
|
481
|
+
expect(resolutionMenu.classList.contains('shaka-hidden')).toBe(true);
|
|
482
|
+
expect(languageMenu.classList.contains('shaka-hidden')).toBe(false);
|
|
483
|
+
});
|
|
484
|
+
});
|
|
485
|
+
|
|
412
486
|
describe('resolutions menu', () => {
|
|
413
487
|
/** @type {!HTMLElement} */
|
|
414
488
|
let resolutionsMenu;
|
|
@@ -611,6 +685,182 @@ describe('UI', () => {
|
|
|
611
685
|
goog.asserts.assert(found, 'Unable to find resolution menu');
|
|
612
686
|
}
|
|
613
687
|
});
|
|
688
|
+
|
|
689
|
+
describe('custom context menu', () => {
|
|
690
|
+
/** @type {!HTMLElement} */
|
|
691
|
+
let controlsContainer;
|
|
692
|
+
/** @type {!HTMLElement} */
|
|
693
|
+
let contextMenu;
|
|
694
|
+
|
|
695
|
+
beforeEach(() => {
|
|
696
|
+
const config = {
|
|
697
|
+
customContextMenu: true,
|
|
698
|
+
contextMenuElements: [
|
|
699
|
+
'fakeElement',
|
|
700
|
+
'statistics',
|
|
701
|
+
'fakeElement',
|
|
702
|
+
],
|
|
703
|
+
};
|
|
704
|
+
const ui = UiUtils.createUIThroughAPI(videoContainer, video, config);
|
|
705
|
+
|
|
706
|
+
controlsContainer = ui.getControls().getControlsContainer();
|
|
707
|
+
|
|
708
|
+
const contextMenus =
|
|
709
|
+
videoContainer.getElementsByClassName('shaka-context-menu');
|
|
710
|
+
expect(contextMenus.length).toBe(1);
|
|
711
|
+
contextMenu = /** @type {!HTMLElement} */
|
|
712
|
+
(contextMenus[0]);
|
|
713
|
+
});
|
|
714
|
+
|
|
715
|
+
it('responds to contextmenu event', () => {
|
|
716
|
+
expect(contextMenu.classList.contains('shaka-hidden')).toBe(true);
|
|
717
|
+
UiUtils.simulateEvent(controlsContainer, 'contextmenu');
|
|
718
|
+
expect(contextMenu.classList.contains('shaka-hidden')).toBe(false);
|
|
719
|
+
UiUtils.simulateEvent(controlsContainer, 'contextmenu');
|
|
720
|
+
expect(contextMenu.classList.contains('shaka-hidden')).toBe(true);
|
|
721
|
+
});
|
|
722
|
+
it('hides on click event', () => {
|
|
723
|
+
UiUtils.simulateEvent(controlsContainer, 'contextmenu');
|
|
724
|
+
UiUtils.simulateEvent(controlsContainer, 'click');
|
|
725
|
+
expect(contextMenu.classList.contains('shaka-hidden')).toBe(true);
|
|
726
|
+
UiUtils.simulateEvent(controlsContainer, 'contextmenu');
|
|
727
|
+
UiUtils.simulateEvent(window, 'click');
|
|
728
|
+
expect(contextMenu.classList.contains('shaka-hidden')).toBe(true);
|
|
729
|
+
});
|
|
730
|
+
it('builds internal elements', () => {
|
|
731
|
+
expect(contextMenu.childNodes.length).toBe(1);
|
|
732
|
+
|
|
733
|
+
expect(contextMenu.childNodes[0]['className'])
|
|
734
|
+
.toBe('shaka-statistics-button');
|
|
735
|
+
});
|
|
736
|
+
});
|
|
737
|
+
|
|
738
|
+
describe('statistics context menu', () => {
|
|
739
|
+
/** @type {!HTMLElement} */
|
|
740
|
+
let statisticsButton;
|
|
741
|
+
/** @type {!HTMLElement} */
|
|
742
|
+
let statisticsContainer;
|
|
743
|
+
|
|
744
|
+
beforeEach(() => {
|
|
745
|
+
const config = {
|
|
746
|
+
customContextMenu: true,
|
|
747
|
+
contextMenuElements: [
|
|
748
|
+
'statistics',
|
|
749
|
+
],
|
|
750
|
+
statisticsList: Object.keys(new shaka.util.Stats().getBlob()),
|
|
751
|
+
};
|
|
752
|
+
const ui = UiUtils.createUIThroughAPI(videoContainer, video, config);
|
|
753
|
+
player = ui.getControls().getLocalPlayer();
|
|
754
|
+
|
|
755
|
+
const statisticsButtons =
|
|
756
|
+
videoContainer.getElementsByClassName('shaka-statistics-button');
|
|
757
|
+
expect(statisticsButtons.length).toBe(1);
|
|
758
|
+
statisticsButton = /** @type {!HTMLElement} */
|
|
759
|
+
(statisticsButtons[0]);
|
|
760
|
+
|
|
761
|
+
const statisticsContainers =
|
|
762
|
+
videoContainer.getElementsByClassName('shaka-statistics-container');
|
|
763
|
+
expect(statisticsContainers.length).toBe(1);
|
|
764
|
+
statisticsContainer = /** @type {!HTMLElement} */
|
|
765
|
+
(statisticsContainers[0]);
|
|
766
|
+
});
|
|
767
|
+
|
|
768
|
+
it('appears and disappears on toggle', () => {
|
|
769
|
+
expect(statisticsContainer.classList.contains('shaka-hidden'))
|
|
770
|
+
.toBe(true);
|
|
771
|
+
|
|
772
|
+
statisticsButton.click();
|
|
773
|
+
expect(statisticsContainer.classList.contains('shaka-hidden'))
|
|
774
|
+
.toBe(false);
|
|
775
|
+
|
|
776
|
+
statisticsButton.click();
|
|
777
|
+
expect(statisticsContainer.classList.contains('shaka-hidden'))
|
|
778
|
+
.toBe(true);
|
|
779
|
+
});
|
|
780
|
+
|
|
781
|
+
it('displays all the available statistics', () => {
|
|
782
|
+
const skippedStats = ['stateHistory', 'switchHistory'];
|
|
783
|
+
const nodes = statisticsContainer.childNodes;
|
|
784
|
+
let nodeIndex = 0;
|
|
785
|
+
|
|
786
|
+
for (const statistic in new shaka.util.Stats().getBlob()) {
|
|
787
|
+
if (!skippedStats.includes(statistic)) {
|
|
788
|
+
// Text content of label (without ':') is a valid statistic
|
|
789
|
+
const label = nodes[nodeIndex].childNodes[0].textContent;
|
|
790
|
+
expect(label.replace(':', '')).toBe(statistic);
|
|
791
|
+
|
|
792
|
+
// Value has been parsed and it is not the default 'NaN'
|
|
793
|
+
const value = nodes[nodeIndex].childNodes[1].textContent;
|
|
794
|
+
expect(value).not.toBe('NaN');
|
|
795
|
+
|
|
796
|
+
nodeIndex += 1;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
});
|
|
800
|
+
it('is updated periodically', async () => {
|
|
801
|
+
function getStatsFromContainer() {
|
|
802
|
+
const nodes = statisticsContainer.childNodes;
|
|
803
|
+
width = nodes[0].childNodes[1].textContent.replace(' (px)', '');
|
|
804
|
+
height = nodes[1].childNodes[1].textContent.replace(' (px)', '');
|
|
805
|
+
bufferingTime =
|
|
806
|
+
nodes[13].childNodes[1].textContent.replace(' (s)', '');
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
/** @type {!string} */
|
|
810
|
+
let width;
|
|
811
|
+
/** @type {!string} */
|
|
812
|
+
let height;
|
|
813
|
+
/** @type {!string} */
|
|
814
|
+
let bufferingTime;
|
|
815
|
+
/** @type {!string} */
|
|
816
|
+
let lastBufferingTime;
|
|
817
|
+
|
|
818
|
+
const manifest =
|
|
819
|
+
shaka.test.ManifestGenerator.generate((manifest) => {
|
|
820
|
+
manifest.addVariant(/* id= */ 0, (variant) => {
|
|
821
|
+
variant.addVideo(1, (stream) => {
|
|
822
|
+
stream.size(1920, 1080);
|
|
823
|
+
});
|
|
824
|
+
});
|
|
825
|
+
});
|
|
826
|
+
|
|
827
|
+
shaka.media.ManifestParser.registerParserByMime(
|
|
828
|
+
fakeMimeType, () => new shaka.test.FakeManifestParser(manifest));
|
|
829
|
+
|
|
830
|
+
await player.load(
|
|
831
|
+
/* uri= */ 'fake', /* startTime= */ 0, fakeMimeType);
|
|
832
|
+
|
|
833
|
+
// Placeholder statistics are available before toggle
|
|
834
|
+
getStatsFromContainer();
|
|
835
|
+
expect(width).toBe('NaN');
|
|
836
|
+
expect(height).toBe('NaN');
|
|
837
|
+
expect(bufferingTime).toBe('NaN');
|
|
838
|
+
|
|
839
|
+
// Statistics are displayed on toggle
|
|
840
|
+
statisticsButton.click();
|
|
841
|
+
await Util.delay(0.2);
|
|
842
|
+
|
|
843
|
+
getStatsFromContainer();
|
|
844
|
+
expect(width).toBe('1920');
|
|
845
|
+
expect(height).toBe('1080');
|
|
846
|
+
expect(bufferingTime).toBeGreaterThanOrEqual(0.1);
|
|
847
|
+
|
|
848
|
+
// Statistics are updated over time
|
|
849
|
+
lastBufferingTime = bufferingTime;
|
|
850
|
+
await Util.delay(0.2);
|
|
851
|
+
|
|
852
|
+
getStatsFromContainer();
|
|
853
|
+
expect(bufferingTime).toBeGreaterThan(lastBufferingTime);
|
|
854
|
+
|
|
855
|
+
// Statistics stop updating when the container is hidden
|
|
856
|
+
statisticsButton.click();
|
|
857
|
+
lastBufferingTime = bufferingTime;
|
|
858
|
+
await Util.delay(0.2);
|
|
859
|
+
|
|
860
|
+
getStatsFromContainer();
|
|
861
|
+
expect(bufferingTime).toBe(lastBufferingTime);
|
|
862
|
+
});
|
|
863
|
+
});
|
|
614
864
|
});
|
|
615
865
|
|
|
616
866
|
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/*! @license
|
|
2
|
+
* Shaka Player
|
|
3
|
+
* Copyright 2016 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
goog.require('shaka.util.CmcdManager');
|
|
8
|
+
goog.require('shaka.util.ObjectUtils');
|
|
9
|
+
|
|
10
|
+
describe('CmcdManager', () => {
|
|
11
|
+
const CmcdManager = shaka.util.CmcdManager;
|
|
12
|
+
const uuidRegex =
|
|
13
|
+
'[A-F\\d]{8}-[A-F\\d]{4}-4[A-F\\d]{3}-[89AB][A-F\\d]{3}-[A-F\\d]{12}';
|
|
14
|
+
const data = {
|
|
15
|
+
'sid': 'c936730c-031e-4a73-976f-92bc34039c60',
|
|
16
|
+
'cid': 'xyz',
|
|
17
|
+
'su': false,
|
|
18
|
+
'nor': '../testing/3.m4v',
|
|
19
|
+
'nrr': '0-99',
|
|
20
|
+
'd': 6066.66,
|
|
21
|
+
'mtp': 10049,
|
|
22
|
+
'bs': true,
|
|
23
|
+
'br': 52317,
|
|
24
|
+
'v': 1,
|
|
25
|
+
'pr': 1,
|
|
26
|
+
'com.test-hello': 'world',
|
|
27
|
+
'com.test-testing': 1234,
|
|
28
|
+
'com.test-exists': true,
|
|
29
|
+
'com.test-notExists': false,
|
|
30
|
+
'com.test-token': Symbol('s'),
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
describe('Query serialization', () => {
|
|
34
|
+
it('produces correctly serialized data', () => {
|
|
35
|
+
const query = CmcdManager.toQuery(data);
|
|
36
|
+
const result = 'CMCD=br%3D52317%2Cbs%2Ccid%3D%22xyz%22%2C' +
|
|
37
|
+
'com.test-exists%2Ccom.test-hello%3D%22world%22%2C' +
|
|
38
|
+
'com.test-testing%3D1234%2Ccom.test-token%3Ds%2C' +
|
|
39
|
+
'd%3D6067%2Cmtp%3D10000%2C' +
|
|
40
|
+
'nor%3D%22..%252Ftesting%252F3.m4v%22%2C' +
|
|
41
|
+
'nrr%3D%220-99%22%2C' +
|
|
42
|
+
'sid%3D%22c936730c-031e-4a73-976f-92bc34039c60%22';
|
|
43
|
+
expect(query).toBe(result);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('Header serialization', () => {
|
|
48
|
+
it('produces all header shards', () => {
|
|
49
|
+
const header = CmcdManager.toHeaders(data);
|
|
50
|
+
expect(header).toEqual({
|
|
51
|
+
'CMCD-Object': 'br=52317,d=6067',
|
|
52
|
+
'CMCD-Request': 'com.test-exists,com.test-hello="world",' +
|
|
53
|
+
'com.test-testing=1234,com.test-token=s,mtp=10000,' +
|
|
54
|
+
'nor="..%2Ftesting%2F3.m4v",nrr="0-99"',
|
|
55
|
+
'CMCD-Session': 'cid="xyz",sid="c936730c-031e-4a73-976f-92bc34039c60"',
|
|
56
|
+
'CMCD-Status': 'bs',
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('ignores empty shards', () => {
|
|
61
|
+
expect(CmcdManager.toHeaders({br: 200})).toEqual({
|
|
62
|
+
'CMCD-Object': 'br=200',
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe('CmcdManager instance', () => {
|
|
68
|
+
const ObjectUtils = shaka.util.ObjectUtils;
|
|
69
|
+
|
|
70
|
+
const playerInterface = {
|
|
71
|
+
isLive: () => false,
|
|
72
|
+
getBandwidthEstimate: () => 10000000,
|
|
73
|
+
getBufferedInfo: () => ({
|
|
74
|
+
video: [
|
|
75
|
+
{start: 0, end: 5},
|
|
76
|
+
{start: 6, end: 31.234},
|
|
77
|
+
{start: 35, end: 40},
|
|
78
|
+
],
|
|
79
|
+
}),
|
|
80
|
+
getManifest: () => /** @type {shaka.extern.Manifest} */({
|
|
81
|
+
variants: [
|
|
82
|
+
{video: {bandwidth: 50000}},
|
|
83
|
+
{video: {bandwidth: 5000000}},
|
|
84
|
+
],
|
|
85
|
+
}),
|
|
86
|
+
getPlaybackRate: () => 1,
|
|
87
|
+
getCurrentTime: () => 10,
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const sid = '2ed2d1cd-970b-48f2-bfb3-50a79e87cfa3';
|
|
91
|
+
const config = {
|
|
92
|
+
enabled: false,
|
|
93
|
+
sessionId: '',
|
|
94
|
+
contentId: 'testing',
|
|
95
|
+
useHeaders: false,
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/** @type shaka.util.CmcdManager */
|
|
99
|
+
let cmcdManager = new CmcdManager(playerInterface, config);
|
|
100
|
+
|
|
101
|
+
const request = {
|
|
102
|
+
uris: ['https://test.com/test.mpd'],
|
|
103
|
+
method: 'GET',
|
|
104
|
+
body: null,
|
|
105
|
+
headers: {
|
|
106
|
+
testing: '1234',
|
|
107
|
+
},
|
|
108
|
+
allowCrossSiteCredentials: false,
|
|
109
|
+
retryParameters: /** @type {shaka.extern.RetryParameters} */({}),
|
|
110
|
+
licenseRequestType: null,
|
|
111
|
+
sessionId: null,
|
|
112
|
+
streamDataCallback: null,
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const manifestInfo = {
|
|
116
|
+
format: shaka.util.CmcdManager.StreamingFormat.DASH,
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const segmentInfo = {
|
|
120
|
+
type: 'video',
|
|
121
|
+
init: false,
|
|
122
|
+
duration: 3.33,
|
|
123
|
+
mimeType: 'application/mp4',
|
|
124
|
+
codecs: 'avc1.42001e',
|
|
125
|
+
bandwidth: 5234167,
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
describe('configuration', () => {
|
|
129
|
+
it('does not modify requests when disabled', () => {
|
|
130
|
+
const r = ObjectUtils.cloneObject(request);
|
|
131
|
+
|
|
132
|
+
cmcdManager.applyManifestData(r, manifestInfo);
|
|
133
|
+
expect(r.uris[0]).toBe(request.uris[0]);
|
|
134
|
+
|
|
135
|
+
cmcdManager.applySegmentData(r, segmentInfo);
|
|
136
|
+
expect(r.uris[0]).toBe(request.uris[0]);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('generates a session id if not provided', () => {
|
|
140
|
+
config.enabled = true;
|
|
141
|
+
cmcdManager = new CmcdManager(playerInterface, config);
|
|
142
|
+
|
|
143
|
+
const r = ObjectUtils.cloneObject(request);
|
|
144
|
+
|
|
145
|
+
cmcdManager.applyManifestData(r, manifestInfo);
|
|
146
|
+
const regex = new RegExp(`sid%3D%22${uuidRegex}%22`, 'i');
|
|
147
|
+
expect(regex.test(r.uris[0])).toBe(true);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
describe('query mode', () => {
|
|
152
|
+
beforeAll(() => {
|
|
153
|
+
config.sessionId = sid;
|
|
154
|
+
cmcdManager = new CmcdManager(playerInterface, config);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('modifies manifest request uris', () => {
|
|
158
|
+
const r = ObjectUtils.cloneObject(request);
|
|
159
|
+
cmcdManager.applyManifestData(r, manifestInfo);
|
|
160
|
+
const uri = 'https://test.com/test.mpd?CMCD=cid%3D%22testing%22%2C' +
|
|
161
|
+
'mtp%3D10000%2Cot%3Dm%2Csf%3Dd%2C' +
|
|
162
|
+
'sid%3D%222ed2d1cd-970b-48f2-bfb3-50a79e87cfa3%22%2Csu';
|
|
163
|
+
expect(r.uris[0]).toBe(uri);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('modifies segment request uris', () => {
|
|
167
|
+
const r = ObjectUtils.cloneObject(request);
|
|
168
|
+
cmcdManager.applySegmentData(r, segmentInfo);
|
|
169
|
+
const uri = 'https://test.com/test.mpd?CMCD=bl%3D21200%2Cbr%3D5234%2Ccid%3D%22' +
|
|
170
|
+
'testing%22%2Cd%3D3330%2Cmtp%3D10000%2Cot%3Dv%2Csf%3Dd%2C' +
|
|
171
|
+
'sid%3D%222ed2d1cd-970b-48f2-bfb3-50a79e87cfa3%22%2Cst%3Dv%2Csu%2C' +
|
|
172
|
+
'tb%3D5000';
|
|
173
|
+
expect(r.uris[0]).toBe(uri);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it('modifies text request uris', () => {
|
|
177
|
+
const r = ObjectUtils.cloneObject(request);
|
|
178
|
+
cmcdManager.applyTextData(r);
|
|
179
|
+
const uri = 'https://test.com/test.mpd?CMCD=cid%3D%22' +
|
|
180
|
+
'testing%22%2Cmtp%3D10000%2Cot%3Dc%2Csf%3Dd%2C' +
|
|
181
|
+
'sid%3D%222ed2d1cd-970b-48f2-bfb3-50a79e87cfa3%22%2Csu';
|
|
182
|
+
expect(r.uris[0]).toBe(uri);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
describe('header mode', () => {
|
|
187
|
+
beforeAll(() => {
|
|
188
|
+
config.useHeaders = true;
|
|
189
|
+
cmcdManager = new CmcdManager(playerInterface, config);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it('modifies manifest request headers', () => {
|
|
193
|
+
const r = ObjectUtils.cloneObject(request);
|
|
194
|
+
cmcdManager.applyManifestData(r, manifestInfo);
|
|
195
|
+
expect(r.headers).toEqual({
|
|
196
|
+
'testing': '1234',
|
|
197
|
+
'CMCD-Object': 'ot=m',
|
|
198
|
+
'CMCD-Request': 'mtp=10000,su',
|
|
199
|
+
'CMCD-Session': 'cid="testing",sf=d,' +
|
|
200
|
+
'sid="2ed2d1cd-970b-48f2-bfb3-50a79e87cfa3"',
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it('modifies segment request headers', () => {
|
|
205
|
+
const r = ObjectUtils.cloneObject(request);
|
|
206
|
+
cmcdManager.applySegmentData(r, segmentInfo);
|
|
207
|
+
expect(r.headers).toEqual({
|
|
208
|
+
'testing': '1234',
|
|
209
|
+
'CMCD-Object': 'br=5234,d=3330,ot=v,tb=5000',
|
|
210
|
+
'CMCD-Request': 'bl=21200,mtp=10000,su',
|
|
211
|
+
'CMCD-Session': 'cid="testing",sf=d,' +
|
|
212
|
+
'sid="2ed2d1cd-970b-48f2-bfb3-50a79e87cfa3",st=v',
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
describe('src= mode', () => {
|
|
218
|
+
it('modifies media stream uris', () => {
|
|
219
|
+
const r = cmcdManager
|
|
220
|
+
.appendSrcData('https://test.com/test.mp4', 'video/mp4');
|
|
221
|
+
const uri = 'https://test.com/test.mp4?CMCD=cid%3D%22testing%22%2C' +
|
|
222
|
+
'mtp%3D10000%2Cot%3Dav%2Csf%3Dd%2C' +
|
|
223
|
+
'sid%3D%222ed2d1cd-970b-48f2-bfb3-50a79e87cfa3%22%2Csu';
|
|
224
|
+
expect(r).toBe(uri);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('modifies manifest stream uris', () => {
|
|
228
|
+
const r = cmcdManager
|
|
229
|
+
.appendSrcData('https://test.com/test.m3u8', 'application/x-mpegurl');
|
|
230
|
+
const uri = 'https://test.com/test.m3u8?CMCD=cid%3D%22testing%22%2C' +
|
|
231
|
+
'mtp%3D10000%2Cot%3Dm%2Csf%3Dd%2C' +
|
|
232
|
+
'sid%3D%222ed2d1cd-970b-48f2-bfb3-50a79e87cfa3%22%2Csu';
|
|
233
|
+
expect(r).toBe(uri);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
it('modifies text track uris', () => {
|
|
237
|
+
const r = cmcdManager.appendTextTrackData('https://test.com/test.vtt');
|
|
238
|
+
const uri = 'https://test.com/test.vtt?CMCD=cid%3D%22testing%22%2C' +
|
|
239
|
+
'mtp%3D10000%2Cot%3Dc%2Csf%3Dd%2C' +
|
|
240
|
+
'sid%3D%222ed2d1cd-970b-48f2-bfb3-50a79e87cfa3%22%2Csu';
|
|
241
|
+
expect(r).toBe(uri);
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
describe('adheres to the spec', () => {
|
|
246
|
+
beforeAll(() => {
|
|
247
|
+
cmcdManager.setBuffering(false);
|
|
248
|
+
cmcdManager.setBuffering(true);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it('sends bs only once', () => {
|
|
252
|
+
let r = ObjectUtils.cloneObject(request);
|
|
253
|
+
cmcdManager.applySegmentData(r, segmentInfo);
|
|
254
|
+
expect(r.headers['CMCD-Status']).toContain('bs');
|
|
255
|
+
|
|
256
|
+
r = ObjectUtils.cloneObject(request);
|
|
257
|
+
cmcdManager.applySegmentData(r, segmentInfo);
|
|
258
|
+
expect(r.headers['CMCD-Status']).not.toContain('bs');
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
it('sends su until buffering is complete', () => {
|
|
262
|
+
let r = ObjectUtils.cloneObject(request);
|
|
263
|
+
cmcdManager.applySegmentData(r, segmentInfo);
|
|
264
|
+
expect(r.headers['CMCD-Request']).toContain(',su');
|
|
265
|
+
|
|
266
|
+
r = ObjectUtils.cloneObject(request);
|
|
267
|
+
cmcdManager.applySegmentData(r, segmentInfo);
|
|
268
|
+
expect(r.headers['CMCD-Request']).toContain(',su');
|
|
269
|
+
|
|
270
|
+
cmcdManager.setBuffering(false);
|
|
271
|
+
r = ObjectUtils.cloneObject(request);
|
|
272
|
+
cmcdManager.applySegmentData(r, segmentInfo);
|
|
273
|
+
expect(r.headers['CMCD-Request']).not.toContain(',su');
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
});
|