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

The following examples show how to use com.google.android.exoplayer2.util.ParsableByteArray#setPosition() . 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: AtomParsers.java    From K-Sonic with MIT License 6 votes vote down vote up
/**
 * Parses encryption data from an audio/video sample entry, populating {@code out} and returning
 * the unencrypted atom type, or 0 if no common encryption sinf atom was present.
 */
private static int parseSampleEntryEncryptionData(ParsableByteArray parent, int position,
    int size, StsdData out, int entryIndex) {
  int childPosition = parent.getPosition();
  while (childPosition - position < size) {
    parent.setPosition(childPosition);
    int childAtomSize = parent.readInt();
    Assertions.checkArgument(childAtomSize > 0, "childAtomSize should be positive");
    int childAtomType = parent.readInt();
    if (childAtomType == Atom.TYPE_sinf) {
      Pair<Integer, TrackEncryptionBox> result = parseSinfFromParent(parent, childPosition,
          childAtomSize);
      if (result != null) {
        out.trackEncryptionBoxes[entryIndex] = result.second;
        return result.first;
      }
    }
    childPosition += childAtomSize;
  }
  // This enca/encv box does not have a data format so return an invalid atom type.
  return 0;
}
 
Example 2
Source File: AtomParsers.java    From TelePlus-Android with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Parses a udta atom.
 *
 * @param udtaAtom The udta (user data) atom to decode.
 * @param isQuickTime True for QuickTime media. False otherwise.
 * @return Parsed metadata, or null.
 */
public static Metadata parseUdta(Atom.LeafAtom udtaAtom, boolean isQuickTime) {
  if (isQuickTime) {
    // Meta boxes are regular boxes rather than full boxes in QuickTime. For now, don't try and
    // decode one.
    return null;
  }
  ParsableByteArray udtaData = udtaAtom.data;
  udtaData.setPosition(Atom.HEADER_SIZE);
  while (udtaData.bytesLeft() >= Atom.HEADER_SIZE) {
    int atomPosition = udtaData.getPosition();
    int atomSize = udtaData.readInt();
    int atomType = udtaData.readInt();
    if (atomType == Atom.TYPE_meta) {
      udtaData.setPosition(atomPosition);
      return parseMetaAtom(udtaData, atomPosition + atomSize);
    }
    udtaData.skipBytes(atomSize - Atom.HEADER_SIZE);
  }
  return null;
}
 
Example 3
Source File: AtomParsers.java    From Telegram-FOSS with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Parses a udta atom.
 *
 * @param udtaAtom The udta (user data) atom to decode.
 * @param isQuickTime True for QuickTime media. False otherwise.
 * @return Parsed metadata, or null.
 */
@Nullable
public static Metadata parseUdta(Atom.LeafAtom udtaAtom, boolean isQuickTime) {
  if (isQuickTime) {
    // Meta boxes are regular boxes rather than full boxes in QuickTime. For now, don't try and
    // decode one.
    return null;
  }
  ParsableByteArray udtaData = udtaAtom.data;
  udtaData.setPosition(Atom.HEADER_SIZE);
  while (udtaData.bytesLeft() >= Atom.HEADER_SIZE) {
    int atomPosition = udtaData.getPosition();
    int atomSize = udtaData.readInt();
    int atomType = udtaData.readInt();
    if (atomType == Atom.TYPE_meta) {
      udtaData.setPosition(atomPosition);
      return parseUdtaMeta(udtaData, atomPosition + atomSize);
    }
    udtaData.setPosition(atomPosition + atomSize);
  }
  return null;
}
 
Example 4
Source File: MetadataUtil.java    From MediaSDK with Apache License 2.0 6 votes vote down vote up
/**
 * Parses an 'mdta' metadata entry starting at the current position in an ilst box.
 *
 * @param ilst The ilst box.
 * @param endPosition The end position of the entry in the ilst box.
 * @param key The mdta metadata entry key for the entry.
 * @return The parsed element, or null if the entry wasn't recognized.
 */
@Nullable
public static MdtaMetadataEntry parseMdtaMetadataEntryFromIlst(
    ParsableByteArray ilst, int endPosition, String key) {
  int atomPosition;
  while ((atomPosition = ilst.getPosition()) < endPosition) {
    int atomSize = ilst.readInt();
    int atomType = ilst.readInt();
    if (atomType == Atom.TYPE_data) {
      int typeIndicator = ilst.readInt();
      int localeIndicator = ilst.readInt();
      int dataSize = atomSize - 16;
      byte[] value = new byte[dataSize];
      ilst.readBytes(value, 0, dataSize);
      return new MdtaMetadataEntry(key, value, localeIndicator, typeIndicator);
    }
    ilst.setPosition(atomPosition + atomSize);
  }
  return null;
}
 
Example 5
Source File: AtomParsers.java    From Telegram-FOSS with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Parses the edts atom (defined in 14496-12 subsection 8.6.5).
 *
 * @param edtsAtom edts (edit box) atom to decode.
 * @return Pair of edit list durations and edit list media times, or a pair of nulls if they are
 *     not present.
 */
private static Pair<long[], long[]> parseEdts(Atom.ContainerAtom edtsAtom) {
  Atom.LeafAtom elst;
  if (edtsAtom == null || (elst = edtsAtom.getLeafAtomOfType(Atom.TYPE_elst)) == null) {
    return Pair.create(null, null);
  }
  ParsableByteArray elstData = elst.data;
  elstData.setPosition(Atom.HEADER_SIZE);
  int fullAtom = elstData.readInt();
  int version = Atom.parseFullAtomVersion(fullAtom);
  int entryCount = elstData.readUnsignedIntToInt();
  long[] editListDurations = new long[entryCount];
  long[] editListMediaTimes = new long[entryCount];
  for (int i = 0; i < entryCount; i++) {
    editListDurations[i] =
        version == 1 ? elstData.readUnsignedLongToLong() : elstData.readUnsignedInt();
    editListMediaTimes[i] = version == 1 ? elstData.readLong() : elstData.readInt();
    int mediaRateInteger = elstData.readShort();
    if (mediaRateInteger != 1) {
      // The extractor does not handle dwell edits (mediaRateInteger == 0).
      throw new IllegalArgumentException("Unsupported media rate.");
    }
    elstData.skipBytes(2);
  }
  return Pair.create(editListDurations, editListMediaTimes);
}
 
