Java Code Examples for com.google.android.exoplayer2.extractor.ExtractorInput#getPosition()

The following examples show how to use com.google.android.exoplayer2.extractor.ExtractorInput#getPosition() . 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: InitializationChunk.java    From K-Sonic with MIT License 6 votes vote down vote up
@SuppressWarnings("NonAtomicVolatileUpdate")
@Override
public void load() throws IOException, InterruptedException {
  DataSpec loadDataSpec = Util.getRemainderDataSpec(dataSpec, bytesLoaded);
  try {
    // Create and open the input.
    ExtractorInput input = new DefaultExtractorInput(dataSource,
        loadDataSpec.absoluteStreamPosition, dataSource.open(loadDataSpec));
    if (bytesLoaded == 0) {
      extractorWrapper.init(null);
    }
    // Load and decode the initialization data.
    try {
      Extractor extractor = extractorWrapper.extractor;
      int result = Extractor.RESULT_CONTINUE;
      while (result == Extractor.RESULT_CONTINUE && !loadCanceled) {
        result = extractor.read(input, null);
      }
      Assertions.checkState(result != Extractor.RESULT_SEEK);
    } finally {
      bytesLoaded = (int) (input.getPosition() - dataSpec.absoluteStreamPosition);
    }
  } finally {
    Util.closeQuietly(dataSource);
  }
}
 
Example 2
Source File: FragmentedMp4Extractor.java    From K-Sonic with MIT License 6 votes vote down vote up
private void readEncryptionData(ExtractorInput input) throws IOException, InterruptedException {
  TrackBundle nextTrackBundle = null;
  long nextDataOffset = Long.MAX_VALUE;
  int trackBundlesSize = trackBundles.size();
  for (int i = 0; i < trackBundlesSize; i++) {
    TrackFragment trackFragment = trackBundles.valueAt(i).fragment;
    if (trackFragment.sampleEncryptionDataNeedsFill
        && trackFragment.auxiliaryDataPosition < nextDataOffset) {
      nextDataOffset = trackFragment.auxiliaryDataPosition;
      nextTrackBundle = trackBundles.valueAt(i);
    }
  }
  if (nextTrackBundle == null) {
    parserState = STATE_READING_SAMPLE_START;
    return;
  }
  int bytesToSkip = (int) (nextDataOffset - input.getPosition());
  if (bytesToSkip < 0) {
    throw new ParserException("Offset to encryption data was negative.");
  }
  input.skipFully(bytesToSkip);
  nextTrackBundle.fragment.fillEncryptionData(input);
}
 
Example 3
Source File: PsDurationReader.java    From Telegram-FOSS with GNU General Public License v2.0 6 votes vote down vote up
private int readFirstScrValue(ExtractorInput input, PositionHolder seekPositionHolder)
    throws IOException, InterruptedException {
  int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, input.getLength());
  int searchStartPosition = 0;
  if (input.getPosition() != searchStartPosition) {
    seekPositionHolder.position = searchStartPosition;
    return Extractor.RESULT_SEEK;
  }

  packetBuffer.reset(bytesToSearch);
  input.resetPeekPosition();
  input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToSearch);

  firstScrValue = readFirstScrValueFromBuffer(packetBuffer);
  isFirstScrValueRead = true;
  return Extractor.RESULT_CONTINUE;
}
 
Example 4
Source File: TsDurationReader.java    From Telegram-FOSS with GNU General Public License v2.0 6 votes vote down vote up
private int readFirstPcrValue(ExtractorInput input, PositionHolder seekPositionHolder, int pcrPid)
    throws IOException, InterruptedException {
  int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, input.getLength());
  int searchStartPosition = 0;
  if (input.getPosition() != searchStartPosition) {
    seekPositionHolder.position = searchStartPosition;
    return Extractor.RESULT_SEEK;
  }

  packetBuffer.reset(bytesToSearch);
  input.resetPeekPosition();
  input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToSearch);

  firstPcrValue = readFirstPcrValueFromBuffer(packetBuffer, pcrPid);
  isFirstPcrValueRead = true;
  return Extractor.RESULT_CONTINUE;
}
 
