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

项目:ExoPlayer-Demo    文件:Id3Parser.java   
private static TxxxFrame parseTxxxFrame(ParsableByteArray id3Data, int frameSize)
    throws UnsupportedEncodingException {
  int encoding = id3Data.readUnsignedByte();
  String charset = getCharsetName(encoding);

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

  int descriptionEndIndex = indexOfEos(data, 0, encoding);
  String description = new String(data, 0, descriptionEndIndex, charset);

  int valueStartIndex = descriptionEndIndex + delimiterLength(encoding);
  int valueEndIndex = indexOfEos(data, valueStartIndex, encoding);
  String value = new String(data, valueStartIndex, valueEndIndex - valueStartIndex, charset);

  return new TxxxFrame(description, value);
}
项目:miku    文件:TsExtractor.java   
@Override
public void consume(ParsableByteArray data, boolean payloadUnitStartIndicator,
    ExtractorOutput output) {
  // Skip pointer.
  if (payloadUnitStartIndicator) {
    int pointerField = data.readUnsignedByte();
    data.skipBytes(pointerField);
  }

  data.readBytes(patScratch, 3);
  patScratch.skipBits(12); // table_id (8), section_syntax_indicator (1), '0' (1), reserved (2)
  int sectionLength = patScratch.readBits(12);
  // transport_stream_id (16), reserved (2), version_number (5), current_next_indicator (1),
  // section_number (8), last_section_number (8)
  data.skipBytes(5);

  int programCount = (sectionLength - 9) / 4;
  for (int i = 0; i < programCount; i++) {
    data.readBytes(patScratch, 4);
    patScratch.skipBits(19); // program_number (16), reserved (3)
    int pid = patScratch.readBits(13);
    tsPayloadReaders.put(pid, new PmtReader());
  }

  // Skip CRC_32.
}
项目:ExoPlayer-Demo    文件:AtomParsers.java   
/**
 * Parses the edts atom (defined in 14496-12 subsection 8.6.5).
 *
 * @param edtsAtom edts (edit box) atom to parse.
 * @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);
}
项目:miku    文件:Ac3Reader.java   
/**
 * Locates the next sync word, advancing the position to the byte that immediately follows it.
 * If a sync word was not located, the position is advanced to the limit.
 *
 * @param pesBuffer The buffer whose position should be advanced.
 * @return True if a sync word position was found. False otherwise.
 */
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;
}
项目:miku    文件:AdtsReader.java   
/**
 * Locates the next sync word, advancing the position to the byte that immediately follows it.
 * If a sync word was not located, the position is advanced to the limit.
 *
 * @param pesBuffer The buffer whose position should be advanced.
 * @return True if a sync word position was found. False otherwise.
 */
