From e67e28c4aaf4b9030056236b3289f94b10e8d2ec Mon Sep 17 00:00:00 2001 From: ibaker Date: Mon, 3 Jul 2023 15:11:11 +0000 Subject: [PATCH] Introduce `CuesWithTiming` and use it in `SubtitleParser` PiperOrigin-RevId: 545224876 --- .../media3/extractor/text/CuesWithTiming.java | 55 +++++++++++++++++++ .../media3/extractor/text/SubtitleParser.java | 25 +++++---- 2 files changed, 70 insertions(+), 10 deletions(-) create mode 100644 libraries/extractor/src/main/java/androidx/media3/extractor/text/CuesWithTiming.java diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/text/CuesWithTiming.java b/libraries/extractor/src/main/java/androidx/media3/extractor/text/CuesWithTiming.java new file mode 100644 index 0000000000..30d8141227 --- /dev/null +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/text/CuesWithTiming.java @@ -0,0 +1,55 @@ +/* + * Copyright 2023 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 + * + * https://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; + +import androidx.media3.common.C; +import androidx.media3.common.text.Cue; +import androidx.media3.common.util.UnstableApi; +import com.google.common.collect.ImmutableList; +import java.util.List; + +/** A list of {@link Cue} instances with a start time and duration. */ +@UnstableApi +public class CuesWithTiming { + + /** The cues to show on screen. */ + public final ImmutableList cues; + + /** + * The time at which {@link #cues} should be shown on screen, in microseconds. + * + *

The time base of this depends on the context from which this instance was obtained. + */ + public final long startTimeUs; + + /** + * The duration for which {@link #cues} should be shown on screen, in microseconds, or {@link + * C#TIME_UNSET} if not known. + * + *

If this value is set then {@link #cues} from multiple instances may be shown on the screen + * simultaneously (if their durations overlap). If this value is {@link C#TIME_UNSET} then {@link + * #cues} should be shown on the screen until the {@link #startTimeUs} of the next instance. + */ + public final long durationUs; + + /** Creates an instance. */ + public CuesWithTiming(List cues, long startTimeUs, long durationUs) { + this.cues = ImmutableList.copyOf(cues); + this.startTimeUs = startTimeUs; + this.durationUs = durationUs; + } +} diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/text/SubtitleParser.java b/libraries/extractor/src/main/java/androidx/media3/extractor/text/SubtitleParser.java index fba84727a2..ae6520b0f3 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/text/SubtitleParser.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/text/SubtitleParser.java @@ -17,15 +17,15 @@ package androidx.media3.extractor.text; import androidx.annotation.Nullable; -import androidx.media3.common.text.CueGroup; +import androidx.media3.common.Format; import androidx.media3.common.util.UnstableApi; import java.util.List; /** - * Parses subtitle data into timed {@linkplain CueGroup cue groups}. + * Parses subtitle data into timed {@linkplain CuesWithTiming} instances. * *

Instances are stateful, so samples can be fed in repeated calls to {@link #parse(byte[])}, and - * one or more complete {@link CueGroup} instances will be returned when enough data has been + * one or more complete {@link CuesWithTiming} instances will be returned when enough data has been * received. Due to this stateful-ness, {@link #reset()} must be called after a seek or similar * discontinuity in the source data. */ @@ -34,33 +34,38 @@ public interface SubtitleParser { /** * Parses {@code data} (and any data stored from previous invocations) and returns any resulting - * complete {@link CueGroup} instances. + * complete {@link CuesWithTiming} instances. * *

Equivalent to {@link #parse(byte[], int, int) parse(data, 0, data.length)}. */ @Nullable - default List parse(byte[] data) { + default List parse(byte[] data) { return parse(data, /* offset= */ 0, data.length); } /** * Parses {@code data} (and any data stored from previous invocations) and returns any resulting - * complete {@link CueGroup} instances. + * complete {@link CuesWithTiming} instances. * *

Any samples not used from {@code data} will be persisted and used during subsequent calls to * this method. * + *

{@link CuesWithTiming#startTimeUs} in the returned instance is derived only from the + * provided sample data, so has to be considered together with any relevant {@link + * Format#subsampleOffsetUs}. + * * @param data The subtitle data to parse. This must contain only complete samples. For subtitles * muxed inside a media container, a sample is usually defined by the container. For subtitles * read from a text file, a sample is usually the entire contents of the text file. * @param offset The index in {@code data} to start reading from (inclusive). * @param length The number of bytes to read from {@code data}. - * @return The {@linkplain CueGroup cue groups} parsed from {@code data} (and possibly previous - * provided samples too), sorted in ascending order by {@link CueGroup#presentationTimeUs}. - * Otherwise null if there is insufficient data to generate a complete {@link CueGroup}. + * @return The {@linkplain CuesWithTiming} instances parsed from {@code data} (and possibly + * previous provided samples too), sorted in ascending order by {@link + * CuesWithTiming#startTimeUs}. Otherwise null if there is insufficient data to generate a + * complete {@link CuesWithTiming}. */ @Nullable - List parse(byte[] data, int offset, int length); + List parse(byte[] data, int offset, int length); /** * Clears any data stored inside this parser from previous {@link #parse(byte[])} calls.