diff --git a/RELEASENOTES.md b/RELEASENOTES.md index fa6c42ca88..a468e72a7a 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,24 +1,34 @@ # Release notes # +### r2.1.1 ### + +Bugfix release only. Users of r2.1.0 and r2.0.x should proactively update to +this version. + +* Fix some subtitle types (e.g. WebVTT) being displayed out of sync + ([#2208](https://github.com/google/ExoPlayer/issues/2208)). +* Fix incorrect position reporting for on-demand HLS media that includes + EXT-X-PROGRAM-DATE-TIME tags + ([#2224](https://github.com/google/ExoPlayer/issues/2224)). +* Fix issue where playbacks could get stuck in the initial buffering state if + over 1MB of data needs to be read to initialize the playback. + ### r2.1.0 ### -This release contains important bug fixes. Users of r2.0.x should proactively -update to this version. - * HLS: Support for seeking in live streams - ([87](https://github.com/google/ExoPlayer/issues/87)). + ([#87](https://github.com/google/ExoPlayer/issues/87)). * HLS: Improved support: * Support for EXT-X-PROGRAM-DATE-TIME - ([747](https://github.com/google/ExoPlayer/issues/747)). + ([#747](https://github.com/google/ExoPlayer/issues/747)). * Improved handling of sample timestamps and their alignment across variants and renditions. * Fix issue that could cause playbacks to get stuck in an endless initial buffering state. * Correctly propagate BehindLiveWindowException instead of IndexOutOfBoundsException exception - ([1695](https://github.com/google/ExoPlayer/issues/1695)). + ([#1695](https://github.com/google/ExoPlayer/issues/1695)). * MP3/MP4: Support for ID3 metadata, including embedded album art - ([979](https://github.com/google/ExoPlayer/issues/979)). + ([#979](https://github.com/google/ExoPlayer/issues/979)). * Improved customization of UI components. You can read about customization of ExoPlayer's UI components [here](https://medium.com/google-exoplayer/customizing-exoplayers-ui-components-728cf55ee07a#.9ewjg7avi). @@ -31,30 +41,30 @@ update to this version. * Support SCTE-35 splice information messages. * Support multiple table sections in a single PSI section. * Fix NullPointerException when an unsupported stream type is encountered - ([2149](https://github.com/google/ExoPlayer/issues/2149)). + ([#2149](https://github.com/google/ExoPlayer/issues/2149)). * Avoid failure when expected ID3 header not found - ([1966](https://github.com/google/ExoPlayer/issues/1966)). + ([#1966](https://github.com/google/ExoPlayer/issues/1966)). * Improvements to the upstream cache package. * Support caching of media segments for DASH, HLS and SmoothStreaming. Note that caching of manifest and playlist files is still not supported in the (normal) case where the corresponding responses are compressed. * Support caching for ExtractorMediaSource based playbacks. * Improved flexibility of SimpleExoPlayer - ([2102](https://github.com/google/ExoPlayer/issues/2102)). + ([#2102](https://github.com/google/ExoPlayer/issues/2102)). * Fix issue where only the audio of a video would play due to capability - detection issues ([2007](https://github.com/google/ExoPlayer/issues/2007)) - ([2034](https://github.com/google/ExoPlayer/issues/2034)) - ([2157](https://github.com/google/ExoPlayer/issues/2157)). + detection issues ([#2007](https://github.com/google/ExoPlayer/issues/2007)) + ([#2034](https://github.com/google/ExoPlayer/issues/2034)) + ([#2157](https://github.com/google/ExoPlayer/issues/2157)). * Fix issues that could cause ExtractorMediaSource based playbacks to get stuck - buffering ([1962](https://github.com/google/ExoPlayer/issues/1962)). + buffering ([#1962](https://github.com/google/ExoPlayer/issues/1962)). * Correctly set SimpleExoPlayerView surface aspect ratio when an active player - is attached ([2077](https://github.com/google/ExoPlayer/issues/1976)). + is attached ([#2077](https://github.com/google/ExoPlayer/issues/1976)). * OGG: Fix playback of short OGG files - ([1976](https://github.com/google/ExoPlayer/issues/1976)). + ([#1976](https://github.com/google/ExoPlayer/issues/1976)). * MP4: Support `.mp3` tracks - ([2066](https://github.com/google/ExoPlayer/issues/2066)). + ([#2066](https://github.com/google/ExoPlayer/issues/2066)). * SubRip: Don't fail playbacks if SubRip file contains negative timestamps - ([2145](https://github.com/google/ExoPlayer/issues/2145)). + ([#2145](https://github.com/google/ExoPlayer/issues/2145)). * Misc bugfixes. ### r2.0.4 ### @@ -185,11 +195,11 @@ V2 release. * Improvements to the upstream cache package. * MP4: Support `.mp3` tracks - ([2066](https://github.com/google/ExoPlayer/issues/2066)). + ([#2066](https://github.com/google/ExoPlayer/issues/2066)). * SubRip: Don't fail playbacks if SubRip file contains negative timestamps - ([2145](https://github.com/google/ExoPlayer/issues/2145)). + ([#2145](https://github.com/google/ExoPlayer/issues/2145)). * MPEG-TS: Avoid failure when expected ID3 header not found - ([1966](https://github.com/google/ExoPlayer/issues/1966)). + ([#1966](https://github.com/google/ExoPlayer/issues/1966)). * Misc bugfixes. ### r1.5.12 ### diff --git a/build.gradle b/build.gradle index 0ea3ad66f3..358b8f1404 100644 --- a/build.gradle +++ b/build.gradle @@ -35,7 +35,7 @@ allprojects { releaseRepoName = 'exoplayer' releaseUserOrg = 'google' releaseGroupId = 'com.google.android.exoplayer' - releaseVersion = 'r2.1.0' + releaseVersion = 'r2.1.1' releaseWebsite = 'https://github.com/google/ExoPlayer' } } diff --git a/demo/src/main/AndroidManifest.xml b/demo/src/main/AndroidManifest.xml index d1b44abafe..4c6d832211 100644 --- a/demo/src/main/AndroidManifest.xml +++ b/demo/src/main/AndroidManifest.xml @@ -16,8 +16,8 @@ + android:versionCode="2101" + android:versionName="2.1.1"> diff --git a/library/src/main/java/com/google/android/exoplayer2/BaseRenderer.java b/library/src/main/java/com/google/android/exoplayer2/BaseRenderer.java index 447e39bf52..514bbca8f4 100644 --- a/library/src/main/java/com/google/android/exoplayer2/BaseRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer2/BaseRenderer.java @@ -267,6 +267,12 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities { return streamIsFinal ? C.RESULT_BUFFER_READ : C.RESULT_NOTHING_READ; } buffer.timeUs += streamOffsetUs; + } else if (result == C.RESULT_FORMAT_READ) { + Format format = formatHolder.format; + if (format.subsampleOffsetUs != Format.OFFSET_SAMPLE_RELATIVE) { + format = format.copyWithSubsampleOffsetUs(format.subsampleOffsetUs + streamOffsetUs); + formatHolder.format = format; + } } return result; } diff --git a/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java b/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java index 66be6b7478..8866bb7c48 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java +++ b/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java @@ -676,6 +676,7 @@ import java.io.IOException; standaloneMediaClock.stop(); rendererMediaClock = null; rendererMediaClockSource = null; + rendererPositionUs = RENDERER_TIMESTAMP_OFFSET_US; for (Renderer renderer : enabledRenderers) { try { ensureStopped(renderer); @@ -823,9 +824,6 @@ import java.io.IOException; } private boolean haveSufficientBuffer(boolean rebuffering) { - if (loadingPeriodHolder == null) { - return false; - } long loadingPeriodBufferedPositionUs = !loadingPeriodHolder.prepared ? loadingPeriodHolder.startPositionUs : loadingPeriodHolder.mediaPeriod.getBufferedPositionUs(); @@ -1287,7 +1285,8 @@ import java.io.IOException; } private void maybeContinueLoading() { - long nextLoadPositionUs = loadingPeriodHolder.mediaPeriod.getNextLoadPositionUs(); + long nextLoadPositionUs = !loadingPeriodHolder.prepared ? 0 + : loadingPeriodHolder.mediaPeriod.getNextLoadPositionUs(); if (nextLoadPositionUs == C.TIME_END_OF_SOURCE) { setIsLoading(false); } else { diff --git a/library/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java b/library/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java index 45f63d713d..ea522ac4c8 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java +++ b/library/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java @@ -23,7 +23,7 @@ public interface ExoPlayerLibraryInfo { /** * The version of the library, expressed as a string. */ - String VERSION = "2.1.0"; + String VERSION = "2.1.1"; /** * The version of the library, expressed as an integer. @@ -32,7 +32,7 @@ public interface ExoPlayerLibraryInfo { * corresponding integer version 1002003 (001-002-003), and "123.45.6" has the corresponding * integer version 123045006 (123-045-006). */ - int VERSION_INT = 2001000; + int VERSION_INT = 2001001; /** * Whether the library was compiled with {@link com.google.android.exoplayer2.util.Assertions} diff --git a/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java b/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java index 0b7190d382..8ab4d45c47 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java @@ -244,7 +244,7 @@ import java.io.IOException; @Override public long getNextLoadPositionUs() { - return getBufferedPositionUs(); + return enabledTrackCount == 0 ? C.TIME_END_OF_SOURCE : getBufferedPositionUs(); } @Override diff --git a/library/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java b/library/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java index a3c1c88df4..f4a9665b10 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java @@ -133,4 +133,32 @@ public interface MediaPeriod extends SequenceableLoader { */ long seekToUs(long positionUs); + // SequenceableLoader interface. Overridden to provide more specific documentation. + + /** + * Returns the next load time, or {@link C#TIME_END_OF_SOURCE} if loading has finished. + *

+ * This method should only be called after the period has been prepared. It may be called when no + * tracks are selected. + */ + @Override + long getNextLoadPositionUs(); + + /** + * Attempts to continue loading. + *

+ * This method may be called both during and after the period has been prepared. + *

+ * A period may call {@link Callback#onContinueLoadingRequested(SequenceableLoader)} on the + * {@link Callback} passed to {@link #prepare(Callback)} to request that this method be called + * when the period is permitted to continue loading data. A period may do this both during and + * after preparation. + * + * @param positionUs The current playback position. + * @return True if progress was made, meaning that {@link #getNextLoadPositionUs()} will return + * a different value than prior to the call. False otherwise. + */ + @Override + boolean continueLoading(long positionUs); + } diff --git a/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java index 2f46fc694c..869efa6cdc 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java @@ -104,15 +104,14 @@ public final class HlsMediaSource implements MediaSource, SinglePeriodTimeline timeline; if (playlistTracker.isLive()) { // TODO: fix windowPositionInPeriodUs when playlist is empty. - long windowPositionInPeriodUs = playlist.startTimeUs; List segments = playlist.segments; long windowDefaultStartPositionUs = segments.isEmpty() ? 0 : segments.get(Math.max(0, segments.size() - 3)).relativeStartTimeUs; timeline = new SinglePeriodTimeline(C.TIME_UNSET, playlist.durationUs, - windowPositionInPeriodUs, windowDefaultStartPositionUs, true, !playlist.hasEndTag); + playlist.startTimeUs, windowDefaultStartPositionUs, true, !playlist.hasEndTag); } else /* not live */ { - timeline = new SinglePeriodTimeline(playlist.durationUs, playlist.durationUs, 0, 0, true, - false); + timeline = new SinglePeriodTimeline(playlist.startTimeUs + playlist.durationUs, + playlist.durationUs, playlist.startTimeUs, 0, true, false); } sourceListener.onSourceInfoRefreshed(timeline, playlist); }