com.google.android.exoplayer2.Timeline类的使用及代码示例

x33g5p2x  于2022-01-30 转载在 其他  
字(14.9k)|赞(0)|评价(0)|浏览(301)

本文整理了Java中com.google.android.exoplayer2.Timeline类的一些代码示例,展示了Timeline类的具体用法。这些代码示例主要来源于Github/Stackoverflow/Maven等平台,是从一些精选项目中提取出来的代码,具有较强的参考意义,能在一定程度帮忙到你。Timeline类的具体详情如下:
包路径:com.google.android.exoplayer2.Timeline
类名称:Timeline

Timeline介绍

[英]A flexible representation of the structure of media. A timeline is able to represent the structure of a wide variety of media, from simple cases like a single media file through to complex compositions of media such as playlists and streams with inserted ads. Instances are immutable. For cases where media is changing dynamically (e.g. live streams), a timeline provides a snapshot of the current state.

A timeline consists of related Periods and Windows. A period defines a single logical piece of media, for example a media file. It may also define groups of ads inserted into the media, along with information about whether those ads have been loaded and played. A window spans one or more periods, defining the region within those periods that's currently available for playback along with additional information such as whether seeking is supported within the window. Each window defines a default position, which is the position from which playback will start when the player starts playing the window. The following examples illustrate timelines for various use cases.

Single media file or on-demand stream

A timeline for a single media file or on-demand stream consists of a single period and window. The window spans the whole period, indicating that all parts of the media are available for playback. The window's default position is typically at the start of the period (indicated by the black dot in the figure above).

Playlist of media files or on-demand streams

A timeline for a playlist of media files or on-demand streams consists of multiple periods, each with its own window. Each window spans the whole of the corresponding period, and typically has a default position at the start of the period. The properties of the periods and windows (e.g. their durations and whether the window is seekable) will often only become known when the player starts buffering the corresponding file or stream.

Live stream with limited availability

A timeline for a live stream consists of a period whose duration is unknown, since it's continually extending as more content is broadcast. If content only remains available for a limited period of time then the window may start at a non-zero position, defining the region of content that can still be played. The window will have Window#isDynamic set to true if the stream is still live. Its default position is typically near to the live edge (indicated by the black dot in the figure above).

Live stream with indefinite availability

A timeline for a live stream with indefinite availability is similar to the Live stream with limited availability case, except that the window starts at the beginning of the period to indicate that all of the previously broadcast content can still be played.

Live stream with multiple periods

This case arises when a live stream is explicitly divided into separate periods, for example at content boundaries. This case is similar to the Live stream with limited availability case, except that the window may span more than one period. Multiple periods are also possible in the indefinite availability case.

On-demand stream followed by live stream

This case is the concatenation of the Single media file or on-demand stream and Live stream with multiple periods cases. When playback of the on-demand stream ends, playback of the live stream will start from its default position near the live edge.

On-demand stream with mid-roll ads

