use of com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest.StreamElement in project ExoPlayer by google.
the class DefaultSsChunkSource method updateManifest.
@Override
public void updateManifest(SsManifest newManifest) {
StreamElement currentElement = manifest.streamElements[elementIndex];
int currentElementChunkCount = currentElement.chunkCount;
StreamElement newElement = newManifest.streamElements[elementIndex];
if (currentElementChunkCount == 0 || newElement.chunkCount == 0) {
// There's no overlap between the old and new elements because at least one is empty.
currentManifestChunkOffset += currentElementChunkCount;
} else {
long currentElementEndTimeUs = currentElement.getStartTimeUs(currentElementChunkCount - 1) + currentElement.getChunkDurationUs(currentElementChunkCount - 1);
long newElementStartTimeUs = newElement.getStartTimeUs(0);
if (currentElementEndTimeUs <= newElementStartTimeUs) {
// There's no overlap between the old and new elements.
currentManifestChunkOffset += currentElementChunkCount;
} else {
// The new element overlaps with the old one.
currentManifestChunkOffset += currentElement.getChunkIndex(newElementStartTimeUs);
}
}
manifest = newManifest;
}
use of com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest.StreamElement in project ExoPlayer by google.
the class SsMediaSource method processManifest.
// Internal methods
private void processManifest() {
for (int i = 0; i < mediaPeriods.size(); i++) {
mediaPeriods.get(i).updateManifest(manifest);
}
Timeline timeline;
if (manifest.isLive) {
long startTimeUs = Long.MAX_VALUE;
long endTimeUs = Long.MIN_VALUE;
for (int i = 0; i < manifest.streamElements.length; i++) {
StreamElement element = manifest.streamElements[i];
if (element.chunkCount > 0) {
startTimeUs = Math.min(startTimeUs, element.getStartTimeUs(0));
endTimeUs = Math.max(endTimeUs, element.getStartTimeUs(element.chunkCount - 1) + element.getChunkDurationUs(element.chunkCount - 1));
}
}
if (startTimeUs == Long.MAX_VALUE) {
timeline = new SinglePeriodTimeline(C.TIME_UNSET, false);
} else {
if (manifest.dvrWindowLengthUs != C.TIME_UNSET && manifest.dvrWindowLengthUs > 0) {
startTimeUs = Math.max(startTimeUs, endTimeUs - manifest.dvrWindowLengthUs);
}
long durationUs = endTimeUs - startTimeUs;
long defaultStartPositionUs = durationUs - C.msToUs(livePresentationDelayMs);
if (defaultStartPositionUs < MIN_LIVE_DEFAULT_START_POSITION_US) {
// The default start position is too close to the start of the live window. Set it to the
// minimum default start position provided the window is at least twice as big. Else set
// it to the middle of the window.
defaultStartPositionUs = Math.min(MIN_LIVE_DEFAULT_START_POSITION_US, durationUs / 2);
}
timeline = new SinglePeriodTimeline(C.TIME_UNSET, durationUs, startTimeUs, defaultStartPositionUs, true, /* isSeekable */
true);
}
} else {
boolean isSeekable = manifest.durationUs != C.TIME_UNSET;
timeline = new SinglePeriodTimeline(manifest.durationUs, isSeekable);
}
sourceListener.onSourceInfoRefreshed(timeline, manifest);
}
use of com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest.StreamElement in project ExoPlayer by google.
the class DefaultSsChunkSource method getNextChunk.
@Override
public final void getNextChunk(MediaChunk previous, long playbackPositionUs, ChunkHolder out) {
if (fatalError != null) {
return;
}
long bufferedDurationUs = previous != null ? (previous.endTimeUs - playbackPositionUs) : 0;
trackSelection.updateSelectedTrack(bufferedDurationUs);
StreamElement streamElement = manifest.streamElements[elementIndex];
if (streamElement.chunkCount == 0) {
// There aren't any chunks for us to load.
out.endOfStream = !manifest.isLive;
return;
}
int chunkIndex;
if (previous == null) {
chunkIndex = streamElement.getChunkIndex(playbackPositionUs);
} else {
chunkIndex = previous.getNextChunkIndex() - currentManifestChunkOffset;
if (chunkIndex < 0) {
// This is before the first chunk in the current manifest.
fatalError = new BehindLiveWindowException();
return;
}
}
if (chunkIndex >= streamElement.chunkCount) {
// This is beyond the last chunk in the current manifest.
out.endOfStream = !manifest.isLive;
return;
}
long chunkStartTimeUs = streamElement.getStartTimeUs(chunkIndex);
long chunkEndTimeUs = chunkStartTimeUs + streamElement.getChunkDurationUs(chunkIndex);
int currentAbsoluteChunkIndex = chunkIndex + currentManifestChunkOffset;
int trackSelectionIndex = trackSelection.getSelectedIndex();
ChunkExtractorWrapper extractorWrapper = extractorWrappers[trackSelectionIndex];
int manifestTrackIndex = trackSelection.getIndexInTrackGroup(trackSelectionIndex);
Uri uri = streamElement.buildRequestUri(manifestTrackIndex, chunkIndex);
out.chunk = newMediaChunk(trackSelection.getSelectedFormat(), dataSource, uri, null, currentAbsoluteChunkIndex, chunkStartTimeUs, chunkEndTimeUs, trackSelection.getSelectionReason(), trackSelection.getSelectionData(), extractorWrapper);
}
Aggregations