com.google.android.exoplayer.smoothstreaming.SmoothStreamingManifest.StreamElement Java Examples

The following examples show how to use com.google.android.exoplayer.smoothstreaming.SmoothStreamingManifest.StreamElement. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: SmoothStreamingManifestParser.java    From Exoplayer_VLC with Apache License 2.0 6 votes vote down vote up
private void parseStreamElementStartTag(XmlPullParser parser) throws ParserException {
  type = parseType(parser);
  putNormalizedAttribute(KEY_TYPE, type);
  if (type == StreamElement.TYPE_TEXT) {
    subType = parseRequiredString(parser, KEY_SUB_TYPE);
  } else {
    subType = parser.getAttributeValue(null, KEY_SUB_TYPE);
  }
  name = parser.getAttributeValue(null, KEY_NAME);
  qualityLevels = parseInt(parser, KEY_QUALITY_LEVELS, -1);
  url = parseRequiredString(parser, KEY_URL);
  maxWidth = parseInt(parser, KEY_MAX_WIDTH, -1);
  maxHeight = parseInt(parser, KEY_MAX_HEIGHT, -1);
  displayWidth = parseInt(parser, KEY_DISPLAY_WIDTH, -1);
  displayHeight = parseInt(parser, KEY_DISPLAY_HEIGHT, -1);
  language = parser.getAttributeValue(null, KEY_LANGUAGE);
  timescale = parseInt(parser, KEY_TIME_SCALE, -1);
  if (timescale == -1) {
    timescale = (Long) getNormalizedAttribute(KEY_TIME_SCALE);
  }
  startTimes = new ArrayList<Long>();
}
 
Example #2
Source File: SmoothStreamingChunkSource.java    From Exoplayer_VLC with Apache License 2.0 6 votes vote down vote up
@Override
public void continueBuffering(long playbackPositionUs) {
  if (manifestFetcher == null || !currentManifest.isLive || fatalError != null) {
    return;
  }

  SmoothStreamingManifest newManifest = manifestFetcher.getManifest();
  if (currentManifest != newManifest && newManifest != null) {
    StreamElement currentElement = getElement(currentManifest);
    StreamElement newElement = getElement(newManifest);
    if (newElement.chunkCount == 0) {
      currentManifestChunkOffset += currentElement.chunkCount;
    } else if (currentElement.chunkCount > 0) {
      currentManifestChunkOffset += currentElement.getChunkIndex(newElement.getStartTimeUs(0));
    }
    currentManifest = newManifest;
    finishedCurrentManifest = false;
  }

  if (finishedCurrentManifest && (SystemClock.elapsedRealtime()
      > manifestFetcher.getManifestLoadTimestamp() + MINIMUM_MANIFEST_REFRESH_PERIOD_MS)) {
    manifestFetcher.requestRefresh();
  }
}
 
Example #3
Source File: SmoothStreamingManifestParser.java    From Exoplayer_VLC with Apache License 2.0 5 votes vote down vote up
@Override
public void addChild(Object child) {
  if (child instanceof StreamElement) {
    streamElements.add((StreamElement) child);
  } else if (child instanceof ProtectionElement) {
    Assertions.checkState(protectionElement == null);
    protectionElement = (ProtectionElement) child;
  }
}
 
Example #4
Source File: SmoothStreamingManifestParser.java    From Exoplayer_VLC with Apache License 2.0 5 votes vote down vote up
@Override
public Object build() {
  StreamElement[] streamElementArray = new StreamElement[streamElements.size()];
  streamElements.toArray(streamElementArray);
  return new SmoothStreamingManifest(majorVersion, minorVersion, timescale, duration,
      dvrWindowLength, lookAheadCount, isLive, protectionElement, streamElementArray);
}
 