This case includes mid-roll ad groups, which are defined as part of the timeline's single period. The period can be queried for information about the ad groups and the ads they contain.
[中]媒体结构的灵活表现。时间线能够表示各种媒体的结构,从简单的案例(如单个媒体文件)到复杂的媒体组合(如播放列表和插入广告的流)。实例是不变的。对于媒体动态变化的情况(例如实时流),时间线提供当前状态的快照。
时间线由相关的时段和窗口组成。句点定义了单个逻辑介质,例如介质文件。它还可以定义插入媒体的广告组,以及有关这些广告是否已加载和播放的信息。窗口跨越一个或多个时段,定义这些时段内当前可供播放的区域,以及其他信息,如窗口内是否支持搜索。每个窗口定义一个默认位置,即播放器开始播放窗口时开始播放的位置。以下示例说明了各种用例的时间表。
####单个媒体文件或按需流
单个媒体文件或点播流的时间线由单个时段和窗口组成。该窗口跨越整个时段,表示媒体的所有部分都可用于播放。窗口的默认位置通常在时段开始时(由上图中的黑点指示)。
####媒体文件或点播流的播放列表
媒体文件或点播流播放列表的时间线由多个时段组成,每个时段都有自己的窗口。每个窗口跨越整个相应的时段,通常在时段开始时有一个默认位置。只有在播放器开始缓冲相应的文件或流时,才会知道时段和窗口的属性(例如,它们的持续时间以及窗口是否可查找)。
####可用性有限的直播
直播流的时间线由一个持续时间未知的时段组成,因为随着更多内容的播放,它会不断延长。如果内容仅在有限的时间内保持可用,则窗口可能从非零位置开始,定义仍然可以播放的内容区域。如果流仍处于活动状态,则窗口将“窗口#isDynamic”设置为true。其默认位置通常靠近活动边(由上图中的黑点指示)。
####无限可用的实时流
不确定可用性的直播流的时间线与Live stream with limited availability的情况类似,只是窗口从时段开始时开始,以指示所有以前的广播内容仍然可以播放。
####多时段直播
当一个实时流被明确划分为不同的时段(例如在内容边界)时,就会出现这种情况。这种情况类似于{$1$}情况,只是窗口可能跨越多个时段。在不确定可用性的情况下,也可能出现多个时段。
####点播流之后是直播流
这个案例是{$2$}和{$3$}案例的串联。当按需流的播放结束时,直播流的播放将从直播边缘附近的默认位置开始。
####带中期广告的点播流
本案例包括中期广告组,它们被定义为时间线单周期的一部分。可以查询时段以获取有关广告组及其包含的广告的信息。

代码示例

代码示例来源:origin: google/ExoPlayer

@Override
@Nullable
public Object getTag() {
 boolean hasTimeline = timeline != null && !timeline.isEmpty();
 return hasTimeline ? timeline.getWindow(0, new Timeline.Window()).tag : null;
}

代码示例来源:origin: google/ExoPlayer

/**
 * Asserts that the durations of the periods in the {@link Timeline} and the durations in the
 * given sequence are equal.
 */
public static void assertPeriodDurations(Timeline timeline, long... durationsUs) {
 int periodCount = timeline.getPeriodCount();
 assertThat(periodCount).isEqualTo(durationsUs.length);
 Period period = new Period();
 for (int i = 0; i < periodCount; i++) {
  assertThat(timeline.getPeriod(i, period).durationUs).isEqualTo(durationsUs[i]);
 }
}

代码示例来源:origin: google/ExoPlayer

@Override
@Nullable
public final Object getCurrentTag() {
 int windowIndex = getCurrentWindowIndex();
 Timeline timeline = getCurrentTimeline();
 return windowIndex >= timeline.getWindowCount()
   ? null
   : timeline.getWindow(windowIndex, window, /* setTag= */ true).tag;
}

代码示例来源:origin: google/ExoPlayer

/**
 * Populates a {@link Period} with data for the period with the specified unique identifier.
 *
 * @param periodUid The unique identifier of the period.
 * @param period The {@link Period} to populate. Must not be null.
 * @return The populated {@link Period}, for convenience.
 */
public Period getPeriodByUid(Object periodUid, Period period) {
 return getPeriod(getIndexOfPeriod(periodUid), period, /* setIds= */ true);
}

代码示例来源:origin: google/ExoPlayer

/**
 * Returns the index of the last window in the playback order depending on whether shuffling is
 * enabled.
 *
 * @param shuffleModeEnabled Whether shuffling is enabled.
 * @return The index of the last window in the playback order, or {@link C#INDEX_UNSET} if the
 *     timeline is empty.
 */
public int getLastWindowIndex(boolean shuffleModeEnabled) {
 return isEmpty() ? C.INDEX_UNSET : getWindowCount() - 1;
}

代码示例来源:origin: google/ExoPlayer

