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

The following examples show how to use com.google.android.exoplayer2.util.ParsableByteArray#skipBytes() . 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: DefaultTrackOutput.java    From K-Sonic with MIT License 6 votes vote down vote up
@Override
public void sampleData(ParsableByteArray buffer, int length) {
  if (!startWriteOperation()) {
    buffer.skipBytes(length);
    return;
  }
  while (length > 0) {
    int thisAppendLength = prepareForAppend(length);
    buffer.readBytes(lastAllocation.data, lastAllocation.translateOffset(lastAllocationOffset),
        thisAppendLength);
    lastAllocationOffset += thisAppendLength;
    totalBytesWritten += thisAppendLength;
    length -= thisAppendLength;
  }
  endWriteOperation();
}
 
Example 2
Source File: MetadataUtil.java    From TelePlus-Android with GNU General Public License v2.0 6 votes vote down vote up
private static @Nullable ApicFrame parseCoverArt(ParsableByteArray data) {
  int atomSize = data.readInt();
  int atomType = data.readInt();
  if (atomType == Atom.TYPE_data) {
    int fullVersionInt = data.readInt();
    int flags = Atom.parseFullAtomFlags(fullVersionInt);
    String mimeType = flags == 13 ? "image/jpeg" : flags == 14 ? "image/png" : null;
    if (mimeType == null) {
      Log.w(TAG, "Unrecognized cover art flags: " + flags);
      return null;
    }
    data.skipBytes(4); // empty (4)
    byte[] pictureData = new byte[atomSize - 16];
    data.readBytes(pictureData, 0, pictureData.length);
    return new ApicFrame(
        mimeType,
        /* description= */ null,
        /* pictureType= */ PICTURE_TYPE_FRONT_COVER,
        pictureData);
  }
  Log.w(TAG, "Failed to parse cover art attribute");
  return null;
}
 
Example 3
Source File: DolbyVisionConfig.java    From Telegram with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Parses Dolby Vision configuration data.
 *
 * @param data A {@link ParsableByteArray}, whose position is set to the start of the Dolby Vision
 *     configuration data to parse.
 * @return The {@link DolbyVisionConfig} corresponding to the configuration, or {@code null} if
 *     the configuration isn't supported.
 */
@Nullable
public static DolbyVisionConfig parse(ParsableByteArray data) {
  data.skipBytes(2); // dv_version_major, dv_version_minor
  int profileData = data.readUnsignedByte();
  int dvProfile = (profileData >> 1);
  int dvLevel = ((profileData & 0x1) << 5) | ((data.readUnsignedByte() >> 3) & 0x1F);
  String codecsPrefix;
  if (dvProfile == 4 || dvProfile == 5) {
    codecsPrefix = "dvhe";
  } else if (dvProfile == 8) {
    codecsPrefix = "hev1";
  } else if (dvProfile == 9) {
    codecsPrefix = "avc3";
  } else {
    return null;
  }
  String codecs = codecsPrefix + ".0" + dvProfile + ".0" + dvLevel;
  return new DolbyVisionConfig(dvProfile, dvLevel, codecs);
}
 
Example 4
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 5
Source File: MetadataUtil.java    From TelePlus-Android with GNU General Public License v2.0 6 votes vote down vote up
private static @Nullable ApicFrame parseCoverArt(ParsableByteArray data) {
  int atomSize = data.readInt();
  int atomType = data.readInt();
  if (atomType == Atom.TYPE_data) {
    int fullVersionInt = data.readInt();
    int flags = Atom.parseFullAtomFlags(fullVersionInt);
    String mimeType = flags == 13 ? "image/jpeg" : flags == 14 ? "image/png" : null;
    if (mimeType == null) {
      Log.w(TAG, "Unrecognized cover art flags: " + flags);
      return null;
    }
    data.skipBytes(4); // empty (4)
    byte[] pictureData = new byte[atomSize - 16];
    data.readBytes(pictureData, 0, pictureData.length);
    return new ApicFrame(
        mimeType,
        /* description= */ null,
        /* pictureType= */ PICTURE_TYPE_FRONT_COVER,
        pictureData);
  }
  Log.w(TAG, "Failed to parse cover art attribute");
  return null;
}
 
Example 6
Source File: CssParser.java    From TelePlus-Android with GNU General Public License v2.0 6 votes vote down vote up
private static boolean maybeSkipComment(ParsableByteArray input) {
  int position = input.getPosition();
  int limit = input.limit();
  byte[] data = input.data;
  if (position + 2 <= limit && data[position++] == '/' && data[position++] == '*') {
    while (position + 1 < limit) {
      char skippedChar = (char) data[position++];
      if (skippedChar == '*') {
        if (((char) data[position]) == '/') {
          position++;
          limit = position;
        }
      }
    }
    input.skipBytes(limit - input.getPosition());
    return true;
  }
  return false;
}
 
Example 7
Source File: CssParser.java    From K-Sonic with MIT License 5 votes vote down vote up
private static boolean maybeSkipWhitespace(ParsableByteArray input) {
  switch(peekCharAtPosition(input, input.getPosition())) {
    case '\t':
    case '\r':
    case '\n':
    case '\f':
    case ' ':
      input.skipBytes(1);
      return true;
    default:
      return false;
  }
}
 
Example 8
Source File: FragmentedMp4Extractor.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
/** Skips the encryption data for the current sample. */
private void skipSampleEncryptionData() {
  TrackEncryptionBox encryptionBox = getEncryptionBoxIfEncrypted();
  if (encryptionBox == null) {
    return;
  }

  ParsableByteArray sampleEncryptionData = fragment.sampleEncryptionData;
  if (encryptionBox.perSampleIvSize != 0) {
    sampleEncryptionData.skipBytes(encryptionBox.perSampleIvSize);
  }
  if (fragment.sampleHasSubsampleEncryptionTable(currentSampleIndex)) {
    sampleEncryptionData.skipBytes(6 * sampleEncryptionData.readUnsignedShort());
  }
}
 
Example 9
Source File: AtomParsers.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
static Pair<Integer, TrackEncryptionBox> parseCommonEncryptionSinfFromParent(
    ParsableByteArray parent, int position, int size) {
  int childPosition = position + Atom.HEADER_SIZE;
  int schemeInformationBoxPosition = C.POSITION_UNSET;
  int schemeInformationBoxSize = 0;
  String schemeType = null;
  Integer dataFormat = null;
  while (childPosition - position < size) {
    parent.setPosition(childPosition);
    int childAtomSize = parent.readInt();
    int childAtomType = parent.readInt();
    if (childAtomType == Atom.TYPE_frma) {
      dataFormat = parent.readInt();
    } else if (childAtomType == Atom.TYPE_schm) {
      parent.skipBytes(4);
      // Common encryption scheme_type values are defined in ISO/IEC 23001-7:2016, section 4.1.
      schemeType = parent.readString(4);
    } else if (childAtomType == Atom.TYPE_schi) {
      schemeInformationBoxPosition = childPosition;
      schemeInformationBoxSize = childAtomSize;
    }
    childPosition += childAtomSize;
  }

  if (C.CENC_TYPE_cenc.equals(schemeType) || C.CENC_TYPE_cbc1.equals(schemeType)
      || C.CENC_TYPE_cens.equals(schemeType) || C.CENC_TYPE_cbcs.equals(schemeType)) {
    Assertions.checkArgument(dataFormat != null, "frma atom is mandatory");
    Assertions.checkArgument(schemeInformationBoxPosition != C.POSITION_UNSET,
        "schi atom is mandatory");
    TrackEncryptionBox encryptionBox = parseSchiFromParent(parent, schemeInformationBoxPosition,
        schemeInformationBoxSize, schemeType);
    Assertions.checkArgument(encryptionBox != null, "tenc atom is mandatory");
    return Pair.create(dataFormat, encryptionBox);
  } else {
    return null;
  }
}
 
