mirror of
https://github.com/samsonjs/media.git
synced 2026-04-08 11:45:51 +00:00
DrmSession cleanup
These changes are in part related to handling playback of mixed clear and encrypted content, where we might want to use a secure decoder throughout, but only have drm init data and only care about the state of the DrmSession during playback of encrypted parts. - requiresSecureDecoderComponent became unnecessary when we added ExoMediaCrypto, which provides a layer in which requiresSecureDecoderComponent can be overridden. - Relaxed requirements for obtaining the MediaCrypto. It's helpful to allow retrieval in the error state, since it can be used to instantiate a decoder and play clear samples. - Deferred throwing of errors in renderer implementations. As long as we can get a MediaCrypto, we should init the codec. We can also play clear samples without failing if playClearSamplesWithoutKeys is true, regardless of the errors state. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=160536365
This commit is contained in:
parent
beb0734107
commit
db177db6d9
9 changed files with 124 additions and 142 deletions
|
|
@ -30,6 +30,7 @@ import com.google.android.exoplayer2.FormatHolder;
|
|||
import com.google.android.exoplayer2.decoder.DecoderCounters;
|
||||
import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
|
||||
import com.google.android.exoplayer2.drm.DrmSession;
|
||||
import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException;
|
||||
import com.google.android.exoplayer2.drm.DrmSessionManager;
|
||||
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
|
|
@ -185,42 +186,21 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
// We have a format.
|
||||
drmSession = pendingDrmSession;
|
||||
ExoMediaCrypto mediaCrypto = null;
|
||||
if (drmSession != null) {
|
||||
int drmSessionState = drmSession.getState();
|
||||
if (drmSessionState == DrmSession.STATE_ERROR) {
|
||||
throw ExoPlaybackException.createForRenderer(drmSession.getError(), getIndex());
|
||||
} else if (drmSessionState == DrmSession.STATE_OPENED
|
||||
|| drmSessionState == DrmSession.STATE_OPENED_WITH_KEYS) {
|
||||
mediaCrypto = drmSession.getMediaCrypto();
|
||||
} else {
|
||||
// The drm session isn't open yet.
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (decoder == null) {
|
||||
// If we don't have a decoder yet, we need to instantiate one.
|
||||
long codecInitializingTimestamp = SystemClock.elapsedRealtime();
|
||||
TraceUtil.beginSection("createVpxDecoder");
|
||||
decoder = new VpxDecoder(NUM_BUFFERS, NUM_BUFFERS, INITIAL_INPUT_BUFFER_SIZE, mediaCrypto);
|
||||
decoder.setOutputMode(outputMode);
|
||||
// If we don't have a decoder yet, we need to instantiate one.
|
||||
maybeInitDecoder();
|
||||
|
||||
if (decoder != null) {
|
||||
try {
|
||||
// Rendering loop.
|
||||
TraceUtil.beginSection("drainAndFeed");
|
||||
while (drainOutputBuffer(positionUs)) {}
|
||||
while (feedInputBuffer()) {}
|
||||
TraceUtil.endSection();
|
||||
long codecInitializedTimestamp = SystemClock.elapsedRealtime();
|
||||
eventDispatcher.decoderInitialized(decoder.getName(), codecInitializedTimestamp,
|
||||
codecInitializedTimestamp - codecInitializingTimestamp);
|
||||
decoderCounters.decoderInitCount++;
|
||||
} catch (VpxDecoderException e) {
|
||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
||||
}
|
||||
TraceUtil.beginSection("drainAndFeed");
|
||||
while (drainOutputBuffer(positionUs)) {}
|
||||
while (feedInputBuffer()) {}
|
||||
TraceUtil.endSection();
|
||||
} catch (VpxDecoderException e) {
|
||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
||||
decoderCounters.ensureUpdated();
|
||||
}
|
||||
decoderCounters.ensureUpdated();
|
||||
}
|
||||
|
||||
private boolean drainOutputBuffer(long positionUs) throws VpxDecoderException {
|
||||
|
|
@ -399,15 +379,14 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
|
|||
}
|
||||
|
||||
private boolean shouldWaitForKeys(boolean bufferEncrypted) throws ExoPlaybackException {
|
||||
if (drmSession == null) {
|
||||
if (drmSession == null || (!bufferEncrypted && playClearSamplesWithoutKeys)) {
|
||||
return false;
|
||||
}
|
||||
int drmSessionState = drmSession.getState();
|
||||
@DrmSession.State int drmSessionState = drmSession.getState();
|
||||
if (drmSessionState == DrmSession.STATE_ERROR) {
|
||||
throw ExoPlaybackException.createForRenderer(drmSession.getError(), getIndex());
|
||||
}
|
||||
return drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS
|
||||
&& (bufferEncrypted || !playClearSamplesWithoutKeys);
|
||||
return drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS;
|
||||
}
|
||||
|
||||
private void flushDecoder() {
|
||||
|
|
@ -516,6 +495,40 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
private void maybeInitDecoder() throws ExoPlaybackException {
|
||||
if (decoder != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
drmSession = pendingDrmSession;
|
||||
ExoMediaCrypto mediaCrypto = null;
|
||||
if (drmSession != null) {
|
||||
mediaCrypto = drmSession.getMediaCrypto();
|
||||
if (mediaCrypto == null) {
|
||||
DrmSessionException drmError = drmSession.getError();
|
||||
if (drmError != null) {
|
||||
throw ExoPlaybackException.createForRenderer(drmError, getIndex());
|
||||
}
|
||||
// The drm session isn't open yet.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
long codecInitializingTimestamp = SystemClock.elapsedRealtime();
|
||||
TraceUtil.beginSection("createVpxDecoder");
|
||||
decoder = new VpxDecoder(NUM_BUFFERS, NUM_BUFFERS, INITIAL_INPUT_BUFFER_SIZE, mediaCrypto);
|
||||
decoder.setOutputMode(outputMode);
|
||||
TraceUtil.endSection();
|
||||
long codecInitializedTimestamp = SystemClock.elapsedRealtime();
|
||||
eventDispatcher.decoderInitialized(decoder.getName(), codecInitializedTimestamp,
|
||||
codecInitializedTimestamp - codecInitializingTimestamp);
|
||||
decoderCounters.decoderInitCount++;
|
||||
} catch (VpxDecoderException e) {
|
||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
||||
}
|
||||
}
|
||||
|
||||
private void releaseDecoder() {
|
||||
if (decoder != null) {
|
||||
decoder.release();
|
||||
|
|
|
|||
|
|
@ -1463,7 +1463,7 @@ public final class AudioTrack {
|
|||
@TargetApi(21)
|
||||
private int writeNonBlockingWithAvSyncV21(android.media.AudioTrack audioTrack,
|
||||
ByteBuffer buffer, int size, long presentationTimeUs) {
|
||||
// TODO: Uncomment this when [Internal ref b/33627517] is clarified or fixed.
|
||||
// TODO: Uncomment this when [Internal ref: b/33627517] is clarified or fixed.
|
||||
// if (Util.SDK_INT >= 23) {
|
||||
// // The underlying platform AudioTrack writes AV sync headers directly.
|
||||
// return audioTrack.write(buffer, size, WRITE_NON_BLOCKING, presentationTimeUs * 1000);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
|
|||
import com.google.android.exoplayer2.decoder.SimpleDecoder;
|
||||
import com.google.android.exoplayer2.decoder.SimpleOutputBuffer;
|
||||
import com.google.android.exoplayer2.drm.DrmSession;
|
||||
import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException;
|
||||
import com.google.android.exoplayer2.drm.DrmSessionManager;
|
||||
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
|
|
@ -376,15 +377,14 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
|
|||
}
|
||||
|
||||
private boolean shouldWaitForKeys(boolean bufferEncrypted) throws ExoPlaybackException {
|
||||
if (drmSession == null) {
|
||||
if (drmSession == null || (!bufferEncrypted && playClearSamplesWithoutKeys)) {
|
||||
return false;
|
||||
}
|
||||
@DrmSession.State int drmSessionState = drmSession.getState();
|
||||
if (drmSessionState == DrmSession.STATE_ERROR) {
|
||||
throw ExoPlaybackException.createForRenderer(drmSession.getError(), getIndex());
|
||||
}
|
||||
return drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS
|
||||
&& (bufferEncrypted || !playClearSamplesWithoutKeys);
|
||||
return drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS;
|
||||
}
|
||||
|
||||
private void processEndOfStream() throws ExoPlaybackException {
|
||||
|
|
@ -514,13 +514,12 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
|
|||
drmSession = pendingDrmSession;
|
||||
ExoMediaCrypto mediaCrypto = null;
|
||||
if (drmSession != null) {
|
||||
@DrmSession.State int drmSessionState = drmSession.getState();
|
||||
if (drmSessionState == DrmSession.STATE_ERROR) {
|
||||
throw ExoPlaybackException.createForRenderer(drmSession.getError(), getIndex());
|
||||
} else if (drmSessionState == DrmSession.STATE_OPENED
|
||||
|| drmSessionState == DrmSession.STATE_OPENED_WITH_KEYS) {
|
||||
mediaCrypto = drmSession.getMediaCrypto();
|
||||
} else {
|
||||
mediaCrypto = drmSession.getMediaCrypto();
|
||||
if (mediaCrypto == null) {
|
||||
DrmSessionException drmError = drmSession.getError();
|
||||
if (drmError != null) {
|
||||
throw ExoPlaybackException.createForRenderer(drmError, getIndex());
|
||||
}
|
||||
// The drm session isn't open yet.
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -222,7 +222,6 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
|
|||
this.eventHandler = eventHandler;
|
||||
this.eventListener = eventListener;
|
||||
mediaDrm.setOnEventListener(new MediaDrmEventListener());
|
||||
state = STATE_CLOSED;
|
||||
mode = MODE_PLAYBACK;
|
||||
}
|
||||
|
||||
|
|
@ -358,7 +357,7 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
|
|||
if (--openCount != 0) {
|
||||
return;
|
||||
}
|
||||
state = STATE_CLOSED;
|
||||
state = STATE_RELEASED;
|
||||
provisioningInProgress = false;
|
||||
mediaDrmHandler.removeCallbacksAndMessages(null);
|
||||
postResponseHandler.removeCallbacksAndMessages(null);
|
||||
|
|
@ -384,35 +383,19 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
|
|||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final T getMediaCrypto() {
|
||||
if (state != STATE_OPENED && state != STATE_OPENED_WITH_KEYS) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return mediaCrypto;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requiresSecureDecoderComponent(String mimeType) {
|
||||
if (state != STATE_OPENED && state != STATE_OPENED_WITH_KEYS) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return mediaCrypto.requiresSecureDecoderComponent(mimeType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DrmSessionException getError() {
|
||||
return state == STATE_ERROR ? lastException : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final T getMediaCrypto() {
|
||||
return mediaCrypto;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> queryKeyStatus() {
|
||||
// User may call this method rightfully even if state == STATE_ERROR. So only check if there is
|
||||
// a sessionId
|
||||
if (sessionId == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return mediaDrm.queryKeyStatus(sessionId);
|
||||
return sessionId == null ? null : mediaDrm.queryKeyStatus(sessionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -41,16 +41,16 @@ public interface DrmSession<T extends ExoMediaCrypto> {
|
|||
* The state of the DRM session.
|
||||
*/
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({STATE_ERROR, STATE_CLOSED, STATE_OPENING, STATE_OPENED, STATE_OPENED_WITH_KEYS})
|
||||
@IntDef({STATE_RELEASED, STATE_ERROR, STATE_OPENING, STATE_OPENED, STATE_OPENED_WITH_KEYS})
|
||||
@interface State {}
|
||||
/**
|
||||
* The session has been released.
|
||||
*/
|
||||
int STATE_RELEASED = 0;
|
||||
/**
|
||||
* The session has encountered an error. {@link #getError()} can be used to retrieve the cause.
|
||||
*/
|
||||
int STATE_ERROR = 0;
|
||||
/**
|
||||
* The session is closed.
|
||||
*/
|
||||
int STATE_CLOSED = 1;
|
||||
int STATE_ERROR = 1;
|
||||
/**
|
||||
* The session is being opened.
|
||||
*/
|
||||
|
|
@ -65,66 +65,40 @@ public interface DrmSession<T extends ExoMediaCrypto> {
|
|||
int STATE_OPENED_WITH_KEYS = 4;
|
||||
|
||||
/**
|
||||
* Returns the current state of the session.
|
||||
*
|
||||
* @return One of {@link #STATE_ERROR}, {@link #STATE_CLOSED}, {@link #STATE_OPENING},
|
||||
* {@link #STATE_OPENED} and {@link #STATE_OPENED_WITH_KEYS}.
|
||||
* Returns the current state of the session, which is one of {@link #STATE_ERROR},
|
||||
* {@link #STATE_RELEASED}, {@link #STATE_OPENING}, {@link #STATE_OPENED} and
|
||||
* {@link #STATE_OPENED_WITH_KEYS}.
|
||||
*/
|
||||
@State int getState();
|
||||
|
||||
/**
|
||||
* Returns a {@link ExoMediaCrypto} for the open session.
|
||||
* <p>
|
||||
* This method may be called when the session is in the following states:
|
||||
* {@link #STATE_OPENED}, {@link #STATE_OPENED_WITH_KEYS}
|
||||
*
|
||||
* @return A {@link ExoMediaCrypto} for the open session.
|
||||
* @throws IllegalStateException If called when a session isn't opened.
|
||||
*/
|
||||
T getMediaCrypto();
|
||||
|
||||
/**
|
||||
* Whether the session requires a secure decoder for the specified mime type.
|
||||
* <p>
|
||||
* Normally this method should return
|
||||
* {@link ExoMediaCrypto#requiresSecureDecoderComponent(String)}, however in some cases
|
||||
* implementations may wish to modify the return value (i.e. to force a secure decoder even when
|
||||
* one is not required).
|
||||
* <p>
|
||||
* This method may be called when the session is in the following states:
|
||||
* {@link #STATE_OPENED}, {@link #STATE_OPENED_WITH_KEYS}
|
||||
*
|
||||
* @return Whether the open session requires a secure decoder for the specified mime type.
|
||||
* @throws IllegalStateException If called when a session isn't opened.
|
||||
*/
|
||||
boolean requiresSecureDecoderComponent(String mimeType);
|
||||
|
||||
/**
|
||||
* Returns the cause of the error state.
|
||||
* <p>
|
||||
* This method may be called when the session is in any state.
|
||||
*
|
||||
* @return An exception if the state is {@link #STATE_ERROR}. Null otherwise.
|
||||
*/
|
||||
DrmSessionException getError();
|
||||
|
||||
/**
|
||||
* Returns an informative description of the key status for the session. The status is in the form
|
||||
* of {name, value} pairs.
|
||||
*
|
||||
* <p>Since DRM license policies vary by vendor, the specific status field names are determined by
|
||||
* Returns a {@link ExoMediaCrypto} for the open session, or null if called before the session has
|
||||
* been opened or after it's been released.
|
||||
*/
|
||||
T getMediaCrypto();
|
||||
|
||||
/**
|
||||
* Returns a map describing the key status for the session, or null if called before the session
|
||||
* has been opened or after it's been released.
|
||||
* <p>
|
||||
* Since DRM license policies vary by vendor, the specific status field names are determined by
|
||||
* each DRM vendor. Refer to your DRM provider documentation for definitions of the field names
|
||||
* for a particular DRM engine plugin.
|
||||
*
|
||||
* @return A map of key status.
|
||||
* @throws IllegalStateException If called when the session isn't opened.
|
||||
* @return A map describing the key status for the session, or null if called before the session
|
||||
* has been opened or after it's been released.
|
||||
* @see MediaDrm#queryKeyStatus(byte[])
|
||||
*/
|
||||
Map<String, String> queryKeyStatus();
|
||||
|
||||
/**
|
||||
* Returns the key set id of the offline license loaded into this session, if there is one. Null
|
||||
* otherwise.
|
||||
* Returns the key set id of the offline license loaded into this session, or null if there isn't
|
||||
* one.
|
||||
*/
|
||||
byte[] getOfflineLicenseKeySetId();
|
||||
|
||||
|
|
|
|||
|
|
@ -26,9 +26,12 @@ import com.google.android.exoplayer2.util.Assertions;
|
|||
public final class FrameworkMediaCrypto implements ExoMediaCrypto {
|
||||
|
||||
private final MediaCrypto mediaCrypto;
|
||||
private final boolean forceAllowInsecureDecoderComponents;
|
||||
|
||||
/* package */ FrameworkMediaCrypto(MediaCrypto mediaCrypto) {
|
||||
/* package */ FrameworkMediaCrypto(MediaCrypto mediaCrypto,
|
||||
boolean forceAllowInsecureDecoderComponents) {
|
||||
this.mediaCrypto = Assertions.checkNotNull(mediaCrypto);
|
||||
this.forceAllowInsecureDecoderComponents = forceAllowInsecureDecoderComponents;
|
||||
}
|
||||
|
||||
public MediaCrypto getWrappedMediaCrypto() {
|
||||
|
|
@ -37,7 +40,8 @@ public final class FrameworkMediaCrypto implements ExoMediaCrypto {
|
|||
|
||||
@Override
|
||||
public boolean requiresSecureDecoderComponent(String mimeType) {
|
||||
return mediaCrypto.requiresSecureDecoderComponent(mimeType);
|
||||
return !forceAllowInsecureDecoderComponents
|
||||
&& mediaCrypto.requiresSecureDecoderComponent(mimeType);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,9 @@ import android.media.NotProvisionedException;
|
|||
import android.media.ResourceBusyException;
|
||||
import android.media.UnsupportedSchemeException;
|
||||
import android.support.annotation.NonNull;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
|
@ -163,7 +165,12 @@ public final class FrameworkMediaDrm implements ExoMediaDrm<FrameworkMediaCrypto
|
|||
@Override
|
||||
public FrameworkMediaCrypto createMediaCrypto(UUID uuid, byte[] initData)
|
||||
throws MediaCryptoException {
|
||||
return new FrameworkMediaCrypto(new MediaCrypto(uuid, initData));
|
||||
// Work around a bug prior to Lollipop where L1 Widevine forced into L3 mode would still
|
||||
// indicate that it required secure video decoders [Internal ref: b/11428937].
|
||||
boolean forceAllowInsecureDecoderComponents = Util.SDK_INT < 21
|
||||
&& C.WIDEVINE_UUID.equals(uuid) && "L3".equals(getPropertyString("securityLevel"));
|
||||
return new FrameworkMediaCrypto(new MediaCrypto(uuid, initData),
|
||||
forceAllowInsecureDecoderComponents);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,14 +34,16 @@ public final class WidevineUtil {
|
|||
/**
|
||||
* Returns license and playback durations remaining in seconds.
|
||||
*
|
||||
* @return A {@link Pair} consisting of the remaining license and playback durations in seconds.
|
||||
* @throws IllegalStateException If called when a session isn't opened.
|
||||
* @param drmSession
|
||||
* @param drmSession The drm session to query.
|
||||
* @return A {@link Pair} consisting of the remaining license and playback durations in seconds,
|
||||
* or null if called before the session has been opened or after it's been released.
|
||||
*/
|
||||
public static Pair<Long, Long> getLicenseDurationRemainingSec(DrmSession<?> drmSession) {
|
||||
Map<String, String> keyStatus = drmSession.queryKeyStatus();
|
||||
return new Pair<>(
|
||||
getDurationRemainingSec(keyStatus, PROPERTY_LICENSE_DURATION_REMAINING),
|
||||
if (keyStatus == null) {
|
||||
return null;
|
||||
}
|
||||
return new Pair<>(getDurationRemainingSec(keyStatus, PROPERTY_LICENSE_DURATION_REMAINING),
|
||||
getDurationRemainingSec(keyStatus, PROPERTY_PLAYBACK_DURATION_REMAINING));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import com.google.android.exoplayer2.FormatHolder;
|
|||
import com.google.android.exoplayer2.decoder.DecoderCounters;
|
||||
import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
|
||||
import com.google.android.exoplayer2.drm.DrmSession;
|
||||
import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException;
|
||||
import com.google.android.exoplayer2.drm.DrmSessionManager;
|
||||
import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
|
||||
import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException;
|
||||
|
|
@ -298,20 +299,20 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||
|
||||
drmSession = pendingDrmSession;
|
||||
String mimeType = format.sampleMimeType;
|
||||
MediaCrypto mediaCrypto = null;
|
||||
MediaCrypto wrappedMediaCrypto = null;
|
||||
boolean drmSessionRequiresSecureDecoder = false;
|
||||
if (drmSession != null) {
|
||||
@DrmSession.State int drmSessionState = drmSession.getState();
|
||||
if (drmSessionState == DrmSession.STATE_ERROR) {
|
||||
throw ExoPlaybackException.createForRenderer(drmSession.getError(), getIndex());
|
||||
} else if (drmSessionState == DrmSession.STATE_OPENED
|
||||
|| drmSessionState == DrmSession.STATE_OPENED_WITH_KEYS) {
|
||||
mediaCrypto = drmSession.getMediaCrypto().getWrappedMediaCrypto();
|
||||
drmSessionRequiresSecureDecoder = drmSession.requiresSecureDecoderComponent(mimeType);
|
||||
} else {
|
||||
FrameworkMediaCrypto mediaCrypto = drmSession.getMediaCrypto();
|
||||
if (mediaCrypto == null) {
|
||||
DrmSessionException drmError = drmSession.getError();
|
||||
if (drmError != null) {
|
||||
throw ExoPlaybackException.createForRenderer(drmError, getIndex());
|
||||
}
|
||||
// The drm session isn't open yet.
|
||||
return;
|
||||
}
|
||||
wrappedMediaCrypto = mediaCrypto.getWrappedMediaCrypto();
|
||||
drmSessionRequiresSecureDecoder = mediaCrypto.requiresSecureDecoderComponent(mimeType);
|
||||
}
|
||||
|
||||
if (codecInfo == null) {
|
||||
|
|
@ -358,7 +359,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||
codec = MediaCodec.createByCodecName(codecName);
|
||||
TraceUtil.endSection();
|
||||
TraceUtil.beginSection("configureCodec");
|
||||
configureCodec(codecInfo, codec, format, mediaCrypto);
|
||||
configureCodec(codecInfo, codec, format, wrappedMediaCrypto);
|
||||
TraceUtil.endSection();
|
||||
TraceUtil.beginSection("startCodec");
|
||||
codec.start();
|
||||
|
|
@ -736,15 +737,14 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||
}
|
||||
|
||||
private boolean shouldWaitForKeys(boolean bufferEncrypted) throws ExoPlaybackException {
|
||||
if (drmSession == null) {
|
||||
if (drmSession == null || (!bufferEncrypted && playClearSamplesWithoutKeys)) {
|
||||
return false;
|
||||
}
|
||||
@DrmSession.State int drmSessionState = drmSession.getState();
|
||||
if (drmSessionState == DrmSession.STATE_ERROR) {
|
||||
throw ExoPlaybackException.createForRenderer(drmSession.getError(), getIndex());
|
||||
}
|
||||
return drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS
|
||||
&& (bufferEncrypted || !playClearSamplesWithoutKeys);
|
||||
return drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue