shaka-player 4.4.3 → 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/release-please.yaml +2 -27
- package/CHANGELOG.md +64 -45
- package/README.md +16 -10
- package/demo/asset_card.js +18 -21
- package/demo/cast_receiver/index.html +0 -1
- package/demo/close_button.js +0 -3
- package/demo/common/asset.js +22 -5
- package/demo/common/assets.js +132 -49
- package/demo/config.js +192 -253
- package/demo/custom.js +39 -98
- package/demo/front.js +7 -10
- package/demo/index.html +19 -22
- package/demo/input.js +6 -11
- package/demo/input_container.js +8 -9
- package/demo/main.js +51 -123
- package/demo/search.js +22 -34
- package/demo/service_worker.js +0 -3
- package/demo/tooltip.js +3 -5
- package/demo/visualizer.js +3 -5
- package/demo/visualizer_button.js +1 -20
- package/dist/demo.compiled.debug.js +152 -178
- package/dist/demo.compiled.debug.map +4 -4
- package/dist/demo.compiled.js +152 -178
- package/dist/demo.compiled.map +4 -4
- package/dist/deps.js +27 -24
- package/dist/locales.js +31 -31
- package/dist/receiver.compiled.debug.js +22 -43
- package/dist/receiver.compiled.debug.map +4 -4
- package/dist/receiver.compiled.js +22 -43
- package/dist/receiver.compiled.map +4 -4
- package/dist/shaka-player.compiled.d.ts +507 -365
- package/dist/shaka-player.compiled.debug.d.ts +507 -365
- package/dist/shaka-player.compiled.debug.externs.js +205 -51
- package/dist/shaka-player.compiled.debug.js +541 -450
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +205 -51
- package/dist/shaka-player.compiled.js +1120 -1066
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +562 -410
- package/dist/shaka-player.ui.debug.d.ts +562 -410
- package/dist/shaka-player.ui.debug.externs.js +226 -51
- package/dist/shaka-player.ui.debug.js +606 -506
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +226 -51
- package/dist/shaka-player.ui.js +1266 -1207
- package/dist/shaka-player.ui.map +4 -4
- package/docs/design/lcevc-integration.md +14 -14
- package/docs/tutorials/faq.md +27 -55
- package/docs/tutorials/index.json +2 -1
- package/docs/tutorials/lcevc.md +118 -0
- package/docs/tutorials/ui-customization.md +4 -0
- package/externs/css_style_declaration.js +19 -0
- package/externs/lcevc.js +37 -13
- package/externs/media_remote.js +68 -0
- package/externs/mediatailor.js +193 -0
- package/externs/pictureinpicture.js +11 -0
- package/externs/shaka/ads.js +27 -0
- package/externs/shaka/manifest.js +10 -5
- package/externs/shaka/manifest_parser.js +7 -1
- package/externs/shaka/offline.js +4 -0
- package/externs/shaka/player.js +12 -1
- package/karma.conf.js +7 -3
- package/lib/abr/simple_abr_manager.js +43 -3
- package/lib/ads/ad_manager.js +104 -50
- package/lib/ads/media_tailor_ad.js +297 -0
- package/lib/ads/media_tailor_ad_manager.js +828 -0
- package/lib/cea/ts_cea_parser.js +15 -2
- package/lib/config/codec_switching_strategy.js +24 -0
- package/lib/dash/content_protection.js +120 -2
- package/lib/dash/dash_parser.js +75 -12
- package/lib/dash/mpd_utils.js +10 -6
- package/lib/dash/segment_base.js +13 -5
- package/lib/dash/segment_list.js +13 -5
- package/lib/dash/segment_template.js +43 -85
- package/lib/dependencies/all.js +8 -7
- package/lib/hls/hls_parser.js +44 -16
- package/lib/lcevc/lcevc_dec.js +220 -0
- package/lib/media/adaptation_set.js +22 -11
- package/lib/media/adaptation_set_criteria.js +25 -7
- package/lib/media/media_source_engine.js +215 -27
- package/lib/media/segment_index.js +1 -1
- package/lib/media/segment_reference.js +7 -7
- package/lib/media/streaming_engine.js +33 -18
- package/lib/mss/mss_parser.js +1 -0
- package/lib/net/networking_engine.js +1 -0
- package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
- package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
- package/lib/offline/manifest_converter.js +1 -0
- package/lib/offline/storage.js +3 -0
- package/lib/player.js +142 -72
- package/lib/routing/payload.js +5 -1
- package/lib/text/cue.js +15 -0
- package/lib/text/ttml_text_parser.js +17 -0
- package/lib/text/ui_text_displayer.js +4 -0
- package/lib/text/vtt_text_parser.js +33 -20
- package/lib/transmuxer/h265.js +862 -0
- package/lib/transmuxer/mpeg_ts_transmuxer.js +3 -2
- package/lib/transmuxer/ts_transmuxer.js +160 -15
- package/lib/util/error.js +28 -9
- package/lib/util/exp_golomb.js +30 -2
- package/lib/util/fake_event.js +3 -0
- package/lib/util/mp4_generator.js +4 -4
- package/lib/util/periods.js +2 -0
- package/lib/util/platform.js +40 -0
- package/lib/util/player_configuration.js +8 -0
- package/lib/util/state_history.js +6 -2
- package/lib/util/stream_utils.js +133 -217
- package/lib/util/ts_parser.js +226 -40
- package/maintained-branches.md +3 -2
- package/package.json +4 -6
- package/roadmap.md +15 -5
- package/shaka-player.uncompiled.js +2 -1
- package/support.html +0 -1
- package/test/cast/cast_receiver_integration.js +47 -0
- package/test/codec_switching/codec_switching_integration.js +181 -0
- package/test/dash/dash_parser_content_protection_unit.js +2 -0
- package/test/dash/dash_parser_integration.js +73 -0
- package/test/dash/dash_parser_live_unit.js +2 -0
- package/test/dash/dash_parser_manifest_unit.js +42 -0
- package/test/dash/dash_parser_segment_base_unit.js +2 -0
- package/test/dash/dash_parser_segment_list_unit.js +2 -0
- package/test/dash/dash_parser_segment_template_unit.js +2 -0
- package/test/demo/demo_unit.js +0 -16
- package/test/hls/hls_live_unit.js +2 -0
- package/test/hls/hls_parser_unit.js +8 -6
- package/test/media/adaptation_set_criteria_unit.js +118 -0
- package/test/media/adaptation_set_unit.js +1 -0
- package/test/media/media_source_engine_unit.js +165 -1
- package/test/media/segment_index_unit.js +4 -4
- package/test/media/segment_prefetch_unit.js +1 -1
- package/test/media/streaming_engine_unit.js +17 -17
- package/test/mss/mss_parser_unit.js +2 -0
- package/test/offline/manifest_convert_unit.js +5 -0
- package/test/offline/storage_integration.js +1 -4
- package/test/player_unit.js +102 -131
- package/test/routing/walker_unit.js +1 -0
- package/test/test/assets/dash-aes-128/Fragments(video=0,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=20000000,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=40000000,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=60000000,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=i,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/dash.mpd +18 -0
- package/test/test/assets/dash-aes-128/license +1 -0
- package/test/test/assets/dash-multi-codec/audio_en_2c_128k_aac.mp4 +0 -0
- package/test/test/assets/dash-multi-codec/audio_es_2c_64k_opus.webm +0 -0
- package/test/test/assets/dash-multi-codec/dash.mpd +32 -0
- package/test/test/assets/dash-multi-codec/video_144p_108k_h264.mp4 +0 -0
- package/test/test/assets/hls-ts-h265/0.ts +0 -0
- package/test/test/assets/hls-ts-h265/hevc.m3u8 +6 -0
- package/test/test/assets/hls-ts-h265/index.m3u8 +7 -0
- package/test/test/assets/hls-ts-muxed-aac-h265/0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h265/1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h265/media.m3u8 +9 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/media.m3u8 +24 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00000.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00001.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00002.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00003.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00004.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00005.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0000.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0001.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0002.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0003.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/prog_index.m3u8 +14 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/index.m3u8 +23 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-1-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-2-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-3-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-4-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-5-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-6-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-7-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-8-v1-a1.ts +0 -0
- package/test/test/util/dash_parser_util.js +4 -0
- package/test/test/util/fake_ad_manager.js +20 -0
- package/test/test/util/fake_media_source_engine.js +8 -2
- package/test/test/util/manifest_generator.js +7 -3
- package/test/test/util/mss_parser_util.js +4 -0
- package/test/test/util/offline_utils.js +1 -0
- package/test/test/util/streaming_engine_util.js +7 -4
- package/test/text/ttml_text_parser_unit.js +52 -0
- package/test/text/vtt_text_parser_unit.js +103 -31
- package/test/transmuxer/transmuxer_integration.js +117 -0
- package/test/ui/ui_unit.js +3 -10
- package/test/util/stream_utils_unit.js +208 -74
- package/ui/controls.js +125 -0
- package/ui/externs/ui.js +8 -1
- package/ui/pip_button.js +22 -120
- package/ui/remote_button.js +201 -0
- package/ui/ui.js +5 -2
- package/demo/common/message_ids.js +0 -309
- package/demo/locales/en.json +0 -288
- package/demo/locales/source.json +0 -1146
- package/externs/mux.js +0 -69
- package/lib/lcevc/lcevc_dil.js +0 -152
- package/lib/transmuxer/muxjs_transmuxer.js +0 -242
- package/test/transmuxer/muxjs_transmuxer_integration.js +0 -177
|
@@ -128,8 +128,9 @@ shaka.transmuxer.MpegTsTransmuxer = class {
|
|
|
128
128
|
* @override
|
|
129
129
|
* @export
|
|
130
130
|
*/
|
|
131
|
-
transmux(data) {
|
|
131
|
+
transmux(data, stream, reference, duration, contentType) {
|
|
132
132
|
const MpegAudio = shaka.transmuxer.MpegAudio;
|
|
133
|
+
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
133
134
|
const Uint8ArrayUtils = shaka.util.Uint8ArrayUtils;
|
|
134
135
|
|
|
135
136
|
if (!this.tsParser_) {
|
|
@@ -142,7 +143,7 @@ shaka.transmuxer.MpegTsTransmuxer = class {
|
|
|
142
143
|
|
|
143
144
|
const tsParser = this.tsParser_.parse(uint8ArrayData);
|
|
144
145
|
const codecs = tsParser.getCodecs();
|
|
145
|
-
if (codecs.audio != 'mp3' ||
|
|
146
|
+
if (codecs.audio != 'mp3' || contentType != ContentType.AUDIO) {
|
|
146
147
|
return Promise.reject(new shaka.util.Error(
|
|
147
148
|
shaka.util.Error.Severity.CRITICAL,
|
|
148
149
|
shaka.util.Error.Category.MEDIA,
|
|
@@ -11,6 +11,7 @@ goog.require('shaka.transmuxer.Ac3');
|
|
|
11
11
|
goog.require('shaka.transmuxer.ADTS');
|
|
12
12
|
goog.require('shaka.transmuxer.Ec3');
|
|
13
13
|
goog.require('shaka.transmuxer.H264');
|
|
14
|
+
goog.require('shaka.transmuxer.H265');
|
|
14
15
|
goog.require('shaka.transmuxer.MpegAudio');
|
|
15
16
|
goog.require('shaka.transmuxer.TransmuxerEngine');
|
|
16
17
|
goog.require('shaka.util.BufferUtils');
|
|
@@ -21,6 +22,8 @@ goog.require('shaka.util.Mp4Generator');
|
|
|
21
22
|
goog.require('shaka.util.TsParser');
|
|
22
23
|
goog.require('shaka.util.Uint8ArrayUtils');
|
|
23
24
|
|
|
25
|
+
goog.requireType('shaka.media.SegmentReference');
|
|
26
|
+
|
|
24
27
|
|
|
25
28
|
/**
|
|
26
29
|
* @implements {shaka.extern.Transmuxer}
|
|
@@ -80,11 +83,6 @@ shaka.transmuxer.TsTransmuxer = class {
|
|
|
80
83
|
const videoCodec = shaka.util.ManifestParserUtils.guessCodecsSafe(
|
|
81
84
|
ContentType.VIDEO, allCodecs);
|
|
82
85
|
|
|
83
|
-
// We don't support muxed content yet.
|
|
84
|
-
if (audioCodec && videoCodec) {
|
|
85
|
-
return false;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
86
|
const TsTransmuxer = shaka.transmuxer.TsTransmuxer;
|
|
89
87
|
|
|
90
88
|
if (audioCodec) {
|
|
@@ -179,7 +177,11 @@ shaka.transmuxer.TsTransmuxer = class {
|
|
|
179
177
|
switch (codecs.video) {
|
|
180
178
|
case 'avc':
|
|
181
179
|
streamInfo =
|
|
182
|
-
this.getAvcStreamInfo_(tsParser, stream, duration);
|
|
180
|
+
this.getAvcStreamInfo_(tsParser, stream, duration, reference);
|
|
181
|
+
break;
|
|
182
|
+
case 'hvc':
|
|
183
|
+
streamInfo =
|
|
184
|
+
this.getHvcStreamInfo_(tsParser, stream, duration, reference);
|
|
183
185
|
break;
|
|
184
186
|
}
|
|
185
187
|
if (streamInfo) {
|
|
@@ -191,7 +193,7 @@ shaka.transmuxer.TsTransmuxer = class {
|
|
|
191
193
|
switch (codecs.audio) {
|
|
192
194
|
case 'aac':
|
|
193
195
|
streamInfo =
|
|
194
|
-
this.getAacStreamInfo_(tsParser, stream, duration);
|
|
196
|
+
this.getAacStreamInfo_(tsParser, stream, duration, reference);
|
|
195
197
|
break;
|
|
196
198
|
case 'ac3':
|
|
197
199
|
streamInfo =
|
|
@@ -242,10 +244,11 @@ shaka.transmuxer.TsTransmuxer = class {
|
|
|
242
244
|
* @param {shaka.util.TsParser} tsParser
|
|
243
245
|
* @param {shaka.extern.Stream} stream
|
|
244
246
|
* @param {number} duration
|
|
247
|
+
* @param {?shaka.media.SegmentReference} reference
|
|
245
248
|
* @return {shaka.util.Mp4Generator.StreamInfo}
|
|
246
249
|
* @private
|
|
247
250
|
*/
|
|
248
|
-
getAacStreamInfo_(tsParser, stream, duration) {
|
|
251
|
+
getAacStreamInfo_(tsParser, stream, duration, reference) {
|
|
249
252
|
const ADTS = shaka.transmuxer.ADTS;
|
|
250
253
|
const timescale = shaka.util.TsParser.Timescale;
|
|
251
254
|
|
|
@@ -306,10 +309,58 @@ shaka.transmuxer.TsTransmuxer = class {
|
|
|
306
309
|
}
|
|
307
310
|
|
|
308
311
|
if (!info || firstPts == null) {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
312
|
+
if (!tsParser.getVideoData().length) {
|
|
313
|
+
throw new shaka.util.Error(
|
|
314
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
315
|
+
shaka.util.Error.Category.MEDIA,
|
|
316
|
+
shaka.util.Error.Code.TRANSMUXING_FAILED);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
firstPts = reference.startTime * timescale;
|
|
320
|
+
|
|
321
|
+
const allCodecs = shaka.util.MimeUtils.splitCodecs(stream.codecs);
|
|
322
|
+
const audioCodec = shaka.util.ManifestParserUtils.guessCodecsSafe(
|
|
323
|
+
shaka.util.ManifestParserUtils.ContentType.AUDIO, allCodecs);
|
|
324
|
+
if (!audioCodec || !stream.channelsCount || !stream.audioSamplingRate) {
|
|
325
|
+
throw new shaka.util.Error(
|
|
326
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
327
|
+
shaka.util.Error.Category.MEDIA,
|
|
328
|
+
shaka.util.Error.Code.TRANSMUXING_FAILED);
|
|
329
|
+
}
|
|
330
|
+
info = {
|
|
331
|
+
sampleRate: stream.audioSamplingRate,
|
|
332
|
+
channelCount: stream.channelsCount,
|
|
333
|
+
codec: audioCodec,
|
|
334
|
+
};
|
|
335
|
+
const silenceFrame =
|
|
336
|
+
ADTS.getSilentFrame(audioCodec, stream.channelsCount);
|
|
337
|
+
if (!silenceFrame) {
|
|
338
|
+
throw new shaka.util.Error(
|
|
339
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
340
|
+
shaka.util.Error.Category.MEDIA,
|
|
341
|
+
shaka.util.Error.Code.TRANSMUXING_FAILED);
|
|
342
|
+
}
|
|
343
|
+
const segmentDuration =
|
|
344
|
+
(reference.endTime - reference.startTime) * timescale;
|
|
345
|
+
const finalPTs = firstPts + segmentDuration;
|
|
346
|
+
let currentPts = firstPts;
|
|
347
|
+
while (currentPts < finalPTs) {
|
|
348
|
+
samples.push({
|
|
349
|
+
data: silenceFrame,
|
|
350
|
+
size: silenceFrame.byteLength,
|
|
351
|
+
duration: ADTS.AAC_SAMPLES_PER_FRAME,
|
|
352
|
+
cts: 0,
|
|
353
|
+
flags: {
|
|
354
|
+
isLeading: 0,
|
|
355
|
+
isDependedOn: 0,
|
|
356
|
+
hasRedundancy: 0,
|
|
357
|
+
degradPrio: 0,
|
|
358
|
+
dependsOn: 2,
|
|
359
|
+
isNonSync: 0,
|
|
360
|
+
},
|
|
361
|
+
});
|
|
362
|
+
currentPts += ADTS.AAC_SAMPLES_PER_FRAME / info.sampleRate * timescale;
|
|
363
|
+
}
|
|
313
364
|
}
|
|
314
365
|
|
|
315
366
|
/** @type {number} */
|
|
@@ -609,10 +660,11 @@ shaka.transmuxer.TsTransmuxer = class {
|
|
|
609
660
|
* @param {shaka.util.TsParser} tsParser
|
|
610
661
|
* @param {shaka.extern.Stream} stream
|
|
611
662
|
* @param {number} duration
|
|
663
|
+
* @param {?shaka.media.SegmentReference} reference
|
|
612
664
|
* @return {shaka.util.Mp4Generator.StreamInfo}
|
|
613
665
|
* @private
|
|
614
666
|
*/
|
|
615
|
-
getAvcStreamInfo_(tsParser, stream, duration) {
|
|
667
|
+
getAvcStreamInfo_(tsParser, stream, duration, reference) {
|
|
616
668
|
const H264 = shaka.transmuxer.H264;
|
|
617
669
|
const timescale = shaka.util.TsParser.Timescale;
|
|
618
670
|
|
|
@@ -630,7 +682,7 @@ shaka.transmuxer.TsTransmuxer = class {
|
|
|
630
682
|
if (i + 1 < videoData.length) {
|
|
631
683
|
nextPes = videoData[i + 1];
|
|
632
684
|
}
|
|
633
|
-
const dataNalus = tsParser.
|
|
685
|
+
const dataNalus = tsParser.parseNalus(pes, nextPes);
|
|
634
686
|
nalus = nalus.concat(dataNalus);
|
|
635
687
|
const frame = H264.parseFrame(dataNalus);
|
|
636
688
|
if (!frame) {
|
|
@@ -642,8 +694,10 @@ shaka.transmuxer.TsTransmuxer = class {
|
|
|
642
694
|
let duration;
|
|
643
695
|
if (i + 1 < videoData.length) {
|
|
644
696
|
duration = (videoData[i + 1].dts || 0) - (pes.dts || 0);
|
|
645
|
-
} else {
|
|
697
|
+
} else if (videoData.length > 1) {
|
|
646
698
|
duration = (pes.dts || 0) - (videoData[i - 1].dts || 0);
|
|
699
|
+
} else {
|
|
700
|
+
duration = (reference.endTime - reference.startTime) * timescale;
|
|
647
701
|
}
|
|
648
702
|
samples.push({
|
|
649
703
|
data: frame.data,
|
|
@@ -690,6 +744,96 @@ shaka.transmuxer.TsTransmuxer = class {
|
|
|
690
744
|
stream: stream,
|
|
691
745
|
};
|
|
692
746
|
}
|
|
747
|
+
|
|
748
|
+
|
|
749
|
+
/**
|
|
750
|
+
* @param {shaka.util.TsParser} tsParser
|
|
751
|
+
* @param {shaka.extern.Stream} stream
|
|
752
|
+
* @param {number} duration
|
|
753
|
+
* @param {?shaka.media.SegmentReference} reference
|
|
754
|
+
* @return {shaka.util.Mp4Generator.StreamInfo}
|
|
755
|
+
* @private
|
|
756
|
+
*/
|
|
757
|
+
getHvcStreamInfo_(tsParser, stream, duration, reference) {
|
|
758
|
+
const H265 = shaka.transmuxer.H265;
|
|
759
|
+
const timescale = shaka.util.TsParser.Timescale;
|
|
760
|
+
|
|
761
|
+
/** @type {!Array.<shaka.util.Mp4Generator.Mp4Sample>} */
|
|
762
|
+
const samples = [];
|
|
763
|
+
|
|
764
|
+
/** @type {?number} */
|
|
765
|
+
let baseMediaDecodeTime = null;
|
|
766
|
+
|
|
767
|
+
let nalus = [];
|
|
768
|
+
const videoData = tsParser.getVideoData();
|
|
769
|
+
for (let i = 0; i < videoData.length; i++) {
|
|
770
|
+
const pes = videoData[i];
|
|
771
|
+
let nextPes;
|
|
772
|
+
if (i + 1 < videoData.length) {
|
|
773
|
+
nextPes = videoData[i + 1];
|
|
774
|
+
}
|
|
775
|
+
const dataNalus = tsParser.parseNalus(pes, nextPes);
|
|
776
|
+
nalus = nalus.concat(dataNalus);
|
|
777
|
+
const frame = H265.parseFrame(dataNalus);
|
|
778
|
+
if (!frame) {
|
|
779
|
+
continue;
|
|
780
|
+
}
|
|
781
|
+
if (baseMediaDecodeTime == null && pes.dts != null) {
|
|
782
|
+
baseMediaDecodeTime = pes.dts;
|
|
783
|
+
}
|
|
784
|
+
let duration;
|
|
785
|
+
if (i + 1 < videoData.length) {
|
|
786
|
+
duration = (videoData[i + 1].dts || 0) - (pes.dts || 0);
|
|
787
|
+
} else if (videoData.length > 1) {
|
|
788
|
+
duration = (pes.dts || 0) - (videoData[i - 1].dts || 0);
|
|
789
|
+
} else {
|
|
790
|
+
duration = (reference.endTime - reference.startTime) * timescale;
|
|
791
|
+
}
|
|
792
|
+
samples.push({
|
|
793
|
+
data: frame.data,
|
|
794
|
+
size: frame.data.byteLength,
|
|
795
|
+
duration: duration,
|
|
796
|
+
cts: Math.round((pes.pts || 0) - (pes.dts || 0)),
|
|
797
|
+
flags: {
|
|
798
|
+
isLeading: 0,
|
|
799
|
+
isDependedOn: 0,
|
|
800
|
+
hasRedundancy: 0,
|
|
801
|
+
degradPrio: 0,
|
|
802
|
+
dependsOn: frame.isKeyframe ? 2 : 1,
|
|
803
|
+
isNonSync: frame.isKeyframe ? 0 : 1,
|
|
804
|
+
},
|
|
805
|
+
});
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
const info = H265.parseInfo(nalus);
|
|
809
|
+
|
|
810
|
+
if (!info || baseMediaDecodeTime == null) {
|
|
811
|
+
throw new shaka.util.Error(
|
|
812
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
813
|
+
shaka.util.Error.Category.MEDIA,
|
|
814
|
+
shaka.util.Error.Code.TRANSMUXING_FAILED);
|
|
815
|
+
}
|
|
816
|
+
stream.height = info.height;
|
|
817
|
+
stream.width = info.width;
|
|
818
|
+
|
|
819
|
+
return {
|
|
820
|
+
id: stream.id,
|
|
821
|
+
type: shaka.util.ManifestParserUtils.ContentType.VIDEO,
|
|
822
|
+
codecs: 'hvc1',
|
|
823
|
+
encrypted: stream.encrypted && stream.drmInfos.length > 0,
|
|
824
|
+
timescale: timescale,
|
|
825
|
+
duration: duration,
|
|
826
|
+
videoNalus: [],
|
|
827
|
+
audioConfig: new Uint8Array([]),
|
|
828
|
+
videoConfig: info.videoConfig,
|
|
829
|
+
data: {
|
|
830
|
+
sequenceNumber: this.frameIndex_,
|
|
831
|
+
baseMediaDecodeTime: baseMediaDecodeTime,
|
|
832
|
+
samples: samples,
|
|
833
|
+
},
|
|
834
|
+
stream: stream,
|
|
835
|
+
};
|
|
836
|
+
}
|
|
693
837
|
};
|
|
694
838
|
|
|
695
839
|
/**
|
|
@@ -713,6 +857,7 @@ shaka.transmuxer.TsTransmuxer.SUPPORTED_AUDIO_CODECS_ = [
|
|
|
713
857
|
*/
|
|
714
858
|
shaka.transmuxer.TsTransmuxer.SUPPORTED_VIDEO_CODECS_ = [
|
|
715
859
|
'avc',
|
|
860
|
+
'hevc',
|
|
716
861
|
];
|
|
717
862
|
|
|
718
863
|
|
package/lib/util/error.js
CHANGED
|
@@ -728,15 +728,8 @@ shaka.util.Error.Code = {
|
|
|
728
728
|
*/
|
|
729
729
|
'NO_WEB_CRYPTO_API': 4042,
|
|
730
730
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
*/
|
|
734
|
-
'HLS_AES_128_INVALID_IV_LENGTH': 4043,
|
|
735
|
-
|
|
736
|
-
/**
|
|
737
|
-
* AES-128 encryption key length should be 16 bytes.
|
|
738
|
-
*/
|
|
739
|
-
'HLS_AES_128_INVALID_KEY_LENGTH': 4044,
|
|
731
|
+
// RETIRED: 'HLS_AES_128_INVALID_IV_LENGTH': 4043,
|
|
732
|
+
// RETIRED: 'HLS_AES_128_INVALID_KEY_LENGTH': 4044,
|
|
740
733
|
|
|
741
734
|
/**
|
|
742
735
|
* External thumbnails tracks cannot be added to live streams.
|
|
@@ -754,6 +747,26 @@ shaka.util.Error.Code = {
|
|
|
754
747
|
*/
|
|
755
748
|
'MSS_LIVE_CONTENT_NOT_SUPPORTED': 4047,
|
|
756
749
|
|
|
750
|
+
/**
|
|
751
|
+
* AES-128 iv length should be 16 bytes.
|
|
752
|
+
*/
|
|
753
|
+
'AES_128_INVALID_IV_LENGTH': 4048,
|
|
754
|
+
|
|
755
|
+
/**
|
|
756
|
+
* AES-128 encryption key length should be 16 bytes.
|
|
757
|
+
*/
|
|
758
|
+
'AES_128_INVALID_KEY_LENGTH': 4049,
|
|
759
|
+
|
|
760
|
+
/**
|
|
761
|
+
* The DASH Manifest specifies conflicting AES-128 keys.
|
|
762
|
+
*/
|
|
763
|
+
'DASH_CONFLICTING_AES_128': 4050,
|
|
764
|
+
|
|
765
|
+
/**
|
|
766
|
+
* The DASH Manifest specifies a unsupported AES-128 encryption.
|
|
767
|
+
*/
|
|
768
|
+
'DASH_UNSUPPORTED_AES_128': 4051,
|
|
769
|
+
|
|
757
770
|
|
|
758
771
|
// RETIRED: 'INCONSISTENT_BUFFER_STATE': 5000,
|
|
759
772
|
// RETIRED: 'INVALID_SEGMENT_INDEX': 5001,
|
|
@@ -1107,4 +1120,10 @@ shaka.util.Error.Code = {
|
|
|
1107
1120
|
* for the previous request to complete before initiating a new one.
|
|
1108
1121
|
*/
|
|
1109
1122
|
'CURRENT_DAI_REQUEST_NOT_FINISHED': 10004,
|
|
1123
|
+
|
|
1124
|
+
/**
|
|
1125
|
+
* MediaTailor Ad Manager needs to be initialized to enable MediaTailor
|
|
1126
|
+
* Ad Insertion. Call adManager.initMediaTailor() to do it.
|
|
1127
|
+
*/
|
|
1128
|
+
'MT_AD_MANAGER_NOT_INITIALIZED': 10005,
|
|
1110
1129
|
};
|
package/lib/util/exp_golomb.js
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
goog.provide('shaka.util.ExpGolomb');
|
|
19
19
|
|
|
20
|
+
goog.require('shaka.util.BufferUtils');
|
|
20
21
|
goog.require('shaka.util.DataViewReader');
|
|
21
22
|
|
|
22
23
|
|
|
@@ -31,13 +32,17 @@ goog.require('shaka.util.DataViewReader');
|
|
|
31
32
|
shaka.util.ExpGolomb = class {
|
|
32
33
|
/**
|
|
33
34
|
* @param {!Uint8Array} data
|
|
35
|
+
* @param {boolean=} convertEbsp2rbsp
|
|
34
36
|
*/
|
|
35
|
-
constructor(data) {
|
|
37
|
+
constructor(data, convertEbsp2rbsp = false) {
|
|
36
38
|
/** @private {!Uint8Array} */
|
|
37
39
|
this.data_ = data;
|
|
40
|
+
if (convertEbsp2rbsp) {
|
|
41
|
+
this.data_ = this.ebsp2rbsp_(data);
|
|
42
|
+
}
|
|
38
43
|
|
|
39
44
|
/** @private {number} */
|
|
40
|
-
this.workingBytesAvailable_ =
|
|
45
|
+
this.workingBytesAvailable_ = this.data_.byteLength;
|
|
41
46
|
|
|
42
47
|
// the current word being examined
|
|
43
48
|
/** @private {number} */
|
|
@@ -48,6 +53,29 @@ shaka.util.ExpGolomb = class {
|
|
|
48
53
|
this.workingBitsAvailable_ = 0;
|
|
49
54
|
}
|
|
50
55
|
|
|
56
|
+
/**
|
|
57
|
+
* @param {!Uint8Array} data
|
|
58
|
+
* @return {!Uint8Array}
|
|
59
|
+
* @private
|
|
60
|
+
*/
|
|
61
|
+
ebsp2rbsp_(data) {
|
|
62
|
+
const ret = new Uint8Array(data.byteLength);
|
|
63
|
+
let retIndex = 0;
|
|
64
|
+
|
|
65
|
+
for (let i = 0; i < data.byteLength; i++) {
|
|
66
|
+
if (i >= 2) {
|
|
67
|
+
// Unescape: Skip 0x03 after 00 00
|
|
68
|
+
if (data[i] == 0x03 && data[i - 1] == 0x00 && data[i - 2] == 0x00) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
ret[retIndex] = data[i];
|
|
73
|
+
retIndex++;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return shaka.util.BufferUtils.toUint8(ret, 0, retIndex);
|
|
77
|
+
}
|
|
78
|
+
|
|
51
79
|
/**
|
|
52
80
|
* Load the next word
|
|
53
81
|
*
|
package/lib/util/fake_event.js
CHANGED
|
@@ -164,9 +164,11 @@ shaka.util.FakeEvent.EventName = {
|
|
|
164
164
|
Error: 'error',
|
|
165
165
|
ExpirationUpdated: 'expirationupdated',
|
|
166
166
|
GapJumped: 'gapjumped',
|
|
167
|
+
KeyStatusChanged: 'keystatuschanged',
|
|
167
168
|
Loaded: 'loaded',
|
|
168
169
|
Loading: 'loading',
|
|
169
170
|
ManifestParsed: 'manifestparsed',
|
|
171
|
+
ManifestUpdated: 'manifestupdated',
|
|
170
172
|
MediaQualityChanged: 'mediaqualitychanged',
|
|
171
173
|
Metadata: 'metadata',
|
|
172
174
|
OnStateChange: 'onstatechange',
|
|
@@ -175,6 +177,7 @@ shaka.util.FakeEvent.EventName = {
|
|
|
175
177
|
SegmentAppended: 'segmentappended',
|
|
176
178
|
SessionDataEvent: 'sessiondata',
|
|
177
179
|
StallDetected: 'stalldetected',
|
|
180
|
+
StateChanged: 'statechanged',
|
|
178
181
|
Streaming: 'streaming',
|
|
179
182
|
TextChanged: 'textchanged',
|
|
180
183
|
TextTrackVisibility: 'texttrackvisibility',
|
|
@@ -624,7 +624,6 @@ shaka.util.Mp4Generator = class {
|
|
|
624
624
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
625
625
|
|
|
626
626
|
const id = streamInfo.id + 1;
|
|
627
|
-
const bandwidth = streamInfo.stream.bandwidth || 0;
|
|
628
627
|
const channelsCount = streamInfo.stream.channelsCount || 2;
|
|
629
628
|
const audioSamplingRate = streamInfo.stream.audioSamplingRate || 44100;
|
|
630
629
|
|
|
@@ -670,9 +669,10 @@ shaka.util.Mp4Generator = class {
|
|
|
670
669
|
0x11, // length
|
|
671
670
|
0x40, // object type
|
|
672
671
|
0x15, // streamType
|
|
673
|
-
0x00,
|
|
674
|
-
|
|
675
|
-
|
|
672
|
+
0x00, 0x00, 0x00, // bufferSizeDB
|
|
673
|
+
0x00, 0x00, 0x00, 0x00, // maxBitrate
|
|
674
|
+
0x00, 0x00, 0x00, 0x00, // avgBitrate
|
|
675
|
+
|
|
676
676
|
// DecoderSpecificInfo
|
|
677
677
|
0x05, // tag, DecoderSpecificInfoTag
|
|
678
678
|
0x02, // length
|
package/lib/util/periods.js
CHANGED
|
@@ -1495,6 +1495,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
1495
1495
|
return {
|
|
1496
1496
|
id: 0,
|
|
1497
1497
|
originalId: '',
|
|
1498
|
+
groupId: null,
|
|
1498
1499
|
primary: false,
|
|
1499
1500
|
type,
|
|
1500
1501
|
mimeType: '',
|
|
@@ -1532,6 +1533,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
1532
1533
|
return {
|
|
1533
1534
|
id: 0,
|
|
1534
1535
|
originalId: '',
|
|
1536
|
+
groupId: null,
|
|
1535
1537
|
createSegmentIndex: () => Promise.resolve(),
|
|
1536
1538
|
segmentIndex: new shaka.media.SegmentIndex([]),
|
|
1537
1539
|
mimeType: '',
|
package/lib/util/platform.js
CHANGED
|
@@ -154,6 +154,26 @@ shaka.util.Platform = class {
|
|
|
154
154
|
'Chrome/38.0.2125.122 Safari/537.36');
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
/**
|
|
158
|
+
* Check if the current platform is a WebOS 4.
|
|
159
|
+
*
|
|
160
|
+
* @return {boolean}
|
|
161
|
+
*/
|
|
162
|
+
static isWebOS4() {
|
|
163
|
+
// See: http://webostv.developer.lge.com/discover/specifications/web-engine/
|
|
164
|
+
return !!navigator.userAgent.match(/webOS\/4/i);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Check if the current platform is a WebOS 4.
|
|
169
|
+
*
|
|
170
|
+
* @return {boolean}
|
|
171
|
+
*/
|
|
172
|
+
static isWebOS5() {
|
|
173
|
+
// See: http://webostv.developer.lge.com/discover/specifications/web-engine/
|
|
174
|
+
return !!navigator.userAgent.match(/webOS\/5/i);
|
|
175
|
+
}
|
|
176
|
+
|
|
157
177
|
/**
|
|
158
178
|
* Check if the current platform is a Google Chromecast.
|
|
159
179
|
*
|
|
@@ -460,6 +480,26 @@ shaka.util.Platform = class {
|
|
|
460
480
|
return true;
|
|
461
481
|
}
|
|
462
482
|
|
|
483
|
+
/**
|
|
484
|
+
* Returns if codec switching SMOOTH is known reliable device support.
|
|
485
|
+
*
|
|
486
|
+
* Some devices are known not to support `MediaSource.changeType`
|
|
487
|
+
* well. These devices should use the reload strategy. If a device
|
|
488
|
+
* reports that it supports `changeType` but support it reliabley
|
|
489
|
+
* it should be added to this list.
|
|
490
|
+
*
|
|
491
|
+
* @return {boolean}
|
|
492
|
+
*/
|
|
493
|
+
static supportsSmoothCodecSwitching() {
|
|
494
|
+
const Platform = shaka.util.Platform;
|
|
495
|
+
if (Platform.isTizen2() || Platform.isTizen3() ||
|
|
496
|
+
Platform.isTizen4() || Platform.isWebOS3() ||
|
|
497
|
+
Platform.isWebOS4() || Platform.isWebOS5()) {
|
|
498
|
+
return false;
|
|
499
|
+
}
|
|
500
|
+
return true;
|
|
501
|
+
}
|
|
502
|
+
|
|
463
503
|
/**
|
|
464
504
|
* Returns true if MediaKeys is polyfilled
|
|
465
505
|
*
|
|
@@ -9,6 +9,7 @@ goog.provide('shaka.util.PlayerConfiguration');
|
|
|
9
9
|
goog.require('goog.asserts');
|
|
10
10
|
goog.require('shaka.abr.SimpleAbrManager');
|
|
11
11
|
goog.require('shaka.config.AutoShowText');
|
|
12
|
+
goog.require('shaka.config.CodecSwitchingStrategy');
|
|
12
13
|
goog.require('shaka.log');
|
|
13
14
|
goog.require('shaka.net.NetworkingEngine');
|
|
14
15
|
goog.require('shaka.util.ConfigUtils');
|
|
@@ -133,6 +134,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
133
134
|
element);
|
|
134
135
|
},
|
|
135
136
|
sequenceMode: false,
|
|
137
|
+
enableAudioGroups: false,
|
|
136
138
|
},
|
|
137
139
|
hls: {
|
|
138
140
|
ignoreTextStreamFailures: false,
|
|
@@ -307,7 +309,13 @@ shaka.util.PlayerConfiguration = class {
|
|
|
307
309
|
drawLogo: false,
|
|
308
310
|
};
|
|
309
311
|
|
|
312
|
+
let codecSwitchingStrategy = shaka.config.CodecSwitchingStrategy.RELOAD;
|
|
313
|
+
if (shaka.util.Platform.supportsSmoothCodecSwitching()) {
|
|
314
|
+
codecSwitchingStrategy = shaka.config.CodecSwitchingStrategy.SMOOTH;
|
|
315
|
+
}
|
|
316
|
+
|
|
310
317
|
const mediaSource = {
|
|
318
|
+
codecSwitchingStrategy: codecSwitchingStrategy,
|
|
311
319
|
sourceBufferExtraFeatures: '',
|
|
312
320
|
forceTransmux: false,
|
|
313
321
|
insertFakeEncryptionInInit: true,
|
|
@@ -40,13 +40,15 @@ shaka.util.StateHistory = class {
|
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* @param {string} state
|
|
43
|
+
* @return {boolean} True if this changed the state
|
|
43
44
|
*/
|
|
44
45
|
update(state) {
|
|
45
46
|
// |open_| will only be |null| when we first call |update|.
|
|
46
47
|
if (this.open_ == null) {
|
|
47
48
|
this.start_(state);
|
|
49
|
+
return true;
|
|
48
50
|
} else {
|
|
49
|
-
this.update_(state);
|
|
51
|
+
return this.update_(state);
|
|
50
52
|
}
|
|
51
53
|
}
|
|
52
54
|
|
|
@@ -116,6 +118,7 @@ shaka.util.StateHistory = class {
|
|
|
116
118
|
|
|
117
119
|
/**
|
|
118
120
|
* @param {string} state
|
|
121
|
+
* @return {boolean} True if this changed the state
|
|
119
122
|
* @private
|
|
120
123
|
*/
|
|
121
124
|
update_(state) {
|
|
@@ -131,7 +134,7 @@ shaka.util.StateHistory = class {
|
|
|
131
134
|
|
|
132
135
|
// If the state has not changed, there is no need to add a new entry.
|
|
133
136
|
if (this.open_.state == state) {
|
|
134
|
-
return;
|
|
137
|
+
return false;
|
|
135
138
|
}
|
|
136
139
|
|
|
137
140
|
// We have changed states, so "close" the open state.
|
|
@@ -142,6 +145,7 @@ shaka.util.StateHistory = class {
|
|
|
142
145
|
state: state,
|
|
143
146
|
duration: 0,
|
|
144
147
|
};
|
|
148
|
+
return true;
|
|
145
149
|
}
|
|
146
150
|
|
|
147
151
|
/**
|