Java Code Examples for com.google.android.exoplayer2.util.ParsableByteArray#readUnsignedInt24()

The following examples show how to use com.google.android.exoplayer2.util.ParsableByteArray#readUnsignedInt24() . 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: FlacReader.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
/**
 * Parses a FLAC file seek table metadata structure and initializes internal fields.
 *
 * @param data A {@link ParsableByteArray} including whole seek table metadata block. Its
 *     position should be set to the beginning of the block.
 * @see <a href="https://xiph.org/flac/format.html#metadata_block_seektable">FLAC format
 *     METADATA_BLOCK_SEEKTABLE</a>
 */
public void parseSeekTable(ParsableByteArray data) {
  data.skipBytes(METADATA_LENGTH_OFFSET);
  int length = data.readUnsignedInt24();
  int numberOfSeekPoints = length / SEEK_POINT_SIZE;
  seekPointGranules = new long[numberOfSeekPoints];
  seekPointOffsets = new long[numberOfSeekPoints];
  for (int i = 0; i < numberOfSeekPoints; i++) {
    seekPointGranules[i] = data.readLong();
    seekPointOffsets[i] = data.readLong();
    data.skipBytes(2); // Skip "Number of samples in the target frame."
  }
}
 
Example 2
Source File: PgsDecoder.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
private void parseBitmapSection(ParsableByteArray buffer, int sectionLength) {
  if (sectionLength < 4) {
    return;
  }
  buffer.skipBytes(3); // Id (2 bytes), version (1 byte).
  boolean isBaseSection = (0x80 & buffer.readUnsignedByte()) != 0;
  sectionLength -= 4;

  if (isBaseSection) {
    if (sectionLength < 7) {
      return;
    }
    int totalLength = buffer.readUnsignedInt24();
    if (totalLength < 4) {
      return;
    }
    bitmapWidth = buffer.readUnsignedShort();
    bitmapHeight = buffer.readUnsignedShort();
    bitmapData.reset(totalLength - 4);
    sectionLength -= 7;
  }

  int position = bitmapData.getPosition();
  int limit = bitmapData.limit();
  if (position < limit && sectionLength > 0) {
    int bytesToRead = Math.min(sectionLength, limit - position);
    buffer.readBytes(bitmapData.data, position, bytesToRead);
    bitmapData.setPosition(position + bytesToRead);
  }
}
 
Example 3
Source File: PgsDecoder.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
private void parseBitmapSection(ParsableByteArray buffer, int sectionLength) {
  if (sectionLength < 4) {
    return;
  }
  buffer.skipBytes(3); // Id (2 bytes), version (1 byte).
  boolean isBaseSection = (0x80 & buffer.readUnsignedByte()) != 0;
  sectionLength -= 4;

  if (isBaseSection) {
    if (sectionLength < 7) {
      return;
    }
    int totalLength = buffer.readUnsignedInt24();
    if (totalLength < 4) {
      return;
    }
    bitmapWidth = buffer.readUnsignedShort();
    bitmapHeight = buffer.readUnsignedShort();
    bitmapData.reset(totalLength - 4);
    sectionLength -= 7;
  }

  int position = bitmapData.getPosition();
  int limit = bitmapData.limit();
  if (position < limit && sectionLength > 0) {
    int bytesToRead = Math.min(sectionLength, limit - position);
    buffer.readBytes(bitmapData.data, position, bytesToRead);
    bitmapData.setPosition(position + bytesToRead);
  }
}
 
Example 4
Source File: PgsDecoder.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
private void parseBitmapSection(ParsableByteArray buffer, int sectionLength) {
  if (sectionLength < 4) {
    return;
  }
  buffer.skipBytes(3); // Id (2 bytes), version (1 byte).
  boolean isBaseSection = (0x80 & buffer.readUnsignedByte()) != 0;
  sectionLength -= 4;

  if (isBaseSection) {
    if (sectionLength < 7) {
      return;
    }
    int totalLength = buffer.readUnsignedInt24();
    if (totalLength < 4) {
      return;
    }
    bitmapWidth = buffer.readUnsignedShort();
    bitmapHeight = buffer.readUnsignedShort();
    bitmapData.reset(totalLength - 4);
    sectionLength -= 7;
  }

  int position = bitmapData.getPosition();
  int limit = bitmapData.limit();
  if (position < limit && sectionLength > 0) {
    int bytesToRead = Math.min(sectionLength, limit - position);
    buffer.readBytes(bitmapData.data, position, bytesToRead);
    bitmapData.setPosition(position + bytesToRead);
  }
}
 
Example 5
Source File: Id3Decoder.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
private static MlltFrame decodeMlltFrame(ParsableByteArray id3Data, int frameSize) {
  // See ID3v2.4.0 native frames subsection 4.6.
  int mpegFramesBetweenReference = id3Data.readUnsignedShort();
  int bytesBetweenReference = id3Data.readUnsignedInt24();
  int millisecondsBetweenReference = id3Data.readUnsignedInt24();
  int bitsForBytesDeviation = id3Data.readUnsignedByte();
  int bitsForMillisecondsDeviation = id3Data.readUnsignedByte();

  ParsableBitArray references = new ParsableBitArray();
  references.reset(id3Data);
  int referencesBits = 8 * (frameSize - 10);
  int bitsPerReference = bitsForBytesDeviation + bitsForMillisecondsDeviation;
  int referencesCount = referencesBits / bitsPerReference;
  int[] bytesDeviations = new int[referencesCount];
  int[] millisecondsDeviations = new int[referencesCount];
  for (int i = 0; i < referencesCount; i++) {
    int bytesDeviation = references.readBits(bitsForBytesDeviation);
    int millisecondsDeviation = references.readBits(bitsForMillisecondsDeviation);
    bytesDeviations[i] = bytesDeviation;
    millisecondsDeviations[i] = millisecondsDeviation;
  }

  return new MlltFrame(
      mpegFramesBetweenReference,
      bytesBetweenReference,
      millisecondsBetweenReference,
      bytesDeviations,
      millisecondsDeviations);
}
 
Example 6
Source File: FlacReader.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Parses a FLAC file seek table metadata structure and initializes internal fields.
 *
 * @param data A {@link ParsableByteArray} including whole seek table metadata block. Its
 *     position should be set to the beginning of the block.
 * @see <a href="https://xiph.org/flac/format.html#metadata_block_seektable">FLAC format
 *     METADATA_BLOCK_SEEKTABLE</a>
 */
public void parseSeekTable(ParsableByteArray data) {
  data.skipBytes(METADATA_LENGTH_OFFSET);
  int length = data.readUnsignedInt24();
  int numberOfSeekPoints = length / SEEK_POINT_SIZE;
  seekPointGranules = new long[numberOfSeekPoints];
  seekPointOffsets = new long[numberOfSeekPoints];
  for (int i = 0; i < numberOfSeekPoints; i++) {
    seekPointGranules[i] = data.readLong();
    seekPointOffsets[i] = data.readLong();
    data.skipBytes(2); // Skip "Number of samples in the target frame."
  }
}
 
Example 7
Source File: Id3Decoder.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
private static MlltFrame decodeMlltFrame(ParsableByteArray id3Data, int frameSize) {
  // See ID3v2.4.0 native frames subsection 4.6.
  int mpegFramesBetweenReference = id3Data.readUnsignedShort();
  int bytesBetweenReference = id3Data.readUnsignedInt24();
  int millisecondsBetweenReference = id3Data.readUnsignedInt24();
  int bitsForBytesDeviation = id3Data.readUnsignedByte();
  int bitsForMillisecondsDeviation = id3Data.readUnsignedByte();

  ParsableBitArray references = new ParsableBitArray();
  references.reset(id3Data);
  int referencesBits = 8 * (frameSize - 10);
  int bitsPerReference = bitsForBytesDeviation + bitsForMillisecondsDeviation;
  int referencesCount = referencesBits / bitsPerReference;
  int[] bytesDeviations = new int[referencesCount];
  int[] millisecondsDeviations = new int[referencesCount];
  for (int i = 0; i < referencesCount; i++) {
    int bytesDeviation = references.readBits(bitsForBytesDeviation);
    int millisecondsDeviation = references.readBits(bitsForMillisecondsDeviation);
    bytesDeviations[i] = bytesDeviation;
    millisecondsDeviations[i] = millisecondsDeviation;
  }

  return new MlltFrame(
      mpegFramesBetweenReference,
      bytesBetweenReference,
      millisecondsBetweenReference,
      bytesDeviations,
      millisecondsDeviations);
}
 
Example 8
Source File: FlacReader.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Parses a FLAC file seek table metadata structure and initializes internal fields.
 *
 * @param data A {@link ParsableByteArray} including whole seek table metadata block. Its
 *     position should be set to the beginning of the block.
 * @see <a href="https://xiph.org/flac/format.html#metadata_block_seektable">FLAC format
 *     METADATA_BLOCK_SEEKTABLE</a>
 */
public void parseSeekTable(ParsableByteArray data) {
  data.skipBytes(METADATA_LENGTH_OFFSET);
  int length = data.readUnsignedInt24();
  int numberOfSeekPoints = length / SEEK_POINT_SIZE;
  seekPointGranules = new long[numberOfSeekPoints];
  seekPointOffsets = new long[numberOfSeekPoints];
  for (int i = 0; i < numberOfSeekPoints; i++) {
    seekPointGranules[i] = data.readLong();
    seekPointOffsets[i] = data.readLong();
    data.skipBytes(2); // Skip "Number of samples in the target frame."
  }
}
 
Example 9
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 10
Source File: VideoTagPayloadReader.java    From LiveVideoBroadcaster with Apache License 2.0 4 votes vote down vote up
@Override
protected void parsePayload(ParsableByteArray data, long timeUs) throws ParserException {
  int packetType = data.readUnsignedByte();
  int compositionTimeMs = data.readUnsignedInt24();
  timeUs += compositionTimeMs * 1000L;
  // Parse avc sequence header in case this was not done before.
  if (packetType == AVC_PACKET_TYPE_SEQUENCE_HEADER && !hasOutputFormat) {
    ParsableByteArray videoSequence = new ParsableByteArray(new byte[data.bytesLeft()]);
    data.readBytes(videoSequence.data, 0, data.bytesLeft());
    AvcConfig avcConfig = AvcConfig.parse(videoSequence);
    nalUnitLengthFieldLength = avcConfig.nalUnitLengthFieldLength;
    // Construct and output the format.
    Format format = Format.createVideoSampleFormat(null, MimeTypes.VIDEO_H264, null,
        Format.NO_VALUE, Format.NO_VALUE, avcConfig.width, avcConfig.height, Format.NO_VALUE,
        avcConfig.initializationData, Format.NO_VALUE, avcConfig.pixelWidthAspectRatio, null);
    output.format(format);
    hasOutputFormat = true;
  } else if (packetType == AVC_PACKET_TYPE_AVC_NALU) {
    // TODO: Deduplicate with Mp4Extractor.
    // Zero the top three bytes of the array that we'll use to decode nal unit lengths, in case
    // they're only 1 or 2 bytes long.
    byte[] nalLengthData = nalLength.data;
    nalLengthData[0] = 0;
    nalLengthData[1] = 0;
    nalLengthData[2] = 0;
    int nalUnitLengthFieldLengthDiff = 4 - nalUnitLengthFieldLength;
    // NAL units are length delimited, but the decoder requires start code delimited units.
    // Loop until we've written the sample to the track output, replacing length delimiters with
    // start codes as we encounter them.
    int bytesWritten = 0;
    int bytesToWrite;
    while (data.bytesLeft() > 0) {
      // Read the NAL length so that we know where we find the next one.
      data.readBytes(nalLength.data, nalUnitLengthFieldLengthDiff, nalUnitLengthFieldLength);
      nalLength.setPosition(0);
      bytesToWrite = nalLength.readUnsignedIntToInt();

      // Write a start code for the current NAL unit.
      nalStartCode.setPosition(0);
      output.sampleData(nalStartCode, 4);
      bytesWritten += 4;

      // Write the payload of the NAL unit.
      output.sampleData(data, bytesToWrite);
      bytesWritten += bytesToWrite;
    }
    output.sampleMetadata(timeUs, frameType == VIDEO_FRAME_KEYFRAME ? C.BUFFER_FLAG_KEY_FRAME : 0,
        bytesWritten, 0, null);
  }
}
 