private boolean skipToNextSync(ParsableByteArray pesBuffer) {
  byte[] adtsData = pesBuffer.data;
  int startOffset = pesBuffer.getPosition();
  int endOffset = pesBuffer.limit();
  for (int i = startOffset; i < endOffset; i++) {
    boolean byteIsFF = (adtsData[i] & 0xFF) == 0xFF;
    boolean found = lastByteWasFF && !byteIsFF && (adtsData[i] & 0xF0) == 0xF0;
    lastByteWasFF = byteIsFF;
    if (found) {
      hasCrc = (adtsData[i] & 0x1) == 0;
      pesBuffer.setPosition(i + 1);
      // Reset lastByteWasFF for next time.
      lastByteWasFF = false;
      return true;
    }
  }
  pesBuffer.setPosition(endOffset);
  return false;
}
项目:ExoPlayer-Demo    文件:AtomParsers.java   
private static GaplessInfo parseMetaAtom(ParsableByteArray data) {
  data.skipBytes(Atom.FULL_HEADER_SIZE);
  ParsableByteArray ilst = new ParsableByteArray();
  while (data.bytesLeft() >= Atom.HEADER_SIZE) {
    int payloadSize = data.readInt() - Atom.HEADER_SIZE;
    int atomType = data.readInt();
    if (atomType == Atom.TYPE_ilst) {
      ilst.reset(data.data, data.getPosition() + payloadSize);
      ilst.setPosition(data.getPosition());
      GaplessInfo gaplessInfo = parseIlst(ilst);
      if (gaplessInfo != null) {
        return gaplessInfo;
      }
    }
    data.skipBytes(payloadSize);
  }
  return null;
}
项目:ExoPlayer-Demo    文件:VorbisUtilTest.java   
public void testReadIdHeader() throws Exception {
  byte[] data = TestData.getIdentificationHeaderData();
  ParsableByteArray headerData = new ParsableByteArray(data, data.length);

  VorbisUtil.VorbisIdHeader vorbisIdHeader =
      VorbisUtil.readVorbisIdentificationHeader(headerData);

  assertEquals(22050, vorbisIdHeader.sampleRate);
  assertEquals(0, vorbisIdHeader.version);
  assertTrue(vorbisIdHeader.framingFlag);
  assertEquals(2, vorbisIdHeader.channels);
  assertEquals(512, vorbisIdHeader.blockSize0);
  assertEquals(1024, vorbisIdHeader.blockSize1);
  assertEquals(-1, vorbisIdHeader.bitrateMax);
  assertEquals(-1, vorbisIdHeader.bitrateMin);
  assertEquals(66666, vorbisIdHeader.bitrateNominal);
  assertEquals(66666, vorbisIdHeader.getApproximateBitrate());
}
项目:miku    文件:AtomParsers.java   
private static Pair<List<byte[]>, Integer> parseAvcCFromParent(ParsableByteArray parent,
    int position) {
  parent.setPosition(position + Atom.HEADER_SIZE + 4);
  // Start of the AVCDecoderConfigurationRecord (defined in 14496-15)
  int nalUnitLengthFieldLength = (parent.readUnsignedByte() & 0x3) + 1;
  if (nalUnitLengthFieldLength == 3) {
    throw new IllegalStateException();
  }
  List<byte[]> initializationData = new ArrayList<>();
  // TODO: We should try and parse these using CodecSpecificDataUtil.parseSpsNalUnit, and
  // expose the AVC profile and level somewhere useful; Most likely in MediaFormat.
  int numSequenceParameterSets = parent.readUnsignedByte() & 0x1F;
  for (int j = 0; j < numSequenceParameterSets; j++) {
    initializationData.add(NalUnitUtil.parseChildNalUnit(parent));
  }
  int numPictureParameterSets = parent.readUnsignedByte();
  for (int j = 0; j < numPictureParameterSets; j++) {
    initializationData.add(NalUnitUtil.parseChildNalUnit(parent));
  }
  return Pair.create(initializationData, nalUnitLengthFieldLength);
}
项目:miku    文件:AtomParsers.java   
private static TrackEncryptionBox parseSinfFromParent(ParsableByteArray parent, int position,
    int size) {
  int childPosition = position + Atom.HEADER_SIZE;

  TrackEncryptionBox trackEncryptionBox = null;
  while (childPosition - position < size) {
    parent.setPosition(childPosition);
    int childAtomSize = parent.readInt();
    int childAtomType = parent.readInt();
    if (childAtomType == Atom.TYPE_frma) {
      parent.readInt(); // dataFormat.
    } else if (childAtomType == Atom.TYPE_schm) {
      parent.skipBytes(4);
      parent.readInt(); // schemeType. Expect cenc
      parent.readInt(); // schemeVersion. Expect 0x00010000
    } else if (childAtomType == Atom.TYPE_schi) {
      trackEncryptionBox = parseSchiFromParent(parent, childPosition, childAtomSize);
    }
    childPosition += childAtomSize;
  }

  return trackEncryptionBox;
}
项目:miku    文件:FragmentedMp4Extractor.java   
private static void parseSenc(ParsableByteArray senc, int offset, TrackFragment out) {
  senc.setPosition(Atom.HEADER_SIZE + offset);
  int fullAtom = senc.readInt();
  int flags = Atom.parseFullAtomFlags(fullAtom);

  if ((flags & 0x01 /* override_track_encryption_box_parameters */) != 0) {
    // TODO: Implement this.
    throw new IllegalStateException("Overriding TrackEncryptionBox parameters is unsupported");
  }

  boolean subsampleEncryption = (flags & 0x02 /* use_subsample_encryption */) != 0;
  int sampleCount = senc.readUnsignedIntToInt();
  if (sampleCount != out.length) {
    throw new IllegalStateException("Length mismatch: " + sampleCount + ", " + out.length);
  }

  Arrays.fill(out.sampleHasSubsampleEncryptionTable, 0, sampleCount, subsampleEncryption);
  out.initEncryptionData(senc.bytesLeft());
  out.fillEncryptionData(senc);
}
项目:ExoPlayer-Demo    文件:SeiReader.java   
public void consume(long pesTimeUs, ParsableByteArray seiBuffer) {
  int b;
  while (seiBuffer.bytesLeft() > 1 /* last byte will be rbsp_trailing_bits */) {
    // Parse payload type.
    int payloadType = 0;
    do {
      b = seiBuffer.readUnsignedByte();
      payloadType += b;
    } while (b == 0xFF);
    // Parse payload size.
    int payloadSize = 0;
    do {
      b = seiBuffer.readUnsignedByte();
      payloadSize += b;
    } while (b == 0xFF);
    // Process the payload.
    if (Eia608Parser.isSeiMessageEia608(payloadType, payloadSize, seiBuffer)) {
      output.sampleData(seiBuffer, payloadSize);
      output.sampleMetadata(pesTimeUs, C.SAMPLE_FLAG_SYNC, payloadSize, 0, null);
    } else {
      seiBuffer.skipBytes(payloadSize);
    }
  }
}
项目:miku    文件:FragmentedMp4Extractor.java   
private int appendSampleEncryptionData(ParsableByteArray sampleEncryptionData) {
  TrackEncryptionBox encryptionBox =
      track.sampleDescriptionEncryptionBoxes[fragmentRun.sampleDescriptionIndex];
  int vectorSize = encryptionBox.initializationVectorSize;
  boolean subsampleEncryption = fragmentRun.sampleHasSubsampleEncryptionTable[sampleIndex];

  // Write the signal byte, containing the vector size and the subsample encryption flag.
  encryptionSignalByte.data[0] = (byte) (vectorSize | (subsampleEncryption ? 0x80 : 0));
  encryptionSignalByte.setPosition(0);
  trackOutput.sampleData(encryptionSignalByte, 1);
  // Write the vector.
  trackOutput.sampleData(sampleEncryptionData, vectorSize);
  // If we don't have subsample encryption data, we're done.
  if (!subsampleEncryption) {
    return 1 + vectorSize;
  }
  // Write the subsample encryption data.
  int subsampleCount = sampleEncryptionData.readUnsignedShort();
  sampleEncryptionData.skipBytes(-2);
  int subsampleDataLength = 2 + 6 * subsampleCount;
  trackOutput.sampleData(sampleEncryptionData, subsampleDataLength);
  return 1 + vectorSize + subsampleDataLength;
}
项目:ExoPlayer-Demo    文件:AtomParsers.java   
/**
 * Parses a udta atom.
 *
 * @param udtaAtom The udta (user data) atom to parse.
 * @param isQuickTime True for QuickTime media. False otherwise.
 * @return Gapless playback information stored in the user data, or {@code null} if not present.
 */
