Java 类com.google.android.exoplayer2.ParserException 实例源码

项目:Exoplayer2Radio    文件:HlsPlaylistTracker.java   
@Override
public int onLoadError(ParsingLoadable<HlsPlaylist> loadable, long elapsedRealtimeMs,
    long loadDurationMs, IOException error) {
  boolean isFatal = error instanceof ParserException;
  eventDispatcher.loadError(loadable.dataSpec, C.DATA_TYPE_MANIFEST, elapsedRealtimeMs,
      loadDurationMs, loadable.bytesLoaded(), error, isFatal);
  if (isFatal) {
    return Loader.DONT_RETRY_FATAL;
  }
  boolean shouldRetry = true;
  if (ChunkedTrackBlacklistUtil.shouldBlacklist(error)) {
    blacklistUntilMs =
        SystemClock.elapsedRealtime() + ChunkedTrackBlacklistUtil.DEFAULT_TRACK_BLACKLIST_MS;
    notifyPlaylistBlacklisting(playlistUrl,
        ChunkedTrackBlacklistUtil.DEFAULT_TRACK_BLACKLIST_MS);
    shouldRetry = primaryHlsUrl == playlistUrl && !maybeSelectNewPrimaryUrl();
  }
  return shouldRetry ? Loader.RETRY : Loader.DONT_RETRY;
}
项目:Exoplayer2Radio    文件:VorbisUtil.java   
/**
 * Reads a vorbis identification header from {@code headerData}.
 *
 * @see <a href="https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-630004.2.2">Vorbis
 *     spec/Identification header</a>
 * @param headerData a {@link ParsableByteArray} wrapping the header data.
 * @return a {@link VorbisUtil.VorbisIdHeader} with meta data.
 * @throws ParserException thrown if invalid capture pattern is detected.
 */
