diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 7d1191199c..0b81f1bdb4 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -32,6 +32,11 @@ * Fix a bug with playback of ads in playlists, where the incorrect period index was used when deciding whether to trigger playback of an ad after a seek. +* DRM: + * Only dispatch DRM session acquire and release events once per period + when playing content that uses the same encryption keys for both audio & + video tracks (previously separate acquire and release events were + dispatched for each track in each period). * VP9 extension: Update to use NDK r22 ([#8581](https://github.com/google/ExoPlayer/issues/8581)). * FLAC extension: Update to use NDK r22 diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/CopyOnWriteMultiset.java b/library/common/src/main/java/com/google/android/exoplayer2/util/CopyOnWriteMultiset.java index 505ff55cbe..c473e2206b 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/CopyOnWriteMultiset.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/CopyOnWriteMultiset.java @@ -138,4 +138,11 @@ public final class CopyOnWriteMultiset implements Iterable return elements.iterator(); } } + + /** Returns the number of occurrences of an element in this multiset. */ + public int count(E element) { + synchronized (lock) { + return elementCounts.containsKey(element) ? elementCounts.get(element) : 0; + } + } } diff --git a/library/common/src/test/java/com/google/android/exoplayer2/util/CopyOnWriteMultisetTest.java b/library/common/src/test/java/com/google/android/exoplayer2/util/CopyOnWriteMultisetTest.java index 92e4124a6a..edbb2047bc 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/util/CopyOnWriteMultisetTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/util/CopyOnWriteMultisetTest.java @@ -107,4 +107,14 @@ public final class CopyOnWriteMultisetTest { assertThrows(UnsupportedOperationException.class, () -> elementSet.remove("a string")); } + + @Test + public void count() { + CopyOnWriteMultiset multiset = new CopyOnWriteMultiset<>(); + multiset.add("a string"); + multiset.add("a string"); + + assertThat(multiset.count("a string")).isEqualTo(2); + assertThat(multiset.count("another string")).isEqualTo(0); + } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSession.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSession.java index 2f27ad8c08..13423a412a 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSession.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSession.java @@ -293,8 +293,11 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; if (openInternal(true)) { doLicense(true); } - } else if (eventDispatcher != null && isOpen()) { - // If the session is already open then send the acquire event only to the provided dispatcher. + } else if (eventDispatcher != null + && isOpen() + && eventDispatchers.count(eventDispatcher) == 1) { + // If the session is already open and this is the first instance of eventDispatcher we've + // seen, then send the acquire event only to the provided dispatcher. // TODO: Add a parameter to onDrmSessionAcquired to indicate whether the session is being // re-used or not. eventDispatcher.drmSessionAcquired(); @@ -323,9 +326,11 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; } } if (eventDispatcher != null) { - // Acquire and release events are only sent to the provided dispatcher. - eventDispatcher.drmSessionReleased(); eventDispatchers.remove(eventDispatcher); + if (eventDispatchers.count(eventDispatcher) == 0) { + // Release events are only sent to the last-attached instance of each EventDispatcher. + eventDispatcher.drmSessionReleased(); + } } referenceCountListener.onReferenceCountDecremented(this, referenceCount); }