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

The following examples show how to use com.google.android.exoplayer2.extractor.ExtractorInput#advancePeekPosition() . 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: FlvExtractor.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
@Override
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
  // Check if file starts with "FLV" tag
  input.peekFully(scratch.data, 0, 3);
  scratch.setPosition(0);
  if (scratch.readUnsignedInt24() != FLV_TAG) {
    return false;
  }

  // Checking reserved flags are set to 0
  input.peekFully(scratch.data, 0, 2);
  scratch.setPosition(0);
  if ((scratch.readUnsignedShort() & 0xFA) != 0) {
    return false;
  }

  // Read data offset
  input.peekFully(scratch.data, 0, 4);
  scratch.setPosition(0);
  int dataOffset = scratch.readInt();

  input.resetPeekPosition();
  input.advancePeekPosition(dataOffset);

  // Checking first "previous tag size" is set to 0
  input.peekFully(scratch.data, 0, 4);
  scratch.setPosition(0);

  return scratch.readInt() == 0;
}
 
Example 2
Source File: FlvExtractor.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
@Override
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
  // Check if file starts with "FLV" tag
  input.peekFully(scratch.data, 0, 3);
  scratch.setPosition(0);
  if (scratch.readUnsignedInt24() != FLV_TAG) {
    return false;
  }

  // Checking reserved flags are set to 0
  input.peekFully(scratch.data, 0, 2);
  scratch.setPosition(0);
  if ((scratch.readUnsignedShort() & 0xFA) != 0) {
    return false;
  }

  // Read data offset
  input.peekFully(scratch.data, 0, 4);
  scratch.setPosition(0);
  int dataOffset = scratch.readInt();

  input.resetPeekPosition();
  input.advancePeekPosition(dataOffset);

  // Checking first "previous tag size" is set to 0
  input.peekFully(scratch.data, 0, 4);
  scratch.setPosition(0);

  return scratch.readInt() == 0;
}
 
Example 3
Source File: Mp3Extractor.java    From Telegram 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 4
Source File: FlvExtractor.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
@Override
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
  // Check if file starts with "FLV" tag
  input.peekFully(scratch.data, 0, 3);
  scratch.setPosition(0);
  if (scratch.readUnsignedInt24() != FLV_TAG) {
    return false;
  }

  // Checking reserved flags are set to 0
  input.peekFully(scratch.data, 0, 2);
  scratch.setPosition(0);
  if ((scratch.readUnsignedShort() & 0xFA) != 0) {
    return false;
  }

  // Read data offset
  input.peekFully(scratch.data, 0, 4);
  scratch.setPosition(0);
  int dataOffset = scratch.readInt();

  input.resetPeekPosition();
  input.advancePeekPosition(dataOffset);

  // Checking first "previous tag size" is set to 0
  input.peekFully(scratch.data, 0, 4);
  scratch.setPosition(0);

  return scratch.readInt() == 0;
}
 
Example 5
Source File: PsExtractor.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
@Override
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
  byte[] scratch = new byte[14];
  input.peekFully(scratch, 0, 14);

  // Verify the PACK_START_CODE for the first 4 bytes
  if (PACK_START_CODE != (((scratch[0] & 0xFF) << 24) | ((scratch[1] & 0xFF) << 16)
      | ((scratch[2] & 0xFF) << 8) | (scratch[3] & 0xFF))) {
    return false;
  }
  // Verify the 01xxx1xx marker on the 5th byte
  if ((scratch[4] & 0xC4) != 0x44) {
    return false;
  }
  // Verify the xxxxx1xx marker on the 7th byte
  if ((scratch[6] & 0x04) != 0x04) {
    return false;
  }
  // Verify the xxxxx1xx marker on the 9th byte
  if ((scratch[8] & 0x04) != 0x04) {
    return false;
  }
  // Verify the xxxxxxx1 marker on the 10th byte
  if ((scratch[9] & 0x01) != 0x01) {
    return false;
  }
  // Verify the xxxxxx11 marker on the 13th byte
  if ((scratch[12] & 0x03) != 0x03) {
    return false;
  }
  // Read the stuffing length from the 14th byte (last 3 bits)
  int packStuffingLength = scratch[13] & 0x07;
  input.advancePeekPosition(packStuffingLength);
  // Now check that the next 3 bytes are the beginning of an MPEG start code
  input.peekFully(scratch, 0, 3);
  return (PACKET_START_CODE_PREFIX == (((scratch[0] & 0xFF) << 16) | ((scratch[1] & 0xFF) << 8)
      | (scratch[2] & 0xFF)));
}
 
Example 6
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 7
Source File: AdtsExtractor.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
@Override
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
  // Skip any ID3 headers.
  int startPosition = peekId3Header(input);

  // Try to find four or more consecutive AAC audio frames, exceeding the MPEG TS packet size.
  int headerPosition = startPosition;
  int totalValidFramesSize = 0;
  int validFramesCount = 0;
  while (true) {
    input.peekFully(scratch.data, 0, 2);
    scratch.setPosition(0);
    int syncBytes = scratch.readUnsignedShort();
    if (!AdtsReader.isAdtsSyncWord(syncBytes)) {
      validFramesCount = 0;
      totalValidFramesSize = 0;
      input.resetPeekPosition();
      if (++headerPosition - startPosition >= MAX_SNIFF_BYTES) {
        return false;
      }
      input.advancePeekPosition(headerPosition);
    } else {
      if (++validFramesCount >= 4 && totalValidFramesSize > TsExtractor.TS_PACKET_SIZE) {
        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);
      totalValidFramesSize += frameSize;
    }
  }
}
 
Example 8
Source File: Mp3Extractor.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
private boolean synchronize(ExtractorInput input, boolean sniffing)
    throws IOException, InterruptedException {
  int validFrameCount = 0;
  int candidateSynchronizedHeaderData = 0;
  int peekedId3Bytes = 0;
  int searchedBytes = 0;
  int searchLimitBytes = sniffing ? MAX_SNIFF_BYTES : MAX_SYNC_BYTES;
  input.resetPeekPosition();
  if (input.getPosition() == 0) {
    // We need to parse enough ID3 metadata to retrieve any gapless playback information even
    // if ID3 metadata parsing is disabled.
    boolean onlyDecodeGaplessInfoFrames = (flags & FLAG_DISABLE_ID3_METADATA) != 0;
    Id3Decoder.FramePredicate id3FramePredicate =
        onlyDecodeGaplessInfoFrames ? GaplessInfoHolder.GAPLESS_INFO_ID3_FRAME_PREDICATE : null;
    metadata = id3Peeker.peekId3Data(input, id3FramePredicate);
    if (metadata != null) {
      gaplessInfoHolder.setFromMetadata(metadata);
    }
    peekedId3Bytes = (int) input.getPeekPosition();
    if (!sniffing) {
      input.skipFully(peekedId3Bytes);
    }
  }
  while (true) {
    if (!input.peekFully(scratch.data, 0, 4, validFrameCount > 0)) {
      // We reached the end of the stream but found at least one valid frame.
      break;
    }
    scratch.setPosition(0);
    int headerData = scratch.readInt();
    int frameSize;
    if ((candidateSynchronizedHeaderData != 0
        && !headersMatch(headerData, candidateSynchronizedHeaderData))
        || (frameSize = MpegAudioHeader.getFrameSize(headerData)) == C.LENGTH_UNSET) {
      // The header doesn't match the candidate header or is invalid. Try the next byte offset.
      if (searchedBytes++ == searchLimitBytes) {
        if (!sniffing) {
          throw new ParserException("Searched too many bytes.");
        }
        return false;
      }
      validFrameCount = 0;
      candidateSynchronizedHeaderData = 0;
      if (sniffing) {
        input.resetPeekPosition();
        input.advancePeekPosition(peekedId3Bytes + searchedBytes);
      } else {
        input.skipFully(1);
      }
    } else {
      // The header matches the candidate header and/or is valid.
      validFrameCount++;
      if (validFrameCount == 1) {
        MpegAudioHeader.populateHeader(headerData, synchronizedHeader);
        candidateSynchronizedHeaderData = headerData;
      } else if (validFrameCount == 4) {
        break;
      }
      input.advancePeekPosition(frameSize - 4);
    }
  }
  // Prepare to read the synchronized frame.
  if (sniffing) {
    input.skipFully(peekedId3Bytes + searchedBytes);
  } else {
    input.resetPeekPosition();
  }
  synchronizedHeaderData = candidateSynchronizedHeaderData;
  return true;
}
 