public static VorbisIdHeader readVorbisIdentificationHeader(ParsableByteArray headerData)
    throws ParserException {

  verifyVorbisHeaderCapturePattern(0x01, headerData, false);

  long version = headerData.readLittleEndianUnsignedInt();
  int channels = headerData.readUnsignedByte();
  long sampleRate = headerData.readLittleEndianUnsignedInt();
  int bitrateMax = headerData.readLittleEndianInt();
  int bitrateNominal = headerData.readLittleEndianInt();
  int bitrateMin = headerData.readLittleEndianInt();

  int blockSize = headerData.readUnsignedByte();
  int blockSize0 = (int) Math.pow(2, blockSize & 0x0F);
  int blockSize1 = (int) Math.pow(2, (blockSize & 0xF0) >> 4);

  boolean framingFlag = (headerData.readUnsignedByte() & 0x01) > 0;
  // raw data of vorbis setup header has to be passed to decoder as CSD buffer #1
  byte[] data = Arrays.copyOf(headerData.data, headerData.limit());

  return new VorbisIdHeader(version, channels, sampleRate, bitrateMax, bitrateNominal, bitrateMin,
      blockSize0, blockSize1, framingFlag, data);
}
项目: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    文件:Mp4Extractor.java   
private void processAtomEnded(long atomEndPosition) throws ParserException {
  while (!containerAtoms.isEmpty() && containerAtoms.peek().endPosition == atomEndPosition) {
    Atom.ContainerAtom containerAtom = containerAtoms.pop();
    if (containerAtom.type == Atom.TYPE_moov) {
      // We've reached the end of the moov atom. Process it and prepare to read samples.
      processMoovAtom(containerAtom);
      containerAtoms.clear();
      parserState = STATE_READING_SAMPLE;
    } else if (!containerAtoms.isEmpty()) {
      containerAtoms.peek().add(containerAtom);
    }
  }
  if (parserState != STATE_READING_SAMPLE) {
    enterReadingAtomHeaderState();
  }
}
项目:Exoplayer2Radio    文件:FragmentedMp4Extractor.java   
/**
 * Parses a saio atom (defined in 14496-12).
 *
 * @param saio The saio atom to decode.
 * @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();
}
项目:Exoplayer2Radio    文件:FragmentedMp4Extractor.java   
private static void parseSenc(ParsableByteArray senc, int offset, TrackFragment out)
    throws ParserException {
  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 ParserException("Overriding TrackEncryptionBox parameters is unsupported.");
  }

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

  Arrays.fill(out.sampleHasSubsampleEncryptionTable, 0, sampleCount, subsampleEncryption);
  out.initEncryptionData(senc.bytesLeft());
  out.fillEncryptionData(senc);
}
项目:Exoplayer2Radio    文件:FragmentedMp4Extractor.java   
private void readEncryptionData(ExtractorInput input) throws IOException, InterruptedException {
  TrackBundle nextTrackBundle = null;
  long nextDataOffset = Long.MAX_VALUE;
  int trackBundlesSize = trackBundles.size();
  for (int i = 0; i < trackBundlesSize; i++) {
    TrackFragment trackFragment = trackBundles.valueAt(i).fragment;
    if (trackFragment.sampleEncryptionDataNeedsFill
        && trackFragment.auxiliaryDataPosition < nextDataOffset) {
      nextDataOffset = trackFragment.auxiliaryDataPosition;
      nextTrackBundle = trackBundles.valueAt(i);
    }
  }
  if (nextTrackBundle == null) {
    parserState = STATE_READING_SAMPLE_START;
    return;
  }
  int bytesToSkip = (int) (nextDataOffset - input.getPosition());
  if (bytesToSkip < 0) {
    throw new ParserException("Offset to encryption data was negative.");
  }
  input.skipFully(bytesToSkip);
  nextTrackBundle.fragment.fillEncryptionData(input);
}
项目:Exoplayer2Radio    文件:MatroskaExtractor.java   
void stringElement(int id, String value) throws ParserException {
  switch (id) {
    case ID_DOC_TYPE:
      // Validate that DocType is supported.
      if (!DOC_TYPE_WEBM.equals(value) && !DOC_TYPE_MATROSKA.equals(value)) {
        throw new ParserException("DocType " + value + " not supported");
      }
      break;
    case ID_CODEC_ID:
      currentTrack.codecId = value;
      break;
    case ID_LANGUAGE:
      currentTrack.language = value;
      break;
    default:
      break;
  }
}
项目: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    文件: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    文件:RawCcExtractor.java   
private boolean parseTimestampAndSampleCount(ExtractorInput input) throws IOException,
    InterruptedException {
  dataScratch.reset();
  if (version == 0) {
    if (!input.readFully(dataScratch.data, 0, TIMESTAMP_SIZE_V0 + 1, true)) {
      return false;
    }
    // version 0 timestamps are 45kHz, so we need to convert them into us
    timestampUs = dataScratch.readUnsignedInt() * 1000 / 45;
  } else if (version == 1) {
    if (!input.readFully(dataScratch.data, 0, TIMESTAMP_SIZE_V1 + 1, true)) {
      return false;
    }
    timestampUs = dataScratch.readLong();
  } else {
    throw new ParserException("Unsupported version number: " + version);
  }

  remainingSampleCount = dataScratch.readUnsignedByte();
  sampleBytesWritten = 0;
  return true;
}
项目:no-player    文件:ExoPlayerErrorMapper.java   
static NoPlayer.PlayerError errorFor(Exception e) {
    if (e instanceof HttpDataSource.InvalidResponseCodeException) {
        return new NoPlayerError(PlayerErrorType.INVALID_RESPONSE_CODE, formatMessage(e));
    }

    if (e instanceof ParserException) {
        return new NoPlayerError(PlayerErrorType.MALFORMED_CONTENT, formatMessage(e));
    }

    Throwable cause = e.getCause();
    if (e.getCause() instanceof MediaCodec.CryptoException) {
        return new NoPlayerError(PlayerErrorType.FAILED_DRM_DECRYPTION, formatMessage(e));
    }

    if (cause instanceof StreamingModularDrm.DrmRequestException) {
        return new NoPlayerError(PlayerErrorType.FAILED_DRM_REQUEST, formatMessage(e));
    }

    if (e instanceof IOException || cause instanceof IOException) {
        return new NoPlayerError(PlayerErrorType.CONNECTIVITY_ERROR, cause == null ? formatMessage(e) : formatMessage(cause));
    }
    return new NoPlayerError(PlayerErrorType.UNKNOWN, formatMessage(e));
}
项目:videoPickPlayer    文件:SsManifestParser.java   
private void parseStreamElementStartTag(XmlPullParser parser) throws ParserException {
  type = parseType(parser);
  putNormalizedAttribute(KEY_TYPE, type);
  if (type == C.TRACK_TYPE_TEXT) {
    subType = parseRequiredString(parser, KEY_SUB_TYPE);
  } else {
    subType = parser.getAttributeValue(null, KEY_SUB_TYPE);
  }
  name = parser.getAttributeValue(null, KEY_NAME);
  url = parseRequiredString(parser, KEY_URL);
  maxWidth = parseInt(parser, KEY_MAX_WIDTH, Format.NO_VALUE);
  maxHeight = parseInt(parser, KEY_MAX_HEIGHT, Format.NO_VALUE);
  displayWidth = parseInt(parser, KEY_DISPLAY_WIDTH, Format.NO_VALUE);
  displayHeight = parseInt(parser, KEY_DISPLAY_HEIGHT, Format.NO_VALUE);
  language = parser.getAttributeValue(null, KEY_LANGUAGE);
  putNormalizedAttribute(KEY_LANGUAGE, language);
  timescale = parseInt(parser, KEY_TIME_SCALE, -1);
  if (timescale == -1) {
    timescale = (Long) getNormalizedAttribute(KEY_TIME_SCALE);
  }
  startTimes = new ArrayList<>();
}
项目:K-Sonic    文件:FragmentedMp4Extractor.java   
private static void parseSenc(ParsableByteArray senc, int offset, TrackFragment out)
    throws ParserException {
  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 ParserException("Overriding TrackEncryptionBox parameters is unsupported.");
  }

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

  Arrays.fill(out.sampleHasSubsampleEncryptionTable, 0, sampleCount, subsampleEncryption);
  out.initEncryptionData(senc.bytesLeft());
  out.fillEncryptionData(senc);
}
项目:videoPickPlayer    文件:FragmentedMp4Extractor.java   
private static void parseSenc(ParsableByteArray senc, int offset, TrackFragment out)
    throws ParserException {
  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 ParserException("Overriding TrackEncryptionBox parameters is unsupported.");
  }

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

  Arrays.fill(out.sampleHasSubsampleEncryptionTable, 0, sampleCount, subsampleEncryption);
  out.initEncryptionData(senc.bytesLeft());
  out.fillEncryptionData(senc);
}
项目:K-Sonic    文件: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");
  }
}
项目:K-Sonic    文件:HlsPlaylistTracker.java   
@Override
public int onLoadError(ParsingLoadable<HlsPlaylist> loadable, long elapsedRealtimeMs,
    long loadDurationMs, IOException error) {
  boolean isFatal = error instanceof ParserException;
  eventDispatcher.loadError(loadable.dataSpec, C.DATA_TYPE_MANIFEST, elapsedRealtimeMs,
      loadDurationMs, loadable.bytesLoaded(), error, isFatal);
  if (isFatal) {
    return Loader.DONT_RETRY_FATAL;
  }
  boolean shouldRetry = true;
  if (ChunkedTrackBlacklistUtil.shouldBlacklist(error)) {
    blacklistUntilMs =
        SystemClock.elapsedRealtime() + ChunkedTrackBlacklistUtil.DEFAULT_TRACK_BLACKLIST_MS;
    notifyPlaylistBlacklisting(playlistUrl,
        ChunkedTrackBlacklistUtil.DEFAULT_TRACK_BLACKLIST_MS);
    shouldRetry = primaryHlsUrl == playlistUrl && !maybeSelectNewPrimaryUrl();
  }
  return shouldRetry ? Loader.RETRY : Loader.DONT_RETRY;
}
项目:videoPickPlayer    文件: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");
  }
}
项目:K-Sonic    文件:SsManifestParser.java   
private void parseStreamElementStartTag(XmlPullParser parser) throws ParserException {
  type = parseType(parser);
  putNormalizedAttribute(KEY_TYPE, type);
  if (type == C.TRACK_TYPE_TEXT) {
    subType = parseRequiredString(parser, KEY_SUB_TYPE);
  } else {
    subType = parser.getAttributeValue(null, KEY_SUB_TYPE);
  }
  name = parser.getAttributeValue(null, KEY_NAME);
  url = parseRequiredString(parser, KEY_URL);
  maxWidth = parseInt(parser, KEY_MAX_WIDTH, Format.NO_VALUE);
  maxHeight = parseInt(parser, KEY_MAX_HEIGHT, Format.NO_VALUE);
  displayWidth = parseInt(parser, KEY_DISPLAY_WIDTH, Format.NO_VALUE);
  displayHeight = parseInt(parser, KEY_DISPLAY_HEIGHT, Format.NO_VALUE);
  language = parser.getAttributeValue(null, KEY_LANGUAGE);
  putNormalizedAttribute(KEY_LANGUAGE, language);
  timescale = parseInt(parser, KEY_TIME_SCALE, -1);
  if (timescale == -1) {
    timescale = (Long) getNormalizedAttribute(KEY_TIME_SCALE);
  }
  startTimes = new ArrayList<>();
}
项目:videoPickPlayer    文件: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;
  }
}
项目:ExoPlayer-Offline    文件:SampleChooserActivity.java   
private void readSampleGroup(JsonReader reader, List<SampleGroup> groups) throws IOException {
  String groupName = "";
  ArrayList<Sample> samples = new ArrayList<>();

  reader.beginObject();
  while (reader.hasNext()) {
    String name = reader.nextName();
    switch (name) {
      case "name":
        groupName = reader.nextString();
        break;
      case "samples":
        reader.beginArray();
        while (reader.hasNext()) {
          samples.add(readEntry(reader, false));
        }
        reader.endArray();
        break;
      case "offline_samples":
        reader.beginArray();
        while (reader.hasNext()){
          samples.add(readOfflineEntry(reader));
        }
        reader.endArray();
        break;
      case "_comment":
        reader.nextString(); // Ignore.
        break;
      default:
        throw new ParserException("Unsupported name: " + name);
    }
  }
  reader.endObject();

  SampleGroup group = getGroup(groupName, groups);
  group.samples.addAll(samples);
}
项目:ExoPlayer-Offline    文件:SampleChooserActivity.java   
private UUID getDrmUuid(String typeString) throws ParserException {
  switch (typeString.toLowerCase()) {
    case "widevine":
      return C.WIDEVINE_UUID;
    case "playready":
      return C.PLAYREADY_UUID;
    default:
      try {
        return UUID.fromString(typeString);
      } catch (RuntimeException e) {
        throw new ParserException("Unsupported drm type: " + typeString);
      }
  }
}
项目:Exoplayer2Radio    文件:HlsPlaylistTracker.java   
@Override
public int onLoadError(ParsingLoadable<HlsPlaylist> loadable, long elapsedRealtimeMs,
    long loadDurationMs, IOException error) {
  boolean isFatal = error instanceof ParserException;
  eventDispatcher.loadError(loadable.dataSpec, C.DATA_TYPE_MANIFEST, elapsedRealtimeMs,
      loadDurationMs, loadable.bytesLoaded(), error, isFatal);
  return isFatal ? Loader.DONT_RETRY_FATAL : Loader.RETRY;
}
项目:Exoplayer2Radio    文件:HlsPlaylistTracker.java   
@Override
public void onLoadCompleted(ParsingLoadable<HlsPlaylist> loadable, long elapsedRealtimeMs,
    long loadDurationMs) {
  HlsPlaylist result = loadable.getResult();
  if (result instanceof HlsMediaPlaylist) {
    processLoadedPlaylist((HlsMediaPlaylist) result);
    eventDispatcher.loadCompleted(loadable.dataSpec, C.DATA_TYPE_MANIFEST, elapsedRealtimeMs,
        loadDurationMs, loadable.bytesLoaded());
  } else {
    onLoadError(loadable, elapsedRealtimeMs, loadDurationMs,
        new ParserException("Loaded playlist has unexpected type."));
  }
}
项目:Exoplayer2Radio    文件:HlsPlaylistParser.java   
@Override
public HlsPlaylist parse(Uri uri, InputStream inputStream) throws IOException {
  BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
  Queue<String> extraLines = new LinkedList<>();
  String line;
  try {
    if (!checkPlaylistHeader(reader)) {
      throw new UnrecognizedInputFormatException("Input does not start with the #EXTM3U header.",
          uri);
    }
    while ((line = reader.readLine()) != null) {
      line = line.trim();
      if (line.isEmpty()) {
        // Do nothing.
      } else if (line.startsWith(TAG_STREAM_INF)) {
        extraLines.add(line);
        return parseMasterPlaylist(new LineIterator(extraLines, reader), uri.toString());
      } else if (line.startsWith(TAG_TARGET_DURATION)
          || line.startsWith(TAG_MEDIA_SEQUENCE)
          || line.startsWith(TAG_MEDIA_DURATION)
          || line.startsWith(TAG_KEY)
          || line.startsWith(TAG_BYTERANGE)
          || line.equals(TAG_DISCONTINUITY)
          || line.equals(TAG_DISCONTINUITY_SEQUENCE)
          || line.equals(TAG_ENDLIST)) {
        extraLines.add(line);
        return parseMediaPlaylist(new LineIterator(extraLines, reader), uri.toString());
      } else {
        extraLines.add(line);
      }
    }
  } finally {
    Util.closeQuietly(reader);
  }
  throw new ParserException("Failed to parse the playlist, could not identify any tags.");
}
项目:Exoplayer2Radio    文件:HlsPlaylistParser.java   
private static String parseStringAttr(String line, Pattern pattern) throws ParserException {
  Matcher matcher = pattern.matcher(line);
  if (matcher.find() && matcher.groupCount() == 1) {
    return matcher.group(1);
  }
  throw new ParserException("Couldn't match " + pattern.pattern() + " in " + line);
}
项目: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    文件:WavExtractor.java   
@Override
public int read(ExtractorInput input, PositionHolder seekPosition)
    throws IOException, InterruptedException {
  if (wavHeader == null) {
    wavHeader = WavHeaderReader.peek(input);
    if (wavHeader == null) {
      // Should only happen if the media wasn't sniffed.
      throw new ParserException("Unsupported or unrecognized wav header.");
    }
    Format format = Format.createAudioSampleFormat(null, MimeTypes.AUDIO_RAW, null,
        wavHeader.getBitrate(), MAX_INPUT_SIZE, wavHeader.getNumChannels(),
        wavHeader.getSampleRateHz(), wavHeader.getEncoding(), null, null, 0, null);
    trackOutput.format(format);
    bytesPerFrame = wavHeader.getBytesPerFrame();
  }

  if (!wavHeader.hasDataBounds()) {
    WavHeaderReader.skipToData(input, wavHeader);
    extractorOutput.seekMap(this);
  }

  int bytesAppended = trackOutput.sampleData(input, MAX_INPUT_SIZE - pendingBytes, true);
  if (bytesAppended != RESULT_END_OF_INPUT) {
    pendingBytes += bytesAppended;
  }

  // Samples must consist of a whole number of frames.
  int pendingFrames = pendingBytes / bytesPerFrame;
  if (pendingFrames > 0) {
    long timeUs = wavHeader.getTimeUs(input.getPosition() - pendingBytes);
    int size = pendingFrames * bytesPerFrame;
    pendingBytes -= size;
    trackOutput.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, size, pendingBytes, null);
  }

  return bytesAppended == RESULT_END_OF_INPUT ? RESULT_END_OF_INPUT : RESULT_CONTINUE;
}
项目:Exoplayer2Radio    文件:VorbisUtil.java   
/**
 * Reads a vorbis comment header.
 *
 * @see <a href="https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-640004.2.3">
 *     Vorbis spec/Comment header</a>
 * @param headerData a {@link ParsableByteArray} wrapping the header data.
 * @return a {@link VorbisUtil.CommentHeader} with all the comments.
 * @throws ParserException thrown if invalid capture pattern is detected.
 */
