Commit 64703e4a by tonihei Committed by Oliver Woodman

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
parent cbdf45aa
...@@ -56,6 +56,7 @@ ...@@ -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 { ...@@ -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 { ...@@ -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(
...@@ -335,22 +336,46 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities { ...@@ -335,22 +336,46 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
} }
/** /**
* 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
* called. {@link C#RESULT_NOTHING_READ} is returned otherwise. * called. {@link C#RESULT_NOTHING_READ} is returned otherwise.
* *
* @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; ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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) {
this(
type,
cause,
/* rendererIndex= */ C.INDEX_UNSET,
/* rendererFormat= */ null,
/* rendererFormatSupport= */ RendererCapabilities.FORMAT_HANDLED);
} }
private ExoPlaybackException(@Type int type, Throwable cause, int rendererIndex) { 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 { ...@@ -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; ...@@ -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; ...@@ -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.
* *
......
...@@ -238,6 +238,29 @@ public interface RendererCapabilities { ...@@ -238,6 +238,29 @@ public interface RendererCapabilities {
} }
/** /**
* 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
* text renderer will return {@link C#TRACK_TYPE_TEXT}, and so on. * text renderer will return {@link C#TRACK_TYPE_TEXT}, and so on.
......
...@@ -90,10 +90,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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; ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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;
} }
......
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