public static GaplessInfo 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
    // parse one.
    return null;
  }
  ParsableByteArray udtaData = udtaAtom.data;
  udtaData.setPosition(Atom.HEADER_SIZE);
  while (udtaData.bytesLeft() >= Atom.HEADER_SIZE) {
    int atomSize = udtaData.readInt();
    int atomType = udtaData.readInt();
    if (atomType == Atom.TYPE_meta) {
      udtaData.setPosition(udtaData.getPosition() - Atom.HEADER_SIZE);
      udtaData.setLimit(udtaData.getPosition() + atomSize);
      return parseMetaAtom(udtaData);
    } else {
      udtaData.skipBytes(atomSize - Atom.HEADER_SIZE);
    }
  }
  return null;
}
项目:ExoPlayer-Demo    文件:WebmExtractor.java   
/**
 * Parses an MS/ACM codec private, returning whether it indicates PCM audio.
 *
 * @return True if the codec private indicates PCM audio. False otherwise.
 * @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");
  }
}
项目:ExoPlayer-Demo    文件:WebmExtractor.java   
/**
 * Builds initialization data for a {@link MediaFormat} from H.264 (AVC) codec private data.
 *
 * @return The initialization data for the {@link MediaFormat}.
 * @throws ParserException If the initialization data could not be built.
 */
private static Pair<List<byte[]>, Integer> parseAvcCodecPrivate(ParsableByteArray buffer)
    throws ParserException {
  try {
    // TODO: Deduplicate with AtomParsers.parseAvcCFromParent.
    buffer.setPosition(4);
    int nalUnitLengthFieldLength = (buffer.readUnsignedByte() & 0x03) + 1;
    if (nalUnitLengthFieldLength == 3) {
      throw new ParserException();
    }
    List<byte[]> initializationData = new ArrayList<>();
    int numSequenceParameterSets = buffer.readUnsignedByte() & 0x1F;
    for (int i = 0; i < numSequenceParameterSets; i++) {
      initializationData.add(NalUnitUtil.parseChildNalUnit(buffer));
    }
    int numPictureParameterSets = buffer.readUnsignedByte();
    for (int j = 0; j < numPictureParameterSets; j++) {
      initializationData.add(NalUnitUtil.parseChildNalUnit(buffer));
    }
    return Pair.create(initializationData, nalUnitLengthFieldLength);
  } catch (ArrayIndexOutOfBoundsException e) {
    throw new ParserException("Error parsing AVC codec private");
  }
}
项目:ExoPlayer-Demo    文件:FragmentedMp4Extractor.java   
/**
 * Parses a saio atom (defined in 14496-12).
 *
 * @param saio The saio atom to parse.
 * @param out The {@link TrackFragment} to populate with data from the saio atom.
 */
