shaka-player 4.2.4 → 4.3.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.
Files changed (137) hide show
  1. package/.github/workflows/sync-labels.yaml +1 -1
  2. package/.github/workflows/update-issues.yaml +1 -1
  3. package/AUTHORS +4 -0
  4. package/CHANGELOG.md +85 -54
  5. package/CONTRIBUTORS +4 -0
  6. package/README.md +14 -0
  7. package/demo/common/assets.js +58 -0
  8. package/demo/common/message_ids.js +22 -1
  9. package/demo/config.js +89 -5
  10. package/demo/demo.less +7 -1
  11. package/demo/index.html +8 -1
  12. package/demo/locales/en.json +21 -1
  13. package/demo/locales/source.json +82 -2
  14. package/demo/main.js +57 -1
  15. package/demo/search.js +2 -0
  16. package/demo/visualizer.js +337 -0
  17. package/demo/visualizer_button.js +103 -0
  18. package/dist/controls.css +1 -1
  19. package/dist/controls.css.map +1 -1
  20. package/dist/demo.compiled.debug.js +83 -58
  21. package/dist/demo.compiled.debug.map +4 -4
  22. package/dist/demo.compiled.js +83 -58
  23. package/dist/demo.compiled.map +4 -4
  24. package/dist/demo.css +1 -1
  25. package/dist/demo.css.map +1 -1
  26. package/dist/deps.js +16 -9
  27. package/dist/locales.js +32 -32
  28. package/dist/receiver.compiled.debug.js +23 -19
  29. package/dist/receiver.compiled.debug.map +3 -3
  30. package/dist/receiver.compiled.js +23 -19
  31. package/dist/receiver.compiled.map +3 -3
  32. package/dist/shaka-player.compiled.d.ts +173 -26
  33. package/dist/shaka-player.compiled.debug.d.ts +173 -26
  34. package/dist/shaka-player.compiled.debug.externs.js +161 -31
  35. package/dist/shaka-player.compiled.debug.js +464 -401
  36. package/dist/shaka-player.compiled.debug.map +4 -4
  37. package/dist/shaka-player.compiled.externs.js +161 -31
  38. package/dist/shaka-player.compiled.js +897 -862
  39. package/dist/shaka-player.compiled.map +4 -4
  40. package/dist/shaka-player.ui.d.ts +173 -26
  41. package/dist/shaka-player.ui.debug.d.ts +173 -26
  42. package/dist/shaka-player.ui.debug.externs.js +161 -31
  43. package/dist/shaka-player.ui.debug.js +488 -422
  44. package/dist/shaka-player.ui.debug.map +4 -4
  45. package/dist/shaka-player.ui.externs.js +161 -31
  46. package/dist/shaka-player.ui.js +1053 -1018
  47. package/dist/shaka-player.ui.map +4 -4
  48. package/docs/design/lcevc-architecture.png +0 -0
  49. package/docs/design/lcevc-demo.png +0 -0
  50. package/docs/design/lcevc-integration.md +72 -0
  51. package/docs/tutorials/fairplay.md +7 -0
  52. package/docs/tutorials/faq.md +1 -1
  53. package/docs/tutorials/ui.md +7 -7
  54. package/docs/tutorials/upgrade.md +6 -0
  55. package/externs/ima.js +13 -1
  56. package/externs/lcevc.js +81 -0
  57. package/externs/mux.js +1 -42
  58. package/externs/shaka/ads.js +11 -1
  59. package/externs/shaka/manifest_parser.js +5 -1
  60. package/externs/shaka/player.js +178 -15
  61. package/lib/abr/simple_abr_manager.js +7 -0
  62. package/lib/ads/ad_manager.js +0 -8
  63. package/lib/ads/client_side_ad.js +15 -0
  64. package/lib/ads/client_side_ad_manager.js +21 -8
  65. package/lib/ads/server_side_ad.js +15 -0
  66. package/lib/ads/server_side_ad_manager.js +3 -3
  67. package/lib/cast/cast_utils.js +2 -0
  68. package/lib/cea/dummy_cea_parser.js +28 -0
  69. package/lib/cea/i_cea_parser.js +14 -2
  70. package/lib/cea/mp4_cea_parser.js +87 -5
  71. package/lib/config/auto_show_text.js +33 -0
  72. package/lib/dash/dash_parser.js +1 -1
  73. package/lib/hls/hls_parser.js +790 -374
  74. package/lib/lcevc/lcevc_dil.js +152 -0
  75. package/lib/media/closed_caption_parser.js +9 -6
  76. package/lib/media/drm_engine.js +14 -6
  77. package/lib/media/media_source_engine.js +106 -26
  78. package/lib/media/presentation_timeline.js +26 -11
  79. package/lib/media/segment_reference.js +49 -1
  80. package/lib/media/streaming_engine.js +142 -12
  81. package/lib/media/transmuxer.js +73 -18
  82. package/lib/offline/storage.js +1 -0
  83. package/lib/player.js +454 -75
  84. package/lib/polyfill/patchedmediakeys_apple.js +55 -1
  85. package/lib/text/ui_text_displayer.js +5 -5
  86. package/lib/text/vtt_text_parser.js +35 -1
  87. package/lib/util/dom_utils.js +0 -1
  88. package/lib/util/error.js +17 -0
  89. package/lib/util/fake_event.js +2 -0
  90. package/lib/util/id3_utils.js +300 -0
  91. package/lib/util/mime_utils.js +3 -6
  92. package/lib/util/mp4_box_parsers.js +15 -5
  93. package/lib/util/platform.js +9 -1
  94. package/lib/util/player_configuration.js +23 -1
  95. package/lib/util/ts_parser.js +499 -0
  96. package/maintained-branches.md +2 -2
  97. package/package.json +4 -1
  98. package/roadmap.md +5 -3
  99. package/test/ads/ad_manager_unit.js +180 -29
  100. package/test/cast/cast_utils_unit.js +3 -1
  101. package/test/dash/dash_parser_content_protection_unit.js +1 -0
  102. package/test/dash/dash_parser_live_unit.js +1 -0
  103. package/test/dash/dash_parser_manifest_unit.js +93 -1
  104. package/test/dash/dash_parser_segment_base_unit.js +1 -0
  105. package/test/dash/dash_parser_segment_list_unit.js +1 -0
  106. package/test/dash/dash_parser_segment_template_unit.js +1 -0
  107. package/test/demo/demo_unit.js +2 -1
  108. package/test/hls/hls_live_unit.js +253 -19
  109. package/test/hls/hls_parser_unit.js +500 -12
  110. package/test/media/closed_caption_parser_unit.js +2 -1
  111. package/test/media/drm_engine_integration.js +3 -1
  112. package/test/media/media_source_engine_integration.js +71 -6
  113. package/test/media/media_source_engine_unit.js +10 -5
  114. package/test/media/streaming_engine_integration.js +4 -1
  115. package/test/media/streaming_engine_unit.js +144 -1
  116. package/test/media/transmuxer_integration.js +21 -10
  117. package/test/player_integration.js +224 -82
  118. package/test/player_unit.js +5 -2
  119. package/test/polyfill/patchedmediakeys_apple_unit.js +124 -0
  120. package/test/test/assets/id3-metadata.aac +0 -0
  121. package/test/test/assets/id3-metadata.ts +0 -0
  122. package/test/test/assets/thumbnails-sprites.vtt +10 -0
  123. package/test/test/assets/thumbnails.vtt +10 -0
  124. package/test/test/util/dash_parser_util.js +2 -0
  125. package/test/test/util/fake_ad.js +21 -0
  126. package/test/test/util/fake_media_source_engine.js +7 -0
  127. package/test/test/util/id3_generator.js +100 -0
  128. package/test/test/util/manifest_generator.js +3 -6
  129. package/test/test/util/simple_fakes.js +4 -0
  130. package/test/test/util/stream_generator.js +38 -0
  131. package/test/test/util/test_scheme.js +43 -14
  132. package/test/text/vtt_text_parser_unit.js +11 -0
  133. package/test/ui/text_displayer_layout_unit.js +14 -0
  134. package/test/util/id3_utils_unit.js +116 -0
  135. package/test/util/ts_parser_unit.js +77 -0
  136. package/ui/less/containers.less +7 -0
  137. package/ui/ui.js +43 -4
@@ -8,6 +8,7 @@ goog.provide('shaka.util.PlayerConfiguration');
8
8
 
9
9
  goog.require('goog.asserts');
10
10
  goog.require('shaka.abr.SimpleAbrManager');
11
+ goog.require('shaka.config.AutoShowText');
11
12
  goog.require('shaka.log');
12
13
  goog.require('shaka.net.NetworkingEngine');
13
14
  goog.require('shaka.util.ConfigUtils');
@@ -120,6 +121,7 @@ shaka.util.PlayerConfiguration = class {
120
121
  [element],
121
122
  element);
122
123
  },
124
+ sequenceMode: false,
123
125
  },
124
126
  hls: {
125
127
  ignoreTextStreamFailures: false,
@@ -129,6 +131,8 @@ shaka.util.PlayerConfiguration = class {
129
131
  ignoreManifestProgramDateTime: false,
130
132
  mediaPlaylistFullMimeType:
131
133
  'video/mp2t; codecs="avc1.42E01E, mp4a.40.2"',
134
+ useSafariBehaviorForLive: true,
135
+ liveSegmentsDelay: 3,
132
136
  },
133
137
  };
134
138
 
@@ -153,7 +157,7 @@ shaka.util.PlayerConfiguration = class {
153
157
  startAtSegmentBoundary: false,
154
158
  gapDetectionThreshold: 0.5,
155
159
  durationBackoff: 1,
156
- forceTransmuxTS: false,
160
+ forceTransmux: false,
157
161
  // Offset by 5 seconds since Chromecast takes a few seconds to start
158
162
  // playing after a seek, even when buffered.
159
163
  safeSeekOffset: 5,
@@ -175,6 +179,7 @@ shaka.util.PlayerConfiguration = class {
175
179
  dispatchAllEmsgBoxes: false,
176
180
  observeQualityChanges: false,
177
181
  maxDisabledTime: 30,
182
+ parsePrftBox: false,
178
183
  };
179
184
 
180
185
  // WebOS, Tizen, and Chromecast have long hardware pipelines that respond
@@ -249,6 +254,7 @@ shaka.util.PlayerConfiguration = class {
249
254
  slowHalfLife: 5,
250
255
  },
251
256
  restrictToElementSize: false,
257
+ restrictToScreenSize: false,
252
258
  ignoreDevicePixelRatio: false,
253
259
  };
254
260
 
@@ -259,14 +265,29 @@ shaka.util.PlayerConfiguration = class {
259
265
  useHeaders: false,
260
266
  };
261
267
 
268
+ const lcevc = {
269
+ enabled: false,
270
+ dynamicPerformanceScaling: true,
271
+ logLevel: 0,
272
+ drawLogo: false,
273
+ };
274
+
275
+ const mediaSource = {
276
+ sourceBufferExtraFeatures: '',
277
+ };
278
+
279
+ const AutoShowText = shaka.config.AutoShowText;
280
+
262
281
  /** @type {shaka.extern.PlayerConfiguration} */
263
282
  const config = {
264
283
  drm: drm,
265
284
  manifest: manifest,
266
285
  streaming: streaming,
286
+ mediaSource: mediaSource,
267
287
  offline: offline,
268
288
  abrFactory: () => new shaka.abr.SimpleAbrManager(),
269
289
  abr: abr,
290
+ autoShowText: AutoShowText.IF_SUBTITLES_MAY_BE_NEEDED,
270
291
  preferredAudioLanguage: '',
271
292
  preferredTextLanguage: '',
272
293
  preferredVariantRole: '',
@@ -292,6 +313,7 @@ shaka.util.PlayerConfiguration = class {
292
313
  playRangeEnd: Infinity,
293
314
  textDisplayFactory: () => null,
294
315
  cmcd: cmcd,
316
+ lcevc: lcevc,
295
317
  };
296
318
 
297
319
  // Add this callback so that we can reference the preferred audio language
@@ -0,0 +1,499 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ goog.provide('shaka.util.TsParser');
8
+
9
+ goog.require('goog.asserts');
10
+ goog.require('shaka.log');
11
+ goog.require('shaka.util.Id3Utils');
12
+ goog.require('shaka.util.Uint8ArrayUtils');
13
+
14
+
15
+ /**
16
+ * @see https://en.wikipedia.org/wiki/MPEG_transport_stream
17
+ * @export
18
+ */
19
+ shaka.util.TsParser = class {
20
+ /** */
21
+ constructor() {
22
+ /** @private {?number} */
23
+ this.pmtId_ = null;
24
+
25
+ /** @private {boolean} */
26
+ this.pmtParsed_ = false;
27
+
28
+ /** @private {?number} */
29
+ this.videoStartTime_ = null;
30
+
31
+ /** @private {?number} */
32
+ this.videoPid_ = null;
33
+
34
+ /** @private {?string} */
35
+ this.videoCodec_ = null;
36
+
37
+ /** @private {!Array.<Uint8Array>} */
38
+ this.videoData_ = [];
39
+
40
+ /** @private {?number} */
41
+ this.audioStartTime_ = null;
42
+
43
+ /** @private {?number} */
44
+ this.audioPid_ = null;
45
+
46
+ /** @private {?string} */
47
+ this.audioCodec_ = null;
48
+
49
+ /** @private {!Array.<Uint8Array>} */
50
+ this.audioData_ = [];
51
+
52
+ /** @private {?number} */
53
+ this.id3Pid_ = null;
54
+
55
+ /** @private {!Array.<Uint8Array>} */
56
+ this.id3Data_ = [];
57
+ }
58
+
59
+ /**
60
+ * Parse the given data
61
+ *
62
+ * @param {Uint8Array} data
63
+ * @return {!shaka.util.TsParser}
64
+ */
65
+ parse(data) {
66
+ const timescale = shaka.util.TsParser.Timescale_;
67
+ const packetLength = shaka.util.TsParser.PacketLength_;
68
+
69
+ // A TS fragment should contain at least 3 TS packets, a PAT, a PMT, and
70
+ // one PID.
71
+ if (data.length < 3 * packetLength) {
72
+ return this;
73
+ }
74
+ const syncOffset = Math.max(0, shaka.util.TsParser.syncOffset(data));
75
+
76
+ const length = data.length - (data.length + syncOffset) % packetLength;
77
+
78
+ let unknownPIDs = false;
79
+
80
+ // loop through TS packets
81
+ for (let start = syncOffset; start < length; start += packetLength) {
82
+ if (data[start] === 0x47) {
83
+ const payloadUnitStartIndicator = !!(data[start + 1] & 0x40);
84
+ // pid is a 13-bit field starting at the last 5 bits of TS[1]
85
+ const pid = ((data[start + 1] & 0x1f) << 8) + data[start + 2];
86
+ const adaptationFieldControl = (data[start + 3] & 0x30) >> 4;
87
+
88
+ // if an adaption field is present, its length is specified by the
89
+ // fifth byte of the TS packet header.
90
+ let offset;
91
+ if (adaptationFieldControl > 1) {
92
+ offset = start + 5 + data[start + 4];
93
+ // continue if there is only adaptation field
94
+ if (offset === start + packetLength) {
95
+ continue;
96
+ }
97
+ } else {
98
+ offset = start + 4;
99
+ }
100
+ switch (pid) {
101
+ case 0:
102
+ if (payloadUnitStartIndicator) {
103
+ offset += data[offset] + 1;
104
+ }
105
+
106
+ this.pmtId_ = this.getPmtId_(data, offset);
107
+ break;
108
+ case 17:
109
+ case 0x1fff:
110
+ break;
111
+ case this.pmtId_: {
112
+ if (payloadUnitStartIndicator) {
113
+ offset += data[offset] + 1;
114
+ }
115
+
116
+ const parsedPIDs = this.parsePMT(data, offset);
117
+
118
+ // only update track id if track PID found while parsing PMT
119
+ // this is to avoid resetting the PID to -1 in case
120
+ // track PID transiently disappears from the stream
121
+ // this could happen in case of transient missing audio samples
122
+ // for example
123
+ // NOTE this is only the PID of the track as found in TS,
124
+ // but we are not using this for MP4 track IDs.
125
+ if (this.videoPid_ == null) {
126
+ this.videoPid_ = parsedPIDs.video;
127
+ this.videoCodec_ = parsedPIDs.videoCodec;
128
+ }
129
+ if (this.audioPid_ == null) {
130
+ this.audioPid_ = parsedPIDs.audio;
131
+ this.audioCodec_ = parsedPIDs.audioCodec;
132
+ }
133
+ if (this.id3Pid_ == null) {
134
+ this.id3Pid_ = parsedPIDs.id3;
135
+ }
136
+
137
+ if (unknownPIDs && !this.pmtParsed_) {
138
+ shaka.log.debug('reparse from beginning');
139
+ unknownPIDs = false;
140
+ // we set it to -188, the += 188 in the for loop will reset
141
+ // start to 0
142
+ start = syncOffset - packetLength;
143
+ }
144
+ this.pmtParsed_ = true;
145
+ break;
146
+ }
147
+ case this.videoPid_: {
148
+ const videoData = data.subarray(offset, start + packetLength);
149
+ if (this.videoStartTime_ == null) {
150
+ const pes = this.parsePES(videoData);
151
+ if (pes && pes.pts != null) {
152
+ this.videoStartTime_ = pes.pts / timescale;
153
+ }
154
+ }
155
+ this.videoData_.push(videoData);
156
+ break;
157
+ }
158
+ case this.audioPid_: {
159
+ const audioData = data.subarray(offset, start + packetLength);
160
+ if (this.audioStartTime_ == null) {
161
+ const pes = this.parsePES(audioData);
162
+ if (pes && pes.pts != null) {
163
+ this.audioStartTime_ = pes.pts / timescale;
164
+ }
165
+ }
166
+ this.audioData_.push(audioData);
167
+ break;
168
+ }
169
+ case this.id3Pid_:
170
+ this.id3Data_.push(data.subarray(offset, start + packetLength));
171
+ break;
172
+ default:
173
+ unknownPIDs = true;
174
+ break;
175
+ }
176
+ } else {
177
+ shaka.log.warning('Found TS packet that do not start with 0x47');
178
+ }
179
+ }
180
+ return this;
181
+ }
182
+
183
+ /**
184
+ * Get the PMT ID from the PAT
185
+ *
186
+ * @param {Uint8Array} data
187
+ * @param {number} offset
188
+ * @return {number}
189
+ * @private
190
+ */
191
+ getPmtId_(data, offset) {
192
+ // skip the PSI header and parse the first PMT entry
193
+ return ((data[offset + 10] & 0x1f) << 8) | data[offset + 11];
194
+ }
195
+
196
+ /**
197
+ * Parse PMT
198
+ *
199
+ * @param {Uint8Array} data
200
+ * @param {number} offset
201
+ * @return {!shaka.util.TsParser.PMT}
202
+ */
203
+ parsePMT(data, offset) {
204
+ const result = {
205
+ audio: -1,
206
+ video: -1,
207
+ id3: -1,
208
+ audioCodec: '',
209
+ videoCodec: '',
210
+ };
211
+ const sectionLength = ((data[offset + 1] & 0x0f) << 8) | data[offset + 2];
212
+ const tableEnd = offset + 3 + sectionLength - 4;
213
+ // to determine where the table is, we have to figure out how
214
+ // long the program info descriptors are
215
+ const programInfoLength =
216
+ ((data[offset + 10] & 0x0f) << 8) | data[offset + 11];
217
+ // advance the offset to the first entry in the mapping table
218
+ offset += 12 + programInfoLength;
219
+ while (offset < tableEnd) {
220
+ const pid = ((data[offset + 1] & 0x1f) << 8) | data[offset + 2];
221
+ switch (data[offset]) {
222
+ // SAMPLE-AES AAC
223
+ case 0xcf:
224
+ break;
225
+ // ISO/IEC 13818-7 ADTS AAC (MPEG-2 lower bit-rate audio)
226
+ case 0x0f:
227
+ if (result.audio === -1) {
228
+ result.audio = pid;
229
+ result.audioCodec = 'aac';
230
+ }
231
+ break;
232
+ // Packetized metadata (ID3)
233
+ case 0x15:
234
+ if (result.id3 === -1) {
235
+ result.id3 = pid;
236
+ }
237
+ break;
238
+ // SAMPLE-AES AVC
239
+ case 0xdb:
240
+ break;
241
+ // ITU-T Rec. H.264 and ISO/IEC 14496-10 (lower bit-rate video)
242
+ case 0x1b:
243
+ if (result.video === -1) {
244
+ result.video = pid;
245
+ result.videoCodec = 'avc';
246
+ }
247
+ break;
248
+ // ISO/IEC 11172-3 (MPEG-1 audio)
249
+ // or ISO/IEC 13818-3 (MPEG-2 halved sample rate audio)
250
+ case 0x03:
251
+ case 0x04:
252
+ if (result.audio === -1) {
253
+ result.audio = pid;
254
+ result.audioCodec = 'mp3';
255
+ }
256
+ break;
257
+ // HEVC
258
+ case 0x24:
259
+ if (result.video === -1) {
260
+ result.video = pid;
261
+ result.videoCodec = 'hvc';
262
+ }
263
+ break;
264
+ default:
265
+ // shaka.log.warning('Unknown stream type:', data[offset]);
266
+ break;
267
+ }
268
+ // move to the next table entry
269
+ // skip past the elementary stream descriptors, if present
270
+ offset += (((data[offset + 3] & 0x0f) << 8) | data[offset + 4]) + 5;
271
+ }
272
+ return result;
273
+ }
274
+
275
+ /**
276
+ * Parse PES
277
+ *
278
+ * @param {Uint8Array} data
279
+ * @return {?shaka.util.TsParser.PES}
280
+ */
281
+ parsePES(data) {
282
+ const startPrefix = (data[0] << 16) | (data[1] << 8) | data[2];
283
+ // In certain live streams, the start of a TS fragment has ts packets
284
+ // that are frame data that is continuing from the previous fragment. This
285
+ // is to check that the pes data is the start of a new pes data
286
+ if (startPrefix !== 1) {
287
+ return null;
288
+ }
289
+ /** @type {shaka.util.TsParser.PES} */
290
+ const pes = {
291
+ data: new Uint8Array(0),
292
+ // get the packet length, this will be 0 for video
293
+ packetLength: 6 + ((data[4] << 8) | data[5]),
294
+ pts: null,
295
+ dts: null,
296
+ };
297
+
298
+ // PES packets may be annotated with a PTS value, or a PTS value
299
+ // and a DTS value. Determine what combination of values is
300
+ // available to work with.
301
+ const ptsDtsFlags = data[7];
302
+
303
+ // PTS and DTS are normally stored as a 33-bit number. Javascript
304
+ // performs all bitwise operations on 32-bit integers but javascript
305
+ // supports a much greater range (52-bits) of integer using standard
306
+ // mathematical operations.
307
+ // We construct a 31-bit value using bitwise operators over the 31
308
+ // most significant bits and then multiply by 4 (equal to a left-shift
309
+ // of 2) before we add the final 2 least significant bits of the
310
+ // timestamp (equal to an OR.)
311
+ if (ptsDtsFlags & 0xC0) {
312
+ // the PTS and DTS are not written out directly. For information
313
+ // on how they are encoded, see
314
+ // http://dvd.sourceforge.net/dvdinfo/pes-hdr.html
315
+ pes.pts =
316
+ (data[9] & 0x0e) * 536870912 + // 1 << 29
317
+ (data[10] & 0xff) * 4194304 + // 1 << 22
318
+ (data[11] & 0xfe) * 16384 + // 1 << 14
319
+ (data[12] & 0xff) * 128 + // 1 << 7
320
+ (data[13] & 0xfe) / 2;
321
+
322
+ pes.dts = pes.pts;
323
+ if (ptsDtsFlags & 0x40) {
324
+ pes.dts =
325
+ (data[14] & 0x0e) * 536870912 + // 1 << 29
326
+ (data[15] & 0xff) * 4194304 + // 1 << 22
327
+ (data[16] & 0xfe) * 16384 + // 1 << 14
328
+ (data[17] & 0xff) * 128 + // 1 << 7
329
+ (data[18] & 0xfe) / 2;
330
+ }
331
+ }
332
+ // the data section starts immediately after the PES header.
333
+ // pes_header_data_length specifies the number of header bytes
334
+ // that follow the last byte of the field.
335
+ pes.data = data.subarray(9 + data[8]);
336
+
337
+ return pes;
338
+ }
339
+
340
+ /**
341
+ * Return the ID3 metadata
342
+ *
343
+ * @return {!Array.<shaka.extern.ID3Metadata>}
344
+ */
345
+ getMetadata() {
346
+ const timescale = shaka.util.TsParser.Timescale_;
347
+ const Uint8ArrayUtils = shaka.util.Uint8ArrayUtils;
348
+ const metadata = [];
349
+ let prevId3Data = new Uint8Array(0);
350
+ // parsePES() only works if the data begins on a PES boundary.
351
+ // Try the last data blob first, and if it doesn't begin on a
352
+ // PES boundary, prepend the previous blob and try again.
353
+ // This way, a successful parse will always begin and end on
354
+ // the correct boundary, and no data will be skipped.
355
+ for (let i = this.id3Data_.length - 1; i >= 0; i--) {
356
+ const data = this.id3Data_[i];
357
+ goog.asserts.assert(data, 'We should have a data');
358
+ const id3Data = Uint8ArrayUtils.concat(data, prevId3Data);
359
+ const pes = this.parsePES(id3Data);
360
+ if (pes) {
361
+ metadata.unshift({
362
+ cueTime: pes.pts ? pes.pts / timescale : null,
363
+ data: pes.data,
364
+ frames: shaka.util.Id3Utils.getID3Frames(pes.data),
365
+ dts: pes.dts,
366
+ pts: pes.pts,
367
+ });
368
+ prevId3Data = new Uint8Array(0);
369
+ } else {
370
+ prevId3Data = id3Data;
371
+ }
372
+ }
373
+ return metadata;
374
+ }
375
+
376
+ /**
377
+ * Return the start time for the audio and video
378
+ *
379
+ * @return {{audio: ?number, video: ?number}}
380
+ */
381
+ getStartTime() {
382
+ return {
383
+ audio: this.audioStartTime_,
384
+ video: this.videoStartTime_,
385
+ };
386
+ }
387
+
388
+ /**
389
+ * Return the audio and video codecs
390
+ *
391
+ * @return {{audio: ?string, video: ?string}}
392
+ */
393
+ getCodecs() {
394
+ return {
395
+ audio: this.audioCodec_,
396
+ video: this.videoCodec_,
397
+ };
398
+ }
399
+
400
+ /**
401
+ * Check if the passed data corresponds to an MPEG2-TS
402
+ *
403
+ * @param {Uint8Array} data
404
+ * @return {boolean}
405
+ */
406
+ static probe(data) {
407
+ const syncOffset = shaka.util.TsParser.syncOffset(data);
408
+ if (syncOffset < 0) {
409
+ return false;
410
+ } else {
411
+ if (syncOffset > 0) {
412
+ shaka.log.warning('MPEG2-TS detected but first sync word found @ ' +
413
+ 'offset ' + syncOffset + ', junk ahead ?');
414
+ }
415
+ return true;
416
+ }
417
+ }
418
+
419
+ /**
420
+ * Returns the synchronization offset
421
+ *
422
+ * @param {Uint8Array} data
423
+ * @return {number}
424
+ */
425
+ static syncOffset(data) {
426
+ const packetLength = shaka.util.TsParser.PacketLength_;
427
+ // scan 1000 first bytes
428
+ const scanwindow = Math.min(1000, data.length - 3 * packetLength);
429
+ let i = 0;
430
+ while (i < scanwindow) {
431
+ // a TS fragment should contain at least 3 TS packets, a PAT, a PMT, and
432
+ // one PID, each starting with 0x47
433
+ if (data[i] === 0x47 &&
434
+ data[i + packetLength] === 0x47 &&
435
+ data[i + 2 * packetLength] === 0x47) {
436
+ return i;
437
+ } else {
438
+ i++;
439
+ }
440
+ }
441
+ return -1;
442
+ }
443
+ };
444
+
445
+
446
+ /**
447
+ * @const {number}
448
+ * @private
449
+ */
450
+ shaka.util.TsParser.PacketLength_ = 188;
451
+
452
+
453
+ /**
454
+ * @const {number}
455
+ * @private
456
+ */
457
+ shaka.util.TsParser.Timescale_ = 90000;
458
+
459
+
460
+ /**
461
+ * @typedef {{
462
+ * audio: number,
463
+ * video: number,
464
+ * id3: number,
465
+ * audioCodec: string,
466
+ * videoCodec: string
467
+ * }}
468
+ *
469
+ * @summary PMT.
470
+ * @property {number} audio
471
+ * Audio PID
472
+ * @property {number} video
473
+ * Video PID
474
+ * @property {number} id3
475
+ * ID3 PID
476
+ * @property {string} audioCodec
477
+ * Audio codec
478
+ * @property {string} videoCodec
479
+ * Video codec
480
+ */
481
+ shaka.util.TsParser.PMT;
482
+
483
+
484
+ /**
485
+ * @typedef {{
486
+ * data: Uint8Array,
487
+ * packetLength: number,
488
+ * pts: ?number,
489
+ * dts: ?number
490
+ * }}
491
+ *
492
+ * @summary PES.
493
+ * @property {Uint8Array} data
494
+ * @property {number} packetLength
495
+ * @property {?number} pts
496
+ * @property {?number} dts
497
+ */
498
+ shaka.util.TsParser.PES;
499
+
@@ -2,8 +2,8 @@
2
2
 
3
3
  We are currently maintaining the following branches of Shaka Player:
4
4
 
5
- - v4.1 (latest)
6
- - v4.0 (previous)
5
+ - v4.3 (latest)
6
+ - v4.2 (previous)
7
7
  - v3.3 (LTS until April 30, 2023)
8
8
  - v3.2 (in use by the Cast Application Framework)
9
9
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "shaka-player",
3
3
  "description": "DASH/EME video player library",
4
- "version": "4.2.4",
4
+ "version": "4.3.0",
5
5
  "homepage": "https://github.com/shaka-project/shaka-player",
6
6
  "author": "Google",
7
7
  "maintainers": [
@@ -46,6 +46,7 @@
46
46
  "karma-sourcemap-loader": "^0.3.8",
47
47
  "karma-spec-reporter": "^0.0.34",
48
48
  "karma-webdriver-launcher": "^1.0.8",
49
+ "lcevc_dil.js": "^1.1.20",
49
50
  "less": "https://gitpkg.now.sh/joeyparrish/less.js/packages/less?28c63a43",
50
51
  "less-plugin-clean-css": "github:austingardner/less-plugin-clean-css#4e9e77bf",
51
52
  "material-design-lite": "^1.3.0",
@@ -71,6 +72,8 @@
71
72
  "eme-encryption-scheme-polyfill/index.js",
72
73
  "es6-promise-polyfill/promise.min.js",
73
74
  "google-closure-library/closure/goog/base.js",
75
+ "lcevc_dil.js/dist/lcevc_dil.min.js",
76
+ "lcevc_dil.js/dist/liblcevc_dpi.wasm",
74
77
  "less/dist/less.js",
75
78
  "material-design-lite/dist/material.indigo-blue.min.css",
76
79
  "material-design-lite/dist/material.min.js",
package/roadmap.md CHANGED
@@ -23,13 +23,15 @@ Candidate features for future release cycles:
23
23
  https://github.com/shaka-project/shaka-player/issues/879
24
24
  - Smaller, more modular binary
25
25
 
26
- v4.3 - 2022 Q4 / 2023 Q1
26
+ =====
27
+
28
+ v4.3 - 2022 Q4
27
29
  - Support ID3 tags in mp4
28
30
  https://github.com/shaka-project/shaka-player/issues/3351
29
31
  - Lazy-load HLS playlists on adaptation
30
32
  https://github.com/shaka-project/shaka-player/issues/1936
31
-
32
- =====
33
+ - HLS key rotation
34
+ https://github.com/shaka-project/shaka-player/issues/741
33
35
 
34
36
  v4.2 - 2022 Q3
35
37
  - Automatic ABR quality restrictions based on size