Commit 2b1614cc by olly Committed by Oliver Woodman

Don't use ParsableBitArray to parse TS packet headers

Really low hanging fruit optimization for TS extraction.

ParsableBitArray is quite expensive. In particular readBits
contains at least 2 if blocks and a for loop, and was being
called 5 times per 188 byte packet (4 times via readBit). A
separate change will follow that optimizes readBit, but for
this particular case there's no real value to using a
ParsableBitArray anyway; use of ParsableBitArray IMO only
really becomes useful when you need to parse a bitstream more
than 4 bytes long, or where parsing the bitstream requires
some control flow (if/for) to parse.

There are probably other places where we're using
ParsableBitArray over-zealously. I'll roll that into a
tracking bug for looking in more detail at all extractors.

Issue: #3040

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=161650940
parent ecc8f6c4
...@@ -111,7 +111,6 @@ public final class TsExtractor implements Extractor { ...@@ -111,7 +111,6 @@ public final class TsExtractor implements Extractor {
@Mode private final int mode; @Mode private final int mode;
private final List<TimestampAdjuster> timestampAdjusters; private final List<TimestampAdjuster> timestampAdjusters;
private final ParsableByteArray tsPacketBuffer; private final ParsableByteArray tsPacketBuffer;
private final ParsableBitArray tsScratch;
private final SparseIntArray continuityCounters; private final SparseIntArray continuityCounters;
private final TsPayloadReader.Factory payloadReaderFactory; private final TsPayloadReader.Factory payloadReaderFactory;
private final SparseArray<TsPayloadReader> tsPayloadReaders; // Indexed by pid private final SparseArray<TsPayloadReader> tsPayloadReaders; // Indexed by pid
...@@ -164,7 +163,6 @@ public final class TsExtractor implements Extractor { ...@@ -164,7 +163,6 @@ public final class TsExtractor implements Extractor {
timestampAdjusters.add(timestampAdjuster); timestampAdjusters.add(timestampAdjuster);
} }
tsPacketBuffer = new ParsableByteArray(BUFFER_SIZE); tsPacketBuffer = new ParsableByteArray(BUFFER_SIZE);
tsScratch = new ParsableBitArray(new byte[3]);
trackIds = new SparseBooleanArray(); trackIds = new SparseBooleanArray();
tsPayloadReaders = new SparseArray<>(); tsPayloadReaders = new SparseArray<>();
continuityCounters = new SparseIntArray(); continuityCounters = new SparseIntArray();
...@@ -250,24 +248,23 @@ public final class TsExtractor implements Extractor { ...@@ -250,24 +248,23 @@ public final class TsExtractor implements Extractor {
return RESULT_CONTINUE; return RESULT_CONTINUE;
} }
tsPacketBuffer.skipBytes(1); int tsPacketHeader = tsPacketBuffer.readInt();
tsPacketBuffer.readBytes(tsScratch, 3); if ((tsPacketHeader & 0x800000) != 0) { // transport_error_indicator
if (tsScratch.readBit()) { // transport_error_indicator
// There are uncorrectable errors in this packet. // There are uncorrectable errors in this packet.
tsPacketBuffer.setPosition(endOfPacket); tsPacketBuffer.setPosition(endOfPacket);
return RESULT_CONTINUE; return RESULT_CONTINUE;
} }
boolean payloadUnitStartIndicator = tsScratch.readBit(); boolean payloadUnitStartIndicator = (tsPacketHeader & 0x400000) != 0;
tsScratch.skipBits(1); // transport_priority // Ignoring transport_priority (tsPacketHeader & 0x200000)
int pid = tsScratch.readBits(13); int pid = (tsPacketHeader & 0x1FFF00) >> 8;
tsScratch.skipBits(2); // transport_scrambling_control // Ignoring transport_scrambling_control (tsPacketHeader & 0xC0)
boolean adaptationFieldExists = tsScratch.readBit(); boolean adaptationFieldExists = (tsPacketHeader & 0x20) != 0;
boolean payloadExists = tsScratch.readBit(); boolean payloadExists = (tsPacketHeader & 0x10) != 0;
// Discontinuity check. // Discontinuity check.
boolean discontinuityFound = false; boolean discontinuityFound = false;
int continuityCounter = tsScratch.readBits(4);
if (mode != MODE_HLS) { if (mode != MODE_HLS) {
int continuityCounter = tsPacketHeader & 0xF;
int previousCounter = continuityCounters.get(pid, continuityCounter - 1); int previousCounter = continuityCounters.get(pid, continuityCounter - 1);
continuityCounters.put(pid, continuityCounter); continuityCounters.put(pid, continuityCounter);
if (previousCounter == continuityCounter) { if (previousCounter == continuityCounter) {
...@@ -276,7 +273,7 @@ public final class TsExtractor implements Extractor { ...@@ -276,7 +273,7 @@ public final class TsExtractor implements Extractor {
tsPacketBuffer.setPosition(endOfPacket); tsPacketBuffer.setPosition(endOfPacket);
return RESULT_CONTINUE; return RESULT_CONTINUE;
} }
} else if (continuityCounter != (previousCounter + 1) % 16) { } else if (continuityCounter != ((previousCounter + 1) & 0xF)) {
discontinuityFound = true; discontinuityFound = true;
} }
} }
...@@ -296,7 +293,6 @@ public final class TsExtractor implements Extractor { ...@@ -296,7 +293,6 @@ public final class TsExtractor implements Extractor {
} }
tsPacketBuffer.setLimit(endOfPacket); tsPacketBuffer.setLimit(endOfPacket);
payloadReader.consume(tsPacketBuffer, payloadUnitStartIndicator); payloadReader.consume(tsPacketBuffer, payloadUnitStartIndicator);
Assertions.checkState(tsPacketBuffer.getPosition() <= endOfPacket);
tsPacketBuffer.setLimit(limit); tsPacketBuffer.setLimit(limit);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment