shaka-player 4.5.0 → 4.6.1

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.
Files changed (214) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
  2. package/AUTHORS +2 -0
  3. package/CHANGELOG.md +109 -0
  4. package/CODE_OF_CONDUCT.md +1 -1
  5. package/CONTRIBUTORS +2 -0
  6. package/README.md +38 -32
  7. package/demo/common/asset.js +11 -17
  8. package/demo/common/assets.js +117 -11
  9. package/demo/config.js +28 -1
  10. package/demo/custom.js +52 -38
  11. package/demo/main.js +11 -3
  12. package/demo/search.js +7 -0
  13. package/dist/controls.css +1 -1
  14. package/dist/controls.css.map +1 -1
  15. package/dist/demo.compiled.debug.js +133 -124
  16. package/dist/demo.compiled.debug.map +3 -3
  17. package/dist/demo.compiled.js +133 -124
  18. package/dist/demo.compiled.map +3 -3
  19. package/dist/deps.js +20 -18
  20. package/dist/locales.js +34 -30
  21. package/dist/receiver.compiled.debug.js +58 -50
  22. package/dist/receiver.compiled.debug.map +3 -3
  23. package/dist/receiver.compiled.js +58 -50
  24. package/dist/receiver.compiled.map +3 -3
  25. package/dist/shaka-player.compiled.d.ts +440 -390
  26. package/dist/shaka-player.compiled.debug.d.ts +440 -390
  27. package/dist/shaka-player.compiled.debug.externs.js +162 -77
  28. package/dist/shaka-player.compiled.debug.js +789 -738
  29. package/dist/shaka-player.compiled.debug.map +4 -4
  30. package/dist/shaka-player.compiled.externs.js +162 -77
  31. package/dist/shaka-player.compiled.js +1147 -1113
  32. package/dist/shaka-player.compiled.map +4 -4
  33. package/dist/shaka-player.ui.d.ts +491 -437
  34. package/dist/shaka-player.ui.debug.d.ts +491 -437
  35. package/dist/shaka-player.ui.debug.externs.js +167 -77
  36. package/dist/shaka-player.ui.debug.js +857 -791
  37. package/dist/shaka-player.ui.debug.map +4 -4
  38. package/dist/shaka-player.ui.externs.js +167 -77
  39. package/dist/shaka-player.ui.js +1359 -1314
  40. package/dist/shaka-player.ui.map +4 -4
  41. package/docs/tutorials/ad_monetization.md +54 -0
  42. package/docs/tutorials/basic-usage.md +2 -1
  43. package/docs/tutorials/errors.md +2 -1
  44. package/docs/tutorials/offline.md +10 -8
  45. package/docs/tutorials/plugins.md +5 -0
  46. package/docs/tutorials/ui-customization.md +13 -0
  47. package/docs/tutorials/ui.md +2 -1
  48. package/docs/tutorials/upgrade.md +3 -0
  49. package/externs/managedmediasource.js +24 -0
  50. package/externs/shaka/abr_manager.js +6 -2
  51. package/externs/shaka/cea.js +7 -0
  52. package/externs/shaka/codecs.js +5 -3
  53. package/externs/shaka/manifest.js +21 -5
  54. package/externs/shaka/manifest_parser.js +17 -0
  55. package/externs/shaka/net.js +2 -2
  56. package/externs/shaka/offline.js +9 -2
  57. package/externs/shaka/player.js +53 -7
  58. package/externs/shaka/text.js +3 -1
  59. package/externs/shaka/transmuxer.js +1 -1
  60. package/lib/abr/simple_abr_manager.js +25 -8
  61. package/lib/ads/media_tailor_ad_manager.js +14 -3
  62. package/lib/cast/cast_receiver.js +1 -1
  63. package/lib/cea/cea_decoder.js +28 -0
  64. package/lib/cea/dummy_caption_decoder.js +5 -0
  65. package/lib/dash/dash_parser.js +251 -84
  66. package/lib/dash/mpd_utils.js +52 -31
  67. package/lib/dash/segment_base.js +4 -5
  68. package/lib/dash/segment_list.js +5 -4
  69. package/lib/dash/segment_template.js +92 -29
  70. package/lib/hls/hls_classes.js +28 -43
  71. package/lib/hls/hls_parser.js +770 -652
  72. package/lib/hls/hls_utils.js +64 -5
  73. package/lib/hls/manifest_text_parser.js +7 -11
  74. package/lib/media/adaptation_set.js +20 -13
  75. package/lib/media/adaptation_set_criteria.js +70 -18
  76. package/lib/media/closed_caption_parser.js +13 -0
  77. package/lib/media/content_workarounds.js +6 -0
  78. package/lib/media/drm_engine.js +8 -13
  79. package/lib/media/manifest_parser.js +8 -113
  80. package/lib/media/media_source_capabilities.js +10 -3
  81. package/lib/media/media_source_engine.js +75 -21
  82. package/lib/media/play_rate_controller.js +8 -38
  83. package/lib/media/presentation_timeline.js +7 -1
  84. package/lib/media/quality_observer.js +1 -1
  85. package/lib/media/segment_index.js +5 -5
  86. package/lib/media/segment_prefetch.js +92 -24
  87. package/lib/media/segment_reference.js +67 -1
  88. package/lib/media/segment_utils.js +343 -0
  89. package/lib/media/stall_detector.js +0 -3
  90. package/lib/media/streaming_engine.js +72 -44
  91. package/lib/mss/mss_parser.js +18 -2
  92. package/lib/net/networking_engine.js +66 -12
  93. package/lib/net/networking_utils.js +95 -0
  94. package/lib/offline/indexeddb/v1_storage_cell.js +2 -0
  95. package/lib/offline/indexeddb/v2_storage_cell.js +2 -0
  96. package/lib/offline/manifest_converter.js +2 -0
  97. package/lib/offline/offline_manifest_parser.js +10 -0
  98. package/lib/offline/storage.js +11 -7
  99. package/lib/player.js +998 -1503
  100. package/lib/polyfill/mediasource.js +22 -1
  101. package/lib/text/mp4_ttml_parser.js +2 -2
  102. package/lib/text/srt_text_parser.js +2 -2
  103. package/lib/text/stub_text_displayer.js +51 -0
  104. package/lib/text/text_engine.js +3 -2
  105. package/lib/text/ttml_text_parser.js +28 -5
  106. package/lib/text/ui_text_displayer.js +4 -0
  107. package/lib/text/vtt_text_parser.js +7 -2
  108. package/lib/transmuxer/aac_transmuxer.js +1 -1
  109. package/lib/transmuxer/ac3_transmuxer.js +1 -1
  110. package/lib/transmuxer/ec3_transmuxer.js +1 -1
  111. package/lib/transmuxer/h264.js +5 -4
  112. package/lib/transmuxer/h265.js +5 -4
  113. package/lib/transmuxer/mp3_transmuxer.js +1 -1
  114. package/lib/transmuxer/mpeg_ts_transmuxer.js +1 -1
  115. package/lib/transmuxer/mss_transmuxer.js +1 -1
  116. package/lib/transmuxer/ts_transmuxer.js +33 -13
  117. package/lib/util/buffer_utils.js +26 -4
  118. package/lib/util/content_steering_manager.js +358 -0
  119. package/lib/util/error.js +2 -6
  120. package/lib/util/fairplay_utils.js +1 -1
  121. package/lib/util/fake_event.js +5 -1
  122. package/lib/util/id3_utils.js +50 -1
  123. package/lib/util/manifest_parser_utils.js +12 -8
  124. package/lib/util/mp4_generator.js +2 -4
  125. package/lib/util/mutex.js +59 -0
  126. package/lib/util/object_utils.js +1 -1
  127. package/lib/util/periods.js +154 -179
  128. package/lib/util/platform.js +4 -3
  129. package/lib/util/player_configuration.js +35 -6
  130. package/lib/util/stream_utils.js +105 -98
  131. package/lib/util/ts_parser.js +124 -73
  132. package/lib/util/uint8array_utils.js +5 -1
  133. package/lib/util/xml_utils.js +5 -0
  134. package/maintained-branches.md +2 -2
  135. package/package.json +1 -1
  136. package/roadmap.md +15 -5
  137. package/shaka-player.uncompiled.js +0 -1
  138. package/test/abr/simple_abr_manager_unit.js +33 -33
  139. package/test/ads/ad_manager_unit.js +3 -2
  140. package/test/cast/cast_receiver_integration.js +3 -4
  141. package/test/cast/cast_utils_unit.js +2 -0
  142. package/test/cea/cea_decoder_unit.js +7 -0
  143. package/test/codec_switching/codec_switching_integration.js +2 -1
  144. package/test/dash/dash_parser_integration.js +2 -1
  145. package/test/dash/dash_parser_live_unit.js +0 -19
  146. package/test/dash/dash_parser_manifest_unit.js +494 -2
  147. package/test/dash/mpd_utils_unit.js +61 -30
  148. package/test/hls/hls_live_unit.js +12 -3
  149. package/test/hls/hls_parser_unit.js +417 -27
  150. package/test/hls/manifest_text_parser_unit.js +32 -99
  151. package/test/media/adaptation_set_criteria_unit.js +172 -21
  152. package/test/media/adaptation_set_unit.js +1 -0
  153. package/test/media/content_workarounds_unit.js +1 -1
  154. package/test/media/drm_engine_unit.js +3 -3
  155. package/test/media/media_source_engine_unit.js +1 -1
  156. package/test/media/play_rate_controller_unit.js +0 -48
  157. package/test/media/segment_index_unit.js +2 -1
  158. package/test/mss/mss_player_integration.js +3 -2
  159. package/test/net/networking_engine_unit.js +3 -3
  160. package/test/{media/manifest_parser_unit.js → net/networking_utils_unit.js} +2 -2
  161. package/test/offline/manifest_convert_unit.js +9 -0
  162. package/test/offline/offline_integration.js +2 -1
  163. package/test/offline/storage_integration.js +21 -9
  164. package/test/player_external.js +4 -2
  165. package/test/player_integration.js +15 -4
  166. package/test/player_load_graph_integration.js +47 -151
  167. package/test/player_src_equals_external.js +1 -0
  168. package/test/player_src_equals_integration.js +71 -4
  169. package/test/player_unit.js +80 -27
  170. package/test/test/util/fake_media_source_engine.js +5 -0
  171. package/test/test/util/fake_networking_engine.js +9 -1
  172. package/test/test/util/fake_segment_prefetch.js +3 -0
  173. package/test/test/util/manifest_generator.js +4 -0
  174. package/test/test/util/manifest_parser_util.js +14 -2
  175. package/test/test/util/offline_utils.js +1 -0
  176. package/test/test/util/simple_fakes.js +2 -2
  177. package/test/test/util/streaming_engine_util.js +3 -0
  178. package/test/test/util/test_scheme.js +6 -0
  179. package/test/test/util/ui_utils.js +4 -3
  180. package/test/text/mp4_ttml_parser_unit.js +4 -4
  181. package/test/text/srt_text_parser_unit.js +1 -1
  182. package/test/text/text_displayer_layout_unit.js +1 -1
  183. package/test/text/text_engine_unit.js +6 -0
  184. package/test/text/ttml_text_parser_unit.js +33 -2
  185. package/test/transmuxer/transmuxer_engine_integration.js +9 -0
  186. package/test/transmuxer/transmuxer_integration.js +33 -3
  187. package/test/ui/ad_ui_unit.js +2 -2
  188. package/test/ui/ui_customization_unit.js +17 -16
  189. package/test/ui/ui_integration.js +30 -20
  190. package/test/ui/ui_unit.js +25 -19
  191. package/test/util/buffer_utils_unit.js +1 -1
  192. package/test/util/content_steering_manager_unit.js +427 -0
  193. package/test/util/id3_utils_unit.js +52 -0
  194. package/test/util/stream_utils_unit.js +17 -113
  195. package/test/util/ts_parser_unit.js +3 -3
  196. package/third_party/closure-uri/uri.js +13 -1
  197. package/ui/audio_language_selection.js +9 -2
  198. package/ui/externs/ui.js +17 -2
  199. package/ui/language_utils.js +43 -8
  200. package/ui/less/range_elements.less +33 -0
  201. package/ui/locales/en.json +1 -0
  202. package/ui/locales/es-419.json +1 -0
  203. package/ui/locales/es.json +1 -0
  204. package/ui/locales/source.json +4 -0
  205. package/ui/localization.js +10 -0
  206. package/ui/remote_button.js +3 -1
  207. package/ui/resolution_selection.js +47 -10
  208. package/ui/seek_bar.js +296 -3
  209. package/ui/text_selection.js +2 -1
  210. package/ui/ui.js +6 -2
  211. package/lib/routing/node.js +0 -23
  212. package/lib/routing/payload.js +0 -47
  213. package/lib/routing/walker.js +0 -587
  214. package/test/routing/walker_unit.js +0 -505
