From eb3460b3aa8a198900f9604a9b038ae53ee19761 Mon Sep 17 00:00:00 2001 From: olly Date: Thu, 28 Apr 2016 02:34:06 -0700 Subject: [PATCH] Refactor #6.2: Start to simplify components. Parse the duration of the media directly from the manifest in the DASH/SS SampleSource implementations. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=121001296 --- .../exoplayer/chunk/ChunkSampleSource.java | 24 +--------- .../android/exoplayer/chunk/ChunkSource.java | 11 ----- .../exoplayer/dash/DashChunkSource.java | 12 ----- .../exoplayer/dash/DashSampleSource.java | 47 ++++++++----------- .../SmoothStreamingChunkSource.java | 12 ++--- .../SmoothStreamingSampleSource.java | 47 ++++++++----------- 6 files changed, 43 insertions(+), 110 deletions(-) diff --git a/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java b/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java index 574f370486..fe61b310f9 100644 --- a/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java @@ -43,7 +43,7 @@ import java.util.List; * A {@link SampleSource} that loads media in {@link Chunk}s, which are themselves obtained from a * {@link ChunkSource}. */ -public class ChunkSampleSource implements SampleSource, TrackStream, Loader.Callback { +public class ChunkSampleSource implements TrackStream, Loader.Callback { /** * The default minimum number of times to retry loading data prior to failing. @@ -60,7 +60,6 @@ public class ChunkSampleSource implements SampleSource, TrackStream, Loader.Call private final EventDispatcher eventDispatcher; private final LoadControl loadControl; - private boolean prepared; private boolean notifyReset; private long lastPreferredQueueSizeEvaluationTimeMs; private Format downstreamFormat; @@ -130,35 +129,21 @@ public class ChunkSampleSource implements SampleSource, TrackStream, Loader.Call // SampleSource implementation. - @Override - public boolean prepare(long positionUs) throws IOException { - if (prepared) { - return true; - } + public void prepare() { TrackGroup tracks = chunkSource.getTracks(); if (tracks != null) { trackGroups = new TrackGroupArray(tracks); } else { trackGroups = new TrackGroupArray(); } - prepared = true; - return true; } - @Override - public long getDurationUs() { - return chunkSource.getDurationUs(); - } - - @Override public TrackGroupArray getTrackGroups() { return trackGroups; } - @Override public TrackStream[] selectTracks(List oldStreams, List newSelections, long positionUs) { - Assertions.checkState(prepared); Assertions.checkState(oldStreams.size() <= 1); Assertions.checkState(newSelections.size() <= 1); boolean trackWasEnabled = trackEnabled; @@ -201,7 +186,6 @@ public class ChunkSampleSource implements SampleSource, TrackStream, Loader.Call return newStreams; } - @Override public void continueBuffering(long positionUs) { downstreamPositionUs = positionUs; if (!loader.isLoading()) { @@ -209,7 +193,6 @@ public class ChunkSampleSource implements SampleSource, TrackStream, Loader.Call } } - @Override public long readReset() { if (notifyReset) { notifyReset = false; @@ -218,7 +201,6 @@ public class ChunkSampleSource implements SampleSource, TrackStream, Loader.Call return C.UNSET_TIME_US; } - @Override public long getBufferedPositionUs() { if (loadingFinished) { return C.END_OF_SOURCE_US; @@ -236,7 +218,6 @@ public class ChunkSampleSource implements SampleSource, TrackStream, Loader.Call } } - @Override public void seekToUs(long positionUs) { downstreamPositionUs = positionUs; lastSeekPositionUs = positionUs; @@ -256,7 +237,6 @@ public class ChunkSampleSource implements SampleSource, TrackStream, Loader.Call notifyReset = true; } - @Override public void release() { if (trackEnabled) { loadControl.unregister(this); diff --git a/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSource.java b/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSource.java index 6d8171b30d..4195241804 100644 --- a/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSource.java +++ b/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSource.java @@ -15,7 +15,6 @@ */ package com.google.android.exoplayer.chunk; -import com.google.android.exoplayer.C; import com.google.android.exoplayer.TrackGroup; import java.io.IOException; @@ -41,16 +40,6 @@ public interface ChunkSource { */ void maybeThrowError() throws IOException; - /** - * Gets the duration of the source in microseconds. - *

