Commit 2d30d667 by olly Committed by Oliver Woodman

Fix release of DRM sessions

There were some edge cases in which we'd forget to release DRM
sessions. For example if we read a format and acquired a
pendingDrmSession (in onInputFormatChanged), then immediately
read another format and overwrote pendingDrmSession, we'd
forget to release the one that's been overwritten.

This change hopefully makes release much clearer. We keep a list
of all drm sessions we're currently holding. Whenever we update
either drmSession or pendingDrmSession, we release any other
sessions that are in the list.

PiperOrigin-RevId: 228905465
parent 71d4f394
...@@ -127,8 +127,8 @@ public class LibvpxVideoRenderer extends BaseRenderer { ...@@ -127,8 +127,8 @@ public class LibvpxVideoRenderer extends BaseRenderer {
private VpxDecoder decoder; private VpxDecoder decoder;
private VpxInputBuffer inputBuffer; private VpxInputBuffer inputBuffer;
private VpxOutputBuffer outputBuffer; private VpxOutputBuffer outputBuffer;
private DrmSession<ExoMediaCrypto> drmSession; @Nullable private DrmSession<ExoMediaCrypto> decoderDrmSession;
private DrmSession<ExoMediaCrypto> pendingDrmSession; @Nullable private DrmSession<ExoMediaCrypto> sourceDrmSession;
private @ReinitializationState int decoderReinitializationState; private @ReinitializationState int decoderReinitializationState;
private boolean decoderReceivedBuffers; private boolean decoderReceivedBuffers;
...@@ -364,26 +364,12 @@ public class LibvpxVideoRenderer extends BaseRenderer { ...@@ -364,26 +364,12 @@ public class LibvpxVideoRenderer extends BaseRenderer {
clearReportedVideoSize(); clearReportedVideoSize();
clearRenderedFirstFrame(); clearRenderedFirstFrame();
try { try {
setSourceDrmSession(null);
releaseDecoder(); releaseDecoder();
} finally { } finally {
try {
if (drmSession != null) {
drmSessionManager.releaseSession(drmSession);
}
} finally {
try {
if (pendingDrmSession != null && pendingDrmSession != drmSession) {
drmSessionManager.releaseSession(pendingDrmSession);
}
} finally {
drmSession = null;
pendingDrmSession = null;
decoderCounters.ensureUpdated();
eventDispatcher.disabled(decoderCounters); eventDispatcher.disabled(decoderCounters);
} }
} }
}
}
@Override @Override
protected void onStreamChanged(Format[] formats, long offsetUs) throws ExoPlaybackException { protected void onStreamChanged(Format[] formats, long offsetUs) throws ExoPlaybackException {
...@@ -433,18 +419,35 @@ public class LibvpxVideoRenderer extends BaseRenderer { ...@@ -433,18 +419,35 @@ public class LibvpxVideoRenderer extends BaseRenderer {
/** Releases the decoder. */ /** Releases the decoder. */
@CallSuper @CallSuper
protected void releaseDecoder() { protected void releaseDecoder() {
if (decoder == null) {
return;
}
inputBuffer = null; inputBuffer = null;
outputBuffer = null; outputBuffer = null;
decoder.release();
decoder = null;
decoderCounters.decoderReleaseCount++;
decoderReinitializationState = REINITIALIZATION_STATE_NONE; decoderReinitializationState = REINITIALIZATION_STATE_NONE;
decoderReceivedBuffers = false; decoderReceivedBuffers = false;
buffersInCodecCount = 0; buffersInCodecCount = 0;
if (decoder != null) {
decoder.release();
decoder = null;
decoderCounters.decoderReleaseCount++;
}
setDecoderDrmSession(null);
}
private void setSourceDrmSession(@Nullable DrmSession<ExoMediaCrypto> session) {
DrmSession<ExoMediaCrypto> previous = sourceDrmSession;
sourceDrmSession = session;
releaseDrmSessionIfUnused(previous);
}
private void setDecoderDrmSession(@Nullable DrmSession<ExoMediaCrypto> session) {
DrmSession<ExoMediaCrypto> previous = decoderDrmSession;
decoderDrmSession = session;
releaseDrmSessionIfUnused(previous);
}
private void releaseDrmSessionIfUnused(@Nullable DrmSession<ExoMediaCrypto> session) {
if (session != null && session != decoderDrmSession && session != sourceDrmSession) {
drmSessionManager.releaseSession(session);
}
} }
/** /**
...@@ -467,16 +470,20 @@ public class LibvpxVideoRenderer extends BaseRenderer { ...@@ -467,16 +470,20 @@ public class LibvpxVideoRenderer extends BaseRenderer {
throw ExoPlaybackException.createForRenderer( throw ExoPlaybackException.createForRenderer(
new IllegalStateException("Media requires a DrmSessionManager"), getIndex()); new IllegalStateException("Media requires a DrmSessionManager"), getIndex());
} }
pendingDrmSession = drmSessionManager.acquireSession(Looper.myLooper(), format.drmInitData); DrmSession<ExoMediaCrypto> session =
if (pendingDrmSession == drmSession) { drmSessionManager.acquireSession(Looper.myLooper(), newFormat.drmInitData);
drmSessionManager.releaseSession(pendingDrmSession); if (session == decoderDrmSession || session == sourceDrmSession) {
// We already had this session. The manager must be reference counting, so release it once
// to get the count attributed to this renderer back down to 1.
drmSessionManager.releaseSession(session);
} }
setSourceDrmSession(session);
} else { } else {
pendingDrmSession = null; setSourceDrmSession(null);
} }
} }
if (pendingDrmSession != drmSession) { if (sourceDrmSession != decoderDrmSession) {
if (decoderReceivedBuffers) { if (decoderReceivedBuffers) {
// Signal end of stream and wait for any final output buffers before re-initialization. // Signal end of stream and wait for any final output buffers before re-initialization.
decoderReinitializationState = REINITIALIZATION_STATE_SIGNAL_END_OF_STREAM; decoderReinitializationState = REINITIALIZATION_STATE_SIGNAL_END_OF_STREAM;
...@@ -704,12 +711,13 @@ public class LibvpxVideoRenderer extends BaseRenderer { ...@@ -704,12 +711,13 @@ public class LibvpxVideoRenderer extends BaseRenderer {
return; return;
} }
drmSession = pendingDrmSession; setDecoderDrmSession(sourceDrmSession);
ExoMediaCrypto mediaCrypto = null; ExoMediaCrypto mediaCrypto = null;
if (drmSession != null) { if (decoderDrmSession != null) {
mediaCrypto = drmSession.getMediaCrypto(); mediaCrypto = decoderDrmSession.getMediaCrypto();
if (mediaCrypto == null) { if (mediaCrypto == null) {
DrmSessionException drmError = drmSession.getError(); DrmSessionException drmError = decoderDrmSession.getError();
if (drmError != null) { if (drmError != null) {
// Continue for now. We may be able to avoid failure if the session recovers, or if a new // Continue for now. We may be able to avoid failure if the session recovers, or if a new
// input format causes the session to be replaced before it's used. // input format causes the session to be replaced before it's used.
...@@ -922,12 +930,12 @@ public class LibvpxVideoRenderer extends BaseRenderer { ...@@ -922,12 +930,12 @@ public class LibvpxVideoRenderer extends BaseRenderer {
} }
private boolean shouldWaitForKeys(boolean bufferEncrypted) throws ExoPlaybackException { private boolean shouldWaitForKeys(boolean bufferEncrypted) throws ExoPlaybackException {
if (drmSession == null || (!bufferEncrypted && playClearSamplesWithoutKeys)) { if (decoderDrmSession == null || (!bufferEncrypted && playClearSamplesWithoutKeys)) {
return false; return false;
} }
@DrmSession.State int drmSessionState = drmSession.getState(); @DrmSession.State int drmSessionState = decoderDrmSession.getState();
if (drmSessionState == DrmSession.STATE_ERROR) { if (drmSessionState == DrmSession.STATE_ERROR) {
throw ExoPlaybackException.createForRenderer(drmSession.getError(), getIndex()); throw ExoPlaybackException.createForRenderer(decoderDrmSession.getError(), getIndex());
} }
return drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS; return drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS;
} }
......
...@@ -147,6 +147,7 @@ public interface AudioRendererEventListener { ...@@ -147,6 +147,7 @@ public interface AudioRendererEventListener {
* Invokes {@link AudioRendererEventListener#onAudioDisabled(DecoderCounters)}. * Invokes {@link AudioRendererEventListener#onAudioDisabled(DecoderCounters)}.
*/ */
public void disabled(final DecoderCounters counters) { public void disabled(final DecoderCounters counters) {
counters.ensureUpdated();
if (listener != null) { if (listener != null) {
handler.post( handler.post(
() -> { () -> {
......
...@@ -548,7 +548,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media ...@@ -548,7 +548,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
try { try {
super.onDisabled(); super.onDisabled();
} finally { } finally {
decoderCounters.ensureUpdated();
eventDispatcher.disabled(decoderCounters); eventDispatcher.disabled(decoderCounters);
} }
} }
......
...@@ -106,8 +106,8 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements ...@@ -106,8 +106,8 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
? extends AudioDecoderException> decoder; ? extends AudioDecoderException> decoder;
private DecoderInputBuffer inputBuffer; private DecoderInputBuffer inputBuffer;
private SimpleOutputBuffer outputBuffer; private SimpleOutputBuffer outputBuffer;
private DrmSession<ExoMediaCrypto> drmSession; @Nullable private DrmSession<ExoMediaCrypto> decoderDrmSession;
private DrmSession<ExoMediaCrypto> pendingDrmSession; @Nullable private DrmSession<ExoMediaCrypto> sourceDrmSession;
@ReinitializationState private int decoderReinitializationState; @ReinitializationState private int decoderReinitializationState;
private boolean decoderReceivedBuffers; private boolean decoderReceivedBuffers;
...@@ -462,12 +462,12 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements ...@@ -462,12 +462,12 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
} }
private boolean shouldWaitForKeys(boolean bufferEncrypted) throws ExoPlaybackException { private boolean shouldWaitForKeys(boolean bufferEncrypted) throws ExoPlaybackException {
if (drmSession == null || (!bufferEncrypted && playClearSamplesWithoutKeys)) { if (decoderDrmSession == null || (!bufferEncrypted && playClearSamplesWithoutKeys)) {
return false; return false;
} }
@DrmSession.State int drmSessionState = drmSession.getState(); @DrmSession.State int drmSessionState = decoderDrmSession.getState();
if (drmSessionState == DrmSession.STATE_ERROR) { if (drmSessionState == DrmSession.STATE_ERROR) {
throw ExoPlaybackException.createForRenderer(drmSession.getError(), getIndex()); throw ExoPlaybackException.createForRenderer(decoderDrmSession.getError(), getIndex());
} }
return drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS; return drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS;
} }
...@@ -568,27 +568,13 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements ...@@ -568,27 +568,13 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
audioTrackNeedsConfigure = true; audioTrackNeedsConfigure = true;
waitingForKeys = false; waitingForKeys = false;
try { try {
setSourceDrmSession(null);
releaseDecoder(); releaseDecoder();
audioSink.reset(); audioSink.reset();
} finally { } finally {
try {
if (drmSession != null) {
drmSessionManager.releaseSession(drmSession);
}
} finally {
try {
if (pendingDrmSession != null && pendingDrmSession != drmSession) {
drmSessionManager.releaseSession(pendingDrmSession);
}
} finally {
drmSession = null;
pendingDrmSession = null;
decoderCounters.ensureUpdated();
eventDispatcher.disabled(decoderCounters); eventDispatcher.disabled(decoderCounters);
} }
} }
}
}
@Override @Override
public void handleMessage(int messageType, @Nullable Object message) throws ExoPlaybackException { public void handleMessage(int messageType, @Nullable Object message) throws ExoPlaybackException {
...@@ -615,12 +601,13 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements ...@@ -615,12 +601,13 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
return; return;
} }
drmSession = pendingDrmSession; setDecoderDrmSession(sourceDrmSession);
ExoMediaCrypto mediaCrypto = null; ExoMediaCrypto mediaCrypto = null;
if (drmSession != null) { if (decoderDrmSession != null) {
mediaCrypto = drmSession.getMediaCrypto(); mediaCrypto = decoderDrmSession.getMediaCrypto();
if (mediaCrypto == null) { if (mediaCrypto == null) {
DrmSessionException drmError = drmSession.getError(); DrmSessionException drmError = decoderDrmSession.getError();
if (drmError != null) { if (drmError != null) {
// Continue for now. We may be able to avoid failure if the session recovers, or if a new // Continue for now. We may be able to avoid failure if the session recovers, or if a new
// input format causes the session to be replaced before it's used. // input format causes the session to be replaced before it's used.
...@@ -646,17 +633,34 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements ...@@ -646,17 +633,34 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
} }
private void releaseDecoder() { private void releaseDecoder() {
if (decoder == null) {
return;
}
inputBuffer = null; inputBuffer = null;
outputBuffer = null; outputBuffer = null;
decoderReinitializationState = REINITIALIZATION_STATE_NONE;
decoderReceivedBuffers = false;
if (decoder != null) {
decoder.release(); decoder.release();
decoder = null; decoder = null;
decoderCounters.decoderReleaseCount++; decoderCounters.decoderReleaseCount++;
decoderReinitializationState = REINITIALIZATION_STATE_NONE; }
decoderReceivedBuffers = false; setDecoderDrmSession(null);
}
private void setSourceDrmSession(@Nullable DrmSession<ExoMediaCrypto> session) {
DrmSession<ExoMediaCrypto> previous = sourceDrmSession;
sourceDrmSession = session;
releaseDrmSessionIfUnused(previous);
}
private void setDecoderDrmSession(@Nullable DrmSession<ExoMediaCrypto> session) {
DrmSession<ExoMediaCrypto> previous = decoderDrmSession;
decoderDrmSession = session;
releaseDrmSessionIfUnused(previous);
}
private void releaseDrmSessionIfUnused(@Nullable DrmSession<ExoMediaCrypto> session) {
if (session != null && session != decoderDrmSession && session != sourceDrmSession) {
drmSessionManager.releaseSession(session);
}
} }
private void onInputFormatChanged(Format newFormat) throws ExoPlaybackException { private void onInputFormatChanged(Format newFormat) throws ExoPlaybackException {
...@@ -671,13 +675,16 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements ...@@ -671,13 +675,16 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
throw ExoPlaybackException.createForRenderer( throw ExoPlaybackException.createForRenderer(
new IllegalStateException("Media requires a DrmSessionManager"), getIndex()); new IllegalStateException("Media requires a DrmSessionManager"), getIndex());
} }
pendingDrmSession = drmSessionManager.acquireSession(Looper.myLooper(), DrmSession<ExoMediaCrypto> session =
inputFormat.drmInitData); drmSessionManager.acquireSession(Looper.myLooper(), newFormat.drmInitData);
if (pendingDrmSession == drmSession) { if (session == decoderDrmSession || session == sourceDrmSession) {
drmSessionManager.releaseSession(pendingDrmSession); // We already had this session. The manager must be reference counting, so release it once
// to get the count attributed to this renderer back down to 1.
drmSessionManager.releaseSession(session);
} }
setSourceDrmSession(session);
} else { } else {
pendingDrmSession = null; setSourceDrmSession(null);
} }
} }
......
...@@ -287,13 +287,13 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -287,13 +287,13 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
private final DecoderInputBuffer flagsOnlyBuffer; private final DecoderInputBuffer flagsOnlyBuffer;
private final FormatHolder formatHolder; private final FormatHolder formatHolder;
private final TimedValueQueue<Format> formatQueue; private final TimedValueQueue<Format> formatQueue;
private final List<Long> decodeOnlyPresentationTimestamps; private final ArrayList<Long> decodeOnlyPresentationTimestamps;
private final MediaCodec.BufferInfo outputBufferInfo; private final MediaCodec.BufferInfo outputBufferInfo;
@Nullable private Format inputFormat; @Nullable private Format inputFormat;
private Format outputFormat; private Format outputFormat;
private DrmSession<FrameworkMediaCrypto> drmSession; @Nullable private DrmSession<FrameworkMediaCrypto> codecDrmSession;
private DrmSession<FrameworkMediaCrypto> pendingDrmSession; @Nullable private DrmSession<FrameworkMediaCrypto> sourceDrmSession;
private long renderTimeLimitMs; private long renderTimeLimitMs;
private float rendererOperatingRate; private float rendererOperatingRate;
@Nullable private MediaCodec codec; @Nullable private MediaCodec codec;
...@@ -457,14 +457,15 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -457,14 +457,15 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
return; return;
} }
drmSession = pendingDrmSession; setCodecDrmSession(sourceDrmSession);
String mimeType = inputFormat.sampleMimeType; String mimeType = inputFormat.sampleMimeType;
MediaCrypto wrappedMediaCrypto = null; MediaCrypto wrappedMediaCrypto = null;
boolean drmSessionRequiresSecureDecoder = false; boolean drmSessionRequiresSecureDecoder = false;
if (drmSession != null) { if (codecDrmSession != null) {
FrameworkMediaCrypto mediaCrypto = drmSession.getMediaCrypto(); FrameworkMediaCrypto mediaCrypto = codecDrmSession.getMediaCrypto();
if (mediaCrypto == null) { if (mediaCrypto == null) {
DrmSessionException drmError = drmSession.getError(); DrmSessionException drmError = codecDrmSession.getError();
if (drmError != null) { if (drmError != null) {
// Continue for now. We may be able to avoid failure if the session recovers, or if a new // Continue for now. We may be able to avoid failure if the session recovers, or if a new
// input format causes the session to be replaced before it's used. // input format causes the session to be replaced before it's used.
...@@ -477,9 +478,9 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -477,9 +478,9 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
drmSessionRequiresSecureDecoder = mediaCrypto.requiresSecureDecoderComponent(mimeType); drmSessionRequiresSecureDecoder = mediaCrypto.requiresSecureDecoderComponent(mimeType);
} }
if (deviceNeedsDrmKeysToConfigureCodecWorkaround()) { if (deviceNeedsDrmKeysToConfigureCodecWorkaround()) {
@DrmSession.State int drmSessionState = drmSession.getState(); @DrmSession.State int drmSessionState = codecDrmSession.getState();
if (drmSessionState == DrmSession.STATE_ERROR) { if (drmSessionState == DrmSession.STATE_ERROR) {
throw ExoPlaybackException.createForRenderer(drmSession.getError(), getIndex()); throw ExoPlaybackException.createForRenderer(codecDrmSession.getError(), getIndex());
} else if (drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS) { } else if (drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS) {
// Wait for keys. // Wait for keys.
return; return;
...@@ -552,7 +553,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -552,7 +553,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
@Override @Override
protected void onDisabled() { protected void onDisabled() {
inputFormat = null; inputFormat = null;
if (drmSession != null || pendingDrmSession != null) { if (codecDrmSession != null || sourceDrmSession != null) {
// TODO: Do something better with this case. // TODO: Do something better with this case.
onReset(); onReset();
} else { } else {
...@@ -565,26 +566,12 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -565,26 +566,12 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
try { try {
releaseCodec(); releaseCodec();
} finally { } finally {
try { setSourceDrmSession(null);
if (drmSession != null) {
drmSessionManager.releaseSession(drmSession);
}
} finally {
try {
if (pendingDrmSession != null && pendingDrmSession != drmSession) {
drmSessionManager.releaseSession(pendingDrmSession);
}
} finally {
drmSession = null;
pendingDrmSession = null;
}
}
} }
} }
protected void releaseCodec() { protected void releaseCodec() {
availableCodecInfos = null; availableCodecInfos = null;
if (codec != null) {
codecInfo = null; codecInfo = null;
codecFormat = null; codecFormat = null;
resetInputBuffer(); resetInputBuffer();
...@@ -593,23 +580,18 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -593,23 +580,18 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
waitingForKeys = false; waitingForKeys = false;
codecHotswapDeadlineMs = C.TIME_UNSET; codecHotswapDeadlineMs = C.TIME_UNSET;
decodeOnlyPresentationTimestamps.clear(); decodeOnlyPresentationTimestamps.clear();
try {
if (codec != null) {
decoderCounters.decoderReleaseCount++; decoderCounters.decoderReleaseCount++;
try { try {
codec.stop(); codec.stop();
} finally { } finally {
try {
codec.release(); codec.release();
} finally {
codec = null;
if (drmSession != null && pendingDrmSession != drmSession) {
try {
drmSessionManager.releaseSession(drmSession);
} finally {
drmSession = null;
}
}
} }
} }
} finally {
codec = null;
setCodecDrmSession(null);
} }
} }
...@@ -928,6 +910,24 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -928,6 +910,24 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
outputBuffer = null; outputBuffer = null;
} }
private void setSourceDrmSession(@Nullable DrmSession<FrameworkMediaCrypto> session) {
DrmSession<FrameworkMediaCrypto> previous = sourceDrmSession;
sourceDrmSession = session;
releaseDrmSessionIfUnused(previous);
}
private void setCodecDrmSession(@Nullable DrmSession<FrameworkMediaCrypto> session) {
DrmSession<FrameworkMediaCrypto> previous = codecDrmSession;
codecDrmSession = session;
releaseDrmSessionIfUnused(previous);
}
private void releaseDrmSessionIfUnused(@Nullable DrmSession<FrameworkMediaCrypto> session) {
if (session != null && session != codecDrmSession && session != sourceDrmSession) {
drmSessionManager.releaseSession(session);
}
}
/** /**
* @return Whether it may be possible to feed more input data. * @return Whether it may be possible to feed more input data.
* @throws ExoPlaybackException If an error occurs feeding the input buffer. * @throws ExoPlaybackException If an error occurs feeding the input buffer.
...@@ -1082,12 +1082,12 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -1082,12 +1082,12 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
} }
private boolean shouldWaitForKeys(boolean bufferEncrypted) throws ExoPlaybackException { private boolean shouldWaitForKeys(boolean bufferEncrypted) throws ExoPlaybackException {
if (drmSession == null || (!bufferEncrypted && playClearSamplesWithoutKeys)) { if (codecDrmSession == null || (!bufferEncrypted && playClearSamplesWithoutKeys)) {
return false; return false;
} }
@DrmSession.State int drmSessionState = drmSession.getState(); @DrmSession.State int drmSessionState = codecDrmSession.getState();
if (drmSessionState == DrmSession.STATE_ERROR) { if (drmSessionState == DrmSession.STATE_ERROR) {
throw ExoPlaybackException.createForRenderer(drmSession.getError(), getIndex()); throw ExoPlaybackException.createForRenderer(codecDrmSession.getError(), getIndex());
} }
return drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS; return drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS;
} }
...@@ -1126,13 +1126,16 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -1126,13 +1126,16 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
throw ExoPlaybackException.createForRenderer( throw ExoPlaybackException.createForRenderer(
new IllegalStateException("Media requires a DrmSessionManager"), getIndex()); new IllegalStateException("Media requires a DrmSessionManager"), getIndex());
} }
pendingDrmSession = DrmSession<FrameworkMediaCrypto> session =
drmSessionManager.acquireSession(Looper.myLooper(), newFormat.drmInitData); drmSessionManager.acquireSession(Looper.myLooper(), newFormat.drmInitData);
if (pendingDrmSession == drmSession) { if (session == codecDrmSession || session == sourceDrmSession) {
drmSessionManager.releaseSession(pendingDrmSession); // We already had this session. The manager must be reference counting, so release it once
// to get the count attributed to this renderer back down to 1.
drmSessionManager.releaseSession(session);
} }
setSourceDrmSession(session);
} else { } else {
pendingDrmSession = null; setSourceDrmSession(null);
} }
} }
...@@ -1143,7 +1146,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -1143,7 +1146,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
// We have an existing codec that we may need to reconfigure or re-initialize. If the existing // We have an existing codec that we may need to reconfigure or re-initialize. If the existing
// codec instance is being kept then its operating rate may need to be updated. // codec instance is being kept then its operating rate may need to be updated.
if (pendingDrmSession != drmSession) { if (sourceDrmSession != codecDrmSession) {
drainAndReinitializeCodec(); drainAndReinitializeCodec();
} else { } else {
switch (canKeepCodec(codec, codecInfo, codecFormat, newFormat)) { switch (canKeepCodec(codec, codecInfo, codecFormat, newFormat)) {
......
...@@ -375,7 +375,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -375,7 +375,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
try { try {
super.onDisabled(); super.onDisabled();
} finally { } finally {
decoderCounters.ensureUpdated();
eventDispatcher.disabled(decoderCounters); eventDispatcher.disabled(decoderCounters);
} }
} }
......
...@@ -179,6 +179,7 @@ public interface VideoRendererEventListener { ...@@ -179,6 +179,7 @@ public interface VideoRendererEventListener {
/** Invokes {@link VideoRendererEventListener#onVideoDisabled(DecoderCounters)}. */ /** Invokes {@link VideoRendererEventListener#onVideoDisabled(DecoderCounters)}. */
public void disabled(DecoderCounters counters) { public void disabled(DecoderCounters counters) {
counters.ensureUpdated();
if (listener != null) { if (listener != null) {
handler.post( handler.post(
() -> { () -> {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment