mirror of
https://github.com/samsonjs/media.git
synced 2026-04-03 10:55:48 +00:00
Don't clear the exception in SimpleDecoder.flush()
Clearing the exception puts the SimpleDecoder into a silent failure
state - the decoder thread is dead (because decode() has returned
false) but it's still possible to queue buffers to the decoder (they
just never get decoded). This partially reverts
4107375c9d
Also always recreate the decoder when handling an error in TextRenderer
This ensures we can try and decode a later subtitle sample after
encountering a decode error. This behaviour is what nulling out the
exception in SimpleDecoder.flush() was trying to achieve. We need to
ensure we don't start passing data to the new decoder until we've
hit the next key frame, so we throw away any non-keyframe samples
inside TextRenderer#render().
Issue: #7590
PiperOrigin-RevId: 319785908
This commit is contained in:
parent
39144a7e76
commit
7474547e0f
3 changed files with 27 additions and 16 deletions
|
|
@ -92,6 +92,8 @@
|
|||
ongoing load should be canceled. Only supported by HLS streams so far.
|
||||
([#2848](https://github.com/google/ExoPlayer/issues/2848)).
|
||||
* Remove throws clause from Renderer.stop.
|
||||
* Don't clear `exception` in `SimpleDecoder#flush()`
|
||||
([#7590](https://github.com/google/ExoPlayer/issues/7590)).
|
||||
* Video: Pass frame rate hint to `Surface.setFrameRate` on Android R devices.
|
||||
* Track selection:
|
||||
* Add `Player.getTrackSelector`.
|
||||
|
|
@ -138,6 +140,9 @@
|
|||
text lines to grid of viewport lines, and ignore `Cue.lineAnchor`.
|
||||
* Check `CaptionManager.isEnabled()` before using it for user-specified
|
||||
font-scaling.
|
||||
* Recreate the decoder when handling & swallowing decode errors in
|
||||
`TextRenderer`
|
||||
([#7590](https://github.com/google/ExoPlayer/issues/7590)).
|
||||
* DRM:
|
||||
* Add support for attaching DRM sessions to clear content in the demo app.
|
||||
* Remove `DrmSessionManager` references from all renderers.
|
||||
|
|
|
|||
|
|
@ -153,7 +153,6 @@ public abstract class SimpleDecoder<
|
|||
while (!queuedOutputBuffers.isEmpty()) {
|
||||
queuedOutputBuffers.removeFirst().release();
|
||||
}
|
||||
exception = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ public final class TextRenderer extends BaseRenderer implements Callback {
|
|||
|
||||
private boolean inputStreamEnded;
|
||||
private boolean outputStreamEnded;
|
||||
private boolean waitingForKeyFrame;
|
||||
@ReplacementState private int decoderReplacementState;
|
||||
@Nullable private Format streamFormat;
|
||||
@Nullable private SubtitleDecoder decoder;
|
||||
|
|
@ -145,15 +146,21 @@ public final class TextRenderer extends BaseRenderer implements Callback {
|
|||
if (decoder != null) {
|
||||
decoderReplacementState = REPLACEMENT_STATE_SIGNAL_END_OF_STREAM;
|
||||
} else {
|
||||
decoder = decoderFactory.createDecoder(streamFormat);
|
||||
initDecoder();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPositionReset(long positionUs, boolean joining) {
|
||||
clearOutput();
|
||||
inputStreamEnded = false;
|
||||
outputStreamEnded = false;
|
||||
resetOutputAndDecoder();
|
||||
if (decoderReplacementState != REPLACEMENT_STATE_NONE) {
|
||||
replaceDecoder();
|
||||
} else {
|
||||
releaseBuffers();
|
||||
decoder.flush();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -239,12 +246,16 @@ public final class TextRenderer extends BaseRenderer implements Callback {
|
|||
if (result == C.RESULT_BUFFER_READ) {
|
||||
if (nextInputBuffer.isEndOfStream()) {
|
||||
inputStreamEnded = true;
|
||||
waitingForKeyFrame = false;
|
||||
} else {
|
||||
nextInputBuffer.subsampleOffsetUs = formatHolder.format.subsampleOffsetUs;
|
||||
nextInputBuffer.flip();
|
||||
waitingForKeyFrame &= !nextInputBuffer.isKeyFrame();
|
||||
}
|
||||
if (!waitingForKeyFrame) {
|
||||
decoder.queueInputBuffer(nextInputBuffer);
|
||||
nextInputBuffer = null;
|
||||
}
|
||||
decoder.queueInputBuffer(nextInputBuffer);
|
||||
nextInputBuffer = null;
|
||||
} else if (result == C.RESULT_NOTHING_READ) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -294,9 +305,14 @@ public final class TextRenderer extends BaseRenderer implements Callback {
|
|||
decoderReplacementState = REPLACEMENT_STATE_NONE;
|
||||
}
|
||||
|
||||
private void initDecoder() {
|
||||
waitingForKeyFrame = true;
|
||||
decoder = decoderFactory.createDecoder(streamFormat);
|
||||
}
|
||||
|
||||
private void replaceDecoder() {
|
||||
releaseDecoder();
|
||||
decoder = decoderFactory.createDecoder(streamFormat);
|
||||
initDecoder();
|
||||
}
|
||||
|
||||
private long getNextEventTime() {
|
||||
|
|
@ -341,16 +357,7 @@ public final class TextRenderer extends BaseRenderer implements Callback {
|
|||
*/
|
||||
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();
|
||||
}
|
||||
replaceDecoder();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue