Java Code Examples for com.google.android.exoplayer2.extractor.TrackOutput#sampleData()

The following examples show how to use com.google.android.exoplayer2.extractor.TrackOutput#sampleData() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: DvbSubtitleReader.java    From MediaSDK with Apache License 2.0 6 votes vote down vote up
@Override
public void consume(ParsableByteArray data) {
  if (writingSample) {
    if (bytesToCheck == 2 && !checkNextByte(data, 0x20)) {
      // Failed to check data_identifier
      return;
    }
    if (bytesToCheck == 1 && !checkNextByte(data, 0x00)) {
      // Check and discard the subtitle_stream_id
      return;
    }
    int dataPosition = data.getPosition();
    int bytesAvailable = data.bytesLeft();
    for (TrackOutput output : outputs) {
      data.setPosition(dataPosition);
      output.sampleData(data, bytesAvailable);
    }
    sampleBytesWritten += bytesAvailable;
  }
}
 
Example 2
Source File: DvbSubtitleReader.java    From Telegram with GNU General Public License v2.0 6 votes vote down vote up
@Override
public void consume(ParsableByteArray data) {
  if (writingSample) {
    if (bytesToCheck == 2 && !checkNextByte(data, 0x20)) {
      // Failed to check data_identifier
      return;
    }
    if (bytesToCheck == 1 && !checkNextByte(data, 0x00)) {
      // Check and discard the subtitle_stream_id
      return;
    }
    int dataPosition = data.getPosition();
    int bytesAvailable = data.bytesLeft();
    for (TrackOutput output : outputs) {
      data.setPosition(dataPosition);
      output.sampleData(data, bytesAvailable);
    }
    sampleBytesWritten += bytesAvailable;
  }
}
 
Example 3
Source File: DvbSubtitleReader.java    From TelePlus-Android with GNU General Public License v2.0 6 votes vote down vote up
@Override
public void consume(ParsableByteArray data) {
  if (writingSample) {
    if (bytesToCheck == 2 && !checkNextByte(data, 0x20)) {
      // Failed to check data_identifier
      return;
    }
    if (bytesToCheck == 1 && !checkNextByte(data, 0x00)) {
      // Check and discard the subtitle_stream_id
      return;
    }
    int dataPosition = data.getPosition();
    int bytesAvailable = data.bytesLeft();
    for (TrackOutput output : outputs) {
      data.setPosition(dataPosition);
      output.sampleData(data, bytesAvailable);
    }
    sampleBytesWritten += bytesAvailable;
  }
}
 
Example 4
Source File: DvbSubtitleReader.java    From Telegram-FOSS with GNU General Public License v2.0 6 votes vote down vote up
@Override
public void consume(ParsableByteArray data) {
  if (writingSample) {
    if (bytesToCheck == 2 && !checkNextByte(data, 0x20)) {
      // Failed to check data_identifier
      return;
    }
    if (bytesToCheck == 1 && !checkNextByte(data, 0x00)) {
      // Check and discard the subtitle_stream_id
      return;
    }
    int dataPosition = data.getPosition();
    int bytesAvailable = data.bytesLeft();
    for (TrackOutput output : outputs) {
      data.setPosition(dataPosition);
      output.sampleData(data, bytesAvailable);
    }
    sampleBytesWritten += bytesAvailable;
  }
}
 
Example 5
Source File: MatroskaExtractor.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
/**
 * Outputs up to {@code length} bytes of sample data to {@code output}, consisting of either
 * {@link #sampleStrippedBytes} or data read from {@code input}.
 */
private int writeToOutput(ExtractorInput input, TrackOutput output, int length)
    throws IOException, InterruptedException {
  int bytesWritten;
  int strippedBytesLeft = sampleStrippedBytes.bytesLeft();
  if (strippedBytesLeft > 0) {
    bytesWritten = Math.min(length, strippedBytesLeft);
    output.sampleData(sampleStrippedBytes, bytesWritten);
  } else {
    bytesWritten = output.sampleData(input, length, false);
  }
  return bytesWritten;
}
 
Example 6
Source File: CeaUtil.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Consumes caption data (cc_data), writing the content as samples to all of the provided outputs.
 *
 * @param presentationTimeUs The presentation time in microseconds for any samples.
 * @param ccDataBuffer The buffer containing the caption data.
 * @param outputs The outputs to which any samples should be written.
 */
public static void consumeCcData(
    long presentationTimeUs, ParsableByteArray ccDataBuffer, TrackOutput[] outputs) {
  // First byte contains: reserved (1), process_cc_data_flag (1), zero_bit (1), cc_count (5).
  int firstByte = ccDataBuffer.readUnsignedByte();
  boolean processCcDataFlag = (firstByte & 0x40) != 0;
  if (!processCcDataFlag) {
    // No need to process.
    return;
  }
  int ccCount = firstByte & 0x1F;
  ccDataBuffer.skipBytes(1); // Ignore em_data
  // Each data packet consists of 24 bits: marker bits (5) + cc_valid (1) + cc_type (2)
  // + cc_data_1 (8) + cc_data_2 (8).
  int sampleLength = ccCount * 3;
  int sampleStartPosition = ccDataBuffer.getPosition();
  for (TrackOutput output : outputs) {
    ccDataBuffer.setPosition(sampleStartPosition);
    output.sampleData(ccDataBuffer, sampleLength);
    output.sampleMetadata(
        presentationTimeUs,
        C.BUFFER_FLAG_KEY_FRAME,
        sampleLength,
        /* offset= */ 0,
        /* encryptionData= */ null);
  }
}
 
Example 7
Source File: SingleSampleMediaChunk.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
@SuppressWarnings("NonAtomicVolatileUpdate")
@Override
public void load() throws IOException, InterruptedException {
  DataSpec loadDataSpec = dataSpec.subrange(nextLoadPosition);
  try {
    // Create and open the input.
    long length = dataSource.open(loadDataSpec);
    if (length != C.LENGTH_UNSET) {
      length += nextLoadPosition;
    }
    ExtractorInput extractorInput =
        new DefaultExtractorInput(dataSource, nextLoadPosition, length);
    BaseMediaChunkOutput output = getOutput();
    output.setSampleOffsetUs(0);
    TrackOutput trackOutput = output.track(0, trackType);
    trackOutput.format(sampleFormat);
    // Load the sample data.
    int result = 0;
    while (result != C.RESULT_END_OF_INPUT) {
      nextLoadPosition += result;
      result = trackOutput.sampleData(extractorInput, Integer.MAX_VALUE, true);
    }
    int sampleSize = (int) nextLoadPosition;
    trackOutput.sampleMetadata(startTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
  } finally {
    Util.closeQuietly(dataSource);
  }
  loadCompleted = true;
}
 
Example 8
Source File: FragmentedMp4Extractor.java    From K-Sonic with MIT License 5 votes vote down vote up
/**
 * Appends the corresponding encryption data to the {@link TrackOutput} contained in the given
 * {@link TrackBundle}.
 *
 * @param trackBundle The {@link TrackBundle} that contains the {@link Track} for which the
 *     Sample encryption data must be output.
 * @return The number of written bytes.
 */
private int appendSampleEncryptionData(TrackBundle trackBundle) {
  TrackFragment trackFragment = trackBundle.fragment;
  ParsableByteArray sampleEncryptionData = trackFragment.sampleEncryptionData;
  int sampleDescriptionIndex = trackFragment.header.sampleDescriptionIndex;
  TrackEncryptionBox encryptionBox = trackFragment.trackEncryptionBox != null
      ? trackFragment.trackEncryptionBox
      : trackBundle.track.sampleDescriptionEncryptionBoxes[sampleDescriptionIndex];
  int vectorSize = encryptionBox.initializationVectorSize;
  boolean subsampleEncryption = trackFragment
      .sampleHasSubsampleEncryptionTable[trackBundle.currentSampleIndex];

  // Write the signal byte, containing the vector size and the subsample encryption flag.
  encryptionSignalByte.data[0] = (byte) (vectorSize | (subsampleEncryption ? 0x80 : 0));
  encryptionSignalByte.setPosition(0);
  TrackOutput output = trackBundle.output;
  output.sampleData(encryptionSignalByte, 1);
  // Write the vector.
  output.sampleData(sampleEncryptionData, vectorSize);
  // If we don't have subsample encryption data, we're done.
  if (!subsampleEncryption) {
    return 1 + vectorSize;
  }
  // Write the subsample encryption data.
  int subsampleCount = sampleEncryptionData.readUnsignedShort();
  sampleEncryptionData.skipBytes(-2);
  int subsampleDataLength = 2 + 6 * subsampleCount;
  output.sampleData(sampleEncryptionData, subsampleDataLength);
  return 1 + vectorSize + subsampleDataLength;
}
 
Example 9
Source File: SingleSampleMediaChunk.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
@SuppressWarnings("NonAtomicVolatileUpdate")
@Override
public void load() throws IOException, InterruptedException {
  DataSpec loadDataSpec = dataSpec.subrange(nextLoadPosition);
  try {
    // Create and open the input.
    long length = dataSource.open(loadDataSpec);
    if (length != C.LENGTH_UNSET) {
      length += nextLoadPosition;
    }
    ExtractorInput extractorInput =
        new DefaultExtractorInput(dataSource, nextLoadPosition, length);
    BaseMediaChunkOutput output = getOutput();
    output.setSampleOffsetUs(0);
    TrackOutput trackOutput = output.track(0, trackType);
    trackOutput.format(sampleFormat);
    // Load the sample data.
    int result = 0;
    while (result != C.RESULT_END_OF_INPUT) {
      nextLoadPosition += result;
      result = trackOutput.sampleData(extractorInput, Integer.MAX_VALUE, true);
    }
    int sampleSize = (int) nextLoadPosition;
    trackOutput.sampleMetadata(startTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
  } finally {
    Util.closeQuietly(dataSource);
  }
  loadCompleted = true;
}
 
Example 10
Source File: FlacExtractor.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
private static void outputSample(
    ParsableByteArray sampleData, int size, long timeUs, TrackOutput output) {
  sampleData.setPosition(0);
  output.sampleData(sampleData, size);
  output.sampleMetadata(
      timeUs, C.BUFFER_FLAG_KEY_FRAME, size, /* offset= */ 0, /* encryptionData= */ null);
}
 
Example 11
Source File: MatroskaExtractor.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Outputs up to {@code length} bytes of sample data to {@code output}, consisting of either
 * {@link #sampleStrippedBytes} or data read from {@code input}.
 */
private int readToOutput(ExtractorInput input, TrackOutput output, int length)
    throws IOException, InterruptedException {
  int bytesRead;
  int strippedBytesLeft = sampleStrippedBytes.bytesLeft();
  if (strippedBytesLeft > 0) {
    bytesRead = Math.min(length, strippedBytesLeft);
    output.sampleData(sampleStrippedBytes, bytesRead);
  } else {
    bytesRead = output.sampleData(input, length, false);
  }
  sampleBytesRead += bytesRead;
  sampleBytesWritten += bytesRead;
  return bytesRead;
}
 
Example 12
Source File: CeaUtil.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Consumes caption data (cc_data), writing the content as samples to all of the provided outputs.
 *
 * @param presentationTimeUs The presentation time in microseconds for any samples.
 * @param ccDataBuffer The buffer containing the caption data.
 * @param outputs The outputs to which any samples should be written.
 */
public static void consumeCcData(
    long presentationTimeUs, ParsableByteArray ccDataBuffer, TrackOutput[] outputs) {
  // First byte contains: reserved (1), process_cc_data_flag (1), zero_bit (1), cc_count (5).
  int firstByte = ccDataBuffer.readUnsignedByte();
  boolean processCcDataFlag = (firstByte & 0x40) != 0;
  if (!processCcDataFlag) {
    // No need to process.
    return;
  }
  int ccCount = firstByte & 0x1F;
  ccDataBuffer.skipBytes(1); // Ignore em_data
  // Each data packet consists of 24 bits: marker bits (5) + cc_valid (1) + cc_type (2)
  // + cc_data_1 (8) + cc_data_2 (8).
  int sampleLength = ccCount * 3;
  int sampleStartPosition = ccDataBuffer.getPosition();
  for (TrackOutput output : outputs) {
    ccDataBuffer.setPosition(sampleStartPosition);
    output.sampleData(ccDataBuffer, sampleLength);
    output.sampleMetadata(
        presentationTimeUs,
        C.BUFFER_FLAG_KEY_FRAME,
        sampleLength,
        /* offset= */ 0,
        /* encryptionData= */ null);
  }
}
 
Example 13
Source File: CeaUtil.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Consumes caption data (cc_data), writing the content as samples to all of the provided outputs.
 *
 * @param presentationTimeUs The presentation time in microseconds for any samples.
 * @param ccDataBuffer The buffer containing the caption data.
 * @param outputs The outputs to which any samples should be written.
 */
public static void consumeCcData(
    long presentationTimeUs, ParsableByteArray ccDataBuffer, TrackOutput[] outputs) {
  // First byte contains: reserved (1), process_cc_data_flag (1), zero_bit (1), cc_count (5).
  int firstByte = ccDataBuffer.readUnsignedByte();
  boolean processCcDataFlag = (firstByte & 0x40) != 0;
  if (!processCcDataFlag) {
    // No need to process.
    return;
  }
  int ccCount = firstByte & 0x1F;
  ccDataBuffer.skipBytes(1); // Ignore em_data
  // Each data packet consists of 24 bits: marker bits (5) + cc_valid (1) + cc_type (2)
  // + cc_data_1 (8) + cc_data_2 (8).
  int sampleLength = ccCount * 3;
  int sampleStartPosition = ccDataBuffer.getPosition();
  for (TrackOutput output : outputs) {
    ccDataBuffer.setPosition(sampleStartPosition);
    output.sampleData(ccDataBuffer, sampleLength);
    output.sampleMetadata(
        presentationTimeUs,
        C.BUFFER_FLAG_KEY_FRAME,
        sampleLength,
        /* offset= */ 0,
        /* encryptionData= */ null);
  }
}
 
Example 14
Source File: FlacExtractor.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
private static void outputSample(
    ParsableByteArray sampleData, int size, long timeUs, TrackOutput output) {
  sampleData.setPosition(0);
  output.sampleData(sampleData, size);
  output.sampleMetadata(
      timeUs, C.BUFFER_FLAG_KEY_FRAME, size, /* offset= */ 0, /* encryptionData= */ null);
}
 
Example 15
Source File: ProgressiveMediaPeriod.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
@Override
public void onIcyMetadata(ParsableByteArray metadata) {
  // Always output the first ICY metadata at the start time. This helps minimize any delay
  // between the start of playback and the first ICY metadata event.
  long timeUs =
      !seenIcyMetadata ? seekTimeUs : Math.max(getLargestQueuedTimestampUs(), seekTimeUs);
  int length = metadata.bytesLeft();
  TrackOutput icyTrackOutput = Assertions.checkNotNull(this.icyTrackOutput);
  icyTrackOutput.sampleData(metadata, length);
  icyTrackOutput.sampleMetadata(
      timeUs, C.BUFFER_FLAG_KEY_FRAME, length, /* offset= */ 0, /* encryptionData= */ null);
  seenIcyMetadata = true;
}
 
Example 16
Source File: ProgressiveMediaPeriod.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
@Override
public void onIcyMetadata(ParsableByteArray metadata) {
  // Always output the first ICY metadata at the start time. This helps minimize any delay
  // between the start of playback and the first ICY metadata event.
  long timeUs =
      !seenIcyMetadata ? seekTimeUs : Math.max(getLargestQueuedTimestampUs(), seekTimeUs);
  int length = metadata.bytesLeft();
  TrackOutput icyTrackOutput = Assertions.checkNotNull(this.icyTrackOutput);
  icyTrackOutput.sampleData(metadata, length);
  icyTrackOutput.sampleMetadata(
      timeUs, C.BUFFER_FLAG_KEY_FRAME, length, /* offset= */ 0, /* encryptionData= */ null);
  seenIcyMetadata = true;
}
 
Example 17
Source File: WebvttExtractor.java    From Telegram with GNU General Public License v2.0 4 votes vote down vote up
private void processSample() throws ParserException {
  ParsableByteArray webvttData = new ParsableByteArray(sampleData);

  // Validate the first line of the header.
  WebvttParserUtil.validateWebvttHeaderLine(webvttData);

  // Defaults to use if the header doesn't contain an X-TIMESTAMP-MAP header.
  long vttTimestampUs = 0;
  long tsTimestampUs = 0;

  // Parse the remainder of the header looking for X-TIMESTAMP-MAP.
  String line;
  while (!TextUtils.isEmpty(line = webvttData.readLine())) {
    if (line.startsWith("X-TIMESTAMP-MAP")) {
      Matcher localTimestampMatcher = LOCAL_TIMESTAMP.matcher(line);
      if (!localTimestampMatcher.find()) {
        throw new ParserException("X-TIMESTAMP-MAP doesn't contain local timestamp: " + line);
      }
      Matcher mediaTimestampMatcher = MEDIA_TIMESTAMP.matcher(line);
      if (!mediaTimestampMatcher.find()) {
        throw new ParserException("X-TIMESTAMP-MAP doesn't contain media timestamp: " + line);
      }
      vttTimestampUs = WebvttParserUtil.parseTimestampUs(localTimestampMatcher.group(1));
      tsTimestampUs = TimestampAdjuster.ptsToUs(Long.parseLong(mediaTimestampMatcher.group(1)));
    }
  }

  // Find the first cue header and parse the start time.
  Matcher cueHeaderMatcher = WebvttParserUtil.findNextCueHeader(webvttData);
  if (cueHeaderMatcher == null) {
    // No cues found. Don't output a sample, but still output a corresponding track.
    buildTrackOutput(0);
    return;
  }

  long firstCueTimeUs = WebvttParserUtil.parseTimestampUs(cueHeaderMatcher.group(1));
  long sampleTimeUs = timestampAdjuster.adjustTsTimestamp(
      TimestampAdjuster.usToPts(firstCueTimeUs + tsTimestampUs - vttTimestampUs));
  long subsampleOffsetUs = sampleTimeUs - firstCueTimeUs;
  // Output the track.
  TrackOutput trackOutput = buildTrackOutput(subsampleOffsetUs);
  // Output the sample.
  sampleDataWrapper.reset(sampleData, sampleSize);
  trackOutput.sampleData(sampleDataWrapper, sampleSize);
  trackOutput.sampleMetadata(sampleTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
}
 
Example 18
Source File: WebvttExtractor.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
private void processSample() throws ParserException {
  ParsableByteArray webvttData = new ParsableByteArray(sampleData);

  // Validate the first line of the header.
  try {
    WebvttParserUtil.validateWebvttHeaderLine(webvttData);
  } catch (SubtitleDecoderException e) {
    throw new ParserException(e);
  }

  // Defaults to use if the header doesn't contain an X-TIMESTAMP-MAP header.
  long vttTimestampUs = 0;
  long tsTimestampUs = 0;

  // Parse the remainder of the header looking for X-TIMESTAMP-MAP.
  String line;
  while (!TextUtils.isEmpty(line = webvttData.readLine())) {
    if (line.startsWith("X-TIMESTAMP-MAP")) {
      Matcher localTimestampMatcher = LOCAL_TIMESTAMP.matcher(line);
      if (!localTimestampMatcher.find()) {
        throw new ParserException("X-TIMESTAMP-MAP doesn't contain local timestamp: " + line);
      }
      Matcher mediaTimestampMatcher = MEDIA_TIMESTAMP.matcher(line);
      if (!mediaTimestampMatcher.find()) {
        throw new ParserException("X-TIMESTAMP-MAP doesn't contain media timestamp: " + line);
      }
      vttTimestampUs = WebvttParserUtil.parseTimestampUs(localTimestampMatcher.group(1));
      tsTimestampUs = TimestampAdjuster.ptsToUs(Long.parseLong(mediaTimestampMatcher.group(1)));
    }
  }

  // Find the first cue header and parse the start time.
  Matcher cueHeaderMatcher = WebvttParserUtil.findNextCueHeader(webvttData);
  if (cueHeaderMatcher == null) {
    // No cues found. Don't output a sample, but still output a corresponding track.
    buildTrackOutput(0);
    return;
  }

  long firstCueTimeUs = WebvttParserUtil.parseTimestampUs(cueHeaderMatcher.group(1));
  long sampleTimeUs = timestampAdjuster.adjustTsTimestamp(
      TimestampAdjuster.usToPts(firstCueTimeUs + tsTimestampUs - vttTimestampUs));
  long subsampleOffsetUs = sampleTimeUs - firstCueTimeUs;
  // Output the track.
  TrackOutput trackOutput = buildTrackOutput(subsampleOffsetUs);
  // Output the sample.
  sampleDataWrapper.reset(sampleData, sampleSize);
  trackOutput.sampleData(sampleDataWrapper, sampleSize);
  trackOutput.sampleMetadata(sampleTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
}
 
Example 19
Source File: WebvttExtractor.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
private void processSample() throws ParserException {
  ParsableByteArray webvttData = new ParsableByteArray(sampleData);

  // Validate the first line of the header.
  WebvttParserUtil.validateWebvttHeaderLine(webvttData);

  // Defaults to use if the header doesn't contain an X-TIMESTAMP-MAP header.
  long vttTimestampUs = 0;
  long tsTimestampUs = 0;

  // Parse the remainder of the header looking for X-TIMESTAMP-MAP.
  String line;
  while (!TextUtils.isEmpty(line = webvttData.readLine())) {
    if (line.startsWith("X-TIMESTAMP-MAP")) {
      Matcher localTimestampMatcher = LOCAL_TIMESTAMP.matcher(line);
      if (!localTimestampMatcher.find()) {
        throw new ParserException("X-TIMESTAMP-MAP doesn't contain local timestamp: " + line);
      }
      Matcher mediaTimestampMatcher = MEDIA_TIMESTAMP.matcher(line);
      if (!mediaTimestampMatcher.find()) {
        throw new ParserException("X-TIMESTAMP-MAP doesn't contain media timestamp: " + line);
      }
      vttTimestampUs = WebvttParserUtil.parseTimestampUs(localTimestampMatcher.group(1));
      tsTimestampUs = TimestampAdjuster.ptsToUs(Long.parseLong(mediaTimestampMatcher.group(1)));
    }
  }

  // Find the first cue header and parse the start time.
  Matcher cueHeaderMatcher = WebvttParserUtil.findNextCueHeader(webvttData);
  if (cueHeaderMatcher == null) {
    // No cues found. Don't output a sample, but still output a corresponding track.
    buildTrackOutput(0);
    return;
  }

  long firstCueTimeUs = WebvttParserUtil.parseTimestampUs(cueHeaderMatcher.group(1));
  long sampleTimeUs = timestampAdjuster.adjustTsTimestamp(
      TimestampAdjuster.usToPts(firstCueTimeUs + tsTimestampUs - vttTimestampUs));
  long subsampleOffsetUs = sampleTimeUs - firstCueTimeUs;
  // Output the track.
  TrackOutput trackOutput = buildTrackOutput(subsampleOffsetUs);
  // Output the sample.
  sampleDataWrapper.reset(sampleData, sampleSize);
  trackOutput.sampleData(sampleDataWrapper, sampleSize);
  trackOutput.sampleMetadata(sampleTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
}
 
Example 20
Source File: WebvttExtractor.java    From K-Sonic with MIT License 4 votes vote down vote up
private void processSample() throws ParserException {
  ParsableByteArray webvttData = new ParsableByteArray(sampleData);

  // Validate the first line of the header.
  try {
    WebvttParserUtil.validateWebvttHeaderLine(webvttData);
  } catch (SubtitleDecoderException e) {
    throw new ParserException(e);
  }

  // Defaults to use if the header doesn't contain an X-TIMESTAMP-MAP header.
  long vttTimestampUs = 0;
  long tsTimestampUs = 0;

  // Parse the remainder of the header looking for X-TIMESTAMP-MAP.
  String line;
  while (!TextUtils.isEmpty(line = webvttData.readLine())) {
    if (line.startsWith("X-TIMESTAMP-MAP")) {
      Matcher localTimestampMatcher = LOCAL_TIMESTAMP.matcher(line);
      if (!localTimestampMatcher.find()) {
        throw new ParserException("X-TIMESTAMP-MAP doesn't contain local timestamp: " + line);
      }
      Matcher mediaTimestampMatcher = MEDIA_TIMESTAMP.matcher(line);
      if (!mediaTimestampMatcher.find()) {
        throw new ParserException("X-TIMESTAMP-MAP doesn't contain media timestamp: " + line);
      }
      vttTimestampUs = WebvttParserUtil.parseTimestampUs(localTimestampMatcher.group(1));
      tsTimestampUs = TimestampAdjuster.ptsToUs(
          Long.parseLong(mediaTimestampMatcher.group(1)));
    }
  }

  // Find the first cue header and parse the start time.
  Matcher cueHeaderMatcher = WebvttParserUtil.findNextCueHeader(webvttData);
  if (cueHeaderMatcher == null) {
    // No cues found. Don't output a sample, but still output a corresponding track.
    buildTrackOutput(0);
    return;
  }

  long firstCueTimeUs = WebvttParserUtil.parseTimestampUs(cueHeaderMatcher.group(1));
  long sampleTimeUs = timestampAdjuster.adjustSampleTimestamp(
      firstCueTimeUs + tsTimestampUs - vttTimestampUs);
  long subsampleOffsetUs = sampleTimeUs - firstCueTimeUs;
  // Output the track.
  TrackOutput trackOutput = buildTrackOutput(subsampleOffsetUs);
  // Output the sample.
  sampleDataWrapper.reset(sampleData, sampleSize);
  trackOutput.sampleData(sampleDataWrapper, sampleSize);
  trackOutput.sampleMetadata(sampleTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
}