mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Refactored the SubtitleParser's parse() signature
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=111326567
This commit is contained in:
parent
9bcd1069b1
commit
681df4e4aa
17 changed files with 188 additions and 121 deletions
|
|
@ -21,13 +21,16 @@ import com.google.android.exoplayer.extractor.Extractor;
|
||||||
import com.google.android.exoplayer.extractor.ExtractorInput;
|
import com.google.android.exoplayer.extractor.ExtractorInput;
|
||||||
import com.google.android.exoplayer.extractor.PositionHolder;
|
import com.google.android.exoplayer.extractor.PositionHolder;
|
||||||
import com.google.android.exoplayer.upstream.DataSpec;
|
import com.google.android.exoplayer.upstream.DataSpec;
|
||||||
|
import com.google.android.exoplayer.util.Util;
|
||||||
|
|
||||||
|
import android.app.Instrumentation;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.test.InstrumentationTestCase;
|
import android.test.InstrumentationTestCase;
|
||||||
|
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
|
@ -115,4 +118,10 @@ public class TestUtil {
|
||||||
MockitoAnnotations.initMocks(instrumentationTestCase);
|
MockitoAnnotations.initMocks(instrumentationTestCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte[] getByteArray(Instrumentation instrumentation, String fileName)
|
||||||
|
throws IOException {
|
||||||
|
InputStream is = instrumentation.getContext().getResources().getAssets().open(fileName);
|
||||||
|
return Util.toByteArray(is);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ import android.util.ArraySet;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -107,29 +106,29 @@ public final class Mp4WebvttParserTest extends TestCase {
|
||||||
|
|
||||||
// Positive tests.
|
// Positive tests.
|
||||||
|
|
||||||
public void testSingleCueSample() throws IOException {
|
public void testSingleCueSample() throws ParserException {
|
||||||
Subtitle result = parser.parse(new ByteArrayInputStream(SINGLE_CUE_SAMPLE));
|
Subtitle result = parser.parse(SINGLE_CUE_SAMPLE, 0, SINGLE_CUE_SAMPLE.length);
|
||||||
Cue expectedCue = new Cue("Hello World"); // Line feed must be trimmed by the parser
|
Cue expectedCue = new Cue("Hello World"); // Line feed must be trimmed by the parser
|
||||||
assertMp4WebvttSubtitleEquals(result, expectedCue);
|
assertMp4WebvttSubtitleEquals(result, expectedCue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTwoCuesSample() throws IOException {
|
public void testTwoCuesSample() throws ParserException {
|
||||||
Subtitle result = parser.parse(new ByteArrayInputStream(DOUBLE_CUE_SAMPLE));
|
Subtitle result = parser.parse(DOUBLE_CUE_SAMPLE, 0, DOUBLE_CUE_SAMPLE.length);
|
||||||
Cue firstExpectedCue = new Cue("Hello World");
|
Cue firstExpectedCue = new Cue("Hello World");
|
||||||
Cue secondExpectedCue = new Cue("Bye Bye");
|
Cue secondExpectedCue = new Cue("Bye Bye");
|
||||||
assertMp4WebvttSubtitleEquals(result, firstExpectedCue, secondExpectedCue);
|
assertMp4WebvttSubtitleEquals(result, firstExpectedCue, secondExpectedCue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNoCueSample() throws IOException {
|
public void testNoCueSample() throws IOException {
|
||||||
Subtitle result = parser.parse(new ByteArrayInputStream(NO_CUE_SAMPLE));
|
Subtitle result = parser.parse(NO_CUE_SAMPLE, 0, NO_CUE_SAMPLE.length);
|
||||||
assertMp4WebvttSubtitleEquals(result, new Cue[] {});
|
assertMp4WebvttSubtitleEquals(result, new Cue[] {});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Negative tests.
|
// Negative tests.
|
||||||
|
|
||||||
public void testSampleWithVttCueWithNoPayload() throws IOException {
|
public void testSampleWithVttCueWithNoPayload() {
|
||||||
try {
|
try {
|
||||||
parser.parse(new ByteArrayInputStream(NO_PAYLOAD_CUE_SAMPLE));
|
parser.parse(NO_PAYLOAD_CUE_SAMPLE, 0, NO_PAYLOAD_CUE_SAMPLE.length);
|
||||||
} catch (ParserException e) {
|
} catch (ParserException e) {
|
||||||
// Expected.
|
// Expected.
|
||||||
return;
|
return;
|
||||||
|
|
@ -137,9 +136,9 @@ public final class Mp4WebvttParserTest extends TestCase {
|
||||||
fail("The parser should have failed, no payload was included in the VTTCue.");
|
fail("The parser should have failed, no payload was included in the VTTCue.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSampleWithIncompleteHeader() throws IOException {
|
public void testSampleWithIncompleteHeader() {
|
||||||
try {
|
try {
|
||||||
parser.parse(new ByteArrayInputStream(INCOMPLETE_HEADER_SAMPLE));
|
parser.parse(INCOMPLETE_HEADER_SAMPLE, 0, INCOMPLETE_HEADER_SAMPLE.length);
|
||||||
} catch (ParserException e) {
|
} catch (ParserException e) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,11 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer.text.subrip;
|
package com.google.android.exoplayer.text.subrip;
|
||||||
|
|
||||||
|
import com.google.android.exoplayer.testutil.TestUtil;
|
||||||
|
|
||||||
import android.test.InstrumentationTestCase;
|
import android.test.InstrumentationTestCase;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit test for {@link SubripParser}.
|
* Unit test for {@link SubripParser}.
|
||||||
|
|
@ -34,8 +35,8 @@ public final class SubripParserTest extends InstrumentationTestCase {
|
||||||
|
|
||||||
public void testParseEmpty() throws IOException {
|
public void testParseEmpty() throws IOException {
|
||||||
SubripParser parser = new SubripParser();
|
SubripParser parser = new SubripParser();
|
||||||
InputStream inputStream = getInputStream(EMPTY_FILE);
|
byte[] bytes = TestUtil.getByteArray(getInstrumentation(), EMPTY_FILE);
|
||||||
SubripSubtitle subtitle = parser.parse(inputStream);
|
SubripSubtitle subtitle = parser.parse(bytes, 0, bytes.length);
|
||||||
// Assert that the subtitle is empty.
|
// Assert that the subtitle is empty.
|
||||||
assertEquals(0, subtitle.getEventTimeCount());
|
assertEquals(0, subtitle.getEventTimeCount());
|
||||||
assertTrue(subtitle.getCues(0).isEmpty());
|
assertTrue(subtitle.getCues(0).isEmpty());
|
||||||
|
|
@ -43,8 +44,8 @@ public final class SubripParserTest extends InstrumentationTestCase {
|
||||||
|
|
||||||
public void testParseTypical() throws IOException {
|
public void testParseTypical() throws IOException {
|
||||||
SubripParser parser = new SubripParser();
|
SubripParser parser = new SubripParser();
|
||||||
InputStream inputStream = getInputStream(TYPICAL_FILE);
|
byte[] bytes = TestUtil.getByteArray(getInstrumentation(), TYPICAL_FILE);
|
||||||
SubripSubtitle subtitle = parser.parse(inputStream);
|
SubripSubtitle subtitle = parser.parse(bytes, 0, bytes.length);
|
||||||
assertEquals(6, subtitle.getEventTimeCount());
|
assertEquals(6, subtitle.getEventTimeCount());
|
||||||
assertTypicalCue1(subtitle, 0);
|
assertTypicalCue1(subtitle, 0);
|
||||||
assertTypicalCue2(subtitle, 2);
|
assertTypicalCue2(subtitle, 2);
|
||||||
|
|
@ -53,8 +54,8 @@ public final class SubripParserTest extends InstrumentationTestCase {
|
||||||
|
|
||||||
public void testParseTypicalExtraBlankLine() throws IOException {
|
public void testParseTypicalExtraBlankLine() throws IOException {
|
||||||
SubripParser parser = new SubripParser();
|
SubripParser parser = new SubripParser();
|
||||||
InputStream inputStream = getInputStream(TYPICAL_EXTRA_BLANK_LINE);
|
byte[] bytes = TestUtil.getByteArray(getInstrumentation(), TYPICAL_EXTRA_BLANK_LINE);
|
||||||
SubripSubtitle subtitle = parser.parse(inputStream);
|
SubripSubtitle subtitle = parser.parse(bytes, 0, bytes.length);
|
||||||
assertEquals(6, subtitle.getEventTimeCount());
|
assertEquals(6, subtitle.getEventTimeCount());
|
||||||
assertTypicalCue1(subtitle, 0);
|
assertTypicalCue1(subtitle, 0);
|
||||||
assertTypicalCue2(subtitle, 2);
|
assertTypicalCue2(subtitle, 2);
|
||||||
|
|
@ -64,8 +65,8 @@ public final class SubripParserTest extends InstrumentationTestCase {
|
||||||
public void testParseTypicalMissingTimecode() throws IOException {
|
public void testParseTypicalMissingTimecode() throws IOException {
|
||||||
// Parsing should succeed, parsing the first and third cues only.
|
// Parsing should succeed, parsing the first and third cues only.
|
||||||
SubripParser parser = new SubripParser();
|
SubripParser parser = new SubripParser();
|
||||||
InputStream inputStream = getInputStream(TYPICAL_MISSING_TIMECODE);
|
byte[] bytes = TestUtil.getByteArray(getInstrumentation(), TYPICAL_MISSING_TIMECODE);
|
||||||
SubripSubtitle subtitle = parser.parse(inputStream);
|
SubripSubtitle subtitle = parser.parse(bytes, 0, bytes.length);
|
||||||
assertEquals(4, subtitle.getEventTimeCount());
|
assertEquals(4, subtitle.getEventTimeCount());
|
||||||
assertTypicalCue1(subtitle, 0);
|
assertTypicalCue1(subtitle, 0);
|
||||||
assertTypicalCue3(subtitle, 2);
|
assertTypicalCue3(subtitle, 2);
|
||||||
|
|
@ -74,8 +75,8 @@ public final class SubripParserTest extends InstrumentationTestCase {
|
||||||
public void testParseTypicalMissingSequence() throws IOException {
|
public void testParseTypicalMissingSequence() throws IOException {
|
||||||
// Parsing should succeed, parsing the first and third cues only.
|
// Parsing should succeed, parsing the first and third cues only.
|
||||||
SubripParser parser = new SubripParser();
|
SubripParser parser = new SubripParser();
|
||||||
InputStream inputStream = getInputStream(TYPICAL_MISSING_SEQUENCE);
|
byte[] bytes = TestUtil.getByteArray(getInstrumentation(), TYPICAL_MISSING_SEQUENCE);
|
||||||
SubripSubtitle subtitle = parser.parse(inputStream);
|
SubripSubtitle subtitle = parser.parse(bytes, 0, bytes.length);
|
||||||
assertEquals(4, subtitle.getEventTimeCount());
|
assertEquals(4, subtitle.getEventTimeCount());
|
||||||
assertTypicalCue1(subtitle, 0);
|
assertTypicalCue1(subtitle, 0);
|
||||||
assertTypicalCue3(subtitle, 2);
|
assertTypicalCue3(subtitle, 2);
|
||||||
|
|
@ -83,8 +84,8 @@ public final class SubripParserTest extends InstrumentationTestCase {
|
||||||
|
|
||||||
public void testParseNoEndTimecodes() throws IOException {
|
public void testParseNoEndTimecodes() throws IOException {
|
||||||
SubripParser parser = new SubripParser();
|
SubripParser parser = new SubripParser();
|
||||||
InputStream inputStream = getInputStream(NO_END_TIMECODES_FILE);
|
byte[] bytes = TestUtil.getByteArray(getInstrumentation(), NO_END_TIMECODES_FILE);
|
||||||
SubripSubtitle subtitle = parser.parse(inputStream);
|
SubripSubtitle subtitle = parser.parse(bytes, 0, bytes.length);
|
||||||
|
|
||||||
// Test event count.
|
// Test event count.
|
||||||
assertEquals(3, subtitle.getEventTimeCount());
|
assertEquals(3, subtitle.getEventTimeCount());
|
||||||
|
|
@ -105,10 +106,6 @@ public final class SubripParserTest extends InstrumentationTestCase {
|
||||||
subtitle.getCues(subtitle.getEventTime(2)).get(0).text.toString());
|
subtitle.getCues(subtitle.getEventTime(2)).get(0).text.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private InputStream getInputStream(String fileName) throws IOException {
|
|
||||||
return getInstrumentation().getContext().getResources().getAssets().open(fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void assertTypicalCue1(SubripSubtitle subtitle, int eventIndex) {
|
private static void assertTypicalCue1(SubripSubtitle subtitle, int eventIndex) {
|
||||||
assertEquals(0, subtitle.getEventTime(eventIndex));
|
assertEquals(0, subtitle.getEventTime(eventIndex));
|
||||||
assertEquals("This is the first subtitle.",
|
assertEquals("This is the first subtitle.",
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer.text.ttml;
|
package com.google.android.exoplayer.text.ttml;
|
||||||
|
|
||||||
|
import com.google.android.exoplayer.testutil.TestUtil;
|
||||||
import com.google.android.exoplayer.text.Cue;
|
import com.google.android.exoplayer.text.Cue;
|
||||||
|
|
||||||
import android.test.InstrumentationTestCase;
|
import android.test.InstrumentationTestCase;
|
||||||
|
|
@ -32,7 +33,6 @@ import android.text.style.TypefaceSpan;
|
||||||
import android.text.style.UnderlineSpan;
|
import android.text.style.UnderlineSpan;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
@ -471,8 +471,7 @@ public final class TtmlParserTest extends InstrumentationTestCase {
|
||||||
|
|
||||||
private TtmlSubtitle getSubtitle(String file) throws IOException {
|
private TtmlSubtitle getSubtitle(String file) throws IOException {
|
||||||
TtmlParser ttmlParser = new TtmlParser();
|
TtmlParser ttmlParser = new TtmlParser();
|
||||||
InputStream inputStream = getInstrumentation().getContext()
|
byte[] bytes = TestUtil.getByteArray(getInstrumentation(), file);
|
||||||
.getResources().getAssets().open(file);
|
return ttmlParser.parse(bytes, 0, bytes.length);
|
||||||
return (TtmlSubtitle) ttmlParser.parse(inputStream);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,14 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer.text.webvtt;
|
package com.google.android.exoplayer.text.webvtt;
|
||||||
|
|
||||||
|
import com.google.android.exoplayer.ParserException;
|
||||||
|
import com.google.android.exoplayer.testutil.TestUtil;
|
||||||
import com.google.android.exoplayer.text.Cue;
|
import com.google.android.exoplayer.text.Cue;
|
||||||
|
|
||||||
import android.test.InstrumentationTestCase;
|
import android.test.InstrumentationTestCase;
|
||||||
import android.text.Layout.Alignment;
|
import android.text.Layout.Alignment;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -39,21 +40,19 @@ public class WebvttParserTest extends InstrumentationTestCase {
|
||||||
|
|
||||||
public void testParseEmpty() throws IOException {
|
public void testParseEmpty() throws IOException {
|
||||||
WebvttParser parser = new WebvttParser();
|
WebvttParser parser = new WebvttParser();
|
||||||
InputStream inputStream = getInstrumentation().getContext().getResources().getAssets()
|
byte[] bytes = TestUtil.getByteArray(getInstrumentation(), EMPTY_FILE);
|
||||||
.open(EMPTY_FILE);
|
|
||||||
try {
|
try {
|
||||||
parser.parse(inputStream);
|
parser.parse(bytes, 0, bytes.length);
|
||||||
fail("Expected IOException");
|
fail("Expected ParserException");
|
||||||
} catch (IOException expected) {
|
} catch (ParserException expected) {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testParseTypical() throws IOException {
|
public void testParseTypical() throws IOException {
|
||||||
WebvttParser parser = new WebvttParser();
|
WebvttParser parser = new WebvttParser();
|
||||||
InputStream inputStream =
|
byte[] bytes = TestUtil.getByteArray(getInstrumentation(), TYPICAL_FILE);
|
||||||
getInstrumentation().getContext().getResources().getAssets().open(TYPICAL_FILE);
|
WebvttSubtitle subtitle = parser.parse(bytes, 0, bytes.length);
|
||||||
WebvttSubtitle subtitle = parser.parse(inputStream);
|
|
||||||
|
|
||||||
// test event count
|
// test event count
|
||||||
assertEquals(4, subtitle.getEventTimeCount());
|
assertEquals(4, subtitle.getEventTimeCount());
|
||||||
|
|
@ -65,9 +64,8 @@ public class WebvttParserTest extends InstrumentationTestCase {
|
||||||
|
|
||||||
public void testParseTypicalWithIds() throws IOException {
|
public void testParseTypicalWithIds() throws IOException {
|
||||||
WebvttParser parser = new WebvttParser();
|
WebvttParser parser = new WebvttParser();
|
||||||
InputStream inputStream = getInstrumentation().getContext().getResources().getAssets()
|
byte[] bytes = TestUtil.getByteArray(getInstrumentation(), TYPICAL_WITH_IDS_FILE);
|
||||||
.open(TYPICAL_WITH_IDS_FILE);
|
WebvttSubtitle subtitle = parser.parse(bytes, 0, bytes.length);
|
||||||
WebvttSubtitle subtitle = parser.parse(inputStream);
|
|
||||||
|
|
||||||
// test event count
|
// test event count
|
||||||
assertEquals(4, subtitle.getEventTimeCount());
|
assertEquals(4, subtitle.getEventTimeCount());
|
||||||
|
|
@ -79,9 +77,8 @@ public class WebvttParserTest extends InstrumentationTestCase {
|
||||||
|
|
||||||
public void testParseTypicalWithComments() throws IOException {
|
public void testParseTypicalWithComments() throws IOException {
|
||||||
WebvttParser parser = new WebvttParser();
|
WebvttParser parser = new WebvttParser();
|
||||||
InputStream inputStream = getInstrumentation().getContext().getResources().getAssets()
|
byte[] bytes = TestUtil.getByteArray(getInstrumentation(), TYPICAL_WITH_COMMENTS_FILE);
|
||||||
.open(TYPICAL_WITH_COMMENTS_FILE);
|
WebvttSubtitle subtitle = parser.parse(bytes, 0, bytes.length);
|
||||||
WebvttSubtitle subtitle = parser.parse(inputStream);
|
|
||||||
|
|
||||||
// test event count
|
// test event count
|
||||||
assertEquals(4, subtitle.getEventTimeCount());
|
assertEquals(4, subtitle.getEventTimeCount());
|
||||||
|
|
@ -93,9 +90,8 @@ public class WebvttParserTest extends InstrumentationTestCase {
|
||||||
|
|
||||||
public void testParseWithTags() throws IOException {
|
public void testParseWithTags() throws IOException {
|
||||||
WebvttParser parser = new WebvttParser();
|
WebvttParser parser = new WebvttParser();
|
||||||
InputStream inputStream = getInstrumentation().getContext().getResources().getAssets()
|
byte[] bytes = TestUtil.getByteArray(getInstrumentation(), WITH_TAGS_FILE);
|
||||||
.open(WITH_TAGS_FILE);
|
WebvttSubtitle subtitle = parser.parse(bytes, 0, bytes.length);
|
||||||
WebvttSubtitle subtitle = parser.parse(inputStream);
|
|
||||||
|
|
||||||
// test event count
|
// test event count
|
||||||
assertEquals(8, subtitle.getEventTimeCount());
|
assertEquals(8, subtitle.getEventTimeCount());
|
||||||
|
|
@ -109,9 +105,8 @@ public class WebvttParserTest extends InstrumentationTestCase {
|
||||||
|
|
||||||
public void testParseWithPositioning() throws IOException {
|
public void testParseWithPositioning() throws IOException {
|
||||||
WebvttParser parser = new WebvttParser();
|
WebvttParser parser = new WebvttParser();
|
||||||
InputStream inputStream = getInstrumentation().getContext().getResources().getAssets()
|
byte[] bytes = TestUtil.getByteArray(getInstrumentation(), WITH_POSITIONING_FILE);
|
||||||
.open(WITH_POSITIONING_FILE);
|
WebvttSubtitle subtitle = parser.parse(bytes, 0, bytes.length);
|
||||||
WebvttSubtitle subtitle = parser.parse(inputStream);
|
|
||||||
|
|
||||||
// test event count
|
// test event count
|
||||||
assertEquals(10, subtitle.getEventTimeCount());
|
assertEquals(10, subtitle.getEventTimeCount());
|
||||||
|
|
@ -135,9 +130,8 @@ public class WebvttParserTest extends InstrumentationTestCase {
|
||||||
|
|
||||||
public void testParseWithBadCueHeader() throws IOException {
|
public void testParseWithBadCueHeader() throws IOException {
|
||||||
WebvttParser parser = new WebvttParser();
|
WebvttParser parser = new WebvttParser();
|
||||||
InputStream inputStream =
|
byte[] bytes = TestUtil.getByteArray(getInstrumentation(), WITH_BAD_CUE_HEADER_FILE);
|
||||||
getInstrumentation().getContext().getResources().getAssets().open(WITH_BAD_CUE_HEADER_FILE);
|
WebvttSubtitle subtitle = parser.parse(bytes, 0, bytes.length);
|
||||||
WebvttSubtitle subtitle = parser.parse(inputStream);
|
|
||||||
|
|
||||||
// test event count
|
// test event count
|
||||||
assertEquals(4, subtitle.getEventTimeCount());
|
assertEquals(4, subtitle.getEventTimeCount());
|
||||||
|
|
|
||||||
|
|
@ -322,4 +322,61 @@ public class ParsableByteArrayTest extends TestCase {
|
||||||
assertEquals((short) 0xFF02, byteArray.readLittleEndianShort());
|
assertEquals((short) 0xFF02, byteArray.readLittleEndianShort());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testReadEmptyString() {
|
||||||
|
byte[] bytes = new byte[0];
|
||||||
|
ParsableByteArray parser = new ParsableByteArray(bytes);
|
||||||
|
assertNull(parser.readLine());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReadSingleLineWithoutEndingTrail() {
|
||||||
|
byte[] bytes = new byte[] {
|
||||||
|
'f', 'o', 'o'
|
||||||
|
};
|
||||||
|
ParsableByteArray parser = new ParsableByteArray(bytes);
|
||||||
|
assertEquals("foo", parser.readLine());
|
||||||
|
assertNull(parser.readLine());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReadSingleLineWithEndingLf() {
|
||||||
|
byte[] bytes = new byte[] {
|
||||||
|
'f', 'o', 'o', '\n'
|
||||||
|
};
|
||||||
|
ParsableByteArray parser = new ParsableByteArray(bytes);
|
||||||
|
assertEquals("foo", parser.readLine());
|
||||||
|
assertNull(parser.readLine());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReadTwoLinesWithLfFollowedByCr() {
|
||||||
|
byte[] bytes = new byte[] {
|
||||||
|
'f', 'o', 'o', '\n', '\r', 'b', 'a', 'r'
|
||||||
|
};
|
||||||
|
ParsableByteArray parser = new ParsableByteArray(bytes);
|
||||||
|
assertEquals("foo", parser.readLine());
|
||||||
|
assertEquals("bar", parser.readLine());
|
||||||
|
assertNull(parser.readLine());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReadThreeLinesWithEmptyLine() {
|
||||||
|
byte[] bytes = new byte[] {
|
||||||
|
'f', 'o', 'o', '\n', '\r', '\n', 'b', 'a', 'r'
|
||||||
|
};
|
||||||
|
ParsableByteArray parser = new ParsableByteArray(bytes);
|
||||||
|
assertEquals("foo", parser.readLine());
|
||||||
|
assertEquals("", parser.readLine());
|
||||||
|
assertEquals("bar", parser.readLine());
|
||||||
|
assertNull(parser.readLine());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReadFourLinesWithCrFollowedByLf() {
|
||||||
|
byte[] bytes = new byte[] {
|
||||||
|
'f', 'o', 'o', '\r', '\n', '\n', 'b', 'a', 'r', '\n', '\r'
|
||||||
|
};
|
||||||
|
ParsableByteArray parser = new ParsableByteArray(bytes);
|
||||||
|
assertEquals("foo", parser.readLine());
|
||||||
|
assertEquals("", parser.readLine());
|
||||||
|
assertEquals("", parser.readLine());
|
||||||
|
assertEquals("bar", parser.readLine());
|
||||||
|
assertNull(parser.readLine());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,10 +31,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
|
||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
@ -111,12 +108,11 @@ import java.util.regex.Pattern;
|
||||||
return Extractor.RESULT_END_OF_INPUT;
|
return Extractor.RESULT_END_OF_INPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processSample() throws IOException {
|
private void processSample() throws ParserException {
|
||||||
BufferedReader reader = new BufferedReader(
|
ParsableByteArray webvttData = new ParsableByteArray(sampleData);
|
||||||
new InputStreamReader(new ByteArrayInputStream(sampleData), C.UTF8_NAME));
|
|
||||||
|
|
||||||
// Validate the first line of the header.
|
// Validate the first line of the header.
|
||||||
WebvttParserUtil.validateWebvttHeaderLine(reader);
|
WebvttParserUtil.validateWebvttHeaderLine(webvttData);
|
||||||
|
|
||||||
// Defaults to use if the header doesn't contain an X-TIMESTAMP-MAP header.
|
// Defaults to use if the header doesn't contain an X-TIMESTAMP-MAP header.
|
||||||
long vttTimestampUs = 0;
|
long vttTimestampUs = 0;
|
||||||
|
|
@ -124,7 +120,7 @@ import java.util.regex.Pattern;
|
||||||
|
|
||||||
// Parse the remainder of the header looking for X-TIMESTAMP-MAP.
|
// Parse the remainder of the header looking for X-TIMESTAMP-MAP.
|
||||||
String line;
|
String line;
|
||||||
while (!TextUtils.isEmpty(line = reader.readLine())) {
|
while (!TextUtils.isEmpty(line = webvttData.readLine())) {
|
||||||
if (line.startsWith("X-TIMESTAMP-MAP")) {
|
if (line.startsWith("X-TIMESTAMP-MAP")) {
|
||||||
Matcher localTimestampMatcher = LOCAL_TIMESTAMP.matcher(line);
|
Matcher localTimestampMatcher = LOCAL_TIMESTAMP.matcher(line);
|
||||||
if (!localTimestampMatcher.find()) {
|
if (!localTimestampMatcher.find()) {
|
||||||
|
|
@ -141,7 +137,7 @@ import java.util.regex.Pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the first cue header and parse the start time.
|
// Find the first cue header and parse the start time.
|
||||||
Matcher cueHeaderMatcher = WebvttParserUtil.findNextCueHeader(reader);
|
Matcher cueHeaderMatcher = WebvttParserUtil.findNextCueHeader(webvttData);
|
||||||
if (cueHeaderMatcher == null) {
|
if (cueHeaderMatcher == null) {
|
||||||
// No cues found. Don't output a sample, but still output a corresponding track.
|
// No cues found. Don't output a sample, but still output a corresponding track.
|
||||||
buildTrackOutput(0);
|
buildTrackOutput(0);
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer.text;
|
package com.google.android.exoplayer.text;
|
||||||
|
|
||||||
import java.io.IOException;
|
import com.google.android.exoplayer.ParserException;
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses {@link Subtitle}s from {@link InputStream}s.
|
* Parses {@link Subtitle}s from a byte array.
|
||||||
*/
|
*/
|
||||||
public interface SubtitleParser {
|
public interface SubtitleParser {
|
||||||
|
|
||||||
|
|
@ -32,12 +31,14 @@ public interface SubtitleParser {
|
||||||
public boolean canParse(String mimeType);
|
public boolean canParse(String mimeType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a {@link Subtitle} from the provided {@link InputStream}.
|
* Parses a {@link Subtitle} from the provided {@code byte[]}.
|
||||||
*
|
*
|
||||||
* @param inputStream The stream from which to parse the subtitle.
|
* @param bytes The array holding the subtitle data.
|
||||||
|
* @param offset The offset of the subtitle data in bytes.
|
||||||
|
* @param length The length of the subtitle data in bytes.
|
||||||
* @return A parsed representation of the subtitle.
|
* @return A parsed representation of the subtitle.
|
||||||
* @throws IOException If a problem occurred reading from the stream.
|
* @throws ParserException If a problem occurred parsing the subtitle data.
|
||||||
*/
|
*/
|
||||||
public Subtitle parse(InputStream inputStream) throws IOException;
|
public Subtitle parse(byte[] bytes, int offset, int length) throws ParserException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
package com.google.android.exoplayer.text;
|
package com.google.android.exoplayer.text;
|
||||||
|
|
||||||
import com.google.android.exoplayer.MediaFormat;
|
import com.google.android.exoplayer.MediaFormat;
|
||||||
|
import com.google.android.exoplayer.ParserException;
|
||||||
import com.google.android.exoplayer.SampleHolder;
|
import com.google.android.exoplayer.SampleHolder;
|
||||||
import com.google.android.exoplayer.util.Assertions;
|
import com.google.android.exoplayer.util.Assertions;
|
||||||
import com.google.android.exoplayer.util.Util;
|
import com.google.android.exoplayer.util.Util;
|
||||||
|
|
@ -25,9 +26,7 @@ import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wraps a {@link SubtitleParser}, exposing an interface similar to {@link MediaCodec} for
|
* Wraps a {@link SubtitleParser}, exposing an interface similar to {@link MediaCodec} for
|
||||||
|
|
@ -165,12 +164,11 @@ import java.io.InputStream;
|
||||||
|
|
||||||
private void handleSample(long sampleTimeUs, SampleHolder holder) {
|
private void handleSample(long sampleTimeUs, SampleHolder holder) {
|
||||||
Subtitle parsedSubtitle = null;
|
Subtitle parsedSubtitle = null;
|
||||||
IOException error = null;
|
ParserException error = null;
|
||||||
RuntimeException runtimeError = null;
|
RuntimeException runtimeError = null;
|
||||||
try {
|
try {
|
||||||
InputStream inputStream = new ByteArrayInputStream(holder.data.array(), 0, holder.size);
|
parsedSubtitle = parser.parse(holder.data.array(), 0, holder.size);
|
||||||
parsedSubtitle = parser.parse(inputStream);
|
} catch (ParserException e) {
|
||||||
} catch (IOException e) {
|
|
||||||
error = e;
|
error = e;
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
runtimeError = e;
|
runtimeError = e;
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,6 @@ import com.google.android.exoplayer.util.MimeTypes;
|
||||||
import com.google.android.exoplayer.util.ParsableByteArray;
|
import com.google.android.exoplayer.util.ParsableByteArray;
|
||||||
import com.google.android.exoplayer.util.Util;
|
import com.google.android.exoplayer.util.Util;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
@ -38,7 +36,6 @@ public final class Mp4WebvttParser implements SubtitleParser {
|
||||||
private static final int TYPE_payl = Util.getIntegerCodeForString("payl");
|
private static final int TYPE_payl = Util.getIntegerCodeForString("payl");
|
||||||
|
|
||||||
private final ParsableByteArray sampleData;
|
private final ParsableByteArray sampleData;
|
||||||
private byte[] inputBytesBuffer;
|
|
||||||
|
|
||||||
public Mp4WebvttParser() {
|
public Mp4WebvttParser() {
|
||||||
sampleData = new ParsableByteArray();
|
sampleData = new ParsableByteArray();
|
||||||
|
|
@ -50,15 +47,11 @@ public final class Mp4WebvttParser implements SubtitleParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mp4WebvttSubtitle parse(InputStream inputStream) throws IOException {
|
public Mp4WebvttSubtitle parse(byte[] bytes, int offset, int length) throws ParserException {
|
||||||
// Webvtt in Mp4 samples have boxes inside of them, so we have to do a traditional box parsing:
|
// Webvtt in Mp4 samples have boxes inside of them, so we have to do a traditional box parsing:
|
||||||
// first 4 bytes size and then 4 bytes type.
|
// first 4 bytes size and then 4 bytes type.
|
||||||
int inputStreamByteCount = inputStream.available();
|
sampleData.reset(bytes, offset + length);
|
||||||
if (inputBytesBuffer == null || inputBytesBuffer.length < inputStreamByteCount) {
|
sampleData.setPosition(offset);
|
||||||
inputBytesBuffer = new byte[inputStreamByteCount];
|
|
||||||
}
|
|
||||||
inputStream.read(inputBytesBuffer, 0, inputStreamByteCount);
|
|
||||||
sampleData.reset(inputBytesBuffer, inputStreamByteCount);
|
|
||||||
List<Cue> resultingCueList = new ArrayList<>();
|
List<Cue> resultingCueList = new ArrayList<>();
|
||||||
while (sampleData.bytesLeft() > 0) {
|
while (sampleData.bytesLeft() > 0) {
|
||||||
if (sampleData.bytesLeft() < BOX_HEADER_SIZE) {
|
if (sampleData.bytesLeft() < BOX_HEADER_SIZE) {
|
||||||
|
|
@ -76,7 +69,7 @@ public final class Mp4WebvttParser implements SubtitleParser {
|
||||||
return new Mp4WebvttSubtitle(resultingCueList);
|
return new Mp4WebvttSubtitle(resultingCueList);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Cue parseVttCueBox(ParsableByteArray sampleData) throws IOException {
|
private static Cue parseVttCueBox(ParsableByteArray sampleData) throws ParserException {
|
||||||
while (sampleData.bytesLeft() > 0) {
|
while (sampleData.bytesLeft() > 0) {
|
||||||
if (sampleData.bytesLeft() < BOX_HEADER_SIZE) {
|
if (sampleData.bytesLeft() < BOX_HEADER_SIZE) {
|
||||||
throw new ParserException("Incomplete vtt cue box header found.");
|
throw new ParserException("Incomplete vtt cue box header found.");
|
||||||
|
|
|
||||||
|
|
@ -15,21 +15,17 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer.text.subrip;
|
package com.google.android.exoplayer.text.subrip;
|
||||||
|
|
||||||
import com.google.android.exoplayer.C;
|
|
||||||
import com.google.android.exoplayer.text.Cue;
|
import com.google.android.exoplayer.text.Cue;
|
||||||
import com.google.android.exoplayer.text.SubtitleParser;
|
import com.google.android.exoplayer.text.SubtitleParser;
|
||||||
import com.google.android.exoplayer.util.LongArray;
|
import com.google.android.exoplayer.util.LongArray;
|
||||||
import com.google.android.exoplayer.util.MimeTypes;
|
import com.google.android.exoplayer.util.MimeTypes;
|
||||||
|
import com.google.android.exoplayer.util.ParsableByteArray;
|
||||||
|
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
@ -57,14 +53,15 @@ public final class SubripParser implements SubtitleParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SubripSubtitle parse(InputStream inputStream) throws IOException {
|
public SubripSubtitle parse(byte[] bytes, int offset, int length) {
|
||||||
ArrayList<Cue> cues = new ArrayList<>();
|
ArrayList<Cue> cues = new ArrayList<>();
|
||||||
LongArray cueTimesUs = new LongArray();
|
LongArray cueTimesUs = new LongArray();
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, C.UTF8_NAME));
|
ParsableByteArray subripData = new ParsableByteArray(bytes, offset + length);
|
||||||
|
subripData.setPosition(offset);
|
||||||
boolean haveEndTimecode;
|
boolean haveEndTimecode;
|
||||||
String currentLine;
|
String currentLine;
|
||||||
|
|
||||||
while ((currentLine = reader.readLine()) != null) {
|
while ((currentLine = subripData.readLine()) != null) {
|
||||||
if (currentLine.length() == 0) {
|
if (currentLine.length() == 0) {
|
||||||
// Skip blank lines.
|
// Skip blank lines.
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -80,7 +77,7 @@ public final class SubripParser implements SubtitleParser {
|
||||||
|
|
||||||
// Read and parse the timing line.
|
// Read and parse the timing line.
|
||||||
haveEndTimecode = false;
|
haveEndTimecode = false;
|
||||||
currentLine = reader.readLine();
|
currentLine = subripData.readLine();
|
||||||
Matcher matcher = SUBRIP_TIMING_LINE.matcher(currentLine);
|
Matcher matcher = SUBRIP_TIMING_LINE.matcher(currentLine);
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
cueTimesUs.add(parseTimecode(matcher.group(1)));
|
cueTimesUs.add(parseTimecode(matcher.group(1)));
|
||||||
|
|
@ -96,7 +93,7 @@ public final class SubripParser implements SubtitleParser {
|
||||||
|
|
||||||
// Read and parse the text.
|
// Read and parse the text.
|
||||||
textBuilder.setLength(0);
|
textBuilder.setLength(0);
|
||||||
while (!TextUtils.isEmpty(currentLine = reader.readLine())) {
|
while (!TextUtils.isEmpty(currentLine = subripData.readLine())) {
|
||||||
if (textBuilder.length() > 0) {
|
if (textBuilder.length() > 0) {
|
||||||
textBuilder.append("<br>");
|
textBuilder.append("<br>");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ package com.google.android.exoplayer.text.ttml;
|
||||||
|
|
||||||
import com.google.android.exoplayer.C;
|
import com.google.android.exoplayer.C;
|
||||||
import com.google.android.exoplayer.ParserException;
|
import com.google.android.exoplayer.ParserException;
|
||||||
import com.google.android.exoplayer.text.Subtitle;
|
|
||||||
import com.google.android.exoplayer.text.SubtitleParser;
|
import com.google.android.exoplayer.text.SubtitleParser;
|
||||||
import com.google.android.exoplayer.util.MimeTypes;
|
import com.google.android.exoplayer.util.MimeTypes;
|
||||||
import com.google.android.exoplayer.util.ParserUtil;
|
import com.google.android.exoplayer.util.ParserUtil;
|
||||||
|
|
@ -30,8 +29,8 @@ import org.xmlpull.v1.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
import org.xmlpull.v1.XmlPullParserFactory;
|
import org.xmlpull.v1.XmlPullParserFactory;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
@ -97,10 +96,11 @@ public final class TtmlParser implements SubtitleParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Subtitle parse(InputStream inputStream) throws IOException {
|
public TtmlSubtitle parse(byte[] bytes, int offset, int length) throws ParserException {
|
||||||
try {
|
try {
|
||||||
XmlPullParser xmlParser = xmlParserFactory.newPullParser();
|
XmlPullParser xmlParser = xmlParserFactory.newPullParser();
|
||||||
Map<String, TtmlStyle> globalStyles = new HashMap<>();
|
Map<String, TtmlStyle> globalStyles = new HashMap<>();
|
||||||
|
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes, offset, length);
|
||||||
xmlParser.setInput(inputStream, null);
|
xmlParser.setInput(inputStream, null);
|
||||||
TtmlSubtitle ttmlSubtitle = null;
|
TtmlSubtitle ttmlSubtitle = null;
|
||||||
LinkedList<TtmlNode> nodeStack = new LinkedList<>();
|
LinkedList<TtmlNode> nodeStack = new LinkedList<>();
|
||||||
|
|
@ -150,6 +150,8 @@ public final class TtmlParser implements SubtitleParser {
|
||||||
return ttmlSubtitle;
|
return ttmlSubtitle;
|
||||||
} catch (XmlPullParserException xppe) {
|
} catch (XmlPullParserException xppe) {
|
||||||
throw new ParserException("Unable to parse source", xppe);
|
throw new ParserException("Unable to parse source", xppe);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalStateException("Unexpected error when reading input.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,6 @@ import com.google.android.exoplayer.text.Subtitle;
|
||||||
import com.google.android.exoplayer.text.SubtitleParser;
|
import com.google.android.exoplayer.text.SubtitleParser;
|
||||||
import com.google.android.exoplayer.util.MimeTypes;
|
import com.google.android.exoplayer.util.MimeTypes;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link SubtitleParser} for tx3g.
|
* A {@link SubtitleParser} for tx3g.
|
||||||
* <p>
|
* <p>
|
||||||
|
|
@ -37,9 +33,8 @@ public final class Tx3gParser implements SubtitleParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Subtitle parse(InputStream inputStream) throws IOException {
|
public Subtitle parse(byte[] bytes, int offset, int length) {
|
||||||
DataInputStream dataInputStream = new DataInputStream(inputStream);
|
String cueText = new String(bytes, offset, length);
|
||||||
String cueText = dataInputStream.readUTF();
|
|
||||||
return new Tx3gSubtitle(new Cue(cueText));
|
return new Tx3gSubtitle(new Cue(cueText));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,19 +15,16 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer.text.webvtt;
|
package com.google.android.exoplayer.text.webvtt;
|
||||||
|
|
||||||
import com.google.android.exoplayer.C;
|
import com.google.android.exoplayer.ParserException;
|
||||||
import com.google.android.exoplayer.text.Cue;
|
import com.google.android.exoplayer.text.Cue;
|
||||||
import com.google.android.exoplayer.text.SubtitleParser;
|
import com.google.android.exoplayer.text.SubtitleParser;
|
||||||
import com.google.android.exoplayer.util.MimeTypes;
|
import com.google.android.exoplayer.util.MimeTypes;
|
||||||
|
import com.google.android.exoplayer.util.ParsableByteArray;
|
||||||
|
|
||||||
import android.text.Layout.Alignment;
|
import android.text.Layout.Alignment;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
@ -59,8 +56,9 @@ public final class WebvttParser implements SubtitleParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final WebvttSubtitle parse(InputStream inputStream) throws IOException {
|
public final WebvttSubtitle parse(byte[] bytes, int offset, int length) throws ParserException {
|
||||||
BufferedReader webvttData = new BufferedReader(new InputStreamReader(inputStream, C.UTF8_NAME));
|
ParsableByteArray webvttData = new ParsableByteArray(bytes, offset + length);
|
||||||
|
webvttData.setPosition(offset);
|
||||||
|
|
||||||
// Validate the first line of the header, and skip the remainder.
|
// Validate the first line of the header, and skip the remainder.
|
||||||
WebvttParserUtil.validateWebvttHeaderLine(webvttData);
|
WebvttParserUtil.validateWebvttHeaderLine(webvttData);
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,8 @@
|
||||||
package com.google.android.exoplayer.text.webvtt;
|
package com.google.android.exoplayer.text.webvtt;
|
||||||
|
|
||||||
import com.google.android.exoplayer.ParserException;
|
import com.google.android.exoplayer.ParserException;
|
||||||
|
import com.google.android.exoplayer.util.ParsableByteArray;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
|
@ -38,9 +37,8 @@ public final class WebvttParserUtil {
|
||||||
*
|
*
|
||||||
* @param input The input from which the line should be read.
|
* @param input The input from which the line should be read.
|
||||||
* @throws ParserException If the line isn't the start of a valid WebVTT file.
|
* @throws ParserException If the line isn't the start of a valid WebVTT file.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
|
||||||
*/
|
*/
|
||||||
public static void validateWebvttHeaderLine(BufferedReader input) throws IOException {
|
public static void validateWebvttHeaderLine(ParsableByteArray input) throws ParserException {
|
||||||
String line = input.readLine();
|
String line = input.readLine();
|
||||||
if (line == null || !HEADER.matcher(line).matches()) {
|
if (line == null || !HEADER.matcher(line).matches()) {
|
||||||
throw new ParserException("Expected WEBVTT. Got " + line);
|
throw new ParserException("Expected WEBVTT. Got " + line);
|
||||||
|
|
@ -51,12 +49,11 @@ public final class WebvttParserUtil {
|
||||||
* Reads lines up to and including the next WebVTT cue header.
|
* Reads lines up to and including the next WebVTT cue header.
|
||||||
*
|
*
|
||||||
* @param input The input from which lines should be read.
|
* @param input The input from which lines should be read.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
|
||||||
* @return A {@link Matcher} for the WebVTT cue header, or null if the end of the input was
|
* @return A {@link Matcher} for the WebVTT cue header, or null if the end of the input was
|
||||||
* reached without a cue header being found. In the case that a cue header is found, groups 1,
|
* reached without a cue header being found. In the case that a cue header is found, groups 1,
|
||||||
* 2 and 3 of the returned matcher contain the start time, end time and settings list.
|
* 2 and 3 of the returned matcher contain the start time, end time and settings list.
|
||||||
*/
|
*/
|
||||||
public static Matcher findNextCueHeader(BufferedReader input) throws IOException {
|
public static Matcher findNextCueHeader(ParsableByteArray input) {
|
||||||
String line;
|
String line;
|
||||||
while ((line = input.readLine()) != null) {
|
while ((line = input.readLine()) != null) {
|
||||||
if (COMMENT.matcher(line).matches()) {
|
if (COMMENT.matcher(line).matches()) {
|
||||||
|
|
|
||||||
|
|
@ -306,4 +306,38 @@ public final class ParsableByteArray {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a line of text. A line is considered to be terminated by any one of a line feed ('\n'), a
|
||||||
|
* carriage return ('\r'), or a carriage return followed immediately by a line feed. Platform
|
||||||
|
* default's charset used.
|
||||||
|
*
|
||||||
|
* @return A String containing the contents of the line, not including any line-termination
|
||||||
|
* characters, or null if the end of the stream has been reached.
|
||||||
|
*/
|
||||||
|
public String readLine() {
|
||||||
|
if (bytesLeft() == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int lineLimit = position;
|
||||||
|
while (lineLimit < limit && data[lineLimit] != '\n' && data[lineLimit] != '\r') {
|
||||||
|
lineLimit++;
|
||||||
|
}
|
||||||
|
String line = new String(data, position, lineLimit - position);
|
||||||
|
position = lineLimit;
|
||||||
|
if (position == limit) {
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
if (data[position] == '\n') {
|
||||||
|
position++;
|
||||||
|
if (position == limit) {
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data[position] == '\r') {
|
||||||
|
position++;
|
||||||
|
}
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,4 +47,5 @@ public final class ParserUtil {
|
||||||
public static String removeNamespacePrefix(String attributeName) {
|
public static String removeNamespacePrefix(String attributeName) {
|
||||||
return attributeName.replaceFirst("^.*:", "");
|
return attributeName.replaceFirst("^.*:", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue