summaryrefslogtreecommitdiffstats
path: root/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/text/webvtt/WebvttCue.java
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/text/webvtt/WebvttCue.java')
-rw-r--r--mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/text/webvtt/WebvttCue.java319
1 files changed, 319 insertions, 0 deletions
diff --git a/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/text/webvtt/WebvttCue.java b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/text/webvtt/WebvttCue.java
new file mode 100644
index 0000000000..af701d8f54
--- /dev/null
+++ b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/text/webvtt/WebvttCue.java
@@ -0,0 +1,319 @@
+/*
+ * 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 org.mozilla.thirdparty.com.google.android.exoplayer2.text.webvtt;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.text.Layout.Alignment;
+import androidx.annotation.IntDef;
+import androidx.annotation.Nullable;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.text.Cue;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.util.Assertions;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.util.Log;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+/** A representation of a WebVTT cue. */
+public final class WebvttCue extends Cue {
+
+ private static final float DEFAULT_POSITION = 0.5f;
+
+ public final long startTime;
+ public final long endTime;
+
+ private WebvttCue(
+ long startTime,
+ long endTime,
+ CharSequence text,
+ @Nullable Alignment textAlignment,
+ float line,
+ @Cue.LineType int lineType,
+ @Cue.AnchorType int lineAnchor,
+ float position,
+ @Cue.AnchorType int positionAnchor,
+ float width) {
+ super(text, textAlignment, line, lineType, lineAnchor, position, positionAnchor, width);
+ this.startTime = startTime;
+ this.endTime = endTime;
+ }
+
+ /**
+ * Returns whether or not this cue should be placed in the default position and rolled-up with
+ * the other "normal" cues.
+ *
+ * @return Whether this cue should be placed in the default position.
+ */
+ public boolean isNormalCue() {
+ return (line == DIMEN_UNSET && position == DEFAULT_POSITION);
+ }
+
+ /** Builder for WebVTT cues. */
+ @SuppressWarnings("hiding")
+ 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({
+ TEXT_ALIGNMENT_START,
+ TEXT_ALIGNMENT_CENTER,
+ TEXT_ALIGNMENT_END,
+ TEXT_ALIGNMENT_LEFT,
+ TEXT_ALIGNMENT_RIGHT
+ })
+ public @interface TextAlignment {}
+ /**
+ * See WebVTT's <a
+ * href="https://www.w3.org/TR/webvtt1/#webvtt-cue-start-alignment">align:start</a>.
+ */
+ public static final int TEXT_ALIGNMENT_START = 1;
+
+ /**
+ * See WebVTT's <a
+ * href="https://www.w3.org/TR/webvtt1/#webvtt-cue-center-alignment">align:center</a>.
+ */
+ public static final int TEXT_ALIGNMENT_CENTER = 2;
+
+ /**
+ * See WebVTT's <a href="https://www.w3.org/TR/webvtt1/#webvtt-cue-end-alignment">align:end</a>.
+ */
+ public static final int TEXT_ALIGNMENT_END = 3;
+
+ /**
+ * See WebVTT's <a href="https://www.w3.org/TR/webvtt1/#webvtt-cue-left-alignment">align:left</a>.
+ */
+ public static final int TEXT_ALIGNMENT_LEFT = 4;
+
+ /**
+ * See WebVTT's <a
+ * href="https://www.w3.org/TR/webvtt1/#webvtt-cue-right-alignment">align:right</a>.
+ */
+ public static final int TEXT_ALIGNMENT_RIGHT = 5;
+
+ private static final String TAG = "WebvttCueBuilder";
+
+ private long startTime;
+ private long endTime;
+ @Nullable private CharSequence text;
+ @TextAlignment private int textAlignment;
+ private float line;
+ // Equivalent to WebVTT's snap-to-lines flag:
+ // https://www.w3.org/TR/webvtt1/#webvtt-cue-snap-to-lines-flag
+ @LineType private int lineType;
+ @AnchorType private int lineAnchor;
+ private float position;
+ @AnchorType private int positionAnchor;
+ private float width;
+
+ // Initialization methods
+
+ // Calling reset() is forbidden because `this` isn't initialized. This can be safely
+ // suppressed because reset() only assigns fields, it doesn't read any.
+ @SuppressWarnings("nullness:method.invocation.invalid")
+ public Builder() {
+ reset();
+ }
+
+ public void reset() {
+ startTime = 0;
+ endTime = 0;
+ text = null;
+ // Default: https://www.w3.org/TR/webvtt1/#webvtt-cue-text-alignment
+ textAlignment = TEXT_ALIGNMENT_CENTER;
+ line = Cue.DIMEN_UNSET;
+ // Defaults to NUMBER (true): https://www.w3.org/TR/webvtt1/#webvtt-cue-snap-to-lines-flag
+ 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;
+ positionAnchor = Cue.TYPE_UNSET;
+ // Default: https://www.w3.org/TR/webvtt1/#webvtt-cue-size
+ width = 1.0f;
+ }
+
+ // Construction methods.
+
+ public WebvttCue build() {
+ line = computeLine(line, lineType);
+
+ if (position == Cue.DIMEN_UNSET) {
+ position = derivePosition(textAlignment);
+ }
+
+ if (positionAnchor == Cue.TYPE_UNSET) {
+ positionAnchor = derivePositionAnchor(textAlignment);
+ }
+
+ width = Math.min(width, deriveMaxSize(positionAnchor, position));
+
+ return new WebvttCue(
+ startTime,
+ endTime,
+ Assertions.checkNotNull(text),
+ convertTextAlignment(textAlignment),
+ line,
+ lineType,
+ lineAnchor,
+ position,
+ positionAnchor,
+ width);
+ }
+
+ public Builder setStartTime(long time) {
+ startTime = time;
+ return this;
+ }
+
+ public Builder setEndTime(long time) {
+ endTime = time;
+ return this;
+ }
+
+ public Builder setText(CharSequence text) {
+ this.text = text;
+ return this;
+ }
+
+ public Builder setTextAlignment(@TextAlignment int textAlignment) {
+ this.textAlignment = textAlignment;
+ return this;
+ }
+
+ public Builder setLine(float line) {
+ this.line = line;
+ return this;
+ }
+
+ public Builder setLineType(@LineType int lineType) {
+ this.lineType = lineType;
+ return this;
+ }
+
+ public Builder setLineAnchor(@AnchorType int lineAnchor) {
+ this.lineAnchor = lineAnchor;
+ return this;
+ }
+
+ public Builder setPosition(float position) {
+ this.position = position;
+ return this;
+ }
+
+ public Builder setPositionAnchor(@AnchorType int positionAnchor) {
+ this.positionAnchor = positionAnchor;
+ return this;
+ }
+
+ public Builder setWidth(float width) {
+ this.width = width;
+ return this;
+ }
+
+ // https://www.w3.org/TR/webvtt1/#webvtt-cue-line
+ private static float computeLine(float line, @LineType int lineType) {
+ 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 {
+ // Steps 4 - 10 (stacking multiple simultaneous cues) are handled by WebvttSubtitle#getCues
+ // and WebvttCue#isNormalCue.
+ return DIMEN_UNSET;
+ }
+ }
+
+ // https://www.w3.org/TR/webvtt1/#webvtt-cue-position
+ private static float derivePosition(@TextAlignment int textAlignment) {
+ switch (textAlignment) {
+ case TEXT_ALIGNMENT_LEFT:
+ return 0.0f;
+ case TEXT_ALIGNMENT_RIGHT:
+ return 1.0f;
+ case TEXT_ALIGNMENT_START:
+ case TEXT_ALIGNMENT_CENTER:
+ case TEXT_ALIGNMENT_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 TEXT_ALIGNMENT_LEFT:
+ case TEXT_ALIGNMENT_START:
+ return Cue.ANCHOR_TYPE_START;
+ case TEXT_ALIGNMENT_RIGHT:
+ case TEXT_ALIGNMENT_END:
+ return Cue.ANCHOR_TYPE_END;
+ case TEXT_ALIGNMENT_CENTER:
+ default:
+ return Cue.ANCHOR_TYPE_MIDDLE;
+ }
+ }
+
+ @Nullable
+ private static Alignment convertTextAlignment(@TextAlignment int textAlignment) {
+ switch (textAlignment) {
+ case TEXT_ALIGNMENT_START:
+ case TEXT_ALIGNMENT_LEFT:
+ return Alignment.ALIGN_NORMAL;
+ case TEXT_ALIGNMENT_CENTER:
+ return Alignment.ALIGN_CENTER;
+ case TEXT_ALIGNMENT_END:
+ case TEXT_ALIGNMENT_RIGHT:
+ return Alignment.ALIGN_OPPOSITE;
+ default:
+ Log.w(TAG, "Unknown textAlignment: " + textAlignment);
+ return null;
+ }
+ }
+
+ // Step 2 here: https://www.w3.org/TR/webvtt1/#processing-cue-settings
+ private static float deriveMaxSize(@AnchorType int positionAnchor, float position) {
+ switch (positionAnchor) {
+ case Cue.ANCHOR_TYPE_START:
+ return 1.0f - position;
+ case Cue.ANCHOR_TYPE_END:
+ return position;
+ case Cue.ANCHOR_TYPE_MIDDLE:
+ if (position <= 0.5f) {
+ return position * 2;
+ } else {
+ return (1.0f - position) * 2;
+ }
+ case Cue.TYPE_UNSET:
+ default:
+ throw new IllegalStateException(String.valueOf(positionAnchor));
+ }
+ }
+ }
+}