Example 5
Source File: PsDurationReader.java    From TelePlus-Android with GNU General Public License v2.0 6 votes vote down vote up
private int readFirstScrValue(ExtractorInput input, PositionHolder seekPositionHolder)
    throws IOException, InterruptedException {
  if (input.getPosition() != 0) {
    seekPositionHolder.position = 0;
    return Extractor.RESULT_SEEK;
  }

  int bytesToRead = (int) Math.min(DURATION_READ_BYTES, input.getLength());
  input.resetPeekPosition();
  input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToRead);
  packetBuffer.setPosition(0);
  packetBuffer.setLimit(bytesToRead);

  firstScrValue = readFirstScrValueFromBuffer(packetBuffer);
  isFirstScrValueRead = true;
  return Extractor.RESULT_CONTINUE;
}
 
Example 6
Source File: AmrExtractor.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
@Override
public int read(ExtractorInput input, PositionHolder seekPosition)
    throws IOException, InterruptedException {
  if (input.getPosition() == 0) {
    if (!readAmrHeader(input)) {
      throw new ParserException("Could not find AMR header.");
    }
  }
  maybeOutputFormat();
  int sampleReadResult = readSample(input);
  maybeOutputSeekMap(input.getLength(), sampleReadResult);
  return sampleReadResult;
}
 
Example 7
Source File: DefaultOggSeeker.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Skips forward to the start of the page containing the {@code targetGranule}.
 *
 * @param input The {@link ExtractorInput} to read from.
 * @throws ParserException If populating the page header fails.
 * @throws IOException If reading from the input fails.
 * @throws InterruptedException If interrupted while reading from the input.
 */
private void skipToPageOfTargetGranule(ExtractorInput input)
    throws IOException, InterruptedException {
  pageHeader.populate(input, /* quiet= */ false);
  while (pageHeader.granulePosition <= targetGranule) {
    input.skipFully(pageHeader.headerSize + pageHeader.bodySize);
    start = input.getPosition();
    startGranule = pageHeader.granulePosition;
    pageHeader.populate(input, /* quiet= */ false);
  }
  input.resetPeekPosition();
}
 
Example 8
Source File: Mp3Extractor.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Peeks the next frame and returns a {@link ConstantBitrateSeeker} based on its bitrate.
 */
private Seeker getConstantBitrateSeeker(ExtractorInput input)
    throws IOException, InterruptedException {
  input.peekFully(scratch.data, 0, 4);
  scratch.setPosition(0);
  MpegAudioHeader.populateHeader(scratch.readInt(), synchronizedHeader);
  return new ConstantBitrateSeeker(input.getLength(), input.getPosition(), synchronizedHeader);
}
 
Example 9
Source File: DefaultOggSeeker.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Skips to the last Ogg page in the stream and reads the header's granule field which is the
 * total number of samples per channel.
 *
 * @param input The {@link ExtractorInput} to read from.
 * @return the total number of samples of this input.
 * @throws IOException thrown if reading from the input fails.
 * @throws InterruptedException thrown if interrupted while reading from the input.
 */
//@VisibleForTesting
long readGranuleOfLastPage(ExtractorInput input)
    throws IOException, InterruptedException {
  skipToNextPage(input);
  pageHeader.reset();
  while ((pageHeader.type & 0x04) != 0x04 && input.getPosition() < endPosition) {
    pageHeader.populate(input, false);
    input.skipFully(pageHeader.headerSize + pageHeader.bodySize);
  }
  return pageHeader.granulePosition;
}
 
