shaka-player 4.6.11 → 4.6.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AUTHORS +1 -0
- package/CHANGELOG.md +29 -0
- package/CONTRIBUTORS +1 -0
- package/README.md +14 -12
- package/demo/common/assets.js +3 -1
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +5 -5
- package/dist/demo.compiled.debug.map +1 -1
- package/dist/demo.compiled.js +5 -5
- package/dist/demo.compiled.map +1 -1
- package/dist/deps.js +1 -1
- package/dist/locales.js +33 -33
- package/dist/receiver.compiled.debug.js +5 -5
- package/dist/receiver.compiled.debug.map +1 -1
- package/dist/receiver.compiled.js +5 -5
- package/dist/receiver.compiled.map +1 -1
- package/dist/shaka-player.compiled.debug.js +265 -265
- package/dist/shaka-player.compiled.debug.map +2 -2
- package/dist/shaka-player.compiled.js +1127 -1122
- package/dist/shaka-player.compiled.map +3 -3
- package/dist/shaka-player.ui.d.ts +1 -1
- package/dist/shaka-player.ui.debug.d.ts +1 -1
- package/dist/shaka-player.ui.debug.js +207 -217
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.js +1191 -1193
- package/dist/shaka-player.ui.map +4 -4
- package/docs/tutorials/ui-customization.md +0 -13
- package/lib/dash/dash_parser.js +1 -1
- package/lib/media/content_workarounds.js +24 -0
- package/lib/mss/mss_parser.js +2 -0
- package/lib/player.js +12 -2
- package/lib/polyfill/media_capabilities.js +14 -1
- package/lib/transmuxer/aac_transmuxer.js +2 -0
- package/lib/transmuxer/ac3_transmuxer.js +2 -0
- package/lib/transmuxer/ec3_transmuxer.js +2 -0
- package/lib/transmuxer/h264.js +28 -1
- package/lib/transmuxer/h265.js +25 -5
- package/lib/transmuxer/mp3_transmuxer.js +2 -0
- package/lib/transmuxer/ts_transmuxer.js +12 -0
- package/lib/util/cmcd_manager.js +13 -0
- package/lib/util/manifest_parser_utils.js +2 -0
- package/lib/util/mp4_generator.js +31 -2
- package/lib/util/stream_utils.js +2 -10
- package/package.json +1 -1
- package/test/dash/dash_parser_live_unit.js +19 -0
- package/test/player_integration.js +46 -40
- package/test/util/stream_utils_unit.js +2 -8
- package/ui/externs/ui.js +1 -10
- package/ui/less/range_elements.less +0 -33
- package/ui/seek_bar.js +0 -212
- package/ui/ui.js +0 -2
|
@@ -188,19 +188,6 @@ const config = {
|
|
|
188
188
|
ui.configure(config);
|
|
189
189
|
```
|
|
190
190
|
|
|
191
|
-
If you've chosen to display chapters, you can specify the color for the chapter markers on
|
|
192
|
-
the timeline and the text color of the chapter titles that popup on hover:
|
|
193
|
-
```js
|
|
194
|
-
const config = {
|
|
195
|
-
displayChapters: true,
|
|
196
|
-
seekBarColors: {
|
|
197
|
-
chapterMarks: 'rgb(27, 27, 27)',
|
|
198
|
-
chapterLabels: 'rgb(255, 255, 255)'
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
ui.configure(config);
|
|
202
|
-
```
|
|
203
|
-
|
|
204
191
|
#### Configuring playback, fast forward and rewind rates
|
|
205
192
|
The rate in which the player can play, fast forward and rewind content can be configured using the `playbackRates`, `fastForwardRates` and `rewindRates` options.
|
|
206
193
|
|
package/lib/dash/dash_parser.js
CHANGED
|
@@ -1640,7 +1640,7 @@ shaka.dash.DashParser = class {
|
|
|
1640
1640
|
// An attribute which is present and set to 0 should still result in
|
|
1641
1641
|
// periodic updates. For more, see:
|
|
1642
1642
|
// https://github.com/Dash-Industry-Forum/Guidelines-TimingModel/issues/48
|
|
1643
|
-
if (this.updatePeriod_
|
|
1643
|
+
if (this.updatePeriod_ < 0) {
|
|
1644
1644
|
return;
|
|
1645
1645
|
}
|
|
1646
1646
|
|
|
@@ -69,6 +69,30 @@ shaka.media.ContentWorkarounds = class {
|
|
|
69
69
|
})
|
|
70
70
|
.fullBox('encv', onEncryptionMetadataBox)
|
|
71
71
|
.fullBox('enca', onEncryptionMetadataBox)
|
|
72
|
+
.fullBox('dvav', (box) => {
|
|
73
|
+
boxesToModify.push({
|
|
74
|
+
box,
|
|
75
|
+
newType: ContentWorkarounds.BOX_TYPE_ENCV_,
|
|
76
|
+
});
|
|
77
|
+
})
|
|
78
|
+
.fullBox('dva1', (box) => {
|
|
79
|
+
boxesToModify.push({
|
|
80
|
+
box,
|
|
81
|
+
newType: ContentWorkarounds.BOX_TYPE_ENCV_,
|
|
82
|
+
});
|
|
83
|
+
})
|
|
84
|
+
.fullBox('dvh1', (box) => {
|
|
85
|
+
boxesToModify.push({
|
|
86
|
+
box,
|
|
87
|
+
newType: ContentWorkarounds.BOX_TYPE_ENCV_,
|
|
88
|
+
});
|
|
89
|
+
})
|
|
90
|
+
.fullBox('dvhe', (box) => {
|
|
91
|
+
boxesToModify.push({
|
|
92
|
+
box,
|
|
93
|
+
newType: ContentWorkarounds.BOX_TYPE_ENCV_,
|
|
94
|
+
});
|
|
95
|
+
})
|
|
72
96
|
.fullBox('hev1', (box) => {
|
|
73
97
|
boxesToModify.push({
|
|
74
98
|
box,
|
package/lib/mss/mss_parser.js
CHANGED
|
@@ -661,6 +661,8 @@ shaka.mss.MssParser = class {
|
|
|
661
661
|
videoNalus: videoNalus,
|
|
662
662
|
audioConfig: new Uint8Array([]),
|
|
663
663
|
videoConfig: new Uint8Array([]),
|
|
664
|
+
hSpacing: 0,
|
|
665
|
+
vSpacing: 0,
|
|
664
666
|
data: null, // Data is not necessary for init segement.
|
|
665
667
|
stream: stream,
|
|
666
668
|
};
|
package/lib/player.js
CHANGED
|
@@ -715,6 +715,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
715
715
|
|
|
716
716
|
if (shaka.Player.adManagerFactory_) {
|
|
717
717
|
this.adManager_ = shaka.Player.adManagerFactory_();
|
|
718
|
+
this.adManager_.configure(this.config_.ads);
|
|
718
719
|
}
|
|
719
720
|
|
|
720
721
|
// If the browser comes back online after being offline, then try to play
|
|
@@ -1778,8 +1779,17 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
1778
1779
|
|
|
1779
1780
|
this.drmEngine_.configure(this.config_.drm);
|
|
1780
1781
|
|
|
1782
|
+
const tracksChanged = shaka.util.StreamUtils.applyRestrictions(
|
|
1783
|
+
this.manifest_.variants, this.config_.restrictions, this.maxHwRes_);
|
|
1784
|
+
if (tracksChanged && this.streamingEngine_) {
|
|
1785
|
+
this.onTracksChanged_();
|
|
1786
|
+
}
|
|
1787
|
+
|
|
1788
|
+
const playableVariants = shaka.util.StreamUtils.getPlayableVariants(
|
|
1789
|
+
this.manifest_.variants);
|
|
1790
|
+
|
|
1781
1791
|
await this.drmEngine_.initForPlayback(
|
|
1782
|
-
|
|
1792
|
+
playableVariants,
|
|
1783
1793
|
this.manifest_.offlineSessionIds);
|
|
1784
1794
|
|
|
1785
1795
|
await this.drmEngine_.attach(this.video_);
|
|
@@ -6827,7 +6837,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
|
|
|
6827
6837
|
* @export
|
|
6828
6838
|
*/
|
|
6829
6839
|
// eslint-disable-next-line no-useless-concat
|
|
6830
|
-
shaka.Player.version = 'v4.6.
|
|
6840
|
+
shaka.Player.version = 'v4.6.13' + '-uncompiled'; // x-release-please-version
|
|
6831
6841
|
|
|
6832
6842
|
// Initialize the deprecation system using the version string we just set
|
|
6833
6843
|
// on the player.
|
|
@@ -191,10 +191,23 @@ shaka.polyfill.MediaCapabilities = class {
|
|
|
191
191
|
const videoCapabilities = [];
|
|
192
192
|
|
|
193
193
|
if (mediaCapkeySystemConfig.audio) {
|
|
194
|
-
|
|
194
|
+
let capability = {
|
|
195
195
|
robustness: mediaCapkeySystemConfig.audio.robustness || '',
|
|
196
196
|
contentType: mediaDecodingConfig.audio.contentType,
|
|
197
197
|
};
|
|
198
|
+
|
|
199
|
+
// Some Tizen devices seem to misreport AC-3 support, but correctly
|
|
200
|
+
// report EC-3 support. So query EC-3 as a fallback for AC-3.
|
|
201
|
+
// See https://github.com/shaka-project/shaka-player/issues/2989 for
|
|
202
|
+
// details.
|
|
203
|
+
if (shaka.util.Platform.isTizen() &&
|
|
204
|
+
mediaDecodingConfig.audio.contentType.includes('codecs="ac-3"')) {
|
|
205
|
+
capability = {
|
|
206
|
+
robustness: capability.robustness,
|
|
207
|
+
contentType: 'audio/mp4; codecs="ec-3"',
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
198
211
|
audioCapabilities.push(capability);
|
|
199
212
|
}
|
|
200
213
|
|
|
@@ -195,6 +195,8 @@ shaka.transmuxer.AacTransmuxer = class {
|
|
|
195
195
|
videoNalus: [],
|
|
196
196
|
audioConfig: new Uint8Array([]),
|
|
197
197
|
videoConfig: new Uint8Array([]),
|
|
198
|
+
hSpacing: 0,
|
|
199
|
+
vSpacing: 0,
|
|
198
200
|
data: {
|
|
199
201
|
sequenceNumber: this.frameIndex_,
|
|
200
202
|
baseMediaDecodeTime: baseMediaDecodeTime,
|
|
@@ -184,6 +184,8 @@ shaka.transmuxer.Ac3Transmuxer = class {
|
|
|
184
184
|
videoNalus: [],
|
|
185
185
|
audioConfig: audioConfig,
|
|
186
186
|
videoConfig: new Uint8Array([]),
|
|
187
|
+
hSpacing: 0,
|
|
188
|
+
vSpacing: 0,
|
|
187
189
|
data: {
|
|
188
190
|
sequenceNumber: this.frameIndex_,
|
|
189
191
|
baseMediaDecodeTime: baseMediaDecodeTime,
|
|
@@ -184,6 +184,8 @@ shaka.transmuxer.Ec3Transmuxer = class {
|
|
|
184
184
|
videoNalus: [],
|
|
185
185
|
audioConfig: audioConfig,
|
|
186
186
|
videoConfig: new Uint8Array([]),
|
|
187
|
+
hSpacing: 0,
|
|
188
|
+
vSpacing: 0,
|
|
187
189
|
data: {
|
|
188
190
|
sequenceNumber: this.frameIndex_,
|
|
189
191
|
baseMediaDecodeTime: baseMediaDecodeTime,
|
package/lib/transmuxer/h264.js
CHANGED
|
@@ -20,7 +20,8 @@ shaka.transmuxer.H264 = class {
|
|
|
20
20
|
* describes the properties of upcoming video frames.
|
|
21
21
|
*
|
|
22
22
|
* @param {!Array.<shaka.extern.VideoNalu>} nalus
|
|
23
|
-
* @return {?{height: number, width: number, videoConfig: !Uint8Array
|
|
23
|
+
* @return {?{height: number, width: number, videoConfig: !Uint8Array,
|
|
24
|
+
* hSpacing: number, vSpacing: number}}
|
|
24
25
|
*/
|
|
25
26
|
static parseInfo(nalus) {
|
|
26
27
|
const H264 = shaka.transmuxer.H264;
|
|
@@ -129,6 +130,30 @@ shaka.transmuxer.H264 = class {
|
|
|
129
130
|
frameCropBottomOffset = expGolombDecoder.readUnsignedExpGolomb();
|
|
130
131
|
}
|
|
131
132
|
|
|
133
|
+
let hSpacing = 1;
|
|
134
|
+
let vSpacing = 1;
|
|
135
|
+
|
|
136
|
+
// vui_parameters_present_flag
|
|
137
|
+
if (expGolombDecoder.readBoolean()) {
|
|
138
|
+
// aspect_ratio_info_present_flag
|
|
139
|
+
if (expGolombDecoder.readBoolean()) {
|
|
140
|
+
const aspectRatioIdc = expGolombDecoder.readUnsignedByte();
|
|
141
|
+
const hSpacingTable = [
|
|
142
|
+
1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160, 4, 3, 2,
|
|
143
|
+
];
|
|
144
|
+
const vSpacingTable = [
|
|
145
|
+
1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99, 3, 2, 1,
|
|
146
|
+
];
|
|
147
|
+
if (aspectRatioIdc > 0 && aspectRatioIdc < 16) {
|
|
148
|
+
hSpacing = hSpacingTable[aspectRatioIdc - 1];
|
|
149
|
+
vSpacing = vSpacingTable[aspectRatioIdc - 1];
|
|
150
|
+
} else if (aspectRatioIdc === 255) {
|
|
151
|
+
hSpacing = expGolombDecoder.readBits(16);
|
|
152
|
+
vSpacing = expGolombDecoder.readBits(16);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
132
157
|
const height = ((2 - frameMbsOnlyFlag) *
|
|
133
158
|
(picHeightInMapUnitsMinus1 + 1) * 16) - (frameCropTopOffset * 2) -
|
|
134
159
|
(frameCropBottomOffset * 2);
|
|
@@ -165,6 +190,8 @@ shaka.transmuxer.H264 = class {
|
|
|
165
190
|
height,
|
|
166
191
|
width,
|
|
167
192
|
videoConfig,
|
|
193
|
+
hSpacing,
|
|
194
|
+
vSpacing,
|
|
168
195
|
};
|
|
169
196
|
}
|
|
170
197
|
|
package/lib/transmuxer/h265.js
CHANGED
|
@@ -20,7 +20,8 @@ shaka.transmuxer.H265 = class {
|
|
|
20
20
|
* describes the properties of upcoming video frames.
|
|
21
21
|
*
|
|
22
22
|
* @param {!Array.<shaka.extern.VideoNalu>} nalus
|
|
23
|
-
* @return {?{height: number, width: number, videoConfig: !Uint8Array
|
|
23
|
+
* @return {?{height: number, width: number, videoConfig: !Uint8Array,
|
|
24
|
+
* hSpacing: number, vSpacing: number}}
|
|
24
25
|
*/
|
|
25
26
|
static parseInfo(nalus) {
|
|
26
27
|
const H265 = shaka.transmuxer.H265;
|
|
@@ -87,6 +88,8 @@ shaka.transmuxer.H265 = class {
|
|
|
87
88
|
height: spsConfiguration.height,
|
|
88
89
|
width: spsConfiguration.width,
|
|
89
90
|
videoConfig,
|
|
91
|
+
hSpacing: spsConfiguration.sarWidth,
|
|
92
|
+
vSpacing: spsConfiguration.sarHeight,
|
|
90
93
|
};
|
|
91
94
|
}
|
|
92
95
|
|
|
@@ -298,6 +301,8 @@ shaka.transmuxer.H265 = class {
|
|
|
298
301
|
}
|
|
299
302
|
}
|
|
300
303
|
let defaultDisplayWindowFlag = false; // for calc offset
|
|
304
|
+
let sarWidth = 1;
|
|
305
|
+
let sarHeight = 1;
|
|
301
306
|
let minSpatialSegmentationIdc = 0; // for hvcC
|
|
302
307
|
gb.readBoolean(); // sps_temporal_mvp_enabled_flag
|
|
303
308
|
gb.readBoolean(); // strong_intra_smoothing_enabled_flag
|
|
@@ -306,9 +311,18 @@ shaka.transmuxer.H265 = class {
|
|
|
306
311
|
const aspectRatioInfoPresentFlag = gb.readBoolean();
|
|
307
312
|
if (aspectRatioInfoPresentFlag) {
|
|
308
313
|
const aspectRatioIdc = gb.readUnsignedByte();
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
314
|
+
const sarWidthTable = [
|
|
315
|
+
1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160, 4, 3, 2,
|
|
316
|
+
];
|
|
317
|
+
const sarHeightTable = [
|
|
318
|
+
1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99, 3, 2, 1,
|
|
319
|
+
];
|
|
320
|
+
if (aspectRatioIdc > 0 && aspectRatioIdc < 16) {
|
|
321
|
+
sarWidth = sarWidthTable[aspectRatioIdc - 1];
|
|
322
|
+
sarHeight = sarHeightTable[aspectRatioIdc - 1];
|
|
323
|
+
} else if (aspectRatioIdc === 255) {
|
|
324
|
+
sarWidth = gb.readBits(16);
|
|
325
|
+
sarHeight = gb.readBits(16);
|
|
312
326
|
}
|
|
313
327
|
}
|
|
314
328
|
const overscanInfoPresentFlag = gb.readBoolean();
|
|
@@ -459,6 +473,8 @@ shaka.transmuxer.H265 = class {
|
|
|
459
473
|
bitDepthChromaMinus8,
|
|
460
474
|
width: codecWidth,
|
|
461
475
|
height: codecHeight,
|
|
476
|
+
sarWidth: sarWidth,
|
|
477
|
+
sarHeight: sarHeight,
|
|
462
478
|
};
|
|
463
479
|
}
|
|
464
480
|
|
|
@@ -773,7 +789,9 @@ shaka.transmuxer.H265.VPSConfiguration;
|
|
|
773
789
|
* bitDepthLumaMinus8: number,
|
|
774
790
|
* bitDepthChromaMinus8: number,
|
|
775
791
|
* width: number,
|
|
776
|
-
* height: number
|
|
792
|
+
* height: number,
|
|
793
|
+
* sarWidth: number,
|
|
794
|
+
* sarHeight: number
|
|
777
795
|
* }}
|
|
778
796
|
*
|
|
779
797
|
* @property {number} generalProfileSpace
|
|
@@ -797,6 +815,8 @@ shaka.transmuxer.H265.VPSConfiguration;
|
|
|
797
815
|
* @property {number} bitDepthChromaMinus8
|
|
798
816
|
* @property {number} width
|
|
799
817
|
* @property {number} height
|
|
818
|
+
* @property {number} sarWidth
|
|
819
|
+
* @property {number} sarHeight
|
|
800
820
|
*/
|
|
801
821
|
shaka.transmuxer.H265.SPSConfiguration;
|
|
802
822
|
|
|
@@ -176,6 +176,8 @@ shaka.transmuxer.Mp3Transmuxer = class {
|
|
|
176
176
|
videoNalus: [],
|
|
177
177
|
audioConfig: new Uint8Array([]),
|
|
178
178
|
videoConfig: new Uint8Array([]),
|
|
179
|
+
hSpacing: 0,
|
|
180
|
+
vSpacing: 0,
|
|
179
181
|
data: {
|
|
180
182
|
sequenceNumber: this.frameIndex_,
|
|
181
183
|
baseMediaDecodeTime: baseMediaDecodeTime,
|
|
@@ -409,6 +409,8 @@ shaka.transmuxer.TsTransmuxer = class {
|
|
|
409
409
|
videoNalus: [],
|
|
410
410
|
audioConfig: new Uint8Array([]),
|
|
411
411
|
videoConfig: new Uint8Array([]),
|
|
412
|
+
hSpacing: 0,
|
|
413
|
+
vSpacing: 0,
|
|
412
414
|
data: {
|
|
413
415
|
sequenceNumber: this.frameIndex_,
|
|
414
416
|
baseMediaDecodeTime: baseMediaDecodeTime,
|
|
@@ -500,6 +502,8 @@ shaka.transmuxer.TsTransmuxer = class {
|
|
|
500
502
|
videoNalus: [],
|
|
501
503
|
audioConfig: audioConfig,
|
|
502
504
|
videoConfig: new Uint8Array([]),
|
|
505
|
+
hSpacing: 0,
|
|
506
|
+
vSpacing: 0,
|
|
503
507
|
data: {
|
|
504
508
|
sequenceNumber: this.frameIndex_,
|
|
505
509
|
baseMediaDecodeTime: baseMediaDecodeTime,
|
|
@@ -591,6 +595,8 @@ shaka.transmuxer.TsTransmuxer = class {
|
|
|
591
595
|
videoNalus: [],
|
|
592
596
|
audioConfig: audioConfig,
|
|
593
597
|
videoConfig: new Uint8Array([]),
|
|
598
|
+
hSpacing: 0,
|
|
599
|
+
vSpacing: 0,
|
|
594
600
|
data: {
|
|
595
601
|
sequenceNumber: this.frameIndex_,
|
|
596
602
|
baseMediaDecodeTime: baseMediaDecodeTime,
|
|
@@ -677,6 +683,8 @@ shaka.transmuxer.TsTransmuxer = class {
|
|
|
677
683
|
videoNalus: [],
|
|
678
684
|
audioConfig: new Uint8Array([]),
|
|
679
685
|
videoConfig: new Uint8Array([]),
|
|
686
|
+
hSpacing: 0,
|
|
687
|
+
vSpacing: 0,
|
|
680
688
|
data: {
|
|
681
689
|
sequenceNumber: this.frameIndex_,
|
|
682
690
|
baseMediaDecodeTime: baseMediaDecodeTime,
|
|
@@ -769,6 +777,8 @@ shaka.transmuxer.TsTransmuxer = class {
|
|
|
769
777
|
videoNalus: [],
|
|
770
778
|
audioConfig: new Uint8Array([]),
|
|
771
779
|
videoConfig: info.videoConfig,
|
|
780
|
+
hSpacing: info.hSpacing,
|
|
781
|
+
vSpacing: info.vSpacing,
|
|
772
782
|
data: {
|
|
773
783
|
sequenceNumber: this.frameIndex_,
|
|
774
784
|
baseMediaDecodeTime: baseMediaDecodeTime,
|
|
@@ -861,6 +871,8 @@ shaka.transmuxer.TsTransmuxer = class {
|
|
|
861
871
|
videoNalus: [],
|
|
862
872
|
audioConfig: new Uint8Array([]),
|
|
863
873
|
videoConfig: info.videoConfig,
|
|
874
|
+
hSpacing: info.hSpacing,
|
|
875
|
+
vSpacing: info.vSpacing,
|
|
864
876
|
data: {
|
|
865
877
|
sequenceNumber: this.frameIndex_,
|
|
866
878
|
baseMediaDecodeTime: baseMediaDecodeTime,
|
package/lib/util/cmcd_manager.js
CHANGED
|
@@ -65,6 +65,9 @@ shaka.util.CmcdManager = class {
|
|
|
65
65
|
*/
|
|
66
66
|
configure(config) {
|
|
67
67
|
this.config_ = config;
|
|
68
|
+
if (this.config_.sessionId && this.config_.sessionId != this.sid_) {
|
|
69
|
+
this.sid_ = '';
|
|
70
|
+
}
|
|
68
71
|
}
|
|
69
72
|
|
|
70
73
|
/**
|
|
@@ -407,6 +410,15 @@ shaka.util.CmcdManager = class {
|
|
|
407
410
|
*/
|
|
408
411
|
getObjectTypeFromMimeType_(mimeType) {
|
|
409
412
|
switch (mimeType.toLowerCase()) {
|
|
413
|
+
case 'audio/mp4':
|
|
414
|
+
case 'audio/webm':
|
|
415
|
+
case 'audio/ogg':
|
|
416
|
+
case 'audio/mpeg':
|
|
417
|
+
case 'audio/aac':
|
|
418
|
+
case 'audio/flac':
|
|
419
|
+
case 'audio/wav':
|
|
420
|
+
return shaka.util.CmcdManager.ObjectType.AUDIO;
|
|
421
|
+
|
|
410
422
|
case 'video/webm':
|
|
411
423
|
case 'video/mp4':
|
|
412
424
|
case 'video/mpeg':
|
|
@@ -417,6 +429,7 @@ shaka.util.CmcdManager = class {
|
|
|
417
429
|
case 'application/vnd.apple.mpegurl':
|
|
418
430
|
case 'application/dash+xml':
|
|
419
431
|
case 'video/vnd.mpeg.dash.mpd':
|
|
432
|
+
case 'application/vnd.ms-sstr+xml':
|
|
420
433
|
return shaka.util.CmcdManager.ObjectType.MANIFEST;
|
|
421
434
|
|
|
422
435
|
default:
|
|
@@ -371,12 +371,13 @@ shaka.util.Mp4Generator = class {
|
|
|
371
371
|
]);
|
|
372
372
|
|
|
373
373
|
let boxName = 'avc1';
|
|
374
|
+
const paspBox = this.pasp_(streamInfo);
|
|
374
375
|
let sinfBox = new Uint8Array([]);
|
|
375
376
|
if (streamInfo.encrypted) {
|
|
376
377
|
sinfBox = this.sinf_(streamInfo);
|
|
377
378
|
boxName = 'encv';
|
|
378
379
|
}
|
|
379
|
-
return Mp4Generator.box(boxName, avc1Bytes, avcCBox, sinfBox);
|
|
380
|
+
return Mp4Generator.box(boxName, avc1Bytes, avcCBox, paspBox, sinfBox);
|
|
380
381
|
}
|
|
381
382
|
|
|
382
383
|
/**
|
|
@@ -500,12 +501,34 @@ shaka.util.Mp4Generator = class {
|
|
|
500
501
|
]);
|
|
501
502
|
|
|
502
503
|
let boxName = 'hvc1';
|
|
504
|
+
const paspBox = this.pasp_(streamInfo);
|
|
503
505
|
let sinfBox = new Uint8Array([]);
|
|
504
506
|
if (streamInfo.encrypted) {
|
|
505
507
|
sinfBox = this.sinf_(streamInfo);
|
|
506
508
|
boxName = 'encv';
|
|
507
509
|
}
|
|
508
|
-
return Mp4Generator.box(boxName, hvc1Bytes, hvcCBox, sinfBox);
|
|
510
|
+
return Mp4Generator.box(boxName, hvc1Bytes, hvcCBox, paspBox, sinfBox);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* Generate a PASP box
|
|
515
|
+
*
|
|
516
|
+
* @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
|
|
517
|
+
* @return {!Uint8Array}
|
|
518
|
+
* @private
|
|
519
|
+
*/
|
|
520
|
+
pasp_(streamInfo) {
|
|
521
|
+
if (!streamInfo.hSpacing && !streamInfo.vSpacing) {
|
|
522
|
+
return new Uint8Array([]);
|
|
523
|
+
}
|
|
524
|
+
const Mp4Generator = shaka.util.Mp4Generator;
|
|
525
|
+
const hSpacing = streamInfo.hSpacing;
|
|
526
|
+
const vSpacing = streamInfo.vSpacing;
|
|
527
|
+
const bytes = new Uint8Array([
|
|
528
|
+
...this.breakNumberIntoBytes_(hSpacing, 4), // hSpacing
|
|
529
|
+
...this.breakNumberIntoBytes_(vSpacing, 4), // vSpacing
|
|
530
|
+
]);
|
|
531
|
+
return Mp4Generator.box('pasp', bytes);
|
|
509
532
|
}
|
|
510
533
|
|
|
511
534
|
/**
|
|
@@ -1301,6 +1324,8 @@ shaka.util.Mp4Generator.DINF_ = new Uint8Array([]);
|
|
|
1301
1324
|
* videoNalus: !Array.<string>,
|
|
1302
1325
|
* audioConfig: !Uint8Array,
|
|
1303
1326
|
* videoConfig: !Uint8Array,
|
|
1327
|
+
* hSpacing: number,
|
|
1328
|
+
* vSpacing: number,
|
|
1304
1329
|
* data: ?shaka.util.Mp4Generator.Data,
|
|
1305
1330
|
* stream: !shaka.extern.Stream
|
|
1306
1331
|
* }}
|
|
@@ -1325,6 +1350,10 @@ shaka.util.Mp4Generator.DINF_ = new Uint8Array([]);
|
|
|
1325
1350
|
* The stream's audio config.
|
|
1326
1351
|
* @property {!Uint8Array} videoConfig
|
|
1327
1352
|
* The stream's video config.
|
|
1353
|
+
* @property {number} hSpacing
|
|
1354
|
+
* The stream's video horizontal spacing of pixels.
|
|
1355
|
+
* @property {number} vSpacing
|
|
1356
|
+
* The stream's video vertial spacing of pixels.
|
|
1328
1357
|
* @property {?shaka.util.Mp4Generator.Data} data
|
|
1329
1358
|
* The stream's data.
|
|
1330
1359
|
* @property {!shaka.extern.Stream} stream
|
package/lib/util/stream_utils.js
CHANGED
|
@@ -161,7 +161,7 @@ shaka.util.StreamUtils = class {
|
|
|
161
161
|
const currentCodec =
|
|
162
162
|
MimeUtils.getNormalizedCodec(stream.codecs);
|
|
163
163
|
if (previousCodec == currentCodec) {
|
|
164
|
-
if (stream.bandwidth
|
|
164
|
+
if (stream.bandwidth > previousStream.bandwidth) {
|
|
165
165
|
validVideoStreams.push(stream);
|
|
166
166
|
validVideoIds.push(stream.id);
|
|
167
167
|
}
|
|
@@ -848,15 +848,7 @@ shaka.util.StreamUtils = class {
|
|
|
848
848
|
return 'opus';
|
|
849
849
|
}
|
|
850
850
|
|
|
851
|
-
|
|
852
|
-
// report EC-3 support. So query EC-3 as a fallback for AC-3.
|
|
853
|
-
// See https://github.com/shaka-project/shaka-player/issues/2989 for
|
|
854
|
-
// details.
|
|
855
|
-
if (shaka.util.Platform.isTizen()) {
|
|
856
|
-
return codecs.toLowerCase() == 'ac-3' ? 'ec-3' : codecs;
|
|
857
|
-
} else {
|
|
858
|
-
return codecs;
|
|
859
|
-
}
|
|
851
|
+
return codecs;
|
|
860
852
|
}
|
|
861
853
|
|
|
862
854
|
|
package/package.json
CHANGED
|
@@ -642,6 +642,25 @@ describe('DashParser Live', () => {
|
|
|
642
642
|
expect(updateTick).toHaveBeenCalledTimes(1);
|
|
643
643
|
});
|
|
644
644
|
|
|
645
|
+
it('still updates when @minimumUpdatePeriod is zero', async () => {
|
|
646
|
+
const lines = [
|
|
647
|
+
'<SegmentTemplate startNumber="1" media="s$Number$.mp4" duration="2" />',
|
|
648
|
+
];
|
|
649
|
+
// updateTime parameter sets @minimumUpdatePeriod in the manifest.
|
|
650
|
+
const manifestText = makeSimpleLiveManifestText(lines, /* updateTime= */ 0);
|
|
651
|
+
|
|
652
|
+
/** @type {!jasmine.Spy} */
|
|
653
|
+
const tickAfter = updateTickSpy();
|
|
654
|
+
Date.now = () => 0;
|
|
655
|
+
|
|
656
|
+
fakeNetEngine.setResponseText('dummy://foo', manifestText);
|
|
657
|
+
await parser.start('dummy://foo', playerInterface);
|
|
658
|
+
|
|
659
|
+
expect(tickAfter).toHaveBeenCalledTimes(1);
|
|
660
|
+
const delay = tickAfter.calls.mostRecent().args[0];
|
|
661
|
+
expect(delay).toBe(0);
|
|
662
|
+
});
|
|
663
|
+
|
|
645
664
|
it('uses @minimumUpdatePeriod', async () => {
|
|
646
665
|
const lines = [
|
|
647
666
|
'<SegmentTemplate startNumber="1" media="s$Number$.mp4" duration="2" />',
|
|
@@ -61,6 +61,46 @@ describe('Player', () => {
|
|
|
61
61
|
document.body.removeChild(video);
|
|
62
62
|
});
|
|
63
63
|
|
|
64
|
+
describe('seek range', () => {
|
|
65
|
+
// Regression test for Issue #3675.
|
|
66
|
+
it('has a reasonable seek range after going from live to VOD', async () => {
|
|
67
|
+
const netEngine = player.getNetworkingEngine();
|
|
68
|
+
const startTime = Date.now();
|
|
69
|
+
netEngine.registerRequestFilter((type, request) => {
|
|
70
|
+
if (type != shaka.net.NetworkingEngine.RequestType.MANIFEST) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
// Simulate a live stream by providing different manifests over time.
|
|
74
|
+
const time = (Date.now() - startTime) / 1000;
|
|
75
|
+
const manifestNumber = Math.min(5, Math.floor(0.5 + time / 2));
|
|
76
|
+
request.uris = [
|
|
77
|
+
'/base/test/test/assets/3675/dash_' + manifestNumber + '.mpd',
|
|
78
|
+
];
|
|
79
|
+
console.log('getting manifest', request.uris);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Play the stream.
|
|
83
|
+
await player.load('/base/test/test/assets/3675/dash_0.mpd');
|
|
84
|
+
await video.play();
|
|
85
|
+
|
|
86
|
+
// Wait for the stream to be over.
|
|
87
|
+
eventManager.listen(player, 'error', Util.spyFunc(onErrorSpy));
|
|
88
|
+
/** @type {shaka.test.Waiter} */
|
|
89
|
+
const waiter = new shaka.test.Waiter(eventManager)
|
|
90
|
+
.setPlayer(player)
|
|
91
|
+
.timeoutAfter(40)
|
|
92
|
+
.failOnTimeout(true);
|
|
93
|
+
await waiter.waitForEnd(video);
|
|
94
|
+
|
|
95
|
+
// The stream should have transitioned to VOD by now.
|
|
96
|
+
expect(player.isLive()).toBe(false);
|
|
97
|
+
|
|
98
|
+
// Check that the final seek range is as expected.
|
|
99
|
+
const seekRange = player.seekRange();
|
|
100
|
+
expect(seekRange.end).toBeCloseTo(14);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
64
104
|
describe('attach', () => {
|
|
65
105
|
beforeEach(async () => {
|
|
66
106
|
// To test attach, we want to construct a player without a video element
|
|
@@ -908,46 +948,6 @@ describe('Player', () => {
|
|
|
908
948
|
});
|
|
909
949
|
});
|
|
910
950
|
|
|
911
|
-
describe('seek range', () => {
|
|
912
|
-
// Regression test for Issue #3675.
|
|
913
|
-
it('has a reasonable seek range after going from live to VOD', async () => {
|
|
914
|
-
const netEngine = player.getNetworkingEngine();
|
|
915
|
-
const startTime = Date.now();
|
|
916
|
-
netEngine.registerRequestFilter((type, request) => {
|
|
917
|
-
if (type != shaka.net.NetworkingEngine.RequestType.MANIFEST) {
|
|
918
|
-
return;
|
|
919
|
-
}
|
|
920
|
-
// Simulate a live stream by providing different manifests over time.
|
|
921
|
-
const time = (Date.now() - startTime) / 1000;
|
|
922
|
-
const manifestNumber = Math.min(5, Math.floor(0.5 + time / 2));
|
|
923
|
-
request.uris = [
|
|
924
|
-
'/base/test/test/assets/3675/dash_' + manifestNumber + '.mpd',
|
|
925
|
-
];
|
|
926
|
-
console.log('getting manifest', request.uris);
|
|
927
|
-
});
|
|
928
|
-
|
|
929
|
-
// Play the stream.
|
|
930
|
-
await player.load('/base/test/test/assets/3675/dash_0.mpd');
|
|
931
|
-
await video.play();
|
|
932
|
-
|
|
933
|
-
// Wait for the stream to be over.
|
|
934
|
-
eventManager.listen(player, 'error', Util.spyFunc(onErrorSpy));
|
|
935
|
-
/** @type {shaka.test.Waiter} */
|
|
936
|
-
const waiter = new shaka.test.Waiter(eventManager)
|
|
937
|
-
.setPlayer(player)
|
|
938
|
-
.timeoutAfter(40)
|
|
939
|
-
.failOnTimeout(true);
|
|
940
|
-
await waiter.waitForEnd(video);
|
|
941
|
-
|
|
942
|
-
// The stream should have transitioned to VOD by now.
|
|
943
|
-
expect(player.isLive()).toBe(false);
|
|
944
|
-
|
|
945
|
-
// Check that the final seek range is as expected.
|
|
946
|
-
const seekRange = player.seekRange();
|
|
947
|
-
expect(seekRange.end).toBeCloseTo(14);
|
|
948
|
-
});
|
|
949
|
-
});
|
|
950
|
-
|
|
951
951
|
describe('buffering', () => {
|
|
952
952
|
const startBuffering = jasmine.objectContaining({buffering: true});
|
|
953
953
|
const endBuffering = jasmine.objectContaining({buffering: false});
|
|
@@ -1012,6 +1012,9 @@ describe('Player', () => {
|
|
|
1012
1012
|
});
|
|
1013
1013
|
|
|
1014
1014
|
it('buffers ahead of the playhead', async () => {
|
|
1015
|
+
if (window.ManagedMediaSource) {
|
|
1016
|
+
pending('ManagedMediaSource has buffer control signals.');
|
|
1017
|
+
}
|
|
1015
1018
|
player.configure('streaming.bufferingGoal', 10);
|
|
1016
1019
|
|
|
1017
1020
|
await player.load('test:sintel_long_compiled');
|
|
@@ -1036,6 +1039,9 @@ describe('Player', () => {
|
|
|
1036
1039
|
});
|
|
1037
1040
|
|
|
1038
1041
|
it('clears buffer behind playhead', async () => {
|
|
1042
|
+
if (window.ManagedMediaSource) {
|
|
1043
|
+
pending('ManagedMediaSource has buffer control signals.');
|
|
1044
|
+
}
|
|
1039
1045
|
player.configure('streaming.bufferingGoal', 30);
|
|
1040
1046
|
player.configure('streaming.bufferBehind', 30);
|
|
1041
1047
|
|
|
@@ -826,12 +826,6 @@ describe('StreamUtils', () => {
|
|
|
826
826
|
stream.size(20, 20);
|
|
827
827
|
});
|
|
828
828
|
});
|
|
829
|
-
manifest.addVariant(6, (variant) => {
|
|
830
|
-
variant.addVideo(7, (stream) => {
|
|
831
|
-
stream.bandwidth = 600000;
|
|
832
|
-
stream.size(20, 20);
|
|
833
|
-
});
|
|
834
|
-
});
|
|
835
829
|
});
|
|
836
830
|
|
|
837
831
|
shaka.util.StreamUtils.chooseCodecsAndFilterManifest(manifest,
|
|
@@ -839,8 +833,8 @@ describe('StreamUtils', () => {
|
|
|
839
833
|
/* preferredAudioCodecs= */[],
|
|
840
834
|
/* preferredDecodingAttributes= */[]);
|
|
841
835
|
|
|
842
|
-
expect(manifest.variants.length).toBe(
|
|
843
|
-
expect(manifest.variants.every((v) => [300000, 500000].includes(
|
|
836
|
+
expect(manifest.variants.length).toBe(3);
|
|
837
|
+
expect(manifest.variants.every((v) => [300000, 400000, 500000].includes(
|
|
844
838
|
v.video.bandwidth))).toBeTruthy();
|
|
845
839
|
});
|
|
846
840
|
|