com.google.android.exoplayer2.source.chunk.MediaChunkIterator Java Examples

The following examples show how to use com.google.android.exoplayer2.source.chunk.MediaChunkIterator. 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: HlsChunkSource.java    From Telegram with GNU General Public License v2.0 6 votes vote down vote up
@Override
public void updateSelectedTrack(
    long playbackPositionUs,
    long bufferedDurationUs,
    long availableDurationUs,
    List<? extends MediaChunk> queue,
    MediaChunkIterator[] mediaChunkIterators) {
  long nowMs = SystemClock.elapsedRealtime();
  if (!isBlacklisted(selectedIndex, nowMs)) {
    return;
  }
  // Try from lowest bitrate to highest.
  for (int i = length - 1; i >= 0; i--) {
    if (!isBlacklisted(i, nowMs)) {
      selectedIndex = i;
      return;
    }
  }
  // Should never happen.
  throw new IllegalStateException();
}
 
Example #2
Source File: WindowedTrackBitrateEstimator.java    From Telegram with GNU General Public License v2.0 6 votes vote down vote up
@Override
public int[] getBitrates(
    Format[] formats,
    List<? extends MediaChunk> queue,
    MediaChunkIterator[] iterators,
    @Nullable int[] bitrates) {
  if (maxFutureDurationUs > 0 || maxPastDurationUs > 0) {
    return TrackSelectionUtil.getBitratesUsingPastAndFutureInfo(
        formats,
        queue,
        maxPastDurationUs,
        iterators,
        maxFutureDurationUs,
        useFormatBitrateAsLowerBound,
        bitrates);
  }
  return TrackSelectionUtil.getFormatBitrates(formats, bitrates);
}
 
Example #3
Source File: TrackSelectionUtil.java    From Telegram with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Returns bitrate values for a set of tracks whose formats are given, using the given upcoming
 * media chunk iterators and the queue of already buffered {@link MediaChunk}s.
 *
 * @param formats The track formats.
 * @param queue The queue of already buffered {@link MediaChunk}s. Must not be modified.
 * @param maxPastDurationUs Maximum duration of past chunks to be included in average bitrate
 *     values, in microseconds.
 * @param iterators An array of {@link MediaChunkIterator}s providing information about the
 *     sequence of upcoming media chunks for each track.
 * @param maxFutureDurationUs Maximum duration of future chunks to be included in average bitrate
 *     values, in microseconds.
 * @param useFormatBitrateAsLowerBound Whether to return the estimated bitrate only if it's higher
 *     than the bitrate of the track's format.
 * @param bitrates An array into which the bitrate values will be written. If non-null, this array
 *     is the one that will be returned.
 * @return Bitrate values for the tracks. As long as the format of a track has set bitrate, a
 *     bitrate value is set in the returned array. Otherwise it might be set to {@link
 *     Format#NO_VALUE}.
 */
public static int[] getBitratesUsingPastAndFutureInfo(
    Format[] formats,
    List<? extends MediaChunk> queue,
    long maxPastDurationUs,
    MediaChunkIterator[] iterators,
    long maxFutureDurationUs,
    boolean useFormatBitrateAsLowerBound,
    @Nullable int[] bitrates) {
  bitrates = getBitratesUsingFutureInfo(iterators, formats, maxFutureDurationUs, bitrates);
  getBitratesUsingPastInfo(queue, formats, maxPastDurationUs, bitrates);
  for (int i = 0; i < bitrates.length; i++) {
    int bitrate = bitrates[i];
    if (bitrate == Format.NO_VALUE
        || (useFormatBitrateAsLowerBound
            && formats[i].bitrate != Format.NO_VALUE
            && bitrate < formats[i].bitrate)) {
      bitrates[i] = formats[i].bitrate;
    }
  }
  return bitrates;
}
 
Example #4
Source File: TrackSelectionUtil.java    From Telegram with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Returns average bitrate for chunks in bits per second. Chunks are included in average until
 * {@code maxDurationMs} or the first unknown length chunk.
 *
 * @param iterator Iterator for media chunk sequences.
 * @param maxDurationUs Maximum duration of chunks to be included in average bitrate, in
 *     microseconds.
 * @return Average bitrate for chunks in bits per second, or {@link Format#NO_VALUE} if there are
 *     no chunks or the first chunk length is unknown.
 */
public static int getAverageBitrate(MediaChunkIterator iterator, long maxDurationUs) {
  long totalDurationUs = 0;
  long totalLength = 0;
  while (iterator.next()) {
    long chunkLength = iterator.getDataSpec().length;
    if (chunkLength == C.LENGTH_UNSET) {
      break;
    }
    long chunkDurationUs = iterator.getChunkEndTimeUs() - iterator.getChunkStartTimeUs();
    if (totalDurationUs + chunkDurationUs >= maxDurationUs) {
      totalLength += chunkLength * (maxDurationUs - totalDurationUs) / chunkDurationUs;
      totalDurationUs = maxDurationUs;
      break;
    }
    totalDurationUs += chunkDurationUs;
    totalLength += chunkLength;
  }
  return totalDurationUs == 0
      ? Format.NO_VALUE
      : (int) (totalLength * C.BITS_PER_BYTE * C.MICROS_PER_SECOND / totalDurationUs);
}
 
Example #5
Source File: HlsChunkSource.java    From MediaSDK with Apache License 2.0 6 votes vote down vote up
@Override
public void updateSelectedTrack(
    long playbackPositionUs,
    long bufferedDurationUs,
    long availableDurationUs,
    List<? extends MediaChunk> queue,
    MediaChunkIterator[] mediaChunkIterators) {
  long nowMs = SystemClock.elapsedRealtime();
  if (!isBlacklisted(selectedIndex, nowMs)) {
    return;
  }
  // Try from lowest bitrate to highest.
  for (int i = length - 1; i >= 0; i--) {
    if (!isBlacklisted(i, nowMs)) {
      selectedIndex = i;
      return;
    }
  }
  // Should never happen.
  throw new IllegalStateException();
}
 
Example #6
Source File: HlsChunkSource.java    From Telegram-FOSS with GNU General Public License v2.0 6 votes vote down vote up
@Override
public void updateSelectedTrack(
    long playbackPositionUs,
    long bufferedDurationUs,
    long availableDurationUs,
    List<? extends MediaChunk> queue,
    MediaChunkIterator[] mediaChunkIterators) {
  long nowMs = SystemClock.elapsedRealtime();
  if (!isBlacklisted(selectedIndex, nowMs)) {
    return;
  }
  // Try from lowest bitrate to highest.
  for (int i = length - 1; i >= 0; i--) {
    if (!isBlacklisted(i, nowMs)) {
      selectedIndex = i;
      return;
    }
  }
  // Should never happen.
  throw new IllegalStateException();
}
 
Example #7
Source File: WindowedTrackBitrateEstimator.java    From Telegram-FOSS with GNU General Public License v2.0 6 votes vote down vote up
@Override
public int[] getBitrates(
    Format[] formats,
    List<? extends MediaChunk> queue,
    MediaChunkIterator[] iterators,
    @Nullable int[] bitrates) {
  if (maxFutureDurationUs > 0 || maxPastDurationUs > 0) {
    return TrackSelectionUtil.getBitratesUsingPastAndFutureInfo(
        formats,
        queue,
        maxPastDurationUs,
        iterators,
        maxFutureDurationUs,
        useFormatBitrateAsLowerBound,
        bitrates);
  }
  return TrackSelectionUtil.getFormatBitrates(formats, bitrates);
}
 
Example #8
Source File: TrackSelectionUtil.java    From Telegram-FOSS with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Returns average bitrate for chunks in bits per second. Chunks are included in average until
 * {@code maxDurationMs} or the first unknown length chunk.
 *
 * @param iterator Iterator for media chunk sequences.
 * @param maxDurationUs Maximum duration of chunks to be included in average bitrate, in
 *     microseconds.
 * @return Average bitrate for chunks in bits per second, or {@link Format#NO_VALUE} if there are
 *     no chunks or the first chunk length is unknown.
 */
public static int getAverageBitrate(MediaChunkIterator iterator, long maxDurationUs) {
  long totalDurationUs = 0;
  long totalLength = 0;
  while (iterator.next()) {
    long chunkLength = iterator.getDataSpec().length;
    if (chunkLength == C.LENGTH_UNSET) {
      break;
    }
    long chunkDurationUs = iterator.getChunkEndTimeUs() - iterator.getChunkStartTimeUs();
    if (totalDurationUs + chunkDurationUs >= maxDurationUs) {
      totalLength += chunkLength * (maxDurationUs - totalDurationUs) / chunkDurationUs;
      totalDurationUs = maxDurationUs;
      break;
    }
    totalDurationUs += chunkDurationUs;
    totalLength += chunkLength;
  }
  return totalDurationUs == 0
      ? Format.NO_VALUE
      : (int) (totalLength * C.BITS_PER_BYTE * C.MICROS_PER_SECOND / totalDurationUs);
}
 
Example #9
Source File: TrackSelectionUtil.java    From Telegram-FOSS with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Returns bitrate values for a set of tracks whose formats are given, using the given upcoming
 * media chunk iterators and the queue of already buffered {@link MediaChunk}s.
 *
 * @param formats The track formats.
 * @param queue The queue of already buffered {@link MediaChunk}s. Must not be modified.
 * @param maxPastDurationUs Maximum duration of past chunks to be included in average bitrate
 *     values, in microseconds.
 * @param iterators An array of {@link MediaChunkIterator}s providing information about the
 *     sequence of upcoming media chunks for each track.
 * @param maxFutureDurationUs Maximum duration of future chunks to be included in average bitrate
 *     values, in microseconds.
 * @param useFormatBitrateAsLowerBound Whether to return the estimated bitrate only if it's higher
 *     than the bitrate of the track's format.
 * @param bitrates An array into which the bitrate values will be written. If non-null, this array
 *     is the one that will be returned.
 * @return Bitrate values for the tracks. As long as the format of a track has set bitrate, a
 *     bitrate value is set in the returned array. Otherwise it might be set to {@link
 *     Format#NO_VALUE}.
 */
public static int[] getBitratesUsingPastAndFutureInfo(
    Format[] formats,
    List<? extends MediaChunk> queue,
    long maxPastDurationUs,
    MediaChunkIterator[] iterators,
    long maxFutureDurationUs,
    boolean useFormatBitrateAsLowerBound,
    @Nullable int[] bitrates) {
  bitrates = getBitratesUsingFutureInfo(iterators, formats, maxFutureDurationUs, bitrates);
  getBitratesUsingPastInfo(queue, formats, maxPastDurationUs, bitrates);
  for (int i = 0; i < bitrates.length; i++) {
    int bitrate = bitrates[i];
    if (bitrate == Format.NO_VALUE
        || (useFormatBitrateAsLowerBound
            && formats[i].bitrate != Format.NO_VALUE
            && bitrate < formats[i].bitrate)) {
      bitrates[i] = formats[i].bitrate;
    }
  }
  return bitrates;
}
 
Example #10
Source File: RandomTrackSelection.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
@Override
public void updateSelectedTrack(
    long playbackPositionUs,
    long bufferedDurationUs,
    long availableDurationUs,
    List<? extends MediaChunk> queue,
    MediaChunkIterator[] mediaChunkIterators) {
  // Count the number of non-blacklisted formats.
  long nowMs = SystemClock.elapsedRealtime();
  int nonBlacklistedFormatCount = 0;
  for (int i = 0; i < length; i++) {
    if (!isBlacklisted(i, nowMs)) {
      nonBlacklistedFormatCount++;
    }
  }

  selectedIndex = random.nextInt(nonBlacklistedFormatCount);
  if (nonBlacklistedFormatCount != length) {
    // Adjust the format index to account for blacklisted formats.
    nonBlacklistedFormatCount = 0;
    for (int i = 0; i < length; i++) {
      if (!isBlacklisted(i, nowMs) && selectedIndex == nonBlacklistedFormatCount++) {
        selectedIndex = i;
        return;
      }
    }
  }
}
 
Example #11
Source File: HlsChunkSource.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Returns an array of {@link MediaChunkIterator}s for upcoming media chunks.
 *
 * @param previous The previous media chunk. May be null.
 * @param loadPositionUs The position at which the iterators will start.
 * @return Array of {@link MediaChunkIterator}s for each track.
 */
public MediaChunkIterator[] createMediaChunkIterators(
    @Nullable HlsMediaChunk previous, long loadPositionUs) {
  int oldTrackIndex = previous == null ? C.INDEX_UNSET : trackGroup.indexOf(previous.trackFormat);
  MediaChunkIterator[] chunkIterators = new MediaChunkIterator[trackSelection.length()];
  for (int i = 0; i < chunkIterators.length; i++) {
    int trackIndex = trackSelection.getIndexInTrackGroup(i);
    Uri playlistUrl = playlistUrls[trackIndex];
    if (!playlistTracker.isSnapshotValid(playlistUrl)) {
      chunkIterators[i] = MediaChunkIterator.EMPTY;
      continue;
    }
    HlsMediaPlaylist playlist =
        playlistTracker.getPlaylistSnapshot(playlistUrl, /* isForPlayback= */ false);
    long startOfPlaylistInPeriodUs =
        playlist.startTimeUs - playlistTracker.getInitialStartTimeUs();
    boolean switchingTrack = trackIndex != oldTrackIndex;
    long chunkMediaSequence =
        getChunkMediaSequence(
            previous, switchingTrack, playlist, startOfPlaylistInPeriodUs, loadPositionUs);
    if (chunkMediaSequence < playlist.mediaSequence) {
      chunkIterators[i] = MediaChunkIterator.EMPTY;
      continue;
    }
    int chunkIndex = (int) (chunkMediaSequence - playlist.mediaSequence);
    chunkIterators[i] =
        new HlsMediaPlaylistSegmentIterator(playlist, startOfPlaylistInPeriodUs, chunkIndex);
  }
  return chunkIterators;
}
 
Example #12
Source File: BufferSizeAdaptationBuilder.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
@Override
public void updateSelectedTrack(
    long playbackPositionUs,
    long bufferedDurationUs,
    long availableDurationUs,
    List<? extends MediaChunk> queue,
    MediaChunkIterator[] mediaChunkIterators) {
  updateFormatBitrates(/* nowMs= */ clock.elapsedRealtime());

  // Make initial selection
  if (selectionReason == C.SELECTION_REASON_UNKNOWN) {
    selectionReason = C.SELECTION_REASON_INITIAL;
    selectedIndex = selectIdealIndexUsingBandwidth(/* isInitialSelection= */ true);
    return;
  }

  long bufferUs = getCurrentPeriodBufferedDurationUs(playbackPositionUs, bufferedDurationUs);
  int oldSelectedIndex = selectedIndex;
  if (isInSteadyState) {
    selectIndexSteadyState(bufferUs);
  } else {
    selectIndexStartUpPhase(bufferUs);
  }
  if (selectedIndex != oldSelectedIndex) {
    selectionReason = C.SELECTION_REASON_ADAPTIVE;
  }
}
 
Example #13
Source File: RandomTrackSelection.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
@Override
public void updateSelectedTrack(
    long playbackPositionUs,
    long bufferedDurationUs,
    long availableDurationUs,
    List<? extends MediaChunk> queue,
    MediaChunkIterator[] mediaChunkIterators) {
  // Count the number of non-blacklisted formats.
  long nowMs = SystemClock.elapsedRealtime();
  int nonBlacklistedFormatCount = 0;
  for (int i = 0; i < length; i++) {
    if (!isBlacklisted(i, nowMs)) {
      nonBlacklistedFormatCount++;
    }
  }

  selectedIndex = random.nextInt(nonBlacklistedFormatCount);
  if (nonBlacklistedFormatCount != length) {
    // Adjust the format index to account for blacklisted formats.
    nonBlacklistedFormatCount = 0;
    for (int i = 0; i < length; i++) {
      if (!isBlacklisted(i, nowMs) && selectedIndex == nonBlacklistedFormatCount++) {
        selectedIndex = i;
        return;
      }
    }
  }
}
 
Example #14
Source File: FixedTrackSelection.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
@Override
public void updateSelectedTrack(
    long playbackPositionUs,
    long bufferedDurationUs,
    long availableDurationUs,
    List<? extends MediaChunk> queue,
    MediaChunkIterator[] mediaChunkIterators) {
  // Do nothing.
}
 
Example #15
Source File: HlsChunkSource.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Returns an array of {@link MediaChunkIterator}s for upcoming media chunks.
 *
 * @param previous The previous media chunk. May be null.
 * @param loadPositionUs The position at which the iterators will start.
 * @return Array of {@link MediaChunkIterator}s for each track.
 */
public MediaChunkIterator[] createMediaChunkIterators(
    @Nullable HlsMediaChunk previous, long loadPositionUs) {
  int oldTrackIndex = previous == null ? C.INDEX_UNSET : trackGroup.indexOf(previous.trackFormat);
  MediaChunkIterator[] chunkIterators = new MediaChunkIterator[trackSelection.length()];
  for (int i = 0; i < chunkIterators.length; i++) {
    int trackIndex = trackSelection.getIndexInTrackGroup(i);
    Uri playlistUrl = playlistUrls[trackIndex];
    if (!playlistTracker.isSnapshotValid(playlistUrl)) {
      chunkIterators[i] = MediaChunkIterator.EMPTY;
      continue;
    }
    HlsMediaPlaylist playlist =
        playlistTracker.getPlaylistSnapshot(playlistUrl, /* isForPlayback= */ false);
    long startOfPlaylistInPeriodUs =
        playlist.startTimeUs - playlistTracker.getInitialStartTimeUs();
    boolean switchingTrack = trackIndex != oldTrackIndex;
    long chunkMediaSequence =
        getChunkMediaSequence(
            previous, switchingTrack, playlist, startOfPlaylistInPeriodUs, loadPositionUs);
    if (chunkMediaSequence < playlist.mediaSequence) {
      chunkIterators[i] = MediaChunkIterator.EMPTY;
      continue;
    }
    int chunkIndex = (int) (chunkMediaSequence - playlist.mediaSequence);
    chunkIterators[i] =
        new HlsMediaPlaylistSegmentIterator(playlist, startOfPlaylistInPeriodUs, chunkIndex);
  }
  return chunkIterators;
}
 
Example #16
Source File: DownloadHelper.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
@Override
public void updateSelectedTrack(
    long playbackPositionUs,
    long bufferedDurationUs,
    long availableDurationUs,
    List<? extends MediaChunk> queue,
    MediaChunkIterator[] mediaChunkIterators) {
  // Do nothing.
}
 
Example #17
Source File: FixedTrackSelection.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
@Override
public void updateSelectedTrack(
    long playbackPositionUs,
    long bufferedDurationUs,
    long availableDurationUs,
    List<? extends MediaChunk> queue,
    MediaChunkIterator[] mediaChunkIterators) {
  // Do nothing.
}
 
Example #18
Source File: BufferSizeAdaptationBuilder.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
@Override
public void updateSelectedTrack(
    long playbackPositionUs,
    long bufferedDurationUs,
    long availableDurationUs,
    List<? extends MediaChunk> queue,
    MediaChunkIterator[] mediaChunkIterators) {
  updateFormatBitrates(/* nowMs= */ clock.elapsedRealtime());

  // Make initial selection
  if (selectionReason == C.SELECTION_REASON_UNKNOWN) {
    selectionReason = C.SELECTION_REASON_INITIAL;
    selectedIndex = selectIdealIndexUsingBandwidth(/* isInitialSelection= */ true);
    return;
  }

  long bufferUs = getCurrentPeriodBufferedDurationUs(playbackPositionUs, bufferedDurationUs);
  int oldSelectedIndex = selectedIndex;
  if (isInSteadyState) {
    selectIndexSteadyState(bufferUs);
  } else {
    selectIndexStartUpPhase(bufferUs);
  }
  if (selectedIndex != oldSelectedIndex) {
    selectionReason = C.SELECTION_REASON_ADAPTIVE;
  }
}
 
Example #19
Source File: HlsChunkSource.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
/**
 * Returns an array of {@link MediaChunkIterator}s for upcoming media chunks.
 *
 * @param previous The previous media chunk. May be null.
 * @param loadPositionUs The position at which the iterators will start.
 * @return Array of {@link MediaChunkIterator}s for each track.
 */
public MediaChunkIterator[] createMediaChunkIterators(
    @Nullable HlsMediaChunk previous, long loadPositionUs) {
  int oldTrackIndex = previous == null ? C.INDEX_UNSET : trackGroup.indexOf(previous.trackFormat);
  MediaChunkIterator[] chunkIterators = new MediaChunkIterator[trackSelection.length()];
  for (int i = 0; i < chunkIterators.length; i++) {
    int trackIndex = trackSelection.getIndexInTrackGroup(i);
    Uri playlistUrl = playlistUrls[trackIndex];
    if (!playlistTracker.isSnapshotValid(playlistUrl)) {
      chunkIterators[i] = MediaChunkIterator.EMPTY;
      continue;
    }
    HlsMediaPlaylist playlist =
        playlistTracker.getPlaylistSnapshot(playlistUrl, /* isForPlayback= */ false);
    // Playlist snapshot is valid (checked by if() above) so playlist must be non-null.
    Assertions.checkNotNull(playlist);
    long startOfPlaylistInPeriodUs =
        playlist.startTimeUs - playlistTracker.getInitialStartTimeUs();
    boolean switchingTrack = trackIndex != oldTrackIndex;
    long chunkMediaSequence =
        getChunkMediaSequence(
            previous, switchingTrack, playlist, startOfPlaylistInPeriodUs, loadPositionUs);
    if (chunkMediaSequence < playlist.mediaSequence) {
      chunkIterators[i] = MediaChunkIterator.EMPTY;
      continue;
    }
    int chunkIndex = (int) (chunkMediaSequence - playlist.mediaSequence);
    chunkIterators[i] =
        new HlsMediaPlaylistSegmentIterator(playlist, startOfPlaylistInPeriodUs, chunkIndex);
  }
  return chunkIterators;
}
 
Example #20
Source File: FixedTrackSelection.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
@Override
public void updateSelectedTrack(
    long playbackPositionUs,
    long bufferedDurationUs,
    long availableDurationUs,
    List<? extends MediaChunk> queue,
    MediaChunkIterator[] mediaChunkIterators) {
  // Do nothing.
}
 
Example #21
Source File: RandomTrackSelection.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
@Override
public void updateSelectedTrack(
    long playbackPositionUs,
    long bufferedDurationUs,
    long availableDurationUs,
    List<? extends MediaChunk> queue,
    MediaChunkIterator[] mediaChunkIterators) {
  // Count the number of non-blacklisted formats.
  long nowMs = SystemClock.elapsedRealtime();
  int nonBlacklistedFormatCount = 0;
  for (int i = 0; i < length; i++) {
    if (!isBlacklisted(i, nowMs)) {
      nonBlacklistedFormatCount++;
    }
  }

  selectedIndex = random.nextInt(nonBlacklistedFormatCount);
  if (nonBlacklistedFormatCount != length) {
    // Adjust the format index to account for blacklisted formats.
    nonBlacklistedFormatCount = 0;
    for (int i = 0; i < length; i++) {
      if (!isBlacklisted(i, nowMs) && selectedIndex == nonBlacklistedFormatCount++) {
        selectedIndex = i;
        return;
      }
    }
  }
}
 
Example #22
Source File: BufferSizeAdaptationBuilder.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
@Override
public void updateSelectedTrack(
    long playbackPositionUs,
    long bufferedDurationUs,
    long availableDurationUs,
    List<? extends MediaChunk> queue,
    MediaChunkIterator[] mediaChunkIterators) {
  updateFormatBitrates(/* nowMs= */ clock.elapsedRealtime());

  // Make initial selection
  if (selectionReason == C.SELECTION_REASON_UNKNOWN) {
    selectionReason = C.SELECTION_REASON_INITIAL;
    selectedIndex = selectIdealIndexUsingBandwidth(/* isInitialSelection= */ true);
    return;
  }

  long bufferUs = getCurrentPeriodBufferedDurationUs(playbackPositionUs, bufferedDurationUs);
  int oldSelectedIndex = selectedIndex;
  if (isInSteadyState) {
    selectIndexSteadyState(bufferUs);
  } else {
    selectIndexStartUpPhase(bufferUs);
  }
  if (selectedIndex != oldSelectedIndex) {
    selectionReason = C.SELECTION_REASON_ADAPTIVE;
  }
}
 
Example #23
Source File: TrackSelectionUtil.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Returns bitrate values for a set of tracks whose upcoming media chunk iterators and formats are
 * given.
 *
 * <p>If an average bitrate can't be calculated, an estimation is calculated using average bitrate
 * of another track and the ratio of the bitrate values defined in the formats of the two tracks.
 *
 * @param iterators An array of {@link MediaChunkIterator}s providing information about the
 *     sequence of upcoming media chunks for each track.
 * @param formats The track formats.
 * @param maxDurationUs Maximum duration of chunks to be included in average bitrate values, in
 *     microseconds.
 * @param bitrates If not null, stores bitrate values in this array.
 * @return Average bitrate values for the tracks. If for a track, an average bitrate or an
 *     estimation can't be calculated, {@link Format#NO_VALUE} is set.
 * @see #getAverageBitrate(MediaChunkIterator, long)
 */
@VisibleForTesting
/* package */ static int[] getBitratesUsingFutureInfo(
    MediaChunkIterator[] iterators,
    Format[] formats,
    long maxDurationUs,
    @Nullable int[] bitrates) {
  int trackCount = iterators.length;
  Assertions.checkArgument(trackCount == formats.length);
  if (trackCount == 0) {
    return new int[0];
  }
  if (bitrates == null) {
    bitrates = new int[trackCount];
  }
  if (maxDurationUs == 0) {
    Arrays.fill(bitrates, Format.NO_VALUE);
    return bitrates;
  }

  int[] formatBitrates = new int[trackCount];
  float[] bitrateRatios = new float[trackCount];
  boolean needEstimateBitrate = false;
  boolean canEstimateBitrate = false;
  for (int i = 0; i < trackCount; i++) {
    int bitrate = getAverageBitrate(iterators[i], maxDurationUs);
    if (bitrate != Format.NO_VALUE) {
      int formatBitrate = formats[i].bitrate;
      formatBitrates[i] = formatBitrate;
      if (formatBitrate != Format.NO_VALUE) {
        bitrateRatios[i] = ((float) bitrate) / formatBitrate;
        canEstimateBitrate = true;
      }
    } else {
      needEstimateBitrate = true;
      formatBitrates[i] = Format.NO_VALUE;
    }
    bitrates[i] = bitrate;
  }

  if (needEstimateBitrate && canEstimateBitrate) {
    estimateBitrates(bitrates, formats, formatBitrates, bitrateRatios);
  }
  return bitrates;
}
 
Example #24
Source File: TrackSelectionUtil.java    From Telegram with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Returns bitrate values for a set of tracks whose upcoming media chunk iterators and formats are
 * given.
 *
 * <p>If an average bitrate can't be calculated, an estimation is calculated using average bitrate
 * of another track and the ratio of the bitrate values defined in the formats of the two tracks.
 *
 * @param iterators An array of {@link MediaChunkIterator}s providing information about the
 *     sequence of upcoming media chunks for each track.
 * @param formats The track formats.
 * @param maxDurationUs Maximum duration of chunks to be included in average bitrate values, in
 *     microseconds.
 * @param bitrates If not null, stores bitrate values in this array.
 * @return Average bitrate values for the tracks. If for a track, an average bitrate or an
 *     estimation can't be calculated, {@link Format#NO_VALUE} is set.
 * @see #getAverageBitrate(MediaChunkIterator, long)
 */
@VisibleForTesting
/* package */ static int[] getBitratesUsingFutureInfo(
    MediaChunkIterator[] iterators,
    Format[] formats,
    long maxDurationUs,
    @Nullable int[] bitrates) {
  int trackCount = iterators.length;
  Assertions.checkArgument(trackCount == formats.length);
  if (trackCount == 0) {
    return new int[0];
  }
  if (bitrates == null) {
    bitrates = new int[trackCount];
  }
  if (maxDurationUs == 0) {
    Arrays.fill(bitrates, Format.NO_VALUE);
    return bitrates;
  }

  int[] formatBitrates = new int[trackCount];
  float[] bitrateRatios = new float[trackCount];
  boolean needEstimateBitrate = false;
  boolean canEstimateBitrate = false;
  for (int i = 0; i < trackCount; i++) {
    int bitrate = getAverageBitrate(iterators[i], maxDurationUs);
    if (bitrate != Format.NO_VALUE) {
      int formatBitrate = formats[i].bitrate;
      formatBitrates[i] = formatBitrate;
      if (formatBitrate != Format.NO_VALUE) {
        bitrateRatios[i] = ((float) bitrate) / formatBitrate;
        canEstimateBitrate = true;
      }
    } else {
      needEstimateBitrate = true;
      formatBitrates[i] = Format.NO_VALUE;
    }
    bitrates[i] = bitrate;
  }

  if (needEstimateBitrate && canEstimateBitrate) {
    estimateBitrates(bitrates, formats, formatBitrates, bitrateRatios);
  }
  return bitrates;
}
 
Example #25
Source File: AdaptiveTrackSelection.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
@Override
public void updateSelectedTrack(
    long playbackPositionUs,
    long bufferedDurationUs,
    long availableDurationUs,
    List<? extends MediaChunk> queue,
    MediaChunkIterator[] mediaChunkIterators) {
  long nowMs = clock.elapsedRealtime();

  // Make initial selection
  if (reason == C.SELECTION_REASON_UNKNOWN) {
    reason = C.SELECTION_REASON_INITIAL;
    selectedIndex = determineIdealSelectedIndex(nowMs);
    return;
  }

  // Stash the current selection, then make a new one.
  int currentSelectedIndex = selectedIndex;
  selectedIndex = determineIdealSelectedIndex(nowMs);
  if (selectedIndex == currentSelectedIndex) {
    return;
  }

  if (!isBlacklisted(currentSelectedIndex, nowMs)) {
    // Revert back to the current selection if conditions are not suitable for switching.
    Format currentFormat = getFormat(currentSelectedIndex);
    Format selectedFormat = getFormat(selectedIndex);
    if (selectedFormat.bitrate > currentFormat.bitrate
        && bufferedDurationUs < minDurationForQualityIncreaseUs(availableDurationUs)) {
      // The selected track is a higher quality, but we have insufficient buffer to safely switch
      // up. Defer switching up for now.
      selectedIndex = currentSelectedIndex;
    } else if (selectedFormat.bitrate < currentFormat.bitrate
        && bufferedDurationUs >= maxDurationForQualityDecreaseUs) {
      // The selected track is a lower quality, but we have sufficient buffer to defer switching
      // down for now.
      selectedIndex = currentSelectedIndex;
    }
  }
  // If we adapted, update the trigger.
  if (selectedIndex != currentSelectedIndex) {
    reason = C.SELECTION_REASON_ADAPTIVE;
  }
}
 
Example #26
Source File: AdaptiveTrackSelection.java    From Telegram with GNU General Public License v2.0 4 votes vote down vote up
@Override
public void updateSelectedTrack(
    long playbackPositionUs,
    long bufferedDurationUs,
    long availableDurationUs,
    List<? extends MediaChunk> queue,
    MediaChunkIterator[] mediaChunkIterators) {
  long nowMs = clock.elapsedRealtime();

  // Update the estimated track bitrates.
  trackBitrateEstimator.getBitrates(formats, queue, mediaChunkIterators, trackBitrates);

  // Make initial selection
  if (reason == C.SELECTION_REASON_UNKNOWN) {
    reason = C.SELECTION_REASON_INITIAL;
    selectedIndex = determineIdealSelectedIndex(nowMs, trackBitrates);
    return;
  }

  // Stash the current selection, then make a new one.
  int currentSelectedIndex = selectedIndex;
  selectedIndex = determineIdealSelectedIndex(nowMs, trackBitrates);
  if (selectedIndex == currentSelectedIndex) {
    return;
  }

  if (!isBlacklisted(currentSelectedIndex, nowMs)) {
    // Revert back to the current selection if conditions are not suitable for switching.
    Format currentFormat = getFormat(currentSelectedIndex);
    Format selectedFormat = getFormat(selectedIndex);
    if (selectedFormat.bitrate > currentFormat.bitrate
        && bufferedDurationUs < minDurationForQualityIncreaseUs(availableDurationUs)) {
      // The selected track is a higher quality, but we have insufficient buffer to safely switch
      // up. Defer switching up for now.
      selectedIndex = currentSelectedIndex;
    } else if (selectedFormat.bitrate < currentFormat.bitrate
        && bufferedDurationUs >= maxDurationForQualityDecreaseUs) {
      // The selected track is a lower quality, but we have sufficient buffer to defer switching
      // down for now.
      selectedIndex = currentSelectedIndex;
    }
  }
  // If we adapted, update the trigger.
  if (selectedIndex != currentSelectedIndex) {
    reason = C.SELECTION_REASON_ADAPTIVE;
  }
}
 
Example #27
Source File: AdaptiveTrackSelection.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
@Override
public void updateSelectedTrack(
    long playbackPositionUs,
    long bufferedDurationUs,
    long availableDurationUs,
    List<? extends MediaChunk> queue,
    MediaChunkIterator[] mediaChunkIterators) {
  long nowMs = clock.elapsedRealtime();

  // Update the estimated track bitrates.
  trackBitrateEstimator.getBitrates(formats, queue, mediaChunkIterators, trackBitrates);

  // Make initial selection
  if (reason == C.SELECTION_REASON_UNKNOWN) {
    reason = C.SELECTION_REASON_INITIAL;
    selectedIndex = determineIdealSelectedIndex(nowMs, trackBitrates);
    return;
  }

  // Stash the current selection, then make a new one.
  int currentSelectedIndex = selectedIndex;
  selectedIndex = determineIdealSelectedIndex(nowMs, trackBitrates);
  if (selectedIndex == currentSelectedIndex) {
    return;
  }

  if (!isBlacklisted(currentSelectedIndex, nowMs)) {
    // Revert back to the current selection if conditions are not suitable for switching.
    Format currentFormat = getFormat(currentSelectedIndex);
    Format selectedFormat = getFormat(selectedIndex);
    if (selectedFormat.bitrate > currentFormat.bitrate
        && bufferedDurationUs < minDurationForQualityIncreaseUs(availableDurationUs)) {
      // The selected track is a higher quality, but we have insufficient buffer to safely switch
      // up. Defer switching up for now.
      selectedIndex = currentSelectedIndex;
    } else if (selectedFormat.bitrate < currentFormat.bitrate
        && bufferedDurationUs >= maxDurationForQualityDecreaseUs) {
      // The selected track is a lower quality, but we have sufficient buffer to defer switching
      // down for now.
      selectedIndex = currentSelectedIndex;
    }
  }
  // If we adapted, update the trigger.
  if (selectedIndex != currentSelectedIndex) {
    reason = C.SELECTION_REASON_ADAPTIVE;
  }
}
 
Example #28
Source File: TrackSelection.java    From Telegram with GNU General Public License v2.0 3 votes vote down vote up
/**
 * Updates the selected track for sources that load media in discrete {@link MediaChunk}s.
 *
 * <p>This method may only be called when the selection is enabled.
 *
 * @param playbackPositionUs The current playback position in microseconds. If playback of the
 *     period to which this track selection belongs has not yet started, the value will be the
 *     starting position in the period minus the duration of any media in previous periods still
 *     to be played.
 * @param bufferedDurationUs The duration of media currently buffered from the current playback
 *     position, in microseconds. Note that the next load position can be calculated as {@code
 *     (playbackPositionUs + bufferedDurationUs)}.
 * @param availableDurationUs The duration of media available for buffering from the current
 *     playback position, in microseconds, or {@link C#TIME_UNSET} if media can be buffered to the
 *     end of the current period. Note that if not set to {@link C#TIME_UNSET}, the position up to
 *     which media is available for buffering can be calculated as {@code (playbackPositionUs +
 *     availableDurationUs)}.
 * @param queue The queue of already buffered {@link MediaChunk}s. Must not be modified.
 * @param mediaChunkIterators An array of {@link MediaChunkIterator}s providing information about
 *     the sequence of upcoming media chunks for each track in the selection. All iterators start
 *     from the media chunk which will be loaded next if the respective track is selected. Note
 *     that this information may not be available for all tracks, and so some iterators may be
 *     empty.
 */
default void updateSelectedTrack(
    long playbackPositionUs,
    long bufferedDurationUs,
    long availableDurationUs,
    List<? extends MediaChunk> queue,
    MediaChunkIterator[] mediaChunkIterators) {
  updateSelectedTrack(playbackPositionUs, bufferedDurationUs, availableDurationUs);
}
 
Example #29
Source File: TrackSelection.java    From MediaSDK with Apache License 2.0 3 votes vote down vote up
/**
 * Updates the selected track for sources that load media in discrete {@link MediaChunk}s.
 *
 * <p>This method may only be called when the selection is enabled.
 *
 * @param playbackPositionUs The current playback position in microseconds. If playback of the
 *     period to which this track selection belongs has not yet started, the value will be the
 *     starting position in the period minus the duration of any media in previous periods still
 *     to be played.
 * @param bufferedDurationUs The duration of media currently buffered from the current playback
 *     position, in microseconds. Note that the next load position can be calculated as {@code
 *     (playbackPositionUs + bufferedDurationUs)}.
 * @param availableDurationUs The duration of media available for buffering from the current
 *     playback position, in microseconds, or {@link C#TIME_UNSET} if media can be buffered to the
 *     end of the current period. Note that if not set to {@link C#TIME_UNSET}, the position up to
 *     which media is available for buffering can be calculated as {@code (playbackPositionUs +
 *     availableDurationUs)}.
 * @param queue The queue of already buffered {@link MediaChunk}s. Must not be modified.
 * @param mediaChunkIterators An array of {@link MediaChunkIterator}s providing information about
 *     the sequence of upcoming media chunks for each track in the selection. All iterators start
 *     from the media chunk which will be loaded next if the respective track is selected. Note
 *     that this information may not be available for all tracks, and so some iterators may be
 *     empty.
 */
void updateSelectedTrack(
        long playbackPositionUs,
        long bufferedDurationUs,
        long availableDurationUs,
        List<? extends MediaChunk> queue,
        MediaChunkIterator[] mediaChunkIterators);
 
Example #30
Source File: TrackSelection.java    From Telegram-FOSS with GNU General Public License v2.0 3 votes vote down vote up
/**
 * Updates the selected track for sources that load media in discrete {@link MediaChunk}s.
 *
 * <p>This method may only be called when the selection is enabled.
 *
 * @param playbackPositionUs The current playback position in microseconds. If playback of the
 *     period to which this track selection belongs has not yet started, the value will be the
 *     starting position in the period minus the duration of any media in previous periods still
 *     to be played.
 * @param bufferedDurationUs The duration of media currently buffered from the current playback
 *     position, in microseconds. Note that the next load position can be calculated as {@code
 *     (playbackPositionUs + bufferedDurationUs)}.
 * @param availableDurationUs The duration of media available for buffering from the current
 *     playback position, in microseconds, or {@link C#TIME_UNSET} if media can be buffered to the
 *     end of the current period. Note that if not set to {@link C#TIME_UNSET}, the position up to
 *     which media is available for buffering can be calculated as {@code (playbackPositionUs +
 *     availableDurationUs)}.
 * @param queue The queue of already buffered {@link MediaChunk}s. Must not be modified.
 * @param mediaChunkIterators An array of {@link MediaChunkIterator}s providing information about
 *     the sequence of upcoming media chunks for each track in the selection. All iterators start
 *     from the media chunk which will be loaded next if the respective track is selected. Note
 *     that this information may not be available for all tracks, and so some iterators may be
 *     empty.
 */
default void updateSelectedTrack(
    long playbackPositionUs,
    long bufferedDurationUs,
    long availableDurationUs,
    List<? extends MediaChunk> queue,
    MediaChunkIterator[] mediaChunkIterators) {
  updateSelectedTrack(playbackPositionUs, bufferedDurationUs, availableDurationUs);
}