Example 9
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 10
Source File: Sniffer.java    From TelePlus-Android 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.readUnsignedLongToLong();
    } else if (atomSize == Atom.EXTENDS_TO_END_SIZE) {
      // The atom extends to the end of the file.
      long endPosition = input.getLength();
      if (endPosition != C.LENGTH_UNSET) {
        atomSize = endPosition - input.getPosition() + 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) {
      // 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: WavHeaderReader.java    From TelePlus-Android 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 != Util.getIntegerCodeForString("RIFF")) {
    return null;
  }

  input.peekFully(scratch.data, 0, 4);
  scratch.setPosition(0);
  int riffFormat = scratch.readInt();
  if (riffFormat != Util.getIntegerCodeForString("WAVE")) {
    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 != Util.getIntegerCodeForString("fmt ")) {
    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;
  switch (type) {
    case TYPE_PCM:
    case TYPE_WAVE_FORMAT_EXTENSIBLE:
      encoding = Util.getPcmEncoding(bitsPerSample);
      break;
    case TYPE_FLOAT:
      encoding = bitsPerSample == 32 ? C.ENCODING_PCM_FLOAT : C.ENCODING_INVALID;
      break;
    case TYPE_A_LAW:
      encoding = C.ENCODING_PCM_A_LAW;
      break;
    case TYPE_MU_LAW:
      encoding = C.ENCODING_PCM_MU_LAW;
      break;
    default:
      Log.e(TAG, "Unsupported WAV format type: " + type);
      return null;
  }

  if (encoding == C.ENCODING_INVALID) {
    Log.e(TAG, "Unsupported WAV bit depth " + bitsPerSample + " for 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 12
Source File: Ac4Extractor.java    From Telegram 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, /* offset= */ 0, /* length= */ 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, /* offset= */ 0, /* length= */ FRAME_HEADER_SIZE);
    scratch.setPosition(0);
    int syncBytes = scratch.readUnsignedShort();
    if (syncBytes != AC40_SYNCWORD && syncBytes != AC41_SYNCWORD) {
      validFramesCount = 0;
      input.resetPeekPosition();
      if (++headerPosition - startPosition >= MAX_SNIFF_BYTES) {
        return false;
      }
      input.advancePeekPosition(headerPosition);
    } else {
      if (++validFramesCount >= 4) {
        return true;
      }
      int frameSize = Ac4Util.parseAc4SyncframeSize(scratch.data, syncBytes);
      if (frameSize == C.LENGTH_UNSET) {
        return false;
      }
      input.advancePeekPosition(frameSize - FRAME_HEADER_SIZE);
    }
  }
}
 
Example 13
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 14
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 15
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 16
Source File: AdtsExtractor.java    From Telegram-FOSS with GNU General Public License v2.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;
  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;
      }
    }
  }
  input.resetPeekPosition();
  if (numValidFrames > 0) {
    averageFrameSize = (int) (totalValidFramesSize / numValidFrames);
  } else {
    averageFrameSize = C.LENGTH_UNSET;
  }
  hasCalculatedAverageFrameSize = true;
}
 
Example 17
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 18
Source File: AdtsExtractor.java    From TelePlus-Android 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);
  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;
    }
  }
}
 
Example 19
Source File: AdtsExtractor.java    From Telegram with GNU General Public License v2.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;
  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;
      }
    }
  }
  input.resetPeekPosition();
  if (numValidFrames > 0) {
    averageFrameSize = (int) (totalValidFramesSize / numValidFrames);
  } else {
    averageFrameSize = C.LENGTH_UNSET;
  }
  hasCalculatedAverageFrameSize = true;
}
 
Example 20
Source File: Ac3Extractor.java    From Telegram 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);
    }
  }
}