# Source: transmux-worker.js

    /**
     * @file transmuxer-worker.js
     */

    /**
     * videojs-contrib-media-sources
     *
     * Copyright (c) 2015 Brightcove
     * All rights reserved.
     *
     * Handles communication between the browser-world and the mux.js
     * transmuxer running inside of a WebWorker by exposing a simple
     * message-based interface to a Transmuxer object.
     */
    import window from 'global/window';
    import mp4 from 'mux.js/lib/mp4';

    /**
     * Re-emits tranmsuxer events by converting them into messages to the
     * world outside the worker.
     *
     * @param {Object} transmuxer the transmuxer to wire events on
     * @private
     */
    const wireTransmuxerEvents = function(transmuxer) {
      transmuxer.on('data', function(segment) {
        // transfer ownership of the underlying ArrayBuffer
        // instead of doing a copy to save memory
        // ArrayBuffers are transferable but generic TypedArrays are not
        // @link https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers#Passing_data_by_transferring_ownership_(transferable_objects)
        let typedArray = segment.data;

        segment.data = typedArray.buffer;
        window.postMessage({
          action: 'data',
          segment,
          byteOffset: typedArray.byteOffset,
          byteLength: typedArray.byteLength
        }, [segment.data]);
      });

      if (transmuxer.captionStream) {
        transmuxer.captionStream.on('data', function(caption) {
          window.postMessage({
            action: 'caption',
            data: caption
          });
        });
      }

      transmuxer.on('done', function(data) {
        window.postMessage({ action: 'done' });
      });
    };

    /**
     * All incoming messages route through this hash. If no function exists
     * to handle an incoming message, then we ignore the message.
     *
     * @class MessageHandlers
     * @param {Object} options the options to initialize with
     */
    class MessageHandlers {
      constructor(options) {
        this.options = options || {};
        this.init();
      }

      /**
       * initialize our web worker and wire all the events.
       */
      init() {
        if (this.transmuxer) {
          this.transmuxer.dispose();
        }
        this.transmuxer = new mp4.Transmuxer(this.options);
        wireTransmuxerEvents(this.transmuxer);
      }

      /**
       * Adds data (a ts segment) to the start of the transmuxer pipeline for
       * processing.
       *
       * @param {ArrayBuffer} data data to push into the muxer
       */
      push(data) {
        // Cast array buffer to correct type for transmuxer
        let segment = new Uint8Array(data.data, data.byteOffset, data.byteLength);

        this.transmuxer.push(segment);
      }

      /**
       * Recreate the transmuxer so that the next segment added via `push`
       * start with a fresh transmuxer.
       */
      reset() {
        this.init();
      }

      /**
       * Set the value that will be used as the `baseMediaDecodeTime` time for the
       * next segment pushed in. Subsequent segments will have their `baseMediaDecodeTime`
       * set relative to the first based on the PTS values.
       *
       * @param {Object} data used to set the timestamp offset in the muxer
       */
      setTimestampOffset(data) {
        let timestampOffset = data.timestampOffset || 0;

        this.transmuxer.setBaseMediaDecodeTime(Math.round(timestampOffset * 90000));
      }

      /**
       * Forces the pipeline to finish processing the last segment and emit it's
       * results.
       *
       * @param {Object} data event data, not really used
       */
      flush(data) {
        this.transmuxer.flush();
      }
    }

    /**
     * Our web wroker interface so that things can talk to mux.js
     * that will be running in a web worker. the scope is passed to this by
     * webworkify.
     *
     * @param {Object} self the scope for the web worker
     */
    const Worker = function(self) {
      self.onmessage = function(event) {
        if (event.data.action === 'init' && event.data.options) {
          this.messageHandlers = new MessageHandlers(event.data.options);
          return;
        }

        if (!this.messageHandlers) {
          this.messageHandlers = new MessageHandlers();
        }

        if (event.data && event.data.action && event.data.action !== 'init') {
          if (this.messageHandlers[event.data.action]) {
            this.messageHandlers[event.data.action](event.data);
          }
        }
      };
    };

    export default (self) => {
      return new Worker(self);
    };