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
package/lib/util/ts_parser.js
CHANGED
|
@@ -427,10 +427,34 @@ shaka.util.TsParser = class {
|
|
|
427
427
|
* @export
|
|
428
428
|
*/
|
|
429
429
|
parseAvcNalus(pes, nextPes) {
|
|
430
|
+
shaka.Deprecate.deprecateFeature(5,
|
|
431
|
+
'TsParser',
|
|
432
|
+
'Please use parseNalus function instead.');
|
|
433
|
+
return this.parseNalus(pes, nextPes);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Parse AVC and HVC Nalus
|
|
438
|
+
*
|
|
439
|
+
* The code is based on hls.js
|
|
440
|
+
* Credit to https://github.com/video-dev/hls.js/blob/master/src/demux/tsdemuxer.ts
|
|
441
|
+
*
|
|
442
|
+
* @param {shaka.extern.MPEG_PES} pes
|
|
443
|
+
* @param {?shaka.extern.MPEG_PES=} nextPes
|
|
444
|
+
* @param {?shaka.extern.VideoNalu=} lastNalu
|
|
445
|
+
* @return {!Array.<shaka.extern.VideoNalu>}
|
|
446
|
+
* @export
|
|
447
|
+
*/
|
|
448
|
+
parseNalus(pes, nextPes, lastNalu) {
|
|
430
449
|
const timescale = shaka.util.TsParser.Timescale;
|
|
431
450
|
const time = pes.pts ? pes.pts / timescale : null;
|
|
432
|
-
|
|
433
|
-
|
|
451
|
+
const data = pes.data;
|
|
452
|
+
const len = data.byteLength;
|
|
453
|
+
|
|
454
|
+
let naluHeaderSize = 1;
|
|
455
|
+
if (this.videoCodec_ == 'hvc') {
|
|
456
|
+
naluHeaderSize = 2;
|
|
457
|
+
}
|
|
434
458
|
|
|
435
459
|
// A NALU does not contain is its size.
|
|
436
460
|
// The Annex B specification solves this by requiring ‘Start Codes’ to
|
|
@@ -448,8 +472,6 @@ shaka.util.TsParser = class {
|
|
|
448
472
|
// Extracted from the first byte.
|
|
449
473
|
let lastNaluType = 0;
|
|
450
474
|
|
|
451
|
-
let tryToFinishLastNalu = false;
|
|
452
|
-
|
|
453
475
|
/** @type {?shaka.extern.VideoNalu} */
|
|
454
476
|
let infoOfLastNalu;
|
|
455
477
|
|
|
@@ -457,25 +479,25 @@ shaka.util.TsParser = class {
|
|
|
457
479
|
const value = data[i];
|
|
458
480
|
if (!value) {
|
|
459
481
|
numZeros++;
|
|
460
|
-
} else if (numZeros >= 2 && value == 1 &&
|
|
482
|
+
} else if (numZeros >= 2 && value == 1 && lastNalu) {
|
|
461
483
|
// If we are scanning the next PES, we need append the data to the
|
|
462
484
|
// previous Nalu and don't scan for more nalus.
|
|
463
485
|
const startCodeSize = numZeros > 3 ? 3 : numZeros;
|
|
464
486
|
const lastByteToKeep = i - startCodeSize;
|
|
465
487
|
// Optimization
|
|
466
488
|
if (lastByteToKeep == 0) {
|
|
467
|
-
|
|
489
|
+
return [];
|
|
468
490
|
}
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
491
|
+
lastNalu.data = shaka.util.Uint8ArrayUtils.concat(
|
|
492
|
+
lastNalu.data, data.subarray(0, lastByteToKeep));
|
|
493
|
+
lastNalu.fullData = shaka.util.Uint8ArrayUtils.concat(
|
|
494
|
+
lastNalu.fullData, data.subarray(0, lastByteToKeep));
|
|
495
|
+
return [];
|
|
474
496
|
} else if (numZeros >= 2 && value == 1) {
|
|
475
497
|
// We just read a start code. Consume the NALU we passed, if any.
|
|
476
498
|
if (lastNaluStart >= 0) {
|
|
477
|
-
// Because the start position includes the
|
|
478
|
-
const firstByteToKeep = lastNaluStart +
|
|
499
|
+
// Because the start position includes the header size.
|
|
500
|
+
const firstByteToKeep = lastNaluStart + naluHeaderSize;
|
|
479
501
|
|
|
480
502
|
// Compute the last byte to keep. The start code is at most 3 zeros.
|
|
481
503
|
// Any earlier zeros are not part of the start code.
|
|
@@ -491,11 +513,17 @@ shaka.util.TsParser = class {
|
|
|
491
513
|
time: time,
|
|
492
514
|
};
|
|
493
515
|
nalus.push(nalu);
|
|
516
|
+
} else if (lastNalu) {
|
|
517
|
+
const overflow = i - numZeros;
|
|
518
|
+
if (overflow > 0) {
|
|
519
|
+
lastNalu.data = shaka.util.Uint8ArrayUtils.concat(
|
|
520
|
+
lastNalu.data, data.subarray(0, overflow));
|
|
521
|
+
}
|
|
494
522
|
}
|
|
495
523
|
|
|
496
524
|
// We just read a start code, so there should be another byte here, at
|
|
497
525
|
// least, for the NALU type. Check just in case.
|
|
498
|
-
if (i >= len -
|
|
526
|
+
if (i >= len - naluHeaderSize) {
|
|
499
527
|
shaka.log.warning('Malformed TS, incomplete NALU, ignoring.');
|
|
500
528
|
return nalus;
|
|
501
529
|
}
|
|
@@ -503,7 +531,11 @@ shaka.util.TsParser = class {
|
|
|
503
531
|
// Advance and read the type of the next NALU.
|
|
504
532
|
i++;
|
|
505
533
|
lastNaluStart = i;
|
|
506
|
-
|
|
534
|
+
if (this.videoCodec_ == 'hvc') {
|
|
535
|
+
lastNaluType = (data[i] >> 1) & 0x3f;
|
|
536
|
+
} else {
|
|
537
|
+
lastNaluType = data[i] & 0x1f;
|
|
538
|
+
}
|
|
507
539
|
numZeros = 0;
|
|
508
540
|
} else {
|
|
509
541
|
numZeros = 0;
|
|
@@ -512,27 +544,17 @@ shaka.util.TsParser = class {
|
|
|
512
544
|
// unfinished Nalu, we will try to use the next PES to complete the
|
|
513
545
|
// unfinished Nalu.
|
|
514
546
|
if (i >= (len - 1) && lastNaluStart >= 0 && numZeros >= 0) {
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
data: data.subarray(firstByteToKeep, len),
|
|
527
|
-
fullData: data.subarray(lastNaluStart, len),
|
|
528
|
-
type: lastNaluType,
|
|
529
|
-
time: time,
|
|
530
|
-
};
|
|
531
|
-
if (nextPes && pes.packetLength == 0) {
|
|
532
|
-
data = nextPes.data;
|
|
533
|
-
len = data.byteLength;
|
|
534
|
-
i = -1;
|
|
535
|
-
}
|
|
547
|
+
// The rest of the buffer was a NALU.
|
|
548
|
+
// Because the start position includes the header size.
|
|
549
|
+
const firstByteToKeep = lastNaluStart + naluHeaderSize;
|
|
550
|
+
infoOfLastNalu = {
|
|
551
|
+
data: data.subarray(firstByteToKeep, len),
|
|
552
|
+
fullData: data.subarray(lastNaluStart, len),
|
|
553
|
+
type: lastNaluType,
|
|
554
|
+
time: time,
|
|
555
|
+
};
|
|
556
|
+
if (nextPes) {
|
|
557
|
+
this.parseNalus(nextPes, /* nextPes= */ null, infoOfLastNalu);
|
|
536
558
|
}
|
|
537
559
|
}
|
|
538
560
|
}
|
|
@@ -540,6 +562,12 @@ shaka.util.TsParser = class {
|
|
|
540
562
|
if (infoOfLastNalu) {
|
|
541
563
|
nalus.push(infoOfLastNalu);
|
|
542
564
|
}
|
|
565
|
+
if (!nalus.length && lastNalu) {
|
|
566
|
+
lastNalu.data = shaka.util.Uint8ArrayUtils.concat(
|
|
567
|
+
lastNalu.data, data);
|
|
568
|
+
lastNalu.fullData = shaka.util.Uint8ArrayUtils.concat(
|
|
569
|
+
lastNalu.fullData, data);
|
|
570
|
+
}
|
|
543
571
|
return nalus;
|
|
544
572
|
}
|
|
545
573
|
|
|
@@ -664,9 +692,6 @@ shaka.util.TsParser = class {
|
|
|
664
692
|
*/
|
|
665
693
|
getVideoNalus() {
|
|
666
694
|
const nalus = [];
|
|
667
|
-
if (this.videoCodec_ != 'avc') {
|
|
668
|
-
return nalus;
|
|
669
|
-
}
|
|
670
695
|
const videoData = this.getVideoData();
|
|
671
696
|
for (let i = 0; i < videoData.length; i++) {
|
|
672
697
|
const pes = videoData[i];
|
|
@@ -674,7 +699,7 @@ shaka.util.TsParser = class {
|
|
|
674
699
|
if (i + 1 < videoData.length) {
|
|
675
700
|
nextPes = videoData[i + 1];
|
|
676
701
|
}
|
|
677
|
-
nalus.push(...this.
|
|
702
|
+
nalus.push(...this.parseNalus(pes, nextPes));
|
|
678
703
|
}
|
|
679
704
|
return nalus;
|
|
680
705
|
}
|
|
@@ -703,6 +728,19 @@ shaka.util.TsParser = class {
|
|
|
703
728
|
* @export
|
|
704
729
|
*/
|
|
705
730
|
getVideoInfo() {
|
|
731
|
+
if (this.videoCodec_ == 'hvc') {
|
|
732
|
+
return this.getHvcInfo_();
|
|
733
|
+
}
|
|
734
|
+
return this.getAvcInfo_();
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
/**
|
|
738
|
+
* Return the video information for AVC
|
|
739
|
+
*
|
|
740
|
+
* @return {{height: ?string, width: ?string, codec: ?string}}
|
|
741
|
+
* @private
|
|
742
|
+
*/
|
|
743
|
+
getAvcInfo_() {
|
|
706
744
|
const TsParser = shaka.util.TsParser;
|
|
707
745
|
const videoInfo = {
|
|
708
746
|
height: null,
|
|
@@ -823,6 +861,146 @@ shaka.util.TsParser = class {
|
|
|
823
861
|
return videoInfo;
|
|
824
862
|
}
|
|
825
863
|
|
|
864
|
+
/**
|
|
865
|
+
* Return the video information for HVC
|
|
866
|
+
*
|
|
867
|
+
* @return {{height: ?string, width: ?string, codec: ?string}}
|
|
868
|
+
* @private
|
|
869
|
+
*/
|
|
870
|
+
getHvcInfo_() {
|
|
871
|
+
const TsParser = shaka.util.TsParser;
|
|
872
|
+
const videoInfo = {
|
|
873
|
+
height: null,
|
|
874
|
+
width: null,
|
|
875
|
+
codec: null,
|
|
876
|
+
};
|
|
877
|
+
const videoNalus = this.getVideoNalus();
|
|
878
|
+
if (!videoNalus.length) {
|
|
879
|
+
return videoInfo;
|
|
880
|
+
}
|
|
881
|
+
const spsNalu = videoNalus.find((nalu) => {
|
|
882
|
+
return nalu.type == TsParser.H265_NALU_TYPE_SPS_;
|
|
883
|
+
});
|
|
884
|
+
if (!spsNalu) {
|
|
885
|
+
return videoInfo;
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
const gb = new shaka.util.ExpGolomb(
|
|
889
|
+
spsNalu.fullData, /* convertEbsp2rbsp= */ true);
|
|
890
|
+
|
|
891
|
+
// remove NALu Header
|
|
892
|
+
gb.readUnsignedByte();
|
|
893
|
+
gb.readUnsignedByte();
|
|
894
|
+
|
|
895
|
+
// SPS
|
|
896
|
+
gb.readBits(4); // video_paramter_set_id
|
|
897
|
+
const maxSubLayersMinus1 = gb.readBits(3);
|
|
898
|
+
gb.readBoolean(); // temporal_id_nesting_flag
|
|
899
|
+
|
|
900
|
+
// profile_tier_level begin
|
|
901
|
+
const generalProfileSpace = gb.readBits(2);
|
|
902
|
+
const generalTierFlag = gb.readBits(1);
|
|
903
|
+
const generalProfileIdc = gb.readBits(5);
|
|
904
|
+
const generalProfileCompatibilityFlags = gb.readBits(32);
|
|
905
|
+
const generalConstraintIndicatorFlags1 = gb.readUnsignedByte();
|
|
906
|
+
const generalConstraintIndicatorFlags2 = gb.readUnsignedByte();
|
|
907
|
+
const generalConstraintIndicatorFlags3 = gb.readUnsignedByte();
|
|
908
|
+
const generalConstraintIndicatorFlags4 = gb.readUnsignedByte();
|
|
909
|
+
const generalConstraintIndicatorFlags5 = gb.readUnsignedByte();
|
|
910
|
+
const generalConstraintIndicatorFlags6 = gb.readUnsignedByte();
|
|
911
|
+
const generalLevelIdc = gb.readUnsignedByte();
|
|
912
|
+
const subLayerProfilePresentFlag = [];
|
|
913
|
+
const subLayerLevelPresentFlag = [];
|
|
914
|
+
for (let i = 0; i < maxSubLayersMinus1; i++) {
|
|
915
|
+
subLayerProfilePresentFlag.push(gb.readBoolean());
|
|
916
|
+
subLayerLevelPresentFlag.push(gb.readBoolean());
|
|
917
|
+
}
|
|
918
|
+
if (maxSubLayersMinus1 > 0) {
|
|
919
|
+
for (let i = maxSubLayersMinus1; i < 8; i++) {
|
|
920
|
+
gb.readBits(2);
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
for (let i = 0; i < maxSubLayersMinus1; i++) {
|
|
924
|
+
if (subLayerProfilePresentFlag[i]) {
|
|
925
|
+
gb.readBits(88);
|
|
926
|
+
}
|
|
927
|
+
if (subLayerLevelPresentFlag[i]) {
|
|
928
|
+
gb.readUnsignedByte();
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
// profile_tier_level end
|
|
932
|
+
|
|
933
|
+
gb.readUnsignedExpGolomb(); // seq_parameter_set_id
|
|
934
|
+
const chromaFormatIdc = gb.readUnsignedExpGolomb();
|
|
935
|
+
if (chromaFormatIdc == 3) {
|
|
936
|
+
gb.readBits(1); // separate_colour_plane_flag
|
|
937
|
+
}
|
|
938
|
+
const picWidthInLumaSamples = gb.readUnsignedExpGolomb();
|
|
939
|
+
const picHeightInLumaSamples = gb.readUnsignedExpGolomb();
|
|
940
|
+
let leftOffset = 0;
|
|
941
|
+
let rightOffset = 0;
|
|
942
|
+
let topOffset = 0;
|
|
943
|
+
let bottomOffset = 0;
|
|
944
|
+
const conformanceWindowFlag = gb.readBoolean();
|
|
945
|
+
if (conformanceWindowFlag) {
|
|
946
|
+
leftOffset += gb.readUnsignedExpGolomb();
|
|
947
|
+
rightOffset += gb.readUnsignedExpGolomb();
|
|
948
|
+
topOffset += gb.readUnsignedExpGolomb();
|
|
949
|
+
bottomOffset += gb.readUnsignedExpGolomb();
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
const subWc = chromaFormatIdc === 1 || chromaFormatIdc === 2 ? 2 : 1;
|
|
953
|
+
const subHc = chromaFormatIdc === 1 ? 2 : 1;
|
|
954
|
+
videoInfo.width =
|
|
955
|
+
String(picWidthInLumaSamples - (leftOffset + rightOffset) * subWc);
|
|
956
|
+
videoInfo.height =
|
|
957
|
+
String(picHeightInLumaSamples - (topOffset + bottomOffset) * subHc);
|
|
958
|
+
|
|
959
|
+
const reverseBits = (integer) => {
|
|
960
|
+
let result = 0;
|
|
961
|
+
for (let i = 0; i < 32; i++) {
|
|
962
|
+
result |= ((integer >> i) & 1) << (31 - i);
|
|
963
|
+
}
|
|
964
|
+
return result >>> 0;
|
|
965
|
+
};
|
|
966
|
+
|
|
967
|
+
const profileSpace = ['', 'A', 'B', 'C'][generalProfileSpace];
|
|
968
|
+
const profileCompatibility = reverseBits(generalProfileCompatibilityFlags);
|
|
969
|
+
const tierFlag = generalTierFlag == 1 ? 'H' : 'L';
|
|
970
|
+
|
|
971
|
+
let codec = 'hvc1';
|
|
972
|
+
codec += '.' + profileSpace + generalProfileIdc;
|
|
973
|
+
codec += '.' + profileCompatibility.toString(16).toUpperCase();
|
|
974
|
+
codec += '.' + tierFlag + generalLevelIdc;
|
|
975
|
+
if (generalConstraintIndicatorFlags6) {
|
|
976
|
+
codec += '.' +
|
|
977
|
+
generalConstraintIndicatorFlags6.toString(16).toUpperCase();
|
|
978
|
+
}
|
|
979
|
+
if (generalConstraintIndicatorFlags5) {
|
|
980
|
+
codec += '.' +
|
|
981
|
+
generalConstraintIndicatorFlags5.toString(16).toUpperCase();
|
|
982
|
+
}
|
|
983
|
+
if (generalConstraintIndicatorFlags4) {
|
|
984
|
+
codec += '.' +
|
|
985
|
+
generalConstraintIndicatorFlags4.toString(16).toUpperCase();
|
|
986
|
+
}
|
|
987
|
+
if (generalConstraintIndicatorFlags3) {
|
|
988
|
+
codec += '.' +
|
|
989
|
+
generalConstraintIndicatorFlags3.toString(16).toUpperCase();
|
|
990
|
+
}
|
|
991
|
+
if (generalConstraintIndicatorFlags2) {
|
|
992
|
+
codec += '.' +
|
|
993
|
+
generalConstraintIndicatorFlags2.toString(16).toUpperCase();
|
|
994
|
+
}
|
|
995
|
+
if (generalConstraintIndicatorFlags1) {
|
|
996
|
+
codec += '.' +
|
|
997
|
+
generalConstraintIndicatorFlags1.toString(16).toUpperCase();
|
|
998
|
+
}
|
|
999
|
+
videoInfo.codec = codec;
|
|
1000
|
+
|
|
1001
|
+
return videoInfo;
|
|
1002
|
+
}
|
|
1003
|
+
|
|
826
1004
|
/**
|
|
827
1005
|
* Convert a byte to 2 digits of hex. (Only handles values 0-255.)
|
|
828
1006
|
*
|
|
@@ -904,6 +1082,14 @@ shaka.util.TsParser.PacketLength_ = 188;
|
|
|
904
1082
|
shaka.util.TsParser.H264_NALU_TYPE_SPS_ = 0x07;
|
|
905
1083
|
|
|
906
1084
|
|
|
1085
|
+
/**
|
|
1086
|
+
* NALU type for Sequence Parameter Set (SPS) for H.265.
|
|
1087
|
+
* @const {number}
|
|
1088
|
+
* @private
|
|
1089
|
+
*/
|
|
1090
|
+
shaka.util.TsParser.H265_NALU_TYPE_SPS_ = 0x21;
|
|
1091
|
+
|
|
1092
|
+
|
|
907
1093
|
/**
|
|
908
1094
|
* Values of profile_idc that indicate additional fields are included in the
|
|
909
1095
|
* SPS.
|
package/maintained-branches.md
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
We are currently maintaining the following branches of Shaka Player:
|
|
4
4
|
|
|
5
|
-
- v4.
|
|
6
|
-
- v4.
|
|
5
|
+
- v4.5 (latest)
|
|
6
|
+
- v4.4 (previous)
|
|
7
|
+
- v4.3 (in use by the Cast Application Framework)
|
|
7
8
|
- No active LTS branches at this time
|
|
8
9
|
|
|
9
10
|
Other branches are no longer receiving bug fixes, and we recommend you upgrade
|
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.
|
|
4
|
+
"version": "4.5.0",
|
|
5
5
|
"homepage": "https://github.com/shaka-project/shaka-player",
|
|
6
6
|
"author": "Google",
|
|
7
7
|
"maintainers": [
|
|
@@ -48,11 +48,10 @@
|
|
|
48
48
|
"karma-sourcemap-loader": "^0.3.8",
|
|
49
49
|
"karma-spec-reporter": "^0.0.34",
|
|
50
50
|
"karma-webdriver-launcher": "^1.0.8",
|
|
51
|
-
"
|
|
51
|
+
"lcevc_dec.js": "^1.0.0",
|
|
52
52
|
"less": "https://gitpkg.now.sh/joeyparrish/less.js/packages/less?28c63a43",
|
|
53
53
|
"less-plugin-clean-css": "github:austingardner/less-plugin-clean-css#4e9e77bf",
|
|
54
54
|
"material-design-lite": "^1.3.0",
|
|
55
|
-
"mux.js": "^6.2.0",
|
|
56
55
|
"open-sans-fonts": "^1.6.2",
|
|
57
56
|
"postcss-less": "^6.0.0",
|
|
58
57
|
"pwacompat": "^2.0.17",
|
|
@@ -75,12 +74,11 @@
|
|
|
75
74
|
"eme-encryption-scheme-polyfill/index.js",
|
|
76
75
|
"es6-promise-polyfill/promise.min.js",
|
|
77
76
|
"google-closure-library/closure/goog/base.js",
|
|
78
|
-
"
|
|
79
|
-
"
|
|
77
|
+
"lcevc_dec.js/dist/lcevc_dec.min.js",
|
|
78
|
+
"lcevc_dec.js/dist/liblcevc_dpi.wasm",
|
|
80
79
|
"less/dist/less.js",
|
|
81
80
|
"material-design-lite/dist/material.indigo-blue.min.css",
|
|
82
81
|
"material-design-lite/dist/material.min.js",
|
|
83
|
-
"mux.js/dist/mux.min.js",
|
|
84
82
|
"popper.js/dist/umd/popper.min.js",
|
|
85
83
|
"pwacompat/pwacompat.min.js",
|
|
86
84
|
"tippy.js/umd/index.min.js",
|
package/roadmap.md
CHANGED
|
@@ -9,22 +9,32 @@ The goals of future milestones are fluid until we begin that development cycle,
|
|
|
9
9
|
so the exact milestone for future features is not pre-determined.
|
|
10
10
|
|
|
11
11
|
Candidate features for future release cycles:
|
|
12
|
-
- Preload API
|
|
13
|
-
https://github.com/shaka-project/shaka-player/issues/880
|
|
14
12
|
- Official TypeScript defs, generated from source
|
|
15
13
|
https://github.com/shaka-project/shaka-player/issues/1030
|
|
16
14
|
- Background fetch for offline storage
|
|
17
15
|
https://github.com/shaka-project/shaka-player/issues/879
|
|
18
16
|
- Smaller, more modular binary
|
|
19
17
|
|
|
20
|
-
v4.
|
|
18
|
+
v4.6 - 2024 Q1
|
|
19
|
+
- Content Steering
|
|
20
|
+
https://github.com/shaka-project/shaka-player/issues/5704
|
|
21
|
+
- Preload API
|
|
22
|
+
https://github.com/shaka-project/shaka-player/issues/880
|
|
23
|
+
- New DASH protocol for Low Latency.
|
|
24
|
+
- ManagedMediaSource
|
|
25
|
+
https://github.com/shaka-project/shaka-player/issues/5271
|
|
26
|
+
|
|
27
|
+
=====
|
|
28
|
+
|
|
29
|
+
v4.5 - 2023 Q4
|
|
21
30
|
- Built-in transmuxer support for muxed content streams (audio+video)
|
|
22
31
|
- Built-in transmuxer support for H265 streams
|
|
23
32
|
- Remove optional mux.js dependency
|
|
24
33
|
- Codec switching
|
|
25
34
|
https://github.com/shaka-project/shaka-player/issues/1528
|
|
26
|
-
|
|
27
|
-
|
|
35
|
+
- AES-128 in DASH.
|
|
36
|
+
https://github.com/shaka-project/shaka-player/issues/5622
|
|
37
|
+
- AWS Elemental MediaTailor
|
|
28
38
|
|
|
29
39
|
v4.4 - 2023 Q3
|
|
30
40
|
- Built-in transmuxer for common cases, no mux.js required:
|
|
@@ -72,12 +72,12 @@ goog.require('shaka.transmuxer.ADTS');
|
|
|
72
72
|
goog.require('shaka.transmuxer.Ec3');
|
|
73
73
|
goog.require('shaka.transmuxer.Ec3Transmuxer');
|
|
74
74
|
goog.require('shaka.transmuxer.H264');
|
|
75
|
+
goog.require('shaka.transmuxer.H265');
|
|
75
76
|
goog.require('shaka.transmuxer.Mp3Transmuxer');
|
|
76
77
|
goog.require('shaka.transmuxer.MpegAudio');
|
|
77
78
|
goog.require('shaka.transmuxer.MpegTsTransmuxer');
|
|
78
79
|
goog.require('shaka.transmuxer.TransmuxerEngine');
|
|
79
80
|
goog.require('shaka.transmuxer.MssTransmuxer');
|
|
80
|
-
goog.require('shaka.transmuxer.MuxjsTransmuxer');
|
|
81
81
|
goog.require('shaka.transmuxer.TsTransmuxer');
|
|
82
82
|
goog.require('shaka.ui.Controls');
|
|
83
83
|
goog.require('shaka.ui.PlayButton');
|
|
@@ -100,6 +100,7 @@ goog.require('shaka.ui.Overlay');
|
|
|
100
100
|
goog.require('shaka.ui.PipButton');
|
|
101
101
|
goog.require('shaka.ui.PlaybackRateSelection');
|
|
102
102
|
goog.require('shaka.ui.PresentationTimeTracker');
|
|
103
|
+
goog.require('shaka.ui.RemoteButton');
|
|
103
104
|
goog.require('shaka.ui.ResolutionSelection');
|
|
104
105
|
goog.require('shaka.ui.RewindButton');
|
|
105
106
|
goog.require('shaka.ui.SkipAdButton');
|
package/support.html
CHANGED
|
@@ -139,6 +139,53 @@ filterDescribe('CastReceiver', castReceiverIntegrationSupport, () => {
|
|
|
139
139
|
}
|
|
140
140
|
});
|
|
141
141
|
|
|
142
|
+
describe('state changed event', () => {
|
|
143
|
+
it('does not trigger a stack overflow', async () => {
|
|
144
|
+
const p = waitForLoadedData();
|
|
145
|
+
|
|
146
|
+
// We had a regression in which polling attributes eventually triggered a
|
|
147
|
+
// stack overflow because of a state change event that fired every time
|
|
148
|
+
// we checked the state. The error itself got swallowed and hidden
|
|
149
|
+
// inside CastReceiver, but would cause tests to disconnect in some
|
|
150
|
+
// environments (consistently in GitHub Actions VMs, inconsistently
|
|
151
|
+
// elsewhere).
|
|
152
|
+
//
|
|
153
|
+
// Testing for this is subtle: if we try to catch the error, it will be
|
|
154
|
+
// caught at a point when the stack has already or is about to overflow.
|
|
155
|
+
// Then if we call "fail", Jasmine will grow the stack further,
|
|
156
|
+
// triggering *another* overflow inside of fail(), causing our test to
|
|
157
|
+
// *pass*. So we need to fail fast. The best way I have found is to
|
|
158
|
+
// catch the very first recursion of pollAttributes_, long before we
|
|
159
|
+
// overflow, fail, then return early to avoid the actual recursion.
|
|
160
|
+
const original = /** @type {?} */(receiver).pollAttributes_;
|
|
161
|
+
let numRecursions = 0;
|
|
162
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
163
|
+
/** @type {?} */(receiver).pollAttributes_ = function() {
|
|
164
|
+
try {
|
|
165
|
+
if (numRecursions > 0) {
|
|
166
|
+
fail('Found recursion in pollAttributes_!');
|
|
167
|
+
return undefined;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
numRecursions++;
|
|
171
|
+
return original.apply(receiver, arguments);
|
|
172
|
+
} finally {
|
|
173
|
+
numRecursions--;
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// Start the process of loading by sending a fake init message.
|
|
178
|
+
fakeConnectedSenders(1);
|
|
179
|
+
fakeIncomingMessage({
|
|
180
|
+
type: 'init',
|
|
181
|
+
initState: fakeInitState,
|
|
182
|
+
appData: {},
|
|
183
|
+
}, mockShakaMessageBus);
|
|
184
|
+
|
|
185
|
+
await p;
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
142
189
|
describe('without drm', () => {
|
|
143
190
|
it('sends reasonably-sized updates', async () => {
|
|
144
191
|
// Use an unencrypted asset.
|