# All files / src/demux mp3demuxer.js

24.44% Statements 11/45
0% Branches 0/14
14.29% Functions 1/7
25% Lines 11/44

    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

    16x
    16x
    16x

    16x

    16x

    16x

    16x

    16x

    16x

    16x

    16x
     /**
     * MP3 demuxer
     */
    import ID3 from '../demux/id3';
    import { logger } from '../utils/logger';
    import MpegAudio from './mpegaudio';

    class MP3Demuxer {
      constructor (observer, remuxer, config) {
        this.observer = observer;
        this.config = config;
        this.remuxer = remuxer;
      }

      resetInitSegment (initSegment, audioCodec, videoCodec, duration) {
        this._audioTrack = { container: 'audio/mpeg', type: 'audio', id: -1, sequenceNumber: 0, isAAC: false, samples: [], len: 0, manifestCodec: audioCodec, duration: duration, inputTimeScale: 90000 };
      }

      resetTimeStamp () {
      }

      static probe (data) {
        // check if data contains ID3 timestamp and MPEG sync word
        let offset, length;
        let id3Data = ID3.getID3Data(data, 0);
        if (id3Data && ID3.getTimeStamp(id3Data) !== undefined) {
          // Look for MPEG header | 1111 1111 | 111X XYZX | where X can be either 0 or 1 and Y or Z should be 1
          // Layer bits (position 14 and 15) in header should be always different from 0 (Layer I or Layer II or Layer III)
          // More info http://www.mp3-tech.org/programmer/frame_header.html
          for (offset = id3Data.length, length = Math.min(data.length - 1, offset + 100); offset < length; offset++) {
            if (MpegAudio.probe(data, offset)) {
              logger.log('MPEG Audio sync word found !');
              return true;
            }
          }
        }
        return false;
      }

      // feed incoming data to the front of the parsing pipeline
      append (data, timeOffset, contiguous, accurateTimeOffset) {
        let id3Data = ID3.getID3Data(data, 0);
        let timestamp = ID3.getTimeStamp(id3Data);
        let pts = timestamp ? 90 * timestamp : timeOffset * 90000;
        let offset = id3Data.length;
        let length = data.length;
        let frameIndex = 0, stamp = 0;
        let track = this._audioTrack;

        let id3Samples = [{ pts: pts, dts: pts, data: id3Data }];

        while (offset < length) {
          if (MpegAudio.isHeader(data, offset)) {
            let frame = MpegAudio.appendFrame(track, data, offset, pts, frameIndex);
            if (frame) {
              offset += frame.length;
              stamp = frame.sample.pts;
              frameIndex++;
            } else {
              // logger.log('Unable to parse Mpeg audio frame');
              break;
            }
          } else if (ID3.isHeader(data, offset)) {
            id3Data = ID3.getID3Data(data, offset);
            id3Samples.push({ pts: stamp, dts: stamp, data: id3Data });
            offset += id3Data.length;
          } else {
            // nothing found, keep looking
            offset++;
          }
        }

        this.remuxer.remux(track,
          { samples: [] },
          { samples: id3Samples, inputTimeScale: 90000 },
          { samples: [] },
          timeOffset,
          contiguous,
          accurateTimeOffset);
      }

      destroy () {
      }
    }

    export default MP3Demuxer;