use of androidx.media3.exoplayer.drm.DrmSession in project media by androidx.
the class MediaCodecRenderer method drmNeedsCodecReinitialization.
/**
* Returns whether it's necessary to re-initialize the codec to handle a DRM change. If {@code
* false} is returned then either {@code oldSession == newSession} (i.e., there was no change), or
* it's possible to update the existing codec using MediaCrypto.setMediaDrmSession.
*/
private boolean drmNeedsCodecReinitialization(MediaCodecInfo codecInfo, Format newFormat, @Nullable DrmSession oldSession, @Nullable DrmSession newSession) throws ExoPlaybackException {
if (oldSession == newSession) {
// No need to re-initialize if the old and new sessions are the same.
return false;
}
if (newSession == null || oldSession == null) {
// Changing from DRM to no DRM and vice-versa always requires re-initialization.
return true;
}
if (Util.SDK_INT < 23) {
// required to switch to newSession on older API levels.
return true;
}
if (C.PLAYREADY_UUID.equals(oldSession.getSchemeUuid()) || C.PLAYREADY_UUID.equals(newSession.getSchemeUuid())) {
// TODO: Add an API check once [Internal ref: b/128835874] is fixed.
return true;
}
@Nullable FrameworkCryptoConfig newCryptoConfig = getFrameworkCryptoConfig(newSession);
if (newCryptoConfig == null) {
// the case is to occur, so we re-initialize in this case.
return true;
}
boolean requiresSecureDecoder;
if (newCryptoConfig.forceAllowInsecureDecoderComponents) {
requiresSecureDecoder = false;
} else {
requiresSecureDecoder = newSession.requiresSecureDecoder(newFormat.sampleMimeType);
}
if (!codecInfo.secure && requiresSecureDecoder) {
// output path.
return true;
}
return false;
}
use of androidx.media3.exoplayer.drm.DrmSession in project media by androidx.
the class OfflineLicenseHelper method blockingKeyRequest.
private byte[] blockingKeyRequest(@Mode int licenseMode, @Nullable byte[] offlineLicenseKeySetId, Format format) throws DrmSessionException {
drmSessionManager.setPlayer(handlerThread.getLooper(), PlayerId.UNSET);
drmSessionManager.prepare();
DrmSession drmSession = openBlockingKeyRequest(licenseMode, offlineLicenseKeySetId, format);
DrmSessionException error = drmSession.getError();
byte[] keySetId = drmSession.getOfflineLicenseKeySetId();
drmSession.release(eventDispatcher);
drmSessionManager.release();
if (error != null) {
throw error;
}
return Assertions.checkNotNull(keySetId);
}
use of androidx.media3.exoplayer.drm.DrmSession in project media by androidx.
the class DefaultAnalyticsCollectorTest method drmEvents_periodsWithSameDrmData_keysReusedButLoadEventReportedTwice.
@Test
public void drmEvents_periodsWithSameDrmData_keysReusedButLoadEventReportedTwice() throws Exception {
BlockingDrmCallback mediaDrmCallback = BlockingDrmCallback.returnsEmpty();
DrmSessionManager blockingDrmSessionManager = new DefaultDrmSessionManager.Builder().setUuidAndExoMediaDrmProvider(DRM_SCHEME_UUID, uuid -> new FakeExoMediaDrm.Builder().setEnforceValidKeyResponses(false).build()).setMultiSession(true).build(mediaDrmCallback);
MediaSource mediaSource = new ConcatenatingMediaSource(new FakeMediaSource(SINGLE_PERIOD_TIMELINE, blockingDrmSessionManager, VIDEO_FORMAT_DRM_1), new FakeMediaSource(SINGLE_PERIOD_TIMELINE, blockingDrmSessionManager, VIDEO_FORMAT_DRM_1));
TestAnalyticsListener listener = runAnalyticsTest(mediaSource, // already preacquired by the time the key load completes).
new ActionSchedule.Builder(TAG).waitForIsLoading(false).waitForIsLoading(true).waitForIsLoading(false).executeRunnable(mediaDrmCallback.keyCondition::open).build());
populateEventIds(listener.lastReportedTimeline);
assertThat(listener.getEvents(EVENT_DRM_SESSION_MANAGER_ERROR)).isEmpty();
assertThat(listener.getEvents(EVENT_DRM_SESSION_ACQUIRED)).containsExactly(period0, period1).inOrder();
// This includes both period0 and period1 because period1's DrmSession was preacquired before
// the key load completed. There's only one key load (a second would block forever). We can't
// assume the order these events will arrive in because it depends on the iteration order of a
// HashSet of EventDispatchers inside DefaultDrmSession.
assertThat(listener.getEvents(EVENT_DRM_KEYS_LOADED)).containsExactly(period0, period1);
// The period1 release event is lost because it's posted to "ExoPlayerTest thread" after that
// thread has been quit during clean-up.
assertThat(listener.getEvents(EVENT_DRM_SESSION_RELEASED)).containsExactly(period0);
}
use of androidx.media3.exoplayer.drm.DrmSession in project media by androidx.
the class DefaultDrmSessionManager method acquireSession.
// Must be called on the playback thread.
@Nullable
private DrmSession acquireSession(Looper playbackLooper, @Nullable DrmSessionEventListener.EventDispatcher eventDispatcher, Format format, boolean shouldReleasePreacquiredSessionsBeforeRetrying) {
maybeCreateMediaDrmHandler(playbackLooper);
if (format.drmInitData == null) {
// Content is not encrypted.
return maybeAcquirePlaceholderSession(MimeTypes.getTrackType(format.sampleMimeType), shouldReleasePreacquiredSessionsBeforeRetrying);
}
@Nullable List<SchemeData> schemeDatas = null;
if (offlineLicenseKeySetId == null) {
schemeDatas = getSchemeDatas(checkNotNull(format.drmInitData), uuid, false);
if (schemeDatas.isEmpty()) {
final MissingSchemeDataException error = new MissingSchemeDataException(uuid);
Log.e(TAG, "DRM error", error);
if (eventDispatcher != null) {
eventDispatcher.drmSessionManagerError(error);
}
return new ErrorStateDrmSession(new DrmSessionException(error, PlaybackException.ERROR_CODE_DRM_CONTENT_ERROR));
}
}
@Nullable DefaultDrmSession session;
if (!multiSession) {
session = noMultiSessionDrmSession;
} else {
// Only use an existing session if it has matching init data.
session = null;
for (DefaultDrmSession existingSession : sessions) {
if (Util.areEqual(existingSession.schemeDatas, schemeDatas)) {
session = existingSession;
break;
}
}
}
if (session == null) {
// Create a new session.
session = createAndAcquireSessionWithRetry(schemeDatas, /* isPlaceholderSession= */
false, eventDispatcher, shouldReleasePreacquiredSessionsBeforeRetrying);
if (!multiSession) {
noMultiSessionDrmSession = session;
}
sessions.add(session);
} else {
session.acquire(eventDispatcher);
}
return session;
}
use of androidx.media3.exoplayer.drm.DrmSession in project media by androidx.
the class DefaultDrmSessionManagerTest method managerRelease_keepaliveDisabled_doesntReleaseAnySessions.
@Test(timeout = 10_000)
public void managerRelease_keepaliveDisabled_doesntReleaseAnySessions() throws Exception {
FakeExoMediaDrm.LicenseServer licenseServer = FakeExoMediaDrm.LicenseServer.allowingSchemeDatas(DRM_SCHEME_DATAS);
DrmSessionManager drmSessionManager = new DefaultDrmSessionManager.Builder().setUuidAndExoMediaDrmProvider(DRM_SCHEME_UUID, uuid -> new FakeExoMediaDrm()).setSessionKeepaliveMs(C.TIME_UNSET).build(/* mediaDrmCallback= */
licenseServer);
drmSessionManager.prepare();
drmSessionManager.setPlayer(/* playbackLooper= */
Looper.myLooper(), PlayerId.UNSET);
DrmSession drmSession = checkNotNull(drmSessionManager.acquireSession(/* eventDispatcher= */
null, FORMAT_WITH_DRM_INIT_DATA));
waitForOpenedWithKeys(drmSession);
assertThat(drmSession.getState()).isEqualTo(DrmSession.STATE_OPENED_WITH_KEYS);
// Release the manager, the session should still be open (though it's unusable because
// the underlying ExoMediaDrm is released).
drmSessionManager.release();
assertThat(drmSession.getState()).isEqualTo(DrmSession.STATE_OPENED_WITH_KEYS);
}
Aggregations