Example #5
Source File: SmoothStreamingManifestParser.java    From Exoplayer_VLC with Apache License 2.0 5 votes vote down vote up
private int parseType(XmlPullParser parser) throws ParserException {
  String value = parser.getAttributeValue(null, KEY_TYPE);
  if (value != null) {
    if (KEY_TYPE_AUDIO.equalsIgnoreCase(value)) {
      return StreamElement.TYPE_AUDIO;
    } else if (KEY_TYPE_VIDEO.equalsIgnoreCase(value)) {
      return StreamElement.TYPE_VIDEO;
    } else if (KEY_TYPE_TEXT.equalsIgnoreCase(value)) {
      return StreamElement.TYPE_TEXT;
    } else {
      throw new ParserException("Invalid key value[" + value + "]");
    }
  }
  throw new MissingFieldException(KEY_TYPE);
}
 
Example #6
Source File: SmoothStreamingManifestParser.java    From Exoplayer_VLC with Apache License 2.0 5 votes vote down vote up
@Override
public Object build() {
  TrackElement[] trackElements = new TrackElement[tracks.size()];
  tracks.toArray(trackElements);
  return new StreamElement(baseUri, url, type, subType, timescale, name, qualityLevels,
      maxWidth, maxHeight, displayWidth, displayHeight, language, trackElements, startTimes,
      lastChunkDuration);
}
 
Example #7
Source File: SmoothStreamingChunkSource.java    From Exoplayer_VLC with Apache License 2.0 5 votes vote down vote up
/**
 * For live playbacks, determines the seek position that snaps playback to be
 * {@link #liveEdgeLatencyUs} behind the live edge of the current manifest
 *
 * @return The seek position in microseconds.
 */
private long getLiveSeekPosition() {
  long liveEdgeTimestampUs = Long.MIN_VALUE;
  for (int i = 0; i < currentManifest.streamElements.length; i++) {
    StreamElement streamElement = currentManifest.streamElements[i];
    if (streamElement.chunkCount > 0) {
      long elementLiveEdgeTimestampUs =
          streamElement.getStartTimeUs(streamElement.chunkCount - 1)
          + streamElement.getChunkDurationUs(streamElement.chunkCount - 1);
      liveEdgeTimestampUs = Math.max(liveEdgeTimestampUs, elementLiveEdgeTimestampUs);
    }
  }
  return liveEdgeTimestampUs - liveEdgeLatencyUs;
}
 
Example #8
Source File: SmoothStreamingManifestParser.java    From Exoplayer_VLC with Apache License 2.0 4 votes vote down vote up
public SmoothStreamMediaParser(ElementParser parent, Uri baseUri) {
  super(parent, baseUri, TAG);
  lookAheadCount = -1;
  protectionElement = null;
  streamElements = new LinkedList<StreamElement>();
}
 
Example #9
Source File: SmoothStreamingManifestParser.java    From Exoplayer_VLC with Apache License 2.0 4 votes vote down vote up
@Override
public void parseStartTag(XmlPullParser parser) throws ParserException {
  int type = (Integer) getNormalizedAttribute(KEY_TYPE);
  content = null;
  String value;

  index = parseInt(parser, KEY_INDEX, -1);
  bitrate = parseRequiredInt(parser, KEY_BITRATE);
  nalUnitLengthField = parseInt(parser, KEY_NAL_UNIT_LENGTH_FIELD, 4);

  if (type == StreamElement.TYPE_VIDEO) {
    maxHeight = parseRequiredInt(parser, KEY_MAX_HEIGHT);
    maxWidth = parseRequiredInt(parser, KEY_MAX_WIDTH);
    mimeType = fourCCToMimeType(parseRequiredString(parser, KEY_FOUR_CC));
  } else {
    maxHeight = -1;
    maxWidth = -1;
    String fourCC = parser.getAttributeValue(null, KEY_FOUR_CC);
    // If fourCC is missing and the stream type is audio, we assume AAC.
    mimeType = fourCC != null ? fourCCToMimeType(fourCC)
        : type == StreamElement.TYPE_AUDIO ? MimeTypes.AUDIO_AAC : null;
  }

  if (type == StreamElement.TYPE_AUDIO) {
    samplingRate = parseRequiredInt(parser, KEY_SAMPLING_RATE);
    channels = parseRequiredInt(parser, KEY_CHANNELS);
    bitPerSample = parseRequiredInt(parser, KEY_BITS_PER_SAMPLE);
    packetSize = parseRequiredInt(parser, KEY_PACKET_SIZE);
    audioTag = parseRequiredInt(parser, KEY_AUDIO_TAG);
  } else {
    samplingRate = -1;
    channels = -1;
    bitPerSample = -1;
    packetSize = -1;
    audioTag = -1;
  }

  value = parser.getAttributeValue(null, KEY_CODEC_PRIVATE_DATA);
  if (value != null && value.length() > 0) {
    byte[] codecPrivateData = hexStringToByteArray(value);
    byte[][] split = CodecSpecificDataUtil.splitNalUnits(codecPrivateData);
    if (split == null) {
      csd.add(codecPrivateData);
    } else {
      for (int i = 0; i < split.length; i++) {
        Pair<Integer, Integer> spsParameters = CodecSpecificDataUtil.parseSpsNalUnit(split[i]);
        if (spsParameters != null) {
          profile = spsParameters.first;
          level = spsParameters.second;
        }
        csd.add(split[i]);
      }
    }
  }
}
 
Example #10
Source File: SmoothStreamingChunkSource.java    From Exoplayer_VLC with Apache License 2.0 4 votes vote down vote up
private SmoothStreamingChunkSource(ManifestFetcher<SmoothStreamingManifest> manifestFetcher,
    SmoothStreamingManifest initialManifest, int streamElementIndex, int[] trackIndices,
    DataSource dataSource, FormatEvaluator formatEvaluator, long liveEdgeLatencyMs) {
  this.manifestFetcher = manifestFetcher;
  this.streamElementIndex = streamElementIndex;
  this.currentManifest = initialManifest;
  this.dataSource = dataSource;
  this.formatEvaluator = formatEvaluator;
  this.liveEdgeLatencyUs = liveEdgeLatencyMs * 1000;

  StreamElement streamElement = getElement(initialManifest);
  trackInfo = new TrackInfo(streamElement.tracks[0].mimeType, initialManifest.durationUs);
  evaluation = new Evaluation();

  TrackEncryptionBox[] trackEncryptionBoxes = null;
  ProtectionElement protectionElement = initialManifest.protectionElement;
  if (protectionElement != null) {
    byte[] keyId = getKeyId(protectionElement.data);
    trackEncryptionBoxes = new TrackEncryptionBox[1];
    trackEncryptionBoxes[0] = new TrackEncryptionBox(true, INITIALIZATION_VECTOR_SIZE, keyId);
    psshInfo = Collections.singletonMap(protectionElement.uuid, protectionElement.data);
  } else {
    psshInfo = null;
  }

  int trackCount = trackIndices != null ? trackIndices.length : streamElement.tracks.length;
  formats = new SmoothStreamingFormat[trackCount];
  extractors = new SparseArray<FragmentedMp4Extractor>();
  int maxWidth = 0;
  int maxHeight = 0;
  for (int i = 0; i < trackCount; i++) {
    int trackIndex = trackIndices != null ? trackIndices[i] : i;
    TrackElement trackElement = streamElement.tracks[trackIndex];
    formats[i] = new SmoothStreamingFormat(String.valueOf(trackIndex), trackElement.mimeType,
        trackElement.maxWidth, trackElement.maxHeight, trackElement.numChannels,
        trackElement.sampleRate, trackElement.bitrate, trackIndex);
    maxWidth = Math.max(maxWidth, trackElement.maxWidth);
    maxHeight = Math.max(maxHeight, trackElement.maxHeight);

    MediaFormat mediaFormat = getMediaFormat(streamElement, trackIndex);
    int trackType = streamElement.type == StreamElement.TYPE_VIDEO ? Track.TYPE_VIDEO
        : Track.TYPE_AUDIO;
    FragmentedMp4Extractor extractor = new FragmentedMp4Extractor(
        FragmentedMp4Extractor.WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME);
    extractor.setTrack(new Track(trackIndex, trackType, streamElement.timescale,
        initialManifest.durationUs, mediaFormat, trackEncryptionBoxes));
    extractors.put(trackIndex, extractor);
  }
  this.maxHeight = maxHeight;
  this.maxWidth = maxWidth;
  Arrays.sort(formats, new DecreasingBandwidthComparator());
}
 
