source-updater.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /**
  2. * @file source-updater.js
  3. */
  4. 'use strict';
  5. Object.defineProperty(exports, '__esModule', {
  6. value: true
  7. });
  8. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  9. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  10. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
  11. var _videoJs = require('video.js');
  12. var _videoJs2 = _interopRequireDefault(_videoJs);
  13. var noop = function noop() {};
  14. /**
  15. * A queue of callbacks to be serialized and applied when a
  16. * MediaSource and its associated SourceBuffers are not in the
  17. * updating state. It is used by the segment loader to update the
  18. * underlying SourceBuffers when new data is loaded, for instance.
  19. *
  20. * @class SourceUpdater
  21. * @param {MediaSource} mediaSource the MediaSource to create the
  22. * SourceBuffer from
  23. * @param {String} mimeType the desired MIME type of the underlying
  24. * SourceBuffer
  25. */
  26. var SourceUpdater = (function () {
  27. function SourceUpdater(mediaSource, mimeType) {
  28. var _this = this;
  29. _classCallCheck(this, SourceUpdater);
  30. var createSourceBuffer = function createSourceBuffer() {
  31. _this.sourceBuffer_ = mediaSource.addSourceBuffer(mimeType);
  32. // run completion handlers and process callbacks as updateend
  33. // events fire
  34. _this.onUpdateendCallback_ = function () {
  35. var pendingCallback = _this.pendingCallback_;
  36. _this.pendingCallback_ = null;
  37. if (pendingCallback) {
  38. pendingCallback();
  39. }
  40. _this.runCallback_();
  41. };
  42. _this.sourceBuffer_.addEventListener('updateend', _this.onUpdateendCallback_);
  43. _this.runCallback_();
  44. };
  45. this.callbacks_ = [];
  46. this.pendingCallback_ = null;
  47. this.timestampOffset_ = 0;
  48. this.mediaSource = mediaSource;
  49. this.processedAppend_ = false;
  50. if (mediaSource.readyState === 'closed') {
  51. mediaSource.addEventListener('sourceopen', createSourceBuffer);
  52. } else {
  53. createSourceBuffer();
  54. }
  55. }
  56. /**
  57. * Aborts the current segment and resets the segment parser.
  58. *
  59. * @param {Function} done function to call when done
  60. * @see http://w3c.github.io/media-source/#widl-SourceBuffer-abort-void
  61. */
  62. _createClass(SourceUpdater, [{
  63. key: 'abort',
  64. value: function abort(done) {
  65. var _this2 = this;
  66. if (this.processedAppend_) {
  67. this.queueCallback_(function () {
  68. _this2.sourceBuffer_.abort();
  69. }, done);
  70. }
  71. }
  72. /**
  73. * Queue an update to append an ArrayBuffer.
  74. *
  75. * @param {ArrayBuffer} bytes
  76. * @param {Function} done the function to call when done
  77. * @see http://www.w3.org/TR/media-source/#widl-SourceBuffer-appendBuffer-void-ArrayBuffer-data
  78. */
  79. }, {
  80. key: 'appendBuffer',
  81. value: function appendBuffer(bytes, done) {
  82. var _this3 = this;
  83. this.processedAppend_ = true;
  84. this.queueCallback_(function () {
  85. _this3.sourceBuffer_.appendBuffer(bytes);
  86. }, done);
  87. }
  88. /**
  89. * Indicates what TimeRanges are buffered in the managed SourceBuffer.
  90. *
  91. * @see http://www.w3.org/TR/media-source/#widl-SourceBuffer-buffered
  92. */
  93. }, {
  94. key: 'buffered',
  95. value: function buffered() {
  96. if (!this.sourceBuffer_) {
  97. return _videoJs2['default'].createTimeRanges();
  98. }
  99. return this.sourceBuffer_.buffered;
  100. }
  101. /**
  102. * Queue an update to remove a time range from the buffer.
  103. *
  104. * @param {Number} start where to start the removal
  105. * @param {Number} end where to end the removal
  106. * @see http://www.w3.org/TR/media-source/#widl-SourceBuffer-remove-void-double-start-unrestricted-double-end
  107. */
  108. }, {
  109. key: 'remove',
  110. value: function remove(start, end) {
  111. var _this4 = this;
  112. if (this.processedAppend_) {
  113. this.queueCallback_(function () {
  114. _this4.sourceBuffer_.remove(start, end);
  115. }, noop);
  116. }
  117. }
  118. /**
  119. * Whether the underlying sourceBuffer is updating or not
  120. *
  121. * @return {Boolean} the updating status of the SourceBuffer
  122. */
  123. }, {
  124. key: 'updating',
  125. value: function updating() {
  126. return !this.sourceBuffer_ || this.sourceBuffer_.updating || this.pendingCallback_;
  127. }
  128. /**
  129. * Set/get the timestampoffset on the SourceBuffer
  130. *
  131. * @return {Number} the timestamp offset
  132. */
  133. }, {
  134. key: 'timestampOffset',
  135. value: function timestampOffset(offset) {
  136. var _this5 = this;
  137. if (typeof offset !== 'undefined') {
  138. this.queueCallback_(function () {
  139. _this5.sourceBuffer_.timestampOffset = offset;
  140. });
  141. this.timestampOffset_ = offset;
  142. }
  143. return this.timestampOffset_;
  144. }
  145. /**
  146. * Queue a callback to run
  147. */
  148. }, {
  149. key: 'queueCallback_',
  150. value: function queueCallback_(callback, done) {
  151. this.callbacks_.push([callback.bind(this), done]);
  152. this.runCallback_();
  153. }
  154. /**
  155. * Run a queued callback
  156. */
  157. }, {
  158. key: 'runCallback_',
  159. value: function runCallback_() {
  160. var callbacks = undefined;
  161. if (!this.updating() && this.callbacks_.length) {
  162. callbacks = this.callbacks_.shift();
  163. this.pendingCallback_ = callbacks[1];
  164. callbacks[0]();
  165. }
  166. }
  167. /**
  168. * dispose of the source updater and the underlying sourceBuffer
  169. */
  170. }, {
  171. key: 'dispose',
  172. value: function dispose() {
  173. this.sourceBuffer_.removeEventListener('updateend', this.onUpdateendCallback_);
  174. if (this.sourceBuffer_ && this.mediaSource.readyState === 'open') {
  175. this.sourceBuffer_.abort();
  176. }
  177. }
  178. }]);
  179. return SourceUpdater;
  180. })();
  181. exports['default'] = SourceUpdater;
  182. module.exports = exports['default'];