text: /**
   * mux.js
   *
   * Copyright (c) Brightcove
   * Licensed Apache-2.0 https://github.com/videojs/mux.js/blob/master/LICENSE
   */
  var
    tagTypes = {
      0x08: 'audio',
      0x09: 'video',
      0x12: 'metadata'
    },
    hex = function(val) {
      return '0x' + ('00' + val.toString(16)).slice(-2).toUpperCase();
    },
    hexStringList = function(data) {
      var arr = [], i;
  
      while (data.byteLength > 0) {
        i = 0;
        arr.push(hex(data[i++]));
        data = data.subarray(i);
      }
      return arr.join(' ');
    },
    parseAVCTag = function(tag, obj) {
      var
        avcPacketTypes = [
          'AVC Sequence Header',
          'AVC NALU',
          'AVC End-of-Sequence'
        ],
        compositionTime = (tag[1] & parseInt('01111111', 2) << 16) | (tag[2] << 8) | tag[3];
  
      obj = obj || {};
  
      obj.avcPacketType = avcPacketTypes[tag[0]];
      obj.CompositionTime = (tag[1] & parseInt('10000000', 2)) ? -compositionTime : compositionTime;
  
      if (tag[0] === 1) {
        obj.nalUnitTypeRaw = hexStringList(tag.subarray(4, 100));
      } else {
        obj.data = hexStringList(tag.subarray(4));
      }
  
      return obj;
    },
    parseVideoTag = function(tag, obj) {
      var
        frameTypes = [
          'Unknown',
          'Keyframe (for AVC, a seekable frame)',
          'Inter frame (for AVC, a nonseekable frame)',
          'Disposable inter frame (H.263 only)',
          'Generated keyframe (reserved for server use only)',
          'Video info/command frame'
        ],
        codecID = tag[0] & parseInt('00001111', 2);
  
      obj = obj || {};
  
      obj.frameType = frameTypes[(tag[0] & parseInt('11110000', 2)) >>> 4];
      obj.codecID = codecID;
  
      if (codecID === 7) {
        return parseAVCTag(tag.subarray(1), obj);
      }
      return obj;
    },
    parseAACTag = function(tag, obj) {
      var packetTypes = [
        'AAC Sequence Header',
        'AAC Raw'
      ];
  
      obj = obj || {};
  
      obj.aacPacketType = packetTypes[tag[0]];
      obj.data = hexStringList(tag.subarray(1));
  
      return obj;
    },
    parseAudioTag = function(tag, obj) {
      var
        formatTable = [
          'Linear PCM, platform endian',
          'ADPCM',
          'MP3',
          'Linear PCM, little endian',
          'Nellymoser 16-kHz mono',
          'Nellymoser 8-kHz mono',
          'Nellymoser',
          'G.711 A-law logarithmic PCM',
          'G.711 mu-law logarithmic PCM',
          'reserved',
          'AAC',
          'Speex',
          'MP3 8-Khz',
          'Device-specific sound'
        ],
        samplingRateTable = [
          '5.5-kHz',
          '11-kHz',
          '22-kHz',
          '44-kHz'
        ],
        soundFormat = (tag[0] & parseInt('11110000', 2)) >>> 4;
  
      obj = obj || {};
  
      obj.soundFormat = formatTable[soundFormat];
      obj.soundRate = samplingRateTable[(tag[0] & parseInt('00001100', 2)) >>> 2];
      obj.soundSize = ((tag[0] & parseInt('00000010', 2)) >>> 1) ? '16-bit' : '8-bit';
      obj.soundType = (tag[0] & parseInt('00000001', 2)) ? 'Stereo' : 'Mono';
  
      if (soundFormat === 10) {
        return parseAACTag(tag.subarray(1), obj);
      }
      return obj;
    },
    parseGenericTag = function(tag) {
      return {
        tagType: tagTypes[tag[0]],
        dataSize: (tag[1] << 16) | (tag[2] << 8) | tag[3],
        timestamp: (tag[7] << 24) | (tag[4] << 16) | (tag[5] << 8) | tag[6],
        streamID: (tag[8] << 16) | (tag[9] << 8) | tag[10]
      };
    },
    inspectFlvTag = function(tag) {
      var header = parseGenericTag(tag);
      switch (tag[0]) {
        case 0x08:
          parseAudioTag(tag.subarray(11), header);
          break;
        case 0x09:
          parseVideoTag(tag.subarray(11), header);
          break;
        case 0x12:
      }
      return header;
    },
    inspectFlv = function(bytes) {
      var i = 9, // header
          dataSize,
          parsedResults = [],
          tag;
  
      // traverse the tags
      i += 4; // skip previous tag size
      while (i < bytes.byteLength) {
        dataSize = bytes[i + 1] << 16;
        dataSize |= bytes[i + 2] << 8;
        dataSize |= bytes[i + 3];
        dataSize += 11;
  
        tag = bytes.subarray(i, i + dataSize);
        parsedResults.push(inspectFlvTag(tag));
        i += dataSize + 4;
      }
      return parsedResults;
    },
    textifyFlv = function(flvTagArray) {
      return JSON.stringify(flvTagArray, null, 2);
    };
  
  export default {
    inspectFlvTag,
    inspectFlv,
    textifyFlv
  };
  