Example 11
Source File: VbriSeeker.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Returns a {@link VbriSeeker} for seeking in the stream, if required information is present.
 * Returns {@code null} if not. On returning, {@code frame}'s position is not specified so the
 * caller should reset it.
 *
 * @param inputLength The length of the stream in bytes, or {@link C#LENGTH_UNSET} if unknown.
 * @param position The position of the start of this frame in the stream.
 * @param mpegAudioHeader The MPEG audio header associated with the frame.
 * @param frame The data in this audio frame, with its position set to immediately after the
 *     'VBRI' tag.
 * @return A {@link VbriSeeker} for seeking in the stream, or {@code null} if the required
 *     information is not present.
 */
public static VbriSeeker create(long inputLength, long position, MpegAudioHeader mpegAudioHeader,
    ParsableByteArray frame) {
  frame.skipBytes(10);
  int numFrames = frame.readInt();
  if (numFrames <= 0) {
    return null;
  }
  int sampleRate = mpegAudioHeader.sampleRate;
  long durationUs = Util.scaleLargeTimestamp(numFrames,
      C.MICROS_PER_SECOND * (sampleRate >= 32000 ? 1152 : 576), sampleRate);
  int entryCount = frame.readUnsignedShort();
  int scale = frame.readUnsignedShort();
  int entrySize = frame.readUnsignedShort();
  frame.skipBytes(2);

  long minPosition = position + mpegAudioHeader.frameSize;
  // Read table of contents entries.
  long[] timesUs = new long[entryCount];
  long[] positions = new long[entryCount];
  for (int index = 0; index < entryCount; index++) {
    timesUs[index] = (index * durationUs) / entryCount;
    // Ensure positions do not fall within the frame containing the VBRI header. This constraint
    // will normally only apply to the first entry in the table.
    positions[index] = Math.max(position, minPosition);
    int segmentSize;
    switch (entrySize) {
      case 1:
        segmentSize = frame.readUnsignedByte();
        break;
      case 2:
        segmentSize = frame.readUnsignedShort();
        break;
      case 3:
        segmentSize = frame.readUnsignedInt24();
        break;
      case 4:
        segmentSize = frame.readUnsignedIntToInt();
        break;
      default:
        return null;
    }
    position += segmentSize * scale;
  }
  if (inputLength != C.LENGTH_UNSET && inputLength != position) {
    Log.w(TAG, "VBRI data size mismatch: " + inputLength + ", " + position);
  }
  return new VbriSeeker(timesUs, positions, durationUs);
}
 
Example 12
Source File: Ac3Extractor.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);
  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);

  int headerPosition = startPosition;
  int validFramesCount = 0;
  while (true) {
    input.peekFully(scratch.data, 0, 5);
    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 - 5);
    }
  }
}
 
