diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/SubtitleDecoderFactory.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/SubtitleDecoderFactory.java
index 3b545da21f..2ebd09a0da 100644
--- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/SubtitleDecoderFactory.java
+++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/SubtitleDecoderFactory.java
@@ -24,6 +24,7 @@ import androidx.media3.extractor.text.SubtitleDecoder;
import androidx.media3.extractor.text.SubtitleParser;
import androidx.media3.extractor.text.cea.Cea608Decoder;
import androidx.media3.extractor.text.cea.Cea708Decoder;
+import androidx.media3.extractor.text.ttml.TtmlDecoder;
import java.util.Objects;
/** A factory for {@link SubtitleDecoder} instances. */
@@ -54,6 +55,7 @@ public interface SubtitleDecoderFactory {
*
Supports formats supported by {@link DefaultSubtitleParserFactory} as well as the following:
*
*
+ * - TTML ({@link TtmlDecoder})
*
- Cea608 ({@link Cea608Decoder})
*
- Cea708 ({@link Cea708Decoder})
*
- Exoplayer Cues ({@link ExoplayerCuesDecoder})
@@ -68,6 +70,7 @@ public interface SubtitleDecoderFactory {
public boolean supportsFormat(Format format) {
@Nullable String mimeType = format.sampleMimeType;
return delegate.supportsFormat(format)
+ || Objects.equals(mimeType, MimeTypes.APPLICATION_TTML)
|| Objects.equals(mimeType, MimeTypes.APPLICATION_CEA608)
|| Objects.equals(mimeType, MimeTypes.APPLICATION_MP4CEA608)
|| Objects.equals(mimeType, MimeTypes.APPLICATION_CEA708)
@@ -84,6 +87,8 @@ public interface SubtitleDecoderFactory {
@Nullable String mimeType = format.sampleMimeType;
if (mimeType != null) {
switch (mimeType) {
+ case MimeTypes.APPLICATION_TTML:
+ return new TtmlDecoder();
case MimeTypes.APPLICATION_CEA608:
case MimeTypes.APPLICATION_MP4CEA608:
return new Cea608Decoder(
diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/text/DefaultSubtitleParserFactory.java b/libraries/extractor/src/main/java/androidx/media3/extractor/text/DefaultSubtitleParserFactory.java
index 1d3db619eb..0c2c80c799 100644
--- a/libraries/extractor/src/main/java/androidx/media3/extractor/text/DefaultSubtitleParserFactory.java
+++ b/libraries/extractor/src/main/java/androidx/media3/extractor/text/DefaultSubtitleParserFactory.java
@@ -23,7 +23,6 @@ import androidx.media3.extractor.text.dvb.DvbParser;
import androidx.media3.extractor.text.pgs.PgsParser;
import androidx.media3.extractor.text.ssa.SsaParser;
import androidx.media3.extractor.text.subrip.SubripParser;
-import androidx.media3.extractor.text.ttml.TtmlParser;
import androidx.media3.extractor.text.tx3g.Tx3gParser;
import androidx.media3.extractor.text.webvtt.Mp4WebvttParser;
import androidx.media3.extractor.text.webvtt.WebvttParser;
@@ -42,7 +41,6 @@ import java.util.Objects;
*
- TX3G ({@link Tx3gParser})
*
- PGS ({@link PgsParser})
*
- DVB ({@link DvbParser})
- *
- TTML ({@link TtmlParser})
*
*/
@UnstableApi
@@ -57,8 +55,7 @@ public final class DefaultSubtitleParserFactory implements SubtitleParser.Factor
|| Objects.equals(mimeType, MimeTypes.APPLICATION_SUBRIP)
|| Objects.equals(mimeType, MimeTypes.APPLICATION_TX3G)
|| Objects.equals(mimeType, MimeTypes.APPLICATION_PGS)
- || Objects.equals(mimeType, MimeTypes.APPLICATION_DVBSUBS)
- || Objects.equals(mimeType, MimeTypes.APPLICATION_TTML);
+ || Objects.equals(mimeType, MimeTypes.APPLICATION_DVBSUBS);
}
@Override
@@ -80,8 +77,6 @@ public final class DefaultSubtitleParserFactory implements SubtitleParser.Factor
return new PgsParser();
case MimeTypes.APPLICATION_DVBSUBS:
return new DvbParser(format.initializationData);
- case MimeTypes.APPLICATION_TTML:
- return new TtmlParser();
default:
break;
}
diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/text/ttml/TtmlParser.java b/libraries/extractor/src/main/java/androidx/media3/extractor/text/ttml/TtmlDecoder.java
similarity index 97%
rename from libraries/extractor/src/main/java/androidx/media3/extractor/text/ttml/TtmlParser.java
rename to libraries/extractor/src/main/java/androidx/media3/extractor/text/ttml/TtmlDecoder.java
index ab8c0ea43f..f9dea101f1 100644
--- a/libraries/extractor/src/main/java/androidx/media3/extractor/text/ttml/TtmlParser.java
+++ b/libraries/extractor/src/main/java/androidx/media3/extractor/text/ttml/TtmlDecoder.java
@@ -15,8 +15,6 @@
*/
package androidx.media3.extractor.text.ttml;
-import static androidx.media3.common.util.Assertions.checkArgument;
-import static androidx.media3.common.util.Assertions.checkNotNull;
import static java.lang.Math.max;
import static java.lang.Math.min;
@@ -31,12 +29,10 @@ import androidx.media3.common.util.Log;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util;
import androidx.media3.common.util.XmlPullParserUtil;
-import androidx.media3.extractor.text.CuesWithTiming;
import androidx.media3.extractor.text.SimpleSubtitleDecoder;
+import androidx.media3.extractor.text.Subtitle;
import androidx.media3.extractor.text.SubtitleDecoderException;
-import androidx.media3.extractor.text.SubtitleParser;
import com.google.common.base.Ascii;
-import com.google.common.collect.ImmutableList;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayDeque;
@@ -72,9 +68,9 @@ import org.xmlpull.v1.XmlPullParserFactory;
* See the TTML specification
*/
@UnstableApi
-public final class TtmlParser implements SubtitleParser {
+public final class TtmlDecoder extends SimpleSubtitleDecoder {
- private static final String TAG = "TtmlParser";
+ private static final String TAG = "TtmlDecoder";
private static final String TTP = "http://www.w3.org/ns/ttml#parameter";
@@ -108,7 +104,8 @@ public final class TtmlParser implements SubtitleParser {
private final XmlPullParserFactory xmlParserFactory;
- public TtmlParser() {
+ public TtmlDecoder() {
+ super("TtmlDecoder");
try {
xmlParserFactory = XmlPullParserFactory.newInstance();
xmlParserFactory.setNamespaceAware(true);
@@ -117,16 +114,16 @@ public final class TtmlParser implements SubtitleParser {
}
}
- @Nullable
@Override
- public ImmutableList parse(byte[] data, int offset, int length) {
+ protected Subtitle decode(byte[] data, int length, boolean reset)
+ throws SubtitleDecoderException {
try {
XmlPullParser xmlParser = xmlParserFactory.newPullParser();
Map globalStyles = new HashMap<>();
Map regionMap = new HashMap<>();
Map imageMap = new HashMap<>();
regionMap.put(TtmlNode.ANONYMOUS_REGION_ID, new TtmlRegion(TtmlNode.ANONYMOUS_REGION_ID));
- ByteArrayInputStream inputStream = new ByteArrayInputStream(data, offset, length);
+ ByteArrayInputStream inputStream = new ByteArrayInputStream(data, 0, length);
xmlParser.setInput(inputStream, null);
@Nullable TtmlSubtitle ttmlSubtitle = null;
ArrayDeque nodeStack = new ArrayDeque<>();
@@ -183,15 +180,20 @@ public final class TtmlParser implements SubtitleParser {
xmlParser.next();
eventType = xmlParser.getEventType();
}
- return checkNotNull(ttmlSubtitle).toCuesWithTimingList();
+ if (ttmlSubtitle != null) {
+ return ttmlSubtitle;
+ } else {
+ throw new SubtitleDecoderException("No TTML subtitles found");
+ }
} catch (XmlPullParserException xppe) {
- throw new IllegalStateException("Unable to decode source", xppe);
+ throw new SubtitleDecoderException("Unable to decode source", xppe);
} catch (IOException e) {
throw new IllegalStateException("Unexpected error when reading input.", e);
}
}
- private static FrameAndTickRate parseFrameAndTickRates(XmlPullParser xmlParser) {
+ private static FrameAndTickRate parseFrameAndTickRates(XmlPullParser xmlParser)
+ throws SubtitleDecoderException {
int frameRate = DEFAULT_FRAME_RATE;
String frameRateString = xmlParser.getAttributeValue(TTP, "frameRate");
if (frameRateString != null) {
@@ -202,7 +204,9 @@ public final class TtmlParser implements SubtitleParser {
String frameRateMultiplierString = xmlParser.getAttributeValue(TTP, "frameRateMultiplier");
if (frameRateMultiplierString != null) {
String[] parts = Util.split(frameRateMultiplierString, " ");
- checkArgument(parts.length == 2, "frameRateMultiplier doesn't have 2 parts");
+ if (parts.length != 2) {
+ throw new SubtitleDecoderException("frameRateMultiplier doesn't have 2 parts");
+ }
float numerator = Integer.parseInt(parts[0]);
float denominator = Integer.parseInt(parts[1]);
frameRateMultiplier = numerator / denominator;
@@ -223,7 +227,7 @@ public final class TtmlParser implements SubtitleParser {
}
private static CellResolution parseCellResolution(
- XmlPullParser xmlParser, CellResolution defaultValue) {
+ XmlPullParser xmlParser, CellResolution defaultValue) throws SubtitleDecoderException {
String cellResolution = xmlParser.getAttributeValue(TTP, "cellResolution");
if (cellResolution == null) {
return defaultValue;
@@ -237,7 +241,9 @@ public final class TtmlParser implements SubtitleParser {
try {
int columns = Integer.parseInt(Assertions.checkNotNull(cellResolutionMatcher.group(1)));
int rows = Integer.parseInt(Assertions.checkNotNull(cellResolutionMatcher.group(2)));
- checkArgument(columns != 0 && rows != 0, "Invalid cell resolution " + columns + " " + rows);
+ if (columns == 0 || rows == 0) {
+ throw new SubtitleDecoderException("Invalid cell resolution " + columns + " " + rows);
+ }
return new CellResolution(columns, rows);
} catch (NumberFormatException e) {
Log.w(TAG, "Ignoring malformed cell resolution: " + cellResolution);
diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/text/DelegatingSubtitleDecoderTtmlParserTest.java b/libraries/extractor/src/test/java/androidx/media3/extractor/text/ttml/TtmlDecoderTest.java
similarity index 88%
rename from libraries/exoplayer/src/test/java/androidx/media3/exoplayer/text/DelegatingSubtitleDecoderTtmlParserTest.java
rename to libraries/extractor/src/test/java/androidx/media3/extractor/text/ttml/TtmlDecoderTest.java
index 0b69807a89..02092ef714 100644
--- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/text/DelegatingSubtitleDecoderTtmlParserTest.java
+++ b/libraries/extractor/src/test/java/androidx/media3/extractor/text/ttml/TtmlDecoderTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package androidx.media3.exoplayer.text;
+package androidx.media3.extractor.text.ttml;
import static androidx.media3.test.utils.truth.SpannedSubject.assertThat;
import static com.google.common.truth.Truth.assertThat;
@@ -27,7 +27,7 @@ import androidx.media3.common.util.Assertions;
import androidx.media3.common.util.ColorParser;
import androidx.media3.extractor.text.CuesWithTiming;
import androidx.media3.extractor.text.Subtitle;
-import androidx.media3.extractor.text.ttml.TtmlParser;
+import androidx.media3.extractor.text.SubtitleDecoderException;
import androidx.media3.test.utils.TestUtil;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -37,9 +37,9 @@ import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
-/** Unit test for {@link TtmlParser}. */
+/** Unit test for {@link TtmlDecoder}. */
@RunWith(AndroidJUnit4.class)
-public final class DelegatingSubtitleDecoderTtmlParserTest {
+public final class TtmlDecoderTest {
private static final String INLINE_ATTRIBUTES_TTML_FILE =
"media/ttml/inline_style_attributes.xml";
@@ -73,8 +73,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
private static final String SHEAR_FILE = "media/ttml/shear.xml";
@Test
- public void inlineAttributes() throws IOException {
- Subtitle subtitle = getSubtitle(INLINE_ATTRIBUTES_TTML_FILE);
+ public void inlineAttributes() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(INLINE_ATTRIBUTES_TTML_FILE);
assertThat(subtitle.getEventTimeCount()).isEqualTo(4);
@@ -92,8 +92,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void inheritInlineAttributes() throws IOException {
- Subtitle subtitle = getSubtitle(INLINE_ATTRIBUTES_TTML_FILE);
+ public void inheritInlineAttributes() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(INLINE_ATTRIBUTES_TTML_FILE);
assertThat(subtitle.getEventTimeCount()).isEqualTo(4);
@@ -118,8 +118,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
// KitKat Color:
// https://github.com/android/platform_frameworks_base/blob/kitkat-mr2.2-release/graphics/java/android/graphics/Color.java#L414
@Test
- public void lime() throws IOException {
- Subtitle subtitle = getSubtitle(INLINE_ATTRIBUTES_TTML_FILE);
+ public void lime() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(INLINE_ATTRIBUTES_TTML_FILE);
assertThat(subtitle.getEventTimeCount()).isEqualTo(4);
@@ -133,8 +133,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void inheritGlobalStyle() throws IOException {
- Subtitle subtitle = getSubtitle(INHERIT_STYLE_TTML_FILE);
+ public void inheritGlobalStyle() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(INHERIT_STYLE_TTML_FILE);
assertThat(subtitle.getEventTimeCount()).isEqualTo(2);
@@ -148,8 +148,9 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void inheritGlobalStyleOverriddenByInlineAttributes() throws IOException {
- Subtitle subtitle = getSubtitle(INHERIT_STYLE_OVERRIDE_TTML_FILE);
+ public void inheritGlobalStyleOverriddenByInlineAttributes()
+ throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(INHERIT_STYLE_OVERRIDE_TTML_FILE);
assertThat(subtitle.getEventTimeCount()).isEqualTo(4);
@@ -181,8 +182,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void inheritGlobalAndParent() throws IOException {
- Subtitle subtitle = getSubtitle(INHERIT_GLOBAL_AND_PARENT_TTML_FILE);
+ public void inheritGlobalAndParent() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(INHERIT_GLOBAL_AND_PARENT_TTML_FILE);
assertThat(subtitle.getEventTimeCount()).isEqualTo(4);
@@ -214,8 +215,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void inheritMultipleStyles() throws IOException {
- Subtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE);
+ public void inheritMultipleStyles() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE);
assertThat(subtitle.getEventTimeCount()).isEqualTo(12);
@@ -229,8 +230,9 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void inheritMultipleStylesWithoutLocalAttributes() throws IOException {
- Subtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE);
+ public void inheritMultipleStylesWithoutLocalAttributes()
+ throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE);
assertThat(subtitle.getEventTimeCount()).isEqualTo(12);
@@ -250,8 +252,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void mergeMultipleStylesWithParentStyle() throws IOException {
- Subtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE);
+ public void mergeMultipleStylesWithParentStyle() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE);
assertThat(subtitle.getEventTimeCount()).isEqualTo(12);
@@ -272,8 +274,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void multipleRegions() throws IOException {
- Subtitle subtitle = getSubtitle(MULTIPLE_REGIONS_TTML_FILE);
+ public void multipleRegions() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(MULTIPLE_REGIONS_TTML_FILE);
List cues = subtitle.getCues(1_000_000);
assertThat(cues).hasSize(2);
@@ -321,8 +323,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void emptyStyleAttribute() throws IOException {
- Subtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE);
+ public void emptyStyleAttribute() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE);
assertThat(subtitle.getEventTimeCount()).isEqualTo(12);
@@ -333,8 +335,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void nonexistingStyleId() throws IOException {
- Subtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE);
+ public void nonexistingStyleId() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE);
assertThat(subtitle.getEventTimeCount()).isEqualTo(12);
@@ -345,8 +347,9 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void nonExistingAndExistingStyleIdWithRedundantSpaces() throws IOException {
- Subtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE);
+ public void nonExistingAndExistingStyleIdWithRedundantSpaces()
+ throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE);
assertThat(subtitle.getEventTimeCount()).isEqualTo(12);
@@ -356,8 +359,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void multipleChaining() throws IOException {
- Subtitle subtitle = getSubtitle(CHAIN_MULTIPLE_STYLES_TTML_FILE);
+ public void multipleChaining() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(CHAIN_MULTIPLE_STYLES_TTML_FILE);
assertThat(subtitle.getEventTimeCount()).isEqualTo(4);
@@ -380,8 +383,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void noUnderline() throws IOException {
- Subtitle subtitle = getSubtitle(NO_UNDERLINE_LINETHROUGH_TTML_FILE);
+ public void noUnderline() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(NO_UNDERLINE_LINETHROUGH_TTML_FILE);
assertThat(subtitle.getEventTimeCount()).isEqualTo(4);
@@ -392,8 +395,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void noLinethrough() throws IOException {
- Subtitle subtitle = getSubtitle(NO_UNDERLINE_LINETHROUGH_TTML_FILE);
+ public void noLinethrough() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(NO_UNDERLINE_LINETHROUGH_TTML_FILE);
assertThat(subtitle.getEventTimeCount()).isEqualTo(4);
@@ -404,8 +407,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void fontSizeSpans() throws IOException {
- Subtitle subtitle = getSubtitle(FONT_SIZE_TTML_FILE);
+ public void fontSizeSpans() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(FONT_SIZE_TTML_FILE);
assertThat(subtitle.getEventTimeCount()).isEqualTo(10);
@@ -431,8 +434,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void fontSizeWithMissingUnitIsIgnored() throws IOException {
- Subtitle subtitle = getSubtitle(FONT_SIZE_MISSING_UNIT_TTML_FILE);
+ public void fontSizeWithMissingUnitIsIgnored() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(FONT_SIZE_MISSING_UNIT_TTML_FILE);
assertThat(subtitle.getEventTimeCount()).isEqualTo(2);
@@ -443,8 +446,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void fontSizeWithInvalidValueIsIgnored() throws IOException {
- Subtitle subtitle = getSubtitle(FONT_SIZE_INVALID_TTML_FILE);
+ public void fontSizeWithInvalidValueIsIgnored() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(FONT_SIZE_INVALID_TTML_FILE);
assertThat(subtitle.getEventTimeCount()).isEqualTo(6);
@@ -465,8 +468,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void fontSizeWithEmptyValueIsIgnored() throws IOException {
- Subtitle subtitle = getSubtitle(FONT_SIZE_EMPTY_TTML_FILE);
+ public void fontSizeWithEmptyValueIsIgnored() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(FONT_SIZE_EMPTY_TTML_FILE);
assertThat(subtitle.getEventTimeCount()).isEqualTo(2);
@@ -477,8 +480,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void frameRate() throws IOException {
- Subtitle subtitle = getSubtitle(FRAME_RATE_TTML_FILE);
+ public void frameRate() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(FRAME_RATE_TTML_FILE);
assertThat(subtitle.getEventTimeCount()).isEqualTo(4);
assertThat(subtitle.getEventTime(0)).isEqualTo(1_000_000);
@@ -488,8 +491,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void bitmapPercentageRegion() throws IOException {
- Subtitle subtitle = getSubtitle(BITMAP_REGION_FILE);
+ public void bitmapPercentageRegion() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(BITMAP_REGION_FILE);
Cue cue = getOnlyCueAtTimeUs(subtitle, 1_000_000);
assertThat(cue.text).isNull();
@@ -517,8 +520,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void bitmapPixelRegion() throws IOException {
- Subtitle subtitle = getSubtitle(BITMAP_PIXEL_REGION_FILE);
+ public void bitmapPixelRegion() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(BITMAP_PIXEL_REGION_FILE);
Cue cue = getOnlyCueAtTimeUs(subtitle, 1_000_000);
assertThat(cue.text).isNull();
@@ -538,8 +541,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void bitmapUnsupportedRegion() throws IOException {
- Subtitle subtitle = getSubtitle(BITMAP_UNSUPPORTED_REGION_FILE);
+ public void bitmapUnsupportedRegion() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(BITMAP_UNSUPPORTED_REGION_FILE);
Cue cue = getOnlyCueAtTimeUs(subtitle, 1_000_000);
assertThat(cue.text).isNull();
@@ -559,8 +562,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void textAlign() throws IOException {
- Subtitle subtitle = getSubtitle(TEXT_ALIGN_FILE);
+ public void textAlign() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(TEXT_ALIGN_FILE);
Cue firstCue = getOnlyCueAtTimeUs(subtitle, 10_000_000);
assertThat(firstCue.text.toString()).isEqualTo("Start alignment");
@@ -600,8 +603,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void multiRowAlign() throws IOException {
- Subtitle subtitle = getSubtitle(MULTI_ROW_ALIGN_FILE);
+ public void multiRowAlign() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(MULTI_ROW_ALIGN_FILE);
Cue firstCue = getOnlyCueAtTimeUs(subtitle, 10_000_000);
assertThat(firstCue.multiRowAlignment).isEqualTo(Layout.Alignment.ALIGN_NORMAL);
@@ -626,8 +629,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void verticalText() throws IOException {
- Subtitle subtitle = getSubtitle(VERTICAL_TEXT_FILE);
+ public void verticalText() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(VERTICAL_TEXT_FILE);
Cue firstCue = getOnlyCueAtTimeUs(subtitle, 10_000_000);
assertThat(firstCue.verticalType).isEqualTo(Cue.VERTICAL_TYPE_RL);
@@ -640,8 +643,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void textCombine() throws IOException {
- Subtitle subtitle = getSubtitle(TEXT_COMBINE_FILE);
+ public void textCombine() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(TEXT_COMBINE_FILE);
Spanned firstCue = getOnlyCueTextAtTimeUs(subtitle, 10_000_000);
assertThat(firstCue)
@@ -658,8 +661,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void rubies() throws IOException {
- Subtitle subtitle = getSubtitle(RUBIES_FILE);
+ public void rubies() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(RUBIES_FILE);
Spanned firstCue = getOnlyCueTextAtTimeUs(subtitle, 10_000_000);
assertThat(firstCue.toString()).isEqualTo("Cue with annotated text.");
@@ -678,9 +681,7 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
Spanned thirdCue = getOnlyCueTextAtTimeUs(subtitle, 30_000_000);
assertThat(thirdCue.toString()).isEqualTo("Cue with annotated text.");
- assertThat(thirdCue)
- .hasRubySpanBetween("Cue with ".length(), "Cue with annotated".length())
- .withTextAndPosition("rubies", TextAnnotation.POSITION_UNKNOWN);
+ assertThat(thirdCue).hasRubySpanBetween("Cue with ".length(), "Cue with annotated".length());
Spanned fourthCue = getOnlyCueTextAtTimeUs(subtitle, 40_000_000);
assertThat(fourthCue.toString()).isEqualTo("Cue with annotated text.");
@@ -708,8 +709,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void textEmphasis() throws IOException {
- Subtitle subtitle = getSubtitle(TEXT_EMPHASIS_FILE);
+ public void textEmphasis() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(TEXT_EMPHASIS_FILE);
Spanned firstCue = getOnlyCueTextAtTimeUs(subtitle, 10_000_000);
assertThat(firstCue)
@@ -848,8 +849,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void shear() throws IOException {
- Subtitle subtitle = getSubtitle(SHEAR_FILE);
+ public void shear() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(SHEAR_FILE);
Cue firstCue = getOnlyCueAtTimeUs(subtitle, 10_000_000);
assertThat(firstCue.shearDegrees).isZero();
@@ -877,8 +878,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
}
@Test
- public void toCuesWithTimingConversion() throws IOException {
- Subtitle subtitle = getSubtitle(INLINE_ATTRIBUTES_TTML_FILE);
+ public void toCuesWithTimingConversion() throws IOException, SubtitleDecoderException {
+ TtmlSubtitle subtitle = getSubtitle(INLINE_ATTRIBUTES_TTML_FILE);
ImmutableList cuesWithTimingsList = subtitle.toCuesWithTimingList();
assertThat(subtitle.getEventTimeCount()).isEqualTo(4);
@@ -921,10 +922,10 @@ public final class DelegatingSubtitleDecoderTtmlParserTest {
return cues.get(0);
}
- private static Subtitle getSubtitle(String file) throws IOException {
- DelegatingSubtitleDecoder ttmlDecoder =
- new DelegatingSubtitleDecoder("TtmlParserDecoder", new TtmlParser());
+ private static TtmlSubtitle getSubtitle(String file)
+ throws IOException, SubtitleDecoderException {
+ TtmlDecoder ttmlDecoder = new TtmlDecoder();
byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), file);
- return ttmlDecoder.decode(bytes, bytes.length, false);
+ return (TtmlSubtitle) ttmlDecoder.decode(bytes, bytes.length, false);
}
}
diff --git a/libraries/extractor/src/test/java/androidx/media3/extractor/text/ttml/TtmlParserTest.java b/libraries/extractor/src/test/java/androidx/media3/extractor/text/ttml/TtmlParserTest.java
deleted file mode 100644
index 14b883756e..0000000000
--- a/libraries/extractor/src/test/java/androidx/media3/extractor/text/ttml/TtmlParserTest.java
+++ /dev/null
@@ -1,920 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package androidx.media3.extractor.text.ttml;
-
-import static androidx.media3.test.utils.truth.SpannedSubject.assertThat;
-import static com.google.common.truth.Truth.assertThat;
-
-import android.text.Layout;
-import android.text.Spanned;
-import androidx.media3.common.text.Cue;
-import androidx.media3.common.text.TextAnnotation;
-import androidx.media3.common.text.TextEmphasisSpan;
-import androidx.media3.common.util.Assertions;
-import androidx.media3.common.util.ColorParser;
-import androidx.media3.extractor.text.CuesWithTiming;
-import androidx.media3.test.utils.TestUtil;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/** Unit test for {@link TtmlParser}. */
-@RunWith(AndroidJUnit4.class)
-public final class TtmlParserTest {
-
- private static final String INLINE_ATTRIBUTES_TTML_FILE =
- "media/ttml/inline_style_attributes.xml";
- private static final String INHERIT_STYLE_TTML_FILE = "media/ttml/inherit_style.xml";
- private static final String INHERIT_STYLE_OVERRIDE_TTML_FILE =
- "media/ttml/inherit_and_override_style.xml";
- private static final String INHERIT_GLOBAL_AND_PARENT_TTML_FILE =
- "media/ttml/inherit_global_and_parent.xml";
- private static final String INHERIT_MULTIPLE_STYLES_TTML_FILE =
- "media/ttml/inherit_multiple_styles.xml";
- private static final String CHAIN_MULTIPLE_STYLES_TTML_FILE =
- "media/ttml/chain_multiple_styles.xml";
- private static final String MULTIPLE_REGIONS_TTML_FILE = "media/ttml/multiple_regions.xml";
- private static final String NO_UNDERLINE_LINETHROUGH_TTML_FILE =
- "media/ttml/no_underline_linethrough.xml";
- private static final String FONT_SIZE_TTML_FILE = "media/ttml/font_size.xml";
- private static final String FONT_SIZE_MISSING_UNIT_TTML_FILE = "media/ttml/font_size_no_unit.xml";
- private static final String FONT_SIZE_INVALID_TTML_FILE = "media/ttml/font_size_invalid.xml";
- private static final String FONT_SIZE_EMPTY_TTML_FILE = "media/ttml/font_size_empty.xml";
- private static final String FRAME_RATE_TTML_FILE = "media/ttml/frame_rate.xml";
- private static final String BITMAP_REGION_FILE = "media/ttml/bitmap_percentage_region.xml";
- private static final String BITMAP_PIXEL_REGION_FILE = "media/ttml/bitmap_pixel_region.xml";
- private static final String BITMAP_UNSUPPORTED_REGION_FILE =
- "media/ttml/bitmap_unsupported_region.xml";
- private static final String TEXT_ALIGN_FILE = "media/ttml/text_align.xml";
- private static final String MULTI_ROW_ALIGN_FILE = "media/ttml/multi_row_align.xml";
- private static final String VERTICAL_TEXT_FILE = "media/ttml/vertical_text.xml";
- private static final String TEXT_COMBINE_FILE = "media/ttml/text_combine.xml";
- private static final String RUBIES_FILE = "media/ttml/rubies.xml";
- private static final String TEXT_EMPHASIS_FILE = "media/ttml/text_emphasis.xml";
- private static final String SHEAR_FILE = "media/ttml/shear.xml";
-
- @Test
- public void inlineAttributes() throws Exception {
- ImmutableList allCues = getAllCues(INLINE_ATTRIBUTES_TTML_FILE);
-
- assertThat(allCues).hasSize(2);
-
- Spanned spanned = getOnlyCueTextAtIndex(allCues, 0);
- assertThat(spanned.toString()).isEqualTo("text 1");
- assertThat(spanned).hasTypefaceSpanBetween(0, spanned.length()).withFamily("serif");
- assertThat(spanned).hasBoldItalicSpanBetween(0, spanned.length());
- assertThat(spanned).hasUnderlineSpanBetween(0, spanned.length());
- assertThat(spanned)
- .hasBackgroundColorSpanBetween(0, spanned.length())
- .withColor(ColorParser.parseTtmlColor("blue"));
- assertThat(spanned)
- .hasForegroundColorSpanBetween(0, spanned.length())
- .withColor(ColorParser.parseTtmlColor("yellow"));
- }
-
- @Test
- public void inheritInlineAttributes() throws Exception {
- ImmutableList allCues = getAllCues(INLINE_ATTRIBUTES_TTML_FILE);
-
- assertThat(allCues).hasSize(2);
-
- Spanned spanned = getOnlyCueTextAtIndex(allCues, 1);
- assertThat(spanned.toString()).isEqualTo("text 2");
- assertThat(spanned).hasTypefaceSpanBetween(0, spanned.length()).withFamily("sansSerif");
- assertThat(spanned).hasItalicSpanBetween(0, spanned.length());
- assertThat(spanned).hasStrikethroughSpanBetween(0, spanned.length());
- assertThat(spanned).hasBackgroundColorSpanBetween(0, spanned.length()).withColor(0xFF00FFFF);
- assertThat(spanned)
- .hasForegroundColorSpanBetween(0, spanned.length())
- .withColor(ColorParser.parseTtmlColor("lime"));
- }
-
- /**
- * Regression test for devices on JellyBean where some named colors are not correctly defined on
- * framework level. Tests that lime resolves to #FF00FF00
not #00FF00
- *
.
- */
- // JellyBean Color:
- // https://github.com/android/platform_frameworks_base/blob/jb-mr2-release/graphics/java/android/graphics/Color.java#L414
- // KitKat Color:
- // https://github.com/android/platform_frameworks_base/blob/kitkat-mr2.2-release/graphics/java/android/graphics/Color.java#L414
- @Test
- public void lime() throws Exception {
- ImmutableList allCues = getAllCues(INLINE_ATTRIBUTES_TTML_FILE);
-
- assertThat(allCues).hasSize(2);
-
- Spanned spanned = getOnlyCueTextAtIndex(allCues, 1);
- assertThat(spanned.toString()).isEqualTo("text 2");
- assertThat(spanned).hasTypefaceSpanBetween(0, spanned.length()).withFamily("sansSerif");
- assertThat(spanned).hasItalicSpanBetween(0, spanned.length());
- assertThat(spanned).hasStrikethroughSpanBetween(0, spanned.length());
- assertThat(spanned).hasBackgroundColorSpanBetween(0, spanned.length()).withColor(0xFF00FFFF);
- assertThat(spanned).hasForegroundColorSpanBetween(0, spanned.length()).withColor(0xFF00FF00);
- }
-
- @Test
- public void inheritGlobalStyle() throws Exception {
- ImmutableList allCues = getAllCues(INHERIT_STYLE_TTML_FILE);
-
- assertThat(allCues).hasSize(1);
-
- Spanned spanned = getOnlyCueTextAtIndex(allCues, 0);
- assertThat(spanned.toString()).isEqualTo("text 1");
- assertThat(spanned).hasTypefaceSpanBetween(0, spanned.length()).withFamily("serif");
- assertThat(spanned).hasBoldItalicSpanBetween(0, spanned.length());
- assertThat(spanned).hasUnderlineSpanBetween(0, spanned.length());
- assertThat(spanned).hasBackgroundColorSpanBetween(0, spanned.length()).withColor(0xFF0000FF);
- assertThat(spanned).hasForegroundColorSpanBetween(0, spanned.length()).withColor(0xFFFFFF00);
- }
-
- @Test
- public void inheritGlobalStyleOverriddenByInlineAttributes() throws Exception {
- ImmutableList allCues = getAllCues(INHERIT_STYLE_OVERRIDE_TTML_FILE);
-
- assertThat(allCues).hasSize(2);
-
- Spanned firstCueText = getOnlyCueTextAtIndex(allCues, 0);
- assertThat(firstCueText.toString()).isEqualTo("text 1");
- assertThat(firstCueText).hasTypefaceSpanBetween(0, firstCueText.length()).withFamily("serif");
- assertThat(firstCueText).hasBoldItalicSpanBetween(0, firstCueText.length());
- assertThat(firstCueText).hasUnderlineSpanBetween(0, firstCueText.length());
- assertThat(firstCueText)
- .hasBackgroundColorSpanBetween(0, firstCueText.length())
- .withColor(0xFF0000FF);
- assertThat(firstCueText)
- .hasForegroundColorSpanBetween(0, firstCueText.length())
- .withColor(0xFFFFFF00);
-
- Spanned secondCueText = getOnlyCueTextAtIndex(allCues, 1);
- assertThat(secondCueText.toString()).isEqualTo("text 2");
- assertThat(secondCueText)
- .hasTypefaceSpanBetween(0, secondCueText.length())
- .withFamily("sansSerif");
- assertThat(secondCueText).hasItalicSpanBetween(0, secondCueText.length());
- assertThat(secondCueText).hasUnderlineSpanBetween(0, secondCueText.length());
- assertThat(secondCueText)
- .hasBackgroundColorSpanBetween(0, secondCueText.length())
- .withColor(0xFFFF0000);
- assertThat(secondCueText)
- .hasForegroundColorSpanBetween(0, secondCueText.length())
- .withColor(0xFFFFFF00);
- }
-
- @Test
- public void inheritGlobalAndParent() throws Exception {
- ImmutableList allCues = getAllCues(INHERIT_GLOBAL_AND_PARENT_TTML_FILE);
-
- assertThat(allCues).hasSize(2);
-
- Spanned firstCueText = getOnlyCueTextAtIndex(allCues, 0);
- assertThat(firstCueText.toString()).isEqualTo("text 1");
- assertThat(firstCueText)
- .hasTypefaceSpanBetween(0, firstCueText.length())
- .withFamily("sansSerif");
- assertThat(firstCueText).hasStrikethroughSpanBetween(0, firstCueText.length());
- assertThat(firstCueText)
- .hasBackgroundColorSpanBetween(0, firstCueText.length())
- .withColor(0xFFFF0000);
- assertThat(firstCueText)
- .hasForegroundColorSpanBetween(0, firstCueText.length())
- .withColor(ColorParser.parseTtmlColor("lime"));
-
- Spanned secondCueText = getOnlyCueTextAtIndex(allCues, 1);
- assertThat(secondCueText.toString()).isEqualTo("text 2");
- assertThat(secondCueText).hasTypefaceSpanBetween(0, secondCueText.length()).withFamily("serif");
- assertThat(secondCueText).hasBoldItalicSpanBetween(0, secondCueText.length());
- assertThat(secondCueText).hasUnderlineSpanBetween(0, secondCueText.length());
- assertThat(secondCueText).hasStrikethroughSpanBetween(0, secondCueText.length());
- assertThat(secondCueText)
- .hasBackgroundColorSpanBetween(0, secondCueText.length())
- .withColor(0xFF0000FF);
- assertThat(secondCueText)
- .hasForegroundColorSpanBetween(0, secondCueText.length())
- .withColor(0xFFFFFF00);
- }
-
- @Test
- public void inheritMultipleStyles() throws Exception {
- ImmutableList allCues = getAllCues(INHERIT_MULTIPLE_STYLES_TTML_FILE);
-
- assertThat(allCues).hasSize(6);
-
- Spanned spanned = getOnlyCueTextAtIndex(allCues, 0);
- assertThat(spanned.toString()).isEqualTo("text 1");
- assertThat(spanned).hasTypefaceSpanBetween(0, spanned.length()).withFamily("sansSerif");
- assertThat(spanned).hasBoldItalicSpanBetween(0, spanned.length());
- assertThat(spanned).hasStrikethroughSpanBetween(0, spanned.length());
- assertThat(spanned).hasBackgroundColorSpanBetween(0, spanned.length()).withColor(0xFF0000FF);
- assertThat(spanned).hasForegroundColorSpanBetween(0, spanned.length()).withColor(0xFFFFFF00);
- }
-
- @Test
- public void inheritMultipleStylesWithoutLocalAttributes() throws Exception {
- ImmutableList allCues = getAllCues(INHERIT_MULTIPLE_STYLES_TTML_FILE);
-
- assertThat(allCues).hasSize(6);
-
- Spanned secondCueText = getOnlyCueTextAtIndex(allCues, 1);
- assertThat(secondCueText.toString()).isEqualTo("text 2");
- assertThat(secondCueText)
- .hasTypefaceSpanBetween(0, secondCueText.length())
- .withFamily("sansSerif");
- assertThat(secondCueText).hasBoldItalicSpanBetween(0, secondCueText.length());
- assertThat(secondCueText).hasStrikethroughSpanBetween(0, secondCueText.length());
- assertThat(secondCueText)
- .hasBackgroundColorSpanBetween(0, secondCueText.length())
- .withColor(0xFF0000FF);
- assertThat(secondCueText)
- .hasForegroundColorSpanBetween(0, secondCueText.length())
- .withColor(0xFF000000);
- }
-
- @Test
- public void mergeMultipleStylesWithParentStyle() throws Exception {
- ImmutableList allCues = getAllCues(INHERIT_MULTIPLE_STYLES_TTML_FILE);
-
- assertThat(allCues).hasSize(6);
-
- Spanned thirdCueText = getOnlyCueTextAtIndex(allCues, 2);
- assertThat(thirdCueText.toString()).isEqualTo("text 2.5");
- assertThat(thirdCueText)
- .hasTypefaceSpanBetween(0, thirdCueText.length())
- .withFamily("sansSerifInline");
- assertThat(thirdCueText).hasItalicSpanBetween(0, thirdCueText.length());
- assertThat(thirdCueText).hasUnderlineSpanBetween(0, thirdCueText.length());
- assertThat(thirdCueText).hasStrikethroughSpanBetween(0, thirdCueText.length());
- assertThat(thirdCueText)
- .hasBackgroundColorSpanBetween(0, thirdCueText.length())
- .withColor(0xFFFF0000);
- assertThat(thirdCueText)
- .hasForegroundColorSpanBetween(0, thirdCueText.length())
- .withColor(0xFFFFFF00);
- }
-
- @Test
- public void multipleRegions() throws Exception {
- ImmutableList allCues = getAllCues(MULTIPLE_REGIONS_TTML_FILE);
-
- assertThat(allCues).hasSize(6);
-
- ImmutableList cues = allCues.get(0).cues;
- assertThat(cues).hasSize(2);
- Cue cue = cues.get(0);
- assertThat(cue.text.toString()).isEqualTo("lorem");
- assertThat(cue.position).isEqualTo(10f / 100f);
- assertThat(cue.line).isEqualTo(10f / 100f);
- assertThat(cue.size).isEqualTo(20f / 100f);
-
- cue = cues.get(1);
- assertThat(cue.text.toString()).isEqualTo("amet");
- assertThat(cue.position).isEqualTo(60f / 100f);
- assertThat(cue.line).isEqualTo(10f / 100f);
- assertThat(cue.size).isEqualTo(20f / 100f);
-
- cue = Iterables.getOnlyElement(allCues.get(1).cues);
- assertThat(cue.text.toString()).isEqualTo("ipsum");
- assertThat(cue.position).isEqualTo(40f / 100f);
- assertThat(cue.line).isEqualTo(40f / 100f);
- assertThat(cue.size).isEqualTo(20f / 100f);
-
- cue = Iterables.getOnlyElement(allCues.get(2).cues);
- assertThat(cue.text.toString()).isEqualTo("dolor");
- assertThat(cue.position).isEqualTo(Cue.DIMEN_UNSET);
- assertThat(cue.line).isEqualTo(Cue.DIMEN_UNSET);
- assertThat(cue.size).isEqualTo(Cue.DIMEN_UNSET);
- // TODO: Should be as below, once https://github.com/google/ExoPlayer/issues/2953 is fixed.
- // assertEquals(10f / 100f, cue.position);
- // assertEquals(80f / 100f, cue.line);
- // assertEquals(1f, cue.size);
-
- cue = Iterables.getOnlyElement(allCues.get(3).cues);
- assertThat(cue.text.toString()).isEqualTo("They first said this");
- assertThat(cue.position).isEqualTo(45f / 100f);
- assertThat(cue.line).isEqualTo(45f / 100f);
- assertThat(cue.size).isEqualTo(35f / 100f);
-
- cue = Iterables.getOnlyElement(allCues.get(4).cues);
- assertThat(cue.text.toString()).isEqualTo("They first said this\nThen this");
-
- cue = Iterables.getOnlyElement(allCues.get(5).cues);
- assertThat(cue.text.toString()).isEqualTo("They first said this\nThen this\nFinally this");
- assertThat(cue.position).isEqualTo(45f / 100f);
- assertThat(cue.line).isEqualTo(45f / 100f);
- }
-
- @Test
- public void emptyStyleAttribute() throws Exception {
- ImmutableList allCues = getAllCues(INHERIT_MULTIPLE_STYLES_TTML_FILE);
-
- assertThat(allCues).hasSize(6);
-
- Spanned spanned = getOnlyCueTextAtIndex(allCues, 3);
-
- assertThat(allCues.get(3).startTimeUs).isEqualTo(40_000_000);
- assertThat(spanned.toString()).isEqualTo("text 3");
- assertThat(spanned).hasNoSpans();
- }
-
- @Test
- public void nonexistingStyleId() throws Exception {
- ImmutableList allCues = getAllCues(INHERIT_MULTIPLE_STYLES_TTML_FILE);
-
- assertThat(allCues).hasSize(6);
-
- Spanned spanned = getOnlyCueTextAtIndex(allCues, 4);
-
- assertThat(allCues.get(4).startTimeUs).isEqualTo(50_000_000);
- assertThat(spanned.toString()).isEqualTo("text 4");
- assertThat(spanned).hasNoSpans();
- }
-
- @Test
- public void nonExistingAndExistingStyleIdWithRedundantSpaces() throws Exception {
- ImmutableList allCues = getAllCues(INHERIT_MULTIPLE_STYLES_TTML_FILE);
-
- assertThat(allCues).hasSize(6);
-
- Spanned spanned = getOnlyCueTextAtIndex(allCues, 5);
-
- assertThat(allCues.get(5).startTimeUs).isEqualTo(60_000_000);
- assertThat(spanned.toString()).isEqualTo("text 5");
- assertThat(spanned).hasBackgroundColorSpanBetween(0, spanned.length()).withColor(0xFFFF0000);
- }
-
- @Test
- public void multipleChaining() throws Exception {
- ImmutableList allCues = getAllCues(CHAIN_MULTIPLE_STYLES_TTML_FILE);
-
- assertThat(allCues).hasSize(2);
-
- Spanned spanned1 = getOnlyCueTextAtIndex(allCues, 0);
- assertThat(spanned1.toString()).isEqualTo("text 1");
- assertThat(spanned1).hasTypefaceSpanBetween(0, spanned1.length()).withFamily("serif");
- assertThat(spanned1).hasBackgroundColorSpanBetween(0, spanned1.length()).withColor(0xFFFF0000);
- assertThat(spanned1).hasForegroundColorSpanBetween(0, spanned1.length()).withColor(0xFF000000);
- assertThat(spanned1).hasBoldItalicSpanBetween(0, spanned1.length());
- assertThat(spanned1).hasStrikethroughSpanBetween(0, spanned1.length());
-
- // only difference: foreground (font) color must be RED
- Spanned spanned2 = getOnlyCueTextAtIndex(allCues, 1);
- assertThat(spanned2.toString()).isEqualTo("text 2");
- assertThat(spanned2).hasTypefaceSpanBetween(0, spanned2.length()).withFamily("serif");
- assertThat(spanned2).hasBackgroundColorSpanBetween(0, spanned2.length()).withColor(0xFFFF0000);
- assertThat(spanned2).hasForegroundColorSpanBetween(0, spanned2.length()).withColor(0xFFFF0000);
- assertThat(spanned2).hasBoldItalicSpanBetween(0, spanned2.length());
- assertThat(spanned2).hasStrikethroughSpanBetween(0, spanned2.length());
- }
-
- @Test
- public void noUnderline() throws Exception {
- ImmutableList allCues = getAllCues(NO_UNDERLINE_LINETHROUGH_TTML_FILE);
-
- assertThat(allCues).hasSize(2);
-
- Spanned spanned = getOnlyCueTextAtIndex(allCues, 0);
- assertThat(spanned.toString()).isEqualTo("text 1");
- // noUnderline from inline attribute overrides s0 global underline style id
- assertThat(spanned).hasNoUnderlineSpanBetween(0, spanned.length());
- }
-
- @Test
- public void noLinethrough() throws Exception {
- ImmutableList allCues = getAllCues(NO_UNDERLINE_LINETHROUGH_TTML_FILE);
-
- assertThat(allCues).hasSize(2);
-
- Spanned spanned = getOnlyCueTextAtIndex(allCues, 1);
- assertThat(spanned.toString()).isEqualTo("text 2");
- // noLineThrough from inline attribute overrides s1 global lineThrough style id
- assertThat(spanned).hasNoStrikethroughSpanBetween(0, spanned.length());
- }
-
- @Test
- public void fontSizeSpans() throws Exception {
- ImmutableList allCues = getAllCues(FONT_SIZE_TTML_FILE);
-
- assertThat(allCues).hasSize(5);
-
- Spanned spanned = getOnlyCueTextAtIndex(allCues, 0);
- assertThat(String.valueOf(spanned)).isEqualTo("text 1");
- assertThat(spanned).hasAbsoluteSizeSpanBetween(0, spanned.length()).withAbsoluteSize(32);
-
- spanned = getOnlyCueTextAtIndex(allCues, 1);
- assertThat(spanned.toString()).isEqualTo("text 2");
- assertThat(spanned).hasRelativeSizeSpanBetween(0, spanned.length()).withSizeChange(2.2f);
-
- spanned = getOnlyCueTextAtIndex(allCues, 2);
- assertThat(spanned.toString()).isEqualTo("text 3");
- assertThat(spanned).hasRelativeSizeSpanBetween(0, spanned.length()).withSizeChange(1.5f);
-
- spanned = getOnlyCueTextAtIndex(allCues, 3);
- assertThat(spanned.toString()).isEqualTo("two values");
- assertThat(spanned).hasAbsoluteSizeSpanBetween(0, spanned.length()).withAbsoluteSize(16);
-
- spanned = getOnlyCueTextAtIndex(allCues, 4);
- assertThat(spanned.toString()).isEqualTo("leading dot");
- assertThat(spanned).hasRelativeSizeSpanBetween(0, spanned.length()).withSizeChange(0.5f);
- }
-
- @Test
- public void fontSizeWithMissingUnitIsIgnored() throws Exception {
- ImmutableList allCues = getAllCues(FONT_SIZE_MISSING_UNIT_TTML_FILE);
-
- assertThat(allCues).hasSize(1);
-
- Spanned spanned = getOnlyCueTextAtIndex(allCues, 0);
- assertThat(spanned.toString()).isEqualTo("no unit");
- assertThat(spanned).hasNoRelativeSizeSpanBetween(0, spanned.length());
- assertThat(spanned).hasNoAbsoluteSizeSpanBetween(0, spanned.length());
- }
-
- @Test
- public void fontSizeWithInvalidValueIsIgnored() throws Exception {
- ImmutableList allCues = getAllCues(FONT_SIZE_INVALID_TTML_FILE);
-
- assertThat(allCues).hasSize(3);
-
- Spanned spanned = getOnlyCueTextAtIndex(allCues, 0);
- assertThat(String.valueOf(spanned)).isEqualTo("invalid");
- assertThat(spanned).hasNoRelativeSizeSpanBetween(0, spanned.length());
- assertThat(spanned).hasNoAbsoluteSizeSpanBetween(0, spanned.length());
-
- spanned = getOnlyCueTextAtIndex(allCues, 1);
- assertThat(String.valueOf(spanned)).isEqualTo("invalid");
- assertThat(spanned).hasNoRelativeSizeSpanBetween(0, spanned.length());
- assertThat(spanned).hasNoAbsoluteSizeSpanBetween(0, spanned.length());
-
- spanned = getOnlyCueTextAtIndex(allCues, 2);
- assertThat(String.valueOf(spanned)).isEqualTo("invalid dot");
- assertThat(spanned).hasNoRelativeSizeSpanBetween(0, spanned.length());
- assertThat(spanned).hasNoAbsoluteSizeSpanBetween(0, spanned.length());
- }
-
- @Test
- public void fontSizeWithEmptyValueIsIgnored() throws Exception {
- ImmutableList allCues = getAllCues(FONT_SIZE_EMPTY_TTML_FILE);
-
- assertThat(allCues).hasSize(1);
-
- Spanned spanned = getOnlyCueTextAtIndex(allCues, 0);
- assertThat(String.valueOf(spanned)).isEqualTo("empty");
- assertThat(spanned).hasNoRelativeSizeSpanBetween(0, spanned.length());
- assertThat(spanned).hasNoAbsoluteSizeSpanBetween(0, spanned.length());
- }
-
- @Test
- public void frameRate() throws Exception {
- ImmutableList allCues = getAllCues(FRAME_RATE_TTML_FILE);
-
- assertThat(allCues).hasSize(2);
- assertThat(allCues.get(0).startTimeUs).isEqualTo(1_000_000);
- assertThat(allCues.get(0).durationUs).isEqualTo(10_000);
- assertThat((double) allCues.get(1).startTimeUs).isWithin(1000).of(1_001_000_000);
- assertThat((double) allCues.get(1).durationUs).isWithin(2000).of(1_001_000_000);
- }
-
- @Test
- public void bitmapPercentageRegion() throws Exception {
- ImmutableList allCues = getAllCues(BITMAP_REGION_FILE);
-
- assertThat(allCues).hasSize(3);
-
- assertThat(allCues.get(0).startTimeUs).isEqualTo(200_000);
- assertThat(allCues.get(0).durationUs).isEqualTo(2_800_000);
- Cue cue = Iterables.getOnlyElement(allCues.get(0).cues);
- assertThat(cue.text).isNull();
- assertThat(cue.bitmap).isNotNull();
- assertThat(cue.position).isEqualTo(24f / 100f);
- assertThat(cue.line).isEqualTo(28f / 100f);
- assertThat(cue.size).isEqualTo(51f / 100f);
- assertThat(cue.bitmapHeight).isEqualTo(12f / 100f);
-
- assertThat(allCues.get(1).startTimeUs).isEqualTo(3_200_000);
- assertThat(allCues.get(1).durationUs).isEqualTo(3_737_000);
- cue = Iterables.getOnlyElement(allCues.get(1).cues);
- assertThat(cue.text).isNull();
- assertThat(cue.bitmap).isNotNull();
- assertThat(cue.position).isEqualTo(21f / 100f);
- assertThat(cue.line).isEqualTo(35f / 100f);
- assertThat(cue.size).isEqualTo(57f / 100f);
- assertThat(cue.bitmapHeight).isEqualTo(6f / 100f);
-
- assertThat(allCues.get(2).startTimeUs).isEqualTo(7_200_000);
- cue = Iterables.getOnlyElement(allCues.get(2).cues);
- assertThat(cue.text).isNull();
- assertThat(cue.bitmap).isNotNull();
- assertThat(cue.position).isEqualTo(24f / 100f);
- assertThat(cue.line).isEqualTo(28f / 100f);
- assertThat(cue.size).isEqualTo(51f / 100f);
- assertThat(cue.bitmapHeight).isEqualTo(12f / 100f);
- }
-
- @Test
- public void bitmapPixelRegion() throws Exception {
- ImmutableList allCues = getAllCues(BITMAP_PIXEL_REGION_FILE);
-
- assertThat(allCues).hasSize(2);
-
- assertThat(allCues.get(0).startTimeUs).isEqualTo(200_000);
- assertThat(allCues.get(0).durationUs).isEqualTo(2_800_000);
- Cue cue = Iterables.getOnlyElement(allCues.get(0).cues);
- assertThat(cue.text).isNull();
- assertThat(cue.bitmap).isNotNull();
- assertThat(cue.position).isEqualTo(307f / 1280f);
- assertThat(cue.line).isEqualTo(562f / 720f);
- assertThat(cue.size).isEqualTo(653f / 1280f);
- assertThat(cue.bitmapHeight).isEqualTo(86f / 720f);
-
- assertThat(allCues.get(1).startTimeUs).isEqualTo(3_200_000);
- assertThat(allCues.get(1).durationUs).isEqualTo(3_737_000);
- cue = Iterables.getOnlyElement(allCues.get(1).cues);
- assertThat(cue.text).isNull();
- assertThat(cue.bitmap).isNotNull();
- assertThat(cue.position).isEqualTo(269f / 1280f);
- assertThat(cue.line).isEqualTo(612f / 720f);
- assertThat(cue.size).isEqualTo(730f / 1280f);
- assertThat(cue.bitmapHeight).isEqualTo(43f / 720f);
- }
-
- @Test
- public void bitmapUnsupportedRegion() throws Exception {
- ImmutableList allCues = getAllCues(BITMAP_UNSUPPORTED_REGION_FILE);
-
- assertThat(allCues).hasSize(2);
-
- assertThat(allCues.get(0).startTimeUs).isEqualTo(200_000);
- assertThat(allCues.get(0).durationUs).isEqualTo(2_800_000);
- Cue cue = Iterables.getOnlyElement(allCues.get(0).cues);
- assertThat(cue.text).isNull();
- assertThat(cue.bitmap).isNotNull();
- assertThat(cue.position).isEqualTo(Cue.DIMEN_UNSET);
- assertThat(cue.line).isEqualTo(Cue.DIMEN_UNSET);
- assertThat(cue.size).isEqualTo(Cue.DIMEN_UNSET);
- assertThat(cue.bitmapHeight).isEqualTo(Cue.DIMEN_UNSET);
-
- assertThat(allCues.get(1).startTimeUs).isEqualTo(3_200_000);
- assertThat(allCues.get(1).durationUs).isEqualTo(3_737_000);
- cue = Iterables.getOnlyElement(allCues.get(1).cues);
- assertThat(cue.text).isNull();
- assertThat(cue.bitmap).isNotNull();
- assertThat(cue.position).isEqualTo(Cue.DIMEN_UNSET);
- assertThat(cue.line).isEqualTo(Cue.DIMEN_UNSET);
- assertThat(cue.size).isEqualTo(Cue.DIMEN_UNSET);
- assertThat(cue.bitmapHeight).isEqualTo(Cue.DIMEN_UNSET);
- }
-
- @Test
- public void textAlign() throws Exception {
- ImmutableList allCues = getAllCues(TEXT_ALIGN_FILE);
-
- assertThat(allCues).hasSize(9);
-
- Cue firstCue = Iterables.getOnlyElement(allCues.get(0).cues);
- assertThat(firstCue.text.toString()).isEqualTo("Start alignment");
- assertThat(firstCue.textAlignment).isEqualTo(Layout.Alignment.ALIGN_NORMAL);
-
- Cue secondCue = Iterables.getOnlyElement(allCues.get(1).cues);
- assertThat(secondCue.text.toString()).isEqualTo("Left alignment");
- assertThat(secondCue.textAlignment).isEqualTo(Layout.Alignment.ALIGN_NORMAL);
-
- Cue thirdCue = Iterables.getOnlyElement(allCues.get(2).cues);
- assertThat(thirdCue.text.toString()).isEqualTo("Center alignment");
- assertThat(thirdCue.textAlignment).isEqualTo(Layout.Alignment.ALIGN_CENTER);
-
- Cue fourthCue = Iterables.getOnlyElement(allCues.get(3).cues);
- assertThat(fourthCue.text.toString()).isEqualTo("Right alignment");
- assertThat(fourthCue.textAlignment).isEqualTo(Layout.Alignment.ALIGN_OPPOSITE);
-
- Cue fifthCue = Iterables.getOnlyElement(allCues.get(4).cues);
- assertThat(fifthCue.text.toString()).isEqualTo("End alignment");
- assertThat(fifthCue.textAlignment).isEqualTo(Layout.Alignment.ALIGN_OPPOSITE);
-
- Cue sixthCue = Iterables.getOnlyElement(allCues.get(5).cues);
- assertThat(sixthCue.text.toString()).isEqualTo("Justify alignment (unsupported)");
- assertThat(sixthCue.textAlignment).isNull();
-
- Cue seventhCue = Iterables.getOnlyElement(allCues.get(6).cues);
- assertThat(seventhCue.text.toString()).isEqualTo("No textAlign property");
- assertThat(seventhCue.textAlignment).isNull();
-
- Cue eighthCue = Iterables.getOnlyElement(allCues.get(7).cues);
- assertThat(eighthCue.text.toString()).isEqualTo("Ancestor start alignment");
- assertThat(eighthCue.textAlignment).isEqualTo(Layout.Alignment.ALIGN_NORMAL);
-
- Cue ninthCue = Iterables.getOnlyElement(allCues.get(8).cues);
- assertThat(ninthCue.text.toString()).isEqualTo("Not a P node");
- assertThat(ninthCue.textAlignment).isNull();
- }
-
- @Test
- public void multiRowAlign() throws Exception {
- ImmutableList allCues = getAllCues(MULTI_ROW_ALIGN_FILE);
-
- Cue firstCue = Iterables.getOnlyElement(allCues.get(0).cues);
- assertThat(firstCue.multiRowAlignment).isEqualTo(Layout.Alignment.ALIGN_NORMAL);
-
- Cue secondCue = Iterables.getOnlyElement(allCues.get(1).cues);
- assertThat(secondCue.multiRowAlignment).isEqualTo(Layout.Alignment.ALIGN_CENTER);
-
- Cue thirdCue = Iterables.getOnlyElement(allCues.get(2).cues);
- assertThat(thirdCue.multiRowAlignment).isEqualTo(Layout.Alignment.ALIGN_OPPOSITE);
-
- Cue fourthCue = Iterables.getOnlyElement(allCues.get(3).cues);
- assertThat(fourthCue.multiRowAlignment).isEqualTo(Layout.Alignment.ALIGN_NORMAL);
-
- Cue fifthCue = Iterables.getOnlyElement(allCues.get(4).cues);
- assertThat(fifthCue.multiRowAlignment).isEqualTo(Layout.Alignment.ALIGN_OPPOSITE);
-
- Cue sixthCue = Iterables.getOnlyElement(allCues.get(5).cues);
- assertThat(sixthCue.multiRowAlignment).isNull();
-
- Cue seventhCue = Iterables.getOnlyElement(allCues.get(6).cues);
- assertThat(seventhCue.multiRowAlignment).isNull();
- }
-
- @Test
- public void verticalText() throws Exception {
- ImmutableList allCues = getAllCues(VERTICAL_TEXT_FILE);
-
- Cue firstCue = Iterables.getOnlyElement(allCues.get(0).cues);
- assertThat(firstCue.verticalType).isEqualTo(Cue.VERTICAL_TYPE_RL);
-
- Cue secondCue = Iterables.getOnlyElement(allCues.get(1).cues);
- assertThat(secondCue.verticalType).isEqualTo(Cue.VERTICAL_TYPE_LR);
-
- Cue thirdCue = Iterables.getOnlyElement(allCues.get(2).cues);
- assertThat(thirdCue.verticalType).isEqualTo(Cue.TYPE_UNSET);
- }
-
- @Test
- public void textCombine() throws Exception {
- ImmutableList allCues = getAllCues(TEXT_COMBINE_FILE);
-
- Spanned firstCue = getOnlyCueTextAtIndex(allCues, 0);
- assertThat(firstCue)
- .hasHorizontalTextInVerticalContextSpanBetween(
- "text with ".length(), "text with combined".length());
-
- Spanned secondCue = getOnlyCueTextAtIndex(allCues, 1);
- assertThat(secondCue)
- .hasNoHorizontalTextInVerticalContextSpanBetween(
- "text with ".length(), "text with un-combined".length());
-
- Spanned thirdCue = getOnlyCueTextAtIndex(allCues, 2);
- assertThat(thirdCue).hasNoHorizontalTextInVerticalContextSpanBetween(0, thirdCue.length());
- }
-
- @Test
- public void rubies() throws Exception {
- ImmutableList allCues = getAllCues(RUBIES_FILE);
-
- Spanned firstCue = getOnlyCueTextAtIndex(allCues, 0);
- assertThat(firstCue.toString()).isEqualTo("Cue with annotated text.");
- assertThat(firstCue)
- .hasRubySpanBetween("Cue with ".length(), "Cue with annotated".length())
- .withTextAndPosition("1st rubies", TextAnnotation.POSITION_BEFORE);
- assertThat(firstCue)
- .hasRubySpanBetween("Cue with annotated ".length(), "Cue with annotated text".length())
- .withTextAndPosition("2nd rubies", TextAnnotation.POSITION_UNKNOWN);
-
- Spanned secondCue = getOnlyCueTextAtIndex(allCues, 1);
- assertThat(secondCue.toString()).isEqualTo("Cue with annotated text.");
- assertThat(secondCue)
- .hasRubySpanBetween("Cue with ".length(), "Cue with annotated".length())
- .withTextAndPosition("rubies", TextAnnotation.POSITION_UNKNOWN);
-
- Spanned thirdCue = getOnlyCueTextAtIndex(allCues, 2);
- assertThat(thirdCue.toString()).isEqualTo("Cue with annotated text.");
- assertThat(thirdCue)
- .hasRubySpanBetween("Cue with ".length(), "Cue with annotated".length())
- .withTextAndPosition("rubies", TextAnnotation.POSITION_UNKNOWN);
-
- Spanned fourthCue = getOnlyCueTextAtIndex(allCues, 3);
- assertThat(fourthCue.toString()).isEqualTo("Cue with annotated text.");
- assertThat(fourthCue).hasNoRubySpanBetween(0, fourthCue.length());
-
- Spanned fifthCue = getOnlyCueTextAtIndex(allCues, 4);
- assertThat(fifthCue.toString()).isEqualTo("Cue with text.");
- assertThat(fifthCue).hasNoRubySpanBetween(0, fifthCue.length());
-
- Spanned sixthCue = getOnlyCueTextAtIndex(allCues, 5);
- assertThat(sixthCue.toString()).isEqualTo("Cue with annotated text.");
- assertThat(sixthCue).hasNoRubySpanBetween(0, sixthCue.length());
-
- Spanned seventhCue = getOnlyCueTextAtIndex(allCues, 6);
- assertThat(seventhCue.toString()).isEqualTo("Cue with annotated text.");
- assertThat(seventhCue)
- .hasRubySpanBetween("Cue with ".length(), "Cue with annotated".length())
- .withTextAndPosition("rubies", TextAnnotation.POSITION_BEFORE);
-
- Spanned eighthCue = getOnlyCueTextAtIndex(allCues, 7);
- assertThat(eighthCue.toString()).isEqualTo("Cue with annotated text.");
- assertThat(eighthCue)
- .hasRubySpanBetween("Cue with ".length(), "Cue with annotated".length())
- .withTextAndPosition("rubies", TextAnnotation.POSITION_AFTER);
- }
-
- @Test
- public void textEmphasis() throws Exception {
- ImmutableList allCues = getAllCues(TEXT_EMPHASIS_FILE);
-
- Spanned firstCue = getOnlyCueTextAtIndex(allCues, 0);
- assertThat(firstCue)
- .hasTextEmphasisSpanBetween("None ".length(), "None おはよ".length())
- .withMarkAndPosition(
- TextEmphasisSpan.MARK_SHAPE_NONE,
- TextEmphasisSpan.MARK_FILL_UNKNOWN,
- TextAnnotation.POSITION_BEFORE);
-
- Spanned secondCue = getOnlyCueTextAtIndex(allCues, 1);
- assertThat(secondCue)
- .hasTextEmphasisSpanBetween("Auto ".length(), "Auto ございます".length())
- .withMarkAndPosition(
- TextEmphasisSpan.MARK_SHAPE_CIRCLE,
- TextEmphasisSpan.MARK_FILL_FILLED,
- TextAnnotation.POSITION_BEFORE);
-
- Spanned thirdCue = getOnlyCueTextAtIndex(allCues, 2);
- assertThat(thirdCue)
- .hasTextEmphasisSpanBetween("Filled circle ".length(), "Filled circle こんばんは".length())
- .withMarkAndPosition(
- TextEmphasisSpan.MARK_SHAPE_CIRCLE,
- TextEmphasisSpan.MARK_FILL_FILLED,
- TextAnnotation.POSITION_BEFORE);
-
- Spanned fourthCue = getOnlyCueTextAtIndex(allCues, 3);
- assertThat(fourthCue)
- .hasTextEmphasisSpanBetween("Filled dot ".length(), "Filled dot ございます".length())
- .withMarkAndPosition(
- TextEmphasisSpan.MARK_SHAPE_DOT,
- TextEmphasisSpan.MARK_FILL_FILLED,
- TextAnnotation.POSITION_BEFORE);
-
- Spanned fifthCue = getOnlyCueTextAtIndex(allCues, 4);
- assertThat(fifthCue)
- .hasTextEmphasisSpanBetween("Filled sesame ".length(), "Filled sesame おはよ".length())
- .withMarkAndPosition(
- TextEmphasisSpan.MARK_SHAPE_SESAME,
- TextEmphasisSpan.MARK_FILL_FILLED,
- TextAnnotation.POSITION_BEFORE);
-
- Spanned sixthCue = getOnlyCueTextAtIndex(allCues, 5);
- assertThat(sixthCue)
- .hasTextEmphasisSpanBetween(
- "Open circle before ".length(), "Open circle before ございます".length())
- .withMarkAndPosition(
- TextEmphasisSpan.MARK_SHAPE_CIRCLE,
- TextEmphasisSpan.MARK_FILL_OPEN,
- TextAnnotation.POSITION_BEFORE);
-
- Spanned seventhCue = getOnlyCueTextAtIndex(allCues, 6);
- assertThat(seventhCue)
- .hasTextEmphasisSpanBetween("Open dot after ".length(), "Open dot after おはよ".length())
- .withMarkAndPosition(
- TextEmphasisSpan.MARK_SHAPE_DOT,
- TextEmphasisSpan.MARK_FILL_OPEN,
- TextAnnotation.POSITION_AFTER);
-
- Spanned eighthCue = getOnlyCueTextAtIndex(allCues, 7);
- assertThat(eighthCue)
- .hasTextEmphasisSpanBetween(
- "Open sesame outside ".length(), "Open sesame outside ございます".length())
- .withMarkAndPosition(
- TextEmphasisSpan.MARK_SHAPE_SESAME,
- TextEmphasisSpan.MARK_FILL_OPEN,
- TextAnnotation.POSITION_BEFORE);
-
- Spanned ninthCue = getOnlyCueTextAtIndex(allCues, 8);
- assertThat(ninthCue)
- .hasTextEmphasisSpanBetween("Auto outside ".length(), "Auto outside おはよ".length())
- .withMarkAndPosition(
- TextEmphasisSpan.MARK_SHAPE_CIRCLE,
- TextEmphasisSpan.MARK_FILL_FILLED,
- TextAnnotation.POSITION_BEFORE);
-
- Spanned tenthCue = getOnlyCueTextAtIndex(allCues, 9);
- assertThat(tenthCue)
- .hasTextEmphasisSpanBetween("Circle before ".length(), "Circle before ございます".length())
- .withMarkAndPosition(
- TextEmphasisSpan.MARK_SHAPE_CIRCLE,
- TextEmphasisSpan.MARK_FILL_FILLED,
- TextAnnotation.POSITION_BEFORE);
-
- Spanned eleventhCue = getOnlyCueTextAtIndex(allCues, 10);
- assertThat(eleventhCue)
- .hasTextEmphasisSpanBetween("Sesame after ".length(), "Sesame after おはよ".length())
- .withMarkAndPosition(
- TextEmphasisSpan.MARK_SHAPE_SESAME,
- TextEmphasisSpan.MARK_FILL_FILLED,
- TextAnnotation.POSITION_AFTER);
-
- Spanned twelfthCue = getOnlyCueTextAtIndex(allCues, 11);
- assertThat(twelfthCue)
- .hasTextEmphasisSpanBetween("Dot outside ".length(), "Dot outside ございます".length())
- .withMarkAndPosition(
- TextEmphasisSpan.MARK_SHAPE_DOT,
- TextEmphasisSpan.MARK_FILL_FILLED,
- TextAnnotation.POSITION_BEFORE);
-
- Spanned thirteenthCue = getOnlyCueTextAtIndex(allCues, 12);
- assertThat(thirteenthCue)
- .hasNoTextEmphasisSpanBetween(
- "No textEmphasis property ".length(), "No textEmphasis property おはよ".length());
-
- Spanned fourteenthCue = getOnlyCueTextAtIndex(allCues, 13);
- assertThat(fourteenthCue)
- .hasTextEmphasisSpanBetween("Auto (TBLR) ".length(), "Auto (TBLR) ございます".length())
- .withMarkAndPosition(
- TextEmphasisSpan.MARK_SHAPE_SESAME,
- TextEmphasisSpan.MARK_FILL_FILLED,
- TextAnnotation.POSITION_BEFORE);
-
- Spanned fifteenthCue = getOnlyCueTextAtIndex(allCues, 14);
- assertThat(fifteenthCue)
- .hasTextEmphasisSpanBetween("Auto (TBRL) ".length(), "Auto (TBRL) おはよ".length())
- .withMarkAndPosition(
- TextEmphasisSpan.MARK_SHAPE_SESAME,
- TextEmphasisSpan.MARK_FILL_FILLED,
- TextAnnotation.POSITION_BEFORE);
-
- Spanned sixteenthCue = getOnlyCueTextAtIndex(allCues, 15);
- assertThat(sixteenthCue)
- .hasTextEmphasisSpanBetween("Auto (TB) ".length(), "Auto (TB) ございます".length())
- .withMarkAndPosition(
- TextEmphasisSpan.MARK_SHAPE_SESAME,
- TextEmphasisSpan.MARK_FILL_FILLED,
- TextAnnotation.POSITION_BEFORE);
-
- Spanned seventeenthCue = getOnlyCueTextAtIndex(allCues, 16);
- assertThat(seventeenthCue)
- .hasTextEmphasisSpanBetween("Auto (LR) ".length(), "Auto (LR) おはよ".length())
- .withMarkAndPosition(
- TextEmphasisSpan.MARK_SHAPE_CIRCLE,
- TextEmphasisSpan.MARK_FILL_FILLED,
- TextAnnotation.POSITION_BEFORE);
- }
-
- @Test
- public void shear() throws Exception {
- ImmutableList allCues = getAllCues(SHEAR_FILE);
-
- Cue firstCue = Iterables.getOnlyElement(allCues.get(0).cues);
- assertThat(firstCue.shearDegrees).isZero();
-
- Cue secondCue = Iterables.getOnlyElement(allCues.get(1).cues);
- assertThat(secondCue.shearDegrees).isWithin(0.01f).of(-15f);
-
- Cue thirdCue = Iterables.getOnlyElement(allCues.get(2).cues);
- assertThat(thirdCue.shearDegrees).isWithin(0.01f).of(15f);
-
- Cue fourthCue = Iterables.getOnlyElement(allCues.get(3).cues);
- assertThat(fourthCue.shearDegrees).isWithin(0.01f).of(-15f);
-
- Cue fifthCue = Iterables.getOnlyElement(allCues.get(4).cues);
- assertThat(fifthCue.shearDegrees).isWithin(0.01f).of(-22.5f);
-
- Cue sixthCue = Iterables.getOnlyElement(allCues.get(5).cues);
- assertThat(sixthCue.shearDegrees).isWithin(0.01f).of(0f);
-
- Cue seventhCue = Iterables.getOnlyElement(allCues.get(6).cues);
- assertThat(seventhCue.shearDegrees).isWithin(0.01f).of(-90f);
-
- Cue eighthCue = Iterables.getOnlyElement(allCues.get(7).cues);
- assertThat(eighthCue.shearDegrees).isWithin(0.01f).of(90f);
- }
-
- private static Spanned getOnlyCueTextAtIndex(ImmutableList allCues, int index) {
- Cue cue = getOnlyCueAtIndex(allCues, index);
- assertThat(cue.text).isInstanceOf(Spanned.class);
- return (Spanned) Assertions.checkNotNull(cue.text);
- }
-
- private static Cue getOnlyCueAtIndex(ImmutableList allCues, int index) {
- ImmutableList cues = allCues.get(index).cues;
- assertThat(cues).hasSize(1);
- return cues.get(0);
- }
-
- private static ImmutableList getAllCues(String file) throws Exception {
- TtmlParser ttmlParser = new TtmlParser();
- byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), file);
- return ttmlParser.parse(bytes, 0, bytes.length);
- }
-}