use of com.google.android.exoplayer2.source.MediaSource.MediaPeriodId in project ExoPlayer by google.
the class FakeMediaSource method finishSourcePreparation.
private void finishSourcePreparation(boolean sendManifestLoadEvents) {
refreshSourceInfo(Assertions.checkStateNotNull(timeline));
if (!timeline.isEmpty() && sendManifestLoadEvents) {
MediaLoadData mediaLoadData = new MediaLoadData(C.DATA_TYPE_MANIFEST, C.TRACK_TYPE_UNKNOWN, /* trackFormat= */
null, C.SELECTION_REASON_UNKNOWN, /* trackSelectionData= */
null, /* mediaStartTimeMs= */
C.TIME_UNSET, /* mediaEndTimeMs = */
C.TIME_UNSET);
long elapsedRealTimeMs = SystemClock.elapsedRealtime();
MediaSourceEventListener.EventDispatcher eventDispatcher = createEventDispatcher(/* mediaPeriodId= */
null);
long loadTaskId = LoadEventInfo.getNewId();
eventDispatcher.loadStarted(new LoadEventInfo(loadTaskId, FAKE_DATA_SPEC, FAKE_DATA_SPEC.uri, /* responseHeaders= */
ImmutableMap.of(), elapsedRealTimeMs, /* loadDurationMs= */
0, /* bytesLoaded= */
0), mediaLoadData);
eventDispatcher.loadCompleted(new LoadEventInfo(loadTaskId, FAKE_DATA_SPEC, FAKE_DATA_SPEC.uri, /* responseHeaders= */
ImmutableMap.of(), elapsedRealTimeMs, /* loadDurationMs= */
0, /* bytesLoaded= */
MANIFEST_LOAD_BYTES), mediaLoadData);
}
}
use of com.google.android.exoplayer2.source.MediaSource.MediaPeriodId in project ExoPlayer by google.
the class FakeMediaSource method createPeriod.
@Override
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
assertThat(preparedSource).isTrue();
assertThat(releasedSource).isFalse();
int periodIndex = castNonNull(timeline).getIndexOfPeriod(id.periodUid);
Assertions.checkArgument(periodIndex != C.INDEX_UNSET);
Period period = timeline.getPeriod(periodIndex, new Period());
MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher = createEventDispatcher(period.windowIndex, id, period.getPositionInWindowMs());
DrmSessionEventListener.EventDispatcher drmEventDispatcher = createDrmEventDispatcher(period.windowIndex, id);
MediaPeriod mediaPeriod = createMediaPeriod(id, trackGroupArray, allocator, mediaSourceEventDispatcher, drmSessionManager, drmEventDispatcher, transferListener);
activeMediaPeriods.add(mediaPeriod);
createdMediaPeriods.add(id);
return mediaPeriod;
}
use of com.google.android.exoplayer2.source.MediaSource.MediaPeriodId in project ExoPlayer by google.
the class MediaPeriodQueue method getMediaPeriodInfoForContent.
private MediaPeriodInfo getMediaPeriodInfoForContent(Timeline timeline, Object periodUid, long startPositionUs, long requestedContentPositionUs, long windowSequenceNumber) {
timeline.getPeriodByUid(periodUid, period);
int nextAdGroupIndex = period.getAdGroupIndexAfterPositionUs(startPositionUs);
boolean clipPeriodAtContentDuration = false;
if (nextAdGroupIndex == C.INDEX_UNSET) {
// Clip SSAI streams when at the end of the period.
clipPeriodAtContentDuration = period.getAdGroupCount() > 0 && period.isServerSideInsertedAdGroup(period.getRemovedAdGroupCount());
} else if (period.isServerSideInsertedAdGroup(nextAdGroupIndex) && period.getAdGroupTimeUs(nextAdGroupIndex) == period.durationUs) {
if (period.hasPlayedAdGroup(nextAdGroupIndex)) {
// Clip period before played SSAI post-rolls.
nextAdGroupIndex = C.INDEX_UNSET;
clipPeriodAtContentDuration = true;
}
}
MediaPeriodId id = new MediaPeriodId(periodUid, windowSequenceNumber, nextAdGroupIndex);
boolean isLastInPeriod = isLastInPeriod(id);
boolean isLastInWindow = isLastInWindow(timeline, id);
boolean isLastInTimeline = isLastInTimeline(timeline, id, isLastInPeriod);
boolean isFollowedByTransitionToSameStream = nextAdGroupIndex != C.INDEX_UNSET && period.isServerSideInsertedAdGroup(nextAdGroupIndex);
long endPositionUs = nextAdGroupIndex != C.INDEX_UNSET ? period.getAdGroupTimeUs(nextAdGroupIndex) : clipPeriodAtContentDuration ? period.durationUs : C.TIME_UNSET;
long durationUs = endPositionUs == C.TIME_UNSET || endPositionUs == C.TIME_END_OF_SOURCE ? period.durationUs : endPositionUs;
if (durationUs != C.TIME_UNSET && startPositionUs >= durationUs) {
// Ensure start position doesn't exceed duration.
startPositionUs = max(0, durationUs - 1);
}
return new MediaPeriodInfo(id, startPositionUs, requestedContentPositionUs, endPositionUs, durationUs, isFollowedByTransitionToSameStream, isLastInPeriod, isLastInWindow, isLastInTimeline);
}
use of com.google.android.exoplayer2.source.MediaSource.MediaPeriodId in project ExoPlayer by google.
the class MediaPeriodQueue method getFollowingMediaPeriodInfo.
/**
* Returns the {@link MediaPeriodInfo} for the media period following {@code mediaPeriodHolder}'s
* media period.
*
* @param timeline The current timeline.
* @param mediaPeriodHolder The media period holder.
* @param rendererPositionUs The current renderer position in microseconds.
* @return The following media period's info, or {@code null} if it is not yet possible to get the
* next media period info.
*/
@Nullable
private MediaPeriodInfo getFollowingMediaPeriodInfo(Timeline timeline, MediaPeriodHolder mediaPeriodHolder, long rendererPositionUs) {
// TODO: This method is called repeatedly from ExoPlayerImplInternal.maybeUpdateLoadingPeriod
// but if the timeline is not ready to provide the next period it can't return a non-null value
// until the timeline is updated. Store whether the next timeline period is ready when the
// timeline is updated, to avoid repeatedly checking the same timeline.
MediaPeriodInfo mediaPeriodInfo = mediaPeriodHolder.info;
// The expected delay until playback transitions to the new period is equal the duration of
// media that's currently buffered (assuming no interruptions). This is used to project forward
// the start position for transitions to new windows.
long bufferedDurationUs = mediaPeriodHolder.getRendererOffset() + mediaPeriodInfo.durationUs - rendererPositionUs;
if (mediaPeriodInfo.isLastInTimelinePeriod) {
int currentPeriodIndex = timeline.getIndexOfPeriod(mediaPeriodInfo.id.periodUid);
int nextPeriodIndex = timeline.getNextPeriodIndex(currentPeriodIndex, period, window, repeatMode, shuffleModeEnabled);
if (nextPeriodIndex == C.INDEX_UNSET) {
// We can't create a next period yet.
return null;
}
// We either start a new period in the same window or the first period in the next window.
long startPositionUs = 0;
long contentPositionUs = 0;
int nextWindowIndex = timeline.getPeriod(nextPeriodIndex, period, /* setIds= */
true).windowIndex;
Object nextPeriodUid = checkNotNull(period.uid);
long windowSequenceNumber = mediaPeriodInfo.id.windowSequenceNumber;
if (timeline.getWindow(nextWindowIndex, window).firstPeriodIndex == nextPeriodIndex) {
// We're starting to buffer a new window. When playback transitions to this window we'll
// want it to be from its default start position, so project the default start position
// forward by the duration of the buffer, and start buffering from this point.
contentPositionUs = C.TIME_UNSET;
@Nullable Pair<Object, Long> defaultPositionUs = timeline.getPeriodPositionUs(window, period, nextWindowIndex, /* windowPositionUs= */
C.TIME_UNSET, /* defaultPositionProjectionUs= */
max(0, bufferedDurationUs));
if (defaultPositionUs == null) {
return null;
}
nextPeriodUid = defaultPositionUs.first;
startPositionUs = defaultPositionUs.second;
@Nullable MediaPeriodHolder nextMediaPeriodHolder = mediaPeriodHolder.getNext();
if (nextMediaPeriodHolder != null && nextMediaPeriodHolder.uid.equals(nextPeriodUid)) {
windowSequenceNumber = nextMediaPeriodHolder.info.id.windowSequenceNumber;
} else {
windowSequenceNumber = nextWindowSequenceNumber++;
}
}
@Nullable MediaPeriodId periodId = resolveMediaPeriodIdForAds(timeline, nextPeriodUid, startPositionUs, windowSequenceNumber, window, period);
if (contentPositionUs != C.TIME_UNSET && mediaPeriodInfo.requestedContentPositionUs != C.TIME_UNSET) {
boolean isPrecedingPeriodAnAd = timeline.getPeriodByUid(mediaPeriodInfo.id.periodUid, period).getAdGroupCount() > 0 && period.isServerSideInsertedAdGroup(period.getRemovedAdGroupCount());
// Handle the requested content position for period transitions within the same window.
if (periodId.isAd() && isPrecedingPeriodAnAd) {
// Propagate the requested position to the following ad period in the same window.
contentPositionUs = mediaPeriodInfo.requestedContentPositionUs;
} else if (isPrecedingPeriodAnAd) {
// Use the requested content position of the preceding ad period as the start position.
startPositionUs = mediaPeriodInfo.requestedContentPositionUs;
}
}
return getMediaPeriodInfo(timeline, periodId, contentPositionUs, startPositionUs);
}
MediaPeriodId currentPeriodId = mediaPeriodInfo.id;
timeline.getPeriodByUid(currentPeriodId.periodUid, period);
if (currentPeriodId.isAd()) {
int adGroupIndex = currentPeriodId.adGroupIndex;
int adCountInCurrentAdGroup = period.getAdCountInAdGroup(adGroupIndex);
if (adCountInCurrentAdGroup == C.LENGTH_UNSET) {
return null;
}
int nextAdIndexInAdGroup = period.getNextAdIndexToPlay(adGroupIndex, currentPeriodId.adIndexInAdGroup);
if (nextAdIndexInAdGroup < adCountInCurrentAdGroup) {
// Play the next ad in the ad group if it's available.
return getMediaPeriodInfoForAd(timeline, currentPeriodId.periodUid, adGroupIndex, nextAdIndexInAdGroup, mediaPeriodInfo.requestedContentPositionUs, currentPeriodId.windowSequenceNumber);
} else {
// Play content from the ad group position.
long startPositionUs = mediaPeriodInfo.requestedContentPositionUs;
if (startPositionUs == C.TIME_UNSET) {
// If we're transitioning from an ad group to content starting from its default position,
// project the start position forward as if this were a transition to a new window.
@Nullable Pair<Object, Long> defaultPositionUs = timeline.getPeriodPositionUs(window, period, period.windowIndex, /* windowPositionUs= */
C.TIME_UNSET, /* defaultPositionProjectionUs= */
max(0, bufferedDurationUs));
if (defaultPositionUs == null) {
return null;
}
startPositionUs = defaultPositionUs.second;
}
long minStartPositionUs = getMinStartPositionAfterAdGroupUs(timeline, currentPeriodId.periodUid, currentPeriodId.adGroupIndex);
return getMediaPeriodInfoForContent(timeline, currentPeriodId.periodUid, max(minStartPositionUs, startPositionUs), mediaPeriodInfo.requestedContentPositionUs, currentPeriodId.windowSequenceNumber);
}
} else {
// Play the next ad group if it's still available.
int adIndexInAdGroup = period.getFirstAdIndexToPlay(currentPeriodId.nextAdGroupIndex);
boolean isPlayedServerSideInsertedAd = period.isServerSideInsertedAdGroup(currentPeriodId.nextAdGroupIndex) && period.getAdState(currentPeriodId.nextAdGroupIndex, adIndexInAdGroup) == AdPlaybackState.AD_STATE_PLAYED;
if (adIndexInAdGroup == period.getAdCountInAdGroup(currentPeriodId.nextAdGroupIndex) || isPlayedServerSideInsertedAd) {
// The next ad group has no ads left to play or is a played SSAI ad group. Play content from
// the end position instead.
long startPositionUs = getMinStartPositionAfterAdGroupUs(timeline, currentPeriodId.periodUid, currentPeriodId.nextAdGroupIndex);
return getMediaPeriodInfoForContent(timeline, currentPeriodId.periodUid, startPositionUs, /* requestedContentPositionUs= */
mediaPeriodInfo.durationUs, currentPeriodId.windowSequenceNumber);
}
return getMediaPeriodInfoForAd(timeline, currentPeriodId.periodUid, currentPeriodId.nextAdGroupIndex, adIndexInAdGroup, /* contentPositionUs= */
mediaPeriodInfo.durationUs, currentPeriodId.windowSequenceNumber);
}
}
use of com.google.android.exoplayer2.source.MediaSource.MediaPeriodId in project ExoPlayer by google.
the class MediaPeriodQueue method getMediaPeriodInfoForAd.
private MediaPeriodInfo getMediaPeriodInfoForAd(Timeline timeline, Object periodUid, int adGroupIndex, int adIndexInAdGroup, long contentPositionUs, long windowSequenceNumber) {
MediaPeriodId id = new MediaPeriodId(periodUid, adGroupIndex, adIndexInAdGroup, windowSequenceNumber);
long durationUs = timeline.getPeriodByUid(id.periodUid, period).getAdDurationUs(id.adGroupIndex, id.adIndexInAdGroup);
long startPositionUs = adIndexInAdGroup == period.getFirstAdIndexToPlay(adGroupIndex) ? period.getAdResumePositionUs() : 0;
boolean isFollowedByTransitionToSameStream = period.isServerSideInsertedAdGroup(id.adGroupIndex);
if (durationUs != C.TIME_UNSET && startPositionUs >= durationUs) {
// Ensure start position doesn't exceed duration.
startPositionUs = max(0, durationUs - 1);
}
return new MediaPeriodInfo(id, startPositionUs, contentPositionUs, /* endPositionUs= */
C.TIME_UNSET, durationUs, isFollowedByTransitionToSameStream, /* isLastInTimelinePeriod= */
false, /* isLastInTimelineWindow= */
false, /* isFinal= */
false);
}
Aggregations