shaka-player 3.3.0 → 3.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +54 -0
- package/build/conformance.textproto +183 -169
- package/dist/controls.css +1 -1
- package/dist/deps.js +1 -1
- package/dist/locales.js +30 -30
- package/dist/shaka-player.compiled.d.ts +25 -2
- package/dist/shaka-player.compiled.debug.d.ts +25 -2
- package/dist/shaka-player.compiled.debug.externs.js +22 -1
- package/dist/shaka-player.compiled.debug.js +226 -222
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.externs.js +22 -1
- package/dist/shaka-player.compiled.js +814 -812
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +25 -2
- package/dist/shaka-player.ui.debug.d.ts +25 -2
- package/dist/shaka-player.ui.debug.externs.js +22 -1
- package/dist/shaka-player.ui.debug.js +244 -240
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.externs.js +22 -1
- package/dist/shaka-player.ui.js +995 -992
- package/dist/shaka-player.ui.map +4 -4
- package/externs/cmcd.js +186 -0
- package/externs/shaka/player.js +8 -0
- package/externs/shaka/text.js +10 -0
- package/lib/hls/hls_parser.js +30 -0
- package/lib/media/segment_index.js +2 -1
- package/lib/media/segment_reference.js +19 -1
- package/lib/media/streaming_engine.js +5 -2
- package/lib/player.js +23 -17
- package/lib/polyfill/media_capabilities.js +30 -15
- package/lib/text/cue.js +6 -0
- package/lib/text/ttml_text_parser.js +84 -58
- package/lib/text/ui_text_displayer.js +17 -11
- package/lib/util/cmcd_manager.js +47 -201
- package/lib/util/stream_utils.js +86 -10
- package/lib/util/xml_utils.js +19 -0
- package/package.json +2 -2
- package/test/media/drm_engine_unit.js +3 -3
- package/test/media/streaming_engine_integration.js +2 -1
- package/test/media/streaming_engine_unit.js +145 -0
- package/test/player_integration.js +41 -8
- package/test/player_src_equals_integration.js +41 -8
- package/test/player_unit.js +19 -9
- package/test/test/assets/chapters.vtt +2 -2
- package/test/test/assets/chapters2.vtt +10 -0
- package/test/test/util/ttml_utils.js +81 -0
- package/test/text/mp4_ttml_parser_unit.js +11 -18
- package/test/text/ttml_text_parser_unit.js +499 -230
- package/test/util/cmcd_manager_unit.js +29 -15
- package/test/util/stream_utils_unit.js +36 -30
- package/third_party/closure-uri/uri.js +21 -0
- package/ui/text_selection.js +1 -0
- package/externs/media_capabilities.js +0 -16
package/lib/util/cmcd_manager.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
goog.provide('shaka.util.CmcdManager');
|
|
8
8
|
|
|
9
|
+
goog.require('goog.Uri');
|
|
9
10
|
goog.require('shaka.log');
|
|
10
11
|
|
|
11
12
|
|
|
@@ -31,7 +32,7 @@ shaka.util.CmcdManager = class {
|
|
|
31
32
|
*
|
|
32
33
|
* @private {string}
|
|
33
34
|
*/
|
|
34
|
-
this.sid_ =
|
|
35
|
+
this.sid_ = '';
|
|
35
36
|
|
|
36
37
|
/**
|
|
37
38
|
* Streaming format
|
|
@@ -118,10 +119,11 @@ shaka.util.CmcdManager = class {
|
|
|
118
119
|
|
|
119
120
|
data.ot = this.getObjectType_(segmentInfo);
|
|
120
121
|
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
data.ot ===
|
|
124
|
-
data.ot ===
|
|
122
|
+
const ObjectType = shaka.util.CmcdManager.ObjectType;
|
|
123
|
+
const isMedia = data.ot === ObjectType.VIDEO ||
|
|
124
|
+
data.ot === ObjectType.AUDIO ||
|
|
125
|
+
data.ot === ObjectType.MUXED ||
|
|
126
|
+
data.ot === ObjectType.TIMED_TEXT;
|
|
125
127
|
|
|
126
128
|
if (isMedia) {
|
|
127
129
|
data.bl = this.getBufferLength_(segmentInfo.type);
|
|
@@ -131,7 +133,9 @@ shaka.util.CmcdManager = class {
|
|
|
131
133
|
data.br = segmentInfo.bandwidth / 1000;
|
|
132
134
|
}
|
|
133
135
|
|
|
134
|
-
data.
|
|
136
|
+
if (isMedia && data.ot !== ObjectType.TIMED_TEXT) {
|
|
137
|
+
data.tb = this.getTopBandwidth_(data.ot) / 1000;
|
|
138
|
+
}
|
|
135
139
|
|
|
136
140
|
this.apply_(request, data);
|
|
137
141
|
} catch (error) {
|
|
@@ -147,6 +151,10 @@ shaka.util.CmcdManager = class {
|
|
|
147
151
|
*/
|
|
148
152
|
applyTextData(request) {
|
|
149
153
|
try {
|
|
154
|
+
if (!this.config_.enabled) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
150
158
|
this.apply_(request, {
|
|
151
159
|
ot: shaka.util.CmcdManager.ObjectType.CAPTION,
|
|
152
160
|
su: true,
|
|
@@ -213,10 +221,13 @@ shaka.util.CmcdManager = class {
|
|
|
213
221
|
/**
|
|
214
222
|
* Create baseline CMCD data
|
|
215
223
|
*
|
|
216
|
-
* @return {
|
|
224
|
+
* @return {CmcdData}
|
|
217
225
|
* @private
|
|
218
226
|
*/
|
|
219
227
|
createData_() {
|
|
228
|
+
if (!this.sid_) {
|
|
229
|
+
this.sid_ = this.config_.sessionId || window.crypto.randomUUID();
|
|
230
|
+
}
|
|
220
231
|
return {
|
|
221
232
|
v: shaka.util.CmcdManager.Version,
|
|
222
233
|
sf: this.sf_,
|
|
@@ -230,7 +241,7 @@ shaka.util.CmcdManager = class {
|
|
|
230
241
|
* Apply CMCD data to a request.
|
|
231
242
|
*
|
|
232
243
|
* @param {!shaka.extern.Request} request The request to apply CMCD data to
|
|
233
|
-
* @param {!
|
|
244
|
+
* @param {!CmcdData} data The data object
|
|
234
245
|
* @param {boolean} useHeaders Send data via request headers
|
|
235
246
|
* @private
|
|
236
247
|
*/
|
|
@@ -380,23 +391,31 @@ shaka.util.CmcdManager = class {
|
|
|
380
391
|
* @private
|
|
381
392
|
*/
|
|
382
393
|
getTopBandwidth_(type) {
|
|
383
|
-
const
|
|
384
|
-
if (!
|
|
394
|
+
const variants = this.playerInterface_.getVariantTracks();
|
|
395
|
+
if (!variants.length) {
|
|
385
396
|
return NaN;
|
|
386
397
|
}
|
|
387
398
|
|
|
388
|
-
|
|
389
|
-
manifest.textStreams : manifest.variants;
|
|
390
|
-
let top = variants[0][type] || variants[0];
|
|
399
|
+
let top = variants[0];
|
|
391
400
|
|
|
392
401
|
for (const variant of variants) {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
top = stream;
|
|
402
|
+
if (variant.type === 'variant' && variant.bandwidth > top.bandwidth) {
|
|
403
|
+
top = variant;
|
|
396
404
|
}
|
|
397
405
|
}
|
|
398
406
|
|
|
399
|
-
|
|
407
|
+
const ObjectType = shaka.util.CmcdManager.ObjectType;
|
|
408
|
+
|
|
409
|
+
switch (type) {
|
|
410
|
+
case ObjectType.VIDEO:
|
|
411
|
+
return top.videoBandwidth || NaN;
|
|
412
|
+
|
|
413
|
+
case ObjectType.AUDIO:
|
|
414
|
+
return top.audioBandwidth || NaN;
|
|
415
|
+
|
|
416
|
+
default:
|
|
417
|
+
return top.bandwidth;
|
|
418
|
+
}
|
|
400
419
|
}
|
|
401
420
|
|
|
402
421
|
/**
|
|
@@ -404,7 +423,7 @@ shaka.util.CmcdManager = class {
|
|
|
404
423
|
* section 3.2 of
|
|
405
424
|
* [CTA-5004](https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf).
|
|
406
425
|
*
|
|
407
|
-
* @param {
|
|
426
|
+
* @param {CmcdData} data The CMCD data object
|
|
408
427
|
* @return {string}
|
|
409
428
|
*/
|
|
410
429
|
static serialize(data) {
|
|
@@ -456,7 +475,7 @@ shaka.util.CmcdManager = class {
|
|
|
456
475
|
let result;
|
|
457
476
|
|
|
458
477
|
if (type === 'string' && key !== 'ot' && key !== 'sf' && key !== 'st') {
|
|
459
|
-
result = `${key}
|
|
478
|
+
result = `${key}=${JSON.stringify(value)}`;
|
|
460
479
|
} else if (type === 'boolean') {
|
|
461
480
|
result = key;
|
|
462
481
|
} else if (type === 'symbol') {
|
|
@@ -476,7 +495,7 @@ shaka.util.CmcdManager = class {
|
|
|
476
495
|
* defined in the section 2.1 and 3.2 of
|
|
477
496
|
* [CTA-5004](https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf).
|
|
478
497
|
*
|
|
479
|
-
* @param {
|
|
498
|
+
* @param {CmcdData} data The CMCD data object
|
|
480
499
|
* @return {!Object}
|
|
481
500
|
*/
|
|
482
501
|
static toHeaders(data) {
|
|
@@ -512,11 +531,11 @@ shaka.util.CmcdManager = class {
|
|
|
512
531
|
* defined in the section 2.2 and 3.2 of
|
|
513
532
|
* [CTA-5004](https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf).
|
|
514
533
|
*
|
|
515
|
-
* @param {
|
|
534
|
+
* @param {CmcdData} data The CMCD data object
|
|
516
535
|
* @return {string}
|
|
517
536
|
*/
|
|
518
537
|
static toQuery(data) {
|
|
519
|
-
return
|
|
538
|
+
return shaka.util.CmcdManager.serialize(data);
|
|
520
539
|
}
|
|
521
540
|
|
|
522
541
|
/**
|
|
@@ -535,8 +554,9 @@ shaka.util.CmcdManager = class {
|
|
|
535
554
|
return uri;
|
|
536
555
|
}
|
|
537
556
|
|
|
538
|
-
const
|
|
539
|
-
|
|
557
|
+
const url = new goog.Uri(uri);
|
|
558
|
+
url.getQueryData().set('CMCD', query);
|
|
559
|
+
return url.toString();
|
|
540
560
|
}
|
|
541
561
|
};
|
|
542
562
|
|
|
@@ -546,7 +566,7 @@ shaka.util.CmcdManager = class {
|
|
|
546
566
|
* getBandwidthEstimate: function():number,
|
|
547
567
|
* getBufferedInfo: function():shaka.extern.BufferedInfo,
|
|
548
568
|
* getCurrentTime: function():number,
|
|
549
|
-
*
|
|
569
|
+
* getVariantTracks: function():Array.<shaka.extern.Track>,
|
|
550
570
|
* getPlaybackRate: function():number,
|
|
551
571
|
* isLive: function():boolean
|
|
552
572
|
* }}
|
|
@@ -557,8 +577,8 @@ shaka.util.CmcdManager = class {
|
|
|
557
577
|
* Get information about what the player has buffered.
|
|
558
578
|
* @property {function():number} getCurrentTime
|
|
559
579
|
* Get the current time
|
|
560
|
-
* @property {function():shaka.extern.
|
|
561
|
-
* Get the
|
|
580
|
+
* @property {function():Array.<shaka.extern.Track>} getVariantTracks
|
|
581
|
+
* Get the variant tracks
|
|
562
582
|
* @property {function():number} getPlaybackRate
|
|
563
583
|
* Get the playback rate
|
|
564
584
|
* @property {function():boolean} isLive
|
|
@@ -608,180 +628,6 @@ shaka.util.CmcdManager.SegmentInfo;
|
|
|
608
628
|
shaka.util.CmcdManager.ManifestInfo;
|
|
609
629
|
|
|
610
630
|
|
|
611
|
-
/**
|
|
612
|
-
* @typedef {{
|
|
613
|
-
* br: (number|undefined),
|
|
614
|
-
* d: (number|undefined),
|
|
615
|
-
* ot: (shaka.util.CmcdManager.ObjectType|undefined),
|
|
616
|
-
* tb: (number|undefined),
|
|
617
|
-
* bl: (number|undefined),
|
|
618
|
-
* dl: (number|undefined),
|
|
619
|
-
* mtp: (number|undefined),
|
|
620
|
-
* nor: (string|undefined),
|
|
621
|
-
* nrr: (string|undefined),
|
|
622
|
-
* su: (boolean|undefined),
|
|
623
|
-
* cid: (string|undefined),
|
|
624
|
-
* pr: (number|undefined),
|
|
625
|
-
* sf: (shaka.util.CmcdManager.StreamingFormat|undefined),
|
|
626
|
-
* sid: (string|undefined),
|
|
627
|
-
* st: (shaka.util.CmcdManager.StreamType|undefined),
|
|
628
|
-
* v: (number|undefined),
|
|
629
|
-
* bs: (boolean|undefined),
|
|
630
|
-
* rtp: (number|undefined)
|
|
631
|
-
* }}
|
|
632
|
-
*
|
|
633
|
-
* @description
|
|
634
|
-
* Client Media Common Data (CMCD) data.
|
|
635
|
-
*
|
|
636
|
-
* @property {number} br
|
|
637
|
-
* The encoded bitrate of the audio or video object being requested. This may
|
|
638
|
-
* not be known precisely by the player; however, it MAY be estimated based
|
|
639
|
-
* upon playlist/manifest declarations. If the playlist declares both peak and
|
|
640
|
-
* average bitrate values, the peak value should be transmitted.
|
|
641
|
-
*
|
|
642
|
-
* @property {number} d
|
|
643
|
-
* The playback duration in milliseconds of the object being requested. If a
|
|
644
|
-
* partial segment is being requested, then this value MUST indicate the
|
|
645
|
-
* playback duration of that part and not that of its parent segment. This
|
|
646
|
-
* value can be an approximation of the estimated duration if the explicit
|
|
647
|
-
* value is not known.
|
|
648
|
-
*
|
|
649
|
-
* @property {shaka.util.CmcdManager.ObjectType} ot
|
|
650
|
-
* The media type of the current object being requested:
|
|
651
|
-
* - `m` = text file, such as a manifest or playlist
|
|
652
|
-
* - `a` = audio only
|
|
653
|
-
* - `v` = video only
|
|
654
|
-
* - `av` = muxed audio and video
|
|
655
|
-
* - `i` = init segment
|
|
656
|
-
* - `c` = caption or subtitle
|
|
657
|
-
* - `tt` = ISOBMFF timed text track
|
|
658
|
-
* - `k` = cryptographic key, license or certificate.
|
|
659
|
-
* - `o` = other
|
|
660
|
-
*
|
|
661
|
-
* If the object type being requested is unknown, then this key MUST NOT be
|
|
662
|
-
* used.
|
|
663
|
-
*
|
|
664
|
-
* @property {number} tb
|
|
665
|
-
* The highest bitrate rendition in the manifest or playlist that the client
|
|
666
|
-
* is allowed to play, given current codec, licensing and sizing constraints.
|
|
667
|
-
*
|
|
668
|
-
* @property {number} bl
|
|
669
|
-
* The buffer length associated with the media object being requested. This
|
|
670
|
-
* value MUST be rounded to the nearest 100 ms. This key SHOULD only be sent
|
|
671
|
-
* with an object type of ‘a’, ‘v’ or ‘av’.
|
|
672
|
-
*
|
|
673
|
-
* @property {number} dl
|
|
674
|
-
* Deadline from the request time until the first sample of this
|
|
675
|
-
* Segment/Object needs to be available in order to not create a buffer
|
|
676
|
-
* underrun or any other playback problems. This value MUST be rounded to the
|
|
677
|
-
* nearest 100ms. For a playback rate of 1, this may be equivalent to the
|
|
678
|
-
* player’s remaining buffer length.
|
|
679
|
-
*
|
|
680
|
-
* @property {number} mtp
|
|
681
|
-
* The throughput between client and server, as measured by the client and
|
|
682
|
-
* MUST be rounded to the nearest 100 kbps. This value, however derived,
|
|
683
|
-
* SHOULD be the value that the client is using to make its next Adaptive
|
|
684
|
-
* Bitrate switching decision. If the client is connected to multiple
|
|
685
|
-
* servers concurrently, it must take care to report only the throughput
|
|
686
|
-
* measured against the receiving server. If the client has multiple
|
|
687
|
-
* concurrent connections to the server, then the intent is that this value
|
|
688
|
-
* communicates the aggregate throughput the client sees across all those
|
|
689
|
-
* connections.
|
|
690
|
-
*
|
|
691
|
-
* @property {string} nor
|
|
692
|
-
* Relative path of the next object to be requested. This can be used to
|
|
693
|
-
* trigger pre-fetching by the CDN. This MUST be a path relative to the
|
|
694
|
-
* current request. This string MUST be URLEncoded. The client SHOULD NOT
|
|
695
|
-
* depend upon any pre-fetch action being taken - it is merely a request for
|
|
696
|
-
* such a pre-fetch to take place.
|
|
697
|
-
*
|
|
698
|
-
* @property {string} nrr
|
|
699
|
-
* If the next request will be a partial object request, then this string
|
|
700
|
-
* denotes the byte range to be requested. If the ‘nor’ field is not set, then
|
|
701
|
-
* the object is assumed to match the object currently being requested. The
|
|
702
|
-
* client SHOULD NOT depend upon any pre-fetch action being taken – it is
|
|
703
|
-
* merely a request for such a pre-fetch to take place. Formatting is similar
|
|
704
|
-
* to the HTTP Range header, except that the unit MUST be ‘byte’, the ‘Range:’
|
|
705
|
-
* prefix is NOT required and specifying multiple ranges is NOT allowed. Valid
|
|
706
|
-
* combinations are:
|
|
707
|
-
*
|
|
708
|
-
* - `"\<range-start\>-"`
|
|
709
|
-
* - `"\<range-start\>-\<range-end\>"`
|
|
710
|
-
* - `"-\<suffix-length\>"`
|
|
711
|
-
*
|
|
712
|
-
* @property {boolean} su
|
|
713
|
-
* Key is included without a value if the object is needed urgently due to
|
|
714
|
-
* startup, seeking or recovery after a buffer-empty event. The media SHOULD
|
|
715
|
-
* not be rendering when this request is made. This key MUST not be sent if it
|
|
716
|
-
* is FALSE.
|
|
717
|
-
*
|
|
718
|
-
* @property {string} cid
|
|
719
|
-
* A unique string identifying the current content. Maximum length is 64
|
|
720
|
-
* characters. This value is consistent across multiple different sessions and
|
|
721
|
-
* devices and is defined and updated at the discretion of the service
|
|
722
|
-
* provider.
|
|
723
|
-
*
|
|
724
|
-
* @property {number} pr
|
|
725
|
-
* The playback rate. `1` if real-time, `2` if double speed, `0` if not
|
|
726
|
-
* playing. SHOULD only be sent if not equal to `1`.
|
|
727
|
-
*
|
|
728
|
-
* @property {shaka.util.CmcdManager.StreamingFormat} sf
|
|
729
|
-
* The streaming format that defines the current request.
|
|
730
|
-
*
|
|
731
|
-
* - `d` = MPEG DASH
|
|
732
|
-
* - `h` = HTTP Live Streaming (HLS)
|
|
733
|
-
* - `s` = Smooth Streaming
|
|
734
|
-
* - `o` = other
|
|
735
|
-
*
|
|
736
|
-
* If the streaming format being requested is unknown, then this key MUST NOT
|
|
737
|
-
* be used.
|
|
738
|
-
*
|
|
739
|
-
* @property {string} sid
|
|
740
|
-
* A GUID identifying the current playback session. A playback session
|
|
741
|
-
* typically ties together segments belonging to a single media asset. Maximum
|
|
742
|
-
* length is 64 characters. It is RECOMMENDED to conform to the UUID
|
|
743
|
-
* specification.
|
|
744
|
-
*
|
|
745
|
-
* @property {shaka.util.CmcdManager.StreamType} st
|
|
746
|
-
* Stream type
|
|
747
|
-
* - `v` = all segments are available – e.g., VOD
|
|
748
|
-
* - `l` = segments become available over time – e.g., LIVE
|
|
749
|
-
*
|
|
750
|
-
* @property {number} v
|
|
751
|
-
* The version of this specification used for interpreting the defined key
|
|
752
|
-
* names and values. If this key is omitted, the client and server MUST
|
|
753
|
-
* interpret the values as being defined by version 1. Client SHOULD omit this
|
|
754
|
-
* field if the version is 1.
|
|
755
|
-
*
|
|
756
|
-
* @property {boolean} bs
|
|
757
|
-
* Buffer starvation key is included without a value if the buffer was starved
|
|
758
|
-
* at some point between the prior request and this object request, resulting
|
|
759
|
-
* in the player being in a rebuffering state and the video or audio playback
|
|
760
|
-
* being stalled. This key MUST NOT be sent if the buffer was not starved
|
|
761
|
-
* since the prior request.
|
|
762
|
-
*
|
|
763
|
-
* If the object type `ot` key is sent along with this key, then the `bs` key
|
|
764
|
-
* refers to the buffer associated with the particular object type. If no
|
|
765
|
-
* object type is communicated, then the buffer state applies to the current
|
|
766
|
-
* session.
|
|
767
|
-
*
|
|
768
|
-
* @property {number} rtp
|
|
769
|
-
* Requested maximum throughput
|
|
770
|
-
*
|
|
771
|
-
* The requested maximum throughput that the client considers sufficient for
|
|
772
|
-
* delivery of the asset. Values MUST be rounded to the nearest 100kbps. For
|
|
773
|
-
* example, a client would indicate that the current segment, encoded at
|
|
774
|
-
* 2Mbps, is to be delivered at no more than 10Mbps, by using rtp=10000.
|
|
775
|
-
*
|
|
776
|
-
* Note: This can benefit clients by preventing buffer saturation through
|
|
777
|
-
* over-delivery and can also deliver a community benefit through fair-share
|
|
778
|
-
* delivery. The concept is that each client receives the throughput necessary
|
|
779
|
-
* for great performance, but no more. The CDN may not support the rtp
|
|
780
|
-
* feature.
|
|
781
|
-
*/
|
|
782
|
-
shaka.util.CmcdManager.Data;
|
|
783
|
-
|
|
784
|
-
|
|
785
631
|
/**
|
|
786
632
|
* @enum {string}
|
|
787
633
|
*/
|
package/lib/util/stream_utils.js
CHANGED
|
@@ -419,13 +419,48 @@ shaka.util.StreamUtils = class {
|
|
|
419
419
|
*/
|
|
420
420
|
static async filterManifestByMediaCapabilities(
|
|
421
421
|
manifest, usePersistentLicenses) {
|
|
422
|
-
goog.asserts.assert(
|
|
422
|
+
goog.asserts.assert(navigator.mediaCapabilities,
|
|
423
423
|
'MediaCapabilities should be valid.');
|
|
424
424
|
|
|
425
425
|
await shaka.util.StreamUtils.getDecodingInfosForVariants(
|
|
426
426
|
manifest.variants, usePersistentLicenses, /* srcEquals= */ false);
|
|
427
427
|
manifest.variants = manifest.variants.filter((variant) => {
|
|
428
|
+
// See: https://github.com/google/shaka-player/issues/3860
|
|
428
429
|
const video = variant.video;
|
|
430
|
+
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
431
|
+
if (video) {
|
|
432
|
+
let videoCodecs = shaka.util.StreamUtils.patchVp9(video.codecs);
|
|
433
|
+
// For multiplexed streams. Here we must check the audio of the
|
|
434
|
+
// stream to see if it is compatible.
|
|
435
|
+
if (video.codecs.includes(',')) {
|
|
436
|
+
const allCodecs = video.codecs.split(',');
|
|
437
|
+
videoCodecs = shaka.util.ManifestParserUtils.guessCodecs(
|
|
438
|
+
ContentType.VIDEO, allCodecs);
|
|
439
|
+
const audioCodecs = shaka.util.ManifestParserUtils.guessCodecs(
|
|
440
|
+
ContentType.AUDIO, allCodecs);
|
|
441
|
+
const audioFullType = shaka.util.MimeUtils.getFullOrConvertedType(
|
|
442
|
+
video.mimeType, audioCodecs, ContentType.AUDIO);
|
|
443
|
+
if (!MediaSource.isTypeSupported(audioFullType)) {
|
|
444
|
+
return false;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
const fullType = shaka.util.MimeUtils.getFullOrConvertedType(
|
|
448
|
+
video.mimeType, videoCodecs, ContentType.VIDEO);
|
|
449
|
+
if (!MediaSource.isTypeSupported(fullType)) {
|
|
450
|
+
return false;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
const audio = variant.audio;
|
|
454
|
+
if (audio) {
|
|
455
|
+
const codecs =
|
|
456
|
+
shaka.util.StreamUtils.getCorrectAudioCodecs_(audio.codecs);
|
|
457
|
+
const fullType = shaka.util.MimeUtils.getFullOrConvertedType(
|
|
458
|
+
audio.mimeType, codecs, ContentType.AUDIO);
|
|
459
|
+
if (!MediaSource.isTypeSupported(fullType)) {
|
|
460
|
+
return false;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
429
464
|
// See: https://github.com/google/shaka-player/issues/3380
|
|
430
465
|
if (shaka.util.Platform.isXboxOne() && video &&
|
|
431
466
|
((video.width && video.width > 1920) ||
|
|
@@ -468,7 +503,7 @@ shaka.util.StreamUtils = class {
|
|
|
468
503
|
return;
|
|
469
504
|
}
|
|
470
505
|
|
|
471
|
-
const mediaCapabilities =
|
|
506
|
+
const mediaCapabilities = navigator.mediaCapabilities;
|
|
472
507
|
|
|
473
508
|
const operations = [];
|
|
474
509
|
const getVariantDecodingInfos = (async (variant, decodingConfig) => {
|
|
@@ -562,12 +597,8 @@ shaka.util.StreamUtils = class {
|
|
|
562
597
|
}
|
|
563
598
|
}
|
|
564
599
|
if (audio) {
|
|
565
|
-
// Some Tizen devices seem to misreport AC-3 support, but correctly
|
|
566
|
-
// report EC-3 support. So query EC-3 as a fallback for AC-3.
|
|
567
|
-
// See https://github.com/google/shaka-player/issues/2989 for details.
|
|
568
600
|
const codecs =
|
|
569
|
-
(audio.codecs
|
|
570
|
-
shaka.util.Platform.isTizen()) ? 'ec-3' : audio.codecs;
|
|
601
|
+
shaka.util.StreamUtils.getCorrectAudioCodecs_(audio.codecs);
|
|
571
602
|
const fullType = shaka.util.MimeUtils.getFullOrConvertedType(
|
|
572
603
|
audio.mimeType, codecs, ContentType.AUDIO);
|
|
573
604
|
|
|
@@ -678,6 +709,26 @@ shaka.util.StreamUtils = class {
|
|
|
678
709
|
return configs;
|
|
679
710
|
}
|
|
680
711
|
|
|
712
|
+
|
|
713
|
+
/**
|
|
714
|
+
* Generates the correct audio codec for MediaDecodingConfiguration and
|
|
715
|
+
* for MediaSource.isTypeSupported.
|
|
716
|
+
* @param {string} codecs
|
|
717
|
+
* @return {string}
|
|
718
|
+
* @private
|
|
719
|
+
*/
|
|
720
|
+
static getCorrectAudioCodecs_(codecs) {
|
|
721
|
+
// Some Tizen devices seem to misreport AC-3 support, but correctly
|
|
722
|
+
// report EC-3 support. So query EC-3 as a fallback for AC-3.
|
|
723
|
+
// See https://github.com/google/shaka-player/issues/2989 for details.
|
|
724
|
+
if (shaka.util.Platform.isTizen()) {
|
|
725
|
+
return codecs.toLowerCase() == 'ac-3' ? 'ec-3' : codecs;
|
|
726
|
+
} else {
|
|
727
|
+
return codecs;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
|
|
681
732
|
/**
|
|
682
733
|
* MediaCapabilities supports 'vp09...' codecs, but not 'vp9'. Translate vp9
|
|
683
734
|
* codec strings into 'vp09...', to allow such content to play with
|
|
@@ -989,6 +1040,31 @@ shaka.util.StreamUtils = class {
|
|
|
989
1040
|
static imageStreamToTrack(stream) {
|
|
990
1041
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
991
1042
|
|
|
1043
|
+
let width = stream.width || null;
|
|
1044
|
+
let height = stream.height || null;
|
|
1045
|
+
|
|
1046
|
+
// The stream width and height represent the size of the entire thumbnail
|
|
1047
|
+
// sheet, so divide by the layout.
|
|
1048
|
+
let reference = null;
|
|
1049
|
+
// Note: segmentIndex is built by default for HLS, but not for DASH, but
|
|
1050
|
+
// in DASH this information comes at the stream level and not at the
|
|
1051
|
+
// segment level.
|
|
1052
|
+
if (stream.segmentIndex) {
|
|
1053
|
+
reference = stream.segmentIndex.get(0);
|
|
1054
|
+
}
|
|
1055
|
+
let layout = stream.tilesLayout;
|
|
1056
|
+
if (reference) {
|
|
1057
|
+
layout = reference.getTilesLayout() || layout;
|
|
1058
|
+
}
|
|
1059
|
+
if (layout && width != null) {
|
|
1060
|
+
width /= Number(layout.split('x')[0]);
|
|
1061
|
+
}
|
|
1062
|
+
if (layout && height != null) {
|
|
1063
|
+
height /= Number(layout.split('x')[1]);
|
|
1064
|
+
}
|
|
1065
|
+
// TODO: What happens if there are multiple grids, with different
|
|
1066
|
+
// layout sizes, inside this image stream?
|
|
1067
|
+
|
|
992
1068
|
/** @type {shaka.extern.Track} */
|
|
993
1069
|
const track = {
|
|
994
1070
|
id: stream.id,
|
|
@@ -998,8 +1074,8 @@ shaka.util.StreamUtils = class {
|
|
|
998
1074
|
language: '',
|
|
999
1075
|
label: null,
|
|
1000
1076
|
kind: null,
|
|
1001
|
-
width
|
|
1002
|
-
height
|
|
1077
|
+
width,
|
|
1078
|
+
height,
|
|
1003
1079
|
frameRate: null,
|
|
1004
1080
|
pixelAspectRatio: null,
|
|
1005
1081
|
hdr: null,
|
|
@@ -1016,7 +1092,7 @@ shaka.util.StreamUtils = class {
|
|
|
1016
1092
|
channelsCount: null,
|
|
1017
1093
|
audioSamplingRate: null,
|
|
1018
1094
|
spatialAudio: false,
|
|
1019
|
-
tilesLayout:
|
|
1095
|
+
tilesLayout: layout || null,
|
|
1020
1096
|
audioBandwidth: null,
|
|
1021
1097
|
videoBandwidth: null,
|
|
1022
1098
|
originalVideoId: null,
|
package/lib/util/xml_utils.js
CHANGED
|
@@ -103,6 +103,25 @@ shaka.util.XmlUtils = class {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Gets a namespace-qualified attribute.
|
|
108
|
+
* @param {!Element} elem The element to get from.
|
|
109
|
+
* @param {!Array.<string>} nsList The lis of namespace URIs.
|
|
110
|
+
* @param {string} name The local name of the attribute.
|
|
111
|
+
* @return {?string} The attribute's value, or null if not present.
|
|
112
|
+
*/
|
|
113
|
+
static getAttributeNSList(elem, nsList, name) {
|
|
114
|
+
// Some browsers return the empty string when the attribute is missing,
|
|
115
|
+
// so check if it exists first. See: https://mzl.la/2L7F0UK
|
|
116
|
+
for (const ns of nsList) {
|
|
117
|
+
if (elem.hasAttributeNS(ns, name)) {
|
|
118
|
+
return elem.getAttributeNS(ns, name);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
106
125
|
/**
|
|
107
126
|
* Gets the text contents of a node.
|
|
108
127
|
* @param {!Node} elem The XML element.
|
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": "3.3.
|
|
4
|
+
"version": "3.3.1",
|
|
5
5
|
"homepage": "https://github.com/google/shaka-player",
|
|
6
6
|
"author": "Google",
|
|
7
7
|
"maintainers": [
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
],
|
|
13
13
|
"devDependencies": {
|
|
14
14
|
"@chiragrupani/karma-chromium-edge-launcher": "^2.1.0",
|
|
15
|
+
"@onslip/karma-safari-launcher": "^1.0.1",
|
|
15
16
|
"@teppeis/clutz": "^1.0.29-4c95e12.v20190929",
|
|
16
17
|
"awesomplete": "^1.1.4",
|
|
17
18
|
"babel-core": "^6.26.3",
|
|
@@ -44,7 +45,6 @@
|
|
|
44
45
|
"karma-jasmine": "^3.3.1",
|
|
45
46
|
"karma-jasmine-ajax": "^0.1.13",
|
|
46
47
|
"karma-opera-launcher": "^1.0.0",
|
|
47
|
-
"karma-safari-launcher": "^1.0.0",
|
|
48
48
|
"karma-sourcemap-loader": "^0.3.7",
|
|
49
49
|
"karma-spec-reporter": "0.0.32",
|
|
50
50
|
"karma-webdriver-launcher": "^1.0.8",
|
|
@@ -31,7 +31,7 @@ describe('DrmEngine', () => {
|
|
|
31
31
|
navigator.requestMediaKeySystemAccess;
|
|
32
32
|
const originalLogError = shaka.log.error;
|
|
33
33
|
const originalBatchTime = shaka.media.DrmEngine.KEY_STATUS_BATCH_TIME;
|
|
34
|
-
const originalDecodingInfo =
|
|
34
|
+
const originalDecodingInfo = navigator.mediaCapabilities.decodingInfo;
|
|
35
35
|
|
|
36
36
|
/** @type {!jasmine.Spy} */
|
|
37
37
|
let decodingInfoSpy;
|
|
@@ -76,7 +76,7 @@ describe('DrmEngine', () => {
|
|
|
76
76
|
|
|
77
77
|
beforeEach(() => {
|
|
78
78
|
decodingInfoSpy = jasmine.createSpy('decodingInfo');
|
|
79
|
-
|
|
79
|
+
navigator.mediaCapabilities.decodingInfo =
|
|
80
80
|
shaka.test.Util.spyFunc(decodingInfoSpy);
|
|
81
81
|
|
|
82
82
|
logErrorSpy = jasmine.createSpy('shaka.log.error');
|
|
@@ -153,7 +153,7 @@ describe('DrmEngine', () => {
|
|
|
153
153
|
|
|
154
154
|
navigator.requestMediaKeySystemAccess =
|
|
155
155
|
originalRequestMediaKeySystemAccess;
|
|
156
|
-
|
|
156
|
+
navigator.mediaCapabilities.decodingInfo = originalDecodingInfo;
|
|
157
157
|
shaka.log.error = originalLogError;
|
|
158
158
|
});
|
|
159
159
|
|
|
@@ -420,8 +420,9 @@ describe('StreamingEngine', () => {
|
|
|
420
420
|
// 3. Playhead seeks to force us back inside the window
|
|
421
421
|
// 4. (maybe) seek if there is a gap at the period boundary
|
|
422
422
|
// 5. (maybe) seek to flush a pipeline stall
|
|
423
|
+
// 6. (maybe) on slower platforms (e.g. GitHub actions)
|
|
423
424
|
expect(seekCount).toBeGreaterThan(2);
|
|
424
|
-
expect(seekCount).toBeLessThan(
|
|
425
|
+
expect(seekCount).toBeLessThan(7);
|
|
425
426
|
});
|
|
426
427
|
});
|
|
427
428
|
|