Standardise the use of ParsableByteArray use among SubtitleParsers

PiperOrigin-RevId: 549609028
This commit is contained in:
jbibik 2023-07-20 14:06:14 +01:00 committed by Rohit Singh
parent 9128293236
commit 27bda610aa
7 changed files with 33 additions and 74 deletions

View File

@ -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<CuesWithTiming> 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);

View File

@ -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<CuesWithTiming> 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<Cue> cues = new ArrayList<>();

View File

@ -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<String, SsaStyle> 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<byte[]> 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<List<Cue>> cues = new ArrayList<>();
List<Long> 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<CuesWithTiming> cuesWithStartTimeAndDuration = ImmutableList.builder();
for (int i = 0; i < cues.size(); i++) {

View File

@ -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<String> 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<CuesWithTiming> parse(byte[] data, int offset, int length) {
ImmutableList.Builder<CuesWithTiming> 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("<br>");
}
textBuilder.append(processLine(currentLine, tags));
currentLine = subripData.readLine(charset);
currentLine = parsableByteArray.readLine(charset);
}
Spanned text = Html.fromHtml(textBuilder.toString());

View File

@ -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<CuesWithTiming> 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(

View File

@ -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<CuesWithTiming> 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<Cue> 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()

View File

@ -53,7 +53,7 @@ public final class WebvttParser implements SubtitleParser {
@Override
public ImmutableList<CuesWithTiming> parse(byte[] data, int offset, int length) {
parsableWebvttData.reset(data, length);
parsableWebvttData.reset(data, /* limit= */ offset + length);
parsableWebvttData.setPosition(offset);
List<WebvttCssStyle> definedStyles = new ArrayList<>();