diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 05ff1b9535..9660bd4714 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -65,11 +65,12 @@ Matroska or MP4. * Javadocs: Add favicon for easier identification in browser tabs * FMP4: Add support for encrypted AC-4 tracks. -* Reduce startup latency for DASH and SmoothStreaming adaptive playbacks. - In previous versions, codec initialization would only occur after the network - connection for requesting the first media segment had been established. Codec - initialization can now occur before this network connection being established, - reducing startup latency. +* Startup latency optimizations: + * Reduce startup latency for DASH and SmoothStreaming playbacks by allowing + codec initialization to occur before the network connection for the first + media segment has been established. + * Reduce startup latency for on-demand DASH playbacks by allowing codec + initialization to occur before the sidx box has been loaded. ### 2.11.1 (2019-12-20) ### diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunkOutput.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunkOutput.java index 0bcc46fcbf..a23e506d08 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunkOutput.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunkOutput.java @@ -21,7 +21,10 @@ import com.google.android.exoplayer2.source.SampleQueue; import com.google.android.exoplayer2.source.chunk.ChunkExtractorWrapper.TrackOutputProvider; import com.google.android.exoplayer2.util.Log; -/** An output for {@link BaseMediaChunk}s. */ +/** + * A {@link TrackOutputProvider} that provides {@link TrackOutput TrackOutputs} based on a + * predefined mapping from track type to output. + */ public final class BaseMediaChunkOutput implements TrackOutputProvider { private static final String TAG = "BaseMediaChunkOutput"; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java index 32160904c6..5b71b01d49 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java @@ -74,7 +74,7 @@ public class ChunkSampleStream implements SampleStream, S private final List readOnlyMediaChunks; private final SampleQueue primarySampleQueue; private final SampleQueue[] embeddedSampleQueues; - private final BaseMediaChunkOutput mediaChunkOutput; + private final BaseMediaChunkOutput chunkOutput; private Format primaryDownstreamTrackFormat; @Nullable private ReleaseCallback releaseCallback; @@ -142,7 +142,7 @@ public class ChunkSampleStream implements SampleStream, S trackTypes[i + 1] = embeddedTrackTypes[i]; } - mediaChunkOutput = new BaseMediaChunkOutput(trackTypes, sampleQueues); + chunkOutput = new BaseMediaChunkOutput(trackTypes, sampleQueues); pendingResetPositionUs = positionUs; lastSeekPositionUs = positionUs; } @@ -554,8 +554,10 @@ public class ChunkSampleStream implements SampleStream, S decodeOnlyUntilPositionUs = resetToMediaChunk ? 0 : pendingResetPositionUs; pendingResetPositionUs = C.TIME_UNSET; } - mediaChunk.init(mediaChunkOutput); + mediaChunk.init(chunkOutput); mediaChunks.add(mediaChunk); + } else if (loadable instanceof InitializationChunk) { + ((InitializationChunk) loadable).init(chunkOutput); } long elapsedRealtimeMs = loader.startLoading( diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ContainerMediaChunk.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ContainerMediaChunk.java index 5003208f7b..9dffe09194 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ContainerMediaChunk.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ContainerMediaChunk.java @@ -21,6 +21,7 @@ import com.google.android.exoplayer2.extractor.DefaultExtractorInput; import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.ExtractorInput; import com.google.android.exoplayer2.extractor.PositionHolder; +import com.google.android.exoplayer2.source.chunk.ChunkExtractorWrapper.TrackOutputProvider; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.util.Assertions; @@ -144,16 +145,13 @@ public class ContainerMediaChunk extends BaseMediaChunk { } /** - * Returns the {@link ChunkExtractorWrapper.TrackOutputProvider} to be used by the wrapped - * extractor. + * Returns the {@link TrackOutputProvider} to be used by the wrapped extractor. * * @param baseMediaChunkOutput The {@link BaseMediaChunkOutput} most recently passed to {@link * #init(BaseMediaChunkOutput)}. - * @return A {@link ChunkExtractorWrapper.TrackOutputProvider} to be used by the wrapped - * extractor. + * @return A {@link TrackOutputProvider} to be used by the wrapped extractor. */ - protected ChunkExtractorWrapper.TrackOutputProvider getTrackOutputProvider( - BaseMediaChunkOutput baseMediaChunkOutput) { + protected TrackOutputProvider getTrackOutputProvider(BaseMediaChunkOutput baseMediaChunkOutput) { return baseMediaChunkOutput; } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/InitializationChunk.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/InitializationChunk.java index 892a4f1e32..178fb94c7c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/InitializationChunk.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/InitializationChunk.java @@ -22,11 +22,13 @@ import com.google.android.exoplayer2.extractor.DefaultExtractorInput; import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.ExtractorInput; import com.google.android.exoplayer2.extractor.PositionHolder; +import com.google.android.exoplayer2.source.chunk.ChunkExtractorWrapper.TrackOutputProvider; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Util; import java.io.IOException; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** * A {@link Chunk} that uses an {@link Extractor} to decode initialization data for single track. @@ -37,6 +39,7 @@ public final class InitializationChunk extends Chunk { private final ChunkExtractorWrapper extractorWrapper; + @MonotonicNonNull private TrackOutputProvider trackOutputProvider; private long nextLoadPosition; private volatile boolean loadCanceled; @@ -60,6 +63,17 @@ public final class InitializationChunk extends Chunk { this.extractorWrapper = extractorWrapper; } + /** + * Initializes the chunk for loading, setting a {@link TrackOutputProvider} for track outputs to + * which formats will be written as they are loaded. + * + * @param trackOutputProvider The {@link TrackOutputProvider} for track outputs to which formats + * will be written as they are loaded. + */ + public void init(TrackOutputProvider trackOutputProvider) { + this.trackOutputProvider = trackOutputProvider; + } + // Loadable implementation. @Override @@ -72,9 +86,7 @@ public final class InitializationChunk extends Chunk { public void load() throws IOException, InterruptedException { if (nextLoadPosition == 0) { extractorWrapper.init( - /* trackOutputProvider= */ null, - /* startTimeUs= */ C.TIME_UNSET, - /* endTimeUs= */ C.TIME_UNSET); + trackOutputProvider, /* startTimeUs= */ C.TIME_UNSET, /* endTimeUs= */ C.TIME_UNSET); } try { // Create and open the input.