private MlltSeeker(long[] referencePositions, long[] referenceTimesMs) { this.referencePositions = referencePositions; this.referenceTimesMs = referenceTimesMs; // Use the last reference point as the duration, as extrapolating variable bitrate at the end of // the stream may give a large error. durationUs = C.msToUs(referenceTimesMs[referenceTimesMs.length - 1]); }
/** * Returns the duration of the window in milliseconds, or {@link C#TIME_UNSET} if unknown. */ public long getDurationMs() { return C.usToMs(durationUs); }
contentPositionMs = pendingContentPositionMs; expectedAdGroupIndex = adPlaybackState.getAdGroupIndexForPositionUs(C.msToUs(contentPositionMs)); } else if (fakeContentProgressElapsedRealtimeMs != C.TIME_UNSET) { long elapsedSinceEndMs = SystemClock.elapsedRealtime() - fakeContentProgressElapsedRealtimeMs; contentPositionMs = fakeContentProgressOffsetMs + elapsedSinceEndMs; expectedAdGroupIndex = adPlaybackState.getAdGroupIndexForPositionUs(C.msToUs(contentPositionMs)); } else if (imaAdState == IMA_AD_STATE_NONE && !playingAd && hasContentDuration) { contentPositionMs = player.getCurrentPosition(); adPlaybackState.getAdGroupIndexAfterPositionUs(C.msToUs(contentPositionMs)); if (nextAdGroupIndex != expectedAdGroupIndex && nextAdGroupIndex != C.INDEX_UNSET) { long nextAdGroupTimeMs = C.usToMs(adPlaybackState.adGroupTimesUs[nextAdGroupIndex]); if (nextAdGroupTimeMs == C.TIME_END_OF_SOURCE) { nextAdGroupTimeMs = contentDurationMs;
@Override public void initPlayer(final boolean playOnReady) { super.initPlayer(playOnReady); // Setup video view simpleExoPlayer.setVideoSurfaceView(surfaceView); simpleExoPlayer.addVideoListener(this); // Setup subtitle view simpleExoPlayer.addTextOutput(cues -> subtitleView.onCues(cues)); // Setup audio session with onboard equalizer if (Build.VERSION.SDK_INT >= 21) { trackSelector.setParameters(trackSelector.buildUponParameters() .setTunnelingAudioSessionId(C.generateAudioSessionIdV21(context))); } }
@Override public SeekPoints getSeekPoints(long timeUs) { timeUs = Util.constrainValue(timeUs, 0, durationUs); Pair<Long, Long> timeMsAndPosition = linearlyInterpolate(C.usToMs(timeUs), referenceTimesMs, referencePositions); timeUs = C.msToUs(timeMsAndPosition.first); long position = timeMsAndPosition.second; return new SeekPoints(new SeekPoint(timeUs, position)); }
trackSelector.setTunnelingAudioSessionId(C.generateAudioSessionIdV21(this));
/** * Returns the default position relative to the start of the window at which to begin playback, * in milliseconds. May be {@link C#TIME_UNSET} if and only if the window was populated with a * non-zero default position projection, and if the specified projection cannot be performed * whilst remaining within the bounds of the window. */ public long getDefaultPositionMs() { return C.usToMs(defaultPositionUs); }
} 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); internalPlayer.seekTo(timeline, windowIndex, C.msToUs(positionMs)); for (Player.EventListener listener : listeners) { listener.onPositionDiscontinuity(DISCONTINUITY_REASON_SEEK);
/** * Returns the position of the start of this window relative to the start of the first period * belonging to it, in milliseconds. */ public long getPositionInFirstPeriodMs() { return C.usToMs(positionInFirstPeriodUs); }
/** * Returns the duration in microseconds advertised by a media info, or {@link C#TIME_UNSET} if * unknown or not applicable. * * @param mediaInfo The media info to get the duration from. * @return The duration in microseconds. */ public static long getStreamDurationUs(MediaInfo mediaInfo) { long durationMs = mediaInfo != null ? mediaInfo.getStreamDuration() : MediaInfo.UNKNOWN_DURATION; return durationMs != MediaInfo.UNKNOWN_DURATION ? C.msToUs(durationMs) : C.TIME_UNSET; }
long liveStreamDurationUs = getNowUnixTimeUs() - C.msToUs(manifest.availabilityStartTimeMs); long liveStreamEndPositionInLastPeriodUs = liveStreamDurationUs - C.msToUs(manifest.getPeriod(lastPeriodIndex).startMs); currentEndTimeUs = Math.min(liveStreamEndPositionInLastPeriodUs, currentEndTimeUs); if (manifest.timeShiftBufferDepthMs != C.TIME_UNSET) { long timeShiftBufferDepthUs = C.msToUs(manifest.timeShiftBufferDepthMs); long offsetInPeriodUs = currentEndTimeUs - timeShiftBufferDepthUs; int periodIndex = lastPeriodIndex; windowDefaultStartPositionUs = windowDurationUs - C.msToUs(presentationDelayForManifestMs); if (windowDefaultStartPositionUs < MIN_LIVE_DEFAULT_START_POSITION_US) { + manifest.getPeriod(0).startMs + C.usToMs(currentStartTimeUs); DashTimeline timeline = new DashTimeline(
/** * Returns the duration of the period in milliseconds, or {@link C#TIME_UNSET} if unknown. */ public long getDurationMs() { return C.usToMs(durationUs); }
@Override public long getTimeUs(long position) { Pair<Long, Long> positionAndTimeMs = linearlyInterpolate(position, referencePositions, referenceTimesMs); return C.msToUs(positionAndTimeMs.second); }
/** * Returns the position of the start of this period relative to the start of the window to which * it belongs, in milliseconds. May be negative if the start of the period is not within the * window. */ public long getPositionInWindowMs() { return C.usToMs(positionInWindowUs); }
public final long getPeriodDurationUs(int index) { return C.msToUs(getPeriodDurationMs(index)); }
private long adjustMediaTime(long mediaTimeUs) { long mediaTimeMs = C.usToMs(mediaTimeUs); return mediaTimeMs == C.TIME_UNSET ? C.TIME_UNSET : mediaTimeOffsetMs + mediaTimeMs; }
public long getFirstAvailableSegmentNum( DashManifest manifest, int periodIndex, long nowUnixTimeUs) { if (getSegmentCount() == DashSegmentIndex.INDEX_UNBOUNDED && manifest.timeShiftBufferDepthMs != C.TIME_UNSET) { // The index is itself unbounded. We need to use the current time to calculate the range of // available segments. long liveEdgeTimeUs = nowUnixTimeUs - C.msToUs(manifest.availabilityStartTimeMs); long periodStartUs = C.msToUs(manifest.getPeriod(periodIndex).startMs); long liveEdgeTimeInPeriodUs = liveEdgeTimeUs - periodStartUs; long bufferDepthUs = C.msToUs(manifest.timeShiftBufferDepthMs); return Math.max( getFirstSegmentNum(), getSegmentNum(liveEdgeTimeInPeriodUs - bufferDepthUs)); } return getFirstSegmentNum(); }
@Override protected long getMediaTimeForChildMediaTime(Void id, long mediaTimeMs) { if (mediaTimeMs == C.TIME_UNSET) { return C.TIME_UNSET; } long startMs = C.usToMs(startUs); long clippedTimeMs = Math.max(0, mediaTimeMs - startMs); if (endUs != C.TIME_END_OF_SOURCE) { clippedTimeMs = Math.min(C.usToMs(endUs) - startMs, clippedTimeMs); } return clippedTimeMs; }
@Override public long getPositionUs() { long positionUs = baseUs; if (started) { long elapsedSinceBaseMs = clock.elapsedRealtime() - baseElapsedMs; if (playbackParameters.speed == 1f) { positionUs += C.msToUs(elapsedSinceBaseMs); } else { positionUs += playbackParameters.getMediaTimeUsForPlayoutTimeMs(elapsedSinceBaseMs); } } return positionUs; }