Fix SSA and SRT to display an in-progress cue when enabling subtitles

Issue: androidx/media#2309
PiperOrigin-RevId: 751424941
This commit is contained in:
ibaker 2025-04-25 08:24:13 -07:00 committed by Copybara-Service
parent 35303c94a1
commit 170098b400
6 changed files with 19 additions and 12 deletions

View File

@ -40,6 +40,8 @@
* Improve codec performance checks for software video codecs. This may
lead to some additional tracks being marked as `EXCEEDS_CAPABILITIES`.
* Text:
* Fix SSA and SubRip to display an in-progress cue when enabling subtitles
([#2309](https://github.com/androidx/media/issues/2309)).
* Metadata:
* Image:
* DataSource:

View File

@ -259,7 +259,7 @@ public class SubtitleExtractor implements Extractor {
cuesWithTiming.startTimeUs,
cueEncoder.encode(cuesWithTiming.cues, cuesWithTiming.durationUs));
samples.add(sample);
if (seekTimeUs == C.TIME_UNSET || cuesWithTiming.startTimeUs >= seekTimeUs) {
if (seekTimeUs == C.TIME_UNSET || cuesWithTiming.endTimeUs >= seekTimeUs) {
writeToOutput(sample);
}
});

View File

@ -167,13 +167,14 @@ public final class SsaParser implements SubtitleParser {
}
long startTimeUs = startTimesUs.get(i);
// It's safe to inspect element i+1, because we already exited the loop above if i=size()-1.
long durationUs = startTimesUs.get(i + 1) - startTimesUs.get(i);
if (outputOptions.startTimeUs == C.TIME_UNSET || startTimeUs >= outputOptions.startTimeUs) {
output.accept(new CuesWithTiming(cuesForThisStartTime, startTimeUs, durationUs));
long endTimeUs = startTimesUs.get(i + 1);
CuesWithTiming cuesWithTiming =
new CuesWithTiming(
cuesForThisStartTime, startTimeUs, /* durationUs= */ endTimeUs - startTimeUs);
if (outputOptions.startTimeUs == C.TIME_UNSET || endTimeUs >= outputOptions.startTimeUs) {
output.accept(cuesWithTiming);
} else if (cuesWithTimingBeforeRequestedStartTimeUs != null) {
cuesWithTimingBeforeRequestedStartTimeUs.add(
new CuesWithTiming(cuesForThisStartTime, startTimeUs, durationUs));
cuesWithTimingBeforeRequestedStartTimeUs.add(cuesWithTiming);
}
}
if (cuesWithTimingBeforeRequestedStartTimeUs != null) {

View File

@ -166,7 +166,7 @@ public final class SubripParser implements SubtitleParser {
break;
}
}
if (outputOptions.startTimeUs == C.TIME_UNSET || startTimeUs >= outputOptions.startTimeUs) {
if (outputOptions.startTimeUs == C.TIME_UNSET || endTimeUs >= outputOptions.startTimeUs) {
output.accept(
new CuesWithTiming(
ImmutableList.of(buildCue(text, alignmentTag)),

View File

@ -129,7 +129,8 @@ public final class SsaParserTest {
SsaParser parser = new SsaParser();
byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL);
List<CuesWithTiming> cues = new ArrayList<>();
parser.parse(bytes, OutputOptions.onlyCuesAfter(/* startTimeUs= */ 1_000_000), cues::add);
// Choose a start time halfway through the second cue, and expect it to be included.
parser.parse(bytes, OutputOptions.onlyCuesAfter(/* startTimeUs= */ 3_000_000), cues::add);
assertThat(cues).hasSize(2);
assertTypicalCue2(cues.get(0));
@ -141,9 +142,10 @@ public final class SsaParserTest {
SsaParser parser = new SsaParser();
byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL);
List<CuesWithTiming> cues = new ArrayList<>();
// Choose a start time halfway through the second cue, and expect it to be considered 'after'.
parser.parse(
bytes,
OutputOptions.cuesAfterThenRemainingCuesBefore(/* startTimeUs= */ 1_000_000),
OutputOptions.cuesAfterThenRemainingCuesBefore(/* startTimeUs= */ 3_000_000),
cues::add);
assertThat(cues).hasSize(3);

View File

@ -105,7 +105,8 @@ public final class SubripParserTest {
byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL_FILE);
List<CuesWithTiming> cues = new ArrayList<>();
parser.parse(bytes, OutputOptions.onlyCuesAfter(/* startTimeUs= */ 1_000_000), cues::add);
// Choose a start time halfway through the second cue, and expect it to be included.
parser.parse(bytes, OutputOptions.onlyCuesAfter(/* startTimeUs= */ 3_000_000), cues::add);
assertThat(cues).hasSize(2);
assertTypicalCue2(cues.get(0));
@ -118,9 +119,10 @@ public final class SubripParserTest {
byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL_FILE);
List<CuesWithTiming> cues = new ArrayList<>();
// Choose a start time halfway through the second cue, and expect it to be considered 'after'.
parser.parse(
bytes,
OutputOptions.cuesAfterThenRemainingCuesBefore(/* startTimeUs= */ 1_000_000),
OutputOptions.cuesAfterThenRemainingCuesBefore(/* startTimeUs= */ 3_000_000),
cues::add);
assertThat(cues).hasSize(3);