use of com.google.android.exoplayer2.source.MediaSource.MediaPeriodId in project ExoPlayer by google.
the class ExoPlayerImpl method getDuration.
@Override
public long getDuration() {
verifyApplicationThread();
if (isPlayingAd()) {
MediaPeriodId periodId = playbackInfo.periodId;
playbackInfo.timeline.getPeriodByUid(periodId.periodUid, period);
long adDurationUs = period.getAdDurationUs(periodId.adGroupIndex, periodId.adIndexInAdGroup);
return Util.usToMs(adDurationUs);
}
return getContentDuration();
}
use of com.google.android.exoplayer2.source.MediaSource.MediaPeriodId in project ExoPlayer by google.
the class ExoPlayerImplInternal method seekToPeriodPosition.
private long seekToPeriodPosition(MediaPeriodId periodId, long periodPositionUs, boolean forceDisableRenderers, boolean forceBufferingState) throws ExoPlaybackException {
stopRenderers();
isRebuffering = false;
if (forceBufferingState || playbackInfo.playbackState == Player.STATE_READY) {
setState(Player.STATE_BUFFERING);
}
// Find the requested period if it already exists.
@Nullable MediaPeriodHolder oldPlayingPeriodHolder = queue.getPlayingPeriod();
@Nullable MediaPeriodHolder newPlayingPeriodHolder = oldPlayingPeriodHolder;
while (newPlayingPeriodHolder != null) {
if (periodId.equals(newPlayingPeriodHolder.info.id)) {
break;
}
newPlayingPeriodHolder = newPlayingPeriodHolder.getNext();
}
// renderer timestamps, or if forced.
if (forceDisableRenderers || oldPlayingPeriodHolder != newPlayingPeriodHolder || (newPlayingPeriodHolder != null && newPlayingPeriodHolder.toRendererTime(periodPositionUs) < 0)) {
for (Renderer renderer : renderers) {
disableRenderer(renderer);
}
if (newPlayingPeriodHolder != null) {
// Update the queue and reenable renderers if the requested media period already exists.
while (queue.getPlayingPeriod() != newPlayingPeriodHolder) {
queue.advancePlayingPeriod();
}
queue.removeAfter(newPlayingPeriodHolder);
newPlayingPeriodHolder.setRendererOffset(MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US);
enableRenderers();
}
}
// Do the actual seeking.
if (newPlayingPeriodHolder != null) {
queue.removeAfter(newPlayingPeriodHolder);
if (!newPlayingPeriodHolder.prepared) {
newPlayingPeriodHolder.info = newPlayingPeriodHolder.info.copyWithStartPositionUs(periodPositionUs);
} else if (newPlayingPeriodHolder.hasEnabledTracks) {
periodPositionUs = newPlayingPeriodHolder.mediaPeriod.seekToUs(periodPositionUs);
newPlayingPeriodHolder.mediaPeriod.discardBuffer(periodPositionUs - backBufferDurationUs, retainBackBufferFromKeyframe);
}
resetRendererPosition(periodPositionUs);
maybeContinueLoading();
} else {
// New period has not been prepared.
queue.clear();
resetRendererPosition(periodPositionUs);
}
handleLoadingMediaPeriodChanged(/* loadingTrackSelectionChanged= */
false);
handler.sendEmptyMessage(MSG_DO_SOME_WORK);
return periodPositionUs;
}
use of com.google.android.exoplayer2.source.MediaSource.MediaPeriodId in project ExoPlayer by google.
the class ExoPlayerImplInternal method isUsingPlaceholderPeriod.
private static boolean isUsingPlaceholderPeriod(PlaybackInfo playbackInfo, Timeline.Period period) {
MediaPeriodId periodId = playbackInfo.periodId;
Timeline timeline = playbackInfo.timeline;
return timeline.isEmpty() || timeline.getPeriodByUid(periodId.periodUid, period).isPlaceholder;
}
use of com.google.android.exoplayer2.source.MediaSource.MediaPeriodId in project ExoPlayer by google.
the class ExoPlayerImplInternal method seekToInternal.
private void seekToInternal(SeekPosition seekPosition) throws ExoPlaybackException {
playbackInfoUpdate.incrementPendingOperationAcks(/* operationAcks= */
1);
MediaPeriodId periodId;
long periodPositionUs;
long requestedContentPositionUs;
boolean seekPositionAdjusted;
@Nullable Pair<Object, Long> resolvedSeekPosition = resolveSeekPositionUs(playbackInfo.timeline, seekPosition, /* trySubsequentPeriods= */
true, repeatMode, shuffleModeEnabled, window, period);
if (resolvedSeekPosition == null) {
// The seek position was valid for the timeline that it was performed into, but the
// timeline has changed or is not ready and a suitable seek position could not be resolved.
Pair<MediaPeriodId, Long> firstPeriodAndPositionUs = getPlaceholderFirstMediaPeriodPositionUs(playbackInfo.timeline);
periodId = firstPeriodAndPositionUs.first;
periodPositionUs = firstPeriodAndPositionUs.second;
requestedContentPositionUs = C.TIME_UNSET;
seekPositionAdjusted = !playbackInfo.timeline.isEmpty();
} else {
// Update the resolved seek position to take ads into account.
Object periodUid = resolvedSeekPosition.first;
long resolvedContentPositionUs = resolvedSeekPosition.second;
requestedContentPositionUs = seekPosition.windowPositionUs == C.TIME_UNSET ? C.TIME_UNSET : resolvedContentPositionUs;
periodId = queue.resolveMediaPeriodIdForAdsAfterPeriodPositionChange(playbackInfo.timeline, periodUid, resolvedContentPositionUs);
if (periodId.isAd()) {
playbackInfo.timeline.getPeriodByUid(periodId.periodUid, period);
periodPositionUs = period.getFirstAdIndexToPlay(periodId.adGroupIndex) == periodId.adIndexInAdGroup ? period.getAdResumePositionUs() : 0;
seekPositionAdjusted = true;
} else {
periodPositionUs = resolvedContentPositionUs;
seekPositionAdjusted = seekPosition.windowPositionUs == C.TIME_UNSET;
}
}
try {
if (playbackInfo.timeline.isEmpty()) {
// Save seek position for later, as we are still waiting for a prepared source.
pendingInitialSeekPosition = seekPosition;
} else if (resolvedSeekPosition == null) {
// End playback, as we didn't manage to find a valid seek position.
if (playbackInfo.playbackState != Player.STATE_IDLE) {
setState(Player.STATE_ENDED);
}
resetInternal(/* resetRenderers= */
false, /* resetPosition= */
true, /* releaseMediaSourceList= */
false, /* resetError= */
true);
} else {
// Execute the seek in the current media periods.
long newPeriodPositionUs = periodPositionUs;
if (periodId.equals(playbackInfo.periodId)) {
MediaPeriodHolder playingPeriodHolder = queue.getPlayingPeriod();
if (playingPeriodHolder != null && playingPeriodHolder.prepared && newPeriodPositionUs != 0) {
newPeriodPositionUs = playingPeriodHolder.mediaPeriod.getAdjustedSeekPositionUs(newPeriodPositionUs, seekParameters);
}
if (Util.usToMs(newPeriodPositionUs) == Util.usToMs(playbackInfo.positionUs) && (playbackInfo.playbackState == Player.STATE_BUFFERING || playbackInfo.playbackState == Player.STATE_READY)) {
// Seek will be performed to the current position. Do nothing.
periodPositionUs = playbackInfo.positionUs;
return;
}
}
newPeriodPositionUs = seekToPeriodPosition(periodId, newPeriodPositionUs, /* forceBufferingState= */
playbackInfo.playbackState == Player.STATE_ENDED);
seekPositionAdjusted |= periodPositionUs != newPeriodPositionUs;
periodPositionUs = newPeriodPositionUs;
updatePlaybackSpeedSettingsForNewPeriod(/* newTimeline= */
playbackInfo.timeline, /* newPeriodId= */
periodId, /* oldTimeline= */
playbackInfo.timeline, /* oldPeriodId= */
playbackInfo.periodId, /* positionForTargetOffsetOverrideUs= */
requestedContentPositionUs);
}
} finally {
playbackInfo = handlePositionDiscontinuity(periodId, periodPositionUs, requestedContentPositionUs, /* discontinuityStartPositionUs= */
periodPositionUs, /* reportDiscontinuity= */
seekPositionAdjusted, Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT);
}
}
use of com.google.android.exoplayer2.source.MediaSource.MediaPeriodId in project ExoPlayer by google.
the class ExoPlayerImplInternal method resetInternal.
private void resetInternal(boolean resetRenderers, boolean resetPosition, boolean releaseMediaSourceList, boolean resetError) {
handler.removeMessages(MSG_DO_SOME_WORK);
pendingRecoverableRendererError = null;
isRebuffering = false;
mediaClock.stop();
rendererPositionUs = MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US;
for (Renderer renderer : renderers) {
try {
disableRenderer(renderer);
} catch (ExoPlaybackException | RuntimeException e) {
// There's nothing we can do.
Log.e(TAG, "Disable failed.", e);
}
}
if (resetRenderers) {
for (Renderer renderer : renderers) {
if (renderersToReset.remove(renderer)) {
try {
renderer.reset();
} catch (RuntimeException e) {
// There's nothing we can do.
Log.e(TAG, "Reset failed.", e);
}
}
}
}
enabledRendererCount = 0;
MediaPeriodId mediaPeriodId = playbackInfo.periodId;
long startPositionUs = playbackInfo.positionUs;
long requestedContentPositionUs = playbackInfo.periodId.isAd() || isUsingPlaceholderPeriod(playbackInfo, period) ? playbackInfo.requestedContentPositionUs : playbackInfo.positionUs;
boolean resetTrackInfo = false;
if (resetPosition) {
pendingInitialSeekPosition = null;
Pair<MediaPeriodId, Long> firstPeriodAndPositionUs = getPlaceholderFirstMediaPeriodPositionUs(playbackInfo.timeline);
mediaPeriodId = firstPeriodAndPositionUs.first;
startPositionUs = firstPeriodAndPositionUs.second;
requestedContentPositionUs = C.TIME_UNSET;
if (!mediaPeriodId.equals(playbackInfo.periodId)) {
resetTrackInfo = true;
}
}
queue.clear();
shouldContinueLoading = false;
playbackInfo = new PlaybackInfo(playbackInfo.timeline, mediaPeriodId, requestedContentPositionUs, /* discontinuityStartPositionUs= */
startPositionUs, playbackInfo.playbackState, resetError ? null : playbackInfo.playbackError, /* isLoading= */
false, resetTrackInfo ? TrackGroupArray.EMPTY : playbackInfo.trackGroups, resetTrackInfo ? emptyTrackSelectorResult : playbackInfo.trackSelectorResult, resetTrackInfo ? ImmutableList.of() : playbackInfo.staticMetadata, mediaPeriodId, playbackInfo.playWhenReady, playbackInfo.playbackSuppressionReason, playbackInfo.playbackParameters, /* bufferedPositionUs= */
startPositionUs, /* totalBufferedDurationUs= */
0, /* positionUs= */
startPositionUs, offloadSchedulingEnabled, /* sleepingForOffload= */
false);
if (releaseMediaSourceList) {
mediaSourceList.release();
}
}
Aggregations