- * This method should only be called after the source has been prepared. - * - * @return The duration of the source in microseconds, or {@link C#UNSET_TIME_US} if the duration - * is unknown. - */ - long getDurationUs(); - /** * Gets the group of tracks provided by the source. *

diff --git a/library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java b/library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java index 2c01193853..d7cb4a8ee2 100644 --- a/library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java +++ b/library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java @@ -71,10 +71,6 @@ public class DashChunkSource implements ChunkSource { private final FormatEvaluator adaptiveFormatEvaluator; private final Evaluation evaluation; - // Properties of the initial manifest. - private boolean live; - private long durationUs; - private MediaPresentationDescription currentManifest; private DrmInitData drmInitData; @@ -118,11 +114,6 @@ public class DashChunkSource implements ChunkSource { initForManifest(currentManifest); } - @Override - public long getDurationUs() { - return durationUs; - } - @Override public final TrackGroup getTracks() { return trackGroup; @@ -293,9 +284,6 @@ public class DashChunkSource implements ChunkSource { private void initForManifest(MediaPresentationDescription manifest) { Period period = manifest.getPeriod(0); - live = currentManifest.dynamic; - durationUs = live ? C.UNSET_TIME_US : currentManifest.duration * 1000; - for (int i = 0; i < period.adaptationSets.size(); i++) { AdaptationSet adaptationSet = period.adaptationSets.get(i); if (adaptationSet.type == adaptationSetType) { diff --git a/library/src/main/java/com/google/android/exoplayer/dash/DashSampleSource.java b/library/src/main/java/com/google/android/exoplayer/dash/DashSampleSource.java index 9a10a267d7..2526edfa02 100644 --- a/library/src/main/java/com/google/android/exoplayer/dash/DashSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/dash/DashSampleSource.java @@ -52,8 +52,8 @@ public final class DashSampleSource implements SampleSource { private final ManifestFetcher manifestFetcher; private final DashChunkSource[] chunkSources; - private final SampleSource[] sources; - private final IdentityHashMap trackStreamSources; + private final ChunkSampleSource[] sources; + private final IdentityHashMap trackStreamSources; private final int[] selectedTrackCounts; private MediaPresentationDescription currentManifest; @@ -61,7 +61,7 @@ public final class DashSampleSource implements SampleSource { private boolean seenFirstTrackSelection; private long durationUs; private TrackGroupArray trackGroups; - private SampleSource[] enabledSources; + private ChunkSampleSource[] enabledSources; public DashSampleSource(Uri uri, DataSourceFactory dataSourceFactory, BandwidthMeter bandwidthMeter, Handler eventHandler, @@ -94,7 +94,7 @@ public final class DashSampleSource implements SampleSource { C.DEFAULT_TEXT_BUFFER_SIZE, eventHandler, eventListener, C.TRACK_TYPE_TEXT); chunkSources = new DashChunkSource[] {videoChunkSource, audioChunkSource, textChunkSource}; - sources = new SampleSource[] {videoSampleSource, audioSampleSource, textSampleSource}; + sources = new ChunkSampleSource[] {videoSampleSource, audioSampleSource, textSampleSource}; trackStreamSources = new IdentityHashMap<>(); selectedTrackCounts = new int[sources.length]; } @@ -112,32 +112,23 @@ public final class DashSampleSource implements SampleSource { manifestFetcher.requestRefresh(); return false; } else { + durationUs = currentManifest.dynamic ? C.UNSET_TIME_US : currentManifest.duration * 1000; for (DashChunkSource chunkSource : chunkSources) { chunkSource.init(currentManifest); } } } - boolean sourcesPrepared = true; - for (SampleSource source : sources) { - sourcesPrepared &= source.prepare(positionUs); + for (ChunkSampleSource source : sources) { + source.prepare(); } - if (!sourcesPrepared) { - return false; - } - durationUs = 0; int totalTrackGroupCount = 0; - for (SampleSource source : sources) { + for (ChunkSampleSource source : sources) { totalTrackGroupCount += source.getTrackGroups().length; - if (durationUs != C.UNSET_TIME_US) { - long sourceDurationUs = source.getDurationUs(); - durationUs = sourceDurationUs == C.UNSET_TIME_US - ? C.UNSET_TIME_US : Math.max(durationUs, sourceDurationUs); - } } TrackGroup[] trackGroupArray = new TrackGroup[totalTrackGroupCount]; int trackGroupIndex = 0; - for (SampleSource source : sources) { + for (ChunkSampleSource source : sources) { int sourceTrackGroupCount = source.getTrackGroups().length; for (int j = 0; j < sourceTrackGroupCount; j++) { trackGroupArray[trackGroupIndex++] = source.getTrackGroups().get(j); @@ -173,7 +164,7 @@ public final class DashSampleSource implements SampleSource { } } // Update the enabled sources. - enabledSources = new SampleSource[enabledSourceCount]; + enabledSources = new ChunkSampleSource[enabledSourceCount]; enabledSourceCount = 0; for (int i = 0; i < sources.length; i++) { if (selectedTrackCounts[i] > 0) { @@ -210,7 +201,7 @@ public final class DashSampleSource implements SampleSource { } } - for (SampleSource source : enabledSources) { + for (ChunkSampleSource source : enabledSources) { source.continueBuffering(positionUs); } } @@ -218,7 +209,7 @@ public final class DashSampleSource implements SampleSource { @Override public long readReset() { long resetPositionUs = C.UNSET_TIME_US; - for (SampleSource source : enabledSources) { + for (ChunkSampleSource source : enabledSources) { long childResetPositionUs = source.readReset(); if (resetPositionUs == C.UNSET_TIME_US) { resetPositionUs = childResetPositionUs; @@ -232,7 +223,7 @@ public final class DashSampleSource implements SampleSource { @Override public long getBufferedPositionUs() { long bufferedPositionUs = durationUs != C.UNSET_TIME_US ? durationUs : Long.MAX_VALUE; - for (SampleSource source : enabledSources) { + for (ChunkSampleSource source : enabledSources) { long rendererBufferedPositionUs = source.getBufferedPositionUs(); if (rendererBufferedPositionUs == C.UNSET_TIME_US) { return C.UNSET_TIME_US; @@ -247,7 +238,7 @@ public final class DashSampleSource implements SampleSource { @Override public void seekToUs(long positionUs) { - for (SampleSource source : enabledSources) { + for (ChunkSampleSource source : enabledSources) { source.seekToUs(positionUs); } } @@ -255,14 +246,14 @@ public final class DashSampleSource implements SampleSource { @Override public void release() { manifestFetcher.release(); - for (SampleSource source : sources) { + for (ChunkSampleSource source : sources) { source.release(); } } // Internal methods. - private int selectTracks(SampleSource source, List allOldStreams, + private int selectTracks(ChunkSampleSource source, List allOldStreams, List allNewSelections, long positionUs, TrackStream[] allNewStreams) { // Get the subset of the old streams for the source. ArrayList oldStreams = new ArrayList<>(); @@ -278,7 +269,7 @@ public final class DashSampleSource implements SampleSource { int[] newSelectionOriginalIndices = new int[allNewSelections.size()]; for (int i = 0; i < allNewSelections.size(); i++) { TrackSelection selection = allNewSelections.get(i); - Pair sourceAndGroup = getSourceAndGroup(selection.group); + Pair sourceAndGroup = getSourceAndGroup(selection.group); if (sourceAndGroup.first == source) { newSelectionOriginalIndices[newSelections.size()] = i; newSelections.add(new TrackSelection(sourceAndGroup.second, selection.getTracks())); @@ -297,9 +288,9 @@ public final class DashSampleSource implements SampleSource { return newSelections.size() - oldStreams.size(); } - private Pair getSourceAndGroup(int group) { + private Pair getSourceAndGroup(int group) { int totalTrackGroupCount = 0; - for (SampleSource source : sources) { + for (ChunkSampleSource source : sources) { int sourceTrackGroupCount = source.getTrackGroups().length; if (group < totalTrackGroupCount + sourceTrackGroupCount) { return Pair.create(source, group - totalTrackGroupCount); diff --git a/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingChunkSource.java b/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingChunkSource.java index a3adf3a0df..cbfb481049 100644 --- a/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingChunkSource.java +++ b/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingChunkSource.java @@ -60,7 +60,6 @@ public class SmoothStreamingChunkSource implements ChunkSource { private final Evaluation evaluation; private final FormatEvaluator adaptiveFormatEvaluator; - private long durationUs; private TrackEncryptionBox[] trackEncryptionBoxes; private DrmInitData.Mapped drmInitData; private SmoothStreamingManifest currentManifest; @@ -107,7 +106,6 @@ public class SmoothStreamingChunkSource implements ChunkSource { public void init(SmoothStreamingManifest initialManifest) { currentManifest = initialManifest; - durationUs = currentManifest.durationUs; ProtectionElement protectionElement = currentManifest.protectionElement; if (protectionElement != null) { byte[] keyId = getProtectionElementKeyId(protectionElement.data); @@ -123,11 +121,6 @@ public class SmoothStreamingChunkSource implements ChunkSource { initForManifest(currentManifest); } - @Override - public long getDurationUs() { - return durationUs; - } - @Override public final TrackGroup getTracks() { return trackGroup; @@ -274,8 +267,9 @@ public class SmoothStreamingChunkSource implements ChunkSource { extractorWrappers = new ChunkExtractorWrapper[formats.length]; for (int j = 0; j < formats.length; j++) { int nalUnitLengthFieldLength = streamElementType == C.TRACK_TYPE_VIDEO ? 4 : -1; - Track track = new Track(j, streamElementType, timescale, C.UNSET_TIME_US, durationUs, - formats[j], trackEncryptionBoxes, nalUnitLengthFieldLength, null, null); + Track track = new Track(j, streamElementType, timescale, C.UNSET_TIME_US, + manifest.durationUs, formats[j], trackEncryptionBoxes, nalUnitLengthFieldLength, + null, null); FragmentedMp4Extractor extractor = new FragmentedMp4Extractor( FragmentedMp4Extractor.FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME | FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_TFDT_BOX, track); diff --git a/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingSampleSource.java b/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingSampleSource.java index bb0cc8a2ea..48f855ead5 100644 --- a/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingSampleSource.java @@ -53,8 +53,8 @@ public final class SmoothStreamingSampleSource implements SampleSource { private final ManifestFetcher manifestFetcher; private final SmoothStreamingChunkSource[] chunkSources; - private final SampleSource[] sources; - private final IdentityHashMap trackStreamSources; + private final ChunkSampleSource[] sources; + private final IdentityHashMap trackStreamSources; private final int[] selectedTrackCounts; private SmoothStreamingManifest currentManifest; @@ -62,7 +62,7 @@ public final class SmoothStreamingSampleSource implements SampleSource { private boolean seenFirstTrackSelection; private long durationUs; private TrackGroupArray trackGroups; - private SampleSource[] enabledSources; + private ChunkSampleSource[] enabledSources; public SmoothStreamingSampleSource(Uri uri, DataSourceFactory dataSourceFactory, BandwidthMeter bandwidthMeter, Handler eventHandler, @@ -99,7 +99,7 @@ public final class SmoothStreamingSampleSource implements SampleSource { chunkSources = new SmoothStreamingChunkSource[] {videoChunkSource, audioChunkSource, textChunkSource}; - sources = new SampleSource[] {videoSampleSource, audioSampleSource, textSampleSource}; + sources = new ChunkSampleSource[] {videoSampleSource, audioSampleSource, textSampleSource}; trackStreamSources = new IdentityHashMap<>(); selectedTrackCounts = new int[sources.length]; } @@ -117,32 +117,23 @@ public final class SmoothStreamingSampleSource implements SampleSource { manifestFetcher.requestRefresh(); return false; } else { + durationUs = currentManifest.durationUs; for (SmoothStreamingChunkSource chunkSource : chunkSources) { chunkSource.init(currentManifest); } } } - boolean sourcesPrepared = true; - for (SampleSource source : sources) { - sourcesPrepared &= source.prepare(positionUs); + for (ChunkSampleSource source : sources) { + source.prepare(); } - if (!sourcesPrepared) { - return false; - } - durationUs = 0; int totalTrackGroupCount = 0; - for (SampleSource source : sources) { + for (ChunkSampleSource source : sources) { totalTrackGroupCount += source.getTrackGroups().length; - if (durationUs != C.UNSET_TIME_US) { - long sourceDurationUs = source.getDurationUs(); - durationUs = sourceDurationUs == C.UNSET_TIME_US - ? C.UNSET_TIME_US : Math.max(durationUs, sourceDurationUs); - } } TrackGroup[] trackGroupArray = new TrackGroup[totalTrackGroupCount]; int trackGroupIndex = 0; - for (SampleSource source : sources) { + for (ChunkSampleSource source : sources) { int sourceTrackGroupCount = source.getTrackGroups().length; for (int j = 0; j < sourceTrackGroupCount; j++) { trackGroupArray[trackGroupIndex++] = source.getTrackGroups().get(j); @@ -178,7 +169,7 @@ public final class SmoothStreamingSampleSource implements SampleSource { } } // Update the enabled sources. - enabledSources = new SampleSource[enabledSourceCount]; + enabledSources = new ChunkSampleSource[enabledSourceCount]; enabledSourceCount = 0; for (int i = 0; i < sources.length; i++) { if (selectedTrackCounts[i] > 0) { @@ -211,7 +202,7 @@ public final class SmoothStreamingSampleSource implements SampleSource { } } - for (SampleSource source : enabledSources) { + for (ChunkSampleSource source : enabledSources) { source.continueBuffering(positionUs); } } @@ -219,7 +210,7 @@ public final class SmoothStreamingSampleSource implements SampleSource { @Override public long readReset() { long resetPositionUs = C.UNSET_TIME_US; - for (SampleSource source : enabledSources) { + for (ChunkSampleSource source : enabledSources) { long childResetPositionUs = source.readReset(); if (resetPositionUs == C.UNSET_TIME_US) { resetPositionUs = childResetPositionUs; @@ -233,7 +224,7 @@ public final class SmoothStreamingSampleSource implements SampleSource { @Override public long getBufferedPositionUs() { long bufferedPositionUs = durationUs != C.UNSET_TIME_US ? durationUs : Long.MAX_VALUE; - for (SampleSource source : enabledSources) { + for (ChunkSampleSource source : enabledSources) { long rendererBufferedPositionUs = source.getBufferedPositionUs(); if (rendererBufferedPositionUs == C.UNSET_TIME_US) { return C.UNSET_TIME_US; @@ -248,7 +239,7 @@ public final class SmoothStreamingSampleSource implements SampleSource { @Override public void seekToUs(long positionUs) { - for (SampleSource source : enabledSources) { + for (ChunkSampleSource source : enabledSources) { source.seekToUs(positionUs); } } @@ -256,14 +247,14 @@ public final class SmoothStreamingSampleSource implements SampleSource { @Override public void release() { manifestFetcher.release(); - for (SampleSource source : sources) { + for (ChunkSampleSource source : sources) { source.release(); } } // Internal methods. - private int selectTracks(SampleSource source, List allOldStreams, + private int selectTracks(ChunkSampleSource source, List allOldStreams, List allNewSelections, long positionUs, TrackStream[] allNewStreams) { // Get the subset of the old streams for the source. ArrayList oldStreams = new ArrayList<>(); @@ -279,7 +270,7 @@ public final class SmoothStreamingSampleSource implements SampleSource { int[] newSelectionOriginalIndices = new int[allNewSelections.size()]; for (int i = 0; i < allNewSelections.size(); i++) { TrackSelection selection = allNewSelections.get(i); - Pair sourceAndGroup = getSourceAndGroup(selection.group); + Pair sourceAndGroup = getSourceAndGroup(selection.group); if (sourceAndGroup.first == source) { newSelectionOriginalIndices[newSelections.size()] = i; newSelections.add(new TrackSelection(sourceAndGroup.second, selection.getTracks())); @@ -298,9 +289,9 @@ public final class SmoothStreamingSampleSource implements SampleSource { return newSelections.size() - oldStreams.size(); } - private Pair getSourceAndGroup(int group) { + private Pair getSourceAndGroup(int group) { int totalTrackGroupCount = 0; - for (SampleSource source : sources) { + for (ChunkSampleSource source : sources) { int sourceTrackGroupCount = source.getTrackGroups().length; if (group < totalTrackGroupCount + sourceTrackGroupCount) { return Pair.create(source, group - totalTrackGroupCount);