shaka-player 4.2.5 → 4.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/.github/workflows/build-and-test.yaml +7 -0
- package/.github/workflows/sync-labels.yaml +1 -1
- package/.github/workflows/update-issues.yaml +1 -1
- package/AUTHORS +4 -0
- package/CHANGELOG.md +114 -74
- package/CONTRIBUTORS +4 -0
- package/README.md +14 -0
- package/conditional/dummy_cast_proxy.js +120 -0
- package/demo/common/assets.js +58 -0
- package/demo/common/message_ids.js +22 -1
- package/demo/config.js +89 -5
- package/demo/demo.less +7 -1
- package/demo/index.html +8 -1
- package/demo/locales/en.json +21 -1
- package/demo/locales/source.json +82 -2
- package/demo/main.js +57 -1
- package/demo/search.js +2 -0
- package/demo/visualizer.js +337 -0
- package/demo/visualizer_button.js +103 -0
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +107 -88
- package/dist/demo.compiled.debug.map +4 -4
- package/dist/demo.compiled.js +107 -88
- package/dist/demo.compiled.map +4 -4
- package/dist/demo.css +1 -1
- package/dist/demo.css.map +1 -1
- package/dist/deps.js +21 -13
- package/dist/locales.js +31 -31
- package/dist/receiver.compiled.debug.js +75 -77
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +75 -77
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.d.ts +181 -27
- package/dist/shaka-player.compiled.debug.d.ts +181 -27
- package/dist/shaka-player.compiled.debug.externs.js +169 -31
- package/dist/shaka-player.compiled.debug.js +510 -450
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +169 -31
- package/dist/shaka-player.compiled.js +912 -874
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +181 -27
- package/dist/shaka-player.ui.debug.d.ts +181 -27
- package/dist/shaka-player.ui.debug.externs.js +169 -31
- package/dist/shaka-player.ui.debug.js +533 -471
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +169 -31
- package/dist/shaka-player.ui.js +1073 -1036
- package/dist/shaka-player.ui.map +4 -4
- package/docs/design/lcevc-architecture.png +0 -0
- package/docs/design/lcevc-demo.png +0 -0
- package/docs/design/lcevc-integration.md +72 -0
- package/docs/tutorials/fairplay.md +7 -0
- package/docs/tutorials/faq.md +1 -1
- package/docs/tutorials/ui.md +7 -7
- package/docs/tutorials/upgrade.md +6 -0
- package/externs/ima.js +13 -1
- package/externs/lcevc.js +81 -0
- package/externs/mux.js +1 -42
- package/externs/shaka/ads.js +11 -1
- package/externs/shaka/manifest_parser.js +5 -1
- package/externs/shaka/mp4_parser.js +3 -0
- package/externs/shaka/player.js +178 -15
- package/lib/abr/simple_abr_manager.js +7 -0
- package/lib/ads/ad_manager.js +0 -8
- package/lib/ads/client_side_ad.js +15 -0
- package/lib/ads/client_side_ad_manager.js +21 -8
- package/lib/ads/server_side_ad.js +15 -0
- package/lib/ads/server_side_ad_manager.js +3 -3
- package/lib/cast/cast_utils.js +2 -0
- package/lib/cea/dummy_cea_parser.js +28 -0
- package/lib/cea/i_cea_parser.js +14 -2
- package/lib/cea/mp4_cea_parser.js +108 -5
- package/lib/config/auto_show_text.js +33 -0
- package/lib/dash/dash_parser.js +1 -1
- package/lib/hls/hls_parser.js +808 -384
- package/lib/lcevc/lcevc_dil.js +152 -0
- package/lib/media/closed_caption_parser.js +9 -6
- package/lib/media/drm_engine.js +14 -6
- package/lib/media/media_source_capabilities.js +36 -0
- package/lib/media/media_source_engine.js +113 -28
- package/lib/media/presentation_timeline.js +26 -11
- package/lib/media/segment_reference.js +49 -1
- package/lib/media/streaming_engine.js +142 -12
- package/lib/media/transmuxer.js +78 -21
- package/lib/offline/storage.js +1 -0
- package/lib/player.js +456 -77
- package/lib/polyfill/media_capabilities.js +9 -5
- package/lib/polyfill/patchedmediakeys_apple.js +63 -4
- package/lib/text/vtt_text_parser.js +35 -1
- package/lib/util/dom_utils.js +0 -1
- package/lib/util/error.js +17 -0
- package/lib/util/fake_event.js +2 -0
- package/lib/util/id3_utils.js +300 -0
- package/lib/util/mime_utils.js +3 -6
- package/lib/util/mp4_box_parsers.js +39 -5
- package/lib/util/mp4_parser.js +35 -0
- package/lib/util/player_configuration.js +23 -1
- package/lib/util/stream_utils.js +5 -3
- package/lib/util/ts_parser.js +499 -0
- package/maintained-branches.md +2 -2
- package/package.json +7 -4
- package/roadmap.md +5 -3
- package/test/ads/ad_manager_unit.js +182 -29
- package/test/cast/cast_utils_unit.js +3 -1
- package/test/dash/dash_parser_content_protection_unit.js +1 -0
- package/test/dash/dash_parser_live_unit.js +1 -0
- package/test/dash/dash_parser_manifest_unit.js +93 -1
- package/test/dash/dash_parser_segment_base_unit.js +1 -0
- package/test/dash/dash_parser_segment_list_unit.js +1 -0
- package/test/dash/dash_parser_segment_template_unit.js +1 -0
- package/test/demo/demo_unit.js +2 -1
- package/test/hls/hls_live_unit.js +253 -19
- package/test/hls/hls_parser_unit.js +631 -12
- package/test/media/closed_caption_parser_unit.js +2 -1
- package/test/media/drm_engine_integration.js +3 -1
- package/test/media/media_source_engine_integration.js +71 -6
- package/test/media/media_source_engine_unit.js +10 -5
- package/test/media/streaming_engine_integration.js +4 -1
- package/test/media/streaming_engine_unit.js +144 -1
- package/test/media/transmuxer_integration.js +21 -10
- package/test/player_integration.js +224 -82
- package/test/player_unit.js +5 -2
- package/test/polyfill/media_capabilities_unit.js +21 -23
- package/test/polyfill/patchedmediakeys_apple_unit.js +130 -0
- package/test/test/assets/id3-metadata.aac +0 -0
- package/test/test/assets/id3-metadata.ts +0 -0
- package/test/test/assets/thumbnails-sprites.vtt +10 -0
- package/test/test/assets/thumbnails.vtt +10 -0
- package/test/test/util/dash_parser_util.js +2 -0
- package/test/test/util/fake_ad.js +21 -0
- package/test/test/util/fake_media_source_engine.js +7 -0
- package/test/test/util/id3_generator.js +100 -0
- package/test/test/util/manifest_generator.js +3 -6
- package/test/test/util/simple_fakes.js +4 -0
- package/test/test/util/stream_generator.js +38 -0
- package/test/test/util/test_scheme.js +43 -14
- package/test/text/vtt_text_parser_unit.js +11 -0
- package/test/util/id3_utils_unit.js +116 -0
- package/test/util/ts_parser_unit.js +77 -0
- package/third_party/closure-uri/uri.js +1 -1
- package/ui/less/containers.less +7 -0
- package/ui/ui.js +43 -4
|
@@ -24,6 +24,7 @@ goog.require('shaka.util.Destroyer');
|
|
|
24
24
|
goog.require('shaka.util.Error');
|
|
25
25
|
goog.require('shaka.util.FakeEvent');
|
|
26
26
|
goog.require('shaka.util.IDestroyable');
|
|
27
|
+
goog.require('shaka.util.Id3Utils');
|
|
27
28
|
goog.require('shaka.util.ManifestParserUtils');
|
|
28
29
|
goog.require('shaka.util.MimeUtils');
|
|
29
30
|
goog.require('shaka.util.Mp4Parser');
|
|
@@ -77,6 +78,9 @@ shaka.media.StreamingEngine = class {
|
|
|
77
78
|
/** @private {?shaka.extern.Stream} */
|
|
78
79
|
this.currentTextStream_ = null;
|
|
79
80
|
|
|
81
|
+
/** @private {boolean} */
|
|
82
|
+
this.parsedPrftEventRaised_ = false;
|
|
83
|
+
|
|
80
84
|
/**
|
|
81
85
|
* Maps a content type, e.g., 'audio', 'video', or 'text', to a MediaState.
|
|
82
86
|
*
|
|
@@ -780,9 +784,9 @@ shaka.media.StreamingEngine = class {
|
|
|
780
784
|
|
|
781
785
|
// Init MediaSourceEngine.
|
|
782
786
|
const mediaSourceEngine = this.playerInterface_.mediaSourceEngine;
|
|
783
|
-
const
|
|
787
|
+
const forceTransmux = this.config_.forceTransmux;
|
|
784
788
|
|
|
785
|
-
await mediaSourceEngine.init(streamsByType,
|
|
789
|
+
await mediaSourceEngine.init(streamsByType, forceTransmux,
|
|
786
790
|
this.manifest_.sequenceMode);
|
|
787
791
|
this.destroyer_.ensureNotDestroyed();
|
|
788
792
|
|
|
@@ -1370,7 +1374,8 @@ shaka.media.StreamingEngine = class {
|
|
|
1370
1374
|
JSON.stringify(buffered));
|
|
1371
1375
|
|
|
1372
1376
|
if (!mediaState.waitingToClearBuffer) {
|
|
1373
|
-
this.playerInterface_.onSegmentAppended(
|
|
1377
|
+
this.playerInterface_.onSegmentAppended(
|
|
1378
|
+
reference.startTime, reference.endTime, mediaState.type);
|
|
1374
1379
|
}
|
|
1375
1380
|
|
|
1376
1381
|
// Update right away.
|
|
@@ -1626,6 +1631,17 @@ shaka.media.StreamingEngine = class {
|
|
|
1626
1631
|
try {
|
|
1627
1632
|
const initSegment = await fetchInit;
|
|
1628
1633
|
this.destroyer_.ensureNotDestroyed();
|
|
1634
|
+
|
|
1635
|
+
const parser = new shaka.util.Mp4Parser();
|
|
1636
|
+
const Mp4Parser = shaka.util.Mp4Parser;
|
|
1637
|
+
parser.box('moov', Mp4Parser.children)
|
|
1638
|
+
.box('trak', Mp4Parser.children)
|
|
1639
|
+
.box('mdia', Mp4Parser.children)
|
|
1640
|
+
.fullBox('mdhd', (box) => {
|
|
1641
|
+
this.parseMDHD_(reference, box);
|
|
1642
|
+
})
|
|
1643
|
+
.parse(initSegment);
|
|
1644
|
+
|
|
1629
1645
|
shaka.log.v1(logPrefix, 'appending init segment');
|
|
1630
1646
|
const hasClosedCaptions = mediaState.stream.closedCaptions &&
|
|
1631
1647
|
mediaState.stream.closedCaptions.size > 0;
|
|
@@ -1665,15 +1681,36 @@ shaka.media.StreamingEngine = class {
|
|
|
1665
1681
|
|
|
1666
1682
|
const hasClosedCaptions = stream.closedCaptions &&
|
|
1667
1683
|
stream.closedCaptions.size > 0;
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1684
|
+
|
|
1685
|
+
let parser;
|
|
1686
|
+
const hasEmsg = ((stream.emsgSchemeIdUris != null &&
|
|
1687
|
+
stream.emsgSchemeIdUris.length > 0) ||
|
|
1688
|
+
this.config_.dispatchAllEmsgBoxes);
|
|
1689
|
+
const shouldParsePrftBox =
|
|
1690
|
+
(this.config_.parsePrftBox && !this.parsedPrftEventRaised_);
|
|
1691
|
+
|
|
1692
|
+
if (hasEmsg || shouldParsePrftBox) {
|
|
1693
|
+
parser = new shaka.util.Mp4Parser();
|
|
1694
|
+
}
|
|
1695
|
+
|
|
1696
|
+
if (hasEmsg) {
|
|
1697
|
+
parser
|
|
1672
1698
|
.fullBox(
|
|
1673
1699
|
'emsg',
|
|
1674
1700
|
(box) => this.parseEMSG_(
|
|
1675
|
-
reference, stream.emsgSchemeIdUris, box))
|
|
1676
|
-
|
|
1701
|
+
reference, stream.emsgSchemeIdUris, box));
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1704
|
+
if (shouldParsePrftBox) {
|
|
1705
|
+
parser
|
|
1706
|
+
.fullBox(
|
|
1707
|
+
'prft',
|
|
1708
|
+
(box) => this.parsePrft_(
|
|
1709
|
+
reference, box));
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
if (hasEmsg || shouldParsePrftBox) {
|
|
1713
|
+
parser.parse(segment);
|
|
1677
1714
|
}
|
|
1678
1715
|
|
|
1679
1716
|
await this.evict_(mediaState, presentationTime);
|
|
@@ -1769,6 +1806,21 @@ shaka.media.StreamingEngine = class {
|
|
|
1769
1806
|
// A special scheme in DASH used to signal manifest updates.
|
|
1770
1807
|
if (schemeId == 'urn:mpeg:dash:event:2012') {
|
|
1771
1808
|
this.playerInterface_.onManifestUpdate();
|
|
1809
|
+
} else if (schemeId == 'https://aomedia.org/emsg/ID3') {
|
|
1810
|
+
// See https://aomediacodec.github.io/id3-emsg/
|
|
1811
|
+
const frames = shaka.util.Id3Utils.getID3Frames(messageData);
|
|
1812
|
+
if (frames.length && reference) {
|
|
1813
|
+
/** @private {shaka.extern.ID3Metadata} */
|
|
1814
|
+
const metadata = {
|
|
1815
|
+
cueTime: reference.startTime,
|
|
1816
|
+
data: messageData,
|
|
1817
|
+
frames: frames,
|
|
1818
|
+
dts: reference.startTime,
|
|
1819
|
+
pts: reference.startTime,
|
|
1820
|
+
};
|
|
1821
|
+
this.playerInterface_.onMetadata(
|
|
1822
|
+
[metadata], /* offset= */ 0, reference.endTime);
|
|
1823
|
+
}
|
|
1772
1824
|
} else {
|
|
1773
1825
|
/** @type {shaka.extern.EmsgInfo} */
|
|
1774
1826
|
const emsg = {
|
|
@@ -1792,6 +1844,77 @@ shaka.media.StreamingEngine = class {
|
|
|
1792
1844
|
}
|
|
1793
1845
|
}
|
|
1794
1846
|
|
|
1847
|
+
/**
|
|
1848
|
+
* Parse MDHD box.
|
|
1849
|
+
* @param {!shaka.media.SegmentReference} reference
|
|
1850
|
+
* @param {!shaka.extern.ParsedBox} box
|
|
1851
|
+
* @private
|
|
1852
|
+
*/
|
|
1853
|
+
parseMDHD_(reference, box) {
|
|
1854
|
+
const parsedMDHDBox = shaka.util.Mp4BoxParsers.parseMDHD(
|
|
1855
|
+
box.reader || 0, box.version || 0);
|
|
1856
|
+
reference.initSegmentReference.timescale = parsedMDHDBox.timescale;
|
|
1857
|
+
}
|
|
1858
|
+
|
|
1859
|
+
/**
|
|
1860
|
+
* Parse PRFT box.
|
|
1861
|
+
* @param {!shaka.media.SegmentReference} reference
|
|
1862
|
+
* @param {!shaka.extern.ParsedBox} box
|
|
1863
|
+
* @private
|
|
1864
|
+
*/
|
|
1865
|
+
parsePrft_(reference, box) {
|
|
1866
|
+
if (this.parsedPrftEventRaised_ ||
|
|
1867
|
+
!reference.initSegmentReference.timescale) {
|
|
1868
|
+
return;
|
|
1869
|
+
}
|
|
1870
|
+
box.reader.readUint32(); // Ignore referenceTrackId
|
|
1871
|
+
const ntpTimestampSec = box.reader.readUint32();
|
|
1872
|
+
const ntpTimestampFrac = box.reader.readUint32();
|
|
1873
|
+
const ntpTimestamp = ntpTimestampSec * 1000 +
|
|
1874
|
+
ntpTimestampFrac / 2**32 * 1000;
|
|
1875
|
+
|
|
1876
|
+
let mediaTime;
|
|
1877
|
+
if (box.version === 0) {
|
|
1878
|
+
mediaTime = box.reader.readUint32();
|
|
1879
|
+
} else {
|
|
1880
|
+
try {
|
|
1881
|
+
mediaTime = box.reader.readUint64();
|
|
1882
|
+
} catch (e) {
|
|
1883
|
+
shaka.log.warning('parsePrft_: parsing mediatime resulted in a '+
|
|
1884
|
+
'MEDIA.JS_INTEGER_OVERFLOW exception');
|
|
1885
|
+
this.parsedPrftEventRaised_ = true;
|
|
1886
|
+
return;
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1890
|
+
const timescale = reference.initSegmentReference.timescale;
|
|
1891
|
+
const wallClockTime = this.convertNtp(ntpTimestamp);
|
|
1892
|
+
const programStartDate = new Date(wallClockTime -
|
|
1893
|
+
(mediaTime / timescale) * 1000);
|
|
1894
|
+
const prftInfo = {
|
|
1895
|
+
wallClockTime,
|
|
1896
|
+
programStartDate,
|
|
1897
|
+
};
|
|
1898
|
+
|
|
1899
|
+
const eventName = shaka.util.FakeEvent.EventName.Prft;
|
|
1900
|
+
const data = (new Map()).set('detail', prftInfo);
|
|
1901
|
+
const event = new shaka.util.FakeEvent(
|
|
1902
|
+
eventName, data);
|
|
1903
|
+
this.playerInterface_.onEvent(event);
|
|
1904
|
+
this.parsedPrftEventRaised_ = true;
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
|
|
1908
|
+
/**
|
|
1909
|
+
* Convert Ntp ntpTimeStamp to UTC Time
|
|
1910
|
+
*
|
|
1911
|
+
* @param {number} ntpTimeStamp
|
|
1912
|
+
* @return {number} utcTime
|
|
1913
|
+
*/
|
|
1914
|
+
convertNtp(ntpTimeStamp) {
|
|
1915
|
+
const start = new Date(Date.UTC(1900, 0, 1, 0, 0, 0));
|
|
1916
|
+
return new Date(start.getTime() + ntpTimeStamp).getTime();
|
|
1917
|
+
}
|
|
1795
1918
|
|
|
1796
1919
|
/**
|
|
1797
1920
|
* Evicts media to meet the max buffer behind limit.
|
|
@@ -2071,10 +2194,12 @@ shaka.media.StreamingEngine = class {
|
|
|
2071
2194
|
* onError: function(!shaka.util.Error),
|
|
2072
2195
|
* onEvent: function(!Event),
|
|
2073
2196
|
* onManifestUpdate: function(),
|
|
2074
|
-
* onSegmentAppended: function(
|
|
2197
|
+
* onSegmentAppended: function(number, number,
|
|
2198
|
+
* !shaka.util.ManifestParserUtils.ContentType),
|
|
2075
2199
|
* onInitSegmentAppended: function(!number,!shaka.media.InitSegmentReference),
|
|
2076
2200
|
* beforeAppendSegment: function(
|
|
2077
|
-
* shaka.util.ManifestParserUtils.ContentType,!BufferSource):Promise
|
|
2201
|
+
* shaka.util.ManifestParserUtils.ContentType,!BufferSource):Promise,
|
|
2202
|
+
* onMetadata: !function(!Array.<shaka.extern.ID3Metadata>, number, ?number)
|
|
2078
2203
|
* }}
|
|
2079
2204
|
*
|
|
2080
2205
|
* @property {function():number} getPresentationTime
|
|
@@ -2097,14 +2222,19 @@ shaka.media.StreamingEngine = class {
|
|
|
2097
2222
|
* Called when an event occurs that should be sent to the app.
|
|
2098
2223
|
* @property {function()} onManifestUpdate
|
|
2099
2224
|
* Called when an embedded 'emsg' box should trigger a manifest update.
|
|
2100
|
-
* @property {function(
|
|
2225
|
+
* @property {function(number, number,
|
|
2226
|
+
* !shaka.util.ManifestParserUtils.ContentType)} onSegmentAppended
|
|
2101
2227
|
* Called after a segment is successfully appended to a MediaSource.
|
|
2228
|
+
* The parameters are the start and end time.
|
|
2102
2229
|
* @property
|
|
2103
2230
|
* {function(!number, !shaka.media.InitSegmentReference)} onInitSegmentAppended
|
|
2104
2231
|
* Called when an init segment is appended to a MediaSource.
|
|
2105
2232
|
* @property {!function(shaka.util.ManifestParserUtils.ContentType,
|
|
2106
2233
|
* !BufferSource):Promise} beforeAppendSegment
|
|
2107
2234
|
* A function called just before appending to the source buffer.
|
|
2235
|
+
* @property
|
|
2236
|
+
* {!function(!Array.<shaka.extern.ID3Metadata>, number, ?number)} onMetadata
|
|
2237
|
+
* Called when an ID3 is found in a EMSG.
|
|
2108
2238
|
*/
|
|
2109
2239
|
shaka.media.StreamingEngine.PlayerInterface;
|
|
2110
2240
|
|
package/lib/media/transmuxer.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
goog.provide('shaka.media.Transmuxer');
|
|
8
8
|
|
|
9
9
|
goog.require('goog.asserts');
|
|
10
|
+
goog.require('shaka.media.Capabilities');
|
|
10
11
|
goog.require('shaka.util.BufferUtils');
|
|
11
12
|
goog.require('shaka.util.Error');
|
|
12
13
|
goog.require('shaka.util.IDestroyable');
|
|
@@ -18,13 +19,18 @@ goog.require('shaka.dependencies');
|
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Transmuxer provides all operations for transmuxing from Transport
|
|
21
|
-
* Stream to MP4.
|
|
22
|
+
* Stream or AAC to MP4.
|
|
22
23
|
*
|
|
23
24
|
* @implements {shaka.util.IDestroyable}
|
|
24
25
|
*/
|
|
25
26
|
shaka.media.Transmuxer = class {
|
|
26
|
-
/**
|
|
27
|
-
|
|
27
|
+
/**
|
|
28
|
+
* @param {string} mimeType
|
|
29
|
+
*/
|
|
30
|
+
constructor(mimeType) {
|
|
31
|
+
/** @private {string} */
|
|
32
|
+
this.originalMimeType_ = mimeType;
|
|
33
|
+
|
|
28
34
|
/** @private {?muxjs} */
|
|
29
35
|
this.muxjs_ = shaka.dependencies.muxjs();
|
|
30
36
|
|
|
@@ -42,9 +48,6 @@ shaka.media.Transmuxer = class {
|
|
|
42
48
|
/** @private {!Array.<muxjs.mp4.ClosedCaption>} */
|
|
43
49
|
this.captions_ = [];
|
|
44
50
|
|
|
45
|
-
/** @private {!Array.<muxjs.mp4.Metadata>} */
|
|
46
|
-
this.metadata_ = [];
|
|
47
|
-
|
|
48
51
|
/** @private {boolean} */
|
|
49
52
|
this.isTransmuxing_ = false;
|
|
50
53
|
|
|
@@ -64,29 +67,49 @@ shaka.media.Transmuxer = class {
|
|
|
64
67
|
|
|
65
68
|
|
|
66
69
|
/**
|
|
67
|
-
* Check if the content type is Transport Stream, and if muxjs is
|
|
70
|
+
* Check if the content type is Transport Stream or AAC, and if muxjs is
|
|
71
|
+
* loaded.
|
|
68
72
|
* @param {string} mimeType
|
|
69
73
|
* @param {string=} contentType
|
|
70
74
|
* @return {boolean}
|
|
71
75
|
*/
|
|
72
76
|
static isSupported(mimeType, contentType) {
|
|
73
77
|
const Transmuxer = shaka.media.Transmuxer;
|
|
78
|
+
const Capabilities = shaka.media.Capabilities;
|
|
79
|
+
|
|
80
|
+
const isTs = Transmuxer.isTsContainer_(mimeType);
|
|
81
|
+
const isAac = Transmuxer.isAacContainer_(mimeType);
|
|
74
82
|
|
|
75
|
-
if (!shaka.dependencies.muxjs() || !
|
|
83
|
+
if (!shaka.dependencies.muxjs() || (!isTs && !isAac)) {
|
|
76
84
|
return false;
|
|
77
85
|
}
|
|
78
86
|
|
|
87
|
+
if (isAac) {
|
|
88
|
+
return Capabilities.isTypeSupported(Transmuxer.convertAacCodecs_());
|
|
89
|
+
}
|
|
90
|
+
|
|
79
91
|
if (contentType) {
|
|
80
|
-
return
|
|
81
|
-
Transmuxer.
|
|
92
|
+
return Capabilities.isTypeSupported(
|
|
93
|
+
Transmuxer.convertTsCodecs_(contentType, mimeType));
|
|
82
94
|
}
|
|
83
95
|
|
|
84
96
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
85
97
|
|
|
86
|
-
const audioMime = Transmuxer.
|
|
87
|
-
const videoMime = Transmuxer.
|
|
88
|
-
return
|
|
89
|
-
|
|
98
|
+
const audioMime = Transmuxer.convertTsCodecs_(ContentType.AUDIO, mimeType);
|
|
99
|
+
const videoMime = Transmuxer.convertTsCodecs_(ContentType.VIDEO, mimeType);
|
|
100
|
+
return Capabilities.isTypeSupported(audioMime) ||
|
|
101
|
+
Capabilities.isTypeSupported(videoMime);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Check if the mimetype is 'audio/aac'.
|
|
107
|
+
* @param {string} mimeType
|
|
108
|
+
* @return {boolean}
|
|
109
|
+
* @private
|
|
110
|
+
*/
|
|
111
|
+
static isAacContainer_(mimeType) {
|
|
112
|
+
return mimeType.toLowerCase().split(';')[0] == 'audio/aac';
|
|
90
113
|
}
|
|
91
114
|
|
|
92
115
|
|
|
@@ -94,19 +117,48 @@ shaka.media.Transmuxer = class {
|
|
|
94
117
|
* Check if the mimetype contains 'mp2t'.
|
|
95
118
|
* @param {string} mimeType
|
|
96
119
|
* @return {boolean}
|
|
120
|
+
* @private
|
|
97
121
|
*/
|
|
98
|
-
static
|
|
122
|
+
static isTsContainer_(mimeType) {
|
|
99
123
|
return mimeType.toLowerCase().split(';')[0].split('/')[1] == 'mp2t';
|
|
100
124
|
}
|
|
101
125
|
|
|
102
126
|
|
|
127
|
+
/**
|
|
128
|
+
* For any stream, convert its codecs to MP4 codecs.
|
|
129
|
+
* @param {string} contentType
|
|
130
|
+
* @param {string} mimeType
|
|
131
|
+
* @return {string}
|
|
132
|
+
*/
|
|
133
|
+
static convertCodecs(contentType, mimeType) {
|
|
134
|
+
const Transmuxer = shaka.media.Transmuxer;
|
|
135
|
+
if (Transmuxer.isAacContainer_(mimeType)) {
|
|
136
|
+
return Transmuxer.convertAacCodecs_();
|
|
137
|
+
} else if (Transmuxer.isTsContainer_(mimeType)) {
|
|
138
|
+
return Transmuxer.convertTsCodecs_(contentType, mimeType);
|
|
139
|
+
}
|
|
140
|
+
return mimeType;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* For aac stream, convert its codecs to MP4 codecs.
|
|
146
|
+
* @return {string}
|
|
147
|
+
* @private
|
|
148
|
+
*/
|
|
149
|
+
static convertAacCodecs_() {
|
|
150
|
+
return 'audio/mp4; codecs="mp4a.40.2"';
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
|
|
103
154
|
/**
|
|
104
155
|
* For transport stream, convert its codecs to MP4 codecs.
|
|
105
156
|
* @param {string} contentType
|
|
106
157
|
* @param {string} tsMimeType
|
|
107
158
|
* @return {string}
|
|
159
|
+
* @private
|
|
108
160
|
*/
|
|
109
|
-
static
|
|
161
|
+
static convertTsCodecs_(contentType, tsMimeType) {
|
|
110
162
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
111
163
|
let mp4MimeType = tsMimeType.replace(/mp2t/i, 'mp4');
|
|
112
164
|
if (contentType == ContentType.AUDIO) {
|
|
@@ -148,12 +200,20 @@ shaka.media.Transmuxer = class {
|
|
|
148
200
|
}
|
|
149
201
|
|
|
150
202
|
|
|
203
|
+
/**
|
|
204
|
+
* Returns the original mimetype of the transmuxer.
|
|
205
|
+
* @return {string}
|
|
206
|
+
*/
|
|
207
|
+
getOrginalMimeType() {
|
|
208
|
+
return this.originalMimeType_;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
|
|
151
212
|
/**
|
|
152
213
|
* Transmux from Transport stream to MP4, using the mux.js library.
|
|
153
214
|
* @param {BufferSource} data
|
|
154
215
|
* @return {!Promise.<{data: !Uint8Array,
|
|
155
|
-
* captions: !Array.<!muxjs.mp4.ClosedCaption
|
|
156
|
-
* metadata: !Array.<!Object>}>}
|
|
216
|
+
* captions: !Array.<!muxjs.mp4.ClosedCaption>}>}
|
|
157
217
|
*/
|
|
158
218
|
transmux(data) {
|
|
159
219
|
goog.asserts.assert(!this.isTransmuxing_,
|
|
@@ -162,7 +222,6 @@ shaka.media.Transmuxer = class {
|
|
|
162
222
|
this.transmuxPromise_ = new shaka.util.PublicPromise();
|
|
163
223
|
this.transmuxedData_ = [];
|
|
164
224
|
this.captions_ = [];
|
|
165
|
-
this.metadata_ = [];
|
|
166
225
|
|
|
167
226
|
const dataArray = shaka.util.BufferUtils.toUint8(data);
|
|
168
227
|
this.muxTransmuxer_.push(dataArray);
|
|
@@ -200,7 +259,6 @@ shaka.media.Transmuxer = class {
|
|
|
200
259
|
*/
|
|
201
260
|
onTransmuxed_(segment) {
|
|
202
261
|
this.captions_ = segment.captions;
|
|
203
|
-
this.metadata_ = segment.metadata;
|
|
204
262
|
this.transmuxedData_.push(
|
|
205
263
|
shaka.util.Uint8ArrayUtils.concat(segment.initSegment, segment.data));
|
|
206
264
|
}
|
|
@@ -215,7 +273,6 @@ shaka.media.Transmuxer = class {
|
|
|
215
273
|
const output = {
|
|
216
274
|
data: shaka.util.Uint8ArrayUtils.concat(...this.transmuxedData_),
|
|
217
275
|
captions: this.captions_,
|
|
218
|
-
metadata: this.metadata_,
|
|
219
276
|
};
|
|
220
277
|
|
|
221
278
|
this.transmuxPromise_.resolve(output);
|
package/lib/offline/storage.js
CHANGED