mirror of
https://github.com/samsonjs/media.git
synced 2026-04-05 11:15:46 +00:00
Skip negative SubRip timecodes
Issue: #2145 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=140868079
This commit is contained in:
parent
e0649db513
commit
bbbd61e319
4 changed files with 36 additions and 20 deletions
|
|
@ -0,0 +1,12 @@
|
|||
1
|
||||
-0:00:04,567 --> -0:00:03,456
|
||||
This is the first subtitle.
|
||||
|
||||
2
|
||||
-00:00:02,345 --> 00:00:01,234
|
||||
This is the second subtitle.
|
||||
Second subtitle with second line.
|
||||
|
||||
3
|
||||
00:00:04,567 --> 00:00:08,901
|
||||
This is the third subtitle.
|
||||
|
|
@ -30,6 +30,7 @@ public final class SubripDecoderTest extends InstrumentationTestCase {
|
|||
private static final String TYPICAL_EXTRA_BLANK_LINE = "subrip/typical_extra_blank_line";
|
||||
private static final String TYPICAL_MISSING_TIMECODE = "subrip/typical_missing_timecode";
|
||||
private static final String TYPICAL_MISSING_SEQUENCE = "subrip/typical_missing_sequence";
|
||||
private static final String TYPICAL_NEGATIVE_TIMESTAMPS = "subrip/typical_negative_timestamps";
|
||||
private static final String NO_END_TIMECODES_FILE = "subrip/no_end_timecodes";
|
||||
|
||||
public void testDecodeEmpty() throws IOException {
|
||||
|
|
@ -91,6 +92,15 @@ public final class SubripDecoderTest extends InstrumentationTestCase {
|
|||
assertTypicalCue3(subtitle, 2);
|
||||
}
|
||||
|
||||
public void testDecodeTypicalNegativeTimestamps() throws IOException {
|
||||
// Parsing should succeed, parsing the third cue only.
|
||||
SubripDecoder decoder = new SubripDecoder();
|
||||
byte[] bytes = TestUtil.getByteArray(getInstrumentation(), TYPICAL_NEGATIVE_TIMESTAMPS);
|
||||
SubripSubtitle subtitle = decoder.decode(bytes, bytes.length);
|
||||
assertEquals(2, subtitle.getEventTimeCount());
|
||||
assertTypicalCue3(subtitle, 0);
|
||||
}
|
||||
|
||||
public void testDecodeNoEndTimecodes() throws IOException {
|
||||
SubripDecoder decoder = new SubripDecoder();
|
||||
byte[] bytes = TestUtil.getByteArray(getInstrumentation(), NO_END_TIMECODES_FILE);
|
||||
|
|
|
|||
|
|
@ -548,7 +548,7 @@ public final class Cea608Decoder extends CeaDecoder {
|
|||
private static boolean isPreambleAddressCode(byte cc1, byte cc2) {
|
||||
// cc1 - 0|0|0|1|C|X|X|X
|
||||
// cc2 - 0|1|X|X|X|X|X|X
|
||||
return ((cc1 & 0xF0) == 0x10) && ((cc2 & 0xC0) == 0x80);
|
||||
return ((cc1 & 0xF0) == 0x10) && ((cc2 & 0xC0) == 0x40);
|
||||
}
|
||||
|
||||
private static boolean isTabCtrlCode(byte cc1, byte cc2) {
|
||||
|
|
|
|||
|
|
@ -34,9 +34,9 @@ public final class SubripDecoder extends SimpleSubtitleDecoder {
|
|||
|
||||
private static final String TAG = "SubripDecoder";
|
||||
|
||||
private static final Pattern SUBRIP_TIMING_LINE = Pattern.compile("(\\S*)\\s*-->\\s*(\\S*)");
|
||||
private static final Pattern SUBRIP_TIMESTAMP =
|
||||
Pattern.compile("(?:(\\d+):)?(\\d+):(\\d+),(\\d+)");
|
||||
private static final String SUBRIP_TIMECODE = "(?:(\\d+):)?(\\d+):(\\d+),(\\d+)";
|
||||
private static final Pattern SUBRIP_TIMING_LINE =
|
||||
Pattern.compile("\\s*(" + SUBRIP_TIMECODE + ")\\s*-->\\s*(" + SUBRIP_TIMECODE + ")?\\s*");
|
||||
|
||||
private final StringBuilder textBuilder;
|
||||
|
||||
|
|
@ -50,7 +50,6 @@ public final class SubripDecoder extends SimpleSubtitleDecoder {
|
|||
ArrayList<Cue> cues = new ArrayList<>();
|
||||
LongArray cueTimesUs = new LongArray();
|
||||
ParsableByteArray subripData = new ParsableByteArray(bytes, length);
|
||||
boolean haveEndTimecode;
|
||||
String currentLine;
|
||||
|
||||
while ((currentLine = subripData.readLine()) != null) {
|
||||
|
|
@ -68,15 +67,14 @@ public final class SubripDecoder extends SimpleSubtitleDecoder {
|
|||
}
|
||||
|
||||
// Read and parse the timing line.
|
||||
haveEndTimecode = false;
|
||||
boolean haveEndTimecode = false;
|
||||
currentLine = subripData.readLine();
|
||||
Matcher matcher = SUBRIP_TIMING_LINE.matcher(currentLine);
|
||||
if (matcher.find()) {
|
||||
cueTimesUs.add(parseTimecode(matcher.group(1)));
|
||||
String endTimecode = matcher.group(2);
|
||||
if (!TextUtils.isEmpty(endTimecode)) {
|
||||
if (matcher.matches()) {
|
||||
cueTimesUs.add(parseTimecode(matcher, 1));
|
||||
if (!TextUtils.isEmpty(matcher.group(6))) {
|
||||
haveEndTimecode = true;
|
||||
cueTimesUs.add(parseTimecode(matcher.group(2)));
|
||||
cueTimesUs.add(parseTimecode(matcher, 6));
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "Skipping invalid timing: " + currentLine);
|
||||
|
|
@ -105,15 +103,11 @@ public final class SubripDecoder extends SimpleSubtitleDecoder {
|
|||
return new SubripSubtitle(cuesArray, cueTimesUsArray);
|
||||
}
|
||||
|
||||
private static long parseTimecode(String s) throws NumberFormatException {
|
||||
Matcher matcher = SUBRIP_TIMESTAMP.matcher(s);
|
||||
if (!matcher.matches()) {
|
||||
throw new NumberFormatException("has invalid format");
|
||||
}
|
||||
long timestampMs = Long.parseLong(matcher.group(1)) * 60 * 60 * 1000;
|
||||
timestampMs += Long.parseLong(matcher.group(2)) * 60 * 1000;
|
||||
timestampMs += Long.parseLong(matcher.group(3)) * 1000;
|
||||
timestampMs += Long.parseLong(matcher.group(4));
|
||||
private static long parseTimecode(Matcher matcher, int groupOffset) {
|
||||
long timestampMs = Long.parseLong(matcher.group(groupOffset + 1)) * 60 * 60 * 1000;
|
||||
timestampMs += Long.parseLong(matcher.group(groupOffset + 2)) * 60 * 1000;
|
||||
timestampMs += Long.parseLong(matcher.group(groupOffset + 3)) * 1000;
|
||||
timestampMs += Long.parseLong(matcher.group(groupOffset + 4));
|
||||
return timestampMs * 1000;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue