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

The following examples show how to use com.google.android.exoplayer2.extractor.ExtractorInput#getLength() . 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: PsDurationReader.java    From MediaSDK with Apache License 2.0 6 votes vote down vote up
private int readLastScrValue(ExtractorInput input, PositionHolder seekPositionHolder)
    throws IOException, InterruptedException {
  long inputLength = input.getLength();
  int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, inputLength);
  long searchStartPosition = inputLength - bytesToSearch;
  if (input.getPosition() != searchStartPosition) {
    seekPositionHolder.position = searchStartPosition;
    return Extractor.RESULT_SEEK;
  }

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

  lastScrValue = readLastScrValueFromBuffer(packetBuffer);
  isLastScrValueRead = true;
  return Extractor.RESULT_CONTINUE;
}
 
Example 2
Source File: WebvttExtractor.java    From TelePlus-Android with GNU General Public License v2.0 6 votes vote down vote up
@Override
public int read(ExtractorInput input, PositionHolder seekPosition)
    throws IOException, InterruptedException {
  int currentFileSize = (int) input.getLength();

  // Increase the size of sampleData if necessary.
  if (sampleSize == sampleData.length) {
    sampleData = Arrays.copyOf(sampleData,
        (currentFileSize != C.LENGTH_UNSET ? currentFileSize : sampleData.length) * 3 / 2);
  }

  // Consume to the input.
  int bytesRead = input.read(sampleData, sampleSize, sampleData.length - sampleSize);
  if (bytesRead != C.RESULT_END_OF_INPUT) {
    sampleSize += bytesRead;
    if (currentFileSize == C.LENGTH_UNSET || sampleSize != currentFileSize) {
      return Extractor.RESULT_CONTINUE;
    }
  }

  // We've reached the end of the input, which corresponds to the end of the current file.
  processSample();
  return Extractor.RESULT_END_OF_INPUT;
}
 
Example 3
Source File: TsDurationReader.java    From Telegram with GNU General Public License v2.0 6 votes vote down vote up
private int readLastPcrValue(ExtractorInput input, PositionHolder seekPositionHolder, int pcrPid)
    throws IOException, InterruptedException {
  long inputLength = input.getLength();
  int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, inputLength);
  long searchStartPosition = inputLength - bytesToSearch;
  if (input.getPosition() != searchStartPosition) {
    seekPositionHolder.position = searchStartPosition;
    return Extractor.RESULT_SEEK;
  }

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

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

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

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

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

  lastPcrValue = readLastPcrValueFromBuffer(packetBuffer, pcrPid);
  isLastPcrValueRead = true;
  return Extractor.RESULT_CONTINUE;
}
 
Example 6
Source File: WebvttExtractor.java    From Telegram with GNU General Public License v2.0 6 votes vote down vote up
@Override
public int read(ExtractorInput input, PositionHolder seekPosition)
    throws IOException, InterruptedException {
  int currentFileSize = (int) input.getLength();

  // Increase the size of sampleData if necessary.
  if (sampleSize == sampleData.length) {
    sampleData = Arrays.copyOf(sampleData,
        (currentFileSize != C.LENGTH_UNSET ? currentFileSize : sampleData.length) * 3 / 2);
  }

  // Consume to the input.
  int bytesRead = input.read(sampleData, sampleSize, sampleData.length - sampleSize);
  if (bytesRead != C.RESULT_END_OF_INPUT) {
    sampleSize += bytesRead;
    if (currentFileSize == C.LENGTH_UNSET || sampleSize != currentFileSize) {
      return Extractor.RESULT_CONTINUE;
    }
  }

  // We've reached the end of the input, which corresponds to the end of the current file.
  processSample();
  return Extractor.RESULT_END_OF_INPUT;
}
 