Example 10
Source File: AmrExtractor.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
private int readSample(ExtractorInput extractorInput) throws IOException, InterruptedException {
  if (currentSampleBytesRemaining == 0) {
    try {
      currentSampleSize = peekNextSampleSize(extractorInput);
    } catch (EOFException e) {
      return RESULT_END_OF_INPUT;
    }
    currentSampleBytesRemaining = currentSampleSize;
    if (firstSampleSize == C.LENGTH_UNSET) {
      firstSamplePosition = extractorInput.getPosition();
      firstSampleSize = currentSampleSize;
    }
    if (firstSampleSize == currentSampleSize) {
      numSamplesWithSameSize++;
    }
  }

  int bytesAppended =
      trackOutput.sampleData(
          extractorInput, currentSampleBytesRemaining, /* allowEndOfInput= */ true);
  if (bytesAppended == C.RESULT_END_OF_INPUT) {
    return RESULT_END_OF_INPUT;
  }
  currentSampleBytesRemaining -= bytesAppended;
  if (currentSampleBytesRemaining > 0) {
    return RESULT_CONTINUE;
  }

  trackOutput.sampleMetadata(
      timeOffsetUs + currentSampleTimeUs,
      C.BUFFER_FLAG_KEY_FRAME,
      currentSampleSize,
      /* offset= */ 0,
      /* encryptionData= */ null);
  currentSampleTimeUs += SAMPLE_TIME_PER_FRAME_US;
  return RESULT_CONTINUE;
}
 
Example 11
Source File: DefaultOggSeeker.java    From K-Sonic with MIT License 5 votes vote down vote up
/**
 * Skips to the last Ogg page in the stream and reads the header's granule field which is the
 * total number of samples per channel.
 *
 * @param input The {@link ExtractorInput} to read from.
 * @return the total number of samples of this input.
 * @throws IOException thrown if reading from the input fails.
 * @throws InterruptedException thrown if interrupted while reading from the input.
 */
//@VisibleForTesting
long readGranuleOfLastPage(ExtractorInput input)
    throws IOException, InterruptedException {
  skipToNextPage(input);
  pageHeader.reset();
  while ((pageHeader.type & 0x04) != 0x04 && input.getPosition() < endPosition) {
    pageHeader.populate(input, false);
    input.skipFully(pageHeader.headerSize + pageHeader.bodySize);
  }
  return pageHeader.granulePosition;
}
 
Example 12
Source File: StreamReader.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
private int readHeaders(ExtractorInput input) throws IOException, InterruptedException {
  boolean readingHeaders = true;
  while (readingHeaders) {
    if (!oggPacket.populate(input)) {
      state = STATE_END_OF_INPUT;
      return Extractor.RESULT_END_OF_INPUT;
    }
    lengthOfReadPacket = input.getPosition() - payloadStartPosition;

    readingHeaders = readHeaders(oggPacket.getPayload(), payloadStartPosition, setupData);
    if (readingHeaders) {
      payloadStartPosition = input.getPosition();
    }
  }

  sampleRate = setupData.format.sampleRate;
  if (!formatSet) {
    trackOutput.format(setupData.format);
    formatSet = true;
  }

  if (setupData.oggSeeker != null) {
    oggSeeker = setupData.oggSeeker;
  } else if (input.getLength() == C.LENGTH_UNSET) {
    oggSeeker = new UnseekableOggSeeker();
  } else {
    OggPageHeader firstPayloadPageHeader = oggPacket.getPageHeader();
    oggSeeker = new DefaultOggSeeker(payloadStartPosition, input.getLength(), this,
        firstPayloadPageHeader.headerSize + firstPayloadPageHeader.bodySize,
        firstPayloadPageHeader.granulePosition);
  }

  setupData = null;
  state = STATE_READ_PAYLOAD;
  // First payload packet. Trim the payload array of the ogg packet after headers have been read.
  oggPacket.trimPayload();
  return Extractor.RESULT_CONTINUE;
}
 
Example 13
Source File: TsBinarySearchSeeker.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
@Override
public TimestampSearchResult searchForTimestamp(
    ExtractorInput input, long targetTimestamp, OutputFrameHolder outputFrameHolder)
    throws IOException, InterruptedException {
  long inputPosition = input.getPosition();
  int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, input.getLength() - inputPosition);

  packetBuffer.reset(bytesToSearch);
  input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToSearch);

  return searchForPcrValueInBuffer(packetBuffer, targetTimestamp, inputPosition);
}
 
Example 14
Source File: TsBinarySearchSeeker.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
@Override
public TimestampSearchResult searchForTimestamp(
    ExtractorInput input, long targetTimestamp, OutputFrameHolder outputFrameHolder)
    throws IOException, InterruptedException {
  long inputPosition = input.getPosition();
  int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, input.getLength() - inputPosition);

  packetBuffer.reset(bytesToSearch);
  input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToSearch);

  return searchForPcrValueInBuffer(packetBuffer, targetTimestamp, inputPosition);
}
 
Example 15
Source File: DefaultOggSeeker.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
/**
 * Performs a single step of a seeking binary search, returning the byte position from which data
 * should be provided for the next step, or {@link C#POSITION_UNSET} if the search has converged.
 * If the search has converged then {@link #skipToPageOfTargetGranule(ExtractorInput)} should be
 * called to skip to the target page.
 *
 * @param input The {@link ExtractorInput} to read from.
 * @return The byte position from which data should be provided for the next step, or {@link
 *     C#POSITION_UNSET} if the search has converged.
 * @throws IOException If reading from the input fails.
 * @throws InterruptedException If interrupted while reading from the input.
 */
private long getNextSeekPosition(ExtractorInput input) throws IOException, InterruptedException {
  if (start == end) {
    return C.POSITION_UNSET;
  }

  long currentPosition = input.getPosition();
  if (!skipToNextPage(input, end)) {
    if (start == currentPosition) {
      throw new IOException("No ogg page can be found.");
    }
    return start;
  }

  pageHeader.populate(input, /* quiet= */ false);
  input.resetPeekPosition();

  long granuleDistance = targetGranule - pageHeader.granulePosition;
  int pageSize = pageHeader.headerSize + pageHeader.bodySize;
  if (0 <= granuleDistance && granuleDistance < MATCH_RANGE) {
    return C.POSITION_UNSET;
  }

  if (granuleDistance < 0) {
    end = currentPosition;
    endGranule = pageHeader.granulePosition;
  } else {
    start = input.getPosition() + pageSize;
    startGranule = pageHeader.granulePosition;
  }

  if (end - start < MATCH_BYTE_RANGE) {
    end = start;
    return start;
  }

  long offset = pageSize * (granuleDistance <= 0 ? 2L : 1L);
  long nextPosition =
      input.getPosition()
          - offset
          + (granuleDistance * (end - start) / (endGranule - startGranule));
  return Util.constrainValue(nextPosition, start, end - 1);
}
 
Example 16
Source File: WavExtractor.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
@Override
public int read(ExtractorInput input, PositionHolder seekPosition)
    throws IOException, InterruptedException {
  if (wavHeader == null) {
    wavHeader = WavHeaderReader.peek(input);
    if (wavHeader == null) {
      // Should only happen if the media wasn't sniffed.
      throw new ParserException("Unsupported or unrecognized wav header.");
    }
    Format format = Format.createAudioSampleFormat(null, MimeTypes.AUDIO_RAW, null,
        wavHeader.getBitrate(), MAX_INPUT_SIZE, wavHeader.getNumChannels(),
        wavHeader.getSampleRateHz(), wavHeader.getEncoding(), null, null, 0, null);
    trackOutput.format(format);
    bytesPerFrame = wavHeader.getBytesPerFrame();
  }

  if (!wavHeader.hasDataBounds()) {
    WavHeaderReader.skipToData(input, wavHeader);
    extractorOutput.seekMap(wavHeader);
  } else if (input.getPosition() == 0) {
    input.skipFully(wavHeader.getDataStartPosition());
  }

  long dataEndPosition = wavHeader.getDataEndPosition();
  Assertions.checkState(dataEndPosition != C.POSITION_UNSET);

  long bytesLeft = dataEndPosition - input.getPosition();
  if (bytesLeft <= 0) {
    return Extractor.RESULT_END_OF_INPUT;
  }

  int maxBytesToRead = (int) Math.min(MAX_INPUT_SIZE - pendingBytes, bytesLeft);
  int bytesAppended = trackOutput.sampleData(input, maxBytesToRead, true);
  if (bytesAppended != RESULT_END_OF_INPUT) {
    pendingBytes += bytesAppended;
  }

  // Samples must consist of a whole number of frames.
  int pendingFrames = pendingBytes / bytesPerFrame;
  if (pendingFrames > 0) {
    long timeUs = wavHeader.getTimeUs(input.getPosition() - pendingBytes);
    int size = pendingFrames * bytesPerFrame;
    pendingBytes -= size;
    trackOutput.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, size, pendingBytes, null);
  }

  return bytesAppended == RESULT_END_OF_INPUT ? RESULT_END_OF_INPUT : RESULT_CONTINUE;
}
 