private boolean isLastInTimeline(MediaPeriodId id, boolean isLastMediaPeriodInPeriod) {
  int periodIndex = timeline.getIndexOfPeriod(id.periodUid);
  int windowIndex = timeline.getPeriod(periodIndex, period).windowIndex;
  return !timeline.getWindow(windowIndex, window).isDynamic
    && timeline.isLastPeriod(periodIndex, period, window, repeatMode, shuffleModeEnabled)
    && isLastMediaPeriodInPeriod;
 }
}

代码示例来源:origin: google/ExoPlayer

int windowCount = timeline.getWindowCount();
assertThat(windowCount).isEqualTo(expectedPeriodCounts.length);
int[] accumulatedPeriodCounts = new int[windowCount + 1];
assertThat(timeline.getPeriodCount())
  .isEqualTo(accumulatedPeriodCounts[accumulatedPeriodCounts.length - 1]);
Window window = new Window();
Period period = new Period();
for (int i = 0; i < windowCount; i++) {
 timeline.getWindow(i, window, true);
 assertThat(window.firstPeriodIndex).isEqualTo(accumulatedPeriodCounts[i]);
 assertThat(window.lastPeriodIndex).isEqualTo(accumulatedPeriodCounts[i + 1] - 1);
for (int i = 0; i < timeline.getPeriodCount(); i++) {
 timeline.getPeriod(i, period, true);
 while (i >= accumulatedPeriodCounts[expectedWindowIndex + 1]) {
  expectedWindowIndex++;
 assertThat(timeline.getIndexOfPeriod(period.uid)).isEqualTo(i);
 assertThat(timeline.getUidOfPeriod(i)).isEqualTo(period.uid);
 for (int repeatMode : REPEAT_MODES) {
  if (i < accumulatedPeriodCounts[expectedWindowIndex + 1] - 1) {
   assertThat(timeline.getNextPeriodIndex(i, period, window, repeatMode, false))
     .isEqualTo(i + 1);
  } else {
   int nextWindow = timeline.getNextWindowIndex(expectedWindowIndex, repeatMode, false);
   int nextPeriod =
     nextWindow == C.INDEX_UNSET ? C.INDEX_UNSET : accumulatedPeriodCounts[nextWindow];
   assertThat(timeline.getNextPeriodIndex(i, period, window, repeatMode, false))

代码示例来源:origin: CarGuo/GSYVideoPlayer

@Override
public void onTimelineChanged(Timeline timeline, Object manifest, int reason) {
  int periodCount = timeline.getPeriodCount();
  int windowCount = timeline.getWindowCount();
  Log.d(TAG, "sourceInfo [periodCount=" + periodCount + ", windowCount=" + windowCount);
  for (int i = 0; i < Math.min(periodCount, MAX_TIMELINE_ITEM_LINES); i++) {
    timeline.getPeriod(i, period);
    Log.d(TAG, "  " + "period [" + getTimeString(period.getDurationMs()) + "]");
  }
  if (periodCount > MAX_TIMELINE_ITEM_LINES) {
    Log.d(TAG, "  ...");
  }
  for (int i = 0; i < Math.min(windowCount, MAX_TIMELINE_ITEM_LINES); i++) {
    timeline.getWindow(i, window);
    Log.d(TAG, "  " + "window [" + getTimeString(window.getDurationMs()) + ", "
        + window.isSeekable + ", " + window.isDynamic + "]");
  }
  if (windowCount > MAX_TIMELINE_ITEM_LINES) {
    Log.d(TAG, "  ...");
  }
  Log.d(TAG, "]");
}

代码示例来源:origin: google/ExoPlayer

@Test
public void testClippingStartAndEnd() throws IOException {
 Timeline timeline = new SinglePeriodTimeline(TEST_PERIOD_DURATION_US, true, false);
 Timeline clippedTimeline =
   getClippedTimeline(
     timeline, TEST_CLIP_AMOUNT_US, TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US * 2);
 assertThat(clippedTimeline.getWindow(0, window).getDurationUs())
   .isEqualTo(TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US * 3);
 assertThat(clippedTimeline.getPeriod(0, period).getDurationUs())
   .isEqualTo(TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US * 2);
}

代码示例来源:origin: google/ExoPlayer

@Override
public void seekTo(int windowIndex, long positionMs) {
 Timeline timeline = playbackInfo.timeline;
 if (windowIndex < 0 || (!timeline.isEmpty() && windowIndex >= timeline.getWindowCount())) {
  throw new IllegalSeekPositionException(timeline, windowIndex, positionMs);
 if (timeline.isEmpty()) {
  maskingWindowPositionMs = positionMs == C.TIME_UNSET ? 0 : positionMs;
  maskingPeriodIndex = 0;
 } else {
  long windowPositionUs = positionMs == C.TIME_UNSET
    ? timeline.getWindow(windowIndex, window).getDefaultPositionUs() : C.msToUs(positionMs);
  Pair<Object, Long> periodUidAndPosition =
    timeline.getPeriodPosition(window, period, windowIndex, windowPositionUs);
  maskingWindowPositionMs = C.usToMs(windowPositionUs);
  maskingPeriodIndex = timeline.getIndexOfPeriod(periodUidAndPosition.first);

代码示例来源:origin: google/ExoPlayer

/**
 * Returns dummy media period id for the first-to-be-played period of the current timeline.
 *
 * @param shuffleModeEnabled Whether shuffle mode is enabled.
 * @param window A writable {@link Timeline.Window}.
 * @return A dummy media period id for the first-to-be-played period of the current timeline.
 */
public MediaPeriodId getDummyFirstMediaPeriodId(
  boolean shuffleModeEnabled, Timeline.Window window) {
 if (timeline.isEmpty()) {
  return DUMMY_MEDIA_PERIOD_ID;
 }
 int firstPeriodIndex =
   timeline.getWindow(timeline.getFirstWindowIndex(shuffleModeEnabled), window)
     .firstPeriodIndex;
 return new MediaPeriodId(timeline.getUidOfPeriod(firstPeriodIndex));
}

代码示例来源:origin: google/ExoPlayer

@Override
public long getDuration() {
 if (timeline.isEmpty()) {
  return C.INDEX_UNSET;
 }
 if (isPlayingAd()) {
  long adDurationUs =
    timeline.getPeriod(0, period).getAdDurationUs(adGroupIndex, adIndexInAdGroup);
  return C.usToMs(adDurationUs);
 } else {
  return timeline.getWindow(getCurrentWindowIndex(), window).getDurationMs();
 }
}

代码示例来源:origin: google/ExoPlayer

/**
 * Returns the index of the period after the period at index {@code periodIndex} depending on the
 * {@code repeatMode} and whether shuffling is enabled.
 *
 * @param periodIndex Index of a period in the timeline.
 * @param period A {@link Period} to be used internally. Must not be null.
 * @param window A {@link Window} to be used internally. Must not be null.
 * @param repeatMode A repeat mode.
 * @param shuffleModeEnabled Whether shuffling is enabled.
 * @return The index of the next period, or {@link C#INDEX_UNSET} if this is the last period.
 */
public final int getNextPeriodIndex(int periodIndex, Period period, Window window,
  @Player.RepeatMode int repeatMode, boolean shuffleModeEnabled) {
 int windowIndex = getPeriod(periodIndex, period).windowIndex;
 if (getWindow(windowIndex, window).lastPeriodIndex == periodIndex) {
  int nextWindowIndex = getNextWindowIndex(windowIndex, repeatMode, shuffleModeEnabled);
  if (nextWindowIndex == C.INDEX_UNSET) {
   return C.INDEX_UNSET;
  }
  return getWindow(nextWindowIndex, window).firstPeriodIndex;
 }
 return periodIndex + 1;
}

代码示例来源:origin: google/ExoPlayer

/**
 * Populates a {@link Window} with data for the window at the specified index. Does not populate
 * {@link Window#tag}.
 *
 * @param windowIndex The index of the window.
 * @param window The {@link Window} to populate. Must not be null.
 * @return The populated {@link Window}, for convenience.
 */
public final Window getWindow(int windowIndex, Window window) {
 return getWindow(windowIndex, window, false);
}

代码示例来源:origin: ChangWeiBa/AesExoPlayer

/**
 * 下一首
 */
private void next() {
  Timeline timeline = player.getCurrentTimeline();
  if (timeline.isEmpty()) {
    return;
  }
  int windowIndex = player.getCurrentWindowIndex();
  Timber.e("windowIndex:" + windowIndex);
  int nextWindowIndex = timeline.getNextWindowIndex(windowIndex, player.getRepeatMode());
  Timber.e("nextWindowIndex:" + nextWindowIndex);
  Timber.e("isDynamic:" + window.isDynamic);
  Timber.e("TIME_UNSET:" + C.TIME_UNSET);
  if (nextWindowIndex != C.INDEX_UNSET) {
    player.seekTo(nextWindowIndex, C.TIME_UNSET);
  } else if (timeline.getWindow(windowIndex, window, false).isDynamic) {
    player.seekTo(windowIndex, C.TIME_UNSET);
    Timber.e("已经最后一首");
  }
}

代码示例来源:origin: ChangWeiBa/AesExoPlayer

/**
   * 上一首
   */
  private void previous() {
    Timeline timeline = player.getCurrentTimeline();
    if (timeline.isEmpty()) {
      return;
    }
    int windowIndex = player.getCurrentWindowIndex();
    timeline.getWindow(windowIndex, window);
    int previousWindowIndex = timeline.getPreviousWindowIndex(windowIndex, player.getRepeatMode());
    Timber.e("previousWindowIndex:" + previousWindowIndex);
    Timber.e("getCurrentPosition:" + player.getCurrentPosition());
    Timber.e("isDynamic:" + window.isDynamic);
    Timber.e("isSeekable:" + window.isSeekable);
    Timber.e("TIME_UNSET:" + C.TIME_UNSET);
    Timber.e("TIME_UNSET:" + C.TIME_UNSET);
    if (previousWindowIndex != C.INDEX_UNSET) {
      player.seekTo(previousWindowIndex, C.TIME_UNSET);
    } else {
      Timber.e("seekTo(0):");
      Timber.e("已经是第一首");
//            player.seekTo(0);
    }
  }

代码示例来源:origin: google/ExoPlayer

public LoopingTimeline(Timeline childTimeline, int loopCount) {
 super(/* isAtomic= */ false, new UnshuffledShuffleOrder(loopCount));
 this.childTimeline = childTimeline;
 childPeriodCount = childTimeline.getPeriodCount();
 childWindowCount = childTimeline.getWindowCount();
 this.loopCount = loopCount;
 if (childPeriodCount > 0) {
  Assertions.checkState(loopCount <= Integer.MAX_VALUE / childPeriodCount,
    "LoopingMediaSource contains too many periods");
 }
}

代码示例来源:origin: google/ExoPlayer

/**
 * Populates a {@link Period} with data for the period at the specified index. Does not populate
 * {@link Period#id} and {@link Period#uid}.
 *
 * @param periodIndex The index of the period.
 * @param period The {@link Period} to populate. Must not be null.
 * @return The populated {@link Period}, for convenience.
 */
public final Period getPeriod(int periodIndex, Period period) {
 return getPeriod(periodIndex, period, false);
}

代码示例来源:origin: google/ExoPlayer

/**
 * Returns the index of the first window in the playback order depending on whether shuffling is
 * enabled.
 *
 * @param shuffleModeEnabled Whether shuffling is enabled.
 * @return The index of the first window in the playback order, or {@link C#INDEX_UNSET} if the
 *     timeline is empty.
 */
public int getFirstWindowIndex(boolean shuffleModeEnabled) {
 return isEmpty() ? C.INDEX_UNSET : 0;
}

代码示例来源:origin: google/ExoPlayer

/**
 * Returns whether the timeline is empty.
 */
public final boolean isEmpty() {
 return getWindowCount() == 0;
}

相关文章