mirror of
https://github.com/androidx/media.git
synced 2025-05-16 03:59:54 +08:00
Cache the last DrmSessionManager instance inside the default provider
Without this a new manager is instantiated for every item in a playlist, meaning the impact of caching improvements to DefaultDrmSessionManager are reduced (since the cache doesn't persist across playlist items). With this change, playlists of items with identical DRM config will use the same manager instance (and thus share existing sessions). Issue: #8523 #minor-release PiperOrigin-RevId: 356690852
This commit is contained in:
parent
753bccec1f
commit
a062075462
@ -20,6 +20,10 @@
|
||||
instead.
|
||||
* Remove `extension-jobdispatcher` module. Use the `extension-workmanager`
|
||||
module instead.
|
||||
* DRM:
|
||||
* Re-use the previous `DrmSessionManager` instance when playing a playlist
|
||||
(if possible)
|
||||
([#8523](https://github.com/google/ExoPlayer/issues/8523)).
|
||||
|
||||
### 2.13.0 (2021-02-04)
|
||||
|
||||
|
@ -16,23 +16,39 @@
|
||||
package com.google.android.exoplayer2.drm;
|
||||
|
||||
import static com.google.android.exoplayer2.drm.DefaultDrmSessionManager.MODE_PLAYBACK;
|
||||
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
|
||||
|
||||
import androidx.annotation.GuardedBy;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import com.google.android.exoplayer2.MediaItem;
|
||||
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
|
||||
import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
|
||||
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import com.google.common.primitives.Ints;
|
||||
import java.util.Map;
|
||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
/** Default implementation of {@link DrmSessionManagerProvider}. */
|
||||
@RequiresApi(18)
|
||||
public final class DefaultDrmSessionManagerProvider implements DrmSessionManagerProvider {
|
||||
|
||||
private final Object lock;
|
||||
|
||||
@GuardedBy("lock")
|
||||
private MediaItem.@MonotonicNonNull DrmConfiguration drmConfiguration;
|
||||
|
||||
@GuardedBy("lock")
|
||||
private @MonotonicNonNull DrmSessionManager manager;
|
||||
|
||||
@Nullable private HttpDataSource.Factory drmHttpDataSourceFactory;
|
||||
@Nullable private String userAgent;
|
||||
|
||||
public DefaultDrmSessionManagerProvider() {
|
||||
lock = new Object();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link HttpDataSource.Factory} to be used for creating {@link HttpMediaDrmCallback
|
||||
* HttpMediaDrmCallbacks} which executes key and provisioning requests over HTTP. If {@code null}
|
||||
@ -60,12 +76,23 @@ public final class DefaultDrmSessionManagerProvider implements DrmSessionManager
|
||||
|
||||
@Override
|
||||
public DrmSessionManager get(MediaItem mediaItem) {
|
||||
Assertions.checkNotNull(mediaItem.playbackProperties);
|
||||
checkNotNull(mediaItem.playbackProperties);
|
||||
@Nullable
|
||||
MediaItem.DrmConfiguration drmConfiguration = mediaItem.playbackProperties.drmConfiguration;
|
||||
if (drmConfiguration == null || Util.SDK_INT < 18) {
|
||||
return DrmSessionManager.DRM_UNSUPPORTED;
|
||||
}
|
||||
|
||||
synchronized (lock) {
|
||||
if (!Util.areEqual(drmConfiguration, this.drmConfiguration)) {
|
||||
this.drmConfiguration = drmConfiguration;
|
||||
this.manager = createManager(drmConfiguration);
|
||||
}
|
||||
return checkNotNull(this.manager);
|
||||
}
|
||||
}
|
||||
|
||||
private DrmSessionManager createManager(MediaItem.DrmConfiguration drmConfiguration) {
|
||||
HttpDataSource.Factory dataSourceFactory =
|
||||
drmHttpDataSourceFactory != null
|
||||
? drmHttpDataSourceFactory
|
||||
|
@ -51,4 +51,39 @@ public class DefaultDrmSessionManagerProviderTest {
|
||||
|
||||
assertThat(drmSessionManager).isNotEqualTo(DrmSessionManager.DRM_UNSUPPORTED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void create_reusesCachedInstanceWherePossible() {
|
||||
MediaItem mediaItem1 =
|
||||
new MediaItem.Builder()
|
||||
.setUri("https://example.test/content-1")
|
||||
.setDrmUuid(C.WIDEVINE_UUID)
|
||||
.build();
|
||||
// Same DRM info as item1, but different URL to check it doesn't prevent re-using a manager.
|
||||
MediaItem mediaItem2 =
|
||||
new MediaItem.Builder()
|
||||
.setUri("https://example.test/content-2")
|
||||
.setDrmUuid(C.WIDEVINE_UUID)
|
||||
.build();
|
||||
// Different DRM info to 1 and 2, needs a different manager instance.
|
||||
MediaItem mediaItem3 =
|
||||
new MediaItem.Builder()
|
||||
.setUri("https://example.test/content-3")
|
||||
.setDrmUuid(C.WIDEVINE_UUID)
|
||||
.setDrmLicenseUri("https://example.test/license")
|
||||
.build();
|
||||
|
||||
DefaultDrmSessionManagerProvider provider = new DefaultDrmSessionManagerProvider();
|
||||
DrmSessionManager drmSessionManager1 = provider.get(mediaItem1);
|
||||
DrmSessionManager drmSessionManager2 = provider.get(mediaItem2);
|
||||
DrmSessionManager drmSessionManager3 = provider.get(mediaItem3);
|
||||
|
||||
// Get a manager for the first item again - expect it to be a different instance to last time
|
||||
// since we only cache one.
|
||||
DrmSessionManager drmSessionManager4 = provider.get(mediaItem1);
|
||||
|
||||
assertThat(drmSessionManager1).isSameInstanceAs(drmSessionManager2);
|
||||
assertThat(drmSessionManager1).isNotSameInstanceAs(drmSessionManager3);
|
||||
assertThat(drmSessionManager1).isNotSameInstanceAs(drmSessionManager4);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user