Example 17
Source File: FragmentedMp4Extractor.java    From K-Sonic with MIT License 4 votes vote down vote up
private boolean readAtomHeader(ExtractorInput input) throws IOException, InterruptedException {
  if (atomHeaderBytesRead == 0) {
    // Read the standard length atom header.
    if (!input.readFully(atomHeader.data, 0, Atom.HEADER_SIZE, true)) {
      return false;
    }
    atomHeaderBytesRead = Atom.HEADER_SIZE;
    atomHeader.setPosition(0);
    atomSize = atomHeader.readUnsignedInt();
    atomType = atomHeader.readInt();
  }

  if (atomSize == Atom.LONG_SIZE_PREFIX) {
    // Read the extended atom size.
    int headerBytesRemaining = Atom.LONG_HEADER_SIZE - Atom.HEADER_SIZE;
    input.readFully(atomHeader.data, Atom.HEADER_SIZE, headerBytesRemaining);
    atomHeaderBytesRead += headerBytesRemaining;
    atomSize = atomHeader.readUnsignedLongToLong();
  }

  if (atomSize < atomHeaderBytesRead) {
    throw new ParserException("Atom size less than header length (unsupported).");
  }

  long atomPosition = input.getPosition() - atomHeaderBytesRead;
  if (atomType == Atom.TYPE_moof) {
    // The data positions may be updated when parsing the tfhd/trun.
    int trackCount = trackBundles.size();
    for (int i = 0; i < trackCount; i++) {
      TrackFragment fragment = trackBundles.valueAt(i).fragment;
      fragment.atomPosition = atomPosition;
      fragment.auxiliaryDataPosition = atomPosition;
      fragment.dataPosition = atomPosition;
    }
  }

  if (atomType == Atom.TYPE_mdat) {
    currentTrackBundle = null;
    endOfMdatPosition = atomPosition + atomSize;
    if (!haveOutputSeekMap) {
      extractorOutput.seekMap(new SeekMap.Unseekable(durationUs));
      haveOutputSeekMap = true;
    }
    parserState = STATE_READING_ENCRYPTION_DATA;
    return true;
  }

  if (shouldParseContainerAtom(atomType)) {
    long endPosition = input.getPosition() + atomSize - Atom.HEADER_SIZE;
    containerAtoms.add(new ContainerAtom(atomType, endPosition));
    if (atomSize == atomHeaderBytesRead) {
      processAtomEnded(endPosition);
    } else {
      // Start reading the first child atom.
      enterReadingAtomHeaderState();
    }
  } else if (shouldParseLeafAtom(atomType)) {
    if (atomHeaderBytesRead != Atom.HEADER_SIZE) {
      throw new ParserException("Leaf atom defines extended atom size (unsupported).");
    }
    if (atomSize > Integer.MAX_VALUE) {
      throw new ParserException("Leaf atom with length > 2147483647 (unsupported).");
    }
    atomData = new ParsableByteArray((int) atomSize);
    System.arraycopy(atomHeader.data, 0, atomData.data, 0, Atom.HEADER_SIZE);
    parserState = STATE_READING_ATOM_PAYLOAD;
  } else {
    if (atomSize > Integer.MAX_VALUE) {
      throw new ParserException("Skipping atom with length > 2147483647 (unsupported).");
    }
    atomData = null;
    parserState = STATE_READING_ATOM_PAYLOAD;
  }

  return true;
}
 
