shaka-player 3.2.2 → 3.3.2

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 (188) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +1 -1
  3. package/.github/ISSUE_TEMPLATE/question.md +1 -1
  4. package/.github/workflows/build_and_test.yaml +73 -0
  5. package/.github/workflows/release.yaml +53 -0
  6. package/AUTHORS +6 -5
  7. package/CHANGELOG.md +314 -1
  8. package/CONTRIBUTORS +4 -2
  9. package/build/checkversion.py +1 -1
  10. package/build/conformance.textproto +183 -169
  11. package/build/test.py +6 -0
  12. package/build/types/core +3 -0
  13. package/build/types/offline +1 -0
  14. package/build/types/polyfill +1 -0
  15. package/build/types/ui +2 -0
  16. package/demo/common/assets.js +18 -0
  17. package/demo/common/message_ids.js +13 -1
  18. package/demo/config.js +31 -1
  19. package/demo/index.html +1 -1
  20. package/demo/locales/en.json +12 -0
  21. package/demo/locales/source.json +48 -0
  22. package/dist/controls.css +26 -2
  23. package/dist/controls.css.map +1 -1
  24. package/dist/demo.compiled.debug.js +19 -16
  25. package/dist/demo.compiled.debug.map +3 -3
  26. package/dist/demo.compiled.js +19 -16
  27. package/dist/demo.compiled.map +3 -3
  28. package/dist/deps.js +21 -14
  29. package/dist/locales.js +31 -29
  30. package/dist/receiver.compiled.debug.js +11 -9
  31. package/dist/receiver.compiled.debug.map +3 -3
  32. package/dist/receiver.compiled.js +11 -9
  33. package/dist/receiver.compiled.map +3 -3
  34. package/dist/shaka-player.compiled.d.ts +232 -18
  35. package/dist/shaka-player.compiled.debug.d.ts +232 -18
  36. package/dist/shaka-player.compiled.debug.externs.js +293 -17
  37. package/dist/shaka-player.compiled.debug.js +481 -422
  38. package/dist/shaka-player.compiled.debug.map +4 -4
  39. package/dist/shaka-player.compiled.externs.js +293 -17
  40. package/dist/shaka-player.compiled.js +846 -817
  41. package/dist/shaka-player.compiled.map +4 -4
  42. package/dist/shaka-player.ui.d.ts +250 -30
  43. package/dist/shaka-player.ui.debug.d.ts +250 -30
  44. package/dist/shaka-player.ui.debug.externs.js +322 -28
  45. package/dist/shaka-player.ui.debug.js +630 -553
  46. package/dist/shaka-player.ui.debug.map +4 -4
  47. package/dist/shaka-player.ui.externs.js +322 -28
  48. package/dist/shaka-player.ui.js +1048 -1006
  49. package/dist/shaka-player.ui.map +4 -4
  50. package/docs/design/bg-fetch-after.gv +29 -0
  51. package/docs/design/bg-fetch-after.gv.png +0 -0
  52. package/docs/design/bg-fetch-before.gv +18 -0
  53. package/docs/design/bg-fetch-before.gv.png +0 -0
  54. package/docs/design/bg-fetch.md +134 -0
  55. package/docs/tutorials/blob-url.md +15 -0
  56. package/docs/tutorials/index.json +1 -0
  57. package/docs/tutorials/ui-customization.md +66 -0
  58. package/docs/tutorials/ui.md +5 -5
  59. package/externs/cmcd.js +186 -0
  60. package/externs/ima.js +3 -0
  61. package/externs/shaka/ads.js +5 -0
  62. package/externs/shaka/manifest.js +12 -1
  63. package/externs/shaka/manifest_parser.js +10 -1
  64. package/externs/shaka/net.js +20 -4
  65. package/externs/shaka/offline.js +31 -2
  66. package/externs/shaka/player.js +138 -5
  67. package/externs/shaka/text.js +24 -0
  68. package/externs/webcrypto.js +18 -0
  69. package/karma.conf.js +19 -15
  70. package/lib/abr/ewma.js +14 -0
  71. package/lib/abr/ewma_bandwidth_estimator.js +16 -2
  72. package/lib/abr/simple_abr_manager.js +6 -0
  73. package/lib/ads/ad_manager.js +1 -0
  74. package/lib/ads/client_side_ad.js +8 -0
  75. package/lib/ads/client_side_ad_manager.js +8 -4
  76. package/lib/ads/server_side_ad.js +7 -0
  77. package/lib/cast/cast_proxy.js +3 -0
  78. package/lib/cast/cast_receiver.js +3 -0
  79. package/lib/cast/cast_utils.js +1 -0
  80. package/lib/dash/dash_parser.js +79 -33
  81. package/lib/dash/segment_base.js +25 -1
  82. package/lib/dash/segment_list.js +18 -9
  83. package/lib/dash/segment_template.js +23 -10
  84. package/lib/hls/hls_parser.js +116 -23
  85. package/lib/hls/manifest_text_parser.js +1 -0
  86. package/lib/media/quality_observer.js +274 -0
  87. package/lib/media/region_observer.js +39 -33
  88. package/lib/media/region_timeline.js +17 -19
  89. package/lib/media/segment_index.js +8 -1
  90. package/lib/media/segment_reference.js +37 -4
  91. package/lib/media/streaming_engine.js +47 -6
  92. package/lib/net/http_fetch_plugin.js +31 -11
  93. package/lib/net/http_plugin_utils.js +1 -0
  94. package/lib/net/http_xhr_plugin.js +40 -14
  95. package/lib/net/networking_engine.js +85 -18
  96. package/lib/offline/download_info.js +68 -0
  97. package/lib/offline/download_manager.js +13 -5
  98. package/lib/offline/indexeddb/base_storage_cell.js +35 -0
  99. package/lib/offline/indexeddb/storage_mechanism.js +1 -1
  100. package/lib/offline/indexeddb/v5_storage_cell.js +5 -0
  101. package/lib/offline/storage.js +401 -293
  102. package/lib/offline/stored_content_utils.js +2 -0
  103. package/lib/player.js +254 -27
  104. package/lib/polyfill/media_capabilities.js +30 -15
  105. package/lib/polyfill/random_uuid.js +52 -0
  106. package/lib/text/cue.js +18 -0
  107. package/lib/text/ttml_text_parser.js +109 -60
  108. package/lib/text/ui_text_displayer.js +19 -13
  109. package/lib/util/cmcd_manager.js +672 -0
  110. package/lib/util/error.js +6 -0
  111. package/lib/util/fake_event_target.js +21 -1
  112. package/lib/util/language_utils.js +12 -0
  113. package/lib/util/mutex.js +52 -0
  114. package/lib/util/periods.js +98 -64
  115. package/lib/util/player_configuration.js +18 -0
  116. package/lib/util/stream_utils.js +86 -10
  117. package/lib/util/xml_utils.js +19 -0
  118. package/package.json +3 -6
  119. package/shaka-player.uncompiled.js +3 -0
  120. package/test/dash/dash_parser_content_protection_unit.js +2 -0
  121. package/test/dash/dash_parser_live_unit.js +144 -1
  122. package/test/dash/dash_parser_manifest_unit.js +37 -2
  123. package/test/dash/dash_parser_segment_base_unit.js +2 -0
  124. package/test/dash/dash_parser_segment_list_unit.js +2 -1
  125. package/test/dash/dash_parser_segment_template_unit.js +2 -1
  126. package/test/hls/hls_live_unit.js +2 -0
  127. package/test/hls/hls_parser_unit.js +76 -0
  128. package/test/media/drm_engine_unit.js +3 -3
  129. package/test/media/quality_observer_unit.js +142 -0
  130. package/test/media/region_observer_unit.js +40 -5
  131. package/test/media/region_timeline_unit.js +40 -22
  132. package/test/media/segment_reference_unit.js +16 -1
  133. package/test/media/streaming_engine_integration.js +4 -2
  134. package/test/media/streaming_engine_unit.js +147 -0
  135. package/test/net/http_plugin_unit.js +20 -15
  136. package/test/offline/storage_integration.js +108 -4
  137. package/test/player_integration.js +140 -8
  138. package/test/player_src_equals_integration.js +41 -8
  139. package/test/player_unit.js +19 -9
  140. package/test/test/assets/chapters.vtt +2 -2
  141. package/test/test/assets/chapters2.vtt +10 -0
  142. package/test/test/util/dash_parser_util.js +4 -0
  143. package/test/test/util/fake_ad.js +7 -0
  144. package/test/test/util/fake_drm_engine.js +9 -2
  145. package/test/test/util/manifest_generator.js +3 -2
  146. package/test/test/util/test_scheme.js +14 -1
  147. package/test/test/util/ttml_utils.js +81 -0
  148. package/test/test/util/util.js +10 -7
  149. package/test/text/mp4_ttml_parser_unit.js +11 -18
  150. package/test/text/ttml_text_parser_unit.js +544 -228
  151. package/test/ui/text_displayer_layout_unit.js +8 -7
  152. package/test/ui/ui_unit.js +250 -0
  153. package/test/util/cmcd_manager_unit.js +291 -0
  154. package/test/util/stream_utils_unit.js +36 -30
  155. package/third_party/closure-uri/uri.js +21 -0
  156. package/ui/airplay_button.js +1 -0
  157. package/ui/audio_language_selection.js +7 -0
  158. package/ui/cast_button.js +1 -0
  159. package/ui/context_menu.js +109 -0
  160. package/ui/controls.js +44 -7
  161. package/ui/controls.less +1 -0
  162. package/ui/enums.js +4 -0
  163. package/ui/externs/ui.js +28 -1
  164. package/ui/fast_forward_button.js +14 -5
  165. package/ui/fullscreen_button.js +1 -0
  166. package/ui/less/buttons.less +0 -4
  167. package/ui/less/containers.less +74 -0
  168. package/ui/less/overflow_menu.less +0 -10
  169. package/ui/less/tooltip.less +97 -0
  170. package/ui/locales/en.json +1 -0
  171. package/ui/locales/source.json +4 -0
  172. package/ui/localization.js +12 -36
  173. package/ui/loop_button.js +5 -0
  174. package/ui/mute_button.js +2 -1
  175. package/ui/overflow_menu.js +5 -25
  176. package/ui/pip_button.js +5 -0
  177. package/ui/play_button.js +2 -2
  178. package/ui/playback_rate_selection.js +8 -9
  179. package/ui/resolution_selection.js +7 -0
  180. package/ui/rewind_button.js +15 -6
  181. package/ui/seek_bar.js +4 -2
  182. package/ui/settings_menu.js +36 -4
  183. package/ui/small_play_button.js +1 -0
  184. package/ui/statistics_button.js +253 -0
  185. package/ui/text_selection.js +12 -4
  186. package/ui/ui.js +30 -0
  187. package/ui/volume_bar.js +1 -1
  188. package/externs/media_capabilities.js +0 -16
