support zlib compressed PGS subtitles

This commit is contained in:
Sven Wischnowsky 2018-02-28 18:08:03 +01:00
parent aa57062199
commit 5d1c84cebc

View File

@ -25,6 +25,10 @@ import com.google.android.exoplayer2.util.Util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.zip.InflaterInputStream;
/** A {@link SimpleSubtitleDecoder} for PGS subtitles. */
public final class PgsDecoder extends SimpleSubtitleDecoder {
@ -34,18 +38,29 @@ public final class PgsDecoder extends SimpleSubtitleDecoder {
private static final int SECTION_TYPE_IDENTIFIER = 0x16;
private static final int SECTION_TYPE_END = 0x80;
private static final int INFLATE_HEADER = 0x78;
private static final int INFLATE_BUFFER_SIZE = 5;
private final ParsableByteArray buffer;
private final CueBuilder cueBuilder;
private final ByteArrayOutputStream inflateBuffer;
private final byte[] inflateReadBuffer;
public PgsDecoder() {
super("PgsDecoder");
buffer = new ParsableByteArray();
cueBuilder = new CueBuilder();
inflateBuffer = new ByteArrayOutputStream();
inflateReadBuffer = new byte[INFLATE_BUFFER_SIZE];
}
@Override
protected Subtitle decode(byte[] data, int size, boolean reset) throws SubtitleDecoderException {
buffer.reset(data, size);
byte[] inflated = tryInflateBuffer(data, size);
if (inflated == null)
buffer.reset(data, size);
else
buffer.reset(inflated, inflated.length);
cueBuilder.reset();
ArrayList<Cue> cues = new ArrayList<>();
while (buffer.bytesLeft() >= 3) {
@ -57,6 +72,25 @@ public final class PgsDecoder extends SimpleSubtitleDecoder {
return new PgsSubtitle(Collections.unmodifiableList(cues));
}
private byte[] tryInflateBuffer(byte[] data, int size) {
if (size > 0 && (((int) data[0]) & 0xff) != INFLATE_HEADER) return null;
inflateBuffer.reset();
try {
InflaterInputStream iis = new InflaterInputStream(new ByteArrayInputStream(data, 0, size));
int len = -1;
while ((len = iis.read(inflateReadBuffer)) != -1) {
inflateBuffer.write(inflateReadBuffer, 0, len);
}
return inflateBuffer.toByteArray();
}
catch (IOException e) { }
return null;
}
private static Cue readNextSection(ParsableByteArray buffer, CueBuilder cueBuilder) {
int limit = buffer.limit();
int sectionType = buffer.readUnsignedByte();