public static CommentHeader readVorbisCommentHeader(ParsableByteArray headerData)
    throws ParserException {

  verifyVorbisHeaderCapturePattern(0x03, headerData, false);
  int length = 7;

  int len = (int) headerData.readLittleEndianUnsignedInt();
  length += 4;
  String vendor = headerData.readString(len);
  length += vendor.length();

  long commentListLen = headerData.readLittleEndianUnsignedInt();
  String[] comments = new String[(int) commentListLen];
  length += 4;
  for (int i = 0; i < commentListLen; i++) {
    len = (int) headerData.readLittleEndianUnsignedInt();
    length += 4;
    comments[i] = headerData.readString(len);
    length += comments[i].length();
  }
  if ((headerData.readUnsignedByte() & 0x01) == 0) {
    throw new ParserException("framing bit expected to be set");
  }
  length += 1;
  return new CommentHeader(vendor, comments, length);
}
项目:Exoplayer2Radio    文件:VorbisUtil.java   
/**
 * Verifies whether the next bytes in {@code header} are a vorbis header of the given
 * {@code headerType}.
 *
 * @param headerType the type of the header expected.
 * @param header the alleged header bytes.
 * @param quiet if {@code true} no exceptions are thrown. Instead {@code false} is returned.
 * @return the number of bytes read.
 * @throws ParserException thrown if header type or capture pattern is not as expected.
 */
public static boolean verifyVorbisHeaderCapturePattern(int headerType, ParsableByteArray header,
    boolean quiet)
    throws ParserException {
  if (header.bytesLeft() < 7) {
    if (quiet) {
      return false;
    } else {
      throw new ParserException("too short header: " + header.bytesLeft());
    }
  }

  if (header.readUnsignedByte() != headerType) {
    if (quiet) {
      return false;
    } else {
      throw new ParserException("expected header type " + Integer.toHexString(headerType));
    }
  }

  if (!(header.readUnsignedByte() == 'v'
      && header.readUnsignedByte() == 'o'
      && header.readUnsignedByte() == 'r'
      && header.readUnsignedByte() == 'b'
      && header.readUnsignedByte() == 'i'
      && header.readUnsignedByte() == 's')) {
    if (quiet) {
      return false;
    } else {
      throw new ParserException("expected characters 'vorbis'");
    }
  }
  return true;
}
项目:Exoplayer2Radio    文件:VorbisUtil.java   
/**
 * This method reads the modes which are located at the very end of the vorbis setup header.
 * That's why we need to partially decode or at least read the entire setup header to know
 * where to start reading the modes.
 *
 * @see <a href="https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-650004.2.4">
 *     Vorbis spec/Setup header</a>
 * @param headerData a {@link ParsableByteArray} containing setup header data.
 * @param channels the number of channels.
 * @return an array of {@link Mode}s.
 * @throws ParserException thrown if bit stream is invalid.
 */
