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 @@
* Add `MediaPeriod.isLoading` to improve `Player.isLoading` state.
* Fix issue where player errors are thrown too early at playlist transitions
([#5407](https://github.com/google/ExoPlayer/issues/5407)).
* Add `Format` and renderer support flags to renderer `ExoPlaybackException`s.
* DRM:
* Inject `DrmSessionManager` into the `MediaSources` instead of `Renderers`.
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 readingPositionUs;
private boolean streamIsFinal;
private boolean throwRendererExceptionIsExecuting;
/**
* @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;
if (newFormat.drmInitData != null) {
if (drmSessionManager == null) {
throw ExoPlaybackException.createForRenderer(
new IllegalStateException("Media requires a DrmSessionManager"), getIndex());
throw createRendererException(
new IllegalStateException("Media requires a DrmSessionManager"), newFormat);
}
newSourceDrmSession =
drmSessionManager.acquireSession(
......@@ -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
* {@link C#RESULT_BUFFER_READ} is only returned if {@link #setCurrentStreamFinal()} has been
* called. {@link C#RESULT_NOTHING_READ} is returned otherwise.
*
* @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
* end of the stream. If the end of the stream has been reached, the
* {@link C#BUFFER_FLAG_END_OF_STREAM} flag will be set on the buffer.
* end of the stream. If the end of the stream has been reached, the {@link
* 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
* 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.
* @return The result, which can be {@link C#RESULT_NOTHING_READ}, {@link C#RESULT_FORMAT_READ} or
* {@link C#RESULT_BUFFER_READ}.
*/
protected final int readSource(FormatHolder formatHolder, DecoderInputBuffer buffer,
boolean formatRequired) {
protected final int readSource(
FormatHolder formatHolder, DecoderInputBuffer buffer, boolean formatRequired) {
int result = stream.readData(formatHolder, buffer, formatRequired);
if (result == C.RESULT_BUFFER_READ) {
if (buffer.isEndOfStream()) {
......
......@@ -18,6 +18,7 @@ package com.google.android.exoplayer2;
import android.os.SystemClock;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.RendererCapabilities.FormatSupport;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.util.Assertions;
import java.io.IOException;
......@@ -74,6 +75,19 @@ public final class ExoPlaybackException extends Exception {
*/
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. */
public final long timestampMs;
......@@ -86,7 +100,7 @@ public final class ExoPlaybackException extends Exception {
* @return The created instance.
*/
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 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.
*/
public static ExoPlaybackException createForRenderer(Exception cause, int rendererIndex) {
return new ExoPlaybackException(TYPE_RENDERER, cause, rendererIndex);
public static ExoPlaybackException createForRenderer(
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.
*/
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.
*/
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);
this.type = type;
this.cause = cause;
this.rendererIndex = rendererIndex;
this.rendererFormat = rendererFormat;
this.rendererFormatSupport = rendererFormatSupport;
timestampMs = SystemClock.elapsedRealtime();
}
......@@ -142,6 +185,8 @@ public final class ExoPlaybackException extends Exception {
super(message);
this.type = type;
rendererIndex = C.INDEX_UNSET;
rendererFormat = null;
rendererFormatSupport = RendererCapabilities.FORMAT_UNSUPPORTED_TYPE;
cause = null;
timestampMs = SystemClock.elapsedRealtime();
}
......
......@@ -384,7 +384,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
}
maybeNotifyPlaybackInfoChanged();
} catch (ExoPlaybackException e) {
Log.e(TAG, "Playback error.", e);
Log.e(TAG, getExoPlaybackExceptionMessage(e), e);
stopInternal(
/* forceResetRenderers= */ true,
/* resetPositionAndState= */ false,
......@@ -417,6 +417,20 @@ import java.util.concurrent.atomic.AtomicBoolean;
// 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.
*
......
......@@ -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
* 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.
......
......@@ -90,10 +90,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
private boolean codecNeedsDiscardChannelsWorkaround;
private boolean codecNeedsEosBufferTimestampWorkaround;
private android.media.MediaFormat passthroughMediaFormat;
private @C.Encoding int pcmEncoding;
private int channelCount;
private int encoderDelay;
private int encoderPadding;
@Nullable private Format inputFormat;
private long currentPositionUs;
private boolean allowFirstBufferPositionDiscontinuity;
private boolean allowPositionDiscontinuity;
......@@ -551,15 +548,8 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
@Override
protected void onInputFormatChanged(FormatHolder formatHolder) throws ExoPlaybackException {
super.onInputFormatChanged(formatHolder);
Format newFormat = formatHolder.format;
eventDispatcher.inputFormatChanged(newFormat);
// 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;
inputFormat = formatHolder.format;
eventDispatcher.inputFormatChanged(inputFormat);
}
@Override
......@@ -575,14 +565,14 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
mediaFormat.getString(MediaFormat.KEY_MIME));
} else {
mediaFormat = outputMediaFormat;
encoding = pcmEncoding;
encoding = getPcmEncoding(inputFormat);
}
int channelCount = mediaFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
int sampleRate = mediaFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
int[] channelMap;
if (codecNeedsDiscardChannelsWorkaround && channelCount == 6 && this.channelCount < 6) {
channelMap = new int[this.channelCount];
for (int i = 0; i < this.channelCount; i++) {
if (codecNeedsDiscardChannelsWorkaround && channelCount == 6 && inputFormat.channelCount < 6) {
channelMap = new int[inputFormat.channelCount];
for (int i = 0; i < inputFormat.channelCount; i++) {
channelMap[i] = i;
}
} else {
......@@ -590,10 +580,17 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
}
try {
audioSink.configure(encoding, channelCount, sampleRate, 0, channelMap, encoderDelay,
encoderPadding);
audioSink.configure(
encoding,
channelCount,
sampleRate,
0,
channelMap,
inputFormat.encoderDelay,
inputFormat.encoderPadding);
} 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;
}
} catch (AudioSink.InitializationException | AudioSink.WriteException e) {
throw ExoPlaybackException.createForRenderer(e, getIndex());
// TODO(internal: b/145658993) Use outputFormat instead.
throw createRendererException(e, inputFormat);
}
return false;
}
......@@ -830,7 +828,8 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
try {
audioSink.playToEndOfStream();
} 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"));
}
@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 {
@Override
......
......@@ -263,7 +263,7 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
try {
audioSink.playToEndOfStream();
} catch (AudioSink.WriteException e) {
throw ExoPlaybackException.createForRenderer(e, getIndex());
throw createRendererException(e, inputFormat);
}
return;
}
......@@ -300,7 +300,7 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
TraceUtil.endSection();
} catch (AudioDecoderException | AudioSink.ConfigurationException
| AudioSink.InitializationException | AudioSink.WriteException e) {
throw ExoPlaybackException.createForRenderer(e, getIndex());
throw createRendererException(e, inputFormat);
}
decoderCounters.ensureUpdated();
}
......@@ -483,7 +483,7 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
}
@DrmSession.State int drmSessionState = decoderDrmSession.getState();
if (drmSessionState == DrmSession.STATE_ERROR) {
throw ExoPlaybackException.createForRenderer(decoderDrmSession.getError(), getIndex());
throw createRendererException(decoderDrmSession.getError(), inputFormat);
}
return drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS;
}
......@@ -493,7 +493,8 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
try {
audioSink.playToEndOfStream();
} 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);
decoderCounters.decoderInitCount++;
} catch (AudioDecoderException e) {
throw ExoPlaybackException.createForRenderer(e, getIndex());
throw createRendererException(e, inputFormat);
}
}
......
......@@ -527,7 +527,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
try {
return supportsFormat(mediaCodecSelector, drmSessionManager, format);
} catch (DecoderQueryException e) {
throw ExoPlaybackException.createForRenderer(e, getIndex());
throw createRendererException(e, format);
}
}
......@@ -602,7 +602,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
try {
mediaCrypto = new MediaCrypto(sessionMediaCrypto.uuid, sessionMediaCrypto.sessionId);
} catch (MediaCryptoException e) {
throw ExoPlaybackException.createForRenderer(e, getIndex());
throw createRendererException(e, inputFormat);
}
mediaCryptoRequiresSecureDecoder =
!sessionMediaCrypto.forceAllowInsecureDecoderComponents
......@@ -612,7 +612,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
if (FrameworkMediaCrypto.WORKAROUND_DEVICE_NEEDS_KEYS_TO_CONFIGURE_CODEC) {
@DrmSession.State int drmSessionState = codecDrmSession.getState();
if (drmSessionState == DrmSession.STATE_ERROR) {
throw ExoPlaybackException.createForRenderer(codecDrmSession.getError(), getIndex());
throw createRendererException(codecDrmSession.getError(), inputFormat);
} else if (drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS) {
// Wait for keys.
return;
......@@ -623,7 +623,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
try {
maybeInitCodecWithFallback(mediaCrypto, mediaCryptoRequiresSecureDecoder);
} catch (DecoderInitializationException e) {
throw ExoPlaybackException.createForRenderer(e, getIndex());
throw createRendererException(e, inputFormat);
}
}
......@@ -790,8 +790,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
decoderCounters.ensureUpdated();
} catch (IllegalStateException e) {
if (isMediaCodecException(e)) {
throw ExoPlaybackException.createForRenderer(
createDecoderException(e, getCodecInfo()), getIndex());
throw createRendererException(e, inputFormat);
}
throw e;
}
......@@ -1210,7 +1209,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
resetInputBuffer();
}
} catch (CryptoException e) {
throw ExoPlaybackException.createForRenderer(e, getIndex());
throw createRendererException(e, inputFormat);
}
return false;
}
......@@ -1266,7 +1265,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
codecReconfigurationState = RECONFIGURATION_STATE_NONE;
decoderCounters.inputBufferCount++;
} catch (CryptoException e) {
throw ExoPlaybackException.createForRenderer(e, getIndex());
throw createRendererException(e, inputFormat);
}
return true;
}
......@@ -1279,7 +1278,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
}
@DrmSession.State int drmSessionState = codecDrmSession.getState();
if (drmSessionState == DrmSession.STATE_ERROR) {
throw ExoPlaybackException.createForRenderer(codecDrmSession.getError(), getIndex());
throw createRendererException(codecDrmSession.getError(), inputFormat);
}
return drmSessionState != DrmSession.STATE_OPENED_WITH_KEYS;
}
......@@ -1822,7 +1821,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
try {
mediaCrypto.setMediaDrmSession(sessionMediaCrypto.sessionId);
} catch (MediaCryptoException e) {
throw ExoPlaybackException.createForRenderer(e, getIndex());
throw createRendererException(e, inputFormat);
}
setCodecDrmSession(sourceDrmSession);
codecDrainState = DRAIN_STATE_NONE;
......
......@@ -165,7 +165,7 @@ public final class TextRenderer extends BaseRenderer implements Callback {
try {
nextSubtitle = decoder.dequeueOutputBuffer();
} 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) {
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.RendererCapabilities;
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.analytics.AnalyticsListener;
import com.google.android.exoplayer2.audio.AudioAttributes;
......@@ -218,7 +217,7 @@ public class EventLogger implements AnalyticsListener {
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
String status = getTrackStatusString(trackSelection, trackGroup, trackIndex);
String formatSupport =
getFormatSupportString(
RendererCapabilities.getFormatSupportString(
mappedTrackInfo.getTrackSupport(rendererIndex, groupIndex, trackIndex));
logd(
" "
......@@ -257,7 +256,8 @@ public class EventLogger implements AnalyticsListener {
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
String status = getTrackStatusString(false);
String formatSupport =
getFormatSupportString(RendererCapabilities.FORMAT_UNSUPPORTED_TYPE);
RendererCapabilities.getFormatSupportString(
RendererCapabilities.FORMAT_UNSUPPORTED_TYPE);
logd(
" "
+ status
......@@ -289,7 +289,7 @@ public class EventLogger implements AnalyticsListener {
@Override
public void onDecoderEnabled(EventTime eventTime, int trackType, DecoderCounters counters) {
logd(eventTime, "decoderEnabled", getTrackTypeString(trackType));
logd(eventTime, "decoderEnabled", Util.getTrackTypeString(trackType));
}
@Override
......@@ -319,7 +319,7 @@ public class EventLogger implements AnalyticsListener {
@Override
public void onDecoderInitialized(
EventTime eventTime, int trackType, String decoderName, long initializationDurationMs) {
logd(eventTime, "decoderInitialized", getTrackTypeString(trackType) + ", " + decoderName);
logd(eventTime, "decoderInitialized", Util.getTrackTypeString(trackType) + ", " + decoderName);
}
@Override
......@@ -327,12 +327,12 @@ public class EventLogger implements AnalyticsListener {
logd(
eventTime,
"decoderInputFormat",
getTrackTypeString(trackType) + ", " + Format.toLogString(format));
Util.getTrackTypeString(trackType) + ", " + Format.toLogString(format));
}
@Override
public void onDecoderDisabled(EventTime eventTime, int trackType, DecoderCounters counters) {
logd(eventTime, "decoderDisabled", getTrackTypeString(trackType));
logd(eventTime, "decoderDisabled", Util.getTrackTypeString(trackType));
}
@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(
int trackCount, @AdaptiveSupport int adaptiveSupport) {
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(
@PlaybackSuppressionReason int playbackSuppressionReason) {
switch (playbackSuppressionReason) {
......
......@@ -2014,6 +2014,33 @@ public final class Util {
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
private static String getSystemProperty(String name) {
try {
......
......@@ -198,7 +198,7 @@ public abstract class SimpleDecoderVideoRenderer extends BaseRenderer {
while (feedInputBuffer()) {}
TraceUtil.endSection();
} catch (VideoDecoderException e) {
throw ExoPlaybackException.createForRenderer(e, getIndex());
throw createRendererException(e, inputFormat);
}
decoderCounters.ensureUpdated();
}
......@@ -681,7 +681,7 @@ public abstract class SimpleDecoderVideoRenderer extends BaseRenderer {
decoderInitializedTimestamp - decoderInitializingTimestamp);
decoderCounters.decoderInitCount++;
} 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();
if (drmSessionState == DrmSession.STATE_ERROR) {
throw ExoPlaybackException.createForRenderer(decoderDrmSession.getError(), getIndex());
throw createRendererException(decoderDrmSession.getError(), inputFormat);
}
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