Handle C.TIME_END_OF_SOURCE buffer timestamps in CeaDecoder

The behaviour was changed in 1.4.0 with 0f42dd4752,
so that the buffer timestamp is compared to `outputStartTimeUs` when
deciding whether to discard a "decode only" buffer before decoding
(instead of the deprecated/removed `isDecodeOnly` property). This breaks
when the buffer timestamp is `TIME_END_OF_SOURCE` (which is
`Long.MIN_VALUE`), because `TIME_END_OF_SOURCE < outputStartTimeUs` is
always true, so the end-of-stream buffer is never passed to the decoder
and on to `TextRenderer` where it is used to
[set `inputStreamEnded = true`](40f187e4b4/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/TextRenderer.java (L434-L436))
and so playback hangs.

Issue: androidx/media#1863
PiperOrigin-RevId: 695767247
(cherry picked from commit 19b38c83b6ce1d13effc08da834cc8ff284cb969)
This commit is contained in:
ibaker 2024-11-12 09:35:59 -08:00 committed by Ian Baker
parent f109a8167b
commit a46716c0e9
3 changed files with 25 additions and 1 deletions

View File

@ -5,6 +5,8 @@
* Text:
* Fix garbled CEA-608 subtitles in content with more than one SEI message
per sample.
* Fix playback hanging on DASH multi-period streams when CEA-608 subtitles
are enabled ([#1863](https://github.com/androidx/media/issues/1863)).
## 1.5

View File

@ -84,7 +84,9 @@ import java.util.ArrayDeque;
public void queueInputBuffer(SubtitleInputBuffer inputBuffer) throws SubtitleDecoderException {
Assertions.checkArgument(inputBuffer == dequeuedInputBuffer);
CeaInputBuffer ceaInputBuffer = (CeaInputBuffer) inputBuffer;
if (outputStartTimeUs != C.TIME_UNSET && ceaInputBuffer.timeUs < outputStartTimeUs) {
if (ceaInputBuffer.timeUs != C.TIME_END_OF_SOURCE
&& outputStartTimeUs != C.TIME_UNSET
&& ceaInputBuffer.timeUs < outputStartTimeUs) {
// We can start decoding anywhere in CEA formats, so discarding on the input side is fine.
releaseInputBuffer(ceaInputBuffer);
} else {

View File

@ -328,6 +328,26 @@ public class Cea608DecoderTest {
assertThat(getOnlyCue(firstSubtitle).text.toString()).isEqualTo("test");
}
// https://github.com/androidx/media/issues/1863
@Test
public void endOfStreamBuffer_flagPassedThrough() throws Exception {
Cea608Decoder decoder =
new Cea608Decoder(
MimeTypes.APPLICATION_CEA608,
/* accessibilityChannel= */ 1,
Cea608Decoder.MIN_DATA_CHANNEL_TIMEOUT_MS);
SubtitleInputBuffer inputBuffer = checkNotNull(decoder.dequeueInputBuffer());
inputBuffer.timeUs = C.TIME_END_OF_SOURCE;
inputBuffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);
decoder.setOutputStartTimeUs(0);
decoder.queueInputBuffer(inputBuffer);
decoder.setPositionUs(123);
SubtitleOutputBuffer outputBuffer = decoder.dequeueOutputBuffer();
assertThat(outputBuffer.isEndOfStream()).isTrue();
}
private static byte[] createPacket(int header, int cc1, int cc2) {
return new byte[] {
UnsignedBytes.checkedCast(header),