@@ -101,6 +101,7 @@ shaka.extern.Request;
101
101
  * @typedef {{
102
102
  * uri: string,
103
103
  * data: BufferSource,
104
+ * status: (number|undefined),
104
105
  * headers: !Object.<string, string>,
105
106
  * timeMs: (number|undefined),
106
107
  * fromCache: (boolean|undefined)
@@ -119,6 +120,8 @@ shaka.extern.Request;
119
120
  * redirects, but after request filters are executed.
120
121
  * @property {BufferSource} data
121
122
  * The body of the response.
123
+ * @property {(number|undefined)} status
124
+ * The response HTTP status code.
122
125
  * @property {!Object.<string, string>} headers
123
126
  * A map of response headers, if supported by the underlying protocol.
124
127
  * All keys should be lowercased.
@@ -139,15 +142,17 @@ shaka.extern.Response;
139
142
  * @typedef {!function(string,
140
143
  * shaka.extern.Request,
141
144
  * shaka.net.NetworkingEngine.RequestType,
142
- * shaka.extern.ProgressUpdated):
145
+ * shaka.extern.ProgressUpdated,
146
+ * shaka.extern.HeadersReceived):
143
147
  * !shaka.extern.IAbortableOperation.<shaka.extern.Response>}
144
148
  * @description
145
149
  * Defines a plugin that handles a specific scheme.
146
150
  *
147
151
  * The functions accepts four parameters, uri string, request, request type,
148
- * and a progressUpdated function. The progressUpdated function can be ignored
149
- * by plugins that do not have this information, but it will always be provided
150
- * by NetworkingEngine.
152
+ * a progressUpdated function, and a headersReceived function. The
153
+ * progressUpdated and headersReceived functions can be ignored by plugins that
154
+ * do not have this information, but it will always be provided by
155
+ * NetworkingEngine.
151
156
  *
152
157
  * @exportDoc
153
158
  */
@@ -171,6 +176,17 @@ shaka.extern.SchemePlugin;
171
176
  shaka.extern.ProgressUpdated;
172
177
 
173
178
 
179
+ /**
180
+ * @typedef {function(!Object.<string, string>)}
181
+ *
182
+ * @description
183
+ * A callback function to handle headers received events through networking
184
+ * engine in player.
185
+ * The first argument is the headers object of the response.
186
+ */
187
+ shaka.extern.HeadersReceived;
188
+
189
+
174
190
  /**
175
191
  * Defines a filter for requests. This filter takes the request and modifies
176
192
  * it before it is sent to the scheme plugin.
@@ -33,7 +33,8 @@ shaka.extern.OfflineSupport;
33
33
  * size: number,
34
34
  * expiration: number,
35
35
  * tracks: !Array.<shaka.extern.Track>,
36
- * appMetadata: Object
36
+ * appMetadata: Object,
37
+ * isIncomplete: boolean
37
38
  * }}
38
39
  *
39
40
  * @property {?string} offlineUri
@@ -53,6 +54,9 @@ shaka.extern.OfflineSupport;
53
54
  * The tracks that are stored.
54
55
  * @property {Object} appMetadata
55
56
  * The metadata passed to store().
57
+ * @property {boolean} isIncomplete
58
+ * If true, the content is still downloading. Manifests with this set cannot
59
+ * be played yet.
56
60
  * @exportDoc
57
61
  */
58
62
  shaka.extern.StoredContent;
@@ -68,7 +72,8 @@ shaka.extern.StoredContent;
68
72
  * streams: !Array.<shaka.extern.StreamDB>,
69
73
  * sessionIds: !Array.<string>,
70
74
  * drmInfo: ?shaka.extern.DrmInfo,
71
- * appMetadata: Object
75
+ * appMetadata: Object,
76
+ * isIncomplete: (boolean|undefined)
72
77
  * }}
73
78
  *
74
79
  * @property {number} creationTime
@@ -91,6 +96,8 @@ shaka.extern.StoredContent;
91
96
  * The DRM info used to initialize EME.
92
97
  * @property {Object} appMetadata
93
98
  * A metadata object passed from the application.
99
+ * @property {(boolean|undefined)} isIncomplete
100
+ * If true, the content is still downloading.
94
101
  */
95
102
  shaka.extern.ManifestDB;
96
103
 
@@ -195,6 +202,8 @@ shaka.extern.StreamDB;
195
202
  * appendWindowEnd: number,
196
203
  * timestampOffset: number,
197
204
  * tilesLayout: ?string,
205
+ * pendingSegmentRefId: (string|undefined),
206
+ * pendingInitSegmentRefId: (string|undefined),
198
207
  * dataKey: number
199
208
  * }}
200
209
  *
@@ -215,6 +224,17 @@ shaka.extern.StreamDB;
215
224
  * The value is a grid-item-dimension consisting of two positive decimal
216
225
  * integers in the format: column-x-row ('4x3'). It describes the
217
226
  * arrangement of Images in a Grid. The minimum valid LAYOUT is '1x1'.
227
+ * @property {(string|undefined)} pendingSegmentRefId
228
+ * Contains an id that identifies what the segment was, originally. Used to
229
+ * coordinate where segments are stored, during the downloading process.
230
+ * If this field is non-null, it's assumed that the segment is not fully
231
+ * downloaded.
232
+ * @property {(string|undefined)} pendingInitSegmentRefId
233
+ * Contains an id that identifies what the init segment was, originally.
234
+ * Used to coordinate where init segments are stored, during the downloading
235
+ * process.
236
+ * If this field is non-null, it's assumed that the init segment is not fully
237
+ * downloaded.
218
238
  * @property {number} dataKey
219
239
  * The key to the data in storage.
220
240
  */
@@ -333,6 +353,15 @@ shaka.extern.StorageCell = class {
333
353
  */
334
354
  addManifests(manifests) {}
335
355
 
356
+ /**
357
+ * Updates the given manifest, stored at the given key.
358
+ *
359
+ * @param {number} key
360
+ * @param {!shaka.extern.ManifestDB} manifest
361
+ * @return {!Promise}
362
+ */
363
+ updateManifest(key, manifest) {}
364
+
336
365
  /**
337
366
  * Replace the expiration time of the manifest stored under |key| with
338
367
  * |newExpiration|. If no manifest is found under |key| then this should
@@ -468,6 +468,48 @@ shaka.extern.ID3Metadata;
468
468
  */
469
469
  shaka.extern.TimelineRegionInfo;
470
470
 
471
+ /**
472
+ * @typedef {{
473
+ * audioSamplingRate: ?number,
474
+ * bandwidth: number,
475
+ * codecs: string,
476
+ * contentType: string,
477
+ * frameRate: ?number,
478
+ * height: ?number,
479
+ * mimeType: ?string,
480
+ * channelsCount: ?number,
481
+ * pixelAspectRatio: ?string,
482
+ * width: ?number
483
+ * }}
484
+ *
485
+ * @description
486
+ * Contains information about the quality of an audio or video media stream.
487
+ *
488
+ * @property {?number} audioSamplingRate
489
+ * Specifies the maximum sampling rate of the content.
490
+ * @property {number} bandwidth
491
+ * The bandwidth in bits per second.
492
+ * @property {string} codecs
493
+ * The Stream's codecs, e.g., 'avc1.4d4015' or 'vp9', which must be
494
+ * compatible with the Stream's MIME type.
495
+ * @property {string} contentType
496
+ * The type of content, which may be "video" or "audio".
497
+ * @property {?number} frameRate
498
+ * The video frame rate.
499
+ * @property {?number} height
500
+ * The video height in pixels.
501
+ * @property {string} mimeType
502
+ * The MIME type.
503
+ * @property {?number} channelsCount
504
+ * The number of audio channels, or null if unknown.
505
+ * @property {?string} pixelAspectRatio
506
+ * The pixel aspect ratio value; e.g "1:1".
507
+ * @property {?number} width
508
+ * The video width in pixels.
509
+ * @exportDoc
510
+ */
511
+ shaka.extern.MediaQualityInfo;
512
+
471
513
 
472
514
  /**
473
515
  * @typedef {{
@@ -698,7 +740,9 @@ shaka.extern.DashManifestConfiguration;
698
740
  * @typedef {{
699
741
  * ignoreTextStreamFailures: boolean,
700
742
  * ignoreImageStreamFailures: boolean,
701
- * useFullSegmentsForStartTime: boolean
743
+ * useFullSegmentsForStartTime: boolean,
744
+ * defaultAudioCodec: string,
745
+ * defaultVideoCodec: string
702
746
  * }}
703
747
  *
704
748
  * @property {boolean} ignoreTextStreamFailures
@@ -710,6 +754,12 @@ shaka.extern.DashManifestConfiguration;
710
754
  * @property {boolean} useFullSegmentsForStartTime
711
755
  * If <code>true</code>, force HlsParser to use a full segment request for
712
756
  * determining start time in case the server does not support partial requests
757
+ * @property {string} defaultAudioCodec
758
+ * The default audio codec if it is not specified in the HLS playlist.
759
+ * <i>Defaults to <code>'mp4a.40.2'</code>.</i>
760
+ * @property {string} defaultVideoCodec
761
+ * The default video codec if it is not specified in the HLS playlist.
762
+ * <i>Defaults to <code>'avc1.42E01E'</code>.</i>
713
763
  * @exportDoc
714
764
  */
715
765
  shaka.extern.HlsManifestConfiguration;
@@ -790,7 +840,9 @@ shaka.extern.ManifestConfiguration;
790
840
  * autoLowLatencyMode: boolean,
791
841
  * forceHTTPS: boolean,
792
842
  * preferNativeHls: boolean,
793
- * updateIntervalSeconds: number
843
+ * updateIntervalSeconds: number,
844
+ * dispatchAllEmsgBoxes: boolean,
845
+ * observeQualityChanges: boolean
794
846
  * }}
795
847
  *
796
848
  * @description
@@ -899,7 +951,11 @@ shaka.extern.ManifestConfiguration;
899
951
  * If true, prefer native HLS playback when possible, regardless of platform.
900
952
  * @property {number} updateIntervalSeconds
901
953
  * The minimum number of seconds to see if the manifest has changes.
902
- *
954
+ * @property {boolean} dispatchAllEmsgBoxes
955
+ * If true, all emsg boxes are parsed and dispatched.
956
+ * @property {boolean} observeQualityChanges
957
+ * If true, monitor media quality changes and emit
958
+ * <code.shaka.Player.MediaQualityChangedEvent</code>.
903
959
  * @exportDoc
904
960
  */
905
961
  shaka.extern.StreamingConfiguration;
@@ -913,7 +969,8 @@ shaka.extern.StreamingConfiguration;
913
969
  * restrictions: shaka.extern.Restrictions,
914
970
  * switchInterval: number,
915
971
  * bandwidthUpgradeTarget: number,
916
- * bandwidthDowngradeTarget: number
972
+ * bandwidthDowngradeTarget: number,
973
+ * advanced: shaka.extern.AdvancedAbrConfiguration
917
974
  * }}
918
975
  *
919
976
  * @property {boolean} enabled
@@ -930,7 +987,7 @@ shaka.extern.StreamingConfiguration;
930
987
  * automatically, but will still appear in the track list and can still be
931
988
  * selected via <code>selectVariantTrack()</code>. If no tracks meet these
932
989
  * restrictions, AbrManager should not fail, but choose a low-res or
933
- * low-bandwidth variant instead. It is the responsibiliy of AbrManager
990
+ * low-bandwidth variant instead. It is the responsibility of AbrManager
934
991
  * implementations to follow these rules and implement this behavior.
935
992
  * @property {number} switchInterval
936
993
  * The minimum amount of time that must pass between switches, in
@@ -941,11 +998,76 @@ shaka.extern.StreamingConfiguration;
941
998
  * @property {number} bandwidthDowngradeTarget
942
999
  * The largest fraction of the estimated bandwidth we should use. We should
943
1000
  * downgrade to avoid this.
1001
+ * @property {shaka.extern.AdvancedAbrConfiguration} advanced
1002
+ * Advanced ABR configuration.
944
1003
  * @exportDoc
945
1004
  */
946
1005
  shaka.extern.AbrConfiguration;
947
1006
 
948
1007
 
1008
+ /**
1009
+ * @typedef {{
1010
+ * minTotalBytes: number,
1011
+ * minBytes: number,
1012
+ * fastHalfLife: number,
1013
+ * slowHalfLife: number
1014
+ * }}
1015
+ *
1016
+ * @property {number} minTotalBytes
1017
+ * Minimum number of bytes sampled before we trust the estimate. If we have
1018
+ * not sampled much data, our estimate may not be accurate enough to trust.
1019
+ * @property {number} minBytes
1020
+ * Minimum number of bytes, under which samples are discarded. Our models
1021
+ * do not include latency information, so connection startup time (time to
1022
+ * first byte) is considered part of the download time. Because of this, we
1023
+ * should ignore very small downloads which would cause our estimate to be
1024
+ * too low.
1025
+ * @property {number} fastHalfLife
1026
+ * The quantity of prior samples (by weight) used when creating a new
1027
+ * estimate, in seconds. Those prior samples make up half of the
1028
+ * new estimate.
1029
+ * @property {number} slowHalfLife
1030
+ * The quantity of prior samples (by weight) used when creating a new
1031
+ * estimate, in seconds. Those prior samples make up half of the
1032
+ * new estimate.
1033
+ * @exportDoc
1034
+ */
1035
+ shaka.extern.AdvancedAbrConfiguration;
1036
+
1037
+
1038
+ /**
1039
+ * @typedef {{
1040
+ * enabled: boolean,
1041
+ * useHeaders: boolean,
1042
+ * sessionId: string,
1043
+ * contentId: string
1044
+ * }}
1045
+ *
1046
+ * @description
1047
+ * Common Media Client Data (CMCD) configuration.
1048
+ *
1049
+ * @property {boolean} enabled
1050
+ * If <code>true</code>, enable CMCD data to be sent with media requests.
1051
+ * Defaults to <code>false</code>.
1052
+ * @property {boolean} useHeaders
1053
+ * If <code>true</code>, send CMCD data using the header transmission mode
1054
+ * instead of query args. Defaults to <code>false</code>.
1055
+ * @property {string} sessionId
1056
+ * A GUID identifying the current playback session. A playback session
1057
+ * typically ties together segments belonging to a single media asset.
1058
+ * Maximum length is 64 characters. It is RECOMMENDED to conform to the UUID
1059
+ * specification. By default the sessionId is automatically generated on each
1060
+ * <code>load()</code> call.
1061
+ * @property {string} contentId
1062
+ * A unique string identifying the current content. Maximum length is 64
1063
+ * characters. This value is consistent across multiple different sessions and
1064
+ * devices and is defined and updated at the discretion of the service
1065
+ * provider.
1066
+ * @exportDoc
1067
+ */
1068
+ shaka.extern.CmcdConfiguration;
1069
+
1070
+
949
1071
  /**
950
1072
  * @typedef {{
951
1073
  * trackSelectionCallback:
@@ -987,6 +1109,7 @@ shaka.extern.OfflineConfiguration;
987
1109
  * streaming: shaka.extern.StreamingConfiguration,
988
1110
  * abrFactory: shaka.extern.AbrManager.Factory,
989
1111
  * abr: shaka.extern.AbrConfiguration,
1112
+ * cmcd: shaka.extern.CmcdConfiguration,
990
1113
  * offline: shaka.extern.OfflineConfiguration,
991
1114
  * preferredAudioLanguage: string,
992
1115
  * preferredTextLanguage: string,
@@ -1013,6 +1136,8 @@ shaka.extern.OfflineConfiguration;
1013
1136
  * A factory to construct an abr manager.
1014
1137
  * @property {shaka.extern.AbrConfiguration} abr
1015
1138
  * ABR configuration and settings.
1139
+ * @property {shaka.extern.CmcdConfiguration} cmcd
1140
+ * CMCD configuration and settings. (Common Media Client Data)
1016
1141
  * @property {shaka.extern.OfflineConfiguration} offline
1017
1142
  * Offline configuration and settings.
1018
1143
  * @property {string} preferredAudioLanguage
@@ -1082,6 +1207,8 @@ shaka.extern.LanguageRole;
1082
1207
 
1083
1208
  /**
1084
1209
  * @typedef {{
1210
+ * imageHeight: number,
1211
+ * imageWidth: number,
1085
1212
  * height: number,
1086
1213
  * positionX: number,
1087
1214
  * positionY: number,
@@ -1091,6 +1218,12 @@ shaka.extern.LanguageRole;
1091
1218
  * width: number
1092
1219
  * }}
1093
1220
  *
1221
+ * @property {number} imageHeight
1222
+ * The image height in px. The image height could be different to height if
1223
+ * the layout is different to 1x1.
1224
+ * @property {number} imageWidth
1225
+ * The image width in px. The image width could be different to width if
1226
+ * the layout is different to 1x1.
1094
1227
  * @property {number} height
1095
1228
  * The thumbnail height in px.
1096
1229
  * @property {number} positionX
@@ -297,6 +297,20 @@ shaka.extern.Cue = class {
297
297
  */
298
298
  this.fontFamily;
299
299
 
300
+ /**
301
+ * Text stroke color as a CSS color, e.g. "#FFFFFF" or "white".
302
+ * @type {string}
303
+ * @exportDoc
304
+ */
305
+ this.textStrokeColor;
306
+
307
+ /**
308
+ * Text stroke width as a CSS stroke-width value.
309
+ * @type {string}
310
+ * @exportDoc
311
+ */
312
+ this.textStrokeWidth;
313
+
300
314
  /**
301
315
  * Text letter spacing as a CSS letter-spacing value.
302
316
  * @type {string}
@@ -349,6 +363,16 @@ shaka.extern.Cue = class {
349
363
  */
350
364
  this.nestedCues;
351
365
 
366
+ /**
367
+ * If true, this represents a container element that is "above" the main
368
+ * cues. For example, the <body> and <div> tags that contain the <p> tags
369
+ * in a TTML file. This controls the flow of the final cues; any nested cues
370
+ * within an "isContainer" cue will be laid out as separate lines.
371
+ * @type {boolean}
372
+ * @exportDoc
373
+ */
374
+ this.isContainer;
375
+
352
376
  /**
353
377
  * Whether or not the cue only acts as a line break between two nested cues.
354
378
  * Should only appear in nested cues.
@@ -0,0 +1,18 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+
8
+ /**
9
+ * @fileoverview Externs for crypto properties not in the Closure compiler.
10
+ *
11
+ * @externs
12
+ */
13
+
14
+
15
+ /**
16
+ * @return {string}
17
+ */
18
+ webCrypto.Crypto.prototype.randomUUID = function() {};
package/karma.conf.js CHANGED
@@ -11,6 +11,7 @@ const Jimp = require('jimp');
11
11
  const fs = require('fs');
