jmuxer.min.js 74 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564
  1. var JMuxer = (function () {
  2. 'use strict';
  3. function _classCallCheck(instance, Constructor) {
  4. if (!(instance instanceof Constructor)) {
  5. throw new TypeError("Cannot call a class as a function");
  6. }
  7. }
  8. function _defineProperties(target, props) {
  9. for (var i = 0; i < props.length; i++) {
  10. var descriptor = props[i];
  11. descriptor.enumerable = descriptor.enumerable || false;
  12. descriptor.configurable = true;
  13. if ("value" in descriptor) descriptor.writable = true;
  14. Object.defineProperty(target, descriptor.key, descriptor);
  15. }
  16. }
  17. function _createClass(Constructor, protoProps, staticProps) {
  18. if (protoProps) _defineProperties(Constructor.prototype, protoProps);
  19. if (staticProps) _defineProperties(Constructor, staticProps);
  20. return Constructor;
  21. }
  22. function _defineProperty(obj, key, value) {
  23. if (key in obj) {
  24. Object.defineProperty(obj, key, {
  25. value: value,
  26. enumerable: true,
  27. configurable: true,
  28. writable: true
  29. });
  30. } else {
  31. obj[key] = value;
  32. }
  33. return obj;
  34. }
  35. function _inherits(subClass, superClass) {
  36. if (typeof superClass !== "function" && superClass !== null) {
  37. throw new TypeError("Super expression must either be null or a function");
  38. }
  39. subClass.prototype = Object.create(superClass && superClass.prototype, {
  40. constructor: {
  41. value: subClass,
  42. writable: true,
  43. configurable: true
  44. }
  45. });
  46. if (superClass) _setPrototypeOf(subClass, superClass);
  47. }
  48. function _getPrototypeOf(o) {
  49. _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
  50. return o.__proto__ || Object.getPrototypeOf(o);
  51. };
  52. return _getPrototypeOf(o);
  53. }
  54. function _setPrototypeOf(o, p) {
  55. _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
  56. o.__proto__ = p;
  57. return o;
  58. };
  59. return _setPrototypeOf(o, p);
  60. }
  61. function _isNativeReflectConstruct() {
  62. if (typeof Reflect === "undefined" || !Reflect.construct) return false;
  63. if (Reflect.construct.sham) return false;
  64. if (typeof Proxy === "function") return true;
  65. try {
  66. Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
  67. return true;
  68. } catch (e) {
  69. return false;
  70. }
  71. }
  72. function _assertThisInitialized(self) {
  73. if (self === void 0) {
  74. throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  75. }
  76. return self;
  77. }
  78. function _possibleConstructorReturn(self, call) {
  79. if (call && (typeof call === "object" || typeof call === "function")) {
  80. return call;
  81. }
  82. return _assertThisInitialized(self);
  83. }
  84. function _createSuper(Derived) {
  85. var hasNativeReflectConstruct = _isNativeReflectConstruct();
  86. return function _createSuperInternal() {
  87. var Super = _getPrototypeOf(Derived),
  88. result;
  89. if (hasNativeReflectConstruct) {
  90. var NewTarget = _getPrototypeOf(this).constructor;
  91. result = Reflect.construct(Super, arguments, NewTarget);
  92. } else {
  93. result = Super.apply(this, arguments);
  94. }
  95. return _possibleConstructorReturn(this, result);
  96. };
  97. }
  98. function _unsupportedIterableToArray(o, minLen) {
  99. if (!o) return;
  100. if (typeof o === "string") return _arrayLikeToArray(o, minLen);
  101. var n = Object.prototype.toString.call(o).slice(8, -1);
  102. if (n === "Object" && o.constructor) n = o.constructor.name;
  103. if (n === "Map" || n === "Set") return Array.from(o);
  104. if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
  105. }
  106. function _arrayLikeToArray(arr, len) {
  107. if (len == null || len > arr.length) len = arr.length;
  108. for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
  109. return arr2;
  110. }
  111. function _createForOfIteratorHelper(o, allowArrayLike) {
  112. var it;
  113. if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) {
  114. if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
  115. if (it) o = it;
  116. var i = 0;
  117. var F = function () {};
  118. return {
  119. s: F,
  120. n: function () {
  121. if (i >= o.length) return {
  122. done: true
  123. };
  124. return {
  125. done: false,
  126. value: o[i++]
  127. };
  128. },
  129. e: function (e) {
  130. throw e;
  131. },
  132. f: F
  133. };
  134. }
  135. throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  136. }
  137. var normalCompletion = true,
  138. didErr = false,
  139. err;
  140. return {
  141. s: function () {
  142. it = o[Symbol.iterator]();
  143. },
  144. n: function () {
  145. var step = it.next();
  146. normalCompletion = step.done;
  147. return step;
  148. },
  149. e: function (e) {
  150. didErr = true;
  151. err = e;
  152. },
  153. f: function () {
  154. try {
  155. if (!normalCompletion && it.return != null) it.return();
  156. } finally {
  157. if (didErr) throw err;
  158. }
  159. }
  160. };
  161. }
  162. var logger;
  163. var errorLogger;
  164. function setLogger() {
  165. /*eslint-disable */
  166. logger = console.log;
  167. errorLogger = console.error;
  168. /*eslint-enable */
  169. }
  170. function log(message) {
  171. if (logger) {
  172. for (var _len = arguments.length, optionalParams = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  173. optionalParams[_key - 1] = arguments[_key];
  174. }
  175. logger.apply(void 0, [message].concat(optionalParams));
  176. }
  177. }
  178. function error(message) {
  179. if (errorLogger) {
  180. for (var _len2 = arguments.length, optionalParams = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
  181. optionalParams[_key2 - 1] = arguments[_key2];
  182. }
  183. errorLogger.apply(void 0, [message].concat(optionalParams));
  184. }
  185. }
  186. var NALU = /*#__PURE__*/function () {
  187. _createClass(NALU, null, [{
  188. key: "type",
  189. value: function type(nalu) {
  190. if (nalu.ntype in NALU.TYPES) {
  191. return NALU.TYPES[nalu.ntype];
  192. } else {
  193. return 'UNKNOWN';
  194. }
  195. }
  196. }, {
  197. key: "NDR",
  198. get: function get() {
  199. return 1;
  200. }
  201. }, {
  202. key: "IDR",
  203. get: function get() {
  204. return 5;
  205. }
  206. }, {
  207. key: "SEI",
  208. get: function get() {
  209. return 6;
  210. }
  211. }, {
  212. key: "SPS",
  213. get: function get() {
  214. return 7;
  215. }
  216. }, {
  217. key: "PPS",
  218. get: function get() {
  219. return 8;
  220. }
  221. }, {
  222. key: "AUD",
  223. get: function get() {
  224. return 9;
  225. }
  226. }, {
  227. key: "TYPES",
  228. get: function get() {
  229. var _ref;
  230. return _ref = {}, _defineProperty(_ref, NALU.IDR, 'IDR'), _defineProperty(_ref, NALU.SEI, 'SEI'), _defineProperty(_ref, NALU.SPS, 'SPS'), _defineProperty(_ref, NALU.PPS, 'PPS'), _defineProperty(_ref, NALU.NDR, 'NDR'), _defineProperty(_ref, NALU.AUD, 'AUD'), _ref;
  231. }
  232. }]);
  233. function NALU(data) {
  234. _classCallCheck(this, NALU);
  235. this.payload = data;
  236. this.nri = (this.payload[0] & 0x60) >> 5; // nal_ref_idc
  237. this.ntype = this.payload[0] & 0x1f;
  238. this.isvcl = this.ntype == 1 || this.ntype == 5;
  239. this.stype = ''; // slice_type
  240. this.isfmb = false; // first_mb_in_slice
  241. }
  242. _createClass(NALU, [{
  243. key: "toString",
  244. value: function toString() {
  245. return "".concat(NALU.type(this), ": NRI: ").concat(this.getNri());
  246. }
  247. }, {
  248. key: "getNri",
  249. value: function getNri() {
  250. return this.nri;
  251. }
  252. }, {
  253. key: "type",
  254. value: function type() {
  255. return this.ntype;
  256. }
  257. }, {
  258. key: "isKeyframe",
  259. value: function isKeyframe() {
  260. return this.ntype === NALU.IDR || this.stype === 7;
  261. }
  262. }, {
  263. key: "getPayload",
  264. value: function getPayload() {
  265. return this.payload;
  266. }
  267. }, {
  268. key: "getPayloadSize",
  269. value: function getPayloadSize() {
  270. return this.payload.byteLength;
  271. }
  272. }, {
  273. key: "getSize",
  274. value: function getSize() {
  275. return 4 + this.getPayloadSize();
  276. }
  277. }, {
  278. key: "getData",
  279. value: function getData() {
  280. var result = new Uint8Array(this.getSize());
  281. var view = new DataView(result.buffer);
  282. view.setUint32(0, this.getSize() - 4);
  283. result.set(this.getPayload(), 4);
  284. return result;
  285. }
  286. }]);
  287. return NALU;
  288. }();
  289. /**
  290. * Parser for exponential Golomb codes, a variable-bitwidth number encoding scheme used by h264.
  291. */
  292. var ExpGolomb = /*#__PURE__*/function () {
  293. function ExpGolomb(data) {
  294. _classCallCheck(this, ExpGolomb);
  295. this.data = data;
  296. this.index = 0;
  297. this.bitLength = data.byteLength * 8;
  298. }
  299. _createClass(ExpGolomb, [{
  300. key: "skipBits",
  301. value: function skipBits(size) {
  302. // console.log(` skip bits: size=${size}, ${this.index}.`);
  303. if (this.bitsAvailable < size) {
  304. //throw new Error('no bytes available');
  305. return false;
  306. }
  307. this.index += size;
  308. }
  309. }, {
  310. key: "readBits",
  311. value: function readBits(size) {
  312. var moveIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
  313. // console.log(` read bits: size=${size}, ${this.index}.`);
  314. var result = this.getBits(size, this.index, moveIndex); // console.log(` read bits: result=${result}`);
  315. return result;
  316. }
  317. }, {
  318. key: "getBits",
  319. value: function getBits(size, offsetBits) {
  320. var moveIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
  321. if (this.bitsAvailable < size) {
  322. //throw new Error('no bytes available');
  323. return 0;
  324. }
  325. var offset = offsetBits % 8;
  326. var _byte = this.data[offsetBits / 8 | 0] & 0xff >>> offset;
  327. var bits = 8 - offset;
  328. if (bits >= size) {
  329. if (moveIndex) {
  330. this.index += size;
  331. }
  332. return _byte >> bits - size;
  333. } else {
  334. if (moveIndex) {
  335. this.index += bits;
  336. }
  337. var nextSize = size - bits;
  338. return _byte << nextSize | this.getBits(nextSize, offsetBits + bits, moveIndex);
  339. }
  340. }
  341. }, {
  342. key: "skipLZ",
  343. value: function skipLZ() {
  344. var leadingZeroCount;
  345. for (leadingZeroCount = 0; leadingZeroCount < this.bitLength - this.index; ++leadingZeroCount) {
  346. if (this.getBits(1, this.index + leadingZeroCount, false) !== 0) {
  347. // console.log(` skip LZ : size=${leadingZeroCount}, ${this.index}.`);
  348. this.index += leadingZeroCount;
  349. return leadingZeroCount;
  350. }
  351. }
  352. return leadingZeroCount;
  353. }
  354. }, {
  355. key: "skipUEG",
  356. value: function skipUEG() {
  357. this.skipBits(1 + this.skipLZ());
  358. }
  359. }, {
  360. key: "skipEG",
  361. value: function skipEG() {
  362. this.skipBits(1 + this.skipLZ());
  363. }
  364. }, {
  365. key: "readUEG",
  366. value: function readUEG() {
  367. var prefix = this.skipLZ();
  368. return this.readBits(prefix + 1) - 1;
  369. }
  370. }, {
  371. key: "readEG",
  372. value: function readEG() {
  373. var value = this.readUEG();
  374. if (0x01 & value) {
  375. // the number is odd if the low order bit is set
  376. return 1 + value >>> 1; // add 1 to make it even, and divide by 2
  377. } else {
  378. return -1 * (value >>> 1); // divide by two then make it negative
  379. }
  380. }
  381. }, {
  382. key: "readBoolean",
  383. value: function readBoolean() {
  384. return this.readBits(1) === 1;
  385. }
  386. }, {
  387. key: "readUByte",
  388. value: function readUByte() {
  389. var numberOfBytes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
  390. return this.readBits(numberOfBytes * 8);
  391. }
  392. }, {
  393. key: "readUShort",
  394. value: function readUShort() {
  395. return this.readBits(16);
  396. }
  397. }, {
  398. key: "readUInt",
  399. value: function readUInt() {
  400. return this.readBits(32);
  401. }
  402. }, {
  403. key: "bitsAvailable",
  404. get: function get() {
  405. return this.bitLength - this.index;
  406. }
  407. }]);
  408. return ExpGolomb;
  409. }();
  410. var H264Parser = /*#__PURE__*/function () {
  411. _createClass(H264Parser, null, [{
  412. key: "extractNALu",
  413. value: function extractNALu(buffer) {
  414. var i = 0,
  415. length = buffer.byteLength,
  416. value,
  417. state = 0,
  418. result = [],
  419. lastIndex;
  420. while (i < length) {
  421. value = buffer[i++]; // finding 3 or 4-byte start codes (00 00 01 OR 00 00 00 01)
  422. switch (state) {
  423. case 0:
  424. if (value === 0) {
  425. state = 1;
  426. }
  427. break;
  428. case 1:
  429. if (value === 0) {
  430. state = 2;
  431. } else {
  432. state = 0;
  433. }
  434. break;
  435. case 2:
  436. case 3:
  437. if (value === 0) {
  438. state = 3;
  439. } else if (value === 1 && i < length) {
  440. if (lastIndex) {
  441. result.push(buffer.subarray(lastIndex, i - state - 1));
  442. }
  443. lastIndex = i;
  444. state = 0;
  445. } else {
  446. state = 0;
  447. }
  448. break;
  449. }
  450. }
  451. if (lastIndex) {
  452. result.push(buffer.subarray(lastIndex, length));
  453. }
  454. return result;
  455. }
  456. /**
  457. * Advance the ExpGolomb decoder past a scaling list. The scaling
  458. * list is optionally transmitted as part of a sequence parameter
  459. * set and is not relevant to transmuxing.
  460. * @param decoder {ExpGolomb} exp golomb decoder
  461. * @param count {number} the number of entries in this scaling list
  462. * @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1
  463. */
  464. }, {
  465. key: "skipScalingList",
  466. value: function skipScalingList(decoder, count) {
  467. var lastScale = 8,
  468. nextScale = 8,
  469. deltaScale;
  470. for (var j = 0; j < count; j++) {
  471. if (nextScale !== 0) {
  472. deltaScale = decoder.readEG();
  473. nextScale = (lastScale + deltaScale + 256) % 256;
  474. }
  475. lastScale = nextScale === 0 ? lastScale : nextScale;
  476. }
  477. }
  478. /**
  479. * Read a sequence parameter set and return some interesting video
  480. * properties. A sequence parameter set is the H264 metadata that
  481. * describes the properties of upcoming video frames.
  482. * @param data {Uint8Array} the bytes of a sequence parameter set
  483. * @return {object} an object with configuration parsed from the
  484. * sequence parameter set, including the dimensions of the
  485. * associated video frames.
  486. */
  487. }, {
  488. key: "readSPS",
  489. value: function readSPS(data) {
  490. var decoder = new ExpGolomb(data);
  491. var frameCropLeftOffset = 0,
  492. frameCropRightOffset = 0,
  493. frameCropTopOffset = 0,
  494. frameCropBottomOffset = 0,
  495. sarScale = 1,
  496. profileIdc,
  497. profileCompat,
  498. levelIdc,
  499. numRefFramesInPicOrderCntCycle,
  500. picWidthInMbsMinus1,
  501. picHeightInMapUnitsMinus1,
  502. frameMbsOnlyFlag,
  503. scalingListCount;
  504. decoder.readUByte();
  505. profileIdc = decoder.readUByte(); // profile_idc
  506. profileCompat = decoder.readBits(5); // constraint_set[0-4]_flag, u(5)
  507. decoder.skipBits(3); // reserved_zero_3bits u(3),
  508. levelIdc = decoder.readUByte(); // level_idc u(8)
  509. decoder.skipUEG(); // seq_parameter_set_id
  510. // some profiles have more optional data we don't need
  511. if (profileIdc === 100 || profileIdc === 110 || profileIdc === 122 || profileIdc === 244 || profileIdc === 44 || profileIdc === 83 || profileIdc === 86 || profileIdc === 118 || profileIdc === 128) {
  512. var chromaFormatIdc = decoder.readUEG();
  513. if (chromaFormatIdc === 3) {
  514. decoder.skipBits(1); // separate_colour_plane_flag
  515. }
  516. decoder.skipUEG(); // bit_depth_luma_minus8
  517. decoder.skipUEG(); // bit_depth_chroma_minus8
  518. decoder.skipBits(1); // qpprime_y_zero_transform_bypass_flag
  519. if (decoder.readBoolean()) {
  520. // seq_scaling_matrix_present_flag
  521. scalingListCount = chromaFormatIdc !== 3 ? 8 : 12;
  522. for (var i = 0; i < scalingListCount; ++i) {
  523. if (decoder.readBoolean()) {
  524. // seq_scaling_list_present_flag[ i ]
  525. if (i < 6) {
  526. H264Parser.skipScalingList(decoder, 16);
  527. } else {
  528. H264Parser.skipScalingList(decoder, 64);
  529. }
  530. }
  531. }
  532. }
  533. }
  534. decoder.skipUEG(); // log2_max_frame_num_minus4
  535. var picOrderCntType = decoder.readUEG();
  536. if (picOrderCntType === 0) {
  537. decoder.readUEG(); // log2_max_pic_order_cnt_lsb_minus4
  538. } else if (picOrderCntType === 1) {
  539. decoder.skipBits(1); // delta_pic_order_always_zero_flag
  540. decoder.skipEG(); // offset_for_non_ref_pic
  541. decoder.skipEG(); // offset_for_top_to_bottom_field
  542. numRefFramesInPicOrderCntCycle = decoder.readUEG();
  543. for (var _i = 0; _i < numRefFramesInPicOrderCntCycle; ++_i) {
  544. decoder.skipEG(); // offset_for_ref_frame[ i ]
  545. }
  546. }
  547. decoder.skipUEG(); // max_num_ref_frames
  548. decoder.skipBits(1); // gaps_in_frame_num_value_allowed_flag
  549. picWidthInMbsMinus1 = decoder.readUEG();
  550. picHeightInMapUnitsMinus1 = decoder.readUEG();
  551. frameMbsOnlyFlag = decoder.readBits(1);
  552. if (frameMbsOnlyFlag === 0) {
  553. decoder.skipBits(1); // mb_adaptive_frame_field_flag
  554. }
  555. decoder.skipBits(1); // direct_8x8_inference_flag
  556. if (decoder.readBoolean()) {
  557. // frame_cropping_flag
  558. frameCropLeftOffset = decoder.readUEG();
  559. frameCropRightOffset = decoder.readUEG();
  560. frameCropTopOffset = decoder.readUEG();
  561. frameCropBottomOffset = decoder.readUEG();
  562. }
  563. if (decoder.readBoolean()) {
  564. // vui_parameters_present_flag
  565. if (decoder.readBoolean()) {
  566. // aspect_ratio_info_present_flag
  567. var sarRatio;
  568. var aspectRatioIdc = decoder.readUByte();
  569. switch (aspectRatioIdc) {
  570. case 1:
  571. sarRatio = [1, 1];
  572. break;
  573. case 2:
  574. sarRatio = [12, 11];
  575. break;
  576. case 3:
  577. sarRatio = [10, 11];
  578. break;
  579. case 4:
  580. sarRatio = [16, 11];
  581. break;
  582. case 5:
  583. sarRatio = [40, 33];
  584. break;
  585. case 6:
  586. sarRatio = [24, 11];
  587. break;
  588. case 7:
  589. sarRatio = [20, 11];
  590. break;
  591. case 8:
  592. sarRatio = [32, 11];
  593. break;
  594. case 9:
  595. sarRatio = [80, 33];
  596. break;
  597. case 10:
  598. sarRatio = [18, 11];
  599. break;
  600. case 11:
  601. sarRatio = [15, 11];
  602. break;
  603. case 12:
  604. sarRatio = [64, 33];
  605. break;
  606. case 13:
  607. sarRatio = [160, 99];
  608. break;
  609. case 14:
  610. sarRatio = [4, 3];
  611. break;
  612. case 15:
  613. sarRatio = [3, 2];
  614. break;
  615. case 16:
  616. sarRatio = [2, 1];
  617. break;
  618. case 255:
  619. {
  620. sarRatio = [decoder.readUByte() << 8 | decoder.readUByte(), decoder.readUByte() << 8 | decoder.readUByte()];
  621. break;
  622. }
  623. }
  624. if (sarRatio) {
  625. sarScale = sarRatio[0] / sarRatio[1];
  626. }
  627. }
  628. if (decoder.readBoolean()) {
  629. decoder.skipBits(1);
  630. }
  631. if (decoder.readBoolean()) {
  632. decoder.skipBits(4);
  633. if (decoder.readBoolean()) {
  634. decoder.skipBits(24);
  635. }
  636. }
  637. if (decoder.readBoolean()) {
  638. decoder.skipUEG();
  639. decoder.skipUEG();
  640. }
  641. if (decoder.readBoolean()) {
  642. var unitsInTick = decoder.readUInt();
  643. var timeScale = decoder.readUInt();
  644. var fixedFrameRate = decoder.readBoolean();
  645. }
  646. }
  647. return {
  648. width: Math.ceil(((picWidthInMbsMinus1 + 1) * 16 - frameCropLeftOffset * 2 - frameCropRightOffset * 2) * sarScale),
  649. height: (2 - frameMbsOnlyFlag) * (picHeightInMapUnitsMinus1 + 1) * 16 - (frameMbsOnlyFlag ? 2 : 4) * (frameCropTopOffset + frameCropBottomOffset)
  650. };
  651. }
  652. }, {
  653. key: "parseHeader",
  654. value: function parseHeader(unit) {
  655. var decoder = new ExpGolomb(unit.getPayload()); // skip NALu type
  656. decoder.readUByte();
  657. unit.isfmb = decoder.readUEG() === 0;
  658. unit.stype = decoder.readUEG();
  659. }
  660. }]);
  661. function H264Parser(remuxer) {
  662. _classCallCheck(this, H264Parser);
  663. this.remuxer = remuxer;
  664. this.track = remuxer.mp4track;
  665. }
  666. _createClass(H264Parser, [{
  667. key: "parseSPS",
  668. value: function parseSPS(sps) {
  669. var config = H264Parser.readSPS(new Uint8Array(sps));
  670. this.track.width = config.width;
  671. this.track.height = config.height;
  672. this.track.sps = [new Uint8Array(sps)];
  673. this.track.codec = 'avc1.';
  674. var codecarray = new DataView(sps.buffer, sps.byteOffset + 1, 4);
  675. for (var i = 0; i < 3; ++i) {
  676. var h = codecarray.getUint8(i).toString(16);
  677. if (h.length < 2) {
  678. h = '0' + h;
  679. }
  680. this.track.codec += h;
  681. }
  682. }
  683. }, {
  684. key: "parsePPS",
  685. value: function parsePPS(pps) {
  686. this.track.pps = [new Uint8Array(pps)];
  687. }
  688. }, {
  689. key: "parseNAL",
  690. value: function parseNAL(unit) {
  691. if (!unit) return false;
  692. var push = false;
  693. switch (unit.type()) {
  694. case NALU.IDR:
  695. case NALU.NDR:
  696. push = true;
  697. break;
  698. case NALU.PPS:
  699. if (!this.track.pps) {
  700. this.parsePPS(unit.getPayload());
  701. if (!this.remuxer.readyToDecode && this.track.pps && this.track.sps) {
  702. this.remuxer.readyToDecode = true;
  703. }
  704. }
  705. push = true;
  706. break;
  707. case NALU.SPS:
  708. if (!this.track.sps) {
  709. this.parseSPS(unit.getPayload());
  710. if (!this.remuxer.readyToDecode && this.track.pps && this.track.sps) {
  711. this.remuxer.readyToDecode = true;
  712. }
  713. }
  714. push = true;
  715. break;
  716. case NALU.AUD:
  717. log('AUD - ignoing');
  718. break;
  719. case NALU.SEI:
  720. log('SEI - ignoing');
  721. break;
  722. }
  723. return push;
  724. }
  725. }]);
  726. return H264Parser;
  727. }();
  728. var aacHeader;
  729. var AACParser = /*#__PURE__*/function () {
  730. _createClass(AACParser, null, [{
  731. key: "getHeaderLength",
  732. value: function getHeaderLength(data) {
  733. return data[1] & 0x01 ? 7 : 9; // without CRC 7 and with CRC 9 Refs: https://wiki.multimedia.cx/index.php?title=ADTS
  734. }
  735. }, {
  736. key: "getFrameLength",
  737. value: function getFrameLength(data) {
  738. return (data[3] & 0x03) << 11 | data[4] << 3 | (data[5] & 0xE0) >>> 5; // 13 bits length ref: https://wiki.multimedia.cx/index.php?title=ADTS
  739. }
  740. }, {
  741. key: "isAACPattern",
  742. value: function isAACPattern(data) {
  743. return data[0] === 0xff && (data[1] & 0xf0) === 0xf0 && (data[1] & 0x06) === 0x00;
  744. }
  745. }, {
  746. key: "extractAAC",
  747. value: function extractAAC(buffer) {
  748. var i = 0,
  749. length = buffer.byteLength,
  750. result = [],
  751. headerLength,
  752. frameLength;
  753. if (!AACParser.isAACPattern(buffer)) {
  754. error('Invalid ADTS audio format');
  755. return result;
  756. }
  757. headerLength = AACParser.getHeaderLength(buffer);
  758. if (!aacHeader) {
  759. aacHeader = buffer.subarray(0, headerLength);
  760. }
  761. while (i < length) {
  762. frameLength = AACParser.getFrameLength(buffer);
  763. result.push(buffer.subarray(headerLength, frameLength));
  764. buffer = buffer.slice(frameLength);
  765. i += frameLength;
  766. }
  767. return result;
  768. }
  769. }, {
  770. key: "samplingRateMap",
  771. get: function get() {
  772. return [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350];
  773. }
  774. }, {
  775. key: "getAACHeaderData",
  776. get: function get() {
  777. return aacHeader;
  778. }
  779. }]);
  780. function AACParser(remuxer) {
  781. _classCallCheck(this, AACParser);
  782. this.remuxer = remuxer;
  783. this.track = remuxer.mp4track;
  784. }
  785. _createClass(AACParser, [{
  786. key: "setAACConfig",
  787. value: function setAACConfig() {
  788. var objectType,
  789. sampleIndex,
  790. channelCount,
  791. config = new Uint8Array(2),
  792. headerData = AACParser.getAACHeaderData;
  793. if (!headerData) return;
  794. objectType = ((headerData[2] & 0xC0) >>> 6) + 1;
  795. sampleIndex = (headerData[2] & 0x3C) >>> 2;
  796. channelCount = (headerData[2] & 0x01) << 2;
  797. channelCount |= (headerData[3] & 0xC0) >>> 6;
  798. /* refer to http://wiki.multimedia.cx/index.php?title=MPEG-4_Audio#Audio_Specific_Config */
  799. config[0] = objectType << 3;
  800. config[0] |= (sampleIndex & 0x0E) >> 1;
  801. config[1] |= (sampleIndex & 0x01) << 7;
  802. config[1] |= channelCount << 3;
  803. this.track.codec = 'mp4a.40.' + objectType;
  804. this.track.channelCount = channelCount;
  805. this.track.config = config;
  806. this.remuxer.readyToDecode = true;
  807. }
  808. }]);
  809. return AACParser;
  810. }();
  811. var Event = /*#__PURE__*/function () {
  812. function Event(type) {
  813. _classCallCheck(this, Event);
  814. this.listener = {};
  815. this.type = type | '';
  816. }
  817. _createClass(Event, [{
  818. key: "on",
  819. value: function on(event, fn) {
  820. if (!this.listener[event]) {
  821. this.listener[event] = [];
  822. }
  823. this.listener[event].push(fn);
  824. return true;
  825. }
  826. }, {
  827. key: "off",
  828. value: function off(event, fn) {
  829. if (this.listener[event]) {
  830. var index = this.listener[event].indexOf(fn);
  831. if (index > -1) {
  832. this.listener[event].splice(index, 1);
  833. }
  834. return true;
  835. }
  836. return false;
  837. }
  838. }, {
  839. key: "offAll",
  840. value: function offAll() {
  841. this.listener = {};
  842. }
  843. }, {
  844. key: "dispatch",
  845. value: function dispatch(event, data) {
  846. if (this.listener[event]) {
  847. this.listener[event].map(function (each) {
  848. each.apply(null, [data]);
  849. });
  850. return true;
  851. }
  852. return false;
  853. }
  854. }]);
  855. return Event;
  856. }();
  857. /**
  858. * Generate MP4 Box
  859. * taken from: https://github.com/dailymotion/hls.js
  860. */
  861. var MP4 = /*#__PURE__*/function () {
  862. function MP4() {
  863. _classCallCheck(this, MP4);
  864. }
  865. _createClass(MP4, null, [{
  866. key: "init",
  867. value: function init() {
  868. MP4.types = {
  869. avc1: [],
  870. // codingname
  871. avcC: [],
  872. btrt: [],
  873. dinf: [],
  874. dref: [],
  875. esds: [],
  876. ftyp: [],
  877. hdlr: [],
  878. mdat: [],
  879. mdhd: [],
  880. mdia: [],
  881. mfhd: [],
  882. minf: [],
  883. moof: [],
  884. moov: [],
  885. mp4a: [],
  886. mvex: [],
  887. mvhd: [],
  888. sdtp: [],
  889. stbl: [],
  890. stco: [],
  891. stsc: [],
  892. stsd: [],
  893. stsz: [],
  894. stts: [],
  895. tfdt: [],
  896. tfhd: [],
  897. traf: [],
  898. trak: [],
  899. trun: [],
  900. trex: [],
  901. tkhd: [],
  902. vmhd: [],
  903. smhd: []
  904. };
  905. var i;
  906. for (i in MP4.types) {
  907. if (MP4.types.hasOwnProperty(i)) {
  908. MP4.types[i] = [i.charCodeAt(0), i.charCodeAt(1), i.charCodeAt(2), i.charCodeAt(3)];
  909. }
  910. }
  911. var videoHdlr = new Uint8Array([0x00, // version 0
  912. 0x00, 0x00, 0x00, // flags
  913. 0x00, 0x00, 0x00, 0x00, // pre_defined
  914. 0x76, 0x69, 0x64, 0x65, // handler_type: 'vide'
  915. 0x00, 0x00, 0x00, 0x00, // reserved
  916. 0x00, 0x00, 0x00, 0x00, // reserved
  917. 0x00, 0x00, 0x00, 0x00, // reserved
  918. 0x56, 0x69, 0x64, 0x65, 0x6f, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x00 // name: 'VideoHandler'
  919. ]);
  920. var audioHdlr = new Uint8Array([0x00, // version 0
  921. 0x00, 0x00, 0x00, // flags
  922. 0x00, 0x00, 0x00, 0x00, // pre_defined
  923. 0x73, 0x6f, 0x75, 0x6e, // handler_type: 'soun'
  924. 0x00, 0x00, 0x00, 0x00, // reserved
  925. 0x00, 0x00, 0x00, 0x00, // reserved
  926. 0x00, 0x00, 0x00, 0x00, // reserved
  927. 0x53, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x00 // name: 'SoundHandler'
  928. ]);
  929. MP4.HDLR_TYPES = {
  930. video: videoHdlr,
  931. audio: audioHdlr
  932. };
  933. var dref = new Uint8Array([0x00, // version 0
  934. 0x00, 0x00, 0x00, // flags
  935. 0x00, 0x00, 0x00, 0x01, // entry_count
  936. 0x00, 0x00, 0x00, 0x0c, // entry_size
  937. 0x75, 0x72, 0x6c, 0x20, // 'url' type
  938. 0x00, // version 0
  939. 0x00, 0x00, 0x01 // entry_flags
  940. ]);
  941. var stco = new Uint8Array([0x00, // version
  942. 0x00, 0x00, 0x00, // flags
  943. 0x00, 0x00, 0x00, 0x00 // entry_count
  944. ]);
  945. MP4.STTS = MP4.STSC = MP4.STCO = stco;
  946. MP4.STSZ = new Uint8Array([0x00, // version
  947. 0x00, 0x00, 0x00, // flags
  948. 0x00, 0x00, 0x00, 0x00, // sample_size
  949. 0x00, 0x00, 0x00, 0x00 // sample_count
  950. ]);
  951. MP4.VMHD = new Uint8Array([0x00, // version
  952. 0x00, 0x00, 0x01, // flags
  953. 0x00, 0x00, // graphicsmode
  954. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // opcolor
  955. ]);
  956. MP4.SMHD = new Uint8Array([0x00, // version
  957. 0x00, 0x00, 0x00, // flags
  958. 0x00, 0x00, // balance
  959. 0x00, 0x00 // reserved
  960. ]);
  961. MP4.STSD = new Uint8Array([0x00, // version 0
  962. 0x00, 0x00, 0x00, // flags
  963. 0x00, 0x00, 0x00, 0x01]); // entry_count
  964. var majorBrand = new Uint8Array([105, 115, 111, 109]); // isom
  965. var avc1Brand = new Uint8Array([97, 118, 99, 49]); // avc1
  966. var minorVersion = new Uint8Array([0, 0, 0, 1]);
  967. MP4.FTYP = MP4.box(MP4.types.ftyp, majorBrand, minorVersion, majorBrand, avc1Brand);
  968. MP4.DINF = MP4.box(MP4.types.dinf, MP4.box(MP4.types.dref, dref));
  969. }
  970. }, {
  971. key: "box",
  972. value: function box(type) {
  973. for (var _len = arguments.length, payload = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  974. payload[_key - 1] = arguments[_key];
  975. }
  976. var size = 8,
  977. i = payload.length,
  978. len = i,
  979. result; // calculate the total size we need to allocate
  980. while (i--) {
  981. size += payload[i].byteLength;
  982. }
  983. result = new Uint8Array(size);
  984. result[0] = size >> 24 & 0xff;
  985. result[1] = size >> 16 & 0xff;
  986. result[2] = size >> 8 & 0xff;
  987. result[3] = size & 0xff;
  988. result.set(type, 4); // copy the payload into the result
  989. for (i = 0, size = 8; i < len; ++i) {
  990. // copy payload[i] array @ offset size
  991. result.set(payload[i], size);
  992. size += payload[i].byteLength;
  993. }
  994. return result;
  995. }
  996. }, {
  997. key: "hdlr",
  998. value: function hdlr(type) {
  999. return MP4.box(MP4.types.hdlr, MP4.HDLR_TYPES[type]);
  1000. }
  1001. }, {
  1002. key: "mdat",
  1003. value: function mdat(data) {
  1004. return MP4.box(MP4.types.mdat, data);
  1005. }
  1006. }, {
  1007. key: "mdhd",
  1008. value: function mdhd(timescale, duration) {
  1009. return MP4.box(MP4.types.mdhd, new Uint8Array([0x00, // version 0
  1010. 0x00, 0x00, 0x00, // flags
  1011. 0x00, 0x00, 0x00, 0x02, // creation_time
  1012. 0x00, 0x00, 0x00, 0x03, // modification_time
  1013. timescale >> 24 & 0xFF, timescale >> 16 & 0xFF, timescale >> 8 & 0xFF, timescale & 0xFF, // timescale
  1014. duration >> 24, duration >> 16 & 0xFF, duration >> 8 & 0xFF, duration & 0xFF, // duration
  1015. 0x55, 0xc4, // 'und' language (undetermined)
  1016. 0x00, 0x00]));
  1017. }
  1018. }, {
  1019. key: "mdia",
  1020. value: function mdia(track) {
  1021. return MP4.box(MP4.types.mdia, MP4.mdhd(track.timescale, track.duration), MP4.hdlr(track.type), MP4.minf(track));
  1022. }
  1023. }, {
  1024. key: "mfhd",
  1025. value: function mfhd(sequenceNumber) {
  1026. return MP4.box(MP4.types.mfhd, new Uint8Array([0x00, 0x00, 0x00, 0x00, // flags
  1027. sequenceNumber >> 24, sequenceNumber >> 16 & 0xFF, sequenceNumber >> 8 & 0xFF, sequenceNumber & 0xFF // sequence_number
  1028. ]));
  1029. }
  1030. }, {
  1031. key: "minf",
  1032. value: function minf(track) {
  1033. if (track.type === 'audio') {
  1034. return MP4.box(MP4.types.minf, MP4.box(MP4.types.smhd, MP4.SMHD), MP4.DINF, MP4.stbl(track));
  1035. } else {
  1036. return MP4.box(MP4.types.minf, MP4.box(MP4.types.vmhd, MP4.VMHD), MP4.DINF, MP4.stbl(track));
  1037. }
  1038. }
  1039. }, {
  1040. key: "moof",
  1041. value: function moof(sn, baseMediaDecodeTime, track) {
  1042. return MP4.box(MP4.types.moof, MP4.mfhd(sn), MP4.traf(track, baseMediaDecodeTime));
  1043. }
  1044. /**
  1045. * @param tracks... (optional) {array} the tracks associated with this movie
  1046. */
  1047. }, {
  1048. key: "moov",
  1049. value: function moov(tracks, duration, timescale) {
  1050. var i = tracks.length,
  1051. boxes = [];
  1052. while (i--) {
  1053. boxes[i] = MP4.trak(tracks[i]);
  1054. }
  1055. return MP4.box.apply(null, [MP4.types.moov, MP4.mvhd(timescale, duration)].concat(boxes).concat(MP4.mvex(tracks)));
  1056. }
  1057. }, {
  1058. key: "mvex",
  1059. value: function mvex(tracks) {
  1060. var i = tracks.length,
  1061. boxes = [];
  1062. while (i--) {
  1063. boxes[i] = MP4.trex(tracks[i]);
  1064. }
  1065. return MP4.box.apply(null, [MP4.types.mvex].concat(boxes));
  1066. }
  1067. }, {
  1068. key: "mvhd",
  1069. value: function mvhd(timescale, duration) {
  1070. var bytes = new Uint8Array([0x00, // version 0
  1071. 0x00, 0x00, 0x00, // flags
  1072. 0x00, 0x00, 0x00, 0x01, // creation_time
  1073. 0x00, 0x00, 0x00, 0x02, // modification_time
  1074. timescale >> 24 & 0xFF, timescale >> 16 & 0xFF, timescale >> 8 & 0xFF, timescale & 0xFF, // timescale
  1075. duration >> 24 & 0xFF, duration >> 16 & 0xFF, duration >> 8 & 0xFF, duration & 0xFF, // duration
  1076. 0x00, 0x01, 0x00, 0x00, // 1.0 rate
  1077. 0x01, 0x00, // 1.0 volume
  1078. 0x00, 0x00, // reserved
  1079. 0x00, 0x00, 0x00, 0x00, // reserved
  1080. 0x00, 0x00, 0x00, 0x00, // reserved
  1081. 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, // transformation: unity matrix
  1082. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // pre_defined
  1083. 0xff, 0xff, 0xff, 0xff // next_track_ID
  1084. ]);
  1085. return MP4.box(MP4.types.mvhd, bytes);
  1086. }
  1087. }, {
  1088. key: "sdtp",
  1089. value: function sdtp(track) {
  1090. var samples = track.samples || [],
  1091. bytes = new Uint8Array(4 + samples.length),
  1092. flags,
  1093. i; // leave the full box header (4 bytes) all zero
  1094. // write the sample table
  1095. for (i = 0; i < samples.length; i++) {
  1096. flags = samples[i].flags;
  1097. bytes[i + 4] = flags.dependsOn << 4 | flags.isDependedOn << 2 | flags.hasRedundancy;
  1098. }
  1099. return MP4.box(MP4.types.sdtp, bytes);
  1100. }
  1101. }, {
  1102. key: "stbl",
  1103. value: function stbl(track) {
  1104. return MP4.box(MP4.types.stbl, MP4.stsd(track), MP4.box(MP4.types.stts, MP4.STTS), MP4.box(MP4.types.stsc, MP4.STSC), MP4.box(MP4.types.stsz, MP4.STSZ), MP4.box(MP4.types.stco, MP4.STCO));
  1105. }
  1106. }, {
  1107. key: "avc1",
  1108. value: function avc1(track) {
  1109. var sps = [],
  1110. pps = [],
  1111. i,
  1112. data,
  1113. len; // assemble the SPSs
  1114. for (i = 0; i < track.sps.length; i++) {
  1115. data = track.sps[i];
  1116. len = data.byteLength;
  1117. sps.push(len >>> 8 & 0xFF);
  1118. sps.push(len & 0xFF);
  1119. sps = sps.concat(Array.prototype.slice.call(data)); // SPS
  1120. } // assemble the PPSs
  1121. for (i = 0; i < track.pps.length; i++) {
  1122. data = track.pps[i];
  1123. len = data.byteLength;
  1124. pps.push(len >>> 8 & 0xFF);
  1125. pps.push(len & 0xFF);
  1126. pps = pps.concat(Array.prototype.slice.call(data));
  1127. }
  1128. var avcc = MP4.box(MP4.types.avcC, new Uint8Array([0x01, // version
  1129. sps[3], // profile
  1130. sps[4], // profile compat
  1131. sps[5], // level
  1132. 0xfc | 3, // lengthSizeMinusOne, hard-coded to 4 bytes
  1133. 0xE0 | track.sps.length // 3bit reserved (111) + numOfSequenceParameterSets
  1134. ].concat(sps).concat([track.pps.length // numOfPictureParameterSets
  1135. ]).concat(pps))),
  1136. // "PPS"
  1137. width = track.width,
  1138. height = track.height; // console.log('avcc:' + Hex.hexDump(avcc));
  1139. return MP4.box(MP4.types.avc1, new Uint8Array([0x00, 0x00, 0x00, // reserved
  1140. 0x00, 0x00, 0x00, // reserved
  1141. 0x00, 0x01, // data_reference_index
  1142. 0x00, 0x00, // pre_defined
  1143. 0x00, 0x00, // reserved
  1144. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // pre_defined
  1145. width >> 8 & 0xFF, width & 0xff, // width
  1146. height >> 8 & 0xFF, height & 0xff, // height
  1147. 0x00, 0x48, 0x00, 0x00, // horizresolution
  1148. 0x00, 0x48, 0x00, 0x00, // vertresolution
  1149. 0x00, 0x00, 0x00, 0x00, // reserved
  1150. 0x00, 0x01, // frame_count
  1151. 0x12, 0x62, 0x69, 0x6E, 0x65, // binelpro.ru
  1152. 0x6C, 0x70, 0x72, 0x6F, 0x2E, 0x72, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // compressorname
  1153. 0x00, 0x18, // depth = 24
  1154. 0x11, 0x11]), // pre_defined = -1
  1155. avcc, MP4.box(MP4.types.btrt, new Uint8Array([0x00, 0x1c, 0x9c, 0x80, // bufferSizeDB
  1156. 0x00, 0x2d, 0xc6, 0xc0, // maxBitrate
  1157. 0x00, 0x2d, 0xc6, 0xc0])) // avgBitrate
  1158. );
  1159. }
  1160. }, {
  1161. key: "esds",
  1162. value: function esds(track) {
  1163. var configlen = track.config.byteLength;
  1164. var data = new Uint8Array(26 + configlen + 3);
  1165. data.set([0x00, // version 0
  1166. 0x00, 0x00, 0x00, // flags
  1167. 0x03, // descriptor_type
  1168. 0x17 + configlen, // length
  1169. 0x00, 0x01, // es_id
  1170. 0x00, // stream_priority
  1171. 0x04, // descriptor_type
  1172. 0x0f + configlen, // length
  1173. 0x40, // codec : mpeg4_audio
  1174. 0x15, // stream_type
  1175. 0x00, 0x00, 0x00, // buffer_size
  1176. 0x00, 0x00, 0x00, 0x00, // maxBitrate
  1177. 0x00, 0x00, 0x00, 0x00, // avgBitrate
  1178. 0x05, // descriptor_type
  1179. configlen]);
  1180. data.set(track.config, 26);
  1181. data.set([0x06, 0x01, 0x02], 26 + configlen); // return new Uint8Array([
  1182. // 0x00, // version 0
  1183. // 0x00, 0x00, 0x00, // flags
  1184. //
  1185. // 0x03, // descriptor_type
  1186. // 0x17+configlen, // length
  1187. // 0x00, 0x01, //es_id
  1188. // 0x00, // stream_priority
  1189. //
  1190. // 0x04, // descriptor_type
  1191. // 0x0f+configlen, // length
  1192. // 0x40, //codec : mpeg4_audio
  1193. // 0x15, // stream_type
  1194. // 0x00, 0x00, 0x00, // buffer_size
  1195. // 0x00, 0x00, 0x00, 0x00, // maxBitrate
  1196. // 0x00, 0x00, 0x00, 0x00, // avgBitrate
  1197. //
  1198. // 0x05 // descriptor_type
  1199. // ].concat([configlen]).concat(track.config).concat([0x06, 0x01, 0x02])); // GASpecificConfig)); // length + audio config descriptor
  1200. return data;
  1201. }
  1202. }, {
  1203. key: "mp4a",
  1204. value: function mp4a(track) {
  1205. var audiosamplerate = track.audiosamplerate;
  1206. return MP4.box(MP4.types.mp4a, new Uint8Array([0x00, 0x00, 0x00, // reserved
  1207. 0x00, 0x00, 0x00, // reserved
  1208. 0x00, 0x01, // data_reference_index
  1209. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved
  1210. 0x00, track.channelCount, // channelcount
  1211. 0x00, 0x10, // sampleSize:16bits
  1212. 0x00, 0x00, // pre_defined
  1213. 0x00, 0x00, // reserved2
  1214. audiosamplerate >> 8 & 0xFF, audiosamplerate & 0xff, //
  1215. 0x00, 0x00]), MP4.box(MP4.types.esds, MP4.esds(track)));
  1216. }
  1217. }, {
  1218. key: "stsd",
  1219. value: function stsd(track) {
  1220. if (track.type === 'audio') {
  1221. return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp4a(track));
  1222. } else {
  1223. return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track));
  1224. }
  1225. }
  1226. }, {
  1227. key: "tkhd",
  1228. value: function tkhd(track) {
  1229. var id = track.id,
  1230. duration = track.duration,
  1231. width = track.width,
  1232. height = track.height,
  1233. volume = track.volume;
  1234. return MP4.box(MP4.types.tkhd, new Uint8Array([0x00, // version 0
  1235. 0x00, 0x00, 0x07, // flags
  1236. 0x00, 0x00, 0x00, 0x00, // creation_time
  1237. 0x00, 0x00, 0x00, 0x00, // modification_time
  1238. id >> 24 & 0xFF, id >> 16 & 0xFF, id >> 8 & 0xFF, id & 0xFF, // track_ID
  1239. 0x00, 0x00, 0x00, 0x00, // reserved
  1240. duration >> 24, duration >> 16 & 0xFF, duration >> 8 & 0xFF, duration & 0xFF, // duration
  1241. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved
  1242. 0x00, 0x00, // layer
  1243. 0x00, 0x00, // alternate_group
  1244. volume >> 0 & 0xff, volume % 1 * 10 >> 0 & 0xff, // track volume // FIXME
  1245. 0x00, 0x00, // reserved
  1246. 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, // transformation: unity matrix
  1247. width >> 8 & 0xFF, width & 0xFF, 0x00, 0x00, // width
  1248. height >> 8 & 0xFF, height & 0xFF, 0x00, 0x00 // height
  1249. ]));
  1250. }
  1251. }, {
  1252. key: "traf",
  1253. value: function traf(track, baseMediaDecodeTime) {
  1254. var sampleDependencyTable = MP4.sdtp(track),
  1255. id = track.id;
  1256. return MP4.box(MP4.types.traf, MP4.box(MP4.types.tfhd, new Uint8Array([0x00, // version 0
  1257. 0x00, 0x00, 0x00, // flags
  1258. id >> 24, id >> 16 & 0XFF, id >> 8 & 0XFF, id & 0xFF // track_ID
  1259. ])), MP4.box(MP4.types.tfdt, new Uint8Array([0x00, // version 0
  1260. 0x00, 0x00, 0x00, // flags
  1261. baseMediaDecodeTime >> 24, baseMediaDecodeTime >> 16 & 0XFF, baseMediaDecodeTime >> 8 & 0XFF, baseMediaDecodeTime & 0xFF // baseMediaDecodeTime
  1262. ])), MP4.trun(track, sampleDependencyTable.length + 16 + // tfhd
  1263. 16 + // tfdt
  1264. 8 + // traf header
  1265. 16 + // mfhd
  1266. 8 + // moof header
  1267. 8), // mdat header
  1268. sampleDependencyTable);
  1269. }
  1270. /**
  1271. * Generate a track box.
  1272. * @param track {object} a track definition
  1273. * @return {Uint8Array} the track box
  1274. */
  1275. }, {
  1276. key: "trak",
  1277. value: function trak(track) {
  1278. track.duration = track.duration || 0xffffffff;
  1279. return MP4.box(MP4.types.trak, MP4.tkhd(track), MP4.mdia(track));
  1280. }
  1281. }, {
  1282. key: "trex",
  1283. value: function trex(track) {
  1284. var id = track.id;
  1285. return MP4.box(MP4.types.trex, new Uint8Array([0x00, // version 0
  1286. 0x00, 0x00, 0x00, // flags
  1287. id >> 24, id >> 16 & 0XFF, id >> 8 & 0XFF, id & 0xFF, // track_ID
  1288. 0x00, 0x00, 0x00, 0x01, // default_sample_description_index
  1289. 0x00, 0x00, 0x00, 0x00, // default_sample_duration
  1290. 0x00, 0x00, 0x00, 0x00, // default_sample_size
  1291. 0x00, 0x01, 0x00, 0x01 // default_sample_flags
  1292. ]));
  1293. }
  1294. }, {
  1295. key: "trun",
  1296. value: function trun(track, offset) {
  1297. var samples = track.samples || [],
  1298. len = samples.length,
  1299. arraylen = 12 + 16 * len,
  1300. array = new Uint8Array(arraylen),
  1301. i,
  1302. sample,
  1303. duration,
  1304. size,
  1305. flags,
  1306. cts;
  1307. offset += 8 + arraylen;
  1308. array.set([0x00, // version 0
  1309. 0x00, 0x0f, 0x01, // flags
  1310. len >>> 24 & 0xFF, len >>> 16 & 0xFF, len >>> 8 & 0xFF, len & 0xFF, // sample_count
  1311. offset >>> 24 & 0xFF, offset >>> 16 & 0xFF, offset >>> 8 & 0xFF, offset & 0xFF // data_offset
  1312. ], 0);
  1313. for (i = 0; i < len; i++) {
  1314. sample = samples[i];
  1315. duration = sample.duration;
  1316. size = sample.size;
  1317. flags = sample.flags;
  1318. cts = sample.cts;
  1319. array.set([duration >>> 24 & 0xFF, duration >>> 16 & 0xFF, duration >>> 8 & 0xFF, duration & 0xFF, // sample_duration
  1320. size >>> 24 & 0xFF, size >>> 16 & 0xFF, size >>> 8 & 0xFF, size & 0xFF, // sample_size
  1321. flags.isLeading << 2 | flags.dependsOn, flags.isDependedOn << 6 | flags.hasRedundancy << 4 | flags.paddingValue << 1 | flags.isNonSync, flags.degradPrio & 0xF0 << 8, flags.degradPrio & 0x0F, // sample_flags
  1322. cts >>> 24 & 0xFF, cts >>> 16 & 0xFF, cts >>> 8 & 0xFF, cts & 0xFF // sample_composition_time_offset
  1323. ], 12 + 16 * i);
  1324. }
  1325. return MP4.box(MP4.types.trun, array);
  1326. }
  1327. }, {
  1328. key: "initSegment",
  1329. value: function initSegment(tracks, duration, timescale) {
  1330. if (!MP4.types) {
  1331. MP4.init();
  1332. }
  1333. var movie = MP4.moov(tracks, duration, timescale),
  1334. result;
  1335. result = new Uint8Array(MP4.FTYP.byteLength + movie.byteLength);
  1336. result.set(MP4.FTYP);
  1337. result.set(movie, MP4.FTYP.byteLength);
  1338. return result;
  1339. }
  1340. }]);
  1341. return MP4;
  1342. }();
  1343. var track_id = 1;
  1344. var BaseRemuxer = /*#__PURE__*/function () {
  1345. _createClass(BaseRemuxer, null, [{
  1346. key: "getTrackID",
  1347. value: function getTrackID() {
  1348. return track_id++;
  1349. }
  1350. }]);
  1351. function BaseRemuxer() {
  1352. _classCallCheck(this, BaseRemuxer);
  1353. this.seq = 1;
  1354. }
  1355. _createClass(BaseRemuxer, [{
  1356. key: "flush",
  1357. value: function flush() {
  1358. this.seq++;
  1359. this.mp4track.len = 0;
  1360. this.mp4track.samples = [];
  1361. }
  1362. }, {
  1363. key: "isReady",
  1364. value: function isReady() {
  1365. if (!this.readyToDecode || !this.samples.length) return null;
  1366. return true;
  1367. }
  1368. }]);
  1369. return BaseRemuxer;
  1370. }();
  1371. var AACRemuxer = /*#__PURE__*/function (_BaseRemuxer) {
  1372. _inherits(AACRemuxer, _BaseRemuxer);
  1373. var _super = _createSuper(AACRemuxer);
  1374. function AACRemuxer() {
  1375. var _this;
  1376. _classCallCheck(this, AACRemuxer);
  1377. _this = _super.call(this);
  1378. _this.readyToDecode = false;
  1379. _this.nextDts = 0;
  1380. _this.dts = 0;
  1381. _this.timescale = 1000;
  1382. _this.mp4track = {
  1383. id: BaseRemuxer.getTrackID(),
  1384. type: 'audio',
  1385. channelCount: 0,
  1386. len: 0,
  1387. fragmented: true,
  1388. timescale: _this.timescale,
  1389. duration: _this.timescale,
  1390. samples: [],
  1391. config: '',
  1392. codec: ''
  1393. };
  1394. _this.samples = [];
  1395. _this.aac = new AACParser(_assertThisInitialized(_this));
  1396. return _this;
  1397. }
  1398. _createClass(AACRemuxer, [{
  1399. key: "resetTrack",
  1400. value: function resetTrack() {
  1401. this.readyToDecode = false;
  1402. this.mp4track.codec = '';
  1403. this.mp4track.channelCount = '';
  1404. this.mp4track.config = '';
  1405. this.mp4track.timescale = this.timescale;
  1406. }
  1407. }, {
  1408. key: "remux",
  1409. value: function remux(frames) {
  1410. if (frames.length > 0) {
  1411. for (var i = 0; i < frames.length; i++) {
  1412. var frame = frames[i];
  1413. var payload = frame.units;
  1414. var size = payload.byteLength;
  1415. this.samples.push({
  1416. units: payload,
  1417. size: size,
  1418. duration: frame.duration
  1419. });
  1420. this.mp4track.len += size;
  1421. if (!this.readyToDecode) {
  1422. this.aac.setAACConfig();
  1423. }
  1424. }
  1425. }
  1426. }
  1427. }, {
  1428. key: "getPayload",
  1429. value: function getPayload() {
  1430. if (!this.isReady()) {
  1431. return null;
  1432. }
  1433. var payload = new Uint8Array(this.mp4track.len);
  1434. var offset = 0;
  1435. var samples = this.mp4track.samples;
  1436. var mp4Sample, duration;
  1437. this.dts = this.nextDts;
  1438. while (this.samples.length) {
  1439. var sample = this.samples.shift(),
  1440. units = sample.units;
  1441. duration = sample.duration;
  1442. if (duration <= 0) {
  1443. log("remuxer: invalid sample duration at DTS: ".concat(this.nextDts, " :").concat(duration));
  1444. this.mp4track.len -= sample.size;
  1445. continue;
  1446. }
  1447. this.nextDts += duration;
  1448. mp4Sample = {
  1449. size: sample.size,
  1450. duration: duration,
  1451. cts: 0,
  1452. flags: {
  1453. isLeading: 0,
  1454. isDependedOn: 0,
  1455. hasRedundancy: 0,
  1456. degradPrio: 0,
  1457. dependsOn: 1
  1458. }
  1459. };
  1460. payload.set(sample.units, offset);
  1461. offset += sample.size;
  1462. samples.push(mp4Sample);
  1463. }
  1464. if (!samples.length) return null;
  1465. return new Uint8Array(payload.buffer, 0, this.mp4track.len);
  1466. }
  1467. }]);
  1468. return AACRemuxer;
  1469. }(BaseRemuxer);
  1470. var H264Remuxer = /*#__PURE__*/function (_BaseRemuxer) {
  1471. _inherits(H264Remuxer, _BaseRemuxer);
  1472. var _super = _createSuper(H264Remuxer);
  1473. function H264Remuxer() {
  1474. var _this;
  1475. _classCallCheck(this, H264Remuxer);
  1476. _this = _super.call(this);
  1477. _this.readyToDecode = false;
  1478. _this.nextDts = 0;
  1479. _this.dts = 0;
  1480. _this.timescale = 1000;
  1481. _this.mp4track = {
  1482. id: BaseRemuxer.getTrackID(),
  1483. type: 'video',
  1484. len: 0,
  1485. fragmented: true,
  1486. sps: '',
  1487. pps: '',
  1488. width: 0,
  1489. height: 0,
  1490. timescale: _this.timescale,
  1491. duration: _this.timescale,
  1492. samples: []
  1493. };
  1494. _this.samples = [];
  1495. _this.h264 = new H264Parser(_assertThisInitialized(_this));
  1496. return _this;
  1497. }
  1498. _createClass(H264Remuxer, [{
  1499. key: "resetTrack",
  1500. value: function resetTrack() {
  1501. this.readyToDecode = false;
  1502. this.mp4track.sps = '';
  1503. this.mp4track.pps = '';
  1504. }
  1505. }, {
  1506. key: "remux",
  1507. value: function remux(frames) {
  1508. var _iterator = _createForOfIteratorHelper(frames),
  1509. _step;
  1510. try {
  1511. for (_iterator.s(); !(_step = _iterator.n()).done;) {
  1512. var frame = _step.value;
  1513. var units = [];
  1514. var size = 0;
  1515. var _iterator2 = _createForOfIteratorHelper(frame.units),
  1516. _step2;
  1517. try {
  1518. for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
  1519. var unit = _step2.value;
  1520. if (this.h264.parseNAL(unit)) {
  1521. units.push(unit);
  1522. size += unit.getSize();
  1523. }
  1524. }
  1525. } catch (err) {
  1526. _iterator2.e(err);
  1527. } finally {
  1528. _iterator2.f();
  1529. }
  1530. if (units.length > 0 && this.readyToDecode) {
  1531. this.mp4track.len += size;
  1532. this.samples.push({
  1533. units: units,
  1534. size: size,
  1535. keyFrame: frame.keyFrame,
  1536. duration: frame.duration
  1537. });
  1538. }
  1539. }
  1540. } catch (err) {
  1541. _iterator.e(err);
  1542. } finally {
  1543. _iterator.f();
  1544. }
  1545. }
  1546. }, {
  1547. key: "getPayload",
  1548. value: function getPayload() {
  1549. if (!this.isReady()) {
  1550. return null;
  1551. }
  1552. var payload = new Uint8Array(this.mp4track.len);
  1553. var offset = 0;
  1554. var samples = this.mp4track.samples;
  1555. var mp4Sample, duration;
  1556. this.dts = this.nextDts;
  1557. while (this.samples.length) {
  1558. var sample = this.samples.shift(),
  1559. units = sample.units;
  1560. duration = sample.duration;
  1561. if (duration <= 0) {
  1562. log("remuxer: invalid sample duration at DTS: ".concat(this.nextDts, " :").concat(duration));
  1563. this.mp4track.len -= sample.size;
  1564. continue;
  1565. }
  1566. this.nextDts += duration;
  1567. mp4Sample = {
  1568. size: sample.size,
  1569. duration: duration,
  1570. cts: 0,
  1571. flags: {
  1572. isLeading: 0,
  1573. isDependedOn: 0,
  1574. hasRedundancy: 0,
  1575. degradPrio: 0,
  1576. isNonSync: sample.keyFrame ? 0 : 1,
  1577. dependsOn: sample.keyFrame ? 2 : 1
  1578. }
  1579. };
  1580. var _iterator3 = _createForOfIteratorHelper(units),
  1581. _step3;
  1582. try {
  1583. for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
  1584. var unit = _step3.value;
  1585. payload.set(unit.getData(), offset);
  1586. offset += unit.getSize();
  1587. }
  1588. } catch (err) {
  1589. _iterator3.e(err);
  1590. } finally {
  1591. _iterator3.f();
  1592. }
  1593. samples.push(mp4Sample);
  1594. }
  1595. if (!samples.length) return null;
  1596. return new Uint8Array(payload.buffer, 0, this.mp4track.len);
  1597. }
  1598. }]);
  1599. return H264Remuxer;
  1600. }(BaseRemuxer);
  1601. function appendByteArray(buffer1, buffer2) {
  1602. var tmp = new Uint8Array((buffer1.byteLength | 0) + (buffer2.byteLength | 0));
  1603. tmp.set(buffer1, 0);
  1604. tmp.set(buffer2, buffer1.byteLength | 0);
  1605. return tmp;
  1606. }
  1607. function secToTime(sec) {
  1608. var seconds,
  1609. hours,
  1610. minutes,
  1611. result = '';
  1612. seconds = Math.floor(sec);
  1613. hours = parseInt(seconds / 3600, 10) % 24;
  1614. minutes = parseInt(seconds / 60, 10) % 60;
  1615. seconds = seconds < 0 ? 0 : seconds % 60;
  1616. if (hours > 0) {
  1617. result += (hours < 10 ? '0' + hours : hours) + ':';
  1618. }
  1619. result += (minutes < 10 ? '0' + minutes : minutes) + ':' + (seconds < 10 ? '0' + seconds : seconds);
  1620. return result;
  1621. }
  1622. var RemuxController = /*#__PURE__*/function (_Event) {
  1623. _inherits(RemuxController, _Event);
  1624. var _super = _createSuper(RemuxController);
  1625. function RemuxController(streaming) {
  1626. var _this;
  1627. _classCallCheck(this, RemuxController);
  1628. _this = _super.call(this, 'remuxer');
  1629. _this.initialized = false;
  1630. _this.trackTypes = [];
  1631. _this.tracks = {};
  1632. _this.mediaDuration = streaming ? Infinity : 1000;
  1633. return _this;
  1634. }
  1635. _createClass(RemuxController, [{
  1636. key: "addTrack",
  1637. value: function addTrack(type) {
  1638. if (type === 'video' || type === 'both') {
  1639. this.tracks.video = new H264Remuxer();
  1640. this.trackTypes.push('video');
  1641. }
  1642. if (type === 'audio' || type === 'both') {
  1643. this.tracks.audio = new AACRemuxer();
  1644. this.trackTypes.push('audio');
  1645. }
  1646. }
  1647. }, {
  1648. key: "reset",
  1649. value: function reset() {
  1650. var _iterator = _createForOfIteratorHelper(this.trackTypes),
  1651. _step;
  1652. try {
  1653. for (_iterator.s(); !(_step = _iterator.n()).done;) {
  1654. var type = _step.value;
  1655. this.tracks[type].resetTrack();
  1656. }
  1657. } catch (err) {
  1658. _iterator.e(err);
  1659. } finally {
  1660. _iterator.f();
  1661. }
  1662. this.initialized = false;
  1663. }
  1664. }, {
  1665. key: "destroy",
  1666. value: function destroy() {
  1667. this.tracks = {};
  1668. this.offAll();
  1669. }
  1670. }, {
  1671. key: "flush",
  1672. value: function flush() {
  1673. if (!this.initialized) {
  1674. if (this.isReady()) {
  1675. this.dispatch('ready');
  1676. var _iterator2 = _createForOfIteratorHelper(this.trackTypes),
  1677. _step2;
  1678. try {
  1679. for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
  1680. var type = _step2.value;
  1681. var track = this.tracks[type];
  1682. var data = {
  1683. type: type,
  1684. payload: MP4.initSegment([track.mp4track], this.mediaDuration, track.mp4track.timescale)
  1685. };
  1686. this.dispatch('buffer', data);
  1687. }
  1688. } catch (err) {
  1689. _iterator2.e(err);
  1690. } finally {
  1691. _iterator2.f();
  1692. }
  1693. log('Initial segment generated.');
  1694. this.initialized = true;
  1695. this.flush();
  1696. }
  1697. } else {
  1698. var _iterator3 = _createForOfIteratorHelper(this.trackTypes),
  1699. _step3;
  1700. try {
  1701. for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
  1702. var _type = _step3.value;
  1703. var _track = this.tracks[_type];
  1704. var pay = _track.getPayload();
  1705. if (pay && pay.byteLength) {
  1706. var moof = MP4.moof(_track.seq, _track.dts, _track.mp4track);
  1707. var mdat = MP4.mdat(pay);
  1708. var payload = appendByteArray(moof, mdat);
  1709. var _data = {
  1710. type: _type,
  1711. payload: payload,
  1712. dts: _track.dts
  1713. };
  1714. this.dispatch('buffer', _data);
  1715. var duration = secToTime(_track.dts / 1000);
  1716. log("put segment (".concat(_type, "): ").concat(_track.seq, " dts: ").concat(_track.dts, " frames: ").concat(_track.mp4track.samples.length, " second: ").concat(duration));
  1717. _track.flush();
  1718. }
  1719. }
  1720. } catch (err) {
  1721. _iterator3.e(err);
  1722. } finally {
  1723. _iterator3.f();
  1724. }
  1725. }
  1726. }
  1727. }, {
  1728. key: "isReady",
  1729. value: function isReady() {
  1730. var _iterator4 = _createForOfIteratorHelper(this.trackTypes),
  1731. _step4;
  1732. try {
  1733. for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
  1734. var type = _step4.value;
  1735. if (!this.tracks[type].readyToDecode || !this.tracks[type].samples.length) return false;
  1736. }
  1737. } catch (err) {
  1738. _iterator4.e(err);
  1739. } finally {
  1740. _iterator4.f();
  1741. }
  1742. return true;
  1743. }
  1744. }, {
  1745. key: "remux",
  1746. value: function remux(data) {
  1747. var _iterator5 = _createForOfIteratorHelper(this.trackTypes),
  1748. _step5;
  1749. try {
  1750. for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
  1751. var type = _step5.value;
  1752. var frames = data[type];
  1753. if (type === 'audio' && this.tracks.video && !this.tracks.video.readyToDecode) continue;
  1754. /* if video is present, don't add audio until video get ready */
  1755. if (frames.length > 0) {
  1756. this.tracks[type].remux(frames);
  1757. }
  1758. }
  1759. } catch (err) {
  1760. _iterator5.e(err);
  1761. } finally {
  1762. _iterator5.f();
  1763. }
  1764. this.flush();
  1765. }
  1766. }]);
  1767. return RemuxController;
  1768. }(Event);
  1769. var BufferController = /*#__PURE__*/function (_Event) {
  1770. _inherits(BufferController, _Event);
  1771. var _super = _createSuper(BufferController);
  1772. function BufferController(sourceBuffer, type) {
  1773. var _this;
  1774. _classCallCheck(this, BufferController);
  1775. _this = _super.call(this, 'buffer');
  1776. _this.type = type;
  1777. _this.queue = new Uint8Array();
  1778. _this.cleaning = false;
  1779. _this.pendingCleaning = 0;
  1780. _this.cleanOffset = 30;
  1781. _this.cleanRanges = [];
  1782. _this.sourceBuffer = sourceBuffer;
  1783. _this.sourceBuffer.addEventListener('updateend', function () {
  1784. if (_this.pendingCleaning > 0) {
  1785. _this.initCleanup(_this.pendingCleaning);
  1786. _this.pendingCleaning = 0;
  1787. }
  1788. _this.cleaning = false;
  1789. if (_this.cleanRanges.length) {
  1790. _this.doCleanup();
  1791. return;
  1792. }
  1793. });
  1794. _this.sourceBuffer.addEventListener('error', function () {
  1795. _this.dispatch('error', {
  1796. type: _this.type,
  1797. name: 'buffer',
  1798. error: 'buffer error'
  1799. });
  1800. });
  1801. return _this;
  1802. }
  1803. _createClass(BufferController, [{
  1804. key: "destroy",
  1805. value: function destroy() {
  1806. this.queue = null;
  1807. this.sourceBuffer = null;
  1808. this.offAll();
  1809. }
  1810. }, {
  1811. key: "doCleanup",
  1812. value: function doCleanup() {
  1813. if (!this.cleanRanges.length) {
  1814. this.cleaning = false;
  1815. return;
  1816. }
  1817. var range = this.cleanRanges.shift();
  1818. log("".concat(this.type, " remove range [").concat(range[0], " - ").concat(range[1], ")"));
  1819. this.cleaning = true;
  1820. this.sourceBuffer.remove(range[0], range[1]);
  1821. }
  1822. }, {
  1823. key: "initCleanup",
  1824. value: function initCleanup(cleanMaxLimit) {
  1825. if (this.sourceBuffer.updating) {
  1826. this.pendingCleaning = cleanMaxLimit;
  1827. return;
  1828. }
  1829. if (this.sourceBuffer.buffered && this.sourceBuffer.buffered.length && !this.cleaning) {
  1830. for (var i = 0; i < this.sourceBuffer.buffered.length; ++i) {
  1831. var start = this.sourceBuffer.buffered.start(i);
  1832. var end = this.sourceBuffer.buffered.end(i);
  1833. if (cleanMaxLimit - start > this.cleanOffset) {
  1834. end = cleanMaxLimit - this.cleanOffset;
  1835. if (start < end) {
  1836. this.cleanRanges.push([start, end]);
  1837. }
  1838. }
  1839. }
  1840. this.doCleanup();
  1841. }
  1842. }
  1843. }, {
  1844. key: "doAppend",
  1845. value: function doAppend() {
  1846. if (!this.queue.length) return;
  1847. if (this.sourceBuffer.updating) {
  1848. return;
  1849. }
  1850. try {
  1851. this.sourceBuffer.appendBuffer(this.queue);
  1852. this.queue = new Uint8Array();
  1853. } catch (e) {
  1854. if (e.name === 'QuotaExceededError') {
  1855. log("".concat(this.type, " buffer quota full"));
  1856. this.dispatch('error', {
  1857. type: this.type,
  1858. name: 'QuotaExceeded',
  1859. error: 'buffer error'
  1860. });
  1861. return;
  1862. }
  1863. error("Error occured while appending ".concat(this.type, " buffer - ").concat(e.name, ": ").concat(e.message));
  1864. this.dispatch('error', {
  1865. type: this.type,
  1866. name: 'unexpectedError',
  1867. error: 'buffer error'
  1868. });
  1869. }
  1870. }
  1871. }, {
  1872. key: "feed",
  1873. value: function feed(data) {
  1874. this.queue = appendByteArray(this.queue, data);
  1875. }
  1876. }]);
  1877. return BufferController;
  1878. }(Event);
  1879. window.MediaSource = window.MediaSource || window.WebKitMediaSource;
  1880. var JMuxmer = /*#__PURE__*/function (_Event) {
  1881. _inherits(JMuxmer, _Event);
  1882. var _super = _createSuper(JMuxmer);
  1883. _createClass(JMuxmer, null, [{
  1884. key: "isSupported",
  1885. value: function isSupported(codec) {
  1886. return window.MediaSource && window.MediaSource.isTypeSupported(codec);
  1887. }
  1888. }]);
  1889. function JMuxmer(options) {
  1890. var _this;
  1891. _classCallCheck(this, JMuxmer);
  1892. _this = _super.call(this, 'jmuxer');
  1893. window.MediaSource = window.MediaSource || window.WebKitMediaSource;
  1894. var defaults = {
  1895. node: '',
  1896. mode: 'both',
  1897. // both, audio, video
  1898. flushingTime: 1500,
  1899. clearBuffer: true,
  1900. onReady: null,
  1901. // function called when MSE is ready to accept frames
  1902. fps: 30,
  1903. debug: false
  1904. };
  1905. _this.options = Object.assign({}, defaults, options);
  1906. if (_this.options.debug) {
  1907. setLogger();
  1908. }
  1909. if (typeof _this.options.node === 'string' && _this.options.node == '') {
  1910. error('no video element were found to render, provide a valid video element');
  1911. }
  1912. if (!_this.options.fps) {
  1913. _this.options.fps = 30;
  1914. }
  1915. _this.frameDuration = 1000 / _this.options.fps | 0; // todo remove
  1916. _this.node = typeof _this.options.node === 'string' ? document.getElementById(_this.options.node) : _this.options.node;
  1917. _this.sourceBuffers = {};
  1918. _this.isMSESupported = !!window.MediaSource;
  1919. if (!_this.isMSESupported) {
  1920. throw 'Oops! Browser does not support media source extension.';
  1921. }
  1922. _this.setupMSE();
  1923. _this.remuxController = new RemuxController(_this.options.clearBuffer);
  1924. _this.remuxController.addTrack(_this.options.mode);
  1925. _this.mseReady = false;
  1926. _this.lastCleaningTime = Date.now();
  1927. _this.kfPosition = [];
  1928. _this.kfCounter = 0;
  1929. /* events callback */
  1930. _this.remuxController.on('buffer', _this.onBuffer.bind(_assertThisInitialized(_this)));
  1931. _this.remuxController.on('ready', _this.createBuffer.bind(_assertThisInitialized(_this)));
  1932. _this.startInterval();
  1933. return _this;
  1934. }
  1935. _createClass(JMuxmer, [{
  1936. key: "setupMSE",
  1937. value: function setupMSE() {
  1938. this.mediaSource = new MediaSource();
  1939. this.node.src = URL.createObjectURL(this.mediaSource);
  1940. this.mediaSource.addEventListener('sourceopen', this.onMSEOpen.bind(this));
  1941. this.mediaSource.addEventListener('sourceclose', this.onMSEClose.bind(this));
  1942. this.mediaSource.addEventListener('webkitsourceopen', this.onMSEOpen.bind(this));
  1943. this.mediaSource.addEventListener('webkitsourceclose', this.onMSEClose.bind(this));
  1944. }
  1945. }, {
  1946. key: "feed",
  1947. value: function feed(data) {
  1948. var remux = false,
  1949. slices,
  1950. duration,
  1951. chunks = {
  1952. video: [],
  1953. audio: []
  1954. };
  1955. if (!data || !this.remuxController) return;
  1956. duration = data.duration ? parseInt(data.duration) : 0;
  1957. if (data.video) {
  1958. slices = H264Parser.extractNALu(data.video);
  1959. if (slices.length > 0) {
  1960. chunks.video = this.getVideoFrames(slices, duration);
  1961. remux = true;
  1962. }
  1963. }
  1964. if (data.audio) {
  1965. slices = AACParser.extractAAC(data.audio);
  1966. if (slices.length > 0) {
  1967. chunks.audio = this.getAudioFrames(slices, duration);
  1968. remux = true;
  1969. }
  1970. }
  1971. if (!remux) {
  1972. error('Input object must have video and/or audio property. Make sure it is a valid typed array');
  1973. return;
  1974. }
  1975. this.remuxController.remux(chunks);
  1976. }
  1977. }, {
  1978. key: "getVideoFrames",
  1979. value: function getVideoFrames(nalus, duration) {
  1980. var _this2 = this;
  1981. var units = [],
  1982. frames = [],
  1983. fd = 0,
  1984. tt = 0,
  1985. keyFrame = false,
  1986. vcl = false;
  1987. var _iterator = _createForOfIteratorHelper(nalus),
  1988. _step;
  1989. try {
  1990. for (_iterator.s(); !(_step = _iterator.n()).done;) {
  1991. var nalu = _step.value;
  1992. var unit = new NALU(nalu);
  1993. if (unit.type() === NALU.IDR || unit.type() === NALU.NDR) {
  1994. H264Parser.parseHeader(unit);
  1995. }
  1996. if (units.length && vcl && (unit.isfmb || !unit.isvcl)) {
  1997. frames.push({
  1998. units: units,
  1999. keyFrame: keyFrame
  2000. });
  2001. units = [];
  2002. keyFrame = false;
  2003. vcl = false;
  2004. }
  2005. units.push(unit);
  2006. keyFrame = keyFrame || unit.isKeyframe();
  2007. vcl = vcl || unit.isvcl;
  2008. }
  2009. } catch (err) {
  2010. _iterator.e(err);
  2011. } finally {
  2012. _iterator.f();
  2013. }
  2014. if (units.length) {
  2015. if (vcl || !frames.length) {
  2016. frames.push({
  2017. units: units,
  2018. keyFrame: keyFrame
  2019. });
  2020. } else {
  2021. var last = frames.length - 1;
  2022. frames[last].units = frames[last].units.concat(units);
  2023. }
  2024. }
  2025. fd = duration ? duration / frames.length | 0 : this.frameDuration;
  2026. tt = duration ? duration - fd * frames.length : 0;
  2027. frames.map(function (frame) {
  2028. frame.duration = fd;
  2029. if (tt > 0) {
  2030. frame.duration++;
  2031. tt--;
  2032. }
  2033. _this2.kfCounter++;
  2034. if (frame.keyFrame && _this2.options.clearBuffer) {
  2035. _this2.kfPosition.push(_this2.kfCounter * fd / 1000);
  2036. }
  2037. });
  2038. log("jmuxer: No. of frames of the last chunk: ".concat(frames.length));
  2039. return frames;
  2040. }
  2041. }, {
  2042. key: "getAudioFrames",
  2043. value: function getAudioFrames(aacFrames, duration) {
  2044. var frames = [],
  2045. fd = 0,
  2046. tt = 0;
  2047. var _iterator2 = _createForOfIteratorHelper(aacFrames),
  2048. _step2;
  2049. try {
  2050. for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
  2051. var units = _step2.value;
  2052. frames.push({
  2053. units: units
  2054. });
  2055. }
  2056. } catch (err) {
  2057. _iterator2.e(err);
  2058. } finally {
  2059. _iterator2.f();
  2060. }
  2061. fd = duration ? duration / frames.length | 0 : this.frameDuration;
  2062. tt = duration ? duration - fd * frames.length : 0;
  2063. frames.map(function (frame) {
  2064. frame.duration = fd;
  2065. if (tt > 0) {
  2066. frame.duration++;
  2067. tt--;
  2068. }
  2069. });
  2070. return frames;
  2071. }
  2072. }, {
  2073. key: "destroy",
  2074. value: function destroy() {
  2075. this.stopInterval();
  2076. if (this.mediaSource) {
  2077. try {
  2078. if (this.bufferControllers) {
  2079. this.mediaSource.endOfStream();
  2080. }
  2081. } catch (e) {
  2082. error("mediasource is not available to end ".concat(e.message));
  2083. }
  2084. this.mediaSource = null;
  2085. }
  2086. if (this.remuxController) {
  2087. this.remuxController.destroy();
  2088. this.remuxController = null;
  2089. }
  2090. if (this.bufferControllers) {
  2091. for (var type in this.bufferControllers) {
  2092. this.bufferControllers[type].destroy();
  2093. }
  2094. this.bufferControllers = null;
  2095. }
  2096. this.node = false;
  2097. this.mseReady = false;
  2098. this.videoStarted = false;
  2099. }
  2100. }, {
  2101. key: "createBuffer",
  2102. value: function createBuffer() {
  2103. if (!this.mseReady || !this.remuxController || !this.remuxController.isReady() || this.bufferControllers) return;
  2104. this.bufferControllers = {};
  2105. for (var type in this.remuxController.tracks) {
  2106. var track = this.remuxController.tracks[type];
  2107. if (!JMuxmer.isSupported("".concat(type, "/mp4; codecs=\"").concat(track.mp4track.codec, "\""))) {
  2108. error('Browser does not support codec');
  2109. return false;
  2110. }
  2111. var sb = this.mediaSource.addSourceBuffer("".concat(type, "/mp4; codecs=\"").concat(track.mp4track.codec, "\""));
  2112. this.bufferControllers[type] = new BufferController(sb, type);
  2113. this.sourceBuffers[type] = sb;
  2114. this.bufferControllers[type].on('error', this.onBufferError.bind(this));
  2115. }
  2116. }
  2117. }, {
  2118. key: "startInterval",
  2119. value: function startInterval() {
  2120. var _this3 = this;
  2121. this.interval = setInterval(function () {
  2122. if (_this3.bufferControllers) {
  2123. _this3.releaseBuffer();
  2124. _this3.clearBuffer();
  2125. }
  2126. }, this.options.flushingTime);
  2127. }
  2128. }, {
  2129. key: "stopInterval",
  2130. value: function stopInterval() {
  2131. if (this.interval) {
  2132. clearInterval(this.interval);
  2133. }
  2134. }
  2135. }, {
  2136. key: "releaseBuffer",
  2137. value: function releaseBuffer() {
  2138. for (var type in this.bufferControllers) {
  2139. this.bufferControllers[type].doAppend();
  2140. }
  2141. }
  2142. }, {
  2143. key: "getSafeClearOffsetOfBuffer",
  2144. value: function getSafeClearOffsetOfBuffer(offset) {
  2145. var maxLimit = this.options.mode === 'audio' && offset || 0,
  2146. adjacentOffset;
  2147. for (var i = 0; i < this.kfPosition.length; i++) {
  2148. if (this.kfPosition[i] >= offset) {
  2149. break;
  2150. }
  2151. adjacentOffset = this.kfPosition[i];
  2152. }
  2153. if (adjacentOffset) {
  2154. this.kfPosition = this.kfPosition.filter(function (kfDelimiter) {
  2155. if (kfDelimiter < adjacentOffset) {
  2156. maxLimit = kfDelimiter;
  2157. }
  2158. return kfDelimiter >= adjacentOffset;
  2159. });
  2160. }
  2161. return maxLimit;
  2162. }
  2163. }, {
  2164. key: "clearBuffer",
  2165. value: function clearBuffer() {
  2166. if (this.options.clearBuffer && Date.now() - this.lastCleaningTime > 10000) {
  2167. for (var type in this.bufferControllers) {
  2168. var cleanMaxLimit = this.getSafeClearOffsetOfBuffer(this.node.currentTime);
  2169. this.bufferControllers[type].initCleanup(cleanMaxLimit);
  2170. }
  2171. this.lastCleaningTime = Date.now();
  2172. }
  2173. }
  2174. }, {
  2175. key: "onBuffer",
  2176. value: function onBuffer(data) {
  2177. if (this.bufferControllers && this.bufferControllers[data.type]) {
  2178. this.bufferControllers[data.type].feed(data.payload);
  2179. }
  2180. }
  2181. /* Events on MSE */
  2182. }, {
  2183. key: "onMSEOpen",
  2184. value: function onMSEOpen() {
  2185. this.mseReady = true;
  2186. if (typeof this.options.onReady === 'function') {
  2187. this.options.onReady();
  2188. this.options.onReady = null;
  2189. }
  2190. this.createBuffer();
  2191. }
  2192. }, {
  2193. key: "onMSEClose",
  2194. value: function onMSEClose() {
  2195. this.mseReady = false;
  2196. this.videoStarted = false;
  2197. }
  2198. }, {
  2199. key: "onBufferError",
  2200. value: function onBufferError(data) {
  2201. if (data.name == 'QuotaExceeded') {
  2202. this.bufferControllers[data.type].initCleanup(this.node.currentTime);
  2203. return;
  2204. }
  2205. if (this.mediaSource.sourceBuffers.length > 0 && this.sourceBuffers[data.type]) {
  2206. this.mediaSource.removeSourceBuffer(this.sourceBuffers[data.type]);
  2207. }
  2208. if (this.mediaSource.sourceBuffers.length == 0) {
  2209. try {
  2210. this.mediaSource.endOfStream();
  2211. } catch (e) {
  2212. error('mediasource is not available to end');
  2213. }
  2214. }
  2215. }
  2216. }]);
  2217. return JMuxmer;
  2218. }(Event);
  2219. return JMuxmer;
  2220. }());