Ensure non-fatal errors are logged to logcat.

We already report these errors through callbacks to interested listeners.
However, to ease debugging with bugreports and local error detection,
it's helpful to also log these non-fatal execptions to logcat. Otherwise
nothing in logcat indicates that the player recovered from an exception.

Issue: #6384
PiperOrigin-RevId: 357923899
This commit is contained in:
tonihei 2021-02-17 12:57:36 +00:00 committed by kim-vde
parent f191000e20
commit 7830eb7ae5
8 changed files with 25 additions and 4 deletions

View File

@ -242,6 +242,11 @@ public interface AudioSink {
*/ */
public UnexpectedDiscontinuityException( public UnexpectedDiscontinuityException(
long actualPresentationTimeUs, long expectedPresentationTimeUs) { long actualPresentationTimeUs, long expectedPresentationTimeUs) {
super(
"Unexpected audio track timestamp discontinuity: expected "
+ expectedPresentationTimeUs
+ ", got "
+ actualPresentationTimeUs);
this.actualPresentationTimeUs = actualPresentationTimeUs; this.actualPresentationTimeUs = actualPresentationTimeUs;
this.expectedPresentationTimeUs = expectedPresentationTimeUs; this.expectedPresentationTimeUs = expectedPresentationTimeUs;
} }

View File

@ -47,6 +47,7 @@ import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException;
import com.google.android.exoplayer2.drm.ExoMediaCrypto; import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.MediaClock; import com.google.android.exoplayer2.util.MediaClock;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.TraceUtil; import com.google.android.exoplayer2.util.TraceUtil;
@ -82,6 +83,8 @@ public abstract class DecoderAudioRenderer<
Decoder<DecoderInputBuffer, ? extends SimpleOutputBuffer, ? extends DecoderException>> Decoder<DecoderInputBuffer, ? extends SimpleOutputBuffer, ? extends DecoderException>>
extends BaseRenderer implements MediaClock { extends BaseRenderer implements MediaClock {
private static final String TAG = "DecoderAudioRenderer";
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@IntDef({ @IntDef({
@ -300,6 +303,7 @@ public abstract class DecoderAudioRenderer<
while (feedInputBuffer()) {} while (feedInputBuffer()) {}
TraceUtil.endSection(); TraceUtil.endSection();
} catch (DecoderException e) { } catch (DecoderException e) {
Log.e(TAG, "Audio codec error", e);
eventDispatcher.audioCodecError(e); eventDispatcher.audioCodecError(e);
throw createRendererException(e, inputFormat); throw createRendererException(e, inputFormat);
} catch (AudioSink.ConfigurationException e) { } catch (AudioSink.ConfigurationException e) {
@ -620,6 +624,7 @@ public abstract class DecoderAudioRenderer<
codecInitializedTimestamp - codecInitializingTimestamp); codecInitializedTimestamp - codecInitializingTimestamp);
decoderCounters.decoderInitCount++; decoderCounters.decoderInitCount++;
} catch (DecoderException e) { } catch (DecoderException e) {
Log.e(TAG, "Audio codec error", e);
eventDispatcher.audioCodecError(e); eventDispatcher.audioCodecError(e);
throw createRendererException(e, inputFormat); throw createRendererException(e, inputFormat);
} catch (OutOfMemoryError e) { } catch (OutOfMemoryError e) {
@ -739,6 +744,7 @@ public abstract class DecoderAudioRenderer<
@Override @Override
public void onAudioSinkError(Exception audioSinkError) { public void onAudioSinkError(Exception audioSinkError) {
Log.e(TAG, "Audio sink error", audioSinkError);
eventDispatcher.audioSinkError(audioSinkError); eventDispatcher.audioSinkError(audioSinkError);
} }
} }

View File

@ -49,6 +49,7 @@ import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer;
import com.google.android.exoplayer2.mediacodec.MediaCodecSelector; import com.google.android.exoplayer2.mediacodec.MediaCodecSelector;
import com.google.android.exoplayer2.mediacodec.MediaCodecUtil; import com.google.android.exoplayer2.mediacodec.MediaCodecUtil;
import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException; import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException;
import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.MediaClock; import com.google.android.exoplayer2.util.MediaClock;
import com.google.android.exoplayer2.util.MediaFormatUtil; import com.google.android.exoplayer2.util.MediaFormatUtil;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
@ -416,6 +417,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
@Override @Override
protected void onCodecError(Exception codecError) { protected void onCodecError(Exception codecError) {
Log.e(TAG, "Audio codec error", codecError);
eventDispatcher.audioCodecError(codecError); eventDispatcher.audioCodecError(codecError);
} }
@ -853,6 +855,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
@Override @Override
public void onAudioSinkError(Exception audioSinkError) { public void onAudioSinkError(Exception audioSinkError) {
Log.e(TAG, "Audio sink error", audioSinkError);
eventDispatcher.audioSinkError(audioSinkError); eventDispatcher.audioSinkError(audioSinkError);
} }
} }

View File

@ -446,7 +446,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
mediaDrm.restoreKeys(sessionId, offlineLicenseKeySetId); mediaDrm.restoreKeys(sessionId, offlineLicenseKeySetId);
return true; return true;
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "Error trying to restore keys.", e);
onError(e); onError(e);
} }
return false; return false;
@ -522,6 +521,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
private void onError(final Exception e) { private void onError(final Exception e) {
lastException = new DrmSessionException(e); lastException = new DrmSessionException(e);
Log.e(TAG, "DRM session error", e);
dispatchEvent(eventDispatcher -> eventDispatcher.drmSessionManagerError(e)); dispatchEvent(eventDispatcher -> eventDispatcher.drmSessionManagerError(e));
if (state != STATE_OPENED_WITH_KEYS) { if (state != STATE_OPENED_WITH_KEYS) {
state = STATE_ERROR; state = STATE_ERROR;

View File

@ -489,6 +489,7 @@ public class DefaultDrmSessionManager implements DrmSessionManager {
schemeDatas = getSchemeDatas(Assertions.checkNotNull(format.drmInitData), uuid, false); schemeDatas = getSchemeDatas(Assertions.checkNotNull(format.drmInitData), uuid, false);
if (schemeDatas.isEmpty()) { if (schemeDatas.isEmpty()) {
final MissingSchemeDataException error = new MissingSchemeDataException(uuid); final MissingSchemeDataException error = new MissingSchemeDataException(uuid);
Log.e(TAG, "DRM error", error);
if (eventDispatcher != null) { if (eventDispatcher != null) {
eventDispatcher.drmSessionManagerError(error); eventDispatcher.drmSessionManagerError(error);
} }

View File

@ -435,24 +435,24 @@ public final class Loader implements LoaderErrorThrower {
} }
} catch (Exception e) { } catch (Exception e) {
// This should never happen, but handle it anyway. // This should never happen, but handle it anyway.
Log.e(TAG, "Unexpected exception loading stream", e);
if (!released) { if (!released) {
Log.e(TAG, "Unexpected exception loading stream", e);
obtainMessage(MSG_IO_EXCEPTION, new UnexpectedLoaderException(e)).sendToTarget(); obtainMessage(MSG_IO_EXCEPTION, new UnexpectedLoaderException(e)).sendToTarget();
} }
} catch (OutOfMemoryError e) { } catch (OutOfMemoryError e) {
// This can occur if a stream is malformed in a way that causes an extractor to think it // This can occur if a stream is malformed in a way that causes an extractor to think it
// needs to allocate a large amount of memory. We don't want the process to die in this // needs to allocate a large amount of memory. We don't want the process to die in this
// case, but we do want the playback to fail. // case, but we do want the playback to fail.
Log.e(TAG, "OutOfMemory error loading stream", e);
if (!released) { if (!released) {
Log.e(TAG, "OutOfMemory error loading stream", e);
obtainMessage(MSG_IO_EXCEPTION, new UnexpectedLoaderException(e)).sendToTarget(); obtainMessage(MSG_IO_EXCEPTION, new UnexpectedLoaderException(e)).sendToTarget();
} }
} catch (Error e) { } catch (Error e) {
// We'd hope that the platform would shut down the process if an Error is thrown here, but // We'd hope that the platform would shut down the process if an Error is thrown here, but
// the executor may catch the error (b/20616433). Throw it here, but also pass and throw it // the executor may catch the error (b/20616433). Throw it here, but also pass and throw it
// from the handler thread so the process dies even if the executor behaves in this way. // from the handler thread so the process dies even if the executor behaves in this way.
Log.e(TAG, "Unexpected error loading stream", e);
if (!released) { if (!released) {
Log.e(TAG, "Unexpected error loading stream", e);
obtainMessage(MSG_FATAL_ERROR, e).sendToTarget(); obtainMessage(MSG_FATAL_ERROR, e).sendToTarget();
} }
throw e; throw e;

View File

@ -43,6 +43,7 @@ import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException;
import com.google.android.exoplayer2.drm.ExoMediaCrypto; import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.TimedValueQueue; import com.google.android.exoplayer2.util.TimedValueQueue;
import com.google.android.exoplayer2.util.TraceUtil; import com.google.android.exoplayer2.util.TraceUtil;
import com.google.android.exoplayer2.video.VideoRendererEventListener.EventDispatcher; import com.google.android.exoplayer2.video.VideoRendererEventListener.EventDispatcher;
@ -69,6 +70,8 @@ import java.lang.annotation.RetentionPolicy;
*/ */
public abstract class DecoderVideoRenderer extends BaseRenderer { public abstract class DecoderVideoRenderer extends BaseRenderer {
private static final String TAG = "DecoderVideoRenderer";
/** Decoder reinitialization states. */ /** Decoder reinitialization states. */
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@ -206,6 +209,7 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
while (feedInputBuffer()) {} while (feedInputBuffer()) {}
TraceUtil.endSection(); TraceUtil.endSection();
} catch (DecoderException e) { } catch (DecoderException e) {
Log.e(TAG, "Video codec error", e);
eventDispatcher.videoCodecError(e); eventDispatcher.videoCodecError(e);
throw createRendererException(e, inputFormat); throw createRendererException(e, inputFormat);
} }
@ -709,6 +713,7 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
decoderInitializedTimestamp - decoderInitializingTimestamp); decoderInitializedTimestamp - decoderInitializingTimestamp);
decoderCounters.decoderInitCount++; decoderCounters.decoderInitCount++;
} catch (DecoderException e) { } catch (DecoderException e) {
Log.e(TAG, "Video codec error", e);
eventDispatcher.videoCodecError(e); eventDispatcher.videoCodecError(e);
throw createRendererException(e, inputFormat); throw createRendererException(e, inputFormat);
} catch (OutOfMemoryError e) { } catch (OutOfMemoryError e) {

View File

@ -692,6 +692,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
@Override @Override
protected void onCodecError(Exception codecError) { protected void onCodecError(Exception codecError) {
Log.e(TAG, "Video codec error", codecError);
eventDispatcher.videoCodecError(codecError); eventDispatcher.videoCodecError(codecError);
} }