Java 类com.google.android.exoplayer2.util.ParsableByteArray 实例源码

项目:Exoplayer2Radio    文件:TsExtractor.java   
/**
 * @param mode Mode for the extractor. One of {@link #MODE_MULTI_PMT}, {@link #MODE_SINGLE_PMT}
 *     and {@link #MODE_HLS}.
 * @param timestampAdjuster A timestamp adjuster for offsetting and scaling sample timestamps.
 * @param payloadReaderFactory Factory for injecting a custom set of payload readers.
 */
public TsExtractor(@Mode int mode, TimestampAdjuster timestampAdjuster,
    TsPayloadReader.Factory payloadReaderFactory) {
  this.payloadReaderFactory = Assertions.checkNotNull(payloadReaderFactory);
  this.mode = mode;
  if (mode == MODE_SINGLE_PMT || mode == MODE_HLS) {
    timestampAdjusters = Collections.singletonList(timestampAdjuster);
  } else {
    timestampAdjusters = new ArrayList<>();
    timestampAdjusters.add(timestampAdjuster);
  }
  tsPacketBuffer = new ParsableByteArray(BUFFER_SIZE);
  tsScratch = new ParsableBitArray(new byte[3]);
  trackIds = new SparseBooleanArray();
  tsPayloadReaders = new SparseArray<>();
  continuityCounters = new SparseIntArray();
  resetPayloadReaders();
}
项目:Exoplayer2Radio    文件:MetadataUtil.java   
private static 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, null, 3 /* Cover (front) */, pictureData);
  }
  Log.w(TAG, "Failed to parse cover art attribute");
  return null;
}
项目:Exoplayer2Radio    文件:Ac3Reader.java   
/**
 * Locates the next syncword, advancing the position to the byte that immediately follows it. If a
 * syncword was not located, the position is advanced to the limit.
 *
 * @param pesBuffer The buffer whose position should be advanced.
 * @return Whether a syncword position was found.
 */
private boolean skipToNextSync(ParsableByteArray pesBuffer) {
  while (pesBuffer.bytesLeft() > 0) {
    if (!lastByteWas0B) {
      lastByteWas0B = pesBuffer.readUnsignedByte() == 0x0B;
      continue;
    }
    int secondByte = pesBuffer.readUnsignedByte();
    if (secondByte == 0x77) {
      lastByteWas0B = false;
      return true;
    } else {
      lastByteWas0B = secondByte == 0x0B;
    }
  }
  return false;
}
项目:Exoplayer2Radio    文件:MpegAudioReader.java   
@Override
public void consume(ParsableByteArray data) {
  while (data.bytesLeft() > 0) {
    switch (state) {
      case STATE_FINDING_HEADER:
        findHeader(data);
        break;
      case STATE_READING_HEADER:
        readHeaderRemainder(data);
        break;
      case STATE_READING_FRAME:
        readFrameRemainder(data);
        break;
    }
  }
}
项目:Exoplayer2Radio    文件:ScriptTagPayloadReader.java   
private static Object readAmfData(ParsableByteArray data, int type) {
  switch (type) {
    case AMF_TYPE_NUMBER:
      return readAmfDouble(data);
    case AMF_TYPE_BOOLEAN:
      return readAmfBoolean(data);
    case AMF_TYPE_STRING:
      return readAmfString(data);
    case AMF_TYPE_OBJECT:
      return readAmfObject(data);
    case AMF_TYPE_ECMA_ARRAY:
      return readAmfEcmaArray(data);
    case AMF_TYPE_STRICT_ARRAY:
      return readAmfStrictArray(data);
    case AMF_TYPE_DATE:
      return readAmfDate(data);
    default:
      return null;
  }
}
项目:Exoplayer2Radio    文件:ScriptTagPayloadReader.java   
@Override
protected void parsePayload(ParsableByteArray data, long timeUs) throws ParserException {
  int nameType = readAmfType(data);
  if (nameType != AMF_TYPE_STRING) {
    // Should never happen.
    throw new ParserException();
  }
  String name = readAmfString(data);
  if (!NAME_METADATA.equals(name)) {
    // We're only interested in metadata.
    return;
  }
  int type = readAmfType(data);
  if (type != AMF_TYPE_ECMA_ARRAY) {
    // We're not interested in this metadata.
    return;
  }
  // Set the duration to the value contained in the metadata, if present.
  Map<String, Object> metadata = readAmfEcmaArray(data);
  if (metadata.containsKey(KEY_DURATION)) {
    double durationSeconds = (double) metadata.get(KEY_DURATION);
    if (durationSeconds > 0.0) {
      durationUs = (long) (durationSeconds * C.MICROS_PER_SECOND);
    }
  }
}
项目:Exoplayer2Radio    文件:MatroskaExtractor.java   
/**
 * Parses an MS/ACM codec private, returning whether it indicates PCM audio.
 *
 * @return Whether the codec private indicates PCM audio.
 * @throws ParserException If a parsing error occurs.
 */
