Update WebvttCue to use defaults from the spec
Cue's UNSET and null values should be used when the source data doesn't specify *and* the spec doesn't provide a clear default. In the WebVTT case, the defaults are clear, so we use them explicitly. PiperOrigin-RevId: 277522899
This commit is contained in:
parent
0c63362258
commit
b3f94e3768
@ -15,15 +15,23 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.text.webvtt;
|
package com.google.android.exoplayer2.text.webvtt;
|
||||||
|
|
||||||
|
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||||
|
|
||||||
import android.text.Layout.Alignment;
|
import android.text.Layout.Alignment;
|
||||||
|
import androidx.annotation.IntDef;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.text.Cue;
|
import com.google.android.exoplayer2.text.Cue;
|
||||||
import com.google.android.exoplayer2.util.Log;
|
import com.google.android.exoplayer2.util.Log;
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A representation of a WebVTT cue.
|
* A representation of a WebVTT cue.
|
||||||
*/
|
*/
|
||||||
public final class WebvttCue extends Cue {
|
public final class WebvttCue extends Cue {
|
||||||
|
|
||||||
|
private static final float DEFAULT_POSITION = 0.5f;
|
||||||
|
|
||||||
public final long startTime;
|
public final long startTime;
|
||||||
public final long endTime;
|
public final long endTime;
|
||||||
|
|
||||||
@ -50,26 +58,73 @@ public final class WebvttCue extends Cue {
|
|||||||
* @return Whether this cue should be placed in the default position.
|
* @return Whether this cue should be placed in the default position.
|
||||||
*/
|
*/
|
||||||
public boolean isNormalCue() {
|
public boolean isNormalCue() {
|
||||||
return (line == DIMEN_UNSET && position == DIMEN_UNSET);
|
return (line == DIMEN_UNSET && position == DEFAULT_POSITION);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Builder for WebVTT cues. */
|
||||||
* Builder for WebVTT cues.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("hiding")
|
@SuppressWarnings("hiding")
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Valid values for {@link #setTextAlignment(int)}.
|
||||||
|
*
|
||||||
|
* <p>We use a custom list (and not {@link Alignment} directly) in order to include both {@code
|
||||||
|
* START}/{@code LEFT} and {@code END}/{@code RIGHT}. The distinction is important for {@link
|
||||||
|
* #derivePosition(int)}.
|
||||||
|
*
|
||||||
|
* <p>These correspond to the valid values for the 'align' cue setting in the <a
|
||||||
|
* href="https://www.w3.org/TR/webvtt1/#webvtt-cue-text-alignment">WebVTT spec</a>.
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Retention(SOURCE)
|
||||||
|
@IntDef({
|
||||||
|
TextAlignment.START,
|
||||||
|
TextAlignment.CENTER,
|
||||||
|
TextAlignment.END,
|
||||||
|
TextAlignment.LEFT,
|
||||||
|
TextAlignment.RIGHT
|
||||||
|
})
|
||||||
|
public @interface TextAlignment {
|
||||||
|
/**
|
||||||
|
* See WebVTT's <a
|
||||||
|
* href="https://www.w3.org/TR/webvtt1/#webvtt-cue-start-alignment">align:start</a>.
|
||||||
|
*/
|
||||||
|
int START = 1;
|
||||||
|
/**
|
||||||
|
* See WebVTT's <a
|
||||||
|
* href="https://www.w3.org/TR/webvtt1/#webvtt-cue-center-alignment">align:center</a>.
|
||||||
|
*/
|
||||||
|
int CENTER = 2;
|
||||||
|
/**
|
||||||
|
* See WebVTT's <a
|
||||||
|
* href="https://www.w3.org/TR/webvtt1/#webvtt-cue-end-alignment">align:end</a>.
|
||||||
|
*/
|
||||||
|
int END = 3;
|
||||||
|
/**
|
||||||
|
* See WebVTT's <a
|
||||||
|
* href="https://www.w3.org/TR/webvtt1/#webvtt-cue-left-alignment">align:left</a>.
|
||||||
|
*/
|
||||||
|
int LEFT = 4;
|
||||||
|
/**
|
||||||
|
* See WebVTT's <a
|
||||||
|
* href="https://www.w3.org/TR/webvtt1/#webvtt-cue-right-alignment">align:right</a>.
|
||||||
|
*/
|
||||||
|
int RIGHT = 5;
|
||||||
|
}
|
||||||
|
|
||||||
private static final String TAG = "WebvttCueBuilder";
|
private static final String TAG = "WebvttCueBuilder";
|
||||||
|
|
||||||
private long startTime;
|
private long startTime;
|
||||||
private long endTime;
|
private long endTime;
|
||||||
private CharSequence text;
|
@Nullable private CharSequence text;
|
||||||
private Alignment textAlignment;
|
@TextAlignment private int textAlignment;
|
||||||
private float line;
|
private float line;
|
||||||
private int lineType;
|
// Equivalent to WebVTT's snap-to-lines flag:
|
||||||
private int lineAnchor;
|
// https://www.w3.org/TR/webvtt1/#webvtt-cue-snap-to-lines-flag
|
||||||
|
@LineType private int lineType;
|
||||||
|
@AnchorType private int lineAnchor;
|
||||||
private float position;
|
private float position;
|
||||||
private int positionAnchor;
|
@AnchorType private int positionAnchor;
|
||||||
private float width;
|
private float width;
|
||||||
|
|
||||||
// Initialization methods
|
// Initialization methods
|
||||||
@ -82,23 +137,43 @@ public final class WebvttCue extends Cue {
|
|||||||
startTime = 0;
|
startTime = 0;
|
||||||
endTime = 0;
|
endTime = 0;
|
||||||
text = null;
|
text = null;
|
||||||
textAlignment = null;
|
// Default: https://www.w3.org/TR/webvtt1/#webvtt-cue-text-alignment
|
||||||
|
textAlignment = TextAlignment.CENTER;
|
||||||
line = Cue.DIMEN_UNSET;
|
line = Cue.DIMEN_UNSET;
|
||||||
lineType = Cue.TYPE_UNSET;
|
// Defaults to NUMBER (true): https://www.w3.org/TR/webvtt1/#webvtt-cue-snap-to-lines-flag
|
||||||
lineAnchor = Cue.TYPE_UNSET;
|
lineType = Cue.LINE_TYPE_NUMBER;
|
||||||
|
// Default: https://www.w3.org/TR/webvtt1/#webvtt-cue-line-alignment
|
||||||
|
lineAnchor = Cue.ANCHOR_TYPE_START;
|
||||||
position = Cue.DIMEN_UNSET;
|
position = Cue.DIMEN_UNSET;
|
||||||
positionAnchor = Cue.TYPE_UNSET;
|
positionAnchor = Cue.TYPE_UNSET;
|
||||||
width = Cue.DIMEN_UNSET;
|
// Default: https://www.w3.org/TR/webvtt1/#webvtt-cue-size
|
||||||
|
width = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construction methods.
|
// Construction methods.
|
||||||
|
|
||||||
public WebvttCue build() {
|
public WebvttCue build() {
|
||||||
if (position != Cue.DIMEN_UNSET && positionAnchor == Cue.TYPE_UNSET) {
|
line = computeLine(line, lineType);
|
||||||
derivePositionAnchorFromAlignment();
|
|
||||||
|
if (position == Cue.DIMEN_UNSET) {
|
||||||
|
position = derivePosition(textAlignment);
|
||||||
}
|
}
|
||||||
return new WebvttCue(startTime, endTime, text, textAlignment, line, lineType, lineAnchor,
|
|
||||||
position, positionAnchor, width);
|
if (positionAnchor == Cue.TYPE_UNSET) {
|
||||||
|
positionAnchor = derivePositionAnchor(textAlignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new WebvttCue(
|
||||||
|
startTime,
|
||||||
|
endTime,
|
||||||
|
text,
|
||||||
|
convertTextAlignment(textAlignment),
|
||||||
|
line,
|
||||||
|
lineType,
|
||||||
|
lineAnchor,
|
||||||
|
position,
|
||||||
|
positionAnchor,
|
||||||
|
width);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setStartTime(long time) {
|
public Builder setStartTime(long time) {
|
||||||
@ -116,7 +191,7 @@ public final class WebvttCue extends Cue {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setTextAlignment(Alignment textAlignment) {
|
public Builder setTextAlignment(@TextAlignment int textAlignment) {
|
||||||
this.textAlignment = textAlignment;
|
this.textAlignment = textAlignment;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -126,12 +201,12 @@ public final class WebvttCue extends Cue {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setLineType(int lineType) {
|
public Builder setLineType(@LineType int lineType) {
|
||||||
this.lineType = lineType;
|
this.lineType = lineType;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setLineAnchor(int lineAnchor) {
|
public Builder setLineAnchor(@AnchorType int lineAnchor) {
|
||||||
this.lineAnchor = lineAnchor;
|
this.lineAnchor = lineAnchor;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -141,7 +216,7 @@ public final class WebvttCue extends Cue {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setPositionAnchor(int positionAnchor) {
|
public Builder setPositionAnchor(@AnchorType int positionAnchor) {
|
||||||
this.positionAnchor = positionAnchor;
|
this.positionAnchor = positionAnchor;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -151,29 +226,69 @@ public final class WebvttCue extends Cue {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Builder derivePositionAnchorFromAlignment() {
|
// https://www.w3.org/TR/webvtt1/#webvtt-cue-line
|
||||||
if (textAlignment == null) {
|
private static float computeLine(float line, @LineType int lineType) {
|
||||||
positionAnchor = Cue.TYPE_UNSET;
|
if (line != Cue.DIMEN_UNSET
|
||||||
|
&& lineType == Cue.LINE_TYPE_FRACTION
|
||||||
|
&& (line < 0.0f || line > 1.0f)) {
|
||||||
|
return 1.0f; // Step 1
|
||||||
|
} else if (line != Cue.DIMEN_UNSET) {
|
||||||
|
// Step 2: Do nothing, line is already correct.
|
||||||
|
return line;
|
||||||
|
} else if (lineType == Cue.LINE_TYPE_FRACTION) {
|
||||||
|
return 1.0f; // Step 3
|
||||||
} else {
|
} else {
|
||||||
switch (textAlignment) {
|
// Steps 4 - 10 (stacking multiple simultaneous cues) are handled by WebvttSubtitle#getCues
|
||||||
case ALIGN_NORMAL:
|
// and WebvttCue#isNormalCue.
|
||||||
positionAnchor = Cue.ANCHOR_TYPE_START;
|
return DIMEN_UNSET;
|
||||||
break;
|
|
||||||
case ALIGN_CENTER:
|
|
||||||
positionAnchor = Cue.ANCHOR_TYPE_MIDDLE;
|
|
||||||
break;
|
|
||||||
case ALIGN_OPPOSITE:
|
|
||||||
positionAnchor = Cue.ANCHOR_TYPE_END;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Log.w(TAG, "Unrecognized alignment: " + textAlignment);
|
|
||||||
positionAnchor = Cue.ANCHOR_TYPE_START;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
// https://www.w3.org/TR/webvtt1/#webvtt-cue-position
|
||||||
|
private static float derivePosition(@TextAlignment int textAlignment) {
|
||||||
|
switch (textAlignment) {
|
||||||
|
case TextAlignment.LEFT:
|
||||||
|
return 0.0f;
|
||||||
|
case TextAlignment.RIGHT:
|
||||||
|
return 1.0f;
|
||||||
|
case TextAlignment.START:
|
||||||
|
case TextAlignment.CENTER:
|
||||||
|
case TextAlignment.END:
|
||||||
|
default:
|
||||||
|
return DEFAULT_POSITION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/webvtt1/#webvtt-cue-position-alignment
|
||||||
|
@AnchorType
|
||||||
|
private static int derivePositionAnchor(@TextAlignment int textAlignment) {
|
||||||
|
switch (textAlignment) {
|
||||||
|
case TextAlignment.LEFT:
|
||||||
|
case TextAlignment.START:
|
||||||
|
return Cue.ANCHOR_TYPE_START;
|
||||||
|
case TextAlignment.RIGHT:
|
||||||
|
case TextAlignment.END:
|
||||||
|
return Cue.ANCHOR_TYPE_END;
|
||||||
|
case TextAlignment.CENTER:
|
||||||
|
default:
|
||||||
|
return Cue.ANCHOR_TYPE_MIDDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Alignment convertTextAlignment(@TextAlignment int textAlignment) {
|
||||||
|
switch (textAlignment) {
|
||||||
|
case TextAlignment.START:
|
||||||
|
case TextAlignment.LEFT:
|
||||||
|
return Alignment.ALIGN_NORMAL;
|
||||||
|
case TextAlignment.CENTER:
|
||||||
|
return Alignment.ALIGN_CENTER;
|
||||||
|
case TextAlignment.END:
|
||||||
|
case TextAlignment.RIGHT:
|
||||||
|
return Alignment.ALIGN_OPPOSITE;
|
||||||
|
default:
|
||||||
|
Log.w(TAG, "Unknown textAlignment: " + textAlignment);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
package com.google.android.exoplayer2.text.webvtt;
|
package com.google.android.exoplayer2.text.webvtt;
|
||||||
|
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.text.Layout.Alignment;
|
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
@ -87,7 +86,7 @@ public final class WebvttCueParser {
|
|||||||
* Parses the next valid WebVTT cue in a parsable array, including timestamps, settings and text.
|
* Parses the next valid WebVTT cue in a parsable array, including timestamps, settings and text.
|
||||||
*
|
*
|
||||||
* @param webvttData Parsable WebVTT file data.
|
* @param webvttData Parsable WebVTT file data.
|
||||||
* @param builder Builder for WebVTT Cues.
|
* @param builder Builder for WebVTT Cues (output parameter).
|
||||||
* @param styles List of styles defined by the CSS style blocks preceding the cues.
|
* @param styles List of styles defined by the CSS style blocks preceding the cues.
|
||||||
* @return Whether a valid Cue was found.
|
* @return Whether a valid Cue was found.
|
||||||
*/
|
*/
|
||||||
@ -252,14 +251,11 @@ public final class WebvttCueParser {
|
|||||||
|
|
||||||
// Internal methods
|
// Internal methods
|
||||||
|
|
||||||
private static void parseLineAttribute(String s, WebvttCue.Builder builder)
|
private static void parseLineAttribute(String s, WebvttCue.Builder builder) {
|
||||||
throws NumberFormatException {
|
|
||||||
int commaIndex = s.indexOf(',');
|
int commaIndex = s.indexOf(',');
|
||||||
if (commaIndex != -1) {
|
if (commaIndex != -1) {
|
||||||
builder.setLineAnchor(parsePositionAnchor(s.substring(commaIndex + 1)));
|
builder.setLineAnchor(parsePositionAnchor(s.substring(commaIndex + 1)));
|
||||||
s = s.substring(0, commaIndex);
|
s = s.substring(0, commaIndex);
|
||||||
} else {
|
|
||||||
builder.setLineAnchor(Cue.TYPE_UNSET);
|
|
||||||
}
|
}
|
||||||
if (s.endsWith("%")) {
|
if (s.endsWith("%")) {
|
||||||
builder.setLine(WebvttParserUtil.parsePercentage(s)).setLineType(Cue.LINE_TYPE_FRACTION);
|
builder.setLine(WebvttParserUtil.parsePercentage(s)).setLineType(Cue.LINE_TYPE_FRACTION);
|
||||||
@ -274,18 +270,16 @@ public final class WebvttCueParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void parsePositionAttribute(String s, WebvttCue.Builder builder)
|
private static void parsePositionAttribute(String s, WebvttCue.Builder builder) {
|
||||||
throws NumberFormatException {
|
|
||||||
int commaIndex = s.indexOf(',');
|
int commaIndex = s.indexOf(',');
|
||||||
if (commaIndex != -1) {
|
if (commaIndex != -1) {
|
||||||
builder.setPositionAnchor(parsePositionAnchor(s.substring(commaIndex + 1)));
|
builder.setPositionAnchor(parsePositionAnchor(s.substring(commaIndex + 1)));
|
||||||
s = s.substring(0, commaIndex);
|
s = s.substring(0, commaIndex);
|
||||||
} else {
|
|
||||||
builder.setPositionAnchor(Cue.TYPE_UNSET);
|
|
||||||
}
|
}
|
||||||
builder.setPosition(WebvttParserUtil.parsePercentage(s));
|
builder.setPosition(WebvttParserUtil.parsePercentage(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Cue.AnchorType
|
||||||
private static int parsePositionAnchor(String s) {
|
private static int parsePositionAnchor(String s) {
|
||||||
switch (s) {
|
switch (s) {
|
||||||
case "start":
|
case "start":
|
||||||
@ -301,20 +295,24 @@ public final class WebvttCueParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Alignment parseTextAlignment(String s) {
|
@WebvttCue.Builder.TextAlignment
|
||||||
|
private static int parseTextAlignment(String s) {
|
||||||
switch (s) {
|
switch (s) {
|
||||||
case "start":
|
case "start":
|
||||||
|
return WebvttCue.Builder.TextAlignment.START;
|
||||||
case "left":
|
case "left":
|
||||||
return Alignment.ALIGN_NORMAL;
|
return WebvttCue.Builder.TextAlignment.LEFT;
|
||||||
case "center":
|
case "center":
|
||||||
case "middle":
|
case "middle":
|
||||||
return Alignment.ALIGN_CENTER;
|
return WebvttCue.Builder.TextAlignment.CENTER;
|
||||||
case "end":
|
case "end":
|
||||||
|
return WebvttCue.Builder.TextAlignment.END;
|
||||||
case "right":
|
case "right":
|
||||||
return Alignment.ALIGN_OPPOSITE;
|
return WebvttCue.Builder.TextAlignment.RIGHT;
|
||||||
default:
|
default:
|
||||||
Log.w(TAG, "Invalid alignment value: " + s);
|
Log.w(TAG, "Invalid alignment value: " + s);
|
||||||
return null;
|
// Default value: https://www.w3.org/TR/webvtt1/#webvtt-cue-text-alignment
|
||||||
|
return WebvttCue.Builder.TextAlignment.CENTER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,6 +83,9 @@ import java.util.List;
|
|||||||
list = new ArrayList<>();
|
list = new ArrayList<>();
|
||||||
}
|
}
|
||||||
WebvttCue cue = cues.get(i);
|
WebvttCue cue = cues.get(i);
|
||||||
|
// TODO(ibaker): Replace this with a closer implementation of the WebVTT spec (keeping
|
||||||
|
// individual cues, but tweaking their `line` value):
|
||||||
|
// https://www.w3.org/TR/webvtt1/#cue-computed-line
|
||||||
if (cue.isNormalCue()) {
|
if (cue.isNormalCue()) {
|
||||||
// we want to merge all of the normal cues into a single cue to ensure they are drawn
|
// we want to merge all of the normal cues into a single cue to ensure they are drawn
|
||||||
// correctly (i.e. don't overlap) and to emulate roll-up, but only if there are multiple
|
// correctly (i.e. don't overlap) and to emulate roll-up, but only if there are multiple
|
||||||
|
@ -21,13 +21,12 @@ NOTE Line as absolute negative number and without line alignment.
|
|||||||
00:06.000 --> 00:07.000 line:-10 align:middle
|
00:06.000 --> 00:07.000 line:-10 align:middle
|
||||||
This is the fourth subtitle.
|
This is the fourth subtitle.
|
||||||
|
|
||||||
NOTE The positioning alignment should be inherited from align.
|
NOTE The position and positioning alignment should be inherited from align.
|
||||||
|
|
||||||
00:07.000 --> 00:08.000 position:10% align:end size:10%
|
00:07.000 --> 00:08.000 align:right
|
||||||
This is the fifth subtitle.
|
This is the fifth subtitle.
|
||||||
|
|
||||||
NOTE In newer drafts, align:middle has been replaced by align:center
|
NOTE In newer drafts, align:middle has been replaced by align:center
|
||||||
|
|
||||||
00:10.000 --> 00:11.000 line:45%,end align:center size:35%
|
00:10.000 --> 00:11.000 line:45%,end align:center size:35%
|
||||||
This is the sixth subtitle.
|
This is the sixth subtitle.
|
||||||
|
|
||||||
|
@ -87,7 +87,8 @@ public final class Mp4WebvttDecoderTest {
|
|||||||
public void testSingleCueSample() throws SubtitleDecoderException {
|
public void testSingleCueSample() throws SubtitleDecoderException {
|
||||||
Mp4WebvttDecoder decoder = new Mp4WebvttDecoder();
|
Mp4WebvttDecoder decoder = new Mp4WebvttDecoder();
|
||||||
Subtitle result = decoder.decode(SINGLE_CUE_SAMPLE, SINGLE_CUE_SAMPLE.length, false);
|
Subtitle result = decoder.decode(SINGLE_CUE_SAMPLE, SINGLE_CUE_SAMPLE.length, false);
|
||||||
Cue expectedCue = new Cue("Hello World"); // Line feed must be trimmed by the decoder
|
// Line feed must be trimmed by the decoder
|
||||||
|
Cue expectedCue = new WebvttCue.Builder().setText("Hello World").build();
|
||||||
assertMp4WebvttSubtitleEquals(result, expectedCue);
|
assertMp4WebvttSubtitleEquals(result, expectedCue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,8 +96,8 @@ public final class Mp4WebvttDecoderTest {
|
|||||||
public void testTwoCuesSample() throws SubtitleDecoderException {
|
public void testTwoCuesSample() throws SubtitleDecoderException {
|
||||||
Mp4WebvttDecoder decoder = new Mp4WebvttDecoder();
|
Mp4WebvttDecoder decoder = new Mp4WebvttDecoder();
|
||||||
Subtitle result = decoder.decode(DOUBLE_CUE_SAMPLE, DOUBLE_CUE_SAMPLE.length, false);
|
Subtitle result = decoder.decode(DOUBLE_CUE_SAMPLE, DOUBLE_CUE_SAMPLE.length, false);
|
||||||
Cue firstExpectedCue = new Cue("Hello World");
|
Cue firstExpectedCue = new WebvttCue.Builder().setText("Hello World").build();
|
||||||
Cue secondExpectedCue = new Cue("Bye Bye");
|
Cue secondExpectedCue = new WebvttCue.Builder().setText("Bye Bye").build();
|
||||||
assertMp4WebvttSubtitleEquals(result, firstExpectedCue, secondExpectedCue);
|
assertMp4WebvttSubtitleEquals(result, firstExpectedCue, secondExpectedCue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +105,9 @@ public final class Mp4WebvttDecoderTest {
|
|||||||
public void testNoCueSample() throws SubtitleDecoderException {
|
public void testNoCueSample() throws SubtitleDecoderException {
|
||||||
Mp4WebvttDecoder decoder = new Mp4WebvttDecoder();
|
Mp4WebvttDecoder decoder = new Mp4WebvttDecoder();
|
||||||
Subtitle result = decoder.decode(NO_CUE_SAMPLE, NO_CUE_SAMPLE.length, false);
|
Subtitle result = decoder.decode(NO_CUE_SAMPLE, NO_CUE_SAMPLE.length, false);
|
||||||
assertMp4WebvttSubtitleEquals(result);
|
assertThat(result.getEventTimeCount()).isEqualTo(1);
|
||||||
|
assertThat(result.getEventTime(0)).isEqualTo(0);
|
||||||
|
assertThat(result.getCues(0)).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Negative tests.
|
// Negative tests.
|
||||||
|
@ -224,8 +224,8 @@ public class WebvttDecoderTest {
|
|||||||
"This is the first subtitle.",
|
"This is the first subtitle.",
|
||||||
Alignment.ALIGN_NORMAL,
|
Alignment.ALIGN_NORMAL,
|
||||||
/* line= */ Cue.DIMEN_UNSET,
|
/* line= */ Cue.DIMEN_UNSET,
|
||||||
/* lineType= */ Cue.TYPE_UNSET,
|
/* lineType= */ Cue.LINE_TYPE_NUMBER,
|
||||||
/* lineAnchor= */ Cue.TYPE_UNSET,
|
/* 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);
|
||||||
@ -237,10 +237,10 @@ public class WebvttDecoderTest {
|
|||||||
"This is the second subtitle.",
|
"This is the second subtitle.",
|
||||||
Alignment.ALIGN_OPPOSITE,
|
Alignment.ALIGN_OPPOSITE,
|
||||||
/* line= */ Cue.DIMEN_UNSET,
|
/* line= */ Cue.DIMEN_UNSET,
|
||||||
/* lineType= */ Cue.TYPE_UNSET,
|
/* lineType= */ Cue.LINE_TYPE_NUMBER,
|
||||||
/* lineAnchor= */ Cue.TYPE_UNSET,
|
/* lineAnchor= */ Cue.ANCHOR_TYPE_START,
|
||||||
/* position= */ Cue.DIMEN_UNSET,
|
/* position= */ 0.5f,
|
||||||
/* positionAnchor= */ Cue.TYPE_UNSET,
|
/* positionAnchor= */ Cue.ANCHOR_TYPE_END,
|
||||||
/* size= */ 0.35f);
|
/* size= */ 0.35f);
|
||||||
assertCue(
|
assertCue(
|
||||||
subtitle,
|
subtitle,
|
||||||
@ -252,8 +252,8 @@ public class WebvttDecoderTest {
|
|||||||
/* line= */ 0.45f,
|
/* line= */ 0.45f,
|
||||||
/* lineType= */ Cue.LINE_TYPE_FRACTION,
|
/* lineType= */ Cue.LINE_TYPE_FRACTION,
|
||||||
/* lineAnchor= */ Cue.ANCHOR_TYPE_END,
|
/* lineAnchor= */ Cue.ANCHOR_TYPE_END,
|
||||||
/* position= */ Cue.DIMEN_UNSET,
|
/* position= */ 0.5f,
|
||||||
/* positionAnchor= */ Cue.TYPE_UNSET,
|
/* positionAnchor= */ Cue.ANCHOR_TYPE_MIDDLE,
|
||||||
/* size= */ 0.35f);
|
/* size= */ 0.35f);
|
||||||
assertCue(
|
assertCue(
|
||||||
subtitle,
|
subtitle,
|
||||||
@ -262,12 +262,12 @@ public class WebvttDecoderTest {
|
|||||||
/* endTimeUs= */ 7000000,
|
/* endTimeUs= */ 7000000,
|
||||||
"This is the fourth subtitle.",
|
"This is the fourth subtitle.",
|
||||||
Alignment.ALIGN_CENTER,
|
Alignment.ALIGN_CENTER,
|
||||||
/* line= */ -11f,
|
/* line= */ -11.0f,
|
||||||
/* lineType= */ Cue.LINE_TYPE_NUMBER,
|
/* lineType= */ Cue.LINE_TYPE_NUMBER,
|
||||||
/* lineAnchor= */ Cue.TYPE_UNSET,
|
/* lineAnchor= */ Cue.ANCHOR_TYPE_START,
|
||||||
/* position= */ Cue.DIMEN_UNSET,
|
/* position= */ 0.5f,
|
||||||
/* positionAnchor= */ Cue.TYPE_UNSET,
|
/* positionAnchor= */ Cue.ANCHOR_TYPE_MIDDLE,
|
||||||
/* size= */ Cue.DIMEN_UNSET);
|
/* size= */ 1.0f);
|
||||||
assertCue(
|
assertCue(
|
||||||
subtitle,
|
subtitle,
|
||||||
/* eventTimeIndex= */ 8,
|
/* eventTimeIndex= */ 8,
|
||||||
@ -276,11 +276,11 @@ public class WebvttDecoderTest {
|
|||||||
"This is the fifth subtitle.",
|
"This is the fifth subtitle.",
|
||||||
Alignment.ALIGN_OPPOSITE,
|
Alignment.ALIGN_OPPOSITE,
|
||||||
/* line= */ Cue.DIMEN_UNSET,
|
/* line= */ Cue.DIMEN_UNSET,
|
||||||
/* lineType= */ Cue.TYPE_UNSET,
|
/* lineType= */ Cue.LINE_TYPE_NUMBER,
|
||||||
/* lineAnchor= */ Cue.TYPE_UNSET,
|
/* lineAnchor= */ Cue.ANCHOR_TYPE_START,
|
||||||
/* position= */ 0.1f,
|
/* position= */ 1.0f,
|
||||||
/* positionAnchor= */ Cue.ANCHOR_TYPE_END,
|
/* positionAnchor= */ Cue.ANCHOR_TYPE_END,
|
||||||
/* size= */ 0.1f);
|
/* size= */ 1.0f);
|
||||||
assertCue(
|
assertCue(
|
||||||
subtitle,
|
subtitle,
|
||||||
/* eventTimeIndex= */ 10,
|
/* eventTimeIndex= */ 10,
|
||||||
@ -291,8 +291,8 @@ public class WebvttDecoderTest {
|
|||||||
/* line= */ 0.45f,
|
/* line= */ 0.45f,
|
||||||
/* lineType= */ Cue.LINE_TYPE_FRACTION,
|
/* lineType= */ Cue.LINE_TYPE_FRACTION,
|
||||||
/* lineAnchor= */ Cue.ANCHOR_TYPE_END,
|
/* lineAnchor= */ Cue.ANCHOR_TYPE_END,
|
||||||
/* position= */ Cue.DIMEN_UNSET,
|
/* position= */ 0.5f,
|
||||||
/* positionAnchor= */ Cue.TYPE_UNSET,
|
/* positionAnchor= */ Cue.ANCHOR_TYPE_MIDDLE,
|
||||||
/* size= */ 0.35f);
|
/* size= */ 0.35f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,13 +412,13 @@ public class WebvttDecoderTest {
|
|||||||
startTimeUs,
|
startTimeUs,
|
||||||
endTimeUs,
|
endTimeUs,
|
||||||
text,
|
text,
|
||||||
/* textAlignment= */ null,
|
/* textAlignment= */ Alignment.ALIGN_CENTER,
|
||||||
/* line= */ Cue.DIMEN_UNSET,
|
/* line= */ Cue.DIMEN_UNSET,
|
||||||
/* lineType= */ Cue.TYPE_UNSET,
|
/* lineType= */ Cue.LINE_TYPE_NUMBER,
|
||||||
/* lineAnchor= */ Cue.TYPE_UNSET,
|
/* lineAnchor= */ Cue.ANCHOR_TYPE_START,
|
||||||
/* position= */ Cue.DIMEN_UNSET,
|
/* position= */ 0.5f,
|
||||||
/* positionAnchor= */ Cue.TYPE_UNSET,
|
/* positionAnchor= */ Cue.ANCHOR_TYPE_MIDDLE,
|
||||||
/* size= */ Cue.DIMEN_UNSET);
|
/* size= */ 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void assertCue(
|
private static void assertCue(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user