jmuxer 2.0.1 → 2.0.4

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/dist/jmuxer.js CHANGED
@@ -1,8 +1,24 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3
- typeof define === 'function' && define.amd ? define(factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.JMuxer = factory());
5
- }(this, (function () { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('stream')) :
3
+ typeof define === 'function' && define.amd ? define(['stream'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.JMuxer = factory(global.stream));
5
+ }(this, (function (stream) { 'use strict';
6
+
7
+ function _typeof(obj) {
8
+ "@babel/helpers - typeof";
9
+
10
+ if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
11
+ _typeof = function (obj) {
12
+ return typeof obj;
13
+ };
14
+ } else {
15
+ _typeof = function (obj) {
16
+ return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
17
+ };
18
+ }
19
+
20
+ return _typeof(obj);
21
+ }
6
22
 
7
23
  function _classCallCheck(instance, Constructor) {
8
24
  if (!(instance instanceof Constructor)) {
@@ -120,6 +136,41 @@
120
136
  };
121
137
  }
122
138
 
139
+ function _slicedToArray(arr, i) {
140
+ return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
141
+ }
142
+
143
+ function _arrayWithHoles(arr) {
144
+ if (Array.isArray(arr)) return arr;
145
+ }
146
+
147
+ function _iterableToArrayLimit(arr, i) {
148
+ if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
149
+ var _arr = [];
150
+ var _n = true;
151
+ var _d = false;
152
+ var _e = undefined;
153
+
154
+ try {
155
+ for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
156
+ _arr.push(_s.value);
157
+
158
+ if (i && _arr.length === i) break;
159
+ }
160
+ } catch (err) {
161
+ _d = true;
162
+ _e = err;
163
+ } finally {
164
+ try {
165
+ if (!_n && _i["return"] != null) _i["return"]();
166
+ } finally {
167
+ if (_d) throw _e;
168
+ }
169
+ }
170
+
171
+ return _arr;
172
+ }
173
+
123
174
  function _unsupportedIterableToArray(o, minLen) {
124
175
  if (!o) return;
125
176
  if (typeof o === "string") return _arrayLikeToArray(o, minLen);
@@ -137,6 +188,10 @@
137
188
  return arr2;
138
189
  }
139
190
 
191
+ function _nonIterableRest() {
192
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
193
+ }
194
+
140
195
  function _createForOfIteratorHelper(o, allowArrayLike) {
141
196
  var it;
142
197
 
@@ -301,7 +356,7 @@
301
356
  }, {
302
357
  key: "isKeyframe",
303
358
  value: function isKeyframe() {
304
- return this.ntype === NALU.IDR || this.stype === 7;
359
+ return this.ntype === NALU.IDR;
305
360
  }
306
361
  }, {
307
362
  key: "getPayload",
@@ -332,6 +387,30 @@
332
387
  return NALU;
333
388
  }();
334
389
 
390
+ function appendByteArray(buffer1, buffer2) {
391
+ var tmp = new Uint8Array((buffer1.byteLength | 0) + (buffer2.byteLength | 0));
392
+ tmp.set(buffer1, 0);
393
+ tmp.set(buffer2, buffer1.byteLength | 0);
394
+ return tmp;
395
+ }
396
+ function secToTime(sec) {
397
+ var seconds,
398
+ hours,
399
+ minutes,
400
+ result = '';
401
+ seconds = Math.floor(sec);
402
+ hours = parseInt(seconds / 3600, 10) % 24;
403
+ minutes = parseInt(seconds / 60, 10) % 60;
404
+ seconds = seconds < 0 ? 0 : seconds % 60;
405
+
406
+ if (hours > 0) {
407
+ result += (hours < 10 ? '0' + hours : hours) + ':';
408
+ }
409
+
410
+ result += (minutes < 10 ? '0' + minutes : minutes) + ':' + (seconds < 10 ? '0' + seconds : seconds);
411
+ return result;
412
+ }
413
+
335
414
  /**
336
415
  * Parser for exponential Golomb codes, a variable-bitwidth number encoding scheme used by h264.
337
416
  */
@@ -478,7 +557,8 @@
478
557
  value,
479
558
  state = 0,
480
559
  result = [],
481
- lastIndex;
560
+ left,
561
+ lastIndex = 0;
482
562
 
483
563
  while (i < length) {
484
564
  value = buffer[i++]; // finding 3 or 4-byte start codes (00 00 01 OR 00 00 00 01)
@@ -505,7 +585,7 @@
505
585
  if (value === 0) {
506
586
  state = 3;
507
587
  } else if (value === 1 && i < length) {
508
- if (lastIndex) {
588
+ if (lastIndex != i - state - 1) {
509
589
  result.push(buffer.subarray(lastIndex, i - state - 1));
510
590
  }
511
591
 
@@ -519,11 +599,11 @@
519
599
  }
520
600
  }
521
601
 
522
- if (lastIndex) {
523
- result.push(buffer.subarray(lastIndex, length));
602
+ if (lastIndex < length) {
603
+ left = buffer.subarray(lastIndex, length);
524
604
  }
525
605
 
526
- return result;
606
+ return [result, left];
527
607
  }
528
608
  /**
529
609
  * Advance the ExpGolomb decoder past a scaling list. The scaling
@@ -1536,23 +1616,13 @@
1536
1616
 
1537
1617
  var track_id = 1;
1538
1618
  var BaseRemuxer = /*#__PURE__*/function () {
1539
- _createClass(BaseRemuxer, null, [{
1540
- key: "getTrackID",
1541
- value: function getTrackID() {
1542
- return track_id++;
1543
- }
1544
- }]);
1545
-
1546
1619
  function BaseRemuxer() {
1547
1620
  _classCallCheck(this, BaseRemuxer);
1548
-
1549
- this.seq = 1;
1550
1621
  }
1551
1622
 
1552
1623
  _createClass(BaseRemuxer, [{
1553
1624
  key: "flush",
1554
1625
  value: function flush() {
1555
- this.seq++;
1556
1626
  this.mp4track.len = 0;
1557
1627
  this.mp4track.samples = [];
1558
1628
  }
@@ -1562,6 +1632,11 @@
1562
1632
  if (!this.readyToDecode || !this.samples.length) return null;
1563
1633
  return true;
1564
1634
  }
1635
+ }], [{
1636
+ key: "getTrackID",
1637
+ value: function getTrackID() {
1638
+ return track_id++;
1639
+ }
1565
1640
  }]);
1566
1641
 
1567
1642
  return BaseRemuxer;
@@ -1572,7 +1647,7 @@
1572
1647
 
1573
1648
  var _super = _createSuper(AACRemuxer);
1574
1649
 
1575
- function AACRemuxer() {
1650
+ function AACRemuxer(timescale) {
1576
1651
  var _this;
1577
1652
 
1578
1653
  _classCallCheck(this, AACRemuxer);
@@ -1581,15 +1656,14 @@
1581
1656
  _this.readyToDecode = false;
1582
1657
  _this.nextDts = 0;
1583
1658
  _this.dts = 0;
1584
- _this.timescale = 1000;
1585
1659
  _this.mp4track = {
1586
1660
  id: BaseRemuxer.getTrackID(),
1587
1661
  type: 'audio',
1588
1662
  channelCount: 0,
1589
1663
  len: 0,
1590
1664
  fragmented: true,
1591
- timescale: _this.timescale,
1592
- duration: _this.timescale,
1665
+ timescale: timescale,
1666
+ duration: timescale,
1593
1667
  samples: [],
1594
1668
  config: '',
1595
1669
  codec: ''
@@ -1607,6 +1681,8 @@
1607
1681
  this.mp4track.channelCount = '';
1608
1682
  this.mp4track.config = '';
1609
1683
  this.mp4track.timescale = this.timescale;
1684
+ this.nextDts = 0;
1685
+ this.dts = 0;
1610
1686
  }
1611
1687
  }, {
1612
1688
  key: "remux",
@@ -1684,7 +1760,7 @@
1684
1760
 
1685
1761
  var _super = _createSuper(H264Remuxer);
1686
1762
 
1687
- function H264Remuxer() {
1763
+ function H264Remuxer(timescale) {
1688
1764
  var _this;
1689
1765
 
1690
1766
  _classCallCheck(this, H264Remuxer);
@@ -1693,7 +1769,6 @@
1693
1769
  _this.readyToDecode = false;
1694
1770
  _this.nextDts = 0;
1695
1771
  _this.dts = 0;
1696
- _this.timescale = 1000;
1697
1772
  _this.mp4track = {
1698
1773
  id: BaseRemuxer.getTrackID(),
1699
1774
  type: 'video',
@@ -1703,8 +1778,8 @@
1703
1778
  pps: '',
1704
1779
  width: 0,
1705
1780
  height: 0,
1706
- timescale: _this.timescale,
1707
- duration: _this.timescale,
1781
+ timescale: timescale,
1782
+ duration: timescale,
1708
1783
  samples: []
1709
1784
  };
1710
1785
  _this.samples = [];
@@ -1718,6 +1793,8 @@
1718
1793
  this.readyToDecode = false;
1719
1794
  this.mp4track.sps = '';
1720
1795
  this.mp4track.pps = '';
1796
+ this.nextDts = 0;
1797
+ this.dts = 0;
1721
1798
  }
1722
1799
  }, {
1723
1800
  key: "remux",
@@ -1830,36 +1907,12 @@
1830
1907
  return H264Remuxer;
1831
1908
  }(BaseRemuxer);
1832
1909
 
1833
- function appendByteArray(buffer1, buffer2) {
1834
- var tmp = new Uint8Array((buffer1.byteLength | 0) + (buffer2.byteLength | 0));
1835
- tmp.set(buffer1, 0);
1836
- tmp.set(buffer2, buffer1.byteLength | 0);
1837
- return tmp;
1838
- }
1839
- function secToTime(sec) {
1840
- var seconds,
1841
- hours,
1842
- minutes,
1843
- result = '';
1844
- seconds = Math.floor(sec);
1845
- hours = parseInt(seconds / 3600, 10) % 24;
1846
- minutes = parseInt(seconds / 60, 10) % 60;
1847
- seconds = seconds < 0 ? 0 : seconds % 60;
1848
-
1849
- if (hours > 0) {
1850
- result += (hours < 10 ? '0' + hours : hours) + ':';
1851
- }
1852
-
1853
- result += (minutes < 10 ? '0' + minutes : minutes) + ':' + (seconds < 10 ? '0' + seconds : seconds);
1854
- return result;
1855
- }
1856
-
1857
1910
  var RemuxController = /*#__PURE__*/function (_Event) {
1858
1911
  _inherits(RemuxController, _Event);
1859
1912
 
1860
1913
  var _super = _createSuper(RemuxController);
1861
1914
 
1862
- function RemuxController(streaming) {
1915
+ function RemuxController(env) {
1863
1916
  var _this;
1864
1917
 
1865
1918
  _classCallCheck(this, RemuxController);
@@ -1868,7 +1921,10 @@
1868
1921
  _this.initialized = false;
1869
1922
  _this.trackTypes = [];
1870
1923
  _this.tracks = {};
1871
- _this.mediaDuration = streaming ? Infinity : 1000;
1924
+ _this.seq = 1;
1925
+ _this.env = env;
1926
+ _this.timescale = 1000;
1927
+ _this.mediaDuration = 0;
1872
1928
  return _this;
1873
1929
  }
1874
1930
 
@@ -1876,12 +1932,12 @@
1876
1932
  key: "addTrack",
1877
1933
  value: function addTrack(type) {
1878
1934
  if (type === 'video' || type === 'both') {
1879
- this.tracks.video = new H264Remuxer();
1935
+ this.tracks.video = new H264Remuxer(this.timescale);
1880
1936
  this.trackTypes.push('video');
1881
1937
  }
1882
1938
 
1883
1939
  if (type === 'audio' || type === 'both') {
1884
- this.tracks.audio = new AACRemuxer();
1940
+ this.tracks.audio = new AACRemuxer(this.timescale);
1885
1941
  this.trackTypes.push('audio');
1886
1942
  }
1887
1943
  }
@@ -1916,64 +1972,82 @@
1916
1972
  if (!this.initialized) {
1917
1973
  if (this.isReady()) {
1918
1974
  this.dispatch('ready');
1919
-
1920
- var _iterator2 = _createForOfIteratorHelper(this.trackTypes),
1921
- _step2;
1922
-
1923
- try {
1924
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
1925
- var type = _step2.value;
1926
- var track = this.tracks[type];
1927
- var data = {
1928
- type: type,
1929
- payload: MP4.initSegment([track.mp4track], this.mediaDuration, track.mp4track.timescale)
1930
- };
1931
- this.dispatch('buffer', data);
1932
- }
1933
- } catch (err) {
1934
- _iterator2.e(err);
1935
- } finally {
1936
- _iterator2.f();
1937
- }
1938
-
1939
- log('Initial segment generated.');
1975
+ this.initSegment();
1940
1976
  this.initialized = true;
1941
1977
  this.flush();
1942
1978
  }
1943
1979
  } else {
1944
- var _iterator3 = _createForOfIteratorHelper(this.trackTypes),
1945
- _step3;
1980
+ var _iterator2 = _createForOfIteratorHelper(this.trackTypes),
1981
+ _step2;
1946
1982
 
1947
1983
  try {
1948
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
1949
- var _type = _step3.value;
1950
- var _track = this.tracks[_type];
1951
-
1952
- var pay = _track.getPayload();
1984
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
1985
+ var type = _step2.value;
1986
+ var track = this.tracks[type];
1987
+ var pay = track.getPayload();
1953
1988
 
1954
1989
  if (pay && pay.byteLength) {
1955
- var moof = MP4.moof(_track.seq, _track.dts, _track.mp4track);
1990
+ var moof = MP4.moof(this.seq, track.dts, track.mp4track);
1956
1991
  var mdat = MP4.mdat(pay);
1957
1992
  var payload = appendByteArray(moof, mdat);
1958
- var _data = {
1959
- type: _type,
1993
+ var data = {
1994
+ type: type,
1960
1995
  payload: payload,
1961
- dts: _track.dts
1996
+ dts: track.dts
1962
1997
  };
1963
- this.dispatch('buffer', _data);
1964
- var duration = secToTime(_track.dts / 1000);
1965
- log("put segment (".concat(_type, "): ").concat(_track.seq, " dts: ").concat(_track.dts, " gop: ").concat(_track.mp4track.samples.length, " second: ").concat(duration));
1966
-
1967
- _track.flush();
1998
+ this.dispatch('buffer', data);
1999
+ var duration = secToTime(track.dts / this.timescale);
2000
+ log("put segment (".concat(type, "): dts: ").concat(track.dts, " frames: ").concat(track.mp4track.samples.length, " second: ").concat(duration));
2001
+ track.flush();
2002
+ this.seq++;
1968
2003
  }
1969
2004
  }
1970
2005
  } catch (err) {
1971
- _iterator3.e(err);
2006
+ _iterator2.e(err);
1972
2007
  } finally {
1973
- _iterator3.f();
2008
+ _iterator2.f();
1974
2009
  }
1975
2010
  }
1976
2011
  }
2012
+ }, {
2013
+ key: "initSegment",
2014
+ value: function initSegment() {
2015
+ var tracks = [];
2016
+
2017
+ var _iterator3 = _createForOfIteratorHelper(this.trackTypes),
2018
+ _step3;
2019
+
2020
+ try {
2021
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
2022
+ var type = _step3.value;
2023
+ var track = this.tracks[type];
2024
+
2025
+ if (this.env == 'browser') {
2026
+ var _data = {
2027
+ type: type,
2028
+ payload: MP4.initSegment([track.mp4track], this.mediaDuration, this.timescale)
2029
+ };
2030
+ this.dispatch('buffer', _data);
2031
+ } else {
2032
+ tracks.push(track.mp4track);
2033
+ }
2034
+ }
2035
+ } catch (err) {
2036
+ _iterator3.e(err);
2037
+ } finally {
2038
+ _iterator3.f();
2039
+ }
2040
+
2041
+ if (this.env == 'node') {
2042
+ var data = {
2043
+ type: 'all',
2044
+ payload: MP4.initSegment(tracks, this.mediaDuration, this.timescale)
2045
+ };
2046
+ this.dispatch('buffer', data);
2047
+ }
2048
+
2049
+ log('Initial segment generated.');
2050
+ }
1977
2051
  }, {
1978
2052
  key: "isReady",
1979
2053
  value: function isReady() {
@@ -2155,98 +2229,140 @@
2155
2229
  return BufferController;
2156
2230
  }(Event);
2157
2231
 
2158
- window.MediaSource = window.MediaSource || window.WebKitMediaSource;
2232
+ var JMuxer = /*#__PURE__*/function (_Event) {
2233
+ _inherits(JMuxer, _Event);
2159
2234
 
2160
- var JMuxmer = /*#__PURE__*/function (_Event) {
2161
- _inherits(JMuxmer, _Event);
2235
+ var _super = _createSuper(JMuxer);
2162
2236
 
2163
- var _super = _createSuper(JMuxmer);
2164
-
2165
- _createClass(JMuxmer, null, [{
2237
+ _createClass(JMuxer, null, [{
2166
2238
  key: "isSupported",
2167
2239
  value: function isSupported(codec) {
2168
2240
  return window.MediaSource && window.MediaSource.isTypeSupported(codec);
2169
2241
  }
2170
2242
  }]);
2171
2243
 
2172
- function JMuxmer(options) {
2244
+ function JMuxer(options) {
2173
2245
  var _this;
2174
2246
 
2175
- _classCallCheck(this, JMuxmer);
2247
+ _classCallCheck(this, JMuxer);
2176
2248
 
2177
2249
  _this = _super.call(this, 'jmuxer');
2178
- window.MediaSource = window.MediaSource || window.WebKitMediaSource;
2179
2250
  var defaults = {
2180
2251
  node: '',
2181
2252
  mode: 'both',
2182
2253
  // both, audio, video
2183
2254
  flushingTime: 1500,
2184
2255
  clearBuffer: true,
2185
- onReady: null,
2186
- // function called when MSE is ready to accept frames
2187
2256
  fps: 30,
2188
- debug: false
2257
+ debug: false,
2258
+ onReady: function onReady() {},
2259
+ // function called when MSE is ready to accept frames
2260
+ onError: function onError() {} // function called when jmuxer encounters any buffer related error
2261
+
2189
2262
  };
2190
2263
  _this.options = Object.assign({}, defaults, options);
2264
+ _this.env = (typeof process === "undefined" ? "undefined" : _typeof(process)) === 'object' && typeof window === 'undefined' ? 'node' : 'browser';
2191
2265
 
2192
2266
  if (_this.options.debug) {
2193
2267
  setLogger();
2194
2268
  }
2195
2269
 
2196
- if (typeof _this.options.node === 'string' && _this.options.node == '') {
2197
- error('no video element were found to render, provide a valid video element');
2198
- }
2199
-
2200
2270
  if (!_this.options.fps) {
2201
2271
  _this.options.fps = 30;
2202
2272
  }
2203
2273
 
2204
- _this.frameDuration = 1000 / _this.options.fps | 0; // todo remove
2205
-
2206
- _this.node = typeof _this.options.node === 'string' ? document.getElementById(_this.options.node) : _this.options.node;
2207
- _this.sourceBuffers = {};
2208
- _this.isMSESupported = !!window.MediaSource;
2209
-
2210
- if (!_this.isMSESupported) {
2211
- throw 'Oops! Browser does not support media source extension.';
2212
- }
2213
-
2214
- _this.setupMSE();
2215
-
2216
- _this.remuxController = new RemuxController(_this.options.clearBuffer);
2274
+ _this.frameDuration = 1000 / _this.options.fps | 0;
2275
+ _this.remuxController = new RemuxController(_this.env);
2217
2276
 
2218
2277
  _this.remuxController.addTrack(_this.options.mode);
2219
2278
 
2220
- _this.mseReady = false;
2221
2279
  _this.lastCleaningTime = Date.now();
2222
2280
  _this.kfPosition = [];
2223
2281
  _this.kfCounter = 0;
2282
+ _this.pendingUnits = {};
2283
+ _this.remainingData = new Uint8Array();
2224
2284
  /* events callback */
2225
2285
 
2226
2286
  _this.remuxController.on('buffer', _this.onBuffer.bind(_assertThisInitialized(_this)));
2227
2287
 
2228
- _this.remuxController.on('ready', _this.createBuffer.bind(_assertThisInitialized(_this)));
2288
+ if (_this.env == 'browser') {
2289
+ _this.remuxController.on('ready', _this.createBuffer.bind(_assertThisInitialized(_this)));
2290
+
2291
+ _this.initBrowser();
2292
+ }
2229
2293
 
2230
2294
  _this.startInterval();
2231
2295
 
2232
2296
  return _this;
2233
2297
  }
2234
2298
 
2235
- _createClass(JMuxmer, [{
2299
+ _createClass(JMuxer, [{
2300
+ key: "initBrowser",
2301
+ value: function initBrowser() {
2302
+ if (typeof this.options.node === 'string' && this.options.node == '') {
2303
+ error('no video element were found to render, provide a valid video element');
2304
+ }
2305
+
2306
+ this.node = typeof this.options.node === 'string' ? document.getElementById(this.options.node) : this.options.node;
2307
+ this.mseReady = false;
2308
+ this.setupMSE();
2309
+ }
2310
+ }, {
2311
+ key: "createStream",
2312
+ value: function createStream() {
2313
+ var feed = this.feed.bind(this);
2314
+ var destroy = this.destroy.bind(this);
2315
+ this.stream = new stream.Duplex({
2316
+ writableObjectMode: true,
2317
+ read: function read(size) {},
2318
+ write: function write(data, encoding, callback) {
2319
+ feed(data);
2320
+ callback();
2321
+ },
2322
+ "final": function final(callback) {
2323
+ destroy();
2324
+ callback();
2325
+ }
2326
+ });
2327
+ return this.stream;
2328
+ }
2329
+ }, {
2236
2330
  key: "setupMSE",
2237
2331
  value: function setupMSE() {
2332
+ window.MediaSource = window.MediaSource || window.WebKitMediaSource;
2333
+
2334
+ if (!window.MediaSource) {
2335
+ throw 'Oops! Browser does not support media source extension.';
2336
+ }
2337
+
2338
+ this.isMSESupported = !!window.MediaSource;
2238
2339
  this.mediaSource = new MediaSource();
2239
- this.node.src = URL.createObjectURL(this.mediaSource);
2340
+ this.url = URL.createObjectURL(this.mediaSource);
2341
+ this.node.src = this.url;
2342
+ this.mseEnded = false;
2240
2343
  this.mediaSource.addEventListener('sourceopen', this.onMSEOpen.bind(this));
2241
2344
  this.mediaSource.addEventListener('sourceclose', this.onMSEClose.bind(this));
2242
2345
  this.mediaSource.addEventListener('webkitsourceopen', this.onMSEOpen.bind(this));
2243
2346
  this.mediaSource.addEventListener('webkitsourceclose', this.onMSEClose.bind(this));
2244
2347
  }
2348
+ }, {
2349
+ key: "endMSE",
2350
+ value: function endMSE() {
2351
+ if (!this.mseEnded) {
2352
+ try {
2353
+ this.mseEnded = true;
2354
+ this.mediaSource.endOfStream();
2355
+ } catch (e) {
2356
+ error('mediasource is not available to end');
2357
+ }
2358
+ }
2359
+ }
2245
2360
  }, {
2246
2361
  key: "feed",
2247
2362
  value: function feed(data) {
2248
2363
  var remux = false,
2249
2364
  slices,
2365
+ left,
2250
2366
  duration,
2251
2367
  chunks = {
2252
2368
  video: [],
@@ -2256,12 +2372,21 @@
2256
2372
  duration = data.duration ? parseInt(data.duration) : 0;
2257
2373
 
2258
2374
  if (data.video) {
2259
- slices = H264Parser.extractNALu(data.video);
2375
+ data.video = appendByteArray(this.remainingData, data.video);
2376
+
2377
+ var _H264Parser$extractNA = H264Parser.extractNALu(data.video);
2378
+
2379
+ var _H264Parser$extractNA2 = _slicedToArray(_H264Parser$extractNA, 2);
2380
+
2381
+ slices = _H264Parser$extractNA2[0];
2382
+ left = _H264Parser$extractNA2[1];
2260
2383
 
2261
2384
  if (slices.length > 0) {
2262
2385
  chunks.video = this.getVideoFrames(slices, duration);
2263
2386
  remux = true;
2264
2387
  }
2388
+
2389
+ this.remainingData = left || new Uint8Array();
2265
2390
  }
2266
2391
 
2267
2392
  if (data.audio) {
@@ -2292,6 +2417,13 @@
2292
2417
  keyFrame = false,
2293
2418
  vcl = false;
2294
2419
 
2420
+ if (this.pendingUnits.units) {
2421
+ units = this.pendingUnits.units;
2422
+ vcl = this.pendingUnits.vcl;
2423
+ keyFrame = this.pendingUnits.keyFrame;
2424
+ this.pendingUnits = {};
2425
+ }
2426
+
2295
2427
  var _iterator = _createForOfIteratorHelper(nalus),
2296
2428
  _step;
2297
2429
 
@@ -2325,7 +2457,14 @@
2325
2457
  }
2326
2458
 
2327
2459
  if (units.length) {
2328
- if (vcl || !frames.length) {
2460
+ // lets keep indecisive nalus as pending in case of fixed fps
2461
+ if (!duration) {
2462
+ this.pendingUnits = {
2463
+ units: units,
2464
+ keyFrame: keyFrame,
2465
+ vcl: vcl
2466
+ };
2467
+ } else if (vcl) {
2329
2468
  frames.push({
2330
2469
  units: units,
2331
2470
  keyFrame: keyFrame
@@ -2395,16 +2534,10 @@
2395
2534
  value: function destroy() {
2396
2535
  this.stopInterval();
2397
2536
 
2398
- if (this.mediaSource) {
2399
- try {
2400
- if (this.bufferControllers) {
2401
- this.mediaSource.endOfStream();
2402
- }
2403
- } catch (e) {
2404
- error("mediasource is not available to end ".concat(e.message));
2405
- }
2406
-
2407
- this.mediaSource = null;
2537
+ if (this.stream) {
2538
+ this.remuxController.flush();
2539
+ this.stream.push(null);
2540
+ this.stream = null;
2408
2541
  }
2409
2542
 
2410
2543
  if (this.remuxController) {
@@ -2418,11 +2551,37 @@
2418
2551
  }
2419
2552
 
2420
2553
  this.bufferControllers = null;
2554
+ this.endMSE();
2421
2555
  }
2422
2556
 
2423
2557
  this.node = false;
2424
2558
  this.mseReady = false;
2425
2559
  this.videoStarted = false;
2560
+ this.mediaSource = null;
2561
+ }
2562
+ }, {
2563
+ key: "reset",
2564
+ value: function reset() {
2565
+ this.node.pause();
2566
+
2567
+ if (this.remuxController) {
2568
+ this.remuxController.reset();
2569
+ }
2570
+
2571
+ if (this.bufferControllers) {
2572
+ for (var type in this.bufferControllers) {
2573
+ this.bufferControllers[type].destroy();
2574
+ }
2575
+
2576
+ this.bufferControllers = null;
2577
+ this.endMSE();
2578
+ }
2579
+
2580
+ if (this.env == 'browser') {
2581
+ this.initBrowser();
2582
+ }
2583
+
2584
+ log('JMuxer was reset');
2426
2585
  }
2427
2586
  }, {
2428
2587
  key: "createBuffer",
@@ -2433,14 +2592,13 @@
2433
2592
  for (var type in this.remuxController.tracks) {
2434
2593
  var track = this.remuxController.tracks[type];
2435
2594
 
2436
- if (!JMuxmer.isSupported("".concat(type, "/mp4; codecs=\"").concat(track.mp4track.codec, "\""))) {
2595
+ if (!JMuxer.isSupported("".concat(type, "/mp4; codecs=\"").concat(track.mp4track.codec, "\""))) {
2437
2596
  error('Browser does not support codec');
2438
2597
  return false;
2439
2598
  }
2440
2599
 
2441
2600
  var sb = this.mediaSource.addSourceBuffer("".concat(type, "/mp4; codecs=\"").concat(track.mp4track.codec, "\""));
2442
2601
  this.bufferControllers[type] = new BufferController(sb, type);
2443
- this.sourceBuffers[type] = sb;
2444
2602
  this.bufferControllers[type].on('error', this.onBufferError.bind(this));
2445
2603
  }
2446
2604
  }
@@ -2512,8 +2670,12 @@
2512
2670
  }, {
2513
2671
  key: "onBuffer",
2514
2672
  value: function onBuffer(data) {
2515
- if (this.bufferControllers && this.bufferControllers[data.type]) {
2516
- this.bufferControllers[data.type].feed(data.payload);
2673
+ if (this.env == 'browser') {
2674
+ if (this.bufferControllers && this.bufferControllers[data.type]) {
2675
+ this.bufferControllers[data.type].feed(data.payload);
2676
+ }
2677
+ } else if (this.stream) {
2678
+ this.stream.push(data.payload);
2517
2679
  }
2518
2680
  }
2519
2681
  /* Events on MSE */
@@ -2524,10 +2686,10 @@
2524
2686
  this.mseReady = true;
2525
2687
 
2526
2688
  if (typeof this.options.onReady === 'function') {
2527
- this.options.onReady();
2528
- this.options.onReady = null;
2689
+ this.options.onReady.call(null);
2529
2690
  }
2530
2691
 
2692
+ URL.revokeObjectURL(this.url);
2531
2693
  this.createBuffer();
2532
2694
  }
2533
2695
  }, {
@@ -2542,25 +2704,19 @@
2542
2704
  if (data.name == 'QuotaExceeded') {
2543
2705
  this.bufferControllers[data.type].initCleanup(this.node.currentTime);
2544
2706
  return;
2707
+ } else {
2708
+ this.endMSE();
2545
2709
  }
2546
2710
 
2547
- if (this.mediaSource.sourceBuffers.length > 0 && this.sourceBuffers[data.type]) {
2548
- this.mediaSource.removeSourceBuffer(this.sourceBuffers[data.type]);
2549
- }
2550
-
2551
- if (this.mediaSource.sourceBuffers.length == 0) {
2552
- try {
2553
- this.mediaSource.endOfStream();
2554
- } catch (e) {
2555
- error('mediasource is not available to end');
2556
- }
2711
+ if (typeof this.options.onError === 'function') {
2712
+ this.options.onError.call(null, data);
2557
2713
  }
2558
2714
  }
2559
2715
  }]);
2560
2716
 
2561
- return JMuxmer;
2717
+ return JMuxer;
2562
2718
  }(Event);
2563
2719
 
2564
- return JMuxmer;
2720
+ return JMuxer;
2565
2721
 
2566
2722
  })));