Catch-and-log all subtitle decode errors
issue:#6885 PiperOrigin-RevId: 295931197
This commit is contained in:
parent
ed1eade980
commit
1818921a20
@ -1,5 +1,11 @@
|
||||
# Release notes #
|
||||
|
||||
### 2.11.4 (not yet released) ###
|
||||
|
||||
* Text: Catch-and-log all fatal exceptions in `TextRenderer` instead of
|
||||
re-throwing, allowing playback to continue even if subtitles fail
|
||||
([#6885](https://github.com/google/ExoPlayer/issues/6885)).
|
||||
|
||||
### 2.11.3 (2020-02-19) ###
|
||||
|
||||
* SmoothStreaming: Fix regression that broke playback in 2.11.2
|
||||
|
@ -149,6 +149,7 @@ public abstract class SimpleDecoder<
|
||||
while (!queuedOutputBuffers.isEmpty()) {
|
||||
queuedOutputBuffers.removeFirst().release();
|
||||
}
|
||||
exception = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -225,6 +226,7 @@ public abstract class SimpleDecoder<
|
||||
if (inputBuffer.isDecodeOnly()) {
|
||||
outputBuffer.addFlag(C.BUFFER_FLAG_DECODE_ONLY);
|
||||
}
|
||||
@Nullable E exception;
|
||||
try {
|
||||
exception = decode(inputBuffer, outputBuffer, resetDecoder);
|
||||
} catch (RuntimeException e) {
|
||||
@ -238,8 +240,9 @@ public abstract class SimpleDecoder<
|
||||
exception = createUnexpectedDecodeException(e);
|
||||
}
|
||||
if (exception != null) {
|
||||
// Memory barrier to ensure that the decoder exception is visible from the playback thread.
|
||||
synchronized (lock) {}
|
||||
synchronized (lock) {
|
||||
this.exception = exception;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -23,11 +23,11 @@ import androidx.annotation.IntDef;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.BaseRenderer;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.FormatHolder;
|
||||
import com.google.android.exoplayer2.RendererCapabilities;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.Log;
|
||||
import com.google.android.exoplayer2.util.MimeTypes;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import java.lang.annotation.Documented;
|
||||
@ -45,6 +45,8 @@ import java.util.List;
|
||||
*/
|
||||
public final class TextRenderer extends BaseRenderer implements Callback {
|
||||
|
||||
private static final String TAG = "TextRenderer";
|
||||
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({
|
||||
@ -143,19 +145,13 @@ public final class TextRenderer extends BaseRenderer implements Callback {
|
||||
|
||||
@Override
|
||||
protected void onPositionReset(long positionUs, boolean joining) {
|
||||
clearOutput();
|
||||
inputStreamEnded = false;
|
||||
outputStreamEnded = false;
|
||||
if (decoderReplacementState != REPLACEMENT_STATE_NONE) {
|
||||
replaceDecoder();
|
||||
} else {
|
||||
releaseBuffers();
|
||||
decoder.flush();
|
||||
}
|
||||
resetOutputAndDecoder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException {
|
||||
public void render(long positionUs, long elapsedRealtimeUs) {
|
||||
if (outputStreamEnded) {
|
||||
return;
|
||||
}
|
||||
@ -165,7 +161,8 @@ public final class TextRenderer extends BaseRenderer implements Callback {
|
||||
try {
|
||||
nextSubtitle = decoder.dequeueOutputBuffer();
|
||||
} catch (SubtitleDecoderException e) {
|
||||
throw createRendererException(e, streamFormat);
|
||||
handleDecoderError(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -247,7 +244,8 @@ public final class TextRenderer extends BaseRenderer implements Callback {
|
||||
}
|
||||
}
|
||||
} catch (SubtitleDecoderException e) {
|
||||
throw createRendererException(e, streamFormat);
|
||||
handleDecoderError(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -329,4 +327,24 @@ public final class TextRenderer extends BaseRenderer implements Callback {
|
||||
output.onCues(cues);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when {@link #decoder} throws an exception, so it can be logged and playback can
|
||||
* continue.
|
||||
*
|
||||
* <p>Logs {@code e} and resets state to allow decoding the next sample.
|
||||
*/
|
||||
private void handleDecoderError(SubtitleDecoderException e) {
|
||||
Log.e(TAG, "Subtitle decoding failed. streamFormat=" + streamFormat, e);
|
||||
resetOutputAndDecoder();
|
||||
}
|
||||
|
||||
private void resetOutputAndDecoder() {
|
||||
clearOutput();
|
||||
if (decoderReplacementState != REPLACEMENT_STATE_NONE) {
|
||||
replaceDecoder();
|
||||
} else {
|
||||
releaseBuffers();
|
||||
decoder.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user