@Override public void enable(int track) { enabledTrack = tracks.get(track); if (enabledTrack.isAdaptive()) { adaptiveFormatEvaluator.enable(); } if (manifestFetcher != null) { manifestFetcher.enable(); } }
@Override public void disable(List<? extends MediaChunk> queue) { if (enabledTrack.isAdaptive()) { adaptiveFormatEvaluator.disable(); } if (manifestFetcher != null) { manifestFetcher.disable(); } evaluation.format = null; fatalError = null; }
@Override public final void getChunkOperation( List<? extends MediaChunk> queue, long playbackPositionUs, ChunkOperationHolder out) { if (fatalError != null) { out.chunk = null; return; } evaluation.queueSize = queue.size(); if (enabledTrack.isAdaptive()) { adaptiveFormatEvaluator.evaluate( queue, playbackPositionUs, enabledTrack.adaptiveFormats, evaluation); } else { evaluation.format = enabledTrack.fixedFormat; evaluation.trigger = Chunk.TRIGGER_MANUAL; } Format selectedFormat = evaluation.format; out.queueSize = evaluation.queueSize; if (selectedFormat == null) { out.chunk = null; return; } else if (out.queueSize == queue.size() && out.chunk != null && out.chunk.format.equals(selectedFormat)) { // We already have a chunk, and the evaluation hasn't changed either the format or the size // of the queue. Leave unchanged. return; } // In all cases where we return before instantiating a new chunk, we want out.chunk to be null. out.chunk = null; StreamElement streamElement = currentManifest.streamElements[enabledTrack.elementIndex]; if (streamElement.chunkCount == 0) { if (currentManifest.isLive) { needManifestRefresh = true; } else { out.endOfStream = true; } return; } int chunkIndex; if (queue.isEmpty()) { if (live) { playbackPositionUs = getLiveSeekPosition(currentManifest, liveEdgeLatencyUs); } chunkIndex = streamElement.getChunkIndex(playbackPositionUs); } else { MediaChunk previous = queue.get(out.queueSize - 1); chunkIndex = previous.chunkIndex + 1 - currentManifestChunkOffset; } if (live && chunkIndex < 0) { // This is before the first chunk in the current manifest. fatalError = new BehindLiveWindowException(); return; } else if (currentManifest.isLive) { if (chunkIndex >= streamElement.chunkCount) { // This is beyond the last chunk in the current manifest. needManifestRefresh = true; return; } else if (chunkIndex == streamElement.chunkCount - 1) { // This is the last chunk in the current manifest. Mark the manifest as being finished, // but continue to return the final chunk. needManifestRefresh = true; } } else if (chunkIndex >= streamElement.chunkCount) { out.endOfStream = true; return; } boolean isLastChunk = !currentManifest.isLive && chunkIndex == streamElement.chunkCount - 1; long chunkStartTimeUs = streamElement.getStartTimeUs(chunkIndex); long chunkEndTimeUs = isLastChunk ? -1 : chunkStartTimeUs + streamElement.getChunkDurationUs(chunkIndex); int currentAbsoluteChunkIndex = chunkIndex + currentManifestChunkOffset; int manifestTrackIndex = getManifestTrackIndex(streamElement, selectedFormat); int manifestTrackKey = getManifestTrackKey(enabledTrack.elementIndex, manifestTrackIndex); Uri uri = streamElement.buildRequestUri(manifestTrackIndex, chunkIndex); Chunk mediaChunk = newMediaChunk( selectedFormat, uri, null, extractorWrappers.get(manifestTrackKey), drmInitData, dataSource, currentAbsoluteChunkIndex, chunkStartTimeUs, chunkEndTimeUs, evaluation.trigger, mediaFormats.get(manifestTrackKey), enabledTrack.adaptiveMaxWidth, enabledTrack.adaptiveMaxHeight); out.chunk = mediaChunk; }