Example 10
Source File: MetadataUtil.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
private static @Nullable TextInformationFrame parseTextAttribute(
    int type, String id, ParsableByteArray data) {
  int atomSize = data.readInt();
  int atomType = data.readInt();
  if (atomType == Atom.TYPE_data) {
    data.skipBytes(8); // version (1), flags (3), empty (4)
    String value = data.readNullTerminatedString(atomSize - 16);
    return new TextInformationFrame(id, /* description= */ null, value);
  }
  Log.w(TAG, "Failed to parse text attribute: " + Atom.getAtomTypeString(type));
  return null;
}
 
Example 11
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 12
Source File: MetadataUtil.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
@Nullable
private static CommentFrame parseCommentAttribute(int type, ParsableByteArray data) {
  int atomSize = data.readInt();
  int atomType = data.readInt();
  if (atomType == Atom.TYPE_data) {
    data.skipBytes(8); // version (1), flags (3), empty (4)
    String value = data.readNullTerminatedString(atomSize - 16);
    return new CommentFrame(LANGUAGE_UNDEFINED, value, value);
  }
  Log.w(TAG, "Failed to parse comment attribute: " + Atom.getAtomTypeString(type));
  return null;
}
 
Example 13
Source File: FragmentedMp4Extractor.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
/**
 * Outputs the encryption data for the current sample.
 *
 * @return The number of written bytes.
 */
public int outputSampleEncryptionData() {
  TrackEncryptionBox encryptionBox = getEncryptionBoxIfEncrypted();
  if (encryptionBox == null) {
    return 0;
  }

  ParsableByteArray initializationVectorData;
  int vectorSize;
  if (encryptionBox.perSampleIvSize != 0) {
    initializationVectorData = fragment.sampleEncryptionData;
    vectorSize = encryptionBox.perSampleIvSize;
  } else {
    // The default initialization vector should be used.
    byte[] initVectorData = encryptionBox.defaultInitializationVector;
    defaultInitializationVector.reset(initVectorData, initVectorData.length);
    initializationVectorData = defaultInitializationVector;
    vectorSize = initVectorData.length;
  }

  boolean subsampleEncryption = fragment.sampleHasSubsampleEncryptionTable(currentSampleIndex);

  // Write the signal byte, containing the vector size and the subsample encryption flag.
  encryptionSignalByte.data[0] = (byte) (vectorSize | (subsampleEncryption ? 0x80 : 0));
  encryptionSignalByte.setPosition(0);
  output.sampleData(encryptionSignalByte, 1);
  // Write the vector.
  output.sampleData(initializationVectorData, vectorSize);
  // If we don't have subsample encryption data, we're done.
  if (!subsampleEncryption) {
    return 1 + vectorSize;
  }
  // Write the subsample encryption data.
  ParsableByteArray subsampleEncryptionData = fragment.sampleEncryptionData;
  int subsampleCount = subsampleEncryptionData.readUnsignedShort();
  subsampleEncryptionData.skipBytes(-2);
  int subsampleDataLength = 2 + 6 * subsampleCount;
  output.sampleData(subsampleEncryptionData, subsampleDataLength);
  return 1 + vectorSize + subsampleDataLength;
}
 
Example 14
Source File: PesReader.java    From K-Sonic with MIT License 4 votes vote down vote up
@Override
public final void consume(ParsableByteArray data, boolean payloadUnitStartIndicator) {
  if (payloadUnitStartIndicator) {
    switch (state) {
      case STATE_FINDING_HEADER:
      case STATE_READING_HEADER:
        // Expected.
        break;
      case STATE_READING_HEADER_EXTENSION:
        Log.w(TAG, "Unexpected start indicator reading extended header");
        break;
      case STATE_READING_BODY:
        // If payloadSize == -1 then the length of the previous packet was unspecified, and so
        // we only know that it's finished now that we've seen the start of the next one. This
        // is expected. If payloadSize != -1, then the length of the previous packet was known,
        // but we didn't receive that amount of data. This is not expected.
        if (payloadSize != -1) {
          Log.w(TAG, "Unexpected start indicator: expected " + payloadSize + " more bytes");
        }
        // Either way, notify the reader that it has now finished.
        reader.packetFinished();
        break;
    }
    setState(STATE_READING_HEADER);
  }

  while (data.bytesLeft() > 0) {
    switch (state) {
      case STATE_FINDING_HEADER:
        data.skipBytes(data.bytesLeft());
        break;
      case STATE_READING_HEADER:
        if (continueRead(data, pesScratch.data, HEADER_SIZE)) {
          setState(parseHeader() ? STATE_READING_HEADER_EXTENSION : STATE_FINDING_HEADER);
        }
        break;
      case STATE_READING_HEADER_EXTENSION:
        int readLength = Math.min(MAX_HEADER_EXTENSION_SIZE, extendedHeaderLength);
        // Read as much of the extended header as we're interested in, and skip the rest.
        if (continueRead(data, pesScratch.data, readLength)
            && continueRead(data, null, extendedHeaderLength)) {
          parseHeaderExtension();
          reader.packetStarted(timeUs, dataAlignmentIndicator);
          setState(STATE_READING_BODY);
        }
        break;
      case STATE_READING_BODY:
        readLength = data.bytesLeft();
        int padding = payloadSize == -1 ? 0 : readLength - payloadSize;
        if (padding > 0) {
          readLength -= padding;
          data.setLimit(data.getPosition() + readLength);
        }
        reader.consume(data);
        if (payloadSize != -1) {
          payloadSize -= readLength;
          if (payloadSize == 0) {
            reader.packetFinished();
            setState(STATE_READING_HEADER);
          }
        }
        break;
    }
  }
}
 
Example 15
Source File: AtomParsers.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
/**
 * Parses a metadata meta atom if it contains metadata with handler 'mdta'.
 *
 * @param meta The metadata atom to decode.
 * @return Parsed metadata, or null.
 */
@Nullable
public static Metadata parseMdtaFromMeta(Atom.ContainerAtom meta) {
  Atom.LeafAtom hdlrAtom = meta.getLeafAtomOfType(Atom.TYPE_hdlr);
  Atom.LeafAtom keysAtom = meta.getLeafAtomOfType(Atom.TYPE_keys);
  Atom.LeafAtom ilstAtom = meta.getLeafAtomOfType(Atom.TYPE_ilst);
  if (hdlrAtom == null
      || keysAtom == null
      || ilstAtom == null
      || AtomParsers.parseHdlr(hdlrAtom.data) != TYPE_mdta) {
    // There isn't enough information to parse the metadata, or the handler type is unexpected.
    return null;
  }

  // Parse metadata keys.
  ParsableByteArray keys = keysAtom.data;
  keys.setPosition(Atom.FULL_HEADER_SIZE);
  int entryCount = keys.readInt();
  String[] keyNames = new String[entryCount];
  for (int i = 0; i < entryCount; i++) {
    int entrySize = keys.readInt();
    keys.skipBytes(4); // keyNamespace
    int keySize = entrySize - 8;
    keyNames[i] = keys.readString(keySize);
  }

  // Parse metadata items.
  ParsableByteArray ilst = ilstAtom.data;
  ilst.setPosition(Atom.HEADER_SIZE);
  ArrayList<Metadata.Entry> entries = new ArrayList<>();
  while (ilst.bytesLeft() > Atom.HEADER_SIZE) {
    int atomPosition = ilst.getPosition();
    int atomSize = ilst.readInt();
    int keyIndex = ilst.readInt() - 1;
    if (keyIndex >= 0 && keyIndex < keyNames.length) {
      String key = keyNames[keyIndex];
      Metadata.Entry entry =
          MetadataUtil.parseMdtaMetadataEntryFromIlst(ilst, atomPosition + atomSize, key);
      if (entry != null) {
        entries.add(entry);
      }
    } else {
      Log.w(TAG, "Skipped metadata with unknown key index: " + keyIndex);
    }
    ilst.setPosition(atomPosition + atomSize);
  }
  return entries.isEmpty() ? null : new Metadata(entries);
}
 