Example 13
Source File: VideoTagPayloadReader.java    From K-Sonic with MIT License 4 votes vote down vote up
@Override
protected void parsePayload(ParsableByteArray data, long timeUs) throws ParserException {
  int packetType = data.readUnsignedByte();
  int compositionTimeMs = data.readUnsignedInt24();
  timeUs += compositionTimeMs * 1000L;
  // Parse avc sequence header in case this was not done before.
  if (packetType == AVC_PACKET_TYPE_SEQUENCE_HEADER && !hasOutputFormat) {
    ParsableByteArray videoSequence = new ParsableByteArray(new byte[data.bytesLeft()]);
    data.readBytes(videoSequence.data, 0, data.bytesLeft());
    AvcConfig avcConfig = AvcConfig.parse(videoSequence);
    nalUnitLengthFieldLength = avcConfig.nalUnitLengthFieldLength;
    // Construct and output the format.
    Format format = Format.createVideoSampleFormat(null, MimeTypes.VIDEO_H264, null,
        Format.NO_VALUE, Format.NO_VALUE, avcConfig.width, avcConfig.height, Format.NO_VALUE,
        avcConfig.initializationData, Format.NO_VALUE, avcConfig.pixelWidthAspectRatio, null);
    output.format(format);
    hasOutputFormat = true;
  } else if (packetType == AVC_PACKET_TYPE_AVC_NALU) {
    // TODO: Deduplicate with Mp4Extractor.
    // Zero the top three bytes of the array that we'll use to decode nal unit lengths, in case
    // they're only 1 or 2 bytes long.
    byte[] nalLengthData = nalLength.data;
    nalLengthData[0] = 0;
    nalLengthData[1] = 0;
    nalLengthData[2] = 0;
    int nalUnitLengthFieldLengthDiff = 4 - nalUnitLengthFieldLength;
    // NAL units are length delimited, but the decoder requires start code delimited units.
    // Loop until we've written the sample to the track output, replacing length delimiters with
    // start codes as we encounter them.
    int bytesWritten = 0;
    int bytesToWrite;
    while (data.bytesLeft() > 0) {
      // Read the NAL length so that we know where we find the next one.
      data.readBytes(nalLength.data, nalUnitLengthFieldLengthDiff, nalUnitLengthFieldLength);
      nalLength.setPosition(0);
      bytesToWrite = nalLength.readUnsignedIntToInt();

      // Write a start code for the current NAL unit.
      nalStartCode.setPosition(0);
      output.sampleData(nalStartCode, 4);
      bytesWritten += 4;

      // Write the payload of the NAL unit.
      output.sampleData(data, bytesToWrite);
      bytesWritten += bytesToWrite;
    }
    output.sampleMetadata(timeUs, frameType == VIDEO_FRAME_KEYFRAME ? C.BUFFER_FLAG_KEY_FRAME : 0,
        bytesWritten, 0, null);
  }
}
 
Example 14
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);
    }
  }
}
 
Example 15
Source File: Ac3Extractor.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
@Override
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
  // Skip any ID3 headers.
  ParsableByteArray scratch = new ParsableByteArray(ID3_HEADER_LENGTH);
  int startPosition = 0;
  while (true) {
    input.peekFully(scratch.data, /* offset= */ 0, ID3_HEADER_LENGTH);
    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: Ac3Extractor.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);
  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);

  int headerPosition = startPosition;
  int validFramesCount = 0;
  while (true) {
    input.peekFully(scratch.data, 0, 5);
    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 - 5);
    }
  }
}
 
Example 17
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 18
Source File: Id3Decoder.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
private static boolean validateFrames(ParsableByteArray id3Data, int majorVersion,
    int frameHeaderSize, boolean unsignedIntFrameSizeHack) {
  int startPosition = id3Data.getPosition();
  try {
    while (id3Data.bytesLeft() >= frameHeaderSize) {
      // Read the next frame header.
      int id;
      long frameSize;
      int flags;
      if (majorVersion >= 3) {
        id = id3Data.readInt();
        frameSize = id3Data.readUnsignedInt();
        flags = id3Data.readUnsignedShort();
      } else {
        id = id3Data.readUnsignedInt24();
        frameSize = id3Data.readUnsignedInt24();
        flags = 0;
      }
      // Validate the frame header and skip to the next one.
      if (id == 0 && frameSize == 0 && flags == 0) {
        // We've reached zero padding after the end of the final frame.
        return true;
      } else {
        if (majorVersion == 4 && !unsignedIntFrameSizeHack) {
          // Parse the data size as a synchsafe integer, as per the spec.
          if ((frameSize & 0x808080L) != 0) {
            return false;
          }
          frameSize = (frameSize & 0xFF) | (((frameSize >> 8) & 0xFF) << 7)
              | (((frameSize >> 16) & 0xFF) << 14) | (((frameSize >> 24) & 0xFF) << 21);
        }
        boolean hasGroupIdentifier = false;
        boolean hasDataLength = false;
        if (majorVersion == 4) {
          hasGroupIdentifier = (flags & FRAME_FLAG_V4_HAS_GROUP_IDENTIFIER) != 0;
          hasDataLength = (flags & FRAME_FLAG_V4_HAS_DATA_LENGTH) != 0;
        } else if (majorVersion == 3) {
          hasGroupIdentifier = (flags & FRAME_FLAG_V3_HAS_GROUP_IDENTIFIER) != 0;
          // A V3 frame has data length if and only if it's compressed.
          hasDataLength = (flags & FRAME_FLAG_V3_IS_COMPRESSED) != 0;
        }
        int minimumFrameSize = 0;
        if (hasGroupIdentifier) {
          minimumFrameSize++;
        }
        if (hasDataLength) {
          minimumFrameSize += 4;
        }
        if (frameSize < minimumFrameSize) {
          return false;
        }
        if (id3Data.bytesLeft() < frameSize) {
          return false;
        }
        id3Data.skipBytes((int) frameSize); // flags
      }
    }
    return true;
  } finally {
    id3Data.setPosition(startPosition);
  }
}
 
