De-duplicate DRM acquire & release events by EventDispatcher

When we add DRM pre-acquire support to SampleQueue, we'll dispatch
twice the number of acquire and release events. This is slightly
confusing, since there's the same number of
DrmSessionManager#acquireSession() calls.

We can mitigate this by only dispatching each acquire and release
event to at most one EventDispatcher.

This also changes the events fired when playing a stream with both audio
and video encrypted with the same keys (even without pre-acquisition).

Before: The EventDispatcher would see 2 aquires, 1 key load and 2
release events.

After: The EventDispatcher will see 1 acquire, 1 key load and 1 release.
PiperOrigin-RevId: 358804502
This commit is contained in:
ibaker 2021-02-22 14:17:07 +00:00 committed by marcbaechinger
parent 0eed19d8a3
commit 623597addb
4 changed files with 31 additions and 4 deletions

View File

@ -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

View File

@ -138,4 +138,11 @@ public final class CopyOnWriteMultiset<E extends Object> implements Iterable<E>
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;
}
}
}

View File

@ -107,4 +107,14 @@ public final class CopyOnWriteMultisetTest {
assertThrows(UnsupportedOperationException.class, () -> elementSet.remove("a string"));
}
@Test
public void count() {
CopyOnWriteMultiset<String> 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);
}
}

View File

@ -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);
}