12
12
  const path = require('path');
13
13
  const rimraf = require('rimraf');
14
+ const {ssim} = require('ssim.js');
14
15
  const util = require('karma/common/util');
15
16
  const which = require('which');
16
17
 
@@ -336,6 +337,10 @@ module.exports = (config) => {
336
337
 
337
338
  config.set({reporters: reporters});
338
339
 
340
+ if (reporters.includes('spec') && settings.spec_hide_passed) {
341
+ config.set({specReporter: {suppressPassed: true}});
342
+ }
343
+
339
344
  if (settings.random) {
340
345
  // If --seed was specified use that value, else generate a seed so that the
341
346
  // exact order can be reproduced if it catches an issue.
@@ -518,8 +523,7 @@ function WebDriverScreenshotMiddlewareFactory(launcher) {
518
523
  *
519
524
  * @param {karma.Launcher.Browser} browser
520
525
  * @param {!Object.<string, string>} params
521
- * @return {!Promise.<number>} The number of pixels changed between the old
522
- * and new screenshots, after cropping and scaling.
526
+ * @return {!Promise.<number>} A similarity score between 0 and 1.
523
527
  */
524
528
  async function diffScreenshot(browser, params) {
525
529
  const webDriverClient = getWebDriverClient(browser);
@@ -604,22 +608,22 @@ function WebDriverScreenshotMiddlewareFactory(launcher) {
604
608
  // Compare the new screenshot to the old one and produce a diff image.
605
609
  // Initially, the image data will be raw pixels, 4 bytes per pixel.
606
610
  // The threshold parameter affects the sensitivity of individual pixel
607
- // comparisons. Setting it too low means small rendering changes in the
608
- // browser can cause failures even when a human can't see the difference,
609
- // and setting it too high means human-noticeable changes could go
610
- // undetected by a test.
611
- const diff = Jimp.diff(oldScreenshot, newScreenshot, /* threshold= */ 0.07);
611
+ // comparisons. This diff is only used for visual review, not for
612
+ // automated similarity checks, so the threshold setting is not so critical
613
+ // as it used to be.
614
+ const threshold = 0.10;
615
+ const diff = Jimp.diff(oldScreenshot, newScreenshot, threshold);
612
616
 
613
617
  // Write the diff to disk. This is used to review when there are changes.
618
+ const fullSizeDiff =
619
+ diff.image.clone().resize(width, height, Jimp.RESIZE_BICUBIC);
614
620
  fs.writeFileSync(
615
- diffScreenshotPath, await diff.image.getBufferAsync('image/png'));
616
-
617
- // "percent" is, surprisingly, a number between 0 and 1, not between 0 and
618
- // 100. Convert this to a number of pixels changed, which has been found to
619
- // be a more effective and less flaky metric.
620
- const pixelsChanged =
621
- diff.percent * diff.image.bitmap.width * diff.image.bitmap.height;
622
- return pixelsChanged;
621
+ diffScreenshotPath, await fullSizeDiff.getBufferAsync('image/png'));
622
+
623
+ // Compare with a structural similarity algorithm. This produces a
624
+ // similarity score that we will use to pass or fail the test.
625
+ const ssimResult = ssim(oldScreenshot.bitmap, newScreenshot.bitmap);
626
+ return ssimResult.mssim; // A score between 0 and 1.
623
627
  }
624
628
 
625
629
  /**
package/lib/abr/ewma.js CHANGED
@@ -35,6 +35,20 @@ shaka.abr.Ewma = class {
35
35
  this.totalWeight_ = 0;
36
36
  }
37
37
 
38
+
39
+ /**
40
+ * Update the alpha with a new halfLife value.
41
+ *
42
+ * @param {number} halfLife The quantity of prior samples (by weight) used
43
+ * when creating a new estimate. Those prior samples make up half of the
44
+ * new estimate.
45
+ */
46
+ updateAlpha(halfLife) {
47
+ goog.asserts.assert(halfLife > 0, 'expected halfLife to be positive');
48
+ this.alpha_ = Math.exp(Math.log(0.5) / halfLife);
49
+ }
50
+
51
+
38
52
  /**
39
53
  * Takes a sample.
40
54
  *
@@ -47,7 +47,6 @@ shaka.abr.EwmaBandwidthEstimator = class {
47
47
  * This specific value is based on experimentation.
48
48
  *
49
49
  * @private {number}
50
- * @const
51
50
  */
52
51
  this.minTotalBytes_ = 128e3; // 128kB
53
52
 
@@ -60,11 +59,26 @@ shaka.abr.EwmaBandwidthEstimator = class {
60
59
  * This specific value is based on experimentation.
61
60
  *
62
61
  * @private {number}
63
- * @const
64
62
  */
65
63
  this.minBytes_ = 16e3; // 16kB
66
64
  }
67
65
 
66
+
67
+ /**
68
+ * Called by the Player to provide an updated configuration any time it
69
+ * changes.
70
+ * Must be called at least once before init().
71
+ *
72
+ * @param {shaka.extern.AdvancedAbrConfiguration} config
73
+ */
74
+ configure(config) {
75
+ this.minTotalBytes_ = config.minTotalBytes;
76
+ this.minBytes_ = config.minBytes;
77
+ this.fast_.updateAlpha(config.fastHalfLife);
78
+ this.slow_.updateAlpha(config.slowHalfLife);
79
+ }
80
+
81
+
68
82
  /**
69
83
  * Takes a bandwidth sample.
70
84
  *
@@ -54,6 +54,9 @@ shaka.abr.SimpleAbrManager = class {
54
54
  navigator.connection.addEventListener('change', () => {
55
55
  if (this.config_.useNetworkInformation && this.enabled_) {
56
56
  this.bandwidthEstimator_ = new shaka.abr.EwmaBandwidthEstimator();
57
+ if (this.config_) {
58
+ this.bandwidthEstimator_.configure(this.config_.advanced);
59
+ }
57
60
  const chosenVariant = this.chooseVariant();
58
61
  if (chosenVariant) {
59
62
  this.switch_(chosenVariant);
@@ -239,6 +242,9 @@ shaka.abr.SimpleAbrManager = class {
239
242
  */
240
243
  configure(config) {
241
244
  this.config_ = config;
245
+ if (this.bandwidthEstimator_ && this.config_) {
246
+ this.bandwidthEstimator_.configure(this.config_.advanced);
247
+ }
242
248
  }
243
249
 
244
250
 
@@ -448,6 +448,7 @@ shaka.ads.AdManager = class extends shaka.util.FakeEventTarget {
448
448
  this.ssAdManager_.release();
449
449
  this.ssAdManager_ = null;
450
450
  }
451
+ super.release();
451
452
  }
452
453
 
453
454
 
@@ -162,6 +162,14 @@ shaka.ads.ClientSideAd = class {
162
162
  return this.manager_.getVolume() == 0;
163
163
  }
164
164
 
165
+ /**
166
+ * @override
167
+ * @export
168
+ */
169
+ isLinear() {
170
+ return this.ad_.isLinear();
171
+ }
172
+
165
173
 
166
174
  /**
167
175
  * @override
@@ -396,8 +396,10 @@ shaka.ads.ClientSideAdManager = class {
396
396
  .set('originalEvent', e);
397
397
  this.onEvent_(new shaka.util.FakeEvent(
398
398
  shaka.ads.AdManager.AD_STARTED, data));
399
- this.adContainer_.setAttribute('ad-active', 'true');
400
- this.video_.pause();
399
+ if (this.ad_.isLinear()) {
400
+ this.adContainer_.setAttribute('ad-active', 'true');
401
+ this.video_.pause();
402
+ }
401
403
  }
402
404
 
403
405
  /**
@@ -407,7 +409,9 @@ shaka.ads.ClientSideAdManager = class {
407
409
  onAdComplete_(e) {
408
410
  this.onEvent_(new shaka.util.FakeEvent(shaka.ads.AdManager.AD_STOPPED,
409
411
  (new Map()).set('originalEvent', e)));
410
- this.adContainer_.removeAttribute('ad-active');
411
- this.video_.play();
412
+ if (this.ad_.isLinear()) {
413
+ this.adContainer_.removeAttribute('ad-active');
414
+ this.video_.play();
415
+ }
412
416
  }
413
417
  };
@@ -152,6 +152,13 @@ shaka.ads.ServerSideAd = class {
152
152
  return this.video_.muted;
153
153
  }
154
154
 
155
+ /**
156
+ * @override
157
+ * @export
158
+ */
159
+ isLinear() {
160
+ return true;
161
+ }
155
162
 
156
163
  /**
157
164
  * @override
@@ -120,6 +120,9 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
120
120
  this.videoProxy_ = null;
121
121
  this.playerProxy_ = null;
122
122
 
123
+ // FakeEventTarget implements IReleasable
124
+ super.release();
125
+
123
126
  return Promise.all(waitFor);
124
127
  }
125
128
 
@@ -238,6 +238,9 @@ shaka.cast.CastReceiver = class extends shaka.util.FakeEventTarget {
238
238
  this.shakaBus_ = null;
239
239
  this.genericBus_ = null;
240
240
 
241
+ // FakeEventTarget implements IReleasable
242
+ super.release();
243
+
241
244
  await Promise.all(waitFor);
242
245
 
243
246
  const manager = cast.receiver.CastReceiverManager.getInstance();
@@ -388,6 +388,7 @@ shaka.cast.CastUtils.PlayerVoidMethods = [
388
388
  'selectVariantsByLabel',
389
389
  'setTextTrackVisibility',
390
390
  'trickPlay',
391
+ 'updateStartTime',
391
392
  'goToLive',
392
393
  ];
393
394