processMediaSegment_(data, stream, reference) {
    let i;
    /** @type {!ISOFile} */
    const isoFile = this.isoBoxer_.parseBuffer(data);
    // Update track_Id in tfhd box
    const tfhd = isoFile.fetch('tfhd');
    tfhd.track_ID = stream.id + 1;
    // Add tfdt box
    let tfdt = isoFile.fetch('tfdt');
    const traf = isoFile.fetch('traf');
    if (tfdt === null) {
      tfdt = this.isoBoxer_.createFullBox('tfdt', traf, tfhd);
      tfdt.version = 1;
      tfdt.flags = 0;
      const timescale = stream.mssPrivateData.timescale;
      const startTime = reference.startTime;
      tfdt.baseMediaDecodeTime = Math.floor(startTime * timescale);
    }
    const trun = isoFile.fetch('trun');
    // Process tfxd boxes
    // This box provide absolute timestamp but we take the segment start
    // time for tfdt
    let tfxd = isoFile.fetch('tfxd');
    if (tfxd) {
      tfxd._parent.boxes.splice(tfxd._parent.boxes.indexOf(tfxd), 1);
      tfxd = null;
    }
    let tfrf = isoFile.fetch('tfrf');
    if (tfrf) {
      tfrf._parent.boxes.splice(tfrf._parent.boxes.indexOf(tfrf), 1);
      tfrf = null;
    }

    // If protected content in PIFF1.1 format
    // (sepiff box = Sample Encryption PIFF)
    // => convert sepiff box it into a senc box
    // => create saio and saiz boxes (if not already present)
    const sepiff = isoFile.fetch('sepiff');
    if (sepiff !== null) {
      sepiff.type = 'senc';
      sepiff.usertype = undefined;

      let saio = isoFile.fetch('saio');
      if (saio === null) {
        // Create Sample Auxiliary Information Offsets Box box (saio)
        saio = this.isoBoxer_.createFullBox('saio', traf);
        saio.version = 0;
        saio.flags = 0;
        saio.entry_count = 1;
        saio.offset = [0];
        const saiz = this.isoBoxer_.createFullBox('saiz', traf);
        saiz.version = 0;
        saiz.flags = 0;
        saiz.sample_count = sepiff.sample_count;
        saiz.default_sample_info_size = 0;
        saiz.sample_info_size = [];
        if (sepiff.flags & 0x02) {
          // Sub-sample encryption => set sample_info_size for each sample
          for (i = 0; i < sepiff.sample_count; i += 1) {
            // 10 = 8 (InitializationVector field size) + 2
            // (subsample_count field size)
            // 6 = 2 (BytesOfClearData field size) + 4
            // (BytesOfEncryptedData field size)
            const entry = /** @type {!ISOEntry} */ (sepiff.entry[i]);
            saiz.sample_info_size[i] = 10 + (6 * entry.NumberOfEntries);
          }
        } else {
          // No sub-sample encryption => set default
          // sample_info_size = InitializationVector field size (8)
          saiz.default_sample_info_size = 8;
        }
      }
    }

    // set tfhd.base-data-offset-present to false
    tfhd.flags &= 0xFFFFFE;
    // set tfhd.default-base-is-moof to true
    tfhd.flags |= 0x020000;
    // set trun.data-offset-present to true
    trun.flags |= 0x000001;

    // Update trun.data_offset field that corresponds to first data byte
    // (inside mdat box)
    const moof = isoFile.fetch('moof');
    const length = moof.getLength();
    trun.data_offset = length + 8;

    // Update saio box offset field according to new senc box offset
    const saio = isoFile.fetch('saio');
    if (saio !== null) {
      const trafPosInMoof = this.getBoxOffset_(moof, 'traf');
      const sencPosInTraf = this.getBoxOffset_(traf, 'senc');
      // Set offset from begin fragment to the first IV field in senc box
      // 16 = box header (12) + sample_count field size (4)
      saio.offset[0] = trafPosInMoof + sencPosInTraf + 16;
    }

    return shaka.util.BufferUtils.toUint8(isoFile.write());
  }
Process a media segment from a data and stream.
@param {BufferSource} data
@param {shaka.extern.Stream} stream
@param {shaka.media.SegmentReference} reference
@return {!Uint8Array}
@private