private static boolean parseMsAcmCodecPrivate(ParsableByteArray buffer) throws ParserException {
  try {
    int formatTag = buffer.readLittleEndianUnsignedShort();
    if (formatTag == WAVE_FORMAT_PCM) {
      return true;
    } else if (formatTag == WAVE_FORMAT_EXTENSIBLE) {
      buffer.setPosition(WAVE_FORMAT_SIZE + 6); // unionSamples(2), channelMask(4)
      return buffer.readLong() == WAVE_SUBFORMAT_PCM.getMostSignificantBits()
          && buffer.readLong() == WAVE_SUBFORMAT_PCM.getLeastSignificantBits();
    } else {
      return false;
    }
  } catch (ArrayIndexOutOfBoundsException e) {
    throw new ParserException("Error parsing MS/ACM codec private");
  }
}
项目:Exoplayer2Radio    文件:AdtsReader.java   
@Override
public void consume(ParsableByteArray data) {
  while (data.bytesLeft() > 0) {
    switch (state) {
      case STATE_FINDING_SAMPLE:
        findNextSample(data);
        break;
      case STATE_READING_ID3_HEADER:
        if (continueRead(data, id3HeaderBuffer.data, ID3_HEADER_SIZE)) {
          parseId3Header();
        }
        break;
      case STATE_READING_ADTS_HEADER:
        int targetLength = hasCrc ? HEADER_SIZE + CRC_SIZE : HEADER_SIZE;
        if (continueRead(data, adtsScratch.data, targetLength)) {
          parseAdtsHeader();
        }
        break;
      case STATE_READING_SAMPLE:
        readSample(data);
        break;
    }
  }
}
项目:Exoplayer2Radio    文件:SpliceInfoSectionReader.java   
@Override
public void consume(ParsableByteArray sectionData) {
  if (!formatDeclared) {
    if (timestampAdjuster.getTimestampOffsetUs() == C.TIME_UNSET) {
      // There is not enough information to initialize the timestamp adjuster.
      return;
    }
    output.format(Format.createSampleFormat(null, MimeTypes.APPLICATION_SCTE35,
        timestampAdjuster.getTimestampOffsetUs()));
    formatDeclared = true;
  }
  int sampleSize = sectionData.bytesLeft();
  output.sampleData(sectionData, sampleSize);
  output.sampleMetadata(timestampAdjuster.getLastAdjustedTimestampUs(), C.BUFFER_FLAG_KEY_FRAME,
      sampleSize, 0, null);
}
项目:Exoplayer2Radio    文件:Id3Decoder.java   
private static PrivFrame decodePrivFrame(ParsableByteArray id3Data, int frameSize)
    throws UnsupportedEncodingException {
  byte[] data = new byte[frameSize];
  id3Data.readBytes(data, 0, frameSize);

  int ownerEndIndex = indexOfZeroByte(data, 0);
  String owner = new String(data, 0, ownerEndIndex, "ISO-8859-1");

  byte[] privateData;
  int privateDataStartIndex = ownerEndIndex + 1;
  if (privateDataStartIndex < data.length) {
    privateData = Arrays.copyOfRange(data, privateDataStartIndex, data.length);
  } else {
    privateData = new byte[0];
  }

  return new PrivFrame(owner, privateData);
}
项目:Exoplayer2Radio    文件:DvbSubtitleReader.java   
@Override
public void consume(ParsableByteArray data) {
  if (writingSample) {
    if (bytesToCheck == 2 && !checkNextByte(data, 0x20)) {
      // Failed to check data_identifier
      return;
    }
    if (bytesToCheck == 1 && !checkNextByte(data, 0x00)) {
      // Check and discard the subtitle_stream_id
      return;
    }
    int dataPosition = data.getPosition();
    int bytesAvailable = data.bytesLeft();
    for (TrackOutput output : outputs) {
      data.setPosition(dataPosition);
      output.sampleData(data, bytesAvailable);
    }
    sampleBytesWritten += bytesAvailable;
  }
}
项目:Exoplayer2Radio    文件:VorbisReader.java   
@Override
protected boolean readHeaders(ParsableByteArray packet, long position, SetupData setupData)
    throws IOException, InterruptedException {
  if (vorbisSetup != null) {
    return false;
  }

  vorbisSetup = readSetupHeaders(packet);
  if (vorbisSetup == null) {
    return true;
  }

  ArrayList<byte[]> codecInitialisationData = new ArrayList<>();
  codecInitialisationData.add(vorbisSetup.idHeader.data);
  codecInitialisationData.add(vorbisSetup.setupHeaderData);

  setupData.format = Format.createAudioSampleFormat(null, MimeTypes.AUDIO_VORBIS, null,
      this.vorbisSetup.idHeader.bitrateNominal, Format.NO_VALUE,
      this.vorbisSetup.idHeader.channels, (int) this.vorbisSetup.idHeader.sampleRate,
      codecInitialisationData, null, 0, null);
  return true;
}
项目:Exoplayer2Radio    文件:OggExtractor.java   
@Override
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
  try {
    OggPageHeader header = new OggPageHeader();
    if (!header.populate(input, true) || (header.type & 0x02) != 0x02) {
      return false;
    }

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

    if (FlacReader.verifyBitstreamType(resetPosition(scratch))) {
      streamReader = new FlacReader();
    } else if (VorbisReader.verifyBitstreamType(resetPosition(scratch))) {
      streamReader = new VorbisReader();
    } else if (OpusReader.verifyBitstreamType(resetPosition(scratch))) {
      streamReader = new OpusReader();
    } else {
      return false;
    }
    return true;
  } catch (ParserException e) {
    return false;
  }
}
项目:Exoplayer2Radio    文件:Mp4WebvttDecoder.java   
private static Cue parseVttCueBox(ParsableByteArray sampleData, WebvttCue.Builder builder,
      int remainingCueBoxBytes) throws SubtitleDecoderException {
  builder.reset();
  while (remainingCueBoxBytes > 0) {
    if (remainingCueBoxBytes < BOX_HEADER_SIZE) {
      throw new SubtitleDecoderException("Incomplete vtt cue box header found.");
    }
    int boxSize = sampleData.readInt();
    int boxType = sampleData.readInt();
    remainingCueBoxBytes -= BOX_HEADER_SIZE;
    int payloadLength = boxSize - BOX_HEADER_SIZE;
    String boxPayload = new String(sampleData.data, sampleData.getPosition(), payloadLength);
    sampleData.skipBytes(payloadLength);
    remainingCueBoxBytes -= payloadLength;
    if (boxType == TYPE_sttg) {
      WebvttCueParser.parseCueSettingsList(boxPayload, builder);
    } else if (boxType == TYPE_payl) {
      WebvttCueParser.parseCueText(null, boxPayload.trim(), builder,
          Collections.<WebvttCssStyle>emptyList());
    } else {
      // Other VTTCueBox children are still not supported and are ignored.
    }
  }
  return builder.build();
}
项目:Exoplayer2Radio    文件:OpusReader.java   
@Override
protected boolean readHeaders(ParsableByteArray packet, long position, SetupData setupData)
    throws IOException, InterruptedException {
  if (!headerRead) {
    byte[] metadata = Arrays.copyOf(packet.data, packet.limit());
    int channelCount = metadata[9] & 0xFF;
    int preskip = ((metadata[11] & 0xFF) << 8) | (metadata[10] & 0xFF);

    List<byte[]> initializationData = new ArrayList<>(3);
    initializationData.add(metadata);
    putNativeOrderLong(initializationData, preskip);
    putNativeOrderLong(initializationData, DEFAULT_SEEK_PRE_ROLL_SAMPLES);

    setupData.format = Format.createAudioSampleFormat(null, MimeTypes.AUDIO_OPUS, null,
        Format.NO_VALUE, Format.NO_VALUE, channelCount, SAMPLE_RATE, initializationData, null, 0,
        null);
    headerRead = true;
  } else {
    boolean headerPacket = packet.readInt() == OPUS_CODE;
    packet.setPosition(0);
    return headerPacket;
  }
  return true;
}
项目:Exoplayer2Radio    文件:WebvttParserUtil.java   
/**
 * Reads lines up to and including the next WebVTT cue header.
 *
 * @param input The input from which lines should be read.
 * @return A {@link Matcher} for the WebVTT cue header, or null if the end of the input was
 *     reached without a cue header being found. In the case that a cue header is found, groups 1,
 *     2 and 3 of the returned matcher contain the start time, end time and settings list.
 */
public static Matcher findNextCueHeader(ParsableByteArray input) {
  String line;
  while ((line = input.readLine()) != null) {
    if (COMMENT.matcher(line).matches()) {
      // Skip until the end of the comment block.
      while ((line = input.readLine()) != null && !line.isEmpty()) {}
    } else {
      Matcher cueHeaderMatcher = WebvttCueParser.CUE_HEADER_PATTERN.matcher(line);
      if (cueHeaderMatcher.matches()) {
        return cueHeaderMatcher;
      }
    }
  }
  return null;
}
项目:Exoplayer2Radio    文件:CssParser.java   
private static String parseIdentifier(ParsableByteArray input, StringBuilder stringBuilder) {
  stringBuilder.setLength(0);
  int position = input.getPosition();
  int limit = input.limit();
  boolean identifierEndFound = false;
  while (position  < limit && !identifierEndFound) {
    char c = (char) input.data[position];
    if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '#'
        || c == '-' || c == '.' || c == '_') {
      position++;
      stringBuilder.append(c);
    } else {
      identifierEndFound = true;
    }
  }
  input.skipBytes(position - input.getPosition());
  return stringBuilder.toString();
}
项目:Exoplayer2Radio    文件:AtomParsers.java   
/**
 * 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;
}
项目:Exoplayer2Radio    文件:AtomParsers.java   
private static TrackEncryptionBox parseSchiFromParent(ParsableByteArray parent, int position,
    int size) {
  int childPosition = position + Atom.HEADER_SIZE;
  while (childPosition - position < size) {
    parent.setPosition(childPosition);
    int childAtomSize = parent.readInt();
    int childAtomType = parent.readInt();
    if (childAtomType == Atom.TYPE_tenc) {
      parent.skipBytes(6);
      boolean defaultIsEncrypted = parent.readUnsignedByte() == 1;
      int defaultInitVectorSize = parent.readUnsignedByte();
      byte[] defaultKeyId = new byte[16];
      parent.readBytes(defaultKeyId, 0, defaultKeyId.length);
      return new TrackEncryptionBox(defaultIsEncrypted, defaultInitVectorSize, defaultKeyId);
    }
    childPosition += childAtomSize;
  }
  return null;
}
项目:Exoplayer2Radio    文件:MetadataUtil.java   
private static TextInformationFrame parseIndexAndCountAttribute(int type, String attributeName,
    ParsableByteArray data) {
  int atomSize = data.readInt();
  int atomType = data.readInt();
  if (atomType == Atom.TYPE_data && atomSize >= 22) {
    data.skipBytes(10); // version (1), flags (3), empty (4), empty (2)
    int index = data.readUnsignedShort();
    if (index > 0) {
      String value = "" + index;
      int count = data.readUnsignedShort();
      if (count > 0) {
        value += "/" + count;
      }
      return new TextInformationFrame(attributeName, null, value);
    }
  }
  Log.w(TAG, "Failed to parse index/count attribute: " + Atom.getAtomTypeString(type));
  return null;
}
项目:Exoplayer2Radio    文件:FragmentedMp4Extractor.java   
/**
 * 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();
}
项目:Exoplayer2Radio    文件:MetadataUtil.java   
private static int parseUint8AttributeValue(ParsableByteArray data) {
  data.skipBytes(4); // atomSize
  int atomType = data.readInt();
  if (atomType == Atom.TYPE_data) {
    data.skipBytes(8); // version (1), flags (3), empty (4)
    return data.readUnsignedByte();
  }
  Log.w(TAG, "Failed to parse uint8 attribute value");
  return -1;
}
项目:Exoplayer2Radio    文件:Id3Decoder.java   
private static ApicFrame decodeApicFrame(ParsableByteArray id3Data, int frameSize,
    int majorVersion) throws UnsupportedEncodingException {
  int encoding = id3Data.readUnsignedByte();
  String charset = getCharsetName(encoding);

  byte[] data = new byte[frameSize - 1];
  id3Data.readBytes(data, 0, frameSize - 1);

  String mimeType;
  int mimeTypeEndIndex;
  if (majorVersion == 2) {
    mimeTypeEndIndex = 2;
    mimeType = "image/" + Util.toLowerInvariant(new String(data, 0, 3, "ISO-8859-1"));
    if (mimeType.equals("image/jpg")) {
      mimeType = "image/jpeg";
    }
  } else {
    mimeTypeEndIndex = indexOfZeroByte(data, 0);
    mimeType = Util.toLowerInvariant(new String(data, 0, mimeTypeEndIndex, "ISO-8859-1"));
    if (mimeType.indexOf('/') == -1) {
      mimeType = "image/" + mimeType;
    }
  }

  int pictureType = data[mimeTypeEndIndex + 1] & 0xFF;

  int descriptionStartIndex = mimeTypeEndIndex + 2;
  int descriptionEndIndex = indexOfEos(data, descriptionStartIndex, encoding);
  String description = new String(data, descriptionStartIndex,
      descriptionEndIndex - descriptionStartIndex, charset);

  int pictureDataStartIndex = descriptionEndIndex + delimiterLength(encoding);
  byte[] pictureData = Arrays.copyOfRange(data, pictureDataStartIndex, data.length);

  return new ApicFrame(mimeType, description, pictureType, pictureData);
}
项目:Exoplayer2Radio    文件:SpliceScheduleCommand.java   
static SpliceScheduleCommand parseFromSection(ParsableByteArray sectionData) {
  int spliceCount = sectionData.readUnsignedByte();
  ArrayList<Event> events = new ArrayList<>(spliceCount);
  for (int i = 0; i < spliceCount; i++) {
    events.add(Event.parseFromSection(sectionData));
  }
  return new SpliceScheduleCommand(events);
}
项目:Exoplayer2Radio    文件:DtsReader.java   
/**
 * Constructs a new reader for DTS elementary streams.
 *
 * @param language Track language.
 */
public DtsReader(String language) {
  headerScratchBytes = new ParsableByteArray(new byte[HEADER_SIZE]);
  headerScratchBytes.data[0] = (byte) ((SYNC_VALUE >> 24) & 0xFF);
  headerScratchBytes.data[1] = (byte) ((SYNC_VALUE >> 16) & 0xFF);
  headerScratchBytes.data[2] = (byte) ((SYNC_VALUE >> 8) & 0xFF);
  headerScratchBytes.data[3] = (byte) (SYNC_VALUE & 0xFF);
  state = STATE_FINDING_SYNC;
  this.language = language;
}
项目:Exoplayer2Radio    文件:CssParser.java   
/**
 * 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;
}
项目:Exoplayer2Radio    文件:DtsReader.java   
/**
 * Locates the next SYNC value in the buffer, advancing the position to the byte that immediately
 * follows it. If SYNC was not located, the position is advanced to the limit.
 *
 * @param pesBuffer The buffer whose position should be advanced.
 * @return Whether SYNC was found.
 */
private boolean skipToNextSync(ParsableByteArray pesBuffer) {
  while (pesBuffer.bytesLeft() > 0) {
    syncBytes <<= 8;
    syncBytes |= pesBuffer.readUnsignedByte();
    if (syncBytes == SYNC_VALUE) {
      syncBytes = 0;
      return true;
    }
  }
  return false;
}
项目:Exoplayer2Radio    文件:PesReader.java   
/**
 * Continues a read from the provided {@code source} into a given {@code target}. It's assumed
 * that the data should be written into {@code target} starting from an offset of zero.
 *
 * @param source The source from which to read.
 * @param target The target into which data is to be read, or {@code null} to skip.
 * @param targetLength The target length of the read.
 * @return Whether the target length has been reached.
 */
private boolean continueRead(ParsableByteArray source, byte[] target, int targetLength) {
  int bytesToRead = Math.min(source.bytesLeft(), targetLength - bytesRead);
  if (bytesToRead <= 0) {
    return true;
  } else if (target == null) {
    source.skipBytes(bytesToRead);
  } else {
    source.readBytes(target, bytesRead, bytesToRead);
  }
  bytesRead += bytesToRead;
  return bytesRead == targetLength;
}
项目:Exoplayer2Radio    文件:Ac3Reader.java   
/**
 * Constructs a new reader for (E-)AC-3 elementary streams.
 *
 * @param language Track language.
 */
public Ac3Reader(String language) {
  headerScratchBits = new ParsableBitArray(new byte[HEADER_SIZE]);
  headerScratchBytes = new ParsableByteArray(headerScratchBits.data);
  state = STATE_FINDING_SYNC;
  this.language = language;
}
项目:Exoplayer2Radio    文件:Ac3Reader.java   
@Override
public void consume(ParsableByteArray data) {
  while (data.bytesLeft() > 0) {
    switch (state) {
      case STATE_FINDING_SYNC:
        if (skipToNextSync(data)) {
          state = STATE_READING_HEADER;
          headerScratchBytes.data[0] = 0x0B;
          headerScratchBytes.data[1] = 0x77;
          bytesRead = 2;
        }
        break;
      case STATE_READING_HEADER:
        if (continueRead(data, headerScratchBytes.data, HEADER_SIZE)) {
          parseHeader();
          headerScratchBytes.setPosition(0);
          output.sampleData(headerScratchBytes, HEADER_SIZE);
          state = STATE_READING_SAMPLE;
        }
        break;
      case STATE_READING_SAMPLE:
        int bytesToRead = Math.min(data.bytesLeft(), sampleSize - bytesRead);
        output.sampleData(data, bytesToRead);
        bytesRead += bytesToRead;
        if (bytesRead == sampleSize) {
          output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
          timeUs += sampleDurationUs;
          state = STATE_FINDING_SYNC;
        }
        break;
      default:
        break;
    }
  }
}
项目:Exoplayer2Radio    文件:MpegAudioReader.java   
public MpegAudioReader(String language) {
  state = STATE_FINDING_HEADER;
  // The first byte of an MPEG Audio frame header is always 0xFF.
  headerScratch = new ParsableByteArray(4);
  headerScratch.data[0] = (byte) 0xFF;
  header = new MpegAudioHeader();
  this.language = language;
}
项目:Exoplayer2Radio    文件:PrivateCommand.java   
static PrivateCommand parseFromSection(ParsableByteArray sectionData,
    int commandLength, long ptsAdjustment) {
  long identifier = sectionData.readUnsignedInt();
  byte[] privateBytes = new byte[commandLength - 4 /* identifier size */];
  sectionData.readBytes(privateBytes, 0, privateBytes.length);
  return new PrivateCommand(identifier, privateBytes, ptsAdjustment);
}
项目:Exoplayer2Radio    文件:FragmentedMp4Extractor.java   
/**
 * Parses a tfhd atom (defined in 14496-12), updates the corresponding {@link TrackFragment} and
 * returns the {@link TrackBundle} of the corresponding {@link Track}. If the tfhd does not refer
 * to any {@link TrackBundle}, {@code null} is returned and no changes are made.
 *
 * @param tfhd The tfhd atom to decode.
 * @param trackBundles The track bundles, one of which corresponds to the tfhd atom being parsed.
 * @return The {@link TrackBundle} to which the {@link TrackFragment} belongs, or null if the tfhd
 *     does not refer to any {@link TrackBundle}.
 */
private static TrackBundle parseTfhd(ParsableByteArray tfhd,
    SparseArray<TrackBundle> trackBundles, int flags) {
  tfhd.setPosition(Atom.HEADER_SIZE);
  int fullAtom = tfhd.readInt();
  int atomFlags = Atom.parseFullAtomFlags(fullAtom);
  int trackId = tfhd.readInt();
  TrackBundle trackBundle = trackBundles.get((flags & FLAG_SIDELOADED) == 0 ? trackId : 0);
  if (trackBundle == null) {
    return null;
  }
  if ((atomFlags & 0x01 /* base_data_offset_present */) != 0) {
    long baseDataPosition = tfhd.readUnsignedLongToLong();
    trackBundle.fragment.dataPosition = baseDataPosition;
    trackBundle.fragment.auxiliaryDataPosition = baseDataPosition;
  }

  DefaultSampleValues defaultSampleValues = trackBundle.defaultSampleValues;
  int defaultSampleDescriptionIndex =
      ((atomFlags & 0x02 /* default_sample_description_index_present */) != 0)
          ? tfhd.readUnsignedIntToInt() - 1 : defaultSampleValues.sampleDescriptionIndex;
  int defaultSampleDuration = ((atomFlags & 0x08 /* default_sample_duration_present */) != 0)
      ? tfhd.readUnsignedIntToInt() : defaultSampleValues.duration;
  int defaultSampleSize = ((atomFlags & 0x10 /* default_sample_size_present */) != 0)
      ? tfhd.readUnsignedIntToInt() : defaultSampleValues.size;
  int defaultSampleFlags = ((atomFlags & 0x20 /* default_sample_flags_present */) != 0)
      ? tfhd.readUnsignedIntToInt() : defaultSampleValues.flags;
  trackBundle.fragment.header = new DefaultSampleValues(defaultSampleDescriptionIndex,
      defaultSampleDuration, defaultSampleSize, defaultSampleFlags);
  return trackBundle;
}
项目:Exoplayer2Radio    文件:AdtsReader.java   
/**
 * Reads the rest of the sample
 */
private void readSample(ParsableByteArray data) {
  int bytesToRead = Math.min(data.bytesLeft(), sampleSize - bytesRead);
  currentOutput.sampleData(data, bytesToRead);
  bytesRead += bytesToRead;
  if (bytesRead == sampleSize) {
    currentOutput.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
    timeUs += currentSampleDuration;
    setFindingSampleState();
  }
}
项目:Exoplayer2Radio    文件:Mp4Extractor.java   
/**
 * Process an ftyp atom to determine whether the media is QuickTime.
 *
 * @param atomData The ftyp atom data.
 * @return Whether the media is QuickTime.
 */
private static boolean processFtypAtom(ParsableByteArray atomData) {
  atomData.setPosition(Atom.HEADER_SIZE);
  int majorBrand = atomData.readInt();
  if (majorBrand == BRAND_QUICKTIME) {
    return true;
  }
  atomData.skipBytes(4); // minor_version
  while (atomData.bytesLeft() > 0) {
    if (atomData.readInt() == BRAND_QUICKTIME) {
      return true;
    }
  }
  return false;
}
项目:Exoplayer2Radio    文件:CssParser.java   
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;
  }
}
项目:Exoplayer2Radio    文件:DvbSubtitleReader.java   
private boolean checkNextByte(ParsableByteArray data, int expectedValue) {
  if (data.bytesLeft() == 0) {
    return false;
  }
  if (data.readUnsignedByte() != expectedValue) {
    writingSample = false;
  }
  bytesToCheck--;
  return writingSample;
}
项目:Exoplayer2Radio    文件:WavHeaderReader.java   
/**
 * Skips to the data in the given WAV input stream and returns its data size. After calling, the
 * input stream's position will point to the start of sample data in the WAV.
 * <p>
 * If an exception is thrown, the input position will be left pointing to a chunk header.
 *
 * @param input Input stream to skip to the data chunk in. Its peek position must be pointing to
 *     a valid chunk header.
 * @param wavHeader WAV header to populate with data bounds.
 * @throws ParserException If an error occurs parsing chunks.
 * @throws IOException If reading from the input fails.
 * @throws InterruptedException If interrupted while reading from input.
 */
