Remove DrmSessionManager.acquirePlaceholderSession

In order to acquire a placeholder session, clients can call acquireSession
with a format with a null drmInitData.

PiperOrigin-RevId: 327220249
This commit is contained in:
aquilescanta 2020-08-18 15:00:45 +01:00 committed by Oliver Woodman
parent be98509e03
commit 41e6577dca
6 changed files with 108 additions and 99 deletions

View File

@ -409,7 +409,7 @@ public class DefaultDrmSessionManager implements DrmSessionManager {
/** /**
* Sets the mode, which determines the role of sessions acquired from the instance. This must be * Sets the mode, which determines the role of sessions acquired from the instance. This must be
* called before {@link #acquireSession(Looper, DrmSessionEventListener.EventDispatcher, Format)} * called before {@link #acquireSession(Looper, DrmSessionEventListener.EventDispatcher, Format)}
* or {@link #acquirePlaceholderSession} is called. * is called.
* *
* <p>By default, the mode is {@link #MODE_PLAYBACK} and a streaming license is requested when * <p>By default, the mode is {@link #MODE_PLAYBACK} and a streaming license is requested when
* required. * required.
@ -469,34 +469,6 @@ public class DefaultDrmSessionManager implements DrmSessionManager {
@Override @Override
@Nullable @Nullable
public DrmSession acquirePlaceholderSession(Looper playbackLooper, int trackType) {
initPlaybackLooper(playbackLooper);
ExoMediaDrm exoMediaDrm = Assertions.checkNotNull(this.exoMediaDrm);
boolean avoidPlaceholderDrmSessions =
FrameworkMediaCrypto.class.equals(exoMediaDrm.getExoMediaCryptoType())
&& FrameworkMediaCrypto.WORKAROUND_DEVICE_NEEDS_KEYS_TO_CONFIGURE_CODEC;
// Avoid attaching a session to sparse formats.
if (avoidPlaceholderDrmSessions
|| Util.linearSearch(useDrmSessionsForClearContentTrackTypes, trackType) == C.INDEX_UNSET
|| exoMediaDrm.getExoMediaCryptoType() == null) {
return null;
}
maybeCreateMediaDrmHandler(playbackLooper);
if (placeholderDrmSession == null) {
DefaultDrmSession placeholderDrmSession =
createAndAcquireSessionWithRetry(
/* schemeDatas= */ ImmutableList.of(),
/* isPlaceholderSession= */ true,
/* eventDispatcher= */ null);
sessions.add(placeholderDrmSession);
this.placeholderDrmSession = placeholderDrmSession;
} else {
placeholderDrmSession.acquire(/* eventDispatcher= */ null);
}
return placeholderDrmSession;
}
@Override
public DrmSession acquireSession( public DrmSession acquireSession(
Looper playbackLooper, Looper playbackLooper,
@Nullable DrmSessionEventListener.EventDispatcher eventDispatcher, @Nullable DrmSessionEventListener.EventDispatcher eventDispatcher,
@ -504,6 +476,11 @@ public class DefaultDrmSessionManager implements DrmSessionManager {
initPlaybackLooper(playbackLooper); initPlaybackLooper(playbackLooper);
maybeCreateMediaDrmHandler(playbackLooper); maybeCreateMediaDrmHandler(playbackLooper);
if (format.drmInitData == null) {
// Content is not encrypted.
return maybeAcquirePlaceholderSession(MimeTypes.getTrackType(format.sampleMimeType));
}
@Nullable List<SchemeData> schemeDatas = null; @Nullable List<SchemeData> schemeDatas = null;
if (offlineLicenseKeySetId == null) { if (offlineLicenseKeySetId == null) {
schemeDatas = getSchemeDatas(Assertions.checkNotNull(format.drmInitData), uuid, false); schemeDatas = getSchemeDatas(Assertions.checkNotNull(format.drmInitData), uuid, false);
@ -565,6 +542,32 @@ public class DefaultDrmSessionManager implements DrmSessionManager {
// Internal methods. // Internal methods.
@Nullable
private DrmSession maybeAcquirePlaceholderSession(int trackType) {
ExoMediaDrm exoMediaDrm = Assertions.checkNotNull(this.exoMediaDrm);
boolean avoidPlaceholderDrmSessions =
FrameworkMediaCrypto.class.equals(exoMediaDrm.getExoMediaCryptoType())
&& FrameworkMediaCrypto.WORKAROUND_DEVICE_NEEDS_KEYS_TO_CONFIGURE_CODEC;
// Avoid attaching a session to sparse formats.
if (avoidPlaceholderDrmSessions
|| Util.linearSearch(useDrmSessionsForClearContentTrackTypes, trackType) == C.INDEX_UNSET
|| exoMediaDrm.getExoMediaCryptoType() == null) {
return null;
}
if (placeholderDrmSession == null) {
DefaultDrmSession placeholderDrmSession =
createAndAcquireSessionWithRetry(
/* schemeDatas= */ ImmutableList.of(),
/* isPlaceholderSession= */ true,
/* eventDispatcher= */ null);
sessions.add(placeholderDrmSession);
this.placeholderDrmSession = placeholderDrmSession;
} else {
placeholderDrmSession.acquire(/* eventDispatcher= */ null);
}
return placeholderDrmSession;
}
private boolean canAcquireSession(DrmInitData drmInitData) { private boolean canAcquireSession(DrmInitData drmInitData) {
if (offlineLicenseKeySetId != null) { if (offlineLicenseKeySetId != null) {
// An offline license can be restored so a session can always be acquired. // An offline license can be restored so a session can always be acquired.

View File

@ -17,7 +17,6 @@ package com.google.android.exoplayer2.drm;
import android.os.Looper; import android.os.Looper;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
/** Manages a DRM session. */ /** Manages a DRM session. */
@ -33,13 +32,19 @@ public interface DrmSessionManager {
new DrmSessionManager() { new DrmSessionManager() {
@Override @Override
@Nullable
public DrmSession acquireSession( public DrmSession acquireSession(
Looper playbackLooper, Looper playbackLooper,
@Nullable DrmSessionEventListener.EventDispatcher eventDispatcher, @Nullable DrmSessionEventListener.EventDispatcher eventDispatcher,
Format format) { Format format) {
if (format.drmInitData == null) {
return null;
} else {
return new ErrorStateDrmSession( return new ErrorStateDrmSession(
new DrmSession.DrmSessionException( new DrmSession.DrmSessionException(
new UnsupportedDrmException(UnsupportedDrmException.REASON_UNSUPPORTED_SCHEME))); new UnsupportedDrmException(
UnsupportedDrmException.REASON_UNSUPPORTED_SCHEME)));
}
} }
@Override @Override
@ -64,39 +69,27 @@ public interface DrmSessionManager {
// Do nothing. // Do nothing.
} }
/**
* Returns a {@link DrmSession} that does not execute key requests, with an incremented reference
* count. When the caller no longer needs to use the instance, it must call {@link
* DrmSession#release(DrmSessionEventListener.EventDispatcher)} to decrement the reference count.
*
* <p>Placeholder {@link DrmSession DrmSessions} may be used to configure secure decoders for
* playback of clear content periods. This can reduce the cost of transitioning between clear and
* encrypted content periods.
*
* @param playbackLooper The looper associated with the media playback thread.
* @param trackType The type of the track to acquire a placeholder session for. Must be one of the
* {@link C}{@code .TRACK_TYPE_*} constants.
* @return The placeholder DRM session, or null if this DRM session manager does not support
* placeholder sessions.
*/
@Nullable
default DrmSession acquirePlaceholderSession(Looper playbackLooper, int trackType) {
return null;
}
/** /**
* Returns a {@link DrmSession} for the specified {@link Format}, with an incremented reference * Returns a {@link DrmSession} for the specified {@link Format}, with an incremented reference
* count. When the caller no longer needs to use the instance, it must call {@link * count. May return null if the {@link Format#drmInitData} is null and the DRM session manager is
* not configured to attach a {@link DrmSession} to clear content. When the caller no longer needs
* to use a returned {@link DrmSession}, it must call {@link
* DrmSession#release(DrmSessionEventListener.EventDispatcher)} to decrement the reference count. * DrmSession#release(DrmSessionEventListener.EventDispatcher)} to decrement the reference count.
* *
* <p>If the provided {@link Format} contains a null {@link Format#drmInitData}, the returned
* {@link DrmSession} (if not null) will be a placeholder session which does not execute key
* requests, and cannot be used to handle encrypted content. However, a placeholder session may be
* used to configure secure decoders for playback of clear content periods, which can reduce the
* cost of transitioning between clear and encrypted content.
*
* @param playbackLooper The looper associated with the media playback thread. * @param playbackLooper The looper associated with the media playback thread.
* @param eventDispatcher The {@link DrmSessionEventListener.EventDispatcher} used to distribute * @param eventDispatcher The {@link DrmSessionEventListener.EventDispatcher} used to distribute
* events, and passed on to {@link * events, and passed on to {@link
* DrmSession#acquire(DrmSessionEventListener.EventDispatcher)}. * DrmSession#acquire(DrmSessionEventListener.EventDispatcher)}.
* @param format The {@link Format} for which to acquire a {@link DrmSession}. Must contain a * @param format The {@link Format} for which to acquire a {@link DrmSession}.
* non-null {@link Format#drmInitData}. * @return The DRM session. May be null if the given {@link Format#drmInitData} is null.
* @return The DRM session.
*/ */
@Nullable
DrmSession acquireSession( DrmSession acquireSession(
Looper playbackLooper, Looper playbackLooper,
@Nullable DrmSessionEventListener.EventDispatcher eventDispatcher, @Nullable DrmSessionEventListener.EventDispatcher eventDispatcher,
@ -105,16 +98,16 @@ public interface DrmSessionManager {
/** /**
* Returns the {@link ExoMediaCrypto} type associated to sessions acquired for the given {@link * Returns the {@link ExoMediaCrypto} type associated to sessions acquired for the given {@link
* Format}. Returns the {@link UnsupportedMediaCrypto} type if this DRM session manager does not * Format}. Returns the {@link UnsupportedMediaCrypto} type if this DRM session manager does not
* support any of the DRM schemes defined in the given {@link Format}. If the {@link Format} * support any of the DRM schemes defined in the given {@link Format}. Returns null if {@link
* describes unencrypted content, returns an {@link ExoMediaCrypto} type if this DRM session * Format#drmInitData} is null and {@link #acquireSession} would return null for the given {@link
* manager would associate a {@link #acquirePlaceholderSession placeholder session} to the given * Format}.
* {@link Format}, or null otherwise.
* *
* @param format The {@link Format} for which to return the {@link ExoMediaCrypto} type. * @param format The {@link Format} for which to return the {@link ExoMediaCrypto} type.
* @return The {@link ExoMediaCrypto} type associated to sessions acquired using the given * @return The {@link ExoMediaCrypto} type associated to sessions acquired using the given {@link
* parameters, or the {@link UnsupportedMediaCrypto} type if the provided {@code drmInitData} * Format}, or {@link UnsupportedMediaCrypto} if this DRM session manager does not support any
* is not supported, or {@code null} if {@code drmInitData} is null and no DRM session will be * of the DRM schemes defined in the given {@link Format}. May be null if {@link
* associated to the given {@code trackType}. * Format#drmInitData} is null and {@link #acquireSession} would return null for the given
* {@link Format}.
*/ */
@Nullable @Nullable
Class<? extends ExoMediaCrypto> getExoMediaCryptoType(Format format); Class<? extends ExoMediaCrypto> getExoMediaCryptoType(Format format);

View File

@ -184,7 +184,8 @@ public final class OfflineLicenseHelper {
/** /**
* Downloads an offline license. * Downloads an offline license.
* *
* @param format The {@link Format} of the content whose license is to be downloaded. * @param format The {@link Format} of the content whose license is to be downloaded. Must contain
* a non-null {@link Format#drmInitData}.
* @return The key set id for the downloaded license. * @return The key set id for the downloaded license.
* @throws DrmSessionException Thrown when a DRM session error occurs. * @throws DrmSessionException Thrown when a DRM session error occurs.
*/ */
@ -278,13 +279,14 @@ public final class OfflineLicenseHelper {
private DrmSession openBlockingKeyRequest( private DrmSession openBlockingKeyRequest(
@Mode int licenseMode, @Nullable byte[] offlineLicenseKeySetId, Format format) { @Mode int licenseMode, @Nullable byte[] offlineLicenseKeySetId, Format format) {
Assertions.checkNotNull(format.drmInitData);
drmSessionManager.setMode(licenseMode, offlineLicenseKeySetId); drmSessionManager.setMode(licenseMode, offlineLicenseKeySetId);
conditionVariable.close(); conditionVariable.close();
DrmSession drmSession = DrmSession drmSession =
drmSessionManager.acquireSession(handlerThread.getLooper(), eventDispatcher, format); drmSessionManager.acquireSession(handlerThread.getLooper(), eventDispatcher, format);
// Block current thread until key loading is finished // Block current thread until key loading is finished
conditionVariable.block(); conditionVariable.block();
return drmSession; return Assertions.checkNotNull(drmSession);
} }
} }

View File

@ -327,13 +327,7 @@ public class SampleQueue implements TrackOutput {
* Attempts to read from the queue. * Attempts to read from the queue.
* *
* <p>{@link Format Formats} read from this method may be associated to a {@link DrmSession} * <p>{@link Format Formats} read from this method may be associated to a {@link DrmSession}
* through {@link FormatHolder#drmSession}, which is populated in two scenarios: * through {@link FormatHolder#drmSession}.
*
* <ul>
* <li>The {@link Format} has a non-null {@link Format#drmInitData}.
* <li>The {@link DrmSessionManager} provides placeholder sessions for this queue's track type.
* See {@link DrmSessionManager#acquirePlaceholderSession(Looper, int)}.
* </ul>
* *
* @param formatHolder A {@link FormatHolder} to populate in the case of reading a format. * @param formatHolder A {@link FormatHolder} to populate in the case of reading a format.
* @param buffer A {@link DecoderInputBuffer} to populate in the case of reading a sample or the * @param buffer A {@link DecoderInputBuffer} to populate in the case of reading a sample or the
@ -842,10 +836,7 @@ public class SampleQueue implements TrackOutput {
// is being used for both DrmInitData. // is being used for both DrmInitData.
@Nullable DrmSession previousSession = currentDrmSession; @Nullable DrmSession previousSession = currentDrmSession;
currentDrmSession = currentDrmSession =
newDrmInitData != null drmSessionManager.acquireSession(playbackLooper, drmEventDispatcher, newFormat);
? drmSessionManager.acquireSession(playbackLooper, drmEventDispatcher, newFormat)
: drmSessionManager.acquirePlaceholderSession(
playbackLooper, MimeTypes.getTrackType(newFormat.sampleMimeType));
outputFormatHolder.drmSession = currentDrmSession; outputFormatHolder.drmSession = currentDrmSession;
if (previousSession != null) { if (previousSession != null) {

View File

@ -38,6 +38,7 @@ import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSession;
import com.google.android.exoplayer2.drm.DrmSessionEventListener; import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.testutil.TestUtil; import com.google.android.exoplayer2.testutil.TestUtil;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
@ -54,7 +55,6 @@ import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.ArgumentMatchers;
import org.mockito.Mockito; import org.mockito.Mockito;
/** Test for {@link SampleQueue}. */ /** Test for {@link SampleQueue}. */
@ -69,6 +69,8 @@ public final class SampleQueueTest {
private static final Format FORMAT_SPLICED = buildFormat(/* id= */ "spliced"); private static final Format FORMAT_SPLICED = buildFormat(/* id= */ "spliced");
private static final Format FORMAT_ENCRYPTED = private static final Format FORMAT_ENCRYPTED =
new Format.Builder().setId(/* id= */ "encrypted").setDrmInitData(new DrmInitData()).build(); new Format.Builder().setId(/* id= */ "encrypted").setDrmInitData(new DrmInitData()).build();
private static final Format FORMAT_ENCRYPTED_WITH_EXO_MEDIA_CRYPTO_TYPE =
FORMAT_ENCRYPTED.copyWithExoMediaCryptoType(MockExoMediaCrypto.class);
private static final byte[] DATA = TestUtil.buildTestData(ALLOCATION_SIZE * 10); private static final byte[] DATA = TestUtil.buildTestData(ALLOCATION_SIZE * 10);
/* /*
@ -128,7 +130,7 @@ public final class SampleQueueTest {
new TrackOutput.CryptoData(C.CRYPTO_MODE_AES_CTR, new byte[16], 0, 0); new TrackOutput.CryptoData(C.CRYPTO_MODE_AES_CTR, new byte[16], 0, 0);
private Allocator allocator; private Allocator allocator;
private DrmSessionManager mockDrmSessionManager; private MockDrmSessionManager mockDrmSessionManager;
private DrmSession mockDrmSession; private DrmSession mockDrmSession;
private DrmSessionEventListener.EventDispatcher eventDispatcher; private DrmSessionEventListener.EventDispatcher eventDispatcher;
private SampleQueue sampleQueue; private SampleQueue sampleQueue;
@ -138,11 +140,8 @@ public final class SampleQueueTest {
@Before @Before
public void setUp() { public void setUp() {
allocator = new DefaultAllocator(false, ALLOCATION_SIZE); allocator = new DefaultAllocator(false, ALLOCATION_SIZE);
mockDrmSessionManager = Mockito.mock(DrmSessionManager.class);
mockDrmSession = Mockito.mock(DrmSession.class); mockDrmSession = Mockito.mock(DrmSession.class);
when(mockDrmSessionManager.acquireSession( mockDrmSessionManager = new MockDrmSessionManager(mockDrmSession);
ArgumentMatchers.any(), ArgumentMatchers.any(), ArgumentMatchers.any()))
.thenReturn(mockDrmSession);
eventDispatcher = new DrmSessionEventListener.EventDispatcher(); eventDispatcher = new DrmSessionEventListener.EventDispatcher();
sampleQueue = sampleQueue =
new SampleQueue( new SampleQueue(
@ -399,7 +398,7 @@ public final class SampleQueueTest {
@Test @Test
public void isReadyReturnsTrueForValidDrmSession() { public void isReadyReturnsTrueForValidDrmSession() {
writeTestDataWithEncryptedSections(); writeTestDataWithEncryptedSections();
assertReadFormat(/* formatRequired= */ false, FORMAT_ENCRYPTED); assertReadFormat(/* formatRequired= */ false, FORMAT_ENCRYPTED_WITH_EXO_MEDIA_CRYPTO_TYPE);
assertThat(sampleQueue.isReady(/* loadingFinished= */ false)).isFalse(); assertThat(sampleQueue.isReady(/* loadingFinished= */ false)).isFalse();
when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED_WITH_KEYS); when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED_WITH_KEYS);
assertThat(sampleQueue.isReady(/* loadingFinished= */ false)).isTrue(); assertThat(sampleQueue.isReady(/* loadingFinished= */ false)).isTrue();
@ -424,7 +423,7 @@ public final class SampleQueueTest {
when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED); when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED);
writeTestDataWithEncryptedSections(); writeTestDataWithEncryptedSections();
assertReadFormat(/* formatRequired= */ false, FORMAT_ENCRYPTED); assertReadFormat(/* formatRequired= */ false, FORMAT_ENCRYPTED_WITH_EXO_MEDIA_CRYPTO_TYPE);
assertReadNothing(/* formatRequired= */ false); assertReadNothing(/* formatRequired= */ false);
assertThat(inputBuffer.waitingForKeys).isTrue(); assertThat(inputBuffer.waitingForKeys).isTrue();
when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED_WITH_KEYS); when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED_WITH_KEYS);
@ -464,9 +463,7 @@ public final class SampleQueueTest {
when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED_WITH_KEYS); when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED_WITH_KEYS);
DrmSession mockPlaceholderDrmSession = Mockito.mock(DrmSession.class); DrmSession mockPlaceholderDrmSession = Mockito.mock(DrmSession.class);
when(mockPlaceholderDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED_WITH_KEYS); when(mockPlaceholderDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED_WITH_KEYS);
when(mockDrmSessionManager.acquirePlaceholderSession( mockDrmSessionManager.mockPlaceholderDrmSession = mockPlaceholderDrmSession;
ArgumentMatchers.any(), ArgumentMatchers.anyInt()))
.thenReturn(mockPlaceholderDrmSession);
writeTestDataWithEncryptedSections(); writeTestDataWithEncryptedSections();
int result = int result =
@ -497,9 +494,7 @@ public final class SampleQueueTest {
when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED_WITH_KEYS); when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED_WITH_KEYS);
DrmSession mockPlaceholderDrmSession = Mockito.mock(DrmSession.class); DrmSession mockPlaceholderDrmSession = Mockito.mock(DrmSession.class);
when(mockPlaceholderDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED_WITH_KEYS); when(mockPlaceholderDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED_WITH_KEYS);
when(mockDrmSessionManager.acquirePlaceholderSession( mockDrmSessionManager.mockPlaceholderDrmSession = mockPlaceholderDrmSession;
ArgumentMatchers.any(), ArgumentMatchers.anyInt()))
.thenReturn(mockPlaceholderDrmSession);
writeFormat(ENCRYPTED_SAMPLE_FORMATS[0]); writeFormat(ENCRYPTED_SAMPLE_FORMATS[0]);
byte[] sampleData = new byte[] {0, 1, 2}; byte[] sampleData = new byte[] {0, 1, 2};
@ -540,7 +535,7 @@ public final class SampleQueueTest {
when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED); when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED);
writeTestDataWithEncryptedSections(); writeTestDataWithEncryptedSections();
assertReadFormat(/* formatRequired= */ false, FORMAT_ENCRYPTED); assertReadFormat(/* formatRequired= */ false, FORMAT_ENCRYPTED_WITH_EXO_MEDIA_CRYPTO_TYPE);
assertReadNothing(/* formatRequired= */ false); assertReadNothing(/* formatRequired= */ false);
sampleQueue.maybeThrowError(); sampleQueue.maybeThrowError();
when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_ERROR); when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_ERROR);
@ -569,7 +564,7 @@ public final class SampleQueueTest {
when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED); when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED);
writeTestDataWithEncryptedSections(); writeTestDataWithEncryptedSections();
assertReadFormat(/* formatRequired= */ false, FORMAT_ENCRYPTED); assertReadFormat(/* formatRequired= */ false, FORMAT_ENCRYPTED_WITH_EXO_MEDIA_CRYPTO_TYPE);
assertReadEncryptedSample(/* sampleIndex= */ 0); assertReadEncryptedSample(/* sampleIndex= */ 0);
} }
@ -1497,4 +1492,33 @@ public final class SampleQueueTest {
private static Format copyWithLabel(Format format, String label) { private static Format copyWithLabel(Format format, String label) {
return format.buildUpon().setLabel(label).build(); return format.buildUpon().setLabel(label).build();
} }
private static final class MockExoMediaCrypto implements ExoMediaCrypto {}
private static final class MockDrmSessionManager implements DrmSessionManager {
private final DrmSession mockDrmSession;
@Nullable private DrmSession mockPlaceholderDrmSession;
private MockDrmSessionManager(DrmSession mockDrmSession) {
this.mockDrmSession = mockDrmSession;
}
@Nullable
@Override
public DrmSession acquireSession(
Looper playbackLooper,
@Nullable DrmSessionEventListener.EventDispatcher eventDispatcher,
Format format) {
return format.drmInitData != null ? mockDrmSession : mockPlaceholderDrmSession;
}
@Nullable
@Override
public Class<? extends ExoMediaCrypto> getExoMediaCryptoType(Format format) {
return mockPlaceholderDrmSession != null || format.drmInitData != null
? MockExoMediaCrypto.class
: null;
}
}
} }

View File

@ -30,7 +30,6 @@ import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.source.MediaSourceEventListener; import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import java.io.IOException; import java.io.IOException;
@ -274,10 +273,7 @@ public class FakeSampleStream implements SampleStream {
@Nullable DrmSession previousSession = currentDrmSession; @Nullable DrmSession previousSession = currentDrmSession;
Looper playbackLooper = Assertions.checkNotNull(Looper.myLooper()); Looper playbackLooper = Assertions.checkNotNull(Looper.myLooper());
currentDrmSession = currentDrmSession =
newDrmInitData != null drmSessionManager.acquireSession(playbackLooper, drmEventDispatcher, newFormat);
? drmSessionManager.acquireSession(playbackLooper, drmEventDispatcher, newFormat)
: drmSessionManager.acquirePlaceholderSession(
playbackLooper, MimeTypes.getTrackType(newFormat.sampleMimeType));
outputFormatHolder.drmSession = currentDrmSession; outputFormatHolder.drmSession = currentDrmSession;
if (previousSession != null) { if (previousSession != null) {