mirror of
https://github.com/androidx/media.git
synced 2025-05-06 23:20:42 +08:00
Implement acquirePlaceholderSession in DefaultDrmSessionManager
Issue:#4867 PiperOrigin-RevId: 268497377
This commit is contained in:
parent
f7e9e185f7
commit
143d7d6cca
@ -93,11 +93,13 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto>
|
|||||||
@Nullable private final HashMap<String, String> optionalKeyRequestParameters;
|
@Nullable private final HashMap<String, String> optionalKeyRequestParameters;
|
||||||
private final EventDispatcher<DefaultDrmSessionEventListener> eventDispatcher;
|
private final EventDispatcher<DefaultDrmSessionEventListener> eventDispatcher;
|
||||||
private final boolean multiSession;
|
private final boolean multiSession;
|
||||||
|
private final boolean allowPlaceholderSessions;
|
||||||
private final LoadErrorHandlingPolicy loadErrorHandlingPolicy;
|
private final LoadErrorHandlingPolicy loadErrorHandlingPolicy;
|
||||||
|
|
||||||
private final List<DefaultDrmSession<T>> sessions;
|
private final List<DefaultDrmSession<T>> sessions;
|
||||||
private final List<DefaultDrmSession<T>> provisioningSessions;
|
private final List<DefaultDrmSession<T>> provisioningSessions;
|
||||||
|
|
||||||
|
@Nullable private DefaultDrmSession<T> placeholderDrmSession;
|
||||||
@Nullable private Looper playbackLooper;
|
@Nullable private Looper playbackLooper;
|
||||||
private int mode;
|
private int mode;
|
||||||
@Nullable private byte[] offlineLicenseKeySetId;
|
@Nullable private byte[] offlineLicenseKeySetId;
|
||||||
@ -232,6 +234,7 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto>
|
|||||||
callback,
|
callback,
|
||||||
optionalKeyRequestParameters,
|
optionalKeyRequestParameters,
|
||||||
multiSession,
|
multiSession,
|
||||||
|
/* allowPlaceholderSessions= */ false,
|
||||||
new DefaultLoadErrorHandlingPolicy(initialDrmRequestRetryCount));
|
new DefaultLoadErrorHandlingPolicy(initialDrmRequestRetryCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,6 +244,7 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto>
|
|||||||
MediaDrmCallback callback,
|
MediaDrmCallback callback,
|
||||||
@Nullable HashMap<String, String> optionalKeyRequestParameters,
|
@Nullable HashMap<String, String> optionalKeyRequestParameters,
|
||||||
boolean multiSession,
|
boolean multiSession,
|
||||||
|
boolean allowPlaceholderSessions,
|
||||||
LoadErrorHandlingPolicy loadErrorHandlingPolicy) {
|
LoadErrorHandlingPolicy loadErrorHandlingPolicy) {
|
||||||
Assertions.checkNotNull(uuid);
|
Assertions.checkNotNull(uuid);
|
||||||
Assertions.checkNotNull(mediaDrm);
|
Assertions.checkNotNull(mediaDrm);
|
||||||
@ -251,6 +255,11 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto>
|
|||||||
this.optionalKeyRequestParameters = optionalKeyRequestParameters;
|
this.optionalKeyRequestParameters = optionalKeyRequestParameters;
|
||||||
this.eventDispatcher = new EventDispatcher<>();
|
this.eventDispatcher = new EventDispatcher<>();
|
||||||
this.multiSession = multiSession;
|
this.multiSession = multiSession;
|
||||||
|
boolean canAcquirePlaceholderSessions =
|
||||||
|
!FrameworkMediaCrypto.class.equals(mediaDrm.getExoMediaCryptoType())
|
||||||
|
|| !FrameworkMediaCrypto.WORKAROUND_DEVICE_NEEDS_KEYS_TO_CONFIGURE_CODEC;
|
||||||
|
// TODO: Allow customization once this class has a Builder.
|
||||||
|
this.allowPlaceholderSessions = canAcquirePlaceholderSessions && allowPlaceholderSessions;
|
||||||
this.loadErrorHandlingPolicy = loadErrorHandlingPolicy;
|
this.loadErrorHandlingPolicy = loadErrorHandlingPolicy;
|
||||||
mode = MODE_PLAYBACK;
|
mode = MODE_PLAYBACK;
|
||||||
sessions = new ArrayList<>();
|
sessions = new ArrayList<>();
|
||||||
@ -399,14 +408,25 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DrmSession<T> acquireSession(Looper playbackLooper, DrmInitData drmInitData) {
|
@Nullable
|
||||||
Assertions.checkState(this.playbackLooper == null || this.playbackLooper == playbackLooper);
|
public DrmSession<T> acquirePlaceholderSession(Looper playbackLooper) {
|
||||||
if (sessions.isEmpty()) {
|
if (!allowPlaceholderSessions) {
|
||||||
this.playbackLooper = playbackLooper;
|
return null;
|
||||||
if (mediaDrmHandler == null) {
|
|
||||||
mediaDrmHandler = new MediaDrmHandler(playbackLooper);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
maybeCreateMediaDrmHandler(playbackLooper);
|
||||||
|
if (placeholderDrmSession == null) {
|
||||||
|
DefaultDrmSession<T> placeholderDrmSession =
|
||||||
|
createNewDefaultSession(/* schemeDatas= */ null, /* isPlaceholderSession= */ true);
|
||||||
|
sessions.add(placeholderDrmSession);
|
||||||
|
this.placeholderDrmSession = placeholderDrmSession;
|
||||||
|
}
|
||||||
|
placeholderDrmSession.acquireReference();
|
||||||
|
return placeholderDrmSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DrmSession<T> acquireSession(Looper playbackLooper, DrmInitData drmInitData) {
|
||||||
|
maybeCreateMediaDrmHandler(playbackLooper);
|
||||||
|
|
||||||
List<SchemeData> schemeDatas = null;
|
List<SchemeData> schemeDatas = null;
|
||||||
if (offlineLicenseKeySetId == null) {
|
if (offlineLicenseKeySetId == null) {
|
||||||
@ -434,27 +454,41 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto>
|
|||||||
|
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
// Create a new session.
|
// Create a new session.
|
||||||
session =
|
session = createNewDefaultSession(schemeDatas, /* isPlaceholderSession= */ false);
|
||||||
new DefaultDrmSession<>(
|
|
||||||
uuid,
|
|
||||||
mediaDrm,
|
|
||||||
/* provisioningManager= */ this,
|
|
||||||
/* releaseCallback= */ this::onSessionReleased,
|
|
||||||
schemeDatas,
|
|
||||||
mode,
|
|
||||||
/* isPlaceholderSession= */ false,
|
|
||||||
offlineLicenseKeySetId,
|
|
||||||
optionalKeyRequestParameters,
|
|
||||||
callback,
|
|
||||||
playbackLooper,
|
|
||||||
eventDispatcher,
|
|
||||||
loadErrorHandlingPolicy);
|
|
||||||
sessions.add(session);
|
sessions.add(session);
|
||||||
}
|
}
|
||||||
session.acquireReference();
|
session.acquireReference();
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DefaultDrmSession<T> createNewDefaultSession(
|
||||||
|
@Nullable List<SchemeData> schemeDatas, boolean isPlaceholderSession) {
|
||||||
|
return new DefaultDrmSession<>(
|
||||||
|
uuid,
|
||||||
|
mediaDrm,
|
||||||
|
/* provisioningManager= */ this,
|
||||||
|
/* releaseCallback= */ this::onSessionReleased,
|
||||||
|
schemeDatas,
|
||||||
|
mode,
|
||||||
|
isPlaceholderSession,
|
||||||
|
offlineLicenseKeySetId,
|
||||||
|
optionalKeyRequestParameters,
|
||||||
|
callback,
|
||||||
|
Assertions.checkNotNull(playbackLooper),
|
||||||
|
eventDispatcher,
|
||||||
|
loadErrorHandlingPolicy);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void maybeCreateMediaDrmHandler(Looper playbackLooper) {
|
||||||
|
Assertions.checkState(this.playbackLooper == null || this.playbackLooper == playbackLooper);
|
||||||
|
if (sessions.isEmpty()) {
|
||||||
|
this.playbackLooper = playbackLooper;
|
||||||
|
if (mediaDrmHandler == null) {
|
||||||
|
mediaDrmHandler = new MediaDrmHandler(playbackLooper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public Class<T> getExoMediaCryptoType(DrmInitData drmInitData) {
|
public Class<T> getExoMediaCryptoType(DrmInitData drmInitData) {
|
||||||
@ -496,6 +530,9 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto>
|
|||||||
|
|
||||||
private void onSessionReleased(DefaultDrmSession<T> drmSession) {
|
private void onSessionReleased(DefaultDrmSession<T> drmSession) {
|
||||||
sessions.remove(drmSession);
|
sessions.remove(drmSession);
|
||||||
|
if (placeholderDrmSession == drmSession) {
|
||||||
|
placeholderDrmSession = null;
|
||||||
|
}
|
||||||
if (provisioningSessions.size() > 1 && provisioningSessions.get(0) == drmSession) {
|
if (provisioningSessions.size() > 1 && provisioningSessions.get(0) == drmSession) {
|
||||||
// Other sessions were waiting for the released session to complete a provision operation.
|
// Other sessions were waiting for the released session to complete a provision operation.
|
||||||
// We need to have one of those sessions perform the provision operation instead.
|
// We need to have one of those sessions perform the provision operation instead.
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package com.google.android.exoplayer2.drm;
|
package com.google.android.exoplayer2.drm;
|
||||||
|
|
||||||
import android.media.MediaCrypto;
|
import android.media.MediaCrypto;
|
||||||
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -24,6 +25,15 @@ import java.util.UUID;
|
|||||||
*/
|
*/
|
||||||
public final class FrameworkMediaCrypto implements ExoMediaCrypto {
|
public final class FrameworkMediaCrypto implements ExoMediaCrypto {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the device needs keys to have been loaded into the {@link DrmSession} before codec
|
||||||
|
* configuration.
|
||||||
|
*/
|
||||||
|
public static final boolean WORKAROUND_DEVICE_NEEDS_KEYS_TO_CONFIGURE_CODEC =
|
||||||
|
"Amazon".equals(Util.MANUFACTURER)
|
||||||
|
&& ("AFTM".equals(Util.MODEL) // Fire TV Stick Gen 1
|
||||||
|
|| "AFTB".equals(Util.MODEL)); // Fire TV Gen 1
|
||||||
|
|
||||||
/** The DRM scheme UUID. */
|
/** The DRM scheme UUID. */
|
||||||
public final UUID uuid;
|
public final UUID uuid;
|
||||||
/** The DRM session id. */
|
/** The DRM session id. */
|
||||||
|
@ -521,7 +521,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
&& mediaCrypto.requiresSecureDecoderComponent(mimeType);
|
&& mediaCrypto.requiresSecureDecoderComponent(mimeType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (deviceNeedsDrmKeysToConfigureCodecWorkaround()) {
|
if (FrameworkMediaCrypto.WORKAROUND_DEVICE_NEEDS_KEYS_TO_CONFIGURE_CODEC) {
|
||||||
@DrmSession.State int drmSessionState = codecDrmSession.getState();
|
@DrmSession.State int drmSessionState = codecDrmSession.getState();
|
||||||
if (drmSessionState == DrmSession.STATE_ERROR) {
|
if (drmSessionState == DrmSession.STATE_ERROR) {
|
||||||
throw ExoPlaybackException.createForRenderer(codecDrmSession.getError(), getIndex());
|
throw ExoPlaybackException.createForRenderer(codecDrmSession.getError(), getIndex());
|
||||||
@ -1754,16 +1754,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
return error instanceof MediaCodec.CodecException;
|
return error instanceof MediaCodec.CodecException;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the device needs keys to have been loaded into the {@link DrmSession} before
|
|
||||||
* codec configuration.
|
|
||||||
*/
|
|
||||||
private boolean deviceNeedsDrmKeysToConfigureCodecWorkaround() {
|
|
||||||
return "Amazon".equals(Util.MANUFACTURER)
|
|
||||||
&& ("AFTM".equals(Util.MODEL) // Fire TV Stick Gen 1
|
|
||||||
|| "AFTB".equals(Util.MODEL)); // Fire TV Gen 1
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the decoder is known to fail when flushed.
|
* Returns whether the decoder is known to fail when flushed.
|
||||||
* <p>
|
* <p>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user