From 27bda610aa60b5b30e3d3b14888045d5f1cad21a Mon Sep 17 00:00:00 2001 From: jbibik Date: Thu, 20 Jul 2023 14:06:14 +0100 Subject: [PATCH] Standardise the use of `ParsableByteArray` use among `SubtitleParsers` PiperOrigin-RevId: 549609028 --- .../media3/extractor/text/dvb/DvbParser.java | 10 ++----- .../media3/extractor/text/pgs/PgsParser.java | 13 ++------- .../media3/extractor/text/ssa/SsaParser.java | 18 +++++------- .../extractor/text/subrip/SubripParser.java | 22 ++++++-------- .../extractor/text/tx3g/Tx3gParser.java | 13 ++------- .../text/webvtt/Mp4WebvttParser.java | 29 +++++++------------ .../extractor/text/webvtt/WebvttParser.java | 2 +- 7 files changed, 33 insertions(+), 74 deletions(-) diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/text/dvb/DvbParser.java b/libraries/extractor/src/main/java/androidx/media3/extractor/text/dvb/DvbParser.java index bc043edc84..0ba7da8bfc 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/text/dvb/DvbParser.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/text/dvb/DvbParser.java @@ -91,7 +91,6 @@ public final class DvbParser implements SubtitleParser { private final DisplayDefinition defaultDisplayDefinition; private final ClutDefinition defaultClutDefinition; private final SubtitleService subtitleService; - private byte[] dataScratch = Util.EMPTY_BYTE_ARRAY; private @MonotonicNonNull Bitmap bitmap; @@ -131,13 +130,8 @@ public final class DvbParser implements SubtitleParser { @Override public ImmutableList parse(byte[] data, int offset, int length) { - // Parse the input data. - if (dataScratch.length < length) { - dataScratch = new byte[length]; - } - System.arraycopy( - /* src= */ data, /* scrPos= */ offset, /* dest= */ dataScratch, /* destPos= */ 0, length); - ParsableBitArray dataBitArray = new ParsableBitArray(dataScratch, length); + ParsableBitArray dataBitArray = new ParsableBitArray(data, /* limit= */ offset + length); + dataBitArray.setPosition(offset); while (dataBitArray.bitsLeft() >= 48 // sync_byte (8) + segment header (40) && dataBitArray.readBits(8) == 0x0F) { parseSubtitlingSegment(dataBitArray, subtitleService); diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/text/pgs/PgsParser.java b/libraries/extractor/src/main/java/androidx/media3/extractor/text/pgs/PgsParser.java index 95a76cdd9a..95d7e343b8 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/text/pgs/PgsParser.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/text/pgs/PgsParser.java @@ -45,7 +45,6 @@ public final class PgsParser implements SubtitleParser { private final ParsableByteArray buffer; private final ParsableByteArray inflatedBuffer; private final CueBuilder cueBuilder; - private byte[] dataScratch = Util.EMPTY_BYTE_ARRAY; @Nullable private Inflater inflater; public PgsParser() { @@ -59,16 +58,8 @@ public final class PgsParser implements SubtitleParser { @Override public ImmutableList parse(byte[] data, int offset, int length) { - if (offset != 0) { - if (dataScratch.length < length) { - dataScratch = new byte[length]; - } - System.arraycopy( - /* src= */ data, /* scrPos= */ offset, /* dest= */ dataScratch, /* destPos= */ 0, length); - buffer.reset(dataScratch, length); - } else { - buffer.reset(data, length); - } + buffer.reset(data, /* limit= */ offset + length); + buffer.setPosition(offset); maybeInflateData(buffer); cueBuilder.reset(); ArrayList cues = new ArrayList<>(); diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/text/ssa/SsaParser.java b/libraries/extractor/src/main/java/androidx/media3/extractor/text/ssa/SsaParser.java index 371aad6484..46c8f17a48 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/text/ssa/SsaParser.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/text/ssa/SsaParser.java @@ -65,6 +65,7 @@ public final class SsaParser implements SubtitleParser { private final boolean haveInitializationData; @Nullable private final SsaDialogueFormat dialogueFormatFromInitializationData; + private final ParsableByteArray parsableByteArray; private @MonotonicNonNull Map styles; @@ -82,8 +83,6 @@ public final class SsaParser implements SubtitleParser { */ private float screenHeight; - private byte[] dataScratch = Util.EMPTY_BYTE_ARRAY; - public SsaParser() { this(/* initializationData= */ null); } @@ -100,6 +99,7 @@ public final class SsaParser implements SubtitleParser { public SsaParser(@Nullable List initializationData) { screenWidth = Cue.DIMEN_UNSET; screenHeight = Cue.DIMEN_UNSET; + parsableByteArray = new ParsableByteArray(); if (initializationData != null && !initializationData.isEmpty()) { haveInitializationData = true; @@ -126,18 +126,14 @@ public final class SsaParser implements SubtitleParser { List> cues = new ArrayList<>(); List startTimesUs = new ArrayList<>(); - if (dataScratch.length < length) { - dataScratch = new byte[length]; - } - System.arraycopy( - /* src= */ data, /* scrPos= */ offset, /* dest= */ dataScratch, /* destPos= */ 0, length); - ParsableByteArray parsableData = new ParsableByteArray(dataScratch, length); - Charset charset = detectUtfCharset(parsableData); + parsableByteArray.reset(data, /* limit= */ offset + length); + parsableByteArray.setPosition(offset); + Charset charset = detectUtfCharset(parsableByteArray); if (!haveInitializationData) { - parseHeader(parsableData, charset); + parseHeader(parsableByteArray, charset); } - parseEventBody(parsableData, cues, startTimesUs, charset); + parseEventBody(parsableByteArray, cues, startTimesUs, charset); ImmutableList.Builder cuesWithStartTimeAndDuration = ImmutableList.builder(); for (int i = 0; i < cues.size(); i++) { diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/text/subrip/SubripParser.java b/libraries/extractor/src/main/java/androidx/media3/extractor/text/subrip/SubripParser.java index ff4b05006a..b6b2bf3339 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/text/subrip/SubripParser.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/text/subrip/SubripParser.java @@ -27,7 +27,6 @@ import androidx.media3.common.util.Assertions; import androidx.media3.common.util.Log; import androidx.media3.common.util.ParsableByteArray; import androidx.media3.common.util.UnstableApi; -import androidx.media3.common.util.Util; import androidx.media3.extractor.text.CuesWithTiming; import androidx.media3.extractor.text.SubtitleParser; import com.google.common.base.Charsets; @@ -70,11 +69,12 @@ public final class SubripParser implements SubtitleParser { private final StringBuilder textBuilder; private final ArrayList tags; - private byte[] dataScratch = Util.EMPTY_BYTE_ARRAY; + private final ParsableByteArray parsableByteArray; public SubripParser() { textBuilder = new StringBuilder(); tags = new ArrayList<>(); + parsableByteArray = new ParsableByteArray(); } @Nullable @@ -82,16 +82,12 @@ public final class SubripParser implements SubtitleParser { public ImmutableList parse(byte[] data, int offset, int length) { ImmutableList.Builder cues = new ImmutableList.Builder<>(); - if (dataScratch.length < length) { - dataScratch = new byte[length]; - } - System.arraycopy( - /* src= */ data, /* scrPos= */ offset, /* dest= */ dataScratch, /* destPos= */ 0, length); - ParsableByteArray subripData = new ParsableByteArray(dataScratch, length); - Charset charset = detectUtfCharset(subripData); + parsableByteArray.reset(data, /* limit= */ offset + length); + parsableByteArray.setPosition(offset); + Charset charset = detectUtfCharset(parsableByteArray); @Nullable String currentLine; - while ((currentLine = subripData.readLine(charset)) != null) { + while ((currentLine = parsableByteArray.readLine(charset)) != null) { if (currentLine.length() == 0) { // Skip blank lines. continue; @@ -106,7 +102,7 @@ public final class SubripParser implements SubtitleParser { } // Read and parse the timing line. - currentLine = subripData.readLine(charset); + currentLine = parsableByteArray.readLine(charset); if (currentLine == null) { Log.w(TAG, "Unexpected end"); break; @@ -126,13 +122,13 @@ public final class SubripParser implements SubtitleParser { // Read and parse the text and tags. textBuilder.setLength(0); tags.clear(); - currentLine = subripData.readLine(charset); + currentLine = parsableByteArray.readLine(charset); while (!TextUtils.isEmpty(currentLine)) { if (textBuilder.length() > 0) { textBuilder.append("
"); } textBuilder.append(processLine(currentLine, tags)); - currentLine = subripData.readLine(charset); + currentLine = parsableByteArray.readLine(charset); } Spanned text = Html.fromHtml(textBuilder.toString()); diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/text/tx3g/Tx3gParser.java b/libraries/extractor/src/main/java/androidx/media3/extractor/text/tx3g/Tx3gParser.java index bede7019dd..4dff6d9631 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/text/tx3g/Tx3gParser.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/text/tx3g/Tx3gParser.java @@ -79,7 +79,6 @@ public final class Tx3gParser implements SubtitleParser { private final String defaultFontFamily; private final float defaultVerticalPlacement; private final int calculatedVideoTrackHeight; - private byte[] dataScratch = Util.EMPTY_BYTE_ARRAY; /** * Sets up a new {@link Tx3gParser} with default values. @@ -128,16 +127,8 @@ public final class Tx3gParser implements SubtitleParser { @Override public ImmutableList parse(byte[] data, int offset, int length) { - if (offset != 0) { - if (dataScratch.length < length) { - dataScratch = new byte[length]; - } - System.arraycopy( - /* src= */ data, /* scrPos= */ offset, /* dest= */ dataScratch, /* destPos= */ 0, length); - parsableByteArray.reset(dataScratch, length); - } else { - parsableByteArray.reset(data, length); - } + parsableByteArray.reset(data, /* limit= */ offset + length); + parsableByteArray.setPosition(offset); String cueTextString = readSubtitleText(parsableByteArray); if (cueTextString.isEmpty()) { return ImmutableList.of( diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/text/webvtt/Mp4WebvttParser.java b/libraries/extractor/src/main/java/androidx/media3/extractor/text/webvtt/Mp4WebvttParser.java index 5820e0add5..dd2d1e10ee 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/text/webvtt/Mp4WebvttParser.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/text/webvtt/Mp4WebvttParser.java @@ -46,39 +46,30 @@ public final class Mp4WebvttParser implements SubtitleParser { @SuppressWarnings("ConstantCaseForConstants") private static final int TYPE_vttc = 0x76747463; - private final ParsableByteArray sampleData; - private byte[] dataScratch = Util.EMPTY_BYTE_ARRAY; + private final ParsableByteArray parsableByteArray; public Mp4WebvttParser() { - sampleData = new ParsableByteArray(); + parsableByteArray = new ParsableByteArray(); } @Override public ImmutableList parse(byte[] data, int offset, int length) { - if (offset != 0) { - if (dataScratch.length < length) { - dataScratch = new byte[length]; - } - System.arraycopy( - /* src= */ data, /* scrPos= */ offset, /* dest= */ dataScratch, /* destPos= */ 0, length); - sampleData.reset(dataScratch, length); - } else { - sampleData.reset(data, length); - } + parsableByteArray.reset(data, /* limit= */ offset + length); + parsableByteArray.setPosition(offset); List cues = new ArrayList<>(); - while (sampleData.bytesLeft() > 0) { + while (parsableByteArray.bytesLeft() > 0) { // Webvtt in Mp4 samples have boxes inside of them, so we have to do a traditional box // parsing: first 4 bytes size and then 4 bytes type. checkArgument( - sampleData.bytesLeft() >= BOX_HEADER_SIZE, + parsableByteArray.bytesLeft() >= BOX_HEADER_SIZE, "Incomplete Mp4Webvtt Top Level box header found."); - int boxSize = sampleData.readInt(); - int boxType = sampleData.readInt(); + int boxSize = parsableByteArray.readInt(); + int boxType = parsableByteArray.readInt(); if (boxType == TYPE_vttc) { - cues.add(parseVttCueBox(sampleData, boxSize - BOX_HEADER_SIZE)); + cues.add(parseVttCueBox(parsableByteArray, boxSize - BOX_HEADER_SIZE)); } else { // Peers of the VTTCueBox are still not supported and are skipped. - sampleData.skipBytes(boxSize - BOX_HEADER_SIZE); + parsableByteArray.skipBytes(boxSize - BOX_HEADER_SIZE); } } return cues.isEmpty() diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/text/webvtt/WebvttParser.java b/libraries/extractor/src/main/java/androidx/media3/extractor/text/webvtt/WebvttParser.java index 3281e74003..c6060168af 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/text/webvtt/WebvttParser.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/text/webvtt/WebvttParser.java @@ -53,7 +53,7 @@ public final class WebvttParser implements SubtitleParser { @Override public ImmutableList parse(byte[] data, int offset, int length) { - parsableWebvttData.reset(data, length); + parsableWebvttData.reset(data, /* limit= */ offset + length); parsableWebvttData.setPosition(offset); List definedStyles = new ArrayList<>();