mirror of
https://github.com/androidx/media.git
synced 2025-05-04 06:00:37 +08:00
Clean up chunked Sample/Chunk sources.
- Remove need for SampleSources to ref ChunkSources. - Correctly propagate errors loading manifests through ChunkSource components. - Fix some misc warnings. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=123732918
This commit is contained in:
parent
7aae5805b8
commit
7f70ee911b
@ -239,12 +239,12 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
return false;
|
||||
}
|
||||
} catch (ExoPlaybackException e) {
|
||||
Log.e(TAG, "Internal track renderer error.", e);
|
||||
Log.e(TAG, "Renderer error.", e);
|
||||
eventHandler.obtainMessage(MSG_ERROR, e).sendToTarget();
|
||||
stopInternal();
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Source track renderer error.", e);
|
||||
Log.e(TAG, "Source error.", e);
|
||||
eventHandler.obtainMessage(MSG_ERROR, ExoPlaybackException.createForSource(e)).sendToTarget();
|
||||
stopInternal();
|
||||
return true;
|
||||
|
@ -84,4 +84,11 @@ public interface ChunkSource {
|
||||
*/
|
||||
boolean onChunkLoadError(Chunk chunk, boolean cancelable, Exception e);
|
||||
|
||||
/**
|
||||
* Releases the source.
|
||||
* <p>
|
||||
* This method should be called when the source is no longer required.
|
||||
*/
|
||||
void release();
|
||||
|
||||
}
|
||||
|
@ -37,10 +37,11 @@ import java.util.List;
|
||||
/**
|
||||
* A {@link TrackStream} that loads media in {@link Chunk}s, obtained from a {@link ChunkSource}.
|
||||
*/
|
||||
public class ChunkTrackStream implements TrackStream, Loader.Callback<Chunk> {
|
||||
public class ChunkTrackStream<T extends ChunkSource> implements TrackStream,
|
||||
Loader.Callback<Chunk> {
|
||||
|
||||
private final Loader loader;
|
||||
private final ChunkSource chunkSource;
|
||||
private final T chunkSource;
|
||||
private final int minLoadableRetryCount;
|
||||
private final LinkedList<BaseMediaChunk> mediaChunks;
|
||||
private final List<BaseMediaChunk> readOnlyMediaChunks;
|
||||
@ -72,7 +73,7 @@ public class ChunkTrackStream implements TrackStream, Loader.Callback<Chunk> {
|
||||
* @param minLoadableRetryCount The minimum number of times that the source should retry a load
|
||||
* before propagating an error.
|
||||
*/
|
||||
public ChunkTrackStream(ChunkSource chunkSource, LoadControl loadControl,
|
||||
public ChunkTrackStream(T chunkSource, LoadControl loadControl,
|
||||
int bufferSizeContribution, long positionUs, Handler eventHandler,
|
||||
ChunkTrackStreamEventListener eventListener, int eventSourceId, int minLoadableRetryCount) {
|
||||
this.chunkSource = chunkSource;
|
||||
@ -109,6 +110,15 @@ public class ChunkTrackStream implements TrackStream, Loader.Callback<Chunk> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link ChunkSource} used by this stream.
|
||||
*
|
||||
* @return The {@link ChunkSource}.
|
||||
*/
|
||||
public T getChunkSource() {
|
||||
return chunkSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an estimate of the position up to which data is buffered.
|
||||
*
|
||||
@ -160,6 +170,7 @@ public class ChunkTrackStream implements TrackStream, Loader.Callback<Chunk> {
|
||||
* This method should be called when the stream is no longer required.
|
||||
*/
|
||||
public void release() {
|
||||
chunkSource.release();
|
||||
loadControl.unregister(this);
|
||||
if (loader.isLoading()) {
|
||||
loader.cancelLoading();
|
||||
@ -181,7 +192,9 @@ public class ChunkTrackStream implements TrackStream, Loader.Callback<Chunk> {
|
||||
@Override
|
||||
public void maybeThrowError() throws IOException {
|
||||
loader.maybeThrowError();
|
||||
chunkSource.maybeThrowError();
|
||||
if (!loader.isLoading()) {
|
||||
chunkSource.maybeThrowError();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -42,6 +42,7 @@ import com.google.android.exoplayer.extractor.mkv.MatroskaExtractor;
|
||||
import com.google.android.exoplayer.extractor.mp4.FragmentedMp4Extractor;
|
||||
import com.google.android.exoplayer.upstream.DataSource;
|
||||
import com.google.android.exoplayer.upstream.DataSpec;
|
||||
import com.google.android.exoplayer.upstream.Loader;
|
||||
import com.google.android.exoplayer.util.MimeTypes;
|
||||
import com.google.android.exoplayer.util.Util;
|
||||
|
||||
@ -56,6 +57,7 @@ import java.util.List;
|
||||
*/
|
||||
public class DashChunkSource implements ChunkSource {
|
||||
|
||||
private final Loader manifestLoader;
|
||||
private final int adaptationSetIndex;
|
||||
private final TrackGroup trackGroup;
|
||||
private final RepresentationHolder[] representationHolders;
|
||||
@ -72,6 +74,7 @@ public class DashChunkSource implements ChunkSource {
|
||||
private IOException fatalError;
|
||||
|
||||
/**
|
||||
* @param manifestLoader The {@link Loader} being used to load manifests.
|
||||
* @param manifest The initial manifest.
|
||||
* @param adaptationSetIndex The index of the adaptation set in the manifest.
|
||||
* @param trackGroup The track group corresponding to the adaptation set.
|
||||
@ -82,9 +85,10 @@ public class DashChunkSource implements ChunkSource {
|
||||
* server-side unix time and {@link SystemClock#elapsedRealtime()} in milliseconds, specified
|
||||
* as the server's unix time minus the local elapsed time. It unknown, set to 0.
|
||||
*/
|
||||
public DashChunkSource(MediaPresentationDescription manifest, int adaptationSetIndex,
|
||||
TrackGroup trackGroup, int[] tracks, DataSource dataSource,
|
||||
public DashChunkSource(Loader manifestLoader, MediaPresentationDescription manifest,
|
||||
int adaptationSetIndex, TrackGroup trackGroup, int[] tracks, DataSource dataSource,
|
||||
FormatEvaluator adaptiveFormatEvaluator, long elapsedRealtimeOffsetMs) {
|
||||
this.manifestLoader = manifestLoader;
|
||||
this.manifest = manifest;
|
||||
this.adaptationSetIndex = adaptationSetIndex;
|
||||
this.trackGroup = trackGroup;
|
||||
@ -131,18 +135,14 @@ public class DashChunkSource implements ChunkSource {
|
||||
}
|
||||
}
|
||||
|
||||
public void release() {
|
||||
if (adaptiveFormatEvaluator != null) {
|
||||
adaptiveFormatEvaluator.disable();
|
||||
}
|
||||
}
|
||||
|
||||
// ChunkSource implementation.
|
||||
|
||||
@Override
|
||||
public void maybeThrowError() throws IOException {
|
||||
if (fatalError != null) {
|
||||
throw fatalError;
|
||||
} else {
|
||||
manifestLoader.maybeThrowError();
|
||||
}
|
||||
}
|
||||
|
||||
@ -273,6 +273,13 @@ public class DashChunkSource implements ChunkSource {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
if (adaptiveFormatEvaluator != null) {
|
||||
adaptiveFormatEvaluator.disable();
|
||||
}
|
||||
}
|
||||
|
||||
// Private methods.
|
||||
|
||||
private long getNowUnixTimeUs() {
|
||||
|
@ -47,7 +47,6 @@ import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
@ -93,9 +92,7 @@ public final class DashSampleSource implements SampleSource {
|
||||
private int[] trackGroupAdaptationSetIndices;
|
||||
private boolean pendingReset;
|
||||
private long lastSeekPositionUs;
|
||||
|
||||
private DashChunkSource[] chunkSources;
|
||||
private ChunkTrackStream[] trackStreams;
|
||||
private ChunkTrackStream<DashChunkSource>[] trackStreams;
|
||||
|
||||
public DashSampleSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
||||
BandwidthMeter bandwidthMeter, Handler eventHandler,
|
||||
@ -110,8 +107,7 @@ public final class DashSampleSource implements SampleSource {
|
||||
dataSource = dataSourceFactory.createDataSource();
|
||||
manifestParser = new MediaPresentationDescriptionParser();
|
||||
manifestCallback = new ManifestCallback();
|
||||
chunkSources = new DashChunkSource[0];
|
||||
trackStreams = new ChunkTrackStream[0];
|
||||
trackStreams = newTrackStreamArray(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -140,18 +136,15 @@ public final class DashSampleSource implements SampleSource {
|
||||
public TrackStream[] selectTracks(List<TrackStream> oldStreams,
|
||||
List<TrackSelection> newSelections, long positionUs) {
|
||||
int newEnabledSourceCount = trackStreams.length + newSelections.size() - oldStreams.size();
|
||||
DashChunkSource[] newChunkSources = new DashChunkSource[newEnabledSourceCount];
|
||||
ChunkTrackStream[] newTrackStreams = new ChunkTrackStream[newEnabledSourceCount];
|
||||
ChunkTrackStream<DashChunkSource>[] newTrackStreams =
|
||||
newTrackStreamArray(newEnabledSourceCount);
|
||||
int newEnabledSourceIndex = 0;
|
||||
|
||||
// Iterate over currently enabled streams, either releasing them or adding them to the new list.
|
||||
for (int i = 0; i < trackStreams.length; i++) {
|
||||
ChunkTrackStream trackStream = trackStreams[i];
|
||||
for (ChunkTrackStream<DashChunkSource> trackStream : trackStreams) {
|
||||
if (oldStreams.contains(trackStream)) {
|
||||
chunkSources[i].release();
|
||||
trackStream.release();
|
||||
} else {
|
||||
newChunkSources[newEnabledSourceIndex] = chunkSources[i];
|
||||
newTrackStreams[newEnabledSourceIndex++] = trackStream;
|
||||
}
|
||||
}
|
||||
@ -159,14 +152,11 @@ public final class DashSampleSource implements SampleSource {
|
||||
// Instantiate and return new streams.
|
||||
TrackStream[] streamsToReturn = new TrackStream[newSelections.size()];
|
||||
for (int i = 0; i < newSelections.size(); i++) {
|
||||
Pair<DashChunkSource, ChunkTrackStream> trackComponents =
|
||||
buildTrackStream(newSelections.get(i), positionUs);
|
||||
newChunkSources[newEnabledSourceIndex] = trackComponents.first;
|
||||
newTrackStreams[newEnabledSourceIndex++] = trackComponents.second;
|
||||
streamsToReturn[i] = trackComponents.second;
|
||||
newTrackStreams[newEnabledSourceIndex] = buildTrackStream(newSelections.get(i), positionUs);
|
||||
streamsToReturn[i] = newTrackStreams[newEnabledSourceIndex];
|
||||
newEnabledSourceIndex++;
|
||||
}
|
||||
|
||||
chunkSources = newChunkSources;
|
||||
trackStreams = newTrackStreams;
|
||||
return streamsToReturn;
|
||||
}
|
||||
@ -187,7 +177,7 @@ public final class DashSampleSource implements SampleSource {
|
||||
startLoadingManifest();
|
||||
}
|
||||
}
|
||||
for (ChunkTrackStream trackStream : trackStreams) {
|
||||
for (ChunkTrackStream<DashChunkSource> trackStream : trackStreams) {
|
||||
trackStream.continueBuffering(positionUs);
|
||||
}
|
||||
}
|
||||
@ -196,7 +186,7 @@ public final class DashSampleSource implements SampleSource {
|
||||
public long readReset() {
|
||||
if (pendingReset) {
|
||||
pendingReset = false;
|
||||
for (ChunkTrackStream trackStream : trackStreams) {
|
||||
for (ChunkTrackStream<DashChunkSource> trackStream : trackStreams) {
|
||||
trackStream.setReadingEnabled(true);
|
||||
}
|
||||
return lastSeekPositionUs;
|
||||
@ -207,7 +197,7 @@ public final class DashSampleSource implements SampleSource {
|
||||
@Override
|
||||
public long getBufferedPositionUs() {
|
||||
long bufferedPositionUs = Long.MAX_VALUE;
|
||||
for (ChunkTrackStream trackStream : trackStreams) {
|
||||
for (ChunkTrackStream<DashChunkSource> trackStream : trackStreams) {
|
||||
long rendererBufferedPositionUs = trackStream.getBufferedPositionUs();
|
||||
if (rendererBufferedPositionUs != C.END_OF_SOURCE_US) {
|
||||
bufferedPositionUs = Math.min(bufferedPositionUs, rendererBufferedPositionUs);
|
||||
@ -220,7 +210,7 @@ public final class DashSampleSource implements SampleSource {
|
||||
public void seekToUs(long positionUs) {
|
||||
lastSeekPositionUs = positionUs;
|
||||
pendingReset = true;
|
||||
for (ChunkTrackStream trackStream : trackStreams) {
|
||||
for (ChunkTrackStream<DashChunkSource> trackStream : trackStreams) {
|
||||
trackStream.setReadingEnabled(false);
|
||||
trackStream.seekToUs(positionUs);
|
||||
}
|
||||
@ -229,10 +219,7 @@ public final class DashSampleSource implements SampleSource {
|
||||
@Override
|
||||
public void release() {
|
||||
loader.release();
|
||||
for (DashChunkSource chunkSource : chunkSources) {
|
||||
chunkSource.release();
|
||||
}
|
||||
for (ChunkTrackStream trackStream : trackStreams) {
|
||||
for (ChunkTrackStream<DashChunkSource> trackStream : trackStreams) {
|
||||
trackStream.release();
|
||||
}
|
||||
}
|
||||
@ -254,8 +241,8 @@ public final class DashSampleSource implements SampleSource {
|
||||
prepared = true;
|
||||
}
|
||||
} else {
|
||||
for (DashChunkSource chunkSource : chunkSources) {
|
||||
chunkSource.updateManifest(manifest);
|
||||
for (ChunkTrackStream<DashChunkSource> trackStream : trackStreams) {
|
||||
trackStream.getChunkSource().updateManifest(manifest);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -337,7 +324,7 @@ public final class DashSampleSource implements SampleSource {
|
||||
trackGroups = new TrackGroupArray(trackGroupArray);
|
||||
}
|
||||
|
||||
private Pair<DashChunkSource, ChunkTrackStream> buildTrackStream(TrackSelection selection,
|
||||
private ChunkTrackStream<DashChunkSource> buildTrackStream(TrackSelection selection,
|
||||
long positionUs) {
|
||||
int[] selectedTracks = selection.getTracks();
|
||||
FormatEvaluator adaptiveEvaluator = selectedTracks.length > 1
|
||||
@ -348,14 +335,17 @@ public final class DashSampleSource implements SampleSource {
|
||||
int adaptationSetType = adaptationSet.type;
|
||||
int bufferSize = Util.getDefaultBufferSize(adaptationSetType);
|
||||
DataSource dataSource = dataSourceFactory.createDataSource(bandwidthMeter);
|
||||
DashChunkSource chunkSource = new DashChunkSource(manifest, adaptationSetIndex,
|
||||
DashChunkSource chunkSource = new DashChunkSource(loader, manifest, adaptationSetIndex,
|
||||
trackGroups.get(selection.group), selectedTracks, dataSource, adaptiveEvaluator,
|
||||
elapsedRealtimeOffset);
|
||||
ChunkTrackStream trackStream = new ChunkTrackStream(chunkSource, loadControl, bufferSize,
|
||||
positionUs, eventHandler, eventListener, adaptationSetType, MIN_LOADABLE_RETRY_COUNT);
|
||||
return Pair.create(chunkSource, trackStream);
|
||||
return new ChunkTrackStream<>(chunkSource, loadControl, bufferSize, positionUs, eventHandler,
|
||||
eventListener, adaptationSetType, MIN_LOADABLE_RETRY_COUNT);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static ChunkTrackStream<DashChunkSource>[] newTrackStreamArray(int length) {
|
||||
return new ChunkTrackStream[length];
|
||||
}
|
||||
|
||||
private final class ManifestCallback implements
|
||||
Loader.Callback<UriLoadable<MediaPresentationDescription>> {
|
||||
|
@ -93,7 +93,7 @@ import java.util.List;
|
||||
* @param bufferSizeContribution The contribution of this source to the media buffer, in bytes.
|
||||
* @param muxedAudioFormat If HLS master playlist indicates that the stream contains muxed audio,
|
||||
* this is the audio {@link Format} as defined by the playlist.
|
||||
* @param muxedAudioFormat If HLS master playlist indicates that the stream contains muxed
|
||||
* @param muxedCaptionFormat If HLS master playlist indicates that the stream contains muxed
|
||||
* captions, this is the audio {@link Format} as defined by the playlist.
|
||||
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
|
||||
* null if delivery of events is not required.
|
||||
|
@ -34,6 +34,7 @@ import com.google.android.exoplayer.extractor.mp4.TrackEncryptionBox;
|
||||
import com.google.android.exoplayer.smoothstreaming.SmoothStreamingManifest.StreamElement;
|
||||
import com.google.android.exoplayer.upstream.DataSource;
|
||||
import com.google.android.exoplayer.upstream.DataSpec;
|
||||
import com.google.android.exoplayer.upstream.Loader;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
@ -47,6 +48,7 @@ import java.util.List;
|
||||
*/
|
||||
public class SmoothStreamingChunkSource implements ChunkSource {
|
||||
|
||||
private final Loader manifestLoader;
|
||||
private final int elementIndex;
|
||||
private final TrackGroup trackGroup;
|
||||
private final ChunkExtractorWrapper[] extractorWrappers;
|
||||
@ -63,6 +65,7 @@ public class SmoothStreamingChunkSource implements ChunkSource {
|
||||
private IOException fatalError;
|
||||
|
||||
/**
|
||||
* @param manifestLoader The {@link Loader} being used to load manifests.
|
||||
* @param manifest The initial manifest.
|
||||
* @param elementIndex The index of the stream element in the manifest.
|
||||
* @param trackGroup The track group corresponding to the stream element.
|
||||
@ -71,9 +74,10 @@ public class SmoothStreamingChunkSource implements ChunkSource {
|
||||
* @param adaptiveFormatEvaluator For adaptive tracks, selects from the available formats.
|
||||
* @param trackEncryptionBoxes Track encryption boxes for the stream.
|
||||
*/
|
||||
public SmoothStreamingChunkSource(SmoothStreamingManifest manifest, int elementIndex,
|
||||
TrackGroup trackGroup, int[] tracks, DataSource dataSource,
|
||||
public SmoothStreamingChunkSource(Loader manifestLoader, SmoothStreamingManifest manifest,
|
||||
int elementIndex, TrackGroup trackGroup, int[] tracks, DataSource dataSource,
|
||||
FormatEvaluator adaptiveFormatEvaluator, TrackEncryptionBox[] trackEncryptionBoxes) {
|
||||
this.manifestLoader = manifestLoader;
|
||||
this.manifest = manifest;
|
||||
this.elementIndex = elementIndex;
|
||||
this.trackGroup = trackGroup;
|
||||
@ -135,18 +139,14 @@ public class SmoothStreamingChunkSource implements ChunkSource {
|
||||
return needManifestRefresh;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
if (adaptiveFormatEvaluator != null) {
|
||||
adaptiveFormatEvaluator.disable();
|
||||
}
|
||||
}
|
||||
|
||||
// ChunkSource implementation.
|
||||
|
||||
@Override
|
||||
public void maybeThrowError() throws IOException {
|
||||
if (fatalError != null) {
|
||||
throw fatalError;
|
||||
} else {
|
||||
manifestLoader.maybeThrowError();
|
||||
}
|
||||
}
|
||||
|
||||
@ -233,6 +233,13 @@ public class SmoothStreamingChunkSource implements ChunkSource {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
if (adaptiveFormatEvaluator != null) {
|
||||
adaptiveFormatEvaluator.disable();
|
||||
}
|
||||
}
|
||||
|
||||
// Private methods.
|
||||
|
||||
/**
|
||||
|
@ -44,7 +44,6 @@ import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Base64;
|
||||
import android.util.Pair;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
@ -85,8 +84,7 @@ public final class SmoothStreamingSampleSource implements SampleSource,
|
||||
private boolean pendingReset;
|
||||
private long lastSeekPositionUs;
|
||||
|
||||
private SmoothStreamingChunkSource[] chunkSources;
|
||||
private ChunkTrackStream[] trackStreams;
|
||||
private ChunkTrackStream<SmoothStreamingChunkSource>[] trackStreams;
|
||||
|
||||
public SmoothStreamingSampleSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
||||
BandwidthMeter bandwidthMeter, Handler eventHandler,
|
||||
@ -97,11 +95,8 @@ public final class SmoothStreamingSampleSource implements SampleSource,
|
||||
this.bandwidthMeter = bandwidthMeter;
|
||||
this.eventHandler = eventHandler;
|
||||
this.eventListener = eventListener;
|
||||
|
||||
loadControl = new DefaultLoadControl(new DefaultAllocator(C.DEFAULT_BUFFER_SEGMENT_SIZE));
|
||||
chunkSources = new SmoothStreamingChunkSource[0];
|
||||
trackStreams = new ChunkTrackStream[0];
|
||||
|
||||
trackStreams = newTrackStreamArray(0);
|
||||
manifestDataSource = dataSourceFactory.createDataSource();
|
||||
manifestParser = new SmoothStreamingManifestParser();
|
||||
manifestLoader = new Loader("Loader:Manifest");
|
||||
@ -133,19 +128,15 @@ public final class SmoothStreamingSampleSource implements SampleSource,
|
||||
public TrackStream[] selectTracks(List<TrackStream> oldStreams,
|
||||
List<TrackSelection> newSelections, long positionUs) {
|
||||
int newEnabledSourceCount = trackStreams.length + newSelections.size() - oldStreams.size();
|
||||
SmoothStreamingChunkSource[] newChunkSources =
|
||||
new SmoothStreamingChunkSource[newEnabledSourceCount];
|
||||
ChunkTrackStream[] newTrackStreams = new ChunkTrackStream[newEnabledSourceCount];
|
||||
ChunkTrackStream<SmoothStreamingChunkSource>[] newTrackStreams =
|
||||
newTrackStreamArray(newEnabledSourceCount);
|
||||
int newEnabledSourceIndex = 0;
|
||||
|
||||
// Iterate over currently enabled streams, either releasing them or adding them to the new list.
|
||||
for (int i = 0; i < trackStreams.length; i++) {
|
||||
ChunkTrackStream trackStream = trackStreams[i];
|
||||
for (ChunkTrackStream<SmoothStreamingChunkSource> trackStream : trackStreams) {
|
||||
if (oldStreams.contains(trackStream)) {
|
||||
chunkSources[i].release();
|
||||
trackStream.release();
|
||||
} else {
|
||||
newChunkSources[newEnabledSourceIndex] = chunkSources[i];
|
||||
newTrackStreams[newEnabledSourceIndex++] = trackStream;
|
||||
}
|
||||
}
|
||||
@ -153,14 +144,11 @@ public final class SmoothStreamingSampleSource implements SampleSource,
|
||||
// Instantiate and return new streams.
|
||||
TrackStream[] streamsToReturn = new TrackStream[newSelections.size()];
|
||||
for (int i = 0; i < newSelections.size(); i++) {
|
||||
Pair<SmoothStreamingChunkSource, ChunkTrackStream> trackComponents =
|
||||
buildTrackStream(newSelections.get(i), positionUs);
|
||||
newChunkSources[newEnabledSourceIndex] = trackComponents.first;
|
||||
newTrackStreams[newEnabledSourceIndex++] = trackComponents.second;
|
||||
streamsToReturn[i] = trackComponents.second;
|
||||
newTrackStreams[newEnabledSourceIndex] = buildTrackStream(newSelections.get(i), positionUs);
|
||||
streamsToReturn[i] = newTrackStreams[newEnabledSourceIndex];
|
||||
newEnabledSourceIndex++;
|
||||
}
|
||||
|
||||
chunkSources = newChunkSources;
|
||||
trackStreams = newTrackStreams;
|
||||
return streamsToReturn;
|
||||
}
|
||||
@ -170,15 +158,15 @@ public final class SmoothStreamingSampleSource implements SampleSource,
|
||||
if (manifest.isLive) {
|
||||
if (!manifestLoader.isLoading() && SystemClock.elapsedRealtime()
|
||||
> manifestLoadTimestamp + MINIMUM_MANIFEST_REFRESH_PERIOD_MS) {
|
||||
for (SmoothStreamingChunkSource chunkSource : chunkSources) {
|
||||
if (chunkSource.needManifestRefresh()) {
|
||||
for (ChunkTrackStream<SmoothStreamingChunkSource> trackStream : trackStreams) {
|
||||
if (trackStream.getChunkSource().needManifestRefresh()) {
|
||||
startLoadingManifest();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (ChunkTrackStream trackStream : trackStreams) {
|
||||
for (ChunkTrackStream<SmoothStreamingChunkSource> trackStream : trackStreams) {
|
||||
trackStream.continueBuffering(positionUs);
|
||||
}
|
||||
}
|
||||
@ -187,7 +175,7 @@ public final class SmoothStreamingSampleSource implements SampleSource,
|
||||
public long readReset() {
|
||||
if (pendingReset) {
|
||||
pendingReset = false;
|
||||
for (ChunkTrackStream trackStream : trackStreams) {
|
||||
for (ChunkTrackStream<SmoothStreamingChunkSource> trackStream : trackStreams) {
|
||||
trackStream.setReadingEnabled(true);
|
||||
}
|
||||
return lastSeekPositionUs;
|
||||
@ -198,7 +186,7 @@ public final class SmoothStreamingSampleSource implements SampleSource,
|
||||
@Override
|
||||
public long getBufferedPositionUs() {
|
||||
long bufferedPositionUs = Long.MAX_VALUE;
|
||||
for (ChunkTrackStream trackStream : trackStreams) {
|
||||
for (ChunkTrackStream<SmoothStreamingChunkSource> trackStream : trackStreams) {
|
||||
long rendererBufferedPositionUs = trackStream.getBufferedPositionUs();
|
||||
if (rendererBufferedPositionUs != C.END_OF_SOURCE_US) {
|
||||
bufferedPositionUs = Math.min(bufferedPositionUs, rendererBufferedPositionUs);
|
||||
@ -211,7 +199,7 @@ public final class SmoothStreamingSampleSource implements SampleSource,
|
||||
public void seekToUs(long positionUs) {
|
||||
lastSeekPositionUs = positionUs;
|
||||
pendingReset = true;
|
||||
for (ChunkTrackStream trackStream : trackStreams) {
|
||||
for (ChunkTrackStream<SmoothStreamingChunkSource> trackStream : trackStreams) {
|
||||
trackStream.setReadingEnabled(false);
|
||||
trackStream.seekToUs(positionUs);
|
||||
}
|
||||
@ -220,10 +208,7 @@ public final class SmoothStreamingSampleSource implements SampleSource,
|
||||
@Override
|
||||
public void release() {
|
||||
manifestLoader.release();
|
||||
for (SmoothStreamingChunkSource chunkSource : chunkSources) {
|
||||
chunkSource.release();
|
||||
}
|
||||
for (ChunkTrackStream trackStream : trackStreams) {
|
||||
for (ChunkTrackStream<SmoothStreamingChunkSource> trackStream : trackStreams) {
|
||||
trackStream.release();
|
||||
}
|
||||
}
|
||||
@ -245,8 +230,8 @@ public final class SmoothStreamingSampleSource implements SampleSource,
|
||||
}
|
||||
prepared = true;
|
||||
} else {
|
||||
for (SmoothStreamingChunkSource chunkSource : chunkSources) {
|
||||
chunkSource.updateManifest(manifest);
|
||||
for (ChunkTrackStream<SmoothStreamingChunkSource> trackStream : trackStreams) {
|
||||
trackStream.getChunkSource().updateManifest(manifest);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -291,8 +276,8 @@ public final class SmoothStreamingSampleSource implements SampleSource,
|
||||
trackGroups = new TrackGroupArray(trackGroupArray);
|
||||
}
|
||||
|
||||
private Pair<SmoothStreamingChunkSource, ChunkTrackStream> buildTrackStream(
|
||||
TrackSelection selection, long positionUs) {
|
||||
private ChunkTrackStream<SmoothStreamingChunkSource> buildTrackStream(TrackSelection selection,
|
||||
long positionUs) {
|
||||
int[] selectedTracks = selection.getTracks();
|
||||
FormatEvaluator adaptiveEvaluator = selectedTracks.length > 1
|
||||
? new AdaptiveEvaluator(bandwidthMeter) : null;
|
||||
@ -301,12 +286,16 @@ public final class SmoothStreamingSampleSource implements SampleSource,
|
||||
int streamElementType = streamElement.type;
|
||||
int bufferSize = Util.getDefaultBufferSize(streamElementType);
|
||||
DataSource dataSource = dataSourceFactory.createDataSource(bandwidthMeter);
|
||||
SmoothStreamingChunkSource chunkSource = new SmoothStreamingChunkSource(manifest,
|
||||
streamElementIndex, trackGroups.get(selection.group), selectedTracks, dataSource,
|
||||
SmoothStreamingChunkSource chunkSource = new SmoothStreamingChunkSource(manifestLoader,
|
||||
manifest, streamElementIndex, trackGroups.get(selection.group), selectedTracks, dataSource,
|
||||
adaptiveEvaluator, trackEncryptionBoxes);
|
||||
ChunkTrackStream trackStream = new ChunkTrackStream(chunkSource, loadControl, bufferSize,
|
||||
positionUs, eventHandler, eventListener, streamElementType, MIN_LOADABLE_RETRY_COUNT);
|
||||
return Pair.create(chunkSource, trackStream);
|
||||
return new ChunkTrackStream<>(chunkSource, loadControl, bufferSize, positionUs, eventHandler,
|
||||
eventListener, streamElementType, MIN_LOADABLE_RETRY_COUNT);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static ChunkTrackStream<SmoothStreamingChunkSource>[] newTrackStreamArray(int length) {
|
||||
return new ChunkTrackStream[length];
|
||||
}
|
||||
|
||||
private static byte[] getProtectionElementKeyId(byte[] initData) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user