diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 8ddbe4068c..feaa240220 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,20 +1,10 @@ # 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)). * HLS: Improved support: diff --git a/build.gradle b/build.gradle index 358b8f1404..0ea3ad66f3 100644 --- a/build.gradle +++ b/build.gradle @@ -35,7 +35,7 @@ allprojects { releaseRepoName = 'exoplayer' releaseUserOrg = 'google' releaseGroupId = 'com.google.android.exoplayer' - releaseVersion = 'r2.1.1' + releaseVersion = 'r2.1.0' releaseWebsite = 'https://github.com/google/ExoPlayer' } } diff --git a/demo/src/main/AndroidManifest.xml b/demo/src/main/AndroidManifest.xml index 4c6d832211..d1b44abafe 100644 --- a/demo/src/main/AndroidManifest.xml +++ b/demo/src/main/AndroidManifest.xml @@ -16,8 +16,8 @@ + android:versionCode="2100" + android:versionName="2.1.0"> diff --git a/demo/src/main/assets/media.exolist.json b/demo/src/main/assets/media.exolist.json index 5a3015d506..6fa46d7451 100644 --- a/demo/src/main/assets/media.exolist.json +++ b/demo/src/main/assets/media.exolist.json @@ -183,53 +183,29 @@ "uri": "https://storage.googleapis.com/wvmedia/clear/vp9/tears/tears_uhd.mpd" }, { - "name": "WV: Secure Fullsample SD & HD (WebM,VP9)", + "name": "WV: Secure SD & HD (WebM,VP9)", "uri": "https://storage.googleapis.com/wvmedia/cenc/vp9/tears/tears.mpd", "drm_scheme": "widevine", "drm_license_url": "https://proxy.uat.widevine.com/proxy?provider=widevine_test" }, { - "name": "WV: Secure Fullsample SD (WebM,VP9)", + "name": "WV: Secure SD (WebM,VP9)", "uri": "https://storage.googleapis.com/wvmedia/cenc/vp9/tears/tears_sd.mpd", "drm_scheme": "widevine", "drm_license_url": "https://proxy.uat.widevine.com/proxy?provider=widevine_test" }, { - "name": "WV: Secure Fullsample HD (WebM,VP9)", + "name": "WV: Secure HD (WebM,VP9)", "uri": "https://storage.googleapis.com/wvmedia/cenc/vp9/tears/tears_hd.mpd", "drm_scheme": "widevine", "drm_license_url": "https://proxy.uat.widevine.com/proxy?provider=widevine_test" }, { - "name": "WV: Secure Fullsample UHD (WebM,VP9)", + "name": "WV: Secure UHD (WebM,VP9)", "uri": "https://storage.googleapis.com/wvmedia/cenc/vp9/tears/tears_uhd.mpd", "drm_scheme": "widevine", "drm_license_url": "https://proxy.uat.widevine.com/proxy?provider=widevine_test" }, - { - "name": "WV: Secure Subsample SD & HD (WebM,VP9)", - "uri": "https://storage.googleapis.com/wvmedia/cenc/vp9/subsample/24fps/tears/tears.mpd", - "drm_scheme": "widevine", - "drm_license_url": "https://proxy.uat.widevine.com/proxy?provider=widevine_test" - }, - { - "name": "WV: Secure Subsample SD (WebM,VP9)", - "uri": "https://storage.googleapis.com/wvmedia/cenc/vp9/subsample/24fps/tears/tears_sd.mpd", - "drm_scheme": "widevine", - "drm_license_url": "https://proxy.uat.widevine.com/proxy?provider=widevine_test" - }, - { - "name": "WV: Secure Subsample HD (WebM,VP9)", - "uri": "https://storage.googleapis.com/wvmedia/cenc/vp9/subsample/24fps/tears/tears_hd.mpd", - "drm_scheme": "widevine", - "drm_license_url": "https://proxy.uat.widevine.com/proxy?provider=widevine_test" - }, - { - "name": "WV: Secure Subsample UHD (WebM,VP9)", - "uri": "https://storage.googleapis.com/wvmedia/cenc/vp9/subsample/24fps/tears/tears_uhd.mpd", - "drm_scheme": "widevine", - "drm_license_url": "https://proxy.uat.widevine.com/proxy?provider=widevine_test" - }, { "name": "WV: Secure Subsample (WebM, VP9 with altref)", "uri": "https://storage.googleapis.com/widevine_test/vp9/sintel_1080p_vp9_altref_subsample/sintel_1080p_vp9_altref_subsample.mpd", diff --git a/library/src/androidTest/java/com/google/android/exoplayer2/ExoPlayerTest.java b/library/src/androidTest/java/com/google/android/exoplayer2/ExoPlayerTest.java index 0f6f3b07b1..be18d64195 100644 --- a/library/src/androidTest/java/com/google/android/exoplayer2/ExoPlayerTest.java +++ b/library/src/androidTest/java/com/google/android/exoplayer2/ExoPlayerTest.java @@ -31,7 +31,6 @@ import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.MimeTypes; import java.io.IOException; -import java.util.ArrayList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -49,25 +48,12 @@ public final class ExoPlayerTest extends TestCase { */ private static final int TIMEOUT_MS = 10000; - /** - * Tests playback of a source that exposes a single period. - */ public void testPlayToEnd() throws Exception { PlayerWrapper playerWrapper = new PlayerWrapper(); Format format = Format.createVideoSampleFormat(null, MimeTypes.VIDEO_H264, null, Format.NO_VALUE, Format.NO_VALUE, 1280, 720, Format.NO_VALUE, null, null); - playerWrapper.setup(new SinglePeriodTimeline(0, false), null, format); - playerWrapper.blockUntilEnded(TIMEOUT_MS); - } - - /** - * Tests playback of a source that exposes an empty timeline. Playback is expected to end without - * error. - */ - public void testPlayEmptyTimeline() throws Exception { - PlayerWrapper playerWrapper = new PlayerWrapper(); - playerWrapper.setup(Timeline.EMPTY, null, null); - playerWrapper.blockUntilEnded(TIMEOUT_MS); + playerWrapper.setup(new SinglePeriodTimeline(0, false), new Object(), format); + playerWrapper.blockUntilEndedOrError(TIMEOUT_MS); } /** @@ -84,6 +70,7 @@ public final class ExoPlayerTest extends TestCase { private Format expectedFormat; private ExoPlayer player; private Exception exception; + private boolean seenPositionDiscontinuity; public PlayerWrapper() { endedCountDownLatch = new CountDownLatch(1); @@ -94,11 +81,12 @@ public final class ExoPlayerTest extends TestCase { // Called on the test thread. - public void blockUntilEnded(long timeoutMs) throws Exception { + public void blockUntilEndedOrError(long timeoutMs) throws Exception { if (!endedCountDownLatch.await(timeoutMs, TimeUnit.MILLISECONDS)) { exception = new TimeoutException("Test playback timed out."); } release(); + // Throw any pending exception (from playback, timing out or releasing). if (exception != null) { throw exception; @@ -120,7 +108,7 @@ public final class ExoPlayerTest extends TestCase { player.setPlayWhenReady(true); player.prepare(new FakeMediaSource(timeline, manifest, format)); } catch (Exception e) { - handleError(e); + handlePlayerException(e); } } }); @@ -135,7 +123,7 @@ public final class ExoPlayerTest extends TestCase { player.release(); } } catch (Exception e) { - handleError(e); + handlePlayerException(e); } finally { playerThread.quit(); } @@ -144,7 +132,7 @@ public final class ExoPlayerTest extends TestCase { playerThread.join(); } - private void handleError(Exception exception) { + private void handlePlayerException(Exception exception) { if (this.exception == null) { this.exception = exception; } @@ -179,13 +167,20 @@ public final class ExoPlayerTest extends TestCase { @Override public void onPlayerError(ExoPlaybackException exception) { - handleError(exception); + this.exception = exception; + endedCountDownLatch.countDown(); } @Override public void onPositionDiscontinuity() { - // Should never happen. - handleError(new IllegalStateException("Received position discontinuity")); + assertFalse(seenPositionDiscontinuity); + assertEquals(0, player.getCurrentWindowIndex()); + assertEquals(0, player.getCurrentPeriodIndex()); + assertEquals(0, player.getCurrentPosition()); + assertEquals(0, player.getBufferedPosition()); + assertEquals(expectedTimeline, player.getCurrentTimeline()); + assertEquals(expectedManifest, player.getCurrentManifest()); + seenPositionDiscontinuity = true; } } @@ -199,16 +194,17 @@ public final class ExoPlayerTest extends TestCase { private final Timeline timeline; private final Object manifest; private final Format format; - private final ArrayList activeMediaPeriods; + private FakeMediaPeriod mediaPeriod; private boolean preparedSource; + private boolean releasedPeriod; private boolean releasedSource; public FakeMediaSource(Timeline timeline, Object manifest, Format format) { + Assertions.checkArgument(timeline.getPeriodCount() == 1); this.timeline = timeline; this.manifest = manifest; this.format = format; - activeMediaPeriods = new ArrayList<>(); } @Override @@ -225,29 +221,33 @@ public final class ExoPlayerTest extends TestCase { @Override public MediaPeriod createPeriod(int index, Allocator allocator, long positionUs) { - Assertions.checkIndex(index, 0, timeline.getPeriodCount()); assertTrue(preparedSource); + assertNull(mediaPeriod); + assertFalse(releasedPeriod); assertFalse(releasedSource); assertEquals(0, index); assertEquals(0, positionUs); - FakeMediaPeriod mediaPeriod = new FakeMediaPeriod(format); - activeMediaPeriods.add(mediaPeriod); + mediaPeriod = new FakeMediaPeriod(format); return mediaPeriod; } @Override public void releasePeriod(MediaPeriod mediaPeriod) { assertTrue(preparedSource); + assertNotNull(this.mediaPeriod); + assertFalse(releasedPeriod); assertFalse(releasedSource); - assertTrue(activeMediaPeriods.remove(mediaPeriod)); - ((FakeMediaPeriod) mediaPeriod).release(); + assertEquals(this.mediaPeriod, mediaPeriod); + this.mediaPeriod.release(); + releasedPeriod = true; } @Override public void releaseSource() { assertTrue(preparedSource); + assertNotNull(this.mediaPeriod); + assertTrue(releasedPeriod); assertFalse(releasedSource); - assertTrue(activeMediaPeriods.isEmpty()); releasedSource = true; } @@ -400,6 +400,7 @@ public final class ExoPlayerTest extends TestCase { public FakeVideoRenderer(Format expectedFormat) { super(C.TRACK_TYPE_VIDEO); + Assertions.checkArgument(MimeTypes.isVideo(expectedFormat.sampleMimeType)); this.expectedFormat = expectedFormat; } 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 514bbca8f4..447e39bf52 100644 --- a/library/src/main/java/com/google/android/exoplayer2/BaseRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer2/BaseRenderer.java @@ -267,12 +267,6 @@ 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/C.java b/library/src/main/java/com/google/android/exoplayer2/C.java index 5cef177517..3e6fac4a5e 100644 --- a/library/src/main/java/com/google/android/exoplayer2/C.java +++ b/library/src/main/java/com/google/android/exoplayer2/C.java @@ -96,13 +96,6 @@ public final class C { @SuppressWarnings("InlinedApi") public static final int CRYPTO_MODE_AES_CBC = MediaCodec.CRYPTO_MODE_AES_CBC; - /** - * Represents an unset {@link android.media.AudioTrack} session identifier. Equal to - * {@link AudioManager#AUDIO_SESSION_ID_GENERATE}. - */ - @SuppressWarnings("InlinedApi") - public static final int AUDIO_SESSION_ID_UNSET = AudioManager.AUDIO_SESSION_ID_GENERATE; - /** * Represents an audio encoding, or an invalid or unset value. */ diff --git a/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java b/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java index ab4e59e08f..a7cbeb524c 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java +++ b/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java @@ -332,10 +332,8 @@ import java.util.concurrent.CopyOnWriteArraySet; case ExoPlayerImplInternal.MSG_SEEK_ACK: { if (--pendingSeekAcks == 0) { playbackInfo = (ExoPlayerImplInternal.PlaybackInfo) msg.obj; - if (msg.arg1 != 0) { - for (EventListener listener : listeners) { - listener.onPositionDiscontinuity(); - } + for (EventListener listener : listeners) { + listener.onPositionDiscontinuity(); } } break; 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 afae56f1aa..66be6b7478 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java +++ b/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java @@ -559,7 +559,7 @@ import java.io.IOException; // The seek position was valid for the timeline that it was performed into, but the // timeline has changed and a suitable seek position could not be resolved in the new one. playbackInfo = new PlaybackInfo(0, 0); - eventHandler.obtainMessage(MSG_SEEK_ACK, 1, 0, playbackInfo).sendToTarget(); + eventHandler.obtainMessage(MSG_SEEK_ACK, playbackInfo).sendToTarget(); // Set the internal position to (0,TIME_UNSET) so that a subsequent seek to (0,0) isn't // ignored. playbackInfo = new PlaybackInfo(0, C.TIME_UNSET); @@ -569,7 +569,6 @@ import java.io.IOException; return; } - boolean seekPositionAdjusted = seekPosition.windowPositionUs == C.TIME_UNSET; int periodIndex = periodPosition.first; long periodPositionUs = periodPosition.second; @@ -579,13 +578,10 @@ import java.io.IOException; // Seek position equals the current position. Do nothing. return; } - long newPeriodPositionUs = seekToPeriodPosition(periodIndex, periodPositionUs); - seekPositionAdjusted |= periodPositionUs != newPeriodPositionUs; - periodPositionUs = newPeriodPositionUs; + periodPositionUs = seekToPeriodPosition(periodIndex, periodPositionUs); } finally { playbackInfo = new PlaybackInfo(periodIndex, periodPositionUs); - eventHandler.obtainMessage(MSG_SEEK_ACK, seekPositionAdjusted ? 1 : 0, 0, playbackInfo) - .sendToTarget(); + eventHandler.obtainMessage(MSG_SEEK_ACK, playbackInfo).sendToTarget(); } } @@ -680,7 +676,6 @@ import java.io.IOException; standaloneMediaClock.stop(); rendererMediaClock = null; rendererMediaClockSource = null; - rendererPositionUs = RENDERER_TIMESTAMP_OFFSET_US; for (Renderer renderer : enabledRenderers) { try { ensureStopped(renderer); @@ -828,6 +823,9 @@ import java.io.IOException; } private boolean haveSufficientBuffer(boolean rebuffering) { + if (loadingPeriodHolder == null) { + return false; + } long loadingPeriodBufferedPositionUs = !loadingPeriodHolder.prepared ? loadingPeriodHolder.startPositionUs : loadingPeriodHolder.mediaPeriod.getBufferedPositionUs(); @@ -1289,8 +1287,7 @@ import java.io.IOException; } private void maybeContinueLoading() { - long nextLoadPositionUs = !loadingPeriodHolder.prepared ? 0 - : loadingPeriodHolder.mediaPeriod.getNextLoadPositionUs(); + long nextLoadPositionUs = 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 ea522ac4c8..45f63d713d 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.1"; + String VERSION = "2.1.0"; /** * 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 = 2001001; + int VERSION_INT = 2001000; /** * Whether the library was compiled with {@link com.google.android.exoplayer2.util.Assertions} diff --git a/library/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java b/library/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java index 73df6a1e7a..36753309e2 100644 --- a/library/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java +++ b/library/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java @@ -29,6 +29,7 @@ import android.view.SurfaceView; import android.view.TextureView; import com.google.android.exoplayer2.audio.AudioCapabilities; import com.google.android.exoplayer2.audio.AudioRendererEventListener; +import com.google.android.exoplayer2.audio.AudioTrack; import com.google.android.exoplayer2.audio.MediaCodecAudioRenderer; import com.google.android.exoplayer2.decoder.DecoderCounters; import com.google.android.exoplayer2.drm.DrmSessionManager; @@ -177,7 +178,7 @@ public class SimpleExoPlayer implements ExoPlayer { // Set initial values. audioVolume = 1; - audioSessionId = C.AUDIO_SESSION_ID_UNSET; + audioSessionId = AudioTrack.SESSION_ID_NOT_SET; audioStreamType = C.STREAM_TYPE_DEFAULT; videoScalingMode = C.VIDEO_SCALING_MODE_DEFAULT; @@ -392,7 +393,7 @@ public class SimpleExoPlayer implements ExoPlayer { } /** - * Returns the audio session identifier, or {@link C#AUDIO_SESSION_ID_UNSET} if not set. + * Returns the audio session identifier, or {@code AudioTrack.SESSION_ID_NOT_SET} if not set. */ public int getAudioSessionId() { return audioSessionId; @@ -948,7 +949,7 @@ public class SimpleExoPlayer implements ExoPlayer { } audioFormat = null; audioDecoderCounters = null; - audioSessionId = C.AUDIO_SESSION_ID_UNSET; + audioSessionId = AudioTrack.SESSION_ID_NOT_SET; } // TextRenderer.Output implementation diff --git a/library/src/main/java/com/google/android/exoplayer2/audio/AudioTrack.java b/library/src/main/java/com/google/android/exoplayer2/audio/AudioTrack.java index 072180db94..8e6cf68dc8 100644 --- a/library/src/main/java/com/google/android/exoplayer2/audio/AudioTrack.java +++ b/library/src/main/java/com/google/android/exoplayer2/audio/AudioTrack.java @@ -17,7 +17,6 @@ package com.google.android.exoplayer2.audio; import android.annotation.SuppressLint; import android.annotation.TargetApi; -import android.media.AudioAttributes; import android.media.AudioFormat; import android.media.AudioTimestamp; import android.media.PlaybackParams; @@ -31,28 +30,26 @@ import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.Util; import java.lang.reflect.Method; import java.nio.ByteBuffer; -import java.nio.ByteOrder; /** * Plays audio data. The implementation delegates to an {@link android.media.AudioTrack} and handles * playback position smoothing, non-blocking writes and reconfiguration. *

* Before starting playback, specify the input format by calling - * {@link #configure(String, int, int, int, int)}. Next call {@link #initialize(int)} or - * {@link #initializeV21(int, boolean)}, optionally specifying an audio session and whether the - * track is to be used with tunneling video playback. + * {@link #configure(String, int, int, int, int)}. Next call {@link #initialize(int)}, optionally + * specifying an audio session. *

* Call {@link #handleBuffer(ByteBuffer, long)} to write data, and {@link #handleDiscontinuity()} * when the data being fed is discontinuous. Call {@link #play()} to start playing the written data. *

* Call {@link #configure(String, int, int, int, int)} whenever the input format changes. If * {@link #isInitialized()} returns {@code false} after the call, it is necessary to call - * {@link #initialize(int)} or {@link #initializeV21(int, boolean)} before writing more data. + * {@link #initialize(int)} before writing more data. *

* The underlying {@link android.media.AudioTrack} is created by {@link #initialize(int)} and * released by {@link #reset()} (and {@link #configure(String, int, int, int, int)} unless the input - * format is unchanged). It is safe to call {@link #initialize(int)} or - * {@link #initializeV21(int, boolean)} after calling {@link #reset()} without reconfiguration. + * format is unchanged). It is safe to call {@link #initialize(int)} after calling {@link #reset()} + * without reconfiguration. *

* Call {@link #release()} when the instance is no longer required. */ @@ -146,6 +143,11 @@ public final class AudioTrack { */ public static final int RESULT_BUFFER_CONSUMED = 2; + /** + * Represents an unset {@link android.media.AudioTrack} session identifier. + */ + public static final int SESSION_ID_NOT_SET = 0; + /** * Returned by {@link #getCurrentPositionUs} when the position is not set. */ @@ -271,10 +273,6 @@ public final class AudioTrack { private int bufferSize; private long bufferSizeUs; - private boolean useHwAvSync; - private ByteBuffer avSyncHeader; - private int bytesUntilNextAvSync; - private int nextPlayheadOffsetIndex; private int playheadOffsetCount; private long smoothedPlayheadOffsetUs; @@ -343,8 +341,8 @@ public final class AudioTrack { } /** - * Returns whether the audio track has been successfully initialized via {@link #initialize} or - * {@link #initializeV21(int, boolean)}, and has not yet been {@link #reset}. + * Returns whether the audio track has been successfully initialized via {@link #initialize} and + * not yet {@link #reset}. */ public boolean isInitialized() { return audioTrack != null; @@ -444,21 +442,6 @@ public final class AudioTrack { throw new IllegalArgumentException("Unsupported channel count: " + channelCount); } - // Workaround for overly strict channel configuration checks on nVidia Shield. - if (Util.SDK_INT <= 23 && "foster".equals(Util.DEVICE) && "NVIDIA".equals(Util.MANUFACTURER)) { - switch(channelCount) { - case 7: - channelConfig = C.CHANNEL_OUT_7POINT1_SURROUND; - break; - case 3: - case 5: - channelConfig = AudioFormat.CHANNEL_OUT_5POINT1; - break; - default: - break; - } - } - boolean passthrough = !MimeTypes.AUDIO_RAW.equals(mimeType); @C.Encoding int sourceEncoding; if (passthrough) { @@ -515,28 +498,11 @@ public final class AudioTrack { /** * Initializes the audio track for writing new buffers using {@link #handleBuffer}. * - * @param sessionId Audio track session identifier, or {@link C#AUDIO_SESSION_ID_UNSET} to create - * one. - * @return The audio track session identifier. + * @param sessionId Audio track session identifier to re-use, or {@link #SESSION_ID_NOT_SET} to + * create a new one. + * @return The new (or re-used) session identifier. */ public int initialize(int sessionId) throws InitializationException { - return initializeInternal(sessionId, false); - } - - /** - * Initializes the audio track for writing new buffers using {@link #handleBuffer}. - * - * @param sessionId Audio track session identifier, or {@link C#AUDIO_SESSION_ID_UNSET} to create - * one. - * @param tunneling Whether the audio track is to be used with tunneling video playback. - * @return The audio track session identifier. - */ - public int initializeV21(int sessionId, boolean tunneling) throws InitializationException { - Assertions.checkState(Util.SDK_INT >= 21); - return initializeInternal(sessionId, tunneling); - } - - private int initializeInternal(int sessionId, boolean tunneling) throws InitializationException { // If we're asynchronously releasing a previous audio track then we block until it has been // released. This guarantees that we cannot end up in a state where we have multiple audio // track instances. Without this guarantee it would be possible, in extreme cases, to exhaust @@ -544,11 +510,7 @@ public final class AudioTrack { // initialization of the audio track to fail. releasingConditionVariable.block(); - useHwAvSync = tunneling; - if (useHwAvSync) { - audioTrack = createHwAvSyncAudioTrackV21(sampleRate, channelConfig, targetEncoding, - bufferSize, sessionId); - } else if (sessionId == C.AUDIO_SESSION_ID_UNSET) { + if (sessionId == SESSION_ID_NOT_SET) { audioTrack = new android.media.AudioTrack(streamType, sampleRate, channelConfig, targetEncoding, bufferSize, MODE_STREAM); } else { @@ -730,9 +692,7 @@ public final class AudioTrack { buffer.position(buffer.position() + bytesWritten); } } else { - bytesWritten = useHwAvSync - ? writeNonBlockingWithAvSyncV21(audioTrack, buffer, bytesRemaining, presentationTimeUs) - : writeNonBlockingV21(audioTrack, buffer, bytesRemaining); + bytesWritten = writeNonBlockingV21(audioTrack, buffer, bytesRemaining); } if (bytesWritten < 0) { @@ -758,7 +718,6 @@ public final class AudioTrack { public void handleEndOfStream() { if (isInitialized()) { audioTrackUtil.handleEndOfStream(getSubmittedFrames()); - bytesUntilNextAvSync = 0; } } @@ -784,27 +743,19 @@ public final class AudioTrack { } /** - * Sets the stream type for audio track. If the stream type has changed and if the audio track - * is not configured for use with video tunneling, then the audio track is reset and the caller - * must re-initialize the audio track before writing more data. The caller must not reuse the - * audio session identifier when re-initializing with a new stream type. - *

- * If the audio track is configured for use with video tunneling then the stream type is ignored - * and the audio track is not reset. The passed stream type will be used if the audio track is - * later re-configured into non-tunneled mode. + * Sets the stream type for audio track. If the stream type has changed, {@link #isInitialized()} + * will return {@code false} and the caller must re-{@link #initialize(int)} the audio track + * before writing more data. The caller must not reuse the audio session identifier when + * re-initializing with a new stream type. * * @param streamType The {@link C.StreamType} to use for audio output. - * @return Whether the audio track was reset as a result of this call. + * @return Whether the stream type changed. */ public boolean setStreamType(@C.StreamType int streamType) { if (this.streamType == streamType) { return false; } this.streamType = streamType; - if (useHwAvSync) { - // The stream type is ignored in tunneling mode, so no need to reset. - return false; - } reset(); return true; } @@ -844,9 +795,9 @@ public final class AudioTrack { /** * Releases the underlying audio track asynchronously. *

- * Calling {@link #initialize(int)} or {@link #initializeV21(int, boolean)} will block until the - * audio track has been released, so it is safe to initialize immediately after a reset. The audio - * session may remain active until {@link #release()} is called. + * Calling {@link #initialize(int)} will block until the audio track has been released, so it is + * safe to initialize immediately after a reset. The audio session may remain active until + * {@link #release()} is called. */ public void reset() { if (isInitialized()) { @@ -854,7 +805,6 @@ public final class AudioTrack { submittedEncodedFrames = 0; framesPerEncodedSample = 0; currentSourceBuffer = null; - avSyncHeader = null; startMediaTimeState = START_NOT_SET; latencyUs = 0; resetSyncParams(); @@ -1070,26 +1020,6 @@ public final class AudioTrack { && audioTrack.getPlaybackHeadPosition() == 0; } - /** - * Instantiates an {@link android.media.AudioTrack} to be used with tunneling video playback. - */ - @TargetApi(21) - private static android.media.AudioTrack createHwAvSyncAudioTrackV21(int sampleRate, - int channelConfig, int encoding, int bufferSize, int sessionId) { - AudioAttributes attributesBuilder = new AudioAttributes.Builder() - .setUsage(AudioAttributes.USAGE_MEDIA) - .setContentType(AudioAttributes.CONTENT_TYPE_MOVIE) - .setFlags(AudioAttributes.FLAG_HW_AV_SYNC) - .build(); - AudioFormat format = new AudioFormat.Builder() - .setChannelMask(channelConfig) - .setEncoding(encoding) - .setSampleRate(sampleRate) - .build(); - return new android.media.AudioTrack(attributesBuilder, format, bufferSize, MODE_STREAM, - sessionId); - } - /** * Converts the provided buffer into 16-bit PCM. * @@ -1195,50 +1125,11 @@ public final class AudioTrack { } @TargetApi(21) - private static int writeNonBlockingV21(android.media.AudioTrack audioTrack, ByteBuffer buffer, - int size) { + private static int writeNonBlockingV21( + android.media.AudioTrack audioTrack, ByteBuffer buffer, int size) { return audioTrack.write(buffer, size, WRITE_NON_BLOCKING); } - @TargetApi(21) - private int writeNonBlockingWithAvSyncV21(android.media.AudioTrack audioTrack, - ByteBuffer buffer, int size, long presentationTimeUs) { - // TODO: Uncomment this when [Internal ref b/33627517] is clarified or fixed. - // if (Util.SDK_INT >= 23) { - // // The underlying platform AudioTrack writes AV sync headers directly. - // return audioTrack.write(buffer, size, WRITE_NON_BLOCKING, presentationTimeUs * 1000); - // } - if (avSyncHeader == null) { - avSyncHeader = ByteBuffer.allocate(16); - avSyncHeader.order(ByteOrder.BIG_ENDIAN); - avSyncHeader.putInt(0x55550001); - } - if (bytesUntilNextAvSync == 0) { - avSyncHeader.putInt(4, size); - avSyncHeader.putLong(8, presentationTimeUs * 1000); - avSyncHeader.position(0); - bytesUntilNextAvSync = size; - } - int avSyncHeaderBytesRemaining = avSyncHeader.remaining(); - if (avSyncHeaderBytesRemaining > 0) { - int result = audioTrack.write(avSyncHeader, avSyncHeaderBytesRemaining, WRITE_NON_BLOCKING); - if (result < 0) { - bytesUntilNextAvSync = 0; - return result; - } - if (result < avSyncHeaderBytesRemaining) { - return 0; - } - } - int result = writeNonBlockingV21(audioTrack, buffer, size); - if (result < 0) { - bytesUntilNextAvSync = 0; - return result; - } - bytesUntilNextAvSync -= result; - return result; - } - @TargetApi(21) private static void setAudioTrackVolumeV21(android.media.AudioTrack audioTrack, float volume) { audioTrack.setVolume(volume); diff --git a/library/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java b/library/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java index d3cde10afb..648bfd5762 100644 --- a/library/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java @@ -129,7 +129,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media boolean playClearSamplesWithoutKeys, Handler eventHandler, AudioRendererEventListener eventListener, AudioCapabilities audioCapabilities) { super(C.TRACK_TYPE_AUDIO, mediaCodecSelector, drmSessionManager, playClearSamplesWithoutKeys); - audioSessionId = C.AUDIO_SESSION_ID_UNSET; + audioSessionId = AudioTrack.SESSION_ID_NOT_SET; audioTrack = new AudioTrack(audioCapabilities, this); eventDispatcher = new EventDispatcher(eventHandler, eventListener); } @@ -274,7 +274,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media @Override protected void onDisabled() { - audioSessionId = C.AUDIO_SESSION_ID_UNSET; + audioSessionId = AudioTrack.SESSION_ID_NOT_SET; try { audioTrack.release(); } finally { @@ -328,8 +328,8 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media if (!audioTrack.isInitialized()) { // Initialize the AudioTrack now. try { - if (audioSessionId == C.AUDIO_SESSION_ID_UNSET) { - audioSessionId = audioTrack.initialize(C.AUDIO_SESSION_ID_UNSET); + if (audioSessionId == AudioTrack.SESSION_ID_NOT_SET) { + audioSessionId = audioTrack.initialize(AudioTrack.SESSION_ID_NOT_SET); eventDispatcher.audioSessionId(audioSessionId); onAudioSessionId(audioSessionId); } else { @@ -387,7 +387,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media case C.MSG_SET_STREAM_TYPE: @C.StreamType int streamType = (Integer) message; if (audioTrack.setStreamType(streamType)) { - audioSessionId = C.AUDIO_SESSION_ID_UNSET; + audioSessionId = AudioTrack.SESSION_ID_NOT_SET; } break; default: diff --git a/library/src/main/java/com/google/android/exoplayer2/audio/SimpleDecoderAudioRenderer.java b/library/src/main/java/com/google/android/exoplayer2/audio/SimpleDecoderAudioRenderer.java index 5c9acc7739..572f7b54c1 100644 --- a/library/src/main/java/com/google/android/exoplayer2/audio/SimpleDecoderAudioRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer2/audio/SimpleDecoderAudioRenderer.java @@ -145,7 +145,7 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements this.drmSessionManager = drmSessionManager; formatHolder = new FormatHolder(); this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys; - audioSessionId = C.AUDIO_SESSION_ID_UNSET; + audioSessionId = AudioTrack.SESSION_ID_NOT_SET; decoderReinitializationState = REINITIALIZATION_STATE_NONE; audioTrackNeedsConfigure = true; } @@ -245,8 +245,8 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements } if (!audioTrack.isInitialized()) { - if (audioSessionId == C.AUDIO_SESSION_ID_UNSET) { - audioSessionId = audioTrack.initialize(C.AUDIO_SESSION_ID_UNSET); + if (audioSessionId == AudioTrack.SESSION_ID_NOT_SET) { + audioSessionId = audioTrack.initialize(AudioTrack.SESSION_ID_NOT_SET); eventDispatcher.audioSessionId(audioSessionId); onAudioSessionId(audioSessionId); } else { @@ -425,7 +425,7 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements @Override protected void onDisabled() { inputFormat = null; - audioSessionId = C.AUDIO_SESSION_ID_UNSET; + audioSessionId = AudioTrack.SESSION_ID_NOT_SET; audioTrackNeedsConfigure = true; waitingForKeys = false; try { @@ -554,7 +554,7 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements case C.MSG_SET_STREAM_TYPE: @C.StreamType int streamType = (Integer) message; if (audioTrack.setStreamType(streamType)) { - audioSessionId = C.AUDIO_SESSION_ID_UNSET; + audioSessionId = AudioTrack.SESSION_ID_NOT_SET; } break; default: 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 8ab4d45c47..0b7190d382 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 enabledTrackCount == 0 ? C.TIME_END_OF_SOURCE : getBufferedPositionUs(); + return 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 f4a9665b10..a3c1c88df4 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,32 +133,4 @@ 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 869efa6cdc..2f46fc694c 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,14 +104,15 @@ 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, - playlist.startTimeUs, windowDefaultStartPositionUs, true, !playlist.hasEndTag); + windowPositionInPeriodUs, windowDefaultStartPositionUs, true, !playlist.hasEndTag); } else /* not live */ { - timeline = new SinglePeriodTimeline(playlist.startTimeUs + playlist.durationUs, - playlist.durationUs, playlist.startTimeUs, 0, true, false); + timeline = new SinglePeriodTimeline(playlist.durationUs, playlist.durationUs, 0, 0, true, + false); } sourceListener.onSourceInfoRefreshed(timeline, playlist); } diff --git a/library/src/main/java/com/google/android/exoplayer2/text/Cue.java b/library/src/main/java/com/google/android/exoplayer2/text/Cue.java index c4c5a7e4ca..1c29f10c84 100644 --- a/library/src/main/java/com/google/android/exoplayer2/text/Cue.java +++ b/library/src/main/java/com/google/android/exoplayer2/text/Cue.java @@ -15,7 +15,6 @@ */ package com.google.android.exoplayer2.text; -import android.graphics.Color; import android.support.annotation.IntDef; import android.text.Layout.Alignment; import java.lang.annotation.Retention; @@ -37,23 +36,19 @@ public class Cue { @Retention(RetentionPolicy.SOURCE) @IntDef({TYPE_UNSET, ANCHOR_TYPE_START, ANCHOR_TYPE_MIDDLE, ANCHOR_TYPE_END}) public @interface AnchorType {} - /** * An unset anchor or line type value. */ public static final int TYPE_UNSET = Integer.MIN_VALUE; - /** * Anchors the left (for horizontal positions) or top (for vertical positions) edge of the cue * box. */ public static final int ANCHOR_TYPE_START = 0; - /** * Anchors the middle of the cue box. */ public static final int ANCHOR_TYPE_MIDDLE = 1; - /** * Anchors the right (for horizontal positions) or bottom (for vertical positions) edge of the cue * box. @@ -66,12 +61,10 @@ public class Cue { @Retention(RetentionPolicy.SOURCE) @IntDef({TYPE_UNSET, LINE_TYPE_FRACTION, LINE_TYPE_NUMBER}) public @interface LineType {} - /** * Value for {@link #lineType} when {@link #line} is a fractional position. */ public static final int LINE_TYPE_FRACTION = 0; - /** * Value for {@link #lineType} when {@link #line} is a line number. */ @@ -81,12 +74,10 @@ public class Cue { * The cue text. Note the {@link CharSequence} may be decorated with styling spans. */ public final CharSequence text; - /** * The alignment of the cue text within the cue box, or null if the alignment is undefined. */ public final Alignment textAlignment; - /** * The position of the {@link #lineAnchor} of the cue box within the viewport in the direction * orthogonal to the writing direction, or {@link #DIMEN_UNSET}. When set, the interpretation of @@ -95,7 +86,6 @@ public class Cue { * For horizontal text and {@link #lineType} equal to {@link #LINE_TYPE_FRACTION}, this is the * fractional vertical position relative to the top of the viewport. */ - public final float line; /** * The type of the {@link #line} value. @@ -122,7 +112,6 @@ public class Cue { * {@code (line == -2 && lineAnchor == ANCHOR_TYPE_START)} position a cue so that only its first * line is visible at the bottom of the viewport. */ - @LineType public final int lineType; /** @@ -133,7 +122,6 @@ public class Cue { * and {@link #ANCHOR_TYPE_END} correspond to the top, middle and bottom of the cue box * respectively. */ - @AnchorType public final int lineAnchor; /** @@ -145,7 +133,6 @@ public class Cue { * text. */ public final float position; - /** * The cue box anchor positioned by {@link #position}. One of {@link #ANCHOR_TYPE_START}, * {@link #ANCHOR_TYPE_MIDDLE}, {@link #ANCHOR_TYPE_END} and {@link #TYPE_UNSET}. @@ -156,23 +143,12 @@ public class Cue { */ @AnchorType public final int positionAnchor; - /** * The size of the cue box in the writing direction specified as a fraction of the viewport size * in that direction, or {@link #DIMEN_UNSET}. */ public final float size; - /** - * Specifies whether or not the {@link #windowColor} property is set. - */ - public final boolean windowColorSet; - - /** - * The fill color of the window. - */ - public final int windowColor; - /** * Constructs a cue whose {@link #textAlignment} is null, whose type parameters are set to * {@link #TYPE_UNSET} and whose dimension parameters are set to {@link #DIMEN_UNSET}. @@ -195,25 +171,6 @@ public class Cue { */ public Cue(CharSequence text, Alignment textAlignment, float line, @LineType int lineType, @AnchorType int lineAnchor, float position, @AnchorType int positionAnchor, float size) { - this(text, textAlignment, line, lineType, lineAnchor, position, positionAnchor, size, false, - Color.BLACK); - } - - /** - * @param text See {@link #text}. - * @param textAlignment See {@link #textAlignment}. - * @param line See {@link #line}. - * @param lineType See {@link #lineType}. - * @param lineAnchor See {@link #lineAnchor}. - * @param position See {@link #position}. - * @param positionAnchor See {@link #positionAnchor}. - * @param size See {@link #size}. - * @param windowColorSet See {@link #windowColorSet}. - * @param windowColor See {@link #windowColor}. - */ - public Cue(CharSequence text, Alignment textAlignment, float line, @LineType int lineType, - @AnchorType int lineAnchor, float position, @AnchorType int positionAnchor, float size, - boolean windowColorSet, int windowColor) { this.text = text; this.textAlignment = textAlignment; this.line = line; @@ -222,8 +179,6 @@ public class Cue { this.position = position; this.positionAnchor = positionAnchor; this.size = size; - this.windowColorSet = windowColorSet; - this.windowColor = windowColor; } } diff --git a/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java b/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java index 8ac0c64082..d094266fcc 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java +++ b/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java @@ -65,13 +65,6 @@ import java.util.List; *

  • Default: {@code true}
  • * * - *
  • {@code default_artwork} - Default artwork to use if no artwork available in audio - * streams. - *
      - *
    • Corresponding method: {@link #setDefaultArtwork(Bitmap)}
    • - *
    • Default: {@code null}
    • - *
    - *
  • *
  • {@code use_controller} - Whether playback controls are displayed. *
      *
    • Corresponding method: {@link #setUseController(boolean)}
    • @@ -186,7 +179,6 @@ public final class SimpleExoPlayerView extends FrameLayout { private SimpleExoPlayer player; private boolean useController; private boolean useArtwork; - private Bitmap defaultArtwork; private int controllerShowTimeoutMs; public SimpleExoPlayerView(Context context) { @@ -202,7 +194,6 @@ public final class SimpleExoPlayerView extends FrameLayout { int playerLayoutId = R.layout.exo_simple_player_view; boolean useArtwork = true; - int defaultArtwork = 0; boolean useController = true; int surfaceType = SURFACE_TYPE_SURFACE_VIEW; int resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIT; @@ -214,8 +205,6 @@ public final class SimpleExoPlayerView extends FrameLayout { playerLayoutId = a.getResourceId(R.styleable.SimpleExoPlayerView_player_layout_id, playerLayoutId); useArtwork = a.getBoolean(R.styleable.SimpleExoPlayerView_use_artwork, useArtwork); - defaultArtwork = a.getResourceId(R.styleable.SimpleExoPlayerView_default_artwork, - defaultArtwork); useController = a.getBoolean(R.styleable.SimpleExoPlayerView_use_controller, useController); surfaceType = a.getInt(R.styleable.SimpleExoPlayerView_surface_type, surfaceType); resizeMode = a.getInt(R.styleable.SimpleExoPlayerView_resize_mode, resizeMode); @@ -257,9 +246,6 @@ public final class SimpleExoPlayerView extends FrameLayout { // Artwork view. artworkView = (ImageView) findViewById(R.id.exo_artwork); this.useArtwork = useArtwork && artworkView != null; - if (defaultArtwork != 0) { - this.defaultArtwork = BitmapFactory.decodeResource(context.getResources(), defaultArtwork); - } // Subtitle view. subtitleView = (SubtitleView) findViewById(R.id.exo_subtitles); @@ -365,26 +351,6 @@ public final class SimpleExoPlayerView extends FrameLayout { } } - /** - * Returns the default artwork to display. - */ - public Bitmap getDefaultArtwork() { - return defaultArtwork; - } - - /** - * Sets the default artwork to display if {@code useArtwork} is {@code true} and no artwork is - * present in the media. - * - * @param defaultArtwork the default artwork to display. - */ - public void setDefaultArtwork(Bitmap defaultArtwork) { - if (this.defaultArtwork != defaultArtwork) { - this.defaultArtwork = defaultArtwork; - updateForCurrentTrackSelections(); - } - } - /** * Returns whether the playback controls are enabled. */ @@ -603,9 +569,6 @@ public final class SimpleExoPlayerView extends FrameLayout { } } } - if (setArtworkFromBitmap(defaultArtwork)) { - return; - } } // Artwork disabled or unavailable. hideArtwork(); @@ -617,23 +580,18 @@ public final class SimpleExoPlayerView extends FrameLayout { if (metadataEntry instanceof ApicFrame) { byte[] bitmapData = ((ApicFrame) metadataEntry).pictureData; Bitmap bitmap = BitmapFactory.decodeByteArray(bitmapData, 0, bitmapData.length); - return setArtworkFromBitmap(bitmap); - } - } - return false; - } - - private boolean setArtworkFromBitmap(Bitmap bitmap) { - if (bitmap != null) { - int bitmapWidth = bitmap.getWidth(); - int bitmapHeight = bitmap.getHeight(); - if (bitmapWidth > 0 && bitmapHeight > 0) { - if (contentFrame != null) { - contentFrame.setAspectRatio((float) bitmapWidth / bitmapHeight); + if (bitmap != null) { + int bitmapWidth = bitmap.getWidth(); + int bitmapHeight = bitmap.getHeight(); + if (bitmapWidth > 0 && bitmapHeight > 0) { + if (contentFrame != null) { + contentFrame.setAspectRatio((float) bitmapWidth / bitmapHeight); + } + artworkView.setImageBitmap(bitmap); + artworkView.setVisibility(VISIBLE); + return true; + } } - artworkView.setImageBitmap(bitmap); - artworkView.setVisibility(VISIBLE); - return true; } } return false; diff --git a/library/src/main/java/com/google/android/exoplayer2/ui/SubtitlePainter.java b/library/src/main/java/com/google/android/exoplayer2/ui/SubtitlePainter.java index 04f3b986bd..de461ecf0d 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ui/SubtitlePainter.java +++ b/library/src/main/java/com/google/android/exoplayer2/ui/SubtitlePainter.java @@ -146,13 +146,9 @@ import com.google.android.exoplayer2.util.Util; // Nothing to draw. return; } - - int windowColor = cue.windowColorSet ? cue.windowColor : style.windowColor; - if (!applyEmbeddedStyles) { // Strip out any embedded styling. cueText = cueText.toString(); - windowColor = style.windowColor; } if (areCharSequencesEqual(this.cueText, cueText) && Util.areEqual(this.cueTextAlignment, cue.textAlignment) @@ -165,7 +161,7 @@ import com.google.android.exoplayer2.util.Util; && this.applyEmbeddedStyles == applyEmbeddedStyles && this.foregroundColor == style.foregroundColor && this.backgroundColor == style.backgroundColor - && this.windowColor == windowColor + && this.windowColor == style.windowColor && this.edgeType == style.edgeType && this.edgeColor == style.edgeColor && Util.areEqual(this.textPaint.getTypeface(), style.typeface) @@ -191,7 +187,7 @@ import com.google.android.exoplayer2.util.Util; this.applyEmbeddedStyles = applyEmbeddedStyles; this.foregroundColor = style.foregroundColor; this.backgroundColor = style.backgroundColor; - this.windowColor = windowColor; + this.windowColor = style.windowColor; this.edgeType = style.edgeType; this.edgeColor = style.edgeColor; this.textPaint.setTypeface(style.typeface); diff --git a/library/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java b/library/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java index f68b72fb65..2a13953106 100644 --- a/library/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java @@ -403,7 +403,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { bufferPresentationTimeUs, unadjustedFrameReleaseTimeNs); earlyUs = (adjustedReleaseTimeNs - systemTimeNs) / 1000; - if (shouldDropOutputBuffer(earlyUs, elapsedRealtimeUs)) { + if (earlyUs < -30000) { // We're more than 30ms late rendering the frame. dropOutputBuffer(codec, bufferIndex); return true; @@ -437,17 +437,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { return false; } - /** - * Returns true if the current frame should be dropped. - * - * @param earlyUs Time indicating how early the frame is. Negative values indicate late frame. - * @param elapsedRealtimeUs Wall clock time. - */ - protected boolean shouldDropOutputBuffer(long earlyUs, long elapsedRealtimeUs) { - // Drop the frame if we're more than 30ms late rendering the frame. - return earlyUs < -30000; - } - private void skipOutputBuffer(MediaCodec codec, int bufferIndex) { TraceUtil.beginSection("skipVideoBuffer"); codec.releaseOutputBuffer(bufferIndex, false); diff --git a/library/src/main/res/drawable-hdpi/exo_controls_fastforward.png b/library/src/main/res/drawable-hdpi/exo_controls_fastforward.png index 843df84091..c65956ab7f 100644 Binary files a/library/src/main/res/drawable-hdpi/exo_controls_fastforward.png and b/library/src/main/res/drawable-hdpi/exo_controls_fastforward.png differ diff --git a/library/src/main/res/drawable-hdpi/exo_controls_next.png b/library/src/main/res/drawable-hdpi/exo_controls_next.png index c37541472e..6e27b8161e 100644 Binary files a/library/src/main/res/drawable-hdpi/exo_controls_next.png and b/library/src/main/res/drawable-hdpi/exo_controls_next.png differ diff --git a/library/src/main/res/drawable-hdpi/exo_controls_pause.png b/library/src/main/res/drawable-hdpi/exo_controls_pause.png index 0a23452746..1d465a41e4 100644 Binary files a/library/src/main/res/drawable-hdpi/exo_controls_pause.png and b/library/src/main/res/drawable-hdpi/exo_controls_pause.png differ diff --git a/library/src/main/res/drawable-hdpi/exo_controls_play.png b/library/src/main/res/drawable-hdpi/exo_controls_play.png index e98e2b9cbe..2746d17fb1 100644 Binary files a/library/src/main/res/drawable-hdpi/exo_controls_play.png and b/library/src/main/res/drawable-hdpi/exo_controls_play.png differ diff --git a/library/src/main/res/drawable-hdpi/exo_controls_previous.png b/library/src/main/res/drawable-hdpi/exo_controls_previous.png index 3eae5c883b..85b3766904 100644 Binary files a/library/src/main/res/drawable-hdpi/exo_controls_previous.png and b/library/src/main/res/drawable-hdpi/exo_controls_previous.png differ diff --git a/library/src/main/res/drawable-hdpi/exo_controls_rewind.png b/library/src/main/res/drawable-hdpi/exo_controls_rewind.png index 36537d3b73..a4ac181777 100644 Binary files a/library/src/main/res/drawable-hdpi/exo_controls_rewind.png and b/library/src/main/res/drawable-hdpi/exo_controls_rewind.png differ diff --git a/library/src/main/res/drawable-ldpi/exo_controls_fastforward.png b/library/src/main/res/drawable-ldpi/exo_controls_fastforward.png index 19b9e6015c..1b4d9dbef9 100644 Binary files a/library/src/main/res/drawable-ldpi/exo_controls_fastforward.png and b/library/src/main/res/drawable-ldpi/exo_controls_fastforward.png differ diff --git a/library/src/main/res/drawable-ldpi/exo_controls_next.png b/library/src/main/res/drawable-ldpi/exo_controls_next.png index d4872037aa..99927fd27b 100644 Binary files a/library/src/main/res/drawable-ldpi/exo_controls_next.png and b/library/src/main/res/drawable-ldpi/exo_controls_next.png differ diff --git a/library/src/main/res/drawable-ldpi/exo_controls_pause.png b/library/src/main/res/drawable-ldpi/exo_controls_pause.png index 616ec42f39..3b98d66688 100644 Binary files a/library/src/main/res/drawable-ldpi/exo_controls_pause.png and b/library/src/main/res/drawable-ldpi/exo_controls_pause.png differ diff --git a/library/src/main/res/drawable-ldpi/exo_controls_play.png b/library/src/main/res/drawable-ldpi/exo_controls_play.png index 5d1c702892..e7c19724bb 100644 Binary files a/library/src/main/res/drawable-ldpi/exo_controls_play.png and b/library/src/main/res/drawable-ldpi/exo_controls_play.png differ diff --git a/library/src/main/res/drawable-ldpi/exo_controls_previous.png b/library/src/main/res/drawable-ldpi/exo_controls_previous.png index 930534d312..df043228d0 100644 Binary files a/library/src/main/res/drawable-ldpi/exo_controls_previous.png and b/library/src/main/res/drawable-ldpi/exo_controls_previous.png differ diff --git a/library/src/main/res/drawable-ldpi/exo_controls_rewind.png b/library/src/main/res/drawable-ldpi/exo_controls_rewind.png index 83d71782f6..28843f9fb0 100644 Binary files a/library/src/main/res/drawable-ldpi/exo_controls_rewind.png and b/library/src/main/res/drawable-ldpi/exo_controls_rewind.png differ diff --git a/library/src/main/res/drawable-mdpi/exo_controls_fastforward.png b/library/src/main/res/drawable-mdpi/exo_controls_fastforward.png index ee3efe1d69..170dd2daaa 100644 Binary files a/library/src/main/res/drawable-mdpi/exo_controls_fastforward.png and b/library/src/main/res/drawable-mdpi/exo_controls_fastforward.png differ diff --git a/library/src/main/res/drawable-mdpi/exo_controls_next.png b/library/src/main/res/drawable-mdpi/exo_controls_next.png index 9d4d7469ed..fcd73d90e7 100644 Binary files a/library/src/main/res/drawable-mdpi/exo_controls_next.png and b/library/src/main/res/drawable-mdpi/exo_controls_next.png differ diff --git a/library/src/main/res/drawable-mdpi/exo_controls_pause.png b/library/src/main/res/drawable-mdpi/exo_controls_pause.png index f54c942201..3e6b2a17b5 100644 Binary files a/library/src/main/res/drawable-mdpi/exo_controls_pause.png and b/library/src/main/res/drawable-mdpi/exo_controls_pause.png differ diff --git a/library/src/main/res/drawable-mdpi/exo_controls_play.png b/library/src/main/res/drawable-mdpi/exo_controls_play.png index dd0c142859..7966bbc516 100644 Binary files a/library/src/main/res/drawable-mdpi/exo_controls_play.png and b/library/src/main/res/drawable-mdpi/exo_controls_play.png differ diff --git a/library/src/main/res/drawable-mdpi/exo_controls_previous.png b/library/src/main/res/drawable-mdpi/exo_controls_previous.png index 950e213d2f..b653d05b9f 100644 Binary files a/library/src/main/res/drawable-mdpi/exo_controls_previous.png and b/library/src/main/res/drawable-mdpi/exo_controls_previous.png differ diff --git a/library/src/main/res/drawable-mdpi/exo_controls_rewind.png b/library/src/main/res/drawable-mdpi/exo_controls_rewind.png index e75efae189..5489180eb1 100644 Binary files a/library/src/main/res/drawable-mdpi/exo_controls_rewind.png and b/library/src/main/res/drawable-mdpi/exo_controls_rewind.png differ diff --git a/library/src/main/res/drawable-v21/exo_controls_fastforward.xml b/library/src/main/res/drawable-v21/exo_controls_fastforward.xml deleted file mode 100644 index 945d70eef3..0000000000 --- a/library/src/main/res/drawable-v21/exo_controls_fastforward.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - diff --git a/library/src/main/res/drawable-v21/exo_controls_next.xml b/library/src/main/res/drawable-v21/exo_controls_next.xml deleted file mode 100644 index c96f1e4afe..0000000000 --- a/library/src/main/res/drawable-v21/exo_controls_next.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - diff --git a/library/src/main/res/drawable-v21/exo_controls_pause.xml b/library/src/main/res/drawable-v21/exo_controls_pause.xml deleted file mode 100644 index 69a17cb9a1..0000000000 --- a/library/src/main/res/drawable-v21/exo_controls_pause.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - diff --git a/library/src/main/res/drawable-v21/exo_controls_play.xml b/library/src/main/res/drawable-v21/exo_controls_play.xml deleted file mode 100644 index c21978f7f2..0000000000 --- a/library/src/main/res/drawable-v21/exo_controls_play.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - diff --git a/library/src/main/res/drawable-v21/exo_controls_previous.xml b/library/src/main/res/drawable-v21/exo_controls_previous.xml deleted file mode 100644 index c5789d5fe4..0000000000 --- a/library/src/main/res/drawable-v21/exo_controls_previous.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - diff --git a/library/src/main/res/drawable-v21/exo_controls_rewind.xml b/library/src/main/res/drawable-v21/exo_controls_rewind.xml deleted file mode 100644 index 6ecb8f8a27..0000000000 --- a/library/src/main/res/drawable-v21/exo_controls_rewind.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - diff --git a/library/src/main/res/drawable-xhdpi/exo_controls_fastforward.png b/library/src/main/res/drawable-xhdpi/exo_controls_fastforward.png index ead712cfe9..60f7e92181 100644 Binary files a/library/src/main/res/drawable-xhdpi/exo_controls_fastforward.png and b/library/src/main/res/drawable-xhdpi/exo_controls_fastforward.png differ diff --git a/library/src/main/res/drawable-xhdpi/exo_controls_next.png b/library/src/main/res/drawable-xhdpi/exo_controls_next.png index bc1ebf83c5..4def965cec 100644 Binary files a/library/src/main/res/drawable-xhdpi/exo_controls_next.png and b/library/src/main/res/drawable-xhdpi/exo_controls_next.png differ diff --git a/library/src/main/res/drawable-xhdpi/exo_controls_pause.png b/library/src/main/res/drawable-xhdpi/exo_controls_pause.png index 1c868f1831..6bd3d482e1 100644 Binary files a/library/src/main/res/drawable-xhdpi/exo_controls_pause.png and b/library/src/main/res/drawable-xhdpi/exo_controls_pause.png differ diff --git a/library/src/main/res/drawable-xhdpi/exo_controls_play.png b/library/src/main/res/drawable-xhdpi/exo_controls_play.png index f2f934413e..ccfef18056 100644 Binary files a/library/src/main/res/drawable-xhdpi/exo_controls_play.png and b/library/src/main/res/drawable-xhdpi/exo_controls_play.png differ diff --git a/library/src/main/res/drawable-xhdpi/exo_controls_previous.png b/library/src/main/res/drawable-xhdpi/exo_controls_previous.png index d197eff873..c4472ae2d9 100644 Binary files a/library/src/main/res/drawable-xhdpi/exo_controls_previous.png and b/library/src/main/res/drawable-xhdpi/exo_controls_previous.png differ diff --git a/library/src/main/res/drawable-xhdpi/exo_controls_rewind.png b/library/src/main/res/drawable-xhdpi/exo_controls_rewind.png index 3340ef9bd2..167d10e58b 100644 Binary files a/library/src/main/res/drawable-xhdpi/exo_controls_rewind.png and b/library/src/main/res/drawable-xhdpi/exo_controls_rewind.png differ diff --git a/library/src/main/res/drawable-xxhdpi/exo_controls_fastforward.png b/library/src/main/res/drawable-xxhdpi/exo_controls_fastforward.png index e1c6cae292..ab9e022fbf 100644 Binary files a/library/src/main/res/drawable-xxhdpi/exo_controls_fastforward.png and b/library/src/main/res/drawable-xxhdpi/exo_controls_fastforward.png differ diff --git a/library/src/main/res/drawable-xxhdpi/exo_controls_next.png b/library/src/main/res/drawable-xxhdpi/exo_controls_next.png index 232f09e910..ce0a14325a 100644 Binary files a/library/src/main/res/drawable-xxhdpi/exo_controls_next.png and b/library/src/main/res/drawable-xxhdpi/exo_controls_next.png differ diff --git a/library/src/main/res/drawable-xxhdpi/exo_controls_pause.png b/library/src/main/res/drawable-xxhdpi/exo_controls_pause.png index 50a545db4d..9a36b17cb8 100644 Binary files a/library/src/main/res/drawable-xxhdpi/exo_controls_pause.png and b/library/src/main/res/drawable-xxhdpi/exo_controls_pause.png differ diff --git a/library/src/main/res/drawable-xxhdpi/exo_controls_play.png b/library/src/main/res/drawable-xxhdpi/exo_controls_play.png index 08508c5015..41f76bbf99 100644 Binary files a/library/src/main/res/drawable-xxhdpi/exo_controls_play.png and b/library/src/main/res/drawable-xxhdpi/exo_controls_play.png differ diff --git a/library/src/main/res/drawable-xxhdpi/exo_controls_previous.png b/library/src/main/res/drawable-xxhdpi/exo_controls_previous.png index f71acc4875..d4688741b9 100644 Binary files a/library/src/main/res/drawable-xxhdpi/exo_controls_previous.png and b/library/src/main/res/drawable-xxhdpi/exo_controls_previous.png differ diff --git a/library/src/main/res/drawable-xxhdpi/exo_controls_rewind.png b/library/src/main/res/drawable-xxhdpi/exo_controls_rewind.png index db0555f9e5..8ebb2ccf30 100644 Binary files a/library/src/main/res/drawable-xxhdpi/exo_controls_rewind.png and b/library/src/main/res/drawable-xxhdpi/exo_controls_rewind.png differ diff --git a/library/src/main/res/drawable-xxxhdpi/exo_controls_fastforward.png b/library/src/main/res/drawable-xxxhdpi/exo_controls_fastforward.png deleted file mode 100644 index af0435a8b7..0000000000 Binary files a/library/src/main/res/drawable-xxxhdpi/exo_controls_fastforward.png and /dev/null differ diff --git a/library/src/main/res/drawable-xxxhdpi/exo_controls_next.png b/library/src/main/res/drawable-xxxhdpi/exo_controls_next.png deleted file mode 100644 index 50916cf0e7..0000000000 Binary files a/library/src/main/res/drawable-xxxhdpi/exo_controls_next.png and /dev/null differ diff --git a/library/src/main/res/drawable-xxxhdpi/exo_controls_pause.png b/library/src/main/res/drawable-xxxhdpi/exo_controls_pause.png deleted file mode 100644 index 6a5c59335e..0000000000 Binary files a/library/src/main/res/drawable-xxxhdpi/exo_controls_pause.png and /dev/null differ diff --git a/library/src/main/res/drawable-xxxhdpi/exo_controls_play.png b/library/src/main/res/drawable-xxxhdpi/exo_controls_play.png deleted file mode 100644 index 5d1f452d0d..0000000000 Binary files a/library/src/main/res/drawable-xxxhdpi/exo_controls_play.png and /dev/null differ diff --git a/library/src/main/res/drawable-xxxhdpi/exo_controls_previous.png b/library/src/main/res/drawable-xxxhdpi/exo_controls_previous.png deleted file mode 100644 index 00f7b97d1b..0000000000 Binary files a/library/src/main/res/drawable-xxxhdpi/exo_controls_previous.png and /dev/null differ diff --git a/library/src/main/res/drawable-xxxhdpi/exo_controls_rewind.png b/library/src/main/res/drawable-xxxhdpi/exo_controls_rewind.png deleted file mode 100644 index 5f3bb94440..0000000000 Binary files a/library/src/main/res/drawable-xxxhdpi/exo_controls_rewind.png and /dev/null differ diff --git a/library/src/main/res/values/attrs.xml b/library/src/main/res/values/attrs.xml index c73bfb0a3c..b5c01b4575 100644 --- a/library/src/main/res/values/attrs.xml +++ b/library/src/main/res/values/attrs.xml @@ -37,7 +37,6 @@ -