mirror of
https://github.com/androidx/media.git
synced 2025-05-09 00:20:45 +08:00
Consistent Javadoc for text package
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=128160177
This commit is contained in:
parent
f0b73e5d5b
commit
ba0a4235a0
@ -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)
|
||||||
|
@ -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"/>
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
|
@ -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.
|
||||||
|
@ -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}.
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
*
|
*
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
@ -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);
|
||||||
|
@ -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() {
|
||||||
|
@ -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
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
@ -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();
|
||||||
|
@ -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 &lt: and &gt; of a start or end tag.
|
* @param tagExpression Characters between &lt: and &gt; of a start or end tag.
|
||||||
* @return The name of tag.
|
* @return The name of tag.
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
@ -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();
|
Loading…
x
Reference in New Issue
Block a user