shaka-player 4.4.3 → 4.5.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/workflows/release-please.yaml +2 -27
- package/CHANGELOG.md +64 -45
- package/README.md +16 -10
- package/demo/asset_card.js +18 -21
- package/demo/cast_receiver/index.html +0 -1
- package/demo/close_button.js +0 -3
- package/demo/common/asset.js +22 -5
- package/demo/common/assets.js +132 -49
- package/demo/config.js +192 -253
- package/demo/custom.js +39 -98
- package/demo/front.js +7 -10
- package/demo/index.html +19 -22
- package/demo/input.js +6 -11
- package/demo/input_container.js +8 -9
- package/demo/main.js +51 -123
- package/demo/search.js +22 -34
- package/demo/service_worker.js +0 -3
- package/demo/tooltip.js +3 -5
- package/demo/visualizer.js +3 -5
- package/demo/visualizer_button.js +1 -20
- package/dist/demo.compiled.debug.js +152 -178
- package/dist/demo.compiled.debug.map +4 -4
- package/dist/demo.compiled.js +152 -178
- package/dist/demo.compiled.map +4 -4
- package/dist/deps.js +27 -24
- package/dist/locales.js +31 -31
- package/dist/receiver.compiled.debug.js +22 -43
- package/dist/receiver.compiled.debug.map +4 -4
- package/dist/receiver.compiled.js +22 -43
- package/dist/receiver.compiled.map +4 -4
- package/dist/shaka-player.compiled.d.ts +507 -365
- package/dist/shaka-player.compiled.debug.d.ts +507 -365
- package/dist/shaka-player.compiled.debug.externs.js +205 -51
- package/dist/shaka-player.compiled.debug.js +541 -450
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +205 -51
- package/dist/shaka-player.compiled.js +1120 -1066
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +562 -410
- package/dist/shaka-player.ui.debug.d.ts +562 -410
- package/dist/shaka-player.ui.debug.externs.js +226 -51
- package/dist/shaka-player.ui.debug.js +606 -506
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +226 -51
- package/dist/shaka-player.ui.js +1266 -1207
- package/dist/shaka-player.ui.map +4 -4
- package/docs/design/lcevc-integration.md +14 -14
- package/docs/tutorials/faq.md +27 -55
- package/docs/tutorials/index.json +2 -1
- package/docs/tutorials/lcevc.md +118 -0
- package/docs/tutorials/ui-customization.md +4 -0
- package/externs/css_style_declaration.js +19 -0
- package/externs/lcevc.js +37 -13
- package/externs/media_remote.js +68 -0
- package/externs/mediatailor.js +193 -0
- package/externs/pictureinpicture.js +11 -0
- package/externs/shaka/ads.js +27 -0
- package/externs/shaka/manifest.js +10 -5
- package/externs/shaka/manifest_parser.js +7 -1
- package/externs/shaka/offline.js +4 -0
- package/externs/shaka/player.js +12 -1
- package/karma.conf.js +7 -3
- package/lib/abr/simple_abr_manager.js +43 -3
- package/lib/ads/ad_manager.js +104 -50
- package/lib/ads/media_tailor_ad.js +297 -0
- package/lib/ads/media_tailor_ad_manager.js +828 -0
- package/lib/cea/ts_cea_parser.js +15 -2
- package/lib/config/codec_switching_strategy.js +24 -0
- package/lib/dash/content_protection.js +120 -2
- package/lib/dash/dash_parser.js +75 -12
- package/lib/dash/mpd_utils.js +10 -6
- package/lib/dash/segment_base.js +13 -5
- package/lib/dash/segment_list.js +13 -5
- package/lib/dash/segment_template.js +43 -85
- package/lib/dependencies/all.js +8 -7
- package/lib/hls/hls_parser.js +44 -16
- package/lib/lcevc/lcevc_dec.js +220 -0
- package/lib/media/adaptation_set.js +22 -11
- package/lib/media/adaptation_set_criteria.js +25 -7
- package/lib/media/media_source_engine.js +215 -27
- package/lib/media/segment_index.js +1 -1
- package/lib/media/segment_reference.js +7 -7
- package/lib/media/streaming_engine.js +33 -18
- package/lib/mss/mss_parser.js +1 -0
- package/lib/net/networking_engine.js +1 -0
- package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
- package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
- package/lib/offline/manifest_converter.js +1 -0
- package/lib/offline/storage.js +3 -0
- package/lib/player.js +142 -72
- package/lib/routing/payload.js +5 -1
- package/lib/text/cue.js +15 -0
- package/lib/text/ttml_text_parser.js +17 -0
- package/lib/text/ui_text_displayer.js +4 -0
- package/lib/text/vtt_text_parser.js +33 -20
- package/lib/transmuxer/h265.js +862 -0
- package/lib/transmuxer/mpeg_ts_transmuxer.js +3 -2
- package/lib/transmuxer/ts_transmuxer.js +160 -15
- package/lib/util/error.js +28 -9
- package/lib/util/exp_golomb.js +30 -2
- package/lib/util/fake_event.js +3 -0
- package/lib/util/mp4_generator.js +4 -4
- package/lib/util/periods.js +2 -0
- package/lib/util/platform.js +40 -0
- package/lib/util/player_configuration.js +8 -0
- package/lib/util/state_history.js +6 -2
- package/lib/util/stream_utils.js +133 -217
- package/lib/util/ts_parser.js +226 -40
- package/maintained-branches.md +3 -2
- package/package.json +4 -6
- package/roadmap.md +15 -5
- package/shaka-player.uncompiled.js +2 -1
- package/support.html +0 -1
- package/test/cast/cast_receiver_integration.js +47 -0
- package/test/codec_switching/codec_switching_integration.js +181 -0
- package/test/dash/dash_parser_content_protection_unit.js +2 -0
- package/test/dash/dash_parser_integration.js +73 -0
- package/test/dash/dash_parser_live_unit.js +2 -0
- package/test/dash/dash_parser_manifest_unit.js +42 -0
- package/test/dash/dash_parser_segment_base_unit.js +2 -0
- package/test/dash/dash_parser_segment_list_unit.js +2 -0
- package/test/dash/dash_parser_segment_template_unit.js +2 -0
- package/test/demo/demo_unit.js +0 -16
- package/test/hls/hls_live_unit.js +2 -0
- package/test/hls/hls_parser_unit.js +8 -6
- package/test/media/adaptation_set_criteria_unit.js +118 -0
- package/test/media/adaptation_set_unit.js +1 -0
- package/test/media/media_source_engine_unit.js +165 -1
- package/test/media/segment_index_unit.js +4 -4
- package/test/media/segment_prefetch_unit.js +1 -1
- package/test/media/streaming_engine_unit.js +17 -17
- package/test/mss/mss_parser_unit.js +2 -0
- package/test/offline/manifest_convert_unit.js +5 -0
- package/test/offline/storage_integration.js +1 -4
- package/test/player_unit.js +102 -131
- package/test/routing/walker_unit.js +1 -0
- package/test/test/assets/dash-aes-128/Fragments(video=0,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=20000000,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=40000000,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=60000000,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=i,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/dash.mpd +18 -0
- package/test/test/assets/dash-aes-128/license +1 -0
- package/test/test/assets/dash-multi-codec/audio_en_2c_128k_aac.mp4 +0 -0
- package/test/test/assets/dash-multi-codec/audio_es_2c_64k_opus.webm +0 -0
- package/test/test/assets/dash-multi-codec/dash.mpd +32 -0
- package/test/test/assets/dash-multi-codec/video_144p_108k_h264.mp4 +0 -0
- package/test/test/assets/hls-ts-h265/0.ts +0 -0
- package/test/test/assets/hls-ts-h265/hevc.m3u8 +6 -0
- package/test/test/assets/hls-ts-h265/index.m3u8 +7 -0
- package/test/test/assets/hls-ts-muxed-aac-h265/0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h265/1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h265/media.m3u8 +9 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/media.m3u8 +24 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00000.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00001.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00002.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00003.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00004.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00005.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0000.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0001.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0002.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0003.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/prog_index.m3u8 +14 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/index.m3u8 +23 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-1-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-2-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-3-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-4-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-5-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-6-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-7-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-8-v1-a1.ts +0 -0
- package/test/test/util/dash_parser_util.js +4 -0
- package/test/test/util/fake_ad_manager.js +20 -0
- package/test/test/util/fake_media_source_engine.js +8 -2
- package/test/test/util/manifest_generator.js +7 -3
- package/test/test/util/mss_parser_util.js +4 -0
- package/test/test/util/offline_utils.js +1 -0
- package/test/test/util/streaming_engine_util.js +7 -4
- package/test/text/ttml_text_parser_unit.js +52 -0
- package/test/text/vtt_text_parser_unit.js +103 -31
- package/test/transmuxer/transmuxer_integration.js +117 -0
- package/test/ui/ui_unit.js +3 -10
- package/test/util/stream_utils_unit.js +208 -74
- package/ui/controls.js +125 -0
- package/ui/externs/ui.js +8 -1
- package/ui/pip_button.js +22 -120
- package/ui/remote_button.js +201 -0
- package/ui/ui.js +5 -2
- package/demo/common/message_ids.js +0 -309
- package/demo/locales/en.json +0 -288
- package/demo/locales/source.json +0 -1146
- package/externs/mux.js +0 -69
- package/lib/lcevc/lcevc_dil.js +0 -152
- package/lib/transmuxer/muxjs_transmuxer.js +0 -242
- package/test/transmuxer/muxjs_transmuxer_integration.js +0 -177
|
@@ -43,10 +43,11 @@ shaka.media.AdaptationSet = class {
|
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* @param {shaka.extern.Variant} variant
|
|
46
|
+
* @param {boolean=} compareCodecs
|
|
46
47
|
* @return {boolean}
|
|
47
48
|
*/
|
|
48
|
-
add(variant) {
|
|
49
|
-
if (this.canInclude(variant)) {
|
|
49
|
+
add(variant, compareCodecs = true) {
|
|
50
|
+
if (this.canInclude(variant, compareCodecs)) {
|
|
50
51
|
this.variants_.add(variant);
|
|
51
52
|
return true;
|
|
52
53
|
}
|
|
@@ -62,18 +63,21 @@ shaka.media.AdaptationSet = class {
|
|
|
62
63
|
* |false|, calling |add| will result in it being ignored.
|
|
63
64
|
*
|
|
64
65
|
* @param {shaka.extern.Variant} variant
|
|
66
|
+
* @param {boolean=} compareCodecs
|
|
65
67
|
* @return {boolean}
|
|
66
68
|
*/
|
|
67
|
-
canInclude(variant) {
|
|
68
|
-
return shaka.media.AdaptationSet
|
|
69
|
+
canInclude(variant, compareCodecs = true) {
|
|
70
|
+
return shaka.media.AdaptationSet
|
|
71
|
+
.areAdaptable(this.root_, variant, compareCodecs);
|
|
69
72
|
}
|
|
70
73
|
|
|
71
74
|
/**
|
|
72
75
|
* @param {shaka.extern.Variant} a
|
|
73
76
|
* @param {shaka.extern.Variant} b
|
|
77
|
+
* @param {boolean=} compareCodecs
|
|
74
78
|
* @return {boolean}
|
|
75
79
|
*/
|
|
76
|
-
static areAdaptable(a, b) {
|
|
80
|
+
static areAdaptable(a, b, compareCodecs = true) {
|
|
77
81
|
const AdaptationSet = shaka.media.AdaptationSet;
|
|
78
82
|
|
|
79
83
|
// All variants should have audio or should all not have audio.
|
|
@@ -95,7 +99,7 @@ shaka.media.AdaptationSet = class {
|
|
|
95
99
|
!!a.audio == !!b.audio,
|
|
96
100
|
'Both should either have audio or not have audio.');
|
|
97
101
|
if (a.audio && b.audio &&
|
|
98
|
-
!AdaptationSet.areAudiosCompatible_(a.audio, b.audio)) {
|
|
102
|
+
!AdaptationSet.areAudiosCompatible_(a.audio, b.audio, compareCodecs)) {
|
|
99
103
|
return false;
|
|
100
104
|
}
|
|
101
105
|
|
|
@@ -103,7 +107,7 @@ shaka.media.AdaptationSet = class {
|
|
|
103
107
|
!!a.video == !!b.video,
|
|
104
108
|
'Both should either have video or not have video.');
|
|
105
109
|
if (a.video && b.video &&
|
|
106
|
-
!AdaptationSet.areVideosCompatible_(a.video, b.video)) {
|
|
110
|
+
!AdaptationSet.areVideosCompatible_(a.video, b.video, compareCodecs)) {
|
|
107
111
|
return false;
|
|
108
112
|
}
|
|
109
113
|
|
|
@@ -122,10 +126,11 @@ shaka.media.AdaptationSet = class {
|
|
|
122
126
|
*
|
|
123
127
|
* @param {shaka.extern.Stream} a
|
|
124
128
|
* @param {shaka.extern.Stream} b
|
|
129
|
+
* @param {boolean} compareCodecs
|
|
125
130
|
* @return {boolean}
|
|
126
131
|
* @private
|
|
127
132
|
*/
|
|
128
|
-
static areAudiosCompatible_(a, b) {
|
|
133
|
+
static areAudiosCompatible_(a, b, compareCodecs) {
|
|
129
134
|
const AdaptationSet = shaka.media.AdaptationSet;
|
|
130
135
|
|
|
131
136
|
// Don't adapt between channel counts, which could annoy the user
|
|
@@ -139,7 +144,7 @@ shaka.media.AdaptationSet = class {
|
|
|
139
144
|
}
|
|
140
145
|
|
|
141
146
|
// We can only adapt between base-codecs.
|
|
142
|
-
if (!AdaptationSet.canTransitionBetween_(a, b)) {
|
|
147
|
+
if (compareCodecs && !AdaptationSet.canTransitionBetween_(a, b)) {
|
|
143
148
|
return false;
|
|
144
149
|
}
|
|
145
150
|
|
|
@@ -148,6 +153,11 @@ shaka.media.AdaptationSet = class {
|
|
|
148
153
|
return false;
|
|
149
154
|
}
|
|
150
155
|
|
|
156
|
+
// We can only adapt between the same groupId.
|
|
157
|
+
if (a.groupId !== b.groupId) {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
|
|
151
161
|
return true;
|
|
152
162
|
}
|
|
153
163
|
|
|
@@ -156,14 +166,15 @@ shaka.media.AdaptationSet = class {
|
|
|
156
166
|
*
|
|
157
167
|
* @param {shaka.extern.Stream} a
|
|
158
168
|
* @param {shaka.extern.Stream} b
|
|
169
|
+
* @param {boolean} compareCodecs
|
|
159
170
|
* @return {boolean}
|
|
160
171
|
* @private
|
|
161
172
|
*/
|
|
162
|
-
static areVideosCompatible_(a, b) {
|
|
173
|
+
static areVideosCompatible_(a, b, compareCodecs) {
|
|
163
174
|
const AdaptationSet = shaka.media.AdaptationSet;
|
|
164
175
|
|
|
165
176
|
// We can only adapt between base-codecs.
|
|
166
|
-
if (!AdaptationSet.canTransitionBetween_(a, b)) {
|
|
177
|
+
if (compareCodecs && !AdaptationSet.canTransitionBetween_(a, b)) {
|
|
167
178
|
return false;
|
|
168
179
|
}
|
|
169
180
|
|
|
@@ -8,8 +8,10 @@ goog.provide('shaka.media.AdaptationSetCriteria');
|
|
|
8
8
|
goog.provide('shaka.media.ExampleBasedCriteria');
|
|
9
9
|
goog.provide('shaka.media.PreferenceBasedCriteria');
|
|
10
10
|
|
|
11
|
+
goog.require('shaka.config.CodecSwitchingStrategy');
|
|
11
12
|
goog.require('shaka.log');
|
|
12
13
|
goog.require('shaka.media.AdaptationSet');
|
|
14
|
+
goog.require('shaka.media.Capabilities');
|
|
13
15
|
goog.require('shaka.util.LanguageUtils');
|
|
14
16
|
goog.require('shaka.util.StreamUtils');
|
|
15
17
|
|
|
@@ -40,10 +42,14 @@ shaka.media.AdaptationSetCriteria = class {
|
|
|
40
42
|
shaka.media.ExampleBasedCriteria = class {
|
|
41
43
|
/**
|
|
42
44
|
* @param {shaka.extern.Variant} example
|
|
45
|
+
* @param {shaka.config.CodecSwitchingStrategy=} codecSwitchingStrategy
|
|
43
46
|
*/
|
|
44
|
-
constructor(example
|
|
47
|
+
constructor(example,
|
|
48
|
+
codecSwitchingStrategy = shaka.config.CodecSwitchingStrategy.RELOAD) {
|
|
45
49
|
/** @private {shaka.extern.Variant} */
|
|
46
50
|
this.example_ = example;
|
|
51
|
+
/** @private {shaka.config.CodecSwitchingStrategy} */
|
|
52
|
+
this.codecSwitchingStrategy_ = codecSwitchingStrategy;
|
|
47
53
|
|
|
48
54
|
// We can't know if role and label are really important, so we don't use
|
|
49
55
|
// role and label for this.
|
|
@@ -56,15 +62,20 @@ shaka.media.ExampleBasedCriteria = class {
|
|
|
56
62
|
|
|
57
63
|
/** @private {!shaka.media.AdaptationSetCriteria} */
|
|
58
64
|
this.fallback_ = new shaka.media.PreferenceBasedCriteria(
|
|
59
|
-
example.language, role, channelCount, hdrLevel, label
|
|
65
|
+
example.language, role, channelCount, hdrLevel, label,
|
|
66
|
+
codecSwitchingStrategy);
|
|
60
67
|
}
|
|
61
68
|
|
|
62
69
|
/** @override */
|
|
63
70
|
create(variants) {
|
|
71
|
+
const supportsSmoothCodecTransitions = this.codecSwitchingStrategy_ ==
|
|
72
|
+
shaka.config.CodecSwitchingStrategy.SMOOTH &&
|
|
73
|
+
shaka.media.Capabilities.isChangeTypeSupported();
|
|
64
74
|
// We can't assume that the example is in |variants| because it could
|
|
65
75
|
// actually be from another period.
|
|
66
76
|
const shortList = variants.filter((variant) => {
|
|
67
|
-
return shaka.media.AdaptationSet.areAdaptable(this.example_, variant
|
|
77
|
+
return shaka.media.AdaptationSet.areAdaptable(this.example_, variant,
|
|
78
|
+
!supportsSmoothCodecTransitions);
|
|
68
79
|
});
|
|
69
80
|
|
|
70
81
|
if (shortList.length) {
|
|
@@ -90,8 +101,10 @@ shaka.media.PreferenceBasedCriteria = class {
|
|
|
90
101
|
* @param {number} channelCount
|
|
91
102
|
* @param {string} hdrLevel
|
|
92
103
|
* @param {string=} label
|
|
104
|
+
* @param {shaka.config.CodecSwitchingStrategy=} codecSwitchingStrategy
|
|
93
105
|
*/
|
|
94
|
-
constructor(language, role, channelCount, hdrLevel, label = ''
|
|
106
|
+
constructor(language, role, channelCount, hdrLevel, label = '',
|
|
107
|
+
codecSwitchingStrategy = shaka.config.CodecSwitchingStrategy.RELOAD) {
|
|
95
108
|
/** @private {string} */
|
|
96
109
|
this.language_ = language;
|
|
97
110
|
/** @private {string} */
|
|
@@ -102,6 +115,8 @@ shaka.media.PreferenceBasedCriteria = class {
|
|
|
102
115
|
this.hdrLevel_ = hdrLevel;
|
|
103
116
|
/** @private {string} */
|
|
104
117
|
this.label_ = label;
|
|
118
|
+
/** @private {shaka.config.CodecSwitchingStrategy} */
|
|
119
|
+
this.codecSwitchingStrategy_ = codecSwitchingStrategy;
|
|
105
120
|
}
|
|
106
121
|
|
|
107
122
|
/** @override */
|
|
@@ -162,12 +177,15 @@ shaka.media.PreferenceBasedCriteria = class {
|
|
|
162
177
|
}
|
|
163
178
|
}
|
|
164
179
|
|
|
180
|
+
const supportsSmoothCodecTransitions = this.codecSwitchingStrategy_ ==
|
|
181
|
+
shaka.config.CodecSwitchingStrategy.SMOOTH &&
|
|
182
|
+
shaka.media.Capabilities.isChangeTypeSupported();
|
|
183
|
+
|
|
165
184
|
// Make sure we only return a valid adaptation set.
|
|
166
185
|
const set = new shaka.media.AdaptationSet(current[0]);
|
|
167
186
|
for (const variant of current) {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
187
|
+
// `add` checks combatability by calling `canInclude` internally.
|
|
188
|
+
set.add(variant, !supportsSmoothCodecTransitions);
|
|
171
189
|
}
|
|
172
190
|
|
|
173
191
|
return set;
|
|
@@ -8,6 +8,7 @@ goog.provide('shaka.media.MediaSourceEngine');
|
|
|
8
8
|
|
|
9
9
|
goog.require('goog.asserts');
|
|
10
10
|
goog.require('shaka.log');
|
|
11
|
+
goog.require('shaka.config.CodecSwitchingStrategy');
|
|
11
12
|
goog.require('shaka.media.Capabilities');
|
|
12
13
|
goog.require('shaka.media.ContentWorkarounds');
|
|
13
14
|
goog.require('shaka.media.ClosedCaptionParser');
|
|
@@ -31,7 +32,7 @@ goog.require('shaka.util.Mp4Parser');
|
|
|
31
32
|
goog.require('shaka.util.Platform');
|
|
32
33
|
goog.require('shaka.util.PublicPromise');
|
|
33
34
|
goog.require('shaka.util.TsParser');
|
|
34
|
-
goog.require('shaka.lcevc.
|
|
35
|
+
goog.require('shaka.lcevc.Dec');
|
|
35
36
|
|
|
36
37
|
|
|
37
38
|
/**
|
|
@@ -53,10 +54,10 @@ shaka.media.MediaSourceEngine = class {
|
|
|
53
54
|
* MediaSourceEngine is destroyed, it will destroy the displayer.
|
|
54
55
|
* @param {!function(!Array.<shaka.extern.ID3Metadata>, number, ?number)=}
|
|
55
56
|
* onMetadata
|
|
56
|
-
* @param {?shaka.lcevc.
|
|
57
|
+
* @param {?shaka.lcevc.Dec} [lcevcDec] Optional - LCEVC Decoder Object
|
|
57
58
|
*
|
|
58
59
|
*/
|
|
59
|
-
constructor(video, textDisplayer, onMetadata,
|
|
60
|
+
constructor(video, textDisplayer, onMetadata, lcevcDec) {
|
|
60
61
|
/** @private {HTMLMediaElement} */
|
|
61
62
|
this.video_ = video;
|
|
62
63
|
|
|
@@ -91,8 +92,8 @@ shaka.media.MediaSourceEngine = class {
|
|
|
91
92
|
number, ?number)} */
|
|
92
93
|
this.onMetadata_ = onMetadata || onMetadataNoOp;
|
|
93
94
|
|
|
94
|
-
/** @private {?shaka.lcevc.
|
|
95
|
-
this.
|
|
95
|
+
/** @private {?shaka.lcevc.Dec} */
|
|
96
|
+
this.lcevcDec_ = lcevcDec || null;
|
|
96
97
|
|
|
97
98
|
/**
|
|
98
99
|
* @private {!Object.<string,
|
|
@@ -115,6 +116,9 @@ shaka.media.MediaSourceEngine = class {
|
|
|
115
116
|
/** @private {string} */
|
|
116
117
|
this.url_ = '';
|
|
117
118
|
|
|
119
|
+
/** @private {boolean} */
|
|
120
|
+
this.playbackHasBegun_ = false;
|
|
121
|
+
|
|
118
122
|
/** @private {MediaSource} */
|
|
119
123
|
this.mediaSource_ = this.createMediaSource(this.mediaSourceOpen_);
|
|
120
124
|
|
|
@@ -138,6 +142,9 @@ shaka.media.MediaSourceEngine = class {
|
|
|
138
142
|
|
|
139
143
|
/** @private {!shaka.util.PublicPromise.<number>} */
|
|
140
144
|
this.textSequenceModeOffset_ = new shaka.util.PublicPromise();
|
|
145
|
+
|
|
146
|
+
/** @private {boolean} */
|
|
147
|
+
this.needSplitMuxedContent_ = false;
|
|
141
148
|
}
|
|
142
149
|
|
|
143
150
|
/**
|
|
@@ -156,6 +163,11 @@ shaka.media.MediaSourceEngine = class {
|
|
|
156
163
|
this.eventManager_.listenOnce(
|
|
157
164
|
mediaSource, 'sourceopen', () => this.onSourceOpen_(p));
|
|
158
165
|
|
|
166
|
+
// Correctly set when playback has begun.
|
|
167
|
+
this.eventManager_.listenOnce(this.video_, 'playing', () => {
|
|
168
|
+
this.playbackHasBegun_ = true;
|
|
169
|
+
});
|
|
170
|
+
|
|
159
171
|
// Store the object URL for releasing it later.
|
|
160
172
|
this.url_ = shaka.media.MediaSourceEngine.createObjectURL(mediaSource);
|
|
161
173
|
|
|
@@ -341,7 +353,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
341
353
|
this.queues_ = {};
|
|
342
354
|
|
|
343
355
|
// This object is owned by Player
|
|
344
|
-
this.
|
|
356
|
+
this.lcevcDec_ = null;
|
|
345
357
|
}
|
|
346
358
|
|
|
347
359
|
/**
|
|
@@ -379,6 +391,8 @@ shaka.media.MediaSourceEngine = class {
|
|
|
379
391
|
async init(streamsByType, sequenceMode=false,
|
|
380
392
|
manifestType=shaka.media.ManifestParser.UNKNOWN,
|
|
381
393
|
ignoreManifestTimestampsInSegmentsMode=false) {
|
|
394
|
+
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
395
|
+
|
|
382
396
|
await this.mediaSourceOpen_;
|
|
383
397
|
|
|
384
398
|
this.sequenceMode_ = sequenceMode;
|
|
@@ -392,8 +406,13 @@ shaka.media.MediaSourceEngine = class {
|
|
|
392
406
|
|
|
393
407
|
for (const contentType of streamsByType.keys()) {
|
|
394
408
|
const stream = streamsByType.get(contentType);
|
|
395
|
-
this.initSourceBuffer_(contentType, stream);
|
|
396
|
-
this.
|
|
409
|
+
this.initSourceBuffer_(contentType, stream, stream.codecs);
|
|
410
|
+
if (this.needSplitMuxedContent_) {
|
|
411
|
+
this.queues_[ContentType.AUDIO] = [];
|
|
412
|
+
this.queues_[ContentType.VIDEO] = [];
|
|
413
|
+
} else {
|
|
414
|
+
this.queues_[contentType] = [];
|
|
415
|
+
}
|
|
397
416
|
}
|
|
398
417
|
}
|
|
399
418
|
|
|
@@ -402,9 +421,10 @@ shaka.media.MediaSourceEngine = class {
|
|
|
402
421
|
*
|
|
403
422
|
* @param {shaka.util.ManifestParserUtils.ContentType} contentType
|
|
404
423
|
* @param {shaka.extern.Stream} stream
|
|
424
|
+
* @param {string} codecs
|
|
405
425
|
* @private
|
|
406
426
|
*/
|
|
407
|
-
initSourceBuffer_(contentType, stream) {
|
|
427
|
+
initSourceBuffer_(contentType, stream, codecs) {
|
|
408
428
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
409
429
|
|
|
410
430
|
goog.asserts.assert(
|
|
@@ -412,7 +432,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
412
432
|
'Type negotiation should happen before MediaSourceEngine.init!');
|
|
413
433
|
|
|
414
434
|
let mimeType = shaka.util.MimeUtils.getFullType(
|
|
415
|
-
stream.mimeType,
|
|
435
|
+
stream.mimeType, codecs);
|
|
416
436
|
if (contentType == ContentType.TEXT) {
|
|
417
437
|
this.reinitText(mimeType, this.sequenceMode_, stream.external);
|
|
418
438
|
} else {
|
|
@@ -424,9 +444,19 @@ shaka.media.MediaSourceEngine = class {
|
|
|
424
444
|
}
|
|
425
445
|
const mimeTypeWithAllCodecs =
|
|
426
446
|
shaka.util.MimeUtils.getFullTypeWithAllCodecs(
|
|
427
|
-
stream.mimeType,
|
|
447
|
+
stream.mimeType, codecs);
|
|
428
448
|
const TransmuxerEngine = shaka.transmuxer.TransmuxerEngine;
|
|
429
449
|
if (needTransmux) {
|
|
450
|
+
const audioCodec = shaka.util.ManifestParserUtils.guessCodecsSafe(
|
|
451
|
+
ContentType.AUDIO, (codecs || '').split(','));
|
|
452
|
+
const videoCodec = shaka.util.ManifestParserUtils.guessCodecsSafe(
|
|
453
|
+
ContentType.VIDEO, (codecs || '').split(','));
|
|
454
|
+
if (audioCodec && videoCodec) {
|
|
455
|
+
this.needSplitMuxedContent_ = true;
|
|
456
|
+
this.initSourceBuffer_(ContentType.AUDIO, stream, audioCodec);
|
|
457
|
+
this.initSourceBuffer_(ContentType.VIDEO, stream, videoCodec);
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
430
460
|
const transmuxerPlugin =
|
|
431
461
|
TransmuxerEngine.findTransmuxer(mimeTypeWithAllCodecs);
|
|
432
462
|
if (transmuxerPlugin) {
|
|
@@ -513,7 +543,8 @@ shaka.media.MediaSourceEngine = class {
|
|
|
513
543
|
* @return {?number} The timestamp in seconds, or null if nothing is buffered.
|
|
514
544
|
*/
|
|
515
545
|
bufferStart(contentType) {
|
|
516
|
-
if (this.reloadingMediaSource_
|
|
546
|
+
if (this.reloadingMediaSource_ ||
|
|
547
|
+
!Object.keys(this.sourceBuffers_).length) {
|
|
517
548
|
return null;
|
|
518
549
|
}
|
|
519
550
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
@@ -743,7 +774,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
743
774
|
*/
|
|
744
775
|
async appendBuffer(
|
|
745
776
|
contentType, data, reference, stream, hasClosedCaptions, seeked = false,
|
|
746
|
-
adaptation = false, isChunkedData = false) {
|
|
777
|
+
adaptation = false, isChunkedData = false, fromSplit = false) {
|
|
747
778
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
748
779
|
|
|
749
780
|
if (contentType == ContentType.TEXT) {
|
|
@@ -759,6 +790,21 @@ shaka.media.MediaSourceEngine = class {
|
|
|
759
790
|
return;
|
|
760
791
|
}
|
|
761
792
|
|
|
793
|
+
if (!fromSplit && this.needSplitMuxedContent_) {
|
|
794
|
+
await this.appendBuffer(ContentType.AUDIO, data, reference, stream,
|
|
795
|
+
hasClosedCaptions, seeked, adaptation, isChunkedData,
|
|
796
|
+
/* fromSplit= */ true);
|
|
797
|
+
await this.appendBuffer(ContentType.VIDEO, data, reference, stream,
|
|
798
|
+
hasClosedCaptions, seeked, adaptation, isChunkedData,
|
|
799
|
+
/* fromSplit= */ true);
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
if (!this.sourceBuffers_[contentType]) {
|
|
804
|
+
shaka.log.warning('Attempted to restore a non-existent source buffer');
|
|
805
|
+
return;
|
|
806
|
+
}
|
|
807
|
+
|
|
762
808
|
let timestampOffset = this.sourceBuffers_[contentType].timestampOffset;
|
|
763
809
|
|
|
764
810
|
let mimeType = this.sourceBufferTypes_[contentType];
|
|
@@ -850,7 +896,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
850
896
|
if (goog.DEBUG && reference && !reference.isPreload() && !isChunkedData) {
|
|
851
897
|
bufferedBefore = this.getBuffered_(contentType);
|
|
852
898
|
}
|
|
853
|
-
this.append_(contentType, data);
|
|
899
|
+
this.append_(contentType, data, timestampOffset);
|
|
854
900
|
});
|
|
855
901
|
|
|
856
902
|
if (goog.DEBUG && reference && !reference.isPreload() && !isChunkedData) {
|
|
@@ -910,6 +956,11 @@ shaka.media.MediaSourceEngine = class {
|
|
|
910
956
|
await this.enqueueOperation_(
|
|
911
957
|
contentType,
|
|
912
958
|
() => this.remove_(contentType, startTime, endTime));
|
|
959
|
+
if (this.needSplitMuxedContent_) {
|
|
960
|
+
await this.enqueueOperation_(
|
|
961
|
+
ContentType.AUDIO,
|
|
962
|
+
() => this.remove_(ContentType.AUDIO, startTime, endTime));
|
|
963
|
+
}
|
|
913
964
|
}
|
|
914
965
|
}
|
|
915
966
|
|
|
@@ -931,6 +982,12 @@ shaka.media.MediaSourceEngine = class {
|
|
|
931
982
|
await this.enqueueOperation_(
|
|
932
983
|
contentType,
|
|
933
984
|
() => this.remove_(contentType, 0, this.mediaSource_.duration));
|
|
985
|
+
if (this.needSplitMuxedContent_) {
|
|
986
|
+
await this.enqueueOperation_(
|
|
987
|
+
ContentType.AUDIO,
|
|
988
|
+
() => this.remove_(
|
|
989
|
+
ContentType.AUDIO, 0, this.mediaSource_.duration));
|
|
990
|
+
}
|
|
934
991
|
}
|
|
935
992
|
}
|
|
936
993
|
|
|
@@ -961,6 +1018,11 @@ shaka.media.MediaSourceEngine = class {
|
|
|
961
1018
|
await this.enqueueOperation_(
|
|
962
1019
|
contentType,
|
|
963
1020
|
() => this.flush_(contentType));
|
|
1021
|
+
if (this.needSplitMuxedContent_) {
|
|
1022
|
+
await this.enqueueOperation_(
|
|
1023
|
+
ContentType.AUDIO,
|
|
1024
|
+
() => this.flush_(ContentType.AUDIO));
|
|
1025
|
+
}
|
|
964
1026
|
}
|
|
965
1027
|
|
|
966
1028
|
/**
|
|
@@ -1014,16 +1076,33 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1014
1076
|
operations.push(this.enqueueOperation_(
|
|
1015
1077
|
contentType,
|
|
1016
1078
|
() => this.abort_(contentType)));
|
|
1079
|
+
if (this.needSplitMuxedContent_) {
|
|
1080
|
+
operations.push(this.enqueueOperation_(
|
|
1081
|
+
ContentType.AUDIO,
|
|
1082
|
+
() => this.abort_(ContentType.AUDIO)));
|
|
1083
|
+
}
|
|
1017
1084
|
}
|
|
1018
1085
|
if (!ignoreTimestampOffset) {
|
|
1019
1086
|
operations.push(this.enqueueOperation_(
|
|
1020
1087
|
contentType,
|
|
1021
1088
|
() => this.setTimestampOffset_(contentType, timestampOffset)));
|
|
1089
|
+
if (this.needSplitMuxedContent_) {
|
|
1090
|
+
operations.push(this.enqueueOperation_(
|
|
1091
|
+
ContentType.AUDIO,
|
|
1092
|
+
() => this.setTimestampOffset_(
|
|
1093
|
+
ContentType.AUDIO, timestampOffset)));
|
|
1094
|
+
}
|
|
1022
1095
|
}
|
|
1023
1096
|
operations.push(this.enqueueOperation_(
|
|
1024
1097
|
contentType,
|
|
1025
1098
|
() => this.setAppendWindow_(
|
|
1026
1099
|
contentType, appendWindowStart, appendWindowEnd)));
|
|
1100
|
+
if (this.needSplitMuxedContent_) {
|
|
1101
|
+
operations.push(this.enqueueOperation_(
|
|
1102
|
+
ContentType.AUDIO,
|
|
1103
|
+
() => this.setAppendWindow_(
|
|
1104
|
+
ContentType.AUDIO, appendWindowStart, appendWindowEnd)));
|
|
1105
|
+
}
|
|
1027
1106
|
|
|
1028
1107
|
await Promise.all(operations);
|
|
1029
1108
|
}
|
|
@@ -1054,9 +1133,19 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1054
1133
|
this.enqueueOperation_(
|
|
1055
1134
|
contentType,
|
|
1056
1135
|
() => this.abort_(contentType));
|
|
1136
|
+
if (this.needSplitMuxedContent_) {
|
|
1137
|
+
this.enqueueOperation_(
|
|
1138
|
+
ContentType.AUDIO,
|
|
1139
|
+
() => this.abort_(ContentType.AUDIO));
|
|
1140
|
+
}
|
|
1057
1141
|
await this.enqueueOperation_(
|
|
1058
1142
|
contentType,
|
|
1059
1143
|
() => this.setTimestampOffset_(contentType, timestampOffset));
|
|
1144
|
+
if (this.needSplitMuxedContent_) {
|
|
1145
|
+
await this.enqueueOperation_(
|
|
1146
|
+
ContentType.AUDIO,
|
|
1147
|
+
() => this.setTimestampOffset_(ContentType.AUDIO, timestampOffset));
|
|
1148
|
+
}
|
|
1060
1149
|
}
|
|
1061
1150
|
|
|
1062
1151
|
/**
|
|
@@ -1120,16 +1209,17 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1120
1209
|
* Append data to the SourceBuffer.
|
|
1121
1210
|
* @param {shaka.util.ManifestParserUtils.ContentType} contentType
|
|
1122
1211
|
* @param {BufferSource} data
|
|
1212
|
+
* @param {number} timestampOffset
|
|
1123
1213
|
* @private
|
|
1124
1214
|
*/
|
|
1125
|
-
append_(contentType, data) {
|
|
1215
|
+
append_(contentType, data, timestampOffset) {
|
|
1126
1216
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
1127
1217
|
|
|
1128
|
-
// Append only video data to the LCEVC
|
|
1129
|
-
if (contentType == ContentType.VIDEO && this.
|
|
1130
|
-
// Append video buffers to the LCEVC
|
|
1218
|
+
// Append only video data to the LCEVC Dec.
|
|
1219
|
+
if (contentType == ContentType.VIDEO && this.lcevcDec_) {
|
|
1220
|
+
// Append video buffers to the LCEVC Dec for parsing and storing
|
|
1131
1221
|
// of LCEVC data.
|
|
1132
|
-
this.
|
|
1222
|
+
this.lcevcDec_.appendBuffer(data, timestampOffset);
|
|
1133
1223
|
}
|
|
1134
1224
|
|
|
1135
1225
|
// This will trigger an 'updateend' event.
|
|
@@ -1292,7 +1382,6 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1292
1382
|
*/
|
|
1293
1383
|
enqueueOperation_(contentType, start) {
|
|
1294
1384
|
this.destroyer_.ensureNotDestroyed();
|
|
1295
|
-
|
|
1296
1385
|
const operation = {
|
|
1297
1386
|
start: start,
|
|
1298
1387
|
p: new shaka.util.PublicPromise(),
|
|
@@ -1563,8 +1652,24 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1563
1652
|
*/
|
|
1564
1653
|
async reset_(streamsByType) {
|
|
1565
1654
|
const Functional = shaka.util.Functional;
|
|
1655
|
+
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
1566
1656
|
this.reloadingMediaSource_ = true;
|
|
1657
|
+
this.needSplitMuxedContent_ = false;
|
|
1567
1658
|
const currentTime = this.video_.currentTime;
|
|
1659
|
+
|
|
1660
|
+
// When codec switching if the user is currently paused we don't want
|
|
1661
|
+
// to trigger a play when switching codec.
|
|
1662
|
+
// Playing can also end up in a paused state after a codec switch
|
|
1663
|
+
// so we need to remember the current states.
|
|
1664
|
+
const previousAutoPlayState = this.video_.autoplay;
|
|
1665
|
+
const previousPausedState = this.video_.paused;
|
|
1666
|
+
if (this.playbackHasBegun_) {
|
|
1667
|
+
// Only set autoplay to false if the video playback has already begun.
|
|
1668
|
+
// When a codec switch happens before playback has begun this can cause
|
|
1669
|
+
// autoplay not to work as expected.
|
|
1670
|
+
this.video_.autoplay = false;
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1568
1673
|
try {
|
|
1569
1674
|
this.eventManager_.removeAll();
|
|
1570
1675
|
|
|
@@ -1598,7 +1703,6 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1598
1703
|
}
|
|
1599
1704
|
await Promise.all(cleanup);
|
|
1600
1705
|
this.transmuxers_ = {};
|
|
1601
|
-
this.queues_ = {};
|
|
1602
1706
|
this.sourceBuffers_ = {};
|
|
1603
1707
|
|
|
1604
1708
|
const previousDuration = this.mediaSource_.duration;
|
|
@@ -1622,7 +1726,13 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1622
1726
|
|
|
1623
1727
|
for (const contentType of streamsByType.keys()) {
|
|
1624
1728
|
const stream = streamsByType.get(contentType);
|
|
1625
|
-
this.initSourceBuffer_(contentType, stream);
|
|
1729
|
+
this.initSourceBuffer_(contentType, stream, stream.codecs);
|
|
1730
|
+
if (this.needSplitMuxedContent_) {
|
|
1731
|
+
this.queues_[ContentType.AUDIO] = [];
|
|
1732
|
+
this.queues_[ContentType.VIDEO] = [];
|
|
1733
|
+
} else {
|
|
1734
|
+
this.queues_[contentType] = [];
|
|
1735
|
+
}
|
|
1626
1736
|
}
|
|
1627
1737
|
|
|
1628
1738
|
// Fake a seek to catchup the playhead.
|
|
@@ -1631,6 +1741,17 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1631
1741
|
await sourceBufferAdded;
|
|
1632
1742
|
} finally {
|
|
1633
1743
|
this.reloadingMediaSource_ = false;
|
|
1744
|
+
|
|
1745
|
+
this.destroyer_.ensureNotDestroyed();
|
|
1746
|
+
|
|
1747
|
+
this.eventManager_.listenOnce(this.video_, 'canplay', () => {
|
|
1748
|
+
this.destroyer_.ensureNotDestroyed();
|
|
1749
|
+
|
|
1750
|
+
this.video_.autoplay = previousAutoPlayState;
|
|
1751
|
+
if (!previousPausedState) {
|
|
1752
|
+
this.video_.play();
|
|
1753
|
+
}
|
|
1754
|
+
});
|
|
1634
1755
|
}
|
|
1635
1756
|
}
|
|
1636
1757
|
|
|
@@ -1696,7 +1817,10 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1696
1817
|
return false;
|
|
1697
1818
|
}
|
|
1698
1819
|
|
|
1699
|
-
if (
|
|
1820
|
+
if (this.config_.codecSwitchingStrategy ===
|
|
1821
|
+
shaka.config.CodecSwitchingStrategy.SMOOTH &&
|
|
1822
|
+
shaka.media.Capabilities.isChangeTypeSupported() &&
|
|
1823
|
+
!this.needSplitMuxedContent_) {
|
|
1700
1824
|
await this.changeType(contentType, newMimeType, transmuxer);
|
|
1701
1825
|
} else {
|
|
1702
1826
|
if (transmuxer) {
|
|
@@ -1708,11 +1832,75 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1708
1832
|
}
|
|
1709
1833
|
|
|
1710
1834
|
/**
|
|
1711
|
-
*
|
|
1712
|
-
*
|
|
1835
|
+
* Returns true if it's necessary codec switch to load the new stream.
|
|
1836
|
+
*
|
|
1837
|
+
* @param {shaka.util.ManifestParserUtils.ContentType} contentType
|
|
1838
|
+
* @param {shaka.extern.Stream} stream
|
|
1839
|
+
* @return {boolean}
|
|
1840
|
+
* @private
|
|
1841
|
+
*/
|
|
1842
|
+
isCodecSwitchNecessary_(contentType, stream) {
|
|
1843
|
+
const MimeUtils = shaka.util.MimeUtils;
|
|
1844
|
+
const currentCodec = MimeUtils.getCodecBase(
|
|
1845
|
+
MimeUtils.getCodecs(this.sourceBufferTypes_[contentType]));
|
|
1846
|
+
const currentBasicType = MimeUtils.getBasicType(
|
|
1847
|
+
this.sourceBufferTypes_[contentType]);
|
|
1848
|
+
|
|
1849
|
+
let newMimeType = shaka.util.MimeUtils.getFullType(
|
|
1850
|
+
stream.mimeType, stream.codecs);
|
|
1851
|
+
let needTransmux = this.config_.forceTransmux;
|
|
1852
|
+
if (!shaka.media.Capabilities.isTypeSupported(newMimeType) ||
|
|
1853
|
+
(!this.sequenceMode_ &&
|
|
1854
|
+
shaka.util.MimeUtils.RAW_FORMATS.includes(newMimeType))) {
|
|
1855
|
+
needTransmux = true;
|
|
1856
|
+
}
|
|
1857
|
+
const newMimeTypeWithAllCodecs =
|
|
1858
|
+
shaka.util.MimeUtils.getFullTypeWithAllCodecs(
|
|
1859
|
+
stream.mimeType, stream.codecs);
|
|
1860
|
+
const TransmuxerEngine = shaka.transmuxer.TransmuxerEngine;
|
|
1861
|
+
if (needTransmux) {
|
|
1862
|
+
const transmuxerPlugin =
|
|
1863
|
+
TransmuxerEngine.findTransmuxer(newMimeTypeWithAllCodecs);
|
|
1864
|
+
if (transmuxerPlugin) {
|
|
1865
|
+
const transmuxer = transmuxerPlugin();
|
|
1866
|
+
newMimeType =
|
|
1867
|
+
transmuxer.convertCodecs(contentType, newMimeTypeWithAllCodecs);
|
|
1868
|
+
transmuxer.destroy();
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
|
|
1872
|
+
const newCodec = MimeUtils.getCodecBase(
|
|
1873
|
+
MimeUtils.getCodecs(newMimeType));
|
|
1874
|
+
const newBasicType = MimeUtils.getBasicType(newMimeType);
|
|
1875
|
+
|
|
1876
|
+
return currentCodec !== newCodec || currentBasicType !== newBasicType;
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1879
|
+
/**
|
|
1880
|
+
* Returns true if it's necessary reset the media source to load the
|
|
1881
|
+
* new stream.
|
|
1882
|
+
*
|
|
1883
|
+
* @param {shaka.util.ManifestParserUtils.ContentType} contentType
|
|
1884
|
+
* @param {shaka.extern.Stream} stream
|
|
1885
|
+
* @return {boolean}
|
|
1886
|
+
*/
|
|
1887
|
+
isResetMediaSourceNecessary(contentType, stream) {
|
|
1888
|
+
if (!this.isCodecSwitchNecessary_(contentType, stream)) {
|
|
1889
|
+
return false;
|
|
1890
|
+
}
|
|
1891
|
+
|
|
1892
|
+
return this.config_.codecSwitchingStrategy !==
|
|
1893
|
+
shaka.config.CodecSwitchingStrategy.SMOOTH ||
|
|
1894
|
+
!shaka.media.Capabilities.isChangeTypeSupported() ||
|
|
1895
|
+
this.needSplitMuxedContent_;
|
|
1896
|
+
}
|
|
1897
|
+
|
|
1898
|
+
/**
|
|
1899
|
+
* Update LCEVC Decoder object when ready for LCEVC Decode.
|
|
1900
|
+
* @param {?shaka.lcevc.Dec} lcevcDec
|
|
1713
1901
|
*/
|
|
1714
|
-
|
|
1715
|
-
this.
|
|
1902
|
+
updateLcevcDec(lcevcDec) {
|
|
1903
|
+
this.lcevcDec_ = lcevcDec;
|
|
1716
1904
|
}
|
|
1717
1905
|
};
|
|
1718
1906
|
|
|
@@ -379,7 +379,7 @@ shaka.media.SegmentIndex = class {
|
|
|
379
379
|
lastReference.tileDuration,
|
|
380
380
|
lastReference.syncTime,
|
|
381
381
|
lastReference.status,
|
|
382
|
-
lastReference.
|
|
382
|
+
lastReference.aes128Key,
|
|
383
383
|
);
|
|
384
384
|
this.references[this.references.length - 1].discontinuitySequence =
|
|
385
385
|
lastReference.discontinuitySequence;
|