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,44 +112,47 @@
### 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
[WAKE_LOCK](https://developer.android.com/reference/android/Manifest.permission.html#WAKE_LOCK) feature, you must add the
permission to your application's manifest file. [WAKE_LOCK](https://developer.android.com/reference/android/Manifest.permission.html#WAKE_LOCK)
* Text: permission to your application's manifest file.
* Catch and log exceptions in `TextRenderer` rather than re-throwing. This * Text:
allows playback to continue even if subtitle decoding fails * Catch and log exceptions in `TextRenderer` rather than re-throwing. This
([#6885](https://github.com/google/ExoPlayer/issues/6885)). allows playback to continue even if subtitle decoding fails
* Allow missing hours and milliseconds in SubRip (.srt) timecodes ([#6885](https://github.com/google/ExoPlayer/issues/6885)).
([#7122](https://github.com/google/ExoPlayer/issues/7122)). * Allow missing hours and milliseconds in SubRip (.srt) timecodes
* Audio: ([#7122](https://github.com/google/ExoPlayer/issues/7122)).
* Workaround issue that could cause slower than realtime playback of AAC on * Audio:
Android 10 ([#6671](https://github.com/google/ExoPlayer/issues/6671). * Workaround issue that could cause slower than realtime playback of AAC
* Enable playback speed adjustment and silence skipping for floating point PCM on Android 10 ([#6671](https://github.com/google/ExoPlayer/issues/6671).
audio, via resampling to 16-bit integer PCM. To output the original floating * Enable playback speed adjustment and silence skipping for floating point
point audio without adjustment, pass `enableFloatOutput=true` to the PCM audio, via resampling to 16-bit integer PCM. To output the original
`DefaultAudioSink` constructor floating point audio without adjustment, pass `enableFloatOutput=true`
([#7134](https://github.com/google/ExoPlayer/issues/7134)). to the `DefaultAudioSink` constructor
* Fix playback of WAV files with trailing non-media bytes ([#7134](https://github.com/google/ExoPlayer/issues/7134)).
([#7129](https://github.com/google/ExoPlayer/issues/7129)). * Fix playback of WAV files with trailing non-media bytes
* Fix playback of ADTS files with mid-stream ID3 metadata. ([#7129](https://github.com/google/ExoPlayer/issues/7129)).
* DRM: * Fix playback of ADTS files with mid-stream ID3 metadata.
* Fix playback of Widevine protected content that only provides V1 PSSH atoms * DRM:
on API levels 21 and 22. * Fix playback of Widevine protected content that only provides V1 PSSH
* Fix playback of PlayReady content on Fire TV Stick (Gen 2). atoms on API levels 21 and 22.
* DASH: * Fix playback of PlayReady content on Fire TV Stick (Gen 2).
* Update the manifest URI to avoid repeated HTTP redirects * Fix stuck ad playbacks with DRM protected content
([#6907](https://github.com/google/ExoPlayer/issues/6907)). ([#7188](https://github.com/google/ExoPlayer/issues/7188)).
* Parse period `AssetIdentifier` elements. * DASH:
* UI: Add an option to set whether to use the orientation sensor for rotation * Update the manifest URI to avoid repeated HTTP redirects
in spherical playbacks ([#6907](https://github.com/google/ExoPlayer/issues/6907)).
([#6761](https://github.com/google/ExoPlayer/issues/6761)). * Parse period `AssetIdentifier` elements.
* Analytics: Fix `PlaybackStatsListener` behavior when not keeping history * UI: Add an option to set whether to use the orientation sensor for rotation
([#7160](https://github.com/google/ExoPlayer/issues/7160)). in spherical playbacks
* FFmpeg extension: Add support for `x86_64` architecture. ([#6761](https://github.com/google/ExoPlayer/issues/6761)).
* Opus extension: Fix parsing of negative gain values * Analytics: Fix `PlaybackStatsListener` behavior when not keeping history
([#7046](https://github.com/google/ExoPlayer/issues/7046)). ([#7160](https://github.com/google/ExoPlayer/issues/7160)).
* FFmpeg extension: Add support for `x86_64` architecture.
* Opus extension: Fix parsing of negative gain values
([#7046](https://github.com/google/ExoPlayer/issues/7046)).
### 2.11.3 (2020-02-19) ### ### 2.11.3 (2020-02-19) ###
@ -161,63 +164,63 @@
### 2.11.2 (2020-02-13) ### ### 2.11.2 (2020-02-13) ###
* 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
of the current window of the current window
([#6552](https://github.com/google/ExoPlayer/issues/6552)). ([#6552](https://github.com/google/ExoPlayer/issues/6552)).
* Don't use notification chronometer if playback speed is != 1.0 * Don't use notification chronometer if playback speed is != 1.0
([#6816](https://github.com/google/ExoPlayer/issues/6816)). ([#6816](https://github.com/google/ExoPlayer/issues/6816)).
* HLS: Fix playback of DRM protected content that uses key rotation * HLS: Fix playback of DRM protected content that uses key rotation
([#6903](https://github.com/google/ExoPlayer/issues/6903)). ([#6903](https://github.com/google/ExoPlayer/issues/6903)).
* WAV: * WAV:
* Support IMA ADPCM encoded data. * Support IMA ADPCM encoded data.
* Improve support for G.711 A-law and mu-law encoded data. * Improve support for G.711 A-law and mu-law encoded data.
* MP4: Support "twos" codec (big endian PCM) * MP4: Support "twos" codec (big endian PCM)
([#5789](https://github.com/google/ExoPlayer/issues/5789)). ([#5789](https://github.com/google/ExoPlayer/issues/5789)).
* FMP4: Add support for encrypted AC-4 tracks. * FMP4: Add support for encrypted AC-4 tracks.
* HLS: Fix slow seeking into long MP3 segments * HLS: Fix slow seeking into long MP3 segments
([#6155](https://github.com/google/ExoPlayer/issues/6155)). ([#6155](https://github.com/google/ExoPlayer/issues/6155)).
* Fix handling of E-AC-3 streams that contain AC-3 syncframes * Fix handling of E-AC-3 streams that contain AC-3 syncframes
([#6602](https://github.com/google/ExoPlayer/issues/6602)). ([#6602](https://github.com/google/ExoPlayer/issues/6602)).
* Fix playback of TrueHD streams in Matroska * Fix playback of TrueHD streams in Matroska
([#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.
([#6920](https://github.com/google/ExoPlayer/issues/6920)). ([#6920](https://github.com/google/ExoPlayer/issues/6920)).
### 2.11.1 (2019-12-20) ### ### 2.11.1 (2019-12-20) ###

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