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

The following examples show how to use com.google.android.exoplayer2.extractor.ExtractorInput#peekFully() . 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: AdtsExtractor.java    From MediaSDK with Apache License 2.0 6 votes vote down vote up
private int peekId3Header(ExtractorInput input) throws IOException, InterruptedException {
  int firstFramePosition = 0;
  while (true) {
    input.peekFully(scratch.data, /* offset= */ 0, ID3_HEADER_LENGTH);
    scratch.setPosition(0);
    if (scratch.readUnsignedInt24() != ID3_TAG) {
      break;
    }
    scratch.skipBytes(3);
    int length = scratch.readSynchSafeInt();
    firstFramePosition += ID3_HEADER_LENGTH + length;
    input.advancePeekPosition(length);
  }
  input.resetPeekPosition();
  input.advancePeekPosition(firstFramePosition);
  if (this.firstFramePosition == C.POSITION_UNSET) {
    this.firstFramePosition = firstFramePosition;
  }
  return firstFramePosition;
}
 
Example 2
Source File: Sniffer.java    From Telegram with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Peeks a variable-length unsigned EBML integer from the input.
 */
private long readUint(ExtractorInput input) throws IOException, InterruptedException {
  input.peekFully(scratch.data, 0, 1);
  int value = scratch.data[0] & 0xFF;
  if (value == 0) {
    return Long.MIN_VALUE;
  }
  int mask = 0x80;
  int length = 0;
  while ((value & mask) == 0) {
    mask >>= 1;
    length++;
  }
  value &= ~mask;
  input.peekFully(scratch.data, 1, length);
  for (int i = 0; i < length; i++) {
    value <<= 8;
    value += scratch.data[i + 1] & 0xFF;
  }
  peekLength += length + 1;
  return value;
}
 
Example 3
Source File: PsDurationReader.java    From TelePlus-Android with GNU General Public License v2.0 6 votes vote down vote up
private int readLastScrValue(ExtractorInput input, PositionHolder seekPositionHolder)
    throws IOException, InterruptedException {
  int bytesToRead = (int) Math.min(DURATION_READ_BYTES, input.getLength());
  long bufferStartStreamPosition = input.getLength() - bytesToRead;
  if (input.getPosition() != bufferStartStreamPosition) {
    seekPositionHolder.position = bufferStartStreamPosition;
    return Extractor.RESULT_SEEK;
  }

  input.resetPeekPosition();
  input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToRead);
  packetBuffer.setPosition(0);
  packetBuffer.setLimit(bytesToRead);

  lastScrValue = readLastScrValueFromBuffer(packetBuffer);
  isLastScrValueRead = 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 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 5
Source File: DefaultEbmlReader.java    From K-Sonic with MIT License 6 votes vote down vote up
/**
 * Does a byte by byte search to try and find the next level 1 element. This method is called if
 * some invalid data is encountered in the parser.
 *
 * @param input The {@link ExtractorInput} from which data has to be read.
 * @return id of the next level 1 element that has been found.
 * @throws EOFException If the end of input was encountered when searching for the next level 1
 *     element.
 * @throws IOException If an error occurs reading from the input.
 * @throws InterruptedException If the thread is interrupted.
 */
private long maybeResyncToNextLevel1Element(ExtractorInput input) throws IOException,
    InterruptedException {
  input.resetPeekPosition();
  while (true) {
    input.peekFully(scratch, 0, MAX_ID_BYTES);
    int varintLength = VarintReader.parseUnsignedVarintLength(scratch[0]);
    if (varintLength != C.LENGTH_UNSET && varintLength <= MAX_ID_BYTES) {
      int potentialId = (int) VarintReader.assembleVarint(scratch, varintLength, false);
      if (output.isLevel1Element(potentialId)) {
        input.skipFully(varintLength);
        return potentialId;
      }
    }
    input.skipFully(1);
  }
}
 
Example 6
Source File: TsDurationReader.java    From TelePlus-Android 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 {
  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);

  firstPcrValue = readFirstPcrValueFromBuffer(packetBuffer, pcrPid);
  isFirstPcrValueRead = true;
  return Extractor.RESULT_CONTINUE;
}
 
Example 7
Source File: TsExtractor.java    From TelePlus-Android with GNU General Public License v2.0 6 votes vote down vote up
@Override
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
  byte[] buffer = tsPacketBuffer.data;
  input.peekFully(buffer, 0, TS_PACKET_SIZE * SNIFF_TS_PACKET_COUNT);
  for (int startPosCandidate = 0; startPosCandidate < TS_PACKET_SIZE; startPosCandidate++) {
    // Try to identify at least SNIFF_TS_PACKET_COUNT packets starting with TS_SYNC_BYTE.
    boolean isSyncBytePatternCorrect = true;
    for (int i = 0; i < SNIFF_TS_PACKET_COUNT; i++) {
      if (buffer[startPosCandidate + i * TS_PACKET_SIZE] != TS_SYNC_BYTE) {
        isSyncBytePatternCorrect = false;
        break;
      }
    }
    if (isSyncBytePatternCorrect) {
      input.skipFully(startPosCandidate);
      return true;
    }
  }
  return false;
}
 