Example 7
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 8
Source File: Mp3Extractor.java    From Telegram 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: 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 10
Source File: Sniffer.java    From K-Sonic with MIT License 4 votes vote down vote up
private static boolean sniffInternal(ExtractorInput input, boolean fragmented)
    throws IOException, InterruptedException {
  long inputLength = input.getLength();
  int bytesToSearch = (int) (inputLength == C.LENGTH_UNSET || inputLength > SEARCH_LENGTH
      ? SEARCH_LENGTH : inputLength);

  ParsableByteArray buffer = new ParsableByteArray(64);
  int bytesSearched = 0;
  boolean foundGoodFileType = false;
  boolean isFragmented = false;
  while (bytesSearched < bytesToSearch) {
    // Read an atom header.
    int headerSize = Atom.HEADER_SIZE;
    buffer.reset(headerSize);
    input.peekFully(buffer.data, 0, headerSize);
    long atomSize = buffer.readUnsignedInt();
    int atomType = buffer.readInt();
    if (atomSize == Atom.LONG_SIZE_PREFIX) {
      headerSize = Atom.LONG_HEADER_SIZE;
      input.peekFully(buffer.data, Atom.HEADER_SIZE, Atom.LONG_HEADER_SIZE - Atom.HEADER_SIZE);
      buffer.setLimit(Atom.LONG_HEADER_SIZE);
      atomSize = buffer.readUnsignedLongToLong();
    }

    if (atomSize < headerSize) {
      // The file is invalid because the atom size is too small for its header.
      return false;
    }
    bytesSearched += headerSize;

    if (atomType == Atom.TYPE_moov) {
      // Check for an mvex atom inside the moov atom to identify whether the file is fragmented.
      continue;
    }

    if (atomType == Atom.TYPE_moof || atomType == Atom.TYPE_mvex) {
      // The movie is fragmented. Stop searching as we must have read any ftyp atom already.
      isFragmented = true;
      break;
    }

    if (bytesSearched + atomSize - headerSize >= bytesToSearch) {
      // Stop searching as peeking this atom would exceed the search limit.
      break;
    }

    int atomDataSize = (int) (atomSize - headerSize);
    bytesSearched += atomDataSize;
    if (atomType == Atom.TYPE_ftyp) {
      // Parse the atom and check the file type/brand is compatible with the extractors.
      if (atomDataSize < 8) {
        return false;
      }
      buffer.reset(atomDataSize);
      input.peekFully(buffer.data, 0, atomDataSize);
      int brandsCount = atomDataSize / 4;
      for (int i = 0; i < brandsCount; i++) {
        if (i == 1) {
          // This index refers to the minorVersion, not a brand, so skip it.
          buffer.skipBytes(4);
        } else if (isCompatibleBrand(buffer.readInt())) {
          foundGoodFileType = true;
          break;
        }
      }
      if (!foundGoodFileType) {
        // The types were not compatible and there is only one ftyp atom, so reject the file.
        return false;
      }
    } else if (atomDataSize != 0) {
      // Skip the atom.
      input.advancePeekPosition(atomDataSize);
    }
  }
  return foundGoodFileType && fragmented == isFragmented;
}
 