@@ -6,9 +6,8 @@
6
6
 
7
7
  goog.provide('shaka.media.ManifestParser');
8
8
 
9
- goog.require('goog.Uri');
9
+ goog.require('shaka.Deprecate');
10
10
  goog.require('shaka.log');
11
- goog.require('shaka.net.NetworkingEngine');
12
11
  goog.require('shaka.util.Error');
13
12
  goog.require('shaka.util.Platform');
14
13
 
@@ -28,7 +27,9 @@ shaka.media.ManifestParser = class {
28
27
  * @export
29
28
  */
30
29
  static registerParserByExtension(extension, parserFactory) {
31
- shaka.media.ManifestParser.parsersByExtension[extension] = parserFactory;
30
+ shaka.Deprecate.deprecateFeature(5,
31
+ 'ManifestParser',
32
+ 'Please use an ManifestParser with registerParserByMime function.');
32
33
  }
33
34
 
34
35
 
@@ -70,9 +71,6 @@ shaka.media.ManifestParser = class {
70
71
  for (const type in ManifestParser.parsersByMime) {
71
72
  support[type] = true;
72
73
  }
73
- for (const type in ManifestParser.parsersByExtension) {
74
- support[type] = true;
75
- }
76
74
  }
77
75
 
78
76
  // Make sure all well-known types are tested as well, just to show an
@@ -86,14 +84,6 @@ shaka.media.ManifestParser = class {
86
84
  // SmoothStreaming
87
85
  'application/vnd.ms-sstr+xml',
88
86
  ];
89
- const testExtensions = {
90
- // DASH
91
- 'mpd': 'application/dash+xml',
92
- // HLS
93
- 'm3u8': 'application/x-mpegurl',
94
- // SmoothStreaming
95
- 'ism': 'application/vnd.ms-sstr+xml',
96
- };
97
87
 
98
88
  for (const type of testMimeTypes) {
99
89
  // Only query our parsers for MSE-enabled platforms. Otherwise, query a
@@ -105,18 +95,6 @@ shaka.media.ManifestParser = class {
105
95
  }
106
96
  }
107
97
 
108
- for (const extension in testExtensions) {
109
- // Only query our parsers for MSE-enabled platforms. Otherwise, query a
110
- // temporary media element for native support for these MIME type for the
111
- // extension.
112
- if (shaka.util.Platform.supportsMediaSource()) {
113
- support[extension] = !!ManifestParser.parsersByExtension[extension];
114
- } else {
115
- const type = testExtensions[extension];
116
- support[extension] = shaka.util.Platform.supportsMediaType(type);
117
- }
118
- }
119
-
120
98
  return support;
121
99
  }