Example 6
Source File: CssParser.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Returns a string containing the selector. The input is expected to have the form
 * {@code ::cue(tag#id.class1.class2[voice="someone"]}, where every element is optional.
 *
 * @param input From which the selector is obtained.
 * @return A string containing the target, empty string if the selector is universal
 *     (targets all cues) or null if an error was encountered.
 */
private static String parseSelector(ParsableByteArray input, StringBuilder stringBuilder) {
  skipWhitespaceAndComments(input);
  if (input.bytesLeft() < 5) {
    return null;
  }
  String cueSelector = input.readString(5);
  if (!"::cue".equals(cueSelector)) {
    return null;
  }
  int position = input.getPosition();
  String token = parseNextToken(input, stringBuilder);
  if (token == null) {
    return null;
  }
  if (BLOCK_START.equals(token)) {
    input.setPosition(position);
    return "";
  }
  String target = null;
  if ("(".equals(token)) {
    target = readCueTarget(input);
  }
  token = parseNextToken(input, stringBuilder);
  if (!")".equals(token) || token == null) {
    return null;
  }
  return target;
}
 
Example 7
Source File: FlacReader.java    From K-Sonic with MIT License 5 votes vote down vote up
private int getFlacFrameBlockSize(ParsableByteArray packet) {
  int blockSizeCode = (packet.data[2] & 0xFF) >> 4;
  switch (blockSizeCode) {
    case 1:
      return 192;
    case 2:
    case 3:
    case 4:
    case 5:
      return 576 << (blockSizeCode - 2);
    case 6:
    case 7:
      // skip the sample number
      packet.skipBytes(FRAME_HEADER_SAMPLE_NUMBER_OFFSET);
      packet.readUtf8EncodedLong();
      int value = blockSizeCode == 6 ? packet.readUnsignedByte() : packet.readUnsignedShort();
      packet.setPosition(0);
      return value + 1;
    case 8:
    case 9:
    case 10:
    case 11:
    case 12:
    case 13:
    case 14:
    case 15:
      return 256 << (blockSizeCode - 8);
  }
  return -1;
}
 
Example 8
Source File: ProjectionDecoder.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
/** Returns true if the input contains a proj box. Indicates MP4 container. */
private static boolean isProj(ParsableByteArray input) {
  input.skipBytes(4); // size
  int type = input.readInt();
  input.setPosition(0);
  return type == TYPE_PROJ;
}
 
Example 9
Source File: FragmentedMp4Extractor.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Parses an mehd atom (defined in 14496-12).
 */
private static long parseMehd(ParsableByteArray mehd) {
  mehd.setPosition(Atom.HEADER_SIZE);
  int fullAtom = mehd.readInt();
  int version = Atom.parseFullAtomVersion(fullAtom);
  return version == 0 ? mehd.readUnsignedInt() : mehd.readUnsignedLongToLong();
}
 
Example 10
Source File: AtomParsers.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
@Nullable
private static Metadata parseUdtaMeta(ParsableByteArray meta, int limit) {
  meta.skipBytes(Atom.FULL_HEADER_SIZE);
  while (meta.getPosition() < limit) {
    int atomPosition = meta.getPosition();
    int atomSize = meta.readInt();
    int atomType = meta.readInt();
    if (atomType == Atom.TYPE_ilst) {
      meta.setPosition(atomPosition);
      return parseIlst(meta, atomPosition + atomSize);
    }
    meta.setPosition(atomPosition + atomSize);
  }
  return null;
}
 
Example 11
Source File: ProjectionDecoder.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
/** Returns true if the input contains a proj box. Indicates MP4 container. */
private static boolean isProj(ParsableByteArray input) {
  input.skipBytes(4); // size
  int type = input.readInt();
  input.setPosition(0);
  return type == TYPE_PROJ;
}
 
Example 12
Source File: PsshAtomUtil.java    From K-Sonic with MIT License 5 votes vote down vote up
/**
 * Parses the UUID and scheme specific data from a PSSH atom. Version 0 and 1 PSSH atoms are
 * supported.
 *
 * @param atom The atom to parse.
 * @return A pair consisting of the parsed UUID and scheme specific data. Null if the input is
 *     not a valid PSSH atom, or if the PSSH atom has an unsupported version.
 */
private static Pair<UUID, byte[]> parsePsshAtom(byte[] atom) {
  ParsableByteArray atomData = new ParsableByteArray(atom);
  if (atomData.limit() < Atom.FULL_HEADER_SIZE + 16 /* UUID */ + 4 /* DataSize */) {
    // Data too short.
    return null;
  }
  atomData.setPosition(0);
  int atomSize = atomData.readInt();
  if (atomSize != atomData.bytesLeft() + 4) {
    // Not an atom, or incorrect atom size.
    return null;
  }
  int atomType = atomData.readInt();
  if (atomType != Atom.TYPE_pssh) {
    // Not an atom, or incorrect atom type.
    return null;
  }
  int atomVersion = Atom.parseFullAtomVersion(atomData.readInt());
  if (atomVersion > 1) {
    Log.w(TAG, "Unsupported pssh version: " + atomVersion);
    return null;
  }
  UUID uuid = new UUID(atomData.readLong(), atomData.readLong());
  if (atomVersion == 1) {
    int keyIdCount = atomData.readUnsignedIntToInt();
    atomData.skipBytes(16 * keyIdCount);
  }
  int dataSize = atomData.readUnsignedIntToInt();
  if (dataSize != atomData.bytesLeft()) {
    // Incorrect dataSize.
    return null;
  }
  byte[] data = new byte[dataSize];
  atomData.readBytes(data, 0, dataSize);
  return Pair.create(uuid, data);
}
 
Example 13
Source File: AtomParsers.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
/**
 * Parses a mvhd atom (defined in 14496-12), returning the timescale for the movie.
 *
 * @param mvhd Contents of the mvhd atom to be parsed.
 * @return Timescale for the movie.
 */
private static long parseMvhd(ParsableByteArray mvhd) {
  mvhd.setPosition(Atom.HEADER_SIZE);
  int fullAtom = mvhd.readInt();
  int version = Atom.parseFullAtomVersion(fullAtom);
  mvhd.skipBytes(version == 0 ? 8 : 16);
  return mvhd.readUnsignedInt();
}
 
Example 14
Source File: FragmentedMp4Extractor.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Parses a tfdt atom (defined in 14496-12).
 *
 * @return baseMediaDecodeTime The sum of the decode durations of all earlier samples in the
 *     media, expressed in the media's timescale.
 */
private static long parseTfdt(ParsableByteArray tfdt) {
  tfdt.setPosition(Atom.HEADER_SIZE);
  int fullAtom = tfdt.readInt();
  int version = Atom.parseFullAtomVersion(fullAtom);
  return version == 1 ? tfdt.readUnsignedLongToLong() : tfdt.readUnsignedInt();
}
 
Example 15
Source File: TsExtractor.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Returns the stream info read from the available descriptors. Sets {@code data}'s position to
 * the end of the descriptors.
 *
 * @param data A buffer with its position set to the start of the first descriptor.
 * @param length The length of descriptors to read from the current position in {@code data}.
 * @return The stream info read from the available descriptors.
 */
private EsInfo readEsInfo(ParsableByteArray data, int length) {
  int descriptorsStartPosition = data.getPosition();
  int descriptorsEndPosition = descriptorsStartPosition + length;
  int streamType = -1;
  String language = null;
  List<DvbSubtitleInfo> dvbSubtitleInfos = null;
  while (data.getPosition() < descriptorsEndPosition) {
    int descriptorTag = data.readUnsignedByte();
    int descriptorLength = data.readUnsignedByte();
    int positionOfNextDescriptor = data.getPosition() + descriptorLength;
    if (descriptorTag == TS_PMT_DESC_REGISTRATION) { // registration_descriptor
      long formatIdentifier = data.readUnsignedInt();
      if (formatIdentifier == AC3_FORMAT_IDENTIFIER) {
        streamType = TS_STREAM_TYPE_AC3;
      } else if (formatIdentifier == E_AC3_FORMAT_IDENTIFIER) {
        streamType = TS_STREAM_TYPE_E_AC3;
      } else if (formatIdentifier == HEVC_FORMAT_IDENTIFIER) {
        streamType = TS_STREAM_TYPE_H265;
      }
    } else if (descriptorTag == TS_PMT_DESC_AC3) { // AC-3_descriptor in DVB (ETSI EN 300 468)
      streamType = TS_STREAM_TYPE_AC3;
    } else if (descriptorTag == TS_PMT_DESC_EAC3) { // enhanced_AC-3_descriptor
      streamType = TS_STREAM_TYPE_E_AC3;
    } else if (descriptorTag == TS_PMT_DESC_DTS) { // DTS_descriptor
      streamType = TS_STREAM_TYPE_DTS;
    } else if (descriptorTag == TS_PMT_DESC_ISO639_LANG) {
      language = data.readString(3).trim();
      // Audio type is ignored.
    } else if (descriptorTag == TS_PMT_DESC_DVBSUBS) {
      streamType = TS_STREAM_TYPE_DVBSUBS;
      dvbSubtitleInfos = new ArrayList<>();
      while (data.getPosition() < positionOfNextDescriptor) {
        String dvbLanguage = data.readString(3).trim();
        int dvbSubtitlingType = data.readUnsignedByte();
        byte[] initializationData = new byte[4];
        data.readBytes(initializationData, 0, 4);
        dvbSubtitleInfos.add(new DvbSubtitleInfo(dvbLanguage, dvbSubtitlingType,
            initializationData));
      }
    }
    // Skip unused bytes of current descriptor.
    data.skipBytes(positionOfNextDescriptor - data.getPosition());
  }
  data.setPosition(descriptorsEndPosition);
  return new EsInfo(streamType, language, dvbSubtitleInfos,
      Arrays.copyOfRange(data.data, descriptorsStartPosition, descriptorsEndPosition));
}
 
Example 16
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 17
Source File: OggExtractor.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
private static ParsableByteArray resetPosition(ParsableByteArray scratch) {
  scratch.setPosition(0);
  return scratch;
}
 
Example 18
Source File: AtomParsers.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Returns codec-specific initialization data contained in an esds box.
 */
private static Pair<String, byte[]> parseEsdsFromParent(ParsableByteArray parent, int position) {
  parent.setPosition(position + Atom.HEADER_SIZE + 4);
  // Start of the ES_Descriptor (defined in 14496-1)
  parent.skipBytes(1); // ES_Descriptor tag
  parseExpandableClassSize(parent);
  parent.skipBytes(2); // ES_ID

  int flags = parent.readUnsignedByte();
  if ((flags & 0x80 /* streamDependenceFlag */) != 0) {
    parent.skipBytes(2);
  }
  if ((flags & 0x40 /* URL_Flag */) != 0) {
    parent.skipBytes(parent.readUnsignedShort());
  }
  if ((flags & 0x20 /* OCRstreamFlag */) != 0) {
    parent.skipBytes(2);
  }

  // Start of the DecoderConfigDescriptor (defined in 14496-1)
  parent.skipBytes(1); // DecoderConfigDescriptor tag
  parseExpandableClassSize(parent);

  // Set the MIME type based on the object type indication (14496-1 table 5).
  int objectTypeIndication = parent.readUnsignedByte();
  String mimeType = getMimeTypeFromMp4ObjectType(objectTypeIndication);
  if (MimeTypes.AUDIO_MPEG.equals(mimeType)
      || MimeTypes.AUDIO_DTS.equals(mimeType)
      || MimeTypes.AUDIO_DTS_HD.equals(mimeType)) {
    return Pair.create(mimeType, null);
  }

  parent.skipBytes(12);

  // Start of the DecoderSpecificInfo.
  parent.skipBytes(1); // DecoderSpecificInfo tag
  int initializationDataSize = parseExpandableClassSize(parent);
  byte[] initializationData = new byte[initializationDataSize];
  parent.readBytes(initializationData, 0, initializationDataSize);
  return Pair.create(mimeType, initializationData);
}
 
Example 19
Source File: WavHeaderReader.java    From Telegram-FOSS 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 20
Source File: TsBinarySearchSeeker.java    From Telegram with GNU General Public License v2.0 4 votes vote down vote up
private TimestampSearchResult searchForPcrValueInBuffer(
    ParsableByteArray packetBuffer, long targetPcrTimeUs, long bufferStartOffset) {
  int limit = packetBuffer.limit();

  long startOfLastPacketPosition = C.POSITION_UNSET;
  long endOfLastPacketPosition = C.POSITION_UNSET;
  long lastPcrTimeUsInRange = C.TIME_UNSET;

  while (packetBuffer.bytesLeft() >= TsExtractor.TS_PACKET_SIZE) {
    int startOfPacket =
        TsUtil.findSyncBytePosition(packetBuffer.data, packetBuffer.getPosition(), limit);
    int endOfPacket = startOfPacket + TsExtractor.TS_PACKET_SIZE;
    if (endOfPacket > limit) {
      break;
    }
    long pcrValue = TsUtil.readPcrFromPacket(packetBuffer, startOfPacket, pcrPid);
    if (pcrValue != C.TIME_UNSET) {
      long pcrTimeUs = pcrTimestampAdjuster.adjustTsTimestamp(pcrValue);
      if (pcrTimeUs > targetPcrTimeUs) {
        if (lastPcrTimeUsInRange == C.TIME_UNSET) {
          // First PCR timestamp is already over target.
          return TimestampSearchResult.overestimatedResult(pcrTimeUs, bufferStartOffset);
        } else {
          // Last PCR timestamp < target timestamp < this timestamp.
          return TimestampSearchResult.targetFoundResult(
              bufferStartOffset + startOfLastPacketPosition);
        }
      } else if (pcrTimeUs + SEEK_TOLERANCE_US > targetPcrTimeUs) {
        long startOfPacketInStream = bufferStartOffset + startOfPacket;
        return TimestampSearchResult.targetFoundResult(startOfPacketInStream);
      }

      lastPcrTimeUsInRange = pcrTimeUs;
      startOfLastPacketPosition = startOfPacket;
    }
    packetBuffer.setPosition(endOfPacket);
    endOfLastPacketPosition = endOfPacket;
  }

  if (lastPcrTimeUsInRange != C.TIME_UNSET) {
    long endOfLastPacketPositionInStream = bufferStartOffset + endOfLastPacketPosition;
    return TimestampSearchResult.underestimatedResult(
        lastPcrTimeUsInRange, endOfLastPacketPositionInStream);
  } else {
    return TimestampSearchResult.NO_TIMESTAMP_IN_RANGE_RESULT;
  }
}