public static Mode[] readVorbisModes(ParsableByteArray headerData, int channels)
    throws ParserException {

  verifyVorbisHeaderCapturePattern(0x05, headerData, false);

  int numberOfBooks = headerData.readUnsignedByte() + 1;

  VorbisBitArray bitArray  = new VorbisBitArray(headerData.data);
  bitArray.skipBits(headerData.getPosition() * 8);

  for (int i = 0; i < numberOfBooks; i++) {
    readBook(bitArray);
  }

  int timeCount = bitArray.readBits(6) + 1;
  for (int i = 0; i < timeCount; i++) {
    if (bitArray.readBits(16) != 0x00) {
      throw new ParserException("placeholder of time domain transforms not zeroed out");
    }
  }
  readFloors(bitArray);
  readResidues(bitArray);
  readMappings(channels, bitArray);

  Mode[] modes = readModes(bitArray);
  if (!bitArray.readBit()) {
    throw new ParserException("framing bit after modes not set as expected");
  }
  return modes;
}
项目:Exoplayer2Radio    文件:VorbisUtil.java   
private static void readResidues(VorbisBitArray bitArray) throws ParserException {
  int residueCount = bitArray.readBits(6) + 1;
  for (int i = 0; i < residueCount; i++) {
    int residueType = bitArray.readBits(16);
    if (residueType > 2) {
      throw new ParserException("residueType greater than 2 is not decodable");
    } else {
      bitArray.skipBits(24); // begin
      bitArray.skipBits(24); // end
      bitArray.skipBits(24); // partitionSize (add one)
      int classifications = bitArray.readBits(6) + 1;
      bitArray.skipBits(8); // classbook
      int[] cascade = new int[classifications];
      for (int j = 0; j < classifications; j++) {
        int highBits = 0;
        int lowBits = bitArray.readBits(3);
        if (bitArray.readBit()) {
          highBits = bitArray.readBits(5);
        }
        cascade[j] = highBits * 8 + lowBits;
      }
      for (int j = 0; j < classifications; j++) {
        for (int k = 0; k < 8; k++) {
          if ((cascade[j] & (0x01 << k)) != 0) {
            bitArray.skipBits(8); // discard
          }
        }
      }
    }
  }
}
项目:Exoplayer2Radio    文件:VorbisReader.java   
public static boolean verifyBitstreamType(ParsableByteArray data) {
  try {
    return VorbisUtil.verifyVorbisHeaderCapturePattern(0x01, data, true);
  } catch (ParserException e) {
    return false;
  }
}
项目:Exoplayer2Radio    文件:AtomParsers.java   
/**
 * Parses a trak atom (defined in 14496-12).
 *
 * @param trak Atom to decode.
 * @param mvhd Movie header atom, used to get the timescale.
 * @param duration The duration in units of the timescale declared in the mvhd atom, or
 *     {@link C#TIME_UNSET} if the duration should be parsed from the tkhd atom.
 * @param drmInitData {@link DrmInitData} to be included in the format.
 * @param isQuickTime True for QuickTime media. False otherwise.
 * @return A {@link Track} instance, or {@code null} if the track's type isn't supported.
 */