public static void skipToData(ExtractorInput input, WavHeader wavHeader)
    throws IOException, InterruptedException {
  Assertions.checkNotNull(input);
  Assertions.checkNotNull(wavHeader);

  // Make sure the peek position is set to the read position before we peek the first header.
  input.resetPeekPosition();

  ParsableByteArray scratch = new ParsableByteArray(ChunkHeader.SIZE_IN_BYTES);
  // Skip all chunks until we hit the data header.
  ChunkHeader chunkHeader = ChunkHeader.peek(input, scratch);
  while (chunkHeader.id != Util.getIntegerCodeForString("data")) {
    Log.w(TAG, "Ignoring unknown WAV chunk: " + chunkHeader.id);
    long bytesToSkip = ChunkHeader.SIZE_IN_BYTES + chunkHeader.size;
    // Override size of RIFF chunk, since it describes its size as the entire file.
    if (chunkHeader.id == Util.getIntegerCodeForString("RIFF")) {
      bytesToSkip = ChunkHeader.SIZE_IN_BYTES + 4;
    }
    if (bytesToSkip > Integer.MAX_VALUE) {
      throw new ParserException("Chunk is too large (~2GB+) to skip; id: " + chunkHeader.id);
    }
    input.skipFully((int) bytesToSkip);
    chunkHeader = ChunkHeader.peek(input, scratch);
  }
  // Skip past the "data" header.
  input.skipFully(ChunkHeader.SIZE_IN_BYTES);

  wavHeader.setDataBounds(input.getPosition(), chunkHeader.size);
}
项目:Exoplayer2Radio    文件:WavHeaderReader.java   
/**
 * Peeks and returns a {@link ChunkHeader}.
 *
 * @param input Input stream to peek the chunk header from.
 * @param scratch Buffer for temporary use.
 * @throws IOException If peeking from the input fails.
 * @throws InterruptedException If interrupted while peeking from input.
 * @return A new {@code ChunkHeader} peeked from {@code input}.
 */
public static ChunkHeader peek(ExtractorInput input, ParsableByteArray scratch)
    throws IOException, InterruptedException {
  input.peekFully(scratch.data, 0, SIZE_IN_BYTES);
  scratch.setPosition(0);

  int id = scratch.readInt();
  long size = scratch.readLittleEndianUnsignedInt();

  return new ChunkHeader(id, size);
}
项目:Exoplayer2Radio    文件:Mp3Extractor.java   
/**
 * Constructs a new {@link Mp3Extractor}.
 *
 * @param flags Flags that control the extractor's behavior.
 * @param forcedFirstSampleTimestampUs A timestamp to force for the first sample, or
 *     {@link C#TIME_UNSET} if forcing is not required.
 */
public Mp3Extractor(@Flags int flags, long forcedFirstSampleTimestampUs) {
  this.flags = flags;
  this.forcedFirstSampleTimestampUs = forcedFirstSampleTimestampUs;
  scratch = new ParsableByteArray(SCRATCH_LENGTH);
  synchronizedHeader = new MpegAudioHeader();
  gaplessInfoHolder = new GaplessInfoHolder();
  basisTimeUs = C.TIME_UNSET;
}