Example 11
Source File: Sniffer.java    From Telegram with GNU General Public License v2.0 4 votes vote down vote up
private static boolean sniffInternal(ExtractorInput input, boolean fragmented)
    throws IOException, InterruptedException {
  long inputLength = input.getLength();
  int bytesToSearch = (int) (inputLength == C.LENGTH_UNSET || inputLength > SEARCH_LENGTH
      ? SEARCH_LENGTH : inputLength);

  ParsableByteArray buffer = new ParsableByteArray(64);
  int bytesSearched = 0;
  boolean foundGoodFileType = false;
  boolean isFragmented = false;
  while (bytesSearched < bytesToSearch) {
    // Read an atom header.
    int headerSize = Atom.HEADER_SIZE;
    buffer.reset(headerSize);
    input.peekFully(buffer.data, 0, headerSize);
    long atomSize = buffer.readUnsignedInt();
    int atomType = buffer.readInt();
    if (atomSize == Atom.DEFINES_LARGE_SIZE) {
      // Read the large atom size.
      headerSize = Atom.LONG_HEADER_SIZE;
      input.peekFully(buffer.data, Atom.HEADER_SIZE, Atom.LONG_HEADER_SIZE - Atom.HEADER_SIZE);
      buffer.setLimit(Atom.LONG_HEADER_SIZE);
      atomSize = buffer.readLong();
    } else if (atomSize == Atom.EXTENDS_TO_END_SIZE) {
      // The atom extends to the end of the file.
      long fileEndPosition = input.getLength();
      if (fileEndPosition != C.LENGTH_UNSET) {
        atomSize = fileEndPosition - input.getPeekPosition() + headerSize;
      }
    }

    if (inputLength != C.LENGTH_UNSET && bytesSearched + atomSize > inputLength + 10) { //added small trashhold for buggy files
      // The file is invalid because the atom extends past the end of the file.
      return false;
    }
    if (atomSize < headerSize) {
      // The file is invalid because the atom size is too small for its header.
      return false;
    }
    bytesSearched += headerSize;

    if (atomType == Atom.TYPE_moov) {
      // We have seen the moov atom. We increase the search size to make sure we don't miss an
      // mvex atom because the moov's size exceeds the search length.
      bytesToSearch += (int) atomSize;
      if (inputLength != C.LENGTH_UNSET && bytesToSearch > inputLength) {
        // Make sure we don't exceed the file size.
        bytesToSearch = (int) inputLength;
      }
      // Check for an mvex atom inside the moov atom to identify whether the file is fragmented.
      continue;
    }

    if (atomType == Atom.TYPE_moof || atomType == Atom.TYPE_mvex) {
      // The movie is fragmented. Stop searching as we must have read any ftyp atom already.
      isFragmented = true;
      break;
    }

    if (bytesSearched + atomSize - headerSize >= bytesToSearch) {
      // Stop searching as peeking this atom would exceed the search limit.
      break;
    }

    int atomDataSize = (int) (atomSize - headerSize);
    bytesSearched += atomDataSize;
    if (atomType == Atom.TYPE_ftyp) {
      // Parse the atom and check the file type/brand is compatible with the extractors.
      if (atomDataSize < 8) {
        return false;
      }
      buffer.reset(atomDataSize);
      input.peekFully(buffer.data, 0, atomDataSize);
      int brandsCount = atomDataSize / 4;
      for (int i = 0; i < brandsCount; i++) {
        if (i == 1) {
          // This index refers to the minorVersion, not a brand, so skip it.
          buffer.skipBytes(4);
        } else if (isCompatibleBrand(buffer.readInt())) {
          foundGoodFileType = true;
          break;
        }
      }
      if (!foundGoodFileType) {
        // The types were not compatible and there is only one ftyp atom, so reject the file.
        return false;
      }
    } else if (atomDataSize != 0) {
      // Skip the atom.
      input.advancePeekPosition(atomDataSize);
    }
  }
  return foundGoodFileType && fragmented == isFragmented;
}
 
Example 12
Source File: Sniffer.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
/**
 * @see com.google.android.exoplayer2.extractor.Extractor#sniff(ExtractorInput)
 */
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
  long inputLength = input.getLength();
  int bytesToSearch = (int) (inputLength == C.LENGTH_UNSET || inputLength > SEARCH_LENGTH
      ? SEARCH_LENGTH : inputLength);
  // Find four bytes equal to ID_EBML near the start of the input.
  input.peekFully(scratch.data, 0, 4);
  long tag = scratch.readUnsignedInt();
  peekLength = 4;
  while (tag != ID_EBML) {
    if (++peekLength == bytesToSearch) {
      return false;
    }
    input.peekFully(scratch.data, 0, 1);
    tag = (tag << 8) & 0xFFFFFF00;
    tag |= scratch.data[0] & 0xFF;
  }

  // Read the size of the EBML header and make sure it is within the stream.
  long headerSize = readUint(input);
  long headerStart = peekLength;
  if (headerSize == Long.MIN_VALUE
      || (inputLength != C.LENGTH_UNSET && headerStart + headerSize >= inputLength)) {
    return false;
  }

  // Read the payload elements in the EBML header.
  while (peekLength < headerStart + headerSize) {
    long id = readUint(input);
    if (id == Long.MIN_VALUE) {
      return false;
    }
    long size = readUint(input);
    if (size < 0 || size > Integer.MAX_VALUE) {
      return false;
    }
    if (size != 0) {
      int sizeInt = (int) size;
      input.advancePeekPosition(sizeInt);
      peekLength += sizeInt;
    }
  }
  return peekLength == headerStart + headerSize;
}
 
Example 13
Source File: Sniffer.java    From Telegram with GNU General Public License v2.0 4 votes vote down vote up
/**
 * @see com.google.android.exoplayer2.extractor.Extractor#sniff(ExtractorInput)
 */
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
  long inputLength = input.getLength();
  int bytesToSearch = (int) (inputLength == C.LENGTH_UNSET || inputLength > SEARCH_LENGTH
      ? SEARCH_LENGTH : inputLength);
  // Find four bytes equal to ID_EBML near the start of the input.
  input.peekFully(scratch.data, 0, 4);
  long tag = scratch.readUnsignedInt();
  peekLength = 4;
  while (tag != ID_EBML) {
    if (++peekLength == bytesToSearch) {
      return false;
    }
    input.peekFully(scratch.data, 0, 1);
    tag = (tag << 8) & 0xFFFFFF00;
    tag |= scratch.data[0] & 0xFF;
  }

  // Read the size of the EBML header and make sure it is within the stream.
  long headerSize = readUint(input);
  long headerStart = peekLength;
  if (headerSize == Long.MIN_VALUE
      || (inputLength != C.LENGTH_UNSET && headerStart + headerSize >= inputLength)) {
    return false;
  }

  // Read the payload elements in the EBML header.
  while (peekLength < headerStart + headerSize) {
    long id = readUint(input);
    if (id == Long.MIN_VALUE) {
      return false;
    }
    long size = readUint(input);
    if (size < 0 || size > Integer.MAX_VALUE) {
      return false;
    }
    if (size != 0) {
      int sizeInt = (int) size;
      input.advancePeekPosition(sizeInt);
      peekLength += sizeInt;
    }
  }
  return peekLength == headerStart + headerSize;
}
 
Example 14
Source File: OggPageHeader.java    From Telegram with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Peeks an Ogg page header and updates this {@link OggPageHeader}.
 *
 * @param input The {@link ExtractorInput} to read from.
 * @param quiet Whether to return {@code false} rather than throwing an exception if the header
 *     cannot be populated.
 * @return Whether the read was successful. The read fails if the end of the input is encountered
 *     without reading data.
 * @throws IOException If reading data fails or the stream is invalid.
 * @throws InterruptedException If the thread is interrupted.
 */
public boolean populate(ExtractorInput input, boolean quiet)
    throws IOException, InterruptedException {
  scratch.reset();
  reset();
  boolean hasEnoughBytes = input.getLength() == C.LENGTH_UNSET
      || input.getLength() - input.getPeekPosition() >= EMPTY_PAGE_HEADER_SIZE;
  if (!hasEnoughBytes || !input.peekFully(scratch.data, 0, EMPTY_PAGE_HEADER_SIZE, true)) {
    if (quiet) {
      return false;
    } else {
      throw new EOFException();
    }
  }
  if (scratch.readUnsignedInt() != TYPE_OGGS) {
    if (quiet) {
      return false;
    } else {
      throw new ParserException("expected OggS capture pattern at begin of page");
    }
  }

  revision = scratch.readUnsignedByte();
  if (revision != 0x00) {
    if (quiet) {
      return false;
    } else {
      throw new ParserException("unsupported bit stream revision");
    }
  }
  type = scratch.readUnsignedByte();

  granulePosition = scratch.readLittleEndianLong();
  streamSerialNumber = scratch.readLittleEndianUnsignedInt();
  pageSequenceNumber = scratch.readLittleEndianUnsignedInt();
  pageChecksum = scratch.readLittleEndianUnsignedInt();
  pageSegmentCount = scratch.readUnsignedByte();
  headerSize = EMPTY_PAGE_HEADER_SIZE + pageSegmentCount;

  // calculate total size of header including laces
  scratch.reset();
  input.peekFully(scratch.data, 0, pageSegmentCount);
  for (int i = 0; i < pageSegmentCount; i++) {
    laces[i] = scratch.readUnsignedByte();
    bodySize += laces[i];
  }

  return true;
}
 
Example 15
Source File: OggPageHeader.java    From K-Sonic with MIT License 4 votes vote down vote up
/**
 * Peeks an Ogg page header and updates this {@link OggPageHeader}.
 *
 * @param input the {@link ExtractorInput} to read from.
 * @param quiet if {@code true} no Exceptions are thrown but {@code false} is return if something
 *    goes wrong.
 * @return {@code true} if the read was successful. {@code false} if the end of the input was
 *    encountered having read no data.
 * @throws IOException thrown if reading data fails or the stream is invalid.
 * @throws InterruptedException thrown if thread is interrupted when reading/peeking.
 */
