# All files / src/demux demuxer-inline.js

15.38% Statements 8/52
3.57% Branches 1/28
40% Functions 2/5
15.38% Lines 8/52

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125

    11x

    11x

    3x
    3x
    3x
    3x

    1x
    1x

     /**
     *
     * inline demuxer: probe fragments and instantiate
     * appropriate demuxer depending on content type (TSDemuxer, AACDemuxer, ...)
     *
     */

    import Event from '../events';
    import { ErrorTypes, ErrorDetails } from '../errors';
    import Decrypter from '../crypt/decrypter';
    import AACDemuxer from '../demux/aacdemuxer';
    import MP4Demuxer from '../demux/mp4demuxer';
    import TSDemuxer from '../demux/tsdemuxer';
    import MP3Demuxer from '../demux/mp3demuxer';
    import MP4Remuxer from '../remux/mp4-remuxer';
    import PassThroughRemuxer from '../remux/passthrough-remuxer';

    import { getSelfScope } from '../utils/get-self-scope';

    // see https://stackoverflow.com/a/11237259/589493
    /* eslint-disable-next-line no-undef */
    const window = getSelfScope(); // safeguard for code that might run both on worker and main thread

    const { performance } = window;

    class DemuxerInline {
      constructor (observer, typeSupported, config, vendor) {
        this.observer = observer;
        this.typeSupported = typeSupported;
        this.config = config;
        this.vendor = vendor;
      }

      destroy () {
        let demuxer = this.demuxer;
        Iif (demuxer) {
          demuxer.destroy();
        }
      }

      push (data, decryptdata, initSegment, audioCodec, videoCodec, timeOffset, discontinuity, trackSwitch, contiguous, duration, accurateTimeOffset, defaultInitPTS) {
        if ((data.byteLength > 0) && (decryptdata != null) && (decryptdata.key != null) && (decryptdata.method === 'AES-128')) {
          let decrypter = this.decrypter;
          if (decrypter == null) {
            decrypter = this.decrypter = new Decrypter(this.observer, this.config);
          }

          let localthis = this;
          // performance.now() not available on WebWorker, at least on Safari Desktop
          let startTime;
          try {
            startTime = performance.now();
          } catch (error) {
            startTime = Date.now();
          }
          decrypter.decrypt(data, decryptdata.key.buffer, decryptdata.iv.buffer, function (decryptedData) {
            let endTime;
            try {
              endTime = performance.now();
            } catch (error) {
              endTime = Date.now();
            }
            localthis.observer.trigger(Event.FRAG_DECRYPTED, { stats: { tstart: startTime, tdecrypt: endTime } });
            localthis.pushDecrypted(new Uint8Array(decryptedData), decryptdata, new Uint8Array(initSegment), audioCodec, videoCodec, timeOffset, discontinuity, trackSwitch, contiguous, duration, accurateTimeOffset, defaultInitPTS);
          });
        } else {
          this.pushDecrypted(new Uint8Array(data), decryptdata, new Uint8Array(initSegment), audioCodec, videoCodec, timeOffset, discontinuity, trackSwitch, contiguous, duration, accurateTimeOffset, defaultInitPTS);
        }
      }

      pushDecrypted (data, decryptdata, initSegment, audioCodec, videoCodec, timeOffset, discontinuity, trackSwitch, contiguous, duration, accurateTimeOffset, defaultInitPTS) {
        let demuxer = this.demuxer;
        if (!demuxer ||
          // in case of continuity change, or track switch
          // we might switch from content type (AAC container to TS container, or TS to fmp4 for example)
          // so let's check that current demuxer is still valid
          ((discontinuity || trackSwitch) && !this.probe(data))) {
          const observer = this.observer;
          const typeSupported = this.typeSupported;
          const config = this.config;
          // probing order is TS/AAC/MP3/MP4
          const muxConfig = [
            { demux: TSDemuxer, remux: MP4Remuxer },
            { demux: MP4Demuxer, remux: PassThroughRemuxer },
            { demux: AACDemuxer, remux: MP4Remuxer },
            { demux: MP3Demuxer, remux: MP4Remuxer }
          ];

          // probe for content type
          for (let i = 0, len = muxConfig.length; i < len; i++) {
            const mux = muxConfig[i];
            const probe = mux.demux.probe;
            if (probe(data)) {
              const remuxer = this.remuxer = new mux.remux(observer, config, typeSupported, this.vendor);
              demuxer = new mux.demux(observer, remuxer, config, typeSupported);
              this.probe = probe;
              break;
            }
          }
          if (!demuxer) {
            observer.trigger(Event.ERROR, { type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.FRAG_PARSING_ERROR, fatal: true, reason: 'no demux matching with content found' });
            return;
          }
          this.demuxer = demuxer;
        }
        const remuxer = this.remuxer;

        if (discontinuity || trackSwitch) {
          demuxer.resetInitSegment(initSegment, audioCodec, videoCodec, duration);
          remuxer.resetInitSegment();
        }
        if (discontinuity) {
          demuxer.resetTimeStamp(defaultInitPTS);
          remuxer.resetTimeStamp(defaultInitPTS);
        }
        if (typeof demuxer.setDecryptData === 'function') {
          demuxer.setDecryptData(decryptdata);
        }

        demuxer.append(data, timeOffset, contiguous, accurateTimeOffset);
      }
    }

    export default DemuxerInline;