Example 18
Source File: TsExtractor.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
@Override
public @ReadResult int read(ExtractorInput input, PositionHolder seekPosition)
    throws IOException, InterruptedException {
  if (tracksEnded) {
    boolean canReadDuration = input.getLength() != C.LENGTH_UNSET && mode != MODE_HLS;
    if (canReadDuration && !durationReader.isDurationReadFinished()) {
      return durationReader.readDuration(input, seekPosition, pcrPid);
    }
    maybeOutputSeekMap();

    if (pendingSeekToStart) {
      pendingSeekToStart = false;
      seek(/* position= */ 0, /* timeUs= */ 0);
      if (input.getPosition() != 0) {
        seekPosition.position = 0;
        return RESULT_SEEK;
      }
    }
  }

  if (!fillBufferWithAtLeastOnePacket(input)) {
    return RESULT_END_OF_INPUT;
  }

  int endOfPacket = findEndOfFirstTsPacketInBuffer();
  int limit = tsPacketBuffer.limit();
  if (endOfPacket > limit) {
    return RESULT_CONTINUE;
  }

  // Note: See ISO/IEC 13818-1, section 2.4.3.2 for details of the header format.
  int tsPacketHeader = tsPacketBuffer.readInt();
  if ((tsPacketHeader & 0x800000) != 0) { // transport_error_indicator
    // There are uncorrectable errors in this packet.
    tsPacketBuffer.setPosition(endOfPacket);
    return RESULT_CONTINUE;
  }
  boolean payloadUnitStartIndicator = (tsPacketHeader & 0x400000) != 0;
  // Ignoring transport_priority (tsPacketHeader & 0x200000)
  int pid = (tsPacketHeader & 0x1FFF00) >> 8;
  // Ignoring transport_scrambling_control (tsPacketHeader & 0xC0)
  boolean adaptationFieldExists = (tsPacketHeader & 0x20) != 0;
  boolean payloadExists = (tsPacketHeader & 0x10) != 0;

  TsPayloadReader payloadReader = payloadExists ? tsPayloadReaders.get(pid) : null;
  if (payloadReader == null) {
    tsPacketBuffer.setPosition(endOfPacket);
    return RESULT_CONTINUE;
  }

  // Discontinuity check.
  if (mode != MODE_HLS) {
    int continuityCounter = tsPacketHeader & 0xF;
    int previousCounter = continuityCounters.get(pid, continuityCounter - 1);
    continuityCounters.put(pid, continuityCounter);
    if (previousCounter == continuityCounter) {
      // Duplicate packet found.
      tsPacketBuffer.setPosition(endOfPacket);
      return RESULT_CONTINUE;
    } else if (continuityCounter != ((previousCounter + 1) & 0xF)) {
      // Discontinuity found.
      payloadReader.seek();
    }
  }

  // Skip the adaptation field.
  if (adaptationFieldExists) {
    int adaptationFieldLength = tsPacketBuffer.readUnsignedByte();
    tsPacketBuffer.skipBytes(adaptationFieldLength);
  }

  // Read the payload.
  boolean wereTracksEnded = tracksEnded;
  if (shouldConsumePacketPayload(pid)) {
    tsPacketBuffer.setLimit(endOfPacket);
    payloadReader.consume(tsPacketBuffer, payloadUnitStartIndicator);
    tsPacketBuffer.setLimit(limit);
  }
  if (mode != MODE_HLS && !wereTracksEnded && tracksEnded) {
    // We have read all tracks from all PMTs in this stream. Now seek to the beginning and read
    // again to make sure we output all media, including any contained in packets prior to those
    // containing the track information.
    pendingSeekToStart = true;
  }

  tsPacketBuffer.setPosition(endOfPacket);
  return RESULT_CONTINUE;
}
 