Example 8
Source File: Sniffer.java    From TelePlus-Android with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Peeks a variable-length unsigned EBML integer from the input.
 */
private long readUint(ExtractorInput input) throws IOException, InterruptedException {
  input.peekFully(scratch.data, 0, 1);
  int value = scratch.data[0] & 0xFF;
  if (value == 0) {
    return Long.MIN_VALUE;
  }
  int mask = 0x80;
  int length = 0;
  while ((value & mask) == 0) {
    mask >>= 1;
    length++;
  }
  value &= ~mask;
  input.peekFully(scratch.data, 1, length);
  for (int i = 0; i < length; i++) {
    value <<= 8;
    value += scratch.data[i + 1] & 0xFF;
  }
  peekLength += length + 1;
  return value;
}
 
Example 9
Source File: DefaultEbmlReader.java    From MediaSDK with Apache License 2.0 6 votes vote down vote up
/**
 * Does a byte by byte search to try and find the next level 1 element. This method is called if
 * some invalid data is encountered in the parser.
 *
 * @param input The {@link ExtractorInput} from which data has to be read.
 * @return id of the next level 1 element that has been found.
 * @throws EOFException If the end of input was encountered when searching for the next level 1
 *     element.
 * @throws IOException If an error occurs reading from the input.
 * @throws InterruptedException If the thread is interrupted.
 */
private long maybeResyncToNextLevel1Element(ExtractorInput input) throws IOException,
    InterruptedException {
  input.resetPeekPosition();
  while (true) {
    input.peekFully(scratch, 0, MAX_ID_BYTES);
    int varintLength = VarintReader.parseUnsignedVarintLength(scratch[0]);
    if (varintLength != C.LENGTH_UNSET && varintLength <= MAX_ID_BYTES) {
      int potentialId = (int) VarintReader.assembleVarint(scratch, varintLength, false);
      if (processor.isLevel1Element(potentialId)) {
        input.skipFully(varintLength);
        return potentialId;
      }
    }
    input.skipFully(1);
  }
}
 
Example 10
Source File: OggExtractor.java    From TelePlus-Android with GNU General Public License v2.0 6 votes vote down vote up
private boolean sniffInternal(ExtractorInput input) throws IOException, InterruptedException {
  OggPageHeader header = new OggPageHeader();
  if (!header.populate(input, true) || (header.type & 0x02) != 0x02) {
    return false;
  }

  int length = Math.min(header.bodySize, MAX_VERIFICATION_BYTES);
  ParsableByteArray scratch = new ParsableByteArray(length);
  input.peekFully(scratch.data, 0, length);

  if (FlacReader.verifyBitstreamType(resetPosition(scratch))) {
    streamReader = new FlacReader();
  } else if (VorbisReader.verifyBitstreamType(resetPosition(scratch))) {
    streamReader = new VorbisReader();
  } else if (OpusReader.verifyBitstreamType(resetPosition(scratch))) {
    streamReader = new OpusReader();
  } else {
    return false;
  }
  return true;
}
 
Example 11
Source File: Mp3Extractor.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
/**
 * Consumes the next frame from the {@code input} if it contains VBRI or Xing seeking metadata,
 * returning a {@link Seeker} if the metadata was present and valid, or {@code null} otherwise.
 * After this method returns, the input position is the start of the first frame of audio.
 *
 * @param input The {@link ExtractorInput} from which to read.
 * @return A {@link Seeker} if seeking metadata was present and valid, or {@code null} otherwise.
 * @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.
 */
private Seeker maybeReadSeekFrame(ExtractorInput input) throws IOException, InterruptedException {
  ParsableByteArray frame = new ParsableByteArray(synchronizedHeader.frameSize);
  input.peekFully(frame.data, 0, synchronizedHeader.frameSize);
  int xingBase = (synchronizedHeader.version & 1) != 0
      ? (synchronizedHeader.channels != 1 ? 36 : 21) // MPEG 1
      : (synchronizedHeader.channels != 1 ? 21 : 13); // MPEG 2 or 2.5
  int seekHeader = getSeekFrameHeader(frame, xingBase);
  Seeker seeker;
  if (seekHeader == SEEK_HEADER_XING || seekHeader == SEEK_HEADER_INFO) {
    seeker = XingSeeker.create(input.getLength(), input.getPosition(), synchronizedHeader, frame);
    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);
    if (seeker != null && !seeker.isSeekable() && seekHeader == SEEK_HEADER_INFO) {
      // Fall back to constant bitrate seeking for Info headers missing a table of contents.
      return getConstantBitrateSeeker(input);
    }
  } else if (seekHeader == SEEK_HEADER_VBRI) {
    seeker = VbriSeeker.create(input.getLength(), input.getPosition(), synchronizedHeader, frame);
    input.skipFully(synchronizedHeader.frameSize);
  } else { // seekerHeader == SEEK_HEADER_UNSET
    // This frame doesn't contain seeking information, so reset the peek position.
    seeker = null;
    input.resetPeekPosition();
  }
  return seeker;
}
 