Example 19
Source File: VbriSeeker.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
/**
 * Returns a {@link VbriSeeker} for seeking in the stream, if required information is present.
 * Returns {@code null} if not. On returning, {@code frame}'s position is not specified so the
 * caller should reset it.
 *
 * @param inputLength The length of the stream in bytes, or {@link C#LENGTH_UNSET} if unknown.
 * @param position The position of the start of this frame in the stream.
 * @param mpegAudioHeader The MPEG audio header associated with the frame.
 * @param frame The data in this audio frame, with its position set to immediately after the
 *     'VBRI' tag.
 * @return A {@link VbriSeeker} for seeking in the stream, or {@code null} if the required
 *     information is not present.
 */
public static @Nullable VbriSeeker create(
    long inputLength, long position, MpegAudioHeader mpegAudioHeader, ParsableByteArray frame) {
  frame.skipBytes(10);
  int numFrames = frame.readInt();
  if (numFrames <= 0) {
    return null;
  }
  int sampleRate = mpegAudioHeader.sampleRate;
  long durationUs = Util.scaleLargeTimestamp(numFrames,
      C.MICROS_PER_SECOND * (sampleRate >= 32000 ? 1152 : 576), sampleRate);
  int entryCount = frame.readUnsignedShort();
  int scale = frame.readUnsignedShort();
  int entrySize = frame.readUnsignedShort();
  frame.skipBytes(2);

  long minPosition = position + mpegAudioHeader.frameSize;
  // Read table of contents entries.
  long[] timesUs = new long[entryCount];
  long[] positions = new long[entryCount];
  for (int index = 0; index < entryCount; index++) {
    timesUs[index] = (index * durationUs) / entryCount;
    // Ensure positions do not fall within the frame containing the VBRI header. This constraint
    // will normally only apply to the first entry in the table.
    positions[index] = Math.max(position, minPosition);
    int segmentSize;
    switch (entrySize) {
      case 1:
        segmentSize = frame.readUnsignedByte();
        break;
      case 2:
        segmentSize = frame.readUnsignedShort();
        break;
      case 3:
        segmentSize = frame.readUnsignedInt24();
        break;
      case 4:
        segmentSize = frame.readUnsignedIntToInt();
        break;
      default:
        return null;
    }
    position += segmentSize * scale;
  }
  if (inputLength != C.LENGTH_UNSET && inputLength != position) {
    Log.w(TAG, "VBRI data size mismatch: " + inputLength + ", " + position);
  }
  return new VbriSeeker(timesUs, positions, durationUs, /* dataEndPosition= */ position);
}
 
Example 20
Source File: Ac4Extractor.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
@Override
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
  // Skip any ID3 headers.
  ParsableByteArray scratch = new ParsableByteArray(ID3_HEADER_LENGTH);
  int startPosition = 0;
  while (true) {
    input.peekFully(scratch.data, /* offset= */ 0, ID3_HEADER_LENGTH);
    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);
    }
  }
}