Example 16
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 17
Source File: AvcConfig.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
private static byte[] buildNalUnitForChild(ParsableByteArray data) {
  int length = data.readUnsignedShort();
  int offset = data.getPosition();
  data.skipBytes(length);
  return CodecSpecificDataUtil.buildNalUnit(data.data, offset, length);
}
 
Example 18
Source File: AtomParsers.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
/**
 * Parses a tkhd atom (defined in 14496-12).
 *
 * @return An object containing the parsed data.
 */
private static TkhdData parseTkhd(ParsableByteArray tkhd) {
  tkhd.setPosition(Atom.HEADER_SIZE);
  int fullAtom = tkhd.readInt();
  int version = Atom.parseFullAtomVersion(fullAtom);

  tkhd.skipBytes(version == 0 ? 8 : 16);
  int trackId = tkhd.readInt();

  tkhd.skipBytes(4);
  boolean durationUnknown = true;
  int durationPosition = tkhd.getPosition();
  int durationByteCount = version == 0 ? 4 : 8;
  for (int i = 0; i < durationByteCount; i++) {
    if (tkhd.data[durationPosition + i] != -1) {
      durationUnknown = false;
      break;
    }
  }
  long duration;
  if (durationUnknown) {
    tkhd.skipBytes(durationByteCount);
    duration = C.TIME_UNSET;
  } else {
    duration = version == 0 ? tkhd.readUnsignedInt() : tkhd.readUnsignedLongToLong();
    if (duration == 0) {
      // 0 duration normally indicates that the file is fully fragmented (i.e. all of the media
      // samples are in fragments). Treat as unknown.
      duration = C.TIME_UNSET;
    }
  }

  tkhd.skipBytes(16);
  int a00 = tkhd.readInt();
  int a01 = tkhd.readInt();
  tkhd.skipBytes(4);
  int a10 = tkhd.readInt();
  int a11 = tkhd.readInt();

  int rotationDegrees;
  int fixedOne = 65536;
  if (a00 == 0 && a01 == fixedOne && a10 == -fixedOne && a11 == 0) {
    rotationDegrees = 90;
  } else if (a00 == 0 && a01 == -fixedOne && a10 == fixedOne && a11 == 0) {
    rotationDegrees = 270;
  } else if (a00 == -fixedOne && a01 == 0 && a10 == 0 && a11 == -fixedOne) {
    rotationDegrees = 180;
  } else {
    // Only 0, 90, 180 and 270 are supported. Treat anything else as 0.
    rotationDegrees = 0;
  }

  return new TkhdData(trackId, duration, rotationDegrees);
}
 
Example 19
Source File: PesReader.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
@Override
public final void consume(ParsableByteArray data, boolean payloadUnitStartIndicator)
    throws ParserException {
  if (payloadUnitStartIndicator) {
    switch (state) {
      case STATE_FINDING_HEADER:
      case STATE_READING_HEADER:
        // Expected.
        break;
      case STATE_READING_HEADER_EXTENSION:
        Log.w(TAG, "Unexpected start indicator reading extended header");
        break;
      case STATE_READING_BODY:
        // If payloadSize == -1 then the length of the previous packet was unspecified, and so
        // we only know that it's finished now that we've seen the start of the next one. This
        // is expected. If payloadSize != -1, then the length of the previous packet was known,
        // but we didn't receive that amount of data. This is not expected.
        if (payloadSize != -1) {
          Log.w(TAG, "Unexpected start indicator: expected " + payloadSize + " more bytes");
        }
        // Either way, notify the reader that it has now finished.
        reader.packetFinished();
        break;
    }
    setState(STATE_READING_HEADER);
  }

  while (data.bytesLeft() > 0) {
    switch (state) {
      case STATE_FINDING_HEADER:
        data.skipBytes(data.bytesLeft());
        break;
      case STATE_READING_HEADER:
        if (continueRead(data, pesScratch.data, HEADER_SIZE)) {
          setState(parseHeader() ? STATE_READING_HEADER_EXTENSION : STATE_FINDING_HEADER);
        }
        break;
      case STATE_READING_HEADER_EXTENSION:
        int readLength = Math.min(MAX_HEADER_EXTENSION_SIZE, extendedHeaderLength);
        // Read as much of the extended header as we're interested in, and skip the rest.
        if (continueRead(data, pesScratch.data, readLength)
            && continueRead(data, null, extendedHeaderLength)) {
          parseHeaderExtension();
          reader.packetStarted(timeUs, dataAlignmentIndicator);
          setState(STATE_READING_BODY);
        }
        break;
      case STATE_READING_BODY:
        readLength = data.bytesLeft();
        int padding = payloadSize == -1 ? 0 : readLength - payloadSize;
        if (padding > 0) {
          readLength -= padding;
          data.setLimit(data.getPosition() + readLength);
        }
        reader.consume(data);
        if (payloadSize != -1) {
          payloadSize -= readLength;
          if (payloadSize == 0) {
            reader.packetFinished();
            setState(STATE_READING_HEADER);
          }
        }
        break;
    }
  }
}
 
Example 20
Source File: AtomParsers.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Parses a tkhd atom (defined in 14496-12).
 *
 * @return An object containing the parsed data.
 */
private static TkhdData parseTkhd(ParsableByteArray tkhd) {
  tkhd.setPosition(Atom.HEADER_SIZE);
  int fullAtom = tkhd.readInt();
  int version = Atom.parseFullAtomVersion(fullAtom);

  tkhd.skipBytes(version == 0 ? 8 : 16);
  int trackId = tkhd.readInt();

  tkhd.skipBytes(4);
  boolean durationUnknown = true;
  int durationPosition = tkhd.getPosition();
  int durationByteCount = version == 0 ? 4 : 8;
  for (int i = 0; i < durationByteCount; i++) {
    if (tkhd.data[durationPosition + i] != -1) {
      durationUnknown = false;
      break;
    }
  }
  long duration;
  if (durationUnknown) {
    tkhd.skipBytes(durationByteCount);
    duration = C.TIME_UNSET;
  } else {
    duration = version == 0 ? tkhd.readUnsignedInt() : tkhd.readUnsignedLongToLong();
    if (duration == 0) {
      // 0 duration normally indicates that the file is fully fragmented (i.e. all of the media
      // samples are in fragments). Treat as unknown.
      duration = C.TIME_UNSET;
    }
  }

  tkhd.skipBytes(16);
  int a00 = tkhd.readInt();
  int a01 = tkhd.readInt();
  tkhd.skipBytes(4);
  int a10 = tkhd.readInt();
  int a11 = tkhd.readInt();

  int rotationDegrees;
  int fixedOne = 65536;
  if (a00 == 0 && a01 == fixedOne && a10 == -fixedOne && a11 == 0) {
    rotationDegrees = 90;
  } else if (a00 == 0 && a01 == -fixedOne && a10 == fixedOne && a11 == 0) {
    rotationDegrees = 270;
  } else if (a00 == -fixedOne && a01 == 0 && a10 == 0 && a11 == -fixedOne) {
    rotationDegrees = 180;
  } else {
    // Only 0, 90, 180 and 270 are supported. Treat anything else as 0.
    rotationDegrees = 0;
  }

  return new TkhdData(trackId, duration, rotationDegrees);
}