parseMdat_(reader, time, timescale, defaultSampleDuration,
      defaultSampleSize, offset, parsedTRUNs, captionPackets) {
    const BitstreamFormat = shaka.cea.Mp4CeaParser.BitstreamFormat;
    const CeaUtils = shaka.cea.CeaUtils;
    let sampleIndex = 0;

    // The fields in each ParsedTRUNSample contained in the sampleData
    // array are nullable. In the case of sample data and sample duration,
    // we use the defaults provided by the TREX/TFHD boxes. For sample
    // composition time offset, we default to 0.
    let sampleSize = defaultSampleSize;

    // Combine all sample data.  This assumes that the samples described across
    // multiple trun boxes are still continuous in the mdat box.
    const sampleDatas = parsedTRUNs.map((t) => t.sampleData);
    const sampleData = [].concat(...sampleDatas);

    if (sampleData.length) {
      sampleSize = sampleData[0].sampleSize || defaultSampleSize;
    }

    reader.skip(offset + parsedTRUNs[0].dataOffset);

    while (reader.hasMoreData()) {
      const naluSize = reader.readUint32();
      const naluHeader = reader.readUint8();
      let naluType = null;
      let isSeiMessage = false;
      let naluHeaderSize = 1;

      goog.asserts.assert(this.bitstreamFormat_ != BitstreamFormat.UNKNOWN,
          'Bitstream format should have been checked before now!');
      switch (this.bitstreamFormat_) {
        case BitstreamFormat.H264:
          naluType = naluHeader & 0x1f;
          isSeiMessage = naluType == CeaUtils.H264_NALU_TYPE_SEI;
          break;

        case BitstreamFormat.H265:
          naluHeaderSize = 2;
          reader.skip(1);
          naluType = (naluHeader >> 1) & 0x3f;
          isSeiMessage =
              naluType == CeaUtils.H265_PREFIX_NALU_TYPE_SEI ||
              naluType == CeaUtils.H265_SUFFIX_NALU_TYPE_SEI;
          break;

        case BitstreamFormat.H266:
          naluHeaderSize = 2;
          reader.skip(1);
          naluType = (naluHeader >> 1) & 0x3f;
          isSeiMessage =
              naluType == CeaUtils.H266_PREFIX_NALU_TYPE_SEI ||
              naluType == CeaUtils.H266_SUFFIX_NALU_TYPE_SEI;
          break;

        default:
          return;
      }

      if (isSeiMessage) {
        let timeOffset = 0;

        if (sampleIndex < sampleData.length) {
          timeOffset = sampleData[sampleIndex].sampleCompositionTimeOffset || 0;
        }

        const pts = (time + timeOffset) / timescale;
        for (const packet of this.seiProcessor_
            .process(reader.readBytes(naluSize - naluHeaderSize))) {
          captionPackets.push({
            packet,
            pts,
          });
        }
      } else {
        try {
          reader.skip(naluSize - naluHeaderSize);
        } catch (e) {
          // It is necessary to ignore this error because it can break the start
          // of playback even if the user does not want to see the subtitles.
          break;
        }
      }
      sampleSize -= (naluSize + 4);
      if (sampleSize == 0) {
        if (sampleIndex < sampleData.length) {
          time += sampleData[sampleIndex].sampleDuration ||
              defaultSampleDuration;
        } else {
          time += defaultSampleDuration;
        }

        sampleIndex++;

        if (sampleIndex < sampleData.length) {
          sampleSize = sampleData[sampleIndex].sampleSize || defaultSampleSize;
        } else {
          sampleSize = defaultSampleSize;
        }
      }
    }
  }
Parse MDAT box.
@param {!shaka.util.DataViewReader} reader
@param {number} time
@param {number} timescale
@param {number} defaultSampleDuration
@param {number} defaultSampleSize
@param {number} offset
@param {!Array<shaka.util.ParsedTRUNBox>} parsedTRUNs
@param {!Array<!shaka.extern.ICeaParser.CaptionPacket>} captionPackets
@private