Example 12
Source File: Mp3Extractor.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Consumes the next frame from the {@code input} if it contains VBRI or Xing seeking metadata,
 * returning a {@link Seeker} if the metadata was present and valid, or {@code null} otherwise.
 * After this method returns, the input position is the start of the first frame of audio.
 *
 * @param input The {@link ExtractorInput} from which to read.
 * @return A {@link Seeker} if seeking metadata was present and valid, or {@code null} otherwise.
 * @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.
 */
private Seeker maybeReadSeekFrame(ExtractorInput input) throws IOException, InterruptedException {
  ParsableByteArray frame = new ParsableByteArray(synchronizedHeader.frameSize);
  input.peekFully(frame.data, 0, synchronizedHeader.frameSize);
  int xingBase = (synchronizedHeader.version & 1) != 0
      ? (synchronizedHeader.channels != 1 ? 36 : 21) // MPEG 1
      : (synchronizedHeader.channels != 1 ? 21 : 13); // MPEG 2 or 2.5
  int seekHeader = getSeekFrameHeader(frame, xingBase);
  Seeker seeker;
  if (seekHeader == SEEK_HEADER_XING || seekHeader == SEEK_HEADER_INFO) {
    seeker = XingSeeker.create(input.getLength(), input.getPosition(), synchronizedHeader, frame);
    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);
    if (seeker != null && !seeker.isSeekable() && seekHeader == SEEK_HEADER_INFO) {
      // Fall back to constant bitrate seeking for Info headers missing a table of contents.
      return getConstantBitrateSeeker(input);
    }
  } else if (seekHeader == SEEK_HEADER_VBRI) {
    seeker = VbriSeeker.create(input.getLength(), input.getPosition(), synchronizedHeader, frame);
    input.skipFully(synchronizedHeader.frameSize);
  } else { // seekerHeader == SEEK_HEADER_UNSET
    // This frame doesn't contain seeking information, so reset the peek position.
    seeker = null;
    input.resetPeekPosition();
  }
  return seeker;
}
 
Example 13
Source File: MatroskaExtractor.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
public void startSample(ExtractorInput input) throws IOException, InterruptedException {
  if (foundSyncframe) {
    return;
  }
  input.peekFully(syncframePrefix, 0, Ac3Util.TRUEHD_SYNCFRAME_PREFIX_LENGTH);
  input.resetPeekPosition();
  if (Ac3Util.parseTrueHdSyncframeAudioSampleCount(syncframePrefix) == 0) {
    return;
  }
  foundSyncframe = true;
}
 
Example 14
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 15
Source File: Ac3Extractor.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
@Override
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
  // Skip any ID3 headers.
  ParsableByteArray scratch = new ParsableByteArray(10);
  int startPosition = 0;
  while (true) {
    input.peekFully(scratch.data, 0, 10);
    scratch.setPosition(0);
    if (scratch.readUnsignedInt24() != ID3_TAG) {
      break;
    }
    scratch.skipBytes(3); // version, flags
    int length = scratch.readSynchSafeInt();
    startPosition += 10 + length;
    input.advancePeekPosition(length);
  }
  input.resetPeekPosition();
  input.advancePeekPosition(startPosition);

  int headerPosition = startPosition;
  int validFramesCount = 0;
  while (true) {
    input.peekFully(scratch.data, 0, 6);
    scratch.setPosition(0);
    int syncBytes = scratch.readUnsignedShort();
    if (syncBytes != AC3_SYNC_WORD) {
      validFramesCount = 0;
      input.resetPeekPosition();
      if (++headerPosition - startPosition >= MAX_SNIFF_BYTES) {
        return false;
      }
      input.advancePeekPosition(headerPosition);
    } else {
      if (++validFramesCount >= 4) {
        return true;
      }
      int frameSize = Ac3Util.parseAc3SyncframeSize(scratch.data);
      if (frameSize == C.LENGTH_UNSET) {
        return false;
      }
      input.advancePeekPosition(frameSize - 6);
    }
  }
}
 
