diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/pgs/PgsDecoder.java b/library/core/src/main/java/com/google/android/exoplayer2/text/pgs/PgsDecoder.java index 6d60da7d81..e1fef19bfa 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/pgs/PgsDecoder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/pgs/PgsDecoder.java @@ -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 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();