Home Reference Source

src/controller/buffer-operation-queue.ts

  1. import { logger } from '../utils/logger';
  2. import type {
  3. BufferOperation,
  4. BufferOperationQueues,
  5. SourceBuffers,
  6. SourceBufferName,
  7. } from '../types/buffer';
  8.  
  9. export default class BufferOperationQueue {
  10. private buffers: SourceBuffers;
  11. private queues: BufferOperationQueues = {
  12. video: [],
  13. audio: [],
  14. audiovideo: [],
  15. };
  16.  
  17. constructor(sourceBufferReference: SourceBuffers) {
  18. this.buffers = sourceBufferReference;
  19. }
  20.  
  21. public append(operation: BufferOperation, type: SourceBufferName) {
  22. const queue = this.queues[type];
  23. queue.push(operation);
  24. if (queue.length === 1 && this.buffers[type]) {
  25. this.executeNext(type);
  26. }
  27. }
  28.  
  29. public insertAbort(operation: BufferOperation, type: SourceBufferName) {
  30. const queue = this.queues[type];
  31. queue.unshift(operation);
  32. this.executeNext(type);
  33. }
  34.  
  35. public appendBlocker(type: SourceBufferName): Promise<{}> {
  36. let execute;
  37. const promise: Promise<{}> = new Promise((resolve) => {
  38. execute = resolve;
  39. });
  40. const operation: BufferOperation = {
  41. execute,
  42. onStart: () => {},
  43. onComplete: () => {},
  44. onError: () => {},
  45. };
  46.  
  47. this.append(operation, type);
  48. return promise;
  49. }
  50.  
  51. public executeNext(type: SourceBufferName) {
  52. const { buffers, queues } = this;
  53. const sb = buffers[type];
  54. const queue = queues[type];
  55. if (queue.length) {
  56. const operation: BufferOperation = queue[0];
  57. try {
  58. // Operations are expected to result in an 'updateend' event being fired. If not, the queue will lock. Operations
  59. // which do not end with this event must call _onSBUpdateEnd manually
  60. operation.execute();
  61. } catch (e) {
  62. logger.warn(
  63. '[buffer-operation-queue]: Unhandled exception executing the current operation'
  64. );
  65. operation.onError(e);
  66.  
  67. // Only shift the current operation off, otherwise the updateend handler will do this for us
  68. if (!sb || !sb.updating) {
  69. queue.shift();
  70. }
  71. }
  72. }
  73. }
  74.  
  75. public shiftAndExecuteNext(type: SourceBufferName) {
  76. this.queues[type].shift();
  77. this.executeNext(type);
  78. }
  79.  
  80. public current(type: SourceBufferName) {
  81. return this.queues[type][0];
  82. }
  83. }