public static Track parseTrak(Atom.ContainerAtom trak, Atom.LeafAtom mvhd, long duration,
    DrmInitData drmInitData, boolean isQuickTime) throws ParserException {
  Atom.ContainerAtom mdia = trak.getContainerAtomOfType(Atom.TYPE_mdia);
  int trackType = parseHdlr(mdia.getLeafAtomOfType(Atom.TYPE_hdlr).data);
  if (trackType == C.TRACK_TYPE_UNKNOWN) {
    return null;
  }

  TkhdData tkhdData = parseTkhd(trak.getLeafAtomOfType(Atom.TYPE_tkhd).data);
  if (duration == C.TIME_UNSET) {
    duration = tkhdData.duration;
  }
  long movieTimescale = parseMvhd(mvhd.data);
  long durationUs;
  if (duration == C.TIME_UNSET) {
    durationUs = C.TIME_UNSET;
  } else {
    durationUs = Util.scaleLargeTimestamp(duration, C.MICROS_PER_SECOND, movieTimescale);
  }
  Atom.ContainerAtom stbl = mdia.getContainerAtomOfType(Atom.TYPE_minf)
      .getContainerAtomOfType(Atom.TYPE_stbl);

  Pair<Long, String> mdhdData = parseMdhd(mdia.getLeafAtomOfType(Atom.TYPE_mdhd).data);
  StsdData stsdData = parseStsd(stbl.getLeafAtomOfType(Atom.TYPE_stsd).data, tkhdData.id,
      tkhdData.rotationDegrees, mdhdData.second, drmInitData, isQuickTime);
  Pair<long[], long[]> edtsData = parseEdts(trak.getContainerAtomOfType(Atom.TYPE_edts));
  return stsdData.format == null ? null
      : new Track(tkhdData.id, trackType, mdhdData.first, movieTimescale, durationUs,
          stsdData.format, stsdData.requiredSampleTransformation, stsdData.trackEncryptionBoxes,
          stsdData.nalUnitLengthFieldLength, edtsData.first, edtsData.second);
}
项目:Exoplayer2Radio    文件:AtomParsers.java   
/**
 * Parses a stsd atom (defined in 14496-12).
 *
 * @param stsd The stsd atom to decode.
 * @param trackId The track's identifier in its container.
 * @param rotationDegrees The rotation of the track in degrees.
 * @param language The language of the track.
 * @param drmInitData {@link DrmInitData} to be included in the format.
 * @param isQuickTime True for QuickTime media. False otherwise.
 * @return An object containing the parsed data.
 */
