mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Add format and renderer support to renderer exceptions.
This makes the exception easier to interpret and helps with debugging of externally reported issues. PiperOrigin-RevId: 283965317
This commit is contained in:
parent
cbdf45aa5f
commit
64703e4aa6
@ -56,6 +56,7 @@
|
|||||||
* Add `MediaPeriod.isLoading` to improve `Player.isLoading` state.
|
* Add `MediaPeriod.isLoading` to improve `Player.isLoading` state.
|
||||||
* Fix issue where player errors are thrown too early at playlist transitions
|
* Fix issue where player errors are thrown too early at playlist transitions
|
||||||
([#5407](https://github.com/google/ExoPlayer/issues/5407)).
|
([#5407](https://github.com/google/ExoPlayer/issues/5407)).
|
||||||
|
* Add `Format` and renderer support flags to renderer `ExoPlaybackException`s.
|
||||||
* DRM:
|
* DRM:
|
||||||
* Inject `DrmSessionManager` into the `MediaSources` instead of `Renderers`.
|
* Inject `DrmSessionManager` into the `MediaSources` instead of `Renderers`.
|
||||||
This allows each `MediaSource` in a `ConcatenatingMediaSource` to use a
|
This allows each `MediaSource` in a `ConcatenatingMediaSource` to use a
|
||||||
|
@ -44,6 +44,7 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
|
|||||||
private long streamOffsetUs;
|
private long streamOffsetUs;
|
||||||
private long readingPositionUs;
|
private long readingPositionUs;
|
||||||
private boolean streamIsFinal;
|
private boolean streamIsFinal;
|
||||||
|
private boolean throwRendererExceptionIsExecuting;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param trackType The track type that the renderer handles. One of the {@link C}
|
* @param trackType The track type that the renderer handles. One of the {@link C}
|
||||||
@ -314,8 +315,8 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
|
|||||||
@Nullable DrmSession<T> newSourceDrmSession = null;
|
@Nullable DrmSession<T> newSourceDrmSession = null;
|
||||||
if (newFormat.drmInitData != null) {
|
if (newFormat.drmInitData != null) {
|
||||||
if (drmSessionManager == null) {
|
if (drmSessionManager == null) {
|
||||||
throw ExoPlaybackException.createForRenderer(
|
throw createRendererException(
|
||||||
new IllegalStateException("Media requires a DrmSessionManager"), getIndex());
|
new IllegalStateException("Media requires a DrmSessionManager"), newFormat);
|
||||||
}
|
}
|
||||||
newSourceDrmSession =
|
newSourceDrmSession =
|
||||||
drmSessionManager.acquireSession(
|
drmSessionManager.acquireSession(
|
||||||
@ -334,6 +335,30 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an {@link ExoPlaybackException} of type {@link ExoPlaybackException#TYPE_RENDERER} for
|
||||||
|
* this renderer.
|
||||||
|
*
|
||||||
|
* @param cause The cause of the exception.
|
||||||
|
* @param format The current format used by the renderer. May be null.
|
||||||
|
*/
|
||||||
|
protected final ExoPlaybackException createRendererException(
|
||||||
|
Exception cause, @Nullable Format format) {
|
||||||
|
@FormatSupport int formatSupport = RendererCapabilities.FORMAT_HANDLED;
|
||||||
|
if (format != null && !throwRendererExceptionIsExecuting) {
|
||||||
|
// Prevent recursive re-entry from subclass supportsFormat implementations.
|
||||||
|
throwRendererExceptionIsExecuting = true;
|
||||||
|
try {
|
||||||
|
formatSupport = RendererCapabilities.getFormatSupport(supportsFormat(format));
|
||||||
|
} catch (ExoPlaybackException e) {
|
||||||
|
// Ignore, we are already failing.
|
||||||
|
} finally {
|
||||||
|
throwRendererExceptionIsExecuting = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ExoPlaybackException.createForRenderer(cause, getIndex(), format, formatSupport);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads from the enabled upstream source. If the upstream source has been read to the end then
|
* Reads from the enabled upstream source. If the upstream source has been read to the end then
|
||||||
* {@link C#RESULT_BUFFER_READ} is only returned if {@link #setCurrentStreamFinal()} has been
|
* {@link C#RESULT_BUFFER_READ} is only returned if {@link #setCurrentStreamFinal()} has been
|
||||||
@ -341,16 +366,16 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
|
|||||||
*
|
*
|
||||||
* @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
|
||||||
* end of the stream. If the end of the stream has been reached, the
|
* end of the stream. If the end of the stream has been reached, the {@link
|
||||||
* {@link C#BUFFER_FLAG_END_OF_STREAM} flag will be set on the buffer.
|
* C#BUFFER_FLAG_END_OF_STREAM} flag will be set on the buffer.
|
||||||
* @param formatRequired Whether the caller requires that the format of the stream be read even if
|
* @param formatRequired Whether the caller requires that the format of the stream be read even if
|
||||||
* it's not changing. A sample will never be read if set to true, however it is still possible
|
* it's not changing. A sample will never be read if set to true, however it is still possible
|
||||||
* for the end of stream or nothing to be read.
|
* for the end of stream or nothing to be read.
|
||||||
* @return The result, which can be {@link C#RESULT_NOTHING_READ}, {@link C#RESULT_FORMAT_READ} or
|
* @return The result, which can be {@link C#RESULT_NOTHING_READ}, {@link C#RESULT_FORMAT_READ} or
|
||||||
* {@link C#RESULT_BUFFER_READ}.
|
* {@link C#RESULT_BUFFER_READ}.
|
||||||
*/
|
*/
|
||||||
protected final int readSource(FormatHolder formatHolder, DecoderInputBuffer buffer,
|
protected final int readSource(
|
||||||
boolean formatRequired) {
|
FormatHolder formatHolder, DecoderInputBuffer buffer, boolean formatRequired) {
|
||||||
int result = stream.readData(formatHolder, buffer, formatRequired);
|
int result = stream.readData(formatHolder, buffer, formatRequired);
|
||||||
if (result == C.RESULT_BUFFER_READ) {
|
if (result == C.RESULT_BUFFER_READ) {
|
||||||
if (buffer.isEndOfStream()) {
|
if (buffer.isEndOfStream()) {
|
||||||
|
@ -18,6 +18,7 @@ package com.google.android.exoplayer2;
|
|||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import androidx.annotation.IntDef;
|
import androidx.annotation.IntDef;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import com.google.android.exoplayer2.RendererCapabilities.FormatSupport;
|
||||||
import com.google.android.exoplayer2.source.MediaSource;
|
import com.google.android.exoplayer2.source.MediaSource;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -74,6 +75,19 @@ public final class ExoPlaybackException extends Exception {
|
|||||||
*/
|
*/
|
||||||
public final int rendererIndex;
|
public final int rendererIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If {@link #type} is {@link #TYPE_RENDERER}, this is the {@link Format} the renderer was using
|
||||||
|
* at the time of the exception, or null if the renderer wasn't using a {@link Format}.
|
||||||
|
*/
|
||||||
|
@Nullable public final Format rendererFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If {@link #type} is {@link #TYPE_RENDERER}, this is the level of {@link FormatSupport} of the
|
||||||
|
* renderer for {@link #rendererFormat}. If {@link #rendererFormat} is null, this is {@link
|
||||||
|
* RendererCapabilities#FORMAT_HANDLED}.
|
||||||
|
*/
|
||||||
|
@FormatSupport public final int rendererFormatSupport;
|
||||||
|
|
||||||
/** The value of {@link SystemClock#elapsedRealtime()} when this exception was created. */
|
/** The value of {@link SystemClock#elapsedRealtime()} when this exception was created. */
|
||||||
public final long timestampMs;
|
public final long timestampMs;
|
||||||
|
|
||||||
@ -86,7 +100,7 @@ public final class ExoPlaybackException extends Exception {
|
|||||||
* @return The created instance.
|
* @return The created instance.
|
||||||
*/
|
*/
|
||||||
public static ExoPlaybackException createForSource(IOException cause) {
|
public static ExoPlaybackException createForSource(IOException cause) {
|
||||||
return new ExoPlaybackException(TYPE_SOURCE, cause, /* rendererIndex= */ C.INDEX_UNSET);
|
return new ExoPlaybackException(TYPE_SOURCE, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,10 +108,23 @@ public final class ExoPlaybackException extends Exception {
|
|||||||
*
|
*
|
||||||
* @param cause The cause of the failure.
|
* @param cause The cause of the failure.
|
||||||
* @param rendererIndex The index of the renderer in which the failure occurred.
|
* @param rendererIndex The index of the renderer in which the failure occurred.
|
||||||
|
* @param rendererFormat The {@link Format} the renderer was using at the time of the exception,
|
||||||
|
* or null if the renderer wasn't using a {@link Format}.
|
||||||
|
* @param rendererFormatSupport The {@link FormatSupport} of the renderer for {@code
|
||||||
|
* rendererFormat}. Ignored if {@code rendererFormat} is null.
|
||||||
* @return The created instance.
|
* @return The created instance.
|
||||||
*/
|
*/
|
||||||
public static ExoPlaybackException createForRenderer(Exception cause, int rendererIndex) {
|
public static ExoPlaybackException createForRenderer(
|
||||||
return new ExoPlaybackException(TYPE_RENDERER, cause, rendererIndex);
|
Exception cause,
|
||||||
|
int rendererIndex,
|
||||||
|
@Nullable Format rendererFormat,
|
||||||
|
@FormatSupport int rendererFormatSupport) {
|
||||||
|
return new ExoPlaybackException(
|
||||||
|
TYPE_RENDERER,
|
||||||
|
cause,
|
||||||
|
rendererIndex,
|
||||||
|
rendererFormat,
|
||||||
|
rendererFormat == null ? RendererCapabilities.FORMAT_HANDLED : rendererFormatSupport);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -107,7 +134,7 @@ public final class ExoPlaybackException extends Exception {
|
|||||||
* @return The created instance.
|
* @return The created instance.
|
||||||
*/
|
*/
|
||||||
public static ExoPlaybackException createForUnexpected(RuntimeException cause) {
|
public static ExoPlaybackException createForUnexpected(RuntimeException cause) {
|
||||||
return new ExoPlaybackException(TYPE_UNEXPECTED, cause, /* rendererIndex= */ C.INDEX_UNSET);
|
return new ExoPlaybackException(TYPE_UNEXPECTED, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -127,14 +154,30 @@ public final class ExoPlaybackException extends Exception {
|
|||||||
* @return The created instance.
|
* @return The created instance.
|
||||||
*/
|
*/
|
||||||
public static ExoPlaybackException createForOutOfMemoryError(OutOfMemoryError cause) {
|
public static ExoPlaybackException createForOutOfMemoryError(OutOfMemoryError cause) {
|
||||||
return new ExoPlaybackException(TYPE_OUT_OF_MEMORY, cause, /* rendererIndex= */ C.INDEX_UNSET);
|
return new ExoPlaybackException(TYPE_OUT_OF_MEMORY, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExoPlaybackException(@Type int type, Throwable cause, int rendererIndex) {
|
private ExoPlaybackException(@Type int type, Throwable cause) {
|
||||||
|
this(
|
||||||
|
type,
|
||||||
|
cause,
|
||||||
|
/* rendererIndex= */ C.INDEX_UNSET,
|
||||||
|
/* rendererFormat= */ null,
|
||||||
|
/* rendererFormatSupport= */ RendererCapabilities.FORMAT_HANDLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ExoPlaybackException(
|
||||||
|
@Type int type,
|
||||||
|
Throwable cause,
|
||||||
|
int rendererIndex,
|
||||||
|
@Nullable Format rendererFormat,
|
||||||
|
@FormatSupport int rendererFormatSupport) {
|
||||||
super(cause);
|
super(cause);
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.cause = cause;
|
this.cause = cause;
|
||||||
this.rendererIndex = rendererIndex;
|
this.rendererIndex = rendererIndex;
|
||||||
|
this.rendererFormat = rendererFormat;
|
||||||
|
this.rendererFormatSupport = rendererFormatSupport;
|
||||||
timestampMs = SystemClock.elapsedRealtime();
|
timestampMs = SystemClock.elapsedRealtime();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,6 +185,8 @@ public final class ExoPlaybackException extends Exception {
|
|||||||
super(message);
|
super(message);
|
||||||
this.type = type;
|
this.type = type;
|
||||||
rendererIndex = C.INDEX_UNSET;
|
rendererIndex = C.INDEX_UNSET;
|
||||||
|
rendererFormat = null;
|
||||||
|
rendererFormatSupport = RendererCapabilities.FORMAT_UNSUPPORTED_TYPE;
|
||||||
cause = null;
|
cause = null;
|
||||||
timestampMs = SystemClock.elapsedRealtime();
|
timestampMs = SystemClock.elapsedRealtime();
|
||||||
}
|
}
|
||||||
|
@ -384,7 +384,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
}
|
}
|
||||||
maybeNotifyPlaybackInfoChanged();
|
maybeNotifyPlaybackInfoChanged();
|
||||||
} catch (ExoPlaybackException e) {
|
} catch (ExoPlaybackException e) {
|
||||||
Log.e(TAG, "Playback error.", e);
|
Log.e(TAG, getExoPlaybackExceptionMessage(e), e);
|
||||||
stopInternal(
|
stopInternal(
|
||||||
/* forceResetRenderers= */ true,
|
/* forceResetRenderers= */ true,
|
||||||
/* resetPositionAndState= */ false,
|
/* resetPositionAndState= */ false,
|
||||||
@ -417,6 +417,20 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
|
|
||||||
// Private methods.
|
// Private methods.
|
||||||
|
|
||||||
|
private String getExoPlaybackExceptionMessage(ExoPlaybackException e) {
|
||||||
|
if (e.type != ExoPlaybackException.TYPE_RENDERER) {
|
||||||
|
return "Playback error.";
|
||||||
|
}
|
||||||
|
return "Renderer error: index="
|
||||||
|
+ e.rendererIndex
|
||||||
|
+ ", type="
|
||||||
|
+ Util.getTrackTypeString(renderers[e.rendererIndex].getTrackType())
|
||||||
|
+ ", format="
|
||||||
|
+ e.rendererFormat
|
||||||
|
+ ", rendererSupport="
|
||||||
|
+ RendererCapabilities.getFormatSupportString(e.rendererFormatSupport);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Blocks the current thread until {@link #releaseInternal()} is executed on the playback Thread.
|
* Blocks the current thread until {@link #releaseInternal()} is executed on the playback Thread.
|
||||||
*
|
*
|
||||||
|
@ -237,6 +237,29 @@ public interface RendererCapabilities {
|
|||||||
return supportFlags & TUNNELING_SUPPORT_MASK;
|
return supportFlags & TUNNELING_SUPPORT_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns string representation of a {@link FormatSupport} flag.
|
||||||
|
*
|
||||||
|
* @param formatSupport A {@link FormatSupport} flag.
|
||||||
|
* @return A string representation of the flag.
|
||||||
|
*/
|
||||||
|
static String getFormatSupportString(@FormatSupport int formatSupport) {
|
||||||
|
switch (formatSupport) {
|
||||||
|
case RendererCapabilities.FORMAT_HANDLED:
|
||||||
|
return "YES";
|
||||||
|
case RendererCapabilities.FORMAT_EXCEEDS_CAPABILITIES:
|
||||||
|
return "NO_EXCEEDS_CAPABILITIES";
|
||||||
|
case RendererCapabilities.FORMAT_UNSUPPORTED_DRM:
|
||||||
|
return "NO_UNSUPPORTED_DRM";
|
||||||
|
case RendererCapabilities.FORMAT_UNSUPPORTED_SUBTYPE:
|
||||||
|
return "NO_UNSUPPORTED_TYPE";
|
||||||
|
case RendererCapabilities.FORMAT_UNSUPPORTED_TYPE:
|
||||||
|
return "NO";
|
||||||
|
default:
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the track type that the {@link Renderer} handles. For example, a video renderer will
|
* Returns the track type that the {@link Renderer} handles. For example, a video renderer will
|
||||||
* return {@link C#TRACK_TYPE_VIDEO}, an audio renderer will return {@link C#TRACK_TYPE_AUDIO}, a
|
* return {@link C#TRACK_TYPE_VIDEO}, an audio renderer will return {@link C#TRACK_TYPE_AUDIO}, a
|
||||||
|
@ -90,10 +90,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
private boolean codecNeedsDiscardChannelsWorkaround;
|
private boolean codecNeedsDiscardChannelsWorkaround;
|
||||||
private boolean codecNeedsEosBufferTimestampWorkaround;
|
private boolean codecNeedsEosBufferTimestampWorkaround;
|
||||||
private android.media.MediaFormat passthroughMediaFormat;
|
private android.media.MediaFormat passthroughMediaFormat;
|
||||||
private @C.Encoding int pcmEncoding;
|
@Nullable private Format inputFormat;
|
||||||
private int channelCount;
|
|
||||||
private int encoderDelay;
|
|
||||||
private int encoderPadding;
|
|
||||||
private long currentPositionUs;
|
private long currentPositionUs;
|
||||||
private boolean allowFirstBufferPositionDiscontinuity;
|
private boolean allowFirstBufferPositionDiscontinuity;
|
||||||
private boolean allowPositionDiscontinuity;
|
private boolean allowPositionDiscontinuity;
|
||||||
@ -551,15 +548,8 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
@Override
|
@Override
|
||||||
protected void onInputFormatChanged(FormatHolder formatHolder) throws ExoPlaybackException {
|
protected void onInputFormatChanged(FormatHolder formatHolder) throws ExoPlaybackException {
|
||||||
super.onInputFormatChanged(formatHolder);
|
super.onInputFormatChanged(formatHolder);
|
||||||
Format newFormat = formatHolder.format;
|
inputFormat = formatHolder.format;
|
||||||
eventDispatcher.inputFormatChanged(newFormat);
|
eventDispatcher.inputFormatChanged(inputFormat);
|
||||||
// If the input format is anything other than PCM then we assume that the audio decoder will
|
|
||||||
// output 16-bit PCM.
|
|
||||||
pcmEncoding = MimeTypes.AUDIO_RAW.equals(newFormat.sampleMimeType) ? newFormat.pcmEncoding
|
|
||||||
: C.ENCODING_PCM_16BIT;
|
|
||||||
channelCount = newFormat.channelCount;
|
|
||||||
encoderDelay = newFormat.encoderDelay;
|
|
||||||
encoderPadding = newFormat.encoderPadding;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -575,14 +565,14 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
mediaFormat.getString(MediaFormat.KEY_MIME));
|
mediaFormat.getString(MediaFormat.KEY_MIME));
|
||||||
} else {
|
} else {
|
||||||
mediaFormat = outputMediaFormat;
|
mediaFormat = outputMediaFormat;
|
||||||
encoding = pcmEncoding;
|
encoding = getPcmEncoding(inputFormat);
|
||||||
}
|
}
|
||||||
int channelCount = mediaFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
|
int channelCount = mediaFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
|
||||||
int sampleRate = mediaFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
|
int sampleRate = mediaFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
|
||||||
int[] channelMap;
|
int[] channelMap;
|
||||||
if (codecNeedsDiscardChannelsWorkaround && channelCount == 6 && this.channelCount < 6) {
|
if (codecNeedsDiscardChannelsWorkaround && channelCount == 6 && inputFormat.channelCount < 6) {
|
||||||
channelMap = new int[this.channelCount];
|
channelMap = new int[inputFormat.channelCount];
|
||||||
for (int i = 0; i < this.channelCount; i++) {
|
for (int i = 0; i < inputFormat.channelCount; i++) {
|
||||||
channelMap[i] = i;
|
channelMap[i] = i;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -590,10 +580,17 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
audioSink.configure(encoding, channelCount, sampleRate, 0, channelMap, encoderDelay,
|
audioSink.configure(
|
||||||
encoderPadding);
|
encoding,
|
||||||
|
channelCount,
|
||||||
|
sampleRate,
|
||||||
|
0,
|
||||||
|
channelMap,
|
||||||
|
inputFormat.encoderDelay,
|
||||||
|
inputFormat.encoderPadding);
|
||||||
} catch (AudioSink.ConfigurationException e) {
|
} catch (AudioSink.ConfigurationException e) {
|
||||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
// TODO(internal: b/145658993) Use outputFormat instead.
|
||||||
|
throw createRendererException(e, inputFormat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -820,7 +817,8 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (AudioSink.InitializationException | AudioSink.WriteException e) {
|
} catch (AudioSink.InitializationException | AudioSink.WriteException e) {
|
||||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
// TODO(internal: b/145658993) Use outputFormat instead.
|
||||||
|
throw createRendererException(e, inputFormat);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -830,7 +828,8 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
try {
|
try {
|
||||||
audioSink.playToEndOfStream();
|
audioSink.playToEndOfStream();
|
||||||
} catch (AudioSink.WriteException e) {
|
} catch (AudioSink.WriteException e) {
|
||||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
// TODO(internal: b/145658993) Use outputFormat instead.
|
||||||
|
throw createRendererException(e, inputFormat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -992,6 +991,15 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
|| Util.DEVICE.startsWith("ms01"));
|
|| Util.DEVICE.startsWith("ms01"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@C.Encoding
|
||||||
|
private static int getPcmEncoding(Format format) {
|
||||||
|
// If the format is anything other than PCM then we assume that the audio decoder will output
|
||||||
|
// 16-bit PCM.
|
||||||
|
return MimeTypes.AUDIO_RAW.equals(format.sampleMimeType)
|
||||||
|
? format.pcmEncoding
|
||||||
|
: C.ENCODING_PCM_16BIT;
|
||||||
|
}
|
||||||
|
|
||||||
private final class AudioSinkListener implements AudioSink.Listener {
|
private final class AudioSinkListener implements AudioSink.Listener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -263,7 +263,7 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
|
|||||||
try {
|
try {
|
||||||
audioSink.playToEndOfStream();
|
audioSink.playToEndOfStream();
|
||||||
} catch (AudioSink.WriteException e) {
|
} catch (AudioSink.WriteException e) {
|
||||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
throw createRendererException(e, inputFormat);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -300,7 +300,7 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
|
|||||||
TraceUtil.endSection();
|
TraceUtil.endSection();
|
||||||
} catch (AudioDecoderException | AudioSink.ConfigurationException
|
} catch (AudioDecoderException | AudioSink.ConfigurationException
|
||||||
| AudioSink.InitializationException | AudioSink.WriteException e) {
|
| AudioSink.InitializationException | AudioSink.WriteException e) {
|
||||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
throw createRendererException(e, inputFormat);
|
||||||
}
|
}
|
||||||
decoderCounters.ensureUpdated();
|
decoderCounters.ensureUpdated();
|
||||||
}
|
}
|
||||||
@ -483,7 +483,7 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
|
|||||||
}
|
}
|
||||||
@DrmSession.State int drmSessionState = decoderDrmSession.getState();
|
@DrmSession.State int drmSessionState = decoderDrmSession.getState();
|
||||||
if (drmSessionState == DrmSession.STATE_ERROR) {
|
if (drmSessionState == DrmSession.STATE_ERROR) {
|
||||||
throw ExoPlaybackException.createForRenderer(decoderDrmSession.getError(), getIndex());
|
throw createRendererException(decoderDrmSession.getError(), inputFormat);
|
||||||
}
|
}
|
||||||
return drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS;
|
return drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS;
|
||||||
}
|
}
|
||||||
@ -493,7 +493,8 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
|
|||||||
try {
|
try {
|
||||||
audioSink.playToEndOfStream();
|
audioSink.playToEndOfStream();
|
||||||
} catch (AudioSink.WriteException e) {
|
} catch (AudioSink.WriteException e) {
|
||||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
// TODO(internal: b/145658993) Use outputFormat for the call from drainOutputBuffer.
|
||||||
|
throw createRendererException(e, inputFormat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -644,7 +645,7 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
|
|||||||
codecInitializedTimestamp - codecInitializingTimestamp);
|
codecInitializedTimestamp - codecInitializingTimestamp);
|
||||||
decoderCounters.decoderInitCount++;
|
decoderCounters.decoderInitCount++;
|
||||||
} catch (AudioDecoderException e) {
|
} catch (AudioDecoderException e) {
|
||||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
throw createRendererException(e, inputFormat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -527,7 +527,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
try {
|
try {
|
||||||
return supportsFormat(mediaCodecSelector, drmSessionManager, format);
|
return supportsFormat(mediaCodecSelector, drmSessionManager, format);
|
||||||
} catch (DecoderQueryException e) {
|
} catch (DecoderQueryException e) {
|
||||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
throw createRendererException(e, format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -602,7 +602,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
try {
|
try {
|
||||||
mediaCrypto = new MediaCrypto(sessionMediaCrypto.uuid, sessionMediaCrypto.sessionId);
|
mediaCrypto = new MediaCrypto(sessionMediaCrypto.uuid, sessionMediaCrypto.sessionId);
|
||||||
} catch (MediaCryptoException e) {
|
} catch (MediaCryptoException e) {
|
||||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
throw createRendererException(e, inputFormat);
|
||||||
}
|
}
|
||||||
mediaCryptoRequiresSecureDecoder =
|
mediaCryptoRequiresSecureDecoder =
|
||||||
!sessionMediaCrypto.forceAllowInsecureDecoderComponents
|
!sessionMediaCrypto.forceAllowInsecureDecoderComponents
|
||||||
@ -612,7 +612,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
if (FrameworkMediaCrypto.WORKAROUND_DEVICE_NEEDS_KEYS_TO_CONFIGURE_CODEC) {
|
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 createRendererException(codecDrmSession.getError(), inputFormat);
|
||||||
} else if (drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS) {
|
} else if (drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS) {
|
||||||
// Wait for keys.
|
// Wait for keys.
|
||||||
return;
|
return;
|
||||||
@ -623,7 +623,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
try {
|
try {
|
||||||
maybeInitCodecWithFallback(mediaCrypto, mediaCryptoRequiresSecureDecoder);
|
maybeInitCodecWithFallback(mediaCrypto, mediaCryptoRequiresSecureDecoder);
|
||||||
} catch (DecoderInitializationException e) {
|
} catch (DecoderInitializationException e) {
|
||||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
throw createRendererException(e, inputFormat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -790,8 +790,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
decoderCounters.ensureUpdated();
|
decoderCounters.ensureUpdated();
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
if (isMediaCodecException(e)) {
|
if (isMediaCodecException(e)) {
|
||||||
throw ExoPlaybackException.createForRenderer(
|
throw createRendererException(e, inputFormat);
|
||||||
createDecoderException(e, getCodecInfo()), getIndex());
|
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
@ -1210,7 +1209,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
resetInputBuffer();
|
resetInputBuffer();
|
||||||
}
|
}
|
||||||
} catch (CryptoException e) {
|
} catch (CryptoException e) {
|
||||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
throw createRendererException(e, inputFormat);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1266,7 +1265,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
codecReconfigurationState = RECONFIGURATION_STATE_NONE;
|
codecReconfigurationState = RECONFIGURATION_STATE_NONE;
|
||||||
decoderCounters.inputBufferCount++;
|
decoderCounters.inputBufferCount++;
|
||||||
} catch (CryptoException e) {
|
} catch (CryptoException e) {
|
||||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
throw createRendererException(e, inputFormat);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1279,7 +1278,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
}
|
}
|
||||||
@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 createRendererException(codecDrmSession.getError(), inputFormat);
|
||||||
}
|
}
|
||||||
return drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS;
|
return drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS;
|
||||||
}
|
}
|
||||||
@ -1822,7 +1821,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
try {
|
try {
|
||||||
mediaCrypto.setMediaDrmSession(sessionMediaCrypto.sessionId);
|
mediaCrypto.setMediaDrmSession(sessionMediaCrypto.sessionId);
|
||||||
} catch (MediaCryptoException e) {
|
} catch (MediaCryptoException e) {
|
||||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
throw createRendererException(e, inputFormat);
|
||||||
}
|
}
|
||||||
setCodecDrmSession(sourceDrmSession);
|
setCodecDrmSession(sourceDrmSession);
|
||||||
codecDrainState = DRAIN_STATE_NONE;
|
codecDrainState = DRAIN_STATE_NONE;
|
||||||
|
@ -165,7 +165,7 @@ public final class TextRenderer extends BaseRenderer implements Callback {
|
|||||||
try {
|
try {
|
||||||
nextSubtitle = decoder.dequeueOutputBuffer();
|
nextSubtitle = decoder.dequeueOutputBuffer();
|
||||||
} catch (SubtitleDecoderException e) {
|
} catch (SubtitleDecoderException e) {
|
||||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
throw createRendererException(e, streamFormat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,7 +247,7 @@ public final class TextRenderer extends BaseRenderer implements Callback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (SubtitleDecoderException e) {
|
} catch (SubtitleDecoderException e) {
|
||||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
throw createRendererException(e, streamFormat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@ import com.google.android.exoplayer2.Player;
|
|||||||
import com.google.android.exoplayer2.Player.PlaybackSuppressionReason;
|
import com.google.android.exoplayer2.Player.PlaybackSuppressionReason;
|
||||||
import com.google.android.exoplayer2.RendererCapabilities;
|
import com.google.android.exoplayer2.RendererCapabilities;
|
||||||
import com.google.android.exoplayer2.RendererCapabilities.AdaptiveSupport;
|
import com.google.android.exoplayer2.RendererCapabilities.AdaptiveSupport;
|
||||||
import com.google.android.exoplayer2.RendererCapabilities.FormatSupport;
|
|
||||||
import com.google.android.exoplayer2.Timeline;
|
import com.google.android.exoplayer2.Timeline;
|
||||||
import com.google.android.exoplayer2.analytics.AnalyticsListener;
|
import com.google.android.exoplayer2.analytics.AnalyticsListener;
|
||||||
import com.google.android.exoplayer2.audio.AudioAttributes;
|
import com.google.android.exoplayer2.audio.AudioAttributes;
|
||||||
@ -218,7 +217,7 @@ public class EventLogger implements AnalyticsListener {
|
|||||||
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
|
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
|
||||||
String status = getTrackStatusString(trackSelection, trackGroup, trackIndex);
|
String status = getTrackStatusString(trackSelection, trackGroup, trackIndex);
|
||||||
String formatSupport =
|
String formatSupport =
|
||||||
getFormatSupportString(
|
RendererCapabilities.getFormatSupportString(
|
||||||
mappedTrackInfo.getTrackSupport(rendererIndex, groupIndex, trackIndex));
|
mappedTrackInfo.getTrackSupport(rendererIndex, groupIndex, trackIndex));
|
||||||
logd(
|
logd(
|
||||||
" "
|
" "
|
||||||
@ -257,7 +256,8 @@ public class EventLogger implements AnalyticsListener {
|
|||||||
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
|
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
|
||||||
String status = getTrackStatusString(false);
|
String status = getTrackStatusString(false);
|
||||||
String formatSupport =
|
String formatSupport =
|
||||||
getFormatSupportString(RendererCapabilities.FORMAT_UNSUPPORTED_TYPE);
|
RendererCapabilities.getFormatSupportString(
|
||||||
|
RendererCapabilities.FORMAT_UNSUPPORTED_TYPE);
|
||||||
logd(
|
logd(
|
||||||
" "
|
" "
|
||||||
+ status
|
+ status
|
||||||
@ -289,7 +289,7 @@ public class EventLogger implements AnalyticsListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDecoderEnabled(EventTime eventTime, int trackType, DecoderCounters counters) {
|
public void onDecoderEnabled(EventTime eventTime, int trackType, DecoderCounters counters) {
|
||||||
logd(eventTime, "decoderEnabled", getTrackTypeString(trackType));
|
logd(eventTime, "decoderEnabled", Util.getTrackTypeString(trackType));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -319,7 +319,7 @@ public class EventLogger implements AnalyticsListener {
|
|||||||
@Override
|
@Override
|
||||||
public void onDecoderInitialized(
|
public void onDecoderInitialized(
|
||||||
EventTime eventTime, int trackType, String decoderName, long initializationDurationMs) {
|
EventTime eventTime, int trackType, String decoderName, long initializationDurationMs) {
|
||||||
logd(eventTime, "decoderInitialized", getTrackTypeString(trackType) + ", " + decoderName);
|
logd(eventTime, "decoderInitialized", Util.getTrackTypeString(trackType) + ", " + decoderName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -327,12 +327,12 @@ public class EventLogger implements AnalyticsListener {
|
|||||||
logd(
|
logd(
|
||||||
eventTime,
|
eventTime,
|
||||||
"decoderInputFormat",
|
"decoderInputFormat",
|
||||||
getTrackTypeString(trackType) + ", " + Format.toLogString(format));
|
Util.getTrackTypeString(trackType) + ", " + Format.toLogString(format));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDecoderDisabled(EventTime eventTime, int trackType, DecoderCounters counters) {
|
public void onDecoderDisabled(EventTime eventTime, int trackType, DecoderCounters counters) {
|
||||||
logd(eventTime, "decoderDisabled", getTrackTypeString(trackType));
|
logd(eventTime, "decoderDisabled", Util.getTrackTypeString(trackType));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -555,23 +555,6 @@ public class EventLogger implements AnalyticsListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getFormatSupportString(@FormatSupport int formatSupport) {
|
|
||||||
switch (formatSupport) {
|
|
||||||
case RendererCapabilities.FORMAT_HANDLED:
|
|
||||||
return "YES";
|
|
||||||
case RendererCapabilities.FORMAT_EXCEEDS_CAPABILITIES:
|
|
||||||
return "NO_EXCEEDS_CAPABILITIES";
|
|
||||||
case RendererCapabilities.FORMAT_UNSUPPORTED_DRM:
|
|
||||||
return "NO_UNSUPPORTED_DRM";
|
|
||||||
case RendererCapabilities.FORMAT_UNSUPPORTED_SUBTYPE:
|
|
||||||
return "NO_UNSUPPORTED_TYPE";
|
|
||||||
case RendererCapabilities.FORMAT_UNSUPPORTED_TYPE:
|
|
||||||
return "NO";
|
|
||||||
default:
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getAdaptiveSupportString(
|
private static String getAdaptiveSupportString(
|
||||||
int trackCount, @AdaptiveSupport int adaptiveSupport) {
|
int trackCount, @AdaptiveSupport int adaptiveSupport) {
|
||||||
if (trackCount < 2) {
|
if (trackCount < 2) {
|
||||||
@ -645,27 +628,6 @@ public class EventLogger implements AnalyticsListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getTrackTypeString(int trackType) {
|
|
||||||
switch (trackType) {
|
|
||||||
case C.TRACK_TYPE_AUDIO:
|
|
||||||
return "audio";
|
|
||||||
case C.TRACK_TYPE_DEFAULT:
|
|
||||||
return "default";
|
|
||||||
case C.TRACK_TYPE_METADATA:
|
|
||||||
return "metadata";
|
|
||||||
case C.TRACK_TYPE_CAMERA_MOTION:
|
|
||||||
return "camera motion";
|
|
||||||
case C.TRACK_TYPE_NONE:
|
|
||||||
return "none";
|
|
||||||
case C.TRACK_TYPE_TEXT:
|
|
||||||
return "text";
|
|
||||||
case C.TRACK_TYPE_VIDEO:
|
|
||||||
return "video";
|
|
||||||
default:
|
|
||||||
return trackType >= C.TRACK_TYPE_CUSTOM_BASE ? "custom (" + trackType + ")" : "?";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getPlaybackSuppressionReasonString(
|
private static String getPlaybackSuppressionReasonString(
|
||||||
@PlaybackSuppressionReason int playbackSuppressionReason) {
|
@PlaybackSuppressionReason int playbackSuppressionReason) {
|
||||||
switch (playbackSuppressionReason) {
|
switch (playbackSuppressionReason) {
|
||||||
|
@ -2014,6 +2014,33 @@ public final class Util {
|
|||||||
return capabilities;
|
return capabilities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of a {@code TRACK_TYPE_*} constant defined in {@link C}.
|
||||||
|
*
|
||||||
|
* @param trackType A {@code TRACK_TYPE_*} constant,
|
||||||
|
* @return A string representation of this constant.
|
||||||
|
*/
|
||||||
|
public static String getTrackTypeString(int trackType) {
|
||||||
|
switch (trackType) {
|
||||||
|
case C.TRACK_TYPE_AUDIO:
|
||||||
|
return "audio";
|
||||||
|
case C.TRACK_TYPE_DEFAULT:
|
||||||
|
return "default";
|
||||||
|
case C.TRACK_TYPE_METADATA:
|
||||||
|
return "metadata";
|
||||||
|
case C.TRACK_TYPE_CAMERA_MOTION:
|
||||||
|
return "camera motion";
|
||||||
|
case C.TRACK_TYPE_NONE:
|
||||||
|
return "none";
|
||||||
|
case C.TRACK_TYPE_TEXT:
|
||||||
|
return "text";
|
||||||
|
case C.TRACK_TYPE_VIDEO:
|
||||||
|
return "video";
|
||||||
|
default:
|
||||||
|
return trackType >= C.TRACK_TYPE_CUSTOM_BASE ? "custom (" + trackType + ")" : "?";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static String getSystemProperty(String name) {
|
private static String getSystemProperty(String name) {
|
||||||
try {
|
try {
|
||||||
|
@ -198,7 +198,7 @@ public abstract class SimpleDecoderVideoRenderer extends BaseRenderer {
|
|||||||
while (feedInputBuffer()) {}
|
while (feedInputBuffer()) {}
|
||||||
TraceUtil.endSection();
|
TraceUtil.endSection();
|
||||||
} catch (VideoDecoderException e) {
|
} catch (VideoDecoderException e) {
|
||||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
throw createRendererException(e, inputFormat);
|
||||||
}
|
}
|
||||||
decoderCounters.ensureUpdated();
|
decoderCounters.ensureUpdated();
|
||||||
}
|
}
|
||||||
@ -681,7 +681,7 @@ public abstract class SimpleDecoderVideoRenderer extends BaseRenderer {
|
|||||||
decoderInitializedTimestamp - decoderInitializingTimestamp);
|
decoderInitializedTimestamp - decoderInitializingTimestamp);
|
||||||
decoderCounters.decoderInitCount++;
|
decoderCounters.decoderInitCount++;
|
||||||
} catch (VideoDecoderException e) {
|
} catch (VideoDecoderException e) {
|
||||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
throw createRendererException(e, inputFormat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -887,7 +887,7 @@ public abstract class SimpleDecoderVideoRenderer extends BaseRenderer {
|
|||||||
}
|
}
|
||||||
@DrmSession.State int drmSessionState = decoderDrmSession.getState();
|
@DrmSession.State int drmSessionState = decoderDrmSession.getState();
|
||||||
if (drmSessionState == DrmSession.STATE_ERROR) {
|
if (drmSessionState == DrmSession.STATE_ERROR) {
|
||||||
throw ExoPlaybackException.createForRenderer(decoderDrmSession.getError(), getIndex());
|
throw createRendererException(decoderDrmSession.getError(), inputFormat);
|
||||||
}
|
}
|
||||||
return drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS;
|
return drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user