@Override protected Mp4WebvttSubtitle decode(byte[] bytes, int length, boolean reset) throws SubtitleDecoderException { // 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. sampleData.reset(bytes, length); List<Cue> resultingCueList = new ArrayList<>(); while (sampleData.bytesLeft() > 0) { if (sampleData.bytesLeft() < BOX_HEADER_SIZE) { throw new SubtitleDecoderException("Incomplete Mp4Webvtt Top Level box header found."); } int boxSize = sampleData.readInt(); int boxType = sampleData.readInt(); if (boxType == TYPE_vttc) { resultingCueList.add(parseVttCueBox(sampleData, builder, boxSize - BOX_HEADER_SIZE)); } else { // Peers of the VTTCueBox are still not supported and are skipped. sampleData.skipBytes(boxSize - BOX_HEADER_SIZE); } } return new Mp4WebvttSubtitle(resultingCueList); }
private static Cue parseVttCueBox(ParsableByteArray sampleData, WebvttCue.Builder builder, int remainingCueBoxBytes) throws SubtitleDecoderException { builder.reset(); while (remainingCueBoxBytes > 0) { if (remainingCueBoxBytes < BOX_HEADER_SIZE) { throw new SubtitleDecoderException("Incomplete vtt cue box header found."); } int boxSize = sampleData.readInt(); int boxType = sampleData.readInt(); remainingCueBoxBytes -= BOX_HEADER_SIZE; int payloadLength = boxSize - BOX_HEADER_SIZE; String boxPayload = new String(sampleData.data, sampleData.getPosition(), payloadLength); sampleData.skipBytes(payloadLength); remainingCueBoxBytes -= payloadLength; if (boxType == TYPE_sttg) { WebvttCueParser.parseCueSettingsList(boxPayload, builder); } else if (boxType == TYPE_payl) { WebvttCueParser.parseCueText(null, boxPayload.trim(), builder, Collections.<WebvttCssStyle>emptyList()); } else { // Other VTTCueBox children are still not supported and are ignored. } } return builder.build(); }
@Override protected Mp4WebvttSubtitle decode(byte[] bytes, int length) throws SubtitleDecoderException { // 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. sampleData.reset(bytes, length); List<Cue> resultingCueList = new ArrayList<>(); while (sampleData.bytesLeft() > 0) { if (sampleData.bytesLeft() < BOX_HEADER_SIZE) { throw new SubtitleDecoderException("Incomplete Mp4Webvtt Top Level box header found."); } int boxSize = sampleData.readInt(); int boxType = sampleData.readInt(); if (boxType == TYPE_vttc) { resultingCueList.add(parseVttCueBox(sampleData, builder, boxSize - BOX_HEADER_SIZE)); } else { // Peers of the VTTCueBox are still not supported and are skipped. sampleData.skipBytes(boxSize - BOX_HEADER_SIZE); } } return new Mp4WebvttSubtitle(resultingCueList); }
public void testDecodeWithPositioning() throws IOException, SubtitleDecoderException { WebvttSubtitle subtitle = getSubtitleForTestAsset(WITH_POSITIONING_FILE); // Test event count. assertEquals(12, subtitle.getEventTimeCount()); // Test cues. assertCue(subtitle, 0, 0, 1234000, "This is the first subtitle.", Alignment.ALIGN_NORMAL, Cue.DIMEN_UNSET, Cue.TYPE_UNSET, Cue.TYPE_UNSET, 0.1f, Cue.ANCHOR_TYPE_START, 0.35f); assertCue(subtitle, 2, 2345000, 3456000, "This is the second subtitle.", Alignment.ALIGN_OPPOSITE, Cue.DIMEN_UNSET, Cue.TYPE_UNSET, Cue.TYPE_UNSET, Cue.DIMEN_UNSET, Cue.TYPE_UNSET, 0.35f); assertCue(subtitle, 4, 4000000, 5000000, "This is the third subtitle.", Alignment.ALIGN_CENTER, 0.45f, Cue.LINE_TYPE_FRACTION, Cue.ANCHOR_TYPE_END, Cue.DIMEN_UNSET, Cue.TYPE_UNSET, 0.35f); assertCue(subtitle, 6, 6000000, 7000000, "This is the fourth subtitle.", Alignment.ALIGN_CENTER, -10f, Cue.LINE_TYPE_NUMBER, Cue.TYPE_UNSET, Cue.DIMEN_UNSET, Cue.TYPE_UNSET, Cue.DIMEN_UNSET); assertCue(subtitle, 8, 7000000, 8000000, "This is the fifth subtitle.", Alignment.ALIGN_OPPOSITE, Cue.DIMEN_UNSET, Cue.TYPE_UNSET, Cue.TYPE_UNSET, 0.1f, Cue.ANCHOR_TYPE_END, 0.1f); assertCue(subtitle, 10, 10000000, 11000000, "This is the sixth subtitle.", Alignment.ALIGN_CENTER, 0.45f, Cue.LINE_TYPE_FRACTION, Cue.ANCHOR_TYPE_END, Cue.DIMEN_UNSET, Cue.TYPE_UNSET, 0.35f); }
public void testWebvttWithCssStyle() throws IOException, SubtitleDecoderException { WebvttSubtitle subtitle = getSubtitleForTestAsset(WITH_CSS_STYLES); // Test event count. assertEquals(8, subtitle.getEventTimeCount()); // Test cues. assertCue(subtitle, 0, 0, 1234000, "This is the first subtitle."); assertCue(subtitle, 2, 2345000, 3456000, "This is the second subtitle."); Spanned s1 = getUniqueSpanTextAt(subtitle, 0); Spanned s2 = getUniqueSpanTextAt(subtitle, 2345000); Spanned s3 = getUniqueSpanTextAt(subtitle, 20000000); Spanned s4 = getUniqueSpanTextAt(subtitle, 25000000); assertEquals(1, s1.getSpans(0, s1.length(), ForegroundColorSpan.class).length); assertEquals(1, s1.getSpans(0, s1.length(), BackgroundColorSpan.class).length); assertEquals(2, s2.getSpans(0, s2.length(), ForegroundColorSpan.class).length); assertEquals(1, s3.getSpans(10, s3.length(), UnderlineSpan.class).length); assertEquals(2, s4.getSpans(0, 16, BackgroundColorSpan.class).length); assertEquals(1, s4.getSpans(17, s4.length(), StyleSpan.class).length); assertEquals(Typeface.BOLD, s4.getSpans(17, s4.length(), StyleSpan.class)[0].getStyle()); }
public void testMultipleChaining() throws IOException, SubtitleDecoderException { TtmlSubtitle subtitle = getSubtitle(CHAIN_MULTIPLE_STYLES_TTML_FILE); assertEquals(2, subtitle.getEventTimeCount()); Map<String, TtmlStyle> globalStyles = subtitle.getGlobalStyles(); TtmlStyle style = globalStyles.get("s2"); assertEquals("serif", style.getFontFamily()); assertEquals(0xFFFF0000, style.getBackgroundColor()); assertEquals(0xFF000000, style.getFontColor()); assertEquals(TtmlStyle.STYLE_BOLD_ITALIC, style.getStyle()); assertTrue(style.isLinethrough()); style = globalStyles.get("s3"); // only difference: color must be RED assertEquals(0xFFFF0000, style.getFontColor()); assertEquals("serif", style.getFontFamily()); assertEquals(0xFFFF0000, style.getBackgroundColor()); assertEquals(TtmlStyle.STYLE_BOLD_ITALIC, style.getStyle()); assertTrue(style.isLinethrough()); }
public void testDecodeWithMultipleStyl() throws IOException, SubtitleDecoderException { Tx3gDecoder decoder = new Tx3gDecoder(Collections.<byte[]>emptyList()); byte[] bytes = TestUtil.getByteArray(getInstrumentation(), SAMPLE_WITH_MULTIPLE_STYL); Subtitle subtitle = decoder.decode(bytes, bytes.length, false); SpannedString text = new SpannedString(subtitle.getCues(0).get(0).text); assertEquals("Line 2\nLine 3", text.toString()); assertEquals(4, text.getSpans(0, text.length(), Object.class).length); StyleSpan styleSpan = findSpan(text, 0, 5, StyleSpan.class); assertEquals(Typeface.ITALIC, styleSpan.getStyle()); findSpan(text, 7, 12, UnderlineSpan.class); ForegroundColorSpan colorSpan = findSpan(text, 0, 5, ForegroundColorSpan.class); assertEquals(Color.GREEN, colorSpan.getForegroundColor()); colorSpan = findSpan(text, 7, 12, ForegroundColorSpan.class); assertEquals(Color.GREEN, colorSpan.getForegroundColor()); assertFractionalLinePosition(subtitle.getCues(0).get(0), 0.85f); }
public void testInitializationDecodeWithStyl() throws IOException, SubtitleDecoderException { byte[] initBytes = TestUtil.getByteArray(getInstrumentation(), INITIALIZATION); Tx3gDecoder decoder = new Tx3gDecoder(Collections.singletonList(initBytes)); byte[] bytes = TestUtil.getByteArray(getInstrumentation(), SAMPLE_WITH_STYL); Subtitle subtitle = decoder.decode(bytes, bytes.length, false); SpannedString text = new SpannedString(subtitle.getCues(0).get(0).text); assertEquals("CC Test", text.toString()); assertEquals(5, text.getSpans(0, text.length(), Object.class).length); StyleSpan styleSpan = findSpan(text, 0, text.length(), StyleSpan.class); assertEquals(Typeface.BOLD_ITALIC, styleSpan.getStyle()); findSpan(text, 0, text.length(), UnderlineSpan.class); TypefaceSpan typefaceSpan = findSpan(text, 0, text.length(), TypefaceSpan.class); assertEquals(C.SERIF_NAME, typefaceSpan.getFamily()); ForegroundColorSpan colorSpan = findSpan(text, 0, text.length(), ForegroundColorSpan.class); assertEquals(Color.RED, colorSpan.getForegroundColor()); colorSpan = findSpan(text, 0, 6, ForegroundColorSpan.class); assertEquals(Color.GREEN, colorSpan.getForegroundColor()); assertFractionalLinePosition(subtitle.getCues(0).get(0), 0.1f); }
public void testInitializationDecodeWithTbox() throws IOException, SubtitleDecoderException { byte[] initBytes = TestUtil.getByteArray(getInstrumentation(), INITIALIZATION); Tx3gDecoder decoder = new Tx3gDecoder(Collections.singletonList(initBytes)); byte[] bytes = TestUtil.getByteArray(getInstrumentation(), SAMPLE_WITH_TBOX); Subtitle subtitle = decoder.decode(bytes, bytes.length, false); SpannedString text = new SpannedString(subtitle.getCues(0).get(0).text); assertEquals("CC Test", text.toString()); assertEquals(4, text.getSpans(0, text.length(), Object.class).length); StyleSpan styleSpan = findSpan(text, 0, text.length(), StyleSpan.class); assertEquals(Typeface.BOLD_ITALIC, styleSpan.getStyle()); findSpan(text, 0, text.length(), UnderlineSpan.class); TypefaceSpan typefaceSpan = findSpan(text, 0, text.length(), TypefaceSpan.class); assertEquals(C.SERIF_NAME, typefaceSpan.getFamily()); ForegroundColorSpan colorSpan = findSpan(text, 0, text.length(), ForegroundColorSpan.class); assertEquals(Color.RED, colorSpan.getForegroundColor()); assertFractionalLinePosition(subtitle.getCues(0).get(0), 0.1875f); }
public void testInitializationAllDefaultsDecodeWithStyl() throws IOException, SubtitleDecoderException { byte[] initBytes = TestUtil.getByteArray(getInstrumentation(), INITIALIZATION_ALL_DEFAULTS); Tx3gDecoder decoder = new Tx3gDecoder(Collections.singletonList(initBytes)); byte[] bytes = TestUtil.getByteArray(getInstrumentation(), SAMPLE_WITH_STYL); Subtitle subtitle = decoder.decode(bytes, bytes.length, false); SpannedString text = new SpannedString(subtitle.getCues(0).get(0).text); assertEquals("CC Test", text.toString()); assertEquals(3, text.getSpans(0, text.length(), Object.class).length); StyleSpan styleSpan = findSpan(text, 0, 6, StyleSpan.class); assertEquals(Typeface.BOLD_ITALIC, styleSpan.getStyle()); findSpan(text, 0, 6, UnderlineSpan.class); ForegroundColorSpan colorSpan = findSpan(text, 0, 6, ForegroundColorSpan.class); assertEquals(Color.GREEN, colorSpan.getForegroundColor()); assertFractionalLinePosition(subtitle.getCues(0).get(0), 0.85f); }
public void testDecodeWithPositioning() throws IOException, SubtitleDecoderException { WebvttSubtitle subtitle = getSubtitleForTestAsset(WITH_POSITIONING_FILE); // Test event count. assertEquals(12, subtitle.getEventTimeCount()); // Test cues. assertCue(subtitle, 0, 0, 1234000, "This is the first subtitle.", Alignment.ALIGN_NORMAL, Cue.DIMEN_UNSET, Cue.TYPE_UNSET, Cue.TYPE_UNSET, 0.1f, Cue.ANCHOR_TYPE_START, 0.35f); assertCue(subtitle, 2, 2345000, 3456000, "This is the second subtitle.", Alignment.ALIGN_OPPOSITE, Cue.DIMEN_UNSET, Cue.TYPE_UNSET, Cue.TYPE_UNSET, Cue.DIMEN_UNSET, Cue.TYPE_UNSET, 0.35f); assertCue(subtitle, 4, 4000000, 5000000, "This is the third subtitle.", Alignment.ALIGN_CENTER, 0.45f, Cue.LINE_TYPE_FRACTION, Cue.ANCHOR_TYPE_END, Cue.DIMEN_UNSET, Cue.TYPE_UNSET, 0.35f); assertCue(subtitle, 6, 6000000, 7000000, "This is the fourth subtitle.", Alignment.ALIGN_CENTER, -11f, Cue.LINE_TYPE_NUMBER, Cue.TYPE_UNSET, Cue.DIMEN_UNSET, Cue.TYPE_UNSET, Cue.DIMEN_UNSET); assertCue(subtitle, 8, 7000000, 8000000, "This is the fifth subtitle.", Alignment.ALIGN_OPPOSITE, Cue.DIMEN_UNSET, Cue.TYPE_UNSET, Cue.TYPE_UNSET, 0.1f, Cue.ANCHOR_TYPE_END, 0.1f); assertCue(subtitle, 10, 10000000, 11000000, "This is the sixth subtitle.", Alignment.ALIGN_CENTER, 0.45f, Cue.LINE_TYPE_FRACTION, Cue.ANCHOR_TYPE_END, Cue.DIMEN_UNSET, Cue.TYPE_UNSET, 0.35f); }
@Override protected Subtitle decode(byte[] bytes, int length, boolean reset) throws SubtitleDecoderException { parsableByteArray.reset(bytes, length); String cueTextString = readSubtitleText(parsableByteArray); if (cueTextString.isEmpty()) { return Tx3gSubtitle.EMPTY; } // Attach default styles. SpannableStringBuilder cueText = new SpannableStringBuilder(cueTextString); attachFontFace(cueText, defaultFontFace, DEFAULT_FONT_FACE, 0, cueText.length(), SPAN_PRIORITY_LOW); attachColor(cueText, defaultColorRgba, DEFAULT_COLOR, 0, cueText.length(), SPAN_PRIORITY_LOW); attachFontFamily(cueText, defaultFontFamily, DEFAULT_FONT_FAMILY, 0, cueText.length(), SPAN_PRIORITY_LOW); float verticalPlacement = defaultVerticalPlacement; // Find and attach additional styles. while (parsableByteArray.bytesLeft() >= SIZE_ATOM_HEADER) { int position = parsableByteArray.getPosition(); int atomSize = parsableByteArray.readInt(); int atomType = parsableByteArray.readInt(); if (atomType == TYPE_STYL) { assertTrue(parsableByteArray.bytesLeft() >= SIZE_SHORT); int styleRecordCount = parsableByteArray.readUnsignedShort(); for (int i = 0; i < styleRecordCount; i++) { applyStyleRecord(parsableByteArray, cueText); } } else if (atomType == TYPE_TBOX && customVerticalPlacement) { assertTrue(parsableByteArray.bytesLeft() >= SIZE_SHORT); int requestedVerticalPlacement = parsableByteArray.readUnsignedShort(); verticalPlacement = (float) requestedVerticalPlacement / calculatedVideoTrackHeight; verticalPlacement = Util.constrainValue(verticalPlacement, 0.0f, 0.95f); } parsableByteArray.setPosition(position + atomSize); } return new Tx3gSubtitle(new Cue(cueText, null, verticalPlacement, Cue.LINE_TYPE_FRACTION, Cue.ANCHOR_TYPE_START, Cue.DIMEN_UNSET, Cue.TYPE_UNSET, Cue.DIMEN_UNSET)); }
private static String readSubtitleText(ParsableByteArray parsableByteArray) throws SubtitleDecoderException { assertTrue(parsableByteArray.bytesLeft() >= SIZE_SHORT); int textLength = parsableByteArray.readUnsignedShort(); if (textLength == 0) { return ""; } if (parsableByteArray.bytesLeft() >= SIZE_BOM_UTF16) { char firstChar = parsableByteArray.peekChar(); if (firstChar == BOM_UTF16_BE || firstChar == BOM_UTF16_LE) { return parsableByteArray.readString(textLength, Charset.forName(C.UTF16_NAME)); } } return parsableByteArray.readString(textLength, Charset.forName(C.UTF8_NAME)); }
private void applyStyleRecord(ParsableByteArray parsableByteArray, SpannableStringBuilder cueText) throws SubtitleDecoderException { assertTrue(parsableByteArray.bytesLeft() >= SIZE_STYLE_RECORD); int start = parsableByteArray.readUnsignedShort(); int end = parsableByteArray.readUnsignedShort(); parsableByteArray.skipBytes(2); // font identifier int fontFace = parsableByteArray.readUnsignedByte(); parsableByteArray.skipBytes(1); // font size int colorRgba = parsableByteArray.readInt(); attachFontFace(cueText, fontFace, defaultFontFace, start, end, SPAN_PRIORITY_HIGH); attachColor(cueText, colorRgba, defaultColorRgba, start, end, SPAN_PRIORITY_HIGH); }
@Override protected WebvttSubtitle decode(byte[] bytes, int length, boolean reset) throws SubtitleDecoderException { parsableWebvttData.reset(bytes, length); // Initialization for consistent starting state. webvttCueBuilder.reset(); definedStyles.clear(); // Validate the first line of the header, and skip the remainder. WebvttParserUtil.validateWebvttHeaderLine(parsableWebvttData); while (!TextUtils.isEmpty(parsableWebvttData.readLine())) {} int event; ArrayList<WebvttCue> subtitles = new ArrayList<>(); while ((event = getNextEvent(parsableWebvttData)) != EVENT_END_OF_FILE) { if (event == EVENT_COMMENT) { skipComment(parsableWebvttData); } else if (event == EVENT_STYLE_BLOCK) { if (!subtitles.isEmpty()) { throw new SubtitleDecoderException("A style block was found after the first cue."); } parsableWebvttData.readLine(); // Consume the "STYLE" header. WebvttCssStyle styleBlock = cssParser.parseBlock(parsableWebvttData); if (styleBlock != null) { definedStyles.add(styleBlock); } } else if (event == EVENT_CUE) { if (cueParser.parseCue(parsableWebvttData, webvttCueBuilder, definedStyles)) { subtitles.add(webvttCueBuilder.build()); webvttCueBuilder.reset(); } } } return new WebvttSubtitle(subtitles); }
/** * Reads and validates the first line of a WebVTT file. * * @param input The input from which the line should be read. * @throws SubtitleDecoderException If the line isn't the start of a valid WebVTT file. */ public static void validateWebvttHeaderLine(ParsableByteArray input) throws SubtitleDecoderException { String line = input.readLine(); if (line == null || !HEADER.matcher(line).matches()) { throw new SubtitleDecoderException("Expected WEBVTT. Got " + line); } }
@Override public SubtitleInputBuffer dequeueInputBuffer() throws SubtitleDecoderException { Assertions.checkState(dequeuedInputBuffer == null); if (availableInputBuffers.isEmpty()) { return null; } dequeuedInputBuffer = availableInputBuffers.pollFirst(); return dequeuedInputBuffer; }
@Override public void queueInputBuffer(SubtitleInputBuffer inputBuffer) throws SubtitleDecoderException { Assertions.checkArgument(inputBuffer != null); Assertions.checkArgument(inputBuffer == dequeuedInputBuffer); if (inputBuffer.isDecodeOnly()) { // We can drop this buffer early (i.e. before it would be decoded) as the CEA formats allow // for decoding to begin mid-stream. releaseInputBuffer(inputBuffer); } else { queuedInputBuffers.add(inputBuffer); } dequeuedInputBuffer = null; }
private FrameAndTickRate parseFrameAndTickRates(XmlPullParser xmlParser) throws SubtitleDecoderException { int frameRate = DEFAULT_FRAME_RATE; String frameRateString = xmlParser.getAttributeValue(TTP, "frameRate"); if (frameRateString != null) { frameRate = Integer.parseInt(frameRateString); } float frameRateMultiplier = 1; String frameRateMultiplierString = xmlParser.getAttributeValue(TTP, "frameRateMultiplier"); if (frameRateMultiplierString != null) { String[] parts = frameRateMultiplierString.split(" "); if (parts.length != 2) { throw new SubtitleDecoderException("frameRateMultiplier doesn't have 2 parts"); } float numerator = Integer.parseInt(parts[0]); float denominator = Integer.parseInt(parts[1]); frameRateMultiplier = numerator / denominator; } int subFrameRate = DEFAULT_FRAME_AND_TICK_RATE.subFrameRate; String subFrameRateString = xmlParser.getAttributeValue(TTP, "subFrameRate"); if (subFrameRateString != null) { subFrameRate = Integer.parseInt(subFrameRateString); } int tickRate = DEFAULT_FRAME_AND_TICK_RATE.tickRate; String tickRateString = xmlParser.getAttributeValue(TTP, "tickRate"); if (tickRateString != null) { tickRate = Integer.parseInt(tickRateString); } return new FrameAndTickRate(frameRate * frameRateMultiplier, subFrameRate, tickRate); }
private static void parseFontSize(String expression, TtmlStyle out) throws SubtitleDecoderException { String[] expressions = expression.split("\\s+"); Matcher matcher; if (expressions.length == 1) { matcher = FONT_SIZE.matcher(expression); } else if (expressions.length == 2){ matcher = FONT_SIZE.matcher(expressions[1]); Log.w(TAG, "Multiple values in fontSize attribute. Picking the second value for vertical font" + " size and ignoring the first."); } else { throw new SubtitleDecoderException("Invalid number of entries for fontSize: " + expressions.length + "."); } if (matcher.matches()) { String unit = matcher.group(3); switch (unit) { case "px": out.setFontSizeUnit(TtmlStyle.FONT_SIZE_UNIT_PIXEL); break; case "em": out.setFontSizeUnit(TtmlStyle.FONT_SIZE_UNIT_EM); break; case "%": out.setFontSizeUnit(TtmlStyle.FONT_SIZE_UNIT_PERCENT); break; default: throw new SubtitleDecoderException("Invalid unit for fontSize: '" + unit + "'."); } out.setFontSize(Float.valueOf(matcher.group(1))); } else { throw new SubtitleDecoderException("Invalid expression for fontSize: '" + expression + "'."); } }
@Override protected WebvttSubtitle decode(byte[] bytes, int length) throws SubtitleDecoderException { parsableWebvttData.reset(bytes, length); // Initialization for consistent starting state. webvttCueBuilder.reset(); definedStyles.clear(); // Validate the first line of the header, and skip the remainder. WebvttParserUtil.validateWebvttHeaderLine(parsableWebvttData); while (!TextUtils.isEmpty(parsableWebvttData.readLine())) {} int event; ArrayList<WebvttCue> subtitles = new ArrayList<>(); while ((event = getNextEvent(parsableWebvttData)) != EVENT_END_OF_FILE) { if (event == EVENT_COMMENT) { skipComment(parsableWebvttData); } else if (event == EVENT_STYLE_BLOCK) { if (!subtitles.isEmpty()) { throw new SubtitleDecoderException("A style block was found after the first cue."); } parsableWebvttData.readLine(); // Consume the "STYLE" header. WebvttCssStyle styleBlock = cssParser.parseBlock(parsableWebvttData); if (styleBlock != null) { definedStyles.add(styleBlock); } } else if (event == EVENT_CUE) { if (cueParser.parseCue(parsableWebvttData, webvttCueBuilder, definedStyles)) { subtitles.add(webvttCueBuilder.build()); webvttCueBuilder.reset(); } } } return new WebvttSubtitle(subtitles); }
@Override public void queueInputBuffer(SubtitleInputBuffer inputBuffer) throws SubtitleDecoderException { Assertions.checkArgument(inputBuffer != null); Assertions.checkArgument(inputBuffer == dequeuedInputBuffer); queuedInputBuffers.add(inputBuffer); dequeuedInputBuffer = null; }
public void testDecodeEmpty() throws IOException { WebvttDecoder decoder = new WebvttDecoder(); byte[] bytes = TestUtil.getByteArray(getInstrumentation(), EMPTY_FILE); try { decoder.decode(bytes, bytes.length); fail(); } catch (SubtitleDecoderException expected) { // Do nothing. } }