private static StsdData parseStsd(ParsableByteArray stsd, int trackId, int rotationDegrees,
    String language, DrmInitData drmInitData, boolean isQuickTime) throws ParserException {
  stsd.setPosition(Atom.FULL_HEADER_SIZE);
  int numberOfEntries = stsd.readInt();
  StsdData out = new StsdData(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 || childAtomType == Atom.TYPE_vp08
        || childAtomType == Atom.TYPE_vp09) {
      parseVideoSampleEntry(stsd, childAtomType, childStartPosition, childAtomSize, trackId,
          rotationDegrees, drmInitData, out, i);
    } else if (childAtomType == Atom.TYPE_mp4a || childAtomType == Atom.TYPE_enca
        || childAtomType == Atom.TYPE_ac_3 || childAtomType == Atom.TYPE_ec_3
        || childAtomType == Atom.TYPE_dtsc || childAtomType == Atom.TYPE_dtse
        || childAtomType == Atom.TYPE_dtsh || childAtomType == Atom.TYPE_dtsl
        || childAtomType == Atom.TYPE_samr || childAtomType == Atom.TYPE_sawb
        || childAtomType == Atom.TYPE_lpcm || childAtomType == Atom.TYPE_sowt
        || childAtomType == Atom.TYPE__mp3 || childAtomType == Atom.TYPE_alac) {
      parseAudioSampleEntry(stsd, childAtomType, childStartPosition, childAtomSize, trackId,
          language, isQuickTime, drmInitData, out, i);
    } else if (childAtomType == Atom.TYPE_TTML || childAtomType == Atom.TYPE_tx3g
        || childAtomType == Atom.TYPE_wvtt || childAtomType == Atom.TYPE_stpp
        || childAtomType == Atom.TYPE_c608) {
      parseTextSampleEntry(stsd, childAtomType, childStartPosition, childAtomSize, trackId,
          language, drmInitData, out);
    } else if (childAtomType == Atom.TYPE_camm) {
      out.format = Format.createSampleFormat(Integer.toString(trackId),
          MimeTypes.APPLICATION_CAMERA_MOTION, null, Format.NO_VALUE, drmInitData);
    }
    stsd.setPosition(childStartPosition + childAtomSize);
  }
  return out;
}
项目:Exoplayer2Radio    文件:AtomParsers.java   
private static void parseTextSampleEntry(ParsableByteArray parent, int atomType, int position,
    int atomSize, int trackId, String language, DrmInitData drmInitData, StsdData out)
    throws ParserException {
  parent.setPosition(position + Atom.HEADER_SIZE + StsdData.STSD_HEADER_SIZE);

  // Default values.
  List<byte[]> initializationData = null;
  long subsampleOffsetUs = Format.OFFSET_SAMPLE_RELATIVE;

  String mimeType;
  if (atomType == Atom.TYPE_TTML) {
    mimeType = MimeTypes.APPLICATION_TTML;
  } else if (atomType == Atom.TYPE_tx3g) {
    mimeType = MimeTypes.APPLICATION_TX3G;
    int sampleDescriptionLength = atomSize - Atom.HEADER_SIZE - 8;
    byte[] sampleDescriptionData = new byte[sampleDescriptionLength];
    parent.readBytes(sampleDescriptionData, 0, sampleDescriptionLength);
    initializationData = Collections.singletonList(sampleDescriptionData);
  } else if (atomType == Atom.TYPE_wvtt) {
    mimeType = MimeTypes.APPLICATION_MP4VTT;
  } else if (atomType == Atom.TYPE_stpp) {
    mimeType = MimeTypes.APPLICATION_TTML;
    subsampleOffsetUs = 0; // Subsample timing is absolute.
  } else if (atomType == Atom.TYPE_c608) {
    // Defined by the QuickTime File Format specification.
    mimeType = MimeTypes.APPLICATION_MP4CEA608;
    out.requiredSampleTransformation = Track.TRANSFORMATION_CEA608_CDAT;
  } else {
    // Never happens.
    throw new IllegalStateException();
  }

  out.format = Format.createTextSampleFormat(Integer.toString(trackId), mimeType, null,
      Format.NO_VALUE, 0, language, Format.NO_VALUE, drmInitData, subsampleOffsetUs,
      initializationData);
}
项目:Exoplayer2Radio    文件:FragmentedMp4Extractor.java   
private void onLeafAtomRead(LeafAtom leaf, long inputPosition) throws ParserException {
  if (!containerAtoms.isEmpty()) {
    containerAtoms.peek().add(leaf);
  } else if (leaf.type == Atom.TYPE_sidx) {
    Pair<Long, ChunkIndex> result = parseSidx(leaf.data, inputPosition);
    segmentIndexEarliestPresentationTimeUs = result.first;
    extractorOutput.seekMap(result.second);
    haveOutputSeekMap = true;
  } else if (leaf.type == Atom.TYPE_emsg) {
    onEmsgLeafAtomRead(leaf.data);
  }
}
项目:Exoplayer2Radio    文件:FragmentedMp4Extractor.java   
private void onContainerAtomRead(ContainerAtom container) throws ParserException {
  if (container.type == Atom.TYPE_moov) {
    onMoovContainerAtomRead(container);
  } else if (container.type == Atom.TYPE_moof) {
    onMoofContainerAtomRead(container);
  } else if (!containerAtoms.isEmpty()) {
    containerAtoms.peek().add(container);
  }
}
项目:Exoplayer2Radio    文件:FragmentedMp4Extractor.java   
private void onMoofContainerAtomRead(ContainerAtom moof) throws ParserException {
  parseMoof(moof, trackBundles, flags, extendedTypeScratch);
  DrmInitData drmInitData = getDrmInitDataFromAtoms(moof.leafChildren);
  if (drmInitData != null) {
    int trackCount = trackBundles.size();
    for (int i = 0; i < trackCount; i++) {
      trackBundles.valueAt(i).updateDrmInitData(drmInitData);
    }
  }
}
项目:Exoplayer2Radio    文件:FragmentedMp4Extractor.java   
private static void parseMoof(ContainerAtom moof, SparseArray<TrackBundle> trackBundleArray,
    @Flags int flags, byte[] extendedTypeScratch) throws ParserException {
  int moofContainerChildrenSize = moof.containerChildren.size();
  for (int i = 0; i < moofContainerChildrenSize; i++) {
    Atom.ContainerAtom child = moof.containerChildren.get(i);
    // TODO: Support multiple traf boxes per track in a single moof.
    if (child.type == Atom.TYPE_traf) {
      parseTraf(child, trackBundleArray, flags, extendedTypeScratch);
    }
  }
}