jmuxer.js 74 KB

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