Example #11
Source File: SmoothStreamingChunkSource.java    From Exoplayer_VLC with Apache License 2.0 4 votes vote down vote up
@Override
public final void getChunkOperation(List<? extends MediaChunk> queue, long seekPositionUs,
    long playbackPositionUs, ChunkOperationHolder out) {
  if (fatalError != null) {
    out.chunk = null;
    return;
  }

  evaluation.queueSize = queue.size();
  formatEvaluator.evaluate(queue, playbackPositionUs, formats, evaluation);
  SmoothStreamingFormat selectedFormat = (SmoothStreamingFormat) evaluation.format;
  out.queueSize = evaluation.queueSize;

  if (selectedFormat == null) {
    out.chunk = null;
    return;
  } else if (out.queueSize == queue.size() && out.chunk != null
      && out.chunk.format.id.equals(evaluation.format.id)) {
    // We already have a chunk, and the evaluation hasn't changed either the format or the size
    // of the queue. Do nothing.
    return;
  }

  // In all cases where we return before instantiating a new chunk at the bottom of this method,
  // we want out.chunk to be null.
  out.chunk = null;

  StreamElement streamElement = getElement(currentManifest);
  if (streamElement.chunkCount == 0) {
    // The manifest is currently empty for this stream.
    finishedCurrentManifest = true;
    return;
  }

  int chunkIndex;
  if (queue.isEmpty()) {
    if (currentManifest.isLive) {
      seekPositionUs = getLiveSeekPosition();
    }
    chunkIndex = streamElement.getChunkIndex(seekPositionUs);
  } else {
    chunkIndex = queue.get(out.queueSize - 1).nextChunkIndex - currentManifestChunkOffset;
  }

  if (currentManifest.isLive) {
    if (chunkIndex < 0) {
      // This is before the first chunk in the current manifest.
      fatalError = new BehindLiveWindowException();
      return;
    } else if (chunkIndex >= streamElement.chunkCount) {
      // This is beyond the last chunk in the current manifest.
      finishedCurrentManifest = true;
      return;
    } else if (chunkIndex == streamElement.chunkCount - 1) {
      // This is the last chunk in the current manifest. Mark the manifest as being finished,
      // but continue to return the final chunk.
      finishedCurrentManifest = true;
    }
  } else if (chunkIndex == -1) {
    // We've reached the end of the stream.
    return;
  }

  boolean isLastChunk = !currentManifest.isLive && chunkIndex == streamElement.chunkCount - 1;
  long chunkStartTimeUs = streamElement.getStartTimeUs(chunkIndex);
  long nextChunkStartTimeUs = isLastChunk ? -1
      : chunkStartTimeUs + streamElement.getChunkDurationUs(chunkIndex);
  int currentAbsoluteChunkIndex = chunkIndex + currentManifestChunkOffset;

  Uri uri = streamElement.buildRequestUri(selectedFormat.trackIndex, chunkIndex);
  Chunk mediaChunk = newMediaChunk(selectedFormat, uri, null,
      extractors.get(Integer.parseInt(selectedFormat.id)), psshInfo, dataSource,
      currentAbsoluteChunkIndex, isLastChunk, chunkStartTimeUs, nextChunkStartTimeUs, 0);
  out.chunk = mediaChunk;
}
 
Example #12
Source File: SmoothStreamingChunkSource.java    From Exoplayer_VLC with Apache License 2.0 4 votes vote down vote up
private StreamElement getElement(SmoothStreamingManifest manifest) {
  return manifest.streamElements[streamElementIndex];
}