public boolean populate(ExtractorInput input, boolean quiet)
    throws IOException, InterruptedException {
  scratch.reset();
  reset();
  boolean hasEnoughBytes = input.getLength() == C.LENGTH_UNSET
      || input.getLength() - input.getPeekPosition() >= EMPTY_PAGE_HEADER_SIZE;
  if (!hasEnoughBytes || !input.peekFully(scratch.data, 0, EMPTY_PAGE_HEADER_SIZE, true)) {
    if (quiet) {
      return false;
    } else {
      throw new EOFException();
    }
  }
  if (scratch.readUnsignedInt() != TYPE_OGGS) {
    if (quiet) {
      return false;
    } else {
      throw new ParserException("expected OggS capture pattern at begin of page");
    }
  }

  revision = scratch.readUnsignedByte();
  if (revision != 0x00) {
    if (quiet) {
      return false;
    } else {
      throw new ParserException("unsupported bit stream revision");
    }
  }
  type = scratch.readUnsignedByte();

  granulePosition = scratch.readLittleEndianLong();
  streamSerialNumber = scratch.readLittleEndianUnsignedInt();
  pageSequenceNumber = scratch.readLittleEndianUnsignedInt();
  pageChecksum = scratch.readLittleEndianUnsignedInt();
  pageSegmentCount = scratch.readUnsignedByte();
  headerSize = EMPTY_PAGE_HEADER_SIZE + pageSegmentCount;

  // calculate total size of header including laces
  scratch.reset();
  input.peekFully(scratch.data, 0, pageSegmentCount);
  for (int i = 0; i < pageSegmentCount; i++) {
    laces[i] = scratch.readUnsignedByte();
    bodySize += laces[i];
  }

  return true;
}
 
Example 16
Source File: Mp3Extractor.java    From K-Sonic with MIT License 4 votes vote down vote up
/**
 * Returns a {@link Seeker} to seek using metadata read from {@code input}, which should provide
 * data from the start of the first frame in the stream. On returning, the input's position will
 * be set to the start of the first frame of audio.
 *
 * @param input The {@link ExtractorInput} from which to read.
 * @throws IOException Thrown if there was an error reading from the stream. Not expected if the
 *     next two frames were already peeked during synchronization.
 * @throws InterruptedException Thrown if reading from the stream was interrupted. Not expected if
 *     the next two frames were already peeked during synchronization.
 * @return a {@link Seeker}.
 */
private Seeker setupSeeker(ExtractorInput input) throws IOException, InterruptedException {
  // Read the first frame which may contain a Xing or VBRI header with seeking metadata.
  ParsableByteArray frame = new ParsableByteArray(synchronizedHeader.frameSize);
  input.peekFully(frame.data, 0, synchronizedHeader.frameSize);

  long position = input.getPosition();
  long length = input.getLength();
  int headerData = 0;
  Seeker seeker = null;

  // Check if there is a Xing header.
  int xingBase = (synchronizedHeader.version & 1) != 0
      ? (synchronizedHeader.channels != 1 ? 36 : 21) // MPEG 1
      : (synchronizedHeader.channels != 1 ? 21 : 13); // MPEG 2 or 2.5
  if (frame.limit() >= xingBase + 4) {
    frame.setPosition(xingBase);
    headerData = frame.readInt();
  }
  if (headerData == XING_HEADER || headerData == INFO_HEADER) {
    seeker = XingSeeker.create(synchronizedHeader, frame, position, length);
    if (seeker != null && !gaplessInfoHolder.hasGaplessInfo()) {
      // If there is a Xing header, read gapless playback metadata at a fixed offset.
      input.resetPeekPosition();
      input.advancePeekPosition(xingBase + 141);
      input.peekFully(scratch.data, 0, 3);
      scratch.setPosition(0);
      gaplessInfoHolder.setFromXingHeaderValue(scratch.readUnsignedInt24());
    }
    input.skipFully(synchronizedHeader.frameSize);
  } else if (frame.limit() >= 40) {
    // Check if there is a VBRI header.
    frame.setPosition(36); // MPEG audio header (4 bytes) + 32 bytes.
    headerData = frame.readInt();
    if (headerData == VBRI_HEADER) {
      seeker = VbriSeeker.create(synchronizedHeader, frame, position, length);
      input.skipFully(synchronizedHeader.frameSize);
    }
  }

  if (seeker == null || (!seeker.isSeekable()
      && (flags & FLAG_ENABLE_CONSTANT_BITRATE_SEEKING) != 0)) {
    // Repopulate the synchronized header in case we had to skip an invalid seeking header, which
    // would give an invalid CBR bitrate.
    input.resetPeekPosition();
    input.peekFully(scratch.data, 0, 4);
    scratch.setPosition(0);
    MpegAudioHeader.populateHeader(scratch.readInt(), synchronizedHeader);
    seeker = new ConstantBitrateSeeker(input.getPosition(), synchronizedHeader.bitrate, length);
  }

  return seeker;
}
 