Example 19
Source File: Mp4Extractor.java    From K-Sonic with MIT License 4 votes vote down vote up
private boolean readAtomHeader(ExtractorInput input) throws IOException, InterruptedException {
  if (atomHeaderBytesRead == 0) {
    // Read the standard length atom header.
    if (!input.readFully(atomHeader.data, 0, Atom.HEADER_SIZE, true)) {
      return false;
    }
    atomHeaderBytesRead = Atom.HEADER_SIZE;
    atomHeader.setPosition(0);
    atomSize = atomHeader.readUnsignedInt();
    atomType = atomHeader.readInt();
  }

  if (atomSize == Atom.LONG_SIZE_PREFIX) {
    // Read the extended atom size.
    int headerBytesRemaining = Atom.LONG_HEADER_SIZE - Atom.HEADER_SIZE;
    input.readFully(atomHeader.data, Atom.HEADER_SIZE, headerBytesRemaining);
    atomHeaderBytesRead += headerBytesRemaining;
    atomSize = atomHeader.readUnsignedLongToLong();
  }

  if (shouldParseContainerAtom(atomType)) {
    long endPosition = input.getPosition() + atomSize - atomHeaderBytesRead;
    containerAtoms.add(new ContainerAtom(atomType, endPosition));
    if (atomSize == atomHeaderBytesRead) {
      processAtomEnded(endPosition);
    } else {
      // Start reading the first child atom.
      enterReadingAtomHeaderState();
    }
  } else if (shouldParseLeafAtom(atomType)) {
    // We don't support parsing of leaf atoms that define extended atom sizes, or that have
    // lengths greater than Integer.MAX_VALUE.
    Assertions.checkState(atomHeaderBytesRead == Atom.HEADER_SIZE);
    Assertions.checkState(atomSize <= Integer.MAX_VALUE);
    atomData = new ParsableByteArray((int) atomSize);
    System.arraycopy(atomHeader.data, 0, atomData.data, 0, Atom.HEADER_SIZE);
    parserState = STATE_READING_ATOM_PAYLOAD;
  } else {
    atomData = null;
    parserState = STATE_READING_ATOM_PAYLOAD;
  }

  return true;
}
 
Example 20
Source File: AdtsExtractor.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
private void calculateAverageFrameSize(ExtractorInput input)
    throws IOException, InterruptedException {
  if (hasCalculatedAverageFrameSize) {
    return;
  }
  averageFrameSize = C.LENGTH_UNSET;
  input.resetPeekPosition();
  if (input.getPosition() == 0) {
    // Skip any ID3 headers.
    peekId3Header(input);
  }

  int numValidFrames = 0;
  long totalValidFramesSize = 0;
  try {
    while (input.peekFully(
        scratch.data, /* offset= */ 0, /* length= */ 2, /* allowEndOfInput= */ true)) {
      scratch.setPosition(0);
      int syncBytes = scratch.readUnsignedShort();
      if (!AdtsReader.isAdtsSyncWord(syncBytes)) {
        // Invalid sync byte pattern.
        // Constant bit-rate seeking will probably fail for this stream.
        numValidFrames = 0;
        break;
      } else {
        // Read the frame size.
        if (!input.peekFully(
            scratch.data, /* offset= */ 0, /* length= */ 4, /* allowEndOfInput= */ true)) {
          break;
        }
        scratchBits.setPosition(14);
        int currentFrameSize = scratchBits.readBits(13);
        // Either the stream is malformed OR we're not parsing an ADTS stream.
        if (currentFrameSize <= 6) {
          hasCalculatedAverageFrameSize = true;
          throw new ParserException("Malformed ADTS stream");
        }
        totalValidFramesSize += currentFrameSize;
        if (++numValidFrames == NUM_FRAMES_FOR_AVERAGE_FRAME_SIZE) {
          break;
        }
        if (!input.advancePeekPosition(currentFrameSize - 6, /* allowEndOfInput= */ true)) {
          break;
        }
      }
    }
  } catch (EOFException e) {
    // We reached the end of the input during a peekFully() or advancePeekPosition() operation.
    // This is OK, it just means the input has an incomplete ADTS frame at the end. Ideally
    // ExtractorInput would allow these operations to encounter end-of-input without throwing an
    // exception [internal: b/145586657].
  }
  input.resetPeekPosition();
  if (numValidFrames > 0) {
    averageFrameSize = (int) (totalValidFramesSize / numValidFrames);
  } else {
    averageFrameSize = C.LENGTH_UNSET;
  }
  hasCalculatedAverageFrameSize = true;
}