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
eb5016a6ff
commit
1e609e245b
@ -29,6 +29,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(
|
||||
@ -334,6 +335,30 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
|
||||
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
|
||||
* {@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 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, 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);
|
||||
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();
|
||||
}
|
||||
|
@ -378,7 +378,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,
|
||||
@ -411,6 +411,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);
|
||||
}
|
||||
|
||||
private void setState(int state) {
|
||||
if (playbackInfo.playbackState != state) {
|
||||
playbackInfo = playbackInfo.copyWithPlaybackState(state);
|
||||
|
@ -237,6 +237,29 @@ public interface RendererCapabilities {
|
||||
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
|
||||
* 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 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -463,7 +463,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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -538,7 +538,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
|
||||
@ -548,7 +548,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;
|
||||
@ -559,7 +559,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||
try {
|
||||
maybeInitCodecWithFallback(mediaCrypto, mediaCryptoRequiresSecureDecoder);
|
||||
} catch (DecoderInitializationException e) {
|
||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
||||
throw createRendererException(e, inputFormat);
|
||||
}
|
||||
}
|
||||
|
||||
@ -722,8 +722,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;
|
||||
}
|
||||
@ -1130,7 +1129,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||
resetInputBuffer();
|
||||
}
|
||||
} catch (CryptoException e) {
|
||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
||||
throw createRendererException(e, inputFormat);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -1186,7 +1185,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;
|
||||
}
|
||||
@ -1199,7 +1198,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;
|
||||
}
|
||||
@ -1744,7 +1743,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) {
|
||||
|
@ -2001,6 +2001,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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user