Add vertical support to WebvttCueParser
PiperOrigin-RevId: 286583957
This commit is contained in:
parent
f88fbaf655
commit
14a0c9ebfd
@ -313,6 +313,8 @@ public final class WebvttCueParser {
|
|||||||
parsePositionAttribute(value, builder);
|
parsePositionAttribute(value, builder);
|
||||||
} else if ("size".equals(name)) {
|
} else if ("size".equals(name)) {
|
||||||
builder.size = WebvttParserUtil.parsePercentage(value);
|
builder.size = WebvttParserUtil.parsePercentage(value);
|
||||||
|
} else if ("vertical".equals(name)) {
|
||||||
|
builder.verticalType = parseVerticalAttribute(value);
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "Unknown cue setting " + name + ":" + value);
|
Log.w(TAG, "Unknown cue setting " + name + ":" + value);
|
||||||
}
|
}
|
||||||
@ -368,6 +370,19 @@ public final class WebvttCueParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Cue.VerticalType
|
||||||
|
private static int parseVerticalAttribute(String s) {
|
||||||
|
switch (s) {
|
||||||
|
case "rl":
|
||||||
|
return Cue.VERTICAL_TYPE_RL;
|
||||||
|
case "lr":
|
||||||
|
return Cue.VERTICAL_TYPE_LR;
|
||||||
|
default:
|
||||||
|
Log.w(TAG, "Invalid 'vertical' value: " + s);
|
||||||
|
return Cue.TYPE_UNSET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TextAlignment
|
@TextAlignment
|
||||||
private static int parseTextAlignment(String s) {
|
private static int parseTextAlignment(String s) {
|
||||||
switch (s) {
|
switch (s) {
|
||||||
@ -564,6 +579,7 @@ public final class WebvttCueParser {
|
|||||||
public float position;
|
public float position;
|
||||||
@Cue.AnchorType public int positionAnchor;
|
@Cue.AnchorType public int positionAnchor;
|
||||||
public float size;
|
public float size;
|
||||||
|
@Cue.VerticalType public int verticalType;
|
||||||
|
|
||||||
public WebvttCueInfoBuilder() {
|
public WebvttCueInfoBuilder() {
|
||||||
startTimeUs = 0;
|
startTimeUs = 0;
|
||||||
@ -579,6 +595,7 @@ public final class WebvttCueParser {
|
|||||||
positionAnchor = Cue.TYPE_UNSET;
|
positionAnchor = Cue.TYPE_UNSET;
|
||||||
// Default: https://www.w3.org/TR/webvtt1/#webvtt-cue-size
|
// Default: https://www.w3.org/TR/webvtt1/#webvtt-cue-size
|
||||||
size = 1.0f;
|
size = 1.0f;
|
||||||
|
verticalType = Cue.TYPE_UNSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebvttCueInfo build() {
|
public WebvttCueInfo build() {
|
||||||
@ -600,7 +617,8 @@ public final class WebvttCueParser {
|
|||||||
.setLineAnchor(lineAnchor)
|
.setLineAnchor(lineAnchor)
|
||||||
.setPosition(position)
|
.setPosition(position)
|
||||||
.setPositionAnchor(positionAnchor)
|
.setPositionAnchor(positionAnchor)
|
||||||
.setSize(Math.min(size, deriveMaxSize(positionAnchor, position)));
|
.setSize(Math.min(size, deriveMaxSize(positionAnchor, position)))
|
||||||
|
.setVerticalType(verticalType);
|
||||||
|
|
||||||
if (text != null) {
|
if (text != null) {
|
||||||
cueBuilder.setText(text);
|
cueBuilder.setText(text);
|
||||||
|
12
library/core/src/test/assets/webvtt/with_vertical
Normal file
12
library/core/src/test/assets/webvtt/with_vertical
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
WEBVTT
|
||||||
|
|
||||||
|
NOTE vertical spec: https://www.w3.org/TR/webvtt1/#webvtt-alignment-cue-setting
|
||||||
|
|
||||||
|
00:00:00.000 --> 00:00:01.234 vertical:rl
|
||||||
|
Vertical right-to-left (e.g. Japanese)
|
||||||
|
|
||||||
|
00:02.345 --> 00:03.456 vertical:lr
|
||||||
|
Vertical left-to-right (e.g. Mongolian)
|
||||||
|
|
||||||
|
00:04.000 --> 00:05.000
|
||||||
|
No vertical setting (i.e. horizontal)
|
@ -48,6 +48,7 @@ public class WebvttDecoderTest {
|
|||||||
private static final String TYPICAL_WITH_IDS_FILE = "webvtt/typical_with_identifiers";
|
private static final String TYPICAL_WITH_IDS_FILE = "webvtt/typical_with_identifiers";
|
||||||
private static final String TYPICAL_WITH_COMMENTS_FILE = "webvtt/typical_with_comments";
|
private static final String TYPICAL_WITH_COMMENTS_FILE = "webvtt/typical_with_comments";
|
||||||
private static final String WITH_POSITIONING_FILE = "webvtt/with_positioning";
|
private static final String WITH_POSITIONING_FILE = "webvtt/with_positioning";
|
||||||
|
private static final String WITH_VERTICAL_FILE = "webvtt/with_vertical";
|
||||||
private static final String WITH_BAD_CUE_HEADER_FILE = "webvtt/with_bad_cue_header";
|
private static final String WITH_BAD_CUE_HEADER_FILE = "webvtt/with_bad_cue_header";
|
||||||
private static final String WITH_TAGS_FILE = "webvtt/with_tags";
|
private static final String WITH_TAGS_FILE = "webvtt/with_tags";
|
||||||
private static final String WITH_CSS_STYLES = "webvtt/with_css_styles";
|
private static final String WITH_CSS_STYLES = "webvtt/with_css_styles";
|
||||||
@ -231,7 +232,8 @@ public class WebvttDecoderTest {
|
|||||||
/* lineAnchor= */ Cue.ANCHOR_TYPE_START,
|
/* lineAnchor= */ Cue.ANCHOR_TYPE_START,
|
||||||
/* position= */ 0.1f,
|
/* position= */ 0.1f,
|
||||||
/* positionAnchor= */ Cue.ANCHOR_TYPE_START,
|
/* positionAnchor= */ Cue.ANCHOR_TYPE_START,
|
||||||
/* size= */ 0.35f);
|
/* size= */ 0.35f,
|
||||||
|
/* verticalType= */ Cue.TYPE_UNSET);
|
||||||
assertCue(
|
assertCue(
|
||||||
subtitle,
|
subtitle,
|
||||||
/* eventTimeIndex= */ 2,
|
/* eventTimeIndex= */ 2,
|
||||||
@ -244,7 +246,8 @@ public class WebvttDecoderTest {
|
|||||||
/* lineAnchor= */ Cue.ANCHOR_TYPE_START,
|
/* lineAnchor= */ Cue.ANCHOR_TYPE_START,
|
||||||
/* position= */ 0.5f,
|
/* position= */ 0.5f,
|
||||||
/* positionAnchor= */ Cue.ANCHOR_TYPE_END,
|
/* positionAnchor= */ Cue.ANCHOR_TYPE_END,
|
||||||
/* size= */ 0.35f);
|
/* size= */ 0.35f,
|
||||||
|
/* verticalType= */ Cue.TYPE_UNSET);
|
||||||
assertCue(
|
assertCue(
|
||||||
subtitle,
|
subtitle,
|
||||||
/* eventTimeIndex= */ 4,
|
/* eventTimeIndex= */ 4,
|
||||||
@ -257,7 +260,8 @@ public class WebvttDecoderTest {
|
|||||||
/* lineAnchor= */ Cue.ANCHOR_TYPE_END,
|
/* lineAnchor= */ Cue.ANCHOR_TYPE_END,
|
||||||
/* position= */ 0.5f,
|
/* position= */ 0.5f,
|
||||||
/* positionAnchor= */ Cue.ANCHOR_TYPE_MIDDLE,
|
/* positionAnchor= */ Cue.ANCHOR_TYPE_MIDDLE,
|
||||||
/* size= */ 0.35f);
|
/* size= */ 0.35f,
|
||||||
|
/* verticalType= */ Cue.TYPE_UNSET);
|
||||||
assertCue(
|
assertCue(
|
||||||
subtitle,
|
subtitle,
|
||||||
/* eventTimeIndex= */ 6,
|
/* eventTimeIndex= */ 6,
|
||||||
@ -270,7 +274,8 @@ public class WebvttDecoderTest {
|
|||||||
/* lineAnchor= */ Cue.ANCHOR_TYPE_START,
|
/* lineAnchor= */ Cue.ANCHOR_TYPE_START,
|
||||||
/* position= */ 0.5f,
|
/* position= */ 0.5f,
|
||||||
/* positionAnchor= */ Cue.ANCHOR_TYPE_MIDDLE,
|
/* positionAnchor= */ Cue.ANCHOR_TYPE_MIDDLE,
|
||||||
/* size= */ 1.0f);
|
/* size= */ 1.0f,
|
||||||
|
/* verticalType= */ Cue.TYPE_UNSET);
|
||||||
assertCue(
|
assertCue(
|
||||||
subtitle,
|
subtitle,
|
||||||
/* eventTimeIndex= */ 8,
|
/* eventTimeIndex= */ 8,
|
||||||
@ -283,7 +288,8 @@ public class WebvttDecoderTest {
|
|||||||
/* lineAnchor= */ Cue.ANCHOR_TYPE_START,
|
/* lineAnchor= */ Cue.ANCHOR_TYPE_START,
|
||||||
/* position= */ 1.0f,
|
/* position= */ 1.0f,
|
||||||
/* positionAnchor= */ Cue.ANCHOR_TYPE_END,
|
/* positionAnchor= */ Cue.ANCHOR_TYPE_END,
|
||||||
/* size= */ 1.0f);
|
/* size= */ 1.0f,
|
||||||
|
/* verticalType= */ Cue.TYPE_UNSET);
|
||||||
assertCue(
|
assertCue(
|
||||||
subtitle,
|
subtitle,
|
||||||
/* eventTimeIndex= */ 10,
|
/* eventTimeIndex= */ 10,
|
||||||
@ -296,7 +302,58 @@ public class WebvttDecoderTest {
|
|||||||
/* lineAnchor= */ Cue.ANCHOR_TYPE_END,
|
/* lineAnchor= */ Cue.ANCHOR_TYPE_END,
|
||||||
/* position= */ 0.5f,
|
/* position= */ 0.5f,
|
||||||
/* positionAnchor= */ Cue.ANCHOR_TYPE_MIDDLE,
|
/* positionAnchor= */ Cue.ANCHOR_TYPE_MIDDLE,
|
||||||
/* size= */ 0.35f);
|
/* size= */ 0.35f,
|
||||||
|
/* verticalType= */ Cue.TYPE_UNSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDecodeWithVertical() throws Exception {
|
||||||
|
WebvttSubtitle subtitle = getSubtitleForTestAsset(WITH_VERTICAL_FILE);
|
||||||
|
// Test event count.
|
||||||
|
assertThat(subtitle.getEventTimeCount()).isEqualTo(6);
|
||||||
|
// Test cues.
|
||||||
|
assertCue(
|
||||||
|
subtitle,
|
||||||
|
/* eventTimeIndex= */ 0,
|
||||||
|
/* startTimeUs= */ 0,
|
||||||
|
/* endTimeUs= */ 1234000,
|
||||||
|
"Vertical right-to-left (e.g. Japanese)",
|
||||||
|
Alignment.ALIGN_CENTER,
|
||||||
|
/* line= */ Cue.DIMEN_UNSET,
|
||||||
|
/* lineType= */ Cue.LINE_TYPE_NUMBER,
|
||||||
|
/* lineAnchor= */ Cue.ANCHOR_TYPE_START,
|
||||||
|
/* position= */ 0.5f,
|
||||||
|
/* positionAnchor= */ Cue.ANCHOR_TYPE_MIDDLE,
|
||||||
|
/* size= */ 1.0f,
|
||||||
|
Cue.VERTICAL_TYPE_RL);
|
||||||
|
assertCue(
|
||||||
|
subtitle,
|
||||||
|
/* eventTimeIndex= */ 2,
|
||||||
|
/* startTimeUs= */ 2345000,
|
||||||
|
/* endTimeUs= */ 3456000,
|
||||||
|
"Vertical left-to-right (e.g. Mongolian)",
|
||||||
|
Alignment.ALIGN_CENTER,
|
||||||
|
/* line= */ Cue.DIMEN_UNSET,
|
||||||
|
/* lineType= */ Cue.LINE_TYPE_NUMBER,
|
||||||
|
/* lineAnchor= */ Cue.ANCHOR_TYPE_START,
|
||||||
|
/* position= */ 0.5f,
|
||||||
|
/* positionAnchor= */ Cue.ANCHOR_TYPE_MIDDLE,
|
||||||
|
/* size= */ 1.0f,
|
||||||
|
Cue.VERTICAL_TYPE_LR);
|
||||||
|
assertCue(
|
||||||
|
subtitle,
|
||||||
|
/* eventTimeIndex= */ 4,
|
||||||
|
/* startTimeUs= */ 4000000,
|
||||||
|
/* endTimeUs= */ 5000000,
|
||||||
|
"No vertical setting (i.e. horizontal)",
|
||||||
|
Alignment.ALIGN_CENTER,
|
||||||
|
/* line= */ Cue.DIMEN_UNSET,
|
||||||
|
/* lineType= */ Cue.LINE_TYPE_NUMBER,
|
||||||
|
/* lineAnchor= */ Cue.ANCHOR_TYPE_START,
|
||||||
|
/* position= */ 0.5f,
|
||||||
|
/* positionAnchor= */ Cue.ANCHOR_TYPE_MIDDLE,
|
||||||
|
/* size= */ 1.0f,
|
||||||
|
/* verticalType= */ Cue.TYPE_UNSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -421,7 +478,8 @@ public class WebvttDecoderTest {
|
|||||||
/* lineAnchor= */ Cue.ANCHOR_TYPE_START,
|
/* lineAnchor= */ Cue.ANCHOR_TYPE_START,
|
||||||
/* position= */ 0.5f,
|
/* position= */ 0.5f,
|
||||||
/* positionAnchor= */ Cue.ANCHOR_TYPE_MIDDLE,
|
/* positionAnchor= */ Cue.ANCHOR_TYPE_MIDDLE,
|
||||||
/* size= */ 1.0f);
|
/* size= */ 1.0f,
|
||||||
|
/* verticalType= */ Cue.TYPE_UNSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertCue(
|
private void assertCue(
|
||||||
@ -436,7 +494,8 @@ public class WebvttDecoderTest {
|
|||||||
@Cue.AnchorType int lineAnchor,
|
@Cue.AnchorType int lineAnchor,
|
||||||
float position,
|
float position,
|
||||||
@Cue.AnchorType int positionAnchor,
|
@Cue.AnchorType int positionAnchor,
|
||||||
float size) {
|
float size,
|
||||||
|
@Cue.VerticalType int verticalType) {
|
||||||
expect
|
expect
|
||||||
.withMessage("startTimeUs")
|
.withMessage("startTimeUs")
|
||||||
.that(subtitle.getEventTime(eventTimeIndex))
|
.that(subtitle.getEventTime(eventTimeIndex))
|
||||||
@ -457,6 +516,7 @@ public class WebvttDecoderTest {
|
|||||||
expect.withMessage("cue.position").that(cue.position).isEqualTo(position);
|
expect.withMessage("cue.position").that(cue.position).isEqualTo(position);
|
||||||
expect.withMessage("cue.positionAnchor").that(cue.positionAnchor).isEqualTo(positionAnchor);
|
expect.withMessage("cue.positionAnchor").that(cue.positionAnchor).isEqualTo(positionAnchor);
|
||||||
expect.withMessage("cue.size").that(cue.size).isEqualTo(size);
|
expect.withMessage("cue.size").that(cue.size).isEqualTo(size);
|
||||||
|
expect.withMessage("cue.verticalType").that(cue.verticalType).isEqualTo(verticalType);
|
||||||
|
|
||||||
assertThat(expect.hasFailures()).isFalse();
|
assertThat(expect.hasFailures()).isFalse();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user