private static void parseSaio(ParsableByteArray saio, TrackFragment out) throws ParserException {
  saio.setPosition(Atom.HEADER_SIZE);
  int fullAtom = saio.readInt();
  int flags = Atom.parseFullAtomFlags(fullAtom);
  if ((flags & 0x01) == 1) {
    saio.skipBytes(8);
  }

  int entryCount = saio.readUnsignedIntToInt();
  if (entryCount != 1) {
    // We only support one trun element currently, so always expect one entry.
    throw new ParserException("Unexpected saio entry count: " + entryCount);
  }

  int version = Atom.parseFullAtomVersion(fullAtom);
  out.auxiliaryDataPosition +=
      version == 0 ? saio.readUnsignedInt() : saio.readUnsignedLongToLong();
}
项目:ExoPlayer-Demo    文件: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;
  }
}
项目:miku    文件:RollingSampleBuffer.java   
/**
 * @param allocator An {@link Allocator} from which allocations for sample data can be obtained.
 */
public RollingSampleBuffer(Allocator allocator) {
  this.allocator = allocator;
  allocationLength = allocator.getIndividualAllocationLength();
  infoQueue = new InfoQueue();
  dataQueue = new LinkedBlockingDeque<>();
  extrasHolder = new SampleExtrasHolder();
  scratch = new ParsableByteArray(INITIAL_SCRATCH_SIZE);
  lastAllocationOffset = allocationLength;
}
项目:ExoPlayer-Demo    文件:Id3Parser.java   
/**
 * Parses an ID3 header.
 *
 * @param id3Buffer A {@link ParsableByteArray} from which data should be read.
 * @return The size of ID3 frames in bytes, excluding the header and footer.
 * @throws ParserException If ID3 file identifier != "ID3".
 */
private static int parseId3Header(ParsableByteArray id3Buffer) throws ParserException {
  int id1 = id3Buffer.readUnsignedByte();
  int id2 = id3Buffer.readUnsignedByte();
  int id3 = id3Buffer.readUnsignedByte();
  if (id1 != 'I' || id2 != 'D' || id3 != '3') {
    throw new ParserException(String.format(Locale.US,
        "Unexpected ID3 file identifier, expected \"ID3\", actual \"%c%c%c\".", id1, id2, id3));
  }
  id3Buffer.skipBytes(2); // Skip version.

  int flags = id3Buffer.readUnsignedByte();
  int id3Size = id3Buffer.readSynchSafeInt();

  // Check if extended header presents.
  if ((flags & 0x2) != 0) {
    int extendedHeaderSize = id3Buffer.readSynchSafeInt();
    if (extendedHeaderSize > 4) {
      id3Buffer.skipBytes(extendedHeaderSize - 4);
    }
    id3Size -= extendedHeaderSize;
  }

  // Check if footer presents.
  if ((flags & 0x8) != 0) {
    id3Size -= 10;
  }

  return id3Size;
}
项目:miku    文件:RollingSampleBuffer.java   
/**
 * Appends data to the rolling buffer.
 *
 * @param buffer A buffer containing the data to append.
 * @param length The length of the data to append.
 */
public void appendData(ParsableByteArray buffer, int length) {
  while (length > 0) {
    int thisAppendLength = prepareForAppend(length);
    buffer.readBytes(lastAllocation.data, lastAllocation.translateOffset(lastAllocationOffset),
        thisAppendLength);
    lastAllocationOffset += thisAppendLength;
    totalBytesWritten += thisAppendLength;
    length -= thisAppendLength;
  }
}
项目:miku    文件:H264Reader.java   
public H264Reader(TrackOutput output, SeiReader seiReader, boolean idrKeyframesOnly) {
  super(output);
  this.seiReader = seiReader;
  prefixFlags = new boolean[3];
  ifrParserBuffer = (idrKeyframesOnly) ? null : new IfrParserBuffer();
  sps = new NalUnitTargetBuffer(NAL_UNIT_TYPE_SPS, 128);
  pps = new NalUnitTargetBuffer(NAL_UNIT_TYPE_PPS, 128);
  sei = new NalUnitTargetBuffer(NAL_UNIT_TYPE_SEI, 128);
  seiWrapper = new ParsableByteArray();
}
项目:miku    文件:Ac3Reader.java   
@Override
public void consume(ParsableByteArray data, long pesTimeUs, boolean startOfPacket) {
  if (startOfPacket) {
    timeUs = pesTimeUs;
  }
  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.SAMPLE_FLAG_SYNC, sampleSize, 0, null);
          timeUs += frameDurationUs;
          state = STATE_FINDING_SYNC;
        }
        break;
    }
  }
}
项目:ExoPlayer-Demo    文件:WebvttCueParser.java   
/**
 * Parses the next valid WebVTT cue in a parsable array, including timestamps, settings and text.
 *
 * @param webvttData Parsable WebVTT file data.
 * @param builder Builder for WebVTT Cues.
 * @return True if a valid Cue was found, false otherwise.
 */
/* package */ boolean parseNextValidCue(ParsableByteArray webvttData, WebvttCue.Builder builder) {
  Matcher cueHeaderMatcher;
  while ((cueHeaderMatcher = findNextCueHeader(webvttData)) != null) {
    if (parseCue(cueHeaderMatcher, webvttData, builder, textBuilder)) {
      return true;
    }
  }
  return false;
}
项目:ExoPlayer-Demo    文件:XingSeeker.java   
/**
 * Returns a {@link XingSeeker} 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 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
 *    'Xing' or 'Info' tag.
 * @param position The position (byte offset) of the start of this frame in the stream.
 * @param inputLength The length of the stream in bytes.
 * @return A {@link XingSeeker} for seeking in the stream, or {@code null} if the required
 *     information is not present.
 */
public static XingSeeker create(MpegAudioHeader mpegAudioHeader, ParsableByteArray frame,
    long position, long inputLength) {
  int samplesPerFrame = mpegAudioHeader.samplesPerFrame;
  int sampleRate = mpegAudioHeader.sampleRate;
  long firstFramePosition = position + mpegAudioHeader.frameSize;

  int flags = frame.readInt();
  int frameCount;
  if ((flags & 0x01) != 0x01 || (frameCount = frame.readUnsignedIntToInt()) == 0) {
    // If the frame count is missing/invalid, the header can't be used to determine the duration.
    return null;
  }
  long durationUs = Util.scaleLargeTimestamp(frameCount, samplesPerFrame * C.MICROS_PER_SECOND,
      sampleRate);
  if ((flags & 0x06) != 0x06) {
    // If the size in bytes or table of contents is missing, the stream is not seekable.
    return new XingSeeker(firstFramePosition, durationUs, inputLength);
  }

  long sizeBytes = frame.readUnsignedIntToInt();
  frame.skipBytes(1);
  long[] tableOfContents = new long[99];
  for (int i = 0; i < 99; i++) {
    tableOfContents[i] = frame.readUnsignedByte();
  }

  // TODO: Handle encoder delay and padding in 3 bytes offset by xingBase + 213 bytes:
  // delay = (frame.readUnsignedByte() << 4) + (frame.readUnsignedByte() >> 4);
  // padding = ((frame.readUnsignedByte() & 0x0F) << 8) + frame.readUnsignedByte();
  return new XingSeeker(firstFramePosition, durationUs, inputLength, tableOfContents,
      sizeBytes, mpegAudioHeader.frameSize);
}
项目:ExoPlayer-Demo    文件: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.SAMPLE_FLAG_SYNC, sampleSize, 0, null);
    timeUs += currentSampleDuration;
    setFindingSampleState();
  }
}
项目:ExoPlayer-Demo    文件:FragmentedMp4Extractor.java   
private static void parseUuid(ParsableByteArray uuid, TrackFragment out,
    byte[] extendedTypeScratch) throws ParserException {
  uuid.setPosition(Atom.HEADER_SIZE);
  uuid.readBytes(extendedTypeScratch, 0, 16);

  // Currently this parser only supports Microsoft's PIFF SampleEncryptionBox.
  if (!Arrays.equals(extendedTypeScratch, PIFF_SAMPLE_ENCRYPTION_BOX_EXTENDED_TYPE)) {
    return;
  }

  // Except for the extended type, this box is identical to a SENC box. See "Portable encoding of
  // audio-video objects: The Protected Interoperable File Format (PIFF), John A. Bocharov et al,
  // Section 5.3.2.1."
  parseSenc(uuid, 16, out);
}
项目:miku    文件:MpegAudioReader.java   
/**
 * Attempts to read the remainder of the frame.
 * <p>
 * If a frame is read in full then true is returned. The frame will have been output, and the
 * position of the source will have been advanced to the byte that immediately follows the end of
 * the frame.
 * <p>
 * If a frame is not read in full then the position of the source will have been advanced to the
 * limit, and the method should be called again with the next source to continue the read.
 *
 * @param source The source from which to read.
 */
private void readFrameRemainder(ParsableByteArray source) {
  int bytesToRead = Math.min(source.bytesLeft(), frameSize - frameBytesRead);
  output.sampleData(source, bytesToRead);
  frameBytesRead += bytesToRead;
  if (frameBytesRead < frameSize) {
    // We haven't read the whole of the frame yet.
    return;
  }

  output.sampleMetadata(timeUs, C.SAMPLE_FLAG_SYNC, frameSize, 0, null);
  timeUs += frameDurationUs;
  frameBytesRead = 0;
  state = STATE_FINDING_HEADER;
}
项目:miku    文件:H265Reader.java   
public H265Reader(TrackOutput output, SeiReader seiReader) {
  super(output);
  this.seiReader = seiReader;
  prefixFlags = new boolean[3];
  vps = new NalUnitTargetBuffer(VPS_NUT, 128);
  sps = new NalUnitTargetBuffer(SPS_NUT, 128);
  pps = new NalUnitTargetBuffer(PPS_NUT, 128);
  prefixSei = new NalUnitTargetBuffer(PREFIX_SEI_NUT, 128);
  suffixSei = new NalUnitTargetBuffer(SUFFIX_SEI_NUT, 128);
  seiWrapper = new ParsableByteArray();
}
项目:ExoPlayer-Demo    文件:XingSeekerTest.java   
@Override
public void setUp() throws Exception {
  MpegAudioHeader xingFrameHeader = new MpegAudioHeader();
  MpegAudioHeader.populateHeader(XING_FRAME_HEADER_DATA, xingFrameHeader);
  seeker = XingSeeker.create(xingFrameHeader, new ParsableByteArray(XING_FRAME_PAYLOAD),
      XING_FRAME_POSITION, C.UNKNOWN_TIME_US);
  seekerWithInputLength = XingSeeker.create(xingFrameHeader,
      new ParsableByteArray(XING_FRAME_PAYLOAD), XING_FRAME_POSITION, INPUT_LENGTH);
  xingFrameSize = xingFrameHeader.frameSize;
}
项目:miku    文件:AdtsReader.java   
@Override
public void consume(ParsableByteArray data, long pesTimeUs, boolean startOfPacket) {
  if (startOfPacket) {
    timeUs = pesTimeUs;
  }
  while (data.bytesLeft() > 0) {
    switch (state) {
      case STATE_FINDING_SYNC:
        if (skipToNextSync(data)) {
          bytesRead = 0;
          state = STATE_READING_HEADER;
        }
        break;
      case STATE_READING_HEADER:
        int targetLength = hasCrc ? HEADER_SIZE + CRC_SIZE : HEADER_SIZE;
        if (continueRead(data, adtsScratch.data, targetLength)) {
          parseHeader();
          bytesRead = 0;
          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.SAMPLE_FLAG_SYNC, sampleSize, 0, null);
          timeUs += frameDurationUs;
          bytesRead = 0;
          state = STATE_FINDING_SYNC;
        }
        break;
    }
  }
}
项目:ExoPlayer-Demo    文件:FragmentedMp4Extractor.java   
/**
 * Appends the corresponding encryption data to the {@link TrackOutput} contained in the given
 * {@link TrackBundle}.
 *
 * @param trackBundle The {@link TrackBundle} that contains the {@link Track} for which the
 *     Sample encryption data must be output.
 * @return The number of written bytes.
 */
private int appendSampleEncryptionData(TrackBundle trackBundle) {
  TrackFragment trackFragment = trackBundle.fragment;
  ParsableByteArray sampleEncryptionData = trackFragment.sampleEncryptionData;
  int sampleDescriptionIndex = trackFragment.header.sampleDescriptionIndex;
  TrackEncryptionBox encryptionBox = trackFragment.trackEncryptionBox != null
      ? trackFragment.trackEncryptionBox
      : trackBundle.track.sampleDescriptionEncryptionBoxes[sampleDescriptionIndex];
  int vectorSize = encryptionBox.initializationVectorSize;
  boolean subsampleEncryption = trackFragment
      .sampleHasSubsampleEncryptionTable[trackBundle.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);
  TrackOutput output = trackBundle.output;
  output.sampleData(encryptionSignalByte, 1);
  // Write the vector.
  output.sampleData(sampleEncryptionData, vectorSize);
  // If we don't have subsample encryption data, we're done.
  if (!subsampleEncryption) {
    return 1 + vectorSize;
  }
  // Write the subsample encryption data.
  int subsampleCount = sampleEncryptionData.readUnsignedShort();
  sampleEncryptionData.skipBytes(-2);
  int subsampleDataLength = 2 + 6 * subsampleCount;
  output.sampleData(sampleEncryptionData, subsampleDataLength);
  return 1 + vectorSize + subsampleDataLength;
}
项目:miku    文件:AtomParsers.java   
/**
 * 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();
}
项目:miku    文件:AtomParsers.java   
/**
 * Parses an mdhd atom (defined in 14496-12).
 *
 * @param mdhd The mdhd atom to parse.
 * @return The media timescale, defined as the number of time units that pass in one second.
 */
private static long parseMdhd(ParsableByteArray mdhd) {
  mdhd.setPosition(Atom.HEADER_SIZE);
  int fullAtom = mdhd.readInt();
  int version = Atom.parseFullAtomVersion(fullAtom);

  mdhd.skipBytes(version == 0 ? 8 : 16);
  return mdhd.readUnsignedInt();
}
项目:miku    文件:AtomParsers.java   
private static StsdDataHolder parseStsd(ParsableByteArray stsd, long durationUs) {
  stsd.setPosition(Atom.FULL_HEADER_SIZE);
  int numberOfEntries = stsd.readInt();
  StsdDataHolder holder = new StsdDataHolder(numberOfEntries);
  for (int i = 0; i < numberOfEntries; i++) {
    int childStartPosition = stsd.getPosition();
    int childAtomSize = stsd.readInt();
    Assertions.checkArgument(childAtomSize > 0, "childAtomSize should be positive");
    int childAtomType = stsd.readInt();
    if (childAtomType == Atom.TYPE_avc1 || childAtomType == Atom.TYPE_avc3
        || childAtomType == Atom.TYPE_encv || childAtomType == Atom.TYPE_mp4v
        || childAtomType == Atom.TYPE_hvc1 || childAtomType == Atom.TYPE_hev1
        || childAtomType == Atom.TYPE_s263) {
      parseVideoSampleEntry(stsd, childStartPosition, childAtomSize, durationUs, holder, i);
    } else if (childAtomType == Atom.TYPE_mp4a || childAtomType == Atom.TYPE_enca
        || childAtomType == Atom.TYPE_ac_3) {
      parseAudioSampleEntry(stsd, childAtomType, childStartPosition, childAtomSize, durationUs,
          holder, i);
    } else if (childAtomType == Atom.TYPE_TTML) {
      holder.mediaFormat = MediaFormat.createTextFormat(MimeTypes.APPLICATION_TTML, durationUs);
    } else if (childAtomType == Atom.TYPE_tx3g) {
      holder.mediaFormat = MediaFormat.createTextFormat(MimeTypes.APPLICATION_TX3G, durationUs);
    }
    stsd.setPosition(childStartPosition + childAtomSize);
  }
  return holder;
}
项目:ExoPlayer-Demo    文件:Id3Parser.java   
private static TextInformationFrame parseTextInformationFrame(ParsableByteArray id3Data,
    int frameSize, String id) throws UnsupportedEncodingException {
  int encoding = id3Data.readUnsignedByte();
  String charset = getCharsetName(encoding);

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

  int descriptionEndIndex = indexOfEos(data, 0, encoding);
  String description = new String(data, 0, descriptionEndIndex, charset);

  return new TextInformationFrame(id, description);
}
项目:ExoPlayer-Demo    文件:FragmentedMp4Extractor.java   
private static void parseSaiz(TrackEncryptionBox encryptionBox, ParsableByteArray saiz,
    TrackFragment out) throws ParserException {
  int vectorSize = encryptionBox.initializationVectorSize;
  saiz.setPosition(Atom.HEADER_SIZE);
  int fullAtom = saiz.readInt();
  int flags = Atom.parseFullAtomFlags(fullAtom);
  if ((flags & 0x01) == 1) {
    saiz.skipBytes(8);
  }
  int defaultSampleInfoSize = saiz.readUnsignedByte();

  int sampleCount = saiz.readUnsignedIntToInt();
  if (sampleCount != out.length) {
    throw new ParserException("Length mismatch: " + sampleCount + ", " + out.length);
  }

  int totalSize = 0;
  if (defaultSampleInfoSize == 0) {
    boolean[] sampleHasSubsampleEncryptionTable = out.sampleHasSubsampleEncryptionTable;
    for (int i = 0; i < sampleCount; i++) {
      int sampleInfoSize = saiz.readUnsignedByte();
      totalSize += sampleInfoSize;
      sampleHasSubsampleEncryptionTable[i] = sampleInfoSize > vectorSize;
    }
  } else {
    boolean subsampleEncryption = defaultSampleInfoSize > vectorSize;
    totalSize += defaultSampleInfoSize * sampleCount;
    Arrays.fill(out.sampleHasSubsampleEncryptionTable, 0, sampleCount, subsampleEncryption);
  }
  out.initEncryptionData(totalSize);
}
项目:ExoPlayer-Demo    文件:VideoTagPayloadReader.java   
/**
 * Builds initialization data for a {@link MediaFormat} from H.264 (AVC) codec private data.
 *
 * @return The AvcSequenceHeader data needed to initialize the video codec.
 * @throws ParserException If the initialization data could not be built.
 */
