Consistent Javadoc for text package

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=128160177
This commit is contained in:
olly 2016-07-22 03:57:19 -07:00 committed by Oliver Woodman
parent f0b73e5d5b
commit ba0a4235a0
35 changed files with 223 additions and 167 deletions

View File

@ -47,7 +47,7 @@ import com.google.android.exoplayer2.source.smoothstreaming.DefaultSsChunkSource
import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource; import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource;
import com.google.android.exoplayer2.text.CaptionStyleCompat; import com.google.android.exoplayer2.text.CaptionStyleCompat;
import com.google.android.exoplayer2.text.Cue; import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.SubtitleLayout; import com.google.android.exoplayer2.ui.SubtitleView;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector; import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.TrackInfo; import com.google.android.exoplayer2.trackselection.MappingTrackSelector.TrackInfo;
@ -131,7 +131,7 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
private AspectRatioFrameLayout videoFrame; private AspectRatioFrameLayout videoFrame;
private SurfaceView surfaceView; private SurfaceView surfaceView;
private TextView debugTextView; private TextView debugTextView;
private SubtitleLayout subtitleLayout; private SubtitleView subtitleView;
private Button retryButton; private Button retryButton;
private String userAgent; private String userAgent;
@ -187,7 +187,7 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
surfaceView = (SurfaceView) findViewById(R.id.surface_view); surfaceView = (SurfaceView) findViewById(R.id.surface_view);
surfaceView.getHolder().addCallback(this); surfaceView.getHolder().addCallback(this);
debugTextView = (TextView) findViewById(R.id.debug_text_view); debugTextView = (TextView) findViewById(R.id.debug_text_view);
subtitleLayout = (SubtitleLayout) findViewById(R.id.subtitles); subtitleView = (SubtitleView) findViewById(R.id.subtitles);
mediaController = new KeyCompatibleMediaController(this); mediaController = new KeyCompatibleMediaController(this);
retryButton = (Button) findViewById(R.id.retry_button); retryButton = (Button) findViewById(R.id.retry_button);
retryButton.setOnClickListener(this); retryButton.setOnClickListener(this);
@ -582,7 +582,7 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
@Override @Override
public void onCues(List<Cue> cues) { public void onCues(List<Cue> cues) {
subtitleLayout.setCues(cues); subtitleView.setCues(cues);
} }
// SimpleExoPlayer.MetadataListener implementation // SimpleExoPlayer.MetadataListener implementation
@ -646,8 +646,8 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
style = CaptionStyleCompat.DEFAULT; style = CaptionStyleCompat.DEFAULT;
fontScale = 1.0f; fontScale = 1.0f;
} }
subtitleLayout.setStyle(style); subtitleView.setStyle(style);
subtitleLayout.setFractionalTextSize(SubtitleLayout.DEFAULT_TEXT_SIZE_FRACTION * fontScale); subtitleView.setFractionalTextSize(SubtitleView.DEFAULT_TEXT_SIZE_FRACTION * fontScale);
} }
@TargetApi(19) @TargetApi(19)

View File

@ -37,7 +37,8 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@android:color/black"/> android:background="@android:color/black"/>
<com.google.android.exoplayer2.text.SubtitleLayout android:id="@+id/subtitles" <com.google.android.exoplayer2.ui.SubtitleView
android:id="@+id/subtitles"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"/> android:layout_height="match_parent"/>

View File

@ -216,9 +216,9 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
// Drop the frame if we're joining and are more than 30ms late, or if we have the next frame // Drop the frame if we're joining and are more than 30ms late, or if we have the next frame
// and that's also late. Else we'll render what we have. // and that's also late. Else we'll render what we have.
if ((joiningDeadlineMs != -1 && outputBuffer.timestampUs < positionUs - 30000) if ((joiningDeadlineMs != -1 && outputBuffer.timeUs < positionUs - 30000)
|| (nextOutputBuffer != null && !nextOutputBuffer.isEndOfStream() || (nextOutputBuffer != null && !nextOutputBuffer.isEndOfStream()
&& nextOutputBuffer.timestampUs < positionUs)) { && nextOutputBuffer.timeUs < positionUs)) {
decoderCounters.droppedOutputBufferCount++; decoderCounters.droppedOutputBufferCount++;
droppedFrameCount++; droppedFrameCount++;
consecutiveDroppedFrameCount++; consecutiveDroppedFrameCount++;
@ -241,7 +241,7 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
return false; return false;
} }
if (getState() == STATE_STARTED && outputBuffer.timestampUs <= positionUs + 30000) { if (getState() == STATE_STARTED && outputBuffer.timeUs <= positionUs + 30000) {
renderBuffer(); renderBuffer();
} }
return false; return false;

View File

@ -56,12 +56,12 @@ import java.nio.ByteBuffer;
/** /**
* Initializes the buffer. * Initializes the buffer.
* *
* @param timestampUs The presentation timestamp for the buffer, in microseconds. * @param timeUs The presentation timestamp for the buffer, in microseconds.
* @param mode The output mode. One of {@link VpxDecoder#OUTPUT_MODE_NONE}, * @param mode The output mode. One of {@link VpxDecoder#OUTPUT_MODE_NONE},
* {@link VpxDecoder#OUTPUT_MODE_RGB} and {@link VpxDecoder#OUTPUT_MODE_YUV}. * {@link VpxDecoder#OUTPUT_MODE_RGB} and {@link VpxDecoder#OUTPUT_MODE_YUV}.
*/ */
public void init(long timestampUs, int mode) { public void init(long timeUs, int mode) {
this.timestampUs = timestampUs; this.timeUs = timeUs;
this.mode = mode; this.mode = mode;
} }

View File

@ -17,7 +17,7 @@ package com.google.android.exoplayer2.text.ttml;
import com.google.android.exoplayer2.testutil.TestUtil; import com.google.android.exoplayer2.testutil.TestUtil;
import com.google.android.exoplayer2.text.Cue; import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.TextDecoderException; import com.google.android.exoplayer2.text.SubtitleDecoderException;
import com.google.android.exoplayer2.util.ColorParser; import com.google.android.exoplayer2.util.ColorParser;
import android.test.InstrumentationTestCase; import android.test.InstrumentationTestCase;
@ -61,7 +61,7 @@ public final class TtmlDecoderTest extends InstrumentationTestCase {
private static final String FONT_SIZE_EMPTY_TTML_FILE = "ttml/font_size_empty.xml"; private static final String FONT_SIZE_EMPTY_TTML_FILE = "ttml/font_size_empty.xml";
private static final String FRAME_RATE_TTML_FILE = "ttml/frame_rate.xml"; private static final String FRAME_RATE_TTML_FILE = "ttml/frame_rate.xml";
public void testInlineAttributes() throws IOException, TextDecoderException { public void testInlineAttributes() throws IOException, SubtitleDecoderException {
TtmlSubtitle subtitle = getSubtitle(INLINE_ATTRIBUTES_TTML_FILE); TtmlSubtitle subtitle = getSubtitle(INLINE_ATTRIBUTES_TTML_FILE);
assertEquals(4, subtitle.getEventTimeCount()); assertEquals(4, subtitle.getEventTimeCount());
@ -77,7 +77,7 @@ public final class TtmlDecoderTest extends InstrumentationTestCase {
assertTrue(firstPStyle.isUnderline()); assertTrue(firstPStyle.isUnderline());
} }
public void testInheritInlineAttributes() throws IOException, TextDecoderException { public void testInheritInlineAttributes() throws IOException, SubtitleDecoderException {
TtmlSubtitle subtitle = getSubtitle(INLINE_ATTRIBUTES_TTML_FILE); TtmlSubtitle subtitle = getSubtitle(INLINE_ATTRIBUTES_TTML_FILE);
assertEquals(4, subtitle.getEventTimeCount()); assertEquals(4, subtitle.getEventTimeCount());
assertSpans(subtitle, 20, "text 2", "sansSerif", TtmlStyle.STYLE_ITALIC, assertSpans(subtitle, 20, "text 2", "sansSerif", TtmlStyle.STYLE_ITALIC,
@ -95,14 +95,14 @@ public final class TtmlDecoderTest extends InstrumentationTestCase {
* Kitkat Color</a> * Kitkat Color</a>
* @throws IOException thrown if reading subtitle file fails. * @throws IOException thrown if reading subtitle file fails.
*/ */
public void testLime() throws IOException, TextDecoderException { public void testLime() throws IOException, SubtitleDecoderException {
TtmlSubtitle subtitle = getSubtitle(INLINE_ATTRIBUTES_TTML_FILE); TtmlSubtitle subtitle = getSubtitle(INLINE_ATTRIBUTES_TTML_FILE);
assertEquals(4, subtitle.getEventTimeCount()); assertEquals(4, subtitle.getEventTimeCount());
assertSpans(subtitle, 20, "text 2", "sansSerif", TtmlStyle.STYLE_ITALIC, 0xFF00FFFF, 0xFF00FF00, assertSpans(subtitle, 20, "text 2", "sansSerif", TtmlStyle.STYLE_ITALIC, 0xFF00FFFF, 0xFF00FF00,
false, true, null); false, true, null);
} }
public void testInheritGlobalStyle() throws IOException, TextDecoderException { public void testInheritGlobalStyle() throws IOException, SubtitleDecoderException {
TtmlSubtitle subtitle = getSubtitle(INHERIT_STYLE_TTML_FILE); TtmlSubtitle subtitle = getSubtitle(INHERIT_STYLE_TTML_FILE);
assertEquals(2, subtitle.getEventTimeCount()); assertEquals(2, subtitle.getEventTimeCount());
assertSpans(subtitle, 10, "text 1", "serif", TtmlStyle.STYLE_BOLD_ITALIC, 0xFF0000FF, assertSpans(subtitle, 10, "text 1", "serif", TtmlStyle.STYLE_BOLD_ITALIC, 0xFF0000FF,
@ -110,7 +110,7 @@ public final class TtmlDecoderTest extends InstrumentationTestCase {
} }
public void testInheritGlobalStyleOverriddenByInlineAttributes() throws IOException, public void testInheritGlobalStyleOverriddenByInlineAttributes() throws IOException,
TextDecoderException { SubtitleDecoderException {
TtmlSubtitle subtitle = getSubtitle(INHERIT_STYLE_OVERRIDE_TTML_FILE); TtmlSubtitle subtitle = getSubtitle(INHERIT_STYLE_OVERRIDE_TTML_FILE);
assertEquals(4, subtitle.getEventTimeCount()); assertEquals(4, subtitle.getEventTimeCount());
@ -120,7 +120,7 @@ public final class TtmlDecoderTest extends InstrumentationTestCase {
true, false, null); true, false, null);
} }
public void testInheritGlobalAndParent() throws IOException, TextDecoderException { public void testInheritGlobalAndParent() throws IOException, SubtitleDecoderException {
TtmlSubtitle subtitle = getSubtitle(INHERIT_GLOBAL_AND_PARENT_TTML_FILE); TtmlSubtitle subtitle = getSubtitle(INHERIT_GLOBAL_AND_PARENT_TTML_FILE);
assertEquals(4, subtitle.getEventTimeCount()); assertEquals(4, subtitle.getEventTimeCount());
@ -130,7 +130,7 @@ public final class TtmlDecoderTest extends InstrumentationTestCase {
0xFFFFFF00, true, true, Layout.Alignment.ALIGN_CENTER); 0xFFFFFF00, true, true, Layout.Alignment.ALIGN_CENTER);
} }
public void testInheritMultipleStyles() throws IOException, TextDecoderException { public void testInheritMultipleStyles() throws IOException, SubtitleDecoderException {
TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE); TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE);
assertEquals(12, subtitle.getEventTimeCount()); assertEquals(12, subtitle.getEventTimeCount());
assertSpans(subtitle, 10, "text 1", "sansSerif", TtmlStyle.STYLE_BOLD_ITALIC, 0xFF0000FF, assertSpans(subtitle, 10, "text 1", "sansSerif", TtmlStyle.STYLE_BOLD_ITALIC, 0xFF0000FF,
@ -138,21 +138,22 @@ public final class TtmlDecoderTest extends InstrumentationTestCase {
} }
public void testInheritMultipleStylesWithoutLocalAttributes() throws IOException, public void testInheritMultipleStylesWithoutLocalAttributes() throws IOException,
TextDecoderException { SubtitleDecoderException {
TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE); TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE);
assertEquals(12, subtitle.getEventTimeCount()); assertEquals(12, subtitle.getEventTimeCount());
assertSpans(subtitle, 20, "text 2", "sansSerif", TtmlStyle.STYLE_BOLD_ITALIC, 0xFF0000FF, assertSpans(subtitle, 20, "text 2", "sansSerif", TtmlStyle.STYLE_BOLD_ITALIC, 0xFF0000FF,
0xFF000000, false, true, null); 0xFF000000, false, true, null);
} }
public void testMergeMultipleStylesWithParentStyle() throws IOException, TextDecoderException { public void testMergeMultipleStylesWithParentStyle() throws IOException,
SubtitleDecoderException {
TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE); TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE);
assertEquals(12, subtitle.getEventTimeCount()); assertEquals(12, subtitle.getEventTimeCount());
assertSpans(subtitle, 30, "text 2.5", "sansSerifInline", TtmlStyle.STYLE_ITALIC, 0xFFFF0000, assertSpans(subtitle, 30, "text 2.5", "sansSerifInline", TtmlStyle.STYLE_ITALIC, 0xFFFF0000,
0xFFFFFF00, true, true, null); 0xFFFFFF00, true, true, null);
} }
public void testMultipleRegions() throws IOException, TextDecoderException { public void testMultipleRegions() throws IOException, SubtitleDecoderException {
TtmlSubtitle subtitle = getSubtitle(MULTIPLE_REGIONS_TTML_FILE); TtmlSubtitle subtitle = getSubtitle(MULTIPLE_REGIONS_TTML_FILE);
List<Cue> output = subtitle.getCues(1000000); List<Cue> output = subtitle.getCues(1000000);
assertEquals(2, output.size()); assertEquals(2, output.size());
@ -202,7 +203,7 @@ public final class TtmlDecoderTest extends InstrumentationTestCase {
assertEquals(45.f / 100.f, ttmlCue.line); assertEquals(45.f / 100.f, ttmlCue.line);
} }
public void testEmptyStyleAttribute() throws IOException, TextDecoderException { public void testEmptyStyleAttribute() throws IOException, SubtitleDecoderException {
TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE); TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE);
assertEquals(12, subtitle.getEventTimeCount()); assertEquals(12, subtitle.getEventTimeCount());
@ -213,7 +214,7 @@ public final class TtmlDecoderTest extends InstrumentationTestCase {
assertNull(queryChildrenForTag(fourthDiv, TtmlNode.TAG_P, 0).getStyleIds()); assertNull(queryChildrenForTag(fourthDiv, TtmlNode.TAG_P, 0).getStyleIds());
} }
public void testNonexistingStyleId() throws IOException, TextDecoderException { public void testNonexistingStyleId() throws IOException, SubtitleDecoderException {
TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE); TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE);
assertEquals(12, subtitle.getEventTimeCount()); assertEquals(12, subtitle.getEventTimeCount());
@ -225,7 +226,7 @@ public final class TtmlDecoderTest extends InstrumentationTestCase {
} }
public void testNonExistingAndExistingStyleIdWithRedundantSpaces() throws IOException, public void testNonExistingAndExistingStyleIdWithRedundantSpaces() throws IOException,
TextDecoderException { SubtitleDecoderException {
TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE); TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE);
assertEquals(12, subtitle.getEventTimeCount()); assertEquals(12, subtitle.getEventTimeCount());
@ -237,7 +238,7 @@ public final class TtmlDecoderTest extends InstrumentationTestCase {
assertEquals(2, styleIds.length); assertEquals(2, styleIds.length);
} }
public void testMultipleChaining() throws IOException, TextDecoderException { public void testMultipleChaining() throws IOException, SubtitleDecoderException {
TtmlSubtitle subtitle = getSubtitle(CHAIN_MULTIPLE_STYLES_TTML_FILE); TtmlSubtitle subtitle = getSubtitle(CHAIN_MULTIPLE_STYLES_TTML_FILE);
assertEquals(2, subtitle.getEventTimeCount()); assertEquals(2, subtitle.getEventTimeCount());
@ -259,7 +260,7 @@ public final class TtmlDecoderTest extends InstrumentationTestCase {
assertTrue(style.isLinethrough()); assertTrue(style.isLinethrough());
} }
public void testNoUnderline() throws IOException, TextDecoderException { public void testNoUnderline() throws IOException, SubtitleDecoderException {
TtmlSubtitle subtitle = getSubtitle(NO_UNDERLINE_LINETHROUGH_TTML_FILE); TtmlSubtitle subtitle = getSubtitle(NO_UNDERLINE_LINETHROUGH_TTML_FILE);
assertEquals(4, subtitle.getEventTimeCount()); assertEquals(4, subtitle.getEventTimeCount());
@ -271,7 +272,7 @@ public final class TtmlDecoderTest extends InstrumentationTestCase {
assertFalse("noUnderline from inline attribute expected", style.isUnderline()); assertFalse("noUnderline from inline attribute expected", style.isUnderline());
} }
public void testNoLinethrough() throws IOException, TextDecoderException { public void testNoLinethrough() throws IOException, SubtitleDecoderException {
TtmlSubtitle subtitle = getSubtitle(NO_UNDERLINE_LINETHROUGH_TTML_FILE); TtmlSubtitle subtitle = getSubtitle(NO_UNDERLINE_LINETHROUGH_TTML_FILE);
assertEquals(4, subtitle.getEventTimeCount()); assertEquals(4, subtitle.getEventTimeCount());
@ -284,7 +285,7 @@ public final class TtmlDecoderTest extends InstrumentationTestCase {
style.isLinethrough()); style.isLinethrough());
} }
public void testFontSizeSpans() throws IOException, TextDecoderException { public void testFontSizeSpans() throws IOException, SubtitleDecoderException {
TtmlSubtitle subtitle = getSubtitle(FONT_SIZE_TTML_FILE); TtmlSubtitle subtitle = getSubtitle(FONT_SIZE_TTML_FILE);
assertEquals(10, subtitle.getEventTimeCount()); assertEquals(10, subtitle.getEventTimeCount());
@ -319,7 +320,7 @@ public final class TtmlDecoderTest extends InstrumentationTestCase {
assertRelativeFontSize(spannable, 0.5f); assertRelativeFontSize(spannable, 0.5f);
} }
public void testFontSizeWithMissingUnitIsIgnored() throws IOException, TextDecoderException { public void testFontSizeWithMissingUnitIsIgnored() throws IOException, SubtitleDecoderException {
TtmlSubtitle subtitle = getSubtitle(FONT_SIZE_MISSING_UNIT_TTML_FILE); TtmlSubtitle subtitle = getSubtitle(FONT_SIZE_MISSING_UNIT_TTML_FILE);
assertEquals(2, subtitle.getEventTimeCount()); assertEquals(2, subtitle.getEventTimeCount());
List<Cue> cues = subtitle.getCues(10 * 1000000); List<Cue> cues = subtitle.getCues(10 * 1000000);
@ -330,7 +331,7 @@ public final class TtmlDecoderTest extends InstrumentationTestCase {
assertEquals(0, spannable.getSpans(0, spannable.length(), AbsoluteSizeSpan.class).length); assertEquals(0, spannable.getSpans(0, spannable.length(), AbsoluteSizeSpan.class).length);
} }
public void testFontSizeWithInvalidValueIsIgnored() throws IOException, TextDecoderException { public void testFontSizeWithInvalidValueIsIgnored() throws IOException, SubtitleDecoderException {
TtmlSubtitle subtitle = getSubtitle(FONT_SIZE_INVALID_TTML_FILE); TtmlSubtitle subtitle = getSubtitle(FONT_SIZE_INVALID_TTML_FILE);
assertEquals(6, subtitle.getEventTimeCount()); assertEquals(6, subtitle.getEventTimeCount());
@ -358,7 +359,7 @@ public final class TtmlDecoderTest extends InstrumentationTestCase {
assertEquals(0, spannable.getSpans(0, spannable.length(), AbsoluteSizeSpan.class).length); assertEquals(0, spannable.getSpans(0, spannable.length(), AbsoluteSizeSpan.class).length);
} }
public void testFontSizeWithEmptyValueIsIgnored() throws IOException, TextDecoderException { public void testFontSizeWithEmptyValueIsIgnored() throws IOException, SubtitleDecoderException {
TtmlSubtitle subtitle = getSubtitle(FONT_SIZE_EMPTY_TTML_FILE); TtmlSubtitle subtitle = getSubtitle(FONT_SIZE_EMPTY_TTML_FILE);
assertEquals(2, subtitle.getEventTimeCount()); assertEquals(2, subtitle.getEventTimeCount());
List<Cue> cues = subtitle.getCues(10 * 1000000); List<Cue> cues = subtitle.getCues(10 * 1000000);
@ -369,7 +370,7 @@ public final class TtmlDecoderTest extends InstrumentationTestCase {
assertEquals(0, spannable.getSpans(0, spannable.length(), AbsoluteSizeSpan.class).length); assertEquals(0, spannable.getSpans(0, spannable.length(), AbsoluteSizeSpan.class).length);
} }
public void testFrameRate() throws IOException, TextDecoderException { public void testFrameRate() throws IOException, SubtitleDecoderException {
TtmlSubtitle subtitle = getSubtitle(FRAME_RATE_TTML_FILE); TtmlSubtitle subtitle = getSubtitle(FRAME_RATE_TTML_FILE);
assertEquals(4, subtitle.getEventTimeCount()); assertEquals(4, subtitle.getEventTimeCount());
assertEquals(1_000_000, subtitle.getEventTime(0)); assertEquals(1_000_000, subtitle.getEventTime(0));
@ -480,7 +481,7 @@ public final class TtmlDecoderTest extends InstrumentationTestCase {
throw new IllegalStateException("tag not found"); throw new IllegalStateException("tag not found");
} }
private TtmlSubtitle getSubtitle(String file) throws IOException, TextDecoderException { private TtmlSubtitle getSubtitle(String file) throws IOException, SubtitleDecoderException {
TtmlDecoder ttmlDecoder = new TtmlDecoder(); TtmlDecoder ttmlDecoder = new TtmlDecoder();
byte[] bytes = TestUtil.getByteArray(getInstrumentation(), file); byte[] bytes = TestUtil.getByteArray(getInstrumentation(), file);
return ttmlDecoder.decode(bytes, bytes.length); return ttmlDecoder.decode(bytes, bytes.length);

View File

@ -17,7 +17,7 @@ package com.google.android.exoplayer2.text.webvtt;
import com.google.android.exoplayer2.text.Cue; import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.Subtitle; import com.google.android.exoplayer2.text.Subtitle;
import com.google.android.exoplayer2.text.TextDecoderException; import com.google.android.exoplayer2.text.SubtitleDecoderException;
import junit.framework.TestCase; import junit.framework.TestCase;
@ -81,14 +81,14 @@ public final class Mp4WebvttDecoderTest extends TestCase {
// Positive tests. // Positive tests.
public void testSingleCueSample() throws TextDecoderException { public void testSingleCueSample() throws SubtitleDecoderException {
Mp4WebvttDecoder decoder = new Mp4WebvttDecoder(); Mp4WebvttDecoder decoder = new Mp4WebvttDecoder();
Subtitle result = decoder.decode(SINGLE_CUE_SAMPLE, SINGLE_CUE_SAMPLE.length); Subtitle result = decoder.decode(SINGLE_CUE_SAMPLE, SINGLE_CUE_SAMPLE.length);
Cue expectedCue = new Cue("Hello World"); // Line feed must be trimmed by the decoder Cue expectedCue = new Cue("Hello World"); // Line feed must be trimmed by the decoder
assertMp4WebvttSubtitleEquals(result, expectedCue); assertMp4WebvttSubtitleEquals(result, expectedCue);
} }
public void testTwoCuesSample() throws TextDecoderException { public void testTwoCuesSample() throws SubtitleDecoderException {
Mp4WebvttDecoder decoder = new Mp4WebvttDecoder(); Mp4WebvttDecoder decoder = new Mp4WebvttDecoder();
Subtitle result = decoder.decode(DOUBLE_CUE_SAMPLE, DOUBLE_CUE_SAMPLE.length); Subtitle result = decoder.decode(DOUBLE_CUE_SAMPLE, DOUBLE_CUE_SAMPLE.length);
Cue firstExpectedCue = new Cue("Hello World"); Cue firstExpectedCue = new Cue("Hello World");
@ -96,7 +96,7 @@ public final class Mp4WebvttDecoderTest extends TestCase {
assertMp4WebvttSubtitleEquals(result, firstExpectedCue, secondExpectedCue); assertMp4WebvttSubtitleEquals(result, firstExpectedCue, secondExpectedCue);
} }
public void testNoCueSample() throws TextDecoderException { public void testNoCueSample() throws SubtitleDecoderException {
Mp4WebvttDecoder decoder = new Mp4WebvttDecoder(); Mp4WebvttDecoder decoder = new Mp4WebvttDecoder();
Subtitle result = decoder.decode(NO_CUE_SAMPLE, NO_CUE_SAMPLE.length); Subtitle result = decoder.decode(NO_CUE_SAMPLE, NO_CUE_SAMPLE.length);
assertMp4WebvttSubtitleEquals(result, new Cue[0]); assertMp4WebvttSubtitleEquals(result, new Cue[0]);
@ -108,7 +108,7 @@ public final class Mp4WebvttDecoderTest extends TestCase {
Mp4WebvttDecoder decoder = new Mp4WebvttDecoder(); Mp4WebvttDecoder decoder = new Mp4WebvttDecoder();
try { try {
decoder.decode(INCOMPLETE_HEADER_SAMPLE, INCOMPLETE_HEADER_SAMPLE.length); decoder.decode(INCOMPLETE_HEADER_SAMPLE, INCOMPLETE_HEADER_SAMPLE.length);
} catch (TextDecoderException e) { } catch (SubtitleDecoderException e) {
return; return;
} }
fail(); fail();

View File

@ -17,7 +17,7 @@ package com.google.android.exoplayer2.text.webvtt;
import com.google.android.exoplayer2.testutil.TestUtil; import com.google.android.exoplayer2.testutil.TestUtil;
import com.google.android.exoplayer2.text.Cue; import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.TextDecoderException; import com.google.android.exoplayer2.text.SubtitleDecoderException;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.test.InstrumentationTestCase; import android.test.InstrumentationTestCase;
@ -53,12 +53,12 @@ public class WebvttDecoderTest extends InstrumentationTestCase {
try { try {
decoder.decode(bytes, bytes.length); decoder.decode(bytes, bytes.length);
fail(); fail();
} catch (TextDecoderException expected) { } catch (SubtitleDecoderException expected) {
// Do nothing. // Do nothing.
} }
} }
public void testDecodeTypical() throws IOException, TextDecoderException { public void testDecodeTypical() throws IOException, SubtitleDecoderException {
WebvttSubtitle subtitle = getSubtitleForTestAsset(TYPICAL_FILE); WebvttSubtitle subtitle = getSubtitleForTestAsset(TYPICAL_FILE);
// Test event count. // Test event count.
@ -69,7 +69,7 @@ public class WebvttDecoderTest extends InstrumentationTestCase {
assertCue(subtitle, 2, 2345000, 3456000, "This is the second subtitle."); assertCue(subtitle, 2, 2345000, 3456000, "This is the second subtitle.");
} }
public void testDecodeTypicalWithIds() throws IOException, TextDecoderException { public void testDecodeTypicalWithIds() throws IOException, SubtitleDecoderException {
WebvttSubtitle subtitle = getSubtitleForTestAsset(TYPICAL_WITH_IDS_FILE); WebvttSubtitle subtitle = getSubtitleForTestAsset(TYPICAL_WITH_IDS_FILE);
// Test event count. // Test event count.
@ -80,7 +80,7 @@ public class WebvttDecoderTest extends InstrumentationTestCase {
assertCue(subtitle, 2, 2345000, 3456000, "This is the second subtitle."); assertCue(subtitle, 2, 2345000, 3456000, "This is the second subtitle.");
} }
public void testDecodeTypicalWithComments() throws IOException, TextDecoderException { public void testDecodeTypicalWithComments() throws IOException, SubtitleDecoderException {
WebvttSubtitle subtitle = getSubtitleForTestAsset(TYPICAL_WITH_COMMENTS_FILE); WebvttSubtitle subtitle = getSubtitleForTestAsset(TYPICAL_WITH_COMMENTS_FILE);
// test event count // test event count
@ -91,7 +91,7 @@ public class WebvttDecoderTest extends InstrumentationTestCase {
assertCue(subtitle, 2, 2345000, 3456000, "This is the second subtitle."); assertCue(subtitle, 2, 2345000, 3456000, "This is the second subtitle.");
} }
public void testDecodeWithTags() throws IOException, TextDecoderException { public void testDecodeWithTags() throws IOException, SubtitleDecoderException {
WebvttSubtitle subtitle = getSubtitleForTestAsset(WITH_TAGS_FILE); WebvttSubtitle subtitle = getSubtitleForTestAsset(WITH_TAGS_FILE);
// Test event count. // Test event count.
@ -104,7 +104,7 @@ public class WebvttDecoderTest extends InstrumentationTestCase {
assertCue(subtitle, 6, 6000000, 7000000, "This is the <fourth> &subtitle."); assertCue(subtitle, 6, 6000000, 7000000, "This is the <fourth> &subtitle.");
} }
public void testDecodeWithPositioning() throws IOException, TextDecoderException { public void testDecodeWithPositioning() throws IOException, SubtitleDecoderException {
WebvttSubtitle subtitle = getSubtitleForTestAsset(WITH_POSITIONING_FILE); WebvttSubtitle subtitle = getSubtitleForTestAsset(WITH_POSITIONING_FILE);
// Test event count. // Test event count.
assertEquals(12, subtitle.getEventTimeCount()); assertEquals(12, subtitle.getEventTimeCount());
@ -128,7 +128,7 @@ public class WebvttDecoderTest extends InstrumentationTestCase {
Cue.TYPE_UNSET, 0.35f); Cue.TYPE_UNSET, 0.35f);
} }
public void testDecodeWithBadCueHeader() throws IOException, TextDecoderException { public void testDecodeWithBadCueHeader() throws IOException, SubtitleDecoderException {
WebvttSubtitle subtitle = getSubtitleForTestAsset(WITH_BAD_CUE_HEADER_FILE); WebvttSubtitle subtitle = getSubtitleForTestAsset(WITH_BAD_CUE_HEADER_FILE);
// Test event count. // Test event count.
@ -139,7 +139,7 @@ public class WebvttDecoderTest extends InstrumentationTestCase {
assertCue(subtitle, 2, 4000000, 5000000, "This is the third subtitle."); assertCue(subtitle, 2, 4000000, 5000000, "This is the third subtitle.");
} }
public void testWebvttWithCssStyle() throws IOException, TextDecoderException { public void testWebvttWithCssStyle() throws IOException, SubtitleDecoderException {
WebvttSubtitle subtitle = getSubtitleForTestAsset(WITH_CSS_STYLES); WebvttSubtitle subtitle = getSubtitleForTestAsset(WITH_CSS_STYLES);
// Test event count. // Test event count.
@ -162,7 +162,7 @@ public class WebvttDecoderTest extends InstrumentationTestCase {
assertEquals(Typeface.BOLD, s4.getSpans(17, s4.length(), StyleSpan.class)[0].getStyle()); assertEquals(Typeface.BOLD, s4.getSpans(17, s4.length(), StyleSpan.class)[0].getStyle());
} }
public void testWithComplexCssSelectors() throws IOException, TextDecoderException { public void testWithComplexCssSelectors() throws IOException, SubtitleDecoderException {
WebvttSubtitle subtitle = getSubtitleForTestAsset(WITH_CSS_COMPLEX_SELECTORS); WebvttSubtitle subtitle = getSubtitleForTestAsset(WITH_CSS_COMPLEX_SELECTORS);
Spanned text = getUniqueSpanTextAt(subtitle, 0); Spanned text = getUniqueSpanTextAt(subtitle, 0);
assertEquals(1, text.getSpans(30, text.length(), ForegroundColorSpan.class).length); assertEquals(1, text.getSpans(30, text.length(), ForegroundColorSpan.class).length);
@ -193,7 +193,7 @@ public class WebvttDecoderTest extends InstrumentationTestCase {
} }
private WebvttSubtitle getSubtitleForTestAsset(String asset) throws IOException, private WebvttSubtitle getSubtitleForTestAsset(String asset) throws IOException,
TextDecoderException { SubtitleDecoderException {
WebvttDecoder decoder = new WebvttDecoder(); WebvttDecoder decoder = new WebvttDecoder();
byte[] bytes = TestUtil.getByteArray(getInstrumentation(), asset); byte[] bytes = TestUtil.getByteArray(getInstrumentation(), asset);
return decoder.decode(bytes, bytes.length); return decoder.decode(bytes, bytes.length);

View File

@ -204,7 +204,7 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
} }
} }
int handleBufferResult = audioTrack.handleBuffer(outputBuffer.data, outputBuffer.timestampUs); int handleBufferResult = audioTrack.handleBuffer(outputBuffer.data, outputBuffer.timeUs);
lastFeedElapsedRealtimeMs = SystemClock.elapsedRealtime(); lastFeedElapsedRealtimeMs = SystemClock.elapsedRealtime();
// If we are out of sync, allow currentPositionUs to jump backwards. // If we are out of sync, allow currentPositionUs to jump backwards.

View File

@ -23,7 +23,7 @@ public abstract class OutputBuffer extends Buffer {
/** /**
* The presentation timestamp for the buffer, in microseconds. * The presentation timestamp for the buffer, in microseconds.
*/ */
public long timestampUs; public long timeUs;
/** /**
* The number of buffers immediately prior to this one that were skipped in the {@link Decoder}. * The number of buffers immediately prior to this one that were skipped in the {@link Decoder}.

View File

@ -33,12 +33,12 @@ public class SimpleOutputBuffer extends OutputBuffer {
/** /**
* Initializes the buffer. * Initializes the buffer.
* *
* @param timestampUs The presentation timestamp for the buffer, in microseconds. * @param timeUs The presentation timestamp for the buffer, in microseconds.
* @param size An upper bound on the size of the data that will be written to the buffer. * @param size An upper bound on the size of the data that will be written to the buffer.
* @return The {@link #data} buffer, for convenience. * @return The {@link #data} buffer, for convenience.
*/ */
public ByteBuffer init(long timestampUs, int size) { public ByteBuffer init(long timeUs, int size) {
this.timestampUs = timestampUs; this.timeUs = timeUs;
if (data == null || data.capacity() < size) { if (data == null || data.capacity() < size) {
data = ByteBuffer.allocateDirect(size); data = ByteBuffer.allocateDirect(size);
} }

View File

@ -15,7 +15,6 @@
*/ */
package com.google.android.exoplayer2.metadata; package com.google.android.exoplayer2.metadata;
// TODO: This class should implement SimpleDecoder.
/** /**
* Parses objects of type <T> from binary data. * Parses objects of type <T> from binary data.
* *

View File

@ -20,10 +20,17 @@ package com.google.android.exoplayer2.metadata;
*/ */
public class MetadataDecoderException extends Exception { public class MetadataDecoderException extends Exception {
/**
* @param message The detail message.
*/
public MetadataDecoderException(String message) { public MetadataDecoderException(String message) {
super(message); super(message);
} }
/**
* @param message The detail message.
* @param cause The cause.
*/
public MetadataDecoderException(String message, Throwable cause) { public MetadataDecoderException(String message, Throwable cause) {
super(message, cause); super(message, cause);
} }

View File

@ -15,12 +15,11 @@
*/ */
package com.google.android.exoplayer2.metadata; package com.google.android.exoplayer2.metadata;
import com.google.android.exoplayer2.BaseRenderer;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder; import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.BaseRenderer;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
@ -32,7 +31,7 @@ import android.os.Message;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
/** /**
* A {@link Renderer} for metadata embedded in a media stream. * A renderer for metadata.
* *
* @param <T> The type of the metadata. * @param <T> The type of the metadata.
*/ */

View File

@ -25,7 +25,7 @@ import com.google.android.exoplayer2.extractor.PositionHolder;
import com.google.android.exoplayer2.extractor.SeekMap; import com.google.android.exoplayer2.extractor.SeekMap;
import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.extractor.ts.PtsTimestampAdjuster; import com.google.android.exoplayer2.extractor.ts.PtsTimestampAdjuster;
import com.google.android.exoplayer2.text.TextDecoderException; import com.google.android.exoplayer2.text.SubtitleDecoderException;
import com.google.android.exoplayer2.text.webvtt.WebvttParserUtil; import com.google.android.exoplayer2.text.webvtt.WebvttParserUtil;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
@ -122,7 +122,7 @@ import java.util.regex.Pattern;
// Validate the first line of the header. // Validate the first line of the header.
try { try {
WebvttParserUtil.validateWebvttHeaderLine(webvttData); WebvttParserUtil.validateWebvttHeaderLine(webvttData);
} catch (TextDecoderException e) { } catch (SubtitleDecoderException e) {
throw new ParserException(e); throw new ParserException(e);
} }

View File

@ -58,7 +58,7 @@ public class Cue {
*/ */
public final CharSequence text; public final CharSequence text;
/** /**
* The alignment of the cue text within the cue box. * The alignment of the cue text within the cue box, or null if the alignment is undefined.
*/ */
public final Alignment textAlignment; public final Alignment textAlignment;
/** /**
@ -117,16 +117,28 @@ public class Cue {
*/ */
public final float size; public final float size;
public Cue() { /**
this(null); * Constructs a cue whose {@link #textAlignment} is null, whose type parameters are set to
} * {@link #TYPE_UNSET} and whose dimension parameters are set to {@link #DIMEN_UNSET}.
*
* @param text See {@link #text}.
*/
public Cue(CharSequence text) { public Cue(CharSequence text) {
this(text, null, DIMEN_UNSET, TYPE_UNSET, TYPE_UNSET, DIMEN_UNSET, TYPE_UNSET, DIMEN_UNSET); this(text, null, DIMEN_UNSET, TYPE_UNSET, TYPE_UNSET, DIMEN_UNSET, TYPE_UNSET, DIMEN_UNSET);
} }
public Cue(CharSequence text, Alignment textAlignment, float line, int lineType, /**
int lineAnchor, float position, int positionAnchor, float size) { * @param text See {@link #text}.
* @param textAlignment See {@link #textAlignment}.
* @param line See {@link #line}.
* @param lineType See {@link #lineType}.
* @param lineAnchor See {@link #lineAnchor}.
* @param position See {@link #position}.
* @param positionAnchor See {@link #positionAnchor}.
* @param size See {@link #size}.
*/
public Cue(CharSequence text, Alignment textAlignment, float line, int lineType, int lineAnchor,
float position, int positionAnchor, float size) {
this.text = text; this.text = text;
this.textAlignment = textAlignment; this.textAlignment = textAlignment;
this.line = line; this.line = line;

View File

@ -23,11 +23,14 @@ import java.nio.ByteBuffer;
* Base class for subtitle parsers that use their own decode thread. * Base class for subtitle parsers that use their own decode thread.
*/ */
public abstract class SimpleSubtitleDecoder extends public abstract class SimpleSubtitleDecoder extends
SimpleDecoder<SubtitleInputBuffer, SubtitleOutputBuffer, TextDecoderException> implements SimpleDecoder<SubtitleInputBuffer, SubtitleOutputBuffer, SubtitleDecoderException> implements
SubtitleDecoder { SubtitleDecoder {
private final String name; private final String name;
/**
* @param name The name of the decoder.
*/
protected SimpleSubtitleDecoder(String name) { protected SimpleSubtitleDecoder(String name) {
super(new SubtitleInputBuffer[2], new SubtitleOutputBuffer[2]); super(new SubtitleInputBuffer[2], new SubtitleOutputBuffer[2]);
this.name = name; this.name = name;
@ -60,26 +63,26 @@ public abstract class SimpleSubtitleDecoder extends
} }
@Override @Override
protected final TextDecoderException decode(SubtitleInputBuffer inputBuffer, protected final SubtitleDecoderException decode(SubtitleInputBuffer inputBuffer,
SubtitleOutputBuffer outputBuffer, boolean reset) { SubtitleOutputBuffer outputBuffer, boolean reset) {
try { try {
ByteBuffer inputData = inputBuffer.data; ByteBuffer inputData = inputBuffer.data;
Subtitle subtitle = decode(inputData.array(), inputData.limit()); Subtitle subtitle = decode(inputData.array(), inputData.limit());
outputBuffer.setOutput(inputBuffer.timeUs, subtitle, inputBuffer.subsampleOffsetUs); outputBuffer.setContent(inputBuffer.timeUs, subtitle, inputBuffer.subsampleOffsetUs);
return null; return null;
} catch (TextDecoderException e) { } catch (SubtitleDecoderException e) {
return e; return e;
} }
} }
/** /**
* Decodes the data and converts it into a {@link Subtitle}. * Decodes data into a {@link Subtitle}.
* *
* @param data The data to be decoded. * @param data An array holding the data to be decoded, starting at position 0.
* @param size The size of the data. * @param size The size of the data to be decoded.
* @return A {@link Subtitle} to rendered. * @return The decoded {@link Subtitle}.
* @throws TextDecoderException If a decoding error occurs. * @throws SubtitleDecoderException If a decoding error occurs.
*/ */
protected abstract Subtitle decode(byte[] data, int size) throws TextDecoderException; protected abstract Subtitle decode(byte[] data, int size) throws SubtitleDecoderException;
} }

View File

@ -16,12 +16,15 @@
package com.google.android.exoplayer2.text; package com.google.android.exoplayer2.text;
/** /**
* A {@link Subtitle} output from a subtitle parser that extends {@link SimpleSubtitleDecoder}. * A {@link SubtitleOutputBuffer} for decoders that extend {@link SimpleSubtitleDecoder}.
*/ */
public final class SimpleSubtitleOutputBuffer extends SubtitleOutputBuffer { /* package */ final class SimpleSubtitleOutputBuffer extends SubtitleOutputBuffer {
private SimpleSubtitleDecoder owner; private SimpleSubtitleDecoder owner;
/**
* @param owner The decoder that owns this buffer.
*/
public SimpleSubtitleOutputBuffer(SimpleSubtitleDecoder owner) { public SimpleSubtitleOutputBuffer(SimpleSubtitleDecoder owner) {
super(); super();
this.owner = owner; this.owner = owner;

View File

@ -23,7 +23,7 @@ import java.util.List;
public interface Subtitle { public interface Subtitle {
/** /**
* Gets the index of the first event that occurs after a given time (exclusive). * Returns the index of the first event that occurs after a given time (exclusive).
* *
* @param timeUs The time in microseconds. * @param timeUs The time in microseconds.
* @return The index of the next event, or -1 if there are no events after the specified time. * @return The index of the next event, or -1 if there are no events after the specified time.
@ -31,7 +31,7 @@ public interface Subtitle {
int getNextEventTimeIndex(long timeUs); int getNextEventTimeIndex(long timeUs);
/** /**
* Gets the number of event times, where events are defined as points in time at which the cues * Returns the number of event times, where events are defined as points in time at which the cues
* returned by {@link #getCues(long)} changes. * returned by {@link #getCues(long)} changes.
* *
* @return The number of event times. * @return The number of event times.
@ -39,7 +39,7 @@ public interface Subtitle {
int getEventTimeCount(); int getEventTimeCount();
/** /**
* Gets the event time at a specified index. * Returns the event time at a specified index.
* *
* @param index The index of the event time to obtain. * @param index The index of the event time to obtain.
* @return The event time in microseconds. * @return The event time in microseconds.

View File

@ -21,7 +21,7 @@ import com.google.android.exoplayer2.decoder.Decoder;
* Parses {@link Subtitle}s from {@link SubtitleInputBuffer}s. * Parses {@link Subtitle}s from {@link SubtitleInputBuffer}s.
*/ */
public interface SubtitleDecoder extends public interface SubtitleDecoder extends
Decoder<SubtitleInputBuffer, SubtitleOutputBuffer, TextDecoderException> { Decoder<SubtitleInputBuffer, SubtitleOutputBuffer, SubtitleDecoderException> {
/** /**
* Informs the parser of the current playback position. * Informs the parser of the current playback position.

View File

@ -18,13 +18,20 @@ package com.google.android.exoplayer2.text;
/** /**
* Thrown when an error occurs decoding text data. * Thrown when an error occurs decoding text data.
*/ */
public class TextDecoderException extends Exception { public class SubtitleDecoderException extends Exception {
public TextDecoderException(String message) { /**
* @param message The detail message.
*/
public SubtitleDecoderException(String message) {
super(message); super(message);
} }
public TextDecoderException(String message, Throwable cause) { /**
* @param message The detail message.
* @param cause The cause.
*/
public SubtitleDecoderException(String message, Throwable cause) {
super(message, cause); super(message, cause);
} }

View File

@ -31,19 +31,19 @@ import com.google.android.exoplayer2.util.MimeTypes;
public interface SubtitleDecoderFactory { public interface SubtitleDecoderFactory {
/** /**
* Returns whether the factory is able to instantiate a {@link Decoder} for the given * Returns whether the factory is able to instantiate a {@link SubtitleDecoder} for the given
* {@link Format}. * {@link Format}.
* *
* @param format The {@link Format}. * @param format The {@link Format}.
* @return True if the factory can instantiate a suitable {@link Decoder}. False otherwise. * @return Whether the factory can instantiate a suitable {@link SubtitleDecoder}.
*/ */
boolean supportsFormat(Format format); boolean supportsFormat(Format format);
/** /**
* Creates a {@link Decoder} for the given {@link Format}. * Creates a {@link SubtitleDecoder} for the given {@link Format}.
* *
* @param format The {@link Format}. * @param format The {@link Format}.
* @return A new {@link Decoder}. * @return A new {@link SubtitleDecoder}.
* @throws IllegalArgumentException If the {@link Format} is not supported. * @throws IllegalArgumentException If the {@link Format} is not supported.
*/ */
SubtitleDecoder createDecoder(Format format); SubtitleDecoder createDecoder(Format format);

View File

@ -15,14 +15,19 @@
*/ */
package com.google.android.exoplayer2.text; package com.google.android.exoplayer2.text;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
/** /**
* An input buffer for a subtitle parser. * A {@link DecoderInputBuffer} for a {@link SubtitleDecoder}.
*/ */
public final class SubtitleInputBuffer extends DecoderInputBuffer public final class SubtitleInputBuffer extends DecoderInputBuffer
implements Comparable<SubtitleInputBuffer> { implements Comparable<SubtitleInputBuffer> {
/**
* An offset that must be added to the subtitle's event times after it's been decoded, or
* {@link Format#OFFSET_SAMPLE_RELATIVE} if {@link #timeUs} should be added.
*/
public long subsampleOffsetUs; public long subsampleOffsetUs;
public SubtitleInputBuffer() { public SubtitleInputBuffer() {

View File

@ -21,20 +21,26 @@ import com.google.android.exoplayer2.decoder.OutputBuffer;
import java.util.List; import java.util.List;
/** /**
* Base class for a {@link Subtitle} output from a subtitle parser. * Base class for {@link SubtitleDecoder} output buffers.
*/ */
public abstract class SubtitleOutputBuffer extends OutputBuffer implements Subtitle { public abstract class SubtitleOutputBuffer extends OutputBuffer implements Subtitle {
private Subtitle subtitle; private Subtitle subtitle;
private long offsetUs; private long subsampleOffsetUs;
public SubtitleOutputBuffer() { /**
} * Sets the content of the output buffer, consisting of a {@link Subtitle} and associated
* metadata.
public void setOutput(long timestampUs, Subtitle subtitle, long subsampleOffsetUs) { *
this.timestampUs = timestampUs; * @param timeUs The time of the start of the subtitle in microseconds.
* @param subtitle The subtitle.
* @param subsampleOffsetUs An offset that must be added to the subtitle's event times, or
* {@link Format#OFFSET_SAMPLE_RELATIVE} if {@code timeUs} should be added.
*/
public void setContent(long timeUs, Subtitle subtitle, long subsampleOffsetUs) {
this.timeUs = timeUs;
this.subtitle = subtitle; this.subtitle = subtitle;
this.offsetUs = subsampleOffsetUs == Format.OFFSET_SAMPLE_RELATIVE ? timestampUs this.subsampleOffsetUs = subsampleOffsetUs == Format.OFFSET_SAMPLE_RELATIVE ? this.timeUs
: subsampleOffsetUs; : subsampleOffsetUs;
} }
@ -45,17 +51,17 @@ public abstract class SubtitleOutputBuffer extends OutputBuffer implements Subti
@Override @Override
public long getEventTime(int index) { public long getEventTime(int index) {
return subtitle.getEventTime(index) + offsetUs; return subtitle.getEventTime(index) + subsampleOffsetUs;
} }
@Override @Override
public int getNextEventTimeIndex(long timeUs) { public int getNextEventTimeIndex(long timeUs) {
return subtitle.getNextEventTimeIndex(timeUs - offsetUs); return subtitle.getNextEventTimeIndex(timeUs - subsampleOffsetUs);
} }
@Override @Override
public List<Cue> getCues(long timeUs) { public List<Cue> getCues(long timeUs) {
return subtitle.getCues(timeUs - offsetUs); return subtitle.getCues(timeUs - subsampleOffsetUs);
} }
@Override @Override

View File

@ -23,7 +23,6 @@ import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import android.annotation.TargetApi;
import android.os.Handler; import android.os.Handler;
import android.os.Handler.Callback; import android.os.Handler.Callback;
import android.os.Looper; import android.os.Looper;
@ -33,13 +32,12 @@ import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
* A renderer for subtitles. * A renderer for text.
* <p> * <p>
* Text is parsed from sample data using {@link SubtitleDecoder} instances obtained from a * {@link Subtitle}s are decoded from sample data using {@link SubtitleDecoder} instances obtained
* {@link SubtitleDecoderFactory}. The actual rendering of each line of text is delegated to a * from a {@link SubtitleDecoderFactory}. The actual rendering of the subtitle {@link Cue}s is
* {@link Output}. * delegated to an {@link Output}.
*/ */
@TargetApi(16)
public final class TextRenderer extends BaseRenderer implements Callback { public final class TextRenderer extends BaseRenderer implements Callback {
/** /**
@ -142,7 +140,7 @@ public final class TextRenderer extends BaseRenderer implements Callback {
decoder.setPositionUs(positionUs); decoder.setPositionUs(positionUs);
try { try {
nextSubtitle = decoder.dequeueOutputBuffer(); nextSubtitle = decoder.dequeueOutputBuffer();
} catch (TextDecoderException e) { } catch (SubtitleDecoderException e) {
throw ExoPlaybackException.createForRenderer(e, getIndex()); throw ExoPlaybackException.createForRenderer(e, getIndex());
} }
} }
@ -163,7 +161,7 @@ public final class TextRenderer extends BaseRenderer implements Callback {
} }
} }
if (nextSubtitle != null && nextSubtitle.timestampUs <= positionUs) { if (nextSubtitle != null && nextSubtitle.timeUs <= positionUs) {
// Advance to the next subtitle. Sync the next event index and trigger an update. // Advance to the next subtitle. Sync the next event index and trigger an update.
if (subtitle != null) { if (subtitle != null) {
subtitle.release(); subtitle.release();
@ -210,7 +208,7 @@ public final class TextRenderer extends BaseRenderer implements Callback {
break; break;
} }
} }
} catch (TextDecoderException e) { } catch (SubtitleDecoderException e) {
throw ExoPlaybackException.createForRenderer(e, getIndex()); throw ExoPlaybackException.createForRenderer(e, getIndex());
} }
} }

View File

@ -19,7 +19,7 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.text.SubtitleDecoder; import com.google.android.exoplayer2.text.SubtitleDecoder;
import com.google.android.exoplayer2.text.SubtitleInputBuffer; import com.google.android.exoplayer2.text.SubtitleInputBuffer;
import com.google.android.exoplayer2.text.SubtitleOutputBuffer; import com.google.android.exoplayer2.text.SubtitleOutputBuffer;
import com.google.android.exoplayer2.text.TextDecoderException; import com.google.android.exoplayer2.text.SubtitleDecoderException;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
@ -213,7 +213,7 @@ public final class Eia608Decoder implements SubtitleDecoder {
} }
@Override @Override
public SubtitleInputBuffer dequeueInputBuffer() throws TextDecoderException { public SubtitleInputBuffer dequeueInputBuffer() throws SubtitleDecoderException {
Assertions.checkState(dequeuedInputBuffer == null); Assertions.checkState(dequeuedInputBuffer == null);
if (availableInputBuffers.isEmpty()) { if (availableInputBuffers.isEmpty()) {
return null; return null;
@ -223,7 +223,7 @@ public final class Eia608Decoder implements SubtitleDecoder {
} }
@Override @Override
public void queueInputBuffer(SubtitleInputBuffer inputBuffer) throws TextDecoderException { public void queueInputBuffer(SubtitleInputBuffer inputBuffer) throws SubtitleDecoderException {
Assertions.checkArgument(inputBuffer != null); Assertions.checkArgument(inputBuffer != null);
Assertions.checkArgument(inputBuffer == dequeuedInputBuffer); Assertions.checkArgument(inputBuffer == dequeuedInputBuffer);
queuedInputBuffers.add(inputBuffer); queuedInputBuffers.add(inputBuffer);
@ -231,7 +231,7 @@ public final class Eia608Decoder implements SubtitleDecoder {
} }
@Override @Override
public SubtitleOutputBuffer dequeueOutputBuffer() throws TextDecoderException { public SubtitleOutputBuffer dequeueOutputBuffer() throws SubtitleDecoderException {
if (availableOutputBuffers.isEmpty()) { if (availableOutputBuffers.isEmpty()) {
return null; return null;
} }
@ -259,7 +259,7 @@ public final class Eia608Decoder implements SubtitleDecoder {
lastCaptionString = captionString; lastCaptionString = captionString;
if (!inputBuffer.isDecodeOnly()) { if (!inputBuffer.isDecodeOnly()) {
SubtitleOutputBuffer outputBuffer = availableOutputBuffers.pollFirst(); SubtitleOutputBuffer outputBuffer = availableOutputBuffers.pollFirst();
outputBuffer.setOutput(inputBuffer.timeUs, new Eia608Subtitle(captionString), 0); outputBuffer.setContent(inputBuffer.timeUs, new Eia608Subtitle(captionString), 0);
releaseInputBuffer(inputBuffer); releaseInputBuffer(inputBuffer);
return outputBuffer; return outputBuffer;
} }

View File

@ -18,18 +18,23 @@ package com.google.android.exoplayer2.text.eia608;
import com.google.android.exoplayer2.text.Cue; import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.Subtitle; import com.google.android.exoplayer2.text.Subtitle;
import android.text.TextUtils;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
* A representation of an EIA-608 subtitle. * A representation of an EIA-608 subtitle.
*/ */
public final class Eia608Subtitle implements Subtitle { /* package */ final class Eia608Subtitle implements Subtitle {
private final String caption; private final String text;
public Eia608Subtitle(String caption) { /**
this.caption = caption; * @param text The subtitle text.
*/
public Eia608Subtitle(String text) {
this.text = text;
} }
@Override @Override
@ -49,10 +54,10 @@ public final class Eia608Subtitle implements Subtitle {
@Override @Override
public List<Cue> getCues(long timeUs) { public List<Cue> getCues(long timeUs) {
if (caption == null || caption.isEmpty()) { if (TextUtils.isEmpty(text)) {
return Collections.emptyList(); return Collections.emptyList();
} else { } else {
return Collections.singletonList(new Cue(caption)); return Collections.singletonList(new Cue(text));
} }
} }

View File

@ -21,10 +21,13 @@ import com.google.android.exoplayer2.text.SubtitleOutputBuffer;
/** /**
* A {@link Subtitle} output from an {@link Eia608Decoder}. * A {@link Subtitle} output from an {@link Eia608Decoder}.
*/ */
public final class Eia608SubtitleOutputBuffer extends SubtitleOutputBuffer { /* package */ final class Eia608SubtitleOutputBuffer extends SubtitleOutputBuffer {
private Eia608Decoder owner; private Eia608Decoder owner;
/**
* @param owner The decoder that owns this buffer.
*/
public Eia608SubtitleOutputBuffer(Eia608Decoder owner) { public Eia608SubtitleOutputBuffer(Eia608Decoder owner) {
super(); super();
this.owner = owner; this.owner = owner;

View File

@ -18,7 +18,7 @@ package com.google.android.exoplayer2.text.ttml;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.text.Cue; import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.SimpleSubtitleDecoder; import com.google.android.exoplayer2.text.SimpleSubtitleDecoder;
import com.google.android.exoplayer2.text.TextDecoderException; import com.google.android.exoplayer2.text.SubtitleDecoderException;
import com.google.android.exoplayer2.util.ColorParser; import com.google.android.exoplayer2.util.ColorParser;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.util.XmlPullParserUtil; import com.google.android.exoplayer2.util.XmlPullParserUtil;
@ -99,7 +99,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
} }
@Override @Override
protected TtmlSubtitle decode(byte[] bytes, int length) throws TextDecoderException { protected TtmlSubtitle decode(byte[] bytes, int length) throws SubtitleDecoderException {
try { try {
XmlPullParser xmlParser = xmlParserFactory.newPullParser(); XmlPullParser xmlParser = xmlParserFactory.newPullParser();
Map<String, TtmlStyle> globalStyles = new HashMap<>(); Map<String, TtmlStyle> globalStyles = new HashMap<>();
@ -132,7 +132,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
if (parent != null) { if (parent != null) {
parent.addChild(node); parent.addChild(node);
} }
} catch (TextDecoderException e) { } catch (SubtitleDecoderException e) {
Log.w(TAG, "Suppressing parser error", e); Log.w(TAG, "Suppressing parser error", e);
// Treat the node (and by extension, all of its children) as unsupported. // Treat the node (and by extension, all of its children) as unsupported.
unsupportedNodeDepth++; unsupportedNodeDepth++;
@ -158,14 +158,14 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
} }
return ttmlSubtitle; return ttmlSubtitle;
} catch (XmlPullParserException xppe) { } catch (XmlPullParserException xppe) {
throw new TextDecoderException("Unable to decode source", xppe); throw new SubtitleDecoderException("Unable to decode source", xppe);
} catch (IOException e) { } catch (IOException e) {
throw new IllegalStateException("Unexpected error when reading input.", e); throw new IllegalStateException("Unexpected error when reading input.", e);
} }
} }
private FrameAndTickRate parseFrameAndTickRates(XmlPullParser xmlParser) private FrameAndTickRate parseFrameAndTickRates(XmlPullParser xmlParser)
throws TextDecoderException { throws SubtitleDecoderException {
int frameRate = DEFAULT_FRAME_RATE; int frameRate = DEFAULT_FRAME_RATE;
String frameRateString = xmlParser.getAttributeValue(TTP, "frameRate"); String frameRateString = xmlParser.getAttributeValue(TTP, "frameRate");
if (frameRateString != null) { if (frameRateString != null) {
@ -177,7 +177,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
if (frameRateMultiplierString != null) { if (frameRateMultiplierString != null) {
String[] parts = frameRateMultiplierString.split(" "); String[] parts = frameRateMultiplierString.split(" ");
if (parts.length != 2) { if (parts.length != 2) {
throw new TextDecoderException("frameRateMultiplier doesn't have 2 parts"); throw new SubtitleDecoderException("frameRateMultiplier doesn't have 2 parts");
} }
float numerator = Integer.parseInt(parts[0]); float numerator = Integer.parseInt(parts[0]);
float denominator = Integer.parseInt(parts[1]); float denominator = Integer.parseInt(parts[1]);
@ -299,7 +299,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
try { try {
style = createIfNull(style); style = createIfNull(style);
parseFontSize(attributeValue, style); parseFontSize(attributeValue, style);
} catch (TextDecoderException e) { } catch (SubtitleDecoderException e) {
Log.w(TAG, "failed parsing fontSize value: '" + attributeValue + "'"); Log.w(TAG, "failed parsing fontSize value: '" + attributeValue + "'");
} }
break; break;
@ -360,7 +360,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
private TtmlNode parseNode(XmlPullParser parser, TtmlNode parent, private TtmlNode parseNode(XmlPullParser parser, TtmlNode parent,
Map<String, TtmlRegion> regionMap, FrameAndTickRate frameAndTickRate) Map<String, TtmlRegion> regionMap, FrameAndTickRate frameAndTickRate)
throws TextDecoderException { throws SubtitleDecoderException {
long duration = 0; long duration = 0;
long startTime = TtmlNode.UNDEFINED_TIME; long startTime = TtmlNode.UNDEFINED_TIME;
long endTime = TtmlNode.UNDEFINED_TIME; long endTime = TtmlNode.UNDEFINED_TIME;
@ -438,7 +438,8 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
|| tag.equals(TtmlNode.TAG_SMPTE_INFORMATION); || tag.equals(TtmlNode.TAG_SMPTE_INFORMATION);
} }
private static void parseFontSize(String expression, TtmlStyle out) throws TextDecoderException { private static void parseFontSize(String expression, TtmlStyle out) throws
SubtitleDecoderException {
String[] expressions = expression.split("\\s+"); String[] expressions = expression.split("\\s+");
Matcher matcher; Matcher matcher;
if (expressions.length == 1) { if (expressions.length == 1) {
@ -448,8 +449,8 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
Log.w(TAG, "Multiple values in fontSize attribute. Picking the second value for vertical font" Log.w(TAG, "Multiple values in fontSize attribute. Picking the second value for vertical font"
+ " size and ignoring the first."); + " size and ignoring the first.");
} else { } else {
throw new TextDecoderException("Invalid number of entries for fontSize: " + expressions.length throw new SubtitleDecoderException("Invalid number of entries for fontSize: "
+ "."); + expressions.length + ".");
} }
if (matcher.matches()) { if (matcher.matches()) {
@ -465,11 +466,11 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
out.setFontSizeUnit(TtmlStyle.FONT_SIZE_UNIT_PERCENT); out.setFontSizeUnit(TtmlStyle.FONT_SIZE_UNIT_PERCENT);
break; break;
default: default:
throw new TextDecoderException("Invalid unit for fontSize: '" + unit + "'."); throw new SubtitleDecoderException("Invalid unit for fontSize: '" + unit + "'.");
} }
out.setFontSize(Float.valueOf(matcher.group(1))); out.setFontSize(Float.valueOf(matcher.group(1)));
} else { } else {
throw new TextDecoderException("Invalid expression for fontSize: '" + expression + "'."); throw new SubtitleDecoderException("Invalid expression for fontSize: '" + expression + "'.");
} }
} }
@ -482,10 +483,10 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
* @param time A string that includes the time expression. * @param time A string that includes the time expression.
* @param frameAndTickRate The effective frame and tick rates of the stream. * @param frameAndTickRate The effective frame and tick rates of the stream.
* @return The parsed timestamp in microseconds. * @return The parsed timestamp in microseconds.
* @throws TextDecoderException If the given string does not contain a valid time expression. * @throws SubtitleDecoderException If the given string does not contain a valid time expression.
*/ */
private static long parseTimeExpression(String time, FrameAndTickRate frameAndTickRate) private static long parseTimeExpression(String time, FrameAndTickRate frameAndTickRate)
throws TextDecoderException { throws SubtitleDecoderException {
Matcher matcher = CLOCK_TIME.matcher(time); Matcher matcher = CLOCK_TIME.matcher(time);
if (matcher.matches()) { if (matcher.matches()) {
String hours = matcher.group(1); String hours = matcher.group(1);
@ -533,7 +534,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
} }
return (long) (offsetSeconds * C.MICROS_PER_SECOND); return (long) (offsetSeconds * C.MICROS_PER_SECOND);
} }
throw new TextDecoderException("Malformed time expression: " + time); throw new SubtitleDecoderException("Malformed time expression: " + time);
} }
private static final class FrameAndTickRate { private static final class FrameAndTickRate {

View File

@ -17,7 +17,7 @@ package com.google.android.exoplayer2.text.webvtt;
import com.google.android.exoplayer2.text.Cue; import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.SimpleSubtitleDecoder; import com.google.android.exoplayer2.text.SimpleSubtitleDecoder;
import com.google.android.exoplayer2.text.TextDecoderException; import com.google.android.exoplayer2.text.SubtitleDecoderException;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
@ -46,14 +46,14 @@ public final class Mp4WebvttDecoder extends SimpleSubtitleDecoder {
} }
@Override @Override
protected Mp4WebvttSubtitle decode(byte[] bytes, int length) throws TextDecoderException { 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: // 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.
sampleData.reset(bytes, length); sampleData.reset(bytes, length);
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) {
throw new TextDecoderException("Incomplete Mp4Webvtt Top Level box header found."); throw new SubtitleDecoderException("Incomplete Mp4Webvtt Top Level box header found.");
} }
int boxSize = sampleData.readInt(); int boxSize = sampleData.readInt();
int boxType = sampleData.readInt(); int boxType = sampleData.readInt();
@ -68,11 +68,11 @@ public final class Mp4WebvttDecoder extends SimpleSubtitleDecoder {
} }
private static Cue parseVttCueBox(ParsableByteArray sampleData, WebvttCue.Builder builder, private static Cue parseVttCueBox(ParsableByteArray sampleData, WebvttCue.Builder builder,
int remainingCueBoxBytes) throws TextDecoderException { int remainingCueBoxBytes) throws SubtitleDecoderException {
builder.reset(); builder.reset();
while (remainingCueBoxBytes > 0) { while (remainingCueBoxBytes > 0) {
if (remainingCueBoxBytes < BOX_HEADER_SIZE) { if (remainingCueBoxBytes < BOX_HEADER_SIZE) {
throw new TextDecoderException("Incomplete vtt cue box header found."); throw new SubtitleDecoderException("Incomplete vtt cue box header found.");
} }
int boxSize = sampleData.readInt(); int boxSize = sampleData.readInt();
int boxType = sampleData.readInt(); int boxType = sampleData.readInt();

View File

@ -433,7 +433,7 @@ import java.util.regex.Pattern;
} }
/** /**
* Gets the tag name for the given tag contents. * Returns the tag name for the given tag contents.
* *
* @param tagExpression Characters between &amp;lt: and &amp;gt; of a start or end tag. * @param tagExpression Characters between &amp;lt: and &amp;gt; of a start or end tag.
* @return The name of tag. * @return The name of tag.

View File

@ -16,7 +16,7 @@
package com.google.android.exoplayer2.text.webvtt; package com.google.android.exoplayer2.text.webvtt;
import com.google.android.exoplayer2.text.SimpleSubtitleDecoder; import com.google.android.exoplayer2.text.SimpleSubtitleDecoder;
import com.google.android.exoplayer2.text.TextDecoderException; import com.google.android.exoplayer2.text.SubtitleDecoderException;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
import android.text.TextUtils; import android.text.TextUtils;
@ -55,7 +55,7 @@ public final class WebvttDecoder extends SimpleSubtitleDecoder {
} }
@Override @Override
protected WebvttSubtitle decode(byte[] bytes, int length) throws TextDecoderException { protected WebvttSubtitle decode(byte[] bytes, int length) throws SubtitleDecoderException {
parsableWebvttData.reset(bytes, length); parsableWebvttData.reset(bytes, length);
// Initialization for consistent starting state. // Initialization for consistent starting state.
webvttCueBuilder.reset(); webvttCueBuilder.reset();
@ -72,7 +72,7 @@ public final class WebvttDecoder extends SimpleSubtitleDecoder {
skipComment(parsableWebvttData); skipComment(parsableWebvttData);
} else if (eventFound == STYLE_BLOCK_FOUND) { } else if (eventFound == STYLE_BLOCK_FOUND) {
if (!subtitles.isEmpty()) { if (!subtitles.isEmpty()) {
throw new TextDecoderException("A style block was found after the first cue."); throw new SubtitleDecoderException("A style block was found after the first cue.");
} }
parsableWebvttData.readLine(); // Consume the "STYLE" header. parsableWebvttData.readLine(); // Consume the "STYLE" header.
WebvttCssStyle styleBlock = cssParser.parseBlock(parsableWebvttData); WebvttCssStyle styleBlock = cssParser.parseBlock(parsableWebvttData);

View File

@ -15,7 +15,7 @@
*/ */
package com.google.android.exoplayer2.text.webvtt; package com.google.android.exoplayer2.text.webvtt;
import com.google.android.exoplayer2.text.TextDecoderException; import com.google.android.exoplayer2.text.SubtitleDecoderException;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@ -35,12 +35,13 @@ public final class WebvttParserUtil {
* Reads and validates the first line of a WebVTT file. * Reads and validates the first line of a WebVTT file.
* *
* @param input The input from which the line should be read. * @param input The input from which the line should be read.
* @throws TextDecoderException If the line isn't the start of a valid WebVTT file. * @throws SubtitleDecoderException If the line isn't the start of a valid WebVTT file.
*/ */
public static void validateWebvttHeaderLine(ParsableByteArray input) throws TextDecoderException { public static void validateWebvttHeaderLine(ParsableByteArray input)
throws SubtitleDecoderException {
String line = input.readLine(); String line = input.readLine();
if (line == null || !HEADER.matcher(line).matches()) { if (line == null || !HEADER.matcher(line).matches()) {
throw new TextDecoderException("Expected WEBVTT. Got " + line); throw new SubtitleDecoderException("Expected WEBVTT. Got " + line);
} }
} }

View File

@ -30,7 +30,7 @@ import java.util.List;
/** /**
* A representation of a WebVTT subtitle. * A representation of a WebVTT subtitle.
*/ */
public final class WebvttSubtitle implements Subtitle { /* package */ final class WebvttSubtitle implements Subtitle {
private final List<WebvttCue> cues; private final List<WebvttCue> cues;
private final int numCues; private final int numCues;

View File

@ -13,8 +13,10 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.google.android.exoplayer2.text; package com.google.android.exoplayer2.ui;
import com.google.android.exoplayer2.text.CaptionStyleCompat;
import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import android.content.Context; import android.content.Context;
@ -34,11 +36,11 @@ import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
/** /**
* Draws {@link Cue}s. * Draws subtitle {@link Cue}s.
*/ */
/* package */ final class CuePainter { /* package */ final class SubtitleCuePainter {
private static final String TAG = "CuePainter"; private static final String TAG = "SubtitleCuePainter";
/** /**
* Ratio of inner padding to font size. * Ratio of inner padding to font size.
@ -89,7 +91,7 @@ import android.util.Log;
private int textTop; private int textTop;
private int textPaddingX; private int textPaddingX;
public CuePainter(Context context) { public SubtitleCuePainter(Context context) {
int[] viewAttr = {android.R.attr.lineSpacingExtra, android.R.attr.lineSpacingMultiplier}; int[] viewAttr = {android.R.attr.lineSpacingExtra, android.R.attr.lineSpacingMultiplier};
TypedArray styledAttributes = context.obtainStyledAttributes(null, viewAttr, 0, 0); TypedArray styledAttributes = context.obtainStyledAttributes(null, viewAttr, 0, 0);
spacingAdd = styledAttributes.getDimensionPixelSize(0, 0); spacingAdd = styledAttributes.getDimensionPixelSize(0, 0);

View File

@ -13,7 +13,10 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.google.android.exoplayer2.text; package com.google.android.exoplayer2.ui;
import com.google.android.exoplayer2.text.CaptionStyleCompat;
import com.google.android.exoplayer2.text.Cue;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
@ -28,7 +31,7 @@ import java.util.List;
/** /**
* A view for rendering rich-formatted captions. * A view for rendering rich-formatted captions.
*/ */
public final class SubtitleLayout extends View { public final class SubtitleView extends View {
/** /**
* The default fractional text size. * The default fractional text size.
@ -49,7 +52,7 @@ public final class SubtitleLayout extends View {
private static final int FRACTIONAL_IGNORE_PADDING = 1; private static final int FRACTIONAL_IGNORE_PADDING = 1;
private static final int ABSOLUTE = 2; private static final int ABSOLUTE = 2;
private final List<CuePainter> painters; private final List<SubtitleCuePainter> painters;
private List<Cue> cues; private List<Cue> cues;
private int textSizeType; private int textSizeType;
@ -58,11 +61,11 @@ public final class SubtitleLayout extends View {
private CaptionStyleCompat style; private CaptionStyleCompat style;
private float bottomPaddingFraction; private float bottomPaddingFraction;
public SubtitleLayout(Context context) { public SubtitleView(Context context) {
this(context, null); this(context, null);
} }
public SubtitleLayout(Context context, AttributeSet attrs) { public SubtitleView(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
painters = new ArrayList<>(); painters = new ArrayList<>();
textSizeType = FRACTIONAL; textSizeType = FRACTIONAL;
@ -85,7 +88,7 @@ public final class SubtitleLayout extends View {
// Ensure we have sufficient painters. // Ensure we have sufficient painters.
int cueCount = (cues == null) ? 0 : cues.size(); int cueCount = (cues == null) ? 0 : cues.size();
while (painters.size() < cueCount) { while (painters.size() < cueCount) {
painters.add(new CuePainter(getContext())); painters.add(new SubtitleCuePainter(getContext()));
} }
// Invalidate to trigger drawing. // Invalidate to trigger drawing.
invalidate(); invalidate();