@Override public void disable(int track) { Assertions.checkState(state == STATE_ENABLED); Assertions.checkState(--enabledTrackCount == 0); state = STATE_PREPARED; try { chunkSource.disable(mediaChunks); } finally { loadControl.unregister(this); if (loader.isLoading()) { loader.cancelLoading(); } else { sampleQueue.clear(); mediaChunks.clear(); clearCurrentLoadable(); loadControl.trimAllocator(); } } }
@Override public void onLoadCanceled(Loadable loadable) { Chunk currentLoadable = currentLoadableHolder.chunk; notifyLoadCanceled(currentLoadable.bytesLoaded()); clearCurrentLoadable(); if (state == STATE_ENABLED) { restartFrom(pendingResetPositionUs); } else { sampleQueue.clear(); mediaChunks.clear(); clearCurrentLoadable(); loadControl.trimAllocator(); } }
@Override public void enable(int track, long positionUs) { Assertions.checkState(state == STATE_PREPARED); Assertions.checkState(enabledTrackCount++ == 0); state = STATE_ENABLED; chunkSource.enable(track); loadControl.register(this, bufferSizeContribution); downstreamFormat = null; downstreamMediaFormat = null; downstreamPositionUs = positionUs; lastSeekPositionUs = positionUs; pendingDiscontinuity = false; restartFrom(positionUs); }
private void updateLoadControl() { long now = SystemClock.elapsedRealtime(); long nextLoadPositionUs = getNextLoadPositionUs(); boolean isBackedOff = currentLoadableException != null; boolean loadingOrBackedOff = loader.isLoading() || isBackedOff; // If we're not loading or backed off, evaluate the operation if (a) we don't have the next // chunk yet and we're not finished, or (b) if the last evaluation was over 2000ms ago. if (!loadingOrBackedOff && ((currentLoadableHolder.chunk == null && nextLoadPositionUs != -1) || (now - lastPerformedBufferOperation > 2000))) { // Perform the evaluation. lastPerformedBufferOperation = now; doChunkOperation(); boolean chunksDiscarded = discardUpstreamMediaChunks(currentLoadableHolder.queueSize); // Update the next load position as appropriate. if (currentLoadableHolder.chunk == null) { // Set loadPosition to -1 to indicate that we don't have anything to load. nextLoadPositionUs = -1; } else if (chunksDiscarded) { // Chunks were discarded, so we need to re-evaluate the load position. nextLoadPositionUs = getNextLoadPositionUs(); } } // Update the control with our current state, and determine whether we're the next loader. boolean nextLoader = loadControl.update(this, downstreamPositionUs, nextLoadPositionUs, loadingOrBackedOff); if (isBackedOff) { long elapsedMillis = now - currentLoadableExceptionTimestamp; if (elapsedMillis >= getRetryDelayMillis(currentLoadableExceptionCount)) { resumeFromBackOff(); } return; } if (!loader.isLoading() && nextLoader) { maybeStartLoading(); } }
/** * @param chunkSource A {@link ChunkSource} from which chunks to load are obtained. * @param loadControl Controls when the source is permitted to load data. * @param bufferSizeContribution The contribution of this source to the media buffer, in bytes. * @param eventHandler A handler to use when delivering events to {@code eventListener}. May be * null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required. * @param eventSourceId An identifier that gets passed to {@code eventListener} methods. * @param minLoadableRetryCount The minimum number of times that the source should retry a load * before propagating an error. */ public ChunkSampleSource( ChunkSource chunkSource, LoadControl loadControl, int bufferSizeContribution, Handler eventHandler, EventListener eventListener, int eventSourceId, int minLoadableRetryCount) { this.chunkSource = chunkSource; this.loadControl = loadControl; this.bufferSizeContribution = bufferSizeContribution; this.eventHandler = eventHandler; this.eventListener = eventListener; this.eventSourceId = eventSourceId; this.minLoadableRetryCount = minLoadableRetryCount; currentLoadableHolder = new ChunkOperationHolder(); mediaChunks = new LinkedList<>(); readOnlyMediaChunks = Collections.unmodifiableList(mediaChunks); sampleQueue = new DefaultTrackOutput(loadControl.getAllocator()); state = STATE_IDLE; pendingResetPositionUs = NO_RESET_PENDING; }