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
This commit is contained in:
andrewlewis 2020-04-06 19:46:21 +01:00 committed by Oliver Woodman
parent 1f544b0856
commit dc813eca41
5 changed files with 113 additions and 97 deletions

View File

@ -112,9 +112,10 @@
### 2.11.4 (2020-04-08) ### ### 2.11.4 (2020-04-08) ###
* Add `SimpleExoPlayer.setWakeMode` to allow automatic `WifiLock` and `WakeLock` * Add `SimpleExoPlayer.setWakeMode` to allow automatic `WifiLock` and
handling ([#6914](https://github.com/google/ExoPlayer/issues/6914)). To use `WakeLock` handling
this feature, you must add the ([#6914](https://github.com/google/ExoPlayer/issues/6914)). To use this
feature, you must add the
[WAKE_LOCK](https://developer.android.com/reference/android/Manifest.permission.html#WAKE_LOCK) [WAKE_LOCK](https://developer.android.com/reference/android/Manifest.permission.html#WAKE_LOCK)
permission to your application's manifest file. permission to your application's manifest file.
* Text: * Text:
@ -124,20 +125,22 @@
* Allow missing hours and milliseconds in SubRip (.srt) timecodes * Allow missing hours and milliseconds in SubRip (.srt) timecodes
([#7122](https://github.com/google/ExoPlayer/issues/7122)). ([#7122](https://github.com/google/ExoPlayer/issues/7122)).
* Audio: * Audio:
* Workaround issue that could cause slower than realtime playback of AAC on * Workaround issue that could cause slower than realtime playback of AAC
Android 10 ([#6671](https://github.com/google/ExoPlayer/issues/6671). on Android 10 ([#6671](https://github.com/google/ExoPlayer/issues/6671).
* Enable playback speed adjustment and silence skipping for floating point PCM * Enable playback speed adjustment and silence skipping for floating point
audio, via resampling to 16-bit integer PCM. To output the original floating PCM audio, via resampling to 16-bit integer PCM. To output the original
point audio without adjustment, pass `enableFloatOutput=true` to the floating point audio without adjustment, pass `enableFloatOutput=true`
`DefaultAudioSink` constructor to the `DefaultAudioSink` constructor
([#7134](https://github.com/google/ExoPlayer/issues/7134)). ([#7134](https://github.com/google/ExoPlayer/issues/7134)).
* Fix playback of WAV files with trailing non-media bytes * Fix playback of WAV files with trailing non-media bytes
([#7129](https://github.com/google/ExoPlayer/issues/7129)). ([#7129](https://github.com/google/ExoPlayer/issues/7129)).
* Fix playback of ADTS files with mid-stream ID3 metadata. * Fix playback of ADTS files with mid-stream ID3 metadata.
* DRM: * DRM:
* Fix playback of Widevine protected content that only provides V1 PSSH atoms * Fix playback of Widevine protected content that only provides V1 PSSH
on API levels 21 and 22. atoms on API levels 21 and 22.
* Fix playback of PlayReady content on Fire TV Stick (Gen 2). * Fix playback of PlayReady content on Fire TV Stick (Gen 2).
* Fix stuck ad playbacks with DRM protected content
([#7188](https://github.com/google/ExoPlayer/issues/7188)).
* DASH: * DASH:
* Update the manifest URI to avoid repeated HTTP redirects * Update the manifest URI to avoid repeated HTTP redirects
([#6907](https://github.com/google/ExoPlayer/issues/6907)). ([#6907](https://github.com/google/ExoPlayer/issues/6907)).
@ -164,26 +167,26 @@
* Add Java FLAC extractor * Add Java FLAC extractor
([#6406](https://github.com/google/ExoPlayer/issues/6406)). ([#6406](https://github.com/google/ExoPlayer/issues/6406)).
* Startup latency optimization: * Startup latency optimization:
* Reduce startup latency for DASH and SmoothStreaming playbacks by allowing * Reduce startup latency for DASH and SmoothStreaming playbacks by
codec initialization to occur before the network connection for the first allowing codec initialization to occur before the network connection for
media segment has been established. the first media segment has been established.
* Reduce startup latency for on-demand DASH playbacks by allowing codec * Reduce startup latency for on-demand DASH playbacks by allowing codec
initialization to occur before the sidx box has been loaded. initialization to occur before the sidx box has been loaded.
* Downloads: * Downloads:
* Fix download resumption when the requirements for them to continue are * Fix download resumption when the requirements for them to continue are
met ([#6733](https://github.com/google/ExoPlayer/issues/6733), met ([#6733](https://github.com/google/ExoPlayer/issues/6733),
[#6798](https://github.com/google/ExoPlayer/issues/6798)). [#6798](https://github.com/google/ExoPlayer/issues/6798)).
* Fix `DownloadHelper.createMediaSource` to use `customCacheKey` when creating * Fix `DownloadHelper.createMediaSource` to use `customCacheKey` when
`ProgressiveMediaSource` instances. creating `ProgressiveMediaSource` instances.
* DRM: Fix `NullPointerException` when playing DRM-protected content * DRM: Fix `NullPointerException` when playing DRM protected content
([#6951](https://github.com/google/ExoPlayer/issues/6951)). ([#6951](https://github.com/google/ExoPlayer/issues/6951)).
* Metadata: * Metadata:
* Update `IcyDecoder` to try ISO-8859-1 decoding if UTF-8 decoding fails. * Update `IcyDecoder` to try ISO-8859-1 decoding if UTF-8 decoding fails.
Also change `IcyInfo.rawMetadata` from `String` to `byte[]` to allow Also change `IcyInfo.rawMetadata` from `String` to `byte[]` to allow
developers to handle data that's neither UTF-8 nor ISO-8859-1 developers to handle data that's neither UTF-8 nor ISO-8859-1
([#6753](https://github.com/google/ExoPlayer/issues/6753)). ([#6753](https://github.com/google/ExoPlayer/issues/6753)).
* Select multiple metadata tracks if multiple metadata renderers are available * Select multiple metadata tracks if multiple metadata renderers are
([#6676](https://github.com/google/ExoPlayer/issues/6676)). available ([#6676](https://github.com/google/ExoPlayer/issues/6676)).
* Add support for ID3 genres added in Wimamp 5.6 (2010). * Add support for ID3 genres added in Wimamp 5.6 (2010).
* UI: * UI:
* Show ad group markers in `DefaultTimeBar` even if they are after the end * Show ad group markers in `DefaultTimeBar` even if they are after the end
@ -207,13 +210,13 @@
([#6845](https://github.com/google/ExoPlayer/issues/6845)). ([#6845](https://github.com/google/ExoPlayer/issues/6845)).
* Fix MKV subtitles to disappear when intended instead of lasting until the * Fix MKV subtitles to disappear when intended instead of lasting until the
next cue ([#6833](https://github.com/google/ExoPlayer/issues/6833)). next cue ([#6833](https://github.com/google/ExoPlayer/issues/6833)).
* OkHttp extension: Upgrade OkHttp dependency to 3.12.8, which fixes a class of * OkHttp extension: Upgrade OkHttp dependency to 3.12.8, which fixes a class
`SocketTimeoutException` issues when using HTTP/2 of `SocketTimeoutException` issues when using HTTP/2
([#4078](https://github.com/google/ExoPlayer/issues/4078)). ([#4078](https://github.com/google/ExoPlayer/issues/4078)).
* FLAC extension: Fix handling of bit depths other than 16 in `FLACDecoder`. * 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 This issue caused FLAC streams with other bit depths to sound like white
on earlier releases, but only when embedded in a non-FLAC container such as noise on earlier releases, but only when embedded in a non-FLAC container
Matroska or MP4. such as Matroska or MP4.
* Demo apps: Add * Demo apps: Add
[GL demo app](https://github.com/google/ExoPlayer/tree/dev-v2/demos/gl) to [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. show how to render video to a `GLSurfaceView` while applying a GL shader.

View File

@ -63,6 +63,14 @@ public class DecoderInputBuffer extends Buffer {
/** The buffer's data, or {@code null} if no data has been set. */ /** The buffer's data, or {@code null} if no data has been set. */
@Nullable public ByteBuffer data; @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. * The time at which the sample should be presented.
*/ */
@ -183,6 +191,7 @@ public class DecoderInputBuffer extends Buffer {
if (supplementalData != null) { if (supplementalData != null) {
supplementalData.clear(); supplementalData.clear();
} }
waitingForKeys = false;
} }
private ByteBuffer createReplacementByteBuffer(int requiredCapacity) { private ByteBuffer createReplacementByteBuffer(int requiredCapacity) {

View File

@ -329,7 +329,8 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
if (endUs != C.TIME_END_OF_SOURCE if (endUs != C.TIME_END_OF_SOURCE
&& ((result == C.RESULT_BUFFER_READ && buffer.timeUs >= endUs) && ((result == C.RESULT_BUFFER_READ && buffer.timeUs >= endUs)
|| (result == C.RESULT_NOTHING_READ || (result == C.RESULT_NOTHING_READ
&& getBufferedPositionUs() == C.TIME_END_OF_SOURCE))) { && getBufferedPositionUs() == C.TIME_END_OF_SOURCE
&& !buffer.waitingForKeys))) {
buffer.clear(); buffer.clear();
buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM); buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM);
sentEos = true; sentEos = true;

View File

@ -554,7 +554,7 @@ public class SampleQueue implements TrackOutput {
boolean loadingFinished, boolean loadingFinished,
long decodeOnlyUntilUs, long decodeOnlyUntilUs,
SampleExtrasHolder extrasHolder) { SampleExtrasHolder extrasHolder) {
buffer.waitingForKeys = false;
// This is a temporary fix for https://github.com/google/ExoPlayer/issues/6155. // 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. // TODO: Remove it and replace it with a fix that discards samples when writing to the queue.
boolean hasNextSample; boolean hasNextSample;
@ -588,6 +588,7 @@ public class SampleQueue implements TrackOutput {
} }
if (!mayReadSample(relativeReadIndex)) { if (!mayReadSample(relativeReadIndex)) {
buffer.waitingForKeys = true;
return C.RESULT_NOTHING_READ; return C.RESULT_NOTHING_READ;
} }

View File

@ -368,8 +368,10 @@ public final class SampleQueueTest {
assertReadFormat(/* formatRequired= */ false, FORMAT_ENCRYPTED); assertReadFormat(/* formatRequired= */ false, FORMAT_ENCRYPTED);
assertReadNothing(/* formatRequired= */ false); assertReadNothing(/* formatRequired= */ false);
assertThat(inputBuffer.waitingForKeys).isTrue();
when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED_WITH_KEYS); when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED_WITH_KEYS);
assertReadEncryptedSample(/* sampleIndex= */ 0); assertReadEncryptedSample(/* sampleIndex= */ 0);
assertThat(inputBuffer.waitingForKeys).isFalse();
} }
@Test @Test