From 07cbfb65e576e09805cec1b2dc0051ba6c0d0bc2 Mon Sep 17 00:00:00 2001 From: andrewlewis Date: Mon, 6 Apr 2020 19:46:21 +0100 Subject: [PATCH] Fix stuck ad playbacks with DRM-protected content When ClippingMediaPeriod first tried to read a buffer, if its end position was before the end of the stream and it was buffered to its end position, it would sometimes erroneously signal end-of-stream for protected content because the sample queue might be waiting for DRM keys at this point. Work around the issue temporarily by signaling this specific case back to ClippingMediaPeriod via the DecoderInputBuffer. There will likely be a cleaner fix as a result of adding support for dynamic clip end points in the future, at which point this can be reverted. issue:#7188 PiperOrigin-RevId: 305081757 --- RELEASENOTES.md | 116 +++++++++--------- .../decoder/DecoderInputBuffer.java | 9 ++ .../source/ClippingMediaPeriod.java | 3 +- .../exoplayer2/source/SampleQueue.java | 3 +- .../exoplayer2/source/SampleQueueTest.java | 2 + 5 files changed, 74 insertions(+), 59 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 8b0ffde27e..b8074b8c86 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -25,6 +25,8 @@ ([#7129](https://github.com/google/ExoPlayer/issues/7129)). * Fix playback of ADTS files with mid-stream ID3 metadata. * DRM: + * Fix stuck ad playbacks with DRM protected content + ([#7188](https://github.com/google/ExoPlayer/issues/7188)). * Fix playback of Widevine protected content that only provides V1 PSSH atoms on API levels 21 and 22. * Fix playback of PlayReady content on Fire TV Stick (Gen 2). @@ -51,63 +53,63 @@ ### 2.11.2 (2020-02-13) ### -* Add Java FLAC extractor - ([#6406](https://github.com/google/ExoPlayer/issues/6406)). -* Startup latency optimization: - * 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. -* Downloads: - * Fix download resumption when the requirements for them to continue are - met ([#6733](https://github.com/google/ExoPlayer/issues/6733), - [#6798](https://github.com/google/ExoPlayer/issues/6798)). - * Fix `DownloadHelper.createMediaSource` to use `customCacheKey` when creating - `ProgressiveMediaSource` instances. -* DRM: Fix `NullPointerException` when playing DRM-protected content - ([#6951](https://github.com/google/ExoPlayer/issues/6951)). -* Metadata: - * Update `IcyDecoder` to try ISO-8859-1 decoding if UTF-8 decoding fails. - Also change `IcyInfo.rawMetadata` from `String` to `byte[]` to allow - developers to handle data that's neither UTF-8 nor ISO-8859-1 - ([#6753](https://github.com/google/ExoPlayer/issues/6753)). - * Select multiple metadata tracks if multiple metadata renderers are available - ([#6676](https://github.com/google/ExoPlayer/issues/6676)). - * Add support for ID3 genres added in Wimamp 5.6 (2010). -* UI: - * Show ad group markers in `DefaultTimeBar` even if they are after the end - of the current window - ([#6552](https://github.com/google/ExoPlayer/issues/6552)). - * Don't use notification chronometer if playback speed is != 1.0 - ([#6816](https://github.com/google/ExoPlayer/issues/6816)). -* HLS: Fix playback of DRM protected content that uses key rotation - ([#6903](https://github.com/google/ExoPlayer/issues/6903)). -* WAV: - * Support IMA ADPCM encoded data. - * Improve support for G.711 A-law and mu-law encoded data. -* MP4: Support "twos" codec (big endian PCM) - ([#5789](https://github.com/google/ExoPlayer/issues/5789)). -* FMP4: Add support for encrypted AC-4 tracks. -* HLS: Fix slow seeking into long MP3 segments - ([#6155](https://github.com/google/ExoPlayer/issues/6155)). -* Fix handling of E-AC-3 streams that contain AC-3 syncframes - ([#6602](https://github.com/google/ExoPlayer/issues/6602)). -* Fix playback of TrueHD streams in Matroska - ([#6845](https://github.com/google/ExoPlayer/issues/6845)). -* Fix MKV subtitles to disappear when intended instead of lasting until the - next cue ([#6833](https://github.com/google/ExoPlayer/issues/6833)). -* OkHttp extension: Upgrade OkHttp dependency to 3.12.8, which fixes a class of - `SocketTimeoutException` issues when using HTTP/2 - ([#4078](https://github.com/google/ExoPlayer/issues/4078)). -* FLAC extension: Fix handling of bit depths other than 16 in `FLACDecoder`. - This issue caused FLAC streams with other bit depths to sound like white noise - on earlier releases, but only when embedded in a non-FLAC container such as - Matroska or MP4. -* Demo apps: Add - [GL demo app](https://github.com/google/ExoPlayer/tree/dev-v2/demos/gl) to - show how to render video to a `GLSurfaceView` while applying a GL shader. - ([#6920](https://github.com/google/ExoPlayer/issues/6920)). +* Add Java FLAC extractor + ([#6406](https://github.com/google/ExoPlayer/issues/6406)). +* Startup latency optimization: + * 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. +* Downloads: + * Fix download resumption when the requirements for them to continue are + met ([#6733](https://github.com/google/ExoPlayer/issues/6733), + [#6798](https://github.com/google/ExoPlayer/issues/6798)). + * Fix `DownloadHelper.createMediaSource` to use `customCacheKey` when + creating `ProgressiveMediaSource` instances. +* DRM: Fix `NullPointerException` when playing DRM protected content + ([#6951](https://github.com/google/ExoPlayer/issues/6951)). +* Metadata: + * Update `IcyDecoder` to try ISO-8859-1 decoding if UTF-8 decoding fails. + Also change `IcyInfo.rawMetadata` from `String` to `byte[]` to allow + developers to handle data that's neither UTF-8 nor ISO-8859-1 + ([#6753](https://github.com/google/ExoPlayer/issues/6753)). + * Select multiple metadata tracks if multiple metadata renderers are + available ([#6676](https://github.com/google/ExoPlayer/issues/6676)). + * Add support for ID3 genres added in Wimamp 5.6 (2010). +* UI: + * Show ad group markers in `DefaultTimeBar` even if they are after the end + of the current window + ([#6552](https://github.com/google/ExoPlayer/issues/6552)). + * Don't use notification chronometer if playback speed is != 1.0 + ([#6816](https://github.com/google/ExoPlayer/issues/6816)). +* HLS: Fix playback of DRM protected content that uses key rotation + ([#6903](https://github.com/google/ExoPlayer/issues/6903)). +* WAV: + * Support IMA ADPCM encoded data. + * Improve support for G.711 A-law and mu-law encoded data. +* MP4: Support "twos" codec (big endian PCM) + ([#5789](https://github.com/google/ExoPlayer/issues/5789)). +* FMP4: Add support for encrypted AC-4 tracks. +* HLS: Fix slow seeking into long MP3 segments + ([#6155](https://github.com/google/ExoPlayer/issues/6155)). +* Fix handling of E-AC-3 streams that contain AC-3 syncframes + ([#6602](https://github.com/google/ExoPlayer/issues/6602)). +* Fix playback of TrueHD streams in Matroska + ([#6845](https://github.com/google/ExoPlayer/issues/6845)). +* Fix MKV subtitles to disappear when intended instead of lasting until the + next cue ([#6833](https://github.com/google/ExoPlayer/issues/6833)). +* OkHttp extension: Upgrade OkHttp dependency to 3.12.8, which fixes a class + of `SocketTimeoutException` issues when using HTTP/2 + ([#4078](https://github.com/google/ExoPlayer/issues/4078)). +* FLAC extension: Fix handling of bit depths other than 16 in `FLACDecoder`. + This issue caused FLAC streams with other bit depths to sound like white + noise on earlier releases, but only when embedded in a non-FLAC container + such as Matroska or MP4. +* Demo apps: Add + [GL demo app](https://github.com/google/ExoPlayer/tree/dev-v2/demos/gl) to + show how to render video to a `GLSurfaceView` while applying a GL shader. + ([#6920](https://github.com/google/ExoPlayer/issues/6920)). ### 2.11.1 (2019-12-20) ### diff --git a/library/core/src/main/java/com/google/android/exoplayer2/decoder/DecoderInputBuffer.java b/library/core/src/main/java/com/google/android/exoplayer2/decoder/DecoderInputBuffer.java index 31dfa8f020..bd5df4c8b1 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/decoder/DecoderInputBuffer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/decoder/DecoderInputBuffer.java @@ -63,6 +63,14 @@ public class DecoderInputBuffer extends Buffer { /** The buffer's data, or {@code null} if no data has been set. */ @Nullable public ByteBuffer data; + // TODO: Remove this temporary signaling once end-of-stream propagation for clips using content + // protection is fixed. See [Internal: b/153326944] for details. + /** + * Whether the last attempt to read a sample into this buffer failed due to not yet having the DRM + * keys associated with the next sample. + */ + public boolean waitingForKeys; + /** * The time at which the sample should be presented. */ @@ -183,6 +191,7 @@ public class DecoderInputBuffer extends Buffer { if (supplementalData != null) { supplementalData.clear(); } + waitingForKeys = false; } private ByteBuffer createReplacementByteBuffer(int requiredCapacity) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaPeriod.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaPeriod.java index 8aafb9a0e5..4385a41ff3 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaPeriod.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaPeriod.java @@ -324,7 +324,8 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb if (endUs != C.TIME_END_OF_SOURCE && ((result == C.RESULT_BUFFER_READ && buffer.timeUs >= endUs) || (result == C.RESULT_NOTHING_READ - && getBufferedPositionUs() == C.TIME_END_OF_SOURCE))) { + && getBufferedPositionUs() == C.TIME_END_OF_SOURCE + && !buffer.waitingForKeys))) { buffer.clear(); buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM); sentEos = true; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java index d4e447bc61..b5cfe6ed72 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java @@ -539,7 +539,7 @@ public class SampleQueue implements TrackOutput { boolean loadingFinished, long decodeOnlyUntilUs, SampleExtrasHolder extrasHolder) { - + buffer.waitingForKeys = false; // This is a temporary fix for https://github.com/google/ExoPlayer/issues/6155. // TODO: Remove it and replace it with a fix that discards samples when writing to the queue. boolean hasNextSample; @@ -573,6 +573,7 @@ public class SampleQueue implements TrackOutput { } if (!mayReadSample(relativeReadIndex)) { + buffer.waitingForKeys = true; return C.RESULT_NOTHING_READ; } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java b/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java index 427e81d29f..a34488d2e7 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java @@ -372,8 +372,10 @@ public final class SampleQueueTest { assertReadFormat(/* formatRequired= */ false, FORMAT_ENCRYPTED); assertReadNothing(/* formatRequired= */ false); + assertThat(inputBuffer.waitingForKeys).isTrue(); when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED_WITH_KEYS); assertReadEncryptedSample(/* sampleIndex= */ 0); + assertThat(inputBuffer.waitingForKeys).isFalse(); } @Test