Example 17
Source File: Sniffer.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
private static boolean sniffInternal(ExtractorInput input, boolean fragmented)
    throws IOException, InterruptedException {
  long inputLength = input.getLength();
  int bytesToSearch = (int) (inputLength == C.LENGTH_UNSET || inputLength > SEARCH_LENGTH
      ? SEARCH_LENGTH : inputLength);

  ParsableByteArray buffer = new ParsableByteArray(64);
  int bytesSearched = 0;
  boolean foundGoodFileType = false;
  boolean isFragmented = false;
  while (bytesSearched < bytesToSearch) {
    // Read an atom header.
    int headerSize = Atom.HEADER_SIZE;
    buffer.reset(headerSize);
    input.peekFully(buffer.data, 0, headerSize);
    long atomSize = buffer.readUnsignedInt();
    int atomType = buffer.readInt();
    if (atomSize == Atom.DEFINES_LARGE_SIZE) {
      // Read the large atom size.
      headerSize = Atom.LONG_HEADER_SIZE;
      input.peekFully(buffer.data, Atom.HEADER_SIZE, Atom.LONG_HEADER_SIZE - Atom.HEADER_SIZE);
      buffer.setLimit(Atom.LONG_HEADER_SIZE);
      atomSize = buffer.readLong();
    } else if (atomSize == Atom.EXTENDS_TO_END_SIZE) {
      // The atom extends to the end of the file.
      long fileEndPosition = input.getLength();
      if (fileEndPosition != C.LENGTH_UNSET) {
        atomSize = fileEndPosition - input.getPeekPosition() + headerSize;
      }
    }

    if (atomSize < headerSize) {
      // The file is invalid because the atom size is too small for its header.
      return false;
    }
    bytesSearched += headerSize;

    if (atomType == Atom.TYPE_moov) {
      // We have seen the moov atom. We increase the search size to make sure we don't miss an
      // mvex atom because the moov's size exceeds the search length.
      bytesToSearch += (int) atomSize;
      if (inputLength != C.LENGTH_UNSET && bytesToSearch > inputLength) {
        // Make sure we don't exceed the file size.
        bytesToSearch = (int) inputLength;
      }
      // Check for an mvex atom inside the moov atom to identify whether the file is fragmented.
      continue;
    }

    if (atomType == Atom.TYPE_moof || atomType == Atom.TYPE_mvex) {
      // The movie is fragmented. Stop searching as we must have read any ftyp atom already.
      isFragmented = true;
      break;
    }

    if (bytesSearched + atomSize - headerSize >= bytesToSearch) {
      // Stop searching as peeking this atom would exceed the search limit.
      break;
    }

    int atomDataSize = (int) (atomSize - headerSize);
    bytesSearched += atomDataSize;
    if (atomType == Atom.TYPE_ftyp) {
      // Parse the atom and check the file type/brand is compatible with the extractors.
      if (atomDataSize < 8) {
        return false;
      }
      buffer.reset(atomDataSize);
      input.peekFully(buffer.data, 0, atomDataSize);
      int brandsCount = atomDataSize / 4;
      for (int i = 0; i < brandsCount; i++) {
        if (i == 1) {
          // This index refers to the minorVersion, not a brand, so skip it.
          buffer.skipBytes(4);
        } else if (isCompatibleBrand(buffer.readInt())) {
          foundGoodFileType = true;
          break;
        }
      }
      if (!foundGoodFileType) {
        // The types were not compatible and there is only one ftyp atom, so reject the file.
        return false;
      }
    } else if (atomDataSize != 0) {
      // Skip the atom.
      input.advancePeekPosition(atomDataSize);
    }
  }
  return foundGoodFileType && fragmented == isFragmented;
}
 
Example 18
Source File: StreamReader.java    From Telegram-FOSS with GNU General Public License v2.0 4 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();
    boolean isLastPage = (firstPayloadPageHeader.type & 0x04) != 0; // Type 4 is end of stream.
    oggSeeker =
        new DefaultOggSeeker(
            this,
            payloadStartPosition,
            input.getLength(),
            firstPayloadPageHeader.headerSize + firstPayloadPageHeader.bodySize,
            firstPayloadPageHeader.granulePosition,
            isLastPage);
  }

  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 19