Example 16
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 17
Source File: WavHeaderReader.java    From Telegram with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Peeks and returns a {@code WavHeader}.
 *
 * @param input Input stream to peek the WAV header from.
 * @throws ParserException If the input file is an incorrect RIFF WAV.
 * @throws IOException If peeking from the input fails.
 * @throws InterruptedException If interrupted while peeking from input.
 * @return A new {@code WavHeader} peeked from {@code input}, or null if the input is not a
 *     supported WAV format.
 */
public static WavHeader peek(ExtractorInput input) throws IOException, InterruptedException {
  Assertions.checkNotNull(input);

  // Allocate a scratch buffer large enough to store the format chunk.
  ParsableByteArray scratch = new ParsableByteArray(16);

  // Attempt to read the RIFF chunk.
  ChunkHeader chunkHeader = ChunkHeader.peek(input, scratch);
  if (chunkHeader.id != WavUtil.RIFF_FOURCC) {
    return null;
  }

  input.peekFully(scratch.data, 0, 4);
  scratch.setPosition(0);
  int riffFormat = scratch.readInt();
  if (riffFormat != WavUtil.WAVE_FOURCC) {
    Log.e(TAG, "Unsupported RIFF format: " + riffFormat);
    return null;
  }

  // Skip chunks until we find the format chunk.
  chunkHeader = ChunkHeader.peek(input, scratch);
  while (chunkHeader.id != WavUtil.FMT_FOURCC) {
    input.advancePeekPosition((int) chunkHeader.size);
    chunkHeader = ChunkHeader.peek(input, scratch);
  }

  Assertions.checkState(chunkHeader.size >= 16);
  input.peekFully(scratch.data, 0, 16);
  scratch.setPosition(0);
  int type = scratch.readLittleEndianUnsignedShort();
  int numChannels = scratch.readLittleEndianUnsignedShort();
  int sampleRateHz = scratch.readLittleEndianUnsignedIntToInt();
  int averageBytesPerSecond = scratch.readLittleEndianUnsignedIntToInt();
  int blockAlignment = scratch.readLittleEndianUnsignedShort();
  int bitsPerSample = scratch.readLittleEndianUnsignedShort();

  int expectedBlockAlignment = numChannels * bitsPerSample / 8;
  if (blockAlignment != expectedBlockAlignment) {
    throw new ParserException("Expected block alignment: " + expectedBlockAlignment + "; got: "
        + blockAlignment);
  }

  @C.PcmEncoding int encoding = WavUtil.getEncodingForType(type, bitsPerSample);
  if (encoding == C.ENCODING_INVALID) {
    Log.e(TAG, "Unsupported WAV format: " + bitsPerSample + " bit/sample, type " + type);
    return null;
  }

  // If present, skip extensionSize, validBitsPerSample, channelMask, subFormatGuid, ...
  input.advancePeekPosition((int) chunkHeader.size - 16);

  return new WavHeader(
      numChannels, sampleRateHz, averageBytesPerSecond, blockAlignment, bitsPerSample, encoding);
}
 
Example 18
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 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: AdtsExtractor.java    From K-Sonic with MIT License 4 votes vote down vote up
@Override
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
  // Skip any ID3 headers.
  ParsableByteArray scratch = new ParsableByteArray(10);
  ParsableBitArray scratchBits = new ParsableBitArray(scratch.data);
  int startPosition = 0;
  while (true) {
    input.peekFully(scratch.data, 0, 10);
    scratch.setPosition(0);
    if (scratch.readUnsignedInt24() != ID3_TAG) {
      break;
    }
    scratch.skipBytes(3);
    int length = scratch.readSynchSafeInt();
    startPosition += 10 + length;
    input.advancePeekPosition(length);
  }
  input.resetPeekPosition();
  input.advancePeekPosition(startPosition);

  // Try to find four or more consecutive AAC audio frames, exceeding the MPEG TS packet size.
  int headerPosition = startPosition;
  int validFramesSize = 0;
  int validFramesCount = 0;
  while (true) {
    input.peekFully(scratch.data, 0, 2);
    scratch.setPosition(0);
    int syncBytes = scratch.readUnsignedShort();
    if ((syncBytes & 0xFFF6) != 0xFFF0) {
      validFramesCount = 0;
      validFramesSize = 0;
      input.resetPeekPosition();
      if (++headerPosition - startPosition >= MAX_SNIFF_BYTES) {
        return false;
      }
      input.advancePeekPosition(headerPosition);
    } else {
      if (++validFramesCount >= 4 && validFramesSize > 188) {
        return true;
      }

      // Skip the frame.
      input.peekFully(scratch.data, 0, 4);
      scratchBits.setPosition(14);
      int frameSize = scratchBits.readBits(13);
      // Either the stream is malformed OR we're not parsing an ADTS stream.
      if (frameSize <= 6) {
        return false;
      }
      input.advancePeekPosition(frameSize - 6);
      validFramesSize += frameSize;
    }
  }
}