122
100
 
@@ -126,12 +104,10 @@ shaka.media.ManifestParser = class {
126
104
  * parse the manifest at |uri|.
127
105
  *
128
106
  * @param {string} uri
129
- * @param {!shaka.net.NetworkingEngine} netEngine
130
- * @param {shaka.extern.RetryParameters} retryParams
131
107
  * @param {?string} mimeType
132
- * @return {!Promise.<shaka.extern.ManifestParser.Factory>}
108
+ * @return {shaka.extern.ManifestParser.Factory}
133
109
  */
134
- static async getFactory(uri, netEngine, retryParams, mimeType) {
110
+ static getFactory(uri, mimeType) {
135
111
  const ManifestParser = shaka.media.ManifestParser;
136
112
 
137
113
  // Try using the MIME type we were given.
@@ -145,33 +121,6 @@ shaka.media.ManifestParser = class {
145
121
  'Could not determine manifest type using MIME type ', mimeType);
146
122
  }
147
123
 
148
- const extension = ManifestParser.getExtension(uri);
149
- if (extension) {
150
- const factory = ManifestParser.parsersByExtension[extension];
151
- if (factory) {
152
- return factory;
153
- }
154
-
155
- shaka.log.warning(
156
- 'Could not determine manifest type for extension ', extension);
157
- } else {
158
- shaka.log.warning('Could not find extension for ', uri);
159
- }
160
-
161
- if (!mimeType) {
162
- mimeType = await ManifestParser.getMimeType(uri, netEngine, retryParams);
163
-
164
- if (mimeType) {
165
- const factory = shaka.media.ManifestParser.parsersByMime[mimeType];
166
- if (factory) {
167
- return factory;
168
- }
169
-
170
- shaka.log.warning('Could not determine manifest type using MIME type',
171
- mimeType);
172
- }
173
- }
174
-
175
124
  throw new shaka.util.Error(
176
125
  shaka.util.Error.Severity.CRITICAL,
177
126
  shaka.util.Error.Category.MANIFEST,
@@ -181,56 +130,15 @@ shaka.media.ManifestParser = class {
181
130
 
182
131
 
183
132
  /**
184
- * @param {string} uri
185
- * @param {!shaka.net.NetworkingEngine} netEngine
186
- * @param {shaka.extern.RetryParameters} retryParams
187
- * @return {!Promise.<string>}
188
- */
189
- static async getMimeType(uri, netEngine, retryParams) {
190
- const type = shaka.net.NetworkingEngine.RequestType.MANIFEST;
191
-
192
- const request = shaka.net.NetworkingEngine.makeRequest([uri], retryParams);
193
- request.method = 'HEAD';
194
-
195
- const response = await netEngine.request(type, request).promise;
196
-
197
- // https://bit.ly/2K9s9kf says this header should always be available,
198
- // but just to be safe:
199
- const mimeType = response.headers['content-type'];
200
- return mimeType ? mimeType.toLowerCase().split(';').shift() : '';
201
- }
202
-
203
-
204
- /**
205
- * @param {string} uri
206
- * @return {string}
207
- */
208
- static getExtension(uri) {
209
- const uriObj = new goog.Uri(uri);
210
- const uriPieces = uriObj.getPath().split('/');
211
- const uriFilename = uriPieces.pop();
212
- const filenamePieces = uriFilename.split('.');
213
-
214
- // Only one piece means there is no extension.
215
- if (filenamePieces.length == 1) {
216
- return '';
217
- }
218
-
219
- return filenamePieces.pop().toLowerCase();
220
- }
221
-
222
-
223
- /**
224
- * Determines whether or not this URI and MIME type are supported by our own
133
+ * Determines whether or not the MIME type is supported by our own
225
134
  * manifest parsers on this platform. This takes into account whether or not
226
135
  * MediaSource is available, as well as which parsers are registered to the
227
136
  * system.
228
137
  *
229
- * @param {string} uri
230
138
  * @param {string} mimeType
231
139
  * @return {boolean}
232
140
  */
233
- static isSupported(uri, mimeType) {
141
+ static isSupported(mimeType) {
234
142
  // Without MediaSource, our own parsers are useless.
235
143
  if (!shaka.util.Platform.supportsMediaSource()) {
236
144
  return false;
@@ -240,11 +148,6 @@ shaka.media.ManifestParser = class {
240
148
  return true;
241
149
  }
242
150
 
243
- const extension = shaka.media.ManifestParser.getExtension(uri);
244
- if (extension in shaka.media.ManifestParser.parsersByExtension) {
245
- return true;
246
- }
247
-
248
151
  return false;
249
152
  }
250
153
  };
@@ -292,11 +195,3 @@ shaka.media.ManifestParser.AccessibilityPurpose = {
292
195
  shaka.media.ManifestParser.parsersByMime = {};
293
196
 
294
197
 
295
- /**
296
- * Contains the parser factory functions indexed by file extension.
297
- *
298
- * @type {!Object.<string, shaka.extern.ManifestParser.Factory>}
299
- */
300
- shaka.media.ManifestParser.parsersByExtension = {};
301
-
302
-
@@ -23,9 +23,16 @@ shaka.media.Capabilities = class {
23
23
  if (supportMap.has(type)) {
24
24
  return supportMap.get(type);
25
25
  }
26
- const currentSupport = MediaSource.isTypeSupported(type);
27
- supportMap.set(type, currentSupport);
28
- return currentSupport;
26
+ if (window.ManagedMediaSource) {
27
+ const currentSupport = ManagedMediaSource.isTypeSupported(type);
28
+ supportMap.set(type, currentSupport);
29
+ return currentSupport;
30
+ } else if (window.MediaSource) {
31
+ const currentSupport = MediaSource.isTypeSupported(type);
32
+ supportMap.set(type, currentSupport);
33
+ return currentSupport;
34
+ }
35
+ return false;
29
36
  }
30
37
 
31
38
  /**
@@ -119,7 +119,7 @@ shaka.media.MediaSourceEngine = class {
119
119
  /** @private {boolean} */
120
120
  this.playbackHasBegun_ = false;
121
121
 
122
- /** @private {MediaSource} */
122
+ /** @private {(MediaSource|ManagedMediaSource)} */
123
123
  this.mediaSource_ = this.createMediaSource(this.mediaSourceOpen_);
124
124
 
125
125
  /** @private {boolean} */
@@ -145,6 +145,9 @@ shaka.media.MediaSourceEngine = class {
145
145
 
146
146
  /** @private {boolean} */
147
147
  this.needSplitMuxedContent_ = false;
148
+
149
+ /** @private {boolean} */
150
+ this.streamingAllowed_ = true;
148
151
  }
149
152
 
150
153
  /**
@@ -154,30 +157,60 @@ shaka.media.MediaSourceEngine = class {
154
157
  * Replaced by unit tests.
155
158
  *
156
159
  * @param {!shaka.util.PublicPromise} p
157
- * @return {!MediaSource}
160
+ * @return {!(MediaSource|ManagedMediaSource)}
158
161
  */
159
162
  createMediaSource(p) {
160
- const mediaSource = new MediaSource();
163
+ if (window.ManagedMediaSource) {
164
+ this.video_.disableRemotePlayback = true;
161
165
 
162
- // Set up MediaSource on the video element.
163
- this.eventManager_.listenOnce(
164
- mediaSource, 'sourceopen', () => this.onSourceOpen_(p));
166
+ const mediaSource = new ManagedMediaSource();
165
167
 
166
- // Correctly set when playback has begun.
167
- this.eventManager_.listenOnce(this.video_, 'playing', () => {
168
- this.playbackHasBegun_ = true;
169
- });
168
+ this.eventManager_.listenOnce(
169
+ mediaSource, 'sourceopen', () => this.onSourceOpen_(p));
170
+
171
+ this.eventManager_.listen(
172
+ mediaSource, 'startstreaming', () => {
173
+ this.streamingAllowed_ = true;
174
+ });
175
+
176
+ this.eventManager_.listen(
177
+ mediaSource, 'endstreaming', () => {
178
+ this.streamingAllowed_ = false;
179
+ });
180
+
181
+ // Correctly set when playback has begun.
182
+ this.eventManager_.listenOnce(this.video_, 'playing', () => {
183
+ this.playbackHasBegun_ = true;
184
+ });
185
+
186
+ this.url_ = shaka.media.MediaSourceEngine.createObjectURL(mediaSource);
187
+
188
+ this.video_.src = this.url_;
189
+
190
+ return mediaSource;
191
+ } else {
192
+ const mediaSource = new MediaSource();
193
+
194
+ // Set up MediaSource on the video element.
195
+ this.eventManager_.listenOnce(
196
+ mediaSource, 'sourceopen', () => this.onSourceOpen_(p));
170
197
 
171
- // Store the object URL for releasing it later.
172
- this.url_ = shaka.media.MediaSourceEngine.createObjectURL(mediaSource);
198
+ // Correctly set when playback has begun.
199
+ this.eventManager_.listenOnce(this.video_, 'playing', () => {
200
+ this.playbackHasBegun_ = true;
201
+ });
202
+
203
+ // Store the object URL for releasing it later.
204
+ this.url_ = shaka.media.MediaSourceEngine.createObjectURL(mediaSource);
173
205
 
174
- this.video_.src = this.url_;
206
+ this.video_.src = this.url_;
175
207
 
176
- return mediaSource;
208
+ return mediaSource;
209
+ }
177
210
  }
178
211
 
179
212
  /**
180
- * @param {!shaka.util.PublicPromise} p
213
+ * @param {shaka.util.PublicPromise} p
181
214
  * @private
182
215
  */
183
216
  onSourceOpen_(p) {
@@ -229,9 +262,11 @@ shaka.media.MediaSourceEngine = class {
229
262
  'video/mp4; codecs="vp9"',
230
263
  'video/mp4; codecs="vp09.00.10.08"',
231
264
  'video/mp4; codecs="av01.0.01M.08"',
265
+ 'video/mp4; codecs="dvh1.20.01"',
232
266
  'audio/mp4; codecs="mp4a.40.2"',
233
267
  'audio/mp4; codecs="ac-3"',
234
268
  'audio/mp4; codecs="ec-3"',
269
+ 'audio/mp4; codecs="ac-4"',
235
270
  'audio/mp4; codecs="opus"',
236
271
  'audio/mp4; codecs="flac"',
237
272
  'audio/mp4; codecs="dtsc"', // DTS Digital Surround
@@ -480,8 +515,8 @@ shaka.media.MediaSourceEngine = class {
480
515
  shaka.util.Error.Category.MEDIA,
481
516
  shaka.util.Error.Code.MEDIA_SOURCE_OPERATION_THREW,
482
517
  exception,
483
- 'The mediaSource_ status was' + this.mediaSource_.readyState +
484
- 'expected \'open\'');
518
+ 'The mediaSource_ status was ' + this.mediaSource_.readyState +
519
+ ' expected \'open\'');
485
520
  }
486
521
 
487
522
  if (this.sequenceMode_) {
@@ -511,6 +546,16 @@ shaka.media.MediaSourceEngine = class {
511
546
  this.config_ = config;
512
547
  }
513
548
 
549
+ /**
550
+ * Indicate if the streaming is allowed by MediaSourceEngine.
551
+ * If we using MediaSource we allways returns true.
552
+ *
553
+ * @return {boolean}
554
+ */
555
+ isStreamingAllowed() {
556
+ return this.streamingAllowed_;
557
+ }
558
+
514
559
  /**
515
560
  * Reinitialize the TextEngine for a new text type.
516
561
  * @param {string} mimeType
@@ -739,7 +784,7 @@ shaka.media.MediaSourceEngine = class {
739
784
  } else if (!mimeType.includes('/mp4') && !mimeType.includes('/webm') &&
740
785
  shaka.util.TsParser.probe(uint8ArrayData)) {
741
786
  const tsParser = new shaka.util.TsParser().parse(uint8ArrayData);
742
- const startTime = tsParser.getStartTime()[contentType];
787
+ const startTime = tsParser.getStartTime(contentType);
743
788
  if (startTime != null) {
744
789
  timestamp = startTime;
745
790
  }
@@ -786,7 +831,8 @@ shaka.media.MediaSourceEngine = class {
786
831
  await this.textEngine_.appendBuffer(
787
832
  data,
788
833
  reference ? reference.startTime : null,
789
- reference ? reference.endTime : null);
834
+ reference ? reference.endTime : null,
835
+ reference ? reference.getUris()[0] : null);
790
836
  return;
791
837
  }
792
838
 
@@ -809,7 +855,7 @@ shaka.media.MediaSourceEngine = class {
809
855
 
810
856
  let mimeType = this.sourceBufferTypes_[contentType];
811
857
  if (this.transmuxers_[contentType]) {
812
- mimeType = this.transmuxers_[contentType].getOrginalMimeType();
858
+ mimeType = this.transmuxers_[contentType].getOriginalMimeType();
813
859
  }
814
860
  if (reference) {
815
861
  const timestamp = this.getTimestampAndDispatchMetadata_(
@@ -818,7 +864,9 @@ shaka.media.MediaSourceEngine = class {
818
864
  const calculatedTimestampOffset = reference.startTime - timestamp;
819
865
  const timestampOffsetDifference =
820
866
  Math.abs(timestampOffset - calculatedTimestampOffset);
821
- if (timestampOffsetDifference >= 0.1 || seeked || adaptation) {
867
+ if ((timestampOffsetDifference >= 0.1 || seeked || adaptation) &&
868
+ (!isChunkedData || calculatedTimestampOffset > 0 ||
869
+ !timestampOffset)) {
822
870
  timestampOffset = calculatedTimestampOffset;
823
871
  if (this.attemptTimestampOffsetCalculation_) {
824
872
  this.enqueueOperation_(
@@ -1778,6 +1826,9 @@ shaka.media.MediaSourceEngine = class {
1778
1826
  * @private
1779
1827
  */
1780
1828
  async codecSwitchIfNecessary_(contentType, stream, streamsByType) {
1829
+ if (contentType == shaka.util.ManifestParserUtils.ContentType.TEXT) {
1830
+ return false;
1831
+ }
1781
1832
  const MimeUtils = shaka.util.MimeUtils;
1782
1833
  const currentCodec = MimeUtils.getCodecBase(
1783
1834
  MimeUtils.getCodecs(this.sourceBufferTypes_[contentType]));
@@ -1840,6 +1891,9 @@ shaka.media.MediaSourceEngine = class {
1840
1891
  * @private
1841
1892
  */
1842
1893
  isCodecSwitchNecessary_(contentType, stream) {
1894
+ if (contentType == shaka.util.ManifestParserUtils.ContentType.TEXT) {
1895
+ return false;
1896
+ }
1843
1897
  const MimeUtils = shaka.util.MimeUtils;
1844
1898
  const currentCodec = MimeUtils.getCodecBase(
1845
1899
  MimeUtils.getCodecs(this.sourceBufferTypes_[contentType]));
@@ -6,7 +6,6 @@
6
6
 
7
7
  goog.provide('shaka.media.PlayRateController');
8
8
 
9
- goog.require('goog.asserts');
10
9
  goog.require('shaka.log');
11
10
  goog.require('shaka.util.IReleasable');
12
11
  goog.require('shaka.util.Timer');
@@ -17,8 +16,6 @@ goog.require('shaka.util.Timer');
17
16
  * the playback rate on the media element can change outside of the controller,
18
17
  * the playback controller will need to be updated to stay in-sync.
19
18
  *
20
- * TODO: Try not to manage buffering above the browser with playbackRate=0.
21
- *
22
19
  * @implements {shaka.util.IReleasable}
23
20
  * @final
24
21
  */
@@ -30,9 +27,6 @@ shaka.media.PlayRateController = class {
30
27
  /** @private {?shaka.media.PlayRateController.Harness} */
31
28
  this.harness_ = harness;
32
29
 
33
- /** @private {boolean} */
34
- this.isBuffering_ = false;
35
-
36
30
  /** @private {number} */
37
31
  this.rate_ = this.harness_.getRate();
38
32
 
@@ -56,25 +50,15 @@ shaka.media.PlayRateController = class {
56
50
  }
57
51
 
58
52
  /**
59
- * Sets the buffering flag, which controls the effective playback rate.
60
- *
61
- * @param {boolean} isBuffering If true, forces playback rate to 0 internally.
62
- */
63
- setBuffering(isBuffering) {
64
- this.isBuffering_ = isBuffering;
65
- this.apply_();
66
- }
67
-
68
- /**
69
- * Set the playback rate. This rate will only be used as provided when the
70
- * player is not buffering. You should never set the rate to 0.
53
+ * Set the playback rate.
71
54
  *
72
55
  * @param {number} rate
73
56
  */
74
57
  set(rate) {
75
- goog.asserts.assert(rate != 0, 'Should never set rate of 0 explicitly!');
76
- this.rate_ = rate;
77
- this.apply_();
58
+ if (this.rate_ != rate) {
59
+ this.rate_ = rate;
60
+ this.apply_();
61
+ }
78
62
  }
79
63
 
80
64
  /**
@@ -108,14 +92,11 @@ shaka.media.PlayRateController = class {
108
92
  // Always stop the timer. We may not start it again.
109
93
  this.timer_.stop();
110
94
 
111
- /** @type {number} */
112
- const rate = this.calculateCurrentRate_();
95
+ shaka.log.v1('Changing effective playback rate to', this.rate_);
113
96
 
114
- shaka.log.v1('Changing effective playback rate to', rate);
115
-
116
- if (rate >= 0) {
97
+ if (this.rate_ >= 0) {
117
98
  try {
118
- this.applyRate_(rate);
99
+ this.applyRate_(this.rate_);
119
100
  return;
120
101
  } catch (e) {
121
102
  // Fall through to the next clause.
@@ -135,17 +116,6 @@ shaka.media.PlayRateController = class {
135
116
  this.applyRate_(0);
136
117
  }
137
118
 
138
- /**
139
- * Calculate the rate that the controller wants the media element to have
140
- * based on the current state of the controller.
141
- *
142
- * @return {number}
143
- * @private
144
- */
145
- calculateCurrentRate_() {
146
- return this.isBuffering_ ? 0 : this.rate_;
147
- }
148
-
149
119
  /**
150
120
  * If the new rate is different than the media element's playback rate, this
151
121
  * will change the playback rate. If the rate does not need to change, it will
@@ -619,7 +619,9 @@ shaka.media.PresentationTimeline = class {
619
619
  * @typedef {{
620
620
  * start: number,
621
621
  * unscaledStart: number,
622
- * end: number
622
+ * end: number,
623
+ * partialSegments: number,
624
+ * segmentPosition: number
623
625
  * }}
624
626
  *
625
627
  * @description
@@ -631,6 +633,10 @@ shaka.media.PresentationTimeline = class {
631
633
  * The start time of the range in representation timescale units.
632
634
  * @property {number} end
633
635
  * The end time (exclusive) of the range.
636
+ * @property {number} partialSegments
637
+ * The number of partial segments
638
+ * @property {number} segmentPosition
639
+ * The segment position of the timeline entry as it appears in the manifest
634
640
  *
635
641
  * @export
636
642
  */
@@ -261,7 +261,7 @@ shaka.media.QualityObserver.QualityChangePosition;
261
261
  *
262
262
  * @description
263
263
  * Contains media quality information for a specific content type
264
- * e.g video or audio.
264
+ * e.g. video or audio.
265
265
  *
266
266
  * @property {!Array.<shaka.media.QualityObserver.QualityChangePosition>}
267
267
  * qualityChangePositions
@@ -582,7 +582,7 @@ shaka.media.SegmentIterator = class {
582
582
  // new references in merge(), the pointers may not make sense any more.
583
583
  // This adjusts the invalid pointer values to point to the next newly added
584
584
  // segment or partial segment.
585
- if (ref && ref.hasPartialSegments() && ref.getUris().length &&
585
+ if (ref && ref.hasPartialSegments() && ref.hasAllPartialSegments() &&
586
586
  this.currentPartialPosition_ >= ref.partialReferences.length) {
587
587
  this.currentPosition_++;
588
588
  this.currentPartialPosition_ = 0;
@@ -609,12 +609,12 @@ shaka.media.SegmentIterator = class {
609
609
  // If the regular segment contains partial segments, move to the next
610
610
  // partial SegmentReference.
611
611
  this.currentPartialPosition_++;
612
- // If the current regular segment has been published completely (has a
613
- // valid Uri), and we've reached the end of its partial segments list,
614
- // move to the next regular segment.
612
+ // If the current regular segment has been published completely, and
613
+ // we've reached the end of its partial segments list, move to the next
614
+ // regular segment.
615
615
  // If the Partial Segments list is still on the fly, do not move to
616
616
  // the next regular segment.
617
- if (ref.getUris().length &&
617
+ if (ref.hasAllPartialSegments() &&
618
618
  this.currentPartialPosition_ == ref.partialReferences.length) {
619
619
  this.currentPosition_++;
620
620
  this.currentPartialPosition_ = 0;