private AvcSequenceHeaderData parseAvcCodecPrivate(ParsableByteArray buffer)
    throws ParserException {
  // TODO: Deduplicate with AtomParsers.parseAvcCFromParent.
  buffer.setPosition(4);
  int nalUnitLengthFieldLength = (buffer.readUnsignedByte() & 0x03) + 1;
  Assertions.checkState(nalUnitLengthFieldLength != 3);
  List<byte[]> initializationData = new ArrayList<>();
  int numSequenceParameterSets = buffer.readUnsignedByte() & 0x1F;
  for (int i = 0; i < numSequenceParameterSets; i++) {
    initializationData.add(NalUnitUtil.parseChildNalUnit(buffer));
  }
  int numPictureParameterSets = buffer.readUnsignedByte();
  for (int j = 0; j < numPictureParameterSets; j++) {
    initializationData.add(NalUnitUtil.parseChildNalUnit(buffer));
  }

  float pixelWidthAspectRatio = 1;
  int width = MediaFormat.NO_VALUE;
  int height = MediaFormat.NO_VALUE;
  if (numSequenceParameterSets > 0) {
    // Parse the first sequence parameter set to obtain pixelWidthAspectRatio.
    ParsableBitArray spsDataBitArray = new ParsableBitArray(initializationData.get(0));
    // Skip the NAL header consisting of the nalUnitLengthField and the type (1 byte).
    spsDataBitArray.setPosition(8 * (nalUnitLengthFieldLength + 1));
    NalUnitUtil.SpsData sps = NalUnitUtil.parseSpsNalUnit(spsDataBitArray);
    width = sps.width;
    height = sps.height;
    pixelWidthAspectRatio = sps.pixelWidthAspectRatio;
  }

  return new AvcSequenceHeaderData(initializationData, nalUnitLengthFieldLength,
      width, height, pixelWidthAspectRatio);
}
项目:miku    文件:FragmentedMp4Extractor.java   
/**
 * Parses a trex atom (defined in 14496-12).
 */
private static DefaultSampleValues parseTrex(ParsableByteArray trex) {
  trex.setPosition(Atom.FULL_HEADER_SIZE + 4);
  int defaultSampleDescriptionIndex = trex.readUnsignedIntToInt() - 1;
  int defaultSampleDuration = trex.readUnsignedIntToInt();
  int defaultSampleSize = trex.readUnsignedIntToInt();
  int defaultSampleFlags = trex.readInt();
  return new DefaultSampleValues(defaultSampleDescriptionIndex, defaultSampleDuration,
      defaultSampleSize, defaultSampleFlags);
}
项目:ExoPlayer-Demo    文件:DtsReader.java   
@Override
public void consume(ParsableByteArray data) {
  while (data.bytesLeft() > 0) {
    switch (state) {
      case STATE_FINDING_SYNC:
        if (skipToNextSync(data)) {
          bytesRead = SYNC_VALUE_SIZE;
          state = STATE_READING_HEADER;
        }
        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.SAMPLE_FLAG_SYNC, sampleSize, 0, null);
          timeUs += sampleDurationUs;
          state = STATE_FINDING_SYNC;
        }
        break;
    }
  }
}
项目:miku    文件:FragmentedMp4Extractor.java   
/**
 * 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();
}