shaka-player 4.4.2 → 4.4.3
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/CHANGELOG.md +23 -0
- package/demo/common/asset.js +5 -0
- package/demo/common/assets.js +20 -5
- package/demo/common/message_ids.js +1 -1
- package/demo/locales/en.json +2 -1
- package/demo/locales/source.json +5 -1
- package/demo/main.js +1 -1
- package/demo/search.js +3 -3
- package/dist/demo.compiled.debug.js +72 -70
- package/dist/demo.compiled.debug.map +3 -3
- package/dist/demo.compiled.js +72 -70
- package/dist/demo.compiled.map +3 -3
- package/dist/locales.js +30 -30
- package/dist/receiver.compiled.debug.js +38 -36
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +38 -36
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.d.ts +222 -1
- package/dist/shaka-player.compiled.debug.d.ts +222 -1
- package/dist/shaka-player.compiled.debug.externs.js +271 -1
- package/dist/shaka-player.compiled.debug.js +233 -228
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.externs.js +271 -1
- package/dist/shaka-player.compiled.js +1035 -1028
- package/dist/shaka-player.compiled.map +3 -3
- package/dist/shaka-player.ui.d.ts +222 -1
- package/dist/shaka-player.ui.debug.d.ts +222 -1
- package/dist/shaka-player.ui.debug.externs.js +271 -1
- package/dist/shaka-player.ui.debug.js +256 -251
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.externs.js +271 -1
- package/dist/shaka-player.ui.js +1162 -1155
- package/dist/shaka-player.ui.map +3 -3
- package/docs/tutorials/offline.md +1 -1
- package/lib/dash/dash_parser.js +4 -1
- package/lib/hls/hls_parser.js +60 -24
- package/lib/media/segment_index.js +4 -4
- package/lib/media/segment_reference.js +6 -1
- package/lib/media/streaming_engine.js +14 -24
- package/lib/player.js +1 -1
- package/lib/text/cue.js +47 -47
- package/lib/text/vtt_text_parser.js +2 -2
- package/lib/util/cmcd_manager.js +6 -1
- package/lib/util/manifest_parser_utils.js +10 -4
- package/lib/util/platform.js +14 -0
- package/lib/util/ts_parser.js +3 -3
- package/package.json +1 -1
- package/test/dash/dash_parser_manifest_unit.js +5 -0
- package/test/dash/dash_parser_segment_base_unit.js +5 -0
- package/test/dash/dash_parser_segment_list_unit.js +21 -17
- package/test/dash/dash_parser_segment_template_unit.js +47 -0
- package/test/hls/hls_live_unit.js +33 -0
- package/test/hls/hls_parser_unit.js +2 -57
- package/test/test/util/dash_parser_util.js +16 -7
- package/test/text/vtt_text_parser_unit.js +2 -17
- package/test/transmuxer/transmuxer_integration.js +4 -4
- package/test/util/ts_parser_unit.js +1 -1
package/lib/text/cue.js
CHANGED
|
@@ -26,7 +26,7 @@ shaka.text.Cue = class {
|
|
|
26
26
|
* The start time of the cue in seconds, relative to the start of the
|
|
27
27
|
* presentation.
|
|
28
28
|
* @type {number}
|
|
29
|
-
* @
|
|
29
|
+
* @export
|
|
30
30
|
*/
|
|
31
31
|
this.startTime = startTime;
|
|
32
32
|
|
|
@@ -34,7 +34,7 @@ shaka.text.Cue = class {
|
|
|
34
34
|
* The end time of the cue in seconds, relative to the start of the
|
|
35
35
|
* presentation.
|
|
36
36
|
* @type {number}
|
|
37
|
-
* @
|
|
37
|
+
* @export
|
|
38
38
|
*/
|
|
39
39
|
this.endTime = endTime;
|
|
40
40
|
|
|
@@ -42,7 +42,7 @@ shaka.text.Cue = class {
|
|
|
42
42
|
* The text payload of the cue. If nestedCues is non-empty, this should be
|
|
43
43
|
* empty. Top-level block containers should have no payload of their own.
|
|
44
44
|
* @type {string}
|
|
45
|
-
* @
|
|
45
|
+
* @export
|
|
46
46
|
*/
|
|
47
47
|
this.payload = payload;
|
|
48
48
|
|
|
@@ -50,7 +50,7 @@ shaka.text.Cue = class {
|
|
|
50
50
|
* The region to render the cue into. Only supported on top-level cues,
|
|
51
51
|
* because nested cues are inline elements.
|
|
52
52
|
* @type {shaka.text.CueRegion}
|
|
53
|
-
* @
|
|
53
|
+
* @export
|
|
54
54
|
*/
|
|
55
55
|
this.region = new shaka.text.CueRegion();
|
|
56
56
|
|
|
@@ -58,42 +58,42 @@ shaka.text.Cue = class {
|
|
|
58
58
|
* The indent (in percent) of the cue box in the direction defined by the
|
|
59
59
|
* writing direction.
|
|
60
60
|
* @type {?number}
|
|
61
|
-
* @
|
|
61
|
+
* @export
|
|
62
62
|
*/
|
|
63
63
|
this.position = null;
|
|
64
64
|
|
|
65
65
|
/**
|
|
66
66
|
* Position alignment of the cue.
|
|
67
67
|
* @type {shaka.text.Cue.positionAlign}
|
|
68
|
-
* @
|
|
68
|
+
* @export
|
|
69
69
|
*/
|
|
70
70
|
this.positionAlign = Cue.positionAlign.AUTO;
|
|
71
71
|
|
|
72
72
|
/**
|
|
73
73
|
* Size of the cue box (in percents), where 0 means "auto".
|
|
74
74
|
* @type {number}
|
|
75
|
-
* @
|
|
75
|
+
* @export
|
|
76
76
|
*/
|
|
77
77
|
this.size = 0;
|
|
78
78
|
|
|
79
79
|
/**
|
|
80
80
|
* Alignment of the text inside the cue box.
|
|
81
81
|
* @type {shaka.text.Cue.textAlign}
|
|
82
|
-
* @
|
|
82
|
+
* @export
|
|
83
83
|
*/
|
|
84
84
|
this.textAlign = Cue.textAlign.CENTER;
|
|
85
85
|
|
|
86
86
|
/**
|
|
87
87
|
* Text direction of the cue.
|
|
88
88
|
* @type {shaka.text.Cue.direction}
|
|
89
|
-
* @
|
|
89
|
+
* @export
|
|
90
90
|
*/
|
|
91
91
|
this.direction = Cue.direction.HORIZONTAL_LEFT_TO_RIGHT;
|
|
92
92
|
|
|
93
93
|
/**
|
|
94
94
|
* Text writing mode of the cue.
|
|
95
95
|
* @type {shaka.text.Cue.writingMode}
|
|
96
|
-
* @
|
|
96
|
+
* @export
|
|
97
97
|
*/
|
|
98
98
|
this.writingMode = Cue.writingMode.HORIZONTAL_TOP_TO_BOTTOM;
|
|
99
99
|
|
|
@@ -101,7 +101,7 @@ shaka.text.Cue = class {
|
|
|
101
101
|
* The way to interpret line field. (Either as an integer line number or
|
|
102
102
|
* percentage from the display box).
|
|
103
103
|
* @type {shaka.text.Cue.lineInterpretation}
|
|
104
|
-
* @
|
|
104
|
+
* @export
|
|
105
105
|
*/
|
|
106
106
|
this.lineInterpretation = Cue.lineInterpretation.LINE_NUMBER;
|
|
107
107
|
|
|
@@ -109,7 +109,7 @@ shaka.text.Cue = class {
|
|
|
109
109
|
* The offset from the display box in either number of lines or
|
|
110
110
|
* percentage depending on the value of lineInterpretation.
|
|
111
111
|
* @type {?number}
|
|
112
|
-
* @
|
|
112
|
+
* @export
|
|
113
113
|
*/
|
|
114
114
|
this.line = null;
|
|
115
115
|
|
|
@@ -118,7 +118,7 @@ shaka.text.Cue = class {
|
|
|
118
118
|
* (e.g. '100px'/'100em'). If not specified, this should be no less than
|
|
119
119
|
* the largest font size applied to the text in the cue.
|
|
120
120
|
* @type {string}.
|
|
121
|
-
* @
|
|
121
|
+
* @export
|
|
122
122
|
*/
|
|
123
123
|
this.lineHeight = '';
|
|
124
124
|
|
|
@@ -132,7 +132,7 @@ shaka.text.Cue = class {
|
|
|
132
132
|
* (for vertical growing right), or left side (for vertical growing left) is
|
|
133
133
|
* aligned at the line.
|
|
134
134
|
* @type {shaka.text.Cue.lineAlign}
|
|
135
|
-
* @
|
|
135
|
+
* @export
|
|
136
136
|
*/
|
|
137
137
|
this.lineAlign = Cue.lineAlign.START;
|
|
138
138
|
|
|
@@ -141,84 +141,84 @@ shaka.text.Cue = class {
|
|
|
141
141
|
* 'BEFORE' means displaying the captions at the top of the text display
|
|
142
142
|
* container box, 'CENTER' means in the middle, 'AFTER' means at the bottom.
|
|
143
143
|
* @type {shaka.text.Cue.displayAlign}
|
|
144
|
-
* @
|
|
144
|
+
* @export
|
|
145
145
|
*/
|
|
146
146
|
this.displayAlign = Cue.displayAlign.AFTER;
|
|
147
147
|
|
|
148
148
|
/**
|
|
149
149
|
* Text color as a CSS color, e.g. "#FFFFFF" or "white".
|
|
150
150
|
* @type {string}
|
|
151
|
-
* @
|
|
151
|
+
* @export
|
|
152
152
|
*/
|
|
153
153
|
this.color = '';
|
|
154
154
|
|
|
155
155
|
/**
|
|
156
156
|
* Text background color as a CSS color, e.g. "#FFFFFF" or "white".
|
|
157
157
|
* @type {string}
|
|
158
|
-
* @
|
|
158
|
+
* @export
|
|
159
159
|
*/
|
|
160
160
|
this.backgroundColor = '';
|
|
161
161
|
|
|
162
162
|
/**
|
|
163
163
|
* The URL of the background image, e.g. "data:[mime type];base64,[data]".
|
|
164
164
|
* @type {string}
|
|
165
|
-
* @
|
|
165
|
+
* @export
|
|
166
166
|
*/
|
|
167
167
|
this.backgroundImage = '';
|
|
168
168
|
|
|
169
169
|
/**
|
|
170
170
|
* The border around this cue as a CSS border.
|
|
171
171
|
* @type {string}
|
|
172
|
-
* @
|
|
172
|
+
* @export
|
|
173
173
|
*/
|
|
174
174
|
this.border = '';
|
|
175
175
|
|
|
176
176
|
/**
|
|
177
177
|
* Text font size in px or em (e.g. '100px'/'100em').
|
|
178
178
|
* @type {string}
|
|
179
|
-
* @
|
|
179
|
+
* @export
|
|
180
180
|
*/
|
|
181
181
|
this.fontSize = '';
|
|
182
182
|
|
|
183
183
|
/**
|
|
184
184
|
* Text font weight. Either normal or bold.
|
|
185
185
|
* @type {shaka.text.Cue.fontWeight}
|
|
186
|
-
* @
|
|
186
|
+
* @export
|
|
187
187
|
*/
|
|
188
188
|
this.fontWeight = Cue.fontWeight.NORMAL;
|
|
189
189
|
|
|
190
190
|
/**
|
|
191
191
|
* Text font style. Normal, italic or oblique.
|
|
192
192
|
* @type {shaka.text.Cue.fontStyle}
|
|
193
|
-
* @
|
|
193
|
+
* @export
|
|
194
194
|
*/
|
|
195
195
|
this.fontStyle = Cue.fontStyle.NORMAL;
|
|
196
196
|
|
|
197
197
|
/**
|
|
198
198
|
* Text font family.
|
|
199
199
|
* @type {string}
|
|
200
|
-
* @
|
|
200
|
+
* @export
|
|
201
201
|
*/
|
|
202
202
|
this.fontFamily = '';
|
|
203
203
|
|
|
204
204
|
/**
|
|
205
205
|
* Text letter spacing as a CSS letter-spacing value.
|
|
206
206
|
* @type {string}
|
|
207
|
-
* @
|
|
207
|
+
* @export
|
|
208
208
|
*/
|
|
209
209
|
this.letterSpacing = '';
|
|
210
210
|
|
|
211
211
|
/**
|
|
212
212
|
* Text line padding as a CSS line-padding value.
|
|
213
213
|
* @type {string}
|
|
214
|
-
* @
|
|
214
|
+
* @export
|
|
215
215
|
*/
|
|
216
216
|
this.linePadding = '';
|
|
217
217
|
|
|
218
218
|
/**
|
|
219
219
|
* Opacity of the cue element, from 0-1.
|
|
220
220
|
* @type {number}
|
|
221
|
-
* @
|
|
221
|
+
* @export
|
|
222
222
|
*/
|
|
223
223
|
this.opacity = 1;
|
|
224
224
|
|
|
@@ -226,42 +226,42 @@ shaka.text.Cue = class {
|
|
|
226
226
|
* Text decoration. A combination of underline, overline
|
|
227
227
|
* and line through. Empty array means no decoration.
|
|
228
228
|
* @type {!Array.<!shaka.text.Cue.textDecoration>}
|
|
229
|
-
* @
|
|
229
|
+
* @export
|
|
230
230
|
*/
|
|
231
231
|
this.textDecoration = [];
|
|
232
232
|
|
|
233
233
|
/**
|
|
234
234
|
* Text shadow color as a CSS text-shadow value.
|
|
235
235
|
* @type {string}
|
|
236
|
-
* @
|
|
236
|
+
* @export
|
|
237
237
|
*/
|
|
238
238
|
this.textShadow = '';
|
|
239
239
|
|
|
240
240
|
/**
|
|
241
241
|
* Text stroke color as a CSS color, e.g. "#FFFFFF" or "white".
|
|
242
242
|
* @type {string}
|
|
243
|
-
* @
|
|
243
|
+
* @export
|
|
244
244
|
*/
|
|
245
245
|
this.textStrokeColor = '';
|
|
246
246
|
|
|
247
247
|
/**
|
|
248
248
|
* Text stroke width as a CSS stroke-width value.
|
|
249
249
|
* @type {string}
|
|
250
|
-
* @
|
|
250
|
+
* @export
|
|
251
251
|
*/
|
|
252
252
|
this.textStrokeWidth = '';
|
|
253
253
|
|
|
254
254
|
/**
|
|
255
255
|
* Whether or not line wrapping should be applied to the cue.
|
|
256
256
|
* @type {boolean}
|
|
257
|
-
* @
|
|
257
|
+
* @export
|
|
258
258
|
*/
|
|
259
259
|
this.wrapLine = true;
|
|
260
260
|
|
|
261
261
|
/**
|
|
262
262
|
* Id of the cue.
|
|
263
263
|
* @type {string}
|
|
264
|
-
* @
|
|
264
|
+
* @export
|
|
265
265
|
*/
|
|
266
266
|
this.id = '';
|
|
267
267
|
|
|
@@ -270,7 +270,7 @@ shaka.text.Cue = class {
|
|
|
270
270
|
* Top-level cues are blocks, and nested cues are inline elements.
|
|
271
271
|
* Cues can be nested arbitrarily deeply.
|
|
272
272
|
* @type {!Array.<!shaka.text.Cue>}
|
|
273
|
-
* @
|
|
273
|
+
* @export
|
|
274
274
|
*/
|
|
275
275
|
this.nestedCues = [];
|
|
276
276
|
|
|
@@ -280,7 +280,7 @@ shaka.text.Cue = class {
|
|
|
280
280
|
* in a TTML file. This controls the flow of the final cues; any nested cues
|
|
281
281
|
* within an "isContainer" cue will be laid out as separate lines.
|
|
282
282
|
* @type {boolean}
|
|
283
|
-
* @
|
|
283
|
+
* @export
|
|
284
284
|
*/
|
|
285
285
|
this.isContainer = false;
|
|
286
286
|
|
|
@@ -288,7 +288,7 @@ shaka.text.Cue = class {
|
|
|
288
288
|
* Whether or not the cue only acts as a line break between two nested cues.
|
|
289
289
|
* Should only appear in nested cues.
|
|
290
290
|
* @type {boolean}
|
|
291
|
-
* @
|
|
291
|
+
* @export
|
|
292
292
|
*/
|
|
293
293
|
this.lineBreak = false;
|
|
294
294
|
|
|
@@ -297,7 +297,7 @@ shaka.text.Cue = class {
|
|
|
297
297
|
* Region area is divided.
|
|
298
298
|
*
|
|
299
299
|
* @type {{ columns: number, rows: number }}
|
|
300
|
-
* @
|
|
300
|
+
* @export
|
|
301
301
|
*/
|
|
302
302
|
this.cellResolution = {
|
|
303
303
|
columns: 32,
|
|
@@ -551,7 +551,7 @@ shaka.text.CueRegion = class {
|
|
|
551
551
|
/**
|
|
552
552
|
* Region identifier.
|
|
553
553
|
* @type {string}
|
|
554
|
-
* @
|
|
554
|
+
* @export
|
|
555
555
|
*/
|
|
556
556
|
this.id = '';
|
|
557
557
|
|
|
@@ -559,7 +559,7 @@ shaka.text.CueRegion = class {
|
|
|
559
559
|
* The X offset to start the rendering area in viewportAnchorUnits of the
|
|
560
560
|
* video width.
|
|
561
561
|
* @type {number}
|
|
562
|
-
* @
|
|
562
|
+
* @export
|
|
563
563
|
*/
|
|
564
564
|
this.viewportAnchorX = 0;
|
|
565
565
|
|
|
@@ -567,7 +567,7 @@ shaka.text.CueRegion = class {
|
|
|
567
567
|
* The X offset to start the rendering area in viewportAnchorUnits of the
|
|
568
568
|
* video height.
|
|
569
569
|
* @type {number}
|
|
570
|
-
* @
|
|
570
|
+
* @export
|
|
571
571
|
*/
|
|
572
572
|
this.viewportAnchorY = 0;
|
|
573
573
|
|
|
@@ -575,7 +575,7 @@ shaka.text.CueRegion = class {
|
|
|
575
575
|
* The X offset to start the rendering area in percentage (0-100) of this
|
|
576
576
|
* region width.
|
|
577
577
|
* @type {number}
|
|
578
|
-
* @
|
|
578
|
+
* @export
|
|
579
579
|
*/
|
|
580
580
|
this.regionAnchorX = 0;
|
|
581
581
|
|
|
@@ -583,42 +583,42 @@ shaka.text.CueRegion = class {
|
|
|
583
583
|
* The Y offset to start the rendering area in percentage (0-100) of the
|
|
584
584
|
* region height.
|
|
585
585
|
* @type {number}
|
|
586
|
-
* @
|
|
586
|
+
* @export
|
|
587
587
|
*/
|
|
588
588
|
this.regionAnchorY = 0;
|
|
589
589
|
|
|
590
590
|
/**
|
|
591
591
|
* The width of the rendering area in widthUnits.
|
|
592
592
|
* @type {number}
|
|
593
|
-
* @
|
|
593
|
+
* @export
|
|
594
594
|
*/
|
|
595
595
|
this.width = 100;
|
|
596
596
|
|
|
597
597
|
/**
|
|
598
598
|
* The width of the rendering area in heightUnits.
|
|
599
599
|
* @type {number}
|
|
600
|
-
* @
|
|
600
|
+
* @export
|
|
601
601
|
*/
|
|
602
602
|
this.height = 100;
|
|
603
603
|
|
|
604
604
|
/**
|
|
605
605
|
* The units (percentage, pixels or lines) the region height is in.
|
|
606
606
|
* @type {shaka.text.CueRegion.units}
|
|
607
|
-
* @
|
|
607
|
+
* @export
|
|
608
608
|
*/
|
|
609
609
|
this.heightUnits = CueRegion.units.PERCENTAGE;
|
|
610
610
|
|
|
611
611
|
/**
|
|
612
612
|
* The units (percentage or pixels) the region width is in.
|
|
613
613
|
* @type {shaka.text.CueRegion.units}
|
|
614
|
-
* @
|
|
614
|
+
* @export
|
|
615
615
|
*/
|
|
616
616
|
this.widthUnits = CueRegion.units.PERCENTAGE;
|
|
617
617
|
|
|
618
618
|
/**
|
|
619
619
|
* The units (percentage or pixels) the region viewportAnchors are in.
|
|
620
620
|
* @type {shaka.text.CueRegion.units}
|
|
621
|
-
* @
|
|
621
|
+
* @export
|
|
622
622
|
*/
|
|
623
623
|
this.viewportAnchorUnits = CueRegion.units.PERCENTAGE;
|
|
624
624
|
|
|
@@ -628,7 +628,7 @@ shaka.text.CueRegion = class {
|
|
|
628
628
|
* region up. Otherwise (scroll=NONE) cues will stay fixed at the location
|
|
629
629
|
* they were first painted in.
|
|
630
630
|
* @type {shaka.text.CueRegion.scrollMode}
|
|
631
|
-
* @
|
|
631
|
+
* @export
|
|
632
632
|
*/
|
|
633
633
|
this.scroll = CueRegion.scrollMode.NONE;
|
|
634
634
|
}
|
|
@@ -417,6 +417,8 @@ shaka.text.VttTextParser = class {
|
|
|
417
417
|
cue = new shaka.text.Cue(start, end, '');
|
|
418
418
|
}
|
|
419
419
|
|
|
420
|
+
VttTextParser.parseCueStyles(payload, cue, styles);
|
|
421
|
+
|
|
420
422
|
// Parse optional settings.
|
|
421
423
|
parser.skipWhitespace();
|
|
422
424
|
let word = parser.readWord();
|
|
@@ -430,8 +432,6 @@ shaka.text.VttTextParser = class {
|
|
|
430
432
|
word = parser.readWord();
|
|
431
433
|
}
|
|
432
434
|
|
|
433
|
-
VttTextParser.parseCueStyles(payload, cue, styles);
|
|
434
|
-
|
|
435
435
|
if (id != null) {
|
|
436
436
|
cue.id = id;
|
|
437
437
|
}
|
package/lib/util/cmcd_manager.js
CHANGED
|
@@ -406,12 +406,17 @@ shaka.util.CmcdManager = class {
|
|
|
406
406
|
* @private
|
|
407
407
|
*/
|
|
408
408
|
getObjectTypeFromMimeType_(mimeType) {
|
|
409
|
-
switch (mimeType) {
|
|
409
|
+
switch (mimeType.toLowerCase()) {
|
|
410
410
|
case 'video/webm':
|
|
411
411
|
case 'video/mp4':
|
|
412
|
+
case 'video/mpeg':
|
|
413
|
+
case 'video/mp2t':
|
|
412
414
|
return shaka.util.CmcdManager.ObjectType.MUXED;
|
|
413
415
|
|
|
414
416
|
case 'application/x-mpegurl':
|
|
417
|
+
case 'application/vnd.apple.mpegurl':
|
|
418
|
+
case 'application/dash+xml':
|
|
419
|
+
case 'video/vnd.mpeg.dash.mpd':
|
|
415
420
|
return shaka.util.CmcdManager.ObjectType.MANIFEST;
|
|
416
421
|
|
|
417
422
|
default:
|
|
@@ -32,13 +32,19 @@ shaka.util.ManifestParserUtils = class {
|
|
|
32
32
|
return baseUris;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
if (baseUris.length == 1 && relativeUris.length == 1) {
|
|
36
|
+
const baseUri = new goog.Uri(baseUris[0]);
|
|
37
|
+
const relativeUri = new goog.Uri(relativeUris[0]);
|
|
38
|
+
return [baseUri.resolve(relativeUri).toString()];
|
|
39
|
+
}
|
|
40
|
+
|
|
35
41
|
const relativeAsGoog = relativeUris.map((uri) => new goog.Uri(uri));
|
|
36
42
|
// Resolve each URI relative to each base URI, creating an Array of Arrays.
|
|
37
43
|
// Then flatten the Arrays into a single Array.
|
|
38
|
-
return baseUris.map((uri) =>
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
44
|
+
return baseUris.map((uri) => {
|
|
45
|
+
const base = new goog.Uri(uri);
|
|
46
|
+
return relativeAsGoog.map((i) => base.resolve(i).toString());
|
|
47
|
+
}).reduce(Functional.collapseArrays, []);
|
|
42
48
|
}
|
|
43
49
|
|
|
44
50
|
|
package/lib/util/platform.js
CHANGED
|
@@ -368,6 +368,20 @@ shaka.util.Platform = class {
|
|
|
368
368
|
return navigator.platform.toLowerCase().includes('mac');
|
|
369
369
|
}
|
|
370
370
|
|
|
371
|
+
/**
|
|
372
|
+
* Return true if the platform is a Windows, regardless of the browser.
|
|
373
|
+
*
|
|
374
|
+
* @return {boolean}
|
|
375
|
+
*/
|
|
376
|
+
static isWindows() {
|
|
377
|
+
// Try the newer standard first.
|
|
378
|
+
if (navigator.userAgentData && navigator.userAgentData.platform) {
|
|
379
|
+
return navigator.userAgentData.platform.toLowerCase() == 'windows';
|
|
380
|
+
}
|
|
381
|
+
// Fall back to the old API, with less strict matching.
|
|
382
|
+
return navigator.platform.toLowerCase().includes('windows');
|
|
383
|
+
}
|
|
384
|
+
|
|
371
385
|
/**
|
|
372
386
|
* Check if the user agent contains a key. This is the best way we know of
|
|
373
387
|
* right now to detect platforms. If there is a better way, please send a
|
package/lib/util/ts_parser.js
CHANGED
|
@@ -129,15 +129,15 @@ shaka.util.TsParser = class {
|
|
|
129
129
|
// for example
|
|
130
130
|
// NOTE this is only the PID of the track as found in TS,
|
|
131
131
|
// but we are not using this for MP4 track IDs.
|
|
132
|
-
if (
|
|
132
|
+
if (parsedPIDs.video != -1) {
|
|
133
133
|
this.videoPid_ = parsedPIDs.video;
|
|
134
134
|
this.videoCodec_ = parsedPIDs.videoCodec;
|
|
135
135
|
}
|
|
136
|
-
if (
|
|
136
|
+
if (parsedPIDs.audio != -1) {
|
|
137
137
|
this.audioPid_ = parsedPIDs.audio;
|
|
138
138
|
this.audioCodec_ = parsedPIDs.audioCodec;
|
|
139
139
|
}
|
|
140
|
-
if (
|
|
140
|
+
if (parsedPIDs.id3 != -1) {
|
|
141
141
|
this.id3Pid_ = parsedPIDs.id3;
|
|
142
142
|
}
|
|
143
143
|
|
package/package.json
CHANGED
|
@@ -43,6 +43,11 @@ describe('DashParser SegmentBase', () => {
|
|
|
43
43
|
};
|
|
44
44
|
});
|
|
45
45
|
|
|
46
|
+
afterEach(() => {
|
|
47
|
+
// Dash parser stop is synchronous.
|
|
48
|
+
parser.stop();
|
|
49
|
+
});
|
|
50
|
+
|
|
46
51
|
it('requests init data for WebM', async () => {
|
|
47
52
|
const source = [
|
|
48
53
|
'<MPD mediaPresentationDuration="PT75S">',
|
|
@@ -351,24 +351,28 @@ describe('DashParser SegmentList', () => {
|
|
|
351
351
|
updateDuration: () => {},
|
|
352
352
|
newDrmInfo: (stream) => {},
|
|
353
353
|
};
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
354
|
+
try {
|
|
355
|
+
const manifest = await dashParser.start('dummy://foo', playerInterface);
|
|
356
|
+
const stream = manifest.variants[0].video;
|
|
357
|
+
await stream.createSegmentIndex();
|
|
358
|
+
goog.asserts.assert(stream.segmentIndex, 'Expected index to be created');
|
|
358
359
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
360
|
+
// Don't use Dash.testSegmentIndex since it uses SegmentIndex.find, which
|
|
361
|
+
// doesn't reproduce this issue. We want to use Array.from which uses
|
|
362
|
+
// the iterator.
|
|
363
|
+
const expected = [
|
|
364
|
+
ManifestParser.makeReference('s1.mp4', 0, 10, baseUri),
|
|
365
|
+
ManifestParser.makeReference('s2.mp4', 10, 20, baseUri),
|
|
366
|
+
ManifestParser.makeReference('s3.mp4', 20, 30, baseUri),
|
|
366
367
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
368
|
+
ManifestParser.makeReference('s3.mp4', 30, 40, baseUri),
|
|
369
|
+
ManifestParser.makeReference('s4.mp4', 40, 50, baseUri),
|
|
370
|
+
ManifestParser.makeReference('s5.mp4', 50, 60, baseUri),
|
|
371
|
+
];
|
|
372
|
+
const actual = Array.from(stream.segmentIndex);
|
|
373
|
+
expect(actual).toEqual(expected);
|
|
374
|
+
} finally {
|
|
375
|
+
dashParser.stop();
|
|
376
|
+
}
|
|
373
377
|
});
|
|
374
378
|
});
|
|
@@ -52,6 +52,11 @@ describe('DashParser SegmentTemplate', () => {
|
|
|
52
52
|
};
|
|
53
53
|
});
|
|
54
54
|
|
|
55
|
+
afterEach(() => {
|
|
56
|
+
// Dash parser stop is synchronous.
|
|
57
|
+
parser.stop();
|
|
58
|
+
});
|
|
59
|
+
|
|
55
60
|
shaka.test.Dash.makeTimelineTests(
|
|
56
61
|
'SegmentTemplate', 'media="s$Number$.mp4"', []);
|
|
57
62
|
|
|
@@ -670,6 +675,48 @@ describe('DashParser SegmentTemplate', () => {
|
|
|
670
675
|
expect(pos).toBe(1);
|
|
671
676
|
});
|
|
672
677
|
|
|
678
|
+
it('finds correct position in multiperiod content', async () => {
|
|
679
|
+
const source = [
|
|
680
|
+
'<MPD type="static" availabilityStartTime="1970-01-01T00:00:00Z">',
|
|
681
|
+
' <Period duration="PT30S">',
|
|
682
|
+
' <AdaptationSet mimeType="video/mp4">',
|
|
683
|
+
' <Representation bandwidth="500">',
|
|
684
|
+
' <BaseURL>http://example.com</BaseURL>',
|
|
685
|
+
' <SegmentTemplate startNumber="0"',
|
|
686
|
+
' media="$Number$-$Time$-$Bandwidth$.mp4">',
|
|
687
|
+
' <SegmentTimeline>',
|
|
688
|
+
' <S t="0" d="5" r="6" />',
|
|
689
|
+
' </SegmentTimeline>',
|
|
690
|
+
' </SegmentTemplate>',
|
|
691
|
+
' </Representation>',
|
|
692
|
+
' </AdaptationSet>',
|
|
693
|
+
' </Period>',
|
|
694
|
+
' <Period duration="PT30S">',
|
|
695
|
+
' <AdaptationSet mimeType="video/mp4">',
|
|
696
|
+
' <Representation bandwidth="500">',
|
|
697
|
+
' <BaseURL>http://example.com</BaseURL>',
|
|
698
|
+
' <SegmentTemplate startNumber="6"',
|
|
699
|
+
' media="$Number$-$Time$-$Bandwidth$.mp4">',
|
|
700
|
+
' <SegmentTimeline>',
|
|
701
|
+
' <S t="0" d="5" r="6" />',
|
|
702
|
+
' </SegmentTimeline>',
|
|
703
|
+
' </SegmentTemplate>',
|
|
704
|
+
' </Representation>',
|
|
705
|
+
' </AdaptationSet>',
|
|
706
|
+
' </Period>',
|
|
707
|
+
'</MPD>',
|
|
708
|
+
].join('\n');
|
|
709
|
+
|
|
710
|
+
fakeNetEngine.setResponseText('dummy://foo', source);
|
|
711
|
+
const manifest = await parser.start('dummy://foo', playerInterface);
|
|
712
|
+
const stream = manifest.variants[0].video;
|
|
713
|
+
await stream.createSegmentIndex();
|
|
714
|
+
|
|
715
|
+
// simulate a seek into the second period
|
|
716
|
+
const segmentIterator = stream.segmentIndex.getIteratorForTime(42);
|
|
717
|
+
const ref = segmentIterator.next().value;
|
|
718
|
+
expect(ref.startTime).toBe(40);
|
|
719
|
+
});
|
|
673
720
|
|
|
674
721
|
it('returns null if time === last end time', async () => {
|
|
675
722
|
const info = makeTemplateInfo(makeRanges(0, 2.0, 2));
|
|
@@ -540,10 +540,43 @@ describe('HlsParser live', () => {
|
|
|
540
540
|
|
|
541
541
|
it('sets 3 times target duration as presentation delay if not configured',
|
|
542
542
|
async () => {
|
|
543
|
+
const media = [
|
|
544
|
+
'#EXTM3U\n',
|
|
545
|
+
'#EXT-X-TARGETDURATION:5\n',
|
|
546
|
+
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
|
|
547
|
+
'#EXT-X-MEDIA-SEQUENCE:0\n',
|
|
548
|
+
'#EXTINF:2,\n',
|
|
549
|
+
'main.mp4\n',
|
|
550
|
+
'#EXTINF:2,\n',
|
|
551
|
+
'main.mp4\n',
|
|
552
|
+
'#EXTINF:2,\n',
|
|
553
|
+
'main.mp4\n',
|
|
554
|
+
'#EXTINF:2,\n',
|
|
555
|
+
'main.mp4\n',
|
|
556
|
+
'#EXTINF:2,\n',
|
|
557
|
+
'main.mp4\n',
|
|
558
|
+
'#EXTINF:2,\n',
|
|
559
|
+
'main.mp4\n',
|
|
560
|
+
].join('');
|
|
543
561
|
const manifest = await testInitialManifest(master, media);
|
|
544
562
|
expect(manifest.presentationTimeline.getDelay()).toBe(15);
|
|
545
563
|
});
|
|
546
564
|
|
|
565
|
+
it('sets 1 times target duration as presentation delay if there are not enough segments', async () => { // eslint-disable-line max-len
|
|
566
|
+
const media = [
|
|
567
|
+
'#EXTM3U\n',
|
|
568
|
+
'#EXT-X-TARGETDURATION:5\n',
|
|
569
|
+
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
|
|
570
|
+
'#EXT-X-MEDIA-SEQUENCE:0\n',
|
|
571
|
+
'#EXTINF:2,\n',
|
|
572
|
+
'main.mp4\n',
|
|
573
|
+
'#EXTINF:2,\n',
|
|
574
|
+
'main.mp4\n',
|
|
575
|
+
].join('');
|
|
576
|
+
const manifest = await testInitialManifest(master, media);
|
|
577
|
+
expect(manifest.presentationTimeline.getDelay()).toBe(5);
|
|
578
|
+
});
|
|
579
|
+
|
|
547
580
|
it('sets presentation delay if defined', async () => {
|
|
548
581
|
const media = [
|
|
549
582
|
'#EXTM3U\n',
|