Commit ee6afe5e by olly Committed by Oliver Woodman

Merge AudioDecoderException and VideoDecoderException

This is a necessary step for Decoder implementations to support
audio and video. MediaCodecRenderer.DecoderException is renamed
MediaCodecDecoderException and extends the new DecoderException

Issue: #2159
PiperOrigin-RevId: 301698238
parent 395a7031
Showing with 157 additions and 164 deletions
...@@ -15,10 +15,10 @@ ...@@ -15,10 +15,10 @@
*/ */
package com.google.android.exoplayer2.ext.av1; package com.google.android.exoplayer2.ext.av1;
import com.google.android.exoplayer2.video.VideoDecoderException; import com.google.android.exoplayer2.decoder.DecoderException;
/** Thrown when a libgav1 decoder error occurs. */ /** Thrown when a libgav1 decoder error occurs. */
public final class Gav1DecoderException extends VideoDecoderException { public final class Gav1DecoderException extends DecoderException {
/* package */ Gav1DecoderException(String message) { /* package */ Gav1DecoderException(String message) {
super(message); super(message);
......
...@@ -26,13 +26,13 @@ import com.google.android.exoplayer2.ExoPlayer; ...@@ -26,13 +26,13 @@ import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.PlayerMessage.Target; import com.google.android.exoplayer2.PlayerMessage.Target;
import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.decoder.DecoderException;
import com.google.android.exoplayer2.decoder.SimpleDecoder; import com.google.android.exoplayer2.decoder.SimpleDecoder;
import com.google.android.exoplayer2.drm.ExoMediaCrypto; import com.google.android.exoplayer2.drm.ExoMediaCrypto;
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;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.DecoderVideoRenderer; import com.google.android.exoplayer2.video.DecoderVideoRenderer;
import com.google.android.exoplayer2.video.VideoDecoderException;
import com.google.android.exoplayer2.video.VideoDecoderInputBuffer; import com.google.android.exoplayer2.video.VideoDecoderInputBuffer;
import com.google.android.exoplayer2.video.VideoDecoderOutputBuffer; import com.google.android.exoplayer2.video.VideoDecoderOutputBuffer;
import com.google.android.exoplayer2.video.VideoDecoderOutputBufferRenderer; import com.google.android.exoplayer2.video.VideoDecoderOutputBufferRenderer;
...@@ -141,11 +141,8 @@ public class Libgav1VideoRenderer extends DecoderVideoRenderer { ...@@ -141,11 +141,8 @@ public class Libgav1VideoRenderer extends DecoderVideoRenderer {
@Override @Override
protected SimpleDecoder< protected SimpleDecoder<
VideoDecoderInputBuffer, VideoDecoderInputBuffer, ? extends VideoDecoderOutputBuffer, ? extends DecoderException>
? extends VideoDecoderOutputBuffer, createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) throws DecoderException {
? extends VideoDecoderException>
createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto)
throws VideoDecoderException {
TraceUtil.beginSection("createGav1Decoder"); TraceUtil.beginSection("createGav1Decoder");
int initialInputBufferSize = int initialInputBufferSize =
format.maxInputSize != Format.NO_VALUE ? format.maxInputSize : DEFAULT_INPUT_BUFFER_SIZE; format.maxInputSize != Format.NO_VALUE ? format.maxInputSize : DEFAULT_INPUT_BUFFER_SIZE;
......
...@@ -15,12 +15,10 @@ ...@@ -15,12 +15,10 @@
*/ */
package com.google.android.exoplayer2.ext.ffmpeg; package com.google.android.exoplayer2.ext.ffmpeg;
import com.google.android.exoplayer2.audio.AudioDecoderException; import com.google.android.exoplayer2.decoder.DecoderException;
/** /** Thrown when an FFmpeg decoder error occurs. */
* Thrown when an FFmpeg decoder error occurs. public final class FfmpegDecoderException extends DecoderException {
*/
public final class FfmpegDecoderException extends AudioDecoderException {
/* package */ FfmpegDecoderException(String message) { /* package */ FfmpegDecoderException(String message) {
super(message); super(message);
......
...@@ -15,12 +15,10 @@ ...@@ -15,12 +15,10 @@
*/ */
package com.google.android.exoplayer2.ext.flac; package com.google.android.exoplayer2.ext.flac;
import com.google.android.exoplayer2.audio.AudioDecoderException; import com.google.android.exoplayer2.decoder.DecoderException;
/** /** Thrown when an Flac decoder error occurs. */
* Thrown when an Flac decoder error occurs. public final class FlacDecoderException extends DecoderException {
*/
public final class FlacDecoderException extends AudioDecoderException {
/* package */ FlacDecoderException(String message) { /* package */ FlacDecoderException(String message) {
super(message); super(message);
......
...@@ -15,12 +15,10 @@ ...@@ -15,12 +15,10 @@
*/ */
package com.google.android.exoplayer2.ext.opus; package com.google.android.exoplayer2.ext.opus;
import com.google.android.exoplayer2.audio.AudioDecoderException; import com.google.android.exoplayer2.decoder.DecoderException;
/** /** Thrown when an Opus decoder error occurs. */
* Thrown when an Opus decoder error occurs. public final class OpusDecoderException extends DecoderException {
*/
public final class OpusDecoderException extends AudioDecoderException {
/* package */ OpusDecoderException(String message) { /* package */ OpusDecoderException(String message) {
super(message); super(message);
......
...@@ -26,12 +26,12 @@ import com.google.android.exoplayer2.ExoPlayer; ...@@ -26,12 +26,12 @@ import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.PlayerMessage.Target; import com.google.android.exoplayer2.PlayerMessage.Target;
import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.decoder.DecoderException;
import com.google.android.exoplayer2.decoder.SimpleDecoder; import com.google.android.exoplayer2.decoder.SimpleDecoder;
import com.google.android.exoplayer2.drm.ExoMediaCrypto; import com.google.android.exoplayer2.drm.ExoMediaCrypto;
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;
import com.google.android.exoplayer2.video.DecoderVideoRenderer; import com.google.android.exoplayer2.video.DecoderVideoRenderer;
import com.google.android.exoplayer2.video.VideoDecoderException;
import com.google.android.exoplayer2.video.VideoDecoderInputBuffer; import com.google.android.exoplayer2.video.VideoDecoderInputBuffer;
import com.google.android.exoplayer2.video.VideoDecoderOutputBuffer; import com.google.android.exoplayer2.video.VideoDecoderOutputBuffer;
import com.google.android.exoplayer2.video.VideoDecoderOutputBufferRenderer; import com.google.android.exoplayer2.video.VideoDecoderOutputBufferRenderer;
...@@ -148,11 +148,8 @@ public class LibvpxVideoRenderer extends DecoderVideoRenderer { ...@@ -148,11 +148,8 @@ public class LibvpxVideoRenderer extends DecoderVideoRenderer {
@Override @Override
protected SimpleDecoder< protected SimpleDecoder<
VideoDecoderInputBuffer, VideoDecoderInputBuffer, ? extends VideoDecoderOutputBuffer, ? extends DecoderException>
? extends VideoDecoderOutputBuffer, createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) throws DecoderException {
? extends VideoDecoderException>
createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto)
throws VideoDecoderException {
TraceUtil.beginSection("createVpxDecoder"); TraceUtil.beginSection("createVpxDecoder");
int initialInputBufferSize = int initialInputBufferSize =
format.maxInputSize != Format.NO_VALUE ? format.maxInputSize : DEFAULT_INPUT_BUFFER_SIZE; format.maxInputSize != Format.NO_VALUE ? format.maxInputSize : DEFAULT_INPUT_BUFFER_SIZE;
...@@ -167,7 +164,7 @@ public class LibvpxVideoRenderer extends DecoderVideoRenderer { ...@@ -167,7 +164,7 @@ public class LibvpxVideoRenderer extends DecoderVideoRenderer {
@Override @Override
protected void renderOutputBuffer( protected void renderOutputBuffer(
VideoDecoderOutputBuffer outputBuffer, long presentationTimeUs, Format outputFormat) VideoDecoderOutputBuffer outputBuffer, long presentationTimeUs, Format outputFormat)
throws VideoDecoderException { throws DecoderException {
if (frameMetadataListener != null) { if (frameMetadataListener != null) {
frameMetadataListener.onVideoFrameAboutToBeRendered( frameMetadataListener.onVideoFrameAboutToBeRendered(
presentationTimeUs, System.nanoTime(), outputFormat, /* mediaFormat= */ null); presentationTimeUs, System.nanoTime(), outputFormat, /* mediaFormat= */ null);
......
...@@ -15,10 +15,10 @@ ...@@ -15,10 +15,10 @@
*/ */
package com.google.android.exoplayer2.ext.vp9; package com.google.android.exoplayer2.ext.vp9;
import com.google.android.exoplayer2.video.VideoDecoderException; import com.google.android.exoplayer2.decoder.DecoderException;
/** Thrown when a libvpx decoder error occurs. */ /** Thrown when a libvpx decoder error occurs. */
public final class VpxDecoderException extends VideoDecoderException { public final class VpxDecoderException extends DecoderException {
/* package */ VpxDecoderException(String message) { /* package */ VpxDecoderException(String message) {
super(message); super(message);
......
...@@ -31,6 +31,7 @@ import com.google.android.exoplayer2.RendererCapabilities; ...@@ -31,6 +31,7 @@ import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.audio.AudioRendererEventListener.EventDispatcher; import com.google.android.exoplayer2.audio.AudioRendererEventListener.EventDispatcher;
import com.google.android.exoplayer2.decoder.Decoder; import com.google.android.exoplayer2.decoder.Decoder;
import com.google.android.exoplayer2.decoder.DecoderCounters; import com.google.android.exoplayer2.decoder.DecoderCounters;
import com.google.android.exoplayer2.decoder.DecoderException;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.decoder.SimpleOutputBuffer; import com.google.android.exoplayer2.decoder.SimpleOutputBuffer;
import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSession;
...@@ -105,7 +106,7 @@ public abstract class DecoderAudioRenderer extends BaseRenderer implements Media ...@@ -105,7 +106,7 @@ public abstract class DecoderAudioRenderer extends BaseRenderer implements Media
private int encoderPadding; private int encoderPadding;
@Nullable @Nullable
private Decoder<DecoderInputBuffer, ? extends SimpleOutputBuffer, ? extends AudioDecoderException> private Decoder<DecoderInputBuffer, ? extends SimpleOutputBuffer, ? extends DecoderException>
decoder; decoder;
@Nullable private DecoderInputBuffer inputBuffer; @Nullable private DecoderInputBuffer inputBuffer;
...@@ -260,8 +261,10 @@ public abstract class DecoderAudioRenderer extends BaseRenderer implements Media ...@@ -260,8 +261,10 @@ public abstract class DecoderAudioRenderer extends BaseRenderer implements Media
while (drainOutputBuffer()) {} while (drainOutputBuffer()) {}
while (feedInputBuffer()) {} while (feedInputBuffer()) {}
TraceUtil.endSection(); TraceUtil.endSection();
} catch (AudioDecoderException | AudioSink.ConfigurationException } catch (DecoderException
| AudioSink.InitializationException | AudioSink.WriteException e) { | AudioSink.ConfigurationException
| AudioSink.InitializationException
| AudioSink.WriteException e) {
throw createRendererException(e, inputFormat); throw createRendererException(e, inputFormat);
} }
decoderCounters.ensureUpdated(); decoderCounters.ensureUpdated();
...@@ -303,12 +306,11 @@ public abstract class DecoderAudioRenderer extends BaseRenderer implements Media ...@@ -303,12 +306,11 @@ public abstract class DecoderAudioRenderer extends BaseRenderer implements Media
* @param mediaCrypto The {@link ExoMediaCrypto} object required for decoding encrypted content. * @param mediaCrypto The {@link ExoMediaCrypto} object required for decoding encrypted content.
* Maybe null and can be ignored if decoder does not handle encrypted content. * Maybe null and can be ignored if decoder does not handle encrypted content.
* @return The decoder. * @return The decoder.
* @throws AudioDecoderException If an error occurred creating a suitable decoder. * @throws DecoderException If an error occurred creating a suitable decoder.
*/ */
protected abstract Decoder< protected abstract Decoder<
DecoderInputBuffer, ? extends SimpleOutputBuffer, ? extends AudioDecoderException> DecoderInputBuffer, ? extends SimpleOutputBuffer, ? extends DecoderException>
createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) throws DecoderException;
throws AudioDecoderException;
/** /**
* Returns the format of audio buffers output by the decoder. Will not be called until the first * Returns the format of audio buffers output by the decoder. Will not be called until the first
...@@ -327,9 +329,9 @@ public abstract class DecoderAudioRenderer extends BaseRenderer implements Media ...@@ -327,9 +329,9 @@ public abstract class DecoderAudioRenderer extends BaseRenderer implements Media
return false; return false;
} }
private boolean drainOutputBuffer() throws ExoPlaybackException, AudioDecoderException, private boolean drainOutputBuffer()
AudioSink.ConfigurationException, AudioSink.InitializationException, throws ExoPlaybackException, DecoderException, AudioSink.ConfigurationException,
AudioSink.WriteException { AudioSink.InitializationException, AudioSink.WriteException {
if (outputBuffer == null) { if (outputBuffer == null) {
outputBuffer = decoder.dequeueOutputBuffer(); outputBuffer = decoder.dequeueOutputBuffer();
if (outputBuffer == null) { if (outputBuffer == null) {
...@@ -374,7 +376,7 @@ public abstract class DecoderAudioRenderer extends BaseRenderer implements Media ...@@ -374,7 +376,7 @@ public abstract class DecoderAudioRenderer extends BaseRenderer implements Media
return false; return false;
} }
private boolean feedInputBuffer() throws AudioDecoderException, ExoPlaybackException { private boolean feedInputBuffer() throws DecoderException, ExoPlaybackException {
if (decoder == null || decoderReinitializationState == REINITIALIZATION_STATE_WAIT_END_OF_STREAM if (decoder == null || decoderReinitializationState == REINITIALIZATION_STATE_WAIT_END_OF_STREAM
|| inputStreamEnded) { || inputStreamEnded) {
// We need to reinitialize the decoder or the input stream has ended. // We need to reinitialize the decoder or the input stream has ended.
...@@ -607,7 +609,7 @@ public abstract class DecoderAudioRenderer extends BaseRenderer implements Media ...@@ -607,7 +609,7 @@ public abstract class DecoderAudioRenderer extends BaseRenderer implements Media
eventDispatcher.decoderInitialized(decoder.getName(), codecInitializedTimestamp, eventDispatcher.decoderInitialized(decoder.getName(), codecInitializedTimestamp,
codecInitializedTimestamp - codecInitializingTimestamp); codecInitializedTimestamp - codecInitializingTimestamp);
decoderCounters.decoderInitCount++; decoderCounters.decoderInitCount++;
} catch (AudioDecoderException e) { } catch (DecoderException e) {
throw createRendererException(e, inputFormat); throw createRendererException(e, inputFormat);
} }
} }
......
...@@ -13,13 +13,13 @@ ...@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.google.android.exoplayer2.audio; package com.google.android.exoplayer2.decoder;
/** Thrown when an audio decoder error occurs. */ /** Thrown when a {@link Decoder} error occurs. */
public class AudioDecoderException extends Exception { public class DecoderException extends Exception {
/** @param message The detail message for this exception. */ /** @param message The detail message for this exception. */
public AudioDecoderException(String message) { public DecoderException(String message) {
super(message); super(message);
} }
...@@ -28,8 +28,7 @@ public class AudioDecoderException extends Exception { ...@@ -28,8 +28,7 @@ public class AudioDecoderException extends Exception {
* @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method). * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method).
* A <tt>null</tt> value is permitted, and indicates that the cause is nonexistent or unknown. * A <tt>null</tt> value is permitted, and indicates that the cause is nonexistent or unknown.
*/ */
public AudioDecoderException(String message, Throwable cause) { public DecoderException(String message, Throwable cause) {
super(message, cause); super(message, cause);
} }
} }
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.mediacodec;
import android.media.MediaCodec;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.google.android.exoplayer2.decoder.DecoderException;
import com.google.android.exoplayer2.util.Util;
/** Thrown when a failure occurs in a {@link MediaCodec} decoder. */
public class MediaCodecDecoderException extends DecoderException {
/** The {@link MediaCodecInfo} of the decoder that failed. Null if unknown. */
@Nullable public final MediaCodecInfo codecInfo;
/** An optional developer-readable diagnostic information string. May be null. */
@Nullable public final String diagnosticInfo;
public MediaCodecDecoderException(Throwable cause, @Nullable MediaCodecInfo codecInfo) {
super("Decoder failed: " + (codecInfo == null ? null : codecInfo.name), cause);
this.codecInfo = codecInfo;
diagnosticInfo = Util.SDK_INT >= 21 ? getDiagnosticInfoV21(cause) : null;
}
@RequiresApi(21)
@Nullable
private static String getDiagnosticInfoV21(Throwable cause) {
if (cause instanceof MediaCodec.CodecException) {
return ((MediaCodec.CodecException) cause).getDiagnosticInfo();
}
return null;
}
}
...@@ -224,30 +224,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -224,30 +224,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
} }
} }
/** Thrown when a failure occurs in the decoder. */
public static class DecoderException extends Exception {
/** The {@link MediaCodecInfo} of the decoder that failed. Null if unknown. */
@Nullable public final MediaCodecInfo codecInfo;
/** An optional developer-readable diagnostic information string. May be null. */
@Nullable public final String diagnosticInfo;
public DecoderException(Throwable cause, @Nullable MediaCodecInfo codecInfo) {
super("Decoder failed: " + (codecInfo == null ? null : codecInfo.name), cause);
this.codecInfo = codecInfo;
diagnosticInfo = Util.SDK_INT >= 21 ? getDiagnosticInfoV21(cause) : null;
}
@RequiresApi(21)
private static String getDiagnosticInfoV21(Throwable cause) {
if (cause instanceof CodecException) {
return ((CodecException) cause).getDiagnosticInfo();
}
return null;
}
}
/** Indicates no codec operating rate should be set. */ /** Indicates no codec operating rate should be set. */
protected static final float CODEC_OPERATING_RATE_UNSET = -1; protected static final float CODEC_OPERATING_RATE_UNSET = -1;
...@@ -926,9 +902,9 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -926,9 +902,9 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
mediaCryptoRequiresSecureDecoder = false; mediaCryptoRequiresSecureDecoder = false;
} }
protected DecoderException createDecoderException( protected MediaCodecDecoderException createDecoderException(
Throwable cause, @Nullable MediaCodecInfo codecInfo) { Throwable cause, @Nullable MediaCodecInfo codecInfo) {
return new DecoderException(cause, codecInfo); return new MediaCodecDecoderException(cause, codecInfo);
} }
/** Reads into {@link #flagsOnlyBuffer} and returns whether a {@link Format} was read. */ /** Reads into {@link #flagsOnlyBuffer} and returns whether a {@link Format} was read. */
......
...@@ -28,6 +28,7 @@ import com.google.android.exoplayer2.Format; ...@@ -28,6 +28,7 @@ import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder; import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.decoder.Decoder; import com.google.android.exoplayer2.decoder.Decoder;
import com.google.android.exoplayer2.decoder.DecoderCounters; import com.google.android.exoplayer2.decoder.DecoderCounters;
import com.google.android.exoplayer2.decoder.DecoderException;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSession;
import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException; import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException;
...@@ -77,9 +78,7 @@ public abstract class DecoderVideoRenderer extends BaseRenderer { ...@@ -77,9 +78,7 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
private Format inputFormat; private Format inputFormat;
private Format outputFormat; private Format outputFormat;
private Decoder< private Decoder<
VideoDecoderInputBuffer, VideoDecoderInputBuffer, ? extends VideoDecoderOutputBuffer, ? extends DecoderException>
? extends VideoDecoderOutputBuffer,
? extends VideoDecoderException>
decoder; decoder;
private VideoDecoderInputBuffer inputBuffer; private VideoDecoderInputBuffer inputBuffer;
private VideoDecoderOutputBuffer outputBuffer; private VideoDecoderOutputBuffer outputBuffer;
...@@ -179,7 +178,7 @@ public abstract class DecoderVideoRenderer extends BaseRenderer { ...@@ -179,7 +178,7 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
while (drainOutputBuffer(positionUs, elapsedRealtimeUs)) {} while (drainOutputBuffer(positionUs, elapsedRealtimeUs)) {}
while (feedInputBuffer()) {} while (feedInputBuffer()) {}
TraceUtil.endSection(); TraceUtil.endSection();
} catch (VideoDecoderException e) { } catch (DecoderException e) {
throw createRendererException(e, inputFormat); throw createRendererException(e, inputFormat);
} }
decoderCounters.ensureUpdated(); decoderCounters.ensureUpdated();
...@@ -488,14 +487,11 @@ public abstract class DecoderVideoRenderer extends BaseRenderer { ...@@ -488,14 +487,11 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
* @param mediaCrypto The {@link ExoMediaCrypto} object required for decoding encrypted content. * @param mediaCrypto The {@link ExoMediaCrypto} object required for decoding encrypted content.
* May be null and can be ignored if decoder does not handle encrypted content. * May be null and can be ignored if decoder does not handle encrypted content.
* @return The decoder. * @return The decoder.
* @throws VideoDecoderException If an error occurred creating a suitable decoder. * @throws DecoderException If an error occurred creating a suitable decoder.
*/ */
protected abstract Decoder< protected abstract Decoder<
VideoDecoderInputBuffer, VideoDecoderInputBuffer, ? extends VideoDecoderOutputBuffer, ? extends DecoderException>
? extends VideoDecoderOutputBuffer, createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) throws DecoderException;
? extends VideoDecoderException>
createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto)
throws VideoDecoderException;
/** /**
* Renders the specified output buffer. * Renders the specified output buffer.
...@@ -506,11 +502,11 @@ public abstract class DecoderVideoRenderer extends BaseRenderer { ...@@ -506,11 +502,11 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
* @param outputBuffer {@link VideoDecoderOutputBuffer} to render. * @param outputBuffer {@link VideoDecoderOutputBuffer} to render.
* @param presentationTimeUs Presentation time in microseconds. * @param presentationTimeUs Presentation time in microseconds.
* @param outputFormat Output {@link Format}. * @param outputFormat Output {@link Format}.
* @throws VideoDecoderException If an error occurs when rendering the output buffer. * @throws DecoderException If an error occurs when rendering the output buffer.
*/ */
protected void renderOutputBuffer( protected void renderOutputBuffer(
VideoDecoderOutputBuffer outputBuffer, long presentationTimeUs, Format outputFormat) VideoDecoderOutputBuffer outputBuffer, long presentationTimeUs, Format outputFormat)
throws VideoDecoderException { throws DecoderException {
lastRenderTimeUs = C.msToUs(SystemClock.elapsedRealtime() * 1000); lastRenderTimeUs = C.msToUs(SystemClock.elapsedRealtime() * 1000);
int bufferMode = outputBuffer.mode; int bufferMode = outputBuffer.mode;
boolean renderSurface = bufferMode == C.VIDEO_OUTPUT_MODE_SURFACE_YUV && surface != null; boolean renderSurface = bufferMode == C.VIDEO_OUTPUT_MODE_SURFACE_YUV && surface != null;
...@@ -538,10 +534,10 @@ public abstract class DecoderVideoRenderer extends BaseRenderer { ...@@ -538,10 +534,10 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
* *
* @param outputBuffer {@link VideoDecoderOutputBuffer} to render. * @param outputBuffer {@link VideoDecoderOutputBuffer} to render.
* @param surface Output {@link Surface}. * @param surface Output {@link Surface}.
* @throws VideoDecoderException If an error occurs when rendering the output buffer. * @throws DecoderException If an error occurs when rendering the output buffer.
*/ */
protected abstract void renderOutputBufferToSurface( protected abstract void renderOutputBufferToSurface(
VideoDecoderOutputBuffer outputBuffer, Surface surface) throws VideoDecoderException; VideoDecoderOutputBuffer outputBuffer, Surface surface) throws DecoderException;
/** /**
* Sets output surface. * Sets output surface.
...@@ -651,12 +647,12 @@ public abstract class DecoderVideoRenderer extends BaseRenderer { ...@@ -651,12 +647,12 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
decoderInitializedTimestamp, decoderInitializedTimestamp,
decoderInitializedTimestamp - decoderInitializingTimestamp); decoderInitializedTimestamp - decoderInitializingTimestamp);
decoderCounters.decoderInitCount++; decoderCounters.decoderInitCount++;
} catch (VideoDecoderException e) { } catch (DecoderException e) {
throw createRendererException(e, inputFormat); throw createRendererException(e, inputFormat);
} }
} }
private boolean feedInputBuffer() throws VideoDecoderException, ExoPlaybackException { private boolean feedInputBuffer() throws DecoderException, ExoPlaybackException {
if (decoder == null if (decoder == null
|| decoderReinitializationState == REINITIALIZATION_STATE_WAIT_END_OF_STREAM || decoderReinitializationState == REINITIALIZATION_STATE_WAIT_END_OF_STREAM
|| inputStreamEnded) { || inputStreamEnded) {
...@@ -732,7 +728,7 @@ public abstract class DecoderVideoRenderer extends BaseRenderer { ...@@ -732,7 +728,7 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
* @throws ExoPlaybackException If an error occurs draining the output buffer. * @throws ExoPlaybackException If an error occurs draining the output buffer.
*/ */
private boolean drainOutputBuffer(long positionUs, long elapsedRealtimeUs) private boolean drainOutputBuffer(long positionUs, long elapsedRealtimeUs)
throws ExoPlaybackException, VideoDecoderException { throws ExoPlaybackException, DecoderException {
if (outputBuffer == null) { if (outputBuffer == null) {
outputBuffer = decoder.dequeueOutputBuffer(); outputBuffer = decoder.dequeueOutputBuffer();
if (outputBuffer == null) { if (outputBuffer == null) {
...@@ -774,7 +770,7 @@ public abstract class DecoderVideoRenderer extends BaseRenderer { ...@@ -774,7 +770,7 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
* @throws ExoPlaybackException If an error occurs processing the output buffer. * @throws ExoPlaybackException If an error occurs processing the output buffer.
*/ */
private boolean processOutputBuffer(long positionUs, long elapsedRealtimeUs) private boolean processOutputBuffer(long positionUs, long elapsedRealtimeUs)
throws ExoPlaybackException, VideoDecoderException { throws ExoPlaybackException, DecoderException {
if (initialPositionUs == C.TIME_UNSET) { if (initialPositionUs == C.TIME_UNSET) {
initialPositionUs = positionUs; initialPositionUs = positionUs;
} }
......
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.video;
import android.media.MediaCodec;
import android.view.Surface;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.mediacodec.MediaCodecDecoderException;
import com.google.android.exoplayer2.mediacodec.MediaCodecInfo;
/** Thrown when a failure occurs in a {@link MediaCodec} video decoder. */
public class MediaCodecVideoDecoderException extends MediaCodecDecoderException {
/** The {@link System#identityHashCode(Object)} of the surface when the exception occurred. */
public final int surfaceIdentityHashCode;
/** Whether the surface was valid when the exception occurred. */
public final boolean isSurfaceValid;
public MediaCodecVideoDecoderException(
Throwable cause, @Nullable MediaCodecInfo codecInfo, @Nullable Surface surface) {
super(cause, codecInfo);
surfaceIdentityHashCode = System.identityHashCode(surface);
isSurfaceValid = surface == null || surface.isValid();
}
}
...@@ -43,6 +43,7 @@ import com.google.android.exoplayer2.RendererCapabilities; ...@@ -43,6 +43,7 @@ import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.drm.FrameworkMediaCrypto; import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
import com.google.android.exoplayer2.mediacodec.MediaCodecDecoderException;
import com.google.android.exoplayer2.mediacodec.MediaCodecInfo; import com.google.android.exoplayer2.mediacodec.MediaCodecInfo;
import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer; import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer;
import com.google.android.exoplayer2.mediacodec.MediaCodecSelector; import com.google.android.exoplayer2.mediacodec.MediaCodecSelector;
...@@ -95,23 +96,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -95,23 +96,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
/** Magic frame render timestamp that indicates the EOS in tunneling mode. */ /** Magic frame render timestamp that indicates the EOS in tunneling mode. */
private static final long TUNNELING_EOS_PRESENTATION_TIME_US = Long.MAX_VALUE; private static final long TUNNELING_EOS_PRESENTATION_TIME_US = Long.MAX_VALUE;
/** A {@link DecoderException} with additional surface information. */
public static final class VideoDecoderException extends DecoderException {
/** The {@link System#identityHashCode(Object)} of the surface when the exception occurred. */
public final int surfaceIdentityHashCode;
/** Whether the surface was valid when the exception occurred. */
public final boolean isSurfaceValid;
public VideoDecoderException(
Throwable cause, @Nullable MediaCodecInfo codecInfo, @Nullable Surface surface) {
super(cause, codecInfo);
surfaceIdentityHashCode = System.identityHashCode(surface);
isSurfaceValid = surface == null || surface.isValid();
}
}
private static boolean evaluatedDeviceNeedsSetOutputSurfaceWorkaround; private static boolean evaluatedDeviceNeedsSetOutputSurfaceWorkaround;
private static boolean deviceNeedsSetOutputSurfaceWorkaround; private static boolean deviceNeedsSetOutputSurfaceWorkaround;
...@@ -1303,9 +1287,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -1303,9 +1287,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
} }
@Override @Override
protected DecoderException createDecoderException( protected MediaCodecDecoderException createDecoderException(
Throwable cause, @Nullable MediaCodecInfo codecInfo) { Throwable cause, @Nullable MediaCodecInfo codecInfo) {
return new VideoDecoderException(cause, codecInfo, surface); return new MediaCodecVideoDecoderException(cause, codecInfo, surface);
} }
/** /**
......
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.video;
/** Thrown when a video decoder error occurs. */
public class VideoDecoderException extends Exception {
/**
* Creates an instance with the given message.
*
* @param message The detail message for this exception.
*/
public VideoDecoderException(String message) {
super(message);
}
/**
* Creates an instance with the given message and cause.
*
* @param message The detail message for this exception.
* @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method).
* A <tt>null</tt> value is permitted, and indicates that the cause is nonexistent or unknown.
*/
public VideoDecoderException(String message, Throwable cause) {
super(message, cause);
}
}
...@@ -29,6 +29,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; ...@@ -29,6 +29,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.RendererConfiguration; import com.google.android.exoplayer2.RendererConfiguration;
import com.google.android.exoplayer2.decoder.DecoderException;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.decoder.SimpleDecoder; import com.google.android.exoplayer2.decoder.SimpleDecoder;
import com.google.android.exoplayer2.decoder.SimpleOutputBuffer; import com.google.android.exoplayer2.decoder.SimpleOutputBuffer;
...@@ -65,7 +66,7 @@ public class DecoderAudioRendererTest { ...@@ -65,7 +66,7 @@ public class DecoderAudioRendererTest {
@Override @Override
protected SimpleDecoder< protected SimpleDecoder<
DecoderInputBuffer, ? extends SimpleOutputBuffer, ? extends AudioDecoderException> DecoderInputBuffer, ? extends SimpleOutputBuffer, ? extends DecoderException>
createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) { createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) {
return new FakeDecoder(); return new FakeDecoder();
} }
...@@ -114,7 +115,7 @@ public class DecoderAudioRendererTest { ...@@ -114,7 +115,7 @@ public class DecoderAudioRendererTest {
} }
private static final class FakeDecoder private static final class FakeDecoder
extends SimpleDecoder<DecoderInputBuffer, SimpleOutputBuffer, AudioDecoderException> { extends SimpleDecoder<DecoderInputBuffer, SimpleOutputBuffer, DecoderException> {
public FakeDecoder() { public FakeDecoder() {
super(new DecoderInputBuffer[1], new SimpleOutputBuffer[1]); super(new DecoderInputBuffer[1], new SimpleOutputBuffer[1]);
...@@ -136,13 +137,13 @@ public class DecoderAudioRendererTest { ...@@ -136,13 +137,13 @@ public class DecoderAudioRendererTest {
} }
@Override @Override
protected AudioDecoderException createUnexpectedDecodeException(Throwable error) { protected DecoderException createUnexpectedDecodeException(Throwable error) {
return new AudioDecoderException("Unexpected decode error", error); return new DecoderException("Unexpected decode error", error);
} }
@Override @Override
protected AudioDecoderException decode(DecoderInputBuffer inputBuffer, protected DecoderException decode(
SimpleOutputBuffer outputBuffer, boolean reset) { DecoderInputBuffer inputBuffer, SimpleOutputBuffer outputBuffer, boolean reset) {
if (inputBuffer.isEndOfStream()) { if (inputBuffer.isEndOfStream()) {
outputBuffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM); outputBuffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM);
} }
......
...@@ -31,6 +31,7 @@ import com.google.android.exoplayer2.C; ...@@ -31,6 +31,7 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.RendererConfiguration; import com.google.android.exoplayer2.RendererConfiguration;
import com.google.android.exoplayer2.decoder.DecoderException;
import com.google.android.exoplayer2.decoder.SimpleDecoder; import com.google.android.exoplayer2.decoder.SimpleDecoder;
import com.google.android.exoplayer2.drm.ExoMediaCrypto; import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.testutil.FakeSampleStream; import com.google.android.exoplayer2.testutil.FakeSampleStream;
...@@ -128,10 +129,10 @@ public final class DecoderVideoRendererTest { ...@@ -128,10 +129,10 @@ public final class DecoderVideoRendererTest {
protected SimpleDecoder< protected SimpleDecoder<
VideoDecoderInputBuffer, VideoDecoderInputBuffer,
? extends VideoDecoderOutputBuffer, ? extends VideoDecoderOutputBuffer,
? extends VideoDecoderException> ? extends DecoderException>
createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) { createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) {
return new SimpleDecoder< return new SimpleDecoder<
VideoDecoderInputBuffer, VideoDecoderOutputBuffer, VideoDecoderException>( VideoDecoderInputBuffer, VideoDecoderOutputBuffer, DecoderException>(
new VideoDecoderInputBuffer[10], new VideoDecoderOutputBuffer[10]) { new VideoDecoderInputBuffer[10], new VideoDecoderOutputBuffer[10]) {
@Override @Override
protected VideoDecoderInputBuffer createInputBuffer() { protected VideoDecoderInputBuffer createInputBuffer() {
...@@ -144,13 +145,13 @@ public final class DecoderVideoRendererTest { ...@@ -144,13 +145,13 @@ public final class DecoderVideoRendererTest {
} }
@Override @Override
protected VideoDecoderException createUnexpectedDecodeException(Throwable error) { protected DecoderException createUnexpectedDecodeException(Throwable error) {
return new VideoDecoderException("error", error); return new DecoderException("error", error);
} }
@Nullable @Nullable
@Override @Override
protected VideoDecoderException decode( protected DecoderException decode(
VideoDecoderInputBuffer inputBuffer, VideoDecoderInputBuffer inputBuffer,
VideoDecoderOutputBuffer outputBuffer, VideoDecoderOutputBuffer outputBuffer,
boolean reset) { boolean reset) {
......
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