Source File: OggPageHeader.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Peeks an Ogg page header and updates this {@link OggPageHeader}.
 *
 * @param input The {@link ExtractorInput} to read from.
 * @param quiet Whether to return {@code false} rather than throwing an exception if the header
 *     cannot be populated.
 * @return Whether the read was successful. The read fails if the end of the input is encountered
 *     without reading data.
 * @throws IOException If reading data fails or the stream is invalid.
 * @throws InterruptedException If the thread is interrupted.
 */
public boolean populate(ExtractorInput input, boolean quiet)
    throws IOException, InterruptedException {
  scratch.reset();
  reset();
  boolean hasEnoughBytes = input.getLength() == C.LENGTH_UNSET
      || input.getLength() - input.getPeekPosition() >= EMPTY_PAGE_HEADER_SIZE;
  if (!hasEnoughBytes || !input.peekFully(scratch.data, 0, EMPTY_PAGE_HEADER_SIZE, true)) {
    if (quiet) {
      return false;
    } else {
      throw new EOFException();
    }
  }
  if (scratch.readUnsignedInt() != TYPE_OGGS) {
    if (quiet) {
      return false;
    } else {
      throw new ParserException("expected OggS capture pattern at begin of page");
    }
  }

  revision = scratch.readUnsignedByte();
  if (revision != 0x00) {
    if (quiet) {
      return false;
    } else {
      throw new ParserException("unsupported bit stream revision");
    }
  }
  type = scratch.readUnsignedByte();

  granulePosition = scratch.readLittleEndianLong();
  streamSerialNumber = scratch.readLittleEndianUnsignedInt();
  pageSequenceNumber = scratch.readLittleEndianUnsignedInt();
  pageChecksum = scratch.readLittleEndianUnsignedInt();
  pageSegmentCount = scratch.readUnsignedByte();
  headerSize = EMPTY_PAGE_HEADER_SIZE + pageSegmentCount;

  // calculate total size of header including laces
  scratch.reset();
  input.peekFully(scratch.data, 0, pageSegmentCount);
  for (int i = 0; i < pageSegmentCount; i++) {
    laces[i] = scratch.readUnsignedByte();
    bodySize += laces[i];
  }

  return true;
}
 
Example 20
Source File: OggPageHeader.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Peeks an Ogg page header and updates this {@link OggPageHeader}.
 *
 * @param input the {@link ExtractorInput} to read from.
 * @param quiet if {@code true} no Exceptions are thrown but {@code false} is return if something
 *    goes wrong.
 * @return {@code true} if the read was successful. {@code false} if the end of the input was
 *    encountered having read no data.
 * @throws IOException thrown if reading data fails or the stream is invalid.
 * @throws InterruptedException thrown if thread is interrupted when reading/peeking.
 */
public boolean populate(ExtractorInput input, boolean quiet)
    throws IOException, InterruptedException {
  scratch.reset();
  reset();
  boolean hasEnoughBytes = input.getLength() == C.LENGTH_UNSET
      || input.getLength() - input.getPeekPosition() >= EMPTY_PAGE_HEADER_SIZE;
  if (!hasEnoughBytes || !input.peekFully(scratch.data, 0, EMPTY_PAGE_HEADER_SIZE, true)) {
    if (quiet) {
      return false;
    } else {
      throw new EOFException();
    }
  }
  if (scratch.readUnsignedInt() != TYPE_OGGS) {
    if (quiet) {
      return false;
    } else {
      throw new ParserException("expected OggS capture pattern at begin of page");
    }
  }

  revision = scratch.readUnsignedByte();
  if (revision != 0x00) {
    if (quiet) {
      return false;
    } else {
      throw new ParserException("unsupported bit stream revision");
    }
  }
  type = scratch.readUnsignedByte();

  granulePosition = scratch.readLittleEndianLong();
  streamSerialNumber = scratch.readLittleEndianUnsignedInt();
  pageSequenceNumber = scratch.readLittleEndianUnsignedInt();
  pageChecksum = scratch.readLittleEndianUnsignedInt();
  pageSegmentCount = scratch.readUnsignedByte();
  headerSize = EMPTY_PAGE_HEADER_SIZE + pageSegmentCount;

  // calculate total size of header including laces
  scratch.reset();
  input.peekFully(scratch.data, 0, pageSegmentCount);
  for (int i = 0; i < pageSegmentCount; i++) {
    laces[i] = scratch.readUnsignedByte();
    bodySize += laces[i];
  }

  return true;
}