Search in sources :

Example 36 with Timeline

use of com.google.android.exoplayer2.Timeline in project ExoPlayer by google.

the class AdTagLoader method isWaitingForAdToLoad.

/**
 * Returns whether this instance is expecting the first ad in an the upcoming ad group to load
 * within the {@link ImaUtil.Configuration#adPreloadTimeoutMs preload timeout}.
 */
private boolean isWaitingForAdToLoad() {
    @Nullable Player player = this.player;
    if (player == null) {
        return false;
    }
    int adGroupIndex = getLoadingAdGroupIndex();
    if (adGroupIndex == C.INDEX_UNSET) {
        return false;
    }
    AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(adGroupIndex);
    if (adGroup.count != C.LENGTH_UNSET && adGroup.count != 0 && adGroup.states[0] != AdPlaybackState.AD_STATE_UNAVAILABLE) {
        // An ad is available already.
        return false;
    }
    long adGroupTimeMs = Util.usToMs(adGroup.timeUs);
    long contentPositionMs = getContentPeriodPositionMs(player, timeline, period);
    long timeUntilAdMs = adGroupTimeMs - contentPositionMs;
    return timeUntilAdMs < configuration.adPreloadTimeoutMs;
}
Also used : Player(com.google.android.exoplayer2.Player) VideoAdPlayer(com.google.ads.interactivemedia.v3.api.player.VideoAdPlayer) AdPlaybackState(com.google.android.exoplayer2.source.ads.AdPlaybackState) Nullable(androidx.annotation.Nullable)

Example 37 with Timeline

use of com.google.android.exoplayer2.Timeline in project ExoPlayer by google.

the class ImaUtil method splitAdPlaybackStateForPeriods.

/**
 * Splits an {@link AdPlaybackState} into a separate {@link AdPlaybackState} for each period of a
 * content timeline.
 *
 * <p>If a period is enclosed by an ad group, the period is considered an ad period. Splitting
 * results in a separate {@link AdPlaybackState ad playback state} for each period that has either
 * no ads or a single ad. In the latter case, the duration of the single ad is set to the duration
 * of the period consuming the entire duration of the period. Accordingly an ad period does not
 * contribute to the duration of the containing window.
 *
 * @param adPlaybackState The ad playback state to be split.
 * @param contentTimeline The content timeline for each period of which to create an {@link
 *     AdPlaybackState}.
 * @return A map of ad playback states for each period UID in the content timeline.
 */
public static ImmutableMap<Object, AdPlaybackState> splitAdPlaybackStateForPeriods(AdPlaybackState adPlaybackState, Timeline contentTimeline) {
    Timeline.Period period = new Timeline.Period();
    if (contentTimeline.getPeriodCount() == 1) {
        // A single period gets the entire ad playback state that may contain multiple ad groups.
        return ImmutableMap.of(checkNotNull(contentTimeline.getPeriod(/* periodIndex= */
        0, period, /* setIds= */
        true).uid), adPlaybackState);
    }
    int periodIndex = 0;
    long totalElapsedContentDurationUs = 0;
    Object adsId = checkNotNull(adPlaybackState.adsId);
    AdPlaybackState contentOnlyAdPlaybackState = new AdPlaybackState(adsId);
    Map<Object, AdPlaybackState> adPlaybackStates = new HashMap<>();
    for (int i = adPlaybackState.removedAdGroupCount; i < adPlaybackState.adGroupCount; i++) {
        AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(/* adGroupIndex= */
        i);
        if (adGroup.timeUs == C.TIME_END_OF_SOURCE) {
            checkState(i == adPlaybackState.adGroupCount - 1);
            // The last ad group is a placeholder for a potential post roll. We can just stop here.
            break;
        }
        // The ad group start timeUs is in content position. We need to add the ad
        // duration before the ad group to translate the start time to the position in the period.
        long adGroupDurationUs = sum(adGroup.durationsUs);
        long elapsedAdGroupAdDurationUs = 0;
        for (int j = periodIndex; j < contentTimeline.getPeriodCount(); j++) {
            contentTimeline.getPeriod(j, period, /* setIds= */
            true);
            // Subtract one microsecond to work around rounding errors with adGroup.timeUs.
            if (totalElapsedContentDurationUs < adGroup.timeUs - 1) {
                // Period starts before the ad group, so it is a content period.
                adPlaybackStates.put(checkNotNull(period.uid), contentOnlyAdPlaybackState);
                totalElapsedContentDurationUs += period.durationUs;
            } else {
                long periodStartUs = totalElapsedContentDurationUs + elapsedAdGroupAdDurationUs;
                // Add one microsecond to work around rounding errors with adGroup.timeUs.
                if (periodStartUs + period.durationUs <= adGroup.timeUs + adGroupDurationUs + 1) {
                    // The period ends before the end of the ad group, so it is an ad period (Note: A VOD ad
                    // reported by the IMA SDK spans multiple periods before the LOADED event arrives).
                    adPlaybackStates.put(checkNotNull(period.uid), splitAdGroupForPeriod(adsId, adGroup, periodStartUs, period.durationUs));
                    elapsedAdGroupAdDurationUs += period.durationUs;
                } else {
                    // Period is after the current ad group. Continue with next ad group.
                    break;
                }
            }
            // Increment the period index to the next unclassified period.
            periodIndex++;
        }
    }
    // The remaining periods end after the last ad group, so these are content periods.
    for (int i = periodIndex; i < contentTimeline.getPeriodCount(); i++) {
        contentTimeline.getPeriod(i, period, /* setIds= */
        true);
        adPlaybackStates.put(checkNotNull(period.uid), contentOnlyAdPlaybackState);
    }
    return ImmutableMap.copyOf(adPlaybackStates);
}
Also used : Timeline(com.google.android.exoplayer2.Timeline) AdPlaybackState(com.google.android.exoplayer2.source.ads.AdPlaybackState) HashMap(java.util.HashMap)

Example 38 with Timeline

use of com.google.android.exoplayer2.Timeline in project ExoPlayer by google.

the class ImaUtilTest method splitAdPlaybackStateForPeriods_oneMidrollAdGroupOneAd_adSpansTwoPeriods.

@Test
public void splitAdPlaybackStateForPeriods_oneMidrollAdGroupOneAd_adSpansTwoPeriods() {
    int periodCount = 5;
    long periodDurationUs = DEFAULT_WINDOW_DURATION_US / periodCount;
    AdPlaybackState adPlaybackState = new AdPlaybackState(/* adsId= */
    "adsId", DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US + periodDurationUs).withAdCount(/* adGroupIndex= */
    0, 1).withAdDurationsUs(/* adGroupIndex= */
    0, 2 * periodDurationUs).withIsServerSideInserted(/* adGroupIndex= */
    0, true);
    FakeTimeline timeline = new FakeTimeline(new FakeTimeline.TimelineWindowDefinition(/* periodCount= */
    periodCount, /* id= */
    0L));
    ImmutableMap<Object, AdPlaybackState> adPlaybackStates = ImaUtil.splitAdPlaybackStateForPeriods(adPlaybackState, timeline);
    assertThat(adPlaybackStates).hasSize(periodCount);
    assertThat(adPlaybackStates.get(new Pair<>(0L, 0)).adGroupCount).isEqualTo(0);
    for (int i = 1; i < 3; i++) {
        Pair<Long, Integer> periodUid = new Pair<>(0L, i);
        AdPlaybackState periodAdPlaybackState = adPlaybackStates.get(periodUid);
        assertThat(periodAdPlaybackState.adGroupCount).isEqualTo(1);
        assertThat(periodAdPlaybackState.getAdGroup(0).durationsUs).hasLength(1);
        assertThat(periodAdPlaybackState.getAdGroup(0).durationsUs[0]).isEqualTo(2_000_000);
    }
    assertThat(adPlaybackStates.get(new Pair<>(0L, 3)).adGroupCount).isEqualTo(0);
    assertThat(adPlaybackStates.get(new Pair<>(0L, 4)).adGroupCount).isEqualTo(0);
}
Also used : AdPlaybackState(com.google.android.exoplayer2.source.ads.AdPlaybackState) FakeTimeline(com.google.android.exoplayer2.testutil.FakeTimeline) Pair(android.util.Pair) Test(org.junit.Test)

Example 39 with Timeline

use of com.google.android.exoplayer2.Timeline in project ExoPlayer by google.

the class PlayerWrapper method updatePlaylist.

private void updatePlaylist(Timeline timeline) {
    List<androidx.media2.common.MediaItem> media2MediaItemToBeRemoved = new ArrayList<>(media2Playlist);
    media2Playlist.clear();
    exoPlayerPlaylist.clear();
    Timeline.Window window = new Timeline.Window();
    int windowCount = timeline.getWindowCount();
    for (int i = 0; i < windowCount; i++) {
        timeline.getWindow(i, window);
        MediaItem exoPlayerMediaItem = window.mediaItem;
        androidx.media2.common.MediaItem media2MediaItem = Assertions.checkNotNull(mediaItemConverter.convertToMedia2MediaItem(exoPlayerMediaItem));
        exoPlayerPlaylist.add(exoPlayerMediaItem);
        media2Playlist.add(media2MediaItem);
        media2MediaItemToBeRemoved.remove(media2MediaItem);
    }
    for (androidx.media2.common.MediaItem item : media2MediaItemToBeRemoved) {
        releaseMediaItem(item);
    }
}
Also used : Timeline(com.google.android.exoplayer2.Timeline) CallbackMediaItem(androidx.media2.common.CallbackMediaItem) MediaItem(com.google.android.exoplayer2.MediaItem) ArrayList(java.util.ArrayList)

Example 40 with Timeline

use of com.google.android.exoplayer2.Timeline in project ExoPlayer by google.

the class ImaAdsLoader method maybePreloadNextPeriodAds.

private void maybePreloadNextPeriodAds() {
    @Nullable Player player = ImaAdsLoader.this.player;
    if (player == null) {
        return;
    }
    Timeline timeline = player.getCurrentTimeline();
    if (timeline.isEmpty()) {
        return;
    }
    int nextPeriodIndex = timeline.getNextPeriodIndex(player.getCurrentPeriodIndex(), period, window, player.getRepeatMode(), player.getShuffleModeEnabled());
    if (nextPeriodIndex == C.INDEX_UNSET) {
        return;
    }
    timeline.getPeriod(nextPeriodIndex, period);
    @Nullable Object nextAdsId = period.getAdsId();
    if (nextAdsId == null) {
        return;
    }
    @Nullable AdTagLoader nextAdTagLoader = adTagLoaderByAdsId.get(nextAdsId);
    if (nextAdTagLoader == null || nextAdTagLoader == currentAdTagLoader) {
        return;
    }
    long periodPositionUs = timeline.getPeriodPositionUs(window, period, period.windowIndex, /* windowPositionUs= */
    C.TIME_UNSET).second;
    nextAdTagLoader.maybePreloadAds(Util.usToMs(periodPositionUs), Util.usToMs(period.durationUs));
}
Also used : Player(com.google.android.exoplayer2.Player) VideoAdPlayer(com.google.ads.interactivemedia.v3.api.player.VideoAdPlayer) Timeline(com.google.android.exoplayer2.Timeline) Nullable(androidx.annotation.Nullable)

Aggregations

Test (org.junit.Test)347 FakeTimeline (com.google.android.exoplayer2.testutil.FakeTimeline)246 Timeline (com.google.android.exoplayer2.Timeline)163 FakeMediaSource (com.google.android.exoplayer2.testutil.FakeMediaSource)140 SinglePeriodTimeline (com.google.android.exoplayer2.source.SinglePeriodTimeline)125 NoUidTimeline (com.google.android.exoplayer2.testutil.NoUidTimeline)110 TestExoPlayerBuilder (com.google.android.exoplayer2.testutil.TestExoPlayerBuilder)109 TimelineWindowDefinition (com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition)89 MediaPeriodId (com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)85 TrackGroupArray (com.google.android.exoplayer2.source.TrackGroupArray)79 ActionSchedule (com.google.android.exoplayer2.testutil.ActionSchedule)74 ExoPlayerTestRunner (com.google.android.exoplayer2.testutil.ExoPlayerTestRunner)60 Format (com.google.android.exoplayer2.Format)49 MediaSource (com.google.android.exoplayer2.source.MediaSource)47 AdPlaybackState (com.google.android.exoplayer2.source.ads.AdPlaybackState)44 ConcatenatingMediaSource (com.google.android.exoplayer2.source.ConcatenatingMediaSource)38 PlayerRunnable (com.google.android.exoplayer2.testutil.ActionSchedule.PlayerRunnable)36 EventTime (com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)35 MediaItem (com.google.android.exoplayer2.MediaItem)34 RendererCapabilities (com.google.android.exoplayer2.RendererCapabilities)33